From 34a1e32843c7edd5915e3dae97131fdfa3fa1b5b Mon Sep 17 00:00:00 2001 From: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com> Date: Fri, 17 Mar 2023 16:38:08 +0300 Subject: [PATCH] Added in-game credits from Full Tilt. This was kind-of requested a long time ago. --- SpaceCadetPinball/TTextBox.cpp | 40 ++++++++++----------- SpaceCadetPinball/TTextBox.h | 4 +-- SpaceCadetPinball/TTextBoxMessage.cpp | 3 +- SpaceCadetPinball/TTextBoxMessage.h | 3 +- SpaceCadetPinball/control.cpp | 51 +++++++++++++++++++++++++-- SpaceCadetPinball/pb.cpp | 22 +++++++++++- SpaceCadetPinball/pb.h | 3 +- 7 files changed, 97 insertions(+), 29 deletions(-) diff --git a/SpaceCadetPinball/TTextBox.cpp b/SpaceCadetPinball/TTextBox.cpp index 0d0e6eb..555c855 100644 --- a/SpaceCadetPinball/TTextBox.cpp +++ b/SpaceCadetPinball/TTextBox.cpp @@ -71,7 +71,7 @@ void TTextBox::TimerExpired(int timerId, void* caller) } } -void TTextBox::Clear() +void TTextBox::Clear(bool lowPriorityOnly) { gdrv_bitmap8* bmp = BgBmp; if (bmp) @@ -92,16 +92,17 @@ void TTextBox::Clear() timer::kill(Timer); Timer = 0; } - while (CurrentMessage) + while (CurrentMessage && (!lowPriorityOnly || CurrentMessage->LowPriority)) { - TTextBoxMessage* message = CurrentMessage; - TTextBoxMessage* nextMessage = message->NextMessage; + auto message = CurrentMessage; + CurrentMessage = message->NextMessage; delete message; - CurrentMessage = nextMessage; } + if (CurrentMessage) + Draw(); } -void TTextBox::Display(const char* text, float time) +void TTextBox::Display(const char* text, float time, bool lowPriority) { if (!text) return; @@ -124,23 +125,20 @@ void TTextBox::Display(const char* text, float time) if (Timer == -1) Clear(); - auto message = new TTextBoxMessage(text, time); - if (message) + auto message = new TTextBoxMessage(text, time, lowPriority); + if (message->Text) { - if (message->Text) - { - if (CurrentMessage) - PreviousMessage->NextMessage = message; - else - CurrentMessage = message; - PreviousMessage = message; - if (Timer == 0) - Draw(); - } + if (CurrentMessage) + PreviousMessage->NextMessage = message; else - { - delete message; - } + CurrentMessage = message; + PreviousMessage = message; + if (Timer == 0) + Draw(); + } + else + { + delete message; } } } diff --git a/SpaceCadetPinball/TTextBox.h b/SpaceCadetPinball/TTextBox.h index 5970ed9..2cd76b3 100644 --- a/SpaceCadetPinball/TTextBox.h +++ b/SpaceCadetPinball/TTextBox.h @@ -20,8 +20,8 @@ public: TTextBox(TPinballTable* table, int groupIndex); ~TTextBox() override; int Message(MessageCode code, float value) override; - void Clear(); - void Display(const char* text, float time); + void Clear(bool lowPriorityOnly = false); + void Display(const char* text, float time, bool lowPriority = false); void DrawImGui(); private: diff --git a/SpaceCadetPinball/TTextBoxMessage.cpp b/SpaceCadetPinball/TTextBoxMessage.cpp index 97b4583..6bdb433 100644 --- a/SpaceCadetPinball/TTextBoxMessage.cpp +++ b/SpaceCadetPinball/TTextBoxMessage.cpp @@ -2,11 +2,12 @@ #include "TTextBoxMessage.h" #include "pb.h" -TTextBoxMessage::TTextBoxMessage(const char* text, float time) +TTextBoxMessage::TTextBoxMessage(const char* text, float time, bool lowPriority) { NextMessage = nullptr; Time = time; EndTicks = pb::time_ticks + static_cast(time * 1000.0f); + LowPriority = lowPriority; if (text) { const auto textLen = strlen(text) + 1; diff --git a/SpaceCadetPinball/TTextBoxMessage.h b/SpaceCadetPinball/TTextBoxMessage.h index 3d4985f..8bb598f 100644 --- a/SpaceCadetPinball/TTextBoxMessage.h +++ b/SpaceCadetPinball/TTextBoxMessage.h @@ -6,8 +6,9 @@ public: char* Text; float Time; int EndTicks; + bool LowPriority; - TTextBoxMessage(const char* text, float time); + TTextBoxMessage(const char* text, float time, bool lowPriority); ~TTextBoxMessage(); float TimeLeft() const; void Refresh(float time); diff --git a/SpaceCadetPinball/control.cpp b/SpaceCadetPinball/control.cpp index 72b1dfc..2d6a551 100644 --- a/SpaceCadetPinball/control.cpp +++ b/SpaceCadetPinball/control.cpp @@ -916,6 +916,44 @@ void control::pbctrl_bdoor_controller(char key) "I knew it worked too good to be right.", "World's most expensive flippers" }; + static const char* credits[35] + { + "Full Tilt! was created by Cinematronics", + "for Maxis.", + "Cinematronics Team:", + "Programming\nMichael Sandige\nJohn Taylor", + "Art\nJohn Frantz Jr.\nRyan Medeiros", + "Design\nKevin Gliner", + "Sound Effects\nMatt Ridgeway", + "Donald S. Griffin", + "Design Consultant\nMark Sprenger", + "Music\nMatt Ridgeway", + "Producer\nKevin Gliner", + "Voices\nMike McGeary\nWilliam Rice", + "Grand Poobah\nDavid Stafford", + "Special Thanks\nPaula Sandige\nAlex St. John", + "Brad Silverberg\nJeff Camp", + "Danny Thorpe\nGreg Hospelhorn", + "Maxis Team:", + "Producer\nJohn Csicsery", + "Product Manager\nLarry Lee", + "Lead Tester\nMichael Gilmartin", + "QA Manager\nAlan Barton", + "Additional Testing\nJoe Longworth\nScott Shicoff", + "Owen Nelson\nJohn \"Jussi\" Ylinen", + "John Landes\nMarc Meyer", + "Cathy Castro\nKeith Meyer", + "Additional Art\nOcean Quigley", + "Rick Macaraeg\nCharlie Aquilina", + "Art Director\nSharon Barr", + "Install Program\nKevin O'Hare", + "Intro Music", + "Brian Conrad", + "John Csicsery", + "Special Thanks\nSam Poole\nJoe Scirica", + "Jeff Braun\nBob Derber\nAshley Csicsery", + "Tom Forge\nWill \"Burr\" Wright", + }; // Original allowed to enter cheats only before the first launch. std::memmove(&cheatBuffer[0], &cheatBuffer[1], 10); @@ -944,10 +982,19 @@ void control::pbctrl_bdoor_controller(char key) } else if (pb::FullTiltMode && strcmp(bufferEnd - 5, "quote") == 0) { - // A sad developer easter egg type 'cheat' from Full Tilt + // Developer easter egg type 'cheat' from Full Tilt float time = 0; for (auto quote : quotes) - mission_text_box->Display(quote, time += 3); + mission_text_box->Display(quote, time += 3, true); + return; + } + else if (pb::FullTiltMode && strcmp(bufferEnd - 7, "credits") == 0) + { + // Full Tilt in-game credits, shown when idle for 60sec + float time = 0; + for (auto line : credits) + mission_text_box->Display(line, time += 2, true); + pb::CreditsActive = true; return; } else if (strcmp(bufferEnd - 9, "easy mode") == 0) diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index 97f1c14..d249f9b 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -34,7 +34,8 @@ int pb::time_ticks = 0; GameModes pb::game_mode = GameModes::GameOver; float pb::time_now = 0, pb::time_next = 0, pb::time_ticks_remainder = 0; float pb::BallMaxSpeed, pb::BallHalfRadius, pb::BallToBallCollisionDistance; -bool pb::FullTiltMode = false, pb::FullTiltDemoMode = false, pb::cheat_mode = false, pb::demo_mode = false; +float pb::IdleTimerMs = 0; +bool pb::FullTiltMode = false, pb::FullTiltDemoMode = false, pb::cheat_mode = false, pb::demo_mode = false, pb::CreditsActive = false; std::string pb::DatFileName, pb::BasePath; ImU32 pb::TextBoxColor; int pb::quickFlag = 0; @@ -194,6 +195,11 @@ void pb::firsttime_setup() void pb::mode_change(GameModes mode) { + if (CreditsActive) + MissTextBox->Clear(true); + CreditsActive = false; + IdleTimerMs = 0; + switch (mode) { case GameModes::InGame: @@ -283,6 +289,15 @@ void pb::frame(float dtMilliSec) if (dtMilliSec <= 0) return; + if (FullTiltMode && !demo_mode) + { + IdleTimerMs += dtMilliSec; + if (IdleTimerMs >= 60000 && !CreditsActive) + { + PushCheat("credits"); + } + } + float dtSec = dtMilliSec * 0.001f; time_next = time_now + dtSec; timed_frame(dtSec); @@ -563,6 +578,11 @@ void pb::InputDown(GameInput input) if (game_mode != GameModes::InGame || winmain::single_step || demo_mode) return; + if (CreditsActive) + MissTextBox->Clear(true); + CreditsActive = false; + IdleTimerMs = 0; + if (input.Type == InputTypes::Keyboard) control::pbctrl_bdoor_controller(static_cast(input.Value)); diff --git a/SpaceCadetPinball/pb.h b/SpaceCadetPinball/pb.h index 7b951ea..3a01318 100644 --- a/SpaceCadetPinball/pb.h +++ b/SpaceCadetPinball/pb.h @@ -47,7 +47,7 @@ public: static float time_now, time_next, time_ticks_remainder; static float BallMaxSpeed, BallHalfRadius, BallToBallCollisionDistance; static GameModes game_mode; - static bool cheat_mode; + static bool cheat_mode, CreditsActive; static DatFile* record_table; static TPinballTable* MainTable; static bool FullTiltMode, FullTiltDemoMode; @@ -83,5 +83,6 @@ public: static void ShowMessageBox(Uint32 flags, LPCSTR title, LPCSTR message); private: static bool demo_mode; + static float IdleTimerMs; static float BallToBallCollision(const ray_type& ray, const TBall& ball, TEdgeSegment** edge, float collisionDistance); };