Added basis for server-side cooldown checks, added warmup checks, closed #273

Note that cooldown check is currently used only for the holoemote
command. To add a cooldown to any command, all you have to do is
CreatureObject.addCooldown(name). In this commit I also moved some
cooldown variables from CombatCommand to BaseSWGCommand since many
non-combat commands had cooldowns (Wookie Roar, Holo-Emotes). I also put
in a warmup cooldown (time before command is called) for non-combat
commands.
This commit is contained in:
Waverunner
2014-04-03 19:23:31 -04:00
parent edcc6b9c34
commit 9e80b5eeae
8 changed files with 214 additions and 62 deletions
+7 -1
View File
@@ -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):
+5
View File
@@ -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
+62
View File
@@ -0,0 +1,62 @@
/*******************************************************************************
* Copyright (c) 2013 <Project SWG>
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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;
}
}
@@ -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<String, Cooldown> cooldowns = new ConcurrentHashMap<String, Cooldown>();
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;
}
}
}
+1 -1
View File
@@ -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);
}
}
+64
View File
@@ -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;
}
}
+4 -52
View File
@@ -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;
}
+26 -8
View File
@@ -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<BaseSWGCommand> commandLookup = new Vector<BaseSWGCommand>();
private ConcurrentHashMap<String,BaseSWGCommand> aliases = new ConcurrentHashMap<String,BaseSWGCommand>();
private ConcurrentHashMap<Integer,BaseSWGCommand> aliasesByCRC = new ConcurrentHashMap<Integer,BaseSWGCommand>();
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());
}
}
});