CResourceDef * CItemSpawn::FixDef() { ADDTOCALLSTACK("CitemSpawn:FixDef"); // Get a proper RESOURCE_ID from the id provided. // RETURN: true = ok. RESOURCE_ID_BASE rid = ( IsType(IT_SPAWN_ITEM) ? m_itSpawnItem.m_ItemID : m_itSpawnChar.m_CharID ); if ( rid.GetResType() != RES_UNKNOWN ) { return STATIC_CAST <CResourceDef *>(g_Cfg.ResourceGetDef(rid)); } // No type info here !? if ( IsType(IT_SPAWN_ITEM)) { ITEMID_TYPE id = static_cast<ITEMID_TYPE>(rid.GetResIndex()); if ( id < ITEMID_TEMPLATE ) { return( TryItem( id ) ); } else { // try a template. rid = RESOURCE_ID( RES_TEMPLATE, id ); CResourceDef * pDef = g_Cfg.ResourceGetDef(rid); if ( pDef ) { m_itSpawnItem.m_ItemID = rid; return( STATIC_CAST <CResourceDef *>( pDef )); } //if fails return( TryItem( id ) ); } } else { CREID_TYPE id = static_cast<CREID_TYPE>(rid.GetResIndex()); if ( id < SPAWNTYPE_START ) { return( TryChar( id )); } else { // try a spawn group. rid = RESOURCE_ID( RES_SPAWN, id ); CResourceDef * pDef = g_Cfg.ResourceGetDef(rid); if ( pDef ) { m_itSpawnChar.m_CharID = rid; return( STATIC_CAST <CResourceDef *>( pDef )); } //if fails return( TryChar( id )); } } }
bool CClient::Cmd_Skill_Inscription() { ADDTOCALLSTACK("CClient::Cmd_Skill_Inscription"); // Select the scroll type to make. // iSelect = -1 = 1st setup. // iSelect = 0 = cancel // iSelect = x = execute the selection. // we should already be in inscription skill mode. ASSERT(m_pChar); CItem *pBlankScroll = m_pChar->ContentFind(RESOURCE_ID(RES_TYPEDEF, IT_SCROLL_BLANK)); if ( !pBlankScroll ) { SysMessageDefault(DEFMSG_INSCRIPTION_FAIL); return false; } if ( IsTrigUsed(TRIGGER_SKILLMENU) ) { CScriptTriggerArgs args("sm_inscription"); if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE ) return true; } return Cmd_Skill_Menu(g_Cfg.ResourceGetIDType(RES_SKILLMENU, "sm_inscription")); }
bool CContainer::ContentFindKeyFor( CItem * pLocked ) const { ADDTOCALLSTACK("CContainer::ContentFindKeyFor"); // Look for the key that fits this in my possesion. // TODO: Double check for pLocked->m_itContainer.m_lockUID working return( pLocked->m_itContainer.m_lockUID && (ContentFind( RESOURCE_ID( RES_TYPEDEF, IT_KEY ), pLocked->m_itContainer.m_lockUID ) != NULL) ); }
int CChar::Use_PlayMusic( CItem * pInstrument, int iDifficultyToPlay ) { ADDTOCALLSTACK("CChar::Use_PlayMusic"); // SKILL_ENTICEMENT, SKILL_MUSICIANSHIP, // ARGS: // iDifficultyToPlay = 0-100 // RETURN: // >=0 = success // -1 = too hard for u. // -2 = can't play. no instrument. if ( !pInstrument ) { pInstrument = ContentFind(RESOURCE_ID(RES_TYPEDEF, IT_MUSICAL), 0, 1); if ( !pInstrument ) { SysMessageDefault(DEFMSG_MUSICANSHIP_NOTOOL); return -2; } } bool fSuccess = Skill_UseQuick(SKILL_MUSICIANSHIP, iDifficultyToPlay, (Skill_GetActive() != SKILL_MUSICIANSHIP)); Sound(pInstrument->Use_Music(fSuccess)); if ( fSuccess ) return iDifficultyToPlay; // success // Skill gain for SKILL_MUSICIANSHIP failure will need to be triggered // manually, since Skill_UseQuick isn't going to do it for us in this case if ( Skill_GetActive() == SKILL_MUSICIANSHIP ) Skill_Experience(SKILL_MUSICIANSHIP, -iDifficultyToPlay); SysMessageDefault(DEFMSG_MUSICANSHIP_POOR); return -1; // fail }
CResourceDef *CItemSpawn::FixDef() { ADDTOCALLSTACK("CitemSpawn:FixDef"); RESOURCE_ID_BASE rid = (IsType(IT_SPAWN_ITEM) ? m_itSpawnItem.m_ItemID : m_itSpawnChar.m_CharID); if ( rid.GetResType() != RES_UNKNOWN ) return static_cast<CResourceDef *>(g_Cfg.ResourceGetDef(rid)); // No type info here !? if ( IsType(IT_SPAWN_CHAR) ) { CREID_TYPE id = static_cast<CREID_TYPE>(rid.GetResIndex()); if ( id < SPAWNTYPE_START ) return TryChar(id); // try a spawn group. rid = RESOURCE_ID(RES_SPAWN, id); CResourceDef *pDef = g_Cfg.ResourceGetDef(rid); if ( pDef ) { m_itSpawnChar.m_CharID = rid; return pDef; } return TryChar(id); } else { ITEMID_TYPE id = static_cast<ITEMID_TYPE>(rid.GetResIndex()); if ( id < ITEMID_TEMPLATE ) return TryItem(id); // try a template. rid = RESOURCE_ID(RES_TEMPLATE, id); CResourceDef *pDef = g_Cfg.ResourceGetDef(rid); if ( pDef ) { m_itSpawnItem.m_ItemID = rid; return pDef; } return TryItem(id); } }
inline CCharBase *CItemSpawn::TryChar(CREID_TYPE &id) { ADDTOCALLSTACK("CitemSpawn:TryChar"); CCharBase *pCharDef = CCharBase::FindCharBase(id); if ( pCharDef ) { m_itSpawnChar.m_CharID = RESOURCE_ID(RES_CHARDEF, id); return pCharDef; } return NULL; }
inline CItemBase *CItemSpawn::TryItem(ITEMID_TYPE &id) { ADDTOCALLSTACK("CitemSpawn:TryItem"); CItemBase *pItemDef = CItemBase::FindItemBase(id); if ( pItemDef ) { m_itSpawnItem.m_ItemID = RESOURCE_ID(RES_ITEMDEF, id); return pItemDef; } return NULL; }
CSkillDef::CSkillDef( SKILL_TYPE skill ) : CResourceLink( RESOURCE_ID( RES_SKILL, skill )) { m_StatPercent = 0; m_GainRadius = 0; m_dwFlags = 0; m_dwGroup = 0; memset(m_Stat, 0, sizeof(m_Stat)); memset(m_StatBonus, 0, sizeof(m_StatBonus)); m_AdvRate.Init(); }
CCharPlayer::CCharPlayer(CChar *pChar, CAccount *pAccount) : m_pAccount(pAccount) { m_wDeaths = m_wMurders = 0; m_speedMode = 0; m_pflag = 0; m_bKrToolbarEnabled = false; m_timeLastUsed.Init(); memset(m_SkillLock, 0, sizeof(m_SkillLock)); memset(m_StatLock, 0, sizeof(m_StatLock)); SetSkillClass(pChar, RESOURCE_ID(RES_SKILLCLASS)); }
bool CDialogDef::GumpSetup( int iPage, CClient * pClient, CObjBase * pObjSrc, LPCTSTR Arguments ) { ADDTOCALLSTACK("CDialogDef::GumpSetup"); CResourceLock s; m_iControls = 0; m_iTexts = 0; m_pObj = pObjSrc; m_iOriginX = 0; m_iOriginY = 0; m_iPage = static_cast<WORD>(iPage); m_bNoDispose = false; CScriptTriggerArgs Args(iPage, 0, pObjSrc); //DEBUG_ERR(("Args.m_s1_raw %s Args.m_s1 %s Arguments 0x%x\n",Args.m_s1_raw, Args.m_s1, Arguments)); Args.m_s1_raw = Args.m_s1 = Arguments; // read text first if ( g_Cfg.ResourceLock( s, RESOURCE_ID( RES_DIALOG, GetResourceID().GetResIndex(), RES_DIALOG_TEXT ) ) ) { while ( s.ReadKey()) { if ( m_iTexts >= (COUNTOF(m_sText) - 1) ) break; m_pObj->ParseText( s.GetKeyBuffer(), pClient->GetChar() ); m_sText[m_iTexts] = s.GetKey(); m_iTexts++; } } else { // no gump text? } // read the main dialog if ( !ResourceLock( s ) ) return false; if ( !s.ReadKey() ) // read the size. return( false ); // starting x,y location. INT64 iSizes[2]; TCHAR * pszBuf = s.GetKeyBuffer(); m_pObj->ParseText( pszBuf, pClient->GetChar() ); Str_ParseCmds( pszBuf, iSizes, COUNTOF(iSizes) ); m_x = static_cast<int>(iSizes[0]); m_y = static_cast<int>(iSizes[1]); if ( OnTriggerRunVal( s, TRIGRUN_SECTION_TRUE, pClient->GetChar(), &Args ) == TRIGRET_RET_TRUE ) return false; return true; }
bool CItemMessage::LoadSystemPages() { DEBUG_CHECK( IsBookSystem()); CResourceLock s; if ( ! g_Cfg.ResourceLock( s, m_itBook.m_ResID )) return false; int iPages = -1; while ( s.ReadKeyParse()) { switch ( FindTableSorted( s.GetKey(), sm_szLoadKeys, COUNTOF( sm_szLoadKeys )-1 )) { case CIC_AUTHOR: m_sAuthor = s.GetArgStr(); break; case CIC_PAGES: iPages = s.GetArgVal(); break; case CIC_TITLE: SetName( s.GetArgStr()); // Make sure the book is named. break; } } if ( iPages > 2*MAX_BOOK_PAGES || iPages < 0 ) return( false ); TCHAR szTemp[ 16*1024 ]; for ( int iPage=1; iPage<=iPages; iPage++ ) { if ( ! g_Cfg.ResourceLock( s, RESOURCE_ID( RES_BOOK, m_itBook.m_ResID.GetResIndex(), iPage ))) { break; } int iLen = 0; while (s.ReadKey()) { int iLenStr = strlen( s.GetKey()); if ( iLen + iLenStr >= sizeof( szTemp )) break; iLen += strcpylen( szTemp+iLen, s.GetKey()); szTemp[ iLen++ ] = '\t'; } szTemp[ --iLen ] = '\0'; AddPageText( szTemp ); } return( true ); }
bool CChar::NPC_OnHirePay( CChar * pCharSrc, CItemMemory * pMemory, CItem * pGold ) { ADDTOCALLSTACK("CChar::NPC_OnHirePay"); if ( !m_pNPC || !pCharSrc || !pMemory ) return false; CCharBase * pCharDef = Char_GetDef(); if ( IsStatFlag( STATF_Pet )) { if ( ! pMemory->IsMemoryTypes(MEMORY_IPET|MEMORY_FRIEND)) { Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_EMPLOYED ) ); return false; } } else { unsigned int iWage = pCharDef->GetHireDayWage(); if ( iWage <= 0 ) { Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_NOT_FOR_HIRE ) ); return false; } if ( pGold->GetAmount() < iWage ) { Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_NOT_ENOUGH ) ); return false; } // NOTO_TYPE ? if ( pMemory->IsMemoryTypes( MEMORY_FIGHT|MEMORY_HARMEDBY|MEMORY_IRRITATEDBY )) { Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_NOT_WORK ) ); return false; } // Put all my loot cash away. ContentConsume( RESOURCE_ID(RES_TYPEDEF,IT_GOLD), INT_MAX, false, 0 ); // Mark all my stuff ATTR_OWNED - i won't give it away. ContentAttrMod( ATTR_OWNED, true ); NPC_PetSetOwner( pCharSrc ); } pMemory->m_itEqMemory.m_Action = NPC_MEM_ACT_NONE; NPC_OnHirePayMore( pGold, true ); return true; }
CSpellDef::CSpellDef( SPELL_TYPE id ) : CResourceLink( RESOURCE_ID( RES_SPELL, id )) { m_dwFlags = SPELLFLAG_DISABLED; m_dwGroup = 0; m_sound = 0; m_idSpell = ITEMID_NOTHING; m_idScroll = ITEMID_NOTHING; m_idEffect = ITEMID_NOTHING; m_idLayer = LAYER_NONE; m_wManaUse = 0; m_wTithingUse = 0; m_CastTime.Init(); m_Interrupt.Init(); m_Interrupt.m_aiValues.SetCount( 1 ); m_Interrupt.m_aiValues[0] = 1000; }
int CContainer::ContentConsume( RESOURCE_ID_BASE rid, int amount, bool fTest, DWORD dwArg ) { ADDTOCALLSTACK("CContainer::ContentConsume"); // ARGS: // dwArg = a hack for ores. // RETURN: // 0 = all consumed ok. // # = number left to be consumed. (still required) if ( rid.GetResIndex() == 0 ) return( amount ); // from skills menus. CItem * pItemNext; for ( CItem* pItem=GetContentHead(); pItem!=NULL; pItem=pItemNext) { pItemNext = pItem->GetNext(); if ( pItem->IsResourceMatch( rid, dwArg )) { amount -= pItem->ConsumeAmount( amount, fTest ); if ( amount <= 0 ) break; } CItemContainer * pCont = dynamic_cast <CItemContainer*> (pItem); if ( pCont != NULL ) // this is a sub-container. { if ( rid == RESOURCE_ID(RES_TYPEDEF,IT_GOLD)) { if ( pCont->IsType(IT_CONTAINER_LOCKED)) continue; } else { if ( ! pCont->IsSearchable()) continue; } amount = pCont->ContentConsume( rid, amount, fTest, dwArg ); if ( amount <= 0 ) break; } } return( amount ); }
CItemVendable *CChar::NPC_FindVendableItem(CItemVendable *pVendItem, CItemContainer *pContBuy) // static { ADDTOCALLSTACK("CChar::NPC_FindVendableItem"); // Does the NPC want to buy this item? if ( !pVendItem || !pContBuy || !pVendItem->IsValidSaleItem(false) ) return NULL; CItem *pItemTest = pContBuy->ContentFind(RESOURCE_ID(RES_ITEMDEF, pVendItem->GetID())); if ( !pItemTest ) return NULL; CItemVendable *pItemSell = dynamic_cast<CItemVendable *>(pItemTest); if ( !pItemSell ) // the item is not vendable return NULL; if ( pVendItem->GetType() != pItemSell->GetType() ) // sanity check return NULL; return pItemSell; }
TRIGRET_TYPE CClient::Dialog_OnButton( RESOURCE_ID_BASE rid, DWORD dwButtonID, CObjBase * pObj, CDialogResponseArgs * pArgs ) { ADDTOCALLSTACK("CClient::Dialog_OnButton"); // one of the gump dialog buttons was pressed. if ( !pObj ) // object is gone ? return TRIGRET_ENDIF; CResourceLock s; if ( !g_Cfg.ResourceLock(s, RESOURCE_ID(RES_DIALOG, rid.GetResIndex(), RES_DIALOG_BUTTON)) ) return TRIGRET_ENDIF; INT64 piCmd[3]; while ( s.ReadKeyParse()) { if ( ! s.IsKeyHead( "ON", 2 )) continue; size_t iArgs = Str_ParseCmds( s.GetArgStr(), piCmd, COUNTOF(piCmd) ); if ( iArgs == 0 ) continue; if ( iArgs == 1 ) { // single button value if ( (DWORD)piCmd[0] != dwButtonID ) continue; } else { // range of button values if ( dwButtonID < (DWORD)piCmd[0] || dwButtonID > (DWORD)piCmd[1] ) continue; } pArgs->m_iN1 = dwButtonID; return pObj->OnTriggerRunVal( s, TRIGRUN_SECTION_TRUE, m_pChar, pArgs ); } return( TRIGRET_ENDIF ); }
RESOURCE_ID CResourceBase::ResourceGetID( RES_TYPE restype, LPCTSTR & pszName ) { ADDTOCALLSTACK("CResourceBase::ResourceGetID"); // Find the Resource ID given this name. // We are NOT creating a new resource. just looking up an existing one // NOTE: Do not enforce the restype. // Just fill it in if we are not sure what the type is. // NOTE: // Some restype's have private name spaces. (ie. RES_AREA) // RETURN: // pszName is now set to be after the expression. // We are NOT creating. RESOURCE_ID rid; // Try to handle private name spaces. switch ( restype ) { case RES_ACCOUNT: case RES_AREA: case RES_GMPAGE: case RES_ROOM: case RES_SECTOR: break; default: break; } rid.SetPrivateUID( Exp_GetVal(pszName)); // May be some complex expression {} if ( restype != RES_UNKNOWN && rid.GetResType() == RES_UNKNOWN ) { // Label it with the type we want. return RESOURCE_ID( restype, rid.GetResIndex()); } return( rid ); }
FOG_MERGE(0), OMOD(SQ_ALU_OMOD_OFF), ALU_INST(SQ_OP2_INST_KILLNE), BANK_SWIZZLE(SQ_ALU_VEC_012), DST_GPR(0), DST_REL(ABSOLUTE), DST_ELEM(ELEM_X), CLAMP(0)), #endif /* TEX INST 0 */ TEX_DWORD0(TEX_INST(SQ_TEX_INST_SAMPLE), BC_FRAC_MODE(0), FETCH_WHOLE_QUAD(0), RESOURCE_ID(0), SRC_GPR(0), SRC_REL(ABSOLUTE), R7xx_ALT_CONST(0)), TEX_DWORD1(DST_GPR(0), DST_REL(ABSOLUTE), DST_SEL_X(SQ_SEL_X), /* R */ DST_SEL_Y(SQ_SEL_Y), /* G */ DST_SEL_Z(SQ_SEL_Z), /* B */ DST_SEL_W(SQ_SEL_W), /* A */ LOD_BIAS(0), COORD_TYPE_X(TEX_UNNORMALIZED), COORD_TYPE_Y(TEX_UNNORMALIZED), COORD_TYPE_Z(TEX_UNNORMALIZED), COORD_TYPE_W(TEX_UNNORMALIZED)), TEX_DWORD2(OFFSET_X(0),
CResourceDef * CItem::Spawn_FixDef() { // Get a proper RESOURCE_ID from the id provided. // RETURN: true = ok. RESOURCE_ID_BASE rid; if ( IsType(IT_SPAWN_ITEM)) { rid = m_itSpawnItem.m_ItemID; } else { ASSERT( IsType(IT_SPAWN_CHAR) ); rid = m_itSpawnChar.m_CharID; } if ( rid.GetResType() != RES_UNKNOWN ) { return STATIC_CAST <CResourceDef *>( g_Cfg.ResourceGetDef(rid)); } // No type info here !? if ( IsType(IT_SPAWN_ITEM)) { ITEMID_TYPE id = (ITEMID_TYPE) rid.GetResIndex(); if ( id < ITEMID_TEMPLATE ) { why_not_try_this_item: CItemBase * pItemDef = CItemBase::FindItemBase( id ); if ( pItemDef ) { m_itSpawnItem.m_ItemID = RESOURCE_ID( RES_ITEMDEF, id ); return( pItemDef ); } } else { // try a template. rid = RESOURCE_ID( RES_TEMPLATE, id ); CResourceDef * pDef = g_Cfg.ResourceGetDef(rid); if ( pDef ) { m_itSpawnItem.m_ItemID = rid; return( STATIC_CAST <CResourceDef *>( pDef )); } goto why_not_try_this_item; } } else { CREID_TYPE id = (CREID_TYPE) rid.GetResIndex(); if ( id < SPAWNTYPE_START ) { why_not_try_this_char: CCharBase * pCharDef = CCharBase::FindCharBase( id ); if ( pCharDef ) { m_itSpawnChar.m_CharID = RESOURCE_ID( RES_CHARDEF, id ); return( pCharDef ); } } else { // try a spawn group. rid = RESOURCE_ID( RES_SPAWN, id ); CResourceDef * pDef = g_Cfg.ResourceGetDef(rid); if ( pDef ) { m_itSpawnChar.m_CharID = rid; return( STATIC_CAST <CResourceDef *>( pDef )); } goto why_not_try_this_char; } } return( NULL ); }
bool CClient::Cmd_Use_Item( CItem * pItem, bool fTestTouch, bool fScript ) { ADDTOCALLSTACK("CClient::Cmd_Use_Item"); // Assume we can see the target. // called from Event_DoubleClick if ( pItem == NULL ) return false; if (pItem->m_Can & CAN_I_FORCEDC) fTestTouch = false; if ( fTestTouch ) { if( !fScript ) { CItemContainer * container = (dynamic_cast <CItemContainer*>(pItem->GetParent())); if( container != NULL ) { // protect from ,snoop - disallow picking from not opened containers bool isInOpenedContainer = false; IT_TYPE type = container->GetType(); if ( type == IT_EQ_TRADE_WINDOW) { isInOpenedContainer = true; } else { CClient::OpenedContainerMap_t::iterator itContainerFound = m_openedContainers.find( container->GetUID().GetPrivateUID() ); if ( itContainerFound != m_openedContainers.end() ) { DWORD dwTopContainerUID = (((*itContainerFound).second).first).first; DWORD dwTopMostContainerUID = (((*itContainerFound).second).first).second; CPointMap ptOpenedContainerPosition = ((*itContainerFound).second).second; const CObjBaseTemplate * pObjTop = pItem->GetTopLevelObj(); DWORD dwTopContainerUID_ToCheck = 0; if ( container->GetContainer() ) dwTopContainerUID_ToCheck = container->GetContainer()->GetUID().GetPrivateUID(); else dwTopContainerUID_ToCheck = pObjTop->GetUID().GetPrivateUID(); if ( ( dwTopMostContainerUID == pObjTop->GetUID().GetPrivateUID() ) && ( dwTopContainerUID == dwTopContainerUID_ToCheck ) ) { if ( pObjTop->IsChar() ) { isInOpenedContainer = true; // probably a pickup check from pack if pCharTop != this? } else { const CItem * pItemTop = dynamic_cast<const CItem *>(pObjTop); if ( pItemTop && (pItemTop->IsType(IT_SHIP_HOLD) || pItemTop->IsType(IT_SHIP_HOLD_LOCK)) && (pItemTop->GetTopPoint().GetRegion(REGION_TYPE_MULTI) == m_pChar->GetTopPoint().GetRegion(REGION_TYPE_MULTI)) ) { isInOpenedContainer = true; } else if ( ptOpenedContainerPosition.GetDist( pObjTop->GetTopPoint() ) <= 3 ) { isInOpenedContainer = true; } } } } } if( !isInOpenedContainer ) { SysMessageDefault(DEFMSG_REACH_UNABLE); return false; } } } // CanTouch handles priv level compares for chars if ( ! m_pChar->CanUse( pItem, false )) { if ( ! m_pChar->CanTouch( pItem )) { SysMessage(( m_pChar->IsStatFlag( STATF_DEAD )) ? g_Cfg.GetDefaultMsg( DEFMSG_REACH_GHOST ) : g_Cfg.GetDefaultMsg( DEFMSG_REACH_FAIL ) ); } else { SysMessageDefault( DEFMSG_REACH_UNABLE ); } return false; } } CItemBase * pItemDef = pItem->Item_GetDef(); bool fWasEquipped = pItem->IsItemEquipped(); if (( IsTrigUsed(TRIGGER_DCLICK) ) || ( IsTrigUsed(TRIGGER_ITEMDCLICK) )) { if ( pItem->OnTrigger( ITRIG_DCLICK, m_pChar ) == TRIGRET_RET_TRUE ) return true; } if ( pItemDef->IsTypeEquippable() && ! pItem->IsItemEquipped() && pItemDef->GetEquipLayer() ) { if ( pItem->IsType(IT_LIGHT_OUT) && pItem->IsItemInContainer()) { if ( ! Cmd_Use_Item_MustEquip( pItem ) ) return false; } else if ( ! pItem->IsType(IT_LIGHT_OUT) && ! pItem->IsType(IT_LIGHT_LIT) && ! pItem->IsTypeSpellbook() ) { if ( ! Cmd_Use_Item_MustEquip( pItem ) ) return false; } } CItemSpawn * pSpawn = static_cast<CItemSpawn*>(pItem->m_uidSpawnItem.ItemFind()); //Removing this item from it's spawn when players DClick it from ground, no other way to take it out. if ( pSpawn ) pSpawn->DelObj(pItem->GetUID()); SetTargMode(); m_Targ_UID = pItem->GetUID(); // probably already set anyhow. m_tmUseItem.m_pParent = pItem->GetParent(); // Cheat Verify. // Use types of items. (specific to client) switch ( pItem->GetType() ) { case IT_TRACKER: { DIR_TYPE dir = static_cast<DIR_TYPE>(DIR_QTY + 1); // invalid value. if ( ! m_pChar->Skill_Tracking( pItem->m_uidLink, dir )) { if ( pItem->m_uidLink.IsValidUID()) { SysMessageDefault( DEFMSG_TRACKING_UNABLE ); } m_Targ_UID = pItem->GetUID(); addTarget( CLIMODE_TARG_LINK, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_TRACKER_ATTUNE ) ); } } return true; case IT_TRACK_ITEM: // 109 - track a id or type of item. case IT_TRACK_CHAR: // 110 = track a char or range of char id's // Track a type of item or creature. { // Look in the local area for this item or char. } break; case IT_SHAFT: case IT_FEATHER: { if ( IsTrigUsed(TRIGGER_SKILLMENU) ) { CScriptTriggerArgs args("sm_bolts"); if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE ) return true; } return Cmd_Skill_Menu( g_Cfg.ResourceGetIDType( RES_SKILLMENU, "sm_bolts" ) ); } case IT_FISH_POLE: // Just be near water ? m_pChar->m_atResource.m_ridType = RESOURCE_ID( RES_TYPEDEF, IT_WATER ); addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg( DEFMSG_FISHING_PROMT ), true ); return true; case IT_DEED: addTargetDeed( pItem ); return true; case IT_EQ_BANK_BOX: case IT_EQ_VENDOR_BOX: if ( !fScript ) g_Log.Event( LOGL_WARN|LOGM_CHEAT, "%lx:Cheater '%s' is using 3rd party tools to open bank box\n", GetSocketID(), static_cast<LPCTSTR>(GetAccount()->GetName())); return false; case IT_CONTAINER_LOCKED: case IT_SHIP_HOLD_LOCK: if ( ! m_pChar->GetPackSafe()->ContentFindKeyFor( pItem )) { SysMessageDefault( DEFMSG_ITEMUSE_LOCKED ); if ( ! IsPriv( PRIV_GM )) return false; } case IT_CORPSE: case IT_SHIP_HOLD: case IT_CONTAINER: case IT_TRASH_CAN: { CItemContainer * pPack = dynamic_cast <CItemContainer *>(pItem); if (!pPack) return false; if ( ! m_pChar->Skill_Snoop_Check( pPack )) { if( !addContainerSetup(pPack) ) { return false; } } const CItemCorpse * pCorpseItem = dynamic_cast <const CItemCorpse *>(pPack); if ( m_pChar->CheckCorpseCrime( pCorpseItem, true, true ) ) SysMessageDefault(DEFMSG_LOOT_CRIMINAL_ACT); } return true; case IT_GAME_BOARD: if ( ! pItem->IsTopLevel()) { SysMessageDefault( DEFMSG_ITEMUSE_GAMEBOARD_FAIL ); return false; } { CItemContainer* pBoard = dynamic_cast <CItemContainer *>(pItem); ASSERT(pBoard); pBoard->Game_Create(); addContainerSetup( pBoard ); } return true; case IT_BBOARD: addBulletinBoard( dynamic_cast<CItemContainer *>(pItem)); return true; case IT_SIGN_GUMP: // Things like grave stones and sign plaques. // Need custom gumps. { GUMP_TYPE gumpid = pItemDef->m_ttContainer.m_gumpid; if ( ! gumpid ) { return false; } addGumpTextDisp( pItem, gumpid, pItem->GetName(), ( pItem->IsIndividualName()) ? pItem->GetName() : NULL ); } return true; case IT_BOOK: case IT_MESSAGE: if ( ! addBookOpen( pItem )) { SysMessageDefault( DEFMSG_ITEMUSE_BOOK_FAIL ); } return true; case IT_STONE_GUILD: case IT_STONE_TOWN: // Guild and town stones. return true; case IT_POTION: if ( !m_pChar->CanMove(pItem) ) { SysMessageDefault( DEFMSG_ITEMUSE_POTION_FAIL ); return false; } if ( RES_GET_INDEX(pItem->m_itPotion.m_Type) == SPELL_Poison ) { // If we click directly on poison potion, we will drink poison and get ill. // To use it on Poisoning skill, the skill will request to target the potion. m_pChar->OnSpellEffect(SPELL_Poison, m_pChar, pItem->m_itSpell.m_spelllevel, NULL); return true; } else if ( RES_GET_INDEX(pItem->m_itPotion.m_Type) == SPELL_Explosion ) { // Throw explode potion. if ( !m_pChar->ItemPickup(pItem, 1) ) return false; m_tmUseItem.m_pParent = pItem->GetParent(); // put the potion in our hand addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_SELECT_POTION_TARGET), true, true, 5*TICK_PER_SEC); pItem->m_itPotion.m_tick = 4; // countdown to explode pItem->m_itPotion.m_ignited = 1; // ignite it pItem->SetTimeout(TICK_PER_SEC); pItem->m_uidLink = m_pChar->GetUID(); return true; } m_pChar->Use_Drink(pItem); return true; case IT_ANIM_ACTIVE: SysMessage( g_Cfg.GetDefaultMsg( DEFMSG_ITEM_IN_USE ) ); return false; case IT_CLOCK: addObjMessage( m_pChar->GetTopSector()->GetLocalGameTime(), pItem ); return true; case IT_SPAWN_CHAR: { bool fReset = false; if ( pItem->m_itSpawnChar.m_current ) SysMessageDefault( DEFMSG_ITEMUSE_SPAWNCHAR_NEG ); else { SysMessageDefault( DEFMSG_ITEMUSE_SPAWNCHAR_RSET ); fReset = true; } static_cast<CItemSpawn*>(pItem)->KillChildren(); if ( fReset ) pItem->SetTimeout( TICK_PER_SEC ); } return true; case IT_SPAWN_ITEM: { SysMessageDefault(DEFMSG_ITEMUSE_SPAWNITEM_TRIG); //CItemSpawn *pSpawn = static_cast<CItemSpawn*>(pItem); pSpawn->OnTick(true); } return true; case IT_SHRINE: if ( m_pChar->OnSpellEffect( SPELL_Resurrection, m_pChar, 1000, pItem )) return true; SysMessageDefault( DEFMSG_ITEMUSE_SHRINE ); return true; case IT_SHIP_TILLER: // dclick on tiller man. pItem->Speak( g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_TILLERMAN ), HUE_TEXT_DEF, TALKMODE_SAY, FONT_NORMAL ); return true; // A menu or such other action ( not instantanious) case IT_WAND: case IT_SCROLL: // activate the scroll. { SPELL_TYPE spell = static_cast<SPELL_TYPE>(RES_GET_INDEX(pItem->m_itWeapon.m_spell)); const CSpellDef* pSpellDef = g_Cfg.GetSpellDef(spell); if (pSpellDef == NULL) return false; if ( IsSetMagicFlags( MAGICF_PRECAST ) && !pSpellDef->IsSpellType( SPELLFLAG_NOPRECAST ) ) { int skill; if (!pSpellDef->GetPrimarySkill(&skill, NULL)) return false; m_tmSkillMagery.m_Spell = spell; // m_atMagery.m_Spell m_pChar->m_atMagery.m_Spell = spell; m_Targ_UID = pItem->GetUID(); // default target. m_Targ_PrvUID = pItem->GetUID(); m_pChar->Skill_Start(static_cast<SKILL_TYPE>(skill)); return true; } return Cmd_Skill_Magery( spell, pItem ); } case IT_RUNE: // name the rune. if ( ! m_pChar->CanMove( pItem, true )) { return false; } addPromptConsole( CLIMODE_PROMPT_NAME_RUNE, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_RUNE_NAME ), pItem->GetUID() ); return true; case IT_CARPENTRY: // Carpentry type tool { if ( IsTrigUsed(TRIGGER_SKILLMENU) ) { CScriptTriggerArgs args("sm_carpentry"); if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE ) return true; } return Cmd_Skill_Menu( g_Cfg.ResourceGetIDType( RES_SKILLMENU, "sm_carpentry" ) ); } // Solve for the combination of this item with another. case IT_FORGE: addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg ( DEFMSG_ITEMUSE_FORGE ) ); return true; case IT_ORE: // just use the nearest forge. return m_pChar->Skill_Mining_Smelt( pItem, NULL ); case IT_INGOT: return Cmd_Skill_Smith( pItem ); case IT_KEY: case IT_KEYRING: if ( pItem->GetTopLevelObj() != m_pChar && ! m_pChar->IsPriv(PRIV_GM)) { SysMessageDefault( DEFMSG_ITEMUSE_KEY_FAIL ); return false; } addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_KEY_PROMT ), false, true ); return true; case IT_BANDAGE: // SKILL_HEALING, or SKILL_VETERINARY addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_BANDAGE_PROMT ), false, false ); return true; case IT_BANDAGE_BLOOD: // Clean the bandages. case IT_COTTON: // use on a spinning wheel. case IT_WOOL: // use on a spinning wheel. case IT_YARN: // Use this on a loom. case IT_THREAD: // Use this on a loom. case IT_COMM_CRYSTAL: addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg( DEFMSG_TARGET_PROMT ), false, false ); return true; case IT_CARPENTRY_CHOP: case IT_LOCKPICK: // Use on a locked thing. case IT_SCISSORS: addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg( DEFMSG_TARGET_PROMT ), false, true ); return true; case IT_WEAPON_MACE_SHARP: // war axe can be used to cut/chop trees. case IT_WEAPON_SWORD: // 23 = case IT_WEAPON_FENCE: // 24 = can't be used to chop trees. case IT_WEAPON_AXE: // set resource to trees m_pChar->m_atResource.m_ridType = RESOURCE_ID( RES_TYPEDEF, IT_TREE ); case IT_WEAPON_MACE_STAFF: case IT_WEAPON_MACE_SMITH: // Can be used for smithing ? { if (fWasEquipped || !IsSetOF(OF_NoDClickTarget)) addTarget(CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_WEAPON_PROMT), false, true); } return true; case IT_FISH: SysMessageDefault( DEFMSG_ITEMUSE_FISH_FAIL ); return true; case IT_TELESCOPE: // Big telescope. SysMessageDefault( DEFMSG_ITEMUSE_TELESCOPE ); return true; case IT_MAP: addDrawMap(dynamic_cast<CItemMap*>(pItem)); return true; case IT_CANNON_BALL: { TCHAR *pszTemp = Str_GetTemp(); sprintf(pszTemp, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_CBALL_PROMT ), static_cast<LPCTSTR>(pItem->GetName())); addTarget(CLIMODE_TARG_USE_ITEM, pszTemp); } return true; case IT_CANNON_MUZZLE: // Make sure the cannon is loaded. if ( ! m_pChar->CanUse( pItem, false )) return( false ); if ( ! ( pItem->m_itCannon.m_Load & 1 )) { addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_CANNON_POWDER ) ); return true; } if ( ! ( pItem->m_itCannon.m_Load & 2 )) { addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_CANNON_SHOT ) ); return true; } addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_CANNON_TARG ), false, true ); return true; case IT_CRYSTAL_BALL: // Gaze into the crystal ball. return true; case IT_WEAPON_MACE_CROOK: if (fWasEquipped || !IsSetOF(OF_NoDClickTarget)) addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_CROOK_PROMT ), false, true ); return true; case IT_SEED: case IT_PITCHER_EMPTY: { // not a crime. TCHAR *pszTemp = Str_GetTemp(); sprintf(pszTemp, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_PITCHER_TARG ), static_cast<LPCTSTR>(pItem->GetName())); addTarget(CLIMODE_TARG_USE_ITEM, pszTemp, true); } return true; case IT_WEAPON_MACE_PICK: if (fWasEquipped || !IsSetOF(OF_NoDClickTarget)) { // Mine at the location. (possible crime?) TCHAR *pszTemp = Str_GetTemp(); sprintf(pszTemp, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_MACEPICK_TARG ), static_cast<LPCTSTR>(pItem->GetName())); m_pChar->m_atResource.m_ridType = RESOURCE_ID(RES_TYPEDEF, IT_ROCK); addTarget(CLIMODE_TARG_USE_ITEM, pszTemp, true, true); } return true; case IT_SPELLBOOK: addSpellbookOpen( pItem ); return true; case IT_SPELLBOOK_NECRO: addSpellbookOpen( pItem, 101 ); return true; case IT_SPELLBOOK_PALA: addSpellbookOpen( pItem, 201 ); return true; case IT_SPELLBOOK_BUSHIDO: addSpellbookOpen( pItem, 401 ); return true; case IT_SPELLBOOK_NINJITSU: addSpellbookOpen( pItem, 501 ); return true; case IT_SPELLBOOK_ARCANIST: addSpellbookOpen( pItem, 601 ); return true; case IT_SPELLBOOK_MYSTIC: addSpellbookOpen( pItem, 678 ); return true; case IT_SPELLBOOK_BARD: addSpellbookOpen( pItem, 701 ); return true; case IT_HAIR_DYE: if (!m_pChar->LayerFind( LAYER_BEARD ) && !m_pChar->LayerFind( LAYER_HAIR )) { SysMessageDefault( DEFMSG_ITEMUSE_DYE_NOHAIR ); return true; } Dialog_Setup(CLIMODE_DIALOG, g_Cfg.ResourceGetIDType( RES_DIALOG, "d_HAIR_DYE" ), 0, pItem ); return true; case IT_DYE: addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_DYE_VAT ) ); return true; case IT_DYE_VAT: addTarget( CLIMODE_TARG_USE_ITEM, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_DYE_TARG ), false, true ); return true; case IT_MORTAR: { if ( IsTrigUsed(TRIGGER_SKILLMENU) ) { CScriptTriggerArgs args("sm_alchemy"); if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE ) return true; } return Cmd_Skill_Menu( g_Cfg.ResourceGetIDType( RES_SKILLMENU, "sm_alchemy" ) ); } case IT_CARTOGRAPHY: { if ( IsTrigUsed(TRIGGER_SKILLMENU) ) { CScriptTriggerArgs args("sm_cartography"); if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE ) return true; } return Cmd_Skill_Menu( g_Cfg.ResourceGetIDType( RES_SKILLMENU, "sm_cartography" ) ); } case IT_COOKING: { if ( IsTrigUsed(TRIGGER_SKILLMENU) ) { CScriptTriggerArgs args("sm_cooking"); if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE ) return true; } return Cmd_Skill_Menu( g_Cfg.ResourceGetIDType( RES_SKILLMENU, "sm_cooking" ) ); } case IT_TINKER_TOOLS: { if ( IsTrigUsed(TRIGGER_SKILLMENU) ) { CScriptTriggerArgs args("sm_tinker"); if ( m_pChar->OnTrigger("@SkillMenu", m_pChar, &args) == TRIGRET_RET_TRUE ) return true; } return Cmd_Skill_Menu( g_Cfg.ResourceGetIDType( RES_SKILLMENU, "sm_tinker" ) ); } case IT_SEWING_KIT: // IT_SEWING_KIT Sew with materials we have on hand. { TCHAR *pszTemp = Str_GetTemp(); sprintf(pszTemp, g_Cfg.GetDefaultMsg( DEFMSG_ITEMUSE_SEWKIT_PROMT ), static_cast<LPCTSTR>(pItem->GetName())); addTarget(CLIMODE_TARG_USE_ITEM, pszTemp); } return true; case IT_SCROLL_BLANK: Cmd_Skill_Inscription(); return true; default: // An NPC could use it this way. if ( m_pChar->Use_Item( pItem )) return( true ); break; } SysMessageDefault( DEFMSG_ITEMUSE_CANTTHINK ); return( false ); }
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; }