HIGHLY EXPERIMENTAL - USE AT YOUR OWN RISK

implemented Condition System
all systems should work like before
after applying the sql converter you won't be able to apply any Updatepacks (<=up30) so do updates before this
this revesion is not threated as stable!

--HG--
branch : trunk
This commit is contained in:
Rat
2010-06-04 23:24:48 +02:00
parent 5ca00bc14d
commit 1426c2970f
23 changed files with 1737 additions and 758 deletions
+71
View File
@@ -0,0 +1,71 @@
-- ----------------------------
-- Table structure for conditions
-- ----------------------------
CREATE TABLE `conditions` (
`SourceTypeOrReferenceId` mediumint(8) NOT NULL DEFAULT '0',
`SourceGroup` mediumint(8) unsigned NOT NULL DEFAULT '0',
`SourceEntry` mediumint(8) unsigned NOT NULL DEFAULT '0',
`ElseGroup` mediumint(8) unsigned NOT NULL DEFAULT '0',
`ConditionTypeOrReference` mediumint(8) NOT NULL DEFAULT '0',
`ConditionValue1` mediumint(8) unsigned NOT NULL DEFAULT '0',
`ConditionValue2` mediumint(8) unsigned NOT NULL DEFAULT '0',
`ConditionValue3` mediumint(8) unsigned NOT NULL DEFAULT '0',
`ErrorTextId` mediumint(8) unsigned NOT NULL DEFAULT '0',
`Comment` varchar(255) DEFAULT NULL,
PRIMARY KEY (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Condition System';
-- convert loot conditions
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 1,creature_loot_template.entry,creature_loot_template.item,creature_loot_template.lootcondition,creature_loot_template.condition_value1,creature_loot_template.condition_value2 FROM creature_loot_template WHERE creature_loot_template.lootcondition>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 2,disenchant_loot_template.entry,disenchant_loot_template.item,disenchant_loot_template.lootcondition,disenchant_loot_template.condition_value1,disenchant_loot_template.condition_value2 FROM disenchant_loot_template WHERE disenchant_loot_template.lootcondition>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 3,fishing_loot_template.entry,fishing_loot_template.item,fishing_loot_template.lootcondition,fishing_loot_template.condition_value1,fishing_loot_template.condition_value2 FROM fishing_loot_template WHERE fishing_loot_template.lootcondition>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 4,gameobject_loot_template.entry,gameobject_loot_template.item,gameobject_loot_template.lootcondition,gameobject_loot_template.condition_value1,gameobject_loot_template.condition_value2 FROM gameobject_loot_template WHERE gameobject_loot_template.lootcondition>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 5,item_loot_template.entry,item_loot_template.item,item_loot_template.lootcondition,item_loot_template.condition_value1,item_loot_template.condition_value2 FROM item_loot_template WHERE item_loot_template.lootcondition>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 6,mail_loot_template.entry,mail_loot_template.item,mail_loot_template.lootcondition,mail_loot_template.condition_value1,mail_loot_template.condition_value2 FROM mail_loot_template WHERE mail_loot_template.lootcondition>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 7,milling_loot_template.entry,milling_loot_template.item,milling_loot_template.lootcondition,milling_loot_template.condition_value1,milling_loot_template.condition_value2 FROM milling_loot_template WHERE milling_loot_template.lootcondition>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 8,pickpocketing_loot_template.entry,pickpocketing_loot_template.item,pickpocketing_loot_template.lootcondition,pickpocketing_loot_template.condition_value1,pickpocketing_loot_template.condition_value2 FROM pickpocketing_loot_template WHERE pickpocketing_loot_template.lootcondition>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 9,prospecting_loot_template.entry,prospecting_loot_template.item,prospecting_loot_template.lootcondition,prospecting_loot_template.condition_value1,prospecting_loot_template.condition_value2 FROM prospecting_loot_template WHERE prospecting_loot_template.lootcondition>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 10,reference_loot_template.entry,reference_loot_template.item,reference_loot_template.lootcondition,reference_loot_template.condition_value1,reference_loot_template.condition_value2 FROM reference_loot_template WHERE reference_loot_template.lootcondition>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 11,skinning_loot_template.entry,skinning_loot_template.item,skinning_loot_template.lootcondition,skinning_loot_template.condition_value1,skinning_loot_template.condition_value2 FROM skinning_loot_template WHERE skinning_loot_template.lootcondition>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 12,spell_loot_template.entry,spell_loot_template.item,spell_loot_template.lootcondition,spell_loot_template.condition_value1,spell_loot_template.condition_value2 FROM spell_loot_template WHERE spell_loot_template.lootcondition>0;
-- convert spell script targets
INSERT INTO conditions (SourceTypeOrReferenceId,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 13,spell_script_target.entry,18,spell_script_target.type,spell_script_target.targetEntry FROM spell_script_target;
-- convert gossip menu conditions
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 14,gossip_menu.entry,gossip_menu.text_id,gossip_menu.cond_1,gossip_menu.cond_1_val_1,gossip_menu.cond_1_val_2 FROM gossip_menu WHERE gossip_menu.cond_1>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 14,gossip_menu.entry,gossip_menu.text_id,gossip_menu.cond_2,gossip_menu.cond_2_val_1,gossip_menu.cond_2_val_2 FROM gossip_menu WHERE gossip_menu.cond_2>0;
-- convert gossip menu options conditions
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 15,gossip_menu_option.menu_id,gossip_menu_option.id,gossip_menu_option.cond_1,gossip_menu_option.cond_1_val_1,gossip_menu_option.cond_1_val_2 FROM gossip_menu_option WHERE gossip_menu_option.cond_1>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 15,gossip_menu_option.menu_id,gossip_menu_option.id,gossip_menu_option.cond_2,gossip_menu_option.cond_2_val_1,gossip_menu_option.cond_2_val_2 FROM gossip_menu_option WHERE gossip_menu_option.cond_2>0;
INSERT INTO conditions (SourceTypeOrReferenceId,SourceGroup,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 15,gossip_menu_option.menu_id,gossip_menu_option.id,gossip_menu_option.cond_3,gossip_menu_option.cond_3_val_1,gossip_menu_option.cond_3_val_2 FROM gossip_menu_option WHERE gossip_menu_option.cond_3>0;
-- convert item required target
INSERT INTO conditions (SourceTypeOrReferenceId,SourceEntry,ConditionTypeOrReference,ConditionValue1,ConditionValue2) SELECT 18,item_required_target.entry,24,item_required_target.type,item_required_target.targetEntry FROM item_required_target;
-- drop no more needed condition fields
-- drop not used loot conditions
ALTER TABLE creature_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
ALTER TABLE disenchant_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
ALTER TABLE fishing_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
ALTER TABLE gameobject_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
ALTER TABLE item_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
ALTER TABLE mail_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
ALTER TABLE milling_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
ALTER TABLE pickpocketing_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
ALTER TABLE prospecting_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
ALTER TABLE reference_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
ALTER TABLE skinning_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
ALTER TABLE spell_loot_template DROP COLUMN lootcondition,DROP COLUMN condition_value1,DROP COLUMN condition_value2;
-- drop spell_script_target table, it is built into conditions
DROP TABLE IF EXISTS `spell_script_target`;
-- drop item_required_target table, it is built into conditions
DROP TABLE IF EXISTS `item_required_target`;
-- drop not used gossip conditions
ALTER TABLE gossip_menu DROP COLUMN cond_1,DROP COLUMN cond_1_val_1,DROP COLUMN cond_1_val_2,DROP COLUMN cond_2,DROP COLUMN cond_2_val_1,DROP COLUMN cond_2_val_2;
ALTER TABLE gossip_menu_option DROP COLUMN cond_1,DROP COLUMN cond_1_val_1,DROP COLUMN cond_1_val_2,DROP COLUMN cond_2,DROP COLUMN cond_2_val_1,DROP COLUMN cond_2_val_2;
+2
View File
@@ -70,6 +70,8 @@ SET(game_STAT_SRCS
Chat.h
ChatHandler.cpp
CombatHandler.cpp
ConditionMgr.cpp
ConditionMgr.h
ConfusedMovementGenerator.cpp
ConfusedMovementGenerator.h
Corpse.cpp
+1 -2
View File
@@ -451,6 +451,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "areatrigger_teleport", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAreaTriggerTeleportCommand, "", NULL },
{ "autobroadcast", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadAutobroadcastCommand, "", NULL },
{ "command", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCommandCommand, "", NULL },
{ "conditions", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadConditions, "", NULL },
{ "creature_ai_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAIScriptsCommand, "", NULL },
{ "creature_ai_summons", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAISummonsCommand, "", NULL },
{ "creature_ai_texts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadEventAITextsCommand, "", NULL },
@@ -473,7 +474,6 @@ ChatCommand * ChatHandler::getCommandTable()
{ "gossip_menu_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadGossipMenuOptionCommand, "", NULL },
{ "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL },
{ "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL },
{ "item_required_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemRequiredTragetCommand, "", NULL },
{ "locales_achievement_reward", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesAchievementRewardCommand,"", NULL },
{ "locales_creature", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesCreatureCommand, "", NULL },
{ "locales_gameobject", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesGameobjectCommand, "", NULL },
@@ -512,7 +512,6 @@ ChatCommand * ChatHandler::getCommandTable()
{ "spell_linked_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLinkedSpellCommand, "", NULL },
{ "spell_pet_auras", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL },
{ "spell_proc_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL },
{ "spell_script_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptTargetCommand, "", NULL },
{ "spell_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptsCommand, "", NULL },
{ "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL },
{ "spell_threats", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellThreatsCommand, "", NULL },
+1 -2
View File
@@ -374,7 +374,6 @@ class ChatHandler
bool HandleReloadGOQuestRelationsCommand(const char* args);
bool HandleReloadGOQuestInvRelationsCommand(const char* args);
bool HandleReloadItemEnchantementsCommand(const char* args);
bool HandleReloadItemRequiredTragetCommand(const char* args);
bool HandleReloadLocalesAchievementRewardCommand(const char* args);
bool HandleReloadLocalesCreatureCommand(const char* args);
bool HandleReloadLocalesGameobjectCommand(const char* args);
@@ -419,7 +418,6 @@ class ChatHandler
bool HandleReloadSpellLinkedSpellCommand(const char* args);
bool HandleReloadSpellProcEventCommand(const char* args);
bool HandleReloadSpellBonusesCommand(const char* args);
bool HandleReloadSpellScriptTargetCommand(const char* args);
bool HandleReloadSpellScriptsCommand(const char* args);
bool HandleReloadSpellTargetPositionCommand(const char* args);
bool HandleReloadSpellThreatsCommand(const char* args);
@@ -428,6 +426,7 @@ class ChatHandler
bool HandleReloadSpellGroupStackRulesCommand(const char* args);
bool HandleReloadAuctionsCommand(const char* args);
bool HandleReloadWpScriptsCommand(const char* args);
bool HandleReloadConditions(const char* args);
bool HandleResetAchievementsCommand(const char * args);
bool HandleResetAllCommand(const char * args);
+64 -2
View File
@@ -292,17 +292,79 @@ void AOEAI::UpdateAI(const uint32 /*diff*/)
//VehicleAI
//////////////
//NOTE: VehicleAI::UpdateAI runs even while the vehicle is mounted
void VehicleAI::UpdateAI(const uint32 /*diff*/)
VehicleAI::VehicleAI(Creature *c) : CreatureAI(c), m_vehicle(c->GetVehicleKit()), m_IsVehicleInUse(false), m_ConditionsTimer(VEHICLE_CONDITION_CHECK_TIME)
{
LoadConditions();
m_DoDismiss = false;
m_DismissTimer = VEHICLE_DISMISS_TIME;
}
//NOTE: VehicleAI::UpdateAI runs even while the vehicle is mounted
void VehicleAI::UpdateAI(const uint32 diff)
{
CheckConditions(diff);
if (m_DoDismiss)
{
if (m_DismissTimer < diff)
{
m_DoDismiss = false;
me->SetVisibility(VISIBILITY_OFF);
me->ForcedDespawn();
}else m_DismissTimer -= diff;
}
}
void VehicleAI::Reset()
{
me->SetVisibility(VISIBILITY_ON);
m_vehicle->Reset();
}
void VehicleAI::OnCharmed(bool apply)
{
if (m_IsVehicleInUse && !apply && !conditions.empty())//was used and has conditions
{
m_DoDismiss = true;//needs reset
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_PLAYER_VEHICLE);
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
}
else if (apply)
m_DoDismiss = false;//in use again
m_DismissTimer = VEHICLE_DISMISS_TIME;//reset timer
m_IsVehicleInUse = apply;
}
void VehicleAI::LoadConditions()
{
conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE, me->GetEntry());
if (!conditions.empty())
{
sLog.outDebug("VehicleAI::LoadConditions: loaded %u conditions", uint32(conditions.size()));
}
}
void VehicleAI::CheckConditions(const uint32 diff)
{
if(m_ConditionsTimer < diff)
{
if (!conditions.empty())
{
for (SeatMap::iterator itr = m_vehicle->m_Seats.begin(); itr != m_vehicle->m_Seats.end(); ++itr)
if (Unit *passenger = itr->second.passenger)
{
if (Player* plr = passenger->ToPlayer())
{
if (!sConditionMgr.IsPlayerMeetToConditions(plr, conditions))
{
plr->ExitVehicle();
return;//check other pessanger in next tick
}
}
}
}
m_ConditionsTimer = VEHICLE_CONDITION_CHECK_TIME;
} else m_ConditionsTimer -= diff;
}
+10 -2
View File
@@ -23,6 +23,7 @@
#include "CreatureAI.h"
#include "CreatureAIImpl.h"
#include "ConditionMgr.h"
class Creature;
@@ -100,11 +101,12 @@ struct AOEAI : public CreatureAI
static int Permissible(const Creature *);
};
#define VEHICLE_RESET_TIME 5000
#define VEHICLE_CONDITION_CHECK_TIME 1000
#define VEHICLE_DISMISS_TIME 5000
struct VehicleAI : public CreatureAI
{
public:
explicit VehicleAI(Creature *c) : CreatureAI(c), m_vehicle(c->GetVehicleKit()), m_IsVehicleInUse(false) {}
explicit VehicleAI(Creature *c);
void UpdateAI(const uint32 diff);
static int Permissible(const Creature *);
@@ -116,6 +118,12 @@ struct VehicleAI : public CreatureAI
private:
Vehicle* m_vehicle;
bool m_IsVehicleInUse;
void LoadConditions();
void CheckConditions(const uint32 diff);
ConditionList conditions;
uint32 m_ConditionsTimer;
bool m_DoDismiss;
uint32 m_DismissTimer;
};
#endif
File diff suppressed because it is too large Load Diff
+167
View File
@@ -0,0 +1,167 @@
/*
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef TRINITY_CONDITIONMGR_H
#define TRINITY_CONDITIONMGR_H
#include "LootMgr.h"
class Player;
class Unit;
class LootTemplate;
enum ConditionType
{ // value1 value2 value3
CONDITION_NONE = 0, // 0 0 0 always true
CONDITION_AURA = 1, // spell_id effindex +referenceID true if has aura of spell_id with effect effindex
CONDITION_ITEM = 2, // item_id count +referenceID true if has #count of item_ids
CONDITION_ITEM_EQUIPPED = 3, // item_id 0 +referenceID true if has item_id equipped
CONDITION_ZONEID = 4, // zone_id 0 +referenceID true if in zone_id
CONDITION_REPUTATION_RANK = 5, // faction_id min_rank +referenceID true if has min_rank for faction_id
CONDITION_TEAM = 6, // player_team 0, +referenceID 469 - Alliance, 67 - Horde)
CONDITION_SKILL = 7, // skill_id skill_value +referenceID true if has skill_value for skill_id
CONDITION_QUESTREWARDED = 8, // quest_id 0 +referenceID true if quest_id was rewarded before
CONDITION_QUESTTAKEN = 9, // quest_id 0, +referenceID true while quest active
CONDITION_AD_COMMISSION_AURA = 10, // 0 0, +referenceID true while one from AD commission aura active
CONDITION_NO_AURA = 11, // spell_id effindex +referenceID true if does not have aura of spell_id with effect effindex
CONDITION_ACTIVE_EVENT = 12, // event_id 0 +referenceID true if event is active
CONDITION_INSTANCE_DATA = 13, // entry data +referenceID true if data is set in current instance
CONDITION_QUEST_NONE = 14, // quest_id 0 +referenceID true if doesn't have quest saved
CONDITION_CLASS = 15, // class 0 +referenceID true if player's class is equal to class
CONDITION_RACE = 16, // race 0 +referenceID true if player's race is equal to race
CONDITION_ACHIEVEMENT = 17, // achievement_id 0 +referenceID true if achievement is complete
CONDITION_SPELL_SCRIPT_TARGET = 18, // SpellScriptTargetType, TargetEntry, 0
CONDITION_CREATURE_TARGET = 19, // creature entry 0 +referenceID true if current target is creature with value1 entry
CONDITION_TARGET_HEALTH_BELOW_PCT = 20, // 0-100 0 +referenceID true if target's health is below value1 percent, false if over or no target
CONDITION_TARGET_RANGE = 21, // minDistance maxDist +referenceID true if target is closer then minDist and further then maxDist or if max is 0 then max dist is infinit
CONDITION_MAPID = 22, // map_id 0 +referenceID true if in map_id
CONDITION_AREAID = 23, // area_id 0 +referenceID true if in area_id
CONDITION_ITEM_TARGET = 24 // ItemRequiredTargetType, TargetEntry, 0
};
#define MAX_CONDITION 25 // maximum value in ConditionType enum
enum ConditionSourceType
{
CONDITION_SOURCE_TYPE_NONE = 0,//DONE
CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE = 1,//DONE
CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE = 2,//DONE
CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE = 3,//DONE
CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE = 4,//DONE
CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE = 5,//DONE
CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE = 6,//DONE
CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE = 7,//DONE
CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE = 8,//DONE
CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE = 9,//DONE
CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE = 10,//DONE
CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE = 11,//DONE
CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE = 12,//DONE
CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET = 13,//DONE
CONDITION_SOURCE_TYPE_GOSSIP_MENU = 14,//DONE
CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION = 15,//DONE
CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE = 16,//DONE
CONDITION_SOURCE_TYPE_SPELL = 17,//DONE
CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET = 18//DONE
};
#define MAX_CONDITIONSOURCETYPE 19
struct Condition
{
ConditionSourceType mSourceType; //SourceTypeOrReferenceId
uint32 mSourceGroup;
uint32 mSourceEntry;
uint32 mElseGroup;
ConditionType mConditionType; //ConditionTypeOrReference
uint32 mConditionValue1;
uint32 mConditionValue2;
uint32 mConditionValue3;
uint32 ErrorTextd;
uint32 mReferenceId;
Condition()
{
mSourceType = CONDITION_SOURCE_TYPE_NONE;
mSourceGroup = 0;
mSourceEntry = 0;
mElseGroup = 0;
mConditionType = CONDITION_NONE;
mConditionValue1 = 0;
mConditionValue2 = 0;
mConditionValue3 = 0;
mReferenceId = 0;
ErrorTextd = 0;
}
bool Meets(Player * player, Unit* targetOverride = NULL);
bool isLoaded() { return mConditionType > CONDITION_SOURCE_TYPE_NONE || mReferenceId; }
};
typedef std::list<Condition*> ConditionList;
typedef std::map<uint32, ConditionList > ConditionTypeMap;
typedef std::map<ConditionSourceType, ConditionTypeMap > ConditionMap;//used for all conditions, except references
typedef std::map<uint32, ConditionList > ConditionReferenceMap;//only used for references
class ConditionMgr
{
public:
ConditionMgr();
~ConditionMgr();
void LoadConditions(bool isReload = false);
bool isConditionTypeValid(Condition* cond);
ConditionList GetConditionReferences(uint32 refId);
bool IsPlayerMeetToConditions(Player* player, ConditionList conditions, Unit* targetOverride = NULL);
ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sType, uint32 uEntry);
protected:
ConditionMap m_ConditionMap;
ConditionReferenceMap m_ConditionReferenceMap;
private:
bool isSourceTypeValid(Condition* cond);
bool addToLootTemplate(Condition* cond, LootTemplate* loot);
bool addToGossipMenus(Condition* cond);
bool addToGossipMenuItems(Condition* cond);
bool IsPlayerMeetToConditionList(Player* player,const ConditionList& conditions, Unit* targetOverride = NULL);
bool isGroupable(ConditionSourceType sourceType)
{
return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE ||
sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU ||
sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION);
}
};
#define sConditionMgr Trinity::Singleton<ConditionMgr>::Instance()
#endif
+7 -2
View File
@@ -32,6 +32,7 @@
#include "InstanceData.h"
#include "SpellMgr.h"
#include "CreatureAIImpl.h"
#include "ConditionMgr.h"
bool CreatureEventAIHolder::UpdateRepeatTimer(Creature* creature, uint32 repeatMin, uint32 repeatMax)
{
@@ -1330,8 +1331,12 @@ void CreatureEventAI::ReceiveEmote(Player* pPlayer, uint32 text_emote)
if ((*itr).Event.receive_emote.emoteId != text_emote)
return;
PlayerCondition pcon((*itr).Event.receive_emote.condition,(*itr).Event.receive_emote.conditionValue1,(*itr).Event.receive_emote.conditionValue2);
if (pcon.Meets(pPlayer))
Condition* cond = new Condition();
cond->mConditionType = ConditionType((*itr).Event.receive_emote.condition);
cond->mConditionValue1 = (*itr).Event.receive_emote.conditionValue1;
cond->mConditionValue2 = (*itr).Event.receive_emote.conditionValue2;
if (cond->Meets(pPlayer))
{
sLog.outDebug("CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing");
ProcessEvent(*itr, pPlayer);
+11 -4
View File
@@ -26,6 +26,7 @@
#include "Policies/SingletonImp.h"
#include "ObjectDefines.h"
#include "GridDefines.h"
#include "ConditionMgr.h"
INSTANTIATE_SINGLETON_1(CreatureEventAIMgr);
@@ -359,11 +360,17 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: param1 (EmoteTextId: %u) are not valid.",temp.creature_id, i, temp.receive_emote.emoteId);
continue;
}
if (!PlayerCondition::IsValid(ConditionType(temp.receive_emote.condition), temp.receive_emote.conditionValue1, temp.receive_emote.conditionValue2))
if (temp.receive_emote.condition)
{
sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not valid.",temp.creature_id, i, temp.receive_emote.condition);
continue;
Condition* cond = new Condition();
cond->mConditionType = ConditionType(temp.receive_emote.condition);
cond->mConditionValue1 = temp.receive_emote.conditionValue1;
cond->mConditionValue2 = temp.receive_emote.conditionValue2;
if (!sConditionMgr.isConditionTypeValid(cond))
{
sLog.outErrorDb("CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not valid.",temp.creature_id, i, temp.receive_emote.condition);
continue;
}
}
if (!(temp.event_flags & EFLAG_REPEATABLE))
+8 -6
View File
@@ -26,6 +26,7 @@
#include "ItemEnchantmentMgr.h"
#include "SpellMgr.h"
#include "ScriptMgr.h"
#include "ConditionMgr.h"
void AddItemsSetItem(Player*player,Item *item)
{
@@ -824,18 +825,19 @@ bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) const
bool Item::IsTargetValidForItemUse(Unit* pUnitTarget)
{
ItemRequiredTargetMapBounds bounds = objmgr.GetItemRequiredTargetMapBounds(GetProto()->ItemId);
if (bounds.first == bounds.second)
ConditionList conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET, GetProto()->ItemId);
if (conditions.empty())
return true;
if (!pUnitTarget)
return false;
for (ItemRequiredTargetMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
if (itr->second.IsFitToRequirements(pUnitTarget))
for (ConditionList::const_iterator itr = conditions.begin(); itr != conditions.end(); ++itr)
{
ItemRequiredTarget *irt = new ItemRequiredTarget((ItemRequiredTargetType)(*itr)->mConditionValue1, (*itr)->mConditionValue2);
if (irt->IsFitToRequirements(pUnitTarget))
return true;
}
return false;
}
+40 -18
View File
@@ -55,6 +55,7 @@
#include "CreatureEventAIMgr.h"
#include "SpellAuraEffects.h"
#include "DBCEnums.h"
#include "ConditionMgr.h"
bool ChatHandler::HandleAHBotOptionsCommand(const char *args)
{
@@ -591,6 +592,7 @@ bool ChatHandler::HandleReloadAllLootCommand(const char*)
sLog.outString("Re-Loading Loot Tables...");
LoadLootTables();
SendGlobalGMSysMessage("DB tables `*_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -655,7 +657,6 @@ bool ChatHandler::HandleReloadAllSpellCommand(const char*)
HandleReloadSpellLinkedSpellCommand("a");
HandleReloadSpellProcEventCommand("a");
HandleReloadSpellBonusesCommand("a");
HandleReloadSpellScriptTargetCommand("a");
HandleReloadSpellTargetPositionCommand("a");
HandleReloadSpellThreatsCommand("a");
HandleReloadSpellGroupStackRulesCommand("a");
@@ -668,7 +669,6 @@ bool ChatHandler::HandleReloadAllItemCommand(const char*)
{
HandleReloadPageTextsCommand("a");
HandleReloadItemEnchantementsCommand("a");
HandleReloadItemRequiredTragetCommand("a");
return true;
}
@@ -923,6 +923,7 @@ bool ChatHandler::HandleReloadGossipMenuCommand(const char*)
sLog.outString("Re-Loading `gossip_menu` Table!");
objmgr.LoadGossipMenu();
SendGlobalGMSysMessage("DB table `gossip_menu` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -931,6 +932,7 @@ bool ChatHandler::HandleReloadGossipMenuOptionCommand(const char*)
sLog.outString("Re-Loading `gossip_menu_option` Table!");
objmgr.LoadGossipMenuItems();
SendGlobalGMSysMessage("DB table `gossip_menu_option` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -977,6 +979,7 @@ bool ChatHandler::HandleReloadLootTemplatesCreatureCommand(const char*)
LoadLootTemplates_Creature();
LootTemplates_Creature.CheckLootRefs();
SendGlobalGMSysMessage("DB table `creature_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -986,6 +989,7 @@ bool ChatHandler::HandleReloadLootTemplatesDisenchantCommand(const char*)
LoadLootTemplates_Disenchant();
LootTemplates_Disenchant.CheckLootRefs();
SendGlobalGMSysMessage("DB table `disenchant_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -995,6 +999,7 @@ bool ChatHandler::HandleReloadLootTemplatesFishingCommand(const char*)
LoadLootTemplates_Fishing();
LootTemplates_Fishing.CheckLootRefs();
SendGlobalGMSysMessage("DB table `fishing_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -1004,6 +1009,7 @@ bool ChatHandler::HandleReloadLootTemplatesGameobjectCommand(const char*)
LoadLootTemplates_Gameobject();
LootTemplates_Gameobject.CheckLootRefs();
SendGlobalGMSysMessage("DB table `gameobject_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -1013,6 +1019,7 @@ bool ChatHandler::HandleReloadLootTemplatesItemCommand(const char*)
LoadLootTemplates_Item();
LootTemplates_Item.CheckLootRefs();
SendGlobalGMSysMessage("DB table `item_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -1022,6 +1029,7 @@ bool ChatHandler::HandleReloadLootTemplatesMillingCommand(const char*)
LoadLootTemplates_Milling();
LootTemplates_Milling.CheckLootRefs();
SendGlobalGMSysMessage("DB table `milling_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -1031,6 +1039,7 @@ bool ChatHandler::HandleReloadLootTemplatesPickpocketingCommand(const char*)
LoadLootTemplates_Pickpocketing();
LootTemplates_Pickpocketing.CheckLootRefs();
SendGlobalGMSysMessage("DB table `pickpocketing_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -1040,6 +1049,7 @@ bool ChatHandler::HandleReloadLootTemplatesProspectingCommand(const char*)
LoadLootTemplates_Prospecting();
LootTemplates_Prospecting.CheckLootRefs();
SendGlobalGMSysMessage("DB table `prospecting_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -1049,6 +1059,7 @@ bool ChatHandler::HandleReloadLootTemplatesMailCommand(const char*)
LoadLootTemplates_Mail();
LootTemplates_Mail.CheckLootRefs();
SendGlobalGMSysMessage("DB table `mail_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -1057,6 +1068,7 @@ bool ChatHandler::HandleReloadLootTemplatesReferenceCommand(const char*)
sLog.outString("Re-Loading Loot Tables... (`reference_loot_template`)");
LoadLootTemplates_Reference();
SendGlobalGMSysMessage("DB table `reference_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -1066,6 +1078,7 @@ bool ChatHandler::HandleReloadLootTemplatesSkinningCommand(const char*)
LoadLootTemplates_Skinning();
LootTemplates_Skinning.CheckLootRefs();
SendGlobalGMSysMessage("DB table `skinning_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -1075,6 +1088,7 @@ bool ChatHandler::HandleReloadLootTemplatesSpellCommand(const char*)
LoadLootTemplates_Spell();
LootTemplates_Spell.CheckLootRefs();
SendGlobalGMSysMessage("DB table `spell_loot_template` reloaded.");
sConditionMgr.LoadConditions(true);
return true;
}
@@ -1214,14 +1228,6 @@ bool ChatHandler::HandleReloadSpellBonusesCommand(const char*)
return true;
}
bool ChatHandler::HandleReloadSpellScriptTargetCommand(const char*)
{
sLog.outString("Re-Loading SpellsScriptTarget...");
spellmgr.LoadSpellScriptTarget();
SendGlobalGMSysMessage("DB table `spell_script_target` (spell targets selection in case specific creature/GO requirements) reloaded.");
return true;
}
bool ChatHandler::HandleReloadSpellTargetPositionCommand(const char*)
{
sLog.outString("Re-Loading Spell target coordinates...");
@@ -1270,14 +1276,6 @@ bool ChatHandler::HandleReloadItemEnchantementsCommand(const char*)
return true;
}
bool ChatHandler::HandleReloadItemRequiredTragetCommand(const char*)
{
sLog.outString("Re-Loading Item Required Targets Table...");
objmgr.LoadItemRequiredTarget();
SendGlobalGMSysMessage("DB table `item_required_target` reloaded.");
return true;
}
bool ChatHandler::HandleReloadGameObjectScriptsCommand(const char* arg)
{
if (sWorld.IsScriptScheduled())
@@ -1546,6 +1544,14 @@ bool ChatHandler::HandleReloadAuctionsCommand(const char * /*args*/)
return true;
}
bool ChatHandler::HandleReloadConditions(const char* args)
{
sLog.outString("Re-Loading Conditions...");
sConditionMgr.LoadConditions(true);
SendGlobalGMSysMessage("Conditions reloaded.");
return true;
}
bool ChatHandler::HandleAccountSetGmLevelCommand(const char *args)
{
if (!*args)
@@ -6687,7 +6693,11 @@ bool ChatHandler::HandleCastCommand(const char *args)
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
if (!spellInfo)
{
PSendSysMessage(LANG_COMMAND_NOSPELLFOUND);
SetSentErrorMessage(true);
return false;
}
if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer()))
{
@@ -6726,7 +6736,11 @@ bool ChatHandler::HandleCastBackCommand(const char *args)
// number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form
uint32 spell = extractSpellIdFromLink((char*)args);
if (!spell || !sSpellStore.LookupEntry(spell))
{
PSendSysMessage(LANG_COMMAND_NOSPELLFOUND);
SetSentErrorMessage(true);
return false;
}
char* trig_str = strtok(NULL, " ");
if (trig_str)
@@ -6757,7 +6771,11 @@ bool ChatHandler::HandleCastDistCommand(const char *args)
SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
if (!spellInfo)
{
PSendSysMessage(LANG_COMMAND_NOSPELLFOUND);
SetSentErrorMessage(true);
return false;
}
if (!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer()))
{
@@ -6811,7 +6829,11 @@ bool ChatHandler::HandleCastTargetCommand(const char *args)
// number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form
uint32 spell = extractSpellIdFromLink((char*)args);
if (!spell || !sSpellStore.LookupEntry(spell))
{
PSendSysMessage(LANG_COMMAND_NOSPELLFOUND);
SetSentErrorMessage(true);
return false;
}
char* trig_str = strtok(NULL, " ");
if (trig_str)
+122 -28
View File
@@ -64,6 +64,9 @@ class LootTemplate::LootGroup // A set of loot def
void Verify(LootStore const& lootstore, uint32 id, uint8 group_id) const;
void CollectLootIds(LootIdSet& set) const;
void CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const;
LootStoreItemList * GetExplicitlyChancedItemList() { return &ExplicitlyChanced; }
LootStoreItemList * GetEqualChancedItemList() { return &EqualChanced; }
void CopyConditions(ConditionList conditions);
private:
LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB
LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance
@@ -99,8 +102,8 @@ void LootStore::LoadLootTable()
sLog.outString("%s :", GetName());
// 0 1 2 3 4 5 6 7 8 9
QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT entry, item, ChanceOrQuestChance, lootmode, groupid, mincountOrRef, maxcount, lootcondition, condition_value1, condition_value2 FROM %s",GetName());
// 0 1 2 3 4 5 6
QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT entry, item, ChanceOrQuestChance, lootmode, groupid, mincountOrRef, maxcount FROM %s",GetName());
if (result)
{
@@ -118,9 +121,6 @@ void LootStore::LoadLootTable()
uint8 group = fields[4].GetUInt8();
int32 mincountOrRef = fields[5].GetInt32();
int32 maxcount = fields[6].GetInt32();
ConditionType condition = (ConditionType)fields[7].GetUInt8();
uint32 cond_value1 = fields[8].GetUInt32();
uint32 cond_value2 = fields[9].GetUInt32();
if (maxcount > std::numeric_limits<uint8>::max())
{
@@ -128,16 +128,7 @@ void LootStore::LoadLootTable()
continue; // error already printed to log/console.
}
if (!PlayerCondition::IsValid(condition,cond_value1, cond_value2))
{
sLog.outErrorDb("... in table '%s' entry %u item %u", GetName(), entry, item);
continue; // error already printed to log/console.
}
// (condition + cond_value1/2) are converted into single conditionId
uint16 conditionId = objmgr.GetConditionId(condition, cond_value1, cond_value2);
LootStoreItem storeitem = LootStoreItem(item, chanceOrQuestChance, lootmode, group, conditionId, mincountOrRef, maxcount);
LootStoreItem storeitem = LootStoreItem(item, chanceOrQuestChance, lootmode, group, mincountOrRef, maxcount);
if (!storeitem.IsValid(*this,entry)) // Validity checks
continue;
@@ -195,6 +186,16 @@ bool LootStore::HaveQuestLootForPlayer(uint32 loot_id,Player* player) const
return false;
}
void LootStore::ResetConditions()
{
LootTemplateMap m_LootTemplates;
for (LootTemplateMap::iterator itr = m_LootTemplates.begin(); itr != m_LootTemplates.end(); ++itr)
{
ConditionList empty;
(*itr).second->CopyConditions(empty);
}
}
LootTemplate const* LootStore::GetLootFor(uint32 loot_id) const
{
LootTemplateMap::const_iterator tab = m_LootTemplates.find(loot_id);
@@ -205,6 +206,16 @@ LootTemplate const* LootStore::GetLootFor(uint32 loot_id) const
return tab->second;
}
LootTemplate* LootStore::GetLootForConditionFill(uint32 loot_id)
{
LootTemplateMap::iterator tab = m_LootTemplates.find(loot_id);
if (tab == m_LootTemplates.end())
return NULL;
return tab->second;
}
void LootStore::LoadAndCollectLootIds(LootIdSet& ids_set)
{
LoadLootTable();
@@ -316,9 +327,9 @@ bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const
// Constructor, copies most fields from LootStoreItem and generates random count
LootItem::LootItem(LootStoreItem const& li)
{
itemid = li.itemid;
conditionId = li.conditionId;
itemid = li.itemid;
conditions = li.conditions;
ItemPrototype const* proto = objmgr.GetItemPrototype(itemid);
freeforall = proto && (proto->Flags & ITEM_FLAGS_PARTY_LOOT);
@@ -336,8 +347,8 @@ LootItem::LootItem(LootStoreItem const& li)
// Basic checks for player/item compatibility - if false no chance to see the item in the loot
bool LootItem::AllowedForPlayer(Player const * player) const
{
// DB conditions check
if (!objmgr.IsPlayerMeetToCondition(player,conditionId))
// DB conditions check
if (!sConditionMgr.IsPlayerMeetToConditions(const_cast<Player*>(player), conditions))
return false;
if (needs_quest)
@@ -368,7 +379,7 @@ void Loot::AddItem(LootStoreItem const & item)
{
if (quest_items.size() < MAX_NR_QUEST_ITEMS)
quest_items.push_back(LootItem(item));
}
}
else if (items.size() < MAX_NR_LOOT_ITEMS) // Non-quest drop
{
items.push_back(LootItem(item));
@@ -376,7 +387,7 @@ void Loot::AddItem(LootStoreItem const & item)
// non-conditional one-player only items are counted here,
// free for all items are counted in FillFFALoot(),
// non-ffa conditionals are counted in FillNonQuestNonFFAConditionalLoot()
if (!item.conditionId)
if (item.conditions.empty())
{
ItemPrototype const* proto = objmgr.GetItemPrototype(item.itemid);
if (!proto || (proto->Flags & ITEM_FLAGS_PARTY_LOOT) == 0)
@@ -512,7 +523,7 @@ QuestItemList* Loot::FillNonQuestNonFFAConditionalLoot(Player* player)
for (uint8 i = 0; i < items.size(); ++i)
{
LootItem &item = items[i];
if (!item.is_looted && !item.freeforall && item.conditionId && item.AllowedForPlayer(player))
if (!item.is_looted && !item.freeforall && !item.conditions.empty() && item.AllowedForPlayer(player))
{
ql->push_back(QuestItem(i));
if (!item.is_counted)
@@ -649,7 +660,7 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem **qite
}
}
}
else if (item->conditionId)
else if (!item->conditions.empty())
{
QuestItemMap::const_iterator itr = PlayerNonQuestNonFFAConditionalItems.find(player->GetGUIDLow());
if (itr != PlayerNonQuestNonFFAConditionalItems.end())
@@ -776,7 +787,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
// blocked rolled items and quest items, and !ffa items
for (uint8 i = 0; i < l.items.size(); ++i)
{
if (!l.items[i].is_looted && !l.items[i].freeforall && !l.items[i].conditionId && l.items[i].AllowedForPlayer(lv.viewer))
if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer))
{
uint8 slot_type;
@@ -804,7 +815,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
{
for (uint8 i = 0; i < l.items.size(); ++i)
{
if (!l.items[i].is_looted && !l.items[i].freeforall && !l.items[i].conditionId && l.items[i].AllowedForPlayer(lv.viewer))
if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer))
{
if (l.roundRobinPlayer != 0 && lv.viewer->GetGUID() != l.roundRobinPlayer)
// item shall not be displayed.
@@ -823,7 +834,7 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv)
uint8 slot_type = (lv.permission == MASTER_PERMISSION) ? LOOT_SLOT_TYPE_MASTER : LOOT_SLOT_TYPE_ALLOW_LOOT;
for (uint8 i = 0; i < l.items.size(); ++i)
{
if (!l.items[i].is_looted && !l.items[i].freeforall && !l.items[i].conditionId && l.items[i].AllowedForPlayer(lv.viewer))
if (!l.items[i].is_looted && !l.items[i].freeforall && l.items[i].conditions.empty() && l.items[i].AllowedForPlayer(lv.viewer))
{
b << uint8(i) << l.items[i];
b << uint8(slot_type);
@@ -954,6 +965,18 @@ bool LootTemplate::LootGroup::HasQuestDropForPlayer(Player const * player) const
return false;
}
void LootTemplate::LootGroup::CopyConditions(ConditionList conditions)
{
for (LootStoreItemList::iterator i = ExplicitlyChanced.begin(); i != ExplicitlyChanced.end(); ++i)
{
i->conditions = conditions;
}
for (LootStoreItemList::iterator i = EqualChanced.begin(); i != EqualChanced.end(); ++i)
{
i->conditions = conditions;
}
}
// Rolls an item from the group (if any takes its chance) and adds the item to the loot
void LootTemplate::LootGroup::Process(Loot& loot, uint16 lootMode) const
{
@@ -1078,7 +1101,7 @@ void LootTemplate::LootGroup::Verify(LootStore const& lootstore, uint32 id, uint
}
}
void LootTemplate::LootGroup::CheckLootRefs(LootTemplateMap const& /*store*/, LootIdSet* ref_set) const
void LootTemplate::LootGroup::CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const
{
for (LootStoreItemList::const_iterator ieItr=ExplicitlyChanced.begin(); ieItr != ExplicitlyChanced.end(); ++ieItr)
{
@@ -1120,6 +1143,15 @@ void LootTemplate::AddEntry(LootStoreItem& item)
Entries.push_back(item);
}
void LootTemplate::CopyConditions(ConditionList conditions)
{
for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i)
i->conditions = conditions;
for (LootGroups::iterator i = Groups.begin(); i != Groups.end(); ++i)
i->CopyConditions(conditions);
}
// Rolls for every item in the template and adds the rolled items the the loot
void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint16 lootMode, uint8 groupId) const
{
@@ -1165,6 +1197,8 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint16
if (!Referenced)
continue; // Error message already printed at loading stage
const_cast<LootTemplate*>(Referenced)->CopyConditions(i->conditions);//copy conditions from referer template
for (uint32 loop = 0; loop < i->maxcount; ++loop) // Ref multiplicator
Referenced->Process(loot, store, rate, lootMode, i->group);
}
@@ -1268,6 +1302,66 @@ void LootTemplate::CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_se
for (LootGroups::const_iterator grItr = Groups.begin(); grItr != Groups.end(); ++grItr)
grItr->CheckLootRefs(store,ref_set);
}
bool LootTemplate::addConditionItem(Condition* cond)
{
if (!cond || !cond->isLoaded())//should never happen, checked at loading
{
sLog.outError("LootTemplate::addConditionItem: condition is null");
return false;
}
if (!Entries.empty())
{
for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i)
{
if (i->itemid == cond->mSourceEntry)
{
i->conditions.push_back(cond);
return true;
}
}
}
if (!Groups.empty())
{
for (LootGroups::iterator groupItr = Groups.begin(); groupItr != Groups.end(); ++groupItr)
{
LootStoreItemList* itemList = (*groupItr).GetExplicitlyChancedItemList();
if (!itemList->empty())
{
for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i)
{
if ((*i).itemid == cond->mSourceEntry)
{
(*i).conditions.push_back(cond);
return true;
}
}
}
itemList = (*groupItr).GetEqualChancedItemList();
if (!itemList->empty())
{
for (LootStoreItemList::iterator i = itemList->begin(); i != itemList->end(); ++i)
{
if ((*i).itemid == cond->mSourceEntry)
{
(*i).conditions.push_back(cond);
return true;
}
}
}
}
}
return false;
}
bool LootTemplate::isReference(uint32 id)
{
for (LootStoreItemList::const_iterator ieItr = Entries.begin(); ieItr != Entries.end(); ++ieItr)
{
if (ieItr->itemid == id && ieItr->mincountOrRef < 0)
return true;
}
return false;//not found or not reference
}
void LoadLootTemplates_Creature()
{
+13 -4
View File
@@ -25,6 +25,7 @@
#include "ByteBuffer.h"
#include "Utilities/LinkedReference/RefManager.h"
#include "SharedDefines.h"
#include "ConditionMgr.h"
#include <map>
#include <vector>
@@ -98,6 +99,7 @@ enum LootSlotType
class Player;
class LootStore;
class ConditionMgr;
struct LootStoreItem
{
@@ -108,13 +110,13 @@ struct LootStoreItem
uint8 group :7;
bool needs_quest :1; // quest drop (negative ChanceOrQuestChance in DB)
uint8 maxcount :8; // max drop count for the item (mincountOrRef positive) or Ref multiplicator (mincountOrRef negative)
uint16 conditionId :16; // additional loot condition Id
ConditionList conditions; // additional loot condition
// Constructor, converting ChanceOrQuestChance -> (chance, needs_quest)
// displayid is filled in IsValid() which must be called after
LootStoreItem(uint32 _itemid, float _chanceOrQuestChance, uint16 _lootmode, uint8 _group, uint8 _conditionId, int32 _mincountOrRef, uint8 _maxcount)
LootStoreItem(uint32 _itemid, float _chanceOrQuestChance, uint16 _lootmode, uint8 _group, int32 _mincountOrRef, uint8 _maxcount)
: itemid(_itemid), chance(fabs(_chanceOrQuestChance)), mincountOrRef(_mincountOrRef), lootmode(_lootmode),
group(_group), needs_quest(_chanceOrQuestChance < 0), maxcount(_maxcount), conditionId(_conditionId)
group(_group), needs_quest(_chanceOrQuestChance < 0), maxcount(_maxcount)
{}
bool Roll(bool rate) const; // Checks if the entry takes it's chance (at loot generation)
@@ -127,7 +129,7 @@ struct LootItem
uint32 itemid;
uint32 randomSuffix;
int32 randomPropertyId;
uint16 conditionId :16; // allow compiler pack structure
ConditionList conditions; // additional loot condition
uint8 count : 8;
bool is_looted : 1;
bool is_blocked : 1;
@@ -186,6 +188,8 @@ class LootStore
bool HaveQuestLootForPlayer(uint32 loot_id,Player* player) const;
LootTemplate const* GetLootFor(uint32 loot_id) const;
void ResetConditions();
LootTemplate* GetLootForConditionFill(uint32 loot_id);
char const* GetName() const { return m_name; }
char const* GetEntryName() const { return m_entryName; }
@@ -210,6 +214,7 @@ class LootTemplate
void AddEntry(LootStoreItem& item);
// Rolls for every item in the template and adds the rolled items the the loot
void Process(Loot& loot, LootStore const& store, bool rate, uint16 lootMode, uint8 groupId = 0) const;
void CopyConditions(ConditionList conditions);
// True if template includes at least 1 quest drop entry
bool HasQuestDrop(LootTemplateMap const& store, uint8 groupId = 0) const;
@@ -219,6 +224,9 @@ class LootTemplate
// Checks integrity of the template
void Verify(LootStore const& store, uint32 Id) const;
void CheckLootRefs(LootTemplateMap const& store, LootIdSet* ref_set) const;
bool addConditionItem(Condition* cond);
bool isReference(uint32 id);
private:
LootStoreItemList Entries; // not grouped only
LootGroups Groups; // groups have own (optimised) processing, grouped entries go there
@@ -355,6 +363,7 @@ extern LootStore LootTemplates_Item;
extern LootStore LootTemplates_Mail;
extern LootStore LootTemplates_Milling;
extern LootStore LootTemplates_Pickpocketing;
extern LootStore LootTemplates_Reference;
extern LootStore LootTemplates_Skinning;
extern LootStore LootTemplates_Disenchant;
extern LootStore LootTemplates_Prospecting;
+3 -405
View File
@@ -44,7 +44,6 @@
#include "SpellAuras.h"
#include "Util.h"
#include "WaypointManager.h"
#include "InstanceData.h" //for condition_instance_data
#include "GossipDef.h"
#include "Vehicle.h"
#include "AchievementMgr.h"
@@ -182,9 +181,6 @@ ObjectMgr::ObjectMgr()
m_guildId = 1;
m_arenaTeamId = 1;
m_auctionid = 1;
// Only zero condition left, others will be added while loading DB tables
mConditions.resize(1);
}
ObjectMgr::~ObjectMgr()
@@ -2427,107 +2423,6 @@ void ObjectMgr::LoadVehicleAccessories()
sLog.outString(">> Loaded %u Vehicle Accessories", count);
}
void ObjectMgr::LoadItemRequiredTarget()
{
m_ItemRequiredTarget.clear(); // needed for reload case
uint32 count = 0;
QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,type,targetEntry FROM item_required_target");
if (!result)
{
barGoLink bar(1);
bar.step();
sLog.outString();
sLog.outErrorDb(">> Loaded 0 ItemRequiredTarget. DB table `item_required_target` is empty.");
return;
}
barGoLink bar(result->GetRowCount());
do
{
Field *fields = result->Fetch();
bar.step();
uint32 uiItemId = fields[0].GetUInt32();
uint32 uiType = fields[1].GetUInt32();
uint32 uiTargetEntry = fields[2].GetUInt32();
ItemPrototype const* pItemProto = sItemStorage.LookupEntry<ItemPrototype>(uiItemId);
if (!pItemProto)
{
sLog.outErrorDb("Table `item_required_target`: Entry %u listed for TargetEntry %u does not exist in `item_template`.",uiItemId,uiTargetEntry);
continue;
}
bool bIsItemSpellValid = false;
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
if (SpellEntry const* pSpellInfo = sSpellStore.LookupEntry(pItemProto->Spells[i].SpellId))
{
if (pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE ||
pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE)
{
SpellScriptTargetBounds bounds = spellmgr.GetSpellScriptTargetBounds(pSpellInfo->Id);
if (bounds.first != bounds.second)
break;
for (int j = 0; j < 3; ++j)
{
if (pSpellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ENEMY ||
pSpellInfo->EffectImplicitTargetB[i] == TARGET_UNIT_TARGET_ENEMY ||
pSpellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_TARGET_ANY ||
pSpellInfo->EffectImplicitTargetB[i] == TARGET_UNIT_TARGET_ANY)
{
bIsItemSpellValid = true;
break;
}
}
if (bIsItemSpellValid)
break;
}
}
}
if (!bIsItemSpellValid)
{
sLog.outErrorDb("Table `item_required_target`: Spell used by item %u does not have implicit target TARGET_CHAIN_DAMAGE(6), TARGET_DUELVSPLAYER(25), already listed in `spell_script_target` or doesn't have item spelltrigger.",uiItemId);
continue;
}
if (!uiType || uiType > MAX_ITEM_REQ_TARGET_TYPE)
{
sLog.outErrorDb("Table `item_required_target`: Type %u for TargetEntry %u is incorrect.",uiType,uiTargetEntry);
continue;
}
if (!uiTargetEntry)
{
sLog.outErrorDb("Table `item_required_target`: TargetEntry == 0 for Type (%u).",uiType);
continue;
}
if (!sCreatureStorage.LookupEntry<CreatureInfo>(uiTargetEntry))
{
sLog.outErrorDb("Table `item_required_target`: creature template entry %u does not exist.",uiTargetEntry);
continue;
}
m_ItemRequiredTarget.insert(ItemRequiredTargetMap::value_type(uiItemId,ItemRequiredTarget(ItemRequiredTargetType(uiType),uiTargetEntry)));
++count;
} while (result->NextRow());
sLog.outString();
sLog.outString(">> Loaded %u Item required targets", count);
}
void ObjectMgr::LoadPetLevelInfo()
{
// Loading levels data
@@ -7631,28 +7526,6 @@ void ObjectMgr::LoadFishingBaseSkillLevel()
sLog.outString(">> Loaded %u areas for fishing base skill level", count);
}
// Searches for the same condition already in Conditions store
// Returns Id if found, else adds it to Conditions and returns Id
uint16 ObjectMgr::GetConditionId(ConditionType condition, uint32 value1, uint32 value2)
{
PlayerCondition lc = PlayerCondition(condition, value1, value2);
for (uint16 i=0; i < mConditions.size(); ++i)
{
if (lc == mConditions[i])
return i;
}
mConditions.push_back(lc);
if (mConditions.size() > 0xFFFF)
{
sLog.outError("Conditions store overflow! Current and later loaded conditions will ignored!");
return 0;
}
return mConditions.size() - 1;
}
bool ObjectMgr::CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names)
{
for (uint8 i =0; i < MAX_DECLINED_NAME_CASES; ++i)
@@ -7675,225 +7548,6 @@ uint32 ObjectMgr::GetAreaTriggerScriptId(uint32 trigger_id)
return 0;
}
// Checks if player meets the condition
bool PlayerCondition::Meets(Player const * player) const
{
if (!player)
return false; // player not present, return false
switch (condition)
{
case CONDITION_NONE:
return true; // empty condition, always met
case CONDITION_AURA:
return player->HasAuraEffect(value1, value2);
case CONDITION_ITEM:
return player->HasItemCount(value1, value2);
case CONDITION_ITEM_EQUIPPED:
return player->HasItemOrGemWithIdEquipped(value1,1);
case CONDITION_ZONEID:
return player->GetZoneId() == value1;
case CONDITION_REPUTATION_RANK:
{
FactionEntry const* faction = sFactionStore.LookupEntry(value1);
return faction && uint32(player->GetReputationMgr().GetRank(faction)) >= int32(value2);
}
case CONDITION_ACHIEVEMENT:
{
AchievementEntry const* achievement = GetAchievementStore()->LookupEntry(value1);
return player->GetAchievementMgr().HasAchieved(achievement);
}
case CONDITION_TEAM:
return player->GetTeam() == value1;
case CONDITION_CLASS:
return player->getClass() == value1;
case CONDITION_RACE:
return player->getRace() == value1;
case CONDITION_SKILL:
return player->HasSkill(value1) && player->GetBaseSkillValue(value1) >= value2;
case CONDITION_QUESTREWARDED:
return player->GetQuestRewardStatus(value1);
case CONDITION_QUESTTAKEN:
{
QuestStatus status = player->GetQuestStatus(value1);
return (status == QUEST_STATUS_INCOMPLETE);
}
case CONDITION_QUEST_NONE:
{
QuestStatus status = player->GetQuestStatus(value1);
return (status == QUEST_STATUS_NONE);
}
case CONDITION_AD_COMMISSION_AURA:
{
Unit::AuraApplicationMap const& auras = player->GetAppliedAuras();
for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
if ((itr->second->GetBase()->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetBase()->GetSpellProto()->SpellVisual[0] == 3580)
return true;
return false;
}
case CONDITION_NO_AURA:
return !player->HasAuraEffect(value1, value2);
case CONDITION_ACTIVE_EVENT:
return gameeventmgr.IsActiveEvent(value1);
case CONDITION_INSTANCE_DATA:
{
Map *map = player->GetMap();
if (map && map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData())
return ((InstanceMap*)map)->GetInstanceData()->GetData(value1) == value2;
}
default:
return false;
}
}
// Verification of condition values validity
bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 value2)
{
if (condition >= MAX_CONDITION) // Wrong condition type
{
sLog.outErrorDb("Condition has bad type of %u, skipped ", condition);
return false;
}
switch (condition)
{
case CONDITION_AURA:
{
if (!sSpellStore.LookupEntry(value1))
{
sLog.outErrorDb("Aura condition requires to have non existing spell (Id: %d), skipped", value1);
return false;
}
if (value2 > 2)
{
sLog.outErrorDb("Aura condition requires to have non existing effect index (%u) (must be 0..2), skipped", value2);
return false;
}
break;
}
case CONDITION_ITEM:
{
ItemPrototype const *proto = objmgr.GetItemPrototype(value1);
if (!proto)
{
sLog.outErrorDb("Item condition requires to have non existing item (%u), skipped", value1);
return false;
}
break;
}
case CONDITION_ITEM_EQUIPPED:
{
ItemPrototype const *proto = objmgr.GetItemPrototype(value1);
if (!proto)
{
sLog.outErrorDb("ItemEquipped condition requires to have non existing item (%u) equipped, skipped", value1);
return false;
}
break;
}
case CONDITION_ZONEID:
{
AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(value1);
if (!areaEntry)
{
sLog.outErrorDb("Zone condition requires to be in non existing area (%u), skipped", value1);
return false;
}
if (areaEntry->zone != 0)
{
sLog.outErrorDb("Zone condition requires to be in area (%u) which is a subzone but zone expected, skipped", value1);
return false;
}
break;
}
case CONDITION_REPUTATION_RANK:
{
FactionEntry const* factionEntry = sFactionStore.LookupEntry(value1);
if (!factionEntry)
{
sLog.outErrorDb("Reputation condition requires to have reputation non existing faction (%u), skipped", value1);
return false;
}
break;
}
case CONDITION_TEAM:
{
if (value1 != ALLIANCE && value1 != HORDE)
{
sLog.outErrorDb("Team condition specifies unknown team (%u), skipped", value1);
return false;
}
break;
}
case CONDITION_SKILL:
{
SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(value1);
if (!pSkill)
{
sLog.outErrorDb("Skill condition specifies non-existing skill (%u), skipped", value1);
return false;
}
if (value2 < 1 || value2 > sWorld.GetConfigMaxSkillValue())
{
sLog.outErrorDb("Skill condition specifies invalid skill value (%u), skipped", value2);
return false;
}
break;
}
case CONDITION_QUESTREWARDED:
case CONDITION_QUESTTAKEN:
{
Quest const *Quest = objmgr.GetQuestTemplate(value1);
if (!Quest)
{
sLog.outErrorDb("Quest condition specifies non-existing quest (%u), skipped", value1);
return false;
}
if (value2)
sLog.outErrorDb("Quest condition has useless data in value2 (%u)!", value2);
break;
}
case CONDITION_AD_COMMISSION_AURA:
{
if (value1)
sLog.outErrorDb("Quest condition has useless data in value1 (%u)!", value1);
if (value2)
sLog.outErrorDb("Quest condition has useless data in value2 (%u)!", value2);
break;
}
case CONDITION_NO_AURA:
{
if (!sSpellStore.LookupEntry(value1))
{
sLog.outErrorDb("Aura condition requires to have non existing spell (Id: %d), skipped", value1);
return false;
}
if (value2 > 2)
{
sLog.outErrorDb("Aura condition requires to have non existing effect index (%u) (must be 0..2), skipped", value2);
return false;
}
break;
}
case CONDITION_ACTIVE_EVENT:
{
GameEventMgr::GameEventDataMap const& events = gameeventmgr.GetEventMap();
if (value1 >=events.size() || !events[value1].isValid())
{
sLog.outErrorDb("Active event condition requires existed event id (%u), skipped", value1);
return false;
}
break;
}
case CONDITION_INSTANCE_DATA:
//TODO: need some check
break;
case CONDITION_NONE:
break;
}
return true;
}
SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial)
{
switch(pSkill->categoryId)
@@ -8423,8 +8077,7 @@ void ObjectMgr::LoadGossipMenu()
{
m_mGossipMenusMap.clear();
QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, text_id, "
"cond_1, cond_1_val_1, cond_1_val_2, cond_2, cond_2_val_1, cond_2_val_2 FROM gossip_menu");
QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, text_id FROM gossip_menu");
if (!result)
{
@@ -8450,14 +8103,7 @@ void ObjectMgr::LoadGossipMenu()
GossipMenus gMenu;
gMenu.entry = fields[0].GetUInt32();
gMenu.text_id = fields[1].GetUInt32();
ConditionType cond_1 = (ConditionType)fields[2].GetUInt32();
uint32 cond_1_val_1 = fields[3].GetUInt32();
uint32 cond_1_val_2 = fields[4].GetUInt32();
ConditionType cond_2 = (ConditionType)fields[5].GetUInt32();
uint32 cond_2_val_1 = fields[6].GetUInt32();
uint32 cond_2_val_2 = fields[7].GetUInt32();
gMenu.text_id = fields[1].GetUInt32();
if (!GetGossipText(gMenu.text_id))
{
@@ -8465,21 +8111,6 @@ void ObjectMgr::LoadGossipMenu()
continue;
}
if (!PlayerCondition::IsValid(cond_1, cond_1_val_1, cond_1_val_2))
{
sLog.outErrorDb("Table gossip_menu entry %u, invalid condition 1 for id %u", gMenu.entry, gMenu.text_id);
continue;
}
if (!PlayerCondition::IsValid(cond_2, cond_2_val_1, cond_2_val_2))
{
sLog.outErrorDb("Table gossip_menu entry %u, invalid condition 2 for id %u", gMenu.entry, gMenu.text_id);
continue;
}
gMenu.cond_1 = GetConditionId(cond_1, cond_1_val_1, cond_1_val_2);
gMenu.cond_2 = GetConditionId(cond_2, cond_2_val_1, cond_2_val_2);
m_mGossipMenusMap.insert(GossipMenusMap::value_type(gMenu.entry, gMenu));
++count;
@@ -8496,10 +8127,7 @@ void ObjectMgr::LoadGossipMenuItems()
QueryResult_AutoPtr result = WorldDatabase.Query(
"SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, "
"action_menu_id, action_poi_id, action_script_id, box_coded, box_money, box_text, "
"cond_1, cond_1_val_1, cond_1_val_2, "
"cond_2, cond_2_val_1, cond_2_val_2, "
"cond_3, cond_3_val_1, cond_3_val_2 "
"action_menu_id, action_poi_id, action_script_id, box_coded, box_money, box_text "
"FROM gossip_menu_option");
if (!result)
@@ -8543,32 +8171,6 @@ void ObjectMgr::LoadGossipMenuItems()
gMenuItem.box_money = fields[10].GetUInt32();
gMenuItem.box_text = fields[11].GetCppString();
ConditionType cond_1 = (ConditionType)fields[12].GetUInt32();
uint32 cond_1_val_1 = fields[13].GetUInt32();
uint32 cond_1_val_2 = fields[14].GetUInt32();
ConditionType cond_2 = (ConditionType)fields[15].GetUInt32();
uint32 cond_2_val_1 = fields[16].GetUInt32();
uint32 cond_2_val_2 = fields[17].GetUInt32();
ConditionType cond_3 = (ConditionType)fields[18].GetUInt32();
uint32 cond_3_val_1 = fields[19].GetUInt32();
uint32 cond_3_val_2 = fields[20].GetUInt32();
if (!PlayerCondition::IsValid(cond_1, cond_1_val_1, cond_1_val_2))
{
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 1 for id %u", gMenuItem.menu_id, gMenuItem.id);
continue;
}
if (!PlayerCondition::IsValid(cond_2, cond_2_val_1, cond_2_val_2))
{
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 2 for id %u", gMenuItem.menu_id, gMenuItem.id);
continue;
}
if (!PlayerCondition::IsValid(cond_3, cond_3_val_1, cond_3_val_2))
{
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 3 for id %u", gMenuItem.menu_id, gMenuItem.id);
continue;
}
if (gMenuItem.option_icon >= GOSSIP_ICON_MAX)
{
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has unknown icon id %u. Replacing with GOSSIP_ICON_CHAT", gMenuItem.menu_id, gMenuItem.id, gMenuItem.option_icon);
@@ -8601,10 +8203,6 @@ void ObjectMgr::LoadGossipMenuItems()
gossipScriptSet.erase(gMenuItem.action_script_id);
}
gMenuItem.cond_1 = GetConditionId(cond_1, cond_1_val_1, cond_1_val_2);
gMenuItem.cond_2 = GetConditionId(cond_2, cond_2_val_1, cond_2_val_2);
gMenuItem.cond_3 = GetConditionId(cond_3, cond_3_val_1, cond_3_val_2);
m_mGossipMenuItemsMap.insert(GossipMenuItemsMap::value_type(gMenuItem.menu_id, gMenuItem));
++count;
+15 -67
View File
@@ -41,10 +41,11 @@
#include "Policies/Singleton.h"
#include "Database/SQLStorage.h"
#include "Vehicle.h"
#include "ObjectMgr.h"
#include <string>
#include <map>
#include <limits>
#include "ConditionMgr.h"
extern SQLStorage sCreatureStorage;
extern SQLStorage sCreatureDataAddonStorage;
@@ -235,23 +236,22 @@ struct GossipMenuItems
bool box_coded;
uint32 box_money;
std::string box_text;
uint16 cond_1;
uint16 cond_2;
uint16 cond_3;
ConditionList conditions;
};
struct GossipMenus
{
uint32 entry;
uint32 text_id;
uint16 cond_1;
uint16 cond_2;
ConditionList conditions;
};
typedef std::multimap<uint32,GossipMenus> GossipMenusMap;
typedef std::pair<GossipMenusMap::const_iterator, GossipMenusMap::const_iterator> GossipMenusMapBounds;
typedef std::pair<GossipMenusMap::iterator, GossipMenusMap::iterator> GossipMenusMapBoundsNonConst;
typedef std::multimap<uint32,GossipMenuItems> GossipMenuItemsMap;
typedef std::pair<GossipMenuItemsMap::const_iterator, GossipMenuItemsMap::const_iterator> GossipMenuItemsMapBounds;
typedef std::pair<GossipMenuItemsMap::iterator, GossipMenuItemsMap::iterator> GossipMenuItemsMapBoundsNonConst;
struct QuestPOIPoint
{
@@ -300,48 +300,6 @@ struct GraveYardData
};
typedef std::multimap<uint32,GraveYardData> GraveYardMap;
enum ConditionType
{ // value1 value2 for the Condition enumed
CONDITION_NONE = 0, // 0 0
CONDITION_AURA = 1, // spell_id effindex
CONDITION_ITEM = 2, // item_id count
CONDITION_ITEM_EQUIPPED = 3, // item_id 0
CONDITION_ZONEID = 4, // zone_id 0
CONDITION_REPUTATION_RANK = 5, // faction_id min_rank
CONDITION_TEAM = 6, // player_team 0, (469 - Alliance 67 - Horde)
CONDITION_SKILL = 7, // skill_id skill_value
CONDITION_QUESTREWARDED = 8, // quest_id 0
CONDITION_QUESTTAKEN = 9, // quest_id 0, for condition true while quest active.
CONDITION_AD_COMMISSION_AURA = 10, // 0 0, for condition true while one from AD commission aura active
CONDITION_NO_AURA = 11, // spell_id effindex
CONDITION_ACTIVE_EVENT = 12, // event_id
CONDITION_INSTANCE_DATA = 13, // entry data
CONDITION_QUEST_NONE = 14, // quest_id 0
CONDITION_CLASS = 15, // class 0
CONDITION_RACE = 16, // race 0
CONDITION_ACHIEVEMENT = 17 // achievement_id 0
};
#define MAX_CONDITION 18 // maximum value in ConditionType enum
struct PlayerCondition
{
ConditionType condition; // additional condition type
uint32 value1; // data for the condition - see ConditionType definition
uint32 value2;
PlayerCondition(uint8 _condition = 0, uint32 _value1 = 0, uint32 _value2 = 0)
: condition(ConditionType(_condition)), value1(_value1), value2(_value2) {}
static bool IsValid(ConditionType condition, uint32 value1, uint32 value2);
// Checks correctness of values
bool Meets(Player const * APlayer) const; // Checks if the player meets the condition
bool operator == (PlayerCondition const& lc) const
{
return (lc.condition == condition && lc.value1 == value1 && lc.value2 == value2);
}
};
// NPC gossip text id
typedef UNORDERED_MAP<uint32, uint32> CacheNpcTextIdMap;
@@ -648,7 +606,6 @@ class ObjectMgr
void LoadGameobjects();
void LoadGameobjectRespawnTimes();
void LoadItemPrototypes();
void LoadItemRequiredTarget();
void LoadItemLocales();
void LoadQuestLocales();
void LoadNpcTextLocales();
@@ -880,15 +837,6 @@ class ObjectMgr
int GetIndexForLocale(LocaleConstant loc);
LocaleConstant GetLocaleForIndex(int i);
uint16 GetConditionId(ConditionType condition, uint32 value1, uint32 value2);
bool IsPlayerMeetToCondition(Player const* player, uint16 condition_id) const
{
if (condition_id >= mConditions.size())
return false;
return mConditions[condition_id].Meets(player);
}
GameTele const* GetGameTele(uint32 id) const
{
GameTeleMap::const_iterator itr = m_GameTeleMap.find(id);
@@ -942,11 +890,6 @@ class ObjectMgr
return SpellClickInfoMapBounds(mSpellClickInfoMap.lower_bound(creature_id),mSpellClickInfoMap.upper_bound(creature_id));
}
ItemRequiredTargetMapBounds GetItemRequiredTargetMapBounds(uint32 uiItemEntry) const
{
return ItemRequiredTargetMapBounds(m_ItemRequiredTarget.lower_bound(uiItemEntry),m_ItemRequiredTarget.upper_bound(uiItemEntry));
}
GM_Ticket *GetGMTicket(uint64 ticketGuid)
{
for (GmTicketList::const_iterator i = m_GMTicketList.begin(); i != m_GMTicketList.end(); ++i)
@@ -969,10 +912,19 @@ class ObjectMgr
return GossipMenusMapBounds(m_mGossipMenusMap.lower_bound(uiMenuId),m_mGossipMenusMap.upper_bound(uiMenuId));
}
GossipMenusMapBoundsNonConst GetGossipMenusMapBoundsNonConst(uint32 uiMenuId)
{
return GossipMenusMapBoundsNonConst(m_mGossipMenusMap.lower_bound(uiMenuId),m_mGossipMenusMap.upper_bound(uiMenuId));
}
GossipMenuItemsMapBounds GetGossipMenuItemsMapBounds(uint32 uiMenuId) const
{
return GossipMenuItemsMapBounds(m_mGossipMenuItemsMap.lower_bound(uiMenuId),m_mGossipMenuItemsMap.upper_bound(uiMenuId));
}
GossipMenuItemsMapBoundsNonConst GetGossipMenuItemsMapBoundsNonConst(uint32 uiMenuId)
{
return GossipMenuItemsMapBoundsNonConst(m_mGossipMenuItemsMap.lower_bound(uiMenuId),m_mGossipMenuItemsMap.upper_bound(uiMenuId));
}
void AddOrUpdateGMTicket(GM_Ticket &ticket, bool create = false);
void _AddOrUpdateGMTicket(GM_Ticket &ticket);
@@ -1109,10 +1061,6 @@ class ObjectMgr
RespawnTimes mCreatureRespawnTimes;
RespawnTimes mGORespawnTimes;
// Storage for Conditions. First element (index 0) is reserved for zero-condition (nothing required)
typedef std::vector<PlayerCondition> ConditionStore;
ConditionStore mConditions;
CacheNpcTextIdMap m_mCacheNpcTextIdMap;
CacheVendorItemMap m_mCacheVendorItemMap;
CacheTrainerSpellMap m_mCacheTrainerSpellMap;
+7 -12
View File
@@ -66,7 +66,7 @@
#include "AchievementMgr.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "ConditionMgr.h"
#include <cmath>
#define ZONE_UPDATE_INTERVAL (1*IN_MILISECONDS)
@@ -503,6 +503,8 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
m_powerFraction[i] = 0;
m_globalCooldowns.clear();
m_ConditionErrorMsgId = 0;
}
Player::~Player ()
@@ -13302,14 +13304,7 @@ void Player::PrepareGossipMenu(WorldObject *pSource, uint32 menuId, bool showQue
for (GossipMenuItemsMap::const_iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr)
{
bool bCanTalk = true;
if (itr->second.cond_1 && !objmgr.IsPlayerMeetToCondition(this, itr->second.cond_1))
continue;
if (itr->second.cond_2 && !objmgr.IsPlayerMeetToCondition(this, itr->second.cond_2))
continue;
if (itr->second.cond_3 && !objmgr.IsPlayerMeetToCondition(this, itr->second.cond_3))
if (!sConditionMgr.IsPlayerMeetToConditions(this, itr->second.conditions))
continue;
if (pSource->GetTypeId() == TYPEID_UNIT)
@@ -13643,7 +13638,7 @@ uint32 Player::GetGossipTextId(uint32 menuId)
for (GossipMenusMap::const_iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr)
{
if (objmgr.IsPlayerMeetToCondition(this, itr->second.cond_1) && objmgr.IsPlayerMeetToCondition(this, itr->second.cond_2))
if (sConditionMgr.IsPlayerMeetToConditions(this, itr->second.conditions))
textId = itr->second.text_id;
}
@@ -17439,8 +17434,8 @@ bool Player::CheckInstanceLoginValid()
if (GetMap()->IsRaid())
{
// cannot be in raid instance without a raid group
if (!GetGroup() || !GetGroup()->isRaidGroup())
// cannot be in raid instance without a group
if (!GetGroup())
return false;
}
else
+2
View File
@@ -2135,6 +2135,8 @@ class Player : public Unit, public GridObject<Player>
void SetHomebind(WorldLocation const& loc, uint32 area_id);
uint32 m_ConditionErrorMsgId;
// Homebind coordinates
uint32 m_homebindMapId;
uint16 m_homebindAreaId;
+36 -19
View File
@@ -51,6 +51,7 @@
#include "Vehicle.h"
#include "SpellAuraEffects.h"
#include "ScriptMgr.h"
#include "ConditionMgr.h"
#define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILISECONDS)
@@ -1683,10 +1684,10 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType)
{
case SPELL_TARGETS_ENTRY:
{
SpellScriptTargetBounds bounds = spellmgr.GetSpellScriptTargetBounds(m_spellInfo->Id);
if (bounds.first == bounds.second)
ConditionList conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id);
if (conditions.empty())
{
sLog.outDebug("Spell (ID: %u) (caster Entry: %u) does not have record in `spell_script_target`", m_spellInfo->Id, m_caster->GetEntry());
sLog.outDebug("Spell (ID: %u) (caster Entry: %u) does not have record in `conditions` for spell script target (ConditionSourceType 14)", m_spellInfo->Id, m_caster->GetEntry());
if (IsPositiveSpell(m_spellInfo->Id))
return SearchNearbyTarget(range, SPELL_TARGETS_ALLY);
else
@@ -1696,13 +1697,15 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType)
Creature* creatureScriptTarget = NULL;
GameObject* goScriptTarget = NULL;
for (SpellScriptTarget::const_iterator i_spellST = bounds.first; i_spellST != bounds.second; ++i_spellST)
for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST)
{
switch(i_spellST->second.type)
if ((*i_spellST)->mConditionType != CONDITION_SPELL_SCRIPT_TARGET)
continue;
switch((*i_spellST)->mConditionValue1)
{
case SPELL_TARGET_TYPE_CONTROLLED:
for (Unit::ControlList::iterator itr = m_caster->m_Controlled.begin(); itr != m_caster->m_Controlled.end(); ++itr)
if ((*itr)->GetEntry() == i_spellST->second.targetEntry && (*itr)->IsWithinDistInMap(m_caster, range))
if ((*itr)->GetEntry() == (*i_spellST)->mConditionValue2 && (*itr)->IsWithinDistInMap(m_caster, range))
{
goScriptTarget = NULL;
creatureScriptTarget = (*itr)->ToCreature();
@@ -1710,9 +1713,9 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType)
}
break;
case SPELL_TARGET_TYPE_GAMEOBJECT:
if (i_spellST->second.targetEntry)
if ((*i_spellST)->mConditionValue2)
{
if (GameObject *go = m_caster->FindNearestGameObject(i_spellST->second.targetEntry, range))
if (GameObject *go = m_caster->FindNearestGameObject((*i_spellST)->mConditionValue2, range))
{
// remember found target and range, next attempt will find more near target with another entry
goScriptTarget = go;
@@ -1732,11 +1735,11 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType)
}
break;
case SPELL_TARGET_TYPE_CREATURE:
if (m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetEntry() == i_spellST->second.targetEntry)
if (m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetEntry() == (*i_spellST)->mConditionValue2)
return m_targets.getUnitTarget();
case SPELL_TARGET_TYPE_DEAD:
default:
if (Creature *cre = m_caster->FindNearestCreature(i_spellST->second.targetEntry, range, i_spellST->second.type != SPELL_TARGET_TYPE_DEAD))
if (Creature *cre = m_caster->FindNearestCreature((*i_spellST)->mConditionValue2, range, (*i_spellST)->mConditionValue1 != SPELL_TARGET_TYPE_DEAD))
{
creatureScriptTarget = cre;
goScriptTarget = NULL;
@@ -2249,8 +2252,8 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur)
std::list<Unit*> unitList;
if (targetType == SPELL_TARGETS_ENTRY)
{
SpellScriptTargetBounds bounds = spellmgr.GetSpellScriptTargetBounds(m_spellInfo->Id);
if (bounds.first == bounds.second)
ConditionList conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id);
if (conditions.empty())
{
// Custom entries
// TODO: move these to sql
@@ -2321,14 +2324,16 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur)
// let it be done in one check?
else
{
for (SpellScriptTarget::const_iterator i_spellST = bounds.first; i_spellST != bounds.second; ++i_spellST)
for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST)
{
if (i_spellST->second.type == SPELL_TARGET_TYPE_CREATURE)
SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, i_spellST->second.targetEntry);
else if (i_spellST->second.type == SPELL_TARGET_TYPE_CONTROLLED)
if ((*i_spellST)->mConditionType != CONDITION_SPELL_SCRIPT_TARGET)
continue;
if ((*i_spellST)->mConditionValue1 == SPELL_TARGET_TYPE_CREATURE)
SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, (*i_spellST)->mConditionValue2);
else if ((*i_spellST)->mConditionValue1 == SPELL_TARGET_TYPE_CONTROLLED)
{
for (Unit::ControlList::iterator itr = m_caster->m_Controlled.begin(); itr != m_caster->m_Controlled.end(); ++itr)
if ((*itr)->GetEntry() == i_spellST->second.targetEntry &&
if ((*itr)->GetEntry() == (*i_spellST)->mConditionValue2 &&
/*(*itr)->IsWithinDistInMap(m_caster, radius)*/ (*itr)->IsInMap(m_caster)) // For 60243 and 52173 need skip radius check or use range (no radius entry for effect)
unitList.push_back(*itr);
}
@@ -2545,7 +2550,20 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const * triggere
return;
}
}
if (m_caster->ToPlayer())
{
//check for special spell conditions
ConditionList conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL, m_spellInfo->Id);
if (!conditions.empty())
{
if (!sConditionMgr.IsPlayerMeetToConditions(m_caster->ToPlayer(), conditions))
{
SendCastResult(SPELL_FAILED_DONT_REPORT);
finish(false);
return;
}
}
}
if (!m_targets.HasSrc() && m_spellInfo->Targets & TARGET_FLAG_SOURCE_LOCATION)
m_targets.setSrc(m_caster);
@@ -2607,7 +2625,6 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const * triggere
finish(false);
return;
}
if (m_caster->GetTypeId() == TYPEID_PLAYER)
{
if (objmgr.IsPlayerSpellDisabled(m_spellInfo->Id))
-168
View File
@@ -1972,174 +1972,6 @@ void SpellMgr::LoadSpellLearnSpells()
sLog.outString(">> Loaded %u spell learn spells + %u found in DBC", count, dbc_count);
}
void SpellMgr::LoadSpellScriptTarget()
{
mSpellScriptTarget.clear(); // need for reload case
uint32 count = 0;
QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry,type,targetEntry FROM spell_script_target");
if (!result)
{
barGoLink bar(1);
bar.step();
sLog.outString();
sLog.outErrorDb(">> Loaded 0 SpellScriptTarget. DB table `spell_script_target` is empty.");
return;
}
barGoLink bar(result->GetRowCount());
do
{
Field *fields = result->Fetch();
bar.step();
uint32 spellId = fields[0].GetUInt32();
uint32 type = fields[1].GetUInt32();
uint32 targetEntry = fields[2].GetUInt32();
SpellEntry const* spellProto = sSpellStore.LookupEntry(spellId);
if (!spellProto)
{
sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not exist.",spellId,targetEntry);
continue;
}
bool targetfound = false;
for (uint8 i = 0; i < 3; ++i)
{
if (spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENTRY_SRC ||
spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_AREA_ENTRY_SRC ||
spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENTRY_DST ||
spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_AREA_ENTRY_DST ||
spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_NEARBY_ENTRY ||
spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_NEARBY_ENTRY ||
spellProto->EffectImplicitTargetA[i] == TARGET_GAMEOBJECT_NEARBY_ENTRY ||
spellProto->EffectImplicitTargetB[i] == TARGET_GAMEOBJECT_NEARBY_ENTRY ||
spellProto->EffectImplicitTargetA[i] == TARGET_DST_NEARBY_ENTRY ||
spellProto->EffectImplicitTargetB[i] == TARGET_DST_NEARBY_ENTRY ||
spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_CONE_ENTRY ||
spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_CONE_ENTRY)
{
targetfound = true;
break;
}
}
if (!targetfound)
{
sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DST_NEARBY_ENTRY (46)\
,TARGET_UNIT_AREA_ENTRY_SRC(7), TARGET_UNIT_AREA_ENTRY_DST(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)",spellId,targetEntry);
continue;
}
if (type >= MAX_SPELL_TARGET_TYPE)
{
sLog.outErrorDb("Table `spell_script_target`: target type %u for TargetEntry %u is incorrect.",type,targetEntry);
continue;
}
switch(type)
{
case SPELL_TARGET_TYPE_GAMEOBJECT:
{
if (targetEntry == 0)
break;
if (!sGOStorage.LookupEntry<GameObjectInfo>(targetEntry))
{
sLog.outErrorDb("Table `spell_script_target`: gameobject template entry %u does not exist.", targetEntry);
continue;
}
break;
}
case SPELL_TARGET_TYPE_CONTROLLED:
if (targetEntry == 0)
sLog.outErrorDb("Table `spell_script_target`: creature template entry %u does not exist.", targetEntry);
default:
{
//players
/*if (targetEntry == 0)
{
sLog.outErrorDb("Table `spell_script_target`: target entry == 0 for not GO target type (%u).",type);
continue;
}*/
if (targetEntry && !sCreatureStorage.LookupEntry<CreatureInfo>(targetEntry))
{
sLog.outErrorDb("Table `spell_script_target`: creature template entry %u does not exist.", targetEntry);
continue;
}
const CreatureInfo* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(targetEntry);
if (spellId == 30427 && !cInfo->SkinLootId)
{
sLog.outErrorDb("Table `spell_script_target` has creature %u as a target of spellid 30427, but this creature has no skinlootid. Gas extraction will not work!", cInfo->Entry);
continue;
}
break;
}
}
mSpellScriptTarget.insert(SpellScriptTarget::value_type(spellId, SpellTargetEntry(SpellScriptTargetType(type), targetEntry)));
++count;
} while (result->NextRow());
// Check all spells
for (uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
{
SpellEntry const * spellInfo = sSpellStore.LookupEntry(i);
if (!spellInfo)
continue;
bool found = false;
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
{
switch (spellInfo->EffectImplicitTargetA[j])
{
case TARGET_UNIT_AREA_ENTRY_SRC:
case TARGET_UNIT_AREA_ENTRY_DST:
case TARGET_UNIT_NEARBY_ENTRY:
case TARGET_GAMEOBJECT_NEARBY_ENTRY:
case TARGET_DST_NEARBY_ENTRY:
case TARGET_UNIT_CONE_ENTRY:
found = true;
break;
}
if (found)
break;
switch (spellInfo->EffectImplicitTargetB[j])
{
case TARGET_UNIT_AREA_ENTRY_SRC:
case TARGET_UNIT_AREA_ENTRY_DST:
case TARGET_UNIT_NEARBY_ENTRY:
case TARGET_GAMEOBJECT_NEARBY_ENTRY:
case TARGET_DST_NEARBY_ENTRY:
case TARGET_UNIT_CONE_ENTRY:
found = true;
break;
}
if (found)
break;
}
if (found)
{
SpellScriptTargetBounds bounds = spellmgr.GetSpellScriptTargetBounds(i);
//if (bounds.first == bounds.second)
//sLog.outDebug("Spell (ID: %u) does not have record in `spell_script_target`", i);
}
}
sLog.outString();
sLog.outString(">> Loaded %u Spell Script Targets", count);
}
void SpellMgr::LoadSpellPetAuras()
{
mSpellPetAuraMap.clear(); // need for reload case
-11
View File
@@ -685,9 +685,6 @@ struct SpellTargetEntry
uint32 targetEntry;
};
typedef std::multimap<uint32,SpellTargetEntry> SpellScriptTarget;
typedef std::pair<SpellScriptTarget::const_iterator,SpellScriptTarget::const_iterator> SpellScriptTargetBounds;
// coordinates for spells (accessed using SpellMgr functions)
struct SpellTargetPosition
{
@@ -1216,12 +1213,6 @@ class SpellMgr
bool IsSkillBonusSpell(uint32 spellId) const;
bool IsSkillTypeSpell(uint32 spellId, SkillType type) const;
// Spell script targets
SpellScriptTargetBounds GetSpellScriptTargetBounds(uint32 spell_id) const
{
return SpellScriptTargetBounds(mSpellScriptTarget.lower_bound(spell_id),mSpellScriptTarget.upper_bound(spell_id));
}
// Spell correctess for client using
static bool IsSpellValid(SpellEntry const * spellInfo, Player* pl = NULL, bool msg = true);
@@ -1356,7 +1347,6 @@ class SpellMgr
void LoadSpellRequired();
void LoadSpellLearnSkills();
void LoadSpellLearnSpells();
void LoadSpellScriptTarget();
void LoadSpellGroups();
void LoadSpellProcEvents();
void LoadSpellBonusess();
@@ -1377,7 +1367,6 @@ class SpellMgr
bool _isPositiveSpell(uint32 spellId, bool deep) const;
bool _isPositiveEffect(uint32 spellId, uint32 effIndex, bool deep) const;
SpellScriptTarget mSpellScriptTarget;
SpellChainMap mSpellChains;
SpellsRequiringSpellMap mSpellsReqSpell;
SpellRequiredMap mSpellReq;
+4 -6
View File
@@ -70,6 +70,7 @@
#include "ScriptMgr.h"
#include "AddonMgr.h"
#include "LFGMgr.h"
#include "ConditionMgr.h"
INSTANTIATE_SINGLETON_1(World);
@@ -1380,12 +1381,6 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Creature templates...");
objmgr.LoadCreatureTemplates();
sLog.outString("Loading SpellsScriptTarget...");
spellmgr.LoadSpellScriptTarget(); // must be after LoadCreatureTemplates and LoadGameobjectInfo
sLog.outString("Loading ItemRequiredTarget...");
objmgr.LoadItemRequiredTarget();
sLog.outString("Loading Creature Reputation OnKill Data...");
objmgr.LoadReputationOnKill();
@@ -1578,6 +1573,9 @@ void World::SetInitialWorldSettings()
sLog.outString("Loading Creature Formations...");
formation_mgr.LoadCreatureFormations();
sLog.outString("Loading Conditions...");
sConditionMgr.LoadConditions();
sLog.outString("Loading GM tickets...");
objmgr.LoadGMTickets();
+8
View File
@@ -566,6 +566,14 @@
RelativePath="..\..\src\game\CombatHandler.cpp"
>
</File>
<File
RelativePath="..\..\src\game\ConditionMgr.cpp"
>
</File>
<File
RelativePath="..\..\src\game\ConditionMgr.h"
>
</File>
<File
RelativePath="..\..\src\game\DuelHandler.cpp"
>