From e0efae4dcfcf5baf70bdcc94d5cf174a7abb08d0 Mon Sep 17 00:00:00 2001 From: Eric Frechette Date: Wed, 5 Apr 2017 20:52:24 -0700 Subject: [PATCH] NPC buffs now display correct duration on client by using galactic time. Time played is fixed, calculating the time passed since the last time it's been calculated, and adds it to the old playTime. --- src/main/ProjectSWG.java | 2 +- src/resources/objects/creature/Buff.java | 4 ++ .../objects/player/PlayerObject.java | 11 ++-- src/services/commands/BuffService.java | 51 ++++++++++--------- src/services/player/ZoneManager.java | 2 +- 5 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/main/ProjectSWG.java b/src/main/ProjectSWG.java index e85e88ffe..23527aee2 100644 --- a/src/main/ProjectSWG.java +++ b/src/main/ProjectSWG.java @@ -87,7 +87,7 @@ public class ProjectSWG { /** * Returns the server's galactic time. This is the official time sent to * the client and should be used for any official client-time purposes. - * @return the server's galactic time + * @return the server's galactic time in seconds */ public static final long getGalacticTime() { return (long) (System.currentTimeMillis()/1E3 - 1309996800L); // Date is 07/07/2011 GMT diff --git a/src/resources/objects/creature/Buff.java b/src/resources/objects/creature/Buff.java index 15005680b..49c66b64d 100644 --- a/src/resources/objects/creature/Buff.java +++ b/src/resources/objects/creature/Buff.java @@ -157,6 +157,10 @@ public class Buff implements Encodable, Persistable { this.stackCount += adjust; } + public int getStartTime() { + return endTime - duration; + } + @Override public String toString() { return String.format("Buff[End=%d Value=%f Duration=%d Buffer=%d StackCount=%d]", endTime, value, duration, bufferId, stackCount); diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java index 96ebfe6f7..17e346096 100644 --- a/src/resources/objects/player/PlayerObject.java +++ b/src/resources/objects/player/PlayerObject.java @@ -56,6 +56,8 @@ public class PlayerObject extends IntangibleObject { private String biography = ""; private List joinedChannels = new ArrayList<>(); + private int lastUpdatePlayTime = 0; + public PlayerObject(long objectId) { super(objectId, BaselineType.PLAY); setVolume(0); @@ -94,9 +96,11 @@ public class PlayerObject extends IntangibleObject { } public void updatePlayTime() { - int currentTime = (int) (System.currentTimeMillis() / 1000); - int oldPlayTime = getPlayTime(); - int playTime = oldPlayTime + (currentTime - oldPlayTime); + int currentTime = (int)(System.currentTimeMillis() / 1000); + + // calculate how long it's been since the last updatePlayTime and add it to playTime + int playTime = getPlayTime() + (currentTime - lastUpdatePlayTime); + lastUpdatePlayTime = currentTime; play3.setPlayTime(playTime); sendDelta(3, 9, playTime); @@ -385,6 +389,7 @@ public class PlayerObject extends IntangibleObject { public void setStartPlayTime(int startPlayTime) { this.startPlayTime = startPlayTime; + lastUpdatePlayTime = startPlayTime; } @Override diff --git a/src/services/commands/BuffService.java b/src/services/commands/BuffService.java index bd95c3354..9b2700cb9 100644 --- a/src/services/commands/BuffService.java +++ b/src/services/commands/BuffService.java @@ -39,6 +39,7 @@ import intents.BuffIntent; import intents.PlayerEventIntent; import intents.SkillModIntent; import intents.combat.CreatureKilledIntent; +import main.ProjectSWG; import network.packets.swg.zone.PlayClientEffectObjectMessage; import resources.common.CRC; import resources.concurrency.PswgBasicScheduledThread; @@ -102,7 +103,7 @@ public class BuffService extends Service { creatures = new ArrayList<>(monitored); } for (CreatureObject creature : creatures) { - removeAllBuffs(creature, creature.getBuffEntries(buff -> isBuffExpired(buff))); + removeAllBuffs(creature, creature.getBuffEntries(buff -> isBuffExpired(creature, buff))); } } @@ -146,7 +147,7 @@ public class BuffService extends Service { if (cki.getKiller().isPlayer()) { // PvP death - decay durations of certain buffs - corpse.getBuffEntries(buff -> isBuffDecayable(buff)).forEach(buff -> decayDuration(corpse, buff)); + corpse.getBuffEntries(buff -> isBuffDecayable(corpse, buff)).forEach(buff -> decayDuration(corpse, buff)); } else { // PvE death - remove certain buffs removeAllBuffs(corpse, corpse.getBuffEntries(buff -> isBuffRemovedOnDeath(buff))); @@ -165,16 +166,22 @@ public class BuffService extends Service { } } - private int getCurrentTime() { - return (int)(System.currentTimeMillis() / 1000); + private int calculatePlayTime(CreatureObject creature) { + if (creature.isPlayer()) { + creature.getPlayerObject().updatePlayTime(); + return creature.getPlayerObject().getPlayTime(); + } + + // NPC time is based on the current galactic time because NPCs don't have playTime + return (int)ProjectSWG.getGalacticTime(); } - private boolean isBuffExpired(Buff buff) { - return buff.getDuration() >= 0 && System.currentTimeMillis() / 1000 >= buff.getEndTime(); + private boolean isBuffExpired(CreatureObject creature, Buff buff) { + return buff.getDuration() >= 0 && calculatePlayTime(creature) >= buff.getEndTime(); } - private boolean isBuffDecayable(Buff buff) { - return !isBuffExpired(buff) && getBuff(buff).isDecayOnPvpDeath(); + private boolean isBuffDecayable(CreatureObject creature, Buff buff) { + return !isBuffExpired(creature, buff) && getBuff(buff).isDecayOnPvpDeath(); } private boolean isBuffPersistent(Buff buff) { @@ -196,7 +203,7 @@ public class BuffService extends Service { private void decayDuration(CreatureObject creature, Buff buff) { int newDuration = (int) (buff.getDuration() * 0.10); // Duration decays with 10% - creature.setBuffDuration(new CRC(buff.getCrc()), creature.getPlayerObject().getPlayTime(), newDuration); + creature.setBuffDuration(new CRC(buff.getCrc()), buff.getStartTime(), newDuration); } private void removeAllBuffs(CreatureObject creature, Stream buffStream) { @@ -209,11 +216,7 @@ public class BuffService extends Service { String groupName = buffData.getGroupName(); Optional groupBuff = receiver.getBuffEntries(buff -> groupName.equals(getBuff(buff).getGroupName())).findAny(); - if (receiver.isPlayer()) { - receiver.getPlayerObject().updatePlayTime(); - } - - int playTime = getCurrentTime(); + int applyTime = calculatePlayTime(receiver); if (groupBuff.isPresent()) { Buff buff = groupBuff.get(); @@ -223,17 +226,17 @@ public class BuffService extends Service { removeBuff(receiver, buffData, true); } else { // TODO skillmods influencing stack increment - checkStackCount(receiver, buff, playTime, 1); + checkStackCount(receiver, buff, applyTime, 1); } } else { BuffData oldBuff = getBuff(buff); if (buffData.getGroupPriority() >= oldBuff.getGroupPriority()) { removeBuff(receiver, oldBuff, true); - applyBuff(receiver, buffer, buffData, playTime); + applyBuff(receiver, buffer, buffData, applyTime); } } } else { - applyBuff(receiver, buffer, buffData, playTime); + applyBuff(receiver, buffer, buffData, applyTime); } } @@ -245,7 +248,7 @@ public class BuffService extends Service { Buff buff = optionalEntry.get(); if (buffData.getMaxStackCount() > 1 && !expired && buff.getStackCount() > 1) { - checkStackCount(creature, buff, getCurrentTime(), buffData.getMaxStackCount()); + checkStackCount(creature, buff, calculatePlayTime(creature), buffData.getMaxStackCount()); } else { Buff removedBuff = creature.removeBuff(new CRC(buff.getCrc())); Assert.notNull(removedBuff, "Buff must exist if being removed"); @@ -259,7 +262,7 @@ public class BuffService extends Service { } } - private void checkStackCount(CreatureObject receiver, Buff buff, int playTime, int stackMod) { + private void checkStackCount(CreatureObject receiver, Buff buff, int applyTime, int stackMod) { BuffData buffData = getBuff(buff); Assert.notNull(buffData); // If it's the same buff, we need to check for stacks @@ -267,7 +270,7 @@ public class BuffService extends Service { if (maxStackCount < 2) { removeBuff(receiver, buffData, true); - applyBuff(receiver, receiver, buffData, playTime); + applyBuff(receiver, receiver, buffData, applyTime); return; } @@ -281,16 +284,16 @@ public class BuffService extends Service { // If the stack count was incremented, also renew the duration if (stackMod > 0) { - receiver.setBuffDuration(crc, playTime, (int) buffData.getDefaultDuration()); + receiver.setBuffDuration(crc, applyTime, (int) buffData.getDefaultDuration()); } } - private void applyBuff(CreatureObject receiver, CreatureObject buffer, BuffData buffData, int playTime) { + private void applyBuff(CreatureObject receiver, CreatureObject buffer, BuffData buffData, int applyTime) { // TODO stack counts upon add/remove need to be defined on a per-buff basis due to skillmod influence. Scripts might not be a bad idea. int stackCount = 1; int buffDuration = (int) buffData.getDefaultDuration(); - Log.d("buff %s applied to %s from %s; playTime: %d, buffDuration: %d", buffData.getName(), receiver.getObjectName(), buffer.getObjectName(), playTime, buffDuration); - Buff buff = new Buff(buffData.getCrc(), playTime + buffDuration, buffData.getEffectValue(0), buffDuration, buffer.getObjectId(), stackCount); + Log.d("buff %s applied to %s from %s; applyTime: %d, buffDuration: %d", buffData.getName(), receiver.getObjectName(), buffer.getObjectName(), applyTime, buffDuration); + Buff buff = new Buff(buffData.getCrc(), applyTime + buffDuration, buffData.getEffectValue(0), buffDuration, buffer.getObjectId(), stackCount); checkSkillMods(buffData, receiver, 1); receiver.addBuff(buff); diff --git a/src/services/player/ZoneManager.java b/src/services/player/ZoneManager.java index e2153204c..a2beb364b 100644 --- a/src/services/player/ZoneManager.java +++ b/src/services/player/ZoneManager.java @@ -88,7 +88,7 @@ public class ZoneManager extends Manager { private void handlePlayerEventIntent(Player player, PlayerEvent event) { switch (event) { case PE_FIRST_ZONE: - player.getPlayerObject().setStartPlayTime((int) System.currentTimeMillis()); + player.getPlayerObject().setStartPlayTime((int)(System.currentTimeMillis() / 1000)); sendCommitHistory(player); sendMessageOfTheDay(player); break;