[Crash] Add Checks for valid pointers or fix existing. (#3164)

This commit is contained in:
Aeadoin 2023-04-01 12:44:00 -04:00 committed by GitHub
parent 4c2271ff69
commit 0d509a7f3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 228 additions and 179 deletions

View File

@ -1436,7 +1436,7 @@ void Mob::ClearFeignMemory() {
while (remembered_feigned_mobid != feign_memory_list.end())
{
Mob* remembered_mob = entity_list.GetMob(*remembered_feigned_mobid);
if (remembered_mob->IsClient() && remembered_mob != nullptr) { //Still in zone
if (remembered_mob && remembered_mob->IsClient()) { //Still in zone
remembered_mob->CastToClient()->RemoveXTarget(this, false);
}
++remembered_feigned_mobid;

View File

@ -2835,8 +2835,9 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
if (emote_id) {
oos->CastToNPC()->DoNPCEmote(EQ::constants::EmoteEventTypes::KilledNPC, emote_id);
}
killer_mob->TrySpellOnKill(killed_level, spell);
if (killer_mob) {
killer_mob->TrySpellOnKill(killed_level, spell);
}
}
}

View File

@ -963,6 +963,10 @@ bool ZoneDatabase::GetAuraEntry(uint16 spell_id, AuraRecord &record)
void Mob::AddAura(Aura *aura, AuraRecord &record)
{
if (!aura) {
return;
}
LogAura(
"aura owner [{}] spawn_id [{}] aura_name [{}]",
GetCleanName(),
@ -971,7 +975,6 @@ void Mob::AddAura(Aura *aura, AuraRecord &record)
);
// this is called only when it's safe
assert(aura != nullptr);
strn0cpy(aura_mgr.auras[aura_mgr.count].name, aura->GetCleanName(), 64);
aura_mgr.auras[aura_mgr.count].spawn_id = aura->GetID();
aura_mgr.auras[aura_mgr.count].aura = aura;
@ -998,6 +1001,10 @@ void Mob::AddAura(Aura *aura, AuraRecord &record)
void Mob::AddTrap(Aura *aura, AuraRecord &record)
{
if (!aura) {
return;
}
LogAura(
"aura owner [{}] spawn_id [{}] aura_name [{}]",
GetCleanName(),
@ -1006,7 +1013,6 @@ void Mob::AddTrap(Aura *aura, AuraRecord &record)
);
// this is called only when it's safe
assert(aura != nullptr);
strn0cpy(trap_mgr.auras[trap_mgr.count].name, aura->GetCleanName(), 64);
trap_mgr.auras[trap_mgr.count].spawn_id = aura->GetID();
trap_mgr.auras[trap_mgr.count].aura = aura;

View File

@ -4637,7 +4637,9 @@ void Bot::Damage(Mob *from, int64 damage, uint16 spell_id, EQ::skills::SkillType
int64 healed = GetActSpellHealing(spell_id, damage);
LogCombatDetail("Applying lifetap heal of [{}] to [{}]", healed, GetCleanName());
HealDamage(healed);
entity_list.FilteredMessageClose(this, true, RuleI(Range, SpellMessages), Chat::Emote, FilterSocials, "%s beams a smile at %s", GetCleanName(), from->GetCleanName() );
if (from) {
entity_list.FilteredMessageClose(this, true, RuleI(Range, SpellMessages), Chat::Emote, FilterSocials, "%s beams a smile at %s", GetCleanName(), from->GetCleanName());
}
}
CommonDamage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special);
@ -8552,22 +8554,25 @@ std::vector<Mob*> Bot::GetApplySpellList(
if (apply_type == ApplySpellType::Raid && IsRaidGrouped()) {
auto* r = GetRaid();
auto group_id = r->GetGroup(GetCleanName());
if (r && EQ::ValueWithin(group_id, 0, (MAX_RAID_GROUPS - 1))) {
for (const auto& m : r->members) {
if (m.is_bot) {
continue;
}
if (m.member && m.member->IsClient() && (!is_raid_group_only || r->GetGroup(m.member) == group_id)) {
l.push_back(m.member);
if (allow_pets && m.member->HasPet()) {
l.push_back(m.member->GetPet());
if (r) {
auto group_id = r->GetGroup(GetCleanName());
if (EQ::ValueWithin(group_id, 0, (MAX_RAID_GROUPS - 1))) {
for (const auto& m: r->members) {
if (m.is_bot) {
continue;
}
if (m.member && m.member->IsClient() &&
(!is_raid_group_only || r->GetGroup(m.member) == group_id)) {
l.push_back(m.member);
const auto& sbl = entity_list.GetBotListByCharacterID(m.member->CharacterID());
for (const auto& b : sbl) {
l.push_back(b);
if (allow_pets && m.member->HasPet()) {
l.push_back(m.member->GetPet());
}
const auto& sbl = entity_list.GetBotListByCharacterID(m.member->CharacterID());
for (const auto& b: sbl) {
l.push_back(b);
}
}
}
}

View File

@ -1888,11 +1888,15 @@ bool Bot::AIHealRotation(Mob* tar, bool useFastHeals) {
std::list<BotSpell> Bot::GetBotSpellsForSpellEffect(Bot* botCaster, int spellEffect) {
std::list<BotSpell> result;
if (!botCaster) {
return result;
}
if (auto bot_owner = botCaster->GetBotOwner(); !bot_owner) {
return result;
}
if (botCaster && botCaster->AI_HasSpells()) {
if (botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells;
for (int i = botSpellList.size() - 1; i >= 0; i--) {
@ -1919,11 +1923,15 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffect(Bot* botCaster, int spellEff
std::list<BotSpell> Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster, int spellEffect, SpellTargetType targetType) {
std::list<BotSpell> result;
if (!botCaster) {
return result;
}
if (auto bot_owner = botCaster->GetBotOwner(); !bot_owner) {
return result;
}
if (botCaster && botCaster->AI_HasSpells()) {
if (botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells;
for (int i = botSpellList.size() - 1; i >= 0; i--) {
@ -1955,11 +1963,15 @@ std::list<BotSpell> Bot::GetBotSpellsForSpellEffectAndTargetType(Bot* botCaster,
std::list<BotSpell> Bot::GetBotSpellsBySpellType(Bot* botCaster, uint32 spellType) {
std::list<BotSpell> result;
if (!botCaster) {
return result;
}
if (auto bot_owner = botCaster->GetBotOwner(); !bot_owner) {
return result;
}
if (botCaster && botCaster->AI_HasSpells()) {
if (botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells;
for (int i = botSpellList.size() - 1; i >= 0; i--) {
@ -2694,21 +2706,22 @@ BotSpell Bot::GetBestBotSpellForResistDebuff(Bot* botCaster, Mob *tar) {
result.SpellIndex = 0;
result.ManaCost = 0;
if (!tar)
if (!tar || !botCaster) {
return result;
}
int level_mod = (tar->GetLevel() - botCaster->GetLevel())* (tar->GetLevel() - botCaster->GetLevel()) / 2;
if (tar->GetLevel() - botCaster->GetLevel() < 0)
{
if (tar->GetLevel() - botCaster->GetLevel() < 0) {
level_mod = -level_mod;
}
bool needsMagicResistDebuff = (tar->GetMR() + level_mod) > 100;
bool needsColdResistDebuff = (tar->GetCR() + level_mod) > 100;
bool needsFireResistDebuff = (tar->GetFR() + level_mod) > 100;
bool needsPoisonResistDebuff = (tar->GetPR() + level_mod) > 100;
bool needsDiseaseResistDebuff = (tar->GetDR() + level_mod) > 100;
if (botCaster && botCaster->AI_HasSpells()) {
if (botCaster->AI_HasSpells()) {
std::vector<BotSpells_Struct> botSpellList = botCaster->AIBot_spells;
for (int i = botSpellList.size() - 1; i >= 0; i--) {

View File

@ -7470,15 +7470,17 @@ const char* Client::GetClassPlural(Client* client) {
void Client::SendWebLink(const char *website)
{
size_t len = strlen(website) + 1;
if(website != 0 && len > 1)
{
auto outapp = new EQApplicationPacket(OP_Weblink, sizeof(Weblink_Struct) + len);
Weblink_Struct *wl = (Weblink_Struct*)outapp->pBuffer;
memcpy(wl->weblink, website, len);
wl->weblink[len] = '\0';
if (website) {
size_t len = strlen(website) + 1;
if (len > 1)
{
auto outapp = new EQApplicationPacket(OP_Weblink, sizeof(Weblink_Struct) + len);
Weblink_Struct* wl = (Weblink_Struct*)outapp->pBuffer;
memcpy(wl->weblink, website, len);
wl->weblink[len] = '\0';
FastQueuePacket(&outapp);
FastQueuePacket(&outapp);
}
}
}
@ -11734,20 +11736,22 @@ std::vector<Mob*> Client::GetApplySpellList(
if (apply_type == ApplySpellType::Raid && IsRaidGrouped()) {
auto* r = GetRaid();
auto group_id = r->GetGroup(this);
if (r && EQ::ValueWithin(group_id, 0, (MAX_RAID_GROUPS - 1))) {
for (const auto& m : r->members) {
if (m.member && m.member->IsClient() && (!is_raid_group_only || r->GetGroup(m.member) == group_id)) {
l.push_back(m.member);
if (r) {
auto group_id = r->GetGroup(this);
if (EQ::ValueWithin(group_id, 0, (MAX_RAID_GROUPS - 1))) {
for (const auto& m : r->members) {
if (m.member && m.member->IsClient() && (!is_raid_group_only || r->GetGroup(m.member) == group_id)) {
l.push_back(m.member);
if (allow_pets && m.member->HasPet()) {
l.push_back(m.member->GetPet());
}
if (allow_pets && m.member->HasPet()) {
l.push_back(m.member->GetPet());
}
if (allow_bots) {
const auto& sbl = entity_list.GetBotListByCharacterID(m.member->CharacterID());
for (const auto& b : sbl) {
l.push_back(b);
if (allow_bots) {
const auto& sbl = entity_list.GetBotListByCharacterID(m.member->CharacterID());
for (const auto& b : sbl) {
l.push_back(b);
}
}
}
}

View File

@ -11775,13 +11775,13 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket* app)
Bot* player_to_invite = nullptr;
if (RuleB(Bots, Enabled) && entity_list.GetBotByBotName(raid_command_packet->player_name)) {
Bot* player_to_invite = entity_list.GetBotByBotName(raid_command_packet->player_name);
Group* player_to_invite_group = player_to_invite->GetGroup();
if (!player_to_invite) {
break;
}
Bot* player_to_invite = entity_list.GetBotByBotName(raid_command_packet->player_name);
Group* player_to_invite_group = player_to_invite->GetGroup();
if (player_to_invite_group && player_to_invite_group->IsGroupMember(this)) {
MessageString(Chat::Red, ALREADY_IN_PARTY);
break;

View File

@ -1145,6 +1145,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app)
const auto* item = inst->GetItem();
if (
item &&
RuleB(Character, RestrictSpellScribing) &&
!item->IsEquipable(GetRace(), GetClass())
) {

View File

@ -520,8 +520,6 @@ bool PerlembParser::SpellHasQuestSub(uint32 spell_id, QuestEventID evt)
bool PerlembParser::ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt)
{
std::stringstream package_name;
package_name << "qst_item_" << itm->GetID();
if (!perl) {
return false;
@ -535,6 +533,9 @@ bool PerlembParser::ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt)
return false;
}
std::stringstream package_name;
package_name << "qst_item_" << itm->GetID();
const char *subname = QuestEventSubroutines[evt];
auto iter = item_quest_status_.find(itm->GetID());

View File

@ -298,7 +298,7 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
}
//put existing group member(s) into the new member's list
if(InZone && newmember->IsClient())
if(InZone && newmember && newmember->IsClient())
{
if(IsLeader(members[i]))
{
@ -307,13 +307,13 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte
else
{
strcpy(newmember->CastToClient()->GetPP().groupMembers[x], members[i]->GetCleanName());
x++;
++x;
}
}
}
}
if(InZone)
if(InZone && newmember)
{
//put new member in his own list.
newmember->SetGrouped(true);
@ -2499,4 +2499,4 @@ bool Group::IsLeader(const char* name) {
}
return false;
}
}

View File

@ -483,20 +483,22 @@ Mob *HateList::GetEntWithMostHateOnList(Mob *center, Mob *skip, bool skip_mezzed
while (iterator != list.end())
{
struct_HateList *cur = (*iterator);
if (cur->entity_on_hatelist == skip) {
++iterator;
continue;
}
if (cur) {
if (cur->entity_on_hatelist == skip) {
++iterator;
continue;
}
if (skip_mezzed && cur->entity_on_hatelist->IsMezzed()) {
++iterator;
continue;
}
if (skip_mezzed && cur->entity_on_hatelist->IsMezzed()) {
++iterator;
continue;
}
if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy))
{
top_hate = cur->entity_on_hatelist;
hate = cur->stored_hate_amount;
if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy))
{
top_hate = cur->entity_on_hatelist;
hate = cur->stored_hate_amount;
}
}
++iterator;
}
@ -516,24 +518,27 @@ Mob *HateList::GetEntWithMostHateOnList(bool skip_mezzed){
while (iterator != list.end())
{
struct_HateList *cur = (*iterator);
LogHateDetail(
"Looping GetEntWithMostHateOnList1 [{}] cur [{}] hate [{}] calc [{}]",
cur->entity_on_hatelist->GetMobDescription(),
cur->stored_hate_amount,
hate,
(cur->stored_hate_amount > hate)
);
if (cur && cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate))
{
if (cur) {
LogHateDetail(
"Looping GetEntWithMostHateOnList2 [{}]",
cur->entity_on_hatelist->GetMobDescription()
"Looping GetEntWithMostHateOnList1 [{}] cur [{}] hate [{}] calc [{}]",
cur->entity_on_hatelist->GetMobDescription(),
cur->stored_hate_amount,
hate,
(cur->stored_hate_amount > hate)
);
if (!skip_mezzed || !cur->entity_on_hatelist->IsMezzed()) {
top = cur->entity_on_hatelist;
hate = cur->stored_hate_amount;
if (cur->entity_on_hatelist != nullptr && (cur->stored_hate_amount > hate))
{
LogHateDetail(
"Looping GetEntWithMostHateOnList2 [{}]",
cur->entity_on_hatelist->GetMobDescription()
);
if (!skip_mezzed || !cur->entity_on_hatelist->IsMezzed()) {
top = cur->entity_on_hatelist;
hate = cur->stored_hate_amount;
}
}
}
++iterator;

View File

@ -717,12 +717,15 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
EQ::ItemInstance* inst = database.CreateItem(item, charges);
auto timestamps = database.GetItemRecastTimestamps(CharacterID());
const auto* d = inst->GetItem();
if (d->RecastDelay) {
if (d->RecastType != RECAST_TYPE_UNLINKED_ITEM) {
inst->SetRecastTimestamp(timestamps.count(d->RecastType) ? timestamps.at(d->RecastType) : 0);
} else {
inst->SetRecastTimestamp(timestamps.count(d->ID) ? timestamps.at(d->ID) : 0);
if (inst) {
const auto* d = inst->GetItem();
if (d->RecastDelay) {
if (d->RecastType != RECAST_TYPE_UNLINKED_ITEM) {
inst->SetRecastTimestamp(timestamps.count(d->RecastType) ? timestamps.at(d->RecastType) : 0);
}
else {
inst->SetRecastTimestamp(timestamps.count(d->ID) ? timestamps.at(d->ID) : 0);
}
}
}
@ -2043,8 +2046,8 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
}
if ((srcbagid && srcbag->GetItem()->BagType == EQ::item::BagTypeTradersSatchel) ||
(dstbagid && dstbag->GetItem()->BagType == EQ::item::BagTypeTradersSatchel) ||
(srcitemid && src_inst->GetItem()->BagType == EQ::item::BagTypeTradersSatchel) ||
(dstitemid && dst_inst->GetItem()->BagType == EQ::item::BagTypeTradersSatchel)) {
(srcitemid && src_inst && src_inst->GetItem()->BagType == EQ::item::BagTypeTradersSatchel) ||
(dstitemid && dst_inst && dst_inst->GetItem()->BagType == EQ::item::BagTypeTradersSatchel)) {
Trader_EndTrader();
Message(Chat::Red,"You cannot move your Trader Satchels, or items inside them, while Trading.");
}

View File

@ -3261,6 +3261,10 @@ MercSpell Merc::GetBestMercSpellForTargetedAENuke(Merc* caster, Mob* tar) {
result.proc_chance = 0;
result.time_cancast = 0;
if (!caster) {
return result;
}
switch(caster->GetStance())
{
case EQ::constants::stanceBurnAE:
@ -3272,28 +3276,26 @@ MercSpell Merc::GetBestMercSpellForTargetedAENuke(Merc* caster, Mob* tar) {
break;
}
if(caster) {
std::list<MercSpell> mercSpellList = GetMercSpellsBySpellType(caster, SpellType_Nuke);
std::list<MercSpell> mercSpellList = GetMercSpellsBySpellType(caster, SpellType_Nuke);
for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end();
++mercSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order
if(IsAENukeSpell(mercSpellListItr->spellid) && !IsAERainNukeSpell(mercSpellListItr->spellid)
&& !IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, tar, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck && zone->random.Roll(castChance)) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
result.slot = mercSpellListItr->slot;
result.proc_chance = mercSpellListItr->proc_chance;
result.time_cancast = mercSpellListItr->time_cancast;
}
for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end();
++mercSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order
if(IsAENukeSpell(mercSpellListItr->spellid) && !IsAERainNukeSpell(mercSpellListItr->spellid)
&& !IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, tar, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck && zone->random.Roll(castChance)) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
result.slot = mercSpellListItr->slot;
result.proc_chance = mercSpellListItr->proc_chance;
result.time_cancast = mercSpellListItr->time_cancast;
}
}
break;
}
break;
}
}
@ -3313,6 +3315,10 @@ MercSpell Merc::GetBestMercSpellForPBAENuke(Merc* caster, Mob* tar) {
result.proc_chance = 0;
result.time_cancast = 0;
if (!caster) {
return result;
}
switch(caster->GetStance())
{
case EQ::constants::stanceBurnAE:
@ -3324,27 +3330,25 @@ MercSpell Merc::GetBestMercSpellForPBAENuke(Merc* caster, Mob* tar) {
break;
}
if(caster) {
std::list<MercSpell> mercSpellList = GetMercSpellsBySpellType(caster, SpellType_Nuke);
std::list<MercSpell> mercSpellList = GetMercSpellsBySpellType(caster, SpellType_Nuke);
for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end();
++mercSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order
if(IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, caster, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck && zone->random.Roll(castChance)) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
result.slot = mercSpellListItr->slot;
result.proc_chance = mercSpellListItr->proc_chance;
result.time_cancast = mercSpellListItr->time_cancast;
}
for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end();
++mercSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order
if(IsPBAENukeSpell(mercSpellListItr->spellid) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, caster, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck && zone->random.Roll(castChance)) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
result.slot = mercSpellListItr->slot;
result.proc_chance = mercSpellListItr->proc_chance;
result.time_cancast = mercSpellListItr->time_cancast;
}
break;
}
break;
}
}
@ -3364,6 +3368,10 @@ MercSpell Merc::GetBestMercSpellForAERainNuke(Merc* caster, Mob* tar) {
result.proc_chance = 0;
result.time_cancast = 0;
if (!caster) {
return result;
}
switch(caster->GetStance())
{
case EQ::constants::stanceBurnAE:
@ -3375,27 +3383,25 @@ MercSpell Merc::GetBestMercSpellForAERainNuke(Merc* caster, Mob* tar) {
break;
}
if(caster) {
std::list<MercSpell> mercSpellList = GetMercSpellsBySpellType(caster, SpellType_Nuke);
std::list<MercSpell> mercSpellList = GetMercSpellsBySpellType(caster, SpellType_Nuke);
for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end();
++mercSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order
if(IsAERainNukeSpell(mercSpellListItr->spellid) && zone->random.Roll(castChance) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, tar, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
result.slot = mercSpellListItr->slot;
result.proc_chance = mercSpellListItr->proc_chance;
result.time_cancast = mercSpellListItr->time_cancast;
}
for (auto mercSpellListItr = mercSpellList.begin(); mercSpellListItr != mercSpellList.end();
++mercSpellListItr) {
// Assuming all the spells have been loaded into this list by level and in descending order
if(IsAERainNukeSpell(mercSpellListItr->spellid) && zone->random.Roll(castChance) && CheckSpellRecastTimers(caster, mercSpellListItr->spellid)) {
uint8 numTargets = 0;
if(CheckAENuke(caster, tar, mercSpellListItr->spellid, numTargets)) {
if(numTargets >= numTargetsCheck) {
result.spellid = mercSpellListItr->spellid;
result.stance = mercSpellListItr->stance;
result.type = mercSpellListItr->type;
result.slot = mercSpellListItr->slot;
result.proc_chance = mercSpellListItr->proc_chance;
result.time_cancast = mercSpellListItr->time_cancast;
}
break;
}
break;
}
}
@ -4302,7 +4308,12 @@ Merc* Merc::LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id,
if(merc_template)
{
//TODO: Maybe add a way of updating client merc stats in a seperate function? like, for example, on leveling up.
const NPCType* npc_type_to_copy = content_db.GetMercType(merc_template->MercNPCID, merc_template->RaceID, c->GetLevel());
const NPCType* npc_type_to_copy = nullptr;
if (c) {
const NPCType* npc_type_to_copy = content_db.GetMercType(merc_template->MercNPCID, merc_template->RaceID, c->GetLevel());
}
if(npc_type_to_copy != nullptr)
{
//This is actually a very terrible method of assigning stats, and should be changed at some point. See the comment in merc's deconstructor.

View File

@ -5109,6 +5109,10 @@ void Mob::TarGlobal(const char *varname, const char *value, const char *duration
void Mob::DelGlobal(const char *varname) {
if (!zone) {
return;
}
int qgZoneid=zone->GetZoneID();
int qgCharid=0;
int qgNpcid=0;
@ -5129,22 +5133,19 @@ void Mob::DelGlobal(const char *varname) {
database.QueryDatabase(query);
if(zone)
{
auto pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct));
ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct*)pack->pBuffer;
auto pack = new ServerPacket(ServerOP_QGlobalDelete, sizeof(ServerQGlobalDelete_Struct));
ServerQGlobalDelete_Struct *qgu = (ServerQGlobalDelete_Struct*)pack->pBuffer;
qgu->npc_id = qgNpcid;
qgu->char_id = qgCharid;
qgu->zone_id = qgZoneid;
strcpy(qgu->name, varname);
qgu->npc_id = qgNpcid;
qgu->char_id = qgCharid;
qgu->zone_id = qgZoneid;
strcpy(qgu->name, varname);
entity_list.DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id);
zone->DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id);
entity_list.DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id);
zone->DeleteQGlobal(std::string((char*)qgu->name), qgu->npc_id, qgu->char_id, qgu->zone_id);
worldserver.SendPacket(pack);
safe_delete(pack);
}
worldserver.SendPacket(pack);
safe_delete(pack);
}
// Inserts global variable into quest_globals table

View File

@ -445,7 +445,7 @@ Pet::Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 po
GiveNPCTypeData(type_data);
typeofpet = type;
petpower = power;
SetOwnerID(owner->GetID());
SetOwnerID(owner ? owner->GetID() : 0);
SetPetSpellID(spell_id);
// All pets start at false on newer clients. The client

View File

@ -150,7 +150,7 @@ bool Spawn2::Process() {
//grab our spawn group
SpawnGroup *spawn_group = zone->spawn_group_list.GetSpawnGroup(spawngroup_id_);
if (NPCPointerValid() && (spawn_group->despawn == 0 || condition_id != 0)) {
if (NPCPointerValid() && (spawn_group && spawn_group->despawn == 0 || condition_id != 0)) {
return true;
}

View File

@ -147,9 +147,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
if (spells[spell_id].hit_number > 0) {
int numhit = spells[spell_id].hit_number;
numhit += numhit * caster->GetFocusEffect(focusFcLimitUse, spell_id) / 100;
numhit += caster->GetFocusEffect(focusIncreaseNumHits, spell_id);
if (caster) {
numhit += numhit * caster->GetFocusEffect(focusFcLimitUse, spell_id) / 100;
numhit += caster->GetFocusEffect(focusIncreaseNumHits, spell_id);
}
buffs[buffslot].hit_number = numhit;
}
@ -262,7 +263,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
// SE_CurrentHP is calculated at first tick if its a dot/buff
if (buffslot >= 0) {
//This is here so dots with hit counters tic down on initial cast.
if (effect_value < 0) {
if (caster && effect_value < 0) {
caster->GetActDoTDamage(spell_id, effect_value, this, false);
}
break;
@ -1766,7 +1767,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
gid = r->GetGroup(caster->GetName());
if(gid < 11)
{
if(r->GetGroup(TargetClient->GetName()) != gid) {
if (TargetClient && r->GetGroup(TargetClient->GetName()) != gid) {
Message(Chat::Red, "Your target must be a group member for this spell.");
break;
}
@ -1817,7 +1818,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
{
if (IsClient()) {
Client* client_target = CastToClient();
if (client_target->IsGrouped()) {
if (client_target && client_target->IsGrouped()) {
Group* group = client_target->GetGroup();
if (!group->IsGroupMember(caster)) {
if (caster != this) {
@ -1830,7 +1831,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
Raid *raid = caster->GetRaid();
uint32 group_id = raid->GetGroup(caster->GetName());
if (group_id > 0 && group_id < MAX_RAID_GROUPS) {
if (raid->GetGroup(client_target->GetName()) != group_id) {
if (client_target && raid->GetGroup(client_target->GetName()) != group_id) {
caster->MessageString(Chat::Red, SUMMON_ONLY_GROUP_CORPSE);
break;
}
@ -2963,10 +2964,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
if (caster && !caster->IsClient())
break;
if (zone->random.Roll(spells[spell_id].base_value[i])) {
if (caster && zone->random.Roll(spells[spell_id].base_value[i])) {
uint32 best_spell_id = caster->CastToClient()->GetHighestScribedSpellinSpellGroup(spells[spell_id].limit_value[i]);
if (caster && IsValidSpell(best_spell_id))
if (IsValidSpell(best_spell_id))
caster->SpellFinished(best_spell_id, this, EQ::spells::CastingSlot::Item, 0, -1, spells[best_spell_id].resist_difficulty);
}
break;

View File

@ -209,8 +209,7 @@ void Trap::Trigger(Mob* trigger)
{
entity_list.MessageClose(trigger,false,100,13,"%s",message.c_str());
}
if(trigger->IsClient())
{
if (trigger && trigger->IsClient()) {
auto outapp = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct));
CombatDamage_Struct* a = (CombatDamage_Struct*)outapp->pBuffer;
int64 dmg = zone->random.Int(effectvalue, effectvalue2);
@ -226,8 +225,7 @@ void Trap::Trigger(Mob* trigger)
}
}
if (trigger && trigger->IsClient())
{
if (trigger && trigger->IsClient()) {
trigger->CastToClient()->trapid = trap_id;
charid = trigger->CastToClient()->CharacterID();
}

View File

@ -2027,13 +2027,12 @@ ZonePoint* Zone::GetClosestZonePoint(const glm::vec3& location, uint32 to, Clien
// if we have a water map and it says we're in a zoneline, lets assume it's just a really big zone line
// this shouldn't open up any exploits since those situations are detected later on
if ((zone->HasWaterMap() && !zone->watermap->InZoneLine(glm::vec3(client->GetPosition()))) || (!zone->HasWaterMap() && closest_dist > 400.0f && closest_dist < max_distance2))
if ((client && zone->HasWaterMap() && !zone->watermap->InZoneLine(glm::vec3(client->GetPosition()))) || (!zone->HasWaterMap() && closest_dist > 400.0f && closest_dist < max_distance2))
{
if (client) {
if (!client->cheat_manager.GetExemptStatus(Port)) {
client->cheat_manager.CheatDetected(MQZoneUnknownDest, location);
}
if (!client->cheat_manager.GetExemptStatus(Port)) {
client->cheat_manager.CheatDetected(MQZoneUnknownDest, location);
}
LogInfo("WARNING: Closest zone point for zone id [{}] is [{}], you might need to update your zone_points table if you dont arrive at the right spot", to, closest_dist);
LogInfo("<Real Zone Points>. [{}]", to_string(location).c_str());
}