bool CChar::NPC_PetSetOwner( CChar * pChar ) { ADDTOCALLSTACK("CChar::NPC_PetSetOwner"); // m_pNPC may not be set yet if this is a conjured creature. if ( m_pPlayer || pChar == this || pChar == NULL ) return false; CChar * pOwner = NPC_PetGetOwner(); if ( pOwner == pChar ) return false; NPC_PetClearOwners(); // clear previous owner before set the new owner m_ptHome.InitPoint(); // no longer homed CItemSpawn * pSpawn = static_cast<CItemSpawn*>( m_uidSpawnItem.ItemFind() ); if ( pSpawn ) pSpawn->DelObj( GetUID() ); Memory_AddObjTypes(pChar, MEMORY_IPET); NPC_Act_Follow(); if ( NPC_IsVendor() ) { // Clear my cash total. CItemContainer * pBank = GetBank(); pBank->m_itEqBankBox.m_Check_Amount = 0; StatFlag_Set(STATF_INVUL); } if ( IsSetOF(OF_PetSlots) ) pChar->FollowersUpdate(this, static_cast<short>(maximum(1, GetDefNum("FOLLOWERSLOTS", true, true)))); return true; }
bool CChar::NPC_CheckHirelingStatus() { ADDTOCALLSTACK("CChar::NPC_CheckHirelingStatus"); // Am i happy at the moment ? // If not then free myself. // // RETURN: // true = happy. if ( ! IsStatFlag( STATF_Pet )) return( true ); CCharBase * pCharDef = Char_GetDef(); int iFoodConsumeRate = g_Cfg.m_iRegenRate[STAT_FOOD]; unsigned int iWage = pCharDef->GetHireDayWage(); if ( ! iWage || ! iFoodConsumeRate ) return( true ); // I am hired for money not for food. unsigned int iPeriodWage = IMULDIV( iWage, iFoodConsumeRate, 24 * 60 * g_Cfg.m_iGameMinuteLength ); if ( iPeriodWage <= 0 ) iPeriodWage = 1; CItemContainer * pBank = GetBank(); if ( pBank->m_itEqBankBox.m_Check_Amount > iPeriodWage ) { pBank->m_itEqBankBox.m_Check_Amount -= iPeriodWage; } else { TCHAR* pszMsg = Str_GetTemp(); sprintf(pszMsg, g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_WAGE_COST ), iWage); Speak(pszMsg); CChar * pOwner = NPC_PetGetOwner(); if ( pOwner ) { Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_HIRE_TIMEUP ) ); CItem * pMemory = Memory_AddObjTypes( pOwner, MEMORY_SPEAK ); if ( pMemory ) pMemory->m_itEqMemory.m_Action = NPC_MEM_ACT_SPEAK_HIRE; NPC_PetDesert(); return false; } // Some sort of strange bug to get here. Memory_ClearTypes( MEMORY_IPET ); StatFlag_Clear( STATF_Pet ); } return( true ); }
bool CChar::NPC_OnHireHear( CChar * pCharSrc ) { ADDTOCALLSTACK("CChar::NPC_OnHireHear"); if ( !m_pNPC ) return false; CCharBase * pCharDef = Char_GetDef(); unsigned int iWage = pCharDef->GetHireDayWage(); if ( ! iWage ) { Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_NOT_FOR_HIRE ) ); return false; } CItemMemory * pMemory = Memory_FindObj( pCharSrc ); if ( pMemory ) { if ( pMemory->IsMemoryTypes(MEMORY_IPET|MEMORY_FRIEND)) { // Next gold i get goes toward hire. pMemory->m_itEqMemory.m_Action = NPC_MEM_ACT_SPEAK_HIRE; NPC_OnHirePayMore( NULL, false ); return true; } if ( pMemory->IsMemoryTypes( MEMORY_FIGHT|MEMORY_HARMEDBY|MEMORY_IRRITATEDBY )) { Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_NOT_WORK ) ); return false; } } if ( IsStatFlag( STATF_Pet )) { Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_EMPLOYED ) ); return false; } TCHAR *pszMsg = Str_GetTemp(); sprintf(pszMsg, Calc_GetRandVal(2) ? g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_HIRE_AMNT ) : g_Cfg.GetDefaultMsg( DEFMSG_NPC_PET_HIRE_RATE ), iWage ); Speak(pszMsg); pMemory = Memory_AddObjTypes( pCharSrc, MEMORY_SPEAK ); if ( pMemory ) pMemory->m_itEqMemory.m_Action = NPC_MEM_ACT_SPEAK_HIRE; return true; }
bool CChar::NPC_OnTrainHear( CChar * pCharSrc, lpctstr pszCmd ) { ADDTOCALLSTACK("CChar::NPC_OnTrainHear"); // We are asking for training ? if ( ! m_pNPC ) return false; // Check the NPC is capable of teaching if ( (m_pNPC->m_Brain < NPCBRAIN_HUMAN) || (m_pNPC->m_Brain > NPCBRAIN_STABLE) || (m_pNPC->m_Brain == NPCBRAIN_GUARD) ) return false; // Check the NPC isn't busy fighting if ( Memory_FindObjTypes( pCharSrc, MEMORY_FIGHT|MEMORY_HARMEDBY|MEMORY_IRRITATEDBY|MEMORY_AGGREIVED )) { Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_TRAINER_ENEMY ) ); return true; } // Did they mention a skill name i recognize ? TemporaryString pszMsg; for ( size_t i = 0; i < g_Cfg.m_iMaxSkill; i++ ) { if ( !g_Cfg.m_SkillIndexDefs.IsValidIndex(static_cast<SKILL_TYPE>(i)) ) continue; lpctstr pSkillKey = g_Cfg.GetSkillKey(static_cast<SKILL_TYPE>(i)); if ( FindStrWord( pszCmd, pSkillKey ) <= 0) continue; // Can we train in this ? int iTrainCost = NPC_OnTrainCheck(pCharSrc, static_cast<SKILL_TYPE>(i)) * g_Cfg.m_iTrainSkillCost; if ( iTrainCost <= 0 ) return true; sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_TRAINER_PRICE), iTrainCost, static_cast<lpctstr>(pSkillKey)); Speak(pszMsg); CItemMemory * pMemory = Memory_AddObjTypes( pCharSrc, MEMORY_SPEAK ); if ( pMemory ) { pMemory->m_itEqMemory.m_Action = NPC_MEM_ACT_SPEAK_TRAIN; pMemory->m_itEqMemory.m_Skill = (word)(i); } return true; } // What can he teach me about ? // Just tell them what we can teach them or set up a memory to train. strcpy( pszMsg, g_Cfg.GetDefaultMsg( DEFMSG_NPC_TRAINER_PRICE_1 ) ); lpctstr pPrvSkill = NULL; size_t iCount = 0; for ( size_t i = 0; i < g_Cfg.m_iMaxSkill; i++ ) { if ( !g_Cfg.m_SkillIndexDefs.IsValidIndex(static_cast<SKILL_TYPE>(i)) ) continue; int iDiff = NPC_GetTrainMax(pCharSrc, static_cast<SKILL_TYPE>(i)) - pCharSrc->Skill_GetBase(static_cast<SKILL_TYPE>(i)); if ( iDiff <= 0 ) continue; if ( iCount > 6 ) { pPrvSkill = g_Cfg.GetDefaultMsg( DEFMSG_NPC_TRAINER_PRICE_2 ); break; } if ( iCount > 1 ) { strcat( pszMsg, g_Cfg.GetDefaultMsg( DEFMSG_NPC_TRAINER_PRICE_3 ) ); } if ( pPrvSkill ) { strcat( pszMsg, pPrvSkill ); } pPrvSkill = g_Cfg.GetSkillKey(static_cast<SKILL_TYPE>(i)); iCount++; } if ( iCount == 0 ) { Speak( g_Cfg.GetDefaultMsg( DEFMSG_NPC_TRAINER_THATSALL_3 ) ); return true; } if ( iCount > 1 ) { strcat( pszMsg, g_Cfg.GetDefaultMsg( DEFMSG_NPC_TRAINER_THATSALL_4 ) ); } strcat( pszMsg, pPrvSkill ); strcat( pszMsg, "." ); Speak( pszMsg ); 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 ( m_fIgnoreNextPetCmd ) { m_fIgnoreNextPetCmd = false; return false; } switch ( iCmd ) { case PC_FOLLOW: case PC_STAY: case PC_STOP: { // Pet friends can use only these commands if ( Memory_FindObjTypes(pSrc, MEMORY_FRIEND) ) break; } default: { // All others commands are avaible only to pet owner if ( !NPC_IsOwnedBy(pSrc, true) ) return false; } } if ( IsStatFlag(STATF_DEAD) ) { // Bonded NPCs still placed on world even when dead. // They can listen to commands, but not to these commands below if ( iCmd == PC_GUARD || iCmd == PC_GUARD_ME || iCmd == PC_ATTACK || iCmd == PC_KILL || iCmd == PC_TRANSFER || iCmd == PC_DROP || iCmd == PC_DROP_ALL ) return true; } bool bSuccess = false; CItem *pItemTarg = dynamic_cast<CItem *>(pObj); CChar *pCharTarg = dynamic_cast<CChar *>(pObj); switch ( iCmd ) { case PC_ATTACK: case PC_KILL: { if ( !pCharTarg || pCharTarg == pSrc ) break; bSuccess = pCharTarg->OnAttackedBy(pSrc, 1, true); // we know who told them to do this. if ( bSuccess ) bSuccess = Fight_Attack(pCharTarg, true); break; } case PC_FOLLOW: if ( !pCharTarg ) break; m_Act_Targ = pCharTarg->GetUID(); bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; case PC_FRIEND: { if ( !pCharTarg || !pCharTarg->m_pPlayer || pCharTarg == pSrc ) { Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_CONFUSED)); break; } CItemMemory *pMemory = Memory_FindObjTypes(pCharTarg, MEMORY_FRIEND); if ( pMemory ) { pSrc->SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND_ALREADY)); break; } pSrc->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND_SUCCESS1), GetName(), pCharTarg->GetName()); pCharTarg->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND_SUCCESS2), pSrc->GetName(), GetName()); Memory_AddObjTypes(pCharTarg, MEMORY_FRIEND); m_Act_Targ = pCharTarg->GetUID(); bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; } case PC_UNFRIEND: { if ( !pCharTarg || !pCharTarg->m_pPlayer ) { Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_CONFUSED)); break; } CItemMemory *pMemory = Memory_FindObjTypes(pCharTarg, MEMORY_FRIEND); if ( !pMemory ) { pSrc->SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_UNFRIEND_NOTFRIEND)); break; } pSrc->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_UNFRIEND_SUCCESS1), GetName(), pCharTarg->GetName()); pCharTarg->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_UNFRIEND_SUCCESS2), pSrc->GetName(), GetName()); pMemory->Delete(); m_Act_Targ = pSrc->GetUID(); bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; } case PC_GO: if ( !pt.IsValidPoint() ) break; m_Act_p = pt; bSuccess = Skill_Start(NPCACT_GOTO); break; case PC_GUARD: if ( !pCharTarg ) break; pCharTarg->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_GUARD_SUCCESS), GetName()); m_Act_Targ = pCharTarg->GetUID(); bSuccess = Skill_Start(NPCACT_GUARD_TARG); break; case PC_TRANSFER: if ( !pCharTarg || !pCharTarg->IsClient() ) break; 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; } } bSuccess = NPC_PetSetOwner( pCharTarg ); break; case PC_PRICE: // "PRICE" the vendor item. if ( !pItemTarg || !NPC_IsVendor() || !pSrc->IsClient() ) break; if ( IsDigit(pszArgs[0]) ) // did they name a price return NPC_SetVendorPrice(pItemTarg, ATOI(pszArgs)); if ( !NPC_SetVendorPrice(pItemTarg, -1) ) // test if it can be priced return false; pSrc->m_pClient->addPromptConsole(CLIMODE_PROMPT_VENDOR_PRICE, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_SETPRICE_2), pItemTarg->GetUID(), GetUID()); return true; default: break; } // Make some sound to confirm we heard it NPC_OnPetCommand(bSuccess, pSrc); return bSuccess; }
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 ( m_fIgnoreNextPetCmd ) { m_fIgnoreNextPetCmd = false; return false; } if ( !NPC_PetCheckAccess(iCmd, pSrc) ) return true; bool bSuccess = false; CItem *pItemTarg = dynamic_cast<CItem *>(pObj); CChar *pCharTarg = dynamic_cast<CChar *>(pObj); switch ( iCmd ) { case PC_ATTACK: case PC_KILL: { if ( !pCharTarg || (pCharTarg == this) || (pCharTarg == pSrc) ) break; bSuccess = pCharTarg->OnAttackedBy(pSrc, true); if ( bSuccess ) bSuccess = Fight_Attack(pCharTarg, true); break; } case PC_FOLLOW: if ( !pCharTarg || (pCharTarg == this) ) break; m_Act_Targ = pCharTarg->GetUID(); bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; case PC_FRIEND: { if ( !pCharTarg || !pCharTarg->m_pPlayer || (pCharTarg == pSrc) ) { Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_CONFUSED)); break; } CItemMemory *pMemory = Memory_FindObjTypes(pCharTarg, MEMORY_FRIEND); if ( pMemory ) { pSrc->SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND_ALREADY)); break; } pSrc->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND_SUCCESS1), GetName(), pCharTarg->GetName()); pCharTarg->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND_SUCCESS2), pSrc->GetName(), GetName()); Memory_AddObjTypes(pCharTarg, MEMORY_FRIEND); m_Act_Targ = pCharTarg->GetUID(); bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; } case PC_UNFRIEND: { if ( !pCharTarg || !pCharTarg->m_pPlayer ) { Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_CONFUSED)); break; } CItemMemory *pMemory = Memory_FindObjTypes(pCharTarg, MEMORY_FRIEND); if ( !pMemory ) { pSrc->SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_UNFRIEND_NOTFRIEND)); break; } pSrc->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_UNFRIEND_SUCCESS1), GetName(), pCharTarg->GetName()); pCharTarg->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_UNFRIEND_SUCCESS2), pSrc->GetName(), GetName()); pMemory->Delete(); m_Act_Targ = pSrc->GetUID(); bSuccess = Skill_Start(NPCACT_FOLLOW_TARG); break; } case PC_GO: if ( !pt.IsValidPoint() ) break; m_Act_p = pt; bSuccess = Skill_Start(NPCACT_GOTO); break; case PC_GUARD: if ( !pCharTarg || (pCharTarg == this) ) break; pCharTarg->SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_GUARD_SUCCESS), GetName()); m_Act_Targ = pCharTarg->GetUID(); bSuccess = Skill_Start(NPCACT_GUARD_TARG); break; case PC_TRANSFER: if ( !pCharTarg || !pCharTarg->m_pClient ) break; if ( IsSetOF(OF_PetSlots) ) { if ( !pCharTarg->FollowersUpdate(this, static_cast<short>(maximum(1, GetDefNum("FOLLOWERSLOTS", true))), true) ) { pSrc->SysMessageDefault(DEFMSG_PETSLOTS_TRY_TRANSFER); break; } } bSuccess = NPC_PetSetOwner(pCharTarg); break; case PC_PRICE: if ( !pItemTarg || !NPC_IsVendor() || !pSrc->m_pClient ) break; if ( IsDigit(pszArgs[0]) ) // did they name a price return NPC_SetVendorPrice(pItemTarg, ATOI(pszArgs)); if ( !NPC_SetVendorPrice(pItemTarg, -1) ) // test if it can be priced return false; pSrc->m_pClient->addPromptConsole(CLIMODE_PROMPT_VENDOR_PRICE, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_SETPRICE_2), pItemTarg->GetUID(), GetUID()); return true; default: break; } // Make some sound to confirm we heard it NPC_PetConfirmCommand(bSuccess, pSrc); return bSuccess; }
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; }