SexStats.ts 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. module CharacterCreation {
  2. interface rangeOptions {
  3. label? : string;
  4. showValue? : boolean;
  5. onChange : (value : number, labelValue : Text, input : HTMLInputElement) => void;
  6. minValue : number;
  7. maxValue : number;
  8. leftLabel? : string;
  9. rightLabel? : string;
  10. topLabel? : string;
  11. value : number;
  12. step : number;
  13. }
  14. function createRange (options : rangeOptions) {
  15. let valueNode = document.createTextNode(String(options.value));
  16. let div = document.createElement("div");
  17. div.classList.add("ccOption");
  18. if (options.topLabel != undefined) {
  19. let topLabel = document.createElement("div");
  20. topLabel.classList.add("ccOptionTopLabel");
  21. topLabel.appendChild(document.createTextNode(options.topLabel + ":"));
  22. div.appendChild(topLabel);
  23. }
  24. let label = document.createElement("div");
  25. if (options.showValue != false) {
  26. label.classList.add("rangeValue");
  27. if (options.label != undefined) {
  28. let b = document.createElement("b");
  29. b.appendChild(document.createTextNode(options.label + ": "));
  30. label.appendChild(b);
  31. }
  32. label.appendChild(valueNode);
  33. }
  34. let input = <HTMLInputElement> document.createElement("input");
  35. input.classList.add("ccRange");
  36. input.type = "range";
  37. input.min = options.minValue.toString();
  38. input.max = options.maxValue.toString();
  39. input.step = options.step.toString();
  40. input.value = options.value.toString();
  41. let onChange = () => {
  42. valueNode.nodeValue = input.value;
  43. options.onChange(Number(input.value), valueNode, input);
  44. }
  45. input.addEventListener("change", onChange);
  46. let leftButton = document.createElement("a");
  47. leftButton.classList.add("ccButton");
  48. leftButton.addEventListener("click", () => {
  49. input.value = String(Number(input.value) - options.step);
  50. onChange();
  51. });
  52. Controls.KeyHandler.applyCode(leftButton, Controls.KeyHandler.getFirstKeyCode());
  53. if (options.leftLabel != undefined) {
  54. leftButton.appendChild(document.createTextNode(options.leftLabel));
  55. }
  56. let rightButton = document.createElement("a");
  57. rightButton.classList.add("ccButton");
  58. rightButton.addEventListener("click", () => {
  59. input.value = String(Number(input.value) + options.step);
  60. onChange();
  61. });
  62. Controls.KeyHandler.applyCode(rightButton, Controls.KeyHandler.getFirstKeyCode());;
  63. if (options.rightLabel != undefined) {
  64. rightButton.appendChild(document.createTextNode(options.rightLabel));
  65. }
  66. div.appendChild(leftButton);
  67. div.appendChild(input);
  68. div.appendChild(rightButton);
  69. div.appendChild(label);
  70. onChange();
  71. return div;
  72. }
  73. export let CCSexStats = CharacterCreation.rulebook.createAndAddRule({
  74. name : "Character Creation - Sex and Stats",
  75. firstPriority : Rule.PRIORITY_HIGH,
  76. priority: Rule.PRIORITY_HIGH,
  77. code : () => {
  78. Elements.startMenu();
  79. let ccDiv = document.createElement("div");
  80. ccDiv.id = "characterCreation";
  81. let ccLeft = document.createElement("div");
  82. ccLeft.id = "ccLeft";
  83. ccDiv.appendChild(ccLeft);
  84. let ccRight = document.createElement("div");
  85. ccRight.id = "ccRight";
  86. ccDiv.appendChild(ccRight);
  87. let onChange = () => {
  88. (new Say(WorldState.player.description)).getHTMLContent().then((value => {
  89. while (ccRight.firstChild) ccRight.removeChild(ccRight.firstChild);
  90. value.forEach(val => {
  91. ccRight.appendChild(val);
  92. });
  93. }));
  94. };
  95. ccLeft.appendChild(createRange({
  96. minValue : 0, maxValue : 1, step: 1, value : 0, leftLabel : "Male", rightLabel : "Female", topLabel : "Sex",
  97. onChange : (value : number, labelValue : Text, input : HTMLInputElement) => {
  98. labelValue.nodeValue = (value == 0 ? "Male" : "Female");
  99. (<Humanoid> WorldState.player).removeGenderedParts();
  100. if (value == 0) {
  101. (<Humanoid> WorldState.player).addMaleParts();
  102. } else {
  103. (<Humanoid> WorldState.player).addFemaleParts();
  104. }
  105. // Some stats become different whether te player is male or female, so we have to update them all.
  106. let otherInputs = ccDiv.getElementsByTagName("input");
  107. for (let i = 0; i < otherInputs.length; i++) {
  108. let otherInput = otherInputs[i];
  109. if (otherInput != input) {
  110. otherInput.dispatchEvent(new Event("change"));
  111. }
  112. }
  113. onChange();
  114. }
  115. }));
  116. ccLeft.appendChild(createRange({
  117. minValue : 0, maxValue : 4, step: 1, value : 2, leftLabel : "Masculine", rightLabel : "Feminine", topLabel : "Gender",
  118. onChange : (value : number, labelValue : Text) => {
  119. let names = ["Masculine", "Somewhat masculine", "Androgynous", "Somewhat feminine", "Feminine"];
  120. labelValue.nodeValue = names[value];
  121. let player = (<Humanoid> WorldState.player);
  122. let intendedValue : number;
  123. if (player.isMale()) {
  124. let values = [10, 25, 50, 55, 60];
  125. intendedValue = values[value];
  126. } else {
  127. let values = [35, 40, 50, 65, 75];
  128. intendedValue = values[value];
  129. }
  130. (<Humanoid> WorldState.player).setGenderValue(intendedValue);
  131. WorldState.player.setStat(Attributes.GenderIdentity, intendedValue);
  132. onChange();
  133. }
  134. }));
  135. let statsHeader = document.createElement("div");
  136. ccLeft.appendChild(statsHeader);
  137. statsHeader.classList.add("ccHeader");
  138. statsHeader.appendChild(document.createTextNode("Stats ("));
  139. let maxStats = 12;
  140. let statsRemaining = document.createTextNode("4 points remaining");
  141. statsHeader.appendChild(statsRemaining);
  142. statsHeader.appendChild(document.createTextNode(")"));
  143. let setStat = (attr : Attribute, value : number, input : HTMLInputElement) => {
  144. WorldState.player.setStat(attr, value);
  145. let remaining = maxStats
  146. - WorldState.player.getStat(Attributes.Strength)
  147. - WorldState.player.getStat(Attributes.Agility)
  148. - WorldState.player.getStat(Attributes.Intelligence)
  149. - WorldState.player.getStat(Attributes.Charm);
  150. if (remaining < 0) {
  151. value += remaining;
  152. remaining = 0;
  153. input.value = value.toString();
  154. input.dispatchEvent(new Event("change"));
  155. return;
  156. }
  157. statsRemaining.nodeValue = (remaining == 0 ? "Done" :
  158. remaining > 1 ? remaining.toString() + " points remaining" :
  159. remaining.toString() + " point remaining");
  160. };
  161. ccLeft.appendChild(createRange({
  162. minValue : 1, maxValue : 5, step: 1, value : 2, leftLabel : "-", rightLabel : "+", topLabel : "Strength",
  163. onChange : (value : number, labelValue : Text, input : HTMLInputElement) => {
  164. setStat(Attributes.Strength, value, input);
  165. onChange();
  166. }
  167. }));
  168. ccLeft.appendChild(createRange({
  169. minValue : 1, maxValue : 5, step: 1, value : 2, leftLabel : "-", rightLabel : "+", topLabel : "Agility",
  170. onChange : (value : number, labelValue : Text, input : HTMLInputElement) => {
  171. setStat(Attributes.Agility, value, input);
  172. onChange();
  173. }
  174. }));
  175. ccLeft.appendChild(createRange({
  176. minValue : 1, maxValue : 5, step: 1, value : 2, leftLabel : "-", rightLabel : "+", topLabel : "Charm",
  177. onChange : (value : number, labelValue : Text, input : HTMLInputElement) => {
  178. setStat(Attributes.Charm, value, input);
  179. onChange();
  180. }
  181. }));
  182. ccLeft.appendChild(createRange({
  183. minValue : 1, maxValue : 5, step: 1, value : 2, leftLabel : "-", rightLabel : "+", topLabel : "Intelligence",
  184. onChange : (value : number, labelValue : Text, input : HTMLInputElement) => {
  185. setStat(Attributes.Intelligence, value, input);
  186. onChange();
  187. }
  188. }));
  189. let creationDone = new Promise((resolve) => {
  190. (new Say("Confirm")).getHTML("p", ["choice"]).then(elementArray => {
  191. elementArray[0].addEventListener("click", () => {
  192. Elements.endMenu();
  193. resolve();
  194. });
  195. Controls.KeyHandler.applyCode(elementArray[0], Controls.KeyHandler.getSecondKeyCode());
  196. Elements.CurrentTurnHandler.print(elementArray[0]);
  197. });
  198. });
  199. Elements.CurrentTurnHandler.print(ccDiv);
  200. return creationDone;
  201. }
  202. });
  203. // TODO: Pick origin
  204. // TODO: Pick Perks
  205. }