Index: src/game/Creature.cpp =================================================================== --- src/game/Creature.cpp (revision 2652) +++ src/game/Creature.cpp (working copy) @@ -1005,13 +1005,13 @@ SetUInt32Value(UNIT_FIELD_FLAGS,cinfo->Flags); SetUInt32Value(UNIT_DYNAMIC_FLAGS,cinfo->dynamicflags); - SetArmor(cinfo->armor); - SetResistance(SPELL_SCHOOL_HOLY,cinfo->resistance1); - SetResistance(SPELL_SCHOOL_FIRE,cinfo->resistance2); - SetResistance(SPELL_SCHOOL_NATURE,cinfo->resistance3); - SetResistance(SPELL_SCHOOL_FROST,cinfo->resistance4); - SetResistance(SPELL_SCHOOL_SHADOW,cinfo->resistance5); - SetResistance(SPELL_SCHOOL_ARCANE,cinfo->resistance6); + SetBaseArmor(cinfo->armor); + SetBaseResistance(SPELL_SCHOOL_HOLY,cinfo->resistance1); + SetBaseResistance(SPELL_SCHOOL_FIRE,cinfo->resistance2); + SetBaseResistance(SPELL_SCHOOL_NATURE,cinfo->resistance3); + SetBaseResistance(SPELL_SCHOOL_FROST,cinfo->resistance4); + SetBaseResistance(SPELL_SCHOOL_SHADOW,cinfo->resistance5); + SetBaseResistance(SPELL_SCHOOL_ARCANE,cinfo->resistance6); //this is probably wrong SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, cinfo->equipmodel[0]); @@ -1379,12 +1379,12 @@ SetUInt32Value(UNIT_FIELD_BYTES_1,(getloyalty()<<8)); SetHealth( 28 + 10 * level); SetMaxHealth( 28 + 10 * level); - SetStat(STAT_STRENGTH,uint32(20+level*1.55)); - SetStat(STAT_AGILITY,uint32(20+level*0.64)); - SetStat(STAT_STAMINA,uint32(20+level*1.27)); - SetStat(STAT_INTELLECT,uint32(20+level*0.18)); - SetStat(STAT_SPIRIT,uint32(20+level*0.36)); - SetArmor(level*50); + SetBaseStat(STAT_STRENGTH,uint32(20+level*1.55)); + SetBaseStat(STAT_AGILITY,uint32(20+level*0.64)); + SetBaseStat(STAT_STAMINA,uint32(20+level*1.27)); + SetBaseStat(STAT_INTELLECT,uint32(20+level*0.18)); + SetBaseStat(STAT_SPIRIT,uint32(20+level*0.36)); + SetBaseArmor(level*50); if(level - cinfo->minlevel >= 21) loyalty = 7; Index: src/game/Level3.cpp =================================================================== --- src/game/Level3.cpp (revision 2653) +++ src/game/Level3.cpp (working copy) @@ -2570,12 +2570,12 @@ player->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.35f); } else player->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); - player->SetStat(STAT_STRENGTH,info->strength ); - player->SetStat(STAT_AGILITY,info->agility ); - player->SetStat(STAT_STAMINA,info->stamina ); - player->SetStat(STAT_INTELLECT,info->intellect ); - player->SetStat(STAT_SPIRIT,info->spirit ); - player->SetArmor(info->basearmor ); + player->SetBaseStat(STAT_STRENGTH,info->strength ); + player->SetBaseStat(STAT_AGILITY,info->agility ); + player->SetBaseStat(STAT_STAMINA,info->stamina ); + player->SetBaseStat(STAT_INTELLECT,info->intellect ); + player->SetBaseStat(STAT_SPIRIT,info->spirit ); + player->SetBaseArmor(info->basearmor ); player->SetUInt32Value(UNIT_FIELD_ATTACK_POWER, 0 ); player->SetUInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER, 0 ); @@ -2634,11 +2634,11 @@ // reinitilize potential block chance (used if item with Block value equiped) player->SetFloatValue(PLAYER_BLOCK_PERCENTAGE, 5 + (float(player->GetDefenceSkillValue()) - player->getLevel()*5)*0.04); player->SetFloatValue(PLAYER_CRIT_PERCENTAGE, 5); - for (int i = 0; i < 7; i++) + for (int i = 0; i < SPELL_SCHOOL_COUNT; i++) { - player->SetResistance(SpellSchools(i), 0); - player->SetResistanceBuffMods(SpellSchools(i), true, 0); - player->SetResistanceBuffMods(SpellSchools(i), false, 0); + player->SetBaseResistance(SpellSchools(i), 0); + player->SetResistanceBuff(SpellSchools(i), true, 0); + player->SetResistanceBuff(SpellSchools(i), false, 0); } return true; } Index: src/game/MiscHandler.cpp =================================================================== --- src/game/MiscHandler.cpp (revision 2652) +++ src/game/MiscHandler.cpp (working copy) @@ -711,10 +711,10 @@ GetPlayer()->SpawnCorpseBones(); // set health, mana - GetPlayer()->ApplyStats(false); + GetPlayer()->_RemoveStatsMods(); GetPlayer()->SetHealth(GetPlayer()->GetMaxHealth()/2); GetPlayer()->SetPower(POWER_MANA,GetPlayer()->GetMaxPower(POWER_MANA)/2); - GetPlayer()->ApplyStats(true); + GetPlayer()->_ApplyStatsMods(); // update world right away MapManager::Instance().GetMap(GetPlayer()->GetMapId())->Add(GetPlayer()); Index: src/game/NPCHandler.cpp =================================================================== --- src/game/NPCHandler.cpp (revision 2652) +++ src/game/NPCHandler.cpp (working copy) @@ -407,12 +407,12 @@ } } - _player->ApplyStats(false); + _player->_RemoveStatsMods(); _player->SetHealth( _player->GetMaxHealth()/2 ); _player->SetPower(POWER_MANA, _player->GetMaxPower(POWER_MANA)/2 ); _player->SetPower(POWER_RAGE, 0 ); _player->SetPower(POWER_ENERGY, _player->GetMaxPower(POWER_ENERGY)); - _player->ApplyStats(true); + _player->_ApplyStatsMods(); _player->DurabilityLossAll(0.25); _player->SpawnCorpseBones(); Index: src/game/Pet.cpp =================================================================== --- src/game/Pet.cpp (revision 2652) +++ src/game/Pet.cpp (working copy) @@ -90,12 +90,12 @@ petlevel=owner->getLevel(); SetUInt32Value(UNIT_FIELD_BYTES_0,2048); - SetStat(STAT_STRENGTH,22); - SetStat(STAT_AGILITY,22); - SetStat(STAT_STAMINA,25); - SetStat(STAT_INTELLECT,28); - SetStat(STAT_SPIRIT,27); - SetArmor(petlevel*50); + SetBaseStat(STAT_STRENGTH,22); + SetBaseStat(STAT_AGILITY,22); + SetBaseStat(STAT_STAMINA,25); + SetBaseStat(STAT_INTELLECT,28); + SetBaseStat(STAT_SPIRIT,27); + SetBaseArmor(petlevel*50); } else if(owner->getClass() == CLASS_HUNTER && cinfo->type == CREATURE_TYPE_BEAST) { @@ -108,12 +108,12 @@ SetMaxPower(POWER_HAPPINESS,1000000); SetPower( POWER_HAPPINESS,fields[11].GetUInt32()); setPowerType(POWER_FOCUS); - SetStat(STAT_STRENGTH,uint32(20+petlevel*1.55)); - SetStat(STAT_AGILITY,uint32(20+petlevel*0.64)); - SetStat(STAT_STAMINA,uint32(20+petlevel*1.27)); - SetStat(STAT_INTELLECT,uint32(20+petlevel*0.18)); - SetStat(STAT_SPIRIT,uint32(20+petlevel*0.36)); - SetArmor(petlevel*50); + SetBaseStat(STAT_STRENGTH,uint32(20+petlevel*1.55)); + SetBaseStat(STAT_AGILITY,uint32(20+petlevel*0.64)); + SetBaseStat(STAT_STAMINA,uint32(20+petlevel*1.27)); + SetBaseStat(STAT_INTELLECT,uint32(20+petlevel*0.18)); + SetBaseStat(STAT_SPIRIT,uint32(20+petlevel*0.36)); + SetBaseArmor(petlevel*50); } SetLevel( petlevel); SetHealth( 28 + 10 * petlevel); Index: src/game/Player.cpp =================================================================== --- src/game/Player.cpp (revision 2653) +++ src/game/Player.cpp (working copy) @@ -159,6 +159,21 @@ m_resetTalentsCost = 0; m_resetTalentsTime = 0; + + for(int i = 0; i < MAX_STATS; ++i) + m_createStats_field[i] = 0; + + for(int i = 0; i < MAX_STATS; ++i) + m_PosStat[i] = 0; + for(int i = 0; i < MAX_STATS; ++i) + m_NegStat[i] = 0; + for(int i = 0; i < MAX_STATS; ++i) + m_CreateStat[i] = 0; + for(int i = 0; i < SPELL_SCHOOL_COUNT; ++i) + { + m_ResistanceBuff[i][0] = 0; + m_ResistanceBuff[i][1] = 0; + } } Player::~Player () @@ -225,11 +240,11 @@ return false; } - m_createStats[STAT_AGILITY] = (float)info->agility; - m_createStats[STAT_INTELLECT] = (float)info->intellect; - m_createStats[STAT_SPIRIT] = (float)info->spirit; - m_createStats[STAT_STAMINA] = (float)info->stamina; - m_createStats[STAT_STRENGTH] = (float)info->strength; + SetCreateStat(STAT_AGILITY, (float)info->agility); + SetCreateStat(STAT_INTELLECT,(float)info->intellect); + SetCreateStat(STAT_SPIRIT, (float)info->spirit); + SetCreateStat(STAT_STAMINA, (float)info->stamina); + SetCreateStat(STAT_STRENGTH, (float)info->strength); for (i = 0; i < BANK_SLOT_BAG_END; i++) m_items[i] = NULL; @@ -288,12 +303,13 @@ SetFloatValue(OBJECT_FIELD_SCALE_X, 1.35f); } else SetFloatValue(OBJECT_FIELD_SCALE_X, 1.0f); - SetStat(STAT_STRENGTH,info->strength ); - SetStat(STAT_AGILITY,info->agility ); - SetStat(STAT_STAMINA,info->stamina ); - SetStat(STAT_INTELLECT,info->intellect ); - SetStat(STAT_SPIRIT,info->spirit ); - SetArmor(info->basearmor ); + + SetBaseArmor(info->basearmor); + SetBaseStat(STAT_STRENGTH,info->strength ); + SetBaseStat(STAT_AGILITY,info->agility ); + SetBaseStat(STAT_STAMINA,info->stamina ); + SetBaseStat(STAT_INTELLECT,info->intellect ); + SetBaseStat(STAT_SPIRIT,info->spirit ); SetUInt32Value(UNIT_FIELD_ATTACK_POWER, 0 ); SetHealth(info->health); @@ -1591,7 +1607,7 @@ SetMaxHealth(uint32(newHP)); // only integer part for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) - SetStat(Stats(i), uint32(newStats[i])); // only integer part + SetBaseStat(Stats(i), uint32(newStats[i])); // only integer part // update dependent from level part BlockChanceWithoutMods = 5 + (GetDefenceSkillValue() - getLevel()*5)*0.04); UpdateBlockPercentage(); @@ -4186,15 +4202,11 @@ } _RemoveStatsMods(); - AuraList& mModBaseResistancePct = GetAurasByType(SPELL_AURA_MOD_BASE_RESISTANCE_PCT); - for(AuraList::iterator i = mModBaseResistancePct.begin(); i != mModBaseResistancePct.end(); ++i) - (*i)->ApplyModifier(false); _ApplyItemBonuses(proto,slot,apply); - for(AuraList::iterator i = mModBaseResistancePct.begin(); i != mModBaseResistancePct.end(); ++i) - (*i)->ApplyModifier(true); _ApplyStatsMods(); + if(apply) CastItemEquipSpell(item); @@ -4235,28 +4247,23 @@ typestr = "Health"; break; case AGILITY: // modify agility - ApplyStatMod(STAT_AGILITY, val, apply); ApplyPosStatMod(STAT_AGILITY, val, apply); typestr = "AGILITY"; break; case STRENGHT: //modify strength - ApplyStatMod(STAT_STRENGTH, val, apply); ApplyPosStatMod(STAT_STRENGTH, val, apply); typestr = "STRENGHT"; break; case INTELLECT: //modify intellect - ApplyStatMod(STAT_INTELLECT, val, apply); ApplyPosStatMod(STAT_INTELLECT, val, apply); //ApplyMaxPowerMod(POWER_MANA, val*15, apply); typestr = "INTELLECT"; break; case SPIRIT: //modify spirit - ApplyStatMod(STAT_SPIRIT, val, apply); ApplyPosStatMod(STAT_SPIRIT, val, apply); typestr = "SPIRIT"; break; case STAMINA: //modify stamina - ApplyStatMod(STAT_STAMINA ,val, apply); ApplyPosStatMod(STAT_STAMINA ,val, apply); //ApplyMaxHealthMod( val*10,apply); typestr = "STAMINA"; @@ -4269,7 +4276,7 @@ if (proto->Armor) { - ApplyArmorMod( proto->Armor, apply); + ApplyBaseArmorMod( proto->Armor, apply); sLog.outDebug("%s Armor: \t\t%u", applystr.c_str(), proto->Armor); } @@ -4281,37 +4288,37 @@ if (proto->HolyRes) { - ApplyResistanceMod(SPELL_SCHOOL_HOLY, proto->HolyRes, apply); + ApplyBaseResistanceMod(SPELL_SCHOOL_HOLY, proto->HolyRes, apply); sLog.outDebug("%s HolyRes: \t\t%u", applystr.c_str(), proto->HolyRes); } if (proto->FireRes) { - ApplyResistanceMod(SPELL_SCHOOL_FIRE, proto->FireRes, apply); + ApplyBaseResistanceMod(SPELL_SCHOOL_FIRE, proto->FireRes, apply); sLog.outDebug("%s FireRes: \t\t%u", applystr.c_str(), proto->FireRes); } if (proto->NatureRes) { - ApplyResistanceMod(SPELL_SCHOOL_NATURE, proto->NatureRes, apply); + ApplyBaseResistanceMod(SPELL_SCHOOL_NATURE, proto->NatureRes, apply); sLog.outDebug("%s NatureRes: \t\t%u", applystr.c_str(), proto->NatureRes); } if (proto->FrostRes) { - ApplyResistanceMod(SPELL_SCHOOL_FROST, proto->FrostRes, apply); + ApplyBaseResistanceMod(SPELL_SCHOOL_FROST, proto->FrostRes, apply); sLog.outDebug("%s FrostRes: \t\t%u", applystr.c_str(), proto->FrostRes); } if (proto->ShadowRes) { - ApplyResistanceMod(SPELL_SCHOOL_SHADOW, proto->ShadowRes, apply); + ApplyBaseResistanceMod(SPELL_SCHOOL_SHADOW, proto->ShadowRes, apply); sLog.outDebug("%s ShadowRes: \t\t%u", applystr.c_str(), proto->ShadowRes); } if (proto->ArcaneRes) { - ApplyResistanceMod(SPELL_SCHOOL_ARCANE, proto->ArcaneRes, apply); + ApplyBaseResistanceMod(SPELL_SCHOOL_ARCANE, proto->ArcaneRes, apply); sLog.outDebug("%s ArcaneRes: \t\t%u", applystr.c_str(), proto->ArcaneRes); } @@ -4603,10 +4610,6 @@ _RemoveStatsMods(); - AuraList& mModBaseResistancePct = GetAurasByType(SPELL_AURA_MOD_BASE_RESISTANCE_PCT); - for(AuraList::iterator i = mModBaseResistancePct.begin(); i != mModBaseResistancePct.end(); ++i) - (*i)->ApplyModifier(false); - for (int i = 0; i < INVENTORY_SLOT_BAG_END; i++) { if(m_items[i]) @@ -4622,9 +4625,6 @@ } } - for(AuraList::iterator i = mModBaseResistancePct.begin(); i != mModBaseResistancePct.end(); ++i) - (*i)->ApplyModifier(true); - _ApplyStatsMods(); sLog.outDebug("_ApplyAllItemMods complete."); @@ -7712,7 +7712,7 @@ //uint32 enchant_description = pEnchant->description; //SpellEntry *enchantSpell_info = sSpellStore.LookupEntry(enchant_spell_id); if(enchant_display ==4) - SetArmor(GetArmor()-enchant_value1); + ApplyBaseArmorMod(enchant_value1,false); else if(enchant_display ==2) { SetFloatValue(UNIT_FIELD_MINDAMAGE,GetFloatValue(UNIT_FIELD_MINDAMAGE)-enchant_value1); @@ -9889,12 +9889,19 @@ return false; } - m_createStats[STAT_AGILITY] = (float)info->agility; - m_createStats[STAT_INTELLECT] = (float)info->intellect; - m_createStats[STAT_SPIRIT] = (float)info->spirit; - m_createStats[STAT_STAMINA] = (float)info->stamina; - m_createStats[STAT_STRENGTH] = (float)info->strength; + // init create stats before stats initiaization + SetCreateStat(STAT_AGILITY, (float)info->agility); + SetCreateStat(STAT_INTELLECT,(float)info->intellect); + SetCreateStat(STAT_SPIRIT, (float)info->spirit); + SetCreateStat(STAT_STAMINA, (float)info->stamina); + SetCreateStat(STAT_STRENGTH, (float)info->strength); + // currently in m_uint32Values stored base stats, move its to correct fields + for(int i = 0; i < SPELL_SCHOOL_COUNT; ++i) + SetBaseResistance(SpellSchools(i),GetResistance(SpellSchools(i))); + for(int i = 0; i < MAX_STATS; ++i) + SetBaseStat(Stats(i),GetStat(Stats(i))); + uint32 transGUID = fields[29].GetUInt32(); m_positionX = fields[7].GetFloat(); m_positionY = fields[8].GetFloat(); @@ -10461,7 +10468,18 @@ uint16 i; for( i = 0; i < m_valuesCount; i++ ) { - ss << GetUInt32Value(i) << " "; + if(i >= UNIT_FIELD_STATS && i < UNIT_FIELD_STATS + MAX_STATS) + { + + ss << reinterpret_cast(m_BaseStat[Stats(i-UNIT_FIELD_STATS)]) << " "; + } + else + if(i >= UNIT_FIELD_RESISTANCES && i < UNIT_FIELD_RESISTANCES + SPELL_SCHOOL_COUNT) + { + ss << reinterpret_cast(m_BaseResistance[SpellSchools(i-UNIT_FIELD_RESISTANCES)]) << " "; + } + else + ss << GetUInt32Value(i) << " "; } ss << "', '"; @@ -11098,3 +11116,29 @@ //RestTickUpdate SetUInt32Value(PLAYER_REST_STATE_EXPERIENCE, rest_bonus); } + +void Player::UpdateStatsBuffs(Stats stat, float totalpct) +{ + float stat_pos = m_PosStat[stat]; + ApplyPercentModFloatVar(stat_pos,totalpct,true); + SetFloatValue(PLAYER_FIELD_POSSTAT0+stat,stat_pos); + + float stat_neg = m_NegStat[stat]; + ApplyPercentModFloatVar(stat_neg,totalpct,true); + SetFloatValue(PLAYER_FIELD_NEGSTAT0+stat,stat_neg); + + float stat_create = m_CreateStat[stat]; + ApplyPercentModFloatVar(stat_create,totalpct,true); + m_createStats_field[stat] = stat_create; +} + +void Player::UpdateResistanceBuffs(SpellSchools res, float totalpct) +{ + float res_buf_pos = m_ResistanceBuff[res][true]; + ApplyPercentModFloatVar(res_buf_pos,totalpct,true); + SetFloatValue(PLAYER_FIELD_RESISTANCEBUFFMODSPOSITIVE+res,res_buf_pos); + + float res_buf_neg = m_ResistanceBuff[res][false]; + ApplyPercentModFloatVar(res_buf_neg,totalpct,true); + SetFloatValue(PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE+res,res_buf_neg); +} Index: src/game/Player.h =================================================================== --- src/game/Player.h (revision 2653) +++ src/game/Player.h (working copy) @@ -510,23 +510,6 @@ void UnTamePet(Creature* pet = NULL); void Uncharm(); - float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? PLAYER_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); } - void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? PLAYER_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE+school,val); } - void ApplyResistanceBuffModsMod(SpellSchools school, bool positive, float val, bool apply) { ApplyModFloatValue(positive ? PLAYER_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); } - void ApplyResistanceBuffModsPercentMod(SpellSchools school, bool positive, float val, bool apply) { ApplyPercentModFloatValue(positive ? PLAYER_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE+school, val, apply); } - void SetPosStat(Stats stat, float val) { SetFloatValue(PLAYER_FIELD_POSSTAT0+stat, val); } - void ApplyPosStatMod(Stats stat, float val, bool apply) { ApplyModFloatValue(PLAYER_FIELD_POSSTAT0+stat, val, apply); } - void ApplyPosStatPercentMod(Stats stat, float val, bool apply) { ApplyPercentModFloatValue(PLAYER_FIELD_POSSTAT0+stat, val, apply); } - void SetNegStat(Stats stat, float val) { SetFloatValue(PLAYER_FIELD_NEGSTAT0+stat, val); } - void ApplyNegStatMod(Stats stat, float val, bool apply) { ApplyModFloatValue(PLAYER_FIELD_NEGSTAT0+stat, val, apply); } - void ApplyNegStatPercentMod(Stats stat, float val, bool apply) { ApplyPercentModFloatValue(PLAYER_FIELD_NEGSTAT0+stat, val, apply); } - void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; } - void ApplyCreateStatMod(Stats stat, float val, bool apply) { m_createStats[stat] += (apply ? val : -val); } - void ApplyCreateStatPercentMod(Stats stat, float val, bool apply) { m_createStats[stat] *= (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val)); } - float GetPosStat(Stats stat) const { return GetFloatValue(PLAYER_FIELD_POSSTAT0+stat); } - float GetNegStat(Stats stat) const { return GetFloatValue(PLAYER_FIELD_NEGSTAT0+stat); } - float GetCreateStat(Stats stat) const { return m_createStats[stat]; } - /*********************************************************/ /*** STORAGE SYSTEM ***/ /*********************************************************/ @@ -1111,6 +1094,26 @@ float GetTransOffsetZ() const { return m_transZ; } float GetTransOffsetO() const { return m_transO; } + //// Cascade Update System ///////////////////////// + // Stats + float GetPosStat(Stats stat) const { return GetFloatValue(PLAYER_FIELD_POSSTAT0+stat); } + void SetPosStat(Stats stat, float val) { m_PosStat[stat] = val; CascadeUpdateStat(stat); } + void ApplyPosStatMod(Stats stat, float addval, bool apply) { m_PosStat[stat] += (apply ? addval : -addval); CascadeUpdateStat(stat); } + float GetNegStat(Stats stat) const { return GetFloatValue(PLAYER_FIELD_NEGSTAT0+stat); } + void SetNegStat(Stats stat, float val) { m_NegStat[stat] = val; CascadeUpdateStat(stat); } + void ApplyNegStatMod(Stats stat, float addval, bool apply) { m_NegStat[stat] += (apply ? addval : -addval); CascadeUpdateStat(stat); } + float GetCreateStat(Stats stat) const { return m_createStats_field[stat]; } + // called without cascade update, used only at create/load/reset for initial setup + void SetCreateStat(Stats stat, float val) { m_CreateStat[stat] = val; m_createStats_field[stat] = val; } + void ApplyCreateStatMod(Stats stat, float addval, bool apply) { m_CreateStat[stat] += (apply ? addval : -addval); CascadeUpdateStat(stat); } + // ...called from Unit::CascadeUpdateResistance only + void UpdateStatsBuffs(Stats stat, float totalpct); + // Resistance + float GetResistanceBuff(SpellSchools school, bool positive) const { return GetFloatValue(positive ? PLAYER_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); } + void SetResistanceBuff(SpellSchools res,bool positive, float value) { m_ResistanceBuff[res][positive] = value; CascadeUpdateResistance(res); } + void ApplyResistanceBuffMod(SpellSchools res, bool positive, float addval, bool apply) { m_ResistanceBuff[res][positive] += (apply ? addval : -addval); CascadeUpdateResistance(res); } + // ...called from Unit::CascadeUpdateResistance only + void UpdateResistanceBuffs(SpellSchools res, float totalpct); protected: /*********************************************************/ @@ -1191,7 +1194,7 @@ std::string m_rank_name; PlayerCreateInfo *info; - float m_createStats[5]; + float m_createStats_field[5]; // with applied percent mods uint32 m_race; uint32 m_class; @@ -1291,7 +1294,6 @@ float inn_pos_z; float rest_bonus; int rest_type; - ////////////////////Rest System///////////////////// // Transports float m_transX; @@ -1303,6 +1305,12 @@ uint32 m_resetTalentsCost; time_t m_resetTalentsTime; + + //// Cascade Update System ///////////////////////// + float m_PosStat[MAX_STATS]; //(with not applied percent modifiers) + float m_NegStat[MAX_STATS]; //(with not applied percent modifiers) + float m_CreateStat[MAX_STATS]; //(with not applied percent modifiers) + float m_ResistanceBuff[SPELL_SCHOOL_COUNT][2]; //(with not applied percent modifiers) }; int32 irand(int32 min, int32 max); Index: src/game/SharedDefines.h =================================================================== --- src/game/SharedDefines.h (revision 2652) +++ src/game/SharedDefines.h (working copy) @@ -91,6 +91,8 @@ SPELL_SCHOOL_ARCANE = 6 }; +#define SPELL_SCHOOL_COUNT 7 + #define ITEM_QUALITY_POOR 0 //GREY #define ITEM_QUALITY_NORMAL 1 //WHITE #define ITEM_QUALITY_UNCOMMON 2 //GREEN Index: src/game/SpellAuras.cpp =================================================================== --- src/game/SpellAuras.cpp (revision 2652) +++ src/game/SpellAuras.cpp (working copy) @@ -587,9 +587,7 @@ if( m_modifier.m_auraname==SPELL_AURA_MOD_REGEN || m_modifier.m_auraname==SPELL_AURA_MOD_POWER_REGEN ) m_periodicTimer = 5000; - m_target->ApplyStats(false); ApplyModifier(true); - m_target->ApplyStats(true); sLog.outDebug("Aura %u now is in use", m_modifier.m_auraname); @@ -644,7 +642,6 @@ if( m_target->GetTypeId() == TYPEID_PLAYER ) UpdateAuraDuration(); } - } void Aura::_RemoveAura() @@ -653,10 +650,10 @@ if(m_modifier.m_auraname == SPELL_AURA_MOD_SHAPESHIFT) // remove the shapeshift aura's boosts HandleShapeshiftBoosts(false, this); - m_target->ApplyStats(false); + m_target->_RemoveStatsMods(); sLog.outDebug("Aura %u now is remove", m_modifier.m_auraname); ApplyModifier(false); - m_target->ApplyStats(true); + m_target->_ApplyStatsMods(); Unit* caster = GetCaster(); @@ -915,10 +912,8 @@ return; SpellCastTargets targets; targets.setUnitTarget(target); - // prevent double stat apply for triggered auras - target->ApplyStats(true); + spell.prepare(&targets); - target->ApplyStats(false); } } } @@ -1854,90 +1849,20 @@ void Aura::HandleAuraModResistanceExclusive(bool apply) { - if(m_modifier.m_miscvalue < IMMUNE_SCHOOL_PHYSICAL || m_modifier.m_miscvalue > 127) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_BASE_RESISTANCE_PCT not valid"); - return; - } - - bool positive = m_modifier.m_miscvalue2 == 0; - - for(int8 x=0;x < 7;x++) - { - if(m_modifier.m_miscvalue & int32(1<ApplyResistanceMod(school,m_modifier.m_amount, apply); - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->ApplyResistanceBuffModsMod(school,positive,m_modifier.m_amount, apply); - } - } + // applied at aura add/remove } void Aura::HandleAuraModResistance(bool apply) { - if(m_modifier.m_miscvalue < IMMUNE_SCHOOL_PHYSICAL || m_modifier.m_miscvalue > 127) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_BASE_RESISTANCE_PCT not valid"); - return; - } - - bool positive = m_modifier.m_miscvalue2 == 0; - - for(int8 x=0;x < 7;x++) - { - if(m_modifier.m_miscvalue & int32(1<ApplyResistanceMod(school,m_modifier.m_amount, apply); - if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->ApplyResistanceBuffModsMod(school,positive,m_modifier.m_amount, apply); - } - } } void Aura::HandleAuraModBaseResistancePCT(bool apply) { - if(m_modifier.m_miscvalue < IMMUNE_SCHOOL_PHYSICAL || m_modifier.m_miscvalue > 127) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_BASE_RESISTANCE_PCT not valid"); - return; - } - - // only players have base stats - if(m_target->GetTypeId() != TYPEID_PLAYER) - return; - Player *p_target = (Player*)m_target; - - for(int8 x=0;x < 7;x++) - { - if(m_modifier.m_miscvalue & int32(1<GetResistance(school); - float baseRes = curRes + p_target->GetResistanceBuffMods(school, false) - p_target->GetResistanceBuffMods(school, true); - float baseRes_new = baseRes * (apply?(100.0f+m_modifier.m_amount)/100.0f : 100.0f / (100.0f+m_modifier.m_amount)); - p_target->SetResistance(school, curRes + baseRes_new - baseRes); - } - } } void Aura::HandleModResistancePercent(bool apply) { - for(int8 i = 0; i < 7; i++) - { - if(m_modifier.m_miscvalue & int32(1<ApplyResistancePercentMod(SpellSchools(i), m_modifier.m_amount, apply ); - if(m_target->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)m_target)->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply); - ((Player*)m_target)->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply); - } - } - } + // all done in cascade update system and at aura add/remove } void Aura::HandleModBaseResistance(bool apply) @@ -1949,7 +1874,7 @@ for(int i = 0; i < 7; i++) if(m_modifier.m_miscvalue & (1<ApplyResistanceMod(SpellSchools(SPELL_SCHOOL_NORMAL + i),m_modifier.m_amount, apply); + p_target->ApplyBaseResistanceMod(SpellSchools(SPELL_SCHOOL_NORMAL + i),m_modifier.m_amount, apply); } /********************************/ @@ -1968,7 +1893,6 @@ { if (m_modifier.m_miscvalue == -1 || m_modifier.m_miscvalue == i) { - m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply); if(m_target->GetTypeId() == TYPEID_PLAYER) { if (m_modifier.m_miscvalue2 == 0) @@ -1976,57 +1900,19 @@ else ((Player*)m_target)->ApplyNegStatMod(Stats(i),m_modifier.m_amount,apply); } + else + m_target->ApplyBaseStatMod(Stats(i), m_modifier.m_amount,apply); } } } void Aura::HandleModPercentStat(bool apply) { - if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); - return; - } - - // only players have base stats - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - Player *p_target = (Player*)m_target; - - for (int32 i = 0; i < 5; i++) - { - if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) - { - float curStat = p_target->GetStat(Stats(i)); - float baseStat = curStat + p_target->GetNegStat(Stats(i)) - p_target->GetPosStat(Stats(i)); - float baseStat_new = baseStat * (apply?(100.0f+m_modifier.m_amount)/100.0f : 100.0f / (100.0f+m_modifier.m_amount)); - p_target->SetStat(Stats(i), curStat + baseStat_new - baseStat); - p_target->ApplyCreateStatPercentMod(Stats(i), m_modifier.m_amount, apply ); - } - } } void Aura::HandleModTotalPercentStat(bool apply) { - if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); - return; - } - - for (int32 i = 0; i < 5; i++) - { - if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) - { - m_target->ApplyStatPercentMod(Stats(i), m_modifier.m_amount, apply ); - if (m_target->GetTypeId() == TYPEID_PLAYER) - { - ((Player*)m_target)->ApplyPosStatPercentMod(Stats(i), m_modifier.m_amount, apply ); - ((Player*)m_target)->ApplyNegStatPercentMod(Stats(i), m_modifier.m_amount, apply ); - ((Player*)m_target)->ApplyCreateStatPercentMod(Stats(i), m_modifier.m_amount, apply ); - } - } - } + // all done in cascade update system and at aura add/remove } /********************************/ @@ -2520,3 +2406,112 @@ double healthPercentage = (double)unit_target->GetHealth() / (double)unit_target->GetMaxHealth(); unit_target->SetHealth(uint32(ceil((double)unit_target->GetMaxHealth() * healthPercentage))); } + +//// Cascade Update System +void Aura::ApplyModResistancePercent(bool) +{ + for(int8 i = 0; i < SPELL_SCHOOL_COUNT; ++i) + { + if(m_modifier.m_miscvalue & int32(1<CascadeUpdateResistance(SpellSchools(i)); + } +} + +void Aura::ApplyAuraModResistanceExclusive(bool apply) +{ + if(m_modifier.m_miscvalue < IMMUNE_SCHOOL_PHYSICAL || m_modifier.m_miscvalue > 127) + { + sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_BASE_RESISTANCE_PCT not valid"); + return; + } + + bool positive = m_modifier.m_miscvalue2 == 0; + + for(int8 x=0;x < SPELL_SCHOOL_COUNT; ++x) + { + if(m_modifier.m_miscvalue & int32(1<GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->ApplyResistanceBuffMod(school,positive,m_modifier.m_amount, apply); + else + m_target->ApplyBaseResistanceMod(school,m_modifier.m_amount, apply); + } + } +} + +void Aura::ApplyModTotalPercentStat(bool) +{ + if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4) + { + sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); + return; + } + + for (int32 i = 0; i < MAX_STATS; ++i) + { + if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) + m_target->CascadeUpdateStat(Stats(i)); + } +} + +void Aura::ApplyAuraModResistance(bool apply) +{ + if(m_modifier.m_miscvalue < IMMUNE_SCHOOL_PHYSICAL || m_modifier.m_miscvalue > 127) + { + sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_BASE_RESISTANCE_PCT not valid"); + return; + } + + bool positive = m_modifier.m_miscvalue2 == 0; + + for(int8 x=0;x < SPELL_SCHOOL_COUNT;x++) + { + if(m_modifier.m_miscvalue & int32(1<GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->ApplyResistanceBuffMod(school,positive,m_modifier.m_amount, apply); + else + m_target->ApplyBaseResistanceMod(school,m_modifier.m_amount, apply); + } + } +} + +void Aura::ApplyAuraModBaseResistancePCT(bool) +{ + if(m_modifier.m_miscvalue < IMMUNE_SCHOOL_PHYSICAL || m_modifier.m_miscvalue > 127) + { + sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_BASE_RESISTANCE_PCT not valid"); + return; + } + + // only players have base stats + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + Player *p_target = (Player*)m_target; + + for(int8 x=0;x < SPELL_SCHOOL_COUNT;x++) + if(m_modifier.m_miscvalue & int32(1<CascadeUpdateResistance(SpellSchools(SPELL_SCHOOL_NORMAL + x)); +} + +void Aura::ApplyModPercentStat(bool apply) +{ + if (m_modifier.m_miscvalue < -1 || m_modifier.m_miscvalue > 4) + { + sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_PERCENT_STAT not valid"); + return; + } + + // only players have base stats + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + Player *p_target = (Player*)m_target; + + for (int32 i = 0; i < MAX_STATS; i++) + if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) + p_target->CascadeUpdateStat(Stats(i)); +} Index: src/game/SpellAuras.h =================================================================== --- src/game/SpellAuras.h (revision 2652) +++ src/game/SpellAuras.h (working copy) @@ -144,6 +144,15 @@ void HandleRangedAmmoHaste(bool Apply); void HandleModTotalPercentStat(bool Apply); + // Cascade updates at aura adding/removing + void ApplyModTotalPercentStat(bool); + void ApplyModPercentStat(bool); + void ApplyModResistancePercent(bool); + void ApplyAuraModBaseResistancePCT(bool); + void ApplyAuraModResistanceExclusive(bool apply); + void ApplyAuraModResistance(bool apply); + + // Common methods Aura(SpellEntry* spellproto, uint32 eff, Unit *target, Unit *caster = NULL, Item* castItem = NULL); virtual ~Aura(); Index: src/game/SpellEffects.cpp =================================================================== --- src/game/SpellEffects.cpp (revision 2652) +++ src/game/SpellEffects.cpp (working copy) @@ -804,7 +804,7 @@ spawnCreature->SetStat(STAT_INTELLECT,int(20+level*0.18)); spawnCreature->SetStat(STAT_SPIRIT,int(20+level*0.36)); */ - spawnCreature->SetArmor(level*50); + spawnCreature->SetBaseArmor(level*50); spawnCreature->AIM_Initialize(); std::string name; @@ -1048,7 +1048,7 @@ spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000); spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); - spawnCreature->SetArmor(level*50); + spawnCreature->SetBaseArmor(level*50); spawnCreature->AIM_Initialize(); MapManager::Instance().GetMap(m_caster->GetMapId())->Add((Creature*)spawnCreature); @@ -1311,11 +1311,11 @@ NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0); NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000); NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); - NewSummon->SetStat(STAT_STRENGTH,22); - NewSummon->SetStat(STAT_AGILITY,22); - NewSummon->SetStat(STAT_STAMINA,25); - NewSummon->SetStat(STAT_INTELLECT,28); - NewSummon->SetStat(STAT_SPIRIT,27); + NewSummon->SetBaseStat(STAT_STRENGTH,22); + NewSummon->SetBaseStat(STAT_AGILITY,22); + NewSummon->SetBaseStat(STAT_STAMINA,25); + NewSummon->SetBaseStat(STAT_INTELLECT,28); + NewSummon->SetBaseStat(STAT_SPIRIT,27); for(uint32 i=0; i < CREATURE_MAX_SPELLS; i++) NewSummon->m_spells[i] = 0; Index: src/game/Unit.cpp =================================================================== --- src/game/Unit.cpp (revision 2652) +++ src/game/Unit.cpp (working copy) @@ -81,6 +81,11 @@ m_baseSpellCritChance = 5; m_modCastSpeedPct = 0; m_CombatTimer = 0; + + for(int i = 0; i < MAX_STATS; ++i) + m_BaseStat[i] = 0; + for(int i = 0; i < SPELL_SCHOOL_COUNT; ++i) + m_BaseResistance[i] = 0; } Unit::~Unit() @@ -1673,14 +1678,38 @@ } } + if(Aur->GetTarget()) + { + Aur->GetTarget()->_RemoveStatsMods(); + } + Aur->_AddAura(); + m_Auras.insert(AuraMap::value_type(spellEffectPair(Aur->GetId(), Aur->GetEffIndex()), Aur)); + if (Aur->GetModifier()->m_auraname < TOTAL_AURAS) { m_modAuras[Aur->GetModifier()->m_auraname].push_back(Aur); m_AuraModifiers[Aur->GetModifier()->m_auraname] += (Aur->GetModifier()->m_amount); } + //// Cascaded Update System + switch(Aur->GetModifier()->m_auraname) + { + case SPELL_AURA_MOD_RESISTANCE_PCT: Aur->ApplyModResistancePercent(true); break; + case SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE: Aur->ApplyAuraModResistanceExclusive(true); break; + case SPELL_AURA_MOD_BASE_RESISTANCE_PCT: Aur->ApplyAuraModBaseResistancePCT(true); break; + case SPELL_AURA_MOD_RESISTANCE: Aur->ApplyAuraModResistance(true); break; + case SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE: Aur->ApplyModTotalPercentStat(true); break; + case SPELL_AURA_MOD_PERCENT_STAT: Aur->ApplyModPercentStat(true); break; + } + + if(Aur->GetTarget()) + { + Aur->GetTarget()->_ApplyStatsMods(); + } + + if (IsSingleTarget(Aur->GetId()) && Aur->GetTarget() && Aur->GetSpellProto()) { if(Unit* caster = Aur->GetCaster()) @@ -1932,6 +1961,7 @@ } } } + if ((*i).second->GetModifier()->m_auraname < TOTAL_AURAS) { m_AuraModifiers[(*i).second->GetModifier()->m_auraname] -= ((*i).second->GetModifier()->m_amount); @@ -1939,9 +1969,23 @@ } (*i).second->SetRemoveOnDeath(onDeath); (*i).second->_RemoveAura(); - delete (*i).second; + + Aura* Aur = (*i).second; m_Auras.erase(i++); m_removedAuras++; // internal count used by unit update + + //// Cascaded Update System + switch(Aur->GetModifier()->m_auraname) + { + case SPELL_AURA_MOD_RESISTANCE_PCT: Aur->ApplyModResistancePercent(false); break; + case SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE: Aur->ApplyAuraModResistanceExclusive(false);break; + case SPELL_AURA_MOD_BASE_RESISTANCE_PCT: Aur->ApplyAuraModBaseResistancePCT(false); break; + case SPELL_AURA_MOD_RESISTANCE: Aur->ApplyAuraModResistance(false); break; + case SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE: Aur->ApplyModTotalPercentStat(false); break; + case SPELL_AURA_MOD_PERCENT_STAT: Aur->ApplyModPercentStat(false); break; + } + + delete Aur; } bool Unit::SetAurDuration(uint32 spellId, uint32 effindex,uint32 duration) @@ -2001,15 +2045,15 @@ void Unit::_RemoveStatsMods() { - ApplyStats(false); + _ApplyStats(false); } void Unit::_ApplyStatsMods() { - ApplyStats(true); + _ApplyStats(true); } -void Unit::ApplyStats(bool apply) +void Unit::_ApplyStats(bool apply) { // TODO: // -- add -- @@ -2021,71 +2065,7 @@ float val; int32 val2,tem_att_power; - float totalstatmods[5] = {1,1,1,1,1}; - float totalresmods[7] = {1,1,1,1,1,1,1}; - AuraList& mModTotalStatPct = GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); - for(AuraList::iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i) - { - if((*i)->GetModifier()->m_miscvalue != -1) - totalstatmods[(*i)->GetModifier()->m_miscvalue] *= (100.0f + (*i)->GetModifier()->m_amount) / 100.0f; - else - for (uint8 j = 0; j < 5; j++) - totalstatmods[j] *= (100.0f + (*i)->GetModifier()->m_amount) / 100.0f; - } - AuraList& mModResistancePct = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_PCT); - for(AuraList::iterator i = mModResistancePct.begin(); i != mModResistancePct.end(); ++i) - for(uint8 j = 0; j <= 6; j++) - if((*i)->GetModifier()->m_miscvalue & (1<GetModifier()->m_amount) / 100.0f; - - for (uint8 i = 0; i < 5; i++) - totalstatmods[i] = totalstatmods[i] * 100.0f - 100.0f; - for (uint8 i = 0; i < 7; i++) - totalresmods[i] = totalresmods[i] * 100.0f - 100.0f; - - // restore percent mods - if (apply) - { - for (uint8 i = 0; i < 5; i++) - { - if (totalstatmods[i] != 0) - { - ApplyStatPercentMod(Stats(i),totalstatmods[i], apply ); - ((Player*)this)->ApplyPosStatPercentMod(Stats(i),totalstatmods[i], apply ); - ((Player*)this)->ApplyNegStatPercentMod(Stats(i),totalstatmods[i], apply ); - } - } - for (uint8 i = 0; i < 7; i++) - { - if (totalresmods[i] != 0) - { - ApplyResistancePercentMod(SpellSchools(i), totalresmods[i], apply ); - ((Player*)this)->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true, totalresmods[i], apply); - ((Player*)this)->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false, totalresmods[i], apply); - } - } - } - - // Armor - val = 2*(GetStat(STAT_AGILITY) - ((Player*)this)->GetCreateStat(STAT_AGILITY)); - - ApplyArmorMod( val, apply); - - // HP - val2 = uint32((GetStat(STAT_STAMINA) - ((Player*)this)->GetCreateStat(STAT_STAMINA))*10); - - ApplyMaxHealthMod( val2, apply); - - // MP - if(getClass() != WARRIOR && getClass() != ROGUE) - { - val2 = uint32((GetStat(STAT_INTELLECT) - ((Player*)this)->GetCreateStat(STAT_INTELLECT))*15); - - ApplyMaxPowerMod(POWER_MANA, val2, apply); - - } - float classrate = 0; // Melee Attack Power @@ -2174,80 +2154,26 @@ ApplyModFloatValue(PLAYER_PARRY_PERCENTAGE, val, apply); - // remove percent mods to see original stats when adding buffs/items - if (!apply) - { - for (uint8 i = 0; i < 5; i++) - { - if (totalstatmods[i]) - { - ApplyStatPercentMod(Stats(i),totalstatmods[i], apply ); - ((Player*)this)->ApplyPosStatPercentMod(Stats(i),totalstatmods[i], apply ); - ((Player*)this)->ApplyNegStatPercentMod(Stats(i),totalstatmods[i], apply ); - } - } - for (uint8 i = 0; i < 7; i++) - { - if (totalresmods[i]) - { - ApplyResistancePercentMod(SpellSchools(i), totalresmods[i], apply ); - ((Player*)this)->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true, totalresmods[i], apply); - ((Player*)this)->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false, totalresmods[i], apply); - } - } - } } void Unit::_RemoveAllAuraMods() { - ApplyStats(false); + _RemoveStatsMods(); + for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i) - { - switch ((*i).second->GetModifier()->m_auraname) - { - case SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE: - case SPELL_AURA_MOD_RESISTANCE_PCT: - // these are already removed by applystats - break; - default: - (*i).second->ApplyModifier(false); - } - } - ApplyStats(true); + (*i).second->ApplyModifier(false); - // these must be removed after applystats - AuraList& mModTotalStatPct = GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); - for(AuraList::iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i) - (*i)->ApplyModifier(false); - AuraList& mModResistancePct = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_PCT); - for(AuraList::iterator i = mModResistancePct.begin(); i != mModResistancePct.end(); ++i) - (*i)->ApplyModifier(false); + _ApplyStatsMods(); } void Unit::_ApplyAllAuraMods() { - // these must be applied before applystats - AuraList& mModTotalStatPct = GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); - for(AuraList::iterator i = mModTotalStatPct.begin(); i != mModTotalStatPct.end(); ++i) - (*i)->ApplyModifier(true); - AuraList& mModResistancePct = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_PCT); - for(AuraList::iterator i = mModResistancePct.begin(); i != mModResistancePct.end(); ++i) - (*i)->ApplyModifier(true); - ApplyStats(false); + _RemoveStatsMods(); for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i) - { - switch ((*i).second->GetModifier()->m_auraname) - { - case SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE: - case SPELL_AURA_MOD_RESISTANCE_PCT: - // these are already applied by applystats - break; - default: - (*i).second->ApplyModifier(true); - } - } - ApplyStats(true); + (*i).second->ApplyModifier(true); + + _ApplyStatsMods(); } // TODO: FIX-ME!!! @@ -2355,7 +2281,7 @@ if(enchant_display ==4) { - ApplyArmorMod(enchant_value1,apply); + ApplyBaseArmorMod(enchant_value1,apply); } else if(enchant_display ==2) { @@ -3273,3 +3199,94 @@ if(curPower != maxPower) SetPower(power,maxPower); } + +//#### Cascade update methods +float Unit::GetResistance(SpellSchools res) const { + return GetFloatValue(UNIT_FIELD_RESISTANCES+res) + + (GetTypeId()==TYPEID_PLAYER ? (((Player*)this)->GetResistanceBuff(res,true) - ((Player*)this)->GetResistanceBuff(res,false)) : 0); +} + +void Unit::CascadeUpdateResistance(SpellSchools res) +{ + + // base percent modifiers + float basePercentModifier = 0; + AuraList& mModBaseResistancePct = GetAurasByType(SPELL_AURA_MOD_BASE_RESISTANCE_PCT); + for(AuraList::iterator i = mModBaseResistancePct .begin(); i != mModBaseResistancePct .end(); ++i) + if((*i)->GetModifier()->m_miscvalue & int32(1<GetModifier()->m_amount; + + // total percent modifiers + float totalPercentModifier = 0; + AuraList& mModResistancePct = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_PCT); + for(AuraList::iterator i = mModResistancePct.begin(); i != mModResistancePct.end(); ++i) + if((*i)->GetModifier()->m_miscvalue & int32(1<GetModifier()->m_amount; + + float cur_res = m_BaseResistance[res]; + ApplyPercentModFloatVar(cur_res,basePercentModifier,true); + ApplyPercentModFloatVar(cur_res,totalPercentModifier,true); + + // calculate total resistance + if(GetTypeId()==TYPEID_PLAYER) + { + ((Player*)this)->UpdateResistanceBuffs(res,totalPercentModifier); + } + + SetFloatValue(UNIT_FIELD_RESISTANCES+res,cur_res); +} + +void Unit::CascadeUpdateStat(Stats stat) +{ + // temporary until not converted to cascade update + _RemoveStatsMods(); + + // base stat percent modifier + float basePercentModifier = 0; + AuraList& mModBaseStatPct = GetAurasByType(SPELL_AURA_MOD_PERCENT_STAT); + for(AuraList::iterator i = mModBaseStatPct.begin(); i != mModBaseStatPct.end(); ++i) + if((*i)->GetModifier()->m_miscvalue & int32(1<GetModifier()->m_amount; + + // total stat modifier + float totalPercentModifier = 0; + AuraList& mModStatPct = GetAurasByType(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE); + for(AuraList::iterator i = mModStatPct .begin(); i != mModStatPct .end(); ++i) + if((*i)->GetModifier()->m_miscvalue & int32(1<GetModifier()->m_amount; + + float cur_stat = m_BaseStat[stat]; + ApplyPercentModFloatVar(cur_stat,basePercentModifier,true); + ApplyPercentModFloatVar(cur_stat,totalPercentModifier,true); + + float stat_delta = 0; + + // calculate total resistance + if(GetTypeId()==TYPEID_PLAYER) + { + + stat_delta = -(GetStat(stat) - ((Player*)this)->GetCreateStat(stat)); + + ((Player*)this)->UpdateStatsBuffs(stat,totalPercentModifier); + + cur_stat += ((Player*)this)->GetPosStat(stat) - ((Player*)this)->GetNegStat(stat); + + stat_delta += cur_stat - ((Player*)this)->GetCreateStat(stat); + } + + SetFloatValue(UNIT_FIELD_STATS+stat,cur_stat); + + switch(stat) + { + case STAT_AGILITY: ApplyBaseArmorMod(2*stat_delta,true); break; + case STAT_STAMINA: ApplyMaxHealthMod(int32(10*stat_delta),true); break; + case STAT_INTELLECT: + if(getClass() != WARRIOR && getClass() != ROGUE) + ApplyMaxPowerMod(POWER_MANA,int32(10*stat_delta),true); + break; + } + + + // temporary until not converted to cascade update + _ApplyStatsMods(); +} Index: src/game/Unit.h =================================================================== --- src/game/Unit.h (revision 2652) +++ src/game/Unit.h (working copy) @@ -389,27 +389,12 @@ uint32 getClassMask() const { return 1 << (getClass()-1); }; uint8 getGender() const { return (uint8)((GetUInt32Value(UNIT_FIELD_BYTES_0) >> 16) & 0xFF); }; - float GetStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_STATS+stat); } - void SetStat(Stats stat, float val) { SetFloatValue(UNIT_FIELD_STATS+stat, val); } - void ApplyStatMod(Stats stat, float val, bool apply) { ApplyModFloatValue(UNIT_FIELD_STATS+stat, val, apply); } - void ApplyStatPercentMod(Stats stat, float val, bool apply) { ApplyPercentModFloatValue(UNIT_FIELD_STATS+stat, val, apply); } - - float GetArmor() const { return GetResistance(SPELL_SCHOOL_NORMAL) ; } - void SetArmor(float val) { SetResistance(SPELL_SCHOOL_NORMAL, val); } - void ApplyArmorMod(float val, bool apply) { ApplyResistanceMod(SPELL_SCHOOL_NORMAL, val, apply); } - void ApplyArmorPercentMod(float val, bool apply) { ApplyResistancePercentMod(SPELL_SCHOOL_NORMAL, val, apply); } - - float GetResistance(SpellSchools school) const { return GetFloatValue(UNIT_FIELD_RESISTANCES+school); } - void SetResistance(SpellSchools school, float val) { SetFloatValue(UNIT_FIELD_RESISTANCES+school,val); } - void ApplyResistanceMod(SpellSchools school, float val, bool apply) { ApplyModFloatValue(UNIT_FIELD_RESISTANCES+school, val, apply); } - void ApplyResistancePercentMod(SpellSchools school, float val, bool apply) { ApplyPercentModFloatValue(UNIT_FIELD_RESISTANCES+school, val, apply); } - uint32 GetHealth() const { return GetUInt32Value(UNIT_FIELD_HEALTH); } uint32 GetMaxHealth() const { return (uint32)GetFloatValue(UNIT_FIELD_MAXHEALTH); } void SetHealth( uint32 val) { SetUInt32Value(UNIT_FIELD_HEALTH,val); } void SetMaxHealth(uint32 val) { SetFloatValue(UNIT_FIELD_MAXHEALTH,val); } void ModifyHealth(int32 val); - void ApplyMaxHealthMod(uint32 val, bool apply) { ApplyModFloatValue(UNIT_FIELD_MAXHEALTH, val, apply); } + void ApplyMaxHealthMod(int32 val, bool apply) { ApplyModFloatValue(UNIT_FIELD_MAXHEALTH, val, apply); } void ApplyMaxHealthPercentMod(float val, bool apply) { ApplyPercentModFloatValue(UNIT_FIELD_MAXHEALTH, val, apply); } Powers getPowerType() const { return Powers((GetUInt32Value(UNIT_FIELD_BYTES_0) >> 24) & 0xFF); }; @@ -419,9 +404,9 @@ void SetPower( Powers power, uint32 val) { SetFloatValue(UNIT_FIELD_POWER1 +power,val); } void SetMaxPower(Powers power, uint32 val) { SetFloatValue(UNIT_FIELD_MAXPOWER1+power,val); } void ModifyPower(Powers power, int32 val); - void ApplyPowerMod(Powers power, uint32 val, bool apply) { ApplyModFloatValue(UNIT_FIELD_POWER1+power, val, apply); } + void ApplyPowerMod(Powers power, int32 val, bool apply) { ApplyModFloatValue(UNIT_FIELD_POWER1+power, val, apply); } void ApplyPowerPercentMod(Powers power, float val, bool apply) { ApplyPercentModFloatValue(UNIT_FIELD_POWER1+power, val, apply); } - void ApplyMaxPowerMod(Powers power, uint32 val, bool apply) { ApplyModFloatValue(UNIT_FIELD_MAXPOWER1+power, val, apply); } + void ApplyMaxPowerMod(Powers power, int32 val, bool apply) { ApplyModFloatValue(UNIT_FIELD_MAXPOWER1+power, val, apply); } void ApplyMaxPowerPercentMod(Powers power, float val, bool apply) { ApplyPercentModFloatValue(UNIT_FIELD_MAXPOWER1+power, val, apply); } uint32 GetAttackTime(WeaponAttackType att) const { return (uint32)GetFloatValue(UNIT_FIELD_BASEATTACKTIME+att); } @@ -629,7 +614,6 @@ uint32 CalculateDamage(WeaponAttackType attType); void SetStateFlag(uint32 index, uint32 newFlag ); void RemoveStateFlag(uint32 index, uint32 oldFlag ); - void ApplyStats(bool apply); void UnsummonTotem(int8 slot = -1); uint32 SpellDamageBonus(Unit *pVictim, SpellEntry *spellProto, uint32 damage); uint32 SpellHealingBonus(SpellEntry *spellProto, uint32 healamount); @@ -637,11 +621,28 @@ void MeleeDamageBonus(Unit *pVictim, uint32 *damage); void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply); + void _RemoveStatsMods(); + void _ApplyStatsMods(); + + //// Cascade Update System ///////////////////////// + // Stats + float GetStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_STATS+stat); } + void SetBaseStat(Stats stat, float value) { m_BaseStat[stat] = value; CascadeUpdateStat(stat); } + void ApplyBaseStatMod(Stats stat, float addvalue, bool apply) { m_BaseStat[stat] += (apply ? addvalue : -addvalue); CascadeUpdateStat(stat); } + void CascadeUpdateStat(Stats stat); + + // Resistance + float GetArmor() const { return GetResistance(SPELL_SCHOOL_NORMAL) ; } + float GetResistance(SpellSchools school) const; + void SetBaseArmor(float addvalue) { SetBaseResistance(SPELL_SCHOOL_NORMAL,addvalue); } + void ApplyBaseArmorMod(float addvalue,bool apply) { ApplyBaseResistanceMod(SPELL_SCHOOL_NORMAL,addvalue,apply); } + void SetBaseResistance(SpellSchools res,float value) { m_BaseResistance[res] = value; CascadeUpdateResistance(res); } + void ApplyBaseResistanceMod(SpellSchools res,float addvalue,bool apply) { m_BaseResistance[res] += (apply ? addvalue : -addvalue); CascadeUpdateResistance(res); } + void CascadeUpdateResistance(SpellSchools res); protected: Unit ( ); - void _RemoveStatsMods(); - void _ApplyStatsMods(); + void _ApplyStats(bool apply); void _RemoveAllAuraMods(); void _ApplyAllAuraMods(); @@ -673,6 +674,9 @@ long m_AuraModifiers[TOTAL_AURAS]; //std::list< spellEffectPair > AuraSpells[TOTAL_AURAS]; // TODO: use this if ok for mem + //// Cascade Update System ///////////////////////// + float m_BaseStat[MAX_STATS]; // Base Stats (with not applied percent modifiers) + float m_BaseResistance[SPELL_SCHOOL_COUNT]; // Base Resistance (with not applied percent modifiers) private: void SendAttackStop(Unit* victim); // only from AttackStop(Unit*) void SendAttackStart(Unit* pVictim); // only from Unit::AttackStart(Unit*)