*Merged 459

--HG--
branch : trunk
This commit is contained in:
Blaymoira
2008-12-11 21:32:08 +01:00
47 changed files with 1849 additions and 1795 deletions
+36
View File
@@ -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`;
+9
View File
@@ -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);
+14
View File
@@ -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');
-1
View File
@@ -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_darkheart' WHERE `entry` =24246;
UPDATE `creature_template` SET `ScriptName` = 'boss_koragg' WHERE `entry` =24247; 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` = '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` = 'mob_zuljin_vortex' WHERE `entry` = '24136';
UPDATE `creature_template` SET `ScriptName` = 'npc_zulaman_hostage' WHERE `entry` IN (23790, 23999, 24024, 24001); UPDATE `creature_template` SET `ScriptName` = 'npc_zulaman_hostage' WHERE `entry` IN (23790, 23999, 24024, 24001);
+46 -21
View File
@@ -220,6 +220,7 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `creature_addon`; DROP TABLE IF EXISTS `creature_addon`;
CREATE TABLE `creature_addon` ( CREATE TABLE `creature_addon` (
`guid` int(10) unsigned NOT NULL default '0', `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', `mount` mediumint(8) unsigned NOT NULL default '0',
`bytes0` int(10) unsigned NOT NULL default '0', `bytes0` int(10) unsigned NOT NULL default '0',
`bytes1` 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 */; /*!40000 ALTER TABLE `creature_model_info` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
-- --
-- Table structure for table `creature_movement` -- Table structure for table `waypoint_data`
-- --
DROP TABLE IF EXISTS `creature_movement`; DROP TABLE IF EXISTS `waypoint_data`;
CREATE TABLE `creature_movement` ( CREATE TABLE `waypoint_data` (
`id` int(10) unsigned NOT NULL COMMENT 'Creature GUID', `id` int(10) unsigned NOT NULL default '0' COMMENT 'Creature GUID',
`point` mediumint(8) unsigned NOT NULL default '0', `point` mediumint(8) unsigned NOT NULL default '0',
`position_x` float NOT NULL default '0', `position_x` float NOT NULL default '0',
`position_y` float NOT NULL default '0', `position_y` float NOT NULL default '0',
`position_z` float NOT NULL default '0', `position_z` float NOT NULL default '0',
`waittime` int(10) unsigned NOT NULL default '0', `delay` int(10) unsigned NOT NULL default '0',
`text1` text, `move_flag` tinyint(1) NOT NULL default '0',
`text2` text, `action` int(11) NOT NULL default '0',
`text3` text, `action_chance` smallint(3) NOT NULL default '100',
`text4` text, `wpguid` int(11) NOT NULL default '0'
`text5` text, ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
`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';
-- --
-- Dumping data for table `creature_movement` -- Dumping data for table `creature_movement`
-- --
LOCK TABLES `creature_movement` WRITE; LOCK TABLES `waypoint_data` WRITE;
/*!40000 ALTER TABLE `creature_movement` DISABLE KEYS */; /*!40000 ALTER TABLE `waypoint_data` DISABLE KEYS */;
/*!40000 ALTER TABLE `creature_movement` ENABLE 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 `waypoint_scripts` WRITE;
/*!40000 ALTER TABLE `waypoint_scripts` DISABLE KEYS */;
/*!40000 ALTER TABLE `waypoint_scripts` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
-- --
@@ -533,6 +557,7 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `creature_template_addon`; DROP TABLE IF EXISTS `creature_template_addon`;
CREATE TABLE `creature_template_addon` ( CREATE TABLE `creature_template_addon` (
`entry` mediumint(8) unsigned NOT NULL default '0', `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', `mount` mediumint(8) unsigned NOT NULL default '0',
`bytes0` int(10) unsigned NOT NULL default '0', `bytes0` int(10) unsigned NOT NULL default '0',
`bytes1` int(10) unsigned NOT NULL default '0', `bytes1` int(10) unsigned NOT NULL default '0',
+2 -2
View File
@@ -220,10 +220,10 @@ void ScriptedAI::DoStopAttack()
void ScriptedAI::DoCast(Unit* victim, uint32 spellId, bool triggered) void ScriptedAI::DoCast(Unit* victim, uint32 spellId, bool triggered)
{ {
if (!victim || m_creature->IsNonMeleeSpellCasted(false)) if (!victim || m_creature->hasUnitState(UNIT_STAT_CASTING))
return; return;
m_creature->StopMoving(); //m_creature->StopMoving();
m_creature->CastSpell(victim, spellId, triggered); m_creature->CastSpell(victim, spellId, triggered);
} }
+4 -4
View File
@@ -183,13 +183,13 @@ struct TRINITY_DLL_DECL Scripted_NoMovementAI : public ScriptedAI
void AttackStart(Unit *); 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() {} ~NullCreatureAI() {}
Creature *m_creature; void Reset() {}
void Aggro(Unit*) {}
void MoveInLineOfSight(Unit *) {} void MoveInLineOfSight(Unit *) {}
void AttackStart(Unit *) {} void AttackStart(Unit *) {}
void EnterEvadeMode() {} void EnterEvadeMode() {}
@@ -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) blade_of_azzinothAI(Creature* c) : NullCreatureAI(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) { }
void SpellHit(Unit *caster, const SpellEntry *spell) void SpellHit(Unit *caster, const SpellEntry *spell)
{ {
@@ -2060,15 +1996,14 @@ void boss_illidan_stormrageAI::CastEyeBlast()
final.x = 2 * final.x - initial.x; final.x = 2 * final.x - initial.x;
final.y = 2 * final.y - initial.y; 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; if(!Trigger) return;
((demonfireAI*)Trigger->AI())->IsTrigger = true;
Trigger->SetSpeed(MOVE_WALK, 3); Trigger->SetSpeed(MOVE_WALK, 3);
Trigger->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); Trigger->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE);
Trigger->GetMotionMaster()->MovePoint(0, final.x, final.y, final.z); 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()); m_creature->SetUInt64Value(UNIT_FIELD_TARGET, Trigger->GetGUID());
DoCast(Trigger, SPELL_EYE_BLAST); DoCast(Trigger, SPELL_EYE_BLAST);
} }
@@ -2225,11 +2160,6 @@ CreatureAI* GetAI_shadow_demon(Creature *_Creature)
return new shadow_demonAI (_Creature); return new shadow_demonAI (_Creature);
} }
CreatureAI* GetAI_demonfire(Creature *_Creature)
{
return new demonfireAI (_Creature);
}
CreatureAI* GetAI_blade_of_azzinoth(Creature *_Creature) CreatureAI* GetAI_blade_of_azzinoth(Creature *_Creature)
{ {
return new blade_of_azzinothAI (_Creature); return new blade_of_azzinothAI (_Creature);
@@ -2286,11 +2216,6 @@ void AddSC_boss_illidan()
newscript->GetAI = GetAI_shadow_demon; newscript->GetAI = GetAI_shadow_demon;
newscript->RegisterSelf(); newscript->RegisterSelf();
newscript = new Script;
newscript->Name="mob_demon_fire";
newscript->GetAI = GetAI_demonfire;
newscript->RegisterSelf();
newscript = new Script; newscript = new Script;
newscript->Name = "mob_parasitic_shadowfiend"; newscript->Name = "mob_parasitic_shadowfiend";
newscript->GetAI = GetAI_parasitic_shadowfiend; newscript->GetAI = GetAI_parasitic_shadowfiend;
@@ -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) CreatureAI* GetAI_boss_broggokAI(Creature *_Creature)
{ {
return new boss_broggokAI (_Creature); return new boss_broggokAI (_Creature);
} }
CreatureAI* GetAI_mob_broggok_poisoncloudAI(Creature *_Creature)
{
return new mob_broggok_poisoncloudAI (_Creature);
}
void AddSC_boss_broggok() void AddSC_boss_broggok()
{ {
Script *newscript; Script *newscript;
@@ -124,9 +91,4 @@ void AddSC_boss_broggok()
newscript->Name="boss_broggok"; newscript->Name="boss_broggok";
newscript->GetAI = GetAI_boss_broggokAI; newscript->GetAI = GetAI_boss_broggokAI;
newscript->RegisterSelf(); newscript->RegisterSelf();
newscript = new Script;
newscript->Name="mob_broggok_poisoncloud";
newscript->GetAI = GetAI_mob_broggok_poisoncloudAI;
newscript->RegisterSelf();
} }
@@ -31,58 +31,54 @@
struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance
{ {
instance_uldaman(Map *Map) : ScriptedInstance(Map) { instance_uldaman(Map *map) : ScriptedInstance(map)
{
Initialize(); 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 archaedasGUID;
uint64 stoneKeeper[4]; uint64 altarOfTheKeeperTempleDoor;
uint32 stoneKeepersCounter; uint64 archaedasTempleDoor;
uint64 ancientVaultDoor;
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 whoWokeArchaedasGUID; uint64 whoWokeArchaedasGUID;
void OnObjectCreate (GameObject* go) { std::vector<uint64> stoneKeeper;
switch (go->GetEntry()) { 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 case ALTAR_OF_THE_KEEPER_TEMPLE_DOOR: // lock the door
altarOfTheKeeperTempleDoor = go; altarOfTheKeeperTempleDoor = go->GetGUID();
break; break;
case ARCHAEDAS_TEMPLE_DOOR: case ARCHAEDAS_TEMPLE_DOOR:
archaedasTempleDoor = go; archaedasTempleDoor = go->GetGUID();
break; break;
case ANCIENT_VAULT_DOOR: case ANCIENT_VAULT_DOOR:
go->SetUInt32Value(GAMEOBJECT_STATE,1); go->SetUInt32Value(GAMEOBJECT_STATE,1);
go->SetUInt32Value(GAMEOBJECT_FLAGS, 33); go->SetUInt32Value(GAMEOBJECT_FLAGS, 33);
ancientVaultDoor = go; ancientVaultDoor = go->GetGUID();
break; break;
} }
} }
void SetFrozenState(Creature *creature) { void SetFrozenState(Creature *creature)
{
creature->setFaction(35); creature->setFaction(35);
creature->RemoveAllAuras(); creature->RemoveAllAuras();
//creature->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_ANIMATION_FROZEN); //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); creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
} }
void OpenDoor (GameObject *go) { void OpenDoor(uint64 guid)
if (!go) return; {
GameObject *go = instance->GetGameObjectInMap(guid);
if(!go)
return;
go->SetUInt32Value(GAMEOBJECT_FLAGS, 33); go->SetUInt32Value(GAMEOBJECT_FLAGS, 33);
go->SetUInt32Value(GAMEOBJECT_STATE, 0); go->SetUInt32Value(GAMEOBJECT_STATE, 0);
} }
void ActivateStoneKeepers()
{
void ActivateStoneKeepers() { for(std::vector<uint64>::iterator i = stoneKeeper.begin(); i != stoneKeeper.end(); ++i)
Creature *target; {
uint32 counter = stoneKeepersCounter; Creature *target = instance->GetCreatureInMap(*i);
// error_log ("ActivateStoneKeepers"); if (!target || !target->isAlive() || target->getFaction()==14)
// error_log ("counter = %d", counter); continue;
for (; counter>0; ) { target->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE);
target = (Creature *) Unit::GetUnit(*archaedas,stoneKeeper[--counter]);
if (!target || !target->isAlive() || target->getFaction()==14) continue;
target->RemoveFlag (UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_MOVE);
target->setFaction(14); target->setFaction(14);
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
return; // only want the first one we find 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 // if we get this far than all four are dead so open the door
SetData (NULL, 0); SetData (NULL, 0);
} }
void ActivateWallMinions() { void ActivateWallMinions()
Creature *target; {
uint32 counter = archaedasWallMinionsCounter; Creature *archaedas = instance->GetCreatureInMap(archaedasGUID);
for (; counter>0; ) { if(!archaedas)
target = (Creature *) Unit::GetUnit(*archaedas,archaedasWallMinions[--counter]); return;
if (!target || !target->isAlive() || target->getFaction()==14) continue;
archaedas->CastSpell (target, SPELL_AWAKEN_VAULT_WALKER, true); 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); target->CastSpell(target, SPELL_ARCHAEDAS_AWAKEN,true);
return; // only want the first one we find return; // only want the first one we find
} }
} }
// used when Archaedas dies. All active minions must be despawned. // used when Archaedas dies. All active minions must be despawned.
void DeActivateMinions() { void DeActivateMinions()
Creature *target; {
uint32 counter = archaedasWallMinionsCounter;
// first despawn any aggroed wall minions // first despawn any aggroed wall minions
for (; counter>0; ) { for(std::vector<uint64>::iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i)
target = (Creature *) Unit::GetUnit(*archaedas,archaedasWallMinions[--counter]); {
if (!target || target->isDead() || target->getFaction()!=14) continue; Creature *target = instance->GetCreatureInMap(*i);
target->RemoveFromWorld(); if (!target || target->isDead() || target->getFaction()!=14)
target->AI()->EnterEvadeMode(); // need this b/c it still attacks even when removed continue;
target->setDeathState(JUST_DIED);
target->RemoveCorpse();
} }
// Vault Walkers // Vault Walkers
for (counter=0; counter<4; counter++) { for(std::vector<uint64>::iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i)
target = (Creature *) Unit::GetUnit(*archaedas,vaultWalker[counter]); {
if (!target || target->isDead() || target->getFaction() != 14) continue; Creature *target = instance->GetCreatureInMap(*i);
target->RemoveFromWorld(); if (!target || target->isDead() || target->getFaction()!=14)
target->AI()->EnterEvadeMode(); // need this b/c it sill attacks even when removed continue;
target->setDeathState(JUST_DIED);
target->RemoveCorpse();
} }
// Earthen Guardians // Earthen Guardians
for (counter=0; counter<6; counter++) { for(std::vector<uint64>::iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i)
target = (Creature *) Unit::GetUnit(*archaedas,earthenGuardian[counter]); {
if (!target || target->isDead() || target->getFaction() != 14) continue; Creature *target = instance->GetCreatureInMap(*i);
target->RemoveFromWorld(); if (!target || target->isDead() || target->getFaction()!=14)
target->AI()->EnterEvadeMode(); // need this b/c it sill attacks even when removed continue;
target->setDeathState(JUST_DIED);
target->RemoveCorpse();
} }
} }
void ActivateArchaedas(uint64 target) { void ActivateArchaedas(uint64 target)
{
Creature *archaedas = instance->GetCreatureInMap(archaedasGUID);
if(!archaedas)
return;
Unit *victim = Unit::GetUnit(*archaedas, target); if(Unit *victim = Unit::GetUnit(*archaedas, target))
archaedas->CastSpell(archaedas, SPELL_ARCHAEDAS_AWAKEN,false); {
whoWokeArchaedasGUID = target; archaedas->CastSpell(archaedas, SPELL_ARCHAEDAS_AWAKEN,false);
whoWokeArchaedasGUID = target;
}
} }
void RespawnMinions() { void RespawnMinions()
Creature *target; {
uint32 counter = archaedasWallMinionsCounter; // first respawn any aggroed wall minions
for(std::vector<uint64>::iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i)
// first respawn any wall minions {
for (; counter>0; ) { Creature *target = instance->GetCreatureInMap(*i);
target = (Creature *) Unit::GetUnit(*archaedas,archaedasWallMinions[--counter]); if (target && target->isDead())
if (target && target->isDead()) { {
target->Respawn(); target->Respawn();
target->GetMotionMaster()->MoveTargetedHome(); target->GetMotionMaster()->MoveTargetedHome();
//target->AI()->EnterEvadeMode();
SetFrozenState(target); SetFrozenState(target);
} }
} }
// Vault Walkers // Vault Walkers
for (counter=0; counter<4; counter++) { for(std::vector<uint64>::iterator i = vaultWalker.begin(); i != vaultWalker.end(); ++i)
target = (Creature *) Unit::GetUnit(*archaedas,vaultWalker[counter]); {
if (target && target->isDead()) { Creature *target = instance->GetCreatureInMap(*i);
if (target && target->isDead())
{
target->Respawn(); target->Respawn();
target->GetMotionMaster()->MoveTargetedHome(); target->GetMotionMaster()->MoveTargetedHome();
// target->AI()->EnterEvadeMode();
SetFrozenState(target); SetFrozenState(target);
} }
} }
// Earthen Guardians // Earthen Guardians
for (counter=0; counter<6; counter++) { for(std::vector<uint64>::iterator i = earthenGuardian.begin(); i != earthenGuardian.end(); ++i)
target = (Creature *) Unit::GetUnit(*archaedas,earthenGuardian[counter]); {
if (target && target->isDead()) { Creature *target = instance->GetCreatureInMap(*i);
if (target && target->isDead())
{
target->Respawn(); target->Respawn();
target->GetMotionMaster()->MoveTargetedHome(); target->GetMotionMaster()->MoveTargetedHome();
//target->AI()->EnterEvadeMode();
SetFrozenState(target); SetFrozenState(target);
} }
} }
} }
void SetData (uint32 type, uint32 data) { void SetData (uint32 type, uint32 data)
{
//error_log ("SetData: data = %d", data); //error_log ("SetData: data = %d", data);
if (data==0) OpenDoor (altarOfTheKeeperTempleDoor); if (data==0) OpenDoor (altarOfTheKeeperTempleDoor);
if (data==0) OpenDoor (archaedasTempleDoor); if (data==0) OpenDoor (archaedasTempleDoor);
@@ -216,8 +228,11 @@ struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance
} }
void SetData64 (uint32 type, uint64 data) { void SetData64 (uint32 type, uint64 data)
if (type==0 ) { // Archaedas {
// Archaedas
if (type==0 )
{
ActivateArchaedas (data); ActivateArchaedas (data);
} }
} }
@@ -228,33 +243,34 @@ struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance
switch (creature_entry) { switch (creature_entry) {
case 4857: // Stone Keeper case 4857: // Stone Keeper
SetFrozenState (creature); SetFrozenState (creature);
stoneKeeper[stoneKeepersCounter++] = creature->GetGUID(); stoneKeeper.push_back(creature->GetGUID());
break; break;
case 7309: // Earthen Custodian case 7309: // Earthen Custodian
archaedasWallMinions[archaedasWallMinionsCounter++] = creature->GetGUID(); archaedasWallMinions.push_back(creature->GetGUID());
break; break;
case 7077: // Earthen Hallshaper case 7077: // Earthen Hallshaper
archaedasWallMinions[archaedasWallMinionsCounter++] = creature->GetGUID(); archaedasWallMinions.push_back(creature->GetGUID());
break; break;
case 7076: // Earthen Guardian case 7076: // Earthen Guardian
earthenGuardian[earthenGuardianCounter++] = creature->GetGUID(); earthenGuardian.push_back(creature->GetGUID());
break; break;
case 10120: // Vault Walker case 10120: // Vault Walker
vaultWalker[vaultWalkerCounter++] = creature->GetGUID(); vaultWalker.push_back(creature->GetGUID());
break; break;
case 2748: // Archaedas case 2748: // Archaedas
archaedas = creature; archaedasGUID = creature->GetGUID();
break; break;
} // end switch } // end switch
} // end OnCreatureCreate } // end OnCreatureCreate
uint64 GetData64 (uint32 identifier) { uint64 GetData64 (uint32 identifier)
{
if (identifier == 0) return whoWokeArchaedasGUID; if (identifier == 0) return whoWokeArchaedasGUID;
if (identifier == 1) return vaultWalker[0]; // VaultWalker1 if (identifier == 1) return vaultWalker[0]; // VaultWalker1
if (identifier == 2) return vaultWalker[1]; // VaultWalker2 if (identifier == 2) return vaultWalker[1]; // VaultWalker2
@@ -270,7 +286,6 @@ struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance
return 0; return 0;
} // end GetData64 } // end GetData64
}; };
@@ -25,7 +25,6 @@ EndScriptData */
#include "precompiled.h" #include "precompiled.h"
#include "def_zulaman.h" #include "def_zulaman.h"
#include "Spell.h"
#include "Weather.h" #include "Weather.h"
#define SPELL_STATIC_DISRUPTION 43622 #define SPELL_STATIC_DISRUPTION 43622
@@ -34,6 +33,7 @@ EndScriptData */
#define SPELL_GUST_OF_WIND 43621 #define SPELL_GUST_OF_WIND 43621
#define SPELL_ELECTRICAL_STORM 43648 #define SPELL_ELECTRICAL_STORM 43648
#define SPELL_BERSERK 45078 #define SPELL_BERSERK 45078
#define SPELL_ELECTRICAL_DAMAGE 43657
#define SPELL_ELECTRICAL_OVERLOAD 43658 #define SPELL_ELECTRICAL_OVERLOAD 43658
#define SPELL_EAGLE_SWOOP 44732 #define SPELL_EAGLE_SWOOP 44732
@@ -57,15 +57,13 @@ EndScriptData */
#define SE_LOC_Y_MAX 1435 #define SE_LOC_Y_MAX 1435
#define SE_LOC_Y_MIN 1370 #define SE_LOC_Y_MIN 1370
#define MOB_TEMP_TRIGGER 23920
struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI
{ {
boss_akilzonAI(Creature *c) : ScriptedAI(c) boss_akilzonAI(Creature *c) : ScriptedAI(c)
{ {
SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_ELECTRICAL_STORM); SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_ELECTRICAL_DAMAGE);
if(TempSpell) 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()); pInstance = ((ScriptedInstance*)c->GetInstanceData());
Reset(); Reset();
} }
@@ -214,7 +212,7 @@ struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI
{ {
x = 343+rand()%60; x = 343+rand()%60;
y = 1380+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->setFaction(35);
trigger->SetMaxHealth(100000); trigger->SetMaxHealth(100000);
@@ -315,7 +313,7 @@ struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI
target->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); target->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING);
target->SendMonsterMove(x,y,m_creature->GetPositionZ()+15,0,0,0); 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) if(Cloud)
{ {
CloudGUID = Cloud->GetGUID(); CloudGUID = Cloud->GetGUID();
@@ -226,9 +226,9 @@ struct TRINITY_DLL_DECL boss_janalaiAI : public ScriptedAI
for(uint8 j = 0; j < WallNum; j++) for(uint8 j = 0; j < WallNum; j++)
{ {
if(WallNum == 3) 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 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); if(wall) wall->CastSpell(wall, SPELL_FIRE_WALL, true);
} }
} }
@@ -683,14 +683,9 @@ CreatureAI* GetAI_mob_hatchlingAI(Creature *_Creature)
return new mob_hatchlingAI(_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){} mob_eggAI(Creature *c) : NullCreatureAI(c){}
void Reset() {}
void Aggro(Unit* who) {}
void AttackStart(Unit* who) {}
void MoveInLineOfSight(Unit* who) {}
void UpdateAI(const uint32 diff) {}
void SpellHit(Unit *caster, const SpellEntry *spell) void SpellHit(Unit *caster, const SpellEntry *spell)
{ {
@@ -546,23 +546,15 @@ struct TRINITY_DLL_DECL boss_zuljinAI : public ScriptedAI
if(Pillar_Of_Fire_Timer < diff) if(Pillar_Of_Fire_Timer < diff)
{ {
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
{ DoCast(target, SPELL_SUMMON_PILLAR);
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);
}
}
Pillar_Of_Fire_Timer = 10000; Pillar_Of_Fire_Timer = 10000;
}else Pillar_Of_Fire_Timer -= diff; }else Pillar_Of_Fire_Timer -= diff;
if(Flame_Breath_Timer < diff) if(Flame_Breath_Timer < diff)
{ {
if(Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) 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; Flame_Breath_Timer = 10000;
}else Flame_Breath_Timer -= diff; }else Flame_Breath_Timer -= diff;
break; break;
@@ -581,21 +573,6 @@ CreatureAI* GetAI_boss_zuljin(Creature *_Creature)
return new boss_zuljinAI (_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 struct TRINITY_DLL_DECL feather_vortexAI : public ScriptedAI
{ {
feather_vortexAI(Creature *c) : ScriptedAI(c) {} feather_vortexAI(Creature *c) : ScriptedAI(c) {}
@@ -631,11 +608,6 @@ void AddSC_boss_zuljin()
newscript->GetAI = GetAI_boss_zuljin; newscript->GetAI = GetAI_boss_zuljin;
newscript->RegisterSelf(); newscript->RegisterSelf();
newscript = new Script;
newscript->Name="do_nothing";
newscript->GetAI = GetAI_do_nothing;
newscript->RegisterSelf();
newscript = new Script; newscript = new Script;
newscript->Name="mob_zuljin_vortex"; newscript->Name="mob_zuljin_vortex";
newscript->GetAI = GetAI_feather_vortexAI; newscript->GetAI = GetAI_feather_vortexAI;
+1
View File
@@ -142,6 +142,7 @@ struct TRINITY_DLL_DECL Cell
} data; } 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 &) 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> template<class T>
+48
View File
@@ -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 #endif
+15 -7
View File
@@ -137,13 +137,16 @@ ChatCommand * ChatHandler::getCommandTable()
static ChatCommand wpCommandTable[] = static ChatCommand wpCommandTable[] =
{ {
{ "show", SEC_GAMEMASTER, false, &ChatHandler::HandleWpShowCommand, "", NULL }, { "show", SEC_GAMEMASTER, false, &ChatHandler::HandleWpShowCommand, "", NULL },
{ "add", SEC_GAMEMASTER, false, &ChatHandler::HandleWpAddCommand, "", NULL }, { "addwp", SEC_GAMEMASTER, false, &ChatHandler::HandleWpAddCommand, "", NULL },
{ "modify", SEC_GAMEMASTER, false, &ChatHandler::HandleWpModifyCommand, "", NULL }, { "load", SEC_GAMEMASTER, false, &ChatHandler::HandleWpLoadPathCommand, "", NULL },
{ "export", SEC_ADMINISTRATOR, false, &ChatHandler::HandleWpExportCommand, "", NULL }, { "modify", SEC_GAMEMASTER, false, &ChatHandler::HandleWpModifyCommand, "", NULL },
{ "import", SEC_ADMINISTRATOR, false, &ChatHandler::HandleWpImportCommand, "", NULL }, { "event", SEC_GAMEMASTER, false, &ChatHandler::HandleWpEventCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL } { "unload", SEC_GAMEMASTER, false, &ChatHandler::HandleWpUnLoadPathCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
}; };
static ChatCommand banCommandTable[] = static ChatCommand banCommandTable[] =
{ {
{ "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanAccountCommand, "", NULL }, { "account", SEC_ADMINISTRATOR, true, &ChatHandler::HandleBanAccountCommand, "", NULL },
@@ -293,6 +296,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "locales_npc_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesNpcTextCommand, "", NULL }, { "locales_npc_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesNpcTextCommand, "", NULL },
{ "locales_page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesPageTextCommand, "", NULL }, { "locales_page_text", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesPageTextCommand, "", NULL },
{ "locales_quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesQuestCommand, "", NULL }, { "locales_quest", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLocalesQuestCommand, "", NULL },
{ "waypoint_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadWpScriptsCommand, "", NULL },
{ "", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCommand, "", NULL }, { "", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL } { NULL, 0, false, NULL, "", NULL }
@@ -507,8 +511,12 @@ ChatCommand * ChatHandler::getCommandTable()
{ "event", SEC_GAMEMASTER, false, NULL, "", eventCommandTable }, { "event", SEC_GAMEMASTER, false, NULL, "", eventCommandTable },
{ "gobject", SEC_GAMEMASTER, false, NULL, "", gobjectCommandTable }, { "gobject", SEC_GAMEMASTER, false, NULL, "", gobjectCommandTable },
{ "honor", SEC_GAMEMASTER, false, NULL, "", honorCommandTable }, { "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 }, { "reload", SEC_ADMINISTRATOR, true, NULL, "", reloadCommandTable },
{ "list", SEC_ADMINISTRATOR, true, NULL, "", listCommandTable }, { "list", SEC_ADMINISTRATOR, true, NULL, "", listCommandTable },
{ "lookup", SEC_ADMINISTRATOR, true, NULL, "", lookupCommandTable }, { "lookup", SEC_ADMINISTRATOR, true, NULL, "", lookupCommandTable },
+12 -6
View File
@@ -211,7 +211,8 @@ class ChatHandler
bool HandleReloadConfigCommand(const char* args); 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 HandleReloadAreaTriggerTeleportCommand(const char* args);
bool HandleReloadEventScriptsCommand(const char* args); bool HandleReloadEventScriptsCommand(const char* args);
bool HandleReloadCommandCommand(const char* args); bool HandleReloadCommandCommand(const char* args);
@@ -410,11 +411,16 @@ class ChatHandler
bool HandlePasswordCommand(const char* args); bool HandlePasswordCommand(const char* args);
bool HandleLockAccountCommand(const char* args); bool HandleLockAccountCommand(const char* args);
bool HandleRespawnCommand(const char* args); bool HandleRespawnCommand(const char* args);
bool HandleWpAddCommand(const char* args);
bool HandleWpModifyCommand(const char* args); //New Wp Commands
bool HandleWpShowCommand(const char* args); bool HandleWpAddCommand(const char* args);
bool HandleWpExportCommand(const char* args); bool HandleWpLoadPathCommand(const char* args);
bool HandleWpImportCommand(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 HandleFlyModeCommand(const char* args);
bool HandleSendOpcodeCommand(const char* args); bool HandleSendOpcodeCommand(const char* args);
bool HandleSellErrorCommand(const char* args); bool HandleSellErrorCommand(const char* args);
+8 -4
View File
@@ -347,10 +347,10 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data )
m_spells[3] = GetCreatureInfo()->spell4; m_spells[3] = GetCreatureInfo()->spell4;
// HACK: trigger creature is always not selectable // 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); SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
if(isTotem() || GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER if(isTotem() || isTrigger()
|| GetCreatureType() == CREATURE_TYPE_CRITTER) || GetCreatureType() == CREATURE_TYPE_CRITTER)
SetReactState(REACT_PASSIVE); SetReactState(REACT_PASSIVE);
else if(isCivilian()) else if(isCivilian())
@@ -563,7 +563,7 @@ void Creature::RegenerateHealth()
ModifyHealth(addvalue); ModifyHealth(addvalue);
} }
bool Creature::AIM_Initialize() bool Creature::AIM_Initialize(CreatureAI* ai)
{ {
// make sure nothing can change the AI during AI update // make sure nothing can change the AI during AI update
if(m_AI_locked) if(m_AI_locked)
@@ -578,7 +578,7 @@ bool Creature::AIM_Initialize()
CreatureAI * oldAI = i_AI; CreatureAI * oldAI = i_AI;
i_motionMaster.Initialize(); i_motionMaster.Initialize();
i_AI = FactorySelector::selectAI(this); i_AI = ai ? ai : FactorySelector::selectAI(this);
if (oldAI) if (oldAI)
delete oldAI; delete oldAI;
return true; return true;
@@ -2068,6 +2068,10 @@ bool Creature::LoadCreaturesAddon(bool reload)
if (cainfo->move_flags != 0) if (cainfo->move_flags != 0)
SetUnitMovementFlags(cainfo->move_flags); SetUnitMovementFlags(cainfo->move_flags);
//Load Path
if (cainfo->path_id != 0)
m_path_id = cainfo->path_id;
if(cainfo->auras) if(cainfo->auras)
{ {
for (CreatureDataAddonAura const* cAura = cainfo->auras; cAura->spell_id; ++cAura) for (CreatureDataAddonAura const* cAura = cainfo->auras; cAura->spell_id; ++cAura)
+17 -4
View File
@@ -279,7 +279,8 @@ struct CreatureDataAddonAura
struct CreatureDataAddon struct CreatureDataAddon
{ {
uint32 guidOrEntry; uint32 guidOrEntry;
uint32 mount; uint32 path_id;
uint32 mount;
uint32 bytes0; uint32 bytes0;
uint32 bytes1; uint32 bytes1;
uint32 bytes2; uint32 bytes2;
@@ -425,6 +426,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool isTotem() const { return m_isTotem; } bool isTotem() const { return m_isTotem; }
bool isRacialLeader() const { return GetCreatureInfo()->RacialLeader; } bool isRacialLeader() const { return GetCreatureInfo()->RacialLeader; }
bool isCivilian() const { return GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_CIVILIAN; } 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 canWalk() const { return GetCreatureInfo()->InhabitType & INHABIT_GROUND; }
bool canSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; } bool canSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; }
bool canFly() const { return GetCreatureInfo()->InhabitType & INHABIT_AIR; } bool canFly() const { return GetCreatureInfo()->InhabitType & INHABIT_AIR; }
@@ -461,7 +463,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
bool IsInEvadeMode() const; bool IsInEvadeMode() const;
bool AIM_Initialize(); bool AIM_Initialize(CreatureAI* ai = NULL);
void InitPossessedAI(); void InitPossessedAI();
void DisablePossessedAI(); 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; } void GetCombatStartPosition(float &x, float &y, float &z) { x = CombatStartX; y = CombatStartY; z = CombatStartZ; }
uint32 GetGlobalCooldown() const { return m_GlobalCooldown; } 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 CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL);
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, 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; float CombatStartZ;
private: 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()) CreatureInfo const* m_creatureInfo; // in heroic mode can different from ObjMgr::GetCreatureTemplate(GetEntry())
}; };
+1 -1
View File
@@ -1277,7 +1277,7 @@ void GameObject::Use(Unit* user)
void GameObject::CastSpell(Unit* target, uint32 spell) void GameObject::CastSpell(Unit* target, uint32 spell)
{ {
//summon world trigger //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; if(!trigger) return;
trigger->SetVisibility(VISIBILITY_OFF); //should this be true? trigger->SetVisibility(VISIBILITY_OFF); //should this be true?
+23 -2
View File
@@ -33,6 +33,17 @@ class GameObject;
class Pet; class Pet;
class Player; 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 MAX_NUMBER_OF_GRIDS 64
#define SIZE_OF_GRIDS 533.33333f #define SIZE_OF_GRIDS 533.33333f
@@ -43,10 +54,8 @@ class Player;
#define MIN_GRID_DELAY MINUTE*1000 #define MIN_GRID_DELAY MINUTE*1000
#define MIN_MAP_UPDATE_DELAY 50 #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 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 CENTER_GRID_CELL_OFFSET (SIZE_OF_GRID_CELL/2)
#define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS) #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); 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) inline void NormalizeMapCoord(float &c)
{ {
if(c > MAP_HALFSIZE - 0.5) if(c > MAP_HALFSIZE - 0.5)
+675 -708
View File
File diff suppressed because it is too large Load Diff
+22 -1
View File
@@ -136,7 +136,8 @@ bool ChatHandler::HandleReloadAllScriptsCommand(const char*)
HandleReloadSpellScriptsCommand("a"); HandleReloadSpellScriptsCommand("a");
SendGlobalSysMessage("DB tables `*_scripts` reloaded."); SendGlobalSysMessage("DB tables `*_scripts` reloaded.");
HandleReloadDbScriptStringCommand("a"); HandleReloadDbScriptStringCommand("a");
return true; HandleReloadWpScriptsCommand("a");
return true;
} }
bool ChatHandler::HandleReloadAllSpellCommand(const char*) bool ChatHandler::HandleReloadAllSpellCommand(const char*)
@@ -542,6 +543,26 @@ bool ChatHandler::HandleReloadEventScriptsCommand(const char* arg)
return true; 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) bool ChatHandler::HandleReloadQuestEndScriptsCommand(const char* arg)
{ {
if(sWorld.IsScriptScheduled()) if(sWorld.IsScriptScheduled())
+25
View File
@@ -319,6 +319,31 @@ void MotionMaster::Mutate(MovementGenerator *m)
push(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() void MotionMaster::propagateSpeedChange()
{ {
Impl::container_type::iterator it = Impl::c.begin(); Impl::container_type::iterator it = Impl::c.begin();
+1
View File
@@ -80,6 +80,7 @@ class TRINITY_DLL_SPEC MotionMaster : private std::stack<MovementGenerator *>
void MovePoint(uint32 id, float x,float y,float z); void MovePoint(uint32 id, float x,float y,float z);
void MoveTaxiFlight(uint32 path, uint32 pathnode); void MoveTaxiFlight(uint32 path, uint32 pathnode);
void MoveDistract(uint32 time); void MoveDistract(uint32 time);
void MovePath(uint32 path_id, bool repeatable);
MovementGeneratorType GetCurrentMovementGeneratorType() const; MovementGeneratorType GetCurrentMovementGeneratorType() const;
+1 -2
View File
@@ -27,7 +27,6 @@ template<class MOVEMENT_GEN>
inline MovementGenerator* inline MovementGenerator*
MovementGeneratorFactory<MOVEMENT_GEN>::Create(void *data) const MovementGeneratorFactory<MOVEMENT_GEN>::Create(void *data) const
{ {
Creature* creature = reinterpret_cast<Creature *>(data); return (new MOVEMENT_GEN());
return (new MOVEMENT_GEN(*creature));
} }
#endif #endif
+19
View File
@@ -1534,6 +1534,25 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float
return go; 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 void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float absAngle ) const
{ {
x = GetPositionX() + (GetObjectSize() + distance2d) * cos(absAngle); x = GetPositionX() + (GetObjectSize() + distance2d) * cos(absAngle);
+2
View File
@@ -28,6 +28,7 @@
#include "GameSystem/GridReference.h" #include "GameSystem/GridReference.h"
#include "ObjectDefines.h" #include "ObjectDefines.h"
#include "GridDefines.h" #include "GridDefines.h"
#include "CreatureAI.h"
#include <set> #include <set>
#include <string> #include <string>
@@ -457,6 +458,7 @@ class TRINITY_DLL_SPEC WorldObject : public Object
Map const* GetBaseMap() const; Map const* GetBaseMap() const;
Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); 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); 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; } bool isActive() const { return m_isActive; }
void setActive(bool isActive); void setActive(bool isActive);
protected: protected:
+15 -1
View File
@@ -54,6 +54,7 @@ ScriptMapMap sQuestStartScripts;
ScriptMapMap sSpellScripts; ScriptMapMap sSpellScripts;
ScriptMapMap sGameObjectScripts; ScriptMapMap sGameObjectScripts;
ScriptMapMap sEventScripts; ScriptMapMap sEventScripts;
ScriptMapMap sWaypointScripts;
bool normalizePlayerName(std::string& name) 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() void ObjectMgr::LoadItemTexts()
{ {
QueryResult *result = CharacterDatabase.Query("SELECT id, text FROM item_text"); QueryResult *result = CharacterDatabase.Query("SELECT id, text FROM item_text");
@@ -7481,7 +7495,7 @@ void ObjectMgr::LoadDbScriptStrings()
CheckScripts(sGameObjectScripts,ids); CheckScripts(sGameObjectScripts,ids);
CheckScripts(sEventScripts,ids); CheckScripts(sEventScripts,ids);
WaypointMgr.CheckTextsExistance(ids); CheckScripts(sWaypointScripts,ids);
for(std::set<int32>::const_iterator itr = ids.begin(); itr != ids.end(); ++itr) 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); sLog.outErrorDb( "Table `db_script_string` has unused string id %u", *itr);
+2
View File
@@ -98,6 +98,7 @@ extern ScriptMapMap sQuestStartScripts;
extern ScriptMapMap sSpellScripts; extern ScriptMapMap sSpellScripts;
extern ScriptMapMap sGameObjectScripts; extern ScriptMapMap sGameObjectScripts;
extern ScriptMapMap sEventScripts; extern ScriptMapMap sEventScripts;
extern ScriptMapMap sWaypointScripts;
struct AreaTrigger struct AreaTrigger
{ {
@@ -531,6 +532,7 @@ class ObjectMgr
void LoadQuestStartScripts(); void LoadQuestStartScripts();
void LoadEventScripts(); void LoadEventScripts();
void LoadSpellScripts(); void LoadSpellScripts();
void LoadWaypointScripts();
bool LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value); 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); } bool LoadTrinityStrings() { return LoadTrinityStrings(WorldDatabase,"trinity_string",MIN_TRINITY_STRING_ID,MAX_TRINITY_STRING_ID); }
+14 -3
View File
@@ -1330,8 +1330,14 @@ void Player::setDeathState(DeathState s)
bool cur = isAlive(); 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 // drunken state is cleared on death
SetDrunkValue(0); SetDrunkValue(0);
// lost combo points at any target (targeted combo points clear in Unit::setDeathState) // 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; 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 // load the player's map here if it's not already loaded
Map *map = GetMap(); Map *map = GetMap();
if (!map) if (!map)
@@ -13919,11 +13928,13 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
{ {
SetMapId(at->target_mapId); SetMapId(at->target_mapId);
Relocate(at->target_X, at->target_Y, at->target_Z, GetOrientation()); 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 else
{ {
SetMapId(m_homebindMapId); SetMapId(m_homebindMapId);
Relocate(m_homebindX, m_homebindY, m_homebindZ, GetOrientation()); 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(); map = GetMap();
@@ -14168,8 +14179,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
m_social = sSocialMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSOCIALLIST), GetGUIDLow()); m_social = sSocialMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSOCIALLIST), GetGUIDLow());
if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND))) //if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND)))
return false; // return false;
// check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES // check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES
// note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded // note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded
+1 -1
View File
@@ -31,7 +31,7 @@ class TRINITY_DLL_SPEC RandomMovementGenerator
: public MovementGeneratorMedium< T, RandomMovementGenerator<T> > : public MovementGeneratorMedium< T, RandomMovementGenerator<T> >
{ {
public: public:
RandomMovementGenerator(const Unit &) : i_nextMoveTime(0) {} RandomMovementGenerator() : i_nextMoveTime(0) {}
void _setRandomLocation(T &); void _setRandomLocation(T &);
void Initialize(T &); void Initialize(T &);
+5 -4
View File
@@ -788,7 +788,7 @@ enum Targets
TARGET_PET = 5, TARGET_PET = 5,
//TARGET_UNIT_PET //TARGET_UNIT_PET
TARGET_CHAIN_DAMAGE = 6, TARGET_CHAIN_DAMAGE = 6,
//TARGET_UNIT_TARGET_ENEMY TARGET_UNIT_TARGET_ENEMY = 6,
TARGET_UNIT_AREA_ENTRY = 7, TARGET_UNIT_AREA_ENTRY = 7,
TARGET_AREAEFFECT_CUSTOM = 8, TARGET_AREAEFFECT_CUSTOM = 8,
//TARGET_UNIT_AREA_ENTRY_GROUND //TARGET_UNIT_AREA_ENTRY_GROUND
@@ -806,7 +806,7 @@ enum Targets
TARGET_ALL_PARTY_AROUND_CASTER = 20, TARGET_ALL_PARTY_AROUND_CASTER = 20,
//TARGET_UNIT_PARTY_CASTER //TARGET_UNIT_PARTY_CASTER
TARGET_SINGLE_FRIEND = 21, 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_ALL_AROUND_CASTER = 22, // used only in TargetA, target selection dependent from TargetB
//TARGET_DEST_CASTER //TARGET_DEST_CASTER
TARGET_GAMEOBJECT = 23, TARGET_GAMEOBJECT = 23,
@@ -833,7 +833,7 @@ enum Targets
TARGET_ALL_PARTY_AROUND_CASTER_2 = 34, // used in Tranquility TARGET_ALL_PARTY_AROUND_CASTER_2 = 34, // used in Tranquility
//TARGET_UNIT_AREA_PARTY_GROUND //TARGET_UNIT_AREA_PARTY_GROUND
TARGET_SINGLE_PARTY = 35, TARGET_SINGLE_PARTY = 35,
//TARGET_UNIT_TARGET_PARTY TARGET_UNIT_TARGET_PARTY = 35,
TARGET_DEST_CASTER_RANDOM_UNKNOWN = 36, //unknown TARGET_DEST_CASTER_RANDOM_UNKNOWN = 36, //unknown
TARGET_AREAEFFECT_PARTY = 37, TARGET_AREAEFFECT_PARTY = 37,
//TARGET_UNIT_PARTY_TARGET //TARGET_UNIT_PARTY_TARGET
@@ -864,7 +864,7 @@ enum Targets
TARGET_RANDOM_RAID_MEMBER = 56, TARGET_RANDOM_RAID_MEMBER = 56,
//TARGET_UNIT_AREA_RAID //TARGET_UNIT_AREA_RAID
TARGET_SINGLE_FRIEND_2 = 57, TARGET_SINGLE_FRIEND_2 = 57,
//TARGET_UNIT_TARGET_RAID TARGET_UNIT_TARGET_RAID = 57,
TARGET_UNIT_CONE_ALLY = 59, TARGET_UNIT_CONE_ALLY = 59,
TARGET_UNIT_AREA_SCRIPT = 60, TARGET_UNIT_AREA_SCRIPT = 60,
TARGET_AREAEFFECT_PARTY_AND_CLASS = 61, TARGET_AREAEFFECT_PARTY_AND_CLASS = 61,
@@ -908,6 +908,7 @@ enum SpellMissInfo
SPELL_MISS_DEFLECT = 9, SPELL_MISS_DEFLECT = 9,
SPELL_MISS_ABSORB = 10, SPELL_MISS_ABSORB = 10,
SPELL_MISS_REFLECT = 11, SPELL_MISS_REFLECT = 11,
SPELL_MISS_KILL = 12, // kill grounding totem
}; };
enum SpellHitType enum SpellHitType
+54 -40
View File
@@ -286,8 +286,6 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi
m_caster = Caster; m_caster = Caster;
m_selfContainer = NULL; m_selfContainer = NULL;
m_triggeringContainer = triggeringContainer; m_triggeringContainer = triggeringContainer;
m_magnetPair.first = false;
m_magnetPair.second = NULL;
m_referencedFromCurrentSpell = false; m_referencedFromCurrentSpell = false;
m_executedCurrently = false; m_executedCurrently = false;
m_delayAtDamageCount = 0; 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 if (target->reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him
DoSpellHitOnUnit(m_caster, mask); 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 else //TODO: This is a hack. need fix
{ {
uint32 tempMask = 0; uint32 tempMask = 0;
@@ -1169,14 +1173,6 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
if(!unit || !effectMask) if(!unit || !effectMask)
return; 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) // Recheck immune (only for delayed spells)
if( m_spellInfo->speed && if( m_spellInfo->speed &&
!(m_spellInfo->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) !(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); unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL);
//TODO: find a better way to judge CC auras if(spellmgr.GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR_CU_AURA_CC)
if(m_spellInfo->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE)
unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CC); unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CC);
} }
else else
@@ -1475,7 +1470,8 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const u
y = m_caster->GetPositionY(); 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 cell(p);
cell.data.Part.reserved = ALL_DISTRICT; cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate(); cell.SetNoCreate();
@@ -1486,12 +1482,12 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const u
//if(TargetType != SPELL_TARGETS_ENTRY) //if(TargetType != SPELL_TARGETS_ENTRY)
{ {
TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier); 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)) if(!(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY))
{ {
TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer > grid_object_notifier(notifier); 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()) if(!_target->isAlive())
return SPELL_FAILED_BAD_TARGETS; return SPELL_FAILED_BAD_TARGETS;
if(IsPositiveSpell(m_spellInfo->Id)) if(!IsValidSingleTargetSpell(_target))
{ return SPELL_FAILED_BAD_TARGETS;
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;
}
}
} }
//cooldown //cooldown
if(((Creature*)m_caster)->HasSpellCooldown(m_spellInfo->Id)) if(((Creature*)m_caster)->HasSpellCooldown(m_spellInfo->Id))
@@ -5311,7 +5289,7 @@ CurrentSpellTypes Spell::GetCurrentContainer()
bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase ) 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) // 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)) if (!CheckTargetCreatureType(target))
return false; return false;
@@ -5392,14 +5370,21 @@ Unit* Spell::SelectMagnetTarget()
{ {
if(Unit* magnet = (*itr)->GetCaster()) 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); (*itr)->SetAuraProcCharges((*itr)->m_procCharges-1);
m_magnetPair.first = true;
m_magnetPair.second = magnet;
target = magnet; target = magnet;
m_targets.setUnitTarget(target); 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; break;
} }
} }
@@ -5551,3 +5536,32 @@ bool SpellEvent::IsDeletable() const
{ {
return m_Spell->IsDeletable(); 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;
}
+2 -1
View File
@@ -364,7 +364,6 @@ class Spell
void SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap); void SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap);
Unit* SelectMagnetTarget(); Unit* SelectMagnetTarget();
std::pair <bool,Unit *> m_magnetPair;
bool CheckTarget( Unit* target, uint32 eff, bool hitPhase ); bool CheckTarget( Unit* target, uint32 eff, bool hitPhase );
void SendCastResult(uint8 result); void SendCastResult(uint8 result);
@@ -538,6 +537,8 @@ class Spell
SpellTargets TargetType, uint32 entry = 0); SpellTargets TargetType, uint32 entry = 0);
Unit* SearchNearbyTarget(float radius, 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); 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 //List For Triggered Spells
+16 -93
View File
@@ -2079,6 +2079,13 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
} }
return; return;
} }
// electrical storm safe zone
if (GetId() == 44007)
{
m_target->ApplySpellImmune(44007, IMMUNITY_ID, 43657, apply);
return;
}
break; break;
} }
case SPELLFAMILY_MAGE: case SPELLFAMILY_MAGE:
@@ -3040,7 +3047,8 @@ void Aura::HandleModConfuse(bool apply, bool Real)
if(!Real) if(!Real)
return; 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) void Aura::HandleModFear(bool apply, bool Real)
@@ -3048,7 +3056,8 @@ void Aura::HandleModFear(bool apply, bool Real)
if (!Real) if (!Real)
return; 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) void Aura::HandleFeignDeath(bool apply, bool Real)
@@ -3146,46 +3155,7 @@ void Aura::HandleAuraModStun(bool apply, bool Real)
if(!Real) if(!Real)
return; return;
if (apply) m_target->SetControlled(apply, UNIT_STAT_STUNNED);
{
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);
}
}
} }
void Aura::HandleModStealth(bool apply, bool Real) void Aura::HandleModStealth(bool apply, bool Real)
@@ -3355,55 +3325,7 @@ void Aura::HandleAuraModRoot(bool apply, bool Real)
if(!Real) if(!Real)
return; return;
uint32 apply_stat = UNIT_STAT_ROOT; m_target->SetControlled(apply, 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);
}
}
}
} }
void Aura::HandleAuraModSilence(bool apply, bool Real) 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); Unit::AuraList const& fearAuras = m_target->GetAurasByType(SPELL_AURA_MOD_FEAR);
if( !fearAuras.empty() ) if( !fearAuras.empty() )
{ {
if (apply) m_target->SetControlled(!apply, UNIT_STAT_FLEEING);
/*if (apply)
m_target->SetFeared(false, fearAuras.front()->GetCasterGUID()); m_target->SetFeared(false, fearAuras.front()->GetCasterGUID());
else else
m_target->SetFeared(true); m_target->SetFeared(true);*/
} }
} }
+21 -12
View File
@@ -1824,27 +1824,36 @@ void SpellMgr::LoadSpellPetAuras()
// set data in core for now // set data in core for now
void SpellMgr::LoadSpellCustomAttr() void SpellMgr::LoadSpellCustomAttr()
{ {
mSpellCustomAttr.resize(GetSpellStore()->GetNumRows());
SpellEntry *tempSpell; SpellEntry *tempSpell;
for(uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i) for(uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i)
{ {
mSpellCustomAttr[i] = 0;
tempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(i); tempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(i);
if(!tempSpell) if(!tempSpell)
continue; continue;
mSpellCustomAttrMap[tempSpell->Id] = 0; for(uint32 j = 0; j < 3; ++j)
for(uint32 i = 0; i < 3; ++i)
{ {
switch(tempSpell->EffectApplyAuraName[i]) switch(tempSpell->EffectApplyAuraName[j])
{ {
case SPELL_AURA_PERIODIC_DAMAGE: case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
case SPELL_AURA_PERIODIC_LEECH: case SPELL_AURA_PERIODIC_LEECH:
mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_EFFECT_DAMAGE; mSpellCustomAttr[i] |= SPELL_ATTR_CU_AURA_DOT;
break; break;
case SPELL_AURA_PERIODIC_HEAL: case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_OBS_MOD_HEALTH: 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; break;
default: default:
break; break;
@@ -1852,14 +1861,14 @@ void SpellMgr::LoadSpellCustomAttr()
} }
if(tempSpell->SpellVisual == 3879) 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 26029: // dark glare
case 37433: // spout case 37433: // spout
case 43140: case 43215: // flame breath case 43140: case 43215: // flame breath
mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_CONE_LINE; mSpellCustomAttr[i] |= SPELL_ATTR_CU_CONE_LINE;
break; break;
case 24340: case 26558: case 28884: // Meteor case 24340: case 26558: case 28884: // Meteor
case 36837: case 38903: case 41276: // Meteor case 36837: case 38903: case 41276: // Meteor
@@ -1869,7 +1878,7 @@ void SpellMgr::LoadSpellCustomAttr()
case 40810: case 43267: case 43268: // Saber Lash case 40810: case 43267: case 43268: // Saber Lash
case 42384: // Brutal Swipe case 42384: // Brutal Swipe
case 45150: // Meteor Slash case 45150: // Meteor Slash
mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_SHARE_DAMAGE; mSpellCustomAttr[i] |= SPELL_ATTR_CU_SHARE_DAMAGE;
break; break;
case 44978: case 45001: case 45002: // Wild Magic case 44978: case 45001: case 45002: // Wild Magic
case 45004: case 45006: case 45010: // Wild Magic case 45004: case 45006: case 45010: // Wild Magic
@@ -1878,12 +1887,12 @@ void SpellMgr::LoadSpellCustomAttr()
case 44869: // Spectral Blast case 44869: // Spectral Blast
case 45027: // Revitalize case 45027: // Revitalize
case 45976: // Muru Portal Channel case 45976: // Muru Portal Channel
mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_PLAYERS_ONLY; mSpellCustomAttr[i] |= SPELL_ATTR_CU_PLAYERS_ONLY;
tempSpell->MaxAffectedTargets = 1; tempSpell->MaxAffectedTargets = 1;
break; break;
case 41376: // Spite case 41376: // Spite
case 39992: // Needle Spine case 39992: // Needle Spine
mSpellCustomAttrMap[tempSpell->Id] |= SPELL_ATTR_CU_PLAYERS_ONLY; mSpellCustomAttr[i] |= SPELL_ATTR_CU_PLAYERS_ONLY;
tempSpell->MaxAffectedTargets = 3; tempSpell->MaxAffectedTargets = 3;
break; break;
case 8122: case 8124: case 10888: case 10890: // Psychic Scream case 8122: case 8124: case 10888: case 10890: // Psychic Scream
+11 -6
View File
@@ -681,10 +681,11 @@ inline bool IsProfessionSkill(uint32 skill)
#define SPELL_ATTR_CU_CONE_BACK 0x00000002 #define SPELL_ATTR_CU_CONE_BACK 0x00000002
#define SPELL_ATTR_CU_CONE_LINE 0x00000004 #define SPELL_ATTR_CU_CONE_LINE 0x00000004
#define SPELL_ATTR_CU_SHARE_DAMAGE 0x00000008 #define SPELL_ATTR_CU_SHARE_DAMAGE 0x00000008
#define SPELL_ATTR_CU_EFFECT_HEAL 0x00000010 #define SPELL_ATTR_CU_AURA_HOT 0x00000010
#define SPELL_ATTR_CU_EFFECT_DAMAGE 0x00000020 #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; typedef std::map<int32, std::vector<int32> > SpellLinkedMap;
@@ -888,11 +889,15 @@ class SpellMgr
uint32 GetSpellCustomAttr(uint32 spell_id) const 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()) if(itr != mSpellCustomAttrMap.end())
return itr->second; return itr->second;
else else
return 0; return 0;*/
} }
const std::vector<int32> *GetSpellLinked(int32 spell_id) const const std::vector<int32> *GetSpellLinked(int32 spell_id) const
@@ -932,7 +937,7 @@ class SpellMgr
SpellProcEventMap mSpellProcEventMap; SpellProcEventMap mSpellProcEventMap;
SkillLineAbilityMap mSkillLineAbilityMap; SkillLineAbilityMap mSkillLineAbilityMap;
SpellPetAuraMap mSpellPetAuraMap; SpellPetAuraMap mSpellPetAuraMap;
SpellCustomAttrMap mSpellCustomAttrMap; SpellCustomAttribute mSpellCustomAttr;
SpellLinkedMap mSpellLinkedMap; SpellLinkedMap mSpellLinkedMap;
}; };
+222 -14
View File
@@ -862,15 +862,15 @@ void Unit::CastSpell(Unit* Victim,SpellEntry const *spellInfo, bool triggered, I
SpellCastTargets targets; SpellCastTargets targets;
uint32 targetMask = spellInfo->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) 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())); 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; return;
} }
targets.setUnitTarget(Victim); }*/
}
if(targetMask & (TARGET_FLAG_SOURCE_LOCATION|TARGET_FLAG_DEST_LOCATION)) if(targetMask & (TARGET_FLAG_SOURCE_LOCATION|TARGET_FLAG_DEST_LOCATION))
{ {
if(!Victim) if(!Victim)
@@ -916,15 +916,15 @@ void Unit::CastCustomSpell(Unit* Victim,SpellEntry const *spellInfo, int32 const
SpellCastTargets targets; SpellCastTargets targets;
uint32 targetMask = spellInfo->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) 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())); 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; return;
} }
targets.setUnitTarget(Victim); }*/
}
if(targetMask & (TARGET_FLAG_SOURCE_LOCATION|TARGET_FLAG_DEST_LOCATION)) if(targetMask & (TARGET_FLAG_SOURCE_LOCATION|TARGET_FLAG_DEST_LOCATION))
{ {
if(!Victim) if(!Victim)
@@ -8303,7 +8303,7 @@ Unit *Unit::GetCharmer() const
return NULL; return NULL;
} }
Player* Unit::GetCharmerOrOwnerPlayerOrPlayerItself() Player* Unit::GetCharmerOrOwnerPlayerOrPlayerItself() const
{ {
uint64 guid = GetCharmerOrOwnerGUID(); uint64 guid = GetCharmerOrOwnerGUID();
if(IS_PLAYER_GUID(guid)) if(IS_PLAYER_GUID(guid))
@@ -9271,13 +9271,6 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges)
if (!spellInfo) if (!spellInfo)
return false; 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]; SpellImmuneList const& dispelList = m_spellImmune[IMMUNITY_DISPEL];
for(SpellImmuneList::const_iterator itr = dispelList.begin(); itr != dispelList.end(); ++itr) for(SpellImmuneList::const_iterator itr = dispelList.begin(); itr != dispelList.end(); ++itr)
if(itr->type == spellInfo->Dispel) if(itr->type == spellInfo->Dispel)
@@ -11855,6 +11848,7 @@ void Unit::StopMoving()
SendMessageToSet(&data,false); SendMessageToSet(&data,false);
} }
/*
void Unit::SetFeared(bool apply, uint64 casterGUID, uint32 spellID) void Unit::SetFeared(bool apply, uint64 casterGUID, uint32 spellID)
{ {
if( apply ) if( apply )
@@ -11923,6 +11917,7 @@ void Unit::SetConfused(bool apply, uint64 casterGUID, uint32 spellID)
if(GetTypeId() == TYPEID_PLAYER) if(GetTypeId() == TYPEID_PLAYER)
((Player*)this)->SetClientControl(this, !apply); ((Player*)this)->SetClientControl(this, !apply);
} }
*/
bool Unit::IsSitState() const bool Unit::IsSitState() const
{ {
@@ -12657,4 +12652,217 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss)
bg->HandleKillUnit((Creature*)pVictim, player); 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;
} }
+10 -3
View File
@@ -37,6 +37,8 @@
#include "Database/DBCStructure.h" #include "Database/DBCStructure.h"
#include <list> #include <list>
#define WORLD_TRIGGER 12999
enum SpellInterruptFlags enum SpellInterruptFlags
{ {
SPELL_INTERRUPT_FLAG_MOVEMENT = 0x01, // why need this for instant? 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 IsHostileToPlayers() const;
bool IsFriendlyTo(Unit const* unit) const; bool IsFriendlyTo(Unit const* unit) const;
bool IsNeutralToAll() const; bool IsNeutralToAll() const;
bool IsInPartyWith(Unit const* unit) const;
bool IsInRaidWith(Unit const* unit) const;
bool IsContestedGuard() const bool IsContestedGuard() const
{ {
if(FactionTemplateEntry const* entry = getFactionTemplateEntry()) if(FactionTemplateEntry const* entry = getFactionTemplateEntry())
@@ -1055,7 +1059,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
return this; return this;
} }
Player* GetCharmerOrOwnerPlayerOrPlayerItself(); Player* GetCharmerOrOwnerPlayerOrPlayerItself() const;
void SetPet(Pet* pet); void SetPet(Pet* pet);
void SetCharm(Unit* pet); void SetCharm(Unit* pet);
@@ -1348,8 +1352,11 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
uint32 GetUnitMovementFlags() const { return m_unit_movement_flags; } uint32 GetUnitMovementFlags() const { return m_unit_movement_flags; }
void SetUnitMovementFlags(uint32 f) { m_unit_movement_flags = f; } void SetUnitMovementFlags(uint32 f) { m_unit_movement_flags = f; }
void SetFeared(bool apply, uint64 casterGUID = 0, uint32 spellID = 0); void SetControlled(bool apply, UnitState state);
void SetConfused(bool apply, uint64 casterGUID = 0, uint32 spellID = 0); 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 AddComboPointHolder(uint32 lowguid) { m_ComboPointHolders.insert(lowguid); }
void RemoveComboPointHolder(uint32 lowguid) { m_ComboPointHolders.erase(lowguid); } void RemoveComboPointHolder(uint32 lowguid) { m_ComboPointHolders.erase(lowguid); }
+108 -298
View File
@@ -10,333 +10,143 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * 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. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * 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 "Database/DatabaseEnv.h"
#include "GridDefines.h" #include "GridDefines.h"
#include "Policies/SingletonImp.h"
#include "WaypointManager.h" #include "WaypointManager.h"
#include "ProgressBar.h" #include "ProgressBar.h"
#include "MapManager.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) waypoint_map.clear();
return false;
for(int i = 0; i < MAX_WAYPOINT_TEXT; ++i)
if(textid[i])
return false;
return true;
} }
WaypointBehavior::WaypointBehavior(const WaypointBehavior &b) void WaypointStore::Load()
{ {
emote = b.emote; QueryResult *result = WorldDatabase.PQuery("SELECT MAX(`id`) FROM `waypoint_data");
spell = b.spell; if(!result)
model1 = b.model1;
model2 = b.model2;
for(int i=0; i < MAX_WAYPOINT_TEXT; ++i)
textid[i] = b.textid[i];
}
void WaypointManager::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)
{ {
total_paths = result->GetRowCount(); sLog.outError(" an error occured while loading the table `waypoint_data` ( maybe it doesn't exist ?)\n");
barGoLink bar( total_paths ); exit(1); // Stop server at loading non exited table or not accessable table
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;
} }
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"); records = (*result)[0].GetUInt32();
if(result) delete 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)
{ {
barGoLink bar( result->GetRowCount() ); sLog.outErrorDb("The table `creature_addon` is empty or corrupted");
do return;
{
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);
}
/// - 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 )
{
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;
}
}
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);
if(!text)
{
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); WaypointPath* path_data;
if(itr != m_pathMap.end() && point <= itr->second.size()) uint32 total_records = result->GetRowCount();
{
WaypointNode &node = itr->second[point-1];
if(!node.behavior) node.behavior = new WaypointBehavior();
// if(field == "text1") node.behavior->text[0] = text ? text : ""; barGoLink bar( total_records);
// if(field == "text2") node.behavior->text[1] = text ? text : ""; Field *fields;
// if(field == "text3") node.behavior->text[2] = text ? text : ""; uint32 last_id = 0;
// if(field == "text4") node.behavior->text[3] = text ? text : "";
// if(field == "text5") node.behavior->text[4] = text ? text : ""; do
if(field == "emote") node.behavior->emote = text ? atoi(text) : 0; {
if(field == "spell") node.behavior->spell = text ? atoi(text) : 0; fields = result->Fetch();
if(field == "model1") node.behavior->model1 = text ? atoi(text) : 0; uint32 id = fields[0].GetUInt32();
if(field == "model2") node.behavior->model2 = text ? atoi(text) : 0; 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) fields = result->Fetch();
{ uint32 id = fields[0].GetUInt32();
if (!pmItr->second[i].behavior)
continue; WaypointData *wp = new WaypointData;
// Now we check text existence and put all zero texts ids to the end of array float x,y,z;
x = fields[2].GetFloat();
y = fields[3].GetFloat();
z = fields[4].GetFloat();
// Counting leading zeros for futher textid shift Trinity::NormalizeMapCoord(x);
int zeroCount = 0; Trinity::NormalizeMapCoord(y);
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 wp->id = fields[1].GetUInt32();
if (zeroCount) wp->x = x;
{ wp->y = y;
// Correct textid but some zeros leading, so move it forward. wp->z = z;
pmItr->second[i].behavior->textid[j-zeroCount] = pmItr->second[i].behavior->textid[j]; wp->run = fields[5].GetBool();
pmItr->second[i].behavior->textid[j] = 0; 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;
} }
+25 -57
View File
@@ -22,72 +22,40 @@
#define TRINITY_WAYPOINTMANAGER_H #define TRINITY_WAYPOINTMANAGER_H
#include <vector> #include <vector>
#include <string>
#include "Utilities/UnorderedMap.h"
#define MAX_WAYPOINT_TEXT 5 struct WaypointData
struct WaypointBehavior
{ {
uint32 emote; uint32 id;
uint32 spell; float x,y,z;
int32 textid[MAX_WAYPOINT_TEXT]; bool run;
uint32 model1;
uint32 model2;
bool isEmpty();
WaypointBehavior() {}
WaypointBehavior(const WaypointBehavior &b);
};
struct WaypointNode
{
float x;
float y;
float z;
float orientation;
uint32 delay; uint32 delay;
WaypointBehavior * behavior; uint32 event_id;
WaypointNode() {} uint8 event_chance;
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) {}
}; };
typedef std::vector<WaypointNode> WaypointPath; typedef std::vector<WaypointData*> WaypointPath;
extern UNORDERED_MAP<uint32, WaypointPath*> waypoint_map;
class WaypointManager class WaypointStore
{ {
public: private :
WaypointManager() {} uint32 records;
~WaypointManager() { Unload(); }
public:
void Load(); void UpdatePath(uint32 id);
void Unload(); void Load();
void Free();
void Cleanup();
WaypointPath* GetPath(uint32 id)
WaypointPath *GetPath(uint32 id)
{ {
WaypointPathMap::iterator itr = m_pathMap.find(id); if(waypoint_map.find(id) != waypoint_map.end())
return itr != m_pathMap.end() ? &itr->second : NULL; return waypoint_map[id];
} else return 0;
}
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); inline uint32 GetRecordsCount() { return records; }
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;
}; };
#define WaypointMgr Trinity::Singleton<WaypointManager>::Instance() extern WaypointStore WaypointMgr;
#endif #endif
+172 -179
View File
@@ -1,8 +1,6 @@
/* /*
* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> * 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 * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
@@ -10,210 +8,205 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * 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. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * 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
*/ */
/* //Basic header
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';
*/
#include <ctime> #include <ctime>
#include "WaypointMovementGenerator.h" #include "WaypointMovementGenerator.h"
#include "ObjectMgr.h"
#include "Creature.h"
#include "DestinationHolderImp.h" #include "DestinationHolderImp.h"
//Accessors
#include "Database/DatabaseEnv.h"
#include "ObjectMgr.h"
#include "World.h"
//Creature-specific headers
#include "Creature.h"
#include "CreatureAI.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 void
WaypointMovementGenerator<Creature>::LoadPath(Creature &c) WaypointMovementGenerator<T>::Initialize(T &u){}
template<>
void
WaypointMovementGenerator<Creature>::Initialize(Creature &u)
{ {
sLog.outDetail("LoadPath: loading waypoint path for creature %d,%d", c.GetGUIDLow(), c.GetDBTableGUIDLow()); i_currentNode = -1;
u.StopMoving();
i_path = WaypointMgr.GetPath(c.GetDBTableGUIDLow()); if(!path_id)
if(!i_path) path_id = u.GetWaypointPath();
{ waypoints = WaypointMgr.GetPath(path_id);
sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %d) doesn't have waypoint path",
c.GetName(), c.GetEntry(), c.GetDBTableGUIDLow());
return;
}
uint32 node_count = i_path->size();
i_hasDone.resize(node_count);
for(uint32 i = 0; i < node_count-1; i++)
i_hasDone[i] = false;
// 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 void
WaypointMovementGenerator<Creature>::ClearWaypoints() WaypointMovementGenerator<Creature>::Finalize(Creature &u){}
template<>
void
WaypointMovementGenerator<Player>::Finalize(Player &u){}
template<class T>
void
WaypointMovementGenerator<T>::MovementInform(T &unit){}
template<>
void WaypointMovementGenerator<Creature>::MovementInform(Creature &unit)
{ {
i_path = NULL; unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
} }
void template<>
WaypointMovementGenerator<Creature>::Initialize() bool WaypointMovementGenerator<Creature>::GetDestination(float &x, float &y, float &z) const
{ {
} if(i_destinationHolder.HasArrived())
return false;
bool
WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff) i_destinationHolder.GetDestination(x, y, z);
{
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;
// prevent a crash at empty waypoint path.
if(!i_path || i_path->empty())
return true;
// 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;
CreatureTraveller traveller(creature);
i_nextMoveTime.Update(diff);
i_destinationHolder.UpdateTraveller(traveller, diff, false, true);
// 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
}
if( creature.IsStopped())
{
uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1;
if (!i_hasDone[idx])
{
if (i_path->at(idx).orientation !=100)
creature.SetOrientation(i_path->at(idx).orientation);
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;
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()
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);
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;
}
}
return true; return true;
} }
void WaypointMovementGenerator<Creature>::MovementInform(Creature &unit) template<>
bool WaypointMovementGenerator<Player>::GetDestination(float &x, float &y, float &z) const
{ {
if(unit.AI()) return false;
unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
} }
template<>
void WaypointMovementGenerator<Creature>::Reset(Creature &unit){}
template<>
void WaypointMovementGenerator<Player>::Reset(Player &unit){}
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);
}
template<>
void WaypointMovementGenerator<Player>::InitTraveller(Player &unit, const WaypointData &node){}
template<class T>
bool
WaypointMovementGenerator<T>::Update(T &unit, const uint32 &diff)
{
return false;
}
template<>
bool
WaypointMovementGenerator<Creature>::Update(Creature &unit, const uint32 &diff)
{
if(!&unit)
return true;
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;
// Clear the generator if the path doesn't exist
if(!waypoints || !waypoints->size())
return false;
Traveller<Creature> traveller(unit);
i_nextMoveTime.Update(diff);
i_destinationHolder.UpdateTraveller(traveller, diff, false, true);
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);
}
}
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;
}
template void WaypointMovementGenerator<Player>::Initialize(Player &);
template bool WaypointMovementGenerator<Player>::Update(Player &, const uint32 &);
template void WaypointMovementGenerator<Player>::MovementInform(Player &);
//----------------------------------------------------// //----------------------------------------------------//
void void
FlightPathMovementGenerator::LoadPath(Player &) FlightPathMovementGenerator::LoadPath(Player &)
+24 -46
View File
@@ -50,64 +50,41 @@ class TRINITY_DLL_SPEC PathMovementBase
inline bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); } inline bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); }
// template pattern, not defined .. override required
void LoadPath(T &); void LoadPath(T &);
void ReloadPath(T &); void ReloadPath(T &);
uint32 GetCurrentNode() const { return i_currentNode; } uint32 GetCurrentNode() const { return i_currentNode; }
protected: protected:
uint32 i_currentNode; uint32 i_currentNode;
DestinationHolder< Traveller<T> > i_destinationHolder; DestinationHolder< Traveller<T> > i_destinationHolder;
P i_path; 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> template<class T>
class TRINITY_DLL_SPEC WaypointMovementGenerator;
template<> class TRINITY_DLL_SPEC WaypointMovementGenerator
class TRINITY_DLL_SPEC WaypointMovementGenerator<Creature> : public MovementGeneratorMedium< T, WaypointMovementGenerator<T> >, public PathMovementBase<T>
: public MovementGeneratorMedium< Creature, WaypointMovementGenerator<Creature> >,
public PathMovementBase<Creature, WaypointPath*>
{ {
TimeTrackerSmall i_nextMoveTime; public:
std::vector<bool> i_hasDone; WaypointMovementGenerator(uint32 _path_id = 0, bool _repeating = true) :
public: i_nextMoveTime(0), path_id(_path_id), repeating(_repeating), StopedByPlayer(false){}
WaypointMovementGenerator(Creature &) : i_nextMoveTime(0) {}
~WaypointMovementGenerator() { ClearWaypoints(); } void Initialize(T &);
void Initialize(Creature &u) void Finalize(T &);
{ void MovementInform(T &);
i_nextMoveTime.Reset(0); // TODO: check the lower bound (0 is probably too small) void InitTraveller(T &, const WaypointData &);
u.StopMoving(); void GeneratePathId(T &);
LoadPath(u); void Reset(T &unit);
} bool Update(T &, const uint32 &);
void Finalize(Creature &) {} bool GetDestination(float &x, float &y, float &z) const;
void Reset(Creature &u) { ReloadPath(u); } MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; }
bool Update(Creature &u, const uint32 &diff);
void MovementInform(Creature &); private:
WaypointData node;
MovementGeneratorType GetMovementGeneratorType() { return WAYPOINT_MOTION_TYPE; } uint32 i_currentNode, path_id;
TimeTrackerSmall i_nextMoveTime;
// now path movement implmementation WaypointPath *waypoints;
void LoadPath(Creature &c); bool repeating, custom_path, ExecuteScript, StopedByPlayer;
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;
}; };
/** FlightPathMovementGenerator generates movement of the player for the paths /** 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()); } inline bool HasArrived() const { return (i_currentNode >= i_path.Size()); }
void SetCurrentNodeAfterTeleport(); void SetCurrentNodeAfterTeleport();
void SkipCurrentNode() { ++i_currentNode; } 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 #endif
+26 -2
View File
@@ -1271,6 +1271,7 @@ void World::SetInitialWorldSettings()
objmgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data) objmgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadGameObjectScripts(); // 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.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data)
objmgr.LoadWaypointScripts();
sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls
objmgr.LoadDbScriptStrings(); objmgr.LoadDbScriptStrings();
@@ -1313,7 +1314,6 @@ void World::SetInitialWorldSettings()
///- Initilize static helper structures ///- Initilize static helper structures
AIRegistry::Initialize(); AIRegistry::Initialize();
WaypointMovementGenerator<Creature>::Initialize();
Player::InitVisibleBits(); Player::InitVisibleBits();
///- Initialize MapManager ///- Initialize MapManager
@@ -2203,8 +2203,32 @@ void World::ScriptsProcess()
break; 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); sLog.outError("Unknown script command %u called.",step.script->command);
break; break;
} }
+1
View File
@@ -326,6 +326,7 @@ enum RealmZone
#define SCRIPT_COMMAND_ACTIVATE_OBJECT 13 // source = unit, target=GO #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_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_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 /// Storage class for commands issued for delayed execution
struct CliCommandHolder struct CliCommandHolder
+2 -2
View File
@@ -29,9 +29,9 @@ extern DatabaseMysql WorldDatabase;
const char CreatureInfosrcfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiis"; const char CreatureInfosrcfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiis";
const char CreatureInfodstfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiii"; const char CreatureInfodstfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiii";
const char CreatureDataAddonInfofmt[]="iiiiiiis"; const char CreatureDataAddonInfofmt[]="iiiiiiiis";
const char CreatureModelfmt[]="iffbi"; const char CreatureModelfmt[]="iffbi";
const char CreatureInfoAddonInfofmt[]="iiiiiiis"; const char CreatureInfoAddonInfofmt[]="iiiiiiiis";
const char EquipmentInfofmt[]="iiiiiiiiii"; const char EquipmentInfofmt[]="iiiiiiiiii";
const char GameObjectInfosrcfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis"; const char GameObjectInfosrcfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis";
const char GameObjectInfodstfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiii"; const char GameObjectInfodstfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiii";