Sync with L2jServer HighFive Oct 2nd 2015.
This commit is contained in:
5
trunk/dist/game/config/NPC.ini
vendored
5
trunk/dist/game/config/NPC.ini
vendored
@@ -182,8 +182,9 @@ GrandChaosTime = 10
|
|||||||
MinionChaosTime = 10
|
MinionChaosTime = 10
|
||||||
|
|
||||||
# It removes STR,CON... bonuses.
|
# It removes STR,CON... bonuses.
|
||||||
# With this npcs will use the stats given directly from the xml.
|
# With this enabled npcs will use the stats given directly from the xml.
|
||||||
IgnoreNpcStatFormulas = True
|
# Default: False
|
||||||
|
IgnoreNpcStatFormulas = False
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
@@ -224,10 +224,8 @@ public class GeoData
|
|||||||
{
|
{
|
||||||
if (target.isDoor())
|
if (target.isDoor())
|
||||||
{
|
{
|
||||||
// can always see doors :o
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return canSeeTarget(cha.getX(), cha.getY(), cha.getZ(), cha.getInstanceId(), target.getX(), target.getY(), target.getZ(), target.getInstanceId());
|
return canSeeTarget(cha.getX(), cha.getY(), cha.getZ(), cha.getInstanceId(), target.getX(), target.getY(), target.getZ(), target.getInstanceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,7 +33,6 @@ import com.l2jserver.gameserver.GameTimeController;
|
|||||||
import com.l2jserver.gameserver.GeoData;
|
import com.l2jserver.gameserver.GeoData;
|
||||||
import com.l2jserver.gameserver.ThreadPoolManager;
|
import com.l2jserver.gameserver.ThreadPoolManager;
|
||||||
import com.l2jserver.gameserver.data.sql.impl.TerritoryTable;
|
import com.l2jserver.gameserver.data.sql.impl.TerritoryTable;
|
||||||
import com.l2jserver.gameserver.data.xml.impl.NpcData;
|
|
||||||
import com.l2jserver.gameserver.enums.AISkillScope;
|
import com.l2jserver.gameserver.enums.AISkillScope;
|
||||||
import com.l2jserver.gameserver.enums.AIType;
|
import com.l2jserver.gameserver.enums.AIType;
|
||||||
import com.l2jserver.gameserver.model.L2Object;
|
import com.l2jserver.gameserver.model.L2Object;
|
||||||
@@ -51,7 +50,6 @@ import com.l2jserver.gameserver.model.actor.instance.L2MonsterInstance;
|
|||||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||||
import com.l2jserver.gameserver.model.actor.instance.L2RaidBossInstance;
|
import com.l2jserver.gameserver.model.actor.instance.L2RaidBossInstance;
|
||||||
import com.l2jserver.gameserver.model.actor.instance.L2StaticObjectInstance;
|
import com.l2jserver.gameserver.model.actor.instance.L2StaticObjectInstance;
|
||||||
import com.l2jserver.gameserver.model.actor.templates.L2NpcTemplate;
|
|
||||||
import com.l2jserver.gameserver.model.effects.L2EffectType;
|
import com.l2jserver.gameserver.model.effects.L2EffectType;
|
||||||
import com.l2jserver.gameserver.model.events.EventDispatcher;
|
import com.l2jserver.gameserver.model.events.EventDispatcher;
|
||||||
import com.l2jserver.gameserver.model.events.impl.character.npc.attackable.OnAttackableFactionCall;
|
import com.l2jserver.gameserver.model.events.impl.character.npc.attackable.OnAttackableFactionCall;
|
||||||
@@ -66,6 +64,7 @@ import com.l2jserver.util.Rnd;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This class manages AI of L2Attackable.
|
* This class manages AI of L2Attackable.
|
||||||
|
* @author Zoey76
|
||||||
*/
|
*/
|
||||||
public class L2AttackableAI extends L2CharacterAI implements Runnable
|
public class L2AttackableAI extends L2CharacterAI implements Runnable
|
||||||
{
|
{
|
||||||
@@ -111,7 +110,6 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
|
|
||||||
private int _timePass = 0;
|
private int _timePass = 0;
|
||||||
private int _chaosTime = 0;
|
private int _chaosTime = 0;
|
||||||
private final L2NpcTemplate _skillrender;
|
|
||||||
private int _lastBuffTick;
|
private int _lastBuffTick;
|
||||||
// Fear parameters
|
// Fear parameters
|
||||||
private int _fearTime;
|
private int _fearTime;
|
||||||
@@ -124,7 +122,6 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
public L2AttackableAI(L2Attackable creature)
|
public L2AttackableAI(L2Attackable creature)
|
||||||
{
|
{
|
||||||
super(creature);
|
super(creature);
|
||||||
_skillrender = NpcData.getInstance().getTemplate(getActiveChar().getTemplate().getId());
|
|
||||||
_attackTimeout = Integer.MAX_VALUE;
|
_attackTimeout = Integer.MAX_VALUE;
|
||||||
_globalAggro = -10; // 10 seconds timeout of ATTACK after respawn
|
_globalAggro = -10; // 10 seconds timeout of ATTACK after respawn
|
||||||
}
|
}
|
||||||
@@ -370,11 +367,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
super.changeIntention(AI_INTENTION_IDLE, null, null);
|
super.changeIntention(AI_INTENTION_IDLE, null, null);
|
||||||
|
|
||||||
// Stop AI task and detach AI from NPC
|
// Stop AI task and detach AI from NPC
|
||||||
if (_aiTask != null)
|
stopAITask();
|
||||||
{
|
|
||||||
_aiTask.cancel(true);
|
|
||||||
_aiTask = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cancel the AI
|
// Cancel the AI
|
||||||
_actor.detachAI();
|
_actor.detachAI();
|
||||||
@@ -403,13 +396,20 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
// self and buffs
|
// self and buffs
|
||||||
if ((_lastBuffTick + 30) < GameTimeController.getInstance().getGameTicks())
|
if ((_lastBuffTick + 30) < GameTimeController.getInstance().getGameTicks())
|
||||||
{
|
{
|
||||||
for (Skill sk : _skillrender.getAISkills(AISkillScope.BUFF))
|
for (Skill buff : getActiveChar().getTemplate().getAISkills(AISkillScope.BUFF))
|
||||||
{
|
{
|
||||||
if (cast(sk))
|
if (checkSkillCastConditions(getActiveChar(), buff))
|
||||||
{
|
{
|
||||||
|
if (!_actor.isAffectedBySkill(buff.getId()))
|
||||||
|
{
|
||||||
|
_actor.setTarget(_actor);
|
||||||
|
_actor.doCast(buff);
|
||||||
|
_actor.setTarget(target);
|
||||||
|
_log.info(this.getActor().getName() + "used buff skill " + buff.getName() + " on " + _actor.getName());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_lastBuffTick = GameTimeController.getInstance().getGameTicks();
|
_lastBuffTick = GameTimeController.getInstance().getGameTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,7 +634,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
else if (Rnd.nextInt(RANDOM_WALK_RATE) == 0)
|
else if (Rnd.nextInt(RANDOM_WALK_RATE) == 0)
|
||||||
{
|
{
|
||||||
for (Skill sk : _skillrender.getAISkills(AISkillScope.BUFF))
|
for (Skill sk : npc.getTemplate().getAISkills(AISkillScope.BUFF))
|
||||||
{
|
{
|
||||||
if (cast(sk))
|
if (cast(sk))
|
||||||
{
|
{
|
||||||
@@ -651,7 +651,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
int z1 = 0;
|
int z1 = 0;
|
||||||
final int range = Config.MAX_DRIFT_RANGE;
|
final int range = Config.MAX_DRIFT_RANGE;
|
||||||
|
|
||||||
for (Skill sk : _skillrender.getAISkills(AISkillScope.BUFF))
|
for (Skill sk : npc.getTemplate().getAISkills(AISkillScope.BUFF))
|
||||||
{
|
{
|
||||||
if (cast(sk))
|
if (cast(sk))
|
||||||
{
|
{
|
||||||
@@ -659,7 +659,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If NPC with random coord in territory - old method (for backward compartibility)
|
// If NPC with random coord in territory - old method (for backward compatibility)
|
||||||
if ((npc.getSpawn().getX() == 0) && (npc.getSpawn().getY() == 0) && (npc.getSpawn().getSpawnTerritory() == null))
|
if ((npc.getSpawn().getX() == 0) && (npc.getSpawn().getY() == 0) && (npc.getSpawn().getSpawnTerritory() == null))
|
||||||
{
|
{
|
||||||
// Calculate a destination point in the spawn area
|
// Calculate a destination point in the spawn area
|
||||||
@@ -708,8 +708,6 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
z1 = npc.getZ();
|
z1 = npc.getZ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// _log.debug("Current pos ("+getX()+", "+getY()+"), moving to ("+x1+", "+y1+").");
|
|
||||||
// Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
|
// Move the actor to Location (x,y,z) server side AND client side by sending Server->Client packet CharMoveToLocation (broadcast)
|
||||||
final Location moveLoc = GeoData.getInstance().moveCheck(npc.getX(), npc.getY(), npc.getZ(), x1, y1, z1, npc.getInstanceId());
|
final Location moveLoc = GeoData.getInstance().moveCheck(npc.getX(), npc.getY(), npc.getZ(), x1, y1, z1, npc.getInstanceId());
|
||||||
|
|
||||||
@@ -725,9 +723,8 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
* <li>Call all L2Object of its Faction inside the Faction Range</li>
|
* <li>Call all L2Object of its Faction inside the Faction Range</li>
|
||||||
* <li>Chose a target and order to attack it with magic skill or physical attack</li>
|
* <li>Chose a target and order to attack it with magic skill or physical attack</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* TODO: Manage casting rules to healer mobs (like Ant Nurses)
|
|
||||||
*/
|
*/
|
||||||
protected void thinkAttack()
|
protected synchronized void thinkAttack()
|
||||||
{
|
{
|
||||||
final L2Attackable npc = getActiveChar();
|
final L2Attackable npc = getActiveChar();
|
||||||
if (npc.isCastingNow())
|
if (npc.isCastingNow())
|
||||||
@@ -774,13 +771,11 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
Set<Integer> clans = getActiveChar().getTemplate().getClans();
|
Set<Integer> clans = getActiveChar().getTemplate().getClans();
|
||||||
if ((clans != null) && !clans.isEmpty())
|
if ((clans != null) && !clans.isEmpty())
|
||||||
{
|
{
|
||||||
int factionRange = npc.getTemplate().getClanHelpRange() + collision;
|
final int factionRange = npc.getTemplate().getClanHelpRange() + collision;
|
||||||
// Go through all L2Object that belong to its faction
|
// Go through all L2Object that belong to its faction
|
||||||
Collection<L2Object> objs = npc.getKnownList().getKnownObjects().values();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (L2Object obj : objs)
|
for (L2Object obj : npc.getKnownList().getKnownCharactersInRadius(factionRange))
|
||||||
{
|
{
|
||||||
if (obj instanceof L2Npc)
|
if (obj instanceof L2Npc)
|
||||||
{
|
{
|
||||||
@@ -792,7 +787,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if the L2Object is inside the Faction Range of the actor
|
// Check if the L2Object is inside the Faction Range of the actor
|
||||||
if (npc.isInsideRadius(called, factionRange, true, false) && called.hasAI())
|
if (called.hasAI())
|
||||||
{
|
{
|
||||||
if ((Math.abs(originalAttackTarget.getZ() - called.getZ()) < 600) && npc.getAttackByList().contains(originalAttackTarget) && ((called.getAI()._intention == CtrlIntention.AI_INTENTION_IDLE) || (called.getAI()._intention == CtrlIntention.AI_INTENTION_ACTIVE)) && (called.getInstanceId() == npc.getInstanceId()))
|
if ((Math.abs(originalAttackTarget.getZ() - called.getZ()) < 600) && npc.getAttackByList().contains(originalAttackTarget) && ((called.getAI()._intention == CtrlIntention.AI_INTENTION_IDLE) || (called.getAI()._intention == CtrlIntention.AI_INTENTION_ACTIVE)) && (called.getInstanceId() == npc.getInstanceId()))
|
||||||
{
|
{
|
||||||
@@ -815,7 +810,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
catch (NullPointerException e)
|
catch (NullPointerException e)
|
||||||
{
|
{
|
||||||
_log.warning(getClass().getSimpleName() + ": thinkAttack() faction call failed: " + e.getMessage());
|
_log.warning(getClass().getSimpleName() + ": There has been a problem trying to think the attack!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -837,30 +832,22 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
|
|
||||||
final int combinedCollision = collision + mostHate.getTemplate().getCollisionRadius();
|
final int combinedCollision = collision + mostHate.getTemplate().getCollisionRadius();
|
||||||
|
|
||||||
List<Skill> aiSuicideSkills = _skillrender.getAISkills(AISkillScope.SUICIDE);
|
final List<Skill> aiSuicideSkills = npc.getTemplate().getAISkills(AISkillScope.SUICIDE);
|
||||||
if (!aiSuicideSkills.isEmpty() && ((int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100) < 30))
|
if (!aiSuicideSkills.isEmpty() && ((int) ((npc.getCurrentHp() / npc.getMaxHp()) * 100) < 30))
|
||||||
{
|
{
|
||||||
final Skill skill = aiSuicideSkills.get(Rnd.nextInt(aiSuicideSkills.size()));
|
final Skill skill = aiSuicideSkills.get(Rnd.get(aiSuicideSkills.size()));
|
||||||
if (Util.checkIfInRange(skill.getAffectRange(), getActiveChar(), mostHate, false) && (Rnd.get(100) < Rnd.get(npc.getMinSkillChance(), npc.getMaxSkillChance())))
|
if (Util.checkIfInRange(skill.getAffectRange(), getActiveChar(), mostHate, false) && npc.hasSkillChance())
|
||||||
{
|
{
|
||||||
if (cast(skill))
|
if (cast(skill))
|
||||||
{
|
{
|
||||||
|
_log.info(this.getActor().getName() + " used suicide skill " + skill.getName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Skill sk : aiSuicideSkills)
|
|
||||||
{
|
|
||||||
if (cast(sk))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------
|
// ------------------------------------------------------
|
||||||
// In case many mobs are trying to hit from same place, move a bit,
|
// In case many mobs are trying to hit from same place, move a bit, circling around the target
|
||||||
// circling around the target
|
|
||||||
// Note from Gnacik:
|
// Note from Gnacik:
|
||||||
// On l2js because of that sometimes mobs don't attack player only running
|
// On l2js because of that sometimes mobs don't attack player only running
|
||||||
// around player without any sense, so decrease chance for now
|
// around player without any sense, so decrease chance for now
|
||||||
@@ -1000,11 +987,12 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_skillrender.getAISkills(AISkillScope.GENERAL).isEmpty())
|
final List<Skill> generalSkills = npc.getTemplate().getAISkills(AISkillScope.GENERAL);
|
||||||
|
if (!generalSkills.isEmpty())
|
||||||
{
|
{
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
// Heal Condition
|
// Heal Condition
|
||||||
List<Skill> aiHealSkills = _skillrender.getAISkills(AISkillScope.HEAL);
|
final List<Skill> aiHealSkills = npc.getTemplate().getAISkills(AISkillScope.HEAL);
|
||||||
if (!aiHealSkills.isEmpty())
|
if (!aiHealSkills.isEmpty())
|
||||||
{
|
{
|
||||||
double percentage = (npc.getCurrentHp() / npc.getMaxHp()) * 100;
|
double percentage = (npc.getCurrentHp() / npc.getMaxHp()) * 100;
|
||||||
@@ -1013,52 +1001,64 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
L2Character leader = npc.getLeader();
|
L2Character leader = npc.getLeader();
|
||||||
if ((leader != null) && !leader.isDead() && (Rnd.get(100) > ((leader.getCurrentHp() / leader.getMaxHp()) * 100)))
|
if ((leader != null) && !leader.isDead() && (Rnd.get(100) > ((leader.getCurrentHp() / leader.getMaxHp()) * 100)))
|
||||||
{
|
{
|
||||||
for (Skill sk : aiHealSkills)
|
for (Skill healSkill : aiHealSkills)
|
||||||
{
|
{
|
||||||
if (sk.getTargetType() == L2TargetType.SELF)
|
if (healSkill.getTargetType() == L2TargetType.SELF)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!checkSkillCastConditions(sk))
|
|
||||||
|
if (!checkSkillCastConditions(npc, healSkill))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!Util.checkIfInRange((sk.getCastRange() + collision + leader.getTemplate().getCollisionRadius()), npc, leader, false) && !isParty(sk) && !npc.isMovementDisabled())
|
|
||||||
|
if (!Util.checkIfInRange((healSkill.getCastRange() + collision + leader.getTemplate().getCollisionRadius()), npc, leader, false) && !isParty(healSkill) && !npc.isMovementDisabled())
|
||||||
{
|
{
|
||||||
moveToPawn(leader, sk.getCastRange() + collision + leader.getTemplate().getCollisionRadius());
|
moveToPawn(leader, healSkill.getCastRange() + collision + leader.getTemplate().getCollisionRadius());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GeoData.getInstance().canSeeTarget(npc, leader))
|
if (GeoData.getInstance().canSeeTarget(npc, leader))
|
||||||
{
|
{
|
||||||
clientStopMoving(null);
|
clientStopMoving(null);
|
||||||
|
final L2Object target = npc.getTarget();
|
||||||
npc.setTarget(leader);
|
npc.setTarget(leader);
|
||||||
clientStopMoving(null);
|
npc.doCast(healSkill);
|
||||||
npc.doCast(sk);
|
npc.setTarget(target);
|
||||||
|
_log.info(this.getActor().getName() + " used heal skill " + healSkill.getName() + " on leader " + leader.getName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Rnd.get(100) < ((100 - percentage) / 3))
|
if (Rnd.get(100) < ((100 - percentage) / 3))
|
||||||
{
|
{
|
||||||
for (Skill sk : aiHealSkills)
|
for (Skill sk : aiHealSkills)
|
||||||
{
|
{
|
||||||
if (!checkSkillCastConditions(sk))
|
if (!checkSkillCastConditions(npc, sk))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
clientStopMoving(null);
|
clientStopMoving(null);
|
||||||
|
final L2Object target = npc.getTarget();
|
||||||
npc.setTarget(npc);
|
npc.setTarget(npc);
|
||||||
npc.doCast(sk);
|
npc.doCast(sk);
|
||||||
|
npc.setTarget(target);
|
||||||
|
_log.info(this.getActor().getName() + " used heal skill " + sk.getName() + " on itself");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Skill sk : aiHealSkills)
|
for (Skill sk : aiHealSkills)
|
||||||
{
|
{
|
||||||
if (!checkSkillCastConditions(sk))
|
if (!checkSkillCastConditions(npc, sk))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sk.getTargetType() == L2TargetType.ONE)
|
if (sk.getTargetType() == L2TargetType.ONE)
|
||||||
{
|
{
|
||||||
for (L2Character obj : npc.getKnownList().getKnownCharactersInRadius(sk.getCastRange() + collision))
|
for (L2Character obj : npc.getKnownList().getKnownCharactersInRadius(sk.getCastRange() + collision))
|
||||||
@@ -1068,24 +1068,29 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
L2Attackable targets = ((L2Attackable) obj);
|
final L2Attackable targets = (L2Attackable) obj;
|
||||||
if (!((L2Attackable) obj).isInMyClan(npc))
|
if (!targets.isInMyClan(npc))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
percentage = (targets.getCurrentHp() / targets.getMaxHp()) * 100;
|
percentage = (targets.getCurrentHp() / targets.getMaxHp()) * 100;
|
||||||
if (Rnd.get(100) < ((100 - percentage) / 10))
|
if (Rnd.get(100) < ((100 - percentage) / 10))
|
||||||
{
|
{
|
||||||
if (GeoData.getInstance().canSeeTarget(npc, targets))
|
if (GeoData.getInstance().canSeeTarget(npc, targets))
|
||||||
{
|
{
|
||||||
clientStopMoving(null);
|
clientStopMoving(null);
|
||||||
|
final L2Object target = npc.getTarget();
|
||||||
npc.setTarget(obj);
|
npc.setTarget(obj);
|
||||||
npc.doCast(sk);
|
npc.doCast(sk);
|
||||||
|
npc.setTarget(target);
|
||||||
|
_log.info(this.getActor().getName() + " used heal skill " + sk.getName() + " on " + obj.getName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isParty(sk))
|
if (isParty(sk))
|
||||||
{
|
{
|
||||||
clientStopMoving(null);
|
clientStopMoving(null);
|
||||||
@@ -1094,9 +1099,10 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------
|
||||||
// Res Skill Condition
|
// Res Skill Condition
|
||||||
List<Skill> aiResSkills = _skillrender.getAISkills(AISkillScope.RES);
|
final List<Skill> aiResSkills = npc.getTemplate().getAISkills(AISkillScope.RES);
|
||||||
if (!aiResSkills.isEmpty())
|
if (!aiResSkills.isEmpty())
|
||||||
{
|
{
|
||||||
if (npc.isMinion())
|
if (npc.isMinion())
|
||||||
@@ -1110,28 +1116,35 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!checkSkillCastConditions(sk))
|
|
||||||
|
if (!checkSkillCastConditions(npc, sk))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Util.checkIfInRange((sk.getCastRange() + collision + leader.getTemplate().getCollisionRadius()), npc, leader, false) && !isParty(sk) && !npc.isMovementDisabled())
|
if (!Util.checkIfInRange((sk.getCastRange() + collision + leader.getTemplate().getCollisionRadius()), npc, leader, false) && !isParty(sk) && !npc.isMovementDisabled())
|
||||||
{
|
{
|
||||||
moveToPawn(leader, sk.getCastRange() + collision + leader.getTemplate().getCollisionRadius());
|
moveToPawn(leader, sk.getCastRange() + collision + leader.getTemplate().getCollisionRadius());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GeoData.getInstance().canSeeTarget(npc, leader))
|
if (GeoData.getInstance().canSeeTarget(npc, leader))
|
||||||
{
|
{
|
||||||
clientStopMoving(null);
|
clientStopMoving(null);
|
||||||
|
final L2Object target = npc.getTarget();
|
||||||
npc.setTarget(leader);
|
npc.setTarget(leader);
|
||||||
npc.doCast(sk);
|
npc.doCast(sk);
|
||||||
|
npc.setTarget(target);
|
||||||
|
_log.info(this.getActor().getName() + " used resurrection skill " + sk.getName() + " on leader " + leader.getName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Skill sk : aiResSkills)
|
for (Skill sk : aiResSkills)
|
||||||
{
|
{
|
||||||
if (!checkSkillCastConditions(sk))
|
if (!checkSkillCastConditions(npc, sk))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1154,20 +1167,25 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
if (GeoData.getInstance().canSeeTarget(npc, targets))
|
if (GeoData.getInstance().canSeeTarget(npc, targets))
|
||||||
{
|
{
|
||||||
clientStopMoving(null);
|
clientStopMoving(null);
|
||||||
|
final L2Object target = npc.getTarget();
|
||||||
npc.setTarget(obj);
|
npc.setTarget(obj);
|
||||||
npc.doCast(sk);
|
npc.doCast(sk);
|
||||||
|
npc.setTarget(target);
|
||||||
|
_log.info(this.getActor().getName() + " used heal skill " + sk.getName() + " on clan member " + obj.getName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isParty(sk))
|
if (isParty(sk))
|
||||||
{
|
{
|
||||||
clientStopMoving(null);
|
clientStopMoving(null);
|
||||||
L2Object target = getAttackTarget();
|
final L2Object target = npc.getTarget();
|
||||||
npc.setTarget(npc);
|
npc.setTarget(npc);
|
||||||
npc.doCast(sk);
|
npc.doCast(sk);
|
||||||
npc.setTarget(target);
|
npc.setTarget(target);
|
||||||
|
_log.info(this.getActor().getName() + " used heal skill " + sk.getName() + " on party");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1195,69 +1213,35 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
setTimepass(0);
|
setTimepass(0);
|
||||||
// --------------------------------------------------------------------------------
|
|
||||||
// Skill Use
|
|
||||||
List<Skill> aiGeneralSkills = _skillrender.getAISkills(AISkillScope.GENERAL);
|
|
||||||
if (!aiGeneralSkills.isEmpty())
|
|
||||||
{
|
|
||||||
if (Rnd.get(100) < Rnd.get(npc.getMinSkillChance(), npc.getMaxSkillChance()))
|
|
||||||
{
|
|
||||||
Skill skills = aiGeneralSkills.get(Rnd.nextInt(aiGeneralSkills.size()));
|
|
||||||
if (cast(skills))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (Skill sk : aiGeneralSkills)
|
|
||||||
{
|
|
||||||
if (cast(sk))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
// Long/Short Range skill usage.
|
// Long/Short Range skill usage.
|
||||||
if (npc.hasLSkill() || npc.hasSSkill())
|
if (!npc.getShortRangeSkills().isEmpty() && npc.hasSkillChance())
|
||||||
{
|
{
|
||||||
final List<Skill> shortRangeSkills = shortRangeSkillRender();
|
final Skill shortRangeSkill = npc.getShortRangeSkills().get(Rnd.get(npc.getShortRangeSkills().size()));
|
||||||
if (!shortRangeSkills.isEmpty() && npc.hasSSkill() && (dist2 <= 150) && (Rnd.get(100) <= npc.getSSkillChance()))
|
if (checkSkillCastConditions(npc, shortRangeSkill))
|
||||||
{
|
|
||||||
final Skill shortRangeSkill = shortRangeSkills.get(Rnd.get(shortRangeSkills.size()));
|
|
||||||
if ((shortRangeSkill != null) && cast(shortRangeSkill))
|
|
||||||
{
|
{
|
||||||
|
clientStopMoving(null);
|
||||||
|
npc.doCast(shortRangeSkill);
|
||||||
|
_log.info(this.getActor().getName() + " used short range skill " + shortRangeSkill.getName() + " on " + npc.getTarget().getName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (Skill sk : shortRangeSkills)
|
|
||||||
{
|
|
||||||
if ((sk != null) && cast(sk))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<Skill> longRangeSkills = longRangeSkillRender();
|
if (!npc.getLongRangeSkills().isEmpty() && npc.hasSkillChance())
|
||||||
if (!longRangeSkills.isEmpty() && npc.hasLSkill() && (dist2 > 150) && (Rnd.get(100) <= npc.getLSkillChance()))
|
|
||||||
{
|
{
|
||||||
final Skill longRangeSkill = longRangeSkills.get(Rnd.get(longRangeSkills.size()));
|
final Skill longRangeSkill = npc.getLongRangeSkills().get(Rnd.get(npc.getLongRangeSkills().size()));
|
||||||
if ((longRangeSkill != null) && cast(longRangeSkill))
|
if (checkSkillCastConditions(npc, longRangeSkill))
|
||||||
{
|
{
|
||||||
|
clientStopMoving(null);
|
||||||
|
npc.doCast(longRangeSkill);
|
||||||
|
_log.info(this.getActor().getName() + " used long range skill " + longRangeSkill.getName() + " on " + npc.getTarget().getName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (Skill sk : longRangeSkills)
|
|
||||||
{
|
|
||||||
if ((sk != null) && cast(sk))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
// Starts Melee or Primary Skill
|
// Starts melee attack
|
||||||
if ((dist2 > range) || !GeoData.getInstance().canSeeTarget(npc, mostHate))
|
if ((dist2 > range) || !GeoData.getInstance().canSeeTarget(npc, mostHate))
|
||||||
{
|
{
|
||||||
if (npc.isMovementDisabled())
|
if (npc.isMovementDisabled())
|
||||||
@@ -1279,54 +1263,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
melee(npc.getPrimarySkillId());
|
// Attacks target
|
||||||
}
|
|
||||||
|
|
||||||
private void melee(int type)
|
|
||||||
{
|
|
||||||
if (type != 0)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case -1:
|
|
||||||
{
|
|
||||||
for (Skill sk : _skillrender.getAISkills(AISkillScope.GENERAL))
|
|
||||||
{
|
|
||||||
if (cast(sk))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
for (Skill sk : _skillrender.getAISkills(AISkillScope.ATTACK))
|
|
||||||
{
|
|
||||||
if (cast(sk))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
for (Skill sk : _skillrender.getAISkills(AISkillScope.GENERAL))
|
|
||||||
{
|
|
||||||
if (sk.getId() == getActiveChar().getPrimarySkillId())
|
|
||||||
{
|
|
||||||
if (cast(sk))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_actor.doAttack(getAttackTarget());
|
_actor.doAttack(getAttackTarget());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1338,16 +1275,11 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
final L2Attackable caster = getActiveChar();
|
final L2Attackable caster = getActiveChar();
|
||||||
|
if (!checkSkillCastConditions(caster, sk))
|
||||||
if (caster.isCastingNow() && !sk.isSimultaneousCast())
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkSkillCastConditions(sk))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (getAttackTarget() == null)
|
if (getAttackTarget() == null)
|
||||||
{
|
{
|
||||||
if (caster.getMostHated() != null)
|
if (caster.getMostHated() != null)
|
||||||
@@ -1829,6 +1761,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
/**
|
/**
|
||||||
* This AI task will start when ACTOR cannot move and attack range larger than distance
|
* This AI task will start when ACTOR cannot move and attack range larger than distance
|
||||||
*/
|
*/
|
||||||
|
// TODO(Zoey76): Rework this method.
|
||||||
private void movementDisable()
|
private void movementDisable()
|
||||||
{
|
{
|
||||||
final L2Attackable npc = getActiveChar();
|
final L2Attackable npc = getActiveChar();
|
||||||
@@ -1854,16 +1787,16 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if activeChar has any skill
|
// Check if activeChar has any skill
|
||||||
if (!_skillrender.getAISkills(AISkillScope.GENERAL).isEmpty())
|
if (!npc.getTemplate().getAISkills(AISkillScope.GENERAL).isEmpty())
|
||||||
{
|
{
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
// Try to stop the target or disable the target as priority
|
// Try to stop the target or disable the target as priority
|
||||||
int random = Rnd.get(100);
|
int random = Rnd.get(100);
|
||||||
if (!getAttackTarget().isImmobilized() && (random < 2))
|
if (!getAttackTarget().isImmobilized() && (random < 2))
|
||||||
{
|
{
|
||||||
for (Skill sk : _skillrender.getAISkills(AISkillScope.IMMOBILIZE))
|
for (Skill sk : npc.getTemplate().getAISkills(AISkillScope.IMMOBILIZE))
|
||||||
{
|
{
|
||||||
if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
|
if (!checkSkillCastConditions(npc, sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1886,9 +1819,9 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
// Same as Above, but with Mute/FEAR etc....
|
// Same as Above, but with Mute/FEAR etc....
|
||||||
if (random < 5)
|
if (random < 5)
|
||||||
{
|
{
|
||||||
for (Skill sk : _skillrender.getAISkills(AISkillScope.COT))
|
for (Skill sk : npc.getTemplate().getAISkills(AISkillScope.COT))
|
||||||
{
|
{
|
||||||
if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
|
if (!checkSkillCastConditions(npc, sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1910,9 +1843,9 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
if (random < 8)
|
if (random < 8)
|
||||||
{
|
{
|
||||||
for (Skill sk : _skillrender.getAISkills(AISkillScope.DEBUFF))
|
for (Skill sk : npc.getTemplate().getAISkills(AISkillScope.DEBUFF))
|
||||||
{
|
{
|
||||||
if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
|
if (!checkSkillCastConditions(npc, sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1935,9 +1868,9 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
// Some side effect skill like CANCEL or NEGATE
|
// Some side effect skill like CANCEL or NEGATE
|
||||||
if (random < 9)
|
if (random < 9)
|
||||||
{
|
{
|
||||||
for (Skill sk : _skillrender.getAISkills(AISkillScope.NEGATIVE))
|
for (Skill sk : npc.getTemplate().getAISkills(AISkillScope.NEGATIVE))
|
||||||
{
|
{
|
||||||
if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
|
if (!checkSkillCastConditions(npc, sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1960,9 +1893,9 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
// Start ATK SKILL when nothing can be done
|
// Start ATK SKILL when nothing can be done
|
||||||
if ((npc.isMovementDisabled() || (npc.getAiType() == AIType.MAGE) || (npc.getAiType() == AIType.HEALER)))
|
if ((npc.isMovementDisabled() || (npc.getAiType() == AIType.MAGE) || (npc.getAiType() == AIType.HEALER)))
|
||||||
{
|
{
|
||||||
for (Skill sk : _skillrender.getAISkills(AISkillScope.ATTACK))
|
for (Skill sk : npc.getTemplate().getAISkills(AISkillScope.ATTACK))
|
||||||
{
|
{
|
||||||
if (!checkSkillCastConditions(sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
|
if (!checkSkillCastConditions(npc, sk) || (((sk.getCastRange() + npc.getTemplate().getCollisionRadius() + getAttackTarget().getTemplate().getCollisionRadius()) <= dist2) && !canAura(sk)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2034,22 +1967,29 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
melee(npc.getPrimarySkillId());
|
// Attacks target
|
||||||
|
_actor.doAttack(getAttackTarget());
|
||||||
}
|
}
|
||||||
catch (NullPointerException e)
|
catch (NullPointerException e)
|
||||||
{
|
{
|
||||||
setIntention(AI_INTENTION_ACTIVE);
|
setIntention(AI_INTENTION_ACTIVE);
|
||||||
_log.warning(getClass().getSimpleName() + ": " + this + " - failed executing movementDisable(): " + e.getMessage());
|
_log.warning(getClass().getSimpleName() + ": " + this.getActor().getName() + " - failed executing movementDisable()!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param caster the caster
|
||||||
* @param skill the skill to check.
|
* @param skill the skill to check.
|
||||||
* @return {@code true} if the skill is available for casting {@code false} otherwise.
|
* @return {@code true} if the skill is available for casting {@code false} otherwise.
|
||||||
*/
|
*/
|
||||||
private boolean checkSkillCastConditions(Skill skill)
|
private boolean checkSkillCastConditions(L2Attackable caster, Skill skill)
|
||||||
{
|
{
|
||||||
|
if (caster.isCastingNow() && !skill.isSimultaneousCast())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Not enough MP.
|
// Not enough MP.
|
||||||
if (skill.getMpConsume() >= getActiveChar().getCurrentMp())
|
if (skill.getMpConsume() >= getActiveChar().getCurrentMp())
|
||||||
{
|
{
|
||||||
@@ -2550,26 +2490,6 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Skill> longRangeSkillRender()
|
|
||||||
{
|
|
||||||
List<Skill> longRangeSkills = _skillrender.getAISkills(AISkillScope.LONG_RANGE);
|
|
||||||
if (longRangeSkills.isEmpty())
|
|
||||||
{
|
|
||||||
longRangeSkills = getActiveChar().getLongRangeSkill();
|
|
||||||
}
|
|
||||||
return longRangeSkills;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Skill> shortRangeSkillRender()
|
|
||||||
{
|
|
||||||
List<Skill> shortRangeSkills = _skillrender.getAISkills(AISkillScope.SHORT_RANGE);
|
|
||||||
if (shortRangeSkills.isEmpty())
|
|
||||||
{
|
|
||||||
shortRangeSkills = getActiveChar().getShortRangeSkill();
|
|
||||||
}
|
|
||||||
return shortRangeSkills;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manage AI thinking actions of a L2Attackable.
|
* Manage AI thinking actions of a L2Attackable.
|
||||||
*/
|
*/
|
||||||
@@ -2603,7 +2523,7 @@ public class L2AttackableAI extends L2CharacterAI implements Runnable
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_log.warning(getClass().getSimpleName() + ": " + this + " - onEvtThink() failed: " + e.getMessage());
|
_log.warning(getClass().getSimpleName() + ": " + this.getActor().getName() + " - onEvtThink() failed!");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@@ -1629,7 +1629,7 @@ public class L2CharacterAI extends AbstractAI
|
|||||||
|
|
||||||
public boolean canParty(Skill sk)
|
public boolean canParty(Skill sk)
|
||||||
{
|
{
|
||||||
if (sk.getTargetType() == L2TargetType.PARTY)
|
if (isParty(sk))
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int ccount = 0;
|
int ccount = 0;
|
||||||
|
@@ -509,14 +509,17 @@ public class NpcData implements IXmlReader
|
|||||||
Map<AISkillScope, List<Skill>> aiSkillLists = null;
|
Map<AISkillScope, List<Skill>> aiSkillLists = null;
|
||||||
for (Skill skill : skills.values())
|
for (Skill skill : skills.values())
|
||||||
{
|
{
|
||||||
if (!skill.isPassive())
|
if (skill.isPassive())
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (aiSkillLists == null)
|
if (aiSkillLists == null)
|
||||||
{
|
{
|
||||||
aiSkillLists = new EnumMap<>(AISkillScope.class);
|
aiSkillLists = new EnumMap<>(AISkillScope.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<AISkillScope> aiSkillScopes = new ArrayList<>();
|
final List<AISkillScope> aiSkillScopes = new ArrayList<>();
|
||||||
final AISkillScope shortOrLongRangeScope = skill.getCastRange() <= 150 ? AISkillScope.SHORT_RANGE : AISkillScope.SHORT_RANGE;
|
final AISkillScope shortOrLongRangeScope = skill.getCastRange() <= 150 ? AISkillScope.SHORT_RANGE : AISkillScope.SHORT_RANGE;
|
||||||
if (skill.isSuicideAttack())
|
if (skill.isSuicideAttack())
|
||||||
{
|
{
|
||||||
@@ -602,7 +605,6 @@ public class NpcData implements IXmlReader
|
|||||||
aiSkills.add(skill);
|
aiSkills.add(skill);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template.setSkills(skills);
|
template.setSkills(skills);
|
||||||
template.setAISkillLists(aiSkillLists);
|
template.setAISkillLists(aiSkillLists);
|
||||||
|
@@ -48,7 +48,7 @@ import com.l2jserver.util.Rnd;
|
|||||||
*/
|
*/
|
||||||
public class AugmentationData
|
public class AugmentationData
|
||||||
{
|
{
|
||||||
// Zoey76: TODO: Implement using IXmlReader.
|
// TODO(Zoey76): Implement using IXmlReader.
|
||||||
private static final Logger LOGGER = Logger.getLogger(AugmentationData.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(AugmentationData.class.getName());
|
||||||
|
|
||||||
// stats
|
// stats
|
||||||
@@ -350,7 +350,6 @@ public class AugmentationData
|
|||||||
{
|
{
|
||||||
NamedNodeMap aNodeAttributes = null;
|
NamedNodeMap aNodeAttributes = null;
|
||||||
|
|
||||||
// System.out.println("We're going through the list now.");
|
|
||||||
for (Node n = l.getFirstChild(); n != null; n = n.getNextSibling())
|
for (Node n = l.getFirstChild(); n != null; n = n.getNextSibling())
|
||||||
{
|
{
|
||||||
if (n.getNodeName().equals("weapon"))
|
if (n.getNodeName().equals("weapon"))
|
||||||
@@ -359,7 +358,6 @@ public class AugmentationData
|
|||||||
|
|
||||||
aWeaponType = aNodeAttributes.getNamedItem("type").getNodeValue();
|
aWeaponType = aNodeAttributes.getNamedItem("type").getNodeValue();
|
||||||
|
|
||||||
// System.out.println("Now showing Augmentations for " + aWeaponType + " Weapons.");
|
|
||||||
for (Node c = n.getFirstChild(); c != null; c = c.getNextSibling())
|
for (Node c = n.getFirstChild(); c != null; c = c.getNextSibling())
|
||||||
{
|
{
|
||||||
if (c.getNodeName().equals("stone"))
|
if (c.getNodeName().equals("stone"))
|
||||||
@@ -384,7 +382,6 @@ public class AugmentationData
|
|||||||
|
|
||||||
aCategoryChance = Integer.parseInt(aNodeAttributes.getNamedItem("probability").getNodeValue());
|
aCategoryChance = Integer.parseInt(aNodeAttributes.getNamedItem("probability").getNodeValue());
|
||||||
|
|
||||||
// System.out.println("Stone Id: " + aStoneId + ", Variation Id: " + aVariationId + ", Category Chances: " + aCategoryChance);
|
|
||||||
for (Node e = j.getFirstChild(); e != null; e = e.getNextSibling())
|
for (Node e = j.getFirstChild(); e != null; e = e.getNextSibling())
|
||||||
{
|
{
|
||||||
if (e.getNodeName().equals("augment"))
|
if (e.getNodeName().equals("augment"))
|
||||||
|
@@ -18,6 +18,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.l2jserver.gameserver.instancemanager;
|
package com.l2jserver.gameserver.instancemanager;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
@@ -26,9 +28,11 @@ import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
|||||||
import com.l2jserver.gameserver.model.entity.Duel;
|
import com.l2jserver.gameserver.model.entity.Duel;
|
||||||
import com.l2jserver.gameserver.model.skills.Skill;
|
import com.l2jserver.gameserver.model.skills.Skill;
|
||||||
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
|
import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
|
||||||
|
import com.l2jserver.util.Rnd;
|
||||||
|
|
||||||
public final class DuelManager
|
public final class DuelManager
|
||||||
{
|
{
|
||||||
|
private static final List<String> ARENAS = Arrays.asList("OlympiadGrassyArena.xml", "OlympiadHerossVestigesArena.xml", "OlympiadOrbisArena.xml", "OlympiadThreeBridgesArena.xml");
|
||||||
private final Map<Integer, Duel> _duels = new ConcurrentHashMap<>();
|
private final Map<Integer, Duel> _duels = new ConcurrentHashMap<>();
|
||||||
private final AtomicInteger _currentDuelId = new AtomicInteger();
|
private final AtomicInteger _currentDuelId = new AtomicInteger();
|
||||||
|
|
||||||
@@ -209,6 +213,15 @@ public final class DuelManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets new a random Olympiad Stadium instance name.
|
||||||
|
* @return an instance name
|
||||||
|
*/
|
||||||
|
public String getDuelArena()
|
||||||
|
{
|
||||||
|
return ARENAS.get(Rnd.get(ARENAS.size()));
|
||||||
|
}
|
||||||
|
|
||||||
public static final DuelManager getInstance()
|
public static final DuelManager getInstance()
|
||||||
{
|
{
|
||||||
return SingletonHolder._instance;
|
return SingletonHolder._instance;
|
||||||
|
@@ -362,7 +362,7 @@ public class StatsSet implements IParserAdvUtils
|
|||||||
Object val = _set.get(key);
|
Object val = _set.get(key);
|
||||||
if (val == null)
|
if (val == null)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Integer value required, but not specified");
|
throw new IllegalArgumentException("Long value required, but not specified");
|
||||||
}
|
}
|
||||||
if (val instanceof Number)
|
if (val instanceof Number)
|
||||||
{
|
{
|
||||||
@@ -374,7 +374,7 @@ public class StatsSet implements IParserAdvUtils
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Integer value required, but found: " + val);
|
throw new IllegalArgumentException("Long value required, but found: " + val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,7 +396,7 @@ public class StatsSet implements IParserAdvUtils
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Integer value required, but found: " + val);
|
throw new IllegalArgumentException("Long value required, but found: " + val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +414,7 @@ public class StatsSet implements IParserAdvUtils
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return (float) Double.parseDouble((String) val);
|
return Float.parseFloat((String) val);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -436,7 +436,7 @@ public class StatsSet implements IParserAdvUtils
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return (float) Double.parseDouble((String) val);
|
return Float.parseFloat((String) val);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -450,7 +450,7 @@ public class StatsSet implements IParserAdvUtils
|
|||||||
Object val = _set.get(key);
|
Object val = _set.get(key);
|
||||||
if (val == null)
|
if (val == null)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Float value required, but not specified");
|
throw new IllegalArgumentException("Double value required, but not specified");
|
||||||
}
|
}
|
||||||
if (val instanceof Number)
|
if (val instanceof Number)
|
||||||
{
|
{
|
||||||
@@ -462,7 +462,7 @@ public class StatsSet implements IParserAdvUtils
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Float value required, but found: " + val);
|
throw new IllegalArgumentException("Double value required, but found: " + val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,7 +484,7 @@ public class StatsSet implements IParserAdvUtils
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Float value required, but found: " + val);
|
throw new IllegalArgumentException("Double value required, but found: " + val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,7 +607,7 @@ public class StatsSet implements IParserAdvUtils
|
|||||||
Object obj = _set.get(key);
|
Object obj = _set.get(key);
|
||||||
if ((obj == null) || !(obj instanceof List<?>))
|
if ((obj == null) || !(obj instanceof List<?>))
|
||||||
{
|
{
|
||||||
return Collections.EMPTY_LIST;
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (List<MinionHolder>) obj;
|
return (List<MinionHolder>) obj;
|
||||||
|
@@ -111,6 +111,7 @@ public class L2Attackable extends L2Npc
|
|||||||
// Misc
|
// Misc
|
||||||
private boolean _mustGiveExpSp;
|
private boolean _mustGiveExpSp;
|
||||||
protected int _onKillDelay = 5000;
|
protected int _onKillDelay = 5000;
|
||||||
|
private long _lastAttack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an attackable NPC.
|
* Creates an attackable NPC.
|
||||||
@@ -1575,6 +1576,16 @@ public class L2Attackable extends L2Npc
|
|||||||
return _onKillDelay;
|
return _onKillDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getLastAttack()
|
||||||
|
{
|
||||||
|
return _lastAttack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastAttack(long lastAttack)
|
||||||
|
{
|
||||||
|
_lastAttack = lastAttack;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the server allows Random Animation.
|
* Check if the server allows Random Animation.
|
||||||
*/
|
*/
|
||||||
|
@@ -5409,7 +5409,6 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
|
|||||||
// Remove all its Func objects from the L2Character calculator set
|
// Remove all its Func objects from the L2Character calculator set
|
||||||
if (oldSkill != null)
|
if (oldSkill != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Stop casting if this skill is used right now
|
// Stop casting if this skill is used right now
|
||||||
if ((getLastSkillCast() != null) && isCastingNow())
|
if ((getLastSkillCast() != null) && isCastingNow())
|
||||||
{
|
{
|
||||||
@@ -5444,7 +5443,7 @@ public abstract class L2Character extends L2Object implements ISkillsHolder, IDe
|
|||||||
*/
|
*/
|
||||||
public final Collection<Skill> getAllSkills()
|
public final Collection<Skill> getAllSkills()
|
||||||
{
|
{
|
||||||
return new ArrayList<>(_skills.values());
|
return _skills.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -20,7 +20,6 @@ package com.l2jserver.gameserver.model.actor;
|
|||||||
|
|
||||||
import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
|
import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -83,7 +82,6 @@ import com.l2jserver.gameserver.model.items.L2Weapon;
|
|||||||
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
|
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
|
||||||
import com.l2jserver.gameserver.model.olympiad.Olympiad;
|
import com.l2jserver.gameserver.model.olympiad.Olympiad;
|
||||||
import com.l2jserver.gameserver.model.skills.Skill;
|
import com.l2jserver.gameserver.model.skills.Skill;
|
||||||
import com.l2jserver.gameserver.model.skills.targets.L2TargetType;
|
|
||||||
import com.l2jserver.gameserver.model.variables.NpcVariables;
|
import com.l2jserver.gameserver.model.variables.NpcVariables;
|
||||||
import com.l2jserver.gameserver.model.zone.type.L2TownZone;
|
import com.l2jserver.gameserver.model.zone.type.L2TownZone;
|
||||||
import com.l2jserver.gameserver.network.SystemMessageId;
|
import com.l2jserver.gameserver.network.SystemMessageId;
|
||||||
@@ -193,14 +191,6 @@ public class L2Npc extends L2Character
|
|||||||
return getTemplate().getSpiritShotChance();
|
return getTemplate().getSpiritShotChance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the primary attack skill Id
|
|
||||||
*/
|
|
||||||
public int getPrimarySkillId()
|
|
||||||
{
|
|
||||||
return getTemplate().getPrimarySkillId();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMinSkillChance()
|
public int getMinSkillChance()
|
||||||
{
|
{
|
||||||
return getTemplate().getMinSkillChance();
|
return getTemplate().getMinSkillChance();
|
||||||
@@ -211,6 +201,15 @@ public class L2Npc extends L2Character
|
|||||||
return getTemplate().getMaxSkillChance();
|
return getTemplate().getMaxSkillChance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies if the NPC can cast a skill given the minimum and maximum skill chances.
|
||||||
|
* @return {@code true} if the NPC has chances of casting a skill
|
||||||
|
*/
|
||||||
|
public boolean hasSkillChance()
|
||||||
|
{
|
||||||
|
return Rnd.get(100) < Rnd.get(getMinSkillChance(), getMaxSkillChance());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean canMove()
|
public boolean canMove()
|
||||||
{
|
{
|
||||||
return getTemplate().canMove();
|
return getTemplate().canMove();
|
||||||
@@ -226,169 +225,57 @@ public class L2Npc extends L2Character
|
|||||||
return getTemplate().getDodge();
|
return getTemplate().getDodge();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSSkillChance()
|
public List<Skill> getLongRangeSkills()
|
||||||
{
|
{
|
||||||
return getTemplate().getShortRangeSkillChance();
|
return getTemplate().getAISkills(AISkillScope.LONG_RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLSkillChance()
|
public List<Skill> getShortRangeSkills()
|
||||||
{
|
{
|
||||||
return getTemplate().getLongRangeSkillChance();
|
return getTemplate().getAISkills(AISkillScope.SHORT_RANGE);
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasLSkill()
|
|
||||||
{
|
|
||||||
return getTemplate().getLongRangeSkillId() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasSSkill()
|
|
||||||
{
|
|
||||||
return getTemplate().getShortRangeSkillId() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Skill> getLongRangeSkill()
|
|
||||||
{
|
|
||||||
final List<Skill> skilldata = new ArrayList<>();
|
|
||||||
if (getTemplate().getLongRangeSkillId() == 0)
|
|
||||||
{
|
|
||||||
return skilldata;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (getTemplate().getLongRangeSkillId())
|
|
||||||
{
|
|
||||||
case -1:
|
|
||||||
{
|
|
||||||
final Collection<Skill> skills = getAllSkills();
|
|
||||||
if (skills != null)
|
|
||||||
{
|
|
||||||
for (Skill sk : skills)
|
|
||||||
{
|
|
||||||
if ((sk == null) || sk.isPassive() || (sk.getTargetType() == L2TargetType.SELF))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sk.getCastRange() >= 200)
|
|
||||||
{
|
|
||||||
skilldata.add(sk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
for (Skill sk : getTemplate().getAISkills(AISkillScope.UNIVERSAL))
|
|
||||||
{
|
|
||||||
if (sk.getCastRange() >= 200)
|
|
||||||
{
|
|
||||||
skilldata.add(sk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
for (Skill sk : getAllSkills())
|
|
||||||
{
|
|
||||||
if (sk.getId() == getTemplate().getLongRangeSkillId())
|
|
||||||
{
|
|
||||||
skilldata.add(sk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return skilldata;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Skill> getShortRangeSkill()
|
|
||||||
{
|
|
||||||
final List<Skill> skilldata = new ArrayList<>();
|
|
||||||
if (getTemplate().getShortRangeSkillId() == 0)
|
|
||||||
{
|
|
||||||
return skilldata;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (getTemplate().getShortRangeSkillId())
|
|
||||||
{
|
|
||||||
case -1:
|
|
||||||
{
|
|
||||||
Collection<Skill> skills = getAllSkills();
|
|
||||||
if (skills != null)
|
|
||||||
{
|
|
||||||
for (Skill sk : skills)
|
|
||||||
{
|
|
||||||
if ((sk == null) || sk.isPassive() || (sk.getTargetType() == L2TargetType.SELF))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (sk.getCastRange() <= 200)
|
|
||||||
{
|
|
||||||
skilldata.add(sk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
for (Skill sk : getTemplate().getAISkills(AISkillScope.UNIVERSAL))
|
|
||||||
{
|
|
||||||
if (sk.getCastRange() <= 200)
|
|
||||||
{
|
|
||||||
skilldata.add(sk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
for (Skill sk : getAllSkills())
|
|
||||||
{
|
|
||||||
if (sk.getId() == getTemplate().getShortRangeSkillId())
|
|
||||||
{
|
|
||||||
skilldata.add(sk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return skilldata;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Task launching the function onRandomAnimation() */
|
/** Task launching the function onRandomAnimation() */
|
||||||
protected class RandomAnimationTask implements Runnable
|
protected static class RandomAnimationTask implements Runnable
|
||||||
{
|
{
|
||||||
|
private final L2Npc _npc;
|
||||||
|
|
||||||
|
protected RandomAnimationTask(L2Npc npc)
|
||||||
|
{
|
||||||
|
_npc = npc;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (isMob())
|
if (_npc.isMob())
|
||||||
{
|
{
|
||||||
// Cancel further animation timers until intention is changed to ACTIVE again.
|
// Cancel further animation timers until intention is changed to ACTIVE again.
|
||||||
if (getAI().getIntention() != AI_INTENTION_ACTIVE)
|
if (_npc.getAI().getIntention() != AI_INTENTION_ACTIVE)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!isInActiveRegion())
|
if (!_npc.isInActiveRegion())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(isDead() || isStunned() || isSleeping() || isParalyzed()))
|
if (!(_npc.isDead() || _npc.isStunned() || _npc.isSleeping() || _npc.isParalyzed()))
|
||||||
{
|
{
|
||||||
onRandomAnimation(Rnd.get(2, 3));
|
_npc.onRandomAnimation(Rnd.get(2, 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
startRandomAnimationTimer();
|
_npc.startRandomAnimationTimer();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_log.log(Level.SEVERE, "", e);
|
_log.log(Level.SEVERE, "There has been an error trying to perform a random animation for NPC " + _npc.getId() + "!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -425,7 +312,7 @@ public class L2Npc extends L2Character
|
|||||||
int interval = Rnd.get(minWait, maxWait) * 1000;
|
int interval = Rnd.get(minWait, maxWait) * 1000;
|
||||||
|
|
||||||
// Create a RandomAnimation Task that will be launched after the calculated delay
|
// Create a RandomAnimation Task that will be launched after the calculated delay
|
||||||
_rAniTask = new RandomAnimationTask();
|
_rAniTask = new RandomAnimationTask(this);
|
||||||
ThreadPoolManager.getInstance().scheduleGeneral(_rAniTask, interval);
|
ThreadPoolManager.getInstance().scheduleGeneral(_rAniTask, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6774,8 +6774,8 @@ public final class L2PcInstance extends L2Playable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the _accessLevel of the L2PcInstance.
|
* Set the access level for this player.
|
||||||
* @param level
|
* @param level the access level
|
||||||
* @param broadcast
|
* @param broadcast
|
||||||
*/
|
*/
|
||||||
public void setAccessLevel(int level, boolean broadcast)
|
public void setAccessLevel(int level, boolean broadcast)
|
||||||
@@ -6793,7 +6793,7 @@ public final class L2PcInstance extends L2Playable
|
|||||||
|
|
||||||
if (!AdminData.getInstance().hasAccessLevel(level))
|
if (!AdminData.getInstance().hasAccessLevel(level))
|
||||||
{
|
{
|
||||||
_log.warning("Tryed to set unregistered access level " + level + " for " + toString() + ". Setting access level without privileges!");
|
_log.warning("Tried to set unregistered access level " + level + " for " + toString() + ". Setting access level without privileges!");
|
||||||
}
|
}
|
||||||
else if (level > 0)
|
else if (level > 0)
|
||||||
{
|
{
|
||||||
|
@@ -89,11 +89,6 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
|
|||||||
private int _spiritShotChance;
|
private int _spiritShotChance;
|
||||||
private int _minSkillChance;
|
private int _minSkillChance;
|
||||||
private int _maxSkillChance;
|
private int _maxSkillChance;
|
||||||
private int _primarySkillId;
|
|
||||||
private int _shortRangeSkillId;
|
|
||||||
private int _shortRangeSkillChance;
|
|
||||||
private int _longRangeSkillId;
|
|
||||||
private int _longRangeSkillChance;
|
|
||||||
private Map<Integer, Skill> _skills;
|
private Map<Integer, Skill> _skills;
|
||||||
private Map<AISkillScope, List<Skill>> _aiSkillLists;
|
private Map<AISkillScope, List<Skill>> _aiSkillLists;
|
||||||
private Set<Integer> _clans;
|
private Set<Integer> _clans;
|
||||||
@@ -166,11 +161,6 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
|
|||||||
|
|
||||||
_minSkillChance = set.getInt("minSkillChance", 7);
|
_minSkillChance = set.getInt("minSkillChance", 7);
|
||||||
_maxSkillChance = set.getInt("maxSkillChance", 15);
|
_maxSkillChance = set.getInt("maxSkillChance", 15);
|
||||||
_primarySkillId = set.getInt("primarySkillId", 0);
|
|
||||||
_shortRangeSkillId = set.getInt("shortRangeSkillId", 0);
|
|
||||||
_shortRangeSkillChance = set.getInt("shortRangeSkillChance", 0);
|
|
||||||
_longRangeSkillId = set.getInt("longRangeSkillId", 0);
|
|
||||||
_longRangeSkillChance = set.getInt("longRangeSkillChance", 0);
|
|
||||||
|
|
||||||
_collisionRadiusGrown = set.getDouble("collisionRadiusGrown", 0);
|
_collisionRadiusGrown = set.getDouble("collisionRadiusGrown", 0);
|
||||||
_collisionHeightGrown = set.getDouble("collisionHeightGrown", 0);
|
_collisionHeightGrown = set.getDouble("collisionHeightGrown", 0);
|
||||||
@@ -397,31 +387,6 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
|
|||||||
return _maxSkillChance;
|
return _maxSkillChance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPrimarySkillId()
|
|
||||||
{
|
|
||||||
return _primarySkillId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getShortRangeSkillId()
|
|
||||||
{
|
|
||||||
return _shortRangeSkillId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getShortRangeSkillChance()
|
|
||||||
{
|
|
||||||
return _shortRangeSkillChance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLongRangeSkillId()
|
|
||||||
{
|
|
||||||
return _longRangeSkillId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLongRangeSkillChance()
|
|
||||||
{
|
|
||||||
return _longRangeSkillChance;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<Integer, Skill> getSkills()
|
public Map<Integer, Skill> getSkills()
|
||||||
{
|
{
|
||||||
@@ -430,18 +395,17 @@ public final class L2NpcTemplate extends L2CharTemplate implements IIdentifiable
|
|||||||
|
|
||||||
public void setSkills(Map<Integer, Skill> skills)
|
public void setSkills(Map<Integer, Skill> skills)
|
||||||
{
|
{
|
||||||
_skills = skills != null ? Collections.unmodifiableMap(skills) : Collections.<Integer, Skill> emptyMap();
|
_skills = skills != null ? Collections.unmodifiableMap(skills) : Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Skill> getAISkills(AISkillScope aiSkillScope)
|
public List<Skill> getAISkills(AISkillScope aiSkillScope)
|
||||||
{
|
{
|
||||||
final List<Skill> aiSkills = _aiSkillLists.get(aiSkillScope);
|
return _aiSkillLists.getOrDefault(aiSkillScope, Collections.emptyList());
|
||||||
return aiSkills != null ? aiSkills : Collections.<Skill> emptyList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAISkillLists(Map<AISkillScope, List<Skill>> aiSkillLists)
|
public void setAISkillLists(Map<AISkillScope, List<Skill>> aiSkillLists)
|
||||||
{
|
{
|
||||||
_aiSkillLists = aiSkillLists != null ? Collections.unmodifiableMap(aiSkillLists) : Collections.<AISkillScope, List<Skill>> emptyMap();
|
_aiSkillLists = aiSkillLists != null ? Collections.unmodifiableMap(aiSkillLists) : Collections.emptyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Integer> getClans()
|
public Set<Integer> getClans()
|
||||||
|
@@ -20,7 +20,9 @@ package com.l2jserver.gameserver.model.entity;
|
|||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -29,10 +31,17 @@ import com.l2jserver.gameserver.ai.CtrlIntention;
|
|||||||
import com.l2jserver.gameserver.enums.DuelResult;
|
import com.l2jserver.gameserver.enums.DuelResult;
|
||||||
import com.l2jserver.gameserver.enums.Team;
|
import com.l2jserver.gameserver.enums.Team;
|
||||||
import com.l2jserver.gameserver.instancemanager.DuelManager;
|
import com.l2jserver.gameserver.instancemanager.DuelManager;
|
||||||
|
import com.l2jserver.gameserver.instancemanager.InstanceManager;
|
||||||
|
import com.l2jserver.gameserver.instancemanager.ZoneManager;
|
||||||
import com.l2jserver.gameserver.model.Location;
|
import com.l2jserver.gameserver.model.Location;
|
||||||
|
import com.l2jserver.gameserver.model.actor.L2Npc;
|
||||||
|
import com.l2jserver.gameserver.model.actor.L2Summon;
|
||||||
|
import com.l2jserver.gameserver.model.actor.instance.L2DoorInstance;
|
||||||
|
import com.l2jserver.gameserver.model.actor.instance.L2OlympiadManagerInstance;
|
||||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
||||||
import com.l2jserver.gameserver.model.skills.Skill;
|
import com.l2jserver.gameserver.model.skills.Skill;
|
||||||
import com.l2jserver.gameserver.model.zone.ZoneId;
|
import com.l2jserver.gameserver.model.zone.ZoneId;
|
||||||
|
import com.l2jserver.gameserver.model.zone.type.L2OlympiadStadiumZone;
|
||||||
import com.l2jserver.gameserver.network.SystemMessageId;
|
import com.l2jserver.gameserver.network.SystemMessageId;
|
||||||
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
|
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
|
||||||
import com.l2jserver.gameserver.network.serverpackets.ExDuelEnd;
|
import com.l2jserver.gameserver.network.serverpackets.ExDuelEnd;
|
||||||
@@ -43,6 +52,7 @@ import com.l2jserver.gameserver.network.serverpackets.L2GameServerPacket;
|
|||||||
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
|
import com.l2jserver.gameserver.network.serverpackets.PlaySound;
|
||||||
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
|
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
|
||||||
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
|
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
|
||||||
|
import com.l2jserver.util.Rnd;
|
||||||
|
|
||||||
public class Duel
|
public class Duel
|
||||||
{
|
{
|
||||||
@@ -56,16 +66,20 @@ public class Duel
|
|||||||
|
|
||||||
private static final PlaySound B04_S01 = new PlaySound(1, "B04_S01", 0, 0, 0, 0, 0);
|
private static final PlaySound B04_S01 = new PlaySound(1, "B04_S01", 0, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
private static final int PARTY_DUEL_DURATION = 300;
|
||||||
|
private static final int PLAYER_DUEL_DURATION = 120;
|
||||||
|
|
||||||
private final int _duelId;
|
private final int _duelId;
|
||||||
private L2PcInstance _playerA;
|
private L2PcInstance _playerA;
|
||||||
private L2PcInstance _playerB;
|
private L2PcInstance _playerB;
|
||||||
private final boolean _partyDuel;
|
private final boolean _partyDuel;
|
||||||
private final Calendar _duelEndTime;
|
private final Calendar _duelEndTime;
|
||||||
private int _surrenderRequest = 0;
|
private int _surrenderRequest = 0;
|
||||||
private int _countdown = 4;
|
private int _countdown = 5;
|
||||||
private boolean _finished = false;
|
private boolean _finished = false;
|
||||||
|
|
||||||
private final List<PlayerCondition> _playerConditions = new CopyOnWriteArrayList<>();
|
private final Map<Integer, PlayerCondition> _playerConditions = new ConcurrentHashMap<>();
|
||||||
|
private int _duelInstanceId;
|
||||||
|
|
||||||
public Duel(L2PcInstance playerA, L2PcInstance playerB, int partyDuel, int duelId)
|
public Duel(L2PcInstance playerA, L2PcInstance playerB, int partyDuel, int duelId)
|
||||||
{
|
{
|
||||||
@@ -75,21 +89,12 @@ public class Duel
|
|||||||
_partyDuel = partyDuel == 1 ? true : false;
|
_partyDuel = partyDuel == 1 ? true : false;
|
||||||
|
|
||||||
_duelEndTime = Calendar.getInstance();
|
_duelEndTime = Calendar.getInstance();
|
||||||
if (_partyDuel)
|
_duelEndTime.add(Calendar.SECOND, _partyDuel ? PARTY_DUEL_DURATION : PLAYER_DUEL_DURATION);
|
||||||
{
|
|
||||||
_duelEndTime.add(Calendar.SECOND, 300);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_duelEndTime.add(Calendar.SECOND, 120);
|
|
||||||
}
|
|
||||||
|
|
||||||
setFinished(false);
|
setFinished(false);
|
||||||
|
|
||||||
if (_partyDuel)
|
if (_partyDuel)
|
||||||
{
|
{
|
||||||
// increase countdown so that start task can teleport players
|
|
||||||
_countdown++;
|
|
||||||
// inform players that they will be ported shortly
|
// inform players that they will be ported shortly
|
||||||
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.IN_A_MOMENT_YOU_WILL_BE_TRANSPORTED_TO_THE_SITE_WHERE_THE_DUEL_WILL_TAKE_PLACE);
|
SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.IN_A_MOMENT_YOU_WILL_BE_TRANSPORTED_TO_THE_SITE_WHERE_THE_DUEL_WILL_TAKE_PLACE);
|
||||||
broadcastToTeam1(sm);
|
broadcastToTeam1(sm);
|
||||||
@@ -107,7 +112,7 @@ public class Duel
|
|||||||
private double _cp;
|
private double _cp;
|
||||||
private boolean _paDuel;
|
private boolean _paDuel;
|
||||||
private int _x, _y, _z;
|
private int _x, _y, _z;
|
||||||
private List<Skill> _debuffs;
|
private Set<Skill> _debuffs;
|
||||||
|
|
||||||
public PlayerCondition(L2PcInstance player, boolean partyDuel)
|
public PlayerCondition(L2PcInstance player, boolean partyDuel)
|
||||||
{
|
{
|
||||||
@@ -159,7 +164,7 @@ public class Duel
|
|||||||
{
|
{
|
||||||
if (_debuffs == null)
|
if (_debuffs == null)
|
||||||
{
|
{
|
||||||
_debuffs = new CopyOnWriteArrayList<>();
|
_debuffs = ConcurrentHashMap.newKeySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
_debuffs.add(debuff);
|
_debuffs.add(debuff);
|
||||||
@@ -169,7 +174,7 @@ public class Duel
|
|||||||
{
|
{
|
||||||
if (_paDuel)
|
if (_paDuel)
|
||||||
{
|
{
|
||||||
_player.teleToLocation(new Location(_x, _y, _z));
|
_player.teleToLocation(_x, _y, _z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,28 +198,33 @@ public class Duel
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DuelResult status = _duel.checkEndDuelCondition();
|
switch (_duel.checkEndDuelCondition())
|
||||||
|
{
|
||||||
if (status == DuelResult.Canceled)
|
case Canceled:
|
||||||
{
|
{
|
||||||
// do not schedule duel end if it was interrupted
|
// do not schedule duel end if it was interrupted
|
||||||
setFinished(true);
|
setFinished(true);
|
||||||
_duel.endDuel(status);
|
_duel.endDuel(DuelResult.Canceled);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (status != DuelResult.Continue)
|
case Continue:
|
||||||
|
{
|
||||||
|
ThreadPoolManager.getInstance().scheduleGeneral(this, 1000);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
{
|
{
|
||||||
setFinished(true);
|
setFinished(true);
|
||||||
playKneelAnimation();
|
playKneelAnimation();
|
||||||
ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEndDuelTask(_duel, status), 5000);
|
ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleEndDuelTask(_duel, _duel.checkEndDuelCondition()), 5000);
|
||||||
|
InstanceManager.getInstance().destroyInstance(_duel.getDueldInstanceId());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
ThreadPoolManager.getInstance().scheduleGeneral(this, 1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_log.log(Level.SEVERE, "", e);
|
_log.log(Level.SEVERE, "There has been a problem while runing a duel task!", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,13 +248,13 @@ public class Duel
|
|||||||
|
|
||||||
if (count == 4)
|
if (count == 4)
|
||||||
{
|
{
|
||||||
// players need to be teleportet first
|
// Save player conditions before teleporting players
|
||||||
// TODO: stadia manager needs a function to return an unused stadium for duels
|
_duel.savePlayerConditions();
|
||||||
// currently only teleports to the same stadium
|
|
||||||
_duel.teleportPlayers(-83760, -238825, -3331);
|
|
||||||
|
|
||||||
// give players 20 seconds to complete teleport and get ready (its ought to be 30 on offical..)
|
_duel.teleportPlayers();
|
||||||
ThreadPoolManager.getInstance().scheduleGeneral(this, 20000);
|
|
||||||
|
// give players 20 seconds to complete teleport and get ready (its ought to be 30 on official..)
|
||||||
|
ThreadPoolManager.getInstance().scheduleGeneral(this, _duel.isPartyDuel() ? 20000 : 1);
|
||||||
}
|
}
|
||||||
else if (count > 0) // duel not started yet - continue countdown
|
else if (count > 0) // duel not started yet - continue countdown
|
||||||
{
|
{
|
||||||
@@ -287,6 +297,11 @@ public class Duel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getDueldInstanceId()
|
||||||
|
{
|
||||||
|
return _duelInstanceId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops all players from attacking. Used for duel timeout / interrupt.
|
* Stops all players from attacking. Used for duel timeout / interrupt.
|
||||||
*/
|
*/
|
||||||
@@ -301,6 +316,19 @@ public class Duel
|
|||||||
temp.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
|
temp.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
|
||||||
temp.setTarget(null);
|
temp.setTarget(null);
|
||||||
temp.sendPacket(af);
|
temp.sendPacket(af);
|
||||||
|
if (temp.hasSummon())
|
||||||
|
{
|
||||||
|
for (L2Summon summon : temp.getServitors().values())
|
||||||
|
{
|
||||||
|
if (!summon.isDead())
|
||||||
|
{
|
||||||
|
summon.abortCast();
|
||||||
|
summon.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
|
||||||
|
summon.setTarget(null);
|
||||||
|
summon.sendPacket(af);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (L2PcInstance temp : _playerB.getParty().getMembers())
|
for (L2PcInstance temp : _playerB.getParty().getMembers())
|
||||||
{
|
{
|
||||||
@@ -308,6 +336,19 @@ public class Duel
|
|||||||
temp.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
|
temp.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
|
||||||
temp.setTarget(null);
|
temp.setTarget(null);
|
||||||
temp.sendPacket(af);
|
temp.sendPacket(af);
|
||||||
|
if (temp.hasSummon())
|
||||||
|
{
|
||||||
|
for (L2Summon summon : temp.getServitors().values())
|
||||||
|
{
|
||||||
|
if (!summon.isDead())
|
||||||
|
{
|
||||||
|
summon.abortCast();
|
||||||
|
summon.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
|
||||||
|
summon.setTarget(null);
|
||||||
|
summon.sendPacket(af);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -320,6 +361,32 @@ public class Duel
|
|||||||
_playerB.setTarget(null);
|
_playerB.setTarget(null);
|
||||||
_playerA.sendPacket(af);
|
_playerA.sendPacket(af);
|
||||||
_playerB.sendPacket(af);
|
_playerB.sendPacket(af);
|
||||||
|
if (_playerA.hasSummon())
|
||||||
|
{
|
||||||
|
for (L2Summon summon : _playerA.getServitors().values())
|
||||||
|
{
|
||||||
|
if (!summon.isDead())
|
||||||
|
{
|
||||||
|
summon.abortCast();
|
||||||
|
summon.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
|
||||||
|
summon.setTarget(null);
|
||||||
|
summon.sendPacket(af);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_playerB.hasSummon())
|
||||||
|
{
|
||||||
|
for (L2Summon summon : _playerB.getServitors().values())
|
||||||
|
{
|
||||||
|
if (!summon.isDead())
|
||||||
|
{
|
||||||
|
summon.abortCast();
|
||||||
|
summon.getAI().setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
|
||||||
|
summon.setTarget(null);
|
||||||
|
summon.sendPacket(af);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,9 +420,6 @@ public class Duel
|
|||||||
*/
|
*/
|
||||||
public void startDuel()
|
public void startDuel()
|
||||||
{
|
{
|
||||||
// Save player Conditions
|
|
||||||
savePlayerConditions();
|
|
||||||
|
|
||||||
if ((_playerA == null) || (_playerB == null) || _playerA.isInDuel() || _playerB.isInDuel())
|
if ((_playerA == null) || (_playerB == null) || _playerA.isInDuel() || _playerB.isInDuel())
|
||||||
{
|
{
|
||||||
_playerConditions.clear();
|
_playerConditions.clear();
|
||||||
@@ -365,8 +429,7 @@ public class Duel
|
|||||||
|
|
||||||
if (_partyDuel)
|
if (_partyDuel)
|
||||||
{
|
{
|
||||||
// set isInDuel() state
|
// Set duel state and team
|
||||||
// cancel all active trades, just in case? xD
|
|
||||||
for (L2PcInstance temp : _playerA.getParty().getMembers())
|
for (L2PcInstance temp : _playerA.getParty().getMembers())
|
||||||
{
|
{
|
||||||
temp.cancelActiveTrade();
|
temp.cancelActiveTrade();
|
||||||
@@ -384,31 +447,35 @@ public class Duel
|
|||||||
broadcastToTeam1(new ExDuelUpdateUserInfo(temp));
|
broadcastToTeam1(new ExDuelUpdateUserInfo(temp));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send duel Start packets
|
// Send duel packets
|
||||||
ExDuelReady ready = new ExDuelReady(1);
|
broadcastToTeam1(ExDuelReady.PARTY_DUEL);
|
||||||
ExDuelStart start = new ExDuelStart(1);
|
broadcastToTeam2(ExDuelReady.PARTY_DUEL);
|
||||||
|
broadcastToTeam1(ExDuelStart.PARTY_DUEL);
|
||||||
|
broadcastToTeam2(ExDuelStart.PARTY_DUEL);
|
||||||
|
|
||||||
broadcastToTeam1(ready);
|
// Open arena doors
|
||||||
broadcastToTeam2(ready);
|
for (L2DoorInstance door : InstanceManager.getInstance().getInstance(getDueldInstanceId()).getDoors())
|
||||||
broadcastToTeam1(start);
|
{
|
||||||
broadcastToTeam2(start);
|
if ((door != null) && !door.getOpen())
|
||||||
|
{
|
||||||
|
door.openMe();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// set isInDuel() state
|
// Set duel state and team
|
||||||
_playerA.setIsInDuel(_duelId);
|
_playerA.setIsInDuel(_duelId);
|
||||||
_playerA.setTeam(Team.BLUE);
|
_playerA.setTeam(Team.BLUE);
|
||||||
_playerB.setIsInDuel(_duelId);
|
_playerB.setIsInDuel(_duelId);
|
||||||
_playerB.setTeam(Team.RED);
|
_playerB.setTeam(Team.RED);
|
||||||
|
|
||||||
// Send duel Start packets
|
// Send duel Start packets
|
||||||
ExDuelReady ready = new ExDuelReady(0);
|
// Send duel packets
|
||||||
ExDuelStart start = new ExDuelStart(0);
|
broadcastToTeam1(ExDuelReady.PLAYER_DUEL);
|
||||||
|
broadcastToTeam2(ExDuelReady.PLAYER_DUEL);
|
||||||
broadcastToTeam1(ready);
|
broadcastToTeam1(ExDuelStart.PLAYER_DUEL);
|
||||||
broadcastToTeam2(ready);
|
broadcastToTeam2(ExDuelStart.PLAYER_DUEL);
|
||||||
broadcastToTeam1(start);
|
|
||||||
broadcastToTeam2(start);
|
|
||||||
|
|
||||||
broadcastToTeam1(new ExDuelUpdateUserInfo(_playerB));
|
broadcastToTeam1(new ExDuelUpdateUserInfo(_playerB));
|
||||||
broadcastToTeam2(new ExDuelUpdateUserInfo(_playerA));
|
broadcastToTeam2(new ExDuelUpdateUserInfo(_playerA));
|
||||||
@@ -421,7 +488,7 @@ public class Duel
|
|||||||
broadcastToTeam1(B04_S01);
|
broadcastToTeam1(B04_S01);
|
||||||
broadcastToTeam2(B04_S01);
|
broadcastToTeam2(B04_S01);
|
||||||
|
|
||||||
// start duelling task
|
// start dueling task
|
||||||
ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleDuelTask(this), 1000);
|
ThreadPoolManager.getInstance().scheduleGeneral(new ScheduleDuelTask(this), 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,17 +501,17 @@ public class Duel
|
|||||||
{
|
{
|
||||||
for (L2PcInstance player : _playerA.getParty().getMembers())
|
for (L2PcInstance player : _playerA.getParty().getMembers())
|
||||||
{
|
{
|
||||||
_playerConditions.add(new PlayerCondition(player, _partyDuel));
|
_playerConditions.put(player.getObjectId(), new PlayerCondition(player, _partyDuel));
|
||||||
}
|
}
|
||||||
for (L2PcInstance player : _playerB.getParty().getMembers())
|
for (L2PcInstance player : _playerB.getParty().getMembers())
|
||||||
{
|
{
|
||||||
_playerConditions.add(new PlayerCondition(player, _partyDuel));
|
_playerConditions.put(player.getObjectId(), new PlayerCondition(player, _partyDuel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_playerConditions.add(new PlayerCondition(_playerA, _partyDuel));
|
_playerConditions.put(_playerA.getObjectId(), new PlayerCondition(_playerA, _partyDuel));
|
||||||
_playerConditions.add(new PlayerCondition(_playerB, _partyDuel));
|
_playerConditions.put(_playerB.getObjectId(), new PlayerCondition(_playerB, _partyDuel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,7 +554,7 @@ public class Duel
|
|||||||
}
|
}
|
||||||
|
|
||||||
// restore player conditions
|
// restore player conditions
|
||||||
_playerConditions.forEach(c -> c.restoreCondition());
|
_playerConditions.values().forEach(c -> c.restoreCondition());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -546,30 +613,46 @@ public class Duel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* teleport all players to the given coordinates
|
* Teleports all players to a free arena.
|
||||||
* @param x
|
|
||||||
* @param y
|
|
||||||
* @param z
|
|
||||||
*/
|
*/
|
||||||
public void teleportPlayers(int x, int y, int z)
|
public void teleportPlayers()
|
||||||
{
|
{
|
||||||
// TODO: adjust the values if needed... or implement something better (especially using more then 1 arena)
|
|
||||||
if (!_partyDuel)
|
if (!_partyDuel)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
|
final String instanceName = DuelManager.getInstance().getDuelArena();
|
||||||
|
final L2OlympiadStadiumZone zone = ZoneManager.getInstance().getAllZones(L2OlympiadStadiumZone.class) //
|
||||||
|
.stream().filter(z -> z.getInstanceTemplate().equals(instanceName)).findFirst().orElse(null);
|
||||||
|
|
||||||
|
if (zone == null)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Unable to find a party duel arena!");
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Location> spawns = zone.getSpawns();
|
||||||
|
_duelInstanceId = InstanceManager.getInstance().createDynamicInstance(instanceName);
|
||||||
|
|
||||||
|
// Remove Olympiad buffers
|
||||||
|
for (L2Npc buffer : InstanceManager.getInstance().getInstance(getDueldInstanceId()).getNpcs())
|
||||||
|
{
|
||||||
|
if ((buffer instanceof L2OlympiadManagerInstance) && buffer.isVisible())
|
||||||
|
{
|
||||||
|
buffer.decayMe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Location spawn1 = spawns.get(Rnd.get(spawns.size() / 2));
|
||||||
for (L2PcInstance temp : _playerA.getParty().getMembers())
|
for (L2PcInstance temp : _playerA.getParty().getMembers())
|
||||||
{
|
{
|
||||||
temp.teleToLocation(new Location((x + offset) - 180, y - 150, z));
|
temp.teleToLocation(spawn1.getX(), spawn1.getY(), spawn1.getZ(), 0, _duelInstanceId, 0);
|
||||||
offset += 40;
|
|
||||||
}
|
}
|
||||||
offset = 0;
|
|
||||||
|
final Location spawn2 = spawns.get(Rnd.get(spawns.size() / 2, spawns.size()));
|
||||||
for (L2PcInstance temp : _playerB.getParty().getMembers())
|
for (L2PcInstance temp : _playerB.getParty().getMembers())
|
||||||
{
|
{
|
||||||
temp.teleToLocation(new Location((x + offset) - 180, y + 150, z));
|
temp.teleToLocation(spawn2.getX(), spawn2.getY(), spawn2.getZ(), 0, _duelInstanceId, 0);
|
||||||
offset += 40;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -664,7 +747,7 @@ public class Duel
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Playback the bow animation for all loosers
|
* Playback the bow animation for all looser
|
||||||
*/
|
*/
|
||||||
public void playKneelAnimation()
|
public void playKneelAnimation()
|
||||||
{
|
{
|
||||||
@@ -794,17 +877,7 @@ public class Duel
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send end duel packet
|
final ExDuelEnd duelEnd = _partyDuel ? ExDuelEnd.PARTY_DUEL : ExDuelEnd.PLAYER_DUEL;
|
||||||
ExDuelEnd duelEnd = null;
|
|
||||||
if (_partyDuel)
|
|
||||||
{
|
|
||||||
duelEnd = new ExDuelEnd(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
duelEnd = new ExDuelEnd(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
broadcastToTeam1(duelEnd);
|
broadcastToTeam1(duelEnd);
|
||||||
broadcastToTeam2(duelEnd);
|
broadcastToTeam2(duelEnd);
|
||||||
|
|
||||||
@@ -1014,7 +1087,7 @@ public class Duel
|
|||||||
// if he's either playerA or playerB cancel the duel and port the players back
|
// if he's either playerA or playerB cancel the duel and port the players back
|
||||||
if ((player == _playerA) || (player == _playerB))
|
if ((player == _playerA) || (player == _playerB))
|
||||||
{
|
{
|
||||||
for (PlayerCondition cond : _playerConditions)
|
for (PlayerCondition cond : _playerConditions.values())
|
||||||
{
|
{
|
||||||
cond.teleportBack();
|
cond.teleportBack();
|
||||||
cond.getPlayer().setIsInDuel(0);
|
cond.getPlayer().setIsInDuel(0);
|
||||||
@@ -1026,7 +1099,7 @@ public class Duel
|
|||||||
else
|
else
|
||||||
// teleport the player back & delete his PlayerCondition record
|
// teleport the player back & delete his PlayerCondition record
|
||||||
{
|
{
|
||||||
final PlayerCondition cond = _playerConditions.stream().filter(c -> c.getPlayer() == player).findFirst().orElse(null);
|
final PlayerCondition cond = _playerConditions.get(player.getObjectId());
|
||||||
if (cond != null)
|
if (cond != null)
|
||||||
{
|
{
|
||||||
cond.teleportBack();
|
cond.teleportBack();
|
||||||
@@ -1038,7 +1111,7 @@ public class Duel
|
|||||||
|
|
||||||
public void onBuff(L2PcInstance player, Skill debuff)
|
public void onBuff(L2PcInstance player, Skill debuff)
|
||||||
{
|
{
|
||||||
final PlayerCondition cond = _playerConditions.stream().filter(c -> c.getPlayer() == player).findFirst().orElse(null);
|
final PlayerCondition cond = _playerConditions.get(player.getObjectId());
|
||||||
if (cond != null)
|
if (cond != null)
|
||||||
{
|
{
|
||||||
cond.registerDebuff(debuff);
|
cond.registerDebuff(debuff);
|
||||||
|
@@ -19,15 +19,19 @@
|
|||||||
package com.l2jserver.gameserver.network.serverpackets;
|
package com.l2jserver.gameserver.network.serverpackets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author KenM
|
* Duel End packet implementation.
|
||||||
|
* @author KenM, Zoey76
|
||||||
*/
|
*/
|
||||||
public class ExDuelEnd extends L2GameServerPacket
|
public class ExDuelEnd extends L2GameServerPacket
|
||||||
{
|
{
|
||||||
private final int _unk1;
|
public static final ExDuelEnd PLAYER_DUEL = new ExDuelEnd(false);
|
||||||
|
public static final ExDuelEnd PARTY_DUEL = new ExDuelEnd(true);
|
||||||
|
|
||||||
public ExDuelEnd(int unk1)
|
private final int _partyDuel;
|
||||||
|
|
||||||
|
private ExDuelEnd(boolean isPartyDuel)
|
||||||
{
|
{
|
||||||
_unk1 = unk1;
|
_partyDuel = isPartyDuel ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -36,6 +40,6 @@ public class ExDuelEnd extends L2GameServerPacket
|
|||||||
writeC(0xFE);
|
writeC(0xFE);
|
||||||
writeH(0x50);
|
writeH(0x50);
|
||||||
|
|
||||||
writeD(_unk1);
|
writeD(_partyDuel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,15 +19,19 @@
|
|||||||
package com.l2jserver.gameserver.network.serverpackets;
|
package com.l2jserver.gameserver.network.serverpackets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author KenM
|
* Duel Ready packet implementation.
|
||||||
|
* @author KenM, Zoey76
|
||||||
*/
|
*/
|
||||||
public class ExDuelReady extends L2GameServerPacket
|
public class ExDuelReady extends L2GameServerPacket
|
||||||
{
|
{
|
||||||
private final int _unk1;
|
public static final ExDuelReady PLAYER_DUEL = new ExDuelReady(false);
|
||||||
|
public static final ExDuelReady PARTY_DUEL = new ExDuelReady(true);
|
||||||
|
|
||||||
public ExDuelReady(int unk1)
|
private final boolean _partyDuel;
|
||||||
|
|
||||||
|
public ExDuelReady(boolean partyDuel)
|
||||||
{
|
{
|
||||||
_unk1 = unk1;
|
_partyDuel = partyDuel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -36,6 +40,6 @@ public class ExDuelReady extends L2GameServerPacket
|
|||||||
writeC(0xFE);
|
writeC(0xFE);
|
||||||
writeH(0x4E);
|
writeH(0x4E);
|
||||||
|
|
||||||
writeD(_unk1);
|
writeD(_partyDuel ? 1 : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,15 +19,19 @@
|
|||||||
package com.l2jserver.gameserver.network.serverpackets;
|
package com.l2jserver.gameserver.network.serverpackets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author KenM
|
* Duel Start packet implementation.
|
||||||
|
* @author KenM, Zoey76
|
||||||
*/
|
*/
|
||||||
public class ExDuelStart extends L2GameServerPacket
|
public class ExDuelStart extends L2GameServerPacket
|
||||||
{
|
{
|
||||||
private final int _unk1;
|
public static final ExDuelReady PLAYER_DUEL = new ExDuelReady(false);
|
||||||
|
public static final ExDuelReady PARTY_DUEL = new ExDuelReady(true);
|
||||||
|
|
||||||
public ExDuelStart(int unk1)
|
private final boolean _partyDuel;
|
||||||
|
|
||||||
|
public ExDuelStart(boolean partyDuel)
|
||||||
{
|
{
|
||||||
_unk1 = unk1;
|
_partyDuel = partyDuel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -36,6 +40,6 @@ public class ExDuelStart extends L2GameServerPacket
|
|||||||
writeC(0xFE);
|
writeC(0xFE);
|
||||||
writeH(0x4F);
|
writeH(0x4F);
|
||||||
|
|
||||||
writeD(_unk1);
|
writeD(_partyDuel ? 1 : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import com.l2jserver.gameserver.model.Location;
|
import com.l2jserver.gameserver.model.Location;
|
||||||
import com.l2jserver.gameserver.model.actor.L2Character;
|
import com.l2jserver.gameserver.model.actor.L2Character;
|
||||||
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
|
|
||||||
import com.l2jserver.gameserver.model.interfaces.IPositionable;
|
import com.l2jserver.gameserver.model.interfaces.IPositionable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,16 +49,7 @@ public final class MagicSkillUse extends L2GameServerPacket
|
|||||||
_skillLevel = skillLevel;
|
_skillLevel = skillLevel;
|
||||||
_hitTime = hitTime;
|
_hitTime = hitTime;
|
||||||
_reuseDelay = reuseDelay;
|
_reuseDelay = reuseDelay;
|
||||||
Location skillWorldPos = null;
|
_groundLocations = cha.isPlayer() && (cha.getActingPlayer().getCurrentSkillWorldPosition() != null) ? Arrays.asList(cha.getActingPlayer().getCurrentSkillWorldPosition()) : Collections.<Location> emptyList();
|
||||||
if (cha.isPlayer())
|
|
||||||
{
|
|
||||||
final L2PcInstance player = cha.getActingPlayer();
|
|
||||||
if (player.getCurrentSkillWorldPosition() != null)
|
|
||||||
{
|
|
||||||
skillWorldPos = player.getCurrentSkillWorldPosition();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_groundLocations = skillWorldPos != null ? Arrays.asList(skillWorldPos) : Collections.<Location> emptyList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MagicSkillUse(L2Character cha, int skillId, int skillLevel, int hitTime, int reuseDelay)
|
public MagicSkillUse(L2Character cha, int skillId, int skillLevel, int hitTime, int reuseDelay)
|
||||||
|
Reference in New Issue
Block a user