about summary refs log tree commit diff stats
Commit message (Collapse)AuthorAgeFilesLines
* White background for subway mapStar Rauchenberger2024-05-121-1/+1
|
* Subway map hover detection with a quadtreeStar Rauchenberger2024-05-127-0/+498
|
* Higher quality + owl picturesStar Rauchenberger2024-05-122-34/+68
|
* Started making subway mapStar Rauchenberger2024-05-1212-4/+859
|
* Merge branch 'main' into subwayStar Rauchenberger2024-05-1212-232/+517
|\
| * Fix pilgrimage detection when sunwarp shuffle is onStar Rauchenberger2024-04-271-14/+24
| |
| * Released v0.9.0Star Rauchenberger2024-04-222-1/+9
| |
| * More backwards compatibility with 0.4.5 v0.9.0Star Rauchenberger2024-04-221-3/+6
| |
| * Bump versionStar Rauchenberger2024-04-221-1/+1
| |
| * Merge branch 'future'Star Rauchenberger2024-04-229-232/+496
| |\
| | * Fix crossroads roof accessStar Rauchenberger2024-03-171-1/+1
| | | | | | | | | | | | honestly embarrassing
| | * Added connection historyStar Rauchenberger2024-03-175-20/+100
| | |
| | * Added sunwarp shuffleStar Rauchenberger2024-03-027-12/+88
| | |
| | * Fix pilgrimage detection for vanilla doorsStar Rauchenberger2024-02-285-19/+139
| | | | | | | | | | | | Also add new pilgrimage options.
| | * Fix websocketpp on gccStar Rauchenberger2024-02-275-5/+4
| | |
| | * Added pilgrimage goalStar Rauchenberger2024-02-262-1/+3
| | |
| | * Merge branch 'main' into futureStar Rauchenberger2024-02-269-10/+72
| | |\
| | * | Added real pilgrimage detectionStar Rauchenberger2024-02-267-298/+293
| | | |
| | * | Added sunwarp access supportStar Rauchenberger2024-01-316-20/+91
| | | |
| | * | Merge branch 'main' into futureStar Rauchenberger2024-01-3011-216/+213
| | |\ \
| | * | | Handle Color Hunt changesStar Rauchenberger2024-01-212-1/+3
| | | | |
| | * | | Areas changes for Symmetry RoomStar Rauchenberger2024-01-211-2/+6
| | | | |
| | * | | Handle renamed bearer entranceStar Rauchenberger2024-01-191-1/+1
| | | | |
| | * | | Area info from renamesStar Rauchenberger2024-01-191-2/+14
| | | | |
* | | | | Replaced about boxStar Rauchenberger2024-04-202-14/+22
|/ / / /
* | | | Released v0.8.0Star Rauchenberger2024-04-032-2/+10
| | | |
* | | | Bump version v0.8.0Star Rauchenberger2024-04-031-1/+1
| | | |
* | | | Added player position trackingStar Rauchenberger2024-04-035-19/+82
| | | |
* | | | Released v0.7.1Star Rauchenberger2024-04-012-1/+10
| | | |
* | | | Bump version v0.7.1Star Rauchenberger2024-04-011-1/+1
| | | |
* | | | Fixed handling of door groupsStar Rauchenberger2024-04-011-2/+2
| | | |
* | | | Released v0.7.0Star Rauchenberger2024-04-012-1/+9
| | | |
* | | | Bump version v0.7.0Star Rauchenberger2024-03-152-2/+2
| | | |
* | | | Handle Color Hunt changesStar Rauchenberger2024-03-152-1/+3
| | | |
* | | | Areas changes for Symmetry RoomStar Rauchenberger2024-03-151-2/+6
| | | |
* | | | Handle renamed bearer entranceStar Rauchenberger2024-03-151-1/+1
| | | |
* | | | Area info from renamesStar Rauchenberger2024-03-151-2/+14
| | | |
* | | | Released v0.6.6Star Rauchenberger2024-03-072-1/+10
| | | |
* | | | Bump version v0.6.6Star Rauchenberger2024-03-071-1/+1
| | | |
* | | | Added connection historyStar Rauchenberger2024-03-075-20/+100
| | | |
* | | | Fix websocketpp on gccStar Rauchenberger2024-02-275-5/+4
| |_|/ |/| |
* | | Released v0.6.5Star Rauchenberger2024-02-182-1/+9
| | |
* | | Bump version v0.6.5Star Rauchenberger2024-02-181-1/+1
| | |
* | | Make win condition checkableStar Rauchenberger2024-02-186-8/+62
| |/ |/|
* | Released v0.6.4Star Rauchenberger2024-01-272-1/+9
| |
* | Bump version v0.6.4Star Rauchenberger2024-01-271-1/+1
| |
* | Fix area popups not shrinkingStar Rauchenberger2024-01-271-0/+1
| |
* | Released v0.6.3Star Rauchenberger2024-01-192-1/+12
| |
* | Bump version v0.6.3Star Rauchenberger2024-01-191-1/+1
| |
* | Area popups are now paintedStar Rauchenberger2024-01-196-130/+91
| | | | | | | | Instead of being a bunch of controls. This fixes the problem with the window being slow to drag around, and with items in lists disappearing. Overall W for me.
'alt'>
                                                             
                                                                               















                                                                                  
                                                          





                                                                           




















                                           



           












                                           
                                                                                                            



                                                                             

                             
 

                              
                                                                             









                                                    




                                                             




                                                                           
                                         
                                                                
                    













                                                                      
                                 














                                






                             

   



                                                



                                                                   
                                 





















                                                                     
                               



                     
                         


                         
          
                                                          


   







                                                             
#include "message_system.h"
#include "game.h"
#include "util.h"

