#include "StdAfx.h" #include "FieldPvP.h" #include "ChaoState.h" #include "Player.h" #include "ItemManager.h" #include "DropManager.h" #include "SCItemSlotContainer.h" #include "PKScriptParser.h" #include "GameGuildExtension.h" #ifdef _NA_006826_20130722_DOMINATION_RENEWAL #include "GameGuild.h" #include "GameGuildManager.h" #include "DominationInfoParser.h" #include "GameDominationManager.h" #endif // _NA_006826_20130722_DOMINATION_RENEWAL //================================================================================================== FieldPvPRuleManager::FieldPvPRuleManager( WORD wConflictParts ) : m_wConflictParts(wConflictParts) { CreateTroubledPart(); } FieldPvPRuleManager::~FieldPvPRuleManager() { m_vTroubledPart.clear(); } void FieldPvPRuleManager::CreateTroubledPart() { m_vTroubledPart.clear(); if( m_wConflictParts & PTA_PK_TILE ) m_vTroubledPart.push_back(FieldPvpPtr(new BoundaryPart())); if( m_wConflictParts & PTA_CONFLICT_TILE ) m_vTroubledPart.push_back(FieldPvpPtr(new NomalPart())); if( m_wConflictParts & PTA_FREE_CONFLICT_TILE ) m_vTroubledPart.push_back(FieldPvpPtr(new FreePart())); if( m_wConflictParts & PTA_DOMINATION_WAR_TILE ) m_vTroubledPart.push_back(FieldPvpPtr(new DominationPart())); if( m_wConflictParts & PTA_SAFETY_ZONE ) m_vTroubledPart.push_back(FieldPvpPtr(new SafetyPart())); } FieldPvPRuleManager::FieldPvpPtr FieldPvPRuleManager::GetPart(Player* const player) const { if (obj_util::IsValid(player)) { WORD tile = 0; if (player->GetTileAtt(&tile)) { for (FieldPvP_List::const_iterator it = m_vTroubledPart.begin(); it != m_vTroubledPart.end(); ++it) { FieldPvpPtr field_pvp = *it; if (field_pvp->IsPart(tile)) { return field_pvp; } } } } return FieldPvpPtr(); } //================================================================================================== //ÇÊµå ¼­¹ö °øÅë PvP·ê BOOL FieldPvP::ChkServer( OUT RC::eBATTLE_RESULT* pErrCode ) { // ¿ùµå¼­¹ö¿Í ²÷¾îÁ® ÀÖÀ¸¸é PK¸¦ ¸·´Â´Ù. if( !g_pGameServer->IsConnectToWorldServer() ) { *pErrCode = RC::RC_BATTLE_SERVER_STATE_IMPOSSIBLE_PK; return FALSE; // PK°¡ °¡´ÉÇÑ ¼­¹öÀÎÁö üũ } if( !g_pGameServer->IsPVPMode() ) { *pErrCode = RC::RC_BATTLE_ISNOT_PK_SERVER; return FALSE; } return TRUE; } BOOL FieldPvP::ChkTarget( Player *pTarget, OUT RC::eBATTLE_RESULT* pErrCode ) { if( !pTarget ) { *pErrCode = RC::RC_BATTLE_INVALID_MAINTARGET; return FALSE; } // Ÿ°ÙÀÌ Á¸Àç Çҽà ÇǰÝÀÚ Ã¼Å© (µ¿ÀÏ Áö¿ªÀÌ ¾Æ´Ï¶ó¸é °ø°Ý ºÒ°¡) WORD wTileAtt = 0; if( FALSE == pTarget->GetTileAtt(&wTileAtt) ) { *pErrCode = RC::RC_BATTLE_PLAYER_TILE_INVLIDPOS; return FALSE; } if( !IsPart(wTileAtt) ) { *pErrCode = RC::RC_BATTLE_ISNOT_TROUBLED_PART; return FALSE; } return TRUE; } RC::eSKILL_RESULT FieldPvP::ConvErrCode( RC::eBATTLE_RESULT ErrCode ) { switch( ErrCode ) { case RC::RC_BATTLE_FAILED: return RC::RC_SKILL_FAILED; case RC::RC_BATTLE_ISNOT_PK_SERVER: return RC::RC_SKILL_ISNOT_PK_SERVER; case RC::RC_BATTLE_INVALID_MAINTARGET: return RC::RC_SKILL_TARGET_NOTEXIST; case RC::RC_BATTLE_ISNOT_TROUBLED_PART: return RC::RC_SKILL_ISNOT_TROUBLED_TYPE; case RC::RC_BATTLE_TARGET_LEVEL_IS_LOW: return RC::RC_SKILL_TARGET_LEVEL_IS_LOW; case RC::RC_BATTLE_SAME_GUILD_CHARACTER: return RC::RC_SKILL_SAME_GUILD_CHARACTER; case RC::RC_BATTLE_SAME_PARTY_CHARACTER: return RC::RC_SKILL_SAME_PARTY_CHARACTER; case RC::RC_BATTLE_PLAYER_TILE_INVLIDPOS: return RC::RC_SKILL_PLAYER_TILE_INVLIDPOS; case RC::RC_BATTLE_ATTACKER_LEVEL_IS_LOW: return RC::RC_SKILL_ATTACKER_LEVEL_IS_LOW; case RC::RC_BATTLE_PK_IMPOSSIBLE_TARGET_TYPE: return RC::RC_SKILL_PK_IMPOSSIBLE_TARGET_TYPE; case RC::RC_BATTLE_SERVER_STATE_IMPOSSIBLE_PK: return RC::RC_SKILL_SERVER_STATE_IMPOSSIBLE_PK; default: break; } return RC::RC_SKILL_FAILED; } eUSER_RELATION_TYPE FieldPvP::IsFriendPVP( Player* pAttacker, Player *pTarget ) { RC::eBATTLE_RESULT dummy; return PvPRule(pAttacker,pTarget,&dummy); } BOOL FieldPvP::CanPVP( Player* pAttacker, Player* pTarget, OUT RC::eBATTLE_RESULT* pErrCode ) { if( !ChkServer(pErrCode) ) return FALSE; // ¼­¹ö°¡ pvpÇÒ¼ö ¾ø´Ù¸é °ø°Ý ºÒ°¡. PvPRule(pAttacker,pTarget,pErrCode); if( *pErrCode != RC::RC_BATTLE_SUCCESS ) return FALSE; return TRUE; } BOOL FieldPvP::CanPVP( Player* pAttacker, Player* pTarget, OUT RC::eSKILL_RESULT* pErrCode ) { RC::eBATTLE_RESULT BattleErrCode = RC::RC_BATTLE_SUCCESS; if( !CanPVP(pAttacker,pTarget,&BattleErrCode) ) { *pErrCode = ConvErrCode(BattleErrCode); return FALSE; } return TRUE; } VOID FieldPvP::Resurrection( Player* pDeadPlayer ) { GameField* pField = pDeadPlayer->GetField(); WzVector wvPosOfPlayer; if( pField ) wvPosOfPlayer = pField->GetRandomStartingVector(); else pDeadPlayer->GetPos(&wvPosOfPlayer); pDeadPlayer->SetFallDead(wvPosOfPlayer); } BOOL FieldPvP::ChkDropItem( Player* pAttacker, Player* pDeadPlayer ) { // GM ¸Ê¿¡¼­´Â ¾ÆÀÌÅÛÀ» ¶³±¸Áö ¾Ê´Â´Ù. GameField *pField = pDeadPlayer->GetField(); if( pField ) { if( HardCode::MAPCODE_for_GM == pField->GetFieldCode() ) return FALSE; } // µå¶ø ¹æÁö ¾ÆÀÌÅÛÀÌ Á¸ÀçÇÏ´ÂÁö üũ if (pDeadPlayer->GetItemManager()->GetItemFunctionDropProtector().ProtectDrop(pAttacker)) { return FALSE; }; return TRUE; } VOID FieldPvP::DropItem( Player* pAttacker, Player* pDeadPlayer, SLOTIDX DropSlotIndex ) { POSTYPE atSlotPos = 0; SCSlotContainer* pContainer = NULL; switch(DropSlotIndex) { case SI_EQUIPMENT: //210924 RTX ×°±¸30%¼¸ÂʵôÂ䣬ÆäÓàÇé¿öµôÎïÆ· if(((unsigned int)rand()) % 100 <= 29){ pContainer = pDeadPlayer->GetItemManager()->GetItemSlotContainer( SI_EQUIPMENT ); if( !SelectPKDropItem( pContainer, atSlotPos ) ) { pContainer = pDeadPlayer->GetItemManager()->GetItemSlotContainer( SI_INVENTORY ); if( !pDeadPlayer->GetCharInfo()->m_iInventoryLock && SelectPKDropItem(pContainer,atSlotPos) ) DropSlotIndex = SI_INVENTORY; else return; } }else{ pContainer = pDeadPlayer->GetItemManager()->GetItemSlotContainer( SI_INVENTORY ); if( !pDeadPlayer->GetCharInfo()->m_iInventoryLock && SelectPKDropItem(pContainer,atSlotPos) ) DropSlotIndex = SI_INVENTORY; else return; } break; case SI_INVENTORY: pContainer = pDeadPlayer->GetItemManager()->GetItemSlotContainer( SI_INVENTORY ); if( !pDeadPlayer->GetCharInfo()->m_iInventoryLock && SelectPKDropItem(pContainer,atSlotPos) ) {} else return; break; } // ¼±ÅÃÇÑ ¾ÆÀÌÅÛÀ» Çʵ忡 ¶³±º´Ù. SCItemSlot DropItemSlotOut; SCSlotContainer * pAtContainer = pDeadPlayer->GetItemManager()->GetItemSlotContainer( DropSlotIndex ); if( !pAtContainer->DeleteSlot( atSlotPos, &DropItemSlotOut ) ) return; if( DropItemSlotOut.IsPossessionItem() && DropItemSlotOut.GetIdentifyPossession() && !DropItemSlotOut.IsDestroyItem() ) { switch( PKScriptParser::Instance()->GetPKOptionInfo().m_ePossessionDropOption ) { case PKOptionInfo::ENUM_POSSESSION_DROP_NO: SUNLOG( eCRITICAL_LOG, "Can't come to this logic..."); break; case PKOptionInfo::ENUM_POSSESSION_DROP_ORIGINAL: DropItemSlotOut.SetIdentifyPossession( FALSE ); break; case PKOptionInfo::ENUM_POSSESSION_DROP_DESTROY: DropItemSlotOut.SetDestroyItem( TRUE ); break; } } WzVector wvCurPos = pDeadPlayer->GetRandomPosInAround( 2, 30 ); if( !g_DropManager.DropItemToField( pDeadPlayer->GetField(), &wvCurPos, pAttacker->GetObjectKey(), 0, DropItemSlotOut ) ) return; MSG_CG_ITEM_PK_DROP_ITEM_CMD msg; msg.m_atIndex = DropSlotIndex; msg.m_atPos = atSlotPos; pDeadPlayer->SendPacket( &msg, sizeof( msg ) ); // °ÔÀÓ ·Î±× GAMELOG->LogItem( ITEM_PK_DROP, pDeadPlayer, &DropItemSlotOut, 0, DropItemSlotOut.GetNum() ); } BOOL FieldPvP::SelectPKDropItem( SCSlotContainer* pContainer, POSTYPE & OUT atSlotPos ) { // ÇöÀç ÄÁÅ×À̳ʿ¡ µé¾îÀÖ´Â ¾ÆÀÌÅÛ °³¼ö if( pContainer->GetSlotNum() == 0 ) return FALSE; STLX_VECTOR vecValidSlot; PKOptionInfo::ePoessessionDropOption DropOption = PKScriptParser::Instance()->GetPKOptionInfo().m_ePossessionDropOption; //(shogen) for¹®À» µÎ¹ø µ¹Áö ¸»°í º¤Å͸¦ //µÎ°³½á¼­ ÇÏ´Â°Ô ½Ã°£º¹Àâµµ¸¦ ÁÙÀϰǵ¥... //¿À´Ã Åð»ç¶ó ±×³É °©´Ï´Ù. ´ÙÀ½¿¡ º¸½Ã´Â ºÐµé ¼öÁ¤ ºÎÅ¹ÇØ¿ä '')/ //Àåºñ¸¸ °Ë»öÇØ º»´Ù. for( POSTYPE SlotPos = 0; SlotPos < pContainer->GetMaxSlotNum(); ++SlotPos ) { if( pContainer->IsEmpty(SlotPos) ) continue; // ¶ô¿©ºÎ üũ if( pContainer->IsLocked(SlotPos) ) continue; #ifdef _CN_008758_20160329_FIELD_PVP_DROPITEM_TRADESELL_CHANGE // µå¶ø ºÒ°¡´ÉÇÑ ¾ÆÀÌÅÛÀΰ¡? ( Äù½ºÆ® ¾ÆÀÌÅÛ ) SCItemSlot & rSlot = (SCItemSlot &)pContainer->GetSlot(SlotPos); // PK µå¶ø ¾ÆÀÌÅÛÀ» Á¦¿ÜÇÑ ¸ðµç ¾ÆÀÌÅÛ µå¶øÀÌ °¡´ÉÇϵµ·Ï º¯°æ if (rSlot.CanTradeSell(eITEM_TRADESEEL_DROP_CAN_PKDROP) == false) { continue; } #else //210924 BY RTX 0x01Ïà¹Ø²»¿É½»Ò× SCItemSlot & rSlot = (SCItemSlot &)pContainer->GetSlot(SlotPos); if(rSlot.item_info_->trade_sell_type & 0x01){ continue; } // ¸ðµÎ ºÒ´ÉÀÇ ¾ÆÀÌÅÛÀÌ¸é ¹Ù·Î ÆÐ½ºÇÑ´Ù //if (rSlot.CanTradeSell(eITEM_TRADESELL_DONTALL) == false) { // continue; //} //µå¶øºÒ°¡ ¾ÆÀÌÅÛÀ̸鼭 PKµå¶ø °¡´É¾ÆÀÌÅÛÀΰ¡ °Ë»ç if (rSlot.CanTradeSell(eITEM_TRADESELL_DROP) == false) { //_NA_006052_20120904_CANNOT_DROP_CAN_PKDROP if (rSlot.CanTradeSell(eITEM_TRADESEEL_DROP_CAN_PKDROP) == true) { continue; } } #endif //(_CN_008758_20160329_FIELD_PVP_DROPITEM_TRADESELL_CHANGE) //Àåºñ ¾ÆÀÌÅÛÀΰ¡? //210924 BY RTX È¡ÏûÖ»µôÎäÆ÷/µ¯Ò© //if( (!rSlot.GetItemInfo()->IsWeapon()) && !(rSlot.GetItemInfo()->IsArmor()) ) // continue; if( rSlot.IsPossessionItem() && rSlot.GetIdentifyPossession() ) { if( DropOption == PKOptionInfo::ENUM_POSSESSION_DROP_NO ) { if( !rSlot.IsDestroyItem() ) continue; } } // µå¶ø °¡´ÉÇÑ ¾ÆÀÌÅÛÀ» ÀÏ´Ü setValidSlot¿¡ ³Ö´Â´Ù. vecValidSlot.push_back( SlotPos ); } if( vecValidSlot.size() > 0 ) { // ·£´ýÇÏ°Ô ¼¯Àº ÈÄ Ã¹¹øÂ° Ç׸ñÀ» ¼±ÅÃÇÑ´Ù. random_shuffle( vecValidSlot.begin(), vecValidSlot.end() ); atSlotPos = vecValidSlot[0]; return TRUE; } return FALSE; } BYTE FieldPvP::PKDropRatio( int iLevelDiff ) { BYTE byDropRatio = 0; if( iLevelDiff < 0 ) { byDropRatio = max(0, iLevelDiff + 20 ); } else if ( iLevelDiff == 0 ) { #ifdef _CH_006797_20130703_PK_DROP_RULE_MODIFY byDropRatio = 10; #else byDropRatio = 25; #endif // _CH_006797_20130703_PK_DROP_RULE_MODIFY } else if( iLevelDiff > 0 ) { byDropRatio = min(100, iLevelDiff + 30 ); #ifdef _CH_006797_20130703_PK_DROP_RULE_MODIFY if (byDropRatio > 20) { byDropRatio = 20; } #else #ifdef _NA_006057_20120904_PK_DROP_RATIO_MODIFY if (byDropRatio > 50) { byDropRatio = 50; } #endif // _NA_006057_20120904_PK_DROP_RATIO_MODIFY #endif // _CH_006797_20130703_PK_DROP_RULE_MODIFY } return byDropRatio; } // ±æµå ¹«°üÀ̰ųª ±æ¿ø À϶§ false, ½Ö¹æÀû´ë Àû´ë ¼±Æ÷À϶§ true bool FieldPvP::HostilityRelationCheck(Player* pAttacker, Player* pTarget) { if( !pAttacker || !pTarget ) return false; GUILDGUID AttkGld = pAttacker->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; GUILDGUID DefGld = pTarget->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; if( AttkGld == 0 || DefGld == 0 || AttkGld == DefGld ) return false; return GuildSmallContentEntry::RelationSystem::IsHostilityRelation(AttkGld, DefGld); } bool FieldPvP::IsOneSideHostility(Player* pAttacker, Player* pTarget) { if( !pAttacker || !pTarget ) return false; GUILDGUID AttkGld = pAttacker->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; GUILDGUID DefGld = pTarget->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; if( AttkGld == 0 || DefGld == 0 || AttkGld == DefGld ) return false; return eGUILD_RELATION_ONE_SIDE_HOSTILITY == GuildSmallContentEntry::RelationSystem::GetRelationType(AttkGld,DefGld); } ////////////////////////////////////////////////////////////////////////// //ÀÚÀ¯ ºÐÀïÁö¿ª·ê BOOL FreePart::IsPart( const WORD wTileAtt ) { static const BYTE opt = PKScriptParser::Instance()->GetPKOptionInfo().m_IgnorePKTile; if( PKOptionInfo::ignore_FreePart & opt ) return FALSE; return FieldPvP::IsPart(wTileAtt); } BOOL FreePart::RandomizePercent( Player* pAttacker, Player* pDeadPlayer ) { // µå¶ø È®·üÀ» üũÇÑ´Ù. PKOptionInfo & stPKOptionInfo = PKScriptParser::Instance()->GetPKOptionInfo(); int iLevelDiff = pDeadPlayer->GetLevel() - pAttacker->GetLevel(); #ifdef _NA_007710_20141014_MODIFY_CHAO_STATE_NORMAL_DO_NOT_DROP_ITEM if( pDeadPlayer->GetChaoState().GetChaoState() == eCHAO_STATE_NORMAL ) { if( !pAttacker->GetChaoState().FindBadFriend( pDeadPlayer->GetCharGuid() ) ) { // ÀÏ¹Ý »óÅ¿¡¼­´Â PK´çÇØµµ ¸®º¥Áö ´ë»óÀÌ ¾Æ´Ò°æ¿ì ¾ÆÀÌÅÛÀ» µå¶øÇÏÁö ¾Ê´Â´Ù return FALSE; } } #endif // _NA_007710_20141014_MODIFY_CHAO_STATE_NORMAL_DO_NOT_DROP_ITEM BYTE DropRatio = PKDropRatio( iLevelDiff ); return random_percent(DropRatio); } VOID FreePart::KillPlayer( Player* pAttacker, Player* pDeadPlayer, BOOL bSummoned, DAMAGETYPE damage_value /*= 0*/ ) { // ¼Òȯü¸¦ Á×ÀÎ °ÍÀÌ ¾Æ´Ï¶ó¸é ÀÚÀ¯ ºÐÀï Áö¿ª¿¡¼­ ¾ÆÀÌÅÛÀ» ¶³±º´Ù. if( !bSummoned ) { WORD wTileAtt = 0; if( FALSE == pDeadPlayer->GetTileAtt(&wTileAtt) ) { // ´ë»óÀÇ Å¸ÀÏÀÌ Á¸ÀçÇÏÁö ¾Ê´Â´Ù. SUNLOG( eCRITICAL_LOG, "[TroubledPart::%s] Invalid Tile! \n", __FUNCTION__ ); return; } // PK ·Î±×¸¦ ³²±ä´Ù. //_NA_008706_20160229_TEXTLOG_PK GAMELOG->LogAction_PK( ACT_TROUBLED_KILL, pAttacker, pDeadPlayer, damage_value ); GAMELOG->LogAction_PK( ACT_TROUBLED_DIE, pDeadPlayer, pAttacker, damage_value ); //ÇǰÝÀÚ°¡ ÇÁ¸® ºÐÀï Áö¿ªÀϽà ¾ÆÀÌÅÛÀ» ¶³±º´Ù. #ifdef _NA_007710_20141014_MODIFY_CHAO_STATE_NORMAL_DO_NOT_DROP_ITEM if( RandomizePercent(pAttacker,pDeadPlayer) && ChkDropItem(pAttacker,pDeadPlayer) ) #else // _NA_007710_20141014_MODIFY_CHAO_STATE_NORMAL_DO_NOT_DROP_ITEM if( ChkDropItem(pAttacker,pDeadPlayer) && RandomizePercent(pAttacker,pDeadPlayer) ) #endif // _NA_007710_20141014_MODIFY_CHAO_STATE_NORMAL_DO_NOT_DROP_ITEM { SLOTIDX DropSlotIndex = SI_INVENTORY; PKOptionInfo& stPKOptionInfo = PKScriptParser::Instance()->GetPKOptionInfo(); if( random_percent(stPKOptionInfo.m_EquipDropRatio) ) DropSlotIndex = SI_EQUIPMENT; DropItem( pAttacker, pDeadPlayer, DropSlotIndex ); } //¸¶À»¿¡¼­ Á×À»½Ã´Â ºÎȰ ½ÃÄÑÁØ´Ù. //MSG_CG_STATUS_RESURRECTION_TO_SAFEZONE_SYN ÆÐŶÀÌ µé¾î¿Ã °æ¿ì ·ÎÁ÷ º¯°æ ÇÊ¿ä. if( pDeadPlayer->GetGameZoneState() == ePRS_AT_VILLAGE ) Resurrection(pDeadPlayer); } } eUSER_RELATION_TYPE FreePart::PvPRule( Player* pAttacker, Player *pTarget, OUT RC::eBATTLE_RESULT* pErrCode ) { *pErrCode = RC::RC_BATTLE_SUCCESS; if( pAttacker == pTarget ) return USER_RELATION_FRIEND; // 0. ÀÚ±âÀÚ½ÅÀÎÁöÀÌ¸é °ø°Ý(¹öÇÁ) °¡´É if( !ChkTarget(pTarget,pErrCode) ) return USER_RELATION_NEUTRALIST; // 1. ¹üÀ§ °ø°Ý½Ã CanPVP¸¦ ÅëÇÏÁö ¾ÊÀ¸¹Ç·Î üũ ÇÊ¿ä(ŸÀϼӼº). if( !pAttacker->IsForceAttack() ) //.// ÀÏ¹Ý °ø°ÝÀÏ °æ¿ì { if( pAttacker->GetPartyState() == pTarget->GetPartyState() ) // 2. ÆÄƼ¿ø ¾Æ±º return USER_RELATION_FRIEND; GUILDGUID AttkGld = pAttacker->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; GUILDGUID TargetGld = pTarget->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; if( AttkGld != 0 && AttkGld == TargetGld ) return USER_RELATION_FRIEND; // 3. ±æµå¿øÀÌ¸é ¾Æ±ºÀÌ´Ù. if (GuildSmallContentEntry::RelationSystem::GetRelationType(AttkGld, TargetGld) == eGUILD_RELATION_ALLIENCE) return USER_RELATION_FRIEND; // 3_1. ±æµå °ü°è µ¿¸ÍÀÌ¸é ¾Æ±º. } return USER_RELATION_ENEMY; // 4. ¿¹¿Ü¿¡ ºñÇØ´ç À¯Àú Àû±º. } ////////////////////////////////////////////////////////////////////////// //ÀÏ¹Ý ºÐÀïÁö¿ª·ê BOOL NomalPart::IsPart( const WORD wTileAtt ) { static const BYTE opt = PKScriptParser::Instance()->GetPKOptionInfo().m_IgnorePKTile; if( PKOptionInfo::ignore_NomalPart & opt ) return FALSE; return FieldPvP::IsPart(wTileAtt); } VOID NomalPart::KillPlayer( Player* pAttacker, Player* pDeadPlayer, BOOL bSummoned, DAMAGETYPE damage_value /*= 0*/ ) { if( !bSummoned ) { // PK ·Î±×¸¦ ³²±ä´Ù. //_NA_008706_20160229_TEXTLOG_PK GAMELOG->LogAction_PK( ACT_TROUBLED_KILL, pAttacker, pDeadPlayer, damage_value ); GAMELOG->LogAction_PK( ACT_TROUBLED_DIE, pDeadPlayer, pAttacker, damage_value ); //¸¶À»¿¡¼­ Á×À»½Ã´Â ºÎȰ ½ÃÄÑÁØ´Ù. //ÇöÀç ¸¶À»¿¡¼­ Á×´Â °æ¿ì ¾øÀ½. //MSG_CG_STATUS_RESURRECTION_TO_SAFEZONE_SYN ÆÐŶÀÌ µé¾î¿Ã °æ¿ì ·ÎÁ÷ º¯°æ ÇÊ¿ä. if( pDeadPlayer->GetGameZoneState() == ePRS_AT_VILLAGE ) Resurrection(pDeadPlayer); } } eUSER_RELATION_TYPE NomalPart::PvPRule( Player* pAttacker, Player *pTarget, OUT RC::eBATTLE_RESULT* pErrCode ) { *pErrCode = RC::RC_BATTLE_SUCCESS; if( pAttacker == pTarget ) return USER_RELATION_FRIEND; // 0. ÀÚ±âÀÚ½ÅÀÎÁöÀÌ¸é °ø°Ý(¹öÇÁ) °¡´É if( !ChkTarget(pTarget,pErrCode) ) return USER_RELATION_NEUTRALIST; // 1. ¹üÀ§ °ø°Ý½Ã CanPVP¸¦ ÅëÇÏÁö ¾ÊÀ¸¹Ç·Î üũ ÇÊ¿ä(ŸÀϼӼº). if( pAttacker->GetPartyState() == pTarget->GetPartyState() ) // 2. ÆÄƼ¿ø °ø°Ý ºÒ°¡ return USER_RELATION_FRIEND; GUILDGUID AttkGld = pAttacker->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; GUILDGUID DefGld = pTarget->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; if( AttkGld != 0 && AttkGld == DefGld ) return USER_RELATION_FRIEND; // 3. ±æµå¿øÀÌ¸é ¾Æ±ºÀÌ´Ù. if (GuildSmallContentEntry::RelationSystem::GetRelationType(AttkGld, DefGld) == eGUILD_RELATION_ALLIENCE) return USER_RELATION_FRIEND; // 3_1. ±æµå °ü°è µ¿¸ÍÀÌ¸é ¾Æ±º. return USER_RELATION_ENEMY; // 4. °­Á¦°ø°ÝÀÌ Á¸Àç ÇÏÁö ¾ÊÀ¸¸ç, ¿¹¿Ü¿¡ ºñÇØ´ç À¯Àú Àû±º. } ////////////////////////////////////////////////////////////////////////// //°æ°èÁö¿ª·ê //±æµå °ü°è¿¡ µû¸¥ pk·ê Á¤¸® // ±âº»Á¤ÀÇ : "±æµå°£ ¼±ÀüÆ÷°í(Àû´ë¼±Æ÷)¸¦ ÇÑ °æ¿ìÀÇ °ø°ÝÀº Á¤´çÇϸç, // Á¤´çÇÑ °ø°ÝÀº »ó´ë¸¦ Á׿©µµ ÆÐ³ÎƼ¸¦ ¹ÞÁö ¾ÊÀ¸¸ç, ¾ÆÀÌÅÛ ¶ÇÇÑ µå¶øµÇÁö ¾Ê´Â´Ù." // //°æ°èÁö¿ªÀÇ °æ¿ì B¿¡°Ô ¼±ÀüÆ÷°í¸¦ ÇÑ AÀÇ °ø°ÝÀº Á¤´ç°ø°ÝÀ¸·Î ÆÐ³ÎƼ¸¦ ¹ÞÁö ¾ÊÀ¸¸ç //B°¡ Á×ÀÓÀ» ´çÇØµµ ¾ÆÀÌÅÛÀ» µå¶øÇÏÁö ¾Ê´Â´Ù. //¹Ý´ëÀÇ °æ¿ì B°¡ ¼±ÀüÆ÷°í¸¦ ¹Þ¾Æ µéÀÌÁö ¾Ê°í(½Ö¹æÀû´ë), A¸¦ °ø°ÝÇÒ °æ¿ì ÆÐ³ÎƼ¸¦ ¹ÞÀ¸¸ç, //A°¡ ¾ÆÀÌÅÛÀ» µå¶øÇÏ°Ô µÈ´Ù. BOOL BoundaryPart::IsPart( const WORD wTileAtt ) { static const BYTE opt = PKScriptParser::Instance()->GetPKOptionInfo().m_IgnorePKTile; if( PKOptionInfo::ignore_BoundaryPart & opt ) return FALSE; return FieldPvP::IsPart(wTileAtt); } BOOL BoundaryPart::RandomizePercent( Player* pAttacker, Player* pDeadPlayer ) { // µå¶ø È®·üÀ» üũÇÑ´Ù. PKOptionInfo & stPKOptionInfo = PKScriptParser::Instance()->GetPKOptionInfo(); int iLevelDiff = pDeadPlayer->GetLevel() - pAttacker->GetLevel(); BYTE DropRatio = 0; if( pDeadPlayer->GetChaoState().GetChaoState() == eCHAO_STATE_NORMAL ) { // Á×Àº³ÑÀÌ Å³·¯ÀÇ ¸®º¥Áö ´ë»óÀ̸é 50% È®·üÀ» Àû¿ë½ÃŲ´Ù. if( pAttacker->GetChaoState().FindBadFriend( pDeadPlayer->GetCharGuid() ) ) { DropRatio = stPKOptionInfo.m_BadFriendDropRatio; } else { //210924 BY RTX È¡Ïû·ÇºìÃû²»µô±£»¤ //Ö´ÐеôÂÊ=ȡС£¨50£¬µÈ¼¶²î+30£© //#ifdef _NA_007710_20141014_MODIFY_CHAO_STATE_NORMAL_DO_NOT_DROP_ITEM // ÀÏ¹Ý »óÅ¿¡¼­´Â PK´çÇØµµ ¸®º¥Áö ´ë»óÀÌ ¾Æ´Ò°æ¿ì ¾ÆÀÌÅÛÀ» µå¶øÇÏÁö ¾Ê´Â´Ù // return FALSE; //#else // _NA_007710_20141014_MODIFY_CHAO_STATE_NORMAL_DO_NOT_DROP_ITEM DropRatio = PKDropRatio( iLevelDiff ); //#endif // _NA_007710_20141014_MODIFY_CHAO_STATE_NORMAL_DO_NOT_DROP_ITEM } } else if( pDeadPlayer->GetChaoState().GetChaoState() == eCHAO_STATE_PREV_CHAO ) { DropRatio = stPKOptionInfo.m_PreChaoDropRatio; } else if( pDeadPlayer->GetChaoState().GetChaoState() == eCHAO_STATE_CHAO ) { DropRatio = stPKOptionInfo.m_ChaoDropRatio; } return random_percent(DropRatio); } // VOID BoundaryPart::KillPlayer( Player* pAttacker, Player* pDeadPlayer, BOOL bSummoned, DAMAGETYPE damage_value /*= 0*/ ) { //(lst1024)(080905)(2387)¼Òȯ¼ö¸¦ Á×ÀÏ °æ¿ì ÆÐ³ÎƼ ¾øÀ½. if( bSummoned ) return; if( HostilityRelationCheck(pAttacker,pDeadPlayer) ) { //_NA_008706_20160229_TEXTLOG_PK GAMELOG->LogAction_PK( ACT_HOSTILITY_GUILD_KILL, pAttacker, pDeadPlayer, damage_value ); GAMELOG->LogAction_PK( ACT_HOSTILITY_GUILD_DIE, pDeadPlayer, pAttacker, damage_value ); #ifdef _CN_006894_20130913_PK_ITEMDROP_ABOUTHOSTILITYRELATION if( ChkDropItem(pAttacker,pDeadPlayer) && RandomizePercent(pAttacker,pDeadPlayer) ) { SLOTIDX DropSlotIndex = SI_INVENTORY; PKOptionInfo& stPKOptionInfo = PKScriptParser::Instance()->GetPKOptionInfo(); if( random_percent(stPKOptionInfo.m_EquipDropRatio) ) DropSlotIndex = SI_EQUIPMENT; DropItem( pAttacker, pDeadPlayer, DropSlotIndex ); } #endif //_CN_006894_20130913_PK_ITEMDROP_ABOUTHOSTILITYRELATION } else { PKOptionInfo& stPKOptionInfo = PKScriptParser::Instance()->GetPKOptionInfo(); // º¸¶óµ¹ÀÌ »óÅÂ ÇØÁ¦ pAttacker->GetChaoState().EndBoradoriState(); // pTargetÀÌ ¸®º¥Áö ¸®½ºÆ®¿¡ µî·ÏµÈ À¯Àú¶ó¸é ¿ùµå¼­¹ö¿¡ »èÁ¦¸¦ ¿äûÇÑ´Ù. if( pAttacker->GetChaoState().FindBadFriend( pDeadPlayer->GetCharGuid() ) ) { pAttacker->GetChaoState().RequestRemoveBadFriend( pDeadPlayer->GetCharGuid() ); } #if !defined(_CHINA) //CHINA_PK_RULE - Áß±¹ ¹öÀüÀº »ç¿ëÇÏÁö ¾Ê´Â´Ù. // (lst1024)(090617) °ø°ÝÀÚ°¡ ÀϹÝÀ̰í, »ó´ë°¡ ÇÁ¸®Ä«¿ÀÀÏ °æ¿ì´Â Ä«¿À¼ºÇâÀ» ¿Ã¸®Áö¾Ê´Â´Ù. else if( pAttacker->GetChaoState().GetChaoState() == eCHAO_STATE_NORMAL && pDeadPlayer->GetChaoState().GetChaoState() == eCHAO_STATE_PREV_CHAO ) {} #endif // »ó´ë°¡ Ä«¿À, º¸¶óµ¹ÀÌ »óŶó¸é ³ªÀÇ Ä«¿À¼ºÇâÀº ¿Ã¸®Áö ¾Ê´Â´Ù. else if( pDeadPlayer->GetChaoState().GetChaoState() == eCHAO_STATE_CHAO || pDeadPlayer->GetChaoState().IsBoradori() ) {} // (lst1024)(090617)Ä«¿À·ê º¯°æ ÀÚÀ¯ ºÐÀï¿¡ ¼Òȯ¼ö·Î °ø°ÝÈÄ °æ°èÁö¿ªÀ¸·Î µµ¸Á, ¼Òȯ¼ö°¡ Ÿ Äɸ¯À» Á×ÀϽà ¿©±â·Î µé¾î¿Ã¼ö ÀÖÀ½. // 20·¦ ÀÌÇÏ´Â º¸È£ÇÊ¿ä. else if( pAttacker->GetLevel() < stPKOptionInfo.m_PKProtectLV ) {} else { // Ä«¿À¼ºÇâÀ» ¿Ã¸°´Ù. pAttacker->GetChaoState().UpChaoState(); // »ó´ë¹æÀÇ ¸®º¥Áö ¸®½ºÆ®¿¡ ÀÌ¹Ì µî·ÏµÈ À¯ÀúÀÎÁö üũ if( !pDeadPlayer->GetChaoState().FindBadFriend( pAttacker->GetCharGuid() ) ) { // ¸®º¥Áö ¸®½ºÆ®¿¡ µî·ÏÇÒ °ÍÀÎÁö ¹¯´Â´Ù. MSG_CG_CHAO_ASK_REVENGE_ADDITION_CMD cmdMsg; _tcsncpy( cmdMsg.m_ptszRevengeName, pAttacker->GetCharName(), MAX_CHARNAME_LENGTH ); cmdMsg.m_ptszRevengeName[MAX_CHARNAME_LENGTH] = '\0'; pDeadPlayer->SendPacket( &cmdMsg, sizeof(cmdMsg) ); // ¸®º¥Áö ´ë»óÀÇ À̸§À» ±â¾ïÇØ ³õ´Â´Ù. pDeadPlayer->GetChaoState().SetRevengeName( cmdMsg.m_ptszRevengeName ); } } // PK ·Î±×¸¦ ³²±ä´Ù. //_NA_008706_20160229_TEXTLOG_PK GAMELOG->LogAction_PK( ACT_PK_KILL, pAttacker, pDeadPlayer, damage_value ); GAMELOG->LogAction_PK( ACT_PK_DIE, pDeadPlayer, pAttacker, damage_value ); #ifdef _NA_007710_20141014_MODIFY_CHAO_STATE_NORMAL_DO_NOT_DROP_ITEM if( RandomizePercent(pAttacker,pDeadPlayer) && ChkDropItem(pAttacker,pDeadPlayer) ) #else // _NA_007710_20141014_MODIFY_CHAO_STATE_NORMAL_DO_NOT_DROP_ITEM if( ChkDropItem(pAttacker,pDeadPlayer) && RandomizePercent(pAttacker,pDeadPlayer) ) #endif // _NA_007710_20141014_MODIFY_CHAO_STATE_NORMAL_DO_NOT_DROP_ITEM { SLOTIDX DropSlotIndex = SI_INVENTORY; PKOptionInfo& stPKOptionInfo = PKScriptParser::Instance()->GetPKOptionInfo(); if( random_percent(stPKOptionInfo.m_EquipDropRatio) ) DropSlotIndex = SI_EQUIPMENT; DropItem( pAttacker, pDeadPlayer, DropSlotIndex ); } } } eUSER_RELATION_TYPE BoundaryPart::PvPRule( Player* pAttacker, Player *pTarget, OUT RC::eBATTLE_RESULT* pErrCode ) { *pErrCode = RC::RC_BATTLE_SUCCESS; if( pAttacker == pTarget ) return USER_RELATION_FRIEND; // 0. ÀÚ±âÀÚ½ÅÀÎÁöÀÌ¸é °ø°Ý(¹öÇÁ) °¡´É if( !ChkTarget(pTarget,pErrCode) ) return USER_RELATION_NEUTRALIST; // 1. ¹üÀ§ °ø°Ý½Ã CanPVP¸¦ ÅëÇÏÁö ¾ÊÀ¸¹Ç·Î üũ ÇÊ¿ä(ŸÀϼӼº). GUILDGUID AttkGld = pAttacker->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; GUILDGUID DefGld = pTarget->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; if( AttkGld != 0 && AttkGld == DefGld ) { return USER_RELATION_FRIEND; // 2. ±æµå¿øÀÌ¸é ¾Æ±ºÀÌ´Ù. } //(lst1024)(080901) ±æµå °ü°è µ¿¸ÍÀÏ °æ¿ì °­Á¦°ø°Ý ºÒ°¡. if (GuildSmallContentEntry::RelationSystem::GetRelationType(AttkGld, DefGld) == eGUILD_RELATION_ALLIENCE) return USER_RELATION_FRIEND; // 3. ±æµå °ü°è µ¿¸ÍÀÌ¸é ¾Æ±º. if (GuildSmallContentEntry::RelationSystem::IsHostilityRelation(AttkGld, DefGld)) return USER_RELATION_ENEMY; // 4. ±æµå °ü°è Àû´ë¸é Àû±º. if( pAttacker->GetPartyState() == pTarget->GetPartyState() ) { return USER_RELATION_FRIEND; // 5. ÆÄƼ¿ø ÀÌ¸é ¾Æ±º. } #if defined(_CHINA) //CHINA_PK_RULE - Áß±¹ º¸¶óµ¹ÀÌ ÀÚµ¿ °­Á¦°ø°Ý »èÁ¦. if( pTarget->GetChaoState().IsChaoState() ) #else if( pTarget->GetChaoState().IsBoradori() || pTarget->GetChaoState().IsChaoState() ) #endif return USER_RELATION_ENEMY; // 6. º¸¶óµ¹ÀÌ, Ä«¿À»óÅÂÀ̸é Àû±º. if( pAttacker->IsForceAttack() ) //.// °­Á¦ °ø°Ý·ê { if( IsOneSideHostility(pAttacker,pTarget) ) return USER_RELATION_ENEMY; // 7. PK·ê º¸´Ù ±æµå·êÀÌ ¿ì¼± ÇϹǷÎ, ÀϹæÀû´ë½Ã¿¡µµ ´ººñ °ø°ÝÀÌ °¡´ÉÇÏ´Ù. PKOptionInfo& stPKOptionInfo = PKScriptParser::Instance()->GetPKOptionInfo(); if( pTarget->GetLevel() < stPKOptionInfo.m_PKProtectLV ) { *pErrCode = RC::RC_BATTLE_TARGET_LEVEL_IS_LOW; return USER_RELATION_NEUTRALIST; // 8. ÇǰÝÀÚ ·¹º§ üũ } if( pAttacker->GetLevel() < stPKOptionInfo.m_PKAllowableLV ) { *pErrCode = RC::RC_BATTLE_ATTACKER_LEVEL_IS_LOW; return USER_RELATION_NEUTRALIST; // 9. °ø°ÝÀÚ ·¹º§ üũ } return USER_RELATION_ENEMY; // 10. ÀÏ¹Ý Ä«¿À } return USER_RELATION_FRIEND; // 11. ¿¹¿Ü¿¡ ºñÇØ´ç ÇÏ´Â À¯Àú ¾Æ±º } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// //Áö¿ªÁ¡·ÉÀü·ê BOOL DominationPart::IsPart( const WORD wTileAtt ) { static const BYTE opt = PKScriptParser::Instance()->GetPKOptionInfo().m_IgnorePKTile; if( PKOptionInfo::ignore_Domination & opt ) return FALSE; return FieldPvP::IsPart(wTileAtt); } VOID DominationPart::KillPlayer( Player* pAttacker, Player* pDeadPlayer, BOOL bSummoned, DAMAGETYPE damage_value /*= 0*/ ) { if( !bSummoned ) { //_NA_008706_20160229_TEXTLOG_PK // PK ·Î±×¸¦ ³²±ä´Ù. GAMELOG->LogAction_PK( ACT_DOMINATION_KILL, pAttacker, pDeadPlayer, damage_value ); GAMELOG->LogAction_PK( ACT_DOMINATION_DIE, pDeadPlayer, pAttacker, damage_value ); } } eUSER_RELATION_TYPE DominationPart::PvPRule( Player* pAttacker, Player *pTarget, OUT RC::eBATTLE_RESULT* pErrCode ) { *pErrCode = RC::RC_BATTLE_SUCCESS; if( pAttacker == pTarget ) return USER_RELATION_FRIEND; // 0. ÀÚ±âÀÚ½ÅÀÎÁöÀÌ¸é °ø°Ý(¹öÇÁ) °¡´É if( !ChkTarget(pTarget,pErrCode) ) return USER_RELATION_NEUTRALIST; // 1. ¹üÀ§ °ø°Ý½Ã CanPVP¸¦ ÅëÇÏÁö ¾ÊÀ¸¹Ç·Î üũ ÇÊ¿ä(ŸÀϼӼº). GUILDGUID AttkGld = pAttacker->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; GUILDGUID DefGld = pTarget->GetPlayerOwner()->GetCharInfo()->m_GuildGuid; if (AttkGld == 0 || DefGld == 0) return USER_RELATION_ENEMY; else if (AttkGld == DefGld ) return USER_RELATION_FRIEND; // 3. ±æµå¿øÀÌ¸é ¾Æ±ºÀÌ´Ù. #ifdef _NA_006826_20130722_DOMINATION_RENEWAL // 4. °ø°ÝÀÚ¿Í ÇǰÝÀÚÀÇ °ü°è°¡ Àû´ë¶óµµ °¢ÀÚÀÇ ±æµå°¡ ¼ö¼ºÃø°ú µ¿¸ÍÀÏ °æ¿ì.. ¾Æ±ºÀÌ´Ù. GameField* field = pAttacker->GetField(); if (field == NULL) { SUNLOG(eFULL_LOG, "["__FUNCTION__"]Not found field"); return USER_RELATION_NEUTRALIST; } MAPCODE map_code = \ DominationInfoParser::Instance()->GetDominationFieldCode(field->GetFieldCode()); if (map_code == 0) { SUNLOG(eFULL_LOG, "["__FUNCTION__"]Not found mapcode"); return USER_RELATION_NEUTRALIST; } const DOMINATION_INFO* domination_info = GameDominationManager::Instance()->GetDominationInfo(map_code); if (domination_info == NULL) { SUNLOG(eFULL_LOG, "["__FUNCTION__"]Not found domination info"); return USER_RELATION_NEUTRALIST; } const GUILDGUID defense_guild_guid = domination_info->m_inGuildInfo.m_GuildGuid; GameGuild* const defense_game_guild = g_GameGuildManager.FindGuild(defense_guild_guid); // ¼ö¼º ±æµå°¡ ÀÖÀ» °æ¿ì.. if (defense_game_guild) { if (AttkGld == defense_guild_guid || DefGld == defense_guild_guid) { GameGuild* const attacker_game_guild = g_GameGuildManager.FindGuild(AttkGld); GuildRelationSystem::GuildRelationEntry* attacker_guild_entry = \ attacker_game_guild->GetRelationEntry(); eGUILD_RELATION relation = attacker_guild_entry->GetRelationType(DefGld); if (relation == eGUILD_RELATION_ALLIENCE) { return USER_RELATION_FRIEND; } } GuildRelationSystem::GuildRelationEntry* defense_guild_entry = \ defense_game_guild->GetRelationEntry(); eGUILD_RELATION attacker_relation = defense_guild_entry->GetRelationType(AttkGld); eGUILD_RELATION target_relation = defense_guild_entry->GetRelationType(DefGld); if (attacker_relation == eGUILD_RELATION_ALLIENCE && target_relation == eGUILD_RELATION_ALLIENCE) { return USER_RELATION_FRIEND; } else if (attacker_relation != eGUILD_RELATION_ALLIENCE && target_relation != eGUILD_RELATION_ALLIENCE) { GameGuild* const attacker_game_guild = g_GameGuildManager.FindGuild(AttkGld); GuildRelationSystem::GuildRelationEntry* attacker_guild_entry = \ attacker_game_guild->GetRelationEntry(); eGUILD_RELATION relation = attacker_guild_entry->GetRelationType(DefGld); if (relation == eGUILD_RELATION_ALLIENCE) { return USER_RELATION_FRIEND; } } } // ¼ö¼º ±æµå°¡ ¾øÀ» °æ¿ì.. (ºó¼º) else { GameGuild* const attacker_game_guild = g_GameGuildManager.FindGuild(AttkGld); GuildRelationSystem::GuildRelationEntry* attacker_guild_entry = \ attacker_game_guild->GetRelationEntry(); eGUILD_RELATION relation = attacker_guild_entry->GetRelationType(DefGld); if (relation == eGUILD_RELATION_ALLIENCE) { return USER_RELATION_FRIEND; } } #endif // _NA_006826_20130722_DOMINATION_RENEWAL return USER_RELATION_ENEMY; } ////////////////////////////////////////////////////////////////////////// //================================================================================================== BOOL SafetyPart::IsPart(const WORD wTileAtt) { static const BYTE opt = PKScriptParser::Instance()->GetPKOptionInfo().m_IgnorePKTile; // (NOTE) ¾îÂ÷ÇÇ ¿É¼Ç ÀÚü°¡ PvP¹æÁöÀ̹ǷΠ·ÎÁ÷Àº µ¿ÀÏÇÏ°Ô false¹ÝȯÀ¸·Î... if(PKOptionInfo::ignore_SafetyPart & opt) return false; // Çϱ⠳»¿ëÀº Á» ´õ °ËÁõ ÈÄ 'false'·Î ¼öÁ¤ÇÒ ÇÊ¿ä ÀÖ´Ù. return FieldPvP::IsPart(wTileAtt); } VOID SafetyPart::KillPlayer(Player* pAttacker, Player* pDeadPlayer, BOOL bSummoned, BOOL is_oneshot) { SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"]|ÐÅÏ¢=violation PvP rule|Attacker=%s|Dead player=%s|Option=%d|", pAttacker->GetCharName(), pDeadPlayer->GetCharName(), !!bSummoned); } eUSER_RELATION_TYPE SafetyPart::PvPRule(Player* pAttacker, Player* pTarget, OUT RC::eBATTLE_RESULT* pErrCode) { // (NOTE) NormalPart¿Í À¯»çÇÏ´Ù. *pErrCode = RC::RC_BATTLE_SUCCESS; // 0. ÀÚ±âÀÚ½ÅÀÎÁöÀÌ¸é °ø°Ý(¹öÇÁ) °¡´É if(pAttacker == pTarget) return USER_RELATION_FRIEND; // 1. ÆÄƼ¿ø °ø°Ý ºÒ°¡ if(pAttacker->GetPartyState() == pTarget->GetPartyState()) return USER_RELATION_FRIEND; GUILDGUID guild_of_attacker = pAttacker->GetCharInfo()->m_GuildGuid; if(guild_of_attacker != 0) { GUILDGUID guild_of_target = pTarget->GetCharInfo()->m_GuildGuid; if(guild_of_target != 0) { if(guild_of_attacker == guild_of_target) return USER_RELATION_FRIEND; // (NOTE) ÀÌ°Ç ¹«¸®ÇÏ°Ô °Ë»çÇÏÁö ¾Êµµ·Ï ÇÑ´Ù. //if(GetRelationType(guild_of_attacker, guild_of_target) == eGUILD_RELATION_ALLIENCE) // return USER_RELATION_FRIEND; } } // (WARNING) Á» ´õ ·ê¿¡ ´ëÇÑ °í·Á¸¦ ÇÒ Çʿ䰡 ÀÖ´Ù. return USER_RELATION_NEUTRALIST; }