Skip to content

Commit

Permalink
Many changes
Browse files Browse the repository at this point in the history
  • Loading branch information
dairymoose committed Dec 9, 2023
1 parent bd2413f commit 9b650a4
Show file tree
Hide file tree
Showing 37 changed files with 1,569 additions and 193 deletions.
237 changes: 235 additions & 2 deletions Ability.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "Ability.h"
#include "PlayerCharacter.h"
#include "DamageSimulation.h"
#include "GlobalAbilityList.h"
#include <cfloat>

std::function<int32_t (PlayerCharacter *PC, int32_t abilityRank)> Ability::getDamageFunction() const
{
Expand Down Expand Up @@ -122,12 +124,12 @@ void Ability::setName(const std::string &value)
name = value;
}

std::function<float (PlayerCharacter *PC, int32_t abilityRank)> Ability::getCanUseFunction() const
std::function<bool (PlayerCharacter *PC, int32_t abilityRank, float timestamp)> Ability::getCanUseFunction() const
{
return canUseFunction;
}

void Ability::setCanUseFunction(const std::function<float (PlayerCharacter *PC, int32_t abilityRank)> &value)
void Ability::setCanUseFunction(const std::function<bool (PlayerCharacter *PC, int32_t abilityRank, float timestamp)> &value)
{
canUseFunction = value;
}
Expand Down Expand Up @@ -237,11 +239,242 @@ void Ability::setOnGetTooltip(const std::function<std::string (std::string toolt
onGetTooltip = value;
}

std::function<int32_t (PlayerCharacter *PC, int32_t abilityRank, int32_t initialCost)> Ability::getOnGetResourceCostModifier() const
{
return onGetResourceCostModifier;
}

void Ability::setOnGetResourceCostModifier(const std::function<int32_t (PlayerCharacter *PC, int32_t abilityRank, int32_t initialCost)> &value)
{
onGetResourceCostModifier = value;
}

bool Ability::getCannotBeBlockedOrDodgedOrParried() const
{
return cannotBeBlockedOrDodgedOrParried;
}

void Ability::setCannotBeBlockedOrDodgedOrParried(bool value)
{
cannotBeBlockedOrDodgedOrParried = value;
}

Ability::Ability(std::string name)
{
this->name = name;
}

int32_t Ability::convertToPercentFormat(float f)
{
return (int32_t)((FLOATING_POINT_SMALL_NUMBER + f)*100);
}

void Ability::printMeleeAttackTable(MeleeAttackTable &mat, std::ostream &stream)
{
stream<<"Miss: "<<convertToPercentFormat(mat.miss)<<"%<br>";
stream<<"Dodge: "<<convertToPercentFormat(mat.dodge)<<"%<br>";
stream<<"Parry: "<<convertToPercentFormat(mat.parry)<<"%<br>";
stream<<"Glancing Blow: "<<convertToPercentFormat(mat.glancingBlow)<<"%<br>";
stream<<"Block: "<<convertToPercentFormat(mat.block)<<"%<br>";
stream<<"Critical Hit: "<<convertToPercentFormat(mat.criticalHit)<<"%<br>";
stream<<"Crushing Blow: "<<convertToPercentFormat(mat.crushingBlow)<<"%<br>";
stream<<"Ordinary Hit: "<<convertToPercentFormat(mat.ordinaryHit)<<"%<br>";
stream<<"Glancing Blow DR: "<<convertToPercentFormat(mat.glancingBlowDamageReduction)<<"%<br>";
}

void Ability::generateMeleeAttackTable(PlayerCharacter *PC, Enemy *target, MeleeAttackTable& mat)
{
int32_t defenseWeaponSkillDelta = target->getCalculatedDefense() - PC->getCalculatedWeaponSkill();

if (defenseWeaponSkillDelta <= 10) {
float missBase2h = 0.05f;
float missBaseDw = 0.024f;
float baseMissChance = missBase2h;
if (PC->isWhiteAttack(this) && PC->getOffHandItem() != nullptr) {
baseMissChance = missBaseDw;
}
mat.miss = baseMissChance + (defenseWeaponSkillDelta)*0.001f;
}
else {
float missBase2h = 0.06f;
float missBaseDw = 0.025f;
float baseMissChance = missBase2h;
if (PC->isWhiteAttack(this) && PC->getOffHandItem() != nullptr) {
baseMissChance = missBaseDw;
}
mat.miss = baseMissChance + (defenseWeaponSkillDelta - 10)*0.004f;
}
mat.miss = std::max(mat.miss, 0.0f);

mat.dodge = 0.045f;
mat.parry = 0.0f;
if (PC->isWhiteAttack(this))
mat.glancingBlow = 0.10f + 0.02f*(defenseWeaponSkillDelta);
else
mat.glancingBlow = 0.0f;
if (mat.glancingBlow < 0.0f)
mat.glancingBlow = 0.0f;
mat.glancingBlowDamageReduction = std::max(0.0f, -0.15f + 0.03f*(defenseWeaponSkillDelta));

mat.block = 0.0f;
mat.criticalHit = PC->getCritChance();
mat.crushingBlow = 0.0f;

if (this->cannotBeBlockedOrDodgedOrParried) {
mat.block = 0.0f;
mat.dodge = 0.0f;
mat.parry = 0.0f;
}
if (this == GlobalAbilityList::activeList->Overpower) {
int32_t op = PC->getTalentRank("Improved Overpower");
if (op > 0) {
mat.criticalHit += op * 0.25f;
}
}
mat.ordinaryHit = 1.0f - (mat.miss + mat.dodge + mat.parry + mat.glancingBlow + mat.block + mat.criticalHit + mat.crushingBlow);
}

MeleeHitResult Ability::rollAttackTableForHitResult(MeleeAttackTable &mat)
{
float attackTableDiceRanges[8];
attackTableDiceRanges[0] = mat.miss; //8
attackTableDiceRanges[1] = attackTableDiceRanges[0] + mat.dodge; //12.5
attackTableDiceRanges[2] = attackTableDiceRanges[1] + mat.parry; //12.5
attackTableDiceRanges[3] = attackTableDiceRanges[2] + mat.glancingBlow; //52.5
attackTableDiceRanges[4] = attackTableDiceRanges[3] + mat.block;
attackTableDiceRanges[5] = attackTableDiceRanges[4] + mat.criticalHit;
attackTableDiceRanges[6] = attackTableDiceRanges[5] + mat.crushingBlow;
attackTableDiceRanges[7] = attackTableDiceRanges[6] + mat.ordinaryHit; //100.0
MeleeHitResult results[8];
results[0] = MeleeHitResult::Miss;
results[1] = MeleeHitResult::Dodge;
results[2] = MeleeHitResult::Parry;
results[3] = MeleeHitResult::GlancingBlow;
results[4] = MeleeHitResult::Block;
results[5] = MeleeHitResult::CriticalHit;
results[6] = MeleeHitResult::CrushingBlow;
results[7] = MeleeHitResult::OrdinaryHit;
float dieRoll = DamageSimulation::randomFloatBetween(0.0f, 1.0f);
//std::cout<<"Miss = "<<attackTableDiceRanges[0]<<'\n';
for (int i=0; i<8; ++i) {
if (dieRoll < attackTableDiceRanges[i]) {
//std::cout<<"Got meleeHitResult of "<<(int)(results[i])<<" from die roll of "<<dieRoll<<" with upper range of "<<attackTableDiceRanges[i]<<'\n';
return results[i];
}
}
}

void Ability::triggerAbilityDamageMeleeHooks(PlayerCharacter *PC, float timestamp)
{
for (int i=0; i<PC->getBuffs().size(); ++i) {
if (PC->getBuffs()[i]->getBuff()->getOnAbilityDamageMelee() != nullptr) {
PC->getBuffs()[i]->getBuff()->getOnAbilityDamageMelee()(PC, timestamp);
}
}
}

void Ability::execute(PlayerCharacter *PC, std::vector<Enemy *> &enemyList, float timestamp, bool ignoreGcd, bool ignoreResourceCost, bool shouldTriggerCooldown)
{
this->triggerResourceCost(PC, timestamp);
int32_t damage = DamageSimulation::getDamageForAbility(this, PC);
bool isCritical = false;

MeleeAttackTable mat;
this->generateMeleeAttackTable(PC, PC->getTarget(), mat);
MeleeHitResult mhr = this->rollAttackTableForHitResult(mat);
if (mhr == MeleeHitResult::CriticalHit) {
isCritical = true;
damage = PC->applyCritDamage(this, damage);
}

int32_t defenseWeaponSkillDelta = PC->getTarget()->getCalculatedDefense() - PC->getCalculatedWeaponSkill();
if (mhr == MeleeHitResult::GlancingBlow) {
damage *= 1.0f - mat.glancingBlowDamageReduction;
}

if (PC->isWhiteAttack(this) && this == GlobalAbilityList::activeList->MeleeMainhandAutoAttack) {
if (PC->hasBuff(GlobalAbilityList::activeList->Enrage)) {
damage *= 1.20f;
}
}
bool didNotConnect = false;
if (mhr == MeleeHitResult::Miss || mhr == MeleeHitResult::Dodge || mhr == MeleeHitResult::Parry) {
didNotConnect = true;
damage = 0.0f;
}
if (mhr == MeleeHitResult::Dodge) {
PC->getTarget()->setLastDodgeTimestamp(timestamp);
}

if (shouldTriggerCooldown)
this->triggerCooldown(PC, timestamp, ignoreGcd);
int32_t resourceBefore = PC->getResource();
int32_t damageDone = 0;

if (this->isDamageAbility()) {
if (this->getAoeMaxTargets() > 0) {
for (int i=0; i<this->getAoeMaxTargets(); ++i) {
if (i >= enemyList.size()) {
break;
}
if (enemyList[i] != nullptr) {
damageDone += enemyList[i]->applyDamage(PC, damage, mhr, timestamp, this);
}
}
}
else {
if (PC->getTarget() == nullptr && enemyList.size() > 0) {
PC->setTarget(enemyList[0]);
}
if (PC->getTarget() != nullptr) {
damageDone += PC->getTarget()->applyDamage(PC, damage, mhr, timestamp, this);
}
}
}

if (!didNotConnect) {
if (this->getGrantedBuff() != nullptr) {
bool isFree = ignoreResourceCost && ignoreGcd;
PC->applyBuff(PC, timestamp, this->getGrantedBuff(), isFree);
}
if (this->getGrantedDebuff() != nullptr) {
PC->getTarget()->applyDebuff(PC, timestamp, this->getGrantedDebuff());
}
this->triggerResourceGeneration(PC, damageDone, isCritical, timestamp);
int32_t resourceAfter = PC->getResource();
if (resourceAfter > resourceBefore || this->getResourceGenerationFunction() != nullptr) {
if (PC->hasRune("Consumed by Rage")) {
if (resourceBefore < 80 && resourceAfter >= 80) {
PC->applyBuff(PC, timestamp, GlobalAbilityList::activeList->Enrage, false);
}
}
int32_t resourceDiff = resourceAfter - resourceBefore;
COMBAT_LOG(timestamp, PC, "Rage is at "<<PC->getResource()<<" (gained "<<resourceDiff<<" rage)");
}
if (PC->isWhiteAttack(this) && this == GlobalAbilityList::activeList->MeleeMainhandAutoAttack) {
if (!GlobalAbilityList::activeList->inExtraAttack) {
for (int i=0; i<PC->getBuffs().size(); ++i) {
if (PC->getBuffs()[i]->getBuff()->getOnAutoAttack() != nullptr) {
PC->getBuffs()[i]->getBuff()->getOnAutoAttack()(PC);
}
}
}
}
if (damage > 0) {
if (isCritical) {
if (PC->getTalentRank("Deep Wounds") > 0) {
if (PC->getTarget() != nullptr) {
PC->getTarget()->applyDebuff(PC, timestamp, GlobalAbilityList::activeList->DeepWounds);
}
}
}
if (!GlobalAbilityList::activeList->inExtraAttack) {
this->triggerAbilityDamageMeleeHooks(PC, timestamp);
}
}
}
}

void Ability::reset()
{
this->lastUsedTimestamp = 0.0f;
Expand Down
20 changes: 17 additions & 3 deletions Ability.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <functional>
#include <vector>
#include "AbilityDamageType.h"
#include "Enemy.h"
#include "MeleeHitResult.h"

class Buff;
class PlayerCharacter;
Expand All @@ -18,9 +20,10 @@ class Ability
std::function<void (float timestamp, PlayerCharacter *PC, int32_t abilityRank)> onCooldownTriggeredFunction = nullptr;
std::function<int32_t (PlayerCharacter *PC, int32_t abilityRank)> damageFunction = nullptr;
std::function<float (PlayerCharacter *PC, int32_t abilityRank)> cooldownFunction = nullptr;
std::function<float (PlayerCharacter *PC, int32_t abilityRank)> canUseFunction = nullptr;
std::function<float (PlayerCharacter *PC, int32_t abilityRank, float timestamp)> canUseFunction = nullptr;
std::function<int32_t (PlayerCharacter *PC, int32_t abilityRank, int32_t damageDone, bool isCritical)> resourceGenerationFunction = nullptr;
std::function<std::string (std::string tooltipText, float timestamp, PlayerCharacter *PC, Ability *ability)> onGetTooltip = nullptr;
std::function<int32_t (PlayerCharacter *PC, int32_t abilityRank, int32_t initialCost)> onGetResourceCostModifier = nullptr;
bool isGcdAbility = true;
Buff *GrantedBuff = nullptr;
Buff *GrantedDebuff = nullptr;
Expand All @@ -36,9 +39,16 @@ class Ability
float castTime = 0.0f;
bool castedAbilityResetsAutoAttack = true;
std::vector<int32_t> learnLevels;
bool cannotBeBlockedOrDodgedOrParried = false;
int32_t convertToPercentFormat(float f);
public:
Ability(std::string name);

void printMeleeAttackTable(MeleeAttackTable &mat, std::ostream& stream);
void generateMeleeAttackTable(PlayerCharacter *PC, Enemy *target, MeleeAttackTable &mat);
MeleeHitResult rollAttackTableForHitResult(MeleeAttackTable &mat);
void execute(PlayerCharacter *PC, std::vector<Enemy *> &enemyList, float timestamp, bool ignoreGcd=false, bool ignoreResourceCost=false, bool shouldTriggerCooldown=true);
void triggerAbilityDamageMeleeHooks(PlayerCharacter *PC, float timestamp);
void reset();
float getRemainingCooldown(float timestamp);
float getTimeSinceLastUsed(float timestamp);
Expand Down Expand Up @@ -66,8 +76,8 @@ class Ability
void setAbilityDamageType(const AbilityDamageType &value);
std::string getName() const;
void setName(const std::string &value);
std::function<float (PlayerCharacter *PC, int32_t abilityRank)> getCanUseFunction() const;
void setCanUseFunction(const std::function<float (PlayerCharacter *PC, int32_t abilityRank)> &value);
std::function<bool (PlayerCharacter *PC, int32_t abilityRank, float timestamp)> getCanUseFunction() const;
void setCanUseFunction(const std::function<bool (PlayerCharacter *PC, int32_t rank, float timestamp)> &value);
int32_t getRank() const;
void setRank(const int32_t &value);
std::function<void (float timestamp, PlayerCharacter *PC, int32_t abilityRank)> getOnCooldownTriggeredFunction() const;
Expand All @@ -89,6 +99,10 @@ class Ability
void setTooltipText(const std::string &value);
std::function<std::string (std::string tooltipText, float timestamp, PlayerCharacter *PC, Ability *ability)> getOnGetTooltip() const;
void setOnGetTooltip(const std::function<std::string (std::string tooltipText, float timestamp, PlayerCharacter *PC, Ability *ability)> &value);
std::function<int32_t (PlayerCharacter *PC, int32_t abilityRank, int32_t initialCost)> getOnGetResourceCostModifier() const;
void setOnGetResourceCostModifier(const std::function<int32_t (PlayerCharacter *PC, int32_t abilityRank, int32_t initialCost)> &value);
bool getCannotBeBlockedOrDodgedOrParried() const;
void setCannotBeBlockedOrDodgedOrParried(bool value);
};

#endif // ABILITY_H
Loading

0 comments on commit 9b650a4

Please sign in to comment.