8202 lines
315 KiB
C++
8202 lines
315 KiB
C++
|
|
#include <mmo/ArcadiaServer.h>
|
|
|
|
#include <toolkit/XStringUtil.h>
|
|
#include <toolkit/XEnv.h>
|
|
|
|
#include "StructCreature.h"
|
|
#include "StructPlayer.h" // 흠 ;;
|
|
#include "StructNPC.h"
|
|
#include "StructMonster.h"
|
|
#include "StructSkill.h"
|
|
#include "StructSkillProp.h"
|
|
#include "StructSummon.h"
|
|
#include "StructPet.h"
|
|
#include "StructItem.h"
|
|
#include "StructProc.h"
|
|
#include "CreatureBase.h"
|
|
#include "SendMessage.h"
|
|
#include "GameContent.h"
|
|
|
|
// 현재 CalculateStat 관련 로직이 Struct~~에 들어가 있는 당위성은 멤버 변수에 접근하기 편하다는 점 말고는 아무 것도 없다
|
|
// 최종적으로는 CalculateStat과 Struct~~를 구분 짓는 것이 좋겠지만 워낙에 덩치가 커서 당장은 힘들다
|
|
// 우선 이 둘을 물리적인 cpp파일로 구분하여 코드 파악 과정을 조금 더 간결하게 해봅시다
|
|
|
|
// --- 초기화 관련 루틴 ---
|
|
void StructCreature::CalculateStat()
|
|
{
|
|
int prev_max_hp = GetMaxHP();
|
|
int prev_max_mp = GetMaxMP();
|
|
int prev_hp = GetHP();
|
|
int prev_mp = GetMP();
|
|
|
|
std::vector< std::pair< int, int > > prevAddedSkillBySkillId;
|
|
std::vector< std::pair< int, int > > prevAddedSkillBySkillType;
|
|
prevAddedSkillBySkillId.swap( m_vAddedSkillBySkillId );
|
|
prevAddedSkillBySkillType.swap( m_vAddedSkillBySkillType );
|
|
|
|
m_nLuna = 0;
|
|
|
|
// 일단 모든것 초기화
|
|
m_fHPRegenMod = 1.0f;
|
|
m_fMPRegenMod = 1.0f;
|
|
m_nMaxHP = 0;
|
|
m_nMinHP = 0;
|
|
m_nMinHP = 0.0f;
|
|
m_fMaxHPAmplifier = 0.0f;
|
|
m_nMaxMP = 0;
|
|
m_fMaxMPAmplifier = 0.0f;
|
|
|
|
m_fEXPMod = 0.0f;
|
|
|
|
m_fHealRatio = 1.0f;
|
|
m_fMPHealRatio = 1.0f;
|
|
m_fHealRatioByItem = 1.0f;
|
|
m_fMPHealRatioByItem = 1.0f;
|
|
m_fHealRatioByRest = 10.0f;
|
|
m_fMPHealRatioByRest = 2.0f;
|
|
|
|
m_nAdditionalHeal = 0;
|
|
m_nAdditionalMPHeal = 0;
|
|
m_nAdditionalHealByItem = 0;
|
|
m_nAdditionalMPHealByItem = 0;
|
|
m_nAdditionalHealByRest = 0;
|
|
m_nAdditionalMPHealByRest = 0;
|
|
|
|
m_fHateRatio = 1.0f;
|
|
|
|
m_fResistHarmfulState = 0.0f;
|
|
m_mapResistHarmfulState.clear();
|
|
|
|
m_nCastKeep = 100;
|
|
m_fBattleLevel = m_nLevel;
|
|
m_fBowInterval = 0.0f;
|
|
if( IsSummon() )
|
|
m_nMaxEnergy = 5;
|
|
else
|
|
m_nMaxEnergy = 0;
|
|
m_nEnergyUpkeepTime = GameRule::DEFAULT_ENERGY_UPKEEP_TIME;
|
|
m_nEnergyUnconsumptionRate = 0;
|
|
|
|
//m_nAttackPointRightByWeapon = 0;
|
|
//m_nAttackPointRightByWeaponMastery = 0;
|
|
//m_nAttackPointLeftByWeapon = 0;
|
|
//m_nAttackPointLeftByWeaponMastery = 0;
|
|
m_fAttackPointRightWithoutWeapon = 0;
|
|
m_fAttackPointLeftWithoutWeapon = 0;
|
|
|
|
m_fCreatureCardChance = 1.0f;
|
|
|
|
m_vPendStateListByItem.clear();
|
|
|
|
m_fPhysicalDamageManaShieldAbsorbRatio = 0.0f;
|
|
m_fMagicalDamageManaShieldAbsorbRatio = 0.0f;
|
|
|
|
m_vAmplifyPassiveSkillList.clear();
|
|
|
|
m_nChangingGroup = CREATURE_NONE;
|
|
|
|
m_vInterruptedSkill.clear();
|
|
m_vAllowedSkill.clear();
|
|
|
|
m_vAddedSkillBySkillId.clear();
|
|
m_vAddedSkillBySkillType.clear();
|
|
|
|
m_vAddHPMPOnCritical.clear();
|
|
initProc();
|
|
|
|
m_vDamageReducePercentInfo.clear();
|
|
m_vDamageReduceValueInfo.clear();
|
|
|
|
m_SkillCostModifier.init();
|
|
|
|
m_NormalStateAdvantage.Init();
|
|
m_RangeStateAdvantage.Init();
|
|
m_NormalStatePenalty.Init();
|
|
m_RangeStatePenalty.Init();
|
|
m_PhysicalSkillStatePenalty.Init();
|
|
m_MagicalSkillStatePenalty.Init();
|
|
m_StateStatePenalty.Init();
|
|
|
|
for( int i = 0; i < Elemental::TYPE_COUNT; ++i )
|
|
{
|
|
m_GoodPhysicalElementalSkillStateMod[i].Init();
|
|
m_BadPhysicalElementalSkillStateMod[i].Init();
|
|
m_GoodMagicalElementalSkillStateMod[i].Init();
|
|
m_BadMagicalElementalSkillStateMod[i].Init();
|
|
}
|
|
|
|
m_nElementalEffectAttackPointRight = 0;
|
|
m_nElementalEffectAttackPointLeft = 0;
|
|
m_nElementalEffectMagicPoint = 0;
|
|
|
|
m_StatusFlag.On( STATUS_MOVABLE );
|
|
m_StatusFlag.On( STATUS_ATTACKABLE );
|
|
m_StatusFlag.On( STATUS_SKILL_CASTABLE );
|
|
m_StatusFlag.On( STATUS_MAGIC_CASTABLE );
|
|
m_StatusFlag.On( STATUS_ITEM_USABLE );
|
|
m_StatusFlag.On( STATUS_MORTAL );
|
|
|
|
m_StatusFlag.Off( STATUS_FEARED );
|
|
m_StatusFlag.Off( STATUS_FORM_CHANGED );
|
|
m_StatusFlag.Off( STATUS_MOVE_SPEED_FIXED );
|
|
m_StatusFlag.Off( STATUS_HIDING );
|
|
AR_UNIT fPrevDetectHideRange = m_fDetectHideRange;
|
|
m_fDetectHideRange = 0.0f;
|
|
|
|
m_StatusFlag.Off( STATUS_HP_REGEN_STOPPED );
|
|
m_StatusFlag.Off( STATUS_MP_REGEN_STOPPED );
|
|
|
|
m_nDoubleWeaponMasteryLevel = 0;
|
|
|
|
// 지속효과에 의한 증가량 계산용
|
|
CreatureStatServer stateStat;
|
|
CreatureAttributeServer stateAttr;
|
|
|
|
// 어트리뷰트와 레지스트는 0으로 설정하고..
|
|
memset( &stateStat, 0, sizeof( stateStat ) );
|
|
memset( &stateAttr, 0, sizeof( stateAttr ) );
|
|
memset( &m_StatByState, 0, sizeof( m_StatByState ) );
|
|
memset( &m_StatAmplifier, 0, sizeof( m_StatAmplifier ) );
|
|
memset( &m_AttributeByState, 0, sizeof( m_AttributeByState ) );
|
|
memset( &m_AttributeAmplifier, 0, sizeof( m_AttributeAmplifier ) );
|
|
memset( &m_Attribute, 0, sizeof( m_Attribute ) );
|
|
memset( &m_Resist, 0, sizeof( m_Resist ) );
|
|
memset( &m_ResistAmplifier, 0, sizeof( m_ResistAmplifier ) );
|
|
memset( &m_Expert, 0, sizeof( m_Expert ) );
|
|
memset( &m_ElementalStateDamageAdder, 0, sizeof( m_ElementalStateDamageAdder ) );
|
|
memset( &m_ElementalStateDamageAmplifier, 0, sizeof( m_ElementalStateDamageAmplifier ) );
|
|
|
|
m_vNormalAdditionalDamage.clear();
|
|
m_vRangeAdditionalDamage.clear();
|
|
m_vPhysicalSkillAdditionalDamage.clear();
|
|
m_vMagicalSkillAdditionalDamage.clear();
|
|
m_vDamageReflectInfo.clear();
|
|
m_vStateReflectInfo.clear();
|
|
m_vHateMod.clear();
|
|
m_vSetItemEffect.clear();
|
|
m_vSynchronizedParameter.clear();
|
|
|
|
m_vSkillRelatedToDamaging.clear();
|
|
|
|
for ( std::vector< StructSkill* >::iterator it = m_vAllSkillList.begin(); it != m_vAllSkillList.end(); ++it )
|
|
{
|
|
(*it)->GetCostModifier().init();
|
|
}
|
|
|
|
// 우선 기본 스탯 얻어온다
|
|
m_Stat = GetBaseStat();
|
|
|
|
onBeforeCalculateStat();
|
|
|
|
// Checks the performance provided by set items
|
|
checkAdditionalItemEffect();
|
|
|
|
// Applies item effects that can change stats.
|
|
// Since the performance of titles also functions as item performance, it is handled here.
|
|
applyStatByItem();
|
|
applyStatByTitle();
|
|
applyStatByPassiveSkill();
|
|
|
|
// Job Level Bonus 적용
|
|
applyJobLevelBonus();
|
|
|
|
stateStat = m_Stat;
|
|
// 스탯을 변경시킬 수 있는 상태이상 효과 적용하고
|
|
applyStatByState();
|
|
|
|
accumulateStatDiffByState( stateStat ); // 지속 효과에 의한 스탯 증폭치 누적
|
|
|
|
onApplyStat(); // 증폭 전에 처리해야 할 것들(벨트 장착 관련)
|
|
|
|
amplifyStatByItem();
|
|
amplifyStatByTitle();
|
|
amplifyStatByPassiveSkill();
|
|
|
|
// 지속효과에 의한 증폭치 추가 전에 미리 스텟 계산해 봄
|
|
stateStat = m_Stat;
|
|
getAmplifiedStatByAmplifier( &stateStat );
|
|
|
|
// 증폭도 적용시키고
|
|
amplifyStatByState();
|
|
|
|
// 스텟 증폭치 처리
|
|
getAmplifiedStatByAmplifier( &m_Stat );
|
|
|
|
// 스탯 동기화
|
|
onSynchronizeParameter( true );
|
|
accumulateStatDiffByState( stateStat ); // 지속 효과에 의한 스탯 증폭치 누적
|
|
|
|
// 현재 계산 방식에서는 파라미터 기반 계산은 두번 이루어지는데, 두 번 모두 이 계산 이전의 파라미터를 참조해야 한다.
|
|
// 헌데 지금의 구조를 유지하며 계산을 수행하려면 임시 변수에 저장해놨다가 이를 계산에 사용하는 방법 밖에 없다.
|
|
m_StatBeforeParamBasedCalc = m_Stat;
|
|
calcParamBasedStat();
|
|
|
|
// 스탯 적용이 끝났음을 알림
|
|
onAfterApplyStat();
|
|
|
|
// 0 이하로 떨어진 값들 정리
|
|
finalizeStat();
|
|
// !!! 이 밑으로는 스탯이 변경되면 안됨.
|
|
|
|
// hp/mp 설정
|
|
m_nMaxHP += GameRule::GetMaxHP( GetVital(), GetBattleLevel(), GetFCM() );
|
|
m_nMaxMP += GameRule::GetMaxMP( GetIntelligence(), GetBattleLevel(), GetFCM() );
|
|
|
|
// 스탯에 따른 어트리뷰트 적용한 뒤에..
|
|
calcAttribute( &m_Attribute );
|
|
|
|
// 어트리뷰트 계산 직후에 할 일: 벨트 장착 패시브 중 어트리뷰트에 영향 주는 녀석 처리
|
|
onAfterCalculateAttributeByStat();
|
|
|
|
// 아이템빨 적용
|
|
applyItemEffect();
|
|
|
|
// 호칭 성능 적용
|
|
applyTitleEffect();
|
|
|
|
// 그 다음에 패시브빨을 먹인다, 벨트 장착 크리처 패시브 중 스텟이 아닌 파라미터 증가도 여기서 적용
|
|
applyPassiveSkillEffect();
|
|
|
|
stateAttr = m_Attribute;
|
|
|
|
// 상태이상빨 적용한다.
|
|
applyStateEffect();
|
|
|
|
accumulateAttributeDiffByState( stateAttr ); // 지속 효과에 의한 어트리뷰트 증폭치 누적
|
|
|
|
//패시브 스킬에 의한 증폭 효과를 적용 합니다.
|
|
applyPassiveSkillAmplifyEffect();
|
|
|
|
onApplyAttributeAdjustment(); // 증폭 전에 처리해야 할 파라미터 보정치(NPC, Monster 적용)
|
|
|
|
// 파라미터 증폭 적용
|
|
stateAttr = m_Attribute;
|
|
getAmplifiedAttributeByAmplifier( &stateAttr );
|
|
|
|
applyStateAmplifyEffect();
|
|
|
|
getAmplifiedAttributeByAmplifier( &m_Attribute );
|
|
m_fAttackPointRightWithoutWeapon = m_AttributeAmplifier.fAttackPointRight * m_fAttackPointRightWithoutWeapon;
|
|
m_fAttackPointLeftWithoutWeapon = m_AttributeAmplifier.fAttackPointLeft * m_fAttackPointLeftWithoutWeapon;
|
|
|
|
// 스탯 이 외의 파라미터 동기화
|
|
onSynchronizeParameter( false );
|
|
|
|
accumulateAttributeDiffByState( stateAttr ); // 지속 효과에 의한 어트리뷰트 증폭치 누적
|
|
|
|
// 현재 계산 방식에서는 파라미터 기반 계산은 두번 이루어지는데, 두 번 모두 이 계산 이전의 파라미터를 참조해야 한다.
|
|
// 헌데 지금의 구조를 유지하며 계산을 수행하려면 임시 변수에 저장해놨다가 이를 계산에 사용하는 방법 밖에 없다.
|
|
m_AttrBeforeParamBasedCalc = m_Attribute;
|
|
calcParamBasedAttribute();
|
|
applyParamBasedStateEffect();
|
|
applyParamBasedItemEffect();
|
|
|
|
// 속성 이펙트 추가 성능(공격력, 마력) 적용(어떠한 증폭도 적용되지 않아야 함)
|
|
m_Attribute.fAttackPointRight += m_nElementalEffectAttackPointRight;
|
|
m_Attribute.fAttackPointLeft += m_nElementalEffectAttackPointLeft;
|
|
m_Attribute.fMagicPoint += m_nElementalEffectMagicPoint;
|
|
|
|
// 양손 무기에 따른 보정 처리 한다.
|
|
applyDoubleWeaponEffect();
|
|
|
|
// HP, MP 최대치 조정
|
|
m_nMaxHP *= 1.0f + m_fMaxHPAmplifier;
|
|
m_nMaxMP *= 1.0f + m_fMaxMPAmplifier;
|
|
|
|
// 저항 증폭 처리
|
|
getAmplifiedResistByAmplifier( &m_Resist );
|
|
|
|
// onModifyStatAndAttribute와 나눈 이후는, 여기서 각 파생 struct별 최종 파라미터 정리를 하는데, 그때 max_hp가 바뀔 수 있기 때문에,
|
|
// hp 줄이기 전에 이것은 호출되어야 하고, onModifyStatAndAttribute는 최종 파라미터 전송등의 용도로 사용되어야 하기 때문이다.
|
|
onCompleteCalculateStat();
|
|
|
|
// 공속은 최소 10이다.
|
|
if( m_Attribute.fAttackSpeed < 10 ) m_Attribute.fAttackSpeed = 10;
|
|
|
|
// 이속이 최소 10이다.
|
|
if( m_Attribute.fMoveSpeed < GameRule::nMinSpeed ) m_Attribute.fMoveSpeed = GameRule::nMinSpeed;
|
|
|
|
// 크리티컬은 100 이 최대
|
|
if( m_Attribute.fCritical > 100 ) m_Attribute.fCritical = 100;
|
|
|
|
// 회피가 음수가 되어선 안 된다.
|
|
if( m_Attribute.fAvoid < 0 ) m_Attribute.fAvoid = 0;
|
|
if( m_Attribute.fMagicAvoid < 0 ) m_Attribute.fMagicAvoid = 0;
|
|
|
|
// MAX 치가 작아질경우도 있을수 있으므로 줄여준다
|
|
AddHP( 0 );
|
|
AddMP( 0 );
|
|
|
|
// 기공은 최대가 10개
|
|
if( m_nMaxEnergy > GameRule::ENERGY_MAX )
|
|
m_nMaxEnergy = GameRule::ENERGY_MAX;
|
|
|
|
// 라이딩 중이고 그 라이딩 특성이 '현재 속도가 라이딩 속도를 초과할 시 현재 속도로 적용'을 반영한다면
|
|
if( IsPlayer() && m_Attribute.fRidingSpeed && static_cast< StructPlayer* >( this )->IsApplyingFasterSpeedInRiding() )
|
|
{
|
|
if( m_Attribute.fMoveSpeed > m_Attribute.fRidingSpeed )
|
|
m_Attribute.fRidingSpeed = m_Attribute.fMoveSpeed;
|
|
}
|
|
|
|
// 핸들러 호출
|
|
onModifyStatAndAttribute();
|
|
|
|
if( isSkillModified( &prevAddedSkillBySkillType, &m_vAddedSkillBySkillType ) ||
|
|
isSkillModified( &prevAddedSkillBySkillId, &m_vAddedSkillBySkillId ) )
|
|
onModifySkill();
|
|
|
|
if( fPrevDetectHideRange != m_fDetectHideRange )
|
|
onModifyDetectRange();
|
|
|
|
if( IsInWorld() && ( prev_max_hp != GetMaxHP() || prev_max_mp != GetMaxMP() || prev_hp != GetHP() || prev_mp != GetMP() ) )
|
|
{
|
|
BroadcastHPMPMsg( this, GetHP() - prev_hp, GetMP() - prev_mp );
|
|
}
|
|
else if( IsSummon() && !IsInWorld() && ( prev_max_hp != GetMaxHP() || prev_max_mp != GetMaxMP() || prev_hp != GetHP() || prev_mp != GetMP() ) )
|
|
{
|
|
StructPlayer * pPlayer = static_cast< StructSummon * >( this )->GetMaster();
|
|
|
|
if( pPlayer )
|
|
SendHPMPMsg( pPlayer, this, GetHP() - prev_hp, GetMP() - prev_mp );
|
|
}
|
|
}
|
|
|
|
void StructCreature::initProc()
|
|
{
|
|
// 소멸자에서 delete를 하면, 복사 연산자의 호출 시에 문제가 발생하여 Deep copy를 해야하므로 직접 delete
|
|
std::vector< _ATTACK_TAG >::iterator attackIt;
|
|
std::map< int, std::vector< _PROC_TAG > >::iterator mapIt;
|
|
// std::vector< _PROC_TAG >에 대한 iterator를 멤버로 선언하면 _Clean_up_iter_debug에서 멈춰버린다. 원인은 아직 알 수 없음.
|
|
|
|
for( attackIt = m_vProcByAttack.begin(); attackIt != m_vProcByAttack.end(); ++attackIt ) delete (*attackIt).proc;
|
|
for( attackIt = m_vProcByBeingAttacked.begin(); attackIt != m_vProcByBeingAttacked.end(); ++attackIt ) delete (*attackIt).proc;
|
|
for( std::vector< _KILL_TAG >::iterator killIt = m_vProcByKill.begin(); killIt != m_vProcByKill.end(); ++killIt ) delete (*killIt).proc;
|
|
for( std::vector< _KILL_TAG >::iterator killIt = m_vProcByDead.begin(); killIt != m_vProcByDead.end(); ++killIt ) delete (*killIt).proc;
|
|
for( attackIt = m_vProcByCriticalAttack.begin(); attackIt != m_vProcByCriticalAttack.end(); ++attackIt ) delete (*attackIt).proc;
|
|
for( attackIt = m_vProcByBeingCriticalAttacked.begin(); attackIt != m_vProcByBeingCriticalAttacked.end(); ++attackIt ) delete (*attackIt).proc;
|
|
for( attackIt = m_vProcByAvoid.begin(); attackIt != m_vProcByAvoid.end(); ++attackIt ) delete (*attackIt).proc;
|
|
for( attackIt = m_vProcByBlock.begin(); attackIt != m_vProcByBlock.end(); ++attackIt ) delete (*attackIt).proc;
|
|
for( attackIt = m_vProcByPerfectBlock.begin(); attackIt != m_vProcByPerfectBlock.end(); ++attackIt ) delete (*attackIt).proc;
|
|
for( mapIt = m_mapProcBySkillId.begin(); mapIt != m_mapProcBySkillId.end(); ++mapIt )
|
|
{
|
|
for( std::vector< _PROC_TAG >::iterator procIt = (*mapIt).second.begin(); procIt != (*mapIt).second.end(); ++procIt )
|
|
{
|
|
delete (*procIt).proc;
|
|
}
|
|
}
|
|
|
|
m_vProcByAttack.clear();
|
|
m_vProcByBeingAttacked.clear();
|
|
m_vProcByKill.clear();
|
|
m_vProcByDead.clear();
|
|
m_vProcByCriticalAttack.clear();
|
|
m_vProcByBeingCriticalAttacked.clear();
|
|
m_vProcByAvoid.clear();
|
|
m_vProcByBlock.clear();
|
|
m_vProcByPerfectBlock.clear();
|
|
m_mapProcBySkillId.clear();
|
|
}
|
|
|
|
void StructCreature::calcAttribute( CreatureAttributeServer * pAttribute )
|
|
{
|
|
pAttribute->fCriticalPower = 80 ; // 80 Base Critical AziaMafia
|
|
pAttribute->fCritical += GameRule::GetCritical( GetLuck() );
|
|
|
|
if( IsUsingBow() || IsUsingCrossBow() )
|
|
{
|
|
pAttribute->fAttackPointRight += GameRule::GetBowAttackPoint( GetAgility(), GetDexterity(), GetBattleLevel(), GetFCM() );
|
|
}
|
|
else
|
|
{
|
|
pAttribute->fAttackPointRight += GameRule::GetAttackPoint( GetStrength(), GetBattleLevel(), GetFCM() );
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
pAttribute->fAttackPointLeft += GameRule::GetAttackPoint( GetStrength(), GetBattleLevel(), GetFCM() );
|
|
}
|
|
|
|
pAttribute->fMagicPoint += GameRule::GetMagicPoint( GetIntelligence(), GetBattleLevel(), GetFCM() );
|
|
pAttribute->fItemChance += GameRule::GetItemChance( GetLuck() );
|
|
pAttribute->fDefence += GameRule::GetDefence( GetBattleLevel(), GetVital(), GetFCM() );;
|
|
pAttribute->fMagicDefence += GameRule::GetMagicDefence( GetBattleLevel(), GetMentality(), GetFCM() );
|
|
pAttribute->fMaxWeight += GameRule::GetMaxWeight( GetLevel(), GetStrength() );
|
|
|
|
pAttribute->fAccuracyRight += GameRule::GetAccuracy( GetDexterity(), GetBattleLevel(), GetFCM() );
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
pAttribute->fAccuracyLeft += GameRule::GetAccuracy( GetDexterity(), GetBattleLevel(), GetFCM() );
|
|
|
|
pAttribute->fMagicAccuracy += GameRule::GetMagicAccuracy( GetMentality(), GetDexterity(), GetBattleLevel(), GetFCM() );
|
|
pAttribute->fAvoid += GameRule::GetAvoid( GetAgility(), GetBattleLevel(), GetFCM() );
|
|
pAttribute->fMagicAvoid += GameRule::GetMagicAvoid( GetMentality(), GetBattleLevel() , GetFCM());
|
|
|
|
pAttribute->fAttackSpeedRight += GameRule::GetAttackSpeed( GetAgility() ); // 공격속도 (2010-05-07 리뉴얼 적용)
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
pAttribute->fAttackSpeedLeft += GameRule::GetAttackSpeed( GetAgility() ); // 공격속도 (2010-05-07 리뉴얼 적용)
|
|
|
|
if( !isMoveSpeedFixed() )
|
|
{
|
|
pAttribute->fMoveSpeed += GameRule::GetBaseMoveSpeed(); // 기본 이동속도 (2007-03-24 리뉴얼 적용)
|
|
}
|
|
pAttribute->fCastingSpeed += GameRule::GetCastingTime( GetDexterity(), GetMentality(), GetBattleLevel() );
|
|
pAttribute->fCoolTimeSpeed = 100;
|
|
pAttribute->fHPRegenPercentage += GameRule::GetHPRegenPercentage( GetFCM() );
|
|
pAttribute->fHPRegenPoint += GameRule::GetHPRegenPoint( GetBattleLevel() );
|
|
pAttribute->fMPRegenPercentage += GameRule::GetMPRegenPercentage( GetFCM() );
|
|
pAttribute->fMPRegenPoint += GameRule::GetMPRegenPoint( GetBattleLevel(), GetMentality() );
|
|
pAttribute->fPerfectBlock += GameRule::GetPerfectBlock();
|
|
|
|
|
|
// 사거리가 없으면 기본사거리 적용
|
|
if( !pAttribute->fAttackRange ) pAttribute->fAttackRange = GameRule::DEFAULT_ATTACK_RANGE * GameRule::ATTACK_RANGE_UNIT;
|
|
}
|
|
|
|
|
|
void StructSummon::calcAttribute( CreatureAttributeServer* pAttribute )
|
|
{
|
|
StructCreature::calcAttribute( pAttribute );
|
|
|
|
int nCorrection = 0;
|
|
|
|
if( GetMaster() )
|
|
{
|
|
// (2007-03-24 리뉴얼 적용)
|
|
nCorrection = ( 2 * GetMaster()->GetLevel() - GetLevel() ) / GetLevel();
|
|
}
|
|
|
|
pAttribute->fAccuracyRight += nCorrection;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
pAttribute->fAccuracyLeft += nCorrection;
|
|
|
|
pAttribute->fMagicAccuracy += nCorrection;
|
|
}
|
|
|
|
// --- 스탯 및 능력치 연산에 관련된 패시브 스킬들 적용하는 루틴 ---
|
|
void StructCreature::applyStatByPassiveSkill()
|
|
{
|
|
if( m_vPassiveSkillList.empty() ) return;
|
|
|
|
std::vector< StructSkill *>::iterator it;
|
|
|
|
for( it = m_vPassiveSkillList.begin(); it != m_vPassiveSkillList.end(); ++it )
|
|
{
|
|
StructSkill * pSkill = (*it);
|
|
|
|
// 디버프, 랜덤 스킬초기화로 인해 현재 스킬 레벨이 0 이하인 경우 효과가 적용되지 않는다.
|
|
if( pSkill->GetCurrentSkillLevel() <= 0 )
|
|
continue;
|
|
|
|
if( pSkill->GetSkillBase()->IsNeedWeapon() )
|
|
{
|
|
// 스킬에 적합한 무기인지?
|
|
if( pSkill->IsUseableWeapon( ItemBase::CLASS_SHIELD ) )
|
|
{
|
|
if( !IsWearShield() )
|
|
continue;
|
|
}
|
|
else if( !pSkill->IsUseableWeapon( GetWeaponClass() ) )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ( pSkill->GetSkillBase()->GetEffectType() == SkillBase::EF_PARAMETER_INC )
|
|
{
|
|
incParameter( pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), true );
|
|
incParameter( pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), true );
|
|
incParameter( pSkill->GetVar( 12 ), pSkill->GetVar( 13 ) + pSkill->GetVar( 14 ) * pSkill->GetCurrentSkillLevel(), true );
|
|
incParameter( pSkill->GetVar( 15 ), pSkill->GetVar( 16 ) + pSkill->GetVar( 17 ) * pSkill->GetCurrentSkillLevel(), true );
|
|
}
|
|
else if ( pSkill->GetSkillBase()->GetEffectType() == SkillBase::EF_PARAMETER_AMP )
|
|
{
|
|
m_vAmplifyPassiveSkillList.push_back( pSkill );
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructCreature::amplifyStatByPassiveSkill()
|
|
{
|
|
if( m_vAmplifyPassiveSkillList.empty() ) return;
|
|
|
|
std::vector< StructSkill *>::iterator it;
|
|
|
|
for( it = m_vAmplifyPassiveSkillList.begin(); it != m_vAmplifyPassiveSkillList.end(); ++it )
|
|
{
|
|
StructSkill * pSkill = (*it);
|
|
|
|
// 디버프, 랜덤 스킬초기화로 인해 현재 스킬 레벨이 0 이하인 경우 효과가 적용되지 않는다.
|
|
if( pSkill->GetCurrentSkillLevel() <= 0 )
|
|
continue;
|
|
|
|
if ( pSkill->GetSkillBase()->GetEffectType() == SkillBase::EF_PARAMETER_AMP )
|
|
{
|
|
ampParameter( pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), true );
|
|
ampParameter( pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), true );
|
|
ampParameter( pSkill->GetVar( 12 ), pSkill->GetVar( 13 ) + pSkill->GetVar( 14 ) * pSkill->GetCurrentSkillLevel(), true );
|
|
ampParameter( pSkill->GetVar( 15 ), pSkill->GetVar( 16 ) + pSkill->GetVar( 17 ) * pSkill->GetCurrentSkillLevel(), true );
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructCreature::applyPassiveSkillEffect()
|
|
{
|
|
if( m_vPassiveSkillList.empty() ) return;
|
|
|
|
std::vector< StructSkill *>::iterator it;
|
|
|
|
for( it = m_vPassiveSkillList.begin(); it != m_vPassiveSkillList.end(); ++it )
|
|
{
|
|
StructSkill * pSkill = (*it);
|
|
|
|
// 디버프, 랜덤 스킬초기화로 인해 현재 스킬 레벨이 0 이하인 경우 효과가 적용되지 않는다.
|
|
if( pSkill->GetCurrentSkillLevel() <= 0 )
|
|
continue;
|
|
|
|
if( pSkill->GetSkillBase()->IsNeedWeapon() )
|
|
{
|
|
// 스킬에 적합한 무기인지?
|
|
if( pSkill->IsUseableWeapon( ItemBase::CLASS_SHIELD ) )
|
|
{
|
|
if( !IsWearShield() )
|
|
continue;
|
|
}
|
|
else if( !pSkill->IsUseableWeapon( GetWeaponClass() ) )
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
applyPassiveSkillEffect( pSkill );
|
|
}
|
|
}
|
|
|
|
void StructSummon::applyPassiveSkillEffect()
|
|
{
|
|
StructCreature::applyPassiveSkillEffect();
|
|
|
|
m_nMaxHP += m_ParameterForSummon.nMaxHP;
|
|
m_nMaxMP += m_ParameterForSummon.nMaxMP;
|
|
m_nMaxSP += m_ParameterForSummon.nMaxSP;
|
|
m_Attribute.fHPRegenPoint += m_ParameterForSummon.Attribute.fHPRegenPoint;
|
|
m_Attribute.fMPRegenPoint += m_ParameterForSummon.Attribute.fHPRegenPoint;
|
|
m_nSPRegenAdd += m_ParameterForSummon.nSPRegenAdd;
|
|
}
|
|
|
|
void StructCreature::applyPassiveSkillEffect( struct StructSkill * pSkill )
|
|
{
|
|
switch( pSkill->GetSkillBase()->GetSkillEffectType() )
|
|
{
|
|
//case SkillBase::EF_DOUBLE_WEAPON:
|
|
// {
|
|
// // 눈물을 머금고...따로 처리.ㅜ.ㅜ
|
|
// }
|
|
// break;
|
|
|
|
case SkillBase::EF_PARAMETER_INC:
|
|
{
|
|
incParameter( pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
incParameter( pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
incParameter2( pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
incParameter2( pSkill->GetVar( 9 ), pSkill->GetVar( 10 ) + pSkill->GetVar( 11 ) * pSkill->GetCurrentSkillLevel() );
|
|
incParameter( pSkill->GetVar( 12 ), pSkill->GetVar( 13 ) + pSkill->GetVar( 14 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
incParameter( pSkill->GetVar( 15 ), pSkill->GetVar( 16 ) + pSkill->GetVar( 17 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
break;
|
|
}
|
|
case SkillBase::EF_WEAPON_MASTERY:
|
|
{
|
|
StructItem * pWeapon = GetWearedItem( ItemBase::WEAR_WEAPON );
|
|
|
|
if( pSkill->GetSkillId() == StructSkill::SKILL_ADV_WEAPON_EXPERT ) // 전문 무기 숙련은 2랭크 이상에만 적용되게 예외처리
|
|
{
|
|
if( !pWeapon || pWeapon->GetItemRank() < 2 )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
c_fixed10 fAP = pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fSpeed = pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fAccuracy = pSkill->GetVar(4) + pSkill->GetVar(5) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_Attribute.fAttackPointRight += fAP;
|
|
m_Attribute.fAttackSpeedRight += fSpeed;
|
|
m_Attribute.fAccuracyRight += fAccuracy;
|
|
|
|
//m_nAttackPointRightByWeaponMastery += nAP;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
m_Attribute.fAttackPointLeft += fAP;
|
|
m_Attribute.fAttackSpeedLeft += fSpeed;
|
|
m_Attribute.fAccuracyLeft += fAccuracy;
|
|
|
|
//m_nAttackPointLeftByWeaponMastery += nAP;
|
|
}
|
|
|
|
m_Attribute.fMagicPoint += pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * pSkill->GetCurrentSkillLevel();
|
|
m_Attribute.fCritical += pSkill->GetVar( 8 ) + pSkill->GetVar( 9 ) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_BATTLE_PARAMTER_INCREASE:
|
|
{
|
|
c_fixed10 fAP = pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fDefence = pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fMP = pSkill->GetVar(4) + pSkill->GetVar(5) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fMD = pSkill->GetVar(6) + pSkill->GetVar(7) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fAvoid = pSkill->GetVar(8) + pSkill->GetVar(9) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_Attribute.fAttackPointRight += fAP;
|
|
m_fAttackPointRightWithoutWeapon += fAP;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
m_Attribute.fAttackPointLeft += fAP;
|
|
m_fAttackPointLeftWithoutWeapon += fAP;
|
|
}
|
|
|
|
m_Attribute.fDefence += fDefence;
|
|
m_Attribute.fMagicPoint += fMP;
|
|
m_Attribute.fMagicDefence += fMD;
|
|
m_Attribute.fAvoid += fAvoid;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_BLOCK_INCREASE:
|
|
{
|
|
m_Attribute.fBlockChance += pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
m_Attribute.fBlockDefence += pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_ATTACK_RANGE_INCREASE:
|
|
{
|
|
m_Attribute.fAttackRange += ( pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel() ) * GameRule::ATTACK_RANGE_UNIT;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_RESISTANCE_INCREASE:
|
|
{
|
|
m_Attribute.fStunResistance += pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
m_Attribute.fMoveSpeedDecreaseResistance += pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INCREASE_BASE_ATTRIBUTE:
|
|
{
|
|
int nSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
|
|
m_Attribute.fAttackPointRight += pSkill->GetVar( 0 ) * nSkillLevel;
|
|
m_fAttackPointRightWithoutWeapon += pSkill->GetVar( 0 ) * nSkillLevel;
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
m_Attribute.fAttackPointLeft += pSkill->GetVar( 0 ) * nSkillLevel;
|
|
m_fAttackPointLeftWithoutWeapon += pSkill->GetVar( 0 ) * nSkillLevel;
|
|
}
|
|
|
|
m_Attribute.fDefence += pSkill->GetVar( 1 ) * nSkillLevel;
|
|
|
|
m_Attribute.fMagicPoint += pSkill->GetVar( 2 ) * nSkillLevel;
|
|
m_Attribute.fMagicDefence += pSkill->GetVar( 3 ) * nSkillLevel;
|
|
|
|
m_Attribute.fAttackSpeedRight += pSkill->GetVar( 4 ) * nSkillLevel;
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
m_Attribute.fAttackSpeedLeft += pSkill->GetVar( 4 ) * nSkillLevel;
|
|
}
|
|
|
|
if( !isMoveSpeedFixed() ) // fRidingSpeed 수치가 생기면서 라이딩 중에도 기본 속도에 관여할 수 있게 변경 ( 2013-12-20 )
|
|
{
|
|
m_Attribute.fMoveSpeed += pSkill->GetVar( 5 ) * nSkillLevel;
|
|
}
|
|
|
|
m_Attribute.fAccuracyRight += pSkill->GetVar( 6 ) * nSkillLevel;
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
m_Attribute.fAccuracyRight += pSkill->GetVar( 6 ) * nSkillLevel;
|
|
}
|
|
|
|
m_Attribute.fMagicAccuracy += pSkill->GetVar( 7 ) * nSkillLevel;
|
|
|
|
m_Attribute.fAvoid += pSkill->GetVar( 8 ) * nSkillLevel;
|
|
m_Attribute.fMagicAvoid += pSkill->GetVar( 9 ) * nSkillLevel;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_AMPLIFY_BASE_ATTRIBUTE_OLD:
|
|
case SkillBase::EF_AMPLIFY_BASE_ATTRIBUTE:
|
|
{
|
|
int nSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
|
|
m_AttributeAmplifier.fAttackPointRight += pSkill->GetVar(0) * nSkillLevel;
|
|
m_AttributeAmplifier.fAttackSpeedRight += pSkill->GetVar(4) * nSkillLevel;
|
|
m_AttributeAmplifier.fAccuracyRight += pSkill->GetVar(6) * nSkillLevel;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
m_AttributeAmplifier.fAttackPointLeft += pSkill->GetVar(0) * nSkillLevel;
|
|
m_AttributeAmplifier.fAttackSpeedLeft += pSkill->GetVar(4) * nSkillLevel;
|
|
m_AttributeAmplifier.fAccuracyLeft += pSkill->GetVar(6) * nSkillLevel;
|
|
}
|
|
|
|
m_AttributeAmplifier.fDefence += pSkill->GetVar(1) * nSkillLevel;
|
|
m_AttributeAmplifier.fMagicPoint += pSkill->GetVar(2) * nSkillLevel;
|
|
m_AttributeAmplifier.fMagicDefence += pSkill->GetVar(3) * nSkillLevel;
|
|
m_AttributeAmplifier.fMoveSpeed += pSkill->GetVar(5) * nSkillLevel;
|
|
m_AttributeAmplifier.fMagicAccuracy += pSkill->GetVar(7) * nSkillLevel;
|
|
m_AttributeAmplifier.fAvoid += pSkill->GetVar(8) * nSkillLevel;
|
|
m_AttributeAmplifier.fMagicAvoid += pSkill->GetVar(9) * nSkillLevel;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INCREASE_EXTENSION_ATTRIBUTE:
|
|
{
|
|
int nSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
|
|
m_Attribute.fHPRegenPercentage += pSkill->GetVar( 0 ) * nSkillLevel;
|
|
m_Attribute.fHPRegenPoint += pSkill->GetVar( 1 ) * nSkillLevel;
|
|
m_Attribute.fMPRegenPercentage += pSkill->GetVar( 2 ) * nSkillLevel;
|
|
m_Attribute.fMPRegenPoint += pSkill->GetVar( 3 ) * nSkillLevel;
|
|
m_Attribute.fBlockChance += pSkill->GetVar( 4 ) * nSkillLevel;
|
|
m_Attribute.fBlockDefence += pSkill->GetVar( 5 ) * nSkillLevel;
|
|
m_Attribute.fCritical += pSkill->GetVar( 6 ) * nSkillLevel;
|
|
m_Attribute.fCriticalPower += pSkill->GetVar( 7 ) * nSkillLevel;
|
|
m_Attribute.fCastingSpeed += pSkill->GetVar( 8 ) * nSkillLevel;
|
|
// 쿨타임 스피드는 작아야 빠른거다(-┏ 이러고도 스피드냐;;)
|
|
m_Attribute.fCoolTimeSpeed -= pSkill->GetVar( 9 ) * nSkillLevel;
|
|
// 화살 데미지 감소율??
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_MAGIC_REGISTANCE_INCREASE:
|
|
{
|
|
int nElemental;
|
|
int nElementalInc;
|
|
|
|
for( int i = 0; i < 4; ++i )
|
|
{
|
|
nElemental = pSkill->GetVar( 3 * i);
|
|
nElementalInc = pSkill->GetVar( 3 * i + 1 ) + pSkill->GetVar( 3 * i + 2 ) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_Resist.nResist[ nElemental ] += nElementalInc;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_SPECIALIZE_ARMOR:
|
|
{
|
|
if( GetArmorClass() != pSkill->GetVar( 0 ) )
|
|
break;
|
|
|
|
m_Attribute.fAccuracyRight += pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel();
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
m_Attribute.fAccuracyLeft += pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_Attribute.fAvoid += pSkill->GetVar( 3 ) + pSkill->GetVar( 4 ) * pSkill->GetCurrentSkillLevel();
|
|
m_Attribute.fMPRegenPercentage += pSkill->GetVar( 5 ) + pSkill->GetVar( 6 ) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
break;
|
|
case SkillBase::EF_SPECIALIZE_ARMOR_AMP:
|
|
{
|
|
if( GetArmorClass() != pSkill->GetVar( 0 ) )
|
|
break;
|
|
|
|
m_AttributeAmplifier.fAttackSpeedRight += pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel();
|
|
if( IsUsingDoubleWeapon() )
|
|
m_AttributeAmplifier.fAttackSpeedLeft += pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_AttributeAmplifier.fCritical += pSkill->GetVar( 3 ) + pSkill->GetVar( 4 ) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_fMaxHPAmplifier += pSkill->GetVar( 5 ) + pSkill->GetVar( 6 ) * pSkill->GetCurrentSkillLevel();
|
|
m_fMaxMPAmplifier += pSkill->GetVar( 11 ) + pSkill->GetVar( 12 ) * pSkill->GetCurrentSkillLevel();
|
|
m_AttributeAmplifier.fHPRegenPercentage += pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel();
|
|
m_AttributeAmplifier.fMPRegenPercentage += pSkill->GetVar( 9 ) + pSkill->GetVar( 10 ) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
break;
|
|
|
|
// 삭제된 유형
|
|
case SkillBase::EF_MAGIC_TRAINING:
|
|
{
|
|
int nCastSpeed = pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fCoolTime = pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
int nCastKeep = pSkill->GetVar(4) + pSkill->GetVar(5) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_Attribute.fCastingSpeed += nCastSpeed;
|
|
m_Attribute.fCoolTimeSpeed -= m_Attribute.fCoolTimeSpeed * fCoolTime;
|
|
m_nCastKeep += nCastKeep;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_HUNTING_TRAINING:
|
|
{
|
|
for( int i = 0; i < 3; i++ )
|
|
{
|
|
int nCreatureType = pSkill->GetVar( i * 5 );
|
|
|
|
c_fixed10 fDamage = pSkill->GetVar( i * 5 + 1 ) + pSkill->GetVar( i * 5 + 2 ) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fAvoid = pSkill->GetVar( i * 5 + 3 ) + pSkill->GetVar( i * 5 + 4 ) * pSkill->GetCurrentSkillLevel();
|
|
|
|
if( nCreatureType == CREATURE_ALL )
|
|
{
|
|
for( int i = 0 ; i < MAX_CREATURE_TYPE_NUMBER ; ++i )
|
|
{
|
|
m_Expert[ i ].fDamage += fDamage;
|
|
m_Expert[ i ].fAvoid += fAvoid;
|
|
}
|
|
}
|
|
else if( nCreatureType >= 0 && nCreatureType < MAX_CREATURE_TYPE_NUMBER )
|
|
{
|
|
m_Expert[ nCreatureType ].fDamage += fDamage;
|
|
m_Expert[ nCreatureType ].fAvoid += fAvoid;
|
|
}
|
|
else
|
|
{
|
|
assert( 0 && "CREATURE DATA TYPE ERROR!" );
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_BOW_TRAINING:
|
|
{
|
|
// TODO : 나중에 처리
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INCREASE_HP_MP:
|
|
{
|
|
int nMaxHPInc = pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
int nMaxMPInc = pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
int nHPRegenInc = pSkill->GetVar(6) + pSkill->GetVar(7) * pSkill->GetCurrentSkillLevel();
|
|
int nMPRegenInc = pSkill->GetVar(8) + pSkill->GetVar(9) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_nMaxHP += nMaxHPInc;
|
|
m_nMaxMP += nMaxMPInc;
|
|
m_Attribute.fHPRegenPoint += nHPRegenInc;
|
|
m_Attribute.fMPRegenPoint += nMPRegenInc;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_AMPLIFY_HP_MP:
|
|
{
|
|
m_vAmplifyPassiveSkillList.push_back( pSkill );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_HEALING_AMPLIFY:
|
|
{
|
|
c_fixed10 fHPHealRatio = pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fMPHealRatio = pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_fHealRatio += fHPHealRatio;
|
|
m_fMPHealRatio += fMPHealRatio;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_HEALING_AMPLIFY_BY_ITEM:
|
|
{
|
|
c_fixed10 fHPHealRatioByItem = pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fMPHealRatioByItem = pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_fHealRatioByItem += fHPHealRatioByItem;
|
|
m_fMPHealRatioByItem += fMPHealRatioByItem;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_HEALING_AMPLIFY_BY_REST:
|
|
{
|
|
c_fixed10 fHPHealRatioByRest = pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fMPHealRatioByRest = pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_fHealRatioByRest += fHPHealRatioByRest;
|
|
m_fMPHealRatioByRest += fMPHealRatioByRest;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_HATE_AMPLIFY:
|
|
{
|
|
m_fHateRatio += pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
break;
|
|
|
|
|
|
// 코드량이 지나치게 많지만 가독성 때문에 우선 펼쳐둔다.
|
|
case SkillBase::EF_ADD_STATE_ON_ATTACK:
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_ATTACK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 8 ) && weapon_class != pSkill->GetVar( 9 ) && weapon_class != pSkill->GetVar( 10 ) && weapon_class != pSkill->GetVar( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pSkill->GetSkillBase()->GetEffectType() )
|
|
{
|
|
case SkillBase::EF_ADD_STATE_ON_ATTACK: nTarget = StructProc::ATTACKEE; break;
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_ATTACK: nTarget = StructProc::ATTACKER; break;
|
|
}
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 12 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByAttack.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pSkill->GetVar( 0 ) ), pSkill->GetVar( 2 ) + pSkill->GetVar( 3 ) * pSkill->GetCurrentSkillLevel(), ( pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel() ) * 100, nTarget, pSkill->GetVar( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_ADD_STATE_ON_BEING_ATTACKED:
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_BEING_ATTACKED:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 8 ) && weapon_class != pSkill->GetVar( 9 ) && weapon_class != pSkill->GetVar( 10 ) && weapon_class != pSkill->GetVar( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pSkill->GetSkillBase()->GetEffectType() )
|
|
{
|
|
case SkillBase::EF_ADD_STATE_ON_BEING_ATTACKED: nTarget = StructProc::ATTACKER; break;
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_BEING_ATTACKED: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByBeingAttacked.push_back( _ATTACK_TAG( pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 12 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByBeingAttacked.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pSkill->GetVar( 0 ) ), pSkill->GetVar( 2 ) + pSkill->GetVar( 3 ) * pSkill->GetCurrentSkillLevel(), ( pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel() ) * 100, nTarget, pSkill->GetVar( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_KILL:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 8 ) && weapon_class != pSkill->GetVar( 9 ) && weapon_class != pSkill->GetVar( 10 ) && weapon_class != pSkill->GetVar( 11 ) )
|
|
break;
|
|
|
|
m_vProcByKill.push_back( _KILL_TAG( pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), 0, 0, pSkill->GetVar( 18 ), pSkill->GetVar( 19 ), NULL ) );
|
|
m_vProcByKill.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pSkill->GetVar( 0 ) ), pSkill->GetVar( 2 ) + pSkill->GetVar( 3 ) * pSkill->GetCurrentSkillLevel(), ( pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel() ) * 100, StructProc::ATTACKER, pSkill->GetVar( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_ADD_STATE_ON_CRITICAL_ATTACK:
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_CRITICAL_ATTACK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 8 ) && weapon_class != pSkill->GetVar( 9 ) && weapon_class != pSkill->GetVar( 10 ) && weapon_class != pSkill->GetVar( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pSkill->GetSkillBase()->GetEffectType() )
|
|
{
|
|
case SkillBase::EF_ADD_STATE_ON_CRITICAL_ATTACK: nTarget = StructProc::ATTACKEE; break;
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_CRITICAL_ATTACK: nTarget = StructProc::ATTACKER; break;
|
|
}
|
|
|
|
m_vProcByCriticalAttack.push_back( _ATTACK_TAG( pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 12 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByCriticalAttack.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pSkill->GetVar( 0 ) ), pSkill->GetVar( 2 ) + pSkill->GetVar( 3 ) * pSkill->GetCurrentSkillLevel(), ( pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel() ) * 100, nTarget, pSkill->GetVar( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_ADD_STATE_ON_BEING_CRITICAL_ATTACKED:
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_BEING_CRITICAL_ATTACKED:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 8 ) && weapon_class != pSkill->GetVar( 9 ) && weapon_class != pSkill->GetVar( 10 ) && weapon_class != pSkill->GetVar( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pSkill->GetSkillBase()->GetEffectType() )
|
|
{
|
|
case SkillBase::EF_ADD_STATE_ON_BEING_CRITICAL_ATTACKED: nTarget = StructProc::ATTACKER; break;
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_BEING_CRITICAL_ATTACKED: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByBeingCriticalAttacked.push_back( _ATTACK_TAG( pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 12 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByBeingCriticalAttacked.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pSkill->GetVar( 0 ) ), pSkill->GetVar( 2 ) + pSkill->GetVar( 3 ) * pSkill->GetCurrentSkillLevel(), ( pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel() ) * 100, nTarget, pSkill->GetVar( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_ADD_STATE_ON_AVOID:
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_AVOID:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 8 ) && weapon_class != pSkill->GetVar( 9 ) && weapon_class != pSkill->GetVar( 10 ) && weapon_class != pSkill->GetVar( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pSkill->GetSkillBase()->GetEffectType() )
|
|
{
|
|
case SkillBase::EF_ADD_STATE_ON_AVOID: nTarget = StructProc::ATTACKER; break;
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_AVOID: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByAvoid.push_back( _ATTACK_TAG( pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 12 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByAvoid.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pSkill->GetVar( 0 ) ), pSkill->GetVar( 2 ) + pSkill->GetVar( 3 ) * pSkill->GetCurrentSkillLevel(), ( pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel() ) * 100, nTarget, pSkill->GetVar( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_ADD_STATE_ON_BLOCK:
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_BLOCK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 8 ) && weapon_class != pSkill->GetVar( 9 ) && weapon_class != pSkill->GetVar( 10 ) && weapon_class != pSkill->GetVar( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pSkill->GetSkillBase()->GetEffectType() )
|
|
{
|
|
case SkillBase::EF_ADD_STATE_ON_BLOCK: nTarget = StructProc::ATTACKER; break;
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_BLOCK: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByBlock.push_back( _ATTACK_TAG( pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 12 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByBlock.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pSkill->GetVar( 0 ) ), pSkill->GetVar( 2 ) + pSkill->GetVar( 3 ) * pSkill->GetCurrentSkillLevel(), ( pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel() ) * 100, nTarget, pSkill->GetVar( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_ADD_STATE_ON_PERFECT_BLOCK:
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_PERFECT_BLOCK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 8 ) && weapon_class != pSkill->GetVar( 9 ) && weapon_class != pSkill->GetVar( 10 ) && weapon_class != pSkill->GetVar( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pSkill->GetSkillBase()->GetEffectType() )
|
|
{
|
|
case SkillBase::EF_ADD_STATE_ON_PERFECT_BLOCK: nTarget = StructProc::ATTACKER; break;
|
|
case SkillBase::EF_ADD_STATE_BY_SELF_ON_PERFECT_BLOCK: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByPerfectBlock.push_back( _ATTACK_TAG( pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 12 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByPerfectBlock.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pSkill->GetVar( 0 ) ), pSkill->GetVar( 2 ) + pSkill->GetVar( 3 ) * pSkill->GetCurrentSkillLevel(), ( pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel() ) * 100, nTarget, pSkill->GetVar( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_ADD_ENERGY_ON_ATTACK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 8 ) && weapon_class != pSkill->GetVar( 9 ) && weapon_class != pSkill->GetVar( 10 ) && weapon_class != pSkill->GetVar( 11 ) )
|
|
break;
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 12 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByAttack.back().proc = new StructEnergyProc( StructProc::ATTACKER, pSkill->GetVar( 0 ) + pSkill->GetVar( 1 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_ADD_ENERGY_ON_BEING_ATTACKED:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 8 ) && weapon_class != pSkill->GetVar( 9 ) && weapon_class != pSkill->GetVar( 10 ) && weapon_class != pSkill->GetVar( 11 ) )
|
|
break;
|
|
|
|
m_vProcByBeingAttacked.push_back( _ATTACK_TAG( pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 12 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByBeingAttacked.back().proc = new StructEnergyProc( StructProc::ATTACKEE, pSkill->GetVar( 0 ) + pSkill->GetVar( 1 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_SKILL_COOL_TIME_ON_ATTACK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 11 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 11 ) && weapon_class != pSkill->GetVar( 12 ) )
|
|
break;
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( pSkill->GetVar( 9 ) + pSkill->GetVar( 10 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 13 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByAttack.back().proc = new StructCooldownProc( StructProc::ATTACKER, pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_SKILL_COOL_TIME_ON_BEING_ATTACKED:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 11 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 11 ) && weapon_class != pSkill->GetVar( 12 ) )
|
|
break;
|
|
|
|
m_vProcByBeingAttacked.push_back( _ATTACK_TAG( pSkill->GetVar( 9 ) + pSkill->GetVar( 10 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 13 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByBeingAttacked.back().proc = new StructCooldownProc( StructProc::ATTACKEE, pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_SKILL_COOL_TIME_ON_KILL:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 11 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 11 ) && weapon_class != pSkill->GetVar( 12 ) )
|
|
break;
|
|
|
|
m_vProcByKill.push_back( _KILL_TAG( pSkill->GetVar( 9 ) + pSkill->GetVar( 10 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), 0, 0, pSkill->GetVar( 18 ), pSkill->GetVar( 19 ), NULL ) );
|
|
m_vProcByKill.back().proc = new StructCooldownProc( StructProc::ATTACKER, pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_SKILL_COOL_TIME_ON_CRITICAL_ATTACK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 11 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 11 ) && weapon_class != pSkill->GetVar( 12 ) )
|
|
break;
|
|
|
|
m_vProcByCriticalAttack.push_back( _ATTACK_TAG( pSkill->GetVar( 9 ) + pSkill->GetVar( 10 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 13 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByCriticalAttack.back().proc = new StructCooldownProc( StructProc::ATTACKER, pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_SKILL_COOL_TIME_ON_BEING_CRITICAL_ATTACKED:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 11 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 11 ) && weapon_class != pSkill->GetVar( 12 ) )
|
|
break;
|
|
|
|
m_vProcByBeingCriticalAttacked.push_back( _ATTACK_TAG( pSkill->GetVar( 9 ) + pSkill->GetVar( 10 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 13 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByBeingCriticalAttacked.back().proc = new StructCooldownProc( StructProc::ATTACKEE, pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_SKILL_COOL_TIME_ON_AVOID:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 11 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 11 ) && weapon_class != pSkill->GetVar( 12 ) )
|
|
break;
|
|
|
|
m_vProcByAvoid.push_back( _ATTACK_TAG( pSkill->GetVar( 9 ) + pSkill->GetVar( 10 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 13 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByAvoid.back().proc = new StructCooldownProc( StructProc::ATTACKEE, pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_SKILL_COOL_TIME_ON_BLOCK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 11 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 11 ) && weapon_class != pSkill->GetVar( 12 ) )
|
|
break;
|
|
|
|
m_vProcByBlock.push_back( _ATTACK_TAG( pSkill->GetVar( 9 ) + pSkill->GetVar( 10 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 13 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByBlock.back().proc = new StructCooldownProc( StructProc::ATTACKEE, pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_SKILL_COOL_TIME_ON_PERFECT_BLOCK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pSkill->GetVar( 11 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pSkill->GetVar( 11 ) && weapon_class != pSkill->GetVar( 12 ) )
|
|
break;
|
|
|
|
m_vProcByPerfectBlock.push_back( _ATTACK_TAG( pSkill->GetVar( 9 ) + pSkill->GetVar( 10 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), pSkill->GetVar( 13 ), pSkill->GetVar( 18 ), NULL ) );
|
|
m_vProcByPerfectBlock.back().proc = new StructCooldownProc( StructProc::ATTACKEE, pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_SKILL_COOL_TIME_ON_SKILL_OF_ID:
|
|
{
|
|
for( int i = 11; i < 14; ++i )
|
|
{
|
|
int nSkillId = pSkill->GetVar( i );
|
|
if( !nSkillId ) break;
|
|
|
|
std::map< int, std::vector< _PROC_TAG > >::const_iterator it = m_mapProcBySkillId.find( nSkillId );
|
|
|
|
if( it == m_mapProcBySkillId.end() )
|
|
{
|
|
m_mapProcBySkillId.insert( std::make_pair( nSkillId, std::vector< _PROC_TAG >() ) );
|
|
}
|
|
|
|
std::vector< _PROC_TAG > & vProc = m_mapProcBySkillId[ nSkillId ];
|
|
vProc.push_back( _PROC_TAG( pSkill->GetVar( 9 ) + pSkill->GetVar( 10 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 14 ), pSkill->GetVar( 15 ), pSkill->GetVar( 16 ), pSkill->GetVar( 17 ), NULL ) );
|
|
vProc.back().proc = new StructCooldownProc( StructProc::ATTACKER, pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_WEAPON_TRAINING:
|
|
{
|
|
StructItem * pWeapon = GetWearedItem( ItemBase::WEAR_WEAPON );
|
|
|
|
if( !pWeapon )
|
|
break;
|
|
|
|
c_fixed10 fAttackPoint = pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fAttackSpeed = pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fAccuracy = pSkill->GetVar(4) + pSkill->GetVar(5) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fMagicPoint = pSkill->GetVar(6) + pSkill->GetVar(7) * pSkill->GetCurrentSkillLevel();
|
|
c_fixed10 fCritical = pSkill->GetVar(8) + pSkill->GetVar(9) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_AttributeAmplifier.fAttackPointRight += fAttackPoint;
|
|
m_AttributeAmplifier.fAttackSpeedRight += fAttackSpeed;
|
|
m_AttributeAmplifier.fAccuracyRight += fAccuracy;
|
|
|
|
//m_nAttackPointRightByWeaponMastery += nAP;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
m_AttributeAmplifier.fAttackPointLeft += fAttackPoint;
|
|
m_AttributeAmplifier.fAttackSpeedLeft += fAttackSpeed;
|
|
m_AttributeAmplifier.fAccuracyLeft += fAccuracy;
|
|
|
|
//m_nAttackPointLeftByWeaponMastery += nAP;
|
|
}
|
|
|
|
m_AttributeAmplifier.fMagicPoint += fMagicPoint;
|
|
m_AttributeAmplifier.fCritical += fCritical;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_AMPLIFY_EXT_ATTRIBUTE:
|
|
{
|
|
int nSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
|
|
m_AttributeAmplifier.fHPRegenPercentage += pSkill->GetVar(0) * nSkillLevel;
|
|
m_AttributeAmplifier.fHPRegenPoint += pSkill->GetVar(1) * nSkillLevel;
|
|
m_AttributeAmplifier.fMPRegenPercentage += pSkill->GetVar(2) * nSkillLevel;
|
|
m_AttributeAmplifier.fMPRegenPoint += pSkill->GetVar(3) * nSkillLevel;
|
|
m_AttributeAmplifier.fBlockChance += pSkill->GetVar(4) * nSkillLevel;
|
|
m_AttributeAmplifier.fBlockDefence += pSkill->GetVar(5) * nSkillLevel;
|
|
m_AttributeAmplifier.fCritical += pSkill->GetVar(6) * nSkillLevel;
|
|
m_AttributeAmplifier.fCriticalPower += pSkill->GetVar(7) * nSkillLevel;
|
|
m_AttributeAmplifier.fCastingSpeed += pSkill->GetVar(8) * nSkillLevel;
|
|
m_AttributeAmplifier.fCoolTimeSpeed += pSkill->GetVar(9) * nSkillLevel;
|
|
|
|
// 캐스팅 보전 따위... 그냥 곱해
|
|
m_nCastKeep *= pSkill->GetVar(10) * nSkillLevel;
|
|
|
|
// 화살 데미지 감소율: 미구현
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_DAMAGE_BY_TARGET_STATE:
|
|
case SkillBase::EF_AMP_DAMAGE_BY_TARGET_STATE:
|
|
{
|
|
m_vSkillRelatedToDamaging.push_back( pSkill );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_MODIFY_SKILL_COST:
|
|
// StructSkill 내부의 스킬 비용을 변경시키는 용도로 쓰는 변수를 통해 스킬 비용을 수정한다.
|
|
// CalculateStat에서 모든 스킬에 대해 CostModifier를 Reset한 뒤 여기에서 이를 재설정한다.
|
|
// 마음에 드는 방법은 아니나 지금과 같이 상태를 매 번 수동으로 업데이트하는 구조 위에서는 별 도리가 없다.
|
|
// 이 방법 아니면 매 번 스킬 시전할 때마다 StructCreature의 PassiveSkillList를 뒤져서 재계산해야 하는 것이다.
|
|
{
|
|
float HPInc = pSkill->GetVar( 0 ) + pSkill->GetVar( 1 ) * pSkill->GetCurrentSkillLevel();
|
|
float MPInc = pSkill->GetVar( 2 ) + pSkill->GetVar( 3 ) * pSkill->GetCurrentSkillLevel();
|
|
float HPAmp = pSkill->GetVar( 5 ) + pSkill->GetVar( 6 ) * pSkill->GetCurrentSkillLevel();
|
|
float MPAmp = pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel();
|
|
bool applyToAllSkill = ( pSkill->GetVar( 9 ) == 1 );
|
|
|
|
if ( applyToAllSkill == true )
|
|
{
|
|
m_SkillCostModifier.add( MPInc, MPAmp, HPInc, HPAmp );
|
|
}
|
|
else
|
|
{
|
|
for ( std::vector< StructSkill* >::iterator it = m_vAllSkillList.begin(); it != m_vAllSkillList.end(); ++it )
|
|
{
|
|
int skillID = (*it)->GetSkillId();
|
|
|
|
for ( int i = 10; i < 20; i++ )
|
|
{
|
|
if ( skillID == pSkill->GetVar( i ) )
|
|
{
|
|
(*it)->GetCostModifier().add( MPInc, MPAmp, HPInc, HPAmp );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_RESIST_HARMFUL_STATE:
|
|
{
|
|
for( int i = 0; i < 6; ++i )
|
|
{
|
|
StructState::StateCode code = static_cast< StructState::StateCode >( (int)pSkill->GetVar( i * 3 ) );
|
|
c_fixed10 rate = pSkill->GetVar( i * 3 + 1 ) + pSkill->GetVar( i * 3 + 2 ) * pSkill->GetCurrentSkillLevel();
|
|
|
|
if( !code ) continue;
|
|
|
|
std::map< StructState::StateCode, c_fixed10 >::iterator it = m_mapResistHarmfulState.find( code );
|
|
if( it == m_mapResistHarmfulState.end() )
|
|
{
|
|
m_mapResistHarmfulState.insert( std::make_pair< StructState::StateCode, c_fixed10 >( code, rate ) );
|
|
}
|
|
else
|
|
{
|
|
(*it).second += rate;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_DAMAGE_INC_CRIT_RATE_BY_TARGET_HP_RATIO:
|
|
case SkillBase::EF_AMP_DAMAGE_INC_CRIT_RATE_BY_TARGET_HP_RATIO:
|
|
{
|
|
m_vSkillRelatedToDamaging.push_back( pSkill );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_ABSORB_DAMAGE:
|
|
{
|
|
if( pSkill->GetVar(8) != ItemBase::CLASS_EVERY_WEAPON )
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( weapon_class != pSkill->GetVar(8) && weapon_class != pSkill->GetVar(9) &&
|
|
weapon_class != pSkill->GetVar(10) && weapon_class != pSkill->GetVar(11) )
|
|
break;
|
|
}
|
|
|
|
float fHPAbsorbRatio = pSkill->GetVar(0) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(1);
|
|
float fMPAbsorbRatio = pSkill->GetVar(2) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(3);
|
|
int nRatio = pSkill->GetVar(6) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(7);
|
|
int nAttackType = pSkill->GetVar(4);
|
|
|
|
if( !fHPAbsorbRatio && !fMPAbsorbRatio )
|
|
break;
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( nRatio, 0, 0, 0, 0, nAttackType, 99, NULL ) );
|
|
m_vProcByAttack.back().proc = new StructAbsorbProc( StructProc::ATTACKER, fHPAbsorbRatio, fMPAbsorbRatio );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_STEAL_HP_MP:
|
|
{
|
|
if( pSkill->GetVar(8) != ItemBase::CLASS_EVERY_WEAPON )
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( weapon_class != pSkill->GetVar(8) && weapon_class != pSkill->GetVar(9) &&
|
|
weapon_class != pSkill->GetVar(10) && weapon_class != pSkill->GetVar(11) )
|
|
break;
|
|
}
|
|
|
|
int nHPSteal = pSkill->GetVar(0) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(1);
|
|
int nMPSteal = pSkill->GetVar(2) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(3);
|
|
int nRatio = pSkill->GetVar(6) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(7);
|
|
int nAttackType = pSkill->GetVar(4);
|
|
|
|
if( !nHPSteal && !nMPSteal )
|
|
break;
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( nRatio, 0, 0, 0, 0, nAttackType, 99, NULL ) );
|
|
m_vProcByAttack.back().proc = new StructStealProc( StructProc::ATTACKER, nHPSteal, nMPSteal );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INCREASE_ENERGY_UNCONSUMPTION_RATE:
|
|
{
|
|
m_nEnergyUnconsumptionRate += pSkill->GetVar( 0 ) + pSkill->GetVar( 1 ) * pSkill->GetCurrentSkillLevel() + pSkill->GetVar( 2 ) * pSkill->GetEnhance();
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_PARAM_AMPLIFY_HEAL:
|
|
{
|
|
incParameter( pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
incParameter( pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
incParameter2( pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
incParameter2( pSkill->GetVar( 9 ), pSkill->GetVar( 10 ) + pSkill->GetVar( 11 ) * pSkill->GetCurrentSkillLevel() );
|
|
|
|
m_fHealRatio += pSkill->GetVar( 12 ) + pSkill->GetVar( 13 ) * pSkill->GetCurrentSkillLevel();
|
|
m_fMPHealRatio += pSkill->GetVar( 14 ) + pSkill->GetVar( 15 ) * pSkill->GetCurrentSkillLevel();
|
|
|
|
if( pSkill->GetVar( 16 ) != 0 ) // 아이템 적용
|
|
{
|
|
m_fHealRatioByItem += pSkill->GetVar( 12 ) + pSkill->GetVar( 13 ) * pSkill->GetCurrentSkillLevel();
|
|
m_fMPHealRatioByItem += pSkill->GetVar( 14 ) + pSkill->GetVar( 15 ) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
break;
|
|
}
|
|
|
|
case SkillBase::EF_INC_PARAM_BY_STATE:
|
|
{
|
|
bool exist = false;
|
|
for ( int i = 12; i < 20; i++ )
|
|
{
|
|
StructState::StateCode stateCode = (StructState::StateCode)(int) pSkill->GetVar( i );
|
|
|
|
if ( (int)stateCode == 0 )
|
|
{
|
|
break;
|
|
}
|
|
else if ( GetState( stateCode ) != NULL )
|
|
{
|
|
exist = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( exist == true )
|
|
{
|
|
incParameter( pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
incParameter( pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
incParameter2( pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
incParameter2( pSkill->GetVar( 9 ), pSkill->GetVar( 10 ) + pSkill->GetVar( 11 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case SkillBase::EF_AMP_PARAM_AMPLIFY_HEAL:
|
|
case SkillBase::EF_AMP_PARAM_BY_STATE:
|
|
{
|
|
m_vAmplifyPassiveSkillList.push_back( pSkill );
|
|
}
|
|
|
|
case SkillBase::EF_MISC:
|
|
{
|
|
switch( pSkill->GetSkillId() )
|
|
{
|
|
case StructSkill::SKILL_AMORY_UNIT:
|
|
{
|
|
m_vAmplifyPassiveSkillList.push_back( pSkill );
|
|
}
|
|
break;
|
|
|
|
// SKILL_ARMOR_MASTERY
|
|
case StructSkill::SKILL_INCREASE_ENERGY:
|
|
{
|
|
m_nMaxEnergy += pSkill->GetCurrentSkillLevel();
|
|
}
|
|
break;
|
|
case StructSkill::SKILL_ARMOR_MASTERY:
|
|
case StructSkill::SKILL_GAIA_ARMOR_MASTERY:
|
|
if( GetWearedItem( ItemBase::WEAR_ARMOR ) )
|
|
{
|
|
m_Attribute.fDefence += pSkill->GetVar(0) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
break;
|
|
|
|
case StructSkill::SKILL_LIFE_OF_DARKNESS:
|
|
{
|
|
m_Resist.nResist[ Elemental::TYPE_DARK ] += pSkill->GetVar(0) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void StructPlayer::applyPassiveSkillEffect( struct StructSkill * pSkill )
|
|
{
|
|
switch( pSkill->GetSkillBase()->GetSkillEffectType() )
|
|
{
|
|
case SkillBase::EF_INCREASE_SUMMON_HP_MP_SP:
|
|
{
|
|
m_ParameterForSummon.nMaxHP += pSkill->GetVar(0) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(1);
|
|
m_ParameterForSummon.nMaxMP += pSkill->GetVar(2) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(3);
|
|
m_ParameterForSummon.nMaxSP += pSkill->GetVar(4) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(5);
|
|
m_ParameterForSummon.Attribute.fHPRegenPoint += pSkill->GetVar(6) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(7);
|
|
m_ParameterForSummon.Attribute.fMPRegenPoint += pSkill->GetVar(8) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(9);
|
|
m_ParameterForSummon.nSPRegenAdd += pSkill->GetVar(10) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(11);
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_SUMMON_PARAM_BASED_PARAM:
|
|
{
|
|
c_fixed10 sum = CalcStatSum( pSkill->GetVar(12) ); // 스탯 증가 분은 스탯만 참조한다
|
|
c_fixed10 coefficient = pSkill->GetVar(1) + pSkill->GetVar(2) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(0), sum * coefficient, true, &m_ParameterForSummon );
|
|
|
|
sum += CalcAttributeSum( pSkill->GetVar(12), pSkill->GetVar(13) );
|
|
incParameter( pSkill->GetVar(0), sum * coefficient, false, &m_ParameterForSummon );
|
|
|
|
coefficient = pSkill->GetVar(4) + pSkill->GetVar(5) * pSkill->GetCurrentSkillLevel();
|
|
incParameter2( pSkill->GetVar(3), sum * coefficient, &m_ParameterForSummon );
|
|
|
|
sum = CalcStatSum( pSkill->GetVar(14) ); // 스탯 증가 분은 스탯만 참조한다
|
|
coefficient = pSkill->GetVar(7) + pSkill->GetVar(8) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(6), sum * coefficient, true, &m_ParameterForSummon );
|
|
|
|
sum += CalcAttributeSum( pSkill->GetVar(14), pSkill->GetVar(15) );
|
|
incParameter( pSkill->GetVar(6), sum * coefficient, false, &m_ParameterForSummon );
|
|
|
|
coefficient = pSkill->GetVar(10) + pSkill->GetVar(11) * pSkill->GetCurrentSkillLevel();
|
|
incParameter2( pSkill->GetVar(9), sum * coefficient, &m_ParameterForSummon );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_INC_SUMMON_PARAM_BASED_SUMMON_PARAM:
|
|
{
|
|
StructSummon *pSummon = GetMainSummon();
|
|
if( !pSummon )
|
|
break;
|
|
|
|
c_fixed10 sum = pSummon->CalcStatSum( pSkill->GetVar(12), pSummon->GetStatBeforeParamBasedCalc() ); // 스탯 증가 분은 스탯만 참조한다
|
|
c_fixed10 coefficient = pSkill->GetVar(1) + pSkill->GetVar(2) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(0), sum * coefficient, true, &m_ParameterForSummon );
|
|
|
|
sum += pSummon->CalcAttributeSum( pSkill->GetVar(12), pSkill->GetVar(13), pSummon->GetAttrBeforeParamBasedCalc() );
|
|
incParameter( pSkill->GetVar(0), sum * coefficient, false, &m_ParameterForSummon );
|
|
|
|
coefficient = pSkill->GetVar(4) + pSkill->GetVar(5) * pSkill->GetCurrentSkillLevel();
|
|
incParameter2( pSkill->GetVar(3), sum * coefficient, &m_ParameterForSummon );
|
|
|
|
sum = pSummon->CalcStatSum( pSkill->GetVar(14), pSummon->GetStatBeforeParamBasedCalc() ); // 스탯 증가 분은 스탯만 참조한다
|
|
coefficient = pSkill->GetVar(7) + pSkill->GetVar(8) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(6), sum * coefficient, true, &m_ParameterForSummon );
|
|
|
|
sum += pSummon->CalcAttributeSum( pSkill->GetVar(14), pSkill->GetVar(15), pSummon->GetAttrBeforeParamBasedCalc() );
|
|
incParameter( pSkill->GetVar(6), sum * coefficient, false, &m_ParameterForSummon );
|
|
|
|
coefficient = pSkill->GetVar(10) + pSkill->GetVar(11) * pSkill->GetCurrentSkillLevel();
|
|
incParameter2( pSkill->GetVar(9), sum * coefficient, &m_ParameterForSummon );
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_AMPLIFY_SUMMON_HP_MP_SP:
|
|
{
|
|
float fMaxHPInc = pSkill->GetVar(0) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(1);
|
|
float fMaxMPInc = pSkill->GetVar(2) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(3);
|
|
float fMaxSPInc = pSkill->GetVar(4) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(5);
|
|
float fHPRegenInc = pSkill->GetVar(6) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(7);
|
|
float fMPRegenInc = pSkill->GetVar(8) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(9);
|
|
float fSPRegenInc = pSkill->GetVar(10) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(11);
|
|
|
|
m_ParameterForSummon.fMaxHPAmplifier += fMaxHPInc;
|
|
m_ParameterForSummon.fMaxMPAmplifier += fMaxMPInc;
|
|
m_ParameterForSummon.fMaxSPAmplifier += fMaxSPInc;
|
|
m_ParameterForSummon.AttributeAmplifier.fHPRegenPoint += fHPRegenInc;
|
|
m_ParameterForSummon.AttributeAmplifier.fMPRegenPoint += fMPRegenInc;
|
|
m_ParameterForSummon.fSPRegenAddAmplifier += fSPRegenInc;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_AMPLIFY_EXP_FOR_SUMMON:
|
|
{
|
|
m_fActiveSummonExpAmp += pSkill->GetVar(0) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(1);
|
|
m_fDeactiveSummonExpAmp += pSkill->GetVar(2) + pSkill->GetCurrentSkillLevel() * pSkill->GetVar(3);
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_MISC:
|
|
{
|
|
if( pSkill->GetSkillId() == StructSkill::SKILL_TECHNICAL_CREATURE_CONTROL )
|
|
{
|
|
m_nDoubleSummonTime += pSkill->GetCurrentSkillLevel() * pSkill->GetVar(0) * 100;
|
|
break;
|
|
}
|
|
}
|
|
default:
|
|
StructCreature::applyPassiveSkillEffect( pSkill );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void StructCreature::applyPassiveSkillAmplifyEffect()
|
|
{
|
|
if( m_vAmplifyPassiveSkillList.empty() ) return;
|
|
|
|
std::vector< StructSkill *>::iterator it;
|
|
|
|
for( it = m_vAmplifyPassiveSkillList.begin(); it != m_vAmplifyPassiveSkillList.end(); ++it )
|
|
{
|
|
StructSkill * pSkill = (*it);
|
|
|
|
applyPassiveSkillAmplifyEffect( pSkill );
|
|
}
|
|
}
|
|
|
|
void StructSummon::applyPassiveSkillAmplifyEffect()
|
|
{
|
|
StructCreature::applyPassiveSkillAmplifyEffect();
|
|
|
|
m_fMaxHPAmplifier += m_ParameterForSummon.fMaxHPAmplifier;
|
|
m_fMaxMPAmplifier += m_ParameterForSummon.fMaxMPAmplifier;
|
|
m_fMaxSPAmplifier += m_ParameterForSummon.fMaxSPAmplifier;
|
|
m_AttributeAmplifier.fHPRegenPoint += m_ParameterForSummon.AttributeAmplifier.fHPRegenPoint;
|
|
m_AttributeAmplifier.fMPRegenPoint += m_ParameterForSummon.AttributeAmplifier.fMPRegenPoint;
|
|
m_fSPRegenAddAmplifier += m_ParameterForSummon.fSPRegenAddAmplifier;
|
|
}
|
|
|
|
void StructCreature::applyPassiveSkillAmplifyEffect( struct StructSkill * pSkill )
|
|
{
|
|
bool bFighterArmor = false;
|
|
bool bHunterArmor = false;
|
|
bool bMagicianArmor = false;
|
|
bool bSummonerArmor = false;
|
|
|
|
ItemBase::ItemClass armor_class = GetArmorClass();
|
|
|
|
if( armor_class == ItemBase::CLASS_FIGHTER_ARMOR ) bFighterArmor = true;
|
|
else if( armor_class == ItemBase::CLASS_HUNTER_ARMOR ) bHunterArmor = true;
|
|
else if( armor_class == ItemBase::CLASS_MAGICIAN_ARMOR ) bMagicianArmor = true;
|
|
else if( armor_class == ItemBase::CLASS_SUMMONER_ARMOR ) bSummonerArmor = true;
|
|
|
|
if( pSkill->GetSkillId() == StructSkill::SKILL_AMORY_UNIT && bFighterArmor )
|
|
{
|
|
m_AttributeAmplifier.fDefence += pSkill->GetVar( 0 );
|
|
}
|
|
|
|
switch( pSkill->GetSkillBase()->GetSkillEffectType() )
|
|
{
|
|
case SkillBase::EF_PARAMETER_AMP:
|
|
{
|
|
ampParameter( pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
ampParameter( pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
ampParameter2( pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
ampParameter2( pSkill->GetVar( 9 ), pSkill->GetVar( 10 ) + pSkill->GetVar( 11 ) * pSkill->GetCurrentSkillLevel() );
|
|
ampParameter( pSkill->GetVar( 12 ), pSkill->GetVar( 13 ) + pSkill->GetVar( 14 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
ampParameter( pSkill->GetVar( 15 ), pSkill->GetVar( 16 ) + pSkill->GetVar( 17 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
break;
|
|
}
|
|
case SkillBase::EF_AMPLIFY_HP_MP:
|
|
{
|
|
float fMaxHPInc = pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
float fMaxMPInc = pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
float fHPRegenInc = pSkill->GetVar(6) + pSkill->GetVar(7) * pSkill->GetCurrentSkillLevel();
|
|
float fMPRegenInc = pSkill->GetVar(8) + pSkill->GetVar(9) * pSkill->GetCurrentSkillLevel();
|
|
|
|
m_fMaxHPAmplifier += fMaxHPInc;
|
|
m_fMaxMPAmplifier += fMaxMPInc;
|
|
m_AttributeAmplifier.fHPRegenPercentage += fHPRegenInc;
|
|
m_AttributeAmplifier.fMPRegenPercentage += fMPRegenInc;
|
|
}
|
|
break;
|
|
|
|
case SkillBase::EF_AMP_PARAM_AMPLIFY_HEAL:
|
|
{
|
|
ampParameter( pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
ampParameter( pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
ampParameter2( pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
ampParameter2( pSkill->GetVar( 9 ), pSkill->GetVar( 10 ) + pSkill->GetVar( 11 ) * pSkill->GetCurrentSkillLevel() );
|
|
|
|
m_fHealRatio += pSkill->GetVar( 12 ) + pSkill->GetVar( 13 ) * pSkill->GetCurrentSkillLevel();
|
|
m_fMPHealRatio += pSkill->GetVar( 14 ) + pSkill->GetVar( 15 ) * pSkill->GetCurrentSkillLevel();
|
|
|
|
if( pSkill->GetVar( 16 ) != 0 ) // 아이템 적용
|
|
{
|
|
m_fHealRatioByItem += pSkill->GetVar( 12 ) + pSkill->GetVar( 13 ) * pSkill->GetCurrentSkillLevel();
|
|
m_fMPHealRatioByItem += pSkill->GetVar( 14 ) + pSkill->GetVar( 15 ) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
break;
|
|
}
|
|
case SkillBase::EF_AMP_PARAM_BY_STATE:
|
|
{
|
|
bool exist = false;
|
|
for ( int i = 12; i < 20; i++ )
|
|
{
|
|
StructState::StateCode stateCode = (StructState::StateCode)(int) pSkill->GetVar( i );
|
|
|
|
if ( (int)stateCode == 0 )
|
|
{
|
|
break;
|
|
}
|
|
if ( GetState( stateCode ) != NULL )
|
|
{
|
|
exist = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( exist == true )
|
|
{
|
|
ampParameter( pSkill->GetVar( 0 ), pSkill->GetVar( 1 ) + pSkill->GetVar( 2 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
ampParameter( pSkill->GetVar( 3 ), pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * pSkill->GetCurrentSkillLevel(), false );
|
|
ampParameter2( pSkill->GetVar( 6 ), pSkill->GetVar( 7 ) + pSkill->GetVar( 8 ) * pSkill->GetCurrentSkillLevel() );
|
|
ampParameter2( pSkill->GetVar( 9 ), pSkill->GetVar( 10 ) + pSkill->GetVar( 11 ) * pSkill->GetCurrentSkillLevel() );
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void StructCreature::calcParamBasedStat()
|
|
{
|
|
if( m_vPassiveSkillList.empty() ) return;
|
|
|
|
std::vector< StructSkill *>::iterator it;
|
|
|
|
for( it = m_vPassiveSkillList.begin(); it != m_vPassiveSkillList.end(); ++it )
|
|
{
|
|
StructSkill* pSkill = *it;
|
|
|
|
switch( pSkill->GetSkillBase()->GetSkillEffectType() )
|
|
{
|
|
case SkillBase::EF_INC_PARAM_BASED_SUMMON_PARAM:
|
|
{
|
|
// IsPlayer 등의 타입 파악 함수가 존재하는 시점에서 이미 DIP는 깨진 것이나 다름없다.
|
|
// 어차피 깨질대로 깨진 상속 구조에 DIP를 억지로 맞추기 위해 코드의 응집성을 낮추기보다는 당장은 구현에 집중하고
|
|
// 추후 리팩토링을 통해 관련 구현을 StructSkill쪽으로 넘기는 방향을 추구하는 것이 나아 보인다.
|
|
StructCreature* summon = IsPlayer() ? static_cast< StructPlayer* >( this )->GetMainSummon() : NULL;
|
|
if ( summon != NULL )
|
|
{
|
|
c_fixed10 sum = summon->CalcStatSum( pSkill->GetVar(12) );
|
|
c_fixed10 coefficient = pSkill->GetVar(1) + pSkill->GetVar(2) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(0), sum * coefficient, true );
|
|
|
|
sum = summon->CalcStatSum( pSkill->GetVar(14) );
|
|
coefficient = pSkill->GetVar(7) + pSkill->GetVar(8) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(6), sum * coefficient, true );
|
|
}
|
|
break;
|
|
}
|
|
case SkillBase::EF_INC_PARAM_BASED_PARAM:
|
|
{
|
|
c_fixed10 sum = CalcStatSum( pSkill->GetVar(12), m_StatBeforeParamBasedCalc ); // 스탯 증가 분은 스탯만 참조한다
|
|
c_fixed10 coefficient = pSkill->GetVar(1) + pSkill->GetVar(2) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(0), sum * coefficient, true );
|
|
|
|
sum = CalcStatSum( pSkill->GetVar(14), m_StatBeforeParamBasedCalc ); // 스탯 증가 분은 스탯만 참조한다
|
|
coefficient = pSkill->GetVar(7) + pSkill->GetVar(8) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(6), sum * coefficient, true );
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructSummon::calcParamBasedStat()
|
|
{
|
|
StructCreature::calcParamBasedStat();
|
|
|
|
m_Stat += m_ParameterForSummon.Stat;
|
|
}
|
|
|
|
void StructCreature::calcParamBasedAttribute()
|
|
{
|
|
// 스킬 하나가 파라메터에 기반하여 성능이 바뀌기 때문에 어쩔 수 없이 분리
|
|
// TODO: 차후 스탯 적용 시점과 아이템 효과 적용 시점을 분리할 때 이 함수도 합쳐 볼 방안을 찾아본다
|
|
|
|
if( m_vPassiveSkillList.empty() ) return;
|
|
|
|
std::vector< StructSkill *>::iterator it;
|
|
|
|
for( it = m_vPassiveSkillList.begin(); it != m_vPassiveSkillList.end(); ++it )
|
|
{
|
|
StructSkill* pSkill = *it;
|
|
|
|
switch( pSkill->GetSkillBase()->GetSkillEffectType() )
|
|
{
|
|
case SkillBase::EF_INC_PARAM_BASED_PARAM:
|
|
{
|
|
c_fixed10 sum = CalcStatSum( pSkill->GetVar(12), m_StatBeforeParamBasedCalc )
|
|
+ CalcAttributeSum( pSkill->GetVar(12), pSkill->GetVar(13), m_AttrBeforeParamBasedCalc );
|
|
|
|
c_fixed10 coefficient = pSkill->GetVar(1) + pSkill->GetVar(2) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(0), sum * coefficient, false );
|
|
|
|
coefficient = pSkill->GetVar(4) + pSkill->GetVar(5) * pSkill->GetCurrentSkillLevel();
|
|
incParameter2( pSkill->GetVar(3), sum * coefficient);
|
|
|
|
sum = CalcStatSum( pSkill->GetVar(14), m_StatBeforeParamBasedCalc )
|
|
+ CalcAttributeSum( pSkill->GetVar(14), pSkill->GetVar(15), m_AttrBeforeParamBasedCalc );
|
|
|
|
coefficient = pSkill->GetVar(7) + pSkill->GetVar(8) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(6), sum * coefficient, false );
|
|
|
|
coefficient = pSkill->GetVar(10) + pSkill->GetVar(11) * pSkill->GetCurrentSkillLevel();
|
|
incParameter2( pSkill->GetVar(9), sum * coefficient);
|
|
|
|
break;
|
|
}
|
|
case SkillBase::EF_INC_PARAM_BASED_SUMMON_PARAM:
|
|
{
|
|
// IsPlayer 등의 타입 파악 함수가 존재하는 시점에서 이미 DIP는 깨진 것이나 다름없다.
|
|
// 어차피 깨질대로 깨진 상속 구조에 DIP를 억지로 맞추기 위해 코드의 응집성을 낮추기보다는 당장은 구현에 집중하고
|
|
// 추후 리팩토링을 통해 관련 구현을 StructSkill쪽으로 넘기는 방향을 추구하는 것이 나아 보인다.
|
|
StructCreature* summon = IsPlayer() ? static_cast< StructPlayer* >( this )->GetMainSummon() : NULL;
|
|
if ( summon != NULL )
|
|
{
|
|
c_fixed10 sum = summon->CalcStatSum( pSkill->GetVar(12) )
|
|
+ summon->CalcAttributeSum( pSkill->GetVar(12), pSkill->GetVar(13) );
|
|
|
|
c_fixed10 coefficient = pSkill->GetVar(1) + pSkill->GetVar(2) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(0), sum * coefficient, false );
|
|
|
|
coefficient = pSkill->GetVar(4) + pSkill->GetVar(5) * pSkill->GetCurrentSkillLevel();
|
|
incParameter2( pSkill->GetVar(3), sum * coefficient);
|
|
|
|
sum = summon->CalcStatSum( pSkill->GetVar(14) )
|
|
+ summon->CalcAttributeSum( pSkill->GetVar(14), pSkill->GetVar(15) );
|
|
|
|
coefficient = pSkill->GetVar(7) + pSkill->GetVar(8) * pSkill->GetCurrentSkillLevel();
|
|
incParameter( pSkill->GetVar(6), sum * coefficient, false );
|
|
|
|
coefficient = pSkill->GetVar(10) + pSkill->GetVar(11) * pSkill->GetCurrentSkillLevel();
|
|
incParameter2( pSkill->GetVar(9), sum * coefficient);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructSummon::calcParamBasedAttribute()
|
|
{
|
|
StructCreature::calcParamBasedAttribute();
|
|
|
|
m_Attribute += m_ParameterForSummon.Attribute;
|
|
m_fAttackPointRightWithoutWeapon += m_ParameterForSummon.fAttackPointRightWithoutWeapon;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
m_Attribute.fAttackPointLeft += m_ParameterForSummon.Attribute.fAttackPointRight;
|
|
m_fAttackPointLeftWithoutWeapon += m_ParameterForSummon.Attribute.fAttackPointRight;
|
|
m_Attribute.fAttackSpeedLeft += m_ParameterForSummon.Attribute.fAttackSpeedRight;
|
|
m_Attribute.fAccuracyLeft += m_ParameterForSummon.Attribute.fAccuracyRight;
|
|
}
|
|
|
|
if( !isMoveSpeedFixed() )
|
|
{
|
|
m_Attribute.fMoveSpeed += m_ParameterForSummon.Attribute.fMoveSpeed;
|
|
}
|
|
|
|
if( IsUsingBow() || IsUsingCrossBow() )
|
|
// 사정거리 단위, 내부적으로는 기획 DB 에서 ATTACK_RANGE_UNIT 를 곱한 값으로 처리된다.
|
|
m_Attribute.fAttackRange += m_ParameterForSummon.Attribute.fAttackRange * GameRule::ATTACK_RANGE_UNIT;
|
|
|
|
m_Resist += m_ParameterForSummon.Resist;
|
|
}
|
|
|
|
// --- 스탯 및 능력치 연산에 관련된 지속 효과들 적용하는 루틴 ---
|
|
void StructCreature::applyStateEffect()
|
|
{
|
|
if( m_vStateList.empty() ) return;
|
|
|
|
std::vector< std::pair< int, int > > vDecreaseList;
|
|
|
|
STATE_ITERATOR it;
|
|
for( it = m_vStateList.begin(); it != m_vStateList.end(); ++it )
|
|
{
|
|
if( (*it).GetEffectType() == StructState::EF_DECREASE_STATE_EFFECT )
|
|
{
|
|
int nDecreaseLevel = (*it).GetValue(0) + (*it).GetValue(1) * (*it).GetLevel();
|
|
|
|
for( int i = 2 ; i < 11 && (*it).GetValue(i) ; ++i )
|
|
{
|
|
vDecreaseList.push_back( std::pair< int, int >( (int)(*it).GetValue(i), nDecreaseLevel ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
for( it = m_vStateList.begin(); it != m_vStateList.end(); ++it )
|
|
{
|
|
int nOriginalLevel = (*it).GetLevel();
|
|
|
|
for( std::vector< std::pair< int, int > >::iterator itDecrease = vDecreaseList.begin() ; itDecrease != vDecreaseList.end() ; ++itDecrease )
|
|
{
|
|
if( (*itDecrease).first == (*it).GetCode() )
|
|
{
|
|
int nLevel = nOriginalLevel - (*itDecrease).second;
|
|
if( nLevel < 0 )
|
|
{
|
|
(*itDecrease).second = -1 * nLevel;
|
|
nLevel = 0;
|
|
}
|
|
|
|
(*it).SetLevel( nLevel );
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( (*it).GetLevel() > 0 )
|
|
{
|
|
applyState( *it );
|
|
}
|
|
|
|
(*it).SetLevel( nOriginalLevel );
|
|
}
|
|
}
|
|
|
|
void StructCreature::applyState( StructState & state )
|
|
{
|
|
// _applyEffectForState 함수와 대부분 내용 중첩되므로 수정 사항 있으면 같이 수정할 것
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_PARAMETER_INC:
|
|
incParameter( state.GetValue( 0 ), state.GetValue( 1 ) + state.GetValue( 2 ) * state.GetLevel(), false );
|
|
incParameter( state.GetValue( 3 ), state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel(), false );
|
|
incParameter2( state.GetValue( 6 ), state.GetValue( 7 ) + state.GetValue( 8 ) * state.GetLevel() );
|
|
incParameter2( state.GetValue( 9 ), state.GetValue( 10 ) + state.GetValue( 11 ) * state.GetLevel() );
|
|
incParameter( state.GetValue( 12 ), state.GetValue( 13 ) + state.GetValue( 14 ) * state.GetLevel(), false );
|
|
incParameter( state.GetValue( 15 ), state.GetValue( 16 ) + state.GetValue( 17 ) * state.GetLevel(), false );
|
|
|
|
break;
|
|
case StructState::EF_PARAMETER_INC_WHEN_EQUIP_SHIELD:
|
|
if( IsWearShield() )
|
|
{
|
|
incParameter( state.GetValue( 0 ), state.GetValue( 1 ) + state.GetValue( 2 ) * state.GetLevel(), false );
|
|
incParameter( state.GetValue( 3 ), state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel(), false );
|
|
incParameter2( state.GetValue( 6 ), state.GetValue( 7 ) + state.GetValue( 8 ) * state.GetLevel() );
|
|
incParameter2( state.GetValue( 9 ), state.GetValue( 10 ) + state.GetValue( 11 ) * state.GetLevel() );
|
|
}
|
|
|
|
break;
|
|
|
|
case StructState::EF_PARAMETER_AMP_WHEN_EQUIP_SHIELD:
|
|
if( IsWearShield() )
|
|
{
|
|
ampParameter( state.GetValue( 0 ), state.GetValue( 1 ) + state.GetValue( 2 ) * state.GetLevel(), false );
|
|
ampParameter( state.GetValue( 3 ), state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel(), false );
|
|
ampParameter2( state.GetValue( 6 ), state.GetValue( 7 ) + state.GetValue( 8 ) * state.GetLevel() );
|
|
ampParameter2( state.GetValue( 9 ), state.GetValue( 10 ) + state.GetValue( 11 ) * state.GetLevel() );
|
|
}
|
|
|
|
break;
|
|
case StructState::EF_PARAMETER_INC_WHEN_EQUIP:
|
|
case StructState::EF_PARAMETER_AMP_WHEN_EQUIP:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
DWORD nWeaponBitFlag = 0;
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
switch( weapon_class )
|
|
{
|
|
case ItemBase::CLASS_ONEHAND_SWORD: nWeaponBitFlag = StructState::FLAG_EQUIP_ONEHAND_SWORD; break;
|
|
case ItemBase::CLASS_TWOHAND_SWORD: nWeaponBitFlag = StructState::FLAG_EQUIP_TWOHAND_SWORD; break;
|
|
case ItemBase::CLASS_DAGGER: nWeaponBitFlag = StructState::FLAG_EQUIP_DAGGER; break;
|
|
case ItemBase::CLASS_TWOHAND_SPEAR: nWeaponBitFlag = StructState::FLAG_EQUIP_TWOHAND_SPEAR; break;
|
|
case ItemBase::CLASS_TWOHAND_AXE: nWeaponBitFlag = StructState::FLAG_EQUIP_TWOHAND_AXE; break;
|
|
case ItemBase::CLASS_ONEHAND_MACE: nWeaponBitFlag = StructState::FLAG_EQUIP_ONEHAND_MACE; break;
|
|
case ItemBase::CLASS_TWOHAND_MACE: nWeaponBitFlag = StructState::FLAG_EQUIP_TWOHAND_MACE; break;
|
|
case ItemBase::CLASS_HEAVY_BOW: nWeaponBitFlag = StructState::FLAG_EQUIP_HEAVY_BOW; break;
|
|
case ItemBase::CLASS_LIGHT_BOW: nWeaponBitFlag = StructState::FLAG_EQUIP_LIGHT_BOW; break;
|
|
case ItemBase::CLASS_CROSSBOW: nWeaponBitFlag = StructState::FLAG_EQUIP_CROSSBOW; break;
|
|
<<<<<<< HEAD
|
|
=======
|
|
|
|
//Azia Mafia Double Arba
|
|
//case ItemBase::CLASS_DOUBLE_CROSSBOW: nWeaponBitFlag = StructState::FLAG_EQUIP_DOUBLE_CROSSBOW; break;
|
|
|
|
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
|
|
case ItemBase::CLASS_ONEHAND_STAFF: nWeaponBitFlag = StructState::FLAG_EQUIP_ONEHAND_STAFF; break;
|
|
case ItemBase::CLASS_TWOHAND_STAFF: nWeaponBitFlag = StructState::FLAG_EQUIP_TWOHAND_STAFF; break;
|
|
case ItemBase::CLASS_DOUBLE_SWORD: nWeaponBitFlag = StructState::FLAG_EQUIP_DOUBLE_SWORD; break;
|
|
case ItemBase::CLASS_DOUBLE_DAGGER: nWeaponBitFlag = StructState::FLAG_EQUIP_DOUBLE_DAGGER; break;
|
|
}
|
|
|
|
if( !( ((DWORD)state.GetValue(0)) & nWeaponBitFlag ) )
|
|
break;
|
|
|
|
if( state.GetEffectType() == StructState::EF_PARAMETER_INC_WHEN_EQUIP )
|
|
{
|
|
incParameter( state.GetValue( 1 ), state.GetValue( 2 ) + state.GetLevel() * state.GetValue( 3 ), ( state.GetValue( 1 ) <= StructState::FLAG_LUK ) ? true : false );
|
|
incParameter( state.GetValue( 4 ), state.GetValue( 5 ) + state.GetLevel() * state.GetValue( 6 ), ( state.GetValue( 4 ) <= StructState::FLAG_LUK ) ? true : false );
|
|
incParameter2( state.GetValue( 7 ), state.GetValue( 8 ) + state.GetLevel() * state.GetValue( 9 ) );
|
|
}
|
|
else if( state.GetEffectType() == StructState::EF_PARAMETER_AMP_WHEN_EQUIP )
|
|
{
|
|
ampParameter( state.GetValue( 1 ), state.GetValue( 2 ) + state.GetLevel() * state.GetValue( 3 ), ( state.GetValue( 1 ) <= StructState::FLAG_LUK ) ? true : false );
|
|
ampParameter( state.GetValue( 4 ), state.GetValue( 5 ) + state.GetLevel() * state.GetValue( 6 ), ( state.GetValue( 4 ) <= StructState::FLAG_LUK ) ? true : false );
|
|
ampParameter2( state.GetValue( 7 ), state.GetValue( 8 ) + state.GetLevel() * state.GetValue( 9 ) );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_BLESS_OF_GODDESS:
|
|
{
|
|
int nLightDamage = state.GetValue( 16 );
|
|
int nDarkDamage = state.GetValue( 17 );
|
|
|
|
incParameter( state.GetValue( 0 ), state.GetValue( 1 ), false );
|
|
incParameter( state.GetValue( 2 ), state.GetValue( 3 ), false );
|
|
incParameter( state.GetValue( 4 ), state.GetValue( 5 ), false );
|
|
incParameter( state.GetValue( 6 ), state.GetValue( 7 ), false );
|
|
incParameter( state.GetValue( 8 ), state.GetValue( 9 ), false );
|
|
incParameter( state.GetValue( 10 ), state.GetValue( 11 ), false );
|
|
ampParameter( state.GetValue( 12 ), state.GetValue( 13 ), false );
|
|
|
|
incParameter2( StructState::FLAG_ET_LIGHT_ADDITIONAL_DAMAGE, state.GetValue( 14 ) );
|
|
incParameter2( StructState::FLAG_ET_DARK_ADDITIONAL_DAMAGE, state.GetValue( 15 ) );
|
|
|
|
m_vMagicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_LIGHT, nLightDamage, 0 ) );
|
|
m_vPhysicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_LIGHT, nLightDamage, 0 ) );
|
|
m_vMagicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_DARK, nDarkDamage, 0 ) );
|
|
m_vPhysicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_DARK, nDarkDamage, 0 ) );
|
|
|
|
ampParameter( StructState::FLAG_DAMAGE_REDUCE, state.GetValue( 18 ), false );
|
|
incParameter( StructState::FLAG_STR | StructState::FLAG_VIT | StructState::FLAG_INT | StructState::FLAG_MEN, state.GetValue( 19 ), false );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DOUBLE_ATTACK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON )
|
|
{
|
|
if( weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
}
|
|
|
|
m_Attribute.fDoubleAttackRatio += state.GetValue(0) + state.GetLevel() * state.GetValue(1);
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADDITIONAL_DAMAGE_ON_ATTACK:
|
|
{
|
|
if( state.GetValue( 11 ) == 0 || state.GetValue( 11 ) == 99 )
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), Elemental::TYPE_NONE, (Elemental::Type) (int) state.GetValue( 8 ), state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel(), 0 ) );
|
|
if( state.GetValue( 11 ) == 1 || state.GetValue( 11 ) == 99 )
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), Elemental::TYPE_NONE, (Elemental::Type) (int) state.GetValue( 8 ), state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel(), 0 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_ADDITIONAL_DAMAGE_ON_ATTACK:
|
|
{
|
|
if( state.GetValue( 11 ) == 0 || state.GetValue( 11 ) == 99 )
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), Elemental::TYPE_NONE, (Elemental::Type) (int) state.GetValue( 8 ), 0, state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel() ) );
|
|
if( state.GetValue( 11 ) == 1 || state.GetValue( 11 ) == 99 )
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), Elemental::TYPE_NONE, (Elemental::Type) (int) state.GetValue( 8 ), 0, state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel() ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADDITIONAL_DAMAGE_ON_SKILL:
|
|
{
|
|
if( state.GetValue( 11 ) == 0 || state.GetValue( 11 ) == 99 )
|
|
m_vPhysicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), (Elemental::Type) (int) state.GetValue( 5 ), (Elemental::Type) (int) state.GetValue( 8 ), state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel(), 0 ) );
|
|
if( state.GetValue( 11 ) == 1 || state.GetValue( 11 ) == 99 )
|
|
m_vMagicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), (Elemental::Type) (int) state.GetValue( 5 ), (Elemental::Type) (int) state.GetValue( 8 ), state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel(), 0 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_ADDTIONAL_DAMAGE_ON_SKILL:
|
|
{
|
|
if( state.GetValue( 11 ) == 0 || state.GetValue( 11 ) == 99 )
|
|
m_vPhysicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), (Elemental::Type) (int) state.GetValue( 5 ), (Elemental::Type) (int) state.GetValue( 8 ), 0, state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel() ) );
|
|
if( state.GetValue( 11 ) == 1 || state.GetValue( 11 ) == 99 )
|
|
m_vMagicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), (Elemental::Type) (int) state.GetValue( 5 ), (Elemental::Type) (int) state.GetValue( 8 ), 0, state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel() ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_ATTACK_OLD:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), 0, 0, 0, 0, StructState::NormalAttack, 99, NULL ) );
|
|
m_vProcByAttack.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) state.GetValue( 0 ) ), state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel(), ( state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel() ) * 100, StructProc::ATTACKEE, 0 );
|
|
}
|
|
break;
|
|
|
|
// 코드량이 지나치게 많지만 가독성 때문에 우선 펼쳐둔다.
|
|
case StructState::EF_ADD_STATE_ON_ATTACK:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_ATTACK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_ATTACK: nTarget = StructProc::ATTACKEE; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_ATTACK: nTarget = StructProc::ATTACKER; break;
|
|
}
|
|
|
|
StructStateProc *pProc = new StructStateProc( static_cast< StructState::StateCode >( (int) state.GetValue( 0 ) ), state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel(), ( state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel() ) * 100, nTarget, state.GetValue( 13 ) );
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), state.GetValue( 14 ), state.GetValue( 15 ), state.GetValue( 16 ), state.GetValue( 17 ), state.GetValue( 12 ), state.GetValue( 18 ), pProc ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_BEING_ATTACKED:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BEING_ATTACKED:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_BEING_ATTACKED: nTarget = StructProc::ATTACKER; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BEING_ATTACKED: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByBeingAttacked.push_back( _ATTACK_TAG( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), state.GetValue( 14 ), state.GetValue( 15 ), state.GetValue( 16 ), state.GetValue( 17 ), state.GetValue( 12 ), state.GetValue( 18 ), NULL ) );
|
|
m_vProcByBeingAttacked.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) state.GetValue( 0 ) ), state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel(), ( state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel() ) * 100, nTarget, state.GetValue( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_LUNA_ONCE:
|
|
{
|
|
m_nLuna = 1;
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_DAMAGE_BASED_ATTACK_POINT:
|
|
{
|
|
c_fixed10 damage = 0;
|
|
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( state.GetValue( 14 ) != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != state.GetValue( 14 ) &&
|
|
weapon_class != state.GetValue( 15 ) &&
|
|
weapon_class != state.GetValue( 16 ) &&
|
|
weapon_class != state.GetValue( 17 ) )
|
|
break;
|
|
|
|
if ( state.GetValue( 4 ) == 0 || state.GetValue( 4 ) == 99 )
|
|
{
|
|
damage += GetAttackPointRight();
|
|
}
|
|
if ( state.GetValue( 4 ) == 1 || state.GetValue( 4 ) == 99 )
|
|
{
|
|
damage += GetMagicPoint();
|
|
}
|
|
|
|
damage *= state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel();
|
|
|
|
c_fixed10 procRate = state.GetValue( 5 ) + state.GetValue( 6 ) * state.GetLevel();
|
|
|
|
AdditionalDamageInfo additionalDamage( procRate, (Elemental::Type)99, (Elemental::Type)(int)state.GetValue( 7 ), damage, 0 );
|
|
|
|
if ( state.GetValue( 10 ) == 1 )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( additionalDamage );
|
|
}
|
|
if ( state.GetValue( 11 ) == 1 )
|
|
{
|
|
m_vRangeAdditionalDamage.push_back( additionalDamage );
|
|
}
|
|
if ( state.GetValue( 12 ) == 1 )
|
|
{
|
|
m_vPhysicalSkillAdditionalDamage.push_back( additionalDamage );
|
|
}
|
|
if ( state.GetValue( 13 ) == 1 )
|
|
{
|
|
m_vMagicalSkillAdditionalDamage.push_back( additionalDamage );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_KILL:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
|
|
m_vProcByKill.push_back( _KILL_TAG( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), state.GetValue( 14 ), state.GetValue( 15 ), 0, 0, state.GetValue( 18 ), state.GetValue( 19 ), NULL ) );
|
|
m_vProcByKill.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) state.GetValue( 0 ) ), state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel(), ( state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel() ) * 100, StructProc::ATTACKER, state.GetValue( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_DEAD:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
|
|
m_vProcByDead.push_back( _KILL_TAG( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), 0, 0, state.GetValue( 16 ), state.GetValue( 17 ), state.GetValue( 18 ), state.GetValue( 19 ), NULL ) );
|
|
m_vProcByDead.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) state.GetValue( 0 ) ), state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel(), ( state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel() ) * 100, StructProc::ATTACKEE, state.GetValue( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_CRITICAL_ATTACK:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_CRITICAL_ATTACK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_CRITICAL_ATTACK: nTarget = StructProc::ATTACKEE; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_CRITICAL_ATTACK: nTarget = StructProc::ATTACKER; break;
|
|
}
|
|
|
|
m_vProcByCriticalAttack.push_back( _ATTACK_TAG( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), state.GetValue( 14 ), state.GetValue( 15 ), state.GetValue( 16 ), state.GetValue( 17 ), state.GetValue( 12 ), state.GetValue( 18 ), NULL ) );
|
|
m_vProcByCriticalAttack.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) state.GetValue( 0 ) ), state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel(), ( state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel() ) * 100, nTarget, state.GetValue( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_BEING_CRITICAL_ATTACKED:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BEING_CRITICAL_ATTACKED:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_BEING_CRITICAL_ATTACKED: nTarget = StructProc::ATTACKER; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BEING_CRITICAL_ATTACKED: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByBeingCriticalAttacked.push_back( _ATTACK_TAG( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), state.GetValue( 14 ), state.GetValue( 15 ), state.GetValue( 16 ), state.GetValue( 17 ), state.GetValue( 12 ), state.GetValue( 18 ), NULL ) );
|
|
m_vProcByBeingCriticalAttacked.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) state.GetValue( 0 ) ), state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel(), ( state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel() ) * 100, nTarget, state.GetValue( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_AVOID:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_AVOID:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_AVOID: nTarget = StructProc::ATTACKER; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_AVOID: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByAvoid.push_back( _ATTACK_TAG( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), state.GetValue( 14 ), state.GetValue( 15 ), state.GetValue( 16 ), state.GetValue( 17 ), state.GetValue( 12 ), state.GetValue( 18 ), NULL ) );
|
|
m_vProcByAvoid.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) state.GetValue( 0 ) ), state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel(), ( state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel() ) * 100, nTarget, state.GetValue( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_BLOCK:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BLOCK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_BLOCK: nTarget = StructProc::ATTACKER; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BLOCK: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByBlock.push_back( _ATTACK_TAG( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), state.GetValue( 14 ), state.GetValue( 15 ), state.GetValue( 16 ), state.GetValue( 17 ), state.GetValue( 12 ), state.GetValue( 18 ), NULL ) );
|
|
m_vProcByBlock.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) state.GetValue( 0 ) ), state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel(), ( state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel() ) * 100, nTarget, state.GetValue( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_PERFECT_BLOCK:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_PERFECT_BLOCK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON && weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_PERFECT_BLOCK: nTarget = StructProc::ATTACKER; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_PERFECT_BLOCK: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByPerfectBlock.push_back( _ATTACK_TAG( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel(), state.GetValue( 14 ), state.GetValue( 15 ), state.GetValue( 16 ), state.GetValue( 17 ), state.GetValue( 12 ), state.GetValue( 18 ), NULL ) );
|
|
m_vProcByPerfectBlock.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) state.GetValue( 0 ) ), state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel(), ( state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel() ) * 100, nTarget, state.GetValue( 13 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_HP_ON_ATTACK:
|
|
{
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON )
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
}
|
|
|
|
int nHPInc = state.GetValue(0) + state.GetLevel() * state.GetValue(1);
|
|
int nMPInc = state.GetValue(2) + state.GetLevel() * state.GetValue(3);
|
|
int nRatio = state.GetValue(6) + state.GetLevel() * state.GetValue(7);
|
|
|
|
if( !nHPInc && !nMPInc )
|
|
break;
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( nRatio, 0, 0, 0, 0, StructState::NormalAttack, 99, NULL ) );
|
|
m_vProcByAttack.back().proc = new StructHealProc( StructProc::ATTACKER, nHPInc, nMPInc );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ABSORB:
|
|
{
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON )
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
}
|
|
|
|
float fHPAbsorbRatio = state.GetValue(0) + state.GetLevel() * state.GetValue(1);
|
|
float fMPAbsorbRatio = state.GetValue(2) + state.GetLevel() * state.GetValue(3);
|
|
int nRatio = state.GetValue(6) + state.GetLevel() * state.GetValue(7);
|
|
|
|
if( !fHPAbsorbRatio && !fMPAbsorbRatio )
|
|
break;
|
|
|
|
StructAbsorbProc *pProc = new StructAbsorbProc( StructProc::ATTACKER, fHPAbsorbRatio, fMPAbsorbRatio );
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( nRatio, 0, 0, 0, 0, StructState::NormalAttack, 99, pProc ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_STEAL:
|
|
case StructState::EF_STEAL_WITH_REGEN_STOP:
|
|
{
|
|
if( state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON )
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( weapon_class != state.GetValue( 8 ) && weapon_class != state.GetValue( 9 ) && weapon_class != state.GetValue( 10 ) && weapon_class != state.GetValue( 11 ) )
|
|
break;
|
|
}
|
|
|
|
int nHPSteal = state.GetValue(0) + state.GetLevel() * state.GetValue(1);
|
|
int nMPSteal = state.GetValue(2) + state.GetLevel() * state.GetValue(3);
|
|
int nRatio = state.GetValue(6) + state.GetLevel() * state.GetValue(7);
|
|
|
|
if( !nHPSteal && !nMPSteal )
|
|
break;
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( nRatio, 0, 0, 0, 0, StructState::NormalAttack, 99, NULL ) );
|
|
m_vProcByAttack.back().proc = new StructStealProc( StructProc::ATTACKER, nHPSteal, nMPSteal );
|
|
|
|
if( state.GetEffectType() == StructState::EF_STEAL_WITH_REGEN_STOP )
|
|
{
|
|
if( state.GetValue( 12 ) )
|
|
m_StatusFlag.On( STATUS_HP_REGEN_STOPPED );
|
|
if( state.GetValue( 13 ) )
|
|
m_StatusFlag.On( STATUS_MP_REGEN_STOPPED );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REFLECT_PERCENT:
|
|
{
|
|
m_vDamageReflectInfo.push_back( DamageReflectInfo( state.GetValue( 6 ) + state.GetLevel() * state.GetValue( 7 ), state.GetValue( 9 ) * GameRule::DEFAULT_UNIT_SIZE,
|
|
(Elemental::Type) (int) state.GetValue( 8 ), 0,
|
|
state.GetValue( 0 ) + state.GetLevel() * state.GetValue( 1 ),
|
|
state.GetValue( 2 ) + state.GetLevel() * state.GetValue( 3 ),
|
|
state.GetValue( 4 ) + state.GetLevel() * state.GetValue( 5 ),
|
|
state.GetValue( 10 ) ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REFLECT:
|
|
{
|
|
m_vDamageReflectInfo.push_back( DamageReflectInfo( state.GetValue( 6 ) + state.GetLevel() * state.GetValue( 7 ), GameRule::REFLECT_RANGE,
|
|
(Elemental::Type) (int) state.GetValue( 8 ), state.GetValue( 0 ) + state.GetLevel() * state.GetValue( 1 ),
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
state.GetValue( 9 ) ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REFLECT_WHEN_EQUIP_SHIELD:
|
|
{
|
|
if( IsWearShield() )
|
|
{
|
|
m_vStateReflectInfo.push_back( StateReflectInfo( static_cast< StructState::StateCode >( (int)state.GetValue( 0 ) ), state.GetValue( 3 ) + state.GetLevel() * state.GetValue( 4 ), state.GetValue( 1 ) + state.GetLevel() * state.GetValue( 2 ) ) );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_REGEN_ADD:
|
|
{
|
|
m_Attribute.fHPRegenPoint += state.GetValue(0) + state.GetLevel() * state.GetValue(1);
|
|
m_Attribute.fMPRegenPoint += state.GetValue(2) + state.GetLevel() * state.GetValue(3);
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_RECEIVE_DAMAGE:
|
|
{
|
|
// ApplyType(근거리/원거리 설정)은 일반 공격만 적용된다
|
|
int nApplyType = state.GetValue( 0 );
|
|
if( nApplyType == 1 )
|
|
{
|
|
m_NormalStatePenalty.fDamage += ( state.GetValue(7) + state.GetLevel() * state.GetValue(8) );
|
|
}
|
|
else if( nApplyType == 2 )
|
|
{
|
|
m_RangeStatePenalty.fDamage += ( state.GetValue(7) + state.GetLevel() * state.GetValue(8) );
|
|
}
|
|
else if( nApplyType == 99 )
|
|
{
|
|
m_NormalStatePenalty.fDamage += ( state.GetValue(7) + state.GetLevel() * state.GetValue(8) );
|
|
m_RangeStatePenalty.fDamage += ( state.GetValue(7) + state.GetLevel() * state.GetValue(8) );
|
|
}
|
|
|
|
m_StateStatePenalty.fDamage += ( state.GetValue(3) + state.GetLevel() * state.GetValue(4) );
|
|
m_PhysicalSkillStatePenalty.fDamage += ( state.GetValue(5) + state.GetLevel() * state.GetValue(6) );
|
|
m_MagicalSkillStatePenalty.fDamage += ( state.GetValue(9) + state.GetLevel() * state.GetValue(10) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_INC_HATE:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
break;
|
|
|
|
if( weapon_class != state.GetValue( 6 ) && state.GetValue( 6 ) != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != state.GetValue( 7 ) && state.GetValue( 7 ) != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != state.GetValue( 8 ) && state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != state.GetValue( 9 ) && state.GetValue( 9 ) != ItemBase::CLASS_EVERY_WEAPON )
|
|
break;
|
|
|
|
m_vHateMod.push_back( HateModifier( state.GetValue(10), state.GetValue(11), 0, state.GetValue(0) + state.GetValue(1) * state.GetLevel() ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_HATE:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
break;
|
|
|
|
if( weapon_class != state.GetValue( 6 ) && state.GetValue( 6 ) != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != state.GetValue( 7 ) && state.GetValue( 7 ) != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != state.GetValue( 8 ) && state.GetValue( 8 ) != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != state.GetValue( 9 ) && state.GetValue( 9 ) != ItemBase::CLASS_EVERY_WEAPON )
|
|
break;
|
|
|
|
m_vHateMod.push_back( HateModifier( state.GetValue(10), state.GetValue(11), state.GetValue(0) + state.GetValue(1) * state.GetLevel(), 0 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_FORCE_CHIP:
|
|
{
|
|
c_fixed10 fNormalStatePenalty = ( state.GetValue(0) + state.GetValue(1) * state.GetLevel() );
|
|
c_fixed10 fRangeStatePenalty = ( state.GetValue(0) + state.GetValue(1) * state.GetLevel() );
|
|
c_fixed10 fPhysicalSkillStatePenalty = ( state.GetValue(2) + state.GetValue(3) * state.GetLevel() );
|
|
|
|
if( IsPlayer() || IsSummon() )
|
|
{
|
|
fNormalStatePenalty = fNormalStatePenalty * 0.25f;
|
|
fRangeStatePenalty = fRangeStatePenalty * 0.25f;
|
|
fPhysicalSkillStatePenalty = fPhysicalSkillStatePenalty * 0.25f;
|
|
}
|
|
|
|
m_NormalStatePenalty.fDamage += fNormalStatePenalty;
|
|
m_RangeStatePenalty.fDamage += fRangeStatePenalty;
|
|
m_PhysicalSkillStatePenalty.fDamage += fPhysicalSkillStatePenalty;
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_SOUL_CHIP:
|
|
{
|
|
c_fixed10 fMagicalSkillStatePenalty = ( state.GetValue(2) + state.GetLevel() * state.GetValue(3) );
|
|
|
|
if( IsPlayer() || IsSummon() )
|
|
{
|
|
fMagicalSkillStatePenalty = fMagicalSkillStatePenalty * 0.25f;
|
|
}
|
|
|
|
m_MagicalSkillStatePenalty.fDamage += fMagicalSkillStatePenalty;
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_HEALING_CHIP:
|
|
{
|
|
m_fHealRatio += ( state.GetValue(2) + state.GetLevel() * state.GetValue(3) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_LUNAR_CHIP:
|
|
{
|
|
c_fixed10 fNormalStatePenalty = ( state.GetValue(0) + state.GetValue(1) * state.GetLevel() );
|
|
c_fixed10 fRangeStatePenalty = ( state.GetValue(0) + state.GetValue(1) * state.GetLevel() );
|
|
c_fixed10 fPhysicalSkillStatePenalty = ( state.GetValue(2) + state.GetValue(3) * state.GetLevel() );
|
|
c_fixed10 fMagicalSkillStatePenalty = ( state.GetValue(2) + state.GetValue(3) * state.GetLevel() );
|
|
c_fixed10 fStateStatePenalty = ( state.GetValue(12) + state.GetValue(13) * state.GetLevel() );
|
|
|
|
if( IsPlayer() || IsSummon() )
|
|
{
|
|
fNormalStatePenalty = fNormalStatePenalty * 0.25f;
|
|
fRangeStatePenalty = fRangeStatePenalty * 0.25f;
|
|
fPhysicalSkillStatePenalty = fPhysicalSkillStatePenalty * 0.25f;
|
|
fMagicalSkillStatePenalty = fMagicalSkillStatePenalty * 0.25f;
|
|
fStateStatePenalty = fStateStatePenalty * 0.25f;
|
|
}
|
|
|
|
m_NormalStatePenalty.fDamage += fNormalStatePenalty;
|
|
m_RangeStatePenalty.fDamage += fRangeStatePenalty;
|
|
m_PhysicalSkillStatePenalty.fDamage += fPhysicalSkillStatePenalty;
|
|
m_MagicalSkillStatePenalty.fDamage += fMagicalSkillStatePenalty;
|
|
m_StateStatePenalty.fDamage += fStateStatePenalty;
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_MP_COST_INC:
|
|
{
|
|
float fCostReduce = state.GetValue(0) + state.GetLevel() * state.GetValue(1);
|
|
int nElementalType = state.GetValue(5);
|
|
|
|
if( nElementalType != 99 )
|
|
{
|
|
if( state.GetValue( 10 ) == 99 || state.GetValue( 10 ) == 1 )
|
|
{
|
|
if( state.GetValue( 11 ) == 99 || state.GetValue( 11 ) == 0 )
|
|
{
|
|
m_GoodPhysicalElementalSkillStateMod[nElementalType].fManaCostRatio += fCostReduce;
|
|
}
|
|
|
|
if( state.GetValue( 11 ) == 99 || state.GetValue( 11 ) == 1 )
|
|
{
|
|
m_BadPhysicalElementalSkillStateMod[nElementalType].fManaCostRatio += fCostReduce;
|
|
}
|
|
}
|
|
|
|
if( state.GetValue( 10 ) == 99 || state.GetValue( 10 ) == 2 )
|
|
{
|
|
if( state.GetValue( 11 ) == 99 || state.GetValue( 11 ) == 0 )
|
|
{
|
|
m_GoodMagicalElementalSkillStateMod[nElementalType].fManaCostRatio += fCostReduce;
|
|
}
|
|
|
|
if( state.GetValue( 11 ) == 99 || state.GetValue( 11 ) == 1 )
|
|
{
|
|
m_BadMagicalElementalSkillStateMod[nElementalType].fManaCostRatio += fCostReduce;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( int i = 0; i < Elemental::TYPE_COUNT; ++i )
|
|
{
|
|
if( state.GetValue( 10 ) == 99 || state.GetValue( 10 ) == 1 )
|
|
{
|
|
if( state.GetValue( 11 ) == 99 || state.GetValue( 11 ) == 0 )
|
|
{
|
|
m_GoodPhysicalElementalSkillStateMod[i].fManaCostRatio += fCostReduce;
|
|
}
|
|
|
|
if( state.GetValue( 11 ) == 99 || state.GetValue( 11 ) == 1 )
|
|
{
|
|
m_BadPhysicalElementalSkillStateMod[i].fManaCostRatio += fCostReduce;
|
|
}
|
|
}
|
|
|
|
if( state.GetValue( 10 ) == 99 || state.GetValue( 10 ) == 2 )
|
|
{
|
|
if( state.GetValue( 11 ) == 99 || state.GetValue( 11 ) == 0 )
|
|
{
|
|
m_GoodMagicalElementalSkillStateMod[i].fManaCostRatio += fCostReduce;
|
|
}
|
|
|
|
if( state.GetValue( 11 ) == 99 || state.GetValue( 11 ) == 1 )
|
|
{
|
|
m_BadMagicalElementalSkillStateMod[i].fManaCostRatio += fCostReduce;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_PARAMETER_ON_NORMAL_ATTACK:
|
|
{
|
|
if( state.GetValue( 9 ) == 99 || state.GetValue( 9 ) == 1 )
|
|
{
|
|
m_RangeStateAdvantage.fDamage += state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel();
|
|
m_RangeStateAdvantage.fCritical += state.GetValue( 3 ) * state.GetLevel();
|
|
m_RangeStateAdvantage.nCritical += state.GetValue( 4 ) * state.GetLevel();
|
|
m_RangeStateAdvantage.fHate += state.GetValue( 5 ) + state.GetValue( 6 ) * state.GetLevel();
|
|
}
|
|
|
|
if( state.GetValue( 9 ) == 99 || state.GetValue( 9 ) == 0 )
|
|
{
|
|
m_NormalStateAdvantage.fDamage += state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel();
|
|
m_NormalStateAdvantage.fCritical += state.GetValue( 3 ) * state.GetLevel();
|
|
m_NormalStateAdvantage.nCritical += state.GetValue( 4 ) * state.GetLevel();
|
|
m_NormalStateAdvantage.fHate += state.GetValue( 6 ) * state.GetLevel();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_PARAMETER_ON_SKILL:
|
|
{
|
|
float fDamage = state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel();
|
|
float fMagicDamage = state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel();
|
|
int nCritical = state.GetValue( 4 ) * state.GetLevel();
|
|
int nElementalType = state.GetValue( 5 );
|
|
float fHate = state.GetValue( 6 ) * state.GetLevel();
|
|
float fCoolTime = state.GetValue( 7 ) * state.GetLevel();
|
|
bool bExhaustive = state.GetValue( 8 );
|
|
int nApplySkillType = state.GetValue( 9 );
|
|
int nApplyToHarmful = state.GetValue( 10 );
|
|
AR_TIME nCastingSpeedApplyTime = state.GetValue( 11 ) * 100;
|
|
int fCastingSpeed = state.GetValue( 12 ) + state.GetValue( 13 ) * state.GetLevel();
|
|
|
|
if( nElementalType != 99 )
|
|
{
|
|
if( nApplySkillType == 1 || nApplySkillType == 99 )
|
|
{
|
|
if( nApplyToHarmful == 1 || nApplyToHarmful == 99 )
|
|
{
|
|
m_BadPhysicalElementalSkillStateMod[nElementalType].apply( fDamage, fMagicDamage, nCritical, fHate, fCoolTime, nCastingSpeedApplyTime, fCastingSpeed, bExhaustive, state.GetCode() );
|
|
}
|
|
if( nApplyToHarmful == 0 || nApplyToHarmful == 99 )
|
|
{
|
|
m_GoodPhysicalElementalSkillStateMod[nElementalType].apply( fDamage, fMagicDamage, nCritical, fHate, fCoolTime, nCastingSpeedApplyTime, fCastingSpeed, bExhaustive, state.GetCode() );
|
|
}
|
|
}
|
|
if( nApplySkillType == 2 || nApplySkillType == 99 )
|
|
{
|
|
if( nApplyToHarmful == 1 || nApplyToHarmful == 99 )
|
|
{
|
|
m_BadMagicalElementalSkillStateMod[nElementalType].apply( fDamage, fMagicDamage, nCritical, fHate, fCoolTime, nCastingSpeedApplyTime, fCastingSpeed, bExhaustive, state.GetCode() );
|
|
}
|
|
if( nApplyToHarmful == 0 || nApplyToHarmful == 99 )
|
|
{
|
|
m_GoodMagicalElementalSkillStateMod[nElementalType].apply( fDamage, fMagicDamage, nCritical, fHate, fCoolTime, nCastingSpeedApplyTime, fCastingSpeed, bExhaustive, state.GetCode() );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( int i = 0; i < Elemental::TYPE_COUNT; ++i )
|
|
{
|
|
if( nApplySkillType == 1 || nApplySkillType == 99 )
|
|
{
|
|
if( nApplyToHarmful == 1 || nApplyToHarmful == 99 )
|
|
{
|
|
m_BadPhysicalElementalSkillStateMod[i].apply( fDamage, fMagicDamage, nCritical, fHate, fCoolTime, nCastingSpeedApplyTime, fCastingSpeed, bExhaustive, state.GetCode() );
|
|
}
|
|
if( nApplyToHarmful == 0 || nApplyToHarmful == 99 )
|
|
{
|
|
m_GoodPhysicalElementalSkillStateMod[i].apply( fDamage, fMagicDamage, nCritical, fHate, fCoolTime, nCastingSpeedApplyTime, fCastingSpeed, bExhaustive, state.GetCode() );
|
|
}
|
|
|
|
}
|
|
if( nApplySkillType == 2 || nApplySkillType == 99 )
|
|
{
|
|
if( nApplyToHarmful == 1 || nApplyToHarmful == 99 )
|
|
{
|
|
m_BadMagicalElementalSkillStateMod[i].apply( fDamage, fMagicDamage, nCritical, fHate, fCoolTime, nCastingSpeedApplyTime, fCastingSpeed, bExhaustive, state.GetCode() );
|
|
}
|
|
if( nApplyToHarmful == 0 || nApplyToHarmful == 99 )
|
|
{
|
|
m_GoodMagicalElementalSkillStateMod[i].apply( fDamage, fMagicDamage, nCritical, fHate, fCoolTime, nCastingSpeedApplyTime, fCastingSpeed, bExhaustive, state.GetCode() );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
//조작 관련 상태 이상
|
|
case StructState::EF_MEZZ:
|
|
// 모든 조작 불가
|
|
if( state.GetValue(0) )
|
|
{
|
|
m_StatusFlag.Off( STATUS_MOVABLE );
|
|
m_StatusFlag.Off( STATUS_ATTACKABLE );
|
|
m_StatusFlag.Off( STATUS_SKILL_CASTABLE );
|
|
m_StatusFlag.Off( STATUS_MAGIC_CASTABLE );
|
|
m_StatusFlag.Off( STATUS_ITEM_USABLE );
|
|
}
|
|
|
|
// 이동 불가
|
|
if( state.GetValue(1) )
|
|
m_StatusFlag.Off( STATUS_MOVABLE );
|
|
|
|
// 공격 불가
|
|
if( state.GetValue(2) )
|
|
m_StatusFlag.Off( STATUS_ATTACKABLE );
|
|
|
|
// 물리 스킬 시전 불가
|
|
if( state.GetValue(3) )
|
|
m_StatusFlag.Off( STATUS_SKILL_CASTABLE );
|
|
|
|
// 마법 스킬 시전 불가
|
|
if( state.GetValue(4) )
|
|
m_StatusFlag.Off( STATUS_MAGIC_CASTABLE );
|
|
|
|
// 피격 불가
|
|
if( state.GetValue(5) )
|
|
m_StatusFlag.Off( STATUS_MORTAL );
|
|
|
|
// HP 감소
|
|
m_fMaxHPAmplifier -= state.GetValue(8) + state.GetValue(9) * state.GetLevel();
|
|
m_nMaxHP -= state.GetValue(6) + state.GetValue(7) * state.GetLevel();
|
|
|
|
// MP 감소
|
|
m_fMaxMPAmplifier -= state.GetValue(12) + state.GetValue(13) * state.GetLevel();
|
|
m_nMaxMP -= state.GetValue(10) + state.GetValue(11) * state.GetLevel();
|
|
|
|
break;
|
|
|
|
case StructState::EF_TRANSFORMATION:
|
|
// 이동 불가
|
|
if( state.GetValue(1) )
|
|
m_StatusFlag.Off( STATUS_MOVABLE );
|
|
|
|
// 일반 공격 불가
|
|
if( state.GetValue(2) )
|
|
m_StatusFlag.Off( STATUS_ATTACKABLE );
|
|
|
|
// (물리)스킬 사용 불가
|
|
if( state.GetValue(3) == 1 )
|
|
m_StatusFlag.Off( STATUS_SKILL_CASTABLE );
|
|
|
|
// 마법 사용 불가
|
|
if( state.GetValue(3) == 2 )
|
|
m_StatusFlag.Off( STATUS_MAGIC_CASTABLE );
|
|
|
|
// 마법/스킬 모두 사용 불가
|
|
if( state.GetValue(3) == 3 )
|
|
{
|
|
m_StatusFlag.Off( STATUS_SKILL_CASTABLE );
|
|
m_StatusFlag.Off( STATUS_MAGIC_CASTABLE );
|
|
}
|
|
|
|
// 피격 불가
|
|
if( state.GetValue(4) )
|
|
m_StatusFlag.Off( STATUS_MORTAL );
|
|
|
|
// 아이템 사용 불가
|
|
if( state.GetValue(5) )
|
|
m_StatusFlag.Off( STATUS_ITEM_USABLE );
|
|
|
|
incParameter2( state.GetValue(6), state.GetValue(7) + state.GetValue(8) * state.GetLevel() );
|
|
incParameter2( state.GetValue(9), state.GetValue(10) + state.GetValue(11) * state.GetLevel() );
|
|
|
|
break;
|
|
|
|
case StructState::EF_ADD_HP_MP_ON_CRITICAL:
|
|
m_vAddHPMPOnCritical.push_back( AddHPMPOnCriticalInfo( state.GetValue(0) + state.GetValue(1) * state.GetLevel(), state.GetValue(2) + state.GetValue(3) * state.GetLevel(), state.GetValue(4) + state.GetValue(5) * state.GetLevel() ) );
|
|
break;
|
|
|
|
case StructState::EF_HEALING_AMPLIFY:
|
|
{
|
|
c_fixed10 fHPHealRatio = state.GetValue(0) + state.GetValue(1) * state.GetLevel();
|
|
c_fixed10 fMPHealRatio = state.GetValue(2) + state.GetValue(3) * state.GetLevel();
|
|
|
|
m_fHealRatio += fHPHealRatio;
|
|
m_fMPHealRatio += fMPHealRatio;
|
|
|
|
m_nAdditionalHeal += state.GetValue(4) + state.GetValue(5) * state.GetLevel();
|
|
m_nAdditionalMPHeal += state.GetValue(6) + state.GetValue(7) * state.GetLevel();
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DETECT_HIDE:
|
|
m_fDetectHideRange += ( state.GetValue(0) + state.GetLevel() * state.GetValue(1) ) * GameRule::DEFAULT_UNIT_SIZE;
|
|
break;
|
|
|
|
case StructState::EF_SKILL_INTERRUPTION:
|
|
for( int i = 0 ; i < 12 && state.GetValue( i ) ; ++i )
|
|
m_vInterruptedSkill.push_back( state.GetValue( i ) );
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REDUCE_WITH_RACE_BY_PERCENT:
|
|
m_vDamageReducePercentInfo.push_back( DamageReduceInfo( state.GetValue(6), state.GetValue(0) + state.GetLevel() * state.GetValue(1), state.GetValue(2) + state.GetLevel() * state.GetValue(3),
|
|
state.GetValue(4) + state.GetLevel() * state.GetValue(5), state.GetValue(7), state.GetValue(8), state.GetValue(9), state.GetValue(10), state.GetValue(11) ) );
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REDUCE_WITH_RACE_BY_VALUE:
|
|
m_vDamageReduceValueInfo.push_back( DamageReduceInfo( state.GetValue(6), state.GetValue(0) + state.GetLevel() * state.GetValue(1), state.GetValue(2) + state.GetLevel() * state.GetValue(3),
|
|
state.GetValue(4) + state.GetLevel() * state.GetValue(5), state.GetValue(7), state.GetValue(8), state.GetValue(9), state.GetValue(10), state.GetValue(11) ) );
|
|
break;
|
|
|
|
case StructState::EF_MANA_SHIELD:
|
|
{
|
|
int nTargetType = state.GetValue(4);
|
|
if( nTargetType == 1 || nTargetType == 99 )
|
|
m_fPhysicalDamageManaShieldAbsorbRatio += state.GetValue(0) + state.GetLevel() * state.GetValue(1);
|
|
if( nTargetType == 2 || nTargetType == 99 )
|
|
m_fMagicalDamageManaShieldAbsorbRatio += state.GetValue(0) + state.GetLevel() * state.GetValue(1);
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_AND_INC_ITEM_CHANCE:
|
|
// nItemChance == 100 이면 아이템 드랍 체크시 해당 아이템의 드랍율이 2배로 적용됨(드랍율 % 증폭 개념 변수임)
|
|
// GetValue( 0 ) + GetValue( 1 ) * GetLevel() == 1.0 -> 2배 증폭(nItemChance = 100 이 되야 함)
|
|
// 정수 처리 특성상 결과값의 소수 2째 자리 미만은 전부 버려짐
|
|
m_Attribute.fItemChance += ( state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel() ) * 100;
|
|
m_fEXPMod += state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel();
|
|
break;
|
|
|
|
case StructState::EF_CHANGING_GROUP:
|
|
m_nChangingGroup = state.GetValue(0);
|
|
break;
|
|
|
|
case StructState::EF_HUNTING_TRAINING:
|
|
{
|
|
for( int i = 0; i < 3; i++ )
|
|
{
|
|
int nCreatureType = state.GetValue( i * 5 );
|
|
|
|
c_fixed10 fDamage = state.GetValue( i * 5 + 1 ) + state.GetValue( i * 5 + 2 ) * state.GetLevel();
|
|
c_fixed10 fAvoid = state.GetValue( i * 5 + 3 ) + state.GetValue( i * 5 + 4 ) * state.GetLevel();
|
|
|
|
if( nCreatureType == CREATURE_ALL )
|
|
{
|
|
for( int i = 0 ; i < MAX_CREATURE_TYPE_NUMBER ; ++i )
|
|
{
|
|
m_Expert[ i ].fDamage += fDamage;
|
|
m_Expert[ i ].fAvoid += fAvoid;
|
|
}
|
|
}
|
|
else if( nCreatureType >= 0 && nCreatureType < MAX_CREATURE_TYPE_NUMBER )
|
|
{
|
|
m_Expert[ nCreatureType ].fDamage += fDamage;
|
|
m_Expert[ nCreatureType ].fAvoid += fAvoid;
|
|
}
|
|
else
|
|
{
|
|
assert( 0 && "CREATURE DATA TYPE ERROR!" );
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_RESIST_HARMFUL_STATE:
|
|
{
|
|
for( int i = 0; i < 6; ++i )
|
|
{
|
|
StructState::StateCode code = static_cast< StructState::StateCode >( (int)state.GetValue( i * 3 ) );
|
|
c_fixed10 rate = state.GetValue( i * 3 + 1 ) + state.GetValue( i * 3 + 2 ) * state.GetLevel();
|
|
|
|
if( !code ) continue;
|
|
|
|
std::map< StructState::StateCode, c_fixed10 >::iterator it = m_mapResistHarmfulState.find( code );
|
|
if( it == m_mapResistHarmfulState.end() )
|
|
{
|
|
m_mapResistHarmfulState.insert( std::make_pair< StructState::StateCode, c_fixed10 >( code, rate ) );
|
|
}
|
|
else
|
|
{
|
|
(*it).second += rate;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_REDUCE_DAMAGE_ON_ATTACK:
|
|
{
|
|
if( state.GetValue( 7 ) == 0 || state.GetValue( 7 ) == 99 )
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( state.GetValue( 3 ) + state.GetValue( 4 ) * state.GetLevel(), Elemental::TYPE_NONE, (Elemental::Type) (int) state.GetValue( 5 ), state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel(), 0 ) );
|
|
if( state.GetValue( 7 ) == 1 || state.GetValue( 7 ) == 99 )
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( state.GetValue( 3 ) + state.GetValue( 4 ) * state.GetLevel(), Elemental::TYPE_NONE, (Elemental::Type) (int) state.GetValue( 5 ), state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel(), 0 ) );
|
|
m_vDamageReduceValueInfo.push_back( DamageReduceInfo( state.GetValue(15) + state.GetLevel() * state.GetValue(16), state.GetValue(9) + state.GetLevel() * state.GetValue(10), state.GetValue(11) + state.GetLevel() * state.GetValue(12),
|
|
state.GetValue(13) + state.GetLevel() * state.GetValue(14), state.GetValue(17), state.GetValue(18), state.GetValue(19), state.GetValue(19), state.GetValue(19) ) );
|
|
// TODO: 유형 체크에 20번 값을 중복하여 넣은 것은 뒤의 두 값은 사용되지 않기 때문. 동작에는 차이가 없을 것이나 차후 리뷰가 필요할 듯
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REDUCE_BY_PERCENT_AND_VALUE:
|
|
{
|
|
m_vDamageReducePercentInfo.push_back( DamageReduceInfo( state.GetValue(6), state.GetValue(0) + state.GetLevel() * state.GetValue(1), state.GetValue(2) + state.GetLevel() * state.GetValue(3),
|
|
state.GetValue(4) + state.GetLevel() * state.GetValue(5), state.GetValue(7), state.GetValue(8), state.GetValue(9), state.GetValue(9), state.GetValue(9) ) );
|
|
m_vDamageReduceValueInfo.push_back( DamageReduceInfo( state.GetValue(16), state.GetValue(10) + state.GetLevel() * state.GetValue(11), state.GetValue(12) + state.GetLevel() * state.GetValue(13),
|
|
state.GetValue(14) + state.GetLevel() * state.GetValue(15), state.GetValue(17), state.GetValue(18), state.GetValue(19), state.GetValue(19), state.GetValue(19) ) );
|
|
// TODO: 유형 체크에 20번 값을 중복하여 넣은 것은 뒤의 두 값은 사용되지 않기 때문. 동작에는 차이가 없을 것이나 차후 리뷰가 필요할 듯
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_INCREASE_ENERGY_UNCONSUMPTION_RATE:
|
|
{
|
|
m_nEnergyUnconsumptionRate += state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel();
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_MISC:
|
|
{
|
|
c_fixed10 fValue1 = state.GetValue(0) + state.GetValue(1) * state.GetLevel();
|
|
c_fixed10 fValue2 = state.GetValue(2) + state.GetValue(3) * state.GetLevel();
|
|
c_fixed10 fValue3 = state.GetValue(4) + state.GetValue(5) * state.GetLevel();
|
|
c_fixed10 fValue4 = state.GetValue(6) + state.GetValue(7) * state.GetLevel();
|
|
c_fixed10 fValue5 = state.GetValue(8) + state.GetValue(9) * state.GetLevel();
|
|
c_fixed10 fValue6 = state.GetValue(10) + state.GetValue(11) * state.GetLevel();
|
|
|
|
switch( state.GetCode() )
|
|
{
|
|
// 일단 메즈 스킬들
|
|
case StructState::NIGHTMARE:
|
|
m_Attribute.fMagicDefence += fValue1;
|
|
case StructState::STUN:
|
|
case StructState::SLEEP:
|
|
case StructState::ILLUSION:
|
|
case StructState::SEAL:
|
|
case StructState::SHINE_WALL:
|
|
case StructState::CARELESSNESS:
|
|
case StructState::FALL_FROM_SUMMON:
|
|
case StructState::DEMONIC_STUN:
|
|
case StructState::ANOMALY_STUN:
|
|
case StructState::ANOMALY_ILLUSION:
|
|
case StructState::SCELLE: //AziaMafia Fix scellé
|
|
|
|
case StructState::MONSTER_STUN:
|
|
m_StatusFlag.Off( STATUS_ATTACKABLE );
|
|
m_StatusFlag.Off( STATUS_SKILL_CASTABLE );
|
|
m_StatusFlag.Off( STATUS_MAGIC_CASTABLE );
|
|
m_StatusFlag.Off( STATUS_ITEM_USABLE );
|
|
m_StatusFlag.Off(STATUS_MOVABLE);
|
|
case StructState::HOLD:
|
|
case StructState::EARTH_RESTRICTION:
|
|
case StructState::FROZEN_SNARE:
|
|
case StructState::EARTH_TREMOR:
|
|
m_StatusFlag.Off( STATUS_MOVABLE );
|
|
break;
|
|
case StructState::ANOMALY_HOLD:
|
|
m_StatusFlag.Off( STATUS_ATTACKABLE );
|
|
m_StatusFlag.Off( STATUS_MOVABLE );
|
|
break;
|
|
case StructState::STONECURSE:
|
|
m_StatusFlag.Off( STATUS_MORTAL );
|
|
case StructState::STONECURSE_MORTAL:
|
|
m_StatusFlag.On( STATUS_HP_REGEN_STOPPED );
|
|
m_StatusFlag.On( STATUS_MP_REGEN_STOPPED );
|
|
case StructState::FROZEN:
|
|
case StructState::TOTAL_FROZEN:
|
|
case StructState::ANOMALY_FROZEN:
|
|
m_AttributeAmplifier.fDefence += fValue1;
|
|
m_AttributeAmplifier.fMagicDefence += fValue2;
|
|
m_StatusFlag.Off( STATUS_MOVABLE );
|
|
m_StatusFlag.Off( STATUS_ATTACKABLE );
|
|
m_StatusFlag.Off( STATUS_SKILL_CASTABLE );
|
|
m_StatusFlag.Off( STATUS_ITEM_USABLE );
|
|
case StructState::MUTE:
|
|
m_StatusFlag.Off( STATUS_MAGIC_CASTABLE );
|
|
break;
|
|
|
|
case StructState::FEAR:
|
|
case StructState::DRAGONIC_FEAR:
|
|
case StructState::ANOMALY_FEAR:
|
|
m_StatusFlag.Off( STATUS_MOVABLE );
|
|
m_StatusFlag.On( STATUS_FEARED );
|
|
break;
|
|
|
|
case StructState::PROTECTING_FORCE_OF_BEGINNING:
|
|
{
|
|
m_StatusFlag.Off( STATUS_MORTAL );
|
|
m_StatusFlag.Off( STATUS_ATTACKABLE );
|
|
|
|
std::set< int > allowedSkillSet;
|
|
allowedSkillSet.insert( 4001 );
|
|
allowedSkillSet.insert( 4002 );
|
|
m_vAllowedSkill.push_back( allowedSkillSet );
|
|
}
|
|
break;
|
|
|
|
// 아이템 드랍 확률 증가(2007-10-30 삭제 -> 지속효과 유형 201번으로 대체)
|
|
//case StructState::INC_ITEM_CHANCE:
|
|
// m_Attribute.fItemChance += fValue1;
|
|
// break;
|
|
|
|
case StructState::HUNTING_CREATURE_CARD:
|
|
m_fCreatureCardChance += fValue1;
|
|
break;
|
|
|
|
// 블럭챤스 증가
|
|
case StructState::INC_BLOCK_CHANCE:
|
|
m_Attribute.fBlockChance += fValue1;
|
|
break;
|
|
|
|
// 은신, 도망자의 기척<은신><데스매치 전용>
|
|
case StructState::HIDE:
|
|
case StructState::TRACE_OF_FUGITIVE:
|
|
m_StatusFlag.On( STATUS_HIDING );
|
|
m_StatusFlag.Off( STATUS_ATTACKABLE );
|
|
|
|
m_AttributeAmplifier.fMoveSpeed += fValue1;
|
|
break;
|
|
|
|
case StructState::FRENZY:
|
|
{
|
|
m_AttributeAmplifier.fAttackSpeedRight += fValue1;
|
|
if( IsUsingDoubleWeapon() )
|
|
m_AttributeAmplifier.fAttackSpeedLeft += fValue1;
|
|
|
|
// fRidingSpeed 수치가 생기면서 라이딩 중에도 기본 속도에 관여할 수 있게 변경 ( 2013-12-20 )
|
|
m_AttributeAmplifier.fMoveSpeed += fValue2;
|
|
m_Attribute.fCritical = 100;
|
|
|
|
break;
|
|
}
|
|
|
|
case StructState::BURNING_STYLE:
|
|
{
|
|
m_AttributeAmplifier.fAttackPointRight += fValue1;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
m_AttributeAmplifier.fAttackPointLeft += fValue1;
|
|
|
|
m_AttributeAmplifier.fCritical += fValue2;
|
|
m_AttributeAmplifier.fDefence += fValue3;
|
|
m_AttributeAmplifier.fAvoid += fValue4;
|
|
m_fHateRatio += fValue5;
|
|
|
|
break;
|
|
}
|
|
|
|
case StructState::DUSK_STYLE:
|
|
{
|
|
m_AttributeAmplifier.fAccuracyRight += fValue1;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
m_AttributeAmplifier.fAccuracyRight += fValue1;
|
|
|
|
m_AttributeAmplifier.fCastingSpeed += fValue2;
|
|
m_fMaxHPAmplifier += fValue3;
|
|
m_fHateRatio += fValue4;
|
|
|
|
break;
|
|
}
|
|
|
|
case StructState::AGILE_STYLE:
|
|
{
|
|
m_AttributeAmplifier.fMoveSpeed += fValue1;
|
|
m_AttributeAmplifier.fAvoid += fValue2;
|
|
//m_Attribute.fAvoid += fValue2;
|
|
m_AttributeAmplifier.fAttackPointRight += fValue3;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
m_AttributeAmplifier.fAttackPointLeft += fValue3;
|
|
|
|
break;
|
|
}
|
|
|
|
case StructState::LIGHTNING_FORCE_CONGESTION:
|
|
{
|
|
m_AttributeAmplifier.fAttackPointRight += fValue1;
|
|
m_fAttackPointRightWithoutWeapon *= fValue1; // 귀찮아서 나중에 증폭 안하고 그냥...;;
|
|
m_AttributeAmplifier.fAttackSpeedRight += fValue2;
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
m_AttributeAmplifier.fAttackPointLeft += fValue1;
|
|
m_fAttackPointLeftWithoutWeapon *= fValue1;
|
|
m_AttributeAmplifier.fAttackSpeedLeft += fValue2;
|
|
}
|
|
m_fResistHarmfulState += fValue3;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructPlayer::applyState( StructState & state )
|
|
{
|
|
if( state.GetEffectType() == StructState::EF_RIDING )
|
|
{
|
|
if( !isMoveSpeedFixed() )
|
|
{
|
|
m_Attribute.fRidingSpeed = state.GetValue( 0 );
|
|
|
|
bool bUseFasterMoveSpeed = state.GetValue( 8 );
|
|
m_bUseFasterSpeedInRiding = bUseFasterMoveSpeed;
|
|
}
|
|
|
|
m_nRidingStateCode = state.GetCode();
|
|
|
|
return;
|
|
}
|
|
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_CHANGING_FORM:
|
|
{
|
|
// 값 1과 2가 둘 다 0이면 자신의 본래 이속을 따름
|
|
if( state.GetValue( 0 ).get() || state.GetValue( 1 ).get() )
|
|
{
|
|
m_Attribute.fMoveSpeed = state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel();
|
|
m_StatusFlag.On( STATUS_MOVE_SPEED_FIXED );
|
|
}
|
|
|
|
m_StatusFlag.On( STATUS_FORM_CHANGED );
|
|
m_StatusFlag.Set( STATUS_SKILL_CASTABLE, state.GetValue( 2 ) );
|
|
m_StatusFlag.Set( STATUS_MAGIC_CASTABLE, state.GetValue( 2 ) );
|
|
m_bIsSummonable = state.GetValue( 3 );
|
|
m_nMaxHP *= 1 + ( state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel() );
|
|
m_nMaxMP *= 1 + ( state.GetValue( 6 ) + state.GetValue( 7 ) * state.GetLevel() );
|
|
break;
|
|
}
|
|
|
|
case StructState::EF_PARAMETER_INC_TO_ACTIVE_SUMMON:
|
|
incParameter( state.GetValue( 0 ), state.GetValue( 1 ) + state.GetValue( 2 ) * state.GetLevel(), true, &m_ParameterForSummon );
|
|
incParameter( state.GetValue( 0 ), state.GetValue( 1 ) + state.GetValue( 2 ) * state.GetLevel(), false, &m_ParameterForSummon );
|
|
incParameter( state.GetValue( 3 ), state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel(), true, &m_ParameterForSummon );
|
|
incParameter( state.GetValue( 3 ), state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel(), false, &m_ParameterForSummon );
|
|
incParameter2( state.GetValue( 6 ), state.GetValue( 7 ) + state.GetValue( 8 ) * state.GetLevel(), &m_ParameterForSummon );
|
|
incParameter2( state.GetValue( 9 ), state.GetValue( 10 ) + state.GetValue( 11 ) * state.GetLevel(), &m_ParameterForSummon );
|
|
incParameter( state.GetValue( 12 ), state.GetValue( 13 ) + state.GetValue( 14 ) * state.GetLevel(), true, &m_ParameterForSummon );
|
|
incParameter( state.GetValue( 12 ), state.GetValue( 13 ) + state.GetValue( 14 ) * state.GetLevel(), false, &m_ParameterForSummon );
|
|
incParameter( state.GetValue( 15 ), state.GetValue( 16 ) + state.GetValue( 17 ) * state.GetLevel(), true, &m_ParameterForSummon );
|
|
incParameter( state.GetValue( 15 ), state.GetValue( 16 ) + state.GetValue( 17 ) * state.GetLevel(), false, &m_ParameterForSummon );
|
|
break;
|
|
|
|
case StructState::EF_AMP_AND_INC_ITEM_CHANCE:
|
|
m_fActiveSummonExpAmp += state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel();
|
|
StructCreature::applyState( state );
|
|
break;
|
|
|
|
case StructState::EF_IMMORTALIZE:
|
|
{
|
|
if( m_nMinHP < state.GetValue( 0 ) )
|
|
m_nMinHP = state.GetValue( 0 );
|
|
if( m_fMinHP < state.GetValue( 1 ) )
|
|
m_fMinHP = state.GetValue( 1 );
|
|
|
|
break;
|
|
}
|
|
case StructState::EF_INFINITE_SUMMON_TIME:
|
|
{
|
|
m_bIsInfiniteSummonTime = true;
|
|
|
|
if( GetSubSummon() )
|
|
{
|
|
TS_SC_UNSUMMON_NOTICE msg;
|
|
|
|
msg.summon_handle = m_pSubSummon->GetHandle();
|
|
msg.unsummon_duration = 0;
|
|
|
|
PendMessage( this, &msg );
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case StructState::EF_MISC:
|
|
{
|
|
switch( state.GetCode() )
|
|
{
|
|
case StructState::STAMINA_SAVE:
|
|
m_bStaminaSave = true;
|
|
break;
|
|
|
|
case StructState::SUPER_SAVE_0:
|
|
if( GameRule::anSuperSaveLevelMinLimit[ 0 ] <= GetLevel() && GetLevel() <= GameRule::anSuperSaveLevelMaxLimit[ 0 ] )
|
|
m_bSuperSave = true;
|
|
break;
|
|
case StructState::SUPER_SAVE_1:
|
|
if( GameRule::anSuperSaveLevelMinLimit[ 1 ] <= GetLevel() && GetLevel() <= GameRule::anSuperSaveLevelMaxLimit[ 1 ] )
|
|
m_bSuperSave = true;
|
|
break;
|
|
case StructState::SUPER_SAVE_2:
|
|
if( GameRule::anSuperSaveLevelMinLimit[ 2 ] <= GetLevel() && GetLevel() <= GameRule::anSuperSaveLevelMaxLimit[ 2 ] )
|
|
m_bSuperSave = true;
|
|
break;
|
|
case StructState::SUPER_SAVE_3:
|
|
if( GameRule::anSuperSaveLevelMinLimit[ 3 ] <= GetLevel() && GetLevel() <= GameRule::anSuperSaveLevelMaxLimit[ 3 ] )
|
|
m_bSuperSave = true;
|
|
break;
|
|
case StructState::SUPER_SAVE_4:
|
|
if( GameRule::anSuperSaveLevelMinLimit[ 4 ] <= GetLevel() && GetLevel() <= GameRule::anSuperSaveLevelMaxLimit[ 4 ] )
|
|
m_bSuperSave = true;
|
|
break;
|
|
case StructState::SUPER_SAVE_5:
|
|
if( GameRule::anSuperSaveLevelMinLimit[ 5 ] <= GetLevel() && GetLevel() <= GameRule::anSuperSaveLevelMaxLimit[ 5 ] )
|
|
m_bSuperSave = true;
|
|
break;
|
|
case StructState::SUPER_SAVE_6:
|
|
if( GameRule::anSuperSaveLevelMinLimit[ 6 ] <= GetLevel() && GetLevel() <= GameRule::anSuperSaveLevelMaxLimit[ 6 ] )
|
|
m_bSuperSave = true;
|
|
break;
|
|
case StructState::SUPER_SAVE_7:
|
|
m_bSuperSave = true;
|
|
break;
|
|
|
|
case StructState::SUMMON_GROWING_CRACKER_WITHOUT_PENALTY:
|
|
m_eSummonStaminaSaveType = SUMMON_STAMINA_SAVE_WITHOUT_PENALTY;
|
|
break;
|
|
|
|
case StructState::SUMMON_GROWING_CRACKER_1X:
|
|
m_eSummonStaminaSaveType = SUMMON_STAMINA_SAVE_1X;
|
|
break;
|
|
|
|
case StructState::SUMMON_GROWING_CRACKER_2X:
|
|
m_eSummonStaminaSaveType = SUMMON_STAMINA_SAVE_2X;
|
|
break;
|
|
|
|
case StructState::SUMMON_GROWING_CRACKER_3X:
|
|
m_eSummonStaminaSaveType = SUMMON_STAMINA_SAVE_3X;
|
|
break;
|
|
|
|
case StructState::SUMMON_GROWING_CRACKER_4X:
|
|
m_eSummonStaminaSaveType = SUMMON_STAMINA_SAVE_4X;
|
|
break;
|
|
|
|
case StructState::PASS_DAMAGE:
|
|
m_fPassDamageRatio = state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel();
|
|
break;
|
|
|
|
case StructState::FUSION_WITH_SUMMON:
|
|
m_nMaxHP += m_nMaxHP * ( state.GetValue( 0 ) + state.GetValue( 1 ) * state.GetLevel() );
|
|
m_nMaxMP += m_nMaxMP * ( state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel() );
|
|
m_bIsSummonable = false;
|
|
break;
|
|
|
|
default:
|
|
StructCreature::applyState( state );
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
StructCreature::applyState( state );
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void StructMonster::applyState( StructState & state )
|
|
{
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_PROVOKE:
|
|
m_vHateModifierByState.push_back( _HATE_MODIFIER_TAG( state.GetCaster(), state.GetValue(0) + state.GetLevel() * state.GetValue(1) ) );
|
|
m_bNeedToFindEnemy = true;
|
|
break;
|
|
|
|
default:
|
|
StructCreature::applyState( state );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void StructSummon::applyState( StructState & state )
|
|
{
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_HEAL:
|
|
{
|
|
m_nSPAdd += state.GetValue(4) + state.GetLevel() * state.GetValue(5);
|
|
}
|
|
break;
|
|
case StructState::EF_REGEN_ADD:
|
|
{
|
|
m_nSPRegenAdd += state.GetValue(4) + state.GetLevel() * state.GetValue(5);
|
|
}
|
|
break;
|
|
case StructState::EF_HEAL_BY_ITEM:
|
|
{
|
|
m_nSPAdd += state.GetValue(4) + state.GetLevel() * state.GetValue(5);
|
|
}
|
|
break;
|
|
}
|
|
|
|
StructCreature::applyState( state );
|
|
}
|
|
|
|
void StructCreature::applyStateAmplifyEffect()
|
|
{
|
|
if( m_vStateList.empty() ) return;
|
|
|
|
std::vector< std::pair< int, int > > vDecreaseList;
|
|
|
|
STATE_ITERATOR it;
|
|
for( it = m_vStateList.begin(); it != m_vStateList.end(); ++it )
|
|
{
|
|
if( (*it).GetEffectType() == StructState::EF_DECREASE_STATE_EFFECT )
|
|
{
|
|
int nDecreaseLevel = (*it).GetValue(0) + (*it).GetValue(1) * (*it).GetLevel();
|
|
|
|
for( int i = 2 ; i < 11 && (*it).GetValue(i) ; ++i )
|
|
{
|
|
vDecreaseList.push_back( std::pair< int, int >( (int)(*it).GetValue(i), nDecreaseLevel ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
for( it = m_vStateList.begin(); it != m_vStateList.end(); ++it )
|
|
{
|
|
int nOriginalLevel = (*it).GetLevel();
|
|
|
|
for( std::vector< std::pair< int, int > >::iterator itDecrease = vDecreaseList.begin() ; itDecrease != vDecreaseList.end() ; ++itDecrease )
|
|
{
|
|
if( (*itDecrease).first == (*it).GetCode() )
|
|
{
|
|
int nLevel = nOriginalLevel - (*itDecrease).second;
|
|
if( nLevel < 0 )
|
|
{
|
|
(*itDecrease).second = -1 * nLevel;
|
|
nLevel = 0;
|
|
}
|
|
|
|
(*it).SetLevel( nLevel );
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( (*it).GetLevel() > 0 )
|
|
{
|
|
applyStateAmplify( *it );
|
|
}
|
|
|
|
(*it).SetLevel( nOriginalLevel );
|
|
}
|
|
}
|
|
|
|
void StructCreature::applyStateAmplify( StructState & state )
|
|
{
|
|
switch( state.GetEffectType() )
|
|
{
|
|
case StructState::EF_PARAMETER_AMP:
|
|
ampParameter( state.GetValue( 0 ), state.GetValue( 1 ) + state.GetValue( 2 ) * state.GetLevel(), false );
|
|
ampParameter( state.GetValue( 3 ), state.GetValue( 4 ) + state.GetValue( 5 ) * state.GetLevel(), false );
|
|
ampParameter2( state.GetValue( 6 ), state.GetValue( 7 ) + state.GetValue( 8 ) * state.GetLevel() );
|
|
ampParameter2( state.GetValue( 9 ), state.GetValue( 10 ) + state.GetValue( 11 ) * state.GetLevel() );
|
|
ampParameter( state.GetValue( 12 ), state.GetValue( 13 ) + state.GetValue( 14 ) * state.GetLevel(), false );
|
|
ampParameter( state.GetValue( 15 ), state.GetValue( 16 ) + state.GetValue( 17 ) * state.GetLevel(), false );
|
|
break;
|
|
|
|
case StructState::EF_MISC:
|
|
{
|
|
switch( state.GetCode() )
|
|
{
|
|
case StructState::SQUALL_OF_ARROW:
|
|
m_StatusFlag.Set( STATUS_MOVABLE, !state.GetValue( 1 ) );
|
|
|
|
if( GetWeaponClass() == state.GetValue(0) )
|
|
{
|
|
m_AttributeAmplifier.fAttackSpeedRight += ( state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel() );
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
m_AttributeAmplifier.fAttackSpeedLeft += ( state.GetValue( 2 ) + state.GetValue( 3 ) * state.GetLevel() );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructCreature::applyStatByState()
|
|
{
|
|
if( m_vStateList.empty() ) return;
|
|
|
|
std::vector< std::pair< int, int > > vDecreaseList;
|
|
|
|
STATE_ITERATOR it;
|
|
for( it = m_vStateList.begin(); it != m_vStateList.end(); ++it )
|
|
{
|
|
if( (*it).GetEffectType() == StructState::EF_DECREASE_STATE_EFFECT )
|
|
{
|
|
int nDecreaseLevel = (*it).GetValue(0) + (*it).GetValue(1) * (*it).GetLevel();
|
|
|
|
for( int i = 2 ; i < 11 && (*it).GetValue(i) ; ++i )
|
|
{
|
|
vDecreaseList.push_back( std::pair< int, int >( (int)(*it).GetValue(i), nDecreaseLevel ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
for( it = m_vStateList.begin(); it != m_vStateList.end(); ++it )
|
|
{
|
|
int nOriginalLevel = (*it).GetLevel();
|
|
|
|
for( std::vector< std::pair< int, int > >::iterator itDecrease = vDecreaseList.begin() ; itDecrease != vDecreaseList.end() ; ++itDecrease )
|
|
{
|
|
if( (*itDecrease).first == (*it).GetCode() )
|
|
{
|
|
int nLevel = nOriginalLevel - (*itDecrease).second;
|
|
if( nLevel < 0 )
|
|
{
|
|
(*itDecrease).second = -1 * nLevel;
|
|
nLevel = 0;
|
|
}
|
|
|
|
(*it).SetLevel( nLevel );
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( (*it).GetLevel() > 0 )
|
|
{
|
|
switch( (*it).GetEffectType() )
|
|
{
|
|
case StructState::EF_PARAMETER_INC:
|
|
{
|
|
incParameter( (*it).GetValue( 0 ), (*it).GetValue( 1 ) + (*it).GetValue( 2 ) * (*it).GetLevel(), true );
|
|
incParameter( (*it).GetValue( 3 ), (*it).GetValue( 4 ) + (*it).GetValue( 5 ) * (*it).GetLevel(), true );
|
|
incParameter( (*it).GetValue( 12 ), (*it).GetValue( 13 ) + (*it).GetValue( 14 ) * (*it).GetLevel(), true );
|
|
incParameter( (*it).GetValue( 15 ), (*it).GetValue( 16 ) + (*it).GetValue( 17 ) * (*it).GetLevel(), true );
|
|
}
|
|
break;
|
|
case StructState::EF_BLESS_OF_GODDESS:
|
|
{
|
|
incParameter( (*it).GetValue( 0 ), (*it).GetValue( 1 ), true );
|
|
incParameter( (*it).GetValue( 2 ), (*it).GetValue( 3 ), true );
|
|
incParameter( (*it).GetValue( 4 ), (*it).GetValue( 5 ), true );
|
|
incParameter( (*it).GetValue( 6 ), (*it).GetValue( 7 ), true );
|
|
incParameter( (*it).GetValue( 8 ), (*it).GetValue( 9 ), true );
|
|
incParameter( (*it).GetValue( 10 ), (*it).GetValue( 11 ), true );
|
|
ampParameter( (*it).GetValue( 12 ), (*it).GetValue( 13 ), true );
|
|
incParameter( StructState::FLAG_STR | StructState::FLAG_VIT | StructState::FLAG_INT | StructState::FLAG_MEN, (*it).GetValue( 19 ), true );
|
|
}
|
|
break;
|
|
case StructState::EF_PARAMETER_INC_WHEN_EQUIP_SHIELD:
|
|
if( IsWearShield() )
|
|
{
|
|
incParameter( (*it).GetValue( 0 ), (*it).GetValue( 1 ) + (*it).GetValue( 2 ) * (*it).GetLevel(), true );
|
|
incParameter( (*it).GetValue( 3 ), (*it).GetValue( 4 ) + (*it).GetValue( 5 ) * (*it).GetLevel(), true );
|
|
}
|
|
break;
|
|
case StructState::EF_ADD_SKILL:
|
|
{
|
|
addSkill( (*it).GetValue( 0 ), (*it).GetValue( 1 ) + (*it).GetValue( 2 ) * (*it).GetLevel(), (*it).GetValue( 18 ), false );
|
|
addSkill( (*it).GetValue( 3 ), (*it).GetValue( 4 ) + (*it).GetValue( 5 ) * (*it).GetLevel(), (*it).GetValue( 18 ), false );
|
|
addSkill( (*it).GetValue( 6 ), (*it).GetValue( 7 ) + (*it).GetValue( 8 ) * (*it).GetLevel(), (*it).GetValue( 18 ), false );
|
|
addSkill( (*it).GetValue( 9 ), (*it).GetValue( 10 ) + (*it).GetValue( 11 ) * (*it).GetLevel(), (*it).GetValue( 18 ), false );
|
|
addSkill( (*it).GetValue( 12 ), (*it).GetValue( 13 ) + (*it).GetValue( 14 ) * (*it).GetLevel(), (*it).GetValue( 18 ), false );
|
|
|
|
addSkill( (*it).GetValue( 15 ), (*it).GetValue( 16 ) + (*it).GetValue( 17 ) * (*it).GetLevel(), (*it).GetValue( 18 ), true );
|
|
}
|
|
break;
|
|
case StructState::EF_PARAMETER_SYNCHRONIZATION:
|
|
{
|
|
synchronizeParameter( (*it).GetValue( 0 ), (*it).GetValue( 1 ) + (*it).GetValue( 2 ) * (*it).GetLevel() );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
(*it).SetLevel( nOriginalLevel );
|
|
}
|
|
}
|
|
|
|
void StructPlayer::applyStatByState()
|
|
{
|
|
if( m_vStateList.empty() ) return;
|
|
|
|
StructCreature::applyStatByState();
|
|
|
|
std::vector< std::pair< int, int > > vDecreaseList;
|
|
|
|
STATE_ITERATOR it;
|
|
for( it = m_vStateList.begin(); it != m_vStateList.end(); ++it )
|
|
{
|
|
int nOriginalLevel = (*it).GetLevel();
|
|
|
|
for( std::vector< std::pair< int, int > >::iterator itDecrease = vDecreaseList.begin() ; itDecrease != vDecreaseList.end() ; ++itDecrease )
|
|
{
|
|
if( (*itDecrease).first == (*it).GetCode() )
|
|
{
|
|
int nLevel = nOriginalLevel - (*itDecrease).second;
|
|
if( nLevel < 0 )
|
|
{
|
|
(*itDecrease).second = -1 * nLevel;
|
|
nLevel = 0;
|
|
}
|
|
|
|
(*it).SetLevel( nLevel );
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( (*it).GetLevel() > 0 )
|
|
{
|
|
switch( (*it).GetEffectType() )
|
|
{
|
|
case StructState::EF_CREATURE_PARAMETER_AMP:
|
|
{
|
|
m_nDoubleSummonTime += (*it).GetLevel() * (*it).GetValue(4) * 100;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
(*it).SetLevel( nOriginalLevel );
|
|
}
|
|
}
|
|
|
|
void StructSummon::applyStatByState()
|
|
{
|
|
StructCreature::applyStatByState();
|
|
|
|
// 이하는 주인에게 부여된 소환수의 스텟에 영향 주는 지속효과 처리임
|
|
if( !GetMaster() )
|
|
return;
|
|
}
|
|
|
|
void StructCreature::amplifyStatByState()
|
|
{
|
|
if( m_vStateList.empty() ) return;
|
|
|
|
std::vector< std::pair< int, int > > vDecreaseList;
|
|
|
|
STATE_ITERATOR it;
|
|
for( it = m_vStateList.begin(); it != m_vStateList.end(); ++it )
|
|
{
|
|
if( (*it).GetEffectType() == StructState::EF_DECREASE_STATE_EFFECT )
|
|
{
|
|
int nDecreaseLevel = (*it).GetValue(0) + (*it).GetValue(1) * (*it).GetLevel();
|
|
|
|
for( int i = 2 ; i < 11 && (*it).GetValue(i) ; ++i )
|
|
{
|
|
vDecreaseList.push_back( std::pair< int, int >( (int)(*it).GetValue(i), nDecreaseLevel ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
for( it = m_vStateList.begin(); it != m_vStateList.end(); ++it )
|
|
{
|
|
int nOriginalLevel = (*it).GetLevel();
|
|
|
|
for( std::vector< std::pair< int, int > >::iterator itDecrease = vDecreaseList.begin() ; itDecrease != vDecreaseList.end() ; ++itDecrease )
|
|
{
|
|
if( (*itDecrease).first == (*it).GetCode() )
|
|
{
|
|
int nLevel = nOriginalLevel - (*itDecrease).second;
|
|
if( nLevel < 0 )
|
|
{
|
|
(*itDecrease).second = -1 * nLevel;
|
|
nLevel = 0;
|
|
}
|
|
|
|
(*it).SetLevel( nLevel );
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( (*it).GetLevel() > 0 )
|
|
{
|
|
switch( (*it).GetEffectType() )
|
|
{
|
|
case StructState::EF_PARAMETER_AMP:
|
|
{
|
|
ampParameter( (*it).GetValue( 0 ), (*it).GetValue( 1 ) + (*it).GetValue( 2 ) * (*it).GetLevel(), true );
|
|
ampParameter( (*it).GetValue( 3 ), (*it).GetValue( 4 ) + (*it).GetValue( 5 ) * (*it).GetLevel(), true );
|
|
ampParameter( (*it).GetValue( 12 ), (*it).GetValue( 13 ) + (*it).GetValue( 14 ) * (*it).GetLevel(), true );
|
|
ampParameter( (*it).GetValue( 15 ), (*it).GetValue( 16 ) + (*it).GetValue( 17 ) * (*it).GetLevel(), true );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
(*it).SetLevel( nOriginalLevel );
|
|
}
|
|
}
|
|
|
|
void StructCreature::applyParamBasedStateEffect()
|
|
{
|
|
// 지속 효과 하나가 파라메터에 기반하여 성능이 바뀌기 때문에 어쩔 수 없이 분리
|
|
// TODO: 차후 스탯 적용 시점과 아이템 효과 적용 시점을 분리할 때 이 함수도 합쳐 볼 방안을 찾아본다
|
|
if( m_vStateList.empty() ) return;
|
|
|
|
std::vector< std::pair< int, int > > vDecreaseList;
|
|
|
|
STATE_ITERATOR it;
|
|
for( it = m_vStateList.begin(); it != m_vStateList.end(); ++it )
|
|
{
|
|
if( it->GetEffectType() == StructState::EF_DECREASE_STATE_EFFECT )
|
|
{
|
|
int nDecreaseLevel = it->GetValue(0) + it->GetValue(1) * it->GetLevel();
|
|
|
|
for( int i = 2 ; i < 11 && it->GetValue(i) ; ++i )
|
|
{
|
|
vDecreaseList.push_back( std::pair< int, int >( (int)(*it).GetValue(i), nDecreaseLevel ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
for( it = m_vStateList.begin(); it != m_vStateList.end(); ++it )
|
|
{
|
|
int nOriginalLevel = it->GetLevel();
|
|
|
|
for( std::vector< std::pair< int, int > >::iterator itDecrease = vDecreaseList.begin() ; itDecrease != vDecreaseList.end() ; ++itDecrease )
|
|
{
|
|
if( itDecrease->first == it->GetCode() )
|
|
{
|
|
int nLevel = nOriginalLevel - itDecrease->second;
|
|
if( nLevel < 0 )
|
|
{
|
|
itDecrease->second = -1 * nLevel;
|
|
nLevel = 0;
|
|
}
|
|
|
|
it->SetLevel( nLevel );
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( it->GetLevel() > 0 )
|
|
{
|
|
switch( it->GetEffectType() )
|
|
{
|
|
case StructState::EF_INC_DOT_BASED_PARAM:
|
|
{
|
|
for ( int i = 0; i < 2; i++ )
|
|
{
|
|
int varIndex = i * 6;
|
|
int sumIndex = i * 2 + 12;
|
|
|
|
c_fixed10 sum = CalcStatSum( it->GetValue(sumIndex), m_StatBeforeParamBasedCalc )
|
|
+ CalcAttributeSum( it->GetValue(sumIndex), it->GetValue(sumIndex+1), m_AttrBeforeParamBasedCalc );
|
|
int type = it->GetValue(varIndex);
|
|
c_fixed10 adder = it->GetValue(varIndex+1) + it->GetValue(varIndex+2) * it->GetLevel();
|
|
c_fixed10 amplifier = it->GetValue(varIndex+3) + it->GetValue(varIndex+4) * it->GetLevel();
|
|
|
|
if ( type == 99 )
|
|
{
|
|
for ( int j = 0; j < Elemental::TYPE_COUNT; j++ )
|
|
{
|
|
m_ElementalStateDamageAdder[j] += sum * adder;
|
|
m_ElementalStateDamageAmplifier[j] += sum * amplifier;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_ElementalStateDamageAdder[type] += sum * adder;
|
|
m_ElementalStateDamageAmplifier[type] += sum * amplifier;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
it->SetLevel( nOriginalLevel );
|
|
}
|
|
}
|
|
|
|
|
|
// --- 스탯 및 능력치 연산에 관련된 아이템 효과를 적용하는 루틴 ---
|
|
void StructCreature::applyItemEffect()
|
|
{
|
|
int i, x;
|
|
|
|
// { 유니트 익스퍼트
|
|
StructSkill *pUnitExpert = NULL;
|
|
if( ( pUnitExpert = GetCurrentPassiveSkill( StructSkill::SKILL_UNIT_EXPERT_LV6 ) ) ) ;
|
|
else if( ( pUnitExpert = GetCurrentPassiveSkill( StructSkill::SKILL_UNIT_EXPERT_LV5 ) ) ) ;
|
|
else if( ( pUnitExpert = GetCurrentPassiveSkill( StructSkill::SKILL_UNIT_EXPERT_LV4 ) ) ) ;
|
|
else if( ( pUnitExpert = GetCurrentPassiveSkill( StructSkill::SKILL_UNIT_EXPERT_LV3 ) ) ) ;
|
|
else pUnitExpert = GetCurrentPassiveSkill( StructSkill::SKILL_UNIT_EXPERT_LV2 );
|
|
|
|
m_nUnitExpertLevel = 0;
|
|
if( pUnitExpert ) m_nUnitExpertLevel = GameRule::GetItemLevelLimitByRank( pUnitExpert->GetVar( 0 ) );
|
|
// }
|
|
|
|
for( i = 0; i < ItemBase::MAX_ITEM_WEAR; ++i )
|
|
{
|
|
if( !m_anWear[i] ) continue;
|
|
|
|
// 장착 불가는 효과 없음
|
|
if( !IsWearable( (ItemBase::ItemWearType)i, m_anWear[i] ) ) continue;
|
|
|
|
float fItemRatio = 1.0f;
|
|
|
|
// 유니트 익스퍼트로 입은 아이템.
|
|
if( m_anWear[i]->GetLevelLimit() > GetLevel() && m_anWear[i]->GetLevelLimit() <= m_nUnitExpertLevel ) fItemRatio = 0.4f;
|
|
|
|
const ItemBaseServer & base = m_anWear[i]->GetItemBase();
|
|
for( x = 0; x < ItemBase::MAX_OPTION_NUMBER; ++x )
|
|
{
|
|
if( !base.nBaseType[x] ) continue;
|
|
|
|
onItemWearEffect( m_anWear[i], true, base.nBaseType[x], base.fBaseVar1[x], base.fBaseVar2[x], fItemRatio );
|
|
}
|
|
|
|
for( x = 0; x < ItemBase::MAX_OPTION_NUMBER; ++x )
|
|
{
|
|
if( !base.nOptType[x] ) continue;
|
|
|
|
onItemWearEffect( m_anWear[i], false, base.nOptType[x], base.fOptVar1[x], base.fOptVar2[x], fItemRatio );
|
|
}
|
|
|
|
int nEnhance = m_anWear[i]->GetItemEnhance();
|
|
if( nEnhance >= 1 )
|
|
{
|
|
const std::vector< EnhanceEffectInfo * > * pvEffectList = base.pvEnhanceEffectList;
|
|
if( pvEffectList )
|
|
{
|
|
for( auto it = pvEffectList->begin() ; it != pvEffectList->end() ; ++it )
|
|
{
|
|
c_fixed10 fAddPoint = 0;
|
|
for( int iEnhance = 0 ; iEnhance < nEnhance ; ++iEnhance )
|
|
{
|
|
fAddPoint += (*it)->fValue[iEnhance];
|
|
}
|
|
|
|
onItemWearEffect( m_anWear[i], false, (*it)->nEnhanceEffectID, fAddPoint, 0, fItemRatio );
|
|
}
|
|
}
|
|
}
|
|
|
|
_applyEffect( m_anWear[ i ], base.pvEffectList, fItemRatio );
|
|
|
|
int nSocketCount = m_anWear[i]->GetMaxSocketCount();
|
|
for( x = 0 ; x < nSocketCount ; ++x )
|
|
{
|
|
ItemBase::ItemCode nSocketCode = m_anWear[i]->GetSocketCode( x );
|
|
|
|
if( !nSocketCode )
|
|
continue;
|
|
|
|
const ItemBaseServer & SocketBase = StructItem::GetItemBase( nSocketCode );
|
|
|
|
// 레벨 제한 적용 가능 검사
|
|
if( GetLevel() < SocketBase.nMinLevel || GetLevel() > SocketBase.nMaxLevel )
|
|
continue;
|
|
|
|
// 소켓 내구도 검사
|
|
if( !m_anWear[i]->GetCurrentEndurance() )
|
|
continue;
|
|
|
|
for( int k = 0; k < ItemBase::MAX_OPTION_NUMBER; ++k )
|
|
{
|
|
if( !SocketBase.nBaseType[k] ) continue;
|
|
|
|
onItemWearEffect( m_anWear[i], true, SocketBase.nBaseType[k], SocketBase.fBaseVar1[k], SocketBase.fBaseVar2[k], fItemRatio );
|
|
}
|
|
|
|
for( int k = 0; k < ItemBase::MAX_OPTION_NUMBER; ++k )
|
|
{
|
|
if( !SocketBase.nOptType[k] ) continue;
|
|
|
|
onItemWearEffect( m_anWear[i], false, SocketBase.nOptType[k], SocketBase.fOptVar1[k], SocketBase.fOptVar2[k], fItemRatio );
|
|
}
|
|
|
|
_applyEffect( m_anWear[ i ], SocketBase.pvEffectList, fItemRatio );
|
|
}
|
|
|
|
// 각성 여부 확인
|
|
if( m_anWear[i]->IsAwaken() )
|
|
{
|
|
for( int nCnt = 0 ; nCnt < ItemInstance::MAX_AWAKEN_NUMBER ; ++nCnt )
|
|
{
|
|
if( !m_anWear[i]->GetAwakenOptionType( nCnt ) )
|
|
break;
|
|
|
|
if( m_anWear[i]->GetAwakenOptionType( nCnt ) == ITEM_EFFECT_PASSIVE::APPLY_EFFECT )
|
|
{
|
|
_applyEffect( m_anWear[ i ], GameContent::GetEffectInfoVector( m_anWear[i]->GetAwakenOptionValue1( nCnt ) ), fItemRatio );
|
|
}
|
|
else
|
|
{
|
|
onItemWearEffect( m_anWear[i], false, m_anWear[i]->GetAwakenOptionType( nCnt ), m_anWear[i]->GetAwakenOptionValue1( nCnt ), m_anWear[i]->GetAwakenOptionValue2( nCnt ), fItemRatio );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
// 랜덤화 여부 확인
|
|
if( m_anWear[i]->IsIdentified() )
|
|
{
|
|
for( int nCnt = 0 ; nCnt < ItemInstance::MAX_RANDOM_OPTION_NUMBER ; ++nCnt )
|
|
{
|
|
if( !m_anWear[i]->GetIdentifiedOptionType( nCnt ) )
|
|
break;
|
|
|
|
if( m_anWear[i]->GetIdentifiedOptionType( nCnt ) == ITEM_EFFECT_PASSIVE::APPLY_EFFECT )
|
|
{
|
|
_applyEffect( m_anWear[ i ], GameContent::GetEffectInfoVector( m_anWear[i]->GetIdentifiedOptionValue1( nCnt ) ), fItemRatio );
|
|
}
|
|
else
|
|
{
|
|
onItemWearEffect( m_anWear[i], false, m_anWear[i]->GetIdentifiedOptionType( nCnt ), m_anWear[i]->GetIdentifiedOptionValue1( nCnt ), m_anWear[i]->GetIdentifiedOptionValue2( nCnt ), fItemRatio );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
for( std::vector< SetItemEffectInfo * >::const_iterator itSetItemEffectInfo = m_vSetItemEffect.begin() ; itSetItemEffectInfo != m_vSetItemEffect.end() ; ++itSetItemEffectInfo )
|
|
{
|
|
for( int nOptionIndex = 0 ; nOptionIndex < ItemBase::MAX_OPTION_NUMBER ; ++nOptionIndex )
|
|
{
|
|
if( !(*itSetItemEffectInfo)->nBaseType[nOptionIndex] ) continue;
|
|
|
|
onItemWearEffect( NULL, true, (*itSetItemEffectInfo)->nBaseType[nOptionIndex], (*itSetItemEffectInfo)->fBaseVar1[nOptionIndex], (*itSetItemEffectInfo)->fBaseVar2[nOptionIndex], 1.0f );
|
|
}
|
|
|
|
for( int nOptionIndex = 0 ; nOptionIndex < ItemBase::MAX_OPTION_NUMBER ; ++nOptionIndex )
|
|
{
|
|
if( !(*itSetItemEffectInfo)->nOptType[nOptionIndex] ) continue;
|
|
|
|
onItemWearEffect( NULL, false, (*itSetItemEffectInfo)->nOptType[nOptionIndex], (*itSetItemEffectInfo)->fOptVar1[nOptionIndex], (*itSetItemEffectInfo)->fOptVar2[nOptionIndex], 1.0f );
|
|
}
|
|
|
|
_applyEffect( NULL, (*itSetItemEffectInfo)->pvEffectList, 1.0f );
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void StructCreature::_applyEffect( struct StructItem * pItem, const std::vector< EffectInfo * > * pvEffectList, float fRatio )
|
|
{
|
|
if( !pvEffectList || pvEffectList->empty() )
|
|
return;
|
|
|
|
int nEnhance = ( pItem ) ? pItem->GetItemEnhance() : 0;
|
|
|
|
for( std::vector< EffectInfo * >::const_iterator it = pvEffectList->begin() ; it != pvEffectList->end() ; ++it )
|
|
{
|
|
EffectInfo * pEffect = (*it);
|
|
if( pEffect->nMinLevel && GetLevel() < pEffect->nMinLevel ) continue;
|
|
if( pEffect->nMaxLevel && GetLevel() > pEffect->nMaxLevel ) continue;
|
|
|
|
switch( pEffect->eType )
|
|
{
|
|
case EffectInfo::EFFECT_TYPE_BASIC:
|
|
if( pEffect->fValue[ 0 ] ) onItemWearEffect( pItem, true, pEffect->fValue[ 0 ], pEffect->fValue[ 1 ], pEffect->fValue[ 2 ], fRatio );
|
|
if( pEffect->fValue[ 3 ] ) onItemWearEffect( pItem, true, pEffect->fValue[ 3 ], pEffect->fValue[ 4 ], pEffect->fValue[ 5 ], fRatio );
|
|
if( pEffect->fValue[ 6 ] ) onItemWearEffect( pItem, true, pEffect->fValue[ 6 ], pEffect->fValue[ 7 ], pEffect->fValue[ 8 ], fRatio );
|
|
if( pEffect->fValue[ 9 ] ) onItemWearEffect( pItem, true, pEffect->fValue[ 9 ], pEffect->fValue[ 10 ], pEffect->fValue[ 11 ], fRatio );
|
|
break;
|
|
|
|
case EffectInfo::EFFECT_TYPE_OPTIONAL:
|
|
if( pEffect->fValue[ 0 ] ) onItemWearEffect( pItem, false, pEffect->fValue[ 0 ], pEffect->fValue[ 1 ], pEffect->fValue[ 2 ], fRatio );
|
|
if( pEffect->fValue[ 3 ] ) onItemWearEffect( pItem, false, pEffect->fValue[ 3 ], pEffect->fValue[ 4 ], pEffect->fValue[ 5 ], fRatio );
|
|
if( pEffect->fValue[ 6 ] ) onItemWearEffect( pItem, false, pEffect->fValue[ 6 ], pEffect->fValue[ 7 ], pEffect->fValue[ 8 ], fRatio );
|
|
if( pEffect->fValue[ 9 ] ) onItemWearEffect( pItem, false, pEffect->fValue[ 9 ], pEffect->fValue[ 10 ], pEffect->fValue[ 11 ], fRatio );
|
|
break;
|
|
|
|
case EffectInfo::EFFECT_TYPE_STATE:
|
|
_applyEffectForState( pEffect );
|
|
break;
|
|
|
|
case EffectInfo::EFFECT_TYPE_ENHANCE:
|
|
if( nEnhance >= 1 )
|
|
{
|
|
for( int nIndex = 0 ; nIndex < 2 ; ++nIndex )
|
|
{
|
|
if( !pEffect->fValue[ nIndex * 5 ] )
|
|
continue;
|
|
|
|
float fAddPoint = 0.0f;
|
|
|
|
if( nEnhance > 0 ) fAddPoint += std::min( nEnhance, 4 ) * pEffect->fValue[ nIndex + 1 ];
|
|
if( nEnhance > 4 ) fAddPoint += std::min( nEnhance - 4, 4 ) * pEffect->fValue[ nIndex + 2 ];
|
|
if( nEnhance > 8 ) fAddPoint += std::min( nEnhance - 8, 4 ) * pEffect->fValue[ nIndex + 3 ];
|
|
if( nEnhance > 12 ) fAddPoint += std::min( nEnhance - 12, 8 ) * pEffect->fValue[ nIndex + 4 ];
|
|
|
|
onItemWearEffect( pItem, false, pEffect->fValue[ nIndex ], (int)fAddPoint, 0, fRatio );
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
assert( 0 );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructCreature::_applyEffectForState( const EffectInfo * pEffect )
|
|
{
|
|
// applyState 함수와 대부분 내용 중첩되므로 수정 사항 있으면 같이 수정할 것
|
|
// 파라미터 증가/증폭 모두 한 번에 적용함(증폭은 어차피 모아서 마지막에 적용하므로 여기서 해도 별 상관 없으며, 애초에 아이템 적용으로 인한 증가/증폭은 한 번에 처리 됨)
|
|
switch( pEffect->nEffectID )
|
|
{
|
|
case StructState::EF_PARAMETER_INC:
|
|
incParameter( pEffect->fValue[ 0 ], pEffect->fValue[ 1 ] + pEffect->fValue[ 2 ] * pEffect->nEffectLevel, false );
|
|
incParameter( pEffect->fValue[ 3 ], pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel, false );
|
|
incParameter2( pEffect->fValue[ 6 ], pEffect->fValue[ 7 ] + pEffect->fValue[ 8 ] * pEffect->nEffectLevel );
|
|
incParameter2( pEffect->fValue[ 9 ], pEffect->fValue[ 10 ] + pEffect->fValue[ 11 ] * pEffect->nEffectLevel );
|
|
incParameter( pEffect->fValue[ 12 ], pEffect->fValue[ 13 ] + pEffect->fValue[ 14 ] * pEffect->nEffectLevel, false );
|
|
incParameter( pEffect->fValue[ 15 ], pEffect->fValue[ 16 ] + pEffect->fValue[ 17 ] * pEffect->nEffectLevel, false );
|
|
|
|
break;
|
|
case StructState::EF_PARAMETER_INC_WHEN_EQUIP_SHIELD:
|
|
if( IsWearShield() )
|
|
{
|
|
incParameter( pEffect->fValue[ 0 ], pEffect->fValue[ 1 ] + pEffect->fValue[ 2 ] * pEffect->nEffectLevel, false );
|
|
incParameter( pEffect->fValue[ 3 ], pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel, false );
|
|
incParameter2( pEffect->fValue[ 6 ], pEffect->fValue[ 7 ] + pEffect->fValue[ 8 ] * pEffect->nEffectLevel );
|
|
incParameter2( pEffect->fValue[ 9 ], pEffect->fValue[ 10 ] + pEffect->fValue[ 11 ] * pEffect->nEffectLevel );
|
|
}
|
|
|
|
break;
|
|
|
|
case StructState::EF_PARAMETER_AMP_WHEN_EQUIP_SHIELD:
|
|
if( IsWearShield() )
|
|
{
|
|
ampParameter( pEffect->fValue[ 0 ], pEffect->fValue[ 1 ] + pEffect->fValue[ 2 ] * pEffect->nEffectLevel, false );
|
|
ampParameter( pEffect->fValue[ 3 ], pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel, false );
|
|
ampParameter2( pEffect->fValue[ 6 ], pEffect->fValue[ 7 ] + pEffect->fValue[ 8 ] * pEffect->nEffectLevel );
|
|
ampParameter2( pEffect->fValue[ 9 ], pEffect->fValue[ 10 ] + pEffect->fValue[ 11 ] * pEffect->nEffectLevel );
|
|
}
|
|
|
|
break;
|
|
case StructState::EF_PARAMETER_INC_WHEN_EQUIP:
|
|
case StructState::EF_PARAMETER_AMP_WHEN_EQUIP:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
DWORD nWeaponBitFlag = 0;
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
switch( weapon_class )
|
|
{
|
|
case ItemBase::CLASS_ONEHAND_SWORD: nWeaponBitFlag = StructState::FLAG_EQUIP_ONEHAND_SWORD; break;
|
|
case ItemBase::CLASS_TWOHAND_SWORD: nWeaponBitFlag = StructState::FLAG_EQUIP_TWOHAND_SWORD; break;
|
|
case ItemBase::CLASS_DAGGER: nWeaponBitFlag = StructState::FLAG_EQUIP_DAGGER; break;
|
|
case ItemBase::CLASS_TWOHAND_SPEAR: nWeaponBitFlag = StructState::FLAG_EQUIP_TWOHAND_SPEAR; break;
|
|
case ItemBase::CLASS_TWOHAND_AXE: nWeaponBitFlag = StructState::FLAG_EQUIP_TWOHAND_AXE; break;
|
|
case ItemBase::CLASS_ONEHAND_MACE: nWeaponBitFlag = StructState::FLAG_EQUIP_ONEHAND_MACE; break;
|
|
case ItemBase::CLASS_TWOHAND_MACE: nWeaponBitFlag = StructState::FLAG_EQUIP_TWOHAND_MACE; break;
|
|
case ItemBase::CLASS_HEAVY_BOW: nWeaponBitFlag = StructState::FLAG_EQUIP_HEAVY_BOW; break;
|
|
case ItemBase::CLASS_LIGHT_BOW: nWeaponBitFlag = StructState::FLAG_EQUIP_LIGHT_BOW; break;
|
|
case ItemBase::CLASS_CROSSBOW: nWeaponBitFlag = StructState::FLAG_EQUIP_CROSSBOW; break;
|
|
<<<<<<< HEAD
|
|
=======
|
|
|
|
// AziaMafia Double Arba
|
|
//case ItemBase::CLASS_DOUBLE_CROSSBOW: nWeaponBitFlag = StructState::FLAG_EQUIP_DOUBLE_CROSSBOW; break;
|
|
|
|
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
|
|
case ItemBase::CLASS_ONEHAND_STAFF: nWeaponBitFlag = StructState::FLAG_EQUIP_ONEHAND_STAFF; break;
|
|
case ItemBase::CLASS_TWOHAND_STAFF: nWeaponBitFlag = StructState::FLAG_EQUIP_TWOHAND_STAFF; break;
|
|
case ItemBase::CLASS_DOUBLE_SWORD: nWeaponBitFlag = StructState::FLAG_EQUIP_DOUBLE_SWORD; break;
|
|
case ItemBase::CLASS_DOUBLE_DAGGER: nWeaponBitFlag = StructState::FLAG_EQUIP_DOUBLE_DAGGER; break;
|
|
}
|
|
|
|
if( !( ((DWORD)pEffect->fValue[0]) & nWeaponBitFlag ) )
|
|
break;
|
|
|
|
if( pEffect->nEffectID == StructState::EF_PARAMETER_INC_WHEN_EQUIP )
|
|
{
|
|
incParameter( pEffect->fValue[ 1 ], pEffect->fValue[ 2 ] + pEffect->nEffectLevel * pEffect->fValue[ 3 ], ( pEffect->fValue[ 1 ] <= StructState::FLAG_LUK ) ? true : false );
|
|
incParameter( pEffect->fValue[ 4 ], pEffect->fValue[ 5 ] + pEffect->nEffectLevel * pEffect->fValue[ 6 ], ( pEffect->fValue[ 4 ] <= StructState::FLAG_LUK ) ? true : false );
|
|
incParameter2( pEffect->fValue[ 7 ], pEffect->fValue[ 8 ] + pEffect->nEffectLevel * pEffect->fValue[ 9 ] );
|
|
}
|
|
else if( pEffect->nEffectID == StructState::EF_PARAMETER_AMP_WHEN_EQUIP )
|
|
{
|
|
ampParameter( pEffect->fValue[ 1 ], pEffect->fValue[ 2 ] + pEffect->nEffectLevel * pEffect->fValue[ 3 ], ( pEffect->fValue[ 1 ] <= StructState::FLAG_LUK ) ? true : false );
|
|
ampParameter( pEffect->fValue[ 4 ], pEffect->fValue[ 5 ] + pEffect->nEffectLevel * pEffect->fValue[ 6 ], ( pEffect->fValue[ 4 ] <= StructState::FLAG_LUK ) ? true : false );
|
|
ampParameter2( pEffect->fValue[ 7 ], pEffect->fValue[ 8 ] + pEffect->nEffectLevel * pEffect->fValue[ 9 ] );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DOUBLE_ATTACK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON )
|
|
{
|
|
if( weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
}
|
|
|
|
m_Attribute.fDoubleAttackRatio += pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1];
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADDITIONAL_DAMAGE_ON_ATTACK:
|
|
{
|
|
if( pEffect->fValue[ 11 ] == 0 || pEffect->fValue[ 11 ] == 99 )
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, Elemental::TYPE_NONE, (Elemental::Type) (int) pEffect->fValue[ 8 ], pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel, 0 ) );
|
|
if( pEffect->fValue[ 11 ] == 1 || pEffect->fValue[ 11 ] == 99 )
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, Elemental::TYPE_NONE, (Elemental::Type) (int) pEffect->fValue[ 8 ], pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel, 0 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_ADDITIONAL_DAMAGE_ON_ATTACK:
|
|
{
|
|
if( pEffect->fValue[ 11 ] == 0 || pEffect->fValue[ 11 ] == 99 )
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, Elemental::TYPE_NONE, (Elemental::Type) (int) pEffect->fValue[ 8 ], 0, pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel ) );
|
|
if( pEffect->fValue[ 11 ] == 1 || pEffect->fValue[ 11 ] == 99 )
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, Elemental::TYPE_NONE, (Elemental::Type) (int) pEffect->fValue[ 8 ], 0, pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADDITIONAL_DAMAGE_ON_SKILL:
|
|
{
|
|
if( pEffect->fValue[ 11 ] == 0 || pEffect->fValue[ 11 ] == 99 )
|
|
m_vPhysicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, (Elemental::Type) (int) pEffect->fValue[ 5 ], (Elemental::Type) (int) pEffect->fValue[ 8 ], pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel, 0 ) );
|
|
if( pEffect->fValue[ 11 ] == 1 || pEffect->fValue[ 11 ] == 99 )
|
|
m_vMagicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, (Elemental::Type) (int) pEffect->fValue[ 5 ], (Elemental::Type) (int) pEffect->fValue[ 8 ], pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel, 0 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_ADDTIONAL_DAMAGE_ON_SKILL:
|
|
{
|
|
if( pEffect->fValue[ 11 ] == 0 || pEffect->fValue[ 11 ] == 99 )
|
|
m_vPhysicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, (Elemental::Type) (int) pEffect->fValue[ 5 ], (Elemental::Type) (int) pEffect->fValue[ 8 ], 0, pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel ) );
|
|
if( pEffect->fValue[ 11 ] == 1 || pEffect->fValue[ 11 ] == 99 )
|
|
m_vMagicalSkillAdditionalDamage.push_back( AdditionalDamageInfo( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, (Elemental::Type) (int) pEffect->fValue[ 5 ], (Elemental::Type) (int) pEffect->fValue[ 8 ], 0, pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_ATTACK_OLD:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, 0, 0, 0, 0, StructState::NormalAttack, 99, NULL ) );
|
|
m_vProcByAttack.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pEffect->fValue[ 0 ] ), pEffect->fValue[ 2 ] + pEffect->fValue[ 3 ] * pEffect->nEffectLevel, ( pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel ) * 100, StructProc::ATTACKEE, 0 );
|
|
}
|
|
break;
|
|
|
|
// 코드량이 지나치게 많지만 가독성 때문에 우선 펼쳐둔다.
|
|
case StructState::EF_ADD_STATE_ON_ATTACK:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_ATTACK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pEffect->nEffectID )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_ATTACK: nTarget = StructProc::ATTACKEE; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_ATTACK: nTarget = StructProc::ATTACKER; break;
|
|
}
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, pEffect->fValue[ 14 ], pEffect->fValue[ 15 ], pEffect->fValue[ 16 ], pEffect->fValue[ 17 ], pEffect->fValue[ 12 ], pEffect->fValue[ 18 ], NULL ) );
|
|
m_vProcByAttack.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pEffect->fValue[ 0 ] ), pEffect->fValue[ 2 ] + pEffect->fValue[ 3 ] * pEffect->nEffectLevel, ( pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel ) * 100, nTarget, pEffect->fValue[ 13 ] );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_BEING_ATTACKED:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BEING_ATTACKED:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pEffect->nEffectID )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_BEING_ATTACKED: nTarget = StructProc::ATTACKER; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BEING_ATTACKED: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByBeingAttacked.push_back( _ATTACK_TAG( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, pEffect->fValue[ 14 ], pEffect->fValue[ 15 ], pEffect->fValue[ 16 ], pEffect->fValue[ 17 ], pEffect->fValue[ 12 ], pEffect->fValue[ 18 ], NULL ) );
|
|
m_vProcByBeingAttacked.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pEffect->fValue[ 0 ] ), pEffect->fValue[ 2 ] + pEffect->fValue[ 3 ] * pEffect->nEffectLevel, ( pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel ) * 100, nTarget, pEffect->fValue[ 13 ] );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_DAMAGE_BASED_ATTACK_POINT:
|
|
{
|
|
c_fixed10 damage = 0;
|
|
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pEffect->fValue[ 14 ] != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != pEffect->fValue[ 14 ] &&
|
|
weapon_class != pEffect->fValue[ 15 ] &&
|
|
weapon_class != pEffect->fValue[ 16 ] &&
|
|
weapon_class != pEffect->fValue[ 17 ] )
|
|
break;
|
|
|
|
if ( pEffect->fValue[ 4 ] == 0 || pEffect->fValue[ 4 ] == 99 )
|
|
{
|
|
damage += GetAttackPointRight();
|
|
}
|
|
if ( pEffect->fValue[ 4 ] == 1 || pEffect->fValue[ 4 ] == 99 )
|
|
{
|
|
damage += GetMagicPoint();
|
|
}
|
|
|
|
damage *= pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel;
|
|
|
|
c_fixed10 procRate = pEffect->fValue[ 5 ] + pEffect->fValue[ 6 ] * pEffect->nEffectLevel;
|
|
|
|
AdditionalDamageInfo additionalDamage( procRate, (Elemental::Type)99, (Elemental::Type)(int)pEffect->fValue[ 7 ], damage, 0 );
|
|
|
|
if ( pEffect->fValue[ 10 ] == 1 )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( additionalDamage );
|
|
}
|
|
if ( pEffect->fValue[ 11 ] == 1 )
|
|
{
|
|
m_vRangeAdditionalDamage.push_back( additionalDamage );
|
|
}
|
|
if ( pEffect->fValue[ 12 ] == 1 )
|
|
{
|
|
m_vPhysicalSkillAdditionalDamage.push_back( additionalDamage );
|
|
}
|
|
if ( pEffect->fValue[ 13 ] == 1 )
|
|
{
|
|
m_vMagicalSkillAdditionalDamage.push_back( additionalDamage );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_KILL:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
|
|
m_vProcByKill.push_back( _KILL_TAG( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, pEffect->fValue[ 14 ], pEffect->fValue[ 15 ], 0, 0, pEffect->fValue[ 18 ], pEffect->fValue[ 19 ], NULL ) );
|
|
m_vProcByKill.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pEffect->fValue[ 0 ] ), pEffect->fValue[ 2 ] + pEffect->fValue[ 3 ] * pEffect->nEffectLevel, ( pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel ) * 100, StructProc::ATTACKER, pEffect->fValue[ 13 ] );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_DEAD:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
|
|
m_vProcByDead.push_back( _KILL_TAG( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, 0, 0, pEffect->fValue[ 16 ], pEffect->fValue[ 17 ], pEffect->fValue[ 18 ], pEffect->fValue[ 19 ], NULL ) );
|
|
m_vProcByDead.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pEffect->fValue[ 0 ] ), pEffect->fValue[ 2 ] + pEffect->fValue[ 3 ] * pEffect->nEffectLevel, ( pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel ) * 100, StructProc::ATTACKEE, pEffect->fValue[ 13 ] );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_CRITICAL_ATTACK:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_CRITICAL_ATTACK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pEffect->nEffectID )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_CRITICAL_ATTACK: nTarget = StructProc::ATTACKEE; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_CRITICAL_ATTACK: nTarget = StructProc::ATTACKER; break;
|
|
}
|
|
|
|
m_vProcByCriticalAttack.push_back( _ATTACK_TAG( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, pEffect->fValue[ 14 ], pEffect->fValue[ 15 ], pEffect->fValue[ 16 ], pEffect->fValue[ 17 ], pEffect->fValue[ 12 ], pEffect->fValue[ 18 ], NULL ) );
|
|
m_vProcByCriticalAttack.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pEffect->fValue[ 0 ] ), pEffect->fValue[ 2 ] + pEffect->fValue[ 3 ] * pEffect->nEffectLevel, ( pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel ) * 100, nTarget, pEffect->fValue[ 13 ] );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_BEING_CRITICAL_ATTACKED:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BEING_CRITICAL_ATTACKED:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pEffect->nEffectID )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_BEING_CRITICAL_ATTACKED: nTarget = StructProc::ATTACKER; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BEING_CRITICAL_ATTACKED: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByBeingCriticalAttacked.push_back( _ATTACK_TAG( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, pEffect->fValue[ 14 ], pEffect->fValue[ 15 ], pEffect->fValue[ 16 ], pEffect->fValue[ 17 ], pEffect->fValue[ 12 ], pEffect->fValue[ 18 ], NULL ) );
|
|
m_vProcByBeingCriticalAttacked.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pEffect->fValue[ 0 ] ), pEffect->fValue[ 2 ] + pEffect->fValue[ 3 ] * pEffect->nEffectLevel, ( pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel ) * 100, nTarget, pEffect->fValue[ 13 ] );
|
|
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_AVOID:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_AVOID:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pEffect->nEffectID )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_AVOID: nTarget = StructProc::ATTACKER; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_AVOID: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByAvoid.push_back( _ATTACK_TAG( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, pEffect->fValue[ 14 ], pEffect->fValue[ 15 ], pEffect->fValue[ 16 ], pEffect->fValue[ 17 ], pEffect->fValue[ 12 ], pEffect->fValue[ 18 ], NULL ) );
|
|
m_vProcByAvoid.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pEffect->fValue[ 0 ] ), pEffect->fValue[ 2 ] + pEffect->fValue[ 3 ] * pEffect->nEffectLevel, ( pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel ) * 100, nTarget, pEffect->fValue[ 13 ] );
|
|
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_BLOCK:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BLOCK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pEffect->nEffectID )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_BLOCK: nTarget = StructProc::ATTACKER; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_BLOCK: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByBlock.push_back( _ATTACK_TAG( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, pEffect->fValue[ 14 ], pEffect->fValue[ 15 ], pEffect->fValue[ 16 ], pEffect->fValue[ 17 ], pEffect->fValue[ 12 ], pEffect->fValue[ 18 ], NULL ) );
|
|
m_vProcByBlock.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pEffect->fValue[ 0 ] ), pEffect->fValue[ 2 ] + pEffect->fValue[ 3 ] * pEffect->nEffectLevel, ( pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel ) * 100, nTarget, pEffect->fValue[ 13 ] );
|
|
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_ON_PERFECT_BLOCK:
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_PERFECT_BLOCK:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON && weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
|
|
StructProc::TargetType nTarget = StructProc::ATTACKER;
|
|
|
|
switch( pEffect->nEffectID )
|
|
{
|
|
case StructState::EF_ADD_STATE_ON_PERFECT_BLOCK: nTarget = StructProc::ATTACKER; break;
|
|
case StructState::EF_ADD_STATE_BY_SELF_ON_PERFECT_BLOCK: nTarget = StructProc::ATTACKEE; break;
|
|
}
|
|
|
|
m_vProcByPerfectBlock.push_back( _ATTACK_TAG( pEffect->fValue[ 6 ] + pEffect->fValue[ 7 ] * pEffect->nEffectLevel, pEffect->fValue[ 14 ], pEffect->fValue[ 15 ], pEffect->fValue[ 16 ], pEffect->fValue[ 17 ], pEffect->fValue[ 12 ], pEffect->fValue[ 18 ], NULL ) );
|
|
m_vProcByPerfectBlock.back().proc = new StructStateProc( static_cast< StructState::StateCode >( (int) pEffect->fValue[ 0 ] ), pEffect->fValue[ 2 ] + pEffect->fValue[ 3 ] * pEffect->nEffectLevel, ( pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel ) * 100, nTarget, pEffect->fValue[ 13 ] );
|
|
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_HP_ON_ATTACK:
|
|
{
|
|
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON )
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
}
|
|
|
|
int nHPInc = pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1];
|
|
int nMPInc = pEffect->fValue[2] + pEffect->nEffectLevel * pEffect->fValue[3];
|
|
int nRatio = pEffect->fValue[6] + pEffect->nEffectLevel * pEffect->fValue[7];
|
|
|
|
if( !nHPInc && !nMPInc )
|
|
break;
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( nRatio, 0, 0, 0, 0, StructState::NormalAttack, 99, NULL ) );
|
|
m_vProcByAttack.back().proc = new StructHealProc( StructProc::ATTACKER, nHPInc, nMPInc );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ABSORB:
|
|
{
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON )
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
}
|
|
|
|
float fHPAbsorbRatio = pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1];
|
|
float fMPAbsorbRatio = pEffect->fValue[2] + pEffect->nEffectLevel * pEffect->fValue[3];
|
|
int nRatio = pEffect->fValue[6] + pEffect->nEffectLevel * pEffect->fValue[7];
|
|
|
|
if( !fHPAbsorbRatio && !fMPAbsorbRatio )
|
|
break;
|
|
|
|
StructAbsorbProc *pProc = new StructAbsorbProc( StructProc::ATTACKER, fHPAbsorbRatio, fMPAbsorbRatio );
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( nRatio, 0, 0, 0, 0, StructState::NormalAttack, 99, pProc ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_STEAL:
|
|
case StructState::EF_STEAL_WITH_REGEN_STOP:
|
|
{
|
|
if( pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON )
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
{
|
|
break;
|
|
}
|
|
|
|
if( weapon_class != pEffect->fValue[ 8 ] && weapon_class != pEffect->fValue[ 9 ] && weapon_class != pEffect->fValue[ 10 ] && weapon_class != pEffect->fValue[ 11 ] )
|
|
break;
|
|
}
|
|
|
|
int nHPSteal = pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1];
|
|
int nMPSteal = pEffect->fValue[2] + pEffect->nEffectLevel * pEffect->fValue[3];
|
|
int nRatio = pEffect->fValue[6] + pEffect->nEffectLevel * pEffect->fValue[7];
|
|
|
|
if( !nHPSteal && !nMPSteal )
|
|
break;
|
|
|
|
m_vProcByAttack.push_back( _ATTACK_TAG( nRatio, 0, 0, 0, 0, StructState::NormalAttack, 99, NULL ) );
|
|
m_vProcByAttack.back().proc = new StructStealProc( StructProc::ATTACKER, nHPSteal, nMPSteal );
|
|
|
|
if( pEffect->nEffectID == StructState::EF_STEAL_WITH_REGEN_STOP )
|
|
{
|
|
if( pEffect->fValue[ 12 ] )
|
|
m_StatusFlag.On( STATUS_HP_REGEN_STOPPED );
|
|
if( pEffect->fValue[ 13 ] )
|
|
m_StatusFlag.On( STATUS_MP_REGEN_STOPPED );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REFLECT_PERCENT:
|
|
{
|
|
m_vDamageReflectInfo.push_back( DamageReflectInfo( pEffect->fValue[ 6 ] + pEffect->nEffectLevel * pEffect->fValue[ 7 ], pEffect->fValue[ 9 ] * GameRule::DEFAULT_UNIT_SIZE,
|
|
(Elemental::Type) (int) pEffect->fValue[ 8 ], 0,
|
|
pEffect->fValue[ 0 ] + pEffect->nEffectLevel * pEffect->fValue[ 1 ],
|
|
pEffect->fValue[ 2 ] + pEffect->nEffectLevel * pEffect->fValue[ 3 ],
|
|
pEffect->fValue[ 4 ] + pEffect->nEffectLevel * pEffect->fValue[ 5 ],
|
|
pEffect->fValue[ 10 ] ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REFLECT:
|
|
{
|
|
m_vDamageReflectInfo.push_back( DamageReflectInfo( pEffect->fValue[ 6 ] + pEffect->nEffectLevel * pEffect->fValue[ 7 ], GameRule::REFLECT_RANGE,
|
|
(Elemental::Type) (int) pEffect->fValue[ 8 ], pEffect->fValue[ 0 ] + pEffect->nEffectLevel * pEffect->fValue[ 1 ],
|
|
0.0f,
|
|
0.0f,
|
|
0.0f,
|
|
pEffect->fValue[ 9 ] ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REFLECT_WHEN_EQUIP_SHIELD:
|
|
{
|
|
if( IsWearShield() )
|
|
{
|
|
m_vStateReflectInfo.push_back( StateReflectInfo( static_cast< StructState::StateCode >( (int)pEffect->fValue[ 0 ] ), pEffect->fValue[ 3 ] + pEffect->nEffectLevel * pEffect->fValue[ 4 ], pEffect->fValue[ 1 ] + pEffect->nEffectLevel * pEffect->fValue[ 2 ] ) );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_REGEN_ADD:
|
|
{
|
|
m_Attribute.fHPRegenPoint += pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1];
|
|
m_Attribute.fMPRegenPoint += pEffect->fValue[2] + pEffect->nEffectLevel * pEffect->fValue[3];
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_RECEIVE_DAMAGE:
|
|
{
|
|
// ApplyType(근거리/원거리 설정)은 일반 공격만 적용된다
|
|
int nApplyType = pEffect->fValue[ 0 ];
|
|
if( nApplyType == 1 )
|
|
{
|
|
m_NormalStatePenalty.fDamage += ( pEffect->fValue[7] + pEffect->nEffectLevel * pEffect->fValue[8] );
|
|
}
|
|
else if( nApplyType == 2 )
|
|
{
|
|
m_RangeStatePenalty.fDamage += ( pEffect->fValue[7] + pEffect->nEffectLevel * pEffect->fValue[8] );
|
|
}
|
|
else if( nApplyType == 99 )
|
|
{
|
|
m_NormalStatePenalty.fDamage += ( pEffect->fValue[7] + pEffect->nEffectLevel * pEffect->fValue[8] );
|
|
m_RangeStatePenalty.fDamage += ( pEffect->fValue[7] + pEffect->nEffectLevel * pEffect->fValue[8] );
|
|
}
|
|
|
|
m_StateStatePenalty.fDamage += ( pEffect->fValue[3] + pEffect->nEffectLevel * pEffect->fValue[4] );
|
|
m_PhysicalSkillStatePenalty.fDamage += ( pEffect->fValue[5] + pEffect->nEffectLevel * pEffect->fValue[6] );
|
|
m_MagicalSkillStatePenalty.fDamage += ( pEffect->fValue[9] + pEffect->nEffectLevel * pEffect->fValue[10] );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_INC_HATE:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
break;
|
|
|
|
if( weapon_class != pEffect->fValue[ 6 ] && pEffect->fValue[ 6 ] != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != pEffect->fValue[ 7 ] && pEffect->fValue[ 7 ] != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != pEffect->fValue[ 8 ] && pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != pEffect->fValue[ 9 ] && pEffect->fValue[ 9 ] != ItemBase::CLASS_EVERY_WEAPON )
|
|
break;
|
|
|
|
m_vHateMod.push_back( HateModifier( pEffect->fValue[10], pEffect->fValue[11], 0, pEffect->fValue[0] + pEffect->fValue[1] * pEffect->nEffectLevel ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_HATE:
|
|
{
|
|
ItemBase::ItemClass weapon_class = GetWeaponClass();
|
|
|
|
if( !weapon_class )
|
|
break;
|
|
|
|
if( weapon_class != pEffect->fValue[ 6 ] && pEffect->fValue[ 6 ] != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != pEffect->fValue[ 7 ] && pEffect->fValue[ 7 ] != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != pEffect->fValue[ 8 ] && pEffect->fValue[ 8 ] != ItemBase::CLASS_EVERY_WEAPON &&
|
|
weapon_class != pEffect->fValue[ 9 ] && pEffect->fValue[ 9 ] != ItemBase::CLASS_EVERY_WEAPON )
|
|
break;
|
|
|
|
m_vHateMod.push_back( HateModifier( pEffect->fValue[10], pEffect->fValue[11], pEffect->fValue[0] + pEffect->fValue[1] * pEffect->nEffectLevel, 0 ) );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_FORCE_CHIP:
|
|
{
|
|
c_fixed10 fNormalStatePenalty = ( pEffect->fValue[0] + pEffect->fValue[1] * pEffect->nEffectLevel );
|
|
c_fixed10 fRangeStatePenalty = ( pEffect->fValue[0] + pEffect->fValue[1] * pEffect->nEffectLevel );
|
|
c_fixed10 fPhysicalSkillStatePenalty = ( pEffect->fValue[2] + pEffect->fValue[3] * pEffect->nEffectLevel );
|
|
|
|
if( IsPlayer() || IsSummon() )
|
|
{
|
|
fNormalStatePenalty = fNormalStatePenalty * 0.25f;
|
|
fRangeStatePenalty = fRangeStatePenalty * 0.25f;
|
|
fPhysicalSkillStatePenalty = fPhysicalSkillStatePenalty * 0.25f;
|
|
}
|
|
|
|
m_NormalStatePenalty.fDamage += fNormalStatePenalty;
|
|
m_RangeStatePenalty.fDamage += fRangeStatePenalty;
|
|
m_PhysicalSkillStatePenalty.fDamage += fPhysicalSkillStatePenalty;
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_SOUL_CHIP:
|
|
{
|
|
c_fixed10 fMagicalSkillStatePenalty = ( pEffect->fValue[2] + pEffect->nEffectLevel * pEffect->fValue[3] );
|
|
|
|
if( IsPlayer() || IsSummon() )
|
|
{
|
|
fMagicalSkillStatePenalty = fMagicalSkillStatePenalty * 0.25f;
|
|
}
|
|
|
|
m_MagicalSkillStatePenalty.fDamage += fMagicalSkillStatePenalty;
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_HEALING_CHIP:
|
|
{
|
|
m_fHealRatio += ( pEffect->fValue[2] + pEffect->nEffectLevel * pEffect->fValue[3] );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_LUNAR_CHIP:
|
|
{
|
|
c_fixed10 fNormalStatePenalty = ( pEffect->fValue[0] + pEffect->fValue[1] * pEffect->nEffectLevel );
|
|
c_fixed10 fRangeStatePenalty = ( pEffect->fValue[0] + pEffect->fValue[1] * pEffect->nEffectLevel );
|
|
c_fixed10 fPhysicalSkillStatePenalty = ( pEffect->fValue[2] + pEffect->fValue[3] * pEffect->nEffectLevel );
|
|
c_fixed10 fMagicalSkillStatePenalty = ( pEffect->fValue[2] + pEffect->fValue[3] * pEffect->nEffectLevel );
|
|
c_fixed10 fStateStatePenalty = ( pEffect->fValue[12] + pEffect->fValue[13] * pEffect->nEffectLevel );
|
|
|
|
if( IsPlayer() || IsSummon() )
|
|
{
|
|
fNormalStatePenalty = fNormalStatePenalty * 0.25f;
|
|
fRangeStatePenalty = fRangeStatePenalty * 0.25f;
|
|
fPhysicalSkillStatePenalty = fPhysicalSkillStatePenalty * 0.25f;
|
|
fMagicalSkillStatePenalty = fMagicalSkillStatePenalty * 0.25f;
|
|
fStateStatePenalty = fStateStatePenalty * 0.25f;
|
|
}
|
|
|
|
m_NormalStatePenalty.fDamage += fNormalStatePenalty;
|
|
m_RangeStatePenalty.fDamage += fRangeStatePenalty;
|
|
m_PhysicalSkillStatePenalty.fDamage += fPhysicalSkillStatePenalty;
|
|
m_MagicalSkillStatePenalty.fDamage += fMagicalSkillStatePenalty;
|
|
m_StateStatePenalty.fDamage += fStateStatePenalty;
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_LUNA_ONCE:
|
|
{
|
|
m_nLuna = 1;
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_MP_COST_INC:
|
|
{
|
|
float fCostReduce = pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1];
|
|
int nElementalType = pEffect->fValue[5];
|
|
|
|
if( nElementalType != 99 )
|
|
{
|
|
if( pEffect->fValue[ 10 ] == 99 || pEffect->fValue[ 10 ] == 1 )
|
|
{
|
|
if( pEffect->fValue[ 11 ] == 99 || pEffect->fValue[ 11 ] == 0 )
|
|
{
|
|
m_GoodPhysicalElementalSkillStateMod[nElementalType].fManaCostRatio += fCostReduce;
|
|
}
|
|
|
|
if( pEffect->fValue[ 11 ] == 99 || pEffect->fValue[ 11 ] == 1 )
|
|
{
|
|
m_BadPhysicalElementalSkillStateMod[nElementalType].fManaCostRatio += fCostReduce;
|
|
}
|
|
}
|
|
|
|
if( pEffect->fValue[ 10 ] == 99 || pEffect->fValue[ 10 ] == 2 )
|
|
{
|
|
if( pEffect->fValue[ 11 ] == 99 || pEffect->fValue[ 11 ] == 0 )
|
|
{
|
|
m_GoodMagicalElementalSkillStateMod[nElementalType].fManaCostRatio += fCostReduce;
|
|
}
|
|
|
|
if( pEffect->fValue[ 11 ] == 99 || pEffect->fValue[ 11 ] == 1 )
|
|
{
|
|
m_BadMagicalElementalSkillStateMod[nElementalType].fManaCostRatio += fCostReduce;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for( int i = 0; i < Elemental::TYPE_COUNT; ++i )
|
|
{
|
|
if( pEffect->fValue[ 10 ] == 99 || pEffect->fValue[ 10 ] == 1 )
|
|
{
|
|
if( pEffect->fValue[ 11 ] == 99 || pEffect->fValue[ 11 ] == 0 )
|
|
{
|
|
m_GoodPhysicalElementalSkillStateMod[i].fManaCostRatio += fCostReduce;
|
|
}
|
|
|
|
if( pEffect->fValue[ 11 ] == 99 || pEffect->fValue[ 11 ] == 1 )
|
|
{
|
|
m_BadPhysicalElementalSkillStateMod[i].fManaCostRatio += fCostReduce;
|
|
}
|
|
}
|
|
|
|
if( pEffect->fValue[ 10 ] == 99 || pEffect->fValue[ 10 ] == 2 )
|
|
{
|
|
if( pEffect->fValue[ 11 ] == 99 || pEffect->fValue[ 11 ] == 0 )
|
|
{
|
|
m_GoodMagicalElementalSkillStateMod[i].fManaCostRatio += fCostReduce;
|
|
}
|
|
|
|
if( pEffect->fValue[ 11 ] == 99 || pEffect->fValue[ 11 ] == 1 )
|
|
{
|
|
m_BadMagicalElementalSkillStateMod[i].fManaCostRatio += fCostReduce;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_PARAMETER_ON_NORMAL_ATTACK:
|
|
{
|
|
if( pEffect->fValue[ 9 ] == 99 || pEffect->fValue[ 9 ] == 1 )
|
|
{
|
|
m_RangeStateAdvantage.fDamage += pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel;
|
|
m_RangeStateAdvantage.fCritical += pEffect->fValue[ 3 ] * pEffect->nEffectLevel;
|
|
m_RangeStateAdvantage.nCritical += pEffect->fValue[ 4 ] * pEffect->nEffectLevel;
|
|
m_RangeStateAdvantage.fHate += pEffect->fValue[ 5 ] + pEffect->fValue[ 6 ] * pEffect->nEffectLevel;
|
|
}
|
|
|
|
if( pEffect->fValue[ 9 ] == 99 || pEffect->fValue[ 9 ] == 0 )
|
|
{
|
|
m_NormalStateAdvantage.fDamage += pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel;
|
|
m_NormalStateAdvantage.fCritical += pEffect->fValue[ 3 ] * pEffect->nEffectLevel;
|
|
m_NormalStateAdvantage.nCritical += pEffect->fValue[ 4 ] * pEffect->nEffectLevel;
|
|
m_NormalStateAdvantage.fHate += pEffect->fValue[ 6 ] * pEffect->nEffectLevel;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_PARAMETER_ON_SKILL:
|
|
assert( 0 );
|
|
break;
|
|
|
|
//조작 관련 상태 이상
|
|
case StructState::EF_MEZZ:
|
|
// 모든 조작 불가
|
|
if( pEffect->fValue[0] )
|
|
{
|
|
m_StatusFlag.Off( STATUS_MOVABLE );
|
|
m_StatusFlag.Off( STATUS_ATTACKABLE );
|
|
m_StatusFlag.Off( STATUS_SKILL_CASTABLE );
|
|
m_StatusFlag.Off( STATUS_MAGIC_CASTABLE );
|
|
m_StatusFlag.Off( STATUS_ITEM_USABLE );
|
|
}
|
|
|
|
// 이동 불가
|
|
if( pEffect->fValue[1] )
|
|
m_StatusFlag.Off( STATUS_MOVABLE );
|
|
|
|
// 공격 불가
|
|
if( pEffect->fValue[2] )
|
|
m_StatusFlag.Off( STATUS_ATTACKABLE );
|
|
|
|
// 물리 스킬 시전 불가
|
|
if( pEffect->fValue[3] )
|
|
m_StatusFlag.Off( STATUS_SKILL_CASTABLE );
|
|
|
|
// 마법 스킬 시전 불가
|
|
if( pEffect->fValue[4] )
|
|
m_StatusFlag.Off( STATUS_MAGIC_CASTABLE );
|
|
|
|
// 피격 불가
|
|
if( pEffect->fValue[5] )
|
|
m_StatusFlag.Off( STATUS_MORTAL );
|
|
|
|
// HP 감소
|
|
m_fMaxHPAmplifier -= pEffect->fValue[8] + pEffect->fValue[9] * pEffect->nEffectLevel;
|
|
m_nMaxHP -= pEffect->fValue[6] + pEffect->fValue[7] * pEffect->nEffectLevel;
|
|
|
|
// MP 감소
|
|
m_fMaxMPAmplifier -= pEffect->fValue[12] + pEffect->fValue[13] * pEffect->nEffectLevel;
|
|
m_nMaxMP -= pEffect->fValue[10] + pEffect->fValue[11] * pEffect->nEffectLevel;
|
|
|
|
break;
|
|
|
|
case StructState::EF_TRANSFORMATION:
|
|
assert( 0 );
|
|
break;
|
|
|
|
case StructState::EF_ADD_HP_MP_ON_CRITICAL:
|
|
m_vAddHPMPOnCritical.push_back( AddHPMPOnCriticalInfo( pEffect->fValue[0] + pEffect->fValue[1] * pEffect->nEffectLevel, pEffect->fValue[2] + pEffect->fValue[3] * pEffect->nEffectLevel, pEffect->fValue[4] + pEffect->fValue[5] * pEffect->nEffectLevel ) );
|
|
break;
|
|
|
|
case StructState::EF_HEALING_AMPLIFY:
|
|
{
|
|
c_fixed10 fHPHealRatio = pEffect->fValue[0] + pEffect->fValue[1] * pEffect->nEffectLevel;
|
|
c_fixed10 fMPHealRatio = pEffect->fValue[2] + pEffect->fValue[3] * pEffect->nEffectLevel;
|
|
|
|
m_fHealRatio += fHPHealRatio;
|
|
m_fMPHealRatio += fMPHealRatio;
|
|
|
|
m_nAdditionalHeal += pEffect->fValue[4] + pEffect->fValue[5] * pEffect->nEffectLevel;
|
|
m_nAdditionalMPHeal += pEffect->fValue[6] + pEffect->fValue[7] * pEffect->nEffectLevel;
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DETECT_HIDE:
|
|
m_fDetectHideRange += ( pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1] ) * GameRule::DEFAULT_UNIT_SIZE;
|
|
break;
|
|
|
|
case StructState::EF_SKILL_INTERRUPTION:
|
|
for( int i = 0 ; i < 12 && pEffect->fValue[ i ] ; ++i )
|
|
m_vInterruptedSkill.push_back( pEffect->fValue[ i ] );
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REDUCE_WITH_RACE_BY_PERCENT:
|
|
m_vDamageReducePercentInfo.push_back( DamageReduceInfo( pEffect->fValue[6], pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1], pEffect->fValue[2] + pEffect->nEffectLevel * pEffect->fValue[3],
|
|
pEffect->fValue[4] + pEffect->nEffectLevel * pEffect->fValue[5], pEffect->fValue[7], pEffect->fValue[8], pEffect->fValue[9], pEffect->fValue[10], pEffect->fValue[11] ) );
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REDUCE_WITH_RACE_BY_VALUE:
|
|
m_vDamageReduceValueInfo.push_back( DamageReduceInfo( pEffect->fValue[6], pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1], pEffect->fValue[2] + pEffect->nEffectLevel * pEffect->fValue[3],
|
|
pEffect->fValue[4] + pEffect->nEffectLevel * pEffect->fValue[5], pEffect->fValue[7], pEffect->fValue[8], pEffect->fValue[9], pEffect->fValue[10], pEffect->fValue[11] ) );
|
|
break;
|
|
|
|
case StructState::EF_MANA_SHIELD:
|
|
{
|
|
int nTargetType = pEffect->fValue[4];
|
|
if( nTargetType == 1 || nTargetType == 99 )
|
|
m_fPhysicalDamageManaShieldAbsorbRatio += pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1];
|
|
if( nTargetType == 2 || nTargetType == 99 )
|
|
m_fMagicalDamageManaShieldAbsorbRatio += pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1];
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_AMP_AND_INC_ITEM_CHANCE:
|
|
// nItemChance == 100 이면 아이템 드랍 체크시 해당 아이템의 드랍율이 2배로 적용됨(드랍율 % 증폭 개념 변수임)
|
|
// GetValue( 0 ) + GetValue( 1 ) * GetLevel() == 1.0 -> 2배 증폭(nItemChance = 100 이 되야 함)
|
|
// 정수 처리 특성상 결과값의 소수 2째 자리 미만은 전부 버려짐
|
|
m_Attribute.fItemChance += ( pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel ) * 100;
|
|
m_fEXPMod += pEffect->fValue[ 2 ] + pEffect->fValue[ 3 ] * pEffect->nEffectLevel;
|
|
if( this->IsPlayer() )
|
|
{
|
|
StructPlayer *pPlayer = static_cast< StructPlayer * >( this );
|
|
pPlayer->SetActiveSummonExpAmp( pPlayer->GetActiveSummonExpAmp() + pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel );
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_CHANGING_GROUP:
|
|
m_nChangingGroup = pEffect->fValue[ 0 ];
|
|
break;
|
|
|
|
case StructState::EF_HUNTING_TRAINING:
|
|
{
|
|
for( int i = 0; i < 3; i++ )
|
|
{
|
|
int nCreatureType = pEffect->fValue[ i * 5 ];
|
|
|
|
c_fixed10 fDamage = pEffect->fValue[ i * 5 + 1 ] + pEffect->fValue[ i * 5 + 2 ] * pEffect->nEffectLevel;
|
|
c_fixed10 fAvoid = pEffect->fValue[ i * 5 + 3 ] + pEffect->fValue[ i * 5 + 4 ] * pEffect->nEffectLevel;
|
|
|
|
if( nCreatureType == CREATURE_ALL )
|
|
{
|
|
for( int i = 0 ; i < MAX_CREATURE_TYPE_NUMBER ; ++i )
|
|
{
|
|
m_Expert[ i ].fDamage += fDamage;
|
|
m_Expert[ i ].fAvoid += fAvoid;
|
|
}
|
|
}
|
|
else if( nCreatureType >= 0 && nCreatureType < MAX_CREATURE_TYPE_NUMBER )
|
|
{
|
|
m_Expert[ nCreatureType ].fDamage += fDamage;
|
|
m_Expert[ nCreatureType ].fAvoid += fAvoid;
|
|
}
|
|
else
|
|
{
|
|
assert( 0 && "CREATURE DATA TYPE ERROR!" );
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_RESIST_HARMFUL_STATE:
|
|
{
|
|
for( int i = 0; i < 6; ++i )
|
|
{
|
|
StructState::StateCode code = static_cast< StructState::StateCode >( (int)pEffect->fValue[ i * 3 ] );
|
|
c_fixed10 rate = pEffect->fValue[ i * 3 + 1 ] + pEffect->fValue[ i * 3 + 2 ] * pEffect->nEffectLevel;
|
|
|
|
if( !code ) continue;
|
|
|
|
std::map< StructState::StateCode, c_fixed10 >::iterator it = m_mapResistHarmfulState.find( code );
|
|
if( it == m_mapResistHarmfulState.end() )
|
|
{
|
|
m_mapResistHarmfulState.insert( std::make_pair< StructState::StateCode, c_fixed10 >( code, rate ) );
|
|
}
|
|
else
|
|
{
|
|
(*it).second += rate;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_REDUCE_DAMAGE_ON_ATTACK:
|
|
{
|
|
if( pEffect->fValue[7] == 0 || pEffect->fValue[7] == 99 )
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( pEffect->fValue[3] + pEffect->fValue[4] * pEffect->nEffectLevel, Elemental::TYPE_NONE, (Elemental::Type) (int) pEffect->fValue[5], pEffect->fValue[0] + pEffect->fValue[1] * pEffect->nEffectLevel, 0 ) );
|
|
if( pEffect->fValue[7] == 1 || pEffect->fValue[7] == 99 )
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( pEffect->fValue[3] + pEffect->fValue[4] * pEffect->nEffectLevel, Elemental::TYPE_NONE, (Elemental::Type) (int) pEffect->fValue[5], pEffect->fValue[0] + pEffect->fValue[1] * pEffect->nEffectLevel, 0 ) );
|
|
m_vDamageReduceValueInfo.push_back( DamageReduceInfo( pEffect->fValue[15] * pEffect->nEffectLevel * pEffect->fValue[16], pEffect->fValue[9] + pEffect->nEffectLevel * pEffect->fValue[10], pEffect->fValue[11] + pEffect->nEffectLevel * pEffect->fValue[12],
|
|
pEffect->fValue[13] + pEffect->nEffectLevel * pEffect->fValue[14], pEffect->fValue[17], pEffect->fValue[18], pEffect->fValue[19], pEffect->fValue[19], pEffect->fValue[19] ) );
|
|
// TODO: 유형 체크에 20번 값을 중복하여 넣은 것은 뒤의 두 값은 사용되지 않기 때문. 동작 자체에는 차이가 없을 것이나 리뷰가 필요할 듯 함
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_DAMAGE_REDUCE_BY_PERCENT_AND_VALUE:
|
|
{
|
|
m_vDamageReducePercentInfo.push_back( DamageReduceInfo( pEffect->fValue[6], pEffect->fValue[0] + pEffect->nEffectLevel * pEffect->fValue[1], pEffect->fValue[2] + pEffect->nEffectLevel * pEffect->fValue[3],
|
|
pEffect->fValue[4] + pEffect->nEffectLevel * pEffect->fValue[5], pEffect->fValue[7], pEffect->fValue[8], pEffect->fValue[9], pEffect->fValue[9], pEffect->fValue[9] ) );
|
|
m_vDamageReduceValueInfo.push_back( DamageReduceInfo( pEffect->fValue[16], pEffect->fValue[10] + pEffect->nEffectLevel * pEffect->fValue[11], pEffect->fValue[12] + pEffect->nEffectLevel * pEffect->fValue[13],
|
|
pEffect->fValue[14] + pEffect->nEffectLevel * pEffect->fValue[15], pEffect->fValue[17], pEffect->fValue[18], pEffect->fValue[19], pEffect->fValue[19], pEffect->fValue[19] ) );
|
|
// TODO: 유형 체크에 10, 20번 값을 중복하여 넣은 것은 뒤의 두 값은 사용되지 않기 때문. 동작 자체에는 차이가 없을 것이나 리뷰가 필요할 듯 함
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_INCREASE_ENERGY_UNCONSUMPTION_RATE:
|
|
{
|
|
m_nEnergyUnconsumptionRate += pEffect->fValue[ 0 ] + pEffect->fValue[ 1 ] * pEffect->nEffectLevel;
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_ADD_STATE_BY_EQUIP_ITEM:
|
|
{
|
|
AR_TIME t = GetArTime();
|
|
|
|
for( int i = 0; i < 4; ++i )
|
|
{
|
|
int nStateCode = pEffect->fValue[ 3 * i + 0 ];
|
|
int nStateLevel = pEffect->fValue[ 3 * i + 1 ];
|
|
|
|
if ( nStateCode != 0 )
|
|
{
|
|
// 장비하고 있는 동안 지속적으로 걸어주는 지속효과이므로 기본적으로 오오라의 성격을 따른다.
|
|
PendAddStateByItem( (StructState::StateCode)nStateCode, GetHandle(), nStateLevel, t, t + SkillBase::TOGGLE_LIVE_TIME, true, 0, "", false );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case StructState::EF_MISC:
|
|
assert( 0 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void StructPlayer::_applyEffectForState( const EffectInfo * pEffect )
|
|
{
|
|
switch( pEffect->nEffectID )
|
|
{
|
|
case StructState::EF_PARAMETER_INC_TO_ACTIVE_SUMMON:
|
|
incParameter( pEffect->fValue[ 0 ], pEffect->fValue[ 1 ] + pEffect->fValue[ 2 ] * pEffect->nEffectLevel, true, &m_ParameterForSummon );
|
|
incParameter( pEffect->fValue[ 0 ], pEffect->fValue[ 1 ] + pEffect->fValue[ 2 ] * pEffect->nEffectLevel, false, &m_ParameterForSummon );
|
|
incParameter( pEffect->fValue[ 3 ], pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel, true, &m_ParameterForSummon );
|
|
incParameter( pEffect->fValue[ 3 ], pEffect->fValue[ 4 ] + pEffect->fValue[ 5 ] * pEffect->nEffectLevel, false, &m_ParameterForSummon );
|
|
incParameter2( pEffect->fValue[ 6 ], pEffect->fValue[ 7 ] + pEffect->fValue[ 8 ] * pEffect->nEffectLevel, &m_ParameterForSummon );
|
|
incParameter2( pEffect->fValue[ 9 ], pEffect->fValue[ 10 ] + pEffect->fValue[ 11 ] * pEffect->nEffectLevel, &m_ParameterForSummon );
|
|
incParameter( pEffect->fValue[ 12 ], pEffect->fValue[ 13 ] + pEffect->fValue[ 14 ] * pEffect->nEffectLevel, true, &m_ParameterForSummon );
|
|
incParameter( pEffect->fValue[ 12 ], pEffect->fValue[ 13 ] + pEffect->fValue[ 14 ] * pEffect->nEffectLevel, false, &m_ParameterForSummon );
|
|
incParameter( pEffect->fValue[ 15 ], pEffect->fValue[ 16 ] + pEffect->fValue[ 17 ] * pEffect->nEffectLevel, true, &m_ParameterForSummon );
|
|
incParameter( pEffect->fValue[ 15 ], pEffect->fValue[ 16 ] + pEffect->fValue[ 17 ] * pEffect->nEffectLevel, false, &m_ParameterForSummon );
|
|
break;
|
|
}
|
|
|
|
StructCreature::_applyEffectForState( pEffect );
|
|
}
|
|
|
|
void StructSummon::_applyEffectForState( const EffectInfo * pEffect )
|
|
{
|
|
switch( pEffect->nEffectID )
|
|
{
|
|
case StructState::EF_HEAL:
|
|
{
|
|
m_nSPAdd += pEffect->fValue[ 4 ] + pEffect->nEffectLevel * pEffect->fValue[ 5 ];
|
|
}
|
|
break;
|
|
case StructState::EF_REGEN_ADD:
|
|
{
|
|
m_nSPRegenAdd += pEffect->fValue[ 4 ] + pEffect->nEffectLevel * pEffect->fValue[ 5 ];
|
|
}
|
|
break;
|
|
case StructState::EF_HEAL_BY_ITEM:
|
|
{
|
|
m_nSPAdd += pEffect->fValue[ 4 ] + pEffect->nEffectLevel * pEffect->fValue[ 5 ];
|
|
}
|
|
break;
|
|
}
|
|
|
|
StructCreature::_applyEffectForState( pEffect );
|
|
}
|
|
|
|
void StructCreature::_applySkillByEffect( const std::vector< EffectInfo * > * pvEffectList, float fRatio )
|
|
{
|
|
if( !pvEffectList || pvEffectList->empty() )
|
|
return;
|
|
|
|
for( std::vector< EffectInfo * >::const_iterator it = pvEffectList->begin(); it != pvEffectList->end(); it++ )
|
|
{
|
|
if( (*it)->eType != EffectInfo::EFFECT_TYPE_STATE )
|
|
continue;
|
|
|
|
if( (*it)->nMinLevel && GetLevel() < (*it)->nMinLevel ) continue;
|
|
if( (*it)->nMaxLevel && GetLevel() > (*it)->nMaxLevel ) continue;
|
|
|
|
if( (*it)->nEffectID == StructState::EF_ADD_SKILL )
|
|
{
|
|
addSkill( (*it)->fValue[ 0 ], (*it)->fValue[ 1 ] + (*it)->fValue[ 2 ] * (*it)->nEffectLevel, (*it)->fValue[ 18 ], false );
|
|
addSkill( (*it)->fValue[ 3 ], (*it)->fValue[ 4 ] + (*it)->fValue[ 5 ] * (*it)->nEffectLevel, (*it)->fValue[ 18 ], false );
|
|
addSkill( (*it)->fValue[ 6 ], (*it)->fValue[ 7 ] + (*it)->fValue[ 8 ] * (*it)->nEffectLevel, (*it)->fValue[ 18 ], false );
|
|
addSkill( (*it)->fValue[ 9 ], (*it)->fValue[ 10 ] + (*it)->fValue[ 11 ] * (*it)->nEffectLevel, (*it)->fValue[ 18 ], false );
|
|
addSkill( (*it)->fValue[ 12 ], (*it)->fValue[ 13 ] + (*it)->fValue[ 14 ] * (*it)->nEffectLevel, (*it)->fValue[ 18 ], false );
|
|
|
|
addSkill( (*it)->fValue[ 15 ], (*it)->fValue[ 16 ] + (*it)->fValue[ 17 ] * (*it)->nEffectLevel, (*it)->fValue[ 18 ], true );
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructCreature::applyStatByItem()
|
|
{
|
|
int i, x;
|
|
|
|
for( i = 0; i < ItemBase::MAX_ITEM_WEAR; ++i )
|
|
{
|
|
if( !m_anWear[i] ) continue;
|
|
|
|
// 장착 불가는 효과 없음
|
|
if( !IsWearable( (ItemBase::ItemWearType)i, m_anWear[i] ) ) continue;
|
|
|
|
const ItemBaseServer & base = m_anWear[i]->GetItemBase();
|
|
|
|
for( x = 0; x < ItemBase::MAX_OPTION_NUMBER; ++x )
|
|
{
|
|
if( !base.nOptType[x] ) continue;
|
|
|
|
if( base.nOptType[x] == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A )
|
|
{
|
|
incParameter( base.fOptVar1[x], base.fOptVar2[x], true );
|
|
}
|
|
}
|
|
|
|
// Since changes in skills also affect stats, they are modified together
|
|
_applyStatByEffect( base.pvEffectList );
|
|
_applySkillByEffect( base.pvEffectList );
|
|
|
|
for( x = 0 ; x < m_anWear[i]->GetMaxSocketCount() ; ++x )
|
|
{
|
|
ItemBase::ItemCode nSocketCode = m_anWear[i]->GetSocketCode( x );
|
|
|
|
if( !nSocketCode )
|
|
continue;
|
|
|
|
const ItemBaseServer & SocketBase = StructItem::GetItemBase( nSocketCode );
|
|
|
|
// 레벨 제한 적용 가능 검사
|
|
if( GetLevel() < SocketBase.nMinLevel || GetLevel() > SocketBase.nMaxLevel )
|
|
continue;
|
|
|
|
// 소켓 내구도 검사
|
|
if( !m_anWear[i]->GetCurrentEndurance() )
|
|
continue;
|
|
|
|
for( int k = 0; k < ItemBase::MAX_OPTION_NUMBER; ++k )
|
|
{
|
|
if( !SocketBase.nOptType[k] ) continue;
|
|
|
|
if( SocketBase.nOptType[k] == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A )
|
|
{
|
|
incParameter( SocketBase.fOptVar1[k], SocketBase.fOptVar2[k], true );
|
|
|
|
}
|
|
}
|
|
|
|
// 스킬의 변화도 스탯에 영향을 미치므로 함께 변경한다.
|
|
_applyStatByEffect( SocketBase.pvEffectList );
|
|
_applySkillByEffect( SocketBase.pvEffectList );
|
|
}
|
|
|
|
// 각성 여부 확인
|
|
if( m_anWear[i]->IsAwaken() )
|
|
{
|
|
for( int nCnt = 0 ; nCnt < ItemInstance::MAX_AWAKEN_NUMBER ; ++nCnt )
|
|
{
|
|
if( !m_anWear[i]->GetAwakenOptionType( nCnt ) )
|
|
break;
|
|
|
|
if( m_anWear[i]->GetAwakenOptionType( nCnt ) == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A )
|
|
{
|
|
incParameter( m_anWear[i]->GetAwakenOptionValue1( nCnt ), m_anWear[i]->GetAwakenOptionValue2( nCnt ), true );
|
|
}
|
|
else if( m_anWear[i]->GetAwakenOptionType( nCnt ) == ITEM_EFFECT_PASSIVE::APPLY_EFFECT )
|
|
{
|
|
// 스킬의 변화도 스탯에 영향을 미치므로 함께 변경한다.
|
|
const std::vector< EffectInfo * > *pEffectVector = GameContent::GetEffectInfoVector( m_anWear[i]->GetAwakenOptionValue1( nCnt ) );
|
|
_applyStatByEffect( pEffectVector );
|
|
_applySkillByEffect( pEffectVector );
|
|
}
|
|
}
|
|
}
|
|
|
|
// 랜덤화 여부 확인
|
|
if( m_anWear[i]->IsIdentified() )
|
|
{
|
|
for( int nCnt = 0 ; nCnt < ItemInstance::MAX_RANDOM_OPTION_NUMBER ; ++nCnt )
|
|
{
|
|
if( !m_anWear[i]->GetIdentifiedOptionType( nCnt ) )
|
|
break;
|
|
|
|
if( m_anWear[i]->GetIdentifiedOptionType( nCnt ) == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A )
|
|
{
|
|
incParameter( m_anWear[i]->GetIdentifiedOptionValue1( nCnt ), m_anWear[i]->GetIdentifiedOptionValue2( nCnt ), true );
|
|
}
|
|
else if( m_anWear[i]->GetIdentifiedOptionType( nCnt ) == ITEM_EFFECT_PASSIVE::APPLY_EFFECT )
|
|
{
|
|
// 스킬의 변화도 스탯에 영향을 미치므로 함께 변경한다.
|
|
const std::vector< EffectInfo * > *pEffectVector = GameContent::GetEffectInfoVector( m_anWear[i]->GetIdentifiedOptionValue1( nCnt ) );
|
|
_applyStatByEffect( pEffectVector );
|
|
_applySkillByEffect( pEffectVector );
|
|
}
|
|
else if (m_anWear[i]->GetIdentifiedOptionType(nCnt) == ITEM_EFFECT_PASSIVE::INC_SKILL)
|
|
{
|
|
addSkill(m_anWear[i]->GetIdentifiedOptionValue1(nCnt) , m_anWear[i]->GetIdentifiedOptionValue2(nCnt) , 0, false);
|
|
}
|
|
|
|
else if (m_anWear[i]->GetIdentifiedOptionType(nCnt) == ITEM_EFFECT_PASSIVE::INC_ALL_DAMAGE)
|
|
{
|
|
c_fixed10 fDamage = m_anWear[i]->GetIdentifiedOptionValue2(nCnt);
|
|
for (int i = 0; i < MAX_CREATURE_TYPE_NUMBER; ++i)
|
|
{
|
|
//c_fixed10 fAvoid = m_anWear[i]->GetIdentifiedOptionValue1(nCnt);
|
|
m_Expert[i].fDamage += fDamage;
|
|
// m_Expert[i].fAvoid += m_anWear[i]->GetIdentifiedOptionValue1(nCnt) ;
|
|
}
|
|
}
|
|
else if (m_anWear[i]->GetIdentifiedOptionType(nCnt) == ITEM_EFFECT_PASSIVE::REDUC_ALL_DAMAGE)
|
|
{
|
|
c_fixed10 fAvoid = m_anWear[i]->GetIdentifiedOptionValue2(nCnt);
|
|
for (int i = 0; i < MAX_CREATURE_TYPE_NUMBER; ++i)
|
|
{
|
|
//c_fixed10 fDamage = ;
|
|
//m_Expert[i].fDamage += m_anWear[i]->GetIdentifiedOptionValue1(nCnt);
|
|
m_Expert[i].fAvoid += fAvoid;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
for( std::vector< SetItemEffectInfo * >::const_iterator itSetItemEffectInfo = m_vSetItemEffect.begin(); itSetItemEffectInfo != m_vSetItemEffect.end(); ++itSetItemEffectInfo )
|
|
{
|
|
for( x = 0 ; x < ItemBase::MAX_OPTION_NUMBER ; ++x )
|
|
{
|
|
if( !(*itSetItemEffectInfo)->nOptType[x] ) continue;
|
|
|
|
if( (*itSetItemEffectInfo)->nOptType[x] == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A )
|
|
{
|
|
incParameter( (*itSetItemEffectInfo)->fOptVar1[x], (*itSetItemEffectInfo)->fOptVar2[x], true );
|
|
}
|
|
}
|
|
|
|
// Changes in skills also affect stats, so they are modified together
|
|
_applyStatByEffect( (*itSetItemEffectInfo)->pvEffectList );
|
|
_applySkillByEffect( (*itSetItemEffectInfo)->pvEffectList );
|
|
}
|
|
}
|
|
|
|
void StructCreature::_applyStatByEffect( const std::vector< EffectInfo * > * pvEffectList, float fRatio )
|
|
{
|
|
if( !pvEffectList || pvEffectList->empty() )
|
|
return;
|
|
|
|
for( std::vector< EffectInfo * >::const_iterator it = pvEffectList->begin() ; it != pvEffectList->end() ; ++it )
|
|
{
|
|
if( (*it)->eType != EffectInfo::EFFECT_TYPE_OPTIONAL )
|
|
continue;
|
|
|
|
if( (*it)->nMinLevel && GetLevel() < (*it)->nMinLevel ) continue;
|
|
if( (*it)->nMaxLevel && GetLevel() > (*it)->nMaxLevel ) continue;
|
|
|
|
if( (*it)->fValue[ 0 ] == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A ) incParameter( (*it)->fValue[ 1 ], (*it)->fValue[ 2 ] * fRatio, true );
|
|
if( (*it)->fValue[ 3 ] == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A ) incParameter( (*it)->fValue[ 4 ], (*it)->fValue[ 5 ] * fRatio, true );
|
|
if( (*it)->fValue[ 6 ] == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A ) incParameter( (*it)->fValue[ 7 ], (*it)->fValue[ 8 ] * fRatio, true );
|
|
if( (*it)->fValue[ 9 ] == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A ) incParameter( (*it)->fValue[ 10 ], (*it)->fValue[ 11 ] * fRatio, true );
|
|
}
|
|
}
|
|
|
|
void StructCreature::amplifyStatByItem()
|
|
{
|
|
for( int i = 0; i < ItemBase::MAX_ITEM_WEAR; ++i )
|
|
{
|
|
if( !m_anWear[i] ) continue;
|
|
|
|
// 장착 불가는 효과 없음
|
|
if( !IsWearable( (ItemBase::ItemWearType)i, m_anWear[i] ) ) continue;
|
|
|
|
const ItemBaseServer & base = m_anWear[i]->GetItemBase();
|
|
|
|
for( int x = 0; x < ItemBase::MAX_OPTION_NUMBER; ++x )
|
|
{
|
|
if( !base.nOptType[x] ) continue;
|
|
|
|
if( base.nOptType[x] == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A )
|
|
{
|
|
ampParameter( base.fOptVar1[x], base.fOptVar2[x], true );
|
|
}
|
|
}
|
|
|
|
_amplifyStatByEffect( base.pvEffectList );
|
|
|
|
for( int x = 0 ; x < m_anWear[i]->GetMaxSocketCount() ; ++x )
|
|
{
|
|
ItemBase::ItemCode nSocketCode = m_anWear[i]->GetSocketCode( x );
|
|
|
|
if( !nSocketCode )
|
|
continue;
|
|
|
|
const ItemBaseServer & SocketBase = StructItem::GetItemBase( nSocketCode );
|
|
|
|
// 레벨 제한 적용 가능 검사
|
|
if( GetLevel() < SocketBase.nMinLevel || GetLevel() > SocketBase.nMaxLevel )
|
|
continue;
|
|
|
|
// 소켓 내구도 검사
|
|
if( !m_anWear[i]->GetCurrentEndurance() )
|
|
continue;
|
|
|
|
for( int x = 0; x < ItemBase::MAX_OPTION_NUMBER; ++x )
|
|
{
|
|
if( !SocketBase.nOptType[x] ) continue;
|
|
|
|
if( SocketBase.nOptType[x] == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A )
|
|
{
|
|
ampParameter( SocketBase.fOptVar1[x], SocketBase.fOptVar2[x], true );
|
|
}
|
|
}
|
|
|
|
_amplifyStatByEffect( SocketBase.pvEffectList );
|
|
}
|
|
|
|
// 각성 여부 확인
|
|
if( m_anWear[i]->IsAwaken() )
|
|
{
|
|
for( int nCnt = 0 ; nCnt < ItemInstance::MAX_AWAKEN_NUMBER ; ++nCnt )
|
|
{
|
|
if( !m_anWear[i]->GetAwakenOptionType( nCnt ) )
|
|
break;
|
|
|
|
if( m_anWear[i]->GetAwakenOptionType( nCnt ) == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A )
|
|
{
|
|
ampParameter( m_anWear[i]->GetAwakenOptionValue1( nCnt ), m_anWear[i]->GetAwakenOptionValue2( nCnt ), true );
|
|
}
|
|
else if( m_anWear[i]->GetAwakenOptionType( nCnt ) == ITEM_EFFECT_PASSIVE::APPLY_EFFECT )
|
|
{
|
|
_amplifyStatByEffect( GameContent::GetEffectInfoVector( m_anWear[i]->GetAwakenOptionValue1( nCnt ) ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// 랜덤화 여부 확인
|
|
if( m_anWear[i]->IsIdentified() )
|
|
{
|
|
for( int nCnt = 0 ; nCnt < ItemInstance::MAX_RANDOM_OPTION_NUMBER ; ++nCnt )
|
|
{
|
|
if( !m_anWear[i]->GetIdentifiedOptionType( nCnt ) )
|
|
break;
|
|
|
|
if( m_anWear[i]->GetIdentifiedOptionType( nCnt ) == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A )
|
|
{
|
|
ampParameter( m_anWear[i]->GetIdentifiedOptionValue1( nCnt ), m_anWear[i]->GetIdentifiedOptionValue2( nCnt ), true );
|
|
}
|
|
else if( m_anWear[i]->GetIdentifiedOptionType( nCnt ) == ITEM_EFFECT_PASSIVE::APPLY_EFFECT )
|
|
{
|
|
_amplifyStatByEffect( GameContent::GetEffectInfoVector( m_anWear[i]->GetIdentifiedOptionValue1( nCnt ) ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for( std::vector< SetItemEffectInfo * >::const_iterator itSetItemEffectInfo = m_vSetItemEffect.begin(); itSetItemEffectInfo != m_vSetItemEffect.end(); ++itSetItemEffectInfo )
|
|
{
|
|
for( int x = 0 ; x < ItemBase::MAX_OPTION_NUMBER ; ++x )
|
|
{
|
|
if( !(*itSetItemEffectInfo)->nOptType[x] ) continue;
|
|
|
|
if( (*itSetItemEffectInfo)->nOptType[x] == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A )
|
|
{
|
|
ampParameter( (*itSetItemEffectInfo)->fOptVar1[x], (*itSetItemEffectInfo)->fOptVar2[x], true );
|
|
}
|
|
}
|
|
|
|
_amplifyStatByEffect( (*itSetItemEffectInfo)->pvEffectList );
|
|
}
|
|
}
|
|
|
|
void StructCreature::_amplifyStatByEffect( const std::vector< EffectInfo * > * pvEffectList, float fRatio )
|
|
{
|
|
if( !pvEffectList || pvEffectList->empty() )
|
|
return;
|
|
|
|
for( std::vector< EffectInfo * >::const_iterator it = pvEffectList->begin() ; it != pvEffectList->end() ; ++it )
|
|
{
|
|
if( (*it)->eType != EffectInfo::EFFECT_TYPE_OPTIONAL )
|
|
continue;
|
|
|
|
if( (*it)->nMinLevel && GetLevel() < (*it)->nMinLevel ) continue;
|
|
if( (*it)->nMaxLevel && GetLevel() > (*it)->nMaxLevel ) continue;
|
|
|
|
if( (*it)->fValue[ 0 ] == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A ) ampParameter( (*it)->fValue[ 1 ], (*it)->fValue[ 2 ] * fRatio, true );
|
|
if( (*it)->fValue[ 3 ] == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A ) ampParameter( (*it)->fValue[ 4 ], (*it)->fValue[ 5 ] * fRatio, true );
|
|
if( (*it)->fValue[ 6 ] == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A ) ampParameter( (*it)->fValue[ 7 ], (*it)->fValue[ 8 ] * fRatio, true );
|
|
if( (*it)->fValue[ 9 ] == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A ) ampParameter( (*it)->fValue[ 10 ], (*it)->fValue[ 11 ] * fRatio, true );
|
|
}
|
|
}
|
|
|
|
void StructCreature::applyParamBasedItemEffect()
|
|
{
|
|
// 지속 효과 하나가 파라메터에 기반하여 성능이 바뀌기 때문에 어쩔 수 없이 분리
|
|
// TODO: 차후 스탯 적용 시점과 아이템 효과 적용 시점을 분리할 때 이 함수도 합쳐 볼 방안을 찾아본다
|
|
|
|
// 유닛 익스퍼트는 이미 계산되어 있음
|
|
for( int i = 0; i < ItemBase::MAX_ITEM_WEAR; ++i )
|
|
{
|
|
if( !m_anWear[i] ) continue;
|
|
|
|
// 장착 불가는 효과 없음
|
|
if( !IsWearable( (ItemBase::ItemWearType)i, m_anWear[i] ) ) continue;
|
|
|
|
float fItemRatio = 1.0f;
|
|
|
|
// 유니트 익스퍼트로 입은 아이템.
|
|
if( m_anWear[i]->GetLevelLimit() > GetLevel() && m_anWear[i]->GetLevelLimit() <= m_nUnitExpertLevel ) fItemRatio = 0.4f;
|
|
|
|
const ItemBaseServer & base = m_anWear[i]->GetItemBase();
|
|
|
|
_applyParamBasedEffect( base.pvEffectList );
|
|
|
|
int nSocketCount = m_anWear[i]->GetMaxSocketCount();
|
|
for( int x = 0 ; x < nSocketCount ; ++x )
|
|
{
|
|
ItemBase::ItemCode nSocketCode = m_anWear[i]->GetSocketCode( x );
|
|
|
|
if( !nSocketCode )
|
|
continue;
|
|
|
|
const ItemBaseServer & SocketBase = StructItem::GetItemBase( nSocketCode );
|
|
|
|
// 레벨 제한 적용 가능 검사
|
|
if( GetLevel() < SocketBase.nMinLevel || GetLevel() > SocketBase.nMaxLevel )
|
|
continue;
|
|
|
|
// 소켓 내구도 검사
|
|
if( !m_anWear[i]->GetCurrentEndurance() )
|
|
continue;
|
|
|
|
_applyParamBasedEffect( SocketBase.pvEffectList );
|
|
}
|
|
}
|
|
|
|
for( std::vector< SetItemEffectInfo * >::const_iterator itSetItemEffectInfo = m_vSetItemEffect.begin() ; itSetItemEffectInfo != m_vSetItemEffect.end() ; ++itSetItemEffectInfo )
|
|
{
|
|
_applyParamBasedEffect( (*itSetItemEffectInfo)->pvEffectList );
|
|
}
|
|
}
|
|
|
|
void StructCreature::_applyParamBasedEffect( const std::vector< EffectInfo * > * pvEffectList )
|
|
{
|
|
if( !pvEffectList || pvEffectList->empty() )
|
|
return;
|
|
|
|
for( std::vector< EffectInfo * >::const_iterator it = pvEffectList->begin() ; it != pvEffectList->end() ; ++it )
|
|
{
|
|
EffectInfo * pEffect = (*it);
|
|
if( pEffect->nMinLevel && GetLevel() < pEffect->nMinLevel ) continue;
|
|
if( pEffect->nMaxLevel && GetLevel() > pEffect->nMaxLevel ) continue;
|
|
|
|
if ( pEffect->eType == EffectInfo::EFFECT_TYPE_STATE )
|
|
{
|
|
switch ( pEffect->nEffectID )
|
|
{
|
|
case StructState::EF_INC_DOT_BASED_PARAM:
|
|
{
|
|
c_fixed10 sum = CalcStatSum( pEffect->fValue[12], m_StatBeforeParamBasedCalc )
|
|
+ CalcAttributeSum( pEffect->fValue[12], pEffect->fValue[13], m_AttrBeforeParamBasedCalc );
|
|
int type = pEffect->fValue[0];
|
|
|
|
m_ElementalStateDamageAdder[type] += sum * (pEffect->fValue[1] + pEffect->fValue[2] * pEffect->nEffectLevel);
|
|
m_ElementalStateDamageAmplifier[type] += sum * (pEffect->fValue[3] + pEffect->fValue[4] * pEffect->nEffectLevel);
|
|
|
|
sum = CalcStatSum( pEffect->fValue[14], m_StatBeforeParamBasedCalc )
|
|
+ CalcAttributeSum( pEffect->fValue[14], pEffect->fValue[15], m_AttrBeforeParamBasedCalc );
|
|
|
|
type = pEffect->fValue[6];
|
|
|
|
m_ElementalStateDamageAdder[type] += sum * (pEffect->fValue[7] + pEffect->fValue[8] * pEffect->nEffectLevel);
|
|
m_ElementalStateDamageAmplifier[type] += sum * (pEffect->fValue[9] + pEffect->fValue[10] * pEffect->nEffectLevel);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructCreature::onItemWearEffect( struct StructItem* pItem, bool bIsBaseVar, int type, c_fixed10 var1, c_fixed10 var2, float fRatio )
|
|
{
|
|
// 공속의 경우는 페널티 안받도록 수정
|
|
c_fixed10 item_var_penalty = ( type != ITEM_EFFECT_PASSIVE::ATTACK_SPEED ) ? ( var1 * fRatio ) : var1 ;
|
|
|
|
if( pItem )
|
|
{
|
|
// If it's a basic performance item, penalties are applied to level/durability
|
|
// (In the case of attack speed, it has been modified to not receive penalties.)
|
|
if( bIsBaseVar && type != ITEM_EFFECT_PASSIVE::ATTACK_SPEED )
|
|
{
|
|
item_var_penalty += var2 * ( pItem->GetItemLevel() - 1 );
|
|
item_var_penalty = GameRule::GetItemValue( item_var_penalty, var1, GetLevel(), pItem->GetItemRank(), pItem->GetItemLevel(), pItem->GetItemBase().nMinLevel );
|
|
}
|
|
}
|
|
|
|
// 아이템 사용 효율 설정(공속의 경우는 크리처 아이템 익스퍼트 영향을 안받도록 수정)
|
|
if( type != ITEM_EFFECT_PASSIVE::ATTACK_SPEED )
|
|
item_var_penalty *= m_fItemMod;
|
|
|
|
switch( type )
|
|
{
|
|
case ITEM_EFFECT_PASSIVE::MAGIC_POINT :
|
|
{
|
|
m_Attribute.fMagicPoint += item_var_penalty;
|
|
break;
|
|
}
|
|
case ITEM_EFFECT_PASSIVE::ATTACK_POINT :
|
|
{
|
|
bool bApplyRight = true;
|
|
bool bApplyLeft = false;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
if( pItem && pItem->IsWeapon() )
|
|
{
|
|
if( pItem->GetWearInfo() == ItemBase::WEAR_LEFTHAND )
|
|
{
|
|
bApplyLeft = true;
|
|
bApplyRight = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bApplyLeft = true;
|
|
}
|
|
}
|
|
|
|
if( bApplyLeft )
|
|
{
|
|
m_Attribute.fAttackPointLeft += item_var_penalty;
|
|
//m_nAttackPointLeftByWeapon += item_var_penalty;
|
|
}
|
|
|
|
if( bApplyRight )
|
|
{
|
|
m_Attribute.fAttackPointRight += item_var_penalty;
|
|
//m_nAttackPointRightByWeapon += item_var_penalty;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case ITEM_EFFECT_PASSIVE::BLOCK_DEFENCE : m_Attribute.fBlockDefence += item_var_penalty; break;
|
|
case ITEM_EFFECT_PASSIVE::DEFENCE : m_Attribute.fDefence += item_var_penalty; break;
|
|
case ITEM_EFFECT_PASSIVE::ACCURACY :
|
|
{
|
|
bool bApplyRight = true;
|
|
bool bApplyLeft = false;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
if( pItem && pItem->IsWeapon() )
|
|
{
|
|
if(pItem->GetWearInfo() == ItemBase::WEAR_LEFTHAND )
|
|
{
|
|
bApplyLeft = true;
|
|
bApplyRight = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bApplyLeft = true;
|
|
}
|
|
}
|
|
|
|
if( bApplyLeft )
|
|
{
|
|
m_Attribute.fAccuracyLeft += item_var_penalty;
|
|
}
|
|
|
|
if( bApplyRight )
|
|
{
|
|
m_Attribute.fAccuracyRight += item_var_penalty;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case ITEM_EFFECT_PASSIVE::ATTACK_SPEED :
|
|
{
|
|
// 이도류 일 때는 양손 각 장비를 따로, 손에 착용한게 아닐 경우 양손 모두 적용
|
|
bool bApplyRight = true;
|
|
bool bApplyLeft = false;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
if( pItem && pItem->IsWeapon() )
|
|
{
|
|
if( pItem->GetWearInfo() == ItemBase::WEAR_LEFTHAND )
|
|
{
|
|
bApplyLeft = true;
|
|
bApplyRight = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bApplyLeft = true;
|
|
}
|
|
}
|
|
|
|
if( bApplyLeft )
|
|
{
|
|
m_Attribute.fAttackSpeedLeft += item_var_penalty;
|
|
}
|
|
|
|
if( bApplyRight )
|
|
{
|
|
m_Attribute.fAttackSpeedRight += item_var_penalty;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case ITEM_EFFECT_PASSIVE::MAGIC_DEFENCE : m_Attribute.fMagicDefence += item_var_penalty; break;
|
|
case ITEM_EFFECT_PASSIVE::AVOID : m_Attribute.fAvoid += item_var_penalty; break;
|
|
case ITEM_EFFECT_PASSIVE::MOVE_SPEED :
|
|
if( !isMoveSpeedFixed() ) // fRidingSpeed 수치가 생기면서 라이딩 중에도 기본 속도에 관여할 수 있게 변경 ( 2013-12-20 )
|
|
{
|
|
m_Attribute.fMoveSpeed += item_var_penalty;
|
|
}
|
|
break;
|
|
case ITEM_EFFECT_PASSIVE::BLOCK_CHANGE : m_Attribute.fBlockChance += item_var_penalty; break;
|
|
case ITEM_EFFECT_PASSIVE::CARRY_WEIGHT : m_Attribute.fMaxWeight += item_var_penalty; break;
|
|
case ITEM_EFFECT_PASSIVE::CASTING_SPEED : m_Attribute.fCastingSpeed += item_var_penalty; break;
|
|
case ITEM_EFFECT_PASSIVE::MAGIC_ACCURACY: m_Attribute.fMagicAccuracy += item_var_penalty; break;
|
|
case ITEM_EFFECT_PASSIVE::MAGIC_AVOID : m_Attribute.fMagicAvoid += item_var_penalty; break;
|
|
case ITEM_EFFECT_PASSIVE::COOLTIME_SPEED: m_Attribute.fCoolTimeSpeed += item_var_penalty; break;
|
|
case ITEM_EFFECT_PASSIVE::MAX_HP : m_nMaxHP += int( item_var_penalty ); break;
|
|
case ITEM_EFFECT_PASSIVE::MAX_MP : m_nMaxMP += int( item_var_penalty ); break;
|
|
case ITEM_EFFECT_PASSIVE::MP_REGEN_POINT: m_Attribute.fMPRegenPoint += item_var_penalty; break;
|
|
|
|
case ITEM_EFFECT_PASSIVE::BOW_INTERVAL : m_fBowInterval = var1; break;
|
|
case ITEM_EFFECT_PASSIVE::INC_PARAMETER_A: incParameter( var1, var2, false ); break;
|
|
case ITEM_EFFECT_PASSIVE::INC_PARAMETER_B: incParameter2( var1, var2 ); break;
|
|
case ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A: ampParameter( var1, var2, false ); break;
|
|
case ITEM_EFFECT_PASSIVE::AMP_PARAMETER_B: ampParameter2( var1, var2 ); break;
|
|
|
|
case ITEM_EFFECT_PASSIVE::INC_DOUBLE_ATTACK: m_Attribute.fDoubleAttackRatio += (float)(var2 / 100); break;
|
|
case ITEM_EFFECT_PASSIVE::INC_COOLTIME_SPEED: m_Attribute.fCoolTimeSpeed *= ( 100 - var2 ) / 100; break;
|
|
case ITEM_EFFECT_PASSIVE::INC_CASTING_SPEED: m_Attribute.fCastingSpeed *= ( 100 + var2) / 100; break;
|
|
case ITEM_EFFECT_PASSIVE::RESIST_NEGATIVE: m_Attribute.fStunResistance += (float)(var2 / 100); break;
|
|
case ITEM_EFFECT_PASSIVE::INC_CREATURE_FCM: m_fSummonFCM *= (100 + var2) / 100; break;
|
|
|
|
|
|
case ITEM_EFFECT_PASSIVE::INC_FZEXP: m_fEXPMod += var2 ; break;
|
|
|
|
case ITEM_EFFECT_PASSIVE::INC_ALL_SKILL: addSkill(8, var2, 68, true); break;
|
|
|
|
case ITEM_EFFECT_PASSIVE::ADD_STATE_BY_EQUIP_ITEM:
|
|
{
|
|
AR_TIME t = GetArTime();
|
|
int nStateCode = 44000000 ;
|
|
int nStateLevel = 1 ;
|
|
if (nStateCode != 0 && GetState(static_cast<StructState::StateCode>(nStateCode)) == NULL)
|
|
{
|
|
if (IsSummon())
|
|
{
|
|
//GetSummonName();
|
|
std::string szMainSummonName ;
|
|
|
|
XStringUtil::Format(szMainSummonName, "%s|%d", GetName(), (int)var2 );
|
|
|
|
PendAddStateByItem((StructState::StateCode) nStateCode , GetHandle(), nStateLevel+ (int)var2 , t, t + SkillBase::TOGGLE_TRANSFORMATION , true , (int) var1 , szMainSummonName.c_str() , false );
|
|
}
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case ITEM_EFFECT_PASSIVE::INC_FIRE_DAMAGE: m_BadPhysicalElementalSkillStateMod[Elemental::TYPE_FIRE].apply( (var2 / 100), (var2 / 100), 0, 0, 0, 0, 0, 0, StructState::STATE_EMPTY); break;
|
|
case ITEM_EFFECT_PASSIVE::INC_WATER_DAMAGE: m_BadPhysicalElementalSkillStateMod[Elemental::TYPE_WATER].apply((var2 / 100), (var2 / 100), 0, 0, 0, 0, 0, 0, StructState::STATE_EMPTY); break;
|
|
case ITEM_EFFECT_PASSIVE::INC_WIND_DAMAGE: m_BadPhysicalElementalSkillStateMod[Elemental::TYPE_WIND].apply((var2 / 100), (var2 / 100), 0, 0, 0, 0, 0, 0, StructState::STATE_EMPTY); break;
|
|
case ITEM_EFFECT_PASSIVE::INC_EARTH_DAMAGE: m_BadPhysicalElementalSkillStateMod[Elemental::TYPE_EARTH].apply((var2 / 100), (var2 / 100), 0, 0, 0, 0, 0, 0, StructState::STATE_EMPTY); break;
|
|
case ITEM_EFFECT_PASSIVE::INC_LIGHT_DAMAGE: m_BadPhysicalElementalSkillStateMod[Elemental::TYPE_LIGHT].apply((var2 / 100), (var2 / 100), 0, 0, 0, 0, 0, 0, StructState::STATE_EMPTY); break;
|
|
case ITEM_EFFECT_PASSIVE::INC_DARK_DAMAGE: m_BadPhysicalElementalSkillStateMod[Elemental::TYPE_DARK].apply((var2 / 100), (var2 / 100), 0, 0, 0, 0, 0, 0, StructState::STATE_EMPTY); break;
|
|
|
|
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
|
|
void StructPlayer::onItemWearEffect( struct StructItem* pItem, bool bIsBaseVar, int type, c_fixed10 var1, c_fixed10 var2, float fItemRatio )
|
|
{
|
|
switch( type )
|
|
{
|
|
case ITEM_EFFECT_PASSIVE::MAX_CHAOS :
|
|
{
|
|
if( pItem->IsChaosStone() )
|
|
{
|
|
m_nMaxChaos += int(var1) + int(var2) * ( pItem->GetItemLevel() + 10 * pItem->GetItemEnhance() );
|
|
}
|
|
}
|
|
break;
|
|
default: StructCreature::onItemWearEffect( pItem, bIsBaseVar, type, var1, var2, fItemRatio ); break;
|
|
}
|
|
}
|
|
|
|
void StructSummon::onItemWearEffect( struct StructItem* pItem, bool bIsBaseVar, int type, c_fixed10 var1, c_fixed10 var2, float fRatio )
|
|
{
|
|
if( bIsBaseVar && GameRule::nItemExpertCube )
|
|
{
|
|
switch( type )
|
|
{
|
|
case ITEM_EFFECT_PASSIVE::ATTACK_POINT: var1 = var1 * m_fBaseAttackPointRatio; var2 = var2 * m_fBaseAttackPointRatio; break;
|
|
case ITEM_EFFECT_PASSIVE::MAGIC_POINT: var1 = var1 * m_fBaseMagicPointRatio; var2 = var2 * m_fBaseMagicPointRatio; break;
|
|
case ITEM_EFFECT_PASSIVE::DEFENCE: var1 = var1 * m_fBaseDefenceRatio; var2 = var2 * m_fBaseDefenceRatio; break;
|
|
case ITEM_EFFECT_PASSIVE::MAGIC_DEFENCE: var1 = var1 * m_fBaseMagicDefenceRatio; var2 = var2 * m_fBaseMagicDefenceRatio; break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
StructCreature::onItemWearEffect( pItem, bIsBaseVar, type, var1, var2, fRatio );
|
|
}
|
|
|
|
void StructPlayer::applyStatByTitle()
|
|
{
|
|
// 주 호칭
|
|
if( GetMainTitle() )
|
|
{
|
|
const TitleBaseServer * base = GetMainTitle();
|
|
|
|
for( int i = 0; i < TitleBase::MAX_OPTION_NUMBER; i++ )
|
|
{
|
|
if( !base->nOptType[i] ) continue;
|
|
|
|
if( base->nOptType[i] == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A )
|
|
{
|
|
incParameter( base->fOptVar1[i], base->fOptVar2[i], true );
|
|
}
|
|
|
|
// 스킬의 변화도 스탯에 영향을 미치므로 함께 변경한다.
|
|
_applyStatByEffect( base->pvEffectList );
|
|
_applySkillByEffect( base->pvEffectList );
|
|
}
|
|
}
|
|
|
|
// 부 호칭
|
|
for( int i = 0; i < GameRule::SUB_TITLE_COUNT; i++ )
|
|
{
|
|
const TitleBaseServer * base = GetSubTitle( i );
|
|
|
|
if( !base )
|
|
continue;
|
|
|
|
for( int x = 0; x < TitleBase::MAX_OPTION_NUMBER; x++ )
|
|
{
|
|
if( !base->nOptType[x] ) continue;
|
|
|
|
// 부 호칭으로 사용 시에는 성능의 10%만을 적용한다.
|
|
if( base->nOptType[x] == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A )
|
|
{
|
|
incParameter( base->fOptVar1[x], base->fOptVar2[x] * GameRule::SUB_TITLE_RATE, true );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructPlayer::amplifyStatByTitle()
|
|
{
|
|
// 주 호칭
|
|
if( GetMainTitle() )
|
|
{
|
|
const TitleBaseServer * base = GetMainTitle();
|
|
|
|
for( int i = 0; i < TitleBase::MAX_OPTION_NUMBER; i++ )
|
|
{
|
|
if( !base->nOptType[i] ) continue;
|
|
|
|
if( base->nOptType[i] == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A )
|
|
{
|
|
ampParameter( base->fOptVar1[i], base->fOptVar2[i], true );
|
|
}
|
|
|
|
_amplifyStatByEffect( base->pvEffectList );
|
|
}
|
|
}
|
|
|
|
// 부 호칭
|
|
for( int i = 0; i < GameRule::SUB_TITLE_COUNT; i++ )
|
|
{
|
|
const TitleBaseServer * base = GetSubTitle( i );
|
|
|
|
if( !base )
|
|
continue;
|
|
|
|
for( int x = 0; x < TitleBase::MAX_OPTION_NUMBER; x++ )
|
|
{
|
|
if( !base->nOptType[x] ) continue;
|
|
|
|
// 부 호칭으로 사용 시에는 성능의 10%만을 적용한다.
|
|
if( base->nOptType[x] == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A )
|
|
{
|
|
ampParameter( base->fOptVar1[x], base->fOptVar2[x] * GameRule::SUB_TITLE_RATE, true );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void StructPlayer::applyTitleEffect()
|
|
{
|
|
// 주 호칭
|
|
if( GetMainTitle() )
|
|
{
|
|
const TitleBaseServer * base = GetMainTitle();
|
|
|
|
for( int i = 0; i < TitleBase::MAX_OPTION_NUMBER; i++ )
|
|
{
|
|
if( !base->nOptType[i] ) continue;
|
|
|
|
onItemWearEffect( NULL, false, base->nOptType[i], base->fOptVar1[i], base->fOptVar2[i], 1.0f );
|
|
}
|
|
|
|
_applyEffect( NULL, base->pvEffectList, 1.0f );
|
|
}
|
|
|
|
// 부 호칭
|
|
for( int i = 0; i < GameRule::SUB_TITLE_COUNT; i++ )
|
|
{
|
|
const TitleBaseServer * base = GetSubTitle( i );
|
|
|
|
if( !base )
|
|
continue;
|
|
|
|
for( int x = 0; x < TitleBase::MAX_OPTION_NUMBER; x++ )
|
|
{
|
|
if( !base->nOptType[x] ) continue;
|
|
|
|
onItemWearEffect( NULL, false, base->nOptType[i], base->fOptVar1[i], base->fOptVar2[i], GameRule::SUB_TITLE_RATE );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void StructCreature::applyDoubleWeaponEffect()
|
|
{
|
|
// From ZONE source; dual crossbows
|
|
StructSkill* pSkill = NULL;
|
|
|
|
if (IsUsingDoubleWeapon())
|
|
{
|
|
|
|
int nExpertSkillLevel = 1;
|
|
|
|
<<<<<<< HEAD
|
|
if( GetWearedItem( ItemBase::WEAR_LEFTHAND )->GetItemClass() == ItemBase::CLASS_ONEHAND_SWORD &&
|
|
GetWearedItem( ItemBase::WEAR_RIGHTHAND )->GetItemClass() == ItemBase::CLASS_ONEHAND_SWORD ) // 한손검 이도류
|
|
{
|
|
pSkill = GetCurrentPassiveSkill( StructSkill::SKILL_DUAL_SWORD_EXPERT );
|
|
|
|
if( !pSkill )
|
|
{
|
|
pSkill = GetCurrentPassiveSkill( StructSkill::SKILL_TWIN_BLADE_EXPERT );
|
|
}
|
|
|
|
if( pSkill )
|
|
{
|
|
nExpertSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
}
|
|
}
|
|
else if( GetWearedItem( ItemBase::WEAR_LEFTHAND )->GetItemClass() == ItemBase::CLASS_DAGGER &&
|
|
GetWearedItem( ItemBase::WEAR_RIGHTHAND )->GetItemClass() == ItemBase::CLASS_DAGGER ) // 쌍단검
|
|
{
|
|
pSkill = GetCurrentPassiveSkill( StructSkill::SKILL_TWIN_BLADE_EXPERT );
|
|
|
|
if( pSkill )
|
|
{
|
|
nExpertSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
}
|
|
}
|
|
else if( GetWearedItem( ItemBase::WEAR_LEFTHAND )->GetItemClass() == ItemBase::CLASS_ONEHAND_AXE &&
|
|
GetWearedItem( ItemBase::WEAR_RIGHTHAND )->GetItemClass() == ItemBase::CLASS_ONEHAND_AXE ) // 쌍도끼
|
|
{
|
|
pSkill = GetCurrentPassiveSkill( StructSkill::SKILL_TWIN_AXE_EXPERT );
|
|
|
|
if (pSkill)
|
|
{
|
|
nExpertSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
}
|
|
}
|
|
else if (GetWearedItem(ItemBase::WEAR_LEFTHAND)->GetItemClass() == ItemBase::CLASS_CROSSBOW &&
|
|
GetWearedItem(ItemBase::WEAR_RIGHTHAND)->GetItemClass() == ItemBase::CLASS_CROSSBOW) // ½Öµµ³¢
|
|
=======
|
|
if (GetWearedItem(ItemBase::WEAR_LEFTHAND)->GetItemClass() == ItemBase::CLASS_ONEHAND_SWORD &&
|
|
GetWearedItem(ItemBase::WEAR_RIGHTHAND)->GetItemClass() == ItemBase::CLASS_ONEHAND_SWORD) // ÇÑ¼Õ°Ë À̵µ·ù
|
|
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
|
|
{
|
|
pSkill = GetCurrentPassiveSkill(StructSkill::SKILL_DUAL_SWORD_EXPERT);
|
|
|
|
if (!pSkill)
|
|
{
|
|
pSkill = GetCurrentPassiveSkill(StructSkill::SKILL_TWIN_BLADE_EXPERT);
|
|
}
|
|
|
|
if (pSkill)
|
|
{
|
|
nExpertSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
}
|
|
<<<<<<< HEAD
|
|
=======
|
|
}
|
|
else if (GetWearedItem(ItemBase::WEAR_LEFTHAND)->GetItemClass() == ItemBase::CLASS_DAGGER &&
|
|
GetWearedItem(ItemBase::WEAR_RIGHTHAND)->GetItemClass() == ItemBase::CLASS_DAGGER) // ½Ö´Ü°Ë
|
|
{
|
|
pSkill = GetCurrentPassiveSkill(StructSkill::SKILL_TWIN_BLADE_EXPERT);
|
|
>>>>>>> a34328224e914a577b99c79ec6e8ffbcea554a05
|
|
|
|
if (pSkill)
|
|
{
|
|
nExpertSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
}
|
|
}
|
|
else if (GetWearedItem(ItemBase::WEAR_LEFTHAND)->GetItemClass() == ItemBase::CLASS_ONEHAND_AXE &&
|
|
GetWearedItem(ItemBase::WEAR_RIGHTHAND)->GetItemClass() == ItemBase::CLASS_ONEHAND_AXE) // ½Öµµ³¢
|
|
{
|
|
pSkill = GetCurrentPassiveSkill(StructSkill::SKILL_TWIN_AXE_EXPERT);
|
|
|
|
if (pSkill)
|
|
{
|
|
nExpertSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
}
|
|
}
|
|
|
|
m_nDoubleWeaponMasteryLevel = nExpertSkillLevel;
|
|
|
|
c_fixed10 fBase, fAddPerLevel;
|
|
fBase.set(7500);
|
|
fAddPerLevel.set(50);
|
|
m_Attribute.fAttackSpeedRight = (fBase + fAddPerLevel * nExpertSkillLevel) * m_Attribute.fAttackSpeedRight;
|
|
m_Attribute.fAttackSpeedLeft = (fBase + fAddPerLevel * nExpertSkillLevel) * m_Attribute.fAttackSpeedLeft;
|
|
m_Attribute.fAttackSpeed = (m_Attribute.fAttackSpeedRight + m_Attribute.fAttackSpeedLeft) * 0.5f;
|
|
m_AttributeByState.fAttackSpeedRight = (c_fixed10(0.75f) + c_fixed10(0.005f) * nExpertSkillLevel) * m_AttributeByState.fAttackSpeedRight;
|
|
m_AttributeByState.fAttackSpeedLeft = (c_fixed10(0.75f) + c_fixed10(0.005f) * nExpertSkillLevel) * m_AttributeByState.fAttackSpeedLeft;
|
|
m_AttributeByState.fAttackSpeed = (m_AttributeByState.fAttackSpeedRight + m_AttributeByState.fAttackSpeedLeft) * 0.5f;
|
|
|
|
fBase.set(8900);
|
|
fAddPerLevel.set(100);
|
|
m_Attribute.fAccuracyRight = (fBase + fAddPerLevel * nExpertSkillLevel) * m_Attribute.fAccuracyRight;
|
|
m_AttributeByState.fAccuracyRight = (fBase + fAddPerLevel * nExpertSkillLevel) * m_AttributeByState.fAccuracyRight;
|
|
m_Attribute.fAccuracyLeft = (fBase + fAddPerLevel * nExpertSkillLevel) * m_Attribute.fAccuracyLeft;
|
|
m_AttributeByState.fAccuracyLeft = (fBase + fAddPerLevel * nExpertSkillLevel) * m_AttributeByState.fAccuracyLeft;
|
|
|
|
fBase.set(9000);
|
|
fAddPerLevel.set(100);
|
|
m_Attribute.fAttackPointRight = (fBase + fAddPerLevel * nExpertSkillLevel) * m_Attribute.fAttackPointRight;
|
|
m_AttributeByState.fAttackPointRight = (fBase + fAddPerLevel * nExpertSkillLevel) * m_AttributeByState.fAttackPointRight;
|
|
m_fAttackPointRightWithoutWeapon = (fBase + fAddPerLevel * nExpertSkillLevel) * m_fAttackPointRightWithoutWeapon;
|
|
fBase.set(4400);
|
|
fAddPerLevel.set(200);
|
|
m_Attribute.fAttackPointLeft = (fBase + fAddPerLevel * nExpertSkillLevel) * m_Attribute.fAttackPointLeft;
|
|
m_AttributeByState.fAttackPointLeft = (fBase + fAddPerLevel * nExpertSkillLevel) * m_AttributeByState.fAttackPointLeft;
|
|
m_fAttackPointLeftWithoutWeapon = (fBase + fAddPerLevel * nExpertSkillLevel) * m_fAttackPointLeftWithoutWeapon;
|
|
}
|
|
else
|
|
{
|
|
m_Attribute.fAttackSpeed = m_Attribute.fAttackSpeedRight;
|
|
m_AttributeByState.fAttackSpeed = m_AttributeByState.fAttackSpeedRight;
|
|
}
|
|
}
|
|
|
|
// --- 기타 예외적인 처리 ---
|
|
//void StructCreature::applyDoubleWeaponEffect()
|
|
//{
|
|
// // T.T 눈물을 머금고 예외처리.
|
|
// StructSkill* pSkill = NULL;
|
|
//
|
|
// if( IsUsingDoubleWeapon() )
|
|
// {
|
|
//
|
|
// int nExpertSkillLevel = 1;
|
|
//
|
|
// if( GetWearedItem( ItemBase::WEAR_LEFTHAND )->GetItemClass() == ItemBase::CLASS_ONEHAND_SWORD &&
|
|
// GetWearedItem( ItemBase::WEAR_RIGHTHAND )->GetItemClass() == ItemBase::CLASS_ONEHAND_SWORD ) // 한손검 이도류
|
|
// {
|
|
// pSkill = GetCurrentPassiveSkill( StructSkill::SKILL_DUAL_SWORD_EXPERT );
|
|
//
|
|
// if( !pSkill )
|
|
// {
|
|
// pSkill = GetCurrentPassiveSkill( StructSkill::SKILL_TWIN_BLADE_EXPERT );
|
|
// }
|
|
//
|
|
// if( pSkill )
|
|
// {
|
|
// nExpertSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
// }
|
|
// }
|
|
// else if( GetWearedItem( ItemBase::WEAR_LEFTHAND )->GetItemClass() == ItemBase::CLASS_DAGGER &&
|
|
// GetWearedItem( ItemBase::WEAR_RIGHTHAND )->GetItemClass() == ItemBase::CLASS_DAGGER ) // 쌍단검
|
|
// {
|
|
// pSkill = GetCurrentPassiveSkill( StructSkill::SKILL_TWIN_BLADE_EXPERT );
|
|
//
|
|
// if( pSkill )
|
|
// {
|
|
// nExpertSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
// }
|
|
// }
|
|
// else if( GetWearedItem( ItemBase::WEAR_LEFTHAND )->GetItemClass() == ItemBase::CLASS_ONEHAND_AXE &&
|
|
// GetWearedItem( ItemBase::WEAR_RIGHTHAND )->GetItemClass() == ItemBase::CLASS_ONEHAND_AXE ) // 쌍도끼
|
|
// {
|
|
// pSkill = GetCurrentPassiveSkill( StructSkill::SKILL_TWIN_AXE_EXPERT );
|
|
//
|
|
//
|
|
// // AziaMafia Double Arba
|
|
// /*if (pSkill)
|
|
// {
|
|
// nExpertSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
// }
|
|
// */
|
|
//
|
|
// if (pSkill)
|
|
// {
|
|
// nExpertSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
// }
|
|
// }
|
|
// else if (GetWearedItem(ItemBase::WEAR_LEFTHAND)->GetItemClass() == ItemBase::CLASS_CROSSBOW &&
|
|
// GetWearedItem(ItemBase::WEAR_RIGHTHAND)->GetItemClass() == ItemBase::CLASS_CROSSBOW) // ½Öµµ³¢
|
|
// {
|
|
// pSkill = GetCurrentPassiveSkill(StructSkill::SKILL_DUAL_SWORD_EXPERT);
|
|
//
|
|
// if (pSkill)
|
|
// {
|
|
// nExpertSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
// }
|
|
// //END
|
|
//
|
|
// }
|
|
//
|
|
// m_nDoubleWeaponMasteryLevel = nExpertSkillLevel;
|
|
//
|
|
// c_fixed10 fBase, fAddPerLevel;
|
|
// fBase.set( 7500 );
|
|
// fAddPerLevel.set( 50 );
|
|
// m_Attribute.fAttackSpeedRight = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_Attribute.fAttackSpeedRight;
|
|
// m_Attribute.fAttackSpeedLeft = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_Attribute.fAttackSpeedLeft;
|
|
// m_Attribute.fAttackSpeed = ( m_Attribute.fAttackSpeedRight + m_Attribute.fAttackSpeedLeft ) * 0.5f;
|
|
// m_AttributeByState.fAttackSpeedRight = ( c_fixed10( 0.75f ) + c_fixed10( 0.005f ) * nExpertSkillLevel ) * m_AttributeByState.fAttackSpeedRight;
|
|
// m_AttributeByState.fAttackSpeedLeft = ( c_fixed10( 0.75f ) + c_fixed10( 0.005f ) * nExpertSkillLevel ) * m_AttributeByState.fAttackSpeedLeft;
|
|
// m_AttributeByState.fAttackSpeed = ( m_AttributeByState.fAttackSpeedRight + m_AttributeByState.fAttackSpeedLeft ) * 0.5f;
|
|
//
|
|
// fBase.set( 8900 );
|
|
// fAddPerLevel.set( 100 );
|
|
// m_Attribute.fAccuracyRight = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_Attribute.fAccuracyRight;
|
|
// m_AttributeByState.fAccuracyRight = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_AttributeByState.fAccuracyRight;
|
|
// m_Attribute.fAccuracyLeft = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_Attribute.fAccuracyLeft;
|
|
// m_AttributeByState.fAccuracyLeft = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_AttributeByState.fAccuracyLeft;
|
|
//
|
|
// fBase.set( 9000 );
|
|
// fAddPerLevel.set( 100 );
|
|
// m_Attribute.fAttackPointRight = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_Attribute.fAttackPointRight;
|
|
// m_AttributeByState.fAttackPointRight = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_AttributeByState.fAttackPointRight;
|
|
// m_fAttackPointRightWithoutWeapon = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_fAttackPointRightWithoutWeapon;
|
|
// fBase.set( 4400 );
|
|
// fAddPerLevel.set( 200 );
|
|
// m_Attribute.fAttackPointLeft = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_Attribute.fAttackPointLeft;
|
|
// m_AttributeByState.fAttackPointLeft = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_AttributeByState.fAttackPointLeft;
|
|
// m_fAttackPointLeftWithoutWeapon = ( fBase + fAddPerLevel * nExpertSkillLevel ) * m_fAttackPointLeftWithoutWeapon;
|
|
// }
|
|
// else
|
|
// {
|
|
// m_Attribute.fAttackSpeed = m_Attribute.fAttackSpeedRight;
|
|
// m_AttributeByState.fAttackSpeed = m_AttributeByState.fAttackSpeedRight;
|
|
// }
|
|
//}
|
|
|
|
void StructCreature::applyJobLevelBonus()
|
|
{
|
|
}
|
|
|
|
void StructPlayer::applyJobLevelBonus()
|
|
{
|
|
if( !GetJobId() )
|
|
return;
|
|
|
|
int depth = GetJobDepth();
|
|
int jobs[GameRule::MAX_JOB_DEPTH];
|
|
int levels[GameRule::MAX_JOB_DEPTH];
|
|
|
|
int i;
|
|
|
|
for( i = 0; i < depth; ++i )
|
|
{
|
|
jobs[i] = GetPrevJobId( i );
|
|
levels[i] = GetPrevJobLevel( i );
|
|
}
|
|
|
|
jobs[i] = GetJobId();
|
|
levels[i] = GetJobLevel();
|
|
|
|
|
|
CreatureStat stat = GameContent::GetJobLevelBonus( depth, jobs, levels );
|
|
|
|
m_Stat.strength += stat.strength;
|
|
m_Stat.vital += stat.vital;
|
|
m_Stat.dexterity += stat.dexterity;
|
|
m_Stat.agility += stat.agility;
|
|
m_Stat.intelligence += stat.intelligence;
|
|
m_Stat.mentality += stat.mentality;
|
|
m_Stat.luck += stat.luck;
|
|
}
|
|
|
|
void StructSummon::applyJobLevelBonus()
|
|
{
|
|
CreatureStat stat = GameContent::GetSummonLevelBonus( GetSummonCode(), GetTransformLevel(), GetLevel() );
|
|
|
|
m_Stat.strength += stat.strength;
|
|
m_Stat.vital += stat.vital;
|
|
m_Stat.dexterity += stat.dexterity;
|
|
m_Stat.agility += stat.agility;
|
|
m_Stat.intelligence += stat.intelligence;
|
|
m_Stat.mentality += stat.mentality;
|
|
m_Stat.luck += stat.luck;
|
|
}
|
|
|
|
void StructCreature::synchronizeParameter( const int bitset, const c_fixed10 & rate )
|
|
{
|
|
if( bitset == 0 ) return;
|
|
std::vector< std::pair< int, std::pair< c_fixed10, int > > >::iterator it;
|
|
|
|
for( it = m_vSynchronizedParameter.begin(); it != m_vSynchronizedParameter.end(); it++ )
|
|
{
|
|
int nBitset = (*it).first;
|
|
if( ( nBitset & bitset ) != 0 )
|
|
{
|
|
c_fixed10 prevRate = (*it).second.first;
|
|
int count = (*it).second.second;
|
|
|
|
(*it).first |= bitset;
|
|
(*it).second.first = ( prevRate * count + rate ) / ( count + 1 );
|
|
(*it).second.second++;
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
m_vSynchronizedParameter.push_back( std::make_pair( bitset, std::make_pair( rate, 1 ) ) );
|
|
}
|
|
|
|
|
|
|
|
void StructCreature::addSkill( const int id, const int added_level, const int skill_type, const bool bRace )
|
|
{
|
|
if( id == 0 || added_level == 0 ) return;
|
|
|
|
std::vector< std::pair< int, int > >::iterator it;
|
|
|
|
if( bRace )
|
|
{
|
|
int race_id = id;
|
|
|
|
// 적용 대상이 모든 스킬이거나 종족이 해당된다면 스킬을 증가시킨다.
|
|
if( race_id & StructState::FLAG_ALL
|
|
|| ( (race_id & StructState::FLAG_ASURA) && (GetRace() == JobInfo::ASURA) )
|
|
|| ( (race_id & StructState::FLAG_DEVA) && (GetRace() == JobInfo::DEVA) )
|
|
|| ( (race_id & StructState::FLAG_GAIA) && (GetRace() == JobInfo::GAIA) )
|
|
|
|
|| ((race_id & StructState::FLAG_CREATURE)
|
|
&& (GetRace() != JobInfo::ASURA)
|
|
&& (GetRace() != JobInfo::DEVA)
|
|
&& (GetRace() != JobInfo::GAIA)
|
|
)
|
|
)
|
|
{
|
|
|
|
for( it = m_vAddedSkillBySkillType.begin(); it != m_vAddedSkillBySkillType.end(); it++ )
|
|
if( (*it).first == skill_type )
|
|
break;
|
|
|
|
if( it == m_vAddedSkillBySkillType.end() )
|
|
{
|
|
m_vAddedSkillBySkillType.push_back( std::make_pair( skill_type, added_level ) );
|
|
}
|
|
else
|
|
(*it).second += added_level;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 양수일 경우에는 스킬 ID
|
|
if( id > 0 )
|
|
{
|
|
int skill_id = id;
|
|
|
|
for( it = m_vAddedSkillBySkillId.begin(); it != m_vAddedSkillBySkillId.end(); it++ )
|
|
if( (*it).first == skill_id )
|
|
break;
|
|
|
|
if( it == m_vAddedSkillBySkillId.end() )
|
|
m_vAddedSkillBySkillId.push_back( std::make_pair( skill_id, added_level ) );
|
|
else
|
|
(*it).second += added_level;
|
|
}
|
|
// 음수일 경우 직업 ID
|
|
else if( id < 0 )
|
|
{
|
|
int job_id = -id;
|
|
|
|
// 자신의 직업이나 하위 직업 효과라면 적용
|
|
for( int j = 0; j <= GetJobDepth(); j++ )
|
|
{
|
|
int creatureJobId = GetPrevJobId( j );
|
|
if( !creatureJobId ) creatureJobId = GetJobId();
|
|
|
|
if( job_id == creatureJobId )
|
|
{
|
|
for( it = m_vAddedSkillBySkillType.begin(); it != m_vAddedSkillBySkillType.end(); it++ )
|
|
if( (*it).first == skill_type )
|
|
break;
|
|
|
|
if( it == m_vAddedSkillBySkillType.end() )
|
|
m_vAddedSkillBySkillType.push_back( std::make_pair( skill_type, added_level ) );
|
|
else
|
|
(*it).second += added_level;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructCreature::checkAdditionalItemEffect()
|
|
{
|
|
// 세트 아이템, 세트 소울스톤의 세트 착용 정보 수집 맵
|
|
SetPartFlagMap mapSetPartFlag;
|
|
|
|
for( int nWearIndex = ItemBase::WEAR_WEAPON ; nWearIndex < ItemBase::MAX_ITEM_WEAR ; ++nWearIndex )
|
|
{
|
|
StructItem * pEquipment = m_anWear[nWearIndex];
|
|
|
|
if( !pEquipment ) continue;
|
|
|
|
// 세트 아이템 착용 정보 수집
|
|
if( nWearIndex >= ItemBase::WEAR_WEAPON && nWearIndex < ItemBase::MAX_ITEM_WEAR )
|
|
{
|
|
if( pEquipment && pEquipment->GetSetItemID() )
|
|
{
|
|
if( mapSetPartFlag.empty() )
|
|
{
|
|
mapSetPartFlag.insert( std::make_pair( pEquipment->GetSetItemID(), pEquipment->GetSetItemPartFlag() ) );
|
|
}
|
|
else
|
|
{
|
|
SetPartFlagMap::iterator itSetPartFlag = mapSetPartFlag.find( pEquipment->GetSetItemID() );
|
|
if( itSetPartFlag == mapSetPartFlag.end() )
|
|
{
|
|
mapSetPartFlag.insert( std::make_pair( pEquipment->GetSetItemID(), pEquipment->GetSetItemPartFlag() ) );
|
|
}
|
|
else
|
|
{
|
|
(*itSetPartFlag).second |= pEquipment->GetSetItemPartFlag();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 세트 소울스톤 착용 정보 수집
|
|
for( int nSocketIndex = 0 ; nSocketIndex < pEquipment->GetMaxSocketCount() ; ++nSocketIndex )
|
|
{
|
|
ItemBase::ItemCode nSocketCode = pEquipment->GetSocketCode( nSocketIndex );
|
|
|
|
if( !nSocketCode )
|
|
continue;
|
|
|
|
const ItemBase & SocketBase = StructItem::GetItemBase( nSocketCode );
|
|
|
|
// 레벨 제한 적용 가능 검사
|
|
if( GetLevel() < SocketBase.nMinLevel || GetLevel() > SocketBase.nMaxLevel )
|
|
continue;
|
|
|
|
// 소켓 내구도 검사
|
|
if( !pEquipment->GetCurrentEndurance() )
|
|
continue;
|
|
|
|
if( SocketBase.nSetID )
|
|
{
|
|
if( mapSetPartFlag.empty() )
|
|
{
|
|
mapSetPartFlag.insert( std::make_pair( SocketBase.nSetID, SocketBase.nSetPartFlag ) );
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
SetPartFlagMap::iterator itSetPartFlag = mapSetPartFlag.find( SocketBase.nSetID );
|
|
if( itSetPartFlag == mapSetPartFlag.end() )
|
|
{
|
|
mapSetPartFlag.insert( std::make_pair( SocketBase.nSetID, SocketBase.nSetPartFlag ) );
|
|
}
|
|
else
|
|
{
|
|
(*itSetPartFlag).second |= SocketBase.nSetPartFlag;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 착용 무기 속성 이펙트 추가 성능 적용
|
|
if( pEquipment->IsWeapon() && pEquipment->GetElementalEffectType() )
|
|
{
|
|
if( nWearIndex == ItemBase::WEAR_WEAPON )
|
|
m_nElementalEffectAttackPointRight += pEquipment->GetElementalEffectAttackPoint();
|
|
else
|
|
m_nElementalEffectAttackPointLeft += pEquipment->GetElementalEffectAttackPoint();
|
|
|
|
m_nElementalEffectMagicPoint += pEquipment->GetElementalEffectMagicPoint();
|
|
}
|
|
|
|
|
|
|
|
// Fraun Sky Accessories 7/12/2025
|
|
if (pEquipment->GetItemAdditionalEffect() > 0)
|
|
{
|
|
const std::vector<EffectInfo* >* Effect = GameContent::GetEffectInfoVector(pEquipment->GetItemAdditionalEffect());
|
|
|
|
if (Effect->size() > 0)
|
|
{
|
|
for (int eff = 0; eff < 20; )
|
|
{
|
|
if (Effect->at(0)->fValue[eff] != 0)
|
|
{
|
|
incParameter(Effect->at(0)->fValue[1], Effect->at(0)->fValue[2], true);
|
|
}
|
|
eff += 3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 세트 아이템과 세트 소울스톤 세트 착용 정보에 따라 적용될 세트 효과를 추후 스텟/파라미터 계산에 사용하기 위해 m_vSetItemEffect에 보관
|
|
for( SetPartFlagMap::const_iterator it = mapSetPartFlag.begin() ; it != mapSetPartFlag.end() ; ++it )
|
|
{
|
|
const std::vector< SetItemEffectInfo * > * pvSetItemEffectInfo = GameContent::GetSetItemEffectInfoVector( (*it).first );
|
|
|
|
for( std::vector< SetItemEffectInfo * >::const_iterator itSetItemEffect = pvSetItemEffectInfo->begin() ; itSetItemEffect != pvSetItemEffectInfo->end() ; ++itSetItemEffect )
|
|
{
|
|
if( ( (*it).second & (*itSetItemEffect)->nSetPartID ) == (*itSetItemEffect)->nSetPartID )
|
|
{
|
|
m_vSetItemEffect.push_back( *itSetItemEffect );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- 이하 핸들러들 ---
|
|
void StructCreature::onBeforeCalculateStat()
|
|
{
|
|
}
|
|
|
|
void StructPlayer::onBeforeCalculateStat()
|
|
{
|
|
m_bIsSummonable = true;
|
|
m_bIsInfiniteSummonTime = false;
|
|
|
|
m_nRideModifier = 0;
|
|
m_nSpeedModifier = 0;
|
|
m_nMaxWeightModifier = 0;
|
|
m_fPassDamageRatio = 0.0f;
|
|
m_bStaminaSave = false;
|
|
m_bSuperSave = false;
|
|
m_eSummonStaminaSaveType = SUMMON_STAMINA_SAVE_NONE;
|
|
m_nMaxStamina = GameRule::DEFAULT_MAX_STAMINA;
|
|
m_bUsingTent = false;
|
|
m_nStaminaRegenBonus = 0;
|
|
m_nMaxChaos = 0;
|
|
m_nDoubleSummonTime = GameRule::DEFAULT_DOUBLE_SUMMON_TIME;
|
|
m_vAutoRecoverInfo.clear();
|
|
m_nRidingStateCode = static_cast< StructState::StateCode >( 0 );
|
|
m_bUseFasterSpeedInRiding = false;
|
|
|
|
m_fActiveSummonExpAmp = 1.0f;
|
|
m_fDeactiveSummonExpAmp = 0.0f;
|
|
|
|
// 무기 사거리 조정
|
|
StructItem * pWeapon = GetWearedItem( ItemBase::WEAR_WEAPON );
|
|
if( pWeapon )
|
|
m_Attribute.fAttackRange = pWeapon->GetItemAttackRange();
|
|
|
|
m_vSummonPassiveSkillList.clear();
|
|
m_vAmplifySummonPassiveSkillList.clear();
|
|
|
|
m_fBeltSlotAmp = 1.0f;
|
|
|
|
m_fPreviousSummonFCM = m_fSummonFCM;
|
|
m_fSummonFCM = 1.0f;
|
|
|
|
// 벨트 슬롯 결정
|
|
m_nBeltSlotMax = 0;
|
|
StructItem *pItem = m_anWear[ItemBase::WEAR_BELT];
|
|
if( pItem && IsWearable( ItemBase::WEAR_BELT, pItem ) )
|
|
{
|
|
const ItemBaseServer & base = pItem->GetItemBase();
|
|
|
|
for( int i = 0; i < ItemBase::MAX_OPTION_NUMBER; ++i )
|
|
{
|
|
if( base.nOptType[i] == ITEM_EFFECT_PASSIVE::BELT_SLOT )
|
|
m_nBeltSlotMax += base.fOptVar1[i];
|
|
}
|
|
|
|
if( pItem->IsAwaken() )
|
|
{
|
|
if( pItem->GetAwakenOptionType( 0 ) == ITEM_EFFECT_PASSIVE::INC_BELT_ENHANCE )
|
|
m_fBeltSlotAmp += (float)( pItem->GetAwakenOptionValue2( 0 ) / 100);
|
|
}
|
|
|
|
// 벨트는 세공이 불가능한 대신 소켓 정보에 벨트 슬롯 정보를 담고 있다.
|
|
m_nBeltSlotMax += pItem->GetSocketCode( 0 );
|
|
}
|
|
|
|
m_nBeltSlotMax = m_nBeltSlotMax > 8 ? 8 : m_nBeltSlotMax;
|
|
|
|
s_memcpy( &m_PrevParameterForSummon, sizeof( m_PrevParameterForSummon ), &m_ParameterForSummon, sizeof( m_PrevParameterForSummon ) );
|
|
|
|
memset( &m_ParameterForSummon.Stat, 0, sizeof( m_ParameterForSummon.Stat ) );
|
|
memset( &m_ParameterForSummon.Attribute, 0, sizeof( m_ParameterForSummon.Attribute ) );
|
|
memset( &m_ParameterForSummon.Resist, 0, sizeof( m_ParameterForSummon.Resist ) );
|
|
|
|
m_ParameterForSummon.nMaxHP = 0;
|
|
m_ParameterForSummon.nMaxMP = 0;
|
|
m_ParameterForSummon.nMaxSP = 0;
|
|
m_ParameterForSummon.nSPRegenAdd = 0;
|
|
|
|
m_ParameterForSummon.fAttackPointRightWithoutWeapon = 0.0f;
|
|
m_ParameterForSummon.fMoveSpeed = 0.0f;
|
|
m_ParameterForSummon.fAttackRange = 0.0f;
|
|
|
|
m_ParameterForSummon.fMaxHPAmplifier = 0.0f;
|
|
m_ParameterForSummon.fMaxMPAmplifier = 0.0f;
|
|
m_ParameterForSummon.fMaxSPAmplifier = 0.0f;
|
|
m_ParameterForSummon.fSPRegenAddAmplifier = 0.0f;
|
|
|
|
memset( &m_ParameterForSummon.AttributeAmplifier, 0, sizeof( m_ParameterForSummon.AttributeAmplifier ) );
|
|
}
|
|
|
|
void StructMonster::onBeforeCalculateStat()
|
|
{
|
|
// (2007-03-24 리뉴얼 적용)
|
|
if( !isMoveSpeedFixed() )
|
|
{
|
|
m_Attribute.fMoveSpeed += ( m_pContentInfo->run_speed - GameRule::GetBaseMoveSpeed() );
|
|
}
|
|
m_Attribute.fAttackRange = m_pContentInfo->attack_range;
|
|
m_fDetectHideRange = m_pContentInfo->hidesense_range;
|
|
|
|
// 지속효과 도발에 의한 헤이트 보정치 벡터 초기화
|
|
m_vHateModifierByState.clear();
|
|
|
|
c_fixed10 difficultyBonus = GameRule::GetDifficultyBonus( m_nDifficulty );
|
|
m_Stat.strength *= difficultyBonus;
|
|
m_Stat.vital *= difficultyBonus;
|
|
m_Stat.dexterity *= difficultyBonus;
|
|
m_Stat.agility *= difficultyBonus;
|
|
m_Stat.intelligence *= difficultyBonus;
|
|
m_Stat.mentality *= difficultyBonus;
|
|
m_Stat.luck *= difficultyBonus;
|
|
|
|
if( m_pContentInfo->fight_type == MonsterBase::FIGHT_TYPE_IMMORTAL_DUMMY )
|
|
m_StatusFlag.Off( STATUS_MORTAL );
|
|
}
|
|
|
|
void StructSummon::onBeforeCalculateStat()
|
|
{
|
|
// { 스탯 초기화
|
|
m_fSoulConnectionRatio = 0.0f;
|
|
m_fRideSpeedMod = 0.9f;
|
|
m_fCM.set( 7000 );
|
|
m_fHPRegenMod = 1.0f;
|
|
m_fMPRegenMod = 1.0f;
|
|
m_fMaxSPAmplifier = 0.0f;
|
|
m_fSPRegenAddAmplifier = 0.0f;
|
|
|
|
m_fBaseAttackPointRatio = 0;
|
|
m_fBaseMagicPointRatio = 0;
|
|
m_fBaseDefenceRatio = 0;
|
|
m_fBaseMagicDefenceRatio = 0;
|
|
|
|
short nEnhance = 0;
|
|
if( GetParentCard() )
|
|
nEnhance = GetParentCard()->GetItemEnhance();
|
|
float fAmp = 1.0f;
|
|
fAmp += GameContent::GetCreatureEnhanceInfo( nEnhance )->stat_amplify;
|
|
m_Stat.strength *= fAmp;
|
|
m_Stat.vital *= fAmp;
|
|
m_Stat.dexterity *= fAmp;
|
|
m_Stat.agility *= fAmp;
|
|
m_Stat.intelligence *= fAmp;
|
|
m_Stat.mentality *= fAmp;
|
|
m_Stat.luck *= fAmp;
|
|
|
|
const StructSkill *pItemExpert = GetSkillByEffectType( SkillBase::EF_SUMMON_ITEM_EXPERT );
|
|
if( pItemExpert && pItemExpert->GetCurrentSkillLevel() > 0 )
|
|
{
|
|
m_fBaseAttackPointRatio = pItemExpert->GetVar( 0 );
|
|
m_fBaseMagicPointRatio = pItemExpert->GetVar( 1 );
|
|
m_fBaseDefenceRatio = pItemExpert->GetVar( 2 );
|
|
m_fBaseMagicDefenceRatio = pItemExpert->GetVar( 3 );
|
|
}
|
|
|
|
m_nMaxItemWear = GameContent::GetCreatureEnhanceInfo( nEnhance )->slot_amount;
|
|
m_fItemMod = 1.0f;
|
|
m_vMasterAmplifyPassiveSkillList.clear();
|
|
m_bIsRidable = false;
|
|
m_nUnMountProbabilityOnDamage = GameRule::DEFAULT_UNMOUNT_PROBABILITY_ON_DAMAGE;
|
|
m_nUnMountProbabilityOnCriticalDamage = GameRule::DEFAULT_UNMOUNT_PROBABILITY_ON_CRITICAL_DAMAGE;
|
|
// }
|
|
|
|
const StructSkill *pSkill;
|
|
|
|
if( GetMaster() )
|
|
{
|
|
// { 크리쳐 마스터리 적용 (2007-03-24 리뉴얼 적용)
|
|
pSkill = GetMaster()->GetCurrentPassiveSkill( StructSkill::SKILL_CREATURE_MASTERY );
|
|
static const c_fixed10 fCMPerLevel( 300, true );
|
|
if( pSkill ) m_fCM += fCMPerLevel * pSkill->GetCurrentSkillLevel();
|
|
// }
|
|
}
|
|
|
|
m_nSPRegenAdd = ( GetFCM() * 25 ) + 25;
|
|
m_nSPAdd = 0;
|
|
|
|
if( GetMaster() )
|
|
{
|
|
// { 크리처 아바타 레벨차 보정
|
|
// 오버브리드 페널티(오버Lv+크리처Lv-아바타Lv > 10 일 경우 부여되는 페널티) 제거. 2007-04-04
|
|
m_fBattleLevel = GetMaster()->GetLevel() + GameRule::GetSummonLevelPenalty( GetMaster()->GetLevel(), GetLevel() );
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
m_fBattleLevel = GetLevel();
|
|
}
|
|
|
|
// 소환수 이속 보정. 상태이상 적용을 위해서 onCompleteCalculateStat()에 있던걸 이쪽으로 옮겨왔음 2006-09-08 by Synastry
|
|
// (2007-03-24 리뉴얼 적용)
|
|
if( !isMoveSpeedFixed() )
|
|
m_Attribute.fMoveSpeed += ( m_pContentInfo->run_speed - GameRule::GetBaseMoveSpeed() );
|
|
|
|
// 소환수의 공격거리는 DB에 정의된 거리를 따른다
|
|
m_Attribute.fAttackRange = m_pContentInfo->attack_range;
|
|
}
|
|
|
|
void StructNPC::onBeforeCalculateStat()
|
|
{
|
|
// (2007-03-24 리뉴얼 적용)
|
|
if( !isMoveSpeedFixed() )
|
|
{
|
|
m_Attribute.fMoveSpeed += ( m_pBaseInfo->run_speed - GameRule::GetBaseMoveSpeed() );
|
|
}
|
|
m_Attribute.fAttackRange = m_pBaseInfo->attack_range;
|
|
}
|
|
|
|
void StructCreature::onAfterApplyStat()
|
|
{
|
|
}
|
|
|
|
void StructSummon::onAfterApplyStat()
|
|
{
|
|
// { 레벨 별 스텟 페널티 적용
|
|
float stat_penalty = 1.0f;
|
|
|
|
if( GetMaster() )
|
|
stat_penalty = GameRule::GetSummonStatPenalty( GetMaster()->GetLevel(), GetLevel() );
|
|
|
|
m_Stat.strength *= stat_penalty;
|
|
m_Stat.vital *= stat_penalty;
|
|
m_Stat.dexterity *= stat_penalty;
|
|
m_Stat.agility *= stat_penalty;
|
|
m_Stat.intelligence *= stat_penalty;
|
|
m_Stat.mentality *= stat_penalty;
|
|
m_Stat.luck *= stat_penalty;
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
void StructCreature::onApplyStat()
|
|
{
|
|
}
|
|
|
|
void StructPlayer::onApplyStat()
|
|
{
|
|
struct _mySkillFunctor : StructCreature::SKILL_POINTER_FUNCTOR
|
|
{
|
|
_mySkillFunctor( StructPlayer * _pPlayer ) : pPlayer( _pPlayer )
|
|
{
|
|
memset( amplifierCount, 0, sizeof( amplifierCount ) );
|
|
for( int i = 0; i < 7; ++i ) statAmplifier[i] = 0;
|
|
}
|
|
|
|
virtual void onSkill( StructSkill* pSkill )
|
|
{
|
|
// 문제가 있어 사용을 하지 않는다. 벨트 리뉴얼 기획을 따르지 않음.
|
|
if( pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_BELT_ON_PARAMETER_INC )
|
|
{
|
|
pPlayer->m_Stat.strength += pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
pPlayer->m_Stat.vital += pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
pPlayer->m_Stat.agility += pSkill->GetVar(4) + pSkill->GetVar(5) * pSkill->GetCurrentSkillLevel();
|
|
pPlayer->m_Stat.dexterity += pSkill->GetVar(6) + pSkill->GetVar(7) * pSkill->GetCurrentSkillLevel();
|
|
pPlayer->m_Stat.intelligence += pSkill->GetVar(8) + pSkill->GetVar(9) * pSkill->GetCurrentSkillLevel();
|
|
pPlayer->m_Stat.mentality += pSkill->GetVar(10) + pSkill->GetVar(11) * pSkill->GetCurrentSkillLevel();
|
|
pPlayer->m_Stat.luck += pSkill->GetVar(12) + pSkill->GetVar(13) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
else if( pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_BELT_ON_PARAMETER_AMP )
|
|
{
|
|
float amp;
|
|
|
|
for( int i = 0; i < 7; ++i )
|
|
{
|
|
amp = pSkill->GetVar(i*2) + pSkill->GetVar(i*2+1) * pSkill->GetCurrentSkillLevel();
|
|
if( amp )
|
|
{
|
|
statAmplifier[i] += amp;
|
|
++amplifierCount[i];
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
StructPlayer * pPlayer;
|
|
c_fixed10 statAmplifier[7];
|
|
int amplifierCount[7];
|
|
} _fo( this );
|
|
|
|
for( int i = 0; i < m_nBeltSlotMax; ++i )
|
|
{
|
|
StructItem * pItem = m_aBeltSlotCard[i];
|
|
|
|
if( !pItem )
|
|
continue;
|
|
|
|
if( pItem->IsSummonCard() )
|
|
{
|
|
StructSummon * pSummon = pItem->GetSummonStruct();
|
|
|
|
if( !pSummon )
|
|
continue;
|
|
|
|
pSummon->EnumPassiveSkill( _fo );
|
|
}
|
|
else if( pItem->IsEquipmentOnBelt() )
|
|
{
|
|
// 내구도 체크
|
|
if( !pItem->IsWearable() ) continue;
|
|
|
|
// 레벨 체크
|
|
if( pItem->GetLevelLimit() > GetLevel() ) continue;
|
|
if( pItem->GetItemBase().nMinLevel && GetLevel() < pItem->GetItemBase().nMinLevel ) continue;
|
|
if( pItem->GetItemBase().nMaxLevel && GetLevel() > pItem->GetItemBase().nMaxLevel ) continue;
|
|
|
|
const ItemBaseServer & base = pItem->GetItemBase();
|
|
|
|
for( int x = 0; x < ItemBase::MAX_OPTION_NUMBER; ++x )
|
|
{
|
|
if( !base.nOptType[x] ) continue;
|
|
|
|
if( base.nOptType[x] == ITEM_EFFECT_PASSIVE::INC_PARAMETER_A )
|
|
{
|
|
incParameter( base.fOptVar1[x], base.fOptVar2[x], true );
|
|
}
|
|
else if( base.nOptType[x] == ITEM_EFFECT_PASSIVE::AMP_PARAMETER_A )
|
|
{
|
|
ampParameter( base.fOptVar1[x], base.fOptVar2[x], true );
|
|
}
|
|
}
|
|
|
|
// 스킬의 변화도 스탯에 영향을 미치므로 함께 변경한다.
|
|
_applyStatByEffect( base.pvEffectList, m_fBeltSlotAmp );
|
|
_applySkillByEffect( base.pvEffectList, m_fBeltSlotAmp );
|
|
_amplifyStatByEffect( base.pvEffectList, m_fBeltSlotAmp );
|
|
}
|
|
}
|
|
|
|
for( int i = 0; i < 7; ++i )
|
|
{
|
|
if( _fo.statAmplifier[i] > 0.3 ) _fo.statAmplifier[i] = 0.3;
|
|
if( _fo.amplifierCount[i] <= 1 ) _fo.amplifierCount[i] = 0;
|
|
}
|
|
|
|
m_StatAmplifier.strength += ( _fo.statAmplifier[0] + _fo.amplifierCount[0] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_StatAmplifier.vital += ( _fo.statAmplifier[1] + _fo.amplifierCount[1] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_StatAmplifier.agility += ( _fo.statAmplifier[2] + _fo.amplifierCount[2] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_StatAmplifier.dexterity += ( _fo.statAmplifier[3] + _fo.amplifierCount[3] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_StatAmplifier.intelligence += ( _fo.statAmplifier[4] + _fo.amplifierCount[4] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_StatAmplifier.mentality += ( _fo.statAmplifier[5] + _fo.amplifierCount[5] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_StatAmplifier.luck += ( _fo.statAmplifier[6] + _fo.amplifierCount[6] * 0.01 ) * m_fBeltSlotAmp;
|
|
}
|
|
|
|
void StructSummon::onApplyStat()
|
|
{
|
|
struct _mySkillFunctor : StructCreature::SKILL_POINTER_FUNCTOR
|
|
{
|
|
_mySkillFunctor( StructSummon * _pSummon ) : pSummon( _pSummon ) {}
|
|
|
|
virtual void onSkill( StructSkill* pSkill )
|
|
{
|
|
if( pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_INCREASE_STAT )
|
|
{
|
|
int nSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
|
|
pSummon->m_Stat.strength += pSkill->GetVar( 0 ) + pSkill->GetVar( 1 ) * nSkillLevel;
|
|
pSummon->m_Stat.vital += pSkill->GetVar( 2 ) + pSkill->GetVar( 3 ) * nSkillLevel;
|
|
pSummon->m_Stat.agility += pSkill->GetVar( 4 ) + pSkill->GetVar( 5 ) * nSkillLevel;
|
|
pSummon->m_Stat.dexterity += pSkill->GetVar( 6 ) + pSkill->GetVar( 7 ) * nSkillLevel;
|
|
pSummon->m_Stat.intelligence += pSkill->GetVar( 8 ) + pSkill->GetVar( 9 ) * nSkillLevel;
|
|
pSummon->m_Stat.mentality += pSkill->GetVar( 10 ) + pSkill->GetVar( 11 ) * nSkillLevel;
|
|
pSummon->m_Stat.luck += pSkill->GetVar( 12 ) + pSkill->GetVar( 13 ) * nSkillLevel;
|
|
}
|
|
else if( pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_AMPLIFY_STAT )
|
|
{
|
|
int nSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
|
|
pSummon->m_StatAmplifier.strength += pSkill->GetVar( 0 ) * nSkillLevel;
|
|
pSummon->m_StatAmplifier.vital += pSkill->GetVar( 1 ) * nSkillLevel;
|
|
pSummon->m_StatAmplifier.agility += pSkill->GetVar( 2 ) * nSkillLevel;
|
|
pSummon->m_StatAmplifier.dexterity += pSkill->GetVar( 3 ) * nSkillLevel;
|
|
pSummon->m_StatAmplifier.intelligence += pSkill->GetVar( 4 ) * nSkillLevel;
|
|
pSummon->m_StatAmplifier.mentality += pSkill->GetVar( 5 ) * nSkillLevel;
|
|
pSummon->m_StatAmplifier.luck += pSkill->GetVar( 6 ) * nSkillLevel;
|
|
}
|
|
}
|
|
|
|
StructSummon * pSummon;
|
|
} _fo( this );
|
|
|
|
EnumPassiveSkill( _fo );
|
|
}
|
|
|
|
void StructCreature::onAfterCalculateAttributeByStat()
|
|
{
|
|
}
|
|
|
|
void StructPlayer::onAfterCalculateAttributeByStat()
|
|
{
|
|
// 벨트 장착 카드 속성(스텟 아님) 증가 처리
|
|
if( IsPlayer() )
|
|
{
|
|
struct _mySkillFunctor : StructCreature::SKILL_POINTER_FUNCTOR
|
|
{
|
|
_mySkillFunctor( StructPlayer * _pPlayer ) : pPlayer( _pPlayer )
|
|
{
|
|
for( int i = 0; i < 22; ++i ) attributeAmplifier[22] = 0;
|
|
fMaxHPAmplifier = 0.0;
|
|
fMaxMPAmplifier = 0.0;
|
|
memset( amplifierCount, 0, sizeof( amplifierCount ) );
|
|
}
|
|
|
|
virtual void onSkill( StructSkill* pSkill )
|
|
{
|
|
int nSkillLevel = pSkill->GetCurrentSkillLevel();
|
|
|
|
// 문제가 있어 사용을 하지 않는다. 벨트 리뉴얼 기획을 따르지 않음.
|
|
if( pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_BELT_ON_ATTRIBUTE_INC )
|
|
{
|
|
pPlayer->m_Attribute.fAttackPointRight += pSkill->GetVar(0) + pSkill->GetVar(1) * nSkillLevel;
|
|
pPlayer->m_Attribute.fDefence += pSkill->GetVar(2) + pSkill->GetVar(3) * nSkillLevel;
|
|
pPlayer->m_Attribute.fMagicPoint += pSkill->GetVar(4) + pSkill->GetVar(5) * nSkillLevel;
|
|
pPlayer->m_Attribute.fMagicDefence += pSkill->GetVar(6) + pSkill->GetVar(7) * nSkillLevel;
|
|
|
|
pPlayer->m_Attribute.fAttackSpeed += pSkill->GetVar(8) + pSkill->GetVar(9) * nSkillLevel;
|
|
pPlayer->m_Attribute.fAttackSpeed += pSkill->GetVar(8) + pSkill->GetVar(9) * nSkillLevel;
|
|
if( pPlayer->IsUsingDoubleWeapon() )
|
|
pPlayer->m_Attribute.fAttackSpeed += pSkill->GetVar(8) + pSkill->GetVar(9) * nSkillLevel;
|
|
|
|
if( !pPlayer->isMoveSpeedFixed() ) // fRidingSpeed 수치가 생기면서 라이딩 중에도 기본 속도에 관여할 수 있게 변경 ( 2013-12-20 )
|
|
{
|
|
pPlayer->m_Attribute.fMoveSpeed += pSkill->GetVar(10) + pSkill->GetVar(11) * nSkillLevel;
|
|
}
|
|
|
|
pPlayer->m_Attribute.fAccuracyRight += pSkill->GetVar(12) + pSkill->GetVar(13) * nSkillLevel;
|
|
if( pPlayer->IsUsingDoubleWeapon() )
|
|
pPlayer->m_Attribute.fAccuracyLeft += pSkill->GetVar(12) + pSkill->GetVar(13) * nSkillLevel;
|
|
|
|
pPlayer->m_Attribute.fMagicAccuracy += pSkill->GetVar(14) + pSkill->GetVar(15) * nSkillLevel;
|
|
pPlayer->m_Attribute.fAvoid += pSkill->GetVar(16) + pSkill->GetVar(17) * nSkillLevel;
|
|
pPlayer->m_Attribute.fMagicAvoid += pSkill->GetVar(18) + pSkill->GetVar(19) * nSkillLevel;
|
|
}
|
|
// 문제가 있어 사용을 하지 않는다. 벨트 리뉴얼 기획을 따르지 않음.
|
|
else if( pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_BELT_ON_ATTRIBUTE_EX_INC )
|
|
{
|
|
pPlayer->m_Attribute.fHPRegenPercentage += pSkill->GetVar(0) + pSkill->GetVar(1) * nSkillLevel;
|
|
pPlayer->m_Attribute.fHPRegenPoint += pSkill->GetVar(2) + pSkill->GetVar(3) * nSkillLevel;
|
|
pPlayer->m_Attribute.fMPRegenPercentage += pSkill->GetVar(4) + pSkill->GetVar(5) * nSkillLevel;
|
|
pPlayer->m_Attribute.fMPRegenPoint += pSkill->GetVar(6) + pSkill->GetVar(7) * nSkillLevel;
|
|
pPlayer->m_Attribute.fBlockChance += pSkill->GetVar(8) + pSkill->GetVar(9) * nSkillLevel;
|
|
pPlayer->m_Attribute.fBlockDefence += pSkill->GetVar(10) + pSkill->GetVar(11) * nSkillLevel;
|
|
pPlayer->m_Attribute.fCritical += pSkill->GetVar(12) + pSkill->GetVar(13) * nSkillLevel;
|
|
pPlayer->m_Attribute.fCriticalPower += pSkill->GetVar(14) + pSkill->GetVar(15) * nSkillLevel;
|
|
pPlayer->m_nMaxHP += pSkill->GetVar(16) + pSkill->GetVar(17) * nSkillLevel;
|
|
pPlayer->m_nMaxMP += pSkill->GetVar(18) + pSkill->GetVar(19) * nSkillLevel;
|
|
}
|
|
// 문제가 있어 사용을 하지 않는다. 벨트 리뉴얼 기획을 따르지 않음.
|
|
else if( pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_BELT_ON_ATTRIBUTE_EX2_INC )
|
|
{
|
|
pPlayer->m_Attribute.fCastingSpeed += pSkill->GetVar(0) + pSkill->GetVar(1) * nSkillLevel;
|
|
pPlayer->m_Attribute.fCoolTimeSpeed += pSkill->GetVar(2) + pSkill->GetVar(3) * nSkillLevel;
|
|
}
|
|
|
|
else if (pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_BELT_ON_ATTRIBUTE_EX3_INC)
|
|
{
|
|
|
|
if (pPlayer->GetJobId() == 220 || pPlayer->GetJobId() == 343) // Perfect Bloc Only for warrior
|
|
pPlayer->m_Attribute.fPerfectBlock += pSkill->GetVar(0) + pSkill->GetVar(1) * nSkillLevel;
|
|
|
|
//pPlayer->m_Attribute.fDefence +=
|
|
attributeAmplifier[1] += pSkill->GetVar(2) + pSkill->GetVar(3) * nSkillLevel;
|
|
++amplifierCount[1];
|
|
}
|
|
else if (pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_BELT_ON_ATTRIBUTE_EX4_INC)
|
|
{
|
|
//Attack M
|
|
attributeAmplifier[2] += pSkill->GetVar(0) + pSkill->GetVar(1) * nSkillLevel;
|
|
++amplifierCount[2];
|
|
//Incant Speed
|
|
attributeAmplifier[20] += pSkill->GetVar(2) + pSkill->GetVar(3) * nSkillLevel;
|
|
++amplifierCount[20];
|
|
}
|
|
else if (pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_BELT_ON_ATTRIBUTE_EX5_INC)
|
|
{
|
|
attributeAmplifier[20] += pSkill->GetVar(0) + pSkill->GetVar(1) * nSkillLevel;
|
|
++amplifierCount[20];
|
|
}
|
|
|
|
else if( pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_BELT_ON_ATTRIBUTE_AMP )
|
|
{
|
|
float amp;
|
|
|
|
for( int i = 0; i < 10; ++i )
|
|
{
|
|
amp = pSkill->GetVar(i*2) + pSkill->GetVar(i*2+1) * nSkillLevel;
|
|
if( amp )
|
|
{
|
|
attributeAmplifier[i] += amp;
|
|
++amplifierCount[i];
|
|
}
|
|
}
|
|
}
|
|
else if( pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_BELT_ON_ATTRIBUTE_EX_AMP )
|
|
{
|
|
float amp;
|
|
|
|
for( int i = 0; i < 10; ++i )
|
|
{
|
|
amp = pSkill->GetVar(i*2) + pSkill->GetVar(i*2+1) * nSkillLevel;
|
|
if( amp )
|
|
{
|
|
attributeAmplifier[i+10] += amp;
|
|
++amplifierCount[i+10];
|
|
}
|
|
}
|
|
}
|
|
else if( pSkill->GetSkillBase()->GetSkillEffectType() == SkillBase::EF_BELT_ON_ATTRIBUTE_EX2_AMP )
|
|
{
|
|
float amp;
|
|
|
|
for( int i = 0; i < 2; ++i )
|
|
{
|
|
amp = pSkill->GetVar(i*2) + pSkill->GetVar(i*2+1) * nSkillLevel;
|
|
if( amp )
|
|
{
|
|
attributeAmplifier[i+20] += amp;
|
|
++amplifierCount[i+20];
|
|
}
|
|
}
|
|
// 캐스팅 보전 비구현
|
|
// 화살 데미지 감소 비구현
|
|
}
|
|
}
|
|
|
|
StructPlayer * pPlayer;
|
|
c_fixed10 attributeAmplifier[22];
|
|
float fMaxHPAmplifier;
|
|
float fMaxMPAmplifier;
|
|
int amplifierCount[22];
|
|
} _fo( static_cast< StructPlayer * >(this) );
|
|
|
|
for( int i = 0; i < m_nBeltSlotMax; ++i )
|
|
{
|
|
StructItem * pItem = m_aBeltSlotCard[i];
|
|
|
|
if( !pItem )
|
|
continue;
|
|
|
|
if( pItem->IsSummonCard() )
|
|
{
|
|
StructSummon * pSummon = pItem->GetSummonStruct();
|
|
|
|
if( !pSummon )
|
|
continue;
|
|
|
|
pSummon->EnumPassiveSkill( _fo );
|
|
}
|
|
else if( pItem->IsEquipmentOnBelt() )
|
|
{
|
|
// 내구도 체크
|
|
if( !pItem->IsWearable() ) continue;
|
|
|
|
// 레벨 체크
|
|
if( pItem->GetLevelLimit() > GetLevel() ) continue;
|
|
if( pItem->GetItemBase().nMinLevel && GetLevel() < pItem->GetItemBase().nMinLevel ) continue;
|
|
if( pItem->GetItemBase().nMaxLevel && GetLevel() > pItem->GetItemBase().nMaxLevel ) continue;
|
|
|
|
int x;
|
|
|
|
const ItemBaseServer & base = pItem->GetItemBase();
|
|
|
|
for( int x = 0; x < ItemBase::MAX_OPTION_NUMBER; ++x )
|
|
{
|
|
if( !base.nBaseType[x] ) continue;
|
|
|
|
onItemWearEffect( pItem, true, base.nBaseType[x], base.fBaseVar1[x], base.fBaseVar2[x], m_fBeltSlotAmp );
|
|
}
|
|
|
|
for( x = 0; x < ItemBase::MAX_OPTION_NUMBER; ++x )
|
|
{
|
|
if( !base.nOptType[x] ) continue;
|
|
|
|
onItemWearEffect( pItem, false, base.nOptType[x], base.fOptVar1[x], base.fOptVar2[x], m_fBeltSlotAmp );
|
|
}
|
|
|
|
_applyEffect( pItem, base.pvEffectList, m_fBeltSlotAmp );
|
|
}
|
|
}
|
|
|
|
for( int i = 0; i < 22; ++i )
|
|
{
|
|
if( _fo.attributeAmplifier[i] > 0.3 ) _fo.attributeAmplifier[i] = 0.3;
|
|
if( _fo.amplifierCount[i] <= 1 ) _fo.amplifierCount[i] = 0;
|
|
}
|
|
|
|
m_AttributeAmplifier.fAttackPointRight += ( _fo.attributeAmplifier[0] + _fo.amplifierCount[0] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fDefence += ( _fo.attributeAmplifier[1] + _fo.amplifierCount[1] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fMagicPoint += ( _fo.attributeAmplifier[2] + _fo.amplifierCount[2] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fMagicDefence += ( _fo.attributeAmplifier[3] + _fo.amplifierCount[3] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fAttackSpeed += ( _fo.attributeAmplifier[4] + _fo.amplifierCount[4] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fAttackSpeedRight += ( _fo.attributeAmplifier[4] + _fo.amplifierCount[4] * 0.01 ) * m_fBeltSlotAmp;
|
|
if( IsUsingDoubleWeapon() )
|
|
m_AttributeAmplifier.fAttackSpeedLeft += ( _fo.attributeAmplifier[4] + _fo.amplifierCount[4] * 0.01 ) * m_fBeltSlotAmp;
|
|
if( isMoveSpeedFixed() ) // fRidingSpeed 수치가 생기면서 라이딩 중에도 기본 속도에 관여할 수 있게 변경 ( 2013-12-20 )
|
|
m_AttributeAmplifier.fMoveSpeed += ( _fo.attributeAmplifier[5] + _fo.amplifierCount[5] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fAccuracyRight += ( _fo.attributeAmplifier[6] + _fo.amplifierCount[6] * 0.01 ) * m_fBeltSlotAmp;
|
|
if( IsUsingDoubleWeapon() )
|
|
m_AttributeAmplifier.fAccuracyLeft += ( _fo.attributeAmplifier[6] + _fo.amplifierCount[6] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fMagicAccuracy += ( _fo.attributeAmplifier[7] + _fo.amplifierCount[7] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fAvoid += ( _fo.attributeAmplifier[8] + _fo.amplifierCount[8] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fMagicAvoid += ( _fo.attributeAmplifier[9] + _fo.amplifierCount[9] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fHPRegenPercentage += ( _fo.attributeAmplifier[10] + _fo.amplifierCount[10] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fHPRegenPoint += ( _fo.attributeAmplifier[11] + _fo.amplifierCount[11] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fMPRegenPercentage += ( _fo.attributeAmplifier[12] + _fo.amplifierCount[12] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fMPRegenPoint += ( _fo.attributeAmplifier[13] + _fo.amplifierCount[13] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fBlockChance += ( _fo.attributeAmplifier[14] + _fo.amplifierCount[14] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fBlockDefence += ( _fo.attributeAmplifier[15] + _fo.amplifierCount[15] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fCritical += ( _fo.attributeAmplifier[16] + _fo.amplifierCount[16] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fCriticalPower += ( _fo.attributeAmplifier[17] + _fo.amplifierCount[17] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_fMaxHPAmplifier += ( _fo.attributeAmplifier[18] + _fo.amplifierCount[18] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_fMaxMPAmplifier += ( _fo.attributeAmplifier[19] + _fo.amplifierCount[19] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fCastingSpeed += ( _fo.attributeAmplifier[20] + _fo.amplifierCount[20] * 0.01 ) * m_fBeltSlotAmp;
|
|
m_AttributeAmplifier.fCoolTimeSpeed += ( _fo.attributeAmplifier[21] + _fo.amplifierCount[21] * 0.01 ) * m_fBeltSlotAmp;
|
|
}
|
|
}
|
|
|
|
void StructMonster::onApplyAttributeAdjustment()
|
|
{
|
|
m_nMaxHP += m_pContentInfo->hp;
|
|
m_nMaxMP += m_pContentInfo->mp;
|
|
m_Attribute.fAttackPointRight += m_pContentInfo->attack_point;
|
|
m_Attribute.fAttackPointLeft += 0; // 왼손 공격력은 일단 무조건 0
|
|
m_Attribute.fMagicPoint += m_pContentInfo->magic_point;
|
|
m_Attribute.fDefence += m_pContentInfo->defence;
|
|
m_Attribute.fMagicDefence += m_pContentInfo->magic_defence;
|
|
m_Attribute.fAttackSpeedRight += m_pContentInfo->attack_speed;
|
|
m_Attribute.fAttackSpeedLeft += m_pContentInfo->attack_speed; // 왼손 공속은 오른손 공속 보정과 동일하게 적용
|
|
m_Attribute.fCastingSpeed += m_pContentInfo->casting_speed;
|
|
m_Attribute.fAccuracyRight += m_pContentInfo->accuracy;
|
|
m_Attribute.fAccuracyLeft += m_pContentInfo->accuracy; // 왼손 명중률은 오른손 명중률 보정과 동일하게 적용
|
|
m_Attribute.fAvoid += m_pContentInfo->avoid;
|
|
m_Attribute.fMagicAccuracy += m_pContentInfo->magic_accuracy;
|
|
m_Attribute.fMagicAvoid += m_pContentInfo->magic_avoid;
|
|
}
|
|
|
|
void StructCreature::onApplyAttributeAdjustment()
|
|
{
|
|
}
|
|
|
|
void StructNPC::onApplyAttributeAdjustment()
|
|
{
|
|
m_nMaxHP += m_pBaseInfo->hp;
|
|
m_nMaxMP += m_pBaseInfo->mp;
|
|
m_Attribute.fAttackPointRight += m_pBaseInfo->attack_point;
|
|
m_Attribute.fAttackPointLeft += 0; // 왼손 공격력은 일단 무조건 0
|
|
m_Attribute.fMagicPoint += m_pBaseInfo->magic_point;
|
|
m_Attribute.fDefence += m_pBaseInfo->defence;
|
|
m_Attribute.fMagicDefence += m_pBaseInfo->magic_defence;
|
|
m_Attribute.fAttackSpeedRight += m_pBaseInfo->attack_speed;
|
|
m_Attribute.fAttackSpeedLeft += m_pBaseInfo->attack_speed; // 왼손 공속은 오른손 공속 보정과 동일하게 적용
|
|
m_Attribute.fAccuracyRight += m_pBaseInfo->accuracy;
|
|
m_Attribute.fAccuracyLeft += m_pBaseInfo->accuracy; // 왼손 명중률은 오른손 명중률 보정과 동일하게 적용
|
|
m_Attribute.fAvoid += m_pBaseInfo->avoid;
|
|
m_Attribute.fMagicAccuracy += m_pBaseInfo->magic_accuracy;
|
|
m_Attribute.fMagicAvoid += m_pBaseInfo->magic_avoid;
|
|
}
|
|
|
|
void StructCreature::onModifyStatAndAttribute()
|
|
{
|
|
}
|
|
|
|
void StructPlayer::onModifyStatAndAttribute()
|
|
{
|
|
//SendHPMPMsg( this, this );
|
|
SendStatInfo( this, this );
|
|
|
|
SendPropertyMessage( this, GetHandle(), "max_chaos", GetMaxChaos() );
|
|
SendPropertyMessage( this, GetHandle(), "max_stamina", m_nMaxStamina );
|
|
}
|
|
|
|
void StructSummon::onModifyStatAndAttribute()
|
|
{
|
|
if( GetMaster() )
|
|
{
|
|
//SendHPMPMsg( GetMaster(), this );
|
|
SendStatInfo( GetMaster(), this );
|
|
SendSPMsg( GetMaster(), this );
|
|
}
|
|
}
|
|
|
|
|
|
void StructCreature::onModifySkill()
|
|
{
|
|
if( this->IsPlayer() )
|
|
SendAddedSkillMessage( static_cast< StructPlayer * >(this), this );
|
|
else if( this->IsSummon() )
|
|
SendAddedSkillMessage( static_cast< StructSummon * >(this)->GetMaster(), this );
|
|
}
|
|
|
|
void StructCreature::onModifyDetectRange()
|
|
{
|
|
if( IsPlayer() )
|
|
SendDetectRangeMessage( static_cast< StructPlayer * >(this), this );
|
|
else if( IsSummon() )
|
|
SendDetectRangeMessage( static_cast< StructSummon * >(this)->GetMaster(), this );
|
|
}
|
|
|
|
void StructPlayer::onCompleteCalculateStat()
|
|
{
|
|
if( IsRiding() )
|
|
{
|
|
m_Attribute.fRidingSpeed = GetRideObject()->GetSummonBase()->riding_speed;
|
|
}
|
|
|
|
// 부적 적용
|
|
for( std::vector< StructItem * >::iterator it = m_vCharmList.begin(); it != m_vCharmList.end(); ++it )
|
|
applyCharm( *it );
|
|
|
|
// 펫 적용
|
|
StructPet * pPet = GetSummonedPet();
|
|
if( pPet )
|
|
m_Attribute.fMaxWeight += pPet->GetAddedWeight();
|
|
|
|
// 야수 변신과 같은 이동 속도 고정류(MoveSpeedFixed)는 튼튼한 발굽 같은 RidingModifier의 보정을 받는다고 한다.
|
|
if( !isMoveSpeedFixed() )
|
|
m_Attribute.fMoveSpeed += m_nSpeedModifier;
|
|
else
|
|
m_Attribute.fMoveSpeed += m_nRideModifier;
|
|
m_Attribute.fRidingSpeed += m_nRideModifier;
|
|
m_Attribute.fMaxWeight += m_nMaxWeightModifier;
|
|
|
|
if ( m_fPreviousSummonFCM != m_fSummonFCM )
|
|
{
|
|
StructSummon* pMain = GetMainSummon();
|
|
StructSummon* pSub = GetSubSummon();
|
|
|
|
if ( pMain ) pMain->CalculateStat();
|
|
if ( pSub ) pSub->CalculateStat();
|
|
}
|
|
|
|
if( memcmp( &m_ParameterForSummon, &m_PrevParameterForSummon, sizeof( m_ParameterForSummon ) ) )
|
|
{
|
|
onModifyParameterForSummon();
|
|
}
|
|
}
|
|
|
|
void StructPlayer::onModifyParameterForSummon()
|
|
{
|
|
StructSummon *pSummon = GetMainSummon();
|
|
if( pSummon )
|
|
{
|
|
if( pSummon->GetPriority() == ArObject::UPDATE_PRIORITY_NULL ||
|
|
pSummon->GetPriority() == ArObject::UPDATE_PRIORITY_IDLE )
|
|
{
|
|
ArcadiaServer::Instance().SetObjectPriority( pSummon, ArObject::UPDATE_PRIORITY_NORMAL );
|
|
}
|
|
}
|
|
|
|
pSummon = GetSubSummon();
|
|
if( pSummon )
|
|
{
|
|
if( pSummon->GetPriority() == ArObject::UPDATE_PRIORITY_NULL ||
|
|
pSummon->GetPriority() == ArObject::UPDATE_PRIORITY_IDLE )
|
|
{
|
|
ArcadiaServer::Instance().SetObjectPriority( pSummon, ArObject::UPDATE_PRIORITY_NORMAL );
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructPlayer::_applyCharm( const int type, const c_fixed10 & var1, const c_fixed10 & var2, struct StructItem * pItem )
|
|
{
|
|
switch( type )
|
|
{
|
|
case ITEM_EFFECT_CHARM::INC_SPEED:
|
|
if( m_nSpeedModifier < var1 )
|
|
m_nSpeedModifier = var1;
|
|
break;
|
|
case ITEM_EFFECT_CHARM::INC_MAX_STAMINA:
|
|
if( m_nMaxStamina < var1 )
|
|
m_nMaxStamina = var1;
|
|
break;
|
|
case ITEM_EFFECT_CHARM::STAMINA_REGEN_TENT:
|
|
m_bUsingTent = true;
|
|
break;
|
|
case ITEM_EFFECT_CHARM::INC_STAMINA_REGEN:
|
|
m_nStaminaRegenBonus = var1;
|
|
break;
|
|
case ITEM_EFFECT_CHARM::INC_MAX_WEIGHT:
|
|
if( m_nMaxWeightModifier < var1 )
|
|
m_nMaxWeightModifier = var1;
|
|
break;
|
|
case ITEM_EFFECT_CHARM::INC_RIDING_SPEED:
|
|
if( m_nRideModifier < var1 )
|
|
m_nRideModifier = var1;
|
|
break;
|
|
case ITEM_EFFECT_CHARM::AUTO_RECOVER_HP:
|
|
{
|
|
int nIdx = pItem->GetIdx();
|
|
std::vector< AUTO_RECOVER_INFO >::iterator it;
|
|
for( it = m_vAutoRecoverInfo.begin() ; it != m_vAutoRecoverInfo.end() ; ++it )
|
|
{
|
|
if( (*it).m_nOrderIndex > nIdx )
|
|
break;
|
|
}
|
|
m_vAutoRecoverInfo.insert( it, AUTO_RECOVER_INFO( RECOVER_TYPE_HP, var1, var2, pItem->GetHandle(), pItem->GetIdx() ) );
|
|
}
|
|
break;
|
|
case ITEM_EFFECT_CHARM::AUTO_RECOVER_MP:
|
|
{
|
|
int nIdx = pItem->GetIdx();
|
|
std::vector< AUTO_RECOVER_INFO >::iterator it;
|
|
for( it = m_vAutoRecoverInfo.begin() ; it != m_vAutoRecoverInfo.end() ; ++it )
|
|
{
|
|
if( (*it).m_nOrderIndex > nIdx )
|
|
break;
|
|
}
|
|
m_vAutoRecoverInfo.insert( it, AUTO_RECOVER_INFO( RECOVER_TYPE_MP, var1, var2, pItem->GetHandle(), pItem->GetIdx() ) );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void StructPlayer::applyCharm( struct StructItem * pItem )
|
|
{
|
|
const ItemBaseServer & base = pItem->GetItemBase();
|
|
|
|
for( int x = 0; x < ItemBase::MAX_OPTION_NUMBER; ++x )
|
|
{
|
|
if( !base.nOptType[x] )
|
|
continue;
|
|
|
|
_applyCharm( base.nOptType[ x ], base.fOptVar1[ x ], base.fOptVar2[ x ], pItem );
|
|
}
|
|
|
|
if( !base.pvEffectList || base.pvEffectList->empty() )
|
|
return;
|
|
|
|
for( std::vector< EffectInfo * >::const_iterator it = base.pvEffectList->begin() ; it != base.pvEffectList->end() ; ++it )
|
|
{
|
|
if( (*it)->eType != EffectInfo::EFFECT_TYPE_BASIC && (*it)->eType != EffectInfo::EFFECT_TYPE_OPTIONAL )
|
|
continue;
|
|
|
|
if( (*it)->nMinLevel && GetLevel() < (*it)->nMinLevel ) continue;
|
|
if( (*it)->nMaxLevel && GetLevel() > (*it)->nMaxLevel ) continue;
|
|
|
|
_applyCharm( (*it)->fValue[ 0 ], (*it)->fValue[ 1 ], (*it)->fValue[ 2 ], pItem );
|
|
_applyCharm( (*it)->fValue[ 3 ], (*it)->fValue[ 4 ], (*it)->fValue[ 5 ], pItem );
|
|
_applyCharm( (*it)->fValue[ 6 ], (*it)->fValue[ 7 ], (*it)->fValue[ 8 ], pItem );
|
|
_applyCharm( (*it)->fValue[ 9 ], (*it)->fValue[ 10 ], (*it)->fValue[ 11 ], pItem );
|
|
}
|
|
|
|
_applyEffect( pItem, base.pvEffectList, m_fBeltSlotAmp );
|
|
}
|
|
|
|
void StructCreature::onCompleteCalculateStat()
|
|
{
|
|
}
|
|
|
|
void StructMonster::onCompleteCalculateStat()
|
|
{
|
|
if( IsDungeonRaidMonster() )
|
|
{
|
|
m_Attribute.fMoveSpeed *= 1.5f;
|
|
}
|
|
}
|
|
|
|
void StructSummon::onCompleteCalculateStat()
|
|
{
|
|
// { 탑승 가능 소환수인지 확인
|
|
StructSkill * pSkill = GetCurrentPassiveSkill( StructSkill::SKILL_CREATURE_RIDING );
|
|
|
|
if( pSkill )
|
|
{
|
|
m_bIsRidable = true;
|
|
|
|
m_fRideSpeedMod += pSkill->GetVar(0) + pSkill->GetVar(1) * pSkill->GetCurrentSkillLevel();
|
|
|
|
if( m_fRideSpeedMod > 1.0f )
|
|
{
|
|
m_fRideSpeedMod = 1.0f;
|
|
}
|
|
|
|
m_nUnMountProbabilityOnDamage -= pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
m_nUnMountProbabilityOnCriticalDamage -= pSkill->GetVar(2) + pSkill->GetVar(3) * pSkill->GetCurrentSkillLevel();
|
|
}
|
|
|
|
m_nMaxSP *= 1.0f + m_fMaxSPAmplifier;
|
|
m_nSPRegenAdd *= 1.0f + m_fSPRegenAddAmplifier;
|
|
|
|
if( GetMaster() )
|
|
{
|
|
m_Attribute.fAttackPointRight *= GetMaster()->GetFCMRatio();
|
|
m_Attribute.fAttackPointLeft *= GetMaster()->GetFCMRatio();
|
|
m_Attribute.fMagicPoint *= GetMaster()->GetFCMRatio();
|
|
m_Attribute.fDefence *= GetMaster()->GetFCMRatio();
|
|
m_Attribute.fMagicDefence *= GetMaster()->GetFCMRatio();
|
|
}
|
|
|
|
// }
|
|
}
|
|
|
|
// --- 각종 스탯을 계산하는 유틸리티 함수들 ---
|
|
void StructCreature::accumulateStatDiffByState( const CreatureStatServer& stateStat )
|
|
{
|
|
m_StatByState.strength += m_Stat.strength - stateStat.strength;
|
|
m_StatByState.vital += m_Stat.vital - stateStat.vital;
|
|
m_StatByState.dexterity += m_Stat.dexterity - stateStat.dexterity;
|
|
m_StatByState.agility += m_Stat.agility - stateStat.agility;
|
|
m_StatByState.intelligence += m_Stat.intelligence - stateStat.intelligence;
|
|
m_StatByState.mentality += m_Stat.mentality - stateStat.mentality;
|
|
m_StatByState.luck += m_Stat.luck - stateStat.luck;
|
|
}
|
|
|
|
void StructCreature::accumulateAttributeDiffByState( const CreatureAttributeServer& stateAttr )
|
|
{
|
|
m_AttributeByState.fCritical += m_Attribute.fCritical - stateAttr.fCritical;
|
|
m_AttributeByState.fAttackPointRight += m_Attribute.fAttackPointRight - stateAttr.fAttackPointRight;
|
|
m_AttributeByState.fAttackPointLeft += m_Attribute.fAttackPointLeft - stateAttr.fAttackPointLeft;
|
|
m_AttributeByState.fDefence += m_Attribute.fDefence - stateAttr.fDefence;
|
|
m_AttributeByState.fBlockDefence += m_Attribute.fBlockDefence - stateAttr.fBlockDefence;
|
|
m_AttributeByState.fMagicPoint += m_Attribute.fMagicPoint - stateAttr.fMagicPoint;
|
|
m_AttributeByState.fMagicDefence += m_Attribute.fMagicDefence - stateAttr.fMagicDefence;
|
|
m_AttributeByState.fAccuracyRight += m_Attribute.fAccuracyRight - stateAttr.fAccuracyRight;
|
|
m_AttributeByState.fAccuracyLeft += m_Attribute.fAccuracyLeft - stateAttr.fAccuracyLeft;
|
|
m_AttributeByState.fMagicAccuracy += m_Attribute.fMagicAccuracy - stateAttr.fMagicAccuracy;
|
|
m_AttributeByState.fAvoid += m_Attribute.fAvoid - stateAttr.fAvoid;
|
|
m_AttributeByState.fMagicAvoid += m_Attribute.fMagicAvoid - stateAttr.fMagicAvoid;
|
|
m_AttributeByState.fBlockChance += m_Attribute.fBlockChance - stateAttr.fBlockChance;
|
|
m_AttributeByState.fMoveSpeed += m_Attribute.fMoveSpeed - stateAttr.fMoveSpeed;
|
|
m_AttributeByState.fAttackSpeedRight += m_Attribute.fAttackSpeedRight - stateAttr.fAttackSpeedRight;
|
|
m_AttributeByState.fAttackSpeedLeft += m_Attribute.fAttackSpeedLeft - stateAttr.fAttackSpeedLeft;
|
|
m_AttributeByState.fDoubleAttackRatio += m_Attribute.fDoubleAttackRatio - stateAttr.fDoubleAttackRatio;
|
|
m_AttributeByState.fAttackRange += m_Attribute.fAttackRange - stateAttr.fAttackRange;
|
|
m_AttributeByState.fMaxWeight += m_Attribute.fMaxWeight - stateAttr.fMaxWeight;
|
|
m_AttributeByState.fCastingSpeed += m_Attribute.fCastingSpeed - stateAttr.fCastingSpeed;
|
|
m_AttributeByState.fCoolTimeSpeed += m_Attribute.fCoolTimeSpeed - stateAttr.fCoolTimeSpeed;
|
|
m_AttributeByState.fHPRegenPercentage += m_Attribute.fHPRegenPercentage - stateAttr.fHPRegenPercentage;
|
|
m_AttributeByState.fHPRegenPoint += m_Attribute.fHPRegenPoint - stateAttr.fHPRegenPoint;
|
|
m_AttributeByState.fMPRegenPercentage += m_Attribute.fMPRegenPercentage - stateAttr.fMPRegenPercentage;
|
|
m_AttributeByState.fMPRegenPoint += m_Attribute.fMPRegenPoint - stateAttr.fMPRegenPoint;
|
|
m_AttributeByState.fPerfectBlock += m_Attribute.fPerfectBlock - stateAttr.fPerfectBlock;
|
|
m_AttributeByState.fPhysicalDefIgnore += m_Attribute.fPhysicalDefIgnore - stateAttr.fPhysicalDefIgnore;
|
|
m_AttributeByState.fPhysicalDefIgnoreRatio += m_Attribute.fPhysicalDefIgnoreRatio - stateAttr.fPhysicalDefIgnoreRatio;
|
|
m_AttributeByState.fMagicalDefIgnore += m_Attribute.fMagicalDefIgnore - stateAttr.fMagicalDefIgnore;
|
|
m_AttributeByState.fMagicalDefIgnoreRatio += m_Attribute.fMagicalDefIgnoreRatio - stateAttr.fMagicalDefIgnoreRatio;
|
|
m_AttributeByState.fPhysicalPenetration += m_Attribute.fPhysicalPenetration - stateAttr.fPhysicalPenetration;
|
|
m_AttributeByState.fPhysicalPenetrationRatio += m_Attribute.fPhysicalPenetrationRatio - stateAttr.fPhysicalPenetrationRatio;
|
|
m_AttributeByState.fMagicalPenetration += m_Attribute.fMagicalPenetration - stateAttr.fMagicalPenetration;
|
|
m_AttributeByState.fMagicalPenetrationRatio += m_Attribute.fMagicalPenetrationRatio - stateAttr.fMagicalPenetrationRatio;
|
|
}
|
|
|
|
void StructCreature::getAmplifiedStatByAmplifier( CreatureStatServer * pStat )
|
|
{
|
|
pStat->strength += ( m_StatAmplifier.strength ) * pStat->strength;
|
|
pStat->vital += ( m_StatAmplifier.vital ) * pStat->vital;
|
|
pStat->dexterity += ( m_StatAmplifier.dexterity ) * pStat->dexterity;
|
|
pStat->agility += ( m_StatAmplifier.agility ) * pStat->agility;
|
|
pStat->intelligence += ( m_StatAmplifier.intelligence ) * pStat->intelligence;
|
|
pStat->mentality += ( m_StatAmplifier.mentality ) * pStat->mentality;
|
|
pStat->luck += ( m_StatAmplifier.luck ) * pStat->luck;
|
|
}
|
|
|
|
void StructCreature::getAmplifiedAttributeByAmplifier( CreatureAttributeServer * pAttribute )
|
|
{
|
|
pAttribute->fCritical += ( m_AttributeAmplifier.fCritical ) * pAttribute->fCritical;
|
|
pAttribute->fCriticalPower += ( m_AttributeAmplifier.fCriticalPower ) * pAttribute->fCriticalPower;
|
|
pAttribute->fAttackPointRight += ( m_AttributeAmplifier.fAttackPointRight ) * pAttribute->fAttackPointRight;
|
|
pAttribute->fAttackPointLeft += ( m_AttributeAmplifier.fAttackPointLeft ) * pAttribute->fAttackPointLeft;
|
|
pAttribute->fDefence += ( m_AttributeAmplifier.fDefence ) * pAttribute->fDefence;
|
|
pAttribute->fBlockDefence += ( m_AttributeAmplifier.fBlockDefence ) * pAttribute->fBlockDefence;
|
|
pAttribute->fMagicPoint += ( m_AttributeAmplifier.fMagicPoint ) * pAttribute->fMagicPoint;
|
|
pAttribute->fMagicDefence += ( m_AttributeAmplifier.fMagicDefence ) * pAttribute->fMagicDefence;
|
|
pAttribute->fAccuracyRight += ( m_AttributeAmplifier.fAccuracyRight ) * pAttribute->fAccuracyRight;
|
|
pAttribute->fAccuracyLeft += ( m_AttributeAmplifier.fAccuracyLeft ) * pAttribute->fAccuracyLeft;
|
|
pAttribute->fMagicAccuracy += ( m_AttributeAmplifier.fMagicAccuracy ) * pAttribute->fMagicAccuracy;
|
|
pAttribute->fAvoid += ( m_AttributeAmplifier.fAvoid ) * pAttribute->fAvoid;
|
|
pAttribute->fMagicAvoid += ( m_AttributeAmplifier.fMagicAvoid ) * pAttribute->fMagicAvoid;
|
|
pAttribute->fBlockChance += ( m_AttributeAmplifier.fBlockChance ) * pAttribute->fBlockChance;
|
|
if( !isMoveSpeedFixed() )
|
|
{
|
|
pAttribute->fMoveSpeed += ( m_AttributeAmplifier.fMoveSpeed ) * pAttribute->fMoveSpeed;
|
|
}
|
|
pAttribute->fAttackSpeed += ( m_AttributeAmplifier.fAttackSpeed ) * pAttribute->fAttackSpeed;
|
|
pAttribute->fAttackRange += ( m_AttributeAmplifier.fAttackRange ) * pAttribute->fAttackRange;
|
|
pAttribute->fMaxWeight += ( m_AttributeAmplifier.fMaxWeight ) * pAttribute->fMaxWeight;
|
|
pAttribute->fCastingSpeed += ( m_AttributeAmplifier.fCastingSpeed ) * pAttribute->fCastingSpeed;
|
|
pAttribute->fCoolTimeSpeed += ( m_AttributeAmplifier.fCoolTimeSpeed ) * pAttribute->fCoolTimeSpeed;
|
|
pAttribute->fItemChance += ( m_AttributeAmplifier.fItemChance ) * pAttribute->fItemChance;
|
|
pAttribute->fHPRegenPercentage += ( m_AttributeAmplifier.fHPRegenPercentage ) * pAttribute->fHPRegenPercentage;
|
|
pAttribute->fHPRegenPoint += ( m_AttributeAmplifier.fHPRegenPoint ) * pAttribute->fHPRegenPoint;
|
|
pAttribute->fMPRegenPercentage += ( m_AttributeAmplifier.fMPRegenPercentage ) * pAttribute->fMPRegenPercentage;
|
|
pAttribute->fMPRegenPoint += ( m_AttributeAmplifier.fMPRegenPoint ) * pAttribute->fMPRegenPoint;
|
|
|
|
pAttribute->fAttackSpeedRight += ( m_AttributeAmplifier.fAttackSpeedRight ) * pAttribute->fAttackSpeedRight;
|
|
pAttribute->fAttackSpeedLeft += ( m_AttributeAmplifier.fAttackSpeedLeft ) * pAttribute->fAttackSpeedLeft;
|
|
pAttribute->fDoubleAttackRatio += ( m_AttributeAmplifier.fDoubleAttackRatio ) * pAttribute->fDoubleAttackRatio;
|
|
pAttribute->fStunResistance += ( m_AttributeAmplifier.fStunResistance ) * pAttribute->fStunResistance;
|
|
pAttribute->fMoveSpeedDecreaseResistance += ( m_AttributeAmplifier.fMoveSpeedDecreaseResistance ) * pAttribute->fMoveSpeedDecreaseResistance;
|
|
pAttribute->fHPAdd += ( m_AttributeAmplifier.fHPAdd ) * pAttribute->fHPAdd;
|
|
pAttribute->fMPAdd += ( m_AttributeAmplifier.fMPAdd ) * pAttribute->fMPAdd;
|
|
pAttribute->fHPAddByItem += ( m_AttributeAmplifier.fHPAddByItem ) * pAttribute->fHPAddByItem;
|
|
pAttribute->fMPAddByItem += ( m_AttributeAmplifier.fMPAddByItem ) * pAttribute->fMPAddByItem;
|
|
}
|
|
|
|
void StructCreature::getAmplifiedResistByAmplifier( CreatureElementalResist * pResist )
|
|
{
|
|
for( int i = 0; i < Elemental::TYPE_COUNT; ++i )
|
|
{
|
|
pResist->nResist[i] += ( m_ResistAmplifier.fResist[i] ) * pResist->nResist[i];
|
|
}
|
|
}
|
|
|
|
void StructCreature::incParameter( const int nBitset, const c_fixed10 & fValue, const bool bStat, ParameterForSummon *pParam )
|
|
{
|
|
if( bStat )
|
|
{
|
|
CreatureStatServer & Stat = pParam ? pParam->Stat : m_Stat;
|
|
|
|
if( nBitset & StructState::FLAG_STR )
|
|
{
|
|
Stat.strength += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_VIT )
|
|
{
|
|
Stat.vital += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_AGI )
|
|
{
|
|
Stat.agility += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_DEX )
|
|
{
|
|
Stat.dexterity += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_INT )
|
|
{
|
|
Stat.intelligence += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_MEN )
|
|
{
|
|
Stat.mentality += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_LUK )
|
|
{
|
|
Stat.luck += fValue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// pParam의 여부에 따라 반드시 받아야 할 변수
|
|
CreatureAttributeServer & Attribute = pParam ? pParam->Attribute : m_Attribute;
|
|
int & nMaxHP = pParam ? pParam->nMaxHP : m_nMaxHP;
|
|
int & nMaxMP = pParam ? pParam->nMaxMP : m_nMaxMP;
|
|
c_fixed10 & fAttackPointRightWithoutWeapon = pParam ? pParam->fAttackPointRightWithoutWeapon : m_fAttackPointRightWithoutWeapon;
|
|
|
|
if( nBitset & StructState::FLAG_ATTACK_POINT )
|
|
{
|
|
Attribute.fAttackPointRight += fValue;
|
|
fAttackPointRightWithoutWeapon += fValue;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
m_Attribute.fAttackPointLeft += fValue;
|
|
m_fAttackPointLeftWithoutWeapon += fValue;
|
|
}
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAGIC_POINT )
|
|
{
|
|
Attribute.fMagicPoint += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_DEFENCE )
|
|
{
|
|
Attribute.fDefence += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAGIC_DEFENCE )
|
|
{
|
|
Attribute.fMagicDefence += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ATTACK_SPEED )
|
|
{
|
|
Attribute.fAttackSpeedRight += fValue;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
Attribute.fAttackSpeedLeft += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_CAST_SPEED )
|
|
{
|
|
Attribute.fCastingSpeed += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MOVE_SPEED )
|
|
{
|
|
if( pParam || ( !isMoveSpeedFixed() ) ) // fRidingSpeed 수치가 생기면서 라이딩 중에도 기본 속도에 관여할 수 있게 변경 ( 2013-12-20 )
|
|
{
|
|
Attribute.fMoveSpeed += fValue;
|
|
}
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ACCURACY )
|
|
{
|
|
Attribute.fAccuracyRight += fValue;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
Attribute.fAccuracyLeft += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAGIC_ACCURACY )
|
|
{
|
|
Attribute.fMagicAccuracy += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_CRITICAL )
|
|
{
|
|
Attribute.fCritical += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_BLOCK )
|
|
{
|
|
Attribute.fBlockChance += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_BLOCK_DEFENCE )
|
|
{
|
|
Attribute.fBlockDefence += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_AVOID )
|
|
{
|
|
Attribute.fAvoid += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAGIC_RESISTANCE )
|
|
{
|
|
Attribute.fMagicAvoid += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAX_HP )
|
|
{
|
|
nMaxHP += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAX_MP )
|
|
{
|
|
nMaxMP += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAX_SP )
|
|
{
|
|
// 소환수에서만 사용
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_HP_REGEN_ADD )
|
|
{
|
|
Attribute.fHPRegenPoint += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MP_REGEN_ADD )
|
|
{
|
|
Attribute.fMPRegenPoint += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_SP_REGEN_ADD )
|
|
{
|
|
// 소환수에서만 사용
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_HP_REGEN_RATIO )
|
|
{
|
|
Attribute.fHPRegenPercentage += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MP_REGEN_RATIO )
|
|
{
|
|
Attribute.fMPRegenPercentage += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_CRITICAL_DAMAGE_BACKUP )
|
|
{
|
|
Attribute.fCriticalPower += fValue * 3;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAX_WEIGHT )
|
|
{
|
|
Attribute.fMaxWeight += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_DAMAGE_REDUCE )
|
|
{
|
|
m_vDamageReduceValueInfo.push_back( DamageReduceInfo( 100, fValue, fValue, fValue, 0, 99, 0, 0, 0 ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructSummon::incParameter( const int nBitset, const c_fixed10 & fValue, const bool bStat, ParameterForSummon *pParam )
|
|
{
|
|
int & nMaxSP = pParam ? pParam->nMaxSP : m_nMaxSP;
|
|
short & nSPRegenAdd = pParam ? pParam->nSPRegenAdd : m_nSPRegenAdd;
|
|
|
|
if( !bStat )
|
|
{
|
|
if( nBitset & StructState::FLAG_MAX_SP )
|
|
{
|
|
nMaxSP += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_SP_REGEN_ADD )
|
|
{
|
|
nSPRegenAdd += fValue;
|
|
}
|
|
}
|
|
|
|
StructCreature::incParameter( nBitset, fValue, bStat, pParam );
|
|
}
|
|
|
|
void StructCreature::ampParameter( const int nBitset, const c_fixed10 & fValue, const bool bStat )
|
|
{
|
|
if( bStat )
|
|
{
|
|
if( nBitset & StructState::FLAG_STR )
|
|
{
|
|
m_StatAmplifier.strength += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_VIT )
|
|
{
|
|
m_StatAmplifier.vital += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_AGI )
|
|
{
|
|
m_StatAmplifier.agility += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_DEX )
|
|
{
|
|
m_StatAmplifier.dexterity += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_INT )
|
|
{
|
|
m_StatAmplifier.intelligence += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_MEN )
|
|
{
|
|
m_StatAmplifier.mentality += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_LUK )
|
|
{
|
|
m_StatAmplifier.luck += fValue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( nBitset & StructState::FLAG_ATTACK_POINT )
|
|
{
|
|
m_AttributeAmplifier.fAttackPointRight += fValue;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
m_AttributeAmplifier.fAttackPointLeft += fValue;
|
|
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAGIC_POINT )
|
|
{
|
|
m_AttributeAmplifier.fMagicPoint += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_DEFENCE )
|
|
{
|
|
m_AttributeAmplifier.fDefence += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAGIC_DEFENCE )
|
|
{
|
|
m_AttributeAmplifier.fMagicDefence += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ATTACK_SPEED )
|
|
{
|
|
m_AttributeAmplifier.fAttackSpeedRight += fValue;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
m_AttributeAmplifier.fAttackSpeedLeft += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_CAST_SPEED )
|
|
{
|
|
m_AttributeAmplifier.fCastingSpeed += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MOVE_SPEED )
|
|
{
|
|
// fRidingSpeed 수치가 생기면서 라이딩 중에도 기본 속도에 관여할 수 있게 변경 ( 2013-12-20 )
|
|
m_AttributeAmplifier.fMoveSpeed += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ACCURACY )
|
|
{
|
|
m_AttributeAmplifier.fAccuracyRight += fValue;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
m_AttributeAmplifier.fAccuracyLeft += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAGIC_ACCURACY )
|
|
{
|
|
m_AttributeAmplifier.fMagicAccuracy += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_CRITICAL )
|
|
{
|
|
m_AttributeAmplifier.fCritical += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_BLOCK )
|
|
{
|
|
m_AttributeAmplifier.fBlockChance += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_BLOCK_DEFENCE )
|
|
{
|
|
m_AttributeAmplifier.fBlockDefence += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_AVOID )
|
|
{
|
|
m_AttributeAmplifier.fAvoid += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAGIC_RESISTANCE )
|
|
{
|
|
m_AttributeAmplifier.fMagicAvoid += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAX_HP )
|
|
{
|
|
m_fMaxHPAmplifier += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAX_MP )
|
|
{
|
|
m_fMaxMPAmplifier += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAX_SP )
|
|
{
|
|
// 소환수에서만 사용
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_HP_REGEN_ADD )
|
|
{
|
|
m_AttributeAmplifier.fHPRegenPoint += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MP_REGEN_ADD )
|
|
{
|
|
m_AttributeAmplifier.fMPRegenPoint += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_SP_REGEN_ADD )
|
|
{
|
|
// 소환수에서만 사용
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_HP_REGEN_RATIO )
|
|
{
|
|
m_AttributeAmplifier.fHPRegenPercentage += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MP_REGEN_RATIO )
|
|
{
|
|
m_AttributeAmplifier.fMPRegenPercentage += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_CRITICAL_DAMAGE_BACKUP )
|
|
{
|
|
m_AttributeAmplifier.fCriticalPower += fValue * 3;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MAX_WEIGHT )
|
|
{
|
|
m_AttributeAmplifier.fMaxWeight += fValue;
|
|
}
|
|
|
|
if ( nBitset & StructState::FLAG_DAMAGE_REDUCE )
|
|
{
|
|
m_vDamageReducePercentInfo.push_back( DamageReduceInfo( 100, fValue, fValue, fValue, 0, 99, 0, 0, 0 ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructSummon::ampParameter( const int nBitset, const c_fixed10 & fValue, const bool bStat )
|
|
{
|
|
if( !bStat )
|
|
{
|
|
if( nBitset & StructState::FLAG_MAX_SP )
|
|
{
|
|
m_fMaxSPAmplifier += float( fValue );
|
|
}
|
|
if( nBitset & StructState::FLAG_SP_REGEN_ADD )
|
|
{
|
|
m_fSPRegenAddAmplifier += float( fValue );
|
|
}
|
|
}
|
|
|
|
StructCreature::ampParameter( nBitset, fValue, bStat );
|
|
}
|
|
|
|
void StructCreature::incParameter2( const int nBitset, const c_fixed10 & fValue, ParameterForSummon *pParam )
|
|
{
|
|
CreatureAttributeServer & Attribute = pParam ? pParam->Attribute : m_Attribute;
|
|
CreatureElementalResist & Resist = pParam ? pParam->Resist : m_Resist;
|
|
|
|
if( nBitset & StructState::FLAG_ET_NONE_RESIST )
|
|
{
|
|
Resist.nResist[ Elemental::TYPE_NONE ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_FIRE_RESIST )
|
|
{
|
|
Resist.nResist[ Elemental::TYPE_FIRE ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_WATER_RESIST )
|
|
{
|
|
Resist.nResist[ Elemental::TYPE_WATER ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_WIND_RESIST )
|
|
{
|
|
Resist.nResist[ Elemental::TYPE_WIND ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_EARTH_RESIST )
|
|
{
|
|
Resist.nResist[ Elemental::TYPE_EARTH ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_LIGHT_RESIST )
|
|
{
|
|
Resist.nResist[ Elemental::TYPE_LIGHT ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_DARK_RESIST )
|
|
{
|
|
Resist.nResist[ Elemental::TYPE_DARK ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_ATTACK_RANGE )
|
|
{
|
|
if( pParam || IsUsingBow() || IsUsingCrossBow() )
|
|
// 사정거리 단위, 내부적으로는 기획 DB 에서 ATTACK_RANGE_UNIT 를 곱한 값으로 처리된다.
|
|
Attribute.fAttackRange += fValue * GameRule::ATTACK_RANGE_UNIT;
|
|
}
|
|
|
|
if( !pParam )
|
|
{
|
|
if( nBitset & StructState::FLAG_ET_NONE_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_NONE, fValue, 0 ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_NONE, fValue, 0 ) );
|
|
}
|
|
if( nBitset & StructState::FLAG_ET_FIRE_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_FIRE, fValue, 0 ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_FIRE, fValue, 0 ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_WATER_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_WATER, fValue, 0 ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_WATER, fValue, 0 ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_WIND_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_WIND, fValue, 0 ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_WIND, fValue, 0 ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_EARTH_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_EARTH, fValue, 0 ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_EARTH, fValue, 0 ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_LIGHT_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_LIGHT, fValue, 0 ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_LIGHT, fValue, 0 ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_DARK_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_DARK, fValue, 0 ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_DARK, fValue, 0 ) );
|
|
}
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_CRITICAL_DAMAGE )
|
|
{
|
|
Attribute.fCriticalPower += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_PERFECT_BLOCK )
|
|
{
|
|
|
|
if (GetJobId()== 220 || GetJobId() == 343 || GetJobId() == 362) // Perfect Bloc Only for warrior
|
|
Attribute.fPerfectBlock += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_IGNORE_PHYSICAL_DEFENCE )
|
|
{
|
|
Attribute.fPhysicalDefIgnore += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_IGNORE_MAGICAL_DEFENCE )
|
|
{
|
|
Attribute.fMagicalDefIgnore += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_PHYSICAL_PENETRATION )
|
|
{
|
|
Attribute.fPhysicalPenetration += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_MAGICAL_PENETRATION )
|
|
{
|
|
Attribute.fMagicalPenetration += fValue;
|
|
}
|
|
|
|
if( !pParam )
|
|
{
|
|
if( nBitset & StructState::FLAG_HP_REGEN_STOP )
|
|
{
|
|
m_StatusFlag.On( STATUS_HP_REGEN_STOPPED );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MP_REGEN_STOP )
|
|
{
|
|
m_StatusFlag.On( STATUS_MP_REGEN_STOPPED );
|
|
}
|
|
}
|
|
}
|
|
|
|
void StructCreature::ampParameter2( const int nBitset, const c_fixed10 & fValue )
|
|
{
|
|
if( nBitset & StructState::FLAG_ET_NONE_RESIST )
|
|
{
|
|
m_ResistAmplifier.fResist[ Elemental::TYPE_NONE ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_FIRE_RESIST )
|
|
{
|
|
m_ResistAmplifier.fResist[ Elemental::TYPE_FIRE ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_WATER_RESIST )
|
|
{
|
|
m_ResistAmplifier.fResist[ Elemental::TYPE_WATER ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_WIND_RESIST )
|
|
{
|
|
m_ResistAmplifier.fResist[ Elemental::TYPE_WIND ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_EARTH_RESIST )
|
|
{
|
|
m_ResistAmplifier.fResist[ Elemental::TYPE_EARTH ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_LIGHT_RESIST )
|
|
{
|
|
m_ResistAmplifier.fResist[ Elemental::TYPE_LIGHT ] += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_DARK_RESIST )
|
|
{
|
|
m_ResistAmplifier.fResist[ Elemental::TYPE_DARK ] += fValue;
|
|
}
|
|
if( nBitset & StructState::FLAG_ET_ATTACK_RANGE )
|
|
{
|
|
if( IsUsingBow() || IsUsingCrossBow() )
|
|
m_AttributeAmplifier.fAttackRange += fValue;
|
|
}
|
|
|
|
|
|
if( nBitset & StructState::FLAG_ET_NONE_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_NONE, 0, fValue ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_NONE, 0, fValue ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_FIRE_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_FIRE, 0, fValue ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_FIRE, 0, fValue ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_WATER_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_WATER, 0, fValue ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_WATER, 0, fValue ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_WIND_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_WIND, 0, fValue ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_WIND, 0, fValue ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_EARTH_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_EARTH, 0, fValue ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_EARTH, 0, fValue ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_LIGHT_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_LIGHT, 0, fValue ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_LIGHT, 0, fValue ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_DARK_ADDITIONAL_DAMAGE )
|
|
{
|
|
m_vNormalAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_DARK, 0, fValue ) );
|
|
m_vRangeAdditionalDamage.push_back( AdditionalDamageInfo( 100, Elemental::TYPE_NONE, Elemental::TYPE_DARK, 0, fValue ) );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_CRITICAL_DAMAGE )
|
|
{
|
|
m_AttributeAmplifier.fCriticalPower += fValue;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_PERFECT_BLOCK )
|
|
{
|
|
m_AttributeAmplifier.fPerfectBlock += fValue;
|
|
}
|
|
|
|
// 아래 네 가지 파라메터는 증폭에 있어 여타 파라메터들과 다른 정책을 취한다.
|
|
// 즉, 증가와 증폭이 서로 다른 파라메터를 증가시킨다. 이 경우 % 파라메터는 0~100 사이의 값을 가져야 하므로 100을 곱한다.
|
|
if( nBitset & StructState::FLAG_ET_IGNORE_PHYSICAL_DEFENCE )
|
|
{
|
|
m_Attribute.fPhysicalDefIgnoreRatio += fValue * 100;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_IGNORE_MAGICAL_DEFENCE )
|
|
{
|
|
m_Attribute.fMagicalDefIgnoreRatio += fValue * 100;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_PHYSICAL_PENETRATION )
|
|
{
|
|
m_Attribute.fPhysicalPenetrationRatio += fValue * 100;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_ET_MAGICAL_PENETRATION )
|
|
{
|
|
m_Attribute.fMagicalPenetrationRatio += fValue * 100;
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_HP_REGEN_STOP )
|
|
{
|
|
m_StatusFlag.On( STATUS_HP_REGEN_STOPPED );
|
|
}
|
|
|
|
if( nBitset & StructState::FLAG_MP_REGEN_STOP )
|
|
{
|
|
m_StatusFlag.On( STATUS_MP_REGEN_STOPPED );
|
|
}
|
|
}
|
|
|
|
void StructCreature::finalizeStat()
|
|
{
|
|
if( m_Stat.strength < 0 ) m_Stat.strength = 0;
|
|
if( m_Stat.vital < 0 ) m_Stat.vital = 0;
|
|
if( m_Stat.dexterity < 0 ) m_Stat.dexterity = 0;
|
|
if( m_Stat.agility < 0 ) m_Stat.agility = 0;
|
|
if( m_Stat.intelligence < 0 ) m_Stat.intelligence = 0;
|
|
if( m_Stat.mentality < 0 ) m_Stat.mentality = 0;
|
|
if( m_Stat.luck < 0 ) m_Stat.luck = 0;
|
|
}
|
|
|
|
void StructCreature::onSynchronizeParameter( bool bStat )
|
|
{
|
|
for( std::vector< std::pair< int, std::pair< c_fixed10, int > > >::const_iterator it = m_vSynchronizedParameter.begin(); it != m_vSynchronizedParameter.end(); it++ )
|
|
{
|
|
int nBitset = (*it).first;
|
|
c_fixed10 sum = 0;
|
|
int count = 0;
|
|
|
|
if( bStat )
|
|
{
|
|
if( nBitset & StructState::FLAG_STR ) { ++count; sum += m_Stat.strength; }
|
|
if( nBitset & StructState::FLAG_VIT ) { ++count; sum += m_Stat.vital; }
|
|
if( nBitset & StructState::FLAG_AGI ) { ++count; sum += m_Stat.agility; }
|
|
if( nBitset & StructState::FLAG_DEX ) { ++count; sum += m_Stat.dexterity; }
|
|
if( nBitset & StructState::FLAG_INT ) { ++count; sum += m_Stat.intelligence; }
|
|
if( nBitset & StructState::FLAG_MEN ) { ++count; sum += m_Stat.mentality; }
|
|
if( nBitset & StructState::FLAG_LUK ) { ++count; sum += m_Stat.luck; }
|
|
|
|
if( count == 0 ) continue;
|
|
sum /= count;
|
|
sum *= (*it).second.first;
|
|
|
|
// 계산된 평균을 incParameter 함수에서 bStat 인자를 true로 주고 호출하는 편이 성능은 떨어지지만
|
|
// 추후에 incParameter를 Override해서 스텟 계산을 다르게 하는 클래스가 생길 경우에도 문제가 발생하지 않음
|
|
// Ex) StructSummon::incParameter에서 bStat == true 일 때 특정 패시브 스킬에 의해 스텟 증가치가 모두 1.5배가 되게 하는 유형의 기능
|
|
// 아래와 같이 해두면 incParameter virtual 함수 호출 부하와 switch문 처리 부하는 피할 수 있지만
|
|
// 위에서 설명된 내용이 추후에라도 추가될 경우 비정상 동작을 하게됨.
|
|
if( nBitset & StructState::FLAG_STR ) m_Stat.strength = sum;
|
|
if( nBitset & StructState::FLAG_VIT ) m_Stat.vital = sum;
|
|
if( nBitset & StructState::FLAG_AGI ) m_Stat.agility = sum;
|
|
if( nBitset & StructState::FLAG_DEX ) m_Stat.dexterity = sum;
|
|
if( nBitset & StructState::FLAG_INT ) m_Stat.intelligence = sum;
|
|
if( nBitset & StructState::FLAG_MEN ) m_Stat.mentality = sum;
|
|
if( nBitset & StructState::FLAG_LUK ) m_Stat.luck = sum;
|
|
}
|
|
else
|
|
{
|
|
if( nBitset & StructState::FLAG_ATTACK_POINT ) { ++count; sum += m_Attribute.fAttackPointRight; }
|
|
if( nBitset & StructState::FLAG_MAGIC_POINT) { ++count; sum += m_Attribute.fMagicPoint; }
|
|
if( nBitset & StructState::FLAG_DEFENCE ) { ++count; sum += m_Attribute.fDefence; }
|
|
if( nBitset & StructState::FLAG_MAGIC_DEFENCE ) { ++count; sum += m_Attribute.fMagicDefence; }
|
|
if( nBitset & StructState::FLAG_ATTACK_SPEED ) { ++count; sum += m_Attribute.fAttackSpeedRight; }
|
|
if( nBitset & StructState::FLAG_CAST_SPEED ) { ++count; sum += m_Attribute.fCastingSpeed; }
|
|
if( nBitset & StructState::FLAG_MOVE_SPEED ) { ++count; sum += m_Attribute.fMoveSpeed; }
|
|
if( nBitset & StructState::FLAG_ACCURACY ) { ++count; sum += m_Attribute.fAccuracyRight; }
|
|
if( nBitset & StructState::FLAG_MAGIC_ACCURACY ) { ++count; sum += m_Attribute.fMagicAccuracy; }
|
|
if( nBitset & StructState::FLAG_CRITICAL ) { ++count; sum += m_Attribute.fCritical; }
|
|
if( nBitset & StructState::FLAG_BLOCK ) { ++count; sum += m_Attribute.fBlockChance; }
|
|
if( nBitset & StructState::FLAG_BLOCK_DEFENCE ) { ++count; sum += m_Attribute.fBlockDefence; }
|
|
if( nBitset & StructState::FLAG_AVOID ) { ++count; sum += m_Attribute.fAvoid; }
|
|
if( nBitset & StructState::FLAG_MAGIC_RESISTANCE ) { ++count; sum += m_Attribute.fMagicAvoid; }
|
|
if( nBitset & StructState::FLAG_MAX_HP ) { ++count; sum += m_nMaxHP; }
|
|
if( nBitset & StructState::FLAG_MAX_MP ) { ++count; sum += m_nMaxMP; }
|
|
if( nBitset & StructState::FLAG_MAX_SP ) { /* SP는 사용하지 않음. */ }
|
|
if( nBitset & StructState::FLAG_HP_REGEN_ADD ) { ++count; sum += m_Attribute.fHPRegenPoint; }
|
|
if( nBitset & StructState::FLAG_MP_REGEN_ADD ) { ++count; sum += m_Attribute.fMPRegenPoint; }
|
|
if( nBitset & StructState::FLAG_SP_REGEN_ADD ) { /* SP는 사용하지 않음. */ }
|
|
if( nBitset & StructState::FLAG_HP_REGEN_RATIO ) { ++count; sum += m_Attribute.fHPRegenPercentage; }
|
|
if( nBitset & StructState::FLAG_MP_REGEN_RATIO ) { ++count; sum += m_Attribute.fMPRegenPercentage; }
|
|
if( nBitset & StructState::FLAG_MAX_WEIGHT ) { ++count; sum += m_Attribute.fMaxWeight; }
|
|
|
|
if( count == 0 ) continue;
|
|
sum /= count;
|
|
sum *= (*it).second.first;
|
|
|
|
if( nBitset & StructState::FLAG_ATTACK_POINT ) incParameter( StructState::FLAG_ATTACK_POINT, sum - m_Attribute.fAttackPointRight, false );
|
|
if( nBitset & StructState::FLAG_MAGIC_POINT) incParameter( StructState::FLAG_MAGIC_POINT, sum - m_Attribute.fMagicPoint, false );
|
|
if( nBitset & StructState::FLAG_DEFENCE ) incParameter( StructState::FLAG_DEFENCE, sum - m_Attribute.fDefence, false );
|
|
if( nBitset & StructState::FLAG_MAGIC_DEFENCE ) incParameter( StructState::FLAG_MAGIC_DEFENCE, sum - m_Attribute.fMagicDefence, false );
|
|
if( nBitset & StructState::FLAG_ATTACK_SPEED ) incParameter( StructState::FLAG_ATTACK_SPEED, sum - m_Attribute.fAttackSpeedRight, false );
|
|
if( nBitset & StructState::FLAG_CAST_SPEED ) incParameter( StructState::FLAG_CAST_SPEED, sum - m_Attribute.fCastingSpeed, false );
|
|
if( nBitset & StructState::FLAG_MOVE_SPEED ) incParameter( StructState::FLAG_MOVE_SPEED, sum - m_Attribute.fMoveSpeed, false );
|
|
if( nBitset & StructState::FLAG_ACCURACY ) incParameter( StructState::FLAG_ACCURACY, sum - m_Attribute.fAccuracyRight, false );
|
|
if( nBitset & StructState::FLAG_MAGIC_ACCURACY ) incParameter( StructState::FLAG_MAGIC_ACCURACY, sum - m_Attribute.fMagicAccuracy, false );
|
|
if( nBitset & StructState::FLAG_CRITICAL ) incParameter( StructState::FLAG_CRITICAL, sum - m_Attribute.fCritical, false );
|
|
if( nBitset & StructState::FLAG_BLOCK ) incParameter( StructState::FLAG_BLOCK, sum - m_Attribute.fBlockChance, false );
|
|
if( nBitset & StructState::FLAG_BLOCK_DEFENCE ) incParameter( StructState::FLAG_BLOCK_DEFENCE, sum - m_Attribute.fBlockDefence, false );
|
|
if( nBitset & StructState::FLAG_AVOID ) incParameter( StructState::FLAG_AVOID, sum - m_Attribute.fAvoid, false );
|
|
if( nBitset & StructState::FLAG_MAGIC_RESISTANCE ) incParameter( StructState::FLAG_MAGIC_RESISTANCE, sum - m_Attribute.fMagicAvoid, false );
|
|
if( nBitset & StructState::FLAG_MAX_HP ) m_nMaxHP += sum - m_nMaxHP;
|
|
if( nBitset & StructState::FLAG_MAX_MP ) m_nMaxMP += sum - m_nMaxMP;
|
|
if( nBitset & StructState::FLAG_MAX_SP ) { /* SP는 사용하지 않음. */ }
|
|
if( nBitset & StructState::FLAG_HP_REGEN_ADD ) incParameter( StructState::FLAG_HP_REGEN_ADD, sum - m_Attribute.fHPRegenPoint, false );
|
|
if( nBitset & StructState::FLAG_MP_REGEN_ADD ) incParameter( StructState::FLAG_MP_REGEN_ADD, sum - m_Attribute.fMPRegenPoint, false );
|
|
if( nBitset & StructState::FLAG_SP_REGEN_ADD ) { /* SP는 사용하지 않음. */ }
|
|
if( nBitset & StructState::FLAG_HP_REGEN_RATIO ) incParameter( StructState::FLAG_HP_REGEN_RATIO, sum - m_Attribute.fHPRegenPercentage, false );
|
|
if( nBitset & StructState::FLAG_MP_REGEN_RATIO ) incParameter( StructState::FLAG_MP_REGEN_RATIO, sum - m_Attribute.fMPRegenPercentage, false );
|
|
if( nBitset & StructState::FLAG_MAX_WEIGHT ) incParameter( StructState::FLAG_MAX_WEIGHT, sum - m_Attribute.fMaxWeight, false );
|
|
}
|
|
}
|
|
}
|
|
|
|
c_fixed10 StructCreature::CalcStatSum( const int bitset, const CreatureStatServer& statBeforeCalc )
|
|
{
|
|
c_fixed10 sum;
|
|
|
|
if( bitset == 0 )
|
|
{
|
|
return sum;
|
|
}
|
|
|
|
if( bitset & StructState::FLAG_STR )
|
|
{
|
|
sum += statBeforeCalc.strength;
|
|
}
|
|
if( bitset & StructState::FLAG_VIT )
|
|
{
|
|
sum += statBeforeCalc.vital;
|
|
}
|
|
if( bitset & StructState::FLAG_AGI )
|
|
{
|
|
sum += statBeforeCalc.agility;
|
|
}
|
|
if( bitset & StructState::FLAG_DEX )
|
|
{
|
|
sum += statBeforeCalc.dexterity;
|
|
}
|
|
if( bitset & StructState::FLAG_INT )
|
|
{
|
|
sum += statBeforeCalc.intelligence;
|
|
}
|
|
if( bitset & StructState::FLAG_MEN )
|
|
{
|
|
sum += statBeforeCalc.mentality;
|
|
}
|
|
if( bitset & StructState::FLAG_LUK )
|
|
{
|
|
sum += statBeforeCalc.luck;
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
c_fixed10 StructCreature::CalcAttributeSum( const int bitset1, const int bitset2, const CreatureAttributeServer& attrBeforeCalc )
|
|
{
|
|
c_fixed10 sum;
|
|
|
|
if( bitset1 == 0 && bitset2 == 0 )
|
|
{
|
|
return sum;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_ATTACK_POINT )
|
|
{
|
|
sum += attrBeforeCalc.fAttackPointRight;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
{
|
|
sum += attrBeforeCalc.fAttackPointLeft;
|
|
}
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_MAGIC_POINT )
|
|
{
|
|
sum += attrBeforeCalc.fMagicPoint;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_DEFENCE )
|
|
{
|
|
sum += attrBeforeCalc.fDefence;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_MAGIC_DEFENCE )
|
|
{
|
|
sum += attrBeforeCalc.fMagicDefence;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_ATTACK_SPEED )
|
|
{
|
|
sum += attrBeforeCalc.fAttackSpeedRight;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
sum += attrBeforeCalc.fAttackSpeedLeft;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_CAST_SPEED )
|
|
{
|
|
sum += attrBeforeCalc.fCastingSpeed;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_MOVE_SPEED )
|
|
{
|
|
sum += attrBeforeCalc.fMoveSpeed;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_ACCURACY )
|
|
{
|
|
sum += attrBeforeCalc.fAccuracyRight;
|
|
|
|
if( IsUsingDoubleWeapon() )
|
|
sum += attrBeforeCalc.fAccuracyLeft;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_MAGIC_ACCURACY )
|
|
{
|
|
sum += attrBeforeCalc.fMagicAccuracy;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_CRITICAL )
|
|
{
|
|
sum += attrBeforeCalc.fCritical;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_BLOCK )
|
|
{
|
|
sum += attrBeforeCalc.fBlockChance;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_BLOCK_DEFENCE )
|
|
{
|
|
sum += attrBeforeCalc.fBlockDefence;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_AVOID )
|
|
{
|
|
sum += attrBeforeCalc.fAvoid;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_MAGIC_RESISTANCE )
|
|
{
|
|
sum += attrBeforeCalc.fMagicAvoid;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_MAX_HP )
|
|
{
|
|
sum += m_nMaxHP;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_MAX_MP )
|
|
{
|
|
sum += m_nMaxMP;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_MAX_SP )
|
|
{
|
|
// 소환수에서만 사용
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_HP_REGEN_ADD )
|
|
{
|
|
sum += attrBeforeCalc.fHPRegenPoint;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_MP_REGEN_ADD )
|
|
{
|
|
sum += attrBeforeCalc.fMPRegenPoint;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_SP_REGEN_ADD )
|
|
{
|
|
// 소환수에서만 사용
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_HP_REGEN_RATIO )
|
|
{
|
|
sum += attrBeforeCalc.fHPRegenPercentage;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_MP_REGEN_RATIO )
|
|
{
|
|
sum += attrBeforeCalc.fMPRegenPercentage;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_MAX_WEIGHT )
|
|
{
|
|
sum += attrBeforeCalc.fMaxWeight;
|
|
}
|
|
|
|
if( bitset2 & StructState::FLAG_CRITICAL_DAMAGE )
|
|
{
|
|
sum += attrBeforeCalc.fCriticalPower;
|
|
}
|
|
|
|
if( bitset2 & StructState::FLAG_ET_PERFECT_BLOCK )
|
|
{
|
|
if (GetJobId() == 220 || GetJobId() == 343) // Perfect Bloc Only for warrior
|
|
sum += attrBeforeCalc.fPerfectBlock;
|
|
}
|
|
|
|
if( bitset2 & StructState::FLAG_ET_IGNORE_PHYSICAL_DEFENCE )
|
|
{
|
|
sum += attrBeforeCalc.fPhysicalDefIgnore;
|
|
}
|
|
|
|
if( bitset2 & StructState::FLAG_ET_IGNORE_MAGICAL_DEFENCE )
|
|
{
|
|
sum += attrBeforeCalc.fMagicalDefIgnore;
|
|
}
|
|
|
|
if( bitset2 & StructState::FLAG_ET_PHYSICAL_PENETRATION )
|
|
{
|
|
sum += attrBeforeCalc.fPhysicalPenetration;
|
|
}
|
|
|
|
if( bitset2 & StructState::FLAG_ET_MAGICAL_PENETRATION )
|
|
{
|
|
sum += attrBeforeCalc.fMagicalPenetration;
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
c_fixed10 StructSummon::CalcAttributeSum( const int bitset1, const int bitset2, const CreatureAttributeServer& attrBeforeCalc )
|
|
{
|
|
c_fixed10 sum;
|
|
|
|
if( bitset1 & StructState::FLAG_MAX_SP )
|
|
{
|
|
sum += m_nMaxSP;
|
|
}
|
|
|
|
if( bitset1 & StructState::FLAG_SP_REGEN_ADD )
|
|
{
|
|
sum += m_nSPRegenAdd;
|
|
}
|
|
|
|
return sum + StructCreature::CalcAttributeSum( bitset1, bitset2, attrBeforeCalc );
|
|
}
|
|
|
|
bool StructCreature::isSkillModified( std::vector< std::pair< int, int > > * pvPrevAddedSkill, std::vector< std::pair< int, int > > * pvAddedSkill )
|
|
{
|
|
if( pvPrevAddedSkill->size() != pvAddedSkill->size() ) return true;
|
|
|
|
std::vector< std::pair< int, int > >::const_iterator it;
|
|
std::vector< std::pair< int, int > >::const_iterator prevIt;
|
|
|
|
for( it = pvAddedSkill->begin(); it != pvAddedSkill->end(); it++ )
|
|
{
|
|
bool bFound = false;
|
|
|
|
for( prevIt = pvPrevAddedSkill->begin(); prevIt!= pvPrevAddedSkill->end(); prevIt++ )
|
|
{
|
|
if( (*it).first == (*prevIt).first )
|
|
{
|
|
if( (*it).second == (*prevIt).second )
|
|
{
|
|
bFound = true;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !bFound ) return true;
|
|
}
|
|
|
|
return false;
|
|
} |