[Feature] Allow NPCs to cast Sacrifice (#4470)

* [Feature] Teach npcs how to cast sacrifice

* [Feature] Teach npcs how to cast sacrifice

- Remove the hardcoded limit preventing npcs from casting sacrifice. The
  npc will receive as loot an emerald essence as expected.

* Update client.cpp
* Update client_packet.cpp
* Update spell_effects.cpp

* rename Client::SacrificeCaster to Client::sacrifice_caster_id
This commit is contained in:
fuzzlecutter 2024-09-12 14:42:44 -05:00 committed by GitHub
parent 913c5da70f
commit cc0171dfe1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 17 additions and 13 deletions

View File

@ -286,6 +286,7 @@ Client::Client(EQStreamInterface *ieqs) : Mob(
memset(&m_epp, 0, sizeof(m_epp)); memset(&m_epp, 0, sizeof(m_epp));
PendingTranslocate = false; PendingTranslocate = false;
PendingSacrifice = false; PendingSacrifice = false;
sacrifice_caster_id = 0;
controlling_boat_id = 0; controlling_boat_id = 0;
controlled_mob_id = 0; controlled_mob_id = 0;
qGlobals = nullptr; qGlobals = nullptr;
@ -3971,7 +3972,7 @@ void Client::SetEndurance(int32 newEnd)
CheckManaEndUpdate(); CheckManaEndUpdate();
} }
void Client::SacrificeConfirm(Client *caster) void Client::SacrificeConfirm(Mob *caster)
{ {
auto outapp = new EQApplicationPacket(OP_Sacrifice, sizeof(Sacrifice_Struct)); auto outapp = new EQApplicationPacket(OP_Sacrifice, sizeof(Sacrifice_Struct));
Sacrifice_Struct *ss = (Sacrifice_Struct *)outapp->pBuffer; Sacrifice_Struct *ss = (Sacrifice_Struct *)outapp->pBuffer;
@ -3998,14 +3999,14 @@ void Client::SacrificeConfirm(Client *caster)
ss->Confirm = 0; ss->Confirm = 0;
QueuePacket(outapp); QueuePacket(outapp);
safe_delete(outapp); safe_delete(outapp);
// We store the Caster's name, because when the packet comes back, it only has the victim's entityID in it, // We store the Caster's id, because when the packet comes back, it only has the victim's entityID in it,
// not the caster. // not the caster.
SacrificeCaster += caster->GetName(); sacrifice_caster_id = caster->GetID();
PendingSacrifice = true; PendingSacrifice = true;
} }
//Essentially a special case death function //Essentially a special case death function
void Client::Sacrifice(Client *caster) void Client::Sacrifice(Mob *caster)
{ {
if (GetLevel() >= RuleI(Spells, SacrificeMinLevel) && GetLevel() <= RuleI(Spells, SacrificeMaxLevel)) { if (GetLevel() >= RuleI(Spells, SacrificeMinLevel) && GetLevel() <= RuleI(Spells, SacrificeMaxLevel)) {
int exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000); int exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000);
@ -4053,8 +4054,11 @@ void Client::Sacrifice(Client *caster)
} }
Save(); Save();
GoToDeath(); GoToDeath();
if (caster) // I guess it's possible? if (caster && caster->IsClient()) {
caster->SummonItem(RuleI(Spells, SacrificeItemID)); caster->CastToClient()->SummonItem(RuleI(Spells, SacrificeItemID));
} else if (caster && caster->IsNPC()) {
caster->CastToNPC()->AddItem(RuleI(Spells, SacrificeItemID), 1, false);
}
} }
} else { } else {
caster->MessageString(Chat::Red, SAC_TOO_LOW); // This being is not a worthy sacrifice. caster->MessageString(Chat::Red, SAC_TOO_LOW); // This being is not a worthy sacrifice.

View File

@ -762,8 +762,8 @@ public:
void GetRaidAAs(RaidLeadershipAA_Struct *into) const; void GetRaidAAs(RaidLeadershipAA_Struct *into) const;
void ClearGroupAAs(); void ClearGroupAAs();
void UpdateGroupAAs(int32 points, uint32 type); void UpdateGroupAAs(int32 points, uint32 type);
void SacrificeConfirm(Client* caster); void SacrificeConfirm(Mob* caster);
void Sacrifice(Client* caster); void Sacrifice(Mob* caster);
void GoToDeath(); void GoToDeath();
inline const int32 GetInstanceID() const { return zone->GetInstanceID(); } inline const int32 GetInstanceID() const { return zone->GetInstanceID(); }
void SetZoning(bool in) { bZoning = in; } void SetZoning(bool in) { bZoning = in; }
@ -1245,7 +1245,7 @@ public:
bool PendingTranslocate; bool PendingTranslocate;
time_t TranslocateTime; time_t TranslocateTime;
bool PendingSacrifice; bool PendingSacrifice;
std::string SacrificeCaster; uint16 sacrifice_caster_id;
PendingTranslocate_Struct PendingTranslocateData; PendingTranslocate_Struct PendingTranslocateData;
void SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID); void SendOPTranslocateConfirm(Mob *Caster, uint16 SpellID);

View File

@ -13681,11 +13681,11 @@ void Client::Handle_OP_Sacrifice(const EQApplicationPacket *app)
} }
if (ss->Confirm) { if (ss->Confirm) {
Client *Caster = entity_list.GetClientByName(SacrificeCaster.c_str()); Mob *Caster = entity_list.GetMob(sacrifice_caster_id);
if (Caster) Sacrifice(Caster); if (Caster) Sacrifice(Caster);
} }
PendingSacrifice = false; PendingSacrifice = false;
SacrificeCaster.clear(); sacrifice_caster_id = 0;
} }
void Client::Handle_OP_SafeFallSuccess(const EQApplicationPacket *app) // bit of a misnomer, sent whenever safe fall is used (success of fail) void Client::Handle_OP_SafeFallSuccess(const EQApplicationPacket *app) // bit of a misnomer, sent whenever safe fall is used (success of fail)

View File

@ -2202,10 +2202,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
#ifdef SPELL_EFFECT_SPAM #ifdef SPELL_EFFECT_SPAM
snprintf(effect_desc, _EDLEN, "Sacrifice"); snprintf(effect_desc, _EDLEN, "Sacrifice");
#endif #endif
if(!caster || !IsClient() || !caster->IsClient()){ if(!caster || !IsClient() ){
break; break;
} }
CastToClient()->SacrificeConfirm(caster->CastToClient()); CastToClient()->SacrificeConfirm(caster);
break; break;
} }