Simplify new player inventory functions

This commit is contained in:
Kae 2023-10-31 05:34:26 +11:00
parent 012572c199
commit 7eb1cd8dd9
6 changed files with 99 additions and 68 deletions

View File

@ -19,7 +19,7 @@ enum class EquipmentSlot : uint8_t {
};
extern EnumMap<EquipmentSlot> const EquipmentSlotNames;
typedef pair<String, uint8_t> BagSlot;
typedef pair<String, unsigned> BagSlot;
strong_typedef(Empty, SwapSlot);
strong_typedef(Empty, TrashSlot);

View File

@ -183,6 +183,17 @@ bool PlayerInventory::consumeSlot(InventorySlot const& slot, uint64_t count) {
return consumed;
}
bool PlayerInventory::slotValid(InventorySlot const& slot) const {
if (auto bagSlot = slot.ptr<BagSlot>()) {
if (auto bag = bagContents(bagSlot->first)) {
if ((size_t)bagSlot->second >= bag->size())
return false;
}
else return false;
}
return true;
}
ItemPtr PlayerInventory::addItems(ItemPtr items) {
if (!items || items->empty())
return {};
@ -219,7 +230,7 @@ ItemPtr PlayerInventory::addToBags(ItemPtr items) {
if (!items)
break;
for (uint8_t i = 0; i < pair.second->size(); ++i) {
for (unsigned i = 0; i < pair.second->size(); ++i) {
if (!pair.second->at(i)) {
pair.second->setItem(i, take(items));
autoAddToCustomBar(BagSlot(pair.first, i));
@ -549,7 +560,7 @@ bool PlayerInventory::clearSwap() {
};
auto tryBag = [&](String const& bagType) {
for (uint8_t i = 0; i < m_bags[bagType]->size(); ++i) {
for (unsigned i = 0; i < m_bags[bagType]->size(); ++i) {
if (!m_swapSlot || !itemAllowedInBag(m_swapSlot, bagType))
break;
trySlot(BagSlot(bagType, i));

View File

@ -64,6 +64,8 @@ public:
bool consumeSlot(InventorySlot const& slot, uint64_t count = 1);
bool slotValid(InventorySlot const& slot) const;
// Adds items to any slot except the trash or swap slots, returns stack left
// over.
ItemPtr addItems(ItemPtr items);

View File

@ -2,6 +2,39 @@
namespace Star {
LuaValue LuaConverter<InventorySlot>::from(LuaEngine& engine, InventorySlot k) {
if (auto equipment = k.ptr<EquipmentSlot>())
return engine.createString(EquipmentSlotNames.getRight(*equipment));
else if (auto bag = k.ptr<BagSlot>()) {
auto table = engine.createTable(2, 0);
table.set(1, bag->first);
table.set(2, bag->second);
return table;
}
else if (k.is<SwapSlot>())
return engine.createString("Swap");
else if (k.is<TrashSlot>())
return engine.createString("Trash");
}
Maybe<InventorySlot> LuaConverter<InventorySlot>::to(LuaEngine&, LuaValue const& v) {
if (auto str = v.ptr<LuaString>()) {
auto string = str->toString();
if (string.equalsIgnoreCase("Swap"))
return SwapSlot();
else if (string.equalsIgnoreCase("Trash"))
return TrashSlot();
else if (auto equipment = EquipmentSlotNames.leftPtr(str->toString()))
return *equipment;
else
return {};
}
else if (auto table = v.ptr<LuaTable>())
return BagSlot(table->get<LuaString>(1).toString(), table->get<unsigned>(2));
else
return {};
}
LuaValue LuaConverter<CollisionKind>::from(LuaEngine& engine, CollisionKind k) {
return engine.createString(CollisionKindNames.getRight(k));
}

View File

@ -2,6 +2,7 @@
#define STAR_LUA_GAME_CONVERTERS_HPP
#include "StarLuaConverters.hpp"
#include "StarInventoryTypes.hpp"
#include "StarCollisionBlock.hpp"
#include "StarPlatformerAStar.hpp"
#include "StarActorMovementController.hpp"
@ -14,6 +15,12 @@
namespace Star {
template <>
struct LuaConverter<InventorySlot> {
static LuaValue from(LuaEngine& engine, InventorySlot k);
static Maybe<InventorySlot> to(LuaEngine& engine, LuaValue const& v);
};
template <>
struct LuaConverter<CollisionKind> {
static LuaValue from(LuaEngine& engine, CollisionKind k);

View File

@ -153,81 +153,59 @@ LuaCallbacks LuaBindings::makePlayerCallbacks(Player* player) {
}
});
callbacks.registerCallback("actionBarItem", [player](MVariant<int, String> const& slot, Maybe<bool> offHand) -> Json {
callbacks.registerCallback("actionBarSlotLink", [player](int slot, String const& handName) {
auto inventory = player->inventory();
if (!slot) return {};
else if (auto index = slot.ptr<int>()) {
CustomBarIndex wrapped = (*index - 1) % (unsigned)inventory->customBarIndexes();
Maybe<InventorySlot> s;
if (offHand.value(false)) s = inventory->customBarSecondarySlot(wrapped);
else s = inventory->customBarPrimarySlot(wrapped);
if (s.isNothing()) return {};
return itemSafeDescriptor(inventory->itemsAt(s.value())).toJson();
} else {
return itemSafeDescriptor(inventory->essentialItem(EssentialItemNames.getLeft(slot.get<String>()))).toJson();
}
CustomBarIndex wrapped = (slot - 1) % (unsigned)inventory->customBarIndexes();
if (handName == "primary")
return inventory->customBarPrimarySlot(wrapped);
else if (handName == "alt")
return inventory->customBarSecondarySlot(wrapped);
else
throw StarException(strf("Unknown tool hand {}", handName));
});
callbacks.registerCallback("setActionBarItem", [player](MVariant<int, String> const& slot, bool offHand, Json const& item) {
callbacks.registerCallback("setActionBarSlotLink", [player](int slot, String const& handName, Maybe<InventorySlot> inventorySlot) {
auto inventory = player->inventory();
CustomBarIndex wrapped = (slot - 1) % (unsigned)inventory->customBarIndexes();
if (inventorySlot && !inventory->slotValid(*inventorySlot))
inventorySlot.reset();
if (handName == "primary")
inventory->setCustomBarPrimarySlot(wrapped, inventorySlot);
else if (handName == "alt")
inventory->setCustomBarSecondarySlot(wrapped, inventorySlot);
else
throw StarException(strf("Unknown tool hand {}", handName));
});
callbacks.registerCallback("itemBagSize", [player](String const& bagName) -> Maybe<unsigned> {
if (auto bag = player->inventory()->bagContents(bagName))
return (unsigned)bag->size();
else
return {};
});
callbacks.registerCallback("itemAllowedInBag", [player](String const& bagName, Json const& item) {
auto inventory = player->inventory();
auto itemDatabase = Root::singleton().itemDatabase();
if (!slot) return;
else if (auto index = slot.ptr<int>()) {
CustomBarIndex wrapped = (*index - 1) % (unsigned)inventory->customBarIndexes();
if (item.type() == Json::Type::Object && item.contains("name")) {
auto itm = itemDatabase->item(ItemDescriptor(item));
Maybe<InventorySlot> found;
inventory->forEveryItem([player, &found, &itm](InventorySlot const& slot, ItemPtr const& item){
if (!found.isNothing()) return;
if (item->matches(itm, true)) found = slot;
});
if (!found.isNothing()) {
if (offHand) inventory->setCustomBarSecondarySlot(wrapped, found.value());
else inventory->setCustomBarPrimarySlot(wrapped, found.value());
}
} else {
if (offHand) inventory->setCustomBarSecondarySlot(wrapped, {});
else inventory->setCustomBarPrimarySlot(wrapped, {});
}
} else {
// place into essential item slot
//if (item.isNothing()) inventory->setEssentialItem(EssentialItemNames.getLeft(slot.get<String>()), {});
inventory->setEssentialItem(EssentialItemNames.getLeft(slot.get<String>()), itemDatabase->item(ItemDescriptor(item)));
// TODO: why does this always clear the slot. it's literally the same code as giveEssentialItem
}
if (!inventory->bagContents(bagName))
return false;
else
return inventory->itemAllowedInBag(itemDatabase->item(ItemDescriptor(item)), bagName);
});
callbacks.registerCallback("itemBagSize", [player](String const& bag) {
auto inventory = player->inventory();
auto b = inventory->bagContents(bag);
if (!b) return 0;
return (int)b->size();
callbacks.registerCallback("item", [player](InventorySlot const& slot) -> Maybe<Json> {
if (!player->inventory()->slotValid(slot)) return {};
if (auto item = player->inventory()->itemsAt(slot))
return itemSafeDescriptor(item).toJson();
else
return {};
});
callbacks.registerCallback("itemAllowedInBag", [player](String const& bag, Json const& item) {
auto inventory = player->inventory();
callbacks.registerCallback("setItem", [player](InventorySlot const& slot, Json const& item) {
if (!player->inventory()->slotValid(slot)) return;
auto itemDatabase = Root::singleton().itemDatabase();
if (!inventory->bagContents(bag)) return false;
return inventory->itemAllowedInBag(itemDatabase->item(ItemDescriptor(item)), bag);
});
callbacks.registerCallback("itemBagItem", [player](String const& bag, int slot) -> Json {
auto inventory = player->inventory();
auto b = inventory->bagContents(bag);
if (!b || slot <= 0 || slot > (int)b->size()) return {};
return itemSafeDescriptor(b->at(slot - 1)).toJson();
});
callbacks.registerCallback("setItemBagItem", [player](String const& bag, int slot, Json const& item) {
auto inventory = player->inventory();
auto itemDatabase = Root::singleton().itemDatabase();
auto b = const_pointer_cast<ItemBag>(inventory->bagContents(bag)); // bit of a Naughty Access Cheat here, but
if (!b || slot <= 0 || slot > (int)b->size()) return;
b->setItem(slot - 1, itemDatabase->item(ItemDescriptor(item)));
player->inventory()->setItem(slot, itemDatabase->item(ItemDescriptor(item)));
});
callbacks.registerCallback("setDamageTeam", [player](String const& typeName, Maybe<uint16_t> teamNumber) {