From 8e202f4c6c4eaf6d462ea9b5e6ace61a740b9f0b Mon Sep 17 00:00:00 2001
From: hwp <you@example.com>
Date: Thu, 27 Oct 2022 14:34:49 -0400
Subject: [PATCH 1/6] add getMoonState()

---
 game/03-JavaScript/base.js   |  7 ++++++-
 game/03-JavaScript/ingame.js | 25 +++++++++++++++++++++++--
 game/base-system/time.twee   | 36 +++++++++++-------------------------
 3 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/game/03-JavaScript/base.js b/game/03-JavaScript/base.js
index bffef298be..77377b872b 100644
--- a/game/03-JavaScript/base.js
+++ b/game/03-JavaScript/base.js
@@ -25,14 +25,16 @@ Mousetrap.bind(["f"], function () {
 Macro.add("time", {
 	handler() {
 		let daystate; // Never checked and always overwritten - no need to init with old value
+		let nightstate; // Tracks whether it's before midnight or after
 		let time = V.time;
 		// Sanity check
 		if (time < 0) time = 0;
-		if (time >= 24 * 60) time = 23 * 59 + 59;
+		if (time >= 24 * 60) time = (24 * 60) - 1; //note: no changes are made to V.time in this function
 
 		const hour = Math.floor(time / 60);
 		if (hour < 6) {
 			daystate = "night";
+			nightstate = "morning";
 		} else if (hour < 9) {
 			daystate = "dawn";
 		} else if (hour < 18) {
@@ -41,9 +43,12 @@ Macro.add("time", {
 			daystate = "dusk";
 		} else {
 			daystate = "night";
+			nightstate = "evening";
 		}
 		V.hour = hour;
 		V.daystate = daystate;
+		T.nightstate = nightstate;
+		T.timeChecked = true;
 	},
 });
 
diff --git a/game/03-JavaScript/ingame.js b/game/03-JavaScript/ingame.js
index 2afd94ce34..0b0f87e41d 100644
--- a/game/03-JavaScript/ingame.js
+++ b/game/03-JavaScript/ingame.js
@@ -1416,13 +1416,34 @@ function isLoveInterest(name) {
 }
 window.isLoveInterest = isLoveInterest;
 
+function getMoonState(forced = false) {
+	if (!T.timeChecked) time(); // ensure that T.nightstate exists before running (but don't call it every time bc that's wasteful)
+	if (T.moonChecked === V.time && !forced) return V.moonstate; // don't bother recalculating this if time hasn't changed (unless forced to)
+
+	if (T.nightstate === "evening") {
+		if (V.monthday === getLastDayOfMonth()) { // blood moon happens on the last night of the month
+			V.moonstate = "evening";
+		} else {
+			V.moonstate = 0; // moonstate will stay "morning" until the night after the blood moon
+		}
+	} else if (T.nightstate === "morning") { 
+		if (V.moonstate === "evening") { // if it's after midnight and there was a blood moon before midnight, then it's still a blood moon
+			V.moonstate = "morning";
+		}
+	}
+
+	T.moonChecked = V.time; //set this temp var to $time so that we don't recalculate it unless time changes in this passage for some reason
+	return V.moonstate;
+}
+window.getMoonState = getMoonState;
+
 function isBloodmoon() {
-	return V.moonstate === "evening" && V.hour >= 21 || V.moonstate === "morning" && V.hour < 5;
+	return (V.daystate === "night" && getMoonState() !== 0); // it's only a blood moon if it's night
 }
 window.isBloodmoon = isBloodmoon;
 
 function wraithSleepEventCheck() {
-	return V.wraith && V.wraith.state !== "" && V.wraith.nightmare === 1 && (V.moonstate === "evening" && V.hour >= 21 || V.moonstate === "morning" && V.hour < 5);
+	return V.wraith.state !== "" && V.wraith.nightmare === 1 && isBloodmoon(true);
 }
 window.wraithSleepEventCheck = wraithSleepEventCheck;
 
diff --git a/game/base-system/time.twee b/game/base-system/time.twee
index c9fdb46f2f..5a7c73045a 100644
--- a/game/base-system/time.twee
+++ b/game/base-system/time.twee
@@ -1844,31 +1844,17 @@
 
 <<widget "moonstate">>
 
-<<switch $month>>
-	<<case "february">>
-		<<if $year % 4 is 0>>
-			<<set _lastDay to 29>>
-		<<else>>
-			<<set _lastDay to 28>>
+	<<run getMoonState()>>
+
+	<<if $moonstate isnot 0>>
+		<<if $moonstate is "evening">>
+			<<set $moonEvent to true>>
 		<</if>>
-	<<case "april" "june" "september" "november">>
-		<<set _lastDay to 30>>
-	<<default>>
-		<<set _lastDay to 31>>
-<</switch>>
-
-<<if $monthday is _lastDay>>
-	<<set $moonstate to "evening">>
-	<<set $moonEvent to true>>
-	<<checkWraith true>>
-<<elseif $monthday is 1>>
-	<<set $moonstate to "morning">>
-	<<checkWraith true>>
-<<else>>
-	<<set $moonstate to 0>>
-	<<unset $moonEvent>>
-	<<clearWraith>>
-	<<unset $noEarSlime>>
-<</if>>
+		<<checkWraith true>>
+	<<else>>
+		<<unset $moonEvent>>
+		<<clearWraith>>
+		<<unset $noEarSlime>>
+	<</if>>
 
 <</widget>>
-- 
GitLab


From 0aeb9ed1f33cdf10b9728ef07d039ea0aa7a6b49 Mon Sep 17 00:00:00 2001
From: hwp <you@example.com>
Date: Thu, 27 Oct 2022 14:36:38 -0400
Subject: [PATCH 2/6] using isBloodmoon() in more places

---
 game/base-system/caption.twee                 |  2 +-
 game/base-system/mirror.twee                  |  2 +-
 game/base-system/named-npcs.twee              |  2 +-
 game/base-system/stat-changes.twee            |  2 +-
 game/base-system/widgets.twee                 |  2 +-
 game/overworld-forest/loc-cabin/events.twee   |  2 +-
 game/overworld-forest/loc-cabin/main.twee     |  4 +-
 .../overworld-forest/loc-churchyard/main.twee |  2 +-
 game/overworld-forest/loc-forest/events.twee  |  4 +-
 game/overworld-forest/loc-forest/widgets.twee |  8 ++--
 .../overworld-forest/loc-lake/ivory/main.twee | 10 ++---
 .../loc-lake/ivory/widgets.twee               | 20 +++++-----
 game/overworld-forest/loc-lake/main.twee      |  2 +-
 .../overworld-forest/loc-lake/underwater.twee | 40 +++++++++----------
 game/overworld-forest/loc-lake/widgets.twee   | 10 ++---
 game/overworld-forest/loc-wolfpack/main.twee  |  2 +-
 game/overworld-plains/loc-bird/main.twee      |  6 +--
 game/overworld-plains/loc-farm/cottage.twee   |  6 +--
 game/overworld-town/loc-bus/main.twee         |  2 +-
 game/overworld-town/loc-home/main.twee        |  8 ++--
 game/overworld-town/loc-pub/seduction.twee    | 12 +++---
 game/overworld-town/loc-street/widgets.twee   |  4 +-
 game/overworld-town/special-kylar/main.twee   |  2 +-
 game/overworld-town/special-robin/main.twee   |  2 +-
 .../loc-sewers/widgets.twee                   |  4 +-
 25 files changed, 81 insertions(+), 79 deletions(-)

diff --git a/game/base-system/caption.twee b/game/base-system/caption.twee
index e509b5221d..8845412a7f 100644
--- a/game/base-system/caption.twee
+++ b/game/base-system/caption.twee
@@ -446,7 +446,7 @@
 	<<if $dev is 1>>
 		<<set $allure -= ($fame.pimp / 2)>>
 	<</if>>
-	<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+	<<if isBloodmoon()>>
 		<<set $allure += 2000>>
 	<</if>>
 	<<set $baseAllure to $allure>>
diff --git a/game/base-system/mirror.twee b/game/base-system/mirror.twee
index d75f2caa38..050ccfa041 100644
--- a/game/base-system/mirror.twee
+++ b/game/base-system/mirror.twee
@@ -470,7 +470,7 @@ Increasing your allure:
 		Drenched in cum
 		<br>
 	<</if>>
-	<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+	<<if isBloodmoon()>>
 		Full moon
 		<br>
 	<</if>>
diff --git a/game/base-system/named-npcs.twee b/game/base-system/named-npcs.twee
index 074e18da91..4d9ac6b275 100644
--- a/game/base-system/named-npcs.twee
+++ b/game/base-system/named-npcs.twee
@@ -1412,7 +1412,7 @@ alternative way to write that:
 					<<silently>><<speechWraith "lines">><</silently>>
 				<</if>>
 				_line1
-			<<elseif $bus isnot "lake_ruin_prison" and !$wraith.type and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+			<<elseif $bus isnot "lake_ruin_prison" and !$wraith.type and isBloodmoon()>>
 				The Wraith
 				<<if $wraith.state is "haunt">>
 					<span class="red">is looking for you.</span>
diff --git a/game/base-system/stat-changes.twee b/game/base-system/stat-changes.twee
index 2071e6bc8c..99a7e562c8 100644
--- a/game/base-system/stat-changes.twee
+++ b/game/base-system/stat-changes.twee
@@ -96,7 +96,7 @@
 <</widget>>
 
 <<widget "updateHallucinations">>
-	<<if $trauma gte ($traumamax / 10) * 5 or $awareness gte 400 or $hallucinogen gt 0 or ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+	<<if $trauma gte ($traumamax / 10) * 5 or $awareness gte 400 or $hallucinogen gt 0 or isBloodmoon()>>
 		<<set $hallucinations to 2>>
 	<<elseif $trauma gte ($traumamax / 10) * 3 or $awareness gte 300>>
 		<<set $hallucinations to 1>>
diff --git a/game/base-system/widgets.twee b/game/base-system/widgets.twee
index f98ae8dd94..f29fd0951a 100644
--- a/game/base-system/widgets.twee
+++ b/game/base-system/widgets.twee
@@ -1829,7 +1829,7 @@
 			<</switch>>
 		<<elseif $daystate is "night">>
 			<!-- if bloodmoon -->
-			<<set _bloodmoon to ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+			<<set _bloodmoon to isBloodmoon()>>
 
 			<<if $location is "tentworld">>
 				<img id="daystate" src="img/misc/tentskynight.png">
diff --git a/game/overworld-forest/loc-cabin/events.twee b/game/overworld-forest/loc-cabin/events.twee
index 3d5a215e7e..89b050cde8 100644
--- a/game/overworld-forest/loc-cabin/events.twee
+++ b/game/overworld-forest/loc-cabin/events.twee
@@ -3027,7 +3027,7 @@ You and Eden walk through the forest, searching for anything of value.
 	<br><br>
 	Lemons grow from a cluster of small trees.
 	<br><br>
-	<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+	<<if isBloodmoon()>>
 		Eden searches the short trees for <<icon "tending/blood_lemon.gif">> lemons. <span class="green"><<He>> finds a bunch, their yellow skin crissed-crossed by red veins.</span>
 		<<tending_pick blood_lemon 6 18>>
 		<br><br>
diff --git a/game/overworld-forest/loc-cabin/main.twee b/game/overworld-forest/loc-cabin/main.twee
index 513f7f724d..6910f7371c 100644
--- a/game/overworld-forest/loc-cabin/main.twee
+++ b/game/overworld-forest/loc-cabin/main.twee
@@ -762,7 +762,7 @@ Your clothes are kept in the corner.
 <<else>>
 	You snuggle under the covers.
 <</if>>
-<<if $$wraith.state and $wraithPrison and ($moonstate is "evening" and $hour gte 11 or $moonstate is "morning" and $hour lt 6)>>
+<<if $$wraith.state and $wraithPrison and isBloodmoon()>>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
@@ -800,7 +800,7 @@ Your clothes are kept in the corner.
 <<set _autosavehere to true>>
 <<sleep>><<effects>>
 
-<<if $wraith and $wraith.nightmare is 2 and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
 	<<sleepeffects>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
diff --git a/game/overworld-forest/loc-churchyard/main.twee b/game/overworld-forest/loc-churchyard/main.twee
index e0fd754d82..b5d32a7745 100644
--- a/game/overworld-forest/loc-churchyard/main.twee
+++ b/game/overworld-forest/loc-churchyard/main.twee
@@ -4,7 +4,7 @@
 You are the in the forest cemetery. An old manor looms from a hill, surrounded by stone ruins and sepulchres.
 
 <<if $daystate is "night">>
-	<<if $moonstate is "evening" or $moonstate is "morning">>
+	<<if isBloodmoon()>>
 		The graves cast disturbing shadows in the red moonlight.
 	<<else>>
 		<<if $weather is "clear">>
diff --git a/game/overworld-forest/loc-forest/events.twee b/game/overworld-forest/loc-forest/events.twee
index 82d913b312..9ebfae05ac 100644
--- a/game/overworld-forest/loc-forest/events.twee
+++ b/game/overworld-forest/loc-forest/events.twee
@@ -785,7 +785,7 @@ Six pairs of eyes stare at you through the dim light. The pack advances on you.
 		Despite this, you <span class="green">successfully</span> swim across.
 		<br><br>
 		<<rng>>
-		<<if $wraith.hunt and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6) and $danger gte (7900 - ($allure * $forestmod))>>
+		<<if $wraith.hunt and isBloodmoon() and $danger gte (7900 - ($allure * $forestmod))>>
 			As you climb up the bank you feel your foot catch on something.
 			<<if $slimedisable is "f">>
 				You look down to see a pale white slime stuck to you, and many more emerging from the river. <<rainWraith true>>
@@ -818,7 +818,7 @@ Six pairs of eyes stare at you through the dim light. The pack advances on you.
 		The water is too violent, and you <span class="red">fail</span> to swim across the river, instead being swept downstream and deeper into the forest.
 		<br><br>
 		<<rng>>
-		<<if $wraith.hunt and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+		<<if $wraith.hunt and isBloodmoon()>>
 			As you climb up the bank you feel your foot catch on something.
 			<<if $slimedisable is "f">>
 				You look down to see a pale white slime stuck to you, and many more emerging from the river. <<rainWraith true>>
diff --git a/game/overworld-forest/loc-forest/widgets.twee b/game/overworld-forest/loc-forest/widgets.twee
index 44880b82b3..ce9fe58bbb 100644
--- a/game/overworld-forest/loc-forest/widgets.twee
+++ b/game/overworld-forest/loc-forest/widgets.twee
@@ -239,7 +239,7 @@ Go towards town
 
 
 <<widget "eventforest">>
-<<if $foresthunt lte 0 and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and ($wraith.hunt or $wraith.timer gte random(0, 40))>>
+<<if $foresthunt lte 0 and isBloodmoon(true) and $wraith.state and ($wraith.hunt or $wraith.timer gte random(0, 40))>>
 	<<wHunt "forest">>
 <<else>>
 	<<cleareventpool>>
@@ -300,7 +300,7 @@ Go towards town
 
 
 <<widget "eventforestdeep">>
-<<if $foresthunt lte 0 and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and ($wraith.hunt or $wraith.timer gte random(0, 20))>>
+<<if $foresthunt lte 0 and isBloodmoon(true) and $wraith.state and ($wraith.hunt or $wraith.timer gte random(0, 20))>>
 	<<wHunt "forest">>
 <<else>>
 	<<cleareventpool>>
@@ -1093,7 +1093,7 @@ You come to a clearing. A gentle breeze blows against your face, and small, soft
 	<<if _forest_item is 1>>
 		You spot orchids near the edge, at the base of ancient trees.
 	<<else>>
-		<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+		<<if isBloodmoon()>>
 			<span class="red">Red-veined</span> lemons grow from a cluster of small trees.
 		<<else>>
 			Lemons grow from a cluster of small trees.
@@ -1187,7 +1187,7 @@ or $lowerwetstage gte 3 and $underlowerwetstage gte 3>>
 		<</if>>
 	<<else>>
 		<<if currentSkillValue('tending') gte 200>>
-			<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+			<<if isBloodmoon()>>
 				<<icon "tending/lemon.png">> <<link [[Pick lemons (0:20)|Forest Blood Lemon Pick]]>><<pass 20>><</link>><<tendingdifficulty 200 500>>
 				<br>
 			<<else>>
diff --git a/game/overworld-forest/loc-lake/ivory/main.twee b/game/overworld-forest/loc-lake/ivory/main.twee
index 0359b87405..cea3a812c0 100644
--- a/game/overworld-forest/loc-lake/ivory/main.twee
+++ b/game/overworld-forest/loc-lake/ivory/main.twee
@@ -151,7 +151,7 @@ You turn to <<him>>. <<His>> skin has turned a stark white.
 <</switch>>
 <br><br>
 
-<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+<<if isBloodmoon()>>
 	<<link [[Next|Wraith Caught]]>><<set $wraith.exit to "forest">><</link>>
 <<else>>
 	<<link [[Next|Pub Wraith Mimic Attack]]>><</link>>
@@ -162,7 +162,7 @@ You turn to <<him>>. <<His>> skin has turned a stark white.
 <<location "forest">><<effects>>
 You shake your head. <<He>> freezes in an unnatural position, and grins. Your pulse quickens. <<His>> skin grows more and more pale by the second.
 <br><br>
-<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+<<if isBloodmoon()>>
 	"<span class="wraith"><<pcPetname "Wraith">>. You never had a choice.</span>"
 	<<if $wraith.seen gte 3>>
 		You immediately recognise it as the pale being that's been following you.
@@ -368,7 +368,7 @@ This isn't Kylar. <<trauma 12>><<ggtrauma>><<set $wraith.revealed to true>>
 	"<span class="wraith">You stole it from me,</span>" <<he>> hisses. "<span class="wraith">Give it back.</span>" The translucent limbs converge on you.
 <</if>>
 <br><br>
-<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+<<if isBloodmoon()>>
 	<<link [[Next|Wraith Caught]]>><</link>>
 <<else>>
 	<<link [[Next|Wraith Mimic Fight]]>><</link>>
@@ -565,7 +565,7 @@ This isn't $wraith.mimic. <<trauma 24>><<gggtrauma>><<set $wraith.revealed to tr
 <br><br>
 <<startWraith>>
 <br><br>
-<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+<<if isBloodmoon()>>
 	<<link [[Next|Wraith Caught]]>><</link>>
 <<else>>
 	<<link [[Next|Wraith Mimic Fight]]>><</link>>
@@ -1342,7 +1342,7 @@ You rub the tiredness out of your eyes. You catch a glimpse of yourself in the m
 	<</switch>>
 	<br><br>
 
-	<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+	<<if isBloodmoon()>>
 		<<link [[Next|Wraith Caught]]>><</link>>
 	<<else>>
 		<<link [[Next|Wraith Stalk Attack]]>><</link>>
diff --git a/game/overworld-forest/loc-lake/ivory/widgets.twee b/game/overworld-forest/loc-lake/ivory/widgets.twee
index 039be65f61..405ede1134 100644
--- a/game/overworld-forest/loc-lake/ivory/widgets.twee
+++ b/game/overworld-forest/loc-lake/ivory/widgets.twee
@@ -138,7 +138,7 @@
 <<else>>
 	<<switch random(1, 6)>>
 		<<case 1>>
-			<<if $wraith.state is "haunt" or ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+			<<if $wraith.state is "haunt" or isBloodmoon()>>
 				<<initWraith "abomination">>
 			<<else>>
 				<<initWraith "man">>
@@ -1101,7 +1101,7 @@
 	<<if !$possessed>>
 		<<switch _args[0]>>
 			<<case "town">>
-				<<if ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte (random(0, 50))>>
+				<<if isBloodmoon(true) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte (random(0, 50))>>
 					<br><br>
 					<<set $wraith.hunt to 1>>
 					A wave of dizziness and confusion washes over you. Every time you blink, you see a blurred image.
@@ -1162,7 +1162,7 @@
 				<br><br>
 				<<link [[Next|Forest]]>><<set $eventskip to 1>><</link>>
 			<<case "drain">>
-				<<if ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte (random(0, 60))>>
+				<<if isBloodmoon(true) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte (random(0, 60))>>
 					<<set $wraith.hunt to 1>>
 					<br><br>
 					A wave of dizziness and confusion washes over you. Every time you blink, you see a blurred image.
@@ -1194,7 +1194,7 @@
 					<</if>>
 				<</if>>
 			<<case "sewers">>
-				<<if ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte (random(0, 60))>>
+				<<if isBloodmoon(true) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte (random(0, 60))>>
 					<<set $wraith.hunt to 1>>
 					<br><br>
 					A wave of dizziness and confusion washes over you. Every time you blink, you see a blurred image.
@@ -1260,7 +1260,7 @@
 
 <<widget "wPersist">>
 <<if $wraith.state and !$possessed>>
-	<<if $wraith.hunt and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5)>>
+	<<if $wraith.hunt and isBloodmoon(true)>>
 		<<if _args[0] is "forest">>
 			<<if $foresthunt gte 1>>
 				<<set $wraith.hunt to $foresthunt>>
@@ -1293,14 +1293,14 @@
 				<</if>>
 			<</if>>
 		<</if>>
-	<<elseif $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5 and !$possessed>>
+	<<elseif isBloodmoon(true) and !$possessed>>
 		<<wTimerProgress>>
 	<</if>>
 <</if>>
 <</widget>>
 
 <<widget "wTimerProgress">>
-<<if $wraith.state and $wraith.hunt is 0 and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith.state and $wraith.hunt is 0 and isBloodmoon()>>
 	<<set $wraith.timer++>>
 	<<set $wraith.timer += Math.floor(C.npc["Ivory Wraith"].lust / 10)>>
 	<<if $rng gte 60 and ($parasite.left_ear.name is "slime" or $parasite.right_ear.name is "slime")>>
@@ -1376,7 +1376,7 @@
 
 <<widget "rngWraith">>
 <<if $wraith.state>>
-	<<if _args[1] is "night" and $daystate isnot "night" or _args[1] is "noBlood" and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+	<<if _args[1] is "night" and $daystate isnot "night" or _args[1] is "noBlood" and isBloodmoon()>>
 		<<set _wraithEvent to false>>
 	<<else>>
 		<<set _rngWraith to 2 + (Math.floor(C.npc["Ivory Wraith"].lust / 10))>>
@@ -1384,7 +1384,7 @@
 			<<set _rngWraith += 2>>
 		<</if>>
 		<<set _wraithHallucinations to (_args[0] is 1 or _args[0] is 2 ? _args[0] : 0)>>
-		<<if ($hallucinations gte _wraithHallucinations and _rngWraith gte random(1,100)) or ($moonstate is "evening" and $hour gte 21) or ($moonstate is "morning" and $hour lt 6)>>
+		<<if ($hallucinations gte _wraithHallucinations and _rngWraith gte random(1,100)) or isBloodmoon()>>
 			<<set _wraithEvent to true>>
 		<</if>>
 	<</if>>
@@ -1400,7 +1400,7 @@
 	<<if $daystate is "night">>
 		<<set _rngWraithSocial += 2>>
 	<</if>>
-	<<if ($hallucinations gte 1 and _rngWraithSocial gte random(1,100)) or ($moonstate is "evening" and $hour gte 21) or ($moonstate is "morning" and $hour lt 6)>>
+	<<if ($hallucinations gte 1 and _rngWraithSocial gte random(1,100)) or isBloodmoon()>>
 		<<set _wraithEventSocial to true>>
 	<</if>>
 	<<if $wraith.mimic isnot "" and $wraith.revealed>>
diff --git a/game/overworld-forest/loc-lake/main.twee b/game/overworld-forest/loc-lake/main.twee
index eb586ae237..86faee73b4 100644
--- a/game/overworld-forest/loc-lake/main.twee
+++ b/game/overworld-forest/loc-lake/main.twee
@@ -102,7 +102,7 @@ You keep low and stay among the trees to keep your <<lewdness>> hidden.
 		<</if>>
 		<br>
 	<</if>>
-	<<if $season isnot "winter" and !($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+	<<if $season isnot "winter" and !isBloodmoon()>>
 		<<if $exposed gte 2>>
 			<<if $exhibitionism gte 75 and $laketeenspresent is 1>>
 				<<ind>><<link [[Take a stroll (1:00)|Lake Stroll]]>><<pass 60>><<stress -6>><<arousal 1000>><<rng>><<set $phase to 2>><</link>><<exhibitionist5>><<garousal>><<lstress>>
diff --git a/game/overworld-forest/loc-lake/underwater.twee b/game/overworld-forest/loc-lake/underwater.twee
index ee1fd51a6d..9dcc8fe02c 100644
--- a/game/overworld-forest/loc-lake/underwater.twee
+++ b/game/overworld-forest/loc-lake/underwater.twee
@@ -5,7 +5,7 @@
 	<<passoutlake>>
 <<elseif $foresthunt gte 10>>
 	<<foresthunt>>
-<<elseif ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10) and !$possessed>>
+<<elseif isBloodmoon(true) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10) and !$possessed>>
 	<<wHunt "lake">>
 <<else>>
 	<<if $season is "winter">>
@@ -200,7 +200,7 @@ You are in the submerged ruin beneath the lake. Glowing purple lichen covers anc
 	<<passoutlake>>
 <<elseif $foresthunt gte 10>>
 	<<foresthunt>>
-<<elseif ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10) and !$possessed>>
+<<elseif isBloodmoon(true) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10) and !$possessed>>
 	<<wHunt "lake">>
 <<else>>
 	<<if $sciencelichenknown is 1 and $sciencelichenlake isnot 1 and $scienceproject is "ongoing">>
