diff --git a/NEWS b/NEWS index 32e10c556..ddba38e79 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ http://mangos.lighthouseapp.com/ Version 0.13 * Under discussion. + * OpenSSL lib upgrade to OpenSSL 0.9.8k + * ZThread replaced by similar ACE framework functionality. ZThread use dropped. * Upgrade to client version 3.0.9 (build 9551). Version 0.12 diff --git a/sql/mangos.sql b/sql/mangos.sql index 5381bda91..6451c9815 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -23,7 +23,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, - `required_7796_02_mangos_mangos_string` bit(1) default NULL + `required_7830_01_mangos_spell_chain` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -1712,7 +1712,7 @@ CREATE TABLE `item_template` ( `stat_type10` tinyint(3) unsigned NOT NULL default '0', `stat_value10` smallint(6) NOT NULL default '0', `ScalingStatDistribution` smallint(6) NOT NULL default '0', - `ScalingStatValue` smallint(6) NOT NULL default '0', + `ScalingStatValue` int(6) unsigned NOT NULL default '0', `dmg_min1` float NOT NULL default '0', `dmg_max1` float NOT NULL default '0', `dmg_type1` tinyint(3) unsigned NOT NULL default '0', @@ -3159,6 +3159,27 @@ LOCK TABLES `npc_option` WRITE; /*!40000 ALTER TABLE `npc_option` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `npc_spellclick_spells` +-- + +DROP TABLE IF EXISTS `npc_spellclick_spells`; +CREATE TABLE `npc_spellclick_spells` ( + `npc_entry` INT UNSIGNED NOT NULL COMMENT 'reference to creature_template', + `spell_id` INT UNSIGNED NOT NULL COMMENT 'spell which should be casted ', + `quest_id` INT UNSIGNED NOT NULL COMMENT 'reference to quest_template', + `cast_flags` TINYINT UNSIGNED NOT NULL COMMENT 'first bit defines caster: 1=player, 0=creature; second bit defines target, same mapping as caster bit' +) ENGINE = MYISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `npc_spellclick_spells` +-- + +LOCK TABLES `npc_spellclick_spells` WRITE; +/*!40000 ALTER TABLE `npc_spellclick_spells` DISABLE KEYS */; +/*!40000 ALTER TABLE `npc_spellclick_spells` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `npc_text` -- @@ -14476,7 +14497,7 @@ INSERT INTO spell_chain VALUES /*------------------ --(189)Pet-Felhunter ------------------*/ -/*DevourMagic*/ +/*Devour Magic*/ (19505,0,19505,1,0), (19731,19505,19505,2,0), (19734,19731,19505,3,0), @@ -14484,13 +14505,19 @@ INSERT INTO spell_chain VALUES (27276,19736,19505,5,0), (27277,27276,19505,6,0), (48011,27277,19505,7,0), -/*ShadowBite*/ +/*Fel Intelligence*/ +(54424,0,54424,1,0), +(57564,54424,54424,2,0), +(57565,57564,54424,3,0), +(57566,57565,54424,4,0), +(57567,57566,54424,5,0), +/*Shadow Bite*/ (54049,0,54049,1,0), (54050,54049,54049,2,0), (54051,54050,54049,3,0), (54052,54051,54049,4,0), (54053,54052,54049,5,0), -/*SpellLock*/ +/*Spell Lock*/ (19244,0,19244,1,0), (19647,19244,19244,2,0), /*------------------ @@ -17013,9 +17040,9 @@ INSERT INTO `spell_proc_event` VALUES (30293, 0x00000000, 5, 0x00000381, 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (30295, 0x00000000, 5, 0x00000381, 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (30296, 0x00000000, 5, 0x00000381, 0x000000C0, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(30299, 0x00000024, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(30301, 0x00000024, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(30302, 0x00000024, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(30299, 0x0000007E, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(30301, 0x0000007E, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), +(30302, 0x0000007E, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (30675, 0x00000000, 11, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (30678, 0x00000000, 11, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (30679, 0x00000000, 11, 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), @@ -17101,6 +17128,7 @@ INSERT INTO `spell_proc_event` VALUES (33882, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (33883, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (33953, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00004000, 0x00000000, 0.000000, 0.000000, 45), +(34074, 0x00000000, 9, 0x0007FA43, 0x00881081, 0x00000201, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (34080, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0.000000, 0.000000, 0), (34138, 0x00000000, 11, 0x00000080, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (34139, 0x00000000, 10, 0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), diff --git a/sql/updates/7823_01_mangos_item_template.sql b/sql/updates/7823_01_mangos_item_template.sql new file mode 100644 index 000000000..2b3a0b314 --- /dev/null +++ b/sql/updates/7823_01_mangos_item_template.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_7796_02_mangos_mangos_string required_7823_01_mangos_item_template bit; + +ALTER TABLE item_template +CHANGE COLUMN ScalingStatValue ScalingStatValue int(6) unsigned NOT NULL default '0'; \ No newline at end of file diff --git a/sql/updates/7830_01_mangos_spell_chain.sql b/sql/updates/7830_01_mangos_spell_chain.sql new file mode 100644 index 000000000..32815cbb5 --- /dev/null +++ b/sql/updates/7830_01_mangos_spell_chain.sql @@ -0,0 +1,10 @@ +ALTER TABLE db_version CHANGE COLUMN required_7823_01_mangos_item_template required_7830_01_mangos_spell_chain bit; + +DELETE FROM spell_chain WHERE spell_id in (54424,57564,57565,57566,57567); + +INSERT INTO `spell_chain` VALUES + (54424,0, 54424,1,0), + (57564,54424,54424,2,0), + (57565,57564,54424,3,0), + (57566,57565,54424,4,0), + (57567,57566,54424,5,0); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 499016c4b..d20edfdf0 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -184,6 +184,8 @@ pkgdata_DATA = \ 7796_02_mangos_mangos_string.sql \ 7802_01_characters_character_achievement.sql \ 7802_02_characters_character_achievement_progress.sql \ + 7823_01_mangos_item_template.sql \ + 7830_01_mangos_spell_chain.sql \ README ## Additional files to include when running 'make dist' @@ -348,4 +350,6 @@ EXTRA_DIST = \ 7796_02_mangos_mangos_string.sql \ 7802_01_characters_character_achievement.sql \ 7802_02_characters_character_achievement_progress.sql \ + 7823_01_mangos_item_template.sql \ + 7830_01_mangos_spell_chain.sql \ README diff --git a/src/bindings/universal/ScriptMgr.h b/src/bindings/universal/ScriptMgr.h index 5cfb164db..daf4b02a2 100644 --- a/src/bindings/universal/ScriptMgr.h +++ b/src/bindings/universal/ScriptMgr.h @@ -89,7 +89,7 @@ struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI // Is unit visible for MoveInLineOfSight bool IsVisible(Unit* who) const { - return !who->HasStealthAura() && m_creature->GetDistance(who) <= VISIBLE_RANGE; + return !who->HasStealthAura() && m_creature->IsWithinDist(who,VISIBLE_RANGE); } // Called at World update tick diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp index 50878ee59..c1a544d5d 100644 --- a/src/game/AggressorAI.cpp +++ b/src/game/AggressorAI.cpp @@ -140,7 +140,7 @@ AggressorAI::UpdateAI(const uint32 /*diff*/) bool AggressorAI::IsVisible(Unit *pl) const { - return m_creature->GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER) + return m_creature->IsWithinDist(pl,sWorld.getConfig(CONFIG_SIGHT_MONSTER)) && pl->isVisibleForOrDetect(m_creature,true); } diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 4fc950833..491c7a7ca 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -169,7 +169,7 @@ void WorldSession::HandleCharEnumOpcode( WorldPacket & /*recv_data*/ ) // 0 1 2 3 4 5 6 7 8 "SELECT characters.guid, characters.data, characters.name, characters.position_x, characters.position_y, characters.position_z, characters.map, characters.totaltime, characters.leveltime, " // 9 10 11 12 13 14 - "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid, genitive " + "characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, guild_member.guildid, character_declinedname.genitive " "FROM characters LEFT JOIN character_pet ON characters.guid = character_pet.owner AND character_pet.slot='%u' " "LEFT JOIN character_declinedname ON characters.guid = character_declinedname.guid " "LEFT JOIN guild_member ON characters.guid = guild_member.guid " diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 6cdbae73a..fbdbd9eb4 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1778,12 +1778,12 @@ bool Creature::IsOutOfThreatArea(Unit* pVictim) const if(sMapStore.LookupEntry(GetMapId())->IsDungeon()) return false; - float length = pVictim->GetDistance(CombatStartX,CombatStartY,CombatStartZ); float AttackDist = GetAttackDistance(pVictim); uint32 ThreatRadius = sWorld.getConfig(CONFIG_THREAT_RADIUS); //Use AttackDistance in distance check if threat radius is lower. This prevents creature bounce in and out of combat every update tick. - return ( length > (ThreatRadius > AttackDist ? ThreatRadius : AttackDist)); + return !pVictim->IsWithinDist3d(CombatStartX,CombatStartY,CombatStartZ, + ThreatRadius > AttackDist ? ThreatRadius : AttackDist); } CreatureDataAddon const* Creature::GetCreatureAddon() const diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index 49d5634d4..10addd297 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -1277,13 +1277,10 @@ void CreatureEventAI::UpdateAI(const uint32 diff) break; case EVENT_T_RANGE: if (Combat) - { - if (m_creature->IsWithinDistInMap(m_creature->getVictim(),(float)(*i).Event.event_param2)) - { - if (m_creature->GetDistance(m_creature->getVictim()) >= (float)(*i).Event.event_param1) + if (m_creature->IsInMap(m_creature->getVictim())) + if (m_creature->IsInRange(m_creature->getVictim(), + (float)(*i).Event.event_param1,(float)(*i).Event.event_param2)) ProcessEvent(*i); - } - } break; } } @@ -1305,7 +1302,7 @@ void CreatureEventAI::UpdateAI(const uint32 diff) bool CreatureEventAI::IsVisible(Unit *pl) const { - return m_creature->GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER) + return m_creature->IsWithinDist(pl,sWorld.getConfig(CONFIG_SIGHT_MONSTER)) && pl->isVisibleForOrDetect(m_creature,true); } @@ -1584,7 +1581,7 @@ bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Trigge return false; //Unit is out of range of this spell - if (m_creature->GetDistance(Target) > TempRange->maxRange || m_creature->GetDistance(Target) < TempRange->minRange) + if (!m_creature->IsInRange(Target,TempRange->minRange,TempRange->minRange)) return false; return true; diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h index 56bccc947..771d582ef 100644 --- a/src/game/CreatureEventAI.h +++ b/src/game/CreatureEventAI.h @@ -30,7 +30,6 @@ class WorldObject; #define EVENT_UPDATE_TIME 500 #define SPELL_RUN_AWAY 8225 #define MAX_ACTIONS 3 -#define TEXT_SOURCE_RANGE -1000000 //the amount of entries each text source has available enum EventAI_Type { diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp index 5961e0995..bd3631a75 100644 --- a/src/game/CreatureEventAIMgr.cpp +++ b/src/game/CreatureEventAIMgr.cpp @@ -36,7 +36,7 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Texts() m_CreatureEventAI_TextMap.clear(); // Load EventAI Text - LoadMangosStrings(WorldDatabase,"creature_ai_texts",-1,1+(TEXT_SOURCE_RANGE)); + objmgr.LoadMangosStrings(WorldDatabase,"creature_ai_texts",MIN_CREATURE_AI_TEXT_STRING_ID,MAX_CREATURE_AI_TEXT_STRING_ID); // Gather Additional data from EventAI Texts QueryResult *result = WorldDatabase.PQuery("SELECT entry, sound, type, language, emote FROM creature_ai_texts"); @@ -59,15 +59,17 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Texts() temp.Language = fields[3].GetInt32(); temp.Emote = fields[4].GetInt32(); - if (i >= 0) + // range negative + if (i > MIN_CREATURE_AI_TEXT_STRING_ID || i <= MAX_CREATURE_AI_TEXT_STRING_ID) { - sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` is not a negative value.",i); + sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` is not in valid range(%d-%d)",i,MIN_CREATURE_AI_TEXT_STRING_ID,MAX_CREATURE_AI_TEXT_STRING_ID); continue; } - if (i <= TEXT_SOURCE_RANGE) + // range negative (don't must be happen, loaded from same table) + if (!objmgr.GetMangosStringLocale(i)) { - sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` is out of accepted entry range for table.",i); + sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` not found",i); continue; } diff --git a/src/game/DBCEnums.h b/src/game/DBCEnums.h index 68f4bb1be..20b28c1d4 100644 --- a/src/game/DBCEnums.h +++ b/src/game/DBCEnums.h @@ -48,7 +48,7 @@ enum AchievementFlags ACHIEVEMENT_FLAG_SUMM = 0x00000008, // Use summ criteria value from all reqirements (and calculate max value) ACHIEVEMENT_FLAG_MAX_USED = 0x00000010, // Show max criteria (and calculate max value ??) ACHIEVEMENT_FLAG_REQ_COUNT = 0x00000020, // Use not zero req count (and calculate max value) - ACHIEVEMENT_FLAG_AVERANGE = 0x00000040, // Show as averange value (value / time_in_days) depend from other flag (by def use last criteria value) + ACHIEVEMENT_FLAG_AVERAGE = 0x00000040, // Show as average value (value / time_in_days) depend from other flag (by def use last criteria value) ACHIEVEMENT_FLAG_BAR = 0x00000080, // Show as progress bar (value / max vale) depend from other flag (by def use last criteria value) ACHIEVEMENT_FLAG_REALM_FIRST_REACH = 0x00000100, // ACHIEVEMENT_FLAG_REALM_FIRST_KILL = 0x00000200, // diff --git a/src/game/DBCStructure.h b/src/game/DBCStructure.h index 9f02e8d55..8974572e4 100644 --- a/src/game/DBCStructure.h +++ b/src/game/DBCStructure.h @@ -1139,7 +1139,7 @@ struct RandomPropertiesPointsEntry struct ScalingStatDistributionEntry { uint32 Id; - uint32 StatMod[10]; + int32 StatMod[10]; uint32 Modifier[10]; uint32 MaxLevel; }; @@ -1148,7 +1148,58 @@ struct ScalingStatValuesEntry { uint32 Id; uint32 Level; - uint32 Multiplier[17]; + uint32 ssdMultiplier[5]; // Multiplier for ScalingStatDistribution + uint32 armorMod[4]; // Armor for level + uint32 dpsMod[6]; // DPS mod for level + uint32 spellBonus; // not sure.. TODO: need more info about + uint32 feralBonus; // Feral AP bonus + + uint32 getssdMultiplier(uint32 mask) const + { + if (mask&0x001F) + { + if(mask & 0x00000001) return ssdMultiplier[0]; + if(mask & 0x00000002) return ssdMultiplier[1]; + if(mask & 0x00000004) return ssdMultiplier[2]; + if(mask & 0x00000008) return ssdMultiplier[3]; + if(mask & 0x00000010) return ssdMultiplier[4]; + } + return 0; + } + uint32 getArmorMod(uint32 mask) const + { + if (mask&0x01E0) + { + if(mask & 0x00000020) return armorMod[0]; + if(mask & 0x00000040) return armorMod[1]; + if(mask & 0x00000080) return armorMod[2]; + if(mask & 0x00000100) return armorMod[3]; + } + return 0; + } + uint32 getDPSMod(uint32 mask) const + { + if (mask&0x7E00) + { + if(mask & 0x00000200) return dpsMod[0]; + if(mask & 0x00000400) return dpsMod[1]; + if(mask & 0x00000800) return dpsMod[2]; + if(mask & 0x00001000) return dpsMod[3]; + if(mask & 0x00002000) return dpsMod[4]; + if(mask & 0x00004000) return dpsMod[5]; + } + return 0; + } + uint32 getSpellBonus(uint32 mask) const + { + if (mask & 0x00008000) return spellBonus; + return 0; + } + uint32 getFeralBonus(uint32 mask) const + { + if (mask & 0x00010000) return feralBonus; + return 0; + } }; //struct SkillLineCategoryEntry{ diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp index b1acc2b61..1aefbcb4a 100644 --- a/src/game/GridNotifiers.cpp +++ b/src/game/GridNotifiers.cpp @@ -176,14 +176,14 @@ MessageDistDeliverer::Visit(PlayerMapType &m) { for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) { - if( (i_toSelf || iter->getSource() != &i_player ) && + if ((i_toSelf || iter->getSource() != &i_player ) && (!i_ownTeamOnly || iter->getSource()->GetTeam() == i_player.GetTeam() ) && - (!i_dist || iter->getSource()->GetDistance(&i_player) <= i_dist) ) + (!i_dist || iter->getSource()->IsWithinDist(&i_player,i_dist))) { if (!i_player.InSamePhase(iter->getSource())) continue; - if(WorldSession* session = iter->getSource()->GetSession()) + if (WorldSession* session = iter->getSource()->GetSession()) session->SendPacket(i_message); } } @@ -194,12 +194,12 @@ ObjectMessageDistDeliverer::Visit(PlayerMapType &m) { for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) { - if( !i_dist || iter->getSource()->GetDistance(&i_object) <= i_dist ) + if (!i_dist || iter->getSource()->IsWithinDist(&i_object,i_dist)) { - if( !i_object.InSamePhase(iter->getSource())) + if (!i_object.InSamePhase(iter->getSource())) continue; - if(WorldSession* session = iter->getSource()->GetSession()) + if (WorldSession* session = iter->getSource()->GetSession()) session->SendPacket(i_message); } } diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h index daf393eff..d8798d58b 100644 --- a/src/game/GridNotifiers.h +++ b/src/game/GridNotifiers.h @@ -494,7 +494,7 @@ namespace MaNGOS void Visit(PlayerMapType &m) { for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if(itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->GetDistance(i_searcher) <= i_dist) + if (itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->IsWithinDist(i_searcher,i_dist)) i_do(itr->getSource()); } diff --git a/src/game/Group.cpp b/src/game/Group.cpp index b2b495cb8..484e5fde7 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -567,7 +567,7 @@ void Group::GroupLoot(const uint64& playerGUID, Loot *loot, Creature *creature) continue; if ( i->AllowedForPlayer(member) ) { - if (member->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + if (member->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) { r->playerVote[member->GetGUID()] = NOT_EMITED_YET; ++r->totalPlayersRolling; @@ -617,7 +617,7 @@ void Group::NeedBeforeGreed(const uint64& playerGUID, Loot *loot, Creature *crea if (playerToRoll->CanUseItem(item) && i->AllowedForPlayer(playerToRoll) ) { - if (playerToRoll->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + if (playerToRoll->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) { r->playerVote[playerToRoll->GetGUID()] = NOT_EMITED_YET; ++r->totalPlayersRolling; @@ -665,7 +665,7 @@ void Group::MasterLoot(const uint64& playerGUID, Loot* /*loot*/, Creature *creat if (!looter->IsInWorld()) continue; - if (looter->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + if (looter->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) { data << looter->GetGUID(); ++real_count; @@ -677,7 +677,7 @@ void Group::MasterLoot(const uint64& playerGUID, Loot* /*loot*/, Creature *creat for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) { Player *looter = itr->getSource(); - if (looter->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + if (looter->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) looter->GetSession()->SendPacket(&data); } } @@ -1334,7 +1334,7 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed ) { // not update if only update if need and ok Player* looter = ObjectAccessor::FindPlayer(guid_itr->guid); - if(looter && looter->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + if(looter && looter->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) return; } ++guid_itr; @@ -1347,7 +1347,7 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed ) { if(Player* pl = ObjectAccessor::FindPlayer(itr->guid)) { - if (pl->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + if (pl->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) { bool refresh = pl->GetLootGUID()==creature->GetGUID(); @@ -1368,7 +1368,7 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed ) { if(Player* pl = ObjectAccessor::FindPlayer(itr->guid)) { - if (pl->GetDistance2d(creature) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + if (pl->IsWithinDist(creature,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) { bool refresh = pl->GetLootGUID()==creature->GetGUID(); diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp index 8e0e5ba18..5dcbb5a23 100644 --- a/src/game/GuardAI.cpp +++ b/src/game/GuardAI.cpp @@ -125,7 +125,7 @@ void GuardAI::UpdateAI(const uint32 /*diff*/) bool GuardAI::IsVisible(Unit *pl) const { - return m_creature->GetDistance(pl) < sWorld.getConfig(CONFIG_SIGHT_GUARDER) + return m_creature->IsWithinDist(pl,sWorld.getConfig(CONFIG_SIGHT_GUARDER)) && pl->isVisibleForOrDetect(m_creature,true); } diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index 9408122d2..e3bb86c0a 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -594,46 +594,6 @@ struct ItemPrototype return false; } - uint32 GetScalingStatValuesColumn() const - { - if(ScalingStatValue & 0x00000001) // stat mod - return 0; - if(ScalingStatValue & 0x00000002) // stat mod - return 1; - if(ScalingStatValue & 0x00000004) // stat mod - return 2; - if(ScalingStatValue & 0x00000008) // stat mod - return 3; - if(ScalingStatValue & 0x00000010) // stat mod - return 4; - if(ScalingStatValue & 0x00000020) // armor mod - return 5; - if(ScalingStatValue & 0x00000040) // armor mod - return 6; - if(ScalingStatValue & 0x00000080) // armor mod - return 7; - if(ScalingStatValue & 0x00000100) // armor mod - return 8; - if(ScalingStatValue & 0x00000200) // damage mod - return 9; - if(ScalingStatValue & 0x00000400) // damage mod - return 10; - if(ScalingStatValue & 0x00000800) // damage mod - return 11; - if(ScalingStatValue & 0x00001000) // damage mod - return 12; - if(ScalingStatValue & 0x00002000) // damage mod - return 13; - if(ScalingStatValue & 0x00004000) // damage mod - return 14; - if(ScalingStatValue & 0x00008000) // spell power - return 15; - if(ScalingStatValue & 0x00020000) // feral AP - return 16; - - return 0; - } - uint32 GetMaxStackSize() const { return Stackable > 0 ? uint32(Stackable) : uint32(0x7FFFFFFF-1); } float getDPS() const @@ -646,12 +606,12 @@ struct ItemPrototype return temp*500/Delay; } - int32 getFeralBonus() const + int32 getFeralBonus(int32 extraDPS = 0) const { // 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc if (Class == ITEM_CLASS_WEAPON && (1<isPet()) { + if(((Pet*)pCreature)->getPetType()==HUNTER_PET) + { + pCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(lvl)/4); + pCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); + } ((Pet*)pCreature)->GivePetLevel(lvl); } else diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp index 0dc2b5598..cfba29ad3 100644 --- a/src/game/LootHandler.cpp +++ b/src/game/LootHandler.cpp @@ -212,7 +212,7 @@ void WorldSession::HandleLootMoneyOpcode( WorldPacket & /*recv_data*/ ) Player* playerGroup = itr->getSource(); if(!playerGroup) continue; - if (player->GetDistance2d(playerGroup) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) + if (player->IsWithinDist(playerGroup,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) playersNear.push_back(playerGroup); } diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 535355d4a..1993c90f0 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -675,9 +675,7 @@ void WorldSession::HandleReclaimCorpseOpcode(WorldPacket &recv_data) if(corpse->GetGhostTime() + GetPlayer()->GetCorpseReclaimDelay(corpse->GetType()==CORPSE_RESURRECTABLE_PVP) > time(NULL)) return; - float dist = corpse->GetDistance2d(GetPlayer()); - sLog.outDebug("Corpse 2D Distance: \t%f",dist); - if (dist > CORPSE_RECLAIM_RADIUS) + if (!corpse->IsWithinDist(GetPlayer(),CORPSE_RECLAIM_RADIUS,false)) return; uint64 guid; diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 4bebaa849..004c3a501 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1107,7 +1107,7 @@ float WorldObject::GetDistance2d(float x, float y) const return ( dist > 0 ? dist : 0); } -float WorldObject::GetDistance(const float x, const float y, const float z) const +float WorldObject::GetDistance(float x, float y, float z) const { float dx = GetPositionX() - x; float dy = GetPositionY() - y; @@ -1134,10 +1134,33 @@ float WorldObject::GetDistanceZ(const WorldObject* obj) const return ( dist > 0 ? dist : 0); } -bool WorldObject::IsWithinDistInMap(const WorldObject* obj, const float dist2compare, const bool is3D) const +bool WorldObject::IsWithinDist3d(float x, float y, float z, float dist2compare) const { - if (!obj || !IsInMap(obj)) return false; + float dx = GetPositionX() - x; + float dy = GetPositionY() - y; + float dz = GetPositionZ() - z; + float distsq = dx*dx + dy*dy + dz*dz; + float sizefactor = GetObjectSize(); + float maxdist = dist2compare + sizefactor; + + return distsq < maxdist * maxdist; +} + +bool WorldObject::IsWithinDist2d(float x, float y, float dist2compare) const +{ + float dx = GetPositionX() - x; + float dy = GetPositionY() - y; + float distsq = dx*dx + dy*dy; + + float sizefactor = GetObjectSize(); + float maxdist = dist2compare + sizefactor; + + return distsq < maxdist * maxdist; +} + +bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const +{ float dx = GetPositionX() - obj->GetPositionX(); float dy = GetPositionY() - obj->GetPositionY(); float distsq = dx*dx + dy*dy; @@ -1160,7 +1183,7 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const return(IsWithinLOS(ox, oy, oz )); } -bool WorldObject::IsWithinLOS(const float ox, const float oy, const float oz ) const +bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const { float x,y,z; GetPosition(x,y,z); @@ -1168,6 +1191,83 @@ bool WorldObject::IsWithinLOS(const float ox, const float oy, const float oz ) c return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f); } +bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D /* = true */) const +{ + float dx1 = GetPositionX() - obj1->GetPositionX(); + float dy1 = GetPositionY() - obj1->GetPositionY(); + float distsq1 = dx1*dx1 + dy1*dy1; + if(is3D) + { + float dz1 = GetPositionZ() - obj1->GetPositionZ(); + distsq1 += dz1*dz1; + } + + float dx2 = GetPositionX() - obj2->GetPositionX(); + float dy2 = GetPositionY() - obj2->GetPositionY(); + float distsq2 = dx2*dx2 + dy2*dy2; + if(is3D) + { + float dz2 = GetPositionZ() - obj2->GetPositionZ(); + distsq2 += dz2*dz2; + } + + return distsq1 < distsq2; +} + +bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D /* = true */) const +{ + float dx = GetPositionX() - obj->GetPositionX(); + float dy = GetPositionY() - obj->GetPositionY(); + float distsq = dx*dx + dy*dy; + if(is3D) + { + float dz = GetPositionZ() - obj->GetPositionZ(); + distsq += dz*dz; + } + + float sizefactor = GetObjectSize() + obj->GetObjectSize(); + + float mindist = minRange + sizefactor; + if(distsq < mindist * mindist) + return false; + + float maxdist = maxRange + sizefactor; + return distsq < maxdist * maxdist; +} + +bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange) const +{ + float dx = GetPositionX() - x; + float dy = GetPositionY() - y; + float distsq = dx*dx + dy*dy; + + float sizefactor = GetObjectSize(); + + float mindist = minRange + sizefactor; + if(distsq < mindist * mindist) + return false; + + float maxdist = maxRange + sizefactor; + return distsq < maxdist * maxdist; +} + +bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float maxRange) const +{ + float dx = GetPositionX() - x; + float dy = GetPositionY() - y; + float dz = GetPositionZ() - z; + float distsq = dx*dx + dy*dy + dz*dz; + + float sizefactor = GetObjectSize(); + + float mindist = minRange + sizefactor; + if(distsq < mindist * mindist) + return false; + + float maxdist = maxRange + sizefactor; + return distsq < maxdist * maxdist; +} + float WorldObject::GetAngle(const WorldObject* obj) const { if(!obj) return 0; @@ -1563,15 +1663,8 @@ namespace MaNGOS // we must add used pos that can fill places around center void add(WorldObject* u, float x, float y) const { - // dist include size of u - float dist2d = i_object.GetDistance2d(x,y); - - // u is too nearest to i_object - if(dist2d + i_object.GetObjectSize() + u->GetObjectSize() < i_selector.m_dist - i_selector.m_size) - return; - - // u is too far away from i_object - if(dist2d + i_object.GetObjectSize() - u->GetObjectSize() > i_selector.m_dist + i_selector.m_size) + // u is too nearest/far away to i_object + if(!i_object.IsInRange2d(x,y,i_selector.m_dist - i_selector.m_size,i_selector.m_dist + i_selector.m_size)) return; float angle = i_object.GetAngle(u)-i_angle; @@ -1582,6 +1675,8 @@ namespace MaNGOS while(angle < -M_PI) angle += 2.0f * M_PI; + // dist include size of u + float dist2d = i_object.GetDistance2d(x,y); i_selector.AddUsedPos(u->GetObjectSize(),angle,dist2d + i_object.GetObjectSize()); } private: diff --git a/src/game/Object.h b/src/game/Object.h index 7aff8360a..31b90f352 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -421,18 +421,33 @@ class MANGOS_DLL_SPEC WorldObject : public Object virtual const char* GetNameForLocaleIdx(int32 /*locale_idx*/) const { return GetName(); } float GetDistance( const WorldObject* obj ) const; - float GetDistance(const float x, const float y, const float z) const; + float GetDistance(float x, float y, float z) const; float GetDistance2d(const WorldObject* obj) const; - float GetDistance2d(const float x, const float y) const; + float GetDistance2d(float x, float y) const; float GetDistanceZ(const WorldObject* obj) const; bool IsInMap(const WorldObject* obj) const { return IsInWorld() && obj->IsInWorld() && GetMapId()==obj->GetMapId() && GetInstanceId()==obj->GetInstanceId() && InSamePhase(obj); } - bool IsWithinDistInMap(const WorldObject* obj, const float dist2compare, const bool is3D = true) const; - bool IsWithinLOS(const float x, const float y, const float z ) const; + bool IsWithinDist3d(float x, float y, float z, float dist2compare) const; + bool IsWithinDist2d(float x, float y, float dist2compare) const; + bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const; + bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true) const + // use only if you will sure about placing both object at same map + { + return obj && _IsWithinDist(obj,dist2compare,is3D); + } + bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true) const + { + return obj && IsInMap(obj) && _IsWithinDist(obj,dist2compare,is3D); + } + bool IsWithinLOS(float x, float y, float z) const; bool IsWithinLOSInMap(const WorldObject* obj) const; + bool GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D = true) const; + bool IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D = true) const; + bool IsInRange2d(float x, float y, float minRange, float maxRange) const; + bool IsInRange3d(float x, float y, float z, float minRange, float maxRange) const; float GetAngle( const WorldObject* obj ) const; float GetAngle( const float x, const float y ) const; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index ab7017411..a7cb84961 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3590,20 +3590,53 @@ void ObjectMgr::LoadPetCreateSpells() uint32 creature_id = fields[0].GetUInt32(); - if(!creature_id || !sCreatureStorage.LookupEntry(creature_id)) + if(!creature_id) + { + sLog.outErrorDb("Creature id %u listed in `petcreateinfo_spell` not exist.",creature_id); continue; + } + + CreatureInfo const* cInfo = sCreatureStorage.LookupEntry(creature_id); + if(!cInfo) + { + sLog.outErrorDb("Creature id %u listed in `petcreateinfo_spell` not exist.",creature_id); + continue; + } PetCreateSpellEntry PetCreateSpell; + + bool have_spell = false; + bool have_spell_db = false; for(int i = 0; i < 4; i++) { PetCreateSpell.spellid[i] = fields[i + 1].GetUInt32(); - if(PetCreateSpell.spellid[i] && !sSpellStore.LookupEntry(PetCreateSpell.spellid[i])) + if(!PetCreateSpell.spellid[i]) + continue; + + have_spell_db = true; + + SpellEntry const* i_spell = sSpellStore.LookupEntry(PetCreateSpell.spellid[i]); + if(!i_spell) + { sLog.outErrorDb("Spell %u listed in `petcreateinfo_spell` does not exist",PetCreateSpell.spellid[i]); + PetCreateSpell.spellid[i] = 0; + continue; + } + + have_spell = true; } - mPetCreateSpell[creature_id] = PetCreateSpell; + if(!have_spell_db) + { + sLog.outErrorDb("Creature %u listed in `petcreateinfo_spell` have only 0 spell data, why it listed?",creature_id); + continue; + } + if(!have_spell) + continue; + + mPetCreateSpell[creature_id] = PetCreateSpell; ++count; } while (result->NextRow()); @@ -6509,10 +6542,35 @@ void ObjectMgr::LoadGameObjectForQuests() bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value) { + int32 start_value = min_value; + int32 end_value = max_value; + // some string can have negative indexes range + if (start_value < 0) + { + if (end_value >= start_value) + { + sLog.outErrorDb("Table '%s' attempt loaded with invalid range (%d - %d), strings not loaded.",table,min_value,max_value); + return false; + } + + // real range (max+1,min+1) exaple: (-10,-1000) -> -999...-10+1 + std::swap(start_value,end_value); + ++start_value; + ++end_value; + } + else + { + if (start_value >= end_value) + { + sLog.outErrorDb("Table '%s' attempt loaded with invalid range (%d - %d), strings not loaded.",table,min_value,max_value); + return false; + } + } + // cleanup affected map part for reloading case for(MangosStringLocaleMap::iterator itr = mMangosStringLocaleMap.begin(); itr != mMangosStringLocaleMap.end();) { - if(itr->first >= min_value && itr->first <= max_value) + if (itr->first >= start_value && itr->first < end_value) { MangosStringLocaleMap::iterator itr2 = itr; ++itr; @@ -6524,14 +6582,14 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min QueryResult *result = db.PQuery("SELECT entry,content_default,content_loc1,content_loc2,content_loc3,content_loc4,content_loc5,content_loc6,content_loc7,content_loc8 FROM %s",table); - if(!result) + if (!result) { barGoLink bar(1); bar.step(); sLog.outString(); - if(min_value == MIN_MANGOS_STRING_ID) // error only in case internal strings + if (min_value == MIN_MANGOS_STRING_ID) // error only in case internal strings sLog.outErrorDb(">> Loaded 0 mangos strings. DB table `%s` is empty. Cannot continue.",table); else sLog.outString(">> Loaded 0 string templates. DB table `%s` is empty.",table); @@ -6549,22 +6607,20 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min int32 entry = fields[0].GetInt32(); - if(entry==0) + if (entry==0) { sLog.outErrorDb("Table `%s` contain reserved entry 0, ignored.",table); continue; } - else if(entry < min_value || entry > max_value) + else if (entry < start_value || entry >= end_value) { - int32 start = min_value > 0 ? min_value : max_value; - int32 end = min_value > 0 ? max_value : min_value; - sLog.outErrorDb("Table `%s` contain entry %i out of allowed range (%d - %d), ignored.",table,entry,start,end); + sLog.outErrorDb("Table `%s` contain entry %i out of allowed range (%d - %d), ignored.",table,entry,min_value,max_value); continue; } MangosStringLocale& data = mMangosStringLocaleMap[entry]; - if(data.Content.size() > 0) + if (data.Content.size() > 0) { sLog.outErrorDb("Table `%s` contain data for already loaded entry %i (from another table?), ignored.",table,entry); continue; @@ -6579,13 +6635,13 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min for(int i = 1; i < MAX_LOCALE; ++i) { std::string str = fields[i+1].GetCppString(); - if(!str.empty()) + if (!str.empty()) { int idx = GetOrNewIndexForLocale(LocaleConstant(i)); - if(idx >= 0) + if (idx >= 0) { // 0 -> default, idx in to idx+1 - if(data.Content.size() <= idx+1) + if (data.Content.size() <= idx+1) data.Content.resize(idx+2); data.Content[idx+1] = str; @@ -6597,7 +6653,7 @@ bool ObjectMgr::LoadMangosStrings(DatabaseType& db, char const* table, int32 min delete result; sLog.outString(); - if(min_value == MIN_MANGOS_STRING_ID) // error only in case internal strings + if (min_value == MIN_MANGOS_STRING_ID) sLog.outString( ">> Loaded %u MaNGOS strings from table %s", count,table); else sLog.outString( ">> Loaded %u string templates from %s", count,table); @@ -7535,15 +7591,15 @@ uint32 GetAreaTriggerScriptId(uint32 trigger_id) bool LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value, int32 end_value) { - if(start_value >= 0 || start_value <= end_value) // start/end reversed for negative values + // MAX_DB_SCRIPT_STRING_ID is max allowed negative value for scripts (scrpts can use only more deep negative values + // start/end reversed for negative values + if (start_value > MAX_DB_SCRIPT_STRING_ID || end_value >= start_value) { - sLog.outErrorDb("Table '%s' attempt loaded with invalid range (%d - %d), use (%d - %d) instead.",table,start_value,end_value,-1,std::numeric_limits::min()); - start_value = -1; - end_value = std::numeric_limits::min(); + sLog.outErrorDb("Table '%s' attempt loaded with reserved by mangos range (%d - %d), strings not loaded.",table,start_value,end_value+1); + return false; } - // for scripting localized strings allowed use _only_ negative entries - return objmgr.LoadMangosStrings(db,table,end_value,start_value); + return objmgr.LoadMangosStrings(db,table,start_value,end_value); } uint32 MANGOS_DLL_SPEC GetScriptId(const char *name) diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 4e4947ef0..5e15b5b15 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -136,10 +136,12 @@ typedef UNORDERED_MAP RespawnTimes; // mangos string ranges -#define MIN_MANGOS_STRING_ID 1 -#define MAX_MANGOS_STRING_ID 2000000000 -#define MIN_DB_SCRIPT_STRING_ID MAX_MANGOS_STRING_ID -#define MAX_DB_SCRIPT_STRING_ID 2000010000 +#define MIN_MANGOS_STRING_ID 1 // 'mangos_string' +#define MAX_MANGOS_STRING_ID 2000000000 +#define MIN_DB_SCRIPT_STRING_ID MAX_MANGOS_STRING_ID // 'db_script_string' +#define MAX_DB_SCRIPT_STRING_ID 2000010000 +#define MIN_CREATURE_AI_TEXT_STRING_ID (-1) // 'creature_ai_texts' +#define MAX_CREATURE_AI_TEXT_STRING_ID (-1000000) struct MangosStringLocale { @@ -887,7 +889,7 @@ class ObjectMgr #define objmgr MaNGOS::Singleton::Instance() // scripting access functions -MANGOS_DLL_SPEC bool LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value = -1, int32 end_value = std::numeric_limits::min()); +MANGOS_DLL_SPEC bool LoadMangosStrings(DatabaseType& db, char const* table,int32 start_value = MAX_CREATURE_AI_TEXT_STRING_ID, int32 end_value = std::numeric_limits::min()); MANGOS_DLL_SPEC uint32 GetAreaTriggerScriptId(uint32 trigger_id); MANGOS_DLL_SPEC uint32 GetScriptId(const char *name); MANGOS_DLL_SPEC ObjectMgr::ScriptNameMap& GetScriptNames(); diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 8010486d2..527c495a2 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -58,11 +58,7 @@ m_declinedname(NULL) Pet::~Pet() { if(m_uint32Values) // only for fully created Object - { - for (PetSpellMap::const_iterator i = m_spells.begin(); i != m_spells.end(); ++i) - delete i->second; ObjectAccessor::Instance().RemoveObject(this); - } delete m_declinedname; } @@ -345,6 +341,8 @@ bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool } m_loading = false; + + SynchronizeLevelWithOwner(); return true; } @@ -732,12 +730,11 @@ void Pet::GivePetXP(uint32 xp) { newXP -= nextLvlXP; - SetLevel( level + 1 ); + GivePetLevel(level+1); SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(level+1)/4); level = getLevel(); nextLvlXP = GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP); - GivePetLevel(level); } SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP); @@ -940,7 +937,6 @@ bool Pet::InitStatsForLevel(uint32 petlevel) case HUNTER_PET: { SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(petlevel)/4); - learnLevelupSpells(); //these formula may not be correct; however, it is designed to be close to what it should be //this makes dps 0.5 of pets level SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) ); @@ -998,6 +994,9 @@ bool Pet::InitStatsForLevel(uint32 petlevel) for (int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) SetModifierValue(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(createResistance[i])); + if(cinfo->family) + learnLevelupSpells(); + UpdateAllStats(); SetHealth(GetMaxHealth()); @@ -1129,19 +1128,32 @@ void Pet::_LoadSpells() void Pet::_SaveSpells() { - for (PetSpellMap::const_iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next) + for (PetSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next) { ++next; - if (itr->second->type == PETSPELL_FAMILY) continue; // prevent saving family passives to DB - if (itr->second->state == PETSPELL_REMOVED || itr->second->state == PETSPELL_CHANGED) - CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first); - if (itr->second->state == PETSPELL_NEW || itr->second->state == PETSPELL_CHANGED) - CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second->active); - if (itr->second->state == PETSPELL_REMOVED) - _removeSpell(itr->first); - else - itr->second->state = PETSPELL_UNCHANGED; + // prevent saving family passives to DB + if (itr->second.type == PETSPELL_FAMILY) + continue; + + switch(itr->second.state) + { + case PETSPELL_REMOVED: + CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first); + m_spells.erase(itr); + continue; + case PETSPELL_CHANGED: + CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first); + CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second.active); + break; + case PETSPELL_NEW: + CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second.active); + break; + case PETSPELL_UNCHANGED: + continue; + } + + itr->second.state = PETSPELL_UNCHANGED; } } @@ -1272,7 +1284,7 @@ void Pet::_SaveAuras() } } -bool Pet::addSpell(uint32 spell_id, uint16 active, PetSpellState state, PetSpellType type) +bool Pet::addSpell(uint32 spell_id,uint16 active /*= ACT_DECIDE*/, PetSpellState state /*= PETSPELL_NEW*/, PetSpellType type /*= PETSPELL_NORMAL*/) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); if (!spellInfo) @@ -1292,16 +1304,15 @@ bool Pet::addSpell(uint32 spell_id, uint16 active, PetSpellState state, PetSpell PetSpellMap::iterator itr = m_spells.find(spell_id); if (itr != m_spells.end()) { - if (itr->second->state == PETSPELL_REMOVED) + if (itr->second.state == PETSPELL_REMOVED) { - delete itr->second; m_spells.erase(itr); state = PETSPELL_CHANGED; } - else if (state == PETSPELL_UNCHANGED && itr->second->state != PETSPELL_UNCHANGED) + else if (state == PETSPELL_UNCHANGED && itr->second.state != PETSPELL_UNCHANGED) { // can be in case spell loading but learned at some previous spell loading - itr->second->state = PETSPELL_UNCHANGED; + itr->second.state = PETSPELL_UNCHANGED; if(active == ACT_ENABLED) ToggleAutocast(spell_id, true); @@ -1316,19 +1327,19 @@ bool Pet::addSpell(uint32 spell_id, uint16 active, PetSpellState state, PetSpell uint32 oldspell_id = 0; - PetSpell *newspell = new PetSpell; - newspell->state = state; - newspell->type = type; + PetSpell newspell; + newspell.state = state; + newspell.type = type; if(active == ACT_DECIDE) //active was not used before, so we save it's autocast/passive state here { if(IsPassiveSpell(spell_id)) - newspell->active = ACT_PASSIVE; + newspell.active = ACT_PASSIVE; else - newspell->active = ACT_DISABLED; + newspell.active = ACT_DISABLED; } else - newspell->active = active; + newspell.active = active; // talent: unlearn all other talent ranks (high and low) if(TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id)) @@ -1353,13 +1364,13 @@ bool Pet::addSpell(uint32 spell_id, uint16 active, PetSpellState state, PetSpell { for (PetSpellMap::const_iterator itr2 = m_spells.begin(); itr2 != m_spells.end(); ++itr2) { - if(itr2->second->state == PETSPELL_REMOVED) continue; + if(itr2->second.state == PETSPELL_REMOVED) continue; if(spellmgr.GetFirstSpellInChain(itr2->first) == chainstart) { - newspell->active = itr2->second->active; + newspell.active = itr2->second.active; - if(newspell->active == ACT_ENABLED) + if(newspell.active == ACT_ENABLED) ToggleAutocast(itr2->first, false); oldspell_id = itr2->first; @@ -1376,7 +1387,7 @@ bool Pet::addSpell(uint32 spell_id, uint16 active, PetSpellState state, PetSpell else if(state == PETSPELL_NEW) m_charmInfo->AddSpellToAB(oldspell_id, spell_id); - if(newspell->active == ACT_ENABLED) + if(newspell.active == ACT_ENABLED) ToggleAutocast(spell_id, true); uint32 talentCost = GetTalentSpellCost(spell_id); @@ -1452,16 +1463,13 @@ bool Pet::removeSpell(uint32 spell_id) if (itr == m_spells.end()) return false; - if(itr->second->state == PETSPELL_REMOVED) + if(itr->second.state == PETSPELL_REMOVED) return false; - if(itr->second->state == PETSPELL_NEW) - { - delete itr->second; + if(itr->second.state == PETSPELL_NEW) m_spells.erase(itr); - } else - itr->second->state = PETSPELL_REMOVED; + itr->second.state = PETSPELL_REMOVED; RemoveAurasDueToSpell(spell_id); @@ -1480,24 +1488,9 @@ bool Pet::removeSpell(uint32 spell_id) return true; } -bool Pet::_removeSpell(uint32 spell_id) -{ - PetSpellMap::iterator itr = m_spells.find(spell_id); - if (itr != m_spells.end()) - { - delete itr->second; - m_spells.erase(itr); - return true; - } - return false; -} - void Pet::InitPetCreateSpells() { m_charmInfo->InitPetActionBar(); - - for (PetSpellMap::const_iterator i = m_spells.begin(); i != m_spells.end(); ++i) - delete i->second; m_spells.clear(); uint32 petspellid; @@ -1616,7 +1609,7 @@ bool Pet::resetTalents(bool no_cost) { for(PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end();) { - if(itr->second->state == PETSPELL_REMOVED) + if(itr->second.state == PETSPELL_REMOVED) { ++itr; continue; @@ -1701,7 +1694,7 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) if(IsPassiveSpell(spellid)) return; - PetSpellMap::const_iterator itr = m_spells.find(spellid); + PetSpellMap::iterator itr = m_spells.find(spellid); int i; @@ -1714,11 +1707,11 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) { m_autospells.push_back(spellid); - if(itr->second->active != ACT_ENABLED) + if(itr->second.active != ACT_ENABLED) { - itr->second->active = ACT_ENABLED; - if(itr->second->state != PETSPELL_NEW) - itr->second->state = PETSPELL_CHANGED; + itr->second.active = ACT_ENABLED; + if(itr->second.state != PETSPELL_NEW) + itr->second.state = PETSPELL_CHANGED; } } } @@ -1731,11 +1724,11 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) if (i < m_autospells.size()) { m_autospells.erase(itr2); - if(itr->second->active != ACT_DISABLED) + if(itr->second.active != ACT_DISABLED) { - itr->second->active = ACT_DISABLED; - if(itr->second->state != PETSPELL_NEW) - itr->second->state = PETSPELL_CHANGED; + itr->second.active = ACT_DISABLED; + if(itr->second.state != PETSPELL_NEW) + itr->second.state = PETSPELL_CHANGED; } } } @@ -1787,7 +1780,7 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint3 bool Pet::HasSpell(uint32 spell) const { PetSpellMap::const_iterator itr = m_spells.find(spell); - return (itr != m_spells.end() && itr->second->state != PETSPELL_REMOVED ); + return (itr != m_spells.end() && itr->second.state != PETSPELL_REMOVED ); } // Get all passive spells in our skill line @@ -1853,3 +1846,29 @@ void Pet::learnSpellHighRank(uint32 spellid) for(SpellChainMapNext::const_iterator itr = nextMap.lower_bound(spellid); itr != nextMap.upper_bound(spellid); ++itr) learnSpellHighRank(itr->second); } + +void Pet::SynchronizeLevelWithOwner() +{ + Unit* owner = GetOwner(); + if (!owner || owner->GetTypeId() != TYPEID_PLAYER) + return; + + switch(getPetType()) + { + // always same level + case SUMMON_PET: + GivePetLevel(owner->getLevel()); + break; + // can't be greater owner level + case HUNTER_PET: + if(getLevel() > owner->getLevel()) + { + GivePetLevel(owner->getLevel()); + SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(owner->getLevel())/4); + SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP)-1); + } + break; + default: + break; + } +} diff --git a/src/game/Pet.h b/src/game/Pet.h index e88576438..07e1036ce 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -71,8 +71,8 @@ struct PetSpell { uint16 active; - PetSpellState state : 16; - PetSpellType type : 16; + PetSpellState state : 8; + PetSpellType type : 8; }; enum ActionFeedback @@ -106,7 +106,7 @@ enum PetNameInvalidReason PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 16 }; -typedef UNORDERED_MAP PetSpellMap; +typedef UNORDERED_MAP PetSpellMap; typedef std::map TeachSpellMap; typedef std::vector AutoSpellList; @@ -114,7 +114,7 @@ typedef std::vector AutoSpellList; #define ACTIVE_SPELLS_MAX 4 -#define OWNER_MAX_DISTANCE 100 +#define OWNER_MAX_DISTANCE 100.0f #define PET_FOLLOW_DIST 1 #define PET_FOLLOW_ANGLE (M_PI/2) @@ -161,6 +161,7 @@ class Pet : public Creature HappinessState GetHappinessState(); void GivePetXP(uint32 xp); void GivePetLevel(uint32 level); + void SynchronizeLevelWithOwner(); bool InitStatsForLevel(uint32 level); bool HaveInDiet(ItemPrototype const* item) const; uint32 GetCurrentFoodBenefitLevel(uint32 itemlevel); @@ -201,7 +202,6 @@ class Pet : public Creature void learnLevelupSpells(); bool unlearnSpell(uint32 spell_id); bool removeSpell(uint32 spell_id); - bool _removeSpell(uint32 spell_id); PetSpellMap m_spells; TeachSpellMap m_teachspells; diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 3fc412c6f..8de2644f3 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -288,8 +288,7 @@ void PetAI::UpdateAI(const uint32 diff) bool PetAI::_isVisible(Unit *u) const { - //return false; //( ((Creature*)&i_pet)->GetDistanceSq(u) * 1.0<= sWorld.getConfig(CONFIG_SIGHT_GUARDER) && !u->m_stealth && u->isAlive()); - return m_creature->GetDistance(u) < sWorld.getConfig(CONFIG_SIGHT_GUARDER) + return m_creature->IsWithinDist(u,sWorld.getConfig(CONFIG_SIGHT_GUARDER)) && u->isVisibleForOrDetect(m_creature,true); } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 15e5387df..ac64b0c85 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1442,7 +1442,12 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) char_flags |= CHARACTER_FLAG_GHOST; if(HasAtLoginFlag(AT_LOGIN_RENAME)) char_flags |= CHARACTER_FLAG_RENAME; - if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) && (fields[14].GetCppString() != "")) + if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED)) + { + if(!fields[14].GetCppString().empty()) + char_flags |= CHARACTER_FLAG_DECLINED; + } + else char_flags |= CHARACTER_FLAG_DECLINED; *p_data << uint32(char_flags); // character flags @@ -1608,7 +1613,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if (!(options & TELE_TO_NOT_UNSUMMON_PET)) { //same map, only remove pet if out of range for new position - if(pet && pet->GetDistance(x,y,z) >= OWNER_MAX_DISTANCE) + if(pet && !pet->IsWithinDist3d(x,y,z, OWNER_MAX_DISTANCE)) UnsummonPetTemporaryIfAny(); } @@ -2294,10 +2299,10 @@ void Player::GiveLevel(uint32 level) SetPower(POWER_FOCUS, 0); SetPower(POWER_HAPPINESS, 0); - // give level to summoned pet - Pet* pet = GetPet(); - if(pet && pet->getPetType()==SUMMON_PET) - pet->GivePetLevel(level); + // update level to hunter/summon pet + if (Pet* pet = GetPet()) + pet->SynchronizeLevelWithOwner(); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL); } @@ -2485,6 +2490,10 @@ void Player::InitStatsForLevel(bool reapplyMods) SetPower(POWER_FOCUS, 0); SetPower(POWER_HAPPINESS, 0); SetPower(POWER_RUNIC_POWER, 0); + + // update level to hunter/summon pet + if (Pet* pet = GetPet()) + pet->SynchronizeLevelWithOwner(); } void Player::SendInitialSpells() @@ -5659,23 +5668,26 @@ ReputationRank Player::GetReputationRank(uint32 faction) const } //Calculate total reputation percent player gain with quest/creature level -int32 Player::CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, bool for_quest) +int32 Player::CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool for_quest) { float percent = 100.0f; float rate = for_quest ? sWorld.getRate(RATE_REPUTATION_LOWLEVEL_QUEST) : sWorld.getRate(RATE_REPUTATION_LOWLEVEL_KILL); - if(rate != 1.0f && creatureOrQuestLevel <= MaNGOS::XP::GetGrayLevel(getLevel())) + if (rate != 1.0f && creatureOrQuestLevel <= MaNGOS::XP::GetGrayLevel(getLevel())) percent *= rate; - int32 repMod = GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN); + float repMod = GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN); + + if (!for_quest) + repMod += GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_FACTION_REPUTATION_GAIN, faction); percent += rep > 0 ? repMod : -repMod; - if(percent <= 0.0f) + if (percent <= 0.0f) return 0; - return int32(sWorld.getRate(RATE_REPUTATION_GAIN)*rep*percent/100); + return int32(sWorld.getRate(RATE_REPUTATION_GAIN)*rep*percent/100.0f); } //Calculates how many reputation points player gains in victim's enemy factions @@ -5691,7 +5703,7 @@ void Player::RewardReputation(Unit *pVictim, float rate) if(Rep->repfaction1 && (!Rep->team_dependent || GetTeam()==ALLIANCE)) { - int32 donerep1 = CalculateReputationGain(pVictim->getLevel(),Rep->repvalue1,false); + int32 donerep1 = CalculateReputationGain(pVictim->getLevel(), Rep->repvalue1, Rep->repfaction1, false); donerep1 = int32(donerep1*rate); FactionEntry const *factionEntry1 = sFactionStore.LookupEntry(Rep->repfaction1); uint32 current_reputation_rank1 = GetReputationMgr().GetRank(factionEntry1); @@ -5709,7 +5721,7 @@ void Player::RewardReputation(Unit *pVictim, float rate) if(Rep->repfaction2 && (!Rep->team_dependent || GetTeam()==HORDE)) { - int32 donerep2 = CalculateReputationGain(pVictim->getLevel(),Rep->repvalue2,false); + int32 donerep2 = CalculateReputationGain(pVictim->getLevel(), Rep->repvalue2, Rep->repfaction2, false); donerep2 = int32(donerep2*rate); FactionEntry const *factionEntry2 = sFactionStore.LookupEntry(Rep->repfaction2); uint32 current_reputation_rank2 = GetReputationMgr().GetRank(factionEntry2); @@ -5734,7 +5746,7 @@ void Player::RewardReputation(Quest const *pQuest) { if(pQuest->RewRepFaction[i] && pQuest->RewRepValue[i] ) { - int32 rep = CalculateReputationGain(GetQuestLevel(pQuest),pQuest->RewRepValue[i],true); + int32 rep = CalculateReputationGain(GetQuestLevel(pQuest), pQuest->RewRepValue[i], pQuest->RewRepFaction[i], true); FactionEntry const* factionEntry = sFactionStore.LookupEntry(pQuest->RewRepFaction[i]); if(factionEntry) GetReputationMgr().ModifyReputation(factionEntry, rep); @@ -6325,30 +6337,25 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl if(slot >= INVENTORY_SLOT_BAG_END || !proto) return; + ScalingStatDistributionEntry const *ssd = proto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution) : 0; + ScalingStatValuesEntry const *ssv = proto->ScalingStatValue ? sScalingStatValuesStore.LookupEntry(getLevel()) : 0; + for (int i = 0; i < MAX_ITEM_PROTO_STATS; ++i) { uint32 statType = 0; - int32 val = 0; - - if(proto->ScalingStatDistribution) + int32 val = 0; + // If set ScalingStatDistribution need get stats and values from it + if (ssd && ssv) { - if(ScalingStatDistributionEntry const *ssd = sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution)) - { - statType = ssd->StatMod[i]; - - if(uint32 modifier = ssd->Modifier[i]) - { - uint32 level = ((getLevel() > ssd->MaxLevel) ? ssd->MaxLevel : getLevel()); - if(ScalingStatValuesEntry const *ssv = sScalingStatValuesStore.LookupEntry(level)) - { - uint32 multiplier = ssv->Multiplier[proto->GetScalingStatValuesColumn()]; - val = (multiplier * modifier) / 10000; - } - } - } + if (ssd->StatMod[i] < 0) + continue; + statType = ssd->StatMod[i]; + val = (ssv->getssdMultiplier(proto->ScalingStatValue) * ssd->Modifier[i]) / 10000; } else { + if (i >= proto->StatsCount) + continue; statType = proto->ItemStat[i].ItemStatType; val = proto->ItemStat[i].ItemStatValue; } @@ -6503,8 +6510,18 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl } } - if (proto->Armor) - HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(proto->Armor), apply); + // If set ScalingStatValue armor get it or use item armor + uint32 armor = proto->Armor; + if (ssv) + { + if (uint32 ssvarmor = ssv->getArmorMod(proto->ScalingStatValue)) + armor = ssvarmor; + } + // Add armor bonus from ArmorDamageModifier if > 0 + if (proto->ArmorDamageModifier > 0) + armor+=proto->ArmorDamageModifier; + if (armor) + HandleStatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(armor), apply); if (proto->Block) HandleBaseModValue(SHIELD_BLOCK_VALUE, FLAT_MOD, float(proto->Block), apply); @@ -6541,23 +6558,42 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool appl attType = OFF_ATTACK; } - if (proto->Damage[0].DamageMin > 0 ) + float minDamage = proto->Damage[0].DamageMin; + float maxDamage = proto->Damage[0].DamageMax; + int32 extraDPS = 0; + // If set dpsMod in ScalingStatValue use it for min (70% from average), max (130% from average) damage + if (ssv) { - damage = apply ? proto->Damage[0].DamageMin : BASE_MINDAMAGE; + if (extraDPS = ssv->getDPSMod(proto->ScalingStatValue)) + { + float average = extraDPS * proto->Delay / 1000.0f; + minDamage = 0.7f * average; + maxDamage = 1.3f * average; + } + } + if (minDamage > 0 ) + { + damage = apply ? minDamage : BASE_MINDAMAGE; SetBaseWeaponDamage(attType, MINDAMAGE, damage); //sLog.outError("applying mindam: assigning %f to weapon mindamage, now is: %f", damage, GetWeaponDamageRange(attType, MINDAMAGE)); } - if (proto->Damage[0].DamageMax > 0 ) + if (maxDamage > 0 ) { - damage = apply ? proto->Damage[0].DamageMax : BASE_MAXDAMAGE; + damage = apply ? maxDamage : BASE_MAXDAMAGE; SetBaseWeaponDamage(attType, MAXDAMAGE, damage); } - // Druids get feral AP bonus from weapon dps + // Apply feral bonus from ScalingStatValue if set + if (ssv) + { + if (int32 feral_bonus = ssv->getFeralBonus(proto->ScalingStatValue)) + ApplyFeralAPBonus(feral_bonus, apply); + } + // Druids get feral AP bonus from weapon dps (lso use DPS from ScalingStatValue) if(getClass() == CLASS_DRUID) { - int32 feral_bonus = proto->getFeralBonus(); + int32 feral_bonus = proto->getFeralBonus(extraDPS); if (feral_bonus > 0) ApplyFeralAPBonus(feral_bonus, apply); } @@ -9545,18 +9581,22 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo return EQUIP_ERR_CANT_DO_RIGHT_NOW; } - uint8 eslot = FindEquipSlot( pProto, slot, swap ); - if( eslot == NULL_SLOT ) + ScalingStatDistributionEntry const *ssd = pProto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(pProto->ScalingStatDistribution) : 0; + if (ssd && ssd->MaxLevel < getLevel()) return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED; - uint8 msg = CanUseItem( pItem , not_loading ); - if( msg != EQUIP_ERR_OK ) + uint8 eslot = FindEquipSlot( pProto, slot, swap ); + if (eslot == NULL_SLOT) + return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED; + + uint8 msg = CanUseItem(pItem , not_loading); + if (msg != EQUIP_ERR_OK) return msg; - if( !swap && GetItemByPos( INVENTORY_SLOT_BAG_0, eslot ) ) + if (!swap && GetItemByPos(INVENTORY_SLOT_BAG_0, eslot)) return EQUIP_ERR_NO_EQUIPMENT_SLOT_AVAILABLE; // if swap ignore item (equipped also) - if(uint8 res2 = CanEquipUniqueItem(pItem, swap ? eslot : NULL_SLOT)) + if (uint8 res2 = CanEquipUniqueItem(pItem, swap ? eslot : NULL_SLOT)) return res2; // check unique-equipped special item classes @@ -9564,19 +9604,16 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo { for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) { - if( Item* pBag = GetItemByPos( INVENTORY_SLOT_BAG_0, i ) ) + if (Item* pBag = GetItemByPos(INVENTORY_SLOT_BAG_0, i)) { - if( pBag != pItem ) + if (pBag != pItem) { - if( ItemPrototype const* pBagProto = pBag->GetProto() ) + if (ItemPrototype const* pBagProto = pBag->GetProto()) { - if( pBagProto->Class==pProto->Class && (!swap || pBag->GetSlot() != eslot ) ) - { - if(pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH) - return EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH; - else - return EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER; - } + if (pBagProto->Class==pProto->Class && (!swap || pBag->GetSlot() != eslot)) + return (pBagProto->SubClass == ITEM_SUBCLASS_AMMO_POUCH) + ? EQUIP_ERR_CAN_EQUIP_ONLY1_AMMOPOUCH + : EQUIP_ERR_CAN_EQUIP_ONLY1_QUIVER; } } } @@ -9585,25 +9622,25 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo uint32 type = pProto->InventoryType; - if(eslot == EQUIPMENT_SLOT_OFFHAND) + if (eslot == EQUIPMENT_SLOT_OFFHAND) { if (type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND) { - if(!CanDualWield()) + if (!CanDualWield()) return EQUIP_ERR_CANT_DUAL_WIELD; } else if (type == INVTYPE_2HWEAPON) { - if(!CanDualWield() || !CanTitanGrip()) + if (!CanDualWield() || !CanTitanGrip()) return EQUIP_ERR_CANT_DUAL_WIELD; } - if(IsTwoHandUsed()) + if (IsTwoHandUsed()) return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED; } // equip two-hand weapon case (with possible unequip 2 items) - if( type == INVTYPE_2HWEAPON ) + if (type == INVTYPE_2HWEAPON) { if (eslot == EQUIPMENT_SLOT_OFFHAND) { @@ -9618,9 +9655,9 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo // offhand item must can be stored in inventory for offhand item and it also must be unequipped Item *offItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND ); ItemPosCountVec off_dest; - if( offItem && (!not_loading || + if (offItem && (!not_loading || CanUnequipItem(uint16(INVENTORY_SLOT_BAG_0) << 8 | EQUIPMENT_SLOT_OFFHAND,false) != EQUIP_ERR_OK || - CanStoreItem( NULL_BAG, NULL_SLOT, off_dest, offItem, false ) != EQUIP_ERR_OK ) ) + CanStoreItem( NULL_BAG, NULL_SLOT, off_dest, offItem, false ) != EQUIP_ERR_OK )) return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_INVENTORY_FULL; } } @@ -9628,10 +9665,8 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo return EQUIP_ERR_OK; } } - if( !swap ) - return EQUIP_ERR_ITEM_NOT_FOUND; - else - return EQUIP_ERR_ITEMS_CANT_BE_SWAPPED; + + return !swap ? EQUIP_ERR_ITEM_NOT_FOUND : EQUIP_ERR_ITEMS_CANT_BE_SWAPPED; } uint8 Player::CanUnequipItem( uint16 pos, bool swap ) const @@ -9850,38 +9885,49 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p uint8 Player::CanUseItem( Item *pItem, bool not_loading ) const { - if( pItem ) + if (pItem) { sLog.outDebug( "STORAGE: CanUseItem item = %u", pItem->GetEntry()); - if( !isAlive() && not_loading ) + + if (!isAlive() && not_loading) return EQUIP_ERR_YOU_ARE_DEAD; - //if( isStunned() ) + + //if (isStunned()) // return EQUIP_ERR_YOU_ARE_STUNNED; + ItemPrototype const *pProto = pItem->GetProto(); - if( pProto ) + if (pProto) { - if( pItem->IsBindedNotWith(GetGUID()) ) + if (pItem->IsBindedNotWith(GetGUID())) return EQUIP_ERR_DONT_OWN_THAT_ITEM; - if( (pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0 ) + + if ((pProto->AllowableClass & getClassMask()) == 0 || (pProto->AllowableRace & getRaceMask()) == 0) return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM; - if( pItem->GetSkill() != 0 ) + + if (pItem->GetSkill() != 0) { - if( GetSkillValue( pItem->GetSkill() ) == 0 ) + if (GetSkillValue( pItem->GetSkill() ) == 0) return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; } - if( pProto->RequiredSkill != 0 ) + + if (pProto->RequiredSkill != 0) { - if( GetSkillValue( pProto->RequiredSkill ) == 0 ) + if (GetSkillValue( pProto->RequiredSkill ) == 0) return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; - else if( GetSkillValue( pProto->RequiredSkill ) < pProto->RequiredSkillRank ) + + if (GetSkillValue( pProto->RequiredSkill ) < pProto->RequiredSkillRank) return EQUIP_ERR_ERR_CANT_EQUIP_SKILL; } - if( pProto->RequiredSpell != 0 && !HasSpell( pProto->RequiredSpell ) ) + + if (pProto->RequiredSpell != 0 && !HasSpell(pProto->RequiredSpell)) return EQUIP_ERR_NO_REQUIRED_PROFICIENCY; - if( pProto->RequiredReputationFaction && uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank ) + + if (pProto->RequiredReputationFaction && uint32(GetReputationRank(pProto->RequiredReputationFaction)) < pProto->RequiredReputationRank) return EQUIP_ERR_CANT_EQUIP_REPUTATION; - if( getLevel() < pProto->RequiredLevel ) + + if (getLevel() < pProto->RequiredLevel) return EQUIP_ERR_CANT_EQUIP_LEVEL_I; + return EQUIP_ERR_OK; } } @@ -16295,11 +16341,11 @@ void Player::PetSpellInitialize() // spells loop for (PetSpellMap::const_iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr) { - if(itr->second->state == PETSPELL_REMOVED) + if(itr->second.state == PETSPELL_REMOVED) continue; data << uint16(itr->first); - data << uint16(itr->second->active); // pet spell active state isn't boolean + data << uint16(itr->second.active); // pet spell active state isn't boolean ++addlist; } } @@ -20210,4 +20256,4 @@ void Player::DeleteEquipmentSet(uint64 setGuid) break; } } -} +} \ No newline at end of file diff --git a/src/game/Player.h b/src/game/Player.h index 9e1c51e91..5a9197010 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -949,6 +949,7 @@ class MANGOS_DLL_SPEC Player : public Unit void GiveXP(uint32 xp, Unit* victim); void GiveLevel(uint32 level); + void InitStatsForLevel(bool reapplyMods = false); // Played Time Stuff @@ -2315,7 +2316,7 @@ class MANGOS_DLL_SPEC Player : public Unit Item* _StoreItem( uint16 pos, Item *pItem, uint32 count, bool clone, bool update ); void UpdateKnownCurrencies(uint32 itemId, bool apply); - int32 CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, bool for_quest); + int32 CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool for_quest); void AdjustQuestReqItemCount( Quest const* pQuest, QuestStatusData& questStatusData ); GridReference m_gridRef; diff --git a/src/game/RandomMovementGenerator.cpp b/src/game/RandomMovementGenerator.cpp index beb13cd68..c2ff8e85d 100644 --- a/src/game/RandomMovementGenerator.cpp +++ b/src/game/RandomMovementGenerator.cpp @@ -153,7 +153,7 @@ RandomMovementGenerator::Update(Creature &creature, const uint32 &diff creature.SetUnitMovementFlags(irand(0,RUNNING_CHANCE_RANDOMMV) > 0 ? MONSTER_MOVE_WALK : MONSTER_MOVE_NONE); _setRandomLocation(creature); } - else if(creature.isPet() && creature.GetOwner() && creature.GetDistance(creature.GetOwner()) > PET_FOLLOW_DIST+2.5f) + else if(creature.isPet() && creature.GetOwner() && !creature.IsWithinDist(creature.GetOwner(),PET_FOLLOW_DIST+2.5f)) { creature.SetUnitMovementFlags(MONSTER_MOVE_WALK); _setRandomLocation(creature); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 3c2e12d32..72683217b 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -1817,6 +1817,8 @@ enum CreatureFamily CREATURE_FAMILY_SPIRIT_BEAST = 46 }; +#define MAX_CREATURE_FAMILY 47 + enum CreatureTypeFlags { CREATURE_TYPEFLAGS_TAMEABLE = 0x0001, diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 817797fc1..6703ebe6d 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1334,7 +1334,7 @@ struct TargetDistanceOrder : public std::binary_function" bool operator()(const Unit* _Left, const Unit* _Right) const { - return (MainTarget->GetDistance(_Left) < MainTarget->GetDistance(_Right)); + return MainTarget->GetDistanceOrder(_Left,_Right); } }; @@ -1427,7 +1427,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) //Now to get us a random target that's in the initial range of the spell uint32 t = 0; std::list::iterator itr = tempUnitMap.begin(); - while(itr!= tempUnitMap.end() && (*itr)->GetDistance(m_caster) < radius) + while(itr!= tempUnitMap.end() && (*itr)->IsWithinDist(m_caster,radius)) ++t, ++itr; if(!t) @@ -1448,7 +1448,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) while(t && next != tempUnitMap.end() ) { - if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + if(!prev->IsWithinDist(*next,CHAIN_SPELL_JUMP_RADIUS)) break; if(!prev->IsWithinLOSInMap(*next)) @@ -1496,7 +1496,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) //Now to get us a random target that's in the initial range of the spell uint32 t = 0; std::list::iterator itr = tempUnitMap.begin(); - while(itr!= tempUnitMap.end() && (*itr)->GetDistance(m_caster) < radius) + while(itr!= tempUnitMap.end() && (*itr)->IsWithinDist(m_caster,radius)) ++t, ++itr; if(!t) @@ -1517,7 +1517,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) while(t && next != tempUnitMap.end() ) { - if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + if(!prev->IsWithinDist(*next,CHAIN_SPELL_JUMP_RADIUS)) break; if(!prev->IsWithinLOSInMap(*next)) @@ -1602,7 +1602,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) while(t && next != tempUnitMap.end() ) { - if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + if(!prev->IsWithinDist(*next,CHAIN_SPELL_JUMP_RADIUS)) break; if(!prev->IsWithinLOSInMap(*next)) @@ -2029,7 +2029,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,UnitList& TagUnitMap) while(t && next != tempUnitMap.end() ) { - if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS) + if(!prev->IsWithinDist(*next,CHAIN_SPELL_JUMP_RADIUS)) break; if(!prev->IsWithinLOSInMap(*next)) @@ -4688,10 +4688,9 @@ SpellCastResult Spell::CheckRange(bool strict) if(m_targets.m_targetMask == TARGET_FLAG_DEST_LOCATION && m_targets.m_destX != 0 && m_targets.m_destY != 0 && m_targets.m_destZ != 0) { - float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); - if(dist > max_range) + if(!m_caster->IsWithinDist3d(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ,max_range)) return SPELL_FAILED_OUT_OF_RANGE; - if(dist < min_range) + if(m_caster->IsWithinDist3d(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ,min_range)) return SPELL_FAILED_TOO_CLOSE; } diff --git a/src/game/Spell.h b/src/game/Spell.h index ac2544b59..3ffa368eb 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -621,7 +621,7 @@ namespace MaNGOS if( i_originalCaster->IsFriendlyTo(pPlayer) ) continue; - if( pPlayer->GetDistance(i_spell.m_targets.m_destX, i_spell.m_targets.m_destY, i_spell.m_targets.m_destZ) < i_radius ) + if( pPlayer->IsWithinDist3d(i_spell.m_targets.m_destX, i_spell.m_targets.m_destY, i_spell.m_targets.m_destZ,i_radius)) i_data.push_back(pPlayer); } } @@ -656,6 +656,10 @@ namespace MaNGOS if( !itr->getSource()->isAlive() || (itr->getSource()->GetTypeId() == TYPEID_PLAYER && ((Player*)itr->getSource())->isInFlight())) continue; + // mostly phase check + if(!itr->getSource()->IsInMap(i_originalCaster)) + continue; + switch (i_TargetType) { case SPELL_TARGETS_HOSTILE: @@ -701,23 +705,23 @@ namespace MaNGOS switch(i_push_type) { case PUSH_IN_FRONT: - if(i_spell.GetCaster()->isInFront((Unit*)(itr->getSource()), i_radius, 2*M_PI/3 )) + if(i_spell.GetCaster()->isInFrontInMap((Unit*)(itr->getSource()), i_radius, 2*M_PI/3 )) i_data->push_back(itr->getSource()); break; case PUSH_IN_BACK: - if(i_spell.GetCaster()->isInBack((Unit*)(itr->getSource()), i_radius, 2*M_PI/3 )) + if(i_spell.GetCaster()->isInBackInMap((Unit*)(itr->getSource()), i_radius, 2*M_PI/3 )) i_data->push_back(itr->getSource()); break; case PUSH_SELF_CENTER: - if(i_spell.GetCaster()->IsWithinDistInMap((Unit*)(itr->getSource()), i_radius)) + if(i_spell.GetCaster()->IsWithinDist((Unit*)(itr->getSource()), i_radius)) i_data->push_back(itr->getSource()); break; case PUSH_DEST_CENTER: - if((itr->getSource()->GetDistance(i_spell.m_targets.m_destX, i_spell.m_targets.m_destY, i_spell.m_targets.m_destZ) < i_radius )) + if(itr->getSource()->IsWithinDist3d(i_spell.m_targets.m_destX, i_spell.m_targets.m_destY, i_spell.m_targets.m_destZ,i_radius)) i_data->push_back(itr->getSource()); break; case PUSH_TARGET_CENTER: - if(i_spell.m_targets.getUnitTarget()->IsWithinDistInMap((Unit*)(itr->getSource()), i_radius)) + if(i_spell.m_targets.getUnitTarget()->IsWithinDist((Unit*)(itr->getSource()), i_radius)) i_data->push_back(itr->getSource()); break; } diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index aac327cd4..679c1923b 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -240,7 +240,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, //187 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance &Aura::HandleNoImmediateEffect, //188 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_CHANCE implemented in Unit::GetUnitCriticalChance &Aura::HandleModRating, //189 SPELL_AURA_MOD_RATING - &Aura::HandleNULL, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN + &Aura::HandleNoImmediateEffect, //190 SPELL_AURA_MOD_FACTION_REPUTATION_GAIN implemented in Player::CalculateReputationGain &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 3e3693a4b..2e7623f3a 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -592,9 +592,9 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) else if(m_spellInfo->SpellFamilyFlags&0x0004000000000000LL) { // Add main hand dps * effect[2] amount - float averange = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2; + float average = (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 * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK); + damage += count * int32(average * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK); } // Shield of Righteousness else if(m_spellInfo->SpellFamilyFlags&0x0010000000000000LL) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 7c72d2ec2..5b7ba0848 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2126,184 +2126,101 @@ void SpellMgr::LoadSpellPetAuras() sLog.outString( ">> Loaded %u spell pet auras", count ); } +static uint32 family2skillline[MAX_CREATURE_FAMILY][2] = { + /* ----------------------------- = 0 */ {0, 0 }, + /*CREATURE_FAMILY_WOLF = 1 */ {208, 270}, + /*CREATURE_FAMILY_CAT = 2 */ {209, 270}, + /*CREATURE_FAMILY_SPIDER = 3 */ {203, 270}, + /*CREATURE_FAMILY_BEAR = 4 */ {210, 270}, + /*CREATURE_FAMILY_BOAR = 5 */ {211, 270}, + /*CREATURE_FAMILY_CROCOLISK = 6 */ {212, 270}, + /*CREATURE_FAMILY_CARRION_BIRD = 7 */ {213, 270}, + /*CREATURE_FAMILY_CRAB = 8 */ {214, 270}, + /*CREATURE_FAMILY_GORILLA = 9 */ {215, 270}, + /*CREATURE_FAMILY_HORSE_CUSTOM = 10*/ {0, 0 }, + /*CREATURE_FAMILY_RAPTOR = 11*/ {217, 270}, + /*CREATURE_FAMILY_TALLSTRIDER = 12*/ {218, 270}, + /* ----------------------------- = 13*/ {0, 0 }, + /* ----------------------------- = 14*/ {0, 0 }, + /*CREATURE_FAMILY_FELHUNTER = 15*/ {189, 0 }, + /*CREATURE_FAMILY_VOIDWALKER = 16*/ {204, 0 }, + /*CREATURE_FAMILY_SUCCUBUS = 17*/ {205, 0 }, + /* ----------------------------- = 18*/ {0, 0 }, + /*CREATURE_FAMILY_DOOMGUARD = 19*/ {207, 0 }, + /*CREATURE_FAMILY_SCORPID = 20*/ {236, 270}, + /*CREATURE_FAMILY_TURTLE = 21*/ {251, 270}, + /* ----------------------------- = 22*/ {0, 0 }, + /*CREATURE_FAMILY_IMP = 23*/ {188, 0 }, + /*CREATURE_FAMILY_BAT = 24*/ {653, 270}, + /*CREATURE_FAMILY_HYENA = 25*/ {654, 270}, + /*CREATURE_FAMILY_BIRD_OF_PREY = 26*/ {655, 270}, + /*CREATURE_FAMILY_WIND_SERPENT = 27*/ {656, 270}, + /*CREATURE_FAMILY_REMOTE_CONTROL = 28*/ {758, 0 }, + /*CREATURE_FAMILY_FELGUARD = 29*/ {761, 0 }, + /*CREATURE_FAMILY_DRAGONHAWK = 30*/ {763, 270}, + /*CREATURE_FAMILY_RAVAGER = 31*/ {767, 270}, + /*CREATURE_FAMILY_WARP_STALKER = 32*/ {766, 270}, + /*CREATURE_FAMILY_SPOREBAT = 33*/ {765, 270}, + /*CREATURE_FAMILY_NETHER_RAY = 34*/ {764, 270}, + /*CREATURE_FAMILY_SERPENT = 35*/ {768, 270}, + /* ----------------------------- = 36*/ {0, 0 }, + /*CREATURE_FAMILY_MOTH = 37*/ {775, 270}, + /*CREATURE_FAMILY_CHIMAERA = 38*/ {780, 270}, + /*CREATURE_FAMILY_DEVILSAUR = 39*/ {781, 270}, + /*CREATURE_FAMILY_GHOUL = 40*/ {782, 0 }, + /*CREATURE_FAMILY_SILITHID = 41*/ {783, 270}, + /*CREATURE_FAMILY_WORM = 42*/ {784, 270}, + /*CREATURE_FAMILY_RHINO = 43*/ {786, 270}, + /*CREATURE_FAMILY_WASP = 44*/ {785, 270}, + /*CREATURE_FAMILY_CORE_HOUND = 45*/ {787, 270}, + /*CREATURE_FAMILY_SPIRIT_BEAST = 46*/ {788, 270} +}; + void SpellMgr::LoadPetLevelupSpellMap() { - CreatureFamilyEntry const *creatureFamily; - SpellEntry const *spell; uint32 count = 0; + uint32 family_count = 0; for (uint32 i = 0; i < sCreatureFamilyStore.GetNumRows(); ++i) { - creatureFamily = sCreatureFamilyStore.LookupEntry(i); - + CreatureFamilyEntry const *creatureFamily = sCreatureFamilyStore.LookupEntry(i); if(!creatureFamily) // not exist continue; - if(creatureFamily->petTalentType < 0) // not hunter pet family + if(i >= MAX_CREATURE_FAMILY) continue; - for(uint32 j = 0; j < sSpellStore.GetNumRows(); ++j) + if(!family2skillline[i][0]) + continue; + + for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) { - spell = sSpellStore.LookupEntry(j); - - // not exist - if(!spell) + SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j); + if( !skillLine ) continue; - // not hunter spell - if(spell->SpellFamilyName != SPELLFAMILY_HUNTER) + if (skillLine->skillId!=family2skillline[i][0] && + (!family2skillline[i][1] || skillLine->skillId!=family2skillline[i][1])) continue; - // not pet spell - if(!(spell->SpellFamilyFlags & 0x1000000000000000LL)) + if(skillLine->learnOnGetSkill != ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL) continue; - // not Growl or Cower (generics) - if(spell->SpellIconID != 201 && spell->SpellIconID != 958) - { - switch(creatureFamily->ID) - { - case CREATURE_FAMILY_BAT: // Bite and Sonic Blast - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1577) - continue; - break; - case CREATURE_FAMILY_BEAR: // Claw and Swipe - if(spell->SpellIconID != 262 && spell->SpellIconID != 1562) - continue; - break; - case CREATURE_FAMILY_BIRD_OF_PREY: // Claw and Snatch - if(spell->SpellIconID != 262 && spell->SpellIconID != 168) - continue; - break; - case CREATURE_FAMILY_BOAR: // Bite and Gore - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1578) - continue; - break; - case CREATURE_FAMILY_CARRION_BIRD: // Bite and Demoralizing Screech - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1579) - continue; - break; - case CREATURE_FAMILY_CAT: // Claw and Prowl and Rake - if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 494) - continue; - break; - case CREATURE_FAMILY_CHIMAERA: // Bite and Froststorm Breath - if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) - continue; - break; - case CREATURE_FAMILY_CORE_HOUND: // Bite and Lava Breath - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1197) - continue; - break; - case CREATURE_FAMILY_CRAB: // Claw and Pin - if(spell->SpellIconID != 262 && spell->SpellIconID != 2679) - continue; - break; - case CREATURE_FAMILY_CROCOLISK: // Bite and Bad Attitude - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1581) - continue; - break; - case CREATURE_FAMILY_DEVILSAUR: // Bite and Monstrous Bite - if(spell->SpellIconID != 1680 && spell->SpellIconID != 599) - continue; - break; - case CREATURE_FAMILY_DRAGONHAWK: // Bite and Fire Breath - if(spell->SpellIconID != 1680 && spell->SpellIconID != 2128) - continue; - break; - case CREATURE_FAMILY_GORILLA: // Smack and Thunderstomp - if(spell->SpellIconID != 473 && spell->SpellIconID != 148) - continue; - break; - case CREATURE_FAMILY_HYENA: // Bite and Tendon Rip - if(spell->SpellIconID != 1680 && spell->SpellIconID != 138) - continue; - break; - case CREATURE_FAMILY_MOTH: // Serenity Dust and Smack - if(spell->SpellIconID != 1714 && spell->SpellIconID != 473) - continue; - break; - case CREATURE_FAMILY_NETHER_RAY: // Bite and Nether Shock - if(spell->SpellIconID != 1680 && spell->SpellIconID != 2027) - continue; - break; - case CREATURE_FAMILY_RAPTOR: // Claw and Savage Rend - if(spell->SpellIconID != 262 && spell->SpellIconID != 245) - continue; - break; - case CREATURE_FAMILY_RAVAGER: // Bite and Ravage - if(spell->SpellIconID != 1680 && spell->SpellIconID != 2253) - continue; - break; - case CREATURE_FAMILY_RHINO: // Smack and Stampede - if(spell->SpellIconID != 473 && spell->SpellIconID != 3066) - continue; - break; - case CREATURE_FAMILY_SCORPID: // Claw and Scorpid Poison - if(spell->SpellIconID != 262 && spell->SpellIconID != 163) - continue; - break; - case CREATURE_FAMILY_SERPENT: // Bite and Poison Spit - if(spell->SpellIconID != 1680 && spell->SpellIconID != 68) - continue; - break; - case CREATURE_FAMILY_SILITHID: // Claw and Venom Web Spray - if(spell->SpellIconID != 262 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 12013)) - continue; - break; - case CREATURE_FAMILY_SPIDER: // Bite and Web - if(spell->SpellIconID != 1680 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 684)) - continue; - break; - case CREATURE_FAMILY_SPIRIT_BEAST: // Claw and Prowl and Spirit Strike - if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 255) - continue; - break; - case CREATURE_FAMILY_SPOREBAT: // Smack and Spore Cloud - if(spell->SpellIconID != 473 && spell->SpellIconID != 2681) - continue; - break; - case CREATURE_FAMILY_TALLSTRIDER: // Claw and Dust Cloud - if(spell->SpellIconID != 262 && (spell->SpellIconID != 157 && !(spell->Attributes & 0x4000000))) - continue; - break; - case CREATURE_FAMILY_TURTLE: // Bite and Shell Shield - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1588) - continue; - break; - case CREATURE_FAMILY_WARP_STALKER: // Bite and Warp - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1952) - continue; - break; - case CREATURE_FAMILY_WASP: // Smack and Sting - if(spell->SpellIconID != 473 && spell->SpellIconID != 110) - continue; - break; - case CREATURE_FAMILY_WIND_SERPENT: // Bite and Lightning Breath - if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) - continue; - break; - case CREATURE_FAMILY_WOLF: // Bite and Furious Howl - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1573) - continue; - break; - case CREATURE_FAMILY_WORM: // Acid Spit and Bite - if(spell->SpellIconID != 636 && spell->SpellIconID != 1680) - continue; - break; - default: - sLog.outError("LoadPetLevelupSpellMap: Unhandled creature family %u", creatureFamily->ID); - continue; - } - } + SpellEntry const *spell = sSpellStore.LookupEntry(skillLine->spellId); + if(!spell) // not exist + continue; - mPetLevelupSpellMap[creatureFamily->ID][spell->spellLevel] = spell->Id; + PetLevelupSpellSet& spellSet = mPetLevelupSpellMap[creatureFamily->ID]; + if(spellSet.empty()) + ++family_count; + + spellSet.insert(PetLevelupSpellSet::value_type(spell->spellLevel,spell->Id)); count++; } } sLog.outString(); - sLog.outString( ">> Loaded %u pet levelup spells", count ); + sLog.outString( ">> Loaded %u pet levelup and default spells for %u families", count, family_count ); } /// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 8061dbee3..48ef3f744 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -559,7 +559,7 @@ typedef std::multimap SpellLearnSpellMap; typedef std::multimap SkillLineAbilityMap; -typedef std::map PetLevelupSpellSet; +typedef std::multimap PetLevelupSpellSet; typedef std::map PetLevelupSpellMap; inline bool IsPrimaryProfessionSkill(uint32 skill) diff --git a/src/game/TradeHandler.cpp b/src/game/TradeHandler.cpp index aa323c974..64408c6b5 100644 --- a/src/game/TradeHandler.cpp +++ b/src/game/TradeHandler.cpp @@ -459,30 +459,30 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) { CHECK_PACKET_SIZE(recvPacket,8); - if( GetPlayer()->pTrader ) + if (GetPlayer()->pTrader) return; uint64 ID; - if( !GetPlayer()->isAlive() ) + if (!GetPlayer()->isAlive()) { SendTradeStatus(TRADE_STATUS_YOU_DEAD); return; } - if( GetPlayer()->hasUnitState(UNIT_STAT_STUNNED) ) + if (GetPlayer()->hasUnitState(UNIT_STAT_STUNNED)) { SendTradeStatus(TRADE_STATUS_YOU_STUNNED); return; } - if( isLogingOut() ) + if (isLogingOut()) { SendTradeStatus(TRADE_STATUS_YOU_LOGOUT); return; } - if( GetPlayer()->isInFlight() ) + if (GetPlayer()->isInFlight()) { SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); return; @@ -492,55 +492,55 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket) Player* pOther = ObjectAccessor::FindPlayer( ID ); - if( !pOther ) + if (!pOther) { SendTradeStatus(TRADE_STATUS_NO_TARGET); return; } - if( pOther == GetPlayer() || pOther->pTrader ) + if (pOther == GetPlayer() || pOther->pTrader) { SendTradeStatus(TRADE_STATUS_BUSY); return; } - if( !pOther->isAlive() ) + if (!pOther->isAlive()) { SendTradeStatus(TRADE_STATUS_TARGET_DEAD); return; } - if( pOther->isInFlight() ) + if (pOther->isInFlight()) { SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); return; } - if( pOther->hasUnitState(UNIT_STAT_STUNNED) ) + if (pOther->hasUnitState(UNIT_STAT_STUNNED)) { SendTradeStatus(TRADE_STATUS_TARGET_STUNNED); return; } - if( pOther->GetSession()->isLogingOut() ) + if (pOther->GetSession()->isLogingOut()) { SendTradeStatus(TRADE_STATUS_TARGET_LOGOUT); return; } - if( pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()) ) + if (pOther->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) { SendTradeStatus(TRADE_STATUS_IGNORE_YOU); return; } - if(pOther->GetTeam() !=_player->GetTeam() ) + if (pOther->GetTeam() !=_player->GetTeam() ) { SendTradeStatus(TRADE_STATUS_WRONG_FACTION); return; } - if( pOther->GetDistance2d( _player ) > 10.0f ) + if (!pOther->IsWithinDistInMap(_player,10.0f,false)) { SendTradeStatus(TRADE_STATUS_TARGET_TO_FAR); return; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index c4433e342..687786800 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3207,7 +3207,7 @@ Spell* Unit::FindCurrentSpellBySpellId(uint32 spell_id) const return NULL; } -bool Unit::isInFront(Unit const* target, float distance, float arc) const +bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const { return IsWithinDistInMap(target, distance) && HasInArc( arc, target ); } @@ -3217,7 +3217,7 @@ void Unit::SetInFront(Unit const* target) SetOrientation(GetAngle(target)); } -bool Unit::isInBack(Unit const* target, float distance, float arc) const +bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const { return IsWithinDistInMap(target, distance) && !HasInArc( 2 * M_PI - arc, target ); } @@ -9077,9 +9077,7 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList, return true; // If there is collision rogue is seen regardless of level difference - // TODO: check sizes in DB - float distance = GetDistance(u); - if (distance < 0.24f) + if (IsWithinDist(u,0.24f)) return true; //If a mob or player is stunned he will not be able to detect stealth @@ -9090,14 +9088,14 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList, if(u->GetTypeId() != TYPEID_PLAYER) { //Always invisible from back and out of aggro range - bool isInFront = u->isInFront(this,((Creature const*)u)->GetAttackDistance(this)); + bool isInFront = u->isInFrontInMap(this,((Creature const*)u)->GetAttackDistance(this)); if(!isInFront) return false; } else { //Always invisible from back - bool isInFront = u->isInFront(this,(GetTypeId()==TYPEID_PLAYER || GetCharmerOrOwnerGUID()) ? World::GetMaxVisibleDistanceForPlayer() : World::GetMaxVisibleDistanceForCreature()); + bool isInFront = u->isInFrontInMap(this,(GetTypeId()==TYPEID_PLAYER || GetCharmerOrOwnerGUID()) ? World::GetMaxVisibleDistanceForPlayer() : World::GetMaxVisibleDistanceForCreature()); if(!isInFront) return false; } @@ -9123,7 +9121,7 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList, //based on wowwiki every 5 mod we have 1 more level diff in calculation visibleDistance += (int32(u->GetTotalAuraModifier(SPELL_AURA_MOD_DETECT)) - stealthMod)/5.0f; - if(distance > visibleDistance) + if(!IsWithinDist(u,visibleDistance)) return false; } diff --git a/src/game/Unit.h b/src/game/Unit.h index e1cfd271c..f221783cd 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1276,9 +1276,9 @@ class MANGOS_DLL_SPEC Unit : public WorldObject float GetWeaponDamageRange(WeaponAttackType attType ,WeaponDamageRange type) const; void SetBaseWeaponDamage(WeaponAttackType attType ,WeaponDamageRange damageRange, float value) { m_weaponDamage[attType][damageRange] = value; } - bool isInFront(Unit const* target,float distance, float arc = M_PI) const; + bool isInFrontInMap(Unit const* target,float distance, float arc = M_PI) const; void SetInFront(Unit const* target); - bool isInBack(Unit const* target, float distance, float arc = M_PI) const; + bool isInBackInMap(Unit const* target, float distance, float arc = M_PI) const; // Visibility system UnitVisibility GetVisibility() const { return m_Visibility; } diff --git a/src/game/World.h b/src/game/World.h index d126b32ef..0fd19e9b8 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -557,7 +557,7 @@ class World static float m_VisibleObjectGreyDistance; // CLI command holder to be thread safe - ACE_Based::LockedQueue cliCmdQueue; + ACE_Based::LockedQueue cliCmdQueue; SqlResultQueue *m_resultQueue; // next daily quests reset time @@ -568,7 +568,7 @@ class World //sessions that are added async void AddSession_(WorldSession* s); - ACE_Based::LockedQueue addSessQueue; + ACE_Based::LockedQueue addSessQueue; //used versions std::string m_DBVersion; diff --git a/src/shared/Database/Database.cpp b/src/shared/Database/Database.cpp index c8a4b20b1..84ef210db 100644 --- a/src/shared/Database/Database.cpp +++ b/src/shared/Database/Database.cpp @@ -108,7 +108,7 @@ bool Database::PExecuteLog(const char * format,...) void Database::SetResultQueue(SqlResultQueue * queue) { - m_queryQueues[ACE_Based::Thread::current()] = queue; + m_queryQueues[ACE_Based::Thread::current()] = queue; } diff --git a/src/shared/Database/DatabaseMysql.cpp b/src/shared/Database/DatabaseMysql.cpp index bb58c66b2..74efbf71b 100644 --- a/src/shared/Database/DatabaseMysql.cpp +++ b/src/shared/Database/DatabaseMysql.cpp @@ -335,7 +335,7 @@ bool DatabaseMysql::CommitTransaction() // don't use queued execution if it has not been initialized if (!m_threadBody) { - if (tranThread != ACE_Based::Thread::current()) + if (tranThread != ACE_Based::Thread::current()) return false; bool _res = _TransactionCmd("COMMIT"); tranThread = NULL; diff --git a/src/shared/Threading.cpp b/src/shared/Threading.cpp index b2c88a2c2..496e86353 100644 --- a/src/shared/Threading.cpp +++ b/src/shared/Threading.cpp @@ -44,40 +44,43 @@ ThreadPriority::ThreadPriority() ASSERT (!_tmp.empty()); - const size_t max_pos = _tmp.size(); - size_t min_pos = 1; - size_t norm_pos = 0; - for (size_t i = 0; i < max_pos; ++i) + if(_tmp.size() >= MAXPRIORITYNUM) { - if(_tmp[i] == ACE_THR_PRI_OTHER_DEF) + const size_t max_pos = _tmp.size(); + size_t min_pos = 1; + size_t norm_pos = 0; + for (size_t i = 0; i < max_pos; ++i) { - norm_pos = i + 1; - break; + if(_tmp[i] == ACE_THR_PRI_OTHER_DEF) + { + norm_pos = i + 1; + break; + } } + + //since we have only 7(seven) values in enum Priority + //and 3 we know already (Idle, Normal, Realtime) so + //we need to split each list [Idle...Normal] and [Normal...Realtime] + //into ¹ piesces + const size_t _divider = 4; + size_t _div = (norm_pos - min_pos) / _divider; + if(_div == 0) + _div = 1; + + min_pos = (norm_pos - 1); + + m_priority[Low] = _tmp[min_pos -= _div]; + m_priority[Lowest] = _tmp[min_pos -= _div ]; + + _div = (max_pos - norm_pos) / _divider; + if(_div == 0) + _div = 1; + + min_pos = norm_pos - 1; + + m_priority[High] = _tmp[min_pos += _div]; + m_priority[Highest] = _tmp[min_pos += _div]; } - - //since we have only 7(seven) values in enum Priority - //and 3 we know already (Idle, Normal, Realtime) so - //we need to split each list [Idle...Normal] and [Normal...Realtime] - //into ¹ piesces - const size_t _divider = 4; - size_t _div = (norm_pos - min_pos) / _divider; - if(_div == 0) - _div = 1; - - min_pos = (norm_pos - 1); - - m_priority[Low] = _tmp[min_pos -= _div]; - m_priority[Lowest] = _tmp[min_pos -= _div ]; - - _div = (max_pos - norm_pos) / _divider; - if(_div == 0) - _div = 1; - - min_pos = norm_pos - 1; - - m_priority[High] = _tmp[min_pos += _div]; - m_priority[Highest] = _tmp[min_pos += _div]; } int ThreadPriority::getPriority(Priority p) const diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index d40415776..13bd699da 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7814" + #define REVISION_NR "7835" #endif // __REVISION_NR_H__