[svn] Rewrite canSeeOrDetect function.

Minor change on trigger creatures.
Remove some unused hacks in scripts.

--HG--
branch : trunk
This commit is contained in:
megamage
2008-11-06 10:27:58 -06:00
parent 5746d0e98d
commit 43910434c5
19 changed files with 592 additions and 857 deletions
-2
View File
@@ -1,5 +1,3 @@
update creature_template set spell1 = 40836, flags_extra = 128, scriptname = '' where entry = 23336;
DROP TABLE IF EXISTS `spell_linked_spell`; DROP TABLE IF EXISTS `spell_linked_spell`;
CREATE TABLE `spell_linked_spell` ( CREATE TABLE `spell_linked_spell` (
`spell_trigger` int(10) NOT NULL, `spell_trigger` int(10) NOT NULL,
+10 -2
View File
@@ -1,7 +1,15 @@
DELETE FROM spell_linked_spell WHERE `spell_trigger` IN (39992, 39835, 42052, -41914, 41126); DELETE FROM spell_linked_spell WHERE `spell_trigger` IN (39992, 39835, 42052, -41914, 41126, 41376);
-- INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (39992, 39835, 1, 'Needle Spine'); -- INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (39992, 39835, 1, 'Needle Spine');
INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (39835, 39968, 1, 'Needle Spine'); INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (39835, 39968, 1, 'Needle Spine');
INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (-41376, 41377, 0, 'Spite');
INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (-41914, 41915, 0, 'Summon Parasitic Shadowfiend'); INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (-41914, 41915, 0, 'Summon Parasitic Shadowfiend');
INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (41126, 41131, 1, 'Flame Crash'); INSERT INTO spell_linked_spell (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES (41126, 41131, 1, 'Flame Crash');
UPDATE creature_template SET flags_extra = 128, speed = 1.0 WHERE entry = 23095; -- molten_flame
UPDATE creature_template SET flags_extra = 128, speed = 1.0 WHERE entry = 23095;
-- volcano
UPDATE creature_template SET spell1 = 40117, flags_extra = 128, scriptname = '' WHERE entry = 23085;
-- flame crash
update creature_template set spell1 = 40836, flags_extra = 128, scriptname = '' where entry = 23336;
-- blaze
update creature_template set spell1 = 40610, flags_extra = 128, scriptname = '' where entry = 23259;
@@ -1,18 +1,18 @@
/* Copyright (C) 2006 - 2008 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> /* Copyright (C) 2006 - 2008 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* 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
* (at your option) any later version. * (at your option) any later version.
* *
* 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
*/ */
/* ScriptData /* ScriptData
SDName: boss_illidan_stormrage SDName: boss_illidan_stormrage
@@ -382,8 +382,6 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
uint64 FlameGUID[2]; uint64 FlameGUID[2];
uint64 GlaiveGUID[2]; uint64 GlaiveGUID[2];
std::list<uint64> ParasiteTargets; // for safety, do not use Unit*
void Reset(); void Reset();
void JustSummoned(Creature* summon) void JustSummoned(Creature* summon)
@@ -433,6 +431,7 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
void Aggro(Unit *who) void Aggro(Unit *who)
{ {
m_creature->setActive(true);
DoZoneInCombat(); DoZoneInCombat();
} }
@@ -503,19 +502,6 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
} }
} }
void AddParasiteTarget(uint64 targetGUID)
{
for(std::list<uint64>::iterator tIter = ParasiteTargets.begin(); tIter != ParasiteTargets.end(); tIter++)
{
if(*tIter == targetGUID)
return;
}
ParasiteTargets.push_back(targetGUID);
if(Phase == PHASE_NORMAL || Phase == PHASE_NORMAL_2 || Phase == PHASE_NORMAL_MAIEV)
Timer[EVENT_PARASITE_CHECK] += 1000;
}
void DeleteFromThreatList(uint64 TargetGUID) void DeleteFromThreatList(uint64 TargetGUID)
{ {
for(std::list<HostilReference*>::iterator itr = m_creature->getThreatManager().getThreatList().begin(); itr != m_creature->getThreatManager().getThreatList().end(); ++itr) for(std::list<HostilReference*>::iterator itr = m_creature->getThreatManager().getThreatList().begin(); itr != m_creature->getThreatManager().getThreatList().end(); ++itr)
@@ -562,19 +548,14 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
{ {
case 1://lift off case 1://lift off
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
//m_creature->GetMotionMaster()->Clear(false);
m_creature->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT); m_creature->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT);
//m_creature->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ());
m_creature->StopMoving(); m_creature->StopMoving();
DoYell(SAY_TAKEOFF, LANG_UNIVERSAL, NULL); DoYell(SAY_TAKEOFF, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_TAKEOFF); DoPlaySoundToSet(m_creature, SOUND_TAKEOFF);
Timer[EVENT_FLIGHT_SEQUENCE] = 3000; Timer[EVENT_FLIGHT_SEQUENCE] = 3000;
break; break;
case 2://move to center case 2://move to center
//m_creature->GetMotionMaster()->Clear(false);
//m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
m_creature->GetMotionMaster()->MovePoint(0, CENTER_X + 5, CENTER_Y, CENTER_Z); //+5, for SPELL_THROW_GLAIVE bug m_creature->GetMotionMaster()->MovePoint(0, CENTER_X + 5, CENTER_Y, CENTER_Z); //+5, for SPELL_THROW_GLAIVE bug
//m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
Timer[EVENT_FLIGHT_SEQUENCE] = 0; Timer[EVENT_FLIGHT_SEQUENCE] = 0;
break; break;
case 3://throw one glaive case 3://throw one glaive
@@ -614,15 +595,11 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
Timer[EVENT_FLIGHT_SEQUENCE] = 3000; Timer[EVENT_FLIGHT_SEQUENCE] = 3000;
break; break;
case 6://fly to hover point case 6://fly to hover point
//m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
m_creature->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z); m_creature->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z);
//m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
Timer[EVENT_FLIGHT_SEQUENCE] = 0; Timer[EVENT_FLIGHT_SEQUENCE] = 0;
break; break;
case 7://return to center case 7://return to center
//m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
m_creature->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z); m_creature->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z);
//m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
Timer[EVENT_FLIGHT_SEQUENCE] = 0; Timer[EVENT_FLIGHT_SEQUENCE] = 0;
break; break;
case 8://glaive return case 8://glaive return
@@ -641,9 +618,7 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
Timer[EVENT_FLIGHT_SEQUENCE] = 2000; Timer[EVENT_FLIGHT_SEQUENCE] = 2000;
break; break;
case 9://land case 9://land
//m_creature->GetMotionMaster()->Clear(false);
m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT); m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT);
//m_creature->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ());
m_creature->StopMoving(); m_creature->StopMoving();
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
for(uint8 i = 0; i < 2; i++) for(uint8 i = 0; i < 2; i++)
@@ -663,7 +638,6 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
case 10://attack case 10://attack
DoResetThreat(); DoResetThreat();
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
//m_creature->GetMotionMaster()->Clear();
m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE );
EnterPhase(PHASE_NORMAL_2); EnterPhase(PHASE_NORMAL_2);
break; break;
@@ -723,11 +697,12 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
void UpdateAI(const uint32 diff) void UpdateAI(const uint32 diff)
{ {
if((!m_creature->SelectHostilTarget() || !m_creature->getVictim()) && Phase < PHASE_TALK_SEQUENCE) if((!m_creature->SelectHostilTarget() && !m_creature->getVictim()) && Phase < PHASE_TALK_SEQUENCE)
return; return;
Event = EVENT_NULL; Event = EVENT_NULL;
for(uint32 i = 1; i <= MaxTimer[Phase]; i++) for(uint32 i = 1; i <= MaxTimer[Phase]; i++)
{
if(Timer[i]) if(Timer[i])
if(Timer[i] <= diff) if(Timer[i] <= diff)
{ {
@@ -735,224 +710,188 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI
Event = (EventIllidan)i; Event = (EventIllidan)i;
} }
else Timer[i] -= diff; else Timer[i] -= diff;
}
switch(Phase) switch(Phase)
{
case PHASE_NORMAL:
if(HPPCT(m_creature) < 65)
EnterPhase(PHASE_FLIGHT_SEQUENCE);
break;
case PHASE_NORMAL_2:
if(m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 30)
EnterPhase(PHASE_TALK_SEQUENCE);
break;
case PHASE_NORMAL_MAIEV:
if(m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 1)
EnterPhase(PHASE_TALK_SEQUENCE);
break;
case PHASE_TALK_SEQUENCE:
if(Event == EVENT_TALK_SEQUENCE)
HandleTalkSequence();
break;
case PHASE_FLIGHT_SEQUENCE:
if(Event == EVENT_FLIGHT_SEQUENCE)
HandleFlightSequence();
break;
case PHASE_TRANSFORM_SEQUENCE:
if(Event == EVENT_TRANSFORM_SEQUENCE)
HandleTransformSequence();
break;
}
if(m_creature->IsNonMeleeSpellCasted(false))
return;
if(Phase == PHASE_NORMAL || Phase == PHASE_NORMAL_2 || Phase == PHASE_NORMAL_MAIEV && !m_creature->HasAura(SPELL_CAGED, 0))
{
switch(Event)
{
//PHASE_NORMAL
case EVENT_BERSERK:
DoYell(SAY_ENRAGE, LANG_UNIVERSAL, NULL);
DoPlaySoundToSet(m_creature, SOUND_ENRAGE);
DoCast(m_creature, SPELL_BERSERK, true);
Timer[EVENT_BERSERK] = 5000;//The buff actually lasts forever.
break;
case EVENT_TAUNT:
{ {
case PHASE_NORMAL: uint32 random = rand()%4;
if(HPPCT(m_creature) < 65) char* yell = RandomTaunts[random].text;
EnterPhase(PHASE_FLIGHT_SEQUENCE); uint32 soundid = RandomTaunts[random].sound;
break; if(yell)
DoYell(yell, LANG_UNIVERSAL, NULL);
case PHASE_NORMAL_2: if(soundid)
if(m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 30) DoPlaySoundToSet(m_creature, soundid);
EnterPhase(PHASE_TALK_SEQUENCE);
break;
case PHASE_NORMAL_MAIEV:
if(m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 1)
EnterPhase(PHASE_TALK_SEQUENCE);
break;
case PHASE_TALK_SEQUENCE:
if(Event == EVENT_TALK_SEQUENCE)
HandleTalkSequence();
break;
case PHASE_FLIGHT_SEQUENCE:
if(Event == EVENT_FLIGHT_SEQUENCE)
HandleFlightSequence();
break;
case PHASE_TRANSFORM_SEQUENCE:
if(Event == EVENT_TRANSFORM_SEQUENCE)
HandleTransformSequence();
break;
} }
Timer[EVENT_TAUNT] = 32000;
break;
if(m_creature->IsNonMeleeSpellCasted(false)) case EVENT_SHEAR:
return; DoCast(m_creature->getVictim(), SPELL_SHEAR);
Timer[EVENT_SHEAR] = 25000 + (rand()%16 * 1000);
break;
if(Phase == PHASE_NORMAL || Phase == PHASE_NORMAL_2 || Phase == PHASE_NORMAL_MAIEV && !m_creature->HasAura(SPELL_CAGED, 0)) case EVENT_FLAME_CRASH:
DoCast(m_creature->getVictim(), SPELL_FLAME_CRASH);
Timer[EVENT_FLAME_CRASH] = 35000;
break;
case EVENT_PARASITIC_SHADOWFIEND:
{ {
switch(Event) Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1, 200, true);
{ if(!target) target = m_creature->getVictim();
//PHASE_NORMAL if(target)
case EVENT_BERSERK: m_creature->CastSpell(target, SPELL_PARASITIC_SHADOWFIEND, true);
DoYell(SAY_ENRAGE, LANG_UNIVERSAL, NULL); }break;
DoPlaySoundToSet(m_creature, SOUND_ENRAGE);
DoCast(m_creature, SPELL_BERSERK, true);
Timer[EVENT_BERSERK] = 5000;//The buff actually lasts forever.
break;
case EVENT_TAUNT: case EVENT_PARASITE_CHECK:
{ Timer[EVENT_PARASITE_CHECK] = 0;
uint32 random = rand()%4; break;
char* yell = RandomTaunts[random].text;
uint32 soundid = RandomTaunts[random].sound;
if(yell)
DoYell(yell, LANG_UNIVERSAL, NULL);
if(soundid)
DoPlaySoundToSet(m_creature, soundid);
}
Timer[EVENT_TAUNT] = 32000;
break;
case EVENT_SHEAR: case EVENT_DRAW_SOUL:
DoCast(m_creature->getVictim(), SPELL_SHEAR); DoCast(m_creature->getVictim(), SPELL_DRAW_SOUL);
Timer[EVENT_SHEAR] = 25000 + (rand()%16 * 1000); Timer[EVENT_DRAW_SOUL] = 55000;
break; break;
case EVENT_FLAME_CRASH: //PHASE_NORMAL_2
DoCast(m_creature->getVictim(), SPELL_FLAME_CRASH); case EVENT_AGONIZING_FLAMES:
Timer[EVENT_FLAME_CRASH] = 35000; DoCast(SelectUnit(SELECT_TARGET_RANDOM,0), SPELL_AGONIZING_FLAMES);
break; Timer[EVENT_AGONIZING_FLAMES] = 0;
break;
case EVENT_PARASITIC_SHADOWFIEND: case EVENT_TRANSFORM_NORMAL:
{ EnterPhase(PHASE_TRANSFORM_SEQUENCE);
Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); break;
if(!target) target = m_creature->getVictim();
if(target->GetTypeId() == TYPEID_PLAYER && !target->HasAura(SPELL_PARASITIC_SHADOWFIEND, 0))
{
target->CastSpell(target, SPELL_PARASITIC_SHADOWFIEND, true); // do not miss
ParasiteTargets.push_back(target->GetGUID());
Timer[EVENT_PARASITE_CHECK] += 1000; // do not check immediately
}
Timer[EVENT_PARASITIC_SHADOWFIEND] = 40000;
}
break;
case EVENT_PARASITE_CHECK: //PHASE_NORMAL_MAIEV
for(std::list<uint64>::iterator tIter = ParasiteTargets.begin(); tIter != ParasiteTargets.end();) case EVENT_ENRAGE:
{ DoCast(m_creature, SPELL_ENRAGE);
Unit* target = Unit::GetUnit((*m_creature), *tIter); Timer[EVENT_ENRAGE] = 0;
if(!target || !target->HasAura(SPELL_PARASITIC_SHADOWFIEND, 0)) break;
{
if(target && target->isAlive())
target->CastSpell(target, SPELL_SUMMON_PARASITICS, true);
std::list<uint64>::iterator tIter2 = tIter;
++tIter;
ParasiteTargets.erase(tIter2);
}
else
++tIter;
}
if(ParasiteTargets.empty())
Timer[EVENT_PARASITE_CHECK] = 0;
else
Timer[EVENT_PARASITE_CHECK] = 1000;
break;
case EVENT_DRAW_SOUL: default:
DoCast(m_creature->getVictim(), SPELL_DRAW_SOUL); break;
Timer[EVENT_DRAW_SOUL] = 55000; }
break; DoMeleeAttackIfReady();
}
//PHASE_NORMAL_2 if(Phase == PHASE_FLIGHT)
case EVENT_AGONIZING_FLAMES: {
DoCast(SelectUnit(SELECT_TARGET_RANDOM,0), SPELL_AGONIZING_FLAMES); switch(Event)
Timer[EVENT_AGONIZING_FLAMES] = 0; {
break; case EVENT_FIREBALL:
DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL);
Timer[EVENT_FIREBALL] = 3000;
break;
case EVENT_TRANSFORM_NORMAL: case EVENT_DARK_BARRAGE:
EnterPhase(PHASE_TRANSFORM_SEQUENCE); DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE);
break; Timer[EVENT_DARK_BARRAGE] = 0;
break;
//PHASE_NORMAL_MAIEV case EVENT_EYE_BLAST:
case EVENT_ENRAGE: CastEyeBlast();
DoCast(m_creature, SPELL_ENRAGE); Timer[EVENT_EYE_BLAST] = 0;
Timer[EVENT_ENRAGE] = 0; break;
break;
default: case EVENT_MOVE_POINT:
break; Phase = PHASE_FLIGHT_SEQUENCE;
} Timer[EVENT_FLIGHT_SEQUENCE] = 0;//do not start Event when changing hover point
DoMeleeAttackIfReady(); for (uint8 i = 0; i <= rand()%3; i++)
}
if(Phase == PHASE_FLIGHT)
{ {
switch(Event) HoverPoint++;
{ if(HoverPoint > 3)
case EVENT_FIREBALL: HoverPoint = 0;
DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL);
Timer[EVENT_FIREBALL] = 3000;
break;
case EVENT_DARK_BARRAGE:
DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE);
Timer[EVENT_DARK_BARRAGE] = 0;
break;
case EVENT_EYE_BLAST:
CastEyeBlast();
Timer[EVENT_EYE_BLAST] = 0;
break;
case EVENT_MOVE_POINT:
Phase = PHASE_FLIGHT_SEQUENCE;
Timer[EVENT_FLIGHT_SEQUENCE] = 0;//do not start Event when changing hover point
for (uint8 i = 0; i <= rand()%3; i++)
{
HoverPoint++;
if(HoverPoint > 3)
HoverPoint = 0;
}
m_creature->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
m_creature->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z);
m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
break;
default:
break;
}
} }
m_creature->GetMotionMaster()->MovePoint(0, HoverPosition[HoverPoint].x, HoverPosition[HoverPoint].y, HoverPosition[HoverPoint].z);
break;
if(Phase == PHASE_DEMON) default:
{ break;
switch(Event) }
{ }
case EVENT_SHADOW_BLAST:
m_creature->GetMotionMaster()->Clear(false); if(Phase == PHASE_DEMON)
if(!m_creature->IsWithinDistInMap(m_creature->getVictim(), 50)||!m_creature->IsWithinLOSInMap(m_creature->getVictim())) {
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), 30); switch(Event)
else {
m_creature->GetMotionMaster()->MoveIdle(); case EVENT_SHADOW_BLAST:
DoCast(m_creature->getVictim(), SPELL_SHADOW_BLAST); m_creature->GetMotionMaster()->Clear(false);
Timer[EVENT_SHADOW_BLAST] = 4000; if(!m_creature->IsWithinDistInMap(m_creature->getVictim(), 50)||!m_creature->IsWithinLOSInMap(m_creature->getVictim()))
break; m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), 30);
case EVENT_SHADOWDEMON: else
DoCast(m_creature, SPELL_SUMMON_SHADOWDEMON); m_creature->GetMotionMaster()->MoveIdle();
Timer[EVENT_SHADOWDEMON] = 0; DoCast(m_creature->getVictim(), SPELL_SHADOW_BLAST);
Timer[EVENT_FLAME_BURST] += 10000; Timer[EVENT_SHADOW_BLAST] = 4000;
break; break;
case EVENT_FLAME_BURST: case EVENT_SHADOWDEMON:
DoCast(m_creature, SPELL_FLAME_BURST); DoCast(m_creature, SPELL_SUMMON_SHADOWDEMON);
Timer[EVENT_FLAME_BURST] = 15000; Timer[EVENT_SHADOWDEMON] = 0;
break; Timer[EVENT_FLAME_BURST] += 10000;
case EVENT_TRANSFORM_DEMON: break;
EnterPhase(PHASE_TRANSFORM_SEQUENCE); case EVENT_FLAME_BURST:
break; DoCast(m_creature, SPELL_FLAME_BURST);
default: Timer[EVENT_FLAME_BURST] = 15000;
break; break;
} case EVENT_TRANSFORM_DEMON:
} EnterPhase(PHASE_TRANSFORM_SEQUENCE);
break;
default:
break;
}
}
} }
}; };
/********************************** End of Illidan AI ******************************************/ /********************************** End of Illidan AI ******************************************/
//This is used to sort the players by distance in preparation for being charged by the flames.
struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit, bool>
{
const Unit* MainTarget;
TargetDistanceOrder(const Unit* Target) : MainTarget(Target) {};
// functor for operator ">"
bool operator()(const Unit* _Left, const Unit* _Right) const
{
return (MainTarget->GetDistance(_Left) > MainTarget->GetDistance(_Right));
}
};
struct TRINITY_DLL_DECL flame_of_azzinothAI : public ScriptedAI struct TRINITY_DLL_DECL flame_of_azzinothAI : public ScriptedAI
{ {
flame_of_azzinothAI(Creature *c) : ScriptedAI(c) {Reset();} flame_of_azzinothAI(Creature *c) : ScriptedAI(c) {Reset();}
@@ -972,29 +911,7 @@ struct TRINITY_DLL_DECL flame_of_azzinothAI : public ScriptedAI
void ChargeCheck() void ChargeCheck()
{ {
// Get the Threat List Unit* target = SelectUnit(SELECT_TARGET_FARTHEST, 0, 200, false);
std::list<HostilReference *> m_threatlist = m_creature->getThreatManager().getThreatList();
if(!m_threatlist.size()) return; // He doesn't have anyone in his threatlist, useless to continue
std::list<Unit *> targets;
std::list<HostilReference *>::iterator itr = m_threatlist.begin();
for( ; itr!= m_threatlist.end(); ++itr) //store the threat list in a different container
{
Unit *target = Unit::GetUnit(*m_creature, (*itr)->getUnitGuid());
if(target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER && target->GetPositionZ()>350) //only on alive players
targets.push_back(target);
}
if (!targets.size())
return;
//Sort the list of players
targets.sort(TargetDistanceOrder(m_creature));
//Resize so we only get the furthest target
targets.resize(1);
Unit* target = (*targets.begin());
if(target && (!m_creature->IsWithinDistInMap(target, FLAME_CHARGE_DISTANCE))) if(target && (!m_creature->IsWithinDistInMap(target, FLAME_CHARGE_DISTANCE)))
{ {
m_creature->AttackStop(); m_creature->AttackStop();
@@ -1128,6 +1045,7 @@ struct TRINITY_DLL_DECL npc_akama_illidanAI : public ScriptedAI
m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has strange values.. m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Database sometimes has strange values..
m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
m_creature->setActive(false);
} }
// Do not call reset in Akama's evade mode, as this will stop him from summoning minions after he kills the first bit // Do not call reset in Akama's evade mode, as this will stop him from summoning minions after he kills the first bit
@@ -1184,6 +1102,8 @@ struct TRINITY_DLL_DECL npc_akama_illidanAI : public ScriptedAI
void BeginChannel() void BeginChannel()
{ {
m_creature->setActive(true);
float x, y, z; float x, y, z;
if(GETGO(Gate, GateGUID)) if(GETGO(Gate, GateGUID))
Gate->GetPosition(x, y, z); Gate->GetPosition(x, y, z);
@@ -1527,7 +1447,6 @@ struct TRINITY_DLL_DECL boss_maievAI : public ScriptedAI
} }
m_creature->InterruptNonMeleeSpells(false); m_creature->InterruptNonMeleeSpells(false);
m_creature->GetMotionMaster()->Clear(false); m_creature->GetMotionMaster()->Clear(false);
//m_creature->GetMotionMaster()->MoveIdle();
m_creature->AttackStop(); m_creature->AttackStop();
m_creature->SetUInt64Value(UNIT_FIELD_TARGET, IllidanGUID); m_creature->SetUInt64Value(UNIT_FIELD_TARGET, IllidanGUID);
MaxTimer = 0; MaxTimer = 0;
@@ -1557,7 +1476,6 @@ struct TRINITY_DLL_DECL boss_maievAI : public ScriptedAI
m_creature->AttackStop(); m_creature->AttackStop();
m_creature->InterruptNonMeleeSpells(false); m_creature->InterruptNonMeleeSpells(false);
m_creature->GetMotionMaster()->Clear(false); m_creature->GetMotionMaster()->Clear(false);
//m_creature->GetMotionMaster()->MoveIdle();
m_creature->Relocate(x, y, z); m_creature->Relocate(x, y, z);
m_creature->SendMonsterMove(x, y, z, 0, 0, 0); m_creature->SendMonsterMove(x, y, z, 0, 0, 0);
DoCast(m_creature, SPELL_TELEPORT_VISUAL, true); DoCast(m_creature, SPELL_TELEPORT_VISUAL, true);
@@ -1839,9 +1757,7 @@ struct TRINITY_DLL_DECL mob_parasitic_shadowfiendAI : public ScriptedAI
{ {
if(!m_creature->getVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND, 0)) if(!m_creature->getVictim()->HasAura(SPELL_PARASITIC_SHADOWFIEND, 0))
{ {
m_creature->getVictim()->CastSpell(m_creature->getVictim(), SPELL_PARASITIC_SHADOWFIEND, true); //do not stack m_creature->getVictim()->CastSpell(m_creature->getVictim(), SPELL_PARASITIC_SHADOWFIEND, true, 0, 0, IllidanGUID); //do not stack
if(GETCRE(Illidan, IllidanGUID))
((boss_illidan_stormrageAI*)Illidan->AI())->AddParasiteTarget(m_creature->getVictim()->GetGUID());
} }
m_creature->AttackerStateUpdate(m_creature->getVictim()); m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer(); m_creature->resetAttackTimer();
@@ -1936,67 +1852,6 @@ struct TRINITY_DLL_DECL demonfireAI : public ScriptedAI
} }
}; };
struct TRINITY_DLL_DECL blazeAI : public ScriptedAI
{
blazeAI(Creature *c) : ScriptedAI(c) {Reset();}
uint32 BlazeTimer;
uint32 DespawnTimer;
void Reset()
{
BlazeTimer = 3000;
DespawnTimer = 60000; // Spell duration = 1 min
//((TemporarySummon*)m_creature)->Summon(TEMPSUMMON_TIMED_DESPAWN, 0, false);
}
void Aggro(Unit *who) {}
void AttackStart(Unit* who) { }
void MoveInLineOfSight(Unit *who){ }
void UpdateAI(const uint32 diff)
{
if(BlazeTimer)
if(BlazeTimer <= diff)
{
DoCast(m_creature, SPELL_BLAZE_EFFECT);//duration 60s
BlazeTimer = 0;
}else BlazeTimer -= diff;
if(DespawnTimer < diff)
{
m_creature->SetVisibility(VISIBILITY_OFF);
m_creature->setDeathState(JUST_DIED);
}else DespawnTimer -= diff;
}
};
struct TRINITY_DLL_DECL flamecrashAI : public ScriptedAI
{
flamecrashAI(Creature *c) : ScriptedAI(c) {Reset();}
uint32 DespawnTimer;
void Reset()
{
DoCast(m_creature, SPELL_FLAME_CRASH_EFFECT);//duration inf
DespawnTimer = 120000; // summon spell duration
}
void Aggro(Unit *who) {}
void AttackStart(Unit *who) { }
void MoveInLineOfSight(Unit *who){ }
void UpdateAI(const uint32 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 struct TRINITY_DLL_DECL blade_of_azzinothAI : public ScriptedAI
{ {
blade_of_azzinothAI(Creature* c) : ScriptedAI(c) {} blade_of_azzinothAI(Creature* c) : ScriptedAI(c) {}
@@ -2070,8 +1925,6 @@ void boss_illidan_stormrageAI::Reset()
FlightCount = 0; FlightCount = 0;
TransformCount = 0; TransformCount = 0;
ParasiteTargets.clear();
m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 21135); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 21135);
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
@@ -2080,6 +1933,7 @@ void boss_illidan_stormrageAI::Reset()
m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT); m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT);
m_creature->CastSpell(m_creature, SPELL_DUAL_WIELD, true); m_creature->CastSpell(m_creature, SPELL_DUAL_WIELD, true);
m_creature->setActive(false);
} }
void boss_illidan_stormrageAI::HandleTalkSequence() void boss_illidan_stormrageAI::HandleTalkSequence()
@@ -2377,21 +2231,11 @@ CreatureAI* GetAI_shadow_demon(Creature *_Creature)
return new shadow_demonAI (_Creature); return new shadow_demonAI (_Creature);
} }
CreatureAI* GetAI_flamecrash(Creature *_Creature)
{
return new flamecrashAI (_Creature);
}
CreatureAI* GetAI_demonfire(Creature *_Creature) CreatureAI* GetAI_demonfire(Creature *_Creature)
{ {
return new demonfireAI (_Creature); return new demonfireAI (_Creature);
} }
CreatureAI* GetAI_blaze(Creature *_Creature)
{
return new blazeAI (_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);
@@ -2448,21 +2292,11 @@ void AddSC_boss_illidan()
newscript->GetAI = GetAI_shadow_demon; newscript->GetAI = GetAI_shadow_demon;
m_scripts[nrscripts++] = newscript; m_scripts[nrscripts++] = newscript;
newscript = new Script;
newscript->Name="mob_flame_crash";
newscript->GetAI = GetAI_flamecrash;
m_scripts[nrscripts++] = newscript;
newscript = new Script; newscript = new Script;
newscript->Name="mob_demon_fire"; newscript->Name="mob_demon_fire";
newscript->GetAI = GetAI_demonfire; newscript->GetAI = GetAI_demonfire;
m_scripts[nrscripts++] = newscript; m_scripts[nrscripts++] = newscript;
newscript = new Script;
newscript->Name="mob_blaze";
newscript->GetAI = GetAI_blaze;
m_scripts[nrscripts++] = newscript;
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;
@@ -634,45 +634,6 @@ struct TRINITY_DLL_DECL boss_essence_of_angerAI : public ScriptedAI
} }
} }
void SelectSpiteTarget(uint32 num, float max_range = 999)
{
if(!num) return;
CellPair p(Trinity::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
std::list<Unit *> tempUnitMap;
{
Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(m_creature, m_creature, max_range);
Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(tempUnitMap, u_check);
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, world_unit_searcher, *(m_creature->GetMap()));
cell_lock->Visit(cell_lock, grid_unit_searcher, *(m_creature->GetMap()));
}
std::list<Unit*>::iterator itr;
while(tempUnitMap.size() && SpiteTargetGUID.size() < num)
{
itr = tempUnitMap.begin();
advance(itr, rand()%tempUnitMap.size());
SpiteTargetGUID.push_back((*itr)->GetGUID());
tempUnitMap.erase(itr);
}
for(itr = tempUnitMap.begin(); itr != tempUnitMap.end(); ++itr)
(*itr)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_creature->CastSpell(m_creature, SPELL_SPITE_TARGET, true); // must true
for(itr = tempUnitMap.begin(); itr != tempUnitMap.end(); ++itr)
(*itr)->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
void UpdateAI(const uint32 diff) void UpdateAI(const uint32 diff)
{ {
//Return since we have no target //Return since we have no target
@@ -700,7 +661,7 @@ struct TRINITY_DLL_DECL boss_essence_of_angerAI : public ScriptedAI
if(SoulScreamTimer < diff) if(SoulScreamTimer < diff)
{ {
DoCast(m_creature->getVictim(), SPELL_SOUL_SCREAM); DoCast(m_creature->getVictim(), SPELL_SOUL_SCREAM);
SoulScreamTimer = 10000; SoulScreamTimer = 9000 + rand()%2000;
if(!(rand()%3)) if(!(rand()%3))
{ {
DoYell(ANGER_SAY_SCREAM,LANG_UNIVERSAL,NULL); DoYell(ANGER_SAY_SCREAM,LANG_UNIVERSAL,NULL);
@@ -710,26 +671,10 @@ struct TRINITY_DLL_DECL boss_essence_of_angerAI : public ScriptedAI
if(SpiteTimer < diff) if(SpiteTimer < diff)
{ {
if(!SpiteTargetGUID.empty()) DoCast(m_creature, SPELL_SPITE_TARGET);
{ SpiteTimer = 30000;
for (std::list<uint64>::iterator itr = SpiteTargetGUID.begin(); itr != SpiteTargetGUID.end(); ++itr) DoYell(ANGER_SAY_SPEC,LANG_UNIVERSAL,NULL);
{ DoPlaySoundToSet(m_creature, ANGER_SOUND_SPEC);
if(Unit* target = Unit::GetUnit(*m_creature, *itr))
{
target->RemoveAurasDueToSpell(SPELL_SPITE_TARGET);
m_creature->CastSpell(target, SPELL_SPITE_DAMAGE, true);
}
}
SpiteTargetGUID.clear();
SpiteTimer = 24000;
}
else
{
SelectSpiteTarget(3);
SpiteTimer = 6000;
DoYell(ANGER_SAY_SPEC,LANG_UNIVERSAL,NULL);
DoPlaySoundToSet(m_creature, ANGER_SOUND_SPEC);
}
}else SpiteTimer -= diff; }else SpiteTimer -= diff;
DoMeleeAttackIfReady(); DoMeleeAttackIfReady();
@@ -1,18 +1,18 @@
/* Copyright (C) 2006 - 2008 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> /* Copyright (C) 2006 - 2008 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
* 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
* (at your option) any later version. * (at your option) any later version.
* *
* 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
*/ */
/* ScriptData /* ScriptData
SDName: Instance_Black_Temple SDName: Instance_Black_Temple
@@ -55,22 +55,21 @@ struct TRINITY_DLL_DECL instance_black_temple : public ScriptedInstance
uint64 BloodElfCouncilVoice; uint64 BloodElfCouncilVoice;
uint64 IllidanStormrage; uint64 IllidanStormrage;
uint16 BossKilled; uint16 BossKilled;
uint64 NajentusGate; uint64 NajentusGate;
uint64 MainTempleDoors; uint64 MainTempleDoors;
uint64 ShadeOfAkamaDoor; uint64 ShadeOfAkamaDoor;
uint64 CommonDoor;//Teron uint64 CommonDoor;//Teron
uint64 TeronDoor; uint64 TeronDoor;
uint64 GuurtogDoor; uint64 GuurtogDoor;
uint64 MotherDoor; uint64 MotherDoor;
uint64 TempleDoor;//Befor mother uint64 TempleDoor;//Befor mother
uint64 CouncilDoor; uint64 CouncilDoor;
uint64 SimpleDoor;//council uint64 SimpleDoor;//council
uint64 IllidanGate; uint64 IllidanGate;
uint64 IllidanDoor[2]; uint64 IllidanDoor[2];
uint32 Encounters[ENCOUNTERS]; uint32 Encounters[ENCOUNTERS];
void Initialize() void Initialize()
@@ -88,18 +87,18 @@ struct TRINITY_DLL_DECL instance_black_temple : public ScriptedInstance
BloodElfCouncilVoice = 0; BloodElfCouncilVoice = 0;
IllidanStormrage = 0; IllidanStormrage = 0;
BossKilled = 0; BossKilled = 0;
NajentusGate = 0; NajentusGate = 0;
MainTempleDoors = 0; MainTempleDoors = 0;
ShadeOfAkamaDoor= 0; ShadeOfAkamaDoor= 0;
CommonDoor = 0;//teron CommonDoor = 0;//teron
TeronDoor = 0; TeronDoor = 0;
GuurtogDoor = 0; GuurtogDoor = 0;
MotherDoor = 0; MotherDoor = 0;
TempleDoor = 0; TempleDoor = 0;
SimpleDoor = 0;//Bycouncil SimpleDoor = 0;//Bycouncil
CouncilDoor = 0; CouncilDoor = 0;
IllidanGate = 0; IllidanGate = 0;
IllidanDoor[0] = 0; IllidanDoor[0] = 0;
IllidanDoor[1] = 0; IllidanDoor[1] = 0;
@@ -118,38 +117,32 @@ struct TRINITY_DLL_DECL instance_black_temple : public ScriptedInstance
void OpenDoor(uint64 DoorGUID, bool open) void OpenDoor(uint64 DoorGUID, bool open)
{ {
if(((InstanceMap*)instance)->GetPlayers().size()) if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID))
if(Player* first = ((InstanceMap*)instance)->GetPlayers().front()) Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1);
if(GameObject *Door = GameObject::GetGameObject(*first, DoorGUID))
Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1);
} }
void CloseDoor(uint64 DoorGUID, bool close) void CloseDoor(uint64 DoorGUID, bool close)
{ {
if(((InstanceMap*)instance)->GetPlayers().size()) if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID))
if(Player* first = ((InstanceMap*)instance)->GetPlayers().front()) Door->SetUInt32Value(GAMEOBJECT_STATE, close ? 1 : 0);
if(GameObject *Door = GameObject::GetGameObject(*first, DoorGUID)) }
Door->SetUInt32Value(GAMEOBJECT_STATE, close ? 1 : 0);
}
void OnCreatureCreate(Creature *creature, uint32 creature_entry) void OnCreatureCreate(Creature *creature, uint32 creature_entry)
{ {
switch(creature_entry) switch(creature_entry)
{ {
case 22887: Najentus = creature->GetGUID(); break; case 22887: Najentus = creature->GetGUID(); break;
case 23089: Akama = creature->GetGUID(); break; case 23089: Akama = creature->GetGUID(); break;
case 22990: Akama_Shade = creature->GetGUID(); break; case 22990: Akama_Shade = creature->GetGUID(); break;
case 22841: ShadeOfAkama = creature->GetGUID(); break; case 22841: ShadeOfAkama = creature->GetGUID(); break;
case 22898: Supremus = creature->GetGUID(); break; case 22898: Supremus = creature->GetGUID(); break;
case 22917: IllidanStormrage = creature->GetGUID(); break; case 22917: IllidanStormrage = creature->GetGUID(); break;
case 22949: GathiosTheShatterer = creature->GetGUID(); break; case 22949: GathiosTheShatterer = creature->GetGUID(); break;
case 22950: HighNethermancerZerevor = creature->GetGUID(); break; case 22950: HighNethermancerZerevor = creature->GetGUID(); break;
case 22951: LadyMalande = creature->GetGUID(); break; case 22951: LadyMalande = creature->GetGUID(); break;
case 22952: VerasDarkshadow = creature->GetGUID(); break; case 22952: VerasDarkshadow = creature->GetGUID(); break;
case 23426: IllidariCouncil = creature->GetGUID(); break; case 23426: IllidariCouncil = creature->GetGUID(); break;
case 23499: BloodElfCouncilVoice = creature->GetGUID(); break; case 23499: BloodElfCouncilVoice = creature->GetGUID(); break;
} }
} }
@@ -157,38 +150,38 @@ struct TRINITY_DLL_DECL instance_black_temple : public ScriptedInstance
{ {
switch(go->GetEntry()) switch(go->GetEntry())
{ {
case 185483: // Gate past Naj'entus (at the entrance to Supermoose's courtyards) case 185483: // Gate past Naj'entus (at the entrance to Supermoose's courtyards)
NajentusGate = go->GetGUID();break; NajentusGate = go->GetGUID();break;
case 185882: // Main Temple Doors - right past Supermoose (Supremus) case 185882: // Main Temple Doors - right past Supermoose (Supremus)
MainTempleDoors = go->GetGUID();break; MainTempleDoors = go->GetGUID();break;
case 185478: case 185478:
ShadeOfAkamaDoor = go->GetGUID();break; ShadeOfAkamaDoor = go->GetGUID();break;
case 185480: case 185480:
CommonDoor = go->GetGUID();break; CommonDoor = go->GetGUID();break;
case 186153: case 186153:
TeronDoor = go->GetGUID();break; TeronDoor = go->GetGUID();break;
case 185892: case 185892:
GuurtogDoor = go->GetGUID();break; GuurtogDoor = go->GetGUID();break;
case 185479: case 185479:
TempleDoor = go->GetGUID();break; TempleDoor = go->GetGUID();break;
case 185482: case 185482:
MotherDoor = go->GetGUID();break; MotherDoor = go->GetGUID();break;
case 185481: case 185481:
CouncilDoor = go->GetGUID();break; CouncilDoor = go->GetGUID();break;
case 186152://used by council case 186152://used by council
SimpleDoor = go->GetGUID();break; SimpleDoor = go->GetGUID();break;
case 185905: // Gate leading to Temple Summit case 185905: // Gate leading to Temple Summit
IllidanGate = go->GetGUID(); IllidanGate = go->GetGUID();
go->SetUInt32Value(GAMEOBJECT_FLAGS,GO_FLAG_NODESPAWN+GO_FLAG_INTERACT_COND); go->SetUInt32Value(GAMEOBJECT_FLAGS,GO_FLAG_NODESPAWN+GO_FLAG_INTERACT_COND);
break; break;
case 186261: // Right door at Temple Summit case 186261: // Right door at Temple Summit
IllidanDoor[0] = go->GetGUID(); IllidanDoor[0] = go->GetGUID();
go->SetUInt32Value(GAMEOBJECT_FLAGS,GO_FLAG_NODESPAWN+GO_FLAG_INTERACT_COND); go->SetUInt32Value(GAMEOBJECT_FLAGS,GO_FLAG_NODESPAWN+GO_FLAG_INTERACT_COND);
break; break;
case 186262: // Left door at Temple Summit case 186262: // Left door at Temple Summit
IllidanDoor[1] = go->GetGUID(); IllidanDoor[1] = go->GetGUID();
go->SetUInt32Value(GAMEOBJECT_FLAGS,GO_FLAG_NODESPAWN+GO_FLAG_INTERACT_COND); go->SetUInt32Value(GAMEOBJECT_FLAGS,GO_FLAG_NODESPAWN+GO_FLAG_INTERACT_COND);
break; break;
} }
} }
@@ -196,23 +189,23 @@ struct TRINITY_DLL_DECL instance_black_temple : public ScriptedInstance
{ {
switch(identifier) switch(identifier)
{ {
case DATA_HIGHWARLORDNAJENTUS: return Najentus; case DATA_HIGHWARLORDNAJENTUS: return Najentus;
case DATA_AKAMA: return Akama; case DATA_AKAMA: return Akama;
case DATA_AKAMA_SHADE: return Akama_Shade; case DATA_AKAMA_SHADE: return Akama_Shade;
case DATA_SHADEOFAKAMA: return ShadeOfAkama; case DATA_SHADEOFAKAMA: return ShadeOfAkama;
case DATA_SUPREMUS: return Supremus; case DATA_SUPREMUS: return Supremus;
case DATA_ILLIDANSTORMRAGE: return IllidanStormrage; case DATA_ILLIDANSTORMRAGE: return IllidanStormrage;
case DATA_GATHIOSTHESHATTERER: return GathiosTheShatterer; case DATA_GATHIOSTHESHATTERER: return GathiosTheShatterer;
case DATA_HIGHNETHERMANCERZEREVOR: return HighNethermancerZerevor; case DATA_HIGHNETHERMANCERZEREVOR: return HighNethermancerZerevor;
case DATA_LADYMALANDE: return LadyMalande; case DATA_LADYMALANDE: return LadyMalande;
case DATA_VERASDARKSHADOW: return VerasDarkshadow; case DATA_VERASDARKSHADOW: return VerasDarkshadow;
case DATA_ILLIDARICOUNCIL: return IllidariCouncil; case DATA_ILLIDARICOUNCIL: return IllidariCouncil;
case DATA_GAMEOBJECT_NAJENTUS_GATE: return NajentusGate; case DATA_GAMEOBJECT_NAJENTUS_GATE: return NajentusGate;
case DATA_GAMEOBJECT_ILLIDAN_GATE: return IllidanGate; case DATA_GAMEOBJECT_ILLIDAN_GATE: return IllidanGate;
case DATA_GAMEOBJECT_ILLIDAN_DOOR_R: return IllidanDoor[0]; case DATA_GAMEOBJECT_ILLIDAN_DOOR_R: return IllidanDoor[0];
case DATA_GAMEOBJECT_ILLIDAN_DOOR_L: return IllidanDoor[1]; case DATA_GAMEOBJECT_ILLIDAN_DOOR_L: return IllidanDoor[1];
case DATA_GAMEOBJECT_SUPREMUS_DOORS: return MainTempleDoors; case DATA_GAMEOBJECT_SUPREMUS_DOORS: return MainTempleDoors;
case DATA_BLOOD_ELF_COUNCIL_VOICE: return BloodElfCouncilVoice; case DATA_BLOOD_ELF_COUNCIL_VOICE: return BloodElfCouncilVoice;
} }
return 0; return 0;
@@ -222,69 +215,69 @@ struct TRINITY_DLL_DECL instance_black_temple : public ScriptedInstance
{ {
switch(type) switch(type)
{ {
case DATA_HIGHWARLORDNAJENTUSEVENT: Encounters[0] = data; break; case DATA_HIGHWARLORDNAJENTUSEVENT: Encounters[0] = data; break;
case DATA_SUPREMUSEVENT: Encounters[1] = data; break; case DATA_SUPREMUSEVENT: Encounters[1] = data; break;
case DATA_SHADEOFAKAMAEVENT: Encounters[2] = data; break; case DATA_SHADEOFAKAMAEVENT: Encounters[2] = data; break;
case DATA_TERONGOREFIENDEVENT: Encounters[3] = data; break; case DATA_TERONGOREFIENDEVENT: Encounters[3] = data; break;
case DATA_GURTOGGBLOODBOILEVENT: Encounters[4] = data; break; case DATA_GURTOGGBLOODBOILEVENT: Encounters[4] = data; break;
case DATA_RELIQUARYOFSOULSEVENT: Encounters[5] = data; break; case DATA_RELIQUARYOFSOULSEVENT: Encounters[5] = data; break;
case DATA_MOTHERSHAHRAZEVENT: Encounters[6] = data; break; case DATA_MOTHERSHAHRAZEVENT: Encounters[6] = data; break;
case DATA_ILLIDARICOUNCILEVENT: Encounters[7] = data; break; case DATA_ILLIDARICOUNCILEVENT: Encounters[7] = data; break;
case DATA_ILLIDANSTORMRAGEEVENT: Encounters[8] = data; break; case DATA_ILLIDANSTORMRAGEEVENT: Encounters[8] = data; break;
} }
if(data == DONE) if(data == DONE)
{ {
SaveToDB(); SaveToDB();
BossKilled++; BossKilled++;
} }
CheckInstanceStatus(); CheckInstanceStatus();
} }
void CheckInstanceStatus() void CheckInstanceStatus()
{ {
if(BossKilled >= 6) if(BossKilled >= 6)
OpenDoor(TempleDoor, true); OpenDoor(TempleDoor, true);
if(Encounters[0] == DONE) if(Encounters[0] == DONE)
OpenDoor(NajentusGate, true); OpenDoor(NajentusGate, true);
if(Encounters[2] == IN_PROGRESS) if(Encounters[2] == IN_PROGRESS)
CloseDoor(ShadeOfAkamaDoor, true); CloseDoor(ShadeOfAkamaDoor, true);
else OpenDoor(ShadeOfAkamaDoor, true); else OpenDoor(ShadeOfAkamaDoor, true);
if(Encounters[3] == IN_PROGRESS) if(Encounters[3] == IN_PROGRESS)
{ {
CloseDoor(TeronDoor, true); CloseDoor(TeronDoor, true);
CloseDoor(CommonDoor, true); CloseDoor(CommonDoor, true);
}else{ }else{
OpenDoor(TeronDoor, true); OpenDoor(TeronDoor, true);
OpenDoor(CommonDoor, true); OpenDoor(CommonDoor, true);
} }
if(Encounters[4] == DONE) if(Encounters[4] == DONE)
OpenDoor(GuurtogDoor, true); OpenDoor(GuurtogDoor, true);
if(Encounters[6] == DONE) if(Encounters[6] == DONE)
OpenDoor(MotherDoor, true); OpenDoor(MotherDoor, true);
if(Encounters[7] == IN_PROGRESS) if(Encounters[7] == IN_PROGRESS)
{ {
CloseDoor(CouncilDoor, true); CloseDoor(CouncilDoor, true);
CloseDoor(SimpleDoor, true); CloseDoor(SimpleDoor, true);
}else{ }else{
OpenDoor(CouncilDoor, true); OpenDoor(CouncilDoor, true);
OpenDoor(SimpleDoor, true); OpenDoor(SimpleDoor, true);
} }
} }
uint32 GetData(uint32 type) uint32 GetData(uint32 type)
{ {
switch(type) switch(type)
{ {
case DATA_HIGHWARLORDNAJENTUSEVENT: return Encounters[0]; case DATA_HIGHWARLORDNAJENTUSEVENT: return Encounters[0];
case DATA_SUPREMUSEVENT: return Encounters[1]; case DATA_SUPREMUSEVENT: return Encounters[1];
case DATA_SHADEOFAKAMAEVENT: return Encounters[2]; case DATA_SHADEOFAKAMAEVENT: return Encounters[2];
case DATA_TERONGOREFIENDEVENT: return Encounters[3]; case DATA_TERONGOREFIENDEVENT: return Encounters[3];
case DATA_GURTOGGBLOODBOILEVENT: return Encounters[4]; case DATA_GURTOGGBLOODBOILEVENT: return Encounters[4];
case DATA_RELIQUARYOFSOULSEVENT: return Encounters[5]; case DATA_RELIQUARYOFSOULSEVENT: return Encounters[5];
case DATA_MOTHERSHAHRAZEVENT: return Encounters[6]; case DATA_MOTHERSHAHRAZEVENT: return Encounters[6];
case DATA_ILLIDARICOUNCILEVENT: return Encounters[7]; case DATA_ILLIDARICOUNCILEVENT: return Encounters[7];
case DATA_ILLIDANSTORMRAGEEVENT: return Encounters[8]; case DATA_ILLIDANSTORMRAGEEVENT: return Encounters[8];
} }
return 0; return 0;
@@ -319,8 +312,8 @@ struct TRINITY_DLL_DECL instance_black_temple : public ScriptedInstance
OUT_LOAD_INST_DATA(in); OUT_LOAD_INST_DATA(in);
std::istringstream stream(in); std::istringstream stream(in);
stream >> Encounters[0] >> Encounters[1] >> Encounters[2] >> Encounters[3] stream >> Encounters[0] >> Encounters[1] >> Encounters[2] >> Encounters[3]
>> Encounters[4] >> Encounters[5] >> Encounters[6] >> Encounters[7] >> Encounters[4] >> Encounters[5] >> Encounters[6] >> Encounters[7]
>> Encounters[8]; >> Encounters[8];
for(uint8 i = 0; i < ENCOUNTERS; ++i) for(uint8 i = 0; i < ENCOUNTERS; ++i)
if(Encounters[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. if(Encounters[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead.
Encounters[i] = NOT_STARTED; Encounters[i] = NOT_STARTED;
+46 -1
View File
@@ -319,6 +319,10 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data )
m_spells[2] = GetCreatureInfo()->spell3; m_spells[2] = GetCreatureInfo()->spell3;
m_spells[3] = GetCreatureInfo()->spell4; m_spells[3] = GetCreatureInfo()->spell4;
// HACK: trigger creature is always not selectable
if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
return true; return true;
} }
@@ -1487,6 +1491,47 @@ void Creature::DeleteFromDB()
WorldDatabase.CommitTransaction(); WorldDatabase.CommitTransaction();
} }
bool Creature::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const
{
// not in world
if(!IsInWorld() || !u->IsInWorld())
return false;
// all dead creatures/players not visible for any creatures
if(!u->isAlive() || !isAlive())
return false;
// Always can see self
if (u == this)
return true;
// always seen by owner
if(GetGUID() == u->GetCharmerOrOwnerGUID())
return true;
if(u->GetVisibility() == VISIBILITY_OFF) //GM
return false;
// invisible aura
if((m_invisibilityMask || u->m_invisibilityMask) && !canDetectInvisibilityOf(u))
return false;
// unit got in stealth in this moment and must ignore old detected state
//if (m_Visibility == VISIBILITY_GROUP_NO_DETECT)
// return false;
// GM invisibility checks early, invisibility if any detectable, so if not stealth then visible
if(u->GetVisibility() == VISIBILITY_GROUP_STEALTH)
{
//do not know what is the use of this detect
if(!detect || !canDetectStealthOf(u, GetDistance(u)))
return false;
}
// Now check is target visible with LoS
return u->IsWithinLOS(GetPositionX(),GetPositionY(),GetPositionZ());
}
float Creature::GetAttackDistance(Unit const* pl) const float Creature::GetAttackDistance(Unit const* pl) const
{ {
float aggroRate = sWorld.getRate(RATE_CREATURE_AGGRO); float aggroRate = sWorld.getRate(RATE_CREATURE_AGGRO);
@@ -1698,7 +1743,7 @@ SpellEntry const *Creature::reachWithSpellCure(Unit *pVictim)
return NULL; return NULL;
} }
bool Creature::IsVisibleInGridForPlayer(Player* pl) const bool Creature::IsVisibleInGridForPlayer(Player const* pl) const
{ {
// gamemaster in GM mode see all, including ghosts // gamemaster in GM mode see all, including ghosts
if(pl->isGameMaster()) if(pl->isGameMaster())
+2 -1
View File
@@ -547,6 +547,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
CreatureSpellCooldowns m_CreatureCategoryCooldowns; CreatureSpellCooldowns m_CreatureCategoryCooldowns;
uint32 m_GlobalCooldown; uint32 m_GlobalCooldown;
bool canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const;
float GetAttackDistance(Unit const* pl) const; float GetAttackDistance(Unit const* pl) const;
void CallAssistence(); void CallAssistence();
@@ -560,7 +561,7 @@ class TRINITY_DLL_SPEC Creature : public Unit
Cell const& GetCurrentCell() const { return m_currentCell; } Cell const& GetCurrentCell() const { return m_currentCell; }
void SetCurrentCell(Cell const& cell) { m_currentCell = cell; } void SetCurrentCell(Cell const& cell) { m_currentCell = cell; }
bool IsVisibleInGridForPlayer(Player* pl) const; bool IsVisibleInGridForPlayer(Player const* pl) const;
void RemoveCorpse(); void RemoveCorpse();
+1 -1
View File
@@ -1486,7 +1486,7 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa
{ {
if(GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER) if(GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER)
pCreature->setFaction(((Unit*)this)->getFaction()); pCreature->setFaction(((Unit*)this)->getFaction());
pCreature->CastSpell(pCreature, pCreature->m_spells[0], true, 0, 0, GetGUID()); pCreature->CastSpell(pCreature, pCreature->m_spells[0], false, 0, 0, GetGUID());
} }
//return the creature therewith the summoner has access to it //return the creature therewith the summoner has access to it
+3 -3
View File
@@ -50,13 +50,13 @@ bool OutdoorPvPObjectiveAI::IsVisible(Unit *pl) const
void OutdoorPvPObjectiveAI::AttackStart(Unit *) void OutdoorPvPObjectiveAI::AttackStart(Unit *)
{ {
EnterEvadeMode(); //EnterEvadeMode();
} }
void OutdoorPvPObjectiveAI::EnterEvadeMode() void OutdoorPvPObjectiveAI::EnterEvadeMode()
{ {
i_creature.DeleteThreatList(); // i_creature.DeleteThreatList();
i_creature.CombatStop(); // i_creature.CombatStop();
} }
void OutdoorPvPObjectiveAI::UpdateAI(const uint32 diff) void OutdoorPvPObjectiveAI::UpdateAI(const uint32 diff)
+104 -4
View File
@@ -2000,8 +2000,8 @@ void Player::SetGMVisible(bool on)
// Reapply stealth/invisibility if active or show if not any // Reapply stealth/invisibility if active or show if not any
if(HasAuraType(SPELL_AURA_MOD_STEALTH)) if(HasAuraType(SPELL_AURA_MOD_STEALTH))
SetVisibility(VISIBILITY_GROUP_STEALTH); SetVisibility(VISIBILITY_GROUP_STEALTH);
else if(HasAuraType(SPELL_AURA_MOD_INVISIBILITY)) //else if(HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
SetVisibility(VISIBILITY_GROUP_INVISIBILITY); // SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
else else
SetVisibility(VISIBILITY_ON); SetVisibility(VISIBILITY_ON);
} }
@@ -16395,7 +16395,6 @@ void Player::HandleStealthedUnitsDetection()
if ((*i)->isVisibleForOrDetect(this,true)) if ((*i)->isVisibleForOrDetect(this,true))
{ {
(*i)->SendUpdateToPlayer(this); (*i)->SendUpdateToPlayer(this);
m_clientGUIDs.insert((*i)->GetGUID()); m_clientGUIDs.insert((*i)->GetGUID());
@@ -17188,7 +17187,108 @@ void Player::ReportedAfkBy(Player* reporter)
} }
} }
bool Player::IsVisibleInGridForPlayer( Player* pl ) const bool Player::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const
{
// Always can see self
if (u == this)
return true;
// player visible for other player if not logout and at same transport
// including case when player is out of world
bool at_same_transport =
GetTransport() && u->GetTypeId() == TYPEID_PLAYER
&& !GetSession()->PlayerLogout() && !((Player*)u)->GetSession()->PlayerLogout()
&& !GetSession()->PlayerLoading() && !((Player*)u)->GetSession()->PlayerLoading()
&& GetTransport() == ((Player*)u)->GetTransport();
// not in world
if(!at_same_transport && (!IsInWorld() || !u->IsInWorld()))
return false;
// forbidden to seen (at GM respawn command)
if(u->GetVisibility() == VISIBILITY_RESPAWN)
return false;
// always seen by owner
if(GetGUID() == u->GetCharmerOrOwnerGUID())
return true;
// Grid dead/alive checks
// non visible at grid for any stealth state
if(!u->IsVisibleInGridForPlayer(this))
return false;
// If the player is currently possessing, update visibility from the possessed unit's location
const Unit* target = isPossessing() ? GetCharm() : this;
// different visible distance checks
if(isInFlight()) // what see player in flight
{
if (!target->IsWithinDistInMap(u,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)))
return false;
}
else if(!u->isAlive()) // distance for show body
{
if (!target->IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)))
return false;
}
else if(u->GetTypeId()==TYPEID_PLAYER) // distance for show player
{
// Players far than max visible distance for player or not in our map are not visible too
if (!at_same_transport && !target->IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f)))
return false;
}
else if(u->GetCharmerOrOwnerGUID()) // distance for show pet/charmed
{
// Pet/charmed far than max visible distance for player or not in our map are not visible too
if (!target->IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f)))
return false;
}
else // distance for show creature
{
// Units far than max visible distance for creature or not in our map are not visible too
if (!target->IsWithinDistInMap(u, target->isActive()
? (MAX_VISIBILITY_DISTANCE - (inVisibleList ? 0.0f : World::GetVisibleUnitGreyDistance()))
: (World::GetMaxVisibleDistanceForCreature() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))))
return false;
}
// GMs see any players, not higher GMs and all units
if(isGameMaster())
{
if(u->GetTypeId() == TYPEID_PLAYER)
return ((Player *)u)->GetSession()->GetSecurity() <= GetSession()->GetSecurity();
else
return true;
}
if(u->GetVisibility() == VISIBILITY_OFF)
return false;
// player see other player with stealth/invisibility only if he in same group or raid or same team (raid/team case dependent from conf setting)
if((m_invisibilityMask || u->m_invisibilityMask) && !canDetectInvisibilityOf(u))
if(!(u->GetTypeId()==TYPEID_PLAYER && !IsHostileTo(u) && IsGroupVisibleFor(((Player*)u))))
return false;
// GM invisibility checks early, invisibility if any detectable, so if not stealth then visible
if(u->GetVisibility() == VISIBILITY_GROUP_STEALTH)
{
// if player is dead then he can't detect anyone in anycases
//do not know what is the use of this detect
// stealth and detected and visible for some seconds
if(!isAlive())
detect = false;
if(m_DetectInvTimer < 300 || !HaveAtClient(u))
if(!(u->GetTypeId()==TYPEID_PLAYER && !IsHostileTo(u) && IsGroupVisibleFor(((Player*)u))))
if(!detect || !canDetectStealthOf(u, GetDistance(u)))
return false;
}
// Now check is target visible with LoS
return u->IsWithinLOS(GetPositionX(),GetPositionY(),GetPositionZ());
}
bool Player::IsVisibleInGridForPlayer( Player const * pl ) const
{ {
// gamemaster in GM mode see all, including ghosts // gamemaster in GM mode see all, including ghosts
if(pl->isGameMaster() && GetSession()->GetSecurity() <= pl->GetSession()->GetSecurity()) if(pl->isGameMaster() && GetSession()->GetSecurity() <= pl->GetSession()->GetSecurity())
+3 -2
View File
@@ -1992,9 +1992,10 @@ class TRINITY_DLL_SPEC Player : public Unit
typedef std::set<uint64> ClientGUIDs; typedef std::set<uint64> ClientGUIDs;
ClientGUIDs m_clientGUIDs; ClientGUIDs m_clientGUIDs;
bool HaveAtClient(WorldObject const* u) { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); } bool HaveAtClient(WorldObject const* u) const { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); }
bool IsVisibleInGridForPlayer(Player* pl) const; bool canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const;
bool IsVisibleInGridForPlayer(Player const* pl) const;
bool IsVisibleGloballyFor(Player* pl) const; bool IsVisibleGloballyFor(Player* pl) const;
void UpdateVisibilityOf(WorldObject* target); void UpdateVisibilityOf(WorldObject* target);
+8 -5
View File
@@ -3230,7 +3230,8 @@ void Aura::HandleModStealth(bool apply, bool Real)
// apply only if not in GM invisibility (and overwrite invisibility state) // apply only if not in GM invisibility (and overwrite invisibility state)
if(m_target->GetVisibility()!=VISIBILITY_OFF) if(m_target->GetVisibility()!=VISIBILITY_OFF)
{ {
m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
m_target->SetVisibility(VISIBILITY_OFF);
m_target->SetVisibility(VISIBILITY_GROUP_STEALTH); m_target->SetVisibility(VISIBILITY_GROUP_STEALTH);
} }
@@ -3258,8 +3259,9 @@ void Aura::HandleModStealth(bool apply, bool Real)
// restore invisibility if any // restore invisibility if any
if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY)) if(m_target->HasAuraType(SPELL_AURA_MOD_INVISIBILITY))
{ {
m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY); //m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
m_target->SetVisibility(VISIBILITY_ON);
} }
else else
{ {
@@ -3314,8 +3316,9 @@ void Aura::HandleInvisibility(bool apply, bool Real)
if(m_target->GetVisibility()==VISIBILITY_ON) if(m_target->GetVisibility()==VISIBILITY_ON)
{ {
// Aura not added yet but visibility code expect temporary add aura // Aura not added yet but visibility code expect temporary add aura
m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT); //m_target->SetVisibility(VISIBILITY_GROUP_NO_DETECT);
m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY); //m_target->SetVisibility(VISIBILITY_GROUP_INVISIBILITY);
m_target->SetVisibility(VISIBILITY_ON);
} }
} }
else else
+7
View File
@@ -3576,6 +3576,13 @@ void Spell::EffectSummonGuardian(uint32 i)
return; return;
} }
// trigger
if(m_spellInfo->Id == 40276)
{
EffectSummonWild(i);
return;
}
// set timer for unsummon // set timer for unsummon
int32 duration = GetSpellDuration(m_spellInfo); int32 duration = GetSpellDuration(m_spellInfo);
+54 -254
View File
@@ -8506,9 +8506,6 @@ bool Unit::isTargetableForAttack() const
if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE)) if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE))
return false; return false;
if(GetTypeId()==TYPEID_UNIT && (((Creature *)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER))
return false;
return isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/; return isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/;
} }
@@ -8580,259 +8577,23 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList)
{ {
if(!u) if(!u)
return false; return false;
return u->canSeeOrDetect(this, detect, inVisibleList);
// Always can see self
if (u==this)
return true;
// player visible for other player if not logout and at same transport
// including case when player is out of world
bool at_same_transport =
GetTypeId() == TYPEID_PLAYER && u->GetTypeId()==TYPEID_PLAYER &&
!((Player*)this)->GetSession()->PlayerLogout() && !((Player*)u)->GetSession()->PlayerLogout() &&
!((Player*)this)->GetSession()->PlayerLoading() && !((Player*)u)->GetSession()->PlayerLoading() &&
((Player*)this)->GetTransport() && ((Player*)this)->GetTransport() == ((Player*)u)->GetTransport();
// not in world
if(!at_same_transport && (!IsInWorld() || !u->IsInWorld()))
return false;
// forbidden to seen (at GM respawn command)
if(m_Visibility==VISIBILITY_RESPAWN)
return false;
// always seen by owner
if(GetCharmerOrOwnerGUID()==u->GetGUID())
return true;
// Grid dead/alive checks
if( u->GetTypeId()==TYPEID_PLAYER)
{
// non visible at grid for any stealth state
if(!IsVisibleInGridForPlayer((Player *)u))
return false;
// if player is dead then he can't detect anyone in anycases
if(!u->isAlive())
detect = false;
}
else
{
// all dead creatures/players not visible for any creatures
if(!u->isAlive() || !isAlive())
return false;
}
// If the player is currently possessing, update visibility from the possessed unit's location
const Unit* target = u->GetTypeId() == TYPEID_PLAYER && u->isPossessing() ? u->GetCharm() : u;
// different visible distance checks
if(u->isInFlight()) // what see player in flight
{
// use object grey distance for all (only see objects any way)
if (!IsWithinDistInMap(target,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)))
return false;
}
else if(!isAlive()) // distance for show body
{
if (!IsWithinDistInMap(target,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)))
return false;
}
else if(GetTypeId()==TYPEID_PLAYER) // distance for show player
{
if(u->GetTypeId()==TYPEID_PLAYER)
{
// Players far than max visible distance for player or not in our map are not visible too
if (!at_same_transport && !IsWithinDistInMap(target,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f)))
return false;
}
else
{
// Units far than max visible distance for creature or not in our map are not visible too
// Active unit should always be visibile
if (!IsWithinDistInMap(target, target->isActive()
? (MAX_VISIBILITY_DISTANCE - (inVisibleList ? 0.0f : World::GetVisibleUnitGreyDistance()))
: (World::GetMaxVisibleDistanceForCreature() + (inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))))
return false;
}
}
else if(GetCharmerOrOwnerGUID()) // distance for show pet/charmed
{
// Pet/charmed far than max visible distance for player or not in our map are not visible too
if (!IsWithinDistInMap(target,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f)))
return false;
}
else // distance for show creature
{
// Units far than max visible distance for creature or not in our map are not visible too
if (!IsWithinDistInMap(target,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f)))
return false;
}
// Visible units, always are visible for all units, except for units under invisibility
if (m_Visibility == VISIBILITY_ON && u->m_invisibilityMask==0)
return true;
// GMs see any players, not higher GMs and all units
if (u->GetTypeId() == TYPEID_PLAYER && ((Player *)u)->isGameMaster())
{
if(GetTypeId() == TYPEID_PLAYER)
return ((Player *)this)->GetSession()->GetSecurity() <= ((Player *)u)->GetSession()->GetSecurity();
else
return true;
}
// non faction visibility non-breakable for non-GMs
if (m_Visibility == VISIBILITY_OFF)
return false;
// raw invisibility
bool invisible = (m_invisibilityMask != 0 || u->m_invisibilityMask !=0);
// detectable invisibility case
if( invisible && (
// Invisible units, always are visible for units under same invisibility type
(m_invisibilityMask & u->m_invisibilityMask)!=0 ||
// Invisible units, always are visible for unit that can detect this invisibility (have appropriate level for detect)
u->canDetectInvisibilityOf(this) ||
// Units that can detect invisibility always are visible for units that can be detected
canDetectInvisibilityOf(u) ))
{
invisible = false;
}
// special cases for always overwrite invisibility/stealth
if(invisible || m_Visibility == VISIBILITY_GROUP_STEALTH)
{
// non-hostile case
if (!u->IsHostileTo(this))
{
// player see other player with stealth/invisibility only if he in same group or raid or same team (raid/team case dependent from conf setting)
if(GetTypeId()==TYPEID_PLAYER && u->GetTypeId()==TYPEID_PLAYER)
{
if(((Player*)this)->IsGroupVisibleFor(((Player*)u)))
return true;
// else apply same rules as for hostile case (detecting check for stealth)
}
}
// hostile case
else
{
// Hunter mark functionality
AuraList const& auras = GetAurasByType(SPELL_AURA_MOD_STALKED);
for(AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
if((*iter)->GetCasterGUID()==u->GetGUID())
return true;
// else apply detecting check for stealth
}
// none other cases for detect invisibility, so invisible
if(invisible)
return false;
// else apply stealth detecting check
}
// unit got in stealth in this moment and must ignore old detected state
if (m_Visibility == VISIBILITY_GROUP_NO_DETECT)
return false;
// GM invisibility checks early, invisibility if any detectable, so if not stealth then visible
if (m_Visibility != VISIBILITY_GROUP_STEALTH)
return true;
// NOW ONLY STEALTH CASE
// stealth and detected and visible for some seconds
if (u->GetTypeId() == TYPEID_PLAYER && ((Player*)u)->m_DetectInvTimer > 300 && ((Player*)u)->HaveAtClient(this))
return true;
//if in non-detect mode then invisible for unit
if (!detect)
return false;
// Special cases
// If is attacked then stealth is lost, some creature can use stealth too
if( !getAttackers().empty() )
return true;
// If there is collision rogue is seen regardless of level difference
// TODO: check sizes in DB
float distance = GetDistance(u);
if (distance < 0.24f)
return true;
//If a mob or player is stunned he will not be able to detect stealth
if (u->hasUnitState(UNIT_STAT_STUNNED) && (u != this))
return false;
// Creature can detect target only in aggro radius
if(u->GetTypeId() != TYPEID_PLAYER)
{
//Always invisible from back and out of aggro range
bool isInFront = u->isInFront(this,((Creature const*)u)->GetAttackDistance(this));
if(!isInFront)
return false;
}
else
{
//Always invisible from back
bool isInFront = u->isInFront(this,(GetTypeId()==TYPEID_PLAYER || GetCharmerOrOwnerGUID()) ? World::GetMaxVisibleDistanceForPlayer() : World::GetMaxVisibleDistanceForCreature());
if(!isInFront)
return false;
}
// if doesn't have stealth detection (Shadow Sight), then check how stealthy the unit is, otherwise just check los
if(!u->HasAuraType(SPELL_AURA_DETECT_STEALTH))
{
//Calculation if target is in front
//Visible distance based on stealth value (stealth rank 4 300MOD, 10.5 - 3 = 7.5)
float visibleDistance = 10.5f - (GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH)/100.0f);
//Visible distance is modified by
//-Level Diff (every level diff = 1.0f in visible distance)
visibleDistance += int32(u->getLevelForTarget(this)) - int32(this->getLevelForTarget(u));
//This allows to check talent tree and will add addition stealth dependent on used points)
int32 stealthMod = GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH_LEVEL);
if(stealthMod < 0)
stealthMod = 0;
//-Stealth Mod(positive like Master of Deception) and Stealth Detection(negative like paranoia)
//based on wowwiki every 5 mod we have 1 more level diff in calculation
visibleDistance += (int32(u->GetTotalAuraModifier(SPELL_AURA_MOD_DETECT)) - stealthMod)/5.0f;
if(distance > visibleDistance)
return false;
}
// Now check is target visible with LoS
float ox,oy,oz;
u->GetPosition(ox,oy,oz);
return IsWithinLOS(ox,oy,oz);
} }
void Unit::SetVisibility(UnitVisibility x) bool Unit::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const
{ {
m_Visibility = x; return true;
if(IsInWorld())
{
Map *m = MapManager::Instance().GetMap(GetMapId(), this);
if(GetTypeId()==TYPEID_PLAYER)
m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
else
m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
}
} }
bool Unit::canDetectInvisibilityOf(Unit const* u) const bool Unit::canDetectInvisibilityOf(Unit const* u) const
{ {
if(m_invisibilityMask & u->m_invisibilityMask) // same group
return true;
AuraList const& auras = GetAurasByType(SPELL_AURA_MOD_STALKED); // Hunter mark
for(AuraList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
if((*iter)->GetCasterGUID()==u->GetGUID())
return true;
if(uint32 mask = (m_detectInvisibilityMask & u->m_invisibilityMask)) if(uint32 mask = (m_detectInvisibilityMask & u->m_invisibilityMask))
{ {
for(uint32 i = 0; i < 10; ++i) for(uint32 i = 0; i < 10; ++i)
@@ -8849,15 +8610,17 @@ bool Unit::canDetectInvisibilityOf(Unit const* u) const
// find invisibility detect level // find invisibility detect level
uint32 detectLevel = 0; uint32 detectLevel = 0;
Unit::AuraList const& dAuras = GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
for(Unit::AuraList::const_iterator itr = dAuras.begin(); itr != dAuras.end(); ++itr)
if(((*itr)->GetModifier()->m_miscvalue)==i && detectLevel < (*itr)->GetModifier()->m_amount)
detectLevel = (*itr)->GetModifier()->m_amount;
if(i==6 && GetTypeId()==TYPEID_PLAYER) // special drunk detection case if(i==6 && GetTypeId()==TYPEID_PLAYER) // special drunk detection case
{ {
detectLevel = ((Player*)this)->GetDrunkValue(); detectLevel = ((Player*)this)->GetDrunkValue();
} }
else
{
Unit::AuraList const& dAuras = GetAurasByType(SPELL_AURA_MOD_INVISIBILITY_DETECTION);
for(Unit::AuraList::const_iterator itr = dAuras.begin(); itr != dAuras.end(); ++itr)
if(((*itr)->GetModifier()->m_miscvalue)==i && detectLevel < (*itr)->GetModifier()->m_amount)
detectLevel = (*itr)->GetModifier()->m_amount;
}
if(invLevel <= detectLevel) if(invLevel <= detectLevel)
return true; return true;
@@ -8867,6 +8630,43 @@ bool Unit::canDetectInvisibilityOf(Unit const* u) const
return false; return false;
} }
bool Unit::canDetectStealthOf(Unit const* target, float distance) const
{
if(hasUnitState(UNIT_STAT_STUNNED))
return false;
if(distance < 0.24f) //collision
return true;
if(!HasInArc(M_PI, target)) //behind
return false;
if(HasAuraType(SPELL_AURA_DETECT_STEALTH))
return true;
//Visible distance based on stealth value (stealth rank 4 300MOD, 10.5 - 3 = 7.5)
float visibleDistance = 10.5f - target->GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH) / 100.0f;
//Visible distance is modified by -Level Diff (every level diff = 1.0f in visible distance)
visibleDistance += int32(getLevelForTarget(target)) - int32(target->getLevelForTarget(this));
//-Stealth Mod(positive like Master of Deception) and Stealth Detection(negative like paranoia)
//based on wowwiki every 5 mod we have 1 more level diff in calculation
visibleDistance += (float)(GetTotalAuraModifier(SPELL_AURA_MOD_DETECT) - target->GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH_LEVEL)) / 5.0f;
return distance < visibleDistance;
}
void Unit::SetVisibility(UnitVisibility x)
{
m_Visibility = x;
if(IsInWorld())
{
Map *m = MapManager::Instance().GetMap(GetMapId(), this);
if(GetTypeId()==TYPEID_PLAYER)
m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
else
m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
}
}
void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
{ {
int32 main_speed_mod = 0; int32 main_speed_mod = 0;
+5 -3
View File
@@ -437,8 +437,8 @@ enum UnitVisibility
VISIBILITY_OFF = 0, // absolute, not detectable, GM-like, can see all other VISIBILITY_OFF = 0, // absolute, not detectable, GM-like, can see all other
VISIBILITY_ON = 1, VISIBILITY_ON = 1,
VISIBILITY_GROUP_STEALTH = 2, // detect chance, seen and can see group members VISIBILITY_GROUP_STEALTH = 2, // detect chance, seen and can see group members
VISIBILITY_GROUP_INVISIBILITY = 3, // invisibility, can see and can be seen only another invisible unit or invisible detection unit, set only if not stealthed, and in checks not used (mask used instead) //VISIBILITY_GROUP_INVISIBILITY = 3, // invisibility, can see and can be seen only another invisible unit or invisible detection unit, set only if not stealthed, and in checks not used (mask used instead)
VISIBILITY_GROUP_NO_DETECT = 4, // state just at stealth apply for update Grid state. Don't remove, otherwise stealth spells will break //VISIBILITY_GROUP_NO_DETECT = 4, // state just at stealth apply for update Grid state. Don't remove, otherwise stealth spells will break
VISIBILITY_RESPAWN = 5 // special totally not detectable visibility for force delete object at respawn command VISIBILITY_RESPAWN = 5 // special totally not detectable visibility for force delete object at respawn command
}; };
@@ -1135,13 +1135,15 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void SetVisibility(UnitVisibility x); void SetVisibility(UnitVisibility x);
// common function for visibility checks for player/creatures with detection code // common function for visibility checks for player/creatures with detection code
virtual bool canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) const;
bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false) const; bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false) const;
bool canDetectInvisibilityOf(Unit const* u) const; bool canDetectInvisibilityOf(Unit const* u) const;
bool canDetectStealthOf(Unit const* u, float distance) const;
// virtual functions for all world objects types // virtual functions for all world objects types
bool isVisibleForInState(Player const* u, bool inVisibleList) const; bool isVisibleForInState(Player const* u, bool inVisibleList) const;
// function for low level grid visibility checks in player/creature cases // function for low level grid visibility checks in player/creature cases
virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0; virtual bool IsVisibleInGridForPlayer(Player const* pl) const = 0;
bool waterbreath; bool waterbreath;
AuraList & GetSingleCastAuras() { return m_scAuras; } AuraList & GetSingleCastAuras() { return m_scAuras; }
+2 -2
View File
@@ -10,12 +10,12 @@
* *
* 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
*/ */
/** \file /** \file
+3 -4
View File
@@ -10,12 +10,12 @@
* *
* 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
*/ */
/// \addtogroup realmd /// \addtogroup realmd
@@ -75,8 +75,7 @@ class AuthSocket: public TcpSocket
std::string _login; std::string _login;
std::string _safelogin; std::string _safelogin;
// Since GetLocaleByName() is _NOT_ bijective, we have to store the locale as a string. Otherwise we can't differ // Since GetLocaleByName() is _NOT_ bijective, we have to store the locale as a string. Otherwise we can't differ
// between enUS and enGB, which is important for the patch system // between enUS and enGB, which is important for the patch system
std::string _localizationName; std::string _localizationName;
+2 -3
View File
@@ -10,12 +10,12 @@
* *
* 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
*/ */
/// \addtogroup realmd Realm Daemon /// \addtogroup realmd Realm Daemon
@@ -340,7 +340,6 @@ void UnhookSignals()
#ifdef _WIN32 #ifdef _WIN32
signal(SIGBREAK, 0); signal(SIGBREAK, 0);
#endif #endif
} }
/// @} /// @}
+2 -2
View File
@@ -10,12 +10,12 @@
* *
* 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
*/ */
/** \file /** \file