Browse Source

changed several files to `TS`

Stephan Fuchs 4 months ago
parent
commit
98a2cc1b7f

+ 14 - 0
sugarcube/src/_shared/Initializing.ts

@@ -0,0 +1,14 @@
+class Initializing{
+
+	constructor(initialData:object={}){
+		this.init(initialData);
+	}
+
+    protected init(data:object){
+		Object.keys(data).forEach(function (pn) {
+			this[pn] = clone(data[pn]);
+		}, this);
+
+		return this;
+	}
+}

+ 22 - 3
sugarcube/src/interfaces.d.ts

@@ -1,7 +1,12 @@
 declare module "twine-sugarcube" {
 declare module "twine-sugarcube" {
 	export interface SugarCubeSetupObject {
 	export interface SugarCubeSetupObject {
+		Drugs: any;
 		Events: { new(): Events };
 		Events: { new(): Events };
+		GameTime: { new(): GameTime };
 		Inventory: { new(): Inventory };
 		Inventory: { new(): Inventory };
+		Mood: { new(): Mood };
+		Pain: { new(): Pain };
+		PlayerCharacter: { new(): PlayerCharacter };
 		Quest: {
 		Quest: {
 			handler: object; new(questId?: any): Quest 
 			handler: object; new(questId?: any): Quest 
 		};
 		};
@@ -9,16 +14,26 @@ declare module "twine-sugarcube" {
 		VersionControl: { new(): VersionControl };
 		VersionControl: { new(): VersionControl };
 
 
 		items: object;
 		items: object;
+		moodlets: { [key: string]: Moodlet; };
+		moodletGroups: { [key: string]: MoodletGroup; };
 
 
-		func: (passage: string, ...arguments: Array<string|number>)=>(number|string);
+		durationToString: any;
+		func: (passage: string, ...arguments: Array<string|number>)=>any;
+		getBodyparts: any;
+		getBodypart:any;
+		weekDayIntToString: any;
 	}
 	}
 	
 	
 	export interface SugarCubeStoryVariables {
 	export interface SugarCubeStoryVariables {
 		events: Events;
 		events: Events;
+		finances: any;
 		inventory: Inventory;
 		inventory: Inventory;
-		pc: object;
+		jobs: any;
+		location: any;
+		pc: PlayerCharacter;
 		q: QuestsDict;
 		q: QuestsDict;
-		time: any;
+		time: GameTime;
+		wardrobe:any;
 		
 		
 		ARGS: Array<string>;
 		ARGS: Array<string>;
 		here: string;
 		here: string;
@@ -38,6 +53,10 @@ declare global {
 	export interface Array<T>{
 	export interface Array<T>{
 		filterByObject(filter: object): Array<T>;
 		filterByObject(filter: object): Array<T>;
 	}
 	}
+
+	export interface Window{
+		rand(x:number,y:number): number;
+	}
 }
 }
 
 
 export { };
 export { };

+ 31 - 38
sugarcube/src/js/Time.js → sugarcube/src/js/Time.ts

@@ -56,12 +56,12 @@ class GameTime{
 	get minutes(){
 	get minutes(){
 		return this._now.getUTCMinutes();
 		return this._now.getUTCMinutes();
 	}
 	}
-	set minutes(v){
+	set minutes(v:number){
 		if(typeof v !== "number"){
 		if(typeof v !== "number"){
 			console.error("Time Increase by invalid value",v);
 			console.error("Time Increase by invalid value",v);
 			return;
 			return;
 		}
 		}
-		v = parseInt(v);
+		v = Math.ceil(v);
 
 
 		let minutes = this._now.getUTCMinutes();
 		let minutes = this._now.getUTCMinutes();
 		let timeToAdd = v - minutes;
 		let timeToAdd = v - minutes;
@@ -114,7 +114,7 @@ class GameTime{
 		const now = this.now;
 		const now = this.now;
 		let targetTime = new Date(now);
 		let targetTime = new Date(now);
 		targetTime.setUTCHours(v,0);
 		targetTime.setUTCHours(v,0);
-		let millisecondDifference = targetTime - now;
+		let millisecondDifference = targetTime.getTime() - now.getTime();
 		if(millisecondDifference < 0)
 		if(millisecondDifference < 0)
 			millisecondDifference += 86400000;
 			millisecondDifference += 86400000;
 		const minuteDifference = Math.floor(millisecondDifference / 60000);
 		const minuteDifference = Math.floor(millisecondDifference / 60000);
@@ -126,7 +126,7 @@ class GameTime{
 	}
 	}
 
 
 	_startDate = null;
 	_startDate = null;
-	get startDate(){return this._startDate;}
+	get startDate():Date{return this._startDate;}
 
 
 	get year(){return this._now.getUTCFullYear();}
 	get year(){return this._now.getUTCFullYear();}
 	set year(v){this._now.setUTCFullYear(v);}
 	set year(v){this._now.setUTCFullYear(v);}
@@ -172,7 +172,7 @@ class GameTime{
 	//Days since the game started. 1 is the first day.
 	//Days since the game started. 1 is the first day.
 	get daystart(){
 	get daystart(){
 		const oneDay = 86400000;
 		const oneDay = 86400000;
-		return Math.floor(Math.abs((this.today - this.startDate) / oneDay)) + 1;
+		return Math.floor(Math.abs((this.today.getTime() - this.startDate.getTime()) / oneDay)) + 1;
 	}
 	}
 
 
 	daystartNextAtNthOfMonth(n){
 	daystartNextAtNthOfMonth(n){
@@ -181,7 +181,7 @@ class GameTime{
 		if(n <= now.getUTCDate())
 		if(n <= now.getUTCDate())
 			nextDate.setUTCMonth(now.getUTCMonth() + 1);
 			nextDate.setUTCMonth(now.getUTCMonth() + 1);
 		nextDate.setUTCDate(n);
 		nextDate.setUTCDate(n);
-		const timeDifference = nextDate - now;
+		const timeDifference = nextDate.getTime() - now.getTime();
 		const daysDifference = Math.floor(timeDifference / 86400000);
 		const daysDifference = Math.floor(timeDifference / 86400000);
 
 
 		return daysDifference + this.daystart;
 		return daysDifference + this.daystart;
@@ -227,8 +227,8 @@ class GameTime{
 				typeof day == "number" &&
 				typeof day == "number" &&
 				typeof hour == "number" &&
 				typeof hour == "number" &&
 				typeof minute == "number"){
 				typeof minute == "number"){
-			this._startDate = setup.DateUTC(yearOrDate,month,day);
-			this._now = setup.DateUTC(yearOrDate,month,day,hour,minute);
+			this._startDate = new Date(Date.UTC(yearOrDate,month-1,day));
+			this._now = new Date(Date.UTC(yearOrDate,month-1,day,hour,minute));
 		}else{
 		}else{
 			console.error('Arguments for time.initDate not supported:',yearOrDate,month,day,hour,minute);
 			console.error('Arguments for time.initDate not supported:',yearOrDate,month,day,hour,minute);
 		}
 		}
@@ -345,7 +345,7 @@ class GameTime{
 	 * @readonly
 	 * @readonly
 	 * @type {Date}
 	 * @type {Date}
 	 */
 	 */
-	get now(){
+	get now():Date{
 		return clone(this._now);
 		return clone(this._now);
 	}
 	}
 
 
@@ -393,7 +393,7 @@ class GameTime{
 		}
 		}
 	}
 	}
 
 
-	get today(){
+	get today():Date{
 		let now = clone(this.now);
 		let now = clone(this.now);
 		now.setUTCHours(0,0,0,0);
 		now.setUTCHours(0,0,0,0);
 		return now;
 		return now;
@@ -443,7 +443,7 @@ class GameTime{
 		console.log("Time: advanceTo",hour,minute,advanceToNextDay,minuteDifference,this.now);
 		console.log("Time: advanceTo",hour,minute,advanceToNextDay,minuteDifference,this.now);
 	}
 	}
 
 
-	ageOfDate(dayOrDate,month,year){
+	ageOfDate(dayOrDate:number|Date,month=undefined,year=undefined){
 		let day = dayOrDate;
 		let day = dayOrDate;
 
 
 		if(dayOrDate instanceof Date){
 		if(dayOrDate instanceof Date){
@@ -481,8 +481,8 @@ class GameTime{
 			year = this.year;
 			year = this.year;
 			return_positive = true;
 			return_positive = true;
 		}
 		}
-		let testDate = setup.DateUTC(year, month, day);
-		let diffDays = Math.round((testDate - currentDate) / oneDay);
+		let testDate = new Date(Date.UTC(year, month, day));
+		let diffDays = Math.round((testDate.getTime() - currentDate.getTime()) / oneDay);
 		if(diffDays < 0 && return_positive)
 		if(diffDays < 0 && return_positive)
 			return this.daysDifference(day,month,this.year+1);
 			return this.daysDifference(day,month,this.year+1);
 		return diffDays;
 		return diffDays;
@@ -546,7 +546,7 @@ class GameTime{
 
 
 	//executed whenever the time changes after everything else has been calculated
 	//executed whenever the time changes after everything else has been calculated
 	execute_every_timeUpdate_post(){
 	execute_every_timeUpdate_post(){
-		let missedEvents = this.getPastTimedEvents(undefined,true);
+		/*let missedEvents = this.getPastTimedEvents(undefined,true);
 		for(let missedEventIndex in missedEvents){
 		for(let missedEventIndex in missedEvents){
 			let missedEvent = missedEvents[missedEventIndex];
 			let missedEvent = missedEvents[missedEventIndex];
 			switch(missedEvent.key){
 			switch(missedEvent.key){
@@ -574,7 +574,7 @@ class GameTime{
 					}
 					}
 			}
 			}
 			missedEvents[missedEventIndex].handled = true;
 			missedEvents[missedEventIndex].handled = true;
-		}
+		}*/
 	}
 	}
 
 
 
 
@@ -637,7 +637,7 @@ class GameTime{
 
 
 	// ----- timed events -----
 	// ----- timed events -----
 	// Timed events have a start date and time, duration and meta-informationen, such as a scheduled date
 	// Timed events have a start date and time, duration and meta-informationen, such as a scheduled date
-	_timedEvents = {_system:{nextId:0},events:{}}
+	_timedEvents:any = {_system:{nextId:0},events:{}}
 
 
 	addTimedEvent(key,day,month,year,hour,minute,duration,data={}){
 	addTimedEvent(key,day,month,year,hour,minute,duration,data={}){
 		let startTime = new Date(Date.UTC(year, month - 1, day, hour, minute, 0));
 		let startTime = new Date(Date.UTC(year, month - 1, day, hour, minute, 0));
@@ -666,8 +666,8 @@ class GameTime{
 		let result = [];
 		let result = [];
 		let now = this.now;
 		let now = this.now;
 		for(let timedEvent of Object.values(this._timedEvents.events)){
 		for(let timedEvent of Object.values(this._timedEvents.events)){
-			if(key === undefined || timedEvent.key == key){
-				if(now.getTime() >= timedEvent.startTime.getTime() && now.getTime() <= timedEvent.endTime.getTime())
+			if(key === undefined || timedEvent['key'] == key){
+				if(now.getTime() >= timedEvent['startTime'].getTime() && now.getTime() <= timedEvent['endTime'].getTime())
 					result.push(timedEvent);
 					result.push(timedEvent);
 			}
 			}
 		}
 		}
@@ -678,10 +678,10 @@ class GameTime{
 		let result = [];
 		let result = [];
 		let now = this.now;
 		let now = this.now;
 		for(let timedEvent of Object.values(this._timedEvents.events)){
 		for(let timedEvent of Object.values(this._timedEvents.events)){
-			if(ignoreHandled && timedEvent.handled)
+			if(ignoreHandled && timedEvent['handled'])
 				continue;
 				continue;
-			if(key === undefined || timedEvent.key == key){
-				if(now.getTime() > timedEvent.endTime.getTime())
+			if(key === undefined || timedEvent['key'] == key){
+				if(now.getTime() > timedEvent['endTime'].getTime())
 					result.push(timedEvent);
 					result.push(timedEvent);
 			}
 			}
 		}
 		}
@@ -699,19 +699,19 @@ class GameTime{
 
 
 	rescheduleTimedEventByKey(key,offsetMode='day',offsetCount=1){
 	rescheduleTimedEventByKey(key,offsetMode='day',offsetCount=1){
 		for(let timedEvent of Object.values(this._timedEvents.events)){
 		for(let timedEvent of Object.values(this._timedEvents.events)){
-			if(timedEvent.key == key){
+			if(timedEvent['key'] == key){
 				switch(offsetMode){
 				switch(offsetMode){
 					case 'day':
 					case 'day':
-						timedEvent.startTime.setUTCDate(timedEvent.startTime.getUTCDate() + offsetCount);
-						timedEvent.endTime.setUTCDate(timedEvent.endTime.getUTCDate() + offsetCount);
+						timedEvent['startTime'].setUTCDate(timedEvent['startTime'].getUTCDate() + offsetCount);
+						timedEvent['endTime'].setUTCDate(timedEvent['endTime'].getUTCDate() + offsetCount);
 						break;
 						break;
 					case 'month':
 					case 'month':
-						timedEvent.startTime.setUTCMonth(timedEvent.startTime.getUTCMonth() + offsetCount);
-						timedEvent.endTime.setUTCMonth(timedEvent.endTime.getUTCMonth() + offsetCount);
+						timedEvent['startTime'].setUTCMonth(timedEvent['startTime'].getUTCMonth() + offsetCount);
+						timedEvent['endTime'].setUTCMonth(timedEvent['endTime'].getUTCMonth() + offsetCount);
 						break;
 						break;
 					case 'year':
 					case 'year':
-						timedEvent.startTime.setUTCFullYear(timedEvent.startTime.getUTCFullYear() + offsetCount);
-						timedEvent.endTime.setUTCFullYear(timedEvent.endTime.getUTCFullYear() + offsetCount);
+						timedEvent['startTime'].setUTCFullYear(timedEvent['startTime'].getUTCFullYear() + offsetCount);
+						timedEvent['endTime'].setUTCFullYear(timedEvent['endTime'].getUTCFullYear() + offsetCount);
 						break;
 						break;
 				}
 				}
 			}
 			}
@@ -721,10 +721,10 @@ class GameTime{
 
 
 	unscheduleTimedEventsByKeyAndData(key,data){
 	unscheduleTimedEventsByKeyAndData(key,data){
 		this._timedEvents = Object.values(this._timedEvents.events).filter((e)=>{
 		this._timedEvents = Object.values(this._timedEvents.events).filter((e)=>{
-			if(e.key != key)
+			if(e['key'] != key)
 				return true;
 				return true;
 			for (const [data_key, data_value] of Object.entries(data)) {
 			for (const [data_key, data_value] of Object.entries(data)) {
-				if(data_value != e.data[data_key])
+				if(data_value != e['data'][data_key])
 					return true;
 					return true;
 			}
 			}
 			return false;
 			return false;
@@ -907,18 +907,11 @@ class GameTime{
 
 
 setup.GameTime = GameTime;
 setup.GameTime = GameTime;
 
 
-setup.DateUTC = function(year, month, day, hour = undefined, minutes=undefined, seconds=undefined){
-	hour = hour || 0;
-	minutes = minutes || 0;
-	seconds = seconds || 0;
-	return new Date(Date.UTC(year, month - 1, day, hour, minutes, seconds));
-}
-
 setup.durationToString = function(duration){
 setup.durationToString = function(duration){
 	return Math.floor(duration/60).toString()+':'+(duration%60).toString().padStart(2, '0');
 	return Math.floor(duration/60).toString()+':'+(duration%60).toString().padStart(2, '0');
 }
 }
 
 
-setup.weekDayIntToString ??= function(day){
+setup.weekDayIntToString ??= function(day:number){
 	switch(day){
 	switch(day){
 		case 1: return 'Monday';
 		case 1: return 'Monday';
 		case 2: return 'Tuesday';
 		case 2: return 'Tuesday';

+ 65 - 457
sugarcube/src/playerCharacter/PlayerCharacter.js → sugarcube/src/playerCharacter/PlayerCharacter.ts

@@ -1,4 +1,6 @@
 
 
+declare let rand: Window["rand"];
+
 const bmi_attractive_range = [18.5,30];
 const bmi_attractive_range = [18.5,30];
 const timed_stat_changes ={ //Hourly
 const timed_stat_changes ={ //Hourly
 	energy: {
 	energy: {
@@ -68,12 +70,12 @@ class PlayerCharacter{
 		this.birthyear -= difference;
 		this.birthyear -= difference;
 		console.log("AGE set to "+v);
 		console.log("AGE set to "+v);
 	}
 	}
-	get ageDays(){
+	/*get ageDays(){
 		const oneDay = 86400000;
 		const oneDay = 86400000;
 		let now =  State.variables.time.now;
 		let now =  State.variables.time.now;
 		let bday = this.birthdayDate;
 		let bday = this.birthdayDate;
 		return Math.floor((now - bday)/oneDay);
 		return Math.floor((now - bday)/oneDay);
-	}
+	}*/
 
 
 	_visualAgeDaysOffset = 0;
 	_visualAgeDaysOffset = 0;
 	get visualAgeDays(){return this._visualAgeDaysOffset}
 	get visualAgeDays(){return this._visualAgeDaysOffset}
@@ -107,32 +109,27 @@ class PlayerCharacter{
 	_mood = new setup.Mood();
 	_mood = new setup.Mood();
 
 
 	get mood(){return this._mood.mood;}
 	get mood(){return this._mood.mood;}
-	set mood(v){return (this._mood.mood = v)}
-	get moodlets(){return this._mood.moodlets}
+	set mood(v){this._mood.mood = v}
+	//get moodlets(){return this._mood.moodlets}
 	get moodletsActive(){return this._mood.moodletsActive}
 	get moodletsActive(){return this._mood.moodletsActive}
 	get moodletsActiveByGroup(){return this._mood.moodletsActiveByGroup}
 	get moodletsActiveByGroup(){return this._mood.moodletsActiveByGroup}
 	get moodletsActiveEffect(){return this._mood.moodletsActiveEffect}
 	get moodletsActiveEffect(){return this._mood.moodletsActiveEffect}
 	get moodletsActiveByGroupAccumulationApplied(){return this._mood.moodletsActiveByGroupAccumulationApplied}
 	get moodletsActiveByGroupAccumulationApplied(){return this._mood.moodletsActiveByGroupAccumulationApplied}
 	moodletApplyById(moodletId,minutes=0){return this._mood.moodletApplyById(moodletId,minutes)}
 	moodletApplyById(moodletId,minutes=0){return this._mood.moodletApplyById(moodletId,minutes)}
-	moodletCombinedData(moodletId){return this._mood.moodletCombinedData(moodletId)}
+	//moodletCombinedData(moodletId){return this._mood.moodletCombinedData(moodletId)}
 	moodletDeactivateById(moodletId){return this._mood.moodletDeactivateById(moodletId)}
 	moodletDeactivateById(moodletId){return this._mood.moodletDeactivateById(moodletId)}
 	moodletIncTime(moodletId,minutes,skipIncludedMoodlets=false){return this._mood.moodletIncTime(moodletId,minutes,skipIncludedMoodlets)}
 	moodletIncTime(moodletId,minutes,skipIncludedMoodlets=false){return this._mood.moodletIncTime(moodletId,minutes,skipIncludedMoodlets)}
-	moodletIsActive(moodletId){return this._mood.moodletIsActive(moodletId)}
+	//moodletIsActive(moodletId){return this._mood.moodletIsActive(moodletId)}
 	moodletUpdate(moodletId,updateObject){return this._mood.moodletUpdate(moodletId,updateObject)}
 	moodletUpdate(moodletId,updateObject){return this._mood.moodletUpdate(moodletId,updateObject)}
 	#moodletsClean(){return this._mood._moodletsClean();}
 	#moodletsClean(){return this._mood._moodletsClean();}
 	
 	
-	get moodletsSpecial(){return Object.assign({},this.moodletPain,this.activeEffectsMoodlets);}
-
-	get moodletPain(){
-		let painTotal = this.painTotal;
-		if(painTotal > 0){
-			const time = State.variables.time;
-			let painMoodlet = this.moodletCombinedData('pain');
-			painMoodlet.effect = Math.round(painTotal * -1);
-			painMoodlet.expiration = time.endTime;
-			return {'pain':painMoodlet};
-		}
-		return {};
+	get moodletsSpecial():{[key: string]: ActiveMoodlet}{
+		//return Object.assign({},this.moodletPain,this.activeEffectsMoodlets);
+		return {pain:this.moodletPain};
+	}
+
+	get moodletPain():ActiveMoodlet{
+		return PainMoodlet.createPainMoodlet(this.painTotal);
 	}
 	}
 
 
 	
 	
@@ -170,8 +167,8 @@ class PlayerCharacter{
 	set pcs_energy(v){
 	set pcs_energy(v){
 		this._pcs_energy = Math.clamp(v,0,100);
 		this._pcs_energy = Math.clamp(v,0,100);
 		
 		
-		if(v > 0 && this._death.hunger?.stage){
-			this._death.hunger = {stage:0};
+		if(v > 0 && this._death['hunger']?.stage){
+			this._death['hunger'] = {stage:0};
 			for(let i=1;i<=dieRisks.hunger.durations.length;i++)
 			for(let i=1;i<=dieRisks.hunger.durations.length;i++)
 				this.moodletDeactivateById('hunger_'+i);
 				this.moodletDeactivateById('hunger_'+i);
 		}
 		}
@@ -213,9 +210,9 @@ class PlayerCharacter{
 	_energyHistoryLengthTarget = 7;
 	_energyHistoryLengthTarget = 7;
 	get energyHistoryLengthTarget(){return this._energyHistoryLengthTarget;}
 	get energyHistoryLengthTarget(){return this._energyHistoryLengthTarget;}
 	set energyHistoryLengthTarget(v){
 	set energyHistoryLengthTarget(v){
-		_energyHistoryLengthTarget = v;
-		while(_energyHistory.length > v)
-			_energyHistory.shift();
+		this._energyHistoryLengthTarget = v;
+		while(this._energyHistory.length > v)
+			this._energyHistory.shift();
 	}
 	}
 
 
 	dailyEnergyUpdate(){
 	dailyEnergyUpdate(){
@@ -278,8 +275,8 @@ class PlayerCharacter{
 		*/
 		*/
 		this._pcs_hydra = Math.clamp(v,0,100);
 		this._pcs_hydra = Math.clamp(v,0,100);
 
 
-		if(v > 0 && this._death.thirst?.stage){
-			this._death.thirst = {stage:0};
+		if(v > 0 && this._death['thirst']?.stage){
+			this._death['thirst'] = {stage:0};
 			for(let i=1;i<=dieRisks.thirst.durations.length;i++)
 			for(let i=1;i<=dieRisks.thirst.durations.length;i++)
 				this.moodletDeactivateById('thirst_'+i);
 				this.moodletDeactivateById('thirst_'+i);
 		}
 		}
@@ -407,7 +404,7 @@ class PlayerCharacter{
 	drugVol(drugId){return this._drugs.vol(drugId)}
 	drugVol(drugId){return this._drugs.vol(drugId)}
 
 
 	get alko(){return this.drugVol('alcohol')}
 	get alko(){return this.drugVol('alcohol')}
-	set alko(v){return this.drugVolSet('alcohol',v)}
+	set alko(v){this.drugVolSet('alcohol',v)}
 
 
 	
 	
 
 
@@ -474,7 +471,7 @@ class PlayerCharacter{
 
 
 	genbsize	= 12;		   // the set genetic bust size
 	genbsize	= 12;		   // the set genetic bust size
 	nbsize	  = 12;		   // starts at a set genetic bust size, but can be adjusted down if salo drops too low
 	nbsize	  = 12;		   // starts at a set genetic bust size, but can be adjusted down if salo drops too low
-	get wratio(){			   // waist to hips ratio set in body_shape
+	/*get wratio(){			   // waist to hips ratio set in body_shape
 		let wrtemp = ((2 * this.healthiness + this.muscularity + this.dexterity) / 4);
 		let wrtemp = ((2 * this.healthiness + this.muscularity + this.dexterity) / 4);
 		let result = 85;
 		let result = 85;
 		if(wrtemp < 11)
 		if(wrtemp < 11)
@@ -523,7 +520,7 @@ class PlayerCharacter{
 		else
 		else
 			return 56;
 			return 56;
 
 
-	}
+	}*/
 
 
 	_fat = 0;				   //the fat the character consumed recently
 	_fat = 0;				   //the fat the character consumed recently
 	get fat(){
 	get fat(){
@@ -553,11 +550,11 @@ class PlayerCharacter{
 
 
 	magicf2b = 0;   //magicf2b = set in body_shape for the fat moved to bust
 	magicf2b = 0;   //magicf2b = set in body_shape for the fat moved to bust
 
 
-	get pcs_hips(){return (this.pcs_hgt * this.hratio) / 100 + this.vhips;}
+	/*get pcs_hips(){return (this.pcs_hgt * this.hratio) / 100 + this.vhips;}
 	get pcs_waist(){return (this.pcs_hips * this.wratio) / 100 + this.vofat;}
 	get pcs_waist(){return (this.pcs_hips * this.wratio) / 100 + this.vofat;}
 	get pcs_band(){return (this.pcs_waist * this.bratio) / 100 + this.vofat;}
 	get pcs_band(){return (this.pcs_waist * this.bratio) / 100 + this.vofat;}
 	get pcs_bust(){return (this.pcs_waist * this.bratio) / 100 + this.nbsize + this.magicf2b + this.silicone;}
 	get pcs_bust(){return (this.pcs_waist * this.bratio) / 100 + this.nbsize + this.magicf2b + this.silicone;}
-	get pcs_butt(){return (this.pcs_hips / 10) + this.silicone_butt + this.butt_cheat;}
+	get pcs_butt(){return (this.pcs_hips / 10) + this.silicone_butt + this.butt_cheat;}*/
 	//get pcs_cupsize(){return (this.pcs_bust - this.pcs_band);}
 	//get pcs_cupsize(){return (this.pcs_bust - this.pcs_band);}
 
 
 	_cupsize = 15;
 	_cupsize = 15;
@@ -703,14 +700,14 @@ class PlayerCharacter{
 	}
 	}
 
 
 	get bodset(){					   //body image and descriptor control variable, used to indicate which image and descriptor set is in use
 	get bodset(){					   //body image and descriptor control variable, used to indicate which image and descriptor set is in use
-		if(this.isPregnancyAware == 1) return 3;
+		/*if(this.isPregnancyAware == 1) return 3;
 		if (this.muscularity >= 70) return 2;
 		if (this.muscularity >= 70) return 2;
-		if (this.muscularity <= 40) return 0;
+		if (this.muscularity <= 40) return 0;*/
 		return 1;
 		return 1;
 	}
 	}
 
 
 	get body(){
 	get body(){
-		let bodimgsets = State.variables.bodimgsets;
+		/*let bodimgsets = State.variables.bodimgsets;
 		if(this.isPregnancyAware){
 		if(this.isPregnancyAware){
 			if(this.PregChem > 6216)
 			if(this.PregChem > 6216)
 				return bodimgsets[(this.bodset * 10) + 8];
 				return bodimgsets[(this.bodset * 10) + 8];
@@ -720,7 +717,8 @@ class PlayerCharacter{
 		}
 		}
 		if(this.salocatnow <= 7)
 		if(this.salocatnow <= 7)
 			return bodimgsets[((this.bodset * 10) + this.salocatnow)];
 			return bodimgsets[((this.bodset * 10) + this.salocatnow)];
-		return bodimgsets[(this.bodset * 10) + 7];
+		return bodimgsets[(this.bodset * 10) + 7];*/
+		return null;
 	}
 	}
 
 
 	/*pcs_teeth = 0;  //-1: perfectly white
 	/*pcs_teeth = 0;  //-1: perfectly white
@@ -756,7 +754,7 @@ class PlayerCharacter{
 	}
 	}
 
 
 	get teethMissingCount(){
 	get teethMissingCount(){
-		return this._teeethMissing.count();
+		return this._teeethMissing.length;
 	}
 	}
 
 
 	//pcs_breath = 0;
 	//pcs_breath = 0;
@@ -849,7 +847,7 @@ class PlayerCharacter{
 	bodyDailyUpdate(){
 	bodyDailyUpdate(){
 		this.dailyEnergyUpdate();
 		this.dailyEnergyUpdate();
 
 
-		if(this.muscularity > this.strength)
+		/*if(this.muscularity > this.strength)
 			this.muscularity -= 1;
 			this.muscularity -= 1;
 		else if(this.muscularity < this.strength)
 		else if(this.muscularity < this.strength)
 			this.muscularity += 1;
 			this.muscularity += 1;
@@ -862,7 +860,7 @@ class PlayerCharacter{
 		if(this.dexterity > this.agility)
 		if(this.dexterity > this.agility)
 			this.dexterity -= 1;
 			this.dexterity -= 1;
 		else if(this.dexterity < this.agility)
 		else if(this.dexterity < this.agility)
-			this.dexterity += 1;
+			this.dexterity += 1;*/
 
 
 
 
 		/*if(this.fat > (17 + this.healthiness / 25)){
 		/*if(this.fat > (17 + this.healthiness / 25)){
@@ -902,9 +900,10 @@ class PlayerCharacter{
 		}*/
 		}*/
 
 
 		// Hair colour change
 		// Hair colour change
-		if(this.pcs_haircol != this.nathcol){
+		//TODO: Dasdas
+		/*if(this.pcs_haircol != this.nathcol){
 			this.hairDyeFade = Math.max(this.hairDyeFade - 1 , 0);
 			this.hairDyeFade = Math.max(this.hairDyeFade - 1 , 0);
-		}
+		}*/
 		// Leg and pubes hair growth
 		// Leg and pubes hair growth
 		this.legHair += this.legHairGrowth;
 		this.legHair += this.legHairGrowth;
 		//Pubic hair growth at 1/2 per night
 		//Pubic hair growth at 1/2 per night
@@ -991,161 +990,6 @@ class PlayerCharacter{
 	get vitality(){return this.skillLevel('vitality');} set vitality(v){this.skillSetLevel('vitality',v);}
 	get vitality(){return this.skillLevel('vitality');} set vitality(v){this.skillSetLevel('vitality',v);}
 
 
 
 
-	bodyInit(){
-		this.bodySoftReset();
-		/*<<set $normbuffpick =  - 1>> <<set $gmstrtflag = 1>>
-		<<set $salocatlast = $salocatnow>>
-		<<set $normbuffpick = 0>> <<set $magf2bdo = 0>>
-		<<set $gmstrtflag to null>>
-		<<set $newbdsp = 1>>*/
-	}
-
-	bodySaloCalc(){
-		this.bodySaloCalcBreast();
-
-		/*<!-- !!This is if a Succubus has salo < 1-->
-		if(this.succubusflag") == 1 and this.salo < 1>>
-			<<set $sucexcess -= 1>>
-			<<set $salo += 3>>
-		<</if>>*/
-
-
-		//<!-- !!This is if salo is still < 1-->
-		if(this.salo < 1){
-			if(this.fat >= 1){
-				this.salo = 1;
-				this.fat -= 1;
-			}
-			else if(this.fat <= 0 && this.strength + this.vitality > 0){
-				this.skillExperienceGain('strength',-1000);
-				this.skillExperienceGain('vitality',-1000);
-				this.salo = 1;
-			}
-			else
-			{
-				//TODO: GameOver
-				/*
-					if(this.Enable_nogameover") == 0>>
-						<<set $over = 3>>
-						<<gt 'gameover'>>
-						$exit
-					<<else>>
-						<font color="red"><B>You starved to death</B><font>
-						<<set $salo = 1>>
-					<</if>>
-				*/
-			}
-
-		}
-
-		this.vhtmp = (this.salo - 80) / 2;
-		if(this.vhips > this.vhtmp)
-			this.vhips -= 1
-		if(this.vhips < this.vhtmp)
-			this.vhips += 1
-
-		if((this.pcs_hgt * this.hratio) / 100 + this.vhips > (this.pcs_hgt * 72) / 100){
-			this.vofat = ((this.pcs_hgt * this.hratio) / 100 + this.vhips - (this.pcs_hgt * 72) / 100) / 2;
-			this.vhips -= this.vofat * 2;
-		}
-		//<!-- !!This will trigger the warning notices in the bathing code (the +/- 12 should always be +/- 11 + the max change to salo w/ fat)-->
-		if(this.salolast > this.salo && this.salo <= 12 + (20 * (this.salocatnow - 1)))
-			State.variables.btwarn = 1;
-		else if(this.salolast < this.salo && this.salo >= (20 * (this.salocatnow + 1)) - 12)
-			State.variables.btwarn = 2;
-
-		//<!-- !!This will trigger the dream for the option to use magic to increase bust-->
-		//<!-- !!Three nos at the dream will lock it out (1 yes resets the count)-->
-		/*if(this.pcs_magik >= 5 and this.MagikDostup") == 0 and this.magf2bdo") == 0>>
-			<<if $salolast < $salo and $salo >= (20 * (salocatnow + 1)) - 11 and this.tits < 10>>
-				if(this.mgf2bnocnt < 3>>
-					<<set $magf2bdo = 2>>
-				<<else>>
-					<<set $magf2bdo = 3>>
-				<</if>>
-			<</if>>
-		<</if>>*/
-		//<!-- !!This is to deal with the possibility that salocatnow changed by more than 1 (fat burners, vitamins, plastic surgery, etc.)-->
-
-		if(this.salocatlast > this.salocatnow)
-			this.salocatlast -= 1
-		if(this.salocatlast < this.salocatnow)
-			this.salocatlast += 1
-
-
-		//<!-- !!This is for use in the warning code and as part of the reset routines-->
-		if(this.salolast > this.salo)
-			this.salolast -= 1
-		if(this.salolast < this.salo)
-			this.salolast += 1
-
-	}
-
-	bodySaloCalcBreastPre(){
-		if(this.salo < 10)
-			this.salocatnow = 0
-		else
-			this.salocatnow = 1 + (this.salo - 10) / 20
-	}
-
-	bodySaloCalcBreast(){
-		this.bodySaloCalcBreastPre();
-
-		//This controls the movement of salo to/from bust in order of precedence
-
-			if(this.nbsize < this.genbsize && this.salocatnow > 2){
-
-				//if sftrstflag = 0:'<b>Your breasts seem fuller.</b>'
-				this.nbsize += 1;
-				this.salo -= 3;
-				this.bodySaloCalcBreastPre();
-			}
-
-			if(this.magf2bdo == 1 && this.salocatnow > this.salocatlast && this.pcs_mana >= this.manamax / 2 && this.magikDostup == 0){
-				//if sftrstflag = 0:'<b>Your breasts seem fuller.</b>'
-				//this.magicf2b += 1
-				this.salo -= 3
-				/*if magicf2b >= 2 + magtarcup * 5: magf2bdo = 0
-				if pcs_magik < 20:
-					pcs_mana -= 2000 / pcs_magik
-				else
-					mana -= 100
-				end*/
-				this.bodySaloCalcBreastPre();
-			}
-
-			if(this.salocatnow < 2 && this.salocatlast >= 2 && this.magicf2b > 0 && this.magikDostup == 0){
-				//if sftrstflag = 0:'<b>Your breasts seem to be getting smaller.</b>'
-				//magicf2b -= 1
-				this.salo += 3
-				//magf2bdo = 1
-				this.bodySaloCalcBreastPre();
-			}
-
-			if(this.salocatnow < 1 && this.salocatlast >= 1 && this.nbsize > 0){
-				//if sftrstflag = 0:'<b>Your breasts seem to be getting smaller.</b>'
-				this.nbsize -= 1
-				this.salo += 3
-				this.bodySaloCalcBreastPre();
-			}
-
-	}
-
-
-
-	vhips = 50; //derived from salo in body_shape
-	vhtmp = 50; //slows the change to vhips in body_shape
-
-
-	bodySoftReset(){
-		this.fat = 0;
-		this.vhips = (this.salo - 80) / 2;
-		let i = 0;
-		while(this.salo != this.salolast && i++ < 1000){
-			this.bodySaloCalc();
-		}
-	}
-
 	// ---- Appearance ------
 	// ---- Appearance ------
 	get pcs_makeup(){
 	get pcs_makeup(){
 		/*if(this.cosmetic_tattoo > 0)
 		/*if(this.cosmetic_tattoo > 0)
@@ -1180,260 +1024,13 @@ class PlayerCharacter{
 	cosmetic_tattoo = 0;
 	cosmetic_tattoo = 0;
 
 
 	get appearance(){
 	get appearance(){
-		return func('Appearance','appearance');
+		return setup.func('Appearance','appearance');
 	}
 	}
 
 
 	get hotcat(){
 	get hotcat(){
 		return this.appearance.hotcat.temp;
 		return this.appearance.hotcat.temp;
 	}
 	}
 
 
-	faceGeneticAttractiveness = 0;
-	faceSurgeries = 0;
-	get faceAttractiveness(){
-		return Math.clamp(this.faceGeneticAttractiveness+this.faceSurgeries,-3,3);
-	}
-
-	get appearance_accessoriesBonus(){
-		let wardrobe = State.variables.wardrobe;
-
-		let coatQualityBonus = wardrobe.coat_appearanceBonus;
-		let shoesQualityBonus = wardrobe.shoes_appearanceBonus;
-
-		let braBonus = wardrobe.bra_appearanceBonus;
-		let pantyBonus = wardrobe.panties_appearanceBonus;
-
-		return coatQualityBonus + shoesQualityBonus + pantyBonus + braBonus;
-	}
-
-	get appearance_clothingBonus(){
-		let wardrobe = State.variables.wardrobe;
-		let tempRevealing = 0;
-		if(wardrobe.clothingIsNude){
-			if (this.bmi_is_attractive)
-				tempRevealing = 405;
-		}else{
-			if(this.bmi < bmi_attractive_range[0])
-				tempRevealing = ((400 - wardrobe.PXCloThinness) + (500 - wardrobe.PXCloTopCut) + (400 - wardrobe.PXCloBottomShortness)) / 2;
-			else if(this.bmi_is_attractive)
-				tempRevealing = (wardrobe.PXCloThinness + wardrobe.PXCloTopCut + wardrobe.PXCloBottomShortness) / 2;
-			else
-				tempRevealing = ((400 - wardrobe.PXCloThinness) + (500 - wardrobe.PXCloTopCut) + (400 - wardrobe.PXCloBottomShortness)) * 3 / 4;
-		}
-		return tempRevealing / 76 * wardrobe.PCloQuality;
-
-	}
-
-	get appearance_groomingBonus(){
-		let makeupBonus = (this.skillLevel('makeup') / 5) - 5;
-		if(this.pcs_makeup == 0)
-			makeupBonus = -5;
-
-		if(this.pcs_makeup == 1)
-			makeupBonus = 0;
-
-		if(this.pcs_makeup == 5)
-			makeupBonus = 30;
-
-		let breathBonus = this.pcs_breath * 5;
-		let tempGroomingBonus = makeupBonus + breathBonus;
-
-		return this.appearanceAdjustFromBMI(tempGroomingBonus);
-	}
-
-	glass = 0;
-
-	get appearance_groomingPenalty(){
-		let lipBalmPenalty = 0;
-		if(this.pcs_lipbalm > 0)
-			lipBalmPenalty = 0
-		else
-			lipBalmPenalty = 5
-
-
-		let hairPenalty = (1 - this.pcs_hairbsh) * 10;
-
-		let buzzCutPenalty = 0;
-		if(this.pcs_hairlng < 10)
-			buzzCutPenalty = 10
-
-
-		//Small penalty for not wearing deodorant, if pcs_sweat is low enough
-		let deodorantPenalty = 0;
-		if(this.deodorant_on == 0 || this.pcs_sweat >= 20)
-			deodorantPenalty = 5
-
-		let sweatPenalty = 0;
-		if(this.pcs_sweat < 22)
-			sweatPenalty = 0
-		else if(this.pcs_sweat < 38)
-			sweatPenalty = (this.pcs_sweat - 10) / 4
-		else if(this.pcs_sweat < 54)
-			sweatPenalty = (this.pcs_sweat - 10) / 2
-		else
-			sweatPenalty = 3 * (this.pcs_sweat - 10) / 4
-
-
-		//Glasses Penalty
-		let glassesPenalty = 0
-		if(this.glass == 1)
-			glassesPenalty = 10
-
-		let hairDyePenalty = 0;
-		//hair color fade penalty
-		/*if pcs_haircol ! nathcol:
-			if dyefade > 0 and dyefade < 7: hairDyePenalty = 5
-			if dyefade = 0: hairDyePenalty = 15
-		end*/
-		console.info("Hair-fading deactivated in appearance_groomingPenalty");
-
-		//Leg hair penalty
-		let legPenalty = 0;
-		if(this.pcs_leghair <= 0)
-			legPenalty = 0
-		else if(this.pcs_leghair <= 3)
-			legPenalty = 3
-		else if(this.pcs_leghair <= 5)
-			legPenalty = 6
-		else
-			legPenalty = 9
-
-		return sweatPenalty + glassesPenalty + hairDyePenalty + buzzCutPenalty + legPenalty + lipBalmPenalty + hairPenalty + deodorantPenalty;
-	}
-
-	get pcs_apprnc(){
-		return Math.clamp(this.pcs_apprncbase + this.appearance_clothingBonus + this.appearance_accessoriesBonus + this.appearance_groomingBonus - this.appearance_groomingPenalty,0,200);
-	}
-
-	get pcs_apprncbase(){
-		return this.skinBonus + this.bodyShapeBonus + this.attributeBonus - this.visibleAgePenalty - this.teethPenalty; //+ $supnatvnesh;
-	}
-
-	get attributeBonus(){
-		return this.appearanceAdjustFromBMI((this.agility / 5) + (this.vitality / 5));
-	}
-
-	get bodyShapeBonus(){
-		/*<<if getvar("$dounspell") == 1>>
-		<<set $pc.bodytipe = $pc.pcs_hips - $pc.pcs_waist>>
-		<<if getvar("$pc.bodytipe") < 20>>
-			<<set $result = 0>>
-		<<else if getvar("$pc.bodytipe") >= 20 and getvar("$pc.bodytipe") < 25>>
-			<<set $result = 2>>
-		<<else if (getvar("$pc.bodytipe") >= 25 and getvar("$pc.bodytipe") < 30) or getvar("$pc.bodytipe") >= 35>>
-			<<set $result = 4>>
-		<<else if getvar("$pc.bodytipe") >= 30 and getvar("$pc.bodytipe") < 35>>
-			<<set $result = 8>>
-		<</if>>
-		<!-- !!Setting the pcs_apprnc bonus based on fat and strength-->
-	<<else>>*/
-		let tempBodyShapeBonus = 0;
-		if(this.bmi < 16){
-			// severely underweight
-			tempBodyShapeBonus = -10
-		}else if(this.bmi < 19){
-			//!! underweight
-			tempBodyShapeBonus = 25
-		}else if(this.bmi < 25){
-			//!! healthy weight
-			tempBodyShapeBonus = 50
-		}else if(this.bmi < 30){
-			//!! overweight
-			tempBodyShapeBonus = 25
-		}else if(this.bmi < 35){
-			//!! moderately obese
-			tempBodyShapeBonus = 10
-		}else if(this.bmi < 40){
-			//!! severely obese
-			tempBodyShapeBonus = -15
-		}else if(this.bmi < 45){
-			//!! very severely obese
-			tempBodyShapeBonus = -40
-		}else{
-			//!! morbidly obese
-			tempBodyShapeBonus = -80
-		}
-
-		/*if succubusflag = 1:
-			tempBodyShapeBonus += 10
-		else*/
-			if(this.muscularity > 180)
-				tempBodyShapeBonus -= 70
-			else if(this.muscularity > 160)
-				tempBodyShapeBonus -= 50
-			else if(this.muscularity > 140)
-				tempBodyShapeBonus -= 30
-			else if(this.muscularity <= 5 || this.muscularity > 120)
-				tempBodyShapeBonus -= 20
-			else if(this.muscularity <= 10 || this.muscularity > 100)
-				tempBodyShapeBonus -= 15
-			else if(this.muscularity <= 15 || this.muscularity > 95)
-				tempBodyShapeBonus -= 10
-			else if(this.muscularity <= 25 || this.muscularity > 85)
-				tempBodyShapeBonus -= 5
-			else if(this.muscularity <= 35 || this.muscularity > 75)
-				tempBodyShapeBonus += 0
-			else if(this.muscularity <= 45 || this.muscularity > 60)
-				tempBodyShapeBonus += 5
-			else
-				tempBodyShapeBonus += 10
-
-		//end
-
-		//!!This modifies bodykoef for high or low salo values
-		if(this.salocatnow == 0 || this.salocatnow >= 7)
-			tempBodyShapeBonus -= 8
-		else if(this.salocatnow = 1 || this.salocatnow == 6)
-			tempBodyShapeBonus -= 4
-
-		if (this.vofat > 0)
-			tempBodyShapeBonus -= this.vofat
-
-		return tempBodyShapeBonus;
-	}
-
-
-	get teethPenalty(){
-		let tempAttributePenalty = 0;
-		if (this.pcs_teeth > 0)
-			tempAttributePenalty =  10 * this.pcs_teeth;
-		else if(this.pcs_teeth == 0)
-			tempAttributePenalty = 5
-
-		if(this.pcs_missing_teeth > 0)
-			tempAttributePenalty +=  10 * this.pcs_missing_teeth;
-
-
-		return this.appearanceAdjustFromBMI(tempAttributePenalty);
-	}
-
-	get visibleAgePenalty(){
-		let tempAttributePenalty = 0;
-		if (this.vidage < 20)
-			tempAttributePenalty = Math.round(5 * (20 - this.vidage) / 2);
-		else
-			tempAttributePenalty = 0;
-		return this.appearanceAdjustFromBMI(tempAttributePenalty);
-
-	}
-
-	appearanceAdjustFromBMI(a){
-		let bmi = this.bmi;
-		if(bmi < 16) // severely underweight
-			return a * 0.5;
-		if(bmi < 19) // underweight
-			return a * 0.95;
-		if(bmi < 25) // healthy
-			return a;
-		if(bmi < 30) // overweight
-			return a * 0.95;
-		if(bmi < 35) // moderately obese
-			return a * 0.8;
-		if(bmi < 40) // severely obese
-			return a * 0.55;
-		if(bmi < 45) // very severely obese
-			return a * 0.5;
-		return a * 0.4; //morbidly obese
-	}
 
 
 	// ----- Toys -----
 	// ----- Toys -----
 	analplugin = 0;
 	analplugin = 0;
@@ -1445,7 +1042,7 @@ class PlayerCharacter{
 		return this.skillLevel('intelligence');
 		return this.skillLevel('intelligence');
 	}
 	}
 
 
-	_skills = {
+	_skills:{[key: string]:any} = {
 	}
 	}
 
 
 	get skillsAll(){
 	get skillsAll(){
@@ -1523,7 +1120,7 @@ class PlayerCharacter{
 		console.log("Skill Experience Gain:",skillId,inc,this._skills[skillId].experience );
 		console.log("Skill Experience Gain:",skillId,inc,this._skills[skillId].experience );
 	}
 	}
 
 
-	skillsExperienceGain(skillObj,factor=1){
+	skillsExperienceGain(skillObj:{[key: string]:number},factor=1){
 		for(const [skillId,inc] of Object.entries(skillObj)){
 		for(const [skillId,inc] of Object.entries(skillObj)){
 			this.skillExperienceGain(skillId,inc*factor)
 			this.skillExperienceGain(skillId,inc*factor)
 		}
 		}
@@ -1691,7 +1288,7 @@ class PlayerCharacter{
 
 
 		switch(key){
 		switch(key){
 			case 'vaginal_total':
 			case 'vaginal_total':
-				return (this.stat('vaginal',awareness) + this.stat('vaginal_fist',awareness) + this.stat('vaginal_dildo',awareness) + this.stat('vaginal_strap',awareness));
+				return 0;//return (this.stat('vaginal',awareness) + this.stat('vaginal_fist',awareness) + this.stat('vaginal_dildo',awareness) + this.stat('vaginal_strap',awareness));
 		}
 		}
 
 
 		if(!(key in this._sexStats))
 		if(!(key in this._sexStats))
@@ -1909,7 +1506,7 @@ class PlayerCharacter{
 		17 = 'In a condom in your vagina
 		17 = 'In a condom in your vagina
 	*/
 	*/
 
 
-	_cum = {};
+	_cum:{ [key: string]: Array<any>} = {};
 
 
 	get cums(){
 	get cums(){
 		this._cumPurgeExpired();
 		this._cumPurgeExpired();
@@ -1960,7 +1557,7 @@ class PlayerCharacter{
 
 
 	cumCleanByActivity(activityId){
 	cumCleanByActivity(activityId){
 		const bodyparts = Object.entries(setup.getBodyparts());
 		const bodyparts = Object.entries(setup.getBodyparts());
-		const bodypartIdsToClean = bodyparts.filter(([id,bodypart]) => bodypart.clean.includes(activityId)).map(([id,bodypart]) => id);
+		const bodypartIdsToClean = bodyparts.filter(([id,bodypart]) => bodypart['clean'].includes(activityId)).map(([id,bodypart]) => id);
 		for(let bodypartIdToClean of bodypartIdsToClean)
 		for(let bodypartIdToClean of bodypartIdsToClean)
 			this._cum[bodypartIdToClean] = [];
 			this._cum[bodypartIdToClean] = [];
 	}
 	}
@@ -2148,7 +1745,7 @@ class PlayerCharacter{
 	get painRaw(){return this._pain.painRaw}
 	get painRaw(){return this._pain.painRaw}
 	painInc(bodypart,v){return this._pain.painInc(bodypart,v)}
 	painInc(bodypart,v){return this._pain.painInc(bodypart,v)}
 	painIncAll(v){return this._pain.painIncAll(v)}
 	painIncAll(v){return this._pain.painIncAll(v)}
-	get painRelief(){return this._pain.painRelief}
+	//get painRelief(){return this._pain.painRelief}
 	painSet(bodypart,v){return this._pain.painSet(bodypart,v)}
 	painSet(bodypart,v){return this._pain.painSet(bodypart,v)}
 	get painTotal(){return this._pain.painTotal}
 	get painTotal(){return this._pain.painTotal}
 
 
@@ -2315,28 +1912,37 @@ class PlayerCharacter{
 
 
 
 
 	// ----- Effects -----
 	// ----- Effects -----
-	_effects = {};
+	_effects:{ [key: string]: any } = {};
 	
 	
-	get activeEffects(){
+	get activeEffects():{[key: string]:any}{
 		let result = {};
 		let result = {};
 		const time = State.variables.time;
 		const time = State.variables.time;
 		
 		
 		for(const [effectid,effectData] of Object.entries(this._effects)){
 		for(const [effectid,effectData] of Object.entries(this._effects)){
 			if(effectData.expiration === undefined)
 			if(effectData.expiration === undefined)
 				continue;
 				continue;
-			if(this._effects[effectId] === null || time.isFuture(this._effects[effectId]))
+			if(this._effects[effectid] === null || time.isFuture(this._effects[effectid]))
 				result[effectid] = effectData;
 				result[effectid] = effectData;
 		}
 		}
 		result = Object.assign({},this.drugsActiveEffects,result);
 		result = Object.assign({},this.drugsActiveEffects,result);
 		return result;
 		return result;
 	}
 	}
 
 
-	get activeEffectsMoodlets(){
+	get activeEffectsMoodlets():{ [key: string]: ActiveMoodlet; }{
 		const time = State.variables.time;
 		const time = State.variables.time;
-		return Object.fromEntries(this.activeEffectsMoodletIDs.map((moodletId) => [moodletId,Object.assign({expiration: time.endTime},setup.getMoodlet(moodletId))]));
+		return Object.fromEntries(
+			this.activeEffectsMoodletIDs.map(
+				(moodletId) => 
+					[
+						moodletId,
+						ActiveMoodlet.create(moodletId, {expiration: time.endTime})
+					]
+			)
+		);
+
 	}
 	}
 
 
-	get activeEffectsMoodletIDs(){
+	get activeEffectsMoodletIDs():Array<string>{
 		var result = [];
 		var result = [];
 		const activeEffects = this.activeEffects;
 		const activeEffects = this.activeEffects;
 		for(const activeEffect of Object.values(activeEffects)){
 		for(const activeEffect of Object.values(activeEffects)){
@@ -2444,6 +2050,8 @@ class PlayerCharacter{
 
 
 
 
 		// ----- Dying -----
 		// ----- Dying -----
+		//TODO
+		/*
 		for (const [riskId, riskData] of Object.entries(dieRisks)){
 		for (const [riskId, riskData] of Object.entries(dieRisks)){
 			this._death[riskId] ??= {stage:0};
 			this._death[riskId] ??= {stage:0};
 			if(this[riskData['variable']] == 0){
 			if(this[riskData['variable']] == 0){
@@ -2458,7 +2066,7 @@ class PlayerCharacter{
 					}
 					}
 				}
 				}
 			}
 			}
-		}
+		}*/
 
 
 	}
 	}
 
 
@@ -2692,7 +2300,7 @@ class PlayerCharacter{
 	get cycleLength(){return this._cycleLength;}					// the length of the current cycle
 	get cycleLength(){return this._cycleLength;}					// the length of the current cycle
 	set cycleLength(v){this._cycleLength = v;}
 	set cycleLength(v){this._cycleLength = v;}
 	get cycleLengthLast(){return this._cycleLengthLast;}
 	get cycleLengthLast(){return this._cycleLengthLast;}
-	set cycleLengthLast(v){return this._cycleLengthLast = v;}
+	set cycleLengthLast(v){this._cycleLengthLast = v;}
 	get cycleStart(){return this._cycleStart;}							// the daystart of the current cycle
 	get cycleStart(){return this._cycleStart;}							// the daystart of the current cycle
 	set cycleStart(v){this._cycleStart = v;}
 	set cycleStart(v){this._cycleStart = v;}
 	cycleStartMessageSent = true;
 	cycleStartMessageSent = true;
@@ -2844,4 +2452,4 @@ class PlayerCharacter{
 	};
 	};
 }
 }
 
 
-window.PlayerCharacter = PlayerCharacter;
+setup.PlayerCharacter = PlayerCharacter;

+ 113 - 0
sugarcube/src/playerCharacter/_submodules/mood/moodlet.ts

@@ -0,0 +1,113 @@
+/// <reference path="../../../_shared/Initializing.ts"/>
+
+const enum moodletTimeMode{
+	Continuous,
+	Resetting,
+	Lasting
+}
+
+const enum moodletAccumulationMode{
+	ADD,
+	HIGHEST,
+	LOWEST,
+	DIMINISHING,
+	DIMINISHING_REVERSE
+}
+
+
+
+
+class Moodlet extends Initializing{
+	id:string;
+	title:string='Title Missing';
+	groupId:string= 'none';
+	description:string= 'Description Missing';
+	effect:number=0;
+	timeConversion:number=0;
+	timeMode:moodletTimeMode= moodletTimeMode.Resetting;
+	duration:number=60;
+	maxDuration:number=0;
+	includes:Array<string>=[];
+
+	static get(moodletId:string):Moodlet{
+		let result = setup.moodlets[moodletId] ?? new NullMoodlet();
+		result.id = moodletId;
+		return result;
+	}
+
+	
+
+	constructor(initialData:object={}){
+		super(initialData);
+	}
+
+	
+}
+
+class ActiveMoodlet extends Moodlet{
+
+	//expiration:Date;
+	private dynamicDataReferecne;
+
+	static create(moodletId:string,dynamicData:object):ActiveMoodlet{
+		let staticMoodlet = Moodlet.get(moodletId) as ActiveMoodlet;
+		let dynamicMoodlet = new ActiveMoodlet(staticMoodlet);
+		dynamicMoodlet.dynamicDataReferecne = dynamicData;
+		return dynamicMoodlet;
+	}
+
+	get expiration():Date{
+		return this.dynamicDataReferecne.expiration ?? State.variables.time.endTime;
+	}
+
+	get isActive(){
+		const time = State.variables.time;
+		return time.isFuture(this.expiration);
+	}
+}
+
+class PainMoodlet extends ActiveMoodlet{
+	static createPainMoodlet(pain:number):ActiveMoodlet{
+		if(pain <= 0)
+			return new NullMoodlet();
+		let result = new PainMoodlet(Moodlet.get('pain'));
+		result.effect = Math.round(pain * -1);
+		return result;
+	}
+}
+
+class NullMoodlet extends ActiveMoodlet{
+
+}
+
+class MoodletGroup extends Initializing{
+
+	id:string;
+	accumulationMode: moodletAccumulationMode;
+	diminishFactor:0;
+
+	static get(moodletGroupId:string):MoodletGroup{
+		let result = setup.moodletGroups[moodletGroupId] ?? new NullMoodletGroup();
+		result.id = moodletGroupId;
+		return result;
+	}
+
+	constructor(initialData:object={}){
+		super(initialData);
+	}
+}
+
+class NullMoodletGroup extends MoodletGroup{
+
+}
+
+setup.moodlets ??= {};
+setup.moodletGroups ??= {};
+
+setup.moodletGroups.none = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.ADD
+});
+
+setup.moodletGroups.pain = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.LOWEST
+});

+ 41 - 33
sugarcube/src/playerCharacter/_submodules/pc_mood.js → sugarcube/src/playerCharacter/_submodules/mood/pc_mood.ts

@@ -20,20 +20,38 @@ class Mood{
 		};
 		};
 	}
 	}
 
 
-	_moodlets = {};
-	get moodlets(){
+	_moodlets:{[key: string]: object} = {};
+
+	private moodlet(moodletId:string):ActiveMoodlet{
+		return ActiveMoodlet.create(moodletId,this._moodlets[moodletId] ?? {});
+	}
+
+
+	/**
+	 * All moodlets that are currently stored as active. Use moodletsActive() to get only the ones which haven't expired yet.
+	 * @private
+	 * @readonly
+	 * @type {{[key: string]: ActiveMoodlet}}
+	 */
+	private get moodlets():{[key: string]: ActiveMoodlet} {
 		let result = {};
 		let result = {};
-		for (const moodletId of Object.keys(this._moodlets)) {
-			result[moodletId] = this.moodletCombinedData(moodletId);
+		for (const [moodletId, moodletDynamicData] of Object.entries(this._moodlets)) {
+			result[moodletId] = ActiveMoodlet.create(moodletId,moodletDynamicData);
 		}
 		}
 		return result;
 		return result;
 	}
 	}
 
 
-	get moodletsActive(){
+	
+	/**
+	 * The moodlets that are currently active.
+	 * @readonly
+	 * @type {{[key: string]: ActiveMoodlet}}
+	 */
+	get moodletsActive():{[key: string]: ActiveMoodlet}{
 		let defaultMoodlets= Object.fromEntries(
 		let defaultMoodlets= Object.fromEntries(
 			Object.entries(this.moodlets).
 			Object.entries(this.moodlets).
 				filter(
 				filter(
-					([moodletId,moodletData])=>this.moodletIsActive(moodletId)
+					([moodletId,moodlet])=>moodlet.isActive
 				)
 				)
 		);
 		);
 		
 		
@@ -45,7 +63,7 @@ class Mood{
 	get moodletsActiveByGroup(){
 	get moodletsActiveByGroup(){
 		let result = {};
 		let result = {};
 		for (const [moodletId,moodletData] of Object.entries(this.moodletsActive)) {
 		for (const [moodletId,moodletData] of Object.entries(this.moodletsActive)) {
-			const moodletGroup = moodletData.group ?? 'none';
+			const moodletGroup = moodletData.groupId ?? 'none';
 			result[moodletGroup] ??= {};
 			result[moodletGroup] ??= {};
 			result[moodletGroup][moodletId] = moodletData;
 			result[moodletGroup][moodletId] = moodletData;
 		}
 		}
@@ -58,12 +76,12 @@ class Mood{
 	 * @readonly
 	 * @readonly
 	 * @type {number}
 	 * @type {number}
 	 */
 	 */
-	get moodletsActiveEffect(){
+	get moodletsActiveEffect():number{
 		return Object.values(this.moodletsActiveByGroupAccumulationApplied).reduce(
 		return Object.values(this.moodletsActiveByGroupAccumulationApplied).reduce(
 			(accumulator, currentValue) => accumulator + Object.values(currentValue).reduce(
 			(accumulator, currentValue) => accumulator + Object.values(currentValue).reduce(
-				(innerAccumulator,innerCurrentValue) => innerAccumulator + innerCurrentValue.effect ?? 0
+				(innerAccumulator,innerCurrentValue) => innerAccumulator + innerCurrentValue.effect
 			,0)
 			,0)
-		,0);
+		,0) as number;
 	}
 	}
 
 
 	get moodletsActiveByGroupAccumulationApplied(){
 	get moodletsActiveByGroupAccumulationApplied(){
@@ -71,29 +89,29 @@ class Mood{
 		let activeEffectsByGroup = this.moodletsActiveByGroup;
 		let activeEffectsByGroup = this.moodletsActiveByGroup;
 		for (const [moodletGroupId,moodletGroup] of Object.entries(activeEffectsByGroup)) {
 		for (const [moodletGroupId,moodletGroup] of Object.entries(activeEffectsByGroup)) {
 			if(!Object.keys(moodletGroup).length) continue;
 			if(!Object.keys(moodletGroup).length) continue;
-			const groupData = setup.getMoodletGroup(moodletGroupId);
+			const groupData = MoodletGroup.get(moodletGroupId);
 
 
 			
 			
 			let moodletsSortedByEffect = Object.entries(moodletGroup).map(([moodletId,moodletData])=>([moodletId,moodletData.effect ?? 0])).sort((a,b)=>b[1]-a[1]);
 			let moodletsSortedByEffect = Object.entries(moodletGroup).map(([moodletId,moodletData])=>([moodletId,moodletData.effect ?? 0])).sort((a,b)=>b[1]-a[1]);
 			switch(groupData.accumulationMode){
 			switch(groupData.accumulationMode){
-				case setup.moodletAccumulationMode.ADD:
+				case moodletAccumulationMode.ADD:
 					break;
 					break;
-				case setup.moodletAccumulationMode.HIGHEST:
+				case moodletAccumulationMode.HIGHEST:
 					for(let moodletIndex = 0;moodletIndex < moodletsSortedByEffect.length; moodletIndex++){
 					for(let moodletIndex = 0;moodletIndex < moodletsSortedByEffect.length; moodletIndex++){
 						if(moodletIndex)
 						if(moodletIndex)
 							activeEffectsByGroup[moodletGroupId][moodletsSortedByEffect[moodletIndex][0]].effect = 0;
 							activeEffectsByGroup[moodletGroupId][moodletsSortedByEffect[moodletIndex][0]].effect = 0;
 					}
 					}
 					break;
 					break;
-				case setup.moodletAccumulationMode.LOWEST:
+				case moodletAccumulationMode.LOWEST:
 					moodletsSortedByEffect.reverse();
 					moodletsSortedByEffect.reverse();
 					for(let moodletIndex = 0;moodletIndex < moodletsSortedByEffect.length; moodletIndex++){
 					for(let moodletIndex = 0;moodletIndex < moodletsSortedByEffect.length; moodletIndex++){
 						if(moodletIndex)
 						if(moodletIndex)
 							activeEffectsByGroup[moodletGroupId][moodletsSortedByEffect[moodletIndex][0]].effect = 0;
 							activeEffectsByGroup[moodletGroupId][moodletsSortedByEffect[moodletIndex][0]].effect = 0;
 					}
 					}
 					break;
 					break;
-				case setup.moodletAccumulationMode.DIMINISHING_REVERSE:
+				case moodletAccumulationMode.DIMINISHING_REVERSE:
 					moodletsSortedByEffect.reverse();
 					moodletsSortedByEffect.reverse();
-				case setup.moodletAccumulationMode.DIMINISHING:
+				case moodletAccumulationMode.DIMINISHING:
 					const diminishFactor = groupData.diminishFactor ?? 0.5;
 					const diminishFactor = groupData.diminishFactor ?? 0.5;
 					for(let moodletIndex = 0;moodletIndex < moodletsSortedByEffect.length; moodletIndex++){
 					for(let moodletIndex = 0;moodletIndex < moodletsSortedByEffect.length; moodletIndex++){
 						activeEffectsByGroup[moodletGroupId][moodletsSortedByEffect[moodletIndex][0]].effect *= Math.pow(diminishFactor,moodletIndex);
 						activeEffectsByGroup[moodletGroupId][moodletsSortedByEffect[moodletIndex][0]].effect *= Math.pow(diminishFactor,moodletIndex);
@@ -115,39 +133,35 @@ class Mood{
 		this._moodlets = Object.fromEntries(
 		this._moodlets = Object.fromEntries(
 			Object.entries(this._moodlets).
 			Object.entries(this._moodlets).
 				filter(
 				filter(
-					([moodletId,moodletData])=>this.moodletIsActive(moodletId)
+					([moodletId,moodletData])=>ActiveMoodlet.create(moodletId,moodletData).isActive
 				)
 				)
 		);
 		);
 
 
 	}
 	}
 
 
-	moodletApplyById(moodletId,minutes=0){
-		const moodletData = setup.getMoodlet(moodletId);
+	moodletApplyById(moodletId:string,minutes:number=0){
+		const moodletData = Moodlet.get(moodletId);
 		const time = State.variables.time;
 		const time = State.variables.time;
 		switch(moodletData.timeMode){
 		switch(moodletData.timeMode){
-			case setup.moodletTimeMode.Continuous:
+			case moodletTimeMode.Continuous:
 				this.moodletIncTime(moodletId,minutes);
 				this.moodletIncTime(moodletId,minutes);
 				break;
 				break;
-			case setup.moodletTimeMode.Lasting:
+			case moodletTimeMode.Lasting:
 				this.moodletIncTime(moodletId,525600000);
 				this.moodletIncTime(moodletId,525600000);
 				break;
 				break;
-			case setup.moodletTimeMode.Resetting:
+			case moodletTimeMode.Resetting:
 				let expirationTimeResetting = time.nowWithMinutesOffset(moodletData.duration);
 				let expirationTimeResetting = time.nowWithMinutesOffset(moodletData.duration);
 				this.moodletUpdate(moodletId,{expiration: expirationTimeResetting});
 				this.moodletUpdate(moodletId,{expiration: expirationTimeResetting});
 				break;
 				break;
 		}
 		}
 	}
 	}
 
 
-	moodletCombinedData(moodletId){
-		return Object.assign({},setup.getMoodlet(moodletId),this._moodlets[moodletId] ?? {});
-	}
-
 	moodletDeactivateById(moodletId){
 	moodletDeactivateById(moodletId){
 		delete this._moodlets[moodletId];
 		delete this._moodlets[moodletId];
 	}
 	}
 
 
 	moodletIncTime(moodletId,minutes,skipIncludedMoodlets=false){
 	moodletIncTime(moodletId,minutes,skipIncludedMoodlets=false){
-		const moodletData = this.moodletCombinedData(moodletId);
+		const moodletData = this.moodlet(moodletId);
 		const time = State.variables.time;
 		const time = State.variables.time;
 		let expiration;
 		let expiration;
 
 
@@ -174,12 +188,6 @@ class Mood{
 		}
 		}
 	}
 	}
 
 
-	moodletIsActive(moodletId){
-		const moodletData = this.moodletCombinedData(moodletId);
-		const time = State.variables.time;
-		return time.isFuture(moodletData.expiration);
-	}
-
 	moodletUpdate(moodletId,updateObject){
 	moodletUpdate(moodletId,updateObject){
 		this._moodlets[moodletId] = Object.assign({},this._moodlets[moodletId],updateObject);
 		this._moodlets[moodletId] = Object.assign({},this._moodlets[moodletId],updateObject);
 	}
 	}

+ 5 - 5
sugarcube/src/playerCharacter/_submodules/pc_pain.js → sugarcube/src/playerCharacter/_submodules/pc_pain.ts

@@ -1,16 +1,16 @@
 class Pain{
 class Pain{
 	get OWNER(){return State.variables.pc}
 	get OWNER(){return State.variables.pc}
 
 
-    _pain = {
+    _pain:{[key: string]:number} = {
 	}
 	}
 
 
 	pain(bodypart){
 	pain(bodypart){
 		return this._pain[bodypart] || 0;
 		return this._pain[bodypart] || 0;
 	}
 	}
 
 
-	get painByBodyparts(){
+	get painByBodyparts():{[key: string]:number}{
 		var result = {};
 		var result = {};
-		var painRaw = {};
+		var painRaw:{[key: string]:Array<number>} = {};
 		for (const [bodypart, currentPain] of Object.entries(this._pain)) {
 		for (const [bodypart, currentPain] of Object.entries(this._pain)) {
 			painRaw[bodypart] = [currentPain];
 			painRaw[bodypart] = [currentPain];
 		}
 		}
@@ -21,7 +21,7 @@ class Pain{
 		}
 		}
 
 
 		for(const [bodypartId,painValues] of Object.entries(painRaw)){
 		for(const [bodypartId,painValues] of Object.entries(painRaw)){
-			let painValuesSorted = painValues.toSorted((a,b) => b - a);
+			let painValuesSorted:Array<number> = painValues.toSorted((a,b) => b - a);
 			let i=0;
 			let i=0;
 			let sum = 0;
 			let sum = 0;
 			for(const painValue of painValuesSorted){
 			for(const painValue of painValuesSorted){
@@ -42,7 +42,7 @@ class Pain{
         return 1/120;
         return 1/120;
     }
     }
 
 
-	get painOfActiveEffects(){
+	get painOfActiveEffects():{[key: string]:number}{
 		return this.OWNER.painOfActiveEffects;
 		return this.OWNER.painOfActiveEffects;
 	}
 	}
 
 

+ 0 - 262
sugarcube/src/playerCharacter/mood/moodlets.js

@@ -1,262 +0,0 @@
-setup.moodletTimeMode = {
-	Continuous: 0,
-	Resetting: 1,
-	Lasting: 2
-}
-
-setup.moodletAccumulationMode = {
-	ADD: 0,
-	HIGHEST: 1,
-	LOWEST: 2,
-	DIMINISHING: 3,
-	DIMINISHING_REVERSE: 4
-}
-
-setup.moodlets ??= {};
-setup.moodletGroups ??= {};
-setup.moodletGroups.none = {
-	accumulationMode: setup.moodletAccumulationMode.ADD
-}
-
-setup.moodletGroups.pain = {
-	accumulationMode: setup.moodletAccumulationMode.LOWEST
-}
-
-setup.moodlets.pain = {
-	title: "Pain",
-	group: 'pain',
-	description: '',
-	effect: 0,
-	timeMode: setup.moodletTimeMode.Lasting
-};
-
-setup.moodletGroups.pleasure = {
-	accumulationMode: setup.moodletAccumulationMode.HIGHEST
-}
-setup.moodlets.orgasm = {
-	title: "Orgasm",
-	group: 'pleasure',
-	description: '',
-	effect: 30,
-	timeMode: setup.moodletTimeMode.Resetting,
-	duration: 240
-};
-
-setup.moodletGroups.socialNegative = {
-	accumulationMode: setup.moodletAccumulationMode.LOWEST
-}
-setup.moodlets.annoyed = {
-	title: "Annoyed",
-	group: 'socialNegative',
-	description: 'Somebody has annoyed you with their behavior.',
-	effect: -5,
-	timeMode: setup.moodletTimeMode.Resetting,
-	duration: 30
-};
-setup.moodlets.embarrassed = {
-	title: "Embarrassed",
-	group: 'socialNegative',
-	description: 'You have been embarrassed.',
-	effect: -30,
-	timeMode: setup.moodletTimeMode.Resetting,
-	duration: 240
-};
-
-setup.moodlets.ignored = {
-	title: "Ignored",
-	group: 'socialNegative',
-	description: 'You have been ignored where you would have liked to get attention.',
-	effect: -5,
-	timeMode: setup.moodletTimeMode.Resetting,
-	duration: 60
-};
-
-setup.moodlets.insulted = {
-	title: "Insulted",
-	group: 'socialNegative',
-	description: 'You have been insulted.',
-	effect: -10,
-	timeMode: setup.moodletTimeMode.Resetting,
-	duration: 240
-};
-
-
-
-setup.moodletGroups.socialPositive = {
-	accumulationMode: setup.moodletAccumulationMode.HIGHEST
-}
-
-setup.moodlets.acknowledged = {
-	title: "Acknowledged",
-	group: 'socialPositive',
-	description: 'You got the positive attention you wanted.',
-	effect: 5,
-	timeMode: setup.moodletTimeMode.Resetting,
-	duration: 60
-};
-
-setup.moodlets.littlePraise = {
-	title: "Little Praise",
-	group: 'socialPositive',
-	description: 'You received a minor praise.',
-	effect: 10,
-	timeMode: setup.moodletTimeMode.Resetting,
-	duration: 120
-};
-
-setup.moodlets.niceChat = {
-	title: "Nice Chat",
-	group: 'socialPositive',
-	description: '',
-	effect: 15,
-	timeMode: setup.moodletTimeMode.Resetting,
-	duration: 120
-};
-
-setup.moodletGroups.vanity = {
-	accumulationMode: setup.moodletAccumulationMode.DIMINISHING
-}
-
-setup.moodletGroups.victim = {
-	accumulationMode: setup.moodletAccumulationMode.LOWEST
-}
-
-// ----- Hunger -----
-setup.moodletGroups.hunger = {
-	accumulationMode: setup.moodletAccumulationMode.LOWEST
-}
-
-setup.moodlets.hunger_1 = {
-	title: "Very Hungry",
-	group: 'hunger',
-	description: '',
-	effect: -30,
-	timeMode: setup.moodletTimeMode.Lasting
-};
-
-setup.moodlets.hunger_2 = {
-	title: "Extremely Hungry",
-	group: 'hunger',
-	description: '',
-	effect: -60,
-	timeMode: setup.moodletTimeMode.Lasting
-};
-
-setup.moodlets.hunger_3 = {
-	title: "Dying from Hunger",
-	group: 'hunger',
-	description: '',
-	effect: -120,
-	timeMode: setup.moodletTimeMode.Lasting
-};
-
-// ----- Thirst -----
-setup.moodletGroups.thirst = {
-	accumulationMode: setup.moodletAccumulationMode.LOWEST
-}
-setup.moodlets.thirst_1 = {
-	title: "Very Thirsty",
-	group: 'thirst',
-	description: '',
-	effect: -30,
-	timeMode: setup.moodletTimeMode.Lasting
-};
-
-setup.moodlets.thirst_2 = {
-	title: "Extremely Thirsty",
-	group: 'thirst',
-	description: '',
-	effect: -60,
-	timeMode: setup.moodletTimeMode.Lasting
-};
-
-setup.moodlets.thirst_3 = {
-	title: "Dying from Thirst",
-	group: 'thirst',
-	description: '',
-	effect: -120,
-	timeMode: setup.moodletTimeMode.Lasting
-};
-
-// ----- Phone -----
-setup.moodletGroups.phone = {
-	accumulationMode: setup.moodletAccumulationMode.HIGHEST
-}
-setup.moodlets.phone_0 = {
-	title: "Played with phone",
-	group: 'phone_0',
-	description: 'You played with your phone.',
-	effect: 20,
-	timeMode: setup.moodletTimeMode.Resetting,
-	duration: 120,
-	maxDuration: 480
-};
-
-// ----- Reading -----
-setup.moodletGroups.read = {
-	accumulationMode: setup.moodletAccumulationMode.HIGHEST
-}
-setup.moodlets.read_finish = {
-	title: "Finished Book",
-	group: 'read',
-	description: 'You finished a book.',
-	effect: 15,
-	timeMode: setup.moodletTimeMode.Resetting,
-	duration: 240
-};
-setup.moodlets.read = {
-	title: "Read",
-	group: 'read',
-	description: 'You read a book.',
-	effect: 10,
-	timeMode: setup.moodletTimeMode.Continuous,
-	timeConversion: 1,
-	maxDuration: 480
-};
-
-// ----- TV -----
-setup.moodletGroups.tv = {
-	accumulationMode: setup.moodletAccumulationMode.HIGHEST
-}
-setup.moodlets.tv_0 = {
-	title: "Watched TV (Low Quality)",
-	group: 'tv',
-	description: 'You watched TV on a low quality TV.',
-	effect: 5,
-	timeMode: setup.moodletTimeMode.Continuous,
-	timeConversion: 1,
-	maxDuration: 480
-};
-
-setup.moodlets.tv_1 = {
-	title: "Watched TV (Medium Quality)",
-	group: 'tv',
-	description: 'You watched TV on a medium quality TV.',
-	effect: 10,
-	timeMode: setup.moodletTimeMode.Continuous,
-	timeConversion: 1,
-	maxDuration: 480,
-	includes:['tv_0']
-};
-
-// ----- work -----
-setup.moodletGroups.work = {
-	accumulationMode: setup.moodletAccumulationMode.ADD
-}
-setup.moodlets.housework = {
-	title: "Housework",
-	group: 'work',
-	description: 'You performed housework.',
-	effect: -20,
-	timeMode: setup.moodletTimeMode.Continuous,
-	timeConversion: 2,
-	maxDuration: 480
-};
-
-setup.getMoodlet ??= function(moodletId){
-	return setup.moodlets[moodletId] ?? {};
-}
-
-setup.getMoodletGroup ??= function(moodletGroupId){
-	return setup.moodletGroups[moodletGroupId] ?? {};
-}

+ 234 - 0
sugarcube/src/playerCharacter/mood/moodlets.ts

@@ -0,0 +1,234 @@
+setup.moodlets.pain = new Moodlet({
+	title: "Pain",
+	group: 'pain',
+	description: '',
+	effect: 0,
+	timeMode: moodletTimeMode.Lasting
+});
+
+setup.moodletGroups.pleasure = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.HIGHEST
+});
+setup.moodlets.orgasm = new Moodlet({
+	title: "Orgasm",
+	group: 'pleasure',
+	description: '',
+	effect: 30,
+	timeMode: moodletTimeMode.Resetting,
+	duration: 240
+});
+
+setup.moodletGroups.socialNegative = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.LOWEST
+});
+setup.moodlets.annoyed = new Moodlet({
+	title: "Annoyed",
+	group: 'socialNegative',
+	description: 'Somebody has annoyed you with their behavior.',
+	effect: -5,
+	timeMode: moodletTimeMode.Resetting,
+	duration: 30
+});
+setup.moodlets.embarrassed = new Moodlet({
+	title: "Embarrassed",
+	group: 'socialNegative',
+	description: 'You have been embarrassed.',
+	effect: -30,
+	timeMode: moodletTimeMode.Resetting,
+	duration: 240
+});
+
+setup.moodlets.ignored = new Moodlet({
+	title: "Ignored",
+	group: 'socialNegative',
+	description: 'You have been ignored where you would have liked to get attention.',
+	effect: -5,
+	timeMode: moodletTimeMode.Resetting,
+	duration: 60
+});
+
+setup.moodlets.insulted = new Moodlet({
+	title: "Insulted",
+	group: 'socialNegative',
+	description: 'You have been insulted.',
+	effect: -10,
+	timeMode: moodletTimeMode.Resetting,
+	duration: 240
+});
+
+
+
+setup.moodletGroups.socialPositive = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.HIGHEST
+});
+
+setup.moodlets.acknowledged = new Moodlet({
+	title: "Acknowledged",
+	group: 'socialPositive',
+	description: 'You got the positive attention you wanted.',
+	effect: 5,
+	timeMode: moodletTimeMode.Resetting,
+	duration: 60
+});
+
+setup.moodlets.littlePraise = new Moodlet({
+	title: "Little Praise",
+	group: 'socialPositive',
+	description: 'You received a minor praise.',
+	effect: 10,
+	timeMode: moodletTimeMode.Resetting,
+	duration: 120
+});
+
+setup.moodlets.niceChat = new Moodlet({
+	title: "Nice Chat",
+	group: 'socialPositive',
+	description: '',
+	effect: 15,
+	timeMode: moodletTimeMode.Resetting,
+	duration: 120
+});
+
+setup.moodletGroups.vanity = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.DIMINISHING
+});
+
+setup.moodletGroups.victim = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.LOWEST
+});
+
+// ----- Hunger -----
+setup.moodletGroups.hunger = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.LOWEST
+});
+
+setup.moodlets.hunger_1 = new Moodlet({
+	title: "Very Hungry",
+	group: 'hunger',
+	description: '',
+	effect: -30,
+	timeMode: moodletTimeMode.Lasting
+});
+
+setup.moodlets.hunger_2 = new Moodlet({
+	title: "Extremely Hungry",
+	group: 'hunger',
+	description: '',
+	effect: -60,
+	timeMode: moodletTimeMode.Lasting
+});
+
+setup.moodlets.hunger_3 = new Moodlet({
+	title: "Dying from Hunger",
+	group: 'hunger',
+	description: '',
+	effect: -120,
+	timeMode: moodletTimeMode.Lasting
+});
+
+// ----- Thirst -----
+setup.moodletGroups.thirst = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.LOWEST
+});
+
+setup.moodlets.thirst_1 = new Moodlet({
+	title: "Very Thirsty",
+	group: 'thirst',
+	description: '',
+	effect: -30,
+	timeMode: moodletTimeMode.Lasting
+});
+
+setup.moodlets.thirst_2 = new Moodlet({
+	title: "Extremely Thirsty",
+	group: 'thirst',
+	description: '',
+	effect: -60,
+	timeMode: moodletTimeMode.Lasting
+});
+
+setup.moodlets.thirst_3 = new Moodlet({
+	title: "Dying from Thirst",
+	group: 'thirst',
+	description: '',
+	effect: -120,
+	timeMode: moodletTimeMode.Lasting
+});
+
+// ----- Phone -----
+setup.moodletGroups.phone = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.HIGHEST
+});
+
+setup.moodlets.phone_0 = new Moodlet({
+	title: "Played with phone",
+	group: 'phone_0',
+	description: 'You played with your phone.',
+	effect: 20,
+	timeMode: moodletTimeMode.Resetting,
+	duration: 120,
+	maxDuration: 480
+});
+
+// ----- Reading -----
+setup.moodletGroups.read = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.HIGHEST
+});
+
+setup.moodlets.read_finish = new Moodlet({
+	title: "Finished Book",
+	group: 'read',
+	description: 'You finished a book.',
+	effect: 15,
+	timeMode: moodletTimeMode.Resetting,
+	duration: 240
+});
+setup.moodlets.read = new Moodlet({
+	title: "Read",
+	group: 'read',
+	description: 'You read a book.',
+	effect: 10,
+	timeMode: moodletTimeMode.Continuous,
+	timeConversion: 1,
+	maxDuration: 480
+});
+
+// ----- TV -----
+setup.moodletGroups.tv = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.HIGHEST
+});
+setup.moodlets.tv_0 = new Moodlet({
+	title: "Watched TV (Low Quality)",
+	group: 'tv',
+	description: 'You watched TV on a low quality TV.',
+	effect: 5,
+	timeMode: moodletTimeMode.Continuous,
+	timeConversion: 1,
+	maxDuration: 480
+});
+
+setup.moodlets.tv_1 = new Moodlet({
+	title: "Watched TV (Medium Quality)",
+	group: 'tv',
+	description: 'You watched TV on a medium quality TV.',
+	effect: 10,
+	timeMode: moodletTimeMode.Continuous,
+	timeConversion: 1,
+	maxDuration: 480,
+	includes:['tv_0']
+});
+
+// ----- work -----
+setup.moodletGroups.work = new MoodletGroup({
+	accumulationMode: moodletAccumulationMode.ADD
+});
+
+setup.moodlets.housework = new Moodlet({
+	title: "Housework",
+	group: 'work',
+	description: 'You performed housework.',
+	effect: -20,
+	timeMode: moodletTimeMode.Continuous,
+	timeConversion: 2,
+	maxDuration: 480
+});

+ 3 - 3
sugarcube/src/playerCharacter/mood/moodlets.tw

@@ -58,19 +58,19 @@
 					<</textWithTooltip>>
 					<</textWithTooltip>>
 			<</switch>>
 			<</switch>>
 			<<switch _moodletData.timeMode>>
 			<<switch _moodletData.timeMode>>
-				<<case setup.moodletTimeMode.Continuous>>
+				<<case 0>>
 					<<textWithTooltip "🔁">>
 					<<textWithTooltip "🔁">>
 						<h3>Repeatable</h3>
 						<h3>Repeatable</h3>
 						This mood effect can be gained multiple times. This will increase the time it is active, up to a maximum number of minutes.
 						This mood effect can be gained multiple times. This will increase the time it is active, up to a maximum number of minutes.
 						For example, you can make the effect of watching TV last longer by watching more TV.
 						For example, you can make the effect of watching TV last longer by watching more TV.
 					<</textWithTooltip>>
 					<</textWithTooltip>>
-				<<case setup.moodletTimeMode.Resetting>>
+				<<case 1>>
 					<<textWithTooltip "🔂">>
 					<<textWithTooltip "🔂">>
 						<h3>Resetting</h3>
 						<h3>Resetting</h3>
 						When this mood effect is gained, it resets the time it is active.
 						When this mood effect is gained, it resets the time it is active.
 						For example, the effect of gaining a compliment lasts for 4 hours. If you get another compliment 2 hours after you got the first one, the effect will last for 6 hours (2 of the first and 4 of the second compliment).
 						For example, the effect of gaining a compliment lasts for 4 hours. If you get another compliment 2 hours after you got the first one, the effect will last for 6 hours (2 of the first and 4 of the second compliment).
 					<</textWithTooltip>>
 					<</textWithTooltip>>
-				<<case setup.moodletTimeMode.Lasting>>
+				<<case 2>>
 					<<textWithTooltip "🔚">>
 					<<textWithTooltip "🔚">>
 						<h3>Lasting</h3>
 						<h3>Lasting</h3>
 						This mood effect will last until canceled. Depending on the effect, this might be an interaction with a NPC, sleeping for a specified amount of time, random chance or anything else.
 						This mood effect will last until canceled. Depending on the effect, this might be an interaction with a NPC, sleeping for a specified amount of time, random chance or anything else.

+ 1 - 1
sugarcube/src/start/initialization/init_pre_intro.tw

@@ -1,7 +1,7 @@
 :: init_pre_intro[include]
 :: init_pre_intro[include]
     <!-- Only the initialization that MUST happen for the intro to function. -->
     <!-- Only the initialization that MUST happen for the intro to function. -->
     <<script>>
     <<script>>
-		State.variables.pc = new PlayerCharacter();
+		State.variables.pc = new setup.PlayerCharacter();
 		State.variables.time = new setup.GameTime();
 		State.variables.time = new setup.GameTime();
 		State.variables.wardrobe = new Wardrobe();
 		State.variables.wardrobe = new Wardrobe();
 		State.variables.npcs = new NPCsDict();
 		State.variables.npcs = new NPCsDict();

+ 4 - 4
sugarcube/src/version/VersionControl.ts

@@ -25,13 +25,13 @@ class VersionControl{
 				variables.q['school'].groups[['cool','jocks','nerds','gopniks','outcasts','teachers'][variables['grupTipe'] - 1]].member = true;
 				variables.q['school'].groups[['cool','jocks','nerds','gopniks','outcasts','teachers'][variables['grupTipe'] - 1]].member = true;
 			}
 			}
 		}
 		}
-		/*
+		
 		if(versionOfVariables < 14){
 		if(versionOfVariables < 14){
-			variables.pc._makeupAmount = variables.pc._pcs_makeup;
+			variables.pc._makeupAmount = variables.pc['_pcs_makeup'];
 			variables.pc._makeupQuality= 2;
 			variables.pc._makeupQuality= 2;
-			variables.pc._leghair = variables.pc.pcs_leghair;
+			variables.pc._leghair = variables.pc['pcs_leghair'];
 		}
 		}
-
+		/*
 		if(versionOfVariables < 16){
 		if(versionOfVariables < 16){
 			if(variables.housing._home == 'parents_home')			variables.housing._home = 'homeParents';
 			if(variables.housing._home == 'parents_home')			variables.housing._home = 'homeParents';
 			if(variables.housing._access.includes('parents_home'))	variables.housing._access.push('homeParents');
 			if(variables.housing._access.includes('parents_home'))	variables.housing._access.push('homeParents');

+ 1 - 1
sugarcube/tsconfig.json

@@ -1,6 +1,6 @@
 {
 {
 	"compilerOptions": {
 	"compilerOptions": {
-		"target": "ES2022", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
+		"target": "ESNext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
 		"module": "amd", /* Specify module code generation: */
 		"module": "amd", /* Specify module code generation: */
 		"sourceMap": false, 
 		"sourceMap": false, 
 		"outFile": "temp/typescript.js",
 		"outFile": "temp/typescript.js",