Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e1b73b9
The computer conversation panel now shows what the game shows:
vrifftech Oct 24, 2026
9913eb3
The experience a creature's next level needs is exptable.2da's XP at
vrifftech Oct 24, 2026
7c35ff4
One pulse, shared by every GUI and advanced in real time, replaces the
vrifftech Oct 24, 2026
5f87f51
- #1 reply conditions after the entry's scripts (both panels, both
vrifftech Oct 24, 2026
aa86f54
- #6 FIXED: the character sheet takes the experience table's amount a…
vrifftech Oct 24, 2026
f61560c
- #3 FIXED (pulse): a selected Button's or ToggleButton's text pulses…
vrifftech Oct 24, 2026
5b539df
- Keyboard skip: FIXED. Return and keypad Enter skip the shown entry …
vrifftech Oct 24, 2026
a6322ca
Test fix
vrifftech Oct 24, 2026
53b837d
A stream that runs out of queued sound now plays on from where it
vrifftech Oct 26, 2026
9f0ffcf
The sound now starts on the movie's first update, with its first frame
vrifftech Oct 26, 2026
ba1ad97
Every control is now laid out from the box's corner, where the layout
vrifftech Oct 26, 2026
d1fb5cc
the overview showed Equip labelled Close beside the back button: two …
vrifftech Oct 26, 2026
d7cea7f
- The cinematic panel's reply rows are cleared as an entry, or the empty
vrifftech Oct 26, 2026
95ea419
A click ends a movie at once, but only its picture: its sound played on
vrifftech Oct 26, 2026
74de1ab
A movie now switches
vrifftech Oct 26, 2026
dc0f298
A clip whose frames share one format and rate now goes into one buffer
vrifftech Oct 26, 2026
b32a3bf
every loading screen shown with music starts it, and the
vrifftech Oct 26, 2026
9b02687
While a conversation that is an animated cutscene owns the screen, a
vrifftech Oct 26, 2026
6256cce
test fix
vrifftech Oct 26, 2026
fce4918
- The camera wait belongs to the clip the entry's camera request name…
vrifftech Oct 27, 2026
f152f9c
A conversation request is done once it has started its conversation, and
vrifftech Oct 28, 2026
3679f6e
Fix the Endar Spire duel, door visibility and saved placed objects
vrifftech Oct 28, 2026
bce8cb5
Adding instruction limit to script execution
vrifftech Oct 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions include/reone/audio/source.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,17 @@ class AudioSource : boost::noncopyable {

~AudioSource() { deinit(); }

/**
* Prepares the sound. A clip whose frames share one format and rate goes
* into one buffer whole and plays on the device's clock; any other clip is
* streamed a few frames at a time.
*/
void init();
/**
* Refills a stream's queue with the sound that follows. A stream that ran
* out of queued sound since the last refill, because the frame came late,
* plays on from where it ran out.
*/
void render();

void play();
Expand All @@ -53,6 +63,8 @@ class AudioSource : boost::noncopyable {
void startPaused();

void setPosition(glm::vec3 position);
/** Sets whether the source starts again from the beginning when it ends. */
void setLooping(bool loop);
/** Scales the gain the source was created with; used to fade it out. */
void setGainScale(float scale);
/** Plays the source at \p pitch times its own rate, which raises or lowers its pitch. */
Expand All @@ -70,6 +82,8 @@ class AudioSource : boost::noncopyable {

bool _inited {false};
bool _playing {false};
/** Paused, or created paused, and not resumed since. */
bool _paused {false};

std::vector<uint32_t> _buffers;
bool _streaming {false};
Expand Down
25 changes: 23 additions & 2 deletions include/reone/game/areamusicplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <array>
#include <cstdint>
#include <functional>
#include <memory>
#include <optional>
#include <string>
Expand Down Expand Up @@ -64,6 +65,15 @@ class AreaMusicPlayer : boost::noncopyable {
*/
void init(bool tsl);

/**
* What hands over the playing load-screen music when the background
* music asks for the same track; it returns none when it does not. Only
* TSL sets it.
*/
void setLoadMusicHandover(std::function<std::shared_ptr<audio::AudioSource>(const std::string &)> handover) {
_loadMusicHandover = std::move(handover);
}

/**
* Take the area being entered. Its music and ambient loop wait for the
* start; whether each is on starts from what the area asks for.
Expand All @@ -73,6 +83,12 @@ class AreaMusicPlayer : boost::noncopyable {
void start();
/** Fade out the music, end the ambient loop and forget the pending restart and battle state. */
void stopSounds();
/**
* A movie starts. As stopSounds once the area's sounds have started;
* before then the music is left to start on arrival, but the battle
* music, the pending restart and the ambient loop are switched off.
*/
void stopSoundsForMovie();
/** Stop for the area being left; nothing plays until the next area is loaded and started. */
void unload();
/** Advance the fades, repeat ended tracks and restart an ended ambient loop. */
Expand Down Expand Up @@ -133,6 +149,7 @@ class AreaMusicPlayer : boost::noncopyable {
};

ServicesView &_services;
std::function<std::shared_ptr<audio::AudioSource>(const std::string &)> _loadMusicHandover;

// Tables

Expand Down Expand Up @@ -203,8 +220,12 @@ class AreaMusicPlayer : boost::noncopyable {
bool isMusicPlaying();
/** Whether the ambient loop sounds, a fading loop until its fade ends. */
bool isAmbientPlaying();
/** Plays the music track \p resRef; false when it does not play. */
bool playTrack(const std::string &resRef);
/**
* Plays the music track \p resRef; false when it does not play.
* @param takeLoadMusic whether the playing load-screen music of the same
* track is taken over instead, as the background music does
*/
bool playTrack(const std::string &resRef, bool takeLoadMusic = false);
/** Fades out the music that is playing. */
void fadeAndStop();
/** Plays one of the track's stingers at random, once the area has been arrived in. */
Expand Down
6 changes: 4 additions & 2 deletions include/reone/game/combat.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,8 @@ class Combat {
* round: a round the partner began, or one of its own, ends. A round the
* two share starts again from the beginning for both; a partner whose
* round was its own gets a side, with no command yet, in the attacker's
* round, held for the attack's pause. An engaged partner owning no round
* is held for the attack's pause.
* round, held for the attack's pause and free to act as soon as that hold
* ends. An engaged partner owning no round is held for the attack's pause.
*/
bool engagePhysicalTarget(const Creature &attacker, Object &target, int pauseMilliseconds);
/** The round the action runs in is engaged. */
Expand All @@ -319,6 +319,8 @@ class Combat {
bool awaitsRoundEnd(const Creature &actor, std::optional<std::reference_wrapper<const Action>> self) const;
/** Whether the creature has a command in a round that has not ended. */
bool ownsRound(const Creature &actor) const;
/** The action carries out its creature's side of a round that has not ended. */
bool runsRound(const Action &action) const;
/** The creature owns a round that no action still waiting in its queue belongs to. */
bool ownsDetachedRound(const Creature &actor) const;
/** The creature takes part in an engaged (paired) round. */
Expand Down
65 changes: 55 additions & 10 deletions include/reone/game/game.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ class Game : boost::noncopyable {
* that one is due.
*/
bool consumeTimingDiscontinuity();
/**
* The world waits while the window is out of focus: none of that time
* passes in it, and its clock takes up again from the next update.
*/
void holdWorldClock() { _worldClockSample.reset(); }

/**
* Play a movie, ending any module transition movies.
Expand Down Expand Up @@ -464,6 +469,8 @@ class Game : boost::noncopyable {

void openMainMenu();
void openInGame();
/** Covers the screen with \p color at opacity \p alpha, over what is drawn so far. */
void renderScreenFill(const glm::vec3 &color, float alpha);

bool hasPlayableRuntimeSession() const { return _runtimeSessionPlayable; }

Expand Down Expand Up @@ -554,6 +561,20 @@ class Game : boost::noncopyable {
// END KotOR I Pazaak lifecycle

void startCharacterGeneration();

/**
* Sets the music the next loading screens play to the one the
* loading-screen table gives the module named \p moduleName.
*/
void setLoadMusicForModule(const std::string &moduleName);
/** Stops the loading-screen music; the track stays set for the next loading screen. */
void stopLoadMusic();
/**
* Fades the menu music out for a fixed wait and then stops it, holding
* everything else meanwhile, as starting a new game or loading a save
* from the main menu does.
*/
void fadeOutMenuMusic();
void startDialog(const std::shared_ptr<Object> &owner, const std::string &resRef,
GlobalFade::DialogTicket admission = {},
const std::shared_ptr<Object> &listener = nullptr);
Expand Down Expand Up @@ -584,7 +605,8 @@ class Game : boost::noncopyable {
StatusSummaryAccumulator &statusSummary() { return _statusSummary; }
/**
* A status summary was taken down or passed by unseen. TSL then looks for
* the story's reaction to the player character's alignment.
* the story's reaction to the player character's alignment, and, the first
* time the player's own character can level up, runs the level-up dialog.
*/
void finishStatusSummaryCycle();

Expand All @@ -607,6 +629,11 @@ class Game : boost::noncopyable {
return _screen == Screen::Conversation;
}

/** A conversation owns the screen, and its dialog is an animated cutscene. */
bool isAnimatedCutsceneShowing() const {
return isConversationActive() && _conversation && _conversation->isAnimatedCutscene();
}

/** The object is the running dialogue's current speaker or listener. */
bool isConversationSpeakerOrListener(const Object &object) const {
return isConversationActive() && _conversation == _dialog.get() && _dialog->isSpeakerOrListener(object);
Expand All @@ -628,6 +655,11 @@ class Game : boost::noncopyable {
return _pointer->type();
}

/** Where the pointer last moved to, in screen coordinates. */
glm::ivec2 pointerPosition() const {
return _pointer->position();
}

bool relativeMouseMode() const;

// Module loading
Expand Down Expand Up @@ -671,6 +703,8 @@ class Game : boost::noncopyable {
std::string startWaypoint;
uint32_t pauseDay {0};
uint32_t pauseTime {0};
/** The loading-screen music the save asks for. */
std::string loadMusic;
};

std::unique_ptr<resource::SaveSessionState> session;
Expand Down Expand Up @@ -1858,17 +1892,11 @@ class Game : boost::noncopyable {
bool _showEndGameGui {true};
uint32_t _lastPartyMemberTempKilled {script::kObjectInvalid};
/**
* How fast the world, its presentation and the fade run during the death
* sequence. The first title slows play from full speed to a fifth over
* the first four seconds of real time; its time and rate carry over to
* later deaths for the program's lifetime. The second title runs at a quarter
* while its gameover panel is up.
* How fast the world, its presentation and the fade run: a quarter while
* the second title's gameover panel is up, else full speed. The first
* title's death sequence keeps full speed.
*/
float _deathTimeScale {1.0f};
uint32_t _deathSequenceSample {0};
float _deathSequenceSeconds {0.0f};
float _deathSlowRate {0.0f};
bool _deathSequenceStarting {true};
std::unique_ptr<ContainerGUI> _container;
std::unique_ptr<PartySelection> _partySelect;
std::unique_ptr<SaveLoad> _saveLoad;
Expand Down Expand Up @@ -1920,6 +1948,16 @@ class Game : boost::noncopyable {
std::string _musicResRef;
std::shared_ptr<audio::AudioSource> _music;
AreaMusicPlayer _areaMusic;
/**
* The music loading screens play. It is set by a new game, a save load
* and the module picker, and kept from one load, and one session, to the
* next.
*/
std::string _loadMusicResRef;
/** The loading-screen music that is playing, or paused under a movie. */
std::shared_ptr<audio::AudioSource> _loadMusic;
/** The coming module load follows transition movies, and plays no loading-screen music. */
bool _loadComesWithMovies {false};

// END Audio

Expand All @@ -1946,6 +1984,9 @@ class Game : boost::noncopyable {
std::optional<std::reference_wrapper<const Creature>> subject, bool hideActions,
bool &hidden) const;

/** TSL: runs the level-up dialog script the first time only. */
void runLevelUpDialogOnce();

void advanceWorldTime(double dt);
void advanceTimeStopClock(double dt);
void advancePlayedTime(float dt);
Expand Down Expand Up @@ -2044,6 +2085,10 @@ class Game : boost::noncopyable {
bool loadParty();
void loadNextModule();
void playMusic(const std::string &resRef);
/** Starts, or resumes, the loading-screen music, as a loading screen does when it is shown. */
void startLoadMusic();
/** Hands the playing loading-screen music over to the background music when it asks for the same track. */
std::shared_ptr<audio::AudioSource> takeLoadMusic(const std::string &resRef);
void toggleInGameCameraType();
void enterFreeLook();
void exitFreeLook();
Expand Down
3 changes: 2 additions & 1 deletion include/reone/game/gui/chargen/abilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ class CharGenAbilities : public GameGUI {

int getPointCost(Ability ability) const;

void onAbilityLabelSelectionChanged(Ability ability, bool selected);
/** Pulses the row's name and points while the row is hovered, and describes its ability. */
void onAbilityLabelSelectionChanged(Ability ability, gui::Label &label, gui::Button &points, bool selected);
void onMinusButtonClick(Ability ability);
void onPlusButtonClick(Ability ability);
};
Expand Down
6 changes: 6 additions & 0 deletions include/reone/game/gui/chargen/custom.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ class CustomCharacterGeneration : public GameGUI {

void setStep(int step);

/**
* Shows the current step as current again, its number and name pulsing,
* as when the panel returns from one of the steps' screens.
*/
void refreshStep() { doSetStep(_step); }

private:
struct Controls {
std::shared_ptr<gui::Button> BTN_BACK;
Expand Down
6 changes: 6 additions & 0 deletions include/reone/game/gui/chargen/levelup.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ class LevelUpMenu : public GameGUI {

void setStep(int step);

/**
* Shows the current step as current again, its number and name pulsing,
* as when the panel returns from one of the steps' screens.
*/
void refreshStep() { doSetStep(_step); }

/** Whether the coming level offers a choice of feats. */
bool hasFeatChoices() const;
/** Whether the coming level offers a choice of powers. */
Expand Down
6 changes: 6 additions & 0 deletions include/reone/game/gui/chargen/quick.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ class QuickCharacterGeneration : public GameGUI {

void setStep(int step);

/**
* Shows the current step as current again, its number and name pulsing,
* as when the panel returns from one of the steps' screens.
*/
void refreshStep() { doSetStep(_step); }

private:
struct Controls {
std::shared_ptr<gui::Button> BTN_BACK;
Expand Down
3 changes: 2 additions & 1 deletion include/reone/game/gui/chargen/skills.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,8 @@ class CharGenSkills : public GameGUI {

void onMinusButtonClick(SkillType skill);
void onPlusButtonClick(SkillType skill);
void onSkillLabelSelectionChanged(SkillType skill, bool selected);
/** Pulses the row's name and points while the row is hovered, and describes its skill. */
void onSkillLabelSelectionChanged(SkillType skill, gui::Label &label, gui::Button &points, bool selected);
};

} // namespace game
Expand Down
Loading
Loading