Files
Sun1602/Server/GameServer/QuestCondition_Concrete.cpp
T
2022-10-26 12:25:11 +08:00

688 lines
21 KiB
C++

#include "stdafx.h"
#include "QuestCondition_Concrete.h"
#include <Global.h>
#include <QuestManager.h>
#include <Quest.h>
#include <MapInfoParser.h>
#include "Player.h"
#include "ChaoState.h"
#include "ItemManager.h"
#include "MissionManager.h"
#include "WarehouseSlotContainer.h"
#include "GameField.h"
#include "MovingPlanner.h"
#include "ExtraNPCManager.h"
#include "HonorSystem/HonorSystem.h" //_NA_003027_20111013_HONOR_SYSTEM
#include "ResultCode.h"
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_REPEAT )
RC::eQUEST_RESULT QUEST_CONDITION_REPEAT::CanAccept( void * pvParam )
{
// IsSatisfy에서 해주긴 하지만 그래도;;
if( 0 == GetInfo()->GetMaxRepeatNum() )
{
return RC::RC_QUEST_SUCCESS;
}
return GetInfo()->IsSatisfy( GetQuest()->GetRepeatNum() );
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_CHARLV )
RC::eQUEST_RESULT QUEST_CONDITION_CHARLV::CanAccept( void * pvParam )
{
Player * pPlayer = (Player *)pvParam;
return GetInfo()->IsSatisfy(pPlayer->GetLevel());
}
RC::eQUEST_RESULT QUEST_CONDITION_CHARLV::CanComplete( void * pvParam )
{
return CanAccept(pvParam);
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_CHARCLASS )
RC::eQUEST_RESULT QUEST_CONDITION_CHARCLASS::CanAccept( void * pvParam )
{
Player * pPlayer = (Player *)pvParam;
return GetInfo()->IsSatisfy(CharTypeToClassType(pPlayer->GetCharType()));
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_QUEST )
RC::eQUEST_RESULT QUEST_CONDITION_QUEST::CanAccept( void * pvParam )
{
if( GetInfo()->IsNecessaryQuest() ) //< 퀘스트가 필요한가
{
if( GetInfo()->IsProgrQuest() ) //< 진행중인 퀘스트 검사
{
if( GetInfo()->GetOperator() == QOP_AND )
{
for( BYTE i = 0 ; i < GetInfo()->GetQuestArrayCount() ; ++i )
{
QCODE qCode = GetInfo()->GetQuestCode(i);
if( 0 == qCode ) continue;
if( NULL == GetManager()->FindQuest( qCode ) )
{
return RC::RC_QUEST_NOT_EXIST_NECESSARY_QUEST;
}
}
return RC::RC_QUEST_SUCCESS;
}
else
{
for( BYTE i = 0 ; i < GetInfo()->GetQuestArrayCount() ; ++i )
{
QCODE qCode = GetInfo()->GetQuestCode(i);
if( 0 == qCode ) continue;
if( NULL != GetManager()->FindQuest( qCode ) )
{
return RC::RC_QUEST_SUCCESS;
}
}
return RC::RC_QUEST_NOT_EXIST_NECESSARY_QUEST;
}
}
else //< 완료된 퀘스트 검사
{
if( GetInfo()->GetOperator() == QOP_AND )
{
for( BYTE i = 0 ; i < GetInfo()->GetQuestArrayCount() ; ++i )
{
QCODE qCode = GetInfo()->GetQuestCode(i);
if( 0 == qCode ) continue;
QUESTPART_COMPL * pQuest = GetManager()->FindComplQuest( qCode );
if( NULL == pQuest || pQuest->m_Num < GetInfo()->GetQuestNum(i) )
{
return RC::RC_QUEST_NOT_EXIST_NECESSARY_QUEST;
}
}
return RC::RC_QUEST_SUCCESS;
}
else
{
for( BYTE i = 0 ; i < GetInfo()->GetQuestArrayCount() ; ++i )
{
QCODE qCode = GetInfo()->GetQuestCode(i);
if( 0 == qCode ) continue;
QUESTPART_COMPL * pQuest = GetManager()->FindComplQuest( qCode );
if( NULL != pQuest && pQuest->m_Num >= GetInfo()->GetQuestNum(i) )
{
return RC::RC_QUEST_SUCCESS;
}
}
return RC::RC_QUEST_NOT_EXIST_NECESSARY_QUEST;
}
}
}
else
{
// 없어야 한다
if( GetInfo()->IsProgrQuest() ) //< 진행중인 퀘스트 검사
{
if( GetInfo()->GetOperator() == QOP_AND )
{
for( BYTE i = 0 ; i < GetInfo()->GetQuestArrayCount() ; ++i )
{
QCODE qCode = GetInfo()->GetQuestCode(i);
if( 0 == qCode ) continue;
if( NULL != GetManager()->FindQuest( qCode ) )
{
return RC::RC_QUEST_MUST_NOT_EXIST_QUEST;
}
}
return RC::RC_QUEST_SUCCESS;
}
else
{
for( BYTE i = 0 ; i < GetInfo()->GetQuestArrayCount() ; ++i )
{
QCODE qCode = GetInfo()->GetQuestCode(i);
if( 0 == qCode ) continue;
if( NULL == GetManager()->FindQuest( qCode ) )
{
return RC::RC_QUEST_SUCCESS;
}
}
return RC::RC_QUEST_MUST_NOT_EXIST_QUEST;
}
}
else //< 완료된 퀘스트 검사
{
if( GetInfo()->GetOperator() == QOP_AND )
{
for( BYTE i = 0 ; i < GetInfo()->GetQuestArrayCount() ; ++i )
{
QCODE qCode = GetInfo()->GetQuestCode(i);
if( 0 == qCode ) continue;
QUESTPART_COMPL * pQuest = GetManager()->FindComplQuest( qCode );
if( NULL != pQuest || pQuest->m_Num < GetInfo()->GetQuestNum(i) )
{
return RC::RC_QUEST_MUST_NOT_EXIST_QUEST;
}
}
return RC::RC_QUEST_SUCCESS;
}
else
{
for( BYTE i = 0 ; i < GetInfo()->GetQuestArrayCount() ; ++i )
{
QCODE qCode = GetInfo()->GetQuestCode(i);
if( 0 == qCode ) continue;
QUESTPART_COMPL * pQuest = GetManager()->FindComplQuest( qCode );
if( NULL == pQuest && pQuest->m_Num >= GetInfo()->GetQuestNum(i) )
{
return RC::RC_QUEST_SUCCESS;
}
}
return RC::RC_QUEST_MUST_NOT_EXIST_QUEST;
}
}
}
//return GetInfo()->IsSatisfy(pPlayer->GetLevel());
}
RC::eQUEST_RESULT QUEST_CONDITION_QUEST::CanComplete( void * pvParam )
{
return CanAccept(pvParam);
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_ITEM )
RC::eQUEST_RESULT QUEST_CONDITION_ITEM::CanAccept( void * pvParam )
{
Player * pPlayer = (Player *)pvParam;
if( GetInfo()->IsNecessaryItem() ) //< 아이템이 있어야하는가
{
// 다른 종류의 아이템이어야 한다!
// 같은 종류가 다른 배열에 있는 가정은 하지 않는다 ; 당연 체크도 하지 않는다.
for( BYTE i = 0 ; i < GetInfo()->GetItemArrayCount() ; ++i )
{
int cur_exist_item_num = pPlayer->GetItemManager()->ExistItem( SI_INVENTORY, GetInfo()->GetItemCode(i), GetInfo()->GetItemNum(i) );
if( GetInfo()->GetItemNum(i) != cur_exist_item_num )
{
SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"] Item QuestComplete Failed! [QCode:%d][ItemCode:%d][Cur:%d][Goal:%d]",
GetQuest()->GetQuestCode(), GetInfo()->GetItemCode(i), cur_exist_item_num, GetInfo()->GetItemNum(i));
return RC::RC_QUEST_NOT_EXIST_NECESSARY_ITEM;
}
}
return RC::RC_QUEST_SUCCESS;
}
else
{
for( BYTE i = 0 ; i < GetInfo()->GetItemArrayCount() ; ++i )
{
// 아이템이 없어야 한다
if( GetInfo()->GetItemNum(i) != pPlayer->GetItemManager()->ExistItem( SI_INVENTORY, GetInfo()->GetItemCode(i), GetInfo()->GetItemNum(i) ) )
{
return RC::RC_QUEST_MUST_NOT_EXIST_ITEM;
}
}
return RC::RC_QUEST_SUCCESS;
}
}
RC::eQUEST_RESULT QUEST_CONDITION_ITEM::CanComplete( void * pvParam )
{
return CanAccept(pvParam);
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_CLASSITEM )
RC::eQUEST_RESULT QUEST_CONDITION_CLASSITEM::CanAccept( void * pvParam )
{
// 제한된 클래스의 아이템을 가지면 안됨
// 아직은 사용되지 않음
SUNLOG( eCRITICAL_LOG, "[QUEST_CONDITION_CLASSITEM]사용되지 않는 퀘스트 조건이 사용되었다.\n" );
/*
Player * pPlayer = (Player *)pvParam;
SCItemSlotContainer * pContainer = pPlayer->GetItemManager()->GetItemSlotContainer(SI_INVENTORY);
for( POSTYPE pos = 0 ; pos < pContainer->GetMaxSlotNum() ; ++pos )
{
if( !pContainer->IsEmpty(pos) )
{
SCItemSlot & slot = (SCItemSlot &)pContainer->GetSlot(pos);
if( 0 != slot.GetItemInfo()->m_wEqClass1 )
{
if( m_pPlayer->GetCharType() != eCHAR_BERSERKER ) return FALSE;
}
if( 0 != slot.GetItemInfo()->m_wEqClass2 )
{
if( m_pPlayer->GetCharType() != eCHAR_DRAGON ) return FALSE;
}
if( 0 != slot.GetItemInfo()->m_wEqClass3 )
{
if( m_pPlayer->GetCharType() != eCHAR_SHADOW ) return FALSE;
}
if( 0 != slot.GetItemInfo()->m_wEqClass4 )
{
if( m_pPlayer->GetCharType() != eCHAR_VALKYRIE ) return FALSE;
}
if( 0 != slot.GetItemInfo()->m_wEqClass5 )
{
if( m_pPlayer->GetCharType() != eCHAR_ELEMENTALIST ) return FALSE;
}
}
}
*/
return RC::RC_QUEST_FAILED;
}
RC::eQUEST_RESULT QUEST_CONDITION_CLASSITEM::CanComplete( void * pvParam )
{
return CanAccept(pvParam);
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_MONEY )
RC::eQUEST_RESULT QUEST_CONDITION_MONEY::CanAccept( void * pvParam )
{
Player * pPlayer = (Player *)pvParam;
return GetInfo()->IsSatisfy( pPlayer->GetMoney() );
}
RC::eQUEST_RESULT QUEST_CONDITION_MONEY::CanComplete( void * pvParam )
{
return CanAccept(pvParam);
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_KILLMONSTER )
void QUEST_CONDITION_KILLMONSTER::Init( const QUESTPART_PROGR * pStream )
{
Clear();
if( pStream )
{
for( BYTE i=0;i<QUEST_CONDITION_KILLMONSTER_INFO::_MAX_CHECK_NUM;++i)
{
SetCurMonsterNum(i, pStream->m_KCount[i]);
}
}
}
void QUEST_CONDITION_KILLMONSTER::Clear()
{
for( BYTE i=0;i<QUEST_CONDITION_KILLMONSTER_INFO::_MAX_CHECK_NUM;++i)
{
SetCurMonsterNum(i,0);
}
}
void QUEST_CONDITION_KILLMONSTER::CopyOut( QUESTPART_PROGR & OUT rStream )
{
for( BYTE i=0;i<QUEST_CONDITION_KILLMONSTER_INFO::_MAX_CHECK_NUM;++i)
{
rStream.m_KCount[i] = GetCurMonsterNum(i);
}
}
RC::eQUEST_RESULT QUEST_CONDITION_KILLMONSTER::CanComplete( void * pvParam )
{
for( BYTE i=0;i<QUEST_CONDITION_KILLMONSTER_INFO::_MAX_CHECK_NUM;++i)
{
if( GetCurMonsterNum(i) < GetInfo()->GetMonsterNum(i) )
{
SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"] KillMonster QuestComplete Failed! [Cur:%d][Goal:%d",
GetCurMonsterNum(i), GetInfo()->GetMonsterNum(i));
return RC::RC_QUEST_NOT_KILL_NECESSARY_MONSTER;
}
}
return RC::RC_QUEST_SUCCESS;
}
BOOL QUEST_CONDITION_KILLMONSTER::Event( eQUEST_EVENT evt, QUEST_MSG * pMsg )
{
if( evt == QUEST_EVENT_MONSTERKILL )
{
// QUEST_CONDITION_KILLMONSTER_INFO 에 동일한 몬스터 코드가 다른 배열인덱스에 존재하지 않는다는 가정
QUEST_MONSTER_KILL_MSG * pmsg = (QUEST_MONSTER_KILL_MSG *)pMsg;
for( BYTE i=0;i<QUEST_CONDITION_KILLMONSTER_INFO::_MAX_CHECK_NUM;++i)
{
if( GetInfo()->GetMonsterCode(i) == pmsg->m_MonsterCode &&
GetCurMonsterNum(i) < GetInfo()->GetMonsterNum(i) )
{
SetCurMonsterNum( i, GetCurMonsterNum(i)+1 ); //pmsg->m_MonsterNum );
return TRUE;
}
}
}
else if(evt == QUEST_EVENT_MONSTERKILL_GRADE)
{
QUEST_MONSTER_KILL_GRADE_MSG * pmsg = (QUEST_MONSTER_KILL_GRADE_MSG *)pMsg;
QUEST_CONDITION_KILLMONSTER_INFO* pInfo = GetInfo();
for( BYTE i=0;i<QUEST_CONDITION_KILLMONSTER_INFO::_MAX_CHECK_NUM;++i)
{
const BYTE QuestMonsterGrade = pInfo->GetMonsterGrade(i);
const WORD QuestMonsterLevel = pInfo->GetMonsterLevel(i);
const BYTE QuestMonsterNum = pInfo->GetMonsterNum(i);
if( QuestMonsterGrade == pmsg->m_MonsterGrade &&
QuestMonsterLevel <= pmsg->m_MonsterLevel &&
QuestMonsterNum > m_pCurMonsterNum[i] )
{
++m_pCurMonsterNum[i];
#ifdef _NA_006644_20130419_BUG_QUEST_KILLMONSTER
#else
// 클라에서 필요한 퀘스트정보를 준다.
pmsg->m_MonsterLevel = QuestMonsterLevel;
#endif //_NA_006644_20130419_BUG_QUEST_KILLMONSTER
return TRUE;
}
}
}
return FALSE;
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_MISSION )
RC::eQUEST_RESULT QUEST_CONDITION_MISSION::CanAccept( void * pvParam )
{
Player * pPlayer = (Player *)pvParam;
for( BYTE i = 0 ; i < QUEST_CONDITION_MISSION_INFO::_MAX_CHECK_NUM ; ++i )
{
if( 0 == GetInfo()->GetMissionCode(i) ) continue;
ASSERT(SAFE_NUMERIC_TYPECAST( WORD, GetInfo()->GetMissionCode(i), BYTE ));
WORD point = pPlayer->GetMissionManager()->GetMissionPoint((BYTE)GetInfo()->GetMissionCode(i));
if( point == 0 || point < GetInfo()->GetMissionNum(i) )
{
return RC::RC_QUEST_NOT_LESS_MISSION_POINT;
}
}
return RC::RC_QUEST_SUCCESS;
}
RC::eQUEST_RESULT QUEST_CONDITION_MISSION::CanComplete( void * pvParam )
{
return CanAccept(pvParam);
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_AREA )
void QUEST_CONDITION_AREA::Init( const QUESTPART_PROGR * pStream )
{
Clear();
if( NULL == pStream )
return;
SetCurSearchedArea(Area1, pStream->m_SearchedArea1);
SetCurSearchedArea(Area2, pStream->m_SearchedArea2);
SetCurSearchedArea(Area3, pStream->m_SearchedArea3);
}
void QUEST_CONDITION_AREA::Clear()
{
for( BYTE i=0;i<QUEST_CONDITION_AREA_INFO::_MAX_CHECK_NUM;++i)
SetCurSearchedArea(i,UNKNOWN_AREA);
}
void QUEST_CONDITION_AREA::CopyOut( QUESTPART_PROGR & OUT rStream )
{
rStream.m_SearchedArea1 = GetCurSearchedArea(Area1);
rStream.m_SearchedArea2 = GetCurSearchedArea(Area2);
rStream.m_SearchedArea3 = GetCurSearchedArea(Area3);
}
BOOL QUEST_CONDITION_AREA::Event( eQUEST_EVENT evt, QUEST_MSG * pMsg )
{
if( evt == QUEST_EVENT_AREA )
{
QUEST_AREA_MSG * pmsg = (QUEST_AREA_MSG *)pMsg;
for( BYTE i=0;i<QUEST_CONDITION_AREA_INFO::_MAX_CHECK_NUM;++i)
{
if( GetInfo()->GetAreaID(i) == pmsg->m_AreaID )
{
SetCurSearchedArea( i, SEARCHED_AREA );
return TRUE;
}
}
}
return FALSE;
}
RC::eQUEST_RESULT QUEST_CONDITION_AREA::CanComplete( void * pvParam )
{
Player * pPlayer = (Player *)pvParam;
GameField* pField = pPlayer->GetField();
if( !pField )
{
return RC::RC_QUEST_NOT_FIELD;
}
for( BYTE i=0;i<QUEST_CONDITION_AREA_INFO::_MAX_CHECK_NUM;++i)
{
if( 0 != GetInfo()->GetAreaID(i) &&
UNKNOWN_AREA == GetCurSearchedArea(i) )
{
return RC::RC_QUEST_NOT_CRASH_AREA;
}
}
return RC::RC_QUEST_SUCCESS;
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_ITEM_SPACE )
RC::eQUEST_RESULT QUEST_CONDITION_ITEM_SPACE::CanAccept( void * pvParam )
{
Player * pPlayer = (Player *)pvParam;
static JUST_INVENTORY_TOTAL_INFO s_JustTotalInfo;
/*
if( GetInfo()->GetItemArrayCount() == 0 )
return TRUE;
RC::eITEM_RESULT rt = pPlayer->GetItemManager()->ObtainAllKindOfItem(
GetInfo()->GetItemArrayCount(), GetInfo()->GetItemCodePtr(), GetInfo()->GetItemNumPtr(), &s_JustTotalInfo );
if( rt != RC::RC_ITEM_SUCCESS )
{
return FALSE;
}
// 성공하면 삭제
pPlayer->GetItemManager()->DeleteFromTotalInfo( &s_JustTotalInfo );
return TRUE;
*/
SCItemSlotContainer * pInven = pPlayer->GetItemManager()->GetItemSlotContainer(SI_INVENTORY);
if(pInven->GetSlotNum() + GetInfo()->GetItemArrayCount() > pInven->GetMaxSlotNum())
{
return RC::RC_QUEST_NOT_EMPTY_ITEM_SPACE;
}
else
{
return RC::RC_QUEST_SUCCESS;
}
}
RC::eQUEST_RESULT QUEST_CONDITION_ITEM_SPACE::CanComplete( void * pvParam )
{
return CanAccept(pvParam);
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
__IMPL_CUSTOMPOOL_PTR( QUEST_CONDITION_CHAO )
RC::eQUEST_RESULT QUEST_CONDITION_CHAO::CanAccept( void * pvParam )
{
Player * pPlayer = (Player *)pvParam;
return GetInfo()->IsSatisfy(pPlayer->GetChaoState().GetChaoState());
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
//{__NA1279_1281_090209_TIMELINE_QUEST_BASED_MISSION__
__IMPL_CUSTOMPOOL_PTR(QUEST_CONDITION_CREATE_PORTAL)
// 은파씨 저 일욜 휴무라 빌드 시 필요 한 부분입니다.
// 출근 하신다면 꼭 좀 작업 부탁드려요.
// 전화 하니까 안받다가 끊어버리시네 -_- 09.03.21(SAT)
// <- waverix왈... 전화기 외투 속에 있고, 외투는 다른 방 옷장에 있습니다. (보통...-.- 오해는 마시길.)
#define ERROR_RETURN_FOR_QUEST_CONDITION(return_type) (return_type)
RC::eQUEST_RESULT QUEST_CONDITION_CREATE_PORTAL::CanAccept(void* pvParam)
{
RC::eQUEST_RESULT ret = RC::RC_QUEST_SUCCESS;
Player* pPlayer = (Player*)pvParam;
if(pPlayer == 0)
return ERROR_RETURN_FOR_QUEST_CONDITION(RC::RC_QUEST_NOT_PLAYER);
GameField* pField = pPlayer->GetField();
if(pField == 0)
return ERROR_RETURN_FOR_QUEST_CONDITION(RC::RC_QUEST_NOT_FIELD);
//일단 아래 제약 조건은 다른 곳에서 가져오긴 했는데... NULL이어도 되나? 오히려 위험 코드.
Quest* pQuest = GetQuest();
if(pQuest == 0)
return ERROR_RETURN_FOR_QUEST_CONDITION(RC::RC_QUEST_EMPTY);
QuestInfo* pQuestInfo = pQuest->GetQuestInfo();
DWORD startNpcCode = pQuestInfo->GetNPCCode_Start();
if(!g_ExtraNPCManager.IsLengthCanUseNPC(startNpcCode, pPlayer))
return ERROR_RETURN_FOR_QUEST_CONDITION(RC::RC_QUEST_DISTANCE_DIFF_TOO_LONG);
QUEST_CONDITION_CREATE_PORTAL_INFO* pInfo = GetInfo();
MAPCODE mapCode = pInfo->GetMapPortalCode();
if(mapCode == 0)
return ERROR_RETURN_FOR_QUEST_CONDITION(RC::RC_QUEST_NOT_CRASH_AREA);
const sMAPINFO* pMapInfo = MapInfoParser::Instance()->FindMapInfo(mapCode);
if(pMapInfo == 0)
{
SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"] Can't Find MapPortalCode %u\n", mapCode);
return ERROR_RETURN_FOR_QUEST_CONDITION(RC::RC_QUEST_NOT_CRASH_AREA);
}
const eZONETYPE zoneType = (eZONETYPE)pMapInfo->byMKind;
const BOOLEAN acceptableMap = zoneType == eZONETYPE_MISSION ||
zoneType == eZONETYPE_INSTANCE;
if(acceptableMap == FALSE)
return ERROR_RETURN_FOR_QUEST_CONDITION(RC::RC_QUEST_NOT_CRASH_AREA);
// Register Portal Constraints { NPC 기준 범위... 제약, 기본 타임아웃도 존재하는데... }
// A<->G 계열 Zone Control이 요구된다.
nsAI::MovingPlanner* pMovingPlanner = pField->GetMovingPlanner();
const WzVector* pCurPos = pPlayer->GetPosPtr();
WORD attributes;
INT iTile = pMovingPlanner->GetAllowTileToStand(*pCurPos, NULL, -1.0f, 100.0f, &attributes,
PTA_NO_WALK | PTA_PLAYER_FALLDOWN_TILE);
if(iTile < 0)
return ERROR_RETURN_FOR_QUEST_CONDITION(RC::RC_QUEST_NOT_CRASH_AREA);
return ERROR_RETURN_FOR_QUEST_CONDITION(RC::RC_QUEST_SUCCESS);
}
//}__NA1279_1281_090209_TIMELINE_QUEST_BASED_MISSION__
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
#ifdef _NA_003027_20111013_HONOR_SYSTEM
RC::eQUEST_RESULT QUEST_CONDITION_DAILY_QUEST::CanAccept( void * pvParam )
{
Player* player = (Player*)pvParam;
if(player == 0)
return RC::RC_QUEST_NOT_PLAYER;
Quest* quest = GetQuest();
if( !quest->GetQuestInfo()->IsDailyQuest() )
return RC::RC_QUEST_NOT_DAILY;
QCODE code = quest->GetQuestCode();
WORD group = quest->GetQuestInfo()->GetSquadCode();
QuestManager* quest_manager = quest->GetQuestManager();
if( group <= 0 ) {
return RC::RC_QUEST_NOT_TODAY;
}
if( !HonorSystem::Instance()->IsTodayQuest(group, code) )
{
SUNLOG(eCRITICAL_LOG, "["__FUNCTION__"] Daily Quest Error! [Group:%d][ClientQuestCode:%d]", group, code);
return RC::RC_QUEST_NOT_TODAY;
}
if (quest->GetQuestInfo()->GetDailyQuest() == DAILYQUEST_GUILD &&
player->GetGuildGuid() == INVALID_GUILDGUID)
return RC::RC_QUEST_FAILED;
return quest_manager->CanDoAcceptDailyQuest(code, player);
}
#endif //_NA_003027_20111013_HONOR_SYSTEM
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
#ifdef _NA_006607_20130402_ADD_QUESTTYPE
void QUEST_CONDITION_MISSION_CLEAR::Init(const QUESTPART_PROGR *pStream)
{
Clear();
if(pStream)
{
for( BYTE i=0;i<QUEST_CONDITION_MISSION_CLEAR_INFO::_MAX_CHECK_NUM; ++i)
{
SetCurClearNum(i, pStream->mission_number[i]);
}
}
}
void QUEST_CONDITION_MISSION_CLEAR::Clear()
{
for( BYTE i=0;i<QUEST_CONDITION_MISSION_CLEAR_INFO::_MAX_CHECK_NUM;++i)
{
SetCurClearNum(i,0);
}
}
void QUEST_CONDITION_MISSION_CLEAR::CopyOut( QUESTPART_PROGR & OUT rStream )
{
for( BYTE i=0;i<QUEST_CONDITION_MISSION_CLEAR_INFO::_MAX_CHECK_NUM;++i)
{
rStream.mission_number[i] = GetCurClearNum(i);
}
}
RC::eQUEST_RESULT QUEST_CONDITION_MISSION_CLEAR::CanComplete(void *pvParam)
{
for( BYTE i=0;i<QUEST_CONDITION_MISSION_CLEAR_INFO::_MAX_CHECK_NUM;++i)
{
if( GetCurClearNum(i) < GetInfo()->GetMissionNum(i) )
{
return RC::RC_QUEST_NOT_ENOUGH_MISSION_CLEAR_COUNT;
}
}
return RC::RC_QUEST_SUCCESS;
}
BOOL QUEST_CONDITION_MISSION_CLEAR::Event(eQUEST_EVENT evt, QUEST_MSG *pMsg)
{
if( evt == QUEST_EVENT_MISSION_CLEAR)
{
QUEST_MISSION_CLEAR_MSG* pmsg = (QUEST_MISSION_CLEAR_MSG *)pMsg;
for(BYTE i=0; i<QUEST_CONDITION_MISSION_CLEAR_INFO::_MAX_CHECK_NUM; ++i)
{
if(GetInfo()->GetMissionCode(i) == pmsg->mission_code &&
GetCurClearNum(i) < GetInfo()->GetMissionNum(i))
{
SetCurClearNum(i, GetCurClearNum(i)+1);
return true;
}
}
}
return FALSE;
}
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
#endif //_NA_006607_20130402_ADD_QUESTTYPE