public static void SetVital(Session session, params string[] parameters) { string paramVital = parameters[0].ToLower(); string paramValue = parameters[1]; bool relValue = paramValue[0] == '+' || paramValue[0] == '-'; int value = int.MaxValue; if (!int.TryParse(paramValue, out value)) { ChatPacket.SendServerMessage(session, "setvital Error: Invalid set value", ChatMessageType.Broadcast); return; } // Parse args... CreatureVital vital = null; if (paramVital == "health" || paramVital == "hp") { vital = session.Player.Health; } else if (paramVital == "stamina" || paramVital == "stam" || paramVital == "sp") { vital = session.Player.Stamina; } else if (paramVital == "mana" || paramVital == "mp") { vital = session.Player.Mana; } else { ChatPacket.SendServerMessage(session, "setvital Error: Invalid vital", ChatMessageType.Broadcast); return; } if (!relValue) { session.Player.UpdateVital(vital, (uint)value); } else { session.Player.DeltaVital(vital, value); } }
/// <summary> /// Sets the current vital to a new value /// </summary> /// <returns>The actual change in the vital, after clamping between 0 and MaxVital</returns> public override int UpdateVital(CreatureVital vital, int newVal) { var change = base.UpdateVital(vital, newVal); if (change != 0) { Session.Network.EnqueueSend(new GameMessagePrivateUpdateAttribute2ndLevel(this, vital.ToEnum(), vital.Current)); } // check for exhaustion if (vital.Vital == PropertyAttribute2nd.Stamina || vital.Vital == PropertyAttribute2nd.MaxStamina) { if (change != 0 && vital.Current == 0) { OnExhausted(); } } return(change); }
private void DeltaVitalInternal(CreatureVital vital, long delta) { uint absVal; if (delta < 0 && Math.Abs(delta) > vital.Current) { absVal = (uint)(-1 * vital.Current); } else if (delta + vital.Current > vital.MaxValue) { absVal = vital.MaxValue - vital.Current; } else { absVal = (uint)(vital.Current + delta); } UpdateVitalInternal(vital, absVal); }
private void VitalTick(CreatureVital vital) { double tickTime = vital.NextTickTime; if (double.IsNegativeInfinity(tickTime)) { tickTime = vital.RegenRate; } else { tickTime -= WorldManager.PortalYearTicks; } // Set up our next tick ActionChain tickChain = new ActionChain(); tickChain.AddDelayTicks(tickTime); tickChain.AddAction(this, () => VitalTickInternal(vital)); tickChain.EnqueueChain(); }
/// <summary> /// Returns the vital regeneration modifier based on player stance /// (combat, crouch, sitting, sleeping) /// </summary> public float GetStanceMod(CreatureVital vital) { // only applies to players if ((this as Player) == null) { return(1.0f); } // does not apply for mana? if (vital.Vital == PropertyAttribute2nd.MaxMana) { return(1.0f); } var forwardCommand = CurrentMovementData.MovementType == MovementType.Invalid && CurrentMovementData.Invalid != null ? CurrentMovementData.Invalid.State.ForwardCommand : MotionCommand.Invalid; // combat mode / running if (CombatMode != CombatMode.NonCombat || forwardCommand == MotionCommand.RunForward) { return(0.5f); } switch (forwardCommand) { // TODO: verify multipliers default: return(1.0f); case MotionCommand.Crouch: return(2.0f); case MotionCommand.Sitting: return(2.5f); case MotionCommand.Sleeping: return(3.0f); } }
/// <summary> /// Returns the vital regeneration modifier based on player stance /// (combat, crouch, sitting, sleeping) /// </summary> public float GetStanceMod(CreatureVital vital) { // only applies to players if ((this as Player) == null) { return(1.0f); } // does not apply for mana? if (vital.Vital == PropertyAttribute2nd.MaxMana) { return(1.0f); } // combat mode / running if (CombatMode != CombatMode.NonCombat || CurrentMotionCommand == (uint)MotionCommand.RunForward) { return(0.5f); } switch (CurrentMotionCommand) { // TODO: verify multipliers default: return(1.0f); case 0x12: // MotionCommand.Crouch return(2.0f); case 0x13: // MotionCommand.Sitting return(2.5f); case 0x14: // MotionCommand.Sleeping return(3.0f); } }
/// <summary> /// Sets the current vital to a new value /// </summary> public override void UpdateVital(CreatureVital vital, uint newVal) { //check for exhaustion if (vital.Vital == PropertyAttribute2nd.Stamina || vital.Vital == PropertyAttribute2nd.MaxStamina) { if (vital.Current != newVal && newVal < 1) { // force player to experience exhaustion var motion = new UniversalMotion(CurrentMotionState.Stance); // this should be autonymous, like retail, but if it's set to autonymous here, the desired effect doesn't happen // motion.IsAutonomous = true; motion.MovementData = new MovementData() { CurrentStyle = (uint)CurrentMotionState.Stance, ForwardCommand = (uint)MotionCommand.RunForward }; CurrentMotionState = motion; CurrentLandblock.EnqueueBroadcastMotion(this, motion); Session.Network.EnqueueSend(new GameEventCommunicationTransientString(Session, "You're Exhausted!")); } } base.UpdateVital(vital, newVal); Session.Network.EnqueueSend(new GameMessagePrivateUpdateAttribute2ndLevel(this, vital.ToEnum(), vital.Current)); }
/// <summary> /// Returns the vital regeneration modifier based on attributes /// (strength, endurance for health, stamina) /// </summary> public float GetAttributeMod(CreatureVital vital) { // only applies to players if (!(this is Player)) { return(1.0f); } // only applies for health? if (vital.Vital != PropertyAttribute2nd.MaxHealth) { return(1.0f); } // The combination of strength and endurance (with endurance being more important) allows one to regenerate hit points // at a faster rate the higher one's endurance is. This bonus is in addition to any regeneration spells one may have placed upon themselves. // This regeneration bonus caps at around 110%. var strength = Strength.Base; var endurance = Endurance.Base; var strAndEnd = strength + (endurance * 2); //var modifier = 1.0 + (0.0494 * Math.Pow(strAndEnd, 1.179) / 100.0f); // formula deduced from values present in the client pdb //var attributeMod = Math.Clamp(modifier, 1.0, 2.1); // cap between + 0-110% if (strAndEnd <= 200) { return(1.0f); } var modifier = 1.0f + (float)(strAndEnd - 200) / 600 * 1.1f; var attributeMod = Math.Min(modifier, 2.1f); return(attributeMod); }
/// <summary> /// Updates a vital relative to current value /// </summary> public int UpdateVitalDelta(CreatureVital vital, int delta) { var newVital = (int)vital.Current + delta; return(UpdateVital(vital, newVital)); }
public virtual int UpdateVital(CreatureVital vital, uint newVal) { return(UpdateVital(vital, (int)newVal)); }
public GameMessagePrivateUpdateVital(Session session, PropertyAttribute2nd attribute, CreatureVital cv) : this(session, attribute, cv.Ranks, cv.StartingValue, cv.ExperienceSpent, cv.Current) { }
/// <summary> /// Updates a particular vital according to regeneration rate /// </summary> /// <param name="vital">The vital stat to update (health/stamina/mana)</param> /// <returns>TRUE if vital has changed</returns> public bool VitalHeartBeat(CreatureVital vital) { // Current and MaxValue are properties and include overhead in getting their values. We cache them so we only hit the overhead once. var vitalCurrent = vital.Current; var vitalMax = vital.MaxValue; if (vitalCurrent == vitalMax) { return(false); } if (vitalCurrent > vitalMax) { UpdateVital(vital, vitalMax); return(true); } if (vital.RegenRate == 0.0) { return(false); } // take attributes into consideration (strength, endurance) var attributeMod = GetAttributeMod(vital); // take stance into consideration (combat, crouch, sitting, sleeping) var stanceMod = GetStanceMod(vital); // take enchantments into consideration: // (regeneration / rejuvenation / mana renewal / etc.) var enchantmentMod = EnchantmentManager.GetRegenerationMod(vital); var augMod = 1.0f; if (this is Player player && player.AugmentationFasterRegen > 0) { augMod += player.AugmentationFasterRegen; } // cap rate? var currentTick = vital.RegenRate * attributeMod * stanceMod * enchantmentMod * augMod; // add in partially accumulated / rounded vitals from previous tick(s) var totalTick = currentTick + vital.PartialRegen; // accumulate partial vital rates between ticks var intTick = (int)totalTick; vital.PartialRegen = totalTick - intTick; if (intTick > 0) { UpdateVitalDelta(vital, intTick); if (vital.Vital == PropertyAttribute2nd.MaxHealth) { DamageHistory.OnHeal((uint)intTick); } return(true); } //Console.WriteLine($"VitalTick({vital.Vital.ToSentence()}): attributeMod={attributeMod}, stanceMod={stanceMod}, enchantmentMod={enchantmentMod}, regenRate={vital.RegenRate}, currentTick={currentTick}, totalTick={totalTick}, accumulated={vital.PartialRegen}"); return(false); }
public GameMessagePrivateUpdateVital(Session session, Entity.Enum.Ability ability, CreatureVital cv) : this(session, ability, cv.Ranks, cv.Base, cv.ExperienceSpent, cv.Current) { }
/// <summary> /// Sets the current vital to a new value /// </summary> public override void UpdateVital(CreatureVital vital, uint newVal) { base.UpdateVital(vital, newVal); Session.Network.EnqueueSend(new GameMessagePrivateUpdateAttribute2ndLevel(this, vital.ToEnum(), vital.Current)); }
/// <summary> /// Sets the current vital to a new value /// </summary> public virtual void UpdateVital(CreatureVital vital, uint newVal) { vital.Current = Math.Clamp(newVal, 0, vital.MaxValue); }
public int UpdateVitalDelta(CreatureVital vital, uint delta) { return(UpdateVitalDelta(vital, (int)delta)); }
public void DeltaVital(CreatureVital vital, long delta) { EnqueueAction(new ActionEventDelegate(() => DeltaVitalInternal(vital, delta))); }
public static void SetVital(Session session, params string[] parameters) { string paramVital = parameters[0].ToLower(); string paramValue = parameters[1]; bool relValue = paramValue[0] == '+' || paramValue[0] == '-'; int value = int.MaxValue; if (!int.TryParse(paramValue, out value)) { ChatPacket.SendServerMessage(session, "setvital Error: Invalid set value", ChatMessageType.Broadcast); return; } Entity.Enum.Ability ability; // Parse args... CreatureVital vital = null; if (paramVital == "health" || paramVital == "hp") { ability = Entity.Enum.Ability.Health; vital = session.Player.Health; } else if (paramVital == "stamina" || paramVital == "stam" || paramVital == "sp") { ability = Entity.Enum.Ability.Stamina; vital = session.Player.Stamina; } else if (paramVital == "mana" || paramVital == "mp") { ability = Entity.Enum.Ability.Mana; vital = session.Player.Mana; } else { ChatPacket.SendServerMessage(session, "setvital Error: Invalid vital", ChatMessageType.Broadcast); return; } long targetValue = 0; if (relValue) { targetValue = vital.Current + value; } else { targetValue = value; } if (targetValue < 0 || targetValue > vital.MaxValue) { ChatPacket.SendServerMessage(session, "setvital Error: Value over/underflow", ChatMessageType.Broadcast); return; } vital.Current = (uint)targetValue; // Send an update packet session.Network.EnqueueSend(new GameMessagePrivateUpdateVital(session, ability, vital)); }
/// <summary> /// Updates a vital, returns true if vital is now < max /// </summary> public void UpdateVital(CreatureVital vital, uint newVal) { EnqueueAction(new ActionEventDelegate(() => UpdateVitalInternal(vital, newVal))); }