Skip to content

Commit

Permalink
Merge branch 'main-canary' into ot-projeto-(rebase-13/12/23)
Browse files Browse the repository at this point in the history
  • Loading branch information
jacques-tony committed Dec 13, 2023
2 parents 7aa59a1 + e570944 commit 1eaf75c
Show file tree
Hide file tree
Showing 16 changed files with 124 additions and 58 deletions.
3 changes: 2 additions & 1 deletion config.lua.dist
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,13 @@ statusProtocolPort = 7171
maxPlayers = 0
serverName = "PhoenixOT"
serverMotd = "Welcome to the PhoenixOT!"
onePlayerOnlinePerAccount = false
statusTimeout = 5 * 1000
replaceKickOnLogin = true
maxPacketsPerSecond = 25
maxItem = 2000
maxContainer = 100
maxPlayersOnlinePerAccount = 1
maxPlayersOutsidePZPerAccount = 1

-- Packet Compression
-- Minimize network bandwith and reduce ping
Expand Down
10 changes: 0 additions & 10 deletions data-otservbr-global/lib/compat/compat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -573,16 +573,6 @@ function getOnlinePlayers()
return result
end

function getPlayersByAccountNumber(accountNumber)
local result = {}
for _, player in ipairs(Game.getPlayers()) do
if player:getAccountId() == accountNumber then
result[#result + 1] = player:getId()
end
end
return result
end

function getPlayerGUIDByName(name)
local player = Player(name)
if player then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ monster.loot = {
monster.attacks = {
{ name = "melee", interval = 2000, chance = 100, minDamage = -100, maxDamage = -300 },
{ name = "combat", interval = 2500, chance = 35, type = COMBAT_ENERGYDAMAGE, minDamage = -100, maxDamage = -300, radius = 4, target = false, effect = CONST_ME_ENERGYHIT },
{ name = "combat", interval = 2000, chance = 35, type = COMBAT_LIFEDRAIN, minDamage = -100, maxDamage = -300, radius = 3, target = true, effect = CONST_ME_GHOSTLYBITE },
{ name = "combat", interval = 2000, chance = 35, type = COMBAT_LIFEDRAIN, minDamage = -100, maxDamage = -300, radius = 3, target = true, effect = CONST_ME_GHOSTLY_BITE },
{ name = "combat", interval = 3000, chance = 45, type = COMBAT_PHYSICALDAMAGE, minDamage = -100, maxDamage = -300, range = 1, radius = 1, target = true, effect = CONST_ME_EXPLOSIONAREA },
}

Expand Down
2 changes: 1 addition & 1 deletion data-otservbr-global/scripts/actions/other/potions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ function flaskPotion.onUse(player, item, fromPosition, target, toPosition, isHot
end

local potion = potions[item:getId()]
if potion.level and player:getLevel() < potion.level or potion.vocations and not table.contains(potion.vocations, player:getVocation():getBaseId()) and not (player:getGroup():getId() >= 2) then
if potion.level and player:getLevel() < potion.level or potion.vocations and not table.contains(potion.vocations, player:getVocation():getBaseId()) and not (player:getGroup():getId() >= GROUP_TYPE_GAMEMASTER) then
player:say(potion.description, MESSAGE_POTION)
return true
end
Expand Down
22 changes: 22 additions & 0 deletions data-otservbr-global/scripts/spells/monster/sparks_chain.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
local combat = Combat()
combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_LIFEDRAIN)
combat:setParameter(COMBAT_PARAM_CHAIN_EFFECT, CONST_ME_MAGIC_RED)

function getChainValue(creature)
return 2, 3, false
end

combat:setCallback(CALLBACK_PARAM_CHAINVALUE, "getChainValue")

local spell = Spell("instant")

function spell.onCastSpell(creature, var)
return combat:execute(creature, var)
end

spell:name("sparks chain")
spell:words("###6054")
spell:needLearn(true)
spell:cooldown("2000")
spell:isSelfTarget(true)
spell:register()
12 changes: 0 additions & 12 deletions data/libs/functions/game.lua
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,6 @@ function Game.getHouseByPlayerGUID(playerGUID)
return nil
end

function Game.getPlayersByAccountNumber(accountNumber)
local result = {}
local players, player = Game.getPlayers()
for i = 1, #players do
player = players[i]
if player:getAccountId() == accountNumber then
result[#result + 1] = player
end
end
return result
end

function Game.getPlayersByIPAddress(ip, mask)
if not mask then
mask = 0xFFFFFFFF
Expand Down
2 changes: 1 addition & 1 deletion data/libs/functions/player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function Player.feed(self, food)
end

function Player.getClosestFreePosition(self, position, extended)
if self:getGroup():getAccess() and self:getAccountType() >= ACCOUNT_TYPE_GOD then
if self:getGroup():getAccess() and self:getAccountType() == ACCOUNT_TYPE_GOD then
return position
end
return Creature.getClosestFreePosition(self, position, extended)
Expand Down
2 changes: 2 additions & 0 deletions src/config/config_definitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ enum ConfigKey_t : uint16_t {
MAX_PLAYERS,
WHEEL_POINTS_PER_RESETS,
MULTIPLIER_ATTACKONFIST,
MAX_PLAYERS_OUTSIDE_PZ_PER_ACCOUNT,
MAX_PLAYERS_PER_ACCOUNT,
MAX_SPEED_ATTACKONFIST,
METRICS_ENABLE_OSTREAM,
METRICS_ENABLE_PROMETHEUS,
Expand Down
3 changes: 2 additions & 1 deletion src/config/configmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ bool ConfigManager::load() {
}

loadBoolConfig(L, ALLOW_CHANGEOUTFIT, "allowChangeOutfit", true);
loadBoolConfig(L, ONE_PLAYER_ON_ACCOUNT, "onePlayerOnlinePerAccount", true);
loadIntConfig(L, MAX_PLAYERS_PER_ACCOUNT, "maxPlayersOnlinePerAccount", 1);
loadIntConfig(L, MAX_PLAYERS_OUTSIDE_PZ_PER_ACCOUNT, "maxPlayersOutsidePZPerAccount", 1);
loadBoolConfig(L, AIMBOT_HOTKEY_ENABLED, "hotkeyAimbotEnabled", true);
loadBoolConfig(L, REMOVE_RUNE_CHARGES, "removeChargesFromRunes", true);
loadBoolConfig(L, EXPERIENCE_FROM_PLAYERS, "experienceByKillingPlayers", false);
Expand Down
19 changes: 19 additions & 0 deletions src/creatures/combat/spells.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,25 @@ Spells::Spells() = default;
Spells::~Spells() = default;

TalkActionResult_t Spells::playerSaySpell(std::shared_ptr<Player> player, std::string &words) {
auto maxOnline = g_configManager().getNumber(MAX_PLAYERS_PER_ACCOUNT, __FUNCTION__);
auto tile = player->getTile();
if (maxOnline > 1 && player->getAccountType() < account::ACCOUNT_TYPE_GAMEMASTER && tile && !tile->hasFlag(TILESTATE_PROTECTIONZONE)) {
auto maxOutsizePZ = g_configManager().getNumber(MAX_PLAYERS_OUTSIDE_PZ_PER_ACCOUNT, __FUNCTION__);
auto accountPlayers = g_game().getPlayersByAccount(player->getAccount());
int countOutsizePZ = 0;
for (const auto &accountPlayer : accountPlayers) {
if (accountPlayer == player || accountPlayer->isOffline()) {
continue;
}
if (accountPlayer->getTile() && !accountPlayer->getTile()->hasFlag(TILESTATE_PROTECTIONZONE)) {
++countOutsizePZ;
}
}
if (countOutsizePZ >= maxOutsizePZ) {
player->sendTextMessage(MESSAGE_FAILURE, fmt::format("You cannot cast spells while you have {} character(s) outside of a protection zone.", maxOutsizePZ));
return TALKACTION_FAILED;
}
}
std::string str_words = words;

if (player->hasCondition(CONDITION_FEARED)) {
Expand Down
32 changes: 14 additions & 18 deletions src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5987,32 +5987,28 @@ void Player::clearModalWindows() {
}

uint16_t Player::getHelpers() const {
uint16_t helpers;

if (guild && party) {
phmap::flat_hash_set<std::shared_ptr<Player>> helperSet;
const auto &guildMembers = guild->getMembersOnline();

const auto guildMembers = guild->getMembersOnline();
helperSet.insert(guildMembers.begin(), guildMembers.end());
stdext::vector_set<std::shared_ptr<Player>> helperSet;
helperSet.insert(helperSet.end(), guildMembers.begin(), guildMembers.end());
helperSet.insertAll(party->getMembers());
helperSet.insertAll(party->getInvitees());

const auto partyMembers = party->getMembers();
helperSet.insert(partyMembers.begin(), partyMembers.end());
helperSet.emplace(party->getLeader());

const auto partyInvitees = party->getInvitees();
helperSet.insert(partyInvitees.begin(), partyInvitees.end());
return static_cast<uint16_t>(helperSet.size());
}

helperSet.insert(party->getLeader());
if (guild) {
return static_cast<uint16_t>(guild->getMemberCountOnline());
}

helpers = helperSet.size();
} else if (guild) {
helpers = guild->getMemberCountOnline();
} else if (party) {
helpers = party->getMemberCount() + party->getInvitationCount() + 1;
} else {
helpers = 0;
if (party) {
return static_cast<uint16_t>(party->getMemberCount() + party->getInvitationCount() + 1);
}

return helpers;
return 0u;
}

void Player::sendClosePrivate(uint16_t channelId) {
Expand Down
16 changes: 11 additions & 5 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -830,13 +830,19 @@ ReturnValue Game::getPlayerByNameWildcard(const std::string &s, std::shared_ptr<
return RETURNVALUE_NOERROR;
}

std::shared_ptr<Player> Game::getPlayerByAccount(uint32_t acc) {
for (const auto &it : players) {
if (it.second->getAccountId() == acc) {
return it.second;
std::vector<std::shared_ptr<Player>> Game::getPlayersByAccount(std::shared_ptr<account::Account> acc, bool allowOffline /* = false */) {
auto [accountPlayers, error] = acc->getAccountPlayers();
if (error != account::ERROR_NO) {
return {};
}
std::vector<std::shared_ptr<Player>> ret;
for (const auto &[name, _] : accountPlayers) {
auto player = getPlayerByName(name, allowOffline);
if (player) {
ret.push_back(player);
}
}
return nullptr;
return ret;
}

bool Game::internalPlaceCreature(std::shared_ptr<Creature> creature, const Position &pos, bool extendedPos /*=false*/, bool forced /*= false*/, bool creatureCheck /*= false*/) {
Expand Down
2 changes: 1 addition & 1 deletion src/game/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ class Game {

ReturnValue getPlayerByNameWildcard(const std::string &s, std::shared_ptr<Player> &player);

std::shared_ptr<Player> getPlayerByAccount(uint32_t acc);
std::vector<std::shared_ptr<Player>> getPlayersByAccount(std::shared_ptr<account::Account> acc, bool allowOffline = false);

bool internalPlaceCreature(std::shared_ptr<Creature> creature, const Position &pos, bool extendedPos = false, bool forced = false, bool creatureCheck = false);

Expand Down
21 changes: 21 additions & 0 deletions src/items/tile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,27 @@ ReturnValue Tile::queryAdd(int32_t, const std::shared_ptr<Thing> &thing, uint32_
}

const auto playerTile = player->getTile();
// moving from a pz tile to a non-pz tile
if (playerTile && playerTile->hasFlag(TILESTATE_PROTECTIONZONE)) {
auto maxOnline = g_configManager().getNumber(MAX_PLAYERS_PER_ACCOUNT, __FUNCTION__);
if (maxOnline > 1 && player->getAccountType() < account::ACCOUNT_TYPE_GAMEMASTER && !hasFlag(TILESTATE_PROTECTIONZONE)) {
auto maxOutsizePZ = g_configManager().getNumber(MAX_PLAYERS_OUTSIDE_PZ_PER_ACCOUNT, __FUNCTION__);
auto accountPlayers = g_game().getPlayersByAccount(player->getAccount());
int countOutsizePZ = 0;
for (const auto &accountPlayer : accountPlayers) {
if (accountPlayer == player || accountPlayer->isOffline()) {
continue;
}
if (accountPlayer->getTile() && !accountPlayer->getTile()->hasFlag(TILESTATE_PROTECTIONZONE)) {
++countOutsizePZ;
}
}
if (countOutsizePZ >= maxOutsizePZ) {
player->sendCreatureSay(player, TALKTYPE_MONSTER_SAY, fmt::format("You can only have {} character{} from your account outside of a protection zone.", maxOutsizePZ == 1 ? "one" : std::to_string(maxOutsizePZ), maxOutsizePZ > 1 ? "s" : ""), &getPosition());
return RETURNVALUE_NOTPOSSIBLE;
}
}
}
if (playerTile && player->isPzLocked()) {
if (!playerTile->hasFlag(TILESTATE_PVPZONE)) {
// player is trying to enter a pvp zone while being pz-locked
Expand Down
10 changes: 5 additions & 5 deletions src/lua/functions/creatures/npc/npc_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,6 @@ int NpcFunctions::luaNpcOpenShopWindowTable(lua_State* L) {
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");
Expand All @@ -397,10 +396,11 @@ int NpcFunctions::luaNpcOpenShopWindowTable(lua_State* L) {
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));
auto itemName = getFieldString(L, tableIndex, "itemName");
if (itemName.empty()) {
itemName = Item::items[itemId].name;
}
items.emplace_back(itemId, subType, buyPrice, sellPrice, storageKey, storageValue, itemName);
lua_pop(L, 8);
}
lua_pop(L, 3);
Expand Down
24 changes: 22 additions & 2 deletions src/server/network/protocol/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -515,9 +515,11 @@ void ProtocolGame::login(const std::string &name, uint32_t accountId, OperatingS
return;
}

if (g_configManager().getBoolean(ONE_PLAYER_ON_ACCOUNT, __FUNCTION__) && player->getAccountType() < account::ACCOUNT_TYPE_GAMEMASTER && g_game().getPlayerByAccount(player->getAccountId())) {
auto onlineCount = g_game().getPlayersByAccount(player->getAccount()).size();
auto maxOnline = g_configManager().getNumber(MAX_PLAYERS_PER_ACCOUNT, __FUNCTION__);
if (player->getAccountType() < account::ACCOUNT_TYPE_GAMEMASTER && onlineCount >= maxOnline) {
g_game().removePlayerUniqueLogin(player);
disconnectClient("You may only login with one character\nof your account at the same time.");
disconnectClient(fmt::format("You may only login with {} character{}\nof your account at the same time.", maxOnline, maxOnline > 1 ? "s" : ""));
return;
}

Expand Down Expand Up @@ -570,6 +572,24 @@ void ProtocolGame::login(const std::string &name, uint32_t accountId, OperatingS

player->setOperatingSystem(operatingSystem);

const auto tile = g_game().map.getOrCreateTile(player->getLoginPosition());
// moving from a pz tile to a non-pz tile
if (maxOnline > 1 && player->getAccountType() < account::ACCOUNT_TYPE_GAMEMASTER && !tile->hasFlag(TILESTATE_PROTECTIONZONE)) {
auto maxOutsizePZ = g_configManager().getNumber(MAX_PLAYERS_OUTSIDE_PZ_PER_ACCOUNT, __FUNCTION__);
auto accountPlayers = g_game().getPlayersByAccount(player->getAccount());
int countOutsizePZ = 0;
for (const auto &accountPlayer : accountPlayers) {
if (accountPlayer != player && accountPlayer->getTile() && !accountPlayer->getTile()->hasFlag(TILESTATE_PROTECTIONZONE)) {
++countOutsizePZ;
}
}
if (countOutsizePZ >= maxOutsizePZ) {
g_game().removePlayerUniqueLogin(player);
disconnectClient(fmt::format("You can only have {} character{} from your account outside of a protection zone.", maxOutsizePZ == 1 ? "one" : std::to_string(maxOutsizePZ), maxOutsizePZ > 1 ? "s" : ""));
return;
}
}

if (!g_game().placeCreature(player, player->getLoginPosition()) && !g_game().placeCreature(player, player->getTemplePosition(), false, true)) {
g_game().removePlayerUniqueLogin(player);
disconnectClient("Temple position is wrong. Please, contact the administrator.");
Expand Down

0 comments on commit 1eaf75c

Please sign in to comment.