BOOL KSkillManager::LoadSkillTable()
{
    BOOL        bResult     = false;
    BOOL        bRetCode    = false;
    DWORD       dwSkillID   = 0;
    DWORD       dwStepID    = 0;  
    KSkill*     pSkill      = NULL;
    ITabFile*   piTabFile   = NULL;
    std::pair<KSkillTable::iterator, bool> InsRet;
    const int   MAX_COLUMN_NAME_LEN = 64;
    char        szMoveState[MAX_COLUMN_NAME_LEN] = "";
    KAttribData  AttributeData;
    KMAP_SKILL_DATA cSkillBinaryData;
    KMAP_SKILL_DATA::iterator it;
    char        szValue[64];
    char	    szScriptName[MAX_PATH];

    bRetCode = LoadSkillBinaryData(cSkillBinaryData);
    KGLOG_PROCESS_ERROR(bRetCode);

    piTabFile = g_OpenTabFile(SETTING_DIR"/"SKILL_LIST_FILE_NAME);
    KGLOG_PROCESS_ERROR(piTabFile);

    for (int nRowIndex = 2; nRowIndex <= piTabFile->GetHeight(); nRowIndex++)
    {
        bRetCode = piTabFile->GetInteger(nRowIndex, "ID", 0, (int*)(&dwSkillID));
        KGLOG_PROCESS_ERROR(bRetCode > 0);

        bRetCode = piTabFile->GetInteger(nRowIndex, "Step", 0, (int*)(&dwStepID));
        KGLOG_PROCESS_ERROR(bRetCode);
        KGLOG_PROCESS_ERROR(dwStepID >= 0);
          
        InsRet = m_SkillTable.insert(std::make_pair(MAKE_INT64(dwSkillID, dwStepID), KSkill()));
        KGLOG_PROCESS_ERROR(InsRet.second);

        pSkill = &(InsRet.first->second);

        pSkill->m_dwID = dwSkillID;
        pSkill->m_dwStepID = dwStepID;

        bRetCode = piTabFile->GetInteger(nRowIndex, "NirvanaSkill", 0, &pSkill->m_bNirvanaSkill);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetString(nRowIndex, "BelongToSlot", "", szValue, sizeof(szValue));
        KGLOG_PROCESS_ERROR(bRetCode);
        bRetCode = g_ParseMutiInteger(szValue, ";", pSkill->m_vecBelongToSlots);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "SrcBuffID", 0, (int*)(&pSkill->m_dwSrcBuffID));
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "DestBuffID", 0, (int*)(&pSkill->m_dwDestBuffID));
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "AimType", 0, (int*)(&pSkill->m_dwAimType));
        KGLOG_PROCESS_ERROR(bRetCode);

        for (int i = 1; i <= 8; i++)
        {
            bRetCode = LoadAttribute(piTabFile, nRowIndex, "SrcAttribute", i, &AttributeData);
            KGLOG_PROCESS_ERROR(bRetCode);

            if (AttributeData.nKey != atInvalid)
            {
                APPEND_ATTRIB(pSkill->m_pSrcAttribute, AttributeData);
            }

            bRetCode = LoadAttribute(piTabFile, nRowIndex, "DestAttribute", i, &AttributeData);
            KGLOG_PROCESS_ERROR(bRetCode);

            if (AttributeData.nKey != atInvalid)
            {
                APPEND_ATTRIB(pSkill->m_pDestAttribute, AttributeData);
            }
        }

        bRetCode = piTabFile->GetInteger(nRowIndex, "CanCastWithBall", 0, &pSkill->m_bCanCastWithBall);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "SkillType", skilltypeInvalid, (int*)&pSkill->m_eSkillType);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "AttackIntervalFrame", 0, &pSkill->m_nAttackIntervalFrame);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "TargetCostEndurance", 0, &pSkill->m_nTargetCostEndurance);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "TargetCostStamina", 0, &pSkill->m_nTargetCostStamina);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "TargetCostEndurancePercent", 0, &pSkill->m_nTargetCostEndurancePercent);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "TargetCostStaminaPercent", 0, &pSkill->m_nTargetCostStaminaPercent);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetString(nRowIndex, "MoveState", "cmsInvalid", szMoveState, sizeof(szMoveState));
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = ENUM_STR2INT(HERO_MOVESTATE, szMoveState, pSkill->m_nMoveState);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "MoveStateFrame", 0, &pSkill->m_nMoveStateFrame);
        KGLOG_PROCESS_ERROR(bRetCode);
        pSkill->m_nMoveStateFrame = pSkill->m_nMoveStateFrame * GAME_FPS / cdTimeBase;

        bRetCode = piTabFile->GetInteger(nRowIndex, "StepMinTime", 0, &pSkill->m_nStepMinFrame);
        KGLOG_PROCESS_ERROR(bRetCode);
        pSkill->m_nStepMinFrame = pSkill->m_nStepMinFrame * GAME_FPS / cdTimeBase;

        bRetCode = piTabFile->GetInteger(nRowIndex, "StepMaxTime", 0, &pSkill->m_nStepMaxFrame);
        KGLOG_PROCESS_ERROR(bRetCode);
        pSkill->m_nStepMaxFrame = pSkill->m_nStepMaxFrame * GAME_FPS / cdTimeBase;

        bRetCode = piTabFile->GetInteger(nRowIndex, "EndType", 0, (int*)&pSkill->m_eEndType);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "EndFrame", 0, &pSkill->m_nEndFrame);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "InterruptLevel", 0, &pSkill->m_nInterruptLevel);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetString(nRowIndex, "Script", "", szScriptName, sizeof(szScriptName));
        KGLOG_PROCESS_ERROR(bRetCode);
        szScriptName[sizeof(szScriptName) - 1] = '\0';
        
        if (szScriptName[0] != '\0')
            pSkill->m_dwScriptID = g_FileNameHash(szScriptName);
        else
            pSkill->m_dwScriptID = 0;

        for (int i = 0; i < countof(pSkill->m_SubSkill); ++i)
        {
            char szKey[32] = "";

            sprintf(szKey, "SubSkillID%d", i+1);
            bRetCode = piTabFile->GetInteger(nRowIndex, szKey, ERROR_ID, (int*)&pSkill->m_SubSkill[i].dwID);
            KGLOG_PROCESS_ERROR(bRetCode);

            sprintf(szKey, "SubSkillTriggerType%d", i+1);
            bRetCode = piTabFile->GetInteger(nRowIndex, szKey, KSKILL_TRIGGER_TYPE_INVALID, (int*)&pSkill->m_SubSkill[i].eType);
            KGLOG_PROCESS_ERROR(bRetCode);

            sprintf(szKey, "SubSkillTriggerTimer%d", i+1);
            bRetCode = piTabFile->GetInteger(nRowIndex, szKey, 0, &pSkill->m_SubSkill[i].nFrame);
            KGLOG_PROCESS_ERROR(bRetCode);      
            pSkill->m_SubSkill[i].nFrame = pSkill->m_SubSkill[i].nFrame * GAME_FPS / cdTimeBase;

            sprintf(szKey, "SubSkillRate%d", i+1);
            bRetCode = piTabFile->GetInteger(nRowIndex, szKey, 0, (int*)&pSkill->m_SubSkill[i].dwRate);
            KGLOG_PROCESS_ERROR(bRetCode);
        }

        bRetCode = piTabFile->GetInteger(nRowIndex, "SelfAddAngry", 0, &pSkill->m_nSelfAddAngry);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "TargetAddAngry", 0, &pSkill->m_nTargetAddAngry);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "NeedAngry", 0, &pSkill->m_nNeedAngry);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "CostAngry", 0, &pSkill->m_nCostAngry);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "CostAngryPercent", 0, &pSkill->m_nCostAngryPercent);
        KGLOG_PROCESS_ERROR(bRetCode);
        
        bRetCode = piTabFile->GetInteger(nRowIndex, "TargetBuffLimit", 0, (int*)&pSkill->m_dwTargetBuffLimit);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "CanCastCountInAir", 0, &pSkill->m_nCanCastCountInAir);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "SpasticityTime", 0, &pSkill->m_nSpasticityFrame);
        KGLOG_PROCESS_ERROR(bRetCode);
        pSkill->m_nSpasticityFrame = pSkill->m_nSpasticityFrame * GAME_FPS / cdTimeBase;

        bRetCode = piTabFile->GetInteger(nRowIndex, "DelayEffect", 0, &pSkill->m_bDelayApplySkillEffect);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "Invincible", 0, &pSkill->m_bInvincibleOnSpasticity);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "IsCommonSkill", 0, (int*)&pSkill->m_bIsCommonSkill);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "RequireLevel", 0, (int*)&pSkill->m_nRequireLevel);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "GravityPercent", 0, &pSkill->m_nGravityPercent);
        KGLOG_PROCESS_ERROR(bRetCode > 0);

        bRetCode = piTabFile->GetInteger(nRowIndex, "JudgeBoxMinX", 0, &pSkill->m_nJudgeBoxMinX);
        KGLOG_PROCESS_ERROR(bRetCode > 0);

        bRetCode = piTabFile->GetInteger(nRowIndex, "JudgeBoxMaxX", 0, &pSkill->m_nJudgeBoxMaxX);
        KGLOG_PROCESS_ERROR(bRetCode > 0);

        bRetCode = piTabFile->GetInteger(nRowIndex, "JudgeBoxMinY", 0, &pSkill->m_nJudgeBoxMinY);
        KGLOG_PROCESS_ERROR(bRetCode > 0);

        bRetCode = piTabFile->GetInteger(nRowIndex, "JudgeBoxMaxY", 0, &pSkill->m_nJudgeBoxMaxY);
        KGLOG_PROCESS_ERROR(bRetCode > 0);

        bRetCode = piTabFile->GetInteger(nRowIndex, "JudgeBoxMinZ", 0, &pSkill->m_nJudgeBoxMinZ);
        KGLOG_PROCESS_ERROR(bRetCode > 0);

        bRetCode = piTabFile->GetInteger(nRowIndex, "JudgeBoxMaxZ", 0, &pSkill->m_nJudgeBoxMaxZ);
        KGLOG_PROCESS_ERROR(bRetCode > 0);

        bRetCode = piTabFile->GetInteger(nRowIndex, "CanSpecifyCastDir", 0, &pSkill->m_bCanSpecifyCastDir);
        KGLOG_PROCESS_ERROR(bRetCode > 0);

        bRetCode = piTabFile->GetInteger(nRowIndex, "CanSpecifyCastingDir", 0, &pSkill->m_bCanSpecifyCastingDir);
        KGLOG_PROCESS_ERROR(bRetCode > 0);

        bRetCode = piTabFile->GetString(nRowIndex, "RestraintType", "",  szValue, countof(szValue));
        KGLOG_PROCESS_ERROR(bRetCode > 0);
        szValue[countof(szValue) - 1] = '\0';

        bRetCode = EnumStr2Int("RESTRAINT_TYPE", szValue, &pSkill->m_nRestraintType);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "ClearVelocityAtEnd", 0, &pSkill->m_bClearVelocityAtEnd);
        KGLOG_PROCESS_ERROR(bRetCode > 0); 

        bRetCode = piTabFile->GetInteger(nRowIndex, "Series", 0, &pSkill->m_nSeries);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "FireAIEvent", 0, &pSkill->m_bFireAIEvent);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "AIEventMinX", 0, &pSkill->m_nAIEventMinX);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "AIEventMaxX", 0, &pSkill->m_nAIEventMaxX);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "AIEventMinY", 0, &pSkill->m_nAIEventMinY);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "AIEventMaxY", 0, &pSkill->m_nAIEventMaxY);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "AIEventMinZ", 0, &pSkill->m_nAIEventMinZ);
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = piTabFile->GetInteger(nRowIndex, "AIEventMaxZ", 0, &pSkill->m_nAIEventMaxZ);
        KGLOG_PROCESS_ERROR(bRetCode);

        it = cSkillBinaryData.find(InsRet.first->first);
        if (it != cSkillBinaryData.end())
        {
            pSkill->SetBinaryData(it->second);
        }

        // 以下代码用于验证输入内容的合法性

        KGLOG_PROCESS_ERROR(pSkill->m_eSkillType > skilltypeInvalid && pSkill->m_eSkillType < skilltypeTotal);
        KGLOG_PROCESS_ERROR(pSkill->m_nMoveState >= cmsInvalid && pSkill->m_nMoveState < cmsTotal);

        KGLOG_PROCESS_ERROR(pSkill->m_eEndType >= KSKILL_END_TYPE_NONE && pSkill->m_eEndType < KSKILL_END_TYPE_TOTAL);

        // KGLOG_PROCESS_ERROR(pSkill->m_eSkillType != skilltypeGrab || pSkill->m_eEndType == KSKILL_END_TYPE_BY_TIME);

        KGLOG_PROCESS_ERROR(pSkill->m_eEndType != KSKILL_END_TYPE_BY_TIME || pSkill->m_nEndFrame >= 0);

        KGLOG_PROCESS_ERROR(pSkill->m_nSpasticityFrame >= 0);
        KGLOG_PROCESS_ERROR(pSkill->m_nSpasticityFrame != 0 || !pSkill->m_bDelayApplySkillEffect);
        KGLOG_PROCESS_ERROR(pSkill->m_nSpasticityFrame != 0 || !pSkill->m_bInvincibleOnSpasticity);

        for (int i = 0; i < countof(pSkill->m_SubSkill); ++i)
        {
            KGLOG_PROCESS_ERROR(pSkill->m_SubSkill[i].eType >= KSKILL_TRIGGER_TYPE_INVALID && pSkill->m_SubSkill[i].eType < KSKILL_TRIGGER_TYPE_TOTAL);
            KGLOG_PROCESS_ERROR(pSkill->m_SubSkill[i].dwRate >=0 && pSkill->m_SubSkill[i].dwRate <= SKILL_RATE_BASE);
            KGLOG_PROCESS_ERROR(pSkill->m_SubSkill[i].eType != KSKILL_TRIGGER_TYPE_TIMER || pSkill->m_SubSkill[i].nFrame > 0);
        }

        KGLOG_PROCESS_ERROR(pSkill->m_nSpasticityFrame >= 0);

        KGLOG_PROCESS_ERROR(pSkill->m_nAIEventMinX <= pSkill->m_nAIEventMaxX);
        KGLOG_PROCESS_ERROR(pSkill->m_nAIEventMinY <= pSkill->m_nAIEventMaxY);
        KGLOG_PROCESS_ERROR(pSkill->m_nAIEventMinZ <= pSkill->m_nAIEventMaxZ);
    }

    for (KSkillTable::iterator it = m_SkillTable.begin(); it != m_SkillTable.end(); ++it)
    {
        dwSkillID =  it->second.m_dwID;
        bRetCode = it->second.UpdateOnSkillLoaded();
        KGLOG_PROCESS_ERROR(bRetCode);
    }

    bResult = true;
