Skip to content

Commit

Permalink
[11299] Handle aura durations in SpellAuraHolder
Browse files Browse the repository at this point in the history
- Unit::CalculateSpellDuration split into two functions
    - CalculateSpellDuration taking into account combo points and caster-side spell mods
    - Unit::CalculateAuraDuration taking into account target-side spell mods
- Diminishing is now applied before duration reduction mods
- Implement saving per-effect periodic timers to DB (required for auras affected by haste)
  • Loading branch information
zergtmn committed Mar 30, 2011
1 parent a79ca96 commit 09090ac
Show file tree
Hide file tree
Showing 19 changed files with 387 additions and 378 deletions.
36 changes: 17 additions & 19 deletions sql/characters.sql
Expand Up @@ -21,7 +21,7 @@

DROP TABLE IF EXISTS `character_db_version`;
CREATE TABLE `character_db_version` (
`required_11117_02_characters_world` bit(1) default NULL
`required_11299_02_characters_pet_aura` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB';

--
Expand Down Expand Up @@ -372,18 +372,17 @@ CREATE TABLE `character_aura` (
`caster_guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Full Global Unique Identifier',
`item_guid` int(11) unsigned NOT NULL default '0',
`spell` int(11) unsigned NOT NULL default '0',
`stackcount` int(11) NOT NULL default '1',
`remaincharges` int(11) NOT NULL default '0',
`stackcount` INT(11) UNSIGNED NOT NULL DEFAULT '1',
`remaincharges` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`basepoints0` INT(11) NOT NULL DEFAULT '0',
`basepoints1` INT(11) NOT NULL DEFAULT '0',
`basepoints2` INT(11) NOT NULL DEFAULT '0',
`maxduration0` INT(11) NOT NULL DEFAULT '0',
`maxduration1` INT(11) NOT NULL DEFAULT '0',
`maxduration2` INT(11) NOT NULL DEFAULT '0',
`remaintime0` INT(11) NOT NULL DEFAULT '0',
`remaintime1` INT(11) NOT NULL DEFAULT '0',
`remaintime2` INT(11) NOT NULL DEFAULT '0',
`effIndexMask` INT(11) NOT NULL DEFAULT '0',
`periodictime0` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`periodictime1` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`periodictime2` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`maxduration` INT(11) NOT NULL DEFAULT '0',
`remaintime` INT(11) NOT NULL DEFAULT '0',
`effIndexMask` INT(11) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`guid`,`caster_guid`,`item_guid`,`spell`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System';

Expand Down Expand Up @@ -1565,18 +1564,17 @@ CREATE TABLE `pet_aura` (
`caster_guid` bigint(20) unsigned NOT NULL default '0' COMMENT 'Full Global Unique Identifier',
`item_guid` int(11) unsigned NOT NULL default '0',
`spell` int(11) unsigned NOT NULL default '0',
`stackcount` int(11) NOT NULL default '1',
`remaincharges` int(11) NOT NULL default '0',
`stackcount` INT(11) UNSIGNED NOT NULL DEFAULT '1',
`remaincharges` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`basepoints0` INT(11) NOT NULL DEFAULT '0',
`basepoints1` INT(11) NOT NULL DEFAULT '0',
`basepoints2` INT(11) NOT NULL DEFAULT '0',
`maxduration0` INT(11) NOT NULL DEFAULT '0',
`maxduration1` INT(11) NOT NULL DEFAULT '0',
`maxduration2` INT(11) NOT NULL DEFAULT '0',
`remaintime0` INT(11) NOT NULL DEFAULT '0',
`remaintime1` INT(11) NOT NULL DEFAULT '0',
`remaintime2` INT(11) NOT NULL DEFAULT '0',
`effIndexMask` INT(11) NOT NULL DEFAULT '0',
`periodictime0` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`periodictime1` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`periodictime2` INT(11) UNSIGNED NOT NULL DEFAULT '0',
`maxduration` INT(11) NOT NULL DEFAULT '0',
`remaintime` INT(11) NOT NULL DEFAULT '0',
`effIndexMask` INT(11) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`guid`,`caster_guid`,`item_guid`,`spell`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Pet System';

Expand Down
16 changes: 16 additions & 0 deletions sql/updates/11299_01_characters_character_aura.sql
@@ -0,0 +1,16 @@
ALTER TABLE character_db_version CHANGE COLUMN required_11117_02_characters_world required_11299_01_characters_character_aura bit;

TRUNCATE TABLE character_aura;
ALTER TABLE character_aura
CHANGE COLUMN `maxduration0` `maxduration` INT(11) NOT NULL DEFAULT '0',
CHANGE COLUMN `remaintime0` `remaintime` INT(11) NOT NULL DEFAULT '0',
ADD COLUMN `periodictime0` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `basepoints2`,
ADD COLUMN `periodictime1` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `periodictime0`,
ADD COLUMN `periodictime2` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `periodictime1`,
DROP COLUMN `maxduration1`,
DROP COLUMN `maxduration2`,
DROP COLUMN `remaintime1`,
DROP COLUMN `remaintime2`,
CHANGE COLUMN `stackcount` `stackcount` INT(11) UNSIGNED NOT NULL DEFAULT '1',
CHANGE COLUMN `remaincharges` `remaincharges` INT(11) UNSIGNED NOT NULL DEFAULT '0',
CHANGE COLUMN `effIndexMask` `effIndexMask` INT(11) UNSIGNED NOT NULL DEFAULT '0';
16 changes: 16 additions & 0 deletions sql/updates/11299_02_characters_pet_aura.sql
@@ -0,0 +1,16 @@
ALTER TABLE character_db_version CHANGE COLUMN required_11299_01_characters_character_aura required_11299_02_characters_pet_aura bit;

TRUNCATE TABLE pet_aura;
ALTER TABLE pet_aura
CHANGE COLUMN `maxduration0` `maxduration` INT(11) NOT NULL DEFAULT '0',
CHANGE COLUMN `remaintime0` `remaintime` INT(11) NOT NULL DEFAULT '0',
ADD COLUMN `periodictime0` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `basepoints2`,
ADD COLUMN `periodictime1` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `periodictime0`,
ADD COLUMN `periodictime2` INT(11) UNSIGNED NOT NULL DEFAULT '0' AFTER `periodictime1`,
DROP COLUMN `maxduration1`,
DROP COLUMN `maxduration2`,
DROP COLUMN `remaintime1`,
DROP COLUMN `remaintime2`,
CHANGE COLUMN `stackcount` `stackcount` INT(11) UNSIGNED NOT NULL DEFAULT '1',
CHANGE COLUMN `remaincharges` `remaincharges` INT(11) UNSIGNED NOT NULL DEFAULT '0',
CHANGE COLUMN `effIndexMask` `effIndexMask` INT(11) UNSIGNED NOT NULL DEFAULT '0';
2 changes: 1 addition & 1 deletion src/game/CharacterHandler.cpp
Expand Up @@ -74,7 +74,7 @@ bool LoginQueryHolder::Initialize()
"health, power1, power2, power3, power4, power5, power6, power7, specCount, activeSpec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars FROM characters WHERE guid = '%u'", m_guid.GetCounter());
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT groupId FROM group_member WHERE memberGuid ='%u'", m_guid.GetCounter());
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", m_guid.GetCounter());
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,item_guid,spell,stackcount,remaincharges,basepoints0,basepoints1,basepoints2,maxduration0,maxduration1,maxduration2,remaintime0,remaintime1,remaintime2,effIndexMask FROM character_aura WHERE guid = '%u'", m_guid.GetCounter());
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,item_guid,spell,stackcount,remaincharges,basepoints0,basepoints1,basepoints2,periodictime0,periodictime1,periodictime2,maxduration,remaintime,effIndexMask FROM character_aura WHERE guid = '%u'", m_guid.GetCounter());
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'", m_guid.GetCounter());
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS, "SELECT quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4 FROM character_queststatus WHERE guid = '%u'", m_guid.GetCounter());
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,"SELECT quest FROM character_queststatus_daily WHERE guid = '%u'", m_guid.GetCounter());
Expand Down
16 changes: 6 additions & 10 deletions src/game/GridNotifiersImpl.h
Expand Up @@ -164,16 +164,7 @@ inline void MaNGOS::DynamicObjectUpdater::VisitHelper(Unit* target)

if (holder)
{
if (Aura* aura = holder->GetAuraByEffectIndex(eff_index))
{
// already exists, refresh duration
if (aura->GetAuraDuration() >=0 && uint32(aura->GetAuraDuration()) < i_dynobject.GetDuration())
{
aura->SetAuraDuration(i_dynobject.GetDuration());
holder->SendAuraUpdate(false);
}
}
else
if (!holder->GetAuraByEffectIndex(eff_index))
{
PersistentAreaAura* Aur = new PersistentAreaAura(spellInfo, eff_index, NULL, holder, target, i_dynobject.GetCaster());
holder->AddAura(Aur, eff_index);
Expand All @@ -182,6 +173,11 @@ inline void MaNGOS::DynamicObjectUpdater::VisitHelper(Unit* target)
Aur->ApplyModifier(true,true);
holder->SetInUse(false);
}
else if (holder->GetAuraDuration() >= 0 && uint32(holder->GetAuraDuration()) < i_dynobject.GetDuration())
{
holder->SetAuraDuration(i_dynobject.GetDuration());
holder->SendAuraUpdate(false);
}
}
else
{
Expand Down
71 changes: 34 additions & 37 deletions src/game/Pet.cpp
Expand Up @@ -1243,7 +1243,7 @@ void Pet::_LoadAuras(uint32 timediff)
{
RemoveAllAuras();

QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,item_guid,spell,stackcount,remaincharges,basepoints0,basepoints1,basepoints2,maxduration0,maxduration1,maxduration2,remaintime0,remaintime1,remaintime2,effIndexMask FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,item_guid,spell,stackcount,remaincharges,basepoints0,basepoints1,basepoints2,periodictime0,periodictime1,periodictime2,maxduration,remaintime,effIndexMask FROM pet_aura WHERE guid = '%u'", m_charmInfo->GetPetNumber());

if(result)
{
Expand All @@ -1255,16 +1255,18 @@ void Pet::_LoadAuras(uint32 timediff)
uint32 spellid = fields[2].GetUInt32();
uint32 stackcount = fields[3].GetUInt32();
uint32 remaincharges = fields[4].GetUInt32();
int32 damage[MAX_EFFECT_INDEX];
int32 maxduration[MAX_EFFECT_INDEX];
int32 remaintime[MAX_EFFECT_INDEX];
int32 damage[MAX_EFFECT_INDEX];
uint32 periodicTime[MAX_EFFECT_INDEX];

for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
damage[i] = fields[i+5].GetInt32();
maxduration[i] = fields[i+8].GetInt32();
remaintime[i] = fields[i+11].GetInt32();
periodicTime[i] = fields[i+8].GetUInt32();
}
uint32 effIndexMask = fields[14].GetUInt32();

int32 maxduration = fields[11].GetInt32();
int32 remaintime = fields[12].GetInt32();
uint32 effIndexMask = fields[13].GetUInt32();

SpellEntry const* spellproto = sSpellStore.LookupEntry(spellid);
if (!spellproto)
Expand All @@ -1277,6 +1279,14 @@ void Pet::_LoadAuras(uint32 timediff)
if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto))
continue;

if (remaintime != -1 && !IsPositiveSpell(spellproto))
{
if (remaintime/IN_MILLISECONDS <= int32(timediff))
continue;

remaintime -= timediff*IN_MILLISECONDS;
}

// prevent wrong values of remaincharges
uint32 procCharges = spellproto->procCharges;
if (procCharges)
Expand All @@ -1294,34 +1304,24 @@ void Pet::_LoadAuras(uint32 timediff)
else if (!stackcount)
stackcount = 1;


SpellAuraHolder *holder = CreateSpellAuraHolder(spellproto, this, NULL);
holder->SetLoadedState(caster_guid, ObjectGuid(HIGHGUID_ITEM, item_lowguid), stackcount, remaincharges, maxduration, remaintime);

for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
if ((effIndexMask & (1 << i)) == 0)
continue;

if (remaintime[i] != -1 && !IsPositiveEffect(spellproto, SpellEffectIndex(i)))
{
if (remaintime[i]/IN_MILLISECONDS <= int32(timediff))
continue;

remaintime[i] -= timediff*IN_MILLISECONDS;
}

Aura* aura = CreateAura(spellproto, SpellEffectIndex(i), NULL, holder, this);
if (!damage[i])
damage[i] = aura->GetModifier()->m_amount;

aura->SetLoadedState(damage[i], maxduration[i], remaintime[i]);
aura->SetLoadedState(damage[i], periodicTime[i]);
holder->AddAura(aura, SpellEffectIndex(i));
}

if (!holder->IsEmptyHolder())
{
holder->SetLoadedState(caster_guid, ObjectGuid(HIGHGUID_ITEM, item_lowguid), stackcount, remaincharges);
AddSpellAuraHolder(holder);
}
else
delete holder;
}
Expand All @@ -1344,6 +1344,10 @@ void Pet::_SaveAuras()
if (auraHolders.empty())
return;

stmt = CharacterDatabase.CreateStatement(insAuras, "INSERT INTO pet_aura (guid, caster_guid, item_guid, spell, stackcount, remaincharges, "
"basepoints0, basepoints1, basepoints2, periodictime0, periodictime1, periodictime2, maxduration, remaintime, effIndexMask) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

for(SpellAuraHolderMap::const_iterator itr = auraHolders.begin(); itr != auraHolders.end(); ++itr)
{
SpellAuraHolder *holder = itr->second;
Expand All @@ -1365,16 +1369,14 @@ void Pet::_SaveAuras()
//do not save single target holders (unless they were cast by the player)
if (save && !holder->IsPassive() && !IsChanneledSpell(holder->GetSpellProto()) && (holder->GetCasterGUID() == GetGUID() || !holder->IsSingleTarget()))
{
int32 damage[MAX_EFFECT_INDEX];
int32 remaintime[MAX_EFFECT_INDEX];
int32 maxduration[MAX_EFFECT_INDEX];
int32 damage[MAX_EFFECT_INDEX];
uint32 periodicTime[MAX_EFFECT_INDEX];
uint32 effIndexMask = 0;

for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
damage[i] = 0;
remaintime[i] = 0;
maxduration[i] = 0;
periodicTime[i] = 0;

if (Aura *aur = holder->GetAuraByEffectIndex(SpellEffectIndex(i)))
{
Expand All @@ -1383,34 +1385,29 @@ void Pet::_SaveAuras()
continue;

damage[i] = aur->GetModifier()->m_amount;
remaintime[i] = aur->GetAuraDuration();
maxduration[i] = aur->GetAuraMaxDuration();
periodicTime[i] = aur->GetModifier()->periodictime;
effIndexMask |= (1 << i);
}
}

if (!effIndexMask)
continue;

stmt = CharacterDatabase.CreateStatement(insAuras, "INSERT INTO pet_aura (guid, caster_guid, item_guid, spell, stackcount, remaincharges, basepoints0, basepoints1, basepoints2, maxduration0, maxduration1, maxduration2, remaintime0, remaintime1, remaintime2, effIndexMask) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");

stmt.addUInt32(m_charmInfo->GetPetNumber());
stmt.addUInt64(holder->GetCasterGuid().GetRawValue());
stmt.addUInt32(holder->GetCastItemGuid().GetCounter());
stmt.addUInt32(holder->GetId());
stmt.addUInt32(holder->GetStackAmount());
stmt.addUInt8(holder->GetAuraCharges());

for (int i = EFFECT_INDEX_0; i <= EFFECT_INDEX_2; ++i )
for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i)
stmt.addInt32(damage[i]);

for (int i = EFFECT_INDEX_0; i <= EFFECT_INDEX_2; ++i )
stmt.addInt32(maxduration[i]);

for (int i = EFFECT_INDEX_0; i <= EFFECT_INDEX_2; ++i )
stmt.addInt32(remaintime[i]);
for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i)
stmt.addUInt32(periodicTime[i]);

stmt.addInt32(holder->GetAuraMaxDuration());
stmt.addInt32(holder->GetAuraDuration());
stmt.addUInt32(effIndexMask);
stmt.Execute();
}
Expand Down

1 comment on commit 09090ac

@Feanordev
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, DMR before duration calculation fixes few talents not working on 10+sec spells (Fear etc). Nice work :)

Please sign in to comment.