void CStoneMember::SetTitle( LPCTSTR pTitle ) { ADDTOCALLSTACK("CStoneMember::SetTitle"); m_sTitle = pTitle; }
bool CChat::JoinChannel(CChatChanMember * pMember, lpctstr pszChannel, lpctstr pszPassword) { ADDTOCALLSTACK("CChat::JoinChannel"); ASSERT(pMember != nullptr); CClient * pMemberClient = pMember->GetClient(); ASSERT(pMemberClient != nullptr); // Are we in a channel now? CChatChannel * pCurrentChannel = pMember->GetChannel(); if (pCurrentChannel != nullptr) { // Is it the same channel as the one I'm already in? if (strcmp(pszChannel, pCurrentChannel->GetName()) == 0) { // Tell them and return pMember->SendChatMsg(CHATMSG_AlreadyInConference, pszChannel); return false; } } CChatChannel * pNewChannel = FindChannel(pszChannel); if (pNewChannel == nullptr) { pMemberClient->addChatSystemMessage(CHATMSG_NoConference, pszChannel ); return false; } // If there's a password, is it the correct one? if (strcmp(pNewChannel->GetPassword(), pszPassword) != 0) { pMemberClient->addChatSystemMessage(CHATMSG_IncorrectPassword); return false; } // Leave the old channel 1st // Remove from old channel (if any) if (pCurrentChannel != nullptr) { // Remove myself from the channels list of members pCurrentChannel->RemoveMember(pMember); // If noone is left, tell the chat system to delete it from memory if (pCurrentChannel->m_Members.size() <= 0) { // Am I the last one here? Delete it from all other clients? DeleteChannel(pCurrentChannel); } // Since we left, clear all members from our client that might be in our list from the channel we just left pMemberClient->addChatSystemMessage(CHATMSG_ClearMemberList); } // Now join a new channel // Add all the members of the channel to the clients list of channel participants pNewChannel->SendMembers(pMember); // Add ourself to the channels list of members if (!pNewChannel->AddMember(pMember)) return false; // Set the channel name title bar pMemberClient->addChatSystemMessage(CHATMSG_UpdateChannelBar, pszChannel); // Now send out my name to all clients in this channel pNewChannel->SendThisMember(pMember); return true; }
void CItemVendable::SetPlayerVendorPrice( DWORD lPrice ) { ADDTOCALLSTACK("CItemVendable::SetPlayerVendorPrice"); // This can only be inside a vendor container. m_price = maximum(lPrice, 0); }
bool CChar::Use_Eat( CItem * pItemFood, short iQty ) { ADDTOCALLSTACK("CChar::Use_Eat"); // What we can eat should depend on body type. // How much we can eat should depend on body size and current fullness. // // ??? monsters should be able to eat corpses / raw meat // IT_FOOD or IT_FOOD_RAW // NOTE: Some foods like apples are stackable ! if ( !CanMove(pItemFood) ) { SysMessageDefault(DEFMSG_FOOD_CANTMOVE); return false; } if ( Stat_GetMax(STAT_FOOD) == 0 ) { SysMessageDefault(DEFMSG_FOOD_CANTEAT); return false; } // Is this edible by me ? if ( !Food_CanEat(pItemFood) ) { SysMessageDefault(DEFMSG_FOOD_RCANTEAT); return false; } if ( Stat_GetVal(STAT_FOOD) >= Stat_GetMax(STAT_FOOD) ) { SysMessageDefault(DEFMSG_FOOD_CANTEATF); return false; } Use_EatQty(pItemFood, iQty); LPCTSTR pMsg; int index = IMULDIV(Stat_GetVal(STAT_FOOD), 5, Stat_GetMax(STAT_FOOD)); switch ( index ) { case 0: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_1); break; case 1: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_2); break; case 2: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_3); break; case 3: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_4); break; case 4: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_5); break; case 5: default: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_6); break; } SysMessage(pMsg); return true; }
void CChat::DoCommand(CChatChanMember * pBy, lpctstr szMsg) { ADDTOCALLSTACK("CChat::DoCommand"); static lpctstr const sm_szCmd_Chat[] = { "ALLKICK", "BC", "BCALL", "CHATSOK", "CLEARIGNORE", "KILLCHATS", "NOCHATS", "SYSMSG", "WHEREIS" }; ASSERT(pBy != nullptr); ASSERT(szMsg != nullptr); tchar buffer[2048]; ASSERT(strlen(szMsg) < CountOf(buffer)); strcpy(buffer, szMsg); tchar * pszCommand = buffer; tchar * pszText = nullptr; size_t iCommandLength = strlen(pszCommand); for (size_t i = 0; i < iCommandLength; i++) { ASSERT( i<CountOf(buffer)); if (pszCommand[i] == ' ') { pszCommand[i] = 0; pszText = pszCommand + i + 1; } } CSString sFrom; CChatChannel * pChannel = pBy->GetChannel(); CClient * pByClient = pBy->GetClient(); ASSERT(pByClient != nullptr); switch ( FindTableSorted( pszCommand, sm_szCmd_Chat, CountOf(sm_szCmd_Chat))) { case 0: // "ALLKICK" { if (pChannel == nullptr) { pBy->SendChatMsg(CHATMSG_MustBeInAConference); return; } if (!pChannel->IsModerator(pBy->GetChatName())) { pBy->SendChatMsg(CHATMSG_MustHaveOps); return; } pChannel->KickAll(pBy); DecorateName(sFrom, nullptr, true); pBy->SendChatMsg(CHATMSG_PlayerTalk, sFrom, "All members have been kicked!", ""); return; } case 1: // "BC" { if ( ! pByClient->IsPriv( PRIV_GM )) { need_gm_privs: DecorateName(sFrom, nullptr, true); pBy->SendChatMsg(CHATMSG_PlayerTalk, sFrom, "You need to have GM privs to use this command."); return; } Broadcast(pBy, pszText); return; } case 2: // "BCALL" { if ( ! pByClient->IsPriv( PRIV_GM )) goto need_gm_privs; Broadcast(pBy, pszText, "", true); return; } case 3: // "CHATSOK" { if ( ! pByClient->IsPriv( PRIV_GM )) goto need_gm_privs; if (!m_fChatsOK) { m_fChatsOK = true; Broadcast(nullptr, "Conference creation is enabled."); } return; } case 4: // "CLEARIGNORE" { pBy->ClearIgnoreList(); return; } case 5: // "KILLCHATS" { if ( ! pByClient->IsPriv( PRIV_GM )) goto need_gm_privs; KillChannels(); return; } case 6: // "NOCHATS" { if ( ! pByClient->IsPriv( PRIV_GM )) goto need_gm_privs; if (m_fChatsOK) { Broadcast(nullptr, "Conference creation is now disabled."); m_fChatsOK = false; } return; } case 7: // "SYSMSG" { if ( ! pByClient->IsPriv( PRIV_GM )) goto need_gm_privs; Broadcast(nullptr, pszText, "", true); return; } case 8: // "WHEREIS" { WhereIs(pBy, pszText); return; } default: { tchar *pszMsg = Str_GetTemp(); sprintf(pszMsg, "Unknown command: '%s'", pszCommand); DecorateName(sFrom, nullptr, true); pBy->SendChatMsg(CHATMSG_PlayerTalk, sFrom, pszMsg); return; } } }
bool CChar::Use_CarveCorpse( CItemCorpse * pCorpse ) { ADDTOCALLSTACK("CChar::Use_CarveCorpse"); CREID_TYPE CorpseID = pCorpse->m_itCorpse.m_BaseID; CCharBase *pCorpseDef = CCharBase::FindCharBase(CorpseID); if ( !pCorpseDef || pCorpse->m_itCorpse.m_carved ) { SysMessageDefault(DEFMSG_CARVE_CORPSE_NOTHING); return false; } CChar *pChar = pCorpse->m_uidLink.CharFind(); CPointMap pnt = pCorpse->GetTopLevelObj()->GetTopPoint(); UpdateAnimate(ANIM_BOW); if ( pCorpse->m_TagDefs.GetKeyNum("BLOOD") ) { CItem *pBlood = CItem::CreateBase(ITEMID_BLOOD4); ASSERT(pBlood); pBlood->SetHue(pCorpseDef->m_wBloodHue); pBlood->MoveToDecay(pnt, 5 * TICK_PER_SEC); } size_t iItems = 0; for ( size_t i = 0; i < pCorpseDef->m_BaseResources.GetCount(); i++ ) { long long iQty = pCorpseDef->m_BaseResources[i].GetResQty(); RESOURCE_ID rid = pCorpseDef->m_BaseResources[i].GetResourceID(); if ( rid.GetResType() != RES_ITEMDEF ) continue; ITEMID_TYPE id = static_cast<ITEMID_TYPE>(rid.GetResIndex()); if ( id == ITEMID_NOTHING ) break; iItems++; CItem *pPart = CItem::CreateTemplate(id, NULL, this); ASSERT(pPart); switch ( pPart->GetType() ) { case IT_FOOD: case IT_FOOD_RAW: case IT_MEAT_RAW: SysMessageDefault(DEFMSG_CARVE_CORPSE_MEAT); //pPart->m_itFood.m_MeatType = CorpseID; break; case IT_HIDE: SysMessageDefault(DEFMSG_CARVE_CORPSE_HIDES); //pPart->m_itSkin.m_creid = CorpseID; if ( (g_Cfg.m_iRacialFlags & RACIALF_HUMAN_WORKHORSE) && IsHuman() ) // humans always find 10% bonus when gathering hides, ores and logs (Workhorse racial trait) iQty = iQty * 110 / 100; break; case IT_FEATHER: SysMessageDefault(DEFMSG_CARVE_CORPSE_FEATHERS); //pPart->m_itSkin.m_creid = CorpseID; break; case IT_WOOL: SysMessageDefault(DEFMSG_CARVE_CORPSE_WOOL); //pPart->m_itSkin.m_creid = CorpseID; break; /*case IT_DRAGON_SCALE: // TO-DO (typedef IT_DRAGON_SCALE doesn't exist yet) SysMessageDefault(DEFMSG_CARVE_CORPSE_SCALES); //pPart->m_itSkin.m_creid = CorpseID; break;*/ default: break; } if ( iQty > 1 ) pPart->SetAmount(static_cast<WORD>(iQty)); if ( pChar && pChar->m_pPlayer ) { TCHAR *pszMsg = Str_GetTemp(); sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_CORPSE_NAME), pPart->GetName(), pChar->GetName()); pPart->SetName(pszMsg); pPart->m_uidLink = pChar->GetUID(); pPart->MoveToDecay(pnt, pPart->GetDecayTime()); continue; } pCorpse->ContentAdd(pPart); } if ( iItems < 1 ) SysMessageDefault(DEFMSG_CARVE_CORPSE_NOTHING); CheckCorpseCrime(pCorpse, false, false); pCorpse->m_itCorpse.m_carved = 1; // mark as been carved pCorpse->m_itCorpse.m_uidKiller = GetUID(); // by you if ( pChar && pChar->m_pPlayer ) pCorpse->SetTimeout(0); // reset corpse timer to make it turn bones return true; }
bool CChar::Use_Item_Web( CItem * pItemWeb ) { ADDTOCALLSTACK("CChar::Use_Item_Web"); // IT_WEB // IT_EQ_STUCK // Try to break out of the web. // Or just try to damage it. // // RETURN: true = held in place. // false = walk thru it. if ( GetDispID() == CREID_GIANT_SPIDER || !pItemWeb || !pItemWeb->IsTopLevel() || IsStatFlag(STATF_DEAD|STATF_Insubstantial) || IsPriv(PRIV_GM) ) return false; // just walk through it // Try to break it. int iStr = pItemWeb->m_itWeb.m_Hits_Cur; if ( iStr == 0 ) iStr = pItemWeb->m_itWeb.m_Hits_Cur = 60 + Calc_GetRandVal(250); // Since broken webs become spider silk, we should get out of here now if we aren't in a web. CItem *pFlag = LayerFind(LAYER_FLAG_Stuck); if ( CanMove(pItemWeb, false) ) { if ( pFlag ) pFlag->Delete(); return false; } if ( pFlag ) { if ( pFlag->IsTimerSet() ) // don't allow me to try to damage it too often return true; } int iDmg = pItemWeb->OnTakeDamage(Stat_GetAdjusted(STAT_STR), this); switch ( iDmg ) { case 0: // damage blocked case 1: // web survived default: // unknown if ( GetTopPoint() == pItemWeb->GetTopPoint() ) // is character still stuck on the web? break; case 2: // web turned into silk case INT_MAX: // web destroyed if ( pFlag ) pFlag->Delete(); return false; } // Stuck in it still. if ( !pFlag ) { if ( iDmg < 0 ) return false; // First time message. pFlag = CItem::CreateBase(ITEMID_WEB1_1); ASSERT(pFlag); pFlag->SetAttr(ATTR_DECAY); pFlag->SetType(IT_EQ_STUCK); pFlag->m_uidLink = pItemWeb->GetUID(); pFlag->SetTimeout(pItemWeb->GetTimerDAdjusted()); LayerAdd(pFlag, LAYER_FLAG_Stuck); } else { if ( iDmg < 0 ) { pFlag->Delete(); return false; } SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SWEB_STUCK), pItemWeb->GetName()); } return true; }
bool CClient::r_WriteVal(LPCTSTR pszKey, CGString &sVal, CTextConsole *pSrc) { ADDTOCALLSTACK("CClient::r_WriteVal"); EXC_TRY("WriteVal"); if ( !strnicmp("CTAG.", pszKey, 5) ) { if ( pszKey[4] != '.' ) return false; pszKey += 5; CVarDefCont *pVar = m_TagDefs.GetKey(pszKey); sVal = pVar ? pVar->GetValStr() : ""; return true; } if ( !strnicmp("CTAG0.", pszKey, 6) ) { if ( pszKey[5] != '.' ) return false; pszKey += 6; CVarDefCont *pVar = m_TagDefs.GetKey(pszKey); sVal = pVar ? pVar->GetValStr() : "0"; return true; } int index; if ( !strnicmp("TARGP", pszKey, 5) && ((pszKey[5] == '\0') || (pszKey[5] == '.')) ) index = CC_TARGP; else if ( !strnicmp("SCREENSIZE", pszKey, 10) && ((pszKey[10] == '\0') || (pszKey[10] == '.')) ) index = CC_SCREENSIZE; else if ( !strnicmp("REPORTEDCLIVER", pszKey, 14) && ((pszKey[14] == '\0') || (pszKey[14] == '.')) ) index = CC_REPORTEDCLIVER; else index = FindTableSorted(pszKey, sm_szLoadKeys, COUNTOF(sm_szLoadKeys) - 1); switch ( index ) { case CC_ALLMOVE: sVal.FormatVal(IsPriv(PRIV_ALLMOVE)); break; case CC_ALLSHOW: sVal.FormatVal(IsPriv(PRIV_ALLSHOW)); break; case CC_CLIENTIS3D: sVal.FormatVal(m_NetState->isClient3D()); break; case CC_CLIENTISKR: sVal.FormatVal(m_NetState->isClientKR()); break; case CC_CLIENTISSA: sVal.FormatVal(m_NetState->isClientEnhanced()); break; case CC_CLIENTVERSION: { TCHAR szVersion[128]; sVal = m_Crypt.WriteClientVerString(m_Crypt.GetClientVer(), szVersion); break; } case CC_DEBUG: sVal.FormatVal(IsPriv(PRIV_DEBUG)); break; case CC_DETAIL: sVal.FormatVal(IsPriv(PRIV_DETAIL)); break; case CC_GM: sVal.FormatVal(IsPriv(PRIV_GM)); break; case CC_HEARALL: sVal.FormatVal(IsPriv(PRIV_HEARALL)); break; case CC_LASTEVENT: sVal.FormatLLVal(m_timeLastEvent.GetTimeRaw()); break; case CC_PRIVSHOW: sVal.FormatVal(!IsPriv(PRIV_PRIV_NOSHOW)); break; case CC_REPORTEDCLIVER: { pszKey += 14; GETNONWHITESPACE(pszKey); DWORD dwCliVer = m_NetState->getReportedVersion(); if ( pszKey[0] == '\0' ) { // Return full version string (eg: 5.0.2d) TCHAR szVersion[128]; sVal = CCrypt::WriteClientVerString(dwCliVer, szVersion); } else { // Return raw version number (eg: 5.0.2d = 5000204) sVal.FormatUVal(dwCliVer); } break; } case CC_SCREENSIZE: { if ( pszKey[10] == '.' ) { pszKey += 10; SKIP_SEPARATORS(pszKey); if ( !strnicmp("X", pszKey, 1) ) sVal.Format("%hu", m_ScreenSize.x); else if ( !strnicmp("Y", pszKey, 1) ) sVal.Format("%hu", m_ScreenSize.y); else return false; } else sVal.Format("%hu,%hu", m_ScreenSize.x, m_ScreenSize.y); break; } case CC_TARG: sVal.FormatHex(m_Targ_UID); break; case CC_TARGP: { if ( pszKey[5] == '.' ) return m_Targ_p.r_WriteVal(pszKey + 6, sVal); sVal = m_Targ_p.WriteUsed(); break; } case CC_TARGPROP: sVal.FormatHex(m_Prop_UID); break; case CC_TARGPRV: sVal.FormatHex(m_Targ_PrvUID); break; case CC_TARGTXT: sVal = m_Targ_Text; break; default: return CScriptObj::r_WriteVal(pszKey, sVal, pSrc); } return true; EXC_CATCH; EXC_DEBUG_START; EXC_ADD_KEYRET(pSrc); EXC_DEBUG_END; return false; }
bool CClient::r_LoadVal(CScript &s) { ADDTOCALLSTACK("CClient::r_LoadVal"); EXC_TRY("LoadVal"); if ( !m_pAccount ) return false; LPCTSTR pszKey = s.GetKey(); if ( s.IsKeyHead("CTAG.", 5) || s.IsKeyHead("CTAG0.", 6) ) { bool fZero = s.IsKeyHead("CTAG0.", 6); bool fQuoted = false; pszKey = pszKey + (fZero ? 6 : 5); m_TagDefs.SetStr(pszKey, fQuoted, s.GetArgStr(&fQuoted), fZero); return true; } switch ( FindTableSorted(pszKey, sm_szLoadKeys, COUNTOF(sm_szLoadKeys) - 1) ) { case CC_ALLMOVE: { m_pAccount->TogPrivFlags(PRIV_ALLMOVE, s.GetArgStr()); addPlayerSee(NULL); if ( IsSetOF(OF_Command_Sysmsgs) ) m_pChar->SysMessage(IsPriv(PRIV_ALLMOVE) ? "Allmove ON" : "Allmove OFF"); break; } case CC_ALLSHOW: { if ( IsPriv(PRIV_ALLSHOW) ) addRemoveAll(false, true); m_pAccount->TogPrivFlags(PRIV_ALLSHOW, s.GetArgStr()); addPlayerSee(NULL); if ( IsSetOF(OF_Command_Sysmsgs) ) m_pChar->SysMessage(IsPriv(PRIV_ALLSHOW) ? "Allshow ON" : "Allshow OFF"); break; } case CC_DEBUG: { addRemoveAll(true, false); m_pAccount->TogPrivFlags(PRIV_DEBUG, s.GetArgStr()); addPlayerSee(NULL); if ( IsSetOF(OF_Command_Sysmsgs) ) m_pChar->SysMessage(IsPriv(PRIV_DEBUG) ? "Debug ON" : "Debug OFF"); break; } case CC_DETAIL: { m_pAccount->TogPrivFlags(PRIV_DETAIL, s.GetArgStr()); if ( IsSetOF(OF_Command_Sysmsgs) ) m_pChar->SysMessage(IsPriv(PRIV_DETAIL) ? "Detail ON" : "Detail OFF"); break; } case CC_GM: { if ( GetPrivLevel() >= PLEVEL_GM ) { m_pAccount->TogPrivFlags(PRIV_GM, s.GetArgStr()); m_pChar->UpdatePropertyFlag(); addPlayerSee(NULL); if ( IsSetOF(OF_Command_Sysmsgs) ) m_pChar->SysMessage(IsPriv(PRIV_GM) ? "GM ON" : "GM OFF"); } break; } case CC_HEARALL: { m_pAccount->TogPrivFlags(PRIV_HEARALL, s.GetArgStr()); if ( IsSetOF(OF_Command_Sysmsgs) ) m_pChar->SysMessage(IsPriv(PRIV_HEARALL) ? "Hearall ON" : "Hearall OFF"); break; } case CC_PRIVSHOW: if ( GetPrivLevel() >= PLEVEL_Counsel ) { if ( !s.HasArgs() ) m_pAccount->TogPrivFlags(PRIV_PRIV_NOSHOW, NULL); else if ( s.GetArgVal() ) m_pAccount->ClearPrivFlags(PRIV_PRIV_NOSHOW); else m_pAccount->SetPrivFlags(PRIV_PRIV_NOSHOW); m_pChar->UpdatePropertyFlag(); if ( IsSetOF(OF_Command_Sysmsgs) ) m_pChar->SysMessage(IsPriv(PRIV_PRIV_NOSHOW) ? "Privshow OFF" : "Privshow ON"); } break; case CC_TARG: m_Targ_UID = s.GetArgVal(); break; case CC_TARGP: m_Targ_p.Read(s.GetArgRaw()); if ( !m_Targ_p.IsValidPoint() ) { m_Targ_p.ValidatePoint(); SysMessagef("Invalid point: %s", s.GetArgStr()); } break; case CC_TARGPROP: m_Prop_UID = s.GetArgVal(); break; case CC_TARGPRV: m_Targ_PrvUID = s.GetArgVal(); break; default: return false; } return true; EXC_CATCH; EXC_DEBUG_START; EXC_ADD_SCRIPT; EXC_DEBUG_END; return false; }
void CClient::UpdateFeatureFlags() { ADDTOCALLSTACK("CClient::UpdateFeatureFlags"); // Update ingame features enabled on this client // NOTE: Flags > 0x10000 requires at least client 6.0.14.2 // 0x000001 Enable T2A features // 0x000002 Enable Renaissance features (play MP3 instead midi, ...) // 0x000004 Enable TD features // 0x000008 Enable LBR features // 0x000010 Enable AOS features (necro/paladin, house customization engine, ...) // 0x000020 Sixth character slot // 0x000040 Enable SE features // 0x000080 Enable ML features // 0x000100 8th age // 0x000200 9th age (enable crystal/shadow custom house tiles) // 0x000400 10th age // 0x000800 Increased house/bank storage // 0x001000 Seventh character slot // 0x002000 Enable extra roleplay face styles on character creation (enhanced clients only) // 0x004000 Trial account // 0x008000 Live account (required on clients 4.0.0+, otherwise bits 3..14 will be ignored) // 0x010000 Enable SA features // 0x020000 Enable HS features // 0x040000 Enable gothic custom house tiles // 0x080000 Enable rustic custom house tiles // 0x100000 Enable jungle custom house tiles // 0x200000 Enable shadowguard custom house tiles // 0x400000 Enable TOL features // 0x800000 Free account (Endless Journey) if ( !m_pAccount ) return; RESDISPLAY_VERSION iResDisp = static_cast<RESDISPLAY_VERSION>(m_pAccount->GetResDisp()); BYTE bMaxChars = static_cast<BYTE>(maximum(m_pAccount->GetMaxChars(), m_pAccount->m_Chars.GetCharCount())); m_FeatureFlags = 0; // Expansion features if ( iResDisp >= RDS_T2A ) { if ( g_Cfg.m_iFeatureT2A & FEATURE_T2A_UPDATE ) m_FeatureFlags |= 0x4; if ( g_Cfg.m_iFeatureT2A & FEATURE_T2A_CHAT ) m_FeatureFlags |= 0x1; } if ( iResDisp >= RDS_LBR ) { if ( g_Cfg.m_iFeatureLBR & FEATURE_LBR_UPDATE ) m_FeatureFlags |= 0x8; if ( g_Cfg.m_iFeatureLBR & FEATURE_LBR_SOUND ) m_FeatureFlags |= 0x2; } if ( iResDisp >= RDS_AOS ) { if ( g_Cfg.m_iFeatureAOS & FEATURE_AOS_UPDATE_A ) m_FeatureFlags |= 0x10; } if ( iResDisp >= RDS_SE ) { if ( g_Cfg.m_iFeatureSE & FEATURE_SE_UPDATE ) m_FeatureFlags |= 0x40; } if ( iResDisp >= RDS_ML ) { if ( g_Cfg.m_iFeatureML & FEATURE_ML_UPDATE ) m_FeatureFlags |= 0x80; } if ( iResDisp >= RDS_SA ) { if ( g_Cfg.m_iFeatureSA & FEATURE_SA_UPDATE ) m_FeatureFlags |= 0x10000; } if ( iResDisp >= RDS_TOL ) { if ( g_Cfg.m_iFeatureTOL & FEATURE_TOL_UPDATE ) m_FeatureFlags |= 0x400000; } // Max character slots if ( bMaxChars > 6 ) m_FeatureFlags |= 0x1000; if ( bMaxChars == 6 ) m_FeatureFlags |= 0x20; // Extra housing features (enable expansion items on house customization engine) // PS: main expansion items are already enabled with flags 0x10 (AOS), 0x40 (SE), 0x80 (ML), 0x10000 (SA) and 0x400000 (TOL) if ( g_Cfg.m_iFeatureExtra & FEATURE_EXTRA_CRYSTAL ) m_FeatureFlags |= 0x200; if ( g_Cfg.m_iFeatureExtra & FEATURE_EXTRA_GOTHIC ) m_FeatureFlags |= 0x40000; if ( g_Cfg.m_iFeatureExtra & FEATURE_EXTRA_RUSTIC ) m_FeatureFlags |= 0x80000; if ( g_Cfg.m_iFeatureExtra & FEATURE_EXTRA_JUNGLE ) m_FeatureFlags |= 0x100000; if ( g_Cfg.m_iFeatureExtra & FEATURE_EXTRA_SHADOWGUARD ) m_FeatureFlags |= 0x200000; // Misc if ( m_NetState->isClientKR() || m_NetState->isClientEnhanced() ) { if ( g_Cfg.m_iFeatureExtra & FEATURE_EXTRA_ROLEPLAYFACES ) m_FeatureFlags |= 0x2000; } }
void CClient::UpdateCharacterListFlags() { ADDTOCALLSTACK("CClient::UpdateCharacterListFlags"); // Update character list features enabled on this client // 0x0001 Unknown // 0x0002 Overwrite config buttons // 0x0004 Single character slot // 0x0008 Context menus // 0x0010 Limit character slots // 0x0020 Enable AOS features (tooltip, fight book) // 0x0040 Sixth character slot // 0x0080 Enable SE features // 0x0100 Enable ML features // 0x0200 Unknown (KR) // 0x0400 Enable KR/SA packet 0xE1 at character list (possibly other unknown effects) // 0x0800 Unknown (KR/SA) // 0x1000 Seventh character slot // 0x2000 Unknown (SA) // 0x4000 Enable new SA movement packets 0xF0 / 0xF1 / 0xF2 // 0x8000 New Felucca areas / faction strongholds (uses map0x.mul, statics0x.mul, etc) - client 7.0.6+ if ( !m_pAccount ) return; RESDISPLAY_VERSION iResDisp = static_cast<RESDISPLAY_VERSION>(m_pAccount->GetResDisp()); BYTE bMaxChars = static_cast<BYTE>(maximum(m_pAccount->GetMaxChars(), m_pAccount->m_Chars.GetCharCount())); m_CharacterListFlags = 0; // Expansion features if ( iResDisp >= RDS_AOS ) { if ( g_Cfg.m_iFeatureAOS & FEATURE_AOS_UPDATE_B ) m_CharacterListFlags |= 0x20; if ( g_Cfg.m_iFeatureAOS & FEATURE_AOS_POPUP ) m_CharacterListFlags |= 0x8; } if ( iResDisp >= RDS_SE ) { if ( g_Cfg.m_iFeatureSE & FEATURE_SE_NINJASAM ) m_CharacterListFlags |= 0x80; } if ( iResDisp >= RDS_ML ) { if ( g_Cfg.m_iFeatureML & FEATURE_ML_UPDATE ) m_CharacterListFlags |= 0x100; } if ( iResDisp >= RDS_KR ) { if ( g_Cfg.m_iFeatureKR & FEATURE_KR_UPDATE ) m_CharacterListFlags |= 0x200; } if ( iResDisp >= RDS_SA ) { if ( g_Cfg.m_iFeatureSA & FEATURE_SA_MOVEMENT ) m_CharacterListFlags |= 0x4000; } // Max character slots if ( bMaxChars > 6 ) m_CharacterListFlags |= 0x1000; else if ( bMaxChars == 6 ) m_CharacterListFlags |= 0x40; else if ( bMaxChars == 1 ) m_CharacterListFlags |= (0x10|0x4); // Misc if ( m_NetState->isClientKR() || m_NetState->isClientEnhanced() ) // tooltips must be always enabled on enhanced clients m_CharacterListFlags |= (0x400|0x200|0x20); m_TooltipEnabled = (m_CharacterListFlags & 0x20); m_ContainerGridEnabled = (m_NetState->isClientVersion(MINCLIVER_CONTAINERGRID) || m_NetState->isClientKR() || m_NetState->isClientEnhanced()); m_UseNewChatSystem = m_NetState->isClientVersion(MINCLIVER_NEWCHATSYSTEM); }
void CStoneMember::SetAccountGold( int iGold ) { ADDTOCALLSTACK("CStoneMember::SetAccountGold"); m_Member.m_iAccountGold = iGold; }
int CStoneMember::GetAccountGold() const { ADDTOCALLSTACK("CStoneMember::GetAccountGold"); return( m_Member.m_iAccountGold ); }
CGrayUID CStoneMember::GetLoyalToUID() const { ADDTOCALLSTACK("CStoneMember::GetLoyalToUID"); return( m_uidLoyalTo ); }
int CChar::Do_Use_Item(CItem *pItem, bool fLink) { ADDTOCALLSTACK("CChar::Do_Use_Item"); if ( !pItem ) return false; if ( m_pNPC && (IsTrigUsed(TRIGGER_DCLICK) || IsTrigUsed(TRIGGER_ITEMDCLICK)) ) // for players, DClick was called before this function { if ( pItem->OnTrigger(ITRIG_DCLICK, this) == TRIGRET_RET_TRUE ) return false; } CItemSpawn *pSpawn = static_cast<CItemSpawn *>(pItem->m_uidSpawnItem.ItemFind()); if ( pSpawn ) pSpawn->DelObj(pItem->GetUID()); // remove this item from it's spawn when DClicks it int fAction = true; switch ( pItem->GetType() ) { case IT_ITEM_STONE: { // Give them this item if ( pItem->m_itItemStone.m_wAmount == USHRT_MAX ) { SysMessageDefault(DEFMSG_MSG_IT_IS_DEAD); return true; } if ( pItem->m_itItemStone.m_wRegenTime ) { if ( pItem->IsTimerSet() ) { SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_MSG_STONEREG_TIME), pItem->GetTimerDiff() / TICK_PER_SEC); return true; } pItem->SetTimeout(pItem->m_itItemStone.m_wRegenTime * TICK_PER_SEC); } ItemBounce(CItem::CreateTemplate(pItem->m_itItemStone.m_ItemID, GetContainerCreate(LAYER_PACK), this)); if ( pItem->m_itItemStone.m_wAmount != 0 ) { pItem->m_itItemStone.m_wAmount--; if ( pItem->m_itItemStone.m_wAmount == 0 ) pItem->m_itItemStone.m_wAmount = USHRT_MAX; } return true; } case IT_SEED: return Use_Seed(pItem, NULL); case IT_BEDROLL: return Use_BedRoll(pItem); case IT_KINDLING: return Use_Kindling(pItem); case IT_SPINWHEEL: { if ( fLink ) return false; // Just make them spin pItem->SetAnim(static_cast<ITEMID_TYPE>(pItem->GetID() + 1), 2 * TICK_PER_SEC); SysMessageDefault(DEFMSG_ITEMUSE_SPINWHEEL); return true; } case IT_TRAIN_DUMMY: { if ( fLink ) return false; Use_Train_Dummy(pItem, true); return true; } case IT_TRAIN_PICKPOCKET: { if ( fLink ) return false; Use_Train_PickPocketDip(pItem, true); return true; } case IT_ARCHERY_BUTTE: { if ( fLink ) return false; Use_Train_ArcheryButte(pItem, true); return true; } case IT_LOOM: { if ( fLink ) return false; SysMessageDefault(DEFMSG_ITEMUSE_LOOM); return true; } case IT_BEE_HIVE: { if ( fLink ) return false; // Get honey from it ITEMID_TYPE id = ITEMID_NOTHING; if ( !pItem->m_itBeeHive.m_honeycount ) SysMessageDefault(DEFMSG_ITEMUSE_BEEHIVE); else { switch ( Calc_GetRandVal(3) ) { case 1: id = ITEMID_JAR_HONEY; break; case 2: id = ITEMID_BEE_WAX; break; default: break; } } if ( id ) { ItemBounce(CItem::CreateScript(id, this)); pItem->m_itBeeHive.m_honeycount--; } else { SysMessageDefault(DEFMSG_ITEMUSE_BEEHIVE_STING); OnTakeDamage(Calc_GetRandVal(5), this, DAMAGE_POISON|DAMAGE_GENERAL); } pItem->SetTimeout(15 * 60 * TICK_PER_SEC); return true; } case IT_MUSICAL: { if ( !Skill_Wait(SKILL_MUSICIANSHIP) ) { m_Act_Targ = pItem->GetUID(); Skill_Start(SKILL_MUSICIANSHIP); } break; } case IT_CROPS: case IT_FOLIAGE: { // Pick cotton/hay/etc fAction = pItem->Plant_Use(this); break; } case IT_FIGURINE: { // Create the creature here if ( Use_Figurine(pItem) ) pItem->Delete(); return true; } case IT_TRAP: case IT_TRAP_ACTIVE: { // Activate the trap (plus any linked traps) int iDmg = pItem->Use_Trap(); if ( CanTouch(pItem->GetTopLevelObj()->GetTopPoint()) ) OnTakeDamage(iDmg, NULL, DAMAGE_HIT_BLUNT|DAMAGE_GENERAL); break; } case IT_SWITCH: { // Switches can be linked to gates and doors and such. // Flip the switch graphic. pItem->SetSwitchState(); break; } case IT_PORT_LOCKED: if ( !fLink && !IsPriv(PRIV_GM) ) { SysMessageDefault(DEFMSG_ITEMUSE_PORT_LOCKED); return true; } case IT_PORTCULIS: // Open a metal gate vertically pItem->Use_Portculis(); break; case IT_DOOR_LOCKED: if ( !ContentFindKeyFor(pItem) ) { SysMessageDefault(DEFMSG_MSG_KEY_DOORLOCKED); if ( !pItem->IsTopLevel() ) return false; if ( pItem->IsAttr(ATTR_MAGIC) ) // show it's magic face { ITEMID_TYPE id = (GetDispID() & DOOR_NORTHSOUTH) ? ITEMID_DOOR_MAGIC_SI_NS : ITEMID_DOOR_MAGIC_SI_EW; CItem *pFace = CItem::CreateBase(id); ASSERT(pFace); pFace->MoveToDecay(pItem->GetTopPoint(), 4 * TICK_PER_SEC); } if ( !IsPriv(PRIV_GM) ) return true; } case IT_DOOR_OPEN: case IT_DOOR: { if ( fLink || !pItem->Use_DoorNew(fLink) ) // don't link if we are just closing the door return true; } break; case IT_SHIP_PLANK: { // Close the plank if I'm inside the ship if ( m_pArea->IsFlag(REGION_FLAG_SHIP) && m_pArea->GetResourceID() == pItem->m_uidLink ) { if ( pItem->m_itShipPlank.m_itSideType == IT_SHIP_SIDE_LOCKED && !ContentFindKeyFor(pItem) ) { SysMessageDefault(DEFMSG_ITEMUSE_SHIPSIDE); return true; } return pItem->Ship_Plank(false); } else if ( pItem->IsTopLevel() ) { // Teleport to plank if I'm outside the ship CPointMap pntTarg = pItem->GetTopPoint(); pntTarg.m_z++; Spell_Teleport(pntTarg, true, false, false); } return true; } case IT_SHIP_SIDE_LOCKED: if ( !ContentFindKeyFor(pItem) ) { SysMessageDefault(DEFMSG_ITEMUSE_SHIPSIDE); return true; } case IT_SHIP_SIDE: // Open the plank pItem->Ship_Plank(true); return true; case IT_GRAIN: case IT_GRASS: case IT_GARBAGE: case IT_FRUIT: case IT_FOOD: case IT_FOOD_RAW: case IT_MEAT_RAW: { if ( fLink ) return false; Use_Eat(pItem); return true; } case IT_POTION: case IT_DRINK: case IT_PITCHER: case IT_WATER_WASH: case IT_BOOZE: { if ( fLink ) return false; Use_Drink(pItem); return true; } case IT_LIGHT_OUT: // can the light be lit? case IT_LIGHT_LIT: // can the light be doused? fAction = pItem->Use_Light(); break; case IT_CLOTHING: case IT_ARMOR: case IT_ARMOR_LEATHER: case IT_SHIELD: case IT_WEAPON_MACE_CROOK: case IT_WEAPON_MACE_PICK: case IT_WEAPON_MACE_SMITH: case IT_WEAPON_MACE_SHARP: case IT_WEAPON_SWORD: case IT_WEAPON_FENCE: case IT_WEAPON_BOW: case IT_WEAPON_AXE: case IT_WEAPON_XBOW: case IT_WEAPON_MACE_STAFF: case IT_JEWELRY: case IT_WEAPON_THROWING: { if ( fLink ) return false; return ItemEquip(pItem); } case IT_WEB: { if ( fLink ) return false; Use_Item_Web(pItem); return true; } case IT_SPY_GLASS: { if ( fLink ) return false; // Spyglass will tell you the moon phases static LPCTSTR const sm_sPhases[8] = { g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M1), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M2), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M3), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M4), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M5), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M6), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M7), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_M8) }; SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_TR), sm_sPhases[g_World.GetMoonPhase(false)]); SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SPYGLASS_FE), sm_sPhases[g_World.GetMoonPhase(true)]); if ( m_pArea && m_pArea->IsFlag(REGION_FLAG_SHIP) ) ObjMessage(pItem->Use_SpyGlass(this), this); return true; } case IT_SEXTANT: { if ( fLink ) return false; if ( (GetTopPoint().m_map <= 1) && (GetTopPoint().m_x > UO_SIZE_X_REAL) ) // dungeons and T2A lands ObjMessage(g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SEXTANT_T2A), this); else { TCHAR *pszMsg = Str_GetTemp(); sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SEXTANT), m_pArea->GetName(), pItem->Use_Sextant(GetTopPoint())); ObjMessage(pszMsg, this); } return true; } default: fAction = false; } return fAction | MASK_RETURN_FOLLOW_LINKS; }
bool CClient::r_Verb(CScript &s, CTextConsole *pSrc) // Execute command from script { ADDTOCALLSTACK("CClient::r_Verb"); EXC_TRY("Verb"); // NOTE: This can be called directly from a RES_WEBPAGE script. // So do not assume we are a game client ! // NOTE: Mostly called from CChar::r_Verb // NOTE: Little security here so watch out for dangerous scripts ! ASSERT(pSrc); LPCTSTR pszKey = s.GetKey(); // Old ver if ( s.IsKeyHead("SET", 3) && !g_Cfg.m_Functions.ContainsKey(pszKey) ) { PLEVEL_TYPE ilevel = g_Cfg.GetPrivCommandLevel("SET"); if ( ilevel > GetPrivLevel() ) return false; ASSERT(m_pChar); addTargetVerb(pszKey + 3, s.GetArgRaw()); return true; } if ( (toupper(pszKey[0]) == 'X') && !g_Cfg.m_Functions.ContainsKey(pszKey) ) { PLEVEL_TYPE ilevel = g_Cfg.GetPrivCommandLevel("SET"); if ( ilevel > GetPrivLevel() ) return false; // Target this command verb on some other object. ASSERT(m_pChar); addTargetVerb(pszKey + 1, s.GetArgRaw()); return true; } int index = FindTableSorted(s.GetKey(), sm_szVerbKeys, COUNTOF(sm_szVerbKeys) - 1); switch ( index ) { case CV_ADD: { if ( s.HasArgs() ) { TCHAR *ppArgs[2]; size_t iArgQty = Str_ParseCmds(s.GetArgStr(), ppArgs, COUNTOF(ppArgs)); if ( !IsValidGameObjDef(static_cast<LPCTSTR>(ppArgs[0])) ) { g_Log.EventWarn("Invalid ADD argument '%s'\n", ppArgs[0]); SysMessageDefault(DEFMSG_CMD_INVALID); return true; } RESOURCE_ID rid = g_Cfg.ResourceGetID(RES_QTY, const_cast<LPCTSTR &>(ppArgs[0])); m_tmAdd.m_id = rid.GetResIndex(); m_tmAdd.m_amount = (iArgQty > 1) ? static_cast<WORD>(maximum(ATOI(ppArgs[1]), 1)) : 1; if ( (rid.GetResType() == RES_CHARDEF) || (rid.GetResType() == RES_SPAWN) ) { m_Targ_PrvUID.InitUID(); return addTargetChars(CLIMODE_TARG_ADDCHAR, static_cast<CREID_TYPE>(m_tmAdd.m_id), false); } else return addTargetItems(CLIMODE_TARG_ADDITEM, static_cast<ITEMID_TYPE>(m_tmAdd.m_id)); break; } if ( IsValidDef("d_add") ) Dialog_Setup(CLIMODE_DIALOG, g_Cfg.ResourceGetIDType(RES_DIALOG, "d_add"), 0, m_pChar); else Menu_Setup(g_Cfg.ResourceGetIDType(RES_MENU, "MENU_ADDITEM")); break; } case CV_ADDBUFF: { TCHAR *ppArgs[11]; Str_ParseCmds(s.GetArgStr(), ppArgs, COUNTOF(ppArgs)); int iArgs[4]; for ( int i = 0; i < 4; ++i ) { if ( !IsStrNumeric(ppArgs[i]) ) { DEBUG_ERR(("Invalid AddBuff argument number %u\n", i + 1)); return true; } iArgs[i] = Exp_GetVal(ppArgs[i]); } if ( (iArgs[0] < 0) || (iArgs[0] > USHRT_MAX) ) { DEBUG_ERR(("Invalid AddBuff icon ID\n")); break; } LPCTSTR pszArgs[7]; size_t iArgQty = 0; for ( int i = 0; i < 7; ++i ) { pszArgs[i] = ppArgs[i + 4]; if ( pszArgs[i] != NULL ) ++iArgQty; } addBuff(static_cast<BUFF_ICONS>(iArgs[0]), static_cast<DWORD>(iArgs[1]), static_cast<DWORD>(iArgs[2]), static_cast<WORD>(iArgs[3]), pszArgs, iArgQty); break; } case CV_REMOVEBUFF: { BUFF_ICONS IconId = static_cast<BUFF_ICONS>(s.GetArgVal()); if ( (IconId < 0) || (IconId > USHRT_MAX) ) { DEBUG_ERR(("Invalid RemoveBuff icon ID\n")); break; } removeBuff(IconId); break; } case CV_ADDCLILOC: { // Add cliloc in @ClientTooltip trigger TCHAR *ppArgs[256]; size_t iArgQty = Str_ParseCmds(s.GetArgRaw(), ppArgs, COUNTOF(ppArgs), ","); DWORD dwClilocId = static_cast<DWORD>(Exp_GetLLVal(ppArgs[0])); CGString sVal; for ( size_t i = 1; i < iArgQty; ++i ) { if ( sVal.GetLength() ) sVal += "\t"; sVal += !strcmp(ppArgs[i], "NULL") ? " " : ppArgs[i]; } if ( g_Cfg.m_wDebugFlags & DEBUGF_SCRIPTS ) g_Log.EventDebug("SCRIPT: addcliloc(%lu,'%s')\n", dwClilocId, static_cast<LPCTSTR>(sVal)); m_TooltipData.Add(new CClientTooltip(dwClilocId, sVal)); break; } case CV_ADDCONTEXTENTRY: { TCHAR *ppArgs[20]; if ( Str_ParseCmds(s.GetArgRaw(), ppArgs, COUNTOF(ppArgs), ",") > 4 ) { DEBUG_ERR(("Bad AddContextEntry usage: Function takes maximum of 4 arguments!\n")); return true; } if ( !m_pPopupPacket ) { DEBUG_ERR(("Bad AddContextEntry usage: Not used under a @ContextMenuRequest/@itemContextMenuRequest trigger!\n")); return true; } for ( int i = 0; i < 4; ++i ) { if ( (i > 1) && IsStrEmpty(ppArgs[i]) ) continue; if ( !IsStrNumeric(ppArgs[i]) ) { DEBUG_ERR(("Bad AddContextEntry usage: Argument %d must be a number!\n", i + 1)); return true; } } int iTextEntry = Exp_GetVal(ppArgs[0]); if ( iTextEntry < 100 ) { DEBUG_ERR(("Bad AddContextEntry usage: TextEntry < 100 is reserved for server usage!\n")); return true; } m_pPopupPacket->addOption(static_cast<WORD>(iTextEntry), static_cast<DWORD>(Exp_GetLLVal(ppArgs[1])), static_cast<WORD>(Exp_GetLLVal(ppArgs[2])), static_cast<WORD>(Exp_GetLLVal(ppArgs[3]))); break; } case CV_ARROWQUEST: { INT64 piVal[3]; Str_ParseCmds(s.GetArgRaw(), piVal, COUNTOF(piVal)); addArrowQuest(static_cast<WORD>(piVal[0]), static_cast<WORD>(piVal[1]), static_cast<DWORD>(piVal[2])); break; } case CV_BADSPAWN: { // Loop the world searching for bad spawns bool fFound = false; CItem *pItem = NULL; CSector *pSector = NULL; CResourceDef *pSpawnDef = NULL; for ( int m = 0; (m < 256) && !fFound; ++m ) { if ( !g_MapList.m_maps[m] ) continue; for ( int s = 0; (s < g_MapList.GetSectorQty(m)) && !fFound; ++s ) { pSector = g_World.GetSector(m, s); if ( !pSector ) continue; for ( pItem = static_cast<CItem *>(pSector->m_Items_Timer.GetHead()); (pItem != NULL) && !fFound; pItem = pItem->GetNext() ) { if ( pItem->IsType(IT_SPAWN_ITEM) || pItem->IsType(IT_SPAWN_CHAR) ) { pSpawnDef = static_cast<CItemSpawn *>(pItem)->FixDef(); if ( !pSpawnDef ) { RESOURCE_ID_BASE rid = pItem->IsType(IT_SPAWN_ITEM) ? pItem->m_itSpawnItem.m_ItemID : pItem->m_itSpawnChar.m_CharID; CPointMap pt = pItem->GetTopPoint(); m_pChar->Spell_Teleport(pt, true, false); m_pChar->m_Act_Targ = pItem->GetUID(); SysMessagef("Bad spawn (0%lx, id=%s). Set as ACT", static_cast<DWORD>(pItem->GetUID()), g_Cfg.ResourceGetName(rid)); fFound = true; } } } } } if ( !fFound ) SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_NO_BAD_SPAWNS)); break; } case CV_BANKSELF: { addBankOpen(m_pChar, LAYER_BANKBOX); break; } case CV_CAST: { SPELL_TYPE spell = static_cast<SPELL_TYPE>(g_Cfg.ResourceGetIndexType(RES_SPELL, s.GetArgStr())); const CSpellDef *pSpellDef = g_Cfg.GetSpellDef(spell); if ( !pSpellDef ) return true; CObjBase *pObjSrc = dynamic_cast<CObjBase *>(pSrc); if ( IsSetMagicFlags(MAGICF_PRECAST) && !pSpellDef->IsSpellType(SPELLFLAG_NOPRECAST) ) { int iSkill; if ( !pSpellDef->GetPrimarySkill(&iSkill, NULL) ) return true; m_tmSkillMagery.m_Spell = spell; // m_atMagery.m_Spell m_pChar->m_atMagery.m_Spell = spell; if ( pObjSrc ) { m_Targ_UID = pObjSrc->GetUID(); // default target. m_Targ_PrvUID = pObjSrc->GetUID(); } else { m_Targ_UID.ClearUID(); m_Targ_PrvUID.ClearUID(); } m_pChar->Skill_Start(static_cast<SKILL_TYPE>(iSkill)); break; } else Cmd_Skill_Magery(spell, pObjSrc); break; } case CV_CHANGEFACE: // open 'face selection' dialog (enhanced clients only) { addGumpDialog(CLIMODE_DIALOG, NULL, 0, NULL, 0, 0, 0, m_pChar, CLIMODE_DIALOG_FACESELECTION); break; } case CV_CHARLIST: // usually just a gm command { if ( !PacketChangeCharacter::CanSendTo(m_NetState) ) break; new PacketChangeCharacter(this); CharDisconnect(); // since there is no undoing this in the client. SetTargMode(CLIMODE_SETUP_CHARLIST); break; } case CV_CTAGLIST: { if ( !strcmpi(s.GetArgStr(), "log") ) pSrc = &g_Serv; m_TagDefs.DumpKeys(pSrc, "CTAG."); break; } case CV_CLEARCTAGS: { if ( s.HasArgs() ) { LPCTSTR pszArgs = s.GetArgStr(); SKIP_SEPARATORS(pszArgs); m_TagDefs.ClearKeys(pszArgs); } else m_TagDefs.ClearKeys(); break; } case CV_CLOSEPAPERDOLL: { const CChar *pChar = s.HasArgs() ? static_cast<CGrayUID>(s.GetArgVal()).CharFind() : m_pChar; if ( pChar ) closeUIWindow(pChar, 0x1); break; } case CV_CLOSEPROFILE: { const CChar *pChar = s.HasArgs() ? static_cast<CGrayUID>(s.GetArgVal()).CharFind() : m_pChar; if ( pChar ) closeUIWindow(pChar, 0x8); break; } case CV_CLOSESTATUS: { const CChar *pChar = s.HasArgs() ? static_cast<CGrayUID>(s.GetArgVal()).CharFind() : m_pChar; if ( pChar ) closeUIWindow(pChar, 0x2); break; } case CV_CODEXOFWISDOM: { INT64 piArgs[2]; size_t iArgQty = Str_ParseCmds(s.GetArgStr(), piArgs, COUNTOF(piArgs)); if ( iArgQty < 1 ) { SysMessage("Usage: CODEXOFWISDOM TopicID [ForceOpen]"); break; } addCodexOfWisdom(static_cast<DWORD>(piArgs[0]), static_cast<bool>(piArgs[1])); break; } case CV_DYE: { const CObjBase *pObj = s.HasArgs() ? static_cast<CGrayUID>(s.GetArgVal()).ObjFind() : NULL; if ( pObj ) addDyeOption(pObj); break; } case CV_EVERBTARG: { m_Prompt_Text = s.GetArgStr(); addPromptConsole(CLIMODE_PROMPT_TARG_VERB, m_Targ_Text.IsEmpty() ? "Enter the verb" : "Enter the text", m_Targ_UID); break; } case CV_EXTRACT: { // sort of like EXPORT but for statics. // Opposite of the "UNEXTRACT" command TCHAR *ppArgs[2]; size_t iArgQty = Str_ParseCmds(s.GetArgStr(), ppArgs, COUNTOF(ppArgs)); if ( iArgQty < 2 ) { SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_EXTRACT_USAGE)); break; } m_Targ_Text = ppArgs[0]; // point at the options (if any) m_tmTile.m_ptFirst.InitPoint(); // clear this first m_tmTile.m_Code = CV_EXTRACT; // set extract code m_tmTile.m_id = Exp_GetVal(ppArgs[1]); // extract id addTarget(CLIMODE_TARG_TILE, g_Cfg.GetDefaultMsg(DEFMSG_SELECT_EXTRACT_AREA), true); break; } case CV_UNEXTRACT: { // Create item from script. // Opposite of the "EXTRACT" command TCHAR *ppArgs[2]; size_t iArgQty = Str_ParseCmds(s.GetArgStr(), ppArgs, COUNTOF(ppArgs)); if ( iArgQty < 2 ) { SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_UNEXTRACT_USAGE)); break; } m_Targ_Text = ppArgs[0]; // point at the options (if any) m_tmTile.m_ptFirst.InitPoint(); // clear this first m_tmTile.m_Code = CV_UNEXTRACT; // set extract code m_tmTile.m_id = Exp_GetVal(ppArgs[1]); // extract id addTarget(CLIMODE_TARG_UNEXTRACT, g_Cfg.GetDefaultMsg(DEFMSG_SELECT_MULTI_POS), true); break; } case CV_GMPAGE: { m_Targ_Text = s.GetArgStr(); if ( !m_Targ_Text.IsEmpty() && !strnicmp(m_Targ_Text, "ADD ", 4) ) { Cmd_GM_Page(m_Targ_Text + 4); break; } addPromptConsole(CLIMODE_PROMPT_GM_PAGE_TEXT, g_Cfg.GetDefaultMsg(DEFMSG_GMPAGE_PROMPT)); break; } case CV_GOTARG: // go to my (preselected) target. { ASSERT(m_pChar); CObjBase *pObj = m_Targ_UID.ObjFind(); if ( pObj ) { CPointMap pt = pObj->GetTopLevelObj()->GetTopPoint(); m_pChar->m_dirFace = m_pChar->GetDir(pObj, m_pChar->m_dirFace); m_pChar->Spell_Teleport(pt, true, false); } break; } case CV_INFO: { // We could also get ground tile info. addTarget(CLIMODE_TARG_OBJ_INFO, g_Cfg.GetDefaultMsg(DEFMSG_SELECT_ITEM_INFO), true, false); break; } case CV_INFORMATION: { SysMessage(g_Serv.GetStatusString(0x22)); SysMessage(g_Serv.GetStatusString(0x24)); break; } case CV_LAST: // fake previous target { if ( GetTargMode() >= CLIMODE_MOUSE_TYPE ) { ASSERT(m_pChar); CObjBase *pObj = m_pChar->m_Act_Targ.ObjFind(); if ( pObj ) { Event_Target(GetTargMode(), pObj->GetUID(), pObj->GetTopPoint()); addTargetCancel(); } break; } return false; } case CV_LINK: // link doors { m_Targ_UID.InitUID(); addTarget(CLIMODE_TARG_LINK, g_Cfg.GetDefaultMsg(DEFMSG_SELECT_LINK_ITEM)); break; } case CV_MAPWAYPOINT: { INT64 piVal[2]; size_t iArgQty = Str_ParseCmds(s.GetArgRaw(), piVal, COUNTOF(piVal)); if ( iArgQty < 2 ) { SysMessage("Usage: MAPWAYPOINT uid type"); break; } CObjBase *pObj = static_cast<CGrayUID>(piVal[0]).ObjFind(); addMapWaypoint(pObj, static_cast<MAPWAYPOINT_TYPE>(piVal[1])); break; } case CV_MENU: { Menu_Setup(g_Cfg.ResourceGetIDType(RES_MENU, s.GetArgStr())); break; } case CV_MIDILIST: { INT64 piMidi[64]; size_t iArgQty = Str_ParseCmds(s.GetArgStr(), piMidi, COUNTOF(piMidi)); if ( iArgQty > 0 ) addMusic(static_cast<MIDI_TYPE>(piMidi[Calc_GetRandVal(iArgQty)])); break; } case CV_NUDGE: { if ( !s.HasArgs() ) { SysMessage("Usage: NUDGE dx dy dz"); break; } m_Targ_Text = s.GetArgRaw(); m_tmTile.m_ptFirst.InitPoint(); // clear this first m_tmTile.m_Code = CV_NUDGE; addTarget(CLIMODE_TARG_TILE, g_Cfg.GetDefaultMsg(DEFMSG_SELECT_NUDGE_AREA), true); break; } case CV_NUKE: { m_Targ_Text = s.GetArgRaw(); m_tmTile.m_ptFirst.InitPoint(); // clear this first m_tmTile.m_Code = CV_NUKE; // set nuke code addTarget(CLIMODE_TARG_TILE, g_Cfg.GetDefaultMsg(DEFMSG_SELECT_NUKE_AREA), true); break; } case CV_NUKECHAR: { m_Targ_Text = s.GetArgRaw(); m_tmTile.m_ptFirst.InitPoint(); // clear this first m_tmTile.m_Code = CV_NUKECHAR; // set nuke code addTarget(CLIMODE_TARG_TILE, g_Cfg.GetDefaultMsg(DEFMSG_SELECT_NUKE_CHAR_AREA), true); break; } case CV_OPENPAPERDOLL: { const CChar *pChar = s.HasArgs() ? static_cast<CGrayUID>(s.GetArgVal()).CharFind() : m_pChar; if ( pChar ) addCharPaperdoll(pChar); break; } case CV_OPENTRADEWINDOW: { TCHAR *ppArgs[2]; Str_ParseCmds(s.GetArgStr(), ppArgs, COUNTOF(ppArgs)); CChar *pChar = ppArgs[0] ? static_cast<CGrayUID>(Exp_GetLLVal(ppArgs[0])).CharFind() : NULL; if ( pChar ) { CItem *pItem = ppArgs[1] ? static_cast<CGrayUID>(Exp_GetLLVal(ppArgs[1])).ItemFind() : NULL; Cmd_SecureTrade(pChar, pItem); } break; } case CV_PAGE: Cmd_GM_PageCmd(s.GetArgStr()); break; case CV_REPAIR: addTarget(CLIMODE_TARG_REPAIR, g_Cfg.GetDefaultMsg(DEFMSG_SELECT_ITEM_REPAIR)); break; case CV_FLUSH: #ifndef _MTNETWORK g_NetworkOut.flush(this); #else g_NetworkManager.flush(m_NetState); #endif break; case CV_RESEND: addReSync(); break; case CV_SAVE: g_World.Save(s.GetArgVal() != 0); break; case CV_SCROLL: // put a scroll up. addScrollResource(s.GetArgStr(), SCROLL_TYPE_UPDATES); break; case CV_SENDPACKET: SendPacket(s.GetArgStr()); break; case CV_SELF: // fake self target if ( GetTargMode() >= CLIMODE_MOUSE_TYPE ) { ASSERT(m_pChar); Event_Target(GetTargMode(), m_pChar->GetUID(), m_pChar->GetTopPoint()); addTargetCancel(); break; } return false; case CV_SHOWSKILLS: addSkillWindow(static_cast<SKILL_TYPE>(g_Cfg.m_iMaxSkill)); // reload the real skills break; case CV_SKILLMENU: Cmd_Skill_Menu(g_Cfg.ResourceGetIDType(RES_SKILLMENU, s.GetArgStr())); break; case CV_SKILLSELECT: Event_Skill_Use(g_Cfg.FindSkillKey(s.GetArgStr())); break; case CV_SUMMON: { ASSERT(m_pChar); const CSpellDef *pSpellDef = g_Cfg.GetSpellDef(SPELL_Summon); if ( !pSpellDef ) return false; m_pChar->m_Act_Targ = m_pChar->GetUID(); m_pChar->m_Act_TargPrv = m_pChar->GetUID(); if ( pSpellDef->IsSpellType(SPELLFLAG_TARG_OBJ|SPELLFLAG_TARG_XYZ) ) { m_tmSkillMagery.m_Spell = SPELL_Summon; m_tmSkillMagery.m_SummonID = static_cast<CREID_TYPE>(g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr())); LPCTSTR pszPrompt = g_Cfg.GetDefaultMsg(DEFMSG_SELECT_MAGIC_TARGET); if ( !pSpellDef->m_sTargetPrompt.IsEmpty() ) pszPrompt = pSpellDef->m_sTargetPrompt; int iSpellTimeout = static_cast<int>(GetDefNum("SPELLTIMEOUT")); if ( !iSpellTimeout ) iSpellTimeout = g_Cfg.m_iSpellTimeout * TICK_PER_SEC; addTarget(CLIMODE_TARG_SKILL_MAGERY, pszPrompt, pSpellDef->IsSpellType(SPELLFLAG_TARG_XYZ), pSpellDef->IsSpellType(SPELLFLAG_HARM), iSpellTimeout); break; } else { m_pChar->m_atMagery.m_Spell = SPELL_Summon; m_pChar->m_atMagery.m_SummonID = static_cast<CREID_TYPE>(g_Cfg.ResourceGetIndexType(RES_CHARDEF, s.GetArgStr())); if ( IsSetMagicFlags(MAGICF_PRECAST) && !pSpellDef->IsSpellType(SPELLFLAG_NOPRECAST) ) { m_pChar->Spell_CastDone(); break; } else { int iSkill; if ( !pSpellDef->GetPrimarySkill(&iSkill, NULL) ) return false; m_pChar->Skill_Start(static_cast<SKILL_TYPE>(iSkill)); } } break; } case CV_SMSG: case CV_SYSMESSAGE: SysMessage(s.GetArgStr()); break; case CV_SYSMESSAGEF: // there is still an issue with numbers not resolving properly when %i,%d,or other numeric format code is in use { TCHAR *ppArgs[4]; size_t iArgQty = Str_ParseCmds(s.GetArgRaw(), ppArgs, COUNTOF(ppArgs)); if ( iArgQty < 2 ) { g_Log.EventError("SysMessagef with less than 1 args for the given text\n"); return false; } if ( iArgQty > 4 ) { g_Log.EventError("Too many arguments given to SysMessagef (max = text + 3\n"); return false; } if ( *ppArgs[0] == '"' ) // skip quotes ++ppArgs[0]; for ( TCHAR *pEnd = ppArgs[0] + strlen(ppArgs[0]) - 1; pEnd >= ppArgs[0]; --pEnd ) { if ( *pEnd == '"' ) // skip quotes { *pEnd = '\0'; break; } } SysMessagef(ppArgs[0], ppArgs[1], ppArgs[2] ? ppArgs[2] : 0, ppArgs[3] ? ppArgs[3] : 0); break; } case CV_SMSGU: case CV_SYSMESSAGEUA: { TCHAR *ppArgs[5]; size_t iArgQty = Str_ParseCmds(s.GetArgRaw(), ppArgs, COUNTOF(ppArgs)); if ( iArgQty > 4 ) { // Font and mode are actually ignored here, but they never made a difference anyway.. I'd like to keep the syntax similar to SAYUA NCHAR szBuffer[MAX_TALK_BUFFER]; CvtSystemToNUNICODE(szBuffer, COUNTOF(szBuffer), ppArgs[4], -1); addBarkUNICODE(szBuffer, NULL, static_cast<HUE_TYPE>(Exp_GetLLVal(ppArgs[0])), TALKMODE_SYSTEM, FONT_NORMAL, ppArgs[3]); } break; } case CV_SMSGL: case CV_SYSMESSAGELOC: { TCHAR *ppArgs[256]; size_t iArgQty = Str_ParseCmds(s.GetArgRaw(), ppArgs, COUNTOF(ppArgs), ","); if ( iArgQty > 1 ) { HUE_TYPE hue = HUE_TEXT_DEF; if ( ATOI(ppArgs[0]) > 0 ) hue = static_cast<HUE_TYPE>(Exp_GetLLVal(ppArgs[0])); DWORD dwClilocId = static_cast<DWORD>(Exp_GetLLVal(ppArgs[1])); CGString sVal; for ( size_t i = 2; i < iArgQty; ++i ) { if ( sVal.GetLength() ) sVal += "\t"; sVal += !strcmp(ppArgs[i], "NULL") ? " " : ppArgs[i]; } addBarkLocalized(dwClilocId, NULL, hue, TALKMODE_SYSTEM, FONT_NORMAL, sVal.GetPtr()); } break; } case CV_SMSGLEX: case CV_SYSMESSAGELOCEX: { TCHAR *ppArgs[256]; size_t iArgQty = Str_ParseCmds(s.GetArgRaw(), ppArgs, COUNTOF(ppArgs), ","); if ( iArgQty > 2 ) { HUE_TYPE hue = HUE_TEXT_DEF; AFFIX_TYPE affix = AFFIX_APPEND; if ( ATOI(ppArgs[0]) > 0 ) hue = static_cast<HUE_TYPE>(Exp_GetLLVal(ppArgs[0])); DWORD dwClilocId = static_cast<DWORD>(Exp_GetLLVal(ppArgs[1])); if ( ppArgs[2] ) affix = static_cast<AFFIX_TYPE>(Exp_GetLLVal(ppArgs[2])); CGString sVal; for ( size_t i = 4; i < iArgQty; ++i ) { if ( sVal.GetLength() ) sVal += "\t"; sVal += !strcmp(ppArgs[i], "NULL") ? " " : ppArgs[i]; } addBarkLocalizedEx(dwClilocId, NULL, hue, TALKMODE_SYSTEM, FONT_NORMAL, affix, ppArgs[3], sVal.GetPtr()); } break; } case CV_TELE: Cmd_Skill_Magery(SPELL_Teleport, dynamic_cast<CObjBase *>(pSrc)); break; case CV_TILE: if ( !s.HasArgs() ) { SysMessage("Usage: TILE z-height item1 item2 itemX"); break; } m_Targ_Text = s.GetArgStr(); // point at the options m_tmTile.m_ptFirst.InitPoint(); // clear this first m_tmTile.m_Code = CV_TILE; addTarget(CLIMODE_TARG_TILE, "Pick 1st corner:", true); break; case CV_VERSION: SysMessage(g_szServerDescription); break; case CV_WEBLINK: addWebLaunch(s.GetArgStr()); break; default: if ( r_LoadVal(s) ) { CGString sVal; if ( r_WriteVal(s.GetKey(), sVal, pSrc) ) return true; } return CScriptObj::r_Verb(s, pSrc); // used in the case of web pages to access server level things } return true; EXC_CATCH; EXC_DEBUG_START; EXC_ADD_SCRIPTSRC; EXC_DEBUG_END; return false; }
bool CChar::Use_Train_Dummy( CItem * pItem, bool fSetup ) { ADDTOCALLSTACK("CChar::Use_Train_Dummy"); // IT_TRAIN_DUMMY // Dummy animation timer prevents over dclicking. ASSERT(pItem); SKILL_TYPE skill = Fight_GetWeaponSkill(); if ( g_Cfg.IsSkillFlag(skill, SKF_RANGED) ) // do not allow archery training on dummys { SysMessageDefault(DEFMSG_ITEMUSE_TDUMMY_ARCH); return false; } char skilltag[32]; sprintf(skilltag, "OVERRIDE.PracticeMax.SKILL_%d", skill &~0xD2000000); CVarDefCont *pSkillTag = pItem->GetKey(skilltag, true); WORD iMaxSkill = pSkillTag ? static_cast<WORD>(pSkillTag->GetValNum()) : g_Cfg.m_iSkillPracticeMax; if ( Skill_GetBase(skill) > iMaxSkill ) { SysMessageDefault(DEFMSG_ITEMUSE_TDUMMY_SKILL); return false; } if ( !pItem->IsTopLevel() ) { baddumy: SysMessageDefault(DEFMSG_ITEMUSE_TDUMMY_P); return false ; } // Check location int dx = GetTopPoint().m_x - pItem->GetTopPoint().m_x; int dy = GetTopPoint().m_y - pItem->GetTopPoint().m_y; if ( pItem->GetDispID() == ITEMID_DUMMY1 ) { if ( !(!dx && abs(dy) < 2) ) goto baddumy; } else { if ( !(!dy && abs(dx) < 2) ) goto baddumy; } if ( fSetup ) { if ( Skill_GetActive() == NPCACT_TRAINING ) return true; UpdateAnimate(ANIM_ATTACK_WEAPON); m_Act_TargPrv = m_uidWeapon; m_Act_Targ = pItem->GetUID(); Skill_Start(NPCACT_TRAINING); } else { static const SOUND_TYPE sm_TrainingDummySounds[] = { 0x3A4, 0x3A6, 0x3A9, 0x3AE, 0x3B4, 0x3B6 }; pItem->Sound(sm_TrainingDummySounds[Calc_GetRandVal(COUNTOF(sm_TrainingDummySounds))]); pItem->SetAnim(static_cast<ITEMID_TYPE>(pItem->GetID() + 1), 3 * TICK_PER_SEC); Skill_UseQuick(skill, Calc_GetRandLLVal(40)); } return true; }
bool CChar::NPC_OnHearPetCmdTarg( int iCmd, CChar * pSrc, CObjBase * pObj, const CPointMap & pt, LPCTSTR pszArgs ) { ADDTOCALLSTACK("CChar::NPC_OnHearPetCmdTarg"); // Pet commands that required a target. if ( iCmd == PC_FOLLOW || iCmd == PC_STAY || iCmd == PC_STOP ) { // Pet friends can use only these commands if ( ! NPC_IsOwnedBy( pSrc ) && Memory_FindObjTypes( pSrc, MEMORY_FRIEND ) == NULL ) return false; } else { // All others commands are avaible only to pet owner if ( ! NPC_IsOwnedBy( pSrc, true ) ) return false; } if ( m_fIgnoreNextPetCmd == true ) { m_fIgnoreNextPetCmd = false; return(false); } bool fSuccess = false; // No they won't do it. // Could be NULL CItem * pItemTarg = dynamic_cast<CItem*>(pObj); CChar * pCharTarg = dynamic_cast<CChar*>(pObj); switch ( iCmd ) { case PC_GO: // Go to the location x,y if ( ! pt.IsValidPoint()) break; m_Act_p = pt; fSuccess = Skill_Start( NPCACT_GOTO ); break; case PC_GUARD: if ( pObj == NULL ) break; m_Act_Targ = pObj->GetUID(); fSuccess = Skill_Start( NPCACT_GUARD_TARG ); break; case PC_TRANSFER: // transfer ownership via the transfer command. if ( pCharTarg == NULL ) break; if ( pCharTarg->IsClient() ) { if ( IsSetOF(OF_PetSlots) ) { if ( !pCharTarg->FollowersUpdate(this, static_cast<short>(maximum(1, GetDefNum("FOLLOWERSLOTS", true, true))), true) ) { pSrc->SysMessageDefault( DEFMSG_PETSLOTS_TRY_TRANSFER ); break; } } fSuccess = NPC_PetSetOwner( pCharTarg ); } break; case PC_KILL: case PC_ATTACK: // Attack the target. if ( pCharTarg == NULL ) break; // refuse to attack friends. if ( NPC_IsOwnedBy( pCharTarg, true )) { fSuccess = false; // take no commands break; } fSuccess = pCharTarg->OnAttackedBy( pSrc, 1, true ); // we know who told them to do this. if ( fSuccess ) { fSuccess = Fight_Attack( pCharTarg, true ); } break; case PC_FOLLOW: if ( pCharTarg == NULL ) break; m_Act_Targ = pCharTarg->GetUID(); fSuccess = Skill_Start( NPCACT_FOLLOW_TARG ); break; case PC_FRIEND: // Not the same as owner, if ( pCharTarg == NULL ) break; Memory_AddObjTypes( pCharTarg, MEMORY_FRIEND ); break; case PC_PRICE: // "PRICE" the vendor item. if ( pItemTarg == NULL ) break; if ( ! NPC_IsVendor()) break; // did they name a price if ( IsDigit( pszArgs[0] )) { return NPC_SetVendorPrice( pItemTarg, ATOI(pszArgs) ); } // test if it is pricable. if ( ! NPC_SetVendorPrice( pItemTarg, -1 )) { return false; } // Now set it's price. if ( ! pSrc->IsClient()) break; pSrc->m_pClient->addPromptConsole( CLIMODE_PROMPT_VENDOR_PRICE, g_Cfg.GetDefaultMsg( DEFMSG_NPC_VENDOR_SETPRICE_2 ), pItemTarg->GetUID(), GetUID() ); return( true ); default: break; } // Make the yes/no noise. NPC_OnPetCommand( fSuccess, pSrc ); return fSuccess; }
bool CChar::Use_Train_ArcheryButte( CItem * pButte, bool fSetup ) { ADDTOCALLSTACK("CChar::Use_Train_ArcheryButte"); // IT_ARCHERY_BUTTE ASSERT(pButte); ITEMID_TYPE AmmoID; if ( GetDist(pButte) < 2 ) // if we are standing right next to the butte, retrieve the arrows/bolts { if ( pButte->m_itArcheryButte.m_AmmoCount == 0 ) { SysMessageDefault(DEFMSG_ITEMUSE_ARCHB_EMPTY); return true; } AmmoID = pButte->m_itArcheryButte.m_AmmoType; CItemBase *pAmmoDef = CItemBase::FindItemBase(AmmoID); if ( pAmmoDef ) { TCHAR *pszMsg = Str_GetTemp(); sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_REM), pAmmoDef->GetName(), (pButte->m_itArcheryButte.m_AmmoCount == 1) ? "" : g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_REMS)); Emote(pszMsg); CItem *pRemovedAmmo = CItem::CreateBase(AmmoID); ASSERT(pRemovedAmmo); pRemovedAmmo->SetAmount(pButte->m_itArcheryButte.m_AmmoCount); ItemBounce(pRemovedAmmo); } // Clear the target pButte->m_itArcheryButte.m_AmmoType = ITEMID_NOTHING; pButte->m_itArcheryButte.m_AmmoCount = 0; return true; } SKILL_TYPE skill = Fight_GetWeaponSkill(); if ( !g_Cfg.IsSkillFlag(skill, SKF_RANGED) ) { SysMessageDefault(DEFMSG_ITEMUSE_ARCHB_WS); return true; } if ( Skill_GetBase(skill) > g_Cfg.m_iSkillPracticeMax ) { SysMessageDefault(DEFMSG_ITEMUSE_ARCHB_SKILL); return true; } // Make sure we have some ammo CItem *pWeapon = m_uidWeapon.ItemFind(); ASSERT(pWeapon); const CItemBase *pWeaponDef = pWeapon->Item_GetDef(); // Determine ammo type CVarDefCont *pVarAmmoType = pWeapon->GetDefKey("AMMOTYPE", true); RESOURCE_ID_BASE rid; LPCTSTR t_Str; if ( pVarAmmoType ) { t_Str = pVarAmmoType->GetValStr(); rid = static_cast<RESOURCE_ID_BASE>(g_Cfg.ResourceGetID(RES_ITEMDEF, t_Str)); } else { rid = pWeaponDef->m_ttWeaponBow.m_idAmmo; } AmmoID = static_cast<ITEMID_TYPE>(rid.GetResIndex()); // If there is a different ammo type on the butte currently, tell us to remove the current type first if ( (pButte->m_itArcheryButte.m_AmmoType != ITEMID_NOTHING) && (pButte->m_itArcheryButte.m_AmmoType != AmmoID) ) { SysMessageDefault(DEFMSG_ITEMUSE_ARCHB_X); return true; } // We need to be correctly aligned with the target before we can use it // For the south facing butte, we need to have the same X value and a Y > 2 // For the east facing butte, we need to have the same Y value and an X > 2 if ( !pButte->IsTopLevel() ) { badalign: SysMessageDefault(DEFMSG_ITEMUSE_ARCHB_P); return true; } int targDistX = GetTopPoint().m_x - pButte->GetTopPoint().m_x; int targDistY = GetTopPoint().m_y - pButte->GetTopPoint().m_y; if ( (pButte->GetID() == ITEMID_ARCHERYBUTTE_S) || (pButte->GetID() == ITEMID_MONGBATTARGET_S) ) { if ( !(targDistX == 0 && targDistY > 2) ) goto badalign; } else { if ( !(targDistY == 0 && targDistX > 2) ) goto badalign; } if ( !CanSeeLOS(pButte, LOS_NB_WINDOWS) ) //we should be able to shoot through a window { SysMessageDefault(DEFMSG_ITEMUSE_ARCHB_BLOCK); return true; } if ( fSetup ) { if ( Skill_GetActive() == NPCACT_TRAINING ) return true; UpdateAnimate(ANIM_ATTACK_WEAPON); m_Act_TargPrv = m_uidWeapon; m_Act_Targ = pButte->GetUID(); Skill_Start(NPCACT_TRAINING); return true; } CVarDefCont *pCont = pWeapon->GetDefKey("AMMOCONT",true); if ( m_pPlayer && AmmoID ) { DWORD iFound = 1; if ( pCont ) { //check for UID CGrayUID uidCont = static_cast<CGrayUID>(pCont->GetValNum()); CItemContainer *pNewCont = dynamic_cast<CItemContainer *>(uidCont.ItemFind()); if ( !pNewCont ) //if no UID, check for ITEMID_TYPE { t_Str = pCont->GetValStr(); RESOURCE_ID_BASE rContid = static_cast<RESOURCE_ID_BASE>(g_Cfg.ResourceGetID(RES_ITEMDEF, t_Str)); ITEMID_TYPE ContID = static_cast<ITEMID_TYPE>(rContid.GetResIndex()); if ( ContID ) pNewCont = dynamic_cast<CItemContainer *>(ContentFind(rContid)); } if ( pNewCont ) iFound = pNewCont->ContentConsume(RESOURCE_ID(RES_ITEMDEF, AmmoID)); else iFound = ContentConsume(RESOURCE_ID(RES_ITEMDEF, AmmoID)); } else iFound = ContentConsume(RESOURCE_ID(RES_ITEMDEF, AmmoID)); if ( iFound ) { SysMessageDefault(DEFMSG_ITEMUSE_ARCHB_NOAMMO); return true; } } // OK...go ahead and fire at the target // Check the skill bool fSuccess = Skill_UseQuick(skill, Calc_GetRandLLVal(40)); // determine animation parameters CVarDefCont *pVarAnim = pWeapon->GetDefKey("AMMOANIM", true); CVarDefCont *pVarAnimColor = pWeapon->GetDefKey("AMMOANIMHUE", true); CVarDefCont *pVarAnimRender = pWeapon->GetDefKey("AMMOANIMRENDER", true); ITEMID_TYPE AmmoAnim; DWORD AmmoHue = pVarAnimColor ? static_cast<DWORD>(pVarAnimColor->GetValNum()) : 0; DWORD AmmoRender = pVarAnimRender ? static_cast<DWORD>(pVarAnimRender->GetValNum()) : 0; if ( pVarAnim ) { t_Str = pVarAnim->GetValStr(); rid = static_cast<RESOURCE_ID_BASE>(g_Cfg.ResourceGetID(RES_ITEMDEF, t_Str)); AmmoAnim = static_cast<ITEMID_TYPE>(rid.GetResIndex()); } else AmmoAnim = static_cast<ITEMID_TYPE>(pWeaponDef->m_ttWeaponBow.m_idAmmoX.GetResIndex()); pButte->Effect(EFFECT_BOLT, AmmoAnim, this, 16, 0, false, AmmoHue, AmmoRender); pButte->Sound(SOUND_CROSSBOW); // Did we destroy the ammo? const CItemBase *pAmmoDef = NULL; if ( AmmoID ) pAmmoDef = CItemBase::FindItemBase(AmmoID); if ( !fSuccess ) { // Small chance of destroying the ammo if ( pAmmoDef && !Calc_GetRandVal(10) ) { TCHAR *pszMsg = Str_GetTemp(); sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_DEST), pAmmoDef->GetName()); Emote(pszMsg, NULL, true); return true; } static LPCTSTR const sm_Txt_ArcheryButte_Failure[] = { g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_MISS_1), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_MISS_2), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_MISS_3), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_MISS_4) }; Emote(sm_Txt_ArcheryButte_Failure[Calc_GetRandVal(COUNTOF(sm_Txt_ArcheryButte_Failure))]); } else { // Very small chance of destroying another arrow if ( pAmmoDef && !Calc_GetRandVal(50) && pButte->m_itArcheryButte.m_AmmoCount ) { TCHAR *pszMsg = Str_GetTemp(); sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_SPLIT), pAmmoDef->GetName()); Emote(pszMsg, NULL, true); return true; } static LPCTSTR const sm_Txt_ArcheryButte_Success[] = { g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_HIT_1), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_HIT_2), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_HIT_3), g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_ARCHB_HIT_4) }; Emote(sm_Txt_ArcheryButte_Success[Calc_GetRandVal(COUNTOF(sm_Txt_ArcheryButte_Success))]); } // Update the target if ( AmmoID ) { pButte->m_itArcheryButte.m_AmmoType = AmmoID; pButte->m_itArcheryButte.m_AmmoCount++; } return true; }
bool CChar::NPC_OnHearPetCmd( LPCTSTR pszCmd, CChar * pSrc, bool fAllPets ) { ADDTOCALLSTACK("CChar::NPC_OnHearPetCmd"); // This should just be another speech block !!! // We own this char (pet or hireling) // pObjTarget = the m_ActTarg has been set for them to attack. // RETURN: // true = we understand this. tho we may not do what we are told. // false = this is not a command we know. // if ( GetTargMode() == CLIMODE_TARG_PET_CMD ) it needs a target. static LPCTSTR const sm_Pet_table[] = { "ATTACK", "BOUGHT", "CASH", "COME", "DROP", // "GIVE" ? "DROP ALL", "EQUIP", "FOLLOW", "FOLLOW ME", "FRIEND", "GO", "GUARD", "GUARD ME", "KILL", "PRICE", // may have args ? "RELEASE", "SAMPLES", "SPEAK", "STATUS", "STAY", "STOCK", "STOP", "TRANSFER", "RELEASE" }; // Kill me? // attack me? m_fIgnoreNextPetCmd = false; // We clear this incase it's true from previous pet cmds. if ( !pSrc->IsClient() || m_pPlayer || !m_pNPC ) return false; TALKMODE_TYPE mode = TALKMODE_SAY; if ( OnTriggerSpeech( true, pszCmd, pSrc, mode) ) { m_fIgnoreNextPetCmd = !fAllPets; return true; } PC_TYPE iCmd = (PC_TYPE) FindTableSorted( pszCmd, sm_Pet_table, COUNTOF(sm_Pet_table)); if ( iCmd < 0 ) { if ( ! strnicmp( pszCmd, sm_Pet_table[PC_PRICE], 5 )) iCmd = PC_PRICE; else return false; } if ( iCmd == PC_FOLLOW || iCmd == PC_STAY || iCmd == PC_STOP ) { // Pet friends can use only these commands if ( ! NPC_IsOwnedBy( pSrc, true ) && Memory_FindObjTypes( pSrc, MEMORY_FRIEND ) == NULL ) return false; } else { // All others commands are avaible only to pet owner if ( ! NPC_IsOwnedBy( pSrc, true ) ) return false; } CCharBase * pCharDef = Char_GetDef(); bool fTargAllowGround = false; bool fMayBeCrime = false; LPCTSTR pTargPrompt = NULL; switch ( iCmd ) { case PC_ATTACK: do_attack: pTargPrompt = g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_TARG_ATT ); fMayBeCrime = true; break; case PC_CASH: // Drop all we have. if ( ! NPC_IsVendor()) return( false ); { // Give up my cash total. CItemContainer * pBank = GetBank(); if ( pBank ) { unsigned int iWage = pCharDef->GetHireDayWage(); TCHAR *pszMsg = Str_GetTemp(); if ( pBank->m_itEqBankBox.m_Check_Amount > iWage ) { sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_GETGOLD_1), pBank->m_itEqBankBox.m_Check_Amount - iWage); pSrc->AddGoldToPack( pBank->m_itEqBankBox.m_Check_Amount - iWage ); pBank->m_itEqBankBox.m_Check_Amount = iWage; } else sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_GETGOLD_2), pBank->m_itEqBankBox.m_Check_Amount); Speak(pszMsg); } return true; } break; case PC_COME: case PC_GUARD_ME: case PC_FOLLOW_ME: m_Act_Targ = pSrc->GetUID(); Skill_Start( NPCACT_FOLLOW_TARG ); break; case PC_RELEASE: Skill_Start( SKILL_NONE ); NPC_PetClearOwners(); SoundChar( CRESND_RAND2 ); // No noise return( true ); case PC_DROP: // Drop just the stuff we are carrying. (not wearing) // "GIVE" ? { CItemContainer * pPack = GetPack(); if ( pPack ) { if ( pPack->GetCount() > 0 ) { pPack->ContentsDump( GetTopPoint(), ATTR_OWNED ); break; } } if ( NPC_CanSpeak()) { Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_CARRYNOTHING ) ); } return( true ); } break; case PC_DROP_ALL: DropAll( NULL, ATTR_OWNED ); break; case PC_FOLLOW: pTargPrompt = g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_TARG_FOLLOW ); break; case PC_FRIEND: pTargPrompt = g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_TARG_FRIEND ); break; case PC_GO: pTargPrompt = g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_TARG_GO ); fTargAllowGround = true; break; case PC_GUARD: pTargPrompt = g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_TARG_GUARD ); fMayBeCrime = true; break; case PC_KILL: goto do_attack; case PC_PRICE: if ( ! NPC_IsVendor()) return( false ); pTargPrompt = g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_SETPRICE ); break; case PC_SPEAK: NPC_OnPetCommand( true, pSrc ); return( true ); case PC_EQUIP: ItemEquipWeapon(false); ItemEquipArmor(false); break; case PC_STATUS: if ( NPC_CanSpeak() ) { CItemContainer * pBank = GetBank(); unsigned int iWage = pCharDef->GetHireDayWage(); TCHAR *pszMsg = Str_GetTemp(); if ( NPC_IsVendor() ) { CItemContainer * pCont = GetBank(LAYER_VENDOR_STOCK); TCHAR *pszTemp1 = Str_GetTemp(); TCHAR *pszTemp2 = Str_GetTemp(); TCHAR *pszTemp3 = Str_GetTemp(); if ( iWage ) { sprintf(pszTemp1, g_Cfg.GetDefaultMsg( DEFMSG_NPC_VENDOR_STAT_GOLD_1 ), pBank->m_itEqBankBox.m_Check_Amount); sprintf(pszTemp2, g_Cfg.GetDefaultMsg( DEFMSG_NPC_VENDOR_STAT_GOLD_2 ), pBank->m_itEqBankBox.m_Check_Amount / iWage); sprintf(pszTemp3, g_Cfg.GetDefaultMsg( DEFMSG_NPC_VENDOR_STAT_GOLD_3 ), static_cast<int>(pCont->GetCount()) ); } else { sprintf(pszTemp1, g_Cfg.GetDefaultMsg( DEFMSG_NPC_VENDOR_STAT_GOLD_1 ), pBank->m_itEqBankBox.m_Check_Amount ); sprintf(pszTemp2, g_Cfg.GetDefaultMsg( DEFMSG_NPC_VENDOR_STAT_GOLD_4 ), pBank->m_itEqBankBox.m_Check_Restock, pBank->GetTimerAdjusted() / 60); sprintf(pszTemp3, g_Cfg.GetDefaultMsg( DEFMSG_NPC_VENDOR_STAT_GOLD_3 ), static_cast<int>(pCont->GetCount()) ); } sprintf(pszMsg, "%s %s %s", pszTemp1, pszTemp2, pszTemp3); } else if ( iWage ) { sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_DAYS_LEFT), pBank->m_itEqBankBox.m_Check_Amount / iWage); } Speak(pszMsg); return true; } break; case PC_STAY: case PC_STOP: Skill_Start( NPCACT_STAY ); break; case PC_TRANSFER: pTargPrompt = g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_TARG_TRANSFER ); break; case PC_STOCK: // Magic restocking container. if ( !NPC_IsVendor() || !pSrc->IsClient() ) return false; Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_ITEMS_SELL ) ); pSrc->GetClient()->addBankOpen( this, LAYER_VENDOR_STOCK ); break; case PC_BOUGHT: if ( !NPC_IsVendor() || !pSrc->IsClient() ) return false; Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_ITEMS_BUY ) ); pSrc->GetClient()->addBankOpen( this, LAYER_VENDOR_EXTRA ); break; case PC_SAMPLES: if ( !NPC_IsVendor() || !pSrc->IsClient() ) return false; Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_ITEMS_SAMPLE ) ); pSrc->GetClient()->addBankOpen( this, LAYER_VENDOR_BUYS ); break; default: return( false ); } if ( pTargPrompt ) { pszCmd += strlen( sm_Pet_table[iCmd] ); GETNONWHITESPACE( pszCmd ); // I Need a target arg. if ( ! pSrc->IsClient()) return( false ); pSrc->m_pClient->m_tmPetCmd.m_iCmd = iCmd; pSrc->m_pClient->m_tmPetCmd.m_fAllPets = fAllPets; pSrc->m_pClient->m_Targ_UID = GetUID(); pSrc->m_pClient->m_Targ_Text = pszCmd; pSrc->m_pClient->addTarget( CLIMODE_TARG_PET_CMD, pTargPrompt, fTargAllowGround, fMayBeCrime ); return( true ); } // make some sound to confirm we heard it. // Make the yes noise. NPC_OnPetCommand( true, pSrc ); return( true ); }
bool CChar::Use_Repair( CItem * pItemArmor ) { ADDTOCALLSTACK("CChar::Use_Repair"); // Attempt to repair the item. // If it is repairable. if ( !pItemArmor || !pItemArmor->Armor_IsRepairable() ) { SysMessageDefault(DEFMSG_REPAIR_NOT); return false; } if ( pItemArmor->IsItemEquipped() ) { SysMessageDefault(DEFMSG_REPAIR_WORN); return false; } if ( !CanUse(pItemArmor, true) ) { SysMessageDefault(DEFMSG_REPAIR_REACH); return false; } // Quickly use arms lore skill, but don't gain any skill until later on int iArmsLoreDiff = Calc_GetRandVal(30); if ( !Skill_UseQuick(SKILL_ARMSLORE, iArmsLoreDiff, false) ) { // apply arms lore skillgain for failure Skill_Experience(SKILL_ARMSLORE, -iArmsLoreDiff); SysMessageDefault(DEFMSG_REPAIR_UNK); return false; } if ( pItemArmor->m_itArmor.m_Hits_Cur >= pItemArmor->m_itArmor.m_Hits_Max ) { SysMessageDefault(DEFMSG_REPAIR_FULL); return false; } m_Act_p = g_World.FindItemTypeNearby(GetTopPoint(), IT_ANVIL, 2, false, true); if ( !m_Act_p.IsValidPoint() ) { SysMessageDefault(DEFMSG_REPAIR_ANVIL); return false; } CItemBase *pItemDef = pItemArmor->Item_GetDef(); ASSERT(pItemDef); // Use up some raw materials to repair. int iTotalHits = pItemArmor->m_itArmor.m_Hits_Max; int iDamageHits = pItemArmor->m_itArmor.m_Hits_Max - pItemArmor->m_itArmor.m_Hits_Cur; int iDamagePercent = IMULDIV(100, iDamageHits, iTotalHits); size_t iMissing = ResourceConsumePart(&(pItemDef->m_BaseResources), 1, iDamagePercent / 2, true); if ( iMissing != pItemDef->m_BaseResources.BadIndex() ) { // Need this to repair. const CResourceDef *pCompDef = g_Cfg.ResourceGetDef(pItemDef->m_BaseResources.GetAt(iMissing).GetResourceID()); SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_REPAIR_LACK_1), pCompDef ? pCompDef->GetName() : g_Cfg.GetDefaultMsg(DEFMSG_REPAIR_LACK_2)); return false; } UpdateDir(m_Act_p); UpdateAnimate(ANIM_ATTACK_1H_SLASH); // quarter the skill to make it. // + more damaged items should be harder to repair. // higher the percentage damage the closer to the skills to make it. size_t iRes = pItemDef->m_SkillMake.FindResourceType(RES_SKILL); if ( iRes == pItemDef->m_SkillMake.BadIndex() ) return false; CResourceQty RetMainSkill = pItemDef->m_SkillMake[iRes]; int iSkillLevel = static_cast<int>(RetMainSkill.GetResQty()) / 10; int iDifficulty = IMULDIV(iSkillLevel, iDamagePercent, 100); if ( iDifficulty < iSkillLevel / 4 ) iDifficulty = iSkillLevel / 4; // apply arms lore skillgain now LPCTSTR pszText; Skill_Experience(SKILL_ARMSLORE, iArmsLoreDiff); bool fSuccess = Skill_UseQuick(static_cast<SKILL_TYPE>(RetMainSkill.GetResIndex()), iDifficulty); if ( fSuccess ) { pItemArmor->m_itArmor.m_Hits_Cur = static_cast<WORD>(iTotalHits); pszText = g_Cfg.GetDefaultMsg(DEFMSG_REPAIR_1); } else { /***************************** // not sure if this is working! ******************************/ // Failure if ( !Calc_GetRandVal(6) ) { pszText = g_Cfg.GetDefaultMsg(DEFMSG_REPAIR_2); pItemArmor->m_itArmor.m_Hits_Max--; pItemArmor->m_itArmor.m_Hits_Cur--; } else if ( !Calc_GetRandVal(3) ) { pszText = g_Cfg.GetDefaultMsg(DEFMSG_REPAIR_3); pItemArmor->m_itArmor.m_Hits_Cur--; } else pszText = g_Cfg.GetDefaultMsg( DEFMSG_REPAIR_4 ); iDamagePercent = Calc_GetRandVal(iDamagePercent); // some random amount } ResourceConsumePart(&(pItemDef->m_BaseResources), 1, iDamagePercent / 2, false); if ( pItemArmor->m_itArmor.m_Hits_Cur <= 0 ) pszText = g_Cfg.GetDefaultMsg(DEFMSG_REPAIR_5); TCHAR *pszMsg = Str_GetTemp(); sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_REPAIR_MSG), pszText, pItemArmor->GetName()); Emote(pszMsg); if ( pItemArmor->m_itArmor.m_Hits_Cur <= 0 ) pItemArmor->Delete(); else pItemArmor->UpdatePropertyFlag(AUTOTOOLTIP_FLAG_DURABILITY); return fSuccess; }
CChar * CChar::Use_Figurine( CItem * pItem, bool bCheckFollowerSlots ) { ADDTOCALLSTACK("CChar::Use_Figurine"); // NOTE: The figurine is NOT destroyed. bool bCreatedNewNpc = false; if ( !pItem ) return NULL; if ( pItem->m_uidLink.IsValidUID() && pItem->m_uidLink.IsChar() && pItem->m_uidLink != GetUID() && !IsPriv(PRIV_GM) ) { SysMessageDefault(DEFMSG_MSG_FIGURINE_NOTYOURS); return NULL; } // Create a new NPC if there's no one linked to this figurine CChar *pPet = pItem->m_itFigurine.m_UID.CharFind(); if ( !pPet ) { CREID_TYPE id = pItem->m_itFigurine.m_ID; if ( !id ) { id = CItemBase::FindCharTrack(pItem->GetID()); if ( !id ) { DEBUG_ERR(("FIGURINE id 0%x, no creature\n", pItem->GetDispID())); return NULL; } } bCreatedNewNpc = true; pPet = CreateNPC(id); ASSERT(pPet); pPet->SetName(pItem->GetName()); if ( pItem->GetHue() ) { pPet->m_prev_Hue = pItem->GetHue(); pPet->SetHue(pItem->GetHue()); } } if ( bCheckFollowerSlots && IsSetOF(OF_PetSlots) ) { if ( !FollowersUpdate(pPet, static_cast<short>(maximum(1, pPet->GetDefNum("FOLLOWERSLOTS", true))), true) ) { SysMessageDefault(DEFMSG_PETSLOTS_TRY_CONTROL); if ( bCreatedNewNpc ) pPet->Delete(); return NULL; } } if ( pPet->IsDisconnected() ) pPet->StatFlag_Clear(STATF_Ridden); // pull the creature out of IDLE space pItem->m_itFigurine.m_UID.InitUID(); pPet->m_dirFace = m_dirFace; pPet->NPC_PetSetOwner(this); pPet->MoveToChar(pItem->GetTopLevelObj()->GetTopPoint()); pPet->Update(); pPet->Skill_Start(SKILL_NONE); pPet->SoundChar(CRESND_RAND1); return pPet; }
bool CChar::Use_Drink( CItem * pItem ) { ADDTOCALLSTACK("CChar::Use_Drink"); // IT_POTION: // IT_DRINK: // IT_PITCHER: // IT_WATER_WASH: // IT_BOOZE: if ( !CanMove(pItem) ) { SysMessageDefault(DEFMSG_DRINK_CANTMOVE); return false; } const CItemBase *pItemDef = pItem->Item_GetDef(); ITEMID_TYPE idbottle = static_cast<ITEMID_TYPE>(RES_GET_INDEX(pItemDef->m_ttDrink.m_idEmpty)); if ( pItem->IsType(IT_BOOZE) ) { // Beer wine and liquor. vary strength of effect. int iAlcohol = Calc_GetRandVal(4); CItem *pDrunkLayer = LayerFind(LAYER_FLAG_Drunk); if ( !pDrunkLayer ) pDrunkLayer = Spell_Effect_Create(SPELL_Liquor, LAYER_FLAG_Drunk, 0, 5 * TICK_PER_SEC, this); pDrunkLayer->m_itSpell.m_spellcharges += iAlcohol; if ( pDrunkLayer->m_itSpell.m_spellcharges > 60 ) pDrunkLayer->m_itSpell.m_spellcharges = 60; } if ( pItem->IsType(IT_POTION) ) { // Time limit on using potions. if ( LayerFind(LAYER_FLAG_PotionUsed) ) { SysMessageDefault(DEFMSG_DRINK_POTION_DELAY); return false; } // Convey the effect of the potion. int iSkillQuality = pItem->m_itPotion.m_skillquality; if ( g_Cfg.m_iFeatureAOS & FEATURE_AOS_UPDATE_B ) { int iEnhance = static_cast<int>(GetDefNum("EnhancePotions")); if ( iEnhance ) iSkillQuality += IMULDIV(iSkillQuality, iEnhance, 100); } OnSpellEffect(static_cast<SPELL_TYPE>(RES_GET_INDEX(pItem->m_itPotion.m_Type)), this, iSkillQuality, pItem); // Give me the marker that i've used a potion. Spell_Effect_Create(SPELL_NONE, LAYER_FLAG_PotionUsed, iSkillQuality, 15 * TICK_PER_SEC, this); } if ( pItem->IsType(IT_DRINK) && IsSetOF(OF_DrinkIsFood) ) { short iRestore = 0; if ( pItem->m_itDrink.m_foodval ) iRestore = static_cast<short>(pItem->m_itDrink.m_foodval); else iRestore = static_cast<short>(pItem->Item_GetDef()->GetVolume()); if ( iRestore < 1 ) iRestore = 1; if ( Stat_GetVal(STAT_FOOD) >= Stat_GetMax(STAT_FOOD) ) { SysMessageDefault(DEFMSG_DRINK_FULL); return false; } Stat_SetVal(STAT_FOOD, Stat_GetVal(STAT_FOOD) + iRestore); if ( pItem->m_itFood.m_poison_skill ) SetPoison(pItem->m_itFood.m_poison_skill * 10, 1 + (pItem->m_itFood.m_poison_skill / 50), this); } //Sound(sm_DrinkSounds[Calc_GetRandVal(COUNTOF(sm_DrinkSounds))]); UpdateAnimate(ANIM_EAT); pItem->ConsumeAmount(); // Create the empty bottle ? if ( idbottle != ITEMID_NOTHING ) ItemBounce(CItem::CreateScript(idbottle, this), false); return true; }
bool CChar::Use_Key( CItem * pKey, CItem * pItemTarg ) { ADDTOCALLSTACK("CChar::Use_Key"); ASSERT(pKey); ASSERT(pKey->IsType(IT_KEY)); if ( !pItemTarg ) { SysMessageDefault(DEFMSG_MSG_KEY_TARG); return false; } if ( pKey != pItemTarg && pItemTarg->IsType(IT_KEY) ) { // We are trying to copy a key ? if ( !CanUse(pItemTarg, true) ) { SysMessageDefault(DEFMSG_MSG_KEY_TARG_REACH); return false; } if ( !pKey->m_itKey.m_lockUID && !pItemTarg->m_itKey.m_lockUID ) { SysMessageDefault(DEFMSG_MSG_KEY_BLANKS); return false; } if ( pItemTarg->m_itKey.m_lockUID && pKey->m_itKey.m_lockUID ) { SysMessageDefault(DEFMSG_MSG_KEY_NOTBLANKS); return false; } // Need tinkering tools ??? if ( !Skill_UseQuick(SKILL_TINKERING, 30 + Calc_GetRandLLVal(40)) ) { SysMessageDefault(DEFMSG_MSG_KEY_FAILC); return false; } if ( pItemTarg->m_itKey.m_lockUID ) pKey->m_itKey.m_lockUID = pItemTarg->m_itKey.m_lockUID; else pItemTarg->m_itKey.m_lockUID = pKey->m_itKey.m_lockUID; return true; } if ( !pKey->m_itKey.m_lockUID ) { SysMessageDefault(DEFMSG_MSG_KEY_ISBLANK); return false; } if ( pKey == pItemTarg ) // rename the key { if ( m_pClient ) m_pClient->addPromptConsole(CLIMODE_PROMPT_NAME_KEY, g_Cfg.GetDefaultMsg(DEFMSG_MSG_KEY_SETNAME), pKey->GetUID()); return false; } if ( !CanUse(pItemTarg, false) ) { SysMessageDefault(DEFMSG_MSG_KEY_CANTREACH); return false; } if ( m_pArea->GetResourceID() == pKey->m_itKey.m_lockUID ) { if ( Use_MultiLockDown(pItemTarg) ) return true; } if ( !pItemTarg->m_itContainer.m_lockUID ) // or m_itContainer.m_lockUID { SysMessageDefault(DEFMSG_MSG_KEY_NOLOCK); return false; } if ( !pKey->IsKeyLockFit(pItemTarg->m_itContainer.m_lockUID) ) // or m_itKey { SysMessageDefault(DEFMSG_MSG_KEY_WRONGLOCK); return false; } return Use_KeyChange(pItemTarg); }
void CChat::DeleteChannel(CChatChannel * pChannel) { ADDTOCALLSTACK("CChat::DeleteChannel"); SendDeleteChannel(pChannel); // tell everyone about it first. delete pChannel; }
bool CChar::Use_KeyChange( CItem * pItemTarg ) { ADDTOCALLSTACK("CChar::Use_KeyChange"); // Lock or unlock the item. switch ( pItemTarg->GetType() ) { case IT_SIGN_GUMP: // We may rename the sign. if ( m_pClient ) m_pClient->addPromptConsole(CLIMODE_PROMPT_NAME_SIGN, g_Cfg.GetDefaultMsg(DEFMSG_MSG_KEY_TARG_SIGN), pItemTarg->GetUID()); return true; case IT_CONTAINER: pItemTarg->SetType(IT_CONTAINER_LOCKED); SysMessageDefault(DEFMSG_MSG_KEY_TARG_CONT_LOCK); break; case IT_CONTAINER_LOCKED: pItemTarg->SetType(IT_CONTAINER); SysMessageDefault(DEFMSG_MSG_KEY_TARG_CONT_ULOCK); break; case IT_SHIP_HOLD: pItemTarg->SetType(IT_SHIP_HOLD_LOCK); SysMessageDefault(DEFMSG_MSG_KEY_TARG_HOLD_LOCK); break; case IT_SHIP_HOLD_LOCK: pItemTarg->SetType(IT_SHIP_HOLD); SysMessageDefault(DEFMSG_MSG_KEY_TARG_HOLD_ULOCK); break; case IT_DOOR: case IT_DOOR_OPEN: pItemTarg->SetType(IT_DOOR_LOCKED); SysMessageDefault(DEFMSG_MSG_KEY_TARG_DOOR_LOCK); break; case IT_DOOR_LOCKED: pItemTarg->SetType(IT_DOOR); SysMessageDefault(DEFMSG_MSG_KEY_TARG_DOOR_ULOCK); break; case IT_SHIP_TILLER: if ( m_pClient ) m_pClient->addPromptConsole(CLIMODE_PROMPT_NAME_SHIP, g_Cfg.GetDefaultMsg(DEFMSG_MSG_SHIPNAME_PROMT), pItemTarg->GetUID()); return true; case IT_SHIP_PLANK: pItemTarg->Ship_Plank(false); // just close it. if ( pItemTarg->GetType() == IT_SHIP_SIDE_LOCKED ) { pItemTarg->SetType(IT_SHIP_SIDE); SysMessageDefault(DEFMSG_MSG_KEY_TARG_SHIP_ULOCK); break; } // Then fall thru and lock it. case IT_SHIP_SIDE: pItemTarg->SetType(IT_SHIP_SIDE_LOCKED); SysMessageDefault(DEFMSG_MSG_KEY_TARG_SHIP_LOCK); break; case IT_SHIP_SIDE_LOCKED: pItemTarg->SetType(IT_SHIP_SIDE); SysMessageDefault(DEFMSG_MSG_KEY_TARG_SHIP_ULOCK); break; default: SysMessageDefault(DEFMSG_MSG_KEY_TARG_NOLOCK); return false; } return true; }
void CChat::EventMsg( CClient * pClient, const nchar * pszText, int len, CLanguageID lang ) // Text from a client { ADDTOCALLSTACK("CChat::EventMsg"); // ARGS: // len = length of the pszText string in nchar's. // CChatChanMember * pMe = pClient; ASSERT(pMe); // newer clients do not send the 'chat button' packet, leading to all kinds of problems // with the client not being initialised properly for chat (e.g. blank name and exceptions // when leaving a chat room) - if chat is not active then we must simulate the chat button // event before processing the chat message if (pMe->IsChatActive() == false) { // simulate the chat button being clicked pClient->Event_ChatButton(nullptr); // if chat isn't active now then cancel processing the event if (pMe->IsChatActive() == false) return; } CChatChannel * pChannel = pMe->GetChannel(); tchar szText[MAX_TALK_BUFFER * 2]; CvtNUNICODEToSystem( szText, sizeof(szText), pszText, len ); // The 1st character is a command byte, join channel, private message someone, etc etc tchar * szMsg = szText+1; switch ( szText[0] ) { case 'a': // a = client typed a plain message in the text entry area { // Check for a chat command here if (szMsg[0] == '/') { DoCommand(pMe, szMsg + 1); break; } if (!pChannel) { not_in_a_channel: pMe->SendChatMsg(CHATMSG_MustBeInAConference); return; } // Not a chat command, must be speech pChannel->MemberTalk(pMe, szMsg, lang); break; }; case 'A': // A = change the channel password { if (!pChannel) goto not_in_a_channel; pChannel->ChangePassword(pMe, szMsg); break; }; case 'b': // b = client joining an existing channel { // Look for second double quote to separate channel from password size_t i = 1; for (; szMsg[i] != '\0'; i++) if (szMsg[i] == '"') break; szMsg[i] = '\0'; tchar * pszPassword = szMsg + i + 1; if (pszPassword[0] == ' ') // skip leading space if any pszPassword++; JoinChannel( pMe, szMsg + 1, pszPassword); break; }; case 'c': // c = client creating (and joining) new channel { tchar * pszPassword = nullptr; size_t iMsgLength = strlen(szMsg); for (size_t i = 0; i < iMsgLength; i++) { if (szMsg[i] == '{') // OK, there's a password here { szMsg[i] = 0; pszPassword = szMsg + i + 1; size_t iPasswordLength = strlen(pszPassword); for (i = 0; i < iPasswordLength; i++) { if (pszPassword[i] == '}') { pszPassword[i] = '\0'; break; } } break; } } CreateJoinChannel(pMe, szMsg, pszPassword); break; }; case 'd': // d = (/rename x) rename conference { if (!pChannel) goto not_in_a_channel; pMe->RenameChannel(szMsg); break; }; case 'e': // e = Send a private message to .... { if (!pChannel) goto not_in_a_channel; tchar buffer[2048]; strcpy(buffer, szMsg); // Separate the recipient from the message (look for a space) size_t i = 0; size_t bufferLength = strlen(buffer); for (; i < bufferLength; i++) { if (buffer[i] == ' ') { buffer[i] = '\0'; break; } } pChannel->SendPrivateMessage(pMe, buffer, buffer+i+1); break; }; case 'f': // f = (+ignore) ignore this person { pMe->Ignore(szMsg); break; }; case 'g': // g = (-ignore) don't ignore this person { pMe->DontIgnore(szMsg); break; }; case 'h': // h = toggle ignoring this person { pMe->ToggleIgnore(szMsg); break; }; case 'i': // i = grant speaking privs to this person { if (!pChannel) goto not_in_a_channel; pChannel->GrantVoice(pMe, szMsg); break; }; case 'j': // j = remove speaking privs from this person { if (!pChannel) goto not_in_a_channel; pChannel->RevokeVoice(pMe, szMsg); break; }; case 'k': // k = (/voice) toggle voice status { if (!pChannel) goto not_in_a_channel; pChannel->ToggleVoice(pMe, szMsg); break; }; case 'l': // l = grant moderator status to this person { if (!pChannel) goto not_in_a_channel; pChannel->GrantModerator(pMe, szMsg); break; }; case 'm': // m = remove moderator status from this person { if (!pChannel) goto not_in_a_channel; pChannel->RevokeModerator(pMe, szMsg); break; }; case 'n': // m = toggle the moderator status for this person { if (!pChannel) goto not_in_a_channel; pChannel->ToggleModerator(pMe, szMsg); break; } case 'o': // o = turn on receiving private messages { pMe->SetReceiving(true); break; } case 'p': // p = turn off receiving private messages { pMe->SetReceiving(false); break; } case 'q': // q = toggle receiving messages { pMe->ToggleReceiving(); break; }; case 'r': // r = (+showname) turn on showing character name { pMe->PermitWhoIs(); break; }; case 's': // s = (-showname) turn off showing character name { pMe->ForbidWhoIs(); break; }; case 't': // t = toggle showing character name { pMe->ToggleWhoIs(); break; }; case 'u': // u = who is this player { if (!pChannel) goto not_in_a_channel; pChannel->WhoIs(pMe->GetChatName(), szMsg); break; }; case 'v': // v = kick this person out of the conference { if (!pChannel) goto not_in_a_channel; CChatChanMember * pMember = pChannel->FindMember(szMsg); if (!pMember) { pMe->SendChatMsg(CHATMSG_NoPlayer, szMsg); break; } pChannel->KickMember(pMe, pMember); // If noone is left, tell the chat system to // delete it from memory (you can kick yourself) if (pChannel->m_Members.size() <= 0) // Kicked self { DeleteChannel(pChannel); } break; }; case 'X': // X = client quit chat QuitChat(pClient); break; case 'w': // w = (+defaultvoice) make moderators be the only ones with a voice by default if (!pChannel) goto not_in_a_channel; pChannel->DisableVoiceDefault(pMe->GetChatName()); break; case 'x': // x = (-defaultvoice) give everyone a voice by default if (!pChannel) goto not_in_a_channel; pChannel->EnableVoiceDefault(pMe->GetChatName()); break; case 'y': // y = (/defaultvoice) toggle if (!pChannel) goto not_in_a_channel; pChannel->ToggleVoiceDefault(pMe->GetChatName()); break; case 'z': // z = emote if (!pChannel) goto not_in_a_channel; pChannel->Emote(pMe->GetChatName(), szMsg, lang ); break; }; }
bool CChar::Use_Seed( CItem * pSeed, CPointMap * pPoint ) { ADDTOCALLSTACK("CChar::Use_Seed"); // Use the seed at the current point on the ground or some new point that i can touch. // IT_SEED from IT_FRUIT ASSERT(pSeed); CPointMap pt; if ( pPoint ) pt = *pPoint; else if ( pSeed->IsTopLevel() ) pt = pSeed->GetTopPoint(); else pt = GetTopPoint(); if ( !CanTouch(pt) ) { SysMessageDefault(DEFMSG_MSG_SEED_REACH); return false; } // is there soil here ? IT_DIRT if ( !IsPriv(PRIV_GM) && !g_World.IsItemTypeNear(pt, IT_DIRT, 0, false, true) ) { SysMessageDefault(DEFMSG_MSG_SEED_TARGSOIL); return(false); } const CItemBase *pItemDef = pSeed->Item_GetDef(); ITEMID_TYPE idReset = static_cast<ITEMID_TYPE>(RES_GET_INDEX(pItemDef->m_ttFruit.m_idReset)); if ( idReset == 0 ) { SysMessageDefault(DEFMSG_MSG_SEED_NOGOOD); return false; } // Already a plant here ? CWorldSearch AreaItems(pt); for (;;) { CItem *pItem = AreaItems.GetItem(); if ( !pItem ) break; if ( pItem->IsType(IT_TREE) || pItem->IsType(IT_FOLIAGE) ) // there's already a tree here { SysMessageDefault(DEFMSG_MSG_SEED_ATREE); return false; } if ( pItem->IsType(IT_CROPS) ) // there's already a plant here pItem->Delete(); } // plant it and consume the seed. CItem *pPlant = CItem::CreateScript(idReset, this); ASSERT(pPlant); pPlant->MoveToUpdate(pt); if ( pPlant->IsType(IT_CROPS) || pPlant->IsType(IT_FOLIAGE) ) { pPlant->m_itCrop.m_ReapFruitID = pSeed->GetID(); pPlant->Plant_CropReset(); } else { pPlant->SetDecayTime(10 * g_Cfg.m_iDecay_Item); } pSeed->ConsumeAmount(); return true; }
DWORD CItemVendable::GetBasePrice() const { ADDTOCALLSTACK("CItemVendable::GetBasePrice"); // Get the price that the player set on his vendor return m_price; }
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; }