Sync with L2jServer HighFive Oct 2nd 2015.

This commit is contained in:
MobiusDev
2015-10-03 13:41:08 +00:00
parent c90d8eb135
commit 7259087da5
18 changed files with 469 additions and 602 deletions

View File

@@ -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
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@@ -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());
} }

View File

@@ -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
{ {

View File

@@ -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;

View File

@@ -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);

View File

@@ -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"))

View File

@@ -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;

View File

@@ -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;

View File

@@ -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.
*/ */

View File

@@ -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();
} }
/** /**

View File

@@ -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);
} }

View File

@@ -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)
{ {

View File

@@ -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()

View File

@@ -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);

View File

@@ -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);
} }
} }

View File

@@ -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);
} }
} }

View File

@@ -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);
} }
} }

View File

@@ -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)