From d473a5c729c57fccf93aea8091b25f94e7969a5e Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Sun, 18 Sep 2016 08:11:02 +0200 Subject: [PATCH 01/21] Fixed lingering thread in TCPServer --- src/resources/network/TCPServer.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/resources/network/TCPServer.java b/src/resources/network/TCPServer.java index 0ee4372f..b3550a5a 100644 --- a/src/resources/network/TCPServer.java +++ b/src/resources/network/TCPServer.java @@ -33,6 +33,7 @@ import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.nio.ByteBuffer; +import java.nio.channels.ClosedByInterruptException; import java.nio.channels.ClosedChannelException; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; @@ -126,6 +127,7 @@ public class TCPServer { public boolean close() { listener.stop(); + callbackExecutor.shutdown(); try { if (channel != null) channel.close(); @@ -267,6 +269,10 @@ public class TCPServer { callbackExecutor.execute(() -> callback.onIncomingData(s.socket(), smaller.array())); return true; } + } catch (ClosedByInterruptException e) { + key.cancel(); + disconnect(s); + stop(); } catch (IOException e) { if (e.getMessage() != null && e.getMessage().toLowerCase(Locale.US).contains("connection reset")) Log.e("TCPServer", "Connection Reset with %s", s.socket().getRemoteSocketAddress()); From 0b3d3694cb21695d14cf6c08c2475024291e4548 Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Sun, 18 Sep 2016 08:16:24 +0200 Subject: [PATCH 02/21] Fixed lingering threads caused by ScheduledUtilities --- src/services/CoreManager.java | 2 ++ src/utilities/ScheduledUtilities.java | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/services/CoreManager.java b/src/services/CoreManager.java index d0a53b29..03bfaa09 100644 --- a/src/services/CoreManager.java +++ b/src/services/CoreManager.java @@ -59,6 +59,7 @@ import resources.server_info.Log.LogLevel; import services.admin.OnlineInterfaceService; import services.galaxy.GalacticManager; import utilities.CrcDatabaseGenerator; +import utilities.ScheduledUtilities; import utilities.ThreadUtilities; public class CoreManager extends Manager { @@ -133,6 +134,7 @@ public class CoreManager extends Manager { @Override public boolean terminate() { shutdownService.shutdownNow(); + ScheduledUtilities.shutdown(); return super.terminate(); } diff --git a/src/utilities/ScheduledUtilities.java b/src/utilities/ScheduledUtilities.java index 9b16bb16..58a07eed 100644 --- a/src/utilities/ScheduledUtilities.java +++ b/src/utilities/ScheduledUtilities.java @@ -46,9 +46,6 @@ public class ScheduledUtilities { if (executor == null) { int processors = Runtime.getRuntime().availableProcessors(); executor = Executors.newScheduledThreadPool(processors, ThreadUtilities.newThreadFactory("scheduled-utilities-%d")); - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - executor.shutdown(); - })); } return executor; } @@ -66,4 +63,12 @@ public class ScheduledUtilities { return getScheduler().schedule(r, delay, unit); } + public static void shutdown() { + synchronized (mutex) { + if (executor != null) { + executor.shutdown(); + } + } + } + } From ef666ea7447e81701f457f67ec9557b0c6e2c6e3 Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Sun, 18 Sep 2016 10:59:34 +0200 Subject: [PATCH 03/21] ExecutorService in FactionService now uses a ThreadFactory --- src/services/faction/FactionService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/faction/FactionService.java b/src/services/faction/FactionService.java index 49addcaf..77411ba8 100644 --- a/src/services/faction/FactionService.java +++ b/src/services/faction/FactionService.java @@ -46,6 +46,7 @@ import resources.objects.SWGObject; import resources.objects.creature.CreatureObject; import resources.objects.tangible.TangibleObject; import resources.player.Player; +import utilities.ThreadUtilities; public final class FactionService extends Service { @@ -57,7 +58,7 @@ public final class FactionService extends Service { @Override public boolean initialize() { - executor = Executors.newSingleThreadScheduledExecutor(); + executor = Executors.newSingleThreadScheduledExecutor(ThreadUtilities.newThreadFactory("faction-service")); return super.initialize(); } From bc61075d6b27be665603f84c91b6602ee95a0476 Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Mon, 3 Oct 2016 12:59:51 +0200 Subject: [PATCH 04/21] Added deathblows, currently only seems to work through radial --- scripts/commands/generic/cmdCoupDeGrace.js | 4 ++ src/intents/combat/CreatureKilledIntent.java | 8 ++- src/intents/combat/DeathblowIntent.java | 67 ++++++++++++++++++ src/services/combat/CombatManager.java | 72 ++++++++++++++++++-- 4 files changed, 144 insertions(+), 7 deletions(-) create mode 100644 scripts/commands/generic/cmdCoupDeGrace.js create mode 100644 src/intents/combat/DeathblowIntent.java diff --git a/scripts/commands/generic/cmdCoupDeGrace.js b/scripts/commands/generic/cmdCoupDeGrace.js new file mode 100644 index 00000000..6a40df04 --- /dev/null +++ b/scripts/commands/generic/cmdCoupDeGrace.js @@ -0,0 +1,4 @@ +function executeCommand(galacticManager, player, target, args) { + var DeathblowIntent = Java.type("intents.combat.DeathblowIntent"); + new DeathblowIntent(true, player.getCreatureObject(), target).broadcast(); +} \ No newline at end of file diff --git a/src/intents/combat/CreatureKilledIntent.java b/src/intents/combat/CreatureKilledIntent.java index 66749f0e..9db56032 100644 --- a/src/intents/combat/CreatureKilledIntent.java +++ b/src/intents/combat/CreatureKilledIntent.java @@ -34,13 +34,19 @@ public class CreatureKilledIntent extends Intent { public static final String TYPE = "CreatureKilledIntent"; + private final CreatureObject killerCreature; private final CreatureObject killedCreature; - public CreatureKilledIntent(CreatureObject killedCreature) { + public CreatureKilledIntent(CreatureObject killerCreature, CreatureObject killedCreature) { super(TYPE); + this.killerCreature = killerCreature; this.killedCreature = killedCreature; } + public CreatureObject getKillerCreature() { + return killerCreature; + } + public CreatureObject getKilledCreature() { return killedCreature; } diff --git a/src/intents/combat/DeathblowIntent.java b/src/intents/combat/DeathblowIntent.java new file mode 100644 index 00000000..688cca19 --- /dev/null +++ b/src/intents/combat/DeathblowIntent.java @@ -0,0 +1,67 @@ +/*********************************************************************************** +* Copyright (c) 2015 /// Project SWG /// www.projectswg.com * +* * +* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * +* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * +* Our goal is to create an emulator which will provide a server for players to * +* continue playing a game similar to the one they used to play. We are basing * +* it on the final publish of the game prior to end-game events. * +* * +* This file is part of Holocore. * +* * +* -------------------------------------------------------------------------------- * +* * +* Holocore is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Affero General Public License as * +* published by the Free Software Foundation, either version 3 of the * +* License, or (at your option) any later version. * +* * +* Holocore 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 Affero General Public License for more details. * +* * +* You should have received a copy of the GNU Affero General Public License * +* along with Holocore. If not, see . * +* * +***********************************************************************************/ +package intents.combat; + +import resources.control.Intent; +import resources.objects.creature.CreatureObject; + +public class DeathblowIntent extends Intent { + + public static final String TYPE = "DeathblowIntent"; + + private final boolean request; + private final CreatureObject killerCreature; + private final CreatureObject killedCreature; + + /** + * + * @param request is {@code true} if a deathblow is being requested and + * {@code false} if the deathblow has happened + * @param killerCreature {@code CreatureObject} that's deathblowing + * @param killedCreature {@code CreatureObject} that's being deathblown + */ + public DeathblowIntent(boolean request, CreatureObject killerCreature, CreatureObject killedCreature) { + super(TYPE); + this.request = request; + this.killerCreature = killerCreature; + this.killedCreature = killedCreature; + } + + public boolean isRequest() { + return request; + } + + public CreatureObject getKillerCreature() { + return killerCreature; + } + + public CreatureObject getKilledCreature() { + return killedCreature; + } + +} diff --git a/src/services/combat/CombatManager.java b/src/services/combat/CombatManager.java index ea2ebd4b..15b88263 100644 --- a/src/services/combat/CombatManager.java +++ b/src/services/combat/CombatManager.java @@ -41,7 +41,9 @@ import network.packets.swg.zone.object_controller.ShowFlyText.Scale; import network.packets.swg.zone.object_controller.combat.CombatAction; import intents.chat.ChatCommandIntent; import intents.combat.CreatureKilledIntent; +import intents.combat.DeathblowIntent; import java.util.Iterator; +import java.util.concurrent.Future; import resources.Posture; import resources.PvpFaction; import resources.PvpFlag; @@ -68,14 +70,17 @@ public class CombatManager extends Manager { private final Map inCombat; private final Set regeneratingHealthCreatures; // Only allowed outside of combat private final Set regeneratingActionCreatures; // Always allowed + private final Map> incapacitatedCreatures; private final CorpseService corpseService; private ScheduledExecutorService executor; public CombatManager() { + registerForIntent(DeathblowIntent.TYPE); inCombat = new HashMap<>(); regeneratingHealthCreatures = new HashSet<>(); regeneratingActionCreatures = new HashSet<>(); + incapacitatedCreatures = new HashMap<>(); corpseService = new CorpseService(); addChildService(corpseService); @@ -110,8 +115,10 @@ public class CombatManager extends Manager { @Override public void onIntentReceived(Intent i) { - if (i instanceof ChatCommandIntent) - processChatCommand((ChatCommandIntent) i); + switch(i.getType()) { + case ChatCommandIntent.TYPE: processChatCommand((ChatCommandIntent) i); break; + case DeathblowIntent.TYPE: procesDeathblow((DeathblowIntent) i); break; + } } private void periodicChecks() { @@ -320,7 +327,7 @@ public class CombatManager extends Manager { incapacitatePlayer(killedCreature); } else { // This is just a plain ol' NPC. Die! - killCreature(killedCreature); + killCreature(killer, killedCreature); } exitCombat(killedCreature); @@ -334,7 +341,16 @@ public class CombatManager extends Manager { Log.i(this, "%s was incapacitated", incapacitatedPlayer); // Once the incapacitation counter expires, revive them. - executor.schedule(() -> reviveCreature(incapacitatedPlayer), incapacitationCounter, TimeUnit.SECONDS); + synchronized(incapacitatedCreatures) { + incapacitatedCreatures.put(incapacitatedPlayer, executor.schedule(() -> expireIncapacitation(incapacitatedPlayer), incapacitationCounter, TimeUnit.SECONDS)); + } + } + + private void expireIncapacitation(CreatureObject incapacitatedPlayer) { + synchronized(incapacitatedCreatures) { + incapacitatedCreatures.remove(incapacitatedPlayer); + reviveCreature(incapacitatedPlayer); + } } private void reviveCreature(CreatureObject revivedCreature) { @@ -360,10 +376,44 @@ public class CombatManager extends Manager { Log.i(this, "% was revived", revivedCreature); } - private void killCreature(CreatureObject killedCreature) { + private void killCreature(CreatureObject killerCreature, CreatureObject killedCreature) { killedCreature.setPosture(Posture.DEAD); Log.i(this, "%s was killed", killedCreature); - new CreatureKilledIntent(killedCreature).broadcast(); + new CreatureKilledIntent(killerCreature, killedCreature).broadcast(); + } + + private void procesDeathblow(DeathblowIntent i) { + if(i.isRequest()) { + CreatureObject killerCreature = i.getKillerCreature(); + CreatureObject killedCreature = i.getKilledCreature(); + + // Only players may deathblow eachother + if(killerCreature.isPlayer() && killedCreature.isPlayer()) { + // They must be enemies + if(killedCreature.isEnemy(killerCreature)) { + // The target of the deathblow must be incapacitated! + if(killedCreature.getPosture() == Posture.INCAPACITATED) { + // If this happens, they obviously can't get back up + synchronized (incapacitatedCreatures) { + Future incapacitationTimer = incapacitatedCreatures.remove(killedCreature); + + if(incapacitationTimer != null) { + if(incapacitationTimer.cancel(false)) { // If the task is running, let them get back up + killCreature(killerCreature, killedCreature); + new DeathblowIntent(false, killerCreature, killedCreature).broadcast(); + Log.i(this, "%s was deathblown by %s", killedCreature, killerCreature); + } + } else { + // Can't happen with the current code, but in case it's ever refactored... + Log.e(this, "Incapacitation timer for player %s being deathblown unexpectedly didn't exist!", ""); + } + } + } + } + } else { + Log.i(this, "%s tried to deathblow NPC %s", killerCreature, killedCreature); + } + } } private boolean handleStatus(CreatureObject source, CombatStatus status) { @@ -396,6 +446,16 @@ public class CombatManager extends Manager { } else if ((tangibleTarget.getPvpFlags() & PvpFlag.ATTACKABLE.getBitmask()) == 0) return CombatStatus.INVALID_TARGET; + if(target instanceof CreatureObject) { + CreatureObject creature = (CreatureObject) target; + + switch(creature.getPosture()) { + case DEAD: + case INCAPACITATED: + return CombatStatus.INVALID_TARGET; + } + } + CombatStatus status; switch (c.getAttackType()) { case AREA: From 0d42d02749476e02247fd5b18695ddb0d7d43dee Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Mon, 3 Oct 2016 13:26:08 +0200 Subject: [PATCH 05/21] DeathblowIntent is now only used for deathblow requests --- scripts/commands/generic/cmdCoupDeGrace.js | 2 +- src/intents/combat/DeathblowIntent.java | 11 +---- src/services/combat/CombatManager.java | 47 ++++++++++------------ 3 files changed, 24 insertions(+), 36 deletions(-) diff --git a/scripts/commands/generic/cmdCoupDeGrace.js b/scripts/commands/generic/cmdCoupDeGrace.js index 6a40df04..58a3d454 100644 --- a/scripts/commands/generic/cmdCoupDeGrace.js +++ b/scripts/commands/generic/cmdCoupDeGrace.js @@ -1,4 +1,4 @@ function executeCommand(galacticManager, player, target, args) { var DeathblowIntent = Java.type("intents.combat.DeathblowIntent"); - new DeathblowIntent(true, player.getCreatureObject(), target).broadcast(); + new DeathblowIntent(player.getCreatureObject(), target).broadcast(); } \ No newline at end of file diff --git a/src/intents/combat/DeathblowIntent.java b/src/intents/combat/DeathblowIntent.java index 688cca19..b8e31753 100644 --- a/src/intents/combat/DeathblowIntent.java +++ b/src/intents/combat/DeathblowIntent.java @@ -34,28 +34,19 @@ public class DeathblowIntent extends Intent { public static final String TYPE = "DeathblowIntent"; - private final boolean request; private final CreatureObject killerCreature; private final CreatureObject killedCreature; /** - * - * @param request is {@code true} if a deathblow is being requested and - * {@code false} if the deathblow has happened * @param killerCreature {@code CreatureObject} that's deathblowing * @param killedCreature {@code CreatureObject} that's being deathblown */ - public DeathblowIntent(boolean request, CreatureObject killerCreature, CreatureObject killedCreature) { + public DeathblowIntent(CreatureObject killerCreature, CreatureObject killedCreature) { super(TYPE); - this.request = request; this.killerCreature = killerCreature; this.killedCreature = killedCreature; } - public boolean isRequest() { - return request; - } - public CreatureObject getKillerCreature() { return killerCreature; } diff --git a/src/services/combat/CombatManager.java b/src/services/combat/CombatManager.java index 15b88263..a682b312 100644 --- a/src/services/combat/CombatManager.java +++ b/src/services/combat/CombatManager.java @@ -383,36 +383,33 @@ public class CombatManager extends Manager { } private void procesDeathblow(DeathblowIntent i) { - if(i.isRequest()) { - CreatureObject killerCreature = i.getKillerCreature(); - CreatureObject killedCreature = i.getKilledCreature(); - - // Only players may deathblow eachother - if(killerCreature.isPlayer() && killedCreature.isPlayer()) { - // They must be enemies - if(killedCreature.isEnemy(killerCreature)) { - // The target of the deathblow must be incapacitated! - if(killedCreature.getPosture() == Posture.INCAPACITATED) { - // If this happens, they obviously can't get back up - synchronized (incapacitatedCreatures) { - Future incapacitationTimer = incapacitatedCreatures.remove(killedCreature); - - if(incapacitationTimer != null) { - if(incapacitationTimer.cancel(false)) { // If the task is running, let them get back up - killCreature(killerCreature, killedCreature); - new DeathblowIntent(false, killerCreature, killedCreature).broadcast(); - Log.i(this, "%s was deathblown by %s", killedCreature, killerCreature); - } - } else { - // Can't happen with the current code, but in case it's ever refactored... - Log.e(this, "Incapacitation timer for player %s being deathblown unexpectedly didn't exist!", ""); + CreatureObject killerCreature = i.getKillerCreature(); + CreatureObject killedCreature = i.getKilledCreature(); + + // Only players may deathblow eachother + if (killerCreature.isPlayer() && killedCreature.isPlayer()) { + // They must be enemies + if (killedCreature.isEnemy(killerCreature)) { + // The target of the deathblow must be incapacitated! + if (killedCreature.getPosture() == Posture.INCAPACITATED) { + // If this happens, they obviously can't get back up + synchronized (incapacitatedCreatures) { + Future incapacitationTimer = incapacitatedCreatures.remove(killedCreature); + + if (incapacitationTimer != null) { + if (incapacitationTimer.cancel(false)) { // If the task is running, let them get back up + killCreature(killerCreature, killedCreature); + Log.i(this, "%s was deathblown by %s", killedCreature, killerCreature); } + } else { + // Can't happen with the current code, but in case it's ever refactored... + Log.e(this, "Incapacitation timer for player %s being deathblown unexpectedly didn't exist!", ""); } } } - } else { - Log.i(this, "%s tried to deathblow NPC %s", killerCreature, killedCreature); } + } else { + Log.i(this, "%s tried to deathblow NPC %s", killerCreature, killedCreature); } } From 31374b3e2c32caf76b37dc4c2e2a86c344c5cc4b Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Mon, 10 Oct 2016 12:50:05 +0200 Subject: [PATCH 06/21] Simplified deathblow code and renamed fields in DeathblowIntent and CreatureKilledIntent --- src/intents/combat/CreatureKilledIntent.java | 20 +++---- src/intents/combat/DeathblowIntent.java | 22 ++++---- src/services/combat/CombatManager.java | 58 +++++++++++--------- src/services/combat/CorpseService.java | 6 +- 4 files changed, 55 insertions(+), 51 deletions(-) diff --git a/src/intents/combat/CreatureKilledIntent.java b/src/intents/combat/CreatureKilledIntent.java index 9db56032..dd830d40 100644 --- a/src/intents/combat/CreatureKilledIntent.java +++ b/src/intents/combat/CreatureKilledIntent.java @@ -34,21 +34,21 @@ public class CreatureKilledIntent extends Intent { public static final String TYPE = "CreatureKilledIntent"; - private final CreatureObject killerCreature; - private final CreatureObject killedCreature; + private final CreatureObject killer; + private final CreatureObject corpse; - public CreatureKilledIntent(CreatureObject killerCreature, CreatureObject killedCreature) { + public CreatureKilledIntent(CreatureObject killer, CreatureObject corpse) { super(TYPE); - this.killerCreature = killerCreature; - this.killedCreature = killedCreature; + this.killer = killer; + this.corpse = corpse; } - public CreatureObject getKillerCreature() { - return killerCreature; + public CreatureObject getKiller() { + return killer; } - public CreatureObject getKilledCreature() { - return killedCreature; + public CreatureObject getCorpse() { + return corpse; } - + } diff --git a/src/intents/combat/DeathblowIntent.java b/src/intents/combat/DeathblowIntent.java index b8e31753..67eb4d14 100644 --- a/src/intents/combat/DeathblowIntent.java +++ b/src/intents/combat/DeathblowIntent.java @@ -34,25 +34,25 @@ public class DeathblowIntent extends Intent { public static final String TYPE = "DeathblowIntent"; - private final CreatureObject killerCreature; - private final CreatureObject killedCreature; + private final CreatureObject killer; + private final CreatureObject corpse; /** - * @param killerCreature {@code CreatureObject} that's deathblowing - * @param killedCreature {@code CreatureObject} that's being deathblown + * @param killer {@code CreatureObject} that's deathblowing + * @param corpse {@code CreatureObject} that's being deathblown */ - public DeathblowIntent(CreatureObject killerCreature, CreatureObject killedCreature) { + public DeathblowIntent(CreatureObject killer, CreatureObject corpse) { super(TYPE); - this.killerCreature = killerCreature; - this.killedCreature = killedCreature; + this.killer = killer; + this.corpse = corpse; } - public CreatureObject getKillerCreature() { - return killerCreature; + public CreatureObject getKiller() { + return killer; } - public CreatureObject getKilledCreature() { - return killedCreature; + public CreatureObject getCorpse() { + return corpse; } } diff --git a/src/services/combat/CombatManager.java b/src/services/combat/CombatManager.java index a682b312..bc930495 100644 --- a/src/services/combat/CombatManager.java +++ b/src/services/combat/CombatManager.java @@ -376,40 +376,44 @@ public class CombatManager extends Manager { Log.i(this, "% was revived", revivedCreature); } - private void killCreature(CreatureObject killerCreature, CreatureObject killedCreature) { - killedCreature.setPosture(Posture.DEAD); - Log.i(this, "%s was killed", killedCreature); - new CreatureKilledIntent(killerCreature, killedCreature).broadcast(); + private void killCreature(CreatureObject killer, CreatureObject corpse) { + corpse.setPosture(Posture.DEAD); + Log.i(this, "%s was killed", corpse); + new CreatureKilledIntent(killer, corpse).broadcast(); } private void procesDeathblow(DeathblowIntent i) { - CreatureObject killerCreature = i.getKillerCreature(); - CreatureObject killedCreature = i.getKilledCreature(); + CreatureObject killer = i.getKiller(); + CreatureObject corpse = i.getCorpse(); - // Only players may deathblow eachother - if (killerCreature.isPlayer() && killedCreature.isPlayer()) { - // They must be enemies - if (killedCreature.isEnemy(killerCreature)) { - // The target of the deathblow must be incapacitated! - if (killedCreature.getPosture() == Posture.INCAPACITATED) { - // If this happens, they obviously can't get back up - synchronized (incapacitatedCreatures) { - Future incapacitationTimer = incapacitatedCreatures.remove(killedCreature); + // Only deathblowing players is allowed! + if (!corpse.isPlayer()) { + return; + } + + // They must be enemies + if (!corpse.isEnemy(killer)) { + return; + } + + // The target of the deathblow must be incapacitated! + if (corpse.getPosture() != Posture.INCAPACITATED) { + return; + } + + // If they're deathblown while incapacitated, their incapacitation expiration timer should cancel + synchronized (incapacitatedCreatures) { + Future incapacitationTimer = incapacitatedCreatures.remove(corpse); - if (incapacitationTimer != null) { - if (incapacitationTimer.cancel(false)) { // If the task is running, let them get back up - killCreature(killerCreature, killedCreature); - Log.i(this, "%s was deathblown by %s", killedCreature, killerCreature); - } - } else { - // Can't happen with the current code, but in case it's ever refactored... - Log.e(this, "Incapacitation timer for player %s being deathblown unexpectedly didn't exist!", ""); - } - } + if (incapacitationTimer != null) { + if (incapacitationTimer.cancel(false)) { // If the task is running, let them get back up + killCreature(killer, corpse); + Log.i(this, "%s was deathblown by %s", corpse, killer); } + } else { + // Can't happen with the current code, but in case it's ever refactored... + Log.e(this, "Incapacitation timer for player %s being deathblown unexpectedly didn't exist!", ""); } - } else { - Log.i(this, "%s tried to deathblow NPC %s", killerCreature, killedCreature); } } diff --git a/src/services/combat/CorpseService.java b/src/services/combat/CorpseService.java index 31a3b8fd..0ea6e01c 100644 --- a/src/services/combat/CorpseService.java +++ b/src/services/combat/CorpseService.java @@ -67,16 +67,16 @@ public final class CorpseService extends Service { } private void handleCreatureKilledIntent(CreatureKilledIntent i) { - CreatureObject killedCreature = i.getKilledCreature(); + CreatureObject corpse = i.getCorpse(); - if(killedCreature.isPlayer()) { + if(corpse.isPlayer()) { // TODO show cloning system message // TODO show cloning SUI window, with all possible facilities to clone at // TODO after 30 minutes, close the SUI window and force them to clone at the nearest cloning facility // TODO if the SUI window is closed by the player, make sure it reappears } else { // This is a NPC - schedule corpse for deletion - executor.schedule(() -> deleteCorpse(killedCreature), 120, TimeUnit.SECONDS); + executor.schedule(() -> deleteCorpse(corpse), 120, TimeUnit.SECONDS); } } From 0e2e896fd64ddabe4a22d85f1702d15c93b67957 Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Mon, 10 Oct 2016 16:26:59 +0200 Subject: [PATCH 07/21] Fixed cfg/nge.cfg not being ignored properly --- cfg/nge.cfg | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 cfg/nge.cfg diff --git a/cfg/nge.cfg b/cfg/nge.cfg deleted file mode 100644 index 7c38af40..00000000 --- a/cfg/nge.cfg +++ /dev/null @@ -1,15 +0,0 @@ -# 19/08/2016 05:19:18 MESZ -CLEAN-CHARACTER-DATA=0 -ENABLE-LOGGING=true -GALAXY-MAX-CHARACTERS=5 -GALAXY-MAX-CHARACTERS-PER-PERIOD=5 -GALAXY-MAX-ONLINE=3000 -GALAXY-NAME=Holocore -LOAD-OBJECTS=true -LOCAL-DB=nge -LOCAL-PASS=nge -LOCAL-USER=nge -LOG-LEVEL=DEBUG -PACKET-DEBUG=false -PRIMARY-SPAWN-LOCATION=tat_moseisley -WIPE-ODB-FILES=0 \ No newline at end of file From 08f807bd70a0dc10df1296c95f933ebcf526300f Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Mon, 10 Oct 2016 23:05:23 +0200 Subject: [PATCH 08/21] Added combat XP when killing creatures --- src/services/combat/CombatManager.java | 3 + src/services/combat/CombatXpService.java | 194 +++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 src/services/combat/CombatXpService.java diff --git a/src/services/combat/CombatManager.java b/src/services/combat/CombatManager.java index bc930495..018161c0 100644 --- a/src/services/combat/CombatManager.java +++ b/src/services/combat/CombatManager.java @@ -72,6 +72,7 @@ public class CombatManager extends Manager { private final Set regeneratingActionCreatures; // Always allowed private final Map> incapacitatedCreatures; private final CorpseService corpseService; + private final CombatXpService combatXpService; private ScheduledExecutorService executor; @@ -83,7 +84,9 @@ public class CombatManager extends Manager { incapacitatedCreatures = new HashMap<>(); corpseService = new CorpseService(); + combatXpService = new CombatXpService(); addChildService(corpseService); + addChildService(combatXpService); } @Override diff --git a/src/services/combat/CombatXpService.java b/src/services/combat/CombatXpService.java new file mode 100644 index 00000000..a363abed --- /dev/null +++ b/src/services/combat/CombatXpService.java @@ -0,0 +1,194 @@ +/************************************************************************************ + * Copyright (c) 2015 /// Project SWG /// www.projectswg.com * + * * + * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * + * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * + * Our goal is to create an emulator which will provide a server for players to * + * continue playing a game similar to the one they used to play. We are basing * + * it on the final publish of the game prior to end-game events. * + * * + * This file is part of Holocore. * + * * + * -------------------------------------------------------------------------------- * + * * + * Holocore is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * Holocore 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 Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with Holocore. If not, see . * + * * + ***********************************************************************************/ +package services.combat; + +import intents.combat.CreatureKilledIntent; +import intents.experience.ExperienceIntent; +import intents.object.DestroyObjectIntent; +import intents.object.ObjectCreatedIntent; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import resources.control.Intent; +import resources.control.Service; +import resources.objects.SWGObject; +import resources.objects.creature.CreatureDifficulty; +import resources.objects.creature.CreatureObject; +import resources.objects.group.GroupObject; +import resources.server_info.Log; +import resources.server_info.RelationalDatabase; +import resources.server_info.RelationalServerFactory; + +/** + * + * @author mads + */ +public class CombatXpService extends Service { + + private final Map xpData; + private final Map groupObjects; + + public CombatXpService() { + xpData = new HashMap<>(); + groupObjects = new HashMap<>(); + } + + @Override + public void onIntentReceived(Intent i) { + switch(i.getType()) { + case ObjectCreatedIntent.TYPE: handleObjectCreatedIntent((ObjectCreatedIntent) i); break; + case DestroyObjectIntent.TYPE: handleDestroyObjectIntent((DestroyObjectIntent) i); break; + case CreatureKilledIntent.TYPE: handleCreatureKilledIntent((CreatureKilledIntent) i); break; + } + } + + @Override + public boolean initialize() { + loadXpData(); + + return super.initialize(); + } + + @Override + public boolean start() { + // The objects we care about are only created/destroyed at this point anyways. + registerForIntent(ObjectCreatedIntent.TYPE); + registerForIntent(DestroyObjectIntent.TYPE); + registerForIntent(CreatureKilledIntent.TYPE); + + return super.start(); + } + + private void loadXpData() { + long start = System.nanoTime(); + + Log.i(this, "Loading combat XP rates..."); + try (RelationalDatabase npcStats = RelationalServerFactory.getServerData("creatures/npc_stats.db", "npc_stats")) { + try (ResultSet set = npcStats.executeQuery("SELECT * FROM npc_stats")) { + while (set.next()) { + xpData.put(set.getShort("Level"), new XpData(set.getInt("XP"), set.getInt("Elite_XP"), set.getInt("Boss_XP"))); + } + } catch (SQLException e) { + Log.e(this, e); + } + } + + double time = (System.nanoTime()-start)/1E6; + Log.i(this, "Finished loading %d combat XP rates. Time: %fms", xpData.size(), time); + } + + private void handleObjectCreatedIntent(ObjectCreatedIntent i) { + SWGObject object = i.getObject(); + + if(object instanceof GroupObject) { + synchronized (groupObjects) { + groupObjects.put(object.getObjectId(), (GroupObject) object); + } + } + } + + private void handleDestroyObjectIntent(DestroyObjectIntent i) { + SWGObject object = i.getObject(); + + synchronized (groupObjects) { + if(object instanceof GroupObject && groupObjects.remove(object.getObjectId()) == null) { + Log.w(this, "%s was expected to be in the GroupObject mapping but wasn't", object); + } + } + } + + private void handleCreatureKilledIntent(CreatureKilledIntent i) { + CreatureObject killer = i.getKiller(); + + // Entertainers gain no combat XP! + if(killer.hasSkill("class_entertainer_phase1_novice")) { + return; + } + + CreatureObject corpse = i.getCorpse(); + GroupObject group = groupObjects.get(corpse.getGroupId()); + short effectiveLevel = group != null ? group.getLevel() : corpse.getLevel(); + + XpData xpForLevel = this.xpData.get(effectiveLevel); + + if(xpForLevel == null) { + Log.e(this, "%s received no XP: No XP data was found for level %d!", killer, effectiveLevel); + return; + } + + int experienceGained; + CreatureDifficulty creatureDifficulty = corpse.getDifficulty(); + + switch(creatureDifficulty) { + case BOSS: experienceGained = xpForLevel.getBossXp(); break; + case ELITE: experienceGained = xpForLevel.getEliteXp(); break; + case NORMAL: experienceGained = xpForLevel.getXp(); break; + default: + Log.e(this, "%s received no XP: Unsupported creature difficulty %s of corpse %s", creatureDifficulty); + return; + } + + if(experienceGained == 0) { + Log.w(this, "%s received no XP: XP for creature difficulty %s at level %d was %d", killer, creatureDifficulty, effectiveLevel, experienceGained); + return; + } + + if(group == null) { + new ExperienceIntent(killer, "combat", experienceGained).broadcast(); + } else { + group.getGroupMemberObjects().forEach(groupMember -> new ExperienceIntent(groupMember, "combat", experienceGained).broadcast()); + } + } + + private class XpData { + private final int xp; + private final int eliteXp; + private final int bossXp; + + public XpData(int xp, int eliteXp, int bossXp) { + this.xp = xp; + this.eliteXp = eliteXp; + this.bossXp = bossXp; + } + + public int getXp() { + return xp; + } + + public int getEliteXp() { + return eliteXp; + } + + public int getBossXp() { + return bossXp; + } + + } + +} From 6809647040d7a8afb48048b22a8ddb4f5225dc87 Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Mon, 10 Oct 2016 23:34:27 +0200 Subject: [PATCH 09/21] Combat XP is now only gained by nearby group members --- src/services/combat/CombatXpService.java | 68 +++++++++++++++--------- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/src/services/combat/CombatXpService.java b/src/services/combat/CombatXpService.java index a363abed..9682edf0 100644 --- a/src/services/combat/CombatXpService.java +++ b/src/services/combat/CombatXpService.java @@ -127,45 +127,65 @@ public class CombatXpService extends Service { CreatureObject killer = i.getKiller(); // Entertainers gain no combat XP! - if(killer.hasSkill("class_entertainer_phase1_novice")) { + if (isEntertainer(killer)) { return; } CreatureObject corpse = i.getCorpse(); GroupObject group = groupObjects.get(corpse.getGroupId()); - short effectiveLevel = group != null ? group.getLevel() : corpse.getLevel(); - - XpData xpForLevel = this.xpData.get(effectiveLevel); - - if(xpForLevel == null) { - Log.e(this, "%s received no XP: No XP data was found for level %d!", killer, effectiveLevel); - return; - } - + short killerLevel = group != null ? group.getLevel() : killer.getLevel(); + short corpseLevel = corpse.getLevel(); int experienceGained; - CreatureDifficulty creatureDifficulty = corpse.getDifficulty(); - switch(creatureDifficulty) { - case BOSS: experienceGained = xpForLevel.getBossXp(); break; - case ELITE: experienceGained = xpForLevel.getEliteXp(); break; - case NORMAL: experienceGained = xpForLevel.getXp(); break; - default: - Log.e(this, "%s received no XP: Unsupported creature difficulty %s of corpse %s", creatureDifficulty); + // If the difference between killer and corpse is 10 or above, they only gain 1 xp + if (killerLevel - corpseLevel >= 10) { + experienceGained = 1; + } else { + + XpData xpForLevel = this.xpData.get(corpseLevel); + + if (xpForLevel == null) { + Log.e(this, "%s received no XP: No XP data was found for level %d!", killer, corpseLevel); return; + } + + CreatureDifficulty creatureDifficulty = corpse.getDifficulty(); + + switch (creatureDifficulty) { + case BOSS: experienceGained = xpForLevel.getBossXp(); break; + case ELITE: experienceGained = xpForLevel.getEliteXp(); break; + case NORMAL: experienceGained = xpForLevel.getXp(); break; + default: + Log.e(this, "%s received no XP: Unsupported creature difficulty %s of corpse %s", creatureDifficulty); + return; + } + + if (experienceGained == 0) { + Log.w(this, "%s received no XP: XP for creature difficulty %s at level %d was %d", killer, creatureDifficulty, killerLevel, experienceGained); + return; + } } - if(experienceGained == 0) { - Log.w(this, "%s received no XP: XP for creature difficulty %s at level %d was %d", killer, creatureDifficulty, effectiveLevel, experienceGained); - return; - } - - if(group == null) { + if (group == null) { new ExperienceIntent(killer, "combat", experienceGained).broadcast(); } else { - group.getGroupMemberObjects().forEach(groupMember -> new ExperienceIntent(groupMember, "combat", experienceGained).broadcast()); + group.getGroupMemberObjects().stream() + .filter(groupMember -> !isEntertainer(groupMember) && isMemberEligible(corpse, groupMember)) + .forEach(eligibleMember -> new ExperienceIntent(eligibleMember, "combat", experienceGained).broadcast()); } } + private boolean isEntertainer(CreatureObject creature) { + return creature.hasSkill("class_entertainer_phase1_novice"); + } + + /** + * @return true if {@code groupMember} is an observer of {@code corpse} + */ + private boolean isMemberEligible(CreatureObject corpse, CreatureObject groupMember) { + return corpse.getObservers().contains(groupMember); + } + private class XpData { private final int xp; private final int eliteXp; From 513279a39e3967217f9f58463f202986fa622604 Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Tue, 11 Oct 2016 00:31:02 +0200 Subject: [PATCH 10/21] Fixed an issue where an entertainer killing a creature would block XP to otherwise eligible group members --- src/services/combat/CombatXpService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/services/combat/CombatXpService.java b/src/services/combat/CombatXpService.java index 9682edf0..9d946189 100644 --- a/src/services/combat/CombatXpService.java +++ b/src/services/combat/CombatXpService.java @@ -125,14 +125,15 @@ public class CombatXpService extends Service { private void handleCreatureKilledIntent(CreatureKilledIntent i) { CreatureObject killer = i.getKiller(); + GroupObject group = groupObjects.get(killer.getGroupId()); - // Entertainers gain no combat XP! - if (isEntertainer(killer)) { + // Ungrouped entertainer + if (group == null && isEntertainer(killer)) { return; } CreatureObject corpse = i.getCorpse(); - GroupObject group = groupObjects.get(corpse.getGroupId()); + short killerLevel = group != null ? group.getLevel() : killer.getLevel(); short corpseLevel = corpse.getLevel(); int experienceGained; From 4cfee250307281c2d35a8fcbc90493beb46bcbc6 Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Tue, 11 Oct 2016 02:02:03 +0200 Subject: [PATCH 11/21] You no longer gain XP by killing players --- src/services/combat/CombatXpService.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/services/combat/CombatXpService.java b/src/services/combat/CombatXpService.java index 9d946189..957c7cc5 100644 --- a/src/services/combat/CombatXpService.java +++ b/src/services/combat/CombatXpService.java @@ -124,6 +124,13 @@ public class CombatXpService extends Service { } private void handleCreatureKilledIntent(CreatureKilledIntent i) { + CreatureObject corpse = i.getCorpse(); + + // You don't gain XP by PvP'ing + if(corpse.isPlayer()) { + return; + } + CreatureObject killer = i.getKiller(); GroupObject group = groupObjects.get(killer.getGroupId()); @@ -132,8 +139,6 @@ public class CombatXpService extends Service { return; } - CreatureObject corpse = i.getCorpse(); - short killerLevel = group != null ? group.getLevel() : killer.getLevel(); short corpseLevel = corpse.getLevel(); int experienceGained; From 5511a9309527dcf0f112b679fb1e3c6d14b406d5 Mon Sep 17 00:00:00 2001 From: Undercova PSWG Date: Tue, 11 Oct 2016 20:03:30 +0000 Subject: [PATCH 12/21] - Smuggler roadmap pistol (CL30) changed from unarmed to pistol weapon category - Jedi roadmap polearm restricted to Force-Sensitive profession only --- serverdata/items/weapon.sdb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/serverdata/items/weapon.sdb b/serverdata/items/weapon.sdb index eac17a48..d9efe8d7 100644 --- a/serverdata/items/weapon.sdb +++ b/serverdata/items/weapon.sdb @@ -103,8 +103,8 @@ weapon_knuckler_ent_roadmap_02_03 object/weapon/melee/special/vibroknuckler_stat weapon_knuckler_ent_roadmap_02_04 object/weapon/melee/special/vibroknuckler_static.iff weapon Glamour Vibroknuckler 1 1000 190 375 melee_weapon UNARMED kinetic none 0 100 100 0 5 - 282 283 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 30 entertainer TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE strength_modified=5 0 1 FALSE 0 2 1 lvl 30 roadmap - weapon_knuckler_fs_roadmap_01_02 object/weapon/melee/special/vibroknuckler_static.iff weapon Precise Knuckler 1 1000 334 668 melee_weapon UNARMED kinetic none 0 100 100 0 5 - 501 501 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 50 force_sensitive TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE strength_modified=3 0 4500 FALSE 0 2 2 lvl 50 roadmap - weapon_knuckler_fs_roadmap_02_02 object/weapon/melee/special/vibroknuckler_static.iff weapon Neophyte Vibroknuckler 1 1000 188 375 melee_weapon UNARMED kinetic none 0 100 100 0 5 - 282 282 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 30 force_sensitive TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE strength_modified=5 0 2200 FALSE 0 2 2 lvl 30 roadmap - -weapon_knuckler_smuggler_roadmap_01_02 object/weapon/ranged/pistol/pistol_scout_blaster_static.iff weapon Scoundrel's Scout Blaster 1 1000 73 145 ranged_weapon UNARMED kinetic none 0 40 100 0 35 - 282 273 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 30 smuggler TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=5 0 2200 FALSE 0 2 2 lvl 30 roadmap - -weapon_knuckler_smuggler_roadmap_02_02 object/weapon/ranged/pistol/pistol_striker_static.iff weapon Precise Striker Pistol 1 1000 131 261 ranged_weapon UNARMED kinetic none 0 40 100 0 35 - 490 490 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 50 smuggler TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=10 0 4500 FALSE 0 2 2 lvl 50 roadmap - +weapon_knuckler_smuggler_roadmap_01_02 object/weapon/ranged/pistol/pistol_scout_blaster_static.iff weapon Scoundrel's Scout Blaster 1 1000 73 145 ranged_weapon PISTOL kinetic none 0 40 100 0 35 - 282 273 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 30 smuggler TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=5 0 2200 FALSE 0 2 2 lvl 30 roadmap - +weapon_knuckler_smuggler_roadmap_02_02 object/weapon/ranged/pistol/pistol_striker_static.iff weapon Precise Striker Pistol 1 1000 131 261 ranged_weapon PISTOL kinetic none 0 40 100 0 35 - 490 490 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 50 smuggler TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=10 0 4500 FALSE 0 2 2 lvl 50 roadmap - weapon_lightningbeam_commando_roadmap_01_02 object/weapon/ranged/rifle/rifle_dlt20.iff weapon Precise DLT-20 1 1000 182 363 ranged_weapon HEAVY_WEAPON energy none 0 100 100 0 64 - 273 273 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 30 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=5 0 2200 FALSE 0 2 2 lvl 30 roadmap - weapon_magna_guard_polearm_04_01 object/weapon/melee/polearm/lance_staff_magna_guard.iff weapon MagnaGuard Electrostaff 1 1000 700 1000 melee_weapon POLEARM_MELEE kinetic electricity 20 100 100 0 5 - 900 890 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 75 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE FALSE - 0 1000 FALSE 0 4 1 pvp BF reward - weapon_mandalorian_carbine_04_01 object/weapon/ranged/carbine/carbine_mandalorian.iff weapon Crusader M-XIII Carbine 1 1000 415 755 ranged_weapon CARBINE energy none 0 60 100 0 50 - 975 975 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 75 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=10,constitution_modified=5 0 5000 FALSE 0 4 1 - - @@ -150,7 +150,7 @@ weapon_pistol_spy_roadmap_01_02 object/weapon/ranged/pistol/pistol_striker_stati weapon_pistol_trader_roadmap_01_02 object/weapon/ranged/pistol/pistol_scout_blaster_static.iff weapon Trader's Friend 1 1000 250 500 ranged_weapon PISTOL energy none 0 40 100 0 35 - 120 938 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 50 trader TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 250 FALSE 0 2 1 noncombat roadmap - weapon_polearm_02_01 object/weapon/melee/polearm/lance_staff_wood_s2.iff weapon Basic Wood Staff 1 1000 43 86 melee_weapon POLEARM_MELEE kinetic none 0 100 100 0 5 - 65 65 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 5 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE melee_accuracy=1 0 45 FALSE 0 2 1 level 5 required - weapon_polearm_02_02 object/weapon/melee/polearm/lance_staff_wood_s2_npe.iff weapon Issued Staff 1 1000 29 58 melee_weapon POLEARM_MELEE kinetic none 0 100 100 0 5 - 44 44 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 1 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 45 FALSE 0 2 1 level 1 npe - -weapon_polearm_02_03 object/weapon/melee/polearm/polearm_vibro_axe_npe.iff weapon Jedi Training Polearm 1 1000 43 75 melee_weapon POLEARM_MELEE kinetic none 0 100 100 0 5 - 59 59 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 1 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 45 FALSE 0 2 1 level 3 NPE - +weapon_polearm_02_03 object/weapon/melee/polearm/polearm_vibro_axe_npe.iff weapon Jedi Training Polearm 1 1000 43 75 melee_weapon POLEARM_MELEE kinetic none 0 100 100 0 5 - 59 59 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 1 force_sensitive TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 45 FALSE 0 2 1 Jedi starter weapon - weapon_polearm_02_04 object/weapon/melee/polearm/lance_staff_wood_s2_npe.iff weapon Reinforced Staff 1 1000 46 91 melee_weapon POLEARM_MELEE kinetic none 0 100 100 0 5 - 69 69 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 6 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 200 FALSE 0 2 1 level 6 npe - weapon_polearm_02_05 object/weapon/melee/polearm/lance_staff_wood_s2_npe.iff weapon Reinforced Staff 1 1000 64 128 melee_weapon POLEARM_MELEE kinetic none 0 100 100 0 5 - 96 96 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 9 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 300 FALSE 0 2 1 level 9 npe - weapon_polearm_04_01 object/weapon/melee/polearm/lance_controllerfp_npe.iff weapon Modified Lance 1 1000 85 170 melee_weapon POLEARM_MELEE kinetic none 0 100 100 0 5 - 128 128 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 13 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 400 FALSE 0 4 1 level 13 npe - From 80bc19afaef51b34560750266475b80359a9cb1e Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Wed, 12 Oct 2016 14:07:50 +0200 Subject: [PATCH 13/21] Split a big method in CombatXpService into smaller methods --- src/services/combat/CombatXpService.java | 74 ++++++++++++++---------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/src/services/combat/CombatXpService.java b/src/services/combat/CombatXpService.java index 957c7cc5..584d48e6 100644 --- a/src/services/combat/CombatXpService.java +++ b/src/services/combat/CombatXpService.java @@ -140,43 +140,18 @@ public class CombatXpService extends Service { } short killerLevel = group != null ? group.getLevel() : killer.getLevel(); - short corpseLevel = corpse.getLevel(); - int experienceGained; + int experienceGained = calculateXpGain(killer, corpse, killerLevel); - // If the difference between killer and corpse is 10 or above, they only gain 1 xp - if (killerLevel - corpseLevel >= 10) { - experienceGained = 1; - } else { - - XpData xpForLevel = this.xpData.get(corpseLevel); - - if (xpForLevel == null) { - Log.e(this, "%s received no XP: No XP data was found for level %d!", killer, corpseLevel); - return; - } - - CreatureDifficulty creatureDifficulty = corpse.getDifficulty(); - - switch (creatureDifficulty) { - case BOSS: experienceGained = xpForLevel.getBossXp(); break; - case ELITE: experienceGained = xpForLevel.getEliteXp(); break; - case NORMAL: experienceGained = xpForLevel.getXp(); break; - default: - Log.e(this, "%s received no XP: Unsupported creature difficulty %s of corpse %s", creatureDifficulty); - return; - } - - if (experienceGained == 0) { - Log.w(this, "%s received no XP: XP for creature difficulty %s at level %d was %d", killer, creatureDifficulty, killerLevel, experienceGained); - return; - } + if (experienceGained <= 0) { + Log.w(this, "%s received no XP: XP for creature difficulty %s at level %d was %d", killer, corpse.getDifficulty(), killerLevel, experienceGained); + return; } if (group == null) { new ExperienceIntent(killer, "combat", experienceGained).broadcast(); } else { group.getGroupMemberObjects().stream() - .filter(groupMember -> !isEntertainer(groupMember) && isMemberEligible(corpse, groupMember)) + .filter(groupMember -> !isEntertainer(groupMember) && isMemberNearby(corpse, groupMember)) .forEach(eligibleMember -> new ExperienceIntent(eligibleMember, "combat", experienceGained).broadcast()); } } @@ -185,14 +160,49 @@ public class CombatXpService extends Service { return creature.hasSkill("class_entertainer_phase1_novice"); } + private int calculateXpGain(CreatureObject killer, CreatureObject corpse, short killerLevel) { + int experienceGained; + short corpseLevel = corpse.getLevel(); + // If the difference between killer and corpse is 10 or above, they only gain 1 xp + if (killerLevel - corpseLevel >= 10) { + experienceGained = 1; + } else { + XpData xpForLevel = this.xpData.get(corpseLevel); + + if (xpForLevel == null) { + Log.e(this, "%s received no XP: No XP data was found for level %d!", killer, corpseLevel); + return 0; + } + + CreatureDifficulty creatureDifficulty = corpse.getDifficulty(); + + switch (creatureDifficulty) { + case BOSS: + experienceGained = xpForLevel.getBossXp(); + break; + case ELITE: + experienceGained = xpForLevel.getEliteXp(); + break; + case NORMAL: + experienceGained = xpForLevel.getXp(); + break; + default: + Log.e(this, "%s received no XP: Unsupported creature difficulty %s of corpse %s", killer, creatureDifficulty, corpse); + return 0; + } + } + + return experienceGained; + } + /** * @return true if {@code groupMember} is an observer of {@code corpse} */ - private boolean isMemberEligible(CreatureObject corpse, CreatureObject groupMember) { + private boolean isMemberNearby(CreatureObject corpse, CreatureObject groupMember) { return corpse.getObservers().contains(groupMember); } - private class XpData { + private static class XpData { private final int xp; private final int eliteXp; private final int bossXp; From 709db360e1d4aac76453b9600f70f8df47be3884 Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Wed, 12 Oct 2016 14:24:28 +0200 Subject: [PATCH 14/21] Weapon damage now affects combat calculations --- scripts/commands/combat/meleeHit.js | 2 +- scripts/commands/combat/placeholder.txt | 0 .../commands/combat/rangedShotlightrifle.js | 7 ++++ scripts/commands/combat/rangedShotpistol.js | 7 ++++ scripts/commands/combat/rangedShotrifle.js | 7 ++++ .../objects/weapon/WeaponObject.java | 35 ++++++++++++++++--- src/services/combat/CombatManager.java | 18 +++++++++- .../player/CharacterCreationService.java | 2 ++ 8 files changed, 71 insertions(+), 7 deletions(-) delete mode 100644 scripts/commands/combat/placeholder.txt create mode 100644 scripts/commands/combat/rangedShotlightrifle.js create mode 100644 scripts/commands/combat/rangedShotpistol.js create mode 100644 scripts/commands/combat/rangedShotrifle.js diff --git a/scripts/commands/combat/meleeHit.js b/scripts/commands/combat/meleeHit.js index ff937081..cc849b9e 100644 --- a/scripts/commands/combat/meleeHit.js +++ b/scripts/commands/combat/meleeHit.js @@ -3,5 +3,5 @@ function canPerform(source, target, command) { } function doCombat(source, target, command) { - return 100; + return 0; } diff --git a/scripts/commands/combat/placeholder.txt b/scripts/commands/combat/placeholder.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/scripts/commands/combat/rangedShotlightrifle.js b/scripts/commands/combat/rangedShotlightrifle.js new file mode 100644 index 00000000..cc849b9e --- /dev/null +++ b/scripts/commands/combat/rangedShotlightrifle.js @@ -0,0 +1,7 @@ +function canPerform(source, target, command) { + return (Java.type("resources.combat.CombatStatus")).SUCCESS; +} + +function doCombat(source, target, command) { + return 0; +} diff --git a/scripts/commands/combat/rangedShotpistol.js b/scripts/commands/combat/rangedShotpistol.js new file mode 100644 index 00000000..cc849b9e --- /dev/null +++ b/scripts/commands/combat/rangedShotpistol.js @@ -0,0 +1,7 @@ +function canPerform(source, target, command) { + return (Java.type("resources.combat.CombatStatus")).SUCCESS; +} + +function doCombat(source, target, command) { + return 0; +} diff --git a/scripts/commands/combat/rangedShotrifle.js b/scripts/commands/combat/rangedShotrifle.js new file mode 100644 index 00000000..cc849b9e --- /dev/null +++ b/scripts/commands/combat/rangedShotrifle.js @@ -0,0 +1,7 @@ +function canPerform(source, target, command) { + return (Java.type("resources.combat.CombatStatus")).SUCCESS; +} + +function doCombat(source, target, command) { + return 0; +} diff --git a/src/resources/objects/weapon/WeaponObject.java b/src/resources/objects/weapon/WeaponObject.java index ee95b35f..91cdd005 100644 --- a/src/resources/objects/weapon/WeaponObject.java +++ b/src/resources/objects/weapon/WeaponObject.java @@ -27,18 +27,24 @@ ***********************************************************************************/ package resources.objects.weapon; +import intents.chat.PersistentMessageIntent; +import intents.object.DestroyObjectIntent; +import main.ProjectSWG.CoreException; import network.packets.swg.zone.baselines.Baseline.BaselineType; import resources.combat.DamageType; +import resources.encodables.player.Mail; import resources.network.BaselineBuilder; import resources.network.NetBuffer; import resources.network.NetBufferStream; +import resources.objects.creature.CreatureObject; import resources.objects.tangible.TangibleObject; import resources.player.Player; +import services.CoreManager; public class WeaponObject extends TangibleObject { - private static final long serialVersionUID = 1L; - + private int minDamage; + private int maxDamage; // WEAO03 private float attackSpeed = 0.5f; private int accuracy; @@ -118,6 +124,22 @@ public class WeaponObject extends TangibleObject { public void setType(WeaponType type) { this.type = type; } + + public int getMinDamage() { + return minDamage; + } + + public void setMinDamage(int minDamage) { + this.minDamage = minDamage; + } + + public int getMaxDamage() { + return maxDamage; + } + + public void setMaxDamage(int maxDamage) { + this.maxDamage = maxDamage; + } @Override public boolean equals(Object o) { @@ -176,7 +198,9 @@ public class WeaponObject extends TangibleObject { @Override public void save(NetBufferStream stream) { super.save(stream); - stream.addByte(1); + stream.addByte(2); + stream.addInt(minDamage); + stream.addInt(maxDamage); stream.addAscii(damageType.name()); stream.addAscii(elementalType != null ? elementalType.name() : ""); stream.addInt(elementalValue); @@ -189,7 +213,9 @@ public class WeaponObject extends TangibleObject { public void read(NetBufferStream stream) { super.read(stream); switch(stream.getByte()) { - case 1: + case 0: + minDamage = stream.getInt(); + maxDamage = stream.getInt(); damageType = DamageType.valueOf(stream.getAscii()); String elementalTypeName = stream.getAscii(); @@ -198,7 +224,6 @@ public class WeaponObject extends TangibleObject { elementalType = DamageType.valueOf(elementalTypeName); elementalValue = stream.getInt(); - default: attackSpeed = stream.getFloat(); maxRange = stream.getFloat(); type = WeaponType.valueOf(stream.getAscii()); diff --git a/src/services/combat/CombatManager.java b/src/services/combat/CombatManager.java index 018161c0..f6221f83 100644 --- a/src/services/combat/CombatManager.java +++ b/src/services/combat/CombatManager.java @@ -43,6 +43,7 @@ import intents.chat.ChatCommandIntent; import intents.combat.CreatureKilledIntent; import intents.combat.DeathblowIntent; import java.util.Iterator; +import java.util.Random; import java.util.concurrent.Future; import resources.Posture; import resources.PvpFaction; @@ -71,6 +72,7 @@ public class CombatManager extends Manager { private final Set regeneratingHealthCreatures; // Only allowed outside of combat private final Set regeneratingActionCreatures; // Always allowed private final Map> incapacitatedCreatures; + private final Random random; private final CorpseService corpseService; private final CombatXpService combatXpService; @@ -82,6 +84,7 @@ public class CombatManager extends Manager { regeneratingHealthCreatures = new HashSet<>(); regeneratingActionCreatures = new HashSet<>(); incapacitatedCreatures = new HashMap<>(); + random = new Random(); corpseService = new CorpseService(); combatXpService = new CombatXpService(); @@ -264,7 +267,9 @@ public class CombatManager extends Manager { enterCombat(target); target.addDefender(source); source.addDefender(target); - // Note: This will not kill anyone + + addWeaponDamage(source, command, info); + if (target.getHealth() <= info.getDamage()) doCreatureDeath(target, source); else @@ -496,6 +501,17 @@ public class CombatManager extends Manager { return CombatStatus.SUCCESS; } + private void addWeaponDamage(CreatureObject source, CombatCommand command, AttackInfoLight info) { + int abilityDamage = info.getDamage(); + WeaponObject weapon = source.getEquippedWeapon(); + int minDamage = weapon.getMinDamage(); + int weaponDamage = random.nextInt((weapon.getMaxDamage() - minDamage) + 1) + minDamage; + + // TODO multiply with weaponPercentAdd from CombatCommand + + info.setDamage(abilityDamage + weaponDamage); + } + private void showFlyText(TangibleObject obj, String text, Scale scale, Color c, ShowFlyText.Flag ... flags) { obj.sendSelf(new ShowFlyText(obj.getObjectId(), text, scale, new RGB(c), flags)); } diff --git a/src/services/player/CharacterCreationService.java b/src/services/player/CharacterCreationService.java index a500d2c3..4caa6621 100644 --- a/src/services/player/CharacterCreationService.java +++ b/src/services/player/CharacterCreationService.java @@ -406,6 +406,8 @@ public class CharacterCreationService extends Service { defWeapon.setMaxRange(5); defWeapon.setType(WeaponType.UNARMED); defWeapon.setAttackSpeed(1); + defWeapon.setMinDamage(50); + defWeapon.setMaxDamage(100); creatureObj.setEquippedWeapon(defWeapon); defWeapon.moveToContainer(creatureObj); // Occupies the default_weapon slot createInventoryObject(objManager, creatureObj, "object/tangible/inventory/shared_character_inventory.iff"); From be4eff77a1ea508f0a8d626d5abcadd4a418aebc Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Wed, 12 Oct 2016 14:25:12 +0200 Subject: [PATCH 15/21] Fixed an issue where ranged weapons weren't shooting --- src/services/objects/StaticItemService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/services/objects/StaticItemService.java b/src/services/objects/StaticItemService.java index 8737e847..2422e357 100644 --- a/src/services/objects/StaticItemService.java +++ b/src/services/objects/StaticItemService.java @@ -576,13 +576,15 @@ public final class StaticItemService extends Service { object.addAttribute("cat_wpn_other.wpn_range", rangeString); // Ziggy: Special Action Cost would go under cat_wpn_other as well, but it's a pre-NGE artifact. - // TODO set all WeaponObject properties WeaponObject weapon = (WeaponObject) object; + weapon.setType(category); weapon.setAttackSpeed(attackSpeed); weapon.setMinRange(minRange); weapon.setMaxRange(maxRange); weapon.setDamageType(damageTypeEnum); weapon.setElementalType(elementalTypeEnum); + weapon.setMinDamage(minDamage); + weapon.setMaxDamage(maxDamage); } } From c6159b0e23fd5c00fb84748f8982c513b785e9de Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Wed, 12 Oct 2016 15:42:53 +0200 Subject: [PATCH 16/21] Carbines can now be fired --- scripts/commands/combat/rangedShotlightRifle.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 scripts/commands/combat/rangedShotlightRifle.js diff --git a/scripts/commands/combat/rangedShotlightRifle.js b/scripts/commands/combat/rangedShotlightRifle.js new file mode 100644 index 00000000..cc849b9e --- /dev/null +++ b/scripts/commands/combat/rangedShotlightRifle.js @@ -0,0 +1,7 @@ +function canPerform(source, target, command) { + return (Java.type("resources.combat.CombatStatus")).SUCCESS; +} + +function doCombat(source, target, command) { + return 0; +} From 22993660ae001e5abb970379eafa53369c2bcc92 Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Wed, 12 Oct 2016 15:43:21 +0200 Subject: [PATCH 17/21] Weapon damage is now accounted for --- scripts/commands/combat/rangedShotlightrifle.js | 7 ------- src/resources/commands/CombatCommand.java | 9 +++++++++ src/services/combat/CombatManager.java | 2 +- src/services/commands/CommandService.java | 2 ++ 4 files changed, 12 insertions(+), 8 deletions(-) delete mode 100644 scripts/commands/combat/rangedShotlightrifle.js diff --git a/scripts/commands/combat/rangedShotlightrifle.js b/scripts/commands/combat/rangedShotlightrifle.js deleted file mode 100644 index cc849b9e..00000000 --- a/scripts/commands/combat/rangedShotlightrifle.js +++ /dev/null @@ -1,7 +0,0 @@ -function canPerform(source, target, command) { - return (Java.type("resources.combat.CombatStatus")).SUCCESS; -} - -function doCombat(source, target, command) { - return 0; -} diff --git a/src/resources/commands/CombatCommand.java b/src/resources/commands/CombatCommand.java index eea0160d..28e9eebc 100644 --- a/src/resources/commands/CombatCommand.java +++ b/src/resources/commands/CombatCommand.java @@ -48,6 +48,7 @@ public class CombatCommand extends Command { private boolean ignoreDistance; private boolean pvpOnly; private int attackRolls; + private float percentAddFromWeapon; public CombatCommand(String name) { super(name); @@ -146,5 +147,13 @@ public class CombatCommand extends Command { public void setAnimations(WeaponType type, String [] animations) { this.animations.put(type, animations); } + + public float getPercentAddFromWeapon() { + return percentAddFromWeapon; + } + + public void setPercentAddFromWeapon(float percentAddFromWeapon) { + this.percentAddFromWeapon = percentAddFromWeapon; + } } diff --git a/src/services/combat/CombatManager.java b/src/services/combat/CombatManager.java index f6221f83..fca26df4 100644 --- a/src/services/combat/CombatManager.java +++ b/src/services/combat/CombatManager.java @@ -507,7 +507,7 @@ public class CombatManager extends Manager { int minDamage = weapon.getMinDamage(); int weaponDamage = random.nextInt((weapon.getMaxDamage() - minDamage) + 1) + minDamage; - // TODO multiply with weaponPercentAdd from CombatCommand + weaponDamage *= command.getPercentAddFromWeapon(); info.setDamage(abilityDamage + weaponDamage); } diff --git a/src/services/commands/CommandService.java b/src/services/commands/CommandService.java index feffb0a7..f0be9ef8 100644 --- a/src/services/commands/CommandService.java +++ b/src/services/commands/CommandService.java @@ -337,6 +337,7 @@ public class CommandService extends Service { int pvpOnly = combatCommands.getColumnFromName("pvp_only"); int attackRolls = combatCommands.getColumnFromName("attack_rolls"); int animDefault = combatCommands.getColumnFromName("animDefault"); + int percentAddFromWeapon = combatCommands.getColumnFromName("percentAddFromWeapon"); // animDefault anim_unarmed anim_onehandmelee anim_twohandmelee anim_polearm // anim_pistol anim_lightRifle anim_carbine anim_rifle anim_heavyweapon // anim_thrown anim_onehandlightsaber anim_twohandlightsaber anim_polearmlightsaber @@ -358,6 +359,7 @@ public class CommandService extends Service { cc.setPvpOnly(((int) cmdRow[pvpOnly]) != 0); cc.setAttackRolls((int) cmdRow[attackRolls]); cc.setDefaultAnimation(getAnimationList((String) cmdRow[animDefault])); + cc.setPercentAddFromWeapon((float) cmdRow[percentAddFromWeapon]); cc.setAnimations(WeaponType.UNARMED, getAnimationList((String) cmdRow[animDefault+1])); cc.setAnimations(WeaponType.ONE_HANDED_MELEE, getAnimationList((String) cmdRow[animDefault+2])); cc.setAnimations(WeaponType.TWO_HANDED_MELEE, getAnimationList((String) cmdRow[animDefault+3])); From 02973c7c82bd162a35d48013a331d5cdbedaf4ae Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Wed, 12 Oct 2016 16:02:53 +0200 Subject: [PATCH 18/21] Fixed WeaponObject versioning --- .../objects/weapon/WeaponObject.java | 38 ++++++++----------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/src/resources/objects/weapon/WeaponObject.java b/src/resources/objects/weapon/WeaponObject.java index 91cdd005..e93a7283 100644 --- a/src/resources/objects/weapon/WeaponObject.java +++ b/src/resources/objects/weapon/WeaponObject.java @@ -27,19 +27,13 @@ ***********************************************************************************/ package resources.objects.weapon; -import intents.chat.PersistentMessageIntent; -import intents.object.DestroyObjectIntent; -import main.ProjectSWG.CoreException; import network.packets.swg.zone.baselines.Baseline.BaselineType; import resources.combat.DamageType; -import resources.encodables.player.Mail; import resources.network.BaselineBuilder; import resources.network.NetBuffer; import resources.network.NetBufferStream; -import resources.objects.creature.CreatureObject; import resources.objects.tangible.TangibleObject; import resources.player.Player; -import services.CoreManager; public class WeaponObject extends TangibleObject { @@ -198,7 +192,7 @@ public class WeaponObject extends TangibleObject { @Override public void save(NetBufferStream stream) { super.save(stream); - stream.addByte(2); + stream.addByte(0); stream.addInt(minDamage); stream.addInt(maxDamage); stream.addAscii(damageType.name()); @@ -212,23 +206,21 @@ public class WeaponObject extends TangibleObject { @Override public void read(NetBufferStream stream) { super.read(stream); - switch(stream.getByte()) { - case 0: - minDamage = stream.getInt(); - maxDamage = stream.getInt(); - damageType = DamageType.valueOf(stream.getAscii()); - String elementalTypeName = stream.getAscii(); - - // A weapon doesn't necessarily have an elemental type - if(!elementalTypeName.isEmpty()) - elementalType = DamageType.valueOf(elementalTypeName); - - elementalValue = stream.getInt(); - attackSpeed = stream.getFloat(); - maxRange = stream.getFloat(); - type = WeaponType.valueOf(stream.getAscii()); - break; + stream.getByte(); + minDamage = stream.getInt(); + maxDamage = stream.getInt(); + damageType = DamageType.valueOf(stream.getAscii()); + String elementalTypeName = stream.getAscii(); + + // A weapon doesn't necessarily have an elemental type + if (!elementalTypeName.isEmpty()) { + elementalType = DamageType.valueOf(elementalTypeName); } + + elementalValue = stream.getInt(); + attackSpeed = stream.getFloat(); + maxRange = stream.getFloat(); + type = WeaponType.valueOf(stream.getAscii()); } } \ No newline at end of file From e0feeaa19f3868027eacda75bf6aedacd5516e02 Mon Sep 17 00:00:00 2001 From: Undercova PSWG Date: Wed, 12 Oct 2016 15:49:13 +0000 Subject: [PATCH 19/21] Fixed weapon type for "Pulse Cannon" and Commando CL30 roadmap reward rifle --- serverdata/items/weapon.sdb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/serverdata/items/weapon.sdb b/serverdata/items/weapon.sdb index d9efe8d7..68ce41db 100644 --- a/serverdata/items/weapon.sdb +++ b/serverdata/items/weapon.sdb @@ -86,7 +86,7 @@ weapon_event_hairtrigger_carbine_03_01 object/weapon/ranged/carbine/event_carbin weapon_eweb_blaster_rifle object/weapon/ranged/rifle/rifle_eweb.iff weapon E-Web Rifle 1 1000 485 980 ranged_weapon RIFLE energy none 0 80 100 0 64 - 915 915 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 90 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE FALSE - 0 0 FALSE 0 4 1 - - weapon_gcw_carbine_charric_03_01 object/weapon/ranged/carbine/carbine_charric.iff weapon Charric Carbine 1 1000 242 482 ranged_weapon CARBINE kinetic none 0 60 100 0 50 - 603 603 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 65 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE FALSE - 0 600 FALSE 0 3 2 - - weapon_gcw_dh18a_pistol_03_01 object/weapon/ranged/pistol/pistol_dh18a_gcw.iff weapon DH-18A Blaster Pistol Prototype 1 1000 161 321 ranged_weapon PISTOL kinetic none 0 40 100 0 35 - 603 602 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 65 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE FALSE - 0 600 FALSE 0 3 2 - - -weapon_gcw_heavy_pulse_cannon_03_01 object/weapon/ranged/heavy/heavy_pulse_cannon.iff weapon Pulse Cannon 1 1000 462 777 ranged_weapon HEAVY_WEAPON kinetic heat 15 100 100 0 64 - 643 643 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 65 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE FALSE - 0 600 FALSE 0 3 2 GCW - +weapon_gcw_heavy_pulse_cannon_03_01 object/weapon/ranged/heavy/heavy_pulse_cannon.iff weapon Pulse Cannon 1 1000 462 777 ranged_weapon GROUND_TARGETTING kinetic heat 15 100 100 0 64 - 643 643 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 65 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE FALSE - 0 600 FALSE 0 3 2 GCW - weapon_gcw_lance_03_01 object/weapon/melee/polearm/lance_gcw_gand_shockprod.iff weapon Gand Shockprod Staff 1 1000 428 655 melee_weapon POLEARM_MELEE kinetic none 0 100 100 0 5 - 567 562 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 65 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE FALSE - 0 600 FALSE 0 3 2 - - weapon_gcw_tc22_rifle_03_01 object/weapon/ranged/rifle/rifle_tc22_blaster.iff weapon TC-22 Blaster Rifle Replica 1 1000 322 643 ranged_weapon RIFLE kinetic none 0 80 100 0 64 - 603 602 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 65 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE FALSE - 0 600 FALSE 0 3 2 - - weapon_grenade_fragmentation_01_01 object/weapon/ranged/grenade/grenade_fragmentation_generic.iff weapon Fragmentation Grenade 1 1000 325 650 ranged_weapon THROWN kinetic none 0 1000 100 0 40 - 49 49 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 1 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 0 FALSE 3 2 1 - int:reuseTimer=5,string:effect_class=fragmentation @@ -105,7 +105,7 @@ weapon_knuckler_fs_roadmap_01_02 object/weapon/melee/special/vibroknuckler_stati weapon_knuckler_fs_roadmap_02_02 object/weapon/melee/special/vibroknuckler_static.iff weapon Neophyte Vibroknuckler 1 1000 188 375 melee_weapon UNARMED kinetic none 0 100 100 0 5 - 282 282 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 30 force_sensitive TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE strength_modified=5 0 2200 FALSE 0 2 2 lvl 30 roadmap - weapon_knuckler_smuggler_roadmap_01_02 object/weapon/ranged/pistol/pistol_scout_blaster_static.iff weapon Scoundrel's Scout Blaster 1 1000 73 145 ranged_weapon PISTOL kinetic none 0 40 100 0 35 - 282 273 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 30 smuggler TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=5 0 2200 FALSE 0 2 2 lvl 30 roadmap - weapon_knuckler_smuggler_roadmap_02_02 object/weapon/ranged/pistol/pistol_striker_static.iff weapon Precise Striker Pistol 1 1000 131 261 ranged_weapon PISTOL kinetic none 0 40 100 0 35 - 490 490 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 50 smuggler TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=10 0 4500 FALSE 0 2 2 lvl 50 roadmap - -weapon_lightningbeam_commando_roadmap_01_02 object/weapon/ranged/rifle/rifle_dlt20.iff weapon Precise DLT-20 1 1000 182 363 ranged_weapon HEAVY_WEAPON energy none 0 100 100 0 64 - 273 273 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 30 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=5 0 2200 FALSE 0 2 2 lvl 30 roadmap - +weapon_lightningbeam_commando_roadmap_01_02 object/weapon/ranged/rifle/rifle_dlt20.iff weapon Precise DLT-20 1 1000 182 363 ranged_weapon RIFLE energy none 0 100 100 0 64 - 273 273 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 30 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=5 0 2200 FALSE 0 2 2 lvl 30 roadmap - weapon_magna_guard_polearm_04_01 object/weapon/melee/polearm/lance_staff_magna_guard.iff weapon MagnaGuard Electrostaff 1 1000 700 1000 melee_weapon POLEARM_MELEE kinetic electricity 20 100 100 0 5 - 900 890 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 75 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE FALSE - 0 1000 FALSE 0 4 1 pvp BF reward - weapon_mandalorian_carbine_04_01 object/weapon/ranged/carbine/carbine_mandalorian.iff weapon Crusader M-XIII Carbine 1 1000 415 755 ranged_weapon CARBINE energy none 0 60 100 0 50 - 975 975 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 75 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=10,constitution_modified=5 0 5000 FALSE 0 4 1 - - weapon_mandalorian_heavy_04_01 object/weapon/ranged/heavy/heavy_mandalorian.iff weapon Crusader M-XX Heavy Rifle 1 1000 800 1300 ranged_weapon GROUND_TARGETTING kinetic electricity 50 100 100 0 64 - 1050 1050 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 75 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE FALSE precision_modified=10,constitution_modified=5 0 5000 FALSE 0 4 2 - - From c3eb3f9ed9f5fa60449e010173efebc7f1229f5f Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Wed, 12 Oct 2016 18:42:34 +0200 Subject: [PATCH 20/21] Fixed heavy weapons not being loaded and DPS attribute is now applied --- serverdata/items/weapon.sdb | 14 +++++++------- src/services/objects/StaticItemService.java | 11 ++++++++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/serverdata/items/weapon.sdb b/serverdata/items/weapon.sdb index 68ce41db..81314279 100644 --- a/serverdata/items/weapon.sdb +++ b/serverdata/items/weapon.sdb @@ -228,16 +228,16 @@ weapon_tow_carbine_geo_05_01 object/weapon/ranged/carbine/carbine_geo_generic.if weapon_tow_carbine_sfor_03_01 object/weapon/ranged/carbine/som_carbine_republic_sfor_generic.iff weapon Kubaza Carbine 1 1000 375 750 ranged_weapon CARBINE energy electricity 28 60 100 0 50 - 938 938 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 6000 FALSE 0 3 1 ToW expansion - weapon_tow_carbine_sfor_05_01 object/weapon/ranged/carbine/som_carbine_republic_sfor_generic.iff weapon HK-47 Carbine 1 1000 395 790 ranged_weapon CARBINE energy electricity 34 60 100 0 50 - 938 988 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 7000 FALSE 0 5 1 ToW expansion - weapon_tow_carbine_wookiee_06_01 object/weapon/ranged/carbine/ep3/carbine_wookiee_bowcaster_generic.iff weapon Malevolent Bowcaster 1 1000 395 790 ranged_weapon CARBINE energy none 0 60 100 0 50 - 938 988 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 - TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE - 0 10000 FALSE 0 6 1 ToW expansion - -weapon_tow_flamer_01_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Heavy Republic Flame Thrower 1 1000 148 295 ranged_weapon DIRECTIONAL energy heat 28 25 100 0 20 - 938 886 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=10 0 4000 FALSE 0 1 2 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 -weapon_tow_flamer_02_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Heavy Republic Flame Thrower 1 1000 153 305 ranged_weapon DIRECTIONAL energy heat 30 25 100 0 20 - 938 916 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=11 0 4500 FALSE 0 2 2 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 -weapon_tow_flamer_03_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Heavy Republic Flame Thrower 1 1000 156 312 ranged_weapon DIRECTIONAL energy heat 32 25 100 0 20 - 938 936 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=11 0 6000 FALSE 0 3 2 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 -weapon_tow_flamer_04_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Heavy Republic Flame Thrower 1 1000 162 323 ranged_weapon DIRECTIONAL energy heat 34 25 100 0 20 - 938 970 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=12 0 6500 FALSE 0 4 2 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 -weapon_tow_flamer_05_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Heavy Republic Flame Thrower 1 1000 165 329 ranged_weapon DIRECTIONAL energy heat 40 25 100 0 20 - 938 988 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=12 0 7000 FALSE 0 5 2 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 +weapon_tow_flamer_01_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Heavy Republic Flame Thrower 1 1000 148 295 ranged_weapon DIRECTIONAL_TARGET_WEAPON energy heat 28 25 100 0 20 - 938 886 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=10 0 4000 FALSE 0 1 2 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 +weapon_tow_flamer_02_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Heavy Republic Flame Thrower 1 1000 153 305 ranged_weapon DIRECTIONAL_TARGET_WEAPON energy heat 30 25 100 0 20 - 938 916 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=11 0 4500 FALSE 0 2 2 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 +weapon_tow_flamer_03_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Heavy Republic Flame Thrower 1 1000 156 312 ranged_weapon DIRECTIONAL_TARGET_WEAPON energy heat 32 25 100 0 20 - 938 936 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=11 0 6000 FALSE 0 3 2 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 +weapon_tow_flamer_04_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Heavy Republic Flame Thrower 1 1000 162 323 ranged_weapon DIRECTIONAL_TARGET_WEAPON energy heat 34 25 100 0 20 - 938 970 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=12 0 6500 FALSE 0 4 2 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 +weapon_tow_flamer_05_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Heavy Republic Flame Thrower 1 1000 165 329 ranged_weapon DIRECTIONAL_TARGET_WEAPON energy heat 40 25 100 0 20 - 938 988 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE precision_modified=12 0 7000 FALSE 0 5 2 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 weapon_tow_grenade_fragmentation_04_01 object/weapon/ranged/grenade/grenade_fragmentation_generic.iff weapon Old Republic Fragmentation Grenade 1 1000 721 1442 ranged_weapon THROWN energy none 0 1000 100 0 40 - 108 108 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 100 FALSE 15 4 1 ToW expansion int:reuseTimer=5,string:effect_class=fragmentation weapon_tow_hammer_03_01 object/weapon/melee/2h_sword/2h_sword_maul.iff weapon Hammer of the Miner 1 1000 667 1333 melee_weapon TWO_HANDED_MELEE kinetic none 0 100 100 0 5 - 1000 1000 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 64 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE strength_modified=12 0 6000 FALSE 0 3 2 ToW expansion - weapon_tow_heavy_acid_beam_04_01 object/weapon/ranged/heavy/heavy_acid_beam_static.iff weapon Devastator Acid Launcher 1 1000 683 1366 ranged_weapon GROUND_TARGETTING energy acid 128 100 100 0 64 - 1000 1025 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 6500 FALSE 0 4 3 ToW expansion float:intAOEDamagePercent=0.0,int:intWeaponType=6,string:strWeaponType=acid_beam -weapon_tow_heavy_flamer_repub_06_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Malevolent Flamethrower 1 1000 175 350 ranged_weapon DIRECTIONAL energy heat 30 25 100 0 20 - 1000 1050 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 10000 FALSE 0 6 1 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 -weapon_tow_heavy_repub_flamethrower_05_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Oppressor Flame Thrower 1 1000 175 350 ranged_weapon DIRECTIONAL energy heat 40 25 100 0 20 - 1000 1050 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 7000 FALSE 0 5 1 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 +weapon_tow_heavy_flamer_repub_06_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Malevolent Flamethrower 1 1000 175 350 ranged_weapon DIRECTIONAL_TARGET_WEAPON energy heat 30 25 100 0 20 - 1000 1050 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 10000 FALSE 0 6 1 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 +weapon_tow_heavy_repub_flamethrower_05_01 object/weapon/ranged/heavy/som_republic_flamer_generic.iff weapon Oppressor Flame Thrower 1 1000 175 350 ranged_weapon DIRECTIONAL_TARGET_WEAPON energy heat 40 25 100 0 20 - 1000 1050 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 7000 FALSE 0 5 1 ToW expansion float:intAOEDamagePercent=0.55,int:intWeaponType=9 weapon_tow_heavy_rocket_launcher_05_01 object/weapon/ranged/heavy/heavy_rocket_launcher_generic.iff weapon AK-Prime Rocket Launcher 1 1000 659 1317 ranged_weapon GROUND_TARGETTING kinetic heat 135 100 100 0 64 - 938 988 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 commando TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 7000 FALSE 0 5 1 ToW expansion - weapon_tow_knuckler_05_01 object/weapon/melee/special/vibroknuckler_static.iff weapon Forward Commander Knuckler 1 1000 659 1317 melee_weapon UNARMED kinetic none 0 100 100 0 5 - 938 988 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 7000 FALSE 0 5 1 ToW expansion - weapon_tow_knuckler_blacksun_06_01 object/weapon/melee/special/blacksun_razor_generic.iff weapon Malevolent Razorknuckler 1 1000 700 1400 melee_weapon UNARMED kinetic none 0 100 100 0 5 - 1000 1050 0 - FALSE - 0 0 - - - 0 - - - - - - - - 0 0 - - - 0 - 88 - TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE - 0 10000 FALSE 0 6 1 ToW expansion - diff --git a/src/services/objects/StaticItemService.java b/src/services/objects/StaticItemService.java index a454304e..c050c250 100644 --- a/src/services/objects/StaticItemService.java +++ b/src/services/objects/StaticItemService.java @@ -461,6 +461,7 @@ public final class StaticItemService extends Service { private String elementalTypeString; private short elementalDamage; private String procEffect; + private String dps; // special_attack_cost: Pre-NGE artifact? (SAC) public WeaponAttributes(String itemName, String iffTemplate) { @@ -499,10 +500,11 @@ public final class StaticItemService extends Service { case "ONE_HANDED_SABER": category = WeaponType.ONE_HANDED_SABER; break; case "TWO_HANDED_SABER": category = WeaponType.TWO_HANDED_SABER; break; case "POLEARM_SABER": category = WeaponType.POLEARM_SABER; break; - case "DIRECTIONAL_TARGET_WEAPON": category = WeaponType.DIRECTIONAL_TARGET_WEAPON; break; // Free targeting + case "GROUND_TARGETTING": category = WeaponType.HEAVY_WEAPON; break; + case "DIRECTIONAL_TARGET_WEAPON": category = WeaponType.DIRECTIONAL_TARGET_WEAPON; break; case "LIGHT_RIFLE": category = WeaponType.LIGHT_RIFLE; break; default: - // TODO log the fact that the weapon type isn't recognised. + Log.e(this, "Unrecognised weapon type %s at row %d", weaponType, resultSet.getRow()); // We return false here. That way, we don't store the // itemName in the Map and the item can never be spawned. return false; @@ -535,7 +537,7 @@ public final class StaticItemService extends Service { procEffect = "@ui_buff:" + procEffectString; } - // TODO calculate DPS + dps = resultSet.getString("actual_dps"); return true; } @@ -552,6 +554,8 @@ public final class StaticItemService extends Service { object.addAttribute("cat_wpn_damage.wpn_elemental_value", String.valueOf(elementalDamage)); } + object.addAttribute("cat_wpn_damage.weapon_dps", dps); + if(procEffect != null) // Not all weapons have a proc effect object.addAttribute("proc_name", procEffect); // TODO set DPS @@ -559,6 +563,7 @@ public final class StaticItemService extends Service { object.addAttribute("cat_wpn_other.wpn_range", rangeString); // Ziggy: Special Action Cost would go under cat_wpn_other as well, but it's a pre-NGE artifact. + // TODO set all WeaponObject properties WeaponObject weapon = (WeaponObject) object; weapon.setType(category); weapon.setAttackSpeed(attackSpeed); From fa46576f5aa96ad3985cca96d5bd2116ce4a54df Mon Sep 17 00:00:00 2001 From: Mads Boddum Date: Wed, 12 Oct 2016 18:43:47 +0200 Subject: [PATCH 21/21] Removed an old TODO in StaticItemService --- src/services/objects/StaticItemService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/objects/StaticItemService.java b/src/services/objects/StaticItemService.java index c050c250..ce0705a0 100644 --- a/src/services/objects/StaticItemService.java +++ b/src/services/objects/StaticItemService.java @@ -563,7 +563,6 @@ public final class StaticItemService extends Service { object.addAttribute("cat_wpn_other.wpn_range", rangeString); // Ziggy: Special Action Cost would go under cat_wpn_other as well, but it's a pre-NGE artifact. - // TODO set all WeaponObject properties WeaponObject weapon = (WeaponObject) object; weapon.setType(category); weapon.setAttackSpeed(attackSpeed);