Files
scummvm-cursorfix/engines/ultima/ultima4/controllers/intro_controller.h
2026-02-02 04:50:13 +01:00

437 lines
11 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef ULTIMA4_CONTROLLERS_INTRO_CONTROLLER_H
#define ULTIMA4_CONTROLLERS_INTRO_CONTROLLER_H
#include "ultima/ultima4/controllers/controller.h"
#include "ultima/ultima4/core/observer.h"
#include "ultima/ultima4/filesys/savegame.h"
#include "ultima/ultima4/views/menu.h"
#include "ultima/ultima4/views/textview.h"
#include "ultima/ultima4/views/imageview.h"
#include "ultima/ultima4/views/tileview.h"
#include "common/file.h"
namespace Ultima {
namespace Ultima4 {
class IntroObjectState;
class Tile;
/**
* Binary data loaded from the U4DOS title.exe file.
*/
class IntroBinData {
private:
// disallow assignments, copy construction
IntroBinData(const IntroBinData &);
const IntroBinData &operator=(const IntroBinData &);
void openFile(Common::File &f, const Common::String &name);
public:
IntroBinData();
~IntroBinData();
bool load();
Std::vector<MapTile> _introMap;
byte *_sigData;
byte *_scriptTable;
Tile **_baseTileTable;
byte *_beastie1FrameTable;
byte *_beastie2FrameTable;
Std::vector<Common::String> _introText;
Std::vector<Common::String> _introQuestions;
Std::vector<Common::String> _introGypsy;
};
/**
* Controls the title animation sequences, including the traditional
* plotted "Lord British" signature, the pixelized fade-in of the
* "Ultima IV" game title, as well as the other more simple animated
* features, followed by the traditional animated map and "Journey
* Onward" menu, plus the xU4-specific configuration menu.
*
* @todo
* <ul>
* <li>make initial menu a Menu too</li>
* <li>get rid of mode and switch(mode) statements</li>
* <li>get rid global intro instance -- should only need to be accessed from u4.cpp</li>
* </ul>
*/
class IntroController : public Controller, public Observer<Menu *, MenuEvent &> {
public:
IntroController();
~IntroController() override;
/**
* Initializes intro state and loads in introduction graphics, text
* and map data from title.exe.
*/
bool init();
bool hasInitiatedNewGame();
/**
* Frees up data not needed after introduction.
*/
void deleteIntro();
/**
* Handles keystrokes during the introduction.
*/
bool keyPressed(int key) override;
/**
* Mouse button was pressed
*/
bool mousePressed(const Common::Point &mousePos) override;
byte *getSigData();
/**
* Paints the screen.
*/
void updateScreen();
/**
* Timer callback for the intro sequence. Handles animating the intro
* map, the beasties, etc..
*/
void timerFired() override;
/**
* Preload map tiles
*/
void preloadMap();
/**
* Update the screen when an observed menu is reset or has an item
* activated.
* TODO: Reduce duped code.
*/
void update(Menu *menu, MenuEvent &event) override;
void updateConfMenu(MenuEvent &event);
void updateVideoMenu(MenuEvent &event);
void updateGfxMenu(MenuEvent &event);
void updateSoundMenu(MenuEvent &event);
void updateInputMenu(MenuEvent &event);
void updateSpeedMenu(MenuEvent &event);
void updateGameplayMenu(MenuEvent &event);
void updateInterfaceMenu(MenuEvent &event);
//
// Title methods
//
/**
* Initialize the title elements
*/
void initTitles();
/**
* Update the title element, drawing the appropriate frame of animation
*/
bool updateTitle();
private:
/**
* Draws the small map on the intro screen.
*/
void drawMap();
void drawMapStatic();
void drawMapAnimated();
/**
* Draws the animated beasts in the upper corners of the screen.
*/
void drawBeasties();
/**
* Animates the "beasties". The animate intro image is made up frames
* for the two creatures in the top left and top right corners of the
* screen. This function draws the frame for the given beastie on the
* screen. vertoffset is used lower the creatures down from the top
* of the screen.
*/
void drawBeastie(int beast, int vertoffset, int frame);
/**
* Animates the moongate in the tree intro image. There are two
* overlays in the part of the image normally covered by the text. If
* the frame parameter is "moongate", the moongate overlay is painted
* over the image. If frame is "items", the second overlay is
* painted: the circle without the moongate, but with a small white
* dot representing the anhk and history book.
*/
void animateTree(const Common::String &frame);
/**
* Draws the cards in the character creation sequence with the gypsy.
*/
void drawCard(int pos, int card);
/**
* Draws the beads in the abacus during the character creation sequence
*/
void drawAbacusBeads(int row, int selectedVirtue, int rejectedVirtue);
/**
* Initializes the question tree. The tree starts off with the first
* eight entries set to the numbers 0-7 in a random order.
*/
void initQuestionTree();
/**
* Updates the question tree with the given answer, and advances to
* the next round.
* @return true if all questions have been answered, false otherwise
*/
bool doQuestion(int answer);
/**
* Build the initial avatar player record from the answers to the
* gypsy's questions.
*/
void initPlayers(SaveGame *saveGame);
/**
* Get the text for the question giving a choice between virtue v1 and
* virtue v2 (zero based virtue index, starting at honesty).
*/
Common::String getQuestion(int v1, int v2);
#ifdef IOS_ULTIMA4
public:
/**
* Try to put the intro music back at just the correct moment on iOS;
* don't play it at the very beginning.
*/
void tryTriggerIntroMusic();
#endif
/**
* Initiate a new savegame by reading the name, sex, then presenting a
* series of questions to determine the class of the new character.
*/
void initiateNewGame();
void finishInitiateGame(const Common::String &nameBuffer, SexType sex);
/**
* Starts the gypsys questioning that eventually determines the new
* characters class.
*/
void startQuestions();
void showStory();
/**
* Starts the game.
*/
void journeyOnward();
/**
* Shows an about box.
*/
void about();
#ifdef IOS_ULTIMA4
private:
#endif
/**
* Shows text in the question area.
*/
void showText(const Common::String &text);
/**
* Run a menu and return when the menu has been closed. Screen
* updates are handled by observing the menu.
*/
void runMenu(Menu *menu, TextView *view, bool withBeasties);
/**
* The states of the intro.
*/
enum {
INTRO_TITLES, // displaying the animated intro titles
INTRO_MAP, // displaying the animated intro map
INTRO_MENU, // displaying the main menu: journey onward, etc.
INTRO_ABOUT
} _mode;
enum MenuConstants {
MI_CONF_VIDEO,
MI_CONF_SOUND,
MI_CONF_INPUT,
MI_CONF_SPEED,
MI_CONF_GAMEPLAY,
MI_CONF_INTERFACE,
MI_CONF_01,
MI_VIDEO_CONF_GFX,
MI_VIDEO_02,
MI_VIDEO_03,
MI_VIDEO_07,
MI_VIDEO_08,
MI_GFX_SCHEME,
MI_GFX_TILE_TRANSPARENCY,
MI_GFX_TILE_TRANSPARENCY_SHADOW_SIZE,
MI_GFX_TILE_TRANSPARENCY_SHADOW_OPACITY,
MI_GFX_RETURN,
MI_SOUND_03,
MI_INPUT_03,
MI_SPEED_01,
MI_SPEED_02,
MI_SPEED_03,
MI_SPEED_04,
MI_SPEED_05,
MI_SPEED_06,
MI_SPEED_07,
MI_GAMEPLAY_01,
MI_GAMEPLAY_02,
MI_GAMEPLAY_03,
MI_GAMEPLAY_04,
MI_GAMEPLAY_05,
MI_GAMEPLAY_06,
MI_INTERFACE_01,
MI_INTERFACE_02,
MI_INTERFACE_03,
MI_INTERFACE_04,
MI_INTERFACE_05,
MI_INTERFACE_06,
USE_SETTINGS = 0xFE,
CANCEL = 0xFF
};
ImageView _backgroundArea;
TextView _menuArea;
TextView _extendedMenuArea;
TextView _questionArea;
TileView _mapArea;
Image *_mapScreen;
// menus
Menu _mainMenu;
Menu _confMenu;
Menu _videoMenu;
Menu _gfxMenu;
Menu _soundMenu;
Menu _inputMenu;
Menu _speedMenu;
Menu _gameplayMenu;
Menu _interfaceMenu;
// data loaded in from title.exe
IntroBinData *_binData;
// additional introduction state data
Common::String _errorMessage;
int _answerInd;
int _questionRound;
int _questionTree[15];
int _beastie1Cycle;
int _beastie2Cycle;
int _beastieOffset;
bool _beastiesVisible;
int _sleepCycles;
int _scrPos; /* current position in the script table */
IntroObjectState *_objectStateTable;
bool _justInitiatedNewGame;
Common::String _profileName;
bool _useProfile;
//
// Title defs, structs, methods, and data members
//
enum AnimType {
SIGNATURE,
AND,
BAR,
ORIGIN,
PRESENT,
TITLE,
SUBTITLE,
MAP
};
struct AnimPlot {
uint8 x, y;
uint8 r, g, b, a;
};
struct AnimElement {
void shufflePlotData();
int _rx, _ry; // screen/source x and y
int _rw, _rh; // source width and height
AnimType _method; // render method
int _animStep; // tracks animation position
int _animStepMax;
int _timeBase; // initial animation time
uint32 _timeDelay; // delay before rendering begins
int _timeDuration; // total animation time
Image *_srcImage; // storage for the source image
Image *_destImage; // storage for the animation frame
Std::vector <AnimPlot> _plotData; // plot data
bool _prescaled;
};
/**
* Add the intro element to the element list
*/
void addTitle(int x, int y, int w, int h, AnimType method, uint32 delay, int duration);
/**
* The title element has finished drawing all frames, so delete, remove,
* or free data that is no longer needed
*/
void compactTitle();
/**
* Scale the animation canvas, then draw it to the screen
*/
void drawTitle();
/**
* Get the source data for title elements that have already been initialized
*/
void getTitleSourceData();
/**
* skip the remaining titles
*/
void skipTitles();
Std::vector<AnimElement> _titles; // list of title elements
Std::vector<AnimElement>::iterator _title; // current title element
int _transparentIndex; // palette index for transparency
RGBA _transparentColor; // palette color for transparency
bool _bSkipTitles;
// Temporary place-holder for settings changes
SettingsData _settingsChanged;
};
extern IntroController *g_intro;
} // End of namespace Ultima4
} // End of namespace Ultima
#endif