Beispiel #1
0
void CSector::RespawnDeadNPCs()
{
	ADDTOCALLSTACK("CSector::RespawnDeadNPCs");
	// skip sectors in unsupported maps
	if ( !g_MapList.m_maps[m_map] ) return;

	// Respawn dead NPC's
	CChar * pCharNext;
	CChar * pChar = STATIC_CAST <CChar *>( m_Chars_Disconnect.GetHead());
	for ( ; pChar != NULL; pChar = pCharNext )
	{
		pCharNext = pChar->GetNext();
		if ( ! pChar->m_pNPC )
			continue;
		if ( ! pChar->m_ptHome.IsValidPoint())
			continue;
		if ( ! pChar->IsStatFlag( STATF_DEAD ))
			continue;

		// Restock them with npc stuff.
		pChar->NPC_LoadScript(true);

		// Res them back to their "home".
		int iDist = pChar->m_pNPC->m_Home_Dist_Wander;
		pChar->MoveNear( pChar->m_ptHome, ( iDist < SHRT_MAX ) ? iDist : 4 );
		pChar->NPC_CreateTrigger(); //Removed from NPC_LoadScript() and triggered after char placement
		pChar->Spell_Resurrection();
	}
}
Beispiel #2
0
void CSector::SetLightNow( bool fFlash )
{
	ADDTOCALLSTACK("CSector::SetLightNow");
	// Set the light level for all the CClients here.

	CChar * pChar = STATIC_CAST <CChar*>( m_Chars_Active.GetHead());
	for ( ; pChar != NULL; pChar = pChar->GetNext())
	{
		if ( pChar->IsStatFlag( STATF_DEAD | STATF_NightSight ))
			continue;

		if ( pChar->IsClient())
		{
			CClient * pClient = pChar->GetClient();
			ASSERT(pClient);

			if ( fFlash )	// This does not seem to work predicably !
			{
				BYTE bPrvLight = m_Env.m_Light;
				m_Env.m_Light = LIGHT_BRIGHT;	// full bright.
				pClient->addLight();
				m_Env.m_Light = bPrvLight;	// back to previous.
			}
			pClient->addLight();
		}

		// don't fire trigger when server is loading or light is flashing
		if (( ! g_Serv.IsLoading() && fFlash == false ) && ( IsTrigUsed(TRIGGER_ENVIRONCHANGE) ))
		{
			pChar->OnTrigger( CTRIG_EnvironChange, pChar );
		}
	}
}
Beispiel #3
0
CChar *CItemCorpse::IsCorpseSleeping() const
{
	ADDTOCALLSTACK("CItemCorpse::IsCorpseSleeping");
	// Is this corpse really a sleeping person ?
	// CItemCorpse
	if ( !IsType(IT_CORPSE) )
	{
		DEBUG_ERR(("Corpse (0%x) doesn't have type T_CORPSE! (it has %d)\n", (dword)GetUID(), GetType()));
		return NULL;
	}

	CChar *pCharCorpse = m_uidLink.CharFind();
	if ( pCharCorpse && pCharCorpse->IsStatFlag(STATF_Sleeping) && !GetTimeStamp().IsTimeValid() )
		return pCharCorpse;

	return NULL;
}
Beispiel #4
0
bool CClient::Cmd_Skill_Tracking( WORD track_sel, bool bExec )
{
	ADDTOCALLSTACK("CClient::Cmd_Skill_Tracking");
	// look around for stuff.

	ASSERT(m_pChar);
	if ( track_sel == USHRT_MAX )
	{
		// Unlike others skills, Tracking is used during menu setup
		m_pChar->Skill_Cleanup();	// clean up current skill

		CMenuItem item[6];
		item[0].m_sText = g_Cfg.GetDefaultMsg(DEFMSG_TRACKING_SKILLMENU_TITLE);

		item[1].m_id = ITEMID_TRACK_HORSE;
		item[1].m_color = 0;
		item[1].m_sText = g_Cfg.GetDefaultMsg(DEFMSG_TRACKING_SKILLMENU_ANIMALS);
		item[2].m_id = ITEMID_TRACK_OGRE;
		item[2].m_color = 0;
		item[2].m_sText = g_Cfg.GetDefaultMsg(DEFMSG_TRACKING_SKILLMENU_MONSTERS);
		item[3].m_id = ITEMID_TRACK_MAN;
		item[3].m_color = 0;
		item[3].m_sText = g_Cfg.GetDefaultMsg(DEFMSG_TRACKING_SKILLMENU_NPCS);
		item[4].m_id = ITEMID_TRACK_WOMAN;
		item[4].m_color = 0;
		item[4].m_sText = g_Cfg.GetDefaultMsg(DEFMSG_TRACKING_SKILLMENU_PLAYERS);

		m_tmMenu.m_Item[0] = 0;
		addItemMenu(CLIMODE_MENU_SKILL_TRACK_SETUP, item, 4);
		return true;
	}

	if ( track_sel > 0 ) // Not Cancelled
	{
		ASSERT(track_sel < COUNTOF(m_tmMenu.m_Item));
		if ( bExec )
		{
			// Tracking menu got us here. Start tracking the selected creature.
			m_pChar->SetTimeout(1 * TICK_PER_SEC);
			m_pChar->m_Act_Targ = static_cast<CGrayUID>(m_tmMenu.m_Item[track_sel]);
			m_pChar->Skill_Start(SKILL_TRACKING);
			return true;
		}

		static const NPCBRAIN_TYPE sm_Track_Brain[] =
		{
			NPCBRAIN_QTY,	// not used here
			NPCBRAIN_ANIMAL,
			NPCBRAIN_MONSTER,
			NPCBRAIN_HUMAN,
			NPCBRAIN_NONE	// players
		};

		if ( track_sel >= COUNTOF(sm_Track_Brain) )
			track_sel = COUNTOF(sm_Track_Brain) - 1;

		NPCBRAIN_TYPE track_type = sm_Track_Brain[track_sel];
		CMenuItem item[minimum(MAX_MENU_ITEMS, COUNTOF(m_tmMenu.m_Item))];
		size_t count = 0;

		item[0].m_sText = g_Cfg.GetDefaultMsg(DEFMSG_TRACKING_SKILLMENU_TITLE);
		m_tmMenu.m_Item[0] = track_sel;

		CWorldSearch AreaChars(m_pChar->GetTopPoint(), m_pChar->Skill_GetBase(SKILL_TRACKING) / 10 + 10);
		for (;;)
		{
			CChar *pChar = AreaChars.GetChar();
			if ( !pChar )
				break;
			if ( pChar == m_pChar )
				continue;

			if ( pChar->GetNPCBrain() != track_type )
				continue;
			if ( pChar->IsStatFlag(STATF_DEAD) )	// can't track ghosts
				continue;

			if ( pChar->m_pPlayer )
			{
				// Prevent track hidden GMs
				if ( pChar->IsStatFlag(STATF_Insubstantial) && (pChar->GetPrivLevel() > GetPrivLevel()) )
					continue;

				// Check action difficulty when trying to track players
				int tracking = m_pChar->Skill_GetBase(SKILL_TRACKING);
				int detectHidden = m_pChar->Skill_GetBase(SKILL_DETECTINGHIDDEN);
				if ( (g_Cfg.m_iRacialFlags & RACIALF_ELF_DIFFTRACK) && pChar->IsElf() )
					tracking /= 2;			// elves are more difficult to track (Difficult to Track racial trait)

				int hiding = pChar->Skill_GetBase(SKILL_HIDING);
				int stealth = pChar->Skill_GetBase(SKILL_STEALTH);
				int divisor = maximum(hiding + stealth, 1);

				int chance;
				if ( g_Cfg.m_iFeatureSE & FEATURE_SE_UPDATE )
					chance = 50 * (tracking * 2 + detectHidden) / divisor;
				else
					chance = 50 * (tracking + detectHidden + 10 * Calc_GetRandVal(20)) / divisor;

				if ( Calc_GetRandVal(100) > chance )
					continue;
			}

			CCharBase *pCharDef = pChar->Char_GetDef();
			if ( !pCharDef )
				continue;

			count++;
			item[count].m_id = static_cast<WORD>(pCharDef->m_trackID);
			item[count].m_color = 0;
			item[count].m_sText = pChar->GetName();
			m_tmMenu.m_Item[count] = pChar->GetUID();

			if ( count >= COUNTOF(item) - 1 )
				break;
		}

		// Some credit for trying
		if ( count > 0 )
		{
			m_pChar->Skill_UseQuick(SKILL_TRACKING, 20 + Calc_GetRandLLVal(30));
			ASSERT(count < COUNTOF(item));
			addItemMenu(CLIMODE_MENU_SKILL_TRACK, item, count);
			return true;
		}
		else
		{
			// Tracking failed or cancelled
			m_pChar->Skill_UseQuick(SKILL_TRACKING, 10 + Calc_GetRandLLVal(30));

			static LPCTSTR const sm_Track_FailMsg[] =
			{
				g_Cfg.GetDefaultMsg(DEFMSG_TRACKING_FAIL_ANIMAL),
				g_Cfg.GetDefaultMsg(DEFMSG_TRACKING_FAIL_MONSTER),
				g_Cfg.GetDefaultMsg(DEFMSG_TRACKING_FAIL_PEOPLE),
				g_Cfg.GetDefaultMsg(DEFMSG_TRACKING_FAIL_PEOPLE)
			};

			if ( sm_Track_FailMsg[track_sel - 1] )
				SysMessage(sm_Track_FailMsg[track_sel - 1]);
		}
	}
	return false;
}
Beispiel #5
0
void CSector::OnTick(int iPulseCount)
{
	ADDTOCALLSTACK_INTENSIVE("CSector::OnTick");
	// CWorld gives OnTick() to all CSectors.

	EXC_TRY("Tick");
	EXC_SET("light change");

	//	do not tick sectors on maps not supported by server
	if ( !g_MapList.m_maps[m_map] ) return;

	// Check for light change before putting the sector to sleep, since in other case the
	// world light levels will be shitty
	bool fEnvironChange = false;
	bool fLightChange = false;
	bool fSleeping = false;

	if ( ! ( iPulseCount & 0x7f ))	// 30 seconds or so.
	{
		// check for local light level change ?
		BYTE blightprv = m_Env.m_Light;
		m_Env.m_Light = GetLightCalc( false );
		if ( m_Env.m_Light != blightprv )
		{
			fEnvironChange = true;
			fLightChange = true;
		}
	}

	EXC_SET("sector sleeping?");
	size_t clients = m_Chars_Active.HasClients();

	if ( clients <= 0 ) // having no clients inside
	{
		// Put the sector to sleep if no clients been here in a while.
		fSleeping = IsSectorSleeping();
		if ( fSleeping )
		{
			if ( !g_Cfg.m_iSectorSleepMask )
				return;
			if (( iPulseCount & g_Cfg.m_iSectorSleepMask ) != ( GetIndex() & g_Cfg.m_iSectorSleepMask ))
				return;
		}
	}

	EXC_SET("sound effects");
	// random weather noises and effects.
	SOUND_TYPE sound = 0;
	bool fWeatherChange = false;
	int iRegionPeriodic = 0;

	if ( ! ( iPulseCount & 0x7f ))	// 30 seconds or so.
	{
		// Only do this every x minutes or so (TICK_PER_SEC)
		// check for local weather change ?
		WEATHER_TYPE weatherprv = m_Env.m_Weather;
		if ( ! Calc_GetRandVal( 30 ))	// change less often
		{
			m_Env.m_Weather = GetWeatherCalc();
			if ( weatherprv != m_Env.m_Weather )
			{
				fWeatherChange = true;
				fEnvironChange = true;
			}
		}

		// Random area noises. Only do if clients about.
		if ( clients > 0 )
		{
			iRegionPeriodic = 2;

			static const SOUND_TYPE sm_SfxRain[] = { 0x10, 0x11 };
			static const SOUND_TYPE sm_SfxWind[] = { 0x14, 0x15, 0x16 };
			static const SOUND_TYPE sm_SfxThunder[] = { 0x28, 0x29 , 0x206 };

			// Lightning ?	// wind, rain,
			switch ( GetWeather() )
			{
				case WEATHER_CLOUDY:
					break;

				case WEATHER_SNOW:
					if ( ! Calc_GetRandVal(5) )
						sound = sm_SfxWind[ Calc_GetRandVal( COUNTOF( sm_SfxWind )) ];
					break;

				case WEATHER_RAIN:
					{
						int iVal = Calc_GetRandVal(30);
						if ( iVal < 5 )
						{
							// Mess up the light levels for a sec..
							LightFlash();
							sound = sm_SfxThunder[ Calc_GetRandVal( COUNTOF( sm_SfxThunder )) ];
						}
						else if ( iVal < 10 )
							sound = sm_SfxRain[ Calc_GetRandVal( COUNTOF( sm_SfxRain )) ];
						else if ( iVal < 15 )
							sound = sm_SfxWind[ Calc_GetRandVal( COUNTOF( sm_SfxWind )) ];
					}
					break;

				default:
					break;
			}
		}
	}

	// regen all creatures and do AI

	ProfileTask charactersTask(PROFILE_CHARS);

	//pChar = STATIC_CAST <CChar*>( m_Chars_Active.GetHead());
	CChar * pCharNext = NULL;
	CChar * pChar = dynamic_cast <CChar*>( m_Chars_Active.GetHead());
	for ( ; pChar != NULL; pChar = pCharNext )
	{
		EXC_TRYSUB("TickChar");

		pCharNext = pChar->GetNext();
		if (( fEnvironChange ) && ( IsTrigUsed(TRIGGER_ENVIRONCHANGE) ))
			pChar->OnTrigger(CTRIG_EnvironChange, pChar);

		if ( pChar->IsClient())
		{
			CClient * pClient = pChar->GetClient();
			ASSERT( pClient );
			if ( sound )
				pClient->addSound(sound, pChar);

			if ( fLightChange && ! pChar->IsStatFlag( STATF_DEAD | STATF_NightSight ))
				pClient->addLight();

			if ( fWeatherChange )
				pClient->addWeather(GetWeather());

			if ( iRegionPeriodic && pChar->m_pArea )
			{
				if (( iRegionPeriodic == 2 )&&( IsTrigUsed(TRIGGER_REGPERIODIC) ))
				{
					pChar->m_pArea->OnRegionTrigger( pChar, RTRIG_REGPERIODIC );
					iRegionPeriodic--;
				}
				if ( IsTrigUsed(TRIGGER_CLIPERIODIC) )
					pChar->m_pArea->OnRegionTrigger( pChar, RTRIG_CLIPERIODIC );
			}
		}
		// Can only die on your own tick.
		if ( !pChar->OnTick() )
			pChar->Delete();

		EXC_CATCHSUB("Sector");

		EXC_DEBUGSUB_START;
		CPointMap pt = GetBasePoint();
		g_Log.EventDebug("char 0%lx '%s'\n", static_cast<DWORD>(pChar->GetUID()), pChar->GetName());
		g_Log.EventDebug("sector #%d [%d,%d,%d,%d]\n", GetIndex(),  pt.m_x, pt.m_y, pt.m_z, pt.m_map);
		EXC_DEBUGSUB_END;
	}

	// decay items on ground = time out spells / gates etc.. etc..
	// No need to check these so often !

	ProfileTask itemsTask(PROFILE_ITEMS);

	CItem * pItemNext = NULL;
	CItem * pItem = dynamic_cast <CItem*>( m_Items_Timer.GetHead());
	for ( ; pItem != NULL; pItem = pItemNext )
	{
		EXC_TRYSUB("TickItem");
		pItemNext = pItem->GetNext();

		EXC_SETSUB("TimerExpired");
		if ( pItem->IsTimerExpired() )
		{
			EXC_SETSUB("ItemTick");
			if ( !pItem->OnTick() )
			{
				EXC_SETSUB("ItemDelete");
				pItem->Delete();
			}
			else
			{
				EXC_SETSUB("TimerExpired2");
				if ( pItem->IsTimerExpired() )	// forgot to clear the timer.? strange.
				{
					EXC_SETSUB("SetTimeout");
					pItem->SetTimeout(-1);
				}
			}
		}

		EXC_SETSUB("UpdateFlags");
		pItem->OnTickStatusUpdate();

#ifdef _WIN32
		EXC_CATCHSUB("Sector");

		EXC_DEBUGSUB_START;
		CPointMap pt = GetBasePoint();
		g_Log.EventError("item 0%lx '%s' [timer=%lld, type=%lld]\n", static_cast<DWORD>(pItem->GetUID()), pItem->GetName(), pItem->GetTimerAdjusted(), static_cast<int>(pItem->GetType()));
		g_Log.EventError("sector #%d [%d,%d,%d,%d]\n", GetIndex(),  pt.m_x, pt.m_y, pt.m_z, pt.m_map);
		
		EXC_DEBUGSUB_END;
#else
		}
#ifndef _DEBUG
		catch ( const CGrayError& e )
Beispiel #6
0
bool CWebPageDef::r_Verb( CScript & s, CTextConsole * pSrc )	// some command on this object as a target
{
	ADDTOCALLSTACK("CWebPageDef::r_Verb");
	EXC_TRY("Verb");
	ASSERT(pSrc);
	sm_iListIndex = 0;
	TCHAR *pszTmp2 = Str_GetTemp();

	WV_TYPE iHeadKey = (WV_TYPE) FindTableSorted( s.GetKey(), sm_szVerbKeys, COUNTOF(sm_szVerbKeys)-1 );
	switch ( iHeadKey )
	{
		case WV_WEBPAGE:
		{
			// serv a web page to the pSrc
			CClient *pClient = dynamic_cast<CClient *>(pSrc);
			if ( !pClient )
				return false;
			return ServPage(pClient, s.GetArgStr(), NULL);
		}
	
		case WV_CLIENTLIST:
		{
			ClientIterator it;
			for ( CClient *pClient = it.next(); pClient != NULL; pClient = it.next() )
			{
				CChar *pChar = pClient->GetChar();
				if ( !pChar )
					continue;
				if ( pChar->IsStatFlag(STATF_Insubstantial) && (pClient->GetPrivLevel() > PLEVEL_Player) )
					continue;

				sm_iListIndex++;

				LPCTSTR pszArgs = s.GetArgStr();
				if ( pszArgs[0] == '\0' )
					pszArgs = "<tr><td>%NAME%</td><td>%REGION.NAME%</td></tr>\n";
				strcpy(pszTmp2, pszArgs);
				pChar->ParseText(Str_MakeFiltered(pszTmp2), &g_Serv, 1);
				pSrc->SysMessage(pszTmp2);
			}
			break;
		}
	
		case WV_GUILDLIST:
		case WV_TOWNLIST:
		{
			if ( !s.HasArgs() )
				return false;

			IT_TYPE	needtype = (iHeadKey == WV_GUILDLIST) ? IT_STONE_GUILD : IT_STONE_TOWN;

			for ( size_t i = 0; i < g_World.m_Stones.GetCount(); i++ )
			{
				CItemStone *pStone = g_World.m_Stones[i];
				if ( !pStone || !pStone->IsType(needtype) )
					continue;

				sm_iListIndex++;

				strcpy(pszTmp2, s.GetArgStr());
				pStone->ParseText(Str_MakeFiltered(pszTmp2), &g_Serv, 1);
				pSrc->SysMessage(pszTmp2);
			}
			break;
		}

		case WV_GMPAGELIST:
		{
			if ( !s.HasArgs() )
				return false;
			CGMPage *pPage = static_cast<CGMPage *>(g_World.m_GMPages.GetHead());
			for ( ; pPage != NULL; pPage = pPage->GetNext() )
			{
				sm_iListIndex++;
				strcpy(pszTmp2, s.GetArgStr());
				pPage->ParseText(Str_MakeFiltered(pszTmp2), &g_Serv, 1);
				pSrc->SysMessage(pszTmp2);
			}
			break;
		}
	
		default:
			return CResourceLink::r_Verb(s, pSrc);
	}
	return true;
	EXC_CATCH;

	EXC_DEBUG_START;
	EXC_ADD_SCRIPTSRC;
	EXC_DEBUG_END;
	return false;
}
Beispiel #7
0
bool CSector::OnTick()
{
	ADDTOCALLSTACK("CSector::OnTick");
	/*Ticking sectors from CWorld
    * Timer is automatically updated at the end with a 30 seconds default delay
    * Any return before it will threat this CSector as Sleep and will make it
    * not tick again until a new player enters (WARNING: even if there are
    * players already inside).
    */

	EXC_TRY("Tick");

	//	do not tick sectors on maps not supported by server
	if ( !g_MapList.m_maps[m_map] )
		return true;

    EXC_SET_BLOCK("light change");
	// Check for light change before putting the sector to sleep, since in other case the
	// world light levels will be shitty
	bool fEnvironChange = false;
	bool fLightChange = false;

	// check for local light level change ?
	byte bLightPrv = m_Env.m_Light;
	m_Env.m_Light = GetLightCalc( false );
	if ( m_Env.m_Light != bLightPrv )
	{
		fEnvironChange = true;
		fLightChange = true;
	}

	EXC_SET_BLOCK("sector sleeping?");
    bool fCanSleep = CanSleep(true);
    int64 iCurTime = CServerTime::GetCurrentTime().GetTimeRaw();

	// Put the sector to sleep if no clients been here in a while.
	if (fCanSleep && (g_Cfg._iSectorSleepDelay > 0))
	{
        if (!IsSleeping())
        {
            GoSleep();
        }
		return true;
	}


	EXC_SET_BLOCK("sound effects");
	// random weather noises and effects.
	SOUND_TYPE sound = 0;
	bool fWeatherChange = false;
	int iRegionPeriodic = 0;

	WEATHER_TYPE weatherprv = m_Env.m_Weather;
	if ( ! Calc_GetRandVal( 30 ))	// change less often
	{
		m_Env.m_Weather = GetWeatherCalc();
		if ( weatherprv != m_Env.m_Weather )
		{
			fWeatherChange = true;
			fEnvironChange = true;
		}
	}

	// Random area noises. Only do if clients about.
	if ( GetClientsNumber() > 0 )
	{
		iRegionPeriodic = 2;

		static const SOUND_TYPE sm_SfxRain[] = { 0x10, 0x11 };
		static const SOUND_TYPE sm_SfxWind[] = { 0x14, 0x15, 0x16 };
		static const SOUND_TYPE sm_SfxThunder[] = { 0x28, 0x29 , 0x206 };

		// Lightning ?	// wind, rain,
		switch ( GetWeather() )
		{
			case WEATHER_CLOUDY:
				break;

			case WEATHER_SNOW:
				if ( ! Calc_GetRandVal(5) )
					sound = sm_SfxWind[ Calc_GetRandVal( CountOf( sm_SfxWind )) ];
				break;

			case WEATHER_RAIN:
				{
					int iVal = Calc_GetRandVal(30);
					if ( iVal < 5 )
					{
						// Mess up the light levels for a sec..
						LightFlash();
						sound = sm_SfxThunder[ Calc_GetRandVal( CountOf( sm_SfxThunder )) ];
					}
					else if ( iVal < 10 )
						sound = sm_SfxRain[ Calc_GetRandVal( CountOf( sm_SfxRain )) ];
					else if ( iVal < 15 )
						sound = sm_SfxWind[ Calc_GetRandVal( CountOf( sm_SfxWind )) ];
				}
				break;

			default:
				break;
		}
	}

    // Check environ changes and inform clients of it.
	ProfileTask charactersTask(PROFILE_CHARS);

	CChar * pCharNext = nullptr;
	CChar * pChar = static_cast <CChar*>( m_Chars_Active.GetHead());
	for ( ; pChar != nullptr; pChar = pCharNext )
	{
		EXC_TRYSUB("TickChar");

		pCharNext = pChar->GetNext();

		if (( fEnvironChange ) && ( IsTrigUsed(TRIGGER_ENVIRONCHANGE) ))
			pChar->OnTrigger(CTRIG_EnvironChange, pChar);

		if ( pChar->IsClient())
		{
			CClient * pClient = pChar->GetClient();
			ASSERT( pClient );
			if ( sound )
				pClient->addSound(sound, pChar);

			if ( fLightChange && ! pChar->IsStatFlag( STATF_DEAD | STATF_NIGHTSIGHT ))
				pClient->addLight();

			if ( fWeatherChange )
				pClient->addWeather(GetWeather());

			if ( iRegionPeriodic && pChar->m_pArea )
			{
				if ( ( iRegionPeriodic == 2 ) && IsTrigUsed(TRIGGER_REGPERIODIC))
				{
					pChar->m_pArea->OnRegionTrigger( pChar, RTRIG_REGPERIODIC );
					--iRegionPeriodic;
				}
				if ( IsTrigUsed(TRIGGER_CLIPERIODIC) )
					pChar->m_pArea->OnRegionTrigger( pChar, RTRIG_CLIPERIODIC );
			}
		}

		EXC_CATCHSUB("Sector");

		EXC_DEBUGSUB_START;
		CPointMap pt = GetBasePoint();
		g_Log.EventDebug("#0 char 0%x '%s'\n", (dword)(pChar->GetUID()), pChar->GetName());
		g_Log.EventDebug("#0 sector #%d [%d,%d,%d,%d]\n", GetIndex(),  pt.m_x, pt.m_y, pt.m_z, pt.m_map);
		EXC_DEBUGSUB_END;
	}

	ProfileTask overheadTask(PROFILE_OVERHEAD);

	EXC_SET_BLOCK("check map cache");
	if (fCanSleep && m_iMapBlockCacheTime < iCurTime)     // Only if the sector can sleep.
	{
		// delete the static CServerMapBlock items that have not been used recently.
		m_iMapBlockCacheTime = CServerTime::GetCurrentTime().GetTimeRaw() + g_Cfg.m_iMapCacheTime ;
		CheckMapBlockCache();
	}
	EXC_CATCH;

    SetTimeoutS(30);  // Sector is Awake, make it tick after 30 seconds.

	EXC_DEBUG_START;
	CPointMap pt = GetBasePoint();
	g_Log.EventError("#4 sector #%d [%hd,%hd,%hhd,%hhu]\n", GetIndex(), pt.m_x, pt.m_y, pt.m_z, pt.m_map);
	EXC_DEBUG_END;
    return true;
}