Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • PantyNabber/fc-pregmod
  • pregmodfan/fc-pregmod
  • Alice.Grant/fc-pregmod
  • powerfful/fc-pregmod
  • elstumpo/fc-pregmod
  • Y/fc-pregmod
  • floer/fc-pregmod
  • oidocrop/fc-pregmod
  • hawk5005/fc-pregmod
  • nn/fc-pregmod
  • latios298/fc-pregmod
  • brpregmodfan/fc-pregmod
  • SomeoneTookMyUserName/fc-pregmod
  • 000-250-006/fc-pregmod
  • rewrica/fc-pregmod
  • Stuffedgame/fc-pregmod
  • wisepants314/fc-pregmod
  • fcanon/fc-pregmod
  • randomanon1/pregmod-mod-cyberfurry
  • teddy.buckland/fc-pregmod
  • farsinian_591b7a2d8b49d/fc-pregmod
  • FCShotadev/fc-pregmod
  • uselessartifact/fc-pregmod
  • irina_90/fc-pregmod
  • thaumx/fc-pregmod
  • MouseOfLight/fc-pregmod
  • empresssela/fc-pregmod
  • MasterAaran/fc-pregmod
  • ishy/fc-pregmod
  • psychofox/fc-pregmod
  • shadomancer/fc-pregmod
  • tycrakgg/fc-pregmod
  • azktaawc/fc-pregmod
  • andonno07/fc-pregmod
  • Onithyr/fc-pregmod
  • redneck987.jl/fc-pregmod
  • Farseeker/fc-pregmod
  • milliarc/fc-pregmod
  • BeefimusMaximus/fc-pregmod
  • magicknight79/fc-pregmod
  • hexall90/fc-pregmod
  • cantworkforever/fc-pregmod
  • jc052005/fc-pregmod
  • klorpa/fc-pregmod
  • doku/fc-pregmod
  • samhradh/fc-pregmod
  • scientist/fc-pregmod
  • albania420/fc-pregmod
  • Editoranon/fc-pregmod
  • Anony/fc-pregmod
  • deimios666/fc-pregmod
  • IvoHoe/fc-pregmod
  • bitty/fc-pregmod
  • RealAnon1800/fc-pregmod
  • brankirk/fc-pregmod
  • Amygdalan/fc-pregmod
  • DankWolf/fc-pregmod
  • Supot1951/fc-pregmod
  • bcy603/fc-pregmod
  • pwfxjpuv/fc-pregmod
  • ThreadAnon/fc-pregmod
  • Anon1800/fc-pregmod
  • Echoart/fc-pregmod
  • Dingotush/fc-pregmod
  • anonman/fc-pregmod
  • Arkerthan/fc-pregmod
  • svornost/fc-pregmod
  • wierdwierdos/fc-pregmod
  • wetwareAnon/fc-pregmod
  • QuartzHat/fc-pregmod
  • IchthysdeKilt/fc-pregmod
  • AnonAnonFC/fc-pregmod
  • Alexsis/fc-pregmod
  • LoyalTreeWP/fc-pregmod
  • aerialace/fc-pregmod
  • NurseryAnon/fc-pregmod
  • drakeashordcataclysm/fc-pregmod
  • AshVaris/fc-pregmod
  • purely0nothing/fc-pregmod
  • alex2011/fc-pregmod
  • Lindontree/fc-pregmod
  • FCaa/fc-pregmod
  • TR-8R/fc-pregmod
  • Jones/fc-pregmod
  • brr99/fc-pregmod
  • WriteAnon101/fc-pregmod
  • Drosil/fc-pregmod
  • Bob1221/fc-pregmod
  • vas/fc-pregmod
  • gitgud.user.937/fc-pregmod
  • D-K/fc-pregmod
  • AnonDev/fc-pregmod
  • madman23456/fc-pregmod
  • InarusLynx/fc-pregmod
  • Sonofrevvan/fc-pregmod
  • Randoisrando/fc-pregmod
  • cheez94/fc-pregmod
  • dldldl/fc-pregmod
  • alice321/fc-pregmod
  • Alexei91/fc-pregmod
  • darkcy/fc-pregmod
  • MapleMAD/fc-pregmod
  • pillarofsalt/fc-pregmod
  • vultureangels/fc-pregmod
  • kernel/fc-pregmod
  • nooneman/fc-pregmod
  • deepmurk/fc-pregmod
  • uglybead/fc-pregmod
  • lemongrab/fc-pregmod
  • temperence-chan/fc-pregmod
  • hcommenter/fc-pregmod
  • SpedeMemerson/fc-pregmod
  • qwijqwsf/fc-pregmod
  • BuDClow/fc-pregmod
  • HiveBro/fc-pregmod
  • shoku/fc-pregmod
  • ezsh/fc-pregmod
  • Blank/fc-pregmod
  • randoralcissian/fc-pregmod
  • benito92/fc-pregmod
  • balakart/fc-pregmod
  • wedonotsaw/fc-pregmod
  • Cayleth/fc-pregmod
  • Khip/fc-pregmod
  • Zfair/fc-pregmod
  • promethium/fc-pregmod
  • scyne/fc-pregmod
  • ZZC/fc-pregmod
  • SilverJanine/fc-pregmod
  • joxosix654email-9.co/fc-pregmod
  • Littlefootlittleguy/fc-pregmod
  • FelipeBA/fc-pregmod
  • bigtiddygothbf/fc-pregmod
  • Qotsafan/fc-pregmod
  • Zachpocalypse/fc-pregmod
  • milkanon66/fc-pregmod
  • GreGGoZZ/fc-pregmod
  • drsnarf86/fc-pregmod
  • valen102938/fc-pregmod
  • pregspammer/fc-pregmod
  • ponderin94/fc-pregmod
  • nook/fc-pregmod
  • carnifex34/fc-pregmod-mod-carni
  • SyntheticHigh/fc-pregmod
  • bob112211/fc-pregmod
  • amomynous0/fc-pregmod
  • oxone/fc-pregmod
  • MaxEuwe/fc-pregmod
  • nekoanon/fc-pregmod
  • preglocke/fc-pregmod
  • valen10293847/fc-pregmod
  • 2hu4u/fc-pregmod
  • mayibrad/fc-pregmod
  • Screm/fc-pregmod
  • Ansopedi/fc-pregmod
  • mrchaosbones/fc-pregmod
  • putrid/fc-pregmod
  • Kinnerman/fc-pregmod
  • gungrave1155/fc-pregmod
  • prndev/fc-pregmod
  • weresmilodon/fc-pregmod
  • auxxigobin/fc-pregmod
  • alice-chan/fc-pregmod
  • wigglie/fc-pregmod
  • jrliltfgb/fc-pregmod
  • Lord.alek.shade/fc-pregmod
  • truetailthesquire/fc-pregmod
  • lowercasedonkey/fc-pregmod
  • alice-chan9/fc-pregmod
  • eroglyphics/fc-pregmod
  • taliyent/fc-pregmod
  • zenzombie90/fc-pregmod
  • kjarik/fc-pregmod
  • wriggler/fc-pregmod
  • midnightblue/fc-pregmod
  • faraen/fc-pregmod
  • sigurd.cole/fc-pregmod
  • FCbuganon/fc-pregmod
  • kidkinster/fc-pregmod
  • Kar_Dragon/fc-pregmod
  • Zhafier/fc-pregmod
  • crcaretti/fc-pregmod
  • anond/fc-pregmod
  • tempmania/fc-pregmod
  • Dhanze/fc-pregmod
  • EstaUnCachucha/fc-pregmod
  • oniAnon/fc-pregmod
  • plebian/fc-pregmod
  • maxd569/fc-pregmod
  • Levarn/fc-pregmod
  • pumpkinspice/fc-pregmod
  • GammaXai/fc-pregmod
  • DanBackslide/fc-pregmod
  • i107760/fc-pregmod
  • Absimiliard/fc-pregmod
  • AmbrosiaCheesecake/fc-pregmod
  • fuguer/fc-pregmod
  • Azurel/fc-pregmod
  • Fake_Dev/fc-pregmod
  • ddongsanda/fc-pregmod
  • Combine456/fc-pregmod
  • UnwrappedGodiva/fc-pregmod
  • toyRuberDucky/fc-pregmod
  • zmobie/fc-pregmod
  • chuongk/fc-pregmod
  • BigWalnuts/fc-pregmod
  • Birdstrike/fc-pregmod
  • r3d/fc-pregmod
  • mawspa/fc-pregmod
  • sushila/fc-pregmod
  • DeathShip/fc-pregmod
  • eggrollsandwich/fc-pregmod
  • krayken/fc-pregmod
  • Reman/fc-pregmod
  • dwiafgts/fc-pregmod
  • jort93/fc-pregmod
  • teruterubouzu/fc-pregmod
  • flut/fc-pregmod
  • john-normal/fc-pregmod
  • Jonathan2405/fc-pregmod
  • Tyrgalon/fc-pregmod
  • NovX/fc-pregmod
  • Star1/fc-pregmod
  • Transhumanist01/fc-pregmod
  • m1017242/fc-pregmod
  • Rizal98798/fc-pregmod
  • jamezu369/fc-pregmod
  • thisisawittyname/fc-pregmod
  • KnightBoulegard/fc-pregmod
  • jblack/fc-pregmod
  • Souldrainr/fc-pregmod
  • torbjornhub/fc-pregmod
  • turnop/fc-pregmod
  • breadedpigeon/fc-pregmod
  • fire.maker/fc-pregmod
  • Inahaze/fc-pregmod
  • Waerjak/fc-pregmod
  • Trashman1138/fc-pregmod
  • supanintendo/fc-pregmod
  • _no0neman/fc-pregmod
  • Weslo/fc-pregmod
  • qw89/fc-pregmod
  • EvilDruid/fc-pregmod
  • dt25/fc-pregmod
  • Raou/fc-pregmod
  • DDouFu/fc-pregmod
  • Mauno/fc-pregmod
  • PandemoniumPenguin/fc-pregmod
  • AngelPuppet/fc-pregmod
  • DasUser79/fc-pregmod
  • Keaeag3s/fc-pregmod
  • HazeHazeHaze/fc-pregmod
  • hpotato/fc-pregmod
  • owouchthatbloodyhurt/fc-pregmod
  • v7Silent/fc-pregmod
  • nickylass/fc-pregmod
  • ThePrimer/fc-pregmod
  • PineCone/fc-pregmod
  • bruhmomentum17/fc-pregmod
  • CheatDude/fc-pregmod
  • synnove/fc-pregmod
  • en_bees/fc-pregmod
  • seronis/fc-pregmod
  • Nepidinepnep/fc-pregmod
  • Titanninja/fc-pregmod
  • Elohiem/fc-pregmod
  • cocoajazz/fc-pregmod
  • tfwncagf/fc-pregmod
  • ChunkyMonke/fc-pregmod
  • Dracoman671/fc-pregmod
  • jgl/fc-pregmod
  • Inev/fc-pregmod
  • jbige/fc-pregmod
  • MonsterMate/fc-pregmod
  • Konstantin6961/fc-pregmod
  • darth_ashi/fc-pregmod
  • shinx/fc-pregmod
  • Anu/fc-pregmod
  • Greytide/fc-pregmod
  • Bonafidemetal/fc-pregmod
  • Peje/fc-pregmod
  • Hexfy98/fc-pregmod
  • TooSlow/fc-pregmod
  • SoGu/fc-pregmod
  • CloudyCoffee/fc-pregmod
  • Welptard/fc-pregmod
  • Ploc/fc-pregmod-ploc
  • rain-/fc-pregmod
  • Pecanus/fc-pregmod
  • Jhortrax/fc-pregmod
  • valleytwo/fc-pregmod
  • QCmd/fc-pregmod
  • kung-wada/fc-pregmod
  • LolGaye/fc-pregmod
  • Exspiravit1/fc-pregmod
  • jadeddog/fc-pregmod
  • buster-scruggs/fs-antebellum-revivalism
  • policia123/fc-pregmod
  • evrgentesee/fc-pregmod
  • rko127/fc-pregmod
  • ExcalGrip12/fc-pregmod
  • BlackAion/fc-pregmod
  • Boss2020/fc-pregmod
  • Lawled/fc-pregmod
  • shiro/fc-pregmod
  • Skavenkeri/fc-pregmod
  • PooPooDooDooHead/fc-pregmod
  • Dugee/fc-pregmod
  • Portal124/fc-pregmod-vore
  • Fekenol/fc-pregmod
  • elGuapo/fc-pregmod
  • KelioSteel/fc-pregmod
  • sldlddk/fc-pregmod
  • lumepanter/fc-pregmod
  • ryuhana/fc-pregmod
  • Nene1009yb/fc-pregmod
  • DontAskDontTell/fc-pregmod-extra-events
  • Dulgi/fc-pregmod
  • Jate/fc-pregmod
  • percy365/fc-pregmod
  • franklygeorge/fc-pregmod
  • Dragneel117/fc-pregmod
  • vl96/fc-pregmod
  • Gorlom/fc-economicmod
  • NotAlive/fc-pregmod
  • Heretek/fc-pregmod
  • joeshmo828282/fc-pregmod
  • deswes/fc-pregmod
  • Nanana21/fc-pregmod
  • Gbr6/fc-pregmod
  • RandomNecro/fc-pregmod
  • Trinidad/fc-pregmod
  • anonymousey/fc-pregmod
  • macaronideath/fc-pregmod
  • fcbleh/fc-pregmod
  • jk3000/fc-pregmod
  • Akane/fc-pregmod
  • TheBoi/fc-pregmod
  • Sheenariel/fc-pregmod
  • Metapod/multi-custom
  • Banyanael/fc-pregmod
  • frogge/fc-pregmod
  • idkkk12385/fc-pregmod
  • Mirarara/fc-pregmod
  • DeaDa/fc-pregmod-thedeal
  • CobraCommander/fc-pregmod
  • bicobus/fc-pregmod
  • CardcaptorRLH85/fc-pregmod
  • temp-ui-start/fc-pregmod
  • PresidentConvert/fc-pregmod
  • delizious/fc-pregmod
  • Ducati/fc-pregmod
  • DerangedLoner/fc-pregmod-development-fork
  • ProjectVictory/fc-pregmod
  • forecastle/fc-pregmod
  • Apathy/fc-pregmod
  • indf/fc-pregmod-dev
  • GavAndAlt/fc-pregmod
  • hagamablabla/fc-pregmod
  • Alaco/fc-pregmod
  • DCoded/fc-pregmod
  • LittlePlague/fc-pregmod
  • MissOnahole/fc-pregmod
  • ishy2317/fc-pregmod
  • nielkazama/fc-pregmod
  • Phobos/fc-pregmod
  • kraster/fc-pregmod
  • JasWS/fc-pregmod
  • FelixJS/fc-pregmod
  • NCherfaoui/fc-pregmod
  • MidnightMoose/fc-pregmod
  • jjjjjj/fc-pregmod
  • Cl0ver/fc-pregmod
  • Pythoniqus/fc-pregmod
  • JohnMolotov/fc-pregmod
  • anonymouspregmodder/fc-pregmod-anonymouspregmodder
  • Fanatey/fc-pregmod
  • Mizako/fc-pregmod
  • Nithhogg/fc-pregmod
  • Bluecoffee/fc-pregmod
  • Exarch/pregmod-ai-clothing
