Fixed the buff database entries and updated database migrations

This commit is contained in:
dannuic
2026-05-03 01:43:53 -06:00
parent 18df055f16
commit 7a191fc6bb
55 changed files with 1299 additions and 819 deletions
+5 -5
View File
@@ -1568,7 +1568,7 @@ bool Bot::LoadPet()
NPC *pet_inst = GetPet()->CastToNPC();
SpellBuff_Struct pet_buffs[PET_BUFF_COUNT];
Buffs_Struct pet_buffs[PET_BUFF_COUNT];
memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * PET_BUFF_COUNT));
database.botdb.LoadPetBuffs(GetBotID(), pet_buffs);
@@ -1576,7 +1576,7 @@ bool Bot::LoadPet()
memset(pet_items, 0, (sizeof(uint32) * EQ::invslot::EQUIPMENT_COUNT));
database.botdb.LoadPetItems(GetBotID(), pet_items);
pet_inst->SetPetState(pet_buffs, pet_items);
pet_inst->RestorePetState(pet_buffs, pet_items);
pet_inst->CalcBonuses();
pet_inst->SetHP(pet_hp);
pet_inst->SetMana(pet_mana);
@@ -1601,14 +1601,14 @@ bool Bot::SavePet()
}
auto pet_name = new char[64];
SpellBuff_Struct pet_buffs[PET_BUFF_COUNT];
Buffs_Struct pet_buffs[PET_BUFF_COUNT];
uint32 pet_items[EQ::invslot::EQUIPMENT_COUNT];
memset(pet_name, 0, 64);
memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * PET_BUFF_COUNT));
memset(pet_buffs, 0, (sizeof(Buffs_Struct) * PET_BUFF_COUNT));
memset(pet_items, 0, (sizeof(uint32) * EQ::invslot::EQUIPMENT_COUNT));
pet_inst->GetPetState(pet_buffs, pet_items, pet_name);
pet_inst->SavePetState(pet_buffs, pet_items, pet_name);
std::string pet_name_str = pet_name;
safe_delete_array(pet_name)
+107 -43
View File
@@ -622,41 +622,70 @@ bool BotDatabase::LoadBuffs(Bot* b)
buffs[index].spellid = SPELL_UNKNOWN;
}
uint32 buff_count = 0;
uint32 buff_index = 0;
for (const auto& e : l) {
if (buff_count >= BUFF_COUNT) {
if (buff_index >= BUFF_COUNT) {
continue;
}
buffs[buff_count].spellid = e.spell_id;
buffs[buff_count].casterlevel = e.caster_level;
buffs[buff_count].ticsremaining = e.tics_remaining;
buffs[buff_count].counters = 0;
Client* c = entity_list.GetClientByName(e.caster_name.c_str());
if (CalculatePoisonCounters(buffs[buff_count].spellid) > 0) {
buffs[buff_count].counters = e.poison_counters;
} else if (CalculateDiseaseCounters(buffs[buff_count].spellid) > 0) {
buffs[buff_count].counters = e.disease_counters;
} else if (CalculateCurseCounters(buffs[buff_count].spellid) > 0) {
buffs[buff_count].counters = e.curse_counters;
} else if (CalculateCorruptionCounters(buffs[buff_count].spellid) > 0) {
buffs[buff_count].counters = e.corruption_counters;
buffs[buff_index].spellid = e.spell_id;
buffs[buff_index].casterlevel = e.caster_level;
if (c) {
buffs[buff_index].casterid = c->GetID();
buffs[buff_index].client = true;
strncpy(buffs[buff_index].caster_name, c->GetName(), 64);
} else {
buffs[buff_index].casterid = 0;
buffs[buff_index].client = false;
strncpy(buffs[buff_index].caster_name, "", 64);
}
buffs[buff_count].hit_number = e.numhits;
buffs[buff_count].melee_rune = e.melee_rune;
buffs[buff_count].magic_rune = e.magic_rune;
buffs[buff_count].dot_rune = e.dot_rune;
buffs[buff_count].persistant_buff = e.persistent;
buffs[buff_count].caston_x = e.caston_x;
buffs[buff_count].caston_y = e.caston_y;
buffs[buff_count].caston_z = e.caston_z;
buffs[buff_count].ExtraDIChance = e.extra_di_chance;
buffs[buff_count].instrument_mod = e.instrument_mod;
buffs[buff_count].casterid = 0;
buffs[buff_index].ticsremaining = e.tics_remaining;
buffs[buff_index].initialduration = e.initial_duration;
buffs[buff_index].counters = 0;
buffs[buff_index].hit_number = e.numhits;
buffs[buff_index].melee_rune = e.melee_rune;
buffs[buff_index].magic_rune = e.magic_rune;
buffs[buff_index].persistent_buff = e.persistent ? true : false;
buffs[buff_index].dot_rune = e.dot_rune;
buffs[buff_index].caston_x = e.caston_x;
buffs[buff_index].caston_y = e.caston_y;
buffs[buff_index].caston_z = e.caston_z;
buffs[buff_index].ExtraDIChance = e.extra_di_chance;
buffs[buff_index].RootBreakChance = 0;
buffs[buff_index].virus_spread_time = 0;
buffs[buff_index].UpdateClient = false;
buffs[buff_index].instrument_mod = e.instrument_mod;
++buff_count;
if (CalculatePoisonCounters(buffs[buff_index].spellid) > 0) {
buffs[buff_index].counters = e.poison_counters;
} else if (CalculateDiseaseCounters(buffs[buff_index].spellid) > 0) {
buffs[buff_index].counters = e.disease_counters;
} else if (CalculateCurseCounters(buffs[buff_index].spellid) > 0) {
buffs[buff_index].counters = e.curse_counters;
} else if (CalculateCorruptionCounters(buffs[buff_index].spellid) > 0) {
buffs[buff_index].counters = e.corruption_counters;
}
buffs[buff_index].hit_number = e.numhits;
buffs[buff_index].melee_rune = e.melee_rune;
buffs[buff_index].magic_rune = e.magic_rune;
buffs[buff_index].dot_rune = e.dot_rune;
buffs[buff_index].persistent_buff = e.persistent;
buffs[buff_index].caston_x = e.caston_x;
buffs[buff_index].caston_y = e.caston_y;
buffs[buff_index].caston_z = e.caston_z;
buffs[buff_index].ExtraDIChance = e.extra_di_chance;
buffs[buff_index].instrument_mod = e.instrument_mod;
buffs[buff_index].casterid = 0;
++buff_index;
}
return true;
@@ -691,8 +720,10 @@ bool BotDatabase::SaveBuffs(Bot* b)
e.spell_id = buffs[buff_index].spellid;
e.caster_level = buffs[buff_index].casterlevel;
e.caster_name = buffs[buff_index].caster_name;
e.duration_formula = spells[buffs[buff_index].spellid].buff_duration_formula;
e.tics_remaining = buffs[buff_index].ticsremaining;
e.initial_duration = buffs[buff_index].initialduration;
e.poison_counters = CalculatePoisonCounters(buffs[buff_index].spellid) > 0 ? buffs[buff_index].counters : 0;
e.disease_counters = CalculateDiseaseCounters(buffs[buff_index].spellid) > 0 ? buffs[buff_index].counters : 0;
e.curse_counters = CalculateCurseCounters(buffs[buff_index].spellid) > 0 ? buffs[buff_index].counters : 0;
@@ -701,7 +732,7 @@ bool BotDatabase::SaveBuffs(Bot* b)
e.melee_rune = buffs[buff_index].melee_rune;
e.magic_rune = buffs[buff_index].magic_rune;
e.dot_rune = buffs[buff_index].dot_rune;
e.persistent = buffs[buff_index].persistant_buff ? 1 : 0;
e.persistent = buffs[buff_index].persistent_buff ? 1 : 0;
e.caston_x = buffs[buff_index].caston_x;
e.caston_y = buffs[buff_index].caston_y;
e.caston_z = buffs[buff_index].caston_z;
@@ -1360,7 +1391,7 @@ bool BotDatabase::DeletePetStats(const uint32 bot_id)
return BotPetsRepository::DeleteOne(database, saved_pet_index) == 1;
}
bool BotDatabase::LoadPetBuffs(const uint32 bot_id, SpellBuff_Struct* pet_buffs)
bool BotDatabase::LoadPetBuffs(const uint32 bot_id, Buffs_Struct* pet_buffs)
{
if (!bot_id) {
return false;
@@ -1395,27 +1426,47 @@ bool BotDatabase::LoadPetBuffs(const uint32 bot_id, SpellBuff_Struct* pet_buffs)
break;
}
pet_buffs[buff_index].spellid = e.spell_id;
pet_buffs[buff_index].level = e.caster_level;
pet_buffs[buff_index].duration = e.duration;
Client* c = entity_list.GetClientByName(e.caster_name.c_str());
if (CalculatePoisonCounters(pet_buffs[buff_index].spellid) > 0) {
pet_buffs[buff_index].counters = CalculatePoisonCounters(pet_buffs[buff_index].spellid);
} else if (CalculateDiseaseCounters(pet_buffs[buff_index].spellid) > 0) {
pet_buffs[buff_index].counters = CalculateDiseaseCounters(pet_buffs[buff_index].spellid);
} else if (CalculateCurseCounters(pet_buffs[buff_index].spellid) > 0) {
pet_buffs[buff_index].counters = CalculateCurseCounters(pet_buffs[buff_index].spellid);
} else if (CalculateCorruptionCounters(pet_buffs[buff_index].spellid) > 0) {
pet_buffs[buff_index].counters = CalculateCorruptionCounters(pet_buffs[buff_index].spellid);
pet_buffs[buff_index].spellid = e.spell_id;
pet_buffs[buff_index].casterlevel = e.caster_level;
if (c) {
pet_buffs[buff_index].casterid = c->GetID();
pet_buffs[buff_index].client = true;
strncpy(pet_buffs[buff_index].caster_name, c->GetName(), 64);
} else {
pet_buffs[buff_index].casterid = 0;
pet_buffs[buff_index].client = false;
strncpy(pet_buffs[buff_index].caster_name, "", 64);
}
pet_buffs[buff_index].ticsremaining = e.tics_remaining;
pet_buffs[buff_index].initialduration = e.initial_duration;
pet_buffs[buff_index].counters = e.counters;
pet_buffs[buff_index].hit_number = e.numhits;
pet_buffs[buff_index].melee_rune = e.melee_rune;
pet_buffs[buff_index].magic_rune = e.magic_rune;
pet_buffs[buff_index].persistent_buff = e.persistent ? true : false;
pet_buffs[buff_index].dot_rune = e.dot_rune;
pet_buffs[buff_index].caston_x = e.caston_x;
pet_buffs[buff_index].caston_y = e.caston_y;
pet_buffs[buff_index].caston_z = e.caston_z;
pet_buffs[buff_index].ExtraDIChance = e.extra_di_chance;
pet_buffs[buff_index].RootBreakChance = 0;
pet_buffs[buff_index].virus_spread_time = 0;
pet_buffs[buff_index].UpdateClient = false;
pet_buffs[buff_index].instrument_mod = e.instrument_mod;
++buff_index;
}
return true;
}
bool BotDatabase::SavePetBuffs(const uint32 bot_id, const SpellBuff_Struct* pet_buffs, bool delete_flag)
bool BotDatabase::SavePetBuffs(const uint32 bot_id, const Buffs_Struct* pet_buffs, bool delete_flag)
{
if (
!bot_id ||
@@ -1446,9 +1497,22 @@ bool BotDatabase::SavePetBuffs(const uint32 bot_id, const SpellBuff_Struct* pet_
continue;
}
e.spell_id = pet_buffs[buff_index].spellid;
e.caster_level = pet_buffs[buff_index].level;
e.duration = pet_buffs[buff_index].duration;
e.spell_id = pet_buffs[buff_index].spellid;
e.caster_level = pet_buffs[buff_index].casterlevel;
e.caster_name = pet_buffs[buff_index].caster_name;
e.tics_remaining = pet_buffs[buff_index].ticsremaining;
e.initial_duration = pet_buffs[buff_index].initialduration;
e.counters = pet_buffs[buff_index].counters;
e.numhits = pet_buffs[buff_index].hit_number;
e.melee_rune = pet_buffs[buff_index].melee_rune;
e.magic_rune = pet_buffs[buff_index].magic_rune;
e.persistent = pet_buffs[buff_index].persistent_buff;
e.dot_rune = pet_buffs[buff_index].dot_rune;
e.caston_x = pet_buffs[buff_index].caston_x;
e.caston_y = pet_buffs[buff_index].caston_y;
e.caston_z = pet_buffs[buff_index].caston_z;
e.extra_di_chance = pet_buffs[buff_index].ExtraDIChance;
e.instrument_mod = pet_buffs[buff_index].instrument_mod;
v.emplace_back(e);
}
+2 -2
View File
@@ -96,8 +96,8 @@ public:
bool SavePetStats(const uint32 bot_id, const std::string& pet_name, const uint32 pet_mana, const uint32 pet_hp, const int32 pet_spell_id);
bool DeletePetStats(const uint32 bot_id);
bool LoadPetBuffs(const uint32 bot_id, SpellBuff_Struct* pet_buffs);
bool SavePetBuffs(const uint32 bot_id, const SpellBuff_Struct* pet_buffs, bool delete_flag = false);
bool LoadPetBuffs(const uint32 bot_id, Buffs_Struct* pet_buffs);
bool SavePetBuffs(const uint32 bot_id, const Buffs_Struct* pet_buffs, bool delete_flag = false);
bool DeletePetBuffs(const uint32 bot_id);
bool LoadPetItems(const uint32 bot_id, uint32* pet_items);
+3 -3
View File
@@ -1048,7 +1048,7 @@ bool Client::Save(uint8 iCommitNow) {
m_petinfo.SpellID = pet->CastToNPC()->GetPetSpellID();
m_petinfo.HP = pet->GetHP();
m_petinfo.Mana = pet->GetMana();
pet->GetPetState(m_petinfo.Buffs, m_petinfo.Items, m_petinfo.Name);
pet->SavePetState(m_petinfo.Buffs, m_petinfo.Items, m_petinfo.Name);
m_petinfo.petpower = pet->GetPetPower();
m_petinfo.size = pet->GetSize();
m_petinfo.taunting = pet->CastToNPC()->IsTaunting();
@@ -6325,7 +6325,7 @@ void Client::SuspendMinion(int value)
if(value >= 1)
{
CurrentPet->SetPetState(m_suspendedminion.Buffs, m_suspendedminion.Items);
CurrentPet->RestorePetState(m_suspendedminion.Buffs, m_suspendedminion.Items);
ClientPatch::SendFullBuffRefresh(CurrentPet);
}
CurrentPet->CalcBonuses();
@@ -6392,7 +6392,7 @@ void Client::SuspendMinion(int value)
m_suspendedminion.size = CurrentPet->GetSize();
if(value >= 1)
CurrentPet->GetPetState(m_suspendedminion.Buffs, m_suspendedminion.Items, m_suspendedminion.Name);
CurrentPet->SavePetState(m_suspendedminion.Buffs, m_suspendedminion.Items, m_suspendedminion.Name);
else
strn0cpy(m_suspendedminion.Name, CurrentPet->GetName(), 64); // Name stays even at rank 1
+3 -3
View File
@@ -663,7 +663,7 @@ void Client::CompleteConnect()
break;
}
if (buffs[j1].persistant_buff) {
if (buffs[j1].persistent_buff) {
Mob *caster = entity_list.GetMobID(buffs[j1].casterid);
ApplySpellEffectIllusion(spell.id, caster, j1, spell.base_value[x1], spell.limit_value[x1], spell.max_value[x1]);
}
@@ -1715,13 +1715,13 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (RuleB(NPC, PetZoneWithOwner)) {
/* Load Pet */
database.LoadPetInfo(this);
database.LoadPetInfo(this); // TODO: Is the pet loading correctly? I don't get any buffs
if (m_petinfo.SpellID > 1 && !GetPet() && m_petinfo.SpellID <= SPDAT_RECORDS) {
MakePoweredPet(m_petinfo.SpellID, spells[m_petinfo.SpellID].teleport_zone, m_petinfo.petpower,
m_petinfo.Name, m_petinfo.size);
if (GetPet() && GetPet()->IsNPC()) {
NPC *pet = GetPet()->CastToNPC();
pet->SetPetState(m_petinfo.Buffs, m_petinfo.Items);
pet->RestorePetState(m_petinfo.Buffs, m_petinfo.Items);
pet->CalcBonuses();
pet->SetHP(m_petinfo.HP);
pet->SetMana(m_petinfo.Mana);
+3 -2
View File
@@ -241,7 +241,7 @@ struct Buffs_Struct {
int16 RootBreakChance; //Not saved to dbase
uint32 instrument_mod;
int32 virus_spread_time; //time till next attempted viral spread
bool persistant_buff;
bool persistent_buff;
bool client; //True if the caster is a client
bool UpdateClient; // This is for legacy client support only. Newer clients take refresh packets for the entire buff list
@@ -261,6 +261,7 @@ struct Buffs_Struct {
CEREAL_NVP(casterid),
CEREAL_NVP(caster_name_str),
CEREAL_NVP(ticsremaining),
CEREAL_NVP(initialduration),
CEREAL_NVP(counters),
CEREAL_NVP(hit_number),
CEREAL_NVP(melee_rune),
@@ -273,7 +274,7 @@ struct Buffs_Struct {
CEREAL_NVP(RootBreakChance),
CEREAL_NVP(instrument_mod),
CEREAL_NVP(virus_spread_time),
CEREAL_NVP(persistant_buff),
CEREAL_NVP(persistent_buff),
CEREAL_NVP(client),
CEREAL_NVP(UpdateClient)
);
+1 -1
View File
@@ -134,7 +134,7 @@ bool Lua_Buff::IsCasterClient()
bool Lua_Buff::IsPersistentBuff()
{
Lua_Safe_Call_Bool();
return self->persistant_buff;
return self->persistent_buff;
}
bool Lua_Buff::SendsClientUpdate()
+4 -3
View File
@@ -184,8 +184,8 @@ public:
void GoToBind(uint8 bind_number = 0) { GMMove(m_SpawnPoint.x, m_SpawnPoint.y, m_SpawnPoint.z, m_SpawnPoint.w); }
void Gate(uint8 bind_number = 0);
void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name);
void SetPetState(SpellBuff_Struct *buffs, uint32 *items);
void SavePetState(Buffs_Struct* buffs, uint32 *items, char *name) const;
void RestorePetState(const Buffs_Struct* pet_buffs, const uint32* items);
virtual void SpellProcess();
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
@@ -611,6 +611,7 @@ public:
buffs[i].casterid = b.casterid;
strncpy(buffs[i].caster_name, b.caster_name, 64);
buffs[i].ticsremaining = b.ticsremaining;
buffs[i].initialduration = b.initialduration;
buffs[i].counters = b.counters;
buffs[i].hit_number = b.hit_number;
buffs[i].melee_rune = b.melee_rune;
@@ -623,7 +624,7 @@ public:
buffs[i].RootBreakChance = b.RootBreakChance;
buffs[i].instrument_mod = b.instrument_mod;
buffs[i].virus_spread_time = b.virus_spread_time;
buffs[i].persistant_buff = b.persistant_buff;
buffs[i].persistent_buff = b.persistent_buff;
buffs[i].client = b.client;
buffs[i].UpdateClient = b.UpdateClient;
i++;
+1 -1
View File
@@ -114,7 +114,7 @@ bool Perl_Buff_IsCasterClient(Buffs_Struct* self)
bool Perl_Buff_IsPersistentBuff(Buffs_Struct* self)
{
return self->persistant_buff;
return self->persistent_buff;
}
bool Perl_Buff_SendsClientUpdate(Buffs_Struct* self)
+54 -84
View File
@@ -471,7 +471,8 @@ void Mob::SetPetID(uint16 NewPetID) {
}
}
void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) {
void NPC::SavePetState(Buffs_Struct* pet_buffs, uint32 *items, char *name) const
{
//save the pet name
strn0cpy(name, GetName(), 64);
@@ -479,102 +480,71 @@ void NPC::GetPetState(SpellBuff_Struct *pet_buffs, uint32 *items, char *name) {
memcpy(items, equipment, sizeof(uint32) * EQ::invslot::EQUIPMENT_COUNT);
//save their buffs.
for (int i=EQ::invslot::EQUIPMENT_BEGIN; i < GetPetMaxTotalSlots(); i++) {
if (IsValidSpell(buffs[i].spellid)) {
pet_buffs[i].spellid = buffs[i].spellid;
pet_buffs[i].effect_type = i+1;
pet_buffs[i].duration = buffs[i].ticsremaining;
pet_buffs[i].level = buffs[i].casterlevel;
pet_buffs[i].bard_modifier = 10;
pet_buffs[i].counters = buffs[i].counters;
pet_buffs[i].bard_modifier = buffs[i].instrument_mod;
}
else {
pet_buffs[i].spellid = SPELL_UNKNOWN;
pet_buffs[i].duration = 0;
pet_buffs[i].level = 0;
pet_buffs[i].bard_modifier = 10;
pet_buffs[i].counters = 0;
}
}
memcpy(pet_buffs, buffs, sizeof(Buffs_Struct) * GetPetMaxTotalSlots());
}
void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) {
void NPC::RestorePetState(const Buffs_Struct* pet_buffs, const uint32* items) {
//restore their buffs...
memcpy(buffs, pet_buffs, sizeof(Buffs_Struct) * GetPetMaxTotalSlots());
int i;
for (i = 0; i < GetPetMaxTotalSlots(); i++) {
for(int z = 0; z < GetPetMaxTotalSlots(); z++) {
// check for duplicates
if(IsValidSpell(buffs[z].spellid) && buffs[z].spellid == pet_buffs[i].spellid) {
buffs[z].spellid = SPELL_UNKNOWN;
pet_buffs[i].spellid = 0xFFFFFFFF;
}
}
if (pet_buffs[i].spellid <= (uint32)SPDAT_RECORDS && pet_buffs[i].spellid != 0 && (pet_buffs[i].duration > 0 || pet_buffs[i].duration == -1)) {
if(pet_buffs[i].level == 0 || pet_buffs[i].level > 100)
pet_buffs[i].level = 1;
buffs[i].spellid = pet_buffs[i].spellid;
buffs[i].ticsremaining = pet_buffs[i].duration;
buffs[i].casterlevel = pet_buffs[i].level;
buffs[i].casterid = 0;
buffs[i].counters = pet_buffs[i].counters;
buffs[i].hit_number = spells[pet_buffs[i].spellid].hit_number;
buffs[i].instrument_mod = pet_buffs[i].bard_modifier;
}
else {
buffs[i].spellid = SPELL_UNKNOWN;
pet_buffs[i].spellid = 0xFFFFFFFF;
pet_buffs[i].effect_type = 0;
pet_buffs[i].level = 0;
pet_buffs[i].duration = 0;
pet_buffs[i].bard_modifier = 0;
}
}
for (int j1=0; j1 < GetPetMaxTotalSlots(); j1++) {
if (buffs[j1].spellid <= (uint32)SPDAT_RECORDS) {
for (int x1=0; x1 < EFFECT_COUNT; x1++) {
switch (spells[buffs[j1].spellid].effect_id[x1]) {
case SpellEffect::AddMeleeProc:
case SpellEffect::WeaponProc:
// We need to reapply buff based procs
// We need to do this here so suspended pets also regain their procs.
AddProcToWeapon(GetProcID(buffs[j1].spellid,x1), false, 100+spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, buffs[j1].casterlevel, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::MELEE_PROC));
break;
case SpellEffect::DefensiveProc:
AddDefensiveProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::DEFENSIVE_PROC));
break;
case SpellEffect::RangedProc:
AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100 + spells[buffs[j1].spellid].limit_value[x1], buffs[j1].spellid, GetSpellProcLimitTimer(buffs[j1].spellid, ProcType::RANGED_PROC));
break;
case SpellEffect::Charm:
case SpellEffect::Rune:
case SpellEffect::NegateAttacks:
case SpellEffect::Illusion:
buffs[j1].spellid = SPELL_UNKNOWN;
pet_buffs[j1].spellid = SPELL_UNKNOWN;
pet_buffs[j1].effect_type = 0;
pet_buffs[j1].level = 0;
pet_buffs[j1].duration = 0;
pet_buffs[j1].bard_modifier = 0;
x1 = EFFECT_COUNT;
break;
// We can't send appearance packets yet, put down at CompleteConnect
for (int slot = 0; slot < GetPetMaxTotalSlots(); ++slot) {
if (IsValidSpell(buffs[slot].spellid)) {
// check for duplicates of valid spells, keep the lowest one
for (int slot2 = slot + 1; slot2 < GetPetMaxTotalSlots(); ++slot2) {
if (IsValidSpell(buffs[slot2].spellid) && buffs[slot].spellid == buffs[slot2].spellid) {
buffs[slot2].spellid = SPELL_UNKNOWN;
buffs[slot2].ticsremaining = 0;
}
}
// re-add any specific passive effects that need to be added
for (int effect = 0; effect < EFFECT_COUNT; ++effect) {
switch (spells[buffs[slot].spellid].effect_id[effect]) {
case SpellEffect::AddMeleeProc:
case SpellEffect::WeaponProc:
// We need to reapply buff based procs
// We need to do this here so suspended pets also regain their procs.
AddProcToWeapon(GetProcID(buffs[slot].spellid, effect), false,
100 + spells[buffs[slot].spellid].limit_value[effect], buffs[slot].spellid,
buffs[slot].casterlevel, GetSpellProcLimitTimer(buffs[slot].spellid, ProcType::MELEE_PROC));
break;
case SpellEffect::DefensiveProc:
AddDefensiveProc(GetProcID(buffs[slot].spellid, effect),
100 + spells[buffs[slot].spellid].limit_value[effect], buffs[slot].spellid,
GetSpellProcLimitTimer(buffs[slot].spellid, ProcType::DEFENSIVE_PROC));
break;
case SpellEffect::RangedProc:
AddRangedProc(GetProcID(buffs[slot].spellid, effect),
100 + spells[buffs[slot].spellid].limit_value[effect], buffs[slot].spellid,
GetSpellProcLimitTimer(buffs[slot].spellid, ProcType::RANGED_PROC));
break;
case SpellEffect::Charm:
case SpellEffect::Rune:
case SpellEffect::NegateAttacks:
case SpellEffect::Illusion:
buffs[slot].spellid = SPELL_UNKNOWN;
buffs[slot].ticsremaining = 0;
effect = EFFECT_COUNT; // don't process any more effects, this buff is gone
break;
// We can't send appearance packets yet, put down at CompleteConnect
default:
break;
}
}
} else {
// ensure this buff isn't going to stick around
buffs[slot].spellid = SPELL_UNKNOWN;
buffs[slot].ticsremaining = 0;
}
}
//restore their equipment...
for (i = EQ::invslot::EQUIPMENT_BEGIN; i <= EQ::invslot::EQUIPMENT_END; i++) {
if (items[i] == 0) {
for (int equip = EQ::invslot::EQUIPMENT_BEGIN; equip <= EQ::invslot::EQUIPMENT_END; equip++) {
if (items[equip] == 0) {
continue;
}
const EQ::ItemData *item2 = database.GetItem(items[i]);
if (item2) {
if (const EQ::ItemData *item2 = database.GetItem(items[equip])) {
bool noDrop = (item2->NoDrop == 0); // Field is reverse logic
bool petCanHaveNoDrop = (RuleB(Pets, CanTakeNoDrop) && _CLIENTPET(this) && GetPetType() <= PetType::Normal);
+4 -3
View File
@@ -10532,10 +10532,10 @@ void Mob::ApplySpellEffectIllusion(int32 spell_id, Mob *caster, int buffslot, in
RuleB(Spells, IllusionsAlwaysPersist)
)
) {
buffs[buffslot].persistant_buff = 1;
buffs[buffslot].persistent_buff = 1;
}
else {
buffs[buffslot].persistant_buff = 0;
buffs[buffslot].persistent_buff = 0;
}
}
}
@@ -10654,6 +10654,7 @@ int Mob::GetBuffStatValueBySlot(uint8 slot, const char* stat_identifier)
else if (id == "spell_id") { return buffs[slot].spellid; }
else if (id == "caster_id") { return buffs[slot].spellid; }
else if (id == "ticsremaining") { return buffs[slot].ticsremaining; }
else if (id == "initialduration") { return buffs[slot].initialduration; }
else if (id == "counters") { return buffs[slot].counters; }
else if (id == "hit_number") { return buffs[slot].hit_number; }
else if (id == "melee_rune") { return buffs[slot].melee_rune; }
@@ -10663,7 +10664,7 @@ int Mob::GetBuffStatValueBySlot(uint8 slot, const char* stat_identifier)
else if (id == "caston_y") { return buffs[slot].caston_y; }
else if (id == "caston_z") { return buffs[slot].caston_z; }
else if (id == "instrument_mod") { return buffs[slot].instrument_mod; }
else if (id == "persistant_buff") { return buffs[slot].persistant_buff; }
else if (id == "persistant_buff") { return buffs[slot].persistent_buff; }
else if (id == "client") { return buffs[slot].client; }
else if (id == "extra_di_chance") { return buffs[slot].ExtraDIChance; }
else if (id == "root_break_chance") { return buffs[slot].RootBreakChance; }
+4 -6
View File
@@ -3724,7 +3724,7 @@ int Mob::AddBuff(Mob *caster, int32 spell_id, int duration, int32 level_override
buffs[emptyslot].counters = CalculateCounters(spell_id);
buffs[emptyslot].hit_number = spells[spell_id].hit_number;
buffs[emptyslot].client = caster ? caster->IsClient() : 0;
buffs[emptyslot].persistant_buff = 0;
buffs[emptyslot].persistent_buff = 0;
buffs[emptyslot].caston_x = 0;
buffs[emptyslot].caston_y = 0;
buffs[emptyslot].caston_z = 0;
@@ -4574,11 +4574,9 @@ bool Mob::SpellOnTarget(
// if SpellEffect returned false there's a problem applying the
// spell. It's most likely a buff that can't stack.
LogSpells("Spell [{}] could not apply its effects [{}] -> [{}]\n", spell_id, GetName(), spelltar->GetName());
if (casting_spell_aa_id) {
MessageString(Chat::SpellFailure, SPELL_NO_HOLD);
if (RuleB(Spells, LegacyManaburn) && IsClient() && casting_spell_aa_id == aaManaBurn) {
StopCasting();
}
MessageString(Chat::SpellFailure, SPELL_NO_HOLD);
if (casting_spell_aa_id && RuleB(Spells, LegacyManaburn) && IsClient() && casting_spell_aa_id == aaManaBurn) {
StopCasting();
}
safe_delete(action_packet);
return false;
+82 -39
View File
@@ -2381,6 +2381,7 @@ void ZoneDatabase::SaveMercenaryBuffs(Merc* m)
e.CasterLevel = buffs[slot_id].casterlevel;
e.DurationFormula = spells[buffs[slot_id].spellid].buff_duration_formula;
e.TicsRemaining = buffs[slot_id].ticsremaining;
e.InitialDuration = buffs[slot_id].initialduration;
e.PoisonCounters = CalculatePoisonCounters(buffs[slot_id].spellid) > 0 ? buffs[slot_id].counters : 0;
e.DiseaseCounters = CalculateDiseaseCounters(buffs[slot_id].spellid) > 0 ? buffs[slot_id].counters : 0;
e.CurseCounters = CalculateCurseCounters(buffs[slot_id].spellid) > 0 ? buffs[slot_id].counters : 0;
@@ -2392,8 +2393,9 @@ void ZoneDatabase::SaveMercenaryBuffs(Merc* m)
e.caston_x = buffs[slot_id].caston_x;
e.caston_y = buffs[slot_id].caston_y;
e.caston_z = buffs[slot_id].caston_z;
e.Persistent = buffs[slot_id].persistant_buff ? 1 : 0;
e.Persistent = buffs[slot_id].persistent_buff ? 1 : 0;
e.ExtraDIChance = buffs[slot_id].ExtraDIChance;
e.instrument_mod = buffs[slot_id].instrument_mod;
v.emplace_back(e);
}
@@ -2430,6 +2432,7 @@ void ZoneDatabase::LoadMercenaryBuffs(Merc* m)
buffs[slot_id].spellid = e.SpellId;
buffs[slot_id].casterlevel = e.CasterLevel;
buffs[slot_id].ticsremaining = e.TicsRemaining;
buffs[slot_id].initialduration = e.InitialDuration;
buffs[slot_id].hit_number = e.HitCount;
buffs[slot_id].melee_rune = e.MeleeRune;
buffs[slot_id].magic_rune = e.MagicRune;
@@ -2439,7 +2442,8 @@ void ZoneDatabase::LoadMercenaryBuffs(Merc* m)
buffs[slot_id].caston_z = e.caston_z;
buffs[slot_id].casterid = 0;
buffs[slot_id].ExtraDIChance = e.ExtraDIChance;
buffs[slot_id].persistant_buff = e.Persistent;
buffs[slot_id].persistent_buff = e.Persistent;
buffs[slot_id].instrument_mod = e.instrument_mod;
if (CalculatePoisonCounters(buffs[slot_id].spellid) > 0) {
buffs[slot_id].counters = e.PoisonCounters;
@@ -2926,23 +2930,24 @@ void ZoneDatabase::SaveBuffs(Client *client)
continue;
}
e.character_id = client->CharacterID();
e.slot_id = slot_id;
e.spell_id = buffs[slot_id].spellid;
e.caster_level = buffs[slot_id].casterlevel;
e.caster_name = buffs[slot_id].caster_name;
e.ticsremaining = buffs[slot_id].ticsremaining;
e.counters = buffs[slot_id].counters;
e.numhits = buffs[slot_id].hit_number;
e.melee_rune = buffs[slot_id].melee_rune;
e.magic_rune = buffs[slot_id].magic_rune;
e.persistent = buffs[slot_id].persistant_buff;
e.dot_rune = buffs[slot_id].dot_rune;
e.caston_x = buffs[slot_id].caston_x;
e.caston_y = buffs[slot_id].caston_y;
e.caston_z = buffs[slot_id].caston_z;
e.ExtraDIChance = buffs[slot_id].ExtraDIChance;
e.instrument_mod = buffs[slot_id].instrument_mod;
e.character_id = client->CharacterID();
e.slot_id = slot_id;
e.spell_id = buffs[slot_id].spellid;
e.caster_level = buffs[slot_id].casterlevel;
e.caster_name = buffs[slot_id].caster_name;
e.ticsremaining = buffs[slot_id].ticsremaining;
e.initialduration = buffs[slot_id].initialduration;
e.counters = buffs[slot_id].counters;
e.numhits = buffs[slot_id].hit_number;
e.melee_rune = buffs[slot_id].melee_rune;
e.magic_rune = buffs[slot_id].magic_rune;
e.persistent = buffs[slot_id].persistent_buff;
e.dot_rune = buffs[slot_id].dot_rune;
e.caston_x = buffs[slot_id].caston_x;
e.caston_y = buffs[slot_id].caston_y;
e.caston_z = buffs[slot_id].caston_z;
e.ExtraDIChance = buffs[slot_id].ExtraDIChance;
e.instrument_mod = buffs[slot_id].instrument_mod;
v.emplace_back(e);
}
@@ -3000,11 +3005,12 @@ void ZoneDatabase::LoadBuffs(Client *client)
}
buffs[e.slot_id].ticsremaining = e.ticsremaining;
buffs[e.slot_id].initialduration = e.initialduration;
buffs[e.slot_id].counters = e.counters;
buffs[e.slot_id].hit_number = e.numhits;
buffs[e.slot_id].melee_rune = e.melee_rune;
buffs[e.slot_id].magic_rune = e.magic_rune;
buffs[e.slot_id].persistant_buff = e.persistent ? true : false;
buffs[e.slot_id].persistent_buff = e.persistent ? true : false;
buffs[e.slot_id].dot_rune = e.dot_rune;
buffs[e.slot_id].caston_x = e.caston_x;
buffs[e.slot_id].caston_y = e.caston_y;
@@ -3030,7 +3036,7 @@ void ZoneDatabase::LoadBuffs(Client *client)
}
if (IsEffectInSpell(buffs[slot_id].spellid, SpellEffect::Illusion)) {
if (buffs[slot_id].persistant_buff) {
if (buffs[slot_id].persistent_buff) {
break;
}
@@ -3139,14 +3145,25 @@ void ZoneDatabase::SavePetInfo(Client *client)
continue;
}
pet_buff.char_id = client->CharacterID();
pet_buff.pet = pet_info_type;
pet_buff.slot = slot_id;
pet_buff.spell_id = p->Buffs[slot_id].spellid;
pet_buff.caster_level = p->Buffs[slot_id].level;
pet_buff.ticsremaining = p->Buffs[slot_id].duration;
pet_buff.counters = p->Buffs[slot_id].counters;
pet_buff.instrument_mod = p->Buffs[slot_id].bard_modifier;
pet_buff.character_id = client->CharacterID();
pet_buff.pet = pet_info_type;
pet_buff.slot_id = slot_id;
pet_buff.spell_id = p->Buffs[slot_id].spellid;
pet_buff.caster_level = p->Buffs[slot_id].casterlevel;
pet_buff.caster_name = p->Buffs[slot_id].caster_name;
pet_buff.ticsremaining = p->Buffs[slot_id].ticsremaining;
pet_buff.initialduration = p->Buffs[slot_id].initialduration;
pet_buff.counters = p->Buffs[slot_id].counters;
pet_buff.numhits = p->Buffs[slot_id].hit_number;
pet_buff.melee_rune = p->Buffs[slot_id].melee_rune;
pet_buff.magic_rune = p->Buffs[slot_id].magic_rune;
pet_buff.persistent = p->Buffs[slot_id].persistent_buff;
pet_buff.dot_rune = p->Buffs[slot_id].dot_rune;
pet_buff.caston_x = p->Buffs[slot_id].caston_x;
pet_buff.caston_y = p->Buffs[slot_id].caston_y;
pet_buff.caston_z = p->Buffs[slot_id].caston_z;
pet_buff.ExtraDIChance = p->Buffs[slot_id].ExtraDIChance;
pet_buff.instrument_mod = p->Buffs[slot_id].instrument_mod;
pet_buffs.push_back(pet_buff);
}
@@ -3200,7 +3217,7 @@ void ZoneDatabase::SavePetInfo(Client *client)
CharacterPetBuffsRepository::DeleteWhere(
database,
fmt::format(
"`char_id` = {}",
"`character_id` = {}",
client->CharacterID()
)
);
@@ -3299,7 +3316,7 @@ void ZoneDatabase::LoadPetInfo(Client *client)
const auto& buffs = CharacterPetBuffsRepository::GetWhere(
database,
fmt::format(
"`char_id` = {}",
"`character_id` = {}",
client->CharacterID()
)
);
@@ -3314,7 +3331,7 @@ void ZoneDatabase::LoadPetInfo(Client *client)
continue;
}
if (e.slot >= RuleI(Spells, MaxTotalSlotsPET)) {
if (e.slot_id >= RuleI(Spells, MaxTotalSlotsPET)) {
continue;
}
@@ -3322,13 +3339,39 @@ void ZoneDatabase::LoadPetInfo(Client *client)
continue;
}
p->Buffs[e.slot].spellid = e.spell_id;
p->Buffs[e.slot].level = e.caster_level;
p->Buffs[e.slot].player_id = 0;
p->Buffs[e.slot].effect_type = BuffEffectType::Buff;
p->Buffs[e.slot].duration = e.ticsremaining;
p->Buffs[e.slot].counters = e.counters;
p->Buffs[e.slot].bard_modifier = e.instrument_mod;
Client* c = entity_list.GetClientByName(e.caster_name.c_str());
p->Buffs[e.slot_id].spellid = e.spell_id;
p->Buffs[e.slot_id].casterlevel = e.caster_level;
if (c) {
p->Buffs[e.slot_id].casterid = c->GetID();
p->Buffs[e.slot_id].client = true;
strncpy(p->Buffs[e.slot_id].caster_name, c->GetName(), 64);
} else {
p->Buffs[e.slot_id].casterid = 0;
p->Buffs[e.slot_id].client = false;
strncpy(p->Buffs[e.slot_id].caster_name, "", 64);
}
p->Buffs[e.slot_id].ticsremaining = e.ticsremaining;
p->Buffs[e.slot_id].initialduration = e.initialduration;
p->Buffs[e.slot_id].counters = e.counters;
p->Buffs[e.slot_id].hit_number = e.numhits;
p->Buffs[e.slot_id].melee_rune = e.melee_rune;
p->Buffs[e.slot_id].magic_rune = e.magic_rune;
p->Buffs[e.slot_id].persistent_buff = e.persistent ? true : false;
p->Buffs[e.slot_id].dot_rune = e.dot_rune;
p->Buffs[e.slot_id].caston_x = e.caston_x;
p->Buffs[e.slot_id].caston_y = e.caston_y;
p->Buffs[e.slot_id].caston_z = e.caston_z;
p->Buffs[e.slot_id].ExtraDIChance = e.ExtraDIChance;
p->Buffs[e.slot_id].RootBreakChance = 0;
p->Buffs[e.slot_id].virus_spread_time = 0;
p->Buffs[e.slot_id].UpdateClient = false;
p->Buffs[e.slot_id].instrument_mod = e.instrument_mod;
}
}
+1 -1
View File
@@ -209,7 +209,7 @@ struct PetInfo {
uint32 HP;
uint32 Mana;
float size;
SpellBuff_Struct Buffs[PET_BUFF_COUNT];
Buffs_Struct Buffs[PET_BUFF_COUNT];
uint32 Items[EQ::invslot::EQUIPMENT_COUNT];
char Name[64];
bool taunting;