I was working on some custom spells. I wanted to make a group ward for shaman like in eq2. It throws up a short duration (30 sec) Rune for a certain amount. Whenever the total damage to all group members exceeds the amount of the rune, it wears off. So if only one person is getting beat on, they get the whole rune. Otherwise it is divvy'd up based on who is getting beat on.
I added this to spdat.cpp to help me identity whether or not a buff was a Group ward or not:
Code:
bool IsGroupWard(int16 spell_id)
{
switch(spell_id)
{
case 9827:
case 9830:
case 9831:
case 9833:
case 9834:
return true;
}
return false;
}
I added a function to spells.cpp for Mob::GetBuffSlotFromSpellID. I only added this because I did not see an apparent way to retrieve what slot contains the buff I want. (Note: this will only return the first instance of a buff slot with this spell id)
Code:
sint16 Mob::GetBuffSlotFromSpellID(int16 spell_id) {
uint32 buff_count = GetMaxTotalSlots();
for(int i = 0; i < buff_count; i++) {
if (buffs[i].spellid != SPELL_UNKNOWN) {
if (buffs[i].spellid == spell_id)
return i;
}
}
return -1;
}
I then went into attack.cpp, Mob::ReduceDamage and changed the function that handles runes from
Code:
slot = GetBuffSlotFromType(SE_Rune);
while(slot >= 0)
{
uint32 melee_rune_left = buffs[slot].melee_rune;
if(melee_rune_left >= damage)
{
melee_rune_left -= damage;
damage = -6;
buffs[slot].melee_rune = melee_rune_left;
Message(0, "Your group ward has %i points remaining.", melee_rune_left);
break;
}
else
{
if(melee_rune_left > 0)
damage -= melee_rune_left;
if(!TryFadeEffect(slot))
BuffFadeBySlot(slot);
slot = GetBuffSlotFromType(SE_Rune);
UpdateRuneFlags();
}
}
to this
Code:
slot = GetBuffSlotFromType(SE_Rune);
while(slot >= 0)
{
// This code should apply the damage to the ward of everyone in the group whenever one person in the group takes damage
if(this->IsClient() && IsGroupWard(buffs[slot].spellid) && this->CastToClient()->GetGroup())
{
int groupWardSpellID = buffs[slot].spellid;
Mob* member;
for (int i = 0; i < this->CastToClient()->GetGroup()->GroupCount(); i++)
{
member = this->CastToClient()->GetGroup()->members[i];
if(member == this || !member->FindBuff(groupWardSpellID))
continue;
int _slot = member->GetBuffSlotFromSpellID(groupWardSpellID);
uint32 _melee_rune_left = member->buffs[_slot].melee_rune;
if(_melee_rune_left >= damage)
{
_melee_rune_left -= damage;
member->buffs[_slot].melee_rune = _melee_rune_left;
member->Message(0, "Your group ward has %i points remaining.", _melee_rune_left);
}
else
{
if(!member->TryFadeEffect(_slot))
member->BuffFadeBySlot(_slot);
member->UpdateRuneFlags();
}
}
}
uint32 melee_rune_left = buffs[slot].melee_rune;
if(melee_rune_left >= damage)
{
melee_rune_left -= damage;
damage = -6;
buffs[slot].melee_rune = melee_rune_left;
Message(0, "Your group ward has %i points remaining.", melee_rune_left);
break;
}
else
{
if(melee_rune_left > 0)
damage -= melee_rune_left;
if(!TryFadeEffect(slot))
BuffFadeBySlot(slot);
slot = GetBuffSlotFromType(SE_Rune);
UpdateRuneFlags();
}
}
It iterates through every group member, if they have that ward on them, it decreases their wards by the damage amount, and then moves on and adjusts it for the person actually attacked. To prevent any sort of exploitation, I am now working to add code that will strip the buff off anyone that leaves the shamans group.
Just thought I would share. If anyone knows a better way to handle this, please share.