bool CDockingPorts::ShipsNearPort (CSpaceObject *pOwner, CSpaceObject *pRequestingObj, const CVector &vPortPos) // ShipsNearPort // // Returns TRUE if there are ships near the given port { int i; CSystem *pSystem = pOwner->GetSystem(); for (i = 0; i < pSystem->GetObjectCount(); i++) { CSpaceObject *pObj = pSystem->GetObject(i); if (pObj && pObj->GetCategory() == CSpaceObject::catShip && !pObj->IsInactive() && pObj != pRequestingObj) { Metric rDist2 = (pObj->GetPos() - vPortPos).Length2(); if (rDist2 < MIN_PORT_DISTANCE2 && !IsDockedOrDocking(pObj)) return true; } } return false; }
void CAutoDefenseClass::Update (CInstalledDevice *pDevice, CSpaceObject *pSource, int iTick, bool *retbSourceDestroyed, bool *retbConsumedItems) // Update // // Update device { if (pDevice->IsReady() && pDevice->IsEnabled()) { int i; // Look for a target CSpaceObject *pBestTarget = NULL; Metric rBestDist2 = MAX_INTERCEPT_DISTANCE * MAX_INTERCEPT_DISTANCE; for (i = 0; i < pSource->GetSystem()->GetObjectCount(); i++) { CSpaceObject *pObj = pSource->GetSystem()->GetObject(i); if (pObj && pObj->GetCategory() == CSpaceObject::catMissile && pObj->GetSource() != pSource && (pObj->GetSource() == NULL || pSource->IsEnemy(pObj->GetSource()))) { CVector vRange = pObj->GetPos() - pSource->GetPos(); Metric rDistance2 = vRange.Dot(vRange); if (rDistance2 < rBestDist2) { pBestTarget = pObj; rBestDist2 = rDistance2; } } } // If we found a target, try to shoot at it if (pBestTarget) { CDeviceClass *pWeapon = GetWeapon(); if (pWeapon) { int iFireAngle; if (pWeapon->IsWeaponAligned(pSource, pDevice, pBestTarget, &iFireAngle)) { pDevice->SetFireAngle(iFireAngle); pWeapon->Activate(pDevice, pSource, pBestTarget, iFireAngle, retbSourceDestroyed, retbConsumedItems); pDevice->SetActivationDelay(m_iRechargeTicks); } } } } }
bool CFerianShipAI::InRangeOfThreat (CSpaceObject **retpThreat) // InRangeOfThreat // // Returns the nearest threat { if (m_pShip->IsDestinyTime(19)) { CSystem *pSystem = m_pShip->GetSystem(); int iDestiny = m_pShip->GetDestiny(); // Get the list of objects that intersect the object SSpaceObjectGridEnumerator i; pSystem->EnumObjectsInBoxStart(i, m_pShip->GetPos(), MAX_THREAT_DIST); // Loop over all objects Metric rNearestDist2 = MAX_THREAT_DIST * MAX_THREAT_DIST2; CSpaceObject *pNearestObj = NULL; while (pSystem->EnumObjectsInBoxHasMore(i)) { CSpaceObject *pObj = pSystem->EnumObjectsInBoxGetNext(i); // If the object is in the bounding box then remember // it so that we can do a more accurate calculation. if (pObj->GetCategory() == CSpaceObject::catShip && (!m_pShip->IsFriend(pObj) || pObj->GetDestiny() < iDestiny) && pObj->CanAttack()) { Metric rDist2 = m_pShip->GetDistance2(pObj); if (rDist2 < rNearestDist2) { pNearestObj = pObj; rNearestDist2 = rDist2; } } } // Done if (pNearestObj) { *retpThreat = pNearestObj; return true; } } return false; }
void DoTradeSim (CUniverse &Universe, CXMLElement *pCmdLine) { ALERROR error; int i, j; CSovereign *pPlayer = Universe.FindSovereign(g_PlayerSovereignUNID); int iSystemSample = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1); bool bLogo = !pCmdLine->GetAttributeBool(NO_LOGO_SWITCH); // For each station type we keep track of the items that it sells and the // various prices that each instances charges. SStationData AllStations; // For each item type we keep track of the stations that sell and/or // buy it. SItemData AllItems; // Generate systems for multiple games for (i = 0; i < iSystemSample; i++) { if (bLogo) printf("pass %d...\n", i+1); CTopologyNode *pNode = Universe.GetFirstTopologyNode(); while (true) { // Create the system CSystem *pSystem; if (error = Universe.CreateStarSystem(pNode, &pSystem)) { printf("ERROR: Unable to create star system.\n"); return; } // For all active stations in the system, get their trading information for (j = 0; j < pSystem->GetObjectCount(); j++) { CSpaceObject *pObj = pSystem->GetObject(j); if (pObj && pObj->GetCategory() == CSpaceObject::catStation) CompileTradeData(pObj, &AllStations, &AllItems); } // Get the next node CString sEntryPoint; pNode = pSystem->GetStargateDestination(CONSTLIT("Outbound"), &sEntryPoint); if (pNode == NULL || pNode->IsEndGame()) break; // Done with old system Universe.DestroySystem(pSystem); } Universe.Reinit(); } if (bLogo) printf("FINAL STATISTICS\n\n"); // Loop over each item and output the best trading strategy printf("Item\tSeller\tSell Price\tBuyer\tBuy Price\tProfit\n"); for (i = 0; i < AllItems.GetCount(); i++) { ComputeAverages(&AllItems[i]); OutputTradingStrategy(AllItems[i]); } }
void GenerateStationPlaceSim (CUniverse &Universe, CXMLElement *pCmdLine) { ALERROR error; int i, j, k; CSovereign *pPlayer = Universe.FindSovereign(g_PlayerSovereignUNID); int iSystemSample = pCmdLine->GetAttributeIntegerBounded(CONSTLIT("count"), 1, -1, 1); bool bLogo = !pCmdLine->GetAttributeBool(NO_LOGO_SWITCH); // Generate systems for multiple games CSymbolTable AllSystems(TRUE, TRUE); for (i = 0; i < iSystemSample; i++) { if (bLogo) printf("pass %d...\n", i+1); CTopologyNode *pNode = Universe.GetFirstTopologyNode(); while (true) { // Create the system CSystem *pSystem; if (error = Universe.CreateStarSystem(pNode, &pSystem)) { printf("ERROR: Unable to create star system.\n"); return; } // Find this system in the table. SPSimSystemInfo *pSystemEntry; if (error = AllSystems.Lookup(pNode->GetSystemName(), (CObject **)&pSystemEntry)) { pSystemEntry = new SPSimSystemInfo; pSystemEntry->sName = pNode->GetSystemName(); pSystemEntry->iLevel = pNode->GetLevel(); pSystemEntry->dwSystemType = pNode->GetSystemTypeUNID(); pSystemEntry->iCount = 1; for (j = 0; j < DIST_BUCKET_COUNT; j++) pSystemEntry->iEnemies[j] = 0; AllSystems.AddEntry(pSystemEntry->sName, pSystemEntry); } else pSystemEntry->iCount++; // For all active stations in the system, count the number of enemy stations // within certain distance buckets for (j = 0; j < pSystem->GetObjectCount(); j++) { CSpaceObject *pObj = pSystem->GetObject(j); // Find any objects that are lootable by the player if (pObj && pObj->GetCategory() == CSpaceObject::catStation && pObj->CanAttack()) { // Count to see how many enemy stations are in range for (k = 0; k < pSystem->GetObjectCount(); k++) { CSpaceObject *pEnemy = pSystem->GetObject(k); if (pEnemy && pEnemy->GetCategory() == CSpaceObject::catStation && pEnemy->CanAttack() && (pEnemy->IsEnemy(pObj) || pObj->IsEnemy(pEnemy))) { Metric rDist = pObj->GetDistance(pEnemy); int iDist = DistToBucketIndex(rDist); if (iDist != -1) { ASSERT(iDist < DIST_BUCKET_COUNT && iDist >= 0); pSystemEntry->iEnemies[iDist]++; int iLSDist = (int)((rDist / LIGHT_SECOND) + 0.5); if (iLSDist < 30) { printf("%s: %s (%x) and %s (%x) within %d ls\n", pSystem->GetName().GetASCIIZPointer(), pObj->GetNounPhrase().GetASCIIZPointer(), pObj->GetID(), pEnemy->GetNounPhrase().GetASCIIZPointer(), pEnemy->GetID(), iLSDist); } } } } } } // Get the next node CString sEntryPoint; pNode = pSystem->GetStargateDestination(CONSTLIT("Outbound"), &sEntryPoint); if (pNode == NULL || pNode->IsEndGame()) break; // Done with old system Universe.DestroySystem(pSystem); } Universe.Reinit(); } if (bLogo) printf("FINAL SYSTEM STATISTICS\n\n"); // Output total value stats printf("Level\tSystem\t<10 ls\t<25 ls\t<50ls\t<100 ls\n"); int iTotals[DIST_BUCKET_COUNT]; for (i = 0; i < DIST_BUCKET_COUNT; i++) iTotals[i] = 0; for (i = 0; i < AllSystems.GetCount(); i++) { SPSimSystemInfo *pSystemEntry = (SPSimSystemInfo *)AllSystems.GetValue(i); printf("%d\t%s", pSystemEntry->iLevel, pSystemEntry->sName.GetASCIIZPointer()); for (j = 0; j < DIST_BUCKET_COUNT; j++) { printf("\t%.2f", (double)pSystemEntry->iEnemies[j] / (double)pSystemEntry->iCount); iTotals[j] += pSystemEntry->iEnemies[j]; } printf("\n"); } // Totals printf("\n"); printf("Within 10 ls: %.2f\n", iTotals[0] / (double)iSystemSample); printf("Within 25 ls: %.2f\n", iTotals[1] / (double)iSystemSample); printf("Within 50 ls: %.2f\n", iTotals[2] / (double)iSystemSample); printf("Within 100 ls: %.2f\n", iTotals[3] / (double)iSystemSample); printf("\n"); }
void CParticleEffect::OnUpdate (Metric rSecondsPerTick) // OnUpdate // // Update the effect { int iTick = GetSystem()->GetTick() + GetDestiny(); // Do not bother updating everything if we are far from the POV bool bFarAway = false; if (g_pUniverse->GetPOV() && g_pUniverse->GetCurrentSystem() == GetSystem()) { Metric rPOVDist2 = (GetPos() - g_pUniverse->GetPOV()->GetPos()).Length2(); Metric rMaxUpdateDist2 = LIGHT_SECOND * LIGHT_SECOND * 3600; bFarAway = (rPOVDist2 > rMaxUpdateDist2); } // Update the particles SParticleArray *pGroup = m_pFirstGroup; while (pGroup) { SParticleType *pType = pGroup->pType; // Max distance for a particle in this group Metric rMaxDist2 = pType->rRadius * pType->rRadius; Metric rMinDist2 = pType->rHoleRadius * pType->rHoleRadius; // If the particle field causes damage then we need to // compute its average density int iDensity = 0; if (pType->m_fDamage) { Metric rRadius2 = pType->rRadius * pType->rRadius; Metric rArea = rRadius2 / (LIGHT_SECOND * LIGHT_SECOND); iDensity = (int)(4 * pGroup->iCount / rArea); } // Get an array of objects in the particle field that // may influence the particles CSpaceObject *Objects[ctMaxObjsInField]; int iObjCount = 0; if (!bFarAway && (pType->m_fWake || pType->m_fDamage)) { Metric rMaxInfluenceDist2 = rMaxDist2; for (int i = 0; i < GetSystem()->GetObjectCount(); i++) { CSpaceObject *pObj = GetSystem()->GetObject(i); if (pObj && pObj->GetCategory() == catShip && pObj != this) { CVector vDist = GetPos() - pObj->GetPos(); Metric rDist2 = vDist.Length2(); if (rDist2 < rMaxInfluenceDist2 && (pObj->GetVel().Length2() > g_KlicksPerPixel) && iObjCount < ctMaxObjsInField) { Objects[iObjCount++] = pObj; // See if the object should take damage if (pType->m_fDamage) { CVector vDeltaV = pObj->GetVel() - GetVel(); int iSpeed = (int)(vDeltaV.Length() / g_KlicksPerPixel); if (iSpeed == 0) iSpeed = 1; if (mathRandom(1, 1000) < (iDensity * iSpeed)) { pObj->Damage(this, pObj->GetPos(), VectorToPolar(vDeltaV), pType->Damage); } } } } } } // If we're computing drag then we need to compute the new velocity // of the whole particle system CVector vNewVel; if (pType->m_fDrag) vNewVel = GetVel() * g_SpaceDragFactor; // Iterate over all particles SParticle *pParticle = pGroup->pParticles; SParticle *pEnd = pParticle + pGroup->iCount; while (pParticle < pEnd) { if (pParticle->IsValid()) { // Lifespan. If we're far away and we're regenerating, // then don't bother to compute lifespan. if (pType->m_fLifespan && !(bFarAway && (pType->m_fRegenerate && pType->iRegenerationTimer))) { if (--pParticle->iLifeLeft == 0) { // Do we regenerate? if (pType->m_fRegenerate && pType->iRegenerationTimer) { pParticle->iLifeLeft = pType->iLifespan; pParticle->vPos = NullVector; // Speed Metric rSpeed = mathRandom(1, 100) * (pType->rAveSpeed / 100.0); if (pType->iDirection == -1) pParticle->vVel = PolarToVector(mathRandom(0, 359), rSpeed); else { int iAngle = (pType->iDirection + 360 + mathRandom(0, 2 * pType->iDirRange) - pType->iDirRange) % 360; pParticle->vVel = PolarToVector(iAngle, rSpeed); } } // Otherwise we die else { pParticle->iLifeLeft = -1; pGroup->iAlive--; pParticle++; continue; } } } // Update the position if (!bFarAway) { pParticle->vPos = pParticle->vPos + pParticle->vVel; // Change the velocity to keep the particles within // the radius if (pType->m_fMaxRadius) { Metric rDist2 = pParticle->vPos.Length2(); if (pType->m_fMaxRadius && rDist2 > rMaxDist2) { CVector vChange = pParticle->vPos + g_KlicksPerPixel * pParticle->vPos.Perpendicular().Normal(); pParticle->vVel = pParticle->vVel - (0.00005 * vChange); } else if (rDist2 < rMinDist2) { CVector vNormal = pParticle->vPos.Normal(); CVector vChange = g_KlicksPerPixel * (400 * vNormal - 50 * vNormal.Perpendicular()); pParticle->vVel = pParticle->vVel + (0.00005 * vChange); } else pParticle->vVel = pParticle->vVel * pType->rDampening; } if (pType->m_fDrag) { // Compute the new absolute velocity (after drag) CVector vAbsolute = pType->rDampening * (pParticle->vVel + GetVel()); // The particle velocity is the absolute vel minus the // system velocity. pParticle->vVel = vAbsolute - vNewVel; } // Change the velocity based on influences from other objects if (pType->m_fWake && (iTick % 4) == 0) { for (int i = 0; i < iObjCount; i++) { Metric rDist2 = (Objects[i]->GetPos() - (pParticle->vPos + GetPos())).Length2(); if (rDist2 < g_KlicksPerPixel * g_KlicksPerPixel * 1000) { if (Objects[i]->GetVel().Dot(pParticle->vVel) < Objects[i]->GetVel().Length2()) pParticle->vVel = pParticle->vVel + 0.2 * Objects[i]->GetVel(); } } } } } pParticle++; } // Regeneration timer if (pType->m_fRegenerate && pType->iRegenerationTimer) pType->iRegenerationTimer--; // If there are no more particles left alive in this group then kill // the group if (pGroup->iAlive == 0) { SParticleArray *pNext = pGroup->pNext; SParticleArray *pPrev = NULL; // Find the previous group SParticleArray *pFind = m_pFirstGroup; while (pFind != pGroup) { if (pPrev) pPrev = pPrev->pNext; else pPrev = m_pFirstGroup; pFind = pFind->pNext; } // Fix up the linked list if (pPrev) pPrev->pNext = pNext; else m_pFirstGroup = pNext; // Delete the group delete pGroup; pGroup = pNext; } // Otherwise, next group else pGroup = pGroup->pNext; } // If we have no more groups then we destroy ourselves if (m_pFirstGroup == NULL) { Destroy(removedFromSystem, NULL); return; } // If we're moving, slow down SetVel(CVector(GetVel().GetX() * g_SpaceDragFactor, GetVel().GetY() * g_SpaceDragFactor)); }
ALERROR CTranscendenceWnd::StartIntro (void) // StartIntro // // Start introduction { ALERROR error; int i; ClearDebugLines(); // Use widescreen topology int cyBarHeight = (g_cyScreen - INTRO_DISPLAY_HEIGHT) / 2; m_rcIntroTop.top = 0; m_rcIntroTop.left = 0; m_rcIntroTop.bottom = cyBarHeight; m_rcIntroTop.right = g_cxScreen; m_rcIntroMain.top = cyBarHeight; m_rcIntroMain.left = 0; m_rcIntroMain.bottom = g_cyScreen - cyBarHeight; m_rcIntroMain.right = g_cxScreen; m_rcIntroBottom.top = g_cyScreen - cyBarHeight; m_rcIntroBottom.left = 0; m_rcIntroBottom.bottom = g_cyScreen; m_rcIntroBottom.right = g_cxScreen; m_Screen.DrawRectFilled(m_rcIntroTop.left, m_rcIntroTop.top,m_rcIntroTop.right, m_rcIntroTop.bottom, CGImage::RGBColor(0, 0, 0)); m_Screen.DrawRectFilled(m_rcIntroBottom.left, m_rcIntroBottom.top,m_rcIntroBottom.right, m_rcIntroBottom.bottom, CGImage::RGBColor(0, 0, 0)); // Create the High-Score display RECT rcRect; rcRect.left = m_rcMainScreen.left + HIGHSCORE_DISPLAY_X; rcRect.top = m_rcMainScreen.top + HIGHSCORE_DISPLAY_Y; rcRect.right = rcRect.left + HIGHSCORE_DISPLAY_WIDTH; rcRect.bottom = rcRect.top + HIGHSCORE_DISPLAY_HEIGHT; m_HighScoreDisplay.Init(rcRect, m_pHighScoreList, m_iLastHighScore); m_HighScoreDisplay.SetFontTable(&m_Fonts); m_HighScoreDisplay.Update(); // Create the player display m_PlayerDisplay.Init(this, m_rcIntroTop, m_Options.bDebugMode); // Create the buttons m_ButtonBar.Init(); CString sContinueLabel = ComputeLoadGameLabel(&m_bSavedGame); m_ButtonBar.AddButton(CMD_CONTINUE_OLD_GAME, CONSTLIT("Continue Game"), sContinueLabel, CONSTLIT("C"), 0, CButtonBarData::alignLeft); if (sContinueLabel.IsBlank()) m_ButtonBar.SetVisible(0, false); m_ButtonBar.AddButton(CMD_START_NEW_GAME, CONSTLIT("New Game"), CONSTLIT("Begin a New Game"), CONSTLIT("N"), 1, CButtonBarData::alignCenter); m_ButtonBar.AddButton(CMD_QUIT_GAME, CONSTLIT("Quit"), CONSTLIT("Exit Transcendence"), CONSTLIT("Q"), 2, CButtonBarData::alignRight); m_ButtonBarDisplay.SetFontTable(&m_Fonts); m_ButtonBarDisplay.Init(this, &m_ButtonBar, m_rcIntroBottom); // Create an empty system if (error = m_Universe.CreateEmptyStarSystem(&m_pIntroSystem)) { ASSERT(false); return error; } m_Universe.SetCurrentSystem(m_pIntroSystem); CSovereign *pSovereign1 = m_Universe.FindSovereign(g_PlayerSovereignUNID); CSovereign *pSovereign2 = m_Universe.FindSovereign(g_PirateSovereignUNID); // Create a couple of random enemy ships CShip *pShip1; CShip *pShip2; if ((error = CreateRandomShip(m_pIntroSystem, pSovereign1, &pShip1))) { ASSERT(false); return error; } if ((error = CreateRandomShip(m_pIntroSystem, pSovereign2, &pShip2))) { ASSERT(false); return error; } // Make the ships attack each other for (i = 0; i < m_pIntroSystem->GetObjectCount(); i++) { CSpaceObject *pObj = m_pIntroSystem->GetObject(i); if (pObj && pObj->GetCategory() == CSpaceObject::catShip && !pObj->GetData(CONSTLIT("IntroController")).IsBlank()) { CShip *pShip = pObj->AsShip(); if (pShip) { IShipController *pController = pShip->GetController(); if (pShip->GetSovereign() == pSovereign1) pController->AddOrder(IShipController::orderDestroyTarget, pShip2, 0); else pController->AddOrder(IShipController::orderDestroyTarget, pShip1, 0); } } } // Other initialization m_bOverwriteGameDlg = false; m_rcOverwriteGameDlg.left = m_rcIntroMain.left + (RectWidth(m_rcIntroMain) - DIALOG_WIDTH) / 2; m_rcOverwriteGameDlg.top = m_rcIntroMain.top + (RectHeight(m_rcIntroMain) - DIALOG_HEIGHT) / 2; m_rcOverwriteGameDlg.right = m_rcOverwriteGameDlg.left + DIALOG_WIDTH; m_rcOverwriteGameDlg.bottom = m_rcOverwriteGameDlg.top + DIALOG_HEIGHT; int cxMid = m_rcOverwriteGameDlg.left + (DIALOG_WIDTH / 2); m_rcOverwriteGameOK.left = cxMid - DIALOG_SPACING_X - DIALOG_BUTTON_WIDTH; m_rcOverwriteGameOK.top = m_rcOverwriteGameDlg.bottom - DIALOG_SPACING_Y - DIALOG_BUTTON_HEIGHT; m_rcOverwriteGameOK.right = m_rcOverwriteGameOK.left + DIALOG_BUTTON_WIDTH; m_rcOverwriteGameOK.bottom = m_rcOverwriteGameOK.top + DIALOG_BUTTON_HEIGHT; m_rcOverwriteGameCancel = m_rcOverwriteGameOK; m_rcOverwriteGameCancel.left = cxMid + DIALOG_SPACING_X; m_rcOverwriteGameCancel.right = m_rcOverwriteGameCancel.left + DIALOG_BUTTON_WIDTH; // No sound m_Universe.SetSound(false); // Set the POV to one of them m_Universe.SetPOV(pShip1); m_iTick = 0; m_iLastShipCreated = m_iTick; m_State = gsIntro; // Show the cursor SDL_ShowCursor(true); return NOERROR; }