From 2b9eeb782e7600469d4aeea94c58314f8f45ca48 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 1 Mar 2009 05:09:35 +0300 Subject: [PATCH 01/28] [7362] Use IN_MILISECONDS where appropriate, other cleanups. --- src/game/AuctionHouseMgr.cpp | 34 ++++++++++++------------- src/game/BattleGroundEY.h | 4 +-- src/game/BattleGroundWS.h | 4 +-- src/game/Creature.cpp | 12 ++++----- src/game/GameEvent.cpp | 2 +- src/game/GridDefines.h | 2 +- src/game/Level0.cpp | 2 +- src/game/MiscHandler.cpp | 2 +- src/game/Pet.cpp | 2 +- src/game/PetAI.cpp | 2 +- src/game/Player.cpp | 47 +++++++++++++++++----------------- src/game/Player.h | 4 +-- src/game/Spell.cpp | 8 +++--- src/game/Spell.h | 2 +- src/game/SpellAuras.cpp | 49 ++++++++++++++++++------------------ src/game/SpellEffects.cpp | 24 +++++++++--------- src/game/SpellMgr.h | 7 ++++++ src/game/Unit.cpp | 4 +-- src/game/Weather.cpp | 2 +- src/game/World.cpp | 15 +++++------ src/shared/Common.h | 1 + src/shared/revision_nr.h | 2 +- 22 files changed, 120 insertions(+), 111 deletions(-) diff --git a/src/game/AuctionHouseMgr.cpp b/src/game/AuctionHouseMgr.cpp index b5370c19b..de7518c8f 100644 --- a/src/game/AuctionHouseMgr.cpp +++ b/src/game/AuctionHouseMgr.cpp @@ -630,29 +630,29 @@ bool AuctionEntry::BuildAuctionInfo(WorldPacket & data) const sLog.outError("auction to item, that doesn't exist !!!!"); return false; } - data << (uint32) Id; - data << (uint32) pItem->GetEntry(); + data << uint32(Id); + data << uint32(pItem->GetEntry()); for (uint8 i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; i++) { - data << (uint32) pItem->GetEnchantmentId(EnchantmentSlot(i)); - data << (uint32) pItem->GetEnchantmentDuration(EnchantmentSlot(i)); - data << (uint32) pItem->GetEnchantmentCharges(EnchantmentSlot(i)); + data << uint32(pItem->GetEnchantmentId(EnchantmentSlot(i))); + data << uint32(pItem->GetEnchantmentDuration(EnchantmentSlot(i))); + data << uint32(pItem->GetEnchantmentCharges(EnchantmentSlot(i))); } - data << (uint32) pItem->GetItemRandomPropertyId(); //random item property id - data << (uint32) pItem->GetItemSuffixFactor(); //SuffixFactor - data << (uint32) pItem->GetCount(); //item->count - data << (uint32) pItem->GetSpellCharges(); //item->charge FFFFFFF - data << (uint32) 0; //Unknown - data << (uint64) owner; //Auction->owner - data << (uint32) startbid; //Auction->startbid (not sure if useful) - data << (uint32) (bid ? GetAuctionOutBid() : 0); + data << uint32(pItem->GetItemRandomPropertyId()); //random item property id + data << uint32(pItem->GetItemSuffixFactor()); //SuffixFactor + data << uint32(pItem->GetCount()); //item->count + data << uint32(pItem->GetSpellCharges()); //item->charge FFFFFFF + data << uint32(0); //Unknown + data << uint32(owner); //Auction->owner + data << uint32(startbid); //Auction->startbid (not sure if useful) + data << uint32(bid ? GetAuctionOutBid() : 0); //minimal outbid - data << (uint32) buyout; //auction->buyout - data << (uint32) (expire_time - time(NULL))* 1000; //time left - data << (uint64) bidder; //auction->bidder current - data << (uint32) bid; //current bid + data << uint32(buyout); //auction->buyout + data << uint32((expire_time-time(NULL))*IN_MILISECONDS);//time left + data << uint64(bidder) ; //auction->bidder current + data << uint32(bid); //current bid return true; } diff --git a/src/game/BattleGroundEY.h b/src/game/BattleGroundEY.h index 5db6a796b..700efe20a 100644 --- a/src/game/BattleGroundEY.h +++ b/src/game/BattleGroundEY.h @@ -24,8 +24,8 @@ class BattleGround; #define EY_MAX_TEAM_SCORE 2000 -#define BG_EY_FLAG_RESPAWN_TIME 10000 //10 seconds -#define BG_EY_FPOINTS_TICK_TIME 2000 //2 seconds +#define BG_EY_FLAG_RESPAWN_TIME (10*IN_MILISECONDS) //10 seconds +#define BG_EY_FPOINTS_TICK_TIME (2*IN_MILISECONDS) //2 seconds enum BG_EY_WorldStates { diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h index 281d182d5..f36834f65 100644 --- a/src/game/BattleGroundWS.h +++ b/src/game/BattleGroundWS.h @@ -22,8 +22,8 @@ #include "BattleGround.h" #define BG_WS_MAX_TEAM_SCORE 3 -#define BG_WS_FLAG_RESPAWN_TIME 23000 -#define BG_WS_FLAG_DROP_TIME 10000 +#define BG_WS_FLAG_RESPAWN_TIME (23*IN_MILISECONDS) +#define BG_WS_FLAG_DROP_TIME (10*IN_MILISECONDS) enum BG_WS_Sound { diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 32ab79c6a..bfdd2d58a 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1450,7 +1450,7 @@ void Creature::setDeathState(DeathState s) { if((s == JUST_DIED && !m_isDeadByDefault)||(s == JUST_ALIVED && m_isDeadByDefault)) { - m_deathTimer = m_corpseDelay*1000; + m_deathTimer = m_corpseDelay*IN_MILISECONDS; // always save boss respawn time at death to prevent crash cheating if(sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY) || isWorldBoss()) @@ -1756,7 +1756,7 @@ void Creature::SaveRespawnTime() if(m_respawnTime > time(NULL)) // dead (no corpse) objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),m_respawnTime); else if(m_deathTimer > 0) // dead (corpse) - objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),time(NULL)+m_respawnDelay+m_deathTimer/1000); + objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),time(NULL)+m_respawnDelay+m_deathTimer/IN_MILISECONDS); } bool Creature::IsOutOfThreatArea(Unit* pVictim) const @@ -1877,7 +1877,7 @@ void Creature::AddCreatureSpellCooldown(uint32 spellid) uint32 cooldown = GetSpellRecoveryTime(spellInfo); if(cooldown) - _AddCreatureSpellCooldown(spellid, time(NULL) + cooldown/1000); + _AddCreatureSpellCooldown(spellid, time(NULL) + cooldown/IN_MILISECONDS); if(spellInfo->Category) _AddCreatureCategoryCooldown(spellInfo->Category, time(NULL)); @@ -1896,7 +1896,7 @@ bool Creature::HasCategoryCooldown(uint32 spell_id) const return true; CreatureSpellCooldowns::const_iterator itr = m_CreatureCategoryCooldowns.find(spellInfo->Category); - return(itr != m_CreatureCategoryCooldowns.end() && time_t(itr->second + (spellInfo->CategoryRecoveryTime / 1000)) > time(NULL)); + return(itr != m_CreatureCategoryCooldowns.end() && time_t(itr->second + (spellInfo->CategoryRecoveryTime / IN_MILISECONDS)) > time(NULL)); } bool Creature::HasSpellCooldown(uint32 spell_id) const @@ -1925,7 +1925,7 @@ time_t Creature::GetRespawnTimeEx() const if(m_respawnTime > now) // dead (no corpse) return m_respawnTime; else if(m_deathTimer > 0) // dead (corpse) - return now+m_respawnDelay+m_deathTimer/1000; + return now+m_respawnDelay+m_deathTimer/IN_MILISECONDS; else return now; } @@ -1967,7 +1967,7 @@ void Creature::AllLootRemovedFromCorpse() // corpse was not skinnable -> apply corpse looted timer if (!cinfo || !cinfo->SkinLootId) - nDeathTimer = (uint32)((m_corpseDelay * 1000) * sWorld.getRate(RATE_CORPSE_DECAY_LOOTED)); + nDeathTimer = (uint32)((m_corpseDelay * IN_MILISECONDS) * sWorld.getRate(RATE_CORPSE_DECAY_LOOTED)); // corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update else nDeathTimer = 0; diff --git a/src/game/GameEvent.cpp b/src/game/GameEvent.cpp index 464083499..2504f454f 100644 --- a/src/game/GameEvent.cpp +++ b/src/game/GameEvent.cpp @@ -447,7 +447,7 @@ uint32 GameEvent::Update() // return the next e nextEventDelay = calcDelay; } sLog.outBasic("Next game event check in %u seconds.", nextEventDelay + 1); - return (nextEventDelay + 1) * 1000; // Add 1 second to be sure event has started/stopped at next call + return (nextEventDelay + 1) * IN_MILISECONDS; // Add 1 second to be sure event has started/stopped at next call } void GameEvent::UnApplyEvent(uint16 event_id) diff --git a/src/game/GridDefines.h b/src/game/GridDefines.h index ee05d069a..e1fdbc6b1 100644 --- a/src/game/GridDefines.h +++ b/src/game/GridDefines.h @@ -38,7 +38,7 @@ class Player; #define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2) -#define MIN_GRID_DELAY MINUTE*1000 +#define MIN_GRID_DELAY (MINUTE*IN_MILISECONDS) #define MIN_MAP_UPDATE_DELAY 50 #define MAX_NUMBER_OF_CELLS 8 diff --git a/src/game/Level0.cpp b/src/game/Level0.cpp index b7338a07f..15e0747e7 100644 --- a/src/game/Level0.cpp +++ b/src/game/Level0.cpp @@ -145,7 +145,7 @@ bool ChatHandler::HandleSaveCommand(const char* /*args*/) // save or plan save after 20 sec (logout delay) if current next save time more this value and _not_ output any messages to prevent cheat planning uint32 save_interval = sWorld.getConfig(CONFIG_INTERVAL_SAVE); - if(save_interval==0 || save_interval > 20*1000 && player->GetSaveTimer() <= save_interval - 20*1000) + if(save_interval==0 || save_interval > 20*IN_MILISECONDS && player->GetSaveTimer() <= save_interval - 20*IN_MILISECONDS) player->SaveToDB(); return true; diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 52ce0d565..5258f4778 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1125,7 +1125,7 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket&/* recv_data*/) recv_data >> guid; recv_data >> flags >> time; DEBUG_LOG("Guid " I64FMTD,guid); - DEBUG_LOG("Flags %u, time %u",flags, time/1000); + DEBUG_LOG("Flags %u, time %u",flags, time/IN_MILISECONDS); */ } diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index a66f1ccf4..7cf205f67 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -1023,7 +1023,7 @@ void Pet::_LoadSpellCooldowns() continue; data << uint32(spell_id); - data << uint32(uint32(db_time-curTime)*1000); // in m.secs + data << uint32(uint32(db_time-curTime)*IN_MILISECONDS); _AddCreatureSpellCooldown(spell_id,db_time); diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index ffc843235..424af420e 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -298,7 +298,7 @@ void PetAI::UpdateAllies() Unit* owner = i_pet.GetCharmerOrOwner(); Group *pGroup = NULL; - m_updateAlliesTimer = 10000; //update friendly targets every 10 seconds, lesser checks increase performance + m_updateAlliesTimer = 10*IN_MILISECONDS; //update friendly targets every 10 seconds, lesser checks increase performance if(!owner) return; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index b97e044b4..ca8c42850 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -62,7 +62,7 @@ #include -#define ZONE_UPDATE_INTERVAL 1000 +#define ZONE_UPDATE_INTERVAL (1*IN_MILISECONDS) #define PLAYER_SKILL_INDEX(x) (PLAYER_SKILL_INFO_1_1 + ((x)*3)) #define PLAYER_SKILL_VALUE_INDEX(x) (PLAYER_SKILL_INDEX(x)+1) @@ -363,7 +363,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) m_swingErrorMsg = 0; - m_DetectInvTimer = 1000; + m_DetectInvTimer = 1*IN_MILISECONDS; m_bgBattleGroundID = 0; m_bgTypeID = BATTLEGROUND_TYPE_NONE; @@ -813,7 +813,7 @@ void Player::StartMirrorTimer(MirrorTimerType Type, uint32 MaxValue) void Player::ModifyMirrorTimer(MirrorTimerType Type, uint32 MaxValue, uint32 CurrentValue, uint32 Regen) { if(Type==BREATH_TIMER) - m_breathTimer = ((MaxValue + 1000) - CurrentValue) / Regen; + m_breathTimer = ((MaxValue + 1*IN_MILISECONDS) - CurrentValue) / Regen; WorldPacket data(SMSG_START_MIRROR_TIMER, (21)); data << (uint32)Type; @@ -871,7 +871,7 @@ void Player::HandleDrowning() return; } - uint32 UnderWaterTime = 3*MINUTE*1000; // default duration + uint32 UnderWaterTime = 3*MINUTE*IN_MILISECONDS; // default duration AuraList const& mModWaterBreathing = GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING); for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i) @@ -883,7 +883,7 @@ void Player::HandleDrowning() if (!(m_isunderwater & UNDERWATER_WATER_TRIGGER)) { m_isunderwater|= UNDERWATER_WATER_TRIGGER; - m_breathTimer = UnderWaterTime + 1000; + m_breathTimer = UnderWaterTime + 1*IN_MILISECONDS; } //single trigger "show Breathbar" if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & UNDERWATER_WATER_BREATHB)) @@ -928,7 +928,7 @@ void Player::HandleLava() if (!(m_isunderwater & UNDERWATER_INLAVA)) { m_isunderwater|= UNDERWATER_WATER_BREATHB; - m_breathTimer = 1000; + m_breathTimer = 1*IN_MILISECONDS; } */ // Reset BreathTimer and still in the lava @@ -941,7 +941,7 @@ void Player::HandleLava() if ( !isGameMaster() ) EnvironmentalDamage(guid, DAMAGE_LAVA, damage); - m_breathTimer = 1000; + m_breathTimer = 1*IN_MILISECONDS; } } else if (!isAlive()) // Disable breath timer and reset underwater flags @@ -1261,7 +1261,7 @@ void Player::Update( uint32 p_time ) { m_drunkTimer += p_time; - if (m_drunkTimer > 10000) + if (m_drunkTimer > 10*IN_MILISECONDS) HandleSobering(); } @@ -2439,7 +2439,7 @@ void Player::SendInitialSpells() time_t cooldown = 0; time_t curTime = time(NULL); if(itr->second.end > curTime) - cooldown = (itr->second.end-curTime)*1000; + cooldown = (itr->second.end-curTime)*IN_MILISECONDS; data << uint16(itr->second.itemid); // cast item id data << uint16(sEntry->Category); // spell category @@ -3126,8 +3126,8 @@ void Player::RemoveArenaSpellCooldowns() SpellEntry const * entry = sSpellStore.LookupEntry(itr->first); // check if spellentry is present and if the cooldown is less than 15 mins if( entry && - entry->RecoveryTime <= 15 * MINUTE * 1000 && - entry->CategoryRecoveryTime <= 15 * MINUTE * 1000 ) + entry->RecoveryTime <= 15 * MINUTE * IN_MILISECONDS && + entry->CategoryRecoveryTime <= 15 * MINUTE * IN_MILISECONDS ) { // notify player WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); @@ -3898,7 +3898,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) { if(Aura* Aur = GetAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,i)) { - Aur->SetAuraDuration(delta*1000); + Aur->SetAuraDuration(delta*IN_MILISECONDS); Aur->SendAuraUpdate(false); } } @@ -3919,7 +3919,7 @@ void Player::KillPlayer() ApplyModFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTE_RELEASE_TIMER, !sMapStore.LookupEntry(GetMapId())->Instanceable()); // 6 minutes until repop at graveyard - m_deathTimer = 6*MINUTE*1000; + m_deathTimer = 6*MINUTE*IN_MILISECONDS; UpdateCorpseReclaimDelay(); // dependent at use SetDeathPvP() call before kill @@ -12635,10 +12635,10 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver ) // shared timed quest if(questGiver && questGiver->GetTypeId()==TYPEID_PLAYER) - limittime = ((Player*)questGiver)->getQuestStatusMap()[quest_id].m_timer / 1000; + limittime = ((Player*)questGiver)->getQuestStatusMap()[quest_id].m_timer / IN_MILISECONDS; AddTimedQuest( quest_id ); - questStatusData.m_timer = limittime * 1000; + questStatusData.m_timer = limittime * IN_MILISECONDS; qtime = static_cast(time(NULL)) + limittime; } else @@ -15133,7 +15133,7 @@ void Player::_LoadQuestStatus(QueryResult *result) if (quest_time <= sWorld.GetGameTime()) questStatusData.m_timer = 1; else - questStatusData.m_timer = (quest_time - sWorld.GetGameTime()) * 1000; + questStatusData.m_timer = (quest_time - sWorld.GetGameTime()) * IN_MILISECONDS; } else quest_time = 0; @@ -15840,6 +15840,7 @@ void Player::_SaveAuras() AuraMap::const_iterator itr2 = itr; // save previous spellEffectPair to db itr2--; + SpellEntry const *spellInfo = itr2->second->GetSpellProto(); //skip all auras from spells that are passive or need a shapeshift @@ -16014,11 +16015,11 @@ void Player::_SaveQuestStatus() case QUEST_NEW : CharacterDatabase.PExecute("INSERT INTO character_queststatus (guid,quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4) " "VALUES ('%u', '%u', '%u', '%u', '%u', '" I64FMTD "', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u')", - GetGUIDLow(), i->first, i->second.m_status, i->second.m_rewarded, i->second.m_explored, uint64(i->second.m_timer / 1000 + sWorld.GetGameTime()), i->second.m_creatureOrGOcount[0], i->second.m_creatureOrGOcount[1], i->second.m_creatureOrGOcount[2], i->second.m_creatureOrGOcount[3], i->second.m_itemcount[0], i->second.m_itemcount[1], i->second.m_itemcount[2], i->second.m_itemcount[3]); + GetGUIDLow(), i->first, i->second.m_status, i->second.m_rewarded, i->second.m_explored, uint64(i->second.m_timer / IN_MILISECONDS+ sWorld.GetGameTime()), i->second.m_creatureOrGOcount[0], i->second.m_creatureOrGOcount[1], i->second.m_creatureOrGOcount[2], i->second.m_creatureOrGOcount[3], i->second.m_itemcount[0], i->second.m_itemcount[1], i->second.m_itemcount[2], i->second.m_itemcount[3]); break; case QUEST_CHANGED : CharacterDatabase.PExecute("UPDATE character_queststatus SET status = '%u',rewarded = '%u',explored = '%u',timer = '" I64FMTD "',mobcount1 = '%u',mobcount2 = '%u',mobcount3 = '%u',mobcount4 = '%u',itemcount1 = '%u',itemcount2 = '%u',itemcount3 = '%u',itemcount4 = '%u' WHERE guid = '%u' AND quest = '%u' ", - i->second.m_status, i->second.m_rewarded, i->second.m_explored, uint64(i->second.m_timer / 1000 + sWorld.GetGameTime()), i->second.m_creatureOrGOcount[0], i->second.m_creatureOrGOcount[1], i->second.m_creatureOrGOcount[2], i->second.m_creatureOrGOcount[3], i->second.m_itemcount[0], i->second.m_itemcount[1], i->second.m_itemcount[2], i->second.m_itemcount[3], GetGUIDLow(), i->first ); + i->second.m_status, i->second.m_rewarded, i->second.m_explored, uint64(i->second.m_timer / IN_MILISECONDS + sWorld.GetGameTime()), i->second.m_creatureOrGOcount[0], i->second.m_creatureOrGOcount[1], i->second.m_creatureOrGOcount[2], i->second.m_creatureOrGOcount[3], i->second.m_itemcount[0], i->second.m_itemcount[1], i->second.m_itemcount[2], i->second.m_itemcount[3], GetGUIDLow(), i->first ); break; case QUEST_UNCHANGED: break; @@ -16728,7 +16729,7 @@ void Player::PetSpellInitialize() time_t cooldown = 0; if(itr->second > curTime) - cooldown = (itr->second - curTime) * 1000; + cooldown = (itr->second - curTime) * IN_MILISECONDS; data << uint16(itr->first); // spellid data << uint16(0); // spell category? @@ -16741,7 +16742,7 @@ void Player::PetSpellInitialize() time_t cooldown = 0; if(itr->second > curTime) - cooldown = (itr->second - curTime) * 1000; + cooldown = (itr->second - curTime) * IN_MILISECONDS; data << uint16(itr->first); // spellid data << uint16(0); // spell category? @@ -17258,7 +17259,7 @@ void Player::ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs ) { data << unSpellId; data << unTimeMs; // in m.secs - AddSpellCooldown(unSpellId, 0, curTime + unTimeMs/1000); + AddSpellCooldown(unSpellId, 0, curTime + unTimeMs/IN_MILISECONDS); } } GetSession()->SendPacket(&data); @@ -17645,7 +17646,7 @@ void Player::SendCooldownEvent(SpellEntry const *spellInfo) if (cooldown < 0) cooldown = 0; // Add cooldown - AddSpellCooldown(spellInfo->Id, 0, time(NULL) + cooldown / 1000); + AddSpellCooldown(spellInfo->Id, 0, time(NULL) + cooldown / IN_MILISECONDS); // Send activate WorldPacket data(SMSG_COOLDOWN_EVENT, (4+8)); data << spellInfo->Id; @@ -19126,7 +19127,7 @@ void Player::SendCorpseReclaimDelay(bool load) //! corpse reclaim delay 30 * 1000ms or longer at often deaths WorldPacket data(SMSG_CORPSE_RECLAIM_DELAY, 4); - data << uint32(delay*1000); + data << uint32(delay*IN_MILISECONDS); GetSession()->SendPacket( &data ); } diff --git a/src/game/Player.h b/src/game/Player.h index 2176150f6..80b4b0c9b 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1976,7 +1976,7 @@ class MANGOS_DLL_SPEC Player : public Unit /*** REST SYSTEM ***/ /*********************************************************/ - bool isRested() const { return GetRestTime() >= 10000; } + bool isRested() const { return GetRestTime() >= 10*IN_MILISECONDS; } uint32 GetXPRestBonus(uint32 xp); uint32 GetRestTime() const { return m_restTime;}; void SetRestTime(uint32 v) { m_restTime = v;}; @@ -2425,7 +2425,7 @@ template T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &bas continue; // special case (skip >10sec spell casts for instant cast setting) - if( mod->op==SPELLMOD_CASTING_TIME && basevalue >= T(10000) && mod->value <= -100) + if( mod->op==SPELLMOD_CASTING_TIME && basevalue >= T(10*IN_MILISECONDS) && mod->value <= -100) continue; totalpct += mod->value; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 781187922..b7b5077dd 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -46,7 +46,7 @@ #include "BattleGround.h" #include "Util.h" -#define SPELL_CHANNEL_UPDATE_INTERVAL 1000 +#define SPELL_CHANNEL_UPDATE_INTERVAL (1*IN_MILISECONDS) extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS]; @@ -2585,8 +2585,8 @@ void Spell::SendSpellCooldown() time_t curTime = time(NULL); - time_t catrecTime = catrec ? curTime+catrec/1000 : 0; // in secs - time_t recTime = rec ? curTime+rec/1000 : catrecTime;// in secs + time_t catrecTime = catrec ? curTime+catrec/IN_MILISECONDS : 0; + time_t recTime = rec ? curTime+rec/IN_MILISECONDS : catrecTime; // self spell cooldown if(recTime > 0) @@ -3819,7 +3819,7 @@ uint8 Spell::CanCast(bool strict) // - with greater than 15 min CD without SPELL_ATTR_EX4_USABLE_IN_ARENA flag // - with SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA flag if( (m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA) || - GetSpellRecoveryTime(m_spellInfo) > 15 * MINUTE * 1000 && !(m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_USABLE_IN_ARENA) ) + GetSpellRecoveryTime(m_spellInfo) > 15 * MINUTE * IN_MILISECONDS && !(m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_USABLE_IN_ARENA) ) if(MapEntry const* mapEntry = sMapStore.LookupEntry(m_caster->GetMapId())) if(mapEntry->IsBattleArena()) return SPELL_FAILED_NOT_IN_ARENA; diff --git a/src/game/Spell.h b/src/game/Spell.h index 620d2c6a4..2b70422ac 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -204,7 +204,7 @@ enum SpellState SPELL_STATE_DELAYED = 5 }; -#define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL 1000 +#define SPELL_SPELL_CHANNEL_UPDATE_INTERVAL (1*IN_MILISECONDS) typedef std::multimap SpellTargetTimeMap; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 8f713f38b..1adc0a70a 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -576,7 +576,7 @@ void Aura::Update(uint32 diff) { Powers powertype = Powers(m_spellProto->powerType); int32 manaPerSecond = m_spellProto->manaPerSecond + m_spellProto->manaPerSecondPerLevel * caster->getLevel(); - m_timeCla = 1000; + m_timeCla = 1*IN_MILISECONDS; if (manaPerSecond) { if(powertype==POWER_HEALTH) @@ -2123,30 +2123,29 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; } - // Waiting to Resurrect - if(GetId()==2584) + switch(GetId()) { - // Waiting to resurrect spell cancel, we must remove player from resurrect queue - if(m_target->GetTypeId() == TYPEID_PLAYER) - if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) - bg->RemovePlayerFromResurrectQueue(m_target->GetGUID()); - return; - } - - // Dark Fiend - if(GetId()==45934) - { - // Kill target if dispelled - if (m_removeMode==AURA_REMOVE_BY_DISPEL) - m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return; - } - - // Burning Winds - if(GetId()==46308) // casted only at creatures at spawn - { - m_target->CastSpell(m_target,47287,true,NULL,this); - return; + case 2584: // Waiting to Resurrect + { + // Waiting to resurrect spell cancel, we must remove player from resurrect queue + if(m_target->GetTypeId() == TYPEID_PLAYER) + if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) + bg->RemovePlayerFromResurrectQueue(m_target->GetGUID()); + return; + } + case 45934: // Dark Fiend + { + // Kill target if dispelled + if (m_removeMode==AURA_REMOVE_BY_DISPEL) + m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + case 46308: // Burning Winds + { + // casted only at creatures at spawn + m_target->CastSpell(m_target,47287,true,NULL,this); + return; + } } if (caster && m_removeMode == AURA_REMOVE_BY_DEATH) @@ -2828,7 +2827,7 @@ void Aura::HandleAuraTransform(bool apply, bool Real) // for players, start regeneration after 1s (in polymorph fast regeneration case) // only if caster is Player (after patch 2.4.2) if(IS_PLAYER_GUID(GetCasterGUID()) ) - ((Player*)m_target)->setRegenTimer(1000); + ((Player*)m_target)->setRegenTimer(1*IN_MILISECONDS); //dismount polymorphed target (after patch 2.4.2) if (m_target->IsMounted()) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 9d937a29c..c0335b226 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -590,7 +590,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) // Add main hand dps * effect[2] amount float averange = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2; int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget); - damage += count * int32(averange * 1000) / m_caster->GetAttackTime(BASE_ATTACK); + damage += count * int32(averange * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK); } break; } @@ -3413,7 +3413,7 @@ void Spell::EffectDispel(uint32 i) // On succes dispel // Devour Magic - if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == 12) + if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC) { uint32 heal_spell = 0; switch (m_spellInfo->Id) @@ -3484,7 +3484,7 @@ void Spell::EffectDistract(uint32 /*i*/) // Set creature Distracted, Stop it, And turn it unitTarget->SetOrientation(angle); unitTarget->StopMoving(); - unitTarget->GetMotionMaster()->MoveDistract(damage*1000); + unitTarget->GetMotionMaster()->MoveDistract(damage*IN_MILISECONDS); } } @@ -4575,7 +4575,7 @@ void Spell::EffectSummonObjectWild(uint32 i) } int32 duration = GetSpellDuration(m_spellInfo); - pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); pGameObj->SetSpellId(m_spellInfo->Id); if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)... @@ -4618,7 +4618,7 @@ void Spell::EffectSummonObjectWild(uint32 i) if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map, m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) { - linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0); + linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); linkedGO->SetSpellId(m_spellInfo->Id); m_caster->AddGameObject(linkedGO); @@ -5243,7 +5243,7 @@ void Spell::EffectDuel(uint32 i) pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() ); pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 ); int32 duration = GetSpellDuration(m_spellInfo); - pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); pGameObj->SetSpellId(m_spellInfo->Id); m_caster->AddGameObject(pGameObj); @@ -5320,7 +5320,7 @@ void Spell::EffectSummonPlayer(uint32 /*i*/) WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4); data << uint64(m_caster->GetGUID()); // summoner guid data << uint32(m_caster->GetZoneId()); // summoner zone - data << uint32(MAX_PLAYER_SUMMON_DELAY*1000); // auto decline after msecs + data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs ((Player*)unitTarget)->GetSession()->SendPacket(&data); } @@ -5503,7 +5503,7 @@ void Spell::EffectEnchantHeldItem(uint32 i) return; // Apply the temporary enchantment - item->SetEnchantment(slot, enchant_id, duration*1000, 0); + item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0); item_owner->ApplyEnchantment(item,slot,true); } } @@ -5634,7 +5634,7 @@ void Spell::EffectSummonObject(uint32 i) pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel()); int32 duration = GetSpellDuration(m_spellInfo); - pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); pGameObj->SetSpellId(m_spellInfo->Id); m_caster->AddGameObject(pGameObj); @@ -6250,7 +6250,7 @@ void Spell::EffectTransmitted(uint32 effIndex) case 3: lastSec = 17; break; } - duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000; + duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS; break; } case GAMEOBJECT_TYPE_SUMMONING_RITUAL: @@ -6270,7 +6270,7 @@ void Spell::EffectTransmitted(uint32 effIndex) } } - pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); pGameObj->SetOwnerGUID(m_caster->GetGUID() ); @@ -6293,7 +6293,7 @@ void Spell::EffectTransmitted(uint32 effIndex) if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap, m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) { - linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0); + linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); linkedGO->SetSpellId(m_spellInfo->Id); linkedGO->SetOwnerGUID(m_caster->GetGUID() ); diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 157981d5c..25e54a302 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -223,6 +223,13 @@ enum SpellFailedReason SPELL_FAILED_UNKNOWN = 181 }; +// only used in code +enum SpellCategories +{ + SPELLCATEGORY_HEALTH_MANA_POTIONS = 4, + SPELLCATEGORY_DEVOUR_MAGIC = 12 +}; + enum SpellFamilyNames { SPELLFAMILY_GENERIC = 0, diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 6d5c8ce9d..77c88666a 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3691,7 +3691,7 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit // set its duration and maximum duration // max duration 2 minutes (in msecs) int32 dur = aur->GetAuraDuration(); - const int32 max_dur = 2*MINUTE*1000; + const int32 max_dur = 2*MINUTE*IN_MILISECONDS; new_aur->SetAuraMaxDuration( max_dur > dur ? dur : max_dur ); new_aur->SetAuraDuration( max_dur > dur ? dur : max_dur ); @@ -11343,4 +11343,4 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update) if(IsInWorld()) if(Pet* pet = GetPet()) pet->SetPhaseMask(newPhaseMask,true); -} \ No newline at end of file +} diff --git a/src/game/Weather.cpp b/src/game/Weather.cpp index aea7c19b9..be1aec79c 100644 --- a/src/game/Weather.cpp +++ b/src/game/Weather.cpp @@ -36,7 +36,7 @@ Weather::Weather(uint32 zone, WeatherZoneChances const* weatherChances) : m_zone m_type = WEATHER_TYPE_FINE; m_grade = 0; - sLog.outDetail("WORLD: Starting weather system for zone %u (change every %u minutes).", m_zone, (uint32)(m_timer.GetInterval() / (1000*MINUTE)) ); + sLog.outDetail("WORLD: Starting weather system for zone %u (change every %u minutes).", m_zone, (uint32)(m_timer.GetInterval() / (MINUTE*IN_MILISECONDS)) ); } /// Launch a weather update diff --git a/src/game/World.cpp b/src/game/World.cpp index 8b04917a7..1e8aa787c 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -811,7 +811,7 @@ void World::LoadConfigSettings(bool reload) } if(reload) { - m_timers[WUPDATE_UPTIME].SetInterval(m_configs[CONFIG_UPTIME_UPDATE]*MINUTE*1000); + m_timers[WUPDATE_UPTIME].SetInterval(m_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILISECONDS); m_timers[WUPDATE_UPTIME].Reset(); } @@ -1365,18 +1365,19 @@ void World::SetInitialWorldSettings() m_timers[WUPDATE_OBJECTS].SetInterval(0); m_timers[WUPDATE_SESSIONS].SetInterval(0); - m_timers[WUPDATE_WEATHERS].SetInterval(1000); - m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*1000); //set auction update interval to 1 minute - m_timers[WUPDATE_UPTIME].SetInterval(m_configs[CONFIG_UPTIME_UPDATE]*MINUTE*1000); + m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILISECONDS); + m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILISECONDS); + m_timers[WUPDATE_UPTIME].SetInterval(m_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILISECONDS); //Update "uptime" table based on configuration entry in minutes. - m_timers[WUPDATE_CORPSES].SetInterval(20*MINUTE*1000); //erase corpses every 20 minutes + m_timers[WUPDATE_CORPSES].SetInterval(20*MINUTE*IN_MILISECONDS); + //erase corpses every 20 minutes //to set mailtimer to return mails every day between 4 and 5 am //mailtimer is increased when updating auctions //one second is 1000 -(tested on win system) - mail_timer = ((((localtime( &m_gameTime )->tm_hour + 20) % 24)* HOUR * 1000) / m_timers[WUPDATE_AUCTIONS].GetInterval() ); + mail_timer = ((((localtime( &m_gameTime )->tm_hour + 20) % 24)* HOUR * IN_MILISECONDS) / m_timers[WUPDATE_AUCTIONS].GetInterval() ); //1440 - mail_timer_expires = ( (DAY * 1000) / (m_timers[WUPDATE_AUCTIONS].GetInterval())); + mail_timer_expires = ( (DAY * IN_MILISECONDS) / (m_timers[WUPDATE_AUCTIONS].GetInterval())); sLog.outDebug("Mail timer set to: %u, mail return is called every %u minutes", mail_timer, mail_timer_expires); ///- Initilize static helper structures diff --git a/src/shared/Common.h b/src/shared/Common.h index 2dce4ac37..c18f854ee 100644 --- a/src/shared/Common.h +++ b/src/shared/Common.h @@ -158,6 +158,7 @@ enum TimeConstants HOUR = MINUTE*60, DAY = HOUR*24, MONTH = DAY*30, + YEAR = MONTH*12, IN_MILISECONDS = 1000 }; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6ce673beb..e4c8695c2 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 "7361" + #define REVISION_NR "7362" #endif // __REVISION_NR_H__ From ed6123c8045e61e48b2f854a06e9a19e36393177 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 1 Mar 2009 05:42:47 +0300 Subject: [PATCH 02/28] [7363] Propertly set cooldown at server side for category spells at cooldown event send to client. Also support item dependent cooldown set propetly at cooldown event send to client. Last will used in follow potion cooldown delay in combat patch. --- src/game/Player.cpp | 98 +++++++++++++++++++++++++++++++++++----- src/game/Player.h | 3 +- src/game/Spell.cpp | 80 +------------------------------- src/game/SpellAuras.cpp | 1 + src/game/Unit.cpp | 1 + src/shared/revision_nr.h | 2 +- 6 files changed, 92 insertions(+), 93 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index ca8c42850..d6c9b9517 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17626,6 +17626,88 @@ void Player::UpdatePvP(bool state, bool ovrride) } } +void Player::AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 itemId, Spell* spell) +{ + // init cooldown values + uint32 cat = 0; + int32 rec = -1; + int32 catrec = -1; + + // some special item spells without correct cooldown in SpellInfo + // cooldown information stored in item prototype + // This used in same way in WorldSession::HandleItemQuerySingleOpcode data sending to client. + + if(itemId) + { + if(ItemPrototype const* proto = ObjectMgr::GetItemPrototype(itemId)) + { + for(int idx = 0; idx < 5; ++idx) + { + if(proto->Spells[idx].SpellId == spellInfo->Id) + { + cat = proto->Spells[idx].SpellCategory; + rec = proto->Spells[idx].SpellCooldown; + catrec = proto->Spells[idx].SpellCategoryCooldown; + break; + } + } + } + } + + // if no cooldown found above then base at DBC data + if(rec < 0 && catrec < 0) + { + cat = spellInfo->Category; + rec = spellInfo->RecoveryTime; + catrec = spellInfo->CategoryRecoveryTime; + } + + // shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK) + // prevent 0 cooldowns set by another way + if (rec <= 0 && catrec <= 0 && (cat == 76 || IsAutoRepeatRangedSpell(spellInfo) && spellInfo->Id != SPELL_ID_AUTOSHOT)) + rec = GetAttackTime(RANGED_ATTACK); + + // Now we have cooldown data (if found any), time to apply mods + if(rec > 0) + ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, rec, spell); + + if(catrec > 0) + ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, catrec, spell); + + // replace negative cooldowns by 0 + if (rec < 0) rec = 0; + if (catrec < 0) catrec = 0; + + // no cooldown after applying spell mods + if( rec == 0 && catrec == 0) + return; + + time_t curTime = time(NULL); + + time_t catrecTime = catrec ? curTime+catrec/IN_MILISECONDS : 0; // in secs + time_t recTime = rec ? curTime+rec/IN_MILISECONDS : catrecTime;// in secs + + // self spell cooldown + if(recTime > 0) + AddSpellCooldown(spellInfo->Id, itemId, recTime); + + // category spells + if (catrec > 0) + { + SpellCategoryStore::const_iterator i_scstore = sSpellCategoryStore.find(cat); + if(i_scstore != sSpellCategoryStore.end()) + { + for(SpellCategorySet::const_iterator i_scset = i_scstore->second.begin(); i_scset != i_scstore->second.end(); ++i_scset) + { + if(*i_scset == spellInfo->Id) // skip main spell, already handled above + continue; + + AddSpellCooldown(*i_scset, itemId, catrecTime); + } + } + } +} + void Player::AddSpellCooldown(uint32 spellid, uint32 itemid, time_t end_time) { SpellCooldown sc; @@ -17634,20 +17716,12 @@ void Player::AddSpellCooldown(uint32 spellid, uint32 itemid, time_t end_time) m_spellCooldowns[spellid] = sc; } -void Player::SendCooldownEvent(SpellEntry const *spellInfo) +void Player::SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId, Spell* spell) { - if ( !(spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) ) - return; + // start cooldowns at server side, if any + AddSpellAndCategoryCooldowns(spellInfo,itemId,spell); - // Get spell cooldown - int32 cooldown = GetSpellRecoveryTime(spellInfo); - // Apply spellmods - ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, cooldown); - if (cooldown < 0) - cooldown = 0; - // Add cooldown - AddSpellCooldown(spellInfo->Id, 0, time(NULL) + cooldown / IN_MILISECONDS); - // Send activate + // Send activate cooldown timer (possible 0) at client side WorldPacket data(SMSG_COOLDOWN_EVENT, (4+8)); data << spellInfo->Id; data << GetGUID(); diff --git a/src/game/Player.h b/src/game/Player.h index 80b4b0c9b..0ae542f4c 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1491,8 +1491,9 @@ class MANGOS_DLL_SPEC Player : public Unit time_t t = time(NULL); return itr != m_spellCooldowns.end() && itr->second.end > t ? itr->second.end - t : 0; } + void AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 itemId, Spell* spell = NULL); void AddSpellCooldown(uint32 spell_id, uint32 itemid, time_t end_time); - void SendCooldownEvent(SpellEntry const *spellInfo); + void SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId = 0, Spell* spell = NULL); void ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs ); void RemoveSpellCooldown(uint32 spell_id) { m_spellCooldowns.erase(spell_id); } void RemoveArenaSpellCooldowns(); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index b7b5077dd..dee553b60 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2528,85 +2528,7 @@ void Spell::SendSpellCooldown() return; } - // init cooldown values - uint32 cat = 0; - int32 rec = -1; - int32 catrec = -1; - - // some special item spells without correct cooldown in SpellInfo - // cooldown information stored in item prototype - // This used in same way in WorldSession::HandleItemQuerySingleOpcode data sending to client. - - if(m_CastItem) - { - ItemPrototype const* proto = m_CastItem->GetProto(); - if(proto) - { - for(int idx = 0; idx < MAX_ITEM_PROTO_SPELLS; ++idx) - { - if(proto->Spells[idx].SpellId == m_spellInfo->Id) - { - cat = proto->Spells[idx].SpellCategory; - rec = proto->Spells[idx].SpellCooldown; - catrec = proto->Spells[idx].SpellCategoryCooldown; - break; - } - } - } - } - - // if no cooldown found above then base at DBC data - if(rec < 0 && catrec < 0) - { - cat = m_spellInfo->Category; - rec = m_spellInfo->RecoveryTime; - catrec = m_spellInfo->CategoryRecoveryTime; - } - - // shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK) - // prevent 0 cooldowns set by another way - if (rec <= 0 && catrec <= 0 && (cat == 76 || IsAutoRepeatRangedSpell(m_spellInfo) && m_spellInfo->Id != SPELL_ID_AUTOSHOT)) - rec = _player->GetAttackTime(RANGED_ATTACK); - - // Now we have cooldown data (if found any), time to apply mods - if(rec > 0) - _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, rec, this); - - if(catrec > 0) - _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, catrec, this); - - // replace negative cooldowns by 0 - if (rec < 0) rec = 0; - if (catrec < 0) catrec = 0; - - // no cooldown after applying spell mods - if( rec == 0 && catrec == 0) - return; - - time_t curTime = time(NULL); - - time_t catrecTime = catrec ? curTime+catrec/IN_MILISECONDS : 0; - time_t recTime = rec ? curTime+rec/IN_MILISECONDS : catrecTime; - - // self spell cooldown - if(recTime > 0) - _player->AddSpellCooldown(m_spellInfo->Id, m_CastItem ? m_CastItem->GetEntry() : 0, recTime); - - // category spells - if (catrec > 0) - { - SpellCategoryStore::const_iterator i_scstore = sSpellCategoryStore.find(cat); - if(i_scstore != sSpellCategoryStore.end()) - { - for(SpellCategorySet::const_iterator i_scset = i_scstore->second.begin(); i_scset != i_scstore->second.end(); ++i_scset) - { - if(*i_scset == m_spellInfo->Id) // skip main spell, already handled above - continue; - - _player->AddSpellCooldown(*i_scset, m_CastItem ? m_CastItem->GetEntry() : 0, catrecTime); - } - } - } + _player->AddSpellAndCategoryCooldowns(m_spellInfo,m_CastItem ? m_CastItem->GetEntry() : 0, this); } void Spell::update(uint32 difftime) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 1adc0a70a..8b3a44e37 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1117,6 +1117,7 @@ void Aura::_RemoveAura() if(caster && caster->GetTypeId() == TYPEID_PLAYER) { if ( GetSpellProto()->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE ) + // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases) ((Player*)caster)->SendCooldownEvent(GetSpellProto()); } } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 77c88666a..f008b090a 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -4078,6 +4078,7 @@ void Unit::RemoveGameObject(GameObject* gameObj, bool del) SpellEntry const* createBySpell = sSpellStore.LookupEntry(gameObj->GetSpellId()); // Need activate spell use for owner if (createBySpell && createBySpell->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) + // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases) ((Player*)this)->SendCooldownEvent(createBySpell); } gameObj->SetOwnerGUID(0); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e4c8695c2..ee63de4fc 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 "7362" + #define REVISION_NR "7363" #endif // __REVISION_NR_H__ From 2b10d8fd71464d73a62634577222e20e118afaf6 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 1 Mar 2009 10:14:55 +0300 Subject: [PATCH 03/28] [7364] Really implenent server-side anti-cheating cooldown check for spells with SPELL_ATTR_DISABLED_WHILE_ACTIVE. Move apply cooldown for like spells to aura apply (GO registering for owner in GO summon spell case) Store "infinity" cooldown for like spells, ignore it at save and reapply it at aura loading. Note: one problem still exist for like spells: at loading/far teleport spell icon lost diabled state at client. Need sedn some unknown data in SendInitialPacketsBeforeAddToMap or SendInitialPacketsAfterAddToMap for restore it state. --- src/game/Player.cpp | 77 ++++++++++++++++++++++++++-------------- src/game/Player.h | 2 +- src/game/Spell.cpp | 9 ++--- src/game/SpellAuras.cpp | 10 ++++++ src/game/Unit.cpp | 9 +++++ src/shared/revision_nr.h | 2 +- 6 files changed, 74 insertions(+), 35 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index d6c9b9517..c50288a39 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2402,6 +2402,9 @@ void Player::InitStatsForLevel(bool reapplyMods) void Player::SendInitialSpells() { + time_t curTime = time(NULL); + time_t infTime = curTime + MONTH/2; + uint16 spellCount = 0; WorldPacket data(SMSG_INITIAL_SPELLS, (1+2+4*m_spells.size()+2+m_spellCooldowns.size()*(2+2+2+4+4))); @@ -2434,10 +2437,13 @@ void Player::SendInitialSpells() if(!sEntry) continue; + // not send infinity cooldown + if(itr->second.end > infTime) + continue; + data << uint16(itr->first); time_t cooldown = 0; - time_t curTime = time(NULL); if(itr->second.end > curTime) cooldown = (itr->second.end-curTime)*IN_MILISECONDS; @@ -3157,7 +3163,7 @@ void Player::RemoveAllSpellCooldown() void Player::_LoadSpellCooldowns(QueryResult *result) { - m_spellCooldowns.clear(); + // some cooldowns can be already set at aura loading... //QueryResult *result = CharacterDatabase.PQuery("SELECT spell,item,time FROM character_spell_cooldown WHERE guid = '%u'",GetGUIDLow()); @@ -3198,17 +3204,20 @@ void Player::_SaveSpellCooldowns() CharacterDatabase.PExecute("DELETE FROM character_spell_cooldown WHERE guid = '%u'", GetGUIDLow()); time_t curTime = time(NULL); + time_t infTime = curTime + MONTH/2; // remove outdated and save active for(SpellCooldowns::iterator itr = m_spellCooldowns.begin();itr != m_spellCooldowns.end();) { if(itr->second.end <= curTime) m_spellCooldowns.erase(itr++); - else + else if(itr->second.end <= infTime) // not save locked cooldowns, it will be reset or set at reload { CharacterDatabase.PExecute("INSERT INTO character_spell_cooldown (guid,spell,item,time) VALUES ('%u', '%u', '%u', '" I64FMTD "')", GetGUIDLow(), itr->first, itr->second.itemid, uint64(itr->second.end)); ++itr; } + else + ++itr; } } @@ -17626,7 +17635,7 @@ void Player::UpdatePvP(bool state, bool ovrride) } } -void Player::AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 itemId, Spell* spell) +void Player::AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 itemId, Spell* spell, bool infinityCooldown) { // init cooldown values uint32 cat = 0; @@ -17662,37 +17671,51 @@ void Player::AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 it catrec = spellInfo->CategoryRecoveryTime; } - // shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK) - // prevent 0 cooldowns set by another way - if (rec <= 0 && catrec <= 0 && (cat == 76 || IsAutoRepeatRangedSpell(spellInfo) && spellInfo->Id != SPELL_ID_AUTOSHOT)) - rec = GetAttackTime(RANGED_ATTACK); - - // Now we have cooldown data (if found any), time to apply mods - if(rec > 0) - ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, rec, spell); - - if(catrec > 0) - ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, catrec, spell); - - // replace negative cooldowns by 0 - if (rec < 0) rec = 0; - if (catrec < 0) catrec = 0; - - // no cooldown after applying spell mods - if( rec == 0 && catrec == 0) - return; - time_t curTime = time(NULL); - time_t catrecTime = catrec ? curTime+catrec/IN_MILISECONDS : 0; // in secs - time_t recTime = rec ? curTime+rec/IN_MILISECONDS : catrecTime;// in secs + time_t catrecTime; + time_t recTime; + + // overwrite time for selected category + if(infinityCooldown) + { + // use +MONTH as infinity mark for spell cooldown (will checked as MONTH/2 at save ans skipped) + // but not allow ignore until reset or re-login + catrecTime = catrec > 0 ? curTime+MONTH : 0; + recTime = rec > 0 ? curTime+MONTH : catrecTime; + } + else + { + // shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK) + // prevent 0 cooldowns set by another way + if (rec <= 0 && catrec <= 0 && (cat == 76 || IsAutoRepeatRangedSpell(spellInfo) && spellInfo->Id != SPELL_ID_AUTOSHOT)) + rec = GetAttackTime(RANGED_ATTACK); + + // Now we have cooldown data (if found any), time to apply mods + if(rec > 0) + ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, rec, spell); + + if(catrec > 0) + ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, catrec, spell); + + // replace negative cooldowns by 0 + if (rec < 0) rec = 0; + if (catrec < 0) catrec = 0; + + // no cooldown after applying spell mods + if( rec == 0 && catrec == 0) + return; + + catrecTime = catrec ? curTime+catrec/IN_MILISECONDS : 0; + recTime = rec ? curTime+rec/IN_MILISECONDS : catrecTime; + } // self spell cooldown if(recTime > 0) AddSpellCooldown(spellInfo->Id, itemId, recTime); // category spells - if (catrec > 0) + if (cat && catrec > 0) { SpellCategoryStore::const_iterator i_scstore = sSpellCategoryStore.find(cat); if(i_scstore != sSpellCategoryStore.end()) diff --git a/src/game/Player.h b/src/game/Player.h index 0ae542f4c..2b6966375 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1491,7 +1491,7 @@ class MANGOS_DLL_SPEC Player : public Unit time_t t = time(NULL); return itr != m_spellCooldowns.end() && itr->second.end > t ? itr->second.end - t : 0; } - void AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 itemId, Spell* spell = NULL); + void AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 itemId, Spell* spell = NULL, bool infinityCooldown = false ); void AddSpellCooldown(uint32 spell_id, uint32 itemid, time_t end_time); void SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId = 0, Spell* spell = NULL); void ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs ); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index dee553b60..ac1fb932f 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2520,13 +2520,10 @@ void Spell::SendSpellCooldown() return; Player* _player = (Player*)m_caster; - // Add cooldown for max (disable spell) - // Cooldown started on SendCooldownEvent call - if (m_spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) - { - _player->AddSpellCooldown(m_spellInfo->Id, 0, time(NULL) - 1); + + // have infinity cooldown but set at aura apply + if(m_spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) return; - } _player->AddSpellAndCategoryCooldowns(m_spellInfo,m_CastItem ? m_CastItem->GetEntry() : 0, this); } diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 8b3a44e37..06f64c635 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -935,6 +935,16 @@ void Aura::_AddAura() Unit* caster = GetCaster(); + // set infinity cooldown state for spells + if(caster && caster->GetTypeId() == TYPEID_PLAYER) + { + if (m_spellProto->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) + { + Item* castItem = m_castItemGuid ? ((Player*)caster)->GetItemByGuid(m_castItemGuid) : NULL; + ((Player*)caster)->AddSpellAndCategoryCooldowns(m_spellProto,castItem ? castItem->GetEntry() : 0, NULL,true); + } + } + // passive auras (except totem auras) do not get placed in the slots // area auras with SPELL_AURA_NONE are not shown on target if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index f008b090a..f736bda9f 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -4066,6 +4066,15 @@ void Unit::AddGameObject(GameObject* gameObj) assert(gameObj && gameObj->GetOwnerGUID()==0); m_gameObj.push_back(gameObj); gameObj->SetOwnerGUID(GetGUID()); + + if ( GetTypeId()==TYPEID_PLAYER && gameObj->GetSpellId() ) + { + SpellEntry const* createBySpell = sSpellStore.LookupEntry(gameObj->GetSpellId()); + // Need disable spell use for owner + if (createBySpell && createBySpell->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) + // note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases) + ((Player*)this)->AddSpellAndCategoryCooldowns(createBySpell,0,NULL,true); + } } void Unit::RemoveGameObject(GameObject* gameObj, bool del) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ee63de4fc..7e292898b 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 "7363" + #define REVISION_NR "7364" #endif // __REVISION_NR_H__ From de513631513c4e4e56c344791001e60847758c7e Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 1 Mar 2009 10:30:24 +0300 Subject: [PATCH 04/28] [7365] Implement potion in combat delay proper work. Original patch provided by miranda.conrado. --- src/game/Player.cpp | 26 ++++++++++++++++++++++++++ src/game/Player.h | 3 +++ src/game/Spell.cpp | 13 +++++++++++++ src/game/Unit.cpp | 2 ++ src/shared/revision_nr.h | 2 +- 5 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index c50288a39..a548b102a 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -420,6 +420,8 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) m_InstanceValid = true; m_dungeonDifficulty = DIFFICULTY_NORMAL; + m_lastPotionId = 0; + for (int i = 0; i < BASEMOD_END; i++) { m_auraBaseMod[i][FLAT_MOD] = 0.0f; @@ -17750,6 +17752,30 @@ void Player::SendCooldownEvent(SpellEntry const *spellInfo, uint32 itemId, Spell data << GetGUID(); SendDirectMessage(&data); } + +void Player::UpdatePotionCooldown(Spell* spell) +{ + // no potion used i combat or still in combat + if(!m_lastPotionId || isInCombat()) + return; + + // Call not from spell cast, send cooldown event for item spells if no in combat + if(!spell) + { + // spell/item pair let set proper cooldown (except not existed charged spell cooldown spellmods for potions) + if(ItemPrototype const* proto = ObjectMgr::GetItemPrototype(m_lastPotionId)) + for(int idx = 0; idx < 5; ++idx) + if(proto->Spells[idx].SpellId && proto->Spells[idx].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE) + if(SpellEntry const* spellInfo = sSpellStore.LookupEntry(proto->Spells[idx].SpellId)) + SendCooldownEvent(spellInfo,m_lastPotionId); + } + // from spell cases (m_lastPotionId set in Spell::SendSpellCooldown) + else + SendCooldownEvent(spell->m_spellInfo,m_lastPotionId,spell); + + m_lastPotionId = 0; +} + //slot to be excluded while counting bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot) { diff --git a/src/game/Player.h b/src/game/Player.h index 2b6966375..f1140df93 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1500,6 +1500,8 @@ class MANGOS_DLL_SPEC Player : public Unit void RemoveAllSpellCooldown(); void _LoadSpellCooldowns(QueryResult *result); void _SaveSpellCooldowns(); + void SetLastPotionId(uint32 item_id) { m_lastPotionId = item_id; } + void UpdatePotionCooldown(Spell* spell = NULL); void setResurrectRequestData(uint64 guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana) { @@ -2276,6 +2278,7 @@ class MANGOS_DLL_SPEC Player : public Unit PlayerMails m_mail; PlayerSpellMap m_spells; SpellCooldowns m_spellCooldowns; + uint32 m_lastPotionId; // last used health/mana potion in combat, that block next potion use ActionButtonList m_actionButtons; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index ac1fb932f..ab28d2cc5 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2521,6 +2521,15 @@ void Spell::SendSpellCooldown() Player* _player = (Player*)m_caster; + // mana/health potions, disabled by client + if (m_spellInfo->Category==SPELLCATEGORY_HEALTH_MANA_POTIONS) + { + // need in some way provided data for Spell::finish SendCooldownEvent + if(m_CastItem) + _player->SetLastPotionId(m_CastItem->GetEntry()); + return; + } + // have infinity cooldown but set at aura apply if(m_spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE) return; @@ -2716,6 +2725,10 @@ void Spell::finish(bool ok) ((Player*)m_caster)->ClearComboPoints(); } + // mana/health potions, disabled by client, send event "not in combat" + if (m_caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->Category == SPELLCATEGORY_HEALTH_MANA_POTIONS) + ((Player*)m_caster)->UpdatePotionCooldown(this); + // call triggered spell only at successful cast (after clear combo points -> for add some if need) if(!m_TriggerSpells.empty()) TriggerSpell(); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index f736bda9f..b693a4cb8 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -8597,6 +8597,8 @@ void Unit::ClearInCombat() // Player's state will be cleared in Player::UpdateContestedPvP if(GetTypeId()!=TYPEID_PLAYER) clearUnitState(UNIT_STAT_ATTACK_PLAYER); + else + ((Player*)this)->UpdatePotionCooldown(); } bool Unit::isTargetableForAttack() const diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 7e292898b..e09088eb3 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 "7364" + #define REVISION_NR "7365" #endif // __REVISION_NR_H__ From aa5f021d289b62bb68f8ba270902931a0236a9c2 Mon Sep 17 00:00:00 2001 From: Triply Date: Sun, 1 Mar 2009 12:20:11 +0100 Subject: [PATCH 05/28] [7366] Enabled skirmish arena matches for same faction. Patch is tested and should not add crashes. Signed-off-by: Triply --- src/game/BattleGroundMgr.cpp | 64 ++++++++++++++++++++++++++++++++++-- src/game/BattleGroundMgr.h | 1 + src/shared/revision_nr.h | 2 +- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 457b36c70..8db24d0bb 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -583,7 +583,7 @@ bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 return false; } -//this function tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam +// this method tries to create battleground or arena with MinPlayersPerTeam against MinPlayersPerTeam bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 minPlayers, uint32 maxPlayers) { GroupsQueueType::const_iterator itr_team[BG_TEAMS_COUNT]; @@ -626,6 +626,65 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBas return m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() >= minPlayers && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() >= minPlayers; } +// this method will check if we can invite players to same faction skirmish match +bool BattleGroundQueue::CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_id, uint32 minPlayersPerTeam) +{ + if( m_SelectionPools[BG_TEAM_ALLIANCE].GetPlayerCount() < minPlayersPerTeam && m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() < minPlayersPerTeam ) + return false; + uint32 teamIndex = BG_TEAM_ALLIANCE; + uint32 otherTeam = BG_TEAM_HORDE; + uint32 otherTeamId = HORDE; + if ( m_SelectionPools[BG_TEAM_HORDE].GetPlayerCount() == minPlayersPerTeam ) + { + teamIndex = BG_TEAM_HORDE; + otherTeam = BG_TEAM_ALLIANCE; + otherTeamId = ALLIANCE; + } + //clear other team's selection + m_SelectionPools[otherTeam].Init(); + //store last ginfo pointer + GroupQueueInfo* ginfo = m_SelectionPools[teamIndex].SelectedGroups.back(); + //set itr_team to group that was added to selection pool latest + GroupsQueueType::iterator itr_team = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].begin(); + for(; itr_team != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team) + if( ginfo == *itr_team ) + break; + if( itr_team == m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end() ) + return false; + GroupsQueueType::iterator itr_team2 = ++itr_team; + //invite players to other selection pool + for(; itr_team2 != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team2) + { + if( !(*itr_team2)->IsInvitedToBGInstanceGUID ) + { + m_SelectionPools[otherTeam].AddGroup(*itr_team2, minPlayersPerTeam); + if( m_SelectionPools[otherTeam].GetPlayerCount() == minPlayersPerTeam ) + break; + } + } + if( m_SelectionPools[otherTeam].GetPlayerCount() != minPlayersPerTeam ) + return false; + + //here we have correct 2 selections and we need to change one teams team and move selection pool teams to other team's queue + for(GroupsQueueType::iterator itr = m_SelectionPools[otherTeam].SelectedGroups.begin(); itr != m_SelectionPools[otherTeam].SelectedGroups.end(); ++itr) + { + //set correct team + (*itr)->Team = otherTeamId; + //add team to other queue + m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + otherTeam].push_front(*itr); + //remove team from old queue + for(GroupsQueueType::iterator itr2 = itr_team; itr2 != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr2) + { + if( *itr2 == *itr ) + { + m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].erase(itr2); + break; + } + } + } + return true; +} + /* this method is called when group is inserted, or player / group is removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue it must be called after fully adding the members of a group to ensure group joining @@ -754,7 +813,8 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve if( !isRated ) { // if there are enough players in pools, start new battleground or non rated arena - if( CheckNormalMatch(bg_template, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam) ) + if( CheckNormalMatch(bg_template, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam) + || (bg_template->isArena() && CheckSkirmishForSameFaction(queue_id, MinPlayersPerTeam)) ) { // we successfully created a pool BattleGround * bg2 = NULL; diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index cf500629d..df4903e89 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -74,6 +74,7 @@ class BattleGroundQueue void FillPlayersToBG(BattleGround* bg, BGQueueIdBasedOnLevel queue_id); bool CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam); bool CheckNormalMatch(BattleGround* bg_template, BGQueueIdBasedOnLevel queue_id, uint32 minPlayers, uint32 maxPlayers); + bool CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_id, uint32 minPlayersPerTeam); GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, bool isPremade, uint32 ArenaRating, uint32 ArenaTeamId = 0); void AddPlayer(Player *plr, GroupQueueInfo *ginfo); void RemovePlayer(const uint64& guid, bool decreaseInvitedCount); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e09088eb3..ec8cdbfe7 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 "7365" + #define REVISION_NR "7366" #endif // __REVISION_NR_H__ From 98750bd95b7eb2d39a2e9200caf20a8e6d086e8c Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 1 Mar 2009 19:01:17 +0300 Subject: [PATCH 06/28] [7367] Restore one more time broken auctions work. Sorry :( --- src/game/AuctionHouseMgr.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/AuctionHouseMgr.cpp b/src/game/AuctionHouseMgr.cpp index de7518c8f..f0699d62e 100644 --- a/src/game/AuctionHouseMgr.cpp +++ b/src/game/AuctionHouseMgr.cpp @@ -645,7 +645,7 @@ bool AuctionEntry::BuildAuctionInfo(WorldPacket & data) const data << uint32(pItem->GetCount()); //item->count data << uint32(pItem->GetSpellCharges()); //item->charge FFFFFFF data << uint32(0); //Unknown - data << uint32(owner); //Auction->owner + data << uint64(owner); //Auction->owner data << uint32(startbid); //Auction->startbid (not sure if useful) data << uint32(bid ? GetAuctionOutBid() : 0); //minimal outbid diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index ec8cdbfe7..926ee3485 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 "7366" + #define REVISION_NR "7367" #endif // __REVISION_NR_H__ From 2f02dc7642b4ad2a4a71b7a9d58f3e4183849200 Mon Sep 17 00:00:00 2001 From: Lightguard Date: Mon, 2 Mar 2009 02:43:40 +0300 Subject: [PATCH 07/28] [7368] Implement unequip unexpected offhand weapons at talent reset (mostly for warror talent case). Signed-off-by: VladimirMangos Implemented OffhandCheckAtTalentsReset option for unequip at zone change (default) and at talent reset itself (can be enabled). --- src/game/Player.cpp | 25 ++++++++++++++++++++++--- src/game/World.cpp | 2 ++ src/game/World.h | 1 + src/mangosd/mangosd.conf.dist.in | 6 ++++++ src/shared/revision_nr.h | 2 +- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a548b102a..e8e516256 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3342,6 +3342,13 @@ bool Player::resetTalents(bool no_cost) //FIXME: remove pet before or after unlearn spells? for now after unlearn to allow removing of talent related, pet affecting auras RemovePet(NULL,PET_SAVE_NOT_IN_SLOT, true); + if(m_canTitanGrip) + { + m_canTitanGrip = false; + if(sWorld.getConfig(CONFIG_OFFHAND_CHECK_AT_TALENTS_RESET)) + AutoUnequipOffhandIfNeed(); + } + return true; } @@ -6417,6 +6424,9 @@ void Player::UpdateZone(uint32 newZone) if(isAlive()) DestroyZoneLimitedItem( true, newZone ); + // check some item equip limitations (in result lost CanTitanGrip at talent reset, for example) + AutoUnequipOffhandIfNeed(); + // recent client version not send leave/join channel packets for built-in local channels UpdateLocalChannels( newZone ); @@ -18806,8 +18816,8 @@ void Player::AutoUnequipOffhandIfNeed() if(!offItem) return; - // need unequip for 2h-weapon without TitanGrip - if (!IsTwoHandUsed()) + // need unequip offhand for 2h-weapon without TitanGrip (in any from hands) + if (CanTitanGrip() || (offItem->GetProto()->InventoryType != INVTYPE_2HWEAPON && !IsTwoHandUsed())) return; ItemPosCountVec off_dest; @@ -18819,7 +18829,16 @@ void Player::AutoUnequipOffhandIfNeed() } else { - sLog.outError("Player::EquipItem: Can's store offhand item at 2hand item equip for player (GUID: %u).",GetGUIDLow()); + MailItemsInfo mi; + mi.AddItem(offItem->GetGUIDLow(), offItem->GetEntry(), offItem); + MoveItemFromInventory(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND, true); + CharacterDatabase.BeginTransaction(); + offItem->DeleteFromInventoryDB(); // deletes item from character's inventory + offItem->SaveToDB(); // recursive and not have transaction guard into self, item not in inventory and can be save standalone + CharacterDatabase.CommitTransaction(); + + std::string subject = GetSession()->GetMangosString(LANG_NOT_EQUIPPED_ITEM); + WorldSession::SendMailTo(this, MAIL_NORMAL, MAIL_STATIONERY_GM, GetGUIDLow(), GetGUIDLow(), subject, 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE); } } diff --git a/src/game/World.cpp b/src/game/World.cpp index 1e8aa787c..0c7d222f9 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -940,6 +940,8 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_ARENA_SEASON_ID] = sConfig.GetIntDefault ("Arena.ArenaSeason.ID", 1); m_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfig.GetBoolDefault("Arena.ArenaSeason.InProgress", true); + m_configs[CONFIG_OFFHAND_CHECK_AT_TALENTS_RESET] = sConfig.GetBoolDefault("OffhandCheckAtTalentsReset", false); + m_configs[CONFIG_INSTANT_LOGOUT] = sConfig.GetIntDefault("InstantLogout", SEC_MODERATOR); m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1); diff --git a/src/game/World.h b/src/game/World.h index 9c908c127..55c0649ae 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -195,6 +195,7 @@ enum WorldConfigs CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE, CONFIG_ARENA_SEASON_ID, CONFIG_ARENA_SEASON_IN_PROGRESS, + CONFIG_OFFHAND_CHECK_AT_TALENTS_RESET, CONFIG_VALUE_COUNT }; diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 8a333823f..268d81457 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -546,6 +546,11 @@ LogColors = "" # Default: 0 - no skilups # 1 - skilups possible # +# OffhandCheckAtTalentsReset +# Talent reset can change offhand weapon restrictions for equip slots. +# Default: 0 - recheck offhand slot weapon only at zone update +# 1 - recheck offhand slot weapon at talent reset also +# # Event.Announce # Default: 0 (false) # 1 (true) @@ -600,6 +605,7 @@ MaxGroupXPDistance = 74 MailDeliveryDelay = 3600 SkillChance.Prospecting = 0 SkillChance.Milling = 0 +OffhandCheckAtTalentsReset = 0 Event.Announce = 0 BeepAtStart = 1 Motd = "Welcome to the Massive Network Game Object Server." diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 926ee3485..e7c5ed337 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 "7367" + #define REVISION_NR "7368" #endif // __REVISION_NR_H__ From 94de4437f8e331339a6de4ac12b8f9d748c13c9c Mon Sep 17 00:00:00 2001 From: NoFantasy Date: Mon, 2 Mar 2009 03:30:38 +0300 Subject: [PATCH 08/28] [7369] Remove ReqSourceRef in quest_template. Signed-off-by: VladimirMangos --- sql/mangos.sql | 6 +- sql/updates/7369_01_mangos_quest_template.sql | 7 ++ sql/updates/Makefile.am | 2 + src/game/ObjectMgr.cpp | 73 +++---------------- src/game/Player.cpp | 25 +++---- src/game/QuestDef.cpp | 57 +++++++-------- src/game/QuestDef.h | 1 - src/shared/revision_nr.h | 2 +- 8 files changed, 59 insertions(+), 114 deletions(-) create mode 100644 sql/updates/7369_01_mangos_quest_template.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 829a7586d..4e895e9e7 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7349_01_mangos_spell_area` bit(1) default NULL + `required_7369_01_mangos_quest_template` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -13047,10 +13047,6 @@ CREATE TABLE `quest_template` ( `ReqSourceCount2` smallint(5) unsigned NOT NULL default '0', `ReqSourceCount3` smallint(5) unsigned NOT NULL default '0', `ReqSourceCount4` smallint(5) unsigned NOT NULL default '0', - `ReqSourceRef1` tinyint(3) unsigned NOT NULL default '0', - `ReqSourceRef2` tinyint(3) unsigned NOT NULL default '0', - `ReqSourceRef3` tinyint(3) unsigned NOT NULL default '0', - `ReqSourceRef4` tinyint(3) unsigned NOT NULL default '0', `ReqCreatureOrGOId1` mediumint(9) NOT NULL default '0', `ReqCreatureOrGOId2` mediumint(9) NOT NULL default '0', `ReqCreatureOrGOId3` mediumint(9) NOT NULL default '0', diff --git a/sql/updates/7369_01_mangos_quest_template.sql b/sql/updates/7369_01_mangos_quest_template.sql new file mode 100644 index 000000000..734ebe584 --- /dev/null +++ b/sql/updates/7369_01_mangos_quest_template.sql @@ -0,0 +1,7 @@ +ALTER TABLE db_version CHANGE COLUMN required_7349_01_mangos_spell_area required_7369_01_mangos_quest_template bit; + +ALTER TABLE quest_template + DROP COLUMN ReqSourceRef1, + DROP COLUMN ReqSourceRef2, + DROP COLUMN ReqSourceRef3, + DROP COLUMN ReqSourceRef4; \ No newline at end of file diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 6f9ec4dd4..7cff06903 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -188,6 +188,7 @@ pkgdata_DATA = \ 7331_01_mangos_command.sql \ 7332_01_mangos_command.sql \ 7349_01_mangos_spell_area.sql \ + 7369_01_mangos_quest_template.sql \ README ## Additional files to include when running 'make dist' @@ -356,4 +357,5 @@ EXTRA_DIST = \ 7331_01_mangos_command.sql \ 7332_01_mangos_command.sql \ 7349_01_mangos_spell_area.sql \ + 7369_01_mangos_quest_template.sql \ README diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 36c209a00..df7e6ab5b 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -2731,25 +2731,25 @@ void ObjectMgr::LoadQuests() "Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4," // 39 40 41 42 43 44 45 46 "ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4," - // 47 48 49 50 51 52 53 54 55 56 57 58 - "ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4, ReqSourceRef1, ReqSourceRef2, ReqSourceRef3, ReqSourceRef4," - // 59 60 61 62 63 64 65 66 + // 47 48 49 50 51 52 53 54 + "ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4," + // 55 56 57 58 59 60 61 62 "ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4," - // 67 68 69 70 + // 63 64 65 66 "ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4," - // 71 72 73 74 75 76 + // 67 68 69 70 71 72 "RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6," - // 77 78 79 80 81 82 + // 73 74 75 76 77 78 "RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6," - // 83 84 85 86 87 88 89 90 + // 79 80 81 82 83 84 85 86 "RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4," - // 91 92 93 94 95 96 97 98 99 100 + // 87 88 89 90 91 92 93 94 95 96 "RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5," - // 101 102 103 104 105 106 107 108 109 110 111 + // 97 98 99 100 101 102 103 104 105 106 107 "RewHonorableKills, RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt," - // 112 113 114 115 116 117 118 119 120 121 - "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4,IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4," - // 122 123 + // 108 109 110 111 112 113 114 115 116 117 + "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4," + // 118 119 "StartScript, CompleteScript" " FROM quest_template"); if(result == NULL) @@ -3043,20 +3043,6 @@ void ObjectMgr::LoadQuests() qinfo->GetQuestId(),j+1,id,id); // no changes, quest can't be done for this requirement } - - if(!qinfo->ReqSourceCount[j]) - { - sLog.outErrorDb("Quest %u has `ReqSourceId%d` = %u but `ReqSourceCount%d` = 0, quest can't be done.", - qinfo->GetQuestId(),j+1,id,j+1); - qinfo->ReqSourceId[j] = 0; // prevent incorrect work of quest - } - - if(!qinfo->ReqSourceRef[j]) - { - sLog.outErrorDb("Quest %u has `ReqSourceId%d` = %u but `ReqSourceRef%d` = 0, quest can't be done.", - qinfo->GetQuestId(),j+1,id,j+1); - qinfo->ReqSourceId[j] = 0; // prevent incorrect work of quest - } } else { @@ -3066,41 +3052,6 @@ void ObjectMgr::LoadQuests() qinfo->GetQuestId(),j+1,j+1,qinfo->ReqSourceCount[j]); // no changes, quest ignore this data } - - if(qinfo->ReqSourceRef[j]>0) - { - sLog.outErrorDb("Quest %u has `ReqSourceId%d` = 0 but `ReqSourceRef%d` = %u.", - qinfo->GetQuestId(),j+1,j+1,qinfo->ReqSourceRef[j]); - // no changes, quest ignore this data - } - } - } - - for(int j = 0; j < QUEST_SOURCE_ITEM_IDS_COUNT; ++j ) - { - uint32 ref = qinfo->ReqSourceRef[j]; - if(ref) - { - if(ref > QUEST_OBJECTIVES_COUNT) - { - sLog.outErrorDb("Quest %u has `ReqSourceRef%d` = %u but max value in `ReqSourceRef%d` is %u, quest can't be done.", - qinfo->GetQuestId(),j+1,ref,j+1,QUEST_OBJECTIVES_COUNT); - // no changes, quest can't be done for this requirement - } - else - if(!qinfo->ReqItemId[ref-1] && !qinfo->ReqSpell[ref-1]) - { - sLog.outErrorDb("Quest %u has `ReqSourceRef%d` = %u but `ReqItemId%u` = 0 and `ReqSpellCast%u` = 0, quest can't be done.", - qinfo->GetQuestId(),j+1,ref,ref,ref); - // no changes, quest can't be done for this requirement - } - else if(qinfo->ReqItemId[ref-1] && qinfo->ReqSpell[ref-1]) - { - sLog.outErrorDb("Quest %u has `ReqItemId%u` = %u and `ReqSpellCast%u` = %u, quest can't have both fields <> 0, then can't be done.", - qinfo->GetQuestId(),ref,qinfo->ReqItemId[ref-1],ref,qinfo->ReqSpell[ref-1]); - // no changes, quest can't be done for this requirement - qinfo->ReqSourceId[j] = 0; // prevent incorrect work of quest - } } } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e8e516256..3bfd72f01 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -13818,28 +13818,21 @@ bool Player::HasQuestForItem( uint32 itemid ) const for (int j = 0; j < QUEST_SOURCE_ITEM_IDS_COUNT; j++) { // examined item is a source item - if (qinfo->ReqSourceId[j] == itemid && qinfo->ReqSourceRef[j] > 0 && qinfo->ReqSourceRef[j] <= QUEST_OBJECTIVES_COUNT) + if (qinfo->ReqSourceId[j] == itemid) { - uint32 idx = qinfo->ReqSourceRef[j]-1; + ItemPrototype const *pProto = objmgr.GetItemPrototype(itemid); - // total count of created ReqItems and SourceItems is less than ReqItemCount - if(qinfo->ReqItemId[idx] != 0 && - q_status.m_itemcount[idx] * qinfo->ReqSourceCount[j] + GetItemCount(itemid,true) < qinfo->ReqItemCount[idx] * qinfo->ReqSourceCount[j]) + // 'unique' item + if (pProto->MaxCount && GetItemCount(itemid,true) < pProto->MaxCount) return true; - // total count of casted ReqCreatureOrGOs and SourceItems is less than ReqCreatureOrGOCount - if (qinfo->ReqCreatureOrGOId[idx] != 0) + // allows custom amount drop when not 0 + if (qinfo->ReqSourceCount[j]) { - if(q_status.m_creatureOrGOcount[idx] * qinfo->ReqSourceCount[j] + GetItemCount(itemid,true) < qinfo->ReqCreatureOrGOCount[idx] * qinfo->ReqSourceCount[j]) + if (GetItemCount(itemid,true) < qinfo->ReqSourceCount[j]) return true; - } - // spell with SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT (with script) case - else if(qinfo->ReqSpell[idx] != 0) - { - // not casted and need more reagents/item for use. - if(!q_status.m_explored && GetItemCount(itemid,true) < qinfo->ReqSourceCount[j]) - return true; - } + } else if (GetItemCount(itemid,true) < pProto->Stackable) + return true; } } } diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp index 5d3578200..35ffefef4 100644 --- a/src/game/QuestDef.cpp +++ b/src/game/QuestDef.cpp @@ -73,59 +73,56 @@ Quest::Quest(Field * questRecord) for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) ReqSourceCount[i] = questRecord[51+i].GetUInt32(); - for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) - ReqSourceRef[i] = questRecord[55+i].GetUInt32(); + for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) + ReqCreatureOrGOId[i] = questRecord[55+i].GetInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqCreatureOrGOId[i] = questRecord[59+i].GetInt32(); + ReqCreatureOrGOCount[i] = questRecord[59+i].GetUInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqCreatureOrGOCount[i] = questRecord[63+i].GetUInt32(); - - for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqSpell[i] = questRecord[67+i].GetUInt32(); + ReqSpell[i] = questRecord[63+i].GetUInt32(); for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) - RewChoiceItemId[i] = questRecord[71+i].GetUInt32(); + RewChoiceItemId[i] = questRecord[67+i].GetUInt32(); for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) - RewChoiceItemCount[i] = questRecord[77+i].GetUInt32(); + RewChoiceItemCount[i] = questRecord[73+i].GetUInt32(); for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) - RewItemId[i] = questRecord[83+i].GetUInt32(); + RewItemId[i] = questRecord[79+i].GetUInt32(); for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) - RewItemCount[i] = questRecord[87+i].GetUInt32(); + RewItemCount[i] = questRecord[83+i].GetUInt32(); for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) - RewRepFaction[i] = questRecord[91+i].GetUInt32(); + RewRepFaction[i] = questRecord[87+i].GetUInt32(); for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) - RewRepValue[i] = questRecord[96+i].GetInt32(); + RewRepValue[i] = questRecord[92+i].GetInt32(); - RewHonorableKills = questRecord[101].GetUInt32(); - RewOrReqMoney = questRecord[102].GetInt32(); - RewMoneyMaxLevel = questRecord[103].GetUInt32(); - RewSpell = questRecord[104].GetUInt32(); - RewSpellCast = questRecord[105].GetUInt32(); - RewMailTemplateId = questRecord[106].GetUInt32(); - RewMailDelaySecs = questRecord[107].GetUInt32(); - PointMapId = questRecord[108].GetUInt32(); - PointX = questRecord[109].GetFloat(); - PointY = questRecord[110].GetFloat(); - PointOpt = questRecord[111].GetUInt32(); + RewHonorableKills = questRecord[97].GetUInt32(); + RewOrReqMoney = questRecord[98].GetInt32(); + RewMoneyMaxLevel = questRecord[99].GetUInt32(); + RewSpell = questRecord[100].GetUInt32(); + RewSpellCast = questRecord[101].GetUInt32(); + RewMailTemplateId = questRecord[102].GetUInt32(); + RewMailDelaySecs = questRecord[103].GetUInt32(); + PointMapId = questRecord[104].GetUInt32(); + PointX = questRecord[105].GetFloat(); + PointY = questRecord[106].GetFloat(); + PointOpt = questRecord[107].GetUInt32(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - DetailsEmote[i] = questRecord[112+i].GetUInt32(); + DetailsEmote[i] = questRecord[108+i].GetUInt32(); - IncompleteEmote = questRecord[116].GetUInt32(); - CompleteEmote = questRecord[117].GetUInt32(); + IncompleteEmote = questRecord[112].GetUInt32(); + CompleteEmote = questRecord[113].GetUInt32(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - OfferRewardEmote[i] = questRecord[118+i].GetInt32(); + OfferRewardEmote[i] = questRecord[114+i].GetInt32(); - QuestStartScript = questRecord[122].GetUInt32(); - QuestCompleteScript = questRecord[123].GetUInt32(); + QuestStartScript = questRecord[118].GetUInt32(); + QuestCompleteScript = questRecord[119].GetUInt32(); QuestFlags |= SpecialFlags << 16; diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h index f29168a49..166096715 100644 --- a/src/game/QuestDef.h +++ b/src/game/QuestDef.h @@ -229,7 +229,6 @@ class Quest uint32 ReqItemCount[QUEST_OBJECTIVES_COUNT]; uint32 ReqSourceId[QUEST_SOURCE_ITEM_IDS_COUNT]; uint32 ReqSourceCount[QUEST_SOURCE_ITEM_IDS_COUNT]; - uint32 ReqSourceRef[QUEST_SOURCE_ITEM_IDS_COUNT]; int32 ReqCreatureOrGOId[QUEST_OBJECTIVES_COUNT]; // >0 Creature <0 Gameobject uint32 ReqCreatureOrGOCount[QUEST_OBJECTIVES_COUNT]; uint32 ReqSpell[QUEST_OBJECTIVES_COUNT]; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e7c5ed337..f13bf1ca3 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 "7368" + #define REVISION_NR "7369" #endif // __REVISION_NR_H__ From a50606d22583e93b5d1be32da9c28eaf048ea4a1 Mon Sep 17 00:00:00 2001 From: Triply Date: Mon, 2 Mar 2009 09:50:31 +0100 Subject: [PATCH 09/28] [7370] Fixed crash in CheckSkirmishForSameFaction() function, when we erased iterator which shouldn't be erased Fixed crash in BattleGroundQueue::Update() by changing BGFreeSlotQueueType from deque to list. Signed-off-by: Triply --- src/game/BattleGroundMgr.cpp | 12 ++++++------ src/game/BattleGroundMgr.h | 3 ++- src/shared/revision_nr.h | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 8db24d0bb..57ac388e8 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -651,7 +651,8 @@ bool BattleGroundQueue::CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_ break; if( itr_team == m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end() ) return false; - GroupsQueueType::iterator itr_team2 = ++itr_team; + GroupsQueueType::iterator itr_team2 = itr_team; + ++itr_team2; //invite players to other selection pool for(; itr_team2 != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team2) { @@ -673,7 +674,9 @@ bool BattleGroundQueue::CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_ //add team to other queue m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + otherTeam].push_front(*itr); //remove team from old queue - for(GroupsQueueType::iterator itr2 = itr_team; itr2 != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr2) + GroupsQueueType::iterator itr2 = itr_team; + ++itr2; + for(; itr2 != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr2) { if( *itr2 == *itr ) { @@ -703,9 +706,8 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve //battleground with free slot for player should be always in the beggining of the queue // maybe it would be better to create bgfreeslotqueue for each queue_id_based_on_level - bool continueAdding = true; BGFreeSlotQueueType::iterator itr, next; - for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); continueAdding && itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next) + for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next) { next = itr; ++next; @@ -731,8 +733,6 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve if( !bg->HasFreeSlots() ) { - if( next == sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end() ) - continueAdding = false; // remove BG from BGFreeSlotQueue bg->RemoveFromBGFreeSlotQueue(); } diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index df4903e89..dc2979267 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -24,7 +24,8 @@ typedef std::map BattleGroundSet; -typedef std::deque BGFreeSlotQueueType; +//this container can't be deque, because deque doesn't like removing the last element - if you remove it, it invalidates next iterator and crash appears +typedef std::list BGFreeSlotQueueType; typedef UNORDERED_MAP BattleMastersMap; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index f13bf1ca3..bd0712af7 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 "7369" + #define REVISION_NR "7370" #endif // __REVISION_NR_H__ From f454ddf6d08503b36b3cb702804bfd0204407ba4 Mon Sep 17 00:00:00 2001 From: Triply Date: Mon, 2 Mar 2009 10:38:08 +0100 Subject: [PATCH 10/28] [7371] Correctly select closest graveyard in Player::RepoopAtGraveyard(). Patch provided by balrok Thx. Signed-off-by: Triply --- src/game/Player.cpp | 8 ++++---- src/shared/revision_nr.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 3bfd72f01..5c2dedb2e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -4261,11 +4261,11 @@ void Player::RepopAtGraveyard() WorldSafeLocsEntry const *ClosestGrave = NULL; // Special handle for battleground maps - BattleGround *bg = sBattleGroundMgr.GetBattleGround(GetBattleGroundId(), m_bgTypeID); + if( GetBattleGroundTypeId() == BATTLEGROUND_AB || GetBattleGroundTypeId() == BATTLEGROUND_EY ) + if( BattleGround *bg = GetBattleGround() ) + ClosestGrave = bg->GetClosestGraveYard(GetPositionX(), GetPositionY(), GetPositionZ(), GetTeam()); - if(bg && (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_EY)) - ClosestGrave = bg->GetClosestGraveYard(GetPositionX(), GetPositionY(), GetPositionZ(), GetTeam()); - else + if(!ClosestGrave) ClosestGrave = objmgr.GetClosestGraveYard( GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId(), GetTeam() ); // stop countdown until repop diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index bd0712af7..43c6b8e0d 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 "7370" + #define REVISION_NR "7371" #endif // __REVISION_NR_H__ From 99832862803fd24ae58dda0a5a22db6b808bcf76 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 2 Mar 2009 15:35:41 +0300 Subject: [PATCH 11/28] [7372] Cleanup BattleGround::GetClosestGraveYard related code. --- src/game/BattleGround.cpp | 5 +++++ src/game/BattleGround.h | 2 +- src/game/BattleGroundAB.cpp | 24 ++++++++++++++---------- src/game/BattleGroundAB.h | 2 +- src/game/BattleGroundEY.cpp | 25 +++++++++++++++---------- src/game/BattleGroundEY.h | 2 +- src/game/Player.cpp | 8 +++----- src/shared/revision_nr.h | 2 +- 8 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 530ec6b3e..2674fe0a9 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -1514,3 +1514,8 @@ void BattleGround::SetBgRaid( uint32 TeamID, Group *bg_raid ) if(bg_raid) bg_raid->SetBattlegroundGroup(this); old_raid = bg_raid; } + +WorldSafeLocsEntry const* BattleGround::GetClosestGraveYard( Player* player ) +{ + return objmgr.GetClosestGraveYard( player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), player->GetTeam() ); +} \ No newline at end of file diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 696ef84b5..b04eb9c71 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -426,7 +426,7 @@ class BattleGround virtual void EventPlayerCapturedFlag(Player* /*player*/) {} /* Death related */ - virtual WorldSafeLocsEntry const* GetClosestGraveYard(float /*x*/, float /*y*/, float /*z*/, uint32 /*team*/) { return NULL; } + virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); virtual void AddPlayer(Player *plr); // must be implemented in BG subclass diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index 9c6c040e0..282e25298 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -409,20 +409,21 @@ void BattleGroundAB::_NodeDeOccupied(uint8 node) if( !ghost_list.empty() ) { WorldSafeLocsEntry const *ClosestGrave = NULL; - Player *plr; for (std::vector::const_iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) { - plr = objmgr.GetPlayer(*itr); - if( !plr ) + Player* plr = objmgr.GetPlayer(*itr); + if (!plr) continue; - if( !ClosestGrave ) - ClosestGrave = GetClosestGraveYard(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetTeam()); - plr->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation()); + if (!ClosestGrave) // cache + ClosestGrave = GetClosestGraveYard(plr); + + if (ClosestGrave) + plr->TeleportTo(GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation()); } } - if( m_BgCreatures[node] ) + if( m_BgCreatures[node] ) DelCreature(node); // buff object isn't despawned @@ -603,9 +604,9 @@ void BattleGroundAB::Reset() DelCreature(i); } -WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(float x, float y, float /*z*/, uint32 team) +WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(Player* player) { - uint8 teamIndex = GetTeamIndexByTeamId(team); + uint8 teamIndex = GetTeamIndexByTeamId(player->GetTeam()); // Is there any occupied node for this team? std::vector nodes; @@ -617,13 +618,16 @@ WorldSafeLocsEntry const* BattleGroundAB::GetClosestGraveYard(float x, float y, // If so, select the closest node to place ghost on if( !nodes.empty() ) { + float plr_x = player->GetPositionX(); + float plr_y = player->GetPositionY(); + float mindist = 999999.0f; for (uint8 i = 0; i < nodes.size(); ++i) { WorldSafeLocsEntry const*entry = sWorldSafeLocsStore.LookupEntry( BG_AB_GraveyardIds[nodes[i]] ); if( !entry ) continue; - float dist = (entry->x - x)*(entry->x - x)+(entry->y - y)*(entry->y - y); + float dist = (entry->x - plr_x)*(entry->x - plr_x)+(entry->y - plr_y)*(entry->y - plr_y); if( mindist > dist ) { mindist = dist; diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h index 0ea386bcd..3b38b3a96 100644 --- a/src/game/BattleGroundAB.h +++ b/src/game/BattleGroundAB.h @@ -242,7 +242,7 @@ class BattleGroundAB : public BattleGround void HandleAreaTrigger(Player *Source, uint32 Trigger); virtual bool SetupBattleGround(); virtual void Reset(); - virtual WorldSafeLocsEntry const* GetClosestGraveYard(float x, float y, float z, uint32 team); + virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); /* Scorekeeping */ virtual void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 8b826f0cd..acdd4ca51 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -885,16 +885,16 @@ void BattleGroundEY::FillInitialWorldStates(WorldPacket& data) data << uint32(0xc0d) << uint32(0x17b); } -WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(float x, float y, float z, uint32 team) +WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(Player* player) { uint32 g_id = 0; - if(team == ALLIANCE) - g_id = EY_GRAVEYARD_MAIN_ALLIANCE; - else if(team == HORDE) - g_id = EY_GRAVEYARD_MAIN_HORDE; - else - return NULL; + switch(player->GetTeam()) + { + case ALLIANCE: g_id = EY_GRAVEYARD_MAIN_ALLIANCE; break; + case HORDE: g_id = EY_GRAVEYARD_MAIN_HORDE; break; + default: return NULL; + } float distance, nearestDistance; @@ -909,19 +909,24 @@ WorldSafeLocsEntry const *BattleGroundEY::GetClosestGraveYard(float x, float y, return NULL; } - distance = (entry->x - x)*(entry->x - x) + (entry->y - y)*(entry->y - y) + (entry->z - z)*(entry->z - z); + float plr_x = player->GetPositionX(); + float plr_y = player->GetPositionY(); + float plr_z = player->GetPositionZ(); + + + distance = (entry->x - plr_x)*(entry->x - plr_x) + (entry->y - plr_y)*(entry->y - plr_y) + (entry->z - plr_z)*(entry->z - plr_z); nearestDistance = distance; for(uint8 i = 0; i < EY_POINTS_MAX; ++i) { - if(m_PointOwnedByTeam[i]==team && m_PointState[i]==EY_POINT_UNDER_CONTROL) + if(m_PointOwnedByTeam[i]==player->GetTeam() && m_PointState[i]==EY_POINT_UNDER_CONTROL) { entry = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[i].GraveYardId); if(!entry) sLog.outError("BattleGroundEY: Not found graveyard: %u",m_CapturingPointTypes[i].GraveYardId); else { - distance = (entry->x - x)*(entry->x - x) + (entry->y - y)*(entry->y - y) + (entry->z - z)*(entry->z - z); + distance = (entry->x - plr_x)*(entry->x - plr_x) + (entry->y - plr_y)*(entry->y - plr_y) + (entry->z - plr_z)*(entry->z - plr_z); if(distance < nearestDistance) { nearestDistance = distance; diff --git a/src/game/BattleGroundEY.h b/src/game/BattleGroundEY.h index 700efe20a..0da776457 100644 --- a/src/game/BattleGroundEY.h +++ b/src/game/BattleGroundEY.h @@ -315,7 +315,7 @@ class BattleGroundEY : public BattleGround void HandleBuffUse(uint64 const& buff_guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); void HandleKillPlayer(Player *player, Player *killer); - virtual WorldSafeLocsEntry const* GetClosestGraveYard(float x, float y, float z, uint32 team); + virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); virtual bool SetupBattleGround(); virtual void Reset(); void UpdateTeamScore(uint32 Team); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 5c2dedb2e..72e01c956 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -4261,11 +4261,9 @@ void Player::RepopAtGraveyard() WorldSafeLocsEntry const *ClosestGrave = NULL; // Special handle for battleground maps - if( GetBattleGroundTypeId() == BATTLEGROUND_AB || GetBattleGroundTypeId() == BATTLEGROUND_EY ) - if( BattleGround *bg = GetBattleGround() ) - ClosestGrave = bg->GetClosestGraveYard(GetPositionX(), GetPositionY(), GetPositionZ(), GetTeam()); - - if(!ClosestGrave) + if( BattleGround *bg = GetBattleGround() ) + ClosestGrave = bg->GetClosestGraveYard(this); + else ClosestGrave = objmgr.GetClosestGraveYard( GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId(), GetTeam() ); // stop countdown until repop diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 43c6b8e0d..83d193763 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 "7371" + #define REVISION_NR "7372" #endif // __REVISION_NR_H__ From 02dd4318460b7fa76b365579ac90413fc4f41ad4 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 3 Mar 2009 00:29:22 +0300 Subject: [PATCH 12/28] [7373] Implement expansion check at character loading (for homebind, transport and plain coordinates). Also move fall damage calucaltion in new function. --- src/game/MovementHandler.cpp | 47 +---------------------- src/game/Player.cpp | 74 ++++++++++++++++++++++++++++++++++-- src/game/Player.h | 2 + src/shared/revision_nr.h | 2 +- 4 files changed, 75 insertions(+), 50 deletions(-) diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 84a28e463..ef7fee4df 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -231,52 +231,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). if (opcode == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight()) - { - // calculate total z distance of the fall - float z_diff = GetPlayer()->m_lastFallZ - movementInfo.z; - sLog.outDebug("zDiff = %f", z_diff); - Player *target = GetPlayer(); - - //Players with low fall distance, Feather Fall or physical immunity (charges used) are ignored - // 14.57 can be calculated by resolving damageperc formular below to 0 - if (z_diff >= 14.57f && !target->isDead() && !target->isGameMaster() && - !target->HasAuraType(SPELL_AURA_HOVER) && !target->HasAuraType(SPELL_AURA_FEATHER_FALL) && - !target->HasAuraType(SPELL_AURA_FLY) && !target->IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL) ) - { - //Safe fall, fall height reduction - int32 safe_fall = target->GetTotalAuraModifier(SPELL_AURA_SAFE_FALL); - - float damageperc = 0.018f*(z_diff-safe_fall)-0.2426f; - - if(damageperc >0 ) - { - uint32 damage = (uint32)(damageperc * target->GetMaxHealth()*sWorld.getRate(RATE_DAMAGE_FALL)); - - float height = movementInfo.z; - target->UpdateGroundPositionZ(movementInfo.x,movementInfo.y,height); - - if (damage > 0) - { - //Prevent fall damage from being more than the player maximum health - if (damage > target->GetMaxHealth()) - damage = target->GetMaxHealth(); - - // Gust of Wind - if (target->GetDummyAura(43621)) - damage = target->GetMaxHealth()/2; - - target->EnvironmentalDamage(target->GetGUID(), DAMAGE_FALL, damage); - - // recheck alive, might have died of EnvironmentalDamage - if (target->isAlive()) - target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, uint32(z_diff*100)); - } - - //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction - DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, target->GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall); - } - } - } + GetPlayer()->HandleFall(movementInfo); if(((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater()) { diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 72e01c956..f93edd433 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1567,6 +1567,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati else // this will be used instead of the current location in SaveToDB m_teleport_dest = WorldLocation(mapid, x, y, z, orientation); + SetFallInformation(0, z); //BuildHeartBeatMsg(&data); @@ -14338,6 +14339,14 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) { if( (*iter)->GetGUIDLow() == transGUID) { + MapEntry const* transMapEntry = sMapStore.LookupEntry((*iter)->GetMapId()); + // client without expansion support + if(GetSession()->Expansion() < transMapEntry->Expansion()) + { + sLog.outDebug("Player %s using client without required expansion tried login at transport at non accessible map %u", GetName(), (*iter)->GetMapId()); + break; + } + m_transport = *iter; m_transport->AddPassenger(this); SetMapId(m_transport->GetMapId()); @@ -14347,7 +14356,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) if(!m_transport) { - sLog.outError("ERROR: Player (guidlow %d) have invalid transport guid (%u). Teleport to default race/class locations.", + sLog.outError("ERROR: Player (guidlow %d) have problems with transport guid (%u). Teleport to default race/class locations.", guid,transGUID); RelocateToHomebind(); @@ -14360,6 +14369,16 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) transGUID = 0; } } + else // not transport case + { + MapEntry const* mapEntry = sMapStore.LookupEntry(GetMapId()); + // client without expansion support + if(GetSession()->Expansion() < mapEntry->Expansion()) + { + sLog.outDebug("Player %s using client without required expansion tried login at non accessible map %u", GetName(), GetMapId()); + RelocateToHomebind(); + } + } // NOW player must have valid map // load the player's map here if it's not already loaded @@ -15592,9 +15611,11 @@ bool Player::_LoadHomeBind(QueryResult *result) m_homebindZ = fields[4].GetFloat(); delete result; - // accept saved data only for valid position (and non instanceable) + MapEntry const* bindMapEntry = sMapStore.LookupEntry(m_homebindMapId); + + // accept saved data only for valid position (and non instanceable), and accessable if( MapManager::IsValidMapCoord(m_homebindMapId,m_homebindX,m_homebindY,m_homebindZ) && - !sMapStore.LookupEntry(m_homebindMapId)->Instanceable() ) + !bindMapEntry->Instanceable() && GetSession()->Expansion() >= bindMapEntry->Expansion()) { ok = true; } @@ -19776,3 +19797,50 @@ uint8 Player::CanEquipUniqueItem( ItemPrototype const* itemProto, uint8 except_s return EQUIP_ERR_OK; } + +void Player::HandleFall(MovementInfo const& movementInfo) +{ + // calculate total z distance of the fall + float z_diff = m_lastFallZ - movementInfo.z; + sLog.outDebug("zDiff = %f", z_diff); + + //Players with low fall distance, Feather Fall or physical immunity (charges used) are ignored + // 14.57 can be calculated by resolving damageperc formular below to 0 + if (z_diff >= 14.57f && !isDead() && !isGameMaster() && + !HasAuraType(SPELL_AURA_HOVER) && !HasAuraType(SPELL_AURA_FEATHER_FALL) && + !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL) ) + { + //Safe fall, fall height reduction + int32 safe_fall = GetTotalAuraModifier(SPELL_AURA_SAFE_FALL); + + float damageperc = 0.018f*(z_diff-safe_fall)-0.2426f; + + if(damageperc >0 ) + { + uint32 damage = (uint32)(damageperc * GetMaxHealth()*sWorld.getRate(RATE_DAMAGE_FALL)); + + float height = movementInfo.z; + UpdateGroundPositionZ(movementInfo.x,movementInfo.y,height); + + if (damage > 0) + { + //Prevent fall damage from being more than the player maximum health + if (damage > GetMaxHealth()) + damage = GetMaxHealth(); + + // Gust of Wind + if (GetDummyAura(43621)) + damage = GetMaxHealth()/2; + + EnvironmentalDamage(GetGUID(), DAMAGE_FALL, damage); + + // recheck alive, might have died of EnvironmentalDamage + if (isAlive()) + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, uint32(z_diff*100)); + } + + //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction + DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall); + } + } +} diff --git a/src/game/Player.h b/src/game/Player.h index f1140df93..f616108cd 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2010,6 +2010,8 @@ class MANGOS_DLL_SPEC Player : public Unit m_lastFallTime = time; m_lastFallZ = z; } + void HandleFall(MovementInfo const& movementInfo); + bool isMoving() const { return HasUnitMovementFlag(movementFlagsMask); } bool isMovingOrTurning() const { return HasUnitMovementFlag(movementOrTurningFlagsMask); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 83d193763..3645f73bb 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 "7372" + #define REVISION_NR "7373" #endif // __REVISION_NR_H__ From 3ab82641891d582fa4ee34e4dcbf63638b2da8a8 Mon Sep 17 00:00:00 2001 From: Arthorius Date: Tue, 3 Mar 2009 07:38:45 +0300 Subject: [PATCH 13/28] [7374] Fixed search free slot in Player::CanStoreItems in case specialized bag. Signed-off-by: VladimirMangos --- src/game/Player.cpp | 6 ++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index f93edd433..e4864ae85 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -9848,6 +9848,12 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t ); if( pBag ) { + pBagProto = pBag->GetProto(); + + // special bag already checked + if( pBagProto && (pBagProto->Class != ITEM_CLASS_CONTAINER || pBagProto->SubClass != ITEM_SUBCLASS_CONTAINER)) + continue; + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { if( inv_bags[t-INVENTORY_SLOT_BAG_START][j] == 0 ) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3645f73bb..f58ae1cc2 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 "7373" + #define REVISION_NR "7374" #endif // __REVISION_NR_H__ From 03273a49da5a6186adc0f7d2a286018e53c182a9 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 3 Mar 2009 17:09:58 +0300 Subject: [PATCH 14/28] factionTemplate->faction can be 0, add appropriate checks to prevent crashes and unexpected work. --- src/game/ObjectAccessor.cpp | 2 +- src/game/Player.cpp | 5 +- src/game/Unit.cpp | 76 +++++++++++++++++------------- src/shared/Database/DBCStructure.h | 34 +++++++++---- 4 files changed, 73 insertions(+), 44 deletions(-) diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index b18a2d816..8359bd2b9 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -84,7 +84,7 @@ ObjectAccessor::GetNPCIfCanInteractWith(Player const &player, uint64 guid, uint3 if(factionTemplate) { FactionEntry const* faction = sFactionStore.LookupEntry(factionTemplate->faction); - if( faction->reputationListID >= 0 && player.GetReputationRank(faction) <= REP_UNFRIENDLY) + if( faction && faction->reputationListID >= 0 && player.GetReputationRank(faction) <= REP_UNFRIENDLY) return NULL; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e4864ae85..b750e981d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -5652,7 +5652,8 @@ void Player::SetFactionVisibleForFactionTemplateId(uint32 FactionTemplateId) if(!factionTemplateEntry) return; - SetFactionVisibleForFactionId(factionTemplateEntry->faction); + if(factionTemplateEntry->faction) + SetFactionVisibleForFactionId(factionTemplateEntry->faction); } void Player::SetFactionVisibleForFactionId(uint32 FactionId) @@ -18687,7 +18688,7 @@ BGQueueIdBasedOnLevel Player::GetBattleGroundQueueIdFromLevel(BattleGroundTypeId float Player::GetReputationPriceDiscount( Creature const* pCreature ) const { FactionTemplateEntry const* vendor_faction = pCreature->getFactionTemplateEntry(); - if(!vendor_faction) + if(!vendor_faction || !vendor_faction->faction) return 1.0f; ReputationRank rank = GetReputationRank(vendor_faction->faction); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index b693a4cb8..5f525433c 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -6927,28 +6927,34 @@ bool Unit::IsHostileTo(Unit const* unit) const if(tester->GetTypeId()==TYPEID_PLAYER) { // forced reaction - ForcedReactions::const_iterator forceItr = ((Player*)tester)->m_forcedReactions.find(target_faction->faction); - if(forceItr!=((Player*)tester)->m_forcedReactions.end()) - return forceItr->second <= REP_HOSTILE; + if(target_faction->faction) + { + ForcedReactions::const_iterator forceItr = ((Player*)tester)->m_forcedReactions.find(target_faction->faction); + if(forceItr!=((Player*)tester)->m_forcedReactions.end()) + return forceItr->second <= REP_HOSTILE; - // if faction have reputation then hostile state for tester at 100% dependent from at_war state - if(FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction)) - if(raw_target_faction->reputationListID >=0) - if(FactionState const* factionState = ((Player*)tester)->GetFactionState(raw_target_faction)) - return (factionState->Flags & FACTION_FLAG_AT_WAR); + // if faction have reputation then hostile state for tester at 100% dependent from at_war state + if(FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction)) + if(raw_target_faction->reputationListID >=0) + if(FactionState const* factionState = ((Player*)tester)->GetFactionState(raw_target_faction)) + return (factionState->Flags & FACTION_FLAG_AT_WAR); + } } // CvP forced reaction and reputation case else if(target->GetTypeId()==TYPEID_PLAYER) { // forced reaction - ForcedReactions::const_iterator forceItr = ((Player const*)target)->m_forcedReactions.find(tester_faction->faction); - if(forceItr!=((Player const*)target)->m_forcedReactions.end()) - return forceItr->second <= REP_HOSTILE; + if(tester_faction->faction) + { + ForcedReactions::const_iterator forceItr = ((Player const*)target)->m_forcedReactions.find(tester_faction->faction); + if(forceItr!=((Player const*)target)->m_forcedReactions.end()) + return forceItr->second <= REP_HOSTILE; - // apply reputation state - FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction); - if(raw_tester_faction && raw_tester_faction->reputationListID >=0 ) - return ((Player const*)target)->GetReputationRank(raw_tester_faction) <= REP_HOSTILE; + // apply reputation state + FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction); + if(raw_tester_faction && raw_tester_faction->reputationListID >=0 ) + return ((Player const*)target)->GetReputationRank(raw_tester_faction) <= REP_HOSTILE; + } } // common faction based case (CvC,PvC,CvP) @@ -7036,28 +7042,34 @@ bool Unit::IsFriendlyTo(Unit const* unit) const if(tester->GetTypeId()==TYPEID_PLAYER) { // forced reaction - ForcedReactions::const_iterator forceItr = ((Player const*)tester)->m_forcedReactions.find(target_faction->faction); - if(forceItr!=((Player const*)tester)->m_forcedReactions.end()) - return forceItr->second >= REP_FRIENDLY; + if(target_faction->faction) + { + ForcedReactions::const_iterator forceItr = ((Player const*)tester)->m_forcedReactions.find(target_faction->faction); + if(forceItr!=((Player const*)tester)->m_forcedReactions.end()) + return forceItr->second >= REP_FRIENDLY; - // if faction have reputation then friendly state for tester at 100% dependent from at_war state - if(FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction)) - if(raw_target_faction->reputationListID >=0) - if(FactionState const* FactionState = ((Player*)tester)->GetFactionState(raw_target_faction)) - return !(FactionState->Flags & FACTION_FLAG_AT_WAR); + // if faction have reputation then friendly state for tester at 100% dependent from at_war state + if(FactionEntry const* raw_target_faction = sFactionStore.LookupEntry(target_faction->faction)) + if(raw_target_faction->reputationListID >=0) + if(FactionState const* FactionState = ((Player*)tester)->GetFactionState(raw_target_faction)) + return !(FactionState->Flags & FACTION_FLAG_AT_WAR); + } } // CvP forced reaction and reputation case else if(target->GetTypeId()==TYPEID_PLAYER) { // forced reaction - ForcedReactions::const_iterator forceItr = ((Player const*)target)->m_forcedReactions.find(tester_faction->faction); - if(forceItr!=((Player const*)target)->m_forcedReactions.end()) - return forceItr->second >= REP_FRIENDLY; + if(tester_faction->faction) + { + ForcedReactions::const_iterator forceItr = ((Player const*)target)->m_forcedReactions.find(tester_faction->faction); + if(forceItr!=((Player const*)target)->m_forcedReactions.end()) + return forceItr->second >= REP_FRIENDLY; - // apply reputation state - if(FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction)) - if(raw_tester_faction->reputationListID >=0 ) - return ((Player const*)target)->GetReputationRank(raw_tester_faction) >= REP_FRIENDLY; + // apply reputation state + if(FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction)) + if(raw_tester_faction->reputationListID >=0 ) + return ((Player const*)target)->GetReputationRank(raw_tester_faction) >= REP_FRIENDLY; + } } // common faction based case (CvC,PvC,CvP) @@ -7067,7 +7079,7 @@ bool Unit::IsFriendlyTo(Unit const* unit) const bool Unit::IsHostileToPlayers() const { FactionTemplateEntry const* my_faction = getFactionTemplateEntry(); - if(!my_faction) + if(!my_faction || !my_faction->faction) return false; FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->faction); @@ -7080,7 +7092,7 @@ bool Unit::IsHostileToPlayers() const bool Unit::IsNeutralToAll() const { FactionTemplateEntry const* my_faction = getFactionTemplateEntry(); - if(!my_faction) + if(!my_faction || !my_faction->faction) return true; FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->faction); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 55d889c2a..8f739474d 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -730,22 +730,38 @@ struct FactionTemplateEntry // helpers bool IsFriendlyTo(FactionTemplateEntry const& entry) const { - if(enemyFaction[0] == entry.faction || enemyFaction[1] == entry.faction || enemyFaction[2] == entry.faction || enemyFaction[3] == entry.faction ) - return false; - if(friendFaction[0] == entry.faction || friendFaction[1] == entry.faction || friendFaction[2] == entry.faction || friendFaction[3] == entry.faction ) - return true; + if(entry.faction) + { + for(int i = 0; i < 4; ++i) + if (enemyFaction[i] == entry.faction) + return false; + for(int i = 0; i < 4; ++i) + if (friendFaction[i] == entry.faction) + return true; + } return (friendlyMask & entry.ourMask) || (ourMask & entry.friendlyMask); } bool IsHostileTo(FactionTemplateEntry const& entry) const { - if(enemyFaction[0] == entry.faction || enemyFaction[1] == entry.faction || enemyFaction[2] == entry.faction || enemyFaction[3] == entry.faction ) - return true; - if(friendFaction[0] == entry.faction || friendFaction[1] == entry.faction || friendFaction[2] == entry.faction || friendFaction[3] == entry.faction ) - return false; + if(entry.faction) + { + for(int i = 0; i < 4; ++i) + if (enemyFaction[i] == entry.faction) + return true; + for(int i = 0; i < 4; ++i) + if (friendFaction[i] == entry.faction) + return false; + } return (hostileMask & entry.ourMask) != 0; } bool IsHostileToPlayers() const { return (hostileMask & FACTION_MASK_PLAYER) !=0; } - bool IsNeutralToAll() const { return hostileMask == 0 && friendlyMask == 0 && enemyFaction[0]==0 && enemyFaction[1]==0 && enemyFaction[2]==0 && enemyFaction[3]==0; } + bool IsNeutralToAll() const + { + for(int i = 0; i < 4; ++i) + if (enemyFaction[i] != 0) + return false; + return hostileMask == 0 && friendlyMask == 0; + } bool IsContestedGuardFaction() const { return (factionFlags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD)!=0; } }; From 0d96837d489353216e9323d3a55ba921fe1f1780 Mon Sep 17 00:00:00 2001 From: pasdVn Date: Tue, 3 Mar 2009 23:49:50 +0300 Subject: [PATCH 15/28] [7375] Typos in dynamic object registering and deleting for owner. This let have more then one persistent aura in same time. Signed-off-by: VladimirMangos --- src/game/Unit.cpp | 6 +++--- src/shared/revision_nr.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 5f525433c..5e5eb564d 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3999,7 +3999,7 @@ void Unit::RemoveDynObject(uint32 spellid) return; for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();) { - DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*m_dynObjGUIDs.begin()); + DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*i); if(!dynObj) { i = m_dynObjGUIDs.erase(i); @@ -4029,7 +4029,7 @@ DynamicObject * Unit::GetDynObject(uint32 spellId, uint32 effIndex) { for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();) { - DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*m_dynObjGUIDs.begin()); + DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*i); if(!dynObj) { i = m_dynObjGUIDs.erase(i); @@ -4047,7 +4047,7 @@ DynamicObject * Unit::GetDynObject(uint32 spellId) { for (DynObjectGUIDs::iterator i = m_dynObjGUIDs.begin(); i != m_dynObjGUIDs.end();) { - DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*m_dynObjGUIDs.begin()); + DynamicObject* dynObj = ObjectAccessor::GetDynamicObject(*this,*i); if(!dynObj) { i = m_dynObjGUIDs.erase(i); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index f58ae1cc2..3324bd02f 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 "7374" + #define REVISION_NR "7375" #endif // __REVISION_NR_H__ From fee3278e576aca971470ed3a4dd0b1c291435198 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 4 Mar 2009 01:22:03 +0300 Subject: [PATCH 16/28] [7376] Allow store in spell_area.aura_spell negative values for "not has aura" requirement. Also * Allow have in aura_spell spells with SPELL_AURA_PHASE in first effect. * Allow negative aura_spell chaining in spell_area table. * Better check at loading duplicate data (by requiremnt set) in spell_area table. --- sql/mangos.sql | 4 +- sql/updates/7376_01_mangos_spell_area.sql | 4 ++ sql/updates/Makefile.am | 2 + src/game/SpellAuras.cpp | 77 ++++++++++++++--------- src/game/SpellMgr.cpp | 63 ++++++++++++++----- src/game/SpellMgr.h | 2 +- src/shared/revision_nr.h | 2 +- 7 files changed, 103 insertions(+), 51 deletions(-) create mode 100644 sql/updates/7376_01_mangos_spell_area.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 4e895e9e7..0446fda2b 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7369_01_mangos_quest_template` bit(1) default NULL + `required_7376_01_mangos_spell_area` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -13295,7 +13295,7 @@ CREATE TABLE `spell_area` ( `quest_start` mediumint(8) unsigned NOT NULL default '0', `quest_start_active` tinyint(1) unsigned NOT NULL default '0', `quest_end` mediumint(8) unsigned NOT NULL default '0', - `aura_spell` mediumint(8) unsigned NOT NULL default '0', + `aura_spell` mediumint(8) NOT NULL default '0', `racemask` mediumint(8) unsigned NOT NULL default '0', `gender` tinyint(1) unsigned NOT NULL default '2', `autocast` tinyint(1) unsigned NOT NULL default '0', diff --git a/sql/updates/7376_01_mangos_spell_area.sql b/sql/updates/7376_01_mangos_spell_area.sql new file mode 100644 index 000000000..5a3aadd68 --- /dev/null +++ b/sql/updates/7376_01_mangos_spell_area.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_7369_01_mangos_quest_template required_7376_01_mangos_spell_area bit; + +ALTER TABLE spell_area + CHANGE COLUMN `aura_spell` `aura_spell` mediumint(8) NOT NULL default '0'; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 7cff06903..1a5f4d469 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -189,6 +189,7 @@ pkgdata_DATA = \ 7332_01_mangos_command.sql \ 7349_01_mangos_spell_area.sql \ 7369_01_mangos_quest_template.sql \ + 7376_01_mangos_spell_area.sql \ README ## Additional files to include when running 'make dist' @@ -358,4 +359,5 @@ EXTRA_DIST = \ 7332_01_mangos_command.sql \ 7349_01_mangos_spell_area.sql \ 7369_01_mangos_quest_template.sql \ + 7376_01_mangos_spell_area.sql \ README diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 06f64c635..9da84e653 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2073,22 +2073,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real) m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE); return; } - - // some auras applied at aura apply - if(GetEffIndex()==0 && m_target->GetTypeId()==TYPEID_PLAYER) - { - SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); - if(saBounds.first != saBounds.second) - { - uint32 zone = m_target->GetZoneId(); - uint32 area = m_target->GetAreaId(); - - for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) - if(itr->second->autocast && itr->second->IsFitToRequirements((Player*)m_target,zone,area)) - if( !m_target->HasAura(itr->second->spellId,0) ) - m_target->CastSpell(m_target,itr->second->spellId,true); - } - } } // AT REMOVE else @@ -2177,21 +2161,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } } - - // some auras remove at aura remove - if(GetEffIndex()==0 && m_target->GetTypeId()==TYPEID_PLAYER) - { - SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); - if(saBounds.first != saBounds.second) - { - uint32 zone = m_target->GetZoneId(); - uint32 area = m_target->GetAreaId(); - - for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) - if(!itr->second->IsFitToRequirements((Player*)m_target,zone,area)) - m_target->RemoveAurasDueToSpell(itr->second->spellId); - } - } } // AT APPLY & REMOVE @@ -2416,6 +2385,29 @@ void Aura::HandleAuraDummy(bool apply, bool Real) m_target->RemovePetAura(petSpell); return; } + + if(GetEffIndex()==0 && m_target->GetTypeId()==TYPEID_PLAYER) + { + SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); + if(saBounds.first != saBounds.second) + { + uint32 zone = m_target->GetZoneId(); + uint32 area = m_target->GetAreaId(); + + for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + { + // some auras remove at aura remove + if(!itr->second->IsFitToRequirements((Player*)m_target,zone,area)) + m_target->RemoveAurasDueToSpell(itr->second->spellId); + // some auras applied at aura apply + else if(itr->second->autocast) + { + if( !m_target->HasAura(itr->second->spellId,0) ) + m_target->CastSpell(m_target,itr->second->spellId,true); + } + } + } + } } void Aura::HandleAuraMounted(bool apply, bool Real) @@ -6688,6 +6680,29 @@ void Aura::HandlePhase(bool apply, bool Real) m_target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL,false); ((Player*)m_target)->GetSession()->SendSetPhaseShift(apply ? GetMiscValue() : PHASEMASK_NORMAL); + + if(GetEffIndex()==0) + { + SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAuraMapBounds(GetId()); + if(saBounds.first != saBounds.second) + { + uint32 zone = m_target->GetZoneId(); + uint32 area = m_target->GetAreaId(); + + for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr) + { + // some auras remove at aura remove + if(!itr->second->IsFitToRequirements((Player*)m_target,zone,area)) + m_target->RemoveAurasDueToSpell(itr->second->spellId); + // some auras applied at aura apply + else if(itr->second->autocast) + { + if( !m_target->HasAura(itr->second->spellId,0) ) + m_target->CastSpell(m_target,itr->second->spellId,true); + } + } + } + } } else m_target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL,false); diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 89e88600e..f333db815 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2387,7 +2387,7 @@ void SpellMgr::LoadSpellAreas() spellArea.questStart = fields[2].GetUInt32(); spellArea.questStartCanActive = fields[3].GetBool(); spellArea.questEnd = fields[4].GetUInt32(); - spellArea.auraSpell = fields[5].GetUInt32(); + spellArea.auraSpell = fields[5].GetInt32(); spellArea.raceMask = fields[6].GetUInt32(); spellArea.gender = Gender(fields[7].GetUInt8()); spellArea.autocast = fields[8].GetBool(); @@ -2398,10 +2398,35 @@ void SpellMgr::LoadSpellAreas() continue; } - if(mSpellAreaForAuraMap.find(spellArea.spellId)!=mSpellAreaForAuraMap.end()) { - sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell (%u) requirement that already listed in table itself", spell,spellArea.auraSpell); - continue; + bool ok = true; + SpellAreaMapBounds sa_bounds = GetSpellAreaMapBounds(spellArea.spellId); + for(SpellAreaMap::const_iterator itr = sa_bounds.first; itr != sa_bounds.second; ++itr) + { + if(spellArea.spellId && itr->second.spellId && spellArea.spellId != itr->second.spellId) + continue; + if(spellArea.areaId && itr->second.areaId && spellArea.areaId!= itr->second.areaId) + continue; + if(spellArea.questStart && itr->second.questStart && spellArea.questStart!= itr->second.questStart) + continue; + if(spellArea.auraSpell && itr->second.auraSpell && spellArea.auraSpell!= itr->second.auraSpell) + continue; + if(spellArea.raceMask && itr->second.raceMask && (spellArea.raceMask & itr->second.raceMask)==0) + continue; + if(spellArea.gender != GENDER_NONE && itr->second.gender != GENDER_NONE && spellArea.gender!= itr->second.gender) + continue; + + // duplicate by requirements + ok =false; + break; + } + + if(!ok) + { + sLog.outErrorDb("Spell %u listed in `spell_area` already listed with similar requirements.", spell); + continue; + } + } if(spellArea.areaId && !GetAreaEntryByAreaID(spellArea.areaId)) @@ -2433,33 +2458,33 @@ void SpellMgr::LoadSpellAreas() if(spellArea.auraSpell) { - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellArea.auraSpell); + SpellEntry const* spellInfo = sSpellStore.LookupEntry(abs(spellArea.auraSpell)); if(!spellInfo) { - sLog.outErrorDb("Spell %u listed in `spell_area` have wrong aura spell (%u) requirement", spell,spellArea.auraSpell); + sLog.outErrorDb("Spell %u listed in `spell_area` have wrong aura spell (%u) requirement", spell,abs(spellArea.auraSpell)); continue; } - if(spellInfo->EffectApplyAuraName[0]!=SPELL_AURA_DUMMY) + if(spellInfo->EffectApplyAuraName[0]!=SPELL_AURA_DUMMY && spellInfo->EffectApplyAuraName[0]!=SPELL_AURA_PHASE) { - sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell requirement (%u) without dummy aura in effect 0", spell,spellArea.auraSpell); + sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell requirement (%u) without dummy/phase aura in effect 0", spell,abs(spellArea.auraSpell)); continue; } - if(spellArea.auraSpell==spellArea.spellId) + if(abs(spellArea.auraSpell)==spellArea.spellId) { - sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell (%u) requirement for itself", spell,spellArea.auraSpell); + sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell (%u) requirement for itself", spell,abs(spellArea.auraSpell)); continue; } - // not allow autocast chains by auraSpell field - if(spellArea.autocast) + // not allow autocast chains by auraSpell field (but allow use as alternative if not present) + if(spellArea.autocast && spellArea.auraSpell > 0) { bool chain = false; SpellAreaForAuraMapBounds saBound = GetSpellAreaForAuraMapBounds(spellArea.spellId); for(SpellAreaForAuraMap::const_iterator itr = saBound.first; itr != saBound.second; ++itr) { - if(itr->second->autocast) + if(itr->second->autocast && itr->second->auraSpell > 0) { chain = true; break; @@ -2475,7 +2500,7 @@ void SpellMgr::LoadSpellAreas() SpellAreaMapBounds saBound2 = GetSpellAreaMapBounds(spellArea.auraSpell); for(SpellAreaMap::const_iterator itr2 = saBound2.first; itr2 != saBound2.second; ++itr2) { - if(itr2->second.autocast && itr2->second.auraSpell) + if(itr2->second.autocast && itr2->second.auraSpell > 0) { chain = true; break; @@ -2523,7 +2548,7 @@ void SpellMgr::LoadSpellAreas() // for search at aura apply if(spellArea.auraSpell) - mSpellAreaForAuraMap.insert(SpellAreaForAuraMap::value_type(spellArea.auraSpell,sa)); + mSpellAreaForAuraMap.insert(SpellAreaForAuraMap::value_type(abs(spellArea.auraSpell),sa)); ++count; } while( result->NextRow() ); @@ -2810,8 +2835,14 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32 if(auraSpell) { // not have expected aura - if(!player || !player->HasAura(auraSpell,0)) + if(!player) return false; + if(auraSpell > 0) + // have expected aura + return player->HasAura(auraSpell,0); + else + // not have expected aura + return !player->HasAura(-auraSpell,0); } return true; diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 25e54a302..952b42c19 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -690,7 +690,7 @@ struct SpellArea uint32 areaId; // zone/subzone/or 0 is not limited to zone uint32 questStart; // quest start (quest must be active or rewarded for spell apply) uint32 questEnd; // quest end (quest don't must be rewarded for spell apply) - uint32 auraSpell; // spell aura must be applied for spell apply + int32 auraSpell; // spell aura must be applied for spell apply )if possitive) and it don't must be applied in other case uint32 raceMask; // can be applied only to races Gender gender; // can be applied only to gender bool questStartCanActive; // if true then quest start can be active (not only rewarded) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3324bd02f..80833c7f6 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 "7375" + #define REVISION_NR "7376" #endif // __REVISION_NR_H__ From e409b32c714e48b9bae5e8baf26a35857e875e0c Mon Sep 17 00:00:00 2001 From: GriffonHeart Date: Wed, 4 Mar 2009 02:39:33 +0300 Subject: [PATCH 17/28] [7377] Dummy effects for portal spells used in DK starting area. Signed-off-by: VladimirMangos --- src/game/SpellEffects.cpp | 18 +++++++++++++++++- src/shared/revision_nr.h | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index c0335b226..b9151f3b9 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1106,7 +1106,23 @@ void Spell::EffectDummy(uint32 i) { m_caster->CastSpell(m_caster,54586,true); return; - } + } + case 58418: // Portal to Orgrimmar + { + if(!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 58419, true); + break; + } + case 58420: // Portal to Stormwind + { + if(!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 58421, true); + break; + } } //All IconID Check in there diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 80833c7f6..5f4c8033a 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 "7376" + #define REVISION_NR "7377" #endif // __REVISION_NR_H__ From 2d6b8bf0684c8d71137fa29e60eeaa46b7f756ff Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 4 Mar 2009 04:12:30 +0300 Subject: [PATCH 18/28] [7378] Fixed check for ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL for non-class/race specific case. --- src/game/AchievementMgr.cpp | 16 ++++++++++++---- src/shared/revision_nr.h | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 52adc738a..3886e8bb5 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -756,10 +756,18 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve { case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: { - if (achievIdByClass[GetPlayer()->getClass()] == achievement->ID || - achievIdByRace[GetPlayer()->getRace()] == achievement->ID) - return progress->counter >= achievementCriteria->reach_level.level; - return false; + // skip wrong class achievements + for(int i = 1; i < MAX_CLASSES; ++i) + if(achievIdByClass[i] == achievement->ID && i != GetPlayer()->getClass()) + return false; + + // skip wrong race achievements + for(int i = 1; i < MAX_RACES; ++i) + if(achievIdByRace[i] == achievement->ID && i != GetPlayer()->getRace()) + return false; + + // appropriate class/race or not class/race specific + return progress->counter >= achievementCriteria->reach_level.level; } case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: return progress->counter >= achievementCriteria->buy_bank_slot.numberOfSlots; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 5f4c8033a..a6157f0d5 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 "7377" + #define REVISION_NR "7378" #endif // __REVISION_NR_H__ From bff0cb8c75a16d41eb1515f2b4f65d3007a9ea4d Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 5 Mar 2009 02:47:17 +0300 Subject: [PATCH 19/28] [7379] Implement some money related achievement criteria. * ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS: * ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD: * ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING: * ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER: * ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL: * ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: --- src/game/AchievementMgr.cpp | 91 ++++++++++++++++-------------- src/game/CharacterHandler.cpp | 3 +- src/game/LootHandler.cpp | 4 ++ src/game/Mail.cpp | 7 ++- src/game/Player.cpp | 14 ++++- src/shared/Database/DBCStructure.h | 7 +++ src/shared/revision_nr.h | 2 +- 7 files changed, 81 insertions(+), 47 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 3886e8bb5..21783c5c6 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -406,6 +406,26 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui switch (type) { + // std. case: increment at 1 + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: + case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + // std case: increment at miscvalue1 + case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS: + case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD: + case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING: + case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER: + case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL: + case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, miscvalue1, true); + break; case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel()); break; @@ -445,12 +465,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, counter); break; } - case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: - // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case - if(!miscvalue1) - continue; - SetCriteriaProgress(achievementCriteria, miscvalue1, true); - break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) @@ -483,12 +497,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; SetCriteriaProgress(achievementCriteria, 1, true); break; - case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: - // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case - if(!miscvalue1) - continue; - SetCriteriaProgress(achievementCriteria, 1, true); - break; case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: { // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case @@ -674,13 +682,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS: - case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS: case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS: - case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD: - case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING: - case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER: - case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL: - case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT: case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL: case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT: @@ -754,6 +756,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve switch(achievementCriteria->requiredType) { + case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: + return progress->counter >= achievementCriteria->kill_creature.creatureCount; case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: { // skip wrong class achievements @@ -769,57 +773,62 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve // appropriate class/race or not class/race specific return progress->counter >= achievementCriteria->reach_level.level; } - case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: - return progress->counter >= achievementCriteria->buy_bank_slot.numberOfSlots; - case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: - return progress->counter >= achievementCriteria->kill_creature.creatureCount; - case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: - return progress->counter >= 1; case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: return progress->counter >= achievementCriteria->reach_skill_level.skillLevel; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: + return progress->counter >= 1; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT: return progress->counter >= achievementCriteria->complete_quest_count.totalQuestCount; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE: return progress->counter >= achievementCriteria->complete_quests_in_zone.questCount; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: return progress->counter >= achievementCriteria->complete_daily_quest.questCount; - case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: - return progress->counter >= 1; case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: return progress->counter >= achievementCriteria->fall_without_dying.fallHeight; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: return progress->counter >= 1; - case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: - return progress->counter >= achievementCriteria->use_item.itemCount; - case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: - return progress->counter >= achievementCriteria->own_item.itemCount; - case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: - return progress->counter >= achievementCriteria->loot_item.itemCount; case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: return progress->counter >= achievementCriteria->be_spell_target.spellCount; case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: return progress->counter >= achievementCriteria->cast_spell.castCount; - case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: - return progress->counter >= achievementCriteria->learn_skilline_spell.spellCount; - case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: - return progress->counter >= achievementCriteria->visit_barber.numberOfVisits; + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: + return progress->counter >= 1; + case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: + return progress->counter >= achievementCriteria->own_item.itemCount; + case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: + return progress->counter >= achievementCriteria->use_item.itemCount; + case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: + return progress->counter >= achievementCriteria->loot_item.itemCount; + case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: + return progress->counter >= 1; + case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: + return progress->counter >= achievementCriteria->buy_bank_slot.numberOfSlots; case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION: return progress->counter >= achievementCriteria->gain_reputation.reputationAmount; case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION: return progress->counter >= achievementCriteria->gain_exalted_reputation.numberOfExaltedFactions; - case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: - return progress->counter >= 1; - case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: - case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: - return progress->counter >= achievementCriteria->roll_greed_on_loot.count; + case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: + return progress->counter >= achievementCriteria->visit_barber.numberOfVisits; + case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: + case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: + return progress->counter >= achievementCriteria->roll_greed_on_loot.count; + case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD: + return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper; + case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: + return progress->counter >= achievementCriteria->loot_money.goldInCopper; + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: + return progress->counter >= achievementCriteria->learn_skilline_spell.spellCount; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE: case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: + case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS: + case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER: + case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL: return false; } return false; diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index a6b1428ad..423866c94 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -1188,7 +1188,8 @@ void WorldSession::HandleAlterAppearance( WorldPacket & recv_data ) SendPacket(&data); } - _player->SetMoney(_player->GetMoney() - Cost); // it isn't free + _player->ModifyMoney(-int32(Cost)); // it isn't free + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, Cost); _player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id)); _player->SetByteValue(PLAYER_BYTES, 3, uint8(Color)); diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp index 57d1b6910..5c5d02699 100644 --- a/src/game/LootHandler.cpp +++ b/src/game/LootHandler.cpp @@ -222,6 +222,7 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ ) for (std::vector::iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney( money_per_player ); + (*i)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, money_per_player); //Offset surely incorrect, but works WorldPacket data( SMSG_LOOT_MONEY_NOTIFY, 4 ); data << uint32(money_per_player); @@ -229,7 +230,10 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ ) } } else + { player->ModifyMoney( pLoot->gold ); + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, pLoot->gold); + } pLoot->gold = 0; pLoot->NotifyMoneyRemoved(); } diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index c59849415..52cb723c1 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -122,9 +122,11 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data ) return; } - uint32 reqmoney = money + 30; + uint32 cost = money + 30; if (items_count) - reqmoney = money + (30 * items_count); + cost = 30 * items_count; + + uint32 reqmoney = cost + money; if (pl->GetMoney() < reqmoney) { @@ -207,6 +209,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data ) } pl->ModifyMoney( -int32(reqmoney) ); + pl->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost); bool needItemDelay = false; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index b750e981d..15d8784c1 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3335,6 +3335,7 @@ bool Player::resetTalents(bool no_cost) if(!no_cost) { ModifyMoney(-(int32)cost); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS, cost); m_resetTalentsCost = cost; m_resetTalentsTime = time(NULL); @@ -12790,10 +12791,18 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver if ( getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ) GiveXP( XP , NULL ); else - ModifyMoney( int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY)) ); + { + int32 money = int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY)); + ModifyMoney( money ); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, money); + } // Give player extra money if GetRewOrReqMoney > 0 and get ReqMoney if negative - ModifyMoney( pQuest->GetRewOrReqMoney() ); + if(pQuest->GetRewOrReqMoney()) + { + ModifyMoney( pQuest->GetRewOrReqMoney() ); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, pQuest->GetRewOrReqMoney()); + } // honor reward if(pQuest->GetRewHonorableKills()) @@ -17257,6 +17266,7 @@ bool Player::ActivateTaxiPathTo(std::vector const& nodes, uint32 mount_i //Checks and preparations done, DO FLIGHT ModifyMoney(-(int32)totalcost); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost); // prevent stealth flight RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 8f739474d..56812f7f2 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -369,6 +369,13 @@ struct AchievementCriteriaEntry uint32 itemID; // 3 } equip_item; + // ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62 + struct + { + uint32 unused; // 3 + uint32 goldInCopper; // 4 + } quest_reward_money; + // ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67 struct diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a6157f0d5..a3e533120 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 "7378" + #define REVISION_NR "7379" #endif // __REVISION_NR_H__ From 8928df7f07582b72d34c6dbcd4bde339f7955a1c Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 5 Mar 2009 13:45:56 +0300 Subject: [PATCH 20/28] [7380] Implement highest value achievements support. Implement some auction achievements * ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID: * ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD: (FIXME: only for online player) --- src/game/AchievementMgr.cpp | 60 +++++++++++++++++++++----------- src/game/AchievementMgr.h | 3 +- src/game/AuctionHouseHandler.cpp | 2 ++ src/game/AuctionHouseMgr.cpp | 2 ++ src/shared/revision_nr.h | 2 +- 5 files changed, 47 insertions(+), 22 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 21783c5c6..43e889622 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -412,7 +412,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; - SetCriteriaProgress(achievementCriteria, 1, true); + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; // std case: increment at miscvalue1 case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS: @@ -424,7 +424,15 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; - SetCriteriaProgress(achievementCriteria, miscvalue1, true); + SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_ACCUMULATE); + break; + // std case: high value at miscvalue1 + case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID: + case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD: /* FIXME: for online player only currently */ + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_HIGHEST); break; case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel()); @@ -438,7 +446,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; if(achievementCriteria->kill_creature.creatureID != miscvalue1) continue; - SetCriteriaProgress(achievementCriteria, miscvalue2, true); + SetCriteriaProgress(achievementCriteria, miscvalue2, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: if(uint32 skillvalue = GetPlayer()->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID)) @@ -471,7 +479,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; if(GetPlayer()->GetMapId() != achievementCriteria->complete_battleground.mapID) continue; - SetCriteriaProgress(achievementCriteria, miscvalue1, true); + SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID)) @@ -487,7 +495,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; if(GetPlayer()->GetMapId() != achievementCriteria->death_at_map.mapID) continue; - SetCriteriaProgress(achievementCriteria, 1, true); + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case @@ -495,7 +503,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; if(miscvalue1 != achievementCriteria->killed_by_creature.creatureEntry) continue; - SetCriteriaProgress(achievementCriteria, 1, true); + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: { @@ -524,7 +532,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; if(achievementCriteria->use_item.itemID != miscvalue1) continue; - SetCriteriaProgress(achievementCriteria, 1, true); + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: // speedup for non-login case @@ -538,18 +546,18 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; if(miscvalue1 != achievementCriteria->own_item.itemID) continue; - SetCriteriaProgress(achievementCriteria, miscvalue2, true); + SetCriteriaProgress(achievementCriteria, miscvalue2, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: if (!miscvalue1 || miscvalue1 != achievementCriteria->be_spell_target.spellID) continue; - SetCriteriaProgress(achievementCriteria, 1, true); + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) continue; - SetCriteriaProgress(achievementCriteria, 1, true); + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: { @@ -572,7 +580,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; } - SetCriteriaProgress(achievementCriteria, 1, true); + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; } case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: @@ -654,7 +662,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if(!pProto || pProto->ItemLevel ID, newValue); + sLog.outDetail("AchievementMgr::SetCriteriaProgress(%u, %u) for (GUID:%u)", entry->ID, changeValue); CriteriaProgress *progress = NULL; CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID); @@ -885,18 +893,30 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, if(iter == m_criteriaProgress.end()) { // not create record for 0 counter - if(newValue == 0) + if(changeValue == 0) return; progress = &m_criteriaProgress[entry->ID]; - progress->counter = newValue; + progress->counter = changeValue; progress->date = time(NULL); } else { progress = &iter->second; - if(relative) - newValue += progress->counter; + + uint32 newValue; + switch(ptype) + { + case PROGRESS_SET: + newValue = changeValue; + break; + case PROGRESS_ACCUMULATE: + newValue = progress->counter + changeValue; + break; + case PROGRESS_HIGHEST: + newValue = progress->counter < changeValue ? changeValue : progress->counter; + break; + } // not update (not mark as changed) if counter will have same value if(progress->counter == newValue) diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index 7c3b90cc1..af637bcc2 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -104,9 +104,10 @@ class AchievementMgr Player* GetPlayer() { return m_player;} private: + enum ProgressType { PROGRESS_SET, PROGRESS_ACCUMULATE, PROGRESS_HIGHEST }; void SendAchievementEarned(AchievementEntry const* achievement); void SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress); - void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative=false); + void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype = PROGRESS_SET); void CompletedCriteria(AchievementCriteriaEntry const* entry); void CompletedAchievement(AchievementEntry const* entry); bool IsCompletedCriteria(AchievementCriteriaEntry const* entry); diff --git a/src/game/AuctionHouseHandler.cpp b/src/game/AuctionHouseHandler.cpp index ac9ef7131..d12018fb1 100644 --- a/src/game/AuctionHouseHandler.cpp +++ b/src/game/AuctionHouseHandler.cpp @@ -358,6 +358,7 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) } auction->bidder = pl->GetGUIDLow(); auction->bid = price; + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); // after this update we should save player's money ... CharacterDatabase.PExecute("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); @@ -381,6 +382,7 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) } auction->bidder = pl->GetGUIDLow(); auction->bid = auction->buyout; + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); auctionmgr.SendAuctionSalePendingMail( auction ); auctionmgr.SendAuctionSuccessfulMail( auction ); diff --git a/src/game/AuctionHouseMgr.cpp b/src/game/AuctionHouseMgr.cpp index f0699d62e..84457c570 100644 --- a/src/game/AuctionHouseMgr.cpp +++ b/src/game/AuctionHouseMgr.cpp @@ -223,6 +223,8 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail( AuctionEntry * auction ) if (owner) { + //FIXME: what do if owner offline + owner->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD, auction->bid); //send auction owner notification, bidder must be current! owner->GetSession()->SendAuctionOwnerNotification( auction ); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a3e533120..83e54a2b6 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 "7379" + #define REVISION_NR "7380" #endif // __REVISION_NR_H__ From 10f264845512ed9716f240bd942184501d7b3870 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 5 Mar 2009 15:46:56 +0300 Subject: [PATCH 21/28] [7381] Sort cases in AchievementMgr::UpdateAchievementCriteria and mark some case as not used. --- src/game/AchievementMgr.cpp | 369 ++++++++++++++++++------------------ src/shared/revision_nr.h | 2 +- 2 files changed, 190 insertions(+), 181 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 43e889622..d4dd1faa8 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -434,12 +434,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_HIGHEST); break; - case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: - SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel()); - break; - case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: - SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1); - break; + + // specialized cases + case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) @@ -448,10 +445,17 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; SetCriteriaProgress(achievementCriteria, miscvalue2, PROGRESS_ACCUMULATE); break; + case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: + SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel()); + break; case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: if(uint32 skillvalue = GetPlayer()->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID)) SetCriteriaProgress(achievementCriteria, skillvalue); break; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: + if(m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end()) + SetCriteriaProgress(achievementCriteria, 1); + break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT: { uint32 counter =0; @@ -481,14 +485,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_ACCUMULATE); break; - case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: - if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID)) - SetCriteriaProgress(achievementCriteria, 1); - break; - case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: - if(m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end()) - SetCriteriaProgress(achievementCriteria, 1); - break; case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) @@ -526,28 +522,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID)) SetCriteriaProgress(achievementCriteria, 1); break; - case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: - // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case - if(!miscvalue1) - continue; - if(achievementCriteria->use_item.itemID != miscvalue1) - continue; - SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); - break; - case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: - // speedup for non-login case - if(miscvalue1 && achievementCriteria->own_item.itemID!=miscvalue1) - continue; - SetCriteriaProgress(achievementCriteria, GetPlayer()->GetItemCount(achievementCriteria->own_item.itemID, true)); - break; - case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: - // You _have_ to loot that item, just owning it when logging in does _not_ count! - if(!miscvalue1) - continue; - if(miscvalue1 != achievementCriteria->own_item.itemID) - continue; - SetCriteriaProgress(achievementCriteria, miscvalue2, PROGRESS_ACCUMULATE); - break; case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: if (!miscvalue1 || miscvalue1 != achievementCriteria->be_spell_target.spellID) @@ -559,6 +533,117 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: + if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID)) + SetCriteriaProgress(achievementCriteria, 1); + break; + case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: + // speedup for non-login case + if(miscvalue1 && achievementCriteria->own_item.itemID!=miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetItemCount(achievementCriteria->own_item.itemID, true)); + break; + case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(achievementCriteria->use_item.itemID != miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; + case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: + // You _have_ to loot that item, just owning it when logging in does _not_ count! + if(!miscvalue1) + continue; + if(miscvalue1 != achievementCriteria->own_item.itemID) + continue; + SetCriteriaProgress(achievementCriteria, miscvalue2, PROGRESS_ACCUMULATE); + break; + case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: + { + WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference); + if(!worldOverlayEntry) + break; + + int32 exploreFlag = GetAreaFlagByAreaID(worldOverlayEntry->areatableID); + if(exploreFlag < 0) + break; + + uint32 playerIndexOffset = uint32(exploreFlag) / 32; + uint32 mask = 1<< (uint32(exploreFlag) % 32); + + if(GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask) + SetCriteriaProgress(achievementCriteria, 1); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1); + break; + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION: + { + int32 reputation = GetPlayer()->GetReputation(achievementCriteria->gain_reputation.factionID); + if (reputation > 0) + SetCriteriaProgress(achievementCriteria, reputation); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION: + { + uint32 counter = 0; + const FactionStateList factionStateList = GetPlayer()->GetFactionStateList(); + for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); ++iter) + { + if(GetPlayer()->ReputationToRank(iter->second.Standing) >= REP_EXALTED) + ++counter; + } + SetCriteriaProgress(achievementCriteria, counter); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: + { + // skip for login case + if(!miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, 1); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: + case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: + { + // miscvalue1 = itemid + // miscvalue2 = diced value + if(!miscvalue1) + continue; + if(miscvalue2 != achievementCriteria->roll_greed_on_loot.rollValue) + continue; + ItemPrototype const *pProto = objmgr.GetItemPrototype( miscvalue1 ); + + uint32 requiredItemLevel = 0; + if (achievementCriteria->ID == 2412 || achievementCriteria->ID == 2358) + requiredItemLevel = 185; + + if(!pProto || pProto->ItemLevel GetSpellMap().begin(); + spellIter != GetPlayer()->GetSpellMap().end(); + ++spellIter) + { + for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first); + skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first); + ++skillIter) + { + if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine) + spellCount++; + } + } + SetCriteriaProgress(achievementCriteria, spellCount); + break; + } case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: { if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) @@ -583,151 +668,72 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; } - case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: - { - uint32 spellCount = 0; - for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin(); - spellIter != GetPlayer()->GetSpellMap().end(); - ++spellIter) - { - for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first); - skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first); - ++skillIter) - { - if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine) - spellCount++; - } - } - SetCriteriaProgress(achievementCriteria, spellCount); + // std case: not exist in DBC, not triggered in code as result + case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH: + case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER: + case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR: + case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER: + case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT: + case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING: break; - } - case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: - { - // skip for login case - if(!miscvalue1) - continue; - SetCriteriaProgress(achievementCriteria, 1); - break; - } - case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION: - { - int32 reputation = GetPlayer()->GetReputation(achievementCriteria->gain_reputation.factionID); - if (reputation > 0) - SetCriteriaProgress(achievementCriteria, reputation); - break; - } - case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION: - { - uint32 counter = 0; - const FactionStateList factionStateList = GetPlayer()->GetFactionStateList(); - for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); ++iter) - { - if(GetPlayer()->ReputationToRank(iter->second.Standing) >= REP_EXALTED) - ++counter; - } - SetCriteriaProgress(achievementCriteria, counter); - break; - } - case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: - { - WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference); - if(!worldOverlayEntry) - break; - - int32 exploreFlag = GetAreaFlagByAreaID(worldOverlayEntry->areatableID); - if(exploreFlag < 0) - break; - - uint32 playerIndexOffset = uint32(exploreFlag) / 32; - uint32 mask = 1<< (uint32(exploreFlag) % 32); - - if(GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask) - SetCriteriaProgress(achievementCriteria, 1); - break; - } - case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: - case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: - { - // miscvalue1 = itemid - // miscvalue2 = diced value - if(!miscvalue1) - continue; - if(miscvalue2 != achievementCriteria->roll_greed_on_loot.rollValue) - continue; - ItemPrototype const *pProto = objmgr.GetItemPrototype( miscvalue1 ); - - uint32 requiredItemLevel = 0; - if (achievementCriteria->ID == 2412 || achievementCriteria->ID == 2358) - requiredItemLevel = 185; - - if(!pProto || pProto->ItemLevel Date: Thu, 5 Mar 2009 16:01:19 +0300 Subject: [PATCH 22/28] [7382] Add 2 unknown field to `creature_template` sent in SMSG_CREATURE_QUERY_RESPONSE to client Signed-off-by: VladimirMangos --- sql/mangos.sql | 6 ++++-- sql/updates/7382_01_mangos_creature_template.sql | 5 +++++ sql/updates/Makefile.am | 2 ++ src/game/Creature.h | 2 ++ src/game/QueryHandler.cpp | 4 ++-- src/shared/Database/SQLStorage.cpp | 4 ++-- src/shared/revision_nr.h | 2 +- 7 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 sql/updates/7382_01_mangos_creature_template.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 0446fda2b..ae9773f02 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7376_01_mangos_spell_area` bit(1) default NULL + `required_7382_01_mangos_creature_template` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -811,6 +811,8 @@ CREATE TABLE `creature_template` ( `AIName` char(64) NOT NULL default '', `MovementType` tinyint(3) unsigned NOT NULL default '0', `InhabitType` tinyint(3) unsigned NOT NULL default '3', + `unk16` float NOT NULL default '1', + `unk17` float NOT NULL default '1', `RacialLeader` tinyint(3) unsigned NOT NULL default '0', `RegenHealth` tinyint(3) unsigned NOT NULL default '1', `equipment_id` mediumint(8) unsigned NOT NULL default '0', @@ -827,7 +829,7 @@ CREATE TABLE `creature_template` ( LOCK TABLES `creature_template` WRITE; /*!40000 ALTER TABLE `creature_template` DISABLE KEYS */; INSERT INTO `creature_template` VALUES -(1,1,10045,0,10045,0,'Waypoint(Only GM can see it)','Visual',NULL,1,1,64,64,0,0,0,35,35,0,0.91,1,0,14,15,0,100,2000,2200,4096,0,0,0,0,0,0,1.76,2.42,100,8,5242886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,3,0,1,0,0,0x82,''); +(1,1,10045,0,10045,0,'Waypoint(Only GM can see it)','Visual',NULL,1,1,64,64,0,0,0,35,35,0,0.91,1,0,14,15,0,100,2000,2200,4096,0,0,0,0,0,0,1.76,2.42,100,8,5242886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,3,1.0,1.0,0,1,0,0,0x82,''); /*!40000 ALTER TABLE `creature_template` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/7382_01_mangos_creature_template.sql b/sql/updates/7382_01_mangos_creature_template.sql new file mode 100644 index 000000000..9616f20a7 --- /dev/null +++ b/sql/updates/7382_01_mangos_creature_template.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_7376_01_mangos_spell_area required_7382_01_mangos_creature_template bit; + +ALTER TABLE creature_template + ADD COLUMN unk16 float NOT NULL default '1' AFTER InhabitType, + ADD COLUMN unk17 float NOT NULL default '1' AFTER unk16; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 1a5f4d469..138a68cf7 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -190,6 +190,7 @@ pkgdata_DATA = \ 7349_01_mangos_spell_area.sql \ 7369_01_mangos_quest_template.sql \ 7376_01_mangos_spell_area.sql \ + 7382_01_mangos_creature_template.sql \ README ## Additional files to include when running 'make dist' @@ -360,4 +361,5 @@ EXTRA_DIST = \ 7349_01_mangos_spell_area.sql \ 7369_01_mangos_quest_template.sql \ 7376_01_mangos_spell_area.sql \ + 7382_01_mangos_creature_template.sql \ README diff --git a/src/game/Creature.h b/src/game/Creature.h index 59c655477..90a83df10 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -195,6 +195,8 @@ struct CreatureInfo char const* AIName; uint32 MovementType; uint32 InhabitType; + float unk16; + float unk17; bool RacialLeader; bool RegenHealth; uint32 equipmentId; diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp index 45195ec56..42ca28e25 100644 --- a/src/game/QueryHandler.cpp +++ b/src/game/QueryHandler.cpp @@ -189,8 +189,8 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data ) data << (uint32)ci->DisplayID_H; // modelid_female1 ? data << (uint32)ci->DisplayID_A2; // modelid_male2 ? data << (uint32)ci->DisplayID_H2; // modelid_femmale2 ? - data << (float)1.0f; // unk - data << (float)1.0f; // unk + data << (float)ci->unk16; // unk + data << (float)ci->unk17; // unk data << (uint8)ci->RacialLeader; SendPacket( &data ); sLog.outDebug( "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE " ); diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp index b6a51064b..dbeee6540 100644 --- a/src/shared/Database/SQLStorage.cpp +++ b/src/shared/Database/SQLStorage.cpp @@ -25,8 +25,8 @@ extern DatabasePostgre WorldDatabase; extern DatabaseMysql WorldDatabase; #endif -const char CreatureInfosrcfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiis"; -const char CreatureInfodstfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiii"; +const char CreatureInfosrcfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiifflliiis"; +const char CreatureInfodstfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiifflliiii"; const char CreatureDataAddonInfofmt[]="iiiiiiis"; const char CreatureModelfmt[]="iffbi"; const char CreatureInfoAddonInfofmt[]="iiiiiiis"; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 4cfe42ae4..b3a576dcd 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 "7381" + #define REVISION_NR "7382" #endif // __REVISION_NR_H__ From 5179230901d4204748417b24f63aacf7991b4557 Mon Sep 17 00:00:00 2001 From: Triply Date: Thu, 5 Mar 2009 16:48:00 +0100 Subject: [PATCH 23/28] [7383] Changed some comments in config file, changed default MaxRatingDifference from 100 to 150 in default config. Signed-off-by: Triply --- src/game/World.cpp | 10 ++++---- src/mangosd/mangosd.conf.dist.in | 40 ++++++++++++++++---------------- src/shared/revision_nr.h | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/game/World.cpp b/src/game/World.cpp index 0c7d222f9..0f3f1086f 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -552,9 +552,9 @@ void World::LoadConfigSettings(bool reload) } m_configs[CONFIG_ADDON_CHANNEL] = sConfig.GetBoolDefault("AddonChannel", true); m_configs[CONFIG_GRID_UNLOAD] = sConfig.GetBoolDefault("GridUnload", true); - m_configs[CONFIG_INTERVAL_SAVE] = sConfig.GetIntDefault("PlayerSaveInterval", 900000); + m_configs[CONFIG_INTERVAL_SAVE] = sConfig.GetIntDefault("PlayerSaveInterval", 15 * MINUTE * IN_MILISECONDS); - m_configs[CONFIG_INTERVAL_GRIDCLEAN] = sConfig.GetIntDefault("GridCleanUpDelay", 300000); + m_configs[CONFIG_INTERVAL_GRIDCLEAN] = sConfig.GetIntDefault("GridCleanUpDelay", 5 * MINUTE * IN_MILISECONDS); if(m_configs[CONFIG_INTERVAL_GRIDCLEAN] < MIN_GRID_DELAY) { sLog.outError("GridCleanUpDelay (%i) must be greater %u. Use this minimal value.",m_configs[CONFIG_INTERVAL_GRIDCLEAN],MIN_GRID_DELAY); @@ -572,7 +572,7 @@ void World::LoadConfigSettings(bool reload) if(reload) MapManager::Instance().SetMapUpdateInterval(m_configs[CONFIG_INTERVAL_MAPUPDATE]); - m_configs[CONFIG_INTERVAL_CHANGEWEATHER] = sConfig.GetIntDefault("ChangeWeatherInterval", 600000); + m_configs[CONFIG_INTERVAL_CHANGEWEATHER] = sConfig.GetIntDefault("ChangeWeatherInterval", 10 * MINUTE * IN_MILISECONDS); if(reload) { @@ -764,7 +764,7 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_CAST_UNSTUCK] = sConfig.GetBoolDefault("CastUnstuck", true); m_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfig.GetIntDefault("Instance.ResetTimeHour", 4); - m_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfig.GetIntDefault("Instance.UnloadDelay", 1800000); + m_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfig.GetIntDefault("Instance.UnloadDelay", 30 * MINUTE * IN_MILISECONDS); m_configs[CONFIG_MAX_PRIMARY_TRADE_SKILL] = sConfig.GetIntDefault("MaxPrimaryTradeSkill", 2); m_configs[CONFIG_MIN_PETITION_SIGNS] = sConfig.GetIntDefault("MinPetitionSigns", 9); @@ -932,7 +932,7 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_BATTLEGROUND_INVITATION_TYPE] = sConfig.GetIntDefault ("Battleground.InvitationType", 0); m_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfig.GetIntDefault ("BattleGround.PrematureFinishTimer", 5 * MINUTE * IN_MILISECONDS); m_configs[CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH] = sConfig.GetIntDefault ("BattleGround.PremadeGroupWaitForMatch", 30 * MINUTE * IN_MILISECONDS); - m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault ("Arena.MaxRatingDifference", 100); + m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault ("Arena.MaxRatingDifference", 150); m_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfig.GetIntDefault ("Arena.RatingDiscardTimer", 10 * MINUTE * IN_MILISECONDS); m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfig.GetBoolDefault("Arena.AutoDistributePoints", false); m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfig.GetIntDefault ("Arena.AutoDistributeInterval", 7); diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 268d81457..a6a7f29bd 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -94,7 +94,7 @@ BindIP = "0.0.0.0" # # SocketSelectTime # Socket select time (in milliseconds) -# Default: 10000 +# Default: 10000 (10 secs) # # GridCleanUpDelay # Grid clean up delay (in milliseconds) @@ -115,8 +115,8 @@ BindIP = "0.0.0.0" # vmap.enableLOS # vmap.enableHeight # Enable/Disable VMmap support for line of sight and height calculation -# Default: 1 (true) -# 0 (false) +# Default: 0 (disable) +# 1 (enable) # # vmap.ignoreMapIds # Map id that will be ignored by VMaps @@ -504,7 +504,7 @@ LogColors = "" # # Instance.UnloadDelay # Unload the instance map from memory after some time if no players are inside. -# Default: 1800000 (miliseconds, i.e 30 minutes) +# Default: 1800000 (miliseconds 30 minutes) # 0 (instance maps are kept in memory until they are reset) # # Quests.LowLevelHideDiff @@ -841,7 +841,7 @@ Channel.SilentlyGMJoin = 0 # 1 (enable) # # GM.InGMList -# Is GM showed in GM list (if visible) in non-GM state (.gmoff) +# Is GM showed in GM list (if visible) in non-GM state (.gm off) # Default: 0 (false) # 1 (true) # @@ -866,8 +866,8 @@ Channel.SilentlyGMJoin = 0 # # GM.AllowAchievementGain # If enabled it allows gaining achievements for GM characters -# Default: 0 (disable) -# 1 (enable) (default) +# Default: 1 (enable) +# 0 (disable) # ################################################################################################################### @@ -1052,7 +1052,7 @@ Visibility.Distance.Grey.Object = 10 # # Death.Bones.World # Death.Bones.BattlegroundOrArena -# Enabled/disabled creating bones instead corpse at resurrection (in normal zones/instacnes, or battleground/arenas) +# Enable/disable creating bones instead corpse at resurrection (in normal zones/instacnes, or battleground/arenas) # Default: 1 (enabled) # 0 (disabled) # @@ -1116,19 +1116,19 @@ Death.Bones.BattlegroundOrArena = 1 # BATTLEGROUND CONFIG # # Battleground.CastDeserter -# Cast or not Deserter spell at player who leave battleground in progress -# Default: 1 (true) -# 0 (false) +# Cast Deserter spell at player who leave battleground in progress +# Default: 1 (enable) +# 0 (disable) # # Battleground.QueueAnnouncer.Enable # Enable queue announcer posting to chat -# Default: 0 (false) -# 1 (true) +# Default: 0 (disable) +# 1 (enable) # # Battleground.QueueAnnouncer.PlayerOnly # Enable queue announcer posting to chat -# Default: 0 (false) -# 1 (true) +# Default: 0 (disable) +# 1 (enable) # # Battleground.InvitationType # Set Battleground invitation type @@ -1160,7 +1160,7 @@ BattleGround.PremadeGroupWaitForMatch = 1800000 # # Arena.MaxRatingDifference # The maximum rating difference between two groups in rated matches -# Default: 100 (enable, recommended) +# Default: 150 (enable, recommended) # 0 (disable, rating difference is discarded) # # Arena.RatingDiscardTimer @@ -1168,7 +1168,7 @@ BattleGround.PremadeGroupWaitForMatch = 1800000 # rating information will be discarded when selecting teams for matches # also initiates an update by this timer # Default: 600000 (10 minutes, recommended) -# 0 (disable, DO NOT USE - it will cause lags) +# 0 (disable) # # Arena.AutoDistributePoints # Set if arena points should be distributed automatically, or by GM command @@ -1182,8 +1182,8 @@ BattleGround.PremadeGroupWaitForMatch = 1800000 # # Arena.QueueAnnouncer.Enable # Enable bg queue announcer posting to chat -# Default: 0 (false) -# 1 (true) +# Default: 0 (disable) +# 1 (enable) # # Arena.ArenaSeason.ID # Current area season id show in client @@ -1196,7 +1196,7 @@ BattleGround.PremadeGroupWaitForMatch = 1800000 # ################################################################################################################### -Arena.MaxRatingDifference = 100 +Arena.MaxRatingDifference = 150 Arena.RatingDiscardTimer = 600000 Arena.AutoDistributePoints = 0 Arena.AutoDistributeInterval = 7 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b3a576dcd..636d96466 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 "7382" + #define REVISION_NR "7383" #endif // __REVISION_NR_H__ From bfa785fdb8633025d9b1421d1e124792598b1cf6 Mon Sep 17 00:00:00 2001 From: Triply Date: Thu, 5 Mar 2009 22:25:39 +0100 Subject: [PATCH 24/28] [7384] Removed some comments. Fixed problem that queues doesn't invite new players to already running battlegrounds. Some other fixes for announce system will be soon. Signed-off-by: Triply --- src/game/BattleGround.cpp | 2 +- src/game/BattleGround.h | 23 ++++++++++------------- src/game/BattleGroundHandler.cpp | 2 +- src/game/BattleGroundMgr.cpp | 28 +++++++++++----------------- src/shared/revision_nr.h | 2 +- 5 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 2674fe0a9..3cb669f59 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -36,7 +36,7 @@ BattleGround::BattleGround() { m_TypeID = BattleGroundTypeId(0); m_InstanceID = 0; - m_Status = 0; + m_Status = STATUS_NONE; m_EndTime = 0; m_LastResurrectTime = 0; m_QueueId = QUEUE_ID_MAX_LEVEL_19; diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index b04eb9c71..5dd56aa11 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -111,11 +111,11 @@ const uint32 Buff_Entries[3] = { BG_OBJECTID_SPEEDBUFF_ENTRY, BG_OBJECTID_REGENB enum BattleGroundStatus { - STATUS_NONE = 0, - STATUS_WAIT_QUEUE = 1, - STATUS_WAIT_JOIN = 2, - STATUS_IN_PROGRESS = 3, - STATUS_WAIT_LEAVE = 4 // custom + STATUS_NONE = 0, // first status, should mean bg is not instance + STATUS_WAIT_QUEUE = 1, // means bg is empty and waiting for queue + STATUS_WAIT_JOIN = 2, // this means, that BG has already started and it is waiting for more players + STATUS_IN_PROGRESS = 3, // means bg is running + STATUS_WAIT_LEAVE = 4 // means some faction has won BG and it is ending }; struct BattleGroundPlayer @@ -273,7 +273,7 @@ class BattleGround BattleGroundTypeId GetTypeID() const { return m_TypeID; } BGQueueIdBasedOnLevel GetQueueId() const { return m_QueueId; } uint32 GetInstanceID() const { return m_InstanceID; } - uint32 GetStatus() const { return m_Status; } + BattleGroundStatus GetStatus() const { return m_Status; } uint32 GetStartTime() const { return m_StartTime; } uint32 GetEndTime() const { return m_EndTime; } uint32 GetLastResurrectTime() const { return m_LastResurrectTime; } @@ -286,7 +286,7 @@ class BattleGround uint32 GetMaxPlayersPerTeam() const { return m_MaxPlayersPerTeam; } uint32 GetMinPlayersPerTeam() const { return m_MinPlayersPerTeam; } - int GetStartDelayTime() const { return m_StartDelayTime; } + int32 GetStartDelayTime() const { return m_StartDelayTime; } uint8 GetArenaType() const { return m_ArenaType; } uint8 GetWinner() const { return m_Winner; } uint32 GetBattlemasterEntry() const; @@ -302,7 +302,7 @@ class BattleGround this->SetLevelRange((ID + 1) * 10 + diff, (ID + 2) * 10 - ((diff + 1) % 2)); } void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; } - void SetStatus(uint32 Status) { m_Status = Status; } + void SetStatus(BattleGroundStatus Status) { m_Status = Status; } void SetStartTime(uint32 Time) { m_StartTime = Time; } void SetEndTime(uint32 Time) { m_EndTime = Time; } void SetLastResurrectTime(uint32 Time) { m_LastResurrectTime = Time; } @@ -489,7 +489,7 @@ class BattleGround /* Battleground */ BattleGroundTypeId m_TypeID; uint32 m_InstanceID; //BattleGround Instance's GUID! - uint32 m_Status; + BattleGroundStatus m_Status; uint32 m_StartTime; uint32 m_EndTime; uint32 m_LastResurrectTime; @@ -497,9 +497,6 @@ class BattleGround uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 bool m_InBGFreeSlotQueue; // used to make sure that BG is only once inserted into the BattleGroundMgr.BGFreeSlotQueue[bgTypeId] deque bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave - // this variable is not used .... it can be found in many other ways... but to store it in BG object instance is useless - //uint8 m_BattleGroundType; // 3=BG, 4=arena - //instead of uint8 (in previous line) is bool used bool m_IsArena; uint8 m_Winner; // 0=alliance, 1=horde, 2=none int32 m_StartDelayTime; @@ -537,7 +534,7 @@ class BattleGround uint32 m_MinPlayersPerTeam; uint32 m_MinPlayers; - /* Location */ + /* Start location */ uint32 m_MapId; float m_TeamStartLocX[BG_TEAMS_COUNT]; float m_TeamStartLocY[BG_TEAMS_COUNT]; diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 0098490e1..8cb821cca 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -370,7 +370,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) BattleGroundQueueTypeId bgQueueTypeId = BATTLEGROUND_QUEUE_NONE; // get the bg what we were invited to - bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId,type); + bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, type); BattleGroundQueue::QueuedPlayersMap& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers; BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = qpMap.find(_player->GetGUID()); if(itrPlayerStatus == qpMap.end()) diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 57ac388e8..7e7291181 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -113,17 +113,18 @@ bool BattleGroundQueue::SelectionPool::KickGroup(uint32 size) // add group to selection pool // used when building selection pools -// returns true if we can invite more players, otherwise return false - (selection pool is set that time) +// returns true if we can invite more players +// returns false when selection pool is set bool BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo *ginfo, uint32 desiredCount) { //if group is larger than desired count - don't allow to add it to pool - if (!ginfo->IsInvitedToBGInstanceGUID && desiredCount >= PlayerCount + ginfo->Players.size()) + if( !ginfo->IsInvitedToBGInstanceGUID && desiredCount >= PlayerCount + ginfo->Players.size() ) { SelectedGroups.push_back(ginfo); // increase selected players count PlayerCount += ginfo->Players.size(); } - if (PlayerCount == desiredCount) + if( PlayerCount < desiredCount ) return true; return false; } @@ -553,7 +554,8 @@ bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 { for(itr = m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].begin(); itr != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].end(); ++itr) { - if( !(*itr)->IsInvitedToBGInstanceGUID && m_SelectionPools[i].AddGroup((*itr), maxPlayers) ) + //if itr can join BG and player count is less that maxPlayers, then add group to selectionpool + if( !(*itr)->IsInvitedToBGInstanceGUID && !m_SelectionPools[i].AddGroup((*itr), maxPlayers) ) break; } } @@ -575,7 +577,7 @@ bool BattleGroundQueue::CheckPremadeMatch(BGQueueIdBasedOnLevel queue_id, uint32 { //we must insert group to normal queue and erase pointer from premade queue m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + i].push_front((*itr)); - m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].erase(itr); //pop_front(); + m_QueuedGroups[queue_id][BG_QUEUE_PREMADE_ALLIANCE + i].erase(itr); } } } @@ -612,7 +614,7 @@ bool BattleGroundQueue::CheckNormalMatch(BattleGround* bg_template, BGQueueIdBas for(; itr_team[j] != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + j].end(); ++(itr_team[j])) { if( !(*(itr_team[j]))->IsInvitedToBGInstanceGUID ) - if( m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % BG_TEAMS_COUNT].GetPlayerCount()) ) + if( !m_SelectionPools[j].AddGroup(*(itr_team[j]), m_SelectionPools[(j + 1) % BG_TEAMS_COUNT].GetPlayerCount()) ) break; } // do not allow to start bg with more than 2 players more on 1 faction @@ -656,12 +658,9 @@ bool BattleGroundQueue::CheckSkirmishForSameFaction(BGQueueIdBasedOnLevel queue_ //invite players to other selection pool for(; itr_team2 != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team2) { - if( !(*itr_team2)->IsInvitedToBGInstanceGUID ) - { - m_SelectionPools[otherTeam].AddGroup(*itr_team2, minPlayersPerTeam); - if( m_SelectionPools[otherTeam].GetPlayerCount() == minPlayersPerTeam ) - break; - } + //if selection pool is full then break; + if( !(*itr_team2)->IsInvitedToBGInstanceGUID && !m_SelectionPools[otherTeam].AddGroup(*itr_team2, minPlayersPerTeam) ) + break; } if( m_SelectionPools[otherTeam].GetPlayerCount() != minPlayersPerTeam ) return false; @@ -1533,11 +1532,6 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeI // reset the new bg (set status to status_wait_queue from status_none) bg->Reset(); - if( bg->isBattleGround() && sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) - { - sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, bg->GetName(), bg->GetMinLevel(), bg->GetMaxLevel()); - } - // start the joining of the bg bg->SetStatus(STATUS_WAIT_JOIN); bg->SetQueueId(queue_id); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 636d96466..780e1fce4 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 "7383" + #define REVISION_NR "7384" #endif // __REVISION_NR_H__ From c18d20782b84a512b9cb92bcbc93e6ff016b71b2 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 6 Mar 2009 01:10:54 +0300 Subject: [PATCH 25/28] Implement some death related achievements * ACHIEVEMENT_CRITERIA_TYPE_DEATH (normal and arena types counting) * ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON (instance types by man limit counting) Note: need fixed for cases when max allowed players different from recommended count. * ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM (environment damage sources by types) Fixed: * ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER - self-kill counting as death from players - same team player kill in opposition kills counter. Also cleanup in Player::EnvironmentalDamage use DBCStructure.h comment. --- src/game/AchievementMgr.cpp | 112 +++++++++++++++++++++++++- src/game/Player.cpp | 26 +++--- src/game/Unit.cpp | 9 ++- src/shared/Database/DBCStructure.h | 124 +++++++++++++++-------------- 4 files changed, 195 insertions(+), 76 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index d4dd1faa8..b06a2f1c7 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -27,6 +27,7 @@ #include "GameEvent.h" #include "World.h" #include "SpellMgr.h" +#include "ArenaTeam.h" #include "ProgressBar.h" #include "GridNotifiersImpl.h" #include "CellImpl.h" @@ -374,6 +375,18 @@ void AchievementMgr::CheckAllAchievementCriteria() UpdateAchievementCriteria(AchievementCriteriaTypes(i)); } +static const uint32 achievIdByArenaSlot[MAX_ARENA_SLOT] = { 1057, 1107, 1108 }; +static const uint32 achievIdForDangeon[][4] = +{ + // ach_cr_id,is_dungeon,is_raid,is_heroic_dungeon + { 321, true, true, true }, + { 916, false, true, false }, + { 917, false, true, false }, + { 918, true, false, false }, + { 2219, false, false, true }, + { 0, false, false, false } +}; + /** * this function will be called whenever the user might have done a criteria relevant action */ @@ -408,7 +421,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui { // std. case: increment at 1 case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: - case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; @@ -493,6 +505,79 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; + case ACHIEVEMENT_CRITERIA_TYPE_DEATH: + { + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + // skip wrong arena achievements, if not achievIdByArenaSlot then normal totla death counter + bool notfit = false; + for(int i = 0; i < MAX_ARENA_SLOT; ++i) + { + if(achievIdByArenaSlot[i] == achievement->ID) + { + BattleGround* bg = GetPlayer()->GetBattleGround(); + if(!bg || ArenaTeam::GetSlotByType(bg->GetArenaType())!=i) + notfit = true; + + break; + } + } + if(notfit) + continue; + + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON: + { + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + + Map const* map = GetPlayer()->GetMap(); + if(!map->IsDungeon()) + continue; + + // search case + bool found = false; + for(int i = 0; achievIdForDangeon[i][0]; ++i) + { + if(achievIdForDangeon[i][0] == achievement->ID) + { + if(map->IsRaid()) + { + // if raid accepted (ignore difficulty) + if(!achievIdForDangeon[i][2]) + break; // for + } + else if(GetPlayer()->GetDifficulty()==DIFFICULTY_NORMAL) + { + // dungeon in normal mode accepted + if(!achievIdForDangeon[i][1]) + break; // for + } + else + { + // dungeon in heroic mode accepted + if(!achievIdForDangeon[i][3]) + break; // for + } + + found = true; + break; // for + } + } + if(!found) + continue; + + //FIXME: work only for instances where max==min for players + if(((InstanceMap*)map)->GetMaxPlayers() != achievementCriteria->death_in_dungeon.manLimit) + continue; + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; + + } case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE: // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) @@ -501,6 +586,17 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; + case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + + // if team check required: must kill by opposition faction + if(achievement->ID==318 && miscvalue2==GetPlayer()->GetTeam()) + continue; + + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: { // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case @@ -518,6 +614,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, miscvalue1); break; } + case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(miscvalue2 != achievementCriteria->death_from.type) + continue; + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID)) SetCriteriaProgress(achievementCriteria, 1); @@ -680,10 +784,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY: case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE: - case ACHIEVEMENT_CRITERIA_TYPE_DEATH: - case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID: - case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM: case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE: case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA: case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: @@ -836,8 +937,11 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: + case ACHIEVEMENT_CRITERIA_TYPE_DEATH: + case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON: case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE: case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: + case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM: case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS: case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER: case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL: diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 15d8784c1..e42f8d1e8 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -839,6 +839,9 @@ void Player::StopMirrorTimer(MirrorTimerType Type) void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 damage) { + if(!isAlive() || isGameMaster()) + return; + WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21)); data << (uint64)guid; data << (uint8)(type!=DAMAGE_FALL_TO_VOID ? type : DAMAGE_FALL); @@ -849,13 +852,18 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - if(type==DAMAGE_FALL && !isAlive()) // DealDamage not apply item durability loss at self damage + if(!isAlive()) { - DEBUG_LOG("We are fall to death, loosing 10 percents durability"); - DurabilityLossAll(0.10f,false); - // durability lost message - WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 0); - GetSession()->SendPacket(&data); + if(type==DAMAGE_FALL) // DealDamage not apply item durability loss at self damage + { + DEBUG_LOG("We are fall to death, loosing 10 percents durability"); + DurabilityLossAll(0.10f,false); + // durability lost message + WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 0); + GetSession()->SendPacket(&data); + } + + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM, 1, type); } } @@ -939,9 +947,7 @@ void Player::HandleLava() uint64 guid = GetGUID(); uint32 damage = urand(600, 700); // TODO: Get more detailed information about lava damage - // if not gamemaster then deal damage - if ( !isGameMaster() ) - EnvironmentalDamage(guid, DAMAGE_LAVA, damage); + EnvironmentalDamage(guid, DAMAGE_LAVA, damage); m_breathTimer = 1*IN_MILISECONDS; } @@ -1326,6 +1332,8 @@ void Player::setDeathState(DeathState s) if(!ressSpellId) ressSpellId = GetResurrectionSpellId(); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, 1); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH, 1); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON, 1); } Unit::setDeathState(s); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 5e5eb564d..0d79bde04 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -528,6 +528,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if (pVictim->GetTypeId() == TYPEID_UNIT && !((Creature*)pVictim)->isPet() && !((Creature*)pVictim)->hasLootRecipient()) ((Creature*)pVictim)->SetLootRecipient(this); + if (health <= damage) { DEBUG_LOG("DealDamage: victim just died"); @@ -604,12 +605,12 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa ((Creature*)this)->AI()->KilledUnit(pVictim); // achievement stuff - if ( pVictim->GetTypeId() == TYPEID_PLAYER) + if (pVictim->GetTypeId() == TYPEID_PLAYER) { - if(GetTypeId() == TYPEID_UNIT) + if (GetTypeId() == TYPEID_UNIT) ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry()); - else if(GetTypeId() == TYPEID_PLAYER) - ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1); + else if(GetTypeId() == TYPEID_PLAYER && pVictim != this) + ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1, ((Player*)this)->GetTeam()); } // 10% durability loss on death diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 56812f7f2..60d354863 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -72,7 +72,7 @@ struct AchievementCriteriaEntry uint32 requiredType; // 2 union { - // ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0 + // ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0 // TODO: also used for player deaths.. struct { @@ -80,7 +80,7 @@ struct AchievementCriteriaEntry uint32 creatureCount; // 4 } kill_creature; - // ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1 + // ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1 // TODO: there are further criterias instead just winning struct { @@ -88,27 +88,27 @@ struct AchievementCriteriaEntry uint32 winCount; // 4 } win_bg; - // ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5 + // ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5 struct { uint32 unused; // 3 uint32 level; // 4 } reach_level; - // ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7 + // ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7 struct { uint32 skillID; // 3 uint32 skillLevel; // 4 } reach_skill_level; - // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8 + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8 struct { uint32 linkedAchievement; // 3 } complete_achievement; - // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9 + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9 struct { uint32 unused; // 3 @@ -129,67 +129,73 @@ struct AchievementCriteriaEntry uint32 questCount; // 4 } complete_quests_in_zone; - // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14 + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14 struct { uint32 unused; // 3 uint32 questCount; // 4 } complete_daily_quest; - // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND= 15 + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15 struct { uint32 mapID; // 3 } complete_battleground; - // ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP= 16 + // ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP = 16 struct { uint32 mapID; // 3 } death_at_map; - // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19 + // ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18 + struct + { + uint32 manLimit; // 3 + } death_in_dungeon; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19 struct { uint32 groupSize; // 3 can be 5, 10 or 25 } complete_raid; - // ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20 + // ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20 struct { uint32 creatureEntry; // 3 } killed_by_creature; - // ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24 + // ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24 struct { uint32 unused; // 3 uint32 fallHeight; // 4 } fall_without_dying; - // ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26 + // ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26 struct { - uint32 type; // 0 - fatigue, 1 - drowning, 2 - falling, 3 - ??, 5 - fire and lava - } deaths; + uint32 type; // 3, see enum EnviromentalDamage + } death_from; - // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27 + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27 struct { uint32 questID; // 3 uint32 questCount; // 4 } complete_quest; - // ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28 - // ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2= 69 + // ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28 + // ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 = 69 struct { uint32 spellID; // 3 uint32 spellCount; // 4 } be_spell_target; - // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL= 29 - // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110 + // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL = 29 + // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110 struct { uint32 spellID; // 3 @@ -203,32 +209,32 @@ struct AchievementCriteriaEntry uint32 killCount; // 4 } honorable_kill_at_area; - // ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32 + // ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32 struct { uint32 mapID; // 3 Reference to Map.dbc } win_arena; - // ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33 + // ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33 struct { uint32 mapID; // 3 Reference to Map.dbc } play_arena; - // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34 + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34 struct { uint32 spellID; // 3 Reference to Map.dbc } learn_spell; - // ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36 + // ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36 struct { uint32 itemID; // 3 uint32 itemCount; // 4 } own_item; - // ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37 + // ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37 struct { uint32 unused; // 3 @@ -236,62 +242,62 @@ struct AchievementCriteriaEntry uint32 flag; // 5 4=in a row } win_rated_arena; - // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38 + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38 struct { uint32 teamtype; // 3 {2,3,5} } highest_team_rating; - // ACHIEVEMENT_CRITERIA_TYPE_REACH_TEAM_RATING = 39 + // ACHIEVEMENT_CRITERIA_TYPE_REACH_TEAM_RATING = 39 struct { uint32 teamtype; // 3 {2,3,5} uint32 teamrating; // 4 } reach_team_rating; - // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40 + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40 struct { uint32 skillID; // 3 uint32 skillLevel; // 4 apprentice=1, journeyman=2, expert=3, artisan=4, master=5, grand master=6 } learn_skill_level; - // ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41 + // ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41 struct { uint32 itemID; // 3 uint32 itemCount; // 4 } use_item; - // ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42 + // ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42 struct { uint32 itemID; // 3 uint32 itemCount; // 4 } loot_item; - // ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43 + // ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43 struct { // TODO: This rank is _NOT_ the index from AreaTable.dbc uint32 areaReference; // 3 } explore_area; - // ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK= 44 + // ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK = 44 struct { // TODO: This rank is _NOT_ the index from CharTitles.dbc uint32 rank; // 3 } own_rank; - // ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT= 45 + // ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT = 45 struct { uint32 unused; // 3 uint32 numberOfSlots; // 4 } buy_bank_slot; - // ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION= 46 + // ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION = 46 struct { uint32 factionID; // 3 @@ -305,56 +311,56 @@ struct AchievementCriteriaEntry uint32 numberOfExaltedFactions; // 4 } gain_exalted_reputation; - // ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP = 48 + // ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP = 48 struct { uint32 unused; // 3 uint32 numberOfVisits; // 4 } visit_barber; - // ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49 + // ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49 // TODO: where is the required itemlevel stored? struct { uint32 itemSlot; // 3 } equip_epic_item; - // ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT= 50 + // ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50 struct { uint32 rollValue; // 3 uint32 count; // 4 } roll_need_on_loot; - // ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT= 51 + // ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT = 51 struct { uint32 rollValue; // 3 uint32 count; // 4 } roll_greed_on_loot; - // ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52 + // ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52 struct { uint32 classID; // 3 uint32 count; // 4 } hk_class; - // ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53 + // ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53 struct { uint32 raceID; // 3 uint32 count; // 4 } hk_race; - // ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54 + // ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54 // TODO: where is the information about the target stored? struct { uint32 emoteID; // 3 } do_emote; - // ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13 - // ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55 - // ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56 + // ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13 + // ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55 + // ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56 struct { uint32 unused; // 3 @@ -363,13 +369,13 @@ struct AchievementCriteriaEntry uint32 mapid; // 6 } healing_done; - // ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57 + // ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57 struct { uint32 itemID; // 3 } equip_item; - // ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62 + // ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD= 62 struct { uint32 unused; // 3 @@ -377,21 +383,21 @@ struct AchievementCriteriaEntry } quest_reward_money; - // ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67 + // ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67 struct { uint32 unused; // 3 uint32 goldInCopper; // 4 } loot_money; - // ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68 + // ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68 struct { uint32 goEntry; // 3 uint32 useCount; // 4 } use_gameobject; - // ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL= 70 + // ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL = 70 // TODO: are those special criteria stored in the dbc or do we have to add another sql table? struct { @@ -399,66 +405,66 @@ struct AchievementCriteriaEntry uint32 killCount; // 4 } special_pvp_kill; - // ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72 + // ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72 struct { uint32 goEntry; // 3 uint32 lootCount; // 4 } fish_in_gameobject; - // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS= 75 + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75 struct { uint32 skillLine; // 3 uint32 spellCount; // 4 } learn_skilline_spell; - // ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76 + // ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76 struct { uint32 unused; // 3 uint32 duelCount; // 4 } win_duel; - // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER = 96 + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER = 96 struct { uint32 powerType; // 3 mana=0, 1=rage, 3=energy, 6=runic power } highest_power; - // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT = 97 + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT = 97 struct { uint32 statType; // 3 4=spirit, 3=int, 2=stamina, 1=agi, 0=strength } highest_stat; - // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER = 98 + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER = 98 struct { uint32 spellSchool; // 3 } highest_spellpower; - // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING = 100 + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING = 100 struct { uint32 ratingType; // 3 } highest_rating; - // ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109 + // ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109 struct { uint32 lootType; // 3 3=fishing, 2=pickpocket, 4=disentchant uint32 lootTypeCount; // 4 } loot_type; - // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE= 112 + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE = 112 struct { uint32 skillLine; // 3 uint32 spellCount; // 4 } learn_skill_line; - // ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113 + // ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113 struct { uint32 unused; // 3 From 649653956a9af6d92d310fa048886c5c5d616e3e Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 6 Mar 2009 04:25:14 +0300 Subject: [PATCH 26/28] [7385] Fixed mail price calculation broken recently by me. --- src/game/Mail.cpp | 4 +--- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 52cb723c1..912ead72c 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -122,9 +122,7 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data ) return; } - uint32 cost = money + 30; - if (items_count) - cost = 30 * items_count; + uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client uint32 reqmoney = cost + money; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 780e1fce4..fb8ea9d91 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 "7384" + #define REVISION_NR "7385" #endif // __REVISION_NR_H__ From 0e7d940b90070db8f708ba9f01c7b44501019356 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 6 Mar 2009 04:28:23 +0300 Subject: [PATCH 27/28] [7386] Remove from mangos.sql content of `instance_template` table. From this point expected that this table filled from another sources. --- sql/mangos.sql | 30 ------------------------------ src/shared/revision_nr.h | 2 +- 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/sql/mangos.sql b/sql/mangos.sql index ae9773f02..a75345530 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -1472,36 +1472,6 @@ CREATE TABLE `instance_template` ( LOCK TABLES `instance_template` WRITE; /*!40000 ALTER TABLE `instance_template` DISABLE KEYS */; -INSERT INTO `instance_template` VALUES -(33,0,22,30,10,10,7200,NULL,NULL,NULL,NULL,''), -(34,0,24,32,10,10,7200,NULL,NULL,NULL,NULL,''), -(36,0,15,20,10,10,7200,NULL,NULL,NULL,NULL,''), -(43,0,15,21,10,10,7200,NULL,NULL,NULL,NULL,''), -(47,0,29,38,10,10,7200,NULL,NULL,NULL,NULL,''), -(48,0,24,32,10,10,7200,NULL,NULL,NULL,NULL,''), -(70,0,35,47,10,10,7200,NULL,NULL,NULL,NULL,''), -(90,0,29,38,10,10,7200,NULL,NULL,NULL,NULL,''), -(109,0,45,55,10,10,7200,NULL,NULL,NULL,NULL,''), -(129,0,37,46,10,10,7200,NULL,NULL,NULL,NULL,''), -(189,0,34,45,10,10,7200,NULL,NULL,NULL,NULL,''), -(209,0,44,54,10,10,7200,NULL,NULL,NULL,NULL,''), -(229,0,58,0,10,10,120000,78.5083,-225.044,49.839,5.1,''), -(230,0,52,0,5,5,7200,NULL,NULL,NULL,NULL,''), -(249,0,60,0,40,40,432000,NULL,NULL,NULL,NULL,''), -(289,0,57,0,5,5,7200,NULL,NULL,NULL,NULL,''), -(309,0,60,0,20,20,259200,NULL,NULL,NULL,NULL,''), -(329,0,58,60,5,5,7200,NULL,NULL,NULL,NULL,''), -(349,0,46,55,10,10,7200,NULL,NULL,NULL,NULL,''), -(389,0,13,18,10,10,7200,NULL,NULL,NULL,NULL,''), -(409,0,60,0,40,40,604800,NULL,NULL,NULL,NULL,''), -(429,0,55,60,5,5,7200,NULL,NULL,NULL,NULL,''), -(469,0,60,0,40,40,604800,NULL,NULL,NULL,NULL,''), -(509,0,60,0,20,20,259200,NULL,NULL,NULL,NULL,''), -(531,0,60,0,40,40,604800,NULL,NULL,NULL,NULL,''), -(533,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''), -(615,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''), -(616,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''), -(624,0,80,0,10,25,0,NULL,NULL,NULL,NULL,''); /*!40000 ALTER TABLE `instance_template` ENABLE KEYS */; UNLOCK TABLES; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index fb8ea9d91..021233920 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 "7385" + #define REVISION_NR "7386" #endif // __REVISION_NR_H__ From a07718fe29d421848656cd87c757491acac30370 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 6 Mar 2009 04:56:51 +0300 Subject: [PATCH 28/28] [7387] Check maxcount >= min count for item (not reference) record in loot templates DB tables.. --- src/game/LootMgr.cpp | 7 +++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index 591a123f8..3097cff41 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -275,6 +275,13 @@ bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const store.GetName(), entry, itemid, chance); return false; } + + if( maxcount < mincountOrRef) // wrong max count + { + sLog.outErrorDb("Table '%s' entry %d item %d: max count (%u) less that min count (%i) - skipped", store.GetName(), entry, itemid, uint32(maxcount), mincountOrRef); + return false; + } + } else // mincountOrRef < 0 { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 021233920..160925670 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 "7386" + #define REVISION_NR "7387" #endif // __REVISION_NR_H__