Skip to content

Commit

Permalink
Merge branch 'main' into fix-player-name-length
Browse files Browse the repository at this point in the history
  • Loading branch information
murilo09 authored Dec 31, 2024
2 parents dd05ee2 + f821248 commit 9db5710
Show file tree
Hide file tree
Showing 21 changed files with 138 additions and 105 deletions.
7 changes: 4 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ endif()
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)

# Configure build options for compatibility with commodity CPUs
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -mtune=generic -mno-avx -mno-sse4")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -mtune=generic -mno-avx -mno-sse4")

if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -mtune=generic -mno-avx -mno-sse4")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -mtune=generic -mno-avx -mno-sse4")
endif()

# *****************************************************************************
# Include cmake tools
Expand Down
5 changes: 4 additions & 1 deletion data-otservbr-global/scripts/lib/register_actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,10 @@ function onUsePick(player, item, fromPosition, target, toPosition, isHotkey)
-- The Pits of Inferno Quest
if toPosition == Position(32808, 32334, 11) then
for i = 1, #lava do
Game.createItem(5815, 1, lava[i])
local lavaTile = Tile(lava[i]):getItemById(21477)
if lavaTile then
lavaTile:transform(5815)
end
end
target:transform(3141)
toPosition:sendMagicEffect(CONST_ME_SMOKE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ function rookVillage.onStepIn(creature, item, position, fromPosition)
return true
end

player:teleportTo(Position(player:getPosition().x, player:getPosition().y - 1, player:getPosition().z))
player:teleportTo(Position(player:getPosition().x, player:getPosition().y - 3, player:getPosition().z + 1))
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You don't have any business there anymore.")

return true
Expand Down
27 changes: 8 additions & 19 deletions data/events/scripts/party.lua
Original file line number Diff line number Diff line change
Expand Up @@ -66,25 +66,14 @@ function Party:onDisband()
end

function Party:onShareExperience(exp)
local sharedExperienceMultiplier = 1.20 --20%
local vocationsIds = {}
local uniqueVocationsCount = self:getUniqueVocationsCount()
local partySize = self:getMemberCount() + 1

local vocationId = self:getLeader():getVocation():getBase():getId()
if vocationId ~= VOCATION_NONE then
table.insert(vocationsIds, vocationId)
end

for _, member in ipairs(self:getMembers()) do
vocationId = member:getVocation():getBase():getId()
if not table.contains(vocationsIds, vocationId) and vocationId ~= VOCATION_NONE then
table.insert(vocationsIds, vocationId)
end
end

local size = #vocationsIds
if size > 1 then
sharedExperienceMultiplier = 1.0 + ((size * (5 * (size - 1) + 10)) / 100)
end
-- Formula to calculate the % based on the vocations amount
local sharedExperienceMultiplier = ((0.1 * (uniqueVocationsCount ^ 2)) - (0.2 * uniqueVocationsCount) + 1.3)
-- Since the formula its non linear, we need to subtract 0.1 if all vocations are present,
-- because on all vocations the multiplier is 2.1 and it should be 2.0
sharedExperienceMultiplier = partySize < 4 and sharedExperienceMultiplier or sharedExperienceMultiplier - 0.1

return math.ceil((exp * sharedExperienceMultiplier) / (#self:getMembers() + 1))
return math.ceil((exp * sharedExperienceMultiplier) / partySize)
end
12 changes: 6 additions & 6 deletions data/libs/systems/hazard.lua
Original file line number Diff line number Diff line change
Expand Up @@ -193,16 +193,16 @@ function HazardMonster.onSpawn(monster, position)
if not zones then
return true
end

logger.debug("Monster {} spawned in hazard zone, position {}", monster:getName(), position:toString())
for _, zone in ipairs(zones) do
local hazard = Hazard.getByName(zone:getName())
if hazard then
monster:hazard(true)
if hazard then
monster:hazardCrit(hazard.crit)
monster:hazardDodge(hazard.dodge)
monster:hazardDamageBoost(hazard.damageBoost)
monster:hazardDefenseBoost(hazard.defenseBoost)
end
monster:hazardCrit(hazard.crit)
monster:hazardDodge(hazard.dodge)
monster:hazardDamageBoost(hazard.damageBoost)
monster:hazardDefenseBoost(hazard.defenseBoost)
end
end
return true
Expand Down
22 changes: 17 additions & 5 deletions data/libs/systems/zones.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,24 @@ function Zone:randomPosition()
logger.error("Zone:randomPosition() - Zone {} has no positions", self:getName())
return nil
end
local destination = positions[math.random(1, #positions)]
local tile = destination:getTile()
while not tile or not tile:isWalkable(false, false, false, false, true) do
destination = positions[math.random(1, #positions)]
tile = destination:getTile()

local validPositions = {}
for _, position in ipairs(positions) do
local tile = position:getTile()
if tile and tile:isWalkable(false, false, false, false, true) then
table.insert(validPositions, position)
else
logger.debug("Zone:randomPosition() - Position {} is invalid (Tile: {}, Walkable: {})", position, tile or "nil", tile and tile:isWalkable(false, false, false, false, true) or "false")
end
end

if #validPositions == 0 then
logger.error("Zone:randomPosition() - No valid positions in Zone {}", self:getName())
return nil
end

local destination = validPositions[math.random(1, #validPositions)]
logger.debug("Zone:randomPosition() - Selected valid position: {}", destination)
return destination
end

Expand Down
6 changes: 5 additions & 1 deletion data/scripts/lib/register_monster_type.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ end
registerMonsterType.name = function(mtype, mask)
if mask.name then
mtype:name(mask.name)
-- Try register hazard monsters
mtype.onSpawn = function(monster, spawnPosition)
HazardMonster.onSpawn(monster, spawnPosition)
end
end
end
registerMonsterType.description = function(mtype, mask)
Expand Down Expand Up @@ -194,7 +198,7 @@ registerMonsterType.flags = function(mtype, mask)
end
if mask.flags.rewardBoss then
mtype:isRewardBoss(mask.flags.rewardBoss)
mtype.onSpawn = function(monster)
mtype.onSpawn = function(monster, spawnPosition)
monster:setRewardBoss()
end
end
Expand Down
4 changes: 4 additions & 0 deletions src/creatures/creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,10 @@ std::shared_ptr<Item> Creature::getCorpse(const std::shared_ptr<Creature> &, con
}

void Creature::changeHealth(int32_t healthChange, bool sendHealthChange /* = true*/) {
if (isLifeless()) {
return;
}

int32_t oldHealth = health;

if (healthChange > 0) {
Expand Down
6 changes: 5 additions & 1 deletion src/creatures/creature.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,11 @@ class Creature : virtual public Thing, public SharedObject {
}

bool isAlive() const {
return !isDead();
return !isLifeless();
}

bool isLifeless() const {
return health <= 0;
}

virtual int32_t getMaxHealth() const {
Expand Down
66 changes: 19 additions & 47 deletions src/creatures/monsters/monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,9 +501,9 @@ void Monster::onAttackedByPlayer(const std::shared_ptr<Player> &attackerPlayer)
}
}

void Monster::onSpawn() {
void Monster::onSpawn(const Position &position) {
if (mType->info.spawnEvent != -1) {
// onSpawn(self)
// onSpawn(self, spawnPosition)
LuaScriptInterface* scriptInterface = mType->info.scriptInterface;
if (!scriptInterface->reserveScriptEnv()) {
g_logger().error("Monster {} creature {}] Call stack overflow. Too many lua "
Expand All @@ -520,8 +520,9 @@ void Monster::onSpawn() {

LuaScriptInterface::pushUserdata<Monster>(L, getMonster());
LuaScriptInterface::setMetatable(L, -1, "Monster");
LuaScriptInterface::pushPosition(L, position);

scriptInterface->callVoidFunction(1);
scriptInterface->callVoidFunction(2);
}
}

Expand Down Expand Up @@ -1109,7 +1110,7 @@ void Monster::onThink_async() {

void Monster::doAttacking(uint32_t interval) {
const auto &attackedCreature = getAttackedCreature();
if (!attackedCreature || (isSummon() && attackedCreature.get() == this)) {
if (!attackedCreature || attackedCreature->isLifeless() || (isSummon() && attackedCreature.get() == this)) {
return;
}

Expand Down Expand Up @@ -1581,73 +1582,44 @@ bool Monster::getDanceStep(const Position &creaturePos, Direction &moveDirection
uint32_t centerToDist = std::max<uint32_t>(distance_x, distance_y);

// monsters not at targetDistance shouldn't dancestep
if (centerToDist < (uint32_t)targetDistance) {
if (centerToDist < static_cast<uint32_t>(targetDistance)) {
return false;
}

std::vector<Direction> dirList;
if (!keepDistance || offset_y >= 0) {
uint32_t tmpDist = std::max<uint32_t>(distance_x, std::abs((creaturePos.getY() - 1) - centerPos.getY()));
if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_NORTH)) {
auto tryAddDirection = [&](Direction direction, int_fast32_t newX, int_fast32_t newY) {
uint32_t tmpDist = std::max<uint32_t>(std::abs(newX - centerPos.getX()), std::abs(newY - centerPos.getY()));
if (tmpDist == centerToDist && canWalkTo(creaturePos, direction)) {
bool result = true;

if (keepAttack) {
result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y - 1, creaturePos.z), attackedCreature));
result = (!canDoAttackNow || canUseAttack(Position(newX, newY, creaturePos.z), attackedCreature));
}

if (result) {
dirList.push_back(DIRECTION_NORTH);
dirList.emplace_back(direction);
}
}
};

if (!keepDistance || offset_y >= 0) {
tryAddDirection(DIRECTION_NORTH, creaturePos.getX(), creaturePos.getY() - 1);
}

if (!keepDistance || offset_y <= 0) {
uint32_t tmpDist = std::max<uint32_t>(distance_x, std::abs((creaturePos.getY() + 1) - centerPos.getY()));
if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_SOUTH)) {
bool result = true;

if (keepAttack) {
result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y + 1, creaturePos.z), attackedCreature));
}

if (result) {
dirList.push_back(DIRECTION_SOUTH);
}
}
tryAddDirection(DIRECTION_SOUTH, creaturePos.getX(), creaturePos.getY() + 1);
}

if (!keepDistance || offset_x <= 0) {
uint32_t tmpDist = std::max<uint32_t>(std::abs((creaturePos.getX() + 1) - centerPos.getX()), distance_y);
if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_EAST)) {
bool result = true;

if (keepAttack) {
result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x + 1, creaturePos.y, creaturePos.z), attackedCreature));
}

if (result) {
dirList.push_back(DIRECTION_EAST);
}
}
tryAddDirection(DIRECTION_EAST, creaturePos.getX() + 1, creaturePos.getY());
}

if (!keepDistance || offset_x >= 0) {
uint32_t tmpDist = std::max<uint32_t>(std::abs((creaturePos.getX() - 1) - centerPos.getX()), distance_y);
if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_WEST)) {
bool result = true;

if (keepAttack) {
result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x - 1, creaturePos.y, creaturePos.z), attackedCreature));
}

if (result) {
dirList.push_back(DIRECTION_WEST);
}
}
tryAddDirection(DIRECTION_WEST, creaturePos.getX() - 1, creaturePos.getY());
}

if (!dirList.empty()) {
std::shuffle(dirList.begin(), dirList.end(), getRandomGenerator());
std::ranges::shuffle(dirList, getRandomGenerator());
moveDirection = dirList[uniform_random(0, dirList.size() - 1)];
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/creatures/monsters/monster.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class Monster final : public Creature {
void onCreatureMove(const std::shared_ptr<Creature> &creature, const std::shared_ptr<Tile> &newTile, const Position &newPos, const std::shared_ptr<Tile> &oldTile, const Position &oldPos, bool teleport) override;
void onCreatureSay(const std::shared_ptr<Creature> &creature, SpeakClasses type, const std::string &text) override;
void onAttackedByPlayer(const std::shared_ptr<Player> &attackerPlayer);
void onSpawn();
void onSpawn(const Position &position);

void drainHealth(const std::shared_ptr<Creature> &attacker, int32_t damage) override;
void changeHealth(int32_t healthChange, bool sendHealthChange = true) override;
Expand Down
2 changes: 1 addition & 1 deletion src/creatures/monsters/spawns/spawn_monster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ bool SpawnMonster::spawnMonster(uint32_t spawnMonsterId, spawnBlock_t &sb, const

spawnedMonsterMap[spawnMonsterId] = monster;
sb.lastSpawn = OTSYS_TIME();
monster->onSpawn();
monster->onSpawn(sb.pos);
return true;
}

Expand Down
26 changes: 24 additions & 2 deletions src/creatures/players/grouping/party.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "config/configmanager.hpp"
#include "creatures/creature.hpp"
#include "creatures/players/player.hpp"
#include "creatures/players/vocations/vocation.hpp"
#include "game/game.hpp"
#include "game/movement/position.hpp"
#include "lua/callbacks/event_callback.hpp"
Expand Down Expand Up @@ -61,6 +62,25 @@ size_t Party::getInvitationCount() const {
return inviteList.size();
}

uint8_t Party::getUniqueVocationsCount() const {
std::unordered_set<uint8_t> uniqueVocations;

for (const auto &player : getPlayers()) {
if (uniqueVocations.size() >= 4) {
break;
}

const auto &vocation = player->getVocation();
if (!vocation) {
continue;
}

uniqueVocations.insert(vocation->getBaseId());
}

return uniqueVocations.size();
}

void Party::disband() {
if (!g_events().eventPartyOnDisband(getParty())) {
return;
Expand Down Expand Up @@ -504,9 +524,11 @@ void Party::shareExperience(uint64_t experience, const std::shared_ptr<Creature>
g_callbacks().executeCallback(EventCallback_t::partyOnShareExperience, &EventCallback::partyOnShareExperience, getParty(), std::ref(shareExperience));

for (const auto &member : getMembers()) {
member->onGainSharedExperience(shareExperience, target);
const auto memberStaminaBoost = static_cast<float>(member->getStaminaXpBoost()) / 100;
member->onGainSharedExperience(shareExperience * memberStaminaBoost, target);
}
leader->onGainSharedExperience(shareExperience, target);
const auto leaderStaminaBoost = static_cast<float>(leader->getStaminaXpBoost()) / 100;
leader->onGainSharedExperience(shareExperience * leaderStaminaBoost, target);
}

bool Party::canUseSharedExperience(const std::shared_ptr<Player> &player) {
Expand Down
1 change: 1 addition & 0 deletions src/creatures/players/grouping/party.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Party final : public SharedObject {
std::vector<std::shared_ptr<Player>> getInvitees();
size_t getMemberCount() const;
size_t getInvitationCount() const;
uint8_t getUniqueVocationsCount() const;

void disband();
bool invitePlayer(const std::shared_ptr<Player> &player);
Expand Down
2 changes: 1 addition & 1 deletion src/lua/functions/core/game/game_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ int GameFunctions::luaGameCreateMonster(lua_State* L) {
const bool extended = Lua::getBoolean(L, 3, false);
const bool force = Lua::getBoolean(L, 4, false);
if (g_game().placeCreature(monster, position, extended, force)) {
monster->onSpawn();
monster->onSpawn(position);
const auto &mtype = monster->getMonsterType();
if (mtype && mtype->info.raceid > 0 && mtype->info.bosstiaryRace == BosstiaryRarity_t::RARITY_ARCHFOE) {
for (const auto &spectator : Spectators().find<Player>(monster->getPosition(), true)) {
Expand Down
12 changes: 12 additions & 0 deletions src/lua/functions/creatures/player/party_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ void PartyFunctions::init(lua_State* L) {
Lua::registerMethod(L, "Party", "getMemberCount", PartyFunctions::luaPartyGetMemberCount);
Lua::registerMethod(L, "Party", "getInvitees", PartyFunctions::luaPartyGetInvitees);
Lua::registerMethod(L, "Party", "getInviteeCount", PartyFunctions::luaPartyGetInviteeCount);
Lua::registerMethod(L, "Party", "getUniqueVocationsCount", PartyFunctions::luaPartyGetUniqueVocationsCount);
Lua::registerMethod(L, "Party", "addInvite", PartyFunctions::luaPartyAddInvite);
Lua::registerMethod(L, "Party", "removeInvite", PartyFunctions::luaPartyRemoveInvite);
Lua::registerMethod(L, "Party", "addMember", PartyFunctions::luaPartyAddMember);
Expand Down Expand Up @@ -162,6 +163,17 @@ int PartyFunctions::luaPartyGetInviteeCount(lua_State* L) {
return 1;
}

int PartyFunctions::luaPartyGetUniqueVocationsCount(lua_State* L) {
// party:getUniqueVocationsCount()
const auto &party = Lua::getUserdataShared<Party>(L, 1);
if (party) {
lua_pushnumber(L, party->getUniqueVocationsCount());
} else {
lua_pushnil(L);
}
return 1;
}

int PartyFunctions::luaPartyAddInvite(lua_State* L) {
// party:addInvite(player)
const auto &player = Lua::getPlayer(L, 2);
Expand Down
Loading

0 comments on commit 9db5710

Please sign in to comment.