mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-16 01:01:30 +00:00
[Crash] Add Checks for valid pointers or fix existing. (#3164)
This commit is contained in:
parent
4c2271ff69
commit
0d509a7f3a
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
35
zone/bot.cpp
35
zone/bot.cpp
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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--) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -1145,6 +1145,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app)
|
||||
const auto* item = inst->GetItem();
|
||||
|
||||
if (
|
||||
item &&
|
||||
RuleB(Character, RestrictSpellScribing) &&
|
||||
!item->IsEquipable(GetRace(), GetClass())
|
||||
) {
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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.");
|
||||
}
|
||||
|
||||
123
zone/merc.cpp
123
zone/merc.cpp
@ -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.
|
||||
|
||||
27
zone/mob.cpp
27
zone/mob.cpp
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user