[2685] Applied MaNGOS coding style (see trunk/bcpp.cfg).
[mangos-git.git] / src / game / ReactorAI.cpp
blob5dc354961c2981d20f9950dd653162888053da83
1 /*
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"
21 #include "Errors.h"
22 #include "Creature.h"
23 #include "TargetedMovementGenerator.h"
24 #include "FactionTemplateResolver.h"
25 #include "Log.h"
27 #define REACTOR_VISIBLE_RANGE (26.46f)
29 int
30 ReactorAI::Permissible(const Creature *creature)
32 if( creature->IsNeutralToAll() )
33 return PERMIT_BASE_REACTIVE;
35 return PERMIT_BASE_NO;
38 void
39 ReactorAI::MoveInLineOfSight(Unit *)
43 void
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);
59 void
60 ReactorAI::AttackStop(Unit *)
65 void
66 ReactorAI::HealBy(Unit *healer, uint32 amount_healed)
70 void
71 ReactorAI::DamageInflict(Unit *healer, uint32 amount_healed)
75 bool
76 ReactorAI::IsVisible(Unit *pl) const
78 return false;
81 void
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.
89 if( i_victimGuid )
91 if( needToStop() )
93 DEBUG_LOG("Creature %u stopped attacking.", i_creature.GetGUIDLow());
94 stopAttack(); // i_victimGuid == 0 && i_creature.getVictim() == NULL now
95 return;
97 else if( i_creature.IsStopped() )
99 if( i_creature.isAttackReady() )
101 Unit* newtarget = i_creature.SelectHostilTarget();
102 if(newtarget)
103 AttackStart(newtarget);
105 if(!i_creature.canReachWithAttack(i_creature.getVictim()))
106 return;
107 i_creature.AttackerStateUpdate(i_creature.getVictim());
108 i_creature.resetAttackTimer();
110 if ( !i_creature.getVictim() )
111 return;
113 if( needToStop() )
114 stopAttack();
120 bool
121 ReactorAI::needToStop() const
123 if( !i_creature.isAlive() || !i_creature.getVictim() || !i_creature.getVictim()->isTargetableForAttack() )
124 return true;
126 if(!i_creature.getVictim()->isInAccessablePlaceFor(&i_creature))
127 return true;
129 float rx,ry,rz;
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) ));
139 void
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();
146 i_creature->Idle();
147 i_victimGuid = 0;
148 i_creature.CombatStop();
149 return;
152 assert( i_victimGuid );
154 Unit* victim = ObjectAccessor::Instance().GetUnit(i_creature, i_victimGuid );
156 if( !victim )
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());
168 else
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);
177 i_victimGuid = 0;
178 i_creature.AttackStop();