Exemplo n.º 1
0
// Create an NPC from script.
void CChar::NPC_LoadScript( bool fRestock )
{
	ADDTOCALLSTACK("CChar::NPC_LoadScript");
	if ( m_pNPC == NULL )
		// Set a default brian type til we get the real one from scripts.
		SetNPCBrain(GetNPCBrain(false));	// should have a default brain. watch out for override vendor.

	CCharBase * pCharDef = Char_GetDef();

	// 1) CHARDEF trigger
	if ( m_pPlayer == NULL ) //	CHARDEF triggers (based on body type)
	{
		CChar * pChar = this->GetChar();
		if ( pChar != NULL )
		{
			CUID uidOldAct = pChar->m_Act_Targ;
			pChar->m_Act_Targ = GetUID();
			pChar->ReadScriptTrig(pCharDef, CTRIG_Create);
			pChar->m_Act_Targ = uidOldAct;
		}
	}
	//This remains untouched but moved after the chardef's section
	if (( fRestock ) && ( IsTrigUsed(TRIGGER_NPCRESTOCK) ))
		ReadScriptTrig(pCharDef, CTRIG_NPCRestock);

	CreateNewCharCheck();	//This one is giving stats, etc to the char, so we can read/set them in the next triggers.
}
Exemplo n.º 2
0
bool CChar::ItemEquipWeapon( bool fForce )
{
	ADDTOCALLSTACK("CChar::ItemEquipWeapon");
	// Find my best weapon and equip it
	if ( !fForce && m_uidWeapon.IsValidUID() )	// we already have a weapon equipped
		return true;

	CCharBase *pCharDef = Char_GetDef();
	CItemContainer *pPack = GetPack();

	if ( !pPack || !pCharDef || !pCharDef->Can(CAN_C_USEHANDS) )
		return false;

	// Loop through all my weapons and come up with a score for it's usefulness

	CItem *pBestWeapon = NULL;
	int iWeaponScoreMax = NPC_GetWeaponUseScore(NULL);	// wrestling

	for ( CItem *pItem = pPack->GetContentHead(); pItem != NULL; pItem = pItem->GetNext() )
	{
		int iWeaponScore = NPC_GetWeaponUseScore(pItem);
		if ( iWeaponScore > iWeaponScoreMax )
		{
			iWeaponScoreMax = iWeaponScore;
			pBestWeapon = pItem;
		}
	}

	if ( pBestWeapon )
		return ItemEquip(pBestWeapon);

	return true;
}
Exemplo n.º 3
0
size_t CChar::NPC_OnHearName(LPCTSTR pszText) const
{
	ADDTOCALLSTACK("CChar::NPC_OnHearName");
	// Did I just hear my name in this text ?
	// should be able to deal with "hi Dennis" in the future.
	// RETURN:
	//  index to skip past the name.

	LPCTSTR pszName = GetName();

	size_t i = FindStrWord(pszText, pszName);
	if ( i )
		return i;

	// Named the chars type ? (must come first !)
	CCharBase *pCharDef = Char_GetDef();
	pszName = pCharDef->GetTradeName();
	for ( i = 0; pszText[i] != '\0'; i++ )
	{
		if ( pszName[i] == '\0' )
		{
			// found name
			while ( ISWHITESPACE(pszText[i]) )
				i++;
			return i;	// char name found
		}
		if ( toupper(pszName[i]) != toupper(pszText[i]) )	// not the name
			break;
	}

	return 0;
}
Exemplo n.º 4
0
void CChar::NPC_OnHirePayMore(CItem *pGold, bool bHire)
{
	ADDTOCALLSTACK("CChar::NPC_OnHirePayMore");
	// We have been handed money.
	// similar to PC_STATUS

	CCharBase *pCharDef = Char_GetDef();
	CItemContainer *pBank = GetContainerCreate(LAYER_BANKBOX);
	if ( !pCharDef->m_iHireDayWage || !pBank )
		return;

	if ( pGold )
	{
		if ( bHire )
			pBank->m_itEqBankBox.m_Check_Amount = 0;	// clear previous balance

		pBank->m_itEqBankBox.m_Check_Amount += pGold->GetAmount();
		Sound(pGold->GetDropSound(NULL));
		pGold->Delete();
	}

	TCHAR *pszMsg = Str_GetTemp();
	sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_HIRE_TIME), pBank->m_itEqBankBox.m_Check_Amount / pCharDef->m_iHireDayWage);
	Speak(pszMsg);
}
Exemplo n.º 5
0
void CChar::NPC_OnHirePayMore( CItem * pGold, bool fHire )
{
	ADDTOCALLSTACK("CChar::NPC_OnHirePayMore");
	// We have been handed money.
	// similar to PC_STATUS

	CCharBase * pCharDef = Char_GetDef();
	unsigned int iWage = pCharDef->GetHireDayWage();
	CItemContainer	*pBank = GetBank();
	if ( !iWage || !pBank )
		return;

	if ( pGold )
	{
		if ( fHire )
		{
			pBank->m_itEqBankBox.m_Check_Amount = 0;	// zero any previous balance.
		}

		pBank->m_itEqBankBox.m_Check_Amount += pGold->GetAmount();
		Sound( pGold->GetDropSound( NULL ));
		pGold->Delete();
	}

	TCHAR *pszMsg = Str_GetTemp();
	sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_HIRE_TIME), pBank->m_itEqBankBox.m_Check_Amount / iWage);
	Speak(pszMsg);
}
Exemplo n.º 6
0
bool CChar::NPC_CanSpeak() const
{
	ADDTOCALLSTACK("CChar::NPC_CanSpeak");
	//	players and chars with speech can
	if ( m_pNPC == NULL || m_pNPC->m_Speech.GetCount() > 0 )
		return true;

	CCharBase * pCharDef = Char_GetDef();
	return( pCharDef != NULL && pCharDef->m_Speech.GetCount() > 0 );
}
Exemplo n.º 7
0
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 );
}
Exemplo n.º 8
0
bool CChar::ItemEquipArmor( bool fForce )
{
	ADDTOCALLSTACK("CChar::ItemEquipArmor");
	// Equip ourselves as best as possible.

	CCharBase *pCharDef = Char_GetDef();
	CItemContainer *pPack = GetPack();
	if ( !pPack || !pCharDef || !pCharDef->Can(CAN_C_EQUIP) )
		return false;

	int iBestScore[LAYER_HORSE];
	memset(iBestScore, 0, sizeof(iBestScore));
	CItem *pBestArmor[LAYER_HORSE];
	memset(pBestArmor, 0, sizeof(pBestArmor));

	if ( !fForce )
	{
		// Block those layers that are already used
		for ( size_t i = 0; i < COUNTOF(iBestScore); i++ )
		{
			pBestArmor[i] = LayerFind(static_cast<LAYER_TYPE>(i));
			if ( pBestArmor[i] != NULL )
				iBestScore[i] = INT_MAX;
		}
	}

	for ( CItem *pItem = pPack->GetContentHead(); pItem != NULL; pItem = pItem->GetNext() )
	{
		int iScore = pItem->Armor_GetDefense();
		if ( !iScore )	// might not be armor
			continue;

		// Can I even equip this?
		LAYER_TYPE layer = CanEquipLayer(pItem, LAYER_QTY, NULL, true);
		if ( layer == LAYER_NONE )
			continue;

		if ( iScore > iBestScore[layer] )
		{
			iBestScore[layer] = iScore;
			pBestArmor[layer] = pItem;
		}
	}

	// Equip all the stuff we found
	for ( size_t i = 0; i < COUNTOF(iBestScore); i++ )
	{
		if ( pBestArmor[i] )
			ItemEquip(pBestArmor[i], this);
	}

	return true;
}
Exemplo n.º 9
0
int CChar::NPC_GetVendorMarkup( const CChar * pChar ) const
{
	ADDTOCALLSTACK("CChar::NPC_GetVendorMarkup");
	// This vendor marks stuff up/down this percentage.
	// Base this on KARMA. Random is calculated at Restock time
	// When vendor sells to players this is the markup value.
	// fBuy: Client buying
	// RETURN:
	//  0-100

	if ( !pChar || IsStatFlag(STATF_Pet) )	// Not on a hired vendor.
		return( 0 );

	CVarDefCont	*pVar = NULL, *pVarCharDef = NULL;
	CCharBase * pCharDef = Char_GetDef();
	
	if ( pCharDef )
	{
		// get markup value of NPC-chardef
		pVarCharDef = pCharDef->m_TagDefs.GetKey("VENDORMARKUP");
	}

	int iHostility = maximum(NPC_GetHostilityLevelToward(pChar), 0);
	iHostility = minimum(iHostility + 15, 100);

	pVar = m_TagDefs.GetKey("VENDORMARKUP");
	if ( pVar )
	{
		iHostility += static_cast<int>(pVar->GetValNum());
		// add NPC's markup to hostility made by karma difference
	}
	else
	{
		pVar = GetRegion()->m_TagDefs.GetKey("VENDORMARKUP");
		if ( pVar )
		{
			iHostility += static_cast<int>(pVar->GetValNum());
			// if NPC is unmarked, look if the region is
		}
		else
		{
			// neither NPC nor REGION are marked, so look for the chardef
			if ( pVarCharDef )
			{
				iHostility += static_cast<int>(pVarCharDef->GetValNum());
			}
		}
	}

	return( iHostility );
}
Exemplo n.º 10
0
size_t CChar::NPC_OnHearName( LPCTSTR pszText ) const
{
	ADDTOCALLSTACK("CChar::NPC_OnHearName");
	// Did I just hear my name in this text ?
	// should be able to deal with "hi Dennis" in the future.
	// RETURN:
	//  index to skip past the name.

	LPCTSTR pszName = GetName();

	size_t i = FindStrWord( pszText, pszName );
	if ( i )
		return( i );

	if ( m_pNPC )
	{
		// My title ?
		if ( m_pNPC->m_Brain == NPCBRAIN_GUARD )
		{
			if ( ! strnicmp( pszText, "GUARD ", 6 ))
				return 6;
		}
		else if ( NPC_IsVendor())
		{
			if ( ! strnicmp( pszText, "VENDOR ", 7 ))
				return 7;
		}
	}

	CCharBase * pCharDef = Char_GetDef();

	// Named the chars type ? (must come first !)
	pszName = pCharDef->GetTradeName();
	for ( i = 0; pszText[i] != '\0'; i++ )
	{
		if ( pszName[i] == '\0' )
		{
			// found name.
			while ( ISWHITESPACE( pszText[i] ))
				i++;
			return( i );	// Char name found
		}
		if ( toupper( pszName[i] ) != toupper( pszText[i] ))	// not the name.
			break;
	}

	return( 0 );
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
0
int CChar::NPC_WantThisItem( CItem * pItem ) const
{
	ADDTOCALLSTACK("CChar::NPC_WantThisItem");
	//  This should be the ULTIMATE place to check if the NPC wants this in any way.
	//  May not want to use it but rather just put it in my pack.
	//
	// NOTE:
	//  Don't check if i can see this or i can reach it.
	//  Don't check if i can carry this ?
	//
	// RETURN:
	//  0-100 percent = how bad do we want it ?

	if ( !CanMove(pItem, false) )
		return 0;

	CCharBase * pCharDef = Char_GetDef();
	ASSERT(pCharDef != NULL);
	size_t iRet = pCharDef->m_Desires.FindResourceMatch(pItem);
	if ( iRet != pCharDef->m_Desires.BadIndex() )
		return static_cast<int>(pCharDef->m_Desires[iRet].GetResQty());

	// I'm hungry and this is food ?
	int iFoodLevel = Food_GetLevelPercent();
	if ( Food_CanEat(pItem) && iFoodLevel < 100 )
		return 100 - iFoodLevel;

	if ( NPC_IsVendor() )
	{
		// Vendors always want money
		if ( pItem->IsType(IT_GOLD) )
			return 100;

		// Is it something I would buy?
		CItemVendable * pItemSell = NPC_FindVendableItem(dynamic_cast<CItemVendable *>(pItem), const_cast<CChar *>(this)->GetBank(LAYER_VENDOR_BUYS), const_cast<CChar *>(this)->GetBank(LAYER_VENDOR_STOCK));
		if ( pItemSell )
			return pItemSell->GetVendorPrice(0);
	}

	return 0;
}
Exemplo n.º 14
0
int CChar::NPC_GetVendorMarkup() const
{
	ADDTOCALLSTACK("CChar::NPC_GetVendorMarkup");
	// This vendor marks stuff up/down this percentage.
	// When vendor sells to players this is the markup value.
	//
	// RETURN:
	//  +100% = double price
	//  0% = default price
	//  -100% = free

	if ( IsStatFlag(STATF_Pet) )	// not on a hired vendor
		return 0;

	// Use char value
	CVarDefCont *pVar = m_TagDefs.GetKey("VENDORMARKUP");
	if ( pVar )
		return static_cast<int>(pVar->GetValNum());

	// Use region value
	if ( m_pArea )
	{
		pVar = m_pArea->m_TagDefs.GetKey("VENDORMARKUP");
		if ( pVar )
			return static_cast<int>(pVar->GetValNum());
	}

	// Use chardef value
	CCharBase *pCharDef = Char_GetDef();
	if ( pCharDef )
	{
		pVar = pCharDef->m_TagDefs.GetKey("VENDORMARKUP");
		if ( pVar )
			return static_cast<int>(pVar->GetValNum());
	}

	// Use default value
	return 15;
}
Exemplo n.º 15
0
// @Create trigger, NPC version
void CChar::NPC_CreateTrigger()
{
	ADDTOCALLSTACK("CChar::NPC_CreateTrigger");
	if (!m_pNPC)
		return;

	CCharBase *pCharDef = Char_GetDef();
	TRIGRET_TYPE iRet = TRIGRET_RET_DEFAULT;
	lpctstr pszTrigName = "@Create";
	CTRIG_TYPE iAction = (CTRIG_TYPE)FindTableSorted(pszTrigName, sm_szTrigName, CountOf(sm_szTrigName) - 1);

	// 2) TEVENTS
	for (size_t i = 0; i < pCharDef->m_TEvents.GetCount(); ++i)
	{
		CResourceLink * pLink = pCharDef->m_TEvents[i];
		if (!pLink || !pLink->HasTrigger(iAction))
			continue;
		CResourceLock s;
		if (!pLink->ResourceLock(s))
			continue;
		iRet = CScriptObj::OnTriggerScript(s, pszTrigName, this, 0);
		if (iRet != TRIGRET_RET_FALSE && iRet != TRIGRET_RET_DEFAULT)
			return;
	}

	// 4) EVENTSPET triggers
	for (size_t i = 0; i < g_Cfg.m_pEventsPetLink.GetCount(); ++i)
	{
		CResourceLink * pLink = g_Cfg.m_pEventsPetLink[i];
		if (!pLink || !pLink->HasTrigger(iAction))
			continue;
		CResourceLock s;
		if (!pLink->ResourceLock(s))
			continue;
		iRet = CScriptObj::OnTriggerScript(s, pszTrigName, this, 0);
		if (iRet != TRIGRET_RET_FALSE && iRet != TRIGRET_RET_DEFAULT)
			return;
	}
}
Exemplo n.º 16
0
bool CChar::NPC_Vendor_Restock(bool bForce, bool bFillStock)
{
	ADDTOCALLSTACK("CChar::NPC_Vendor_Restock");
	// Restock this NPC char.
	// Then Set the next restock time for this .

	if ( m_pNPC == NULL )
		return false;

	// Make sure that we're a vendor and not a pet
	if ( IsStatFlag(STATF_Pet) || !NPC_IsVendor() )
		return false;

	bool bRestockNow = true;

	if ( !bForce && m_pNPC->m_timeRestock.IsTimeValid() )
	{
		// Restock occurs every 10 minutes of inactivity (unless
		// region tag specifies different time)
		CRegionWorld *region = GetRegion();
		int64 restockIn = 10 * 60 * TICK_PER_SEC;
		if( region != NULL )
		{
			CVarDefCont *vardef = region->m_TagDefs.GetKey("RestockVendors");
			if( vardef != NULL )
				restockIn = vardef->GetValNum();
			if ( region->m_TagDefs.GetKey("NoRestock") != NULL )
				bRestockNow = false;
		}
		if ( m_TagDefs.GetKey("NoRestock") != NULL )
			bRestockNow = false;
		
		if (bRestockNow)
			bRestockNow = ( CServerTime::GetCurrentTime().GetTimeDiff(m_pNPC->m_timeRestock) > restockIn );
	}

	// At restock the containers are actually emptied
	if ( bRestockNow )
	{
		m_pNPC->m_timeRestock.Init();

		for ( size_t i = 0; i < CountOf(sm_VendorLayers); ++i )
		{
			CItemContainer *pCont = GetBank(sm_VendorLayers[i]);
			if ( !pCont )
				return false;

			pCont->Empty();
		}
	}

	if ( bFillStock )
	{
		// An invalid restock time means that the containers are
		// waiting to be filled
		if ( !m_pNPC->m_timeRestock.IsTimeValid() )
		{
			if ( IsTrigUsed(TRIGGER_NPCRESTOCK) )
			{
				CCharBase *pCharDef = Char_GetDef();
				ReadScriptTrig(pCharDef, CTRIG_NPCRestock, true);
			}

			//	we need restock vendor money as well
			GetBank()->Restock();
		}

		// remember that the stock was filled (or considered up-to-date)
		m_pNPC->m_timeRestock.SetCurrentTime();
	}
	return true;
}
Exemplo n.º 17
0
bool CChar::NPC_OnHearPetCmd( LPCTSTR pszCmd, CChar *pSrc, bool fAllPets )
{
	ADDTOCALLSTACK("CChar::NPC_OnHearPetCmd");
	// This should just be another speech block !!!

	// We own this char (pet or hireling)
	// pObjTarget = the m_ActTarg has been set for them to attack.
	// RETURN:
	//  true = we understand this. tho we may not do what we are told.
	//  false = this is not a command we know.
	//  if ( GetTargMode() == CLIMODE_TARG_PET_CMD ) it needs a target.

	if ( !pSrc->IsClient() || m_pPlayer || !m_pNPC )
		return false;

	m_fIgnoreNextPetCmd = false;	// We clear this incase it's true from previous pet cmds.
	TALKMODE_TYPE mode = TALKMODE_SAY;
	if ( OnTriggerSpeech(true, pszCmd, pSrc, mode) )
	{
		m_fIgnoreNextPetCmd = !fAllPets;
		return true;
	}

	static LPCTSTR const sm_Pet_table[] =
	{
		"ATTACK",
		"BOUGHT",
		"CASH",
		"COME",
		"DROP",	// "GIVE" ?
		"DROP ALL",
		"EQUIP",
		"FOLLOW",
		"FOLLOW ME",
		"FRIEND",
		"GO",
		"GUARD",
		"GUARD ME",
		"KILL",
		"PRICE",	// may have args ?
		"RELEASE",
		"SAMPLES",
		"SPEAK",
		"STATUS",
		"STAY",
		"STOCK",
		"STOP",
		"TRANSFER",
		"UNFRIEND"
	};

	PC_TYPE iCmd = static_cast<PC_TYPE>(FindTableSorted(pszCmd, sm_Pet_table, COUNTOF(sm_Pet_table)));
	if ( iCmd < 0 )
	{
		if ( !strnicmp(pszCmd, sm_Pet_table[PC_PRICE], 5) )
			iCmd = PC_PRICE;
		else
			return false;
	}

	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 bTargAllowGround = false;
	bool bCheckCrime = false;
	LPCTSTR pTargPrompt = NULL;
	CCharBase *pCharDef = Char_GetDef();

	switch ( iCmd )
	{
		case PC_ATTACK:
		case PC_KILL:
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_ATT);
			bCheckCrime = true;
			break;

		case PC_COME:
		case PC_GUARD_ME:
		case PC_FOLLOW_ME:
			m_Act_Targ = pSrc->GetUID();
			Skill_Start(NPCACT_FOLLOW_TARG);
			break;

		case PC_FOLLOW:
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FOLLOW);
			break;

		case PC_FRIEND:
			if ( IsStatFlag(STATF_Conjured) )
			{
				pSrc->SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND_SUMMONED));
				return false;
			}
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND);
			break;

		case PC_UNFRIEND:
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_UNFRIEND);
			break;

		case PC_GO:
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_GO);
			bTargAllowGround = true;
			break;

		case PC_GUARD:
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_GUARD);
			bCheckCrime = true;
			break;

		case PC_STAY:
		case PC_STOP:
			Skill_Start(NPCACT_STAY);
			break;

		case PC_TRANSFER:
			if ( IsStatFlag(STATF_Conjured) )
			{
				pSrc->SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_TRANSFER_SUMMONED));
				return true;
			}
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_TRANSFER);
			break;

		case PC_RELEASE:
			SoundChar(CRESND_RAND2);
			if ( IsStatFlag(STATF_Conjured) || (m_pNPC->m_bonded && IsStatFlag(STATF_DEAD)) )
			{
				Delete();
				return true;
			}
			Skill_Start(SKILL_NONE);
			NPC_PetClearOwners();
			ResendTooltip();
			break;
			
		case PC_DROP:
		{
			// Drop backpack items on ground
			// NOTE: This is also called on pet release
			CItemContainer *pPack = GetPack();
			if ( pPack )
			{
				pPack->ContentsDump(GetTopPoint(), ATTR_OWNED);
				break;
			}
			if ( NPC_CanSpeak() )
				Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_CARRYNOTHING));
			return true;
		}

		case PC_DROP_ALL:
			DropAll(NULL, ATTR_OWNED);
			break;

		case PC_SPEAK:
			NPC_OnPetCommand(true, pSrc);
			return true;

		case PC_EQUIP:
			ItemEquipWeapon(false);
			ItemEquipArmor(false);
			break;

		case PC_STATUS:
		{
			if ( !NPC_CanSpeak() )
				break;

			unsigned int iWage = pCharDef->GetHireDayWage();
			CItemContainer *pBank = GetBank();
			TCHAR *pszMsg = Str_GetTemp();
			if ( NPC_IsVendor() )
			{
				CItemContainer *pCont = GetBank(LAYER_VENDOR_STOCK);
				TCHAR *pszTemp1 = Str_GetTemp();
				TCHAR *pszTemp2 = Str_GetTemp();
				TCHAR *pszTemp3 = Str_GetTemp();
				if ( iWage )
				{
					sprintf(pszTemp1, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_1), pBank->m_itEqBankBox.m_Check_Amount);
					sprintf(pszTemp2, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_2), pBank->m_itEqBankBox.m_Check_Amount / iWage);
					sprintf(pszTemp3, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_3), static_cast<int>(pCont->GetCount()));
				}
				else
				{
					sprintf(pszTemp1, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_1), pBank->m_itEqBankBox.m_Check_Amount);
					sprintf(pszTemp2, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_4), pBank->m_itEqBankBox.m_Check_Restock, pBank->GetTimerAdjusted() / 60);
					sprintf(pszTemp3, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_3), static_cast<int>(pCont->GetCount()));
				}
				sprintf(pszMsg, "%s %s %s", pszTemp1, pszTemp2, pszTemp3);
			}
			else if ( iWage )
			{
				sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_DAYS_LEFT), pBank->m_itEqBankBox.m_Check_Amount / iWage);
			}
			Speak(pszMsg);
			return true;
		}

		case PC_CASH:
		{
			// Give up my cash total.
			if ( !NPC_IsVendor() )
				return false;

			CItemContainer *pBank = GetBank();
			if ( pBank )
			{
				unsigned int iWage = pCharDef->GetHireDayWage();
				TCHAR *pszMsg = Str_GetTemp();
				if ( pBank->m_itEqBankBox.m_Check_Amount > iWage )
				{
					sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_GETGOLD_1), pBank->m_itEqBankBox.m_Check_Amount - iWage);
					pSrc->AddGoldToPack(pBank->m_itEqBankBox.m_Check_Amount - iWage);
					pBank->m_itEqBankBox.m_Check_Amount = iWage;
				}
				else
					sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_GETGOLD_2), pBank->m_itEqBankBox.m_Check_Amount);
				Speak(pszMsg);
			}
			return true;
		}

		case PC_BOUGHT:
			if ( !NPC_IsVendor() )
				return false;
			Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_ITEMS_BUY));
			pSrc->GetClient()->addBankOpen(this, LAYER_VENDOR_EXTRA);
			break;

		case PC_PRICE:
			if ( !NPC_IsVendor() )
				return false;
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_SETPRICE);
			break;

		case PC_SAMPLES:
			if ( !NPC_IsVendor() )
				return false;
			Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_ITEMS_SAMPLE));
			pSrc->GetClient()->addBankOpen(this, LAYER_VENDOR_BUYS);
			break;

		case PC_STOCK:
			// Magic restocking container.
			if ( !NPC_IsVendor() )
				return false;
			Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_ITEMS_SELL));
			pSrc->GetClient()->addBankOpen(this, LAYER_VENDOR_STOCK);
			break;

		default:
			return false;
	}

	if ( pTargPrompt )
	{
		pszCmd += strlen(sm_Pet_table[iCmd]);
		GETNONWHITESPACE(pszCmd);
		pSrc->m_pClient->m_tmPetCmd.m_iCmd = iCmd;
		pSrc->m_pClient->m_tmPetCmd.m_fAllPets = fAllPets;
		pSrc->m_pClient->m_Targ_UID = GetUID();
		pSrc->m_pClient->m_Targ_Text = pszCmd;
		pSrc->m_pClient->addTarget(CLIMODE_TARG_PET_CMD, pTargPrompt, bTargAllowGround, bCheckCrime);
		return true;
	}

	// Make some sound to confirm we heard it
	NPC_OnPetCommand(true, pSrc);
	return true;
}
Exemplo n.º 18
0
int CChar::NPC_GetVendorMarkup( const CChar * pChar ) const
{
	ADDTOCALLSTACK("CChar::NPC_GetVendorMarkup");
	// This vendor marks stuff up/down this percentage.
	// Base this on KARMA. Random is calculated at Restock time
	// When vendor sells to players this is the markup value.
	// fBuy: Client buying
	// RETURN:
	//  0-100

	if ( !pChar || IsStatFlag(STATF_Pet) )	// Not on a hired vendor.
		return( 0 );

	CVarDefCont	*pVarRegion = NULL, *pVarCharDef = NULL, *pVarNPC = NULL, *pVarPlayer = NULL;
	CCharBase * pCharDef = Char_GetDef();	// NPC CharDef
	int iMarkUp = 0;
	
	if ( pCharDef )
	{
		// get markup value of NPC-chardef
		pVarCharDef = pCharDef->m_TagDefs.GetKey("VENDORMARKUP");
	}

	pVarPlayer = pChar->m_TagDefs.GetKey("VENDORMARKUP");

	int iHostility = maximum(NPC_GetHostilityLevelToward(pChar), 0);
	iHostility = minimum(iHostility + 15, 100);

	// go thru all possible tweaks

	// Region's markup
	pVarRegion = GetRegion()->m_TagDefs.GetKey("VENDORMARKUP");
	if ( pVarRegion )
	{
		iMarkUp = pVarRegion->GetValNum();
	}

	// NPC's CharDef's markup
	if ( pVarCharDef )
	{
		iMarkUp += pVarCharDef->GetValNum();
	}

	// NPC's personal markup
	pVarNPC = m_TagDefs.GetKey("VENDORMARKUP");
	if ( pVarNPC )
	{
		iMarkUp += pVarNPC->GetValNum();
	}

	// finally: Player char's markup
	pVarPlayer = pChar->m_TagDefs.GetKey("VENDORMARKUP");
	if ( pVarPlayer )
	{
		iMarkUp += pVarPlayer->GetValNum();
	}

	// ensure that the return value is between -100 or positive
	iMarkUp += iHostility;
	if ( iMarkUp < -100 )
		return (-100);
	else
		return ( iMarkUp );
}
Exemplo n.º 19
0
bool CChar::NPC_OnHearPetCmd(LPCTSTR pszCmd, CChar *pSrc, bool bAllPets)
{
	ADDTOCALLSTACK("CChar::NPC_OnHearPetCmd");
	// This should just be another speech block !!!

	// We own this char (pet or hireling)
	// pObjTarget = the m_ActTarg has been set for them to attack.
	// RETURN:
	//  true = we understand this. tho we may not do what we are told.
	//  false = this is not a command we know.
	//  if ( GetTargMode() == CLIMODE_TARG_PET_CMD ) it needs a target.

	if ( !m_pNPC || !pSrc->m_pClient )
		return false;

	m_fIgnoreNextPetCmd = false;	// we clear this incase it's true from previous pet commands
	TALKMODE_TYPE mode = TALKMODE_SAY;
	if ( OnTriggerSpeech(true, pszCmd, pSrc, mode) )
	{
		m_fIgnoreNextPetCmd = !bAllPets;
		return true;
	}

	if ((m_pNPC->m_Brain == NPCBRAIN_BERSERK) && !pSrc->IsPriv(PRIV_GM))
		return false;	// Berserk npcs do not listen to any command (except if src is a GM)

	static LPCTSTR const sm_PetCommands[] =
	{
		"ATTACK",
		"BOUGHT",
		"CASH",
		"COME",
		"DROP",
		"DROP ALL",
		"EQUIP",
		"FOLLOW",
		"FOLLOW ME",
		"FRIEND",
		"GO",
		"GUARD",
		"GUARD ME",
		"KILL",
		"PRICE",
		"RELEASE",
		"SAMPLES",
		"SPEAK",
		"STATUS",
		"STAY",
		"STOCK",
		"STOP",
		"TRANSFER",
		"UNFRIEND"
	};

	PC_TYPE iCmd = static_cast<PC_TYPE>(FindTableSorted(pszCmd, sm_PetCommands, COUNTOF(sm_PetCommands)));
	if ( iCmd < 0 )
	{
		if ( !strnicmp(pszCmd, sm_PetCommands[PC_PRICE], 5) )
			iCmd = PC_PRICE;
		else
			return false;
	}

	if ( !NPC_PetCheckAccess(iCmd, pSrc) )
		return true;

	bool bTargAllowGround = false;
	bool bCheckCrime = false;
	LPCTSTR pTargPrompt = NULL;
	CCharBase *pCharDef = Char_GetDef();

	switch ( iCmd )
	{
		case PC_ATTACK:
		case PC_KILL:
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_ATT);
			bCheckCrime = true;
			break;

		case PC_COME:
		case PC_FOLLOW_ME:
			NPC_OnHearPetCmdTarg(PC_FOLLOW, pSrc, pSrc, NULL, NULL);
			break;

		case PC_FOLLOW:
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FOLLOW);
			break;

		case PC_FRIEND:
			if ( IsStatFlag(STATF_Conjured) )
			{
				pSrc->SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND_SUMMONED));
				return false;
			}
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_FRIEND);
			break;

		case PC_UNFRIEND:
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_UNFRIEND);
			break;

		case PC_GO:
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_GO);
			bTargAllowGround = true;
			break;

		case PC_GUARD:
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_GUARD);
			bCheckCrime = true;
			break;

		case PC_GUARD_ME:
			NPC_OnHearPetCmdTarg(PC_GUARD, pSrc, pSrc, NULL, NULL);
			break;

		case PC_STAY:
		case PC_STOP:
			Skill_Start(NPCACT_STAY);
			break;

		case PC_TRANSFER:
			if ( IsStatFlag(STATF_Conjured) )
			{
				pSrc->SysMessage(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_TRANSFER_SUMMONED));
				return true;
			}
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_TARG_TRANSFER);
			break;

		case PC_RELEASE:
			if ( IsStatFlag(STATF_Conjured) || (m_pNPC->m_bonded && IsStatFlag(STATF_DEAD)) )
			{
				Effect(EFFECT_XYZ, ITEMID_FX_TELE_VANISH, this, 10, 15);
				Sound(SOUND_TELEPORT);
				Delete();
				return true;
			}
			SoundChar(CRESND_NOTICE);
			Skill_Start(SKILL_NONE);
			NPC_PetClearOwners();
			ResendTooltip();
			break;

		case PC_DROP:
		{
			// Drop backpack items on ground
			// NOTE: This is also called on pet release
			CItemContainer *pPack = GetContainer(LAYER_PACK);
			if ( pPack )
			{
				pPack->ContentsDump(GetTopPoint(), ATTR_OWNED);
				break;
			}
			if ( NPC_CanSpeak() )
				Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_CARRYNOTHING));
			return true;
		}

		case PC_DROP_ALL:
			DropAll(NULL, ATTR_OWNED);
			break;

		case PC_SPEAK:
			NPC_PetConfirmCommand(true, pSrc);
			return true;

		case PC_EQUIP:
			ItemEquipWeapon(false);
			ItemEquipArmor(false);
			break;

		case PC_STATUS:
		{
			if ( !NPC_CanSpeak() )
				break;

			CItemContainer *pBank = GetContainerCreate(LAYER_BANKBOX);
			TCHAR *pszMsg = Str_GetTemp();
			if ( NPC_IsVendor() )
			{
				CItemContainer *pCont = GetContainerCreate(LAYER_VENDOR_STOCK);
				TCHAR *pszTemp1 = Str_GetTemp();
				TCHAR *pszTemp2 = Str_GetTemp();
				TCHAR *pszTemp3 = Str_GetTemp();
				if ( pCharDef->m_iHireDayWage )
				{
					sprintf(pszTemp1, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_1), pBank->m_itEqBankBox.m_Check_Amount);
					sprintf(pszTemp2, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_2), pBank->m_itEqBankBox.m_Check_Amount / pCharDef->m_iHireDayWage);
					sprintf(pszTemp3, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_3), static_cast<int>(pCont->GetCount()));
				}
				else
				{
					sprintf(pszTemp1, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_1), pBank->m_itEqBankBox.m_Check_Amount);
					sprintf(pszTemp2, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_4), pBank->m_itEqBankBox.m_Check_Restock, pBank->GetTimerAdjusted() / 60);
					sprintf(pszTemp3, g_Cfg.GetDefaultMsg(DEFMSG_NPC_VENDOR_STAT_GOLD_3), static_cast<int>(pCont->GetCount()));
				}
				sprintf(pszMsg, "%s %s %s", pszTemp1, pszTemp2, pszTemp3);
			}
			else if ( pCharDef->m_iHireDayWage )
			{
				sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_DAYS_LEFT), pBank->m_itEqBankBox.m_Check_Amount / pCharDef->m_iHireDayWage);
			}
			Speak(pszMsg);
			return true;
		}

		case PC_CASH:
		{
			// Give up my cash total.
			if ( !NPC_IsVendor() )
				return false;

			CItemContainer *pBank = GetContainerCreate(LAYER_BANKBOX);
			if ( pBank )
			{
				TCHAR *pszMsg = Str_GetTemp();
				if ( pBank->m_itEqBankBox.m_Check_Amount > pCharDef->m_iHireDayWage )
				{
					sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_GETGOLD_1), pBank->m_itEqBankBox.m_Check_Amount - pCharDef->m_iHireDayWage);
					pSrc->AddGoldToPack(pBank->m_itEqBankBox.m_Check_Amount - pCharDef->m_iHireDayWage);
					pBank->m_itEqBankBox.m_Check_Amount = pCharDef->m_iHireDayWage;
				}
				else
					sprintf(pszMsg, g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_GETGOLD_2), pBank->m_itEqBankBox.m_Check_Amount);
				Speak(pszMsg);
			}
			return true;
		}

		case PC_BOUGHT:
			if ( !NPC_IsVendor() )
				return false;
			Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_ITEMS_BUY));
			pSrc->m_pClient->addBankOpen(this, LAYER_VENDOR_EXTRA);
			break;

		case PC_PRICE:
			if ( !NPC_IsVendor() )
				return false;
			pTargPrompt = g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_SETPRICE);
			break;

		case PC_SAMPLES:
			if ( !NPC_IsVendor() )
				return false;
			Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_ITEMS_SAMPLE));
			pSrc->m_pClient->addBankOpen(this, LAYER_VENDOR_BUYS);
			break;

		case PC_STOCK:
			// Magic restocking container.
			if ( !NPC_IsVendor() )
				return false;
			Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_PET_ITEMS_SELL));
			pSrc->m_pClient->addBankOpen(this, LAYER_VENDOR_STOCK);
			break;

		default:
			return false;
	}

	if ( pTargPrompt )
	{
		pszCmd += strlen(sm_PetCommands[iCmd]);
		GETNONWHITESPACE(pszCmd);
		pSrc->m_pClient->m_tmPetCmd.m_iCmd = iCmd;
		pSrc->m_pClient->m_tmPetCmd.m_fAllPets = bAllPets;
		pSrc->m_pClient->m_Targ_UID = GetUID();
		pSrc->m_pClient->m_Targ_Text = pszCmd;
		pSrc->m_pClient->addTarget(CLIMODE_TARG_PET_CMD, pTargPrompt, bTargAllowGround, bCheckCrime);
		return true;
	}

	// Make some sound to confirm we heard it
	NPC_PetConfirmCommand(true, pSrc);
	return true;
}