Newer
Older
Use Time prefix when accessing any getters or functions (e.g. Time.second, Time.schoolDay, or Time.getLastDayOfMonth(), etc.)
Getters: (Most of these are being used in one way or another)
Time.date - Returns Date object of current date.
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Time.holidayMonths - Returns array of all months that are considered holidays.
Time.second - Returns current number of seconds since last whole minute.
Time.minute - Returns current number of minutes since last whole hour.
Time.hour - Returns current hour of the day.
Time.weekDay - previously $weekday - Returns day of the week (1 being sunday, 7 being saturday)
Time.weekDayName - Returns the day of the week, with first letter in uppercase. (e.g. Monday)
Time.monthDay - Returns current date - (e.g. 12 if its the 12th)
Time.month - previously $month - Returns current month of the year (1 being january, 12 being december)
Time.monthName - Returns name of the current month, with first letter in uppercase. (e.g. January)
Time.year - Returns current year
Time.days - Returns total number of days since game start. (starts at 0)
Time.season - Previously $season - Returns string of current season (e.g. "winter")
Time.startDate - Returns Date object of start date
Time.tomorrow - Returns Date object of day after today
Time.yesterday - Returns Date object of day before today
Time.schoolTerm - Returns true if current day is during a school term, and false if a holiday.
Time.schoolDay - Returns true if current day is a school day, and false otherwise
Time.schoolTime - Returns true if current time is between 8-15 and is a school day
Time.dayState - previously $daystate - Returns string of day state (e.g. "dawn", or "day")
Time.nightState - previously $nightstate- Returns string of night state (e.g. "evening", or "morning")
Time.nextSchoolTermStartDate - Returns date object of the day when the next school term starts
Time.nextSchoolTermEndDate - Returns date object of the day when the current school term ends
*/
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
const moonPhases = {
new: {
start: 0,
end: 0.03,
endAlt: 1,
description: "New Moon",
},
waxingCrescent: {
start: 0.03,
end: 0.22,
description: "Waxing Crescent",
},
firstQuarter: {
start: 0.22,
end: 0.28,
description: "First Quarter",
},
waxingGibbous: {
start: 0.28,
end: 0.47,
description: "Waxing Gibbous",
},
full: {
start: 0.47,
end: 0.53,
description: "Full Moon",
},
waningGibbous: {
start: 0.53,
end: 0.72,
description: "Waning Gibbous",
},
lastQuarter: {
start: 0.72,
end: 0.78,
description: "Last Quarter",
},
waningCrescent: {
start: 0.78,
end: 0.97,
description: "Waning Crescent",
},
};
const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const daysOfWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
function set(time = V.timeStamp) {
V.startDate ??= new DateTime(2022, 9, 4, 7).timeStamp;
if (time instanceof DateTime) {
currentDate = time;
V.timeStamp = time.timeStamp - V.startDate;
} else {
currentDate = new DateTime(V.startDate + time);
V.timeStamp = time;
}
}
/*
* Changes date without "passing time"
*/
function setDate(date) {
set(date.timeStamp - V.startDate);
}
function setTime(hour, minute) {
setDate(new DateTime(currentDate.year, currentDate.month, currentDate.day, hour || 0, minute || 0));
}
function setTimeRelative(hour, minute) {
setDate(new DateTime(currentDate.year, currentDate.month, currentDate.day, currentDate.hour + (hour || 0), currentDate.minute + (minute || 0)));
}
/**
*
* Pass X amount of seconds, executing code after reaching certain thresholds.
* Checks for: year, week, day, hour, minute, dawn, noon.
* Currently no function is called when only passing seconds (if minute mark is not reached)
*
* @param {number} seconds
*/
function pass(seconds) {
const fragment = document.createDocumentFragment();
if (seconds < 0) return fragment;
const prevDate = new DateTime(currentDate);
set(V.timeStamp + seconds);
const minutes = Math.floor((currentDate.timeStamp - prevDate.timeStamp) / 60) || (60 + (currentDate.minute - prevDate.minute)) % 60;
if (!minutes) return fragment;
fragment.append(minutePassed(minutes));
const hours = Math.floor(minutes / 60) || (24 + (currentDate.hour - prevDate.hour)) % 24;
fragment.append(hourPassed(hours));
if (
!V.daily.dawnCheck &&
((prevDate.hour < 6 && (currentDate.hour >= 6 || currentDate.day !== prevDate.day)) || (currentDate.day !== prevDate.day && currentDate.hour >= 6))
) {
fragment.append(dawnCheck());
if (
!V.daily.noonCheck &&
((prevDate.hour < 12 && (currentDate.hour >= 12 || currentDate.day !== prevDate.day)) ||
(currentDate.day !== prevDate.day && currentDate.hour >= 12))
) {
fragment.append(noonCheck());
}
const days = Math.floor(hours / 24) || (prevDate.lastDayOfMonth + currentDate.day - prevDate.day) % prevDate.lastDayOfMonth;
if (!days) return fragment;
if (prevDate.weekDay === 7 && currentDate.weekDay === 1) {
fragment.append(weekPassed());
}
if (prevDate.yearDay < Time.startDate.yearDay && currentDate.yearDay >= Time.startDate.yearDay) {
fragment.append(yearPassed());
}
function getNextSchoolTermStartDate(date) {
while (holidayMonths.includes(newDate.month)) {
newDate.addMonths(1);
return newDate.getFirstWeekdayOfMonth(2);
}
function getNextSchoolTermEndDate(date) {
newDate.addMonths(holidayMonths.find(e => e >= newDate.month) - newDate.month);
return newDate.getFirstWeekdayOfMonth(2).addDays(-3).addHours(15);
let termEndDate = getNextSchoolTermEndDate(date);
termEndDate = new DateTime(termEndDate.year, termEndDate.month, termEndDate.day);
termEndDate.addDays(1);
const prevMonth = ((date.month - 2 + 12) % 12) + 1;
return !(
date.timeStamp >= termEndDate.timeStamp ||
(holidayMonths.includes(date.month) && date.day >= firstMonday.day) ||
(holidayMonths.includes(prevMonth) && date.day < firstMonday.day)
function isSchoolDay(date) {
return isSchoolTerm(date) && date.weekDay > 1 && date.weekDay < 7;
}
function getDayOfYear(date) {
const start = new DateTime(date.year, 1, 1);
const diff = date.timeStamp - start.timeStamp;
}
function getSecondsSinceMidnight(date) {
return date.hour * TimeConstants.secondsPerHour + date.minute * TimeConstants.secondsPerMinute;
}
// Current moon phase
function currentMoonPhase(date) {
const phaseFraction = date.moonPhaseFraction;
for (const phase in moonPhases) {
const range = moonPhases[phase];
if ((phaseFraction >= range.start && phaseFraction < range.end) || (range.endAlt && phaseFraction >= 0.97)) {
return phase;
}
}
}
// Date of previous occurrence of a specific moon phase
// Example: Time.previousMoonPhase("full")
function previousMoonPhase(targetPhase) {
if (!(targetPhase in moonPhases)) {
throw new Error(`Invalid moon phase: ${targetPhase}`);
}
const date = new DateTime(currentDate.year, currentDate.month, currentDate.day, 0, 0);
do {
date.addDays(-1);
const currentPhase = currentMoonPhase(date);
if (currentPhase === targetPhase) {
return date;
}
} while (true);
}
// Date of next occurrence of a specific moon phase
// Example: Time.nextMoonPhase("full")
function nextMoonPhase(targetPhase) {
if (!(targetPhase in moonPhases)) {
throw new Error(`Invalid moon phase: ${targetPhase}`);
}
const date = new DateTime(currentDate.year, currentDate.month, currentDate.day, 0, 0);
do {
date.addDays(1);
const currentPhase = currentMoonPhase(date);
if (currentPhase === targetPhase) {
return date;
}
} while (true);
}
function isBloodMoon(date) {
return (date.day === date.lastDayOfMonth && date.hour >= 21) || (date.day === 1 && date.hour < 6);
}
function getSeason(date) {
return date.month > 11 || date.month < 3 ? "winter" : date.month > 8 ? "autumn" : date.month > 5 ? "summer" : "spring";
}
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
return Object.create({
get date() {
return currentDate;
},
get holidayMonths() {
return holidayMonths;
},
get second() {
return currentDate.second;
},
get minute() {
return currentDate.minute;
},
get hour() {
return currentDate.hour;
},
get weekDay() {
return currentDate.weekDay;
},
get weekDayName() {
return currentDate.weekDayName;
},
get monthDay() {
return currentDate.day;
},
get month() {
return currentDate.month;
},
get monthName() {
return currentDate.monthName;
},
get year() {
return currentDate.year;
},
get days() {
return Math.floor((currentDate.timeStamp - Time.startDate.timeStamp) / TimeConstants.secondsPerDay);
},
set startDate(value) {
V.startDate = value.timeStamp;
},
get startDate() {
return new DateTime(V.startDate);
},
get tomorrow() {
const date = new DateTime(currentDate);
return date.addDays(1);
},
get yesterday() {
const date = new DateTime(currentDate);
return date.addDays(-1);
},
get schoolTerm() {
return isSchoolTerm(currentDate);
},
get schoolDay() {
return isSchoolDay(currentDate);
},
get schoolTime() {
return isSchoolTime(currentDate);
},
get dayState() {
if (hour < 6 || hour >= 21) {
return "night";
}
if (hour >= 18) {
return "dusk";
}
return hour >= 9 ? "day" : "dawn";
return getNextSchoolTermStartDate(currentDate);
return getNextSchoolTermEndDate(currentDate);
},
get lastDayOfMonth() {
return currentDate.lastDayOfMonth;
},
get dayOfYear() {
return getDayOfYear(currentDate);
},
get secondsSinceMidnight() {
return getSecondsSinceMidnight(currentDate);
},
get currentMoonPhase() {
return currentMoonPhase(currentDate);
},
pass,
isSchoolTerm,
isSchoolDay,
isSchoolTime,
getDayOfYear,
getSecondsSinceMidnight,
nextMoonPhase,
previousMoonPhase,
isBloodMoon,
getSeason,
getNextSchoolTermStartDate,
getNextSchoolTermEndDate,
getNextWeekdayDate: weekDay => currentDate.getNextWeekdayDate(weekDay),
getPreviousWeekdayDate: weekDay => currentDate.getPreviousWeekdayDate(weekDay),
isWeekEnd: () => currentDate.weekEnd,
});
})();
window.Time = Time;
/* Set current time */
Time.set();
});
/* Local functions */
function yearPassed() {
const fragment = document.createDocumentFragment();
V.scienceproject = "none";
V.mathsproject = "none";
V.englishPlay = "none";
const fragment = document.createDocumentFragment();
if (V.science_exam >= 200 && V.sciencetrait < 4) {
V.effectsmessage = 1;
V.science_up_message = 1;
fragment.append(wikifier("school_skill_up", "science"));
} else if (V.science_exam <= -100 && V.sciencetrait >= 0) {
V.effectsmessage = 1;
V.science_down_message = 1;
fragment.append(wikifier("school_skill_down", "science"));
}
if (V.maths_exam >= 200 && V.mathstrait < 4) {
V.effectsmessage = 1;
V.maths_up_message = 1;
fragment.append(wikifier("school_skill_up", "maths"));
} else if (V.maths_exam <= -100 && V.mathstrait >= 0) {
V.effectsmessage = 1;
V.maths_down_message = 1;
fragment.append(wikifier("school_skill_down", "maths"));
}
if (V.english_exam >= 200 && V.englishtrait < 4) {
V.effectsmessage = 1;
V.english_up_message = 1;
fragment.append(wikifier("school_skill_up", "english"));
} else if (V.english_exam <= -100 && V.englishtrait >= 0) {
V.effectsmessage = 1;
V.english_down_message = 1;
fragment.append(wikifier("school_skill_down", "english"));
}
if (V.history_exam >= 200 && V.historytrait < 4) {
V.effectsmessage = 1;
V.history_up_message = 1;
fragment.append(wikifier("school_skill_up", "history"));
} else if (V.history_exam <= -100 && V.historytrait >= 0) {
V.effectsmessage = 1;
V.history_down_message = 1;
fragment.append(wikifier("school_skill_down", "history"));
}
if (Time.schoolTerm) {
V.science_exam = Math.clamp(V.science_exam - 7, -107, 200);
V.maths_exam = Math.clamp(V.maths_exam - 7, -107, 200);
V.english_exam = Math.clamp(V.english_exam - 7, -107, 200);
V.history_exam = Math.clamp(V.history_exam - 7, -107, 200);
fragment.append(wikifier("exam_difficulty"));
}
if (V.robinpaid === 1) V.robinPayout = 0;
else {
V.robinmoney -= 400;
if (V.robinmoney <= 0 && V.robindebt >= 0) {
V.robinmoney = 0;
V.robindebt++;
}
}
if (V.robinpaid !== 1 && V.robindebt >= V.robindebtlimit && V.robindebtevent <= 0) {
fragment.append(wikifier("robinPunishment", "docks"));
V.robinmoney += (V.robin.stayup >= 1 ? 250 : 300) + V.robin.moneyModifier;
if (V.edenfreedom >= 1 && V.edenshopping === 2) V.edenshopping = 0;
if (V.loft_kylar) V.loft_spray = 0;
if (V.farm) {
if (V.farm.tower_guard) {
V.farm.tower_guard_unpaid++;
V.farm.tower_guard_patience = 0;
}
}
if (V.sydney) {
if (V.sydney.glasses === "broken" || V.sydney.glasses === "playerbroken") {
V.sydney.glasses = "glasses";
V.sydneyGlassesNotice = 1;
}
}
if (V.syndromewolves === 1) V.wolfcavepatrol = 1;
if (V.photo) {
if (V.photo.silly === "paid") V.photo.silly = 0;
V.photo.shoot = 0;
}
if (V.nightmareTimer && V.nightmareTimer > 0) {
V.nightmareTimer--;
if (V.nightmareTimer <= 0) delete V.nightmareTimer;
}
if (V.brothelVending.condoms === 0 && V.brothelVending.lube === 0) V.brothelVending.weeksEmpty += 1;
if (V.brothelVending.weeksEmpty >= 4) V.brothelVending.status = "sold";
statChange.worldCorruption("soft", V.world_corruption_hard);
const fragment = document.createDocumentFragment();
Weather.sky.initSun();
if (V.statFreeze) return fragment;
fragment.append(wikifier("seenPassageChecks"));
fragment.append(wikifier("prison_day"));
fragment.append(wikifier("clearNPC", "pharmNurse"));
V.physiquechange = 1;
V.home_event_timer--;
V.park_fame = Math.clamp(V.park_fame - 7, 0, 100);
V.museuminterest = Math.clamp(V.museuminterest - (V.museuminterest >= 60 ? 5 : 2), 0, 100);
if (V.gamemode !== "hard" && V.uncomfortable.lewd) {
V.exhibitionism = Math.max(V.exhibitionism - 1, 0);
V.promiscuity = Math.max(V.promiscuity - 1, 0);
V.deviancy = Math.max(V.deviancy - 1, 0);
}
if (V.locker_suspicion > 0) statChange.lockerSuspicion(-1);
if (V.whitneyromance || C.npc.Whitney.dom >= 20) {
V.bullytimer += 20;
V.bullytimeroutside += 10;
} else {
V.bullytimer += 10;
V.bullytimeroutside += 5;
}
if (Time.weekDay === 7) {
if (V.brothelshowdata.type !== "none" && !V.brothelshowdata.done && V.brothelshowdata.intro) {
V.brothelshowdata.missed = true;
V.brothelshowdata.type = "none";
}
V.brothelshowdata.done = false;
}
if (V.brothel_escortjob !== undefined && Time.date.timeStamp > V.brothel_escortjob.date) {
V.brothel_escortjob.missed = true;
}
if (Time.weekDay === 2) {
delete V.museumhorse;
delete V.museumduck;
}
if (V.medicated) V.medicated = Math.max(Math.trunc((V.medicated - 1) * 0.5), 0);
if (V.asylummedicated) V.asylummedicated = Math.max(Math.trunc((V.asylummedicated - 1) * 0.5), 0);
if (V.brothel_rivalry_timer !== undefined) V.brothel_rivalry_timer--;
if (V.orphanageWardIntro) V.home_event_ward_timer--;
if (V.location === "asylum") V.asylumbound--;
const rng = random(1, 100);
if (rng >= 95) V.brothel_basement_price = 3000;
else if (rng >= 85) V.brothel_basement_price = 2000;
else if (rng >= 45) V.brothel_basement_price = 1000;
else V.brothel_basement_price = 500;
if (V.chef_rework > 0) V.chef_rework--;
if (V.chef_sus > 0) V.chef_sus--;
if (V.stall_rejected >= 1) V.stall_rejected = Math.clamp(V.stall_rejected - 1, 0, 100);
if (V.temple_garden >= 1) V.temple_garden = Math.clamp(V.temple_garden - 10, 0, 100);
if (V.temple_quarters >= 1) V.temple_quarters = Math.clamp(V.temple_quarters - 10, 0, 100);
if (V.temple_chastity_timer > 0) V.temple_chastity_timer--;
if (V.temple_rank !== "prospective" && V.temple_rank !== "initiate") {
if (V.grace >= 1 && !V.daily.graceUp) statChange.grace(-2);
}
if (V.temple_evaluation) {
V.temple_evaluation--;
if (V.temple_evaluation <= 0) delete V.temple_evaluation;
}
if (V.wolfcavebreast >= 1) delete V.wolfcavebreast;
if (V.wolfcavepatrol === 1) V.wolfcavepatrolchance = random(1, 3);
if (V.temple_jordan_prayer === 1) delete V.temple_jordan_prayer;
if (V.school_crossdress_message >= 1 || V.school_herm_message >= 1) V.effectsmessage = 1;
if (V.syndromewolves === 1) {
fragment.append(wikifier("wolf_cave_update"));
if (V.wolfchallengetimer === undefined) V.wolfchallengetimer = 14;
else V.wolfchallengetimer--;
}
if (V.estatePersistent) {
if (V.estatePersistent.suspicion && V.estatePersistent.suspicion >= 1) fragment.append(wikifier("blackjackSuspicion", -5 - C.npc.Wren.love / 5));
if (V.estatePersistent.newDeckTimer > 0 && V.estatePersistent.markedCards && V.estatePersistent.markedCards.size > 0) {
/* we don't re-set this to 3 here - we only do that in the same
passage where we actually reset the deck.
we don't do that here because we acknowledge the timer and actually reset it
when the player enters the cottage, to not confuse things mid-game
*/
V.estatePersistent.newDeckTimer--;
}
}
if (V.balloonStand.robin.status === "closed") V.balloonStand.robin.status = "sabotaged";
if (V.robin.timer.customer >= 1) V.robin.timer.customer--;
if (V.robin.timer.hurt >= 1) V.robin.timer.hurt--;
if (V.robin.timer.hurt === 0) V.robin.hurtReason = "nothing";
V.robin.stayup = V.robin.stayup === 1 ? 2 : 0;
if (numberOfEarSlime()) {
// Daily Corruption
if (V.earSlime.growth < 50) statChange.corruption(-1);
statChange.corruption(numberOfEarSlime(), true);
if (V.bell_timer) V.bell_timer--;
if (V.lake_ice_broken >= 1) V.lake_ice_broken--;
if (V.lake_ice_broken < 1) delete V.lake_ice_broken;
if (V.community_service >= 1) {
if (V.community_service_done !== 1 && !["asylum", "prison"].includes(V.location)) {
V.effectsmessage = 1;
V.community_message = "missed";
}
delete V.community_service_done;
}
if (V.awareness >= 300) V.awarelevel = 2;
else if (V.awareness >= 200) V.awarelevel = 1;
else if (V.awareness <= -1) V.awarelevel = -1;
else V.awarelevel = 0;
if (V.awarelevel <= 1 && V.loveInterest.secondary !== "None") {
V.loveInterest_message = 1;
V.loveInterest.secondary = "None";
V.effectsmessage = 1;
} else if (V.awarelevel >= 2 && V.loveInterest.primary !== "None" && V.loveInterest.secondary === "None" && !V.loveInterestAwareMessage) {
V.loveInterest_message = 2;
V.effectsmessage = 1;
}
if (V.pound) {
V.pound.compete = 0;
fragment.append(wikifier("stray_happiness", -1));
// Not seen bailey for more than 2 weeks, tracks missed rent
if (V.renttime < 0 && V.renttime % 7 === 0) {
V.baileyRefusedToPayTotal += V.rentmoney + (V.babyRent || 0);
V.baileyRefusedToPayTotalStat += V.rentmoney + (V.babyRent || 0);
}
if (V.flashbacktown > 0) V.flashbacktown--;
if (V.flashbackhome > 0) V.flashbackhome--;
if (V.flashbackbeach > 0) V.flashbackbeach--;
if (V.flashbackunderground > 0) V.flashbackunderground--;
if (V.flashbackschool > 0) V.flashbackschool--;
if (V.flashbacktown === 1) V.flashbacktownready = 1;
if (V.flashbackhome === 1) V.flashbackhomeready = 1;
if (V.flashbackbeach === 1) V.flashbackbeachready = 1;
if (V.flashbackunderground === 1) V.flashbackundergroundready = 1;
if (V.flashbackschool === 1) V.flashbackschoolready = 1;
V.smuggler_timer--;
if (V.smuggler_timer < 0) {
V.smuggler_timer = random(4, 7);
const rng = random(1, 100);
if (rng >= 76) V.smuggle_location = "forest";
else if (rng >= 51) V.smuggle_location = "sewer";
else if (rng >= 26) V.smuggle_location = "beach";
else V.smuggle_location = "bus";
delete V.smuggler_known;
}
if (V.tailorMonthlyService > 0) V.tailorMonthlyService--;
else if (V.tailorMonthlyService === 0) delete V.tailorMonthlyService;
if (V.wardrobeRepair && V.wardrobeRepair.timeLeft === 1) V.wardrobeRepair.timeLeft = 0;
if (V.clothingShop.ban > 0) V.clothingShop.ban--;
else V.clothingShop.banExtension = false;
if (V.adultShop.ban > 0) V.adultShop.ban--;
else V.adultShop.banExtension = false;
V.adultShop = { ban: 0, banExtension: false, spotted: false, stolenClothes: 0, totalStolenClothes: 0, banCount: 0, rng: random(0, 1000) };
}
if (V.farm) {
if (V.farm.milking.catchChance > random(10, 1000) / 10) V.farm.milking.caught = true;
if (V.farm.milking.catchChance >= 25) V.farm.milking.catchChance = Math.clamp(V.farm.milking.catchChance * 0.95, 0, 100).toFixed(3);
else V.farm.milking.catchChance = Math.clamp(V.farm.milking.catchChance * 0.98, 0, 100).toFixed(3);
if (Weather.precipitation === "rain" && V.bird.upgrades?.firepit && !V.bird.upgrades.shelter) {
const burnTime = getBirdBurnTime() * 60; // seconds
if (burnTime > 0) {
KnotLikeThis
committed
Cooker.addBurnTime(V.bird.firepit, Math.floor(-burnTime / 2) + Time.minute * 30);
if (V.officejobintro === 1) V.officelastcomplaintday++;
delete V.glideScared;
delete V.swimCrossdressPermission;
delete V.masturbation_oralSkillMax;
if (V.pubfame) {
if (V.pubfame.timer >= 1) V.pubfame.timer--;
if (V.pubfame.status === "hiding") V.pubfame.detail = "hiding";
if (V.pubfame.target) V.pubfame.status = "accepted";
else V.pubfame.status = "ready";
delete V.pubfame.timer;
}
for (const fameKeys of Object.keys(V.fameDecay)) {
if (V.fameDecayTimer[fameKeys] >= 1) {
V.fameDecayTimer[fameKeys]--;
V.fame[fameKeys] -= V.fameDecay[fameKeys];
} else if (V.fameDecayTimer[fameKeys] <= 0) {
V.fame[fameKeys] = Math.round(V.fame[fameKeys]);
}
}
}
if (V.randomNNPCStraponsToClear) {
V.NPCName.forEach(npc => {
if (npc.strapons && npc.strapons.length >= 1) {
/* This removes all strapons that have the temp tag, and ignores any that lack this variable */
npc.strapons = npc.strapons.filter(strapon => !strapon.temp);
console.debug("Removed temp strap-ons");
if (V.adultshopprogress < 22 && Time.weekDay === 6) V.adultshopprogress++;
else if (V.adultshopgrandopening) fragment.append(wikifier("unlockAdultShop"));
else if (V.adultshopprogress >= 22 && !V.adultshopunlocked) V.adultshopgrandopening = true;
else if (V.adultshopdegree < 15) V.adultshopdegree += 0.1;
delete V.adultshophelped;
if (V.location !== "tentworld") {
delete V.tentacle_forest_lurker;
}
if (V.brothelVending) {
const rng = random(Math.min(1, V.brothelVending.condoms), Math.min(10, V.brothelVending.condoms));
V.brothelVending.condoms -= rng;
V.brothelVending.condomsToRefill = 200 - V.brothelVending.condoms;
}
if (V.brothelVending) {
const rng = random(Math.min(1, V.brothelVending.lube), Math.min(10, V.brothelVending.lube));
V.brothelVending.lube -= rng;
V.brothelVending.lubeToRefill = 200 - V.brothelVending.lube;
fragment.append(wikifier("menstruationCycle", "daily"));
pregnancyProgress();
pregnancyProgress("anus");
fragment.append(wikifier("rutCycle"));
npcPregnancyCycle();
randomPregnancyProgress();
fragment.append(dailyPlayerEffects());
fragment.append(dailySchoolEffects());
fragment.append(dailyFarmEvents());
fragment.append(dailyTransformationEffects());
fragment.append(dailyNPCEffects());
fragment.append(yearlyEventChecks());
parasiteProgressDay();
parasiteProgressDay("vagina");
fragment.append(wikifier("creatureContainersProgressDay"));
if (Number.isInteger(V.challengetimer)) {
V.challengetimer--;
if (V.challengetimer < 0) delete V.challengetimer;
}
if (V.whitneyRescueStatus) {
V.whitneyRescueTimer = (V.whitneyRescueTimer || 8) - 1;
if (V.whitneyRescueTimer <= 0) {
if (V.whitneyRescueStatus === "humiliated") {
V.whitneyRescueStatus = "shaken";
V.whitneyRescueTimer = 14;
} else {
delete V.whitneyRescueTimer;
delete V.whitneyRescueStatus;
}
}
if (V.moorLessDangerAll > 1) {
V.moorLessDangerAll -= 1000;
} else {
delete V.moorLessDangerAll;
}
if (V.bird.clean >= 1) V.bird.clean = Math.clamp(V.bird.clean - (10 - V.bird.upgrades.shelter), 0, 100);
/* Set flag to determine Kylar's position at lunch */
V.daily.kylar.libraryStalk = rollKylarLibraryStalkFlag();
// daysTillLaying only applies to unfertilised eggs
if (V.harpyEggs) V.harpyEggs.daysTillLaying--;
if (V.harpyEggsPrevent) {
V.harpyEggsPrevent--;
if (V.harpyEggsPrevent <= 0) delete V.harpyEggsPrevent;
}
// Activate the robin pillory
if (V.robinPillory && V.robinPillory.danger !== undefined && (V.robindebtevent <= 1 || !V.baileySold)) V.robinPillory.active = true;
xao
committed
const fragment = document.createDocumentFragment();
if (V.statFreeze) return fragment;
if (V.innocencestate === 1 && V.control <= 0) statChange.awareness(1);
statChange.control(1);
fragment.append(wikifier("orgasmHourlyRecovery"));
fragment.append(wikifier("wetnessCalculate"));
fragment.append(wikifier("bimboCheck", "upper"));
fragment.append(wikifier("bimboCheck", "lower"));
fragment.append(wikifier("bimboCheck", "feet"));
if (V.ejactrait >= 1) V.stress -= (V.goocount + V.semencount) * 10;
if (V.kylarwatched) V.kylarwatchedtimer--;
if (V.parasite.nipples.name) statChange.milkvolume(1);
if (V.worn.head.name === "hairpin" || V.sexStats.pills.pills["Hair Growth Formula"].doseTaken) {
let count = 0 + (V.worn.head.name === "hairpin" && random(0, 100) >= 75 ? 1 : 0);
count += V.sexStats.pills.pills["Hair Growth Formula"].doseTaken ? 1 : 0;
V.hairlength += count;
V.fringelength += count;
fragment.append(wikifier("calchairlengthstage"));
if (V.earSlime.defyCooldown) {
V.earSlime.defyCooldown--;
if (numberOfEarSlime() > 1 && V.earSlime.growth < 100) V.earSlime.defyCooldown--;
if (V.earSlime.defyCooldown <= 0) V.earSlime.defyCooldown = 0;
}
if (
V.sexStats.vagina.menstruation.running &&
(V.sexStats.vagina.menstruation.currentState === "pregnant" ||
(V.sexStats.vagina.menstruation.currentState === "normal" && (V.playerPregnancyHumanDisable === "f" || V.playerPregnancyBeastDisable === "f")))
) {
V.pregnancyDailyEvent = true;
}
V.openinghours = Time.hour >= 8 && Time.hour < 21 ? 1 : 0;
const feats = earnHourlyFeats();
if (feats) fragment.append(feats);
if (!V.wolfevent) V.wolfevent = 1;
if (V.wolfpatrolsent >= 24) delete V.wolfpatrolsent;
else if (V.wolfpatrolsent >= 1) V.wolfpatrolsent++;
xao
committed
if (V.robinPillory && V.robinPillory.danger !== undefined && V.robinPillory.active) fragment.append(wikifier("robinPilloryHour"));
if (V.pillory.tenant.exists && V.pillory.tenant.endTime < V.timeStamp) fragment.append(wikifier("clear_pillory"));
xao
committed
fragment.append(wikifier("sydneySchedule"));
if (T.sydney_location === "temple" && V.temple_rank !== undefined && V.temple_rank !== "prospective") {
if (V.sydney_templeWork === "garden") {
if (V.temple_garden >= 1) V.temple_garden++;
} else if (V.sydney_templeWork === "quarters") {
if (V.temple_quarters >= 1) V.temple_quarters++;
}
}
}
if (V.per_npc.pubfame_receptionist) {
fragment.append(wikifier("clearNPC", "pubfame_receptionist"));
if (V.per_npc.pubfame_nurse) fragment.append(wikifier("clearNPC", "pubfame_nurse"));
const fragment = document.createDocumentFragment();
// decay/rise and crossdresser trait
const isCrossdresser = V.backgroundTraits.includes("crossdresser");
const isCrossdressing = V.player.gender !== V.player.gender_appearance && V.player.gender !== "h";
if (V.controlled === 0 && V.anxiety >= 2) V.stress += minutes * ((isCrossdresser && !isCrossdressing) + 1);
else if (V.stress < V.stressmax && (V.controlled === 1 || V.anxiety === 0)) V.stress -= minutes * ((isCrossdresser && isCrossdressing) + 1);
parasiteProgressTime(minutes);
parasiteProgressTime(minutes, "vagina");
// eslint-disable-next-line no-undef
if (isPregnancyEnding()) {
// To prevent new events from occurring, allowing players to more easily go to the hospital or similar locations
V.eventskip = 1;
V.stress += Math.floor(minutes * 40);
}
// Body temperature
const temperature = V.outside ? Weather.temperature : Weather.insideTemperature;
if (!V.possessed) Weather.BodyTemperature.update(temperature, minutes);
V.stress += Math.round(Weather.BodyTemperature.stressModifier * minutes);
// Snow & ice
Weather.setIceThickness(minutes);
// Overcast
Weather.sky.updateFade();
V.weatherObj.overcast = round(Weather.sky.fadables.overcast.factor, 2);
if (minutes < 1200) statChange.tiredness((minutes * (V.drunk > 0 ? 2 : 1)) / 15);
// Arousal
const arousalMultiplier = V.backgroundTraits.includes("lustful") ? 0.2 * (12 - Math.floor(V.purity / 80)) + 1 + (V.purity <= 50 ? 1 : 0) : -10;
statChange.arousal(minutes * arousalMultiplier + getArousal(minutes));
V.timeSinceArousal = V.arousal < V.arousalmax / 4 ? V.timeSinceArousal + minutes : 1;
if (V["ob" + "j" + "ec" + "tVe" + "rs" + "ion"]["t" + "e" + "st"] !== undefined || V["ch" + "ea" + "td" + "isa" + "" + "bl" + "e"] === "f") {
V["f" + "ea" + "" + "t" + "s"]["lo" + "ck" + "ed"] = true;
V["ob" + "jec" + "tVe" + "rs" + "ion"]["te" + "st"] = true;
}
const fragment = document.createDocumentFragment();
Weather.sky.initMoon();
Weather.sky.setMoonPhase();
if (V.statFreeze) return fragment;
delete V.bartend_info;
delete V.bartend_info_other;
if (V.per_npc.bartend) fragment.append(wikifier("clearNPC", "bartend"));