@@ -245,7 +245,7 @@ You are deep in the submerged ruin beneath the lake. Pots of different sizes fil
 	<<passoutlake>>
 <<elseif $foresthunt gte 10>>
 	<<foresthunt>>
-<<elseif ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10) and !$possessed>>
+<<elseif isBloodmoon(true) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10) and !$possessed>>
 	<<wHunt "lake">>
 <<else>>
 	<<if $lakeruinkey is 1>>
@@ -292,8 +292,8 @@ You jerk back, and convulse. The room shakes and trembles. A crack appears in th
 <<set $corruption_slime to 1>>
 
 <<if $slime_tf is 1>>
-<<set $slime_tf to 0>>
-<<set $physicalTransform to 0>>
+	<<set $slime_tf to 0>>
+	<<set $physicalTransform to 0>>
 <</if>>
 
 <<if $parasite.left_ear.name is "slime" or $parasite.right_ear.name is "slime">>
@@ -302,28 +302,28 @@ You jerk back, and convulse. The room shakes and trembles. A crack appears in th
 <</if>>
 
 <<if $parasite.left_ear.name is "slime">>
-<<removeparasite left_ear>>
+	<<removeparasite left_ear>>
 <</if>>
 <<if $parasite.right_ear.name is "slime">>
-<<removeparasite right_ear>>
+	<<removeparasite right_ear>>
 <</if>>
 <<set $noEarSlime to true>>
 
 <<if $tentacledisable is "f">>
 
