Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: min delay between conditions #2079

Merged
merged 4 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config.lua.dist
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ coinPacketSize = 25
coinImagesURL = "http://127.0.0.1/images/store/"
classicAttackSpeed = false
showScriptsLogInConsole = false
-- time to suppress negative conditions after being affected by them (ms)
minDelayBetweenConditions = 0
-- configure maximum value of critical imbuement
criticalChance = 10
inventoryGlowOnFiveBless = false
Expand Down
1 change: 1 addition & 0 deletions src/config/config_definitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ enum ConfigKey_t : uint16_t {
METRICS_ENABLE_PROMETHEUS,
METRICS_OSTREAM_INTERVAL,
METRICS_PROMETHEUS_ADDRESS,
MIN_DELAY_BETWEEN_CONDITIONS,
MIN_ELEMENTAL_RESISTANCE,
MOMENTUM_CHANCE_FORMULA_A,
MOMENTUM_CHANCE_FORMULA_B,
Expand Down
1 change: 1 addition & 0 deletions src/config/configmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ bool ConfigManager::load() {
loadBoolConfig(L, CLEAN_PROTECTION_ZONES, "cleanProtectionZones", false);
loadBoolConfig(L, GLOBAL_SERVER_SAVE_SHUTDOWN, "globalServerSaveShutdown", true);
loadBoolConfig(L, PUSH_WHEN_ATTACKING, "pushWhenAttacking", false);
loadIntConfig(L, MIN_DELAY_BETWEEN_CONDITIONS, "minDelayBetweenConditions", 0);

loadBoolConfig(L, WEATHER_RAIN, "weatherRain", false);
loadBoolConfig(L, WEATHER_THUNDER, "thunderEffect", false);
Expand Down
2 changes: 1 addition & 1 deletion src/creatures/combat/combat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ void Combat::CombatConditionFunc(std::shared_ptr<Creature> caster, std::shared_p

// TODO: infight condition until all aggressive conditions has ended
if (target) {
target->addCombatCondition(conditionCopy);
target->addCombatCondition(conditionCopy, caster && caster->getPlayer() != nullptr);
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/creatures/combat/condition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1644,7 +1644,9 @@ bool ConditionDamage::getNextDamage(int32_t &damage) {
}

bool ConditionDamage::doDamage(std::shared_ptr<Creature> creature, int32_t healthChange) {
if (creature->isSuppress(getType())) {
auto attacker = g_game().getPlayerByGUID(owner) ? g_game().getPlayerByGUID(owner)->getCreature() : g_game().getCreatureByID(owner);
bool isPlayer = attacker && attacker->getPlayer();
if (creature->isSuppress(getType(), isPlayer)) {
return true;
}

Expand All @@ -1653,7 +1655,6 @@ bool ConditionDamage::doDamage(std::shared_ptr<Creature> creature, int32_t healt
damage.primary.value = healthChange;
damage.primary.type = Combat::ConditionToDamageType(conditionType);

std::shared_ptr<Creature> attacker = g_game().getCreatureByID(owner);
if (field && creature->getPlayer() && attacker && attacker->getPlayer()) {
damage.primary.value = static_cast<int32_t>(std::round(damage.primary.value / 2.));
}
Expand Down
12 changes: 7 additions & 5 deletions src/creatures/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1334,12 +1334,14 @@ bool Creature::setMaster(std::shared_ptr<Creature> newMaster, bool reloadCreatur
return true;
}

bool Creature::addCondition(std::shared_ptr<Condition> condition) {
bool Creature::addCondition(std::shared_ptr<Condition> condition, bool attackerPlayer /* = false*/) {
metrics::method_latency measure(__METHOD_NAME__);
if (condition == nullptr) {
return false;
}

if (isSuppress(condition->getType(), attackerPlayer)) {
return false;
}
std::shared_ptr<Condition> prevCond = getCondition(condition->getType(), condition->getId(), condition->getSubId());
if (prevCond) {
prevCond->addCondition(getCreature(), condition);
Expand All @@ -1355,11 +1357,11 @@ bool Creature::addCondition(std::shared_ptr<Condition> condition) {
return false;
}

bool Creature::addCombatCondition(std::shared_ptr<Condition> condition) {
bool Creature::addCombatCondition(std::shared_ptr<Condition> condition, bool attackerPlayer /* = false*/) {
// Caution: condition variable could be deleted after the call to addCondition
ConditionType_t type = condition->getType();

if (!addCondition(condition)) {
if (!addCondition(condition, attackerPlayer)) {
return false;
}

Expand Down Expand Up @@ -1490,7 +1492,7 @@ void Creature::executeConditions(uint32_t interval) {

bool Creature::hasCondition(ConditionType_t type, uint32_t subId /* = 0*/) const {
metrics::method_latency measure(__METHOD_NAME__);
if (isSuppress(type)) {
if (isSuppress(type, false)) {
return false;
}

Expand Down
6 changes: 3 additions & 3 deletions src/creatures/creature.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,8 @@ class Creature : virtual public Thing, public SharedObject {
return SPEECHBUBBLE_NONE;
}

bool addCondition(std::shared_ptr<Condition> condition);
bool addCombatCondition(std::shared_ptr<Condition> condition);
bool addCondition(std::shared_ptr<Condition> condition, bool attackerPlayer = false);
bool addCombatCondition(std::shared_ptr<Condition> condition, bool attackerPlayer = false);
void removeCondition(ConditionType_t conditionType, ConditionId_t conditionId, bool force = false);
void removeCondition(ConditionType_t type);
void removeCondition(std::shared_ptr<Condition> condition);
Expand All @@ -406,7 +406,7 @@ class Creature : virtual public Thing, public SharedObject {
virtual bool isImmune(ConditionType_t type) const {
return false;
}
virtual bool isSuppress(ConditionType_t type) const {
virtual bool isSuppress(ConditionType_t type, bool attackerPlayer) const {
return false;
};

Expand Down
22 changes: 22 additions & 0 deletions src/creatures/creatures_definitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,28 @@
CONDITION_COUNT = 39
};

// constexpr definiting suppressible conditions
constexpr bool IsConditionSuppressible(ConditionType_t condition) {
constexpr ConditionType_t suppressibleConditions[] = {
CONDITION_POISON,
CONDITION_FIRE,
CONDITION_ENERGY,
CONDITION_BLEEDING,
CONDITION_PARALYZE,
CONDITION_DROWN,
CONDITION_FREEZING,
CONDITION_CURSED,
};

for (const auto &suppressibleCondition : suppressibleConditions) {
if (condition == suppressibleCondition) {

Check warning on line 129 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / cppcheck

[cppcheck] src/creatures/creatures_definitions.hpp#L129

Consider using std::any_of algorithm instead of a raw loop.
Raw output
src/creatures/creatures_definitions.hpp:129:Consider using std::any_of algorithm instead of a raw loop.
return true;
}
}

return false;
}

enum ConditionParam_t {
CONDITION_PARAM_OWNER = 1,
CONDITION_PARAM_TICKS = 2,
Expand Down Expand Up @@ -328,7 +350,7 @@
OBJECTCATEGORY_LAST = OBJECTCATEGORY_DEFAULT,
};

static bool isValidObjectCategory(uint8_t category) {

Check warning on line 353 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

‘bool isValidObjectCategory(uint8_t)’ defined but not used [-Wunused-function]

Check warning on line 353 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

‘bool isValidObjectCategory(uint8_t)’ defined but not used [-Wunused-function]

Check warning on line 353 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘bool isValidObjectCategory(uint8_t)’ defined but not used [-Wunused-function]

Check warning on line 353 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘bool isValidObjectCategory(uint8_t)’ defined but not used [-Wunused-function]
static std::unordered_set<uint8_t> valid = {
OBJECTCATEGORY_NONE,
OBJECTCATEGORY_ARMORS,
Expand Down Expand Up @@ -1680,12 +1702,12 @@

struct ShopBlock {
uint16_t itemId;
std::string itemName;

Check warning on line 1705 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

‘std::string ShopBlock::itemName’ [-Wreorder]

Check warning on line 1705 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

‘std::string ShopBlock::itemName’ [-Wreorder]

Check warning on line 1705 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

‘std::string ShopBlock::itemName’ [-Wreorder]

Check warning on line 1705 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘std::string ShopBlock::itemName’ [-Wreorder]

Check warning on line 1705 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘std::string ShopBlock::itemName’ [-Wreorder]

Check warning on line 1705 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘std::string ShopBlock::itemName’ [-Wreorder]
int32_t itemSubType;
uint32_t itemBuyPrice;
uint32_t itemSellPrice;
int32_t itemStorageKey;
int32_t itemStorageValue;

Check warning on line 1710 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

‘ShopBlock::itemStorageValue’ will be initialized after [-Wreorder]

Check warning on line 1710 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

‘ShopBlock::itemStorageValue’ will be initialized after [-Wreorder]

Check warning on line 1710 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

‘ShopBlock::itemStorageValue’ will be initialized after [-Wreorder]

Check warning on line 1710 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘ShopBlock::itemStorageValue’ will be initialized after [-Wreorder]

Check warning on line 1710 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘ShopBlock::itemStorageValue’ will be initialized after [-Wreorder]

Check warning on line 1710 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

‘ShopBlock::itemStorageValue’ will be initialized after [-Wreorder]

std::vector<ShopBlock> childShop;
ShopBlock() {
Expand All @@ -1698,7 +1720,7 @@
itemStorageValue = 0;
}

explicit ShopBlock(uint16_t newItemId, int32_t newSubType = 0, uint32_t newBuyPrice = 0, uint32_t newSellPrice = 0, int32_t newStorageKey = 0, int32_t newStorageValue = 0, std::string newName = "") :

Check warning on line 1723 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

when initialized here [-Wreorder]

Check warning on line 1723 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-20.04-linux-debug

when initialized here [-Wreorder]

Check warning on line 1723 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

when initialized here [-Wreorder]

Check warning on line 1723 in src/creatures/creatures_definitions.hpp

View workflow job for this annotation

GitHub Actions / ubuntu-22.04-linux-debug

when initialized here [-Wreorder]
itemId(newItemId), itemSubType(newSubType), itemBuyPrice(newBuyPrice), itemSellPrice(newSellPrice), itemStorageKey(newStorageKey), itemStorageValue(newStorageValue), itemName(std::move(newName)) { }

bool operator==(const ShopBlock &other) const {
Expand Down
12 changes: 10 additions & 2 deletions src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,12 @@ std::shared_ptr<Item> Player::getInventoryItem(Slots_t slot) const {
return inventory[slot];
}

bool Player::isSuppress(ConditionType_t conditionType) const {
bool Player::isSuppress(ConditionType_t conditionType, bool attackerPlayer) const {
auto minDelay = g_configManager().getNumber(MIN_DELAY_BETWEEN_CONDITIONS, __FUNCTION__);
if (IsConditionSuppressible(conditionType) && checkLastConditionTimeWithin(conditionType, minDelay)) {
return true;
}

return m_conditionSuppressions[static_cast<size_t>(conditionType)];
}

Expand Down Expand Up @@ -450,7 +455,7 @@ float Player::getDefenseFactor() const {
uint32_t Player::getClientIcons() {
uint32_t icons = 0;
for (const auto &condition : conditions) {
if (!isSuppress(condition->getType())) {
if (!isSuppress(condition->getType(), false)) {
icons |= condition->getIcons();
}
}
Expand Down Expand Up @@ -4481,6 +4486,9 @@ void Player::onAddCondition(ConditionType_t type) {
}

void Player::onAddCombatCondition(ConditionType_t type) {
if (IsConditionSuppressible(type)) {
updateLastConditionTime(type);
}
switch (type) {
case CONDITION_POISON:
sendTextMessage(MESSAGE_FAILURE, "You are poisoned.");
Expand Down
30 changes: 21 additions & 9 deletions src/creatures/players/player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,25 @@ class Player final : public Creature, public Cylinder, public Bankable {
return lastAttackBlockType;
}

uint64_t getLastConditionTime(ConditionType_t type) const {
if (!lastConditionTime.contains(static_cast<uint8_t>(type))) {
return 0;
}
return lastConditionTime.at(static_cast<uint8_t>(type));
}

void updateLastConditionTime(ConditionType_t type) {
lastConditionTime[static_cast<uint8_t>(type)] = OTSYS_TIME();
}

bool checkLastConditionTimeWithin(ConditionType_t type, uint32_t interval) const {
if (!lastConditionTime.contains(static_cast<uint8_t>(type))) {
return false;
}
auto last = lastConditionTime.at(static_cast<uint8_t>(type));
return last > 0 && ((OTSYS_TIME() - last) < interval);
}

uint64_t getLastAttack() const {
return lastAttack;
}
Expand Down Expand Up @@ -924,13 +943,6 @@ class Player final : public Creature, public Cylinder, public Bankable {
lastAggressiveAction = OTSYS_TIME();
}

uint64_t getLastFocusLost() const {
return lastFocusLost;
}
void setLastFocusLost(uint64_t time) {
lastFocusLost = time;
}

std::unordered_set<std::string> getNPCSkips();

std::shared_ptr<Item> getWeapon(Slots_t slot, bool ignoreAmmo) const;
Expand Down Expand Up @@ -2731,8 +2743,8 @@ class Player final : public Creature, public Cylinder, public Bankable {
uint64_t experience = 0;
uint64_t manaSpent = 0;
uint64_t lastAttack = 0;
std::unordered_map<uint8_t, uint64_t> lastConditionTime;
uint64_t lastAggressiveAction = 0;
uint64_t lastFocusLost = 0;
uint64_t bankBalance = 0;
uint64_t lastQuestlogUpdate = 0;
uint64_t preyCards = 0;
Expand Down Expand Up @@ -2953,7 +2965,7 @@ class Player final : public Creature, public Cylinder, public Bankable {
return skillLoss ? static_cast<uint64_t>(experience * getLostPercent()) : 0;
}

bool isSuppress(ConditionType_t conditionType) const override;
bool isSuppress(ConditionType_t conditionType, bool attackerPlayer) const override;
void addConditionSuppression(const std::array<ConditionType_t, ConditionType_t::CONDITION_COUNT> &addConditions);

uint16_t getLookCorpse() const override;
Expand Down
Loading