diff --git a/src/com/massivecraft/factions/ConfServer.java b/src/com/massivecraft/factions/ConfServer.java index 465bce4d..32c9e483 100644 --- a/src/com/massivecraft/factions/ConfServer.java +++ b/src/com/massivecraft/factions/ConfServer.java @@ -43,18 +43,28 @@ public class ConfServer extends SimpleConfig public static Rel factionRankDefault = Rel.RECRUIT; // Power - public static double powerPlayerMax = 10.0; - public static double powerPlayerMin = -10.0; - public static double powerPlayerStarting = 10.0; // New players start out with this power level - public static double powerPerMinute = 0.2; // Default health rate... it takes 5 min to heal one power - public static double powerPerDeath = 4.0; // A death makes you lose 4 power + public static double powerMax = 10.0; + public static double powerMin = -10.0; + public static double powerStarting = 10.0; // New players start out with this power level + + public static double powerPerDeath = -4.0; // A death makes you lose 4 power + + public static double powerPerHourOnline = 10.0; + public static double powerPerHourOffline = 0.0; + + // players will no longer lose power from being offline once their power drops to this amount or less + public static double powerLimitGainOnline = 0.0; + public static double powerLimitGainOffline = 0.0; + public static double powerLimitLossOnline = 0.0; + public static double powerLimitLossOffline = 0.0; + public static boolean scaleNegativePower = false; // Power regeneration rate increase as power decreases public static double scaleNegativeDivisor = 40.0; // Divisor for inverse power regeneration curve - public static boolean powerRegenOffline = false; // does player power regenerate even while they're offline? - public static double powerOfflineLossPerDay = 0.0; // players will lose this much power per day offline - public static double powerOfflineLossLimit = 0.0; // players will no longer lose power from being offline once their power drops to this amount or less + public static double powerFactionMax = 0.0; // if greater than 0, the cap on how much power a faction can have (additional power from players beyond that will act as a "buffer" of sorts) + + public static String prefixLeader = "**"; public static String prefixOfficer = "*"; public static String prefixMember = "+"; diff --git a/src/com/massivecraft/factions/FPlayer.java b/src/com/massivecraft/factions/FPlayer.java index eb633f90..da2bf3f7 100644 --- a/src/com/massivecraft/factions/FPlayer.java +++ b/src/com/massivecraft/factions/FPlayer.java @@ -17,8 +17,11 @@ import com.massivecraft.factions.integration.LWCFeatures; import com.massivecraft.factions.integration.SpoutFeatures; import com.massivecraft.factions.integration.Worldguard; import com.massivecraft.factions.util.RelationUtil; +import com.massivecraft.mcore.mixin.Mixin; import com.massivecraft.mcore.ps.PS; import com.massivecraft.mcore.store.SenderEntity; +import com.massivecraft.mcore.util.TimeDiffUtil; +import com.massivecraft.mcore.util.TimeUnit; import com.massivecraft.mcore.util.Txt; @@ -47,7 +50,6 @@ public class FPlayer extends SenderEntity implements EconomyParticipato this.power = that.power; this.lastPowerUpdateTime = that.lastPowerUpdateTime; - this.lastLoginTime = that.lastLoginTime; return this; } @@ -60,7 +62,7 @@ public class FPlayer extends SenderEntity implements EconomyParticipato // Note: we do not check role or title here since they mean nothing without a faction. // TODO: This line looks obnoxious, investigate it. - if (this.getPowerRounded() != this.getPowerMaxRounded() && this.getPowerRounded() != (int) Math.round(ConfServer.powerPlayerStarting)) return false; + if (this.getPowerRounded() != this.getPowerMaxRounded() && this.getPowerRounded() != (int) Math.round(ConfServer.powerStarting)) return false; if (this.hasPowerBoost()) return false; @@ -98,18 +100,14 @@ public class FPlayer extends SenderEntity implements EconomyParticipato // Note that player powerBoost and faction powerBoost are very similar. private Double powerBoost = null; - // TODO - // FIELD: power + // This field contains the last calculated value of the players power. + // The power calculation is lazy which means that the power is calculated first when you try to view the value. private double power; - // TODO - // FIELD: lastPowerUpdateTime + // This is the timestamp for the last calculation of the power. + // The value is used for the lazy calculation described above. private long lastPowerUpdateTime; - // TODO - // FIELD: lastLoginTime - private long lastLoginTime; - // -------------------------------------------- // // FIELDS: RAW TRANSIENT // -------------------------------------------- // @@ -147,9 +145,8 @@ public class FPlayer extends SenderEntity implements EconomyParticipato public FPlayer() { this.resetFactionData(false); - this.power = ConfServer.powerPlayerStarting; + this.power = ConfServer.powerStarting; this.lastPowerUpdateTime = System.currentTimeMillis(); - this.lastLoginTime = System.currentTimeMillis(); this.loginPvpDisabled = (ConfServer.noPVPDamageToOthersForXSecondsAfterLogin > 0) ? true : false; if ( ! ConfServer.newPlayerStartingFactionID.equals(Const.FACTIONID_NONE) && FactionColl.get().containsId(ConfServer.newPlayerStartingFactionID)) @@ -332,18 +329,179 @@ public class FPlayer extends SenderEntity implements EconomyParticipato } // -------------------------------------------- // - // GETTERS AND SETTERS + // FIELD: lastPowerUpdateTime // -------------------------------------------- // - public long getLastLoginTime() + // RAW + + public long getLastPowerUpdateTime() { - return lastLoginTime; + return this.lastPowerUpdateTime; } + + public void setLastPowerUpdateTime(long lastPowerUpdateTime) + { + this.lastPowerUpdateTime = lastPowerUpdateTime; + this.changed(); + } + + // -------------------------------------------- // + // FIELD: power + // -------------------------------------------- // + + // RAW + + public double getPower() + { + this.updatePower(); + return this.power; + } + + public void setPower(double power) + { + this.setPower(power, System.currentTimeMillis()); + } + + public void setPower(double power, long now) + { + power = Math.min(power, this.getPowerMax()); + power = Math.max(power, this.getPowerMin()); + + // Nochange + if (this.power == power) return; + + this.power = power; + this.setLastPowerUpdateTime(now); + this.changed(); + } + + public double getPowerMax() + { + return ConfServer.powerMax + this.powerBoost; + } + + public double getPowerMin() + { + return ConfServer.powerMin + this.powerBoost; + } + + public void updatePower() + { + this.updatePower(this.isOnline()); + } + + private static final transient long POWER_RECALCULATION_MINIMUM_WAIT_MILLIS = 10 * TimeUnit.MILLIS_PER_SECOND; + + public void updatePower(boolean online) + { + // Is the player really on this server? + // We use the sender ps mixin to fetch the current player location. + // If the PS is null it's OK. We assume the player is here if we do not know. + PS ps = Mixin.getSenderPs(this.getId()); + if (ps != null && !ps.isWorldLoadedOnThisServer()) return; + + // Get the now + long now = System.currentTimeMillis(); + + // We will only update if a certain amount of time has passed. + if (this.getLastPowerUpdateTime() + POWER_RECALCULATION_MINIMUM_WAIT_MILLIS >= now) return; + + // Calculate millis passed + long millisPassed = now - this.getLastPowerUpdateTime(); + + // Note that we updated + this.setLastPowerUpdateTime(now); + + // We consider dead players to be offline. + if (online) + { + Player thisPlayer = this.getPlayer(); + if (thisPlayer != null && thisPlayer.isDead()) + { + online = false; + } + } + + // Depending on online state pick the config values + double powerPerHour = online ? ConfServer.powerPerHourOnline : ConfServer.powerPerHourOffline; + double powerLimitGain = online ? ConfServer.powerLimitGainOnline : ConfServer.powerLimitGainOffline; + double powerLimitLoss = online ? ConfServer.powerLimitLossOnline : ConfServer.powerLimitLossOffline; + + // Apply the negative divisor thingy + if (ConfServer.scaleNegativePower && this.power < 0) + { + powerPerHour += (Math.sqrt(Math.abs(this.power)) * Math.abs(this.power)) / ConfServer.scaleNegativeDivisor; + } + + // Calculate delta and target + double powerDelta = powerPerHour * millisPassed / TimeUnit.MILLIS_PER_HOUR; + double powerTarget = this.power + powerDelta; + + // Check Gain and Loss limits + if (powerDelta >= 0) + { + // Gain + if (powerTarget > powerLimitGain) + { + if (this.power > powerLimitGain) + { + // Did already cross --> Just freeze + powerTarget = this.power; + } + else + { + // Crossing right now --> Snap to limit + powerTarget = powerLimitGain; + } + } + } + else + { + // Loss + if (powerTarget < powerLimitLoss) + { + if (this.power < powerLimitLoss) + { + // Did already cross --> Just freeze + powerTarget = this.power; + } + else + { + // Crossing right now --> Snap to limit + powerTarget = powerLimitLoss; + } + } + } + + this.setPower(powerTarget, now); + } + + // FINER + + public int getPowerRounded() + { + return (int) Math.round(this.getPower()); + } + + public int getPowerMaxRounded() + { + return (int) Math.round(this.getPowerMax()); + } + + public int getPowerMinRounded() + { + return (int) Math.round(this.getPowerMin()); + } + + // -------------------------------------------- // + // FIELD: loginPvpDisabled + // -------------------------------------------- // + // TODO public void setLastLoginTime(long lastLoginTime) { losePowerFromBeingOffline(); - this.lastLoginTime = lastLoginTime; + //this.lastLoginTime = lastLoginTime; this.lastPowerUpdateTime = lastLoginTime; if (ConfServer.noPVPDamageToOthersForXSecondsAfterLogin > 0) { @@ -511,100 +669,6 @@ public class FPlayer extends SenderEntity implements EconomyParticipato player.setHealth(player.getHealth() + amnt); } - // -------------------------------------------- // - // POWER - // -------------------------------------------- // - - public double getPower() - { - this.updatePower(); - return this.power; - } - - protected void alterPower(double delta) - { - this.power += delta; - if (this.power > this.getPowerMax()) - this.power = this.getPowerMax(); - else if (this.power < this.getPowerMin()) - this.power = this.getPowerMin(); - } - - public double getPowerMax() - { - return ConfServer.powerPlayerMax + this.powerBoost; - } - - public double getPowerMin() - { - return ConfServer.powerPlayerMin + this.powerBoost; - } - - public int getPowerRounded() - { - return (int) Math.round(this.getPower()); - } - - public int getPowerMaxRounded() - { - return (int) Math.round(this.getPowerMax()); - } - - public int getPowerMinRounded() - { - return (int) Math.round(this.getPowerMin()); - } - - protected void updatePower() - { - if (this.isOffline()) - { - losePowerFromBeingOffline(); - if (!ConfServer.powerRegenOffline) - { - return; - } - } - long now = System.currentTimeMillis(); - long millisPassed = now - this.lastPowerUpdateTime; - this.lastPowerUpdateTime = now; - - Player thisPlayer = this.getPlayer(); - if (thisPlayer != null && thisPlayer.isDead()) return; // don't let dead players regain power until they respawn - - int millisPerMinute = 60*1000; - double powerPerMinute = ConfServer.powerPerMinute; - if(ConfServer.scaleNegativePower && this.power < 0) - { - powerPerMinute += (Math.sqrt(Math.abs(this.power)) * Math.abs(this.power)) / ConfServer.scaleNegativeDivisor; - } - this.alterPower(millisPassed * powerPerMinute / millisPerMinute); - - } - - protected void losePowerFromBeingOffline() - { - if (ConfServer.powerOfflineLossPerDay > 0.0 && this.power > ConfServer.powerOfflineLossLimit) - { - long now = System.currentTimeMillis(); - long millisPassed = now - this.lastPowerUpdateTime; - this.lastPowerUpdateTime = now; - - double loss = millisPassed * ConfServer.powerOfflineLossPerDay / (24*60*60*1000); - if (this.power - loss < ConfServer.powerOfflineLossLimit) - { - loss = this.power; - } - this.alterPower(-loss); - } - } - - public void onDeath() - { - this.updatePower(); - this.alterPower(-ConfServer.powerPerDeath); - } - // -------------------------------------------- // // TERRITORY // -------------------------------------------- //