-The light fades, and all falls quiet. Yet you feel a presence. Something stayed behind.
-<br><br>
+	The light fades, and all falls quiet. Yet you feel a presence. Something stayed behind.
+	<br><br>
 
-Over a dozen tentacles curl up the side of the plinth, forming a prison around you.
-<br><br>
+	Over a dozen tentacles curl up the side of the plinth, forming a prison around you.
+	<br><br>
 
-<<link [[Next|Lake Ruin Sit Tentacles]]>><<set $molestationstart to 1>><</link>>
-<br>
+	<<link [[Next|Lake Ruin Sit Tentacles]]>><<set $molestationstart to 1>><</link>>
+	<br>
 
 <<else>>
 
-<<link [[Next|Lake Ruin Plinth]]>><</link>>
-<br>
+	<<link [[Next|Lake Ruin Plinth]]>><</link>>
+	<br>
 
 <</if>>
 
@@ -366,7 +366,7 @@ You are deep in the lake ruin, in a small room with a plinth.
 	An ivory necklace sits atop it. It's studded with blue jewels.
 <</if>>
 <<set _leave to 1>>
-<<set _bmoon to (($moonstate is "evening" and $hour gte 21) or ($moonstate is "morning" and $hour lt 6))>>
+<<set _bmoon to isBloodmoon()>>
 <<set _parasite to ($parasite.left_ear.name is "slime" or $parasite.right_ear.name is "slime")>>
 <<if _bmoon>>
 	/* Display these on every blood moon entry */
