Help Fixing Swoop Cannon Skills.
Posted: Wed Nov 04, 2015 2:06 am
Referring to this topic viewtopic.php?f=94&t=30429&start=105
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.
2) Addition to MagicSkillUse.java - another method, with slightly different arguments, to further consistent info as per linked topic (above), i.e. writeLoc(_activeChar) is same coordinates as writeLoc(_target), and writeH(_groundLocations) only sends 1 coordinate, because the array only consists of aimLoc variable and has size 1.
3) Changes to RequestActionUse.java to allow skill IDs 5110 and 5111 to be casted, nothing special.
4) Additions to L2Character.java - new function getAimPoint() for recalculation of the destination point of the skill (because I cannot pass along this Location through Artillery.java, since it returns type L2Object), as well as an addition of the new version MagicSkillUse packet IF the skillTargetType is ARTILLERY.
AND in beginCast() of L2Character.java new MagicSkillUse
5)All the accomodating XML changes to skill - removal of TEMP HACK fixes to target types and locations, commented out some requirements (itemID use, etc) and changed targetype to ARTILLERY. Pretty basic. I only use 5110 (Cannon Fodder) for testing.
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 ???
What else did I miss?
Did I use the packet correctly?[/b]
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]