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); }
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; }