@@ -427,7 +427,7 @@ You are deep in the lake ruin, in a small room with a plinth.
 <<effects>>
 You lift the necklace from the plinth. The craftsmanship is masterful, and you get the feeling that this meant a lot to someone.
 <br><br>
-<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+<<if isBloodmoon()>>
 	You suddenly hear pounding on the walls all around you. <<if $wraith and $wraith.seen gte 1>>A familiar<<else>>An unfamiliar<</if>> voice cries out, and it feels like something's grabbing at your arms and legs. You instinctively flail and push yourself backwards through the water. <<trauma 12>><<ggtrauma>>
 	<br><br>
 	It dies down after a few moments, leaving you shaken.
@@ -829,7 +829,7 @@ A warmth spreads through your fingers, up your arm and into the rest of your bod
 		Several more pairs of arms creep around you.
 	<</if>>
 	<br><br>
-	<<if $wraith.state is "haunt" and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+	<<if $wraith.state is "haunt" and isBloodmoon()>>
 		<<link [[Next|Wraith Caught]]>><<set $wraith.exit to "lake_ruin">><</link>>
 	<<else>>
 		<<link [[Next|Wraith Underwater Rape]]>><<set $molestationstart to 1>><</link>>
@@ -953,7 +953,7 @@ The creature recoils from you and disappears into darkness. <<tearful>> you turn
 	<<set $combat to 1>>
 
 	<<set $enemytype to "swarm">>
