TRIGRET_TYPE CScriptObj::OnTriggerForLoop( CScript &s, int iType, CTextConsole * pSrc, CScriptTriggerArgs * pArgs, CGString * pResult )
{
	// loop from start here to the ENDFOR
	// See WebPageScriptList for dealing with Arrays.

	CScriptLineContext StartContext = s.GetContext();
	CScriptLineContext EndContext = StartContext;
	int LoopsMade = 0;

	if ( iType & 8 )		// WHILE
	{
		TCHAR *		pszCond;
		TCHAR		*pszOrig = Str_GetTemp();
		TCHAR		*pszTemp = Str_GetTemp();
		int			iWhile	= 0;

		strcpy( pszOrig, s.GetArgStr() );
		while(true)
		{
			LoopsMade++;
			if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes ))
				goto toomanyloops;

			pArgs->m_VarsLocal.SetNum( "_WHILE", iWhile, false );
			iWhile++;
			strcpy( pszTemp, pszOrig );
			pszCond	= pszTemp;
			ParseText( pszCond, pSrc, 0, pArgs );
			if ( !Exp_GetVal( pszCond ) )
				break;
			TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult );
			if ( iRet != TRIGRET_ENDIF )
			{
				return( iRet );
			}
			EndContext = s.GetContext();
			s.SeekContext( StartContext );
		}
	}
	else
		ParseText( s.GetArgStr(), pSrc, 0, pArgs );


	
	if ( iType & 4 )		// FOR
	{
		int			fCountDown		= FALSE;
		int			iMin			= 0;
		int			iMax			= 0;
		int			i;
		TCHAR *		ppArgs[3];
		int			iQty			= Str_ParseCmds( s.GetArgStr(), ppArgs, 3, ", " );
		CGString	sLoopVar	= "_FOR";
		
		switch( iQty )
		{
		case 1:		// FOR x
			iMin	= 1;
			iMax	= Exp_GetSingle( ppArgs[0] );
			break;
		case 2:
			if ( isdigit( *ppArgs[0] ) )
			{
				iMin	= Exp_GetSingle( ppArgs[0] );
				iMax	= Exp_GetSingle( ppArgs[1] );
			}
			else
			{
				iMin		= 1;
				iMax		= Exp_GetSingle( ppArgs[1] );
				sLoopVar	= ppArgs[0];
			}
			break;
		case 3:
			sLoopVar	= ppArgs[0];
			iMin		= Exp_GetSingle( ppArgs[1] );;
			iMax		= Exp_GetSingle( ppArgs[2] );
			break;
		default:
			iMin	= iMax		= 1;
			break;
		}

		if ( iMin > iMax )
			fCountDown	= true;

		if ( fCountDown )
			for ( i = iMin; i >= iMax; --i )
			{
				LoopsMade++;
				if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes ))
					goto toomanyloops;

				pArgs->m_VarsLocal.SetNum( sLoopVar, i, false );
				TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult );
				if ( iRet != TRIGRET_ENDIF )
				{
					return( iRet );
				}
				EndContext = s.GetContext();
				s.SeekContext( StartContext );
			}
		else
			for ( i = iMin; i <= iMax; ++i )
			{
				LoopsMade++;
				if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes ))
					goto toomanyloops;

				pArgs->m_VarsLocal.SetNum( sLoopVar, i, false );
				TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult );
				if ( iRet != TRIGRET_ENDIF )
				{
					return( iRet );
				}
				EndContext = s.GetContext();
				s.SeekContext( StartContext );
			}
	}

	if ( (iType & 1) || (iType & 2) )
	{
		int iDist;
		if ( s.HasArgs() )
			iDist = s.GetArgVal();
		else
			iDist = UO_MAP_VIEW_SIZE;

		CObjBaseTemplate * pObj = dynamic_cast <CObjBaseTemplate *>(this);
		if ( pObj == NULL )
		{
			iType = 0;
			DEBUG_ERR(( "FOR Loop trigger on non-world object '%s'\n", GetName()));
		}

		CObjBaseTemplate * pObjTop = pObj->GetTopLevelObj();
		CPointMap pt = pObjTop->GetTopPoint();
		if ( iType & 1 )		// FORITEM, FOROBJ
		{
			CWorldSearch AreaItems( pt, iDist );
			while(true)
			{
				LoopsMade++;
				if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes ))
					goto toomanyloops;

				CItem * pItem = AreaItems.GetItem();
				if ( pItem == NULL )
					break;
				TRIGRET_TYPE iRet = pItem->OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult );
				if ( iRet != TRIGRET_ENDIF )
				{
					return( iRet );
				}
				EndContext = s.GetContext();
				s.SeekContext( StartContext );
			}
		}
		if ( iType & 2 )		// FORCHAR, FOROBJ
		{
			CWorldSearch AreaChars( pt, iDist );
			while(true)
			{
				LoopsMade++;
				if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes ))
					goto toomanyloops;

				CChar * pChar = AreaChars.GetChar();
				if ( pChar == NULL )
					break;
				if ( ( iType & 0x10 ) && ( ! pChar->IsClient() ) )	// FORCLIENTS
					continue;
				if ( ( iType & 0x20 ) && ( pChar->m_pPlayer == NULL ) )	// FORPLAYERS
					continue;
				TRIGRET_TYPE iRet = pChar->OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult );
				if ( iRet != TRIGRET_ENDIF )
				{
					return( iRet );
				}
				EndContext = s.GetContext();
				s.SeekContext( StartContext );
			}
		}
	}

	if ( g_Cfg.m_iMaxLoopTimes )
	{
toomanyloops:
		if ( LoopsMade >= g_Cfg.m_iMaxLoopTimes )
		{
			g_Log.EventError("Terminating loop cycle since it seems being dead-locked (%d iterations already passed)" DEBUG_CR, LoopsMade);
		}
	}

	if ( EndContext.m_lOffset <= StartContext.m_lOffset )
	{
		// just skip to the end.
		TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_FALSE, pSrc, pArgs, pResult );
		if ( iRet != TRIGRET_ENDIF )
		{
			return( iRet );
		}
	}
	else
	{
		s.SeekContext( EndContext );
	}
	return( TRIGRET_ENDIF );
}
Beispiel #2
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 #3
0
bool CWorld::Export( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, int iDist, int dx, int dy )
{
	ADDTOCALLSTACK("CWorld::Export");
	// wModeFlags = IMPFLAGS_TYPE
	// Just get the items in the local area to export.
	// dx = change in x from world to file.
	// dy = change in y

	if ( pSrc == NULL )
		return false;

	size_t iLen = strlen( pszFilename );
	if ( iLen <= 4 )
		return false;

	CScript s;
	if ( ! s.Open( pszFilename, OF_WRITE|OF_TEXT|OF_DEFAULTMODE ))
		return false;

	if ( wModeFlags & IMPFLAGS_RELATIVE )
	{
		dx -= pSrc->GetTopPoint().m_x;
		dy -= pSrc->GetTopPoint().m_y;
	}

	if ( ! strcmpi( pszFilename + (iLen - 4), ".WSC" ))
	{
		// Export as UOX format. for world forge stuff.
		int index = 0;
		CWorldSearch AreaItems( pSrc->GetTopPoint(), iDist );
		AreaItems.SetSearchSquare(true);
		for (;;)
		{
			CItem * pItem = AreaItems.GetItem();
			if ( pItem == NULL )
				break;
			pItem->WriteUOX( s, index++ );
		}
		return true;
	}

	// (???NPC) Chars and the stuff they are carrying.
	if ( wModeFlags & IMPFLAGS_CHARS )
	{
		CWorldSearch AreaChars( pSrc->GetTopPoint(), iDist );
		AreaChars.SetSearchSquare(true);
		AreaChars.SetAllShow( pSrc->IsPriv( PRIV_ALLSHOW ));	// show logged out chars?
		for (;;)
		{
			CChar * pChar = AreaChars.GetChar();
			if ( pChar == NULL )
				break;
			pChar->r_WriteSafe( s );
		}
	}

	if ( wModeFlags & IMPFLAGS_ITEMS )
	{
		// Items on the ground.
		CWorldSearch AreaItems( pSrc->GetTopPoint(), iDist );
		AreaItems.SetSearchSquare(true);
		AreaItems.SetAllShow( pSrc->IsPriv( PRIV_ALLSHOW ));	// show logged out chars?
		for (;;)
		{
			CItem * pItem = AreaItems.GetItem();
			if ( pItem == NULL )
				break;
			pItem->r_WriteSafe( s );
		}
	}

	return true;
}