2 * Copyright (C) 2005,2006 MaNGOS <http://www.mangosproject.org/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "ByteBuffer.h"
20 #include "ReactorAI.h"
23 #include "TargetedMovementGenerator.h"
24 #include "FactionTemplateResolver.h"
27 #define REACTOR_VISIBLE_RANGE (26.46f)
30 ReactorAI::Permissible(const Creature
*creature
)
32 if( creature
->IsNeutralToAll() )
33 return PERMIT_BASE_REACTIVE
;
35 return PERMIT_BASE_NO
;
39 ReactorAI::MoveInLineOfSight(Unit
*)
44 ReactorAI::AttackStart(Unit
*p
)
46 if( i_creature
.getVictim() == NULL
)
48 if(i_creature
.Attack(p
))
50 DEBUG_LOG("Tag unit LowGUID(%u) HighGUID(%u) as a victim", p
->GetGUIDLow(), p
->GetGUIDHigh());
51 i_victimGuid
= p
->GetGUID();
52 i_creature
->Mutate(new TargetedMovementGenerator(*p
));
53 if (p
->GetTypeId() == TYPEID_PLAYER
)
54 i_creature
.SetLootRecipient((Player
*)p
);
60 ReactorAI::AttackStop(Unit
*)
66 ReactorAI::HealBy(Unit
*healer
, uint32 amount_healed
)
71 ReactorAI::DamageInflict(Unit
*healer
, uint32 amount_healed
)
76 ReactorAI::IsVisible(Unit
*pl
) const
82 ReactorAI::UpdateAI(const uint32 time_diff
)
84 // update i_victimGuid if i_creature.getVictim() !=0 and changed
85 if(i_creature
.getVictim())
86 i_victimGuid
= i_creature
.getVictim()->GetGUID();
88 // i_creature.getVictim() can't be used for check in case stop fighting, i_creature.getVictim() cleared at Unit death etc.
93 DEBUG_LOG("Creature %u stopped attacking.", i_creature
.GetGUIDLow());
94 stopAttack(); // i_victimGuid == 0 && i_creature.getVictim() == NULL now
97 else if( i_creature
.IsStopped() )
99 if( i_creature
.isAttackReady() )
101 Unit
* newtarget
= i_creature
.SelectHostilTarget();
103 AttackStart(newtarget
);
105 if(!i_creature
.canReachWithAttack(i_creature
.getVictim()))
107 i_creature
.AttackerStateUpdate(i_creature
.getVictim());
108 i_creature
.resetAttackTimer();
110 if ( !i_creature
.getVictim() )
121 ReactorAI::needToStop() const
123 if( !i_creature
.isAlive() || !i_creature
.getVictim() || !i_creature
.getVictim()->isTargetableForAttack() )
126 if(!i_creature
.getVictim()->isInAccessablePlaceFor(&i_creature
))
130 i_creature
.GetRespawnCoord(rx
, ry
, rz
);
131 float spawndist
=i_creature
.GetDistanceSq(rx
,ry
,rz
);
132 float length
= i_creature
.GetDistanceSq(i_creature
.getVictim());
133 float hostillen
=i_creature
.GetHostility( i_creature
.getVictim()->GetGUID())/(2.5f
* i_creature
.getLevel()+1.0f
);
134 return (( length
> (10.0f
+ hostillen
) * (10.0f
+ hostillen
) && spawndist
> 6400.0f
)
135 || ( length
> (20.0f
+ hostillen
) * (20.0f
+ hostillen
) && spawndist
> 2500.0f
)
136 || ( length
> (30.0f
+ hostillen
) * (30.0f
+ hostillen
) ));
140 ReactorAI::stopAttack()
142 if( !i_creature
.isAlive() )
144 DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", i_creature
.GetGUIDLow());
145 i_creature
->MovementExpired();
148 i_creature
.CombatStop();
152 assert( i_victimGuid
);
154 Unit
* victim
= ObjectAccessor::Instance().GetUnit(i_creature
, i_victimGuid
);
158 DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature
.GetGUIDLow());
160 else if( victim
->isStealth() )
162 DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_creature
.GetGUIDLow());
164 else if( victim
->isInFlight() )
166 DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_creature
.GetGUIDLow());
170 DEBUG_LOG("Creature stopped attacking due to target %s [guid=%u]", victim
->isAlive() ? "out run him" : "is dead", i_creature
.GetGUIDLow());
173 // TargetedMovementGenerator can be already remove at i_creature death and not updated i_victimGuid
174 if( i_creature
->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE
)
175 static_cast<TargetedMovementGenerator
*>(i_creature
->top())->TargetedHome(i_creature
);
178 i_creature
.AttackStop();