Skip to content

Commit

Permalink
Merge branch 'main' into fix/adjust-bosses-lever-and-other-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
luan authored Dec 2, 2023
2 parents 328cef8 + 0e2d7fd commit 6e12718
Show file tree
Hide file tree
Showing 8 changed files with 598 additions and 442 deletions.
294 changes: 165 additions & 129 deletions data-otservbr-global/npc/battlemart.lua

Large diffs are not rendered by default.

643 changes: 349 additions & 294 deletions data-otservbr-global/npc/hireling.lua

Large diffs are not rendered by default.

16 changes: 9 additions & 7 deletions src/creatures/npcs/npc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ void Npc::onPlayerBuyItem(std::shared_ptr<Player> player, uint16_t itemId, uint8
}

uint32_t buyPrice = 0;
const std::vector<ShopBlock> &shopVector = getShopItemVector();
const std::vector<ShopBlock> &shopVector = getShopItemVector(player->getGUID());
for (ShopBlock shopBlock : shopVector) {
if (itemType.id == shopBlock.itemId && shopBlock.itemBuyPrice != 0) {
buyPrice = shopBlock.itemBuyPrice;
Expand Down Expand Up @@ -370,7 +370,7 @@ void Npc::onPlayerSellItem(std::shared_ptr<Player> player, uint16_t itemId, uint

uint32_t sellPrice = 0;
const ItemType &itemType = Item::items[itemId];
const std::vector<ShopBlock> &shopVector = getShopItemVector();
const std::vector<ShopBlock> &shopVector = getShopItemVector(player->getGUID());
for (ShopBlock shopBlock : shopVector) {
if (itemType.id == shopBlock.itemId && shopBlock.itemSellPrice != 0) {
sellPrice = shopBlock.itemSellPrice;
Expand Down Expand Up @@ -642,23 +642,25 @@ bool Npc::getRandomStep(Direction &moveDirection) {
return false;
}

void Npc::addShopPlayer(const std::shared_ptr<Player> &player) {
void Npc::addShopPlayer(const std::shared_ptr<Player> &player, const std::vector<ShopBlock> &shopItems /* = {}*/) {
if (!player) {
return;
}
shopPlayerMap.try_emplace(player->getID(), player);

shopPlayerMap.try_emplace(player->getGUID(), shopItems);
}

void Npc::removeShopPlayer(const std::shared_ptr<Player> &player) {
if (!player) {
return;
}
shopPlayerMap.erase(player->getID());

shopPlayerMap.erase(player->getGUID());
}

void Npc::closeAllShopWindows() {
for (auto &[_, playerPtr] : shopPlayerMap) {
auto shopPlayer = playerPtr.lock();
for (const auto &[playerGUID, playerPtr] : shopPlayerMap) {
auto shopPlayer = g_game().getPlayerByGUID(playerGUID);
if (shopPlayer) {
shopPlayer->closeShopWindow();
}
Expand Down
13 changes: 10 additions & 3 deletions src/creatures/npcs/npc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,14 @@ class Npc final : public Creature {
npcType->info.currencyId = currency;
}

std::vector<ShopBlock> getShopItemVector() {
std::vector<ShopBlock> getShopItemVector(uint32_t playerGUID) {
if (playerGUID != 0) {
auto it = shopPlayerMap.find(playerGUID);
if (it != shopPlayerMap.end() && !it->second.empty()) {
return it->second;
}
}

return npcType->info.shopItemVector;
}

Expand Down Expand Up @@ -159,7 +166,7 @@ class Npc final : public Creature {
internalLight = npcType->info.light;
}

void addShopPlayer(const std::shared_ptr<Player> &player);
void addShopPlayer(const std::shared_ptr<Player> &player, const std::vector<ShopBlock> &shopItems = {});
void removeShopPlayer(const std::shared_ptr<Player> &player);
void closeAllShopWindows();

Expand All @@ -178,7 +185,7 @@ class Npc final : public Creature {

std::map<uint32_t, uint16_t> playerInteractions;

phmap::flat_hash_map<uint32_t, std::weak_ptr<Player>> shopPlayerMap;
phmap::flat_hash_map<uint32_t, std::vector<ShopBlock>> shopPlayerMap;

std::shared_ptr<NpcType> npcType;
std::shared_ptr<SpawnNpc> spawnNpc;
Expand Down
5 changes: 2 additions & 3 deletions src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1474,7 +1474,7 @@ void Player::openImbuementWindow(std::shared_ptr<Item> item) {

void Player::sendSaleItemList(const std::map<uint16_t, uint16_t> &inventoryMap) const {
if (client && shopOwner) {
client->sendSaleItemList(shopOwner->getShopItemVector(), inventoryMap);
client->sendSaleItemList(shopOwner->getShopItemVector(getGUID()), inventoryMap);
}
}

Expand Down Expand Up @@ -1781,7 +1781,6 @@ bool Player::openShopWindow(std::shared_ptr<Npc> npc) {
}

setShopOwner(npc);
npc->addShopPlayer(static_self_cast<Player>());

sendShop(npc);
std::map<uint16_t, uint16_t> inventoryMap;
Expand Down Expand Up @@ -4130,7 +4129,7 @@ bool Player::hasShopItemForSale(uint16_t itemId, uint8_t subType) const {
}

const ItemType &itemType = Item::items[itemId];
std::vector<ShopBlock> shoplist = shopOwner->getShopItemVector();
std::vector<ShopBlock> shoplist = shopOwner->getShopItemVector(getGUID());
return std::any_of(shoplist.begin(), shoplist.end(), [&](const ShopBlock &shopBlock) {
return shopBlock.itemId == itemId && shopBlock.itemBuyPrice != 0 && (!itemType.isFluidContainer() || shopBlock.itemSubType == subType);
});
Expand Down
65 changes: 60 additions & 5 deletions src/lua/functions/creatures/npc/npc_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,60 @@ int NpcFunctions::luaNpcOpenShopWindow(lua_State* L) {
return 1;
}

npc->addShopPlayer(player);
pushBoolean(L, player->openShopWindow(npc));
return 1;
}

int NpcFunctions::luaNpcOpenShopWindowTable(lua_State* L) {
// npc:openShopWindowTable(player, items)
const auto &npc = getUserdataShared<Npc>(L, 1);
if (!npc) {
reportErrorFunc(getErrorDesc(LUA_ERROR_NPC_NOT_FOUND));
pushBoolean(L, false);
return 1;
}

const auto &player = getUserdataShared<Player>(L, 2);
if (!player) {
reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
return 1;
}

if (lua_istable(L, 3) == 0) {
reportError(__FUNCTION__, "item list is not a table.");
pushBoolean(L, false);
return 1;
}

std::vector<ShopBlock> items;
lua_pushnil(L);
while (lua_next(L, 3) != 0) {
const auto tableIndex = lua_gettop(L);
ShopBlock item;

auto itemId = getField<uint16_t>(L, tableIndex, "clientId");
auto subType = getField<int32_t>(L, tableIndex, "subType");
if (subType == 0) {
subType = getField<int32_t>(L, tableIndex, "subtype");
lua_pop(L, 1);
}

auto buyPrice = getField<uint32_t>(L, tableIndex, "buy");
auto sellPrice = getField<uint32_t>(L, tableIndex, "sell");
auto storageKey = getField<int32_t>(L, tableIndex, "storageKey");
auto storageValue = getField<int32_t>(L, tableIndex, "storageValue");
auto realName = getFieldString(L, tableIndex, "name");
g_logger().debug("[{}] item '{}' sell price '{}', buyprice '{}'", __FUNCTION__, realName, sellPrice, buyPrice);

items.emplace_back(itemId, subType, buyPrice, sellPrice, storageKey, storageValue, std::move(realName));
lua_pop(L, 8);
}
lua_pop(L, 3);

// Close any eventual other shop window currently open.
player->closeShopWindow(true);
npc->addShopPlayer(player, items);
pushBoolean(L, player->openShopWindow(npc));
return 1;
}
Expand Down Expand Up @@ -391,8 +445,8 @@ int NpcFunctions::luaNpcIsMerchant(lua_State* L) {
return 1;
}

const std::vector<ShopBlock> shopItems = npc->getShopItemVector();

auto playerGUID = getNumber<uint32_t>(L, 2, 0);
const auto &shopItems = npc->getShopItemVector(playerGUID);
if (shopItems.empty()) {
pushBoolean(L, false);
return 1;
Expand All @@ -411,8 +465,9 @@ int NpcFunctions::luaNpcGetShopItem(lua_State* L) {
return 1;
}

const std::vector<ShopBlock> &shopVector = npc->getShopItemVector();
for (ShopBlock shopBlock : shopVector) {
auto playerGUID = getNumber<uint32_t>(L, 2, 0);
const auto &shopItems = npc->getShopItemVector(playerGUID);
for (ShopBlock shopBlock : shopItems) {
setField(L, "id", shopBlock.itemId);
setField(L, "name", shopBlock.itemName);
setField(L, "subType", shopBlock.itemSubType);
Expand Down Expand Up @@ -522,7 +577,7 @@ int NpcFunctions::luaNpcSellItem(lua_State* L) {
}

uint64_t pricePerUnit = 0;
const std::vector<ShopBlock> &shopVector = npc->getShopItemVector();
const std::vector<ShopBlock> &shopVector = npc->getShopItemVector(player->getGUID());
for (ShopBlock shopBlock : shopVector) {
if (itemId == shopBlock.itemId && shopBlock.itemBuyPrice != 0) {
pricePerUnit = shopBlock.itemBuyPrice;
Expand Down
2 changes: 2 additions & 0 deletions src/lua/functions/creatures/npc/npc_functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class NpcFunctions final : LuaScriptInterface {
registerMethod(L, "Npc", "isInTalkRange", NpcFunctions::luaNpcIsInTalkRange);
registerMethod(L, "Npc", "isPlayerInteractingOnTopic", NpcFunctions::luaNpcIsPlayerInteractingOnTopic);
registerMethod(L, "Npc", "openShopWindow", NpcFunctions::luaNpcOpenShopWindow);
registerMethod(L, "Npc", "openShopWindowTable", NpcFunctions::luaNpcOpenShopWindowTable);
registerMethod(L, "Npc", "closeShopWindow", NpcFunctions::luaNpcCloseShopWindow);
registerMethod(L, "Npc", "getShopItem", NpcFunctions::luaNpcGetShopItem);
registerMethod(L, "Npc", "isMerchant", NpcFunctions::luaNpcIsMerchant);
Expand Down Expand Up @@ -73,6 +74,7 @@ class NpcFunctions final : LuaScriptInterface {
static int luaNpcIsInTalkRange(lua_State* L);
static int luaNpcIsPlayerInteractingOnTopic(lua_State* L);
static int luaNpcOpenShopWindow(lua_State* L);
static int luaNpcOpenShopWindowTable(lua_State* L);
static int luaNpcCloseShopWindow(lua_State* L);
static int luaNpcGetShopItem(lua_State* L);
static int luaNpcIsMerchant(lua_State* L);
Expand Down
2 changes: 1 addition & 1 deletion src/server/network/protocol/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4360,7 +4360,7 @@ void ProtocolGame::sendShop(std::shared_ptr<Npc> npc) {
msg.addString(std::string()); // Currency name
}

std::vector<ShopBlock> shoplist = npc->getShopItemVector();
std::vector<ShopBlock> shoplist = npc->getShopItemVector(player->getGUID());
uint16_t itemsToSend = std::min<size_t>(shoplist.size(), std::numeric_limits<uint16_t>::max());
msg.add<uint16_t>(itemsToSend);

Expand Down

0 comments on commit 6e12718

Please sign in to comment.