mirror of https://github.com/zeldaret/botw.git
uking/ui: Add more inventory functions
This commit is contained in:
parent
fe3a437a26
commit
0ac3ba93ad
|
@ -383,7 +383,7 @@
|
|||
0x0000007100009ffc,_ZNK4sead15RuntimeTypeInfo6DeriveINS_4HeapEE9isDerivedEPKNS0_9InterfaceE,140,
|
||||
0x000000710000a088,_ZNK4sead15RuntimeTypeInfo6DeriveINS_15ResourceFactoryEE9isDerivedEPKNS0_9InterfaceE,140,
|
||||
0x000000710000a114,CookResult::construct,316,
|
||||
0x000000710000a250,CookItem::ctor,384,
|
||||
0x000000710000a250,CookItem::ctor,384,_ZN4ksys8CookItemC1Ev
|
||||
0x000000710000a3d0,sub_710000A3D0,532,
|
||||
0x000000710000a5e4,act::copyCookResultToCookItem,736,
|
||||
0x000000710000a8c4,j_GameObject::m0,4,
|
||||
|
@ -56335,16 +56335,16 @@
|
|||
0x000000710096efb8,PauseMenuDataMgr::__auto4,688,_ZN5uking2ui16PauseMenuDataMgr7itemGetERKN4sead14SafeStringBaseIcEEiPKNS_3act18WeaponModifierInfoE
|
||||
0x000000710096f268,PauseMenuDataMgr::addToPouch,1876,_ZN5uking2ui16PauseMenuDataMgr10addToPouchERKN4sead14SafeStringBaseIcEENS0_13PouchItemTypeERNS1_5ListsEibPKNS_3act18WeaponModifierInfoEb
|
||||
0x000000710096f9bc,PauseMenuDataMgr::saveToGameData,1700,_ZNK5uking2ui16PauseMenuDataMgr14saveToGameDataERKN4sead10OffsetListINS0_9PouchItemEEE
|
||||
0x0000007100970060,PauseMenuDataMgr::pouchGetCookResultMaybe,248,
|
||||
0x0000007100970158,PauseMenuDataMgr::x_1,268,
|
||||
0x0000007100970264,PauseMenuDataMgr::__auto5,116,
|
||||
0x00000071009702d8,sub_71009702D8,268,
|
||||
0x00000071009703e4,PauseMenuDataMgr::__auto10,216,
|
||||
0x00000071009704bc,PauseMenuDataMgr::removeOneFromInventory,1352,
|
||||
0x0000007100970a04,PauseMenuDataMgr::removeFromInventory_,896,
|
||||
0x0000007100970060,PauseMenuDataMgr::pouchGetCookResultMaybe,248,_ZN5uking2ui16PauseMenuDataMgr11cookItemGetERKN4ksys8CookItemE
|
||||
0x0000007100970158,PauseMenuDataMgr::x_1,268,_ZN5uking2ui16PauseMenuDataMgr26setCookDataOnLastAddedItemERKN4ksys8CookItemE
|
||||
0x0000007100970264,PauseMenuDataMgr::__auto5,116,_ZN5uking2ui16PauseMenuDataMgr22autoEquipLastAddedItemEv
|
||||
0x00000071009702d8,sub_71009702D8,268,_ZN5uking2ui16PauseMenuDataMgr9autoEquipEPNS0_9PouchItemERKN4sead10OffsetListIS2_EE?
|
||||
0x00000071009703e4,PauseMenuDataMgr::__auto10,216,_ZN5uking2ui16PauseMenuDataMgr10unequipAllENS0_13PouchItemTypeE?
|
||||
0x00000071009704bc,PauseMenuDataMgr::removeOneFromInventory,1352,_ZN5uking2ui16PauseMenuDataMgr10removeItemERKN4sead14SafeStringBaseIcEE
|
||||
0x0000007100970a04,PauseMenuDataMgr::removeFromInventory_,896,_ZN5uking2ui16PauseMenuDataMgr22removeWeaponIfEquippedERKN4sead14SafeStringBaseIcEE
|
||||
0x0000007100970d84,sub_7100970D84,512,_ZN5uking2ui16PauseMenuDataMgr11removeArrowERKN4sead14SafeStringBaseIcEEi
|
||||
0x0000007100970f84,PauseMenuDataMgr::getItemNum,1204,
|
||||
0x0000007100971438,PauseMenuDataMgr::setPorchValue1,204,_ZN5uking2ui16PauseMenuDataMgr18setWeaponItemValueEiNS0_13PouchItemTypeE
|
||||
0x0000007100970f84,PauseMenuDataMgr::getItemNum,1204,_ZNK5uking2ui16PauseMenuDataMgr12getItemCountERKN4sead14SafeStringBaseIcEEb!
|
||||
0x0000007100971438,PauseMenuDataMgr::setPorchValue1,204,_ZN5uking2ui16PauseMenuDataMgr26setEquippedWeaponItemValueEiNS0_13PouchItemTypeE
|
||||
0x0000007100971504,PauseMenuDataMgr::fromSaveDataMaybe,716,
|
||||
0x00000071009717d0,sub_71009717D0,40,_ZNK5uking2ui16PauseMenuDataMgr19getDefaultEquipmentENS0_13EquipmentSlotE
|
||||
0x00000071009717f8,PauseMenuDataMgr::hasItemMaybe,404,_ZNK5uking2ui16PauseMenuDataMgr7hasItemERKN4sead14SafeStringBaseIcEE
|
||||
|
@ -56441,7 +56441,7 @@
|
|||
0x000000710097e094,PauseMenuDataMgr::openItemCategoryIfNeeded,204,_ZNK5uking2ui16PauseMenuDataMgr24openItemCategoryIfNeededEv
|
||||
0x000000710097e160,PauseMenuDataMgr::giveDefaultSetItems,1804,
|
||||
0x000000710097e86c,PauseMenuDataMgr::doAddToPouch,6284,
|
||||
0x00000071009800f8,sub_71009800F8,612,
|
||||
0x00000071009800f8,sub_71009800F8,612,_ZN5uking2ui9PouchItem15sortIngredientsEv!
|
||||
0x000000710098035c,updateDivineBeastClearFlags,220,_ZN5uking2ui16PauseMenuDataMgr27updateDivineBeastClearFlagsEi
|
||||
0x0000007100980438,j__ZdlPv_464,4,_ZN5uking2ui9PouchItemD0Ev
|
||||
0x000000710098043c,sub_710098043C,648,
|
||||
|
|
Can't render this file because it is too large.
|
2
lib/sead
2
lib/sead
|
@ -1 +1 @@
|
|||
Subproject commit bad3539a0d834cd72b1d26c05b98456b3163881e
|
||||
Subproject commit ed983cc42dee614eb4fbc8d71303acec1c7b2c84
|
|
@ -10,6 +10,7 @@
|
|||
#include "KingSystem/ActorSystem/actActorUtil.h"
|
||||
#include "KingSystem/ActorSystem/actInfoData.h"
|
||||
#include "KingSystem/ActorSystem/actPlayerInfo.h"
|
||||
#include "KingSystem/Cooking/cookItem.h"
|
||||
#include "KingSystem/GameData/gdtCommonFlagsUtils.h"
|
||||
#include "KingSystem/GameData/gdtSpecialFlags.h"
|
||||
#include "KingSystem/System/PlayReportMgr.h"
|
||||
|
@ -945,6 +946,170 @@ void PauseMenuDataMgr::saveToGameData(const sead::OffsetList<PouchItem>& list) c
|
|||
}
|
||||
}
|
||||
|
||||
void PauseMenuDataMgr::cookItemGet(const ksys::CookItem& cook_item) {
|
||||
const auto* info = ksys::act::InfoData::instance();
|
||||
if (!info->hasTag(cook_item.name.cstr(), ksys::act::tags::CookResult))
|
||||
return;
|
||||
|
||||
const auto lock = sead::makeScopedLock(mCritSection);
|
||||
auto& lists = mItemLists;
|
||||
|
||||
ksys::PlayReportMgr::instance()->reportDebug("PouchGet", cook_item.name);
|
||||
const auto type = getType(cook_item.name);
|
||||
addToPouch(cook_item.name, type, lists, 1, false);
|
||||
setCookDataOnLastAddedItem(cook_item);
|
||||
saveToGameData(lists.list1);
|
||||
}
|
||||
|
||||
void PauseMenuDataMgr::setCookDataOnLastAddedItem(const ksys::CookItem& cook_item) {
|
||||
if (!mLastAddedItem)
|
||||
return;
|
||||
|
||||
mLastAddedItem->getCookData().setStaminaRecoverY(cook_item.stamina_recover_y);
|
||||
mLastAddedItem->getCookData().setStaminaRecoverX(cook_item.stamina_recover_x);
|
||||
mLastAddedItem->getCookData().setCookEffect1(cook_item.cook_effect_1);
|
||||
const int y = cook_item.cook_effect_0_y;
|
||||
const int x = cook_item.cook_effect_0_x;
|
||||
mLastAddedItem->getCookData().setCookEffect0({float(x), float(y)});
|
||||
for (s32 i = 0; i < cook_item.ingredients.size(); ++i)
|
||||
mLastAddedItem->setIngredient(i, cook_item.ingredients[i]);
|
||||
mLastAddedItem->sortIngredients();
|
||||
}
|
||||
|
||||
void PauseMenuDataMgr::autoEquipLastAddedItem() {
|
||||
if (mLastAddedItem && mLastAddedItem->getType() <= PouchItemType::ArmorLower) {
|
||||
const auto lock = sead::makeScopedLock(mCritSection);
|
||||
autoEquip(mLastAddedItem, getItems());
|
||||
}
|
||||
}
|
||||
|
||||
// NON_MATCHING: branching
|
||||
const sead::SafeString& PauseMenuDataMgr::autoEquip(PouchItem* item,
|
||||
const sead::OffsetList<PouchItem>& list) {
|
||||
const auto type = item->getType();
|
||||
if (type == PouchItemType::KeyItem)
|
||||
item->mEquipped = true;
|
||||
|
||||
if (type >= PouchItemType::Material)
|
||||
return sead::SafeString::cEmptyString;
|
||||
|
||||
if (isPouchItemArmor(type)) {
|
||||
for (auto& other : list) {
|
||||
if (other.getType() > PouchItemType::ArmorLower)
|
||||
break;
|
||||
if (other.getType() == type)
|
||||
other.mEquipped = false;
|
||||
}
|
||||
} else if (isPouchItemWeapon(type)) {
|
||||
for (auto& other : list) {
|
||||
if (other.getType() > PouchItemType::Shield)
|
||||
break;
|
||||
if (other.getType() == type)
|
||||
other.mEquipped = false;
|
||||
}
|
||||
}
|
||||
|
||||
item->mEquipped = true;
|
||||
updateInventoryInfo(list);
|
||||
saveToGameData(list);
|
||||
return sead::SafeString::cEmptyString;
|
||||
}
|
||||
|
||||
// NON_MATCHING: harmless reordering
|
||||
void PauseMenuDataMgr::unequipAll(PouchItemType type) {
|
||||
const auto lock = sead::makeScopedLock(mCritSection);
|
||||
|
||||
if (type == PouchItemType::Arrow)
|
||||
return;
|
||||
|
||||
for (auto& item : getItems()) {
|
||||
if (type == PouchItemType::Invalid) {
|
||||
if (item.getType() > PouchItemType::ArmorLower)
|
||||
break;
|
||||
if (item.isEquipped() && item.getType() != PouchItemType::Arrow)
|
||||
item.mEquipped = false;
|
||||
|
||||
} else {
|
||||
if (item.getType() > PouchItemType::ArmorLower)
|
||||
break;
|
||||
if (item.isEquipped() && item.getType() == type) {
|
||||
item.mEquipped = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KSYS_ALWAYS_INLINE inline void
|
||||
PauseMenuDataMgr::deleteItem_(const sead::OffsetList<PouchItem>& list, PouchItem* item,
|
||||
const sead::SafeString& name) {
|
||||
if (mItem_444f0 == item)
|
||||
mItem_444f0 = nullptr;
|
||||
|
||||
if (mLastAddedItem == item)
|
||||
mLastAddedItem = nullptr;
|
||||
|
||||
// Reset the PouchItem so that it is ready to be reused.
|
||||
getItems().erase(item);
|
||||
item->~PouchItem();
|
||||
new (item) PouchItem;
|
||||
mItemLists.list2.pushFront(item);
|
||||
|
||||
ksys::PlayReportMgr::instance()->reportDebug("PouchDelete", name);
|
||||
saveToGameData(list);
|
||||
updateInventoryInfo(list);
|
||||
updateListHeads();
|
||||
}
|
||||
|
||||
void PauseMenuDataMgr::removeItem(const sead::SafeString& name) {
|
||||
const auto lock = sead::makeScopedLock(mCritSection);
|
||||
const auto& items = getItems();
|
||||
|
||||
PouchItem* item = nullptr;
|
||||
for (auto& it : items) {
|
||||
if (name == it.getName() && !it.isEquipped()) {
|
||||
item = ⁢
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
// If the item is stackable, just remove one copy of the item if possible.
|
||||
auto* info = ksys::act::InfoData::instance();
|
||||
if (info->hasTag(item->getName().cstr(), ksys::act::tags::CanStack) && item->getValue() > 1) {
|
||||
item->mValue -= 1;
|
||||
ksys::PlayReportMgr::instance()->reportDebug("PouchDelete", name);
|
||||
updateInventoryInfo(items);
|
||||
updateListHeads();
|
||||
saveToGameData(items);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, delete the PouchItem entirely.
|
||||
deleteItem_(items, item, name);
|
||||
}
|
||||
|
||||
void PauseMenuDataMgr::removeWeaponIfEquipped(const sead::SafeString& name) {
|
||||
const auto lock = sead::makeScopedLock(mCritSection);
|
||||
if (!ksys::act::PlayerInfo::instance()->getPlayer())
|
||||
return;
|
||||
|
||||
const auto& items = getItems();
|
||||
|
||||
PouchItem* item = nullptr;
|
||||
for (auto& it : items) {
|
||||
if (name == it.getName() && it.isEquipped()) {
|
||||
item = ⁢
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (item)
|
||||
deleteItem_(items, item, name);
|
||||
}
|
||||
|
||||
void PauseMenuDataMgr::removeArrow(const sead::SafeString& arrow_name, int count) {
|
||||
if (!ksys::act::InfoData::instance()->hasTag(arrow_name.cstr(), ksys::act::tags::Arrow))
|
||||
return;
|
||||
|
@ -969,7 +1134,75 @@ void PauseMenuDataMgr::removeArrow(const sead::SafeString& arrow_name, int count
|
|||
ksys::gdt::setFlag_PorchItem_Value1(num, idx);
|
||||
}
|
||||
|
||||
void PauseMenuDataMgr::setWeaponItemValue(s32 value, PouchItemType type) {
|
||||
// NON_MATCHING: branch merging -- but this is pretty clearly equivalent
|
||||
int PauseMenuDataMgr::getItemCount(const sead::SafeString& name, bool count_equipped) const {
|
||||
const auto type = getType(name);
|
||||
if (isPouchItemInvalid(type))
|
||||
return 0;
|
||||
|
||||
const auto& items = getItems();
|
||||
sead::SafeString group_name;
|
||||
getSameGroupActorName(&group_name, name);
|
||||
|
||||
PouchItem* first = nullptr;
|
||||
switch (type) {
|
||||
case PouchItemType::Sword:
|
||||
first = getItemHead(PouchCategory::Sword);
|
||||
break;
|
||||
case PouchItemType::Bow:
|
||||
first = getItemHead(PouchCategory::Bow);
|
||||
break;
|
||||
case PouchItemType::Arrow:
|
||||
for (auto* item = getItemHead(PouchCategory::Bow); item; item = items.next(item)) {
|
||||
if (item->getType() > PouchItemType::Arrow)
|
||||
break;
|
||||
if (item->getType() == PouchItemType::Arrow) {
|
||||
first = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PouchItemType::Shield:
|
||||
first = getItemHead(PouchCategory::Shield);
|
||||
break;
|
||||
case PouchItemType::Food:
|
||||
first = getItemHead(PouchCategory::Food);
|
||||
break;
|
||||
case PouchItemType::KeyItem:
|
||||
first = getItemHead(PouchCategory::KeyItem);
|
||||
break;
|
||||
default:
|
||||
if (type > PouchItemType::Material)
|
||||
first = getItemHead(PouchCategory::Material);
|
||||
else
|
||||
first = getItemHead(PouchCategory::Armor);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ksys::act::InfoData::instance()->hasTag(group_name.cstr(), ksys::act::tags::CanStack)) {
|
||||
for (auto* item = first; item; item = items.next(item)) {
|
||||
if (group_name == item->getName())
|
||||
return item->getValue();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 count = 0;
|
||||
if (count_equipped) {
|
||||
for (auto* item = first; item; item = items.next(item)) {
|
||||
if (group_name == item->getName())
|
||||
count += item->get25();
|
||||
}
|
||||
} else {
|
||||
for (auto* item = first; item; item = items.next(item)) {
|
||||
if (group_name == item->getName() && item->get25())
|
||||
count += !item->isEquipped();
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void PauseMenuDataMgr::setEquippedWeaponItemValue(s32 value, PouchItemType type) {
|
||||
if (isPouchItemNotWeapon(type))
|
||||
return;
|
||||
|
||||
|
@ -1283,6 +1516,29 @@ bool PauseMenuDataMgr::hasZoraSoulPlus() const {
|
|||
return ksys::gdt::getFlag_IsGet_Obj_DLC_HeroSoul_Zora() && aoc::Manager::instance()->hasAoc3();
|
||||
}
|
||||
|
||||
[[gnu::noinline]] void PouchItem::sortIngredients() {
|
||||
mIngredients.sort(
|
||||
[](const sead::FixedSafeString<64>* lhs, const sead::FixedSafeString<64>* rhs) {
|
||||
auto* info = ksys::act::InfoData::instance();
|
||||
if (!lhs || !rhs || !info)
|
||||
return 0;
|
||||
|
||||
if (rhs->isEmpty()) {
|
||||
if (lhs->isEmpty())
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const s32 key1 = info->getSortKey(lhs->cstr());
|
||||
const s32 key2 = info->getSortKey(rhs->cstr());
|
||||
if (key1 < key2)
|
||||
return -1;
|
||||
if (key1 > key2)
|
||||
return 1;
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
|
||||
void PauseMenuDataMgr::updateDivineBeastClearFlags(int num_cleared_beasts) {
|
||||
switch (num_cleared_beasts) {
|
||||
|
|
|
@ -23,6 +23,10 @@ namespace uking::act {
|
|||
struct WeaponModifierInfo;
|
||||
}
|
||||
|
||||
namespace ksys {
|
||||
struct CookItem;
|
||||
}
|
||||
|
||||
namespace uking::ui {
|
||||
|
||||
constexpr int NumSwordsMax = 20;
|
||||
|
@ -149,6 +153,7 @@ public:
|
|||
|
||||
const sead::SafeString& getIngredient(s32 idx) const { return *mIngredients[idx]; }
|
||||
void setIngredient(s32 idx, const sead::SafeString& value) const { *mIngredients[idx] = value; }
|
||||
void sortIngredients();
|
||||
|
||||
// Only valid if this is a weapon.
|
||||
WeaponData& getWeaponData() { return mData.weapon; }
|
||||
|
@ -213,10 +218,27 @@ public:
|
|||
bool isWeaponSectionFull(const sead::SafeString& get_flag) const;
|
||||
|
||||
void itemGet(const sead::SafeString& name, int value, const act::WeaponModifierInfo* modifier);
|
||||
void cookItemGet(const ksys::CookItem& cook_item);
|
||||
|
||||
void setCookDataOnLastAddedItem(const ksys::CookItem& cook_item);
|
||||
|
||||
void autoEquipLastAddedItem();
|
||||
const sead::SafeString& autoEquip(PouchItem* item, const sead::OffsetList<PouchItem>& list);
|
||||
/// Unequip all inventory items with the specified type.
|
||||
/// If type is PouchItemType::Invalid, all inventory items will be unequipped.
|
||||
void unequipAll(PouchItemType type = PouchItemType::Invalid);
|
||||
|
||||
void removeItem(const sead::SafeString& name);
|
||||
void removeWeaponIfEquipped(const sead::SafeString& name);
|
||||
void removeArrow(const sead::SafeString& arrow_name, int count = 1);
|
||||
int getItemCount(const sead::SafeString& name, bool x = true) const;
|
||||
void setWeaponItemValue(s32 value, PouchItemType type);
|
||||
|
||||
int getItemCount(const sead::SafeString& name, bool count_equipped = true) const;
|
||||
|
||||
// TODO: requires CreatePlayerEquipActorMgr
|
||||
void createPlayerEquipment();
|
||||
void setEquippedWeaponItemValue(s32 value, PouchItemType type);
|
||||
const sead::SafeString& getDefaultEquipment(EquipmentSlot idx) const;
|
||||
|
||||
bool hasItem(const sead::SafeString& name) const;
|
||||
PouchItem* getMasterSword() const;
|
||||
|
||||
|
@ -296,6 +318,9 @@ private:
|
|||
bool equipped, const act::WeaponModifierInfo* modifier = nullptr,
|
||||
bool is_inventory_load = false);
|
||||
|
||||
void deleteItem_(const sead::OffsetList<PouchItem>& list, PouchItem* item,
|
||||
const sead::SafeString& name);
|
||||
|
||||
bool hasFreeSpaceForItem(const Lists& lists, const sead::SafeString& name, int n = 1) const;
|
||||
|
||||
/// @param num_cleared_beasts The number of divine beasts that have been done.
|
||||
|
|
|
@ -3,6 +3,7 @@ add_subdirectory(GameData)
|
|||
add_subdirectory(Resource)
|
||||
|
||||
add_subdirectory(ActorSystem)
|
||||
add_subdirectory(Cooking)
|
||||
add_subdirectory(Ecosystem)
|
||||
add_subdirectory(Event)
|
||||
add_subdirectory(Damage)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
target_sources(uking PRIVATE
|
||||
cookItem.cpp
|
||||
cookItem.h
|
||||
cookManager.cpp
|
||||
cookManager.h
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
#include "KingSystem/Cooking/cookItem.h"
|
||||
|
||||
namespace ksys {
|
||||
|
||||
CookItem::CookItem() = default;
|
||||
|
||||
} // namespace ksys
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <basis/seadTypes.h>
|
||||
#include <container/seadSafeArray.h>
|
||||
#include <prim/seadSafeString.h>
|
||||
#include "KingSystem/Utils/Types.h"
|
||||
|
||||
namespace ksys {
|
||||
|
||||
struct CookItem {
|
||||
CookItem();
|
||||
|
||||
sead::FixedSafeString<64> name{""};
|
||||
sead::SafeArray<sead::FixedSafeString<64>, 5> ingredients;
|
||||
f32 stamina_recover_x{};
|
||||
s32 stamina_recover_y{};
|
||||
s32 cook_effect_1{};
|
||||
s32 cook_effect_0_x = -1;
|
||||
f32 cook_effect_0_y{};
|
||||
bool _224{};
|
||||
};
|
||||
KSYS_CHECK_SIZE_NX150(CookItem, 0x228);
|
||||
|
||||
} // namespace ksys
|
|
@ -0,0 +1 @@
|
|||
#include "KingSystem/Cooking/cookManager.h"
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <heap/seadDisposer.h>
|
||||
|
||||
namespace ksys {
|
||||
|
||||
// TODO
|
||||
class CookingMgr {
|
||||
SEAD_SINGLETON_DISPOSER(CookingMgr)
|
||||
CookingMgr();
|
||||
// TODO: inline
|
||||
~CookingMgr();
|
||||
};
|
||||
|
||||
} // namespace ksys
|
Loading…
Reference in New Issue