Files
Leviathan/Client/Game/game/GameSystem/SPlayerInfoMgr.cpp
T
2026-06-01 12:46:52 +02:00

460 lines
12 KiB
C++

#include "stdafx.h"
#include "SPlayerInfoMgr.h"
#include "SGame.h"
#include "SGameMessage.h"
//#include "SGameMessageUI.h"
#include "SJobDB.h"
#include "SExpDB.h"
#include "SStringDB.h"
//#include "Util.h"
#include "STenacityDB.h"
#include "SSkillDB.h"
#include "SkillBaseFile.h"
#include "SUISysMsgDefine.h"
#include "SDebug_Util.h"
#include "Arena\\ArenaJoinSituationChecker.h"
#include "SGameSystem.h"
extern SGameSystem * g_pCurrentGameSystem;
namespace
{
const float c_fStateCheckTime = 1000.f;
const DWORD NO_TIME = -1;
};
//////////////////////////////////////////////////////////////////////////
// SStateSlot
SStateSlot::SStateSlot()
{
m_hTarget = NULL;
state_handle = NULL;
state_code = 0;
state_level = 0;
state_value = 0;
end_time = 0;
//start_time = 0;
m_dwBeginTime = NO_TIME;
m_dwRemainTime = NO_TIME;
m_dwMaxMilliTime = NO_TIME;
m_bStateStop = false;
m_bIsToggleSkill = false;
m_bIsValidProcTime = false;
}
SStateSlot::~SStateSlot()
{
}
void SStateSlot::Process( DWORD dwTime )
{
if( m_dwBeginTime == 0 )
m_dwBeginTime = dwTime;
m_dwTime = dwTime;
CheckTime();
}
void SStateSlot::SetStateTime( DWORD StartTime, DWORD EndTime )
{
end_time = EndTime;
m_dwBeginTime = ConvertTimeToMilli(StartTime);
m_dwRemainTime = NO_TIME;
m_dwMaxMilliTime = (end_time - StartTime)*10; //클라에서의 프로세스 타임은 밀리세컨드를 사용하기 때문에 10을 곱한다.
}
void SStateSlot::CheckTime()
{
// end_time == 0 이면 삭제 안됨
// 레벨이 0이거나, 시간이 초과되었으면 삭제
if( state_level == 0 || ( end_time != 0 && GetArTime() >= end_time ) ) //여기서는 AR_TIME쓰는 것이 아마도 최대한 서버와 시간을 동기화 하기 위해서 인듯
m_dwRemainTime = m_dwMaxMilliTime;
// m_bStateStop = true; -> 자체적으로 stop하는 것은 없다. 서버에서 지속효과 종료 메세지 오기 전까지 무조건 다 까만색으로 출력
else
{
// 현재 시간 계산
if( m_dwRemainTime == NO_TIME ) m_dwRemainTime = 0;
if( m_dwRemainTime != NO_TIME && m_dwRemainTime < m_dwMaxMilliTime )
{
DWORD dwTime = m_dwTime - m_dwBeginTime;
if( dwTime > 0 && dwTime <= m_dwMaxMilliTime)
m_dwRemainTime = dwTime;
}
}
m_bIsValidProcTime = true;
}
DWORD SStateSlot::ConvertTimeToMilli( AR_TIME at_time )
{
return (at_time - GetArTimeAdjust())*10;
}
//////////////////////////////////////////////////////////////////////////
// SPlayerInfo
SPlayerInfo::SPlayerInfo()
{
Clear();
}
SPlayerInfo::~SPlayerInfo()
{
}
void SPlayerInfo::Clear()
{
m_nStatus = 0;
m_nLevel = 0;
m_nExp = 0;
m_nHP = 0;
m_nMP = 0;
m_nMaxHP = 0;
m_nMaxMP = 0;
m_nJLv = 0;
m_nJp = 0;
m_nJobID = 0;
m_nCurExp = 0;
m_n64_MaxExp = 0;
m_n64_PreviosExp = 0;
m_nGold = money_t( 0 );
m_fInvenWeigth = 0.0f;
/// 2011.02.24 - prodongi
for (int i = 0; i < JOB_INDEX_MAX; ++i)
{
m_nOldJobID[i] = -1;
m_nOldJobLv[i] = -1;
}
m_strName.clear();
m_strJobName.clear();
m_nPermission = 0;
m_nPk_count = 0;
m_nDk_count = 0;
m_nRace = 0;
m_nCharisma = 0;
m_nMoral = 0;
m_nLogin_time = 0;
m_nSex = 0;
m_nX = 0;
m_nY = 0;
m_nStorage_gold= 0;
m_nStamina = 0;
m_nChaos = 0;
m_nMax_chaos = 0;
m_nMax_stamina = 0;
m_nChannel = 0;
m_nStaminaRegen= 0;
m_nEtherealStoneDurability = 0;
m_nHuntaHolicPoint = 0;
m_arContinuous_play_time = 0;
m_arPennalty_play_time = 0;
m_arMaxContinuous_play_time = 0;
m_tp = 0; /// 2011.03.28 - prodongi
m_isFirstTpSet = true;
m_bIsFirstImmoralSett = true;
ZeroMemory( &m_Stat, sizeof(m_Stat) );
ZeroMemory( &m_Attribute, sizeof(m_Attribute) );
m_ap = 0;
m_alias.clear();
}
void SPlayerInfo::SetJobName()
{
m_strJobName = GetJobDB().GetJobName(m_nJobID);
}
void SPlayerInfo::SetStat( const CreatureStat& stat, const CreatureAttribute& attribute )
{
::memcpy( &m_Stat, &stat, sizeof(m_Stat) );
::memcpy( &m_Attribute, &attribute, sizeof(m_Attribute) );
}
void SPlayerInfo::SetStatByItem( const CreatureStat& stat, const CreatureAttribute& attribute )
{
::memcpy( &m_StatByItem, &stat, sizeof(m_StatByItem) );
::memcpy( &m_AttributeByItem, &attribute, sizeof(m_AttributeByItem) );
// 빼준다
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 ;
m_Attribute.nCritical -= attribute.nCritical ;
m_Attribute.nCriticalPower -= attribute.nCriticalPower;
//TODO : Right/Left
m_Attribute.nAttackPointRight -= attribute.nAttackPointRight ;
m_Attribute.nAttackPointLeft -= attribute.nAttackPointLeft ;
m_Attribute.nDefence -= attribute.nDefence ;
m_Attribute.nBlockDefence -= attribute.nBlockDefence ;
m_Attribute.nMagicPoint -= attribute.nMagicPoint ;
m_Attribute.nMagicDefence -= attribute.nMagicDefence ;
//TODO : Right/Left
m_Attribute.nAccuracyRight -= attribute.nAccuracyRight;
m_Attribute.nAccuracyLeft -= attribute.nAccuracyLeft ;
m_Attribute.nMagicAccuracy -= attribute.nMagicAccuracy;
m_Attribute.nAvoid -= attribute.nAvoid ;
m_Attribute.nMagicAvoid -= attribute.nMagicAvoid ;
m_Attribute.nBlockChance -= attribute.nBlockChance ;
m_Attribute.nMoveSpeed -= attribute.nMoveSpeed ;
m_Attribute.nAttackSpeed -= attribute.nAttackSpeed ;
m_Attribute.nAttackRange -= attribute.nAttackRange ;
m_Attribute.nCastingSpeed -= attribute.nCastingSpeed ;
m_Attribute.nCoolTimeSpeed -= attribute.nCoolTimeSpeed;
m_Attribute.nItemChance -= attribute.nItemChance ;
m_Attribute.nHPRegenPercentage -= attribute.nHPRegenPercentage; // HP 리젠%
m_Attribute.nHPRegenPoint -= attribute.nHPRegenPoint ; // HP 리젠P
m_Attribute.nMPRegenPercentage -= attribute.nMPRegenPercentage; // MP 리젠%
m_Attribute.nMPRegenPoint -= attribute.nMPRegenPoint ; // MP 리젠P
/// 2011.03.30 왜 빼는 건가? - prodongi
m_Attribute.nPerfectBlock -= attribute.nPerfectBlock; // 퍼펙트블럭%
m_Attribute.nMagicalDefIgnore -= attribute.nMagicalDefIgnore; // 마법방어력무시P
m_Attribute.nMagicalDefIgnoreRatio -= attribute.nMagicalDefIgnoreRatio; // 마법방어력무시%
m_Attribute.nPhysicalDefIgnore -= attribute.nPhysicalDefIgnore; // 물리방어력무시P
m_Attribute.nPhysicalDefIgnoreRatio -= attribute.nPhysicalDefIgnoreRatio; // 물리방어력무시%
m_Attribute.nMagicalPenetration -= attribute.nMagicalPenetration; // 마법관통력P
m_Attribute.nMagicalPenetrationRatio -= attribute.nMagicalPenetrationRatio; // 마법관통력%
m_Attribute.nPhysicalPenetration -= attribute.nPhysicalPenetration; // 물리관통력P
m_Attribute.nPhysicalPenetrationRatio -= attribute.nPhysicalPenetrationRatio; // 물리관통력%
}
void SPlayerInfo::SetExp( __int64 nExp )
{
m_nExp = nExp;
RefreshExpInfo();
}
void SPlayerInfoMgr::SetGold( money_t nGold )
{
SPlayerInfo::SetGold( nGold );
ProcMsgAtStatic( &SIMSG_UI_SEND_DATA( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_TASKBAR, m_nGold, "gold" ) );
}
void SPlayerInfo::SetLevel( int nLevel )
{
m_nLevel = nLevel;
RefreshExpInfo();
}
void SPlayerInfo::RefreshExpInfo()
{
// 레벨에 따른 exp 재 계산
m_n64_PreviosExp = GetExpDB().GetNeedExp( m_nLevel - 1 );
m_n64_MaxExp = GetExpDB().GetNeedExp(m_nLevel) - m_n64_PreviosExp;
m_nCurExp = m_nExp - m_n64_PreviosExp;
}
//////////////////////////////////////////////////////////////////////////
// SPlayerInfoMgr
SPlayerInfoMgr::SPlayerInfoMgr()
: SGameUIMgr() // 2011.03.29 - servantes
{
Clear();
}
SPlayerInfoMgr::~SPlayerInfoMgr()
{
}
void SPlayerInfoMgr::Clear()
{
m_nPlayerState = STATE_NONE;
m_hPlayer = 0;
m_hTarget = 0;
m_hTradeTarget = 0;
m_dwTime = 0;
m_strTargetName.clear();
m_strTradeTargetName.clear();
m_GameObjType = TS_ENTER::GAME_OBJTYPE_MAX;
}
void SPlayerInfoMgr::ResetInfo()
{
Clear();
SPlayerInfo::Clear();
}
int SPlayerInfoMgr::GetCurrentLocation()
{
if( m_pGame == NULL ) return -1;
return m_pGame->GetCurrentLocation();
}
void SPlayerInfoMgr::Process( DWORD dwTime )
{
m_dwTime = dwTime;
}
void SPlayerInfoMgr::ChangeState( int nState )
{
if( m_nPlayerState != STATE_NONE )
ProcMsgAtStatic( &SIMSG_SHOW_UIWINDOW( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_INPUTNUMBER, false) );
if( nState != m_nPlayerState )
{
if( nState == STATE_NONE )
{
switch(m_nPlayerState)
{
case STATE_TRADE:
{
//기존 트레이드 상태를 취소 하는 것인가?
_oprint( "SPlayerInfoMgr::ChangeState\n" );
SMSG_TRADE TradeMsg;
TradeMsg.mode = TS_TRADE::CANCEL_TRADE;
TradeMsg.rq_mode = true;
TradeMsg.target_player = m_hTradeTarget;
ProcMsgAtStatic( &TradeMsg );
}
break;
case STATE_STORAGE:
ProcMsgAtStatic( &SIMSG_SHOW_UIWINDOW( SIMSG_TOGGLE_UIWINDOW::UIWINDOW_STORAGE, false) );
break;
case STATE_STALL:
break;
}
}
}
m_nPlayerState = nState;
}
void SPlayerInfoMgr::SetPlayerStat( const CreatureStat& stat, const CreatureAttribute& attribute, int nType )
{
switch(nType)
{
case TS_SC_STAT_INFO::TOTAL:
SetStat( stat, attribute );
break;
case TS_SC_STAT_INFO::BY_ITEM:
SetStatByItem( stat, attribute );
break;
}
}
//기본 공격에 시전 1, 4, 5 소스
bool SPlayerInfoMgr::IsSCastAttack( int nAttackType )
{
if( nAttackType == S_CAST_ATTACK || nAttackType == S_CAST_ATTACK_COMBAT || nAttackType == S_CAST_ATTACK_COMBAT_MAGIC )
return true;
return false;
}
//기본 공격에 피격 21, 24, 25 소스
bool SPlayerInfoMgr::IsSHitAttack( int nAttackType )
{
if( nAttackType == S_HIT_ATTACK || nAttackType == S_HIT_ATTACK_COMBAT || nAttackType == S_HIT_ATTACK_COMBAT_MAGIC )
return true;
return false;
}
//기본 공격에 히트 41, 44, 45 타겟
bool SPlayerInfoMgr::IsTHitAttack( int nAttackType )
{
if( nAttackType == T_HIT_ATTACK || nAttackType == T_HIT_ATTACK_COMBAT || nAttackType == T_HIT_ATTACK_COMBAT_MAGIC )
return true;
return false;
}
//전투 스킬에 시전 2, 4, 5 소스
bool SPlayerInfoMgr::IsSCastCombat( int nCombatType, int nFxType )
{
if( nCombatType == S_CAST_COMBAT || nCombatType == S_CAST_ATTACK_COMBAT || nCombatType == S_CAST_ATTACK_COMBAT_MAGIC )
{
//2~5까지는 근접용 스킬
//근접용 스킬인가 검사
if( nFxType == 2 || nFxType == 3 || nFxType == 4 || nFxType == 5)
return true;
}
return false;
}
//전투 스킬에 피격 22, 24, 25 소스
bool SPlayerInfoMgr::IsSHitCombat( int nCombatType, int nFxType )
{
if( nCombatType == S_HIT_COMBAT || nCombatType == S_HIT_ATTACK_COMBAT || nCombatType == S_HIT_ATTACK_COMBAT_MAGIC )
{
//2~5까지는 근접용 스킬
if( nFxType == 2 || nFxType == 3 || nFxType == 4 || nFxType == 5)
return true;
}
return false;
}
//전투 스킬에 피격 42, 44, 45 타겟
bool SPlayerInfoMgr::IsTHitCombat( int nCombatType, int nFxType )
{
if( nCombatType == T_HIT_COMBAT || nCombatType == T_HIT_ATTACK_COMBAT || nCombatType == T_HIT_ATTACK_COMBAT_MAGIC )
{
//2~5까지는 근접용 스킬
if( nFxType == 2 || nFxType == 3 || nFxType == 4 || nFxType == 5)
return true;
}
return false;
}
//매직 스킬 시전 3, 5 소스
bool SPlayerInfoMgr::IsSCastMagic( int nMagicType, int nFxType )
{
if( nMagicType == S_CAST_MAGIC || nMagicType == S_CAST_ATTACK_COMBAT_MAGIC )
{
// 0, 1 마법류 스킬
if( nFxType == 0 || nFxType == 1 )
return true;
}
return false;
}
//매직 스킬 피격 23, 25 소스
bool SPlayerInfoMgr::IsSHitMagic( int nMagicType, int nFxType )
{
if( nMagicType == S_HIT_MAGIC || nMagicType == S_HIT_ATTACK_COMBAT_MAGIC )
{
// 0, 1 마법류 스킬
if( nFxType == 0 || nFxType == 1 )
return true;
}
return false;
}
//매직 스킬 히트 43, 45 타겟
bool SPlayerInfoMgr::IsTHitMagic( int nMagicType, int nFxType )
{
if( nMagicType == T_HIT_MAGIC || nMagicType == T_HIT_ATTACK_COMBAT_MAGIC )
{
// 0, 1 마법류 스킬
if( nFxType == 0 || nFxType == 1 )
return true;
}
return false;
}
void SPlayerInfoMgr::SetTradeTarget(AR_HANDLE hTarget, const char *szName)
{
/// 2012.05.21 - prodongi
if (hTarget || m_hTradeTarget != hTarget)
checkValidArenaJoinSituationAtTrade();
m_hTradeTarget = hTarget;
m_strTradeTargetName = szName;
}
/// 2012.05.21 - prodongi
void SPlayerInfoMgr::checkValidArenaJoinSituationAtTrade()
{
sArenaJoinSituationCondition situationCondition;
/// way
situationCondition.m_notificationWays = cArenaJoinSituationChecker::WAY_NOTIFICATION_WND;
/// situation
situationCondition.add(cArenaJoinSituationChecker::SITUATION_ARENA_WAITING, S(2457));
situationCondition.add(cArenaJoinSituationChecker::SITUATION_ARENA_WAITING_COUNT, S(2457));
g_pCurrentGameSystem->isValidArenaJoinSituation(situationCondition);
}