Enabled Valakas skills.
This commit is contained in:
@@ -16,23 +16,32 @@
|
|||||||
*/
|
*/
|
||||||
package ai.bosses.Valakas;
|
package ai.bosses.Valakas;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||||
import org.l2jmobius.gameserver.enums.MountType;
|
import org.l2jmobius.gameserver.enums.MountType;
|
||||||
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.model.StatsSet;
|
import org.l2jmobius.gameserver.model.StatsSet;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
import org.l2jmobius.gameserver.model.actor.Attackable;
|
||||||
import org.l2jmobius.gameserver.model.actor.Npc;
|
import org.l2jmobius.gameserver.model.actor.Npc;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||||
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||||
|
import org.l2jmobius.gameserver.util.Util;
|
||||||
|
|
||||||
import ai.AbstractNpcAI;
|
import ai.AbstractNpcAI;
|
||||||
|
|
||||||
@@ -46,12 +55,36 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final int VALAKAS = 29028;
|
private static final int VALAKAS = 29028;
|
||||||
// Skills
|
// Skills
|
||||||
private static final int VALAKAS_REGENERATION = 4691;
|
private static final int VALAKAS_REGENERATION = 4691;
|
||||||
/*
|
private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1);
|
||||||
* private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1); private static final SkillHolder[] VALAKAS_REGULAR_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. }; private static final SkillHolder[] VALAKAS_LOWHP_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
private static final SkillHolder[] VALAKAS_REGULAR_SKILLS =
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm }; private static final SkillHolder[] VALAKAS_AOE_SKILLS = { new SkillHolder(4683, 1), // Valakas Dragon Breath new SkillHolder(4684, 1), // Valakas Dragon
|
{
|
||||||
* Breath new SkillHolder(4685, 1), // Valakas Tail Stomp new SkillHolder(4686, 1), // Valakas Tail Stomp new SkillHolder(4688, 1), // Valakas Stun new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm };
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
*/
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_LOWHP_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_AOE_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4684, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4685, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4686, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4688, 1), // Valakas Stun
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
// Locations
|
// Locations
|
||||||
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
||||||
{
|
{
|
||||||
@@ -82,7 +115,7 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
||||||
// Misc
|
// Misc
|
||||||
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
||||||
// private Playable _actualVictim; // Actual target of Valakas.
|
private Playable _actualVictim; // Actual target of Valakas.
|
||||||
private static ZoneType ZONE;
|
private static ZoneType ZONE;
|
||||||
|
|
||||||
private Valakas()
|
private Valakas()
|
||||||
@@ -326,10 +359,10 @@ public class Valakas extends AbstractNpcAI
|
|||||||
|
|
||||||
startQuestTimer("remove_players", 900000, null, null);
|
startQuestTimer("remove_players", 900000, null, null);
|
||||||
}
|
}
|
||||||
// else if (event.equalsIgnoreCase("skill_task"))
|
else if (event.equalsIgnoreCase("skill_task"))
|
||||||
// {
|
{
|
||||||
// callSkillAI(npc);
|
callSkillAI(npc);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
else if (event.equalsIgnoreCase("valakas_unlock"))
|
else if (event.equalsIgnoreCase("valakas_unlock"))
|
||||||
{
|
{
|
||||||
@@ -420,17 +453,114 @@ public class Valakas extends AbstractNpcAI
|
|||||||
return super.onKill(npc, killer, isSummon);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* @Override public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon) { return null; } private void callSkillAI(Npc npc) { if (npc.isInvul() || npc.isCastingNow()) { return; } // Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target. if
|
public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon)
|
||||||
* ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0)) { _actualVictim = getRandomTarget(npc); } // If result is still null, Valakas will roam. Don't go deeper in skill AI. if (_actualVictim == null) { if (getRandom(10) == 0)
|
{
|
||||||
* { final int x = npc.getX(); final int y = npc.getY(); final int z = npc.getZ(); final int posX = x + getRandom(-1400, 1400); final int posY = y + getRandom(-1400, 1400); if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceId())) {
|
return null;
|
||||||
* npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0)); } } return; } final Skill skill = getRandomSkill(npc).getSkill(); // Cast the skill or follow the target. if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc,
|
}
|
||||||
* _actualVictim, true)) { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); npc.setIsCastingNow(true); npc.setTarget(_actualVictim); npc.doCast(skill); } else { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null); npc.setIsCastingNow(false); } } private
|
|
||||||
* SkillHolder getRandomSkill(Npc npc) { final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100); // Valakas Lava Skin has priority. if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId())) { return VALAKAS_LAVA_SKIN; } // Valakas
|
private void callSkillAI(Npc npc)
|
||||||
* will use mass spells if he feels surrounded. if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20) { return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)]; } if (hpRatio > 50) { return
|
{
|
||||||
* VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)]; } return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)]; } private Playable getRandomTarget(Npc npc) { final List<Playable> result = new ArrayList<>(); World.getInstance().forEachVisibleObject(npc, Playable.class,
|
if (npc.isInvul() || npc.isCastingNow())
|
||||||
* obj -> { if ((obj == null) || obj.isPet()) { return; } else if (!obj.isDead() && obj.isPlayable()) { result.add(obj); } }); return result.isEmpty() ? null : result.get(getRandom(result.size())); }
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target.
|
||||||
|
if ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0))
|
||||||
|
{
|
||||||
|
_actualVictim = getRandomTarget(npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If result is still null, Valakas will roam. Don't go deeper in skill AI.
|
||||||
|
if (_actualVictim == null)
|
||||||
|
{
|
||||||
|
if (getRandom(10) == 0)
|
||||||
|
{
|
||||||
|
final int x = npc.getX();
|
||||||
|
final int y = npc.getY();
|
||||||
|
final int z = npc.getZ();
|
||||||
|
|
||||||
|
final int posX = x + getRandom(-1400, 1400);
|
||||||
|
final int posY = y + getRandom(-1400, 1400);
|
||||||
|
|
||||||
|
if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Skill skill = getRandomSkill(npc).getSkill();
|
||||||
|
|
||||||
|
// Cast the skill or follow the target.
|
||||||
|
if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc, _actualVictim, true))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||||
|
npc.setTarget(_actualVictim);
|
||||||
|
npc.doCast(skill);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick a random skill.<br>
|
||||||
|
* Valakas will mostly use utility skills. If Valakas feels surrounded, he will use AoE skills.<br>
|
||||||
|
* Lower than 50% HPs, he will begin to use Meteor skill.
|
||||||
|
* @param npc valakas
|
||||||
|
* @return a skill holder
|
||||||
*/
|
*/
|
||||||
|
private SkillHolder getRandomSkill(Npc npc)
|
||||||
|
{
|
||||||
|
final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100);
|
||||||
|
|
||||||
|
// Valakas Lava Skin has priority.
|
||||||
|
if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId()))
|
||||||
|
{
|
||||||
|
return VALAKAS_LAVA_SKIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valakas will use mass spells if he feels surrounded.
|
||||||
|
if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20)
|
||||||
|
{
|
||||||
|
return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hpRatio > 50)
|
||||||
|
{
|
||||||
|
return VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pickup a random Playable from the zone, deads targets aren't included.
|
||||||
|
* @param npc
|
||||||
|
* @return a random Playable.
|
||||||
|
*/
|
||||||
|
private Playable getRandomTarget(Npc npc)
|
||||||
|
{
|
||||||
|
final List<Playable> result = new ArrayList<>();
|
||||||
|
|
||||||
|
World.getInstance().forEachVisibleObject(npc, Playable.class, obj ->
|
||||||
|
{
|
||||||
|
if ((obj == null) || obj.isPet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!obj.isDead() && obj.isPlayable())
|
||||||
|
{
|
||||||
|
result.add(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.isEmpty() ? null : result.get(getRandom(result.size()));
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
@@ -16,23 +16,32 @@
|
|||||||
*/
|
*/
|
||||||
package ai.bosses.Valakas;
|
package ai.bosses.Valakas;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||||
import org.l2jmobius.gameserver.enums.MountType;
|
import org.l2jmobius.gameserver.enums.MountType;
|
||||||
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.model.StatsSet;
|
import org.l2jmobius.gameserver.model.StatsSet;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
import org.l2jmobius.gameserver.model.actor.Attackable;
|
||||||
import org.l2jmobius.gameserver.model.actor.Npc;
|
import org.l2jmobius.gameserver.model.actor.Npc;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||||
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||||
|
import org.l2jmobius.gameserver.util.Util;
|
||||||
|
|
||||||
import ai.AbstractNpcAI;
|
import ai.AbstractNpcAI;
|
||||||
|
|
||||||
@@ -46,12 +55,36 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final int VALAKAS = 29028;
|
private static final int VALAKAS = 29028;
|
||||||
// Skills
|
// Skills
|
||||||
private static final int VALAKAS_REGENERATION = 4691;
|
private static final int VALAKAS_REGENERATION = 4691;
|
||||||
/*
|
private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1);
|
||||||
* private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1); private static final SkillHolder[] VALAKAS_REGULAR_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. }; private static final SkillHolder[] VALAKAS_LOWHP_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
private static final SkillHolder[] VALAKAS_REGULAR_SKILLS =
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm }; private static final SkillHolder[] VALAKAS_AOE_SKILLS = { new SkillHolder(4683, 1), // Valakas Dragon Breath new SkillHolder(4684, 1), // Valakas Dragon
|
{
|
||||||
* Breath new SkillHolder(4685, 1), // Valakas Tail Stomp new SkillHolder(4686, 1), // Valakas Tail Stomp new SkillHolder(4688, 1), // Valakas Stun new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm };
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
*/
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_LOWHP_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_AOE_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4684, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4685, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4686, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4688, 1), // Valakas Stun
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
// Locations
|
// Locations
|
||||||
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
||||||
{
|
{
|
||||||
@@ -82,7 +115,7 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
||||||
// Misc
|
// Misc
|
||||||
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
||||||
// private Playable _actualVictim; // Actual target of Valakas.
|
private Playable _actualVictim; // Actual target of Valakas.
|
||||||
private static ZoneType ZONE;
|
private static ZoneType ZONE;
|
||||||
|
|
||||||
private Valakas()
|
private Valakas()
|
||||||
@@ -326,10 +359,10 @@ public class Valakas extends AbstractNpcAI
|
|||||||
|
|
||||||
startQuestTimer("remove_players", 900000, null, null);
|
startQuestTimer("remove_players", 900000, null, null);
|
||||||
}
|
}
|
||||||
// else if (event.equalsIgnoreCase("skill_task"))
|
else if (event.equalsIgnoreCase("skill_task"))
|
||||||
// {
|
{
|
||||||
// callSkillAI(npc);
|
callSkillAI(npc);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
else if (event.equalsIgnoreCase("valakas_unlock"))
|
else if (event.equalsIgnoreCase("valakas_unlock"))
|
||||||
{
|
{
|
||||||
@@ -420,17 +453,114 @@ public class Valakas extends AbstractNpcAI
|
|||||||
return super.onKill(npc, killer, isSummon);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* @Override public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon) { return null; } private void callSkillAI(Npc npc) { if (npc.isInvul() || npc.isCastingNow()) { return; } // Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target. if
|
public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon)
|
||||||
* ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0)) { _actualVictim = getRandomTarget(npc); } // If result is still null, Valakas will roam. Don't go deeper in skill AI. if (_actualVictim == null) { if (getRandom(10) == 0)
|
{
|
||||||
* { final int x = npc.getX(); final int y = npc.getY(); final int z = npc.getZ(); final int posX = x + getRandom(-1400, 1400); final int posY = y + getRandom(-1400, 1400); if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceId())) {
|
return null;
|
||||||
* npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0)); } } return; } final Skill skill = getRandomSkill(npc).getSkill(); // Cast the skill or follow the target. if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc,
|
}
|
||||||
* _actualVictim, true)) { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); npc.setIsCastingNow(true); npc.setTarget(_actualVictim); npc.doCast(skill); } else { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null); npc.setIsCastingNow(false); } } private
|
|
||||||
* SkillHolder getRandomSkill(Npc npc) { final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100); // Valakas Lava Skin has priority. if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId())) { return VALAKAS_LAVA_SKIN; } // Valakas
|
private void callSkillAI(Npc npc)
|
||||||
* will use mass spells if he feels surrounded. if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20) { return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)]; } if (hpRatio > 50) { return
|
{
|
||||||
* VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)]; } return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)]; } private Playable getRandomTarget(Npc npc) { final List<Playable> result = new ArrayList<>(); World.getInstance().forEachVisibleObject(npc, Playable.class,
|
if (npc.isInvul() || npc.isCastingNow())
|
||||||
* obj -> { if ((obj == null) || obj.isPet()) { return; } else if (!obj.isDead() && obj.isPlayable()) { result.add(obj); } }); return result.isEmpty() ? null : result.get(getRandom(result.size())); }
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target.
|
||||||
|
if ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0))
|
||||||
|
{
|
||||||
|
_actualVictim = getRandomTarget(npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If result is still null, Valakas will roam. Don't go deeper in skill AI.
|
||||||
|
if (_actualVictim == null)
|
||||||
|
{
|
||||||
|
if (getRandom(10) == 0)
|
||||||
|
{
|
||||||
|
final int x = npc.getX();
|
||||||
|
final int y = npc.getY();
|
||||||
|
final int z = npc.getZ();
|
||||||
|
|
||||||
|
final int posX = x + getRandom(-1400, 1400);
|
||||||
|
final int posY = y + getRandom(-1400, 1400);
|
||||||
|
|
||||||
|
if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Skill skill = getRandomSkill(npc).getSkill();
|
||||||
|
|
||||||
|
// Cast the skill or follow the target.
|
||||||
|
if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc, _actualVictim, true))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||||
|
npc.setTarget(_actualVictim);
|
||||||
|
npc.doCast(skill);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick a random skill.<br>
|
||||||
|
* Valakas will mostly use utility skills. If Valakas feels surrounded, he will use AoE skills.<br>
|
||||||
|
* Lower than 50% HPs, he will begin to use Meteor skill.
|
||||||
|
* @param npc valakas
|
||||||
|
* @return a skill holder
|
||||||
*/
|
*/
|
||||||
|
private SkillHolder getRandomSkill(Npc npc)
|
||||||
|
{
|
||||||
|
final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100);
|
||||||
|
|
||||||
|
// Valakas Lava Skin has priority.
|
||||||
|
if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId()))
|
||||||
|
{
|
||||||
|
return VALAKAS_LAVA_SKIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valakas will use mass spells if he feels surrounded.
|
||||||
|
if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20)
|
||||||
|
{
|
||||||
|
return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hpRatio > 50)
|
||||||
|
{
|
||||||
|
return VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pickup a random Playable from the zone, deads targets aren't included.
|
||||||
|
* @param npc
|
||||||
|
* @return a random Playable.
|
||||||
|
*/
|
||||||
|
private Playable getRandomTarget(Npc npc)
|
||||||
|
{
|
||||||
|
final List<Playable> result = new ArrayList<>();
|
||||||
|
|
||||||
|
World.getInstance().forEachVisibleObject(npc, Playable.class, obj ->
|
||||||
|
{
|
||||||
|
if ((obj == null) || obj.isPet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!obj.isDead() && obj.isPlayable())
|
||||||
|
{
|
||||||
|
result.add(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.isEmpty() ? null : result.get(getRandom(result.size()));
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
@@ -16,23 +16,32 @@
|
|||||||
*/
|
*/
|
||||||
package ai.bosses.Valakas;
|
package ai.bosses.Valakas;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||||
import org.l2jmobius.gameserver.enums.MountType;
|
import org.l2jmobius.gameserver.enums.MountType;
|
||||||
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.model.StatsSet;
|
import org.l2jmobius.gameserver.model.StatsSet;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
import org.l2jmobius.gameserver.model.actor.Attackable;
|
||||||
import org.l2jmobius.gameserver.model.actor.Npc;
|
import org.l2jmobius.gameserver.model.actor.Npc;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||||
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||||
|
import org.l2jmobius.gameserver.util.Util;
|
||||||
|
|
||||||
import ai.AbstractNpcAI;
|
import ai.AbstractNpcAI;
|
||||||
|
|
||||||
@@ -46,12 +55,36 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final int VALAKAS = 29028;
|
private static final int VALAKAS = 29028;
|
||||||
// Skills
|
// Skills
|
||||||
private static final int VALAKAS_REGENERATION = 4691;
|
private static final int VALAKAS_REGENERATION = 4691;
|
||||||
/*
|
private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1);
|
||||||
* private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1); private static final SkillHolder[] VALAKAS_REGULAR_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. }; private static final SkillHolder[] VALAKAS_LOWHP_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
private static final SkillHolder[] VALAKAS_REGULAR_SKILLS =
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm }; private static final SkillHolder[] VALAKAS_AOE_SKILLS = { new SkillHolder(4683, 1), // Valakas Dragon Breath new SkillHolder(4684, 1), // Valakas Dragon
|
{
|
||||||
* Breath new SkillHolder(4685, 1), // Valakas Tail Stomp new SkillHolder(4686, 1), // Valakas Tail Stomp new SkillHolder(4688, 1), // Valakas Stun new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm };
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
*/
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_LOWHP_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_AOE_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4684, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4685, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4686, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4688, 1), // Valakas Stun
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
// Locations
|
// Locations
|
||||||
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
||||||
{
|
{
|
||||||
@@ -82,7 +115,7 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
||||||
// Misc
|
// Misc
|
||||||
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
||||||
// private Playable _actualVictim; // Actual target of Valakas.
|
private Playable _actualVictim; // Actual target of Valakas.
|
||||||
private static ZoneType ZONE;
|
private static ZoneType ZONE;
|
||||||
|
|
||||||
private Valakas()
|
private Valakas()
|
||||||
@@ -326,10 +359,10 @@ public class Valakas extends AbstractNpcAI
|
|||||||
|
|
||||||
startQuestTimer("remove_players", 900000, null, null);
|
startQuestTimer("remove_players", 900000, null, null);
|
||||||
}
|
}
|
||||||
// else if (event.equalsIgnoreCase("skill_task"))
|
else if (event.equalsIgnoreCase("skill_task"))
|
||||||
// {
|
{
|
||||||
// callSkillAI(npc);
|
callSkillAI(npc);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
else if (event.equalsIgnoreCase("valakas_unlock"))
|
else if (event.equalsIgnoreCase("valakas_unlock"))
|
||||||
{
|
{
|
||||||
@@ -420,17 +453,114 @@ public class Valakas extends AbstractNpcAI
|
|||||||
return super.onKill(npc, killer, isSummon);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* @Override public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon) { return null; } private void callSkillAI(Npc npc) { if (npc.isInvul() || npc.isCastingNow()) { return; } // Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target. if
|
public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon)
|
||||||
* ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0)) { _actualVictim = getRandomTarget(npc); } // If result is still null, Valakas will roam. Don't go deeper in skill AI. if (_actualVictim == null) { if (getRandom(10) == 0)
|
{
|
||||||
* { final int x = npc.getX(); final int y = npc.getY(); final int z = npc.getZ(); final int posX = x + getRandom(-1400, 1400); final int posY = y + getRandom(-1400, 1400); if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceId())) {
|
return null;
|
||||||
* npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0)); } } return; } final Skill skill = getRandomSkill(npc).getSkill(); // Cast the skill or follow the target. if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc,
|
}
|
||||||
* _actualVictim, true)) { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); npc.setIsCastingNow(true); npc.setTarget(_actualVictim); npc.doCast(skill); } else { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null); npc.setIsCastingNow(false); } } private
|
|
||||||
* SkillHolder getRandomSkill(Npc npc) { final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100); // Valakas Lava Skin has priority. if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId())) { return VALAKAS_LAVA_SKIN; } // Valakas
|
private void callSkillAI(Npc npc)
|
||||||
* will use mass spells if he feels surrounded. if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20) { return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)]; } if (hpRatio > 50) { return
|
{
|
||||||
* VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)]; } return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)]; } private Playable getRandomTarget(Npc npc) { final List<Playable> result = new ArrayList<>(); World.getInstance().forEachVisibleObject(npc, Playable.class,
|
if (npc.isInvul() || npc.isCastingNow())
|
||||||
* obj -> { if ((obj == null) || obj.isPet()) { return; } else if (!obj.isDead() && obj.isPlayable()) { result.add(obj); } }); return result.isEmpty() ? null : result.get(getRandom(result.size())); }
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target.
|
||||||
|
if ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0))
|
||||||
|
{
|
||||||
|
_actualVictim = getRandomTarget(npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If result is still null, Valakas will roam. Don't go deeper in skill AI.
|
||||||
|
if (_actualVictim == null)
|
||||||
|
{
|
||||||
|
if (getRandom(10) == 0)
|
||||||
|
{
|
||||||
|
final int x = npc.getX();
|
||||||
|
final int y = npc.getY();
|
||||||
|
final int z = npc.getZ();
|
||||||
|
|
||||||
|
final int posX = x + getRandom(-1400, 1400);
|
||||||
|
final int posY = y + getRandom(-1400, 1400);
|
||||||
|
|
||||||
|
if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Skill skill = getRandomSkill(npc).getSkill();
|
||||||
|
|
||||||
|
// Cast the skill or follow the target.
|
||||||
|
if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc, _actualVictim, true))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||||
|
npc.setTarget(_actualVictim);
|
||||||
|
npc.doCast(skill);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick a random skill.<br>
|
||||||
|
* Valakas will mostly use utility skills. If Valakas feels surrounded, he will use AoE skills.<br>
|
||||||
|
* Lower than 50% HPs, he will begin to use Meteor skill.
|
||||||
|
* @param npc valakas
|
||||||
|
* @return a skill holder
|
||||||
*/
|
*/
|
||||||
|
private SkillHolder getRandomSkill(Npc npc)
|
||||||
|
{
|
||||||
|
final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100);
|
||||||
|
|
||||||
|
// Valakas Lava Skin has priority.
|
||||||
|
if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId()))
|
||||||
|
{
|
||||||
|
return VALAKAS_LAVA_SKIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valakas will use mass spells if he feels surrounded.
|
||||||
|
if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20)
|
||||||
|
{
|
||||||
|
return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hpRatio > 50)
|
||||||
|
{
|
||||||
|
return VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pickup a random Playable from the zone, deads targets aren't included.
|
||||||
|
* @param npc
|
||||||
|
* @return a random Playable.
|
||||||
|
*/
|
||||||
|
private Playable getRandomTarget(Npc npc)
|
||||||
|
{
|
||||||
|
final List<Playable> result = new ArrayList<>();
|
||||||
|
|
||||||
|
World.getInstance().forEachVisibleObject(npc, Playable.class, obj ->
|
||||||
|
{
|
||||||
|
if ((obj == null) || obj.isPet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!obj.isDead() && obj.isPlayable())
|
||||||
|
{
|
||||||
|
result.add(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.isEmpty() ? null : result.get(getRandom(result.size()));
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
@@ -16,23 +16,32 @@
|
|||||||
*/
|
*/
|
||||||
package ai.bosses.Valakas;
|
package ai.bosses.Valakas;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||||
import org.l2jmobius.gameserver.enums.MountType;
|
import org.l2jmobius.gameserver.enums.MountType;
|
||||||
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.model.StatsSet;
|
import org.l2jmobius.gameserver.model.StatsSet;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
import org.l2jmobius.gameserver.model.actor.Attackable;
|
||||||
import org.l2jmobius.gameserver.model.actor.Npc;
|
import org.l2jmobius.gameserver.model.actor.Npc;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||||
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||||
|
import org.l2jmobius.gameserver.util.Util;
|
||||||
|
|
||||||
import ai.AbstractNpcAI;
|
import ai.AbstractNpcAI;
|
||||||
|
|
||||||
@@ -46,12 +55,36 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final int VALAKAS = 29028;
|
private static final int VALAKAS = 29028;
|
||||||
// Skills
|
// Skills
|
||||||
private static final int VALAKAS_REGENERATION = 4691;
|
private static final int VALAKAS_REGENERATION = 4691;
|
||||||
/*
|
private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1);
|
||||||
* private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1); private static final SkillHolder[] VALAKAS_REGULAR_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. }; private static final SkillHolder[] VALAKAS_LOWHP_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
private static final SkillHolder[] VALAKAS_REGULAR_SKILLS =
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm }; private static final SkillHolder[] VALAKAS_AOE_SKILLS = { new SkillHolder(4683, 1), // Valakas Dragon Breath new SkillHolder(4684, 1), // Valakas Dragon
|
{
|
||||||
* Breath new SkillHolder(4685, 1), // Valakas Tail Stomp new SkillHolder(4686, 1), // Valakas Tail Stomp new SkillHolder(4688, 1), // Valakas Stun new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm };
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
*/
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_LOWHP_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_AOE_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4684, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4685, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4686, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4688, 1), // Valakas Stun
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
// Locations
|
// Locations
|
||||||
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
||||||
{
|
{
|
||||||
@@ -82,7 +115,7 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
||||||
// Misc
|
// Misc
|
||||||
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
||||||
// private Playable _actualVictim; // Actual target of Valakas.
|
private Playable _actualVictim; // Actual target of Valakas.
|
||||||
private static ZoneType ZONE;
|
private static ZoneType ZONE;
|
||||||
|
|
||||||
private Valakas()
|
private Valakas()
|
||||||
@@ -326,10 +359,10 @@ public class Valakas extends AbstractNpcAI
|
|||||||
|
|
||||||
startQuestTimer("remove_players", 900000, null, null);
|
startQuestTimer("remove_players", 900000, null, null);
|
||||||
}
|
}
|
||||||
// else if (event.equalsIgnoreCase("skill_task"))
|
else if (event.equalsIgnoreCase("skill_task"))
|
||||||
// {
|
{
|
||||||
// callSkillAI(npc);
|
callSkillAI(npc);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
else if (event.equalsIgnoreCase("valakas_unlock"))
|
else if (event.equalsIgnoreCase("valakas_unlock"))
|
||||||
{
|
{
|
||||||
@@ -420,17 +453,114 @@ public class Valakas extends AbstractNpcAI
|
|||||||
return super.onKill(npc, killer, isSummon);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* @Override public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon) { return null; } private void callSkillAI(Npc npc) { if (npc.isInvul() || npc.isCastingNow()) { return; } // Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target. if
|
public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon)
|
||||||
* ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0)) { _actualVictim = getRandomTarget(npc); } // If result is still null, Valakas will roam. Don't go deeper in skill AI. if (_actualVictim == null) { if (getRandom(10) == 0)
|
{
|
||||||
* { final int x = npc.getX(); final int y = npc.getY(); final int z = npc.getZ(); final int posX = x + getRandom(-1400, 1400); final int posY = y + getRandom(-1400, 1400); if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceId())) {
|
return null;
|
||||||
* npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0)); } } return; } final Skill skill = getRandomSkill(npc).getSkill(); // Cast the skill or follow the target. if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc,
|
}
|
||||||
* _actualVictim, true)) { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); npc.setIsCastingNow(true); npc.setTarget(_actualVictim); npc.doCast(skill); } else { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null); npc.setIsCastingNow(false); } } private
|
|
||||||
* SkillHolder getRandomSkill(Npc npc) { final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100); // Valakas Lava Skin has priority. if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId())) { return VALAKAS_LAVA_SKIN; } // Valakas
|
private void callSkillAI(Npc npc)
|
||||||
* will use mass spells if he feels surrounded. if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20) { return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)]; } if (hpRatio > 50) { return
|
{
|
||||||
* VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)]; } return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)]; } private Playable getRandomTarget(Npc npc) { final List<Playable> result = new ArrayList<>(); World.getInstance().forEachVisibleObject(npc, Playable.class,
|
if (npc.isInvul() || npc.isCastingNow())
|
||||||
* obj -> { if ((obj == null) || obj.isPet()) { return; } else if (!obj.isDead() && obj.isPlayable()) { result.add(obj); } }); return result.isEmpty() ? null : result.get(getRandom(result.size())); }
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target.
|
||||||
|
if ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0))
|
||||||
|
{
|
||||||
|
_actualVictim = getRandomTarget(npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If result is still null, Valakas will roam. Don't go deeper in skill AI.
|
||||||
|
if (_actualVictim == null)
|
||||||
|
{
|
||||||
|
if (getRandom(10) == 0)
|
||||||
|
{
|
||||||
|
final int x = npc.getX();
|
||||||
|
final int y = npc.getY();
|
||||||
|
final int z = npc.getZ();
|
||||||
|
|
||||||
|
final int posX = x + getRandom(-1400, 1400);
|
||||||
|
final int posY = y + getRandom(-1400, 1400);
|
||||||
|
|
||||||
|
if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Skill skill = getRandomSkill(npc).getSkill();
|
||||||
|
|
||||||
|
// Cast the skill or follow the target.
|
||||||
|
if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc, _actualVictim, true))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||||
|
npc.setTarget(_actualVictim);
|
||||||
|
npc.doCast(skill);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick a random skill.<br>
|
||||||
|
* Valakas will mostly use utility skills. If Valakas feels surrounded, he will use AoE skills.<br>
|
||||||
|
* Lower than 50% HPs, he will begin to use Meteor skill.
|
||||||
|
* @param npc valakas
|
||||||
|
* @return a skill holder
|
||||||
*/
|
*/
|
||||||
|
private SkillHolder getRandomSkill(Npc npc)
|
||||||
|
{
|
||||||
|
final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100);
|
||||||
|
|
||||||
|
// Valakas Lava Skin has priority.
|
||||||
|
if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId()))
|
||||||
|
{
|
||||||
|
return VALAKAS_LAVA_SKIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valakas will use mass spells if he feels surrounded.
|
||||||
|
if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20)
|
||||||
|
{
|
||||||
|
return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hpRatio > 50)
|
||||||
|
{
|
||||||
|
return VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pickup a random Playable from the zone, deads targets aren't included.
|
||||||
|
* @param npc
|
||||||
|
* @return a random Playable.
|
||||||
|
*/
|
||||||
|
private Playable getRandomTarget(Npc npc)
|
||||||
|
{
|
||||||
|
final List<Playable> result = new ArrayList<>();
|
||||||
|
|
||||||
|
World.getInstance().forEachVisibleObject(npc, Playable.class, obj ->
|
||||||
|
{
|
||||||
|
if ((obj == null) || obj.isPet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!obj.isDead() && obj.isPlayable())
|
||||||
|
{
|
||||||
|
result.add(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.isEmpty() ? null : result.get(getRandom(result.size()));
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
@@ -16,23 +16,32 @@
|
|||||||
*/
|
*/
|
||||||
package ai.bosses.Valakas;
|
package ai.bosses.Valakas;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||||
import org.l2jmobius.gameserver.enums.MountType;
|
import org.l2jmobius.gameserver.enums.MountType;
|
||||||
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.model.StatsSet;
|
import org.l2jmobius.gameserver.model.StatsSet;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
import org.l2jmobius.gameserver.model.actor.Attackable;
|
||||||
import org.l2jmobius.gameserver.model.actor.Npc;
|
import org.l2jmobius.gameserver.model.actor.Npc;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||||
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||||
|
import org.l2jmobius.gameserver.util.Util;
|
||||||
|
|
||||||
import ai.AbstractNpcAI;
|
import ai.AbstractNpcAI;
|
||||||
|
|
||||||
@@ -46,12 +55,36 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final int VALAKAS = 29028;
|
private static final int VALAKAS = 29028;
|
||||||
// Skills
|
// Skills
|
||||||
private static final int VALAKAS_REGENERATION = 4691;
|
private static final int VALAKAS_REGENERATION = 4691;
|
||||||
/*
|
private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1);
|
||||||
* private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1); private static final SkillHolder[] VALAKAS_REGULAR_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. }; private static final SkillHolder[] VALAKAS_LOWHP_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
private static final SkillHolder[] VALAKAS_REGULAR_SKILLS =
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm }; private static final SkillHolder[] VALAKAS_AOE_SKILLS = { new SkillHolder(4683, 1), // Valakas Dragon Breath new SkillHolder(4684, 1), // Valakas Dragon
|
{
|
||||||
* Breath new SkillHolder(4685, 1), // Valakas Tail Stomp new SkillHolder(4686, 1), // Valakas Tail Stomp new SkillHolder(4688, 1), // Valakas Stun new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm };
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
*/
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_LOWHP_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_AOE_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4684, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4685, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4686, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4688, 1), // Valakas Stun
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
// Locations
|
// Locations
|
||||||
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
||||||
{
|
{
|
||||||
@@ -82,7 +115,7 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
||||||
// Misc
|
// Misc
|
||||||
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
||||||
// private Playable _actualVictim; // Actual target of Valakas.
|
private Playable _actualVictim; // Actual target of Valakas.
|
||||||
private static ZoneType ZONE;
|
private static ZoneType ZONE;
|
||||||
|
|
||||||
private Valakas()
|
private Valakas()
|
||||||
@@ -326,10 +359,10 @@ public class Valakas extends AbstractNpcAI
|
|||||||
|
|
||||||
startQuestTimer("remove_players", 900000, null, null);
|
startQuestTimer("remove_players", 900000, null, null);
|
||||||
}
|
}
|
||||||
// else if (event.equalsIgnoreCase("skill_task"))
|
else if (event.equalsIgnoreCase("skill_task"))
|
||||||
// {
|
{
|
||||||
// callSkillAI(npc);
|
callSkillAI(npc);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
else if (event.equalsIgnoreCase("valakas_unlock"))
|
else if (event.equalsIgnoreCase("valakas_unlock"))
|
||||||
{
|
{
|
||||||
@@ -420,17 +453,114 @@ public class Valakas extends AbstractNpcAI
|
|||||||
return super.onKill(npc, killer, isSummon);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* @Override public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon) { return null; } private void callSkillAI(Npc npc) { if (npc.isInvul() || npc.isCastingNow()) { return; } // Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target. if
|
public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon)
|
||||||
* ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0)) { _actualVictim = getRandomTarget(npc); } // If result is still null, Valakas will roam. Don't go deeper in skill AI. if (_actualVictim == null) { if (getRandom(10) == 0)
|
{
|
||||||
* { final int x = npc.getX(); final int y = npc.getY(); final int z = npc.getZ(); final int posX = x + getRandom(-1400, 1400); final int posY = y + getRandom(-1400, 1400); if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceId())) {
|
return null;
|
||||||
* npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0)); } } return; } final Skill skill = getRandomSkill(npc).getSkill(); // Cast the skill or follow the target. if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc,
|
}
|
||||||
* _actualVictim, true)) { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); npc.setIsCastingNow(true); npc.setTarget(_actualVictim); npc.doCast(skill); } else { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null); npc.setIsCastingNow(false); } } private
|
|
||||||
* SkillHolder getRandomSkill(Npc npc) { final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100); // Valakas Lava Skin has priority. if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId())) { return VALAKAS_LAVA_SKIN; } // Valakas
|
private void callSkillAI(Npc npc)
|
||||||
* will use mass spells if he feels surrounded. if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20) { return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)]; } if (hpRatio > 50) { return
|
{
|
||||||
* VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)]; } return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)]; } private Playable getRandomTarget(Npc npc) { final List<Playable> result = new ArrayList<>(); World.getInstance().forEachVisibleObject(npc, Playable.class,
|
if (npc.isInvul() || npc.isCastingNow())
|
||||||
* obj -> { if ((obj == null) || obj.isPet()) { return; } else if (!obj.isDead() && obj.isPlayable()) { result.add(obj); } }); return result.isEmpty() ? null : result.get(getRandom(result.size())); }
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target.
|
||||||
|
if ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0))
|
||||||
|
{
|
||||||
|
_actualVictim = getRandomTarget(npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If result is still null, Valakas will roam. Don't go deeper in skill AI.
|
||||||
|
if (_actualVictim == null)
|
||||||
|
{
|
||||||
|
if (getRandom(10) == 0)
|
||||||
|
{
|
||||||
|
final int x = npc.getX();
|
||||||
|
final int y = npc.getY();
|
||||||
|
final int z = npc.getZ();
|
||||||
|
|
||||||
|
final int posX = x + getRandom(-1400, 1400);
|
||||||
|
final int posY = y + getRandom(-1400, 1400);
|
||||||
|
|
||||||
|
if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Skill skill = getRandomSkill(npc).getSkill();
|
||||||
|
|
||||||
|
// Cast the skill or follow the target.
|
||||||
|
if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc, _actualVictim, true))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||||
|
npc.setTarget(_actualVictim);
|
||||||
|
npc.doCast(skill);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick a random skill.<br>
|
||||||
|
* Valakas will mostly use utility skills. If Valakas feels surrounded, he will use AoE skills.<br>
|
||||||
|
* Lower than 50% HPs, he will begin to use Meteor skill.
|
||||||
|
* @param npc valakas
|
||||||
|
* @return a skill holder
|
||||||
*/
|
*/
|
||||||
|
private SkillHolder getRandomSkill(Npc npc)
|
||||||
|
{
|
||||||
|
final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100);
|
||||||
|
|
||||||
|
// Valakas Lava Skin has priority.
|
||||||
|
if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId()))
|
||||||
|
{
|
||||||
|
return VALAKAS_LAVA_SKIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valakas will use mass spells if he feels surrounded.
|
||||||
|
if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20)
|
||||||
|
{
|
||||||
|
return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hpRatio > 50)
|
||||||
|
{
|
||||||
|
return VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pickup a random Playable from the zone, deads targets aren't included.
|
||||||
|
* @param npc
|
||||||
|
* @return a random Playable.
|
||||||
|
*/
|
||||||
|
private Playable getRandomTarget(Npc npc)
|
||||||
|
{
|
||||||
|
final List<Playable> result = new ArrayList<>();
|
||||||
|
|
||||||
|
World.getInstance().forEachVisibleObject(npc, Playable.class, obj ->
|
||||||
|
{
|
||||||
|
if ((obj == null) || obj.isPet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!obj.isDead() && obj.isPlayable())
|
||||||
|
{
|
||||||
|
result.add(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.isEmpty() ? null : result.get(getRandom(result.size()));
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
@@ -16,23 +16,32 @@
|
|||||||
*/
|
*/
|
||||||
package ai.bosses.Valakas;
|
package ai.bosses.Valakas;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||||
import org.l2jmobius.gameserver.enums.MountType;
|
import org.l2jmobius.gameserver.enums.MountType;
|
||||||
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.model.StatsSet;
|
import org.l2jmobius.gameserver.model.StatsSet;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
import org.l2jmobius.gameserver.model.actor.Attackable;
|
||||||
import org.l2jmobius.gameserver.model.actor.Npc;
|
import org.l2jmobius.gameserver.model.actor.Npc;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||||
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||||
|
import org.l2jmobius.gameserver.util.Util;
|
||||||
|
|
||||||
import ai.AbstractNpcAI;
|
import ai.AbstractNpcAI;
|
||||||
|
|
||||||
@@ -46,12 +55,36 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final int VALAKAS = 29028;
|
private static final int VALAKAS = 29028;
|
||||||
// Skills
|
// Skills
|
||||||
private static final int VALAKAS_REGENERATION = 4691;
|
private static final int VALAKAS_REGENERATION = 4691;
|
||||||
/*
|
private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1);
|
||||||
* private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1); private static final SkillHolder[] VALAKAS_REGULAR_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. }; private static final SkillHolder[] VALAKAS_LOWHP_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
private static final SkillHolder[] VALAKAS_REGULAR_SKILLS =
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm }; private static final SkillHolder[] VALAKAS_AOE_SKILLS = { new SkillHolder(4683, 1), // Valakas Dragon Breath new SkillHolder(4684, 1), // Valakas Dragon
|
{
|
||||||
* Breath new SkillHolder(4685, 1), // Valakas Tail Stomp new SkillHolder(4686, 1), // Valakas Tail Stomp new SkillHolder(4688, 1), // Valakas Stun new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm };
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
*/
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_LOWHP_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_AOE_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4684, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4685, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4686, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4688, 1), // Valakas Stun
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
// Locations
|
// Locations
|
||||||
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
||||||
{
|
{
|
||||||
@@ -82,7 +115,7 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
||||||
// Misc
|
// Misc
|
||||||
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
||||||
// private Playable _actualVictim; // Actual target of Valakas.
|
private Playable _actualVictim; // Actual target of Valakas.
|
||||||
private static ZoneType ZONE;
|
private static ZoneType ZONE;
|
||||||
|
|
||||||
private Valakas()
|
private Valakas()
|
||||||
@@ -326,10 +359,10 @@ public class Valakas extends AbstractNpcAI
|
|||||||
|
|
||||||
startQuestTimer("remove_players", 900000, null, null);
|
startQuestTimer("remove_players", 900000, null, null);
|
||||||
}
|
}
|
||||||
// else if (event.equalsIgnoreCase("skill_task"))
|
else if (event.equalsIgnoreCase("skill_task"))
|
||||||
// {
|
{
|
||||||
// callSkillAI(npc);
|
callSkillAI(npc);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
else if (event.equalsIgnoreCase("valakas_unlock"))
|
else if (event.equalsIgnoreCase("valakas_unlock"))
|
||||||
{
|
{
|
||||||
@@ -420,17 +453,114 @@ public class Valakas extends AbstractNpcAI
|
|||||||
return super.onKill(npc, killer, isSummon);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* @Override public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon) { return null; } private void callSkillAI(Npc npc) { if (npc.isInvul() || npc.isCastingNow()) { return; } // Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target. if
|
public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon)
|
||||||
* ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0)) { _actualVictim = getRandomTarget(npc); } // If result is still null, Valakas will roam. Don't go deeper in skill AI. if (_actualVictim == null) { if (getRandom(10) == 0)
|
{
|
||||||
* { final int x = npc.getX(); final int y = npc.getY(); final int z = npc.getZ(); final int posX = x + getRandom(-1400, 1400); final int posY = y + getRandom(-1400, 1400); if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceId())) {
|
return null;
|
||||||
* npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0)); } } return; } final Skill skill = getRandomSkill(npc).getSkill(); // Cast the skill or follow the target. if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc,
|
}
|
||||||
* _actualVictim, true)) { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); npc.setIsCastingNow(true); npc.setTarget(_actualVictim); npc.doCast(skill); } else { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null); npc.setIsCastingNow(false); } } private
|
|
||||||
* SkillHolder getRandomSkill(Npc npc) { final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100); // Valakas Lava Skin has priority. if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId())) { return VALAKAS_LAVA_SKIN; } // Valakas
|
private void callSkillAI(Npc npc)
|
||||||
* will use mass spells if he feels surrounded. if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20) { return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)]; } if (hpRatio > 50) { return
|
{
|
||||||
* VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)]; } return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)]; } private Playable getRandomTarget(Npc npc) { final List<Playable> result = new ArrayList<>(); World.getInstance().forEachVisibleObject(npc, Playable.class,
|
if (npc.isInvul() || npc.isCastingNow())
|
||||||
* obj -> { if ((obj == null) || obj.isPet()) { return; } else if (!obj.isDead() && obj.isPlayable()) { result.add(obj); } }); return result.isEmpty() ? null : result.get(getRandom(result.size())); }
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target.
|
||||||
|
if ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0))
|
||||||
|
{
|
||||||
|
_actualVictim = getRandomTarget(npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If result is still null, Valakas will roam. Don't go deeper in skill AI.
|
||||||
|
if (_actualVictim == null)
|
||||||
|
{
|
||||||
|
if (getRandom(10) == 0)
|
||||||
|
{
|
||||||
|
final int x = npc.getX();
|
||||||
|
final int y = npc.getY();
|
||||||
|
final int z = npc.getZ();
|
||||||
|
|
||||||
|
final int posX = x + getRandom(-1400, 1400);
|
||||||
|
final int posY = y + getRandom(-1400, 1400);
|
||||||
|
|
||||||
|
if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Skill skill = getRandomSkill(npc).getSkill();
|
||||||
|
|
||||||
|
// Cast the skill or follow the target.
|
||||||
|
if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc, _actualVictim, true))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||||
|
npc.setTarget(_actualVictim);
|
||||||
|
npc.doCast(skill);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick a random skill.<br>
|
||||||
|
* Valakas will mostly use utility skills. If Valakas feels surrounded, he will use AoE skills.<br>
|
||||||
|
* Lower than 50% HPs, he will begin to use Meteor skill.
|
||||||
|
* @param npc valakas
|
||||||
|
* @return a skill holder
|
||||||
*/
|
*/
|
||||||
|
private SkillHolder getRandomSkill(Npc npc)
|
||||||
|
{
|
||||||
|
final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100);
|
||||||
|
|
||||||
|
// Valakas Lava Skin has priority.
|
||||||
|
if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId()))
|
||||||
|
{
|
||||||
|
return VALAKAS_LAVA_SKIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valakas will use mass spells if he feels surrounded.
|
||||||
|
if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20)
|
||||||
|
{
|
||||||
|
return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hpRatio > 50)
|
||||||
|
{
|
||||||
|
return VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pickup a random Playable from the zone, deads targets aren't included.
|
||||||
|
* @param npc
|
||||||
|
* @return a random Playable.
|
||||||
|
*/
|
||||||
|
private Playable getRandomTarget(Npc npc)
|
||||||
|
{
|
||||||
|
final List<Playable> result = new ArrayList<>();
|
||||||
|
|
||||||
|
World.getInstance().forEachVisibleObject(npc, Playable.class, obj ->
|
||||||
|
{
|
||||||
|
if ((obj == null) || obj.isPet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!obj.isDead() && obj.isPlayable())
|
||||||
|
{
|
||||||
|
result.add(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.isEmpty() ? null : result.get(getRandom(result.size()));
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
@@ -16,23 +16,32 @@
|
|||||||
*/
|
*/
|
||||||
package ai.bosses.Valakas;
|
package ai.bosses.Valakas;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||||
import org.l2jmobius.gameserver.enums.MountType;
|
import org.l2jmobius.gameserver.enums.MountType;
|
||||||
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.model.StatsSet;
|
import org.l2jmobius.gameserver.model.StatsSet;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
import org.l2jmobius.gameserver.model.actor.Attackable;
|
||||||
import org.l2jmobius.gameserver.model.actor.Npc;
|
import org.l2jmobius.gameserver.model.actor.Npc;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||||
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||||
|
import org.l2jmobius.gameserver.util.Util;
|
||||||
|
|
||||||
import ai.AbstractNpcAI;
|
import ai.AbstractNpcAI;
|
||||||
|
|
||||||
@@ -46,12 +55,36 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final int VALAKAS = 29028;
|
private static final int VALAKAS = 29028;
|
||||||
// Skills
|
// Skills
|
||||||
private static final int VALAKAS_REGENERATION = 4691;
|
private static final int VALAKAS_REGENERATION = 4691;
|
||||||
/*
|
private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1);
|
||||||
* private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1); private static final SkillHolder[] VALAKAS_REGULAR_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. }; private static final SkillHolder[] VALAKAS_LOWHP_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
private static final SkillHolder[] VALAKAS_REGULAR_SKILLS =
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm }; private static final SkillHolder[] VALAKAS_AOE_SKILLS = { new SkillHolder(4683, 1), // Valakas Dragon Breath new SkillHolder(4684, 1), // Valakas Dragon
|
{
|
||||||
* Breath new SkillHolder(4685, 1), // Valakas Tail Stomp new SkillHolder(4686, 1), // Valakas Tail Stomp new SkillHolder(4688, 1), // Valakas Stun new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm };
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
*/
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_LOWHP_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_AOE_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4684, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4685, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4686, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4688, 1), // Valakas Stun
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
// Locations
|
// Locations
|
||||||
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
||||||
{
|
{
|
||||||
@@ -82,7 +115,7 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
||||||
// Misc
|
// Misc
|
||||||
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
||||||
// private Playable _actualVictim; // Actual target of Valakas.
|
private Playable _actualVictim; // Actual target of Valakas.
|
||||||
private static ZoneType ZONE;
|
private static ZoneType ZONE;
|
||||||
|
|
||||||
private Valakas()
|
private Valakas()
|
||||||
@@ -326,10 +359,10 @@ public class Valakas extends AbstractNpcAI
|
|||||||
|
|
||||||
startQuestTimer("remove_players", 900000, null, null);
|
startQuestTimer("remove_players", 900000, null, null);
|
||||||
}
|
}
|
||||||
// else if (event.equalsIgnoreCase("skill_task"))
|
else if (event.equalsIgnoreCase("skill_task"))
|
||||||
// {
|
{
|
||||||
// callSkillAI(npc);
|
callSkillAI(npc);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
else if (event.equalsIgnoreCase("valakas_unlock"))
|
else if (event.equalsIgnoreCase("valakas_unlock"))
|
||||||
{
|
{
|
||||||
@@ -420,17 +453,114 @@ public class Valakas extends AbstractNpcAI
|
|||||||
return super.onKill(npc, killer, isSummon);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* @Override public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon) { return null; } private void callSkillAI(Npc npc) { if (npc.isInvul() || npc.isCastingNow()) { return; } // Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target. if
|
public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon)
|
||||||
* ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0)) { _actualVictim = getRandomTarget(npc); } // If result is still null, Valakas will roam. Don't go deeper in skill AI. if (_actualVictim == null) { if (getRandom(10) == 0)
|
{
|
||||||
* { final int x = npc.getX(); final int y = npc.getY(); final int z = npc.getZ(); final int posX = x + getRandom(-1400, 1400); final int posY = y + getRandom(-1400, 1400); if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceId())) {
|
return null;
|
||||||
* npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0)); } } return; } final Skill skill = getRandomSkill(npc).getSkill(); // Cast the skill or follow the target. if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc,
|
}
|
||||||
* _actualVictim, true)) { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); npc.setIsCastingNow(true); npc.setTarget(_actualVictim); npc.doCast(skill); } else { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null); npc.setIsCastingNow(false); } } private
|
|
||||||
* SkillHolder getRandomSkill(Npc npc) { final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100); // Valakas Lava Skin has priority. if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId())) { return VALAKAS_LAVA_SKIN; } // Valakas
|
private void callSkillAI(Npc npc)
|
||||||
* will use mass spells if he feels surrounded. if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20) { return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)]; } if (hpRatio > 50) { return
|
{
|
||||||
* VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)]; } return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)]; } private Playable getRandomTarget(Npc npc) { final List<Playable> result = new ArrayList<>(); World.getInstance().forEachVisibleObject(npc, Playable.class,
|
if (npc.isInvul() || npc.isCastingNow())
|
||||||
* obj -> { if ((obj == null) || obj.isPet()) { return; } else if (!obj.isDead() && obj.isPlayable()) { result.add(obj); } }); return result.isEmpty() ? null : result.get(getRandom(result.size())); }
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target.
|
||||||
|
if ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0))
|
||||||
|
{
|
||||||
|
_actualVictim = getRandomTarget(npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If result is still null, Valakas will roam. Don't go deeper in skill AI.
|
||||||
|
if (_actualVictim == null)
|
||||||
|
{
|
||||||
|
if (getRandom(10) == 0)
|
||||||
|
{
|
||||||
|
final int x = npc.getX();
|
||||||
|
final int y = npc.getY();
|
||||||
|
final int z = npc.getZ();
|
||||||
|
|
||||||
|
final int posX = x + getRandom(-1400, 1400);
|
||||||
|
final int posY = y + getRandom(-1400, 1400);
|
||||||
|
|
||||||
|
if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Skill skill = getRandomSkill(npc).getSkill();
|
||||||
|
|
||||||
|
// Cast the skill or follow the target.
|
||||||
|
if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc, _actualVictim, true))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||||
|
npc.setTarget(_actualVictim);
|
||||||
|
npc.doCast(skill);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick a random skill.<br>
|
||||||
|
* Valakas will mostly use utility skills. If Valakas feels surrounded, he will use AoE skills.<br>
|
||||||
|
* Lower than 50% HPs, he will begin to use Meteor skill.
|
||||||
|
* @param npc valakas
|
||||||
|
* @return a skill holder
|
||||||
*/
|
*/
|
||||||
|
private SkillHolder getRandomSkill(Npc npc)
|
||||||
|
{
|
||||||
|
final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100);
|
||||||
|
|
||||||
|
// Valakas Lava Skin has priority.
|
||||||
|
if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId()))
|
||||||
|
{
|
||||||
|
return VALAKAS_LAVA_SKIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valakas will use mass spells if he feels surrounded.
|
||||||
|
if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20)
|
||||||
|
{
|
||||||
|
return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hpRatio > 50)
|
||||||
|
{
|
||||||
|
return VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pickup a random Playable from the zone, deads targets aren't included.
|
||||||
|
* @param npc
|
||||||
|
* @return a random Playable.
|
||||||
|
*/
|
||||||
|
private Playable getRandomTarget(Npc npc)
|
||||||
|
{
|
||||||
|
final List<Playable> result = new ArrayList<>();
|
||||||
|
|
||||||
|
World.getInstance().forEachVisibleObject(npc, Playable.class, obj ->
|
||||||
|
{
|
||||||
|
if ((obj == null) || obj.isPet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!obj.isDead() && obj.isPlayable())
|
||||||
|
{
|
||||||
|
result.add(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.isEmpty() ? null : result.get(getRandom(result.size()));
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
@@ -16,23 +16,32 @@
|
|||||||
*/
|
*/
|
||||||
package ai.bosses.Valakas;
|
package ai.bosses.Valakas;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||||
import org.l2jmobius.gameserver.enums.MountType;
|
import org.l2jmobius.gameserver.enums.MountType;
|
||||||
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.model.StatsSet;
|
import org.l2jmobius.gameserver.model.StatsSet;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
import org.l2jmobius.gameserver.model.actor.Attackable;
|
||||||
import org.l2jmobius.gameserver.model.actor.Npc;
|
import org.l2jmobius.gameserver.model.actor.Npc;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||||
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||||
|
import org.l2jmobius.gameserver.util.Util;
|
||||||
|
|
||||||
import ai.AbstractNpcAI;
|
import ai.AbstractNpcAI;
|
||||||
|
|
||||||
@@ -46,12 +55,36 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final int VALAKAS = 29028;
|
private static final int VALAKAS = 29028;
|
||||||
// Skills
|
// Skills
|
||||||
private static final int VALAKAS_REGENERATION = 4691;
|
private static final int VALAKAS_REGENERATION = 4691;
|
||||||
/*
|
private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1);
|
||||||
* private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1); private static final SkillHolder[] VALAKAS_REGULAR_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. }; private static final SkillHolder[] VALAKAS_LOWHP_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
private static final SkillHolder[] VALAKAS_REGULAR_SKILLS =
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm }; private static final SkillHolder[] VALAKAS_AOE_SKILLS = { new SkillHolder(4683, 1), // Valakas Dragon Breath new SkillHolder(4684, 1), // Valakas Dragon
|
{
|
||||||
* Breath new SkillHolder(4685, 1), // Valakas Tail Stomp new SkillHolder(4686, 1), // Valakas Tail Stomp new SkillHolder(4688, 1), // Valakas Stun new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm };
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
*/
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_LOWHP_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_AOE_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4684, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4685, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4686, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4688, 1), // Valakas Stun
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
// Locations
|
// Locations
|
||||||
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
||||||
{
|
{
|
||||||
@@ -82,7 +115,7 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
||||||
// Misc
|
// Misc
|
||||||
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
||||||
// private Playable _actualVictim; // Actual target of Valakas.
|
private Playable _actualVictim; // Actual target of Valakas.
|
||||||
private static ZoneType ZONE;
|
private static ZoneType ZONE;
|
||||||
|
|
||||||
private Valakas()
|
private Valakas()
|
||||||
@@ -326,10 +359,10 @@ public class Valakas extends AbstractNpcAI
|
|||||||
|
|
||||||
startQuestTimer("remove_players", 900000, null, null);
|
startQuestTimer("remove_players", 900000, null, null);
|
||||||
}
|
}
|
||||||
// else if (event.equalsIgnoreCase("skill_task"))
|
else if (event.equalsIgnoreCase("skill_task"))
|
||||||
// {
|
{
|
||||||
// callSkillAI(npc);
|
callSkillAI(npc);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
else if (event.equalsIgnoreCase("valakas_unlock"))
|
else if (event.equalsIgnoreCase("valakas_unlock"))
|
||||||
{
|
{
|
||||||
@@ -420,17 +453,114 @@ public class Valakas extends AbstractNpcAI
|
|||||||
return super.onKill(npc, killer, isSummon);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* @Override public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon) { return null; } private void callSkillAI(Npc npc) { if (npc.isInvul() || npc.isCastingNow()) { return; } // Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target. if
|
public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon)
|
||||||
* ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0)) { _actualVictim = getRandomTarget(npc); } // If result is still null, Valakas will roam. Don't go deeper in skill AI. if (_actualVictim == null) { if (getRandom(10) == 0)
|
{
|
||||||
* { final int x = npc.getX(); final int y = npc.getY(); final int z = npc.getZ(); final int posX = x + getRandom(-1400, 1400); final int posY = y + getRandom(-1400, 1400); if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceId())) {
|
return null;
|
||||||
* npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0)); } } return; } final Skill skill = getRandomSkill(npc).getSkill(); // Cast the skill or follow the target. if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc,
|
}
|
||||||
* _actualVictim, true)) { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); npc.setIsCastingNow(true); npc.setTarget(_actualVictim); npc.doCast(skill); } else { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null); npc.setIsCastingNow(false); } } private
|
|
||||||
* SkillHolder getRandomSkill(Npc npc) { final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100); // Valakas Lava Skin has priority. if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId())) { return VALAKAS_LAVA_SKIN; } // Valakas
|
private void callSkillAI(Npc npc)
|
||||||
* will use mass spells if he feels surrounded. if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20) { return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)]; } if (hpRatio > 50) { return
|
{
|
||||||
* VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)]; } return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)]; } private Playable getRandomTarget(Npc npc) { final List<Playable> result = new ArrayList<>(); World.getInstance().forEachVisibleObject(npc, Playable.class,
|
if (npc.isInvul() || npc.isCastingNow())
|
||||||
* obj -> { if ((obj == null) || obj.isPet()) { return; } else if (!obj.isDead() && obj.isPlayable()) { result.add(obj); } }); return result.isEmpty() ? null : result.get(getRandom(result.size())); }
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target.
|
||||||
|
if ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0))
|
||||||
|
{
|
||||||
|
_actualVictim = getRandomTarget(npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If result is still null, Valakas will roam. Don't go deeper in skill AI.
|
||||||
|
if (_actualVictim == null)
|
||||||
|
{
|
||||||
|
if (getRandom(10) == 0)
|
||||||
|
{
|
||||||
|
final int x = npc.getX();
|
||||||
|
final int y = npc.getY();
|
||||||
|
final int z = npc.getZ();
|
||||||
|
|
||||||
|
final int posX = x + getRandom(-1400, 1400);
|
||||||
|
final int posY = y + getRandom(-1400, 1400);
|
||||||
|
|
||||||
|
if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Skill skill = getRandomSkill(npc).getSkill();
|
||||||
|
|
||||||
|
// Cast the skill or follow the target.
|
||||||
|
if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc, _actualVictim, true))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||||
|
npc.setTarget(_actualVictim);
|
||||||
|
npc.doCast(skill);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick a random skill.<br>
|
||||||
|
* Valakas will mostly use utility skills. If Valakas feels surrounded, he will use AoE skills.<br>
|
||||||
|
* Lower than 50% HPs, he will begin to use Meteor skill.
|
||||||
|
* @param npc valakas
|
||||||
|
* @return a skill holder
|
||||||
*/
|
*/
|
||||||
|
private SkillHolder getRandomSkill(Npc npc)
|
||||||
|
{
|
||||||
|
final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100);
|
||||||
|
|
||||||
|
// Valakas Lava Skin has priority.
|
||||||
|
if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId()))
|
||||||
|
{
|
||||||
|
return VALAKAS_LAVA_SKIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valakas will use mass spells if he feels surrounded.
|
||||||
|
if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20)
|
||||||
|
{
|
||||||
|
return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hpRatio > 50)
|
||||||
|
{
|
||||||
|
return VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pickup a random Playable from the zone, deads targets aren't included.
|
||||||
|
* @param npc
|
||||||
|
* @return a random Playable.
|
||||||
|
*/
|
||||||
|
private Playable getRandomTarget(Npc npc)
|
||||||
|
{
|
||||||
|
final List<Playable> result = new ArrayList<>();
|
||||||
|
|
||||||
|
World.getInstance().forEachVisibleObject(npc, Playable.class, obj ->
|
||||||
|
{
|
||||||
|
if ((obj == null) || obj.isPet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!obj.isDead() && obj.isPlayable())
|
||||||
|
{
|
||||||
|
result.add(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.isEmpty() ? null : result.get(getRandom(result.size()));
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
@@ -16,23 +16,32 @@
|
|||||||
*/
|
*/
|
||||||
package ai.bosses.Valakas;
|
package ai.bosses.Valakas;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.l2jmobius.Config;
|
import org.l2jmobius.Config;
|
||||||
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
import org.l2jmobius.gameserver.ai.CtrlIntention;
|
||||||
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
import org.l2jmobius.gameserver.data.xml.impl.SkillData;
|
||||||
import org.l2jmobius.gameserver.enums.MountType;
|
import org.l2jmobius.gameserver.enums.MountType;
|
||||||
|
import org.l2jmobius.gameserver.geoengine.GeoEngine;
|
||||||
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
import org.l2jmobius.gameserver.instancemanager.GrandBossManager;
|
||||||
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
import org.l2jmobius.gameserver.instancemanager.ZoneManager;
|
||||||
import org.l2jmobius.gameserver.model.Location;
|
import org.l2jmobius.gameserver.model.Location;
|
||||||
import org.l2jmobius.gameserver.model.StatsSet;
|
import org.l2jmobius.gameserver.model.StatsSet;
|
||||||
|
import org.l2jmobius.gameserver.model.World;
|
||||||
import org.l2jmobius.gameserver.model.actor.Attackable;
|
import org.l2jmobius.gameserver.model.actor.Attackable;
|
||||||
import org.l2jmobius.gameserver.model.actor.Npc;
|
import org.l2jmobius.gameserver.model.actor.Npc;
|
||||||
|
import org.l2jmobius.gameserver.model.actor.Playable;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.GrandBossInstance;
|
||||||
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
|
||||||
|
import org.l2jmobius.gameserver.model.holders.SkillHolder;
|
||||||
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
import org.l2jmobius.gameserver.model.skills.BuffInfo;
|
||||||
|
import org.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
import org.l2jmobius.gameserver.model.zone.ZoneType;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
import org.l2jmobius.gameserver.network.serverpackets.PlaySound;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
import org.l2jmobius.gameserver.network.serverpackets.SocialAction;
|
||||||
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
import org.l2jmobius.gameserver.network.serverpackets.SpecialCamera;
|
||||||
|
import org.l2jmobius.gameserver.util.Util;
|
||||||
|
|
||||||
import ai.AbstractNpcAI;
|
import ai.AbstractNpcAI;
|
||||||
|
|
||||||
@@ -46,12 +55,36 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final int VALAKAS = 29028;
|
private static final int VALAKAS = 29028;
|
||||||
// Skills
|
// Skills
|
||||||
private static final int VALAKAS_REGENERATION = 4691;
|
private static final int VALAKAS_REGENERATION = 4691;
|
||||||
/*
|
private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1);
|
||||||
* private static final SkillHolder VALAKAS_LAVA_SKIN = new SkillHolder(4680, 1); private static final SkillHolder[] VALAKAS_REGULAR_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. }; private static final SkillHolder[] VALAKAS_LOWHP_SKILLS = { new SkillHolder(4681, 1), // Valakas Trample new SkillHolder(4682, 1), // Valakas Trample new SkillHolder(4683, 1), // Valakas Dragon Breath new
|
private static final SkillHolder[] VALAKAS_REGULAR_SKILLS =
|
||||||
* SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm }; private static final SkillHolder[] VALAKAS_AOE_SKILLS = { new SkillHolder(4683, 1), // Valakas Dragon Breath new SkillHolder(4684, 1), // Valakas Dragon
|
{
|
||||||
* Breath new SkillHolder(4685, 1), // Valakas Tail Stomp new SkillHolder(4686, 1), // Valakas Tail Stomp new SkillHolder(4688, 1), // Valakas Stun new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used. new SkillHolder(4690, 1), // Valakas Meteor Storm };
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
*/
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_LOWHP_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4681, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4682, 1), // Valakas Trample
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final SkillHolder[] VALAKAS_AOE_SKILLS =
|
||||||
|
{
|
||||||
|
new SkillHolder(4683, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4684, 1), // Valakas Dragon Breath
|
||||||
|
new SkillHolder(4685, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4686, 1), // Valakas Tail Stomp
|
||||||
|
new SkillHolder(4688, 1), // Valakas Stun
|
||||||
|
new SkillHolder(4689, 1), // Valakas Fear TODO: has two levels only level one is used.
|
||||||
|
new SkillHolder(4690, 1), // Valakas Meteor Storm
|
||||||
|
};
|
||||||
|
|
||||||
// Locations
|
// Locations
|
||||||
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
private static final Location TELEPORT_CUBE_LOCATIONS[] =
|
||||||
{
|
{
|
||||||
@@ -82,7 +115,7 @@ public class Valakas extends AbstractNpcAI
|
|||||||
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
private static final byte DEAD = 3; // Valakas has been killed. Entry is locked.
|
||||||
// Misc
|
// Misc
|
||||||
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
private long _timeTracker = 0; // Time tracker for last attack on Valakas.
|
||||||
// private Playable _actualVictim; // Actual target of Valakas.
|
private Playable _actualVictim; // Actual target of Valakas.
|
||||||
private static ZoneType ZONE;
|
private static ZoneType ZONE;
|
||||||
|
|
||||||
private Valakas()
|
private Valakas()
|
||||||
@@ -326,10 +359,10 @@ public class Valakas extends AbstractNpcAI
|
|||||||
|
|
||||||
startQuestTimer("remove_players", 900000, null, null);
|
startQuestTimer("remove_players", 900000, null, null);
|
||||||
}
|
}
|
||||||
// else if (event.equalsIgnoreCase("skill_task"))
|
else if (event.equalsIgnoreCase("skill_task"))
|
||||||
// {
|
{
|
||||||
// callSkillAI(npc);
|
callSkillAI(npc);
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
else if (event.equalsIgnoreCase("valakas_unlock"))
|
else if (event.equalsIgnoreCase("valakas_unlock"))
|
||||||
{
|
{
|
||||||
@@ -420,17 +453,114 @@ public class Valakas extends AbstractNpcAI
|
|||||||
return super.onKill(npc, killer, isSummon);
|
return super.onKill(npc, killer, isSummon);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Override
|
||||||
* @Override public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon) { return null; } private void callSkillAI(Npc npc) { if (npc.isInvul() || npc.isCastingNow()) { return; } // Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target. if
|
public String onAggroRangeEnter(Npc npc, PlayerInstance player, boolean isSummon)
|
||||||
* ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0)) { _actualVictim = getRandomTarget(npc); } // If result is still null, Valakas will roam. Don't go deeper in skill AI. if (_actualVictim == null) { if (getRandom(10) == 0)
|
{
|
||||||
* { final int x = npc.getX(); final int y = npc.getY(); final int z = npc.getZ(); final int posX = x + getRandom(-1400, 1400); final int posY = y + getRandom(-1400, 1400); if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceId())) {
|
return null;
|
||||||
* npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0)); } } return; } final Skill skill = getRandomSkill(npc).getSkill(); // Cast the skill or follow the target. if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc,
|
}
|
||||||
* _actualVictim, true)) { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE); npc.setIsCastingNow(true); npc.setTarget(_actualVictim); npc.doCast(skill); } else { npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null); npc.setIsCastingNow(false); } } private
|
|
||||||
* SkillHolder getRandomSkill(Npc npc) { final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100); // Valakas Lava Skin has priority. if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId())) { return VALAKAS_LAVA_SKIN; } // Valakas
|
private void callSkillAI(Npc npc)
|
||||||
* will use mass spells if he feels surrounded. if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20) { return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)]; } if (hpRatio > 50) { return
|
{
|
||||||
* VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)]; } return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)]; } private Playable getRandomTarget(Npc npc) { final List<Playable> result = new ArrayList<>(); World.getInstance().forEachVisibleObject(npc, Playable.class,
|
if (npc.isInvul() || npc.isCastingNow())
|
||||||
* obj -> { if ((obj == null) || obj.isPet()) { return; } else if (!obj.isDead() && obj.isPlayable()) { result.add(obj); } }); return result.isEmpty() ? null : result.get(getRandom(result.size())); }
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pickup a target if no or dead victim. 10% luck he decides to reconsiders his target.
|
||||||
|
if ((_actualVictim == null) || _actualVictim.isDead() || !(npc.isInSurroundingRegion(_actualVictim)) || (getRandom(10) == 0))
|
||||||
|
{
|
||||||
|
_actualVictim = getRandomTarget(npc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If result is still null, Valakas will roam. Don't go deeper in skill AI.
|
||||||
|
if (_actualVictim == null)
|
||||||
|
{
|
||||||
|
if (getRandom(10) == 0)
|
||||||
|
{
|
||||||
|
final int x = npc.getX();
|
||||||
|
final int y = npc.getY();
|
||||||
|
final int z = npc.getZ();
|
||||||
|
|
||||||
|
final int posX = x + getRandom(-1400, 1400);
|
||||||
|
final int posY = y + getRandom(-1400, 1400);
|
||||||
|
|
||||||
|
if (GeoEngine.getInstance().canMoveToTarget(x, y, z, posX, posY, z, npc.getInstanceWorld()))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, new Location(posX, posY, z, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Skill skill = getRandomSkill(npc).getSkill();
|
||||||
|
|
||||||
|
// Cast the skill or follow the target.
|
||||||
|
if (Util.checkIfInRange((skill.getCastRange() < 600) ? 600 : skill.getCastRange(), npc, _actualVictim, true))
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
|
||||||
|
npc.setTarget(_actualVictim);
|
||||||
|
npc.doCast(skill);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
npc.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, _actualVictim, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pick a random skill.<br>
|
||||||
|
* Valakas will mostly use utility skills. If Valakas feels surrounded, he will use AoE skills.<br>
|
||||||
|
* Lower than 50% HPs, he will begin to use Meteor skill.
|
||||||
|
* @param npc valakas
|
||||||
|
* @return a skill holder
|
||||||
*/
|
*/
|
||||||
|
private SkillHolder getRandomSkill(Npc npc)
|
||||||
|
{
|
||||||
|
final int hpRatio = (int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100);
|
||||||
|
|
||||||
|
// Valakas Lava Skin has priority.
|
||||||
|
if ((hpRatio < 75) && (getRandom(150) == 0) && !npc.isAffectedBySkill(VALAKAS_LAVA_SKIN.getSkillId()))
|
||||||
|
{
|
||||||
|
return VALAKAS_LAVA_SKIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valakas will use mass spells if he feels surrounded.
|
||||||
|
if (World.getInstance().getVisibleObjectsInRange(npc, PlayerInstance.class, 1200).size() >= 20)
|
||||||
|
{
|
||||||
|
return VALAKAS_AOE_SKILLS[getRandom(VALAKAS_AOE_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hpRatio > 50)
|
||||||
|
{
|
||||||
|
return VALAKAS_REGULAR_SKILLS[getRandom(VALAKAS_REGULAR_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return VALAKAS_LOWHP_SKILLS[getRandom(VALAKAS_LOWHP_SKILLS.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pickup a random Playable from the zone, deads targets aren't included.
|
||||||
|
* @param npc
|
||||||
|
* @return a random Playable.
|
||||||
|
*/
|
||||||
|
private Playable getRandomTarget(Npc npc)
|
||||||
|
{
|
||||||
|
final List<Playable> result = new ArrayList<>();
|
||||||
|
|
||||||
|
World.getInstance().forEachVisibleObject(npc, Playable.class, obj ->
|
||||||
|
{
|
||||||
|
if ((obj == null) || obj.isPet())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!obj.isDead() && obj.isPlayable())
|
||||||
|
{
|
||||||
|
result.add(obj);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.isEmpty() ? null : result.get(getRandom(result.size()));
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args)
|
public static void main(String[] args)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user