/// <summary> /// Broadcasts Eweca notice, called at 6:00 and 18:00. /// </summary> /// <param name="now"></param> private void OnErinnDaytimeTick(ErinnTime now) { var notice = now.IsNight ? Localization.Get("world.eweca_night") // Eweca is rising.\nMana is starting to fill the air all around. : Localization.Get("world.eweca_day"); // Eweca has disappeared.\nThe surrounding Mana is starting to fade away. Send.Notice(NoticeType.MiddleTop, notice); }
/// <summary> /// Handles regularly occuring events and raises time events. /// </summary> /// <remarks> /// On the first call all time events are raised, /// because lastHeartbeat is 0, and the events depend on the time /// since the last heartbeat. This also ensures that they aren't /// called multiple times. /// </remarks> private void Heartbeat(object _) { var now = new ErinnTime(DateTime.Now); var diff = (now.DateTime - _lastHeartbeat).TotalMilliseconds; if (diff != HeartbeatTime && Math.Abs(HeartbeatTime - diff) > HeartbeatTime && diff < 100000000) { Log.Debug("OMG, the server has an irregular heartbeat! ({0})", diff.ToInvariant()); } // Seconds event if ((_secondsTime += diff) >= Second) { _secondsTime = 0; ChannelServer.Instance.Events.OnSecondsTimeTick(now); } // Minutes event if ((_minutesTime += diff) >= Minute) { _minutesTime = (now.DateTime.Second * Second + now.DateTime.Millisecond); ChannelServer.Instance.Events.OnMinutesTimeTick(now); // Mabi tick event if (++_mabiTickCount >= 5) { ChannelServer.Instance.Events.OnMabiTick(now); _mabiTickCount = 0; } } // Hours event if ((_hoursTime += diff) >= Hour) { _hoursTime = (now.DateTime.Minute * Minute + now.DateTime.Second * Second + now.DateTime.Millisecond); ChannelServer.Instance.Events.OnHoursTimeTick(now); } // Erinn time event if ((_erinnTime += diff) >= ErinnMinute) { _erinnTime = 0; ChannelServer.Instance.Events.OnErinnTimeTick(now); // TODO: Dawn/Dusk/Midnight wouldn't be called if the server had a 500+ ms hickup. // Erinn daytime event if (now.IsDawn || now.IsDusk) { ChannelServer.Instance.Events.OnErinnDaytimeTick(now); this.OnErinnDaytimeTick(now); } // Erinn midnight event if (now.IsMidnight) ChannelServer.Instance.Events.OnErinnMidnightTick(now); } this.UpdateEntities(); _lastHeartbeat = now.DateTime; }
/// <summary> /// Applies regens to creature. /// </summary> /// <remarks> /// (Should be) called once a second. /// - Hunger doesn't go beyond 50% of max stamina. /// - Stamina regens at 20% efficiency from StaminaHunger onwards. /// </remarks> public void OnSecondsTimeTick(ErinnTime time) { if (this.Creature.Region == null || this.Creature.IsDead) return; lock (_regens) { var toRemove = new List<int>(); foreach (var regen in _regens.Values) { if (regen.TimeLeft == 0) { toRemove.Add(regen.Id); continue; } switch (regen.Stat) { case Stat.Life: this.Creature.Life += regen.Change; break; case Stat.Mana: this.Creature.Mana += regen.Change; break; case Stat.Stamina: // Only positve regens are affected by the hunger multiplicator. this.Creature.Stamina += regen.Change * (regen.Change > 0 ? this.Creature.StaminaRegenMultiplicator : 1); break; case Stat.Hunger: // Regen can't lower hunger below a certain amount. this.Creature.Hunger += regen.Change; if (this.Creature.Hunger > this.Creature.StaminaMax / 2) this.Creature.Hunger = this.Creature.StaminaMax / 2; break; case Stat.LifeInjured: this.Creature.Injuries -= regen.Change; break; } } foreach (var id in toRemove) this.Remove(id); } }
/// <summary> /// Adds additional mana regen at night. /// </summary> /// <param name="time"></param> public void OnErinnDaytimeTick(ErinnTime time) { if (time.IsNight) { this.Add("NightMana", Stat.Mana, 0.1f, this.Creature.ManaMax); } else { this.Remove("NightMana"); } }
/// <summary> /// Called every 5 minutes, checks changes through food. /// </summary> /// <param name="time"></param> public void OnMabiTick(ErinnTime time) { var weight = this.Temp.WeightFoodChange; var upper = this.Temp.UpperFoodChange; var lower = this.Temp.LowerFoodChange; var life = this.Temp.LifeFoodChange; var mana = this.Temp.ManaFoodChange; var stm = this.Temp.StaminaFoodChange; var str = this.Temp.StrFoodChange; var int_ = this.Temp.IntFoodChange; var dex = this.Temp.DexFoodChange; var will = this.Temp.WillFoodChange; var luck = this.Temp.LuckFoodChange; var changes = false; var sb = new StringBuilder(); if (weight != 0) { changes = true; this.Weight += weight; sb.Append(Localization.Get(weight > 0 ? "world.weight_plus" : "world.weight_minus") + "\r\n"); } if (upper != 0) { changes = true; this.Upper += upper; sb.Append(Localization.Get(upper > 0 ? "world.upper_plus" : "world.upper_minus") + "\r\n"); } if (lower != 0) { changes = true; this.Lower += lower; sb.Append(Localization.Get(lower > 0 ? "world.lower_plus" : "world.lower_minus") + "\r\n"); } if (life != 0) { changes = true; this.LifeFoodMod += life; } if (mana != 0) { changes = true; this.ManaFoodMod += mana; } if (stm != 0) { changes = true; this.StaminaFoodMod += stm; } if (str != 0) { changes = true; this.StrFoodMod += str; } if (int_ != 0) { changes = true; this.IntFoodMod += int_; } if (dex != 0) { changes = true; this.DexFoodMod += dex; } if (will != 0) { changes = true; this.WillFoodMod += will; } if (luck != 0) { changes = true; this.LuckFoodMod += luck; } if (!changes) return; this.Temp.WeightFoodChange = 0; this.Temp.UpperFoodChange = 0; this.Temp.LowerFoodChange = 0; this.Temp.LifeFoodChange = 0; this.Temp.ManaFoodChange = 0; this.Temp.StaminaFoodChange = 0; this.Temp.StrFoodChange = 0; this.Temp.IntFoodChange = 0; this.Temp.DexFoodChange = 0; this.Temp.WillFoodChange = 0; this.Temp.LuckFoodChange = 0; Send.StatUpdate(this, StatUpdateType.Private, Stat.LifeMaxFoodMod, Stat.ManaMaxFoodMod, Stat.StaminaMaxFoodMod, Stat.StrFoodMod, Stat.IntFoodMod, Stat.DexFoodMod, Stat.WillFoodMod, Stat.LuckFoodMod); Send.StatUpdate(this, StatUpdateType.Public, Stat.LifeMaxFoodMod); Send.CreatureBodyUpdate(this); if (sb.Length > 0) Send.Notice(this, sb.ToString()); }
/// <summary> /// 5 min tick, global var saving. /// </summary> /// <param name="time"></param> public void OnMabiTick(ErinnTime time) { ChannelDb.Instance.SaveVars("Aura System", 0, this.GlobalVars.Perm); Log.Info("Saved global script variables."); }