Here are the changes I carried out in order to attempt to make the swoop cannon skills work (very crude, not elegant):
1) Added Artillery.java, which collects target list within getAffectLimit radius around a point that is getCastRange distance away from activeChar, in the direction he is facing. Primarily uses same trigonometry calculations as Warp/Blink. Appropriate ENUM - ARTILLERY is created as well.
Code: Select all
/*
* Copyright (C) 2004-2015 L2J DataPack
*
* This file is part of L2J DataPack.
*
* L2J DataPack 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 DataPack 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 <http://www.gnu.org/licenses/>.
*/
package handlers.targethandlers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.l2jserver.gameserver.GeoData;
import com.l2jserver.gameserver.handler.ITargetTypeHandler;
import com.l2jserver.gameserver.model.L2Object;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.model.skills.targets.L2TargetType;
import com.l2jserver.gameserver.model.zone.ZoneId;
import com.l2jserver.gameserver.util.Util;
/**
* @author UnAfraid (Area) This is a directional area attack target handler - a
* circular area offset from the caster is affected. Intended for Swoop
* Cannon skills 5110 5111
*/
public class Artillery implements ITargetTypeHandler {
@Override
public L2Object[] getTargetList(Skill skill, L2Character activeChar,
boolean onlyFirst, L2Character target) {
List<L2Character> targetList = new ArrayList<>();
final double angle = Util.convertHeadingToDegree(activeChar
.getHeading());
final double radian = Math.toRadians(angle);
final double range = skill.getCastRange();
final int x1 = (int) (Math.cos(Math.PI + radian) * range);
final int y1 = (int) (Math.sin(Math.PI + radian) * range);
final boolean srcInArena = (activeChar.isInsideZone(ZoneId.PVP) && !activeChar
.isInsideZone(ZoneId.SIEGE));
int originx = activeChar.getX() + x1;
int originy = activeChar.getY() + y1;
int originz = GeoData.getInstance().getNearestZ(originx, originy,
activeChar.getZ());
Location origin = new Location(originz, originz, originz);
target = activeChar; // dummy?
int maxTargets = skill.getAffectLimit();
final Collection<L2Character> objs = activeChar.getKnownList()
.getKnownCharacters();
for (L2Character obj : objs) {
if (!(obj.isAttackable() || obj.isPlayable())) {
continue;
}
if (skill.getAffectRange() > Util.calculateDistance(origin,
obj.getLocation(), true, false)) {
if (!Skill.checkForAreaOffensiveSkills(activeChar, obj, skill,
srcInArena)) {
continue;
}
if ((maxTargets > 0) && (targetList.size() >= maxTargets)) {
break;
}
targetList.add(obj);
}
}
if (targetList.isEmpty()) {
return EMPTY_TARGET_LIST;
}
return targetList.toArray(new L2Character[targetList.size()]);
}
@Override
public Enum<L2TargetType> getTargetType() {
return L2TargetType.ARTILLERY;
}
}
Code: Select all
/*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.gameserver.network.serverpackets;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.l2jserver.gameserver.model.Location;
import com.l2jserver.gameserver.model.actor.L2Character;
import com.l2jserver.gameserver.model.interfaces.IPositionable;
/**
* MagicSkillUse server packet implementation.
*
* @author UnAfraid, NosBit
*/
public final class MagicSkillUse extends L2GameServerPacket {
private final int _skillId;
private final int _skillLevel;
private final int _hitTime;
private final int _reuseDelay;
private final L2Character _activeChar;
private final L2Character _target;
private final List<Integer> _unknown = Collections.emptyList();
private final List<Location> _groundLocations;
public MagicSkillUse(L2Character cha, L2Character target, int skillId,
int skillLevel, int hitTime, int reuseDelay) {
_activeChar = cha;
_target = target;
_skillId = skillId;
_skillLevel = skillLevel;
_hitTime = hitTime;
_reuseDelay = reuseDelay;
_groundLocations = cha.isPlayer()
&& (cha.getActingPlayer().getCurrentSkillWorldPosition() != null) ? Arrays
.asList(cha.getActingPlayer().getCurrentSkillWorldPosition())
: Collections.<Location> emptyList();
}
// used in L2Character when skill.getTargetType() == L2TargetType.ARTILLERY
public MagicSkillUse(L2Character cha, int skillId, int skillLevel,
int hitTime, int reuseDelay, Location aimLoc) {
_activeChar = cha;
_target = cha;
_skillId = skillId;
_skillLevel = skillLevel;
_hitTime = hitTime;
_reuseDelay = reuseDelay;
_groundLocations = Arrays.asList(aimLoc); // just one location
}
public MagicSkillUse(L2Character cha, int skillId, int skillLevel,
int hitTime, int reuseDelay) {
this(cha, cha, skillId, skillLevel, hitTime, reuseDelay);
}
@Override
protected final void writeImpl() {
writeC(0x48);
writeD(_activeChar.getObjectId());
writeD(_target.getObjectId());
writeD(_skillId);
writeD(_skillLevel);
writeD(_hitTime);
writeD(_reuseDelay);
writeLoc(_activeChar);
writeH(_unknown.size()); // TODO: Implement me!
for (int unknown : _unknown) {
writeH(unknown);
}
writeH(_groundLocations.size());
for (IPositionable target : _groundLocations) {
writeLoc(target);
}
writeLoc(_target);
}
}
Code: Select all
case 1039: // Swoop Cannon - Cannon Fodder
useSkill(5110, false);
break;
case 1040: // Swoop Cannon - Big Bang
useSkill(5111, false);
break;
Code: Select all
// get the point of destination of projectile for Artillery skills. Used
// primarily for 5110 and 5111
public Location getAimPoint(Skill skill, L2Character activeChar) {
final double angle = Util.convertHeadingToDegree(activeChar
.getHeading());
final double radian = Math.toRadians(angle);
final double range = skill.getCastRange();
final int x1 = (int) (Math.cos(Math.PI + radian) * range);
final int y1 = (int) (Math.sin(Math.PI + radian) * range);
int originx = activeChar.getX() + x1;
int originy = activeChar.getY() + y1;
int originz = GeoData.getInstance().getNearestZ(originx, originy,
activeChar.getZ());
Location aimPoint = new Location(originz, originz, originz);
return aimPoint;
}
Code: Select all
// Send a Server->Client packet MagicSkillUser with target, displayId,
// level, skillTime, reuseDelay
// to the L2Character AND to all L2PcInstance in the _KnownPlayers of
// the L2Character
// If the Skill is Artillery TargetType, used different MagicSkillUse
// that gathers the location of projectile destination.
if (skill.getTargetType() == L2TargetType.ARTILLERY) {
final Location aimLoc = getAimPoint(skill, this);
broadcastPacket(new MagicSkillUse(this, skill.getDisplayId(),
skill.getDisplayLevel(), skillTime, reuseDelay, aimLoc));
} else {
broadcastPacket(new MagicSkillUse(this, target,
skill.getDisplayId(), skill.getDisplayLevel(), skillTime,
reuseDelay));
}
Code: Select all
<skill id="5110" levels="1" name="Cannon Fodder">
<!-- Confirmed CT2.5 -->
<!-- Swoop Cannon Skill -->
<set name="affectRange" val="200" />
<set name="castRange" val="1600" />
<set name="effectPoint" val="-100" />
<set name="effectRange" val="1600" />
<set name="hitTime" val="15000" />
<!-- <set name="itemConsumeCount" val="4" /> -->
<!-- <set name="itemConsumeId" val="8872" /> -->
<set name="magicLvl" val="70" />
<set name="operateType" val="A1" />
<set name="power" val="68" />
<set name="reuseDelay" val="10500" />
<set name="rideState" val="NONE" />
<set name="targetType" val="ARTILLERY" />
<cond msgId="113" addName="1">
<not>
<player insideZoneId="51101, 51102, 51103, 51104, 51105, 51106, 51108, 51108, 51109" />
</not>
</cond>
<for>
<effect name="PhysicalAttack" />
</for>
</skill>
So, whats the result?
I've had no compile issues or problems, so that must count for something .
Problem is, when I try to use the abilities ingame, chatlog gives the typical "Target cannot be found" or something message.
Is this because Artillery.java has a clause
Code: Select all
if (targetList.isEmpty()) {
return EMPTY_TARGET_LIST;
What else did I miss?
Did I use the packet correctly?[/b]