const int CHARS_TO_REVEAL = 1;
const int CHARS_PER_BEEP = 8;

void MessageSystem::tick(double dt) {
  if (barsState_ == BarsState::Opening || barsState_ == BarsState::Closing) {
    accum_ += dt;

    if (accum_ >= length_) {
      if (barsState_ == BarsState::Opening) {
        barsState_ = BarsState::Open;
      } else {
        barsState_ = BarsState::Closed;
      }
    }
  } else if (barsState_ == BarsState::Open) {
    if (!linesToShow_.empty()) {
      textAdvTimer_.accumulate(dt);
      while (textAdvTimer_.step()) {
        // Try to advance text on the first line that isn't totally revealed yet.
        bool advancedChars = false;
        for (MessageLine& line : linesToShow_) {
          if (line.charsRevealed < line.text.size()) {
            // Every so often play a beep.
            if (line.charsRevealed % CHARS_PER_BEEP == 0) {
              if (speaker_ == SpeakerType::Man) {
                game_.getMixer().playSound("../res/sfx/speaking_man.wav");
              } else if (speaker_ == SpeakerType::Woman) {
                game_.getMixer().playSound("../res/sfx/speaking_woman.wav");
              } else if (speaker_ == SpeakerType::Boy) {
                game_.getMixer().playSound("../res/sfx/speaking_boy.wav");
              } else if (speaker_ == SpeakerType::Girl) {
                game_.getMixer().playSound("../res/sfx/speaking_girl.wav");
              } else if (speaker_ == SpeakerType::Nonhuman) {
                game_.getMixer().playSound("../res/sfx/speaking_nonhuman.wav");
              }
            }

            line.charsRevealed += CHARS_TO_REVEAL;
            if (line.charsRevealed > line.text.size()) {
              line.charsRevealed = line.text.size();
            }
            advancedChars = true;
            break;
          }
        }

        if (!advancedChars) {
          // If both lines are totally revealed, see if we can scroll up a line.
          // This is doable as long as the next line isn't the sentinel value that
          // means an A press is required.
          if (!lines_.empty() && lines_.front() != "\f") {
            if (linesToShow_.size() == 2) {
              linesToShow_.pop_front();
            }

            linesToShow_.push_back(MessageLine { .text = lines_.front() });
            lines_.pop_front();
          } else {
            showNextArrow_ = true;
          }
        }
      }

      if (showNextArrow_) {
        nextArrowBobTimer_.accumulate(dt);
        while (nextArrowBobTimer_.step()) {
          if (nextArrowBobDown_) {
            nextArrowBobPos_++;

            if (nextArrowBobPos_ >= 4) {
              nextArrowBobDown_ = false;
            }
          } else {
            nextArrowBobPos_--;

            if (nextArrowBobPos_ <= 0) {
              nextArrowBobDown_ = true;
            }
          }
        }
      }
    }
  }
}

