/* ==========================================================================
* 파    일 : AIManager.h
* 목    적 : ai관리자
* 작 성 자 : 박경희
* 작 성 일 : 2007-11-13
* 주의사항 : 
*===========================================================================*/

#pragma once

#include "BaseObject_Common.h"
#include "Monster_Common.h"
#include "Gathering_Common.h"
#include "IndexGenerator.h"

const int AI_REGEN_PROCESS_DELAY = 100;

class cNaviField;
class cPathFinder;
class cMonster;
class cGathering;

struct sRegenGroupScript;

enum eACTION_ID;
enum eACTION_CHANGE;
enum ePathfindresult;
enum eACTION_GAT_ID;
enum eACTION_GAT_CHANGE;

struct sRegenMonster
{
	unsigned long		mObjectIdx;
	unsigned long		mRegenIdx;
	unsigned long		mRegenTime;
	bool				mDie;
};

struct sRegenGroup
{
	/// 스크립트 참고용 포인터
	sRegenGroupScript*	mpRegenGroup;

	unsigned long		mGroupIdx;
	/// 리젠 퍼센테지를 만족 할 경우 리젠 카운트를 시작하라는 플래그
	bool				mIsRegen;		
	/// 리젠 수행 시간
	unsigned long		mRegenTime;		
	/// 그룹에 해당하는 몬스터 살아 있는 수
	unsigned long		mMonsterAliveCnt;	

	tArray<void*>		mMonsterList;
};

struct sSwichGroup
{
	unsigned long		mSwitchGroup;
	/// 리젠 선택된 그룹인덱스
	unsigned long		mGroupIdx;
	/// 다음 리젠 시간
	unsigned long		mRegenTime;
	/// 리젠 하지 않음
	bool				mRegenStop;

	tArray<unsigned long>*	mpGroupIdxAry;
};

struct sRegenGatherGroup
{
	/// 스크립트 참고용 포인터
	const sGatheringRegenHeader*	mpGetheringRegenHeader;

	unsigned long		mGroupIdx;
	/// 리젠 수행 시간
	unsigned long		mRegenTime;		
	/// 리젠 준비 상태
	bool				mRegenReady;
};


class cAIManager
{
public:

	static cAIManager*	mpAIManager;

public:

	/// 생성소멸
	cAIManager();
	~cAIManager();

	/// 자원관리
	bool				Init( int serverType );
	void				Release();
	void				Process( unsigned long elapsedTime, unsigned long accumTime );

	//////////////////////////////////////////////////////////////////////////
	/// 몬스터
	
	/// 몬스터 리젠 프로세스
	void				MonRegenProcess( unsigned long elapsedTime, unsigned long accumTime );

	void				BossSummonMonRegen( cMonster* pBoss, unsigned short mapNumber, float x , float y, unsigned long genRange, unsigned long genCnt, unsigned long monsterClassIdx );
	void				CheatSummonMonRegen( unsigned short mapNumber, float x , float y, unsigned long monsterClassIdx, unsigned long genCnt );
	unsigned long		QuestSummonMonRegen( unsigned short mapNumber, float x , float y, unsigned long monsterClassIdx, unsigned long destroyTime );

	/// 죽어서 리젠 대기로 넘어가는 몬스터 등록
	void				InsertReadyMonster( unsigned long monsterIdx, unsigned long regenIdx, unsigned long groupIdx );

	void				SwitchRegenStart( unsigned long switchGroupIdx );
	void				SwitchRegenStop( unsigned long switchGroupIdx );

	//////////////////////////////////////////////////////////////////////////
	/// 채집

	/// 채집 리젠 프로세스
	void				GatRegenProcess( unsigned long elapsedTime, unsigned long accumTime );

	/// 죽어서 리젠 대기로 넘어가는 채집 등록
	void				InsertReadyGathering( unsigned long objectIdx, unsigned long regenIdx );


	//////////////////////////////////////////////////////////////////////////
	/// 길찾기

	/// 맵 사이즈
	float				GetPathMaxSideSize( unsigned int mapNum );
	/// 현재 위치 높이값
	bool				CalcHeight( unsigned short mapNumber, float* height, float x, float y ) const;
	/// 이동 가능지역 체크
	bool				IsPassible( unsigned short mapNumber, float x, float y, sObject object ) const;
	bool				IsPassible( unsigned short mapNumber, NiPoint2 start, NiPoint2 goal, sObject object ) const;

	/// 이동 경로 겟수 산출
	unsigned long		CalcPathCnt( unsigned short mapNumber, NiPoint2 start, NiPoint2 goal );

private:
	void				RegenMonster( unsigned long groupIdx, sRegenMonster* pRM );

private:

	typedef tPointerHashMap<unsigned long, void*> cPointHashMap;
	typedef tArray<unsigned long> cArray;
	typedef tArray<void*> cVoidAry;

	/// 리젠그룹을 기준으로 관리해야 하는 몬스터 목록 전체 보유
	/// typedef tPointerHashMap<unsigned long, sRegenGroup*> cPointerHashMap;
	cPointHashMap*		mpRegenGroupMap;

	cPointHashMap*		mpRegenSwitchMap;

	/// typedef tPointerHashMap<unsigned long, sRegenGatherGroup*> cPointerHashMap;
    cPointHashMap*		mpRegenGatherGroupMap;	

	/// 인덱스 생성기
	cIndexGenerator		mMonsterIdxGen;
	cIndexGenerator		mGatheringIdxGen;

	/// 서버부팅후 바로 리젠
	bool				mServerOnRegen;

	/// 리젠 프로세스 부하 방지
	unsigned long		mNextCheckTime;

	/// 채집
	cArray				mReadyGatheringAry;

	/// 일반채널 / 인던 구분
	int					mServerType;

	//////////////////////////////////////////////////////////////////////////
	/// 길찾기
	cNaviField*			mNaviField[MAP_COUNT];		/// 네비필드
	cPathFinder*		mPathFinder[MAP_COUNT];		/// 길찾기
	float				mMapSize[MAP_COUNT];
	
	/// 081106 PKH 인던
	cNaviField*			mInstDgNaviField;
	cPathFinder*		mInstDgPathFinder;
	float				mInstDgMapSize;

	NiPoint2			mTempPathAry[MAX_PATH_COUNT];
};

#define AIMANAGER	cAIManager::mpAIManager
