CurrencyValue CEconomyType::RinHackInc (CSpaceObject *pObj, CurrencyValue iInc) // RinHackInc // // Increment rin { CShip *pPlayerShip = pObj->AsShip(); IShipController *pController = (pPlayerShip ? pPlayerShip->GetController() : NULL); CCurrencyBlock *pMoney = (pController ? pController->GetCurrencyBlock() : NULL); return (pMoney ? pMoney->IncCredits(CONSTLIT("rin"), iInc) : 0); }
void CEconomyType::RinHackSet (CSpaceObject *pObj, const CString &sData) // RinHackSet // // Sets rin { CShip *pPlayerShip = pObj->AsShip(); IShipController *pController = (pPlayerShip ? pPlayerShip->GetController() : NULL); CCurrencyBlock *pMoney = (pController ? pController->GetCurrencyBlock() : NULL); if (pMoney) pMoney->SetCredits(CONSTLIT("rin"), strToInt(sData, 0)); }
CString CEconomyType::RinHackGet (CSpaceObject *pObj) // RinHackGet // // In previous version we used to store rin as object data on the player ship // This hack returns it from the proper place { CShip *pPlayerShip = pObj->AsShip(); IShipController *pController = (pPlayerShip ? pPlayerShip->GetController() : NULL); CCurrencyBlock *pMoney = (pController ? pController->GetCurrencyBlock() : NULL); return (pMoney ? strFromInt((int)pMoney->GetCredits(CONSTLIT("rin"))) : NULL_STR); }
EResults RunEncounter (CUniverse &Universe, CSimViewer &Viewer, CStationType *pDefenderType, CShipClass *pAttackerClass, CSovereign *pAttackerSovereign) { int iTimeOut = DEFAULT_TIME_OUT; // Make sure the universe is clean CString sError; if (Universe.InitGame(0, &sError) != NOERROR) { printf("ERROR: %s", sError.GetASCIIZPointer()); return resultError; } // Create an empty system CSystem *pSystem; if (Universe.CreateEmptyStarSystem(&pSystem) != NOERROR) { printf("ERROR: Unable to create empty star system.\n"); return resultError; } // Create a station in the center of the system CSpaceObject *pStation; if (pSystem->CreateStation(pDefenderType, NULL, CVector(), &pStation) != NOERROR) { printf("ERROR: Unable to create station.\n"); return resultError; } // Set the POV Universe.SetPOV(pStation); pSystem->SetPOVLRS(pStation); // Prepare system Universe.UpdateExtended(); Universe.GarbageCollectLibraryBitmaps(); Universe.StartGame(true); // Now create an attacker some distance away CVector vPos = PolarToVector(mathRandom(0, 359), INITIAL_DISTANCE); CShip *pAttacker; if (pSystem->CreateShip(pAttackerClass->GetUNID(), NULL, NULL, pAttackerSovereign, vPos, CVector(), 0, NULL, NULL, &pAttacker) != NOERROR) { printf("ERROR: Unable to create attacking ship.\n"); return resultError; } // Set the attacker to attack the station IShipController *pController = pAttacker->GetController(); if (pController == NULL) { printf("ERROR: No controller for ship.\n"); return resultError; } pController->AddOrder(IShipController::orderAttackStation, pStation, IShipController::SData()); // Watch the attacker Universe.SetPOV(pAttacker); pSystem->SetPOVLRS(pAttacker); // Update context SSystemUpdateCtx Ctx; Ctx.bForceEventFiring = true; Ctx.bForcePainted = true; // Now keep updating until either the station is destroyed, the ship is destroyed, or we time-out int iTime = 0; int iDestroyedTime = (Viewer.IsEmpty() ? 0 : DESTROY_TIME); bool bDestroyed = false; EResults iResult = resultTimeout; while (iTime < iTimeOut && (!bDestroyed || iDestroyedTime > 0)) { iTime++; Universe.Update(Ctx); if (!Viewer.IsEmpty()) Viewer.PaintViewport(Universe); if (bDestroyed) iDestroyedTime--; else if (pStation->IsDestroyed() || pStation->IsAbandoned()) { bDestroyed = true; iResult = resultDefenderDestroyed; } else if (pAttacker->IsDestroyed()) { bDestroyed = true; iResult = resultAttackerDestroyed; } } // Done return iResult; }
void GenerateWeaponEffectChart (CUniverse &Universe, CXMLElement *pCmdLine) { int i; // Compute the list of weapons to show, making sure we filter to weapons // and missiles only. CItemTypeTable Selection; if (!Selection.Filter(pCmdLine->GetAttribute(CRITERIA_ATTRIB)) || (Selection.IsAll() && !Selection.Filter(CONSTLIT("wm")))) { printf("No entries match criteria.\n"); return; } Selection.Sort(); // Ship to use DWORD dwPlatformUNID; if (!pCmdLine->FindAttributeInteger(SHIP_UNID_ATTRIB, (int *)&dwPlatformUNID)) dwPlatformUNID = WEAPON_PLATFORM_UNID; // Compute some metrics int iFramesPerItem = 10; int cxFrameHorzMargin = 10; int cxMaxDistPerTick = (int)(STD_SECONDS_PER_UPDATE * (LIGHT_SECOND / g_KlicksPerPixel)); int cyFrame = 64; int cxFrame = (2 * cxFrameHorzMargin) + (iFramesPerItem * cxMaxDistPerTick); int iHitEffectFramesPerItem = 5; int cxHitEffect = 128; int cyHitEffect = 128; int cyRowTitle = 20; int cyRow = cyRowTitle + Max(ITEM_ICON_HEIGHT, cyFrame * iFramesPerItem); int cxRow = ITEM_ICON_WIDTH + cxFrame; int iColumns = Max(1, mathSqrt(Selection.GetCount())); int iRows = (Selection.GetCount() + (iColumns - 1)) / iColumns; int cxImage = cxRow * iColumns; int cyImage = cyRow * iRows; // Initialize the output COutputChart Output; Output.SetContentSize(cxImage, cyImage); Output.SetOutputFilespec(pCmdLine->GetAttribute(CONSTLIT("output"))); // Initialize fonts Output.SetStyleFont(STYLE_TITLE, pCmdLine->GetAttribute(CONSTLIT("font"))); Output.SetStyleColor(STYLE_TITLE, CG32bitPixel(0xFF, 0xFF, 0xFF)); // Prepare the universe CSystem *pSystem; if (Universe.CreateEmptyStarSystem(&pSystem) != NOERROR) { printf("ERROR: Unable to create empty star system.\n"); return; } // Create a target in the center of the system CSpaceObject *pStation; CStationType *pTargetType = Universe.FindStationType(TARGET_UNID); if (pTargetType == NULL || pSystem->CreateStation(pTargetType, NULL, CVector(), &pStation) != NOERROR) { printf("ERROR: Unable to create station.\n"); return; } // Create the weapon platform some distance away CSovereign *pPlatformSovereign = Universe.FindSovereign(PLAYER_SOVEREIGN_UNID); CShip *pPlatform; if (pPlatformSovereign == NULL || pSystem->CreateShip(dwPlatformUNID, NULL, NULL, pPlatformSovereign, CVector(-5.0 * LIGHT_SECOND, 0.), CVector(), 0, NULL, NULL, &pPlatform) != NOERROR) { printf("ERROR: Unable to create weapons platform.\n"); return; } // Set the attacker to hold IShipController *pController = pPlatform->GetController(); if (pController == NULL) { printf("ERROR: No controller for ship.\n"); return; } pController->AddOrder(IShipController::orderHold, NULL, IShipController::SData()); pPlatform->SetControllerEnabled(false); // Install the largest possible reactor on the ship CItemType *pReactorType = Universe.FindItemType(REACTOR_UNID); if (pReactorType) { CItem ReactorItem(pReactorType, 1); CItemListManipulator ItemList(pPlatform->GetItemList()); ItemList.AddItem(ReactorItem); pPlatform->OnComponentChanged(comCargo); pPlatform->ItemsModified(); pPlatform->InvalidateItemListAddRemove(); pPlatform->InstallItemAsDevice(ItemList); } // Set the POV Universe.SetPOV(pStation); pSystem->SetPOVLRS(pStation); // Prepare system Universe.UpdateExtended(); Universe.GarbageCollectLibraryBitmaps(); Universe.StartGame(true); // Output each weapon int xOrigin; int yOrigin; CG32bitImage &Image = Output.GetOutputImage(&xOrigin, &yOrigin); const CG16bitFont &TitleFont = Output.GetStyleFont(STYLE_TITLE); CG32bitPixel rgbTitleColor = Output.GetStyleColor(STYLE_TITLE); for (i = 0; i < Selection.GetCount(); i++) { CItemType *pType = Selection.GetItemType(i); // Compute the metrics of this row int xRow = xOrigin + (i % iColumns) * cxRow; int yRow = yOrigin + (i / iColumns) * cyRow; // Paint the weapon title Image.Fill(xRow, yRow, cxRow, cyRow, CG32bitPixel(0x40, 0x40, 0x40)); TitleFont.DrawText(Image, xRow + 8, yRow, rgbTitleColor, pType->GetNounPhrase()); // Paint the frames PaintWeaponFrames(Image, pType, pPlatform, iFramesPerItem, xRow + ITEM_ICON_WIDTH + cxFrameHorzMargin, yRow + cyRowTitle, cxMaxDistPerTick, cyFrame); } // Done Output.Output(); }
void CFleetShipAI::OnObjDestroyedNotify (const SDestroyCtx &Ctx) // OnObjDestroyedNotify // // Deal with an object that has been destroyed { switch (GetCurrentOrder()) { case IShipController::orderEscort: if (Ctx.pObj == GetCurrentOrderTarget()) { CancelCurrentOrder(); // Get the orders of the leader IShipController::OrderTypes iLeaderOrders = IShipController::orderNone; CSpaceObject *pLeaderTarget = NULL; if (Ctx.pObj && Ctx.pObj->GetCategory() == CSpaceObject::catShip) { CShip *pLeader = Ctx.pObj->AsShip(); if (pLeader) iLeaderOrders = pLeader->GetController()->GetCurrentOrderEx(&pLeaderTarget); } // Avenge the leader int iAvengeChance = (pLeaderTarget ? 40 : 100); if (Ctx.pDestroyer && Ctx.pDestroyer != pLeaderTarget && Ctx.pDestroyer->CanAttack() && !m_pShip->IsFriend(Ctx.pDestroyer) && mathRandom(1, 100) <= iAvengeChance) AddOrder(IShipController::orderDestroyTarget, Ctx.pDestroyer, 0); // Take on leader's orders switch (iLeaderOrders) { case IShipController::orderDestroyTarget: case IShipController::orderGuard: if (pLeaderTarget) AddOrder(iLeaderOrders, pLeaderTarget, 0); break; default: break; } // Attack other enemies AddOrder(IShipController::orderAttackNearestEnemy, NULL, 0); } break; case IShipController::orderDock: case IShipController::orderDestroyTarget: case IShipController::orderPatrol: case IShipController::orderGuard: if (Ctx.pObj == GetCurrentOrderTarget()) CancelCurrentOrder(); break; default: break; } // If our target gets destroyed... switch (m_State) { case stateAttackTarget: case stateAttackOnPatrol: if (Ctx.pObj == m_pTarget) SetState(stateNone); break; default: break; } // Reset if (m_pDest == Ctx.pObj) m_pDest = NULL; if (m_pTarget == Ctx.pObj) m_pTarget = NULL; }
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; }
ALERROR CTranscendenceWnd::CreateRandomShip (CSystem *pSystem, CSovereign *pSovereign, CShip **retpShip) // CreateRandomShip // // Creates a random ship { ALERROR error; int i; // Figure out the class CShipClass *pShipClass; if (m_dwIntroShipClass == 0) { do pShipClass = m_Universe.GetShipClass(mathRandom(0, m_Universe.GetShipClassCount()-1)); while (pShipClass->GetScore() > 1000 || pShipClass->IsPlayerShip()); } else { int i; int iIndex = -1; for (i = 0; i < m_Universe.GetShipClassCount(); i++) if (m_Universe.GetShipClass(i)->GetUNID() == m_dwIntroShipClass) { iIndex = i; break; } if (iIndex == -1 || (iIndex + 1) == m_Universe.GetShipClassCount()) pShipClass = m_Universe.GetShipClass(0); else pShipClass = m_Universe.GetShipClass(iIndex + 1); m_dwIntroShipClass = 0; } // Normally we create a single ship, but sometimes we create lots int iCount; int iRoll = mathRandom(1, 100); // Adjust the roll for capital ships if (pShipClass->GetHullMass() >= 10000) iRoll -= 9; else if (pShipClass->GetHullMass() >= 1000) iRoll -= 6; if (iRoll == 100) iCount = mathRandom(30, 60); else if (iRoll >= 98) iCount = mathRandom(10, 20); else if (iRoll >= 95) iCount = mathRandom(5, 10); else if (iRoll >= 90) iCount = mathRandom(2, 5); else iCount = 1; // Create the ships for (i = 0; i < iCount; i++) { CShip *pShip; if ((error = pSystem->CreateShip(pShipClass->GetUNID(), NULL, pSovereign, PolarToVector(mathRandom(0, 359), mathRandom(250, 2500) * g_KlicksPerPixel), NullVector, mathRandom(0, 359), NULL, &pShip))) return error; // Override the controller CIntroShipController *pNewController = new CIntroShipController(this, pShip->GetController()); pShip->SetController(pNewController, false); pNewController->SetShip(pShip); pShip->SetData(CONSTLIT("IntroController"), CONSTLIT("True")); *retpShip = pShip; } return NOERROR; }
void CDockingPorts::UpdateDockingManeuvers (CSpaceObject *pOwner, DockingPort &Port) // UpdateDockingManeuvers // // Updates the motion of a ship docking with a port { CShip *pShip = Port.pObj->AsShip(); ASSERT(pShip); if (pShip == NULL) return; CVector vDest = pOwner->GetPos() + Port.vPos; CVector vDestVel = pOwner->GetVel(); // Figure out how far we are from where we want to be CVector vDelta = vDest - pShip->GetPos(); // Figure out if we're aligned int iFinalRotation = pShip->AlignToRotationAngle(Port.iRotation); // If the docking object is within the appropriate threshold // of the port, then complete the docking sequence. Metric rDelta2 = vDelta.Length2(); if (rDelta2 < DOCKING_THRESHOLD2 && (pShip == g_pUniverse->GetPlayer() || iFinalRotation == pShip->GetRotation())) { pShip->Place(vDest); pShip->UnfreezeControls(); IShipController *pController = pShip->GetController(); pController->SetManeuver(IShipController::NoRotation); Port.iStatus = psInUse; // Tell the owner that somone has docked with it first // (We do this because sometimes we want to handle stuff // in OnObjDocked before we show the player a dock screen) if (pOwner && pOwner->HasOnObjDockedEvent() && pOwner != pShip && !pOwner->IsDestroyed() && pShip->IsSubscribedToEvents(pOwner)) pOwner->FireOnObjDocked(pShip, pOwner); // Set the owner as "explored" (if the ship is the player) if (pShip->IsPlayer()) pOwner->SetExplored(); // Dock pShip->OnDocked(pOwner); // Notify other subscribers pShip->NotifyOnObjDocked(pOwner); } // Otherwise accelerate the ship towards the docking port else { Metric rMaxSpeed = pShip->GetMaxSpeed(); Metric rMinSpeed = rMaxSpeed / 10.0; // We slow down as we get closer Metric rSpeed; if (rDelta2 < FINAL_DOCKING2) rSpeed = rMinSpeed; else if (rDelta2 < FINAL_APPROACH2) { Metric rSpeedRange = rMaxSpeed - rMinSpeed; Metric rDelta = sqrt(rDelta2); rSpeed = rMinSpeed + (rSpeedRange * (rDelta - FINAL_DOCKING) / (FINAL_APPROACH - FINAL_DOCKING)); } else rSpeed = rMaxSpeed; // Figure out the ideal velocity vector that we want to // be following. CVector vIdealVel = vDelta.Normal() * rSpeed; // Calculate the delta v that we need CVector vDeltaV = vIdealVel - pShip->GetVel(); // Rotate if (!pShip->IsPlayer()) { IShipController *pController = pShip->GetController(); // If we're close enough, align to rotation angle if (rDelta2 < FINAL_APPROACH2) pController->SetManeuver(CalcTurnManeuver(iFinalRotation, pShip->GetRotation(), pShip->GetRotationAngle())); // Otherwise, align along delta v else pController->SetManeuver(CalcTurnManeuver(VectorToPolar(vDeltaV), pShip->GetRotation(), pShip->GetRotationAngle())); // Don't let the AI thrust pController->SetThrust(false); } // Accelerate pShip->Accelerate(vDeltaV * pShip->GetMass() / 10000.0, g_SecondsPerUpdate); pShip->ClipSpeed(rSpeed); } }
void CPlayerGameStats::GenerateGameStats (CGameStats &Stats, CSpaceObject *pPlayerShip, bool bGameOver) const // GenerateGameStats // // Generates a stats for everything we track { int j; CShip *pShip = (pPlayerShip ? pPlayerShip->AsShip() : NULL); if (pShip == NULL) return; CPlayerShipController *pPlayer = (CPlayerShipController *)pShip->GetController(); if (pPlayer == NULL) return; CSovereign *pPlayerSovereign = g_pUniverse->FindSovereign(g_PlayerSovereignUNID); if (pPlayerSovereign == NULL) return; // Base stats Stats.Insert(CONSTLIT("Genome"), strCapitalize(GetGenomeName(pPlayer->GetPlayerGenome()))); Stats.Insert(CONSTLIT("Score"), strFormatInteger(CalcEndGameScore(), -1, FORMAT_THOUSAND_SEPARATOR | FORMAT_UNSIGNED)); Stats.Insert(CONSTLIT("Ship class"), pShip->GetNounPhrase(0)); CTimeSpan Time = GetPlayTime(); if (!Time.IsBlank()) Stats.Insert(CONSTLIT("Time played"), Time.Format(NULL_STR)); #ifdef REAL_TIME Time = GetGameTime(); if (!Time.IsBlank()) Stats.Insert(CONSTLIT("Time elapsed in game"), Time.Format(NULL_STR)); #endif // Some combat stats CString sDestroyed = GetStat(ENEMY_SHIPS_DESTROYED_STAT); if (!sDestroyed.IsBlank()) Stats.Insert(CONSTLIT("Enemy ships destroyed"), sDestroyed, CONSTLIT("combat")); sDestroyed = GetStat(FRIENDLY_SHIPS_DESTROYED_STAT); if (!sDestroyed.IsBlank()) Stats.Insert(CONSTLIT("Friendly ships destroyed"), sDestroyed, CONSTLIT("combat")); sDestroyed = GetStat(ENEMY_STATIONS_DESTROYED_STAT); if (!sDestroyed.IsBlank()) Stats.Insert(CONSTLIT("Enemy stations destroyed"), sDestroyed, CONSTLIT("combat")); sDestroyed = GetStat(FRIENDLY_STATIONS_DESTROYED_STAT); if (!sDestroyed.IsBlank()) Stats.Insert(CONSTLIT("Friendly stations destroyed"), sDestroyed, CONSTLIT("combat")); // Add stat for every station destroyed CStatCounterArray CounterArray; CMapIterator i; m_StationStats.Reset(i); while (m_StationStats.HasMore(i)) { SStationTypeStats *pStats; DWORD dwUNID = m_StationStats.GetNext(i, &pStats); CStationType *pType = g_pUniverse->FindStationType(dwUNID); if (pType == NULL) continue; CString sName = pType->GetNounPhrase(0); CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - pType->GetLevel(), sName); if (pType->GetSovereign()->IsEnemy(pPlayerSovereign)) CounterArray.Insert(sName, pStats->iDestroyed, CONSTLIT("Enemy stations destroyed"), sSort); else CounterArray.Insert(sName, pStats->iDestroyed, CONSTLIT("Friendly stations destroyed"), sSort); } CounterArray.GenerateGameStats(Stats); // Add stat for every ship class destroyed CounterArray.DeleteAll(); m_ShipStats.Reset(i); while (m_ShipStats.HasMore(i)) { SShipClassStats *pStats; DWORD dwUNID = m_ShipStats.GetNext(i, &pStats); CShipClass *pClass = g_pUniverse->FindShipClass(dwUNID); if (pClass == NULL) continue; CString sName = pClass->GetNounPhrase(0); CString sSort = strPatternSubst(CONSTLIT("%09d%s"), 100000000 - pClass->GetScore(), sName); if (pStats->iEnemyDestroyed > 0) CounterArray.Insert(sName, pStats->iEnemyDestroyed, CONSTLIT("Enemy ships destroyed"), sSort); if (pStats->iFriendDestroyed > 0) CounterArray.Insert(sName, pStats->iFriendDestroyed, CONSTLIT("Friendly ships destroyed"), sSort); } CounterArray.GenerateGameStats(Stats); // Add stat for every weapon fired m_ItemStats.Reset(i); while (m_ItemStats.HasMore(i)) { SItemTypeStats *pStats; DWORD dwUNID = m_ItemStats.GetNext(i, &pStats); CItemType *pItemType = g_pUniverse->FindItemType(dwUNID); if (pItemType == NULL) continue; CString sName = pItemType->GetNounPhrase(nounShort); CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - pItemType->GetLevel(), sName); // Installed items if (pStats->dwFirstInstalled != INVALID_TIME) Stats.Insert(sName, NULL_STR, CONSTLIT("Items installed"), sSort); if (pStats->iCountFired > 0) Stats.Insert(sName, strFormatInteger(pStats->iCountFired, -1, FORMAT_THOUSAND_SEPARATOR | FORMAT_UNSIGNED), CONSTLIT("Weapons fired"), sSort); } // Stats for player equipment (but only if the game is done) if (bGameOver) { TSortMap<CString, CItem> InstalledItems; // First we generate a sorted list of installed items // (We do this in case there are multiple of the same device/armor so that // we can coalesce them together into a single line). CItemListManipulator ItemList(pShip->GetItemList()); ItemList.ResetCursor(); while (ItemList.MoveCursorForward()) { const CItem &Item(ItemList.GetItemAtCursor()); if (Item.IsInstalled()) { CString sEnhancement = Item.GetEnhancedDesc(pShip); CString sItemName = Item.GetNounPhrase(nounActual | nounCountOnly | nounShort); CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement)); bool bInserted; CItem *pEntry = InstalledItems.SetAt(sLine, &bInserted); if (bInserted) { *pEntry = Item; pEntry->SetCount(1); } else pEntry->SetCount(pEntry->GetCount() + 1); } } // Now add all the installed items to the stats for (j = 0; j < InstalledItems.GetCount(); j++) { // Redo the line now that we know the proper count CString sEnhancement = InstalledItems[j].GetEnhancedDesc(pShip); CString sItemName = InstalledItems[j].GetNounPhrase(nounActual | nounCountOnly); CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement)); // Compute the sort order int iOrder; switch (InstalledItems[j].GetType()->GetCategory()) { case itemcatWeapon: iOrder = 0; break; case itemcatLauncher: iOrder = 1; break; case itemcatShields: iOrder = 2; break; case itemcatArmor: iOrder = 3; break; case itemcatReactor: iOrder = 4; break; case itemcatDrive: iOrder = 5; break; default: iOrder = 6; break; } CString sSort = strPatternSubst(CONSTLIT("%d%03d%s"), iOrder, 100 - InstalledItems[j].GetType()->GetLevel(), sLine); Stats.Insert(sLine, NULL_STR, CONSTLIT("Final equipment"), sSort); } // Add the remaining items ItemList.ResetCursor(); while (ItemList.MoveCursorForward()) { const CItem &Item(ItemList.GetItemAtCursor()); if (!Item.IsInstalled()) { CString sEnhancement = Item.GetEnhancedDesc(pShip); CString sItemName = Item.GetNounPhrase(nounActual | nounCountOnly); CString sLine = (sEnhancement.IsBlank() ? sItemName : strPatternSubst(CONSTLIT("%s [%s]"), sItemName, sEnhancement)); CString sSort = strPatternSubst(CONSTLIT("%03d%s"), 100 - Item.GetType()->GetLevel(), sLine); Stats.Insert(sLine, NULL_STR, CONSTLIT("Final items"), sSort); } } } }
void CDockingPorts::UpdateAll (CSpaceObject *pOwner) // UpdateAll // // UpdateAll { int i, j; for (i = 0; i < m_iPortCount; i++) { if (m_pPort[i].iStatus == psDocking) { CShip *pShip = m_pPort[i].pObj->AsShip(); ASSERT(pShip); if (pShip == NULL) continue; CVector vDest = pOwner->GetPos() + m_pPort[i].vPos; CVector vDestVel = pOwner->GetVel(); // Figure out how far we are from where we want to be CVector vDelta = vDest - pShip->GetPos(); // Figure out if we're aligned int iFinalRotation = pShip->AlignToRotationAngle(m_pPort[i].iRotation); // If the docking object is within the appropriate threshold // of the port, then complete the docking sequence. Metric rDelta2 = vDelta.Length2(); if (rDelta2 < DOCKING_THRESHOLD2 && (pShip == g_pUniverse->GetPlayer() || iFinalRotation == pShip->GetRotation())) { pShip->Place(vDest); pShip->UnfreezeControls(); IShipController *pController = pShip->GetController(); pController->SetManeuver(IShipController::NoRotation); m_pPort[i].iStatus = psInUse; // Tell the owner that somone has docked with it first // (We do this because sometimes we want to handle stuff // in OnObjDocked before we show the player a dock screen) if (pOwner && pOwner->HasOnObjDockedEvent() && pOwner != pShip) pOwner->OnObjDocked(pShip, pOwner); // Dock pShip->OnDocked(pOwner); // Tell all objects in the system that a ship has docked CSystem *pSystem = pShip->GetSystem(); for (j = 0; j < pSystem->GetObjectCount(); j++) { CSpaceObject *pObj = pSystem->GetObject(j); if (pObj && pObj->HasOnObjDockedEvent() && pObj != pShip && pObj != pOwner) pObj->OnObjDocked(pShip, pOwner); } } // Otherwise accelerate the ship towards the docking port else { Metric rMaxSpeed = pShip->GetMaxSpeed(); Metric rMinSpeed = rMaxSpeed / 10.0; // We slow down as we get closer Metric rSpeed; if (rDelta2 < FINAL_DOCKING2) rSpeed = rMinSpeed; else if (rDelta2 < FINAL_APPROACH2) { Metric rSpeedRange = rMaxSpeed - rMinSpeed; Metric rDelta = sqrt(rDelta2); rSpeed = rMinSpeed + (rSpeedRange * (rDelta - FINAL_DOCKING) / (FINAL_APPROACH - FINAL_DOCKING)); } else rSpeed = rMaxSpeed; // Figure out the ideal velocity vector that we want to // be following. CVector vIdealVel = vDelta.Normal() * rSpeed; // Calculate the delta v that we need CVector vDeltaV = vIdealVel - pShip->GetVel(); // Rotate if (pShip != g_pUniverse->GetPlayer()) { IShipController *pController = pShip->GetController(); // If we're close enough, align to rotation angle if (rDelta2 < FINAL_APPROACH2) pController->SetManeuver(CalcTurnManeuver(iFinalRotation, pShip->GetRotation(), pShip->GetRotationAngle())); // Otherwise, align along delta v else pController->SetManeuver(CalcTurnManeuver(VectorToPolar(vDeltaV), pShip->GetRotation(), pShip->GetRotationAngle())); } // Accelerate pShip->Accelerate(vDeltaV * pShip->GetMass() / 10000.0, g_SecondsPerUpdate); pShip->ClipSpeed(rSpeed); } } } }