void MessageSystem::displayCutsceneBars() {
  accum_ = 0.0;
  barsState_ = BarsState::Opening;
}

void MessageSystem::hideCutsceneBars() {
  accum_ = 0.0;
  barsState_ = BarsState::Closing;
}

void MessageSystem::displayMessage(std::string_view msg, std::string speakerName, SpeakerType speakerType) {
  if (!(barsState_ == BarsState::Opening || barsState_ == BarsState::Open)) {
    displayCutsceneBars();
  }

  speaker_ = speakerType;
  speakerName_ = speakerName;

  bool shouldAddBlank = false;

  auto lineChunks = splitStr<std::list<std::string>>(std::string(msg), "\n");
  for (std::string text : lineChunks) {
    if (text.substr(0, 1) == "\f") {
      text.erase(0, 1);
      shouldAddBlank = false;

      if (lines_.empty() || lines_.back() != "\f") {
        lines_.push_back("\f");
      }
    }

    auto words = splitStr<std::list<std::string>>(text, " ");

    std::string curLine;
    int curWidth = 0;
    bool firstWord = true;
    // I'm gonna be frank and admit it: I'm not gonna take hyphenation into
    // consideration. Please don't write any words that are wider than the
    // textbox.
    for (const std::string& word : words) {
      int wordWidth = 0;
      for (int i=0; i<word.size(); i++) {
        wordWidth += game_.getFont().getCharacterWidth(word[i]);
        wordWidth++;
      }

      int nextWidth = curWidth + wordWidth;
      if (!firstWord) {
        nextWidth += game_.getFont().getCharacterWidth(' ');
      }

      if (nextWidth > MESSAGE_TEXT_WIDTH) {
        lines_.push_back(curLine);
        curLine = word;
        curWidth = wordWidth + game_.getFont().getCharacterWidth(' ');

        if (shouldAddBlank) {
          shouldAddBlank = false;
          lines_.push_back("\f");
        } else {
          shouldAddBlank = true;
        }
      } else {
        curWidth = nextWidth;
        if (!firstWord) {
          curLine.append(" ");
        }
        curLine.append(word);
      }

      firstWord = false;
    }

    lines_.push_back(curLine);

    if (shouldAddBlank) {
      shouldAddBlank = false;
      lines_.push_back("\f");
    } else {
      shouldAddBlank = true;
    }
  }

  if (lines_.empty() || lines_.back() != "\f") {
    lines_.push_back("\f");
  }

  if (linesToShow_.empty()) {
    linesToShow_.push_back(MessageLine { .text = lines_.front() });
    lines_.pop_front();

    if (lines_.front() != "\f") {
      linesToShow_.push_back(MessageLine { .text = lines_.front() });
      lines_.pop_front();
    }
  }
}

void MessageSystem::advanceText() {
  if (barsState_ != BarsState::Open) {
    return;
  }

  for (const MessageLine& line : linesToShow_) {
    if (line.charsRevealed != line.text.size()) {
      return;
    }
  }

  if (lines_.empty()) {
    linesToShow_.clear();
    return;
  }

  if (lines_.front() != "\f") {
    return;
  }

  lines_.pop_front();
  showNextArrow_ = false;

  if (lines_.empty()) {
    linesToShow_.clear();
  } else {
    game_.getMixer().playSound("../res/sfx/pageflip.wav");
  }
}

double MessageSystem::getCutsceneBarsProgress() const {
  switch (barsState_) {
    case BarsState::Closed: return 0.0;
    case BarsState::Opening: return accum_ / length_;
    case BarsState::Open: return 1.0;
    case BarsState::Closing: return 1.0 - (accum_ / length_);
  }
}