<?php
/*
444444444
4::::::::4
4:::::::::4
4::::44::::4
4::::4 4::::4 Four Island
4::::4 4::::4
4::::4 4::::4 Written and maintained by Starla Insigna
4::::444444::::444
4::::::::::::::::4 pages/polloftheweek.php
4444444444:::::444
4::::4 Please do not use, reproduce or steal the
4::::4 contents of this file without explicit
4::::4 permission from Hatkirby.
44::::::44
4::::::::4
4444444444
*/
if (!defined('S_INCLUDE_FILE')) {define('S_INCLUDE_FILE',1);}
require('headerproc.php');
if (!isset($_GET['potw']))
{
if (!isset(<#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 (game_.isGameplayPaused()) return;
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");
}
}
if (line.isChoice) {
line.charsRevealed = line.text.size();
choiceSelection_ = 0;
} else {
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 last currently visible line doesn't
// have the flag that means an A press is required.
if (!lines_.empty() && !linesToShow_.back().pause) {
if (linesToShow_.size() == 2) {
linesToShow_.pop_front();
}
linesToShow_.push_back(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().pause = true;
}
}
bool bulleted = false;
if (text.substr(0, 2) == "* ") {
text.erase(0, 2);
bulleted = true;
}
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({.text = curLine, .bulleted = bulleted});
curLine = word;
curWidth = wordWidth + game_.getFont().getCharacterWidth(' ');
bulleted = false;
if (shouldAddBlank) {
shouldAddBlank = false;
lines_.back().pause = true;
} else {
shouldAddBlank = true;
}
} else {
curWidth = nextWidth;
if (!firstWord) {
curLine.append(" ");
}
curLine.append(word);
}
firstWord = false;
}
lines_.push_back({.text = curLine, .bulleted = bulleted});
if (shouldAddBlank) {
shouldAddBlank = false;
lines_.back().pause = true;
} else {
shouldAddBlank = true;
}
}
if (!lines_.empty()) {
lines_.back().pause = true;
}
if (linesToShow_.empty()) {
linesToShow_.push_back(lines_.front());
lines_.pop_front();
if (!linesToShow_.back().pause) {
linesToShow_.push_back(lines_.front());
lines_.pop_front();
}
}
}
void MessageSystem::showChoice(std::string choice1, std::string choice2) {
MessageLine line;
line.text = std::string(8, ' ') + choice1 + std::string(11, ' ') + choice2;
line.pause = true;
line.isChoice = true;
line.choicePos[0] = 8;
line.choicePos[1] = 8 + 11 + choice1.size();
lines_.push_back(line);
}
void MessageSystem::advanceText() {
// Cutscene must be active.
if (barsState_ != BarsState::Open) {
return;
}
if (linesToShow_.empty()) {
return;
}
// We can only advance if all visible lines are fully revealed.
for (const MessageLine& line : linesToShow_) {
if (line.charsRevealed != line.text.size()) {
return;
}
}
// If the last visible line doesn't have a pause, then the cutscene
// will automatically progress without us doing anything.
if (!linesToShow_.back().pause) {
return;
}
// Clear the current pause.
linesToShow_.back().pause = false;
showNextArrow_ = false;
if (lines_.empty()) {
if (isChoiceActive()) {
if (choiceSelection_ == 0) {
game_.getMixer().playSound("../res/sfx/left_selection.wav");
} else {
game_.getMixer().playSound("../res/sfx/right_selection.wav");
}
}
linesToShow_.clear();
} else {
game_.getMixer().playSound("../res/sfx/pageflip.wav");
}
}
void MessageSystem::selectFirstChoice() {
if (isChoiceActive() && choiceSelection_ != 0) {
choiceSelection_ = 0;
game_.getMixer().playSound("../res/sfx/horizontal_menu.wav");
}
}
void MessageSystem::selectSecondChoice() {
if (isChoiceActive() && choiceSelection_ != 1) {
choiceSelection_ = 1;
game_.getMixer().playSound("../res/sfx/horizontal_menu.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_);
}
}