mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-26 15:37:16 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4fc3c27715 | |||
| cea3ad6a42 | |||
| d8926cd5f3 | |||
| efb03164c7 | |||
| 455eb2e6d9 | |||
| b5b0e53da2 | |||
| 68cb94b39c | |||
| 3d95b6c184 | |||
| 7db7631308 | |||
| f053cd3b56 | |||
| cf27f2bc88 | |||
| 79918ebaba | |||
| 2a648507f2 | |||
| f395ee0508 |
@@ -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
|
## [22.26.2] - 09/18/2023
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|||||||
@@ -55,8 +55,14 @@ bool File::Exists(const std::string &name)
|
|||||||
*/
|
*/
|
||||||
void File::Makedir(const std::string &directory_name)
|
void File::Makedir(const std::string &directory_name)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
fs::create_directory(directory_name);
|
fs::create_directory(directory_name);
|
||||||
fs::permissions(directory_name, fs::perms::owner_all);
|
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()
|
std::string File::FindEqemuConfigPath()
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
// Build variables
|
// Build variables
|
||||||
// these get injected during the build pipeline
|
// 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 LOGIN_VERSION "0.8.0"
|
||||||
#define COMPILE_DATE __DATE__
|
#define COMPILE_DATE __DATE__
|
||||||
#define COMPILE_TIME __TIME__
|
#define COMPILE_TIME __TIME__
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "eqemu-server",
|
"name": "eqemu-server",
|
||||||
"version": "22.26.2",
|
"version": "22.27.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/EQEmu/Server.git"
|
"url": "https://github.com/EQEmu/Server.git"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -x
|
set -ex
|
||||||
|
|
||||||
sudo chown eqemu:eqemu /drone/src/ * -R
|
sudo chown eqemu:eqemu /drone/src/ * -R
|
||||||
sudo chown eqemu:eqemu /home/eqemu/.ccache/ * -R
|
sudo chown eqemu:eqemu /home/eqemu/.ccache/ * -R
|
||||||
|
|||||||
@@ -1576,6 +1576,10 @@ bool Mob::SetAA(uint32 rank_id, uint32 new_value, uint32 charges) {
|
|||||||
|
|
||||||
|
|
||||||
bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) {
|
bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) {
|
||||||
|
if (!rank) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
AA::Ability *ability = rank->base_ability;
|
AA::Ability *ability = rank->base_ability;
|
||||||
|
|
||||||
if(!ability)
|
if(!ability)
|
||||||
|
|||||||
@@ -465,6 +465,14 @@ Bot::~Bot() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
entity_list.RemoveBot(GetID());
|
entity_list.RemoveBot(GetID());
|
||||||
|
|
||||||
|
if (GetGroup()) {
|
||||||
|
GetGroup()->DelMember(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetRaid()) {
|
||||||
|
GetRaid()->MemberZoned(CastToClient());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::SetBotID(uint32 botID) {
|
void Bot::SetBotID(uint32 botID) {
|
||||||
|
|||||||
@@ -46,7 +46,12 @@ void command_movechar(Client *c, const Seperator *sep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto zone_id = ZoneID(zone_short_name);
|
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 = (
|
bool is_special_zone = (
|
||||||
zone_short_name.find("cshome") != std::string::npos ||
|
zone_short_name.find("cshome") != std::string::npos ||
|
||||||
@@ -59,7 +64,7 @@ void command_movechar(Client *c, const Seperator *sep)
|
|||||||
Chat::White,
|
Chat::White,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} ({}) is a special zone and you cannot move someone there.",
|
"{} ({}) is a special zone and you cannot move someone there.",
|
||||||
zone_long_name,
|
z->long_name,
|
||||||
zone_short_name
|
zone_short_name
|
||||||
).c_str()
|
).c_str()
|
||||||
);
|
);
|
||||||
@@ -91,7 +96,7 @@ void command_movechar(Client *c, const Seperator *sep)
|
|||||||
fmt::format(
|
fmt::format(
|
||||||
"Character Move {} | Zone: {} ({}) ID: {}",
|
"Character Move {} | Zone: {} ({}) ID: {}",
|
||||||
moved_string,
|
moved_string,
|
||||||
zone_long_name,
|
z->long_name,
|
||||||
zone_short_name,
|
zone_short_name,
|
||||||
zone_id
|
zone_id
|
||||||
).c_str()
|
).c_str()
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ void ShowGroupInfo(Client *c, const Seperator *sep)
|
|||||||
);
|
);
|
||||||
|
|
||||||
const std::string yes = DialogueWindow::ColorMessage("forest_green", "Y");
|
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++) {
|
for (int group_member = 0; group_member < MAX_GROUP_MEMBERS; group_member++) {
|
||||||
if (g->membername[group_member][0] == '\0') {
|
if (g->membername[group_member][0] == '\0') {
|
||||||
@@ -60,8 +60,8 @@ void ShowGroupInfo(Client *c, const Seperator *sep)
|
|||||||
popup_table += DialogueWindow::TableRow(
|
popup_table += DialogueWindow::TableRow(
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{}{}{}{}{}{}",
|
"{}{}{}{}{}{}",
|
||||||
group_member,
|
DialogueWindow::TableCell(std::to_string(group_member)),
|
||||||
(
|
DialogueWindow::TableCell(
|
||||||
strcmp(g->membername[group_member], c->GetCleanName()) ?
|
strcmp(g->membername[group_member], c->GetCleanName()) ?
|
||||||
g->membername[group_member] :
|
g->membername[group_member] :
|
||||||
fmt::format(
|
fmt::format(
|
||||||
@@ -69,10 +69,10 @@ void ShowGroupInfo(Client *c, const Seperator *sep)
|
|||||||
g->membername[group_member]
|
g->membername[group_member]
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
g->members[group_member] ? yes : no,
|
DialogueWindow::TableCell(g->members[group_member] ? yes : no),
|
||||||
is_assist ? yes : no,
|
DialogueWindow::TableCell(is_assist ? yes : no),
|
||||||
is_puller ? yes : no,
|
DialogueWindow::TableCell(is_puller ? yes : no),
|
||||||
is_tank ? yes : no
|
DialogueWindow::TableCell(is_tank ? yes : no)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ void ShowZoneData(Client *c, const Seperator *sep)
|
|||||||
fmt::format(
|
fmt::format(
|
||||||
"{} {} {}",
|
"{} {} {}",
|
||||||
DialogueWindow::ColorMessage(
|
DialogueWindow::ColorMessage(
|
||||||
"red1",
|
"red_1",
|
||||||
std::to_string(zone->newzone_data.fog_red[fog_index])
|
std::to_string(zone->newzone_data.fog_red[fog_index])
|
||||||
),
|
),
|
||||||
DialogueWindow::ColorMessage(
|
DialogueWindow::ColorMessage(
|
||||||
@@ -206,7 +206,7 @@ void ShowZoneData(Client *c, const Seperator *sep)
|
|||||||
DialogueWindow::TableCell(
|
DialogueWindow::TableCell(
|
||||||
zone->newzone_data.suspend_buffs ?
|
zone->newzone_data.suspend_buffs ?
|
||||||
DialogueWindow::ColorMessage("forest_green", "Y") :
|
DialogueWindow::ColorMessage("forest_green", "Y") :
|
||||||
DialogueWindow::ColorMessage("red1", "N")
|
DialogueWindow::ColorMessage("red_1", "N")
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,11 @@ void command_summon(Client *c, const Seperator *sep)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!target) {
|
||||||
|
c->Message(Chat::White, "You must have a target to summon.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
c->Message(
|
c->Message(
|
||||||
Chat::White,
|
Chat::White,
|
||||||
fmt::format(
|
fmt::format(
|
||||||
|
|||||||
+6
-1
@@ -555,9 +555,14 @@ void Group::MemberZoned(Mob* removemob) {
|
|||||||
|
|
||||||
//should NOT clear the name, it is used for world communication.
|
//should NOT clear the name, it is used for world communication.
|
||||||
for (auto & m : members) {
|
for (auto & m : members) {
|
||||||
if (m && (m == removemob || (m->IsBot() && m->CastToBot()->GetBotOwner() == removemob))) {
|
if (m) {
|
||||||
|
if (m->IsBot() && m->CastToBot()->GetBotOwner() && m->CastToBot()->GetBotOwner() == removemob) {
|
||||||
m = nullptr;
|
m = nullptr;
|
||||||
}
|
}
|
||||||
|
else if (m == removemob) {
|
||||||
|
m = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removemob->IsClient() && HasRole(removemob, RoleAssist)) {
|
if (removemob->IsClient() && HasRole(removemob, RoleAssist)) {
|
||||||
|
|||||||
+15
-3
@@ -315,11 +315,16 @@ void Lua_Mob::SetInvisible(int state) {
|
|||||||
self->SetInvisible(state);
|
self->SetInvisible(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Lua_Mob::FindBuff(int spell_id) {
|
bool Lua_Mob::FindBuff(uint16 spell_id) {
|
||||||
Lua_Safe_Call_Bool();
|
Lua_Safe_Call_Bool();
|
||||||
return self->FindBuff(spell_id);
|
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) {
|
uint16 Lua_Mob::FindBuffBySlot(int slot) {
|
||||||
Lua_Safe_Call_Int();
|
Lua_Safe_Call_Int();
|
||||||
return self->FindBuffBySlot(slot);
|
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) {
|
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot) {
|
||||||
Lua_Safe_Call_Bool();
|
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) {
|
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("Emote", &Lua_Mob::Emote)
|
||||||
.def("EntityVariableExists", &Lua_Mob::EntityVariableExists)
|
.def("EntityVariableExists", &Lua_Mob::EntityVariableExists)
|
||||||
.def("FaceTarget", (void(Lua_Mob::*)(Lua_Mob))&Lua_Mob::FaceTarget)
|
.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("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))&Lua_Mob::FindGroundZ)
|
||||||
.def("FindGroundZ", (double(Lua_Mob::*)(double,double,double))&Lua_Mob::FindGroundZ)
|
.def("FindGroundZ", (double(Lua_Mob::*)(double,double,double))&Lua_Mob::FindGroundZ)
|
||||||
|
|||||||
+2
-1
@@ -90,7 +90,8 @@ public:
|
|||||||
uint8 GetInvisibleUndeadLevel();
|
uint8 GetInvisibleUndeadLevel();
|
||||||
void SetSeeInvisibleLevel(uint8 invisible_level);
|
void SetSeeInvisibleLevel(uint8 invisible_level);
|
||||||
void SetSeeInvisibleUndeadLevel(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);
|
uint16 FindBuffBySlot(int slot);
|
||||||
uint32 BuffCount();
|
uint32 BuffCount();
|
||||||
uint32 BuffCount(bool is_beneficial);
|
uint32 BuffCount(bool is_beneficial);
|
||||||
|
|||||||
+35
-35
@@ -593,42 +593,49 @@ void Mob::CalcSeeInvisibleLevel()
|
|||||||
see_invis = std::max({ spellbonuses.SeeInvis, itembonuses.SeeInvis, aabonuses.SeeInvis, innate_see_invis });
|
see_invis = std::max({ spellbonuses.SeeInvis, itembonuses.SeeInvis, aabonuses.SeeInvis, innate_see_invis });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::CalcInvisibleLevel()
|
bool Mob::HasAnInvisibilityEffect() {
|
||||||
{
|
return invisible || hidden || improved_hidden || invisible_animals || invisible_undead;
|
||||||
bool is_invisible = invisible;
|
}
|
||||||
|
|
||||||
invisible = std::max({ spellbonuses.invisibility, nobuff_invisible });
|
void Mob::BreakCharmPetIfConditionsMet() {
|
||||||
invisible_undead = spellbonuses.invisibility_verse_undead;
|
auto pet = GetPet();
|
||||||
invisible_animals = spellbonuses.invisibility_verse_animal;
|
if (pet && pet->GetPetType() == petCharmed && HasAnInvisibilityEffect()) {
|
||||||
|
if (RuleB(Pets, LivelikeBreakCharmOnInvis) || IsInvisible(pet)) {
|
||||||
if (!is_invisible && invisible) {
|
pet->BuffFadeByEffect(SE_Charm);
|
||||||
SetInvisible(Invisibility::Invisible, true);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
LogRules(
|
||||||
if (is_invisible && !invisible) {
|
"Pets:LivelikeBreakCharmOnInvis for [{}] invisible [{}] hidden [{}] improved_hidden (shroud of stealth) [{}] invisible_animals [{}] invisible_undead [{}]",
|
||||||
SetInvisible(invisible, true);
|
GetCleanName(),
|
||||||
return;
|
invisible,
|
||||||
|
hidden,
|
||||||
|
improved_hidden,
|
||||||
|
invisible_animals,
|
||||||
|
invisible_undead
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::SetInvisible(uint8 state, bool set_on_bonus_calc)
|
void Mob::CalcInvisibleLevel()
|
||||||
{
|
{
|
||||||
/*
|
bool was_invisible = invisible;
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
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) {
|
if (state == Invisibility::Visible) {
|
||||||
SendAppearancePacket(AT_Invis, Invisibility::Visible);
|
SendAppearancePacket(AT_Invis, Invisibility::Visible);
|
||||||
ZeroInvisibleVars(InvisType::T_INVISIBLE);
|
ZeroInvisibleVars(InvisType::T_INVISIBLE);
|
||||||
}
|
} else {
|
||||||
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.
|
|
||||||
*/
|
|
||||||
if (!set_on_bonus_calc) {
|
if (!set_on_bonus_calc) {
|
||||||
nobuff_invisible = state;
|
nobuff_invisible = state;
|
||||||
CalcInvisibleLevel();
|
CalcInvisibleLevel();
|
||||||
@@ -636,14 +643,7 @@ void Mob::SetInvisible(uint8 state, bool set_on_bonus_calc)
|
|||||||
SendAppearancePacket(AT_Invis, invisible);
|
SendAppearancePacket(AT_Invis, invisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invis and hide breaks charms
|
BreakCharmPetIfConditionsMet();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::ZeroInvisibleVars(uint8 invisible_type)
|
void Mob::ZeroInvisibleVars(uint8 invisible_type)
|
||||||
@@ -5114,7 +5114,7 @@ std::string Mob::GetTargetDescription(Mob* target, uint8 description_type, uint1
|
|||||||
auto d = fmt::format(
|
auto d = fmt::format(
|
||||||
"{}",
|
"{}",
|
||||||
(
|
(
|
||||||
this == target ?
|
target && this == target ?
|
||||||
self_return :
|
self_return :
|
||||||
fmt::format(
|
fmt::format(
|
||||||
"{} ({})",
|
"{} ({})",
|
||||||
|
|||||||
+3
-1
@@ -269,6 +269,8 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasAnInvisibilityEffect();
|
||||||
|
void BreakCharmPetIfConditionsMet();
|
||||||
//Invisible
|
//Invisible
|
||||||
bool IsInvisible(Mob* other = 0) const;
|
bool IsInvisible(Mob* other = 0) const;
|
||||||
void SetInvisible(uint8 state, bool set_on_bonus_calc = false);
|
void SetInvisible(uint8 state, bool set_on_bonus_calc = false);
|
||||||
@@ -464,7 +466,7 @@ public:
|
|||||||
void DamageShield(Mob* other, bool spell_ds = false);
|
void DamageShield(Mob* other, bool spell_ds = false);
|
||||||
int32 RuneAbsorb(int64 damage, uint16 type);
|
int32 RuneAbsorb(int64 damage, uint16 type);
|
||||||
std::vector<uint16> GetBuffSpellIDs();
|
std::vector<uint16> GetBuffSpellIDs();
|
||||||
bool FindBuff(uint16 spell_id);
|
bool FindBuff(uint16 spell_id, uint16 caster_id = 0);
|
||||||
uint16 FindBuffBySlot(int slot);
|
uint16 FindBuffBySlot(int slot);
|
||||||
uint32 BuffCount(bool is_beneficial = true, bool is_detrimental = true);
|
uint32 BuffCount(bool is_beneficial = true, bool is_detrimental = true);
|
||||||
bool FindType(uint16 type, bool bOffensive = false, uint16 threshold = 100);
|
bool FindType(uint16 type, bool bOffensive = false, uint16 threshold = 100);
|
||||||
|
|||||||
+7
-1
@@ -362,6 +362,11 @@ bool Perl_Mob_FindBuff(Mob* self, uint16 spell_id) // @categories Spells and Dis
|
|||||||
return self->FindBuff(spell_id);
|
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
|
int Perl_Mob_FindBuffBySlot(Mob* self, int slot) // @categories Spells and Disciplines, Script Utility
|
||||||
{
|
{
|
||||||
return self->FindBuffBySlot(slot);
|
return self->FindBuffBySlot(slot);
|
||||||
@@ -3570,7 +3575,8 @@ void perl_register_mob()
|
|||||||
package.add("EntityVariableExists", &Perl_Mob_EntityVariableExists);
|
package.add("EntityVariableExists", &Perl_Mob_EntityVariableExists);
|
||||||
package.add("FaceTarget", (void(*)(Mob*))&Perl_Mob_FaceTarget);
|
package.add("FaceTarget", (void(*)(Mob*))&Perl_Mob_FaceTarget);
|
||||||
package.add("FaceTarget", (void(*)(Mob*, 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("FindBuffBySlot", &Perl_Mob_FindBuffBySlot);
|
||||||
package.add("FindGroundZ", (float(*)(Mob*, float, float))&Perl_Mob_FindGroundZ);
|
package.add("FindGroundZ", (float(*)(Mob*, float, float))&Perl_Mob_FindGroundZ);
|
||||||
package.add("FindGroundZ", (float(*)(Mob*, float, float, float))&Perl_Mob_FindGroundZ);
|
package.add("FindGroundZ", (float(*)(Mob*, float, float, float))&Perl_Mob_FindGroundZ);
|
||||||
|
|||||||
@@ -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
|
if((spell_id != 6882) && (spell_id != 6884)) // Chaotic Jester/Steadfast Servant
|
||||||
{
|
{
|
||||||
char pet_name[64];
|
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);
|
caster->TemporaryPets(spell_id, this, pet_name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2443,7 +2443,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
|||||||
{
|
{
|
||||||
if(caster && caster->IsClient()) {
|
if(caster && caster->IsClient()) {
|
||||||
char pet_name[64];
|
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_count = spells[spell_id].base_value[i];
|
||||||
int pet_duration = spells[spell_id].max_value[i];
|
int pet_duration = spells[spell_id].max_value[i];
|
||||||
caster->CastToClient()->Doppelganger(spell_id, this, pet_name, pet_count, pet_duration);
|
caster->CastToClient()->Doppelganger(spell_id, this, pet_name, pet_count, pet_duration);
|
||||||
|
|||||||
+8
-4
@@ -4411,14 +4411,18 @@ std::vector<uint16> Mob::GetBuffSpellIDs()
|
|||||||
return l;
|
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++) {
|
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 (
|
if (
|
||||||
IsValidSpell(current_spell_id) &&
|
IsValidSpell(current_spell_id) &&
|
||||||
current_spell_id == spell_id
|
current_spell_id == spell_id &&
|
||||||
|
(
|
||||||
|
!caster_id ||
|
||||||
|
buffs[buff_slot].casterid == caster_id
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -157,7 +157,7 @@ void NPC::ResumeWandering()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogError("NPC not paused - can't resume wandering: [{}]", (unsigned long)GetNPCTypeID());
|
LogPathing("NPC not paused - can't resume wandering: [{}]", (unsigned long)GetNPCTypeID());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ void NPC::ResumeWandering()
|
|||||||
}
|
}
|
||||||
else
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@@ -195,7 +195,7 @@ void NPC::PauseWandering(int pausetime)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user