Files
2022-10-26 12:25:11 +08:00

2700 lines
185 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "stdafx.h"
#include "Player.h"
#include <SCSlotContainer.h>
#include <SCItemSlotContainer.h>
#include <SCSKillSlotContainer.h>
#include <PacketStruct_DG.h>
#include <PacketStruct_AG.h>
#include <PacketStruct_GZ.h>
#include <MapInfoParser.h>
#include <CharInfoParser.h>
#include <ExpValueInfoParser.h>
#include <CharacterFormula.h>
//==================================================================================================
// GameServer
#include "GameServerEx.h"
#include "ItemManager.h"
#include "WarehouseSlotContainer.h"
#include "EquipmentSlotContainer.h"
#include "InventorySlotContainer.h"
#include "VendorSlotContainer.h"
#include "Map.h"
#include "GameZone.h"
// Player
#include "MissionManager.h"
#include "QuestManager.h"
#include "QuickManager.h"
#include "QuickStyleManager.h"
#include "./SkillSystem/PerkManager.h"
#include "SKillSlotManager.h"
#include "StatusManager.h"
#include "QuestManager_Concrete.h"
#include <AreaConquestCommonHeader.h>
#include "QuestInfoManagerEx.h"
#include "StatisticsManager.h"
#include "GameCHuntingRoom.h"
#include "GameInstanceDungeon.h"
#include "CHuntingManager.h"
#include "ChaoState.h"
#include "MoveStateControl.h"
#include "PlayerRider.h"
// Object
#include "Collection.h"
#include "CollectedList.h"
// GameGuild
#include "GameGuildManager.h"
#include "GameGuild.h"
#include "GameGuildExtension.h"
//
#include "GMCmdManager.h"
//
#include "DragonTransStatus.h"
// Party
#include "GameParty/NewGameParty.h"
#include "GameParty/NewGamePartyManager.h"
//
//==================================================================================================
// Contents
//
// Domination
#include "GameDominationManager.h" //_NA_0_20100208_DOMINATION_AREA_INFO
#include "FriendInvitation/GFriendInvitationController.h"
#ifdef _NA_0_20110308_SKILL_COOL_TIME_STORAGE
#include "./SkillSystem/SkillCoolTimeAccessor.h"
#endif
#include "ItemExpDistributor.h"
#ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
#include <ServerOptionParserEx.h>
#endif //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
#ifdef _NA_007919_20141211_ADD_GMCOMMAND_EVENT
#include "PeakTimeEvent.h"
#endif //_NA_007919_20141211_ADD_GMCOMMAND_EVENT
// CHANGES, f100827.4L, this is extracted from the SCPlayer
// this method is called by a 'DG_CHARINFO_CHAR_ITEM_CMD' protocol handler
void Player::SetCharInfo(BASE_PLAYERINFO* char_info)
{
// NOTE, a next flow sequence is as follows.
// DG_CHARINFO_CHAR_ITEM_CMD ->
// Player::SetCharInfo ->
// (this flow is copied from a custom logic. removable)
// PlayerAttributeLinker::SetCharInfo ->
// Player::OnSetCharInfo (next method)
attributes_linker_.SetCharInfo(char_info);
}
void Player::OnSetCharInfo()
{
const eCHAR_TYPE char_type = GetCharType();
const eCHAR_CONDITION char_condition = GetStatusManager()->GetCondition();
//
;{
// HPMPSD恢复率
int recover_hp = CalcHPRecover(char_type, char_info_.m_sVitality,
char_condition, char_info_.m_LV);
int recover_mp = CalcMPRecover(char_type, char_info_.m_sSpirit,
char_condition);
int recover_sd = CalcSDRecover(char_type,
char_condition,
CHAR_ACTION_CONDITION_NONE,
char_info_.m_LV);
m_Attr.SetCharInfo(&char_info_, recover_hp, recover_mp, recover_sd);
m_Attr.Update();
};
//
#if !defined(_NA002217_100820_EP2_SKILL_SYSTEM_VERSION_)
m_pSkillSlotManager->ApplyStyleBuff(GetBaseSelectedStyle());
#endif
//
if(char_type == eCHAR_BERSERKER)
{
SetMP(0);
MSG_CG_STATUS_CHANGE_MP_BRD MPMsg;
MPMsg.m_dwObjectKey = GetObjectKey();
MPMsg.m_dwTargetMP = GetMP();
SendPacket(&MPMsg, sizeof(MPMsg));
}
#ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
else if (char_type == eCHAR_WITCHBLADE)
{
SetFP(0);
MSG_CG_STATUS_CHANGE_FP_CMD FPMsg;
FPMsg.object_key = GetObjectKey();
FPMsg.m_dwTargetFP = GetFP();
SendPacket(&FPMsg, sizeof(FPMsg));
}
#endif //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
//保存下一级升级经验.
SetNextExp();
//疲劳度系统初始化
#ifndef __CN_OO0510__FATIGUE_MATCHING_UPDATE
m_pFatigueManager->Init(this);
#endif
//库存Max Size决定=TabNum*Num Of Slot Per Tab
// (CHANGES) (WAVERIX) 归纳出玩家库存的本地参考
CInventorySlotContainer* inventory = static_cast<CInventorySlotContainer*>(\
GetItemManager()->GetItemSlotContainer(SI_INVENTORY));
// assert(MAX_INVENTORY_TAB_NUM + pInfo->m_ExtraInventoryTabCount <= 10)
inventory->SetMaxSlotNum(\
(MAX_INVENTORY_TAB_NUM + char_info_.m_ExtraInventoryTabCount) * MAX_INVENTORY_SLOT_PER_TAB);
// (CHANGES) (f100328.6L) (WAVERIX) 设置库存排序插入配置
inventory->UpdateInventoryConfiguration(char_info_.m_InventoryConfig);
GetItemManager()->GetItemSlotContainer(SI_EQUIPMENT)->SetMaxSlotNum(MAX_EQUIPMENT_SLOT_NUM);
// (CHANGES) (f100714.2L) 预取以支持延迟事件查询过程
#ifdef _NA_20100307_BETAKEY_SYSTEM
SetBetaKeyInfo(char_info_.beta_key_);
#endif
#ifdef _NA_007919_20141211_ADD_GMCOMMAND_EVENT
//第一次入场时,如果正在进行gm经验活动,可以发送经验率信息
PeakTimeEvent::Instance()->SendProgressEventExpRateInfo(this);
#endif //_NA_007919_20141211_ADD_GMCOMMAND_EVENT
/*
// 请求应征的活动信息
MSG_DG_EVENT_ITEM_STATUS_SYN sendMsg;
sendMsg.m_dwKey = char_info_.m_UserGuid;
sendMsg.m_CharGUID = char_info_.m_CharGuid;
SendToGameDBPServer(&sendMsg, sizeof(sendMsg));
//MessageOut(eFULL_LOG, "User EventInfo Req[%u][C:%u]", sendMsg.m_dwKey, sendMsg.m_CharGUID);
*/
}
void
Player::SerializeSkillTotalInfo(SKILL_TOTAL_INFO& rSkillInfo, eSERIALIZE eType)
{
// CHANGES f100825.2L, 将例程更改为完全序列化的技能流转换器
m_pSkillSlotManager->SerializeSkillStreamTotal(&rSkillInfo, eType);
/*
if(eType == SERIALIZE_LOAD)
{
rSkillInfo.m_Count = 0;
SKILLSLOT* pSkillSlot = rSkillInfo.m_Slot;
POSTYPE total = 0;
for(POSTYPE i=0;i<MAX_SKILL_SLOT_NUM;++i)
{
if(!m_pSkillSlotManager->IsEmpty(i))
{
pSkillSlot[total].m_Pos = i;
m_pSkillSlotManager->SerializeSkillStream(pSkillSlot[total].m_Pos, &pSkillSlot[total].m_Stream,SERIALIZE_LOAD);
++total;
++rSkillInfo.m_Count;
}
}
}
else if(eType == SERIALIZE_STORE)
{
SKILLSLOT* pSlot = rSkillInfo.m_Slot;
POSTYPE start = 0;
POSTYPE total = rSkillInfo.m_Count;
ASSERT(m_pSkillSlotManager->GetSkillSlotContainer()->GetSlotNum() == 0);
for(POSTYPE i=start;i<total;++i)
m_pSkillSlotManager->SerializeSkillStream(pSlot[i].m_Pos, &pSlot[i].m_Stream,SERIALIZE_STORE);
}
*/
}
#if !defined(_NA_002289_20110322_EQUIPMENTS_CALCULATOR_CHANGES_FOR_IMPROVEMENT)
//==================================================================================================
// CHANGES: f110420.5L, 移到默认条件例程
//支持扩展的可渲染项选择
bool Player::IsRenderEquipItem(POSTYPE pos) const
{
bool renderabled = CEquipmentSlotContainer::IsDefaultRenderableEquipItem(pos);
//
return renderabled;
}
#endif
//==================================================================================================
POSTYPE
Player::SerializeRenderEquipItemBaseInfo(EQUIP_ITEM_BASEINFO::data_type* const OUT result_slot_list) const
{
#ifdef _NA_002289_20110322_EQUIPMENTS_CALCULATOR_CHANGES_FOR_IMPROVEMENT
typedef CEquipmentSlotContainer::SLOT_LINEAR_LIST SLOT_LINEAR_LIST;
CEquipmentSlotContainer* const equip_container = static_cast<CEquipmentSlotContainer*>(
m_pItemManager->GetItemSlotContainer(SI_EQUIPMENT));
//
const ns_formula::EquipSlotsManageInfo* manage_info = equip_container->GetEquipmentManageInfo();
//----------------------------------------------------------------------------------------------
EQUIP_ITEM_BASEINFO::data_type* dest_it = result_slot_list;
//
const SLOT_LINEAR_LIST& slot_list = equip_container->GetSlotList();
SLOT_LINEAR_LIST::const_iterator slot_it = slot_list.begin();
const SLOT_LINEAR_LIST::const_iterator slot_end = slot_list.end();
for (int pos = 0; slot_it != slot_end; ++pos, ++slot_it)
{
const SCItemSlot* item_slot = static_cast<SCItemSlot*>(slot_it->slot);
if (item_slot->GetItemCode() == 0) {
continue;
};
if (CEquipmentSlotContainer::kDefaultRenderableEquipItems[pos] == false) {
continue;
};
if (const ns_formula::EquipSlotsManageInfo::Node* node = &manage_info->slots[pos]) {
if (node->activated == false) {
continue;
};
};
//-------------------------------------------
if (EQUIP_ITEM_BASEINFO::data_type* target = dest_it++)
{
target->m_Pos = static_cast<POSTYPE>(pos);
item_slot->CopyOut(target->m_Stream);
};
//-------------------------------------------
};//end 'foreach slot_list'
//
const POSTYPE number_of_real_renderable_equips =
static_cast<POSTYPE>(dest_it - result_slot_list);
return number_of_real_renderable_equips;
//----------------------------------------------------------------------------------------------
#else //if !defined(_NA_002289_20110322_EQUIPMENTS_CALCULATOR_CHANGES_FOR_IMPROVEMENT)
POSTYPE total = 0;
for (POSTYPE i = 0; i < MAX_EQUIPMENT_SLOT_NUM; ++i)
{
if(m_pItemManager->IsEmpty(SI_EQUIPMENT, i) == false && IsRenderEquipItem(i))
{
result_slot_list[total].m_Pos = i;
m_pItemManager->SerializeItemStream(SI_EQUIPMENT,
result_slot_list[total].m_Pos, &result_slot_list[total].m_Stream, SERIALIZE_LOAD);
++total;
}
}
return total;
#endif
}
//
//==================================================================================================
//
int
Player::GetPlayerRenderInfo(BOOLEAN is_player_render, PLAYER_RENDER_INFO_EX* OUT pack_info)
{
const WzVector* pPos = GetPosPtr();
const BASE_PLAYERINFO* pInfo = &char_info_;
const Attributes& rAttr = GetAttr();
PLAYER_RENDER_INFO_EX render_temp;
// (WARNING) C COLLECTKEY的生成者需要注意...-.-;;;;
ZeroMemory(&render_temp, sizeof(render_temp));
render_temp.is_player_render = !!is_player_render;
render_temp.player_key = (WORD)GetObjectKey();
render_temp.hp = (PLAYERHP)GetHP();
render_temp.max_hp = (PLAYERHP)GetMaxHP();
render_temp.level = pInfo->m_LV;
strncpy(render_temp.char_name, pInfo->m_tszCharName, _countof(render_temp.char_name));
render_temp.char_name[_countof(render_temp.char_name) - 1] = '\0';
//_NA_000000_20121120_NONAME_IN_SSQ
// 在特定的Zone中不能出现角色的名字,所以要删除和传达角色的名字
//堕落的寺院,扎菲激战地
if (GameZone* const pGameZone = GetGameZonePtr())
{
if( pGameZone->GetZoneType() == eZONETYPE_INSTANCE )
{
GameInstanceDungeon* const pDungeon = static_cast<GameInstanceDungeon*>( pGameZone );
if( pDungeon && pDungeon->GetTypeOfIndun() == INDUN_KIND_SS_QUEST)
{
// 堕落的寺院
memset(render_temp.char_name, 0, sizeof(render_temp.char_name));
}
#ifdef _NA_008679_20160202_REWORK_BATTLEGROUND
else if(this->IsThereBattleGroundZone() == true)
{
// 扎菲激战地
//假名处理
memset(render_temp.char_name, 0, sizeof(render_temp.char_name));
strncpy(render_temp.char_name, this->GetBattleGroundPlayerInfo().GetFalseName(),
_countof(render_temp.char_name));
BattleGround* battleground =
static_cast<BattleGround*>(pDungeon->GetChaosZoneManager()->GetCurrentZone());
if (battleground != NULL)
{
render_temp.special_scene_item_code = battleground->GetTeamFalseCostumeCode(this);
}
}
#endif //_NA_008679_20160202_REWORK_BATTLEGROUND
}
#ifdef _NA_008069_20150210_ADD_SPA_SYSTEM
else if (pGameZone->GetZoneType() == eZONETYPE_SPA_FIELD)
{
render_temp.special_scene_item_code = GetPlayerSpaInfo()->GetSpaTicketCode();
}
#endif //_NA_008069_20150210_ADD_SPA_SYSTEM
}
render_temp.position = *pPos;
render_temp.selected_style_code = GetSelectedStyle();
render_temp.move_speed_ratio = (WORD)rAttr.GetMoveSpeedRatio();
render_temp.attack_speed_ratio = (WORD)rAttr.GetAttSpeedRatio();
StatusManager* const pStatusManager = GetStatusManager();
const StatusField& status_field = pStatusManager->Status;
const STATE_GM_INFO& rGMInfo = GetGMStateInfo();
//
render_temp.hair_style = pInfo->m_byHair;
if(rGMInfo.m_TransOn)
render_temp.transparent = 1;
//_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND
else if (GetBattleGroundPlayerInfo().GetPlayerState() == kPlayerStateStandbyResurection)
render_temp.transparent = 3;
#ifdef _NA_007065_20140217_CHAOSZONE_GOLDRUSH
else if (GetGoldRushPlayerInfo().GetPlayerState() == kPlayerStateStandbyResurection)
render_temp.transparent = 3;
#endif //_NA_007065_20140217_CHAOSZONE_GOLDRUSH
else if(status_field.IsPlayer_TransOn())
render_temp.transparent = 2;
else
render_temp.transparent = 0;
render_temp.height = pInfo->m_byHeight;
render_temp.face = pInfo->m_byFace;
render_temp.helmet = GetHelmetOption();
#ifdef _NA_000000_20120420_EQUIPMENTS_VISIBLE_WING
render_temp.wing = GetWingOption();
#endif //_NA_000000_20120420_EQUIPMENTS_VISIBLE_WING
switch(const BYTE sts = GetSts())
{
case eGM_GRADE_FIRST: case eGM_GRADE_SECOND: case eGM_GRADE_THIRD:
render_temp.gm_grade = sts - eGM_GRADE_BASE;
break;
case eGM_GRADE_VIRTUAL:
render_temp.gm_grade = 4;
break;
}
render_temp.pcroom = !!GetReservedValue();
render_temp.char_condition = (BYTE)pStatusManager->GetCondition();
render_temp.char_class = pInfo->m_byClassCode;
ChaoState& rChaoState = GetChaoState();
render_temp.boradori = !!rChaoState.IsBoradori();
render_temp.chao_state = (BYTE)rChaoState.GetChaoState();
render_temp.behave_state = (BYTE)GetBehave();
#ifdef _NA_002050_20110216_ADD_GENDER
render_temp.gender = pInfo->gender;
#endif
#ifdef _NA001955_110210_WING_COSTUME
render_temp.spread_wings = (status_field.FIELD & status_field.ENABLE_SPREAD_WINGS) != 0;
#endif
#ifdef _NA_003027_20111013_HONOR_SYSTEM
render_temp.honor_title = pInfo->honor_title_;
#endif //_NA_003027_20111013_HONOR_SYSTEM
//_NA_004035_20120227_COSTUME_ITEM
//메인코스튬
render_temp.is_equipped_costume = pInfo->is_equipped_costume_;
if (render_temp.is_equipped_costume)
{
CInventorySlotContainer* const inventory_container =
static_cast<CInventorySlotContainer*>(GetItemManager()->GetItemSlotContainer(SI_INVENTORY));
const SCItemSlot& item_slot =
static_cast<SCItemSlot&>( inventory_container->GetSlot(pInfo->costume_item_pos_) );
const BASE_ITEMINFO* const costume_item_info = item_slot.GetItemInfo();
if (costume_item_info)
{
render_temp.costume_item_code = costume_item_info->m_Code;
}
}
#ifdef _NA_008610_20160104_ADD_DECORATECOSTUME
render_temp.is_equipped_decorate_costume = pInfo->is_equipped_decorate_costume_;
if (render_temp.is_equipped_decorate_costume)
{
CInventorySlotContainer* const inventory_container =
static_cast<CInventorySlotContainer*>(GetItemManager()->GetItemSlotContainer(SI_INVENTORY));
const SCItemSlot& item_slot =
static_cast<SCItemSlot&>( inventory_container->GetSlot(pInfo->decorate_costume_item_pos_) );
const BASE_ITEMINFO* const deco_costume_item_info = item_slot.GetItemInfo();
if (deco_costume_item_info)
{
render_temp.decorate_costume_item_code = deco_costume_item_info->m_Code;
}
}
#endif //_NA_008610_20160104_ADD_DECORATECOSTUME
#ifdef _NA_006683_20130502_EQUIPMENTS_VISIBLE_COSTUME
render_temp.costume = GetCostumeOption();
#endif // _NA_006683_20130502_EQUIPMENTS_VISIBLE_COSTUME
#ifdef _NA_000000_20130206_BROADCAST_ITEM_SCORE
CEquipmentSlotContainer* const equip_container =
static_cast<CEquipmentSlotContainer*>(GetItemManager()->GetItemSlotContainer(SI_EQUIPMENT));
const ns_formula::EquipSlotsManageInfo* const equip_manage_info = \
equip_container->GetEquipmentManageInfo();
const ns_formula::EquipSlotsManageInfo::ItemScoreInfo& item_score_info = \
equip_manage_info->item_score_info;
#ifdef _NA_008679_20160202_REWORK_BATTLEGROUND
//扎皮尔激战地不提供装备评分 xiaomi 修改評分查看
//if (IsThereBattleGroundZone() == true)
// {
render_temp.total_item_score_ = item_score_info.GetTotalScore();
// }
//else
// {
// render_temp.total_item_score_ = 0;
//}
#else
render_temp.total_item_score_ = item_score_info.GetTotalScore();
#endif //_NA_008679_20160202_REWORK_BATTLEGROUND
#endif // _NA_000000_20130206_BROADCAST_ITEM_SCORE
//
//----------------------------------------------------------------------------------------------
// <REF>定义需要渲染的各种视觉效果
render_temp.special_effects = RENDER_EFFECT.GetEffect();
//----------------------------------------------------------------------------------------------
//__NA_0_PET_SYSTEM, __NA_1131_PET_NAME_SETTING(901)
render_temp.is_summoned_pet = !!m_PetManager.AlreadySummonedPet();
if(render_temp.is_summoned_pet) { // (f100524.2L)
const sPet_Script_Info* script_info = m_PetManager.GetImagePetScriptInfo();
render_temp.pet_index = script_info->m_wIndexCode;
render_temp.pet_fullness = m_PetManager.GetFullness();
render_temp.pet_intimacy = m_PetManager.GetIntimacy();
if(m_PetManager.IsSetPetName()) {
const char* pet_name = m_PetManager.GetPetName();
if(pet_name) { // (NOTE)日前有零发生的事例。先维持住吧。.
strncpy(render_temp.pet_name, pet_name, _countof(render_temp.pet_name));
render_temp.pet_name[_countof(render_temp.pet_name) - 1] = '\0';
}
}
}
//----------------------------------------------------------------------------------------------
//__NA_1119_CHANGE_ETHER_EXPEND_STYLE
if(m_EtherManager.IsActive()) {
tagEtherBulletInfo* pBulletInfo = m_EtherManager.GetBulletOption();
if(pBulletInfo)
render_temp.ether_device_index = pBulletInfo->m_byEffectCode;
}
//----------------------------------------------------------------------------------------------
if(render_temp.is_riding = status_field.IsRidingRider()) {
Rider->GetRiderItemStream(&render_temp.rider_item_slot);
}
//----------------------------------------------------------------------------------------------
//render_temp.collection_render_info;
if(m_pCollectedList->IsCollecting()) {
Collection* pCollection =
(Collection*)GetField()->FindObject(COLLECTION_OBJECT,
m_pCollectedList->GetObjKeyCollecting());
if(pCollection) {
COLLECT_PLAYER_RENDER_INFO& collection_render_info = render_temp.collection_render_info;
pCollection->GetRenderInfo(collection_render_info);
SUNLOG(eDEV_LOG,
"[发送Collect COLLECT_PLAYER_RENDER_INFO信息] "
"ObjectKey[%d]集合ID[%d]重新初始化[%d]",
render_temp.char_name,
collection_render_info.m_dwObjectKey,
collection_render_info.m_CollectionID,
collection_render_info.m_dwRemainTime);
}
}
//----------------------------------------------------------------------------------------------
// STATE填满INFO-村里除了龙变身外,不发送状态信息.
pStatusManager->SerialzieStatusInfo(render_temp.state_total_info, !is_player_render);
int written_len = render_temp.ConvertForSend(is_player_render, render_temp, pack_info);
return written_len;
}
//{__NA_0_20090720_GUILD_RENDER_INFO_MODIFY
BOOL
Player::GetGuildRenderInfo(GUILD_RENDER_INFO* OUT pRenderInfo, GUILDGUID other_guildIndex) const
{
const BASE_PLAYERINFO* pInfo = &char_info_;
GameGuild* pGuild = g_GameGuildManager.FindGuild(pInfo->m_GuildGuid);
if( NULL == pGuild)
return FALSE;
#ifdef _NA_008679_20160202_REWORK_BATTLEGROUND
// 扎菲激战地不发送公会信息
if (IsThereBattleGroundZone() == true) {
return FALSE;
}
#endif //_NA_008679_20160202_REWORK_BATTLEGROUND
GameDominationManager* const domination_manager = GameDominationManager::Instance();
pRenderInfo->m_dwObjectKey = GetObjectKey();
pRenderInfo->m_GuildGrade = pGuild->GetGuildGrade();
//_NA_0_20100208_DOMINATION_AREA_INFO
pRenderInfo->m_GuildDuty = (BYTE)pInfo->m_eGuildDuty;
pRenderInfo->m_GuildGuid = pInfo->m_GuildGuid;
pRenderInfo->m_RelationType = GuildSmallContentEntry::RelationSystem::GetRelationType(
other_guildIndex, pInfo->m_GuildGuid);
#ifdef _NA_008334_20150608_SONNENSCHEIN
pRenderInfo->sonnenschein_phase = pGuild->GetSonnenScheinRewardPhase();
#endif //_NA_008334_20150608_SONNENSCHEIN
GuildSmallContentEntry::GuildMark::GetGuildMark(pInfo->m_GuildGuid,
pRenderInfo->m_BackGroundIndex, pRenderInfo->m_PatternIndex);
util::GUILDNAMECOPY(pRenderInfo->m_tszGuildName, pInfo->m_tszGuildName);
//_NA_0_20100208_DOMINATION_AREA_INFO
domination_manager->SerializeAreaInfo(pInfo->m_GuildGuid, pRenderInfo->m_stateTotalInfo);
return TRUE;
}
//}
void
Player::GetVendorRenderInfo(VENDOR_RENDER_INFO* OUT pRenderInfo)
{
pRenderInfo->m_byTitleLength = 0;
if(GetBehave() == PLAYER_BEHAVE_VENDOR_ESTABLISHER_STATE)
{
VendorSlotContainer* pVenderSlotContainer = GetVendorContainer();
if(pVenderSlotContainer == 0)
{
SUNLOG(eCRITICAL_LOG, "[Error]GetVendorContainer() == NULL");
}
else
{
strncpy(pRenderInfo->m_tszVendorTitle, pVenderSlotContainer->GetTitle(),
_countof(pRenderInfo->m_tszVendorTitle));
pRenderInfo->m_tszVendorTitle[_countof(pRenderInfo->m_tszVendorTitle) - 1] = '\0';
pRenderInfo->m_byTitleLength = strlen(pRenderInfo->m_tszVendorTitle);
}
}
}
//
//==================================================================================================
BOOL
Player::SerializeInfoToDBProxy(eGUILDWAREHOUSE_UPDATE_FACTOR updateFactor)
{
// 定期发送到DBproxy的信息:1.角色信息(m CharInfo2.道具3.技能
//需要优化的部分!
//考虑发送更改部分的方法!
// changes, f100818.2L, code arrangement
ePLAYER_STATE player_lifetime_state = ePLAYER_STATE(GetState());
if (player_lifetime_state < PLAYER_LOADING || player_lifetime_state == PLAYER_DESTROYED) {
return true;
}
//
m_DBPUpdateTimer.Reset();
//
// CHANGES: f101115.3L, 做一个独立的方法
//使用共享数据实现稳定的播放器关闭过程.
if (updateFactor == UPDATE_FACTOR_LOGOUT) {
CloseSharedTransactions();
// CHANGES: f110103.2L, IsTransaction的结果仅为真
//当场间移动失败时.
if (zone_transaction_info_.IsTransaction()) {
zone_transaction_info_.RollbackTransaction();
}
}
//
//////////////////////////////////////////////////////////////////////////
// Serialize Temporary Buffer
static BYTE busy_access_buffer_static[1024 * 64];
//////////////////////////////////////////////////////////////////////////
const BYTE channel_id = g_pGameServer->GetKey().GetChannelID();
const DWORD user_key = GetUserKey();
const DWORD char_guid = GetCharGuid();
//
MSG_DG_CHARINFO_UPDATE_TRANSACTION_CONTROL_SYN msg_transaction;
;{ // 为更新锁定启动事务
msg_transaction.m_byTransControl = msg_transaction.SERIALIZE_LOCKING;
msg_transaction.m_ChannelID = channel_id;
msg_transaction.char_guid_ = char_guid; // CHANGES: f110412.2L
if (SendToGameDBPServer(&msg_transaction, sizeof(msg_transaction)) == false)
{
SUNLOG(eCRITICAL_LOG,
_T("|[%s]|无法发送到数据库代理服务器,网络问题|"),
__FUNCTION__);
return false;
}
};
//
;{
MSG_DG_CHARINFO_CHAR_ITEM_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_CHARINFO_CHAR_ITEM_CMD;
msg_cmd->m_ChannelID = channel_id;
msg_cmd->m_CharacterInfo = char_info_;
m_pItemManager->SerializeItemTotalInfo(msg_cmd->m_ItemInfo, SERIALIZE_LOAD);
SendToGameDBPServer(msg_cmd, msg_cmd->GetSize());
};
#if defined(_NA002217_100728_EP2_SKILL_SYSTEM_DB_) && \
defined(_NA002217_100728_EP2_PERK_SYSTEM_)
;{
//MSG_DG_CHARINFO_SKILL_LIST_CMD msg_cmd;
};
;{
MSG_DG_CHARINFO_SKILL_PERK_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_CHARINFO_SKILL_PERK_CMD;
msg_cmd->char_guid_ = char_guid;
this->GetPerkManager()->LoadPerk(&msg_cmd->container_);
SendToGameDBPServer(msg_cmd, msg_cmd->GetSize());
};
#endif
// { reserve deletion
;{
MSG_DG_CHARINFO_SKILL_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_CHARINFO_SKILL_CMD;
msg_cmd->char_guid_ = char_guid;
msg_cmd->m_ChannelID = channel_id;
SerializeSkillTotalInfo(msg_cmd->m_SkillInfo, SERIALIZE_LOAD);
SendToGameDBPServer(msg_cmd, msg_cmd->GetSize());
};
;{
MSG_DG_CHARINFO_QUICK_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_CHARINFO_QUICK_CMD;
msg_cmd->char_guid_ = char_guid;
msg_cmd->m_ChannelID = channel_id;
m_pQuickManager->SerializeQuickTotalInfo(msg_cmd->m_QuickInfo, SERIALIZE_LOAD);
SendToGameDBPServer(msg_cmd, msg_cmd->GetSize());
};
#ifdef _NA_0_20110308_SKILL_COOL_TIME_STORAGE
;{
MSG_DG_CHARINFO_SKILL_COOL_TIME_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_CHARINFO_SKILL_COOL_TIME_CMD;
msg_cmd->char_guid_ = char_guid;
msg_cmd->m_ChannelID = channel_id;
SkillCoolTimeAccessor::Instance()->GetSkillCoolTime(this, &(msg_cmd->skill_cool_time));
SendToGameDBPServer(msg_cmd, msg_cmd->GetSize());
};
#endif
// } reserve deletion
;{
MSG_DG_CHARINFO_QUEST_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_CHARINFO_QUEST_CMD;
msg_cmd->char_guid_ = char_guid;
msg_cmd->m_ChannelID = channel_id;
//
BOOST_STATIC_ASSERT(sizeof(msg_cmd->m_pProgrQStream) == MAX_PROGR_QUESTSTREAM_SIZE);
BOOST_STATIC_ASSERT(sizeof(msg_cmd->m_pComplQStream) == MAX_COMPL_QUESTSTREAM_SIZE);
BOOST_STATIC_ASSERT(sizeof(msg_cmd->m_pMissionStream) == MAX_MISSIONSTREAM_SIZE);
//
m_pQuestManager->SerializeProgrStream(\
msg_cmd->m_pProgrQStream, sizeof(msg_cmd->m_pProgrQStream), QSERIALIZE_LOAD);
m_pQuestManager->SerializeComplStream(\
msg_cmd->m_pComplQStream, sizeof(msg_cmd->m_pComplQStream), QSERIALIZE_LOAD);
m_pMissionManager->SerializeStream(\
msg_cmd->m_pMissionStream, sizeof(msg_cmd->m_pMissionStream), SERIALIZE_LOAD);
//
SendToGameDBPServer(msg_cmd, sizeof(*msg_cmd));
};
//C_NA_0_20100520_ACSYSTEM_CHANGED
;{
MSG_DG_CHARINFO_CHAR_ACHIEVEMENT_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_CHARINFO_CHAR_ACHIEVEMENT_CMD;
msg_cmd->char_guid_ = char_guid;
msg_cmd->channel_id_ = channel_id;
m_pACManager->Serialize(msg_cmd->achievement_info_, ACSERIALIZE_DBPROXY_LOAD);
SendToGameDBPServer(msg_cmd, msg_cmd->GetSize());
};
;{
MSG_DG_CHARINFO_EXTRA_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_CHARINFO_EXTRA_CMD;
msg_cmd->char_guid_ = char_guid;
msg_cmd->m_ChannelID = channel_id;
msg_cmd->m_LoginTime_t = GetLoginTime_t();
SerialzieStatusGMInfo(msg_cmd->m_GMStateInfo, SERIALIZE_LOAD);
m_pStatusManager->SerialzieStatusDetailInfo(msg_cmd->m_TotalInfo, SERIALIZE_LOAD);
SendToGameDBPServer(msg_cmd, msg_cmd->GetSize());
};
//
;{
// 仓库开始时,用DB保存当前的信息.
CWarehouseSlotContainer* const warehouse = GetWarehouseContainer();
warehouse->SaveWarehouseToDBP();
};
#ifdef _NA_20100106_REPURCHAS_BUGFIX_2496
;{
MSG_DG_CHARINFO_CHAR_REPURCHASE_ITEM_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_CHARINFO_CHAR_REPURCHASE_ITEM_CMD;
msg_cmd->char_guid_ = char_guid;
msg_cmd->m_ChannelID = channel_id;
msg_cmd->m_RepurchasItem.m_Count = 0;
m_pItemManager->GetTradingImpl()->SerializeRepurchaseItems(
msg_cmd->m_RepurchasItem, SERIALIZE_LOAD);
SendToGameDBPServer(msg_cmd, msg_cmd->GetSize());
};
#endif //_NA_20100106_REPURCHAS_BUGFIX_2496
;{ // implemented by _KR_0_20091021_FIRENDINVITATION_EXTEND
MSG_DG_CHARINFO_INVITATEDFRIEND_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_CHARINFO_INVITATEDFRIEND_CMD;
msg_cmd->char_guid_ = char_guid;
msg_cmd->channel_id_ = channel_id;
GFriendInvitationController* invite_controller = GFriendInvitationController::Instance();
invite_controller->GetInvitatedFrindInfo(this, msg_cmd, SERIALIZE_LOAD);
SendToGameDBPServer(msg_cmd, msg_cmd->GetSize());
};
#ifdef __CN_OO0510__FATIGUE_MATCHING_UPDATE
;{
MSG_DG_OTHER_FATIGUE_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_OTHER_FATIGUE_CMD;
msg_cmd->m_wPlayTime = GetPlayTime();
msg_cmd->m_wOfflineTime = GetOfflineTime();
SendToGameDBPServer(msg_cmd, sizeof(*msg_cmd));
};
#endif //__CN_OO0510__FATIGUE_MATCHING_UPDATE
;{
MSG_DG_CHARACTER_EXTRA_INFO_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_CHARACTER_EXTRA_INFO_CMD;
#ifdef _NA_006372_20130108_BADGE_ITEM
ToggleItemInfos& toggle_item_info = GetExtraInfoManager().GetToggleItemInfos();
memcpy(&msg_cmd->toggle_item_info_, &toggle_item_info, sizeof(msg_cmd->toggle_item_info_));
#endif //_NA_006372_20130108_BADGE_ITEM
//_NA_005026_20120527_CHAOS_ZONE_BATTLE_GROUND
const BattleGroundRecordInfos& battle_ground_record_infos = \
GetExtraInfoManager().GetBattleGroundRecordInfos();
memcpy(&msg_cmd->battle_ground_record_infos_, &battle_ground_record_infos,
sizeof(msg_cmd->battle_ground_record_infos_));
#ifdef _NA_007065_20140217_CHAOSZONE_GOLDRUSH
const GoldRushRecordInfos& goldrush_record_infos = \
GetExtraInfoManager().GetGoldRushRecordInfos();
memcpy(&msg_cmd->goldrush_record_infos_, &goldrush_record_infos,
sizeof(msg_cmd->goldrush_record_infos_));
#endif //_NA_007065_20140217_CHAOSZONE_GOLDRUSH
#ifdef _NA_000000_20130521_DAILY_QUEST_RESET_ITEM
msg_cmd->daily_quest_reset_item_use_time = GetExtraInfoManager().GetDailyQuestResetUseTime();
#endif //_NA_000000_20130521_DAILY_QUEST_RESET_ITEM
#ifdef _NA_008404_20150712_MINIGAME_SYSTEM
msg_cmd->minigame_bingo_infos = GetExtraInfoManager().GetMiniGameBingoInfos();
#endif //_NA_008404_20150712_MINIGAME_SYSTEM
SendToGameDBPServer(msg_cmd, sizeof(*msg_cmd));
};
#ifdef _NA_007932_20150106_USER_EXTRA_INFO
;{
MSG_DG_USER_EXTRA_INFO_CMD* msg_cmd = \
new (busy_access_buffer_static) MSG_DG_USER_EXTRA_INFO_CMD;
// 添加UserExtraInfo时修改
#ifdef _NA_007932_20150112_ATTENDANCE_CHECK_SYSTEM
const AttendanceInfo& attendance_infos = \
GetExtraInfoManager().GetAttendanceInfos();
memcpy(&msg_cmd->attendance_infos, &attendance_infos,
sizeof(msg_cmd->attendance_infos));
#endif // _NA_007932_20150112_ATTENDANCE_CHECK_SYSTEM
SendToGameDBPServer(msg_cmd, sizeof(*msg_cmd));
};
#endif // _NA_007932_20150106_USER_EXTRA_INFO
//
//
BYTE end_trans_type_selector = msg_transaction.SERIALIZE_UNLOCKING;
if (CGuildWarehouseSlotContainer* guild_warehouse = GetGuildWarehouseContainer())
{
//1. 打开仓库时
//2.打开行会仓库时更新
//3.在打开帮派仓库的情况下退出(选择服务器/选择角色)
//4.服务器选择窗口IsLogOut==true时会传送DBP Disconnect包,直接从DBP更新,因此不需要挂上公会仓库的标签。
//5.角色选择窗口IsLogOut==true时MSG DG CHARINFO UPDATE SYN包会被传送到DBP中,因此不需要挂在公会仓库的标签上.
// TODO : the name of a UPDATE_RESULT enumeration is very generic
UPDATE_RESULT guild_update_result = guild_warehouse->SaveWarehouseToDBP(this, updateFactor);
if (guild_update_result == UPDATE_BY_CHNAGE_SUCCESS)
{
if (UPDATE_FACTOR_LOGOUT != updateFactor) {
end_trans_type_selector = msg_transaction.SERIALIZE_UNLOCKING_WITH_GUILDWAREHOUSE;
}
SUNLOG(eCRITICAL_LOG, "SerializeInfoToDBProxy With GuildWarehouse(%u)(%u)",
char_guid, GetGuildGuid());
}
};
//------------------------------------------------------------------------------------------
// WARNING!! MUST be set LAST position a below section about an unlocking transaction message
;{
// send to the end transaction message for an update unlocking
msg_transaction.m_byTransControl = end_trans_type_selector;
msg_transaction.m_ChannelID = channel_id;
SendToGameDBPServer(&msg_transaction, sizeof(msg_transaction));
};
//
return true;
}
void
Player::CopyToCharInfo(PLAYERINFO_FOR_PACKET& rCharInfoOut)
{
//Hero(自己)的情况下,数值会发送Base数值。
//根据Clara的技能、道具、风格等重新计算数值。
const BASE_PLAYERINFO* pInfo = &char_info_;
const Attributes& rAttr = GetAttr();
rCharInfoOut.m_i64Exp = pInfo->m_i64Exp;
rCharInfoOut.m_MaxHP = rAttr.GetBaseMaxHP();
rCharInfoOut.m_HP = pInfo->m_iHP;
rCharInfoOut.m_MaxMP = rAttr.GetBaseMaxMP();
rCharInfoOut.m_MP = pInfo->m_iMP;
rCharInfoOut.m_Money = pInfo->m_Money;
rCharInfoOut.m_dwRemainStat = pInfo->m_iRemainStat;
rCharInfoOut.m_dwRemainSkill = pInfo->m_iRemainSkill;
// CHANGES: f110704.3L, 同步默认样式。
//第二集技能系统不使用被动技能。
//注意:SynchronizeStyleBasedOn武器的副作用是
//要更改字符信息,请选择样式代码.
rCharInfoOut.m_SelectStyleCode = this->SynchronizeStyleBasedOnWeapon();
rCharInfoOut.m_byPKState = pInfo->m_byPKState;
rCharInfoOut.m_byCharState = pInfo->m_byCharState;
rCharInfoOut.m_StateTime = pInfo->m_StateTime;
// no null terminated?
strncpy(rCharInfoOut.m_tszTitleID, pInfo->m_tszTitleID, _countof(rCharInfoOut.m_tszTitleID));
//rCharInfoOut.m_tszTitleID[_countof(rCharInfoOut.m_tszTitleID) - 1] = '\0';
rCharInfoOut.m_TitleTime = pInfo->m_TitleTime;
ProtectorInventory& rProtector = GetWarehouseInventoryProtector().INVENTORY();
int iFlag = (rProtector.IsEmptyPassword() ? rCharInfoOut.EMPTY_PWD : rCharInfoOut.EXIST_PWD);
iFlag |= rProtector.IsUsable() ? rCharInfoOut.ENABLE : rCharInfoOut.DISABLED;
rCharInfoOut.m_iInventoryLock = (PLAYERINFO_FOR_PACKET::eINVEN_LOCK_MODE)iFlag;
rCharInfoOut.m_sStrength = rAttr.GetBaseSTR();
rCharInfoOut.m_sDexterity = rAttr.GetBaseDEX();
rCharInfoOut.m_sVitality = rAttr.GetBaseVIT();
rCharInfoOut.m_sInteligence = rAttr.GetBaseINT();
rCharInfoOut.m_sSpirit = rAttr.GetBaseSPR();
rCharInfoOut.m_sSkillStat1 = pInfo->m_sSkillStat1;
rCharInfoOut.m_sSkillStat2 = pInfo->m_sSkillStat2;
rCharInfoOut.m_UserPoint = pInfo->m_UserPoint;
rCharInfoOut.m_wMoveSpeedRatio = rAttr.GetMoveSpeedRatio();
rCharInfoOut.m_wAttSpeedRatio = rAttr.GetAttSpeedRatio();
//GM等级设置
switch(GetSts())
{
case eGM_GRADE_FIRST:
case eGM_GRADE_SECOND:
case eGM_GRADE_THIRD:
{
rCharInfoOut.m_byGMGrade = GetSts() - eGM_GRADE_BASE;
}break;
case eGM_GRADE_VIRTUAL:
{
rCharInfoOut.m_byGMGrade = 4;
}break;
default:
{
rCharInfoOut.m_byGMGrade = 0;
}
}
// 当前状态
rCharInfoOut.m_byCondition = GetStatusManager()->GetCondition();
// 网吧玩家
rCharInfoOut.m_byPCBangUser = GetReservedValue() > 0 ? 1 : 0;
//rCharInfoOut.m_byHeight = pInfo->m_byHeight;
//rCharInfoOut.m_byFace = pInfo->m_byFace;
//rCharInfoOut.m_byHair = pInfo->m_byHair;
rCharInfoOut.m_PlayLimitedTime = pInfo->m_PlayLimitedTime;
rCharInfoOut.m_byInvisibleOptFlag = pInfo->m_byInvisibleOptFlag;
rCharInfoOut.m_GuildGuid = pInfo->m_GuildGuid;
rCharInfoOut.m_GuildDuty = pInfo->m_eGuildDuty;
_tcsncpy(rCharInfoOut.m_tszGuildName, pInfo->m_tszGuildName, MAX_GUILDNAME_LENGTH);
rCharInfoOut.m_ChaoState = pInfo->m_ChaoState; // Chao
rCharInfoOut.m_byPCRoomSts = GetPCRoomSts();
rCharInfoOut.m_ExtraInventoryTabCount = pInfo->m_ExtraInventoryTabCount;
rCharInfoOut.m_ExtraEquipCashSlotCount = pInfo->m_ExtraEquipCashSlotCount;
rCharInfoOut.m_bTradeFlag = pInfo->m_bTradeFlag;
rCharInfoOut.m_bWhisperFlag = pInfo->m_bWhisperFlag;
rCharInfoOut.m_byFreeInitCount = pInfo->m_byFreeInitCount;
rCharInfoOut.m_bSummonedPet = pInfo->m_bSummonedPet;
rCharInfoOut.m_bMAXIntimacy = pInfo->m_bMAXIntimacy;
rCharInfoOut.m_PetItemPos = pInfo->m_PetItemPos;
rCharInfoOut.m_bMAXOptionRemainTime = pInfo->m_bMAXOptionRemainTime;
//rCharInfoOut.m_bActiveEtherDevice = m_EtherManager.IsActive();
//Clara为了发送不同的内容,在中间更改分组
if (m_EtherManager.IsActive())
{
tagEtherBulletInfo* pBulletInfo = m_EtherManager.GetBulletOption();
if (pBulletInfo) {
rCharInfoOut.m_bActiveEtherDevice = pBulletInfo->m_byEffectCode;
}
else {
rCharInfoOut.m_bActiveEtherDevice = 1;
}
}
else
{
rCharInfoOut.m_bActiveEtherDevice = 0;
}
if (rCharInfoOut.m_bActiveEtherDevice) {
rCharInfoOut.m_byEtherBulletPos = m_EtherManager.GetBulletItemPos();
}
rCharInfoOut.m_MaxSD = GetAttr().GetBaseMaxSD();
rCharInfoOut.m_SD = pInfo->m_iSD;
#ifdef _NA_003027_20111013_HONOR_SYSTEM
rCharInfoOut.m_wHonorTitle = pInfo->honor_title_;
#endif //_NA_003027_20111013_HONOR_SYSTEM
}
const BASE_ITEMINFO*
Player::GetEquipItemInfo(eEQUIPCONTAINER_POS pos) const
{
SASSERT(m_pItemManager != NULL, "[Player::GetEquipItemInfo] m_pItemManager == NULL");
SCSlotContainer* pContainer = m_pItemManager->GetItemSlotContainer(SI_EQUIPMENT);
SASSERT(pContainer != NULL, "[Player::GetEquipItemInfo] pContainer == NULL");
if(!pContainer->IsEmpty(pos))
{
SCItemSlot& rSlot = static_cast<SCItemSlot&>(pContainer->GetSlot(pos));
return rSlot.GetItemInfo();
}
return NULL;
}
SCItemSlot*
Player::GetEquipItemSlot(eEQUIPCONTAINER_POS pos)
{
SCSlotContainer* pContainer = m_pItemManager->GetItemSlotContainer(SI_EQUIPMENT);
if(pContainer == 0)
{
SUNLOG(eCRITICAL_LOG, "[Player::GetEquipItemInfo] pContainer == NULL");
return NULL;
}
if(!pContainer->IsEmpty(pos))
{
SCItemSlot& rSlot = static_cast<SCItemSlot&>(pContainer->GetSlot(pos));
return &rSlot;
}
return NULL;
}
#if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_)
eARMOR_TYPE
Player::GetArmorType() const
{
const BASE_ITEMINFO* pInfo = GetEquipItemInfo(eEQUIPCONTAINER_ARMOR);
if(pInfo != NULL)
{
return (eARMOR_TYPE)pInfo->m_byArmorType;
}
return eARMOR_UNARMOR;
}
eMELEE_TYPE
Player::GetMeleeType() const
{
const BASE_ITEMINFO* pInfo = GetEquipItemInfo(eEQUIPCONTAINER_WEAPON);
if(pInfo != NULL)
return (eMELEE_TYPE)pInfo->m_byMeleeType;
return eMELEE_TYPE_HIT;
}
#endif
float
Player::GetAttackRange() const
{
float fAttackRange = GetNormalRangeBonus();
//_NA_007079_BUG_WEAPON_INACTIVATE_STATE
CEquipmentSlotContainer* pEquipSlotContainer =
(CEquipmentSlotContainer*)m_pItemManager->GetItemSlotContainer(SI_EQUIPMENT);
SCItemSlot& rSlot = static_cast<SCItemSlot&>(pEquipSlotContainer->GetSlot(eEQUIPCONTAINER_WEAPON));
if(pEquipSlotContainer->IsEmpty(eEQUIPCONTAINER_WEAPON) ||
pEquipSlotContainer->IsActivated(eEQUIPCONTAINER_WEAPON) == false ||
rSlot.GetDura() == 0 )
{
// 맨주먹
fAttackRange += 2.5f;
}
else
{
const BASE_ITEMINFO* pInfo = GetEquipItemInfo(eEQUIPCONTAINER_WEAPON);
if(pInfo)
fAttackRange += pInfo->m_fAttRange;
}
return fAttackRange;
}
EXPTYPE
Player::AddExp(EXPTYPE exp, DWORD dwTargetObjKey, int iBonusRatio, BOOL bSendPacket, eGAME_CONTENT_TYPE ContentType)
{
LEVELTYPE cur_level = GetLevel();
if(cur_level >= Generic::GetMaxLevel(this))
{
exp = 0;
OnAddExp(dwTargetObjKey, iBonusRatio, bSendPacket);
}
if(exp == 0)
return exp;
EXPTYPE curExp = GetExp();
EXPTYPE newExp = curExp + exp;
#ifdef _NA_008333_20150615_FIXED_MAX_LEVEL_EXP
if (cur_level == Generic::GetMaxLevel(this) - 1
&& GetNextExp() && newExp >= GetNextExp())
{
newExp = GetNextExp();
}
#endif // _NA_008333_20150615_FIXED_MAX_LEVEL_EXP
// 保留经验日志(10等分或全部)
MAPCODE mapcode = 0;
if(GetGameZonePtr())
mapcode = GetGameZonePtr()->GetMapCode();
GAMELOG->LogExp(this, cur_level, curExp, newExp, mapcode);
SetExp(newExp);
OnAddExp( dwTargetObjKey, iBonusRatio, bSendPacket, ContentType );
//如果当前经验值高于下一级经验值…升级.
while(GetNextExp() && GetExp() >= GetNextExp())
{
if(!Generic::CheckMaxLevel(this, GetLevel()+1))
{
SUNLOG(eCRITICAL_LOG, "[Player::AddExp] LEVEL Error(%d) CharName(%20s) !!",
GetLevel(), GetCharName());
return exp;
}
// 升级日志
GAMELOG->WriteLevelUp(this, GetLevel(), GetLevel() + 1);
SUNLOG(eFULL_LOG, "[Player::AddExp] [升级] ID = %s, NAME = %s, Level = %d ",
m_pszUserID, char_info_.m_tszCharName, GetLevel()+1);
// 升级日志结束..
// level up! --> 根据当前经验值重新设置level和nextExp.
SetLevel(GetLevel() + 1);
OnLevelUp();
}
return exp;
}
DWORD
Player::GetWeaponKind() const
{
CEquipmentSlotContainer* pEquipSlotContainer =
(CEquipmentSlotContainer*)m_pItemManager->GetItemSlotContainer(SI_EQUIPMENT);
//_NA_007079_BUG_WEAPON_INACTIVATE_STATE
if(pEquipSlotContainer && !pEquipSlotContainer->IsEmpty(eEQUIPCONTAINER_WEAPON))
{
SCItemSlot& rSlot = static_cast<SCItemSlot&>(pEquipSlotContainer->GetSlot(eEQUIPCONTAINER_WEAPON));
//检查激活与否和内部结构
if (pEquipSlotContainer->IsActivated(eEQUIPCONTAINER_WEAPON) == true && rSlot.GetDura() != 0)
{
SCItemSlot& rSlot = static_cast<SCItemSlot&>(pEquipSlotContainer->GetSlot(eEQUIPCONTAINER_WEAPON));
return rSlot.GetItemInfo()->m_wType;
}
}
// 赤手空拳
return eWEAPONTYPE_PUNCH;
}
eATTACK_TYPE
Player::GetWeaponBaseAttType() const
{
eATTACK_TYPE eAttackType = eATTACK_TYPE_MELEE;
if(!m_pItemManager->GetItemSlotContainer(SI_EQUIPMENT)->IsEmpty(eEQUIPCONTAINER_WEAPON))
{
SCItemSlot& rSlot = static_cast<SCItemSlot&>(
m_pItemManager->GetItemSlotContainer(SI_EQUIPMENT)->GetSlot(eEQUIPCONTAINER_WEAPON));
eAttackType = (eATTACK_TYPE)rSlot.GetItemInfo()->m_byBaseAttType;
}
return eAttackType;
}
eATTACK_TYPE
Player::GetWeaponMagicalAttType() const
{
eATTACK_TYPE eAttackType = eATTACK_TYPE_INVALID;
if(!m_pItemManager->GetItemSlotContainer(SI_EQUIPMENT)->IsEmpty(eEQUIPCONTAINER_WEAPON))
{
SCItemSlot& rSlot = static_cast<SCItemSlot&>(
m_pItemManager->GetItemSlotContainer(SI_EQUIPMENT)->GetSlot(eEQUIPCONTAINER_WEAPON));
eAttackType = (eATTACK_TYPE)rSlot.GetItemInfo()->m_byMagicalAttType;
}
return eAttackType;
}
void
Player::UpdateCalcRecover(BOOL hp_updated, BOOL mp_updated, BOOL sd_updated)
{
const eCHAR_TYPE char_type = static_cast<eCHAR_TYPE>(char_info_.m_byClassCode);
eCHAR_CONDITION char_condition = GetStatusManager()->GetCondition();
//
int hp_recovery_quantity = 0;
int mp_recovery_quantity = 0;
int sd_recovery_quantity = 0;
//
if (hp_updated)
{
const int vitality = m_Attr.GetVIT();
hp_recovery_quantity = CalcHPRecover(char_type, vitality, char_condition, char_info_.m_LV);
};
if (mp_updated)
{
const int spirit = m_Attr.GetSPR();
mp_recovery_quantity = CalcMPRecover(char_type, spirit, char_condition);
};
if (sd_updated)
{
const uint8_t moving_flag = IsMoving() ? CHAR_ACTION_CONDITION_MOVING
: CHAR_ACTION_CONDITION_NONE;
// TODO: f110413.1L, changes the method to get fighting_flag.
const uint8_t fighting_flag = GetStatusManager()->FindStatus(eCHAR_STATE_ETC_FIGHTING)
? CHAR_ACTION_CONDITION_FIGHTING
: CHAR_ACTION_CONDITION_NONE;
sd_recovery_quantity = CalcSDRecover(
char_type, char_condition, (moving_flag | fighting_flag), char_info_.m_LV);
};
if (hp_updated || mp_updated || sd_updated)
{
// CHANGES: f110413.1L, change logic to reduce a busy big update process
// because HP, MP and SD recovery update routine is often invoked by a changed value.
m_Attr.UpdateChangedRecoveries(&char_info_,
(hp_updated != false), hp_recovery_quantity,
(mp_updated != false), mp_recovery_quantity,
(sd_updated != false), sd_recovery_quantity);
};
}
//-------------------------------------------------------------------------------------------------
// 参数变化
//-------------------------------------------------------------------------------------------------
// stat
BOOL
Player::CanSelectStat(eATTR_TYPE attrType) const
{
if(char_info_.m_iRemainStat == 0)
{
return FALSE;
}
switch (attrType)
{
case eATTR_STR:
case eATTR_DEX:
case eATTR_VIT:
case eATTR_INT:
case eATTR_SPR:
#if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_)
case eATTR_EXPERTY1:
case eATTR_EXPERTY2:
#endif
break;
default :
return FALSE;
}
return TRUE;
}
#ifdef _NA_0_20110216_STATUS_STAT_POINT_SIMULATION
RC::eSTAT_POINT_RESULT Player::ApplyStat(ushort* INOUT stat_point_array, uint array_count)
{
if (eATTR_BASE_STAT_COUNT != array_count)
return RC::RC_STAT_POINT_FAILED;
if(GetCharType() == eCHAR_DRAGON)
{
StatusManager* const pStatusManager = GetStatusManager();
if( pStatusManager->Status.IsDragonTransforming() )
{
return RC::RC_STAT_POINT_DRAGON_CHANGED;
}
}
ushort stat_point = 0;
uint idx = 0;
int original_stat_point[eATTR_BASE_STAT_COUNT] = {0,};
int desired_stat_point[eATTR_BASE_STAT_COUNT] = {0,};
for (idx = eATTR_BASE_STAT_START_INDEX ; idx < eATTR_BASE_STAT_COUNT ; ++idx)
{
eATTR_TYPE attribute_type = (eATTR_TYPE)idx;
switch (attribute_type)
{
case eATTR_STR:
case eATTR_DEX:
case eATTR_VIT:
case eATTR_INT:
case eATTR_SPR:
break;
default :
ASSERT(! "[Player::SelectStat] Invalid attrType");
return RC::RC_STAT_POINT_FAILED;
}
stat_point = stat_point_array[attribute_type];
if (char_info_.m_iRemainStat < stat_point)
return RC::RC_STAT_POINT_IS_NOT_ENOUGH;
const AttrValue& attr_value = m_Attr[attribute_type];
original_stat_point[attribute_type] = attr_value[eATTR_KIND_BASE];
desired_stat_point[attribute_type] = original_stat_point[attribute_type] + stat_point;
char_info_.m_iRemainStat -= stat_point;
m_Attr[attribute_type][eATTR_KIND_BASE] += stat_point;
}
#ifdef _NA_002289_20110322_EQUIPMENTS_CALCULATOR_CHANGES_FOR_IMPROVEMENT
if (ItemManager* item_manager = GetItemManager()) {
item_manager->UpdateItemAttributes(true, false);
};
#else
m_Attr.UpdateEx();
GetItemManager()->UpdateAttrForEquipItem();
#endif
for (idx = eATTR_BASE_STAT_START_INDEX ; idx < eATTR_BASE_STAT_COUNT ; ++idx)
{
eATTR_TYPE attribute_type = (eATTR_TYPE)idx;
const AttrValue& attr_value = m_Attr[attribute_type];
int result_value = attr_value[eATTR_KIND_BASE];
if (desired_stat_point[attribute_type] != result_value)
{
if (desired_stat_point[attribute_type] > result_value)
char_info_.m_iRemainStat += (desired_stat_point[attribute_type] - result_value);
else
char_info_.m_iRemainStat -= (result_value - desired_stat_point[attribute_type]);
}
stat_point_array[attribute_type] = (ushort)result_value;
}
char_info_.m_iRemainStat = BOUND_CHECK(0, char_info_.m_iRemainStat, SHRT_MAX);
((PlayerAttributes&)GetAttr()).Display();
return RC::RC_STAT_POINT_SUCCESS;
}
#endif
DWORD
Player::SelectStat(eATTR_TYPE attrType, int iIncValue)
{
SASSERT(char_info_.m_dwRemainStat > 0, "[Player::SelectStat] m_dwRemainStat <= 0");
if(attrType != eATTR_STR && attrType != eATTR_DEX &&
attrType != eATTR_VIT && attrType != eATTR_INT &&
attrType != eATTR_SPR
#if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_)
&& attrType != eATTR_EXPERTY1 && attrType !=eATTR_EXPERTY2
#endif
)
{
ASSERT(! "[Player::SelectStat] Invalid attrType");
}
if (char_info_.m_iRemainStat < iIncValue) {
iIncValue = char_info_.m_iRemainStat;
}
// (f100722.2L) fit in a boundary about stat point value calculator
// (NOTE) calculate a lowest boundary
#ifdef _NA001605_EP2_ATTRIBUTES_RENEWAL_
const int stat_lowest_limit = 1;
#else
const int stat_lowest_limit = \
(attrType != eATTR_EXPERTY1 && attrType != eATTR_EXPERTY2) ? 1 : 0;
#endif
// CHANGES: f110415.2L, fixed negative value calculating error when GM command used
const AttrValue& attr_value = m_Attr[attrType];
const int original_stat = attr_value[eATTR_KIND_BASE];
int desired_stat = original_stat + iIncValue;
if (desired_stat < stat_lowest_limit) {
iIncValue = (stat_lowest_limit - original_stat);
}
desired_stat = original_stat + iIncValue;
if (iIncValue == 0) {
return original_stat;
}
char_info_.m_iRemainStat -= iIncValue;
m_Attr[attrType][eATTR_KIND_BASE] += iIncValue;
#ifdef _NA_002289_20110322_EQUIPMENTS_CALCULATOR_CHANGES_FOR_IMPROVEMENT
if (ItemManager* item_manager = GetItemManager()) {
item_manager->UpdateItemAttributes(true, false);
};
#else
m_Attr.UpdateEx();
GetItemManager()->UpdateAttrForEquipItem();
#endif
int result_value = attr_value[eATTR_KIND_BASE];
if (desired_stat != result_value)
{
assert(desired_stat > result_value);
char_info_.m_iRemainStat += (desired_stat - result_value);
}
char_info_.m_iRemainStat = BOUND_CHECK(0, char_info_.m_iRemainStat, SHRT_MAX);
((PlayerAttributes&)GetAttr()).Display();
return result_value;
}
void
Player::LevelUp(DWORD dwPlusLevel)
{
if(!Generic::CheckMaxLevel(this, dwPlusLevel) ||
!Generic::CheckMaxLevel(this, GetLevel() + dwPlusLevel))
{
return;
}
for(DWORD i = 0 ; i < dwPlusLevel ; ++i)
{
SetLevel(GetLevel() + 1);
SetExp(GetAccumExp(GetLevel()));
OnLevelUp();
}
}
//GM指令处理(降级)
//等级下降不影响等级下降的经验值、HP等属性,
//单纯的等级下降。
void
Player::LevelDown(int nDownLevel)
{
if(nDownLevel >= 0)
return;
for(int i = 0 ; i > nDownLevel ; --i)
{
SetLevel(GetLevel() - 1);
//GM命令设置等级经验值.
SetExp(GetAccumExp(GetLevel()));
OnAddExp(GetObjectKey(), 0, TRUE);
OnLevelDown();
}
}
void
Player::StatPointUp(int iBonusStat)
{
// (f100722.2L) fit in a boundary about the remains stat point value
int remains = char_info_.m_iRemainStat + iBonusStat;
; remains = BOUND_CHECK(0, remains, SHRT_MAX);
char_info_.m_iRemainStat = remains;
MSG_CG_GM_STAT_UP_ACK sendMsg;
sendMsg.m_byCategory = CG_GM;
sendMsg.m_byProtocol = CG_GM_STAT_UP_ACK;
sendMsg.m_dwRemainStat = static_cast<uint16_t>(remains); // 剩余属性点
SendPacket(&sendMsg, sizeof(sendMsg));
}
//获得现在剩下的四重奏亮点.
int
Player::GetStatPoint()
{
return char_info_.m_iRemainStat;
}
void
Player::SkillPointUp(int iBonusSkill)
{
char_info_.m_iRemainSkill += iBonusSkill;
if(char_info_.m_iRemainSkill < 0)
char_info_.m_iRemainSkill = 0;
MSG_CG_GM_SKILLPOINT_UP_ACK sendMsg;
sendMsg.m_byCategory = CG_GM;
sendMsg.m_byProtocol = CG_GM_SKILLPOINT_UP_ACK;
sendMsg.m_dwRemainSkill = (WORD)char_info_.m_iRemainSkill;
SendPacket(&sendMsg, sizeof(sendMsg));
}
//获得当前剩余技能点数。
int
Player::GetRemainSkillPoint()
{
return char_info_.m_iRemainSkill;
}
void
Player::SetNextExp()
{
m_NextExp = GetAccumExp(GetLevel() + 1);
}
EXPTYPE
Player::GetAccumExp(LEVELTYPE level)
{
BASE_ACCUM_EXP_INFO* pAccumExpInfo = ExpValueInfoParser::Instance()->GetAccumExpInfo(level);
if(pAccumExpInfo == 0)
{
//WAVERIX)(081028)(BUG-FIX)-在进行宏清除工作时,可能会成为逻辑变更的事例之一…-;
//-changessource version333->334以上阶段发生问题
if(level <= Generic::GetMaxLevel(this))
SUNLOG(eCRITICAL_LOG, "Level[%d]pAccumExpInfo is NULL!!", level);
return 0;
}
return pAccumExpInfo->m_AccumExp;
}
void
Player::FixLevel()
{
LEVELTYPE level = GetLevel();
if(!Generic::CheckMaxLevel(this, level))
{
SUNLOG(eCRITICAL_LOG, "[Player::FixLevel] [Player_Parameter] LEVEL Error(%d) CharName(%20s) !!", GetLevel(), GetCharName());
return;
}
if(Generic::GetMaxLevel(this) == level)
{
return;
}
EXPTYPE curMinExp = GetAccumExp(level);
EXPTYPE nextExp = GetAccumExp(level + 1);
if(GetExp() >= curMinExp && GetExp() < nextExp)
{
// 正常水平
return;
}
// 当前经验值高于下一级经验值时
while(GetNextExp() && GetExp() >= GetNextExp())
{
if(!Generic::CheckMaxLevel(this, GetLevel()+1))
{
SUNLOG(eCRITICAL_LOG, "[Player::FixLevel] [Player_Parameter] LEVEL Error(%d) CharName(%20s) !!", GetLevel(), GetCharName());
return;
}
GAMELOG->WriteLevelUp(this, GetLevel(), GetLevel() + 1);
SetLevel(GetLevel() + 1);
OnLevelUp();
}
}
// implemented by __KR_001355_20090805_CHECK_GROUPSYSTEM_MSG
// level up和各种状态值的变化.
// 要发送攻击包!!
void
Player::OnAddExp(DWORD dwTargetObjKey, int iBonusRatio, BOOL bSendPacket, eGAME_CONTENT_TYPE eContentType)
{
if (!bSendPacket)
return;
switch (eContentType)
{
case GAME_CONTENT_NORMAL:
{
MSG_CG_STATUS_EXP_CMD sendMsg;
sendMsg.m_dwTargetObjKey = dwTargetObjKey;
sendMsg.m_i64Exp = GetExp();
sendMsg.m_BonusRatio = iBonusRatio;
SendPacket(&sendMsg, sizeof(sendMsg));
}
break;
case GAME_CONTENT_GROUPING:
{
MSG_CG_STATUS_GROUPEXP_CMD sendMsg;
sendMsg.m_dwTargetObjKey = dwTargetObjKey;
sendMsg.m_i64Exp = GetExp();
SendPacket(&sendMsg, sizeof(sendMsg));
}
break;
}
}
void
Player::OnLevelUp()
{
BASE_PLAYERINFO* pPlayerInfo = &char_info_;
// Stat bonus
DWORD bonusStat = GetStatPointPerLevel();
pPlayerInfo->m_iRemainStat += bonusStat;
// Skill Bonus!
DWORD bonusSkill = GetSkillPoint(GetLevel());
pPlayerInfo->m_iRemainSkill += bonusSkill;
// 设置下一级升级经验
SetNextExp();
SetHP(GetMaxHP());
if(GetCharType() != eCHAR_BERSERKER)
SetMP(GetMaxMP());
SetSD(GetMaxSD());
MSG_AG_STATUS_LEVEL_UP_CMD cmsg;
cmsg.m_Level = GetLevel();
cmsg.m_wRemainStat = (WORD)pPlayerInfo->m_iRemainStat;
cmsg.m_wRemainSkill = (WORD)pPlayerInfo->m_iRemainSkill;
cmsg.m_dwCurHP = GetHP();
cmsg.m_dwMaxMP = GetMaxMP();
cmsg.m_dwCurMP = GetMP();
cmsg.m_dwMaxAndCurSD = GetSD();
SendPacket(&cmsg, sizeof(cmsg));
MSG_CG_STATUS_LEVEL_UP_BRD sendMsg;
sendMsg.m_dwObjectKey = GetObjectKey();
sendMsg.m_Level = GetLevel();
sendMsg.m_wRemainStat = (WORD)pPlayerInfo->m_iRemainStat;
sendMsg.m_wRemainSkill = (WORD)pPlayerInfo->m_iRemainSkill;
sendMsg.m_dwCurHP = GetHP();
sendMsg.m_dwCurMP = GetMP();
SendPacketAround(&sendMsg, sizeof(sendMsg), FALSE);
if(pPlayerInfo->m_GuildGuid != 0)
{
MSG_GZ_GUILD_CHAR_LEVELUP_SYN synMsg;
synMsg.m_GuildGuid = pPlayerInfo->m_GuildGuid;
synMsg.m_CharGuid = GetCharGuid();
synMsg.m_Level = GetLevel();
SendToGuildServer(&synMsg, sizeof(synMsg));
}
FindAutoAcceptQuest opr(this);
g_QuestInfoManager.for_each_auto(opr);
NewGamePartyManager::Instance()->MemberLevelUp(GetPartyState().GetPartyKey(), GetObjectKey());
if(ePRS_AT_CHUNTING == GetGameZoneState())
{
GameCHuntingRoom* pCHuntingRoom = (GameCHuntingRoom *)GetGameZonePtr();
if(pCHuntingRoom)
pCHuntingRoom->GetCHuntingManager()->LevelUp(this);
}
//_NA_001990_ACSYSTEM_ADD
AchievementManager* pACManager = GetACManager();
if( pACManager )
pACManager->ProcessLevelUp(GetLevel());
}
void
Player::OnLevelDown()
{
SetNextExp();
SetHP(GetMaxHP());
if(GetCharType() != eCHAR_BERSERKER)
SetMP(GetMaxMP());
SetSD(GetMaxSD());
const BASE_PLAYERINFO* pPlayerInfo = &char_info_;
MSG_AG_STATUS_LEVEL_UP_CMD cmsg;
cmsg.m_Level = GetLevel();
cmsg.m_wRemainStat = (WORD)pPlayerInfo->m_iRemainStat;
cmsg.m_wRemainSkill = (WORD)pPlayerInfo->m_iRemainSkill;
cmsg.m_dwCurHP = GetHP();
cmsg.m_dwMaxMP = GetMaxMP();
cmsg.m_dwCurMP = GetMP();
cmsg.m_dwMaxAndCurSD = GetSD();
SendPacket(&cmsg, sizeof(cmsg));
MSG_CG_STATUS_LEVEL_UP_BRD sendMsg;
sendMsg.m_dwObjectKey = GetObjectKey();
sendMsg.m_Level = GetLevel();
sendMsg.m_wRemainStat = (WORD)pPlayerInfo->m_iRemainStat;
sendMsg.m_wRemainSkill = (WORD)pPlayerInfo->m_iRemainSkill;
sendMsg.m_dwCurHP = GetHP();
sendMsg.m_dwCurMP = GetMP();
SendPacketAround(&sendMsg, sizeof(sendMsg), FALSE);
}
DWORD
Player::IncreaseMP(DWORD dwIncreament)
{
dwIncreament = Character::IncreaseMP(dwIncreament);
m_pSkillSlotManager->UpdatePassiveSkills();
return dwIncreament;
}
DWORD
Player::DecreaseMP(DWORD dwDecrement)
{
dwDecrement = Character::DecreaseMP(dwDecrement);
m_pSkillSlotManager->UpdatePassiveSkills();
return dwDecrement;
}
DWORD
Player::IncreaseHP(DWORD dwIncreament)
{
dwIncreament = Character::IncreaseHP(dwIncreament);
if(dwIncreament)
{
m_pSkillSlotManager->UpdatePassiveSkills();
}
return dwIncreament;
}
DWORD
Player::DecreaseHP(DWORD dwDecrement, int fLimitHP)
{
if(GetHP() <= dwDecrement && GetGMStateInfo().m_UndeadOn)
return 0;
dwDecrement = Character::DecreaseHP(dwDecrement, fLimitHP);
m_pSkillSlotManager->UpdatePassiveSkills();
return dwDecrement;
}
#ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
PLAYERFP Player::IncreaseFP( PLAYERFP valueFP )
{
const PLAYERFP curFP = GetFP();
const PLAYERFP calcedFP = curFP + valueFP;
const PLAYERFP maxFP = GetMaxFP();
PLAYERFP fp = min(maxFP, calcedFP);
valueFP = fp - curFP;
SetFP(fp);
return valueFP;
}
PLAYERFP Player::DecreaseFP( PLAYERFP valueFP )
{
PLAYERFP curFP = GetFP();
if (curFP <= valueFP)
{
valueFP = curFP;
SetFP(0);
}
else
{
PLAYERFP fp = curFP - valueFP;
SetFP(fp);
}
return valueFP;
}
#endif //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
void
Player::SaveStartLocation()
{
GameZone* pZone = GetGameZonePtr();
if(pZone == 0)
return;
const WzVector* pCurPos = GetPosPtr();
eZONETYPE zoneType = pZone->GetZoneType();
if (zoneType == eZONETYPE_VILLAGE ||
zoneType == eZONETYPE_DOMINATION_FIELD ||
zoneType == eZONETYPE_FIELD ||
zoneType == eZONETYPE_SPA_FIELD) //_NA_008069_20150210_ADD_SPA_SYSTEM
{
char_info_.m_iRegion = pZone->GetMapCode();
char_info_.m_sLocationX = (SHORT)pCurPos->x;
char_info_.m_sLocationY = (SHORT)pCurPos->y;
char_info_.m_sLocationZ = (SHORT)pCurPos->z;
}
else
{
char_info_.m_sLocationX = 0;
char_info_.m_sLocationY = 0;
char_info_.m_sLocationZ = 0;
Field* pField = GetField();
if(pField == 0)
return;
MSG_AG_CHARINFO_FIELD_POS_FOR_RETURN_PARTY_CMD Cmd;
Cmd.m_ReturnPos = *pCurPos;
Cmd.m_ReturnFieldCode = pField->GetFieldCode();
Cmd.m_ReturnZoneType = pZone->GetZoneType();
Cmd.m_ReturnZoneKey = pZone->GetKey();
Cmd.m_PartyKey = GetPartyState().GetPartyKey();
Cmd.m_CharGUID = GetCharGuid();
SendPacket(&Cmd, sizeof(Cmd));
}
}
BOOL
Player::CanPlusMoney(MONEY plus_money)
{
return TRUE;
}
BOOL
Player::CanMinusMoney(MONEY minus_money)
{
if(GetMoney() < minus_money)
return FALSE;
return TRUE;
}
BOOL
Player::PlusMoney(MONEY plus_money, int type)
{
if(!CanPlusMoney(plus_money))
{
SUNLOG(eCRITICAL_LOG, "[%u:%u=%I64u,%I64u]游戏币增加错误", GetUserGuid(), GetCharGuid(), GetMoney(), plus_money);
return FALSE;
}
SetMoney(GetMoney() + plus_money);
switch(type)
{
case eMONEY_GENERNAL:
g_StatisticsManager.PlusStatisticType(eSTATISTIC_MONEY_PLUS, plus_money);
break;
case eMONEY_CIRCULATING:
g_StatisticsManager.PlusStatisticType(eSTATISTIC_MONEY_CIRCULATION, plus_money);
break;
//__KR_001355_20090624_GROUPINGSYSTEM_ALL
case eMONEY_GROUP:
NotifyGroupMoneyToPlayer(plus_money);
break;
}
return TRUE;
}
BOOL
Player::MinusMoney(MONEY minus_money, int type)
{
if(!CanMinusMoney(minus_money))
{
SUNLOG(eCRITICAL_LOG, "[%u:%u=%I64u,%I64u]游戏币差减错误", GetUserGuid(), GetCharGuid(), GetMoney(), minus_money);
return FALSE;
}
SetMoney(GetMoney() - minus_money);
switch(type)
{
case eMONEY_GENERNAL:
g_StatisticsManager.PlusStatisticType(eSTATISTIC_MONEY_MINUS, minus_money);
break;
}
return TRUE;
}
#if defined(__NA001336_090514_PARTY_NAVI_SUPPORT__) && !defined(__NA_0_20081124_PARTY_REFACTORING_GAMESERVER)
#error "Impossible Build!! - Reason: Violation Dependency Chain"
#endif
//{__NA001336_090514_PARTY_NAVI_SUPPORT__
//_NA_0_20091118_GAMEROOM_BATTLE_RESULT
VOID Player::OnRecover( INT recoverHP, INT recoverMP, INT recoverSD, eRECOVER_TYPE recoverType, Character* pAttacker )
{
DWORD curHP = GetHP();
DWORD curMP = GetMP();
DWORD curSD = GetSD();
if(recoverHP > 0)
{
DWORD maxHP = GetMaxHP();
DWORD reservedHP = GetReserveHP();
if(recoverType == eRECOVER_TYPE_AUTO_HP ||
recoverType == eRECOVER_TYPE_AUTO_HPMP)
{ // assert(recoverHP > 0)
if(GetStatusManager()->GetCondition() == eCHAR_CONDITION_STANDUP)
if(reservedHP < DWORD(recoverHP))
recoverHP = reservedHP;
if(reservedHP > DWORD(recoverHP)) // (WAVERIX) (090823) (CHANGES) from '>=' to '>'
SetReserveHP(reservedHP - recoverHP);
else
SetReserveHP(0);
}
else if(recoverType == eRECOVER_TYPE_NORMAL)
{
if((curHP + recoverHP) > maxHP)
{
recoverHP = maxHP - curHP;
SetReserveHP(0);
}
else if((curHP + recoverHP + reservedHP) > maxHP)
SetReserveHP(maxHP - curHP - recoverHP);
}
}
// _NA_0_20091118_GAMEROOM_BATTLE_RESULT
Character::OnRecover( recoverHP, recoverMP, recoverSD, recoverType, pAttacker );
//BOOLEAN isPartyMember = !!GetPartyState().IsPartyMember();
DWORD changedHP = GetHP();
if(curHP != changedHP)
{
NotifyChangedStatus(PlayerStatEvent::eFlag_ChangedHP);
}
DWORD changedMP = GetMP();
if(curMP != changedMP)
{
NotifyChangedStatus(PlayerStatEvent::eFlag_ChangedMP);
}
DWORD changedSD = GetSD();
if(curSD != changedSD)
{
NotifyChangedStatus(PlayerStatEvent::eFlag_ChangedSD);
}
}
//}__NA001336_090514_PARTY_NAVI_SUPPORT__
#ifdef _NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
VOID Player::OnRecoverFP( PLAYERFP recoverFP )
{
PLAYERFP curFP = GetFP();
if (recoverFP > 0)
{
StatusManager* status_manager = GetStatusManager();
BaseStatus* rising_force = status_manager->FindStatus(eCHAR_STATE_RISING_FORCE);
if (rising_force != NULL) {
return;
}
IncreaseFP(recoverFP);
SERVER_COMMON_OPTION& stServerOptionInfo = ServerOptionParserEx::Instance()->GetServerOption();
BaseStatus* fp_status = GetStatusManager()->FindStatus(eCHAR_STATE_ETC_AUTO_RECOVER_FP);
if (fp_status != NULL) {
fp_status->Init(this, eCHAR_STATE_ETC_AUTO_RECOVER_FP, BASE_EXPIRE_TIME_INFINITY,
stServerOptionInfo.player_fp_regen_period);
}
}
else if(recoverFP < 0)
{
DecreaseFP(-recoverFP);
}
PLAYERFP changed_FP = GetFP();
if (curFP != changed_FP)
{
NotifyChangedStatus(PlayerStatEvent::eFlag_ChangedFP);
if (curFP == GetMaxFP() || changed_FP == GetMaxFP())
{
MSG_CG_STATUS_CHANGE_FP_EFFECT_BRD msg_brd;
msg_brd.object_key = GetObjectKey();
msg_brd.current_fp = changed_FP;
SendPacketAround(&msg_brd, sizeof(msg_brd), FALSE);
}
}
}
#endif //_NA_007514_20140828_NEW_CHARACTER_WITCHBLADE
void
Player::SetAttr(eATTR_TYPE eAttrType, eATTR_KIND eAttrKind, int iValue)
{
BOOLEAN isValid = eATTR_TYPE_INVALID < eAttrType &&
eAttrType < eATTR_MAX;
if(isValid == 0)
{
DISPMSG("[Player::SetAttr] eAttrType[%d] is Invalid", eAttrType);
return;
}
m_Attr[eAttrType][eAttrKind] = iValue;
m_Attr.UpdateEx();
}
int
Player::GetResistBadStatusRatio(WORD wStateID)
{
int resist = m_Attr.GetResistBadStatusRatio();
#ifdef _NA_007123_20140324_SHADOW_SKILL_RENEWAL
switch(wStateID)
{
case eCHAR_STATE_HOLDING: resist += (int)(m_Attr.GetResistHolding()); break;
case eCHAR_STATE_DOWN: resist += (int)(m_Attr.GetResistDown()); break;
case eCHAR_STATE_STUN: resist += (int)(m_Attr.GetResistStun()); break;
case eCHAR_STATE_SLEEP: resist += (int)(m_Attr.GetResistSleep()); break;
case eCHAR_STATE_THRUST:
case eCHAR_STATE_THRUST3:
case eCHAR_STATE_THRUST4:
case eCHAR_STATE_THRUST5:
case eCHAR_STATE_THRUST2:
case eCHAR_STATE_STYLE_THRUST:
resist += (int)(m_Attr.GetResistKnockBack());
break;
case eCHAR_STATE_POISON:
case eCHAR_STATE_POISON2:
case kCharStatePoison3:
case eCHAR_STATE_WOUND:
case eCHAR_STATE_FIRE_WOUND:
case eCHAR_STATE_FIRE_WOUND2:
case eCHAR_STATE_PAIN:
case eCHAR_STATE_PAIN2:
case eCHAR_STATE_PHOENIX_BURN:
case eCHAR_STATE_ELECTRICSHOCK:
case eCHAR_STATE_HP_SUCTION:
case eCHAR_STATE_MP_SUCTION:
resist = 0;
break;
}
#else
switch(wStateID)
{
case eCHAR_STATE_HOLDING: resist += (int)(m_Attr.GetResistHolding()); break;
case eCHAR_STATE_DOWN: resist += (int)(m_Attr.GetResistDown()); break;
case eCHAR_STATE_STUN: resist += (int)(m_Attr.GetResistStun()); break;
case eCHAR_STATE_SLEEP: resist += (int)(m_Attr.GetResistSleep()); break;
case eCHAR_STATE_POISON:
case eCHAR_STATE_POISON2:
resist += (int)(m_Attr.GetResistPoison());
break;
case eCHAR_STATE_THRUST:
case eCHAR_STATE_THRUST3:
case eCHAR_STATE_THRUST4:
case eCHAR_STATE_THRUST5:
case eCHAR_STATE_THRUST2:
case eCHAR_STATE_STYLE_THRUST:
resist += (int)(m_Attr.GetResistKnockBack());
break;
}
#endif //_NA_007123_20140324_SHADOW_SKILL_RENEWAL
return resist;
}
//}_NA_001231_20081216_ADD_OPTION_KIND
void
Player::SetBaseSelectedStyle(WORD wStyleCode)
{
if(wStyleCode == eSTYLE_DRAGON_TRANSFORM1 ||
wStyleCode == eSTYLE_DRAGON_TRANSFORM2)
return;
char_info_.m_iSelectStyleCode = wStyleCode;
SetLastAttackSeq(eATTACK_SEQUENCE_NONE);
}
SLOTCODE
Player::GetSelectedStyle()
{
StatusManager* const pStatusManager = GetStatusManager();
if(pStatusManager->Status.IsDragonTransforming())
{
DragonTransStatus* const pDragonTransStatus =
(DragonTransStatus*)GetStatusManager()->FindStatus(eCHAR_STATE_TRANSFORMATION);
// CHANGES: f110428.6L, prevent a skipping previous style buff release process
// because at this point, player is already transform.
if (pDragonTransStatus->CheckStarting() == false)
{
const eCHAR_TYPE char_type = pDragonTransStatus->GetCharType();
if (char_type == eTRANSFORM_TYPE_DRAGON1) {
return eSTYLE_DRAGON_TRANSFORM1;
}
else if (char_type == eTRANSFORM_TYPE_DRAGON2) {
return eSTYLE_DRAGON_TRANSFORM2;
};
};
};
return (SLOTCODE)char_info_.m_iSelectStyleCode;
}
// CHANGES: f110704.3L, synchronize the default style.
// The Episode II skill system does not use the passive skill and the style skill.
// this method is called once in Player::CopoToCharInfo() per the user
// since continous agent connected.
// returns: synchronized style code
SLOTCODE Player::SynchronizeStyleBasedOnWeapon()
{
CEquipmentSlotContainer* const equip_container = static_cast<CEquipmentSlotContainer*>(
this->GetItemManager()->GetItemSlotContainer(SI_EQUIPMENT));
const SCItemSlot& item_slot = static_cast<SCItemSlot&>(\
equip_container->GetSlot(eEQUIPCONTAINER_WEAPON));
SLOTCODE item_code = item_slot.GetItemCode();
// if the item_code is 0, this result will get the punch style.
//_NA_007079_BUG_WEAPON_INACTIVATE_STATE
// if the weapon is inactivated, select punch style.
if (equip_container->IsActivated(eEQUIPCONTAINER_WEAPON) == false ||
item_slot.GetDura() == 0)
{
GetSkillSlotManager()->DelWeapon();
}
else {
char_info_.m_iSelectStyleCode = this->GetDefaultStyle(item_code);
}
// don't use "this->GetSkillSlotManager()->AddWeapon();"
return static_cast<SLOTCODE>(char_info_.m_iSelectStyleCode);
}
void
Player::SerialzieStatusGMInfo(STATE_GM_INFO& INOUT rStateGMInfo, eSERIALIZE se)
{
if(se == SERIALIZE_LOAD)
{
rStateGMInfo = m_GMStateInfo;
}
else if(se == SERIALIZE_STORE)
{
m_GMStateInfo = rStateGMInfo;
}
}
void
Player::ApplyGMState()
{
if(GetGMStateInfo().m_MoveSpeedLevel)
GMCmdManager::Instance()->ApplySpeed(this, GetGMStateInfo().m_MoveSpeedLevel);
if(GetGMStateInfo().m_TransOn)
GMCmdManager::Instance()->ApplyTransparent(this, TRUE);
}
// NOTE, r100828.3L, a heavy routine after a sd calculation based on a profiling test result.
// currently, 100828, a SD update policy is the points to be considered
// that need check a moving and a fighting status... terrible
// DONE: f110413.1L, waverix, need to desirable upgrade the SD(ShielD point) design.
void Player::UpdateCharStat()
{
const eCHAR_TYPE char_type = static_cast<eCHAR_TYPE>(char_info_.m_byClassCode);
eCHAR_CONDITION char_condition = GetStatusManager()->GetCondition();
const int hp_recovery_quantity = CalcHPRecover(\
char_type, char_info_.m_sVitality, char_condition, char_info_.m_LV);
const int mp_recovery_quantity = CalcMPRecover(\
char_type, char_info_.m_sSpirit, char_condition);
const uint8_t moving_flag = IsMoving() ? CHAR_ACTION_CONDITION_MOVING
: CHAR_ACTION_CONDITION_NONE;
// TODO: f110413.1L, changes the method to get fighting_flag.
const uint8_t fighting_flag = GetStatusManager()->FindStatus(eCHAR_STATE_ETC_FIGHTING)
? CHAR_ACTION_CONDITION_FIGHTING
: CHAR_ACTION_CONDITION_NONE;
const int sd_recovery_quantity = CalcSDRecover(
char_type, char_condition, (moving_flag | fighting_flag), char_info_.m_LV);
m_Attr.SetCharInfo(&char_info_, hp_recovery_quantity, mp_recovery_quantity, sd_recovery_quantity);
m_Attr.UpdateEx();
}
BOOL
Player::InitStat(BYTE eInitStat, WORD& OUT DecreaseValue)
{
// CHANGES: f110701.2L, added the rule is to prevent irregula stat calcuation
// like the dragon transformed state.
if (this->GetStatusManager()->Status.IsDragonTransforming()) {
return false; //RC::RC_ITEM_UNABLE_FUNCTION_FOR_TRANSFORMATION;
};
switch(eInitStat)
{
case eItemWASTE_INIT_STR:
case eItemWASTE_INIT_DEX:
case eItemWASTE_INIT_VIT:
case eItemWASTE_INIT_SPR:
case eItemWASTE_INIT_INT:
case eItemWASTE_INIT_Experty1:
case eItemWASTE_INIT_Experty2:
if(!InitStatAKind(eInitStat, DecreaseValue))
return FALSE;
break;
case eItemWASTE_INIT_ALL:
if(!InitStatAll())
return FALSE;
GAMELOG->WriteInitStatAll(this, ACT_INIT_STAT_ALL);
break;
case eItemWASTE_INIT_BASIC_STAT_ALL:
if(!CanInitBasicStatAll())
return FALSE;
InitBasicStatAll();
GAMELOG->WriteInitStatAll(this, ACT_INIT_BASIC_STAT_ALL);
break;
#ifdef _NA_0_20100901_SKILLTREE_SYSTEM
case eItemWASTE_INIT_EXPERTY_ALL:
InitSkillStatAll();
GAMELOG->WriteInitStatAll(this, ACT_INIT_EXPERTY_STAT_ALL);
break;
#else
case eItemWASTE_INIT_EXPERTY_ALL:
if(!CanInitExpertyStatAll())
return FALSE;
InitExpertyStatAll();
GAMELOG->WriteInitStatAll(this, ACT_INIT_EXPERTY_STAT_ALL);
break;
#endif //_NA_0_20100901_SKILLTREE_SYSTEM
#if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_)
case eItemWASTE_INIT_PASSIVE_ALL:
InitPassiveStatAll();
GAMELOG->WriteInitStatAll(this, ACT_INIT_PASSIVE_SKILL_ALL);
break;
// next logging and fails
#endif
default:
SUNLOG(eCRITICAL_LOG, "ItemManager::UseStatInitItem : 없는 WasteType");
return FALSE;
}
if(eInitStat == eItemWASTE_INIT_ALL ||
eInitStat == eItemWASTE_INIT_BASIC_STAT_ALL ||
eInitStat == eItemWASTE_INIT_EXPERTY_ALL)
{
const BASE_PLAYERINFO* pBasePlayerInfo = &char_info_;
MSG_CG_ITEM_STAT_ALL_CHANGE_CMD msgCMD;
msgCMD.m_sStrength = pBasePlayerInfo->m_sStrength;
msgCMD.m_sDexterity = pBasePlayerInfo->m_sDexterity;
msgCMD.m_sVitality = pBasePlayerInfo->m_sVitality;
msgCMD.m_sInteligence = pBasePlayerInfo->m_sInteligence;
msgCMD.m_sSpirit = pBasePlayerInfo->m_sSpirit;
msgCMD.m_sSkillStat1 = pBasePlayerInfo->m_sSkillStat1;
msgCMD.m_sSkillStat2 = pBasePlayerInfo->m_sSkillStat2;
msgCMD.m_iRemainStat = pBasePlayerInfo->m_iRemainStat;
SendPacket(&msgCMD, sizeof(msgCMD));
}
#ifdef _NA_002289_20110322_EQUIPMENTS_CALCULATOR_CHANGES_FOR_IMPROVEMENT
this->m_pItemManager->UpdateItemAttributes(true, false);
#endif
return TRUE;
}
BOOL
Player::InitStatAKind(BYTE init_char_type, WORD& OUT result_decrease_value)
{
// CHANGES, f100828.2L, waverix, code arrangement
const INIT_CHARINFO* init_char_info = \
CharInfoParser::Instance()->GetInitCharInfo(char_info_.m_byClassCode);
short min_value = 0;
short* change_value_field = NULL;
eATTR_TYPE attr_type = eATTR_TYPE_INVALID;
switch (init_char_type)
{
case eItemWASTE_INIT_STR:
min_value = init_char_info->m_sStrength;
change_value_field = &(char_info_.m_sStrength);
attr_type = eATTR_STR;
break;
case eItemWASTE_INIT_DEX:
min_value = init_char_info->m_sDexterity;
change_value_field = &(char_info_.m_sDexterity);
attr_type = eATTR_DEX;
break;
case eItemWASTE_INIT_VIT:
min_value = init_char_info->m_sVitality;
change_value_field = &(char_info_.m_sVitality);
attr_type = eATTR_VIT;
break;
case eItemWASTE_INIT_SPR:
min_value = init_char_info->m_sSpirit;
change_value_field = &(char_info_.m_sSpirit);
attr_type = eATTR_SPR;
break;
case eItemWASTE_INIT_INT:
min_value = init_char_info->m_sInteligence;
change_value_field = &(char_info_.m_sInteligence);
attr_type = eATTR_INT;
break;
case eItemWASTE_INIT_Experty1:
min_value = init_char_info->m_sSkillStat1;
change_value_field = &(char_info_.m_sSkillStat1);
attr_type = eATTR_EXPERTY1;
m_pSkillSlotManager->InitSkill();
break;
case eItemWASTE_INIT_Experty2:
min_value = init_char_info->m_sSkillStat2;
change_value_field = &(char_info_.m_sSkillStat2);
attr_type = eATTR_EXPERTY2;
m_pSkillSlotManager->InitSkill();
break;
default:
return false;
}
if (change_value_field == NULL)
return false;
if (attr_type == eATTR_TYPE_INVALID)
return false;
if ((*change_value_field) < min_value)
return false;
if (((*change_value_field) - result_decrease_value) < min_value)
result_decrease_value = (*change_value_field) - min_value;
if (result_decrease_value == 0)
return false;
(*change_value_field) -= result_decrease_value;
char_info_.m_iRemainStat += result_decrease_value;
UpdateCharStat();
MSG_CG_ITEM_STAT_ONE_CHANGE_CMD msgCMD;
msgCMD.m_AttrType = attr_type;
msgCMD.m_dwValue = (*change_value_field);
msgCMD.m_iRemainStat = GetRemainStatPoint();
SendPacket(&msgCMD, sizeof(msgCMD));
//LOG
GAMELOG->WriteDecreaseStat(this, attr_type, result_decrease_value);
return true;
}
BOOL
Player::InitStatAll()
{
if(!CanInitBasicStatAll())
return FALSE;
if(!CanInitExpertyStatAll())
return FALSE;
InitBasicStatAll();
InitExpertyStatAll();
#ifdef _JP_20100114_CHANGE_ATTRIBUTE_LETECRARFE
InitPassiveStatAll();
#endif
return TRUE;
}
BOOL
Player::CanInitBasicStatAll()
{
BASE_PLAYERINFO* pPlayerInfo = GetCharInfo();
INIT_CHARINFO* pInitCharInfo =
CharInfoParser::Instance()->GetInitCharInfo(pPlayerInfo->m_byClassCode);
if(pPlayerInfo->m_sStrength < pInitCharInfo->m_sStrength ||
pPlayerInfo->m_sDexterity < pInitCharInfo->m_sDexterity ||
pPlayerInfo->m_sVitality < pInitCharInfo->m_sVitality ||
pPlayerInfo->m_sSpirit < pInitCharInfo->m_sSpirit ||
pPlayerInfo->m_sInteligence < pInitCharInfo->m_sInteligence)
{
return FALSE;
}
return TRUE;
}
void
Player::InitBasicStatAll()
{
BASE_PLAYERINFO* pPlayerInfo = GetCharInfo();
INIT_CHARINFO* pInitCharInfo = CharInfoParser::Instance()->GetInitCharInfo(pPlayerInfo->m_byClassCode);
#ifdef __NA_0_STAT_INIT_WHEN_100LEVEL_CHANGEUP
//STR
if(pPlayerInfo->m_sStrength > pInitCharInfo->m_sStrength)
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sStrength - pInitCharInfo->m_sStrength);
pPlayerInfo->m_sStrength = pInitCharInfo->m_sStrength;
//DEX
if(pPlayerInfo->m_sDexterity > pInitCharInfo->m_sDexterity)
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sDexterity - pInitCharInfo->m_sDexterity);
pPlayerInfo->m_sDexterity = pInitCharInfo->m_sDexterity;
//VIT
if(pPlayerInfo->m_sVitality > pInitCharInfo->m_sVitality)
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sVitality - pInitCharInfo->m_sVitality);
pPlayerInfo->m_sVitality = pInitCharInfo->m_sVitality;
//SPR
if(pPlayerInfo->m_sSpirit > pInitCharInfo->m_sSpirit)
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sSpirit - pInitCharInfo->m_sSpirit);
pPlayerInfo->m_sSpirit = pInitCharInfo->m_sSpirit;
//int
if(pPlayerInfo->m_sInteligence > pInitCharInfo->m_sInteligence)
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sInteligence - pInitCharInfo->m_sInteligence);
pPlayerInfo->m_sInteligence = pInitCharInfo->m_sInteligence;
#else
//STR
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sStrength - pInitCharInfo->m_sStrength);
pPlayerInfo->m_sStrength = pInitCharInfo->m_sStrength;
//DEX
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sDexterity - pInitCharInfo->m_sDexterity);
pPlayerInfo->m_sDexterity = pInitCharInfo->m_sDexterity;
//VIT
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sVitality - pInitCharInfo->m_sVitality);
pPlayerInfo->m_sVitality = pInitCharInfo->m_sVitality;
//SPR
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sSpirit - pInitCharInfo->m_sSpirit);
pPlayerInfo->m_sSpirit = pInitCharInfo->m_sSpirit;
//int
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sInteligence - pInitCharInfo->m_sInteligence);
pPlayerInfo->m_sInteligence = pInitCharInfo->m_sInteligence;
#endif
UpdateCharStat();
}
BOOL
Player::CanInitExpertyStatAll()
{
BASE_PLAYERINFO* pPlayerInfo = GetCharInfo();
INIT_CHARINFO* pInitCharInfo =
CharInfoParser::Instance()->GetInitCharInfo(pPlayerInfo->m_byClassCode);
if(pPlayerInfo->m_sSkillStat1 < pInitCharInfo->m_sSkillStat1 ||
pPlayerInfo->m_sSkillStat2 < pInitCharInfo->m_sSkillStat2)
{
return FALSE;
}
return TRUE;
}
void
Player::InitExpertyStatAll()
{
#if !defined(_NA001605_EP2_ATTRIBUTES_RENEWAL_)
BASE_PLAYERINFO* pPlayerInfo = GetCharInfo();
INIT_CHARINFO* pInitCharInfo =
CharInfoParser::Instance()->GetInitCharInfo(pPlayerInfo->m_byClassCode);
#ifdef __NA_0_STAT_INIT_WHEN_100LEVEL_CHANGEUP
//SKILL1
if(pPlayerInfo->m_sSkillStat1 > pInitCharInfo->m_sSkillStat1)
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sSkillStat1 - pInitCharInfo->m_sSkillStat1);
pPlayerInfo->m_sSkillStat1 = pInitCharInfo->m_sSkillStat1;
//SKILL2
if(pPlayerInfo->m_sSkillStat2 > pInitCharInfo->m_sSkillStat2)
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sSkillStat2 - pInitCharInfo->m_sSkillStat2);
pPlayerInfo->m_sSkillStat2 = pInitCharInfo->m_sSkillStat2;
#else
//SKILL1
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sSkillStat1 - pInitCharInfo->m_sSkillStat1);
pPlayerInfo->m_sSkillStat1 = pInitCharInfo->m_sSkillStat1;
//SKILL2
pPlayerInfo->m_iRemainStat += (pPlayerInfo->m_sSkillStat2 - pInitCharInfo->m_sSkillStat2);
pPlayerInfo->m_sSkillStat2 = pInitCharInfo->m_sSkillStat2;
#endif
//갱신
UpdateCharStat();
#endif
//
m_pSkillSlotManager->InitSkill();
}
void
Player::InitPassiveStatAll()
{
m_pSkillSlotManager->InitPassiveSkillStyle();
}
#ifdef _NA_0_20100901_SKILLTREE_SYSTEM
void
Player::InitSkillStatAll()
{
m_pSkillSlotManager->InitSkill();
}
#endif //_NA_0_20100901_SKILLTREE_SYSTEM
BOOL
Player::CheckValidStatPoint()
{
BASE_PLAYERINFO* pPlayerInfo = GetCharInfo();
INIT_CHARINFO* pInitCharInfo =
CharInfoParser::Instance()->GetInitCharInfo(pPlayerInfo->m_byClassCode);
m_bCheckedStat = TRUE;
//如果初始化字符的状态大于创建的字符,则错误!!!
if(pInitCharInfo->m_sStrength > pPlayerInfo->m_sStrength)
return FALSE;
if(pInitCharInfo->m_sDexterity > pPlayerInfo->m_sDexterity)
return FALSE;
if(pInitCharInfo->m_sVitality > pPlayerInfo->m_sVitality)
return FALSE;
if(pInitCharInfo->m_sInteligence > pPlayerInfo->m_sInteligence)
return FALSE;
if(pInitCharInfo->m_sSpirit > pPlayerInfo->m_sSpirit)
return FALSE;
if(pInitCharInfo->m_sSkillStat1 > pPlayerInfo->m_sSkillStat1)
return FALSE;
if(pInitCharInfo->m_sSkillStat2 > pPlayerInfo->m_sSkillStat2)
return FALSE;
SHORT sumStatPoint = 0;
SHORT mustHavePoint = 0;
// sumStatPoint
sumStatPoint += pPlayerInfo->m_sStrength - pInitCharInfo->m_sStrength;
sumStatPoint += pPlayerInfo->m_sDexterity - pInitCharInfo->m_sDexterity;
sumStatPoint += pPlayerInfo->m_sVitality - pInitCharInfo->m_sVitality;
sumStatPoint += pPlayerInfo->m_sInteligence - pInitCharInfo->m_sInteligence;
sumStatPoint += pPlayerInfo->m_sSpirit - pInitCharInfo->m_sSpirit;
sumStatPoint += pPlayerInfo->m_sSkillStat1 - pInitCharInfo->m_sSkillStat1;
sumStatPoint += pPlayerInfo->m_sSkillStat2 - pInitCharInfo->m_sSkillStat2;
sumStatPoint += pPlayerInfo->m_iRemainStat;
// mustHavePoint - (WAVERIX) (081208) Restrict Warning
mustHavePoint += static_cast<SHORT>((pPlayerInfo->m_LV - 1) * GetStatPointPerLevel());
// check
if(mustHavePoint > sumStatPoint)
return FALSE;
if(mustHavePoint + (MAX_AC_SECTION_NUM * (2) * 5) < sumStatPoint)
return FALSE;
return TRUE;
}
void
Player::RecoveryStatPoint()
{
BASE_PLAYERINFO* pPlayerInfo = GetCharInfo();
INIT_CHARINFO* pInitCharInfo =
CharInfoParser::Instance()->GetInitCharInfo(pPlayerInfo->m_byClassCode);
pPlayerInfo->m_sStrength = pInitCharInfo->m_sStrength;
pPlayerInfo->m_sDexterity = pInitCharInfo->m_sDexterity;
pPlayerInfo->m_sVitality = pInitCharInfo->m_sVitality;
pPlayerInfo->m_sInteligence = pInitCharInfo->m_sInteligence;
pPlayerInfo->m_sSpirit = pInitCharInfo->m_sSpirit;
pPlayerInfo->m_sSkillStat1 = pInitCharInfo->m_sSkillStat1;
pPlayerInfo->m_sSkillStat2 = pInitCharInfo->m_sSkillStat2;
pPlayerInfo->m_iRemainStat = (pPlayerInfo->m_LV - 1) * GetStatPointPerLevel();
UpdateCharStat();
MSG_CG_ITEM_STAT_ALL_CHANGE_CMD CmdMsg;
CmdMsg.m_sStrength = pPlayerInfo->m_sStrength;
CmdMsg.m_sDexterity = pPlayerInfo->m_sDexterity;
CmdMsg.m_sVitality = pPlayerInfo->m_sVitality;
CmdMsg.m_sInteligence = pPlayerInfo->m_sInteligence;
CmdMsg.m_sSpirit = pPlayerInfo->m_sSpirit;
CmdMsg.m_sSkillStat1 = pPlayerInfo->m_sSkillStat1;
CmdMsg.m_sSkillStat2 = pPlayerInfo->m_sSkillStat2;
CmdMsg.m_iRemainStat = pPlayerInfo->m_iRemainStat;
SendPacket(&CmdMsg, sizeof(CmdMsg));
}
#ifdef __NA_0_STAT_INIT_WHEN_100LEVEL_CHANGEUP
BOOL
Player::InitAllStatByChangeUp()
{
InitBasicStatAll();
InitExpertyStatAll();
InitPassiveStatAll();
BASE_PLAYERINFO* pPlayerInfo = GetCharInfo();
MSG_CG_ITEM_STAT_ALL_CHANGE_CMD CmdMsg;
CmdMsg.m_sStrength = pPlayerInfo->m_sStrength;
CmdMsg.m_sDexterity = pPlayerInfo->m_sDexterity;
CmdMsg.m_sVitality = pPlayerInfo->m_sVitality;
CmdMsg.m_sInteligence = pPlayerInfo->m_sInteligence;
CmdMsg.m_sSpirit = pPlayerInfo->m_sSpirit;
CmdMsg.m_sSkillStat1 = pPlayerInfo->m_sSkillStat1;
CmdMsg.m_sSkillStat2 = pPlayerInfo->m_sSkillStat2;
CmdMsg.m_iRemainStat = pPlayerInfo->m_iRemainStat;
SendPacket(&CmdMsg, sizeof(CmdMsg));
return TRUE;
}
#endif
// update all inventory insert rule configures
bool Player::UpdateInventoryConfig(const nsSlot::InventoryConfig& changed_info)
{
//
const nsSlot::InventoryConfig& inven_config = char_info_.m_InventoryConfig;
const nsSlot::InventoryConfig::SetType* src_it = inven_config.configures,
* const src_end = &inven_config.configures[\
_countof(inven_config.configures)];
const nsSlot::InventoryConfig::SetType* change_it = changed_info.configures;
for ( ; src_it != src_end; ++src_it, ++change_it)
{
if (*src_it != *change_it) {
break;
}
}
if (src_it == src_end) { // no changes, don't need update
return false;
}
CInventorySlotContainer* inventory = static_cast<CInventorySlotContainer*>(\
m_pItemManager->GetItemSlotContainer(SI_INVENTORY));
inventory->UpdateInventoryConfiguration(changed_info);
return true;
}
//_NA_000096_20100527_CHANGE_CHARACTER_APPEARANCE_SYSTEM
RC::eCHANGE_CHARACTER_APPEARANCE_RESULT Player::ChangeCharacterAppearance(
CharacterAppearanceInfo& INOUT character_appearance)
{
if (character_appearance.appearance_type_ == ChangeCharacterAppearanceTypeConst::kNone)
{
return RC::RC_CHANGE_CHARACTER_APPEARANCE_FAIL;
}
// BASE_PLAYERINFO* const player = SCPlayer::GetCharInfo(); // backup a previous aliasing code
// NOTE, ... player? this is no big deal in a short term block,
// but the name called player is customarily ambigous
// because of most of codes are used to mean a alias of an instance of the 'Player' class
// so that I replace to char_info_ changed by the f100827.4L. - written by waverix
{
#ifdef _NA_002050_20110216_ADD_GENDER
if (ChangeCharacterAppearanceTypeConst::IsChangeGender(character_appearance.appearance_type_) &&
character_appearance.gender != char_info_.gender)
{
if (character_appearance.gender != GenderType::kMale &&
character_appearance.gender != GenderType::kFemale)
{
return RC::RC_CHANGE_CHARACTER_APPEARANCE_FAIL;
}
char_info_.gender = character_appearance.gender;
}
#endif
if (ChangeCharacterAppearanceTypeConst::IsChangeFace(character_appearance.appearance_type_) &&
character_appearance.face_ != char_info_.m_byFace)
{
char_info_.m_byFace = character_appearance.face_;
}
if (ChangeCharacterAppearanceTypeConst::IsChangeHair(character_appearance.appearance_type_) &&
character_appearance.hair_ != char_info_.m_byHair)
{
char_info_.m_byHair = character_appearance.hair_;
}
if (ChangeCharacterAppearanceTypeConst::IsChangeHeight(character_appearance.appearance_type_) &&
character_appearance.height_ != char_info_.m_byHeight)
{
char_info_.m_byHeight = character_appearance.height_;
}
}
return RC::RC_CHANGE_CHARACTER_APPEARANCE_SUCCESS;
}
// implemented by _NA_002399_20110323_MONEY_DISTRIBUTE_METHOD_CHANGE
BOOL Player::PickMoney(MONEY nMoney, DWORD dwMonsterKey, Player* pOwner)
{
MONEY DropMoney = nMoney;
if( dwMonsterKey != 0 )
{
if( GetBonusMoneyRatio() )
{
DropMoney = (MONEY)(ceil)( DropMoney * ( 1.f + GetBonusMoneyRatio() ) );
}
}
#ifdef __NA_000632_20070817_CHINA_FATIGUE_HEIM
BYTE byPickRatio = GetFatigueManager()->GetShareHeimPickupRatio();
DropMoney = ( DropMoney / (float)(100.0/byPickRatio) );
#endif
PlusMoney( DropMoney );
GAMELOG->LogMoney( MONEY_PICK, this, DropMoney );
#ifdef _NA_20101026_CHANGE_GROUP_BONUS_APPLY_WAY
if (GetGroupHighMemberInfo() == GROUP_HAVE_ONLINE_HIGH ||
GetGroupHighMemberInfo() == GROUP_HAVE_OFFLINE_HIGH)
{
GroupBonusAcceptForMoney( nMoney, DropMoney, eHEIM_ACQUISITION_PICKUP );
}
#else
if( GetGroupLowMemberInfo() == GROUP_HAVE_ONLINE_LOW )
{
GroupBonusAcceptForMoney( nMoney, DropMoney, eHEIM_ACQUISITION_PICKUP );
}
#endif
MSG_CG_ITEM_PICK_MONEY_ACK sendMsg;
sendMsg.m_Money = GetMoney();
sendMsg.m_BonusRatio = (WORD)ceil( GetBonusMoneyRatio() * 100 );
SendPacket( &sendMsg, sizeof( sendMsg ) );
return TRUE;
}