示例#1
0
int CContainer::ResourceConsume( const CResourceQtyArray * pResources, int iReplicationQty, bool fTest, DWORD dwArg )
{
	ADDTOCALLSTACK("CContainer::ResourceConsume");
	// Consume or test all the required resources.
	// ARGS:
	//	pResources = the resources i need to make 1 replication of this end product.
	// RETURN:
	//  how many whole objects can be made. <= iReplicationQty

	if ( iReplicationQty <= 0 )
		iReplicationQty = 1;
	if ( ! fTest && iReplicationQty > 1 )
	{
		// Test what the max number we can really make is first !
		// All resources must be consumed with the same number.
		iReplicationQty = ResourceConsume( pResources, iReplicationQty, true, dwArg );
	}

	int iQtyMin = INT_MAX;
	for ( size_t i = 0; i < pResources->GetCount(); i++ )
	{
		int iResQty = static_cast<int>(pResources->GetAt(i).GetResQty());
		if (iResQty <= 0) // not sure why this would be true
			continue;

		int iQtyTotal = ( iResQty * iReplicationQty );
		RESOURCE_ID rid = pResources->GetAt(i).GetResourceID();
		if ( rid.GetResType() == RES_SKILL )
		{
			CChar *	pChar	= dynamic_cast <CChar *> (this);
			if ( !pChar )
				continue;
			if ( pChar->Skill_GetBase(static_cast<SKILL_TYPE>(rid.GetResIndex())) < iResQty )
				return 0;
			continue;
		}

		int iQtyCur = iQtyTotal - ContentConsume( rid, iQtyTotal, fTest, dwArg );
		iQtyCur /= iResQty;
		if ( iQtyCur < iQtyMin )
			iQtyMin = iQtyCur;
	}

	if ( iQtyMin == INT_MAX )	// it has no resources ? So i guess we can make it from nothing ?
		return( iReplicationQty );

	return( iQtyMin );
}
示例#2
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;
}
示例#3
0
size_t CContainer::ResourceConsumePart( const CResourceQtyArray * pResources, int iReplicationQty, int iDamagePercent, bool fTest, DWORD dwArg )
{
	ADDTOCALLSTACK("CContainer::ResourceConsumePart");
	// Consume just some of the resources.
	// ARGS:
	//	pResources = the resources i need to make 1 replication of this end product.
	//  iDamagePercent = 0-100
	// RETURN:
	//  BadIndex = all needed items where present.
	// index of the item we did not have.

	if ( iDamagePercent <= 0 )
		return pResources->BadIndex();

	size_t iMissing = pResources->BadIndex();

	size_t iQtyRes = pResources->GetCount();
	for ( size_t i = 0; i < iQtyRes; i++ )
	{
		int iResQty = static_cast<int>(pResources->GetAt(i).GetResQty());
		if (iResQty <= 0) // not sure why this would be true
			continue;

		int iQtyTotal = ( iResQty * iReplicationQty );
		if ( iQtyTotal <= 0 )
			continue;
		iQtyTotal = IMULDIV( iQtyTotal, iDamagePercent, 100 );
		if ( iQtyTotal <= 0 )
			continue;

		RESOURCE_ID rid = pResources->GetAt(i).GetResourceID();
		int iRet = ContentConsume( rid, iQtyTotal, fTest, dwArg );
		if ( iRet )
		{
			iMissing = i;
		}
	}

	return( iMissing );
}
示例#4
0
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;
}
示例#5
0
int CContainer::ContentCount( RESOURCE_ID_BASE rid, DWORD dwArg )
{
	ADDTOCALLSTACK("CContainer::ContentCount");
	// Calculate total (gold or other items) in this recursed container
	return( INT_MAX - ContentConsume( rid, INT_MAX, true, dwArg ));
}