381 results
Show changes
Showing
with 761 additions and 91 deletions
......@@ -95,11 +95,18 @@ declare namespace FC {
slaveID?: number;
}
export interface TrinketData {
export interface SlaveTrinketData {
name: string,
id?: number | null
extra?: string,
napkinShape?: string
napkinShape?: string,
}
export interface TrinketData {
slaveTrinket: boolean,
/** if slaveTrinket is false this is used to keep track of how many of the given trinket the player has */
count? : number,
data? : Set<SlaveTrinketData>,
}
/**
......@@ -170,6 +177,9 @@ declare namespace FC {
careerBonusNeeded?: HumanID[];
customLanguage?: string;
/** track impreg actions made to slaves */
slaveIdsImpregnanted?: Set<number>
}
export interface GameVariables extends DefaultGameStateVariables, ResetOnNGPVariables,
......
......@@ -53,16 +53,17 @@ declare global {
export type DeepPartialSlaveState = DeepPartial<SlaveState>;
type SlaveStateRequiredAttributes = "ID" | "slaveName";
export interface HeroSlaveTemplate extends DeepPartial<Omit<SlaveState, SlaveStateRequiredAttributes>>,
export interface HeroSlaveTemplate extends
DeepPartial<Omit<SlaveState, SlaveStateRequiredAttributes>>,
Pick<SlaveState, SlaveStateRequiredAttributes> {
/**
* [left arm, right arm, left leg, right leg].
* When 0 remove the limb, when 1+ sets the limb to the given LimbType.
* [0, 0, 1, 1] would remove both arms, but keep the legs as normal.
* [6, 6, 0, 1] would make both arms cybernetic prostetics and remove the left leg.
*/
_limbs?: [0 | LimbType, 0 | LimbType, 0 | LimbType, 0 | LimbType];
}
/**
* [left arm, right arm, left leg, right leg].
* When 0 remove the limb, when 1+ sets the limb to the given LimbType.
* [0, 0, 1, 1] would remove both arms, but keep the legs as normal.
* [6, 6, 0, 1] would make both arms cybernetic prostetics and remove the left leg.
*/
_limbs?: [0 | LimbType, 0 | LimbType, 0 | LimbType, 0 | LimbType];
}
export interface GingeredSlave extends SlaveState {
// note that all members are optional...GingeredSlave and SlaveState are bidirectionally interchangeable
......@@ -208,18 +209,6 @@ declare global {
| "devout" // resistance through religious faith
| "liberated" // believes slavery is wrong
>;
interface BehavioralFlawFreeze extends Record<string, BehavioralFlaw> {
NONE: "none";
ARROGANT: "arrogant";
BITCHY: "bitchy";
ODD: "odd";
HATESMEN: "hates men";
HATESWOMEN: "hates women";
GLUTTONOUS: "gluttonous";
ANOREXIC: "anorexic";
DEVOUT: "devout";
LIBERATED: "liberated";
}
type BehavioralQuirk = WithNone<
/** believes she has value as a slave */
......@@ -292,28 +281,6 @@ declare global {
| "breeder"
/** addicted to fucking animals */
| "animal lover">;
interface SexualFlawFreeze extends Record<string, SexualFlaw> {
NONE: "none";
HATESORAL: "hates oral";
HATESANAL: "hates anal";
HATESPEN: "hates penetration";
SHAMEFAST: "shamefast";
IDEAL: "idealistic";
REPRESSED: "repressed";
APATHETIC: "apathetic";
CRUDE: "crude";
JUDGEMENT: "judgemental";
NEGLECT: "neglectful";
CUMADDICT: "cum addict";
ANALADDICT: "anal addict";
ATTENTION: "attention whore";
BREASTEXP: "breast growth";
ABUSIVE: "abusive";
MALICIOUS: "malicious";
SELFHATING: "self hating";
BREEDER: "breeder";
ANIMALLOVER: "animal lover";
}
type SexualQuirk = WithNone<
/** can take a facefucking */
......@@ -673,6 +640,32 @@ declare global {
BESTIALITY: "bestiality";
}
type PersonalAttention =
"trading" | "warfare" | "slaving" | "engineering" | "medicine" |
"upkeep" | "hacking" | "HG" | "whoring" | "business" | "smuggling" |
"defensive survey" | "development project" | "technical accidents" |
"fighting" | "sex" | "rest and relaxation" | "proclamation" |
"slave training" | "popularity" | "education" | "degree" |
"advanced education" | "advanced degree";
type PersonalAttentionTrainingObjective =
"health" | "ravish" | "ravished" | "torture" | "build devotion" |
"spar" | "soften behavioral flaw" | "break will" |
"soften sexual flaw" | "learn skills" | "combat training" |
"harshly break will" | "explore sexuality" | "fix behavioral flaw" |
"fix sexual flaw" | "induce arrogance" | "induce bitchiness" |
"induce odd behavior" | "induce hatred of men" |
"induce hatred of women" | "induce gluttony" | "induce anorexia" |
"induce religious devotion" | "induce liberation" |
"induce hatred of oral" | "induce hatred of anal" |
"induce hatred of penetration" | "induce shame" |
"induce sexual idealism" | "induce sexual repression" |
"induce sexual apathy" | "induce crudity" | "induce judgement" |
"induce cum addiction" | "induce anal addiction" |
"induce attention whoring" | "induce breast growth obsession" |
"induce abusiveness" | "induce maliciousness" | "induce self hatred" |
"induce sexual self neglect" | "induce breeding obsession" | "training";
type TeethType = "normal" | "crooked" | "gapped" | "straightening braces" | "cosmetic braces" | "removable" | "pointy" |
"fangs" | "fang" | "baby" | "mixed";
type MinorInjury = Zeroable<"black eye" | "bad bruise" | "split lip" | "sore ass">;
......@@ -719,6 +712,7 @@ declare global {
type ReproductiveSystem = AnimalType | "sterile";
type GeneticQuirk = 0 | 1 | 2;
interface GeneticQuirks {
/** Oversized breasts. Increased growth rate, reduced shrink rate. Breasts try to return to oversized state if reduced. */
macromastia: GeneticQuirk | 3;
......
......@@ -89,6 +89,99 @@ interface Map<K, V> {
asArray(): V[];
}
interface ReadonlyMap<K, V> {
// map extensions are defined in `js/extensions/map.extension.js`
// this is a copy of interface Map<K, V> above with modifications to make things read only
/**
* Filters the map object the same way Array.prototype.filter() filters Arrays.
* Returns a new filtered map object.
*/
filter(callback: (value: Readonly<V>, key: Readonly<K>, originalMap: ReadonlyMap<K, V>) => void): ReadonlyMap<K, V>;
/**
* Returns a random key from the Map.
*/
randomKey(): Readonly<K>;
/**
* Returns a random value from the Map.
*/
randomValue(): Readonly<V>;
/**
* Returns a random entry from the Map.
*/
randomEntry(): [Readonly<K>, Readonly<V>];
/**
* Returns a random key/value pair from the Map. Removing it in the process.
* Returns an object with the properties: key and value
* Will return {key: undefined, value: undefined} if the map has no entries
*/
pluck(): {key: Readonly<K>, value: Readonly<V>};
// TODO: figure out how to indicate in typescript that the return type of the callback is the type in the returned array
/** Returns an array mapped using the provided callback. */
map(callback: (value: Readonly<V>, key: Readonly<K>, map: ReadonlyMap<K, V>) => any): ReadonlyArray<any>;
/**
* Returns a key/value object for the first entry in the map where predicate is true, and undefined otherwise.
*
* @param {Function} predicate
* find calls predicate once for each entry of the map, in ascending order, until it finds one where predicate returns true. If such an element is found, find immediately returns a key/value object. Otherwise, find returns undefined.
*
* @returns {{key: Readonly<any>, value: Readonly<any>}|undefined}
*/
find(predicate: (value: Readonly<V>, key: Readonly<K>, map: ReadonlyMap<K, V>) => boolean): {key: Readonly<K>, value: Readonly<V>};
/**
* Returns a key/value object for the entry at the given index.
* Returns undefined if the index is out of range.
* Expensive; cache the result if you need it more than once.
*/
atIndex(index: number): {key: Readonly<K>, value: Readonly<V>};
/**
* Determines whether all the members of an map satisfy the specified test.
*
* @param {Function} predicate
* A function that accepts up to three arguments. The every method calls the predicate function for each entry in the map until the predicate returns a value which is coercible to the Boolean value false, or until the end of the map.
*/
every(predicate: (value: Readonly<V>, key: Readonly<K>, map: ReadonlyMap<K, V>) => boolean): boolean;
/**
* Returns true if at least one member of a map satisfy the specified test.
*
* @param {Function} predicate
* A function that accepts up to three arguments. The some method calls the predicate function for each entry in the map until the predicate returns a value which is coercible to the Boolean value true, or until the end of the map.
*/
some(predicate: (value: Readonly<V>, key: Readonly<K>, map: ReadonlyMap<K, V>) => boolean): boolean;
/**
* Returns an array of the maps values.
* Expensive; Use `Map.prototype.values()` instead if possible.
*/
asArray(): ReadonlyArray<V>;
}
interface Set<T> {
// set extensions are defined in `js/extensions/set.extension.js`
/**
* Returns a value for the entry at the given index.
* Returns undefined if the index is out of range.
* Expensive; cache the result if you need it more than once.
*/
atIndex(index: number): T|undefined;
/**
* Returns an array of the sets values.
* Expensive; Use `Set.prototype.values()` instead if possible.
*/
asArray(): Array<T>;
}
type EnumerablePropertyKey<T extends PropertyKey> = T extends symbol ? never : (T extends number ? string : T);
interface ObjectConstructor {
......
// Type definitions for JSZip 3.1
// Project: http://stuk.github.com/jszip/, https://github.com/stuk/jszip
// Definitions by: mzeiher <https://github.com/mzeiher>, forabi <https://github.com/forabi>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
/// <reference types="node" />
interface JSZipSupport {
arraybuffer: boolean;
uint8array: boolean;
blob: boolean;
nodebuffer: boolean;
}
type Compression = 'STORE' | 'DEFLATE';
/**
* Depends on the compression type. With `STORE` (no compression), these options are ignored. With
* `DEFLATE`, you can give the compression level between 1 (best speed) and 9 (best compression).
*/
interface CompressionOptions {
level: number;
}
interface InputByType {
base64: string;
string: string;
text: string;
binarystring: string;
array: number[];
uint8array: Uint8Array;
arraybuffer: ArrayBuffer;
blob: Blob;
stream: NodeJS.ReadableStream;
}
interface OutputByType {
base64: string;
string: string;
text: string;
binarystring: string;
array: number[];
uint8array: Uint8Array;
arraybuffer: ArrayBuffer;
blob: Blob;
nodebuffer: Buffer;
}
// This private `_data` property on a JSZipObject uses this interface.
// If/when it is made public this should be uncommented.
// interface CompressedObject {
// compressedSize: number;
// uncompressedSize: number;
// crc32: number;
// compression: object;
// compressedContent: string|ArrayBuffer|Uint8Array|Buffer;
// }
type InputFileFormat = InputByType[keyof InputByType] | Promise<InputByType[keyof InputByType]>;
declare namespace JSZip {
type InputType = keyof InputByType;
type OutputType = keyof OutputByType;
interface JSZipMetadata {
percent: number;
currentFile: string | null;
}
type OnUpdateCallback = (metadata: JSZipMetadata) => void;
interface JSZipObject {
name: string;
/**
* Present for files loadded with `loadAsync`. May contain ".." path components that could
* result in a zip-slip attack. See https://snyk.io/research/zip-slip-vulnerability
*/
unsafeOriginalName?: string;
dir: boolean;
date: Date;
comment: string;
/** The UNIX permissions of the file, if any. */
unixPermissions: number | string | null;
/** The UNIX permissions of the file, if any. */
dosPermissions: number | null;
options: JSZipObjectOptions;
/**
* Prepare the content in the asked type.
* @param type the type of the result.
* @param onUpdate a function to call on each internal update.
* @return Promise the promise of the result.
*/
async<T extends OutputType>(type: T, onUpdate?: OnUpdateCallback): Promise<OutputByType[T]>;
nodeStream(type?: 'nodebuffer', onUpdate?: OnUpdateCallback): NodeJS.ReadableStream;
}
interface JSZipFileOptions {
/** Set to `true` if the data is `base64` encoded. For example image data from a `<canvas>` element. Plain text and HTML do not need this option. */
base64?: boolean;
/**
* Set to `true` if the data should be treated as raw content, `false` if this is a text. If `base64` is used,
* this defaults to `true`, if the data is not a `string`, this will be set to `true`.
*/
binary?: boolean;
/**
* The last modification date, defaults to the current date.
*/
date?: Date;
/**
* Sets per file compression. The `compressionOptions` parameter depends on the compression type.
*/
compression?: Compression;
/**
* Sets per file compression level for `DEFLATE` compression.
*/
compressionOptions?: null | CompressionOptions;
comment?: string;
/** Set to `true` if (and only if) the input is a "binary string" and has already been prepared with a `0xFF` mask. */
optimizedBinaryString?: boolean;
/** Set to `true` if folders in the file path should be automatically created, otherwise there will only be virtual folders that represent the path to the file. */
createFolders?: boolean;
/** Set to `true` if this is a directory and content should be ignored. */
dir?: boolean;
/** 6 bits number. The DOS permissions of the file, if any. */
dosPermissions?: number | null;
/**
* 16 bits number. The UNIX permissions of the file, if any.
* Also accepts a `string` representing the octal value: `"644"`, `"755"`, etc.
*/
unixPermissions?: number | string | null;
}
interface JSZipObjectOptions {
compression: Compression;
}
interface JSZipGeneratorOptions<T extends OutputType = OutputType> {
/**
* Sets compression option for all entries that have not specified their own `compression` option
*/
compression?: Compression;
/**
* Sets compression level for `DEFLATE` compression.
*/
compressionOptions?: null | CompressionOptions;
type?: T;
comment?: string;
/**
* mime-type for the generated file.
* Useful when you need to generate a file with a different extension, ie: “.ods”.
* @default 'application/zip'
*/
mimeType?: string;
encodeFileName?(filename: string): string;
/** Stream the files and create file descriptors */
streamFiles?: boolean;
/** DOS (default) or UNIX */
platform?: 'DOS' | 'UNIX';
}
interface JSZipLoadOptions {
base64?: boolean;
checkCRC32?: boolean;
optimizedBinaryString?: boolean;
createFolders?: boolean;
decodeFileName?: (bytes: string[] | Uint8Array | Buffer) => string;
}
type DataEventCallback<T> = (dataChunk: T, metadata: JSZipMetadata) => void
type EndEventCallback = () => void
type ErrorEventCallback = (error: Error) => void
interface JSZipStreamHelper<T> {
/**
* Register a listener on an event
*/
on(event: 'data', callback: DataEventCallback<T>): this;
on(event: 'end', callback: EndEventCallback): this;
on(event: 'error', callback: ErrorEventCallback): this;
/**
* Read the whole stream and call a callback with the complete content
*
* @param updateCallback The function called every time the stream updates
* @return A Promise of the full content
*/
accumulate(updateCallback?: (metadata: JSZipMetadata) => void): Promise<T>;
/**
* Resume the stream if the stream is paused. Once resumed, the stream starts sending data events again
*
* @return The current StreamHelper object, for chaining
*/
resume(): this;
/**
* Pause the stream if the stream is running. Once paused, the stream stops sending data events
*
* @return The current StreamHelper object, for chaining
*/
pause(): this;
}
}
interface JSZip {
files: {[key: string]: JSZip.JSZipObject};
/**
* Get a file from the archive
*
* @param Path relative path to file
* @return File matching path, null if no file found
*/
file(path: string): JSZip.JSZipObject | null;
/**
* Get files matching a RegExp from archive
*
* @param path RegExp to match
* @return Return all matching files or an empty array
*/
file(path: RegExp): JSZip.JSZipObject[];
/**
* Add a file to the archive
*
* @param path Relative path to file
* @param data Content of the file
* @param options Optional information about the file
* @return JSZip object
*/
file<T extends JSZip.InputType>(path: string, data: InputByType[T] | Promise<InputByType[T]>, options?: JSZip.JSZipFileOptions): this;
file<T extends JSZip.InputType>(path: string, data: null, options?: JSZip.JSZipFileOptions & { dir: true }): this;
/**
* Returns an new JSZip instance with the given folder as root
*
* @param name Name of the folder
* @return New JSZip object with the given folder as root or null
*/
folder(name: string): JSZip | null;
/**
* Returns new JSZip instances with the matching folders as root
*
* @param name RegExp to match
* @return New array of JSZipFile objects which match the RegExp
*/
folder(name: RegExp): JSZip.JSZipObject[];
/**
* Call a callback function for each entry at this folder level.
*
* @param callback function
*/
forEach(callback: (relativePath: string, file: JSZip.JSZipObject) => void): void;
/**
* Get all files which match the given filter function
*
* @param predicate Filter function
* @return Array of matched elements
*/
filter(predicate: (relativePath: string, file: JSZip.JSZipObject) => boolean): JSZip.JSZipObject[];
/**
* Removes the file or folder from the archive
*
* @param path Relative path of file or folder
* @return Returns the JSZip instance
*/
remove(path: string): JSZip;
/**
* Generates a new archive asynchronously
*
* @param options Optional options for the generator
* @param onUpdate The optional function called on each internal update with the metadata.
* @return The serialized archive
*/
generateAsync<T extends JSZip.OutputType>(options?: JSZip.JSZipGeneratorOptions<T>, onUpdate?: JSZip.OnUpdateCallback): Promise<OutputByType[T]>;
/**
* Generates a new archive asynchronously
*
* @param options Optional options for the generator
* @param onUpdate The optional function called on each internal update with the metadata.
* @return A Node.js `ReadableStream`
*/
generateNodeStream(options?: JSZip.JSZipGeneratorOptions<'nodebuffer'>, onUpdate?: JSZip.OnUpdateCallback): NodeJS.ReadableStream;
/**
* Generates the complete zip file with the internal stream implementation
*
* @param options Optional options for the generator
* @return a StreamHelper
*/
generateInternalStream<T extends JSZip.OutputType>(options?: JSZip.JSZipGeneratorOptions<T>): JSZip.JSZipStreamHelper<OutputByType[T]>;
/**
* Deserialize zip file asynchronously
*
* @param data Serialized zip file
* @param options Options for deserializing
* @return Returns promise
*/
loadAsync(data: InputFileFormat, options?: JSZip.JSZipLoadOptions): Promise<JSZip>;
/**
* Create JSZip instance
*/
new(): this;
(): JSZip;
prototype: JSZip;
support: JSZipSupport;
external: {
Promise: PromiseConstructorLike;
};
version: string;
}
declare var JSZip: JSZip;
......@@ -92,8 +92,7 @@ App.PersonalAttention = {};
/**
* The patching system that replaces the legacy BC.
* Its primary file and instructions are located at `/src/data/patches/patch.js`.
* @see App.Patch.Patches
* @see App.Patch.applyAll
* See {@link App.Patch.Patches} and {@link App.Patch.applyAll}
*/
App.Patch = {};
/**
......@@ -132,8 +131,7 @@ App.UI.View = {};
* While it is depreciated, it should not be removed or modifed as it is used as a patch in the new patching system.
* Its files are stored in `/src/data/backwardsCompatibility/`.
* @deprecated Replaced by `App.Patch.applyAll()`.
* @see App.Patch
* @see App.Patch.applyAll
* See {@link App.Patch} and {@link App.Patch.applyAll}
*/
App.Update = {};
App.Utils = {};
......@@ -141,13 +139,13 @@ App.Utils.Math = {};
/**
* The validation system. This replaces the validation that was done in the legacy BC.
* Its primary file and instructions are located at `/src/data/verification/zVerify.js`.
* @see App.Verify.everything
* See {@link App.Verify.everything}
*/
App.Verify = {};
/**
* Storage for validation instructions.
* These are functions that should be added to one or more instruction set(s) in `App.Verify.instructions`.
* @see App.Verify.instructions
* See {@link App.Verify.instructions}
*/
App.Verify.I = {};
/**
......
......@@ -781,7 +781,7 @@ App.Data.clothes = (new Map())
{
name: "Bangles",
exposure: 3,
fs: {loves: new Set(["FSEgyptianRevivalist"])}
fs: {loves: new Set(["FSEgyptianRevivalist", "FSArabianRevivalist"])}
}
)
.set("clubslut netting",
......@@ -907,6 +907,13 @@ App.Data.clothes = (new Map())
fs: {loves: new Set(["FSBodyPurist", "FSIntellectualDependency"])},
}
)
.set("a nipple bikini",
{
name: "Nipple bikini",
exposure: 3,
fs: {loves: new Set(["FSBodyPurist", "FSIntellectualDependency", "FSAssetExpansionist"])},
}
)
.set("a succubus outfit",
{
name: "Succubus costume",
......
......@@ -69,33 +69,55 @@ globalThis.Job = Object.freeze({
TANK: '@lay in tank'
});
/**
* @enum {string}
*/
/** @enum {FC.PersonalAttention} */
globalThis.PersonalAttention = Object.freeze({
/** @type {FC.PersonalAttention} */
TRADE: 'trading',
/** @type {FC.PersonalAttention} */
WAR: 'warfare',
/** @type {FC.PersonalAttention} */
SLAVING: 'slaving',
/** @type {FC.PersonalAttention} */
ENGINEERING: 'engineering',
/** @type {FC.PersonalAttention} */
MEDICINE: 'medicine',
/** @type {FC.PersonalAttention} */
MAID: 'upkeep',
/** @type {FC.PersonalAttention} */
HACKING: 'hacking',
/** @type {FC.PersonalAttention} */
SUPPORT_HG: 'HG',
/** @type {FC.PersonalAttention} */
WHORING: 'whoring',
/** @type {FC.PersonalAttention} */
BUSINESS: 'business',
/** @type {FC.PersonalAttention} */
SMUGGLING: 'smuggling',
/** @type {FC.PersonalAttention} */
SURVEY: 'defensive survey',
/** @type {FC.PersonalAttention} */
DEVELOPMENT: 'development project',
/** @type {FC.PersonalAttention} */
TECH: 'technical accidents',
/** @type {FC.PersonalAttention} */
FIGHT: 'fighting',
/** @type {FC.PersonalAttention} */
SEX: 'sex',
/** @type {FC.PersonalAttention} */
RELAX: 'rest and relaxation',
/** @type {FC.PersonalAttention} */
PROCLAMATION: 'proclamation',
/** @type {FC.PersonalAttention} */
TRAINING: 'slave training',
/** @type {FC.PersonalAttention} */
IMAGE: 'popularity',
/** @type {FC.PersonalAttention} */
STUDY: 'education',
/** @type {FC.PersonalAttention} */
GED: 'degree',
/** @type {FC.PersonalAttention} */
EDUCATION: 'advanced education',
/** @type {FC.PersonalAttention} */
TEST: 'advanced degree',
});
......@@ -128,20 +150,27 @@ globalThis.Fetish = Object.freeze({
BESTIALITY: "bestiality",
});
/**
* @type {FC.BehavioralFlawFreeze}
* @enum {string}
*/
/** @enum {FC.BehavioralFlaw} */
globalThis.BehavioralFlaw = Object.freeze({
/** @type {FC.BehavioralFlaw} */
NONE: "none",
/** @type {FC.BehavioralFlaw} */
ARROGANT: "arrogant",
/** @type {FC.BehavioralFlaw} */
BITCHY: "bitchy",
/** @type {FC.BehavioralFlaw} */
ODD: "odd",
/** @type {FC.BehavioralFlaw} */
HATESMEN: "hates men",
/** @type {FC.BehavioralFlaw} */
HATESWOMEN: "hates women",
/** @type {FC.BehavioralFlaw} */
GLUTTONOUS: "gluttonous",
/** @type {FC.BehavioralFlaw} */
ANOREXIC: "anorexic",
/** @type {FC.BehavioralFlaw} */
DEVOUT: "devout",
/** @type {FC.BehavioralFlaw} */
LIBERATED: "liberated",
});
......@@ -162,30 +191,47 @@ globalThis.BehavioralQuirk = Object.freeze({
ADVOCATE: "advocate",
});
/**
* @type {FC.SexualFlawFreeze}
* @enum {string}
*/
/** @enum {FC.SexualFlaw} */
globalThis.SexualFlaw = Object.freeze({
/** @type {FC.SexualFlaw} */
NONE: "none",
/** @type {FC.SexualFlaw} */
HATESORAL: "hates oral",
/** @type {FC.SexualFlaw} */
HATESANAL: "hates anal",
/** @type {FC.SexualFlaw} */
HATESPEN: "hates penetration",
/** @type {FC.SexualFlaw} */
SHAMEFAST: "shamefast",
/** @type {FC.SexualFlaw} */
IDEAL: "idealistic",
/** @type {FC.SexualFlaw} */
REPRESSED: "repressed",
/** @type {FC.SexualFlaw} */
APATHETIC: "apathetic",
/** @type {FC.SexualFlaw} */
CRUDE: "crude",
/** @type {FC.SexualFlaw} */
JUDGEMENT: "judgemental",
/** @type {FC.SexualFlaw} */
NEGLECT: "neglectful",
/** @type {FC.SexualFlaw} */
CUMADDICT: "cum addict",
/** @type {FC.SexualFlaw} */
ANALADDICT: "anal addict",
/** @type {FC.SexualFlaw} */
ATTENTION: "attention whore",
/** @type {FC.SexualFlaw} */
BREASTEXP: "breast growth",
/** @type {FC.SexualFlaw} */
ABUSIVE: "abusive",
/** @type {FC.SexualFlaw} */
MALICIOUS: "malicious",
/** @type {FC.SexualFlaw} */
SELFHATING: "self hating",
/** @type {FC.SexualFlaw} */
BREEDER: "breeder",
/** @type {FC.SexualFlaw} */
ANIMALLOVER: "animal lover",
});
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
......@@ -3,8 +3,7 @@
App.Data.defaultGameStateVariables = {
/**
* This is used to hold data during passage transitions.
* The contents of this object are reset near the end of `App.EndWeek.nextWeek()` right before autosaving happens
* @see App.EndWeek.nextWeek
* The contents of this object are reset near the end of {@link App.EndWeek.nextWeek}() right before autosaving happens
* @type {FC.TransitionObject}
*/
temp: {},
......@@ -15,8 +14,7 @@ App.Data.defaultGameStateVariables = {
/**
* Stores the traveled passages since the "Main" passage.
* Gets reset by the main passage.
* @see lastPassage
* @see App.Utils.passageHistoryCleanup
* See {@link lastPassage} and {@link App.Utils.passageHistoryCleanup}
* @type {string[]}
*/
passageHistory: [],
......@@ -27,7 +25,7 @@ App.Data.defaultGameStateVariables = {
commitHash: "",
/**
* @type {number} used for patching
* @see App.Patch.applyAll
* See {@link App.Patch.applyAll}
*/
releaseID: 0,
......@@ -39,20 +37,17 @@ App.Data.defaultGameStateVariables = {
/**
* @readonly
* Each slave and the player gets a genepool record when they are created
* The records stored here are missing default values! Use the `getGenePoolRecord()` function to retreive them
* Do not access this directly. Use `addToGenePool()` to add records
* @see getGenePoolRecord
* @see addToGenePool
* The records stored here are missing default values! Use the {@link getGenePoolRecord}() function to retrieve them
* Do not access this directly. Use {@link addToGenePool}() to add records
* @type {Readonly<{[key: string]: Readonly<Partial<FC.GenePoolRecord>>}>}
*/
genePool: {},
/**
* @readonly
* @type {Readonly<FC.GenePoolRecord>} used by `getGenePoolRecord()` to fill in missing defaults
* @see getGenePoolRecord
* @see addToGenePool
* @type {Readonly<FC.GenePoolRecord>} used by {@link getGenePoolRecord}() to fill in missing defaults
* Also see {@link addToGenePool}
*/
genePoolDefaults: undefined, // new App.Entity.GenePoolRecord(); App.Entity.GenePoolRecord doesn't exist yet...
genePoolDefaults: undefined,
/** @type {Record<FC.HumanID, FC.MissingParentRecord>} */
missingTable: {},
detached: {
......@@ -285,10 +280,11 @@ App.Data.defaultGameStateVariables = {
aiApiUrl: "http://localhost:7860",
aiAutoGen: true,
aiAutoGenFrequency: 10,
aiQueueOverlay: 1,
aiUseRAForEvents: false,
aiCfgScale: 5,
aiTimeoutPerStep: 5,
aiChat: false,
aiChat: 0,
aiChatUrl: "http://localhost:5000/v1/chat/completions",
aiChatTemp: 0.5,
aiChatMinP: 0.05,
......@@ -403,7 +399,7 @@ App.Data.defaultGameStateVariables = {
surnamePCOverride: 0,
surnameScheme: 0,
/** @type {{[key: string]: string}} */
tabChoice: {Main: "all"},
tabChoice: {Main: "penthouse"},
universalRulesAssignsSelfFacility: 0,
universalRulesBirthing: 0,
universalRulesCSec: 0,
......@@ -421,6 +417,7 @@ App.Data.defaultGameStateVariables = {
useSlaveListInPageJSNavigation: 0,
useSlaveSummaryOverviewTab: 0,
useSlaveSummaryTabs: 0,
useSlaveArcologyTab: 1,
useTabs: 0,
verboseDescriptions: 0,
verticalizeArcologyLinks: 0,
......@@ -525,6 +522,11 @@ App.Data.defaultGameStateVariables = {
warned: false,
}
},
// Scenarios
scenarios: {
contraceptivesBan: 0,
}
};
// Corp data
......@@ -655,7 +657,9 @@ App.Data.resetOnNGPlus = {
sexualOpenness: 0,
bestialityOpenness: 0,
gumjobFetishism: 0,
gumjobFetishismSMR: 0
gumjobFetishismSMR: 0,
contraceptivesBan: 0
},
FCTV: {
......@@ -735,6 +739,7 @@ App.Data.resetOnNGPlus = {
econRate: 0,
/** @type {FC.ArcologyState[]} */
arcologies: [],
/* These variables exist, so skill changes during the week will only influence prizes in the next week */
HackingSkillMultiplier: 0,
upgradeMultiplierArcology: 0,
upgradeMultiplierMedicine: 0,
......@@ -753,16 +758,9 @@ App.Data.resetOnNGPlus = {
raConfirmDelete: 1,
addButtonsToSlaveLinks: true,
/** @type {{ID: FC.HumanID, type: "adoptFollowUp" | "butthole" | "feminization" | "futa" | "MILF" | "orientation" | "ugly"}[]} */
RECheckInIDs: [],
deathIDs: {
health: [],
overdose: [],
age: []
},
burstIDs: [],
birthIDs: [],
induceIDs: [],
/** @type {FC.Zeroable<FC.SlaveState>} */
activeSlave: 0,
/** @type {FC.Zeroable<FC.InfantState>} */
......@@ -1111,6 +1109,7 @@ App.Data.resetOnNGPlus = {
smartVibes: 0,
smartVaginalAttachments: 0,
smartStrapon: 0,
chastity: 1,
},
},
dairyPiping: 0,
......@@ -1130,6 +1129,8 @@ App.Data.resetOnNGPlus = {
bodyswapAnnounced: 0,
surnamesForbidden: 0,
menstruation: 0,
menstruationKnown: 0,
pregnancyKnown: 0,
FCNNstation: 0,
swanSong: 0,
failedElite: 0,
......@@ -1195,7 +1196,7 @@ App.Data.resetOnNGPlus = {
},
weddingPlanned: 0,
/** @type {{task:string, slaves?:Array<{ID:number, objective:string}>}} */
/** @type {{task: FC.PersonalAttention, slaves?: Array<{ID: FC.HumanID, objective: FC.PersonalAttentionTrainingObjective}>}} */
personalAttention: {task: PersonalAttention.SEX},
HeadGirlID: 0,
HGTimeInGrade: 0,
......@@ -1378,7 +1379,7 @@ App.Data.resetOnNGPlus = {
personalArms: 0,
/**
* @type {Map<string, (Array<FC.TrinketData>|number)>}
* @type {Map<string, FC.TrinketData>}
*/
trinkets: new Map([]),
SPcost: 1000,
......
......@@ -637,6 +637,15 @@ App.Data.Policies.Selection = {
}
}
],
"policies.contraceptivesBan": [ // will change in the future with authority/favor rework
{
title: "Contraceptives Ban",
text: `will ban contraceptives from being sold.`,
activatedText: `contraceptives are no longer commercially available.`,
activatedNote: `Will greatly increase the prices of abortions and chastity devices. Try not to have any accidents!`, // This will be changed later once this is available outside the scenario start
hide: {button: 1, ifActivated: 0}, // Only appears under a specific scenario start
}
],
},
EducationPolicies: {
"TSS.subsidize": [
......
......@@ -388,6 +388,7 @@ App.Data.SlaveSummary = {
"a slutty schutzstaffel uniform": "Slutty Schutzstaffel uniform.",
"a sports bra": "Sports bra.",
"a string bikini": "String bikini.",
"a nipple bikini": "Nipple bikini.",
"a striped bra": "Striped bra.",
"a succubus outfit": "Succubus outfit.",
"a sweater and cutoffs": "Jean shorts, sweater.",
......
......@@ -31,6 +31,7 @@ App.Art.cacheArtData = function() {
App.Data.Art.Vector = makeCache(document.querySelectorAll('[tags="Twine.image"][name^="Art_Vector"]:not([name^="Art_Vector_Revamp"])'));
App.Data.Art.VectorRevamp = makeCache(document.querySelectorAll('[tags="Twine.image"][name^="Art_Vector_Revamp"]'));
App.Data.Art.OtherSVG = makeCache(document.querySelectorAll('[tags="Twine.image"][name="world"]'));
};
App.Art.URLIDMatcher = /url\(#(.*)\)/g;
......
// The smaller, the more global
App.Data.World.TravelFrictionExponent = -0.6;
// The smaller, the more are large nationalities downscaled
App.Data.World.PopScaleFactor = 23;
/**
* @typedef {Record<number, number>} gridPoint
* Not intended for manual handling, use one of the functions below to get the data behind it.
*
* If gridPoint[0] >= 0: Point in the world data grids. (X, Y)
* Otherwise : Encodes a small territory
*/
/**
* @returns {Generator<gridPoint, void, *>}
*/
App.Data.World.gridPoints = function*() {
for (let x = 0; x < App.Data.World.GridDimensions.width; x++) {
for (let y = 0; y < App.Data.World.GridDimensions.height; y++) {
yield [x, y];
}
}
for (let i = 0; i < App.Data.World.SmallTerritories.length; i++) {
yield [-1, i];
}
};
/**
* Turn a grid cell into a global coordinate.
* @param {gridPoint} p
* @returns {[number, number]} Latitude, Longitude
*/
App.Data.World.gridPointToCoordinate = function(p) {
if (p[0] === -1) {
const st = App.Data.World.SmallTerritories[p[1]];
return [st[2], st[3]];
}
const width = App.Data.World.GridDimensions.width;
const height = App.Data.World.GridDimensions.height;
const lon = p[0] / App.Data.World.GridDimensions.width * 360 - 180;
const lat = p[1] / App.Data.World.GridDimensions.height * -180 + 90;
const lonCell = 360 / width;
const latCell = 180 / height;
return [lat - latCell / 2, lon + lonCell / 2];
};
/**
* Return the grid cell that encloses the given coordinates
* @param {number} lat
* @param {number} lon
* @returns {gridPoint}
*/
App.Data.World.coordinateToGridPoint = function(lat, lon) {
const width = App.Data.World.GridDimensions.width;
const height = App.Data.World.GridDimensions.height;
const lonCell = 360 / width;
const latCell = 180 / height;
const x = Math.floor((lon + 180) / lonCell);
const y = Math.floor((-lat + 90) / latCell);
return [x, y];
};
/**
* @param {gridPoint} p
* @returns {number}
*/
App.Data.World.populationAt = function(p) {
if (p[0] === -1) {
const st = App.Data.World.SmallTerritories[p[1]];
return st[1];
}
return App.Data.World.PopGrid[p[1]][p[0]];
};
/**
* @param {gridPoint} p
* @returns {number}
*/
App.Data.World.nationIdAt = function(p) {
if (p[0] === -1) {
const st = App.Data.World.SmallTerritories[p[1]];
return st[0];
}
return App.Data.World.NationGrid[p[1]][p[0]];
};
/**
* @param {gridPoint} p
* @returns {string}
*/
App.Data.World.nationAt = function(p) {
const nationId = App.Data.World.nationIdAt(p);
return App.Data.World.Nations[nationId] || "Stateless";
};
......@@ -23,7 +23,7 @@ App.Loader = (function() {
* To make sure the scripts are loaded series, keep a queue of scripts to be loaded and only load the next once the
* previous one is finished.
*
* @see nextScript
* see {@link nextScript}
*
* @type {Array<()=>void>}
*/
......@@ -191,7 +191,13 @@ App.Modding = (function() {
* @returns {string[]} modList
*/
function loadModList() {
return SugarCube.storage.get("modList") || [];
try {
return SugarCube.storage.get("modList") || [];
} catch (e) {
console.error(e);
console.error(`Failed to get modlist from SugarCube storage`);
return [];
}
}
return {
......
// This provides some helpful functions from the array prototype to the set prototype
// TODO:@franklygeorge implement as many of the extensions from map.extensions.js as makes sense for sets
Object.defineProperty(Set.prototype, "atIndex", {
/**
* Returns a value for the entry at the given index.
* Returns undefined if the index is out of range.
* Expensive; cache the result if you need it more than once.
* @param {number} index
*
* @returns {any}
*/
value: function(index) {
if (index + 1 > this.size) { return undefined; }
return [...this][index];
},
enumerable: false,
configurable: true,
writable: true
});
Object.defineProperty(Set.prototype, "asArray", {
/**
* Returns an array of the sets values.
* Expensive; Use `Set.prototype.values()` instead if possible.
*/
value: function() {
return [...this];
},
enumerable: false,
configurable: true,
writable: true
});
App.Medicine.Surgery.Reactions.AddBalls = class extends App.Medicine.Surgery.SimpleReaction {
/**
* @param {FC.SlaveState} slave
* @param {Partial<FC.SlaveState>} diff
* @returns {reactionResult}
*/
reaction(slave, diff) {
const reaction = super.reaction(slave, diff);
const {He, he, His, his, him, himself} = getPronouns(slave);
......@@ -44,6 +49,11 @@ App.Medicine.Surgery.Reactions.AddBalls = class extends App.Medicine.Surgery.Sim
}
};
App.Medicine.Surgery.Reactions.AddAnimalBalls = class extends App.Medicine.Surgery.SimpleReaction {
/**
* @param {FC.SlaveState} slave
* @param {Partial<FC.SlaveState>} diff
* @returns {reactionResult}
*/
reaction(slave, diff) {
const reaction = super.reaction(slave, diff);
const {He, he, His, his, him, himself} = getPronouns(slave);
......
App.Medicine.Surgery.Reactions.AddDick = class extends App.Medicine.Surgery.SimpleReaction {
/**
* @param {FC.SlaveState} slave
* @param {Partial<FC.SlaveState>} diff
* @returns {reactionResult}
*/
reaction(slave, diff) {
const reaction = super.reaction(slave, diff);
const {He, he, His, his, him} = getPronouns(slave);
......
App.Medicine.Surgery.Reactions.AddForeskin = class extends App.Medicine.Surgery.SimpleReaction {
/**
* @param {FC.SlaveState} slave
* @param {Partial<FC.SlaveState>} diff
* @returns {reactionResult}
*/
reaction(slave, diff) {
const reaction = super.reaction(slave, diff);
const {He, he, His, his, him} = getPronouns(slave);
......
App.Medicine.Surgery.Reactions.AddOvaries = class extends App.Medicine.Surgery.SimpleReaction {
/**
* @param {FC.SlaveState} slave
* @param {Partial<FC.SlaveState>} diff
* @returns {reactionResult}
*/
reaction(slave, diff) {
const reaction = super.reaction(slave, diff);
const {He, he, his, him} = getPronouns(slave);
......@@ -29,6 +34,11 @@ App.Medicine.Surgery.Reactions.AddOvaries = class extends App.Medicine.Surgery.S
}
};
App.Medicine.Surgery.Reactions.AddAnimalOvaries = class extends App.Medicine.Surgery.SimpleReaction {
/**
* @param {FC.SlaveState} slave
* @param {Partial<FC.SlaveState>} diff
* @returns {reactionResult}
*/
reaction(slave, diff) {
const reaction = super.reaction(slave, diff);
const {He, he, his, him} = getPronouns(slave);
......
App.Medicine.Surgery.Reactions.AddProstate = class extends App.Medicine.Surgery.SimpleReaction {
/**
* @param {FC.SlaveState} slave
* @param {Partial<FC.SlaveState>} diff
* @returns {reactionResult}
*/
reaction(slave, diff) {
const reaction = super.reaction(slave, diff);
const {He, he, His, his, him, himself} = getPronouns(slave);
......