void CItemSpawn::DelObj( CGrayUID uid ) { ADDTOCALLSTACK("CitemSpawn:DelObj"); if ( !uid.IsValidUID() ) return; for ( unsigned char i = 0; i < GetCount(); i++ ) { if ( m_obj[i].IsValidUID() && m_obj[i] == uid ) // found this uid, proceeding to clear it { if (GetType() == IT_SPAWN_CHAR) // IT_SPAWN_ITEM uses 'more2' to store how much items to spawn at once, so we must not touch it. m_itSpawnChar.m_current--; // found this UID in the spawn's list, decreasing CChar's count only in this case while ( m_obj[i + 1].IsValidUID() ) // searching for any entry higher than this one... { m_obj[i] = m_obj[i + 1]; // and moving it 1 position to keep values 'together'. i++; } m_obj[i].InitUID(); // Finished moving higher entries (if any) so we free the last entry. break; } } if (uid.ItemFind()) uid.ItemFind()->m_uidSpawnItem.InitUID(); else if (uid.CharFind()) { uid.CharFind()->m_uidSpawnItem.InitUID(); uid.CharFind()->StatFlag_Clear(STATF_Spawned); } }
void CItemSpawn::AddObj( CGrayUID uid ) { ADDTOCALLSTACK("CitemSpawn:AddObj"); unsigned char iMax = GetAmount() > 0 ? static_cast<unsigned char>(GetAmount()) : 1; bool bIsSpawnChar = GetType() == IT_SPAWN_CHAR; if (!uid) return; if ( bIsSpawnChar ) { if ( !uid.CharFind()->m_pNPC) // Only adding NPCs to IT_SPAWN_CHAR.. return; if ( uid.CharFind()->m_uidSpawnItem.ItemFind() ) //... if they doesn't have a SpawnItem already. return; } else if( !uid.ItemFind() ) // Only adding Items to IT_SPAWN_ITEM return; for ( unsigned char i = 0; i < iMax; i++ ) { if ( m_obj[i] == uid ) // Not adding me again return; if ( !m_obj[i].ObjFind() ) { m_obj[i] = uid; if (bIsSpawnChar) { m_itSpawnChar.m_current++; uid.CharFind()->StatFlag_Set(STATF_Spawned); } uid.ObjFind()->m_uidSpawnItem = GetUID(); break; } } }
void CItemSpawn::AddObj(CGrayUID uid) { ADDTOCALLSTACK("CitemSpawn:AddObj"); // NOTE: This function is also called when loading spawn items // on server startup. In this case, some objs UID still invalid // (not loaded yet) so just proceed without any checks. bool bIsSpawnChar = IsType(IT_SPAWN_CHAR); if ( !g_Serv.IsLoading() ) { if ( !uid.IsValidUID() ) return; if ( bIsSpawnChar ) // IT_SPAWN_CHAR can only spawn NPCs { CChar *pChar = uid.CharFind(); if ( !pChar || !pChar->m_pNPC ) return; } else if ( !uid.ItemFind() ) // IT_SPAWN_ITEM can only spawn items return; CItemSpawn *pPrevSpawn = static_cast<CItemSpawn*>(uid.ObjFind()->m_uidSpawnItem.ItemFind()); if ( pPrevSpawn ) { if ( pPrevSpawn == this ) // obj already linked to this spawn return; pPrevSpawn->DelObj(uid); // obj linked to other spawn, remove the link before proceed } } BYTE iMax = maximum(GetAmount(), 1); for (BYTE i = 0; i < iMax; i++ ) { if ( !m_obj[i].IsValidUID() ) { m_obj[i] = uid; m_currentSpawned++; // objects are linked to the spawn at each server start if ( !g_Serv.IsLoading() ) { uid.ObjFind()->m_uidSpawnItem = GetUID(); if ( bIsSpawnChar ) { CChar *pChar = uid.CharFind(); ASSERT(pChar->m_pNPC); pChar->StatFlag_Set(STATF_Spawned); pChar->m_ptHome = GetTopPoint(); pChar->m_pNPC->m_Home_Dist_Wander = static_cast<WORD>(m_itSpawnChar.m_DistMax); } } break; } } if ( !g_Serv.IsLoading() ) ResendTooltip(); }
void CItemStone::WeDeclarePeace(CGrayUID uid, bool fForcePeace) { ADDTOCALLSTACK("CItemStone::WeDeclarePeace"); CItemStone * pEnemyStone = dynamic_cast <CItemStone*>( uid.ItemFind()); if (!pEnemyStone) return; CStoneMember * pMember = GetMember(pEnemyStone); if ( ! pMember ) // No such member return; // Set my flags on the subject. if (!pMember->GetTheyDeclared() || fForcePeace) // If they're not at war with us, delete this record delete pMember; else pMember->SetWeDeclared(false); pEnemyStone->TheyDeclarePeace( this, fForcePeace ); }
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 ) { int iFound = 1; if ( pCont ) { //check for UID CGrayUID uidCont = static_cast<DWORD>(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; DWORD AmmoRender; 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()); AmmoHue = pVarAnimColor ? static_cast<DWORD>(pVarAnimColor->GetValNum()) : 0; AmmoRender = pVarAnimRender ? static_cast<DWORD>(pVarAnimRender->GetValNum()) : 0; pButte->Effect(EFFECT_BOLT, AmmoAnim, this, 16, 0, false, AmmoHue, AmmoRender); pButte->Sound(0x224); // 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 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; }
bool CItemStone::r_GetRef( LPCTSTR & pszKey, CScriptObj * & pRef ) { ADDTOCALLSTACK("CItemStone::r_GetRef"); if ( !strnicmp("member.", pszKey, 7) ) { pszKey = pszKey + 7; if ( !pszKey[0] ) return false; int nNumber = Exp_GetVal(pszKey); SKIP_SEPARATORS(pszKey); CStoneMember * pMember = STATIC_CAST <CStoneMember *>(GetHead()); for ( int i = 0; pMember != NULL; pMember = pMember->GetNext() ) { if ( !pMember->GetLinkUID().IsChar() ) continue; if ( nNumber == i ) { pRef = pMember; return true; } i++; } } else if ( !strnicmp("memberfromuid.", pszKey, 14) ) { pszKey = pszKey + 14; if ( !pszKey[0] ) return false; CGrayUID pMemberUid = static_cast<DWORD>(Exp_GetVal(pszKey)); SKIP_SEPARATORS(pszKey); CChar * pMemberChar = pMemberUid.CharFind(); if ( pMemberChar ) { CStoneMember * pMemberGuild = GetMember( pMemberChar ); if ( pMemberGuild ) { pRef = pMemberGuild; return true; } } } else if ( !strnicmp("guild.", pszKey, 6) ) { pszKey = pszKey + 6; if ( !pszKey[0] ) return false; int nNumber = Exp_GetVal(pszKey); SKIP_SEPARATORS(pszKey); CStoneMember * pMember = STATIC_CAST <CStoneMember *>(GetHead()); for ( int i = 0; pMember != NULL; pMember = pMember->GetNext() ) { if ( pMember->GetLinkUID().IsChar() ) continue; if ( nNumber == i ) { pRef = pMember; return true; } i++; } } else if ( !strnicmp("guildfromuid.", pszKey, 13) ) { pszKey = pszKey + 13; if ( !pszKey[0] ) return false; CGrayUID pGuildUid = static_cast<DWORD>(Exp_GetVal(pszKey)); SKIP_SEPARATORS(pszKey); CItem * pMemberGuild = pGuildUid.ItemFind(); if ( pMemberGuild ) { CStoneMember * pGuild = GetMember( pMemberGuild ); if ( pGuild ) { pRef = pGuild; return true; } } } return CItem::r_GetRef( pszKey, pRef ); }
bool CItemStone::r_Verb( CScript & s, CTextConsole * pSrc ) // Execute command from script { ADDTOCALLSTACK("CItemStone::r_Verb"); EXC_TRY("Verb"); // NOTE:: ONLY CALL this from CChar::r_Verb !!! // Little to no security checking here !!! ASSERT(pSrc); int index = FindTableSorted( s.GetKey(), sm_szVerbKeys, COUNTOF(sm_szVerbKeys)-1 ); if ( index < 0 ) { return( CItem::r_Verb( s, pSrc )); } CChar * pCharSrc = pSrc->GetChar(); CStoneMember * pMember = GetMember(pCharSrc); switch ( index ) { case ISV_ALLGUILDS: { if ( s.HasArgs() ) { TCHAR * pszArgs = s.GetArgRaw(); int iFlags = Exp_GetVal(pszArgs); SKIP_ARGSEP(pszArgs); if ( iFlags < 0 ) { g_Log.EventError("ItemStone::AllGuilds invalid parameter '%i'.\n", iFlags); return false; } else { if ( pszArgs[0] != '\0' ) { pMember = STATIC_CAST <CStoneMember *>(GetHead()); CScript scriptVerb( pszArgs ); for (; pMember != NULL; pMember = pMember->GetNext()) { if ( pMember->GetLinkUID().IsChar() ) continue; if ( !iFlags ) { pMember->r_Verb(scriptVerb, pSrc); } else if ( ( iFlags == 1 ) && ( pMember->GetWeDeclared() && !pMember->GetTheyDeclared() ) ) { pMember->r_Verb(scriptVerb, pSrc); } else if ( ( iFlags == 2 ) && ( !pMember->GetWeDeclared() && pMember->GetTheyDeclared() ) ) { pMember->r_Verb(scriptVerb, pSrc); } else if ( ( iFlags == 3 ) && ( pMember->GetWeDeclared() && pMember->GetTheyDeclared() ) ) { pMember->r_Verb(scriptVerb, pSrc); } } } else { g_Log.EventError("ItemStone::AllGuilds empty args.\n"); return false; } } } } break; case ISV_ALLMEMBERS: { if ( s.HasArgs() ) { TCHAR * pszArgs = s.GetArgRaw(); int iFlags = Exp_GetVal(pszArgs); SKIP_ARGSEP(pszArgs); if (( iFlags < -1 ) || ( iFlags > STONEPRIV_ACCEPTED )) { g_Log.EventError("ItemStone::AllMembers invalid parameter '%i'.\n", iFlags); return false; } else { if ( pszArgs[0] != '\0' ) { pMember = STATIC_CAST <CStoneMember *>(GetHead()); CScript scriptVerb( pszArgs ); for (; pMember != NULL; pMember = pMember->GetNext()) { if ( !pMember->GetLinkUID().IsChar() ) continue; if ( iFlags == -1 ) { pMember->r_Verb(scriptVerb, pSrc); } else if ( pMember->GetPriv() == static_cast<STONEPRIV_TYPE>(iFlags) ) { pMember->r_Verb(scriptVerb, pSrc); } } } else { g_Log.EventError("ItemStone::AllMembers empty args.\n"); return false; } } } } break; case ISV_APPLYTOJOIN: if ( s.HasArgs()) { CGrayUID pMemberUid = s.GetArgVal(); CChar * pMemberChar = pMemberUid.CharFind(); if ( pMemberChar ) { AddRecruit( pMemberChar, STONEPRIV_CANDIDATE ); } } break; case ISV_CHANGEALIGN: if ( s.HasArgs()) { SetAlignType(static_cast<STONEALIGN_TYPE>(s.GetArgVal())); TCHAR *pszMsg = Str_GetTemp(); sprintf(pszMsg, "%s is now a %s %s\n", static_cast<LPCTSTR>(GetName()), static_cast<LPCTSTR>(GetAlignName()), static_cast<LPCTSTR>(GetTypeName())); Speak(pszMsg); } break; case ISV_DECLAREPEACE: if ( s.HasArgs()) { CGrayUID pMemberUid = s.GetArgVal(); WeDeclarePeace(pMemberUid); } break; case ISV_DECLAREWAR: if ( s.HasArgs()) { CGrayUID pMemberUid = s.GetArgVal(); CItem * pEnemyItem = pMemberUid.ItemFind(); if ( pEnemyItem ) { CItemStone * pNewEnemy = dynamic_cast<CItemStone*>(pEnemyItem); if ( pNewEnemy ) { WeDeclareWar(pNewEnemy); } } } break; case ISV_ELECTMASTER: ElectMaster(); break; // Need to change FixWeirdness or rewrite how cstonemember guilds are handled. case ISV_INVITEWAR: { if ( s.HasArgs() ) { INT64 piCmd[2]; size_t iArgQty = Str_ParseCmds( s.GetArgStr(), piCmd, COUNTOF(piCmd)); if ( iArgQty == 2 ) { CGrayUID pGuildUid = static_cast<unsigned long>(piCmd[0]); bool bWeDeclared = (piCmd[1] != 0); CItem * pEnemyItem = pGuildUid.ItemFind(); if ( pEnemyItem && (pEnemyItem->IsType(IT_STONE_GUILD) || pEnemyItem->IsType(IT_STONE_TOWN)) ) { CStoneMember * pMemberGuild = GetMember( pEnemyItem ); if ( !pMemberGuild ) pMemberGuild = new CStoneMember(this, pGuildUid, STONEPRIV_ENEMY); if ( bWeDeclared ) pMemberGuild->SetWeDeclared(true); else pMemberGuild->SetTheyDeclared(true); } } } } break; case ISV_JOINASMEMBER: if ( s.HasArgs()) { CGrayUID pMemberUid = s.GetArgVal(); CChar * pMemberChar = pMemberUid.CharFind(); if ( pMemberChar ) { AddRecruit( pMemberChar, STONEPRIV_MEMBER ); } } break; case ISV_RESIGN: if ( s.HasArgs()) { CGrayUID pMemberUid = s.GetArgVal(); CChar * pMemberChar = pMemberUid.CharFind(); if ( pMemberChar ) { CStoneMember * pMemberGuild = GetMember( pMemberChar ); if ( pMemberGuild ) { delete pMemberGuild; } } } else { if ( pMember != NULL ) delete pMember; } break; case ISV_TOGGLEABBREVIATION: { CGrayUID pMemberUid = pMember->GetLinkUID(); if ( s.HasArgs() ) pMemberUid = s.GetArgVal(); CChar * pMemberChar = pMemberUid.CharFind(); if ( pMemberChar ) { CStoneMember * pMemberGuild = GetMember( pMemberChar ); if ( pMemberGuild ) { pMemberGuild->ToggleAbbrev(); pMemberChar->ResendTooltip(); } } } break; default: return( false ); } return true; EXC_CATCH; EXC_DEBUG_START; EXC_ADD_SCRIPTSRC; EXC_DEBUG_END; return false; }
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 iQty = 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 = (iQty > 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)); } } else { 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 idx = 0; idx < 4; ++idx ) { if ( !IsStrNumeric(ppArgs[idx]) ) { DEBUG_ERR(("Invalid AddBuff argument number %u\n", idx + 1)); return true; } iArgs[idx] = Exp_GetVal(ppArgs[idx]); } if ( (iArgs[0] < BI_START) || (iArgs[0] > BI_QTY) ) { DEBUG_ERR(("Invalid AddBuff icon ID\n")); break; } LPCTSTR Args[7]; size_t ArgsCount = 0; for ( int i = 0; i < 7; ++i ) { Args[i] = ppArgs[i + 4]; if ( Args[i] != NULL ) ArgsCount++; } addBuff(static_cast<BUFF_ICONS>(iArgs[0]), iArgs[1], iArgs[2], static_cast<WORD>(iArgs[3]), Args, ArgsCount); break; } case CV_REMOVEBUFF: { BUFF_ICONS IconId = static_cast<BUFF_ICONS>(s.GetArgVal()); if ( (IconId < BI_START) || (IconId > BI_QTY) ) { DEBUG_ERR(("Invalid RemoveBuff icon ID\n")); break; } removeBuff(IconId); break; } case CV_ADDCLILOC: // add cliloc in @ClientTooltip trigger { TCHAR *ppLocArgs[256]; size_t qty = Str_ParseCmds(s.GetArgRaw(), ppLocArgs, COUNTOF(ppLocArgs), ","); DWORD clilocid = Exp_GetVal(ppLocArgs[0]); CGString LocArgs; for ( size_t y = 1; y < qty; y++ ) { if ( LocArgs.GetLength() ) LocArgs += "\t"; LocArgs += (!strcmp(ppLocArgs[y], "NULL") ? " " : ppLocArgs[y]); } if ( g_Cfg.m_wDebugFlags & DEBUGF_SCRIPTS ) g_Log.EventDebug("SCRIPT: addcliloc(%lu,'%s')\n", clilocid, static_cast<LPCTSTR>(LocArgs)); m_TooltipData.Add(new CClientTooltip(clilocid, LocArgs)); break; } case CV_ADDCONTEXTENTRY: { TCHAR *ppLocArgs[20]; if ( Str_ParseCmds(s.GetArgRaw(), ppLocArgs, COUNTOF(ppLocArgs), ",") > 4 ) { DEBUG_ERR(("Bad AddContextEntry usage: Function takes maximum of 4 arguments!\n")); return true; } if ( m_pPopupPacket == NULL ) { 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(ppLocArgs[i]) ) continue; if ( !IsStrNumeric(ppLocArgs[i]) ) { DEBUG_ERR(("Bad AddContextEntry usage: Argument %d must be a number!\n", i + 1)); return true; } } int entrytag = Exp_GetVal(ppLocArgs[0]); if ( entrytag < 100 ) { DEBUG_ERR(("Bad AddContextEntry usage: TextEntry < 100 is reserved for server usage!\n")); return true; } m_pPopupPacket->addOption(static_cast<WORD>(entrytag), static_cast<DWORD>(Exp_GetVal(ppLocArgs[1])), static_cast<WORD>(Exp_GetVal(ppLocArgs[2])), static_cast<WORD>(Exp_GetVal(ppLocArgs[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])); #ifdef _ALPHASPHERE // todo: should use a proper container for these, since the arrows are lost // when the client logs out, and also newer clients support multiple arrows if ( piVal[0] && piVal[1] && m_pChar ) { m_pChar->SetKeyNum("ARROWQUEST_X", piVal[0]); m_pChar->SetKeyNum("ARROWQUEST_Y", piVal[1]); } else { m_pChar->DeleteKey("ARROWQUEST_X"); m_pChar->DeleteKey("ARROWQUEST_Y"); } #endif break; } case CV_BADSPAWN: { // Loop the world searching for bad spawns bool bFound = false; for ( int m = 0; (m < 256) && !bFound; m++ ) { if ( !g_MapList.m_maps[m] ) continue; for ( int d = 0; (d < g_MapList.GetSectorQty(m)) && !bFound; d++ ) { CSector *pSector = g_World.GetSector(m, d); if ( !pSector ) continue; CItem *pItem = static_cast<CItem *>(pSector->m_Items_Inert.GetHead()); for ( ; (pItem != NULL) && !bFound; pItem = pItem->GetNext() ) { if ( pItem->IsType(IT_SPAWN_ITEM) || pItem->IsType(IT_SPAWN_CHAR) ) { CItemSpawn *pSpawn = static_cast<CItemSpawn *>(pItem); CResourceDef *pDef = pSpawn->FixDef(); if ( !pDef ) { 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)); bFound = true; } } } } } if ( !bFound ) 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 skill; if ( !pSpellDef->GetPrimarySkill(&skill, 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>(skill)); break; } else Cmd_Skill_Magery(spell, pObjSrc); break; } case CV_CHARLIST: // usually just a gm command { 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: { CChar *pChar = m_pChar; if ( s.HasArgs() ) { CGrayUID uid = static_cast<CGrayUID>(s.GetArgVal()); pChar = uid.CharFind(); } if ( pChar ) closeUIWindow(pChar, 0x1); break; } case CV_CLOSEPROFILE: { CChar *pChar = m_pChar; if ( s.HasArgs() ) { CGrayUID uid = static_cast<CGrayUID>(s.GetArgVal()); pChar = uid.CharFind(); } if ( pChar ) closeUIWindow(pChar, 0x8); break; } case CV_CLOSESTATUS: { CChar *pChar = m_pChar; if ( s.HasArgs() ) { CGrayUID uid = static_cast<CGrayUID>(s.GetArgVal()); pChar = uid.CharFind(); } if ( pChar ) closeUIWindow(pChar, 0x2); break; } case CV_DYE: { if ( s.HasArgs() ) { CGrayUID uid = static_cast<CGrayUID>(s.GetArgVal()); CObjBase *pObj = uid.ObjFind(); 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 if ( !s.HasArgs() ) { SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_EXTRACT_USAGE)); } else { TCHAR *ppArgs[2]; Str_ParseCmds(s.GetArgStr(), ppArgs, COUNTOF(ppArgs)); 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 if ( !s.HasArgs() ) { SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_UNEXTRACT_USAGE)); } else { TCHAR *ppArgs[2]; Str_ParseCmds(s.GetArgStr(), ppArgs, COUNTOF(ppArgs)); 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_MENU: { Menu_Setup(g_Cfg.ResourceGetIDType(RES_MENU, s.GetArgStr())); break; } case CV_MIDILIST: { INT64 piMidi[64]; size_t iQty = Str_ParseCmds(s.GetArgStr(), piMidi, COUNTOF(piMidi)); if ( iQty > 0 ) addMusic(static_cast<MIDI_TYPE>(piMidi[Calc_GetRandVal(iQty)])); break; } case CV_NUDGE: { if ( !s.HasArgs() ) { SysMessage("Usage: NUDGE dx dy dz"); } else { 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: { CChar *pChar = m_pChar; if ( s.HasArgs() ) { CGrayUID uid = static_cast<CGrayUID>(s.GetArgVal()); pChar = uid.CharFind(); } if ( pChar ) addCharPaperdoll(pChar); break; } case CV_OPENTRADEWINDOW: { TCHAR *ppArgs[2]; Str_ParseCmds(s.GetArgStr(), ppArgs, COUNTOF(ppArgs)); CChar *pChar = NULL; CItem *pItem = NULL; if ( ppArgs[0] ) { CGrayUID uidChar = static_cast<CGrayUID>(Exp_GetVal(ppArgs[0])); pChar = uidChar.CharFind(); } if ( ppArgs[1] ) { CGrayUID uidItem = static_cast<CGrayUID>(Exp_GetVal(ppArgs[1])); pItem = uidItem.ItemFind(); } if ( pChar ) 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 pPrompt = g_Cfg.GetDefaultMsg(DEFMSG_SELECT_MAGIC_TARGET); if ( !pSpellDef->m_sTargetPrompt.IsEmpty() ) pPrompt = pSpellDef->m_sTargetPrompt; int SpellTimeout = static_cast<int>(GetDefNum("SPELLTIMEOUT")); if ( !SpellTimeout ) SpellTimeout = g_Cfg.m_iSpellTimeout * TICK_PER_SEC; addTarget(CLIMODE_TARG_SKILL_MAGERY, pPrompt, pSpellDef->IsSpellType(SPELLFLAG_TARG_XYZ), pSpellDef->IsSpellType(SPELLFLAG_HARM), SpellTimeout); 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 skill; if ( !pSpellDef->GetPrimarySkill(&skill, NULL) ) return false; m_pChar->Skill_Start(static_cast<SKILL_TYPE>(skill)); } } 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 *pszArgs[4]; size_t iArgQty = Str_ParseCmds(s.GetArgRaw(), pszArgs, COUNTOF(pszArgs)); 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; } //strip quotes if any if ( *pszArgs[0] == '"' ) pszArgs[0]++; for ( TCHAR *pEnd = pszArgs[0] + strlen(pszArgs[0]) - 1; pEnd >= pszArgs[0]; pEnd-- ) { if ( *pEnd == '"' ) { *pEnd = '\0'; break; } } SysMessagef(pszArgs[0], pszArgs[1], pszArgs[2] ? pszArgs[2] : 0, pszArgs[3] ? pszArgs[3] : 0); break; } case CV_SMSGU: case CV_SYSMESSAGEUA: { TCHAR *pszArgs[5]; size_t iArgQty = Str_ParseCmds(s.GetArgRaw(), pszArgs, COUNTOF(pszArgs)); 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), pszArgs[4], -1); addBarkUNICODE(szBuffer, NULL, static_cast<HUE_TYPE>(Exp_GetVal(pszArgs[0])), TALKMODE_SYSTEM, FONT_NORMAL, pszArgs[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 = -1; if ( ppArgs[0] ) hue = Exp_GetVal(ppArgs[0]); if ( hue == -1 ) hue = HUE_TEXT_DEF; DWORD iClilocId = Exp_GetVal(ppArgs[1]); CGString CArgs; for ( size_t i = 2; i < iArgQty; i++ ) { if ( CArgs.GetLength() ) CArgs += "\t"; CArgs += (!strcmp(ppArgs[i], "NULL") ? " " : ppArgs[i]); } addBarkLocalized(iClilocId, NULL, hue, TALKMODE_SYSTEM, FONT_NORMAL, CArgs.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 = -1; int affix = 0; if ( ppArgs[0] ) hue = Exp_GetVal(ppArgs[0]); if ( hue == -1 ) hue = HUE_TEXT_DEF; DWORD iClilocId = Exp_GetVal(ppArgs[1]); if ( ppArgs[2] ) affix = Exp_GetVal(ppArgs[2]); CGString CArgs; for ( size_t i = 4; i < iArgQty; i++ ) { if ( CArgs.GetLength() ) CArgs += "\t"; CArgs += (!strcmp(ppArgs[i], "NULL") ? " " : ppArgs[i]); } addBarkLocalizedEx(iClilocId, NULL, hue, TALKMODE_SYSTEM, FONT_NORMAL, static_cast<AFFIX_TYPE>(affix), ppArgs[3], CArgs.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"); } else { 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: // "SHOW 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) ) { //if ( !s.IsKeyHead("CTAG.", 5) && !s.IsKeyHead("CTAG0.", 6) ) // We don't want output related to CTAG // SysMessagef("%s = %s", s.GetKey(), static_cast<LPCTSTR>(sVal)); // feedback on what we just did. 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; }