The Mega Snivy Update
Some checks failed
Build / Build Game (push) Has been cancelled

This commit is contained in:
2026-02-28 21:48:00 -05:00
parent 8b2edd1359
commit 17f3348e94
163 changed files with 8725 additions and 13281 deletions

294
src/state/main.cpp Normal file
View File

@@ -0,0 +1,294 @@
#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 characterIndex, enum Game game)
{
auto& data = resources.character_get(characterIndex);
auto& saveData = data.save;
auto& itemSchema = data.itemSchema;
auto& dialogue = data.dialogue;
auto& menuSchema = data.menuSchema;
this->characterIndex = characterIndex;
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& 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...");
}
};