Fix the math around sleeping to be simpler
This commit is contained in:
+1
-1
@@ -48,7 +48,7 @@ server.workbench3taxrate "0"
|
|||||||
|
|
||||||
// Animal populations should reflect realistic proportion of predators to prey. They should also
|
// Animal populations should reflect realistic proportion of predators to prey. They should also
|
||||||
// appear at about twice the natural population density to provide a good balance between realism
|
// appear at about twice the natural population density to provide a good balance between realism
|
||||||
// and fun gameplay.
|
// and fun gameplay. The totals provided are assuming a 9sqkm map (3000 world size).
|
||||||
|
|
||||||
bear.population "0.33" // per sqkm, 3 total
|
bear.population "0.33" // per sqkm, 3 total
|
||||||
boar.population "2.77" // per sqkm, 25 total
|
boar.population "2.77" // per sqkm, 25 total
|
||||||
|
|||||||
@@ -14,36 +14,46 @@ namespace Oxide.Plugins {
|
|||||||
[Description("An accelerated way to sleep through the night.")]
|
[Description("An accelerated way to sleep through the night.")]
|
||||||
public class GoodNightsSleep : RustPlugin {
|
public class GoodNightsSleep : RustPlugin {
|
||||||
|
|
||||||
|
// Constants ///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// the earliest time you can go to sleep
|
// the earliest time you can go to sleep
|
||||||
public const float BED_TIME = 22f;
|
public const float BED_TIME = 20f;
|
||||||
|
|
||||||
// the amount you heal per second from sleeping
|
// the amount you heal per second from sleeping
|
||||||
public const float HEAL_RATIO = 1f;
|
public const float HEAL_RATIO = 1f;
|
||||||
|
|
||||||
// the ratio at which time passes (e.g., 10 means 10x usual speed)
|
|
||||||
public const float SLEEP_SPEED = 20;
|
|
||||||
|
|
||||||
// the amount of wall-clock time (in seconds) between sleep steps
|
// the amount of wall-clock time (in seconds) between sleep steps
|
||||||
public const float STEP_SIZE = 1f;
|
public const float STEP_SIZE = 1f;
|
||||||
|
|
||||||
|
// the real-world time sleeping should last (in seconds)
|
||||||
|
public const float SLEEP_TIME = 30f;
|
||||||
|
|
||||||
// the time you wake up in the morning
|
// the time you wake up in the morning
|
||||||
public const float WAKE_TIME = 7f;
|
public const float WAKE_TIME = 8f;
|
||||||
|
|
||||||
|
// the prefab sound to play when someone yawns
|
||||||
|
public const string YAWN_SOUND = "assets/bundled/prefabs/fx/player/yawn.prefab";
|
||||||
|
|
||||||
|
// Helper Class ////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// a an actual instance of sleeping through the night
|
// a an actual instance of sleeping through the night
|
||||||
private class SleepSession {
|
private class SleepSession {
|
||||||
|
|
||||||
|
// the player doing the sleeping
|
||||||
|
public BasePlayer player = null;
|
||||||
|
|
||||||
// in-game time when we last completed a step
|
// in-game time when we last completed a step
|
||||||
private float lastStepAt = 0f;
|
private float lastStepAt = 0f;
|
||||||
|
|
||||||
// callback for when the session is over
|
// callback for when the session is over
|
||||||
private Action onComplete = null;
|
private Action onComplete = null;
|
||||||
|
|
||||||
// the player doing the sleeping
|
|
||||||
private BasePlayer player = null;
|
|
||||||
|
|
||||||
// the plugin itself
|
// the plugin itself
|
||||||
private RustPlugin plugin = null;
|
private RustPlugin plugin = null;
|
||||||
|
|
||||||
|
// the in-game time when sleep began
|
||||||
|
private float startedSleepingAt = 0;
|
||||||
|
|
||||||
// the timer controlling the steps
|
// the timer controlling the steps
|
||||||
private Timer timer = null;
|
private Timer timer = null;
|
||||||
|
|
||||||
@@ -58,9 +68,8 @@ namespace Oxide.Plugins {
|
|||||||
this.Abort();
|
this.Abort();
|
||||||
|
|
||||||
this.timer = timer;
|
this.timer = timer;
|
||||||
this.lastStepAt = this.GetTime();
|
|
||||||
this.player.StartSleeping();
|
this.player.StartSleeping();
|
||||||
this.player.ChatMessage("You slowly start to drift off to sleep.");
|
this.startedSleepingAt = this.GetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void KeepSleeping() {
|
public void KeepSleeping() {
|
||||||
@@ -74,16 +83,13 @@ namespace Oxide.Plugins {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var now = this.GetTime();
|
var totalHours = (24f - BED_TIME) + WAKE_TIME;
|
||||||
var sleepDuration = (now - this.lastStepAt) * 60 * 60; // in seconds
|
var totalSteps = SLEEP_TIME / STEP_SIZE;
|
||||||
this.player.Heal(sleepDuration * GoodNightsSleep.HEAL_RATIO);
|
var incrementHours = totalHours / totalSteps;
|
||||||
|
var incrementSeconds = incrementHours * 60 * 60;
|
||||||
|
|
||||||
this.lastStepAt = now;
|
this.player.Heal(incrementSeconds * GoodNightsSleep.HEAL_RATIO);
|
||||||
this.SetTime(
|
this.SetTime((this.GetTime() + incrementHours) % 24f);
|
||||||
this.GetTime() + (
|
|
||||||
GoodNightsSleep.STEP_SIZE * GoodNightsSleep.SLEEP_SPEED / 60 / 60
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Abort() {
|
public void Abort() {
|
||||||
@@ -118,18 +124,31 @@ namespace Oxide.Plugins {
|
|||||||
|
|
||||||
private bool ShouldWake() {
|
private bool ShouldWake() {
|
||||||
if (this.ShouldAbort()) return false;
|
if (this.ShouldAbort()) return false;
|
||||||
if (this.GetTime() > GoodNightsSleep.WAKE_TIME) return true;
|
|
||||||
|
var now = this.GetTime();
|
||||||
|
var outsideSleepHours = (
|
||||||
|
(now > GoodNightsSleep.WAKE_TIME) &&
|
||||||
|
(now < GoodNightsSleep.BED_TIME)
|
||||||
|
);
|
||||||
|
if (outsideSleepHours) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Member Variables ////////////////////////////////////////////////////
|
||||||
|
|
||||||
// the specific instance of sleeping through the night
|
// the specific instance of sleeping through the night
|
||||||
private SleepSession session = null;
|
private SleepSession session = null;
|
||||||
|
|
||||||
|
// the last time each player got a yawn reminder
|
||||||
|
private int lastYawnDay = -1;
|
||||||
|
|
||||||
|
|
||||||
// Hooks ///////////////////////////////////////////////////////////////////////////////////
|
// Hooks ///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void OnServerInitialized() {
|
void OnServerInitialized() {
|
||||||
Puts("Good Night's Sleep is active");
|
Puts("Good Night's Sleep is active");
|
||||||
|
timer.Every(60f, () => this.CheckSleepiness());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commands ////////////////////////////////////////////////////////////////////////////////
|
// Commands ////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -139,14 +158,26 @@ namespace Oxide.Plugins {
|
|||||||
if (!this.IsSleepy(player)) return;
|
if (!this.IsSleepy(player)) return;
|
||||||
|
|
||||||
this.session = new SleepSession(player, () => this.OnSleepSessionEnded());
|
this.session = new SleepSession(player, () => this.OnSleepSessionEnded());
|
||||||
this.session.Begin(timer.Every(STEP_SIZE, () => this.session.KeepSleeping()));
|
player.ChatMessage("You slowly start to drift off to sleep.");
|
||||||
|
timer.Once(1f, () => {
|
||||||
|
this.session.Begin(timer.Every(STEP_SIZE, () => this.session.KeepSleeping()));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper Methods //////////////////////////////////////////////////////////////////////////
|
// Helper Methods //////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
private void OnSleepSessionEnded() {
|
private void CheckSleepiness() {
|
||||||
this.session.Abort();
|
var today = this.GetDay();
|
||||||
this.session = null;
|
if (this.lastYawnDay == today) return;
|
||||||
|
|
||||||
|
var now = this.GetTime();
|
||||||
|
if ((now > GoodNightsSleep.BED_TIME) && (now < GoodNightsSleep.BED_TIME + 1f)) {
|
||||||
|
this.lastYawnDay = today;
|
||||||
|
|
||||||
|
foreach (var player in BasePlayer.activePlayerList) {
|
||||||
|
Effect.server.Run(GoodNightsSleep.YAWN_SOUND, player.transform.position);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsSleepy(BasePlayer player) {
|
private bool IsSleepy(BasePlayer player) {
|
||||||
@@ -172,7 +203,7 @@ namespace Oxide.Plugins {
|
|||||||
|
|
||||||
var bag = this.FindNearbySleepingBag(player);
|
var bag = this.FindNearbySleepingBag(player);
|
||||||
if (bag == null) {
|
if (bag == null) {
|
||||||
player.ChatMessage("There's nowhere to sleep nearby.");
|
player.ChatMessage("You'd be a lot more comfy in your bed.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,17 +216,23 @@ namespace Oxide.Plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private SleepingBag FindNearbySleepingBag(BasePlayer player) {
|
private SleepingBag FindNearbySleepingBag(BasePlayer player) {
|
||||||
foreach (var bag in UnityEngine.Object.FindObjectsOfType<SleepingBag>()) {
|
// move up a bit so we can look down
|
||||||
if (bag == null) continue;
|
var position = player.transform.position + Vector3.up * 0.1f;
|
||||||
if (bag.deployerUserID != player.userID) continue;
|
|
||||||
|
|
||||||
var distance = Vector3.Distance(player.transform.position, bag.transform.position);
|
|
||||||
if (distance < 2f) {
|
|
||||||
return bag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
RaycastHit hit;
|
||||||
|
Physics.Raycast(position, Vector3.down, out hit, 2f);
|
||||||
|
if (hit.collider == null) return null;
|
||||||
|
|
||||||
|
var bag = hit.collider.GetComponentInParent<SleepingBag>();
|
||||||
|
if (bag == null) return null;
|
||||||
|
if (bag.deployerUserID != player.userID) return null;
|
||||||
|
|
||||||
|
return bag;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetDay() {
|
||||||
|
return TOD_Sky.Instance.Cycle.Day;
|
||||||
}
|
}
|
||||||
|
|
||||||
private float GetTime() {
|
private float GetTime() {
|
||||||
@@ -206,8 +243,7 @@ namespace Oxide.Plugins {
|
|||||||
return (
|
return (
|
||||||
this.IsOnFoundation(bag) &&
|
this.IsOnFoundation(bag) &&
|
||||||
this.IsUnderRoof(bag) &&
|
this.IsUnderRoof(bag) &&
|
||||||
this.IsNearToolchest(bag) &&
|
this.IsNearToolchest(bag)
|
||||||
true
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,17 +252,23 @@ namespace Oxide.Plugins {
|
|||||||
Vis.Entities(bag.transform.position, 25f, privlidges, LayerMask.Deployed);
|
Vis.Entities(bag.transform.position, 25f, privlidges, LayerMask.Deployed);
|
||||||
var result = privlidges.Count > 0;
|
var result = privlidges.Count > 0;
|
||||||
Pool.FreeList(ref privlidges);
|
Pool.FreeList(ref privlidges);
|
||||||
|
if (!result) {
|
||||||
|
Puts("Sleeping bag isn't close to a toolchest");
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsOnFoundation(SleepingBag bag) {
|
private bool IsOnFoundation(SleepingBag bag) {
|
||||||
// get a bit off the floor so we can look down
|
// get a bit off the floor so we can look down
|
||||||
var position = bag.transform.position + Vector3.up * 0.1f;
|
var position = bag.transform.position + Vector3.up * 0.5f;
|
||||||
|
|
||||||
// check that there's some kind of player-placed block under the sleeping bag
|
// check that there's some kind of player-placed block under the sleeping bag
|
||||||
RaycastHit hit;
|
RaycastHit hit;
|
||||||
Physics.Raycast(position, Vector3.down, out hit, 2f);
|
Physics.Raycast(position, Vector3.down, out hit, 2f);
|
||||||
if (hit.collider.GetComponentInParent<BuildingBlock>() == null) return false;
|
if (hit.collider.GetComponentInParent<BuildingBlock>() == null) {
|
||||||
|
Puts("Sleeping bag is not on a foundation");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -234,7 +276,24 @@ namespace Oxide.Plugins {
|
|||||||
private bool IsUnderRoof(SleepingBag bag) {
|
private bool IsUnderRoof(SleepingBag bag) {
|
||||||
RaycastHit hit;
|
RaycastHit hit;
|
||||||
var position = bag.transform.position;
|
var position = bag.transform.position;
|
||||||
return Physics.Raycast(position, Vector3.up, out hit, LayerMask.Construction);
|
if (!Physics.Raycast(position, Vector3.up, out hit, 10f, LayerMask.Construction)) {
|
||||||
|
Puts("Sleeping Bag is not under a roof");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSleepSessionEnded() {
|
||||||
|
if (this.session == null) return;
|
||||||
|
|
||||||
|
var player = this.session.player;
|
||||||
|
this.session.Abort();
|
||||||
|
this.session = null;
|
||||||
|
|
||||||
|
timer.Once(1f, () => {
|
||||||
|
player.ChatMessage("You awake feeling rested and refreshed.");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user