/*
* Copyright (C) 2004-2015 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* L2J Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package com.l2jserver.gameserver.network.clientpackets;
import java.util.Arrays;
import com.l2jserver.Config;
import com.l2jserver.gameserver.ai.CtrlEvent;
import com.l2jserver.gameserver.ai.CtrlIntention;
import com.l2jserver.gameserver.ai.L2SummonAI;
import com.l2jserver.gameserver.ai.NextAction;
import com.l2jserver.gameserver.data.sql.impl.SummonSkillsTable;
import com.l2jserver.gameserver.data.xml.impl.PetDataTable;
import com.l2jserver.gameserver.datatables.BotReportTable;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.enums.MountType;
import com.l2jserver.gameserver.enums.PrivateStoreType;
import com.l2jserver.gameserver.instancemanager.AirShipManager;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.actor.L2Summon;
import com.l2jserver.gameserver.model.actor.instance.L2BabyPetInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.actor.instance.L2PetInstance;
import com.l2jserver.gameserver.model.actor.instance.L2SiegeFlagInstance;
import com.l2jserver.gameserver.model.actor.instance.L2StaticObjectInstance;
import com.l2jserver.gameserver.model.effects.AbstractEffect;
import com.l2jserver.gameserver.model.effects.L2EffectType;
import com.l2jserver.gameserver.model.skills.AbnormalType;
import com.l2jserver.gameserver.model.skills.BuffInfo;
import com.l2jserver.gameserver.network.NpcStringId;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
import com.l2jserver.gameserver.network.serverpackets.ChairSit;
import com.l2jserver.gameserver.network.serverpackets.ExAskCoupleAction;
import com.l2jserver.gameserver.network.serverpackets.ExBasicActionList;
import com.l2jserver.gameserver.network.serverpackets.NpcSay;
import com.l2jserver.gameserver.network.serverpackets.RecipeShopManageList;
import com.l2jserver.gameserver.network.serverpackets.SocialAction;
import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
import com.l2jserver.gameserver.taskmanager.AttackStanceTaskManager;
import com.l2jserver.util.Rnd;
/**
* This class manages the action use request packet.
* @author Zoey76
*/
public final class RequestActionUse extends L2GameClientPacket
{
private static final String _C__56_REQUESTACTIONUSE = "[C] 56 RequestActionUse";
private static final int SIN_EATER_ID = 12564;
private static final int SWITCH_STANCE_ID = 6054;
private static final NpcStringId[] NPC_STRINGS =
{
NpcStringId.USING_A_SPECIAL_SKILL_HERE_COULD_TRIGGER_A_BLOODBATH,
NpcStringId.HEY_WHAT_DO_YOU_EXPECT_OF_ME,
NpcStringId.UGGGGGH_PUSH_ITS_NOT_COMING_OUT,
NpcStringId.AH_I_MISSED_THE_MARK
};
private int _actionId;
private boolean _ctrlPressed;
private boolean _shiftPressed;
@Override
protected void readImpl()
{
_actionId = readD();
_ctrlPressed = (readD() == 1);
_shiftPressed = (readC() == 1);
}
@Override
protected void runImpl()
{
final L2PcInstance activeChar = getActiveChar();
if (activeChar == null)
{
return;
}
if (Config.DEBUG)
{
_log.info(getType() + ": " + activeChar + " requested action use ID: " + _actionId + " Ctrl pressed:" + _ctrlPressed + " Shift pressed:" + _shiftPressed);
}
// Don't do anything if player is dead or confused
if ((activeChar.isFakeDeath() && (_actionId != 0)) || activeChar.isDead() || activeChar.isOutOfControl())
{
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
final BuffInfo info = activeChar.getEffectList().getBuffInfoByAbnormalType(AbnormalType.BOT_PENALTY);
if (info != null)
{
for (AbstractEffect effect : info.getEffects())
{
if (!effect.checkCondition(_actionId))
{
activeChar.sendPacket(SystemMessageId.YOU_HAVE_BEEN_REPORTED_SO_ACTIONS_NOT_ALLOWED);
activeChar.sendPacket(ActionFailed.STATIC_PACKET);
return;
}
}
}
// Don't allow to do some action if player is transformed
if (activeChar.isTransformed())
{
int[] allowedActions = activeChar.isTransformed() ? ExBasicActionList.ACTIONS_ON_TRANSFORM : ExBasicActionList.DEFAULT_ACTION_LIST;
if (!(Arrays.binarySearch(allowedActions, _actionId) >= 0))
{
sendPacket(ActionFailed.STATIC_PACKET);
_log.warning("Player " + activeChar + " used action which he does not have! Id = " + _actionId + " transform: " + activeChar.getTransformation());
return;
}
}
final L2Summon summon = activeChar.getSummon();
final L2Object target = activeChar.getTarget();
switch (_actionId)
{
case 0: // Sit/Stand
if (activeChar.isSitting() || !activeChar.isMoving() || activeChar.isFakeDeath())
{
useSit(activeChar, target);
}
else
{
// Sit when arrive using next action.
// Creating next action class.
final NextAction nextAction = new NextAction(CtrlEvent.EVT_ARRIVED, CtrlIntention.AI_INTENTION_MOVE_TO, () -> useSit(activeChar, target));
// Binding next action to AI.
activeChar.getAI().setNextAction(nextAction);
}
break;
case 1: // Walk/Run
if (activeChar.isRunning())
{
activeChar.setWalking();
}
else
{
activeChar.setRunning();
}
break;
case 10: // Private Store - Sell
activeChar.tryOpenPrivateSellStore(false);
break;
case 15: // Change Movement Mode (Pets)
if (validateSummon(summon, true))
{
((L2SummonAI) summon.getAI()).notifyFollowStatusChange();
}
break;
case 16: // Attack (Pets)
if (validateSummon(summon, true))
{
if (summon.canAttack(_ctrlPressed))
{
summon.doAttack();
}
}
break;
case 17: // Stop (Pets)
if (validateSummon(summon, true))
{
summon.cancelAction();
}
break;
case 19: // Unsummon Pet
if (!validateSummon(summon, true))
{
break;
}
if (summon.isDead())
{
sendPacket(SystemMessageId.DEAD_PET_CANNOT_BE_RETURNED);
break;
}
if (summon.isAttackingNow() || summon.isInCombat() || summon.isMovementDisabled())
{
sendPacket(SystemMessageId.PET_CANNOT_SENT_BACK_DURING_BATTLE);
break;
}
if (summon.isHungry())
{
if (summon.isPet() && !((L2PetInstance) summon).getPetData().getFood().isEmpty())
{
sendPacket(SystemMessageId.YOU_CANNOT_RESTORE_HUNGRY_PETS);
}
else
{
sendPacket(SystemMessageId.THE_HELPER_PET_CANNOT_BE_RETURNED);
}
break;
}
summon.unSummon(activeChar);
break;
case 21: // Change Movement Mode (Servitors)
if (validateSummon(summon, false))
{
((L2SummonAI) summon.getAI()).notifyFollowStatusChange();
}
break;
case 22: // Attack (Servitors)
if (validateSummon(summon, false))
{
if (summon.canAttack(_ctrlPressed))
{
summon.doAttack();
}
}
break;
case 23: // Stop (Servitors)
if (validateSummon(summon, false))
{
summon.cancelAction();
}
break;
case 28: // Private Store - Buy
activeChar.tryOpenPrivateBuyStore();
break;
case 32: // Wild Hog Cannon - Wild Cannon
useSkill(4230, false);
break;
case 36: // Soulless - Toxic Smoke
useSkill(4259, false);
break;
case 37: // Dwarven Manufacture
if (activeChar.isAlikeDead())
{
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (activeChar.getPrivateStoreType() != PrivateStoreType.NONE)
{
activeChar.setPrivateStoreType(PrivateStoreType.NONE);
activeChar.broadcastUserInfo();
}
if (activeChar.isSitting())
{
activeChar.standUp();
}
sendPacket(new RecipeShopManageList(activeChar, true));
break;
case 38: // Mount/Dismount
activeChar.mountPlayer(summon);
break;
case 39: // Soulless - Parasite Burst
useSkill(4138, false);
break;
case 41: // Wild Hog Cannon - Attack
if (validateSummon(summon, false))
{
if ((target != null) && (target.isDoor() || (target instanceof L2SiegeFlagInstance)))
{
useSkill(4230, false);
}
else
{
sendPacket(SystemMessageId.INCORRECT_TARGET);
}
}
break;
case 42: // Kai the Cat - Self Damage Shield
useSkill(4378, activeChar, false);
break;
case 43: // Unicorn Merrow - Hydro Screw
useSkill(4137, false);
break;
case 44: // Big Boom - Boom Attack
useSkill(4139, false);
break;
case 45: // Unicorn Boxer - Master Recharge
useSkill(4025, activeChar, false);
break;
case 46: // Mew the Cat - Mega Storm Strike
useSkill(4261, false);
break;
case 47: // Silhouette - Steal Blood
useSkill(4260, false);
break;
case 48: // Mechanic Golem - Mech. Cannon
useSkill(4068, false);
break;
case 51: // General Manufacture
// Player shouldn't be able to set stores if he/she is alike dead (dead or fake death)
if (activeChar.isAlikeDead())
{
sendPacket(ActionFailed.STATIC_PACKET);
return;
}
if (activeChar.getPrivateStoreType() != PrivateStoreType.NONE)
{
activeChar.setPrivateStoreType(PrivateStoreType.NONE);
activeChar.broadcastUserInfo();
}
if (activeChar.isSitting())
{
activeChar.standUp();
}
sendPacket(new RecipeShopManageList(activeChar, false));
break;
case 52: // Unsummon Servitor
if (validateSummon(summon, false))
{
if (summon.isAttackingNow() || summon.isInCombat())
{
sendPacket(SystemMessageId.SERVITOR_NOT_RETURN_IN_BATTLE);
break;
}
summon.unSummon(activeChar);
}
break;
case 53: // Move to target (Servitors)
if (validateSummon(summon, false))
{
if ((target != null) && (summon != target) && !summon.isMovementDisabled())
{
summon.setFollowStatus(false);
summon.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, target.getLocation());
}
}
break;
case 54: // Move to target (Pets)
if (validateSummon(summon, true))
{
if ((target != null) && (summon != target) && !summon.isMovementDisabled())
{
summon.setFollowStatus(false);
summon.getAI().setIntention(CtrlIntention.AI_INTENTION_MOVE_TO, target.getLocation());
}
}
break;
case 61: // Private Store Package Sell
activeChar.tryOpenPrivateSellStore(true);
break;
case 65: // Bot Report Button
if (Config.BOTREPORT_ENABLE)
{
BotReportTable.getInstance().reportBot(activeChar);
}
else
{
activeChar.sendMessage("This feature is disabled.");
}
break;
case 67: // Steer
if (activeChar.isInAirShip())
{
if (activeChar.getAirShip().setCaptain(activeChar))
{
activeChar.broadcastUserInfo();
}
}
break;
case 68: // Cancel Control
if (activeChar.isInAirShip() && activeChar.getAirShip().isCaptain(activeChar))
{
if (activeChar.getAirShip().setCaptain(null))
{
activeChar.broadcastUserInfo();
}
}
break;
case 69: // Destination Map
AirShipManager.getInstance().sendAirShipTeleportList(activeChar);
break;
case 70: // Exit Airship
if (activeChar.isInAirShip())
{
if (activeChar.getAirShip().isCaptain(activeChar))
{
if (activeChar.getAirShip().setCaptain(null))
{
activeChar.broadcastUserInfo();
}
}
else if (activeChar.getAirShip().isInDock())
{
activeChar.getAirShip().oustPlayer(activeChar);
}
}
break;
case 71:
case 72:
case 73:
useCoupleSocial(_actionId - 55);
break;
case 1000: // Siege Golem - Siege Hammer
if ((target != null) && target.isDoor())
{
useSkill(4079, false);
}
break;
case 1001: // Sin Eater - Ultimate Bombastic Buster
if (validateSummon(summon, true) && (summon.getId() == SIN_EATER_ID))
{
summon.broadcastPacket(new NpcSay(summon.getObjectId(), Say2.NPC_ALL, summon.getId(), NPC_STRINGS[Rnd.get(NPC_STRINGS.length)]));
}
break;
case 1003: // Wind Hatchling/Strider - Wild Stun
useSkill(4710, true);
break;
case 1004: // Wind Hatchling/Strider - Wild Defense
useSkill(4711, activeChar, true);
break;
case 1005: // Star Hatchling/Strider - Bright Burst
useSkill(4712, true);
break;
case 1006: // Star Hatchling/Strider - Bright Heal
useSkill(4713, activeChar, true);
break;
case 1007: // Cat Queen - Blessing of Queen
useSkill(4699, activeChar, false);
break;
case 1008: // Cat Queen - Gift of Queen
useSkill(4700, activeChar, false);
break;
case 1009: // Cat Queen - Cure of Queen
useSkill(4701, false);
break;
case 1010: // Unicorn Seraphim - Blessing of Seraphim
useSkill(4702, activeChar, false);
break;
case 1011: // Unicorn Seraphim - Gift of Seraphim
useSkill(4703, activeChar, false);
break;
case 1012: // Unicorn Seraphim - Cure of Seraphim
useSkill(4704, false);
break;
case 1013: // Nightshade - Curse of Shade
useSkill(4705, false);
break;
case 1014: // Nightshade - Mass Curse of Shade
useSkill(4706, false);
break;
case 1015: // Nightshade - Shade Sacrifice
useSkill(4707, false);
break;
case 1016: // Cursed Man - Cursed Blow
useSkill(4709, false);
break;
case 1017: // Cursed Man - Cursed Strike/Stun
useSkill(4708, false);
break;
case 1031: // Feline King - Slash
useSkill(5135, false);
break;
case 1032: // Feline King - Spinning Slash
useSkill(5136, false);
break;
case 1033: // Feline King - Grip of the Cat
useSkill(5137, false);
break;
case 1034: // Magnus the Unicorn - Whiplash
useSkill(5138, false);
break;
case 1035: // Magnus the Unicorn - Tridal Wave
useSkill(5139, false);
break;
case 1036: // Spectral Lord - Corpse Kaboom
useSkill(5142, false);
break;
case 1037: // Spectral Lord - Dicing Death
useSkill(5141, false);
break;
case 1038: // Spectral Lord - Force Curse
useSkill(5140, false);
break;
case 1039: // Swoop Cannon - Cannon Fodder
if ((target != null) && target.isDoor())
{
useSkill(5110, false);
}
break;
case 1040: // Swoop Cannon - Big Bang
if ((target != null) && target.isDoor())
{
useSkill(5111, false);
}
break;
case 1041: // Great Wolf - Bite Attack
useSkill(5442, true);
break;
case 1042: // Great Wolf - Maul
useSkill(5444, true);
break;
case 1043: // Great Wolf - Cry of the Wolf
useSkill(5443, true);
break;
case 1044: // Great Wolf - Awakening
useSkill(5445, true);
break;
case 1045: // Great Wolf - Howl
useSkill(5584, true);
break;
case 1046: // Strider - Roar
useSkill(5585, true);
break;
case 1047: // Divine Beast - Bite
useSkill(5580, false);
break;
case 1048: // Divine Beast - Stun Attack
useSkill(5581, false);
break;
case 1049: // Divine Beast - Fire Breath
useSkill(5582, false);
break;
case 1050: // Divine Beast - Roar
useSkill(5583, false);
break;
case 1051: // Feline Queen - Bless The Body
useSkill(5638, false);
break;
case 1052: // Feline Queen - Bless The Soul
useSkill(5639, false);
break;
case 1053: // Feline Queen - Haste
useSkill(5640, false);
break;
case 1054: // Unicorn Seraphim - Acumen
useSkill(5643, false);
break;
case 1055: // Unicorn Seraphim - Clarity
useSkill(5647, false);
break;
case 1056: // Unicorn Seraphim - Empower
useSkill(5648, false);
break;
case 1057: // Unicorn Seraphim - Wild Magic
useSkill(5646, false);
break;
case 1058: // Nightshade - Death Whisper
useSkill(5652, false);
break;
case 1059: // Nightshade - Focus
useSkill(5653, false);
break;
case 1060: // Nightshade - Guidance
useSkill(5654, false);
break;
case 1061: // Wild Beast Fighter, White Weasel - Death blow
useSkill(5745, true);
break;
case 1062: // Wild Beast Fighter - Double attack
useSkill(5746, true);
break;
case 1063: // Wild Beast Fighter - Spin attack
useSkill(5747, true);
break;
case 1064: // Wild Beast Fighter - Meteor Shower
useSkill(5748, true);
break;
case 1065: // Fox Shaman, Wild Beast Fighter, White Weasel, Fairy Princess - Awakening
useSkill(5753, true);
break;
case 1066: // Fox Shaman, Spirit Shaman - Thunder Bolt
useSkill(5749, true);
break;
case 1067: // Fox Shaman, Spirit Shaman - Flash
useSkill(5750, true);
break;
case 1068: // Fox Shaman, Spirit Shaman - Lightning Wave
useSkill(5751, true);
break;
case 1069: // Fox Shaman, Fairy Princess - Flare
useSkill(5752, true);
break;
case 1070: // White Weasel, Fairy Princess, Improved Baby Buffalo, Improved Baby Kookaburra, Improved Baby Cougar, Spirit Shaman, Toy Knight, Turtle Ascetic - Buff control
useSkill(5771, true);
break;
case 1071: // Tigress - Power Strike
useSkill(5761, true);
break;
case 1072: // Toy Knight - Piercing attack
useSkill(6046, true);
break;
case 1073: // Toy Knight - Whirlwind
useSkill(6047, true);
break;
case 1074: // Toy Knight - Lance Smash
useSkill(6048, true);
break;
case 1075: // Toy Knight - Battle Cry
useSkill(6049, true);
break;
case 1076: // Turtle Ascetic - Power Smash
useSkill(6050, true);
break;
case 1077: // Turtle Ascetic - Energy Burst
useSkill(6051, true);
break;
case 1078: // Turtle Ascetic - Shockwave
useSkill(6052, true);
break;
case 1079: // Turtle Ascetic - Howl
useSkill(6053, true);
break;
case 1080: // Phoenix Rush
useSkill(6041, false);
break;
case 1081: // Phoenix Cleanse
useSkill(6042, false);
break;
case 1082: // Phoenix Flame Feather
useSkill(6043, false);
break;
case 1083: // Phoenix Flame Beak
useSkill(6044, false);
break;
case 1084: // Switch State
if (summon instanceof L2BabyPetInstance)
{
useSkill(6054, true);
}
break;
case 1086: // Panther Cancel
useSkill(6094, false);
break;
case 1087: // Panther Dark Claw
useSkill(6095, false);
break;
case 1088: // Panther Fatal Claw
useSkill(6096, false);
break;
case 1089: // Deinonychus - Tail Strike
useSkill(6199, true);
break;
case 1090: // Guardian's Strider - Strider Bite
useSkill(6205, true);
break;
case 1091: // Guardian's Strider - Strider Fear
useSkill(6206, true);
break;
case 1092: // Guardian's Strider - Strider Dash
useSkill(6207, true);
break;
case 1093: // Maguen - Maguen Strike
useSkill(6618, true);
break;
case 1094: // Maguen - Maguen Wind Walk
useSkill(6681, true);
break;
case 1095: // Elite Maguen - Maguen Power Strike
useSkill(6619, true);
break;
case 1096: // Elite Maguen - Elite Maguen Wind Walk
useSkill(6682, true);
break;
case 1097: // Maguen - Maguen Return
useSkill(6683, true);
break;
case 1098: // Elite Maguen - Maguen Party Return
useSkill(6684, true);
break;
case 5000: // Baby Rudolph - Reindeer Scratch
useSkill(23155, true);
break;
case 5001: // Deseloph, Hyum, Rekang, Lilias, Lapham, Mafum - Rosy Seduction
useSkill(23167, true);
break;
case 5002: // Deseloph, Hyum, Rekang, Lilias, Lapham, Mafum - Critical Seduction
useSkill(23168, true);
break;
case 5003: // Hyum, Lapham, Hyum, Lapham - Thunder Bolt
useSkill(5749, true);
break;
case 5004: // Hyum, Lapham, Hyum, Lapham - Flash
useSkill(5750, true);
break;
case 5005: // Hyum, Lapham, Hyum, Lapham - Lightning Wave
useSkill(5751, true);
break;
case 5006: // Deseloph, Hyum, Rekang, Lilias, Lapham, Mafum, Deseloph, Hyum, Rekang, Lilias, Lapham, Mafum - Buff Control
useSkill(5771, true);
break;
case 5007: // Deseloph, Lilias, Deseloph, Lilias - Piercing Attack
useSkill(6046, true);
break;
case 5008: // Deseloph, Lilias, Deseloph, Lilias - Spin Attack
useSkill(6047, true);
break;
case 5009: // Deseloph, Lilias, Deseloph, Lilias - Smash
useSkill(6048, true);
break;
case 5010: // Deseloph, Lilias, Deseloph, Lilias - Ignite
useSkill(6049, true);
break;
case 5011: // Rekang, Mafum, Rekang, Mafum - Power Smash
useSkill(6050, true);
break;
case 5012: // Rekang, Mafum, Rekang, Mafum - Energy Burst
useSkill(6051, true);
break;
case 5013: // Rekang, Mafum, Rekang, Mafum - Shockwave
useSkill(6052, true);
break;
case 5014: // Rekang, Mafum, Rekang, Mafum - Ignite
useSkill(6053, true);
break;
case 5015: // Deseloph, Hyum, Rekang, Lilias, Lapham, Mafum, Deseloph, Hyum, Rekang, Lilias, Lapham, Mafum - Switch Stance
useSkill(6054, true);
break;
// Social Packets
case 12: // Greeting
tryBroadcastSocial(2);
break;
case 13: // Victory
tryBroadcastSocial(3);
break;
case 14: // Advance
tryBroadcastSocial(4);
break;
case 24: // Yes
tryBroadcastSocial(6);
break;
case 25: // No
tryBroadcastSocial(5);
break;
case 26: // Bow
tryBroadcastSocial(7);
break;
case 29: // Unaware
tryBroadcastSocial(8);
break;
case 30: // Social Waiting
tryBroadcastSocial(9);
break;
case 31: // Laugh
tryBroadcastSocial(10);
break;
case 33: // Applaud
tryBroadcastSocial(11);
break;
case 34: // Dance
tryBroadcastSocial(12);
break;
case 35: // Sorrow
tryBroadcastSocial(13);
break;
case 62: // Charm
tryBroadcastSocial(14);
break;
case 66: // Shyness
tryBroadcastSocial(15);
break;
default:
_log.warning(activeChar.getName() + ": unhandled action type " + _actionId);
break;
}
}
/**
* Use the sit action.
* @param activeChar the player trying to sit
* @param target the target to sit, throne, bench or chair
* @return {@code true} if the player can sit, {@code false} otherwise
*/
protected boolean useSit(L2PcInstance activeChar, L2Object target)
{
if (activeChar.getMountType() != MountType.NONE)
{
return false;
}
if (!activeChar.isSitting() && (target instanceof L2StaticObjectInstance) && (((L2StaticObjectInstance) target).getType() == 1) && activeChar.isInsideRadius(target, L2StaticObjectInstance.INTERACTION_DISTANCE, false, false))
{
final ChairSit cs = new ChairSit(activeChar, target.getId());
sendPacket(cs);
activeChar.sitDown();
activeChar.broadcastPacket(cs);
return true;
}
if (activeChar.isFakeDeath())
{
activeChar.stopEffects(L2EffectType.FAKE_DEATH);
}
else if (activeChar.isSitting())
{
activeChar.standUp();
}
else
{
activeChar.sitDown();
}
return true;
}
/**
* Cast a skill for active summon.
* Target is specified as a parameter but can be overwrited or ignored depending on skill type.
* @param skillId the skill Id to be casted by the summon
* @param target the target to cast the skill on, overwritten or ignored depending on skill type
* @param pet if {@code true} it'll validate a pet, if {@code false} it will validate a servitor
*/
private void useSkill(int skillId, L2Object target, boolean pet)
{
final L2PcInstance activeChar = getActiveChar();
if (activeChar == null)
{
return;
}
final L2Summon summon = activeChar.getSummon();
if (!validateSummon(summon, pet))
{
return;
}
if (summon instanceof L2BabyPetInstance)
{
if (!((L2BabyPetInstance) summon).isInSupportMode())
{
sendPacket(SystemMessageId.PET_AUXILIARY_MODE_CANNOT_USE_SKILLS);
return;
}
}
int lvl = 0;
if (summon.isPet())
{
if ((summon.getLevel() - activeChar.getLevel()) > 20)
{
sendPacket(SystemMessageId.PET_TOO_HIGH_TO_CONTROL);
return;
}
lvl = PetDataTable.getInstance().getPetData(summon.getId()).getAvailableLevel(skillId, summon.getLevel());
}
else
{
lvl = SummonSkillsTable.getInstance().getAvailableLevel(summon, skillId);
}
if (lvl > 0)
{
summon.setTarget(target);
summon.useMagic(SkillData.getInstance().getSkill(skillId, lvl), _ctrlPressed, _shiftPressed);
}
if (skillId == SWITCH_STANCE_ID)
{
summon.switchMode();
}
}
/**
* Cast a skill for active summon.
* Target is retrieved from owner's target, then validated by overloaded method useSkill(int, L2Character).
* @param skillId the skill Id to use
* @param pet if {@code true} it'll validate a pet, if {@code false} it will validate a servitor
*/
private void useSkill(int skillId, boolean pet)
{
final L2PcInstance activeChar = getActiveChar();
if (activeChar == null)
{
return;
}
useSkill(skillId, activeChar.getTarget(), pet);
}
/**
* Validates the given summon and sends a system message to the master.
* @param summon the summon to validate
* @param checkPet if {@code true} it'll validate a pet, if {@code false} it will validate a servitor
* @return {@code true} if the summon is not null and whether is a pet or a servitor depending on {@code checkPet} value, {@code false} otherwise
*/
private boolean validateSummon(L2Summon summon, boolean checkPet)
{
if ((summon != null) && ((checkPet && summon.isPet()) || summon.isServitor()))
{
if (summon.isPet() && ((L2PetInstance) summon).isUncontrollable())
{
sendPacket(SystemMessageId.WHEN_YOUR_PETS_HUNGER_GAUGE_IS_AT_0_YOU_CANNOT_USE_YOUR_PET);
return false;
}
if (summon.isBetrayed())
{
sendPacket(SystemMessageId.PET_REFUSING_ORDER);
return false;
}
return true;
}
if (checkPet)
{
sendPacket(SystemMessageId.DONT_HAVE_PET);
}
else
{
sendPacket(SystemMessageId.DONT_HAVE_SERVITOR);
}
return false;
}
/**
* Try to broadcast SocialAction packet.
* @param id the social action Id to broadcast
*/
private void tryBroadcastSocial(int id)
{
final L2PcInstance activeChar = getActiveChar();
if (activeChar == null)
{
return;
}
if (activeChar.isFishing())
{
sendPacket(SystemMessageId.CANNOT_DO_WHILE_FISHING_3);
return;
}
if (activeChar.canMakeSocialAction())
{
activeChar.broadcastPacket(new SocialAction(activeChar.getObjectId(), id));
}
}
/**
* Perform a couple social action.
* @param id the couple social action Id
*/
private void useCoupleSocial(final int id)
{
final L2PcInstance requester = getActiveChar();
if (requester == null)
{
return;
}
final L2Object target = requester.getTarget();
if ((target == null) || !target.isPlayer())
{
sendPacket(SystemMessageId.INCORRECT_TARGET);
return;
}
final int distance = (int) requester.calculateDistance(target, false, false);
if ((distance > 125) || (distance < 15) || (requester.getObjectId() == target.getObjectId()))
{
sendPacket(SystemMessageId.TARGET_DO_NOT_MEET_LOC_REQUIREMENTS);
return;
}
SystemMessage sm;
if (requester.isInStoreMode() || requester.isInCraftMode())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_PRIVATE_SHOP_MODE_OR_IN_A_BATTLE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(requester);
sendPacket(sm);
return;
}
if (requester.isInCombat() || requester.isInDuel() || AttackStanceTaskManager.getInstance().hasAttackStanceTask(requester))
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_BATTLE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(requester);
sendPacket(sm);
return;
}
if (requester.isFishing())
{
sendPacket(SystemMessageId.CANNOT_DO_WHILE_FISHING_3);
return;
}
if (requester.getKarma() > 0)
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_CHAOTIC_STATE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(requester);
sendPacket(sm);
return;
}
if (requester.isInOlympiadMode())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_PARTICIPATING_IN_THE_OLYMPIAD_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(requester);
sendPacket(sm);
return;
}
if (requester.isInSiege())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_CASTLE_SIEGE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(requester);
sendPacket(sm);
return;
}
if (requester.isInHideoutSiege())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_PARTICIPATING_IN_A_HIDEOUT_SIEGE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(requester);
sendPacket(sm);
}
if (requester.isMounted() || requester.isFlyingMounted() || requester.isInBoat() || requester.isInAirShip())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_RIDING_A_SHIP_STEED_OR_STRIDER_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(requester);
sendPacket(sm);
return;
}
if (requester.isTransformed())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_CURRENTLY_TRANSFORMING_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(requester);
sendPacket(sm);
return;
}
if (requester.isAlikeDead())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_CURRENTLY_DEAD_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(requester);
sendPacket(sm);
return;
}
// Checks for partner.
final L2PcInstance partner = target.getActingPlayer();
if (partner.isInStoreMode() || partner.isInCraftMode())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_PRIVATE_SHOP_MODE_OR_IN_A_BATTLE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (partner.isInCombat() || partner.isInDuel() || AttackStanceTaskManager.getInstance().hasAttackStanceTask(partner))
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_BATTLE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (partner.getMultiSociaAction() > 0)
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_ALREADY_PARTICIPATING_IN_A_COUPLE_ACTION_AND_CANNOT_BE_REQUESTED_FOR_ANOTHER_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (partner.isFishing())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_FISHING_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (partner.getKarma() > 0)
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_CHAOTIC_STATE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (partner.isInOlympiadMode())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_PARTICIPATING_IN_THE_OLYMPIAD_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (partner.isInHideoutSiege())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_PARTICIPATING_IN_A_HIDEOUT_SIEGE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (partner.isInSiege())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_IN_A_CASTLE_SIEGE_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (partner.isMounted() || partner.isFlyingMounted() || partner.isInBoat() || partner.isInAirShip())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_RIDING_A_SHIP_STEED_OR_STRIDER_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (partner.isTeleporting())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_CURRENTLY_TELEPORTING_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (partner.isTransformed())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_CURRENTLY_TRANSFORMING_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (partner.isAlikeDead())
{
sm = SystemMessage.getSystemMessage(SystemMessageId.C1_IS_CURRENTLY_DEAD_AND_CANNOT_BE_REQUESTED_FOR_A_COUPLE_ACTION);
sm.addPcName(partner);
sendPacket(sm);
return;
}
if (requester.isAllSkillsDisabled() || partner.isAllSkillsDisabled())
{
sendPacket(SystemMessageId.COUPLE_ACTION_CANCELED);
return;
}
requester.setMultiSocialAction(id, partner.getObjectId());
sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_REQUESTED_COUPLE_ACTION_C1);
sm.addPcName(partner);
sendPacket(sm);
if ((requester.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE) || (partner.getAI().getIntention() != CtrlIntention.AI_INTENTION_IDLE))
{
final NextAction nextAction = new NextAction(CtrlEvent.EVT_ARRIVED, CtrlIntention.AI_INTENTION_MOVE_TO, () -> partner.sendPacket(new ExAskCoupleAction(requester.getObjectId(), id)));
requester.getAI().setNextAction(nextAction);
return;
}
if (requester.isCastingNow() || requester.isCastingSimultaneouslyNow())
{
final NextAction nextAction = new NextAction(CtrlEvent.EVT_FINISH_CASTING, CtrlIntention.AI_INTENTION_CAST, () -> partner.sendPacket(new ExAskCoupleAction(requester.getObjectId(), id)));
requester.getAI().setNextAction(nextAction);
return;
}
partner.sendPacket(new ExAskCoupleAction(requester.getObjectId(), id));
}
@Override
public String getType()
{
return _C__56_REQUESTACTIONUSE;
}
@Override
protected boolean triggersOnActionRequest()
{
return (_actionId != 10) && (_actionId != 28);
}
}