Example #1
0
CItemType *CWeaponFireDesc::GetWeaponType (CItemType **retpLauncher) const

//	GetWeaponType
//
//	Returns the item type that best represents this descriptor. For missiles,
//	we return the missile item UNID; for single-shot weapons (including ammo weapons)
//	we return the weapon item UNID

	{
	char *pPos = m_sUNID.GetPointer();

	//	Get the weapon UNID and the ordinal

	DWORD dwUNID = (DWORD)strParseInt(pPos, 0, &pPos);
	ASSERT(*pPos == '/');
	pPos++;
	int iOrdinal = strParseInt(pPos, 0, &pPos);

	//	Get the weapon descriptor

	CWeaponClass *pClass = (CWeaponClass *)g_pUniverse->FindDeviceClass(dwUNID);
	if (pClass == NULL)
		return NULL;

	//	Return the device/launcher

	if (retpLauncher)
		*retpLauncher = pClass->GetItemType();

	//	For launchers, figure out which missile this is

	if (pClass->GetCategory() == itemcatLauncher)
		{
		CWeaponFireDesc *pMissileDesc = pClass->GetVariant(iOrdinal);
		if (pMissileDesc == NULL)
			return NULL;

		//	If we have ammo, then return the ammo type

		CItemType *pAmmoType = pMissileDesc->GetAmmoType();
		if (pAmmoType)
			return pAmmoType;

		//	Otherwise return the launcher (e.g., DM600)

		return pClass->GetItemType();
		}

	//	Otherwise, return the weapon

	else
		return pClass->GetItemType();
	}
void PaintWeaponFrames (CG32bitImage &Image, CItemType *pType, CShip *pPlatform, int iFrames, int x, int y, int cxCell, int cyCell)
	{
	int i, j;

	Metric rFireDist = 18.0 * LIGHT_SECOND;

	//	Make sure we're refueled and in position

	pPlatform->Place(CVector(-rFireDist, 0.0));
	pPlatform->Refuel(pPlatform->GetMaxFuel());
	CItemListManipulator ItemList(pPlatform->GetItemList());

	//	Get the device and weapon fire desc for this item. The call will do the
	//	right thing if this is a missile.

	CDeviceClass *pWeapon;
	int iVariant;
	CWeaponFireDesc *pDesc;
	if (!CDeviceClass::FindWeaponFor(pType, &pWeapon, &iVariant, &pDesc))
		{
		printf("ERROR: Unable to find weapon for ammo.\n");
		return;
		}

	//	Compute the number of ticks that we need to cover the distance

	Metric rDist = rFireDist - (60 * g_KlicksPerPixel);
	Metric rSpeed = pDesc->GetRatedSpeed();
	Metric rTime = (rSpeed > 0.0 ? (rDist / pDesc->GetRatedSpeed()) : 0.0);
	int iFrameToSkip = iFrames / 4;
	int iTicksToHit = (int)(rTime / STD_SECONDS_PER_UPDATE) - iFrameToSkip - 4;

	//	If the item is a missile, create one to fire

	CItemType *pAmmoType = pDesc->GetAmmoType();
	if (pAmmoType)
		{
		CItem MissileItem(pAmmoType, 1);
		ItemList.AddItem(MissileItem);

		pPlatform->OnComponentChanged(comCargo);
		pPlatform->ItemsModified();
		pPlatform->InvalidateItemListAddRemove();
		}

	//	Install the appropriate weapon on the platform

	CItem WeaponItem(pWeapon->GetItemType(), 1);
	ItemList.AddItem(WeaponItem);

	pPlatform->OnComponentChanged(comCargo);
	pPlatform->ItemsModified();
	pPlatform->InvalidateItemListAddRemove();

	pPlatform->InstallItemAsDevice(ItemList);

	//	Select the weapon (we rely on the fact that this is the current
	//	item in the list).

	DeviceNames iDev = pPlatform->SelectWeapon(ItemList.GetItemAtCursor().GetInstalled(), iVariant);
	CInstalledDevice *pInstalledDevice = pPlatform->GetNamedDevice(iDev);
	if (pInstalledDevice == NULL
			|| pInstalledDevice->GetClass()->GetUNID() != pWeapon->GetUNID())
		{
		printf("ERROR: Failed to install %s.\n", pWeapon->GetItemType()->GetNounPhrase(0).GetASCIIZPointer());
		return;
		}

	//	Fire the weapon

	pInstalledDevice->SetTimeUntilReady(0);
	pPlatform->SetWeaponTriggered(iDev);

	//	Update context

	SSystemUpdateCtx Ctx;
	Ctx.bForceEventFiring = true;
	Ctx.bForcePainted = true;

	//	Now loop over the appropriate number of frames

	int xDest = x;
	int yDest = y;
	for (i = 0; i < iFrames; i++)
		{
		//	Update the universe

		g_pUniverse->Update(Ctx);
		if (pPlatform->IsDestroyed())
			printf("Platform destroyed.\n");

		//	Paint

		RECT rcView;
		rcView.left = xDest;
		rcView.top = yDest;
		rcView.right = xDest + (iFrames * cxCell * 2);
		rcView.bottom = yDest + cyCell;

		g_pUniverse->PaintPOV(Image, rcView, CSystem::VWP_NO_STAR_FIELD);

		//	Next

		pPlatform->ClearAllTriggered();

		//	At the half-way mark, update until the missile hits

		if (i == iFrameToSkip)
			{
			for (j = 0; j < iTicksToHit; j++)
				g_pUniverse->Update(Ctx);
			}

		yDest += cyCell;
		}

	//	Skip for a while

	for (j = 0; j < 100; j++)
		{
		g_pUniverse->Update(Ctx);
		if (pPlatform->IsDestroyed())
			printf("Platform destroyed.\n");
		}

	//	Uninstall weapon

	ItemList.Refresh(CItem::NullItem());
	while (ItemList.MoveCursorForward() 
			&& ItemList.GetItemAtCursor().GetType() != pWeapon->GetItemType())
		;

	pPlatform->RemoveItemAsDevice(ItemList);
	}
