#include "stdafx.h" #include "Player.h" #include #include #include #include #include #include #include #include #include #include //================================================================================================== // 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 #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 #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(); // ;{ // HP,MP,SD恢复率 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(\ 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;iIsEmpty(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;iSerializeSkillStream(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( 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(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(pos); item_slot->CopyOut(target->m_Stream); }; //------------------------------------------- };//end 'foreach slot_list' // const POSTYPE number_of_real_renderable_equips = static_cast(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( 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(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(GetItemManager()->GetItemSlotContainer(SI_INVENTORY)); const SCItemSlot& item_slot = static_cast( 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(GetItemManager()->GetItemSlotContainer(SI_INVENTORY)); const SCItemSlot& item_slot = static_cast( 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(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 // //---------------------------------------------------------------------------------------------- // 定义需要渲染的各种视觉效果 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 CharInfo)2.道具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(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(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(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(pEquipSlotContainer->GetSlot(eEQUIPCONTAINER_WEAPON)); //检查激活与否和内部结构 if (pEquipSlotContainer->IsActivated(eEQUIPCONTAINER_WEAPON) == true && rSlot.GetDura() != 0) { SCItemSlot& rSlot = static_cast(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( 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( 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(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(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)-在进行宏清除工作时,可能会成为逻辑变更的事例之一…-; //-changes:source 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( this->GetItemManager()->GetItemSlotContainer(SI_EQUIPMENT)); const SCItemSlot& item_slot = static_cast(\ 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(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(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((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(\ 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; }