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 ); }
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; }
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; }