Exit0:
    if (!bResult)
        KGLogPrintf(KGLOG_ERR, "ID = %u", dwSkillID);

    KG_COM_RELEASE(piTabFile);
    return bResult;
}
BOOL KQuestInfoList::LoadQuestInfo(ITabFile* piTabFile, int nIndex, KQuestInfo* pQuestInfo)
{
    BOOL bResult  = false;
	BOOL bRetCode = false;
    int  nTabData = 0;
    char szColName[64];
    char szScriptName[MAX_PATH];
    char szValue[256] = "";

	bRetCode = piTabFile->GetInteger(nIndex, "QuestID", m_DefaultQuestInfo.dwQuestID, (int*)&(pQuestInfo->dwQuestID));
	KGLOG_PROCESS_ERROR(bRetCode);
    KGLOG_PROCESS_ERROR(pQuestInfo->dwQuestID < MAX_QUEST_COUNT);

	bRetCode = piTabFile->GetString(nIndex, "QuestName", m_DefaultQuestInfo.szQuestName, pQuestInfo->szQuestName, _NAME_LEN);
	KGLOG_PROCESS_ERROR(bRetCode);

    bRetCode = piTabFile->GetInteger(nIndex, "QuestType", m_DefaultQuestInfo.nQuestType, &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->nQuestType = nTabData;
  
	bRetCode = piTabFile->GetInteger(nIndex, "CanRepeat", m_DefaultQuestInfo.bRepeat, &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->bRepeat = (bool)nTabData;

	bRetCode = piTabFile->GetInteger(nIndex, "NeedAccept", m_DefaultQuestInfo.bAccept, &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->bAccept = (bool)nTabData;

    bRetCode = piTabFile->GetInteger(nIndex, "QuestLevel", m_DefaultQuestInfo.byLevel, &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->byLevel = (BYTE)nTabData;

	bRetCode = piTabFile->GetInteger(nIndex, "StartItemType", m_DefaultQuestInfo.byStartItemType, &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->byStartItemType = (BYTE)nTabData;

	bRetCode = piTabFile->GetInteger(nIndex, "StartItemIndex", m_DefaultQuestInfo.wStartItemIndex, &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->wStartItemIndex = (WORD)nTabData;

	bRetCode = piTabFile->GetInteger(nIndex, "MinLevel", m_DefaultQuestInfo.byMinLevel, &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->byMinLevel = (BYTE)nTabData;

	bRetCode = piTabFile->GetInteger(nIndex, "MaxLevel", m_DefaultQuestInfo.byMaxLevel, &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->byMaxLevel = (BYTE)nTabData;

	bRetCode = piTabFile->GetInteger(nIndex, "RequireGender", m_DefaultQuestInfo.byRequireGender, &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->byRequireGender = (BYTE)nTabData;

	bRetCode = piTabFile->GetInteger(nIndex, "RequireSingle", m_DefaultQuestInfo.byRequireSingle, &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
	pQuestInfo->byRequireSingle = (BYTE)nTabData;

	bRetCode = piTabFile->GetInteger(
        nIndex, "CooldownID",
        m_DefaultQuestInfo.dwCoolDownID, (int*)&(pQuestInfo->dwCoolDownID)
    );
	KGLOG_PROCESS_ERROR(bRetCode);

    bRetCode = piTabFile->GetInteger(
        nIndex, "PrequestID",
        m_DefaultQuestInfo.dwPrequestID, (int*)&pQuestInfo->dwPrequestID
    );
    KGLOG_PROCESS_ERROR(bRetCode);
    
    bRetCode = piTabFile->GetInteger(
        nIndex, "SubsequenceID", 
		m_DefaultQuestInfo.dwSubsequenceID, (int*)&(pQuestInfo->dwSubsequenceID)
    );
	KGLOG_PROCESS_ERROR(bRetCode);

	bRetCode = piTabFile->GetInteger(
        nIndex, "StartTime",
		m_DefaultQuestInfo.nStartTime, (int*)&(pQuestInfo->nStartTime)
    );
	KGLOG_PROCESS_ERROR(bRetCode);

	bRetCode = piTabFile->GetInteger(
        nIndex, "EndTime",
		m_DefaultQuestInfo.nEndTime, (int*)&(pQuestInfo->nEndTime)
    );
	KGLOG_PROCESS_ERROR(bRetCode);

    for (int i = 0; i < QUEST_OFFER_ITEM_COUNT; ++i)
    {
        sprintf(szColName, "OfferItemType%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

        bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.dwOfferItemType[i], (int*)&pQuestInfo->dwOfferItemType[i]);
	    KGLOG_PROCESS_ERROR(bRetCode);
        
        sprintf(szColName, "OfferItemIndex%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

	    bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.nOfferItemIndex[i], &pQuestInfo->nOfferItemIndex[i]);
	    KGLOG_PROCESS_ERROR(bRetCode);
        
        sprintf(szColName, "OfferItemAmount%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

	    bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.nOfferItemAmount[i], &pQuestInfo->nOfferItemAmount[i]);
	    KGLOG_PROCESS_ERROR(bRetCode);
    }
    
    for (int i = 0; i < QUEST_END_ITEM_COUNT; ++i)
    {
        sprintf(szColName, "EndRequireItemType%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

        bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.byEndRequireItemType[i], &nTabData);
	    KGLOG_PROCESS_ERROR(bRetCode);
        pQuestInfo->byEndRequireItemType[i] = (BYTE)nTabData;
        
        sprintf(szColName, "EndRequireItemIndex%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

	    bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.wEndRequireItemIndex[i], &nTabData);
	    KGLOG_PROCESS_ERROR(bRetCode);
        pQuestInfo->wEndRequireItemIndex[i] = (WORD)nTabData;
        
        sprintf(szColName, "EndRequireItemAmount%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

	    bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.wEndRequireItemAmount[i], &nTabData);
	    KGLOG_PROCESS_ERROR(bRetCode);
        pQuestInfo->wEndRequireItemAmount[i] = (WORD)nTabData;
        
        sprintf(szColName, "DropDoodadTemplateID%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

        sprintf(szColName, "IsDeleteEndRequireItem%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

	    bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.bIsDeleteEndRequireItem[i], &nTabData);
	    KGLOG_PROCESS_ERROR(bRetCode);
        pQuestInfo->bIsDeleteEndRequireItem[i] = (bool)nTabData;
    }
    
    bRetCode = piTabFile->GetInteger(nIndex, "EventOrder", m_DefaultQuestInfo.bEventOrder, &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->bEventOrder = (bool)nTabData;

    for (int i = 0; i < countof(pQuestInfo->AllEvent); ++i)
    {
        sprintf(szColName, "QuestValue%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

        bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.AllEvent[i].nQuestValue, &nTabData);
        KGLOG_PROCESS_ERROR(bRetCode);
        pQuestInfo->AllEvent[i].nQuestValue = nTabData;

        sprintf(szColName, "QuestEvent%d", i + 1);
        bRetCode = piTabFile->GetString(nIndex, szColName, "peInvalid", szValue, sizeof(szValue));
        KGLOG_PROCESS_ERROR(bRetCode);

        bRetCode = EnumStr2Int("PLAYER_EVENT_TYPE", szValue, &nTabData);
        KGLOG_PROCESS_ERROR(bRetCode);
        pQuestInfo->AllEvent[i].nEvent       = nTabData;

        for (int j = 0; j < countof(pQuestInfo->AllEvent[i].AllCondition); ++j)
        {
            sprintf(szColName, "Event%dParam%d", i + 1, j  + 1);
            szColName[sizeof(szColName) - 1] = '\0';

            bRetCode = piTabFile->GetString(nIndex, szColName, "", szValue, sizeof(szValue));
            KGLOG_PROCESS_ERROR(bRetCode);
            szValue[countof(szValue) - 1] = '\0';

            bRetCode = pQuestInfo->AllEvent[i].AllCondition[j].InitFromString(szValue);
            KGLOG_PROCESS_ERROR(bRetCode);
        }
    }
    
	bRetCode = piTabFile->GetInteger(nIndex, "PresentAll1", m_DefaultQuestInfo.bPresentAll[0], &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->bPresentAll[0] = (bool)nTabData;

	bRetCode = piTabFile->GetInteger(nIndex, "PresentAll2", m_DefaultQuestInfo.bPresentAll[1], &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->bPresentAll[1] = (bool)nTabData;
    
    for (int i = 0; i < cdQuestParamCount; ++i)
    {
        sprintf(szColName, "PresentItemType%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

        bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.byPresentItemType[i], &nTabData);
	    KGLOG_PROCESS_ERROR(bRetCode);
        pQuestInfo->byPresentItemType[i] = (BYTE)nTabData;
        
        sprintf(szColName, "PresentItemIndex%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

	    bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.wPresentItemIndex[i], &nTabData);
	    KGLOG_PROCESS_ERROR(bRetCode);
        pQuestInfo->wPresentItemIndex[i] = (WORD)nTabData;
        
        sprintf(szColName, "PresentItemAmount%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

	    bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.wPresentItemAmount[i], &nTabData);
	    KGLOG_PROCESS_ERROR(bRetCode);
        pQuestInfo->wPresentItemAmount[i] = (WORD)nTabData;

        sprintf(szColName, "PresentItemValuePoint%d", i + 1);
        szColName[sizeof(szColName) - 1] = '\0';

	    bRetCode = piTabFile->GetInteger(nIndex, szColName, m_DefaultQuestInfo.wPresentItemValuePoint[i], &nTabData);
	    KGLOG_PROCESS_ERROR(bRetCode);
        pQuestInfo->wPresentItemValuePoint[i] = (WORD)nTabData;
    }  

	bRetCode = piTabFile->GetInteger(
        nIndex, "PresentExp",
		m_DefaultQuestInfo.nPresentExp, (int*)&(pQuestInfo->nPresentExp)
    );
	KGLOG_PROCESS_ERROR(bRetCode);

	bRetCode = piTabFile->GetInteger(
        nIndex, "PresentMoney",
		m_DefaultQuestInfo.nPresentMoney, (int*)&(pQuestInfo->nPresentMoney)
    );
	KGLOG_PROCESS_ERROR(bRetCode);

	bRetCode = piTabFile->GetInteger(nIndex, "RepeatCutPercent", m_DefaultQuestInfo.byRepeatCutPercent, &nTabData);
	KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->byRepeatCutPercent = (BYTE)nTabData;
    
    pQuestInfo->dwScriptID = 0;
    bRetCode = piTabFile->GetString(nIndex, "ScriptName", "", szScriptName, MAX_PATH);
	KGLOG_PROCESS_ERROR(bRetCode);
    if (szScriptName[0] != '\0')
    {
        pQuestInfo->dwScriptID = g_FileNameHash(szScriptName);
    }

    bRetCode = piTabFile->GetInteger(nIndex, "CostMoney", m_DefaultQuestInfo.nCostMoney, (int*)&(pQuestInfo->nCostMoney));
	KGLOG_PROCESS_ERROR(bRetCode);
    KGLOG_PROCESS_ERROR(pQuestInfo->nCostMoney >= 0);

    bRetCode = piTabFile->GetInteger(nIndex, "AutoFinish", m_DefaultQuestInfo.bAutoFinish, &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->bAutoFinish = (BOOL)nTabData;

    bRetCode = piTabFile->GetInteger(nIndex, "ClientCanFinish", m_DefaultQuestInfo.bClientCanFinish, &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->bClientCanFinish = (BOOL)nTabData;

    bRetCode = piTabFile->GetInteger(nIndex, "Daily", m_DefaultQuestInfo.bDaily, &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->bDaily = (BOOL)nTabData;

    bRetCode = piTabFile->GetInteger(nIndex, "RequireMissionType", m_DefaultQuestInfo.nRequireMissionType, &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->nRequireMissionType = (DWORD)nTabData;

    bRetCode = piTabFile->GetInteger(nIndex, "RequireMissionStep", m_DefaultQuestInfo.nRequireMissionStep, &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->nRequireMissionStep = nTabData;

    bRetCode = piTabFile->GetInteger(nIndex, "RequireMissionLevel", m_DefaultQuestInfo.nRequireMissionLevel, &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->nRequireMissionLevel = nTabData;

    bRetCode = piTabFile->GetInteger(nIndex, "RequireMapType", m_DefaultQuestInfo.nRequireMapType, &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->nRequireMapType = nTabData;
    bRetCode = piTabFile->GetInteger(nIndex, "AwardHero1TemplateID", m_DefaultQuestInfo.dwAwardHeroTemplateID[0], &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->dwAwardHeroTemplateID[0] = nTabData;

    bRetCode = piTabFile->GetInteger(nIndex, "AwardHero2TemplateID", m_DefaultQuestInfo.dwAwardHeroTemplateID[1], &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->dwAwardHeroTemplateID[1] = nTabData;

    bRetCode = piTabFile->GetInteger(nIndex, "AwardHero1Level", m_DefaultQuestInfo.nAwardHeroLevel[0], &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->nAwardHeroLevel[0] = nTabData;

    bRetCode = piTabFile->GetInteger(nIndex, "AwardHero2Level", m_DefaultQuestInfo.nAwardHeroLevel[1], &nTabData);
    KGLOG_PROCESS_ERROR(bRetCode);
    pQuestInfo->nAwardHeroLevel[1] = nTabData;

    bResult = true;
Exit0:
	return bResult;
}