Example #3
0
CWeaponFireDesc *GetWeaponFireDescArg (ICCItem *pArg)

//	GetWeaponFireDescArg
//
//	If arg is a weapon UNID, then we return the first weapon desc
//	If arg is a missile, then we return the first weapon desc we find for the missile
//	If arg is a list, then the first is a weapon UNID and the second is a missile UNID
//	Returns NULL on error

	{
	int i;
	DWORD dwWeaponUNID;
	DWORD dwVariantUNID;

	//	If the argument is a list, then we get the weapon UNID and the variant
	//	from the list.

	if (pArg->IsList() && pArg->GetCount() >= 2)
		{
		dwWeaponUNID = (DWORD)pArg->GetElement(0)->GetIntegerValue();
		dwVariantUNID = (DWORD)pArg->GetElement(1)->GetIntegerValue();
		}

	//	Otherwise, get the first variant of the weapon

	else
		{
		dwWeaponUNID = (DWORD)pArg->GetIntegerValue();
		dwVariantUNID = 0;
		}

	//	Get the item associated with the UNID

	CItemType *pType = g_pUniverse->FindItemType(dwWeaponUNID);
	if (pType == NULL)
		return NULL;

	//	If this is a weapon, then return the weapon fire desc

	if (pType->GetCategory() == itemcatWeapon || pType->GetCategory() == itemcatLauncher)
		{
		CDeviceClass *pClass = pType->GetDeviceClass();
		if (pClass == NULL)
			return NULL;

		CWeaponClass *pWeapon = pClass->AsWeaponClass();
		if (pWeapon == NULL)
			return NULL;

		//	If variant UNID is 0, then we just want the weapon

		if (dwVariantUNID == 0)
			return pWeapon->GetVariant(0);

		//	Otherwise, we need to find the variant index for the given UNID

		int i;
		for (i = 0; i < pWeapon->GetVariantCount(); i++)
			{
			CWeaponFireDesc *pDesc = pWeapon->GetVariant(i);
			if (pDesc->GetAmmoType()->GetUNID() == dwVariantUNID)
				return pDesc;
			}

		//	If we get this far, then we couldn't find the missile

		return NULL;
		}

	//	Otherwise, if this is a missile, then find the appropriate weapon

	else if (pType->GetCategory() == itemcatMissile)
		{
		for (i = 0; i < g_pUniverse->GetItemTypeCount(); i++)
			{
			CItemType *pWeaponType = g_pUniverse->GetItemType(i);
			CDeviceClass *pClass;
			if (pClass = pWeaponType->GetDeviceClass())
				{
				int iWeaponVariant;
				if ((iWeaponVariant = pClass->GetAmmoVariant(pType)) != -1)
					{
					CWeaponClass *pWeapon = dynamic_cast<CWeaponClass *>(pClass);
					if (pWeapon)
						return pWeapon->GetVariant(iWeaponVariant);
					}
				}
			}

		return NULL;
		}

	//	Otherwise, nothing

	else
		return NULL;
	}