Recode the fplayer power calculation

This commit is contained in:
Olof Larsson 2013-04-18 10:35:40 +02:00
parent 10455c7acd
commit 2ddef9f499
2 changed files with 192 additions and 118 deletions

View File

@ -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 = "+";

View File

@ -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<FPlayer> 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<FPlayer> 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<FPlayer> 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<FPlayer> 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<FPlayer> 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<FPlayer> 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
// -------------------------------------------- //