mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 16:37:01 +00:00
[7622] Added creatureAI with related database tables.
Code and concept (also known as EventAI) by ScriptDev2. Note: database table layout are compatible with original db-scripts.
This commit is contained in:
parent
d6223e18f5
commit
6bb6ff0f7e
19 changed files with 2936 additions and 2 deletions
101
sql/mangos.sql
101
sql/mangos.sql
|
|
@ -22,7 +22,7 @@
|
||||||
DROP TABLE IF EXISTS `db_version`;
|
DROP TABLE IF EXISTS `db_version`;
|
||||||
CREATE TABLE `db_version` (
|
CREATE TABLE `db_version` (
|
||||||
`version` varchar(120) default NULL,
|
`version` varchar(120) default NULL,
|
||||||
`required_7616_02_mangos_command` bit(1) default NULL
|
`required_7622_03_mangos_creature_ai_texts` bit(1) default NULL
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
@ -920,6 +920,105 @@ LOCK TABLES `disenchant_loot_template` WRITE;
|
||||||
/*!40000 ALTER TABLE `disenchant_loot_template` ENABLE KEYS */;
|
/*!40000 ALTER TABLE `disenchant_loot_template` ENABLE KEYS */;
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `creature_ai_scripts`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `creature_ai_scripts`;
|
||||||
|
CREATE TABLE `creature_ai_scripts` (
|
||||||
|
`id` int(11) unsigned NOT NULL COMMENT 'Identifier' AUTO_INCREMENT,
|
||||||
|
`creature_id` int(11) unsigned NOT NULL default '0' COMMENT 'Creature Template Identifier',
|
||||||
|
`event_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Event Type',
|
||||||
|
`event_inverse_phase_mask` int(11) signed NOT NULL default '0' COMMENT 'Mask which phases this event will not trigger in',
|
||||||
|
`event_chance` int(3) unsigned NOT NULL default '100',
|
||||||
|
`event_flags` int(3) unsigned NOT NULL default '0',
|
||||||
|
`event_param1` int(11) signed NOT NULL default '0',
|
||||||
|
`event_param2` int(11) signed NOT NULL default '0',
|
||||||
|
`event_param3` int(11) signed NOT NULL default '0',
|
||||||
|
`event_param4` int(11) signed NOT NULL default '0',
|
||||||
|
`action1_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Action Type',
|
||||||
|
`action1_param1` int(11) signed NOT NULL default '0',
|
||||||
|
`action1_param2` int(11) signed NOT NULL default '0',
|
||||||
|
`action1_param3` int(11) signed NOT NULL default '0',
|
||||||
|
`action2_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Action Type',
|
||||||
|
`action2_param1` int(11) signed NOT NULL default '0',
|
||||||
|
`action2_param2` int(11) signed NOT NULL default '0',
|
||||||
|
`action2_param3` int(11) signed NOT NULL default '0',
|
||||||
|
`action3_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Action Type',
|
||||||
|
`action3_param1` int(11) signed NOT NULL default '0',
|
||||||
|
`action3_param2` int(11) signed NOT NULL default '0',
|
||||||
|
`action3_param3` int(11) signed NOT NULL default '0',
|
||||||
|
`comment` varchar(255) NOT NULL default '' COMMENT 'Event Comment',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='EventAI Scripts';
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `creature_ai_scripts`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `creature_ai_scripts` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `creature_ai_scripts` DISABLE KEYS */;
|
||||||
|
/*!40000 ALTER TABLE `creature_ai_scripts` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `creature_ai_summons`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `creature_ai_summons`;
|
||||||
|
CREATE TABLE `creature_ai_summons` (
|
||||||
|
`id` int(11) unsigned NOT NULL COMMENT 'Location Identifier' AUTO_INCREMENT,
|
||||||
|
`position_x` float NOT NULL default '0',
|
||||||
|
`position_y` float NOT NULL default '0',
|
||||||
|
`position_z` float NOT NULL default '0',
|
||||||
|
`orientation` float NOT NULL default '0',
|
||||||
|
`spawntimesecs` int(11) unsigned NOT NULL default '120',
|
||||||
|
`comment` varchar(255) NOT NULL default '' COMMENT 'Summon Comment',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='EventAI Summoning Locations';
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `creature_ai_summons`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `creature_ai_summons` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `creature_ai_summons` DISABLE KEYS */;
|
||||||
|
/*!40000 ALTER TABLE `creature_ai_summons` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `creature_ai_texts`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `creature_ai_texts`;
|
||||||
|
CREATE TABLE `creature_ai_texts` (
|
||||||
|
`entry` mediumint(8) NOT NULL,
|
||||||
|
`content_default` text NOT NULL,
|
||||||
|
`content_loc1` text,
|
||||||
|
`content_loc2` text,
|
||||||
|
`content_loc3` text,
|
||||||
|
`content_loc4` text,
|
||||||
|
`content_loc5` text,
|
||||||
|
`content_loc6` text,
|
||||||
|
`content_loc7` text,
|
||||||
|
`content_loc8` text,
|
||||||
|
`sound` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||||
|
`type` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||||
|
`language` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||||
|
`emote` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||||
|
`comment` text,
|
||||||
|
PRIMARY KEY (`entry`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Script Texts';
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `creature_ai_texts`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `creature_ai_texts` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `creature_ai_texts` DISABLE KEYS */;
|
||||||
|
/*!40000 ALTER TABLE `creature_ai_texts` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Table structure for table `event_scripts`
|
-- Table structure for table `event_scripts`
|
||||||
--
|
--
|
||||||
|
|
|
||||||
30
sql/updates/7622_01_mangos_creature_ai_scripts.sql
Normal file
30
sql/updates/7622_01_mangos_creature_ai_scripts.sql
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
ALTER TABLE db_version CHANGE COLUMN required_7616_02_mangos_command required_7622_01_mangos_creature_ai_scripts bit;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `creature_ai_scripts`;
|
||||||
|
CREATE TABLE `creature_ai_scripts` (
|
||||||
|
`id` int(11) unsigned NOT NULL COMMENT 'Identifier' AUTO_INCREMENT,
|
||||||
|
`creature_id` int(11) unsigned NOT NULL default '0' COMMENT 'Creature Template Identifier',
|
||||||
|
`event_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Event Type',
|
||||||
|
`event_inverse_phase_mask` int(11) signed NOT NULL default '0' COMMENT 'Mask which phases this event will not trigger in',
|
||||||
|
`event_chance` int(3) unsigned NOT NULL default '100',
|
||||||
|
`event_flags` int(3) unsigned NOT NULL default '0',
|
||||||
|
`event_param1` int(11) signed NOT NULL default '0',
|
||||||
|
`event_param2` int(11) signed NOT NULL default '0',
|
||||||
|
`event_param3` int(11) signed NOT NULL default '0',
|
||||||
|
`event_param4` int(11) signed NOT NULL default '0',
|
||||||
|
`action1_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Action Type',
|
||||||
|
`action1_param1` int(11) signed NOT NULL default '0',
|
||||||
|
`action1_param2` int(11) signed NOT NULL default '0',
|
||||||
|
`action1_param3` int(11) signed NOT NULL default '0',
|
||||||
|
`action2_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Action Type',
|
||||||
|
`action2_param1` int(11) signed NOT NULL default '0',
|
||||||
|
`action2_param2` int(11) signed NOT NULL default '0',
|
||||||
|
`action2_param3` int(11) signed NOT NULL default '0',
|
||||||
|
`action3_type` tinyint(5) unsigned NOT NULL default '0' COMMENT 'Action Type',
|
||||||
|
`action3_param1` int(11) signed NOT NULL default '0',
|
||||||
|
`action3_param2` int(11) signed NOT NULL default '0',
|
||||||
|
`action3_param3` int(11) signed NOT NULL default '0',
|
||||||
|
`comment` varchar(255) NOT NULL default '' COMMENT 'Event Comment',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='EventAI Scripts';
|
||||||
14
sql/updates/7622_02_mangos_creature_ai_summons.sql
Normal file
14
sql/updates/7622_02_mangos_creature_ai_summons.sql
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
ALTER TABLE db_version CHANGE COLUMN required_7622_01_mangos_creature_ai_scripts required_7622_02_mangos_creature_ai_summons bit;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `creature_ai_summons`;
|
||||||
|
CREATE TABLE `creature_ai_summons` (
|
||||||
|
`id` int(11) unsigned NOT NULL COMMENT 'Location Identifier' AUTO_INCREMENT,
|
||||||
|
`position_x` float NOT NULL default '0',
|
||||||
|
`position_y` float NOT NULL default '0',
|
||||||
|
`position_z` float NOT NULL default '0',
|
||||||
|
`orientation` float NOT NULL default '0',
|
||||||
|
`spawntimesecs` int(11) unsigned NOT NULL default '120',
|
||||||
|
`comment` varchar(255) NOT NULL default '' COMMENT 'Summon Comment',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='EventAI Summoning Locations';
|
||||||
22
sql/updates/7622_03_mangos_creature_ai_texts.sql
Normal file
22
sql/updates/7622_03_mangos_creature_ai_texts.sql
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
ALTER TABLE db_version CHANGE COLUMN required_7622_02_mangos_creature_ai_summons required_7622_03_mangos_creature_ai_texts bit;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `creature_ai_texts`;
|
||||||
|
CREATE TABLE `creature_ai_texts` (
|
||||||
|
`entry` mediumint(8) NOT NULL,
|
||||||
|
`content_default` text NOT NULL,
|
||||||
|
`content_loc1` text,
|
||||||
|
`content_loc2` text,
|
||||||
|
`content_loc3` text,
|
||||||
|
`content_loc4` text,
|
||||||
|
`content_loc5` text,
|
||||||
|
`content_loc6` text,
|
||||||
|
`content_loc7` text,
|
||||||
|
`content_loc8` text,
|
||||||
|
`sound` mediumint(8) unsigned NOT NULL DEFAULT '0',
|
||||||
|
`type` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||||
|
`language` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||||
|
`emote` tinyint(3) unsigned NOT NULL DEFAULT '0',
|
||||||
|
`comment` text,
|
||||||
|
PRIMARY KEY (`entry`)
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Script Texts';
|
||||||
|
|
@ -214,6 +214,9 @@ pkgdata_DATA = \
|
||||||
7615_01_mangos_command.sql \
|
7615_01_mangos_command.sql \
|
||||||
7616_01_mangos_mangos_string.sql \
|
7616_01_mangos_mangos_string.sql \
|
||||||
7616_02_mangos_command.sql \
|
7616_02_mangos_command.sql \
|
||||||
|
7622_01_mangos_creature_ai_scripts.sql \
|
||||||
|
7622_02_mangos_creature_ai_summons.sql \
|
||||||
|
7622_03_mangos_creature_ai_texts.sql \
|
||||||
README
|
README
|
||||||
|
|
||||||
## Additional files to include when running 'make dist'
|
## Additional files to include when running 'make dist'
|
||||||
|
|
@ -408,4 +411,7 @@ EXTRA_DIST = \
|
||||||
7615_01_mangos_command.sql \
|
7615_01_mangos_command.sql \
|
||||||
7616_01_mangos_mangos_string.sql \
|
7616_01_mangos_mangos_string.sql \
|
||||||
7616_02_mangos_command.sql \
|
7616_02_mangos_command.sql \
|
||||||
|
7622_01_mangos_creature_ai_scripts.sql \
|
||||||
|
7622_02_mangos_creature_ai_summons.sql \
|
||||||
|
7622_03_mangos_creature_ai_texts.sql \
|
||||||
README
|
README
|
||||||
|
|
|
||||||
|
|
@ -304,6 +304,29 @@ enum InhabitTypeValues
|
||||||
INHABIT_ANYWHERE = INHABIT_GROUND | INHABIT_WATER | INHABIT_AIR
|
INHABIT_ANYWHERE = INHABIT_GROUND | INHABIT_WATER | INHABIT_AIR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enums used by StringTextData::Type (CreatureEventAI)
|
||||||
|
enum ChatType
|
||||||
|
{
|
||||||
|
CHAT_TYPE_SAY = 0,
|
||||||
|
CHAT_TYPE_YELL = 1,
|
||||||
|
CHAT_TYPE_TEXT_EMOTE = 2,
|
||||||
|
CHAT_TYPE_BOSS_EMOTE = 3,
|
||||||
|
CHAT_TYPE_WHISPER = 4,
|
||||||
|
CHAT_TYPE_BOSS_WHISPER = 5,
|
||||||
|
CHAT_TYPE_ZONE_YELL = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
//Selection method used by SelectTarget (CreatureEventAI)
|
||||||
|
enum AttackingTarget
|
||||||
|
{
|
||||||
|
ATTACKING_TARGET_RANDOM = 0, //Just selects a random target
|
||||||
|
ATTACKING_TARGET_TOPAGGRO, //Selects targes from top aggro to bottom
|
||||||
|
ATTACKING_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top
|
||||||
|
ATTACKING_TARGET_RANDOM_PLAYER, //Just selects a random target (player only)
|
||||||
|
ATTACKING_TARGET_TOPAGGRO_PLAYER, //Selects targes from top aggro to bottom (player only)
|
||||||
|
ATTACKING_TARGET_BOTTOMAGGRO_PLAYER, //Selects targets from bottom aggro to top (player only)
|
||||||
|
};
|
||||||
|
|
||||||
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
|
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
|
||||||
#if defined( __GNUC__ )
|
#if defined( __GNUC__ )
|
||||||
#pragma pack()
|
#pragma pack()
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include "GuardAI.h"
|
#include "GuardAI.h"
|
||||||
#include "PetAI.h"
|
#include "PetAI.h"
|
||||||
#include "TotemAI.h"
|
#include "TotemAI.h"
|
||||||
|
#include "CreatureEventAI.h"
|
||||||
#include "RandomMovementGenerator.h"
|
#include "RandomMovementGenerator.h"
|
||||||
#include "CreatureAIImpl.h"
|
#include "CreatureAIImpl.h"
|
||||||
#include "MovementGeneratorImpl.h"
|
#include "MovementGeneratorImpl.h"
|
||||||
|
|
@ -38,6 +39,7 @@ namespace AIRegistry
|
||||||
(new CreatureAIFactory<GuardAI>("GuardAI"))->RegisterSelf();
|
(new CreatureAIFactory<GuardAI>("GuardAI"))->RegisterSelf();
|
||||||
(new CreatureAIFactory<PetAI>("PetAI"))->RegisterSelf();
|
(new CreatureAIFactory<PetAI>("PetAI"))->RegisterSelf();
|
||||||
(new CreatureAIFactory<TotemAI>("TotemAI"))->RegisterSelf();
|
(new CreatureAIFactory<TotemAI>("TotemAI"))->RegisterSelf();
|
||||||
|
(new CreatureAIFactory<CreatureEventAI>("EventAI"))->RegisterSelf();
|
||||||
|
|
||||||
(new MovementGeneratorFactory<RandomMovementGenerator<Creature> >(RANDOM_MOTION_TYPE))->RegisterSelf();
|
(new MovementGeneratorFactory<RandomMovementGenerator<Creature> >(RANDOM_MOTION_TYPE))->RegisterSelf();
|
||||||
(new MovementGeneratorFactory<WaypointMovementGenerator<Creature> >(WAYPOINT_MOTION_TYPE))->RegisterSelf();
|
(new MovementGeneratorFactory<WaypointMovementGenerator<Creature> >(WAYPOINT_MOTION_TYPE))->RegisterSelf();
|
||||||
|
|
|
||||||
1705
src/game/CreatureEventAI.cpp
Normal file
1705
src/game/CreatureEventAI.cpp
Normal file
File diff suppressed because it is too large
Load diff
305
src/game/CreatureEventAI.h
Normal file
305
src/game/CreatureEventAI.h
Normal file
|
|
@ -0,0 +1,305 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||||
|
*
|
||||||
|
* 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 MANGOS_CREATURE_EAI_H
|
||||||
|
#define MANGOS_CREATURE_EAI_H
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Creature.h"
|
||||||
|
#include "CreatureAI.h"
|
||||||
|
#include "Unit.h"
|
||||||
|
|
||||||
|
class Player;
|
||||||
|
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 Event_Types
|
||||||
|
{
|
||||||
|
EVENT_T_TIMER = 0, //InitialMin, InitialMax, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_TIMER_OOC = 1, //InitialMin, InitialMax, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_HP = 2, //HPMax%, HPMin%, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_MANA = 3, //ManaMax%,ManaMin% RepeatMin, RepeatMax
|
||||||
|
EVENT_T_AGGRO = 4, //NONE
|
||||||
|
EVENT_T_KILL = 5, //RepeatMin, RepeatMax
|
||||||
|
EVENT_T_DEATH = 6, //NONE
|
||||||
|
EVENT_T_EVADE = 7, //NONE
|
||||||
|
EVENT_T_SPELLHIT = 8, //SpellID, School, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_RANGE = 9, //MinDist, MaxDist, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_OOC_LOS = 10, //NoHostile, NoFriendly, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_SPAWNED = 11, //NONE
|
||||||
|
EVENT_T_TARGET_HP = 12, //HPMax%, HPMin%, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_TARGET_CASTING = 13, //RepeatMin, RepeatMax
|
||||||
|
EVENT_T_FRIENDLY_HP = 14, //HPDeficit, Radius, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_FRIENDLY_IS_CC = 15, //DispelType, Radius, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_FRIENDLY_MISSING_BUFF = 16, //SpellId, Radius, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_SUMMONED_UNIT = 17, //CreatureId, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_TARGET_MANA = 18, //ManaMax%, ManaMin%, RepeatMin, RepeatMax
|
||||||
|
EVENT_T_QUEST_ACCEPT = 19, //QuestID
|
||||||
|
EVENT_T_QUEST_COMPLETE = 20, //
|
||||||
|
EVENT_T_REACHED_HOME = 21, //NONE
|
||||||
|
EVENT_T_RECEIVE_EMOTE = 22, //EmoteId, Condition, CondValue1, CondValue2
|
||||||
|
|
||||||
|
EVENT_T_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Action_Types
|
||||||
|
{
|
||||||
|
ACTION_T_NONE = 0, //No action
|
||||||
|
ACTION_T_TEXT = 1, //-TextId1, optionally -TextId2, optionally -TextId3(if -TextId2 exist). If more than just -TextId1 is defined, randomize. Negative values.
|
||||||
|
ACTION_T_SET_FACTION = 2, //FactionId (or 0 for default)
|
||||||
|
ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3, //Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph)
|
||||||
|
ACTION_T_SOUND = 4, //SoundId
|
||||||
|
ACTION_T_EMOTE = 5, //EmoteId
|
||||||
|
ACTION_T_RANDOM_SAY = 6, //UNUSED
|
||||||
|
ACTION_T_RANDOM_YELL = 7, //UNUSED
|
||||||
|
ACTION_T_RANDOM_TEXTEMOTE = 8, //UNUSED
|
||||||
|
ACTION_T_RANDOM_SOUND = 9, //SoundId1, SoundId2, SoundId3 (-1 in any field means no output if randomed that field)
|
||||||
|
ACTION_T_RANDOM_EMOTE = 10, //EmoteId1, EmoteId2, EmoteId3 (-1 in any field means no output if randomed that field)
|
||||||
|
ACTION_T_CAST = 11, //SpellId, Target, CastFlags
|
||||||
|
ACTION_T_SUMMON = 12, //CreatureID, Target, Duration in ms
|
||||||
|
ACTION_T_THREAT_SINGLE_PCT = 13, //Threat%, Target
|
||||||
|
ACTION_T_THREAT_ALL_PCT = 14, //Threat%
|
||||||
|
ACTION_T_QUEST_EVENT = 15, //QuestID, Target
|
||||||
|
ACTION_T_CASTCREATUREGO = 16, //QuestID, SpellId, Target
|
||||||
|
ACTION_T_SET_UNIT_FIELD = 17, //Field_Number, Value, Target
|
||||||
|
ACTION_T_SET_UNIT_FLAG = 18, //Flags (may be more than one field OR'd together), Target
|
||||||
|
ACTION_T_REMOVE_UNIT_FLAG = 19, //Flags (may be more than one field OR'd together), Target
|
||||||
|
ACTION_T_AUTO_ATTACK = 20, //AllowAttackState (0 = stop attack, anything else means continue attacking)
|
||||||
|
ACTION_T_COMBAT_MOVEMENT = 21, //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
|
||||||
|
ACTION_T_SET_PHASE = 22, //Phase
|
||||||
|
ACTION_T_INC_PHASE = 23, //Value (may be negative to decrement phase, should not be 0)
|
||||||
|
ACTION_T_EVADE = 24, //No Params
|
||||||
|
ACTION_T_FLEE = 25, //No Params
|
||||||
|
ACTION_T_QUEST_EVENT_ALL = 26, //QuestID
|
||||||
|
ACTION_T_CASTCREATUREGO_ALL = 27, //QuestId, SpellId
|
||||||
|
ACTION_T_REMOVEAURASFROMSPELL = 28, //Target, Spellid
|
||||||
|
ACTION_T_RANGED_MOVEMENT = 29, //Distance, Angle
|
||||||
|
ACTION_T_RANDOM_PHASE = 30, //PhaseId1, PhaseId2, PhaseId3
|
||||||
|
ACTION_T_RANDOM_PHASE_RANGE = 31, //PhaseMin, PhaseMax
|
||||||
|
ACTION_T_SUMMON_ID = 32, //CreatureId, Target, SpawnId
|
||||||
|
ACTION_T_KILLED_MONSTER = 33, //CreatureId, Target
|
||||||
|
ACTION_T_SET_INST_DATA = 34, //Field, Data
|
||||||
|
ACTION_T_SET_INST_DATA64 = 35, //Field, Target
|
||||||
|
ACTION_T_UPDATE_TEMPLATE = 36, //Entry, Team
|
||||||
|
ACTION_T_DIE = 37, //No Params
|
||||||
|
ACTION_T_ZONE_COMBAT_PULSE = 38, //No Params
|
||||||
|
|
||||||
|
ACTION_T_END,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Target
|
||||||
|
{
|
||||||
|
//Self (m_creature)
|
||||||
|
TARGET_T_SELF = 0, //Self cast
|
||||||
|
|
||||||
|
//Hostile targets (if pet then returns pet owner)
|
||||||
|
TARGET_T_HOSTILE, //Our current target (ie: highest aggro)
|
||||||
|
TARGET_T_HOSTILE_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks)
|
||||||
|
TARGET_T_HOSTILE_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for)
|
||||||
|
TARGET_T_HOSTILE_RANDOM, //Just any random target on our threat list
|
||||||
|
TARGET_T_HOSTILE_RANDOM_NOT_TOP, //Any random target except top threat
|
||||||
|
|
||||||
|
//Invoker targets (if pet then returns pet owner)
|
||||||
|
TARGET_T_ACTION_INVOKER, //Unit who caused this Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP, EVENT_T_FRIENDLY_IS_CC, EVENT_T_FRIENDLY_MISSING_BUFF)
|
||||||
|
|
||||||
|
//Hostile targets (including pets)
|
||||||
|
TARGET_T_HOSTILE_WPET, //Current target (can be a pet)
|
||||||
|
TARGET_T_HOSTILE_WPET_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks)
|
||||||
|
TARGET_T_HOSTILE_WPET_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for)
|
||||||
|
TARGET_T_HOSTILE_WPET_RANDOM, //Just any random target on our threat list
|
||||||
|
TARGET_T_HOSTILE_WPET_RANDOM_NOT_TOP, //Any random target except top threat
|
||||||
|
|
||||||
|
TARGET_T_ACTION_INVOKER_WPET,
|
||||||
|
|
||||||
|
TARGET_T_END
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CastFlags
|
||||||
|
{
|
||||||
|
CAST_INTURRUPT_PREVIOUS = 0x01, //Interrupt any spell casting
|
||||||
|
CAST_TRIGGERED = 0x02, //Triggered (this makes spell cost zero mana and have no cast time)
|
||||||
|
CAST_FORCE_CAST = 0x04, //Forces cast even if creature is out of mana or out of range
|
||||||
|
CAST_NO_MELEE_IF_OOM = 0x08, //Prevents creature from entering melee if out of mana or out of range
|
||||||
|
CAST_FORCE_TARGET_SELF = 0x10, //Forces the target to cast this spell on itself
|
||||||
|
CAST_AURA_NOT_PRESENT = 0x20, //Only casts the spell if the target does not have an aura from the spell
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EventFlags
|
||||||
|
{
|
||||||
|
EFLAG_REPEATABLE = 0x01, //Event repeats
|
||||||
|
EFLAG_NORMAL = 0x02, //Event only occurs in Normal instance difficulty
|
||||||
|
EFLAG_HEROIC = 0x04, //Event only occurs in Heroic instance difficulty
|
||||||
|
EFLAG_RESERVED_3 = 0x08,
|
||||||
|
EFLAG_RESERVED_4 = 0x10,
|
||||||
|
EFLAG_RESERVED_5 = 0x20,
|
||||||
|
EFLAG_RESERVED_6 = 0x40,
|
||||||
|
EFLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build of SD2 only
|
||||||
|
};
|
||||||
|
|
||||||
|
// String text additional data, used in (CreatureEventAI)
|
||||||
|
struct StringTextData
|
||||||
|
{
|
||||||
|
uint32 SoundId;
|
||||||
|
uint8 Type;
|
||||||
|
uint32 Language;
|
||||||
|
uint32 Emote;
|
||||||
|
};
|
||||||
|
// Text Maps
|
||||||
|
typedef UNORDERED_MAP<int32, StringTextData> CreatureEventAI_TextMap;
|
||||||
|
|
||||||
|
struct CreatureEventAI_Event
|
||||||
|
{
|
||||||
|
uint32 event_id;
|
||||||
|
|
||||||
|
uint32 creature_id;
|
||||||
|
|
||||||
|
uint16 event_type;
|
||||||
|
uint32 event_inverse_phase_mask;
|
||||||
|
uint8 event_chance;
|
||||||
|
uint8 event_flags;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32 event_param1;
|
||||||
|
int32 event_param1_s;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32 event_param2;
|
||||||
|
int32 event_param2_s;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32 event_param3;
|
||||||
|
int32 event_param3_s;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32 event_param4;
|
||||||
|
int32 event_param4_s;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _action
|
||||||
|
{
|
||||||
|
uint16 type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32 param1;
|
||||||
|
int32 param1_s;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32 param2;
|
||||||
|
int32 param2_s;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32 param3;
|
||||||
|
int32 param3_s;
|
||||||
|
};
|
||||||
|
}action[MAX_ACTIONS];
|
||||||
|
};
|
||||||
|
//Event_Map
|
||||||
|
typedef UNORDERED_MAP<uint32, std::vector<CreatureEventAI_Event> > CreatureEventAI_Event_Map;
|
||||||
|
|
||||||
|
struct CreatureEventAI_Summon
|
||||||
|
{
|
||||||
|
uint32 id;
|
||||||
|
|
||||||
|
float position_x;
|
||||||
|
float position_y;
|
||||||
|
float position_z;
|
||||||
|
float orientation;
|
||||||
|
uint32 SpawnTimeSecs;
|
||||||
|
};
|
||||||
|
|
||||||
|
//EventSummon_Map
|
||||||
|
typedef UNORDERED_MAP<uint32, CreatureEventAI_Summon> CreatureEventAI_Summon_Map;
|
||||||
|
|
||||||
|
struct CreatureEventAIHolder
|
||||||
|
{
|
||||||
|
CreatureEventAIHolder(CreatureEventAI_Event p) : Event(p), Time(0), Enabled(true){}
|
||||||
|
|
||||||
|
CreatureEventAI_Event Event;
|
||||||
|
uint32 Time;
|
||||||
|
bool Enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MANGOS_DLL_SPEC CreatureEventAI : public CreatureAI
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
CreatureEventAI(Creature &c);
|
||||||
|
~CreatureEventAI()
|
||||||
|
{
|
||||||
|
CreatureEventAIList.clear();
|
||||||
|
}
|
||||||
|
void JustRespawned();
|
||||||
|
void Reset();
|
||||||
|
void JustReachedHome();
|
||||||
|
void EnterEvadeMode();
|
||||||
|
void JustDied(Unit* killer);
|
||||||
|
void KilledUnit(Unit* victim);
|
||||||
|
void JustSummoned(Creature* pUnit);
|
||||||
|
void Aggro(Unit *who);
|
||||||
|
void AttackStart(Unit *who);
|
||||||
|
void MoveInLineOfSight(Unit *who);
|
||||||
|
void SpellHit(Unit* pUnit, const SpellEntry* pSpell);
|
||||||
|
void UpdateAI(const uint32 diff);
|
||||||
|
bool IsVisible(Unit *) const;
|
||||||
|
static int Permissible(const Creature *);
|
||||||
|
|
||||||
|
bool ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pActionInvoker = NULL);
|
||||||
|
void ProcessAction(uint16 type, uint32 param1, uint32 param2, uint32 param3, uint32 rnd, uint32 EventId, Unit* pActionInvoker);
|
||||||
|
inline uint32 GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3);
|
||||||
|
inline Unit* GetTargetByType(uint32 Target, Unit* pActionInvoker);
|
||||||
|
inline Unit* SelectUnit(AttackingTarget target, uint32 position);
|
||||||
|
|
||||||
|
void DoScriptText(int32 textEntry, WorldObject* pSource, Unit* target);
|
||||||
|
void DoZoneInCombat(Unit* pUnit);
|
||||||
|
void DoMeleeAttackIfReady();
|
||||||
|
bool CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered);
|
||||||
|
bool ReceiveEmote(Player* pPlayer, Creature* pCreature, uint32 uiEmote);
|
||||||
|
|
||||||
|
Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff);
|
||||||
|
void DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid);
|
||||||
|
void DoFindFriendlyCC(std::list<Creature*>& _list, float range);
|
||||||
|
|
||||||
|
//Pointer to creature we are manipulating
|
||||||
|
Creature& m_creature;
|
||||||
|
|
||||||
|
//Bool for if we are in combat or not
|
||||||
|
bool InCombat;
|
||||||
|
|
||||||
|
//Holder for events (stores enabled, time, and eventid)
|
||||||
|
std::list<CreatureEventAIHolder> CreatureEventAIList;
|
||||||
|
uint32 EventUpdateTime; //Time between event updates
|
||||||
|
uint32 EventDiff; //Time between the last event call
|
||||||
|
bool bEmptyList;
|
||||||
|
|
||||||
|
//Variables used by Events themselves
|
||||||
|
uint8 Phase; //Current phase, max 32 phases
|
||||||
|
bool CombatMovementEnabled; //If we allow targeted movment gen (movement twoards top threat)
|
||||||
|
bool MeleeEnabled; //If we allow melee auto attack
|
||||||
|
uint32 AttackDistance; //Distance to attack from
|
||||||
|
float AttackAngle; //Angle of attack
|
||||||
|
};
|
||||||
|
#endif
|
||||||
560
src/game/CreatureEventAIMgr.cpp
Normal file
560
src/game/CreatureEventAIMgr.cpp
Normal file
|
|
@ -0,0 +1,560 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
#include "Database/DatabaseEnv.h"
|
||||||
|
#include "Database/SQLStorage.h"
|
||||||
|
#include "CreatureEventAI.h"
|
||||||
|
#include "CreatureEventAIMgr.h"
|
||||||
|
#include "ObjectMgr.h"
|
||||||
|
#include "ProgressBar.h"
|
||||||
|
#include "Policies/SingletonImp.h"
|
||||||
|
#include "ObjectDefines.h"
|
||||||
|
|
||||||
|
INSTANTIATE_SINGLETON_1(CreatureEventAIMgr);
|
||||||
|
|
||||||
|
// -------------------
|
||||||
|
void CreatureEventAIMgr::LoadCreatureEventAI_Texts()
|
||||||
|
{
|
||||||
|
// Drop Existing Text Map, only done once and we are ready to add data from multiple sources.
|
||||||
|
m_CreatureEventAI_TextMap.clear();
|
||||||
|
|
||||||
|
// Load EventAI Text
|
||||||
|
LoadMangosStrings(WorldDatabase,"creature_ai_texts",-1,1+(TEXT_SOURCE_RANGE));
|
||||||
|
|
||||||
|
// Gather Additional data from EventAI Texts
|
||||||
|
QueryResult *result = WorldDatabase.PQuery("SELECT entry, sound, type, language, emote FROM creature_ai_texts");
|
||||||
|
|
||||||
|
sLog.outString("Loading EventAI Texts additional data...");
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
barGoLink bar(result->GetRowCount());
|
||||||
|
uint32 count = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
bar.step();
|
||||||
|
Field* fields = result->Fetch();
|
||||||
|
StringTextData temp;
|
||||||
|
|
||||||
|
int32 i = fields[0].GetInt32();
|
||||||
|
temp.SoundId = fields[1].GetInt32();
|
||||||
|
temp.Type = fields[2].GetInt32();
|
||||||
|
temp.Language = fields[3].GetInt32();
|
||||||
|
temp.Emote = fields[4].GetInt32();
|
||||||
|
|
||||||
|
if (i >= 0)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` is not a negative value.",i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i <= TEXT_SOURCE_RANGE)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` is out of accepted entry range for table.",i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp.SoundId)
|
||||||
|
{
|
||||||
|
if (!GetSoundEntriesStore()->LookupEntry(temp.SoundId))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` has soundId %u but sound does not exist.",i,temp.SoundId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!GetLanguageDescByID(temp.Language))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` using Language %u but Language does not exist.",i,temp.Language);
|
||||||
|
|
||||||
|
if (temp.Type > CHAT_TYPE_BOSS_WHISPER)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Entry %i in table `creature_ai_texts` has Type %u but this Chat Type does not exist.",i,temp.Type);
|
||||||
|
|
||||||
|
m_CreatureEventAI_TextMap[i] = temp;
|
||||||
|
++count;
|
||||||
|
} while (result->NextRow());
|
||||||
|
|
||||||
|
delete result;
|
||||||
|
|
||||||
|
sLog.outString();
|
||||||
|
sLog.outString(">> Loaded %u additional CreatureEventAI Texts data.", count);
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
barGoLink bar(1);
|
||||||
|
bar.step();
|
||||||
|
sLog.outString();
|
||||||
|
sLog.outString(">> Loaded 0 additional CreatureEventAI Texts data. DB table `creature_ai_texts` is empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------
|
||||||
|
void CreatureEventAIMgr::LoadCreatureEventAI_Summons()
|
||||||
|
{
|
||||||
|
|
||||||
|
//Drop Existing EventSummon Map
|
||||||
|
m_CreatureEventAI_Summon_Map.clear();
|
||||||
|
|
||||||
|
//Gather additional data for EventAI
|
||||||
|
QueryResult *result = WorldDatabase.PQuery("SELECT id, position_x, position_y, position_z, orientation, spawntimesecs FROM creature_ai_summons");
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
barGoLink bar(result->GetRowCount());
|
||||||
|
uint32 Count = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
bar.step();
|
||||||
|
Field *fields = result->Fetch();
|
||||||
|
|
||||||
|
CreatureEventAI_Summon temp;
|
||||||
|
|
||||||
|
uint32 i = fields[0].GetUInt32();
|
||||||
|
temp.position_x = fields[1].GetFloat();
|
||||||
|
temp.position_y = fields[2].GetFloat();
|
||||||
|
temp.position_z = fields[3].GetFloat();
|
||||||
|
temp.orientation = fields[4].GetFloat();
|
||||||
|
temp.SpawnTimeSecs = fields[5].GetUInt32();
|
||||||
|
|
||||||
|
//Add to map
|
||||||
|
m_CreatureEventAI_Summon_Map[i] = temp;
|
||||||
|
++Count;
|
||||||
|
}while (result->NextRow());
|
||||||
|
|
||||||
|
delete result;
|
||||||
|
|
||||||
|
sLog.outString();
|
||||||
|
sLog.outString(">> Loaded %u CreatureEventAI summon definitions", Count);
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
barGoLink bar(1);
|
||||||
|
bar.step();
|
||||||
|
sLog.outString();
|
||||||
|
sLog.outString(">> Loaded 0 CreatureEventAI Summon definitions. DB table `creature_ai_summons` is empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------
|
||||||
|
void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
|
||||||
|
{
|
||||||
|
//Drop Existing EventAI List
|
||||||
|
m_CreatureEventAI_Event_Map.clear();
|
||||||
|
|
||||||
|
//Gather event data
|
||||||
|
QueryResult *result = WorldDatabase.PQuery("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, "
|
||||||
|
"event_param1, event_param2, event_param3, event_param4, "
|
||||||
|
"action1_type, action1_param1, action1_param2, action1_param3, "
|
||||||
|
"action2_type, action2_param1, action2_param2, action2_param3, "
|
||||||
|
"action3_type, action3_param1, action3_param2, action3_param3 "
|
||||||
|
"FROM creature_ai_scripts");
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
barGoLink bar(result->GetRowCount());
|
||||||
|
uint32 Count = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
bar.step();
|
||||||
|
Field *fields = result->Fetch();
|
||||||
|
|
||||||
|
CreatureEventAI_Event temp;
|
||||||
|
|
||||||
|
temp.event_id = fields[0].GetUInt32();
|
||||||
|
uint32 i = temp.event_id;
|
||||||
|
temp.creature_id = fields[1].GetUInt32();
|
||||||
|
uint32 creature_id = temp.creature_id;
|
||||||
|
temp.event_type = fields[2].GetUInt16();
|
||||||
|
temp.event_inverse_phase_mask = fields[3].GetUInt32();
|
||||||
|
temp.event_chance = fields[4].GetUInt8();
|
||||||
|
temp.event_flags = fields[5].GetUInt8();
|
||||||
|
temp.event_param1 = fields[6].GetUInt32();
|
||||||
|
temp.event_param2 = fields[7].GetUInt32();
|
||||||
|
temp.event_param3 = fields[8].GetUInt32();
|
||||||
|
temp.event_param4 = fields[9].GetUInt32();
|
||||||
|
|
||||||
|
CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(temp.creature_id);
|
||||||
|
//Creature does not exist in database
|
||||||
|
if (!cInfo)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u has script for non-existing creature.", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Report any errors in event
|
||||||
|
if (temp.event_type >= EVENT_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u has incorrect event type. Maybe DB requires updated version of SD2.", i);
|
||||||
|
|
||||||
|
//No chance of this event occuring
|
||||||
|
if (temp.event_chance == 0)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u has 0 percent chance. Event will never trigger!", i);
|
||||||
|
|
||||||
|
//Chance above 100, force it to be 100
|
||||||
|
if (temp.event_chance > 100)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u are using event %u with more than 100 percent chance. Adjusting to 100 percent.", temp.creature_id, i);
|
||||||
|
temp.event_chance = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Individual event checks
|
||||||
|
switch (temp.event_type)
|
||||||
|
{
|
||||||
|
case EVENT_T_HP:
|
||||||
|
case EVENT_T_MANA:
|
||||||
|
case EVENT_T_TARGET_HP:
|
||||||
|
{
|
||||||
|
if (temp.event_param2 > 100)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u are using percentage event(%u) with param2 (MinPercent) > 100. Event will never trigger! ", temp.creature_id, i);
|
||||||
|
|
||||||
|
if (temp.event_param1 <= temp.event_param2)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u are using percentage event(%u) with param1 <= param2 (MaxPercent <= MinPercent). Event will never trigger! ", temp.creature_id, i);
|
||||||
|
|
||||||
|
if (temp.event_flags & EFLAG_REPEATABLE && !temp.event_param3 && !temp.event_param4)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u has param3 and param4=0 (RepeatMin/RepeatMax) but cannot be repeatable without timers. Removing EFLAG_REPEATABLE for event %u.", temp.creature_id, i);
|
||||||
|
temp.event_flags &= ~EFLAG_REPEATABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EVENT_T_SPELLHIT:
|
||||||
|
{
|
||||||
|
if (temp.event_param1)
|
||||||
|
{
|
||||||
|
SpellEntry const* pSpell = GetSpellStore()->LookupEntry(temp.event_param1);
|
||||||
|
if (!pSpell)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.event_param1, i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp.event_param2_s != -1 && temp.event_param2 != pSpell->SchoolMask)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.", temp.creature_id, temp.event_param1, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: fix this system with SPELL_SCHOOL_MASK. Current complicate things, using int32(-1) instead of just 0
|
||||||
|
//SPELL_SCHOOL_MASK_NONE = 0 and does not exist, thus it can not ever trigger or be used in SpellHit()
|
||||||
|
if (temp.event_param2_s != -1 && temp.event_param2_s > SPELL_SCHOOL_MASK_ALL)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.event_param2, i);
|
||||||
|
|
||||||
|
if (temp.event_param4 < temp.event_param3)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EVENT_T_RANGE:
|
||||||
|
case EVENT_T_OOC_LOS:
|
||||||
|
case EVENT_T_FRIENDLY_HP:
|
||||||
|
case EVENT_T_FRIENDLY_IS_CC:
|
||||||
|
case EVENT_T_FRIENDLY_MISSING_BUFF:
|
||||||
|
{
|
||||||
|
if (temp.event_param4 < temp.event_param3)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EVENT_T_TIMER:
|
||||||
|
case EVENT_T_TIMER_OOC:
|
||||||
|
{
|
||||||
|
if (temp.event_param2 < temp.event_param1)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u are using timed event(%u) with param2 < param1 (InitialMax < InitialMin). Event will never repeat.", temp.creature_id, i);
|
||||||
|
|
||||||
|
if (temp.event_param4 < temp.event_param3)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EVENT_T_KILL:
|
||||||
|
case EVENT_T_TARGET_CASTING:
|
||||||
|
{
|
||||||
|
if (temp.event_param2 < temp.event_param1)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EVENT_T_AGGRO:
|
||||||
|
case EVENT_T_DEATH:
|
||||||
|
case EVENT_T_EVADE:
|
||||||
|
case EVENT_T_SPAWNED:
|
||||||
|
case EVENT_T_REACHED_HOME:
|
||||||
|
{
|
||||||
|
if (temp.event_flags & EFLAG_REPEATABLE)
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Creature %u has EFLAG_REPEATABLE set. Event can never be repeatable. Removing flag for event %u.", temp.creature_id, i);
|
||||||
|
temp.event_flags &= ~EFLAG_REPEATABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32 j = 0; j < MAX_ACTIONS; j++)
|
||||||
|
{
|
||||||
|
temp.action[j].type = fields[10+(j*4)].GetUInt16();
|
||||||
|
temp.action[j].param1 = fields[11+(j*4)].GetUInt32();
|
||||||
|
temp.action[j].param2 = fields[12+(j*4)].GetUInt32();
|
||||||
|
temp.action[j].param3 = fields[13+(j*4)].GetUInt32();
|
||||||
|
|
||||||
|
//Report any errors in actions
|
||||||
|
switch (temp.action[j].type)
|
||||||
|
{
|
||||||
|
case ACTION_T_TEXT:
|
||||||
|
{
|
||||||
|
if (temp.action[j].param1_s < 0)
|
||||||
|
{
|
||||||
|
if (m_CreatureEventAI_TextMap.find(temp.action[j].param1_s) == m_CreatureEventAI_TextMap.end())
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 refrences non-existing entry in texts table.", i, j+1);
|
||||||
|
}
|
||||||
|
if (temp.action[j].param2_s < 0)
|
||||||
|
{
|
||||||
|
if (m_CreatureEventAI_TextMap.find(temp.action[j].param2_s) == m_CreatureEventAI_TextMap.end())
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 refrences non-existing entry in texts table.", i, j+1);
|
||||||
|
|
||||||
|
if (!temp.action[j].param1_s)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param2, but param1 is not set. Required for randomized text.", i, j+1);
|
||||||
|
}
|
||||||
|
if (temp.action[j].param3_s < 0)
|
||||||
|
{
|
||||||
|
if (m_CreatureEventAI_TextMap.find(temp.action[j].param3_s) == m_CreatureEventAI_TextMap.end())
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 refrences non-existing entry in texts table.", i, j+1);
|
||||||
|
|
||||||
|
if (!temp.action[j].param1_s || !temp.action[j].param2_s)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u has param3, but param1 and/or param2 is not set. Required for randomized text.", i, j+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_SET_FACTION:
|
||||||
|
if (temp.action[j].param1 !=0 && !GetFactionStore()->LookupEntry(temp.action[j].param1))
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant FactionId %u.", i, j+1, temp.action[j].param1);
|
||||||
|
temp.action[j].param1 = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
|
||||||
|
if (temp.action[j].param1 !=0 || temp.action[j].param2 !=0)
|
||||||
|
{
|
||||||
|
if (temp.action[j].param1 && !GetCreatureTemplateStore(temp.action[j].param1))
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, temp.action[j].param1);
|
||||||
|
temp.action[j].param1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp.action[j].param2 && !GetCreatureDisplayStore()->LookupEntry(temp.action[j].param2))
|
||||||
|
{
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, temp.action[j].param2);
|
||||||
|
temp.action[j].param2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_SOUND:
|
||||||
|
if (!GetSoundEntriesStore()->LookupEntry(temp.action[j].param1))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, temp.action[j].param1);
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
case ACTION_T_RANDOM_SOUND:
|
||||||
|
{
|
||||||
|
if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param1))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, temp.action[j].param1);
|
||||||
|
if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param2))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, temp.action[j].param2);
|
||||||
|
if(!GetSoundEntriesStore()->LookupEntry(temp.action[j].param3))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, temp.action[j].param3);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
case ACTION_T_CAST:
|
||||||
|
{
|
||||||
|
const SpellEntry *spell = GetSpellStore()->LookupEntry(temp.action[j].param1);
|
||||||
|
if (!spell)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (spell->RecoveryTime > 0 && temp.event_flags & EFLAG_REPEATABLE)
|
||||||
|
{
|
||||||
|
//output as debug for now, also because there's no general rule all spells have RecoveryTime
|
||||||
|
if (temp.event_param3 < spell->RecoveryTime)
|
||||||
|
debug_log("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1,temp.action[j].param1, spell->RecoveryTime, temp.event_param3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp.action[j].param2 >= TARGET_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_REMOVEAURASFROMSPELL:
|
||||||
|
{
|
||||||
|
if (!GetSpellStore()->LookupEntry(temp.action[j].param2))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
|
||||||
|
|
||||||
|
if (temp.action[j].param1 >= TARGET_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_QUEST_EVENT:
|
||||||
|
{
|
||||||
|
if (Quest const* qid = GetQuestTemplateStore(temp.action[j].param1))
|
||||||
|
{
|
||||||
|
if (!qid->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, temp.action[j].param1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
|
||||||
|
|
||||||
|
if (temp.action[j].param2 >= TARGET_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_QUEST_EVENT_ALL:
|
||||||
|
{
|
||||||
|
if (Quest const* qid = GetQuestTemplateStore(temp.action[j].param1))
|
||||||
|
{
|
||||||
|
if (!qid->HasFlag(QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, temp.action[j].param1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_CASTCREATUREGO:
|
||||||
|
{
|
||||||
|
if (!GetCreatureTemplateStore(temp.action[j].param1))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
|
||||||
|
|
||||||
|
if (!GetSpellStore()->LookupEntry(temp.action[j].param2))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
|
||||||
|
|
||||||
|
if (temp.action[j].param3 >= TARGET_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_CASTCREATUREGO_ALL:
|
||||||
|
{
|
||||||
|
if (!GetQuestTemplateStore(temp.action[j].param1))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant Quest entry %u.", i, j+1, temp.action[j].param1);
|
||||||
|
|
||||||
|
if (!GetSpellStore()->LookupEntry(temp.action[j].param2))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
//2nd param target
|
||||||
|
case ACTION_T_SUMMON_ID:
|
||||||
|
{
|
||||||
|
if (!GetCreatureTemplateStore(temp.action[j].param1))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
|
||||||
|
|
||||||
|
if (m_CreatureEventAI_Summon_Map.find(temp.action[j].param3) == m_CreatureEventAI_Summon_Map.end())
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u summons missing CreatureEventAI_Summon %u", i, j+1, temp.action[j].param3);
|
||||||
|
|
||||||
|
if (temp.action[j].param2 >= TARGET_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_KILLED_MONSTER:
|
||||||
|
{
|
||||||
|
if (!GetCreatureTemplateStore(temp.action[j].param1))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
|
||||||
|
|
||||||
|
if (temp.action[j].param2 >= TARGET_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_SUMMON:
|
||||||
|
{
|
||||||
|
if (!GetCreatureTemplateStore(temp.action[j].param1))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
|
||||||
|
|
||||||
|
if (temp.action[j].param2 >= TARGET_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_THREAT_SINGLE_PCT:
|
||||||
|
case ACTION_T_SET_UNIT_FLAG:
|
||||||
|
case ACTION_T_REMOVE_UNIT_FLAG:
|
||||||
|
if (temp.action[j].param2 >= TARGET_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
//3rd param target
|
||||||
|
case ACTION_T_SET_UNIT_FIELD:
|
||||||
|
if (temp.action[j].param1 < OBJECT_END || temp.action[j].param1 >= UNIT_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1);
|
||||||
|
if (temp.action[j].param3 >= TARGET_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACTION_T_SET_PHASE:
|
||||||
|
if (temp.action[j].param1 > 31)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set phase > 31. Phase mask cannot be used past phase 31.", i, j+1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACTION_T_INC_PHASE:
|
||||||
|
if (!temp.action[j].param1)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ACTION_T_SET_INST_DATA:
|
||||||
|
{
|
||||||
|
if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1);
|
||||||
|
|
||||||
|
if (temp.action[j].param2 > 4/*SPECIAL*/)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_SET_INST_DATA64:
|
||||||
|
{
|
||||||
|
if (!(temp.event_flags & EFLAG_NORMAL) && !(temp.event_flags & EFLAG_HEROIC))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u. Cannot set instance data without event flags (normal/heroic).", i, j+1);
|
||||||
|
|
||||||
|
if (temp.action[j].param2 >= TARGET_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_UPDATE_TEMPLATE:
|
||||||
|
{
|
||||||
|
if (!GetCreatureTemplateStore(temp.action[j].param1))
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, temp.action[j].param1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ACTION_T_RANDOM_SAY:
|
||||||
|
case ACTION_T_RANDOM_YELL:
|
||||||
|
case ACTION_T_RANDOM_TEXTEMOTE:
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u currently unused ACTION type. Did you forget to update database?", i, j+1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (temp.action[j].type >= ACTION_T_END)
|
||||||
|
sLog.outErrorDb("CreatureEventAI: Event %u Action %u has incorrect action type. Maybe DB requires updated version of SD2.", i, j+1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add to list
|
||||||
|
m_CreatureEventAI_Event_Map[creature_id].push_back(temp);
|
||||||
|
++Count;
|
||||||
|
} while (result->NextRow());
|
||||||
|
|
||||||
|
delete result;
|
||||||
|
|
||||||
|
sLog.outString();
|
||||||
|
sLog.outString(">> Loaded %u CreatureEventAI scripts", Count);
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
barGoLink bar(1);
|
||||||
|
bar.step();
|
||||||
|
sLog.outString();
|
||||||
|
sLog.outString(">> Loaded 0 CreatureEventAI scripts. DB table `creature_ai_scripts` is empty.");
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/game/CreatureEventAIMgr.h
Normal file
46
src/game/CreatureEventAIMgr.h
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||||
|
*
|
||||||
|
* 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 MANGOS_CREATURE_EAI_MGR_H
|
||||||
|
#define MANGOS_CREATURE_EAI_MGR_H
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
#include "CreatureEventAI.h"
|
||||||
|
|
||||||
|
class CreatureEventAIMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CreatureEventAIMgr(){};
|
||||||
|
~CreatureEventAIMgr(){};
|
||||||
|
|
||||||
|
void LoadCreatureEventAI_Texts();
|
||||||
|
void LoadCreatureEventAI_Summons();
|
||||||
|
void LoadCreatureEventAI_Scripts();
|
||||||
|
|
||||||
|
CreatureEventAI_Event_Map& GetCreatureEventAIMap() { return m_CreatureEventAI_Event_Map; }
|
||||||
|
CreatureEventAI_Summon_Map& GetCreatureEventAISummonMap() { return m_CreatureEventAI_Summon_Map; }
|
||||||
|
CreatureEventAI_TextMap& GetCreatureEventAITextMap() { return m_CreatureEventAI_TextMap; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
CreatureEventAI_Event_Map m_CreatureEventAI_Event_Map;
|
||||||
|
CreatureEventAI_Summon_Map m_CreatureEventAI_Summon_Map;
|
||||||
|
CreatureEventAI_TextMap m_CreatureEventAI_TextMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CreatureEAI_Mgr MaNGOS::Singleton<CreatureEventAIMgr>::Instance()
|
||||||
|
#endif
|
||||||
|
|
@ -633,6 +633,62 @@ namespace MaNGOS
|
||||||
|
|
||||||
// Unit checks
|
// Unit checks
|
||||||
|
|
||||||
|
class MostHPMissingInRange
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MostHPMissingInRange(Unit const* obj, float range, uint32 hp) : i_obj(obj), i_range(range), i_hp(hp) {}
|
||||||
|
bool operator()(Unit* u)
|
||||||
|
{
|
||||||
|
if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && u->GetMaxHealth() - u->GetHealth() > i_hp)
|
||||||
|
{
|
||||||
|
i_hp = u->GetMaxHealth() - u->GetHealth();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Unit const* i_obj;
|
||||||
|
float i_range;
|
||||||
|
uint32 i_hp;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FriendlyCCedInRange
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {}
|
||||||
|
bool operator()(Unit* u)
|
||||||
|
{
|
||||||
|
if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
|
||||||
|
(u->isFeared() || u->isCharmed() || u->isFrozen() || u->hasUnitState(UNIT_STAT_STUNNED) || u->hasUnitState(UNIT_STAT_CONFUSED)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Unit const* i_obj;
|
||||||
|
float i_range;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FriendlyMissingBuffInRange
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {}
|
||||||
|
bool operator()(Unit* u)
|
||||||
|
{
|
||||||
|
if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
|
||||||
|
!(u->HasAura(i_spell, 0) || u->HasAura(i_spell, 1) || u->HasAura(i_spell, 2)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Unit const* i_obj;
|
||||||
|
float i_range;
|
||||||
|
uint32 i_spell;
|
||||||
|
};
|
||||||
|
|
||||||
class AnyUnfriendlyUnitInObjectRangeCheck
|
class AnyUnfriendlyUnitInObjectRangeCheck
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -62,5 +62,13 @@ class MANGOS_DLL_SPEC InstanceData
|
||||||
|
|
||||||
//called on creature creation
|
//called on creature creation
|
||||||
virtual void OnCreatureCreate(Creature * /*creature*/, uint32 /*creature_entry*/) {}
|
virtual void OnCreatureCreate(Creature * /*creature*/, uint32 /*creature_entry*/) {}
|
||||||
|
|
||||||
|
//All-purpose data storage 64 bit
|
||||||
|
virtual uint64 GetData64(uint32 /*Data*/) { return 0; }
|
||||||
|
virtual void SetData64(uint32 /*Data*/, uint64 /*Value*/) { }
|
||||||
|
|
||||||
|
//All-purpose data storage 32 bit
|
||||||
|
virtual uint32 GetData(uint32 /*Type*/) { return 0; }
|
||||||
|
virtual void SetData(uint32 /*Type*/, uint32 /*Data*/) {}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,10 @@ libmangosgame_a_SOURCES = \
|
||||||
CreatureAIRegistry.h \
|
CreatureAIRegistry.h \
|
||||||
CreatureAISelector.cpp \
|
CreatureAISelector.cpp \
|
||||||
CreatureAISelector.h \
|
CreatureAISelector.h \
|
||||||
|
CreatureEventAI.cpp \
|
||||||
|
CreatureEventAI.h \
|
||||||
|
CreatureEventAIMgr.cpp \
|
||||||
|
CreatureEventAIMgr.h \
|
||||||
Creature.cpp \
|
Creature.cpp \
|
||||||
Creature.h \
|
Creature.h \
|
||||||
DBCEnums.h \
|
DBCEnums.h \
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
#include "AchievementMgr.h"
|
#include "AchievementMgr.h"
|
||||||
#include "AuctionHouseMgr.h"
|
#include "AuctionHouseMgr.h"
|
||||||
#include "ObjectMgr.h"
|
#include "ObjectMgr.h"
|
||||||
|
#include "CreatureEventAIMgr.h"
|
||||||
#include "SpellMgr.h"
|
#include "SpellMgr.h"
|
||||||
#include "Chat.h"
|
#include "Chat.h"
|
||||||
#include "DBCStores.h"
|
#include "DBCStores.h"
|
||||||
|
|
@ -1339,6 +1340,15 @@ void World::SetInitialWorldSettings()
|
||||||
sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls
|
sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls
|
||||||
objmgr.LoadDbScriptStrings();
|
objmgr.LoadDbScriptStrings();
|
||||||
|
|
||||||
|
sLog.outString( "Loading CreatureEventAI Texts...");
|
||||||
|
CreatureEAI_Mgr.LoadCreatureEventAI_Texts();
|
||||||
|
|
||||||
|
sLog.outString( "Loading CreatureEventAI Summons...");
|
||||||
|
CreatureEAI_Mgr.LoadCreatureEventAI_Summons();
|
||||||
|
|
||||||
|
sLog.outString( "Loading CreatureEventAI Scripts...");
|
||||||
|
CreatureEAI_Mgr.LoadCreatureEventAI_Scripts();
|
||||||
|
|
||||||
sLog.outString( "Initializing Scripts..." );
|
sLog.outString( "Initializing Scripts..." );
|
||||||
if(!LoadScriptingModule())
|
if(!LoadScriptingModule())
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "7621"
|
#define REVISION_NR "7622"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
|
|
@ -573,6 +573,18 @@
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\game\DynamicObject.h">
|
RelativePath="..\..\src\game\DynamicObject.h">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAI.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAI.h">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAIMgr.cpp">
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAIMgr.h">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\game\FleeingMovementGenerator.cpp">
|
RelativePath="..\..\src\game\FleeingMovementGenerator.cpp">
|
||||||
</File>
|
</File>
|
||||||
|
|
|
||||||
|
|
@ -938,6 +938,22 @@
|
||||||
RelativePath="..\..\src\game\DynamicObject.h"
|
RelativePath="..\..\src\game\DynamicObject.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAI.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAI.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAIMgr.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAIMgr.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\game\FleeingMovementGenerator.cpp"
|
RelativePath="..\..\src\game\FleeingMovementGenerator.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -940,6 +940,22 @@
|
||||||
RelativePath="..\..\src\game\DynamicObject.h"
|
RelativePath="..\..\src\game\DynamicObject.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAI.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAI.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAIMgr.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\game\CreatureEventAIMgr.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\src\game\FleeingMovementGenerator.cpp"
|
RelativePath="..\..\src\game\FleeingMovementGenerator.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue