aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlaymoira <none@none>2008-12-11 21:32:08 +0100
committerBlaymoira <none@none>2008-12-11 21:32:08 +0100
commit236553f40804c30d4ed8f1a29e01a76dd7be809a (patch)
tree5b7e5d38aa0e1e002a932fb86d2c01e0289b1599
parent5d003e3a6079388149473f0a3da6089b47404a29 (diff)
parentf2028e1583bf935fc3d096748d5b07428cdcaa00 (diff)
*Merged 459
--HG-- branch : trunk
-rw-r--r--sql/updates/444_world.sql36
-rw-r--r--sql/updates/452_world.sql9
-rw-r--r--sql/updates/455_world.sql14
-rw-r--r--sql/updates/full/world_script.sql1
-rw-r--r--sql/world.sql67
-rw-r--r--src/bindings/scripts/include/sc_creature.cpp4
-rw-r--r--src/bindings/scripts/include/sc_creature.h8
-rw-r--r--src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp83
-rw-r--r--src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_broggok.cpp38
-rw-r--r--src/bindings/scripts/scripts/zone/uldaman/instance_uldaman.cpp229
-rw-r--r--src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp12
-rw-r--r--src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp13
-rw-r--r--src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp34
-rw-r--r--src/game/Cell.h1
-rw-r--r--src/game/CellImpl.h48
-rw-r--r--src/game/Chat.cpp22
-rw-r--r--src/game/Chat.h18
-rw-r--r--src/game/Creature.cpp12
-rw-r--r--src/game/Creature.h21
-rw-r--r--src/game/GameObject.cpp2
-rw-r--r--src/game/GridDefines.h25
-rw-r--r--src/game/Level2.cpp1357
-rw-r--r--src/game/Level3.cpp23
-rw-r--r--src/game/MotionMaster.cpp25
-rw-r--r--src/game/MotionMaster.h1
-rw-r--r--src/game/MovementGeneratorImpl.h3
-rw-r--r--src/game/Object.cpp19
-rw-r--r--src/game/Object.h2
-rw-r--r--src/game/ObjectMgr.cpp16
-rw-r--r--src/game/ObjectMgr.h2
-rw-r--r--src/game/Player.cpp17
-rw-r--r--src/game/RandomMovementGenerator.h2
-rw-r--r--src/game/SharedDefines.h9
-rw-r--r--src/game/Spell.cpp94
-rw-r--r--src/game/Spell.h3
-rw-r--r--src/game/SpellAuras.cpp109
-rw-r--r--src/game/SpellMgr.cpp33
-rw-r--r--src/game/SpellMgr.h17
-rw-r--r--src/game/Unit.cpp236
-rw-r--r--src/game/Unit.h13
-rw-r--r--src/game/WaypointManager.cpp406
-rw-r--r--src/game/WaypointManager.h82
-rw-r--r--src/game/WaypointMovementGenerator.cpp321
-rw-r--r--src/game/WaypointMovementGenerator.h72
-rw-r--r--src/game/World.cpp28
-rw-r--r--src/game/World.h1
-rw-r--r--src/shared/Database/SQLStorage.cpp4
47 files changed, 1823 insertions, 1769 deletions
diff --git a/sql/updates/444_world.sql b/sql/updates/444_world.sql
new file mode 100644
index 00000000000..004cf626f88
--- /dev/null
+++ b/sql/updates/444_world.sql
@@ -0,0 +1,36 @@
+DROP TABLE IF EXISTS `waypoint_data`;
+
+CREATE TABLE `waypoint_data` (
+ `id` int(10) unsigned NOT NULL default '0' COMMENT 'Creature GUID',
+ `point` mediumint(8) unsigned NOT NULL default '0',
+ `position_x` float NOT NULL default '0',
+ `position_y` float NOT NULL default '0',
+ `position_z` float NOT NULL default '0',
+ `delay` int(10) unsigned NOT NULL default '0',
+ `move_flag` tinyint(1) NOT NULL default '0',
+ `action` int(11) NOT NULL default '0',
+ `action_chance` smallint(3) NOT NULL default '100',
+ `wpguid` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `waypoint_scripts`;
+
+CREATE TABLE `waypoint_scripts` (
+ `id` int(11) unsigned NOT NULL default '0',
+ `delay` int(11) unsigned NOT NULL default '0',
+ `command` int(11) unsigned NOT NULL default '0',
+ `datalong` int(11) unsigned NOT NULL default '0',
+ `datalong2` int(11) unsigned NOT NULL default '0',
+ `dataint` int(11) unsigned NOT NULL default '0',
+ `x` float NOT NULL default '0',
+ `y` float NOT NULL default '0',
+ `z` float NOT NULL default '0',
+ `o` float NOT NULL default '0',
+ `guid` int(11) NOT NULL default '0',
+ PRIMARY KEY (`guid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+ALTER TABLE `creature_addon`
+ ADD `path_id` int(11) unsigned NOT NULL default '0' AFTER `guid`;
+ALTER TABLE `creature_template_addon`
+ ADD `path_id` int(11) unsigned NOT NULL default '0' AFTER `entry`;
diff --git a/sql/updates/452_world.sql b/sql/updates/452_world.sql
new file mode 100644
index 00000000000..c5ac7f87cfb
--- /dev/null
+++ b/sql/updates/452_world.sql
@@ -0,0 +1,9 @@
+-- link gift of the wild to mark of the wild
+
+DELETE FROM spell_chain WHERE spell_id = 21849;
+DELETE FROM spell_chain WHERE spell_id = 21850;
+DELETE FROM spell_chain WHERE spell_id = 26991;
+
+INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (21849,0,1126,1,0);
+INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (21850,21849,1126,2,0);
+INSERT INTO spell_chain (spell_id,prev_spell,first_spell,rank,req_spell) VALUES (26991,21850,1126,3,0); \ No newline at end of file
diff --git a/sql/updates/455_world.sql b/sql/updates/455_world.sql
new file mode 100644
index 00000000000..74c52f164b0
--- /dev/null
+++ b/sql/updates/455_world.sql
@@ -0,0 +1,14 @@
+-- demon fire
+update creature_template set spell1 = 40029, flags_extra = 128, scriptname = '' where entry = 23069;
+-- pillar of fire
+update creature_template set spell1 = 43218, flags_extra = 128, scriptname = '' where entry = 24187;
+-- Broggok Poison Cloud
+update creature_template set spell1 = 30914, flags_extra = 128, scriptname = '' where entry = 17662;
+
+
+INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (43468, 44007, 1, 'Storm Eye Safe Zone');
+INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (43658, 43653, 0, 'Electrical Arc Visual');
+INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (43658, 43654, 0, 'Electrical Arc Visual');
+INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (43658, 43655, 0, 'Electrical Arc Visual');
+INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (43658, 43656, 0, 'Electrical Arc Visual');
+INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (43658, 43659, 0, 'Electrical Arc Visual'); \ No newline at end of file
diff --git a/sql/updates/full/world_script.sql b/sql/updates/full/world_script.sql
index e1bd272425a..278ed085a65 100644
--- a/sql/updates/full/world_script.sql
+++ b/sql/updates/full/world_script.sql
@@ -19,7 +19,6 @@ UPDATE `creature_template` SET `ScriptName` = 'boss_fenstalker' WHERE `entry` =2
UPDATE `creature_template` SET `ScriptName` = 'boss_darkheart' WHERE `entry` =24246;
UPDATE `creature_template` SET `ScriptName` = 'boss_koragg' WHERE `entry` =24247;
UPDATE `creature_template` SET `ScriptName` = 'boss_zuljin' WHERE `entry` =23863;
-UPDATE `creature_template` SET `ScriptName` = 'do_nothing' WHERE `entry` = '24187';
UPDATE `creature_template` SET `ScriptName` = 'mob_zuljin_vortex' WHERE `entry` = '24136';
UPDATE `creature_template` SET `ScriptName` = 'npc_zulaman_hostage' WHERE `entry` IN (23790, 23999, 24024, 24001);
diff --git a/sql/world.sql b/sql/world.sql
index 01c94db3ce6..ca5af56edd1 100644
--- a/sql/world.sql
+++ b/sql/world.sql
@@ -220,6 +220,7 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `creature_addon`;
CREATE TABLE `creature_addon` (
`guid` int(10) unsigned NOT NULL default '0',
+ `path_id` int(11) unsigned NOT NULL default '0',
`mount` mediumint(8) unsigned NOT NULL default '0',
`bytes0` int(10) unsigned NOT NULL default '0',
`bytes1` int(10) unsigned NOT NULL default '0',
@@ -337,39 +338,62 @@ LOCK TABLES `creature_model_info` WRITE;
/*!40000 ALTER TABLE `creature_model_info` ENABLE KEYS */;
UNLOCK TABLES;
+
--
--- Table structure for table `creature_movement`
+-- Table structure for table `waypoint_data`
--
-DROP TABLE IF EXISTS `creature_movement`;
-CREATE TABLE `creature_movement` (
- `id` int(10) unsigned NOT NULL COMMENT 'Creature GUID',
+DROP TABLE IF EXISTS `waypoint_data`;
+CREATE TABLE `waypoint_data` (
+ `id` int(10) unsigned NOT NULL default '0' COMMENT 'Creature GUID',
`point` mediumint(8) unsigned NOT NULL default '0',
`position_x` float NOT NULL default '0',
`position_y` float NOT NULL default '0',
`position_z` float NOT NULL default '0',
- `waittime` int(10) unsigned NOT NULL default '0',
- `text1` text,
- `text2` text,
- `text3` text,
- `text4` text,
- `text5` text,
- `emote` mediumint(8) unsigned NOT NULL default '0',
- `spell` mediumint(8) unsigned NOT NULL default '0',
- `wpguid` int(11) NOT NULL default '0',
- `orientation` float NOT NULL default '0',
- `model1` mediumint(9) NOT NULL default '0',
- `model2` mediumint(9) NOT NULL default '0',
- PRIMARY KEY (`id`,`point`)
-) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Creature System';
+ `delay` int(10) unsigned NOT NULL default '0',
+ `move_flag` tinyint(1) NOT NULL default '0',
+ `action` int(11) NOT NULL default '0',
+ `action_chance` smallint(3) NOT NULL default '100',
+ `wpguid` int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Dumping data for table `creature_movement`
+--
+
+LOCK TABLES `waypoint_data` WRITE;
+/*!40000 ALTER TABLE `waypoint_data` DISABLE KEYS */;
+/*!40000 ALTER TABLE `waypoint_data` ENABLE KEYS */;
+UNLOCK TABLES;
+
+
+--
+-- Table structure for table `waypoint_scripts`
+--
+
+DROP TABLE IF EXISTS `waypoint_scripts`;
+CREATE TABLE `waypoint_scripts` (
+ `id` int(11) unsigned NOT NULL default '0',
+ `delay` int(11) unsigned NOT NULL default '0',
+ `command` int(11) unsigned NOT NULL default '0',
+ `datalong` int(11) unsigned NOT NULL default '0',
+ `datalong2` int(11) unsigned NOT NULL default '0',
+ `dataint` int(11) unsigned NOT NULL default '0',
+ `x` float NOT NULL default '0',
+ `y` float NOT NULL default '0',
+ `z` float NOT NULL default '0',
+ `o` float NOT NULL default '0',
+ `guid` int(11) NOT NULL default '0',
+ PRIMARY KEY (`guid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Dumping data for table `creature_movement`
--
-LOCK TABLES `creature_movement` WRITE;
-/*!40000 ALTER TABLE `creature_movement` DISABLE KEYS */;
-/*!40000 ALTER TABLE `creature_movement` ENABLE KEYS */;
+LOCK TABLES `waypoint_scripts` WRITE;
+/*!40000 ALTER TABLE `waypoint_scripts` DISABLE KEYS */;
+/*!40000 ALTER TABLE `waypoint_scripts` ENABLE KEYS */;
UNLOCK TABLES;
--
@@ -533,6 +557,7 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `creature_template_addon`;
CREATE TABLE `creature_template_addon` (
`entry` mediumint(8) unsigned NOT NULL default '0',
+ `path_id' int(11) unsigned NOT NULL default '0',
`mount` mediumint(8) unsigned NOT NULL default '0',
`bytes0` int(10) unsigned NOT NULL default '0',
`bytes1` int(10) unsigned NOT NULL default '0',
diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp
index a3c185391cc..e3bcc2129cc 100644
--- a/src/bindings/scripts/include/sc_creature.cpp
+++ b/src/bindings/scripts/include/sc_creature.cpp
@@ -220,10 +220,10 @@ void ScriptedAI::DoStopAttack()
void ScriptedAI::DoCast(Unit* victim, uint32 spellId, bool triggered)
{
- if (!victim || m_creature->IsNonMeleeSpellCasted(false))
+ if (!victim || m_creature->hasUnitState(UNIT_STAT_CASTING))
return;
- m_creature->StopMoving();
+ //m_creature->StopMoving();
m_creature->CastSpell(victim, spellId, triggered);
}
diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h
index 01f5df473c1..c0c09d70e34 100644
--- a/src/bindings/scripts/include/sc_creature.h
+++ b/src/bindings/scripts/include/sc_creature.h
@@ -183,13 +183,13 @@ struct TRINITY_DLL_DECL Scripted_NoMovementAI : public ScriptedAI
void AttackStart(Unit *);
};
-struct TRINITY_DLL_DECL NullCreatureAI : public CreatureAI
+struct TRINITY_DLL_DECL NullCreatureAI : public ScriptedAI
{
- NullCreatureAI(Creature* c) : m_creature(c) {}
+ NullCreatureAI(Creature* c) : ScriptedAI(c) {}
~NullCreatureAI() {}
- Creature *m_creature;
-
+ void Reset() {}
+ void Aggro(Unit*) {}
void MoveInLineOfSight(Unit *) {}
void AttackStart(Unit *) {}
void EnterEvadeMode() {}
diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp
index 272bd0bd2b0..46a05fcf0cc 100644
--- a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp
+++ b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp
@@ -1780,73 +1780,9 @@ struct TRINITY_DLL_DECL mob_parasitic_shadowfiendAI : public ScriptedAI
}
};
-struct TRINITY_DLL_DECL demonfireAI : public ScriptedAI
+struct TRINITY_DLL_DECL blade_of_azzinothAI : public NullCreatureAI
{
- demonfireAI(Creature *c) : ScriptedAI(c)
- {
- pInstance = ((ScriptedInstance*)c->GetInstanceData());
- Reset();
- }
-
- ScriptedInstance* pInstance;
- uint64 IllidanGUID;
- bool IsTrigger;
- bool DemonFire;
- uint32 CheckTimer;
- uint32 DespawnTimer;
-
- void Reset()
- {
- if(pInstance)
- IllidanGUID = pInstance->GetData64(DATA_ILLIDANSTORMRAGE);
- else
- IllidanGUID = 0;
-
- IsTrigger = false;
- DemonFire = false;
-
- CheckTimer = 5000;
- DespawnTimer = 78000; //spell duration, core bug, cannot despawn self
- }
-
- void Aggro(Unit *who) {}
- void AttackStart(Unit* who) {}
- void MoveInLineOfSight(Unit *who){}
-
- void UpdateAI(const uint32 diff)
- {
- if(IsTrigger)
- return;
-
- if(!DemonFire)
- DoCast(m_creature, SPELL_DEMON_FIRE); //duration 60s
-
- if(CheckTimer < diff)
- {
- GETUNIT(Illidan, IllidanGUID);
- if(!Illidan || !Illidan->HasUnitMovementFlag(MOVEMENTFLAG_LEVITATING))
- {
- m_creature->SetVisibility(VISIBILITY_OFF);
- m_creature->setDeathState(JUST_DIED);
- return;
- }else CheckTimer = 5000;
- }else CheckTimer -= diff;
-
- if(DespawnTimer < diff)
- {
- m_creature->SetVisibility(VISIBILITY_OFF);
- m_creature->setDeathState(JUST_DIED);
- }else DespawnTimer -= diff;
- }
-};
-
-struct TRINITY_DLL_DECL blade_of_azzinothAI : public ScriptedAI
-{
- blade_of_azzinothAI(Creature* c) : ScriptedAI(c) {}
- void Reset() {}
- void Aggro(Unit *who) {}
- void AttackStart(Unit* who) { }
- void MoveInLineOfSight(Unit* who) { }
+ blade_of_azzinothAI(Creature* c) : NullCreatureAI(c) {}
void SpellHit(Unit *caster, const SpellEntry *spell)
{
@@ -2060,15 +1996,14 @@ void boss_illidan_stormrageAI::CastEyeBlast()
final.x = 2 * final.x - initial.x;
final.y = 2 * final.y - initial.y;
- Creature* Trigger = m_creature->SummonCreature(DEMON_FIRE, initial.x, initial.y, initial.z, 0, TEMPSUMMON_TIMED_DESPAWN, 13000);
+ Creature* Trigger = m_creature->SummonTrigger(initial.x, initial.y, initial.z, 0, 13000);
if(!Trigger) return;
- ((demonfireAI*)Trigger->AI())->IsTrigger = true;
Trigger->SetSpeed(MOVE_WALK, 3);
Trigger->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE);
Trigger->GetMotionMaster()->MovePoint(0, final.x, final.y, final.z);
- Trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ //Trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_creature->SetUInt64Value(UNIT_FIELD_TARGET, Trigger->GetGUID());
DoCast(Trigger, SPELL_EYE_BLAST);
}
@@ -2225,11 +2160,6 @@ CreatureAI* GetAI_shadow_demon(Creature *_Creature)
return new shadow_demonAI (_Creature);
}
-CreatureAI* GetAI_demonfire(Creature *_Creature)
-{
- return new demonfireAI (_Creature);
-}
-
CreatureAI* GetAI_blade_of_azzinoth(Creature *_Creature)
{
return new blade_of_azzinothAI (_Creature);
@@ -2287,11 +2217,6 @@ void AddSC_boss_illidan()
newscript->RegisterSelf();
newscript = new Script;
- newscript->Name="mob_demon_fire";
- newscript->GetAI = GetAI_demonfire;
- newscript->RegisterSelf();
-
- newscript = new Script;
newscript->Name = "mob_parasitic_shadowfiend";
newscript->GetAI = GetAI_parasitic_shadowfiend;
newscript->RegisterSelf();
diff --git a/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_broggok.cpp b/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_broggok.cpp
index 1431be7dd51..e8797184fbc 100644
--- a/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_broggok.cpp
+++ b/src/bindings/scripts/scripts/zone/hellfire_citadel/blood_furnace/boss_broggok.cpp
@@ -79,44 +79,11 @@ struct TRINITY_DLL_DECL boss_broggokAI : public ScriptedAI
}
};
-struct TRINITY_DLL_DECL mob_broggok_poisoncloudAI : public ScriptedAI
-{
- mob_broggok_poisoncloudAI(Creature *c) : ScriptedAI(c) {Reset();}
-
- bool Start;
-
- void Reset()
- {
- Start = false;
- }
-
- void Aggro(Unit* who)
- {
- }
-
- void UpdateAI(const uint32 diff)
- {
- if(!Start)
- {
- m_creature->SetUInt32Value(UNIT_NPC_FLAGS,0);
- m_creature->setFaction(45);
- m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- Start = true;
- DoCast(m_creature,SPELL_POISON);
- }
- }
-};
-
CreatureAI* GetAI_boss_broggokAI(Creature *_Creature)
{
return new boss_broggokAI (_Creature);
}
-CreatureAI* GetAI_mob_broggok_poisoncloudAI(Creature *_Creature)
-{
- return new mob_broggok_poisoncloudAI (_Creature);
-}
-
void AddSC_boss_broggok()
{
Script *newscript;
@@ -124,9 +91,4 @@ void AddSC_boss_broggok()
newscript->Name="boss_broggok";
newscript->GetAI = GetAI_boss_broggokAI;
newscript->RegisterSelf();
-
- newscript = new Script;
- newscript->Name="mob_broggok_poisoncloud";
- newscript->GetAI = GetAI_mob_broggok_poisoncloudAI;
- newscript->RegisterSelf();
}
diff --git a/src/bindings/scripts/scripts/zone/uldaman/instance_uldaman.cpp b/src/bindings/scripts/scripts/zone/uldaman/instance_uldaman.cpp
index 60776ec9c65..6ae07954950 100644
--- a/src/bindings/scripts/scripts/zone/uldaman/instance_uldaman.cpp
+++ b/src/bindings/scripts/scripts/zone/uldaman/instance_uldaman.cpp
@@ -31,58 +31,54 @@
struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance
{
- instance_uldaman(Map *Map) : ScriptedInstance(Map) {
+ instance_uldaman(Map *map) : ScriptedInstance(map)
+ {
Initialize();
- stoneKeepersCounter = 0;
- altarOfTheKeeperCounter = 0;
- vaultWalkerCounter = 0;
- earthenGuardianCounter = 0;
- archaedasWallMinionsCounter = 0;
- whoWokeArchaedasGUID = 0;
};
+ void Initialize()
+ {
+ archaedasGUID = 0;
+ altarOfTheKeeperTempleDoor = 0;
+ archaedasTempleDoor = 0;
+ ancientVaultDoor = 0;
+ whoWokeArchaedasGUID = 0;
+ }
- Creature* archaedas;
- uint64 stoneKeeper[4];
- uint32 stoneKeepersCounter;
-
- uint64 altarOfTheKeeperCount[5];
- uint32 altarOfTheKeeperCounter;
-
- uint64 vaultWalker[4];
- uint32 vaultWalkerCounter;
-
- uint64 earthenGuardian[6];
- uint32 earthenGuardianCounter;
-
- uint64 archaedasWallMinions[100]; // minions lined up around the wall
- uint32 archaedasWallMinionsCounter;
-
- GameObject *altarOfTheKeeperTempleDoor;
- GameObject *archaedasTempleDoor;
- GameObject *ancientVaultDoor;
-
+ uint64 archaedasGUID;
+ uint64 altarOfTheKeeperTempleDoor;
+ uint64 archaedasTempleDoor;
+ uint64 ancientVaultDoor;
uint64 whoWokeArchaedasGUID;
- void OnObjectCreate (GameObject* go) {
- switch (go->GetEntry()) {
+ std::vector<uint64> stoneKeeper;
+ std::vector<uint64> altarOfTheKeeperCount;
+ std::vector<uint64> vaultWalker;
+ std::vector<uint64> earthenGuardian;
+ std::vector<uint64> archaedasWallMinions; // minions lined up around the wall
+
+ void OnObjectCreate (GameObject* go)
+ {
+ switch (go->GetEntry())
+ {
case ALTAR_OF_THE_KEEPER_TEMPLE_DOOR: // lock the door
- altarOfTheKeeperTempleDoor = go;
+ altarOfTheKeeperTempleDoor = go->GetGUID();
break;
case ARCHAEDAS_TEMPLE_DOOR:
- archaedasTempleDoor = go;
+ archaedasTempleDoor = go->GetGUID();
break;
case ANCIENT_VAULT_DOOR:
go->SetUInt32Value(GAMEOBJECT_STATE,1);
go->SetUInt32Value(GAMEOBJECT_FLAGS, 33);
- ancientVaultDoor = go;
+ ancientVaultDoor = go->GetGUID();
break;
}
}
- void SetFrozenState(Creature *creature) {
+ void SetFrozenState(Creature *creature)
+ {
creature->setFaction(35);
creature->RemoveAllAuras();
//creature->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_ANIMATION_FROZEN);
@@ -90,121 +86,137 @@ struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance
creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
}
- void OpenDoor (GameObject *go) {
- if (!go) return;
+ void OpenDoor(uint64 guid)
+ {
+ GameObject *go = instance->GetGameObjectInMap(guid);
+ if(!go)
+ return;
+
go->SetUInt32Value(GAMEOBJECT_FLAGS, 33);
go->SetUInt32Value(GAMEOBJECT_STATE, 0);
}
-
-
- void ActivateStoneKeepers() {
- Creature *target;
- uint32 counter = stoneKeepersCounter;
- // error_log ("ActivateStoneKeepers");
- // error_log ("counter = %d", counter);
- for (; counter>0; ) {
- target = (Creature *) Unit::GetUnit(*archaedas,stoneKeeper[--counter]);
- if (!target || !target->isAlive() || target->getFaction()==14) continue;
- target->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE);
+ void ActivateStoneKeepers()
+ {
+ for(std::vector<uint64>::iterator i = stoneKeeper.begin(); i != stoneKeeper.end(); ++i)
+ {
+ Creature *target = instance->GetCreatureInMap(*i);
+ if (!target || !target->isAlive() || target->getFaction()==14)
+ continue;
+ target->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE);
target->setFaction(14);
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
return; // only want the first one we find
}
- // error_log ("opening doors");
// if we get this far than all four are dead so open the door
SetData (NULL, 0);
}
- void ActivateWallMinions() {
- Creature *target;
- uint32 counter = archaedasWallMinionsCounter;
- for (; counter>0; ) {
- target = (Creature *) Unit::GetUnit(*archaedas,archaedasWallMinions[--counter]);
- if (!target || !target->isAlive() || target->getFaction()==14) continue;
- archaedas->CastSpell (target, SPELL_AWAKEN_VAULT_WALKER, true);
+ void ActivateWallMinions()
+ {
+ Creature *archaedas = instance->GetCreatureInMap(archaedasGUID);
+ if(!archaedas)
+ return;
+
+ for(std::vector<uint64>::iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i)
+ {
+ Creature *target = instance->GetCreatureInMap(*i);
+ if (!target || !target->isAlive() || target->getFaction()==14)
+ continue;
+ archaedas->CastSpell(target, SPELL_AWAKEN_VAULT_WALKER, true);
target->CastSpell(target, SPELL_ARCHAEDAS_AWAKEN,true);
return; // only want the first one we find
}
}
// used when Archaedas dies. All active minions must be despawned.
- void DeActivateMinions() {
- Creature *target;
- uint32 counter = archaedasWallMinionsCounter;
-
+ void DeActivateMinions()
+ {
// first despawn any aggroed wall minions
- for (; counter>0; ) {
- target = (Creature *) Unit::GetUnit(*archaedas,archaedasWallMinions[--counter]);
- if (!target || target->isDead() || target->getFaction()!=14) continue;
- target->RemoveFromWorld();
- target->AI()->EnterEvadeMode(); // need this b/c it still attacks even when removed
+ for(std::vector<uint64>::iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i)
+ {
+ Creature *target = instance->GetCreatureInMap(*i);
+ if (!target || target->isDead() || target->getFaction()!=14)
+ continue;
+ target->setDeathState(JUST_DIED);
+ target->RemoveCorpse();
}
// Vault Walkers
- for (counter=0; counter<4; counter++) {
- target = (Creature *) Unit::GetUnit(*archaedas,vaultWalker[counter]);
- if (!target || target->isDead() || target->getFaction() != 14) continue;
- target->RemoveFromWorld();
- target->AI()->EnterEvadeMode(); // need this b/c it sill attacks even when removed
+ for(std::vector<uint64>::iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i)
+ {
+ Creature *target = instance->GetCreatureInMap(*i);
+ if (!target || target->isDead() || target->getFaction()!=14)
+ continue;
+ target->setDeathState(JUST_DIED);
+ target->RemoveCorpse();
}
// Earthen Guardians
- for (counter=0; counter<6; counter++) {
- target = (Creature *) Unit::GetUnit(*archaedas,earthenGuardian[counter]);
- if (!target || target->isDead() || target->getFaction() != 14) continue;
- target->RemoveFromWorld();
- target->AI()->EnterEvadeMode(); // need this b/c it sill attacks even when removed
+ for(std::vector<uint64>::iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i)
+ {
+ Creature *target = instance->GetCreatureInMap(*i);
+ if (!target || target->isDead() || target->getFaction()!=14)
+ continue;
+ target->setDeathState(JUST_DIED);
+ target->RemoveCorpse();
}
}
- void ActivateArchaedas(uint64 target) {
-
- Unit *victim = Unit::GetUnit(*archaedas, target);
- archaedas->CastSpell(archaedas, SPELL_ARCHAEDAS_AWAKEN,false);
- whoWokeArchaedasGUID = target;
+ void ActivateArchaedas(uint64 target)
+ {
+ Creature *archaedas = instance->GetCreatureInMap(archaedasGUID);
+ if(!archaedas)
+ return;
+
+ if(Unit *victim = Unit::GetUnit(*archaedas, target))
+ {
+ archaedas->CastSpell(archaedas, SPELL_ARCHAEDAS_AWAKEN,false);
+ whoWokeArchaedasGUID = target;
+ }
}
- void RespawnMinions() {
- Creature *target;
- uint32 counter = archaedasWallMinionsCounter;
-
- // first respawn any wall minions
- for (; counter>0; ) {
- target = (Creature *) Unit::GetUnit(*archaedas,archaedasWallMinions[--counter]);
- if (target && target->isDead()) {
+ void RespawnMinions()
+ {
+ // first respawn any aggroed wall minions
+ for(std::vector<uint64>::iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i)
+ {
+ Creature *target = instance->GetCreatureInMap(*i);
+ if (target && target->isDead())
+ {
target->Respawn();
target->GetMotionMaster()->MoveTargetedHome();
- //target->AI()->EnterEvadeMode();
SetFrozenState(target);
}
}
// Vault Walkers
- for (counter=0; counter<4; counter++) {
- target = (Creature *) Unit::GetUnit(*archaedas,vaultWalker[counter]);
- if (target && target->isDead()) {
+ for(std::vector<uint64>::iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i)
+ {
+ Creature *target = instance->GetCreatureInMap(*i);
+ if (target && target->isDead())
+ {
target->Respawn();
target->GetMotionMaster()->MoveTargetedHome();
- // target->AI()->EnterEvadeMode();
SetFrozenState(target);
}
}
// Earthen Guardians
- for (counter=0; counter<6; counter++) {
- target = (Creature *) Unit::GetUnit(*archaedas,earthenGuardian[counter]);
- if (target && target->isDead()) {
+ for(std::vector<uint64>::iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i)
+ {
+ Creature *target = instance->GetCreatureInMap(*i);
+ if (target && target->isDead())
+ {
target->Respawn();
target->GetMotionMaster()->MoveTargetedHome();
- //target->AI()->EnterEvadeMode();
SetFrozenState(target);
}
}
-
}
- void SetData (uint32 type, uint32 data) {
+ void SetData (uint32 type, uint32 data)
+ {
//error_log ("SetData: data = %d", data);
if (data==0) OpenDoor (altarOfTheKeeperTempleDoor);
if (data==0) OpenDoor (archaedasTempleDoor);
@@ -216,8 +228,11 @@ struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance
}
- void SetData64 (uint32 type, uint64 data) {
- if (type==0 ) { // Archaedas
+ void SetData64 (uint32 type, uint64 data)
+ {
+ // Archaedas
+ if (type==0 )
+ {
ActivateArchaedas (data);
}
}
@@ -228,33 +243,34 @@ struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance
switch (creature_entry) {
case 4857: // Stone Keeper
SetFrozenState (creature);
- stoneKeeper[stoneKeepersCounter++] = creature->GetGUID();
+ stoneKeeper.push_back(creature->GetGUID());
break;
case 7309: // Earthen Custodian
- archaedasWallMinions[archaedasWallMinionsCounter++] = creature->GetGUID();
+ archaedasWallMinions.push_back(creature->GetGUID());
break;
case 7077: // Earthen Hallshaper
- archaedasWallMinions[archaedasWallMinionsCounter++] = creature->GetGUID();
+ archaedasWallMinions.push_back(creature->GetGUID());
break;
case 7076: // Earthen Guardian
- earthenGuardian[earthenGuardianCounter++] = creature->GetGUID();
+ earthenGuardian.push_back(creature->GetGUID());
break;
case 10120: // Vault Walker
- vaultWalker[vaultWalkerCounter++] = creature->GetGUID();
+ vaultWalker.push_back(creature->GetGUID());
break;
case 2748: // Archaedas
- archaedas = creature;
+ archaedasGUID = creature->GetGUID();
break;
} // end switch
} // end OnCreatureCreate
- uint64 GetData64 (uint32 identifier) {
+ uint64 GetData64 (uint32 identifier)
+ {
if (identifier == 0) return whoWokeArchaedasGUID;
if (identifier == 1) return vaultWalker[0]; // VaultWalker1
if (identifier == 2) return vaultWalker[1]; // VaultWalker2
@@ -270,7 +286,6 @@ struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance
return 0;
} // end GetData64
-
};
diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp
index 8f4b4b8d942..0833cf0dfec 100644
--- a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp
+++ b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp
@@ -25,7 +25,6 @@ EndScriptData */
#include "precompiled.h"
#include "def_zulaman.h"
-#include "Spell.h"
#include "Weather.h"
#define SPELL_STATIC_DISRUPTION 43622
@@ -34,6 +33,7 @@ EndScriptData */
#define SPELL_GUST_OF_WIND 43621
#define SPELL_ELECTRICAL_STORM 43648
#define SPELL_BERSERK 45078
+#define SPELL_ELECTRICAL_DAMAGE 43657
#define SPELL_ELECTRICAL_OVERLOAD 43658
#define SPELL_EAGLE_SWOOP 44732
@@ -57,15 +57,13 @@ EndScriptData */
#define SE_LOC_Y_MAX 1435
#define SE_LOC_Y_MIN 1370
-#define MOB_TEMP_TRIGGER 23920
-
struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI
{
boss_akilzonAI(Creature *c) : ScriptedAI(c)
{
- SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_ELECTRICAL_STORM);
+ SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_ELECTRICAL_DAMAGE);
if(TempSpell)
- TempSpell->Effect[1] = 0;//disable bugged lightning until fixed in core
+ TempSpell->EffectBasePoints[1] = 49;//disable bugged lightning until fixed in core
pInstance = ((ScriptedInstance*)c->GetInstanceData());
Reset();
}
@@ -214,7 +212,7 @@ struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI
{
x = 343+rand()%60;
y = 1380+rand()%60;
- if(Unit *trigger = m_creature->SummonCreature(MOB_TEMP_TRIGGER, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 2000))
+ if(Unit *trigger = m_creature->SummonTrigger(x, y, z, 0, 2000))
{
trigger->setFaction(35);
trigger->SetMaxHealth(100000);
@@ -315,7 +313,7 @@ struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI
target->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
target->SendMonsterMove(x,y,m_creature->GetPositionZ()+15,0,0,0);
}
- Unit *Cloud = m_creature->SummonCreature(MOB_TEMP_TRIGGER, x, y, m_creature->GetPositionZ()+16, 0, TEMPSUMMON_TIMED_DESPAWN, 15000);
+ Unit *Cloud = m_creature->SummonTrigger(x, y, m_creature->GetPositionZ()+16, 0, 15000);
if(Cloud)
{
CloudGUID = Cloud->GetGUID();
diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp
index cc176127282..7b0feb4e265 100644
--- a/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp
+++ b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp
@@ -226,9 +226,9 @@ struct TRINITY_DLL_DECL boss_janalaiAI : public ScriptedAI
for(uint8 j = 0; j < WallNum; j++)
{
if(WallNum == 3)
- wall = m_creature->SummonCreature(MOB_FIRE_BOMB, FireWallCoords[i][0],FireWallCoords[i][1]+5*(j-1),FireWallCoords[i][2],FireWallCoords[i][3],TEMPSUMMON_TIMED_DESPAWN,15000);
+ wall = m_creature->SummonTrigger(FireWallCoords[i][0],FireWallCoords[i][1]+5*(j-1),FireWallCoords[i][2],FireWallCoords[i][3],15000);
else
- wall = m_creature->SummonCreature(MOB_FIRE_BOMB, FireWallCoords[i][0]-2+4*j,FireWallCoords[i][1],FireWallCoords[i][2],FireWallCoords[i][3],TEMPSUMMON_TIMED_DESPAWN,15000);
+ wall = m_creature->SummonTrigger(FireWallCoords[i][0]-2+4*j,FireWallCoords[i][1],FireWallCoords[i][2],FireWallCoords[i][3],15000);
if(wall) wall->CastSpell(wall, SPELL_FIRE_WALL, true);
}
}
@@ -683,14 +683,9 @@ CreatureAI* GetAI_mob_hatchlingAI(Creature *_Creature)
return new mob_hatchlingAI(_Creature);
}
-struct TRINITY_DLL_DECL mob_eggAI : public ScriptedAI
+struct TRINITY_DLL_DECL mob_eggAI : public NullCreatureAI
{
- mob_eggAI(Creature *c) : ScriptedAI(c){}
- void Reset() {}
- void Aggro(Unit* who) {}
- void AttackStart(Unit* who) {}
- void MoveInLineOfSight(Unit* who) {}
- void UpdateAI(const uint32 diff) {}
+ mob_eggAI(Creature *c) : NullCreatureAI(c){}
void SpellHit(Unit *caster, const SpellEntry *spell)
{
diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp
index 2313af09831..ade7af821f5 100644
--- a/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp
+++ b/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp
@@ -546,23 +546,15 @@ struct TRINITY_DLL_DECL boss_zuljinAI : public ScriptedAI
if(Pillar_Of_Fire_Timer < diff)
{
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
- {
- float x, y, z;
- target->GetPosition(x, y, z);
- Creature* Pillar = m_creature->SummonCreature(CREATURE_COLUMN_OF_FIRE, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN, 30000);
- if(Pillar)
- {
- Pillar->CastSpell(Pillar, SPELL_PILLAR_TRIGGER, true);
- Pillar->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- }
- }
+ DoCast(target, SPELL_SUMMON_PILLAR);
Pillar_Of_Fire_Timer = 10000;
}else Pillar_Of_Fire_Timer -= diff;
if(Flame_Breath_Timer < diff)
{
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
- m_creature->CastSpell(m_creature, SPELL_FLAME_BREATH, false);
+ m_creature->SetInFront(target);
+ DoCast(m_creature, SPELL_FLAME_BREATH);
Flame_Breath_Timer = 10000;
}else Flame_Breath_Timer -= diff;
break;
@@ -581,21 +573,6 @@ CreatureAI* GetAI_boss_zuljin(Creature *_Creature)
return new boss_zuljinAI (_Creature);
}
-struct TRINITY_DLL_DECL do_nothingAI : public ScriptedAI
-{
- do_nothingAI(Creature *c) : ScriptedAI(c) {}
- void Reset() {}
- void Aggro(Unit* who) {}
- void AttackStart(Unit* who) {}
- void MoveInLineOfSight(Unit* who) {}
- void UpdateAI(const uint32 diff) {}
-};
-
-CreatureAI* GetAI_do_nothing(Creature *_Creature)
-{
- return new do_nothingAI (_Creature);
-}
-
struct TRINITY_DLL_DECL feather_vortexAI : public ScriptedAI
{
feather_vortexAI(Creature *c) : ScriptedAI(c) {}
@@ -632,11 +609,6 @@ void AddSC_boss_zuljin()
newscript->RegisterSelf();
newscript = new Script;
- newscript->Name="do_nothing";
- newscript->GetAI = GetAI_do_nothing;
- newscript->RegisterSelf();
-
- newscript = new Script;
newscript->Name="mob_zuljin_vortex";
newscript->GetAI = GetAI_feather_vortexAI;
newscript->RegisterSelf();
diff --git a/src/game/Cell.h b/src/game/Cell.h
index 719bfc3aaa5..35bcdbeea8a 100644
--- a/src/game/Cell.h
+++ b/src/game/Cell.h
@@ -142,6 +142,7 @@ struct TRINITY_DLL_DECL Cell
} data;
template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &, TypeContainerVisitor<T, CONTAINER> &visitor, Map &) const;
+ template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &, TypeContainerVisitor<T, CONTAINER> &visitor, Map &, float radius, float x_off, float y_off) const;
};
template<class T>
diff --git a/src/game/CellImpl.h b/src/game/CellImpl.h
index ce5f6ed2ece..08182068af9 100644
--- a/src/game/CellImpl.h
+++ b/src/game/CellImpl.h
@@ -129,4 +129,52 @@ Cell::Visit(const CellLock<LOCK_TYPE> &l, TypeContainerVisitor<T, CONTAINER> &vi
}
}
}
+
+template<class LOCK_TYPE,class T, class CONTAINER>
+inline void
+Cell::Visit(const CellLock<LOCK_TYPE> &l, TypeContainerVisitor<T, CONTAINER> &visitor, Map &m, float radius, float x_off, float y_off) const
+{
+ const CellPair &standing_cell = l.i_cellPair;
+ if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
+ return;
+
+ int left = 0, right = 0, upper = 0, lower = 0;
+
+ // Origin = (CENTER_GRID_CELL_OFFSET, CENTER_GRID_CELL_OFFSET)
+ if(CENTER_GRID_CELL_OFFSET - x_off < radius)
+ ++right;
+ if(CENTER_GRID_CELL_OFFSET + x_off < radius)
+ ++left;
+ if(CENTER_GRID_CELL_OFFSET - y_off < radius)
+ ++upper;
+ if(CENTER_GRID_CELL_OFFSET + y_off < radius)
+ ++lower;
+
+ if(!left && !right && !upper && !lower)
+ {
+ m.Visit(l, visitor);
+ return;
+ }
+
+ CellPair begin_cell = standing_cell;
+ CellPair end_cell = standing_cell;
+
+ begin_cell << left; //note: need change << if left > 1
+ begin_cell -= lower;
+ end_cell >> right;
+ end_cell += upper;
+
+ // loop the cell range
+ for(uint32 x = begin_cell.x_coord; x <= end_cell.x_coord; x++)
+ {
+ for(uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; y++)
+ {
+ CellPair cell_pair(x,y);
+ Cell r_zone(cell_pair);
+ r_zone.data.Part.nocreate = l->data.Part.nocreate;
+ CellLock<LOCK_TYPE> lock(r_zone, cell_pair);
+ m.Visit(lock, visitor);
+ }
+ }
+}
#endif
diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp
index 951f443e479..09af5f18c78 100644
--- a/src/game/Chat.cpp
+++ b/src/game/Chat.cpp
@@ -137,13 +137,16 @@ ChatCommand * ChatHandler::getCommandTable()
static ChatCommand wpCommandTable[] =
{
{ "show", SEC_GAMEMASTER, false, &ChatHandler::HandleWpShowCommand, "", NULL },
- { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleWpAddCommand, "", NULL },
- { "modify", SEC_GAMEMASTER, false, &ChatHandler::HandleWpModifyCommand, "", NULL },
- { "export", SEC_ADMINISTRATOR, false, &ChatHandler::HandleWpExportCommand, "", NULL },
- { "import", SEC_ADMINISTRATOR, false, &ChatHandler::HandleWpImportCommand, "", NULL },
- { NULL, 0, false, NULL, "", NULL }
+ { "addwp", SEC_GAMEMASTER, false, &ChatHandler::HandleWpAddCommand, "", NULL },
+ { "load", SEC_GAMEMASTER, false, &ChatHandler::HandleWpLoadPathCommand, "", NULL },
+ { "modify", SEC_GAMEMASTER, false, &ChatHandler::HandleWpModifyCommand, "", NULL },
+ { "event", SEC_GAMEMASTER, false, &ChatHandler::HandleWpEventCommand, "", NULL },
+ { "unload", SEC_GAMEMASTER, false, &ChatHandler::HandleWpUnLoadPathCommand, "", NULL },
+
+ { NULL, 0, false, NULL, "", NULL }
};
+
static ChatCommand banCommandTable[] =
{
{ "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanAccountCommand, "", NULL },
@@ -293,6 +296,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "locales_npc_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesNpcTextCommand, "", NULL },
{ "locales_page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesPageTextCommand, "", NULL },
{ "locales_quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesQuestCommand, "", NULL },
+ { "waypoint_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadWpScriptsCommand, "", NULL },
{ "", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
@@ -507,8 +511,12 @@ ChatCommand * ChatHandler::getCommandTable()
{ "event", SEC_GAMEMASTER, false, NULL, "", eventCommandTable },
{ "gobject", SEC_GAMEMASTER, false, NULL, "", gobjectCommandTable },
{ "honor", SEC_GAMEMASTER, false, NULL, "", honorCommandTable },
- { "wp", SEC_GAMEMASTER, false, NULL, "", wpCommandTable },
- { "quest", SEC_ADMINISTRATOR, false, NULL, "", questCommandTable },
+
+ //wp commands
+ { "path", SEC_GAMEMASTER, false, NULL, "", wpCommandTable },
+ { "loadpath", SEC_ADMINISTRATOR, false, &ChatHandler::HandleReloadAllPaths, "", NULL },
+
+ { "quest", SEC_ADMINISTRATOR, false, NULL, "", questCommandTable },
{ "reload", SEC_ADMINISTRATOR, true, NULL, "", reloadCommandTable },
{ "list", SEC_ADMINISTRATOR, true, NULL, "", listCommandTable },
{ "lookup", SEC_ADMINISTRATOR, true, NULL, "", lookupCommandTable },
diff --git a/src/game/Chat.h b/src/game/Chat.h
index b62bae39d17..57e1b486189 100644
--- a/src/game/Chat.h
+++ b/src/game/Chat.h
@@ -211,7 +211,8 @@ class ChatHandler
bool HandleReloadConfigCommand(const char* args);
- bool HandleReloadAreaTriggerTavernCommand(const char* args);
+ bool HandleReloadWpScriptsCommand(const char* args);
+ bool HandleReloadAreaTriggerTavernCommand(const char* args);
bool HandleReloadAreaTriggerTeleportCommand(const char* args);
bool HandleReloadEventScriptsCommand(const char* args);
bool HandleReloadCommandCommand(const char* args);
@@ -410,11 +411,16 @@ class ChatHandler
bool HandlePasswordCommand(const char* args);
bool HandleLockAccountCommand(const char* args);
bool HandleRespawnCommand(const char* args);
- bool HandleWpAddCommand(const char* args);
- bool HandleWpModifyCommand(const char* args);
- bool HandleWpShowCommand(const char* args);
- bool HandleWpExportCommand(const char* args);
- bool HandleWpImportCommand(const char* args);
+
+ //New Wp Commands
+ bool HandleWpAddCommand(const char* args);
+ bool HandleWpLoadPathCommand(const char* args);
+ bool HandleWpUnLoadPathCommand(const char* args);
+ bool HandleWpModifyCommand(const char* args);
+ bool HandleWpEventCommand(const char* args);
+ bool HandleWpShowCommand(const char* args);
+ bool HandleReloadAllPaths(const char *args);
+
bool HandleFlyModeCommand(const char* args);
bool HandleSendOpcodeCommand(const char* args);
bool HandleSellErrorCommand(const char* args);
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 80eba6fde98..3afc23c3ba4 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -347,10 +347,10 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data )
m_spells[3] = GetCreatureInfo()->spell4;
// HACK: trigger creature is always not selectable
- if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
+ if(isTrigger())
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- if(isTotem() || GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER
+ if(isTotem() || isTrigger()
|| GetCreatureType() == CREATURE_TYPE_CRITTER)
SetReactState(REACT_PASSIVE);
else if(isCivilian())
@@ -563,7 +563,7 @@ void Creature::RegenerateHealth()
ModifyHealth(addvalue);
}
-bool Creature::AIM_Initialize()
+bool Creature::AIM_Initialize(CreatureAI* ai)
{
// make sure nothing can change the AI during AI update
if(m_AI_locked)
@@ -578,7 +578,7 @@ bool Creature::AIM_Initialize()
CreatureAI * oldAI = i_AI;
i_motionMaster.Initialize();
- i_AI = FactorySelector::selectAI(this);
+ i_AI = ai ? ai : FactorySelector::selectAI(this);
if (oldAI)
delete oldAI;
return true;
@@ -2068,6 +2068,10 @@ bool Creature::LoadCreaturesAddon(bool reload)
if (cainfo->move_flags != 0)
SetUnitMovementFlags(cainfo->move_flags);
+ //Load Path
+ if (cainfo->path_id != 0)
+ m_path_id = cainfo->path_id;
+
if(cainfo->auras)
{
for (CreatureDataAddonAura const* cAura = cainfo->auras; cAura->spell_id; ++cAura)
diff --git a/src/game/Creature.h b/src/game/Creature.h
index 31386d3b180..9a76b293266 100644
--- a/src/game/Creature.h
+++ b/src/game/Creature.h
@@ -279,7 +279,8 @@ struct CreatureDataAddonAura
struct CreatureDataAddon
{
uint32 guidOrEntry;
- uint32 mount;
+ uint32 path_id;
+ uint32 mount;
uint32 bytes0;
uint32 bytes1;
uint32 bytes2;
@@ -425,6 +426,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool isTotem() const { return m_isTotem; }
bool isRacialLeader() const { return GetCreatureInfo()->RacialLeader; }
bool isCivilian() const { return GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_CIVILIAN; }
+ bool isTrigger() const { return GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER; }
bool canWalk() const { return GetCreatureInfo()->InhabitType & INHABIT_GROUND; }
bool canSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; }
bool canFly() const { return GetCreatureInfo()->InhabitType & INHABIT_AIR; }
@@ -461,7 +463,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool IsInEvadeMode() const;
- bool AIM_Initialize();
+ bool AIM_Initialize(CreatureAI* ai = NULL);
void InitPossessedAI();
void DisablePossessedAI();
@@ -616,7 +618,14 @@ class TRINITY_DLL_SPEC Creature : public Unit
void GetCombatStartPosition(float &x, float &y, float &z) { x = CombatStartX; y = CombatStartY; z = CombatStartZ; }
uint32 GetGlobalCooldown() const { return m_GlobalCooldown; }
- protected:
+
+ uint32 GetWaypointPath(){return m_path_id;}
+ void LoadPath(uint32 pathid) { m_path_id = pathid; }
+
+ uint32 GetCurrentWaypointID(){return m_waypointID;}
+ void UpdateWaypointID(uint32 wpID){m_waypointID = wpID;}
+
+ protected:
bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL);
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL);
@@ -666,7 +675,11 @@ class TRINITY_DLL_SPEC Creature : public Unit
float CombatStartZ;
private:
- GridReference<Creature> m_gridRef;
+ //WaypointMovementGenerator vars
+ uint32 m_waypointID;
+ uint32 m_path_id;
+
+ GridReference<Creature> m_gridRef;
CreatureInfo const* m_creatureInfo; // in heroic mode can different from ObjMgr::GetCreatureTemplate(GetEntry())
};
diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp
index 7008798b806..e43b703d3cb 100644
--- a/src/game/GameObject.cpp
+++ b/src/game/GameObject.cpp
@@ -1277,7 +1277,7 @@ void GameObject::Use(Unit* user)
void GameObject::CastSpell(Unit* target, uint32 spell)
{
//summon world trigger
- Creature *trigger = SummonCreature(12999, GetPositionX(), GetPositionY(), GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 1);
+ Creature *trigger = SummonTrigger(GetPositionX(), GetPositionY(), GetPositionZ(), 0, 1);
if(!trigger) return;
trigger->SetVisibility(VISIBILITY_OFF); //should this be true?
diff --git a/src/game/GridDefines.h b/src/game/GridDefines.h
index 54dd2d02920..26168651d8a 100644
--- a/src/game/GridDefines.h
+++ b/src/game/GridDefines.h
@@ -33,6 +33,17 @@ class GameObject;
class Pet;
class Player;
+//comment the next line if CPU usage is too high
+#define LARGE_CELL
+
+#ifdef LARGE_CELL
+#define MAX_NUMBER_OF_CELLS 4
+#define CENTER_GRID_CELL_ID 128
+#else
+#define MAX_NUMBER_OF_CELLS 8
+#define CENTER_GRID_CELL_ID 256
+#endif
+
#define MAX_NUMBER_OF_GRIDS 64
#define SIZE_OF_GRIDS 533.33333f
@@ -43,10 +54,8 @@ class Player;
#define MIN_GRID_DELAY MINUTE*1000
#define MIN_MAP_UPDATE_DELAY 50
-#define MAX_NUMBER_OF_CELLS 4
#define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS)
-#define CENTER_GRID_CELL_ID 128
#define CENTER_GRID_CELL_OFFSET (SIZE_OF_GRID_CELL/2)
#define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS)
@@ -141,6 +150,18 @@ namespace Trinity
return Compute<CellPair, CENTER_GRID_CELL_ID>(x, y, CENTER_GRID_CELL_OFFSET, SIZE_OF_GRID_CELL);
}
+ inline CellPair ComputeCellPair(float x, float y, float &x_off, float &y_off)
+ {
+ double x_offset = (double(x) - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL;
+ double y_offset = (double(y) - CENTER_GRID_CELL_OFFSET)/SIZE_OF_GRID_CELL;
+
+ int x_val = int(x_offset + 0.5);
+ int y_val = int(y_offset + 0.5);
+ x_off = (float(x_offset) - x_val) * SIZE_OF_GRID_CELL;
+ y_off = (float(y_offset) - y_val) * SIZE_OF_GRID_CELL;
+ return CellPair(x_val + CENTER_GRID_CELL_ID, y_val + CENTER_GRID_CELL_ID);
+ }
+
inline void NormalizeMapCoord(float &c)
{
if(c > MAP_HALFSIZE - 0.5)
diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp
index bb6a4473e0b..89d27582195 100644
--- a/src/game/Level2.cpp
+++ b/src/game/Level2.cpp
@@ -1371,11 +1371,9 @@ bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
Player* player = m_session->GetPlayer();
- WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), wait, 0);
-
// update movement type
WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
- if(pCreature)
+ if(pCreature && pCreature->GetWaypointPath())
{
pCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
pCreature->GetMotionMaster()->Initialize();
@@ -1387,8 +1385,6 @@ bool ChatHandler::HandleNpcAddMoveCommand(const char* args)
pCreature->SaveToDB();
}
- SendSysMessage(LANG_WAYPOINT_ADDED);
-
return true;
}
@@ -1507,13 +1503,13 @@ bool ChatHandler::HandleNpcSetMoveTypeCommand(const char* args)
else
return false;
- // update movement type
- if(doNotDelete == false)
- WaypointMgr.DeletePath(lowguid);
-
if(pCreature)
{
- pCreature->SetDefaultMovementType(move_type);
+ // update movement type
+ if(doNotDelete == false)
+ pCreature->LoadPath(0);
+
+ pCreature->SetDefaultMovementType(move_type);
pCreature->GetMotionMaster()->Initialize();
if(pCreature->isAlive()) // dead creature will reset movement generator at respawn
{
@@ -2160,190 +2156,414 @@ bool ChatHandler::HandleNpcSpawnTimeCommand(const char* args)
return true;
}
-/**
- * Add a waypoint to a creature.
- *
- * The user can either select an npc or provide its GUID.
- *
- * The user can even select a visual waypoint - then the new waypoint
- * is placed *after* the selected one - this makes insertion of new
- * waypoints possible.
- *
- * eg:
- * .wp add 12345
- * -> adds a waypoint to the npc with the GUID 12345
- *
- * .wp add
- * -> adds a waypoint to the currently selected creature
- *
- *
- * @param args if the user did not provide a GUID, it is NULL
- *
- * @return true - command did succeed, false - something went wrong
- */
+/////WAYPOINT COMMANDS
+
bool ChatHandler::HandleWpAddCommand(const char* args)
{
sLog.outDebug("DEBUG: HandleWpAddCommand");
// optional
- char* guid_str = NULL;
-
+ char* path_number = NULL;
+ uint32 pathid = 0;
+
if(*args)
- {
- guid_str = strtok((char*)args, " ");
- }
-
- uint32 lowguid = 0;
+ path_number = strtok((char*)args, " ");
+
uint32 point = 0;
Creature* target = getSelectedCreature();
- // Did player provide a GUID?
- if (!guid_str)
+
+ if (!path_number)
+ {
+ if(target)
+ pathid = target->GetWaypointPath();
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(id) FROM waypoint_data");
+ uint32 maxpathid = result->Fetch()->GetInt32();
+ pathid = maxpathid+1;
+ sLog.outDebug("DEBUG: HandleWpAddCommand - New path started.");
+ PSendSysMessage("%s%s|r", "|cff00ff00", "New path started.");
+
+ }
+ }
+ else
+ pathid = atoi(path_number);
+
+ // path_id -> ID of the Path
+ // point -> number of the waypoint (if not 0)
+
+ if(!pathid)
+ {
+ sLog.outDebug("DEBUG: HandleWpAddCommand - Current creature haven't loaded path.");
+ PSendSysMessage("%s%s|r", "|cffff33ff", "Current creature haven't loaded path.");
+ return true;
+ }
+
+ sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
+
+ QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM waypoint_data WHERE id = '%u'",pathid);
+
+ if( result )
{
- sLog.outDebug("DEBUG: HandleWpAddCommand - No GUID provided");
+ point = (*result)[0].GetUInt32();
+ delete result;
+ }
+
+ Player* player = m_session->GetPlayer();
+ Map *map = player->GetMap();
- // No GUID provided
- // -> Player must have selected a creature
+ WorldDatabase.PExecuteLog("INSERT INTO waypoint_data (id,point,position_x,position_y,position_z) VALUES ('%u','%u','%f', '%f', '%f')",
+ pathid, point+1, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
- if(!target || target->isPet())
- {
- SendSysMessage(LANG_SELECT_CREATURE);
- SetSentErrorMessage(true);
- return false;
- }
- if (target->GetEntry() == VISUAL_WAYPOINT )
- {
- sLog.outDebug("DEBUG: HandleWpAddCommand - target->GetEntry() == VISUAL_WAYPOINT (1) ");
+ PSendSysMessage("%s%s%u%s%u%s|r", "|cff00ff00", "PathID: |r|cff00ffff", pathid, "|r|cff00ff00: Waypoint |r|cff00ffff", point,"|r|cff00ff00 created. ");
+
+ return true;
+} // HandleWpAddCommand
- QueryResult *result =
- WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u",
- target->GetGUIDLow() );
- if(!result)
- {
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
- // User selected a visual spawnpoint -> get the NPC
- // Select NPC GUID
- // Since we compare float values, we have to deal with
- // some difficulties.
- // Here we search for all waypoints that only differ in one from 1 thousand
- // (0.001) - There is no other way to compare C++ floats with mySQL floats
- // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
- const char* maxDIFF = "0.01";
- result = WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )",
- target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
- if(!result)
- {
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
- SetSentErrorMessage(true);
- return false;
- }
- }
- do
- {
- Field *fields = result->Fetch();
- lowguid = fields[0].GetUInt32();
- point = fields[1].GetUInt32();
- }while( result->NextRow() );
- delete result;
+bool ChatHandler::HandleWpLoadPathCommand(const char *args)
+{
- CreatureData const* data = objmgr.GetCreatureData(lowguid);
- if(!data)
- {
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
- SetSentErrorMessage(true);
- return false;
- }
+ if(!*args)
+ return false;
+
+ // optional
+ char* path_number = NULL;
- target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
- if(!target)
- {
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
- SetSentErrorMessage(true);
- return false;
- }
- }
- else
- {
- lowguid = target->GetDBTableGUIDLow();
- }
+ if(*args)
+ {
+ path_number = strtok((char*)args, " ");
}
- else
- {
- sLog.outDebug("DEBUG: HandleWpAddCommand - GUID provided");
-
- // GUID provided
- // Warn if player also selected a creature
- // -> Creature selection is ignored <-
- if(target)
- {
- SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
- }
- lowguid = atoi((char*)guid_str);
- CreatureData const* data = objmgr.GetCreatureData(lowguid);
- if(!data)
- {
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
+ uint32 pathid = 0;
+ uint32 guidlow = 0;
+ Creature* target = getSelectedCreature();
+
+ // Did player provide a path_id?
+ if (!path_number)
+ sLog.outDebug("DEBUG: HandleWpLoadPathCommand - No path number provided");
+
+ if(!target)
+ {
+ SendSysMessage(LANG_SELECT_CREATURE);
SetSentErrorMessage(true);
return false;
}
-
- target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
- if(!target || target->isPet())
+ if(target->GetEntry() == 1)
{
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
+ PSendSysMessage("%s%s|r", "|cffff33ff", "You want to load path to a waypoint? Aren't you?");
SetSentErrorMessage(true);
return false;
}
- }
- // lowguid -> GUID of the NPC
- // point -> number of the waypoint (if not 0)
- sLog.outDebug("DEBUG: HandleWpAddCommand - danach");
- sLog.outDebug("DEBUG: HandleWpAddCommand - point == 0");
+ pathid = atoi(path_number);
+ if(!pathid)
+ {
+ PSendSysMessage("%s%s|r", "|cffff33ff", "No vallid path number provided.");
+ return true;
+ }
+
+ guidlow = target->GetGUIDLow();
+
+ QueryResult *result = WorldDatabase.PQuery( "SELECT guid FROM creature_addon WHERE guid = '%u'",guidlow);
+
+ if( result )
+ {
+ WorldDatabase.PExecute("UPDATE creature_addon SET path_id = '%u' WHERE guid = '%u'", pathid, guidlow);
+ delete result;
+ }
+ else
+ WorldDatabase.PExecute("INSERT INTO creature_addon(guid,path_id) VALUES ('%u','%u')", guidlow, pathid);
+
+ WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE, guidlow);
+
+ target->LoadPath(pathid);
+
+ target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
+
+ target->GetMotionMaster()->Initialize();
+
+ target->Say("Path loaded.",0,0);
+
+ return true;
+}
- Player* player = m_session->GetPlayer();
- WaypointMgr.AddLastNode(lowguid, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetOrientation(), 0, 0);
- // update movement type
- if(target)
+bool ChatHandler::HandleReloadAllPaths(const char* args)
+{
+if(!*args)
+ return false;
+
+uint32 id = atoi(args);
+
+if(!id)
+ return false;
+
+ PSendSysMessage("%s%s|r|cff00ffff%u|r", "|cff00ff00", "Loading Path: ", id);
+ WaypointMgr.UpdatePath(id);
+ return true;
+}
+
+bool ChatHandler::HandleWpUnLoadPathCommand(const char *args)
+{
+ uint32 guidlow = 0;
+ Creature* target = getSelectedCreature();
+
+ if(!target)
+ {
+ PSendSysMessage("%s%s|r", "|cff33ffff", "You must select target.");
+ return true;
+ }
+
+ if(target->GetCreatureAddon())
+ {
+ if(target->GetCreatureAddon()->path_id != 0)
+ {
+ WorldDatabase.PExecute("DELETE FROM creature_addon WHERE guid = %u", target->GetGUIDLow());
+ target->UpdateWaypointID(0);
+ WorldDatabase.PExecute("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", IDLE_MOTION_TYPE, guidlow);
+ target->LoadPath(0);
+ target->SetDefaultMovementType(IDLE_MOTION_TYPE);
+ target->GetMotionMaster()->MoveTargetedHome();
+ target->GetMotionMaster()->Initialize();
+ target->Say("Path unloaded.",0,0);
+ return true;
+ }
+ PSendSysMessage("%s%s|r", "|cffff33ff", "Target have no loaded path.");
+ return true;
+ }
+ PSendSysMessage("%s%s|r", "|cffff33ff", "Target have no loaded path.");
+ return true;
+}
+
+bool ChatHandler::HandleWpEventCommand(const char* args)
+{
+if(!*args)
+ return false;
+
+ char* show_str = strtok((char*)args, " ");
+
+ std::string show = show_str;
+
+ // Check
+ if( (show != "add") && (show != "mod") && (show != "del") && (show != "listid")) return false;
+
+
+ if(show == "add")
+ {
+ uint32 id = 0;
+ char* arg_id = strtok(NULL, " ");
+
+ if(arg_id)
+ uint32 id = atoi(arg_id);
+
+ if(id)
+ {
+ QueryResult *result = WorldDatabase.PQuery( "SELECT `id` FROM waypoint_scripts WHERE guid = %u", id);
+
+ if( !result )
+ {
+ WorldDatabase.PExecute("INSERT INTO waypoint_scripts(guid)VALUES(%u)", id);
+ PSendSysMessage("%s%s%u|r", "|cff00ff00", "Wp Event: New waypoint event added: ", id);
+ }
+ else
+ {
+ PSendSysMessage("|cff00ff00Wp Event: You have choosed an existing waypoint script guid: %u|r", id);
+ delete result;
+ }
+ }
+ else
+ {
+ QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(guid) FROM waypoint_scripts");
+ id = result->Fetch()->GetUInt32();
+ WorldDatabase.PExecute("INSERT INTO waypoint_scripts(guid)VALUES(%u)", id+1);
+ PSendSysMessage("%s%s%u|r", "|cff00ff00","Wp Event: New waypoint event added: |r|cff00ffff", id+1);
+ }
+
+ return true;
+ }
+
+
+ if(show == "listid")
+ {
+ uint32 id;
+ char* arg_id = strtok(NULL, " ");
+
+ if(!arg_id)
+ {
+ PSendSysMessage("%s%s|r", "|cff33ffff","Wp Event: You must provide waypoint script id.");
+ return true;
+ }
+
+ id = atoi(arg_id);
+
+ uint32 a2, a3, a4, a5, a6;
+ float a8, a9, a10, a11;
+ char const* a7;
+
+ QueryResult *result = WorldDatabase.PQuery( "SELECT `guid`, `delay`, `command`, `datalong`, `datalong2`, `dataint`, `x`, `y`, `z`, `o` FROM waypoint_scripts WHERE id = %u", id);
+
+ if( !result )
+ {
+ PSendSysMessage("%s%s%u|r", "|cff33ffff", "Wp Event: No waypoint scripts found on id: ", id);
+ return true;
+ }
+
+ Field *fields;
+
+ do
+ {
+ fields = result->Fetch();
+ a2 = fields[0].GetUInt32();
+ a3 = fields[1].GetUInt32();
+ a4 = fields[2].GetUInt32();
+ a5 = fields[3].GetUInt32();
+ a6 = fields[4].GetUInt32();
+ a7 = fields[5].GetString();
+ a8 = fields[6].GetFloat();
+ a9 = fields[7].GetFloat();
+ a10 = fields[8].GetFloat();
+ a11 = fields[9].GetFloat();
+
+ PSendSysMessage("|cffff33ffid:|r|cff00ffff %u|r|cff00ff00, guid: |r|cff00ffff%u|r|cff00ff00, delay: |r|cff00ffff%u|r|cff00ff00, command: |r|cff00ffff%u|r|cff00ff00, datalong: |r|cff00ffff%u|r|cff00ff00, datalong2: |r|cff00ffff%u|r|cff00ff00, datatext: |r|cff00ffff%s|r|cff00ff00, posx: |r|cff00ffff%f|r|cff00ff00, posy: |r|cff00ffff%f|r|cff00ff00, posz: |r|cff00ffff%f|r|cff00ff00, orientation: |r|cff00ffff%f|r", id, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+ }while(result->NextRow());
+
+ delete result;
+ }
+
+ if(show == "del")
+ {
+
+ char* arg_id = strtok(NULL, " ");
+ uint32 id = atoi(arg_id);
+
+ QueryResult *result = WorldDatabase.PQuery( "SELECT `guid` FROM waypoint_scripts WHERE guid = %u", id);
+
+ if( result )
{
- target->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
- target->GetMotionMaster()->Initialize();
- if(target->isAlive()) // dead creature will reset movement generator at respawn
- {
- target->setDeathState(JUST_DIED);
- target->Respawn();
- }
- target->SaveToDB();
- }
+
+ WorldDatabase.PExecuteLog("DELETE FROM waypoint_scripts WHERE guid = %u", id);
+ PSendSysMessage("%s%s%u|r","|cff00ff00","Wp Event: Waypoint script removed: ", id);
+ delete result;
+ }
else
- WorldDatabase.PExecuteLog("UPDATE creature SET MovementType = '%u' WHERE guid = '%u'", WAYPOINT_MOTION_TYPE,lowguid);
+ PSendSysMessage("|cffff33ffWp Event: ERROR: you have selected a non existing script: %u|r", id);
+
+ return true;
+ }
+
+
+ if(show == "mod")
+ {
+ char* arg_1 = strtok(NULL," ");
+
+ if(!arg_1)
+ {
+ SendSysMessage("|cffff33ffERROR: Waypoint script guid not present.|r");
+ return true;
+ }
+
+ uint32 id = atoi(arg_1);
- PSendSysMessage(LANG_WAYPOINT_ADDED, point, lowguid);
+ if(!id)
+ {
+ SendSysMessage("|cffff33ffERROR: No vallid waypoint script id not present.|r");
+ return true;
+ }
- return true;
-} // HandleWpAddCommand
+ char* arg_2 = strtok(NULL," ");
+
+ if(!arg_2)
+ { SendSysMessage("|cffff33ffERROR: No argument present.|r");
+ return true;}
+
+
+ std::string arg_string = arg_2;
+
+
+if( (arg_string != "setid") && (arg_string != "delay") && (arg_string != "command")
+&& (arg_string != "datalong") && (arg_string != "datalong2") && (arg_string != "dataint") && (arg_string != "posx")
+&& (arg_string != "posy") && (arg_string != "posz") && (arg_string != "orientation")
+) { SendSysMessage("|cffff33ffERROR: No valid argument present.|r");
+ return true;}
+
+
+char* arg_3;
+std::string arg_str_2 = arg_2;
+arg_3 = strtok(NULL," ");
+
+if(!arg_3)
+{SendSysMessage("|cffff33ffERROR: No additional argument present.|r");
+ return true;}
+
+float coord;
+
+ if(arg_str_2 == "setid")
+ {
+ uint32 newid = atoi(arg_3);
+ PSendSysMessage("%s%s|r|cff00ffff%u|r|cff00ff00%s|r|cff00ffff%u|r","|cff00ff00","Wp Event: Wypoint scipt guid: ", newid," id changed: ", id);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET id='%u' WHERE guid='%u'",
+ newid, id); return true;
+ }
+ else
+ {
+
+ QueryResult *result = WorldDatabase.PQuery("SELECT id FROM waypoint_scripts WHERE guid='%u'",id);
+
+ if(!result)
+ {
+ SendSysMessage("|cffff33ffERROR: You have selected an non existing waypoint script guid.|r");
+ return true;
+ }
+
+ delete result;
+
+if(arg_str_2 == "posx")
+{
+ coord = atof(arg_3);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET x='%f' WHERE guid='%u'",
+ coord, id);
+ PSendSysMessage("|cff00ff00Waypoint script:|r|cff00ffff %u|r|cff00ff00 position_x updated.|r", id);
+ return true;
+}else if(arg_str_2 == "posy")
+{
+ coord = atof(arg_3);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET y='%f' WHERE guid='%u'",
+ coord, id);
+ PSendSysMessage("|cff00ff00Waypoint script: %u position_y updated.|r", id);
+ return true;
+} else if(arg_str_2 == "posz")
+{
+ coord = atof(arg_3);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET z='%f' WHERE guid='%u'",
+ coord, id);
+ PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 position_z updated.|r", id);
+ return true;
+} else if(arg_str_2 == "orientation")
+{
+ coord = atof(arg_3);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET o='%f' WHERE guid='%u'",
+ coord, id);
+ PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 orientation updated.|r", id);
+ return true;
+} else if(arg_str_2 == "dataint")
+{
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%u' WHERE guid='%u'",
+ arg_2, atoi(arg_3), id);
+ PSendSysMessage("|cff00ff00Waypoint script: |r|cff00ffff%u|r|cff00ff00 dataint updated.|r", id);
+ return true;
+}else
+{
+ std::string arg_str_3 = arg_3;
+ WorldDatabase.escape_string(arg_str_3);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_scripts SET %s='%s' WHERE guid='%u'",
+ arg_2, arg_str_3.c_str(), id);
+}
+}
+ PSendSysMessage("%s%s|r|cff00ffff%u:|r|cff00ff00 %s %s|r","|cff00ff00","Waypoint script:", id, arg_2,"updated.");
+}
+return true;
+}
-/**
- * .wp modify emote | spell | text | del | move | add
- *
- * add -> add a WP after the selected visual waypoint
- * User must select a visual waypoint and then issue ".wp modify add"
- *
- * emote <emoteID>
- * User has selected a visual waypoint before.
- * <emoteID> is added to this waypoint. Everytime the
- * NPC comes to this waypoint, the emote is called.
- *
- * emote <GUID> <WPNUM> <emoteID>
- * User has not selected visual waypoint before.
- * For the waypoint <WPNUM> for the NPC with <GUID>
- * an emote <emoteID> is added.
- * Everytime the NPC comes to this waypoint, the emote is called.
- *
- *
- * info <GUID> <WPNUM> -> User did not select a visual waypoint and
- */
bool ChatHandler::HandleWpModifyCommand(const char* args)
{
sLog.outDebug("DEBUG: HandleWpModifyCommand");
@@ -2361,20 +2581,20 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
std::string show = show_str;
// Check
// Remember: "show" must also be the name of a column!
- if( (show != "emote") && (show != "spell") && (show != "textid1") && (show != "textid2")
- && (show != "textid3") && (show != "textid4") && (show != "textid5")
- && (show != "waittime") && (show != "del") && (show != "move") && (show != "add")
- && (show != "model1") && (show != "model2") && (show != "orientation"))
+ if( (show != "delay") && (show != "event_id") && (show != "event_chance")
+ && (show != "move_flag") && (show != "del") && (show != "move") && (show != "wpadd")
+ )
{
return false;
}
// Next arg is: <GUID> <WPNUM> <ARGUMENT>
+ char* arg_str = NULL;
// Did user provide a GUID
// or did the user select a creature?
// -> variable lowguid is filled with the GUID of the NPC
- uint32 lowguid = 0;
+ uint32 pathid = 0;
uint32 point = 0;
uint32 wpGuid = 0;
Creature* target = getSelectedCreature();
@@ -2383,244 +2603,203 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
{
sLog.outDebug("DEBUG: HandleWpModifyCommand - User did select an NPC");
+ // The visual waypoint
+ Creature* wpCreature = NULL;
+
+ wpGuid = target->GetGUIDLow();
+
// Did the user select a visual spawnpoint?
- if (target->GetEntry() != VISUAL_WAYPOINT )
- {
- PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
- SetSentErrorMessage(true);
- return false;
- }
- wpGuid = target->GetGUIDLow();
+ if(wpGuid)
+ wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
- // The visual waypoint
- QueryResult *result =
- WorldDatabase.PQuery( "SELECT id, point FROM creature_movement WHERE wpguid = %u LIMIT 1",
- target->GetGUIDLow() );
- if(!result)
+ // attempt check creature existence by DB data
+ else
{
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
- SetSentErrorMessage(true);
- return false;
+
+ QueryResult *result = WorldDatabase.PQuery( "SELECT guid FROM creature_addon WHERE path_id = '%u'",wpGuid);
+ if(!result)
+ {
+ PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, wpGuid);
+ return true;
+ }
+
}
- sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid");
+ // User did select a visual waypoint?
+ // Check the creature
+ if (wpCreature->GetEntry() == VISUAL_WAYPOINT )
+ {
+ QueryResult *result =
+ WorldDatabase.PQuery( "SELECT id, point FROM waypoint_data WHERE wpguid = %u",
+ wpGuid);
+ if(!result)
+ {
+ sLog.outDebug("DEBUG: HandleWpModifyCommand - No waypoint found - used 'wpguid'");
- Field *fields = result->Fetch();
- lowguid = fields[0].GetUInt32();
- point = fields[1].GetUInt32();
+ PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUIDLow());
+ // Select waypoint number from database
+ // Since we compare float values, we have to deal with
+ // some difficulties.
+ // Here we search for all waypoints that only differ in one from 1 thousand
+ // (0.001) - There is no other way to compare C++ floats with mySQL floats
+ // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
+ const char* maxDIFF = "0.01";
+ result = WorldDatabase.PQuery( "SELECT id, point FROM waypoint_data WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )",
+ wpCreature->GetPositionX(), maxDIFF, wpCreature->GetPositionY(), maxDIFF, wpCreature->GetPositionZ(), maxDIFF);
+ if(!result)
+ {
+ PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, wpGuid);
+ return true;
+ }
+ }
+ sLog.outDebug("DEBUG: HandleWpModifyCommand - After getting wpGuid");
- // Cleanup memory
- sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory");
- delete result;
+ do
+ {
+ Field *fields = result->Fetch();
+ pathid = fields[0].GetUInt32();
+ point = fields[1].GetUInt32();
+ }while( result->NextRow() );
+
+ // Cleanup memory
+ sLog.outDebug("DEBUG: HandleWpModifyCommand - Cleanup memory");
+ delete result;
+ // We have the waypoint number and the GUID of the "master npc"
+ // Text is enclosed in "<>", all other arguments not
+
+ arg_str = strtok((char*)NULL, " ");
+
+ }
}
else
{
// User did provide <GUID> <WPNUM>
-
char* guid_str = strtok((char*)NULL, " ");
- if( !guid_str )
- {
- SendSysMessage(LANG_WAYPOINT_NOGUID);
- return false;
- }
- lowguid = atoi((char*)guid_str);
+ char* point_str = strtok((char*)NULL, " ");
- CreatureData const* data = objmgr.GetCreatureData(lowguid);
- if(!data)
+ arg_str = strtok((char*)NULL, " ");
+
+ if( !guid_str )
{
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
- SetSentErrorMessage(true);
+ SendSysMessage(LANG_WAYPOINT_NOGUID);
return false;
}
- PSendSysMessage("DEBUG: GUID provided: %d", lowguid);
-
- char* point_str = strtok((char*)NULL, " ");
if( !point_str )
{
SendSysMessage(LANG_WAYPOINT_NOWAYPOINTGIVEN);
return false;
}
- point = atoi((char*)point_str);
-
- PSendSysMessage("DEBUG: wpNumber provided: %d", point);
-
- // Now we need the GUID of the visual waypoint
- // -> "del", "move", "add" command
-
- QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' AND point = '%u' LIMIT 1", lowguid, point);
- if (!result)
+ if( (show != "del") && (show != "move") )
{
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, lowguid, point);
- SetSentErrorMessage(true);
- return false;
+ if( !arg_str )
+ {
+ PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show.c_str());
+ return false;
+ }
}
- Field *fields = result->Fetch();
- wpGuid = fields[0].GetUInt32();
+ pathid = atoi((char*)guid_str);
+ PSendSysMessage("|cff33ffffDEBUG: GUID provided: %d|r", pathid);
- // Free memory
- delete result;
- }
+ point = atoi((char*)point_str);
+ PSendSysMessage("|cff33ffffDEBUG: wpNumber provided: %d|r", point);
- char* arg_str = NULL;
- // Check for argument
- if( (show.find("text") == std::string::npos ) && (show != "del") && (show != "move") && (show != "add"))
- {
- // Text is enclosed in "<>", all other arguments not
- if( show.find("text") != std::string::npos )
- arg_str = strtok((char*)NULL, "<>");
- else
- arg_str = strtok((char*)NULL, " ");
+ // Now we need the GUID of the visual waypoint
+ // -> "del", "move", "add" command
- if( !arg_str)
+ QueryResult *result = WorldDatabase.PQuery( "SELECT wpguid FROM waypoint_data WHERE id = '%u' AND point = '%u'", pathid, point);
+ if(result)
{
- PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
- return false;
- }
- }
-
- sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
- // wpGuid -> GUID of the waypoint creature
- // lowguid -> GUID of the NPC
- // point -> waypoint number
-
- // Special functions:
- // add - move - del -> no args commands
- // Add a waypoint after the selected visual
- if(show == "add" && target)
- {
- PSendSysMessage("DEBUG: wp modify add, GUID: %u", lowguid);
-
- // Get the creature for which we read the waypoint
- CreatureData const* data = objmgr.GetCreatureData(lowguid);
- if(!data)
- {
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
- SetSentErrorMessage(true);
- return false;
- }
+ do
+ {
+ Field *fields = result->Fetch();
+ wpGuid = fields[0].GetUInt32();
+ }while( result->NextRow() );
- Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
- if( !npcCreature )
- {
- PSendSysMessage(LANG_WAYPOINT_NPCNOTFOUND);
- SetSentErrorMessage(true);
- return false;
+ // Free memory
+ delete result;
}
-
- sLog.outDebug("DEBUG: HandleWpModifyCommand - add -- npcCreature");
-
- // What to do:
- // Add the visual spawnpoint (DB only)
- // Adjust the waypoints
- // Respawn the owner of the waypoints
- sLog.outDebug("DEBUG: HandleWpModifyCommand - add");
-
- Player* chr = m_session->GetPlayer();
- Map *map = chr->GetMap();
-
- if(npcCreature)
+ else
{
- npcCreature->GetMotionMaster()->Initialize();
- if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
+ PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, pathid, point);
+ // Select waypoint number from database
+ QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM waypoint_data WHERE point='%d' AND id = '%u'", point, pathid);
+ if(!result)
{
- npcCreature->setDeathState(JUST_DIED);
- npcCreature->Respawn();
+ PSendSysMessage(LANG_WAYPOINT_NOTFOUND, pathid);
+ return true;
}
- }
- // create the waypoint creature
- wpGuid = 0;
- Creature* wpCreature = new Creature;
- if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map,VISUAL_WAYPOINT,0))
- {
- PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT);
- delete wpCreature;
- }
- else
- {
- wpCreature->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
+ Field *fields = result->Fetch();
+ float x = fields[0].GetFloat();
+ float y = fields[1].GetFloat();
+ float z = fields[2].GetFloat();
+ // Cleanup memory
+ delete result;
- if(!wpCreature->IsPositionValid())
+ // Select waypoint number from database
+ // Since we compare float values, we have to deal with
+ // some difficulties.
+ // Here we search for all waypoints that only differ in one from 1 thousand
+ // (0.001) - There is no other way to compare C++ floats with mySQL floats
+ // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
+ const char* maxDIFF = "0.01";
+
+ result = WorldDatabase.PQuery( "SELECT guid FROM creature WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s ) and id=%d",
+ x, maxDIFF, y, maxDIFF, z, maxDIFF, VISUAL_WAYPOINT);
+ if(!result)
{
- sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature->GetGUIDLow(),wpCreature->GetEntry(),wpCreature->GetPositionX(),wpCreature->GetPositionY());
- delete wpCreature;
- }
- else
+
+ PSendSysMessage(LANG_WAYPOINT_WPCREATNOTFOUND, VISUAL_WAYPOINT);
+ return true;
+ }
+ do
{
- wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
- // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
- wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(), map);
- map->Add(wpCreature);
- wpGuid = wpCreature->GetGUIDLow();
- }
- }
+ Field *fields = result->Fetch();
+ wpGuid = fields[0].GetUInt32();
+ }while( result->NextRow() );
- WaypointMgr.AddAfterNode(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), 0, 0, wpGuid);
- if(!wpGuid)
- return false;
+ // Free memory
+ delete result;
- PSendSysMessage(LANG_WAYPOINT_ADDED_NO, point+1);
- return true;
- } // add
+ }
+ }
- if(show == "del" && target)
- {
- PSendSysMessage("DEBUG: wp modify del, GUID: %u", lowguid);
+ sLog.outDebug("DEBUG: HandleWpModifyCommand - Parameters parsed - now execute the command");
- // Get the creature for which we read the waypoint
- CreatureData const* data = objmgr.GetCreatureData(lowguid);
- if(!data)
+ // Check for argument
+ if((show != "del") && (show != "move"))
+ {
+ if( arg_str == NULL )
{
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
- SetSentErrorMessage(true);
+ PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, show_str);
return false;
}
+ }
- Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
+ if(show == "del" && target)
+ {
+ PSendSysMessage("|cff00ff00DEBUG: wp modify del, PathID: |r|cff00ffff%u|r", pathid);
+
+ // wpCreature
- // wpCreature
Creature* wpCreature = NULL;
if( wpGuid != 0 )
{
wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
+ wpCreature->CombatStop();
wpCreature->DeleteFromDB();
- wpCreature->CleanupsBeforeDelete();
wpCreature->AddObjectToRemoveList();
}
- // What to do:
- // Remove the visual spawnpoint
- // Adjust the waypoints
- // Respawn the owner of the waypoints
-
- WaypointMgr.DeleteNode(lowguid, point);
-
- if(npcCreature)
- {
- // Any waypoints left?
- QueryResult *result2 = WorldDatabase.PQuery( "SELECT point FROM creature_movement WHERE id = '%u'",lowguid);
- if(!result2)
- {
- npcCreature->SetDefaultMovementType(RANDOM_MOTION_TYPE);
- }
- else
- {
- npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
- delete result2;
- }
- npcCreature->GetMotionMaster()->Initialize();
- if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
- {
- npcCreature->setDeathState(JUST_DIED);
- npcCreature->Respawn();
- }
- npcCreature->SaveToDB();
- }
+ WorldDatabase.PExecuteLog("DELETE FROM waypoint_data WHERE id='%u' AND point='%u'",
+ pathid, point);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET point=point-1 WHERE id='%u' AND point>'%u'",
+ pathid, point);
PSendSysMessage(LANG_WAYPOINT_REMOVED);
return true;
@@ -2628,32 +2807,21 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
if(show == "move" && target)
{
- PSendSysMessage("DEBUG: wp move, GUID: %u", lowguid);
+ PSendSysMessage("|cff00ff00DEBUG: wp move, PathID: |r|cff00ffff%u|r", pathid);
Player *chr = m_session->GetPlayer();
Map *map = chr->GetMap();
{
- // Get the creature for which we read the waypoint
- CreatureData const* data = objmgr.GetCreatureData(lowguid);
- if(!data)
- {
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
- SetSentErrorMessage(true);
- return false;
- }
-
- Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
-
- // wpCreature
- Creature* wpCreature = NULL;
+ // wpCreature
+ Creature* wpCreature = NULL;
// What to do:
// Move the visual spawnpoint
// Respawn the owner of the waypoints
if( wpGuid != 0 )
{
wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(wpGuid, VISUAL_WAYPOINT, HIGHGUID_UNIT));
+ wpCreature->CombatStop();
wpCreature->DeleteFromDB();
- wpCreature->CleanupsBeforeDelete();
wpCreature->AddObjectToRemoveList();
// re-create
Creature* wpCreature2 = new Creature;
@@ -2663,7 +2831,6 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
delete wpCreature2;
return false;
}
-
wpCreature2->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), chr->GetOrientation());
if(!wpCreature2->IsPositionValid())
@@ -2680,81 +2847,38 @@ bool ChatHandler::HandleWpModifyCommand(const char* args)
//MapManager::Instance().GetMap(npcCreature->GetMapId())->Add(wpCreature2);
}
- WaypointMgr.SetNodePosition(lowguid, point, chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ());
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET position_x = '%f',position_y = '%f',position_z = '%f' where id = '%u' AND point='%u'",
+ chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), pathid, point );
- if(npcCreature)
- {
- npcCreature->GetMotionMaster()->Initialize();
- if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
- {
- npcCreature->setDeathState(JUST_DIED);
- npcCreature->Respawn();
- }
- }
PSendSysMessage(LANG_WAYPOINT_CHANGED);
}
return true;
} // move
- // Create creature - npc that has the waypoint
- CreatureData const* data = objmgr.GetCreatureData(lowguid);
- if(!data)
- {
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
- SetSentErrorMessage(true);
- return false;
- }
- // set in game textids not supported
- if( show == "textid1" || show == "textid2" || show == "textid3" ||
- show == "textid4" || show == "textid5" )
+ const char *text = arg_str;
+
+ if( text == 0 )
{
- return false;
+ // show_str check for present in list of correct values, no sql injection possible
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s=NULL WHERE id='%u' AND point='%u'",
+ show_str, pathid, point);
}
-
- WaypointMgr.SetNodeText(lowguid, point, show_str, arg_str);
-
- Creature* npcCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), MAKE_NEW_GUID(lowguid, data->id, HIGHGUID_UNIT));
- if(npcCreature)
+ else
{
- npcCreature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
- npcCreature->GetMotionMaster()->Initialize();
- if(npcCreature->isAlive()) // dead creature will reset movement generator at respawn
- {
- npcCreature->setDeathState(JUST_DIED);
- npcCreature->Respawn();
- }
+ // show_str check for present in list of correct values, no sql injection possible
+ std::string text2 = text;
+ WorldDatabase.escape_string(text2);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET %s='%s' WHERE id='%u' AND point='%u'",
+ show_str, text2.c_str(), pathid, point);
}
- PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
+
+ PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str);
return true;
}
-/**
- * .wp show info | on | off
- *
- * info -> User has selected a visual waypoint before
- *
- * info <GUID> <WPNUM> -> User did not select a visual waypoint and
- * provided the GUID of the NPC and the number of
- * the waypoint.
- *
- * on -> User has selected an NPC; all visual waypoints for this
- * NPC are added to the world
- *
- * on <GUID> -> User did not select an NPC - instead the GUID of the
- * NPC is provided. All visual waypoints for this NPC
- * are added from the world.
- *
- * off -> User has selected an NPC; all visual waypoints for this
- * NPC are removed from the world.
- *
- * on <GUID> -> User did not select an NPC - instead the GUID of the
- * NPC is provided. All visual waypoints for this NPC
- * are removed from the world.
- *
- *
- */
+
bool ChatHandler::HandleWpShowCommand(const char* args)
{
sLog.outDebug("DEBUG: HandleWpShowCommand");
@@ -2771,19 +2895,16 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
// second arg: GUID (optional, if a creature is selected)
char* guid_str = strtok((char*)NULL, " ");
sLog.outDebug("DEBUG: HandleWpShowCommand: show_str: %s guid_str: %s", show_str, guid_str);
- //if (!guid_str) {
- // return false;
- //}
+
+ uint32 pathid = 0;
+ Creature* target = getSelectedCreature();
+
+ // Did player provide a PathID?
- // Did user provide a GUID
- // or did the user select a creature?
- // -> variable lowguid is filled with the GUID
- Creature* target = getSelectedCreature();
- // Did player provide a GUID?
if (!guid_str)
{
sLog.outDebug("DEBUG: HandleWpShowCommand: !guid_str");
- // No GUID provided
+ // No PathID provided
// -> Player must have selected a creature
if(!target)
@@ -2792,11 +2913,14 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
SetSentErrorMessage(true);
return false;
}
- }
+
+ pathid = target->GetWaypointPath();
+ }
+
else
{
- sLog.outDebug("DEBUG: HandleWpShowCommand: GUID provided");
- // GUID provided
+ sLog.outDebug("|cff00ff00DEBUG: HandleWpShowCommand: PathID provided|r");
+ // PathID provided
// Warn if player also selected a creature
// -> Creature selection is ignored <-
if(target)
@@ -2804,118 +2928,86 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
SendSysMessage(LANG_WAYPOINT_CREATSELECTED);
}
- uint32 lowguid = atoi((char*)guid_str);
+ pathid = atoi((char*)guid_str);
+ }
- CreatureData const* data = objmgr.GetCreatureData(lowguid);
- if(!data)
- {
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
- SetSentErrorMessage(true);
- return false;
- }
- target = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT));
+ sLog.outDebug("DEBUG: HandleWpShowCommand: danach");
- if(!target)
- {
- PSendSysMessage(LANG_WAYPOINT_CREATNOTFOUND, lowguid);
- SetSentErrorMessage(true);
- return false;
- }
- }
- uint32 lowguid = target->GetDBTableGUIDLow();
std::string show = show_str;
uint32 Maxpoint;
- sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str);
+ sLog.outDebug("DEBUG: HandleWpShowCommand: PathID: %u", pathid);
+
+ //PSendSysMessage("wpshow - show: %s", show);
// Show info for the selected waypoint
if(show == "info")
- {
- PSendSysMessage("DEBUG: wp info, GUID: %u", lowguid);
- // Check if the user did specify a visual waypoint
+ {
+
+ // Check if the user did specify a visual waypoint
if( target->GetEntry() != VISUAL_WAYPOINT )
+
{
PSendSysMessage(LANG_WAYPOINT_VP_SELECT);
SetSentErrorMessage(true);
return false;
}
- //PSendSysMessage("wp on, GUID: %u", lowguid);
- //pCreature->GetPositionX();
+ QueryResult *result = WorldDatabase.PQuery( "SELECT id, point, delay, move_flag, action, action_chance FROM waypoint_data WHERE wpguid = %u", target->GetGUIDLow());
+
+ if(!result)
- QueryResult *result =
- WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE wpguid = %u",
- target->GetGUIDLow() );
- if(!result)
{
- // Since we compare float values, we have to deal with
- // some difficulties.
- // Here we search for all waypoints that only differ in one from 1 thousand
- // (0.001) - There is no other way to compare C++ floats with mySQL floats
- // See also: http://dev.mysql.com/doc/refman/5.0/en/problems-with-float.html
- const char* maxDIFF = "0.01";
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDSEARCH, target->GetGUID());
-
- result = WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, model1, model2 FROM creature_movement WHERE (abs(position_x - %f) <= %s ) and (abs(position_y - %f) <= %s ) and (abs(position_z - %f) <= %s )",
- target->GetPositionX(), maxDIFF, target->GetPositionY(), maxDIFF, target->GetPositionZ(), maxDIFF);
- if(!result)
- {
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, lowguid);
- SetSentErrorMessage(true);
- return false;
- }
- }
- do
+ SendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM);
+ return true;
+ }
+
+ SendSysMessage("|cff00ffffDEBUG: wp show info:|r");
+
+ do
{
Field *fields = result->Fetch();
- uint32 creGUID = fields[0].GetUInt32();
- uint32 point = fields[1].GetUInt32();
- int waittime = fields[2].GetUInt32();
- uint32 emote = fields[3].GetUInt32();
- uint32 spell = fields[4].GetUInt32();
- uint32 textid[MAX_WAYPOINT_TEXT];
- for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
- textid[i] = fields[5+i].GetUInt32();
- uint32 model1 = fields[10].GetUInt32();
- uint32 model2 = fields[11].GetUInt32();
-
- // Get the creature for which we read the waypoint
- Creature* wpCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(creGUID,VISUAL_WAYPOINT,HIGHGUID_UNIT));
-
- PSendSysMessage(LANG_WAYPOINT_INFO_TITLE, point, (wpCreature ? wpCreature->GetName() : "<not found>"), creGUID);
- PSendSysMessage(LANG_WAYPOINT_INFO_WAITTIME, waittime);
- PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 1, model1);
- PSendSysMessage(LANG_WAYPOINT_INFO_MODEL, 2, model2);
- PSendSysMessage(LANG_WAYPOINT_INFO_EMOTE, emote);
- PSendSysMessage(LANG_WAYPOINT_INFO_SPELL, spell);
- for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
- PSendSysMessage(LANG_WAYPOINT_INFO_TEXT, i+1, textid[i], (textid[i] ? GetTrinityString(textid[i]) : ""));
-
- }while( result->NextRow() );
- // Cleanup memory
+ pathid = fields[0].GetUInt32();
+ uint32 point = fields[1].GetUInt32();
+ uint32 delay = fields[2].GetUInt32();
+ uint32 flag = fields[3].GetUInt32();
+ uint32 ev_id = fields[4].GetUInt32();
+ uint32 ev_chance = fields[5].GetUInt32();
+
+ PSendSysMessage("|cff00ff00Show info: for current point: |r|cff00ffff%u|r|cff00ff00, Path ID: |r|cff00ffff%u|r", point, pathid);
+ PSendSysMessage("|cff00ff00Show info: delay: |r|cff00ffff%u|r", delay);
+ PSendSysMessage("|cff00ff00Show info: Move flag: |r|cff00ffff%u|r", flag);
+ PSendSysMessage("|cff00ff00Show info: Waypoint event: |r|cff00ffff%u|r", ev_id);
+ PSendSysMessage("|cff00ff00Show info: Event chance: |r|cff00ffff%u|r", ev_chance);
+ }while( result->NextRow() );
+
+ // Cleanup memory
delete result;
return true;
}
if(show == "on")
- {
- PSendSysMessage("DEBUG: wp on, GUID: %u", lowguid);
-
- QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM creature_movement WHERE id = '%u'",lowguid);
- if(!result)
+ {
+ QueryResult *result = WorldDatabase.PQuery( "SELECT point, position_x,position_y,position_z FROM waypoint_data WHERE id = '%u'", pathid);
+
+ if(!result)
{
- PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
+ SendSysMessage("|cffff33ffPath no found.|r");
SetSentErrorMessage(true);
return false;
}
- // Delete all visuals for this NPC
- QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM creature_movement WHERE id = '%u' and wpguid <> 0", lowguid);
- if(result2)
+
+ PSendSysMessage("|cff00ff00DEBUG: wp on, PathID: |cff00ffff%u|r", pathid);
+
+ // Delete all visuals for this NPC
+ QueryResult *result2 = WorldDatabase.PQuery( "SELECT wpguid FROM waypoint_data WHERE id = '%u' and wpguid <> 0", pathid);
+
+ if(result2)
{
bool hasError = false;
do
@@ -2932,14 +3024,16 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
}
else
{
+ pCreature->CombatStop();
pCreature->DeleteFromDB();
- pCreature->CleanupsBeforeDelete();
pCreature->AddObjectToRemoveList();
}
}while( result2->NextRow() );
- delete result2;
- if( hasError )
+
+ delete result2;
+
+ if( hasError )
{
PSendSysMessage(LANG_WAYPOINT_TOOFAR1);
PSendSysMessage(LANG_WAYPOINT_TOOFAR2);
@@ -2969,10 +3063,10 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
delete result;
return false;
}
-
- wpCreature->Relocate(x, y, z, o);
-
- if(!wpCreature->IsPositionValid())
+
+ wpCreature->Relocate(x, y, z, o);
+
+ if(!wpCreature->IsPositionValid())
{
sLog.outError("ERROR: Creature (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)",wpCreature->GetGUIDLow(),wpCreature->GetEntry(),wpCreature->GetPositionX(),wpCreature->GetPositionY());
delete wpCreature;
@@ -2980,31 +3074,36 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
return false;
}
- wpCreature->SetVisibility(VISIBILITY_OFF);
- sLog.outDebug("DEBUG: UPDATE creature_movement SET wpguid = '%u");
+ sLog.outDebug("DEBUG: UPDATE waypoint_data SET wpguid = '%u");
// set "wpguid" column to the visual waypoint
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), lowguid, point);
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), pathid, point);
wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
- // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map);
map->Add(wpCreature);
- //MapManager::Instance().GetMap(wpCreature->GetMapId())->Add(wpCreature);
- }while( result->NextRow() );
+
+ if(target)
+ {
+ wpCreature->SetDisplayId(target->GetDisplayId());
+ wpCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5);
+ }
+ }
+ while( result->NextRow() );
- // Cleanup memory
+ SendSysMessage("|cff00ff00Showing the current creature's path.|r");
+ // Cleanup memory
delete result;
return true;
}
if(show == "first")
{
- PSendSysMessage("DEBUG: wp first, GUID: %u", lowguid);
+ PSendSysMessage("|cff00ff00DEBUG: wp first, GUID: %u|r", pathid);
- QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point='1' AND id = '%u'",lowguid);
+ QueryResult *result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM waypoint_data WHERE point='1' AND id = '%u'",pathid);
if(!result)
{
- PSendSysMessage(LANG_WAYPOINT_NOTFOUND, lowguid);
+ PSendSysMessage(LANG_WAYPOINT_NOTFOUND, pathid);
SetSentErrorMessage(true);
return false;
}
@@ -3037,22 +3136,27 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
delete result;
return false;
}
-
- pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
+
+ pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
map->Add(pCreature);
- //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "First Waypoint");
-
- // Cleanup memory
+
+ if(target)
+ {
+ pCreature->SetDisplayId(target->GetDisplayId());
+ pCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5);
+ }
+
+ // Cleanup memory
delete result;
return true;
}
if(show == "last")
{
- PSendSysMessage("DEBUG: wp last, GUID: %u", lowguid);
+ PSendSysMessage("|cff00ff00DEBUG: wp last, PathID: |r|cff00ffff%u|r", pathid);
- QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'",lowguid);
+ QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM waypoint_data WHERE id = '%u'",pathid);
if( result )
{
Maxpoint = (*result)[0].GetUInt32();
@@ -3062,10 +3166,10 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
else
Maxpoint = 0;
- result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM creature_movement WHERE point ='%u' AND id = '%u'",Maxpoint, lowguid);
+ result = WorldDatabase.PQuery( "SELECT position_x,position_y,position_z FROM waypoint_data WHERE point ='%u' AND id = '%u'",Maxpoint, pathid);
if(!result)
{
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, lowguid);
+ PSendSysMessage(LANG_WAYPOINT_NOTFOUNDLAST, pathid);
SetSentErrorMessage(true);
return false;
}
@@ -3097,19 +3201,25 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
delete result;
return false;
}
-
- pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
+
+ pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()));
pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map);
map->Add(pCreature);
- //player->PlayerTalkClass->SendPointOfInterest(x, y, 6, 6, 0, "Last Waypoint");
- // Cleanup memory
+
+ if(target)
+ {
+ pCreature->SetDisplayId(target->GetDisplayId());
+ pCreature->SetFloatValue(OBJECT_FIELD_SCALE_X, 0.5);
+ }
+
+ // Cleanup memory
delete result;
return true;
}
if(show == "off")
{
- QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%d'", VISUAL_WAYPOINT);
+ QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature WHERE id = '%u'", 1);
if(!result)
{
SendSysMessage(LANG_WAYPOINT_VP_NOTFOUND);
@@ -3123,8 +3233,6 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
uint32 guid = fields[0].GetUInt32();
Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(),MAKE_NEW_GUID(guid,VISUAL_WAYPOINT,HIGHGUID_UNIT));
- //Creature* pCreature = ObjectAccessor::GetCreature(*m_session->GetPlayer(), guid);
-
if(!pCreature)
{
PSendSysMessage(LANG_WAYPOINT_NOTREMOVED, guid);
@@ -3133,13 +3241,15 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
}
else
{
+ pCreature->CombatStop();
+
pCreature->DeleteFromDB();
- pCreature->CleanupsBeforeDelete();
+
pCreature->AddObjectToRemoveList();
}
}while(result->NextRow());
// set "wpguid" column to "empty" - no visual waypoint spawned
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0'");
+ WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '0'");
if( hasError )
{
@@ -3155,155 +3265,12 @@ bool ChatHandler::HandleWpShowCommand(const char* args)
return true;
}
- PSendSysMessage("DEBUG: wpshow - no valid command found");
-
- return true;
-} // HandleWpShowCommand
-
-bool ChatHandler::HandleWpExportCommand(const char *args)
-{
- if(!*args)
- return false;
-
- // Next arg is: <GUID> <ARGUMENT>
-
- // Did user provide a GUID
- // or did the user select a creature?
- // -> variable lowguid is filled with the GUID of the NPC
- uint32 lowguid = 0;
- Creature* target = getSelectedCreature();
- char* arg_str = NULL;
- if (target)
- {
- if (target->GetEntry() != VISUAL_WAYPOINT)
- lowguid = target->GetGUIDLow();
- else
- {
- QueryResult *result = WorldDatabase.PQuery( "SELECT id FROM creature_movement WHERE wpguid = %u LIMIT 1", target->GetGUIDLow() );
- if (!result)
- {
- PSendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetGUIDLow());
- return true;
- }
- Field *fields = result->Fetch();
- lowguid = fields[0].GetUInt32();;
- delete result;
- }
-
- arg_str = strtok((char*)args, " ");
- }
- else
- {
- // user provided <GUID>
- char* guid_str = strtok((char*)args, " ");
- if( !guid_str )
- {
- SendSysMessage(LANG_WAYPOINT_NOGUID);
- return false;
- }
- lowguid = atoi((char*)guid_str);
-
- arg_str = strtok((char*)NULL, " ");
- }
-
- if( !arg_str)
- {
- PSendSysMessage(LANG_WAYPOINT_ARGUMENTREQ, "export");
- return false;
- }
-
- PSendSysMessage("DEBUG: wp export, GUID: %u", lowguid);
-
- QueryResult *result = WorldDatabase.PQuery(
- // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- "SELECT point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, id FROM creature_movement WHERE id = '%u' ORDER BY point", lowguid );
-
- if (!result)
- {
- PSendSysMessage(LANG_WAYPOINT_NOTHINGTOEXPORT);
- SetSentErrorMessage(true);
- return false;
- }
-
- std::ofstream outfile;
- outfile.open (arg_str);
-
- do
- {
- Field *fields = result->Fetch();
-
- outfile << "INSERT INTO creature_movement ";
- outfile << "( id, point, position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5 ) VALUES ";
-
- outfile << "( ";
- outfile << fields[15].GetUInt32(); // id
- outfile << ", ";
- outfile << fields[0].GetUInt32(); // point
- outfile << ", ";
- outfile << fields[1].GetFloat(); // position_x
- outfile << ", ";
- outfile << fields[2].GetFloat(); // position_y
- outfile << ", ";
- outfile << fields[3].GetUInt32(); // position_z
- outfile << ", ";
- outfile << fields[4].GetUInt32(); // orientation
- outfile << ", ";
- outfile << fields[5].GetUInt32(); // model1
- outfile << ", ";
- outfile << fields[6].GetUInt32(); // model2
- outfile << ", ";
- outfile << fields[7].GetUInt16(); // waittime
- outfile << ", ";
- outfile << fields[8].GetUInt32(); // emote
- outfile << ", ";
- outfile << fields[9].GetUInt32(); // spell
- outfile << ", ";
- outfile << fields[10].GetUInt32(); // textid1
- outfile << ", ";
- outfile << fields[11].GetUInt32(); // textid2
- outfile << ", ";
- outfile << fields[12].GetUInt32(); // textid3
- outfile << ", ";
- outfile << fields[13].GetUInt32(); // textid4
- outfile << ", ";
- outfile << fields[14].GetUInt32(); // textid5
- outfile << ");\n ";
-
- } while( result->NextRow() );
- delete result;
-
- PSendSysMessage(LANG_WAYPOINT_EXPORTED);
- outfile.close();
+ PSendSysMessage("|cffff33ffDEBUG: wpshow - no valid command found|r");
return true;
}
-bool ChatHandler::HandleWpImportCommand(const char *args)
-{
- if(!*args)
- return false;
-
- char* arg_str = strtok((char*)args, " ");
- if (!arg_str)
- return false;
-
- std::string line;
- std::ifstream infile (arg_str);
- if (infile.is_open())
- {
- while (! infile.eof() )
- {
- getline (infile,line);
- //cout << line << endl;
- QueryResult *result = WorldDatabase.Query(line.c_str());
- delete result;
- }
- infile.close();
- }
- PSendSysMessage(LANG_WAYPOINT_IMPORTED);
-
- return true;
-}
+//////////// WAYPOINT COMMANDS //
//rename characters
bool ChatHandler::HandleRenameCommand(const char* args)
diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp
index 51b9a092ba3..a5c6f54016c 100644
--- a/src/game/Level3.cpp
+++ b/src/game/Level3.cpp
@@ -136,7 +136,8 @@ bool ChatHandler::HandleReloadAllScriptsCommand(const char*)
HandleReloadSpellScriptsCommand("a");
SendGlobalSysMessage("DB tables `*_scripts` reloaded.");
HandleReloadDbScriptStringCommand("a");
- return true;
+ HandleReloadWpScriptsCommand("a");
+ return true;
}
bool ChatHandler::HandleReloadAllSpellCommand(const char*)
@@ -542,6 +543,26 @@ bool ChatHandler::HandleReloadEventScriptsCommand(const char* arg)
return true;
}
+bool ChatHandler::HandleReloadWpScriptsCommand(const char* arg)
+{
+ if(sWorld.IsScriptScheduled())
+ {
+ SendSysMessage("DB scripts used currently, please attempt reload later.");
+ SetSentErrorMessage(true);
+ return false;
+ }
+
+ if(*arg!='a')
+ sLog.outString( "Re-Loading Scripts from `event_scripts`...");
+
+ objmgr.LoadWaypointScripts();
+
+ if(*arg!='a')
+ SendGlobalSysMessage("DB table `event_scripts` reloaded.");
+
+ return true;
+}
+
bool ChatHandler::HandleReloadQuestEndScriptsCommand(const char* arg)
{
if(sWorld.IsScriptScheduled())
diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp
index d3167e180a0..0195e3ebdf6 100644
--- a/src/game/MotionMaster.cpp
+++ b/src/game/MotionMaster.cpp
@@ -319,6 +319,31 @@ void MotionMaster::Mutate(MovementGenerator *m)
push(m);
}
+void MotionMaster::MovePath(uint32 path_id, bool repeatable)
+{
+ if(!path_id)
+ return;
+ //We set waypoint movement as new default movement generator
+ // clear ALL movement generators (including default)
+ while(!empty())
+ {
+ MovementGenerator *curr = top();
+ curr->Finalize(*i_owner);
+ pop();
+ if( !isStatic( curr ) )
+ delete curr;
+ }
+
+ sLog.outError("attempting to move");
+ //i_owner->GetTypeId()==TYPEID_PLAYER ?
+ //Mutate(new WaypointMovementGenerator<Player>(path_id, repeatable)):
+ Mutate(new WaypointMovementGenerator<Creature>(path_id, repeatable));
+
+ DEBUG_LOG("%s (GUID: %u) start moving over path(Id:%u, repeatable: %s)",
+ i_owner->GetTypeId()==TYPEID_PLAYER ? "Player" : "Creature",
+ i_owner->GetGUIDLow(), path_id, repeatable ? "YES" : "NO" );
+}
+
void MotionMaster::propagateSpeedChange()
{
Impl::container_type::iterator it = Impl::c.begin();
diff --git a/src/game/MotionMaster.h b/src/game/MotionMaster.h
index f6d244db2db..3a17b8e135e 100644
--- a/src/game/MotionMaster.h
+++ b/src/game/MotionMaster.h
@@ -80,6 +80,7 @@ class TRINITY_DLL_SPEC MotionMaster : private std::stack<MovementGenerator *>
void MovePoint(uint32 id, float x,float y,float z);
void MoveTaxiFlight(uint32 path, uint32 pathnode);
void MoveDistract(uint32 time);
+ void MovePath(uint32 path_id, bool repeatable);
MovementGeneratorType GetCurrentMovementGeneratorType() const;
diff --git a/src/game/MovementGeneratorImpl.h b/src/game/MovementGeneratorImpl.h
index c8270094b52..43c18ac6866 100644
--- a/src/game/MovementGeneratorImpl.h
+++ b/src/game/MovementGeneratorImpl.h
@@ -27,7 +27,6 @@ template<class MOVEMENT_GEN>
inline MovementGenerator*
MovementGeneratorFactory<MOVEMENT_GEN>::Create(void *data) const
{
- Creature* creature = reinterpret_cast<Creature *>(data);
- return (new MOVEMENT_GEN(*creature));
+ return (new MOVEMENT_GEN());
}
#endif
diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index 35a021ac7c7..2872f29cdaf 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -1534,6 +1534,25 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float
return go;
}
+Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, uint32 duration, CreatureAI* (*GetAI)(Creature*))
+{
+ TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
+ Creature* summon = SummonCreature(WORLD_TRIGGER, x, y, z, ang, summonType, 0);
+ if(!summon)
+ return NULL;
+
+ //summon->SetName(GetName());
+ if(GetTypeId()==TYPEID_PLAYER || GetTypeId()==TYPEID_UNIT)
+ {
+ summon->setFaction(((Unit*)this)->getFaction());
+ summon->SetLevel(((Unit*)this)->getLevel());
+ }
+
+ if(GetAI)
+ summon->AIM_Initialize(GetAI(summon));
+ return summon;
+}
+
void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float absAngle ) const
{
x = GetPositionX() + (GetObjectSize() + distance2d) * cos(absAngle);
diff --git a/src/game/Object.h b/src/game/Object.h
index 2fcd6692288..a63458e6133 100644
--- a/src/game/Object.h
+++ b/src/game/Object.h
@@ -28,6 +28,7 @@
#include "GameSystem/GridReference.h"
#include "ObjectDefines.h"
#include "GridDefines.h"
+#include "CreatureAI.h"
#include <set>
#include <string>
@@ -457,6 +458,7 @@ class TRINITY_DLL_SPEC WorldObject : public Object
Map const* GetBaseMap() const;
Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime);
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime);
+ Creature* SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI* (*GetAI)(Creature*) = NULL);
bool isActive() const { return m_isActive; }
void setActive(bool isActive);
protected:
diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp
index 36d4317b3ec..1d359a2df7c 100644
--- a/src/game/ObjectMgr.cpp
+++ b/src/game/ObjectMgr.cpp
@@ -54,6 +54,7 @@ ScriptMapMap sQuestStartScripts;
ScriptMapMap sSpellScripts;
ScriptMapMap sGameObjectScripts;
ScriptMapMap sEventScripts;
+ScriptMapMap sWaypointScripts;
bool normalizePlayerName(std::string& name)
{
@@ -4110,6 +4111,19 @@ void ObjectMgr::LoadEventScripts()
}
}
+//Load WP Scripts
+void ObjectMgr::LoadWaypointScripts()
+{
+ LoadScripts(sWaypointScripts, "waypoint_scripts");
+
+ for(ScriptMapMap::const_iterator itr = sWaypointScripts.begin(); itr != sWaypointScripts.end(); ++itr)
+ {
+ QueryResult *query = WorldDatabase.PQuery("SELECT * FROM `waypoint_scripts` WHERE `id` = %u", itr->first);
+ if(!query || !query->GetRowCount())
+ sLog.outErrorDb("There is no waypoint which links to the waypoint script %u", itr->first);
+ }
+}
+
void ObjectMgr::LoadItemTexts()
{
QueryResult *result = CharacterDatabase.Query("SELECT id, text FROM item_text");
@@ -7481,7 +7495,7 @@ void ObjectMgr::LoadDbScriptStrings()
CheckScripts(sGameObjectScripts,ids);
CheckScripts(sEventScripts,ids);
- WaypointMgr.CheckTextsExistance(ids);
+ CheckScripts(sWaypointScripts,ids);
for(std::set<int32>::const_iterator itr = ids.begin(); itr != ids.end(); ++itr)
sLog.outErrorDb( "Table `db_script_string` has unused string id %u", *itr);
diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h
index 8c7f8728b0b..7dc6c1f8a9f 100644
--- a/src/game/ObjectMgr.h
+++ b/src/game/ObjectMgr.h
@@ -98,6 +98,7 @@ extern ScriptMapMap sQuestStartScripts;
extern ScriptMapMap sSpellScripts;
extern ScriptMapMap sGameObjectScripts;
extern ScriptMapMap sEventScripts;
+extern ScriptMapMap sWaypointScripts;
struct AreaTrigger
{
@@ -531,6 +532,7 @@ class ObjectMgr
void LoadQuestStartScripts();
void LoadEventScripts();
void LoadSpellScripts();
+ void LoadWaypointScripts();
bool LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value);
bool LoadTrinityStrings() { return LoadTrinityStrings(WorldDatabase,"trinity_string",MIN_TRINITY_STRING_ID,MAX_TRINITY_STRING_ID); }
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index d57f86a0d80..5b5c859097f 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -1330,8 +1330,14 @@ void Player::setDeathState(DeathState s)
bool cur = isAlive();
- if(s == JUST_DIED && cur)
+ if(s == JUST_DIED)
{
+ if(!cur)
+ {
+ sLog.outError("setDeathState: attempt to kill a dead player %s(%d)", GetName(), GetGUIDLow());
+ return;
+ }
+
// drunken state is cleared on death
SetDrunkValue(0);
// lost combo points at any target (targeted combo points clear in Unit::setDeathState)
@@ -13910,6 +13916,9 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
m_movementInfo.t_o = 0.0f;
}
+ if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND)))
+ return false;
+
// load the player's map here if it's not already loaded
Map *map = GetMap();
if (!map)
@@ -13919,11 +13928,13 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
{
SetMapId(at->target_mapId);
Relocate(at->target_X, at->target_Y, at->target_Z, GetOrientation());
+ sLog.outError("Player (guidlow %d) is teleported to gobacktrigger (Map: %u X: %f Y: %f Z: %f O: %f).",guid,GetMapId(),GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
}
else
{
SetMapId(m_homebindMapId);
Relocate(m_homebindX, m_homebindY, m_homebindZ, GetOrientation());
+ sLog.outError("Player (guidlow %d) is teleported to home (Map: %u X: %f Y: %f Z: %f O: %f).",guid,GetMapId(),GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
}
map = GetMap();
@@ -14168,8 +14179,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
m_social = sSocialMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSOCIALLIST), GetGUIDLow());
- if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND)))
- return false;
+ //if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND)))
+ // return false;
// check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES
// note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded
diff --git a/src/game/RandomMovementGenerator.h b/src/game/RandomMovementGenerator.h
index 229761423e6..2825bc306a8 100644
--- a/src/game/RandomMovementGenerator.h
+++ b/src/game/RandomMovementGenerator.h
@@ -31,7 +31,7 @@ class TRINITY_DLL_SPEC RandomMovementGenerator
: public MovementGeneratorMedium< T, RandomMovementGenerator<T> >
{
public:
- RandomMovementGenerator(const Unit &) : i_nextMoveTime(0) {}
+ RandomMovementGenerator() : i_nextMoveTime(0) {}
void _setRandomLocation(T &);
void Initialize(T &);
diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h
index 0d40b4c50dc..3edc724b7a8 100644
--- a/src/game/SharedDefines.h
+++ b/src/game/SharedDefines.h
@@ -788,7 +788,7 @@ enum Targets
TARGET_PET = 5,
//TARGET_UNIT_PET
TARGET_CHAIN_DAMAGE = 6,
- //TARGET_UNIT_TARGET_ENEMY
+ TARGET_UNIT_TARGET_ENEMY = 6,
TARGET_UNIT_AREA_ENTRY = 7,
TARGET_AREAEFFECT_CUSTOM = 8,
//TARGET_UNIT_AREA_ENTRY_GROUND
@@ -806,7 +806,7 @@ enum Targets
TARGET_ALL_PARTY_AROUND_CASTER = 20,
//TARGET_UNIT_PARTY_CASTER
TARGET_SINGLE_FRIEND = 21,
- //TARGET_UNIT_TARGET_ALLY
+ TARGET_UNIT_TARGET_ALLY = 21,
TARGET_ALL_AROUND_CASTER = 22, // used only in TargetA, target selection dependent from TargetB
//TARGET_DEST_CASTER
TARGET_GAMEOBJECT = 23,
@@ -833,7 +833,7 @@ enum Targets
TARGET_ALL_PARTY_AROUND_CASTER_2 = 34, // used in Tranquility
//TARGET_UNIT_AREA_PARTY_GROUND
TARGET_SINGLE_PARTY = 35,
- //TARGET_UNIT_TARGET_PARTY
+ TARGET_UNIT_TARGET_PARTY = 35,
TARGET_DEST_CASTER_RANDOM_UNKNOWN = 36, //unknown
TARGET_AREAEFFECT_PARTY = 37,
//TARGET_UNIT_PARTY_TARGET
@@ -864,7 +864,7 @@ enum Targets
TARGET_RANDOM_RAID_MEMBER = 56,
//TARGET_UNIT_AREA_RAID
TARGET_SINGLE_FRIEND_2 = 57,
- //TARGET_UNIT_TARGET_RAID
+ TARGET_UNIT_TARGET_RAID = 57,
TARGET_UNIT_CONE_ALLY = 59,
TARGET_UNIT_AREA_SCRIPT = 60,
TARGET_AREAEFFECT_PARTY_AND_CLASS = 61,
@@ -908,6 +908,7 @@ enum SpellMissInfo
SPELL_MISS_DEFLECT = 9,
SPELL_MISS_ABSORB = 10,
SPELL_MISS_REFLECT = 11,
+ SPELL_MISS_KILL = 12, // kill grounding totem
};
enum SpellHitType
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 8a5585aad21..78809841e3a 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -286,8 +286,6 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
m_caster = Caster;
m_selfContainer = NULL;
m_triggeringContainer = triggeringContainer;
- m_magnetPair.first = false;
- m_magnetPair.second = NULL;
m_referencedFromCurrentSpell = false;
m_executedCurrently = false;
m_delayAtDamageCount = 0;
@@ -1037,6 +1035,12 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
if (target->reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him
DoSpellHitOnUnit(m_caster, mask);
}
+ else if (missInfo == SPELL_MISS_KILL)
+ {
+ // remove spell_magnet aura after first spell redirect and destroy target if its totem
+ if(unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->isTotem())
+ unit->Kill(unit);
+ }
else //TODO: This is a hack. need fix
{
uint32 tempMask = 0;
@@ -1169,14 +1173,6 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
if(!unit || !effectMask)
return;
- // remove spell_magnet aura after first spell redirect and destroy target if its totem
- if(m_magnetPair.first && m_magnetPair.second && m_magnetPair.second == unit)
- {
- if(unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->isTotem())
- unit->DealDamage(unit,unit->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
- return;
- }
-
// Recheck immune (only for delayed spells)
if( m_spellInfo->speed &&
!(m_spellInfo->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY)
@@ -1199,8 +1195,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
}
unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL);
- //TODO: find a better way to judge CC auras
- if(m_spellInfo->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE)
+ if(spellmgr.GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR_CU_AURA_CC)
unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CC);
}
else
@@ -1475,7 +1470,8 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const u
y = m_caster->GetPositionY();
}
- CellPair p(Trinity::ComputeCellPair(x, y));
+ float x_off, y_off;
+ CellPair p(Trinity::ComputeCellPair(x, y, x_off, y_off));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
@@ -1486,12 +1482,12 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const u
//if(TargetType != SPELL_TARGETS_ENTRY)
{
TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
- cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
+ cell_lock->Visit(cell_lock, world_object_notifier, *m_caster->GetMap(), radius, x_off, y_off);
}
if(!(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY))
{
TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier);
- cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
+ cell_lock->Visit(cell_lock, grid_object_notifier, *m_caster->GetMap(), radius, x_off, y_off);
}
}
@@ -4501,26 +4497,8 @@ int16 Spell::PetCanCast(Unit* target)
if(!_target->isAlive())
return SPELL_FAILED_BAD_TARGETS;
- if(IsPositiveSpell(m_spellInfo->Id))
- {
- if(m_caster->IsHostileTo(_target))
- return SPELL_FAILED_BAD_TARGETS;
- }
- else
- {
- bool duelvsplayertar = false;
- for(int j=0;j<3;j++)
- {
- //TARGET_DUELVSPLAYER is positive AND negative
- duelvsplayertar |= (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DUELVSPLAYER);
- }
- // AoE spells have the caster as their target
- // AOE spells should not have target
- if(m_caster->IsFriendlyTo(target) /*&& m_caster != target*/ && !duelvsplayertar)
- {
- return SPELL_FAILED_BAD_TARGETS;
- }
- }
+ if(!IsValidSingleTargetSpell(_target))
+ return SPELL_FAILED_BAD_TARGETS;
}
//cooldown
if(((Creature*)m_caster)->HasSpellCooldown(m_spellInfo->Id))
@@ -5311,7 +5289,7 @@ CurrentSpellTypes Spell::GetCurrentContainer()
bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase )
{
// Check targets for creature type mask and remove not appropriate (skip explicit self target case, maybe need other explicit targets)
- if(m_spellInfo->EffectImplicitTargetA[eff]!=TARGET_SELF && !m_magnetPair.first)
+ if(m_spellInfo->EffectImplicitTargetA[eff]!=TARGET_SELF)
{
if (!CheckTargetCreatureType(target))
return false;
@@ -5392,14 +5370,21 @@ Unit* Spell::SelectMagnetTarget()
{
if(Unit* magnet = (*itr)->GetCaster())
{
- if((*itr)->m_procCharges>0 && magnet->IsWithinLOSInMap(m_caster))
+ if((*itr)->m_procCharges>0)
{
(*itr)->SetAuraProcCharges((*itr)->m_procCharges-1);
- m_magnetPair.first = true;
- m_magnetPair.second = magnet;
-
target = magnet;
m_targets.setUnitTarget(target);
+ AddUnitTarget(target, 0);
+ uint64 targetGUID = target->GetGUID();
+ for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
+ {
+ if (targetGUID == ihit->targetGUID) // Found in list
+ {
+ (*ihit).missCondition = SPELL_MISS_KILL;
+ break;
+ }
+ }
break;
}
}
@@ -5551,3 +5536,32 @@ bool SpellEvent::IsDeletable() const
{
return m_Spell->IsDeletable();
}
+
+bool Spell::IsValidSingleTargetEffect(Unit const* target, Targets type) const
+{
+ switch(type)
+ {
+ case TARGET_UNIT_TARGET_ENEMY:
+ return !m_caster->IsFriendlyTo(target);
+ case TARGET_UNIT_TARGET_ALLY:
+ return m_caster->IsFriendlyTo(target);
+ case TARGET_UNIT_TARGET_PARTY:
+ return m_caster->IsInPartyWith(target);
+ case TARGET_UNIT_TARGET_RAID:
+ return m_caster->IsInRaidWith(target);
+ }
+ return true;
+}
+
+bool Spell::IsValidSingleTargetSpell(Unit const* target) const
+{
+ for(int i = 0; i < 3; ++i)
+ {
+ if(!IsValidSingleTargetEffect(target, Targets(m_spellInfo->EffectImplicitTargetA[i])))
+ return false;
+ // Need to check B?
+ //if(!IsValidSingleTargetEffect(m_spellInfo->EffectImplicitTargetB[i], target)
+ // return false;
+ }
+ return true;
+} \ No newline at end of file
diff --git a/src/game/Spell.h b/src/game/Spell.h
index 1bdb7154177..3d9494f8a36 100644
--- a/src/game/Spell.h
+++ b/src/game/Spell.h
@@ -364,7 +364,6 @@ class Spell
void SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap);
Unit* SelectMagnetTarget();
- std::pair <bool,Unit *> m_magnetPair;
bool CheckTarget( Unit* target, uint32 eff, bool hitPhase );
void SendCastResult(uint8 result);
@@ -538,6 +537,8 @@ class Spell
SpellTargets TargetType, uint32 entry = 0);
Unit* SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 entry = 0);
void SearchChainTarget(std::list<Unit*> &data, Unit* pUnitTarget, float max_range, uint32 unMaxTargets);
+ bool IsValidSingleTargetEffect(Unit const* target, Targets type) const;
+ bool IsValidSingleTargetSpell(Unit const* target) const;
// -------------------------------------------
//List For Triggered Spells
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp
index 794a54f6788..9f8323c735c 100644
--- a/src/game/SpellAuras.cpp
+++ b/src/game/SpellAuras.cpp
@@ -2079,6 +2079,13 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
}
return;
}
+
+ // electrical storm safe zone
+ if (GetId() == 44007)
+ {
+ m_target->ApplySpellImmune(44007, IMMUNITY_ID, 43657, apply);
+ return;
+ }
break;
}
case SPELLFAMILY_MAGE:
@@ -3040,7 +3047,8 @@ void Aura::HandleModConfuse(bool apply, bool Real)
if(!Real)
return;
- m_target->SetConfused(apply, GetCasterGUID(), GetId());
+ //m_target->SetConfused(apply, GetCasterGUID(), GetId());
+ m_target->SetControlled(apply, UNIT_STAT_CONFUSED);
}
void Aura::HandleModFear(bool apply, bool Real)
@@ -3048,7 +3056,8 @@ void Aura::HandleModFear(bool apply, bool Real)
if (!Real)
return;
- m_target->SetFeared(apply, GetCasterGUID(), GetId());
+ //m_target->SetFeared(apply, GetCasterGUID(), GetId());
+ m_target->SetControlled(apply, UNIT_STAT_FLEEING);
}
void Aura::HandleFeignDeath(bool apply, bool Real)
@@ -3146,46 +3155,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real)
if(!Real)
return;
- if (apply)
- {
- m_target->addUnitState(UNIT_STAT_STUNNED);
- m_target->SetUInt64Value(UNIT_FIELD_TARGET, 0);
-
- m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
- m_target->CastStop(m_target->GetGUID() == GetCasterGUID() ? GetId() : 0);
-
- // Creature specific
- if(m_target->GetTypeId() != TYPEID_PLAYER)
- ((Creature*)m_target)->StopMoving();
- else
- m_target->SetUnitMovementFlags(0); //Clear movement flags
-
- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
-
- data.append(m_target->GetPackGUID());
- data << uint32(0);
- m_target->SendMessageToSet(&data,true);
- }
- else
- {
- // Real remove called after current aura remove from lists, check if other similar auras active
- if(m_target->HasAuraType(SPELL_AURA_MOD_STUN))
- return;
-
- m_target->clearUnitState(UNIT_STAT_STUNNED);
- m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
-
- if(!m_target->hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
- {
- if(m_target->getVictim() && m_target->isAlive())
- m_target->SetUInt64Value(UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
-
- WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
- data.append(m_target->GetPackGUID());
- data << uint32(0);
- m_target->SendMessageToSet(&data,true);
- }
- }
+ m_target->SetControlled(apply, UNIT_STAT_STUNNED);
}
void Aura::HandleModStealth(bool apply, bool Real)
@@ -3355,55 +3325,7 @@ void Aura::HandleAuraModRoot(bool apply, bool Real)
if(!Real)
return;
- uint32 apply_stat = UNIT_STAT_ROOT;
- if (apply)
- {
- m_target->addUnitState(UNIT_STAT_ROOT);
- m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
- // probably wrong
- m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
-
- //Save last orientation
- if( m_target->getVictim() )
- m_target->SetOrientation(m_target->GetAngle(m_target->getVictim()));
-
- if(m_target->GetTypeId() == TYPEID_PLAYER)
- {
- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
- data.append(m_target->GetPackGUID());
- data << (uint32)2;
- m_target->SendMessageToSet(&data,true);
-
- //Clear unit movement flags
- m_target->SetUnitMovementFlags(0);
- }
- else
- ((Creature *)m_target)->StopMoving();
- }
- else
- {
- // Real remove called after current aura remove from lists, check if other similar auras active
- if(m_target->HasAuraType(SPELL_AURA_MOD_ROOT))
- return;
-
- m_target->clearUnitState(UNIT_STAT_ROOT);
- // probably wrong
- m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
-
- if(!m_target->hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
- {
- if(m_target->getVictim() && m_target->isAlive())
- m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
-
- if(m_target->GetTypeId() == TYPEID_PLAYER)
- {
- WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
- data.append(m_target->GetPackGUID());
- data << (uint32)2;
- m_target->SendMessageToSet(&data,true);
- }
- }
- }
+ m_target->SetControlled(apply, UNIT_STAT_ROOT);
}
void Aura::HandleAuraModSilence(bool apply, bool Real)
@@ -6231,10 +6153,11 @@ void Aura::HandlePreventFleeing(bool apply, bool Real)
Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR);
if( !fearAuras.empty() )
{
- if (apply)
+ m_target->SetControlled(!apply, UNIT_STAT_FLEEING);
+ /*if (apply)
m_target->SetFeared(false, fearAuras.front()->GetCasterGUID());
else
- m_target->SetFeared(true);
+ m_target->SetFeared(true);*/
}
}
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 4091efd2003..3ebd9a4d1ac 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -1824,27 +1824,36 @@ void SpellMgr::LoadSpellPetAuras()
// set data in core for now
void SpellMgr::LoadSpellCustomAttr()
{
+ mSpellCustomAttr.resize(GetSpellStore()->GetNumRows());
+
SpellEntry *tempSpell;
for(uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i)
{
+ mSpellCustomAttr[i] = 0;
tempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(i);
if(!tempSpell)
continue;
- mSpellCustomAttrMap[tempSpell->Id] = 0;
-
- for(uint32 i = 0; i < 3; ++i)
+ for(uint32 j = 0; j < 3; ++j)
{
- switch(tempSpell->EffectApplyAuraName[i])
+ switch(tempSpell->EffectApplyAuraName[j])
{
case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
case SPELL_AURA_PERIODIC_LEECH:
- mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_EFFECT_DAMAGE;
+ mSpellCustomAttr[i] |= SPELL_ATTR_CU_AURA_DOT;
break;
case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_OBS_MOD_HEALTH:
- mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_EFFECT_HEAL;
+ mSpellCustomAttr[i] |= SPELL_ATTR_CU_AURA_HOT;
+ break;
+ case SPELL_AURA_MOD_POSSESS:
+ case SPELL_AURA_MOD_CONFUSE:
+ case SPELL_AURA_MOD_CHARM:
+ case SPELL_AURA_MOD_FEAR:
+ case SPELL_AURA_MOD_STUN:
+ case SPELL_AURA_MOD_ROOT:
+ mSpellCustomAttr[i] |= SPELL_ATTR_CU_AURA_CC;
break;
default:
break;
@@ -1852,14 +1861,14 @@ void SpellMgr::LoadSpellCustomAttr()
}
if(tempSpell->SpellVisual == 3879)
- mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_CONE_BACK;
+ mSpellCustomAttr[i] |= SPELL_ATTR_CU_CONE_BACK;
- switch(tempSpell->Id)
+ switch(i)
{
case 26029: // dark glare
case 37433: // spout
case 43140: case 43215: // flame breath
- mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_CONE_LINE;
+ mSpellCustomAttr[i] |= SPELL_ATTR_CU_CONE_LINE;
break;
case 24340: case 26558: case 28884: // Meteor
case 36837: case 38903: case 41276: // Meteor
@@ -1869,7 +1878,7 @@ void SpellMgr::LoadSpellCustomAttr()
case 40810: case 43267: case 43268: // Saber Lash
case 42384: // Brutal Swipe
case 45150: // Meteor Slash
- mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_SHARE_DAMAGE;
+ mSpellCustomAttr[i] |= SPELL_ATTR_CU_SHARE_DAMAGE;
break;
case 44978: case 45001: case 45002: // Wild Magic
case 45004: case 45006: case 45010: // Wild Magic
@@ -1878,12 +1887,12 @@ void SpellMgr::LoadSpellCustomAttr()
case 44869: // Spectral Blast
case 45027: // Revitalize
case 45976: // Muru Portal Channel
- mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_PLAYERS_ONLY;
+ mSpellCustomAttr[i] |= SPELL_ATTR_CU_PLAYERS_ONLY;
tempSpell->MaxAffectedTargets = 1;
break;
case 41376: // Spite
case 39992: // Needle Spine
- mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_PLAYERS_ONLY;
+ mSpellCustomAttr[i] |= SPELL_ATTR_CU_PLAYERS_ONLY;
tempSpell->MaxAffectedTargets = 3;
break;
case 8122: case 8124: case 10888: case 10890: // Psychic Scream
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index f89edb49635..c13d3a25989 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -681,10 +681,11 @@ inline bool IsProfessionSkill(uint32 skill)
#define SPELL_ATTR_CU_CONE_BACK 0x00000002
#define SPELL_ATTR_CU_CONE_LINE 0x00000004
#define SPELL_ATTR_CU_SHARE_DAMAGE 0x00000008
-#define SPELL_ATTR_CU_EFFECT_HEAL 0x00000010
-#define SPELL_ATTR_CU_EFFECT_DAMAGE 0x00000020
+#define SPELL_ATTR_CU_AURA_HOT 0x00000010
+#define SPELL_ATTR_CU_AURA_DOT 0x00000020
+#define SPELL_ATTR_CU_AURA_CC 0x00000040
-typedef std::map<uint32, uint32> SpellCustomAttrMap;
+typedef std::vector<uint32> SpellCustomAttribute;
typedef std::map<int32, std::vector<int32> > SpellLinkedMap;
@@ -888,11 +889,15 @@ class SpellMgr
uint32 GetSpellCustomAttr(uint32 spell_id) const
{
- SpellCustomAttrMap::const_iterator itr = mSpellCustomAttrMap.find(spell_id);
+ if(spell_id >= mSpellCustomAttr.size())
+ return 0;
+ else
+ return mSpellCustomAttr[spell_id];
+ /*SpellCustomAttrMap::const_iterator itr = mSpellCustomAttrMap.find(spell_id);
if(itr != mSpellCustomAttrMap.end())
return itr->second;
else
- return 0;
+ return 0;*/
}
const std::vector<int32> *GetSpellLinked(int32 spell_id) const
@@ -932,7 +937,7 @@ class SpellMgr
SpellProcEventMap mSpellProcEventMap;
SkillLineAbilityMap mSkillLineAbilityMap;
SpellPetAuraMap mSpellPetAuraMap;
- SpellCustomAttrMap mSpellCustomAttrMap;
+ SpellCustomAttribute mSpellCustomAttr;
SpellLinkedMap mSpellLinkedMap;
};
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 97a9a6d04de..9e5da761bcc 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -862,15 +862,15 @@ void Unit::CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, I
SpellCastTargets targets;
uint32 targetMask = spellInfo->Targets;
- if(targetMask & (TARGET_FLAG_UNIT|TARGET_FLAG_UNK2))
+ targets.setUnitTarget(Victim);
+ /*if(targetMask & (TARGET_FLAG_UNIT|TARGET_FLAG_UNK2))
{
if(!Victim)
{
sLog.outError("CastSpell: spell id %i by caster: %s %u) does not have unit target", spellInfo->Id,(GetTypeId()==TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"),(GetTypeId()==TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
return;
}
- targets.setUnitTarget(Victim);
- }
+ }*/
if(targetMask & (TARGET_FLAG_SOURCE_LOCATION|TARGET_FLAG_DEST_LOCATION))
{
if(!Victim)
@@ -916,15 +916,15 @@ void Unit::CastCustomSpell(Unit* Victim,SpellEntry const *spellInfo, int32 const
SpellCastTargets targets;
uint32 targetMask = spellInfo->Targets;
- if(targetMask & (TARGET_FLAG_UNIT|TARGET_FLAG_UNK2))
+ targets.setUnitTarget(Victim);
+ /*if(targetMask & (TARGET_FLAG_UNIT|TARGET_FLAG_UNK2))
{
if(!Victim)
{
sLog.outError("CastCustomSpell: spell id %i by caster: %s %u) does not have unit target", spellInfo->Id,(GetTypeId()==TYPEID_PLAYER ? "player (GUID:" : "creature (Entry:"),(GetTypeId()==TYPEID_PLAYER ? GetGUIDLow() : GetEntry()));
return;
}
- targets.setUnitTarget(Victim);
- }
+ }*/
if(targetMask & (TARGET_FLAG_SOURCE_LOCATION|TARGET_FLAG_DEST_LOCATION))
{
if(!Victim)
@@ -8303,7 +8303,7 @@ Unit *Unit::GetCharmer() const
return NULL;
}
-Player* Unit::GetCharmerOrOwnerPlayerOrPlayerItself()
+Player* Unit::GetCharmerOrOwnerPlayerOrPlayerItself() const
{
uint64 guid = GetCharmerOrOwnerGUID();
if(IS_PLAYER_GUID(guid))
@@ -9271,13 +9271,6 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges)
if (!spellInfo)
return false;
- //FIX ME this hack: don't get feared if stunned
- if (spellInfo->Mechanic == MECHANIC_FEAR )
- {
- if ( hasUnitState(UNIT_STAT_STUNNED) )
- return true;
- }
-
SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_DISPEL];
for(SpellImmuneList::const_iterator itr = dispelList.begin(); itr != dispelList.end(); ++itr)
if(itr->type == spellInfo->Dispel)
@@ -11855,6 +11848,7 @@ void Unit::StopMoving()
SendMessageToSet(&data,false);
}
+/*
void Unit::SetFeared(bool apply, uint64 casterGUID, uint32 spellID)
{
if( apply )
@@ -11923,6 +11917,7 @@ void Unit::SetConfused(bool apply, uint64 casterGUID, uint32 spellID)
if(GetTypeId() == TYPEID_PLAYER)
((Player*)this)->SetClientControl(this, !apply);
}
+*/
bool Unit::IsSitState() const
{
@@ -12657,4 +12652,217 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss)
bg->HandleKillUnit((Creature*)pVictim, player);
}
}
+}
+
+void Unit::SetControlled(bool apply, UnitState state)
+{
+ if(apply)
+ {
+ if(hasUnitState(state))
+ return;
+
+ addUnitState(state);
+
+ switch(state)
+ {
+ case UNIT_STAT_STUNNED:
+ SetStunned(true);
+ break;
+ case UNIT_STAT_ROOT:
+ if(!hasUnitState(UNIT_STAT_STUNNED))
+ SetRooted(true);
+ break;
+ case UNIT_STAT_CONFUSED:
+ if(!hasUnitState(UNIT_STAT_STUNNED))
+ SetConfused(true);
+ break;
+ case UNIT_STAT_FLEEING:
+ if(!hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_CONFUSED))
+ SetFeared(true);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ switch(state)
+ {
+ case UNIT_STAT_STUNNED: if(HasAuraType(SPELL_AURA_MOD_STUN)) return;
+ else SetStunned(false); break;
+ case UNIT_STAT_ROOT: if(HasAuraType(SPELL_AURA_MOD_ROOT)) return;
+ else SetRooted(false); break;
+ case UNIT_STAT_CONFUSED:if(HasAuraType(SPELL_AURA_MOD_CONFUSE)) return;
+ else SetConfused(false); break;
+ case UNIT_STAT_FLEEING: if(HasAuraType(SPELL_AURA_MOD_FEAR)) return;
+ else SetFeared(false); break;
+ default: return;
+ }
+
+ clearUnitState(state);
+
+ if(hasUnitState(UNIT_STAT_STUNNED))
+ SetStunned(true);
+ else
+ {
+ if(hasUnitState(UNIT_STAT_ROOT))
+ SetRooted(true);
+
+ if(hasUnitState(UNIT_STAT_CONFUSED))
+ SetConfused(true);
+ else if(hasUnitState(UNIT_STAT_FLEEING))
+ SetFeared(true);
+ }
+ }
+}
+
+void Unit::SetStunned(bool apply)
+{
+ if(apply)
+ {
+ SetUInt64Value(UNIT_FIELD_TARGET, 0);
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
+ CastStop();
+
+ // Creature specific
+ if(GetTypeId() != TYPEID_PLAYER)
+ ((Creature*)this)->StopMoving();
+ else
+ SetUnitMovementFlags(0); //Clear movement flags
+
+ WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
+ data.append(GetPackGUID());
+ data << uint32(0);
+ SendMessageToSet(&data,true);
+ }
+ else
+ {
+ if(isAlive() && getVictim())
+ SetUInt64Value(UNIT_FIELD_TARGET, getVictim()->GetGUID());
+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
+
+ if(!hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect
+ {
+ WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
+ data.append(GetPackGUID());
+ data << uint32(0);
+ SendMessageToSet(&data,true);
+ }
+ }
+}
+
+void Unit::SetRooted(bool apply)
+{
+ uint32 apply_stat = UNIT_STAT_ROOT;
+ if(apply)
+ {
+ SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16)); // probably wrong
+
+ if(GetTypeId() == TYPEID_PLAYER)
+ {
+ SetUnitMovementFlags(0);
+
+ WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
+ data.append(GetPackGUID());
+ data << (uint32)2;
+ SendMessageToSet(&data,true);
+ }
+ else
+ ((Creature *)this)->StopMoving();
+ }
+ else
+ {
+ RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16)); // probably wrong
+
+ if(!hasUnitState(UNIT_STAT_STUNNED)) // prevent allow move if have also stun effect
+ {
+ if(GetTypeId() == TYPEID_PLAYER)
+ {
+ WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 10);
+ data.append(GetPackGUID());
+ data << (uint32)2;
+ SendMessageToSet(&data,true);
+ }
+ }
+ }
+}
+
+void Unit::SetFeared(bool apply)
+{
+ if(apply)
+ {
+ if(HasAuraType(SPELL_AURA_PREVENTS_FLEEING))
+ return;
+
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
+ CastStop();
+ //GetMotionMaster()->MovementExpired(false);
+ Unit *caster = NULL;
+ Unit::AuraList const& fearAuras = GetAurasByType(SPELL_AURA_MOD_FEAR);
+ if(!fearAuras.empty())
+ caster = ObjectAccessor::GetUnit(*this, fearAuras.front()->GetCasterGUID());
+ GetMotionMaster()->MoveFleeing(caster); // caster==NULL processed in MoveFleeing
+ }
+ else
+ {
+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
+ GetMotionMaster()->MovementExpired(false);
+ if( GetTypeId() != TYPEID_PLAYER && isAlive() )
+ {
+ // restore appropriate movement generator
+ if(getVictim())
+ GetMotionMaster()->MoveChase(getVictim());
+ else
+ GetMotionMaster()->Initialize();
+ }
+ }
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ ((Player*)this)->SetClientControl(this, !apply);
+}
+
+void Unit::SetConfused(bool apply)
+{
+ if(apply)
+ {
+ SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
+ CastStop();
+ GetMotionMaster()->MoveConfused();
+ }
+ else
+ {
+ RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
+ GetMotionMaster()->MovementExpired(false);
+ if( GetTypeId() != TYPEID_PLAYER && isAlive() )
+ {
+ // restore appropriate movement generator
+ if(getVictim())
+ GetMotionMaster()->MoveChase(getVictim());
+ else
+ GetMotionMaster()->Initialize();
+ }
+ }
+
+ if(GetTypeId() == TYPEID_PLAYER)
+ ((Player*)this)->SetClientControl(this, !apply);
+}
+
+bool Unit::IsInPartyWith(Unit const *unit) const
+{
+ const Player *p1 = GetCharmerOrOwnerPlayerOrPlayerItself();
+ const Player *p2 = unit->GetCharmerOrOwnerPlayerOrPlayerItself();
+ if(p1 && p2)
+ return p1->IsInSameGroupWith(p2);
+ else
+ return false;
+}
+
+bool Unit::IsInRaidWith(Unit const *unit) const
+{
+ const Player *p1 = GetCharmerOrOwnerPlayerOrPlayerItself();
+ const Player *p2 = unit->GetCharmerOrOwnerPlayerOrPlayerItself();
+ if(p1 && p2)
+ return p1->IsInSameRaidWith(p2);
+ else
+ return false;
} \ No newline at end of file
diff --git a/src/game/Unit.h b/src/game/Unit.h
index 121aea10091..8f06d09029f 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -37,6 +37,8 @@
#include "Database/DBCStructure.h"
#include <list>
+#define WORLD_TRIGGER 12999
+
enum SpellInterruptFlags
{
SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, // why need this for instant?
@@ -871,6 +873,8 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
bool IsHostileToPlayers() const;
bool IsFriendlyTo(Unit const* unit) const;
bool IsNeutralToAll() const;
+ bool IsInPartyWith(Unit const* unit) const;
+ bool IsInRaidWith(Unit const* unit) const;
bool IsContestedGuard() const
{
if(FactionTemplateEntry const* entry = getFactionTemplateEntry())
@@ -1055,7 +1059,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
return this;
}
- Player* GetCharmerOrOwnerPlayerOrPlayerItself();
+ Player* GetCharmerOrOwnerPlayerOrPlayerItself() const;
void SetPet(Pet* pet);
void SetCharm(Unit* pet);
@@ -1348,8 +1352,11 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
uint32 GetUnitMovementFlags() const { return m_unit_movement_flags; }
void SetUnitMovementFlags(uint32 f) { m_unit_movement_flags = f; }
- void SetFeared(bool apply, uint64 casterGUID = 0, uint32 spellID = 0);
- void SetConfused(bool apply, uint64 casterGUID = 0, uint32 spellID = 0);
+ void SetControlled(bool apply, UnitState state);
+ void SetFeared(bool apply/*, uint64 casterGUID = 0, uint32 spellID = 0*/);
+ void SetConfused(bool apply/*, uint64 casterGUID = 0, uint32 spellID = 0*/);
+ void SetStunned(bool apply);
+ void SetRooted(bool apply);
void AddComboPointHolder(uint32 lowguid) { m_ComboPointHolders.insert(lowguid); }
void RemoveComboPointHolder(uint32 lowguid) { m_ComboPointHolders.erase(lowguid); }
diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp
index 831f616060b..c18c09bcc17 100644
--- a/src/game/WaypointManager.cpp
+++ b/src/game/WaypointManager.cpp
@@ -10,333 +10,143 @@
*
* 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
+ * 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
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "Database/DatabaseEnv.h"
#include "GridDefines.h"
-#include "Policies/SingletonImp.h"
#include "WaypointManager.h"
#include "ProgressBar.h"
#include "MapManager.h"
-#include "ObjectMgr.h"
-INSTANTIATE_SINGLETON_1(WaypointManager);
+UNORDERED_MAP<uint32, WaypointPath*> waypoint_map;
+WaypointStore WaypointMgr;
-bool WaypointBehavior::isEmpty()
+void WaypointStore::Free()
{
- if (emote || spell || model1 || model2)
- return false;
-
- for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
- if(textid[i])
- return false;
-
- return true;
-}
-
-WaypointBehavior::WaypointBehavior(const WaypointBehavior &b)
-{
- emote = b.emote;
- spell = b.spell;
- model1 = b.model1;
- model2 = b.model2;
- for(int i=0; i < MAX_WAYPOINT_TEXT; ++i)
- textid[i] = b.textid[i];
+ waypoint_map.clear();
}
-void WaypointManager::Load()
+void WaypointStore::Load()
{
- Cleanup();
-
- uint32 total_paths = 0;
- uint32 total_nodes = 0;
- uint32 total_behaviors = 0;
-
- QueryResult *result = WorldDatabase.Query("SELECT id, COUNT(point) FROM creature_movement GROUP BY id");
- if(result)
+ QueryResult *result = WorldDatabase.PQuery("SELECT MAX(`id`) FROM `waypoint_data");
+ if(!result)
{
- total_paths = result->GetRowCount();
- barGoLink bar( total_paths );
- do
- {
- Field *fields = result->Fetch();
- uint32 id = fields[0].GetUInt32();
- uint32 count = fields[1].GetUInt32();
- m_pathMap[id].resize(count);
-
- total_nodes += count;
- bar.step();
- } while( result->NextRow() );
- delete result;
+ sLog.outError(" an error occured while loading the table `waypoint_data` ( maybe it doesn't exist ?)\n");
+ exit(1); // Stop server at loading non exited table or not accessable table
}
- result = WorldDatabase.Query("SELECT position_x, position_y, position_z, orientation, model1, model2, waittime, emote, spell, textid1, textid2, textid3, textid4, textid5, id, point FROM creature_movement");
- if(result)
- {
- barGoLink bar( result->GetRowCount() );
- do
- {
- Field *fields = result->Fetch();
- uint32 point = fields[15].GetUInt32();
- uint32 id = fields[14].GetUInt32();
-
- WaypointPath &path = m_pathMap[id];
- // the cleanup queries make sure the following is true
- assert(point >= 1 && point <= path.size());
- WaypointNode &node = path[point-1];
-
- node.x = fields[0].GetFloat();
- node.y = fields[1].GetFloat();
- node.z = fields[2].GetFloat();
- node.orientation = fields[3].GetFloat();
- node.delay = fields[6].GetUInt16();
-
- // prevent using invalid coordinates
- if(!Trinity::IsValidMapCoord(node.x, node.y, node.z, node.orientation))
- {
- QueryResult *result1 = WorldDatabase.PQuery("SELECT id, map FROM creature WHERE guid = '%u'", id);
- if(result1)
- sLog.outErrorDb("ERROR: Creature (guidlow %d, entry %d) have invalid coordinates in his waypoint %d (X: %f, Y: %f).",
- id, result1->Fetch()[0].GetUInt32(), point, node.x, node.y);
- else
- sLog.outErrorDb("ERROR: Waypoint path %d, have invalid coordinates in his waypoint %d (X: %f, Y: %f).",
- id, point, node.x, node.y);
-
- Trinity::NormalizeMapCoord(node.x);
- Trinity::NormalizeMapCoord(node.y);
- if(result1)
- {
- node.z = MapManager::Instance ().GetBaseMap(result1->Fetch()[1].GetUInt32())->GetHeight(node.x, node.y, node.z);
- delete result1;
- }
- WorldDatabase.PExecute("UPDATE creature_movement SET position_x = '%f', position_y = '%f', position_z = '%f' WHERE id = '%u' AND point = '%u'", node.x, node.y, node.z, id, point);
- }
-
- WaypointBehavior be;
- be.model1 = fields[4].GetUInt32();
- be.model2 = fields[5].GetUInt32();
- be.emote = fields[7].GetUInt32();
- be.spell = fields[8].GetUInt32();
-
- for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
- {
- be.textid[i] = fields[9+i].GetUInt32();
- if(be.textid[i])
- {
- if (be.textid[i] < MIN_DB_SCRIPT_STRING_ID || be.textid[i] >= MAX_DB_SCRIPT_STRING_ID)
- {
- sLog.outErrorDb( "Table `db_script_string` not have string id %u", be.textid[i]);
- continue;
- }
- }
- }
-
- // save memory by not storing empty behaviors
- if(!be.isEmpty())
- {
- node.behavior = new WaypointBehavior(be);
- ++total_behaviors;
- }
- else
- node.behavior = NULL;
- bar.step();
- } while( result->NextRow() );
- delete result;
- }
- sLog.outString( ">> Loaded %u paths, %u nodes and %u behaviors", total_paths, total_nodes, total_behaviors);
-}
-
-void WaypointManager::Cleanup()
-{
- // check if points need to be renumbered and do it
- if(QueryResult *result = WorldDatabase.Query("SELECT 1 from creature_movement As T WHERE point <> (SELECT COUNT(*) FROM creature_movement WHERE id = T.id AND point <= T.point) LIMIT 1"))
- {
- delete result;
- WorldDatabase.DirectExecute("CREATE TEMPORARY TABLE temp LIKE creature_movement");
- WorldDatabase.DirectExecute("INSERT INTO temp SELECT * FROM creature_movement");
- WorldDatabase.DirectExecute("ALTER TABLE creature_movement DROP PRIMARY KEY");
- WorldDatabase.DirectExecute("UPDATE creature_movement AS T SET point = (SELECT COUNT(*) FROM temp WHERE id = T.id AND point <= T.point)");
- WorldDatabase.DirectExecute("ALTER TABLE creature_movement ADD PRIMARY KEY (id, point)");
- WorldDatabase.DirectExecute("DROP TABLE temp");
- assert(!(result = WorldDatabase.Query("SELECT 1 from creature_movement As T WHERE point <> (SELECT COUNT(*) FROM creature_movement WHERE id = T.id AND point <= T.point) LIMIT 1")));
- }
-}
-
-void WaypointManager::Unload()
-{
- for(WaypointPathMap::iterator itr = m_pathMap.begin(); itr != m_pathMap.end(); ++itr)
- _clearPath(itr->second);
- m_pathMap.clear();
-}
-
-void WaypointManager::_clearPath(WaypointPath &path)
-{
- for(WaypointPath::iterator itr = path.begin(); itr != path.end(); ++itr)
- if(itr->behavior)
- delete itr->behavior;
- path.clear();
-}
-
-/// - Insert after the last point
-void WaypointManager::AddLastNode(uint32 id, float x, float y, float z, float o, uint32 delay, uint32 wpGuid)
-{
- _addNode(id, GetLastPoint(id, 0) + 1, x, y, z, o, delay, wpGuid);
-}
-
-/// - Insert after a certain point
-void WaypointManager::AddAfterNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid)
-{
- for(uint32 i = GetLastPoint(id, 0); i > point; i--)
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point+1 WHERE id='%u' AND point='%u'", id, i);
-
- _addNode(id, point + 1, x, y, z, o, delay, wpGuid);
-}
+ records = (*result)[0].GetUInt32();
+ delete result;
-/// - Insert without checking for collision
-void WaypointManager::_addNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid)
-{
- if(point == 0) return; // counted from 1 in the DB
- WorldDatabase.PExecuteLog("INSERT INTO creature_movement (id,point,position_x,position_y,position_z,orientation,wpguid,waittime) VALUES ('%u','%u','%f', '%f', '%f', '%f', '%d', '%d')", id, point, x, y, z, o, wpGuid, delay);
- WaypointPathMap::iterator itr = m_pathMap.find(id);
- if(itr == m_pathMap.end())
- itr = m_pathMap.insert(WaypointPathMap::value_type(id, WaypointPath())).first;
- itr->second.insert(itr->second.begin() + (point - 1), WaypointNode(x, y, z, o, delay, NULL));
-}
-uint32 WaypointManager::GetLastPoint(uint32 id, uint32 default_notfound)
-{
- uint32 point = default_notfound;
- /*QueryResult *result = WorldDatabase.PQuery( "SELECT MAX(point) FROM creature_movement WHERE id = '%u'", id);
- if( result )
+ result = WorldDatabase.PQuery("SELECT `id`,`point`,`position_x`,`position_y`,`position_z`,`move_flag`,`delay`,`action`,`action_chance` FROM `waypoint_data` ORDER BY `id`, `point`");
+ if(!result)
{
- point = (*result)[0].GetUInt32()+1;
- delete result;
- }*/
- WaypointPathMap::iterator itr = m_pathMap.find(id);
- if(itr != m_pathMap.end() && itr->second.size() != 0)
- point = itr->second.size();
- return point;
-}
-
-void WaypointManager::DeleteNode(uint32 id, uint32 point)
-{
- if(point == 0) return; // counted from 1 in the DB
- WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id='%u' AND point='%u'", id, point);
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET point=point-1 WHERE id='%u' AND point>'%u'", id, point);
- WaypointPathMap::iterator itr = m_pathMap.find(id);
- if(itr != m_pathMap.end() && point <= itr->second.size())
- itr->second.erase(itr->second.begin() + (point-1));
-}
-
-void WaypointManager::DeletePath(uint32 id)
-{
- WorldDatabase.PExecuteLog("DELETE FROM creature_movement WHERE id='%u'", id);
- WaypointPathMap::iterator itr = m_pathMap.find(id);
- if(itr != m_pathMap.end())
- _clearPath(itr->second);
- // the path is not removed from the map, just cleared
- // WMGs have pointers to the path, so deleting them would crash
- // this wastes some memory, but these functions are
- // only meant to be called by GM commands
-}
-
-void WaypointManager::SetNodePosition(uint32 id, uint32 point, float x, float y, float z)
-{
- if(point == 0) return; // counted from 1 in the DB
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET position_x = '%f',position_y = '%f',position_z = '%f' where id = '%u' AND point='%u'", x, y, z, id, point);
- WaypointPathMap::iterator itr = m_pathMap.find(id);
- if(itr != m_pathMap.end() && point <= itr->second.size())
- {
- itr->second[point-1].x = x;
- itr->second[point-1].y = y;
- itr->second[point-1].z = z;
+ sLog.outErrorDb("The table `creature_addon` is empty or corrupted");
+ return;
}
-}
-void WaypointManager::SetNodeText(uint32 id, uint32 point, const char *text_field, const char *text)
-{
- if(point == 0) return; // counted from 1 in the DB
- if(!text_field) return;
- std::string field = text_field;
- WorldDatabase.escape_string(field);
+ WaypointPath* path_data;
+ uint32 total_records = result->GetRowCount();
- if(!text)
+ barGoLink bar( total_records);
+ Field *fields;
+ uint32 last_id = 0;
+
+ do
{
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s=NULL WHERE id='%u' AND point='%u'", field.c_str(), id, point);
- }
- else
- {
- std::string text2 = text;
- WorldDatabase.escape_string(text2);
- WorldDatabase.PExecuteLog("UPDATE creature_movement SET %s='%s' WHERE id='%u' AND point='%u'", field.c_str(), text2.c_str(), id, point);
- }
-
- WaypointPathMap::iterator itr = m_pathMap.find(id);
- if(itr != m_pathMap.end() && point <= itr->second.size())
- {
- WaypointNode &node = itr->second[point-1];
- if(!node.behavior) node.behavior = new WaypointBehavior();
-
-// if(field == "text1") node.behavior->text[0] = text ? text : "";
-// if(field == "text2") node.behavior->text[1] = text ? text : "";
-// if(field == "text3") node.behavior->text[2] = text ? text : "";
-// if(field == "text4") node.behavior->text[3] = text ? text : "";
-// if(field == "text5") node.behavior->text[4] = text ? text : "";
- if(field == "emote") node.behavior->emote = text ? atoi(text) : 0;
- if(field == "spell") node.behavior->spell = text ? atoi(text) : 0;
- if(field == "model1") node.behavior->model1 = text ? atoi(text) : 0;
- if(field == "model2") node.behavior->model2 = text ? atoi(text) : 0;
- }
+ fields = result->Fetch();
+ uint32 id = fields[0].GetUInt32();
+ bar.step();
+ WaypointData *wp = new WaypointData;
+
+ if(last_id != id)
+ path_data = new WaypointPath;
+
+ float x,y,z;
+ x = fields[2].GetFloat();
+ y = fields[3].GetFloat();
+ z = fields[4].GetFloat();
+
+ Trinity::NormalizeMapCoord(x);
+ Trinity::NormalizeMapCoord(y);
+
+ wp->id = fields[1].GetUInt32();
+ wp->x = x;
+ wp->y = y;
+ wp->z = z;
+ wp->run = fields[5].GetBool();
+ wp->delay = fields[6].GetUInt32();
+ wp->event_id = fields[7].GetUInt32();
+ wp->event_chance = fields[8].GetUInt8();
+
+ path_data->push_back(wp);
+
+ if(id != last_id)
+ waypoint_map[id] = path_data;
+
+ last_id = id;
+
+ } while(result->NextRow()) ;
+
+
+ delete result;
}
-void WaypointManager::CheckTextsExistance(std::set<int32>& ids)
+void WaypointStore::UpdatePath(uint32 id)
{
- WaypointPathMap::iterator pmItr = m_pathMap.begin();
- for ( ; pmItr != m_pathMap.end(); ++pmItr)
+
+ if(waypoint_map.find(id)!= waypoint_map.end())
+ waypoint_map[id]->clear();
+
+ QueryResult *result;
+
+ result = WorldDatabase.PQuery("SELECT `id`,`point`,`position_x`,`position_y`,`position_z`,`move_flag`,`delay`,`action`,`action_chance` FROM `waypoint_data` WHERE id = %u ORDER BY `point`", id);
+
+ if(!result)
+ return;
+
+ WaypointPath* path_data;
+
+ path_data = new WaypointPath;
+
+ Field *fields;
+
+ do
{
- for (int i = 0; i < pmItr->second.size(); ++i)
- {
- if (!pmItr->second[i].behavior)
- continue;
-
- // Now we check text existence and put all zero texts ids to the end of array
-
- // Counting leading zeros for futher textid shift
- int zeroCount = 0;
- for (int j = 0; j < MAX_WAYPOINT_TEXT; ++j)
- {
- if (!pmItr->second[i].behavior->textid[j])
- {
- ++zeroCount;
- continue;
- }
- else
- {
- if (!objmgr.GetTrinityStringLocale(pmItr->second[i].behavior->textid[j]))
- {
- sLog.outErrorDb("ERROR: Some waypoint has textid%u with not existing %u text.", j, pmItr->second[i].behavior->textid[j]);
- pmItr->second[i].behavior->textid[j] = 0;
- ++zeroCount;
- continue;
- }
- else
- ids.erase(pmItr->second[i].behavior->textid[j]);
-
- // Shifting check
- if (zeroCount)
- {
- // Correct textid but some zeros leading, so move it forward.
- pmItr->second[i].behavior->textid[j-zeroCount] = pmItr->second[i].behavior->textid[j];
- pmItr->second[i].behavior->textid[j] = 0;
- }
- }
- }
- }
- }
+ fields = result->Fetch();
+ uint32 id = fields[0].GetUInt32();
+
+ WaypointData *wp = new WaypointData;
+
+ float x,y,z;
+ x = fields[2].GetFloat();
+ y = fields[3].GetFloat();
+ z = fields[4].GetFloat();
+
+ Trinity::NormalizeMapCoord(x);
+ Trinity::NormalizeMapCoord(y);
+
+ wp->id = fields[1].GetUInt32();
+ wp->x = x;
+ wp->y = y;
+ wp->z = z;
+ wp->run = fields[5].GetBool();
+ wp->delay = fields[6].GetUInt32();
+ wp->event_id = fields[7].GetUInt32();
+ wp->event_chance = fields[8].GetUInt8();
+
+ path_data->push_back(wp);
+
+ }while (result->NextRow());
+
+ waypoint_map[id] = path_data;
+
+ delete result;
}
diff --git a/src/game/WaypointManager.h b/src/game/WaypointManager.h
index 38cf5551d64..ec6d46c3b31 100644
--- a/src/game/WaypointManager.h
+++ b/src/game/WaypointManager.h
@@ -22,72 +22,40 @@
#define TRINITY_WAYPOINTMANAGER_H
#include <vector>
-#include <string>
-#include "Utilities/UnorderedMap.h"
-#define MAX_WAYPOINT_TEXT 5
-struct WaypointBehavior
+struct WaypointData
{
- uint32 emote;
- uint32 spell;
- int32 textid[MAX_WAYPOINT_TEXT];
- uint32 model1;
- uint32 model2;
-
- bool isEmpty();
- WaypointBehavior() {}
- WaypointBehavior(const WaypointBehavior &b);
-};
-
-struct WaypointNode
-{
- float x;
- float y;
- float z;
- float orientation;
+ uint32 id;
+ float x,y,z;
+ bool run;
uint32 delay;
- WaypointBehavior * behavior;
- WaypointNode() {}
- WaypointNode(float _x, float _y, float _z, float _o, uint32 _delay, WaypointBehavior * _behavior)
- : x(_x), y(_y), z(_z), orientation(_o), delay(_delay), behavior(_behavior) {}
+ uint32 event_id;
+ uint8 event_chance;
};
-typedef std::vector<WaypointNode> WaypointPath;
+typedef std::vector<WaypointData*> WaypointPath;
+extern UNORDERED_MAP<uint32, WaypointPath*> waypoint_map;
-class WaypointManager
+class WaypointStore
{
- public:
- WaypointManager() {}
- ~WaypointManager() { Unload(); }
-
- void Load();
- void Unload();
-
- void Cleanup();
-
- WaypointPath *GetPath(uint32 id)
+ private :
+ uint32 records;
+
+ public:
+ void UpdatePath(uint32 id);
+ void Load();
+ void Free();
+
+ WaypointPath* GetPath(uint32 id)
{
- WaypointPathMap::iterator itr = m_pathMap.find(id);
- return itr != m_pathMap.end() ? &itr->second : NULL;
- }
-
- void AddLastNode(uint32 id, float x, float y, float z, float o, uint32 delay, uint32 wpGuid);
- void AddAfterNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid);
- uint32 GetLastPoint(uint32 id, uint32 default_notfound);
- void DeleteNode(uint32 id, uint32 point);
- void DeletePath(uint32 id);
- void SetNodePosition(uint32 id, uint32 point, float x, float y, float z);
- void SetNodeText(uint32 id, uint32 point, const char *text_field, const char *text);
- void CheckTextsExistance(std::set<int32>& ids);
-
- private:
- void _addNode(uint32 id, uint32 point, float x, float y, float z, float o, uint32 delay, uint32 wpGuid);
- void _clearPath(WaypointPath &path);
-
- typedef UNORDERED_MAP<uint32, WaypointPath> WaypointPathMap;
- WaypointPathMap m_pathMap;
+ if(waypoint_map.find(id) != waypoint_map.end())
+ return waypoint_map[id];
+ else return 0;
+ }
+
+ inline uint32 GetRecordsCount() { return records; }
};
-#define WaypointMgr Trinity::Singleton<WaypointManager>::Instance()
+extern WaypointStore WaypointMgr;
#endif
diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp
index 3dc3ddebf42..68c63827883 100644
--- a/src/game/WaypointMovementGenerator.cpp
+++ b/src/game/WaypointMovementGenerator.cpp
@@ -1,8 +1,6 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
*
- * Copyright (C) 2008 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
@@ -10,209 +8,204 @@
*
* 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
+ * 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
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-/*
-creature_movement Table
-
-alter table creature_movement add `textid1` int(11) NOT NULL default '0';
-alter table creature_movement add `textid2` int(11) NOT NULL default '0';
-alter table creature_movement add `textid3` int(11) NOT NULL default '0';
-alter table creature_movement add `textid4` int(11) NOT NULL default '0';
-alter table creature_movement add `textid5` int(11) NOT NULL default '0';
-alter table creature_movement add `emote` int(10) unsigned default '0';
-alter table creature_movement add `spell` int(5) unsigned default '0';
-alter table creature_movement add `wpguid` int(11) default '0';
-
-*/
-
+//Basic header
#include <ctime>
#include "WaypointMovementGenerator.h"
+#include "DestinationHolderImp.h"
+//Accessors
+#include "Database/DatabaseEnv.h"
#include "ObjectMgr.h"
+#include "World.h"
+//Creature-specific headers
#include "Creature.h"
-#include "DestinationHolderImp.h"
#include "CreatureAI.h"
-#include "WaypointManager.h"
+//Player-Specific
+#include "Player.h"
+//Visual
+#include "ProgressBar.h"
+#include "MapManager.h"
-#include <cassert>
+template<class T>
+void
+WaypointMovementGenerator<T>::Initialize(T &u){}
-//-----------------------------------------------//
+template<>
void
-WaypointMovementGenerator<Creature>::LoadPath(Creature &c)
+WaypointMovementGenerator<Creature>::Initialize(Creature &u)
{
- sLog.outDetail("LoadPath: loading waypoint path for creature %d,%d", c.GetGUIDLow(), c.GetDBTableGUIDLow());
-
- i_path = WaypointMgr.GetPath(c.GetDBTableGUIDLow());
- if(!i_path)
- {
- sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %d) doesn't have waypoint path",
- c.GetName(), c.GetEntry(), c.GetDBTableGUIDLow());
- return;
- }
+ i_currentNode = -1;
+ u.StopMoving();
+ if(!path_id)
+ path_id = u.GetWaypointPath();
+ waypoints = WaypointMgr.GetPath(path_id);
+}
- uint32 node_count = i_path->size();
- i_hasDone.resize(node_count);
- for(uint32 i = 0; i < node_count-1; i++)
- i_hasDone[i] = false;
+template<>
+void
+WaypointMovementGenerator<Creature>::Finalize(Creature &u){}
- // to prevent a misbehaviour inside "update"
- // update is always called with the next wp - but the wpSys needs the current
- // so when the routine is called the first time, wpSys gets the last waypoint
- // and this prevents the system from performing text/emote, etc
- i_hasDone[node_count - 1] = true;
-}
+template<>
+void
+WaypointMovementGenerator<Player>::Finalize(Player &u){}
+template<class T>
void
-WaypointMovementGenerator<Creature>::ClearWaypoints()
+WaypointMovementGenerator<T>::MovementInform(T &unit){}
+
+template<>
+void WaypointMovementGenerator<Creature>::MovementInform(Creature &unit)
{
- i_path = NULL;
+ unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
}
-void
-WaypointMovementGenerator<Creature>::Initialize()
+template<>
+bool WaypointMovementGenerator<Creature>::GetDestination(float &x, float &y, float &z) const
{
+ if(i_destinationHolder.HasArrived())
+ return false;
+
+ i_destinationHolder.GetDestination(x, y, z);
+ return true;
}
-bool
-WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
+template<>
+bool WaypointMovementGenerator<Player>::GetDestination(float &x, float &y, float &z) const
{
- if(!&creature)
- return true;
-
- // Waypoint movement can be switched on/off
- // This is quite handy for escort quests and other stuff
- if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
- return true;
+ return false;
+}
- // prevent a crash at empty waypoint path.
- if(!i_path || i_path->empty())
- return true;
+template<>
+void WaypointMovementGenerator<Creature>::Reset(Creature &unit){}
- // i_path was modified by chat commands for example
- if(i_path->size() != i_hasDone.size())
- i_hasDone.resize(i_path->size());
- if(i_currentNode >= i_path->size())
- i_currentNode = 0;
+template<>
+void WaypointMovementGenerator<Player>::Reset(Player &unit){}
- CreatureTraveller traveller(creature);
+template<>
+void WaypointMovementGenerator<Creature>::InitTraveller(Creature &unit, const WaypointData &node)
+{
+ node.run ? unit.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE): unit.AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
+
+ unit.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
+ unit.SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
+
+ if(unit.canFly())
+ unit.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
+
+ unit.addUnitState(UNIT_STAT_ROAMING);
+}
- i_nextMoveTime.Update(diff);
- i_destinationHolder.UpdateTraveller(traveller, diff, false, true);
+template<>
+void WaypointMovementGenerator<Player>::InitTraveller(Player &unit, const WaypointData &node){}
- // creature has been stoped in middle of the waypoint segment
- if (!i_destinationHolder.HasArrived() && creature.IsStopped())
- {
- if( i_nextMoveTime.Passed()) // Timer has elapsed, meaning this part controlled it
- {
- SetStopedByPlayer(false);
- // Now we re-set destination to same node and start travel
- creature.addUnitState(UNIT_STAT_ROAMING);
- if (creature.canFly())
- creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
- const WaypointNode &node = i_path->at(i_currentNode);
- i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
- i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
- }
- else // if( !i_nextMoveTime.Passed())
- { // unexpected end of timer && creature stopped && not at end of segment
- if (!IsStopedByPlayer())
- { // Put 30 seconds delay
- i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
- i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
- SetStopedByPlayer(true); // Mark we did it
- }
- }
- return true; // Abort here this update
- }
+template<class T>
+bool
+WaypointMovementGenerator<T>::Update(T &unit, const uint32 &diff)
+{
+ return false;
+}
- if( creature.IsStopped())
- {
- uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1;
+template<>
+bool
+WaypointMovementGenerator<Creature>::Update(Creature &unit, const uint32 &diff)
+{
+ if(!&unit)
+ return true;
- if (!i_hasDone[idx])
- {
- if (i_path->at(idx).orientation !=100)
- creature.SetOrientation(i_path->at(idx).orientation);
+ if(!path_id)
+ return false;
+
+ // Waypoint movement can be switched on/off
+ // This is quite handy for escort quests and other stuff
+ if(unit.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED))
+ return true;
- if(WaypointBehavior *behavior = i_path->at(idx).behavior)
- {
- if(behavior->emote != 0)
- creature.SetUInt32Value(UNIT_NPC_EMOTESTATE,behavior->emote);
- if(behavior->spell != 0)
- creature.CastSpell(&creature,behavior->spell, false);
- if(behavior->model1 != 0)
- creature.SetDisplayId(behavior->model1);
- if(behavior->textid[0])
- {
- // Not only one text is set
- if( behavior->textid[1] )
- {
- // Select one from max 5 texts (0 and 1 already checked)
- int i = 2;
- for( ; i < MAX_WAYPOINT_TEXT; ++i )
- if( !behavior->textid[i] )
- break;
+ // Clear the generator if the path doesn't exist
+ if(!waypoints || !waypoints->size())
+ return false;
- creature.Say(behavior->textid[rand() % i], 0, 0);
- }
- else
- creature.Say(behavior->textid[0], 0, 0);
- }
- } // wpBehaviour found
- i_hasDone[idx] = true;
- MovementInform(creature);
- } // HasDone == false
- } // i_creature.IsStopped()
+ Traveller<Creature> traveller(unit);
- if( i_nextMoveTime.Passed() ) // This is at the end of waypoint segment or has been stopped by player
- {
- if( creature.IsStopped() ) // If stopped then begin a new move segment
- {
- creature.addUnitState(UNIT_STAT_ROAMING);
- if (creature.canFly())
- creature.AddUnitMovementFlag(MOVEMENTFLAG_FLYING2);
- const WaypointNode &node = i_path->at(i_currentNode);
- i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
- i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
- uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1;
-
- if (i_path->at(idx).orientation !=100)
- creature.SetOrientation(i_path->at(idx).orientation);
-
- if(WaypointBehavior *behavior = i_path->at(idx).behavior )
- {
- i_hasDone[idx] = false;
- if(behavior->model2 != 0)
- creature.SetDisplayId(behavior->model2);
+ i_nextMoveTime.Update(diff);
+ i_destinationHolder.UpdateTraveller(traveller, diff, false, true);
- creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
- }
- }
- else // If not stopped then stop it and set the reset of TimeTracker to waittime
- {
- creature.StopMoving();
- SetStopedByPlayer(false);
- i_nextMoveTime.Reset(i_path->at(i_currentNode).delay);
- ++i_currentNode;
- if( i_currentNode >= i_path->size() )
- i_currentNode = 0;
- }
+ if(i_nextMoveTime.Passed())
+ {
+ if(unit.IsStopped())
+ {
+ if(StopedByPlayer)
+ {
+ InitTraveller(unit,node);
+ i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
+ i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
+ StopedByPlayer = false;
+ return true;
+ }
+
+ if(i_currentNode == waypoints->size() - 1) //If that's our last waypoint
+ {
+ if(repeating) //If the movement is repeating
+ i_currentNode = 0; //Start moving all over again
+ else
+ {
+ unit.GetMotionMaster()->Initialize();
+ return false; //Clear the waypoint movement
+ }
+ }
+ else
+ i_currentNode++;
+
+ node = *(waypoints->at(i_currentNode));
+ InitTraveller(unit,node);
+ i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
+ i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
+ }
+ else
+ {
+ //Determine waittime
+ if(node.delay)
+ i_nextMoveTime.Reset(node.delay);
+ else
+ i_nextMoveTime.Reset(100); //Prevents some lag
+
+ if(node.event_id && rand()%100 < node.event_chance && !ExecuteScript)
+ {
+ sWorld.ScriptsStart(sWaypointScripts, node.event_id, &unit, NULL);
+ ExecuteScript = true;
+ }
+
+ MovementInform(unit);
+ unit.UpdateWaypointID(i_currentNode);
+ traveller.Relocation(node.x, node.y, node.z);
+ unit.clearUnitState(UNIT_STAT_MOVING);
+ }
}
- return true;
+ else
+ {
+ if(unit.IsStopped() && !i_destinationHolder.HasArrived())
+ {
+ if(!StopedByPlayer)
+ {
+ i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
+ i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
+ StopedByPlayer = true;
+ }
+ }
+ }
+ return true;
}
-void WaypointMovementGenerator<Creature>::MovementInform(Creature &unit)
-{
- if(unit.AI())
- unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
-}
+template void WaypointMovementGenerator<Player>::Initialize(Player &);
+template bool WaypointMovementGenerator<Player>::Update(Player &, const uint32 &);
+template void WaypointMovementGenerator<Player>::MovementInform(Player &);
//----------------------------------------------------//
void
diff --git a/src/game/WaypointMovementGenerator.h b/src/game/WaypointMovementGenerator.h
index 86e1b0beea3..5995188ac8d 100644
--- a/src/game/WaypointMovementGenerator.h
+++ b/src/game/WaypointMovementGenerator.h
@@ -50,64 +50,41 @@ class TRINITY_DLL_SPEC PathMovementBase
inline bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); }
- // template pattern, not defined .. override required
void LoadPath(T &);
void ReloadPath(T &);
uint32 GetCurrentNode() const { return i_currentNode; }
-
+
protected:
uint32 i_currentNode;
DestinationHolder< Traveller<T> > i_destinationHolder;
P i_path;
};
-/** WaypointMovementGenerator loads a series of way points
- * from the DB and apply it to the creature's movement generator.
- * Hence, the creature will move according to its predefined way points.
- */
-
template<class T>
-class TRINITY_DLL_SPEC WaypointMovementGenerator;
-template<>
-class TRINITY_DLL_SPEC WaypointMovementGenerator<Creature>
-: public MovementGeneratorMedium< Creature, WaypointMovementGenerator<Creature> >,
-public PathMovementBase<Creature, WaypointPath*>
+class TRINITY_DLL_SPEC WaypointMovementGenerator
+ : public MovementGeneratorMedium< T, WaypointMovementGenerator<T> >, public PathMovementBase<T>
{
- TimeTrackerSmall i_nextMoveTime;
- std::vector<bool> i_hasDone;
- public:
- WaypointMovementGenerator(Creature &) : i_nextMoveTime(0) {}
- ~WaypointMovementGenerator() { ClearWaypoints(); }
- void Initialize(Creature &u)
- {
- i_nextMoveTime.Reset(0); // TODO: check the lower bound (0 is probably too small)
- u.StopMoving();
- LoadPath(u);
- }
- void Finalize(Creature &) {}
- void Reset(Creature &u) { ReloadPath(u); }
- bool Update(Creature &u, const uint32 &diff);
-
- void MovementInform(Creature &);
-
- MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; }
-
- // now path movement implmementation
- void LoadPath(Creature &c);
- void ReloadPath(Creature &c) { ClearWaypoints(); LoadPath(c); }
-
- // Player stoping creature
- bool IsStopedByPlayer() { return b_StopedByPlayer; }
- void SetStopedByPlayer(bool val) { b_StopedByPlayer = val; }
-
- // statics
- static void Initialize(void);
-
- bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; }
- private:
- void ClearWaypoints();
- bool b_StopedByPlayer;
+ public:
+ WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true) :
+ i_nextMoveTime(0), path_id(_path_id), repeating(_repeating), StopedByPlayer(false){}
+
+ void Initialize(T &);
+ void Finalize(T &);
+ void MovementInform(T &);
+ void InitTraveller(T &, const WaypointData &);
+ void GeneratePathId(T &);
+ void Reset(T &unit);
+ bool Update(T &, const uint32 &);
+ bool GetDestination(float &x, float &y, float &z) const;
+ MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; }
+
+ private:
+ WaypointData node;
+ uint32 i_currentNode, path_id;
+ TimeTrackerSmall i_nextMoveTime;
+ WaypointPath *waypoints;
+ bool repeating, custom_path, ExecuteScript, StopedByPlayer;
};
/** FlightPathMovementGenerator generates movement of the player for the paths
@@ -135,6 +112,7 @@ public PathMovementBase<Player>
inline bool HasArrived() const { return (i_currentNode >= i_path.Size()); }
void SetCurrentNodeAfterTeleport();
void SkipCurrentNode() { ++i_currentNode; }
- bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; }
+ bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; }
+
};
#endif
diff --git a/src/game/World.cpp b/src/game/World.cpp
index 04b3a1004c9..66054d95afb 100644
--- a/src/game/World.cpp
+++ b/src/game/World.cpp
@@ -1271,6 +1271,7 @@ void World::SetInitialWorldSettings()
objmgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadGameObjectScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data)
+ objmgr.LoadWaypointScripts();
sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls
objmgr.LoadDbScriptStrings();
@@ -1313,7 +1314,6 @@ void World::SetInitialWorldSettings()
///- Initilize static helper structures
AIRegistry::Initialize();
- WaypointMovementGenerator<Creature>::Initialize();
Player::InitVisibleBits();
///- Initialize MapManager
@@ -2203,8 +2203,32 @@ void World::ScriptsProcess()
break;
}
+
+ case SCRIPT_COMMAND_LOAD_PATH:
+ {
+ if(!source)
+ {
+ sLog.outError("SCRIPT_COMMAND_START_MOVE is tried to apply to NON-existing unit.");
+ break;
+ }
- default:
+ if(!source->isType(TYPEMASK_UNIT))
+ {
+ sLog.outError("SCRIPT_COMMAND_START_MOVE source mover isn't unit (TypeId: %u), skipping.",source->GetTypeId());
+ break;
+ }
+
+ if(!WaypointMgr.GetPath(step.script->datalong))
+ {
+ sLog.outError("SCRIPT_COMMAND_START_MOVE source mover has an invallid path, skipping.", step.script->datalong2);
+ break;
+ }
+
+ dynamic_cast<Unit*>(source)->GetMotionMaster()->MovePath(step.script->datalong, step.script->datalong2);
+ break;
+ }
+
+ default:
sLog.outError("Unknown script command %u called.",step.script->command);
break;
}
diff --git a/src/game/World.h b/src/game/World.h
index fc11301f883..885047e6685 100644
--- a/src/game/World.h
+++ b/src/game/World.h
@@ -326,6 +326,7 @@ enum RealmZone
#define SCRIPT_COMMAND_ACTIVATE_OBJECT 13 // source = unit, target=GO
#define SCRIPT_COMMAND_REMOVE_AURA 14 // source (datalong2!=0) or target (datalong==0) unit, datalong = spell_id
#define SCRIPT_COMMAND_CAST_SPELL 15 // source (datalong2!=0) or target (datalong==0) unit, datalong = spell_id
+#define SCRIPT_COMMAND_LOAD_PATH 16 // source = unit, path = datalong, repeatable datalong2
/// Storage class for commands issued for delayed execution
struct CliCommandHolder
diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp
index 720e6e3e683..4845841b6d6 100644
--- a/src/shared/Database/SQLStorage.cpp
+++ b/src/shared/Database/SQLStorage.cpp
@@ -29,9 +29,9 @@ extern DatabaseMysql WorldDatabase;
const char CreatureInfosrcfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiis";
const char CreatureInfodstfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiii";
-const char CreatureDataAddonInfofmt[]="iiiiiiis";
+const char CreatureDataAddonInfofmt[]="iiiiiiiis";
const char CreatureModelfmt[]="iffbi";
-const char CreatureInfoAddonInfofmt[]="iiiiiiis";
+const char CreatureInfoAddonInfofmt[]="iiiiiiiis";
const char EquipmentInfofmt[]="iiiiiiiiii";
const char GameObjectInfosrcfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis";
const char GameObjectInfodstfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiii";