///
interface BodypartValueResult {
value : number;
weight : number;
}
class Bodypart extends Thing {
public static WEIGHT_LOWEST = 1;
public static WEIGHT_LOW = 3;
public static WEIGHT_MEDIUM = 5;
public static WEIGHT_HIGH = 7;
public static WEIGHT_HIGHEST = 9;
public static SLUTTINESS_LOWEST_SAINTLY = 0;
public static SLUTTINESS_LOW_PRUDE = 25;
public static SLUTTINESS_MEDIUM_AVERAGE = 50;
public static SLUTTINESS_HIGH_SLUT = 75;
public static SLUTTINESS_HIGHEST_WHORE = 100;
public static GENDER_LOWEST_MANLIEST = 0;
public static GENDER_LOW_MANLY = 25;
public static GENDER_MEDIUM_ANDROGYNE = 50;
public static GENDER_HIGH_FEMININE = 75;
public static GENDER_HIGHEST_FEMININEST = 100;
// The higher this number, the more the bodypart will be worth for health.
// For instance, HEAD should be worth more than FINGERNAIL.
public sorenessWeight : number = 1;
// 0 to 10
// says how fucked up the bodypart is
public soreness : number = 0;
// How much soreness is healed every turn
public sorenessPerTurn : number = 0.05;
// Last turn soreness got updated
public lastSorenessUpdate : number = 0;
public constructor (options? : ThingOptions) {
super(options);
this.addGetAlterations((bp : Bodypart) => {
return {
Soreness : bp.soreness,
GenderValue : bp.genderValue,
Sluttiness : bp.getSluttiness()
}
});
this.addSetAlterations((bp : Bodypart, changes) => {
this.soreness = changes.Soreness;
this.genderValue = changes.GenderValue;
this.sluttiness = changes.Sluttiness;
});
}
public changeSoreness (soreness : number) {
this.soreness += soreness;
if (this.soreness < 0) {
this.soreness = 0;
}
}
public regenerate() {
this.changeSoreness(- this.sorenessPerTurn);
}
public getSoreness () {
return this.soreness;
}
public getWeightedSoreness() {
return this.getSoreness() * this.sorenessWeight;
}
public getSorenessWeight () {
return this.sorenessWeight;
}
// These are the slots the bodypart is visible on
// Should use Humanoid.SLOT_* !
public slots : Array = [];
public visibleSlots : Array = [];
// GenderValue is how masculine/feminine this bodypart is.
// At 0 = the most masculine possible, at 100 = the most feminine eveter
// 50 would be completely androgynous
public genderValue : number = Bodypart.GENDER_MEDIUM_ANDROGYNE;
// Like with health, the weight makes this bodypart matter more for deciding gender.
// Gender presentation is not about prettiness, so, for instance, having huge breasts will
// strongly push you to the "is a woman" side, even if you're manly as fuck everywhere else.
// If you're too manly everywhere else, though, you'll probably end up closer on the spectrum to male
// or at least androgynous, which might result in not passing.
public genderWeight : number = 1;
/**
* Sluttiness goes from 0 to 100.
* A bodypart's sluttiness is dependent on it being seen.
* @type {number}
*/
public sluttiness : number = 10;
public sluttinessWeight : number = Bodypart.WEIGHT_LOWEST;
public getGenderWeight () {
if (this.slots.length == 0) {
return 0;
}
return this.genderWeight * (this.visibleSlots.length / this.slots.length);
}
public getGenderValue () {
return this.genderValue;
}
public getWeightedGenderValue () {
return this.getGenderValue() * this.getGenderWeight();
}
public getSluttiness() {
return this.sluttiness;
}
public getSluttinessWeight () {
if (this.slots.length == 0) {
return 0;
}
return this.sluttinessWeight * (this.visibleSlots.length / this.slots.length);
}
public getWeightedSluttinessValue () {
return this.getSluttiness() * this.getSluttinessWeight();
}
public updateVisibility () {
this.visibleSlots = this.slots.slice(0);
let parent = Thing.PartRelation.getLeft(this);
if (parent != undefined) {
let clothing = >Thing.WearRelation.getRight(parent);
for (let i = 0; i < clothing.length; i++) {
let covering = clothing[i].getCoveringSlots();
for (let k = 0; k < covering.length; k++) {
let idx = this.visibleSlots.indexOf(covering[k]);
if (idx >= 0) {
this.visibleSlots.splice(idx, 1);
}
}
if (this.visibleSlots.length == 0) break;
}
}
}
public isUncovered () {
this.updateVisibility();
return this.visibleSlots.length == this.slots.length && this.slots.length > 0;
}
public updateStatus () {
this.updateVisibility();
}
public static getSoreness (thing : Thing) {
let bodyparts = Thing.PartRelation.getRightType(thing, Bodypart);
let soreness = 0;
bodyparts.forEach((bodypart : Bodypart) => {
soreness += bodypart.getWeightedSoreness();
});
return soreness;
}
public static getGenderValueOn (thing : Thing) : BodypartValueResult {
let weight = 0;
let value = 0;
let bodyparts = Thing.PartRelation.getRightType(thing, Bodypart);
bodyparts.forEach((bodypart : Bodypart) => {
weight += bodypart.getGenderWeight();
value += bodypart.getWeightedGenderValue();
});
return {
weight : weight,
value : value
};
}
public static getSluttinessValueOn (thing : Thing) : BodypartValueResult {
let weight = 0;
let value = 0;
let bodyparts = Thing.PartRelation.getRightType(thing, Bodypart);
bodyparts.forEach((bodypart : Bodypart) => {
weight += bodypart.getSluttinessWeight();
value += bodypart.getWeightedSluttinessValue();
});
return {
weight : weight,
value : value
};
}
/**
* Changes the bodypart so that it matches the desired genderValue.
* This needs to be implemented in all classes inheriting from Bodypart, as not all bodyparts have a simple "genderValue" to assign.
* @param {number} genderValue
*/
public arrangeGenderValue (genderValue : number) {
this.genderValue = genderValue;
( this.getPartOne()).invalidateCaches();
}
/**
* Attempts to increase Femininity by 5 * amount. Will read Current Gender Value and try to reassign it.
* @param {number} amount
*/
public increaseFemininity (amount : number) {
let currentGV = this.getGenderValue();
this.arrangeGenderValue(currentGV + (5 * amount));
}
/**
* Attempts to increase Masculinity by 5 * amount. Will read Current Gender Value and try to reassign it.
* @param {number} amount
*/
public increaseMasculinity (amount : number) {
let currentGV = this.getGenderValue();
this.arrangeGenderValue(currentGV - (5 * amount));
}
}