diff --git a/scripts/commands/holoemote.py b/scripts/commands/holoemote.py index 37029c45..022e7746 100644 --- a/scripts/commands/holoemote.py +++ b/scripts/commands/holoemote.py @@ -14,6 +14,10 @@ def run(core, actor, target, commandString): installedEmote = '' + if actor.hasCooldown('holoEmote'): + actor.sendSystemMessage('Your Holo-Emote generator is in use or recharging.', 0) # Not sure if this is correct. + return + if player.getHoloEmote() is not None: installedEmote = player.getHoloEmote().replace('holoemote_','') @@ -43,7 +47,9 @@ def run(core, actor, target, commandString): effectObj = 'clienteffect/holoemote_' + commandString + '.cef' actor.playEffectObject(effectObj, 'head') player.setHoloEmoteUses(player.getHoloEmoteUses() - 1) - # TODO: Cooldowns for the holo-emote's + + actor.addCooldown('holoEmote', long(30 * 1000)) + return def holoPrompt(player, emote): diff --git a/scripts/commands/setgodmode.py b/scripts/commands/setgodmode.py index eeaf8ae1..18c5f4f2 100644 --- a/scripts/commands/setgodmode.py +++ b/scripts/commands/setgodmode.py @@ -98,4 +98,9 @@ def run(core, actor, target, commandString): actor.setInStealth(True) actor.setRadarVisible(False) actor.sendSystemMessage('You are now hidden from players. "Stealth Effect" is not implemented, however players still won\'t be able to see you. Type /setgodmode stealth again to be visible.', 0) + + elif command == 'holoEmote' and arg1: + playerObject.setHoloEmote('holoemote_' + arg1) + playerObject.setHoloEmoteUses(20) + actor.sendSystemMessage('Holo-Emote Generator set to ' + 'holoemote_' + arg1, 0) return diff --git a/src/resources/common/Cooldown.java b/src/resources/common/Cooldown.java new file mode 100644 index 00000000..edaf7e94 --- /dev/null +++ b/src/resources/common/Cooldown.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package resources.common; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public class Cooldown { + private long startTimestamp; + private long endTimestamp; + + private ScheduledFuture removalTask; + + public Cooldown(long end) { + startTimestamp = System.currentTimeMillis(); + endTimestamp = startTimestamp + end; + } + + public long getStartTimestamp() { + return startTimestamp; + } + + public void setStartTimestamp(long startTimestamp) { + this.startTimestamp = startTimestamp; + } + + public long getEndTimestamp() { + return endTimestamp; + } + + public void setEndTimestamp(long endTimestamp) { + this.endTimestamp = endTimestamp; + } + + public ScheduledFuture getRemovalTask() { + return removalTask; + } + + public void setRemovalTask(ScheduledFuture removalTask) { + this.removalTask = removalTask; + } +} diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 40f7d8f0..c0eeb579 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -26,7 +26,10 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import org.apache.mina.core.buffer.IoBuffer; @@ -46,6 +49,7 @@ import com.sleepycat.persist.model.NotPersistent; import main.NGECore; import engine.clients.Client; +import resources.common.Cooldown; import resources.objects.Buff; import resources.objects.DamageOverTime; import resources.objects.SWGList; @@ -177,6 +181,8 @@ public class CreatureObject extends TangibleObject implements IPersistent { private int coverCharge; @NotPersistent private TangibleObject conversingNpc; + @NotPersistent + private ConcurrentHashMap cooldowns = new ConcurrentHashMap(); public CreatureObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String Template) { super(objectID, planet, Template, position, orientation); @@ -1722,4 +1728,43 @@ public class CreatureObject extends TangibleObject implements IPersistent { } } + public void addCooldown(String ability, long duration) { + if (cooldowns.containsKey(ability)) + cooldowns.remove(ability); + + Cooldown cd = new Cooldown(duration); + cd.setRemovalTask(Executors.newScheduledThreadPool(1).schedule(new Runnable() { + + @Override + public void run() { + removeCooldown(ability); + } + + }, duration, TimeUnit.MILLISECONDS)); + cooldowns.put(ability, cd); + } + + public boolean hasCooldown(String ability) { + if (cooldowns.containsKey(ability)) + return true; + else + return false; + } + + public boolean removeCooldown(String ability) { + if (cooldowns.containsKey(ability)) { + cooldowns.remove(ability); + return true; + } else { + return false; + } + } + + public Cooldown getCooldown(String ability) { + if (cooldowns.containsKey(ability)) { + return cooldowns.get(ability); + } else { + return null; + } + } } diff --git a/src/services/BuffService.java b/src/services/BuffService.java index 2b395784..b3a0b655 100644 --- a/src/services/BuffService.java +++ b/src/services/BuffService.java @@ -179,7 +179,7 @@ public class BuffService implements INetworkDispatch { if (buffer == null) removeBuffFromCreature(target, buff); - if (target.getPosition().getDistance2D(buffer.getWorldPosition()) > 80) { + if (target.getWorldPosition().getDistance2D(buffer.getWorldPosition()) > 80) { removeBuffFromCreature(target, buff); } } diff --git a/src/services/command/BaseSWGCommand.java b/src/services/command/BaseSWGCommand.java index 2d727994..cca19f25 100644 --- a/src/services/command/BaseSWGCommand.java +++ b/src/services/command/BaseSWGCommand.java @@ -21,6 +21,8 @@ ******************************************************************************/ package services.command; +import engine.clientdata.ClientFileManager; +import engine.clientdata.visitors.DatatableVisitor; import engine.resources.common.CRC; public class BaseSWGCommand implements Cloneable { @@ -31,10 +33,32 @@ public class BaseSWGCommand implements Cloneable { private int maxRangeToTarget; private int commandCRC; private boolean isGmCommand = false; + private String requiredAbility; + private String cooldownGroup; + private float cooldown; + private float executeTime; + private float warmupTime; public BaseSWGCommand(String commandName) { setCommandName(commandName); setCommandCRC(CRC.StringtoCRC(commandName)); + + try { + DatatableVisitor visitor2 = ClientFileManager.loadFile("datatables/command/command_table.iff", DatatableVisitor.class); + for (int i = 0; i < visitor2.getRowCount(); i++) { + if (visitor2.getObject(i, 0) != null) { + if (((String) visitor2.getObject(i, 0)).equalsIgnoreCase(commandName)) { + requiredAbility = (String) visitor2.getObject(i, 7); + cooldownGroup = (String) visitor2.getObject(i, 85); + warmupTime = (Float) visitor2.getObject(i, 86); + executeTime = (Float) visitor2.getObject(i, 87); + cooldown = (Float) visitor2.getObject(i, 88); + } + } + } + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } } public String getCommandName() { @@ -89,4 +113,44 @@ public class BaseSWGCommand implements Cloneable { this.isGmCommand = isGmCommand; } + public String getRequiredAbility() { + return requiredAbility; + } + + public void setRequiredAbility(String requiredAbility) { + this.requiredAbility = requiredAbility; + } + + public String getCooldownGroup() { + return cooldownGroup; + } + + public void setCooldownGroup(String cooldownGroup) { + this.cooldownGroup = cooldownGroup; + } + + public float getCooldown() { + return cooldown; + } + + public void setCooldown(float cooldown) { + this.cooldown = cooldown; + } + + public float getExecuteTime() { + return executeTime; + } + + public void setExecuteTime(float executeTime) { + this.executeTime = executeTime; + } + + public float getWarmupTime() { + return warmupTime; + } + + public void setWarmupTime(float warmupTime) { + this.warmupTime = warmupTime; + } + } diff --git a/src/services/command/CombatCommand.java b/src/services/command/CombatCommand.java index bc412ed2..cab1f4ef 100644 --- a/src/services/command/CombatCommand.java +++ b/src/services/command/CombatCommand.java @@ -67,16 +67,16 @@ public class CombatCommand extends BaseSWGCommand { private int damageType, elementalType, elementalValue; private String performanceSpam; private byte hitSpam; - private float cooldown; + //private float cooldown; private String delayAttackEggTemplate; private String delayAttackParticle; private float initialAttackDelay; private float delayAttackInterval; private int delayAttackLoops; private int delayAttackEggPosition; - private String cooldownGroup; - private float executeTime; - private float warmupTime; + //private String cooldownGroup; + //private float executeTime; + //private float warmupTime; private float vigorCost; // for commando kill meter and bm specials private float criticalChance; private int attack_rolls; @@ -162,22 +162,6 @@ public class CombatCommand extends BaseSWGCommand { } } - - DatatableVisitor visitor2 = ClientFileManager.loadFile("datatables/command/command_table.iff", DatatableVisitor.class); - - for(int i = 0; i < visitor2.getRowCount(); i++) { - if(visitor2.getObject(i, 0) != null) { - if(((String) visitor2.getObject(i, 0)).equalsIgnoreCase(commandName)) { - - cooldownGroup = (String) visitor2.getObject(i, 85); - warmupTime = (Float) visitor2.getObject(i, 86); - executeTime = (Float) visitor2.getObject(i, 87); - cooldown = (Float) visitor2.getObject(i, 88); - - } - } - } - } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } @@ -624,14 +608,6 @@ public class CombatCommand extends BaseSWGCommand { } - public float getCooldown() { - return cooldown; - } - - public void setCooldown(float cooldown) { - this.cooldown = cooldown; - } - public String getDelayAttackEggTemplate() { return delayAttackEggTemplate; } @@ -680,30 +656,6 @@ public class CombatCommand extends BaseSWGCommand { this.delayAttackLoops = delayAttackLoops; } - public String getCooldownGroup() { - return cooldownGroup; - } - - public void setCooldownGroup(String cooldownGroup) { - this.cooldownGroup = cooldownGroup; - } - - public float getExecuteTime() { - return executeTime; - } - - public void setExecuteTime(float executeTime) { - this.executeTime = executeTime; - } - - public float getWarmupTime() { - return warmupTime; - } - - public void setWarmupTime(float warmupTime) { - this.warmupTime = warmupTime; - } - public float getVigorCost() { return vigorCost; } diff --git a/src/services/command/CommandService.java b/src/services/command/CommandService.java index c51a1d67..99b41332 100644 --- a/src/services/command/CommandService.java +++ b/src/services/command/CommandService.java @@ -25,6 +25,9 @@ import java.nio.ByteOrder; import java.util.Map; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import main.NGECore; @@ -52,6 +55,7 @@ public class CommandService implements INetworkDispatch { private Vector commandLookup = new Vector(); private ConcurrentHashMap aliases = new ConcurrentHashMap(); private ConcurrentHashMap aliasesByCRC = new ConcurrentHashMap(); + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); private NGECore core; public CommandService(NGECore core) { @@ -98,16 +102,30 @@ public class CommandService implements INetworkDispatch { CreatureObject actor = (CreatureObject) client.getParent(); - SWGObject target = core.objectService.getObject(commandEnqueue.getTargetID()); - - if(command instanceof CombatCommand) { - CombatCommand command2 = (CombatCommand) command.clone(); - processCombatCommand(actor, target, command2, commandEnqueue.getActionCounter(), commandEnqueue.getCommandArguments()); + if (actor.hasCooldown(command.getCommandName())) return; - } - - core.scriptService.callScript("scripts/commands/", command.getCommandName(), "run", core, actor, target, commandEnqueue.getCommandArguments()); + SWGObject target = core.objectService.getObject(commandEnqueue.getTargetID()); + + // May want to have a warmup def to be called at some point in the future. + if (command.getWarmupTime() != 0 && !(command instanceof CombatCommand)) { + scheduler.schedule(new Runnable() { + + @Override + public void run() { + core.scriptService.callScript("scripts/commands/", command.getCommandName(), "run", core, actor, target, commandEnqueue.getCommandArguments()); + } + }, (long) command.getWarmupTime(), TimeUnit.SECONDS); + } else { + + if(command instanceof CombatCommand) { + CombatCommand command2 = (CombatCommand) command.clone(); + processCombatCommand(actor, target, command2, commandEnqueue.getActionCounter(), commandEnqueue.getCommandArguments()); + return; + } + + core.scriptService.callScript("scripts/commands/", command.getCommandName(), "run", core, actor, target, commandEnqueue.getCommandArguments()); + } } });