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 }
//恢复到缺省技能操作,用于退出修理,鉴定,等特殊鼠标命令状态 VOID CGameInterface::Skill_CancelAction(VOID) { //修理 if( CActionSystem::GetMe()->GetDefaultAction() == CActionItem_MouseCmd_Repair::GetMe()) { CActionSystem::GetMe()->SetDefaultAction(Skill_GetActive()); } else if(CActionSystem::GetMe()->GetDefaultAction() == CActionItem_MouseCmd_Identify::GetMe()) //鉴定 { CDataPool::GetMe()->Identify_UnLock(); CActionSystem::GetMe()->SetDefaultAction(Skill_GetActive()); } }
bool CChar::Use_Train_PickPocketDip( CItem *pItem, bool fSetup ) { ADDTOCALLSTACK("CChar::Use_Train_PickPocketDip"); // IT_TRAIN_PICKPOCKET // Train dummy. ASSERT(pItem); if ( Skill_GetBase(SKILL_STEALING) > g_Cfg.m_iSkillPracticeMax ) { SysMessageDefault(DEFMSG_ITEMUSE_PDUMMY_SKILL); return true; } if ( !pItem->IsTopLevel() ) { badpickpocket: SysMessageDefault(DEFMSG_ITEMUSE_PDUMMY_P); return true; } int dx = GetTopPoint().m_x - pItem->GetTopPoint().m_x; int dy = GetTopPoint().m_y - pItem->GetTopPoint().m_y; bool fNS = (pItem->GetDispID() == ITEMID_PICKPOCKET_NS || pItem->GetDispID() == ITEMID_PICKPOCKET_NS2); if ( fNS ) { if ( !(!dx && abs(dy) < 2) ) goto badpickpocket; } else { if ( !(!dy && abs(dx) < 2) ) goto badpickpocket; } if ( fSetup ) { if ( Skill_GetActive() == NPCACT_TRAINING ) return true; m_Act_TargPrv = m_uidWeapon; m_Act_Targ = pItem->GetUID(); Skill_Start(NPCACT_TRAINING); } else if ( !Skill_UseQuick(SKILL_STEALING, Calc_GetRandLLVal(40)) ) { pItem->Sound(0x041); pItem->SetAnim(fNS ? ITEMID_PICKPOCKET_NS_FX : ITEMID_PICKPOCKET_EW_FX, 3 * TICK_PER_SEC); UpdateAnimate(ANIM_ATTACK_WEAPON); } else { SysMessageDefault(DEFMSG_ITEMUSE_PDUMMY_OK); //pItem->Sound(0x033); } return true; }
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 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); int iMaxSkill = pSkillTag ? static_cast<int>(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 { pItem->SetAnim(static_cast<ITEMID_TYPE>(pItem->GetID() + 1), 3 * TICK_PER_SEC); pItem->Sound(0x033); Skill_UseQuick(skill, Calc_GetRandLLVal(40)); } return true; }