228 lines
6.0 KiB
C++
228 lines
6.0 KiB
C++
#pragma once
|
|
|
|
#include "StructCreature.h"
|
|
|
|
// DamageMessage를 인자로 데미지를 주도록 바꾸는 방식도 고려했지만
|
|
// 당장에 모든 인터페이스를 수정/검증하기 어려운 관계로 이는 추후로 미룬다.
|
|
struct DamageMessage
|
|
{
|
|
DamageMessage( StructCreature* from, StructCreature* target, const StructCreature::DamageType type, const int ignoreFlag,
|
|
const Elemental::Type elementalType, const int initialDamage );
|
|
|
|
void init( const StructCreature::DamageType type, const int ignoreFlag );
|
|
|
|
enum DamageType
|
|
{
|
|
DIRECT_DAMAGE = 0, // 직접 데미지
|
|
STATE_DAMAGE = 1, // 지속 효과 데미지
|
|
ADDITIONAL_DAMAGE = 2, // 추가 데미지
|
|
NAKED_DAMAGE = 3, // 방어력 관련 공식 적용 없는 데미지
|
|
};
|
|
|
|
enum AttackType
|
|
{
|
|
PHYSICAL_ATTACK = 0,
|
|
MAGICAL_ATTACK = 1,
|
|
PHYSICAL_SKILL_ATTACK = 2,
|
|
PHYSICAL_LEFT_HAND_ATTACK = 3,
|
|
};
|
|
|
|
enum
|
|
{
|
|
DEFENCE = ( 1 << 0 ), // 방어력 적용 여부
|
|
CRITICAL = ( 1 << 1 ), // 크리 가능 여부
|
|
BLOCK = ( 1 << 2 ), // 블럭 가능 여부
|
|
AVOID = ( 1 << 3 ), // 회피 가능 여부
|
|
RANDOM = ( 1 << 4 ), // 랜덤 데미지 적용 여부 (5%)
|
|
DAMAGE_REDUCE = ( 1 << 5 ), // 데미지 리듀스 적용 여부
|
|
|
|
FLAG_COUNT = 6,
|
|
FLAG_MASK = ( DEFENCE | CRITICAL | BLOCK | AVOID | RANDOM | DAMAGE_REDUCE ),
|
|
};
|
|
|
|
StructCreature* from;
|
|
StructCreature* target;
|
|
Elemental::Type elementalType;
|
|
int flag;
|
|
int damage;
|
|
DamageType damageType;
|
|
AttackType attackType;
|
|
|
|
StructCreature::DamageType oldDamageType;
|
|
// 기존 가상 함수 인터페이스와의 호환을 위해 일시적으로 보관
|
|
// 추후 StructCreature::DamageType을 적절하게 대체할 수 있으면 함
|
|
|
|
const StructCreature::StateMod* advantage;
|
|
const StructCreature::StateMod* penalty;
|
|
|
|
int criticalBonus;
|
|
int accuracyBonus;
|
|
};
|
|
|
|
|
|
struct SimulationResult
|
|
{
|
|
SimulationResult()
|
|
{
|
|
critical = false;
|
|
missed = false;
|
|
blocked = false;
|
|
perfectBlocked = false;
|
|
}
|
|
|
|
bool critical;
|
|
bool missed;
|
|
bool blocked;
|
|
bool perfectBlocked;
|
|
};
|
|
|
|
struct CalculationResult
|
|
{
|
|
int damage;
|
|
int penetratedDamage;
|
|
int resistedDamage;
|
|
int finalDamage;
|
|
int manaShieldAbsorption;
|
|
|
|
SimulationResult simulation;
|
|
|
|
CalculationResult()
|
|
{
|
|
damage = 0;
|
|
penetratedDamage = 0;
|
|
resistedDamage = 0;
|
|
finalDamage = 0;
|
|
|
|
manaShieldAbsorption = 0;
|
|
}
|
|
|
|
template < typename ModifierType >
|
|
void apply( const ModifierType& modifier, const bool applyPenetration )
|
|
{
|
|
damage = modifier.getDamage( damage );
|
|
|
|
if ( applyPenetration == true )
|
|
{
|
|
penetratedDamage = modifier.getPenetratedDamage( penetratedDamage );
|
|
}
|
|
else
|
|
{
|
|
penetratedDamage = modifier.getDamage( penetratedDamage );
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
struct DamageModifier
|
|
{
|
|
DamageModifier() : inc(0), amp(1.0f) {}
|
|
|
|
const int getDamage( const int damage ) const
|
|
{
|
|
return ( damage + inc ) * amp;
|
|
}
|
|
|
|
const int getPenetratedDamage( const int penetratedDamage ) const
|
|
{
|
|
// 만약 데미지 증가인 경우라면 관통 데미지도 증가, 그 외에는 그대로 유지
|
|
return ( penetratedDamage + std::max( inc, 0 ) ) * std::max( amp, 1.0f );
|
|
}
|
|
|
|
int inc;
|
|
float amp;
|
|
};
|
|
|
|
struct DamageAmplifier
|
|
{
|
|
DamageAmplifier() : amp(1.0f) {}
|
|
|
|
const int getDamage( const int damage ) const
|
|
{
|
|
return damage * amp;
|
|
}
|
|
|
|
const int getPenetratedDamage( const int penetratedDamage ) const
|
|
{
|
|
// 만약 데미지 증가인 경우라면 관통 데미지도 증가, 그 외에는 그대로 유지
|
|
return penetratedDamage * std::max( amp, 1.0f );
|
|
}
|
|
|
|
float amp;
|
|
};
|
|
|
|
struct DamageCalculator
|
|
{
|
|
public:
|
|
DamageMessage::DamageType damageType;
|
|
int originalDamage;
|
|
int flag;
|
|
|
|
int targetLevel;
|
|
int attackerLevel;
|
|
|
|
bool isImmune;
|
|
bool isIgnoreLevelPenalty;
|
|
|
|
int accuracyInc;
|
|
int accuracy;
|
|
int avoid;
|
|
|
|
int critRateInc;
|
|
float critRateAmp;
|
|
int critPower;
|
|
int critical;
|
|
|
|
int blockRate;
|
|
int perfectBlockRate;
|
|
|
|
DamageModifier beforeDefence;
|
|
DamageModifier afterDefence;
|
|
DamageModifier statePenalty;
|
|
DamageModifier stateAdvantage;
|
|
DamageAmplifier expertisePenalty;
|
|
DamageAmplifier expertiseAdvantage;
|
|
DamageAmplifier random;
|
|
DamageAmplifier rule;
|
|
DamageAmplifier resist;
|
|
|
|
int attackPoint;
|
|
int defence;
|
|
int blockDefence;
|
|
int defenceIgnore;
|
|
float defenceIgnoreRatio;
|
|
|
|
int penetration;
|
|
float penetrationRatio;
|
|
|
|
float manaShieldRatio;
|
|
int manaShieldLimit;
|
|
|
|
DamageCalculator();
|
|
DamageCalculator( const DamageMessage& message );
|
|
|
|
void Initiate();
|
|
void Interpret( const DamageMessage& message );
|
|
void Calculate( CalculationResult& result );
|
|
|
|
void SimulateDamageCalculation( SimulationResult& result );
|
|
void CalculateActualDamage( CalculationResult& result ) const;
|
|
|
|
private:
|
|
const bool SimulateAndCheckImmunity( SimulationResult& result );
|
|
const bool SimulateAndCheckAvoidance( SimulationResult& result );
|
|
const bool SimulateAndCheckBlocking( SimulationResult& result );
|
|
void SimulateCritical( SimulationResult& result );
|
|
void SimulateRandomDamage( SimulationResult& result );
|
|
static const int CalculateHitRate( const int levelDiff, const float accuracy, const float avoid, const int bonus );
|
|
static const int CalculateCritRate( const int critRate, const float amplifier, const int bonus );
|
|
|
|
void CalculateDefenceAppliedDamage( CalculationResult& result ) const;
|
|
void CalculateCriticalDamage( CalculationResult& result ) const;
|
|
void CalculateResistance( CalculationResult& result ) const;
|
|
void CalculateLaterDamageModifier( CalculationResult& result ) const;
|
|
void CalculateManaShieldEffect( CalculationResult& result ) const;
|
|
void CalculatePenetrationEffect( CalculationResult& result ) const;
|
|
|
|
static const int CalculateDirectDamageWithDefence( const int damage, const int defence, const int attackerLevel );
|
|
static const int CalculateStateDamageWithDefence( const float damage, const int defence, const int attackPoint );
|
|
}; |