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 CItemStone::r_WriteVal( LPCTSTR pszKey, CGString & sVal, CTextConsole * pSrc ) { ADDTOCALLSTACK("CItemStone::r_WriteVal"); EXC_TRY("WriteVal"); CChar * pCharSrc = pSrc->GetChar(); if ( !strnicmp("member.",pszKey,7) ) { LPCTSTR pszCmd = pszKey + 7; if ( !strnicmp("COUNT",pszCmd,5) ) { pszCmd = pszCmd + 5; int i = 0; CStoneMember * pMember = STATIC_CAST <CStoneMember *>(GetHead()); if ( *pszCmd ) { SKIP_ARGSEP(pszCmd); STONEPRIV_TYPE iPriv = static_cast<STONEPRIV_TYPE>(Exp_GetVal(pszCmd)); for (; pMember != NULL; pMember = pMember->GetNext()) { if ( !pMember->GetLinkUID().IsChar() ) continue; if ( pMember->GetPriv() != iPriv ) continue; i++; } } else { for (; pMember != NULL; pMember = pMember->GetNext()) { if (!pMember->GetLinkUID().IsChar()) continue; i++; } } sVal.FormatVal(i); return true; } int nNumber = Exp_GetVal(pszCmd); SKIP_SEPARATORS(pszCmd); CStoneMember * pMember = STATIC_CAST <CStoneMember *>(GetHead()); sVal.FormatVal(0); for ( int i = 0 ; pMember != NULL; pMember = pMember->GetNext() ) { if (!pMember->GetLinkUID().IsChar()) continue; if ( nNumber == i ) { if (!pszCmd[0]) return true; return pMember->r_WriteVal(pszCmd, sVal, pSrc); } i++; } return true; } else if ( !strnicmp("memberfromuid.", pszKey, 14) ) { LPCTSTR pszCmd = pszKey + 14; sVal.FormatVal(0); if ( !pszCmd[0] ) return true; CGrayUID pMemberUid = static_cast<DWORD>(Exp_GetVal(pszCmd)); SKIP_SEPARATORS(pszCmd); CChar * pMemberChar = pMemberUid.CharFind(); if ( pMemberChar ) { CStoneMember * pMemberGuild = GetMember( pMemberChar ); if ( pMemberGuild ) { return pMemberGuild->r_WriteVal(pszCmd, sVal, pSrc); } } return true; } else if ( !strnicmp("guild.",pszKey,6) ) { LPCTSTR pszCmd = pszKey + 6; if ( !strnicmp("COUNT",pszCmd,5) ) { pszCmd = pszCmd + 5; int i = 0; CStoneMember * pMember = STATIC_CAST <CStoneMember *>(GetHead()); if ( *pszCmd ) { SKIP_ARGSEP(pszCmd); int iToCheck = Exp_GetVal(pszCmd); for (; pMember != NULL; pMember = pMember->GetNext()) { if ( pMember->GetLinkUID().IsChar() ) continue; if ( ( iToCheck == 1 ) && ( pMember->GetWeDeclared() && !pMember->GetTheyDeclared() ) ) i++; else if ( ( iToCheck == 2 ) && ( !pMember->GetWeDeclared() && pMember->GetTheyDeclared() ) ) i++; else if ( ( iToCheck == 3 ) && ( pMember->GetWeDeclared() && pMember->GetTheyDeclared() ) ) i++; } } else { for (; pMember != NULL; pMember = pMember->GetNext()) { if (pMember->GetLinkUID().IsChar()) continue; i++; } } sVal.FormatVal(i); return true; } int nNumber = Exp_GetVal(pszCmd); SKIP_SEPARATORS(pszCmd); CStoneMember * pMember = STATIC_CAST <CStoneMember *>(GetHead()); sVal.FormatVal(0); for ( int i = 0 ; pMember != NULL; pMember = pMember->GetNext() ) { if (pMember->GetLinkUID().IsChar()) continue; if ( nNumber == i ) { if (!pszCmd[0]) return true; return pMember->r_WriteVal(pszCmd, sVal, pSrc); } i++; } return true; } else if ( !strnicmp("guildfromuid.", pszKey, 13) ) { LPCTSTR pszCmd = pszKey + 13; sVal.FormatVal(0); if ( !pszCmd[0] ) return true; CGrayUID pGuildUid = static_cast<DWORD>(Exp_GetVal(pszCmd)); SKIP_SEPARATORS(pszCmd); CItem * pMemberGuild = pGuildUid.ItemFind(); if ( pMemberGuild ) { CStoneMember * pGuild = GetMember( pMemberGuild ); if ( pGuild ) { return pGuild->r_WriteVal(pszCmd, sVal, pSrc); } } return true; } else if ( !strnicmp(sm_szLoadKeys[STC_CHARTER], pszKey, 7) ) { LPCTSTR pszCmd = pszKey + 7; unsigned int i = ATOI(pszCmd); if ( i >= COUNTOF(m_sCharter)) sVal = ""; else sVal = m_sCharter[i]; return( true ); } STC_TYPE iIndex = (STC_TYPE) FindTableSorted( pszKey, sm_szLoadKeys, COUNTOF( sm_szLoadKeys )-1 ); switch ( iIndex ) { case STC_ABBREV: // "ABBREV" sVal = m_sAbbrev; return true; case STC_ALIGN: sVal.FormatVal( GetAlignType()); return true; case STC_WEBPAGE: // "WEBPAGE" sVal = GetWebPageURL(); return true; case STC_AbbreviationToggle: { CStoneMember * pMember = GetMember(pCharSrc); CVarDefCont * pResult = NULL; if ( pMember == NULL ) { pResult = g_Exp.m_VarDefs.GetKey("STONECONFIG_VARIOUSNAME_NONMEMBER"); } else { pResult = pMember->IsAbbrevOn() ? g_Exp.m_VarDefs.GetKey("STONECONFIG_VARIOUSNAME_ABBREVON") : g_Exp.m_VarDefs.GetKey("STONECONFIG_VARIOUSNAME_ABBREVOFF"); } sVal = pResult ? pResult->GetValStr() : ""; } return true; case STC_AlignType: sVal = GetAlignName(); return true; case STC_LoyalTo: { CStoneMember * pMember = GetMember(pCharSrc); CVarDefCont * pResult = NULL; if ( pMember == NULL ) { pResult = g_Exp.m_VarDefs.GetKey("STONECONFIG_VARIOUSNAME_NONMEMBER"); } else { CChar * pLoyalTo = pMember->GetLoyalToUID().CharFind(); if ((pLoyalTo == NULL) || (pLoyalTo == pCharSrc )) { pResult = g_Exp.m_VarDefs.GetKey("STONECONFIG_VARIOUSNAME_YOURSELF"); } else { sVal = pLoyalTo->GetName(); return true; } } sVal = pResult ? pResult->GetValStr() : ""; } return( true ); case STC_Master: { CChar * pMaster = GetMaster(); sVal = (pMaster) ? pMaster->GetName() : g_Exp.m_VarDefs.GetKeyStr("STONECONFIG_VARIOUSNAME_PENDVOTE"); } return( true ); case STC_MasterGenderTitle: { CChar * pMaster = GetMaster(); if ( pMaster == NULL ) sVal = ""; // If no master (vote pending) else if ( pMaster->Char_GetDef()->IsFemale()) sVal = g_Exp.m_VarDefs.GetKeyStr("STONECONFIG_VARIOUSNAME_MASTERGENDERFEMALE"); else sVal = g_Exp.m_VarDefs.GetKeyStr("STONECONFIG_VARIOUSNAME_MASTERGENDERMALE"); } return( true ); case STC_MasterTitle: { CStoneMember * pMember = GetMasterMember(); sVal = (pMember) ? pMember->GetTitle() : ""; } return( true ); case STC_MasterUid: { CChar * pMaster = GetMaster(); if ( pMaster ) sVal.FormatHex( (DWORD) pMaster->GetUID() ); else sVal.FormatHex( (DWORD) 0 ); } return( true ); default: return( CItem::r_WriteVal( pszKey, sVal, pSrc )); } EXC_CATCH; EXC_DEBUG_START; EXC_ADD_KEYRET(pSrc); EXC_DEBUG_END; return false; }