Merge commit 'origin/master' into 310

Conflicts:
	src/game/Player.cpp
This commit is contained in:
tomrus88 2009-05-06 09:40:35 +04:00
commit 6821c24268
27 changed files with 414 additions and 105 deletions

View file

@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`;
CREATE TABLE `db_version` ( CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL,
`required_7720_01_mangos_mangos_string` bit(1) default NULL `required_7782_01_mangos_spell_proc_event` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --

View file

@ -0,0 +1,8 @@
ALTER TABLE db_version CHANGE COLUMN required_7720_01_mangos_mangos_string required_7776_01_mangos_npc_spellclick_spells bit;
CREATE TABLE `npc_spellclick_spells` (
`npc_entry` INT UNSIGNED NOT NULL COMMENT 'reference to creature_template',
`spell_id` INT UNSIGNED NOT NULL COMMENT 'spell which should be casted ',
`quest_id` INT UNSIGNED NOT NULL COMMENT 'reference to quest_template',
`cast_flags` TINYINT UNSIGNED NOT NULL COMMENT 'first bit defines caster: 1=player, 0=creature; second bit defines target, same mapping as caster bit'
) ENGINE = MYISAM DEFAULT CHARSET=utf8;

View file

@ -0,0 +1,6 @@
ALTER TABLE db_version CHANGE COLUMN required_7776_01_mangos_npc_spellclick_spells required_7777_01_mangos_spell_proc_event bit;
DELETE FROM spell_proc_event WHERE entry IN (30299,30301,30302);
INSERT INTO spell_proc_event VALUES (30299, 0x0000007E, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);
INSERT INTO spell_proc_event VALUES (30301, 0x0000007E, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);
INSERT INTO spell_proc_event VALUES (30302, 0x0000007E, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0);

View file

@ -0,0 +1,4 @@
ALTER TABLE db_version CHANGE COLUMN required_7777_01_mangos_spell_proc_event required_7782_01_mangos_spell_proc_event bit;
DELETE FROM spell_proc_event WHERE entry = 34074;
INSERT INTO spell_proc_event VALUES (34074, 0, 9, 522819, 8917121, 513, 0, 0, 0, 0, 0);

View file

@ -177,6 +177,9 @@ pkgdata_DATA = \
7706_01_mangos_command.sql \ 7706_01_mangos_command.sql \
7714_01_mangos_command.sql \ 7714_01_mangos_command.sql \
7720_01_mangos_mangos_string.sql \ 7720_01_mangos_mangos_string.sql \
7776_01_mangos_npc_spellclick_spells.sql \
7777_01_mangos_spell_proc_event.sql \
7782_01_mangos_spell_proc_event.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -334,4 +337,7 @@ EXTRA_DIST = \
7706_01_mangos_command.sql \ 7706_01_mangos_command.sql \
7714_01_mangos_command.sql \ 7714_01_mangos_command.sql \
7720_01_mangos_mangos_string.sql \ 7720_01_mangos_mangos_string.sql \
7776_01_mangos_npc_spellclick_spells.sql \
7777_01_mangos_spell_proc_event.sql \
7782_01_mangos_spell_proc_event.sql \
README README

View file

@ -563,6 +563,11 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
// std. case: increment at 1 // std. case: increment at 1
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS: case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if(!miscvalue1) if(!miscvalue1)
continue; continue;
@ -1126,6 +1131,21 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL: case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS)); SetCriteriaProgress(achievementCriteria, GetPlayer()->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS));
break; break;
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
if (!miscvalue1 || miscvalue1 != achievementCriteria->hk_class.classID)
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
if (!miscvalue1 || miscvalue1 != achievementCriteria->hk_race.raceID)
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetMoney(), PROGRESS_HIGHEST);
break;
// std case: not exist in DBC, not triggered in code as result // std case: not exist in DBC, not triggered in code as result
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
@ -1148,26 +1168,18 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_REACH_TEAM_RATING: case ACHIEVEMENT_CRITERIA_TYPE_REACH_TEAM_RATING:
case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK: case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS: case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL: case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE: case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE: case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS: case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION: case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS: case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED: case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED: case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL: case ACHIEVEMENT_CRITERIA_TYPE_TOTAL:
break; // Not implemented yet :( break; // Not implemented yet :(
} }
@ -1234,14 +1246,15 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
} }
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
return progress->counter >= achievementCriteria->reach_skill_level.skillLevel; return progress->counter >= achievementCriteria->reach_skill_level.skillLevel;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
return progress->counter >= (achievementCriteria->learn_skill_level.skillLevel * 75);
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
return progress->counter >= 1; return progress->counter >= 1;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
return progress->counter >= achievementCriteria->complete_quest_count.totalQuestCount; return progress->counter >= achievementCriteria->complete_quest_count.totalQuestCount;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
return progress->counter >= achievementCriteria->complete_quests_in_zone.questCount; return progress->counter >= achievementCriteria->complete_quests_in_zone.questCount;
case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
return progress->counter >= achievementCriteria->healing_done.count;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
return progress->counter >= achievementCriteria->complete_daily_quest.questCount; return progress->counter >= achievementCriteria->complete_daily_quest.questCount;
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
@ -1256,10 +1269,10 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
return progress->counter >= achievementCriteria->cast_spell.castCount; return progress->counter >= achievementCriteria->cast_spell.castCount;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
return progress->counter >= 1; return progress->counter >= 1;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
return progress->counter >= achievementCriteria->loot_type.lootTypeCount;
case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
return progress->counter >= achievementCriteria->own_item.itemCount; return progress->counter >= achievementCriteria->own_item.itemCount;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
return progress->counter >= (achievementCriteria->learn_skill_level.skillLevel * 75);
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
return progress->counter >= achievementCriteria->use_item.itemCount; return progress->counter >= achievementCriteria->use_item.itemCount;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
@ -1277,11 +1290,12 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
return progress->counter >= achievementCriteria->roll_greed_on_loot.count; return progress->counter >= achievementCriteria->roll_greed_on_loot.count;
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
return progress->counter >= achievementCriteria->hk_class.count;
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
return progress->counter >= achievementCriteria->hk_race.count;
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
return progress->counter >= achievementCriteria->do_emote.count; return progress->counter >= achievementCriteria->do_emote.count;
case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
return progress->counter >= achievementCriteria->healing_done.count;
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
return progress->counter >= achievementCriteria->equip_item.count; return progress->counter >= achievementCriteria->equip_item.count;
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD: case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
@ -1294,6 +1308,10 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
return progress->counter >= achievementCriteria->fish_in_gameobject.lootCount; return progress->counter >= achievementCriteria->fish_in_gameobject.lootCount;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
return progress->counter >= achievementCriteria->learn_skillline_spell.spellCount; return progress->counter >= achievementCriteria->learn_skillline_spell.spellCount;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
return progress->counter >= achievementCriteria->win_duel.duelCount;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
return progress->counter >= achievementCriteria->loot_type.lootTypeCount;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE: case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
return progress->counter >= achievementCriteria->learn_skill_line.spellCount; return progress->counter >= achievementCriteria->learn_skill_line.spellCount;
case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL: case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
@ -1308,16 +1326,22 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM: case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS: case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER: case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL: case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION: case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION: case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS: case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR:
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
return false; return false;
} }
return false; return false;

View file

@ -420,6 +420,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPageTextsCommand, "", NULL }, { "page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPageTextsCommand, "", NULL },
{ "pickpocketing_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesPickpocketingCommand,"",NULL}, { "pickpocketing_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesPickpocketingCommand,"",NULL},
{ "points_of_interest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPointsOfInterestCommand, "",NULL}, { "points_of_interest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadPointsOfInterestCommand, "",NULL},
{ "npc_spellclick_spells", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellClickSpellsCommand, "",NULL},
{ "prospecting_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesProspectingCommand,"", NULL }, { "prospecting_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesProspectingCommand,"", NULL },
{ "quest_mail_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesQuestMailCommand, "", NULL }, { "quest_mail_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesQuestMailCommand, "", NULL },
{ "quest_end_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestEndScriptsCommand, "", NULL }, { "quest_end_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadQuestEndScriptsCommand, "", NULL },

View file

@ -345,6 +345,7 @@ class ChatHandler
bool HandleReloadNpcVendorCommand(const char* args); bool HandleReloadNpcVendorCommand(const char* args);
bool HandleReloadPageTextsCommand(const char* args); bool HandleReloadPageTextsCommand(const char* args);
bool HandleReloadPointsOfInterestCommand(const char* args); bool HandleReloadPointsOfInterestCommand(const char* args);
bool HandleReloadSpellClickSpellsCommand(const char* args);
bool HandleReloadQuestAreaTriggersCommand(const char* args); bool HandleReloadQuestAreaTriggersCommand(const char* args);
bool HandleReloadQuestEndScriptsCommand(const char* args); bool HandleReloadQuestEndScriptsCommand(const char* args);
bool HandleReloadQuestStartScriptsCommand(const char* args); bool HandleReloadQuestStartScriptsCommand(const char* args);

View file

@ -208,7 +208,7 @@ void Group::ConvertToRaid()
// update quest related GO states (quest activity dependent from raid membership) // update quest related GO states (quest activity dependent from raid membership)
for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr)
if(Player* player = objmgr.GetPlayer(citr->guid)) if(Player* player = objmgr.GetPlayer(citr->guid))
player->UpdateForQuestsGO(); player->UpdateForQuestWorldObjects();
} }
bool Group::AddInvite(Player *player) bool Group::AddInvite(Player *player)
@ -302,7 +302,7 @@ bool Group::AddMember(const uint64 &guid, const char* name)
// quest related GO state dependent from raid memebership // quest related GO state dependent from raid memebership
if(isRaidGroup()) if(isRaidGroup())
player->UpdateForQuestsGO(); player->UpdateForQuestWorldObjects();
} }
return true; return true;
@ -319,7 +319,7 @@ uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method)
{ {
// quest related GO state dependent from raid membership // quest related GO state dependent from raid membership
if(isRaidGroup()) if(isRaidGroup())
player->UpdateForQuestsGO(); player->UpdateForQuestWorldObjects();
WorldPacket data; WorldPacket data;
@ -400,7 +400,7 @@ void Group::Disband(bool hideDestroy)
// quest related GO state dependent from raid membership // quest related GO state dependent from raid membership
if(isRaidGroup()) if(isRaidGroup())
player->UpdateForQuestsGO(); player->UpdateForQuestWorldObjects();
if(!player->GetSession()) if(!player->GetSession())
continue; continue;

View file

@ -102,6 +102,7 @@ bool ChatHandler::HandleReloadAllNpcCommand(const char* /*args*/)
HandleReloadNpcTrainerCommand("a"); HandleReloadNpcTrainerCommand("a");
HandleReloadNpcVendorCommand("a"); HandleReloadNpcVendorCommand("a");
HandleReloadPointsOfInterestCommand("a"); HandleReloadPointsOfInterestCommand("a");
HandleReloadSpellClickSpellsCommand("a");
return true; return true;
} }
@ -429,6 +430,14 @@ bool ChatHandler::HandleReloadPointsOfInterestCommand(const char*)
return true; return true;
} }
bool ChatHandler::HandleReloadSpellClickSpellsCommand(const char*)
{
sLog.outString( "Re-Loading `npc_spellclick_spells` Table!" );
objmgr.LoadNPCSpellClickSpells();
SendGlobalSysMessage("DB table `npc_spellclick_spells` reloaded.");
return true;
}
bool ChatHandler::HandleReloadReservedNameCommand(const char*) bool ChatHandler::HandleReloadReservedNameCommand(const char*)
{ {
sLog.outString( "Loading ReservedNames... (`reserved_name`)" ); sLog.outString( "Loading ReservedNames... (`reserved_name`)" );

View file

@ -1564,21 +1564,6 @@ void WorldSession::HandleSetTaxiBenchmarkOpcode( WorldPacket & recv_data )
sLog.outDebug("Client used \"/timetest %d\" command", mode); sLog.outDebug("Client used \"/timetest %d\" command", mode);
} }
void WorldSession::HandleSpellClick( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data, 8);
uint64 guid;
recv_data >> guid;
Vehicle *vehicle = ObjectAccessor::GetVehicle(guid);
if(!vehicle)
return;
_player->EnterVehicle(vehicle);
}
void WorldSession::HandleInspectAchievements( WorldPacket & recv_data ) void WorldSession::HandleInspectAchievements( WorldPacket & recv_data )
{ {
CHECK_PACKET_SIZE(recv_data, 1); CHECK_PACKET_SIZE(recv_data, 1);

View file

@ -24,6 +24,7 @@
#include "Corpse.h" #include "Corpse.h"
#include "Player.h" #include "Player.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "SpellAuras.h"
#include "MapManager.h" #include "MapManager.h"
#include "Transports.h" #include "Transports.h"
#include "BattleGround.h" #include "BattleGround.h"
@ -474,8 +475,8 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
// using charm guid, because we don't have vehicle guid... // using charm guid, because we don't have vehicle guid...
if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID)) if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID))
{ {
_player->ExitVehicle(vehicle); // Aura::HandleAuraControlVehicle will call Player::ExitVehicle
vehicle->Dismiss(); vehicle->RemoveSpellsCausingAura(SPELL_AURA_CONTROL_VEHICLE);
} }
} }

View file

@ -620,9 +620,16 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
{ {
if( updateMask->GetBit( index ) ) if( updateMask->GetBit( index ) )
{ {
// remove custom flag before send
if( index == UNIT_NPC_FLAGS ) if( index == UNIT_NPC_FLAGS )
*data << uint32(m_uint32Values[ index ] & ~UNIT_NPC_FLAG_GUARD); {
// remove custom flag before sending
uint32 appendValue = m_uint32Values[ index ] & ~UNIT_NPC_FLAG_GUARD;
if (GetTypeId() == TYPEID_UNIT && !target->canSeeSpellClickOn((Creature*)this))
appendValue &= ~UNIT_NPC_FLAG_SPELLCLICK;
*data << uint32(appendValue);
}
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format // FIXME: Some values at server stored in float format but must be sent to client in uint32 format
else if(index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME) else if(index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME)
{ {

View file

@ -5927,6 +5927,76 @@ void ObjectMgr::LoadPointsOfInterest()
sLog.outString(">> Loaded %u Points of Interest definitions", count); sLog.outString(">> Loaded %u Points of Interest definitions", count);
} }
void ObjectMgr::LoadNPCSpellClickSpells()
{
uint32 count = 0;
mSpellClickInfoMap.clear();
QueryResult *result = WorldDatabase.Query("SELECT npc_entry, spell_id, quest_id, cast_flags FROM npc_spellclick_spells");
if(!result)
{
barGoLink bar(1);
bar.step();
sLog.outString();
sLog.outErrorDb(">> Loaded 0 spellclick spells. DB table `npc_spellclick_spells` is empty.");
return;
}
barGoLink bar(result->GetRowCount());
do
{
Field *fields = result->Fetch();
bar.step();
uint32 npc_entry = fields[0].GetUInt32();
CreatureInfo const* cInfo = GetCreatureTemplate(npc_entry);
if (!cInfo)
{
sLog.outErrorDb("Table npc_spellclick_spells references unknown creature_template %u. Skipping entry.", npc_entry);
continue;
}
uint32 spellid = fields[1].GetUInt32();
SpellEntry const *spellinfo = sSpellStore.LookupEntry(spellid);
if (!spellinfo)
{
sLog.outErrorDb("Table npc_spellclick_spells references unknown spellid %u. Skipping entry.", spellid);
continue;
}
uint32 quest = fields[2].GetUInt32();
// quest might be 0 to enable spellclick independent of any quest
if (quest)
{
if(mQuestTemplates.find(quest) == mQuestTemplates.end())
{
sLog.outErrorDb("Table npc_spellclick_spells references unknown quest %u. Skipping entry.", spellid);
continue;
}
}
uint8 castFlags = fields[3].GetUInt8();
SpellClickInfo info;
info.spellId = spellid;
info.questId = quest;
info.castFlags = castFlags;
mSpellClickInfoMap.insert(SpellClickInfoMap::value_type(npc_entry, info));
++count;
} while (result->NextRow());
delete result;
sLog.outString();
sLog.outString(">> Loaded %u spellclick definitions", count);
}
void ObjectMgr::LoadWeatherZoneChances() void ObjectMgr::LoadWeatherZoneChances()
{ {
uint32 count = 0; uint32 count = 0;

View file

@ -95,6 +95,15 @@ extern ScriptMapMap sSpellScripts;
extern ScriptMapMap sGameObjectScripts; extern ScriptMapMap sGameObjectScripts;
extern ScriptMapMap sEventScripts; extern ScriptMapMap sEventScripts;
struct SpellClickInfo
{
uint32 spellId;
uint32 questId;
uint8 castFlags;
};
typedef std::multimap<uint32, SpellClickInfo> SpellClickInfoMap;
struct AreaTrigger struct AreaTrigger
{ {
uint8 requiredLevel; uint8 requiredLevel;
@ -533,6 +542,9 @@ class ObjectMgr
void LoadReputationOnKill(); void LoadReputationOnKill();
void LoadPointsOfInterest(); void LoadPointsOfInterest();
SpellClickInfoMap mSpellClickInfoMap;
void LoadNPCSpellClickSpells();
void LoadWeatherZoneChances(); void LoadWeatherZoneChances();
void LoadGameTele(); void LoadGameTele();

View file

@ -552,18 +552,26 @@ void Pet::Update(uint32 diff)
} }
} }
if(getPetType() != HUNTER_PET) //regenerate focus for hunter pets or energy for deathknight's ghoul
break;
//regenerate Focus
if(m_regenTimer <= diff) if(m_regenTimer <= diff)
{ {
RegenerateFocus(); switch (getPowerType())
{
case POWER_FOCUS:
case POWER_ENERGY:
Regenerate(getPowerType());
break;
default:
break;
}
m_regenTimer = 4000; m_regenTimer = 4000;
} }
else else
m_regenTimer -= diff; m_regenTimer -= diff;
if(getPetType() != HUNTER_PET)
break;
if(m_happinessTimer <= diff) if(m_happinessTimer <= diff)
{ {
LooseHappiness(); LooseHappiness();
@ -580,22 +588,41 @@ void Pet::Update(uint32 diff)
Creature::Update(diff); Creature::Update(diff);
} }
void Pet::RegenerateFocus() void Pet::Regenerate(Powers power)
{ {
uint32 curValue = GetPower(POWER_FOCUS); uint32 curValue = GetPower(power);
uint32 maxValue = GetMaxPower(POWER_FOCUS); uint32 maxValue = GetMaxPower(power);
if (curValue >= maxValue) if (curValue >= maxValue)
return; return;
float addvalue = 24 * sWorld.getRate(RATE_POWER_FOCUS); float addvalue = 0.0f;
switch (power)
{
case POWER_FOCUS:
{
// For hunter pets.
addvalue = 24 * sWorld.getRate(RATE_POWER_FOCUS);
break;
}
case POWER_ENERGY:
{
// For deathknight's ghoul.
addvalue = 20;
break;
}
default:
return;
}
// Apply modifiers (if any).
AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT);
for(AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) for(AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i)
if ((*i)->GetModifier()->m_miscvalue == POWER_FOCUS) if ((*i)->GetModifier()->m_miscvalue == power)
addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f; addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f;
ModifyPower(POWER_FOCUS, (int32)addvalue); ModifyPower(power, (int32)addvalue);
} }
void Pet::LooseHappiness() void Pet::LooseHappiness()

View file

@ -152,7 +152,7 @@ class Pet : public Creature
return m_autospells[pos]; return m_autospells[pos];
} }
void RegenerateFocus(); void Regenerate(Powers power);
void LooseHappiness(); void LooseHappiness();
HappinessState GetHappinessState(); HappinessState GetHappinessState();
void GivePetXP(uint32 xp); void GivePetXP(uint32 xp);

View file

@ -5850,6 +5850,8 @@ bool Player::RewardHonor(Unit *uVictim, uint32 groupsize, float honor)
// and those in a lifetime // and those in a lifetime
ApplyModUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 1, true); ApplyModUInt32Value(PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 1, true);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL);
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS, pVictim->getClass());
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_RACE, pVictim->getRace());
} }
else else
{ {
@ -6179,6 +6181,13 @@ void Player::DuelComplete(DuelCompleteType type)
SendMessageToSet(&data,true); SendMessageToSet(&data,true);
} }
if (type == DUEL_WON)
{
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL, 1);
if (duel->opponent)
duel->opponent->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1);
}
// cool-down duel spell // cool-down duel spell
/*data.Initialize(SMSG_SPELL_COOLDOWN, 17); /*data.Initialize(SMSG_SPELL_COOLDOWN, 17);
@ -12240,7 +12249,7 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver )
CastSpell(this,itr->second->spellId,true); CastSpell(this,itr->second->spellId,true);
} }
UpdateForQuestsGO(); UpdateForQuestWorldObjects();
} }
void Player::CompleteQuest( uint32 quest_id ) void Player::CompleteQuest( uint32 quest_id )
@ -12971,7 +12980,7 @@ void Player::SetQuestStatus( uint32 quest_id, QuestStatus status )
if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED;
} }
UpdateForQuestsGO(); UpdateForQuestWorldObjects();
} }
// not used in MaNGOS, but used in scripting code // not used in MaNGOS, but used in scripting code
@ -13092,7 +13101,7 @@ void Player::ItemAddedQuestCheck( uint32 entry, uint32 count )
} }
} }
} }
UpdateForQuestsGO(); UpdateForQuestWorldObjects();
} }
void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count ) void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count )
@ -13133,7 +13142,7 @@ void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count )
} }
} }
} }
UpdateForQuestsGO(); UpdateForQuestWorldObjects();
} }
void Player::KilledMonster( uint32 entry, uint64 guid ) void Player::KilledMonster( uint32 entry, uint64 guid )
@ -16134,8 +16143,11 @@ bool Player::HasGuardianWithEntry(uint32 entry)
// pet guid middle part is entry (and creature also) // pet guid middle part is entry (and creature also)
// and in guardian list must be guardians with same entry _always_ // and in guardian list must be guardians with same entry _always_
for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr) for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr)
if(GUID_ENPART(*itr)==entry) {
if(Pet* pet = ObjectAccessor::GetPet(*itr))
if (pet->GetEntry() == entry)
return true; return true;
}
return false; return false;
} }
@ -16673,11 +16685,31 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_i
// starting node too far away (cheat?) // starting node too far away (cheat?)
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(sourcenode); TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(sourcenode);
if( !node || node->map_id != GetMapId() || if (!node)
{
WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
data << uint32(ERR_TAXINOSUCHPATH);
GetSession()->SendPacket(&data);
return false;
}
// check node starting pos data set case if provided
if (node->x != 0.0f || node->y != 0.0f || node->z != 0.0f)
{
if (node->map_id != GetMapId() ||
(node->x - GetPositionX())*(node->x - GetPositionX())+ (node->x - GetPositionX())*(node->x - GetPositionX())+
(node->y - GetPositionY())*(node->y - GetPositionY())+ (node->y - GetPositionY())*(node->y - GetPositionY())+
(node->z - GetPositionZ())*(node->z - GetPositionZ()) > (node->z - GetPositionZ())*(node->z - GetPositionZ()) >
(2*INTERACTION_DISTANCE)*(2*INTERACTION_DISTANCE)*(2*INTERACTION_DISTANCE) ) (2*INTERACTION_DISTANCE)*(2*INTERACTION_DISTANCE)*(2*INTERACTION_DISTANCE))
{
WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
data << uint32(ERR_TAXITOOFARAWAY);
GetSession()->SendPacket(&data);
return false;
}
}
// node must have pos if not spell case (npc!=0)
else if(npc)
{ {
WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4);
data << uint32(ERR_TAXIUNSPECIFIEDSERVERERROR); data << uint32(ERR_TAXIUNSPECIFIEDSERVERERROR);
@ -16743,10 +16775,8 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_i
uint32 money = GetMoney(); uint32 money = GetMoney();
if(npc) if (npc)
{
totalcost = (uint32)ceil(totalcost*GetReputationPriceDiscount(npc)); totalcost = (uint32)ceil(totalcost*GetReputationPriceDiscount(npc));
}
if(money < totalcost) if(money < totalcost)
{ {
@ -16760,6 +16790,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_i
//Checks and preparations done, DO FLIGHT //Checks and preparations done, DO FLIGHT
ModifyMoney(-(int32)totalcost); ModifyMoney(-(int32)totalcost);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1);
// prevent stealth flight // prevent stealth flight
RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
@ -18262,7 +18293,7 @@ bool Player::HasQuestForGO(int32 GOId) const
return false; return false;
} }
void Player::UpdateForQuestsGO() void Player::UpdateForQuestWorldObjects()
{ {
if(m_clientGUIDs.empty()) if(m_clientGUIDs.empty())
return; return;
@ -18277,6 +18308,24 @@ void Player::UpdateForQuestsGO()
if(obj) if(obj)
obj->BuildValuesUpdateBlockForPlayer(&udata,this); obj->BuildValuesUpdateBlockForPlayer(&udata,this);
} }
else if(IS_CREATURE_GUID(*itr) || IS_VEHICLE_GUID(*itr))
{
Creature *obj = ObjectAccessor::GetCreatureOrPetOrVehicle(*this, *itr);
if(!obj)
continue;
// check if this unit requires quest specific flags
SpellClickInfoMap const& map = objmgr.mSpellClickInfoMap;
for(SpellClickInfoMap::const_iterator itr = map.lower_bound(obj->GetEntry()); itr != map.upper_bound(obj->GetEntry()); ++itr)
{
if(itr->second.questId != 0)
{
obj->BuildCreateUpdateBlockForPlayer(&udata,this);
break;
}
}
}
} }
udata.BuildPacket(&packet); udata.BuildPacket(&packet);
GetSession()->SendPacket(&packet); GetSession()->SendPacket(&packet);
@ -18308,6 +18357,8 @@ void Player::SummonIfPossible(bool agree)
m_summon_expire = 0; m_summon_expire = 0;
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS, 1);
TeleportTo(m_summon_mapid, m_summon_x, m_summon_y, m_summon_z,GetOrientation()); TeleportTo(m_summon_mapid, m_summon_x, m_summon_y, m_summon_z,GetOrientation());
} }
@ -19141,8 +19192,8 @@ void Player::ExitVehicle(Vehicle *vehicle)
data << uint32(0); data << uint32(0);
GetSession()->SendPacket(&data); GetSession()->SendPacket(&data);
// only for flyable vehicles? // maybe called at dummy aura remove?
CastSpell(this, 45472, true); // Parachute // CastSpell(this, 45472, true); // Parachute
} }
bool Player::isTotalImmune() bool Player::isTotalImmune()
@ -19787,6 +19838,17 @@ void Player::ResummonPetTemporaryUnSummonedIfAny()
m_temporaryUnsummonedPetNumber = 0; m_temporaryUnsummonedPetNumber = 0;
} }
bool Player::canSeeSpellClickOn(Creature const *c) const
{
SpellClickInfoMap const& map = objmgr.mSpellClickInfoMap;
for(SpellClickInfoMap::const_iterator itr = map.lower_bound(c->GetEntry()); itr != map.upper_bound(c->GetEntry()); ++itr)
{
if(itr->second.questId == 0 || GetQuestStatus(itr->second.questId) == QUEST_STATUS_INCOMPLETE)
return true;
}
return false;
}
void Player::BuildPlayerTalentsInfoData(WorldPacket *data) void Player::BuildPlayerTalentsInfoData(WorldPacket *data)
{ {
*data << uint32(GetFreeTalentPoints()); // unspentTalentPoints *data << uint32(GetFreeTalentPoints()); // unspentTalentPoints
@ -20072,6 +20134,7 @@ void Player::_SaveEquipmentSets()
break; break;
} }
} }
return false;
} }
void Player::DeleteEquipmentSet(uint64 setGuid) void Player::DeleteEquipmentSet(uint64 setGuid)
@ -20084,4 +20147,3 @@ void Player::DeleteEquipmentSet(uint64 setGuid)
break; break;
} }
} }
}

View file

@ -1208,7 +1208,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void ReputationChanged(FactionEntry const* factionEntry ); void ReputationChanged(FactionEntry const* factionEntry );
bool HasQuestForItem( uint32 itemid ) const; bool HasQuestForItem( uint32 itemid ) const;
bool HasQuestForGO(int32 GOId) const; bool HasQuestForGO(int32 GOId) const;
void UpdateForQuestsGO(); void UpdateForQuestWorldObjects();
bool CanShareQuest(uint32 quest_id) const; bool CanShareQuest(uint32 quest_id) const;
void SendQuestComplete( uint32 quest_id ); void SendQuestComplete( uint32 quest_id );
@ -1289,6 +1289,7 @@ class MANGOS_DLL_SPEC Player : public Unit
{ {
SetUInt32Value (PLAYER_FIELD_COINAGE, value); SetUInt32Value (PLAYER_FIELD_COINAGE, value);
MoneyChanged( value ); MoneyChanged( value );
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED);
} }
QuestStatusMap& getQuestStatusMap() { return mQuestStatus; }; QuestStatusMap& getQuestStatusMap() { return mQuestStatus; };
@ -2063,6 +2064,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void SetTitle(CharTitlesEntry const* title); void SetTitle(CharTitlesEntry const* title);
bool isActiveObject() const { return true; } bool isActiveObject() const { return true; }
bool canSeeSpellClickOn(Creature const* creature) const;
protected: protected:
/*********************************************************/ /*********************************************************/

View file

@ -372,6 +372,8 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPacket& recv_data)
} }
_player->SetQuestSlot(slot, 0); _player->SetQuestSlot(slot, 0);
_player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED, 1);
} }
} }
@ -616,7 +618,7 @@ void WorldSession::HandleQuestgiverStatusQueryMultipleOpcode(WorldPacket& /*recv
uint8 questStatus = DIALOG_STATUS_NONE; uint8 questStatus = DIALOG_STATUS_NONE;
uint8 defstatus = DIALOG_STATUS_NONE; uint8 defstatus = DIALOG_STATUS_NONE;
if(IS_CREATURE_GUID(*itr)) if (IS_CREATURE_OR_PET_GUID(*itr))
{ {
// need also pet quests case support // need also pet quests case support
Creature *questgiver = ObjectAccessor::GetCreatureOrPetOrVehicle(*GetPlayer(),*itr); Creature *questgiver = ObjectAccessor::GetCreatureOrPetOrVehicle(*GetPlayer(),*itr);

View file

@ -43,6 +43,7 @@
#include "Util.h" #include "Util.h"
#include "GridNotifiers.h" #include "GridNotifiers.h"
#include "GridNotifiersImpl.h" #include "GridNotifiersImpl.h"
#include "Vehicle.h"
#include "CellImpl.h" #include "CellImpl.h"
#define NULL_AURA_SLOT 0xFF #define NULL_AURA_SLOT 0xFF
@ -3532,6 +3533,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real)
void Aura::HandleModStealth(bool apply, bool Real) void Aura::HandleModStealth(bool apply, bool Real)
{ {
Unit* pTarget = m_target; Unit* pTarget = m_target;
SpellEntry const* pSpellInfo = GetSpellProto();
if (apply) if (apply)
{ {
@ -3567,7 +3569,7 @@ void Aura::HandleModStealth(bool apply, bool Real)
pTarget->CastCustomSpell(pTarget,31665,&bp,NULL,NULL,true); pTarget->CastCustomSpell(pTarget,31665,&bp,NULL,NULL,true);
} }
// Overkill // Overkill
else if ((*i)->GetId() == 58426 && GetSpellProto()->SpellFamilyFlags & 0x0000000000400000LL) else if ((*i)->GetId() == 58426 && pSpellInfo->SpellFamilyFlags & 0x0000000000400000LL)
{ {
pTarget->RemoveAurasDueToSpell(58428); pTarget->RemoveAurasDueToSpell(58428);
pTarget->CastSpell(pTarget, 58427, true); pTarget->CastSpell(pTarget, 58427, true);
@ -3607,7 +3609,7 @@ void Aura::HandleModStealth(bool apply, bool Real)
if ((*i)->GetSpellProto()->SpellIconID == 2114) if ((*i)->GetSpellProto()->SpellIconID == 2114)
pTarget->CastSpell(pTarget,31666,true); pTarget->CastSpell(pTarget,31666,true);
// Overkill // Overkill
else if ((*i)->GetId() == 58426 && GetSpellProto()->SpellFamilyFlags & 0x0000000000400000LL) else if ((*i)->GetId() == 58426 && pSpellInfo->SpellFamilyFlags & 0x0000000000400000LL)
pTarget->CastSpell(pTarget, 58428, true); pTarget->CastSpell(pTarget, 58428, true);
} }
} }
@ -3992,21 +3994,26 @@ void Aura::HandleModMechanicImmunity(bool apply, bool /*Real*/)
if(GetId()==42292 || GetId()==59752) if(GetId()==42292 || GetId()==59752)
mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK; mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
if(apply && GetSpellProto()->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY) // cache values in local vars for prevent access to possible deleted aura data
SpellEntry const* spellInfo = GetSpellProto();
uint32 misc = m_modifier.m_miscvalue;
Unit* target = m_target;
if(apply && spellInfo->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)
{ {
Unit::AuraMap& Auras = m_target->GetAuras(); Unit::AuraMap& Auras = target->GetAuras();
for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
{ {
next = iter; next = iter;
++next; ++next;
SpellEntry const *spell = iter->second->GetSpellProto(); SpellEntry const *spell = iter->second->GetSpellProto();
if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) && // spells unaffected by invulnerability if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) && // spells unaffected by invulnerability
spell->Id != GetId()) spell->Id != spellInfo->Id)
{ {
//check for mechanic mask //check for mechanic mask
if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic) if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic)
{ {
m_target->RemoveAurasDueToSpell(spell->Id); target->RemoveAurasDueToSpell(spell->Id);
if(Auras.empty()) if(Auras.empty())
break; break;
else else
@ -4016,19 +4023,19 @@ void Aura::HandleModMechanicImmunity(bool apply, bool /*Real*/)
} }
} }
m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply); target->ApplySpellImmune(spellInfo->Id,IMMUNITY_MECHANIC,misc,apply);
// Bestial Wrath // Bestial Wrath
if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1680) if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->SpellIconID == 1680)
{ {
// The Beast Within cast on owner if talent present // The Beast Within cast on owner if talent present
if ( Unit* owner = m_target->GetOwner() ) if (Unit* owner = target->GetOwner())
{ {
// Search talent // Search talent
Unit::AuraList const& m_dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY); Unit::AuraList const& dummyAuras = owner->GetAurasByType(SPELL_AURA_DUMMY);
for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i) for(Unit::AuraList::const_iterator i = dummyAuras.begin(); i != dummyAuras.end(); ++i)
{ {
if ( (*i)->GetSpellProto()->SpellIconID == 2229 ) if ((*i)->GetSpellProto()->SpellIconID == 2229)
{ {
if (apply) if (apply)
owner->CastSpell(owner, 34471, true, 0, this); owner->CastSpell(owner, 34471, true, 0, this);
@ -4041,21 +4048,21 @@ void Aura::HandleModMechanicImmunity(bool apply, bool /*Real*/)
} }
// The Beast Within and Bestial Wrath - immunity // The Beast Within and Bestial Wrath - immunity
if(GetId() == 19574 || GetId() == 34471) if (spellInfo->Id == 19574 || spellInfo->Id == 34471)
{ {
if(apply) if (apply)
{ {
m_target->CastSpell(m_target,24395,true); target->CastSpell(target,24395,true);
m_target->CastSpell(m_target,24396,true); target->CastSpell(target,24396,true);
m_target->CastSpell(m_target,24397,true); target->CastSpell(target,24397,true);
m_target->CastSpell(m_target,26592,true); target->CastSpell(target,26592,true);
} }
else else
{ {
m_target->RemoveAurasDueToSpell(24395); target->RemoveAurasDueToSpell(24395);
m_target->RemoveAurasDueToSpell(24396); target->RemoveAurasDueToSpell(24396);
m_target->RemoveAurasDueToSpell(24397); target->RemoveAurasDueToSpell(24397);
m_target->RemoveAurasDueToSpell(26592); target->RemoveAurasDueToSpell(26592);
} }
} }
} }
@ -6684,19 +6691,35 @@ void Aura::HandleArenaPreparation(bool apply, bool Real)
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION);
} }
void Aura::HandleAuraControlVehicle(bool /*apply*/, bool Real) /**
* Such auras are applied from a caster(=player) to a vehicle.
* This has been verified using spell #49256
*/
void Aura::HandleAuraControlVehicle(bool apply, bool Real)
{ {
if(!Real) if(!Real)
return; return;
if(m_target->GetTypeId() != TYPEID_PLAYER) Unit *player = GetCaster();
Vehicle *vehicle = dynamic_cast<Vehicle*>(m_target);
if(!player || player->GetTypeId()!=TYPEID_PLAYER || !vehicle)
return; return;
if(Pet *pet = m_target->GetPet()) if (apply)
{
if(Pet *pet = player->GetPet())
pet->Remove(PET_SAVE_AS_CURRENT); pet->Remove(PET_SAVE_AS_CURRENT);
((Player*)player)->EnterVehicle(vehicle);
}
else
{
SpellEntry const *spell = GetSpellProto();
WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); // some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them
((Player*)m_target)->GetSession()->SendPacket(&data); player->RemoveAurasDueToSpell(spell->Id);
((Player*)player)->ExitVehicle(vehicle);
}
} }
void Aura::HandleAuraConvertRune(bool apply, bool Real) void Aura::HandleAuraConvertRune(bool apply, bool Real)

View file

@ -1111,6 +1111,19 @@ void Spell::EffectDummy(uint32 i)
m_caster->CastSpell(m_caster, 30452, true, NULL); m_caster->CastSpell(m_caster, 30452, true, NULL);
return; return;
} }
case 51592: // Pickup Primordial Hatchling
{
if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
return;
Creature* creatureTarget = (Creature*)unitTarget;
creatureTarget->setDeathState(JUST_DIED);
creatureTarget->RemoveCorpse();
creatureTarget->SetHealth(0); // just for nice GM-mode view
return;
}
case 52308: case 52308:
{ {
switch(i) switch(i)

View file

@ -489,3 +489,29 @@ void WorldSession::HandleSelfResOpcode( WorldPacket & /*recv_data*/ )
_player->SetUInt32Value(PLAYER_SELF_RES_SPELL, 0); _player->SetUInt32Value(PLAYER_SELF_RES_SPELL, 0);
} }
} }
void WorldSession::HandleSpellClick( WorldPacket & recv_data )
{
CHECK_PACKET_SIZE(recv_data, 8);
uint64 guid;
recv_data >> guid;
Creature *unit = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid);
if(!unit)
return;
SpellClickInfoMap const& map = objmgr.mSpellClickInfoMap;
for(SpellClickInfoMap::const_iterator itr = map.lower_bound(unit->GetEntry()); itr != map.upper_bound(unit->GetEntry()); ++itr)
{
if(itr->second.questId == 0 || _player->GetQuestStatus(itr->second.questId) == QUEST_STATUS_INCOMPLETE)
{
Unit *caster = (itr->second.castFlags & 0x1) ? (Unit*)_player : (Unit*)unit;
Unit *target = (itr->second.castFlags & 0x2) ? (Unit*)_player : (Unit*)unit;
caster->CastSpell(target, itr->second.spellId, true);
}
}
}

View file

@ -1175,6 +1175,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons
(spellInfo_2->Id == 52950 && spellInfo_1->Id == 52707) ) (spellInfo_2->Id == 52950 && spellInfo_1->Id == 52707) )
return false; return false;
// Regular and Night Elf Ghost
if( (spellInfo_1->Id == 8326 && spellInfo_2->Id == 20584) ||
(spellInfo_2->Id == 8326 && spellInfo_1->Id == 20584) )
return false;
break; break;
} }
case SPELLFAMILY_WARRIOR: case SPELLFAMILY_WARRIOR:

View file

@ -3352,6 +3352,7 @@ bool Unit::AddAura(Aura *Aur)
} }
SpellEntry const* aurSpellInfo = Aur->GetSpellProto(); SpellEntry const* aurSpellInfo = Aur->GetSpellProto();
AuraType aurName = Aur->GetModifier()->m_auraname;
spellEffectPair spair = spellEffectPair(Aur->GetId(), Aur->GetEffIndex()); spellEffectPair spair = spellEffectPair(Aur->GetId(), Aur->GetEffIndex());
AuraMap::iterator i = m_Auras.find( spair ); AuraMap::iterator i = m_Auras.find( spair );
@ -3379,7 +3380,7 @@ bool Unit::AddAura(Aura *Aur)
} }
bool stop = false; bool stop = false;
switch(aurSpellInfo->EffectApplyAuraName[Aur->GetEffIndex()]) switch(aurName)
{ {
// DoT/HoT/etc // DoT/HoT/etc
case SPELL_AURA_PERIODIC_DAMAGE: // allow stack case SPELL_AURA_PERIODIC_DAMAGE: // allow stack
@ -3455,13 +3456,13 @@ bool Unit::AddAura(Aura *Aur)
// add aura, register in lists and arrays // add aura, register in lists and arrays
Aur->_AddAura(); Aur->_AddAura();
m_Auras.insert(AuraMap::value_type(spellEffectPair(Aur->GetId(), Aur->GetEffIndex()), Aur)); m_Auras.insert(AuraMap::value_type(spellEffectPair(Aur->GetId(), Aur->GetEffIndex()), Aur));
if (Aur->GetModifier()->m_auraname < TOTAL_AURAS) if (aurName < TOTAL_AURAS)
{ {
m_modAuras[Aur->GetModifier()->m_auraname].push_back(Aur); m_modAuras[aurName].push_back(Aur);
} }
Aur->ApplyModifier(true,true); Aur->ApplyModifier(true,true);
sLog.outDebug("Aura %u now is in use", Aur->GetModifier()->m_auraname); sLog.outDebug("Aura %u now is in use", aurName);
return true; return true;
} }
@ -5323,6 +5324,16 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu
} }
case SPELLFAMILY_HUNTER: case SPELLFAMILY_HUNTER:
{ {
// Aspect of the Viper
if ( dummySpell->SpellFamilyFlags & 0x4000000000000LL )
{
uint32 maxmana = GetMaxPower(POWER_MANA);
basepoints0 = maxmana* GetAttackTime(RANGED_ATTACK)/1000.0f/100.0f;
target = this;
triggered_spell_id = 34075;
break;
}
// Thrill of the Hunt // Thrill of the Hunt
if ( dummySpell->SpellIconID == 2236 ) if ( dummySpell->SpellIconID == 2236 )
{ {
@ -6227,8 +6238,8 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB
switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell))) switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell)))
{ {
case SPELL_SCHOOL_NORMAL: case SPELL_SCHOOL_NORMAL:
case SPELL_SCHOOL_HOLY:
return false; // ignore return false; // ignore
case SPELL_SCHOOL_HOLY: trigger_spell_id = 54370; break;
case SPELL_SCHOOL_FIRE: trigger_spell_id = 54371; break; case SPELL_SCHOOL_FIRE: trigger_spell_id = 54371; break;
case SPELL_SCHOOL_NATURE: trigger_spell_id = 54375; break; case SPELL_SCHOOL_NATURE: trigger_spell_id = 54375; break;
case SPELL_SCHOOL_FROST: trigger_spell_id = 54372; break; case SPELL_SCHOOL_FROST: trigger_spell_id = 54372; break;
@ -10614,6 +10625,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag
break; break;
} }
case SPELL_AURA_MANA_SHIELD: case SPELL_AURA_MANA_SHIELD:
case SPELL_AURA_OBS_MOD_MANA:
case SPELL_AURA_DUMMY: case SPELL_AURA_DUMMY:
{ {
sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());

View file

@ -1200,6 +1200,9 @@ void World::SetInitialWorldSettings()
sLog.outString( ">>> Quests Relations loaded" ); sLog.outString( ">>> Quests Relations loaded" );
sLog.outString(); sLog.outString();
sLog.outString( "Loading UNIT_NPC_FLAG_SPELLCLICK Data..." );
objmgr.LoadNPCSpellClickSpells();
sLog.outString( "Loading SpellArea Data..." ); // must be after quest load sLog.outString( "Loading SpellArea Data..." ); // must be after quest load
spellmgr.LoadSpellAreas(); spellmgr.LoadSpellAreas();

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "7768" #define REVISION_NR "7785"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__