This commit is contained in:
10
MODDING.md
10
MODDING.md
@@ -56,7 +56,7 @@ The file path of the area's texture (background).
|
|||||||
Gravity the area has; applies to items' velocities per tick.
|
Gravity the area has; applies to items' velocities per tick.
|
||||||
#### Friction (float)
|
#### Friction (float)
|
||||||
Friction of the area; applies to items' velocities when grounded or hitting walls.
|
Friction of the area; applies to items' velocities when grounded or hitting walls.
|
||||||
### AirResistance (float)
|
#### AirResistance (float)
|
||||||
Air resistance of the area; applies to items' velocities when airborne.
|
Air resistance of the area; applies to items' velocities when airborne.
|
||||||
|
|
||||||
## character.xml
|
## character.xml
|
||||||
@@ -416,6 +416,10 @@ The additional eat speed multiplier the item will give if eaten.
|
|||||||
The item's gravity; will use the default gravity if not available.
|
The item's gravity; will use the default gravity if not available.
|
||||||
#### ChewCount (int; optional)
|
#### ChewCount (int; optional)
|
||||||
An item's custom chew count.
|
An item's custom chew count.
|
||||||
|
#### UpgradeID (string; optional)
|
||||||
|
The name of another item that this item will be able to be upgraded to.
|
||||||
|
#### UpgradeCount (int; optional)
|
||||||
|
The amount of this item it will take to upgrade to the upgrade item specified in UpgradeID.
|
||||||
#### IsPlayReward (bool; optional)
|
#### IsPlayReward (bool; optional)
|
||||||
The item will be given out when the reward is hit in play (see play.xml)
|
The item will be given out when the reward is hit in play (see play.xml)
|
||||||
#### IsToggleSpritesheet (bool; optional)
|
#### IsToggleSpritesheet (bool; optional)
|
||||||
@@ -451,6 +455,10 @@ The sound that will play, based on SoundRootPath.
|
|||||||
Will play when clicking on a widget in a menu.
|
Will play when clicking on a widget in a menu.
|
||||||
#### Sound (path)
|
#### Sound (path)
|
||||||
The sound that will play, based on SoundRootPath.
|
The sound that will play, based on SoundRootPath.
|
||||||
|
### CheatsActivated
|
||||||
|
Sound that will play after entering a special code to activate cheats.
|
||||||
|
#### Sound (path)
|
||||||
|
The sound that will play, based on SoundRootPath.
|
||||||
|
|
||||||
## play.xml
|
## play.xml
|
||||||
Determines behavior and appearance of the "Play" minigame.
|
Determines behavior and appearance of the "Play" minigame.
|
||||||
|
|||||||
@@ -87,6 +87,22 @@ namespace game::resource::xml
|
|||||||
query_sound_entry_collection(element, "Dispose", archive, soundRootPath, sounds.dispose);
|
query_sound_entry_collection(element, "Dispose", archive, soundRootPath, sounds.dispose);
|
||||||
query_sound_entry_collection(element, "Return", archive, soundRootPath, sounds.return_);
|
query_sound_entry_collection(element, "Return", archive, soundRootPath, sounds.return_);
|
||||||
query_sound_entry_collection(element, "Summon", archive, soundRootPath, sounds.summon);
|
query_sound_entry_collection(element, "Summon", archive, soundRootPath, sounds.summon);
|
||||||
|
query_sound_entry_collection(element, "Upgrade", archive, soundRootPath, sounds.upgrade);
|
||||||
|
query_sound_entry_collection(element, "UpgradeFail", archive, soundRootPath, sounds.upgradeFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto element = root->FirstChildElement("Items"))
|
||||||
|
{
|
||||||
|
int id{};
|
||||||
|
|
||||||
|
for (auto child = element->FirstChildElement("Item"); child; child = child->NextSiblingElement("Item"))
|
||||||
|
{
|
||||||
|
std::string name{};
|
||||||
|
query_string_attribute(child, "Name", &name);
|
||||||
|
stringToIDMap[name] = id;
|
||||||
|
idToStringMap[id] = name;
|
||||||
|
id++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto element = root->FirstChildElement("Items"))
|
if (auto element = root->FirstChildElement("Items"))
|
||||||
@@ -108,7 +124,24 @@ namespace game::resource::xml
|
|||||||
query_float_optional_attribute(child, "DigestionBonus", item.digestionBonus);
|
query_float_optional_attribute(child, "DigestionBonus", item.digestionBonus);
|
||||||
query_float_optional_attribute(child, "EatSpeedBonus", item.eatSpeedBonus);
|
query_float_optional_attribute(child, "EatSpeedBonus", item.eatSpeedBonus);
|
||||||
query_float_optional_attribute(child, "Gravity", item.gravity);
|
query_float_optional_attribute(child, "Gravity", item.gravity);
|
||||||
|
|
||||||
query_int_optional_attribute(child, "ChewCount", item.chewCount);
|
query_int_optional_attribute(child, "ChewCount", item.chewCount);
|
||||||
|
|
||||||
|
if (child->FindAttribute("UpgradeID"))
|
||||||
|
{
|
||||||
|
std::string upgradeIDString{};
|
||||||
|
query_string_attribute(child, "UpgradeID", &upgradeIDString);
|
||||||
|
|
||||||
|
if (!upgradeIDString.empty() && stringToIDMap.contains(upgradeIDString))
|
||||||
|
item.upgradeID = stringToIDMap[upgradeIDString];
|
||||||
|
else if (upgradeIDString.empty())
|
||||||
|
logger.warning(std::format("Empty UpgradeID ({})", item.name));
|
||||||
|
else
|
||||||
|
logger.warning(std::format("Could not find item ID for UpgradeID: {} ({})", upgradeIDString, item.name));
|
||||||
|
|
||||||
|
query_int_optional_attribute(child, "UpgradeCount", item.upgradeCount);
|
||||||
|
}
|
||||||
|
|
||||||
query_bool_attribute(child, "IsPlayReward", &item.isPlayReward);
|
query_bool_attribute(child, "IsPlayReward", &item.isPlayReward);
|
||||||
query_bool_attribute(child, "IsToggleSpritesheet", &item.isToggleSpritesheet);
|
query_bool_attribute(child, "IsToggleSpritesheet", &item.isToggleSpritesheet);
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ namespace game::resource::xml
|
|||||||
std::string description{UNDEFINED};
|
std::string description{UNDEFINED};
|
||||||
int categoryID{};
|
int categoryID{};
|
||||||
int rarityID{};
|
int rarityID{};
|
||||||
|
std::optional<int> upgradeCount{};
|
||||||
|
std::optional<int> upgradeID{};
|
||||||
std::optional<int> flavorID;
|
std::optional<int> flavorID;
|
||||||
std::optional<float> calories{};
|
std::optional<float> calories{};
|
||||||
std::optional<float> eatSpeedBonus{};
|
std::optional<float> eatSpeedBonus{};
|
||||||
@@ -63,11 +65,15 @@ namespace game::resource::xml
|
|||||||
SoundEntryCollection return_{};
|
SoundEntryCollection return_{};
|
||||||
SoundEntryCollection dispose{};
|
SoundEntryCollection dispose{};
|
||||||
SoundEntryCollection summon{};
|
SoundEntryCollection summon{};
|
||||||
|
SoundEntryCollection upgrade{};
|
||||||
|
SoundEntryCollection upgradeFail{};
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unordered_map<std::string, int> categoryMap{};
|
std::unordered_map<std::string, int> categoryMap{};
|
||||||
std::unordered_map<std::string, int> rarityMap{};
|
std::unordered_map<std::string, int> rarityMap{};
|
||||||
std::unordered_map<std::string, int> flavorMap{};
|
std::unordered_map<std::string, int> flavorMap{};
|
||||||
|
std::unordered_map<std::string, int> stringToIDMap{};
|
||||||
|
std::unordered_map<int, std::string> idToStringMap{};
|
||||||
|
|
||||||
using Pool = std::vector<int>;
|
using Pool = std::vector<int>;
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ namespace game::resource::xml
|
|||||||
query_sound_entry_collection(element, "Close", archive, soundRootPath, sounds.close);
|
query_sound_entry_collection(element, "Close", archive, soundRootPath, sounds.close);
|
||||||
query_sound_entry_collection(element, "Hover", archive, soundRootPath, sounds.hover);
|
query_sound_entry_collection(element, "Hover", archive, soundRootPath, sounds.hover);
|
||||||
query_sound_entry_collection(element, "Select", archive, soundRootPath, sounds.select);
|
query_sound_entry_collection(element, "Select", archive, soundRootPath, sounds.select);
|
||||||
|
query_sound_entry_collection(element, "CheatsActivated", archive, soundRootPath, sounds.cheatsActivated);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace game::resource::xml
|
|||||||
SoundEntryCollection close{};
|
SoundEntryCollection close{};
|
||||||
SoundEntryCollection hover{};
|
SoundEntryCollection hover{};
|
||||||
SoundEntryCollection select{};
|
SoundEntryCollection select{};
|
||||||
|
SoundEntryCollection cheatsActivated{};
|
||||||
};
|
};
|
||||||
|
|
||||||
Sounds sounds{};
|
Sounds sounds{};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "main.hpp"
|
#include "main.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_impl_opengl3.h>
|
#include <imgui_impl_opengl3.h>
|
||||||
@@ -34,6 +35,8 @@ namespace game::state
|
|||||||
auto& dialogue = data.dialogue;
|
auto& dialogue = data.dialogue;
|
||||||
auto& menuSchema = data.menuSchema;
|
auto& menuSchema = data.menuSchema;
|
||||||
this->characterIndex = selectedCharacterIndex;
|
this->characterIndex = selectedCharacterIndex;
|
||||||
|
konamiCodeIndex = 0;
|
||||||
|
konamiCodeStartTime = 0.0;
|
||||||
|
|
||||||
character =
|
character =
|
||||||
entity::Character(data, vec2(World::BOUNDS.x + World::BOUNDS.z * 0.5f, World::BOUNDS.w - World::BOUNDS.y));
|
entity::Character(data, vec2(World::BOUNDS.x + World::BOUNDS.z * 0.5f, World::BOUNDS.w - World::BOUNDS.y));
|
||||||
@@ -132,9 +135,55 @@ namespace game::state
|
|||||||
|
|
||||||
void Main::update(Resources& resources)
|
void Main::update(Resources& resources)
|
||||||
{
|
{
|
||||||
|
static constexpr std::array<ImGuiKey, 10> KONAMI_CODE = {
|
||||||
|
ImGuiKey_UpArrow, ImGuiKey_UpArrow, ImGuiKey_DownArrow, ImGuiKey_DownArrow, ImGuiKey_LeftArrow,
|
||||||
|
ImGuiKey_RightArrow, ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_B, ImGuiKey_A};
|
||||||
|
static constexpr std::array<ImGuiKey, 6> KONAMI_INPUT_KEYS = {
|
||||||
|
ImGuiKey_UpArrow, ImGuiKey_DownArrow, ImGuiKey_LeftArrow, ImGuiKey_RightArrow, ImGuiKey_B, ImGuiKey_A};
|
||||||
|
static constexpr auto KONAMI_CODE_INPUT_TIME_SECONDS = 5.0;
|
||||||
|
|
||||||
auto focus = focus_get();
|
auto focus = focus_get();
|
||||||
auto& dialogue = character.data.dialogue;
|
auto& dialogue = character.data.dialogue;
|
||||||
|
|
||||||
|
if (!menu.isCheats)
|
||||||
|
{
|
||||||
|
for (auto key : KONAMI_INPUT_KEYS)
|
||||||
|
{
|
||||||
|
if (!ImGui::IsKeyPressed(key, false)) continue;
|
||||||
|
|
||||||
|
if (key == KONAMI_CODE[konamiCodeIndex])
|
||||||
|
{
|
||||||
|
konamiCodeIndex++;
|
||||||
|
konamiCodeStartTime = ImGui::GetTime();
|
||||||
|
}
|
||||||
|
else if (key == KONAMI_CODE[0])
|
||||||
|
{
|
||||||
|
konamiCodeIndex = 1;
|
||||||
|
konamiCodeStartTime = ImGui::GetTime();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
konamiCodeIndex = 0;
|
||||||
|
konamiCodeStartTime = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (konamiCodeIndex >= (int)KONAMI_CODE.size())
|
||||||
|
{
|
||||||
|
menu.isCheats = true;
|
||||||
|
konamiCodeIndex = 0;
|
||||||
|
konamiCodeStartTime = 0.0;
|
||||||
|
toasts.push("Cheats unlocked!");
|
||||||
|
character.data.menuSchema.sounds.cheatsActivated.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (konamiCodeIndex > 0 && (ImGui::GetTime() - konamiCodeStartTime > KONAMI_CODE_INPUT_TIME_SECONDS))
|
||||||
|
{
|
||||||
|
konamiCodeIndex = 0;
|
||||||
|
konamiCodeStartTime = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isWindows)
|
if (isWindows)
|
||||||
{
|
{
|
||||||
menu.update(resources, itemManager, character, cursor, text, worldCanvas);
|
menu.update(resources, itemManager, character, cursor, text, worldCanvas);
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ namespace game::state
|
|||||||
int areaIndex{};
|
int areaIndex{};
|
||||||
|
|
||||||
float autosaveTime{};
|
float autosaveTime{};
|
||||||
|
int konamiCodeIndex{};
|
||||||
|
double konamiCodeStartTime{};
|
||||||
|
|
||||||
bool isWindows{true};
|
bool isWindows{true};
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ namespace game::state::main
|
|||||||
auto canvasSize = ivec2(std::max(1.0f, previewSize.x), std::max(1.0f, previewSize.y));
|
auto canvasSize = ivec2(std::max(1.0f, previewSize.x), std::max(1.0f, previewSize.y));
|
||||||
if (!canvases.contains(i)) canvases.emplace((int)i, Canvas(canvasSize, Canvas::FLIP));
|
if (!canvases.contains(i)) canvases.emplace((int)i, Canvas(canvasSize, Canvas::FLIP));
|
||||||
auto& canvas = canvases[i];
|
auto& canvas = canvases[i];
|
||||||
|
bool isPossibleToUpgrade = item.upgradeID.has_value() && item.upgradeCount.has_value() &&
|
||||||
|
schema.idToStringMap.contains(*item.upgradeID);
|
||||||
|
bool isAbleToUpgrade = isPossibleToUpgrade && quantity >= *item.upgradeCount;
|
||||||
canvas.zoom = math::to_percent(previewScale);
|
canvas.zoom = math::to_percent(previewScale);
|
||||||
canvas.pan = vec2(rect.x, rect.y);
|
canvas.pan = vec2(rect.x, rect.y);
|
||||||
canvas.bind();
|
canvas.bind();
|
||||||
@@ -90,7 +93,30 @@ namespace game::state::main
|
|||||||
quantity <= 0 ? ImVec4(0, 0, 0, 1) : ImVec4(1, 1, 1, 1))) &&
|
quantity <= 0 ? ImVec4(0, 0, 0, 1) : ImVec4(1, 1, 1, 1))) &&
|
||||||
quantity > 0)
|
quantity > 0)
|
||||||
{
|
{
|
||||||
if (category.isEdible)
|
if (ImGui::IsKeyDown(ImGuiMod_Shift))
|
||||||
|
{
|
||||||
|
if (isAbleToUpgrade)
|
||||||
|
{
|
||||||
|
if (ImGui::IsKeyDown(ImGuiMod_Ctrl))
|
||||||
|
{
|
||||||
|
while (quantity >= *item.upgradeCount)
|
||||||
|
{
|
||||||
|
values.at(*item.upgradeID)++;
|
||||||
|
quantity -= *item.upgradeCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
values.at(*item.upgradeID)++;
|
||||||
|
quantity -= *item.upgradeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
schema.sounds.upgrade.play();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
schema.sounds.upgradeFail.play();
|
||||||
|
}
|
||||||
|
else if (category.isEdible)
|
||||||
{
|
{
|
||||||
if (itemManager.items.size() + 1 >= ItemManager::LIMIT)
|
if (itemManager.items.size() + 1 >= ItemManager::LIMIT)
|
||||||
character.data.itemSchema.sounds.dispose.play();
|
character.data.itemSchema.sounds.dispose.play();
|
||||||
@@ -143,6 +169,14 @@ namespace game::state::main
|
|||||||
else if (eatSpeedBonus < 0)
|
else if (eatSpeedBonus < 0)
|
||||||
ImGui::Text("Eat Speed Penalty: %0.2f%% / sec", *eatSpeedBonus);
|
ImGui::Text("Eat Speed Penalty: %0.2f%% / sec", *eatSpeedBonus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isPossibleToUpgrade)
|
||||||
|
{
|
||||||
|
ImGui::Text("Upgrade: %ix -> %s", *item.upgradeCount, schema.idToStringMap.at(*item.upgradeID).c_str());
|
||||||
|
if (isAbleToUpgrade)
|
||||||
|
ImGui::TextUnformatted("(Shift + Click -> Upgrade)\n(Shift + Ctrl + Click -> Upgrade All)");
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace game::state::main
|
|||||||
state::Configuration configuration;
|
state::Configuration configuration;
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
bool isCheats{true};
|
bool isCheats{};
|
||||||
bool isDebug{true};
|
bool isDebug{true};
|
||||||
#else
|
#else
|
||||||
bool isCheats{};
|
bool isCheats{};
|
||||||
|
|||||||
@@ -22,13 +22,14 @@ namespace game::state::main
|
|||||||
auto& pan = canvas.pan;
|
auto& pan = canvas.pan;
|
||||||
auto& zoom = canvas.zoom;
|
auto& zoom = canvas.zoom;
|
||||||
auto& io = ImGui::GetIO();
|
auto& io = ImGui::GetIO();
|
||||||
bool isPan{true};
|
|
||||||
auto isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle);
|
auto isMouseMiddleDown = ImGui::IsMouseDown(ImGuiMouseButton_Middle);
|
||||||
|
auto isMouseLeftDown = ImGui::IsMouseDown(ImGuiMouseButton_Left);
|
||||||
|
auto isCtrlDown = ImGui::IsKeyDown(ImGuiMod_Ctrl);
|
||||||
auto panMultiplier = ZOOM_BASE / zoom;
|
auto panMultiplier = ZOOM_BASE / zoom;
|
||||||
|
|
||||||
if (!ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) && !ImGui::IsAnyItemActive())
|
if (!ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) && !ImGui::IsAnyItemActive())
|
||||||
{
|
{
|
||||||
if ((isMouseMiddleDown) && isPan)
|
if ((isMouseMiddleDown) || (isMouseLeftDown && isCtrlDown))
|
||||||
{
|
{
|
||||||
cursor.queue_play({cursorSchema.animations.pan.get()});
|
cursor.queue_play({cursorSchema.animations.pan.get()});
|
||||||
pan -= imgui::to_vec2(io.MouseDelta) * panMultiplier;
|
pan -= imgui::to_vec2(io.MouseDelta) * panMultiplier;
|
||||||
|
|||||||
Reference in New Issue
Block a user