/* * This file is part of the L2J Mobius project. * * This program 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. * * This program 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 handlers.effecthandlers; import java.util.logging.Level; import com.l2jmobius.commons.util.Rnd; import com.l2jmobius.gameserver.data.xml.impl.NpcData; import com.l2jmobius.gameserver.model.L2Spawn; import com.l2jmobius.gameserver.model.Location; import com.l2jmobius.gameserver.model.StatsSet; import com.l2jmobius.gameserver.model.actor.L2Character; import com.l2jmobius.gameserver.model.actor.L2Npc; import com.l2jmobius.gameserver.model.actor.instance.L2DecoyInstance; import com.l2jmobius.gameserver.model.actor.instance.L2EffectPointInstance; import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance; import com.l2jmobius.gameserver.model.actor.templates.L2NpcTemplate; import com.l2jmobius.gameserver.model.effects.AbstractEffect; import com.l2jmobius.gameserver.model.effects.L2EffectType; import com.l2jmobius.gameserver.model.items.instance.L2ItemInstance; import com.l2jmobius.gameserver.model.skills.Skill; import com.l2jmobius.gameserver.model.skills.targets.TargetType; /** * Summon Npc effect implementation. * @author Zoey76 */ public final class SummonNpc extends AbstractEffect { private int _despawnDelay; private final int _npcId; private final int _npcCount; private final boolean _randomOffset; private final boolean _isSummonSpawn; private final boolean _singleInstance; // Only one instance of this NPC is allowed. public SummonNpc(StatsSet params) { _despawnDelay = params.getInt("despawnDelay", 20000); _npcId = params.getInt("npcId", 0); _npcCount = params.getInt("npcCount", 1); _randomOffset = params.getBoolean("randomOffset", false); _isSummonSpawn = params.getBoolean("isSummonSpawn", false); _singleInstance = params.getBoolean("singleInstance", false); } @Override public L2EffectType getEffectType() { return L2EffectType.SUMMON_NPC; } @Override public boolean isInstant() { return true; } @Override public void instant(L2Character effector, L2Character effected, Skill skill, L2ItemInstance item) { if (!effected.isPlayer() || effected.isAlikeDead() || effected.getActingPlayer().inObserverMode()) { return; } if ((_npcId <= 0) || (_npcCount <= 0)) { _log.warning(SummonNpc.class.getSimpleName() + ": Invalid NPC ID or count skill ID: " + skill.getId()); return; } final L2PcInstance player = effected.getActingPlayer(); if (player.isMounted()) { return; } final L2NpcTemplate npcTemplate = NpcData.getInstance().getTemplate(_npcId); if (npcTemplate == null) { _log.warning(SummonNpc.class.getSimpleName() + ": Spawn of the nonexisting NPC ID: " + _npcId + ", skill ID:" + skill.getId()); return; } int x = player.getX(); int y = player.getY(); int z = player.getZ(); if (skill.getTargetType() == TargetType.GROUND) { final Location wordPosition = player.getActingPlayer().getCurrentSkillWorldPosition(); if (wordPosition != null) { x = wordPosition.getX(); y = wordPosition.getY(); z = wordPosition.getZ(); } } else { x = effected.getX(); y = effected.getY(); z = effected.getZ(); } if (_randomOffset) { x += (Rnd.nextBoolean() ? Rnd.get(20, 50) : Rnd.get(-50, -20)); y += (Rnd.nextBoolean() ? Rnd.get(20, 50) : Rnd.get(-50, -20)); } switch (npcTemplate.getType()) { case "L2Decoy": { final L2DecoyInstance decoy = new L2DecoyInstance(npcTemplate, player, _despawnDelay); decoy.setCurrentHp(decoy.getMaxHp()); decoy.setCurrentMp(decoy.getMaxMp()); decoy.setHeading(player.getHeading()); decoy.setInstance(player.getInstanceWorld()); decoy.setSummoner(player); decoy.spawnMe(x, y, z); break; } case "L2EffectPoint": // TODO: Implement proper signet skills. { final L2EffectPointInstance effectPoint = new L2EffectPointInstance(npcTemplate, player); effectPoint.setCurrentHp(effectPoint.getMaxHp()); effectPoint.setCurrentMp(effectPoint.getMaxMp()); effectPoint.setIsInvul(true); effectPoint.setSummoner(player); effectPoint.setTitle(player.getName()); effectPoint.spawnMe(x, y, z); _despawnDelay = effectPoint.getParameters().getInt("despawn_time", 0) * 1000; if (_despawnDelay > 0) { effectPoint.scheduleDespawn(_despawnDelay); } break; } default: { L2Spawn spawn; try { spawn = new L2Spawn(npcTemplate); } catch (Exception e) { _log.log(Level.WARNING, SummonNpc.class.getSimpleName() + ": Unable to create spawn. " + e.getMessage(), e); return; } spawn.setX(x); spawn.setY(y); spawn.setZ(z); spawn.setHeading(player.getHeading()); spawn.stopRespawn(); // If only single instance is allowed, delete previous NPCs. if (_singleInstance) { player.getSummonedNpcs().stream().filter(npc -> npc.getId() == _npcId).forEach(npc -> npc.deleteMe()); } final L2Npc npc = spawn.doSpawn(_isSummonSpawn); player.addSummonedNpc(npc); // npc.setSummoner(player); npc.setName(npcTemplate.getName()); npc.setTitle(npcTemplate.getName()); if (_despawnDelay > 0) { npc.scheduleDespawn(_despawnDelay); } npc.setIsRunning(false); // TODO: Fix broadcast info. } } } }