From f53d06ad70fa06fba53021b6236d23c0dfd08a81 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 8 May 2009 16:43:52 +0400 Subject: [PATCH 1/4] [7801] Apply damage mods from scripts or target state not in DealDamage but in new function before send data to client. * Fixed bug with health decrease (client side visual bug) at spell damage by target with AI::DamageTaken damage set to 0 * Fixed bug with ignore .die command and instant kill damage in some cases. --- src/game/Level3.cpp | 22 +++++++------ src/game/Player.cpp | 2 ++ src/game/Spell.cpp | 1 + src/game/SpellAuras.cpp | 12 +++++-- src/game/SpellEffects.cpp | 3 +- src/game/Unit.cpp | 68 +++++++++++++++++++++++++++++---------- src/game/Unit.h | 1 + src/shared/revision_nr.h | 2 +- 8 files changed, 80 insertions(+), 31 deletions(-) diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 2cccc2e56..e71727a1d 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3418,31 +3418,34 @@ bool ChatHandler::HandleDamageCommand(const char * args) Unit* target = getSelectedUnit(); - if(!target || !m_session->GetPlayer()->GetSelection()) + if (!target || !m_session->GetPlayer()->GetSelection()) { SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); SetSentErrorMessage(true); return false; } - if( !target->isAlive() ) + if (!target->isAlive()) return true; char* damageStr = strtok((char*)args, " "); - if(!damageStr) + if (!damageStr) return false; - int32 damage = atoi((char*)damageStr); - if(damage <=0) + int32 damage_int = atoi((char*)damageStr); + if(damage_int <=0) return true; + uint32 damage = damage_int; + char* schoolStr = strtok((char*)NULL, " "); // flat melee damage without resistence/etc reduction - if(!schoolStr) + if (!schoolStr) { m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); + if (target != m_session->GetPlayer()) + m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, SPELL_SCHOOL_MASK_NORMAL, damage, 0, 0, VICTIMSTATE_NORMAL, 0); return true; } @@ -3458,7 +3461,7 @@ bool ChatHandler::HandleDamageCommand(const char * args) char* spellStr = strtok((char*)NULL, " "); // melee damage by specific school - if(!spellStr) + if (!spellStr) { uint32 absorb = 0; uint32 resist = 0; @@ -3470,6 +3473,7 @@ bool ChatHandler::HandleDamageCommand(const char * args) damage -= absorb + resist; + m_session->GetPlayer()->DealDamageMods(target,damage,&absorb); m_session->GetPlayer()->DealDamage(target, damage, NULL, DIRECT_DAMAGE, schoolmask, NULL, false); m_session->GetPlayer()->SendAttackStateUpdate (HITINFO_NORMALSWING2, target, 1, schoolmask, damage, absorb, resist, VICTIMSTATE_NORMAL, 0); return true; @@ -3479,7 +3483,7 @@ bool ChatHandler::HandleDamageCommand(const char * args) // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form uint32 spellid = extractSpellIdFromLink((char*)args); - if(!spellid || !sSpellStore.LookupEntry(spellid)) + if (!spellid || !sSpellStore.LookupEntry(spellid)) return false; m_session->GetPlayer()->SpellNonMeleeDamageLog(target, spellid, damage); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e8f2e3ab2..818694f60 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -846,6 +846,8 @@ void Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage) damage-=absorb+resist; + DealDamageMods(this,damage,&absorb); + WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21)); data << uint64(GetGUID()); data << uint8(type!=DAMAGE_FALL_TO_VOID ? type : DAMAGE_FALL); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index a5c856db4..ba99e4c6c 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1056,6 +1056,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) // Add bonuses and fill damageInfo struct caster->CalculateSpellDamage(&damageInfo, m_damage, m_spellInfo); + caster->DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb); // Send log damage message to client caster->SendSpellNonMeleeDamageLog(&damageInfo); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index c60b551eb..3f9e9a02a 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -5806,6 +5806,8 @@ void Aura::PeriodicTick() sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); + pCaster->DealDamageMods(m_target,pdamage,&absorb); + WorldPacket data(SMSG_PERIODICAURALOG, (21+16));// we guess size data.append(m_target->GetPackGUID()); data.appendPackGUID(GetCasterGUID()); @@ -5984,10 +5986,13 @@ void Aura::PeriodicTick() } else { - pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), gain, GetSpellSchoolMask(GetSpellProto()), 0, 0, false, 0, false); + uint32 damage = gain; + uint32 absorb = 0; + pCaster->DealDamageMods(pCaster,damage,&absorb); + pCaster->SendSpellNonMeleeDamageLog(pCaster, GetId(), damage, GetSpellSchoolMask(GetSpellProto()), absorb, 0, false, 0, false); CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); - pCaster->DealDamage(pCaster, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true); + pCaster->DealDamage(pCaster, damage, &cleanDamage, NODAMAGE, GetSpellSchoolMask(GetSpellProto()), GetSpellProto(), true); } } @@ -6169,6 +6174,9 @@ void Aura::PeriodicTick() //maybe has to be sent different to client, but not by SMSG_PERIODICAURALOG SpellNonMeleeDamage damageInfo(pCaster, m_target, spellProto->Id, spellProto->SchoolMask); pCaster->CalculateSpellDamage(&damageInfo, gain, spellProto); + + pCaster->DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb); + pCaster->SendSpellNonMeleeDamageLog(&damageInfo); // Set trigger flag diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 95ccc7590..ba57067b8 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -279,8 +279,7 @@ void Spell::EffectInstaKill(uint32 /*i*/) if(m_caster==unitTarget) // prevent interrupt message finish(); - uint32 health = unitTarget->GetHealth(); - m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } void Spell::EffectEnvirinmentalDMG(uint32 i) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 9e9b78640..5ea368169 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -367,10 +367,15 @@ void Unit::RemoveSpellbyDamageTaken(AuraType auraType, uint32 damage) RemoveSpellsCausingAura(auraType); } -uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss) +void Unit::DealDamageMods(Unit *pVictim, uint32 &damage, uint32* absorb) { if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) - return 0; + { + if(absorb) + absorb += damage; + damage = 0; + return; + } //You don't lose health from damage taken from another player while in a sanctuary //You still see it in the combat log though @@ -378,9 +383,28 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa { const AreaTableEntry *area = GetAreaEntryByAreaID(pVictim->GetAreaId()); if(area && area->flags & AREA_FLAG_SANCTUARY) //sanctuary - return 0; + { + if(absorb) + absorb += damage; + damage = 0; + } } + uint32 originalDamage = damage; + + //Script Event damage Deal + if( GetTypeId()== TYPEID_UNIT && ((Creature *)this)->AI()) + ((Creature *)this)->AI()->DamageDeal(pVictim, damage); + //Script Event damage taken + if( pVictim->GetTypeId()== TYPEID_UNIT && ((Creature *)pVictim)->AI() ) + ((Creature *)pVictim)->AI()->DamageTaken(this, damage); + + if(absorb && originalDamage > damage) + absorb += (originalDamage - damage); +} + +uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss) +{ // remove affects from victim (including from 0 damage and DoTs) if(pVictim != this) pVictim->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); @@ -398,13 +422,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa pVictim->SetStandState(UNIT_STAND_STATE_STAND); } - //Script Event damage Deal - if( GetTypeId()== TYPEID_UNIT && ((Creature *)this)->AI()) - ((Creature *)this)->AI()->DamageDeal(pVictim, damage); - //Script Event damage taken - if( pVictim->GetTypeId()== TYPEID_UNIT && ((Creature *)pVictim)->AI() ) - ((Creature *)pVictim)->AI()->DamageTaken(this, damage); - if(!damage) { // Rage from physical damage received . @@ -978,6 +995,7 @@ uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); SpellNonMeleeDamage damageInfo(this, pVictim, spellInfo->Id, spellInfo->SchoolMask); CalculateSpellDamage(&damageInfo, damage, spellInfo); + DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb); SendSpellNonMeleeDamageLog(&damageInfo); DealSpellDamage(&damageInfo, true); return damageInfo.damage; @@ -1507,6 +1525,8 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) //CalcAbsorbResist(pVictim, SpellSchools(spellProto->School), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); //damage-=absorb + resist; + pVictim->DealDamageMods(this,damage,NULL); + WorldPacket data(SMSG_SPELLDAMAGESHIELD,(8+8+4+4+4+4)); data << uint64(pVictim->GetGUID()); data << uint64(GetGUID()); @@ -1802,8 +1822,12 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe int32 canabsorb = caster->GetHealth(); if (canabsorb < absorbed) absorbed = canabsorb; - DealDamage(caster, absorbed, NULL, damagetype, schoolMask, 0, false); + RemainingDamage -= absorbed; + + uint32 ab_damage = absorbed; + DealDamageMods(caster,ab_damage,NULL); + DealDamage(caster, ab_damage, NULL, damagetype, schoolMask, 0, false); continue; } break; @@ -1907,10 +1931,15 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe RemainingDamage -= currentAbsorb; - SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, currentAbsorb, schoolMask, 0, 0, false, 0, false); - CleanDamage cleanDamage = CleanDamage(currentAbsorb, BASE_ATTACK, MELEE_HIT_NORMAL); - DealDamage(caster, currentAbsorb, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); + uint32 splitted = currentAbsorb; + uint32 splitted_absorb = 0; + DealDamageMods(caster,splitted,&splitted_absorb); + + SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, splitted_absorb, 0, false, 0, false); + + CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL); + DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); } AuraList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT); @@ -1927,11 +1956,14 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe if(!caster || caster == pVictim || !caster->IsInWorld() || !caster->isAlive()) continue; - int32 splitted = int32(RemainingDamage * (*i)->GetModifier()->m_amount / 100.0f); + uint32 splitted = uint32(RemainingDamage * (*i)->GetModifier()->m_amount / 100.0f); - RemainingDamage -= splitted; + RemainingDamage -= int32(splitted); - SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, 0, 0, false, 0, false); + uint32 split_absorb = 0; + DealDamageMods(caster,splitted,&split_absorb); + + SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, schoolMask, split_absorb, 0, false, 0, false); CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL); DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, schoolMask, (*i)->GetSpellProto(), false); @@ -2021,6 +2053,7 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex CalcDamageInfo damageInfo; CalculateMeleeDamage(pVictim, 0, &damageInfo, attType); // Send log damage message to client + DealDamageMods(pVictim,damageInfo.damage,&damageInfo.absorb); SendAttackStateUpdate(&damageInfo); ProcDamageAndSpell(damageInfo.target, damageInfo.procAttacker, damageInfo.procVictim, damageInfo.procEx, damageInfo.damage, damageInfo.attackType); DealMeleeDamage(&damageInfo,true); @@ -10649,6 +10682,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag sLog.outDebug("ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", auraModifier->m_amount, spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); SpellNonMeleeDamage damageInfo(this, pTarget, spellInfo->Id, spellInfo->SchoolMask); CalculateSpellDamage(&damageInfo, auraModifier->m_amount, spellInfo); + DealDamageMods(damageInfo.target,damageInfo.damage,&damageInfo.absorb); SendSpellNonMeleeDamageLog(&damageInfo); DealSpellDamage(&damageInfo, true); break; diff --git a/src/game/Unit.h b/src/game/Unit.h index 2a3a05374..9ea6ca3e6 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -952,6 +952,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void Unmount(); uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } + void DealDamageMods(Unit *pVictim, uint32 &damage, uint32* absorb); uint32 DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss); int32 DealHeal(Unit *pVictim, uint32 addhealth, SpellEntry const *spellProto, bool critical = false); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a8f60cc0f..bc98b3ab8 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7800" + #define REVISION_NR "7801" #endif // __REVISION_NR_H__ From fffaec6d71ee987d04b231eb6b9b08059ede5594 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 8 May 2009 19:15:46 +0400 Subject: [PATCH 2/4] [7802] Use more appropriate field types in `character_achievement*` tables. Better check data at loading. --- sql/characters.sql | 16 +++++----- ...02_01_characters_character_achievement.sql | 6 ++++ ...racters_character_achievement_progress.sql | 7 +++++ sql/updates/Makefile.am | 4 +++ src/game/AchievementMgr.cpp | 31 +++++++++++++++++-- src/shared/revision_nr.h | 2 +- 6 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 sql/updates/7802_01_characters_character_achievement.sql create mode 100644 sql/updates/7802_02_characters_character_achievement_progress.sql diff --git a/sql/characters.sql b/sql/characters.sql index f59862449..c6f18a193 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -21,7 +21,7 @@ DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_7644_01_characters_character_pet` bit(1) default NULL + `required_7802_02_characters_character_achievement_progress` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- @@ -253,9 +253,9 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `character_achievement`; CREATE TABLE `character_achievement` ( - `guid` int(11) NOT NULL, - `achievement` int(11) NOT NULL, - `date` int(11) NOT NULL, + `guid` int(11) unsigned NOT NULL, + `achievement` int(11) unsigned NOT NULL, + `date` bigint(11) unsigned NOT NULL default '0', PRIMARY KEY (`guid`,`achievement`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; @@ -274,10 +274,10 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `character_achievement_progress`; CREATE TABLE `character_achievement_progress` ( - `guid` int(11) NOT NULL, - `criteria` int(11) NOT NULL, - `counter` int(11) NOT NULL, - `date` int(11) NOT NULL, + `guid` int(11) unsigned NOT NULL, + `criteria` int(11) unsigned NOT NULL, + `counter` int(11) unsigned NOT NULL, + `date` bigint(11) unsigned NOT NULL default '0', PRIMARY KEY (`guid`,`criteria`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; diff --git a/sql/updates/7802_01_characters_character_achievement.sql b/sql/updates/7802_01_characters_character_achievement.sql new file mode 100644 index 000000000..774d1f6b3 --- /dev/null +++ b/sql/updates/7802_01_characters_character_achievement.sql @@ -0,0 +1,6 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_7644_01_characters_character_pet required_7802_01_characters_character_achievement bit; + +ALTER TABLE character_achievement + CHANGE COLUMN guid guid int(11) unsigned NOT NULL, + CHANGE COLUMN achievement achievement int(11) unsigned NOT NULL, + CHANGE COLUMN date date bigint(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/7802_02_characters_character_achievement_progress.sql b/sql/updates/7802_02_characters_character_achievement_progress.sql new file mode 100644 index 000000000..318a430ac --- /dev/null +++ b/sql/updates/7802_02_characters_character_achievement_progress.sql @@ -0,0 +1,7 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_7802_01_characters_character_achievement required_7802_02_characters_character_achievement_progress bit; + +ALTER TABLE character_achievement_progress + CHANGE COLUMN guid guid int(11) unsigned NOT NULL, + CHANGE COLUMN criteria criteria int(11) unsigned NOT NULL, + CHANGE COLUMN counter counter int(11) unsigned NOT NULL, + CHANGE COLUMN date date bigint(11) unsigned NOT NULL default '0'; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index c7e40654d..499016c4b 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -182,6 +182,8 @@ pkgdata_DATA = \ 7782_01_mangos_spell_proc_event.sql \ 7796_01_mangos_command.sql \ 7796_02_mangos_mangos_string.sql \ + 7802_01_characters_character_achievement.sql \ + 7802_02_characters_character_achievement_progress.sql \ README ## Additional files to include when running 'make dist' @@ -344,4 +346,6 @@ EXTRA_DIST = \ 7782_01_mangos_spell_proc_event.sql \ 7796_01_mangos_command.sql \ 7796_02_mangos_mangos_string.sql \ + 7802_01_characters_character_achievement.sql \ + 7802_02_characters_character_achievement_progress.sql \ README diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 12bca0ed5..6c6620465 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -407,7 +407,14 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri do { Field *fields = achievementResult->Fetch(); - CompletedAchievementData& ca = m_completedAchievements[fields[0].GetUInt32()]; + + uint32 achievement_id = fields[0].GetUInt32(); + + // don't must happen: cleanup at server startup in achievementmgr.LoadCompletedAchievements() + if(!sAchievementStore.LookupEntry(achievement_id)) + continue; + + CompletedAchievementData& ca = m_completedAchievements[achievement_id]; ca.date = time_t(fields[1].GetUInt64()); ca.changed = false; } while(achievementResult->NextRow()); @@ -425,7 +432,15 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri time_t date = time_t(fields[2].GetUInt64()); AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(id); - if (!criteria || (criteria->timeLimit && time_t(date + criteria->timeLimit) < time(NULL))) + if (!criteria) + { + // we will remove not existed criteria for all characters + sLog.outError("Not existed achievement creataria %u data removed from table `character_achievement_progress`.",id); + CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE criteria = %u",id); + continue; + } + + if (criteria->timeLimit && time_t(date + criteria->timeLimit) < time(NULL)) continue; CriteriaProgress& progress = m_criteriaProgress[id]; @@ -1763,7 +1778,17 @@ void AchievementGlobalMgr::LoadCompletedAchievements() { bar.step(); Field *fields = result->Fetch(); - m_allCompletedAchievements.insert(fields[0].GetUInt32()); + + uint32 achievement_id = fields[0].GetUInt32(); + if(!sAchievementStore.LookupEntry(achievement_id)) + { + // we will remove not existed achievement for all characters + sLog.outError("Not existed achievement %u data removed from table `character_achievement`.",achievement_id); + CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE achievement = %u",achievement_id); + continue; + } + + m_allCompletedAchievements.insert(achievement_id); } while(result->NextRow()); delete result; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index bc98b3ab8..9fe69ba29 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7801" + #define REVISION_NR "7802" #endif // __REVISION_NR_H__ From 3c057a92f543e5ad021da4a1b18f97b21b86e964 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 8 May 2009 21:31:34 +0400 Subject: [PATCH 3/4] [7803] Prevent ignore max money limit at use .modify money command. --- src/game/Level1.cpp | 15 +++++++++++---- src/shared/revision_nr.h | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 0d7e44510..79b9ab1c5 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -1681,12 +1681,12 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args) uint32 moneyuser = chr->GetMoney(); - if(addmoney < 0) + if (addmoney < 0) { - int32 newmoney = moneyuser + addmoney; + int32 newmoney = int32(moneyuser) + addmoney; sLog.outDetail(GetMangosString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney); - if(newmoney <= 0 ) + if (newmoney <= 0 ) { PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) @@ -1696,6 +1696,9 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args) } else { + if (newmoney > MAX_MONEY_AMOUNT) + newmoney = MAX_MONEY_AMOUNT; + PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), GetNameLink(chr).c_str()); if (needReportToTarget(chr)) ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetNameLink().c_str(), abs(addmoney)); @@ -1707,7 +1710,11 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args) PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetNameLink().c_str(), addmoney); - chr->ModifyMoney( addmoney ); + + if (addmoney >=MAX_MONEY_AMOUNT) + chr->SetMoney(MAX_MONEY_AMOUNT); + else + chr->ModifyMoney( addmoney ); } sLog.outDetail(GetMangosString(LANG_NEW_MONEY), moneyuser, addmoney, chr->GetMoney() ); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 9fe69ba29..64e83df23 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7802" + #define REVISION_NR "7803" #endif // __REVISION_NR_H__ From 7204f83a558b3d6e98d68680e0285862b18da480 Mon Sep 17 00:00:00 2001 From: Foks Date: Sat, 9 May 2009 15:06:28 +0400 Subject: [PATCH 4/4] [7804] Allow swap and move by bag slots equipped ammopouch and quiver Signed-off-by: VladimirMangos --- src/game/Player.cpp | 15 +++++++++------ src/shared/revision_nr.h | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 818694f60..f129320df 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -9570,14 +9570,17 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo { if( Item* pBag = GetItemByPos( INVENTORY_SLOT_BAG_0, i ) ) { - if( ItemPrototype const* pBagProto = pBag->GetProto() ) + if( pBag != pItem ) { - if( pBagProto->Class==pProto->Class && (!swap || pBag->GetSlot() != eslot ) ) + if( ItemPrototype const* pBagProto = pBag->GetProto() ) { - if(pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH) - return EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH; - else - return EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER; + if( pBagProto->Class==pProto->Class && (!swap || pBag->GetSlot() != eslot ) ) + { + if(pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH) + return EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH; + else + return EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER; + } } } } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 64e83df23..cdecaf091 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7803" + #define REVISION_NR "7804" #endif // __REVISION_NR_H__