Compare commits

..

14 Commits

Author SHA1 Message Date
Chris Miles 4fc3c27715 [Release] 22.27.0 (#3614)
* [Release] 22.27.0

* Update bot.cpp
2023-10-07 15:11:21 -05:00
Chris Miles cea3ad6a42 [Crash] Fix crash in #movechar (#3612) 2023-10-07 14:00:27 -05:00
Chris Miles d8926cd5f3 [Crash] Fix dangling pointer crash observed in SendHPPacketsFrom (#3611)
* [Crash] Fix dangling pointer crash observed in SendHPPacketsFrom

* Update bot.cpp
2023-10-07 14:00:19 -05:00
Chris Miles efb03164c7 [Crash] Fix crash in CastSpell Quest API input cast (#3610) 2023-10-07 14:00:11 -05:00
Chris Miles 455eb2e6d9 [Crash] Fix CanUseAlternateAdvancementRank crash (#3609) 2023-10-07 14:00:04 -05:00
Chris Miles b5b0e53da2 [Crash] Fix #summon crash (#3608)
* [Crash] Summon crash fix

* [Crash] Fix summon crash
2023-10-07 13:59:56 -05:00
Chris Miles 68cb94b39c [Crash] Bot member zoned crash fix (#3607) 2023-10-07 13:59:47 -05:00
Chris Miles 3d95b6c184 [Crash] Fix rarer crash with File::Makedir (#3606) 2023-10-07 13:59:40 -05:00
Alex King 7db7631308 [Bug Fix] Fix #show group_info Popup (#3605)
# Notes
- Wasn't using `DialogueWindow::TableCell` so they weren't showing up.
- Fixed `red1` to `red_1` so it shows.
2023-10-04 14:40:05 -04:00
Akkadius f053cd3b56 [Hotfix] Ensure Linux builds report failures 2023-10-03 11:59:50 -05:00
Alex King cf27f2bc88 [Quest API] Add Caster ID Parameter to FindBuff in Perl/Lua (#3590)
* [Quest API] Add Caster ID Parameter to FindBuff in Perl/Lua

# Perl
- Add `$mob->FindBuff(spell_id, caster_id)`.

# Lua
- Add `mob:FindBuff(spell_id, caster_id)`.

# Notes
- Allows operators to check if the spell ID is cast by a specific entity ID.
- We don't use `Mob*` reference here since the mob may have died, left zone, etc.

* Formatting.
2023-09-29 19:38:36 -04:00
JJ 79918ebaba [Logs] Change pathing log messages from Error to Pathing. (#3604)
Change pathing log messages from `Error` to `Pathing`.
2023-09-29 11:54:52 -04:00
Paul Coene 2a648507f2 [Bug Fix] Fix swarm pet names to use '_' instead of ' ' (#3601) 2023-09-19 18:21:47 -04:00
Clayton Dunwell f395ee0508 [Bug Fix] Invis vs. Undead/Animal Breaks Charm for Pets (#3587)
* IVU & IVA break charm pets #2212

* fix typing

* fix tab spacing

* Formatting

* Formatting for CalcInvisibleLevel

---------

Co-authored-by: Akkadius <akkadius1@gmail.com>
2023-09-19 10:16:12 -04:00
20 changed files with 158 additions and 72 deletions
+28
View File
@@ -1,3 +1,31 @@
## [22.27.0] - 10/07/2023
### Crash
* Bot member zoned crash fix ([#3607](https://github.com/EQEmu/Server/pull/3607)) @Akkadius 2023-10-07
* Fix #summon crash ([#3608](https://github.com/EQEmu/Server/pull/3608)) @Akkadius 2023-10-07
* Fix CanUseAlternateAdvancementRank crash ([#3609](https://github.com/EQEmu/Server/pull/3609)) @Akkadius 2023-10-07
* Fix crash in #movechar ([#3612](https://github.com/EQEmu/Server/pull/3612)) @Akkadius 2023-10-07
* Fix crash in CastSpell Quest API input cast ([#3610](https://github.com/EQEmu/Server/pull/3610)) @Akkadius 2023-10-07
* Fix dangling pointer crash observed in SendHPPacketsFrom ([#3611](https://github.com/EQEmu/Server/pull/3611)) @Akkadius 2023-10-07
* Fix rarer crash with File::Makedir ([#3606](https://github.com/EQEmu/Server/pull/3606)) @Akkadius 2023-10-07
### Fixes
* Add Validation to #find, #set, and #show args ([#3598](https://github.com/EQEmu/Server/pull/3598)) @Kinglykrab 2023-09-18
* Ensure Linux builds report failures @Akkadius 2023-10-03
* Fix #show group_info Popup ([#3605](https://github.com/EQEmu/Server/pull/3605)) @Kinglykrab 2023-10-04
* Fix swarm pet names to use '_' instead of ' ' ([#3601](https://github.com/EQEmu/Server/pull/3601)) @noudess 2023-09-19
* Invis vs. Undead/Animal Breaks Charm for Pets ([#3587](https://github.com/EQEmu/Server/pull/3587)) @crdunwel 2023-09-19
### Logs
* Change pathing log messages from Error to Pathing. ([#3604](https://github.com/EQEmu/Server/pull/3604)) @joligario 2023-09-29
### Quest API
* Add Caster ID Parameter to FindBuff in Perl/Lua ([#3590](https://github.com/EQEmu/Server/pull/3590)) @Kinglykrab 2023-09-29
## [22.26.2] - 09/18/2023
### Fixes
+8 -2
View File
@@ -55,8 +55,14 @@ bool File::Exists(const std::string &name)
*/
void File::Makedir(const std::string &directory_name)
{
fs::create_directory(directory_name);
fs::permissions(directory_name, fs::perms::owner_all);
try {
fs::create_directory(directory_name);
fs::permissions(directory_name, fs::perms::owner_all);
}
catch (const fs::filesystem_error &ex) {
std::cout << "Failed to create directory: " << directory_name << std::endl;
std::cout << ex.what() << std::endl;
}
}
std::string File::FindEqemuConfigPath()
+1 -1
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "22.26.2-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "22.27.0-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "22.26.2",
"version": "22.27.0",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/bash
set -x
set -ex
sudo chown eqemu:eqemu /drone/src/ * -R
sudo chown eqemu:eqemu /home/eqemu/.ccache/ * -R
+4
View File
@@ -1576,6 +1576,10 @@ bool Mob::SetAA(uint32 rank_id, uint32 new_value, uint32 charges) {
bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) {
if (!rank) {
return false;
}
AA::Ability *ability = rank->base_ability;
if(!ability)
+8
View File
@@ -465,6 +465,14 @@ Bot::~Bot() {
}
entity_list.RemoveBot(GetID());
if (GetGroup()) {
GetGroup()->DelMember(this);
}
if (GetRaid()) {
GetRaid()->MemberZoned(CastToClient());
}
}
void Bot::SetBotID(uint32 botID) {
+8 -3
View File
@@ -46,7 +46,12 @@ void command_movechar(Client *c, const Seperator *sep)
}
auto zone_id = ZoneID(zone_short_name);
std::string zone_long_name = ZoneLongName(zone_id);
auto z = GetZone(zone_id);
if (!z) {
c->Message(Chat::Red, "Invalid zone.");
return;
}
bool is_special_zone = (
zone_short_name.find("cshome") != std::string::npos ||
@@ -59,7 +64,7 @@ void command_movechar(Client *c, const Seperator *sep)
Chat::White,
fmt::format(
"{} ({}) is a special zone and you cannot move someone there.",
zone_long_name,
z->long_name,
zone_short_name
).c_str()
);
@@ -91,7 +96,7 @@ void command_movechar(Client *c, const Seperator *sep)
fmt::format(
"Character Move {} | Zone: {} ({}) ID: {}",
moved_string,
zone_long_name,
z->long_name,
zone_short_name,
zone_id
).c_str()
+7 -7
View File
@@ -46,7 +46,7 @@ void ShowGroupInfo(Client *c, const Seperator *sep)
);
const std::string yes = DialogueWindow::ColorMessage("forest_green", "Y");
const std::string no = DialogueWindow::ColorMessage("red1", "N");
const std::string no = DialogueWindow::ColorMessage("red_1", "N");
for (int group_member = 0; group_member < MAX_GROUP_MEMBERS; group_member++) {
if (g->membername[group_member][0] == '\0') {
@@ -60,8 +60,8 @@ void ShowGroupInfo(Client *c, const Seperator *sep)
popup_table += DialogueWindow::TableRow(
fmt::format(
"{}{}{}{}{}{}",
group_member,
(
DialogueWindow::TableCell(std::to_string(group_member)),
DialogueWindow::TableCell(
strcmp(g->membername[group_member], c->GetCleanName()) ?
g->membername[group_member] :
fmt::format(
@@ -69,10 +69,10 @@ void ShowGroupInfo(Client *c, const Seperator *sep)
g->membername[group_member]
)
),
g->members[group_member] ? yes : no,
is_assist ? yes : no,
is_puller ? yes : no,
is_tank ? yes : no
DialogueWindow::TableCell(g->members[group_member] ? yes : no),
DialogueWindow::TableCell(is_assist ? yes : no),
DialogueWindow::TableCell(is_puller ? yes : no),
DialogueWindow::TableCell(is_tank ? yes : no)
)
);
}
+2 -2
View File
@@ -24,7 +24,7 @@ void ShowZoneData(Client *c, const Seperator *sep)
fmt::format(
"{} {} {}",
DialogueWindow::ColorMessage(
"red1",
"red_1",
std::to_string(zone->newzone_data.fog_red[fog_index])
),
DialogueWindow::ColorMessage(
@@ -206,7 +206,7 @@ void ShowZoneData(Client *c, const Seperator *sep)
DialogueWindow::TableCell(
zone->newzone_data.suspend_buffs ?
DialogueWindow::ColorMessage("forest_green", "Y") :
DialogueWindow::ColorMessage("red1", "N")
DialogueWindow::ColorMessage("red_1", "N")
)
);
+7 -2
View File
@@ -58,12 +58,17 @@ void command_summon(Client *c, const Seperator *sep)
} else if (c->GetTarget()) {
target = c->GetTarget();
}
if (c == target) {
c->Message(Chat::White, "You cannot summon yourself.");
return;
}
if (!target) {
c->Message(Chat::White, "You must have a target to summon.");
return;
}
c->Message(
Chat::White,
fmt::format(
+7 -2
View File
@@ -555,8 +555,13 @@ void Group::MemberZoned(Mob* removemob) {
//should NOT clear the name, it is used for world communication.
for (auto & m : members) {
if (m && (m == removemob || (m->IsBot() && m->CastToBot()->GetBotOwner() == removemob))) {
m = nullptr;
if (m) {
if (m->IsBot() && m->CastToBot()->GetBotOwner() && m->CastToBot()->GetBotOwner() == removemob) {
m = nullptr;
}
else if (m == removemob) {
m = nullptr;
}
}
}
+15 -3
View File
@@ -315,11 +315,16 @@ void Lua_Mob::SetInvisible(int state) {
self->SetInvisible(state);
}
bool Lua_Mob::FindBuff(int spell_id) {
bool Lua_Mob::FindBuff(uint16 spell_id) {
Lua_Safe_Call_Bool();
return self->FindBuff(spell_id);
}
bool Lua_Mob::FindBuff(uint16 spell_id, uint16 caster_id) {
Lua_Safe_Call_Bool();
return self->FindBuff(spell_id, caster_id);
}
uint16 Lua_Mob::FindBuffBySlot(int slot) {
Lua_Safe_Call_Int();
return self->FindBuffBySlot(slot);
@@ -873,7 +878,13 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id) {
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot) {
Lua_Safe_Call_Bool();
return self->CastSpell(spell_id, target_id, static_cast<EQ::spells::CastingSlot>(slot));
int cast_slot = 0;
if (slot >= 0 || slot <= 23 || slot == 255) {
cast_slot = slot;
}
return self->CastSpell(spell_id, target_id, static_cast<EQ::spells::CastingSlot>(cast_slot));
}
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time) {
@@ -3324,7 +3335,8 @@ luabind::scope lua_register_mob() {
.def("Emote", &Lua_Mob::Emote)
.def("EntityVariableExists", &Lua_Mob::EntityVariableExists)
.def("FaceTarget", (void(Lua_Mob::*)(Lua_Mob))&Lua_Mob::FaceTarget)
.def("FindBuff", &Lua_Mob::FindBuff)
.def("FindBuff", (bool(Lua_Mob::*)(uint16))&Lua_Mob::FindBuff)
.def("FindBuff", (bool(Lua_Mob::*)(uint16,uint16))&Lua_Mob::FindBuff)
.def("FindBuffBySlot", (uint16(Lua_Mob::*)(int))&Lua_Mob::FindBuffBySlot)
.def("FindGroundZ", (double(Lua_Mob::*)(double,double))&Lua_Mob::FindGroundZ)
.def("FindGroundZ", (double(Lua_Mob::*)(double,double,double))&Lua_Mob::FindGroundZ)
+2 -1
View File
@@ -90,7 +90,8 @@ public:
uint8 GetInvisibleUndeadLevel();
void SetSeeInvisibleLevel(uint8 invisible_level);
void SetSeeInvisibleUndeadLevel(uint8 invisible_level);
bool FindBuff(int spell_id);
bool FindBuff(uint16 spell_id);
bool FindBuff(uint16 spell_id, uint16 caster_id);
uint16 FindBuffBySlot(int slot);
uint32 BuffCount();
uint32 BuffCount(bool is_beneficial);
+36 -36
View File
@@ -593,42 +593,49 @@ void Mob::CalcSeeInvisibleLevel()
see_invis = std::max({ spellbonuses.SeeInvis, itembonuses.SeeInvis, aabonuses.SeeInvis, innate_see_invis });
}
void Mob::CalcInvisibleLevel()
{
bool is_invisible = invisible;
bool Mob::HasAnInvisibilityEffect() {
return invisible || hidden || improved_hidden || invisible_animals || invisible_undead;
}
invisible = std::max({ spellbonuses.invisibility, nobuff_invisible });
invisible_undead = spellbonuses.invisibility_verse_undead;
invisible_animals = spellbonuses.invisibility_verse_animal;
if (!is_invisible && invisible) {
SetInvisible(Invisibility::Invisible, true);
return;
}
if (is_invisible && !invisible) {
SetInvisible(invisible, true);
return;
void Mob::BreakCharmPetIfConditionsMet() {
auto pet = GetPet();
if (pet && pet->GetPetType() == petCharmed && HasAnInvisibilityEffect()) {
if (RuleB(Pets, LivelikeBreakCharmOnInvis) || IsInvisible(pet)) {
pet->BuffFadeByEffect(SE_Charm);
}
LogRules(
"Pets:LivelikeBreakCharmOnInvis for [{}] invisible [{}] hidden [{}] improved_hidden (shroud of stealth) [{}] invisible_animals [{}] invisible_undead [{}]",
GetCleanName(),
invisible,
hidden,
improved_hidden,
invisible_animals,
invisible_undead
);
}
}
void Mob::SetInvisible(uint8 state, bool set_on_bonus_calc)
void Mob::CalcInvisibleLevel()
{
/*
If you set an NPC to invisible you will only be able to see it on
your client if your see invisible level is greater than equal to the invisible level.
Note, the clients spell file must match the servers see invisible level on the spell.
*/
bool was_invisible = invisible;
invisible = std::max({spellbonuses.invisibility, nobuff_invisible});
invisible_undead = spellbonuses.invisibility_verse_undead;
invisible_animals = spellbonuses.invisibility_verse_animal;
if (was_invisible != invisible) {
SetInvisible(invisible, true);
return;
}
BreakCharmPetIfConditionsMet();
}
void Mob::SetInvisible(uint8 state, bool set_on_bonus_calc) {
if (state == Invisibility::Visible) {
SendAppearancePacket(AT_Invis, Invisibility::Visible);
ZeroInvisibleVars(InvisType::T_INVISIBLE);
}
else {
/*
if your setting invisible from a script, or escape/fading memories effect then
we use the internal invis variable which allows invisible without a buff on mob.
*/
} else {
if (!set_on_bonus_calc) {
nobuff_invisible = state;
CalcInvisibleLevel();
@@ -636,14 +643,7 @@ void Mob::SetInvisible(uint8 state, bool set_on_bonus_calc)
SendAppearancePacket(AT_Invis, invisible);
}
// Invis and hide breaks charms
auto pet = GetPet();
if (pet && pet->GetPetType() == petCharmed && (invisible || hidden || improved_hidden || invisible_animals || invisible_undead)) {
if (RuleB(Pets, LivelikeBreakCharmOnInvis) || IsInvisible(pet)) {
pet->BuffFadeByEffect(SE_Charm);
}
LogRules("Pets:LivelikeBreakCharmOnInvis for [{}] | Invis [{}] - Hidden [{}] - Shroud of Stealth [{}] - IVA [{}] - IVU [{}]", GetCleanName(), invisible, hidden, improved_hidden, invisible_animals, invisible_undead);
}
BreakCharmPetIfConditionsMet();
}
void Mob::ZeroInvisibleVars(uint8 invisible_type)
@@ -5114,7 +5114,7 @@ std::string Mob::GetTargetDescription(Mob* target, uint8 description_type, uint1
auto d = fmt::format(
"{}",
(
this == target ?
target && this == target ?
self_return :
fmt::format(
"{} ({})",
+3 -1
View File
@@ -269,6 +269,8 @@ public:
return;
}
bool HasAnInvisibilityEffect();
void BreakCharmPetIfConditionsMet();
//Invisible
bool IsInvisible(Mob* other = 0) const;
void SetInvisible(uint8 state, bool set_on_bonus_calc = false);
@@ -464,7 +466,7 @@ public:
void DamageShield(Mob* other, bool spell_ds = false);
int32 RuneAbsorb(int64 damage, uint16 type);
std::vector<uint16> GetBuffSpellIDs();
bool FindBuff(uint16 spell_id);
bool FindBuff(uint16 spell_id, uint16 caster_id = 0);
uint16 FindBuffBySlot(int slot);
uint32 BuffCount(bool is_beneficial = true, bool is_detrimental = true);
bool FindType(uint16 type, bool bOffensive = false, uint16 threshold = 100);
+7 -1
View File
@@ -362,6 +362,11 @@ bool Perl_Mob_FindBuff(Mob* self, uint16 spell_id) // @categories Spells and Dis
return self->FindBuff(spell_id);
}
bool Perl_Mob_FindBuff(Mob* self, uint16 spell_id, uint16 caster_id) // @categories Spells and Disciplines, Script Utility
{
return self->FindBuff(spell_id, caster_id);
}
int Perl_Mob_FindBuffBySlot(Mob* self, int slot) // @categories Spells and Disciplines, Script Utility
{
return self->FindBuffBySlot(slot);
@@ -3570,7 +3575,8 @@ void perl_register_mob()
package.add("EntityVariableExists", &Perl_Mob_EntityVariableExists);
package.add("FaceTarget", (void(*)(Mob*))&Perl_Mob_FaceTarget);
package.add("FaceTarget", (void(*)(Mob*, Mob*))&Perl_Mob_FaceTarget);
package.add("FindBuff", &Perl_Mob_FindBuff);
package.add("FindBuff", (bool(*)(Mob*, uint16))&Perl_Mob_FindBuff);
package.add("FindBuff", (bool(*)(Mob*, uint16, uint16))&Perl_Mob_FindBuff);
package.add("FindBuffBySlot", &Perl_Mob_FindBuffBySlot);
package.add("FindGroundZ", (float(*)(Mob*, float, float))&Perl_Mob_FindGroundZ);
package.add("FindGroundZ", (float(*)(Mob*, float, float, float))&Perl_Mob_FindGroundZ);
+2 -2
View File
@@ -2266,7 +2266,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
if((spell_id != 6882) && (spell_id != 6884)) // Chaotic Jester/Steadfast Servant
{
char pet_name[64];
snprintf(pet_name, sizeof(pet_name), "%s`s pet", caster->GetCleanName());
snprintf(pet_name, sizeof(pet_name), "%s`s_pet", caster->GetCleanName());
caster->TemporaryPets(spell_id, this, pet_name);
}
else
@@ -2443,7 +2443,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
{
if(caster && caster->IsClient()) {
char pet_name[64];
snprintf(pet_name, sizeof(pet_name), "%s`s doppelganger", caster->GetCleanName());
snprintf(pet_name, sizeof(pet_name), "%s`s_doppelganger", caster->GetCleanName());
int pet_count = spells[spell_id].base_value[i];
int pet_duration = spells[spell_id].max_value[i];
caster->CastToClient()->Doppelganger(spell_id, this, pet_name, pet_count, pet_duration);
+8 -4
View File
@@ -4411,14 +4411,18 @@ std::vector<uint16> Mob::GetBuffSpellIDs()
return l;
}
bool Mob::FindBuff(uint16 spell_id)
bool Mob::FindBuff(uint16 spell_id, uint16 caster_id)
{
uint32 buff_count = GetMaxTotalSlots();
const int buff_count = GetMaxTotalSlots();
for (int buff_slot = 0; buff_slot < buff_count; buff_slot++) {
auto current_spell_id = buffs[buff_slot].spellid;
const uint16 current_spell_id = buffs[buff_slot].spellid;
if (
IsValidSpell(current_spell_id) &&
current_spell_id == spell_id
current_spell_id == spell_id &&
(
!caster_id ||
buffs[buff_slot].casterid == caster_id
)
) {
return true;
}
+3 -3
View File
@@ -157,7 +157,7 @@ void NPC::ResumeWandering()
}
else
{
LogError("NPC not paused - can't resume wandering: [{}]", (unsigned long)GetNPCTypeID());
LogPathing("NPC not paused - can't resume wandering: [{}]", (unsigned long)GetNPCTypeID());
return;
}
@@ -173,7 +173,7 @@ void NPC::ResumeWandering()
}
else
{
LogError("NPC not on grid - can't resume wandering: [{}]", (unsigned long)GetNPCTypeID());
LogPathing("NPC not on grid - can't resume wandering: [{}]", (unsigned long)GetNPCTypeID());
}
return;
}
@@ -195,7 +195,7 @@ void NPC::PauseWandering(int pausetime)
}
}
else {
LogError("NPC not on grid - can't pause wandering: [{}]", (unsigned long)GetNPCTypeID());
LogPathing("NPC not on grid - can't pause wandering: [{}]", (unsigned long)GetNPCTypeID());
}
return;
}