123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- /// <reference path="../../World/Classes/Rulebook.ts" />
- /// <reference path="../../World/Classes/Rule.ts" />
- /// <reference path="Say/OneOf.ts" />
- /// <reference path="Say/SayImage.ts" />
- interface Printable {
- getPrintedName () : string;
- }
- interface PrintableElement {
- getPrintedElement () : Array<Element>;
- }
- interface SayNoun {
- say : Say;
- noun : any;
- }
- class SayableObject {}
- class Say {
- // TODO: Separate own sequence from processing queue. This way a Say with functions/other says can be reutilized with fresh values.
- public sequence : Array <Object> = [];
- public skipbreaks : boolean = false;
- public static LINE_BREAK : Object = new SayableObject();
- public static CONDITIONAL_LINE_BREAK : Object = new SayableObject();
- public static PARAGRAPH_BREAK : Object = new SayableObject();
- public static RUN_PARAGRAPH : Object = new SayableObject();
- public static RUN_PARAGRAPH_OFF : Object = new SayableObject();
- public static CENTERED : Object = new SayableObject();
- public static b : Object = new SayableObject();
- public static DO_PARAGRAPH_BREAK = new SayableObject();
- public static DO_LINE_BREAK = new SayableObject();
- public static COCK = new SayableObject();
- public static PUSSY = new SayableObject();
- private centered : boolean = false;
- public static Action (a : any) {
- return new SayAction(a);
- }
- public static Bold (a : any) {
- return new SayBold(a);
- }
- public static Mention (target : Thing, uppercase = true) : Array<any> {
- if (target == WorldState.player) {
- return [new SayYou(uppercase)];
- } else {
- return [new SayThe(uppercase), target];
- }
- }
- public static YouThem (target : Thing, uppercase = true) {
- return Say.Mention(target, uppercase);
- }
- public static YourTheir (target : Thing, uppercase = true) {
- if (target == WorldState.player) {
- return [new SayYour(uppercase)];
- } else {
- return [new SayHisHersIts(target, uppercase)];
- }
- }
- public static Article (target : Thing, uppercase = true) {
- let arr = [];
- if (target.isUnique()) {
- arr.push(new SayThe(uppercase));
- } else {
- arr.push(new SayAn(uppercase));
- }
- arr.push(target);
- return arr;
- }
- /**
- * He, She, It
- * @param target
- * @param uppercase
- * @constructor
- */
- public static Subject (target : Thing, uppercase = true) {
- return new SayHeSheIt(target, uppercase);
- }
- /**
- * Him, Her, It
- * @param target
- * @param uppercase
- * @constructor
- */
- public static Object (target : Thing, uppercase = true) {
- return new SayHimHerIt(target, uppercase);
- }
- /**
- * His, Hers, Its
- * @param target
- * @param uppercase
- * @constructor
- */
- public static Possessive (target : Thing, uppercase = true) {
- return new SayHisHersIts(target, uppercase);
- }
- public static Speak (speaker : Thing | string, ...message : Array<any>) {
- if (typeof speaker == "string") {
- return [new SayBold(speaker, ": "), ...message];
- } else {
- return [new SayBold(...Say.YouThem(speaker), ": "), ...message];
- }
- }
- public constructor (...objs) {
- this.add(...objs);
- }
- public add (...objs : Array<Say | OneOf | Object | Printable | string | number | String | ((say : Say) => string)>) {
- for (let i = 0; i < objs.length; i++) {
- if (Array.isArray(objs[i])) {
- this.sequence.push(...(<Array<any>> objs[i]));
- } else {
- this.sequence.push(objs[i]);
- }
- }
- return this;
- }
- public remove (...objs) {
- for (let i = 0; i < objs.length; i++) {
- let index = this.sequence.indexOf(objs[i]);
- if (index >= 0) {
- this.sequence.splice(index, 1);
- }
- }
- }
- public isEmpty () {
- return this.sequence.length < 1;
- }
- public paragraphs : Array<Array<Element | Text>>;
- public currentParagraph : Array<Element | Text>;
- public sequenceRunner : number;
- // TODO: Create a single function to get the element of anything
- public async getTextOf (index : number, seq : any) : Promise<string> {
- let elements = await this.getElementFor(index, seq);
- let div = document.createElement("div");
- for (let i = 0; i < elements.length; i++) {
- if (typeof elements[i] != "number") {
- div.appendChild(elements[i]);
- }
- }
- return div.innerText;
- }
- public doLineBreak (noDouble : boolean) {
- if (this.currentParagraph.length > 0 && !this.skipbreaks) {
- if (noDouble) {
- let lastElement = this.currentParagraph[this.currentParagraph.length - 1];
- if (lastElement != undefined && lastElement instanceof Element && lastElement.tagName == "BR") {
- return;
- }
- }
- let br = document.createElement("br");
- br.classList.add("linebreak");
- let ti = document.createElement("span");
- ti.classList.add("textIndenter");
- this.currentParagraph.push(br, ti);
- }
- }
- public doParagraphBreak () {
- if (this.currentParagraph.length > 0 && !this.skipbreaks) {
- this.paragraphs.push(this.currentParagraph);
- this.currentParagraph = [];
- }
- }
- public async getParagraphs () : Promise<Array<Array<Element|Text>>> {
- this.paragraphs = [];
- this.currentParagraph = [];
- this.skipbreaks = false;
- for (this.sequenceRunner = 0; this.sequenceRunner < this.sequence.length; this.sequenceRunner++) {
- let seq = this.sequence[this.sequenceRunner];
- if (seq instanceof OneOf) {
- seq = seq.getOne();
- }
- if (seq == Say.CENTERED) {
- this.setCentered(true);
- } else if (seq == Say.b) {
- let boldObjects = [];
- for (let i = this.sequenceRunner + 1; i < this.sequence.length; i++) {
- let candidate = this.sequenceRunner[i];
- if (candidate == Say.b) {
- this.sequence.splice(i, 1);
- break;
- } else {
- boldObjects.push(this.sequence.splice(i, 1));
- }
- }
- if (boldObjects.length > 0) {
- let bold = new SayBold(...boldObjects);
- this.sequence.splice(this.sequenceRunner + 1, 0, bold);
- }
- } else if (seq == Say.COCK) {
- if (HumanoidPenis != undefined) {
- let cock = HumanoidPenis.getSynonym();
- this.currentParagraph.push(document.createTextNode(cock))
- }
- } else if (seq == Say.PUSSY) {
- if (HumanoidVagina != undefined) {
- let vagina = HumanoidVagina.getSynonym();
- this.currentParagraph.push(document.createTextNode(vagina))
- }
- } else if (seq == Say.LINE_BREAK || seq == Say.CONDITIONAL_LINE_BREAK) {
- this.doLineBreak(seq == Say.CONDITIONAL_LINE_BREAK);
- } else if (seq == Say.PARAGRAPH_BREAK) {
- this.doParagraphBreak();
- } else if (seq == Say.RUN_PARAGRAPH) {
- this.skipbreaks = true;
- } else if (seq == Say.RUN_PARAGRAPH_OFF) {
- this.skipbreaks = false;
- } else if (typeof seq == "function") {
- // not a function, but a class
- if (seq.prototype != undefined) {
- this.currentParagraph.push(document.createTextNode(" " + seq.name + " "));
- } else {
- let fObj = (<(s: Say) => any>seq)(this);
- if (Array.isArray(fObj)) {
- for (let k = fObj.length - 1; k >= 0; k--) {
- this.sequence.splice(this.sequenceRunner + 1, 0, fObj[k]);
- }
- } else if (fObj != undefined) {
- this.sequence.splice(this.sequenceRunner + 1, 0, fObj);
- }
- this.sequence.splice(this.sequenceRunner, 1);
- this.sequenceRunner--;
- }
- } else if (seq.constructor == this.constructor) {
- for (let k = (<Say> seq).sequence.length - 1; k >= 0; k--) {
- this.sequence.splice(this.sequenceRunner + 1, 0, (<Say> seq).sequence[k]);
- }
- this.sequence.splice(this.sequenceRunner, 1);
- this.sequenceRunner--;
- } else if (seq != undefined) {
- let elements = await this.getElementFor(this.sequenceRunner, seq);
- for (let i = 0; i < elements.length; i++) {
- if (elements[i] === Say.DO_LINE_BREAK) {
- this.doLineBreak(false);
- } else if (elements[i] === Say.DO_PARAGRAPH_BREAK) {
- this.doParagraphBreak();
- } else {
- this.currentParagraph.push(elements[i]);
- }
- }
- }
- }
- // TODO: Remove line break + text indenter if they are the last in the say
- if (this.currentParagraph.length > 0) {
- this.paragraphs.push(this.currentParagraph);
- }
- return this.paragraphs;
- }
- /**
- * Lord Have mercy, I wish to never have to debug this piece of god.
- * @param {number} index
- * @param {Say | OneOf | Object | Printable | string | number | ((say: Say) => string) | ((say: Say) => Promise<string>) | Element | Text} obj
- * @returns {Promise<Array<Element | Text>>}
- */
- public async getElementFor (index : number, obj : Say | OneOf | Object | Printable | string | number | String | ((say : Say) => string) | ((say : Say) => Promise<string>) | Element | Text) : Promise<Array<Element|Text>> {
- if (obj instanceof Promise) {
- obj = await obj;
- }
- if (typeof obj == "string" || obj instanceof String) {
- return [document.createTextNode(<string> obj)];
- } else if (typeof obj == "number" || obj instanceof Number) {
- return [document.createTextNode((parseFloat((<number> obj).toFixed(2))/1).toString())];
- } else if (typeof obj == "function") {
- let elements = await this.getElementFor(-1, (<any> obj)(this));
- return elements;
- } else if (obj instanceof SayImage) {
- return [obj.getImageElement()];
- } else if (obj instanceof SayLeftRight) {
- return (await obj.getPureElements());
- } else if (obj instanceof Say) {
- let elements = await obj.getPureElements(this);
- return elements;
- } else if (this.isProperElement(obj)) {
- return [<Element> obj];
- } else if (obj instanceof Object) {
- let elements = await this.printName(obj);
- return elements;
- }
- }
- public async getPureElements (say? : Say) : Promise<Array<Element | Text>> {
- let paragraphs = await this.getParagraphs();
- return paragraphs.length == 1 ? paragraphs[0] : Array.prototype.concat.apply([], paragraphs);
- }
- public setCentered (bool : boolean) {
- this.centered = bool;
- }
- public async getHTML (tagName : string, classList : Array<string>, singleParagraph? : boolean) : Promise<Array<HTMLElement>> {
- let paragraphs = await this.getParagraphs();
- // Reduce to single paragraph
- if (singleParagraph == true && paragraphs.length > 1) {
- paragraphs = [Array.prototype.concat.apply([], paragraphs)];
- }
- let elements = [];
- for (let i = 0, paragraph = paragraphs[i]; paragraph != undefined; paragraph = paragraphs[++i]) {
- let parent = <HTMLElement> document.createElement(tagName);
- if (classList.length > 0) {
- parent.classList.add(...classList);
- }
- for (let k = 0, ele = paragraph[k]; ele!= undefined; ele = paragraph[++k]) {
- parent.appendChild(ele);
- }
- elements.push(parent);
- if (this.centered) {
- parent.classList.add("centered");
- }
- }
- return elements;
- }
- public getHTMLContent () : Promise<Array<HTMLElement>> {
- return this.getHTML("p", ["content"]);
- }
- public isProperElement (o) : boolean {
- return (
- typeof Node === "object" ? o instanceof Node :
- o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string"
- ) || (
- typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
- o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName==="string"
- );
- }
- public static beforePrinting = new Rulebook<any>("Before printing the name of something");
- public static printing = new Rulebook<any>("Printing the name of something");
- public static afterPrinting = new Rulebook<any>("After printing the name of something");
- public currentNoun : any;
- public currentNounElements : Array<Element | Text>;
- public async printName (thing : any) : Promise<Array<Element | Text>> {
- this.currentNoun = thing;
- this.currentNounElements = [];
- let before = Say.beforePrinting.execute({noun : this});
- await before;
- let print = Say.printing.execute({noun : this});
- await print;
- let after = Say.afterPrinting.execute({noun : this});
- await after;
- return this.currentNounElements;
- }
- public static hisHersIts (target : Thing, startOfSentence? : boolean) {
- return new SayHisHersIts(target);
- // let result : String;
- // if (target == WorldState.player) {
- // result = "your";
- // } else if (target instanceof Person) {
- // // TODO: Figure out whether target is male or female
- // result = "his";
- // } else {
- // result = "its";
- // }
- // if (startOfSentence == true) {
- // result = result.charAt(0).toUpperCase() + result.substr(1, result.length -1);
- // }
- // return result;
- }
- }
- Say.printing.addRule(new Rule({
- name : "Printing the name of a Printable Element",
- firstPriority : Rule.PRIORITY_LOW,
- code : (rulebook : RulebookRunner<any>) => {
- let say = <Say> rulebook.noun;
- if ((<any> say.currentNoun).getPrintedElement) {
- say.currentNounElements.push(...(<PrintableElement> say.currentNoun).getPrintedElement());
- return true; // We only want to print something once, so return true to stop others from running
- }
- }
- }));
- Say.printing.addRule(new Rule({
- name : "Printing the name of a Printable",
- firstPriority : Rule.PRIORITY_LOW,
- code : (rulebook : RulebookRunner<any>) => {
- let say = <Say> rulebook.noun;
- if ((<any> say.currentNoun).getPrintedName) {
- let thingEle = document.createTextNode(
- (<Printable> say.currentNoun).getPrintedName()
- );
- say.currentNounElements.push(thingEle);
- return true; // We only want to print something once, so return true to stop others from running
- }
- }
- }));
- Say.printing.addRule(new Rule({
- name : "Printing the name of an unknown object",
- firstPriority : Rule.PRIORITY_LOWEST,
- priority : Rule.PRIORITY_LOWEST,
- code : (rulebook : RulebookRunner<any>) => {
- let say = <Say> rulebook.noun;
- if ((<any> say.currentNoun).getPrintedName) {
- say.currentNounElements.push(
- (document.createTextNode((<Object> say.currentNoun).toString()))
- );
- return true; // We only want to print something once, so return true to stop others from running
- }
- }
- }));
- // var msg = new Say ("Hello! Welcome to The Obelisk! This is a game with ", johnTheOgre, " so you must be careful!");
- //
- // var otherSay = new Say (msg, "Will have to learn how to handle dots.");
|