rendered paste bodyIndex: src/framework/Platform/Define.h
===================================================================
--- src/framework/Platform/Define.h (revision 4763)
+++ src/framework/Platform/Define.h (working copy)
@@ -31,6 +31,7 @@
#define MANGOS_IMPORT __cdecl
#define MANGOS_SCRIPT_EXT ".dll"
#define MANGOS_SCRIPT_NAME "MaNGOSScript"
+#define MANGOS_TIER_SCRIPT_NAME "Script"
#define SIGQUIT 3
#else
#define MANGOS_LIBRARY_HANDLE void*
Index: src/game/AggressorAI.cpp
===================================================================
--- src/game/AggressorAI.cpp (revision 4763)
+++ src/game/AggressorAI.cpp (working copy)
@@ -28,129 +28,197 @@
#include <list>
-int
-AggressorAI::Permissible(const Creature *creature)
+int AggressorAI::Permissible(const Creature *creature)
{
// have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight
- if( !creature->isCivilian() && !creature->IsNeutralToAll() )
+ if( !creature->isCivilian() && !creature->IsNeutralToAll() && !creature->m_creatureSpellBook )
return PERMIT_BASE_PROACTIVE;
return PERMIT_BASE_NO;
}
-AggressorAI::AggressorAI(Creature &c) : i_creature(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK)
+AggressorAI::AggressorAI(Creature &c) : i_creature(c), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK)
{
}
-void
-AggressorAI::MoveInLineOfSight(Unit *u)
+void AggressorAI::MoveInLineOfSight(Unit *who)
{
- if( !i_creature.getVictim() && !i_creature.hasUnitState(UNIT_STAT_STUNDED) && u->isTargetableForAttack() &&
- ( i_creature.IsHostileTo( u ) /*|| u->getVictim() && i_creature.IsFriendlyTo( u->getVictim() )*/ ) &&
- u->isInAccessablePlaceFor(&i_creature) )
+ //Planning something to get Rid of all Z check like that will be great since it wrong, GS
+ if( !i_creature.HasPathTo(who) )
+ return;
+
+ if( !i_creature.GetUInt64Value(UNIT_FIELD_TARGET) )
{
- float attackRadius = i_creature.GetAttackDistance(u);
- if(i_creature.IsWithinDistInMap(u, attackRadius) && i_creature.GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE)
+ //MoveInLineOfSight Normal
+ if( i_creature.IsHostileTo(who) && who->isInAccessablePlaceFor(&i_creature) )
{
- if(!i_creature.IsWithinLOSInMap(u)) return;
- AttackStart(u);
- u->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
+ float _attackRadius = i_creature.GetAttackDistance(who);
+ // Without AggroRate will be much Better and I Sugest we remove
+ if( i_creature.IsWithinDistInMap(who, _attackRadius) )
+ {
+ if(!i_creature.IsWithinLOSInMap(who))
+ return;
+
+ if( who->HasStealthAura() )
+ who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
+ selectedAttackRadius = _attackRadius;
+ AttackStart(who);
+ AIMotionTarget(who,FOLLOW_RANGE_MELEE);
+ }
+ //RunAway In Fear, TODO: Check for Attacker List if not empty and we are not in, Stop That and Attack
+ //_attackRadius + RUNAWAY_AGGRO_RANGE, More you put more creature has chance to runaway and from far
+ //_attackRadius <= irand(5,10) , from witch player they runaway... i use same system as aggrorange
+ else if( _attackRadius <= irand(0,10)
+ && who->GetTypeId() == TYPEID_PLAYER
+ && i_creature.IsWithinDistInMap(who, _attackRadius + RUNAWAY_AGGRO_RANGE)
+ && !i_creature.HasAura(CREATURE_SPELL_RUNAWAY,0) )
+ {
+ float X,Y,Z;
+ i_creature.GetRespawnCoord(X,Y,Z);
+ selectedAttackRadius = _attackRadius;
+ if(who->GetDistance2d(X,Y) < RANGE_MAX_AUTO_FEAR)
+ i_creature.CastSpell( (Unit*)&i_creature, CREATURE_SPELL_RUNAWAY, false ,NULL,NULL, who->GetGUID());
+ }
+ return;
}
+ //MoveInLineOfSight Friendly
+ //TODO: hasHealer must be gone away and m_assistance, redesing, GS
+ if( i_creature.IsWithinDistInMap(who,RANGE_AUTO_ASSIST ) && i_creature.IsFriendlyTo(who) && !who->m_hasHealer ) //!irand(0,20) , can be used for Strongnest Adjustement, less Chance more easy
+ {
+ if(!i_creature.IsWithinLOSInMap(who))
+ return;
+
+ //TODO: make it with IsInCombat() + Take target from AttackerList.
+ Unit *victimTarget = who->getVictim();
+ if( who->getVictim() )
+ {
+ if( i_creature.IsHostileTo(victimTarget) )
+ {
+ AttackStart( victimTarget );
+ AIMotionTarget(victimTarget,FOLLOW_RANGE_MELEE);
+ //That is Ugly, i think i can obtain my status into another check with a Operator Overload
+ //So temporary i will let it there.
+ if( who->GetTypeId() == TYPEID_UNIT && ((Creature*)who)->m_AssistenceStatus->requested )
+ ((Creature*)who)->m_AssistenceStatus->obtained = true;
+ }
+ }
+ }
}
}
void AggressorAI::EnterEvadeMode()
{
- if( !i_creature.isAlive() )
- {
- DEBUG_LOG("Creature stopped attacking cuz his dead [guid=%u]", i_creature.GetGUIDLow());
- i_victimGuid = 0;
- i_creature.CombatStop(true);
- i_creature.DeleteThreatList();
+ lastAction = getMSTime()+30000;
+ i_creature.m_AssistenceStatus->reset(); //TODO: fix that scruct, at least make it proctected
+ if( !i_creature.isCharmed() )
+ i_creature.RemoveAllAuras();
+ i_creature.DeleteThreatList();
+ i_creature.CombatStop(true);
+}
+
+void AggressorAI::UpdateAI(const uint32 /*diff*/)
+{
+ if( i_creature.isDead() || i_creature.hasUnitState( UNIT_STAT_FLEEING ) )
return;
- }
- Unit* victim = ObjectAccessor::Instance().GetUnit(i_creature, i_victimGuid );
-
- if( !victim )
- {
- DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature.GetGUIDLow());
+ //RunAway At friend
+ //Unit::getHpPercent(&i_creature)+irand(10,20), can really change the Strongest.
+ if( !i_creature.hasUnitState( UNIT_STAT_ROOT ) && selectedAttackRadius <= irand(0,40) && i_creature.getVictim() && Unit::getHpPercent(&i_creature)+irand(10,20) < Unit::getHpPercent(i_creature.getVictim()) )
+ {
+ //i_creature.getVictim()->getAttackers().size() < 3 , can radicaly change the Strongest
+ if( !i_creature.m_AssistenceStatus->requested && i_creature.getVictim()->getAttackers().size() < 2)
+ {
+ i_creature.CastSpell( (Unit*)&i_creature, CREATURE_SPELL_TAP_FRIEND, false );
+ i_creature.m_AssistenceStatus->requested = true;
+ return;
+ }
+ //Check spell http://www.wowhead.com/?spell=32126, who is Flee Combat Much More Better, and keep fear when no combat
+ else if(i_creature.m_AssistenceStatus->obtained = false && Unit::getHpPercent(&i_creature) < irand(7,14) )
+ i_creature.CastSpell( (Unit*)&i_creature, CREATURE_SPELL_RUNAWAY, false ,NULL,NULL, i_creature.GetUInt64Value(UNIT_FIELD_TARGET));
}
- else if( !victim->isAlive() )
+
+ if( i_creature.SelectHostilTarget() && i_creature.getVictim() && i_creature.isAttackReady() && i_creature.IsWithinDistInMap(i_creature.getVictim(), i_creature.GetFloatValue(UNIT_FIELD_COMBATREACH)) )
{
- DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", i_creature.GetGUIDLow());
+ //TODO:Add a Chance To win and Go to Friend.
+ i_creature.AttackerStateUpdate(i_creature.getVictim());
+ i_creature.resetAttackTimer();
+ lastAction = getMSTime();
}
- else if( victim->HasStealthAura() )
- {
- DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_creature.GetGUIDLow());
- }
- else if( victim->isInFlight() )
- {
- DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_creature.GetGUIDLow());
- }
- else
- {
- DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", i_creature.GetGUIDLow());
- //i_state = STATE_LOOK_AT_VICTIM;
- //i_tracker.Reset(TIME_INTERVAL_LOOK);
- }
- if(!i_creature.isCharmed())
+ //Wait Time Reset Action Selected, TODO: Change that to put more dynamic action at different timer.
+ //A text Chat can be done there, will be cool.
+ //Do search on wowhead for Gossip before any chat text system.
+ if(lastAction+irand(5000*CREATURE_WAIT_RATE,7000*CREATURE_WAIT_RATE) < getMSTime() )
{
- i_creature.RemoveAllAuras();
+ i_creature.m_AssistenceStatus->reset();
- // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
- if( i_creature.GetMotionMaster()->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE )
- i_creature.GetMotionMaster()->TargetedHome();
+ i_creature.SelectHostilTarget();
+
+ lastAction = getMSTime();
}
+}
- i_creature.DeleteThreatList();
- i_victimGuid = 0;
- i_creature.CombatStop(true);
-
+bool AggressorAI::IsVisible(Unit *pl) const
+{
+ return i_creature.GetDistanceSq(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER)
+ && pl->isVisibleForOrDetect(&i_creature,true);
}
-void
-AggressorAI::UpdateAI(const uint32 /*diff*/)
+void AggressorAI::AttackStart(Unit *unit)
{
- // update i_victimGuid if i_creature.getVictim() !=0 and changed
- if(!i_creature.SelectHostilTarget() || !i_creature.getVictim())
+ if( !unit )
return;
- i_victimGuid = i_creature.getVictim()->GetGUID();
-
- if( i_creature.IsWithinDistInMap(i_creature.getVictim(), ATTACK_DISTANCE))
+ if( unit->isTargetableForAttack() /*&& attacker!= m_creature, That should not happen*/ )
{
- if( i_creature.isAttackReady() )
+ if ( i_creature.Attack(unit) )
{
- i_creature.AttackerStateUpdate(i_creature.getVictim());
+ i_creature.AddThreat(unit, 0.0f);
i_creature.resetAttackTimer();
+
+ if (unit->GetTypeId() == TYPEID_PLAYER)
+ i_creature.SetLootRecipient((Player*)unit);
+ selectedAttackRadius = i_creature.GetAttackDistance(unit);
+ AIMotionTarget(unit,FOLLOW_RANGE_MELEE);
+
+ return;
}
}
}
-bool
-AggressorAI::IsVisible(Unit *pl) const
+void AggressorAI::AIMotionTarget(Unit* target, float offSet)
{
- return i_creature.GetDistanceSq(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER)
- && pl->isVisibleForOrDetect(&i_creature,true);
-}
+ bool exist = false;
+ MotionMaster* creatureMM = i_creature.GetMotionMaster();
-void
-AggressorAI::AttackStart(Unit *u)
-{
- if( !u )
- return;
+ if(!target /*&& creatureMM->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE*/)
+ {
+ //creatureMM->MovementExpired();
+ return;
+ }
+ //Here is wrong... TODO fix angle... but in fact i wan MV for Follower and One for Attacker.
+ float angle = NULL;
+ if( !i_creature.IsHostileTo(target) )
+ {
+ angle = target->GetOrientation()*2.0f;
+ }
- if(i_creature.Attack(u))
+ if(creatureMM->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE)
{
- i_creature.AddThreat(u, 0.0f);
- // DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", i_creature.GetName(), u->GetGUIDLow());
- i_victimGuid = u->GetGUID();
-
- i_creature.resetAttackTimer();
- i_creature.GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*u));
- if (u->GetTypeId() == TYPEID_PLAYER)
- i_creature.SetLootRecipient((Player*)u);
+ TargetedMovementGenerator<Creature>* targetMV = static_cast<TargetedMovementGenerator<Creature>*> (creatureMM->top());
+ if( targetMV && targetMV->GetTarget() )
+ {
+ if( targetMV->GetTarget()->GetGUID() != target->GetGUID() )
+ {
+ creatureMM->MovementExpired(false);
+ creatureMM->Mutate(new TargetedMovementGenerator<Creature>(*target,offSet,angle));
+ }
+ else if(targetMV->GetOffSet() != offSet)
+ targetMV->SetOffSet(offSet);
+ }
}
+ else
+ {
+ i_creature.GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*target,offSet,angle));
+ }
}
Index: src/game/AggressorAI.h
===================================================================
--- src/game/AggressorAI.h (revision 4763)
+++ src/game/AggressorAI.h (working copy)
@@ -45,8 +45,10 @@
static int Permissible(const Creature *);
private:
+ void AIMotionTarget(Unit* target, float offSet);
Creature &i_creature;
- uint64 i_victimGuid;
+ uint32 lastAction;
+ float selectedAttackRadius;
AggressorState i_state;
TimeTracker i_tracker;
};
Index: src/game/AggressorCasterAI.cpp
===================================================================
--- src/game/AggressorCasterAI.cpp (revision 0)
+++ src/game/AggressorCasterAI.cpp (revision 0)
@@ -0,0 +1,792 @@
+/*
+ * Copyright (C) 2005,2006,2007 MaNGOS <http://www.mangosproject.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "AggressorCasterAI.h"
+#include "Errors.h"
+#include "Creature.h"
+#include "Player.h"
+#include "TargetedMovementGenerator.h"
+#include "ConfusedMovementGenerator.h"
+#include "RandomMovementGenerator.h"
+#include "HomeMovementGenerator.h"
+#include "Database/DBCStores.h"
+#include "ObjectAccessor.h"
+#include "VMapFactory.h"
+#include "World.h"
+
+#include <list>
+
+int AggressorCasterAI::Permissible(const Creature *creature)
+{
+ // have some hostile factions, it will be selected by IsHostileTo check at MoveInLineOfSight
+ if( !creature->isCivilian() && !creature->IsNeutralToAll() && creature->m_creatureSpellBook )
+ return PERMIT_BASE_PROACTIVE;
+
+ return PERMIT_BASE_NO;
+}
+
+AggressorCasterAI::AggressorCasterAI(Creature &c) : spellCasting(new CreatureSpellCasting(c.m_creatureSpellBook)),
+i_creature(c), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK),
+selectedAttackRadius(100.0f),lastAction(0) {}
+
+void AggressorCasterAI::MoveInLineOfSight(Unit *who)
+{
+ //Planning something to get Rid of all Z check like that will be great since it wrong, GS
+ if( !i_creature.HasPathTo(who) )
+ return;
+
+ if( !i_creature.GetUInt64Value(UNIT_FIELD_TARGET) )
+ {
+ //MoveInLineOfSight Normal
+ if( i_creature.IsHostileTo(who) && who->isInAccessablePlaceFor(&i_creature) )
+ {
+ float _attackRadius = i_creature.GetAttackDistance(who);
+ // Without AggroRate will be much Better and I Sugest we remove
+ if( i_creature.IsWithinDistInMap(who, _attackRadius) )
+ {
+ if(!i_creature.IsWithinLOSInMap(who))
+ return;
+
+ if( who->HasStealthAura() )
+ who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
+ AttackStart(who);
+ selectedAttackRadius = _attackRadius;
+ if(i_creature.m_creatureSpellBook)
+ AIMotionTarget(who,FOLLOW_RANGE_CASTER);
+ else
+ AIMotionTarget(who,FOLLOW_RANGE_MELEE);
+ }
+ //RunAway In Fear, TODO: Check for Attacker List if not empty and we are not in, Stop That and Attack
+ else if( _attackRadius <= irand(0,10)
+ && who->GetTypeId() == TYPEID_PLAYER
+ && i_creature.IsWithinDistInMap(who, _attackRadius + RUNAWAY_AGGRO_RANGE)
+ && !i_creature.HasAura(CREATURE_SPELL_RUNAWAY,0) )
+ {
+
+ float X,Y,Z;
+ i_creature.GetRespawnCoord(X,Y,Z);
+ selectedAttackRadius = _attackRadius;
+ if(who->GetDistance2d(X,Y) < RANGE_MAX_AUTO_FEAR)
+ i_creature.CastSpell( (Unit*)&i_creature, CREATURE_SPELL_RUNAWAY, false ,NULL,NULL, who->GetGUID());
+ }
+ return; //Maybe put dynamic Cast on enemy here.
+ }
+ //MoveInLineOfSight Friendly
+ if( i_creature.IsWithinDistInMap(who,RANGE_AUTO_ASSIST ) && i_creature.IsFriendlyTo(who) && ( !who->m_hasHealer || !irand(0,20) ) ) //!irand(0,20) , can be used for Strongnest Adjustement, less Chance more easy
+ {
+ if(!i_creature.IsWithinLOSInMap(who))
+ return;
+
+ //TODO: make it with IsInCombat() + Take target from AttackerList.
+ Unit *victimTarget = who->getVictim();
+ if( who->getVictim() )
+ {
+ if( i_creature.IsHostileTo(victimTarget) )
+ {
+ if( spellCasting->spellBook && spellCasting->spellBook->hasHealing() && Unit::getMpPercent(&i_creature) > 10 )
+ {
+ i_creature.SetUInt64Value( UNIT_FIELD_TARGET, who->GetGUID() );
+ who->m_hasHealer = true;
+ if(i_creature.m_creatureSpellBook)
+ AIMotionTarget(who,FOLLOW_RANGE_CASTER);
+ else
+ AIMotionTarget(who,FOLLOW_RANGE_MELEE);
+ AISelectSpell( spellCasting );
+ }
+ else
+ {
+ AttackStart( victimTarget );
+ if(i_creature.m_creatureSpellBook)
+ AIMotionTarget(victimTarget,FOLLOW_RANGE_CASTER);
+ else
+ AIMotionTarget(victimTarget,FOLLOW_RANGE_MELEE);
+ }
+ //That is Ugly, i think i can obtain my status into another check with a Operator Overload
+ //So temporary i will let it there.
+ if( who->GetTypeId() == TYPEID_UNIT && ((Creature*)who)->m_AssistenceStatus->requested )
+ ((Creature*)who)->m_AssistenceStatus->obtained = true;
+ }
+ }
+ else if(spellCasting->spellBook && Unit::getHpPercent(who) < 100 ) //Target is IDLE Around we Heal Of Buff if we can
+ AISelectSpell( spellCasting, who );
+ }
+ }
+
+ //That has fucking too much check, must found the fastes way to dynamic heal...
+ //We are probaly doing something, event if, we try to do something on a dynamic target
+ if( i_creature.IsWithinDistInMap(who, RANGE_DYNAMIC_ASSIST ) && i_creature.IsFriendlyTo(who) )
+ {
+ if(!i_creature.IsWithinLOSInMap(who))
+ return;
+
+ if( who->getVictim() && i_creature.IsFriendlyTo(who->getVictim()))
+ return;
+ else if( Unit::getHpPercent(who) < 100 && spellCasting->spellBook
+ && spellCasting->spellBook->hasHealing()
+ && Unit::getMpPercent(&i_creature) > 10 && !irand(0,10))
+ {
+ if( spellCasting->spellIndex > -1 )
+ {
+ if( !spellCasting->reached ) //We cancel Current spell Only if not allready into casting Timer
+ spellCasting->reset();
+ else
+ return;
+ }
+ AISelectSpell( spellCasting, who );
+ return;
+ }
+ }
+ //TODO:Dynamic cast on Enemy should not be needed ... but will test to see result.
+}
+void AggressorCasterAI::EnterEvadeMode()
+{
+ spellCasting->reset(true);
+ lastAction = getMSTime()+30000;
+ i_creature.m_AssistenceStatus->reset(); //TODO: fix that scruct, at least make it proctected
+ if( !i_creature.isCharmed() )
+ i_creature.RemoveAllAuras();
+ i_creature.DeleteThreatList();
+ i_victimGuid = 0;
+ i_creature.CombatStop(true);
+}
+void AggressorCasterAI::UpdateAI(const uint32 diff)
+{
+ if( i_creature.isDead() || i_creature.hasUnitState( UNIT_STAT_FLEEING ) )
+ return;
+
+ //RunAway At friend
+ if( !i_creature.hasUnitState( UNIT_STAT_ROOT ) && selectedAttackRadius <= irand(0,40) && i_creature.getVictim() && Unit::getHpPercent(&i_creature)+irand(1,20) < Unit::getHpPercent(i_creature.getVictim()) )
+ {
+ if( !i_creature.m_AssistenceStatus->requested )
+ {
+ i_creature.CastSpell( (Unit*)&i_creature, CREATURE_SPELL_TAP_FRIEND, false );
+ i_creature.m_AssistenceStatus->requested = true;
+ return;
+ }
+ //Check spell http://www.wowhead.com/?spell=32126, who is Flee Combat Much More Better, and keep fear when no combat
+ else if(i_creature.m_AssistenceStatus->obtained = false && Unit::getHpPercent(&i_creature) < irand(7,14) )
+ i_creature.CastSpell( (Unit*)&i_creature, CREATURE_SPELL_RUNAWAY, false ,NULL,NULL, i_creature.GetUInt64Value(UNIT_FIELD_TARGET));
+ }
+
+ //Spell Casting
+ //Check spell: http://www.wowhead.com/?spell=39258
+ //root spell should be putted by AICast() and Aura Time Controled with the Spell Timer we gonna cast
+ // so 1 check in less into MV for Spellcasting for Monster, Much more better
+ //All this will go Into Spellcasting Scructure or will become a class with self update at the end.
+ //remember
+ if(spellCasting->spellIndex > -1)
+ {
+ //Dynamic Target Check, In Fact is too be sure we don't change target or move during action on Dynamic target
+ //Procedure where made fast and will be need to be symplifie for better reading.
+ Unit *target = i_creature.GetUnit( i_creature,i_creature.GetUInt64Value(UNIT_FIELD_TARGET) );
+ Unit *spellTarget = NULL;
+
+ if( spellCasting->targetGUID != i_creature.GetGUID() )
+ spellTarget = i_creature.GetUnit(i_creature,spellCasting->targetGUID );
+ else
+ spellTarget = ((Unit*)&i_creature);
+
+ bool dynamicTarget = false;
+ if(spellCasting->targetGUID != i_creature.GetGUID() && spellCasting->targetGUID != i_creature.GetUInt64Value(UNIT_FIELD_TARGET))
+ dynamicTarget = true;
+
+ if(spellTarget)
+ {
+ if( !spellCasting->reached )
+ {
+ if(dynamicTarget)
+ {
+ if( i_creature.IsWithinDistInMap(spellTarget, spellCasting->range) )
+ spellCasting->reached = true;
+ else
+ {
+ spellCasting->reset();
+ return;
+ }
+ }
+ else
+ {
+ if( spellTarget->GetGUID() == i_creature.GetGUID() || i_creature.IsWithinDistInMap(spellTarget, spellCasting->range) )
+ spellCasting->reached = true;
+ else
+ {
+ spellCasting->runningTimer += diff;
+ if(spellCasting->runningTimer > irand(500*CREATURE_WAIT_REACH_RATE,1000*CREATURE_WAIT_REACH_RATE) )
+ {
+ //need Speed To reach target, so we cancel Current Spell and try Speed Up.
+ //DoDoSay("Too Long To Reach Target, IsStopped:%u ",i_creature.IsStopped());
+ spellCasting->runningTimer = 0;
+ spellCasting->reset();
+
+ //Not check spellBook since we are here mean she go one for sure... But Maybe i forget something
+ if( i_creature.m_creatureSpellBook->hasSpeed() && !i_creature.hasUnitState( UNIT_STAT_ROOT ) )
+ {
+ spellCasting->reset();
+ AISelectSpell(spellCasting, spellTarget, SELECTSPELL_SPEED);
+ return;
+ }
+ //TODO:
+ //Else If CreatureSpeed < TargetSpeed , Chance To Cast Combat OUT Spell.
+ }
+ //return;
+ }
+ }
+ }
+ if( spellCasting->reached )
+ {
+ if(!spellCasting->started)
+ {
+ //Aura Control for Root or we can get conflit with spellRoot and unroot before time after casting
+ if(!i_creature.hasUnitState(UNIT_STAT_ROOT) && spellCasting->spellBook->info[spellCasting->spellIndex].hasCastTime)
+ {
+ //i_creature.SendMonsterMove(i_creature.GetPositionX(),i_creature.GetPositionY(),i_creature.GetPositionZ(),0,true,0);
+ //i_creature.Relocate(i_creature.GetPositionX(),i_creature.GetPositionY(),i_creature.GetPositionZ());
+ i_creature.addUnitState(UNIT_STAT_ROOT);
+ i_creature.StopMoving();
+ }
+ AICast(spellCasting);
+ lastAction = getMSTime();
+ return;
+ }
+ //Spell Finish
+ else if( i_creature.m_currentSpells[CURRENT_GENERIC_SPELL] )
+ {
+ if( !i_creature.HasSpellChannelActiveTimer() )
+ {
+ //TODO: Change Offset after a spell so we look more alive.
+ //if(!dynamicTarget && target && target->isAlive() && i_creature.hasUnitState(UNIT_STAT_FOLLOW))
+ //AIMotionTarget(target, rand_norm()*(spellCasting->range));
+ if(!i_creature.HasAuraType(SPELL_AURA_MOD_ROOT))
+ i_creature.clearUnitState(UNIT_STAT_ROOT);
+ spellCasting->reset();
+ }
+ return;
+ }
+ else
+ {
+ i_creature.clearUnitState(UNIT_STAT_ROOT);
+ spellCasting->reset();
+ //if(!dynamicTarget && target && target->isAlive() && i_creature.hasUnitState(UNIT_STAT_FOLLOW))
+ //AIMotionTarget(target);
+ return;
+ }
+ }
+ }
+ else if(dynamicTarget) //Bad dynamicTarget Target
+ {
+ if(!spellCasting->reached)
+ spellCasting->reset();
+ }
+ else //Bad Target
+ {
+ if(!spellCasting->reached)
+ spellCasting->reset(true);
+ }
+ //return;
+ }
+
+ //Melee Attack
+ //AICheckFriendTarget(), TODO:remove that from here.... My probleme is the Threath List will remove friend target
+ if( /*!AICheckFriendTarget()*/i_creature.SelectHostilTarget() && i_creature.getVictim() /*&& AICheckVictimTarget()*/ && i_creature.isAttackReady() && i_creature.IsWithinDistInMap(i_creature.getVictim(), i_creature.GetFloatValue(UNIT_FIELD_COMBATREACH)) )
+ {
+ if(i_creature.getVictim()->HasSpellChannelActiveTimer() && i_creature.m_creatureSpellBook && i_creature.m_creatureSpellBook->hasInterrupt())
+ {
+ spellCasting->reset(); //TODO:Check we are casting or not before reset.
+ AISelectSpell( spellCasting, i_creature.getVictim(), SELECTSPELL_INTERRUPT);
+ return;
+ }
+ //Add a Chance To win and Go to Friend.
+
+ i_creature.AttackerStateUpdate(i_creature.getVictim());
+ i_creature.resetAttackTimer();
+ lastAction = getMSTime();
+
+ }
+
+ //Choses a Spell To Cast
+ if( spellCasting->spellIndex < 0 && i_creature.GetUInt64Value(UNIT_FIELD_TARGET) )
+ AISelectSpell( spellCasting );
+
+ //Wait Time Reset Action Selected, TODO: Change that to put more dynamic action at different timer.
+ //A text Chant can be done there, will be cool.
+ if(lastAction+irand(5000*CREATURE_WAIT_RATE,7000*CREATURE_WAIT_RATE) < getMSTime() )
+ {
+ i_creature.m_AssistenceStatus->reset();
+ if( spellCasting->spellIndex > -1 )
+ {
+ if( !spellCasting->reached )
+ spellCasting->reset();
+ else
+ return;
+ }
+
+ if( AICheckFriendTarget() )
+ {
+ Unit* friendTarget = i_creature.GetUnit(i_creature, i_creature.GetUInt64Value(UNIT_FIELD_TARGET));
+ if( friendTarget && friendTarget->getVictim() )
+ {
+ AISelectSpell(spellCasting,friendTarget->getVictim());
+ }
+ else if(friendTarget && Unit::getHpPercent(friendTarget) > irand(90,99))
+ {
+ friendTarget->m_hasHealer = false;
+ i_creature.SelectHostilTarget();
+ }
+ }
+ else
+ i_creature.SelectHostilTarget();
+
+ lastAction = getMSTime();
+ }
+}
+void AggressorCasterAI::DamageTaken(Unit *done_by, uint32 &damage)
+{
+ // Should be Replaced with better Idea...., GS
+ // Make a helper Attack the Persone is attacking him, so next tick he will be a attacker.
+ if( !i_creature.getVictim() && Unit::getHpPercent(&i_creature) < irand(80,99) )
+ {
+ i_creature.SetUInt64Value(UNIT_FIELD_TARGET,0);
+ MoveInLineOfSight(done_by);
+ }
+}
+void AggressorCasterAI::JustDie()
+{
+ // a healer should never ne target by a healer so, else case should be good
+ // More work needed on Healer selection, must be simple and not flood same target for healing purpose, GS
+ if( AICheckFriendTarget() )
+ {
+ Unit* friendTarget = i_creature.GetUnit(i_creature, i_creature.GetUInt64Value(UNIT_FIELD_TARGET));
+ friendTarget->m_hasHealer = false;
+ }
+
+}
+bool AggressorCasterAI::IsVisible(Unit *pl) const
+{
+ return i_creature.GetDistanceSq(pl) < sWorld.getConfig(CONFIG_SIGHT_MONSTER)
+ && pl->isVisibleForOrDetect(&i_creature,true);
+}
+
+void AggressorCasterAI::AttackStart(Unit *unit)
+{
+ if( !unit )
+ return;
+
+ // AICheckFriendTarget() should not appear here, Must be Checked to be sure she never needed here.
+ if( AICheckFriendTarget() && Unit::getHpPercent(unit) > Unit::getHpPercent(&i_creature)+20 )
+ {
+ i_creature.AddThreat(unit, 0.0f); //target can come from threat, should put at better place
+ return;
+ }
+
+ if( unit->isTargetableForAttack() /*&& attacker!= m_creature, That should not happen*/ )
+ {
+ if ( i_creature.Attack(unit) )
+ {
+ i_creature.AddThreat(unit, 0.0f);
+ i_creature.resetAttackTimer();
+ if (unit->GetTypeId() == TYPEID_PLAYER)
+ i_creature.SetLootRecipient((Player*)unit);
+ selectedAttackRadius = i_creature.GetAttackDistance(unit);
+ if(i_creature.m_creatureSpellBook)
+ AIMotionTarget(unit,FOLLOW_RANGE_CASTER);
+ else
+ AIMotionTarget(unit,FOLLOW_RANGE_MELEE);
+ return;
+ }
+ }
+}
+void AggressorCasterAI::AISelectSpell(CreatureSpellCasting *spellCasting, Unit *dynamicTarget, uint8 specialCase)
+{
+ uint16 chosenSpellId;
+ std::list<uint8> spellIndexFound;
+
+ spellIndexFound.clear();
+
+ if(spellCasting->spellIndex > -1 || !spellCasting->spellBook || i_creature.HasSpellCooldown() )
+ return;
+
+ Unit *enemyTarget = NULL;
+ Unit *friendTarget = NULL;
+ if(dynamicTarget)
+ {
+ if(i_creature.IsHostileTo(dynamicTarget))
+ enemyTarget = dynamicTarget;
+ else
+ friendTarget = dynamicTarget;
+ }
+ else if(AICheckFriendTarget())
+ friendTarget = i_creature.GetUnit(*&i_creature, i_creature.GetUInt64Value(UNIT_FIELD_TARGET));
+ else if(AICheckVictimTarget())
+ enemyTarget = i_creature.getVictim();
+
+ switch( specialCase )
+ {
+ case SELECTSPELL_NONE:
+ break;
+ case SELECTSPELL_SPEED:
+ {
+ spellIndexFound.clear();
+ for(uint8 i = CREATURE_SPELL_SPEED_1; i < CREATURE_SPELL_SPEED_MAX; i++)
+ {
+ CreatureSpellBookInfo *spellInfo = &spellCasting->spellBook->info[i];
+ if( spellInfo->id && !i_creature.HasSpellCooldown(spellInfo->id) && AICheckTakePower(i) )
+ spellIndexFound.push_front(i);
+ }
+ if( spellIndexFound.size() > 0 )
+ {
+ chosenSpellId = 0;
+ std::list<uint8>::iterator itr = spellIndexFound.begin();
+ for (uint8 randomIndex = irand(0,spellIndexFound.size()-1); 0 < randomIndex; --randomIndex)++itr;
+ spellCasting->spellIndex = (*itr);
+ chosenSpellId = spellCasting->spellBook->info[(*itr)].id;
+
+ //DoDoSay("Speed: %u",chosenSpellId);
+ SetSpellMaxRange(spellCasting);
+ if( !(spellCasting->spellBook->info[(*itr)].targets & (1 << (SELECT_TARGET_ANY_FRIEND-1))) )
+ spellCasting->targetGUID = i_creature.GetGUID();
+ else
+ spellCasting->targetGUID = enemyTarget->GetGUID();
+ }
+ }return;
+ case SELECTSPELL_INTERRUPT:
+ {
+ CreatureSpellBookInfo *spellInfo = &spellCasting->spellBook->info[CREATURE_SPELL_INTERRUPT_1];
+ if( spellInfo->id && !i_creature.HasSpellCooldown(spellInfo->id) && AICheckTakePower(CREATURE_SPELL_INTERRUPT_1) )
+ {
+ spellCasting->spellIndex = CREATURE_SPELL_INTERRUPT_1;
+ chosenSpellId = spellInfo->id;
+ SetSpellMaxRange(spellCasting);
+ spellCasting->targetGUID = enemyTarget->GetGUID();
+ }
+ }return;
+ }
+ if( friendTarget )
+ {
+ if( friendTarget->isAlive() )
+ {
+ //heal Friend
+ spellIndexFound.clear();
+ for(uint8 i = CREATURE_SPELL_HEALING_1; i < CREATURE_SPELL_HEALING_MAX; i++)
+ {
+ CreatureSpellBookInfo *spellInfo = &spellCasting->spellBook->info[i];
+ if( spellInfo->id && !i_creature.HasSpellCooldown(spellInfo->id) && AICheckTakePower(i) )
+ spellIndexFound.push_front(i);
+ }
+ if( spellIndexFound.size() > 0 && Unit::getHpPercent(friendTarget) < 70)
+ {
+ chosenSpellId = 0;
+ std::list<uint8>::iterator itr = spellIndexFound.begin();
+ for (uint8 randomIndex = irand(0,spellIndexFound.size()-1); 0 < randomIndex; --randomIndex)++itr;
+ spellCasting->spellIndex = (*itr);
+ chosenSpellId = spellCasting->spellBook->info[(*itr)].id;
+ //DoDoSay("Healing(Friend): %u",chosenSpellId);
+ spellCasting->targetGUID = friendTarget->GetGUID();
+ SetSpellMaxRange(spellCasting);
+ if(!dynamicTarget)
+ AIMotionTarget(friendTarget,(rand_norm()*spellCasting->range)+1.0f);
+ return;
+
+ }
+
+ //Buff Friend
+ spellIndexFound.clear();
+ for(uint8 i = CREATURE_SPELL_BUFF_1; i < CREATURE_SPELL_BUFF_MAX; i++)
+ {
+ CreatureSpellBookInfo *spellInfo = &spellCasting->spellBook->info[i];
+ if( spellInfo->id && !i_creature.HasSpellCooldown(spellInfo->id) && AICheckTakePower(i) )
+ spellIndexFound.push_front(i);
+ }
+ if( spellIndexFound.size() > 0 )
+ {
+ srand(getMSTime());
+ chosenSpellId = 0;
+ std::list<uint8>::iterator itr = spellIndexFound.begin();
+ for (uint8 randomIndex = irand(0,spellIndexFound.size()-1); 0 < randomIndex; --randomIndex)++itr;
+ spellCasting->spellIndex = (*itr);
+ chosenSpellId = spellCasting->spellBook->info[(*itr)].id;
+
+ //DoDoSay("Buff Friend: %u",chosenSpellId);
+ spellCasting->targetGUID = friendTarget->GetGUID();
+ SetSpellMaxRange(spellCasting);
+ if(!dynamicTarget)
+ AIMotionTarget(friendTarget,(rand_norm()*spellCasting->range)+1.0f);
+ return;
+ }
+ }
+ }
+ else if(enemyTarget)
+ {
+ if(!dynamicTarget)
+ {
+ float distance = sqrt(i_creature.GetDistance2dSq(enemyTarget));
+
+ if( !spellCasting->oldTargetRange )
+ spellCasting->oldTargetRange = distance;
+
+ // Target Is Casting a Channeled Spell
+ if( enemyTarget->HasSpellChannelActiveTimer() )
+ {
+ //Cast Intterupted Spell if we have available
+ }
+ // Target Is Running Away, try speed-up to get to her.
+ // Far from what i wan... Need to correct that situation
+
+
+ //Potentiel Charge, but for sure Target is comming to Us
+ // Far from what i wan... Need to correct that situation
+ if( distance < spellCasting->oldTargetRange /*&& !enemyTarget->IsStopped()*/)
+ {
+ spellCasting->oldTargetRange = distance;
+
+ spellIndexFound.clear();
+ for(uint8 i = CREATURE_SPELL_STUNT_1; i < CREATURE_SPELL_STUNT_MAX; i++)
+ {
+ CreatureSpellBookInfo *spellInfo = &spellCasting->spellBook->info[i];
+ if( spellInfo->id && !i_creature.HasSpellCooldown(spellInfo->id) && AICheckTakePower(i) )
+ spellIndexFound.push_front(i);
+ }
+ if( spellIndexFound.size() > 0 )
+ {
+ srand(getMSTime());
+ chosenSpellId = 0;
+ std::list<uint8>::iterator itr = spellIndexFound.begin();
+ for (uint8 randomIndex = irand(0,spellIndexFound.size()-1); 0 < randomIndex; --randomIndex)++itr;
+ spellCasting->spellIndex = (*itr);
+ chosenSpellId = spellCasting->spellBook->info[(*itr)].id;
+
+ //DoDoSay("Stun: %u",chosenSpellId);
+ SetSpellMaxRange(spellCasting);
+ if( !(spellCasting->spellBook->info[chosenSpellId].targets & (1 << (SELECT_TARGET_SELF-1))) )
+ spellCasting->targetGUID = i_creature.GetGUID();
+ else
+ {
+ AIMotionTarget(enemyTarget,(rand_norm()*spellCasting->range)+1.0f);
+ spellCasting->targetGUID = enemyTarget->GetGUID();
+ }
+ //spellCasting->spellBook->castingTimer = spellCasting->spellBook->info[(*itr)].castingTime;
+ spellCasting->targetGUID = enemyTarget->GetGUID();
+ return;
+ }
+ }
+ }
+ //Healing
+ if( Unit::getHpPercent(&i_creature) < irand(40,90) )
+ {
+ spellIndexFound.clear();
+ for(uint8 i = CREATURE_SPELL_HEALING_1; i < CREATURE_SPELL_HEALING_MAX; i++)
+ {
+ CreatureSpellBookInfo *spellInfo = &spellCasting->spellBook->info[i];
+ if( spellInfo->id && !i_creature.HasSpellCooldown(spellInfo->id) && AICheckTakePower(i) )
+ spellIndexFound.push_front(i);
+ }
+ if( spellIndexFound.size() > 0 )
+ {
+ srand(getMSTime());
+ chosenSpellId = 0;
+ std::list<uint8>::iterator itr = spellIndexFound.begin();
+ for (uint8 randomIndex = irand(0,spellIndexFound.size()-1); 0 < randomIndex; --randomIndex)++itr;
+ spellCasting->spellIndex = (*itr);
+ chosenSpellId = spellCasting->spellBook->info[(*itr)].id;
+ //DoDoSay("Healing: %u",chosenSpellId);
+ //spellCasting->spellBook->castingTimer = spellCasting->spellBook->info[(*itr)].castingTime;
+ spellCasting->targetGUID = i_creature.GetGUID();
+ SetSpellMaxRange(spellCasting);
+ return;
+ }
+
+ }
+ else //Buff
+ {
+ spellIndexFound.clear();
+ for(uint8 i = CREATURE_SPELL_BUFF_1; i < CREATURE_SPELL_BUFF_MAX; i++)
+ {
+ CreatureSpellBookInfo *spellInfo = &spellCasting->spellBook->info[i];
+ if( spellInfo->id && !i_creature.HasSpellCooldown(spellInfo->id) && AICheckTakePower(i) )
+ spellIndexFound.push_front(i);
+ }
+ if( spellIndexFound.size() > 0 )
+ {
+ srand(getMSTime());
+ chosenSpellId = 0;
+ std::list<uint8>::iterator itr = spellIndexFound.begin();
+ for (uint8 randomIndex = irand(0,spellIndexFound.size()-1); 0 < randomIndex; --randomIndex)++itr;
+ spellCasting->spellIndex = (*itr);
+ chosenSpellId = spellCasting->spellBook->info[(*itr)].id;
+ //DoDoSay("Buff: %u",chosenSpellId);
+ //spellCasting->spellBook->castingTimer = spellCasting->spellBook->info[(*itr)].castingTime;
+ spellCasting->targetGUID = i_creature.GetGUID();
+ SetSpellMaxRange(spellCasting);
+ return;
+ }
+ }
+
+ //Attack Spell
+ spellIndexFound.clear();
+ for(uint8 i = CREATURE_SPELL_ATTACK_1; i < CREATURE_SPELL_ATTACK_MAX; i++)
+ {
+ CreatureSpellBookInfo *spellInfo = &spellCasting->spellBook->info[i];
+ if( spellInfo->id && !i_creature.HasSpellCooldown(spellInfo->id) && AICheckTakePower(i) )
+ spellIndexFound.push_front(i);
+ }
+ if( spellIndexFound.size() )
+ {
+ srand(getMSTime());
+ chosenSpellId = 0;
+ std::list<uint8>::iterator itr = spellIndexFound.begin();
+ for (uint8 randomIndex = irand(0,spellIndexFound.size()-1); 0 < randomIndex; --randomIndex)++itr;
+ spellCasting->spellIndex = (*itr);
+ chosenSpellId = spellCasting->spellBook->info[(*itr)].id;
+
+ //DoDoSay("Attack: %u",chosenSpellId);
+ spellCasting->targetGUID = enemyTarget->GetGUID();
+ SetSpellMaxRange(spellCasting);
+ if(!dynamicTarget)
+ AIMotionTarget(enemyTarget,spellCasting->range/1.1f);
+ return;
+ }
+
+ if(!dynamicTarget && i_creature.IsStopped()) //Debug, got to be removed...
+ AIMotionTarget(enemyTarget,1.5f);
+ }
+}
+
+void AggressorCasterAI::AICast(CreatureSpellCasting *spellCasting)
+{
+ Unit *target = i_creature.GetUnit((i_creature),spellCasting->targetGUID);
+
+ if( !target || !AICheckTakePower(spellCasting->spellIndex, true) )
+ {
+ spellCasting->reset();
+ return;
+ }
+ i_creature.CastSpell(target, spellCasting->spellBook->info[spellCasting->spellIndex].id, false);
+ spellCasting->started = true;
+}
+void AggressorCasterAI::AIMotionTarget(Unit* target, float offSet)
+{
+ bool exist = false;
+ MotionMaster* creatureMM = i_creature.GetMotionMaster();
+
+ if(!target /*&& creatureMM->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE*/)
+ {
+ //creatureMM->MovementExpired();
+ return;
+ }
+
+ float angle = NULL;
+ if( !i_creature.IsHostileTo(target) )
+ {
+ angle = target->GetOrientation()*2.0f;
+ }
+
+ if(creatureMM->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ {
+ TargetedMovementGenerator<Creature>* targetMV = static_cast<TargetedMovementGenerator<Creature>*> (creatureMM->top());
+ if( targetMV && targetMV->GetTarget() )
+ {
+ if( targetMV->GetTarget()->GetGUID() != target->GetGUID() )
+ {
+ creatureMM->MovementExpired(false);
+ creatureMM->Mutate(new TargetedMovementGenerator<Creature>(*target,offSet,angle));
+ }
+ else if(targetMV->GetOffSet() != offSet)
+ targetMV->SetOffSet(offSet);
+ }
+ }
+ else
+ {
+ i_creature.GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*target,offSet,angle));
+ }
+}
+
+bool AggressorCasterAI::AICheckFriendTarget()
+{
+ //Probaly make that function Usable only into Update(), save The status, cause into MoveInLineOfSight(), will be check too much time for nothing.
+ //friend target not found so we reset Status of Friend Follow.
+ if( !i_creature.getVictim() && i_creature.GetUInt64Value(UNIT_FIELD_TARGET) )
+ {
+ Unit* friendTarget = i_creature.GetUnit( i_creature, i_creature.GetUInt64Value(UNIT_FIELD_TARGET) );
+ if( friendTarget && friendTarget->isAlive() && friendTarget->isInCombat() && !i_creature.IsHostileTo(friendTarget) && i_creature.IsWithinDistInMap(friendTarget,35.0f))
+ return true;
+ else
+ {
+ if(friendTarget)
+ friendTarget->m_hasHealer = false;
+ i_creature.SetUInt64Value(UNIT_FIELD_TARGET,0);
+ AIMotionTarget(NULL,NULL);
+ }
+ }
+ return false;
+}
+bool AggressorCasterAI::AICheckVictimTarget()
+{
+ //Check if we have a current target
+ if( i_creature.getVictim() )
+ {
+ //debug Line to help find why sometime MV target is not Creature Target
+ if( i_creature.GetUInt64Value(UNIT_FIELD_TARGET) != i_creature.getVictim()->GetGUID() )
+ i_creature.SetUInt64Value(UNIT_FIELD_TARGET, i_creature.getVictim()->GetGUID());
+
+ if( i_creature.getVictim()->isTargetableForAttack() && i_creature.isAlive())
+ return true;
+ }
+ return false;
+}
+bool AggressorCasterAI::AICheckTakePower(uint8 spellIndex, bool take)
+{
+ uint32 currentPowerValue;
+ // Don't take SpellAddon PowerType, Because can be missing, so is up to us
+ // to not put spell for mage on a warrior.
+ Powers creaturePowerType = i_creature.getPowerType();
+ switch( creaturePowerType )
+ {
+ case POWER_RAGE: currentPowerValue = i_creature.GetPower(POWER_RAGE)/10; break;
+ case POWER_MANA: currentPowerValue = i_creature.GetPower(POWER_MANA); break;
+ case POWER_FOCUS: currentPowerValue = i_creature.GetPower(POWER_FOCUS); break;
+ case POWER_ENERGY: currentPowerValue = i_creature.GetPower(POWER_ENERGY); break;
+ case POWER_HAPPINESS: currentPowerValue = i_creature.GetPower(POWER_HAPPINESS); break;
+ }
+ if( i_creature.m_creatureSpellBook->info[spellIndex].cost > currentPowerValue )
+ return false;
+
+ if( take && !i_creature.m_creatureSpellBook->info[spellIndex].usingDBC )
+ switch(POWER_MANA) //We Only use this one for The Moment
+ {
+ case POWER_RAGE:
+ i_creature.SetPower(creaturePowerType, (currentPowerValue - i_creature.m_creatureSpellBook->info[spellIndex].cost)*10 );break;
+ case POWER_MANA:
+ i_creature.SetPower(creaturePowerType, (currentPowerValue - i_creature.m_creatureSpellBook->info[spellIndex].cost) );break;
+ case POWER_FOCUS:
+ i_creature.SetPower(creaturePowerType, (currentPowerValue - i_creature.m_creatureSpellBook->info[spellIndex].cost) );break;
+ case POWER_ENERGY:
+ i_creature.SetPower(creaturePowerType, (currentPowerValue - i_creature.m_creatureSpellBook->info[spellIndex].cost) );break;
+ case POWER_HAPPINESS:
+ i_creature.SetPower(creaturePowerType, (currentPowerValue - i_creature.m_creatureSpellBook->info[spellIndex].cost) );break;
+ }
+
+ return true;
+}
+
+
+float AggressorCasterAI::SetSpellMaxRange(CreatureSpellCasting *spellCasting)
+{
+ // Not OK ...
+ float _rangeMax = spellCasting->spellBook->info[spellCasting->spellIndex].range[1] - 2.0f;
+ spellCasting->range = _rangeMax < 5.5f ? 5.5f : _rangeMax;
+ return spellCasting->range;
+}
Index: src/game/AggressorCasterAI.h
===================================================================
--- src/game/AggressorCasterAI.h (revision 0)
+++ src/game/AggressorCasterAI.h (revision 0)
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2005,2006,2007 MaNGOS <http://www.mangosproject.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MANGOS_AGGRESSORCASTERAI_H
+#define MANGOS_AGGRESSORCASTERAI_H
+
+#include "Creature.h"
+#include "CreatureAI.h"
+#include "Timer.h"
+
+enum SelectSpellType
+{
+ SELECTSPELL_NONE,
+ SELECTSPELL_SPEED,
+ SELECTSPELL_INTERRUPT
+};
+
+//Will be used like this: CREATURE_GLOBAL_COOLDOWN-(Level*1000)
+#define CREATURE_SPELL_GLOBAL_COOLDOWN 1500
+#define CREATURE_WAIT_REACH_RATE 1
+
+class Creature;
+
+struct CreatureSpellCasting
+{
+ CreatureSpellCasting(CreatureSpellBook *_spellBook) :
+ spellIndex(-1), targetGUID(0), runningTimer(0), oldTargetRange(0.0f),range(0.0f),
+ started(false),reached(false),dynamicTarget(false),spellBook(_spellBook) {}
+
+ int8 spellIndex;
+ uint64 targetGUID;
+ uint32 runningTimer;
+ float oldTargetRange, range;
+ bool started, reached, dynamicTarget;
+ CreatureSpellBook* spellBook;
+
+ void reset(bool resetRange = false)
+ {
+ spellIndex = -1;
+ targetGUID = 0;
+ runningTimer = 0;
+ range = 0.0f;
+ started = false;
+ reached = false;
+ dynamicTarget = false;
+ if(resetRange)
+ oldTargetRange = 0.0f;
+ }
+};
+class MANGOS_DLL_DECL AggressorCasterAI : public CreatureAI
+{
+ enum AggressorState
+ {
+ STATE_NORMAL = 1,
+ STATE_LOOK_AT_VICTIM = 2
+ };
+
+ public:
+
+ AggressorCasterAI(Creature &c);
+
+ void MoveInLineOfSight(Unit *);
+ void AttackStart(Unit *);
+ void EnterEvadeMode();
+ bool IsVisible(Unit *) const;
+ void DamageTaken(Unit *done_by, uint32 &damage);
+ void JustDie();
+ void UpdateAI(const uint32);
+ static int Permissible(const Creature *);
+
+ private:
+ void AISelectAction(Unit* who);
+ void AISelectSpell(CreatureSpellCasting *spellCasting, Unit *target = NULL, uint8 specialCase = 0);
+ void AICast(CreatureSpellCasting *spellCasting);
+ void AIMotionTarget(Unit *target, float offSet = 0.0f);
+ bool AICheckFriendTarget();
+ bool AICheckVictimTarget();
+ bool AICheckTakePower(uint8 spellIndex, bool take = false);
+ float SetSpellMaxRange(CreatureSpellCasting *spellCasting);
+
+ CreatureSpellCasting *spellCasting;
+ Creature &i_creature;
+ uint32 lastAction;
+ uint64 i_victimGuid;
+ float selectedAttackRadius;
+ AggressorState i_state;
+ TimeTracker i_tracker;
+};
+#endif
Index: src/game/ConfusedMovementGenerator.cpp
===================================================================
--- src/game/ConfusedMovementGenerator.cpp (revision 4763)
+++ src/game/ConfusedMovementGenerator.cpp (working copy)
@@ -22,9 +22,7 @@
#include "ConfusedMovementGenerator.h"
#include "DestinationHolderImp.h"
-template<class T>
-void
-ConfusedMovementGenerator<T>::Initialize(T &unit)
+template<class T> void ConfusedMovementGenerator<T>::Initialize(T &unit)
{
const float wander_distance=11;
float x,y,z;
@@ -62,30 +60,22 @@
unit.UpdateGroundPositionZ(i_waypoints[idx][0],i_waypoints[idx][1],z);
i_waypoints[idx][2] = z;
}
-
- unit.StopMoving();
unit.setMoveRunFlag(true);
}
-template<>
-void
-ConfusedMovementGenerator<Creature>::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok)
+template<> void ConfusedMovementGenerator<Creature>::_InitSpecific(Creature &creature, bool &is_water_ok, bool &is_land_ok)
{
is_water_ok = creature.isCanSwimOrFly();
is_land_ok = creature.isCanWalkOrFly();
}
-template<>
-void
-ConfusedMovementGenerator<Player>::_InitSpecific(Player &, bool &is_water_ok, bool &is_land_ok)
+template<> void ConfusedMovementGenerator<Player>::_InitSpecific(Player &, bool &is_water_ok, bool &is_land_ok)
{
is_water_ok = true;
is_land_ok = true;
}
-template<class T>
-void
-ConfusedMovementGenerator<T>::Reset(T &unit)
+template<class T> void ConfusedMovementGenerator<T>::Reset(T &unit)
{
i_nextMove = 1;
i_nextMoveTime.Reset(0);
@@ -93,15 +83,17 @@
unit.StopMoving();
}
-template<class T>
-bool
-ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
+template<class T> bool ConfusedMovementGenerator<T>::Update(T &unit, const uint32 &diff)
{
if(!&unit)
- return true;
- if(unit.hasUnitState(UNIT_STAT_ROOT) || unit.hasUnitState(UNIT_STAT_STUNDED))
- return true;
-
+ return false;
+ //if(unit.hasUnitState(UNIT_STAT_ROOT) || unit.hasUnitState(UNIT_STAT_STUNDED))
+ //return true;
+ if(!unit.HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED))
+ {
+ unit.clearUnitState(UNIT_STAT_CONFUSED);
+ return false;
+ }
if( i_nextMoveTime.Passed() )
{
// currently moving, update location
@@ -110,9 +102,7 @@
{
if( i_destinationHolder.HasArrived())
{
- // arrived, stop and wait a bit
- unit.StopMoving();
-
+ unit.clearUnitState(UNIT_STAT_CONFUSED);
i_nextMove = urand(1,MAX_CONF_WAYPOINTS);
i_nextMoveTime.Reset(urand(0, 1500-1)); // TODO: check the minimum reset time, should be probably higher
}
@@ -129,6 +119,7 @@
const float x = i_waypoints[i_nextMove][0];
const float y = i_waypoints[i_nextMove][1];
const float z = i_waypoints[i_nextMove][2];
+ unit.addUnitState(UNIT_STAT_CONFUSED);
Traveller<T> traveller(unit);
i_destinationHolder.SetDestination(traveller, x, y, z);
}
Index: src/game/ConfusedMovementGenerator.h
===================================================================
--- src/game/ConfusedMovementGenerator.h (revision 4763)
+++ src/game/ConfusedMovementGenerator.h (working copy)
@@ -16,8 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef MANGOS_RANDOMMOTIONGENERATOR_H
-#define MANGOS_RANDOMMOTIONGENERATOR_H
+#ifndef MANGOS_CONFUSEDMOTIONGENERATOR_H
+#define MANGOS_CONFUSEDMOTIONGENERATOR_H
#include "MovementGenerator.h"
#include "DestinationHolder.h"
@@ -35,7 +35,10 @@
void Initialize(T &);
void Reset(T &);
bool Update(T &, const uint32 &);
-
+ void UpdateMapPosition(float &x ,float &y, float &z)
+ {
+ i_destinationHolder.GetLocationNow(x,y,z);
+ }
MovementGeneratorType GetMovementGeneratorType() { return CONFUSED_MOTION_TYPE; }
private:
void _InitSpecific(T &, bool &, bool &);
Index: src/game/Creature.cpp
===================================================================
--- src/game/Creature.cpp (revision 4763)
+++ src/game/Creature.cpp (working copy)
@@ -37,6 +37,7 @@
#include "WaypointMovementGenerator.h"
#include "InstanceData.h"
#include "BattleGround.h"
+#include "spell.h"
// apply implementation of the singletons
#include "Policies/SingletonImp.h"
@@ -56,11 +57,10 @@
for(int i =0; i<4; ++i)
m_spells[i] = 0;
- m_CreatureSpellCooldowns.clear();
m_CreatureCategoryCooldowns.clear();
m_GlobalCooldown = 0;
-
- m_AlreadyCallAssistence = false;
+ m_creatureSpellBook = NULL;
+ m_AssistenceStatus = new AssistenceStatus();
}
Creature::~Creature()
@@ -174,6 +174,7 @@
{
case JUST_DIED:
// Dont must be called, see Creature::setDeathState JUST_DIED -> CORPSE promoting.
+ getHostilRefManager().deleteReferences();
sLog.outError("Creature (GUIDLow: %u Entry: %u ) in wrong state: JUST_DEAD (1)",GetGUIDLow(),GetEntry());
break;
case DEAD:
@@ -204,6 +205,9 @@
if( m_deathTimer <= diff )
{
RemoveCorpse();
+ float x,y,z;
+ GetRespawnCoord(x, y, z);
+ Relocate(x,y,z); //Check this out Use World Relocation if still cool, or GridRelocation and here is probaly Grid needed so..., GS
DEBUG_LOG("Removing corpse... %u ", GetUInt32Value(OBJECT_FIELD_ENTRY));
}
else
@@ -1244,7 +1248,7 @@
// checked at loading
m_defaultMovementType = MovementGeneratorType(cinfo->MovementType);
-
+ m_creatureSpellBook = objmgr.GetCreatureSpellBook(Entry);
//Notify the map's instance data.
//Only works if you create the object in it, not if it is moves to that map.
//Normally non-players do not teleport to other maps.
@@ -1694,14 +1698,13 @@
return false;
}
-void Creature::CallAssistence()
+/*void Creature::CallAssistence()
{
if( !m_AlreadyCallAssistence && getVictim() )
{
- CastSpell(this,SPELL_ID_AGGRO, true, NULL, NULL, getVictim()->GetGUID());
+ //CastSpell(this,SPELL_ID_AGGRO, true, NULL, NULL, getVictim()->GetGUID());
}
-}
-
+}*/
void Creature::SaveRespawnTime()
{
if(isPet())
@@ -1732,7 +1735,10 @@
return false;
float rx,ry,rz;
- GetRespawnCoord(rx, ry, rz);
+ if(isPet() && GetOwner() )
+ GetOwner()->GetPosition(rx,ry,rz);
+ else
+ GetRespawnCoord(rx, ry, rz);
float length = pVictim->GetDistanceSq(rx,ry,rz);
return ( length > 10000.0f); // real value unknown
@@ -1813,14 +1819,39 @@
if(!spellInfo)
return;
- uint32 cooldown = spellInfo->CategoryRecoveryTime > spellInfo->RecoveryTime ? spellInfo->CategoryRecoveryTime : spellInfo->RecoveryTime;
+ uint32 cooldown = 0;
+
+ if(m_creatureSpellBook)
+ {
+ //When Struct SpellCasting Is available into Core, Use Index comming from there
+ //So no use to search the spell we are casting ;), GS
+ CreatureSpellBookInfoMap::const_iterator _info = m_creatureSpellBook->info.begin();
+ for(;_info != m_creatureSpellBook->info.end(); ++_info)
+ {
+ if( _info->second.id == spellid )
+ {
+ cooldown = _info->second.recoveryTime;
+ break;
+ }
+ }
+ }
+
+ if(!cooldown)
+ {
+ SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid);
+ if(!spellInfo)
+ return;
+
+ cooldown = spellInfo->CategoryRecoveryTime > spellInfo->RecoveryTime ? spellInfo->CategoryRecoveryTime : spellInfo->RecoveryTime;
+ }
+
if(cooldown)
_AddCreatureSpellCooldown(spellid, time(NULL) + cooldown/1000);
if(spellInfo->Category)
_AddCreatureCategoryCooldown(spellInfo->Category, time(NULL));
- m_GlobalCooldown = 1500;
+ m_GlobalCooldown = 1500; // We Should Add A Rate, so we Control a little, Strenght Of Spell Casting
}
bool Creature::HasCategoryCooldown(uint32 spell_id) const
@@ -1833,10 +1864,13 @@
return(itr != m_CreatureCategoryCooldowns.end() && time_t(itr->second + (spellInfo->CategoryRecoveryTime / 1000)) > time(NULL));
}
-bool Creature::HasSpellCooldown(uint32 spell_id) const
+bool Creature::HasSpellCooldown(uint32 spell_id,uint32 addTime) const
{
+ if(!spell_id)
+ return m_GlobalCooldown > 0;
+
CreatureSpellCooldowns::const_iterator itr = m_CreatureSpellCooldowns.find(spell_id);
- return (itr != m_CreatureSpellCooldowns.end() && itr->second > time(NULL)) || m_GlobalCooldown > 0 || HasCategoryCooldown(spell_id);
+ return (itr != m_CreatureSpellCooldowns.end() && itr->second > time(NULL)+addTime) || m_GlobalCooldown > 0 || HasCategoryCooldown(spell_id);
}
bool Creature::IsInEvadeMode() const
@@ -1852,3 +1886,159 @@
break;
return i < CREATURE_MAX_SPELLS; //broke before end of iteration of known spells
}
+
+/*void Creature::LoadSpellInfo()
+{
+ if(m_creatureSpellBook)
+ delete m_creatureSpellBook;
+
+ QueryResult* _result = sDatabase.PQuery("SELECT * FROM creature_spellbook WHERE entry=%u",GetEntry());
+ if(_result)
+ {
+ Field *_spellInfo = _result->Fetch();
+ char* _spellId = NULL;
+
+ m_creatureSpellBook = new CreatureSpellBook();
+ //spellId, recoveryTime, unknow1, buffDuration, cost, rangeMin, rangeMax
+ for(uint8 itr = CREATURE_SPELL_MIN; itr < CREATURE_SPELL_MAX; ++itr)
+ {
+ const char* rawSpellInfo = _spellInfo[itr+1].GetString();
+ _spellId = strtok((char*)rawSpellInfo, " ");
+ if( _spellId )
+ {
+ uint32 spellId = m_creatureSpellBook->info[itr].id = atoi(_spellId);
+
+ char* _recoveryTime = strtok(NULL, " ");
+ if(_recoveryTime)
+ m_creatureSpellBook->info[itr].recoveryTime = atoi(_recoveryTime);
+ char* _castingTime = strtok(NULL, " ");
+ if(_castingTime)
+ m_creatureSpellBook->info[itr].unknow1 = atoi(_castingTime);
+ char* _buffDuration = strtok(NULL, " ");
+ if(_buffDuration)
+ m_creatureSpellBook->info[itr].buffDuration = atoi(_buffDuration);
+ char* _cost = strtok(NULL, " ");
+ if(_cost)
+ m_creatureSpellBook->info[itr].cost = atoi(_cost);
+ char* _rangeMin = strtok(NULL, " ");
+ if(_rangeMin)
+ m_creatureSpellBook->info[itr].range[0] = atof(_rangeMin);
+ char* _rangeMax = strtok(NULL, " ");
+ if(_rangeMax)
+ m_creatureSpellBook->info[itr].range[1] = atof(_rangeMax);
+ }
+ }
+ delete _result;
+
+ SpellEntry const* dbcSpell;
+ SpellRangeEntry const *dbcRange;
+ SpellDurationEntry const * dbcDuration;
+ SpellCastTimesEntry const *dbcCastTime;
+
+ CreatureSpellInfoMap::iterator itr = m_creatureSpellBook->info.begin();
+ if(itr == m_creatureSpellBook->info.end())
+ return;
+
+ for(; itr != m_creatureSpellBook->info.end(); ++itr)
+ {
+ dbcSpell = GetSpellStore()->LookupEntry(itr->second.id);
+ if( !dbcSpell )
+ continue;
+ dbcRange = GetSpellRangeStore()->LookupEntry(dbcSpell->rangeIndex);
+ dbcDuration = GetSpellDurationStore()->LookupEntry(dbcSpell->DurationIndex);
+ dbcCastTime = GetCastTimesStore()->LookupEntry(dbcSpell->CastingTimeIndex);
+
+ for (int j=0; j<3; j++)
+ {
+ //Spell targets self
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_SELF )
+ itr->second.targets |= 1 << (SELECT_TARGET_SELF-1);
+
+ //Spell targets a single enemy
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_SELECTED_ENEMY )
+ itr->second.targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1);
+
+ //Spell targets AoE at enemy
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED )
+ itr->second.targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1);
+
+ //Spell targets an enemy
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_SELECTED_ENEMY ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED )
+ itr->second.targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1);
+
+ //Spell targets a single friend(or self)
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_SELF ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY )
+ itr->second.targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1);
+
+ //Spell targets aoe friends
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY )
+ itr->second.targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1);
+
+ //Spell targets any friend(or self)
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_SELF ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY )
+ itr->second.targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1);
+
+ //Make sure that this spell includes a damage effect
+ if ( dbcSpell->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE ||
+ dbcSpell->Effect[j] == SPELL_EFFECT_INSTAKILL ||
+ dbcSpell->Effect[j] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE ||
+ dbcSpell->Effect[j] == SPELL_EFFECT_HEALTH_LEECH )
+ itr->second.effects |= 1 << (SELECT_EFFECT_DAMAGE-1);
+
+ //Make sure that this spell includes a healing effect
+ if ( dbcSpell->Effect[j] == SPELL_EFFECT_HEAL ||
+ dbcSpell->Effect[j] == SPELL_EFFECT_HEAL_MAX_HEALTH ||
+ dbcSpell->Effect[j] == SPELL_EFFECT_HEAL_MECHANICAL )
+ itr->second.effects |= 1 << (SELECT_EFFECT_HEALING-1);
+
+ //Make sure that this spell applies an aura
+ if( dbcSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA )
+ itr->second.effects |= 1 << (SELECT_EFFECT_AURA-1);
+
+ // Buff Duration
+ if( dbcDuration && itr->second.buffDuration < dbcDuration->Duration[j] )//DBC Info Not Good
+ itr->second.buffDuration = dbcDuration->Duration[j];
+ }
+
+ //We use powerCost from SQL on missing DBC value
+ if( dbcSpell->manaCost )
+ {
+ itr->second.usingDBC = true;
+ itr->second.cost = dbcSpell->manaCost;
+ }
+
+ //CoolDown
+ if( !itr->second.recoveryTime && dbcSpell->RecoveryTime )
+ itr->second.recoveryTime = dbcSpell->RecoveryTime;
+
+ if(dbcRange)
+ {
+ //Range Min
+ if( !itr->second.range[0] )
+ itr->second.range[0] = dbcRange->minRange;
+ //Range Max
+ if( !itr->second.range[1] )//DBC Info Not Good
+ itr->second.range[1] = dbcRange->maxRange;
+ }
+
+ //Casttime
+ if(dbcCastTime && dbcCastTime->CastTime)
+ itr->second.isDelayed = true;
+ }
+ }
+}
+*/
Index: src/game/Creature.h
===================================================================
--- src/game/Creature.h (revision 4763)
+++ src/game/Creature.h (working copy)
@@ -269,6 +269,124 @@
uint32 modelid_other_gender;
};
+enum CreatureSpellSelectTarget
+{
+ SELECT_TARGET_DONTCARE = 0, //All target types allowed
+
+ SELECT_TARGET_SELF, //Only Self casting
+
+ SELECT_TARGET_SINGLE_ENEMY, //Only Single Enemy
+ SELECT_TARGET_AOE_ENEMY, //Only AoE Enemy
+ SELECT_TARGET_ANY_ENEMY, //AoE or Single Enemy
+
+ SELECT_TARGET_SINGLE_FRIEND, //Only Single Friend
+ SELECT_TARGET_AOE_FRIEND, //Only AoE Friend
+ SELECT_TARGET_ANY_FRIEND, //AoE or Single Friend
+};
+
+enum CreatureSpellSelectEffect
+{
+ SELECT_EFFECT_DONTCARE = 0, //All spell effects allowed
+ SELECT_EFFECT_DAMAGE, //Spell does damage
+ SELECT_EFFECT_HEALING, //Spell does healing
+ SELECT_EFFECT_AURA, //Spell applies an aura
+};
+enum CreatureSpellIndex
+{
+ CREATURE_SPELL_MIN,
+ CREATURE_SPELL_ATTACK_1 = 0, //Normal Attack
+ CREATURE_SPELL_ATTACK_2,
+ CREATURE_SPELL_ATTACK_3,
+ CREATURE_SPELL_ATTACK_4,
+ CREATURE_SPELL_ATTACK_5,
+ CREATURE_SPELL_ATTACK_MAX,
+ CREATURE_SPELL_SPEED_1 = 5, //When target Run Away
+ CREATURE_SPELL_SPEED_2,
+ CREATURE_SPELL_SPEED_MAX,
+ CREATURE_SPELL_STUNT_1 = 7,
+ CREATURE_SPELL_STUNT_2, //When target Run Closer
+ CREATURE_SPELL_STUNT_MAX,
+ CREATURE_SPELL_HEALING_1 = 9, //When Less Life Or Friend Target
+ CREATURE_SPELL_HEALING_2,
+ CREATURE_SPELL_HEALING_MAX,
+ CREATURE_SPELL_BUFF_1 = 11, //When Begin of the fight Or Friend Target
+ CREATURE_SPELL_BUFF_2,
+ CREATURE_SPELL_BUFF_MAX,
+ CREATURE_SPELL_INTERRUPT_1 = 13, //Select When Target is Casting Channeling Spell
+ CREATURE_SPELL_INTERRUPT_MAX,
+ CREATURE_SPELL_MAX = 14
+};
+struct CreatureSpellBookInfo
+{
+ CreatureSpellBookInfo() : id(NULL), recoveryTime(0),
+ unknow1(0),buffDuration(0),cost(0),
+ targets(0),effects(0),usingDBC(false),hasCastTime(false)
+ {
+ range[0] = 0.0f;
+ range[1] = 0.0f;
+ }
+
+ uint8 targets,effects;
+ uint32 id,recoveryTime,unknow1,buffDuration,cost;
+ float range[2];
+ bool usingDBC,hasCastTime;
+};
+typedef std::map<uint8,CreatureSpellBookInfo> CreatureSpellBookInfoMap;
+struct CreatureSpellBook
+{
+ CreatureSpellBook() { info.clear(); }
+ CreatureSpellBookInfoMap info;
+
+ bool hasHealing()
+ {
+ CreatureSpellBookInfoMap::iterator spellItr;
+ for(uint8 i = CREATURE_SPELL_HEALING_1; i < CREATURE_SPELL_HEALING_MAX; ++i)
+ {
+ spellItr = info.find(i);
+ if( spellItr != info.end() && spellItr->second.id)
+ return true;
+ }
+ return false;
+ }
+ bool hasSpeed()
+ {
+ CreatureSpellBookInfoMap::iterator spellItr;
+ for(uint8 i = CREATURE_SPELL_SPEED_1; i < CREATURE_SPELL_SPEED_MAX; ++i)
+ {
+ spellItr = info.find(i);
+ if( spellItr != info.end() && spellItr->second.id)
+ return true;
+ }
+ return false;
+ }
+ bool hasInterrupt()
+ {
+ CreatureSpellBookInfoMap::iterator spellItr;
+ for(uint8 i = CREATURE_SPELL_INTERRUPT_1; i < CREATURE_SPELL_INTERRUPT_MAX; ++i)
+ {
+ spellItr = info.find(i);
+ if( spellItr != info.end() && spellItr->second.id)
+ return true;
+ }
+ return false;
+ }
+};
+
+
+
+
+struct AssistenceStatus
+{
+ AssistenceStatus() : requested(false), obtained(false) {}
+ bool requested;
+ bool obtained;
+
+ void reset()
+ {
+ obtained = false;
+ requested = false;
+ }
+};
enum InhabitTypeValues
{
INHAVIT_GROUND = 1,
@@ -364,7 +482,7 @@
void _AddCreatureSpellCooldown(uint32 spell_id, time_t end_time);
void _AddCreatureCategoryCooldown(uint32 category, time_t apply_time);
void AddCreatureSpellCooldown(uint32 spellid);
- bool HasSpellCooldown(uint32 spell_id) const;
+ bool HasSpellCooldown(uint32 spell_id = 0, uint32 addTime = 0) const;
bool HasCategoryCooldown(uint32 spell_id) const;
bool HasSpell(uint32 spellID) const;
@@ -465,15 +583,16 @@
SpellEntry const *reachWithSpellCure(Unit *pVictim);
uint32 m_spells[CREATURE_MAX_SPELLS];
+ uint32 m_GlobalCooldown;
CreatureSpellCooldowns m_CreatureSpellCooldowns;
CreatureSpellCooldowns m_CreatureCategoryCooldowns;
- uint32 m_GlobalCooldown;
float GetAttackDistance(Unit *pl) const;
- void CallAssistence();
- void SetNoCallAssistence(bool val) { m_AlreadyCallAssistence = val; }
-
+ //void CallAssistence();
+ //void SetCallAssistence( bool value ) { m_AlreadyCallAssistence = value; }
+ //bool GetCallAssistence() const { return m_AlreadyCallAssistence; }
+ AssistenceStatus* m_AssistenceStatus;
MovementGeneratorType GetDefaultMovementType() const { return m_defaultMovementType; }
void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; }
@@ -507,6 +626,7 @@
else
return m_charmInfo->GetCharmSpell(pos)->spellId;
}
+ CreatureSpellBook *m_creatureSpellBook;
protected:
// vendor items
@@ -548,7 +668,7 @@
uint32 m_regenTimer;
MovementGeneratorType m_defaultMovementType;
Cell m_currentCell; // store current cell where creature listed
- bool m_AlreadyCallAssistence;
+ //bool m_AlreadyCallAssistence;
uint32 m_DBTableGuid;
bool m_regenHealth;
Index: src/game/CreatureAI.h
===================================================================
--- src/game/CreatureAI.h (revision 4763)
+++ src/game/CreatureAI.h (working copy)
@@ -32,6 +32,21 @@
#define TIME_INTERVAL_LOOK 5000
#define VISIBILITY_RANGE 10000
+//Creature Follow Range on aggro
+#define AI_MANGOS 1 //To add Featured or Normal Version
+#define FOLLOW_RANGE_CASTER 9.0f
+#define FOLLOW_RANGE_MELEE 0.0f
+#define RUNAWAY_AGGRO_RANGE 3.3f // +Aggro == start RunAway at that range
+#define RANGE_AUTO_ASSIST 2.0f
+#define RANGE_AUTO_ASSIST_PET 20.0f
+#define RANGE_AUTO_ASSIST_PLAYER 15.0f
+#define RANGE_AUTO_ASSIST_NPC 0.5f
+#define RANGE_DYNAMIC_ASSIST 15.0f
+#define RANGE_MAX_AUTO_FEAR 15.0f //If player distance from SpawnPoint > RANGE_MAX_AUTO_FEAR, AUTO fear Off.
+#define CREATURE_SPELL_RUNAWAY 8225
+#define CREATURE_SPELL_TAP_FRIEND 38192
+#define CREATURE_WAIT_RATE 15
+
class MANGOS_DLL_SPEC CreatureAI
{
public:
Index: src/game/CreatureAIRegistry.cpp
===================================================================
--- src/game/CreatureAIRegistry.cpp (revision 4763)
+++ src/game/CreatureAIRegistry.cpp (working copy)
@@ -20,6 +20,7 @@
#include "NullCreatureAI.h"
#include "ReactorAI.h"
#include "AggressorAI.h"
+#include "AggressorCasterAI.h"
#include "GuardAI.h"
#include "PetAI.h"
#include "TotemAI.h"
@@ -37,6 +38,7 @@
{
(new CreatureAIFactory<NullCreatureAI>("NullAI"))->RegisterSelf();
(new CreatureAIFactory<AggressorAI>("AggressorAI"))->RegisterSelf();
+ (new CreatureAIFactory<AggressorCasterAI>("AggressorCasterAI"))->RegisterSelf();
(new CreatureAIFactory<ReactorAI>("ReactorAI"))->RegisterSelf();
(new CreatureAIFactory<GuardAI>("GuardAI"))->RegisterSelf();
(new CreatureAIFactory<PetAI>("PetAI"))->RegisterSelf();
Index: src/game/DestinationHolder.h
===================================================================
--- src/game/DestinationHolder.h (revision 4763)
+++ src/game/DestinationHolder.h (working copy)
@@ -35,11 +35,12 @@
uint32 i_timeElapsed;
bool i_destSet;
float i_fromX, i_fromY, i_fromZ;
+ uint32 i_fromMapId;
float i_destX, i_destY, i_destZ;
public:
DestinationHolder() : i_tracker(TRAVELLER_UPDATE_INTERVAL), i_totalTravelTime(0), i_timeStarted(0), i_timeElapsed(0),
- i_destSet(false), i_fromX(0), i_fromY(0), i_fromZ(0), i_destX(0), i_destY(0), i_destZ(0) {}
+ i_destSet(false), i_fromX(0), i_fromY(0), i_fromZ(0),i_fromMapId(0), i_destX(0), i_destY(0), i_destZ(0) {}
uint32 SetDestination(TRAVELLER &traveller, float dest_x, float dest_y, float dest_z, bool sendMove = true);
void GetDestination(float &x, float &y, float &z) { x = i_destX; y = i_destY; z = i_destZ; }
@@ -48,13 +49,15 @@
uint32 GetTotalTravelTime(void) const { return i_totalTravelTime; }
uint32 GetStartTravelTime(void) const { return i_timeStarted; }
bool HasDestination(void) const { return i_destSet; }
+ float GetDestinationDiff2d(float x, float y, float z) const;
float GetDestinationDiff(float x, float y, float z) const;
bool HasArrived(void) const { return (i_totalTravelTime == 0 || i_timeElapsed >= i_totalTravelTime); }
+ uint32 GetTimeToDest(void) const { return i_totalTravelTime - i_timeElapsed; }
bool UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update);
uint32 StartTravel(TRAVELLER &traveller, bool sendMove = true);
- void GetLocationNow(float &x, float &y, float &z) const;
+ void GetLocationNow(float &x, float &y, float &z, bool is3D = false) const;
+ float GetDistanceFromDest2dSq(const WorldObject &obj) const;
float GetDistanceFromDestSq(const WorldObject &obj) const;
-
private:
void _findOffSetPoint(float x1, float y1, float x2, float y2, float offset, float &x, float &y);
Index: src/game/DestinationHolderImp.h
===================================================================
--- src/game/DestinationHolderImp.h (revision 4763)
+++ src/game/DestinationHolderImp.h (working copy)
@@ -25,9 +25,7 @@
#include <cmath>
-template<typename TRAVELLER>
-void
-DestinationHolder<TRAVELLER>::_findOffSetPoint(float x1, float y1, float x2, float y2, float offset, float &x, float &y)
+template<typename TRAVELLER> void DestinationHolder<TRAVELLER>::_findOffSetPoint(float x1, float y1, float x2, float y2, float offset, float &x, float &y)
{
/* given the point (x1, y1) and (x2, y2).. need to find the point (x,y) on the same line
* such that the distance from (x, y) to (x2, y2) is offset.
@@ -61,12 +59,10 @@
}
}
-template<typename TRAVELLER>
-uint32
-DestinationHolder<TRAVELLER>::SetDestination(TRAVELLER &traveller, float dest_x, float dest_y, float dest_z, bool sendMove)
+template<typename TRAVELLER> uint32 DestinationHolder<TRAVELLER>::SetDestination(TRAVELLER &traveller, float dest_x, float dest_y, float dest_z, bool sendMove)
{
- if (i_destSet && i_destX == dest_x && i_destY == dest_y && i_destZ == dest_z)
- return 0;
+ //if (i_destSet && i_destX == dest_x && i_destY == dest_y && i_destZ == dest_z)
+ //return 0;
i_destSet = true;
i_destX = dest_x;
@@ -76,34 +72,39 @@
return StartTravel(traveller, sendMove);
}
-template<typename TRAVELLER>
-uint32
-DestinationHolder<TRAVELLER>::StartTravel(TRAVELLER &traveller, bool sendMove)
+template<typename TRAVELLER> uint32 DestinationHolder<TRAVELLER>::StartTravel(TRAVELLER &traveller, bool sendMove)
{
if(!i_destSet) return 0;
i_fromX = traveller.GetPositionX();
i_fromY = traveller.GetPositionY();
i_fromZ = traveller.GetPositionZ();
+ i_fromMapId = traveller.GetTraveller().GetMapId();
float dx = i_destX - i_fromX;
float dy = i_destY - i_fromY;
float dz = i_destZ - i_fromZ;
- double dist = ::sqrt((dx*dx) + (dy*dy) + (dz*dz));
- double speed = traveller.Speed();
- if(speed<=0)
+
+ float dist;
+ //Should be for Creature Flying too and Swimming.
+ if(traveller.GetTraveller().hasUnitState(UNIT_STAT_IN_FLIGHT))
+ dist = sqrt((dx*dx) + (dy*dy) + (dz*dz));
+ else //Walking on the ground
+ dist = sqrt((dx*dx) + (dy*dy));
+ float speed = traveller.Speed();
+ if(speed<=0.0f) // -0 will be reverse ??? for me at lease, GS
speed = 2.5f;
speed *= 0.001f; // speed is in seconds so convert from second to millisecond
- i_totalTravelTime = static_cast<uint32>( dist/speed + 0.5 );
+ i_totalTravelTime = static_cast<uint32>( dist/speed);
i_timeStarted = getMSTime();
i_timeElapsed = 0;
- if(sendMove) traveller.MoveTo(i_destX, i_destY, i_destZ, i_totalTravelTime);
+ if(sendMove)
+ traveller.MoveTo(i_destX, i_destY, i_destZ, i_totalTravelTime);
+
return i_totalTravelTime;
}
-template<typename TRAVELLER>
-bool
-DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update)
+template<typename TRAVELLER> bool DestinationHolder<TRAVELLER>::UpdateTraveller(TRAVELLER &traveller, uint32 diff, bool force_update)
{
i_tracker.Update(diff);
i_timeElapsed += diff;
@@ -112,9 +113,14 @@
ResetUpdate();
if(!i_destSet) return true;
float x,y,z;
- GetLocationNow(x, y, z);
+
+ if(traveller.GetTraveller().hasUnitState(UNIT_STAT_IN_FLIGHT))
+ GetLocationNow(x, y, z,true); //Should repositione Object with right Coord, so i can bypass some Grid Relocation, GS
+ else
+ GetLocationNow(x, y, z);
if( x == -431602080 )
return false;
+
if( traveller.GetTraveller().GetPositionX() != x || traveller.GetTraveller().GetPositionY() != y )
{
float ori = traveller.GetTraveller().GetAngle(x, y);
@@ -125,9 +131,7 @@
return false;
}
-template<typename TRAVELLER>
-void
-DestinationHolder<TRAVELLER>::GetLocationNow(float &x, float &y, float &z) const
+template<typename TRAVELLER> void DestinationHolder<TRAVELLER>::GetLocationNow(float &x, float &y, float &z, bool is3D) const
{
if( HasArrived() )
{
@@ -135,28 +139,49 @@
y = i_destY;
z = i_destZ;
}
- else
+ else if(HasDestination())
{
double percent_passed = (double)i_timeElapsed / (double)i_totalTravelTime;
- x = i_fromX + ((i_destX - i_fromX) * percent_passed);
- y = i_fromY + ((i_destY - i_fromY) * percent_passed);
- z = i_fromZ + ((i_destZ - i_fromZ) * percent_passed);
+ const float distanceX = ((i_destX - i_fromX) * percent_passed);
+ const float distanceY = ((i_destY - i_fromY) * percent_passed);
+ const float distanceZ = ((i_destZ - i_fromZ) * percent_passed);
+ x = i_fromX + distanceX;
+ y = i_fromY + distanceY;
+ //All that is wrong... Probleme is traveller need to fly or swimg... bad way to make it..., GS
+ if(is3D)
+ z = i_fromZ + distanceZ;
+ else
+ {
+ //That part is good... for mob Walking on the floor... But the floor is not allways what we thought :(...
+ z = MapManager::Instance().GetBaseMap(i_fromMapId)->GetHeight(x,y,i_fromZ);
+ const float groundDist = sqrt(distanceX*distanceX + distanceY*distanceY);
+ const float zDist = fabs(i_fromZ - z) + 0.000001f; //FineTune with that value..., GS
+ const float slope = groundDist / zDist;
+ if(fabs(slope) < 1.0f) // Or i set the Z to -10000 and ExpireMG when Z == -10000 so at that precise place the SetLocation will see something is wrong.
+ z = i_destZ;
+ }
}
}
-template<typename TRAVELLER>
-float
-DestinationHolder<TRAVELLER>::GetDistanceFromDestSq(const WorldObject &obj) const
+template<typename TRAVELLER> float DestinationHolder<TRAVELLER>::GetDistanceFromDest2dSq(const WorldObject &obj) const
{
float x,y,z;
obj.GetPosition(x,y,z);
- return (i_destX-x)*(i_destX-x)+(i_destY-y)*(i_destY-y)+(i_destZ-z)*(i_destZ-z);
+ return (i_destX-x)*(i_destX-x) + (i_destY-y)*(i_destY-y);
}
-template<typename TRAVELLER>
-float
-DestinationHolder<TRAVELLER>::GetDestinationDiff(float x, float y, float z) const
+template<typename TRAVELLER> float DestinationHolder<TRAVELLER>::GetDistanceFromDestSq(const WorldObject &obj) const
{
- return sqrt(((x-i_destX)*(x-i_destX)) + ((y-i_destY)*(y-i_destY)) + ((z-i_destZ)*(z-i_destZ)));
+ float x,y,z;
+ obj.GetPosition(x,y,z);
+ return (i_destX-x)*(i_destX-x) + (i_destY-y)*(i_destY-y) + (i_destZ-z)*(i_destZ-z);
}
+template<typename TRAVELLER> float DestinationHolder<TRAVELLER>::GetDestinationDiff2d(float x, float y, float z) const
+{
+ return sqrt( ((x-i_destX)*(x-i_destX)) + ((y-i_destY)*(y-i_destY)) );
+}
+template<typename TRAVELLER> float DestinationHolder<TRAVELLER>::GetDestinationDiff(float x, float y, float z) const
+{
+ return sqrt( ((x-i_destX)*(x-i_destX)) + ((y-i_destY)*(y-i_destY)) + ((z-i_destZ)*(z-i_destZ)));
+}
#endif
Index: src/game/FleeingMovementGenerator.cpp
===================================================================
--- src/game/FleeingMovementGenerator.cpp (revision 0)
+++ src/game/FleeingMovementGenerator.cpp (revision 0)
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2005,2006,2007 MaNGOS <http://www.mangosproject.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Creature.h"
+#include "MapManager.h"
+#include "FleeingMovementGenerator.h"
+#include "DestinationHolderImp.h"
+#include "ObjectAccessor.h"
+
+template<class T> void FleeingMovementGenerator<T>::_setNextLocation(T &unit)
+{
+ //no grid search since, i just need a angle... and badly need one if i fear something, GS
+ Unit* fearWho = ObjectAccessor::Instance().GetUnit(unit, fearWhoGuid);
+ if(!fearWho)
+ return;
+
+ float fearMoveAngle = unit.GetAngle(fearWho)+M_PI;
+ float fearWhoAngle = fearWho->GetOrientation();
+ float speed = unit.GetSpeed(MOVE_RUN);
+ float X = unit.GetPositionX();
+ float Y = unit.GetPositionY();
+ float Z = unit.GetPositionZ();
+ uint32 mapid = unit.GetMapId();
+
+ //TODO: Play with max range, GS
+ if(unit.IsWithinDistInMap(fearWho, 28))
+ {
+ float x = X + speed * cos(fearMoveAngle);
+ float y = Y + speed * sin(fearMoveAngle);
+ float z;
+
+ if(unit.HasPathTo(x,y))
+ {
+ z = MapManager::Instance().GetBaseMap(mapid)->GetHeight(x,y,Z);
+ Traveller<T> traveller(unit);
+ unit.SetOrientation(fearMoveAngle);
+ i_destinationHolder.SetDestination(traveller, x, y, z);
+ unit.addUnitState(UNIT_STAT_FLEEING);
+ }
+ else
+ {
+ Traveller<T> traveller(unit);
+ unit.SetOrientation(fearMoveAngle);
+ i_destinationHolder.SetDestination(traveller, X, Y, Z);
+ unit.clearUnitState(UNIT_STAT_FLEEING);
+ }
+
+ /*uint8 interlevingSide = 0;
+ float leftAngle, rightAngle;
+ leftAngle = rightAngle = 0.0f;
+
+ //That is a path like searching with LOS.... I have another one without LOS... need fine tune and add that, GS.
+ while( (!unit.IsWithinLOS(x,y,z) ) && interlevingSide < 76 ) //interlevingSide 63 gave me about 90 Degree each Side
+ {
+ fearMoveAngle = fearWhoAngle+M_PI;
+ if ( !(interlevingSide & 1)) //Pair Number
+ {
+ leftAngle += 0.05;
+ if(fearMoveAngle + leftAngle > (M_PI*2))
+ fearMoveAngle = fearMoveAngle + leftAngle - (M_PI*2);
+ else
+ fearMoveAngle += leftAngle;
+ ++interlevingSide;
+ }
+ else //Impair Number
+ {
+ rightAngle -= 0.05;
+ if( fearMoveAngle + rightAngle < 0)
+ fearMoveAngle = fearMoveAngle + rightAngle + (M_PI*2);
+ else
+ fearMoveAngle += rightAngle;
+ ++interlevingSide;
+ }
+ x = X + (speed*3+unit.GetObjectSize()) * cos(fearMoveAngle);
+ y = Y + (speed*3+unit.GetObjectSize()) * sin(fearMoveAngle);
+ z = MapManager::Instance().GetBaseMap(mapid)->GetHeight(x,y,Z);
+ }
+
+ if( interlevingSide < 76 )
+ {
+ x = X + (speed*3) * cos(fearMoveAngle);
+ y = Y + (speed*3) * sin(fearMoveAngle);
+ //z = Z; //Doing Test... Probaly not needed...
+ z = MapManager::Instance().GetBaseMap(mapid)->GetHeight(x,y,Z);
+
+
+ }
+ else //At this point i think is better UnFear the MV owner or at max Range.. , GS
+ {
+ Traveller<T> traveller(unit);
+ unit.SetOrientation(fearMoveAngle);
+ i_destinationHolder.SetDestination(traveller, X, Y, Z);
+ unit.clearUnitState(UNIT_STAT_FLEEING);
+ }*/
+ }
+}
+
+template<class T> void FleeingMovementGenerator<T>::Initialize(T &unit)
+{
+ if(!&unit || !unit.isAlive())
+ return;
+
+ unit.setMoveRunFlag(true);
+ _setNextLocation(unit);
+}
+template<class T> void FleeingMovementGenerator<T>::Reset(T &unit)
+{
+
+}
+
+template<class T> bool FleeingMovementGenerator<T>::Update(T &unit, const uint32 &diff)
+{
+ if(!&unit || !unit.isAlive())
+ return false;
+
+ if(!i_destinationHolder.HasArrived() && unit.IsStopped())
+ unit.addUnitState(UNIT_STAT_FLEEING);
+
+ if( i_destinationHolder.GetTimeToDest() < diff )
+ {
+ float x,y,z;
+ i_destinationHolder.GetLocationNow(x,y,z);
+ unit.Relocate(x,y,z);
+ _setNextLocation(unit);
+ }
+ Traveller<T> traveller(unit);
+ i_destinationHolder.UpdateTraveller(traveller, diff, false);
+
+ if( !unit.HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_FLEEING) )
+ {
+ /*if(i_destinationHolder.GetTimeToDest())
+ {
+ float x,y,z;
+ i_destinationHolder.GetLocationNow(x,y,z);
+ unit.Relocate(x,y,z);
+ }*/
+ return false;
+ }
+ return true;
+}
+
+template void FleeingMovementGenerator<Player>::_setNextLocation(Player &);
+template void FleeingMovementGenerator<Creature>::_setNextLocation(Creature &);
+template void FleeingMovementGenerator<Player>::Initialize(Player &player);
+template void FleeingMovementGenerator<Creature>::Initialize(Creature &creature);
+template void FleeingMovementGenerator<Player>::Reset(Player &player);
+template void FleeingMovementGenerator<Creature>::Reset(Creature &creature);
+template bool FleeingMovementGenerator<Player>::Update(Player &player, const uint32 &diff);
+template bool FleeingMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff);
Index: src/game/FleeingMovementGenerator.h
===================================================================
--- src/game/FleeingMovementGenerator.h (revision 0)
+++ src/game/FleeingMovementGenerator.h (revision 0)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2005,2006,2007 MaNGOS <http://www.mangosproject.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef MANGOS_FLEEINGMOTIONGENERATOR_H
+#define MANGOS_FLEEINGMOTIONGENERATOR_H
+
+#include "MovementGenerator.h"
+#include "DestinationHolder.h"
+#include "Traveller.h"
+
+template<class T>
+class MANGOS_DLL_DECL FleeingMovementGenerator
+ : public MovementGeneratorMedium< T, FleeingMovementGenerator<T> >
+{
+ public:
+ FleeingMovementGenerator(const Unit &, const uint64 _fearWhoGuid) : fearWhoGuid(_fearWhoGuid) {}
+
+ void Initialize(T &);
+ void Reset(T &);
+ bool Update(T &, const uint32 &);
+ void UpdateMapPosition(float &x ,float &y, float &z)
+ {
+ i_destinationHolder.GetLocationNow(x,y,z);
+ }
+ MovementGeneratorType GetMovementGeneratorType() { return FLEEING_MOTION_TYPE; }
+ private:
+ void _setNextLocation(T &);
+ DestinationHolder< Traveller<T> > i_destinationHolder;
+ uint64 fearWhoGuid;
+};
+#endif
Index: src/game/GridDefines.h
===================================================================
--- src/game/GridDefines.h (revision 4763)
+++ src/game/GridDefines.h (working copy)
@@ -33,7 +33,7 @@
#define MAX_NUMBER_OF_GRIDS 64
-#define SIZE_OF_GRIDS 533.33333f
+#define SIZE_OF_GRIDS 533.333333f
#define CENTER_GRID_ID (MAX_NUMBER_OF_GRIDS/2)
#define CENTER_GRID_OFFSET (SIZE_OF_GRIDS/2)
Index: src/game/GridNotifiers.h
===================================================================
--- src/game/GridNotifiers.h (revision 4763)
+++ src/game/GridNotifiers.h (working copy)
@@ -623,10 +623,10 @@
return false;
// only from same creature faction
- if(u->getFaction() != i_funit->getFaction() )
+ if( u->getFaction() != i_funit->getFaction() )
return false;
- if(!u->IsWithinLOSInMap(i_enemy) )
+ if( !u->IsWithinLOSInMap(i_enemy) )
return false;
return true;
Index: src/game/GridNotifiersImpl.h
===================================================================
--- src/game/GridNotifiersImpl.h (revision 4763)
+++ src/game/GridNotifiersImpl.h (working copy)
@@ -70,24 +70,26 @@
pl->UpdateVisibilityOf(c);
// Creature AI reaction
- if(!c->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
+ if( !c->hasUnitState( UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING ) )
{
- if( c->AI() && c->AI()->IsVisible(pl) && !c->IsInEvadeMode() )
+ if( c->AI() && c->AI()->IsVisible(pl) /*&& !c->IsInEvadeMode()*/ )
c->AI()->MoveInLineOfSight(pl);
}
}
inline void CreatureCreatureRelocationWorker(Creature* c1, Creature* c2)
{
- if(!c1->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
+ //C2 is the Mover
+ if( !c1->hasUnitState( UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING) )
{
- if( c1->AI() && c1->AI()->IsVisible(c2) && !c1->IsInEvadeMode() )
+ if( c1->AI() && c1->AI()->IsVisible(c2) )
c1->AI()->MoveInLineOfSight(c2);
}
-
- if(!c2->hasUnitState(UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING))
+
+ //To make Pet See everyone they call MILOS on...
+ if( c2->isPet() && !c2->hasUnitState( (UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING )) )
{
- if( c2->AI() && c2->AI()->IsVisible(c1) && !c2->IsInEvadeMode() )
+ if( c2->AI() && c2->AI()->IsVisible(c1) )
c2->AI()->MoveInLineOfSight(c1);
}
}
@@ -107,6 +109,15 @@
inline void
MaNGOS::CreatureRelocationNotifier::Visit(PlayerMapType &m)
{
+ //Here should be when a creature move with RandomMV as example
+ //So she be sure to make all player around call for MILOS, is Player move with have double MILOS and before my change we had 4x MILOS
+ //So now we have MILOS comming from player only when Player move...
+ //All that maybe sound like a probleme... but not if grid notifier.
+ //Grid notifier should get update at all 100MS and checked for changed XY and Z
+ //So we have maximun 1 MILOS by target for a total 100MS.
+ //Why i think is better, not used that needed case here for the moment.
+ //Not good way to solve this situation... Is taking too much CPU, GS.
+ //return;
if(!i_creature.isAlive())
return;
@@ -119,7 +130,7 @@
inline void
MaNGOS::CreatureRelocationNotifier::Visit(CreatureMapType &m)
{
- if(!i_creature.isAlive())
+ if(!i_creature.isAlive() || (!i_creature.hasUnitState(UNIT_STAT_CHASE) && !i_creature.isPet() ) )
return;
for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
Index: src/game/GuardAI.cpp
===================================================================
--- src/game/GuardAI.cpp (revision 4763)
+++ src/game/GuardAI.cpp (working copy)
@@ -44,7 +44,7 @@
u->isInAccessablePlaceFor(&i_creature))
{
float attackRadius = i_creature.GetAttackDistance(u);
- if(i_creature.IsWithinDistInMap(u,attackRadius) && i_creature.GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE)
+ if(i_creature.IsWithinDistInMap(u,attackRadius) && !i_creature.HasPathTo(u))
{
//Need add code to let guard suport player
AttackStart(u);
@@ -58,8 +58,6 @@
if( !i_creature.isAlive() )
{
DEBUG_LOG("Creature stopped attacking because he's dead [guid=%u]", i_creature.GetGUIDLow());
- i_creature.StopMoving();
- i_creature.GetMotionMaster()->Idle();
i_state = STATE_NORMAL;
@@ -97,10 +95,6 @@
i_victimGuid = 0;
i_creature.CombatStop(true);
i_state = STATE_NORMAL;
-
- // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
- if( i_creature.GetMotionMaster()->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE )
- i_creature.GetMotionMaster()->TargetedHome();
}
void GuardAI::UpdateAI(const uint32 diff)
Index: src/game/HomeMovementGenerator.cpp
===================================================================
--- src/game/HomeMovementGenerator.cpp (revision 4763)
+++ src/game/HomeMovementGenerator.cpp (working copy)
@@ -23,50 +23,58 @@
#include "ObjectAccessor.h"
#include "DestinationHolderImp.h"
-void
-HomeMovementGenerator<Creature>::Initialize(Creature & owner)
+#define WALKING_CHANCE_HOMEMV 20 //Chance will be " 1 / WALKING_CHANCE_HOMEMV"
+
+void HomeMovementGenerator<Creature>::_setHomeLocation(Creature & creature)
{
- owner.setMoveRunFlag(true);
- _setTargetLocation(owner);
+ //I don't think set destination should start traveller.... so we are little more flexible, GS
+ if( !&creature || !creature.isAlive() )
+ return;
+
+ float x, y, z;
+ creature.GetRespawnCoord(x, y, z);
+
+ Traveller<Creature> traveller(creature);
+ creature.SetOrientation(creature.GetAngle(x,y));//Need Badly Orientation of Spawn, GS
+ i_destinationHolder.SetDestination(traveller, x, y, z);
+ creature.addUnitState(UNIT_STAT_SEARCHING);
}
-
-void
-HomeMovementGenerator<Creature>::Reset(Creature &)
+void HomeMovementGenerator<Creature>::Initialize(Creature & creature)
{
+ creature.setMoveRunFlag(irand(0,WALKING_CHANCE_HOMEMV));
+ _setHomeLocation(creature);
}
-
-void
-HomeMovementGenerator<Creature>::_setTargetLocation(Creature & owner)
+void HomeMovementGenerator<Creature>::Reset(Creature &)
{
- if( !&owner )
- return;
- if( owner.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED) )
- return;
-
- float x, y, z;
- owner.GetRespawnCoord(x, y, z);
-
- CreatureTraveller traveller(owner);
-
- uint32 travel_time = i_destinationHolder.SetDestination(traveller, x, y, z);
- modifyTravelTime(travel_time);
- owner.clearUnitState(UNIT_STAT_ALL_STATE);
}
-
-bool
-HomeMovementGenerator<Creature>::Update(Creature &owner, const uint32& time_diff)
+bool HomeMovementGenerator<Creature>::Update(Creature &creature, const uint32& diff)
{
- CreatureTraveller traveller( owner);
- i_destinationHolder.UpdateTraveller(traveller, time_diff, false);
+ //TODO: Complete UNIT_STAT_SEARCHING, when creature has this status she won't accept any MILOS...
+ //So a creature going home won't change mind into the first 50% of mv... other MV will herite too.
+ //Juts have to think really with is the best UNIT STAT to use... and Do automation with checking unit field flag, as the client do is best.
+ if(!&creature || !creature.isAlive())
+ return false;
- if (time_diff > i_travel_timer)
+ CreatureTraveller traveller(creature);
+
+ if(!i_destinationHolder.HasDestination())
{
- owner.setMoveRunFlag(false);
+ Initialize(creature);
+ return true;
+ }
+ else if( i_destinationHolder.HasArrived() )
+ {
+ if(!creature.IsStopped())
+ creature.clearUnitState(UNIT_STAT_SEARCHING);
return false;
}
+ else if( i_destinationHolder.GetTimeToDest() < i_destinationHolder.GetTotalTravelTime()/2.0f)
+ creature.clearUnitState(UNIT_STAT_SEARCHING);
+ else if ( creature.IsStopped() )
+ creature.addUnitState((UNIT_STAT_SEARCHING | UNIT_STAT_ROAMING));
- i_travel_timer -= time_diff;
+ i_destinationHolder.UpdateTraveller(traveller, diff, false);
return true;
}
Index: src/game/HomeMovementGenerator.h
===================================================================
--- src/game/HomeMovementGenerator.h (revision 4763)
+++ src/game/HomeMovementGenerator.h (working copy)
@@ -40,14 +40,15 @@
void Initialize(Creature &);
void Reset(Creature &);
bool Update(Creature &, const uint32 &);
- void modifyTravelTime(uint32 travel_time) { i_travel_timer = travel_time; }
+ void UpdateMapPosition(float &x ,float &y, float &z)
+ {
+ i_destinationHolder.GetLocationNow(x,y,z);
+ }
MovementGeneratorType GetMovementGeneratorType() { return HOME_MOTION_TYPE; }
private:
- void _setTargetLocation(Creature &);
+ void _setHomeLocation(Creature &);
DestinationHolder< Traveller<Creature> > i_destinationHolder;
-
- uint32 i_travel_timer;
};
#endif
Index: src/game/IdleMovementGenerator.cpp
===================================================================
--- src/game/IdleMovementGenerator.cpp (revision 4763)
+++ src/game/IdleMovementGenerator.cpp (working copy)
@@ -17,11 +17,28 @@
*/
#include "IdleMovementGenerator.h"
-#include "Creature.h"
+#include "Unit.h"
+//IdleMovementGenerator si_idleMovement;
-IdleMovementGenerator si_idleMovement;
-
-void
-IdleMovementGenerator::Reset(Unit &owner)
+void IdleMovementGenerator::Reset(Unit &owner)
{
+ //Maybe reset lastTimer if not infinite
}
+void IdleMovementGenerator::Initialize(Unit &owner)
+{
+}
+bool IdleMovementGenerator::Update(Unit &owner, const uint32 &diff)
+{
+ if(!owner.IsStopped())
+ owner.clearUnitState(UNIT_STAT_MOVING);
+
+ if(!i_infinite)
+ {
+ if( i_lastTimer < diff )
+ return false;
+ else
+ i_lastTimer -= diff;
+ }
+
+ return true;
+}
Index: src/game/IdleMovementGenerator.h
===================================================================
--- src/game/IdleMovementGenerator.h (revision 4763)
+++ src/game/IdleMovementGenerator.h (working copy)
@@ -24,12 +24,20 @@
class MANGOS_DLL_SPEC IdleMovementGenerator : public MovementGenerator
{
public:
+ IdleMovementGenerator(Unit &, bool infinite = true, uint32 lastTimer = 0) :
+ i_infinite(infinite), i_lastTimer(lastTimer) {}
+ ~IdleMovementGenerator() {}
- void Initialize(Unit &) { }
+ void Initialize(Unit &);
void Reset(Unit &);
- bool Update(Unit &, const uint32 &) { return true; }
+ bool Update(Unit &, const uint32 &);
MovementGeneratorType GetMovementGeneratorType() { return IDLE_MOTION_TYPE; }
+
+ private:
+ uint32 i_lastTimer;
+ bool i_infinite;
+
};
-extern IdleMovementGenerator si_idleMovement;
+//extern IdleMovementGenerator si_idleMovement;
#endif
Index: src/game/Map.cpp
===================================================================
--- src/game/Map.cpp (revision 4763)
+++ src/game/Map.cpp (working copy)
@@ -1448,7 +1448,7 @@
{
CellLock<ReadGuard> cell_lock(cell, cellpair);
MaNGOS::CreatureRelocationNotifier relocationNotifier(*creature);
- cell.data.Part.reserved = ALL_DISTRICT;
+ cell.data.Part.reserved = CENTER_DISTRICT;
cell.SetNoCreate(); // not trigger load unloaded grids at notifier call
TypeContainerVisitor<MaNGOS::CreatureRelocationNotifier, WorldTypeMapContainer > c2world_relocation(relocationNotifier);
Index: src/game/MotionMaster.cpp
===================================================================
--- src/game/MotionMaster.cpp (revision 4763)
+++ src/game/MotionMaster.cpp (working copy)
@@ -20,123 +20,106 @@
#include "CreatureAISelector.h"
#include "Creature.h"
#include "Traveller.h"
+#include "TargetedMovementGenerator.h"
#include "HomeMovementGenerator.h"
#include "IdleMovementGenerator.h"
+#include "RandomMovementGenerator.h"
#include <cassert>
-inline bool isStatic(MovementGenerator *mv)
+MotionMaster::~MotionMaster()
{
- return (mv == &si_idleMovement);
-}
-
-void
-MotionMaster::Initialize()
-{
- // clear ALL movement generators (including default)
- while(!empty())
+ // clear ALL movement generators
+ while( !empty() )
{
MovementGenerator *curr = top();
pop();
- if( !isStatic( curr ) )
- delete curr;
+ delete curr;
}
+}
+void MotionMaster::Initialize()
+{
+ i_owner->StopMoving();
- // set new default movement generator
- if(i_owner->GetTypeId() == TYPEID_UNIT)
+ if(!empty())
+ top()->Initialize(*i_owner);
+ else if(i_owner->GetTypeId() == TYPEID_UNIT && !((Creature*)i_owner)->isPet())
{
MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)i_owner);
- push( movement == NULL ? &si_idleMovement : movement );
+ push( movement == NULL ? new IdleMovementGenerator(*i_owner) : movement );
top()->Initialize(*i_owner);
}
+ else if(i_owner->GetTypeId() == TYPEID_UNIT && ((Creature*)i_owner)->isPet())
+ {
+ push(new RandomMovementGenerator<Creature>(*i_owner));
+ }
else
- push(&si_idleMovement);
-}
-
-MotionMaster::~MotionMaster()
-{
- // clear ALL movement generators (including default)
- while(!empty())
{
- MovementGenerator *curr = top();
- pop();
- if( !isStatic( curr ) )
- delete curr;
+ push(new IdleMovementGenerator(*i_owner));
+ //top()->Initialize(*i_owner);
}
}
-
-void
-MotionMaster::UpdateMotion(const uint32 &diff)
+void MotionMaster::UpdateMotion(const uint32 &diff)
{
- if(i_owner->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED))
+ //TODO: Remove Both with the Use of Idle MV , GS
+ if(i_owner->hasUnitState((UNIT_STAT_ROOT | UNIT_STAT_STUNDED )) )
return;
- assert( !empty() );
+
if (!top()->Update(*i_owner, diff))
MovementExpired();
}
-
-void
-MotionMaster::Clear(bool reset)
+void MotionMaster::Clear(bool reset)
{
- while( !empty() && size() > 1 )
+ while( size() > 1 )
{
MovementGenerator *curr = top();
pop();
- if( !isStatic( curr ) )
- delete curr;
+ delete curr;
}
- assert( !empty() );
- if (reset) top()->Reset(*i_owner);
+ if(reset)
+ top()->Initialize(*i_owner);
}
-
-void
-MotionMaster::MovementExpired(bool reset)
+void MotionMaster::MovementExpired(bool reset)
{
- if( empty() || size() == 1 )
+ if( size() < 2 ) //Never Delete the Index 0, and if we are at 0... something is wrong, GS
return;
- MovementGenerator *curr = top();
- pop();
+ i_owner->StopMoving(); // In Fact No need to STOP, but need to update the Current Map Location before expiration, GS
+ MovementGenerator *curr = top(); // Save pointer to object into the list as Current One
+ pop(); // delete from List current one and put the next one on top.
+ delete curr; // Delete object at pointer, old current one
- if( !isStatic(curr) )
- delete curr;
+ curr = top();
- assert( !empty() );
- while( !empty() && top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE )
- {
- // Should check if target is still valid? If not valid it will crash.
- curr = top();
- pop();
- delete curr;
- }
- if( empty() )
- Initialize();
- if (reset) top()->Reset(*i_owner);
+ if( reset )
+ curr->Initialize(*i_owner);
}
-void
-MotionMaster::TargetedHome()
+void MotionMaster::TargetedHome()
{
- if(i_owner->hasUnitState(UNIT_STAT_FLEEING))
- return;
-
- DEBUG_LOG("Target home location %u", i_owner->GetGUIDLow());
-
- Clear(false);
Mutate(new HomeMovementGenerator<Creature>());
}
-void MotionMaster::Idle(void)
+void MotionMaster::Idle(bool infinite, uint32 lastTimer)
{
- if( empty() || !isStatic( top() ) )
- push( &si_idleMovement );
+ Mutate(new IdleMovementGenerator(*i_owner,infinite,lastTimer) );
}
void MotionMaster::Mutate(MovementGenerator *m)
{
- // HomeMovement is not that important, delete it if meanwhile a new comes
- if (!empty() && top()->GetMovementGeneratorType() == HOME_MOTION_TYPE)
- MovementExpired(false);
+ i_owner->StopMoving();
+
+ if(size() == 1 && i_owner->GetTypeId() == TYPEID_UNIT && !((Creature*)i_owner)->isPet()&& (m->GetMovementGeneratorType() & (TARGETED_MOTION_TYPE | FLEEING_MOTION_TYPE)) )
+ {
+ //Buggy case, but for moment ok doki...
+ switch(top()->GetMovementGeneratorType())
+ {
+ case IDLE_MOTION_TYPE:
+ {
+ push(new HomeMovementGenerator<Creature>());
+ }
+ }
+ }
m->Initialize(*i_owner);
push(m);
}
Index: src/game/MotionMaster.h
===================================================================
--- src/game/MotionMaster.h (revision 4763)
+++ src/game/MotionMaster.h (working copy)
@@ -38,7 +38,8 @@
CONFUSED_MOTION_TYPE = 4, // ConfusedMovementGenerator.h
TARGETED_MOTION_TYPE = 5, // TargetedMovementGenerator.h
HOME_MOTION_TYPE = 6, // HomeMovementGenerator.h
- FLIGHT_MOTION_TYPE = 7 // WaypointMovementGenerator.h
+ FLIGHT_MOTION_TYPE = 7, // WaypointMovementGenerator.h
+ FLEEING_MOTION_TYPE = 8 // FleeingMovementGenerator.h
};
class MANGOS_DLL_SPEC MotionMaster : private std::stack<MovementGenerator *>
@@ -67,7 +68,7 @@
void MovementExpired(bool reset = true);
- void Idle(void);
+ void Idle(bool infinite = true, uint32 lastTimer = 0);
void TargetedHome();
Index: src/game/MovementHandler.cpp
===================================================================
--- src/game/MovementHandler.cpp (revision 4763)
+++ src/game/MovementHandler.cpp (working copy)
@@ -111,7 +111,7 @@
{
CHECK_PACKET_SIZE(recv_data, 4+4+4+4+4+4);
- if(GetPlayer()->GetDontMove())
+ if( GetPlayer()->GetDontMove() )
return;
/* extract packet */
@@ -239,15 +239,19 @@
GetPlayer()->SetInWater( !GetPlayer()->IsInWater() );
/*----------------------*/
- /* process position-change */
- recv_data.put<uint32>(4, getMSTime());
- WorldPacket data(recv_data.GetOpcode(), (GetPlayer()->GetPackGUID().size()+recv_data.size()));
- data.append(GetPlayer()->GetPackGUID());
- data.append(recv_data.contents(), recv_data.size());
- GetPlayer()->SendMessageToSet(&data, false);
- GetPlayer()->SetPosition(x, y, z, orientation);
- GetPlayer()->SetMovementFlags(flags);
+
+ if(!GetPlayer()->HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_FLEEING))
+ {
+ /* process position-change */
+ recv_data.put<uint32>(4, getMSTime());
+ WorldPacket data(recv_data.GetOpcode(), (GetPlayer()->GetPackGUID().size()+recv_data.size()));
+ data.append(GetPlayer()->GetPackGUID());
+ data.append(recv_data.contents(), recv_data.size());
+ GetPlayer()->SendMessageToSet(&data, false);
+ GetPlayer()->SetPosition(x, y, z, orientation);
+ GetPlayer()->SetMovementFlags(flags);
+ }
}
void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
Index: src/game/NPCHandler.cpp
===================================================================
--- src/game/NPCHandler.cpp (revision 4763)
+++ src/game/NPCHandler.cpp (working copy)
@@ -35,6 +35,7 @@
#include "MapManager.h"
#include "Pet.h"
#include "WaypointMovementGenerator.h"
+#include "IdleMovementGenerator.h"
#include "BattleGroundMgr.h"
#include "BattleGround.h"
@@ -250,7 +251,8 @@
if( unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider())
{
- unit->StopMoving();
+ //TODO: Add static until all Gossip are closed.
+ unit->GetMotionMaster()->Mutate(new IdleMovementGenerator(*unit,false,30000));
//npcIsStopped[unit->GetGUID()] = true;
}
Index: src/game/Object.cpp
===================================================================
--- src/game/Object.cpp (revision 4763)
+++ src/game/Object.cpp (working copy)
@@ -864,18 +864,19 @@
return ( dist > 0 ? dist : 0);
}
-bool WorldObject::IsWithinDistInMap(const WorldObject* obj, const float dist2compare) const
+//TODO: Rename to: IsWithinDistInMap2D and create 3D, GS
+bool WorldObject::IsWithinDistInMap(const WorldObject* obj, const float withInDist) const
{
+ //I wan faster, faster, faster Code here :) , GS
if (!obj || !IsInMap(obj)) return false;
float dx = GetPositionX() - obj->GetPositionX();
float dy = GetPositionY() - obj->GetPositionY();
float dz = GetPositionZ() - obj->GetPositionZ();
- float distsq = dx*dx + dy*dy + dz*dz;
- float sizefactor = GetObjectSize() + obj->GetObjectSize();
- float maxdist = dist2compare + sizefactor;
+ float dist2D = sqrt(dx*dx + dy*dy) - GetObjectSize() - obj->GetObjectSize();
+ float distZ = sqrt(dz*dz) - 4.0f; //Each Moving Object is in size 2.0f Tall, event maybe a little more, GS.
- return distsq < maxdist * maxdist;
+ return withInDist >= dist2D && withInDist >= distZ;
}
bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const
@@ -891,7 +892,7 @@
float x,y,z;
GetPosition(x,y,z);
VMAP::IVMapManager *vMapManager = VMAP::VMapFactory::createOrGetVMapManager();
- return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f);
+ return vMapManager->isInLineOfSight(GetMapId(), x, y, z+1.4f, ox, oy, oz+1.4f);
}
float WorldObject::GetAngle(const WorldObject* obj) const
@@ -946,7 +947,9 @@
}
// angle to face `obj` to `this`
- float angle = rand_norm()*2*M_PI;
+ srand(getMSTime());
+ float angle = rand_norm()*(M_PI*2);
+ srand(getMSTime());
float new_dist = rand_norm()*distance;
rand_x = x + new_dist * cos(angle);
@@ -962,7 +965,7 @@
{
float new_z = MapManager::Instance().GetBaseMap(GetMapId())->GetHeight(x,y,z);
if(new_z > VMAP_INVALID_HEIGHT)
- z = new_z+ 0.2f; // just to be sure that we are not a few pixel under the surface
+ z = new_z/*+ 0.1f*/; // just to be sure that we are not a few pixel under the surface
}
}
@@ -1203,20 +1206,82 @@
} // namespace MaNGOS
//===================================================================================================
+//HasPathTo is to test not complete and doing really not good job... so...TESTING, GS
+bool WorldObject::HasPathTo(WorldObject const* who)
+{
+ const float angleToWho = GetAngle(who);
+ const float distanceToWho = GetDistance2d(who);
+ float distanceToCheck = 0.5;
+ float X,Y,Z,x,y,z, checkX,checkY,checkZ;
+ who->GetPosition(x,y,z);
+ GetPosition(X,Y,Z);
+ const Map* map = MapManager::Instance().GetBaseMap(GetMapId());
+
+ //if( fabs(z - Z) + 0.000001f > 3.0f)
+ // return false;
+ for(;distanceToWho > distanceToCheck; distanceToCheck += 0.5)
+ {
+ checkX = X + (distanceToCheck * cos(angleToWho));
+ checkY = Y + (distanceToCheck * sin(angleToWho));
+ checkZ = map->GetHeight(checkX,checkY,Z); //Disable LOS when a creature is the target... For saving cpu... but is needed in fact, GS.
+ const float zDist = fabs(checkZ - Z) + 0.000001f; //FineTune with that value..., GS
+ const float slope = distanceToCheck / zDist;
+ if(fabs(slope) < 1.00 || (map->GetTerrainType(checkX,checkY) & 0x01))
+ return false;
+ }
+ return true;
+}
+bool WorldObject::HasPathTo(float x, float y)
+{
+
+ const float angleToWho = GetAngle(x,y);
+ const float distanceToWho = GetDistance2d(x,y);
+ float distanceToCheck = 0.5;
+ float X,Y,Z, checkX,checkY,checkZ;
+ GetPosition(X,Y,Z);
+ const Map* map = MapManager::Instance().GetBaseMap(GetMapId());
+ for(;distanceToWho > distanceToCheck; distanceToCheck += 0.5)
+ {
+ checkX = X + (distanceToCheck * cos(angleToWho));
+ checkY = Y + (distanceToCheck * sin(angleToWho));
+ checkZ = map->GetHeight(checkX,checkY,Z);
+ const float zDist = fabs(checkZ - Z) + 0.000001f; //FineTune with that value..., GS
+ const float slope = distanceToCheck / zDist;
+ if(fabs(slope) < 1.00 || (map->GetTerrainType(checkX,checkY) & 0x01) )
+ return false;
+ }
+ return true;
+}
void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float absAngle ) const
{
- x = GetPositionX() + (GetObjectSize() + distance2d) * cos(absAngle);
- y = GetPositionY() + (GetObjectSize() + distance2d) * sin(absAngle);
+ x = GetPositionX() + ((distance2d+GetObjectSize()) * cos(absAngle));
+ y = GetPositionY() + ((distance2d+GetObjectSize()) * sin(absAngle));
}
-
-void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y, float &z, float distance2d, float absAngle ) const
+//Pet Follow Will be wrong there, i think best way will be to specifie if Combat Targeted or Following Targeted, GS
+void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y, float &z, float distance2d, float absAngle) const
{
- float size = searcher ? searcher->GetObjectSize() : 0;
-
- GetNearPoint2D(x,y,distance2d+size,absAngle);
+ //Need to fix that so Pet are not using that distance check, should be since searcher is NULL on pet Follow... But... GS
+ float minReachRadius = searcher ? searcher->GetObjectSize() + (searcher->GetFloatValue(UNIT_FIELD_COMBATREACH)/1.75) : 0;
+ distance2d = distance2d < minReachRadius ? minReachRadius : distance2d;
+ GetNearPoint2D(x,y,distance2d,absAngle);
z = GetPositionZ();
+ const float nz = MapManager::Instance().GetBaseMap(GetMapId())->GetHeight(x,y,z);
+
+ //2D-MG
+ const float zDist = fabs(z - nz) + 0.000001f; //FineTune with that value..., GS
+ const float slope = distance2d / zDist;
+ if(fabs(slope) < 1.00 || (MapManager::Instance().GetBaseMap(GetMapId())->GetTerrainType(x,y) & 0x01)) // Doing Loop To find good One is better and Put Next Update time very High if can find any.
+ {
+ if(searcher)
+ {
+ searcher->GetPosition(x,y,z); // all wrong but for testing... as i say ofent into comment Targeted MV need replacement so.., GS
+ }
+ }
+ return;
+ //All below are such complicated for what we really need for poscollision.
+ //TODO: Update that... will be done in fact from MovementGenerator
// if detection disabled, return first point
if(!sWorld.getConfig(CONFIG_DETECT_POS_COLLISION))
{
@@ -1230,7 +1295,7 @@
bool first_los_conflict = false; // first point LOS problems
// prepare selector for for work
- ObjectPosSelector selector(GetPositionX(),GetPositionY(),GetObjectSize(),distance2d+size);
+ ObjectPosSelector selector(GetPositionX(),GetPositionY(),GetObjectSize(),distance2d+minReachRadius);
// adding used positions around object
{
Index: src/game/Object.h
===================================================================
--- src/game/Object.h (revision 4763)
+++ src/game/Object.h (working copy)
@@ -24,13 +24,14 @@
#include "UpdateFields.h"
#include "UpdateData.h"
#include "GameSystem/GridReference.h"
+#include "../shared/Util.h"
#include <set>
#include <string>
#define CONTACT_DISTANCE 0.5
#define INTERACTION_DISTANCE 5
-#define ATTACK_DISTANCE 5
+#define ATTACK_DISTANCE 5
#define DETECT_DISTANCE 20 // max distance to successful detect stealthed unit
#define MAX_VISIBILITY_DISTANCE (5*SIZE_OF_GRID_CELL/2) // max distance for visible object show, limited by active zone for player based at cell size (active zone = 5x5 cells)
#define DEFAULT_VISIBILITY_DISTANCE (SIZE_OF_GRID_CELL) // default visible distance
@@ -278,17 +279,23 @@
void GetPosition( float &x, float &y, float &z ) const
{ x = m_positionX; y = m_positionY; z = m_positionZ; }
float GetOrientation( ) const { return m_orientation; }
+ bool HasPathTo(WorldObject const* who);
+ bool HasPathTo(float x, float y);
void GetNearPoint2D( float &x, float &y, float distance, float absAngle) const;
- void GetNearPoint( WorldObject const* searcher, float &x, float &y, float &z, float distance2d,float absAngle) const;
+ void GetNearPoint( WorldObject const* follower, float &x, float &y, float &z, float distance2d,float absAngle) const;
void GetClosePoint(float &x, float &y, float &z, float distance2d = 0, float angle = 0) const
{
// angle calculated from current orientation
GetNearPoint(NULL,x,y,z,distance2d,GetOrientation() + angle);
+
}
void GetContactPoint( const WorldObject* obj, float &x, float &y, float &z, float distance2d = CONTACT_DISTANCE) const
{
- // angle to face `obj` to `this` using distance includes size of `obj`
- GetNearPoint(obj,x,y,z,distance2d,GetAngle( obj ));
+ //angle to face `obj` to `this` using distance includes size of `obj`
+ //Will be much more better make a MASK 32 Bits on each Unit... and we make 32 possible solution
+ //16 Front 16 Back... i think will be enought, or 64Bits mask... so 32/32
+ //To replace PosCollision, PosCollision is good system but will better, for a global collision system, GS
+ GetNearPoint(obj,x,y,z,distance2d, /*GetAngle(obj)*/rand_norm()*(M_PI*2));
}
const float GetObjectSize() const
{
Index: src/game/ObjectAccessor.cpp
===================================================================
--- src/game/ObjectAccessor.cpp (revision 4763)
+++ src/game/ObjectAccessor.cpp (working copy)
@@ -604,6 +604,9 @@
update_cell << 1;
update_cell -= 1;
+ //Here is Creating Loop under some Circonstance, GS...
+ // >> / << Update X and +/- Update Y
+ //Seem to happen when we are very near Bondary... of a Grid....
for( ; abs(int32(standing_cell.x_coord) - int32(update_cell.x_coord)) < 2; update_cell >> 1 )
{
for(CellPair cell_iter=update_cell; abs(int32(standing_cell.y_coord) - int32(cell_iter.y_coord)) < 2; cell_iter += 1 )
Index: src/game/ObjectMgr.cpp
===================================================================
--- src/game/ObjectMgr.cpp (revision 4763)
+++ src/game/ObjectMgr.cpp (working copy)
@@ -693,7 +693,11 @@
data.movementType = fields[19].GetUInt8();
data.auras = fields[20].GetCppString();
int16 gameEvent = fields[21].GetInt16();
-
+ if(data.movementType == 1 && data.spawndist <= 0.0f)
+ {
+ sLog.outErrorDb("table creature, GUID:%u , table creature_template, ENTRY:%u , Has RandomMovement but SpawnDist==%f",guid,data.id,data.spawndist);
+ data.movementType = 0;
+ }
if (gameEvent==0) // if not this is to be managed by GameEvent System
AddCreatureToGrid(guid, &data);
count++;
@@ -706,6 +710,191 @@
sLog.outString( ">> Loaded %u creatures", mCreatureDataMap.size() );
}
+void ObjectMgr::LoadCreatureSpellBook()
+{
+
+ QueryResult* _result = WorldDatabase.Query("SELECT * FROM creature_spellbook");
+
+ if(!_result)
+ {
+ barGoLink bar(1);
+
+ bar.step();
+
+ sLog.outString("");
+ sLog.outErrorDb(">> Loaded 0 creature_spellBook definition. DB table `creature_spellBook` is empty.");
+ return;
+ }
+
+ barGoLink bar(_result->GetRowCount());
+
+ do
+ {
+ bar.step();
+ Field *_spellInfo = _result->Fetch();
+ uint32 creatureEntry = _spellInfo[0].GetUInt32();
+ if(!creatureEntry)
+ continue;
+
+ char* _spellId = NULL;
+
+ //spellId, recoveryTime, unknow1, buffDuration, cost, rangeMin, rangeMax
+ for(uint8 itr = CREATURE_SPELL_MIN; itr < CREATURE_SPELL_MAX; ++itr)
+ {
+ const char* rawSpellInfo = _spellInfo[itr+1].GetString();
+ _spellId = strtok((char*)rawSpellInfo, " ");
+ if( _spellId )
+ {
+ uint32 spellId = mCreatureSpellBookMap[creatureEntry].info[itr].id = atoi(_spellId);
+
+ char* _recoveryTime = strtok(NULL, " ");
+ if(_recoveryTime)
+ mCreatureSpellBookMap[creatureEntry].info[itr].recoveryTime = atoi(_recoveryTime);
+
+ char* _castingTime = strtok(NULL, " ");
+ if(_castingTime)
+ mCreatureSpellBookMap[creatureEntry].info[itr].unknow1 = atoi(_castingTime);
+
+ char* _buffDuration = strtok(NULL, " ");
+ if(_buffDuration)
+ mCreatureSpellBookMap[creatureEntry].info[itr].buffDuration = atoi(_buffDuration);
+
+ char* _cost = strtok(NULL, " ");
+ if(_cost)
+ mCreatureSpellBookMap[creatureEntry].info[itr].cost = atoi(_cost);
+
+ char* _rangeMin = strtok(NULL, " ");
+ if(_rangeMin)
+ mCreatureSpellBookMap[creatureEntry].info[itr].range[0] = atof(_rangeMin);
+
+ char* _rangeMax = strtok(NULL, " ");
+ if(_rangeMax)
+ mCreatureSpellBookMap[creatureEntry].info[itr].range[1] = atof(_rangeMax);
+ }
+ }
+
+ SpellEntry const* dbcSpell;
+ SpellRangeEntry const *dbcRange;
+ SpellDurationEntry const *dbcDuration;
+ SpellCastTimesEntry const *dbcCastTime;
+
+ CreatureSpellBookInfoMap::iterator itr = mCreatureSpellBookMap[creatureEntry].info.begin();
+
+ for(; itr != mCreatureSpellBookMap[creatureEntry].info.end(); ++itr)
+ {
+ dbcSpell = GetSpellStore()->LookupEntry(itr->second.id);
+ if( !dbcSpell )
+ continue;
+ dbcRange = GetSpellRangeStore()->LookupEntry(dbcSpell->rangeIndex);
+ dbcDuration = GetSpellDurationStore()->LookupEntry(dbcSpell->DurationIndex);
+ dbcCastTime = GetCastTimesStore()->LookupEntry(dbcSpell->CastingTimeIndex);
+
+ for (int j=0; j<3; j++)
+ {
+ //Spell targets self
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_SELF )
+ itr->second.targets |= 1 << (SELECT_TARGET_SELF-1);
+
+ //Spell targets a single enemy
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_SELECTED_ENEMY )
+ itr->second.targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1);
+
+ //Spell targets AoE at enemy
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED )
+ itr->second.targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1);
+
+ //Spell targets an enemy
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_SELECTED_ENEMY ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED )
+ itr->second.targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1);
+
+ //Spell targets a single friend(or self)
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_SELF ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY )
+ itr->second.targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1);
+
+ //Spell targets aoe friends
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY )
+ itr->second.targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1);
+
+ //Spell targets any friend(or self)
+ if ( dbcSpell->EffectImplicitTargetA[j] == TARGET_SELF ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER ||
+ dbcSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY )
+ itr->second.targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1);
+
+ //Make sure that this spell includes a damage effect
+ if ( dbcSpell->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE ||
+ dbcSpell->Effect[j] == SPELL_EFFECT_INSTAKILL ||
+ dbcSpell->Effect[j] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE ||
+ dbcSpell->Effect[j] == SPELL_EFFECT_HEALTH_LEECH )
+ itr->second.effects |= 1 << (SELECT_EFFECT_DAMAGE-1);
+
+ //Make sure that this spell includes a healing effect
+ if ( dbcSpell->Effect[j] == SPELL_EFFECT_HEAL ||
+ dbcSpell->Effect[j] == SPELL_EFFECT_HEAL_MAX_HEALTH ||
+ dbcSpell->Effect[j] == SPELL_EFFECT_HEAL_MECHANICAL )
+ itr->second.effects |= 1 << (SELECT_EFFECT_HEALING-1);
+
+ //Make sure that this spell applies an aura
+ if( dbcSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA )
+ itr->second.effects |= 1 << (SELECT_EFFECT_AURA-1);
+
+ // Buff Duration
+ if( dbcDuration && itr->second.buffDuration < dbcDuration->Duration[j] )//DBC Info Not Good
+ itr->second.buffDuration = dbcDuration->Duration[j];
+ }
+
+ //We use powerCost from SQL on missing DBC value
+ if( dbcSpell->manaCost )
+ {
+ itr->second.usingDBC = true;
+ itr->second.cost = dbcSpell->manaCost;
+ }
+
+ //CoolDown
+ if( !itr->second.recoveryTime && dbcSpell->RecoveryTime )
+ itr->second.recoveryTime = dbcSpell->RecoveryTime;
+
+ if(dbcRange)
+ {
+ //Range Min
+ if( !itr->second.range[0] )
+ itr->second.range[0] = dbcRange->minRange;
+ //Range Max
+ if( !itr->second.range[1] )//DBC Info Not Good
+ itr->second.range[1] = dbcRange->maxRange;
+ }
+
+ //Casttime
+ if(dbcCastTime && dbcCastTime->CastTime)
+ itr->second.hasCastTime = true;
+ }
+ }while( _result->NextRow() );
+
+ delete _result;
+
+ sLog.outString();
+ sLog.outString( ">> Loaded %u creatures", mCreatureSpellBookMap.size() );
+}
+CreatureSpellBook* ObjectMgr::GetCreatureSpellBook(uint32 entry)
+{
+ CreatureSpellBookMap::iterator itr = mCreatureSpellBookMap.find(entry);
+ if( itr != mCreatureSpellBookMap.end() )
+ return &itr->second;
+ else
+ return NULL;
+}
void ObjectMgr::AddCreatureToGrid(uint32 guid, CreatureData const* data)
{
CellPair cell_pair = MaNGOS::ComputeCellPair(data->posX, data->posY);
Index: src/game/ObjectMgr.h
===================================================================
--- src/game/ObjectMgr.h (revision 4763)
+++ src/game/ObjectMgr.h (working copy)
@@ -45,6 +45,7 @@
extern SQLStorage sCreatureStorage;
extern SQLStorage sCreatureDataAddonStorage;
+//extern SQLStorage sCreatureRawSpellBookStorage;
extern SQLStorage sCreatureInfoAddonStorage;
extern SQLStorage sCreatureModelStorage;
extern SQLStorage sEquipmentStorage;
@@ -74,7 +75,6 @@
float z;
float o;
};
-
typedef std::multimap<uint32, ScriptInfo> ScriptMap;
typedef std::map<uint32, ScriptMap > ScriptMapMap;
extern ScriptMapMap sQuestEndScripts;
@@ -115,6 +115,7 @@
typedef HM_NAMESPACE::hash_map<uint64/*(instance,guid) pair*/,time_t> RespawnTimes;
+typedef HM_NAMESPACE::hash_map<uint32,CreatureSpellBook> CreatureSpellBookMap;
typedef HM_NAMESPACE::hash_map<uint32,CreatureData> CreatureDataMap;
typedef HM_NAMESPACE::hash_map<uint32,GameObjectData> GameObjectDataMap;
typedef HM_NAMESPACE::hash_map<uint32,CreatureLocale> CreatureLocaleMap;
@@ -267,15 +268,16 @@
void RemoveArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.erase( arenateam ); }
CreatureInfo const *GetCreatureTemplate( uint32 id );
+
CreatureModelInfo const *GetCreatureModelInfo( uint32 modelid );
CreatureModelInfo const* GetCreatureModelRandomGender(uint32 display_id);
uint32 ChooseDisplayId(uint32 team, const CreatureInfo *cinfo, const CreatureData *data);
EquipmentInfo const *GetEquipmentInfo( uint32 entry );
+
static CreatureDataAddon const *GetCreatureAddon( uint32 lowguid )
{
return sCreatureDataAddonStorage.LookupEntry<CreatureDataAddon>(lowguid);
}
-
static CreatureDataAddon const *GetCreatureTemplateAddon( uint32 entry )
{
return sCreatureInfoAddonStorage.LookupEntry<CreatureDataAddon>(entry);
@@ -464,6 +466,8 @@
void LoadCreatureRespawnTimes();
void LoadCreatureAddons();
void LoadCreatureModelInfo();
+ void LoadCreatureSpellBook();
+ CreatureSpellBook* GetCreatureSpellBook(uint32 entry);
void LoadEquipmentTemplates();
void LoadGameObjectLocales();
void LoadGameobjects();
@@ -821,6 +825,7 @@
MapObjectGuids mMapObjectGuids;
CreatureDataMap mCreatureDataMap;
CreatureLocaleMap mCreatureLocaleMap;
+ CreatureSpellBookMap mCreatureSpellBookMap;
GameObjectDataMap mGameObjectDataMap;
GameObjectLocaleMap mGameObjectLocaleMap;
ItemLocaleMap mItemLocaleMap;
@@ -836,6 +841,6 @@
typedef HM_NAMESPACE::hash_map<uint32, SpellProcEventEntry> SpellProcEventMap;
SpellProcEventMap mSpellProcEventMap;
};
-
+//SQLStorage const* GetCreaturesSpellsBooks() {return &sCreatureSpellBookStorage;}
#define objmgr MaNGOS::Singleton<ObjectMgr>::Instance()
#endif
Index: src/game/Pet.h
===================================================================
--- src/game/Pet.h (revision 4763)
+++ src/game/Pet.h (working copy)
@@ -100,11 +100,12 @@
#define ACTIVE_SPELLS_MAX 4
-#define OWNER_MAX_DISTANCE 100
+#define OWNER_MAX_DISTANCE 100.0f
-#define PET_FOLLOW_DIST 1
-#define PET_FOLLOW_ANGLE (M_PI/2)
+#define PET_FOLLOW_DIST 2.0f
+#define PET_FOLLOW_ANGLE (M_PI/2.0f)
+
class Pet : public Creature
{
public:
Index: src/game/PetAI.cpp
===================================================================
--- src/game/PetAI.cpp (revision 4763)
+++ src/game/PetAI.cpp (working copy)
@@ -42,41 +42,80 @@
UpdateAllies();
}
-void PetAI::MoveInLineOfSight(Unit *u)
+void PetAI::MoveInLineOfSight(Unit *who)
{
- if( !i_pet.getVictim() && (i_pet.isPet() || i_pet.isCharmed()) && i_pet.GetCharmInfo()->HasReactState(REACT_AGGRESSIVE) &&
- u->isTargetableForAttack() && i_pet.IsHostileTo( u ) &&
- u->isInAccessablePlaceFor(&i_pet))
+ if( i_pet.GetCharmInfo() )
{
- float attackRadius = i_pet.GetAttackDistance(u);
- if(i_pet.IsWithinDistInMap(u, attackRadius) && i_pet.GetDistanceZ(u) <= CREATURE_Z_ATTACK_RANGE)
+ //Planning something to get Rid of all Z check like that will be great since it wrong, GS
+ if( !i_pet.HasPathTo(who) )
+ return;
+
+ if( !i_pet.GetUInt64Value(UNIT_FIELD_TARGET) )
{
- if(!i_pet.IsWithinLOSInMap(u)) return;
- AttackStart(u);
- u->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
+ if( i_pet.GetCharmInfo()->HasReactState(REACT_AGGRESSIVE))
+ {
+ if( i_pet.IsWithinDistInMap(who,RANGE_AUTO_ASSIST_PET ) && i_pet.IsFriendlyTo(who) )
+ {
+ if(!i_pet.IsWithinLOSInMap(who))
+ return;
+
+ //TODO: make it with IsInCombat() + Take target from AttackerList.
+ if(!who->getAttackers().empty())
+ {
+ Unit* victimTarget = *(who->getAttackers().begin());
+ if( i_pet.IsHostileTo(victimTarget) && (Unit::getHpPercent(victimTarget) < 100 || Unit::getHpPercent(who) < 100)
+ && i_pet.IsWithinDistInMap(victimTarget, 46.0f) ) //Just a safe distance.
+ AttackStart( victimTarget );
+ }
+ }
+ return;
+ }
+
+ if((i_pet.GetCharmInfo()->HasReactState(REACT_DEFENSIVE) && Unit::getHpPercent(who) < 100))
+ {
+ if( i_pet.IsWithinDistInMap(who,RANGE_AUTO_ASSIST_PET ) && i_pet.IsFriendlyTo(who) )
+ {
+ if(!i_pet.IsWithinLOSInMap(who))
+ return;
+
+ //TODO: make it with IsInCombat() + Take target from AttackerList.
+ if(!who->getAttackers().empty())
+ {
+ Unit* victimTarget = *(who->getAttackers().begin());
+ if( i_pet.IsHostileTo(victimTarget) && i_pet.IsWithinDistInMap(victimTarget, 46.0f)) //Just a safe distance.
+ AttackStart( victimTarget );
+ }
+ }
+ }
}
}
}
-void PetAI::AttackStart(Unit *u)
+void PetAI::AttackStart(Unit *unit)
{
- if( i_pet.getVictim() || !u || i_pet.isPet() && ((Pet&)i_pet).getPetType()==MINI_PET )
+ if( !unit || i_pet.isPet() && ((Pet&)i_pet).getPetType()==MINI_PET )
return;
- if(i_pet.Attack(u))
+ if( unit->isTargetableForAttack() && i_pet.HasPathTo(unit))
{
- i_pet.clearUnitState(UNIT_STAT_FOLLOW);
- // TMGs call CreatureRelocation which via MoveInLineOfSight can call this function
- // thus with the following clear the original TMG gets invalidated and crash, doh
- // hope it doesn't start to leak memory without this :-/
- //i_pet->Clear();
- i_victimGuid = u->GetGUID();
- i_pet.GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*u));
+ if ( i_pet.Attack(unit) )
+ {
+ i_pet.AddThreat(unit, 0.0f);
+ i_pet.resetAttackTimer();
+ if(i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
+ AIMotionTarget(unit,FOLLOW_RANGE_MELEE);
+
+ return;
+ }else if( i_pet.getVictim() == unit && i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW) ) //HackWay... Cause Attack() will return false if same attacker.
+ AIMotionTarget(unit,FOLLOW_RANGE_MELEE);
}
}
void PetAI::EnterEvadeMode()
{
+ i_pet.DeleteThreatList();
+ i_pet.AttackStop();
+ i_pet.ClearInCombat(false);
}
bool PetAI::IsVisible(Unit *pl) const
@@ -98,136 +137,50 @@
void PetAI::_stopAttack()
{
- if( !i_victimGuid )
- return;
+ EnterEvadeMode();
+}
- Unit* victim = ObjectAccessor::Instance().GetUnit(i_pet, i_victimGuid );
-
- if ( !victim )
+void PetAI::UpdateAI(const uint32 diff)
+{
+ Unit* owner = i_pet.GetCharmerOrOwner();
+ if(!owner)
return;
- assert(!i_pet.getVictim() || i_pet.getVictim() == victim);
-
- if( !i_pet.isAlive() )
+ // update i_victimGuid if i_pet.getVictim() !=0 and changed
+ if(!i_pet.getVictim() && !i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE))
{
- DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", i_pet.GetGUIDLow());
- i_pet.StopMoving();
- i_pet.GetMotionMaster()->Clear();
- i_pet.GetMotionMaster()->Idle();
- i_victimGuid = 0;
- i_pet.CombatStop(true);
- i_pet.getHostilRefManager().deleteReferences();
+
+ Unit* ownerAttacker = owner->getAttackerForHelper();
+ if(ownerAttacker)
+ {
- return;
+ if(i_pet.GetCharmInfo()->HasReactState(REACT_AGGRESSIVE) && (Unit::getHpPercent(ownerAttacker) < 100 || Unit::getHpPercent(owner) < 100))
+ AttackStart(ownerAttacker);
+ else if(Unit::getHpPercent(owner) < 100)
+ AttackStart(ownerAttacker);
+ }
}
- else if( !victim )
- {
- DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_pet.GetGUIDLow());
- }
- else if( !victim->isAlive() )
- {
- DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", i_pet.GetGUIDLow());
- }
- else if( victim->HasStealthAura() )
- {
- DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_pet.GetGUIDLow());
- }
- else if( victim->isInFlight() )
- {
- DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_pet.GetGUIDLow());
- }
- else
- {
- DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", i_pet.GetGUIDLow());
- }
- Unit* owner = i_pet.GetCharmerOrOwner();
-
- if(owner && i_pet.GetCharmInfo() && i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
- {
- i_pet.addUnitState(UNIT_STAT_FOLLOW);
- i_pet.GetMotionMaster()->Clear();
- i_pet.GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE));
- }
- else
- {
- i_pet.clearUnitState(UNIT_STAT_FOLLOW);
- i_pet.addUnitState(UNIT_STAT_STOPPED);
- i_pet.GetMotionMaster()->Clear();
- i_pet.GetMotionMaster()->Idle();
- }
- i_victimGuid = 0;
- i_pet.AttackStop();
-}
-
-void PetAI::UpdateAI(const uint32 diff)
-{
- // update i_victimGuid if i_pet.getVictim() !=0 and changed
- if(i_pet.getVictim())
- i_victimGuid = i_pet.getVictim()->GetGUID();
-
- Unit* owner = i_pet.GetCharmerOrOwner();
-
if(m_updateAlliesTimer <= diff)
// UpdateAllies self set update timer
UpdateAllies();
else
m_updateAlliesTimer -= diff;
-
- // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc.
- if( i_victimGuid )
+
+ if( !i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) && !_needToStop() )
{
- if( _needToStop() )
+ if( i_pet.isAttackReady() && i_pet.IsWithinDistInMap(i_pet.getVictim(), i_pet.GetFloatValue(UNIT_FIELD_COMBATREACH)) )
{
- DEBUG_LOG("Pet AI stoped attacking [guid=%u]", i_pet.GetGUIDLow());
- _stopAttack(); // i_victimGuid == 0 && i_pet.getVictim() == NULL now
- return;
+ i_pet.AttackerStateUpdate(i_pet.getVictim());
+ i_pet.resetAttackTimer();
+ i_pet.SelectHostilTarget();
}
- else if( i_pet.IsStopped() || i_pet.IsWithinDistInMap(i_pet.getVictim(), ATTACK_DISTANCE))
- {
- // required to be stopped cases
- if ( i_pet.IsStopped() && i_pet.IsNonMeleeSpellCasted(false) )
- {
- if( i_pet.hasUnitState(UNIT_STAT_FOLLOW) )
- i_pet.InterruptNonMeleeSpells(false);
- else
- return;
- }
- // not required to be stopped case
- else if( i_pet.isAttackReady() && i_pet.canReachWithAttack(i_pet.getVictim()) )
- {
- i_pet.AttackerStateUpdate(i_pet.getVictim());
-
- i_pet.resetAttackTimer();
-
- if ( !i_pet.getVictim() )
- return;
-
- //if pet misses its target, it will also be the first in threat list
- i_pet.getVictim()->AddThreat(&i_pet,0.0f);
-
- if( _needToStop() )
- _stopAttack();
- }
- }
}
- else if(owner && i_pet.GetCharmInfo())
+ if( i_pet.isInCombat() && _needToStop() )
{
- if(owner->isInCombat() && !(i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) || i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY)))
- {
- AttackStart(owner->getAttackerForHelper());
- }
- else if(i_pet.GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
- {
- if (!i_pet.hasUnitState(UNIT_STAT_FOLLOW) )
- {
- i_pet.addUnitState(UNIT_STAT_FOLLOW);
- i_pet.GetMotionMaster()->Clear();
- i_pet.GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*owner,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE));
- }
- }
+ _stopAttack();
+ return;
}
-
//Autocast
HM_NAMESPACE::hash_map<uint32, Unit*> targetMap;
targetMap.clear();
@@ -242,7 +195,7 @@
Spell *spell = new Spell(&i_pet, spellInfo, false, 0);
- if(!IsPositiveSpell(spellInfo->Id) && i_pet.getVictim() && !_needToStop() && !i_pet.hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(i_pet.getVictim()))
+ if(!IsPositiveSpell(spellInfo->Id) && i_pet.getVictim() && !_needToStop() /*&& !i_pet.hasUnitState(UNIT_STAT_FOLLOW)*/ && spell->CanAutoCast(i_pet.getVictim()))
targetMap[spellID] = i_pet.getVictim();
else
{
@@ -294,6 +247,8 @@
spell->prepare(&targets);
}
targetMap.clear();
+
+ //if(i_pet.getVictim())
}
bool PetAI::_isVisible(Unit *u) const
@@ -342,10 +297,48 @@
m_AllySet.insert(owner->GetGUID());
}
-void PetAI::AttackedBy(Unit *attacker)
+void PetAI::AIMotionTarget(Unit* target, float offSet)
{
+ bool exist = false;
+ MotionMaster* creatureMM = i_pet.GetMotionMaster();
+
+ if(!target /*&& creatureMM->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE*/)
+ {
+ //creatureMM->MovementExpired();
+ return;
+ }
+ //Here is wrong... TODO fix angle... but in fact i wan MV for Follower and One for Attacker.
+ float angle = NULL;
+ if( !i_pet.IsHostileTo(target) )
+ {
+ angle = target->GetOrientation()*2.0f;
+ }
+
+ if(creatureMM->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ {
+ TargetedMovementGenerator<Creature>* targetMV = static_cast<TargetedMovementGenerator<Creature>*> (creatureMM->top());
+ if( targetMV && targetMV->GetTarget() )
+ {
+ if( targetMV->GetTarget()->GetGUID() != target->GetGUID() )
+ {
+ creatureMM->MovementExpired(false);
+ creatureMM->Mutate(new TargetedMovementGenerator<Creature>(*target,offSet,angle));
+ }
+ else if(targetMV->GetOffSet() != offSet)
+ targetMV->SetOffSet(offSet);
+ }
+ }
+ else
+ {
+ i_pet.GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*target,offSet,angle));
+ }
+}
+
+/*void PetAI::AttackedBy(Unit *attacker)
+{
//when attacked, fight back in case 1)no victim already AND 2)not set to passive AND 3)not set to stay, unless can it can reach attacker with melee attack anyway
if(!i_pet.getVictim() && i_pet.GetCharmInfo() && !i_pet.GetCharmInfo()->HasReactState(REACT_PASSIVE) &&
(!i_pet.GetCharmInfo()->HasCommandState(COMMAND_STAY) || i_pet.canReachWithAttack(attacker)))
AttackStart(attacker);
}
+*/
Index: src/game/PetAI.h
===================================================================
--- src/game/PetAI.h (revision 4763)
+++ src/game/PetAI.h (working copy)
@@ -34,7 +34,7 @@
void AttackStart(Unit *);
void EnterEvadeMode();
void DamageTaken(Unit *done_by, uint32 &damage) { AttackedBy(done_by); }
- void AttackedBy(Unit *attacker);
+ void AttackedBy(Unit *attacker) {}
bool IsVisible(Unit *) const;
void UpdateAI(const uint32);
@@ -45,6 +45,7 @@
bool _isVisible(Unit *) const;
bool _needToStop(void) const;
void _stopAttack(void);
+ void AIMotionTarget(Unit *, float);
Creature &i_pet;
uint64 i_victimGuid;
Index: src/game/PetHandler.cpp
===================================================================
--- src/game/PetHandler.cpp (revision 4763)
+++ src/game/PetHandler.cpp (working copy)
@@ -26,6 +26,7 @@
#include "Spell.h"
#include "ObjectAccessor.h"
#include "MapManager.h"
+#include "IdleMovementGenerator.h"
#include "TargetedMovementGenerator.h"
#include "CreatureAI.h"
#include "Util.h"
@@ -71,46 +72,51 @@
sLog.outError("WorldSession::HandlePetAction: object "I64FMTD" is considered pet-like but doesn't have a charminfo!", pet->GetGUID());
return;
}
-
+ //All here was wrong... i just tryed to make my own version, until i got real data from official, GS
+ // I have the good data from official and will have some probleme doing the defencive Status.. all other will be much more sample
+ // then the actual one :) , GS
switch(flag)
{
case ACT_COMMAND: //0x0700
switch(spellid)
{
case COMMAND_STAY: //flat=1792 //STAY
- pet->StopMoving();
- pet->GetMotionMaster()->Clear();
- pet->GetMotionMaster()->Idle();
+ if(!pet->hasUnitState(UNIT_STAT_FOLLOW))
+ break;
+ if(pet->GetMotionMaster()->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ pet->GetMotionMaster()->MovementExpired();
+
+ //Will be possible to him to overide Fleeing MV, Check this out, GS
+ //In fact FleeingMV should not accept to be Overide so the fix should be very great that way.
+ //I must be able to add a new MG but at index (top() - 1)
+ pet->GetMotionMaster()->Mutate(new IdleMovementGenerator(*pet));
+ pet->clearUnitState(UNIT_STAT_FOLLOW);
charmInfo->SetCommandState( COMMAND_STAY );
break;
case COMMAND_FOLLOW: //spellid=1792 //FOLLOW
- pet->AttackStop();
- pet->addUnitState(UNIT_STAT_FOLLOW);
+ //Here i use clear() to return to originalMG, but fear must not be overide here.. so same as STAY.. solution will come later, GS
pet->GetMotionMaster()->Clear();
- pet->GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*_player,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE));
+ pet->addUnitState(UNIT_STAT_FOLLOW);
+ ((Creature*)pet)->AI()->EnterEvadeMode();
charmInfo->SetCommandState( COMMAND_FOLLOW );
break;
case COMMAND_ATTACK: //spellid=1792 //ATTACK
{
- // only place where pet can be player
- pet->clearUnitState(UNIT_STAT_FOLLOW);
uint64 selguid = _player->GetSelection();
Unit *TargetUnit = ObjectAccessor::Instance().GetUnit(*_player, selguid);
- if(TargetUnit == NULL) return;
+ if(TargetUnit == NULL)
+ return;
- // not let attack friendly units.
if( GetPlayer()->IsFriendlyTo(TargetUnit))
return;
- if(pet->getVictim() && TargetUnit!=pet->getVictim())
- pet->AttackStop();
+ if(((Creature*)pet)->AI())
+ ((Creature*)pet)->AI()->AttackStart(TargetUnit);
- if(pet->GetTypeId() != TYPEID_PLAYER)
+ break;
+ //TODO: check this out and add it correctely
+ /*if(pet->GetTypeId() != TYPEID_PLAYER)
{
- pet->GetMotionMaster()->Clear();
- if (((Creature*)pet)->AI())
- ((Creature*)pet)->AI()->AttackStart(TargetUnit);
-
//10% chance to play special pet attack talk, else growl
if(((Creature*)pet)->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10)
pet->SendPetTalk((uint32)PET_TALK_ATTACK);
@@ -119,13 +125,8 @@
// 90% chance for pet and 100% chance for charmed creature
pet->SendPetAIReaction(guid1);
}
- }
- else // charmed player
- {
- pet->Attack(TargetUnit);
- pet->SendPetAIReaction(guid1);
- }
- break;
+ break;
+ }*/
}
case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet)
if(((Creature*)pet)->isPet())
@@ -151,7 +152,6 @@
case REACT_DEFENSIVE: //recovery
case REACT_AGGRESSIVE: //activete
charmInfo->SetReactState( ReactStates(spellid) );
- break;
}
break;
case ACT_DISABLED: //0x8100 spell (disabled), ignore
@@ -182,8 +182,6 @@
if(!pet->HasSpell(spellid) || IsPassiveSpell(spellid))
return;
- pet->clearUnitState(UNIT_STAT_FOLLOW);
-
Spell *spell = new Spell(pet, spellInfo, false, 0);
int16 result = spell->PetCanCast(unit_target);
@@ -218,10 +216,6 @@
if( unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->HasAuraType(SPELL_AURA_MOD_POSSESS))
{
- pet->clearUnitState(UNIT_STAT_FOLLOW);
- if(unit_target!=pet->getVictim())
- pet->AttackStop();
- pet->GetMotionMaster()->Clear();
if (((Creature*)pet)->AI())
((Creature*)pet)->AI()->AttackStart(unit_target);
}
@@ -569,8 +563,6 @@
if(!targets.read(&recvPacket,pet))
return;
- pet->clearUnitState(UNIT_STAT_FOLLOW);
-
Spell *spell = new Spell(pet, spellInfo, false, 0);
spell->m_targets = targets;
Index: src/game/RandomMovementGenerator.cpp
===================================================================
--- src/game/RandomMovementGenerator.cpp (revision 4763)
+++ src/game/RandomMovementGenerator.cpp (working copy)
@@ -22,124 +22,105 @@
#include "RandomMovementGenerator.h"
#include "DestinationHolderImp.h"
-/*
-Here interpolation is disabled by default due to it causing crashing
-in some compile environments.
-If your server can handle the small amount of lag this may cause
-and you can build without experiencing a significant increase in crashes
-then you may uncomment the following line to have correct random motion.
-*/
-// uncomment now for wide testing purpose
-#define USE_INTERPOLATION
+#define RUNNING_CHANCE_RANDOMMV 20 //will be "1 / RUNNING_CHANCE_RANDOMMV"
-template<>
-void
-RandomMovementGenerator<Creature>::Initialize(Creature &creature)
+template<> void RandomMovementGenerator<Creature>::_setRandomLocation(Creature &creature)
{
- float x,y,z,z2, wander_distance;
- creature.GetRespawnCoord(x, y, z);
- creature.GetRespawnDist(wander_distance);
- uint32 mapid=creature.GetMapId();
+ //Doing temporay Use of this Generator for Pet.... But still need it Own.. with Life Feature ;), GS
+ float X,Y,Z,z,nx,ny,nz,wander_distance;
- Map const* map = MapManager::Instance().GetBaseMap(mapid);
- // Initialization is done in bulk. Don’t use vamps for that (4. parameter = false). It is too costly when entering a new map grid
- z2 = map->GetHeight(x,y,z, false);
- if( fabs( z2 - z ) < 5 )
- z = z2;
-
- i_nextMove = 1;
- i_waypoints[0][0] = x;
- i_waypoints[0][1] = y;
- i_waypoints[0][2] = z;
-
- bool is_water_ok = creature.isCanSwimOrFly();
- bool is_land_ok = creature.isCanWalkOrFly();
-
- for(unsigned int idx=1; idx < MAX_RAND_WAYPOINTS+1; ++idx)
+ if( creature.isPet() )
{
- const float angle = 2*M_PI*rand_norm();
- const float range = wander_distance*rand_norm();
+ if( !creature.GetOwner() )
+ return;
+ creature.GetOwner()->GetPosition(X, Y, Z);
+ wander_distance = (rand_norm()*PET_FOLLOW_DIST)+2.5f;
+ }
+ else
+ {
+ creature.GetRespawnCoord(X, Y, Z);
+ creature.GetRespawnDist(wander_distance);
+ }
- i_waypoints[idx][0] = x+ range * cos(angle);
- i_waypoints[idx][1] = y+ range * sin(angle);
+ z = creature.GetPositionZ();
+ uint32 mapid=creature.GetMapId();
+ Map const* map = MapManager::Instance().GetBaseMap(mapid);
- // prevent invalid coordinates generation
- MaNGOS::NormalizeMapCoord(i_waypoints[idx][0]);
- MaNGOS::NormalizeMapCoord(i_waypoints[idx][1]);
+ //Both water and fly , will do later... since will be cool to select random Z and will need to check dist into 3d
+ //bool is_water_ok = creature.isCanSwimOrFly();
+ //bool is_land_ok = creature.isCanWalkOrFly();
+ const float angle = rand_norm()*(M_PI*2);
+ srand(getMSTime());
+ const float range = rand_norm()*wander_distance;
+ const float distanceX = range * cos(angle);
+ const float distanceY = range * sin(angle);
+ const float distanceZ = range * tan(angle);
+ nx = X + distanceX;
+ ny = Y + distanceY;
+ //nz = Z + distanceZ; //3D-MG
+ nz = map->GetHeight(nx,ny,Z);
+
+ //2D-MG
+ const float groundDist = sqrt(distanceX*distanceX + distanceY*distanceY);
+ const float zDist = fabs(z - nz) + 0.000001f; //FineTune with that value..., GS
+ const float slope = groundDist / zDist;
+ if(fabs(slope) < 1.0f || (map->GetTerrainType(nx,ny) & 0x01))
+ nz = Z;
- bool is_water = map->IsInWater(i_waypoints[idx][0],i_waypoints[idx][1],z);
- // if generated wrong path just ignore
- if( is_water && !is_water_ok || !is_water && !is_land_ok )
- {
- i_waypoints[idx][0] = i_waypoints[idx-1][0];
- i_waypoints[idx][1] = i_waypoints[idx-1][1];
- i_waypoints[idx][2] = i_waypoints[idx-1][2];
- continue;
- }
+ Traveller<Creature> traveller(creature);
+ creature.SetOrientation(creature.GetAngle(nx,ny));
+ i_destinationHolder.SetDestination(traveller, nx, ny, nz);
+ i_nextMoveTime.Reset(rand32(500+i_destinationHolder.GetTotalTravelTime(),5000+i_destinationHolder.GetTotalTravelTime()));
+ creature.addUnitState(UNIT_STAT_ROAMING);
+}
- // Initialization is done in bulk. Don’t use vamps for that (4. parameter = false). It is too costly when entering a new map grid
- z2 = map->GetHeight(i_waypoints[idx][0],i_waypoints[idx][1],z, false);
- if( fabs( z2 - z ) < 5 )
- z = z2;
- i_waypoints[idx][2] = z;
- }
- i_nextMoveTime.Reset(urand(0, 10000-1)); // TODO: check the lower bound (it is probably too small)
- creature.StopMoving();
+template<> void RandomMovementGenerator<Creature>::Initialize(Creature &creature)
+{
+ if(!&creature || !creature.isAlive())
+ return;
+
+ creature.setMoveRunFlag(irand(0,RUNNING_CHANCE_RANDOMMV) ? false : true);
+ _setRandomLocation(creature);
}
-template<>
-void
-RandomMovementGenerator<Creature>::Reset(Creature &creature)
+template<> void RandomMovementGenerator<Creature>::Reset(Creature &creature)
{
- i_nextMove = 1;
- i_nextMoveTime.Reset(urand(0,10000-1)); // TODO: check the lower bound (it is probably too small)
- creature.StopMoving();
+ Initialize(creature);
}
-template<>
-bool
-RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
+template<> bool RandomMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
{
+ //During a creature death... we will request at each 300Ms the delete of tha Motion... But he can be the index 0
+ //Not creating any probleme... but suck cpu for absolute nothing
if(!&creature)
+ return false;
+
+ if(!creature.isAlive())
+ {
+ i_nextMoveTime.Reset(3000);
return true;
- if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED))
- return true;
+ }
+
i_nextMoveTime.Update(diff);
- #ifdef USE_INTERPOLATION
+
+ if(i_destinationHolder.HasArrived() && !creature.IsStopped())
+ creature.clearUnitState(UNIT_STAT_ROAMING);
+
+ if(!i_destinationHolder.HasArrived() && creature.IsStopped())
+ creature.addUnitState(UNIT_STAT_ROAMING);
+
CreatureTraveller traveller(creature);
- i_destinationHolder.UpdateTraveller(traveller, diff, false);
- #endif
- if( i_nextMoveTime.Passed() )
+ if( i_destinationHolder.UpdateTraveller(traveller, diff, false) )
{
- if( creature.IsStopped() )
+ if(i_nextMoveTime.Passed())
{
- assert( i_nextMove <= MAX_RAND_WAYPOINTS );
- const float x = i_waypoints[i_nextMove][0];
- const float y = i_waypoints[i_nextMove][1];
- const float z = i_waypoints[i_nextMove][2];
- creature.addUnitState(UNIT_STAT_ROAMING);
- CreatureTraveller traveller(creature);
- i_destinationHolder.SetDestination(traveller, x, y, z);
- #ifndef USE_INTERPOLATION
- traveller.Relocation(x,y,z);
- #endif
- i_nextMoveTime.Reset( i_destinationHolder.GetTotalTravelTime() );
+ creature.setMoveRunFlag(irand(0,20) ? false : true);
+ _setRandomLocation(creature);
}
- else
+ else if(creature.isPet() && creature.GetOwner() && creature.GetDistance(creature.GetOwner()) > PET_FOLLOW_DIST+2.5f)
{
- creature.StopMoving();
- creature.setMoveRunFlag(!urand(0,10));
-
- ++i_nextMove;
- if( i_nextMove == MAX_RAND_WAYPOINTS )
- {
- i_nextMove = 0;
- i_nextMoveTime.Reset(urand(0, 3000-1)); // TODO: check the lower bound (it is probably too small)
- }
- else
- {
- i_nextMoveTime.Reset(urand(0, 7000-1)); // TODO: check the lower bound (it is probably too small)
- }
+ creature.setMoveRunFlag(true);
+ _setRandomLocation(creature);
}
}
return true;
Index: src/game/RandomMovementGenerator.h
===================================================================
--- src/game/RandomMovementGenerator.h (revision 4763)
+++ src/game/RandomMovementGenerator.h (working copy)
@@ -23,7 +23,6 @@
#include "DestinationHolder.h"
#include "Traveller.h"
-#define MAX_RAND_WAYPOINTS 8
template<class T>
class MANGOS_DLL_DECL RandomMovementGenerator
@@ -32,14 +31,18 @@
public:
RandomMovementGenerator(const Unit &) : i_nextMoveTime(0) {}
+ void _setRandomLocation(T &);
void Initialize(T &);
void Reset(T &);
bool Update(T &, const uint32 &);
-
+ void UpdateMapPosition(float &x ,float &y, float &z)
+ {
+ i_destinationHolder.GetLocationNow(x,y,z);
+ }
MovementGeneratorType GetMovementGeneratorType() { return RANDOM_MOTION_TYPE; }
private:
- TimeTracker i_nextMoveTime;
- float i_waypoints[MAX_RAND_WAYPOINTS+1][3];
+ TimeTracker2 i_nextMoveTime;
+ //float i_waypoints[MAX_RAND_WAYPOINTS+1][3];
DestinationHolder< Traveller<T> > i_destinationHolder;
uint32 i_nextMove;
};
Index: src/game/ReactorAI.cpp
===================================================================
--- src/game/ReactorAI.cpp (revision 4763)
+++ src/game/ReactorAI.cpp (working copy)
@@ -41,19 +41,26 @@
}
void
-ReactorAI::AttackStart(Unit *p)
+ReactorAI::AttackStart(Unit *unit)
{
- if(!p)
+ if( !unit )
return;
- if(i_creature.Attack(p))
+ if( unit->isTargetableForAttack() /*&& attacker!= m_creature, That should not happen*/ )
{
- DEBUG_LOG("Tag unit GUID: %u (TypeId: %u) as a victim", p->GetGUIDLow(), p->GetTypeId());
- i_creature.AddThreat(p, 0.0f);
- i_victimGuid = p->GetGUID();
- i_creature.GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*p));
- if (p->GetTypeId() == TYPEID_PLAYER)
- i_creature.SetLootRecipient((Player*)p);
+ if ( i_creature.Attack(unit) )
+ {
+ i_creature.AddThreat(unit, 0.0f);
+ selectedAttackRadius = i_creature.GetAttackDistance(unit);
+ i_creature.resetAttackTimer();
+
+ if (unit->GetTypeId() == TYPEID_PLAYER)
+ i_creature.SetLootRecipient((Player*)unit);
+
+ AIMotionTarget(unit,FOLLOW_RANGE_MELEE);
+
+ return;
+ }
}
}
@@ -66,61 +73,86 @@
void
ReactorAI::UpdateAI(const uint32 time_diff)
{
- // update i_victimGuid if i_creature.getVictim() !=0 and changed
- if(!i_creature.SelectHostilTarget() || !i_creature.getVictim())
+ if( i_creature.isDead() || i_creature.hasUnitState( UNIT_STAT_FLEEING ) )
return;
- i_victimGuid = i_creature.getVictim()->GetGUID();
-
- if( i_creature.IsWithinDistInMap(i_creature.getVictim(), ATTACK_DISTANCE))
- {
- if( i_creature.isAttackReady() )
+ //RunAway At friend
+ if( !i_creature.hasUnitState( UNIT_STAT_ROOT ) && selectedAttackRadius <= irand(0,40) && i_creature.getVictim() && Unit::getHpPercent(&i_creature)+irand(1,20) < Unit::getHpPercent(i_creature.getVictim()) )
+ {
+ if( !i_creature.m_AssistenceStatus->requested )
{
- i_creature.AttackerStateUpdate(i_creature.getVictim());
- i_creature.resetAttackTimer();
+ i_creature.CastSpell( (Unit*)&i_creature, CREATURE_SPELL_TAP_FRIEND, false );
+ i_creature.m_AssistenceStatus->requested = true;
+ return;
}
+ //Check spell http://www.wowhead.com/?spell=32126, who is Flee Combat Much More Better, and keep fear when no combat
+ else if(i_creature.m_AssistenceStatus->obtained = false && Unit::getHpPercent(&i_creature) < irand(7,14) )
+ i_creature.CastSpell( (Unit*)&i_creature, CREATURE_SPELL_RUNAWAY, false ,NULL,NULL, i_creature.GetUInt64Value(UNIT_FIELD_TARGET));
}
-}
+
+ if( i_creature.SelectHostilTarget() && i_creature.getVictim() && i_creature.isAttackReady() && i_creature.IsWithinDistInMap(i_creature.getVictim(), i_creature.GetFloatValue(UNIT_FIELD_COMBATREACH)) )
+ {
+ //TODO:Add a Chance To win and Go to Friend.
+ i_creature.AttackerStateUpdate(i_creature.getVictim());
+ i_creature.resetAttackTimer();
+ lastAction = getMSTime();
+ }
-void
-ReactorAI::EnterEvadeMode()
-{
- if( !i_creature.isAlive() )
+ //Wait Time Reset Action Selected, TODO: Change that to put more dynamic action at different timer.
+ //A text Chat can be done there, will be cool.
+ //Do search on wowhead for Gossip before any chat text system.
+ if(lastAction+irand(5000*CREATURE_WAIT_RATE,7000*CREATURE_WAIT_RATE) < getMSTime() )
{
- DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", i_creature.GetGUIDLow());
- i_creature.GetMotionMaster()->MovementExpired();
- i_creature.GetMotionMaster()->Idle();
- i_victimGuid = 0;
- i_creature.CombatStop(true);
- i_creature.DeleteThreatList();
- return;
+ i_creature.m_AssistenceStatus->reset();
+
+ i_creature.SelectHostilTarget();
+
+ lastAction = getMSTime();
}
+}
- Unit* victim = ObjectAccessor::Instance().GetUnit(i_creature, i_victimGuid );
+void ReactorAI::EnterEvadeMode()
+{
+ lastAction = getMSTime()+30000;
+ i_creature.m_AssistenceStatus->reset(); //TODO: fix that scruct, at least make it proctected
+ if( !i_creature.isCharmed() )
+ i_creature.RemoveAllAuras();
+ i_creature.DeleteThreatList();
+ i_creature.CombatStop(true);
+}
+void ReactorAI::AIMotionTarget(Unit* target, float offSet)
+{
+ bool exist = false;
+ MotionMaster* creatureMM = i_creature.GetMotionMaster();
- if( !victim )
+ if(!target /*&& creatureMM->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE*/)
{
- DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_creature.GetGUIDLow());
+ //creatureMM->MovementExpired();
+ return;
}
- else if( victim->HasStealthAura() )
+ //Here is wrong... TODO fix angle... but in fact i wan MV for Follower and One for Attacker.
+ float angle = NULL;
+ if( !i_creature.IsHostileTo(target) )
{
- DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_creature.GetGUIDLow());
+ angle = target->GetOrientation()*2.0f;
}
- else if( victim->isInFlight() )
+
+ if(creatureMM->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE)
{
- DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_creature.GetGUIDLow());
+ TargetedMovementGenerator<Creature>* targetMV = static_cast<TargetedMovementGenerator<Creature>*> (creatureMM->top());
+ if( targetMV && targetMV->GetTarget() )
+ {
+ if( targetMV->GetTarget()->GetGUID() != target->GetGUID() )
+ {
+ creatureMM->MovementExpired(false);
+ creatureMM->Mutate(new TargetedMovementGenerator<Creature>(*target,offSet,angle));
+ }
+ else if(targetMV->GetOffSet() != offSet)
+ targetMV->SetOffSet(offSet);
+ }
}
else
- {
- DEBUG_LOG("Creature stopped attacking due to target %s [guid=%u]", victim->isAlive() ? "out run him" : "is dead", i_creature.GetGUIDLow());
+ {
+ i_creature.GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*target,offSet,angle));
}
-
- i_creature.RemoveAllAuras();
- i_creature.DeleteThreatList();
- i_victimGuid = 0;
- i_creature.CombatStop(true);
-
- // Remove TargetedMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
- if( i_creature.GetMotionMaster()->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE )
- i_creature.GetMotionMaster()->TargetedHome();
}
Index: src/game/ReactorAI.h
===================================================================
--- src/game/ReactorAI.h (revision 4763)
+++ src/game/ReactorAI.h (working copy)
@@ -27,7 +27,7 @@
{
public:
- ReactorAI(Creature &c) : i_creature(c), i_victimGuid(0) {}
+ ReactorAI(Creature &c) : i_creature(c) {}
void MoveInLineOfSight(Unit *);
void AttackStart(Unit *);
@@ -38,7 +38,9 @@
static int Permissible(const Creature *);
private:
+ void AIMotionTarget(Unit* target, float offSet);
+ uint32 lastAction;
+ float selectedAttackRadius;
Creature &i_creature;
- uint64 i_victimGuid;
};
#endif
Index: src/game/ScriptCalls.cpp
===================================================================
--- src/game/ScriptCalls.cpp (revision 4763)
+++ src/game/ScriptCalls.cpp (working copy)
@@ -41,8 +41,18 @@
{
ScriptsSet testScript=new _ScriptSet;
- std::string name = strlen(libName) ? libName : MANGOS_SCRIPT_NAME;
+ std::string name;
+ name = strlen(libName) ? libName : MANGOS_TIER_SCRIPT_NAME;
name += MANGOS_SCRIPT_EXT;
+
+ const char* TierScriptName = name.c_str();
+
+ if( !fopen( TierScriptName, "r") ) //Tier Script Not Present Taking Default MaNGOSScript.dll
+ {
+ printf("Error loading TIER Scripts Library %s !\n",name.c_str());
+ name = strlen(libName) ? libName : MANGOS_SCRIPT_NAME;
+ name += MANGOS_SCRIPT_EXT;
+ }
testScript->hScriptsLib=MANGOS_LOAD_LIBRARY(name.c_str());
Index: src/game/Spell.cpp
===================================================================
--- src/game/Spell.cpp (revision 4763)
+++ src/game/Spell.cpp (working copy)
@@ -1480,6 +1480,8 @@
void Spell::SendSpellCooldown()
{
+ if( m_caster->GetTypeId() == TYPEID_UNIT && !((Creature*)m_caster)->isPet() )
+ ((Creature*)m_caster)->AddCreatureSpellCooldown(m_spellInfo->Id);
if(m_caster->GetTypeId() != TYPEID_PLAYER)
return;
@@ -1639,9 +1641,11 @@
}
// check if the player caster has moved before the spell finished
- if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
- (m_castPositionX != m_caster->GetPositionX() || m_castPositionY != m_caster->GetPositionY() || m_castPositionZ != m_caster->GetPositionZ()) &&
- (m_spellInfo->Effect[0] != SPELL_EFFECT_STUCK || !((Player*)m_caster)->HasMovementFlags(MOVEMENTFLAG_FALLING)) )
+ if( m_timer != 0
+ && ( m_castPositionX != m_caster->GetPositionX()
+ || m_castPositionY != m_caster->GetPositionY()
+ || m_castPositionZ != m_caster->GetPositionZ() )
+ && ( m_spellInfo->Effect[0] != SPELL_EFFECT_STUCK || ( m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->HasMovementFlags(MOVEMENTFLAG_FALLING))) )
{
// always cancel for channeled spells
if( m_spellState == SPELL_STATE_CASTING )
@@ -1686,6 +1690,12 @@
if( m_spellInfo->ChannelInterruptFlags & CHANNEL_FLAG_TURNING && m_castOrientation != m_caster->GetOrientation() )
cancel();
}
+ else
+ {
+ // check for incapacitating NPC states
+ if( m_caster->hasUnitState( UNIT_STAT_STUNDED | UNIT_STAT_CONFUSED ) )
+ cancel();
+ }
// check if there are alive targets left
for(int i=0;i<3;i++)
@@ -2073,6 +2083,7 @@
{
if(time == 0)
{
+ m_timer = 0; //reset Channeling Timer, Should not be there, in place Must Check with State , but have to Be sure Deleyed and CASTING are never together.
m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,0);
m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL,0);
}
@@ -3117,7 +3128,7 @@
if(target && target != m_caster)
{
- float dist = m_caster->GetDistanceSq(target);
+ float dist = m_caster->GetDistance2dSq(target);
if(dist > max_range * max_range)
return SPELL_FAILED_OUT_OF_RANGE; //0x5A;
if(dist < min_range * min_range)
@@ -3129,7 +3140,7 @@
if(m_targets.m_targetMask == TARGET_FLAG_DEST_LOCATION && m_targets.m_destX != 0 && m_targets.m_destY != 0 && m_targets.m_destZ != 0)
{
- float dist = m_caster->GetDistanceSq(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ);
+ float dist = m_caster->GetDistance2d(m_targets.m_destX, m_targets.m_destY) * m_caster->GetDistance2d(m_targets.m_destX, m_targets.m_destY);
if(dist > max_range * max_range)
return SPELL_FAILED_OUT_OF_RANGE;
if(dist < min_range * min_range)
Index: src/game/Spell.h
===================================================================
--- src/game/Spell.h (revision 4763)
+++ src/game/Spell.h (working copy)
@@ -577,6 +577,7 @@
CurrentSpellTypes GetCurrentContainer();
+ uint32 GetTimer() { return m_timer; }
Unit* GetCaster() { return m_caster; }
Unit* GetOriginalCaster() { return m_originalCaster; }
Index: src/game/SpellAuras.cpp
===================================================================
--- src/game/SpellAuras.cpp (revision 4763)
+++ src/game/SpellAuras.cpp (working copy)
@@ -39,6 +39,8 @@
#include "Creature.h"
#include "ConfusedMovementGenerator.h"
#include "TargetedMovementGenerator.h"
+#include "FleeingMovementGenerator.h"
+#include "HomeMovementGenerator.h"
#include "Formulas.h"
#include "BattleGround.h"
#include "BattleGroundAV.h"
@@ -297,7 +299,7 @@
m_procCharges(0), m_spellmod(NULL), m_spellId(spellproto->Id), m_effIndex(eff), m_caster_guid(0), m_target(target),
m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS),
m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false), m_isPersistent(false),
-m_periodicTimer(0), m_PeriodicEventId(0), m_updated(false), m_removeOnDeath(false),m_fearMoveAngle(0)
+m_periodicTimer(0), m_PeriodicEventId(0), m_updated(false), m_removeOnDeath(false),m_fearMoveAngle(0),m_fearMovementTimer(0)
{
assert(target);
@@ -452,52 +454,7 @@
caster->ModifyPower(powertype,-manaPerSecond);
caster->ModifyPower(powertype,-manaPerSecondPerLevel);
}
- if(caster && m_target->isAlive() && m_target->HasFlag(UNIT_FIELD_FLAGS,(UNIT_STAT_FLEEING<<16)))
- {
- int q = rand() % 80;
- if(q == 8) m_fearMoveAngle += (float)(urand(45, 90));
- else if(q == 23) m_fearMoveAngle -= (float)(urand(45, 90));
-
- // If the m_target is player,and if the speed is too slow,change it :P
- float speed = m_target->GetSpeed(MOVE_RUN);
- // Speed modifier, may need to find correct one
- float mod = m_target->GetTypeId() != TYPEID_PLAYER ? 10 : 6;
- float pos_x = m_target->GetPositionX();
- float pos_y = m_target->GetPositionY();
- uint32 mapid = m_target->GetMapId();
- float pos_z = MapManager::Instance().GetBaseMap(mapid)->GetHeight(pos_x,pos_y, m_target->GetPositionZ());
- // Control the max Distance; 28 for temp.
- if(m_target->IsWithinDistInMap(caster, 28))
- {
- float x = m_target->GetPositionX() - (speed*cosf(m_fearMoveAngle))/mod;
- float y = m_target->GetPositionY() - (speed*sinf(m_fearMoveAngle))/mod;
- float z = MapManager::Instance().GetBaseMap(mapid)->GetHeight(x,y, m_target->GetPositionZ());
- // Control the target to not climb or drop when dz > |x|,x = 1.3 for temp.
- // fixed me if it needs checking when the position will be in water?
- //+vmaps
- if((z<=pos_z+1.3 && z>=pos_z-1.3) && m_target->IsWithinLOS(x,y,z))
- {
- m_target->SendMonsterMove(x,y,z,0,true,(diff*2));
- if(m_target->GetTypeId() != TYPEID_PLAYER)
- MapManager::Instance().GetMap(m_target->GetMapId(), m_target)->CreatureRelocation((Creature*)m_target,x,y,z,m_target->GetOrientation());
- }
- else
- {
- //Complete the move only if z coord is now correct
- m_fearMoveAngle += 120;
- x = m_target->GetPositionX() + (speed*sinf(m_fearMoveAngle))/mod;
- y = m_target->GetPositionY() + (speed*cosf(m_fearMoveAngle))/mod;
- z = MapManager::Instance().GetBaseMap(mapid)->GetHeight(x,y, m_target->GetPositionZ());
- //+vmaps
- if((z<=pos_z+1.3 && z>=pos_z-1.3) && m_target->IsWithinLOS(x,y,z))
- {
- m_target->SendMonsterMove(x,y,z,0,true,(diff*2));
- if(m_target->GetTypeId() != TYPEID_PLAYER)
- MapManager::Instance().GetMap(m_target->GetMapId(), m_target)->CreatureRelocation((Creature*)m_target,x,y,z,m_target->GetOrientation());
- }
- }
- }
- }
+ //Better remove all this and create a runaway MV, and we simpli stack one over the other, GS
}
if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent))
@@ -1761,8 +1718,7 @@
m_target->DeleteThreatList();
if(m_target->GetTypeId() == TYPEID_UNIT)
{
- m_target->StopMoving();
- m_target->GetMotionMaster()->Clear();
+ m_target->GetMotionMaster()->Clear(false);
m_target->GetMotionMaster()->Idle();
CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target);
charmInfo->InitPossessCreateSpells();
@@ -1969,7 +1925,6 @@
if( apply )
{
- m_target->addUnitState(UNIT_STAT_CONFUSED);
m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
if(m_target->GetTypeId() == TYPEID_PLAYER)
@@ -2004,7 +1959,6 @@
}
else
{
- m_target->clearUnitState(UNIT_STAT_CONFUSED);
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED);
if(m_target->GetTypeId() == TYPEID_PLAYER)
@@ -2019,15 +1973,7 @@
// only at real remove aura
if(Real)
{
- m_target->GetMotionMaster()->MovementExpired(false);
- if (m_target->GetTypeId() == TYPEID_UNIT)
- {
- Creature* c = (Creature*)m_target;
- // if in combat restore movement generator
- if(c->getVictim())
- c->GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*c->getVictim()));
- }
}
}
}
@@ -2036,53 +1982,23 @@
{
if( Apply )
{
- m_target->addUnitState(UNIT_STAT_FLEEING);
m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
-
- // only at real add aura
+
+ //only at real add aura
if(Real)
{
- //FIX ME: we need Mutate to now not existed FleeMovementGenerator (see Aura::Update hack code)
- // at this moment Idle instead
- m_target->GetMotionMaster()->MovementExpired(false);
- m_target->GetMotionMaster()->Idle();
-
- // what is this for ? (doesn't work anyway)
- /*WorldPacket data(SMSG_DEATH_NOTIFY_OBSOLETE, 9);
- data.append(m_target->GetPackGUID());
- data << uint8(0x00);
- m_target->SendMessageToSet(&data,true);*/
+ if (m_target->GetTypeId() == TYPEID_UNIT)
+ m_target->GetMotionMaster()->Mutate(new FleeingMovementGenerator<Creature>(*m_target,m_caster_guid) );
+ else
+ m_target->GetMotionMaster()->Mutate(new FleeingMovementGenerator<Player>(*m_target,m_caster_guid) );
}
}
else
{
- m_target->clearUnitState(UNIT_STAT_FLEEING);
m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING);
-
// only at real remove aura
if(Real)
{
- m_target->GetMotionMaster()->MovementExpired(false);
-
- if(m_target->GetTypeId() != TYPEID_PLAYER)
- {
- // restore appropriate movement generator
- if(m_target->getVictim())
- m_target->GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*m_target->getVictim()));
- else
- m_target->GetMotionMaster()->Initialize();
-
- // attack caster if can
- Unit* caster = GetCaster();
- if(caster && caster != m_target->getVictim())
- ((Creature*)m_target)->AI()->AttackStart(caster);
- }
-
- // what is this for ? (doesn't work anyway)
- /*WorldPacket data(SMSG_DEATH_NOTIFY_OBSOLETE, 9);
- data.append(m_target->GetPackGUID());
- data << uint8(0x01);
- m_target->SendMessageToSet(&data,true);*/
}
}
}
@@ -2156,7 +2072,7 @@
if (apply)
{
m_target->addUnitState(UNIT_STAT_STUNDED);
- m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
+ //m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE);
if (caster)
@@ -2174,14 +2090,16 @@
// Creature specific
if(m_target->GetTypeId() != TYPEID_PLAYER)
{
+ WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
+
+ data.append(m_target->GetPackGUID());
+ data << uint32(0);
+ m_target->SendMessageToSet(&data,true);
+ }
+ else
+ {
((Creature *)m_target)->StopMoving();
}
-
- WorldPacket data(SMSG_FORCE_MOVE_ROOT, 8);
-
- data.append(m_target->GetPackGUID());
- data << uint32(0);
- m_target->SendMessageToSet(&data,true);
}
else
{
@@ -2194,11 +2112,16 @@
if(m_target->getVictim() && m_target->isAlive())
m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
+ //if(caster && m_target->isAlive())
+ //m_target->SetUInt64Value (UNIT_FIELD_TARGET,GetCasterGUID());
- WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
- data.append(m_target->GetPackGUID());
- data << uint32(0);
- m_target->SendMessageToSet(&data,true);
+ if(m_target->GetTypeId() == TYPEID_PLAYER)
+ {
+ WorldPacket data(SMSG_FORCE_MOVE_UNROOT, 8+4);
+ data.append(m_target->GetPackGUID());
+ data << uint32(0);
+ m_target->SendMessageToSet(&data,true);
+ }
if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->SpellIconID == 1721)
{
if( !caster || caster->GetTypeId()!=TYPEID_PLAYER )
@@ -2386,14 +2309,16 @@
if (apply)
{
m_target->addUnitState(UNIT_STAT_ROOT);
- m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
+ //m_target->SetUInt64Value (UNIT_FIELD_TARGET, 0);
// probably wrong
- m_target->SetFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
+ //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 (caster)
+ // m_target->SetOrientation(m_target->GetAngle(caster));
if(m_target->GetTypeId() == TYPEID_PLAYER)
{
WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10);
@@ -2402,7 +2327,9 @@
m_target->SendMessageToSet(&data,true);
}
else
+ {
((Creature *)m_target)->StopMoving();
+ }
}
else
{
@@ -2414,6 +2341,9 @@
// probably wrong
m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
+ //m_target->RemoveFlag(UNIT_FIELD_FLAGS,(apply_stat<<16));
+ //if(caster && m_target->isAlive()) // set creature facing on root effect if alive
+ //m_target->SetUInt64Value (UNIT_FIELD_TARGET,GetCasterGUID());
if(m_target->getVictim() && m_target->isAlive())
m_target->SetUInt64Value (UNIT_FIELD_TARGET,m_target->getVictim()->GetGUID() );
Index: src/game/SpellAuras.h
===================================================================
--- src/game/SpellAuras.h (revision 4763)
+++ src/game/SpellAuras.h (working copy)
@@ -264,6 +264,7 @@
uint64 m_caster_guid;
Unit* m_target;
int32 m_maxduration;
+ uint16 m_fearMovementTimer;
int32 m_duration;
int32 m_timeCla;
// it is NOT safe to keep a pointer to the item because it may get deleted
Index: src/game/SpellEffects.cpp
===================================================================
--- src/game/SpellEffects.cpp (revision 4763)
+++ src/game/SpellEffects.cpp (working copy)
@@ -53,6 +53,8 @@
#include "BattleGroundWS.h"
#include "VMapFactory.h"
#include "Language.h"
+#include "TargetedMovementGenerator.h"
+#include "IdleMovementGenerator.h"
pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
{
@@ -1233,7 +1235,11 @@
sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
- Aura* Aur = new Aura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget,m_caster, m_CastItem);
+ Aura* Aur;
+ if( m_originalCaster )
+ Aur = new Aura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_originalCaster, m_CastItem);
+ else
+ Aur = new Aura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
if (!Aur->IsPositive() && Aur->GetCasterGUID() != Aur->GetTarget()->GetGUID())
{
@@ -3073,11 +3079,14 @@
switch(m_spellInfo->Id)
{
// Keep in top, because core use it for npc aggro other npc
- case SPELL_ID_AGGRO:
+ case CREATURE_SPELL_TAP_FRIEND:
{
if( !m_caster || m_caster->GetTypeId() != TYPEID_UNIT || !m_caster->getVictim() )
return;
+ // Should be == to diff from Home Location to Location, with a maximun of 50 like, GS
+ //So we can bring her too far away from original location, GS
+ // Need to readjuste, AnyAssistCreatureInRangeCheck to be more smart, Like select Strong First, GS
float radius = sWorld.getConfig(CONFIG_CREATURE_FAMILY_ASSISTEMCE_RADIUS);
if(radius > 0)
{
@@ -3097,16 +3106,14 @@
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, grid_creature_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
}
-
- for(std::list<Creature*>::iterator iter = assistList.begin(); iter != assistList.end(); ++iter)
+ std::list<Creature*>::iterator firstTarget = assistList.begin();
+ if( firstTarget != assistList.end() )
{
- ((Creature*)m_caster)->SetNoCallAssistence(true);
- (*iter)->SetNoCallAssistence(true);
- if((*iter)->AI())
- (*iter)->AI()->AttackStart(m_caster->getVictim());
+ //TODO:Create Bondary Range Check into Object..., GS
+ m_caster->GetMotionMaster()->Mutate(new IdleMovementGenerator(*m_caster,false,1000));
+ m_caster->GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>( *(*firstTarget),(*firstTarget)->GetObjectSize()+m_caster->GetObjectSize(),(rand_norm()*(M_PI*2)),true ));
}
}
-
return;
}
@@ -3764,15 +3771,17 @@
return;
float x, y, z;
- unitTarget->GetContactPoint(m_caster, x, y, z);
- if(unitTarget->GetTypeId() != TYPEID_PLAYER)
- ((Creature *)unitTarget)->StopMoving();
-
+ unitTarget->GetPosition( x, y, z);
m_caster->SendMonsterMove(x, y, z, 0, true,1);
- if(m_caster->GetTypeId() != TYPEID_PLAYER)
+ if(m_caster->GetMotionMaster()->top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE)
+ {
+ m_caster->Relocate(x, y, z);
+ m_caster->GetMotionMaster()->top()->Initialize(*m_caster);
+ }
+ else if(m_caster->GetTypeId() == TYPEID_UNIT)
MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
+ m_caster->Attack(unitTarget,true);
- m_caster->Attack(unitTarget,true);
}
void Spell::EffectSummonCritter(uint32 i)
Index: src/game/TargetedMovementGenerator.cpp
===================================================================
--- src/game/TargetedMovementGenerator.cpp (revision 4763)
+++ src/game/TargetedMovementGenerator.cpp (working copy)
@@ -22,6 +22,7 @@
#include "Creature.h"
#include "MapManager.h"
#include "DestinationHolderImp.h"
+#include "Spell.h"
#define SMALL_ALPHA 0.05f
@@ -39,129 +40,122 @@
};
*/
-template<class T>
-void
-TargetedMovementGenerator<T>::_setTargetLocation(T &owner)
+template<class T> void TargetedMovementGenerator<T>::_setTargetLocation(T &owner)
{
- if( !&i_target || !&owner )
+ if( !&i_target || !&owner || !i_target.isValid()) //Added To make Script.dll don't crash into DEBUG Mode
return;
- if( owner.hasUnitState(UNIT_STAT_ROOT) || owner.hasUnitState(UNIT_STAT_STUNDED) )
- return;
-
- // prevent redundant micro-movement for pets, other followers.
- if(i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset))
- return;
-
float x, y, z;
- if(!i_offset)
- {
- // to nearest contact position
- i_target->GetContactPoint( &owner, x, y, z );
- }
- else
- {
- // to at i_offset distance from target and i_angle from target facing
- i_target->GetClosePoint(x,y,z,owner.GetObjectSize() + i_offset,i_angle);
- }
+
+ const float minReachRadius = owner.GetObjectSize() + (owner.GetFloatValue(UNIT_FIELD_COMBATREACH)/1.75);
+ i_offset = i_offset < minReachRadius ? minReachRadius : i_offset;
- //We don't update Mob Movement, if the difference between New destination and last destination is < BothObjectSize
- float bothObjectSize = i_target->GetObjectSize() + owner.GetObjectSize() + CONTACT_DISTANCE;
- if( i_destinationHolder.HasDestination() && i_destinationHolder.GetDestinationDiff(x,y,z) < bothObjectSize )
- return;
+ //absAngle should herite PositionCollision
+ float const absAngle = owner.GetAngle(i_target.getTarget());
+ x = i_target.getTarget()->GetPositionX() + ((i_offset+i_target.getTarget()->GetObjectSize()) * cos(absAngle));
+ y = i_target.getTarget()->GetPositionY() + ((i_offset+i_target.getTarget()->GetObjectSize()) * sin(absAngle));
+ z = i_target.getTarget()->GetPositionZ();
+
Traveller<T> traveller(owner);
+ owner.SetOrientation(owner.GetAngle(x,y));
i_destinationHolder.SetDestination(traveller, x, y, z);
owner.addUnitState(UNIT_STAT_CHASE);
}
-template<class T>
-void
-TargetedMovementGenerator<T>::Initialize(T &owner)
+template<class T> void TargetedMovementGenerator<T>::Initialize(T &owner)
{
if(!&owner)
return;
+
+ //Will have to change that..., so we can dynamic check for Best walk or run, GS
+ //TODO: AIMotionMaster after spell Casting Walk.... and Lower range, GS
owner.setMoveRunFlag(true);
_setTargetLocation(owner);
}
-
-template<class T>
-void
-TargetedMovementGenerator<T>::Reset(T &owner)
+template<class T> void TargetedMovementGenerator<T>::Reset(T &owner)
{
Initialize(owner);
}
-template<class T>
-bool
-TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
+template<class T> bool TargetedMovementGenerator<T>::Update(T &owner, const uint32 & time_diff)
{
- if(!i_target.isValid())
- {
+ //Hum that is cause ReferenceFollower... Not sure yet again if we really need that... since we should search allways for XYZ
+ // and fuck the target.... so target should never never appear here... only XYZ
+ //TODO: Change the way Targeted Work and make it: FollowerMovementGenerator(), ChasingMovementGenerator()
+ //For the moment is working much better then actual but ... is more like little finetune here and there.
+ //We doo at the end with Path Searching...., GS
+
+ //ReferenceFollower are no more needed i think so, if we keep that Generator only for Victim... :)
+ //if( owner.getVictim() != i_target.getTarget() )
+ // return false;
+
+ if(!i_target.isValid() || !&owner || !owner.isAlive() )
return false;
- }
- if( !&owner || !owner.isAlive() || !&i_target )
- return true;
- if( owner.hasUnitState(UNIT_STAT_ROOT) || owner.hasUnitState(UNIT_STAT_STUNDED) || owner.hasUnitState(UNIT_STAT_FLEEING))
- return true;
- if( !owner.isInCombat() && !owner.hasUnitState(UNIT_STAT_FOLLOW) )
- {
- //owner.AIM_Initialize(); This case must be the one, when a creature aggroed you. By Initalized a new AI, we prevented to Ai::_stopAttack() to be executed properly.
- return true;
- }
- // prevent crash after creature killed pet
- if (!owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != i_target.getTarget())
- return true;
+ if( !owner.GetUInt32Value(UNIT_FIELD_TARGET))
+ return false;
+ //To Debug why sometime Mangos screw: UNIT_FIELD_TARGET, GS
+ if( owner.getVictim() && i_target.getTarget() && owner.GetUInt64Value(UNIT_FIELD_TARGET) != i_target.getTarget()->GetGUID() )
+ owner.GetUInt64Value(UNIT_FIELD_TARGET);
+
+ // prevent crash after creature killed pet //HEIN??? , GS
+ //if( !owner.hasUnitState(UNIT_STAT_FOLLOW) && owner.getVictim() != i_target.getTarget())
+ //return true;
+
Traveller<T> traveller(owner);
if( !i_destinationHolder.HasDestination() )
_setTargetLocation(owner);
+
if( owner.IsStopped() && !i_destinationHolder.HasArrived() )
- {
owner.addUnitState(UNIT_STAT_CHASE);
- i_destinationHolder.StartTravel(traveller);
- return true;
- }
if (i_destinationHolder.UpdateTraveller(traveller, time_diff, false))
{
- // put targeted movement generators on a higher priority
- if (owner.GetObjectSize())
- i_destinationHolder.ResetUpdate(50);
+ // put targeted movement generators on a higher priority, No way Man, GS
+ i_destinationHolder.ResetUpdate(100);
+ //DEBUG value, GS
+ float _asdf = sqrt(i_destinationHolder.GetDistanceFromDest2dSq(*i_target.getTarget()));
+ float _asdf2 = owner.GetFloatValue(UNIT_FIELD_COMBATREACH);
+ float _asdf3 = i_target->GetObjectSize() + owner.GetFloatValue(UNIT_FIELD_COMBATREACH) + owner.GetObjectSize() + i_offset;
- float dist = i_target->GetObjectSize() + owner.GetObjectSize() + CONTACT_DISTANCE;
-
- // try to counter precision differences
- if( i_destinationHolder.GetDistanceFromDestSq(*i_target.getTarget()) > dist * dist + 0.8)
- {
- owner.SetInFront(i_target.getTarget()); // Set new Angle For Map::
- _setTargetLocation(owner); //Calculate New Dest and Send data To Player
+ // try to counter precision differences,
+ float targetDistToDest = sqrt(i_destinationHolder.GetDistanceFromDest2dSq(*i_target.getTarget())) - (i_target->GetObjectSize() + owner.GetFloatValue(UNIT_FIELD_COMBATREACH) + owner.GetObjectSize() + i_offset);
+ // -0.5 should be Bounding radius of this.... but for test use that one... be sure NPC move if your too close.
+ if( targetDistToDest > -0.5f && (i_destinationHolder.HasArrived() || i_destinationHolder.GetTimeToDest() > TRAVELLER_UPDATE_INTERVAL) )
+ {
+ float x,y,z;
+ i_destinationHolder.GetLocationNow(x,y,z);
+ traveller.Relocation(x,y,z);
+ _setTargetLocation(owner);
}
- // Update the Angle of the target only for Map::, no need to send packet for player
- else if ( !i_angle && !owner.HasInArc( 0.01f, i_target.getTarget() ) )
- owner.SetInFront(i_target.getTarget());
+ //Angle update will be made with Operator Overload into GetOrientation()
+ //For fast Angle Update during fight, MeanMachine Rocking idea :), GS
if( !owner.IsStopped() && i_destinationHolder.HasArrived())
{
- //Angle update will take place into owner.StopMoving()
+ owner.clearUnitState(UNIT_STAT_MOVING);
owner.SetInFront(i_target.getTarget());
-
- owner.StopMoving();
- if(owner.canReachWithAttack(i_target.getTarget()) && !owner.hasUnitState(UNIT_STAT_FOLLOW))
- owner.Attack(i_target.getTarget());
+ if(i_forceExpireAtDest)
+ return false;
}
}
return true;
}
-template<class T>
-Unit*
-TargetedMovementGenerator<T>::GetTarget() const
+template<class T> Unit* TargetedMovementGenerator<T>::GetTarget() const
{
return i_target.getTarget();
}
-
+template<class T> float TargetedMovementGenerator<T>::GetOffSet() const
+{
+ return i_offset;
+}
+template<class T> void TargetedMovementGenerator<T>::SetOffSet(float newOffSet)
+{
+ i_offset = *new float(newOffSet);
+}
template void TargetedMovementGenerator<Player>::_setTargetLocation(Player &);
template void TargetedMovementGenerator<Creature>::_setTargetLocation(Creature &);
template void TargetedMovementGenerator<Player>::Initialize(Player &);
@@ -172,3 +166,7 @@
template bool TargetedMovementGenerator<Creature>::Update(Creature &, const uint32 &);
template Unit* TargetedMovementGenerator<Player>::GetTarget() const;
template Unit* TargetedMovementGenerator<Creature>::GetTarget() const;
+template float TargetedMovementGenerator<Player>::GetOffSet() const;
+template float TargetedMovementGenerator<Creature>::GetOffSet() const;
+template void TargetedMovementGenerator<Player>::SetOffSet(float newOffSet);
+template void TargetedMovementGenerator<Creature>::SetOffSet(float newOffSet);
Index: src/game/TargetedMovementGenerator.h
===================================================================
--- src/game/TargetedMovementGenerator.h (revision 4763)
+++ src/game/TargetedMovementGenerator.h (working copy)
@@ -39,10 +39,10 @@
{
public:
- TargetedMovementGenerator(Unit &target)
- : TargetedMovementGeneratorBase(target), i_offset(0), i_angle(0) {}
- TargetedMovementGenerator(Unit &target, float offset, float angle)
- : TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle) {}
+ TargetedMovementGenerator(Unit &target, bool forceExpireAtDest = false)
+ : TargetedMovementGeneratorBase(target), i_offset(0), i_angle(0),i_forceExpireAtDest(forceExpireAtDest) {}
+ TargetedMovementGenerator(Unit &target, float offset, float angle, bool forceExpireAtDest = false)
+ : TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle),i_forceExpireAtDest(forceExpireAtDest) {}
~TargetedMovementGenerator() {}
void Initialize(T &);
@@ -51,7 +51,12 @@
MovementGeneratorType GetMovementGeneratorType() { return TARGETED_MOTION_TYPE; }
Unit* GetTarget() const;
-
+ float GetOffSet() const;
+ void SetOffSet(float newOffSet);
+ void UpdateMapPosition(float &x ,float &y, float &z)
+ {
+ i_destinationHolder.GetLocationNow(x,y,z);
+ }
bool GetDestination(float &x, float &y, float &z)
{
if(!i_destinationHolder.HasDestination()) return false;
@@ -61,9 +66,10 @@
private:
void _setTargetLocation(T &);
-
+
float i_offset;
float i_angle;
+ bool i_forceExpireAtDest;
DestinationHolder< Traveller<T> > i_destinationHolder;
};
#endif
Index: src/game/Traveller.h
===================================================================
--- src/game/Traveller.h (revision 4763)
+++ src/game/Traveller.h (working copy)
@@ -47,6 +47,7 @@
inline float GetPositionX() const { return i_traveller.GetPositionX(); }
inline float GetPositionY() const { return i_traveller.GetPositionY(); }
inline float GetPositionZ() const { return i_traveller.GetPositionZ(); }
+ inline float GetOrientation() const { return i_traveller.GetOrientation(); }
inline T& GetTraveller(void) { return i_traveller; }
float Speed(void) { assert(false); return 0.0f; }
@@ -71,7 +72,7 @@
template<>
inline void Traveller<Creature>::MoveTo(float x, float y, float z, uint32 t)
{
- i_traveller.AI_SendMoveToPacket(x, y, z, t, i_traveller.getMoveRunFlag(), 0);
+ i_traveller.AI_SendMoveToPacket(x, y, z, t, Speed(), 0);
}
// specialization for players
Index: src/game/Unit.cpp
===================================================================
--- src/game/Unit.cpp (revision 4763)
+++ src/game/Unit.cpp (working copy)
@@ -39,6 +39,12 @@
#include "Totem.h"
#include "BattleGround.h"
#include "MovementGenerator.h"
+#include "TargetedMovementGenerator.h"
+#include "ConfusedMovementGenerator.h"
+#include "RandomMovementGenerator.h"
+#include "WaypointMovementGenerator.h"
+#include "HomeMovementGenerator.h"
+#include "FleeingMovementGenerator.h"
#include <math.h>
@@ -132,6 +138,7 @@
for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++)
m_currentSpells[i] = NULL;
+ m_hasHealer = false;
m_addDmgOnce = 0;
m_TotemSlot[0] = m_TotemSlot[1] = m_TotemSlot[2] = m_TotemSlot[3] = 0;
m_ObjectSlot[0] = m_ObjectSlot[1] = m_ObjectSlot[2] = m_ObjectSlot[3] = 0;
@@ -302,17 +309,16 @@
SendMonsterMove(x,y,z,0,run,transitTime);
}
-void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, bool Run, uint32 Time)
+void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, bool Run, uint32 Time, bool tryFlag512)
{
WorldPacket data( SMSG_MONSTER_MOVE, (41 + GetPackGUID().size()) );
data.append(GetPackGUID());
-
// Point A, starting location
data << GetPositionX() << GetPositionY() << GetPositionZ();
// unknown field - unrelated to orientation
// seems to increment about 1000 for every 1.7 seconds
// for now, we'll just use mstime
- data << getMSTime();
+ data << getMSTime()/* + ((Time / 1000) * 140)*/; //Simulate 140 allways Ping
data << uint8(type); // unknown
switch(type)
@@ -323,14 +329,17 @@
SendMessageToSet( &data, true );
return;
case 3: // not used currently
- data << uint64(0); // probably target guid
+ data << uint64(GetUInt64Value(UNIT_FIELD_TARGET)); // probably target guid
break;
case 4: // not used currently
data << float(0); // probably orientation
break;
}
- data << uint32(Run ? 0x00000100 : 0x00000000); // flags (0x100 - running, 0x200 - taxi)
+ if(tryFlag512)
+ data << uint32(0x11111111);
+ else
+ data << uint32(Run ? 0x00000100 : 0x00000000); // flags (0x100 - running, 0x200 - taxi)
/* Flags:
512: Floating, moving without walking/running
*/
@@ -383,6 +392,10 @@
return (!m_modAuras[auraType].empty());
}
+bool Unit::HasSpellChannelActiveTimer()
+{
+ return m_currentSpells[CURRENT_GENERIC_SPELL] ? m_currentSpells[CURRENT_GENERIC_SPELL]->GetTimer() > 0 : false;
+}
/* Called by DealDamage for auras that have a chance to be dispelled on damage taken. */
void Unit::RemoveSpellbyDamageTaken(uint32 auraType, uint32 damage)
{
@@ -643,6 +656,9 @@
((Creature*)pVictim)->AI()->JustDied(this);
}
+
+ m_hasHealer = false;
+
//judge if GainXP, Pet kill like player kill,kill pet not like PvP
bool PvP = false;
Player *player = NULL;
@@ -877,7 +893,7 @@
if (damagetype != NODAMAGE)
{
- if(pVictim->m_currentSpells[CURRENT_CHANNELED_SPELL] && pVictim->GetTypeId() == TYPEID_PLAYER && damage)
+ if(pVictim->m_currentSpells[CURRENT_CHANNELED_SPELL] /*&& pVictim->GetTypeId() == TYPEID_PLAYER*/ && damage)
{
if (pVictim->m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() == SPELL_STATE_CASTING)
{
@@ -2077,7 +2093,7 @@
}
}
- if (pVictim->GetTypeId() == TYPEID_PLAYER && *damage)
+ if (/*pVictim->GetTypeId() == TYPEID_PLAYER &&*/ *damage)
{
for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
{
@@ -4724,19 +4740,21 @@
//Set our target
SetUInt64Value(UNIT_FIELD_TARGET, victim->GetGUID());
+ SetInFront(victim);
addUnitState(UNIT_STAT_ATTACKING);
SetInCombat();
m_attacking = victim;
m_attacking->_addAttacker(this);
- if(m_attacking->GetTypeId()==TYPEID_UNIT && ((Creature*)m_attacking)->AI())
- ((Creature*)m_attacking)->AI()->AttackedBy(this);
+ //if(m_attacking->GetTypeId()==TYPEID_UNIT && ((Creature*)m_attacking)->AI())
+ //((Creature*)m_attacking)->AI()->AttackedBy(this); //Heu.. don't understand why we need that???
- if( GetTypeId()==TYPEID_UNIT && !(((Creature*)this)->isPet() || isCharmed()) )
+ /*if( GetTypeId()==TYPEID_UNIT && !(((Creature*)this)->isPet() || isCharmed()) )
{
((Creature*)this)->CallAssistence();
- }
+ }*/
+
//if(!isAttackReady(BASE_ATTACK))
//resetAttackTimer(BASE_ATTACK);
@@ -4766,11 +4784,12 @@
clearUnitState(UNIT_STAT_ATTACKING);
InterruptSpell(CURRENT_MELEE_SPELL);
-
+ m_hasHealer = false; // I don't wan that, I must get rid at the end.. system should be smooth enought so no need at all, GS
+
if( GetTypeId()==TYPEID_UNIT )
{
- // reset call assistance
- ((Creature*)this)->SetNoCallAssistence(false);
+ // reset assistance
+ ((Creature*)this)->m_AssistenceStatus->reset();
}
SendAttackStop(victim);
@@ -6338,13 +6357,12 @@
}
// no target but something prevent go to evade mode
+ // !isInCombat(), Do EnterEvade Only if inCombat(), no need after
+ // HasAuraType(SPELL_AURA_MOD_TAUNT), Cause EnterEvadeTake Place here : Unit::TauntFadeOut(Unit *taunter)
if( !isInCombat() || HasAuraType(SPELL_AURA_MOD_TAUNT) || !CanFreeMove() )
return false;
- // last case when creature don't must go to evade mode:
- // it in combat but attacker not make any damage and not enter to aggro radius to have record in threat list
- // for example at owner command to pet attack some far away creature
- // Note: creature not have targeted movement generator but have attacker in this case
+ // this, is waiting the Attacker to come to aggro range, no yet Threat Created from Attacker, GS
if( GetMotionMaster()->empty() || GetMotionMaster()->top()->GetMovementGeneratorType() != TARGETED_MOTION_TYPE )
{
for(AttackerSet::const_iterator itr = m_attackers.begin(); itr != m_attackers.end(); ++itr)
@@ -7392,14 +7410,69 @@
void Unit::StopMoving()
{
+ //Should Add other Moving MV and prepare for Compatibility
+ if( !hasUnitState(UNIT_STAT_MOVING))
+ return;
+
+ //Was for testing in begin but since is pretty good, must be updated, GS
+ //TODO: make that much more simple, and Support Player as Creature.
+ if( GetTypeId() == TYPEID_UNIT )
+ {
+ MotionMaster* currentMotion = GetMotionMaster();
+ float x,y,z; //Dummy Usage into that case but needed since we carry pointer.
+ switch( currentMotion->top()->GetMovementGeneratorType() )
+ {
+ case IDLE_MOTION_TYPE:
+ {
+ break;
+ }
+ case TARGETED_MOTION_TYPE:
+ {
+ TargetedMovementGenerator<Creature>* currentMV = static_cast<TargetedMovementGenerator<Creature>*> (currentMotion->top());
+ currentMV->UpdateMapPosition(x,y,z);
+ MapManager::Instance().GetMap(GetMapId(), this)->CreatureRelocation((Creature*)this, x, y, z, this->GetOrientation());
+ break;
+ }
+ case CONFUSED_MOTION_TYPE:
+ {
+ ConfusedMovementGenerator<Creature>* currentMV = static_cast<ConfusedMovementGenerator<Creature>*> (currentMotion->top());
+ currentMV->UpdateMapPosition(x,y,z);
+ MapManager::Instance().GetMap(GetMapId(), this)->CreatureRelocation((Creature*)this, x, y, z, this->GetOrientation());
+ break;
+ }
+ case FLEEING_MOTION_TYPE:
+ {
+ FleeingMovementGenerator<Creature>* currentMV = static_cast<FleeingMovementGenerator<Creature>*> (currentMotion->top());
+ currentMV->UpdateMapPosition(x,y,z);
+ MapManager::Instance().GetMap(GetMapId(), this)->CreatureRelocation((Creature*)this, x, y, z, this->GetOrientation());
+ break;
+ }
+ case HOME_MOTION_TYPE:
+ {
+ HomeMovementGenerator<Creature>* currentMV = static_cast<HomeMovementGenerator<Creature>*> (currentMotion->top());
+ currentMV->UpdateMapPosition(x,y,z);
+ MapManager::Instance().GetMap(GetMapId(), this)->CreatureRelocation((Creature*)this, x, y, z, this->GetOrientation());
+ break;
+ }
+ case RANDOM_MOTION_TYPE:
+ {
+ RandomMovementGenerator<Creature>* currentMV = static_cast<RandomMovementGenerator<Creature>*> (currentMotion->top());
+ currentMV->UpdateMapPosition(x,y,z);
+ MapManager::Instance().GetMap(GetMapId(), this)->CreatureRelocation((Creature*)this, x, y, z, this->GetOrientation());
+ break;
+ }
+ case WAYPOINT_MOTION_TYPE:
+ {
+ WaypointMovementGenerator<Creature>* currentMV = static_cast<WaypointMovementGenerator<Creature>*> (currentMotion->top());
+ currentMV->UpdateMapPosition(x,y,z);
+ MapManager::Instance().GetMap(GetMapId(), this)->CreatureRelocation((Creature*)this, x, y, z, this->GetOrientation());
+ break;
+ }
+ }
+ }
clearUnitState(UNIT_STAT_MOVING);
// send explicit stop packet
- SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(),0,true,0);
-
- // update position and orientation;
- WorldPacket data;
- BuildHeartBeatMsg(&data);
- SendMessageToSet(&data,false);
+ SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(),1,true,0);
}
bool Unit::IsStandState() const
@@ -7409,4 +7482,4 @@
s != PLAYER_STATE_SIT_MEDIUM_CHAIR && s != PLAYER_STATE_SIT_HIGH_CHAIR &&
s != PLAYER_STATE_SIT && s != PLAYER_STATE_SLEEP &&
s != PLAYER_STATE_KNEEL;
-}
\ No newline at end of file
+}
Index: src/game/Unit.h
===================================================================
--- src/game/Unit.h (revision 4763)
+++ src/game/Unit.h (working copy)
@@ -314,9 +314,9 @@
UNIT_STAT_STUNDED = 8,
UNIT_STAT_ROAMING = 16,
UNIT_STAT_CHASE = 32,
- UNIT_STAT_SEARCHING = 64,
+ UNIT_STAT_SEARCHING = 64, //Creature is Moving but no MILOS called to Her... example: She go Home first 25% distance reached creature has SEARCHING, the rest will have normal ROAMING
UNIT_STAT_FLEEING = 128,
- UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING),
+ UNIT_STAT_MOVING = (UNIT_STAT_ROAMING | UNIT_STAT_CHASE | UNIT_STAT_SEARCHING | UNIT_STAT_FLEEING | 2048 | 256 | 512),
UNIT_STAT_IN_FLIGHT = 256, // player is in flight mode
UNIT_STAT_FOLLOW = 512,
UNIT_STAT_ROOT = 1024,
@@ -326,6 +326,9 @@
enum UnitMoveType
{
+ //All that is very important for prediction im gonna do...
+ //I will allways call for bigger Motion and will check if i can stop from there, we do reverse.
+ //Angle will be very important... since a creature will target right in front a player + 5 yard is player is MOVE WALK or RUN, so creature will allways act as intercept and not chasing retared..
MOVE_WALK = 0,
MOVE_RUN = 1,
MOVE_WALKBACK = 2,
@@ -907,6 +910,7 @@
{ return m_Auras.find(spellEffectPair(spellId, effIndex)) != m_Auras.end(); }
bool virtual HasSpell(uint32 /*spellID*/) const { return false; }
+ bool HasSpellChannelActiveTimer();
bool HasStealthAura() const { return HasAuraType(SPELL_AURA_MOD_STEALTH); }
bool HasInvisibilityAura() const { return HasAuraType(SPELL_AURA_MOD_INVISIBILITY); }
@@ -937,7 +941,7 @@
void SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchools DamageType, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount);
void SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchools DamageType,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false);
- void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, bool Run, uint32 Time);
+ void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, bool Run, uint32 Time, bool tryFlag512 = false);
virtual void MoveOutOfRange(Player &) { };
@@ -1022,6 +1026,7 @@
void InterruptNonMeleeSpells(bool withDelayed);
Spell* m_currentSpells[CURRENT_MAX_SPELL];
+ bool m_hasHealer;
uint32 m_addDmgOnce;
uint64 m_TotemSlot[4];
uint64 m_ObjectSlot[4];
@@ -1152,7 +1157,27 @@
bool IsStopped() const { return !(hasUnitState(UNIT_STAT_MOVING)); }
void StopMoving();
-
+
+ //AI Improuved Function
+ const bool hasFriendTarget()
+ {
+ return ( !getVictim() && GetUInt64Value(UNIT_FIELD_TARGET) );
+ }
+ const bool hasVictim()
+ {
+ return getVictim() ? true : false;
+ }
+ static const uint8 getHpPercent(Unit* unit)
+ {
+ return unit->GetMaxHealth() ? uint8( (float)unit->GetHealth() / (float)unit->GetMaxHealth() * 100 ) : 0;
+ }
+ static const uint8 getMpPercent(Unit* unit)
+ {
+ return unit->GetMaxPower( POWER_MANA) ? uint8((float)unit->GetPower(POWER_MANA) / (float)unit->GetMaxPower(POWER_MANA) * 100 ) : 0;
+ }
+ void DoDoSay(const char *text, ...); //Debug Function Should get Removed, GS
+ // END AI Improuved Feature
+
void setMoveRunFlag(bool f) { m_moveRun = f; }
bool getMoveRunFlag() const { return m_moveRun; }
Index: src/game/WaypointMovementGenerator.cpp
===================================================================
--- src/game/WaypointMovementGenerator.cpp (revision 4763)
+++ src/game/WaypointMovementGenerator.cpp (working copy)
@@ -159,6 +159,8 @@
{
QueryResult *result = WorldDatabase.Query("SELECT distinct(`id`) as uniqueid FROM `creature_movement`");
+ //Need to redone everything here... MeanMachine has created a patch for this.... , GS
+ //Badly need MeanMachine Patch + add my change to it.
if( result )
{
do
@@ -181,8 +183,8 @@
// 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_STUNDED))
- return true;
+ //if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNDED))
+ //return true;
// prevent crash at empty waypoint path.
if(i_path.Empty())
@@ -373,34 +375,39 @@
bool
FlightPathMovementGenerator::Update(Player &player, const uint32 &diff)
{
- if( MovementInProgress() )
- {
+ //if( MovementInProgress() )
+ //{
Traveller<Player> traveller(player);
- if( i_destinationHolder.UpdateTraveller(traveller, diff, false) )
- {
- i_destinationHolder.ResetUpdate(FLIGHT_TRAVEL_UPDATE);
+ i_destinationHolder.UpdateTraveller(traveller, diff, false);
+ //if( i_destinationHolder.UpdateTraveller(traveller, diff, false) )
+ //{
+ //i_destinationHolder.ResetUpdate(FLIGHT_TRAVEL_UPDATE);
if( i_destinationHolder.HasArrived() )
{
+ if(i_path.Size() <= i_currentNode+1)
+ {
+ EndFlight(player);
+ return false;
+ }
++i_currentNode;
- if( MovementInProgress() )
- {
- DEBUG_LOG("loading node %u for player %s", i_currentNode, player.GetName());
+ //if( MovementInProgress() )
+ //{
+ //DEBUG_LOG("loading node %u for player %s", i_currentNode, player.GetName());
// do not send movement, it was sent already
i_destinationHolder.SetDestination(traveller, i_path[i_currentNode].x, i_path[i_currentNode].y, i_path[i_currentNode].z, false);
- return true;
- }
+ //}
//else HasArrived()
}
- else
- return true;
- }
- else
- return true;
- }
-
+ //else
+ //return true;
+ //}
+ //else
+ // return true;
+ //}
+ return true;
// we have arrived at the end of the path
- EndFlight(player);
- return false;
+ //EndFlight(player);
+ //return false;
}
void
Index: src/game/WaypointMovementGenerator.h
===================================================================
--- src/game/WaypointMovementGenerator.h (revision 4763)
+++ src/game/WaypointMovementGenerator.h (working copy)
@@ -67,7 +67,10 @@
{
return i_currentNode;
}
-
+ void UpdateMapPosition(float &x ,float &y, float &z)
+ {
+ i_destinationHolder.GetLocationNow(x,y,z);
+ }
protected:
uint32 i_currentNode;
DestinationHolder< Traveller<T> > i_destinationHolder;
Index: src/game/World.cpp
===================================================================
--- src/game/World.cpp (revision 4763)
+++ src/game/World.cpp (working copy)
@@ -380,7 +380,7 @@
m_configs[CONFIG_GROUP_XP_DISTANCE] = m_configs[CONFIG_GROUP_XP_DISTANCE]*m_configs[CONFIG_GROUP_XP_DISTANCE];
/// \todo Add MonsterSight and GuarderSight (with meaning) in mangosd.conf or put them as define
m_configs[CONFIG_SIGHT_MONSTER] = sConfig.GetIntDefault("MonsterSight", 400);
- m_configs[CONFIG_SIGHT_GUARDER] = sConfig.GetIntDefault("GuarderSight", 500);
+ m_configs[CONFIG_SIGHT_GUARDER] = sConfig.GetIntDefault("GuarderSight", 800);
m_configs[CONFIG_GAME_TYPE] = sConfig.GetIntDefault("GameType", 0);
m_configs[CONFIG_ALLOW_TWO_SIDE_ACCOUNTS] = sConfig.GetIntDefault("AllowTwoSide.Accounts", 0);
m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT] = sConfig.GetIntDefault("AllowTwoSide.Interaction.Chat",0);
@@ -633,6 +633,9 @@
sLog.outString( "Loading Creature Respawn Data..." ); // must be after PackInstances()
objmgr.LoadCreatureRespawnTimes();
+ sLog.outString( "Loading Creature SpellBook Data..." );
+ objmgr.LoadCreatureSpellBook();
+
sLog.outString( "Loading Gameobject Data..." );
objmgr.LoadGameobjects();
Index: src/shared/Database/DBCStores.cpp
===================================================================
--- src/shared/Database/DBCStores.cpp (revision 4763)
+++ src/shared/Database/DBCStores.cpp (working copy)
@@ -819,3 +819,5 @@
// script support functions
MANGOS_DLL_SPEC DBCStorage <SpellEntry> const* GetSpellStore() { return &sSpellStore; }
MANGOS_DLL_SPEC DBCStorage <SpellRangeEntry> const* GetSpellRangeStore() { return &sSpellRangeStore; }
+MANGOS_DLL_SPEC DBCStorage <SpellDurationEntry> const* GetSpellDurationStore() { return &sSpellDurationStore; }
+MANGOS_DLL_SPEC DBCStorage <SpellCastTimesEntry> const* GetCastTimesStore() { return &sCastTimesStore; }
Index: src/shared/Database/DBCStores.h
===================================================================
--- src/shared/Database/DBCStores.h (revision 4763)
+++ src/shared/Database/DBCStores.h (working copy)
@@ -202,6 +202,8 @@
void LoadDBCStores(std::string dataPath);
// script support functions
-MANGOS_DLL_SPEC DBCStorage <SpellEntry> const* GetSpellStore() ;
-MANGOS_DLL_SPEC DBCStorage <SpellRangeEntry> const* GetSpellRangeStore() ;
+MANGOS_DLL_SPEC DBCStorage <SpellEntry> const* GetSpellStore();
+MANGOS_DLL_SPEC DBCStorage <SpellRangeEntry> const* GetSpellRangeStore();
+MANGOS_DLL_SPEC DBCStorage <SpellDurationEntry> const* GetSpellDurationStore();
+MANGOS_DLL_SPEC DBCStorage <SpellCastTimesEntry> const* GetCastTimesStore();
#endif
Index: src/shared/Timer.h
===================================================================
--- src/shared/Timer.h (revision 4763)
+++ src/shared/Timer.h (working copy)
@@ -74,4 +74,13 @@
time_t GetExpiry(void) const { return i_expiryTime; }
time_t i_expiryTime;
};
+
+struct TimeTracker2
+{
+ TimeTracker2(int32 expiry) : i_expiryTime(expiry) {}
+ void Update(int32 diff) { i_expiryTime -= diff; }
+ bool Passed(void) const { return (i_expiryTime <= 0); }
+ void Reset(int32 interval) { i_expiryTime = interval; }
+ int32 i_expiryTime;
+};
#endif
Index: src/shared/Util.h
===================================================================
--- src/shared/Util.h (revision 4763)
+++ src/shared/Util.h (working copy)
@@ -36,6 +36,7 @@
/* Return a random number in the range min..max; (max-min) must be smaller than 32768.
* Note: Not reentrant - if two threads call this simultaneously, they will likely
* get the same random number. */
+MANGOS_DLL_SPEC
extern int32 irand(int32 min, int32 max);
/* Return a random number in the range min..max; (max-min) must be smaller than 32768.
@@ -52,11 +53,13 @@
/* Return a random number in the range 0 .. RAND32_MAX.
* Note: Not reentrant - if two threads call this simultaneously, they will likely
* get the same random number. */
+MANGOS_DLL_SPEC
extern int32 rand32(void);
/* Return a random double from 0.0 to 1.0 (exclusive). Floats support only 7 valid decimal digits.
* A double supports up to 15 valid decimal digits and is used internaly (RAND32_MAX has 10 digits).
* With an FPU, there is usually no difference in performance between float and double. */
+MANGOS_DLL_SPEC
inline double rand_norm(void)
{
return double(rand32()) / double(RAND32_MAX+1);
Index: src/shared/vmap/VMapManager.cpp
===================================================================
--- src/shared/vmap/VMapManager.cpp (revision 4763)
+++ src/shared/vmap/VMapManager.cpp (working copy)
@@ -431,9 +431,9 @@
{
height = VMAP_INVALID_HEIGHT; //no height
}
- Command c = Command();
- c.fillTestHeightCmd(pMapId,Vector3(x,y,z),height);
- iCommandLogger.appendCmd(c);
+ //Command c = Command();
+ //c.fillTestHeightCmd(pMapId,Vector3(x,y,z),height);
+ //iCommandLogger.appendCmd(c);
}
return(height);
}
Index: win/mangosdVC80.sln
===================================================================
--- win/mangosdVC80.sln (revision 4763)
+++ win/mangosdVC80.sln (working copy)
@@ -7,10 +7,10 @@
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shared", "VC80\shared.vcproj", "{90297C34-F231-4DF4-848E-A74BCC0E40ED}"
ProjectSection(ProjectDependencies) = postProject
+ {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E} = {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E}
+ {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2} = {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}
+ {8072769E-CF10-48BF-B9E1-12752A5DAC6E} = {8072769E-CF10-48BF-B9E1-12752A5DAC6E}
{262199E8-EEDF-4700-A1D1-E9CC901CF480} = {262199E8-EEDF-4700-A1D1-E9CC901CF480}
- {8072769E-CF10-48BF-B9E1-12752A5DAC6E} = {8072769E-CF10-48BF-B9E1-12752A5DAC6E}
- {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2} = {8F1DEA42-6A5B-4B62-839D-C141A7BFACF2}
- {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E} = {BF6F5D0E-33A5-4E23-9E7D-DD481B7B5B9E}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mangosd", "VC80\mangosd.vcproj", "{A3A04E47-43A2-4C08-90B3-029CEF558594}"
Index: win/VC80/game.vcproj
===================================================================
--- win/VC80/game.vcproj (revision 4763)
+++ win/VC80/game.vcproj (working copy)
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8,00"
+ Version="8.00"
Name="game"
ProjectGUID="{1DC6C4DA-A028-41F3-877D-D5400C594F88}"
RootNamespace="game"
@@ -598,6 +598,14 @@
>
</File>
<File
+ RelativePath="..\..\src\game\AggressorCasterAI.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\game\AggressorCasterAI.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\game\AnimalRandomMovementGenerator.h"
>
</File>
@@ -694,6 +702,14 @@
>
</File>
<File
+ RelativePath="..\..\src\game\FleeingMovementGenerator.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\game\FleeingMovementGenerator.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\game\Formulas.h"
>
</File>
Index: win/VC80/mangosd.vcproj
===================================================================
--- win/VC80/mangosd.vcproj (revision 4763)
+++ win/VC80/mangosd.vcproj (working copy)
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8,00"
+ Version="8.00"
Name="mangosd"
ProjectGUID="{A3A04E47-43A2-4C08-90B3-029CEF558594}"
RootNamespace="mangosd"
Index: win/VC80/shared.vcproj
===================================================================
--- win/VC80/shared.vcproj (revision 4763)
+++ win/VC80/shared.vcproj (working copy)
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
- Version="8,00"
+ Version="8.00"
Name="shared"
ProjectGUID="{90297C34-F231-4DF4-848E-A74BCC0E40ED}"
>