-	<<if $slimedisable is "f" and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+	<<if $slimedisable is "f" and isBloodmoon()>>
 		<<swarminit "pale slimes" "slime mass" "moving towards you" "encircle you" "fend off" 8 0>>
 	<<else>>
 		<<swarminit "fish" "swarm" "moving towards you" "encircle you" "fend off" 1 7>>
@@ -1000,7 +1000,7 @@ The creature recoils from you and disappears into darkness. <<tearful>> you turn
 	<<endcombat>>
 	<<passoutlake>>
 <<else>>
-	<<tearful>> you escape the swarms of <<if $slimedisable is "f" and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>pale slimes<<else>>fish<</if>>. They don't pursue.
+	<<tearful>> you escape the swarms of <<if $slimedisable is "f" and isBloodmoon()>>pale slimes<<else>>fish<</if>>. They don't pursue.
 	<br><br>
 	<<clotheson>>
 	<<endcombat>>
diff --git a/game/overworld-forest/loc-lake/widgets.twee b/game/overworld-forest/loc-lake/widgets.twee
index 6d3a1e2ed6..f42871ecfe 100644
--- a/game/overworld-forest/loc-lake/widgets.twee
+++ b/game/overworld-forest/loc-lake/widgets.twee
@@ -133,7 +133,7 @@ Someone screams. Everyone turns and backs away from the newcomer, a <<beasttype>
 
 <<widget "eventlakewater">>
 
-<<if ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10)>>
+<<if isBloodmoon(true) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10)>>
 	<<wHunt "lake">>
 <<elseif $bus is "lakeshallows">>
 	<<if $laketeenspresent is 1>>
@@ -163,7 +163,7 @@ Someone screams. Everyone turns and backs away from the newcomer, a <<beasttype>
 	<<link [[Next|Lake Vore]]>><<set $molestationstart to 1>><</link>>
 	<br>
 	<<elseif $rng gte 81 and $swarmdisable is "f">>
-		<<if $slimedisable is "f" and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+		<<if $slimedisable is "f" and isBloodmoon()>>
 			The water is agitated. Swarms of pale slimes encircle you.
 		<<else>>
 			The water is agitated. Swarms of small fish encircle you.
@@ -192,7 +192,7 @@ Someone screams. Everyone turns and backs away from the newcomer, a <<beasttype>
 
 <<widget "eventlakeice">>
 <<rng>>
-<<if ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10)>>
+<<if isBloodmoon(true) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10)>>
 	<<wHunt "lake">>
 <<elseif $rng gte 81>>
 	<<dancedifficulty 1 1000 true>>
@@ -237,7 +237,7 @@ Someone screams. Everyone turns and backs away from the newcomer, a <<beasttype>
 		<</if>>
 	<<elseif $weather is "clear">>
 		<<if $daystate is "night">>
-			<<if $moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6>>
+			<<if isBloodmoon()>>
 				The red moon reflects off the ice. Dread stabs at you.<<gtrauma>><<gstress>><<trauma 6>><<stress 6>>
 				<br><br>
 			<<else>>
@@ -280,7 +280,7 @@ Someone screams. Everyone turns and backs away from the newcomer, a <<beasttype>
 <</widget>>
 
 <<widget "eventlake">>
-<<if ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10)>>
+<<if isBloodmoon(true) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte random(0, 10)>>
 	<<wHunt "lake">>
 <<elseif $rng gte 81>>
 	<!-- Modified for Monster People -->
diff --git a/game/overworld-forest/loc-wolfpack/main.twee b/game/overworld-forest/loc-wolfpack/main.twee
index 9bef790222..4d51ed6849 100644
--- a/game/overworld-forest/loc-wolfpack/main.twee
+++ b/game/overworld-forest/loc-wolfpack/main.twee
@@ -430,7 +430,7 @@ You sit on the edge and try to lower yourself down, but the rock gives way and y
 :: Wolf Cave Sleep
 <<set _autosavehere to true>>
 <<sleep>><<effects>>
-<<if $wraith and $wraith.nightmare is 2 and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
 	<<sleepeffects>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
diff --git a/game/overworld-plains/loc-bird/main.twee b/game/overworld-plains/loc-bird/main.twee
index 2069a6dc40..16efe02777 100644
--- a/game/overworld-plains/loc-bird/main.twee
+++ b/game/overworld-plains/loc-bird/main.twee
@@ -1397,7 +1397,7 @@ You don't move.
 	You lie on the nest. It's hard to get comfortable.
 <</if>>
 <<endevent>>
