mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 04:37:00 +00:00
Merge branch 'master' into 310
Conflicts: src/game/Player.cpp src/game/QueryHandler.cpp
This commit is contained in:
commit
6aadc16d7d
54 changed files with 1279 additions and 888 deletions
|
|
@ -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_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;
|
||||
|
||||
|
|
@ -1470,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;
|
||||
|
||||
|
|
@ -13047,10 +13019,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',
|
||||
|
|
@ -13299,7 +13267,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',
|
||||
|
|
|
|||
7
sql/updates/7369_01_mangos_quest_template.sql
Normal file
7
sql/updates/7369_01_mangos_quest_template.sql
Normal file
|
|
@ -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;
|
||||
4
sql/updates/7376_01_mangos_spell_area.sql
Normal file
4
sql/updates/7376_01_mangos_spell_area.sql
Normal file
|
|
@ -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';
|
||||
5
sql/updates/7382_01_mangos_creature_template.sql
Normal file
5
sql/updates/7382_01_mangos_creature_template.sql
Normal file
|
|
@ -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;
|
||||
|
|
@ -188,6 +188,9 @@ pkgdata_DATA = \
|
|||
7331_01_mangos_command.sql \
|
||||
7332_01_mangos_command.sql \
|
||||
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'
|
||||
|
|
@ -356,4 +359,7 @@ EXTRA_DIST = \
|
|||
7331_01_mangos_command.sql \
|
||||
7332_01_mangos_command.sql \
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -406,24 +419,55 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
|||
|
||||
switch (type)
|
||||
{
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
|
||||
SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel());
|
||||
// std. case: increment at 1
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
|
||||
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1);
|
||||
// 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, 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;
|
||||
|
||||
// specialized cases
|
||||
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
if(achievementCriteria->kill_creature.creatureID != miscvalue1)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, miscvalue2, true);
|
||||
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;
|
||||
|
|
@ -445,27 +489,13 @@ 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)
|
||||
continue;
|
||||
if(GetPlayer()->GetMapId() != achievementCriteria->complete_battleground.mapID)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, miscvalue1, true);
|
||||
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);
|
||||
SetCriteriaProgress(achievementCriteria, miscvalue1, PROGRESS_ACCUMULATE);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
|
|
@ -473,21 +503,99 @@ 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_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)
|
||||
continue;
|
||||
if(miscvalue1 != achievementCriteria->killed_by_creature.creatureEntry)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
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;
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
|
||||
// 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:
|
||||
{
|
||||
|
|
@ -506,17 +614,32 @@ 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);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
|
||||
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
|
||||
if(!miscvalue1)
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
|
||||
if (!miscvalue1 || miscvalue1 != achievementCriteria->be_spell_target.spellID)
|
||||
continue;
|
||||
if(achievementCriteria->use_item.itemID != miscvalue1)
|
||||
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_LEARN_SPELL:
|
||||
if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID))
|
||||
SetCriteriaProgress(achievementCriteria, 1);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
|
||||
// speedup for non-login case
|
||||
|
|
@ -524,25 +647,107 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
|||
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, 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)
|
||||
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, true);
|
||||
SetCriteriaProgress(achievementCriteria, 1);
|
||||
break;
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
|
||||
if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID)
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
|
||||
{
|
||||
// miscvalue1 = itemid
|
||||
// miscvalue2 = diced value
|
||||
if(!miscvalue1)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
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 <requiredItemLevel)
|
||||
continue;
|
||||
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);
|
||||
break;
|
||||
}
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
|
||||
{
|
||||
if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID)
|
||||
|
|
@ -564,162 +769,72 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
|
|||
continue;
|
||||
}
|
||||
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
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 <requiredItemLevel)
|
||||
continue;
|
||||
SetCriteriaProgress(achievementCriteria, 1, true);
|
||||
break;
|
||||
}
|
||||
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:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_REACH_TEAM_RATING:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
|
||||
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:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
|
||||
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_HONORED_REPUTATION:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL:
|
||||
break; // Not implemented yet :(
|
||||
// FIXME: not triggered in code as result, need to implement
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_REACH_TEAM_RATING:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL:
|
||||
break; // Not implemented yet :(
|
||||
}
|
||||
if(IsCompletedCriteria(achievementCriteria))
|
||||
CompletedCriteria(achievementCriteria);
|
||||
|
|
@ -754,64 +869,87 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
|
|||
|
||||
switch(achievementCriteria->requiredType)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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_LEVEL:
|
||||
{
|
||||
// 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_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_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:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
|
||||
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -858,9 +996,9 @@ AchievementCompletionState AchievementMgr::GetAchievementCompletionState(Achieve
|
|||
return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED;
|
||||
}
|
||||
|
||||
void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative)
|
||||
void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, ProgressType ptype)
|
||||
{
|
||||
sLog.outDetail("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->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);
|
||||
|
|
@ -868,18 +1006,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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
|
|
@ -630,29 +632,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 << uint64(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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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() );
|
||||
}
|
||||
|
|
@ -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; }
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -409,20 +409,21 @@ void BattleGroundAB::_NodeDeOccupied(uint8 node)
|
|||
if( !ghost_list.empty() )
|
||||
{
|
||||
WorldSafeLocsEntry const *ClosestGrave = NULL;
|
||||
Player *plr;
|
||||
for (std::vector<uint64>::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<uint8> 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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -583,7 +585,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];
|
||||
|
|
@ -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
|
||||
|
|
@ -626,6 +628,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;
|
||||
++itr_team2;
|
||||
//invite players to other selection pool
|
||||
for(; itr_team2 != m_QueuedGroups[queue_id][BG_QUEUE_NORMAL_ALLIANCE + teamIndex].end(); ++itr_team2)
|
||||
{
|
||||
//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;
|
||||
|
||||
//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
|
||||
GroupsQueueType::iterator itr2 = itr_team;
|
||||
++itr2;
|
||||
for(; 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
|
||||
|
|
@ -644,9 +705,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;
|
||||
|
|
@ -672,8 +732,6 @@ void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, BGQueueIdBasedOnLeve
|
|||
|
||||
if( !bg->HasFreeSlots() )
|
||||
{
|
||||
if( next == sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end() )
|
||||
continueAdding = false;
|
||||
// remove BG from BGFreeSlotQueue
|
||||
bg->RemoveFromBGFreeSlotQueue();
|
||||
}
|
||||
|
|
@ -754,7 +812,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;
|
||||
|
|
@ -1473,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);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@
|
|||
|
||||
typedef std::map<uint32, BattleGround*> BattleGroundSet;
|
||||
|
||||
typedef std::deque<BattleGround*> 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<BattleGround*> BGFreeSlotQueueType;
|
||||
|
||||
typedef UNORDERED_MAP<uint32, BattleGroundTypeId> BattleMastersMap;
|
||||
|
||||
|
|
@ -74,6 +75,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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1191,7 +1191,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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -195,6 +195,8 @@ struct CreatureInfo
|
|||
char const* AIName;
|
||||
uint32 MovementType;
|
||||
uint32 InhabitType;
|
||||
float unk16;
|
||||
float unk17;
|
||||
bool RacialLeader;
|
||||
bool RegenHealth;
|
||||
uint32 equipmentId;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ )
|
|||
for (std::vector<Player*>::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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -122,9 +122,9 @@ void WorldSession::HandleSendMail(WorldPacket & recv_data )
|
|||
return;
|
||||
}
|
||||
|
||||
uint32 reqmoney = money + 30;
|
||||
if (items_count)
|
||||
reqmoney = money + (30 * items_count);
|
||||
uint32 cost = items_count ? 30 * items_count : 30; // price hardcoded in client
|
||||
|
||||
uint32 reqmoney = cost + money;
|
||||
|
||||
if (pl->GetMoney() < reqmoney)
|
||||
{
|
||||
|
|
@ -207,6 +207,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -1130,7 +1130,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);
|
||||
*/
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2732,25 +2732,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)
|
||||
|
|
@ -3044,20 +3044,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
|
||||
{
|
||||
|
|
@ -3067,41 +3053,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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
#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)
|
||||
|
|
@ -359,7 +359,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;
|
||||
|
|
@ -416,6 +416,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;
|
||||
|
|
@ -809,7 +811,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;
|
||||
|
|
@ -833,6 +835,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);
|
||||
|
|
@ -843,13 +848,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -867,7 +877,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)
|
||||
|
|
@ -879,7 +889,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))
|
||||
|
|
@ -924,7 +934,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
|
||||
|
|
@ -933,11 +943,9 @@ 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 = 1000;
|
||||
m_breathTimer = 1*IN_MILISECONDS;
|
||||
}
|
||||
}
|
||||
else if (!isAlive()) // Disable breath timer and reset underwater flags
|
||||
|
|
@ -1257,7 +1265,7 @@ void Player::Update( uint32 p_time )
|
|||
{
|
||||
m_drunkTimer += p_time;
|
||||
|
||||
if (m_drunkTimer > 10000)
|
||||
if (m_drunkTimer > 10*IN_MILISECONDS)
|
||||
HandleSobering();
|
||||
}
|
||||
|
||||
|
|
@ -1320,6 +1328,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);
|
||||
|
||||
|
|
@ -1561,6 +1571,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);
|
||||
|
|
@ -2398,6 +2409,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)));
|
||||
|
|
@ -2430,12 +2444,15 @@ void Player::SendInitialSpells()
|
|||
if(!sEntry)
|
||||
continue;
|
||||
|
||||
// not send infinity cooldown
|
||||
if(itr->second.end > infTime)
|
||||
continue;
|
||||
|
||||
data << uint32(itr->first);
|
||||
|
||||
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
|
||||
|
|
@ -3122,8 +3139,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));
|
||||
|
|
@ -3153,7 +3170,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());
|
||||
|
||||
|
|
@ -3194,17 +3211,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3319,6 +3339,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);
|
||||
|
|
@ -3327,6 +3348,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;
|
||||
}
|
||||
|
||||
|
|
@ -3883,7 +3911,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -3904,7 +3932,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
|
||||
|
||||
|
|
@ -4228,10 +4256,8 @@ void Player::RepopAtGraveyard()
|
|||
WorldSafeLocsEntry const *ClosestGrave = NULL;
|
||||
|
||||
// Special handle for battleground maps
|
||||
BattleGround *bg = sBattleGroundMgr.GetBattleGround(GetBattleGroundId(), m_bgTypeID);
|
||||
|
||||
if(bg && (bg->GetTypeID() == BATTLEGROUND_AB || bg->GetTypeID() == BATTLEGROUND_EY))
|
||||
ClosestGrave = bg->GetClosestGraveYard(GetPositionX(), GetPositionY(), GetPositionZ(), GetTeam());
|
||||
if( BattleGround *bg = GetBattleGround() )
|
||||
ClosestGrave = bg->GetClosestGraveYard(this);
|
||||
else
|
||||
ClosestGrave = objmgr.GetClosestGraveYard( GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId(), GetTeam() );
|
||||
|
||||
|
|
@ -5621,7 +5647,8 @@ void Player::SetFactionVisibleForFactionTemplateId(uint32 FactionTemplateId)
|
|||
if(!factionTemplateEntry)
|
||||
return;
|
||||
|
||||
SetFactionVisibleForFactionId(factionTemplateEntry->faction);
|
||||
if(factionTemplateEntry->faction)
|
||||
SetFactionVisibleForFactionId(factionTemplateEntry->faction);
|
||||
}
|
||||
|
||||
void Player::SetFactionVisibleForFactionId(uint32 FactionId)
|
||||
|
|
@ -6389,6 +6416,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 );
|
||||
|
||||
|
|
@ -9811,6 +9841,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 )
|
||||
|
|
@ -12600,10 +12636,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<uint32>(time(NULL)) + limittime;
|
||||
}
|
||||
else
|
||||
|
|
@ -12728,10 +12764,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())
|
||||
|
|
@ -13762,28 +13806,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14323,6 +14360,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());
|
||||
|
|
@ -14332,7 +14377,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();
|
||||
|
|
@ -14345,6 +14390,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
|
||||
|
|
@ -15131,7 +15186,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;
|
||||
|
|
@ -15557,9 +15612,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;
|
||||
}
|
||||
|
|
@ -15818,6 +15875,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
|
||||
|
|
@ -15992,11 +16050,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;
|
||||
|
|
@ -16679,7 +16737,7 @@ void Player::PetSpellInitialize()
|
|||
time_t cooldown = 0;
|
||||
|
||||
if(itr->second > curTime)
|
||||
cooldown = (itr->second - curTime) * 1000;
|
||||
cooldown = (itr->second - curTime) * IN_MILISECONDS;
|
||||
|
||||
data << uint32(itr->first); // spellid
|
||||
data << uint16(0); // spell category?
|
||||
|
|
@ -16692,7 +16750,7 @@ void Player::PetSpellInitialize()
|
|||
time_t cooldown = 0;
|
||||
|
||||
if(itr->second > curTime)
|
||||
cooldown = (itr->second - curTime) * 1000;
|
||||
cooldown = (itr->second - curTime) * IN_MILISECONDS;
|
||||
|
||||
data << uint32(itr->first); // spellid
|
||||
data << uint16(0); // spell category?
|
||||
|
|
@ -17167,6 +17225,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> 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);
|
||||
|
|
@ -17209,7 +17268,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);
|
||||
|
|
@ -17576,6 +17635,102 @@ void Player::UpdatePvP(bool state, bool ovrride)
|
|||
}
|
||||
}
|
||||
|
||||
void Player::AddSpellAndCategoryCooldowns(SpellEntry const* spellInfo, uint32 itemId, Spell* spell, bool infinityCooldown)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
time_t curTime = time(NULL);
|
||||
|
||||
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 (cat && 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;
|
||||
|
|
@ -17584,25 +17739,41 @@ 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 / 1000);
|
||||
// Send activate
|
||||
// Send activate cooldown timer (possible 0) at client side
|
||||
WorldPacket data(SMSG_COOLDOWN_EVENT, (4+8));
|
||||
data << spellInfo->Id;
|
||||
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)
|
||||
{
|
||||
|
|
@ -18479,7 +18650,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);
|
||||
|
|
@ -18626,8 +18797,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;
|
||||
|
|
@ -18639,7 +18810,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -19070,7 +19250,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 );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1509,14 +1509,17 @@ 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, bool infinityCooldown = false );
|
||||
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();
|
||||
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)
|
||||
{
|
||||
|
|
@ -1998,7 +2001,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;};
|
||||
|
|
@ -2029,6 +2032,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); }
|
||||
|
||||
|
|
@ -2297,6 +2302,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;
|
||||
|
||||
|
|
@ -2445,7 +2451,7 @@ template <class T> 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;
|
||||
|
|
|
|||
|
|
@ -192,8 +192,8 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data )
|
|||
data << uint32(ci->DisplayID_A2); // modelid_male2 ?
|
||||
data << uint32(ci->DisplayID_H2); // modelid_femmale2 ?
|
||||
data << uint32(0); // new in 3.1
|
||||
data << float(1.0f); // unk
|
||||
data << float(1.0f); // unk
|
||||
data << float(ci->unk16); // unk
|
||||
data << float(ci->unk17); // unk
|
||||
data << uint8(ci->RacialLeader);
|
||||
for(uint32 i = 0; i < 4; ++i)
|
||||
data << uint32(0); // added in 3.1
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
||||
|
|
@ -2520,93 +2520,21 @@ 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)
|
||||
|
||||
// mana/health potions, disabled by client
|
||||
if (m_spellInfo->Category==SPELLCATEGORY_HEALTH_MANA_POTIONS)
|
||||
{
|
||||
_player->AddSpellCooldown(m_spellInfo->Id, 0, time(NULL) - 1);
|
||||
// need in some way provided data for Spell::finish SendCooldownEvent
|
||||
if(m_CastItem)
|
||||
_player->SetLastPotionId(m_CastItem->GetEntry());
|
||||
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)
|
||||
// have infinity cooldown but set at aura apply
|
||||
if(m_spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE)
|
||||
return;
|
||||
|
||||
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
|
||||
|
||||
// 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)
|
||||
|
|
@ -2797,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();
|
||||
|
|
@ -3818,7 +3750,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;
|
||||
|
|
|
|||
|
|
@ -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<uint64, uint64> SpellTargetTimeMap;
|
||||
|
||||
|
|
|
|||
|
|
@ -581,7 +581,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)
|
||||
|
|
@ -940,6 +940,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())) &&
|
||||
|
|
@ -1122,6 +1132,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());
|
||||
}
|
||||
}
|
||||
|
|
@ -2067,22 +2078,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
|
||||
|
|
@ -2128,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)
|
||||
|
|
@ -2172,21 +2166,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
|
||||
|
|
@ -2411,6 +2390,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)
|
||||
|
|
@ -2833,7 +2835,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())
|
||||
|
|
@ -6683,6 +6685,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);
|
||||
|
|
|
|||
|
|
@ -593,7 +593,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;
|
||||
}
|
||||
|
|
@ -1109,7 +1109,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
|
||||
|
|
@ -3416,7 +3432,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)
|
||||
|
|
@ -3487,7 +3503,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4578,7 +4594,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)...
|
||||
|
|
@ -4621,7 +4637,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);
|
||||
|
|
@ -5246,7 +5262,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);
|
||||
|
|
@ -5323,7 +5339,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);
|
||||
}
|
||||
|
||||
|
|
@ -5507,7 +5523,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -5638,7 +5654,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);
|
||||
|
||||
|
|
@ -6254,7 +6270,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:
|
||||
|
|
@ -6274,7 +6290,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() );
|
||||
|
||||
|
|
@ -6297,7 +6313,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() );
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -683,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)
|
||||
|
|
|
|||
|
|
@ -516,6 +516,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");
|
||||
|
|
@ -592,12 +593,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
|
||||
|
|
@ -3679,7 +3680,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 );
|
||||
|
||||
|
|
@ -3987,7 +3988,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);
|
||||
|
|
@ -4017,7 +4018,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);
|
||||
|
|
@ -4035,7 +4036,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);
|
||||
|
|
@ -4054,6 +4055,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)
|
||||
|
|
@ -4066,6 +4076,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);
|
||||
|
|
@ -6905,28 +6916,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)
|
||||
|
|
@ -7014,28 +7031,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)
|
||||
|
|
@ -7045,7 +7068,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);
|
||||
|
|
@ -7058,7 +7081,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);
|
||||
|
|
@ -8575,6 +8598,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
|
||||
|
|
@ -11331,4 +11356,4 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
|
|||
if(IsInWorld())
|
||||
if(Pet* pet = GetPet())
|
||||
pet->SetPhaseMask(newPhaseMask,true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
|
|
@ -1365,18 +1367,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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."
|
||||
|
|
@ -835,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)
|
||||
#
|
||||
|
|
@ -860,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)
|
||||
#
|
||||
###################################################################################################################
|
||||
|
||||
|
|
@ -1046,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)
|
||||
#
|
||||
|
|
@ -1110,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
|
||||
|
|
@ -1154,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
|
||||
|
|
@ -1162,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
|
||||
|
|
@ -1176,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
|
||||
|
|
@ -1190,7 +1196,7 @@ BattleGround.PremadeGroupWaitForMatch = 1800000
|
|||
#
|
||||
###################################################################################################################
|
||||
|
||||
Arena.MaxRatingDifference = 100
|
||||
Arena.MaxRatingDifference = 150
|
||||
Arena.RatingDiscardTimer = 600000
|
||||
Arena.AutoDistributePoints = 0
|
||||
Arena.AutoDistributeInterval = 7
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ enum TimeConstants
|
|||
HOUR = MINUTE*60,
|
||||
DAY = HOUR*24,
|
||||
MONTH = DAY*30,
|
||||
YEAR = MONTH*12,
|
||||
IN_MILISECONDS = 1000
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,28 +369,35 @@ 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
|
||||
struct
|
||||
{
|
||||
uint32 unused; // 3
|
||||
uint32 goldInCopper; // 4
|
||||
} 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
|
||||
{
|
||||
|
|
@ -392,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
|
||||
|
|
@ -731,22 +744,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; }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "7361"
|
||||
#define REVISION_NR "7387"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue