* location</li> <li>If the actor is a L2MonsterInstance that can't attack, order to it to random walk (1/100)</li><BR>
* <BR>
*/
private void thinkActive()
{
L2Attackable npc = (L2Attackable) _actor;
// Update every 1s the _globalAggro counter to come close to 0
if(_globalAggro != 0)
{
if(_globalAggro < 0)
{
_globalAggro++;
}
else
{
_globalAggro--;
}
}
// Add all autoAttackable L2Character in L2Attackable Aggro Range to its _aggroList with 0 damage and 1 hate
// A L2Attackable isn't aggressive during 10s after its spawn because _globalAggro is set to -10
if(_globalAggro >= 0)
{
// Get all visible objects inside its Aggro Range
//L2Object[] objects = L2World.getInstance().getVisibleObjects(_actor, ((L2NpcInstance)_actor).getAggroRange());
// Go through visible objects
for(L2Object obj : npc.getKnownList().getKnownObjects().values())
{
if(obj == null || !(obj instanceof L2Character))
{
continue;
}
L2Character target = (L2Character) obj;
/*
* Check to see if this is a festival mob spawn.
* If it is, then check to see if the aggro trigger
* is a festival participant...if so, move to attack it.
*/
if(_actor instanceof L2FestivalMonsterInstance && obj instanceof L2PcInstance)
{
L2PcInstance targetPlayer = (L2PcInstance) obj;
if(!targetPlayer.isFestivalParticipant())
{
continue;
}
targetPlayer = null;
}
if(obj instanceof L2PcInstance
|| obj instanceof L2Summon)
{
if(!target.isAlikeDead() && !npc.isInsideRadius(obj, npc.getAggroRange(), true, false))
{
L2PcInstance targetPlayer = obj instanceof L2PcInstance ? (L2PcInstance) obj : ((L2Summon) obj).getOwner();
for(Quest quest : npc.getTemplate().getEventQuests(Quest.QuestEventType.ON_AGGRO_RANGE_ENTER))
{
quest.notifyAggroRangeEnter(npc, targetPlayer, obj instanceof L2Summon);
}
}
}
// For each L2Character check if the target is autoattackable
if(autoAttackCondition(target)) // check aggression
{
// Get the hate level of the L2Attackable against this L2Character target contained in _aggroList
int hating = npc.getHating(target);
// Add the attacker to the L2Attackable _aggroList with 0 damage and 1 hate
if(hating == 0)
{
npc.addDamageHate(target, 0, 1);
}
}
target = null;
}
// Chose a target from its aggroList
L2Character hated;
// Force mobs to attak anybody if confused
if(_actor.isConfused())
{
hated = getAttackTarget();
}
else
{
hated = npc.getMostHated();
}
// Order to the L2Attackable to attack the target
if(hated != null)
{
// Get the hate level of the L2Attackable against this L2Character target contained in _aggroList
int aggro = npc.getHating(hated);
if(aggro + _globalAggro > 0)
{
// Set the L2Character movement type to run and send Server->Client packet ChangeMoveType to all others L2PcInstance
if(!_actor.isRunning())
{
_actor.setRunning();
}
// Set the AI Intention to AI_INTENTION_ATTACK
setIntention(CtrlIntention.AI_INTENTION_ATTACK, hated);
}
return;
}
}
// Check if the actor is a L2GuardInstance
if(_actor instanceof L2GuardInstance)
{
// Order to the L2GuardInstance to return to its home location because there's no target to attack
((L2GuardInstance) _actor).returnHome();
}
// If this is a festival monster, then it remains in the same location.
if(_actor instanceof L2FestivalMonsterInstance)
return;
// Check if the mob should not return to spawn point
if(!npc.canReturnToSpawnPoint())
return;
// Minions following leader
if(_actor instanceof L2MinionInstance && ((L2MinionInstance) _actor).getLeader() != null)
{
int offset;
// for Raids - need correction
if(_actor.isRaid())
{
offset = 500;
}
else
{
// for normal minions - need correction :)
offset = 200;
}
if(((L2MinionInstance) _actor).getLeader().isRunning())
{
_actor.setRunning();
}
else
{
_actor.setWalking();
}
if(_actor.getPlanDistanceSq(((L2MinionInstance) _actor).getLeader()) > offset * offset)
{
int x1, y1, z1;
x1 = ((L2MinionInstance) _actor).getLeader().getX() + Rnd.nextInt((offset - 30) * 2) - (offset - 30);
y1 = ((L2MinionInstance) _actor).getLeader().getY() + Rnd.nextInt((offset - 30) * 2) - (offset - 30);
z1 = ((L2MinionInstance) _actor).getLeader().getZ();
// Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
moveTo(x1, y1, z1);
return;
}
}
// Order to the L2MonsterInstance to random walk (1/100)
else if(!(npc instanceof L2ChestInstance) && npc.getSpawn() != null && Rnd.nextInt(RANDOM_WALK_RATE) == 0)
{
int x1, y1, z1;
// If NPC with random coord in territory
if(npc.getSpawn().getLocx() == 0 && npc.getSpawn().getLocy() == 0)
{
// If NPC with random fixed coord, don't move
if(TerritoryTable.getInstance().getProcMax(npc.getSpawn().getLocation()) > 0)
return;
// Calculate a destination point in the spawn area
int p[] = TerritoryTable.getInstance().getRandomPoint(npc.getSpawn().getLocation());
x1 = p[0];
y1 = p[1];
z1 = p[2];
// Calculate the distance between the current position of the L2Character and the target (x,y)
double distance2 = _actor.getPlanDistanceSq(x1, y1);
if(distance2 > Config.MAX_DRIFT_RANGE * Config.MAX_DRIFT_RANGE)
{
npc.setisReturningToSpawnPoint(true);
float delay = (float) Math.sqrt(distance2) / Config.MAX_DRIFT_RANGE;
x1 = _actor.getX() + (int) ((x1 - _actor.getX()) / delay);
y1 = _actor.getY() + (int) ((y1 - _actor.getY()) / delay);
}
else
{
npc.setisReturningToSpawnPoint(false);
}
}
else
{
if(Config.MONSTER_RETURN_DELAY > 0 && npc instanceof L2MonsterInstance && !npc.isAlikeDead() && !npc.isDead() && npc.getSpawn() != null && !npc.isInsideRadius(npc.getSpawn().getLocx(), npc.getSpawn().getLocy(), Config.MAX_DRIFT_RANGE, false))
{
((L2MonsterInstance) _actor).returnHome();
}
// If NPC with fixed coord
x1 = npc.getSpawn().getLocx() + Rnd.nextInt(Config.MAX_DRIFT_RANGE * 2) - Config.MAX_DRIFT_RANGE;
y1 = npc.getSpawn().getLocy() + Rnd.nextInt(Config.MAX_DRIFT_RANGE * 2) - Config.MAX_DRIFT_RANGE;
z1 = npc.getZ();
}
//_log.config("Curent pos ("+getX()+", "+getY()+"), moving to ("+x1+", "+y1+").");
// Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
moveTo(x1, y1, z1);