-<<if $wraith.state and $wraithPrison and $bird.mirror is 1 and ($moonstate is "evening" and $hour gte 11 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith.state and $wraithPrison and $bird.mirror is 1 and isBloodmoon()>>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
@@ -1528,7 +1528,7 @@ You sit by the rainwater pool.
 <<set _autosavehere to true>>
 <<sleep>><<effects>>
 
-<<if $wraith and $wraith.nightmare is 2 and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
 	<<sleepeffects>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
@@ -1627,7 +1627,7 @@ You sit by the rainwater pool.
 <<set _autosavehere to true>>
 <<sleep>><<effects>>
 
-<<if $wraith and $wraith.nightmare is 2 and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
 	<<sleepeffects>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
diff --git a/game/overworld-plains/loc-farm/cottage.twee b/game/overworld-plains/loc-farm/cottage.twee
index d269204b70..0172130b53 100644
--- a/game/overworld-plains/loc-farm/cottage.twee
+++ b/game/overworld-plains/loc-farm/cottage.twee
@@ -253,7 +253,7 @@ You snuggle under the covers.
 <<if $alex_bed is "player">>
 	Alex snores beside you.
 <</if>>
-<<if $wraith.state and $wraithPrison and ($moonstate is "evening" and $hour gte 11 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith.state and $wraithPrison and isBloodmoon()>>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
@@ -270,7 +270,7 @@ You snuggle under the covers.
 		<<npcincr Alex lust 1>>
 	<</if>>
 <</if>>
-<<if $wraith and $wraith.nightmare is 2 and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
 	<<sleepeffects>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
@@ -967,7 +967,7 @@ You are in Alex's bedroom. It's similar to yours. Clothes tumble from the wardro
 <<else>>
 	You snuggle under the covers.
 <</if>>
-<<if $wraith and $wraith.state isnot "" and $wraithPrison and ($moonstate is "evening" and $hour gte 11 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith and $wraith.state isnot "" and $wraithPrison and isBloodmoon()>>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
diff --git a/game/overworld-town/loc-bus/main.twee b/game/overworld-town/loc-bus/main.twee
index d04cd341e9..45d60f54b6 100644
--- a/game/overworld-town/loc-bus/main.twee
+++ b/game/overworld-town/loc-bus/main.twee
@@ -82,7 +82,7 @@ You take a seat and look out the window.
 	<<set $dangerbus to 0>>
 	<<set $danger to random(1, 10000)>>
 	<<if $danger gte (9900 - $allure)>><<set $dangerbus to random(1, 2)>>
-		<<if $wraith.hunt and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6) and $dangerbus is 1>>
+		<<if $wraith.hunt and isBloodmoon() and $dangerbus is 1>>
 			You gaze out the window at the scenery, all bathed in red moonlight. You notice an unusually pale person stop and look at you through the window.
 			<br><br>
 			Less than a minute passes, and you see it again on the other side of the road. Then at the next stop. You blink, and it's gone.
diff --git a/game/overworld-town/loc-home/main.twee b/game/overworld-town/loc-home/main.twee
index b7cb1362cd..50ecdf4d84 100644
--- a/game/overworld-town/loc-home/main.twee
+++ b/game/overworld-town/loc-home/main.twee
@@ -723,7 +723,7 @@ You are in the bathroom.
 		<<link [[Kiss|Bed Robin Sex]]>><<set $sexstart to 1>><</link>>
 	<</if>>
 	<br>
-<<elseif $location is "home" and $wraith and $wraith.nightmare is 2 and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+<<elseif $location is "home" and $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
 	It's surrounded by trees, all bending inwards, and floating above a lake. Everything moves around you, and you find yourself hanging above a large ruin. You can't breathe.
@@ -952,7 +952,7 @@ You are in the bathroom.
 
 	<<link [[Next|Sleep Rape]]>><<set $molestationstart to 1>><</link>>
 	<br>
-<<elseif $location is "home" and $wraith and $wraith.nightmare is 2 and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+<<elseif $location is "home" and $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
 	It's surrounded by trees, all bending inwards, and floating above a lake. Everything moves around you, and you find yourself hanging above a large ruin. You can't breathe.
@@ -1506,7 +1506,7 @@ You've pushed yourself too much.
 	You snuggle under the covers.
 	<</if>>
 <</if>>
-<<if $wraith.state and $wraithPrison and ($moonstate is "evening" and $hour gte 11 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith.state and $wraithPrison and isBloodmoon()>>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
@@ -1552,7 +1552,7 @@ You've pushed yourself too much.
 You snuggle under the covers with Robin. You can feel the heat from <<his>> <<print ($robinromance is 1 and $NPCName[$NPCNameList.indexOf("Robin")].trauma lte 20 ? "naked " : "")>>body warming the bed.
 <<set $robinbed to "theirs">>
 
-<<if $wraith.state and $wraithPrison and ($moonstate is "evening" and $hour gte 11 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith.state and $wraithPrison and isBloodmoon()>>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <<endevent>>
diff --git a/game/overworld-town/loc-pub/seduction.twee b/game/overworld-town/loc-pub/seduction.twee
index cd452e2e8a..c821da5ad5 100644
--- a/game/overworld-town/loc-pub/seduction.twee
+++ b/game/overworld-town/loc-pub/seduction.twee
@@ -826,13 +826,15 @@ You knock <<him>> into the stall door, which <<he>> crashes through. <<tearful>>
 <<location "forest">><<effects>><<set $forest to 0>>
 
 <<if $drunk gt 0>>
-	<<if $rng gte 51 and !($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>><<set $location to "town">>
+	<<if $rng gte 51 and !isBloodmoon()>>
+	
+		<<set $location to "town">>
 
-	You walk with <<him>>. <<He>> has to grab your shoulders to steady you more than once, but you manage to climb onto the back seat of <<his>> car. The journey doesn't take long. "This is your home right?" <<he>> asks. "It's not my place to say but you should be more careful in the future. There are creeps who prey on cute <<girls>> like you." <<He>> helps you to the front door, only going back to <<his>> car once you're safe inside.
-	<br><br>
+		You walk with <<him>>. <<He>> has to grab your shoulders to steady you more than once, but you manage to climb onto the back seat of <<his>> car. The journey doesn't take long. "This is your home right?" <<he>> asks. "It's not my place to say but you should be more careful in the future. There are creeps who prey on cute <<girls>> like you." <<He>> helps you to the front door, only going back to <<his>> car once you're safe inside.
+		<br><br>
 
-	<<link [[Next|Orphanage]]>><<endevent>><</link>>
-	<br>
+		<<link [[Next|Orphanage]]>><<endevent>><</link>>
+		<br>
 
 	<<else>>
 		<<rngWraith>>
diff --git a/game/overworld-town/loc-street/widgets.twee b/game/overworld-town/loc-street/widgets.twee
index de20d49b5c..87cdc1c41b 100644
--- a/game/overworld-town/loc-street/widgets.twee
+++ b/game/overworld-town/loc-street/widgets.twee
@@ -2686,7 +2686,7 @@ You find a quiet place and open the <<wallet>>.
 
 <<set $dangerevent to random(1, 100)>>
 <<rng>>
-<<if $wraith.state and $eventforced and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6) and !_wraithEventSkipped>>
+<<if $wraith.state and $eventforced and isBloodmoon() and !_wraithEventSkipped>>
 	<<wraithEventStreet>>
 <<elseif $kylarwatched is 1>>
 	<<kylarwatched>>
@@ -3169,7 +3169,7 @@ You find a quiet place and open the <<wallet>>.
 
 <<widget "streeteffects">>
 <<if !$possessed>>
-	<<if ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 5) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte (random(0, 60))>>
+	<<if isBloodmoon(true) and $wraith.state and $wraith.hunt is 0 and $wraith.timer gte (random(0, 60))>>
 		<<wHunt "town">>
 	<<elseif $wraith.hunt>>
 		<<wHunt "town">>
diff --git a/game/overworld-town/special-kylar/main.twee b/game/overworld-town/special-kylar/main.twee
index 04c3e83408..dbc39e1c06 100644
--- a/game/overworld-town/special-kylar/main.twee
+++ b/game/overworld-town/special-kylar/main.twee
@@ -1816,7 +1816,7 @@ You can feel <<his>> breath, now stabilised and calm, against your skin.
 <<endevent>>
 
 You snuggle under the covers with Kylar.
-<<if $wraith.state and $wraithPrison and ($moonstate is "evening" and $hour gte 11 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith.state and $wraithPrison and isBloodmoon()>>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
diff --git a/game/overworld-town/special-robin/main.twee b/game/overworld-town/special-robin/main.twee
index 7e456e8b92..773e53bd17 100644
--- a/game/overworld-town/special-robin/main.twee
+++ b/game/overworld-town/special-robin/main.twee
@@ -4079,7 +4079,7 @@ You get into bed next to <<him>>, and turn off the lamp.
 <<set _autosavehere to true>>
 <<sleep>><<effects>>
 <<sleepeffects>>
-<<if $wraith and $wraith.nightmare is 2 and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
 	It's surrounded by trees, all bending inwards, and floating above a lake. Everything moves around you, and you find yourself hanging above a large ruin. You can't breathe.
diff --git a/game/overworld-underground/loc-sewers/widgets.twee b/game/overworld-underground/loc-sewers/widgets.twee
index 2e100f9f5c..a81edd2cc7 100644
--- a/game/overworld-underground/loc-sewers/widgets.twee
+++ b/game/overworld-underground/loc-sewers/widgets.twee
@@ -87,7 +87,7 @@
 
 <<widget "eventsdrain">>
 	<<rng>>
-	<<if $wraith.state and $wraith.hunt gte 10 and $wraithIntro is true and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6)>>
+	<<if $wraith.state and $wraith.hunt gte 10 and $wraithIntro is true and isBloodmoon()>>
 		The water congeals and warps, forming translucent tendrils that burst from the water. One collides with you, sending you sprawling. <<pain 4>><<gpain>>
 		<br><br>
 		A pale figure rises from the water, creating no disturbance on the surface. It gives you a mad smile.
@@ -420,7 +420,7 @@
 <<widget "eventssewers">>
 	<<set $sewersevent to random(5,12)>>
 	<<rng>>
-	<<if $wraith.state and $eventforced and ($moonstate is "evening" and $hour gte 21 or $moonstate is "morning" and $hour lt 6) and !_wraithEventSkipped>>
+	<<if $wraith.state and $eventforced and isBloodmoon() and !_wraithEventSkipped>>
 		<<wraithEventSewers>>
 	<<elseif $rng gte 91>>
 		You hear chanting echo through the tunnels.	It's hard to pinpoint the direction.
-- 
GitLab


From 537432faa6ca91fb903b3b44b7b3824f1d5b01a5 Mon Sep 17 00:00:00 2001
From: hwp <you@example.com>
Date: Thu, 27 Oct 2022 14:45:06 -0400
Subject: [PATCH 3/6] removing excess "$wraith" checks

---
 game/overworld-forest/loc-cabin/main.twee      | 4 ++--
 game/overworld-forest/loc-lake/underwater.twee | 2 +-
 game/overworld-forest/loc-wolfpack/main.twee   | 2 +-
 game/overworld-plains/loc-bird/main.twee       | 4 ++--
 game/overworld-plains/loc-farm/cottage.twee    | 4 ++--
 game/overworld-town/loc-temple/main.twee       | 2 +-
 game/overworld-town/special-robin/main.twee    | 2 +-
 7 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/game/overworld-forest/loc-cabin/main.twee b/game/overworld-forest/loc-cabin/main.twee
index 6910f7371c..c955bafb56 100644
--- a/game/overworld-forest/loc-cabin/main.twee
+++ b/game/overworld-forest/loc-cabin/main.twee
@@ -762,7 +762,7 @@ Your clothes are kept in the corner.
 <<else>>
 	You snuggle under the covers.
 <</if>>
-<<if $$wraith.state and $wraithPrison and isBloodmoon()>>
+<<if $wraith.state and $wraithPrison and isBloodmoon()>>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
@@ -800,7 +800,7 @@ Your clothes are kept in the corner.
 <<set _autosavehere to true>>
 <<sleep>><<effects>>
 
-<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
+<<if $wraith.nightmare is 2 and isBloodmoon()>>
 	<<sleepeffects>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
diff --git a/game/overworld-forest/loc-lake/underwater.twee b/game/overworld-forest/loc-lake/underwater.twee
index 9dcc8fe02c..f2724e3c94 100644
--- a/game/overworld-forest/loc-lake/underwater.twee
+++ b/game/overworld-forest/loc-lake/underwater.twee
@@ -428,7 +428,7 @@ You are deep in the lake ruin, in a small room with a plinth.
 You lift the necklace from the plinth. The craftsmanship is masterful, and you get the feeling that this meant a lot to someone.
 <br><br>
 <<if isBloodmoon()>>
-	You suddenly hear pounding on the walls all around you. <<if $wraith and $wraith.seen gte 1>>A familiar<<else>>An unfamiliar<</if>> voice cries out, and it feels like something's grabbing at your arms and legs. You instinctively flail and push yourself backwards through the water. <<trauma 12>><<ggtrauma>>
+	You suddenly hear pounding on the walls all around you. <<if $wraith.seen gte 1>>A familiar<<else>>An unfamiliar<</if>> voice cries out, and it feels like something's grabbing at your arms and legs. You instinctively flail and push yourself backwards through the water. <<trauma 12>><<ggtrauma>>
 	<br><br>
 	It dies down after a few moments, leaving you shaken.
 	<<if $wraith.hunt>>
diff --git a/game/overworld-forest/loc-wolfpack/main.twee b/game/overworld-forest/loc-wolfpack/main.twee
index 4d51ed6849..5ccaf9d0ef 100644
--- a/game/overworld-forest/loc-wolfpack/main.twee
+++ b/game/overworld-forest/loc-wolfpack/main.twee
@@ -430,7 +430,7 @@ You sit on the edge and try to lower yourself down, but the rock gives way and y
 :: Wolf Cave Sleep
 <<set _autosavehere to true>>
 <<sleep>><<effects>>
-<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
+<<if $wraith.nightmare is 2 and isBloodmoon()>>
 	<<sleepeffects>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
diff --git a/game/overworld-plains/loc-bird/main.twee b/game/overworld-plains/loc-bird/main.twee
index 16efe02777..e72ff52702 100644
--- a/game/overworld-plains/loc-bird/main.twee
+++ b/game/overworld-plains/loc-bird/main.twee
@@ -1528,7 +1528,7 @@ You sit by the rainwater pool.
 <<set _autosavehere to true>>
 <<sleep>><<effects>>
 
-<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
+<<if $wraith.nightmare is 2 and isBloodmoon()>>
 	<<sleepeffects>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
@@ -1627,7 +1627,7 @@ You sit by the rainwater pool.
 <<set _autosavehere to true>>
 <<sleep>><<effects>>
 
-<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
+<<if $wraith.nightmare is 2 and isBloodmoon()>>
 	<<sleepeffects>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
diff --git a/game/overworld-plains/loc-farm/cottage.twee b/game/overworld-plains/loc-farm/cottage.twee
index 0172130b53..1291cc768e 100644
--- a/game/overworld-plains/loc-farm/cottage.twee
+++ b/game/overworld-plains/loc-farm/cottage.twee
@@ -270,7 +270,7 @@ You snuggle under the covers.
 		<<npcincr Alex lust 1>>
 	<</if>>
 <</if>>
-<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
+<<if $wraith.nightmare is 2 and isBloodmoon()>>
 	<<sleepeffects>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
@@ -967,7 +967,7 @@ You are in Alex's bedroom. It's similar to yours. Clothes tumble from the wardro
 <<else>>
 	You snuggle under the covers.
 <</if>>
-<<if $wraith and $wraith.state isnot "" and $wraithPrison and isBloodmoon()>>
+<<if $wraith.state isnot "" and $wraithPrison and isBloodmoon()>>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
diff --git a/game/overworld-town/loc-temple/main.twee b/game/overworld-town/loc-temple/main.twee
index 9573c2e274..b8b33f580c 100644
--- a/game/overworld-town/loc-temple/main.twee
+++ b/game/overworld-town/loc-temple/main.twee
@@ -755,7 +755,7 @@ You look away from the <<monk>>, and <<he>> continues down the aisle.
 <<link [[Inquire about ear slime|Temple Slime]]>><</link>>
 <br>
 <</if>>
-<<if $wraith and $wraith.seen gte 10>>
+<<if $wraith.seen gte 10>>
 <<link [[Inquire about the pale figure|Temple Pale Story]]>><</link>>
 <br>
 <</if>>
diff --git a/game/overworld-town/special-robin/main.twee b/game/overworld-town/special-robin/main.twee
index 773e53bd17..04f49af996 100644
--- a/game/overworld-town/special-robin/main.twee
+++ b/game/overworld-town/special-robin/main.twee
@@ -4079,7 +4079,7 @@ You get into bed next to <<him>>, and turn off the lamp.
 <<set _autosavehere to true>>
 <<sleep>><<effects>>
 <<sleepeffects>>
-<<if $wraith and $wraith.nightmare is 2 and isBloodmoon()>>
+<<if $wraith.nightmare is 2 and isBloodmoon()>>
 	You dream of a beautiful figure, cloaked in white, standing under the red moon. It has its arms spread out to you in a welcoming gesture. You can feel its gaze boring into your mind as you step closer.
 	<br><br>
 	It's surrounded by trees, all bending inwards, and floating above a lake. Everything moves around you, and you find yourself hanging above a large ruin. You can't breathe.
-- 
GitLab


From 52230d8c50ecc2a91cba516cde006bf56b6ade43 Mon Sep 17 00:00:00 2001
From: hwp <you@example.com>
Date: Thu, 27 Oct 2022 14:53:06 -0400
Subject: [PATCH 4/6] add wraithEvent parameter to isBloodmoon()

---
 game/03-JavaScript/ingame.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/game/03-JavaScript/ingame.js b/game/03-JavaScript/ingame.js
index 0b0f87e41d..cd9da9db16 100644
--- a/game/03-JavaScript/ingame.js
+++ b/game/03-JavaScript/ingame.js
@@ -1437,8 +1437,8 @@ function getMoonState(forced = false) {
 }
 window.getMoonState = getMoonState;
 
-function isBloodmoon() {
-	return (V.daystate === "night" && getMoonState() !== 0); // it's only a blood moon if it's night
+function isBloodmoon(wraithEvent = false) {
+	return (V.daystate === "night" && getMoonState() !== 0 && (!wraithEvent || V.hour < 5)); // it's only a blood moon if it's night. also, wraith events can't start at 5 AM.
 }
 window.isBloodmoon = isBloodmoon;
 
-- 
GitLab


From bc993015d6f75909db3f3a3c58ff332ab80f3d91 Mon Sep 17 00:00:00 2001
From: hwp <you@example.com>
Date: Thu, 27 Oct 2022 15:42:35 -0400
Subject: [PATCH 5/6] add forecast parameter to getMoonState()

---
 game/03-JavaScript/ingame.js                | 18 +++++++++++-------
 game/overworld-forest/loc-cabin/main.twee   |  2 +-
 game/overworld-plains/loc-bird/main.twee    |  2 +-
 game/overworld-plains/loc-farm/cottage.twee |  4 ++--
 game/overworld-town/loc-home/main.twee      |  4 ++--
 5 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/game/03-JavaScript/ingame.js b/game/03-JavaScript/ingame.js
index cd9da9db16..ec92b74a34 100644
--- a/game/03-JavaScript/ingame.js
+++ b/game/03-JavaScript/ingame.js
@@ -1416,24 +1416,28 @@ function isLoveInterest(name) {
 }
 window.isLoveInterest = isLoveInterest;
 
-function getMoonState(forced = false) {
+function getMoonState(forced = false, forecast) {
 	if (!T.timeChecked) time(); // ensure that T.nightstate exists before running (but don't call it every time bc that's wasteful)
 	if (T.moonChecked === V.time && !forced) return V.moonstate; // don't bother recalculating this if time hasn't changed (unless forced to)
 
-	if (T.nightstate === "evening") {
+	const nightstate = forecast || T.nightstate;
+	let moonstate = V.moonstate;
+
+	if (nightstate === "evening") {
 		if (V.monthday === getLastDayOfMonth()) { // blood moon happens on the last night of the month
-			V.moonstate = "evening";
+			moonstate = "evening";
 		} else {
-			V.moonstate = 0; // moonstate will stay "morning" until the night after the blood moon
+			moonstate = 0; // moonstate will stay "morning" until the night after the blood moon
 		}
-	} else if (T.nightstate === "morning") { 
+	} else if (nightstate === "morning") { 
 		if (V.moonstate === "evening") { // if it's after midnight and there was a blood moon before midnight, then it's still a blood moon
-			V.moonstate = "morning";
+			moonstate = "morning";
 		}
 	}
 
 	T.moonChecked = V.time; //set this temp var to $time so that we don't recalculate it unless time changes in this passage for some reason
-	return V.moonstate;
+	if (!forecast) V.moonstate = moonstate; //don't modify the real moonstate if this is just a forecast 
+	return moonstate;
 }
 window.getMoonState = getMoonState;
 
diff --git a/game/overworld-forest/loc-cabin/main.twee b/game/overworld-forest/loc-cabin/main.twee
index c955bafb56..2f3ee2cd4e 100644
--- a/game/overworld-forest/loc-cabin/main.twee
+++ b/game/overworld-forest/loc-cabin/main.twee
@@ -762,7 +762,7 @@ Your clothes are kept in the corner.
 <<else>>
 	You snuggle under the covers.
 <</if>>
-<<if $wraith.state and $wraithPrison and isBloodmoon()>>
+<<if $wraith.state and $wraithPrison and getMoonState(true, "evening") is "evening">>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
diff --git a/game/overworld-plains/loc-bird/main.twee b/game/overworld-plains/loc-bird/main.twee
index e72ff52702..80f28fa574 100644
--- a/game/overworld-plains/loc-bird/main.twee
+++ b/game/overworld-plains/loc-bird/main.twee
@@ -1397,7 +1397,7 @@ You don't move.
 	You lie on the nest. It's hard to get comfortable.
 <</if>>
 <<endevent>>
-<<if $wraith.state and $wraithPrison and $bird.mirror is 1 and isBloodmoon()>>
+<<if $wraith.state and $wraithPrison and $bird.mirror is 1 and getMoonState(true, "evening") is "evening">>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
diff --git a/game/overworld-plains/loc-farm/cottage.twee b/game/overworld-plains/loc-farm/cottage.twee
index 1291cc768e..2895033a6c 100644
--- a/game/overworld-plains/loc-farm/cottage.twee
+++ b/game/overworld-plains/loc-farm/cottage.twee
@@ -253,7 +253,7 @@ You snuggle under the covers.
 <<if $alex_bed is "player">>
 	Alex snores beside you.
 <</if>>
-<<if $wraith.state and $wraithPrison and isBloodmoon()>>
+<<if $wraith.state and $wraithPrison and getMoonState(true, "evening") is "evening">>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
@@ -967,7 +967,7 @@ You are in Alex's bedroom. It's similar to yours. Clothes tumble from the wardro
 <<else>>
 	You snuggle under the covers.
 <</if>>
-<<if $wraith.state isnot "" and $wraithPrison and isBloodmoon()>>
+<<if $wraith.state isnot "" and $wraithPrison and getMoonState(true, "evening") is "evening">>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
diff --git a/game/overworld-town/loc-home/main.twee b/game/overworld-town/loc-home/main.twee
index 50ecdf4d84..a52de0dc14 100644
--- a/game/overworld-town/loc-home/main.twee
+++ b/game/overworld-town/loc-home/main.twee
@@ -1506,7 +1506,7 @@ You've pushed yourself too much.
 	You snuggle under the covers.
 	<</if>>
 <</if>>
-<<if $wraith.state and $wraithPrison and isBloodmoon()>>
+<<if $wraith.state and $wraithPrison and getMoonState(true, "evening") is "evening">>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
@@ -1552,7 +1552,7 @@ You've pushed yourself too much.
 You snuggle under the covers with Robin. You can feel the heat from <<his>> <<print ($robinromance is 1 and $NPCName[$NPCNameList.indexOf("Robin")].trauma lte 20 ? "naked " : "")>>body warming the bed.
 <<set $robinbed to "theirs">>
 
-<<if $wraith.state and $wraithPrison and isBloodmoon()>>
+<<if $wraith.state and $wraithPrison and getMoonState(true, "evening") is "evening">>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <<endevent>>
-- 
GitLab


From 880aee0ab215383a5e351d4e97f4c886e2b540df Mon Sep 17 00:00:00 2001
From: hwp <you@example.com>
Date: Thu, 27 Oct 2022 21:36:12 -0400
Subject: [PATCH 6/6] added bloodmoon forecasting to one more file

---
 game/overworld-town/special-kylar/main.twee | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/game/overworld-town/special-kylar/main.twee b/game/overworld-town/special-kylar/main.twee
index e80f7317c5..85c8986104 100644
--- a/game/overworld-town/special-kylar/main.twee
+++ b/game/overworld-town/special-kylar/main.twee
@@ -1816,7 +1816,7 @@ You can feel <<his>> breath, now stabilised and calm, against your skin.
 <<endevent>>
 
 You snuggle under the covers with Kylar.
-<<if $wraith.state and $wraithPrison and isBloodmoon()>>
+<<if $wraith.state and $wraithPrison and getMoonState(true, "evening") is "evening">>
 	You feel anxious, and your eyes dart over to the mirror.
 <</if>>
 <br><br>
-- 
GitLab