Jump to content

SukH

Premium
  • Posts

    129
  • Joined

  • Last visited

  • Days Won

    1
  • Feedback

    0%

Posts posted by SukH

  1. 23 minutes ago, Sonitex said:

     

    With that attitude I doubt anyone will help you. But what you can do is read some books about programming, it might improve your knowledge.

    don`t need bro i already removed it i was thinking that people here help but is only  boring people sometimes they don`t have to do something and only reply "SHIT" to posts xd

    is not about attitude he just reply at this post without provide anything like i was asking for help  there is no problem i think replying decent  " No we can not provide you help remove it if u got some error we can help you " this i call a help not like that free people only ONline for doing shits xd

     

     

     

    Please close the topic i already removed it by myself if i get any bugg or anything i will ask in new post to help

     

    Thanks :)

  2. i just ask if anybody has the .rar i don`t mean a don`t know removing without defines i already did i just wanna  see just if there left something more or not -.-

    1 hour ago, tierrilopes said:

    Of course

    Do you need some assistance removing the code also?

      i think u need a psychiatrist ? xd better then offering me a assistance to remove

  3. Hello Metin2Dev,

     

    I need a big help  please

     

    Anybody has a .rar of LennT (Shash system Version 1) because i buyed  that system when he released so  he installed it and the installation was without any #DEFINES  so is there a limitation in that system i want is to remove it fully from my  project and install newest version

     

    I need from anybody who has the .rar of the  (VERSION 1) that he can provide it to me to remove the system please please  i lost my .rar when i changed PC a 2 years ago

     

    Thank You

     

  4. 2 minutes ago, Sonitex said:
    
    	void CQuestManager::CancelServerTimers(DWORD arg)
    	{
    		vector<pair<string, DWORD>> ServerTimersToDelete;
    
    		for (auto& kv : m_mapServerTimer) {
    			if (kv.first.second == arg) {
    				LPEVENT event = kv.second;
    				event_cancel(&event);
    				ServerTimersToDelete.push_back(kv.first);
    			}
    		}
    
    		// Delete all the required server timers
    		for (auto &timer : ServerTimersToDelete)
    			m_mapServerTimer.erase(timer);
    
    		// Clean up
    		ServerTimersToDelete.clear();
    	}

    Crash occurs because the game is deleting timers while iterating through them. Code above should fix this issue :) 

     

    thank you very much dude i will try  :)

  5.     void CQuestManager::CancelServerTimers(DWORD arg)
        {
            itertype(m_mapServerTimer) it = m_mapServerTimer.begin();
    Line> 1733        for ( ; it != m_mapServerTimer.end(); ++it) {
                if (it->first.second == arg) {
                    LPEVENT event = it->second;
                    event_cancel(&event);
                    m_mapServerTimer.erase(it);
                }
            }
        }

    this is that function and the line 1733 is

     

            for ( ; it != m_mapServerTimer.end(); ++it) {

     

  6. thnx @TMP4 but i was thinking same but that was already fixed    i just find this on my dungeon.cpp 

     

    if (!pDungeon) //

    { //sys_err("M2_NEW CDungeon failed"); /

    /return NULL;

     

    Dungeon.cpp

    Spoiler
    
    #include "stdafx.h"
    #include "dungeon.h"
    #include "char.h"
    #include "char_manager.h"
    #include "party.h"
    #include "affect.h"
    #include "packet.h"
    #include "desc.h"
    #include "config.h"
    #include "regen.h"
    #include "start_position.h"
    #include "item.h"
    #include "item_manager.h"
    #include "utils.h"
    #include "questmanager.h"
    
    CDungeon::CDungeon(IdType id, long lOriginalMapIndex, long lMapIndex)
    	: m_id(id),
    	m_lOrigMapIndex(lOriginalMapIndex),
    	m_lMapIndex(lMapIndex),
    	m_map_Area(SECTREE_MANAGER::instance().GetDungeonArea(lOriginalMapIndex))
    {
    	Initialize();
    	//sys_log(0,"DUNGEON create orig %d real %d", lOriginalMapIndex, lMapIndex);
    }
    
    CDungeon::~CDungeon()
    {
    	if (m_pParty != NULL)
    	{
    		m_pParty->SetDungeon_for_Only_party (NULL);
    	}
    	//sys_log(0,"DUNGEON destroy orig %d real %d", m_lOrigMapIndex, m_lMapIndex	);
    	ClearRegen();
    	event_cancel(&deadEvent);
    	// <Factor>
    	event_cancel(&exit_all_event_);
    	event_cancel(&jump_to_event_);
    }
    
    void CDungeon::Initialize()
    {
    	deadEvent = NULL;
    	// <Factor>
    	exit_all_event_ = NULL;
    	jump_to_event_ = NULL;
    	regen_id_ = 0;
    
    	m_iMobKill = 0;
    	m_iStoneKill = 0;
    	m_bUsePotion = false;
    	m_bUseRevive = false;
    
    	m_iMonsterCount = 0;
    
    	m_bExitAllAtEliminate = false;
    	m_bWarpAtEliminate = false;
    
    	m_iWarpDelay = 0;
    	m_lWarpMapIndex = 0;
    	m_lWarpX = 0;
    	m_lWarpY = 0;
    
    	m_stRegenFile = "";
    
    	m_pParty = NULL;
    }
    
    void CDungeon::SetFlag(std::string name, int value)
    {
    	itertype(m_map_Flag) it =  m_map_Flag.find(name);
    	if (it != m_map_Flag.end())
    		it->second = value;
    	else
    		m_map_Flag.insert(make_pair(name, value));
    }
    
    int CDungeon::GetFlag(std::string name)
    {
    	itertype(m_map_Flag) it =  m_map_Flag.find(name);
    	if (it != m_map_Flag.end())
    		return it->second;
    	else
    		return 0;
    }
    
    struct FSendDestPosition
    {
    	FSendDestPosition(long x, long y)
    	{
    		p1.bHeader = HEADER_GC_DUNGEON;
    		p1.subheader = DUNGEON_SUBHEADER_GC_DESTINATION_POSITION;
    		p2.x = x;
    		p2.y = y;
    		p1.size = sizeof(p1)+sizeof(p2);
    	}
    
    	void operator()(LPCHARACTER ch)
    	{
    		ch->GetDesc()->BufferedPacket(&p1, sizeof(TPacketGCDungeon));
    		ch->GetDesc()->Packet(&p2, sizeof(TPacketGCDungeonDestPosition));
    	}
    
    	TPacketGCDungeon p1;
    	TPacketGCDungeonDestPosition p2;
    };
    
    void CDungeon::SendDestPositionToParty(LPPARTY pParty, long x, long y)
    {
    	if (m_map_pkParty.find(pParty) == m_map_pkParty.end())
    	{
    		sys_err("PARTY %u not in DUNGEON %d", pParty->GetLeaderPID(), m_lMapIndex);
    		return;
    	}
    
    	FSendDestPosition f(x, y);
    	pParty->ForEachNearMember(f);
    }
    
    struct FWarpToDungeon
    {
    	FWarpToDungeon(long lMapIndex, LPDUNGEON d)
    		: m_lMapIndex(lMapIndex), m_pkDungeon(d)
    		{
    			LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(lMapIndex);
    			m_x = pkSectreeMap->m_setting.posSpawn.x;
    			m_y = pkSectreeMap->m_setting.posSpawn.y;
    		}
    
    	void operator () (LPCHARACTER ch)
    	{
    		ch->SaveExitLocation();
    		ch->WarpSet(m_x, m_y, m_lMapIndex);
    		//m_pkDungeon->IncPartyMember(ch->GetParty());
    	}
    
    	long m_lMapIndex;
    	long m_x;
    	long m_y;
    	LPDUNGEON m_pkDungeon;
    };
    
    void CDungeon::Join(LPCHARACTER ch)
    {
    	if (SECTREE_MANAGER::instance().GetMap(m_lMapIndex) == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return;
    	}
    	FWarpToDungeon(m_lMapIndex, this) (ch);
    }
    
    void CDungeon::JoinParty(LPPARTY pParty)
    {
    	pParty->SetDungeon(this); // @warme011 the begin of the nightmare
    	m_map_pkParty.insert(std::make_pair(pParty,0));
    
    	if (SECTREE_MANAGER::instance().GetMap(m_lMapIndex) == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return;
    	}
    	FWarpToDungeon f(m_lMapIndex, this);
    	pParty->ForEachOnlineMember(f);
    	//sys_log(0, "DUNGEON-PARTY join %p %p", this, pParty);
    }
    
    void CDungeon::QuitParty(LPPARTY pParty)
    {
    	pParty->SetDungeon(NULL);
    	//sys_log(0, "DUNGEON-PARTY quit %p %p", this, pParty);
    	TPartyMap::iterator it = m_map_pkParty.find(pParty); // @warme011 boom! crash!
    
    	if (it != m_map_pkParty.end())
    		m_map_pkParty.erase(it);
    }
    
    EVENTINFO(dungeon_id_info)
    {
    	CDungeon::IdType dungeon_id;
    
    	dungeon_id_info()
    	: dungeon_id(0)
    	{
    	}
    };
    
    EVENTFUNC(dungeon_dead_event)
    {
    	dungeon_id_info* info = dynamic_cast<dungeon_id_info*>( event->info );
    
    	if ( info == NULL )
    	{
    		sys_err( "dungeon_dead_event> <Factor> Null pointer" );
    		return 0;
    	}
    
    	LPDUNGEON pDungeon = CDungeonManager::instance().Find(info->dungeon_id);
    	if (pDungeon == NULL) {
    		return 0;
    	}
    
    	pDungeon->deadEvent = NULL;
    
    	CDungeonManager::instance().Destroy(info->dungeon_id);
    	return 0;
    }
    
    void CDungeon::IncMember(LPCHARACTER ch)
    {
    	if (m_set_pkCharacter.find(ch) == m_set_pkCharacter.end())
    		m_set_pkCharacter.insert(ch);
    
    	event_cancel(&deadEvent);
    }
    
    void CDungeon::DecMember(LPCHARACTER ch)
    {
    	itertype(m_set_pkCharacter) it = m_set_pkCharacter.find(ch);
    
    	if (it == m_set_pkCharacter.end()) {
    		return;
    	}
    
    	m_set_pkCharacter.erase(it);
    
    	if (m_set_pkCharacter.empty())
    	{
    		dungeon_id_info* info = AllocEventInfo<dungeon_id_info>();
    		info->dungeon_id = m_id;
    
    		event_cancel(&deadEvent);
    		deadEvent = event_create(dungeon_dead_event, info, PASSES_PER_SEC(10));
    	}
    }
    
    void CDungeon::IncPartyMember(LPPARTY pParty, LPCHARACTER ch)
    {
    	//sys_log(0, "DUNGEON-PARTY inc %p %p", this, pParty);
    	TPartyMap::iterator it = m_map_pkParty.find(pParty);
    
    	if (it != m_map_pkParty.end())
    		it->second++;
    	else
    		m_map_pkParty.insert(std::make_pair(pParty,1));
    
    	IncMember(ch);
    }
    
    void CDungeon::DecPartyMember(LPPARTY pParty, LPCHARACTER ch)
    {
    	//sys_log(0, "DUNGEON-PARTY dec %p %p", this, pParty);
    	TPartyMap::iterator it = m_map_pkParty.find(pParty);
    
    	if (it == m_map_pkParty.end())
    		sys_err("cannot find party");
    	else
    	{
    		it->second--;
    
    		if (it->second == 0)
    			QuitParty(pParty);
    	}
    
    	DecMember(ch);
    }
    
    struct FWarpToPosition
    {
    	long lMapIndex;
    	long x;
    	long y;
    	FWarpToPosition(long lMapIndex, long x, long y)
    		: lMapIndex(lMapIndex), x(x), y(y)
    		{}
    
    	void operator()(LPENTITY ent)
    	{
    		if (!ent->IsType(ENTITY_CHARACTER)) {
    			return;
    		}
    		LPCHARACTER ch = (LPCHARACTER)ent;
    		if (!ch->IsPC()) {
    			return;
    		}
    		if (ch->GetMapIndex() == lMapIndex)
    		{
    			ch->Show(lMapIndex, x, y, 0);
    			ch->Stop();
    		}
    		else
    		{
    			ch->WarpSet(x,y,lMapIndex);
    		}
    	}
    };
    
    struct FWarpToPositionForce
    {
    	long lMapIndex;
    	long x;
    	long y;
    	FWarpToPositionForce(long lMapIndex, long x, long y)
    		: lMapIndex(lMapIndex), x(x), y(y)
    		{}
    
    	void operator()(LPENTITY ent)
    	{
    		if (!ent->IsType(ENTITY_CHARACTER)) {
    			return;
    		}
    		LPCHARACTER ch = (LPCHARACTER)ent;
    		if (!ch->IsPC()) {
    			return;
    		}
    		ch->WarpSet(x,y,lMapIndex);
    	}
    };
    
    void CDungeon::JumpAll(long lFromMapIndex, int x, int y)
    {
    	x *= 100;
    	y *= 100;
    
    	LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(lFromMapIndex);
    
    	if (!pMap)
    	{
    		sys_err("cannot find map by index %d", lFromMapIndex);
    		return;
    	}
    
    	FWarpToPosition f(m_lMapIndex, x, y);
    
    	// <Factor> SECTREE::for_each -> SECTREE::for_each_entity
    	pMap->for_each(f);
    }
    
    void CDungeon::WarpAll(long lFromMapIndex, int x, int y)
    {
    	x *= 100;
    	y *= 100;
    
    	LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(lFromMapIndex);
    
    	if (!pMap)
    	{
    		sys_err("cannot find map by index %d", lFromMapIndex);
    		return;
    	}
    
    	FWarpToPositionForce f(m_lMapIndex, x, y);
    
    	// <Factor> SECTREE::for_each -> SECTREE::for_each_entity
    	pMap->for_each(f);
    }
    
    void CDungeon::JumpParty(LPPARTY pParty, long lFromMapIndex, int x, int y)
    {
    	x *= 100;
    	y *= 100;
    
    	LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(lFromMapIndex);
    
    	if (!pMap)
    	{
    		sys_err("cannot find map by index %d", lFromMapIndex);
    		return;
    	}
    
    	if (pParty->GetDungeon_for_Only_party() == NULL)
    	{
    		if (m_pParty == NULL)
    		{
    			m_pParty = pParty;
    		}
    		else if (m_pParty != pParty)
    		{
    			sys_err ("Dungeon already has party. Another party cannot jump in dungeon : index %d", GetMapIndex());
    			return;
    		}
    		pParty->SetDungeon_for_Only_party (this);
    	}
    
    	FWarpToPosition f(m_lMapIndex, x, y);
    
    	pParty->ForEachOnMapMember(f, lFromMapIndex);
    }
    
    void CDungeon::SetPartyNull()
    {
    	m_pParty = NULL;
    }
    
    
    void CDungeonManager::Destroy(CDungeon::IdType dungeon_id)
    {
    	sys_log(0, "DUNGEON destroy : map index %u", dungeon_id);
    	LPDUNGEON pDungeon = Find(dungeon_id);
    	if (pDungeon == NULL) {
    		return;
    	}
    	m_map_pkDungeon.erase(dungeon_id);
    
    	long lMapIndex = pDungeon->m_lMapIndex;
    	m_map_pkMapDungeon.erase(lMapIndex);
    
    	DWORD server_timer_arg = lMapIndex;
    	quest::CQuestManager::instance().CancelServerTimers(server_timer_arg);
    
    	SECTREE_MANAGER::instance().DestroyPrivateMap(lMapIndex);
    	M2_DELETE(pDungeon);
    }
    
    LPDUNGEON CDungeonManager::Find(CDungeon::IdType dungeon_id)
    {
    	itertype(m_map_pkDungeon) it = m_map_pkDungeon.find(dungeon_id);
    	if (it != m_map_pkDungeon.end())
    		return it->second;
    	return NULL;
    }
    
    LPDUNGEON CDungeonManager::FindByMapIndex(long lMapIndex)
    {
    	itertype(m_map_pkMapDungeon) it = m_map_pkMapDungeon.find(lMapIndex);
    	if (it != m_map_pkMapDungeon.end()) {
    		return it->second;
    	}
    	return NULL;
    }
    
    LPDUNGEON CDungeonManager::Create(long lOriginalMapIndex)
    {
    	DWORD lMapIndex = SECTREE_MANAGER::instance().CreatePrivateMap(lOriginalMapIndex);
    
    	if (!lMapIndex)
    	{
    		sys_log( 0, "Fail to Create Dungeon : OrginalMapindex %d NewMapindex %d", lOriginalMapIndex, lMapIndex );
    		return NULL;
    	}
    
    	// <Factor> TODO: Change id assignment, or drop it
    	CDungeon::IdType id = next_id_++;
    	while (Find(id) != NULL) {
    		id = next_id_++;
    	}
    
    	LPDUNGEON pDungeon = M2_NEW CDungeon(id, lOriginalMapIndex, lMapIndex);
    
    	m_map_pkDungeon.insert(std::make_pair(id, pDungeon));
    	m_map_pkMapDungeon.insert(std::make_pair(lMapIndex, pDungeon));
    
    	return pDungeon;
    }
    
    CDungeonManager::CDungeonManager()
    	: next_id_(0)
    {
    }
    
    CDungeonManager::~CDungeonManager()
    {
    }
    
    void CDungeon::UniqueSetMaxHP(const std::string& key, int iMaxHP)
    {
    	TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
    	if (it == m_map_UniqueMob.end())
    	{
    		sys_err("Unknown Key : %s", key.c_str());
    		return;
    	}
    	it->second->SetMaxHP(iMaxHP);
    }
    
    void CDungeon::UniqueSetHP(const std::string& key, int iHP)
    {
    	TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
    	if (it == m_map_UniqueMob.end())
    	{
    		sys_err("Unknown Key : %s", key.c_str());
    		return;
    	}
    	it->second->SetHP(iHP);
    }
    
    void CDungeon::UniqueSetDefGrade(const std::string& key, int iGrade)
    {
    	TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
    	if (it == m_map_UniqueMob.end())
    	{
    		sys_err("Unknown Key : %s", key.c_str());
    		return;
    	}
    	it->second->PointChange(POINT_DEF_GRADE,iGrade - it->second->GetPoint(POINT_DEF_GRADE));
    }
    
    void CDungeon::SpawnMoveUnique(const char* key, DWORD vnum, const char* pos_from, const char* pos_to)
    {
    	TAreaMap::iterator it_to = m_map_Area.find(pos_to);
    	if (it_to == m_map_Area.end())
    	{
    		sys_err("Wrong position string : %s", pos_to);
    		return;
    	}
    
    	TAreaMap::iterator it_from = m_map_Area.find(pos_from);
    	if (it_from == m_map_Area.end())
    	{
    		sys_err("Wrong position string : %s", pos_from);
    		return;
    	}
    
    	TAreaInfo & ai = it_from->second;
    	TAreaInfo & ai_to = it_to->second;
    	int dir = ai.dir;
    	if (dir==-1)
    		dir = number(0,359);
    
    	LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (pkSectreeMap == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return;
    	}
    	for (int i=0;i<100;i++)
    	{
    		int dx = number(ai.sx, ai.ex);
    		int dy = number(ai.sy, ai.ey);
    		int tx = number(ai_to.sx, ai_to.ex);
    		int ty = number(ai_to.sy, ai_to.ey);
    
    		LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+dx, pkSectreeMap->m_setting.iBaseY+dy, 0, false, dir);
    
    		if (ch)
    		{
    			m_map_UniqueMob.insert(make_pair(std::string(key), ch));
    			ch->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
    			ch->SetDungeon(this);
    
    			if (ch->Goto(pkSectreeMap->m_setting.iBaseX+tx, pkSectreeMap->m_setting.iBaseY+ty))
    				ch->SendMovePacket(FUNC_WAIT, 0, 0, 0, 0);
    		}
    		else
    		{
    			sys_err("Cannot spawn at %d %d", pkSectreeMap->m_setting.iBaseX+((ai.sx+ai.ex)>>1), pkSectreeMap->m_setting.iBaseY+((ai.sy+ai.ey)>>1));
    		}
    	}
    
    }
    
    void CDungeon::SpawnUnique(const char* key, DWORD vnum, const char* pos)
    {
    	TAreaMap::iterator it = m_map_Area.find(pos);
    	if (it == m_map_Area.end())
    	{
    		sys_err("Wrong position string : %s", pos);
    		return;
    	}
    
    	TAreaInfo & ai = it->second;
    	int dir = ai.dir;
    	if (dir==-1)
    		dir = number(0,359);
    
    	LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (pkSectreeMap == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return;
    	}
    	for (int i=0;i<100;i++)
    	{
    		int dx = number(ai.sx, ai.ex);
    		int dy = number(ai.sy, ai.ey);
    
    		LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+dx, pkSectreeMap->m_setting.iBaseY+dy, 0, false, dir);
    
    		if (ch)
    		{
    			m_map_UniqueMob.insert(make_pair(std::string(key), ch));
    			ch->SetDungeon(this);
    			ch->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
    			break;
    		}
    		else
    		{
    			sys_err("Cannot spawn at %d %d", pkSectreeMap->m_setting.iBaseX+((ai.sx+ai.ex)>>1), pkSectreeMap->m_setting.iBaseY+((ai.sy+ai.ey)>>1));
    		}
    	}
    }
    
    void CDungeon::SetUnique(const char* key, DWORD vid)
    {
    	LPCHARACTER ch = CHARACTER_MANAGER::instance().Find(vid);
    	if (ch)
    	{
    		m_map_UniqueMob.insert(make_pair(std::string(key), ch));
    		ch->AddAffect(AFFECT_DUNGEON_UNIQUE, POINT_NONE, 0, AFF_DUNGEON_UNIQUE, 65535, 0, true);
    	}
    }
    
    void CDungeon::SpawnStoneDoor(const char* key, const char* pos)
    {
    	SpawnUnique(key, 13001, pos);
    }
    
    void CDungeon::SpawnWoodenDoor(const char* key, const char* pos)
    {
    	SpawnUnique(key, 13000, pos);
    	UniqueSetMaxHP(key, 10000);
    	UniqueSetHP(key, 10000);
    	UniqueSetDefGrade(key, 300);
    }
    
    void CDungeon::PurgeUnique(const std::string& key)
    {
    	TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
    	if (it == m_map_UniqueMob.end())
    	{
    		sys_err("Unknown Key or Dead: %s", key.c_str());
    		return;
    	}
    	LPCHARACTER ch = it->second;
    	m_map_UniqueMob.erase(it);
    	M2_DESTROY_CHARACTER(ch);
    }
    
    void CDungeon::KillUnique(const std::string& key)
    {
    	TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
    	if (it == m_map_UniqueMob.end())
    	{
    		sys_err("Unknown Key or Dead: %s", key.c_str());
    		return;
    	}
    	LPCHARACTER ch = it->second;
    	m_map_UniqueMob.erase(it);
    	ch->Dead();
    }
    
    DWORD CDungeon::GetUniqueVid(const std::string& key)
    {
    	TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
    	if (it == m_map_UniqueMob.end())
    	{
    		sys_err("Unknown Key or Dead: %s", key.c_str());
    		return 0;
    	}
    	LPCHARACTER ch = it->second;
    	return ch->GetVID();
    }
    
    float CDungeon::GetUniqueHpPerc(const std::string& key)
    {
    	TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
    	if (it == m_map_UniqueMob.end())
    	{
    		sys_err("Unknown Key : %s", key.c_str());
    		return false;
    	}
    	return (100.f*it->second->GetHP())/it->second->GetMaxHP();
    }
    
    void CDungeon::DeadCharacter(LPCHARACTER ch)
    {
    	if (!ch->IsPC())
    	{
    		TUniqueMobMap::iterator it = m_map_UniqueMob.begin();
    		while (it!=m_map_UniqueMob.end())
    		{
    			if (it->second == ch)
    			{
    				//sys_log(0,"Dead unique %s", it->first.c_str());
    				m_map_UniqueMob.erase(it);
    				break;
    			}
    			++it;
    		}
    	}
    }
    
    bool CDungeon::IsUniqueDead(const std::string& key)
    {
    	TUniqueMobMap::iterator it = m_map_UniqueMob.find(key);
    
    	if (it == m_map_UniqueMob.end())
    	{
    		sys_err("Unknown Key or Dead : %s", key.c_str());
    		return true;
    	}
    
    	return it->second->IsDead();
    }
    
    void CDungeon::Spawn(DWORD vnum, const char* pos)
    {
    	//sys_log(0,"DUNGEON Spawn %u %s", vnum, pos);
    	TAreaMap::iterator it = m_map_Area.find(pos);
    
    	if (it == m_map_Area.end())
    	{
    		sys_err("Wrong position string : %s", pos);
    		return;
    	}
    
    	TAreaInfo & ai = it->second;
    	int dir = ai.dir;
    	if (dir==-1)
    		dir = number(0,359);
    
    	LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (pkSectreeMap == NULL)
    	{
    		sys_err("cannot find map by index %d", m_lMapIndex);
    		return;
    	}
    	int dx = number(ai.sx, ai.ex);
    	int dy = number(ai.sy, ai.ey);
    
    	LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+dx, pkSectreeMap->m_setting.iBaseY+dy, 0, false, dir);
    	if (ch)
    		ch->SetDungeon(this);
    }
    
    LPCHARACTER CDungeon::SpawnMob(DWORD vnum, int x, int y, int dir)
    {
    	LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (pkSectreeMap == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return NULL;
    	}
    	sys_log(0, "CDungeon::SpawnMob %u %d %d", vnum, x,  y);
    
    	LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+x*100, pkSectreeMap->m_setting.iBaseY+y*100, 0, false, dir == 0 ? -1 : (dir - 1) * 45);
    
    	if (ch)
    	{
    		ch->SetDungeon(this);
    		sys_log(0, "CDungeon::SpawnMob name %s", ch->GetName());
    	}
    
    	return ch;
    }
    
    LPCHARACTER CDungeon::SpawnMob_ac_dir(DWORD vnum, int x, int y, int dir)
    {
    	LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (pkSectreeMap == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return NULL;
    	}
    	sys_log(0, "CDungeon::SpawnMob %u %d %d", vnum, x,  y);
    
    	LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+x*100, pkSectreeMap->m_setting.iBaseY+y*100, 0, false, dir);
    
    	if (ch)
    	{
    		ch->SetDungeon(this);
    		sys_log(0, "CDungeon::SpawnMob name %s", ch->GetName());
    	}
    
    	return ch;
    }
    
    void CDungeon::SpawnNameMob(DWORD vnum, int x, int y, const char* name)
    {
    	LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (pkSectreeMap == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return;
    	}
    
    	LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+x, pkSectreeMap->m_setting.iBaseY+y, 0, false, -1);
    	if (ch)
    	{
    		ch->SetName(name);
    		ch->SetDungeon(this);
    	}
    }
    
    void CDungeon::SpawnGotoMob(long lFromX, long lFromY, long lToX, long lToY)
    {
    	const int MOB_GOTO_VNUM = 20039;
    
    	LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (pkSectreeMap == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return;
    	}
    
    	sys_log(0, "SpawnGotoMob %d %d to %d %d", lFromX, lFromY, lToX, lToY);
    
    	lFromX = pkSectreeMap->m_setting.iBaseX+lFromX*100;
    	lFromY = pkSectreeMap->m_setting.iBaseY+lFromY*100;
    
    	LPCHARACTER ch = CHARACTER_MANAGER::instance().SpawnMob(MOB_GOTO_VNUM, m_lMapIndex, lFromX, lFromY, 0, false, -1);
    
    	if (ch)
    	{
    		char buf[30+1];
    		snprintf(buf, sizeof(buf), ". %ld %ld", lToX, lToY);
    
    		ch->SetName(buf);
    		ch->SetDungeon(this);
    	}
    }
    
    LPCHARACTER CDungeon::SpawnGroup(DWORD vnum, long x, long y, float radius, bool bAggressive, int count)
    {
    	LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (pkSectreeMap == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return NULL;
    	}
    
    	int iRadius = (int) radius;
    
    	int sx = pkSectreeMap->m_setting.iBaseX + x - iRadius;
    	int sy = pkSectreeMap->m_setting.iBaseY + y - iRadius;
    	int ex = sx + iRadius;
    	int ey = sy + iRadius;
    
    	LPCHARACTER ch = NULL;
    
    	while (count--)
    	{
    		LPCHARACTER chLeader = CHARACTER_MANAGER::instance().SpawnGroup(vnum, m_lMapIndex, sx, sy, ex, ey, NULL, bAggressive, this);
    		if (chLeader && !ch)
    			ch = chLeader;
    	}
    
    	return ch;
    }
    
    void CDungeon::SpawnRegen(const char* filename, bool bOnce)
    {
    	if (!filename)
    	{
    		sys_err("CDungeon::SpawnRegen(filename=NULL, bOnce=%d) - m_lMapIndex[%d]", bOnce, m_lMapIndex);
    		return;
    	}
    
    	LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (!pkSectreeMap)
    	{
    		sys_err("CDungeon::SpawnRegen(filename=%s, bOnce=%d) - m_lMapIndex[%d]", filename, bOnce, m_lMapIndex);
    		return;
    	}
    	regen_do(filename, m_lMapIndex, pkSectreeMap->m_setting.iBaseX, pkSectreeMap->m_setting.iBaseY, this, bOnce);
    }
    
    void CDungeon::AddRegen(LPREGEN regen)
    {
    	regen->id = regen_id_++;
    	m_regen.push_back(regen);
    }
    
    void CDungeon::ClearRegen()
    {
    	for (itertype(m_regen) it = m_regen.begin(); it != m_regen.end(); ++it)
    	{
    		LPREGEN regen = *it;
    
    		event_cancel(&regen->event);
    		M2_DELETE(regen);
    	}
    	m_regen.clear();
    }
    
    bool CDungeon::IsValidRegen(LPREGEN regen, size_t regen_id) {
    	itertype(m_regen) it = std::find(m_regen.begin(), m_regen.end(), regen);
    	if (it == m_regen.end()) {
    		return false;
    	}
    	LPREGEN found = *it;
    	return (found->id == regen_id);
    }
    
    void CDungeon::SpawnMoveGroup(DWORD vnum, const char* pos_from, const char* pos_to, int count)
    {
    	TAreaMap::iterator it_to = m_map_Area.find(pos_to);
    
    	if (it_to == m_map_Area.end())
    	{
    		sys_err("Wrong position string : %s", pos_to);
    		return;
    	}
    
    	TAreaMap::iterator it_from = m_map_Area.find(pos_from);
    
    	if (it_from == m_map_Area.end())
    	{
    		sys_err("Wrong position string : %s", pos_from);
    		return;
    	}
    
    	TAreaInfo & ai = it_from->second;
    	TAreaInfo & ai_to = it_to->second;
    	int dir = ai.dir;
    
    	if (dir == -1)
    		dir = number(0,359);
    
    	LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (pkSectreeMap == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return;
    	}
    
    	while (count--)
    	{
    		int tx = number(ai_to.sx, ai_to.ex)+pkSectreeMap->m_setting.iBaseX;
    		int ty = number(ai_to.sy, ai_to.ey)+pkSectreeMap->m_setting.iBaseY;
    		CHARACTER_MANAGER::instance().SpawnMoveGroup(vnum, m_lMapIndex, pkSectreeMap->m_setting.iBaseX+ai.sx, pkSectreeMap->m_setting.iBaseY+ai.sy, pkSectreeMap->m_setting.iBaseX+ai.ex, pkSectreeMap->m_setting.iBaseY+ai.ey, tx, ty, NULL, true);
    	}
    }
    
    namespace
    {
    	// DUNGEON_KILL_ALL_BUG_FIX
    	struct FKillSectree
    	{
    		void operator () (LPENTITY ent)
    		{
    			if (ent->IsType(ENTITY_CHARACTER))
    			{
    				LPCHARACTER ch = (LPCHARACTER) ent;
    
    #ifdef NEW_PET_SYSTEM
    				if (!ch->IsPC() && !ch->IsPet() && !ch->IsNewPet())
    #else
    				if (!ch->IsPC() && !ch->IsPet())
    #endif
    					ch->Dead();
    			}
    		}
    	};
    	// END_OF_DUNGEON_KILL_ALL_BUG_FIX
    
    	struct FPurgeSectree
    	{
    		void operator () (LPENTITY ent)
    		{
    			if (ent->IsType(ENTITY_CHARACTER))
    			{
    				LPCHARACTER ch = (LPCHARACTER) ent;
    
    #ifdef NEW_PET_SYSTEM
    				if (!ch->IsPC() && !ch->IsPet() && !ch->IsNewPet())
    #else
    				if (!ch->IsPC() && !ch->IsPet())
    #endif
    				{
    					M2_DESTROY_CHARACTER(ch);
    				}
    			}
    			else if (ent->IsType(ENTITY_ITEM))
    			{
    				LPITEM item = (LPITEM) ent;
    				M2_DESTROY_ITEM(item);
    			}
    			else
    				sys_err("unknown entity type %d is in dungeon", ent->GetType());
    		}
    	};
    }
    
    // DUNGEON_KILL_ALL_BUG_FIX
    void CDungeon::KillAll()
    {
    	LPSECTREE_MAP pkMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (pkMap == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return;
    	}
    	FKillSectree f;
    	pkMap->for_each(f);
    }
    // END_OF_DUNGEON_KILL_ALL_BUG_FIX
    
    void CDungeon::Purge()
    {
    	LPSECTREE_MAP pkMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    	if (pkMap == NULL) {
    		sys_err("CDungeon: SECTREE_MAP not found for #%ld", m_lMapIndex);
    		return;
    	}
    	FPurgeSectree f;
    	pkMap->for_each(f);
    }
    
    void CDungeon::IncKillCount(LPCHARACTER pkKiller, LPCHARACTER pkVictim)
    {
    	if (pkVictim->IsStone())
    		m_iStoneKill ++;
    	else
    		m_iMobKill ++;
    }
    
    void CDungeon::UsePotion(LPCHARACTER ch)
    {
    	m_bUsePotion = true;
    }
    
    void CDungeon::UseRevive(LPCHARACTER ch)
    {
    	m_bUseRevive = true;
    }
    
    bool CDungeon::IsUsePotion()
    {
    	return m_bUsePotion;
    }
    
    bool CDungeon::IsUseRevive()
    {
    	return m_bUseRevive;
    }
    
    int CDungeon::GetKillMobCount()
    {
    	return m_iMobKill;
    }
    int CDungeon::GetKillStoneCount()
    {
    	return m_iStoneKill;
    }
    
    struct FCountMonster
    {
    	int n;
    	FCountMonster() : n(0) {};
    	void operator()(LPENTITY ent)
    	{
    		if (ent->IsType(ENTITY_CHARACTER))
    		{
    			LPCHARACTER ch = (LPCHARACTER) ent;
    			if (!ch->IsPC())
    				n++;
    		}
    	}
    };
    
    int CDungeon::CountRealMonster()
    {
    	LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lOrigMapIndex);
    
    	if (!pMap)
    	{
    		sys_err("cannot find map by index %d", m_lOrigMapIndex);
    		return 0;
    	}
    
    	FCountMonster f;
    
    	// <Factor> SECTREE::for_each -> SECTREE::for_each_entity
    	pMap->for_each(f);
    	return f.n;
    }
    
    struct FExitDungeon
    {
    	void operator()(LPENTITY ent)
    	{
    		if (ent->IsType(ENTITY_CHARACTER))
    		{
    			LPCHARACTER ch = (LPCHARACTER) ent;
    
    			if (ch->IsPC())
    				ch->ExitToSavedLocation();
    		}
    	}
    };
    
    void CDungeon::ExitAll()
    {
    	LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    
    	if (!pMap)
    	{
    		sys_err("cannot find map by index %d", m_lMapIndex);
    		return;
    	}
    
    	FExitDungeon f;
    
    	// <Factor> SECTREE::for_each -> SECTREE::for_each_entity
    	pMap->for_each(f);
    }
    
    // DUNGEON_NOTICE
    namespace
    {
    	struct FNotice
    	{
    		FNotice(const char * psz) : m_psz(psz)
    		{
    		}
    
    		void operator() (LPENTITY ent)
    		{
    			if (ent->IsType(ENTITY_CHARACTER))
    			{
    				LPCHARACTER ch = (LPCHARACTER) ent;
    				ch->ChatPacket(CHAT_TYPE_NOTICE, "%s", m_psz);
    			}
    		}
    
    		const char * m_psz;
    	};
    }
    
    void CDungeon::Notice(const char* msg)
    {
    	sys_log(0, "XXX Dungeon Notice %p %s", this, msg);
    	LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    
    	if (!pMap)
    	{
    		sys_err("cannot find map by index %d", m_lMapIndex);
    		return;
    	}
    
    	FNotice f(msg);
    	pMap->for_each(f);
    }
    // END_OF_DUNGEON_NOTICE
    
    struct FExitDungeonToStartPosition
    {
    	void operator () (LPENTITY ent)
    	{
    		if (ent->IsType(ENTITY_CHARACTER))
    		{
    			LPCHARACTER ch = (LPCHARACTER) ent;
    
    			if (ch->IsPC())
    			{
    				PIXEL_POSITION posWarp;
    
    				// 현재 맵 인덱스를 넣는 것이 아니라 시작하는 맵 인덱스를 넣는다.
    				if (SECTREE_MANAGER::instance().GetRecallPositionByEmpire(g_start_map[ch->GetEmpire()], ch->GetEmpire(), posWarp))
    					ch->WarpSet(posWarp.x, posWarp.y);
    				else
    					ch->ExitToSavedLocation();
    			}
    		}
    	}
    };
    
    void CDungeon::ExitAllToStartPosition()
    {
    	LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    
    	if (!pMap)
    	{
    		sys_err("cannot find map by index %d", m_lMapIndex);
    		return;
    	}
    
    	FExitDungeonToStartPosition f;
    
    	// <Factor> SECTREE::for_each -> SECTREE::for_each_entity
    	pMap->for_each(f);
    }
    
    EVENTFUNC(dungeon_jump_to_event)
    {
    	dungeon_id_info * info = dynamic_cast<dungeon_id_info *>(event->info);
    
    	if ( info == NULL )
    	{
    		sys_err( "dungeon_jump_to_event> <Factor> Null pointer" );
    		return 0;
    	}
    
    	LPDUNGEON pDungeon = CDungeonManager::instance().Find(info->dungeon_id);
    	pDungeon->jump_to_event_ = NULL;
    
    	if (pDungeon)
    		pDungeon->JumpToEliminateLocation();
    	else
    		sys_err("cannot find dungeon with map index %u", info->dungeon_id);
    
    	return 0;
    }
    
    EVENTFUNC(dungeon_exit_all_event)
    {
    	dungeon_id_info * info = dynamic_cast<dungeon_id_info *>(event->info);
    
    	if ( info == NULL )
    	{
    		sys_err( "dungeon_exit_all_event> <Factor> Null pointer" );
    		return 0;
    	}
    
    	LPDUNGEON pDungeon = CDungeonManager::instance().Find(info->dungeon_id);
    	pDungeon->exit_all_event_ = NULL;
    
    	if (pDungeon)
    		pDungeon->ExitAll();
    
    	return 0;
    }
    
    void CDungeon::CheckEliminated()
    {
    	if (m_iMonsterCount > 0)
    		return;
    
    	if (m_bExitAllAtEliminate)
    	{
    		sys_log(0, "CheckEliminated: exit");
    		m_bExitAllAtEliminate = false;
    
    		if (m_iWarpDelay)
    		{
    			dungeon_id_info* info = AllocEventInfo<dungeon_id_info>();
    			info->dungeon_id = m_id;
    
    			event_cancel(&exit_all_event_);
    			exit_all_event_ = event_create(dungeon_exit_all_event, info, PASSES_PER_SEC(m_iWarpDelay));
    		}
    		else
    		{
    			ExitAll();
    		}
    	}
    	else if (m_bWarpAtEliminate)
    	{
    		sys_log(0, "CheckEliminated: warp");
    		m_bWarpAtEliminate = false;
    
    		if (m_iWarpDelay)
    		{
    			dungeon_id_info* info = AllocEventInfo<dungeon_id_info>();
    			info->dungeon_id = m_id;
    
    			event_cancel(&jump_to_event_);
    			jump_to_event_ = event_create(dungeon_jump_to_event, info, PASSES_PER_SEC(m_iWarpDelay));
    		}
    		else
    		{
    			JumpToEliminateLocation();
    		}
    	}
    	else
    		sys_log(0, "CheckEliminated: none");
    }
    
    void CDungeon::SetExitAllAtEliminate(long time)
    {
    	sys_log(0, "SetExitAllAtEliminate: time %d", time);
    	m_bExitAllAtEliminate = true;
    	m_iWarpDelay = time;
    }
    
    void CDungeon::SetWarpAtEliminate(long time, long lMapIndex, int x, int y, const char* regen_file)
    {
    	m_bWarpAtEliminate = true;
    	m_iWarpDelay = time;
    	m_lWarpMapIndex = lMapIndex;
    	m_lWarpX = x;
    	m_lWarpY = y;
    
    	if (!regen_file || !*regen_file)
    		m_stRegenFile.clear();
    	else
    		m_stRegenFile = regen_file;
    
    	sys_log(0, "SetWarpAtEliminate: time %d map %d %dx%d regenfile %s", time, lMapIndex, x, y, m_stRegenFile.c_str());
    }
    
    void CDungeon::JumpToEliminateLocation()
    {
    	LPDUNGEON pDungeon = CDungeonManager::instance().FindByMapIndex(m_lWarpMapIndex);
    
    	if (pDungeon)
    	{
    		pDungeon->JumpAll(m_lMapIndex, m_lWarpX, m_lWarpY);
    
    		if (!m_stRegenFile.empty())
    		{
    			pDungeon->SpawnRegen(m_stRegenFile.c_str());
    			m_stRegenFile.clear();
    		}
    	}
    	else
    	{
    		// 일반 맵으로 워프
    		LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    
    		if (!pMap)
    		{
    			sys_err("no map by index %d", m_lMapIndex);
    			return;
    		}
    
    		FWarpToPosition f(m_lWarpMapIndex, m_lWarpX * 100, m_lWarpY * 100);
    
    		// <Factor> SECTREE::for_each -> SECTREE::for_each_entity
    		pMap->for_each(f);
    	}
    }
    
    struct FNearPosition
    {
    	long x;
    	long y;
    	int dist;
    	bool ret;
    
    	FNearPosition(long x, long y, int d) :
    		x(x), y(y), dist(d), ret(true)
    	{
    	}
    
    	void operator()(LPENTITY ent)
    	{
    		if (ret == false)
    			return;
    
    		if (ent->IsType(ENTITY_CHARACTER))
    		{
    			LPCHARACTER ch = (LPCHARACTER) ent;
    
    			if (ch->IsPC())
    			{
    				if (DISTANCE_APPROX(ch->GetX() - x * 100, ch->GetY() - y * 100) > dist * 100)
    					ret = false;
    			}
    		}
    	}
    };
    
    bool CDungeon::IsAllPCNearTo(int x, int y, int dist)
    {
    	LPSECTREE_MAP pMap = SECTREE_MANAGER::instance().GetMap(m_lMapIndex);
    
    	if (!pMap)
    	{
    		sys_err("cannot find map by index %d", m_lMapIndex);
    		return false;
    	}
    
    	FNearPosition f(x, y, dist);
    
    	// <Factor> SECTREE::for_each -> SECTREE::for_each_entity
    	pMap->for_each(f);
    
    	return f.ret;
    }
    
    void CDungeon::CreateItemGroup (std::string& group_name, ItemGroup& item_group)
    {
    	m_map_ItemGroup.insert (ItemGroupMap::value_type (group_name, item_group));
    }
    
    const CDungeon::ItemGroup* CDungeon::GetItemGroup (std::string& group_name)
    {
    	ItemGroupMap::iterator it = m_map_ItemGroup.find (group_name);
    	if (it != m_map_ItemGroup.end())
    		return &(it->second);
    	else
    		return NULL;
    }

     

    so i removed it i will try if is work now if not i leave here my .cpp files 

     

    Questmanager.cpp

    Spoiler

    #include "stdafx.h"
    #include <fstream>
    #include "constants.h"
    #include "buffer_manager.h"
    #include "packet.h"
    #include "desc_client.h"
    #include "desc_manager.h"
    #include "char.h"
    #include "char_manager.h"
    #include "questmanager.h"
    #include "lzo_manager.h"
    #include "item.h"
    #include "config.h"
    #include "xmas_event.h"
    #include "target.h"
    #include "party.h"
    #include "locale_service.h"

    #include "dungeon.h"

    DWORD g_GoldDropTimeLimitValue = 0;
    extern bool DropEvent_CharStone_SetValue(const std::string& name, int value);
    extern bool DropEvent_RefineBox_SetValue (const std::string& name, int value);

    namespace quest
    {
        using namespace std;

        CQuestManager::CQuestManager()
            : m_pSelectedDungeon(NULL), m_dwServerTimerArg(0), m_iRunningEventIndex(0), L(NULL), m_bNoSend (false),
            m_CurrentRunningState(NULL), m_pCurrentCharacter(NULL), m_pCurrentNPCCharacter(NULL), m_pCurrentPartyMember(NULL),
            m_pCurrentPC(NULL),  m_iCurrentSkin(0), m_bError(false), m_pOtherPCBlockRootPC(NULL)
        {
        }

        CQuestManager::~CQuestManager()
        {
            Destroy();
        }

        void CQuestManager::Destroy()
        {
            if (L)
            {
                lua_close(L);
                L = NULL;
            }
        }    

        bool CQuestManager::Initialize()
        {
            if (g_bAuthServer)
                return true;

            if (!InitializeLua())
                return false;

            m_pSelectedDungeon = NULL;

            m_mapEventName.insert(TEventNameMap::value_type("click", QUEST_CLICK_EVENT));        // NPC를 클릭
            m_mapEventName.insert(TEventNameMap::value_type("kill", QUEST_KILL_EVENT));        // Mob을 사냥
            m_mapEventName.insert(TEventNameMap::value_type("timer", QUEST_TIMER_EVENT));        // 미리 지정해둔 시간이 지남
            m_mapEventName.insert(TEventNameMap::value_type("levelup", QUEST_LEVELUP_EVENT));    // 레벨업을 함
            m_mapEventName.insert(TEventNameMap::value_type("login", QUEST_LOGIN_EVENT));        // 로그인 시
            m_mapEventName.insert(TEventNameMap::value_type("logout", QUEST_LOGOUT_EVENT));        // 로그아웃 시
            m_mapEventName.insert(TEventNameMap::value_type("button", QUEST_BUTTON_EVENT));        // 퀘스트 버튼을 누름
            m_mapEventName.insert(TEventNameMap::value_type("info", QUEST_INFO_EVENT));        // 퀘스트 정보창을 염
            m_mapEventName.insert(TEventNameMap::value_type("chat", QUEST_CHAT_EVENT));        // 특정 키워드로 대화를 함
            m_mapEventName.insert(TEventNameMap::value_type("in", QUEST_ATTR_IN_EVENT));        // 맵의 특정 속성에 들어감
            m_mapEventName.insert(TEventNameMap::value_type("out", QUEST_ATTR_OUT_EVENT));        // 맵의 특정 속성에서 나옴
            m_mapEventName.insert(TEventNameMap::value_type("use", QUEST_ITEM_USE_EVENT));        // 퀘스트 아이템을 사용
            m_mapEventName.insert(TEventNameMap::value_type("server_timer", QUEST_SERVER_TIMER_EVENT));    // 서버 타이머 (아직 테스트 안됐음)
            m_mapEventName.insert(TEventNameMap::value_type("enter", QUEST_ENTER_STATE_EVENT));    // 현재 스테이트가 됨
            m_mapEventName.insert(TEventNameMap::value_type("leave", QUEST_LEAVE_STATE_EVENT));    // 현재 스테이트에서 다른 스테이트로 바뀜
            m_mapEventName.insert(TEventNameMap::value_type("letter", QUEST_LETTER_EVENT));        // 로긴 하거나 스테이트가 바껴 새로 정보를 세팅해줘야함
            m_mapEventName.insert(TEventNameMap::value_type("take", QUEST_ITEM_TAKE_EVENT));    // 아이템을 받음
            m_mapEventName.insert(TEventNameMap::value_type("target", QUEST_TARGET_EVENT));        // 타겟
            m_mapEventName.insert(TEventNameMap::value_type("party_kill", QUEST_PARTY_KILL_EVENT));    // 파티 멤버가 몬스터를 사냥 (리더에게 옴)
            m_mapEventName.insert(TEventNameMap::value_type("unmount", QUEST_UNMOUNT_EVENT));
            m_mapEventName.insert(TEventNameMap::value_type("pick", QUEST_ITEM_PICK_EVENT));    // 떨어져있는 아이템을 습득함.
            m_mapEventName.insert(TEventNameMap::value_type("sig_use", QUEST_SIG_USE_EVENT));        // Special item group에 속한 아이템을 사용함.
            m_mapEventName.insert(TEventNameMap::value_type("item_informer", QUEST_ITEM_INFORMER_EVENT));    // 독일선물기능테스트

            m_bNoSend = false;

            m_iCurrentSkin = QUEST_SKIN_NORMAL;

            {
                ifstream inf((g_stQuestDir + "/questnpc.txt").c_str());
                int line = 0;

                if (!inf.is_open())
                    sys_err( "QUEST Cannot open 'questnpc.txt'");
                else
                    sys_log(0, "QUEST can open 'questnpc.txt' (%s)", g_stQuestDir.c_str() );

                while (1)
                {
                    unsigned int vnum;

                    inf >> vnum;

                    line++;

                    if (inf.fail())
                        break;

                    string s;
                    getline(inf, s);
                    unsigned int li = 0, ri = s.size()-1;
                    while (li < s.size() && isspace(s[li])) li++;
                    while (ri > 0 && isspace(s[ri])) ri--;

                    if (ri < li) 
                    {
                        sys_err("QUEST questnpc.txt:%d:npc name error",line);
                        continue;
                    }

                    s = s.substr(li, ri-li+1);

                    int    n = 0;
                    str_to_number(n, s.c_str());
                    if (n)
                        continue;

                    //cout << '-' << s << '-' << endl;
                    if ( test_server )
                        sys_log(0, "QUEST reading script of %s(%d)", s.c_str(), vnum);
                    m_mapNPC[vnum].Set(vnum, s);
                    m_mapNPCNameID = vnum;
                }

                // notarget quest
                m_mapNPC[0].Set(0, "notarget");
            }

            if (g_iUseLocale)
            {
                SetEventFlag("guild_withdraw_delay", 1);
                SetEventFlag("guild_disband_delay", 1);
            }
            else
            {
                SetEventFlag("guild_withdraw_delay", 3);
                SetEventFlag("guild_disband_delay", 7);
            }
            return true;
        }

        unsigned int CQuestManager::FindNPCIDByName(const string& name)
        {
            map<string, unsigned int>::iterator it = m_mapNPCNameID.find(name);
            return it != m_mapNPCNameID.end() ? it->second : 0;
        }

        void CQuestManager::SelectItem(unsigned int pc, unsigned int selection)
        {
            PC* pPC = GetPC(pc);
            if (pPC && pPC->IsRunning() && pPC->GetRunningQuestState()->suspend_state == SUSPEND_STATE_SELECT_ITEM)
            {
                pPC->SetSendDoneFlag();
                pPC->GetRunningQuestState()->args=1;
                lua_pushnumber(pPC->GetRunningQuestState()->co,selection);

                if (!RunState(*pPC->GetRunningQuestState()))
                {
                    CloseState(*pPC->GetRunningQuestState());
                    pPC->EndRunning();
                }
            }
        }

        void CQuestManager::Confirm(unsigned int pc, EQuestConfirmType confirm, unsigned int pc2)
        {
            PC* pPC = GetPC(pc);

            if (!pPC->IsRunning())
            {
                sys_err("no quest running for pc, cannot process input : %u", pc);
                return;
            }

            if (pPC->GetRunningQuestState()->suspend_state != SUSPEND_STATE_CONFIRM)
            {
                sys_err("not wait for a confirm : %u %d", pc, pPC->GetRunningQuestState()->suspend_state);
                return;
            }

            if (pc2 && !pPC->IsConfirmWait(pc2))
            {
                sys_err("not wait for a confirm : %u %d", pc, pPC->GetRunningQuestState()->suspend_state);
                return;
            }

            pPC->ClearConfirmWait();

            pPC->SetSendDoneFlag();

            pPC->GetRunningQuestState()->args=1;
            lua_pushnumber(pPC->GetRunningQuestState()->co, confirm);

            AddScript("[END_CONFIRM_WAIT]");
            SetSkinStyle(QUEST_SKIN_NOWINDOW);
            SendScript();

            if (!RunState(*pPC->GetRunningQuestState()))
            {
                CloseState(*pPC->GetRunningQuestState());
                pPC->EndRunning();
            }

        }

        void CQuestManager::Input(unsigned int pc, const char* msg)
        {
            PC* pPC = GetPC(pc);
            if (!pPC)
            {
                sys_err("no pc! : %u",pc);
                return;
            }

            if (!pPC->IsRunning())
            {
                sys_err("no quest running for pc, cannot process input : %u", pc);
                return;
            }

            if (pPC->GetRunningQuestState()->suspend_state != SUSPEND_STATE_INPUT)
            {
                sys_err("not wait for a input : %u %d", pc, pPC->GetRunningQuestState()->suspend_state);
                return;
            }

            pPC->SetSendDoneFlag();

            pPC->GetRunningQuestState()->args=1;
            lua_pushstring(pPC->GetRunningQuestState()->co,msg);

            if (!RunState(*pPC->GetRunningQuestState()))
            {
                CloseState(*pPC->GetRunningQuestState());
                pPC->EndRunning();
            }
        }

        void CQuestManager::Select(unsigned int pc, unsigned int selection)
        {
            PC* pPC;

            if ((pPC = GetPC(pc)) && pPC->IsRunning() && pPC->GetRunningQuestState()->suspend_state==SUSPEND_STATE_SELECT)
            {
                pPC->SetSendDoneFlag();

                if (!pPC->GetRunningQuestState()->chat_scripts.empty())
                {
                    // 채팅 이벤트인 경우
                    // 현재 퀘스트는 어느 퀘스트를 실행할 것인가를 고르는 퀘스트 이므로
                    // 끝내고 선택된 퀘스트를 실행한다.
                    QuestState& old_qs = *pPC->GetRunningQuestState();
                    CloseState(old_qs);

                    if (selection >= pPC->GetRunningQuestState()->chat_scripts.size())
                    {
                        pPC->SetSendDoneFlag();
                        GotoEndState(old_qs);
                        pPC->EndRunning();
                    }
                    else
                    {
                        AArgScript* pas = pPC->GetRunningQuestState()->chat_scripts[selection];
                        ExecuteQuestScript(*pPC, pas->quest_index, pas->state_index, pas->script.GetCode(), pas->script.GetSize());
                    }
                }
                else
                {
                    // on default 
                    pPC->GetRunningQuestState()->args=1;
                    lua_pushnumber(pPC->GetRunningQuestState()->co,selection+1);

                    if (!RunState(*pPC->GetRunningQuestState()))
                    {
                        CloseState(*pPC->GetRunningQuestState());
                        pPC->EndRunning();
                    }
                }
            }
            else
            {
                sys_err("wrong QUEST_SELECT request! : %d",pc);
            }
        }

        void CQuestManager::Resume(unsigned int pc)
        {
            PC * pPC;

            if ((pPC = GetPC(pc)) && pPC->IsRunning() && pPC->GetRunningQuestState()->suspend_state == SUSPEND_STATE_PAUSE)
            {
                pPC->SetSendDoneFlag();
                pPC->GetRunningQuestState()->args = 0;

                if (!RunState(*pPC->GetRunningQuestState()))
                {
                    CloseState(*pPC->GetRunningQuestState());
                    pPC->EndRunning();
                }
            }
            else
            {
                //cerr << pPC << endl;
                //cerr << pPC->IsRunning() << endl;
                //cerr << pPC->GetRunningQuestState()->suspend_state;
                //cerr << SUSPEND_STATE_WAIT << endl;
                //cerr << "wrong QUEST_WAIT request! : " << pc << endl;
                sys_err("wrong QUEST_WAIT request! : %d",pc);
            }
        }

        void CQuestManager::EnterState(DWORD pc, DWORD quest_index, int state)
        {
            PC* pPC;
            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                    return;

                m_mapNPC[QUEST_NO_NPC].OnEnterState(*pPC, quest_index, state);
            }
            else
                sys_err("QUEST no such pc id : %d", pc);
        }

        void CQuestManager::LeaveState(DWORD pc, DWORD quest_index, int state)
        {
            PC* pPC;
            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                    return;

                m_mapNPC[QUEST_NO_NPC].OnLeaveState(*pPC, quest_index, state);
            }
            else
                sys_err("QUEST no such pc id : %d", pc);
        }

        void CQuestManager::Letter(DWORD pc, DWORD quest_index, int state)
        {
            PC* pPC;
            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                    return;

                m_mapNPC[QUEST_NO_NPC].OnLetter(*pPC, quest_index, state);
            }
            else
                sys_err("QUEST no such pc id : %d", pc);
        }

        void CQuestManager::LogoutPC(LPCHARACTER ch)
        {
            PC * pPC = GetPC(ch->GetPlayerID());

            if (pPC && pPC->IsRunning())
            {
                CloseState(*pPC->GetRunningQuestState());
                pPC->CancelRunning();
            }

            // 지우기 전에 로그아웃 한다.
            Logout(ch->GetPlayerID());

            if (ch == m_pCurrentCharacter)
            {
                m_pCurrentCharacter = NULL;
                m_pCurrentPC = NULL;
            }
        }

        ///////////////////////////////////////////////////////////////////////////////////////////
        //
        // Quest Event 관련
        //
        ///////////////////////////////////////////////////////////////////////////////////////////
        void CQuestManager::Login(unsigned int pc, const char * c_pszQuest)
        {
            PC * pPC;

            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                    return;

                m_mapNPC[QUEST_NO_NPC].OnLogin(*pPC, c_pszQuest);
            }
            else
            {
                sys_err("QUEST no such pc id : %d", pc);
            }
        }

        void CQuestManager::Logout(unsigned int pc)
        {
            PC * pPC;

            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                    return;

                m_mapNPC[QUEST_NO_NPC].OnLogout(*pPC);
            }
            else
                sys_err("QUEST no such pc id : %d", pc);
        }

        void CQuestManager::Kill(unsigned int pc, unsigned int npc)
        {
            //m_CurrentNPCRace = npc;
            PC * pPC;

            sys_log(0, "CQuestManager::Kill QUEST_KILL_EVENT (pc=%d, npc=%d)", pc, npc);

            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                    return;

                /* [hyo] 몹 kill시 중복 카운팅 이슈 관련한 수정사항
                   quest script에 when 171.kill begin ... 등의 코드로 인하여 스크립트가 처리되었더라도
                   바로 return하지 않고 다른 검사도 수행하도록 변경함. (2011/07/21)
                */   
                // call script
                
                //m_mapNPC[npc].OnKill(*pPC);
                if(npc > 0)
                {
                    m_mapNPC[npc].OnKill(*pPC);
                }

                LPCHARACTER ch = GetCurrentCharacterPtr();
                LPPARTY pParty = ch->GetParty();
                LPCHARACTER leader = pParty ? pParty->GetLeaderCharacter() : ch;

                if (leader)
                {
                    m_pCurrentPartyMember = ch;

                    if (m_mapNPC[npc].OnPartyKill(*GetPC(leader->GetPlayerID())))
                        return;

                    pPC = GetPC(pc);
                }

                if (m_mapNPC[QUEST_NO_NPC].OnKill(*pPC))
                    return;

                if (leader)
                {
                    m_pCurrentPartyMember = ch;
                    m_mapNPC[QUEST_NO_NPC].OnPartyKill(*GetPC(leader->GetPlayerID()));
                }
            }
            else
                sys_err("QUEST: no such pc id : %d", pc);
        }

        bool CQuestManager::ServerTimer(unsigned int npc, unsigned int arg)
        {
            SetServerTimerArg(arg);
            sys_log(0, "XXX ServerTimer Call NPC %p", GetPCForce(0));
            m_pCurrentPC = GetPCForce(0);
            m_pCurrentCharacter = NULL;
            m_pSelectedDungeon = NULL;
            return m_mapNPC[npc].OnServerTimer(*m_pCurrentPC);
        }

        bool CQuestManager::Timer(unsigned int pc, unsigned int npc)
        {
            PC* pPC;

            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                {
                    return false;
                }
                // call script
                return m_mapNPC[npc].OnTimer(*pPC);
            }
            else
            {
                //cout << "no such pc id : " << pc;
                sys_err("QUEST TIMER_EVENT no such pc id : %d", pc);
                return false;
            }
            //cerr << "QUEST TIMER" << endl;
        }

        void CQuestManager::LevelUp(unsigned int pc)
        {
            PC * pPC;

            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                    return;

                m_mapNPC[QUEST_NO_NPC].OnLevelUp(*pPC);
            }
            else
            {
                sys_err("QUEST LEVELUP_EVENT no such pc id : %d", pc);
            }
        }

        void CQuestManager::AttrIn(unsigned int pc, LPCHARACTER ch, int attr)
        {
            PC* pPC;
            if ((pPC = GetPC(pc)))
            {
                m_pCurrentPartyMember = ch;
                if (!CheckQuestLoaded(pPC))
                    return;

                // call script
                m_mapNPC[attr+QUEST_ATTR_NPC_START].OnAttrIn(*pPC);
            }
            else
            {
                //cout << "no such pc id : " << pc;
                sys_err("QUEST no such pc id : %d", pc);
            }
        }

        void CQuestManager::AttrOut(unsigned int pc, LPCHARACTER ch, int attr)
        {
            PC* pPC;
            if ((pPC = GetPC(pc)))
            {
                //m_pCurrentCharacter = ch;
                m_pCurrentPartyMember = ch;
                if (!CheckQuestLoaded(pPC))
                    return;

                // call script
                m_mapNPC[attr+QUEST_ATTR_NPC_START].OnAttrOut(*pPC);
            }
            else
            {
                //cout << "no such pc id : " << pc;
                sys_err("QUEST no such pc id : %d", pc);
            }
        }

        bool CQuestManager::Target(unsigned int pc, DWORD dwQuestIndex, const char * c_pszTargetName, const char * c_pszVerb)
        {
            PC * pPC;

            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                    return false;

                bool bRet;
                return m_mapNPC[QUEST_NO_NPC].OnTarget(*pPC, dwQuestIndex, c_pszTargetName, c_pszVerb, bRet);
            }

            return false;
        }

        void CQuestManager::QuestInfo(unsigned int pc, unsigned int quest_index)
        {
            PC* pPC;

            if ((pPC = GetPC(pc)))
            {
                // call script
                if (!CheckQuestLoaded(pPC))
                {
                    LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);

                    if (ch)
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("퀘스트를 로드하는 중입니다. 잠시만 기다려 주십시오."));

                    return;
                }

                m_mapNPC[QUEST_NO_NPC].OnInfo(*pPC, quest_index);
            }
            else
            {
                //cout << "no such pc id : " << pc;
                sys_err("QUEST INFO_EVENT no such pc id : %d", pc);
            }
        }

        void CQuestManager::QuestButton(unsigned int pc, unsigned int quest_index)
        {
            PC* pPC;
            if ((pPC = GetPC(pc)))
            {
                // call script
                if (!CheckQuestLoaded(pPC))
                {
                    LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
                    if (ch)
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("퀘스트를 로드하는 중입니다. 잠시만 기다려 주십시오."));
                    }
                    return;
                }
                m_mapNPC[QUEST_NO_NPC].OnButton(*pPC, quest_index);
            }
            else
            {
                //cout << "no such pc id : " << pc;
                sys_err("QUEST CLICK_EVENT no such pc id : %d", pc);
            }
        }

        bool CQuestManager::TakeItem(unsigned int pc, unsigned int npc, LPITEM item)
        {
            //m_CurrentNPCRace = npc;
            PC* pPC;

            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                {
                    LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
                    if (ch)
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("퀘스트를 로드하는 중입니다. 잠시만 기다려 주십시오."));
                    }
                    return false;
                }
                // call script
                SetCurrentItem(item);
                return m_mapNPC[npc].OnTakeItem(*pPC);
            }
            else
            {
                //cout << "no such pc id : " << pc;
                sys_err("QUEST USE_ITEM_EVENT no such pc id : %d", pc);
                return false;
            }
        }

        bool CQuestManager::UseItem(unsigned int pc, LPITEM item, bool bReceiveAll)
        {
            if (test_server)
                sys_log( 0, "questmanager::UseItem Start : itemVnum : %d PC : %d", item->GetOriginalVnum(), pc);
            PC* pPC;
            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                {
                    LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
                    if (ch)
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("퀘스트를 로드하는 중입니다. 잠시만 기다려 주십시오."));
                    }
                    return false;
                }
                // call script
                SetCurrentItem(item);
                /*
                if (test_server)
                {
                    sys_log( 0, "Quest UseItem Start : itemVnum : %d PC : %d", item->GetOriginalVnum(), pc);
                    itertype(m_mapNPC) it = m_mapNPC.begin();
                    itertype(m_mapNPC) end = m_mapNPC.end();
                    for( ; it != end ; ++it)
                    {
                        sys_log( 0, "Quest UseItem : vnum : %d item Vnum : %d", it->first, item->GetOriginalVnum());
                    }
                }
                if(test_server)
                sys_log( 0, "questmanager:useItem: mapNPCVnum : %d\n", m_mapNPC[item->GetVnum()].GetVnum());
                */

                return m_mapNPC[item->GetVnum()].OnUseItem(*pPC, bReceiveAll);
            }
            else
            {
                //cout << "no such pc id : " << pc;
                sys_err("QUEST USE_ITEM_EVENT no such pc id : %d", pc);
                return false;
            }
        }

        // Speical Item Group에 정의된 Group Use
        bool CQuestManager::SIGUse(unsigned int pc, DWORD sig_vnum, LPITEM item, bool bReceiveAll)
        {
            if (test_server)
                sys_log( 0, "questmanager::SIGUse Start : itemVnum : %d PC : %d", item->GetOriginalVnum(), pc);
            PC* pPC;
            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                {
                    LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
                    if (ch)
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("퀘스트를 로드하는 중입니다. 잠시만 기다려 주십시오."));
                    }
                    return false;
                }
                // call script
                SetCurrentItem(item);

                return m_mapNPC[sig_vnum].OnSIGUse(*pPC, bReceiveAll);
            }
            else
            {
                //cout << "no such pc id : " << pc;
                sys_err("QUEST USE_ITEM_EVENT no such pc id : %d", pc);
                return false;
            }
        }

        bool CQuestManager::GiveItemToPC(unsigned int pc, LPCHARACTER pkChr)
        {
            if (!pkChr->IsPC())
                return false;

            PC * pPC = GetPC(pc);

            if (pPC)
            {
                if (!CheckQuestLoaded(pPC))
                    return false;

                TargetInfo * pInfo = CTargetManager::instance().GetTargetInfo(pc, TARGET_TYPE_VID, pkChr->GetVID());

                if (pInfo)
                {
                    bool bRet;

                    if (m_mapNPC[QUEST_NO_NPC].OnTarget(*pPC, pInfo->dwQuestIndex, pInfo->szTargetName, "click", bRet))
                        return true;
                }
            }

            return false;
        }

        bool CQuestManager::Click(unsigned int pc, LPCHARACTER pkChrTarget)
        {
            PC * pPC = GetPC(pc);

            if (pPC)
            {
                if (!CheckQuestLoaded(pPC))
                {
                    LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);

                    if (ch)
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("퀘스트를 로드하는 중입니다. 잠시만 기다려 주십시오."));

                    return false;
                }

                TargetInfo * pInfo = CTargetManager::instance().GetTargetInfo(pc, TARGET_TYPE_VID, pkChrTarget->GetVID());
                if (test_server)
                {
                    sys_log(0, "CQuestManager::Click(pid=%d, npc_name=%s) - target_info(%x)", pc, pkChrTarget->GetName(), pInfo);
                }

                if (pInfo)
                {
                    bool bRet;
                    if (m_mapNPC[QUEST_NO_NPC].OnTarget(*pPC, pInfo->dwQuestIndex, pInfo->szTargetName, "click", bRet))
                        return bRet;
                }

                DWORD dwCurrentNPCRace = pkChrTarget->GetRaceNum();

                if (pkChrTarget->IsNPC())
                {
                    map<unsigned int, NPC>::iterator it = m_mapNPC.find(dwCurrentNPCRace);

                    if (it == m_mapNPC.end())
                    {
                        sys_err("CQuestManager::Click(pid=%d, target_npc_name=%s) - NOT EXIST NPC RACE VNUM[%d]",
                                pc, 
                                pkChrTarget->GetName(), 
                                dwCurrentNPCRace);
                        return false;
                    }

                    // call script
                    if (it->second.HasChat())
                    {
                        // if have chat, give chat
                        if (test_server)
                            sys_log(0, "CQuestManager::Click->OnChat");

                        if (!it->second.OnChat(*pPC))
                        {
                            if (test_server)
                                sys_log(0, "CQuestManager::Click->OnChat Failed");

                            return it->second.OnClick(*pPC);
                        }

                        return true;
                    }
                    else
                    {
                        // else click
                        return it->second.OnClick(*pPC);
                    }
                }
                return false;
            }
            else
            {
                //cout << "no such pc id : " << pc;
                sys_err("QUEST CLICK_EVENT no such pc id : %d", pc);
                return false;
            }
            //cerr << "QUEST CLICk" << endl;
        }

        void CQuestManager::Unmount(unsigned int pc)
        {
            PC * pPC;

            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                    return;

                m_mapNPC[QUEST_NO_NPC].OnUnmount(*pPC);
            }
            else
                sys_err("QUEST no such pc id : %d", pc);
        }
        //독일 선물 기능 테스트
        void CQuestManager::ItemInformer(unsigned int pc,unsigned int vnum)
        {
            
            PC* pPC;
            pPC = GetPC(pc);
            
            m_mapNPC[QUEST_NO_NPC].OnItemInformer(*pPC,vnum);
        }
        ///////////////////////////////////////////////////////////////////////////////////////////
        // END OF 퀘스트 이벤트 처리
        ///////////////////////////////////////////////////////////////////////////////////////////

        ///////////////////////////////////////////////////////////////////////////////////////////
        void CQuestManager::LoadStartQuest(const string& quest_name, unsigned int idx)
        {
            for (itertype(g_setQuestObjectDir) it = g_setQuestObjectDir.begin(); it != g_setQuestObjectDir.end(); ++it)
            {
                const string& stQuestObjectDir = *it;
                string full_name = stQuestObjectDir + "/begin_condition/" + quest_name;
                ifstream inf(full_name.c_str());

                if (inf.is_open())
                {
                    sys_log(0, "QUEST loading begin condition for %s", quest_name.c_str());

                    istreambuf_iterator<char> ib(inf), ie;
                    copy(ib, ie, back_inserter(m_hmQuestStartScript[idx]));
                }
            }
        }

        bool CQuestManager::CanStartQuest(unsigned int quest_index, const PC& pc)
        {
            return CanStartQuest(quest_index);
        }

        bool CQuestManager::CanStartQuest(unsigned int quest_index)
        {
            THashMapQuestStartScript::iterator it;

            if ((it = m_hmQuestStartScript.find(quest_index)) == m_hmQuestStartScript.end())
                return true;
            else
            {
                int x = lua_gettop(L);
                lua_dobuffer(L, &(it->second[0]), it->second.size(), "StartScript");
                int bStart = lua_toboolean(L, -1);
                lua_settop(L, x);
                return bStart != 0;
            }
        }

        bool CQuestManager::CanEndQuestAtState(const string& quest_name, const string& state_name)
        {
            return false;
        }

        void CQuestManager::DisconnectPC(LPCHARACTER ch)
        {
            m_mapPC.erase(ch->GetPlayerID());
        }

        PC * CQuestManager::GetPCForce(unsigned int pc)
        {
            PCMap::iterator it;

            if ((it = m_mapPC.find(pc)) == m_mapPC.end())
            {
                PC * pPC = &m_mapPC[pc];
                pPC->SetID(pc);
                return pPC;
            }

            return &it->second;
        }

        PC * CQuestManager::GetPC(unsigned int pc)
        {
            PCMap::iterator it;

            LPCHARACTER pkChr = CHARACTER_MANAGER::instance().FindByPID(pc);

            if (!pkChr)
                return NULL;

            m_pCurrentPC = GetPCForce(pc);
            m_pCurrentCharacter = pkChr;
            m_pSelectedDungeon = NULL;
            return (m_pCurrentPC);
        }

        void CQuestManager::ClearScript()
        {
            m_strScript.clear();
            m_iCurrentSkin = QUEST_SKIN_NORMAL;
        }

        void CQuestManager::AddScript(const string& str)
        {
            m_strScript+=str;
        }

        void CQuestManager::SendScript()
        {
            if (m_bNoSend)
            {
                m_bNoSend = false;
                ClearScript();
                return;
            }

            if (m_strScript=="[DONE]" || m_strScript == "[NEXT]")
            {
                if (m_pCurrentPC && !m_pCurrentPC->GetAndResetDoneFlag() && m_strScript=="[DONE]" && m_iCurrentSkin == QUEST_SKIN_NORMAL && !IsError())
                {
                    ClearScript();
                    return;
                }
                m_iCurrentSkin = QUEST_SKIN_NOWINDOW;
            }

            //sys_log(0, "Send Quest Script to %s", GetCurrentCharacterPtr()->GetName());
            //send -_-!
            struct ::packet_script packet_script;

            packet_script.header = HEADER_GC_SCRIPT;
            packet_script.skin = m_iCurrentSkin;
            packet_script.src_size = m_strScript.size();
            packet_script.size = packet_script.src_size + sizeof(struct packet_script);

            TEMP_BUFFER buf;
            buf.write(&packet_script, sizeof(struct packet_script));
            buf.write(&m_strScript[0], m_strScript.size());

            GetCurrentCharacterPtr()->GetDesc()->Packet(buf.read_peek(), buf.size());

            if (test_server)
                sys_log(0, "m_strScript %s size %d", m_strScript.c_str(), buf.size());

            ClearScript();
        }

        const char* CQuestManager::GetQuestStateName(const string& quest_name, const int state_index)
        {
            int x = lua_gettop(L);
            lua_getglobal(L, quest_name.c_str());
            if (lua_isnil(L,-1))
            {
                sys_err("QUEST wrong quest state file %s.%d", quest_name.c_str(), state_index);
                lua_settop(L,x);
                return "";
            }
            lua_pushnumber(L, state_index);
            lua_gettable(L, -2);

            const char* str = lua_tostring(L, -1);
            lua_settop(L, x);
            return str;
        }

        int CQuestManager::GetQuestStateIndex(const string& quest_name, const string& state_name)
        {
            int x = lua_gettop(L);
            lua_getglobal(L, quest_name.c_str());
            if (lua_isnil(L,-1))
            {
                sys_err("QUEST wrong quest state file %s.%s",quest_name.c_str(),state_name.c_str()  );
                lua_settop(L,x);
                return 0;
            }
            lua_pushstring(L, state_name.c_str());
            lua_gettable(L, -2);

            int v = (int)rint(lua_tonumber(L,-1));
            lua_settop(L, x);
            if ( test_server )
                sys_log( 0,"[QUESTMANAGER] GetQuestStateIndex x(%d) v(%d) %s %s", v,x, quest_name.c_str(), state_name.c_str() );
            return v;
        }

        void CQuestManager::SetSkinStyle(int iStyle)
        {
            if (iStyle<0 || iStyle >= QUEST_SKIN_COUNT)
            {
                m_iCurrentSkin = QUEST_SKIN_NORMAL;
            }
            else
                m_iCurrentSkin = iStyle;
        }

        unsigned int CQuestManager::LoadTimerScript(const string& name)
        {
            map<string, unsigned int>::iterator it;
            if ((it = m_mapTimerID.find(name)) != m_mapTimerID.end())
            {
                return it->second;
            }
            else
            {
                unsigned int new_id = UINT_MAX - m_mapTimerID.size();

                m_mapNPC[new_id].Set(new_id, name);
                m_mapTimerID.insert(make_pair(name, new_id));

                return new_id;
            }
        }

        unsigned int CQuestManager::GetCurrentNPCRace()
        {
            return GetCurrentNPCCharacterPtr() ? GetCurrentNPCCharacterPtr()->GetRaceNum() : 0;
        }

        LPITEM CQuestManager::GetCurrentItem()
        {
            return GetCurrentCharacterPtr() ? GetCurrentCharacterPtr()->GetQuestItemPtr() : NULL; 
        }

        void CQuestManager::ClearCurrentItem()
        {
            if (GetCurrentCharacterPtr())
                GetCurrentCharacterPtr()->ClearQuestItemPtr();
        }

        void CQuestManager::SetCurrentItem(LPITEM item)
        {
            if (GetCurrentCharacterPtr())
                GetCurrentCharacterPtr()->SetQuestItemPtr(item);
        }

        LPCHARACTER CQuestManager::GetCurrentNPCCharacterPtr()
        { 
            return GetCurrentCharacterPtr() ? GetCurrentCharacterPtr()->GetQuestNPC() : NULL; 
        }

        const string & CQuestManager::GetCurrentQuestName()
        {
            return GetCurrentPC()->GetCurrentQuestName();
        }

        LPDUNGEON CQuestManager::GetCurrentDungeon()
        {
            LPCHARACTER ch = GetCurrentCharacterPtr();

            if (!ch)
            {
                if (m_pSelectedDungeon)
                    return m_pSelectedDungeon;
                return NULL;
            }

            return ch->GetDungeonForce();
        }

        void CQuestManager::RegisterQuest(const string & stQuestName, unsigned int idx)
        {
            assert(idx > 0);

            itertype(m_hmQuestName) it;

            if ((it = m_hmQuestName.find(stQuestName)) != m_hmQuestName.end())
                return;

            m_hmQuestName.insert(make_pair(stQuestName, idx));
            LoadStartQuest(stQuestName, idx);
            m_mapQuestNameByIndex.insert(make_pair(idx, stQuestName));

            sys_log(0, "QUEST: Register %4u %s", idx, stQuestName.c_str());
        }

        unsigned int CQuestManager::GetQuestIndexByName(const string& name)
        {
            THashMapQuestName::iterator it = m_hmQuestName.find(name);

            if (it == m_hmQuestName.end())
                return 0; // RESERVED

            return it->second;
        }

        const string & CQuestManager::GetQuestNameByIndex(unsigned int idx)
        {
            itertype(m_mapQuestNameByIndex) it;

            if ((it = m_mapQuestNameByIndex.find(idx)) == m_mapQuestNameByIndex.end())
            {
                sys_err("cannot find quest name by index %u", idx);
                assert(!"cannot find quest name by index");

                static std::string st = "";
                return st;
            }

            return it->second;
        }

        void CQuestManager::SendEventFlagList(LPCHARACTER ch)
        {
            itertype(m_mapEventFlag) it;
            for (it = m_mapEventFlag.begin(); it != m_mapEventFlag.end(); ++it)
            {
                const string& flagname = it->first;
                int value = it->second;

                if (!test_server && value == 1 && flagname == "valentine_drop")
                    ch->ChatPacket(CHAT_TYPE_INFO, "%s %d prob 800", flagname.c_str(), value);
                else if (!test_server && value == 1 && flagname == "newyear_wonso")
                    ch->ChatPacket(CHAT_TYPE_INFO, "%s %d prob 500", flagname.c_str(), value);
                else if (!test_server && value == 1 && flagname == "newyear_fire")
                    ch->ChatPacket(CHAT_TYPE_INFO, "%s %d prob 1000", flagname.c_str(), value);
                else
                    ch->ChatPacket(CHAT_TYPE_INFO, "%s %d", flagname.c_str(), value);
            }
        }

        void CQuestManager::RequestSetEventFlag(const string& name, int value)
        {
            TPacketSetEventFlag p;
            strlcpy(p.szFlagName, name.c_str(), sizeof(p.szFlagName));
            p.lValue = value;
            db_clientdesc->DBPacket(HEADER_GD_SET_EVENT_FLAG, 0, &p, sizeof(TPacketSetEventFlag));
        }

        void CQuestManager::SetEventFlag(const string& name, int value)
        {
            static const char*    DROPEVENT_CHARTONE_NAME        = "drop_char_stone";
            static const int    DROPEVENT_CHARTONE_NAME_LEN = strlen(DROPEVENT_CHARTONE_NAME);

            int prev_value = m_mapEventFlag[name];

            sys_log(0, "QUEST eventflag %s %d prev_value %d", name.c_str(), value, m_mapEventFlag[name]);
            m_mapEventFlag[name] = value;

            if (name == "mob_item")
            {
                CHARACTER_MANAGER::instance().SetMobItemRate(value);
            }
            else if (name == "mob_dam")
            {
                CHARACTER_MANAGER::instance().SetMobDamageRate(value);
            }
            else if (name == "mob_gold")
            {
                CHARACTER_MANAGER::instance().SetMobGoldAmountRate(value);
            }
            else if (name == "mob_gold_pct")
            {
                CHARACTER_MANAGER::instance().SetMobGoldDropRate(value);
            }
            else if (name == "user_dam")
            {
                CHARACTER_MANAGER::instance().SetUserDamageRate(value);
            }
            else if (name == "user_dam_buyer")
            {
                CHARACTER_MANAGER::instance().SetUserDamageRatePremium(value);
            }
            else if (name == "mob_exp")
            {
                CHARACTER_MANAGER::instance().SetMobExpRate(value);
            }
            else if (name == "mob_item_buyer")
            {
                CHARACTER_MANAGER::instance().SetMobItemRatePremium(value);
            }
            else if (name == "mob_exp_buyer")
            {
                CHARACTER_MANAGER::instance().SetMobExpRatePremium(value);
            }
            else if (name == "mob_gold_buyer")
            {
                CHARACTER_MANAGER::instance().SetMobGoldAmountRatePremium(value);
            }
            else if (name == "mob_gold_pct_buyer")
            {
                CHARACTER_MANAGER::instance().SetMobGoldDropRatePremium(value);
            }
            else if (name == "crcdisconnect")
            {
                DESC_MANAGER::instance().SetDisconnectInvalidCRCMode(value != 0);
            }
            else if (!name.compare(0,5,"xmas_"))
            {
                xmas::ProcessEventFlag(name, prev_value, value);
            }
            else if (name == "newyear_boom")
            {
                const DESC_MANAGER::DESC_SET & c_ref_set = DESC_MANAGER::instance().GetClientSet();

                for (itertype(c_ref_set) it = c_ref_set.begin(); it != c_ref_set.end(); ++it)
                {
                    LPCHARACTER ch = (*it)->GetCharacter();

                    if (!ch)
                        continue;

                    ch->ChatPacket(CHAT_TYPE_COMMAND, "newyear_boom %d", value);
                }
            }
            else if ( name == "eclipse" )
            {
                std::string mode("");

                if ( value == 1 )
                {
                    mode = "dark";
                }
                else
                {
                    mode = "light";
                }
                
                const DESC_MANAGER::DESC_SET & c_ref_set = DESC_MANAGER::instance().GetClientSet();

                for (itertype(c_ref_set) it = c_ref_set.begin(); it != c_ref_set.end(); ++it)
                {
                    LPCHARACTER ch = (*it)->GetCharacter();
                    if (!ch)
                        continue;

                    ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode %s", mode.c_str());
                }
            }
            else if (name == "day")
            {
                const DESC_MANAGER::DESC_SET & c_ref_set = DESC_MANAGER::instance().GetClientSet();

                for (itertype(c_ref_set) it = c_ref_set.begin(); it != c_ref_set.end(); ++it)
                {
                    LPCHARACTER ch = (*it)->GetCharacter();
                    if (!ch)
                        continue;
                    if (value)
                    {
                        // 밤
                        ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode dark");
                    }
                    else
                    {
                        // 낮
                        ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode light");
                    }
                }

                if (value && !prev_value)
                {
                    // 없으면 만들어준다
                    struct SNPCSellFireworkPosition
                    {
                        long lMapIndex;
                        int x;
                        int y;
                    } positions[] = {
                        {    1,    615,    618 },
                        {    3,    500,    625 },
                        {    21,    598,    665 },
                        {    23,    476,    360 },
                        {    41,    318,    629 },
                        {    43,    478,    375 },
                        {    0,    0,    0   },
                    };

                    SNPCSellFireworkPosition* p = positions;
                    while (p->lMapIndex)
                    {
                        if (map_allow_find(p->lMapIndex))
                        {
                            PIXEL_POSITION posBase;
                            if (!SECTREE_MANAGER::instance().GetMapBasePositionByMapIndex(p->lMapIndex, posBase))
                            {
                                sys_err("cannot get map base position %d", p->lMapIndex);
                                ++p;
                                continue;
                            }

                            CHARACTER_MANAGER::instance().SpawnMob(xmas::MOB_XMAS_FIRWORK_SELLER_VNUM, p->lMapIndex, posBase.x + p->x * 100, posBase.y + p->y * 100, 0, false, -1);
                        }
                        p++;
                    }
                }
                else if (!value && prev_value)
                {
                    // 있으면 지워준다
                    CharacterVectorInteractor i;

                    if (CHARACTER_MANAGER::instance().GetCharactersByRaceNum(xmas::MOB_XMAS_FIRWORK_SELLER_VNUM, i))
                    {
                        CharacterVectorInteractor::iterator it = i.begin();

                        while (it != i.end()) {
                            M2_DESTROY_CHARACTER(*it++);
                        }
                    }
                }
            }
            else if (name == "pre_event_hc" && true == LC_IsEurope())
            {
                const DWORD EventNPC = 20090;

                struct SEventNPCPosition
                {
                    long lMapIndex;
                    int x;
                    int y;
                } positions[] = {
                    { 3, 588, 617 },
                    { 23, 397, 250 },
                    { 43, 567, 426 },
                    { 0, 0, 0 },
                };

                if (value && !prev_value)
                {
                    SEventNPCPosition* pPosition = positions;

                    while (pPosition->lMapIndex)
                    {
                        if (map_allow_find(pPosition->lMapIndex))
                        {
                            PIXEL_POSITION pos;

                            if (!SECTREE_MANAGER::instance().GetMapBasePositionByMapIndex(pPosition->lMapIndex, pos))
                            {
                                sys_err("cannot get map base position %d", pPosition->lMapIndex);
                                ++pPosition;
                                continue;
                            }

                            CHARACTER_MANAGER::instance().SpawnMob(EventNPC, pPosition->lMapIndex, pos.x+pPosition->x*100, pos.y+pPosition->y*100, 0, false, -1);
                        }
                        pPosition++;
                    }
                }
                else if (!value && prev_value)
                {
                    CharacterVectorInteractor i;

                    if (CHARACTER_MANAGER::instance().GetCharactersByRaceNum(EventNPC, i))
                    {
                        CharacterVectorInteractor::iterator it = i.begin();

                        while (it != i.end())
                        {
                            LPCHARACTER ch = *it++;

                            switch (ch->GetMapIndex())
                            {
                                case 3:
                                case 23:
                                case 43:
                                    M2_DESTROY_CHARACTER(ch);
                                    break;
                            }
                        }
                    }
                }
            }
            else if (name.compare(0, DROPEVENT_CHARTONE_NAME_LEN, DROPEVENT_CHARTONE_NAME)== 0)
            {
                DropEvent_CharStone_SetValue(name, value);
            }
            else if (name.compare(0, strlen("refine_box"), "refine_box")== 0)
            {
                DropEvent_RefineBox_SetValue(name, value);
            }
            else if (name == "gold_drop_limit_time")
            {
                g_GoldDropTimeLimitValue = value * 1000;
            }
            else if (name == "new_xmas_event")
            {
                // 20126 new산타.
                static DWORD new_santa = 20126;
                if (value != 0)
                {
                    CharacterVectorInteractor i;
                    bool map1_santa_exist = false;
                    bool map21_santa_exist = false;
                    bool map41_santa_exist = false;
                    
                    if (CHARACTER_MANAGER::instance().GetCharactersByRaceNum(new_santa, i))
                    {
                        CharacterVectorInteractor::iterator it = i.begin();

                        while (it != i.end())
                        {
                            LPCHARACTER tch = *(it++);

                            if (tch->GetMapIndex() == 1)
                            {
                                map1_santa_exist = true;
                            }
                            else if (tch->GetMapIndex() == 21)
                            {
                                map21_santa_exist = true;
                            }
                            else if (tch->GetMapIndex() == 41)
                            {
                                map41_santa_exist = true;
                            }
                        }
                    }

                    if (map_allow_find(1) && !map1_santa_exist)
                    {
                        LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(1);
                        CHARACTER_MANAGER::instance().SpawnMob(new_santa, 1, pkSectreeMap->m_setting.iBaseX + 60800, pkSectreeMap->m_setting.iBaseY + 61700, 0, false, 90, true);
                    }
                    if (map_allow_find(21) && !map21_santa_exist)
                    {
                        LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(21);
                        CHARACTER_MANAGER::instance().SpawnMob(new_santa, 21, pkSectreeMap->m_setting.iBaseX + 59600, pkSectreeMap->m_setting.iBaseY + 61000, 0, false, 110, true);
                    }
                    if (map_allow_find(41) && !map41_santa_exist)
                    {
                        LPSECTREE_MAP pkSectreeMap = SECTREE_MANAGER::instance().GetMap(41);
                        CHARACTER_MANAGER::instance().SpawnMob(new_santa, 41, pkSectreeMap->m_setting.iBaseX + 35700, pkSectreeMap->m_setting.iBaseY + 74300, 0, false, 140, true);
                    }
                }
                else
                {
                    CharacterVectorInteractor i;
                    CHARACTER_MANAGER::instance().GetCharactersByRaceNum(new_santa, i);
                    
                    for (CharacterVectorInteractor::iterator it = i.begin(); it != i.end(); it++)
                    {
                        M2_DESTROY_CHARACTER(*it);
                    }
                }
            }
        }

        int    CQuestManager::GetEventFlag(const string& name)
        {
            map<string,int>::iterator it = m_mapEventFlag.find(name);

            if (it == m_mapEventFlag.end())
                return 0;

            return it->second;
        }

        void CQuestManager::BroadcastEventFlagOnLogin(LPCHARACTER ch)
        {
            int iEventFlagValue;

            if ((iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("xmas_snow")))
            {
                ch->ChatPacket(CHAT_TYPE_COMMAND, "xmas_snow %d", iEventFlagValue);
            }

            if ((iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("xmas_boom")))
            {
                ch->ChatPacket(CHAT_TYPE_COMMAND, "xmas_boom %d", iEventFlagValue);
            }

            if ((iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("xmas_tree")))
            {
                ch->ChatPacket(CHAT_TYPE_COMMAND, "xmas_tree %d", iEventFlagValue);
            }

            if ((iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("day")))
            {
                ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode dark");
            }

            if ((iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("newyear_boom")))
            {
                ch->ChatPacket(CHAT_TYPE_COMMAND, "newyear_boom %d", iEventFlagValue);
            }

            if ( (iEventFlagValue = quest::CQuestManager::instance().GetEventFlag("eclipse")) )
            {
                std::string mode;

                if ( iEventFlagValue == 1 ) mode = "dark";
                else mode = "light";

                ch->ChatPacket(CHAT_TYPE_COMMAND, "DayMode %s", mode.c_str());
            }
        }

        void CQuestManager::Reload()
        {
            lua_close(L);
            m_mapNPC.clear();
            m_mapNPCNameID.clear();
            m_hmQuestName.clear();
            m_mapTimerID.clear();
            m_hmQuestStartScript.clear();
            m_mapEventName.clear();
            L = NULL;
            Initialize();

            for (itertype(m_registeredNPCVnum) it = m_registeredNPCVnum.begin(); it != m_registeredNPCVnum.end(); ++it)
            {
                char buf[256];
                DWORD dwVnum = *it;
                snprintf(buf, sizeof(buf), "%u", dwVnum);
                m_mapNPC[dwVnum].Set(dwVnum, buf);
            }
        }

        bool CQuestManager::ExecuteQuestScript(PC& pc, DWORD quest_index, const int state, const char* code, const int code_size, vector<AArgScript*>* pChatScripts, bool bUseCache)
        {
            return ExecuteQuestScript(pc, CQuestManager::instance().GetQuestNameByIndex(quest_index), state, code, code_size, pChatScripts, bUseCache);
        }

        bool CQuestManager::ExecuteQuestScript(PC& pc, const string& quest_name, const int state, const char* code, const int code_size, vector<AArgScript*>* pChatScripts, bool bUseCache)
        {
            // 실행공간을 생성
            QuestState qs = CQuestManager::instance().OpenState(quest_name, state);
            if (pChatScripts)
                qs.chat_scripts.swap(*pChatScripts);

            // 코드를 읽어들임
            if (bUseCache)
            {
                lua_getglobal(qs.co, "__codecache");
                // stack : __codecache
                lua_pushnumber(qs.co, (long)code);
                // stack : __codecache (codeptr)
                lua_rawget(qs.co, -2);
                // stack : __codecache (compiled-code)
                if (lua_isnil(qs.co, -1))
                {
                    // cache miss

                    // load code to lua,
                    // save it to cache
                    // and only function remain in stack
                    lua_pop(qs.co, 1);
                    // stack : __codecache
                    luaL_loadbuffer(qs.co, code, code_size, quest_name.c_str());
                    // stack : __codecache (compiled-code)
                    lua_pushnumber(qs.co, (long)code);
                    // stack : __codecache (compiled-code) (codeptr)
                    lua_pushvalue(qs.co, -2);
                    // stack : __codecache (compiled-code) (codeptr) (compiled_code)
                    lua_rawset(qs.co, -4);
                    // stack : __codecache (compiled-code)
                    lua_remove(qs.co, -2);
                    // stack : (compiled-code)
                }
                else
                {
                    // cache hit
                    lua_remove(qs.co, -2);
                    // stack : (compiled-code)
                }
            }
            else
                luaL_loadbuffer(qs.co, code, code_size, quest_name.c_str());

            // 플레이어와 연결
            pc.SetQuest(quest_name, qs);

            // 실행
            QuestState& rqs = *pc.GetRunningQuestState();
            if (!CQuestManager::instance().RunState(rqs))
            {
                CQuestManager::instance().CloseState(rqs);
                pc.EndRunning();
                return false;
            }
            return true;
        }

        void CQuestManager::RegisterNPCVnum(DWORD dwVnum)
        {
            if (m_registeredNPCVnum.find(dwVnum) != m_registeredNPCVnum.end())
                return;

            m_registeredNPCVnum.insert(dwVnum);

            char buf[256];
            DIR* dir;

            for (itertype(g_setQuestObjectDir) it = g_setQuestObjectDir.begin(); it != g_setQuestObjectDir.end(); ++it)
            {
                const string& stQuestObjectDir = *it;
                snprintf(buf, sizeof(buf), "%s/%u", stQuestObjectDir.c_str(), dwVnum);
                sys_log(0, "%s", buf);

                if ((dir = opendir(buf)))
                {
                    closedir(dir);
                    snprintf(buf, sizeof(buf), "%u", dwVnum);
                    sys_log(0, "%s", buf);

                    m_mapNPC[dwVnum].Set(dwVnum, buf);
                }
            }
        }

        void CQuestManager::WriteRunningStateToSyserr()
        {
            const char * state_name = GetQuestStateName(GetCurrentQuestName(), GetCurrentState()->st);

            string event_index_name = "";
            for (itertype(m_mapEventName) it = m_mapEventName.begin(); it != m_mapEventName.end(); ++it)
            {
                if (it->second == m_iRunningEventIndex)
                {
                    event_index_name = it->first;
                    break;
                }
            }

            sys_err("LUA_ERROR: quest %s.%s %s", GetCurrentQuestName().c_str(), state_name, event_index_name.c_str() );
            if (GetCurrentCharacterPtr() && test_server)
                GetCurrentCharacterPtr()->ChatPacket(CHAT_TYPE_PARTY, "LUA_ERROR: quest %s.%s %s", GetCurrentQuestName().c_str(), state_name, event_index_name.c_str() );
        }

    #ifndef __WIN32__
        void CQuestManager::QuestError(const char* func, int line, const char* fmt, ...)
        {
            char szMsg[4096];
            va_list args;

            va_start(args, fmt);
            vsnprintf(szMsg, sizeof(szMsg), fmt, args);
            va_end(args);

            _sys_err(func, line, "%s", szMsg);
            if (test_server)
            {
                LPCHARACTER ch = GetCurrentCharacterPtr();
                if (ch)
                {
                    ch->ChatPacket(CHAT_TYPE_PARTY, "error occurred on [%s:%d]", func,line);
                    ch->ChatPacket(CHAT_TYPE_PARTY, "%s", szMsg);
                }
            }
        }
    #else
        void CQuestManager::QuestError(const char* func, int line, const char* fmt, ...)
        {
            char szMsg[4096];
            va_list args;

            va_start(args, fmt);
            vsnprintf(szMsg, sizeof(szMsg), fmt, args);
            va_end(args);

            _sys_err(func, line, "%s", szMsg);
            if (test_server)
            {
                LPCHARACTER ch = GetCurrentCharacterPtr();
                if (ch)
                {
                    ch->ChatPacket(CHAT_TYPE_PARTY, "error occurred on [%s:%d]", func,line);
                    ch->ChatPacket(CHAT_TYPE_PARTY, "%s", szMsg);
                }
            }
        }
    #endif

        void CQuestManager::AddServerTimer(const std::string& name, DWORD arg, LPEVENT event)
        {
            sys_log(0, "XXX AddServerTimer %s %d %p", name.c_str(), arg, get_pointer(event));
            if (m_mapServerTimer.find(make_pair(name, arg)) != m_mapServerTimer.end())
            {
                sys_err("already registered server timer name:%s arg:%u", name.c_str(), arg);
                return;
            }
            m_mapServerTimer.insert(make_pair(make_pair(name, arg), event));
        }

        void CQuestManager::ClearServerTimerNotCancel(const std::string& name, DWORD arg)
        {
            m_mapServerTimer.erase(make_pair(name, arg));
        }

        void CQuestManager::ClearServerTimer(const std::string& name, DWORD arg)
        {
            itertype(m_mapServerTimer) it = m_mapServerTimer.find(make_pair(name, arg));
            if (it != m_mapServerTimer.end())
            {
                LPEVENT event = it->second;
                event_cancel(&event);
                m_mapServerTimer.erase(it);
            }
        }

        void CQuestManager::CancelServerTimers(DWORD arg)
        {
            itertype(m_mapServerTimer) it = m_mapServerTimer.begin();
            for ( ; it != m_mapServerTimer.end(); ++it) {
                if (it->first.second == arg) {
                    LPEVENT event = it->second;
                    event_cancel(&event);
                    m_mapServerTimer.erase(it);
                }
            }
        }

        void CQuestManager::SetServerTimerArg(DWORD dwArg)
        {
            m_dwServerTimerArg = dwArg;
        }

        DWORD CQuestManager::GetServerTimerArg()
        {
            return m_dwServerTimerArg;
        }

        void CQuestManager::SelectDungeon(LPDUNGEON pDungeon)
        {
            m_pSelectedDungeon = pDungeon;
        }
        
        bool CQuestManager::PickupItem(unsigned int pc, LPITEM item)
        {
            if (test_server)
                sys_log( 0, "questmanager::PickupItem Start : itemVnum : %d PC : %d", item->GetOriginalVnum(), pc);
            PC* pPC;
            if ((pPC = GetPC(pc)))
            {
                if (!CheckQuestLoaded(pPC))
                {
                    LPCHARACTER ch = CHARACTER_MANAGER::instance().FindByPID(pc);
                    if (ch)
                    {
                        ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("퀘스트를 로드하는 중입니다. 잠시만 기다려 주십시오."));
                    }
                    return false;
                }
                // call script
                SetCurrentItem(item);

                return m_mapNPC[item->GetVnum()].OnPickupItem(*pPC);
            }
            else
            {
                sys_err("QUEST PICK_ITEM_EVENT no such pc id : %d", pc);
                return false;
            }
        }
        void CQuestManager::BeginOtherPCBlock(DWORD pid)
        {
            LPCHARACTER ch = GetCurrentCharacterPtr();
            if (NULL == ch)
            {
                sys_err("NULL?");
                return;
            }
            /*
            # 1. current pid = pid0 <- It will be m_pOtherPCBlockRootPC.
            begin_other_pc_block(pid1)
                # 2. current pid = pid1
                begin_other_pc_block(pid2)
                    # 3. current_pid = pid2
                end_other_pc_block()
            end_other_pc_block()
            */
            // when begin_other_pc_block(pid1)
            if (m_vecPCStack.empty())
            {
                m_pOtherPCBlockRootPC = GetCurrentPC();
            }
            m_vecPCStack.push_back(GetCurrentCharacterPtr()->GetPlayerID());
            GetPC(pid);
        }

        void CQuestManager::EndOtherPCBlock()
        {
            if (m_vecPCStack.size() == 0)
            {
                sys_err("m_vecPCStack is alread empty. CurrentQuest{Name(%s), State(%s)}", GetCurrentQuestName().c_str(), GetCurrentState()->_title.c_str());
                return;
            }
            DWORD pc = m_vecPCStack.back();
            m_vecPCStack.pop_back();
            GetPC(pc);

            if (m_vecPCStack.empty())
            {
                m_pOtherPCBlockRootPC = NULL;
            }
        }

        bool CQuestManager::IsInOtherPCBlock()
        {
            return !m_vecPCStack.empty();
        }

        PC*    CQuestManager::GetOtherPCBlockRootPC()
        {
            return m_pOtherPCBlockRootPC;
        }
    }

     

  7. Hello Metin2dev,

     

    I got a problem when users are doing any dungeon they are kicked out and i checked the server side i got this game.core

     

    Example. now there was players on Demons Tower floor 3 and after that server kicked them out 

    happen on every dungeon

    spacer.png

     

    Anyone have anyidea how can i fix this  ? please is urgent i need help

  8. Solucion:

     

    Char.cpp  >  

    WORD CHARACTER::GetOriginalPart(BYTE bPartPos) const

     

    In that function  look for this > 

           

    case PART_WEAPON:
                return GetPart(PART_WEAPON);

     

    i just add like this 

     

    #if defined(CHANGELOOK_SYSTEM) && !defined(WEAPON_COSTUME_SYSTEM)
            case PART_WEAPON:
                return GetPart(PART_WEAPON);
    #endif

     

    This item.cpp part made by @MrQuin  thanks to him :)

     item.cpp 

     

    search for >  

    		case ITEM_WEAPON:
    			{
    				if (0 != m_pOwner->GetWear(WEAR_COSTUME_WEAPON))
    					break;
    
    				if (bAdd)
    				{

     

    above add

     

    	if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
    					{

     

    • Love 1
  9. Hello guys,

     

     

    Can anyone help me to fix this fc..... shit of bugg is getting the way to sucide almost..

     

     

    This bugg happen first like this.

     https://metin2.download/picture/F2wbYglMvaf4770F3T2kOcMBrrQpla06/.gif

    Explanation:  When i equip the weapon with our without transmutate the weapon  then i mount on Horse the weapon disappears and unmount also  happen on " Mounts"  or when using a Skill 

     

    Then i in Discord @flexio  helped me to do one thing i did this  in my "char.cpp"  was this unusual function:

     

    In

    void CHARACTER::EncodeInsertPacket(LPENTITY entity)

     I just removed this:

    CItem * pWeapon = GetWear(WEAR_COSTUME_WEAPON);
    	if (pWeapon)
    		SetPart(PART_WEAPON, pWeapon->GetVnum());	

    Result: 

     

    NOW the bugg was fixed and work but only if i create a new CHARACTER   when i ask to a old user with this Bugg they said me that the still have that bugg 

     

    How can i fix it please help me am able to pay for the fix:)

    You can find me in Mt2dev discord or leave comment here Please am helpless right now for this error :( i need really fix i hope you great people help with this fix :)

     

    I Can Pay for the Fix if anyone can fix it :)

    Thank you very Much

    Waiting for responsee............... 

     

     

     

  10. Still fucked up :v 

    Showing the bonuses wrong way 

     

    https://metin2.download/picture/HnbkI5PVZSFCw1iRn8T7xDtoV6F6Jb9d/.gif

     

    The problem still because when u absorb the bonuses of any item weapon or armour 

     

    in invetory u look good but in "General chat"  showing duplicates bonuses if weapon has "valor de ataque+1 "

    you use the shash in chat ctrl+click u will see "valor de ataque+1" x 2

    @owsap

     can u read Discord  please?

     

  11. 0526 23:53:25663 :: Traceback (most recent call last):
    
    0526 23:53:25663 ::   File "game.py", line 1802, in OnMouseLeftButtonUp
    
    0526 23:53:25663 ::   File "interfaceModule.py", line 462, in MakeHyperlinkTooltip
    
    0526 23:53:25663 ::   File "uiToolTip.py", line 2549, in SetHyperlinkItem
    
    0526 23:53:25663 :: NameError
    0526 23:53:25663 :: : 
    0526 23:53:25663 :: global name 'transmutation' is not defined

    When i try to click in chat  https://metin2.download/picture/m6iaJxZwBitV23oXZEBzO32A7n8Y9KWu/.png

     

     

    Sorry but i hate python always fucked up 

  12. PyObject * playerGetItemLink(PyObject * poSelf, PyObject * poArgs)
    {
    	TItemPos Cell;
    
    	switch (PyTuple_Size(poArgs))
    	{
    	case 1:
    		if (!PyTuple_GetInteger(poArgs, 0, &Cell.cell))
    			return Py_BuildException();
    		break;
    	case 2:
    		if (!PyTuple_GetByte(poArgs, 0, &Cell.window_type))
    			return Py_BuildException();
    		if (!PyTuple_GetInteger(poArgs, 1, &Cell.cell))
    			return Py_BuildException();
    		break;
    	default:
    		return Py_BuildException();
    	}
    	const TItemData * pPlayerItem = CPythonPlayer::Instance().GetItemData(Cell);
    	CItemData * pItemData = NULL;
    	char buf[1024];
    
    	if (pPlayerItem && CItemManager::Instance().GetItemDataPointer(pPlayerItem->vnum, &pItemData))
    	{
    #ifdef ENABLE_CHANGELOOK_SYSTEM
    		char itemlink[256 + 12];
    #else
    		char itemlink[256];
    #endif
    		int len;
    		bool isAttr = false;
    
    		len = snprintf(itemlink, sizeof(itemlink), "item:%x:%x:%x:%x:%x",
    				pPlayerItem->vnum, pPlayerItem->flags,
    				pPlayerItem->alSockets[0], pPlayerItem->alSockets[1], pPlayerItem->alSockets[2]);
    #ifdef ENABLE_CHANGELOOK_SYSTEM
    		len += snprintf(itemlink + len, sizeof(itemlink) - len, ":%x", pPlayerItem->transmutation);
    #endif
    		for (int i = 0; i < ITEM_ATTRIBUTE_SLOT_MAX_NUM; ++i)
    			if (pPlayerItem->aAttr[i].bType != 0)
    			{
    				len += snprintf(itemlink + len, sizeof(itemlink) - len, ":%x:%d",
    						pPlayerItem->aAttr[i].bType, pPlayerItem->aAttr[i].sValue);
    				isAttr = true;
    			}
    
    
    		if( GetDefaultCodePage() == CP_ARABIC ) {
    			if (isAttr)
    				//"item:번호:플래그:소켓0:소켓1:소켓2"
    				snprintf(buf, sizeof(buf), " |h|r[%s]|cffffc700|H%s|h", pItemData->GetName(), itemlink);
    			else
    				snprintf(buf, sizeof(buf), " |h|r[%s]|cfff1e6c0|H%s|h", pItemData->GetName(), itemlink);
    		} else {
    			if (isAttr)
    				//"item:번호:플래그:소켓0:소켓1:소켓2"
    				snprintf(buf, sizeof(buf), "|cffffc700|H%s|h[%s]|h|r", itemlink, pItemData->GetName());
    			else
    				snprintf(buf, sizeof(buf), "|cfff1e6c0|H%s|h[%s]|h|r", itemlink, pItemData->GetName());
    		}
    	}
    	else
    		buf[0] = '\0';
    
    	return Py_BuildValue("s", buf);
    }

     

    uitooltip.py

     

    class HyperlinkItemToolTip(ItemToolTip):
    	def __init__(self):
    		ItemToolTip.__init__(self, isPickable=TRUE)
    
    	def SetHyperlinkItem(self, tokens):
    		minTokenCount = 3 + player.METIN_SOCKET_MAX_NUM
    		if app.ENABLE_CHANGELOOK_SYSTEM:
    			minTokenCount += 1
    		maxTokenCount = minTokenCount + 2 * player.ATTRIBUTE_SLOT_MAX_NUM
    		if tokens and len(tokens) >= minTokenCount and len(tokens) <= maxTokenCount:
    			head, vnum, flag = tokens[:3]
    			itemVnum = int(vnum, 16)
    			metinSlot = [int(metin, 16) for metin in tokens[3:6]]
    
    			rests = tokens[6:]
    			transmutation = 0
    			if app.ENABLE_CHANGELOOK_SYSTEM:
    				rests = tokens[7:]
    				cnv = [int(cnv, 16) for cnv in tokens[6:7]]
    				transmutation = int(cnv[0])
    			if rests:
    				attrSlot = []
    
    				rests.reverse()
    				while rests:
    					key = int(rests.pop(), 16)
    					if rests:
    						val = int(rests.pop())
    						attrSlot.append((key, val))
    
    				attrSlot += [(0, 0)] * (player.ATTRIBUTE_SLOT_MAX_NUM - len(attrSlot))
    			else:
    				attrSlot = [(0, 0)] * player.ATTRIBUTE_SLOT_MAX_NUM
    
    			self.ClearToolTip()
    			if app.ENABLE_CHANGELOOK_SYSTEM:
    				if not transmutation:
    					self.AddItemData(itemVnum, metinSlot, attrSlot, 1)
    				else:
    					self.AddItemData(itemVnum, metinSlot, attrSlot, 1, 0, 0, player.INVENTORY, -1, transmutation)
    			else:
    				self.AddItemData(itemVnum, metinSlot, attrSlot, 1)#try
    			ItemToolTip.OnUpdate(self)
    
    	def OnUpdate(self):
    		pass
    
    	def OnMouseLeftButtonDown(self):
    		self.Hide()

     

    Yes i use change look system

  13. Hello Metin2dev,

     

     

    I have little problem that i was trying to fix but i didn`t find the way

     

    Please look this Gif  i absob the weapon bonus in shash but in inventory i showing correct bonuses of my weapon 

     

    if i do Ctrl+ click to show in a global chat or in PM is show other Bonuses

     

    https://metin2.download/picture/47065SP4b2AlYaln0y8ZnXUyLwEl7OUm/.gif

     

    Please help :)

  14. 0526 18:01:11466 :: 
    playerSettingModule.py(line:1426) LoadGameData
    playerSettingModule.py(line:344) __LoadGameEffect
    
    LoadGameData - <type 'exceptions.AttributeError'>:'module' object has no attribute 'EFFECT_BOSS'
    
    0526 18:01:11466 :: ============================================================================================================
    0526 18:01:11466 :: Abort!!!!

    i Install all well but when try to enter in client in Loading client close and gived me this sysser

    Solved  thnx

     

     

    Solved :$

    30 minutes ago, Arkane2 said:

    0526 18:01:11466 ::  playerSettingModule.py(line:1426) LoadGameData playerSettingModule.py(line:344) __LoadGameEffect LoadGameData - <type 'exceptions.AttributeError'>:'module' object has no attribute 'EFFECT_BOSS' 0526 18:01:11466 :: ============================================================================================================ 0526 18:01:11466 :: Abort!!!!

    
    0526 18:01:11466 :: 
    playerSettingModule.py(line:1426) LoadGameData
    playerSettingModule.py(line:344) __LoadGameEffect
    
    LoadGameData - <type 'exceptions.AttributeError'>:'module' object has no attribute 'EFFECT_BOSS'
    
    0526 18:01:11466 :: ============================================================================================================
    0526 18:01:11466 :: Abort!!!!

    i Install all well but when try to enter in client in Loading client close and gived me this sysser

    Solved  thnx

     

     

    Solved :$

     

     

    i Solved this error all work fine but the effect not appeares on any BOSS  i can not see any effect ?xd 

×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.