295 lines
9.0 KiB
C++
295 lines
9.0 KiB
C++
#include "main.hpp"
|
|
|
|
#include <glm/glm.hpp>
|
|
#include <imgui.h>
|
|
#include <imgui_impl_opengl3.h>
|
|
|
|
#include "../util/imgui.hpp"
|
|
#include "../util/imgui/style.hpp"
|
|
#include "../util/imgui/widget.hpp"
|
|
#include "../util/math.hpp"
|
|
|
|
using namespace game::resource;
|
|
using namespace game::util;
|
|
using namespace game::state::main;
|
|
using namespace glm;
|
|
|
|
namespace game::state
|
|
{
|
|
World::Focus Main::focus_get()
|
|
{
|
|
return menu.isOpen && tools.isOpen ? World::MENU_TOOLS
|
|
: menu.isOpen ? World::MENU
|
|
: tools.isOpen ? World::TOOLS
|
|
: World::CENTER;
|
|
}
|
|
|
|
void Main::set(Resources& resources, int selectedCharacterIndex, enum Game game)
|
|
{
|
|
auto& data = resources.character_get(selectedCharacterIndex);
|
|
auto& saveData = data.save;
|
|
auto& itemSchema = data.itemSchema;
|
|
auto& dialogue = data.dialogue;
|
|
auto& menuSchema = data.menuSchema;
|
|
this->characterIndex = selectedCharacterIndex;
|
|
|
|
character =
|
|
entity::Character(data, vec2(World::BOUNDS.x + World::BOUNDS.z * 0.5f, World::BOUNDS.w - World::BOUNDS.y));
|
|
|
|
auto isAlternateSpritesheet =
|
|
(game == NEW_GAME && math::random_percent_roll(data.alternateSpritesheet.chanceOnNewGame));
|
|
|
|
if (isAlternateSpritesheet || saveData.isAlternateSpritesheet)
|
|
{
|
|
character.spritesheet_set(entity::Character::ALTERNATE);
|
|
if (game == NEW_GAME) character.data.alternateSpritesheet.sound.play();
|
|
}
|
|
|
|
character.totalCaloriesConsumed = saveData.totalCaloriesConsumed;
|
|
character.totalFoodItemsEaten = saveData.totalFoodItemsEaten;
|
|
characterManager = CharacterManager{};
|
|
|
|
cursor = entity::Cursor(character.data.cursorSchema.anm2);
|
|
|
|
menu.inventory = Inventory{};
|
|
for (auto& [id, quantity] : saveData.inventory)
|
|
{
|
|
if (quantity == 0) continue;
|
|
menu.inventory.values[id] = quantity;
|
|
}
|
|
|
|
itemManager = ItemManager{};
|
|
for (auto& item : saveData.items)
|
|
{
|
|
auto& anm2 = itemSchema.anm2s.at(item.id);
|
|
auto chewAnimation = itemSchema.animations.chew + std::to_string(item.chewCount);
|
|
auto animationIndex = item.chewCount > 0 ? anm2.animationMap[chewAnimation] : -1;
|
|
auto& saveItem = itemSchema.anm2s.at(item.id);
|
|
itemManager.items.emplace_back(saveItem, item.position, item.id, item.chewCount, animationIndex, item.velocity,
|
|
item.rotation);
|
|
}
|
|
|
|
imgui::style::rounding_set(menuSchema.rounding);
|
|
imgui::widget::sounds_set(&menuSchema.sounds.hover, &menuSchema.sounds.select);
|
|
|
|
menu.play = Play(character);
|
|
menu.play.totalPlays = saveData.totalPlays;
|
|
menu.play.highScore = saveData.highScore;
|
|
menu.play.bestCombo = saveData.bestCombo;
|
|
menu.play.gradeCounts = saveData.gradeCounts;
|
|
menu.play.isHighScoreAchieved = saveData.highScore > 0 ? true : false;
|
|
|
|
menu.isChat = character.data.dialogue.help.is_valid() || character.data.dialogue.random.is_valid();
|
|
|
|
text.entry = nullptr;
|
|
text.isEnabled = false;
|
|
|
|
if (auto font = character.data.menuSchema.font.get()) ImGui::GetIO().FontDefault = font;
|
|
|
|
if (game == NEW_GAME && dialogue.start.is_valid())
|
|
{
|
|
character.queue_play({.animation = dialogue.start.animation, .isInterruptible = false});
|
|
character.tick();
|
|
isWindows = false;
|
|
isStart = true;
|
|
}
|
|
|
|
isPostgame = saveData.isPostgame;
|
|
|
|
if (isPostgame)
|
|
menu.isCheats = true;
|
|
else
|
|
menu.isCheats = true; //false;
|
|
|
|
worldCanvas.size_set(imgui::to_vec2(ImGui::GetMainViewport()->Size));
|
|
|
|
world.set(character, worldCanvas, focus_get());
|
|
}
|
|
|
|
void Main::exit(Resources& resources)
|
|
{
|
|
imgui::style::rounding_set();
|
|
imgui::widget::sounds_set(nullptr, nullptr);
|
|
ImGui::GetIO().FontDefault = resources.font.get();
|
|
save(resources);
|
|
}
|
|
|
|
void Main::tick(Resources&)
|
|
{
|
|
character.tick();
|
|
cursor.tick();
|
|
menu.tick();
|
|
toasts.tick();
|
|
text.tick(character);
|
|
|
|
for (auto& item : itemManager.items)
|
|
item.tick();
|
|
}
|
|
|
|
void Main::update(Resources& resources)
|
|
{
|
|
auto focus = focus_get();
|
|
auto& dialogue = character.data.dialogue;
|
|
|
|
if (isWindows)
|
|
{
|
|
menu.update(resources, itemManager, character, cursor, text, worldCanvas);
|
|
tools.update(character, cursor, world, focus, worldCanvas);
|
|
info.update(resources, character);
|
|
toasts.update();
|
|
}
|
|
|
|
if (text.isEnabled) text.update(character);
|
|
|
|
if (isStart)
|
|
{
|
|
if (!isStartBegin)
|
|
{
|
|
if (auto animation = character.animation_get())
|
|
{
|
|
if (animation->isLoop || character.state == entity::Actor::STOPPED)
|
|
{
|
|
text.set(dialogue.get(dialogue.start.id), character);
|
|
isStartBegin = true;
|
|
}
|
|
}
|
|
}
|
|
else if (!isStartEnd)
|
|
{
|
|
if (text.entry->is_last())
|
|
{
|
|
isWindows = true;
|
|
isStartEnd = true;
|
|
isStart = false;
|
|
world.character_focus(character, worldCanvas, focus_get());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (character.isJustStageFinal && !isEnd && !isPostgame) isEnd = true;
|
|
|
|
if (isEnd)
|
|
{
|
|
if (!isEndBegin)
|
|
{
|
|
if (character.is_animation_finished())
|
|
{
|
|
text.set(dialogue.get(dialogue.end.id), character);
|
|
isEndBegin = true;
|
|
isWindows = false;
|
|
tools.isOpen = false;
|
|
menu.isOpen = false;
|
|
character.calories = 0;
|
|
character.digestionProgress = 0;
|
|
itemManager.items.clear();
|
|
itemManager.heldItemIndex = -1;
|
|
world.character_focus(character, worldCanvas, focus_get());
|
|
}
|
|
}
|
|
else if (!isEndEnd)
|
|
{
|
|
if (text.entry->is_last())
|
|
{
|
|
menu.isOpen = true;
|
|
isWindows = true;
|
|
isEndEnd = true;
|
|
isEnd = false;
|
|
isPostgame = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
itemManager.update(character, cursor, areaManager, text, World::BOUNDS, worldCanvas);
|
|
characterManager.update(character, cursor, text, worldCanvas);
|
|
|
|
character.update();
|
|
cursor.update();
|
|
world.update(character, cursor, worldCanvas, focus);
|
|
|
|
if (autosaveTime += ImGui::GetIO().DeltaTime; autosaveTime > AUTOSAVE_TIME || menu.configuration.isSave)
|
|
{
|
|
save(resources);
|
|
autosaveTime = 0;
|
|
menu.configuration.isSave = false;
|
|
}
|
|
}
|
|
|
|
void Main::render(Resources& resources, Canvas& canvas)
|
|
{
|
|
auto& textureShader = resources.shaders[shader::TEXTURE];
|
|
auto& rectShader = resources.shaders[shader::RECT];
|
|
auto size = imgui::to_ivec2(ImGui::GetMainViewport()->Size);
|
|
|
|
auto& bgTexture = character.data.areaSchema.areas.at(areaManager.get(character)).texture;
|
|
|
|
auto windowModel = math::quad_model_get(vec2(size));
|
|
auto worldModel = math::quad_model_get(bgTexture.size);
|
|
worldCanvas.bind();
|
|
worldCanvas.size_set(size);
|
|
worldCanvas.clear();
|
|
worldCanvas.texture_render(textureShader, bgTexture.id, worldModel);
|
|
|
|
character.render(textureShader, rectShader, worldCanvas);
|
|
|
|
for (auto& item : itemManager.items)
|
|
item.render(textureShader, rectShader, worldCanvas);
|
|
|
|
if (menu.debug.isBoundsDisplay)
|
|
{
|
|
auto boundsModel =
|
|
math::quad_model_get(glm::vec2(World::BOUNDS.z, World::BOUNDS.w), glm::vec2(World::BOUNDS.x, World::BOUNDS.y),
|
|
glm::vec2(World::BOUNDS.x, World::BOUNDS.y) * 0.5f);
|
|
worldCanvas.rect_render(rectShader, boundsModel);
|
|
}
|
|
worldCanvas.unbind();
|
|
|
|
canvas.bind();
|
|
canvas.texture_render(textureShader, worldCanvas.texture, windowModel);
|
|
ImGui::Render();
|
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
|
cursor.render(textureShader, rectShader, canvas);
|
|
canvas.unbind();
|
|
|
|
SDL_HideCursor();
|
|
}
|
|
|
|
void Main::save(Resources& resources)
|
|
{
|
|
resource::xml::Save save;
|
|
|
|
save.weight = character.weight;
|
|
save.calories = character.calories;
|
|
save.capacity = character.capacity;
|
|
save.digestionRate = character.digestionRate;
|
|
save.eatSpeed = character.eatSpeed;
|
|
save.digestionProgress = character.digestionProgress;
|
|
save.isDigesting = character.isDigesting;
|
|
save.digestionTimer = character.digestionTimer;
|
|
save.totalCaloriesConsumed = character.totalCaloriesConsumed;
|
|
save.totalFoodItemsEaten = character.totalFoodItemsEaten;
|
|
save.totalPlays = menu.play.totalPlays;
|
|
save.highScore = menu.play.highScore;
|
|
save.bestCombo = menu.play.bestCombo;
|
|
save.gradeCounts = menu.play.gradeCounts;
|
|
save.isPostgame = isPostgame;
|
|
save.isAlternateSpritesheet = character.spritesheetType == entity::Character::ALTERNATE;
|
|
|
|
for (auto& [id, quantity] : menu.inventory.values)
|
|
{
|
|
if (quantity == 0) continue;
|
|
save.inventory[id] = quantity;
|
|
}
|
|
|
|
for (auto& item : itemManager.items)
|
|
save.items.emplace_back(item.schemaID, item.chewCount, item.position, item.velocity,
|
|
*item.overrides[item.rotationOverrideID].frame.rotation);
|
|
|
|
save.isValid = true;
|
|
|
|
resources.character_save_set(characterIndex, save);
|
|
save.serialize(character.data.save_path_get());
|
|
|
|
toasts.push("Saving...");
|
|
}
|
|
};
|