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;