battle.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. /*jslint white: false, maxerr: 999, indent: 2 */
  2. /*jshint multistr:true*/
  3. var fBeforeBattle;
  4. var fBefore;
  5. function getPerceptionRate() {
  6. var perception = 75;
  7. var ratio = player.perception() - (rival.cunning() + rival.Mods.perception);
  8. if (ratio > 0) { perception += ratio / 3; }
  9. else if (ratio < 0) { perception += ratio / 3; }
  10. return perception;
  11. }
  12. function Battle(currrival, auto)
  13. {
  14. rival = currrival;
  15. var pushCount = 0;
  16. var drainCount = 0;
  17. var reflectCount = 0;
  18. var playerDefeated = false;
  19. fBeforeBattle = player.isFemale();
  20. var rnd = 0;
  21. var autoTimer;
  22. var bAuto = auto;
  23. var nAccurateTell;
  24. var sTell;
  25. BattleActions = {
  26. "push":Push,
  27. "drain":Drain,
  28. "reflect":Reflect,
  29. "rest":Rest,
  30. "hesistat":Hesitate,
  31. "flee":Flee
  32. };
  33. var description = "";
  34. var rivalmanlwr = rival.name == "Rival man" || rival.name == "Rival woman" ? rival.name.toLowerCase() : rival.name;
  35. var rivalhe = rival.heshe;
  36. var rivalhim = rival.himher;
  37. if (rival.name == "Rival man" || rival.name == "Rival woman") {
  38. $("#rcwomen").html("Rival's Women: <span id='rival_women'>");
  39. $("#rcchangra").html("Rival's Changra: <span id='rival_changra'>");
  40. } else {
  41. $("#rcwomen").html(rival.name + "'s Women: <span id='rival_women'>");
  42. $("#rcchangra").html(rival.name + "'s Changra: <span id='rival_changra'>");
  43. }
  44. $("#rcwomen").show();
  45. $("#rcchangra").show();
  46. $("#goods").hide();
  47. var nextRivalAction = new RivalAction(rival, player);
  48. $("#output").html(
  49. "<div class='combat-controls'>\
  50. <div id='push_controls' class='combat-button-column'></div>\
  51. <div id='drain_controls' class='combat-button-column'></div>\
  52. <div id='support_controls' class='combat-button-column'></div>\
  53. <div id='victory_button_container'></div>\
  54. </div>\
  55. <div id='combat_feed'>\
  56. <div id='last_action'></div>\
  57. <hr/>\
  58. <div id='changes'></div>\
  59. </div>");
  60. if (!bAuto) {
  61. fillPushColumn();
  62. fillDrainColumn();
  63. fillSupportColumn();
  64. } else {
  65. fillManual();
  66. fillFlee();
  67. }
  68. redraw();
  69. var tell = rivalTell();
  70. $("#last_action").html("<p class='rival-tell'>" + tell + "</p>");
  71. if (bAuto) AutoBattleRound();
  72. function fillPushColumn() {
  73. $("#push_controls").html("<h2>Infuse</h2>");
  74. $.each(AVATAR_TRAITS, function( index, trait ) {
  75. traitName = trait === "orientation" ? "Attraction to &#9794;" : capitalize(trait);
  76. if (player[trait] > 50) {
  77. $("#push_controls").append("<button id='push_" + trait + "' class='btn btn-combat btn-push'>&#955; " + traitName + "</button>");
  78. if (player.changra < 13) {
  79. $("#push_" + trait).attr("disabled","disabled");
  80. } else {
  81. $("#push_" + trait).click(function() { new Round(new Push(trait, player)); });
  82. }
  83. } else {
  84. $("#push_controls").append("<button id='push_" + trait + "' class='btn btn-combat btn-summon-maternal'>&#8756; " + traitName + "</button>");
  85. if (player.changra < 7) {
  86. $("#push_" + trait).attr("disabled","disabled");
  87. } else {
  88. $("#push_" + trait).click(function() { new Round(new Push(trait, player)); });
  89. }
  90. }
  91. });
  92. }
  93. function fillDrainColumn() {
  94. $("#drain_controls").html("<h2>Drain</h2>");
  95. $.each(AVATAR_TRAITS, function(index, trait) {
  96. traitName = switchFemForMascTrait(trait);
  97. if (rival[trait] > 50) {
  98. $("#drain_controls").append("<button id='drain_" + trait + "' class='btn btn-combat btn-summon-paternal'>&#8756; " + traitName + "</button>");
  99. if (player.changra < 6) {
  100. $("#drain_" + trait).attr("disabled","disabled");
  101. } else {
  102. $("#drain_" + trait).click(function() { new Round(new Drain(trait, player)); });
  103. }
  104. }
  105. else{
  106. $("#drain_controls").append("<button id='drain_" + trait + "' class='btn btn-combat btn-drain'>&#978; " + traitName + "</button>");
  107. if (player.changra < 4) {
  108. $("#drain_" + trait).attr("disabled","disabled");
  109. } else {
  110. $("#drain_" + trait).click(function() { new Round(new Drain(trait, player)); });
  111. }
  112. }
  113. });
  114. }
  115. function fillFlee() {
  116. $("#support_controls").append("<button id='flee' class='btn btn-combat btn-support'>Flee</button>");
  117. $("#flee").click(function() { eval("new Round(new Flee(player));"); });
  118. }
  119. function fillManual() {
  120. $("#support_controls").append("<button id='manual' class='btn btn-combat btn-support'>Manual</button>");
  121. $("#manual").click(function() {
  122. clearTimeout(autoTimer);
  123. bAuto = false;
  124. fillPushColumn();
  125. fillDrainColumn();
  126. fillSupportColumn();
  127. });
  128. }
  129. function fillSupportColumn() {
  130. $("#support_controls").html("<h2>Other</h2>");
  131. $.each(["reflect", "rest"], function( index, action ) {
  132. $("#support_controls").append("<button id='" + action + "' class='btn btn-combat btn-support'>" + capitalize(action) + "</button>");
  133. $("#" + action).click(function() { eval("new Round(new " + capitalize(action) + "(player));"); });
  134. });
  135. fillFlee();
  136. $("#reflect").addClass("btn-reflect");
  137. }
  138. function standardChange() { return getRandomInt(7, 13); }
  139. function checkForVictoryButton() {
  140. if (rival["physique"].testes <= 11) {
  141. $("#victory_button_container").empty();
  142. return false;
  143. } else {
  144. $("#victory_button_container").html("<button id='victory_button' class='btn btn-victory'>Claim Her</button>");
  145. $("#victory_button").click(rival,
  146. function(evt) {
  147. clearTimeout(autoTimer);
  148. delete rival.currentAction;
  149. delete player.currentAction;
  150. evt.data.Victory();
  151. //eval("rival.Victory()");
  152. }
  153. );
  154. return true;
  155. }
  156. }
  157. function RivalAction(avatar, opponent) {
  158. this.action = "";
  159. this.trait = "";
  160. this.avatar = avatar;
  161. this.opponent = opponent;
  162. // Does they hesitate?
  163. if (this.avatar.submissiveness / 4 >= getRandomInt(0, 100) && this.avatar.Mods.ironwill < 4) {
  164. if ((this.avatar.Mods.ironwill * 25) < getRandomInt(1, 100)) return new Hesitate(this.avatar);
  165. else return new Rest(this.avatar);
  166. }
  167. // Is their opponent defeated
  168. // (rival vs player only)
  169. if (this.avatar == rival) {
  170. var tst = player.calcTestes(false);
  171. if (tst > 11 && player.submissiveness >= rival.desires["submissiveness"] && player.domesticity >= rival.desires["domesticity"] && player.maternalism >= rival.desires["maternalism"] && player.allure >= rival.desires["allure"] && player.orientation >= rival.desires["orientation"]) {
  172. playerDefeated = true;
  173. clearTimeout(autoTimer);
  174. delete rival.currentAction;
  175. delete player.currentAction;
  176. rival.Defeat();
  177. return new Rest(rival);
  178. }
  179. }
  180. // Do they Rest
  181. if (this.avatar.changra < getRandomInt(0, 70)) return new Rest(this.avatar);
  182. // They do another action
  183. var pushPropability = drainCount + this.avatar.pushPreference + getRandomInt(0, this.avatar.unpredictability);
  184. var drainProbability = reflectCount + this.avatar.drainPreference + getRandomInt(0, this.avatar.unpredictability);
  185. var reflectProbability = pushCount + this.avatar.reflectPreference + getRandomInt(0, this.avatar.unpredictability);
  186. var predictions = [{"action": "push", "val": pushPropability}, {"action": "drain", "val": drainProbability}, {"action": "reflect", "val": reflectProbability}];
  187. predictions = predictions.sort(function(a,b) {
  188. return b.val - a.val;
  189. });
  190. this.action = predictions[0].action;
  191. this.trait = rival.determineAttackTrait(this.avatar, this.opponent, this.action);
  192. return new BattleActions[this.action](this.trait,this.avatar);
  193. //return eval("new " + capitalize(this.action) + "('" + this.trait + "', this.avatar);" );
  194. }
  195. function processRound(playerAction, rivalAction) {
  196. if (playerAction.name === rivalAction.vulnerability) playerAction.special();
  197. else if (rivalAction.name === playerAction.vulnerability) rivalAction.special();
  198. else {
  199. playerAction.standard();
  200. rivalAction.standard();
  201. }
  202. }
  203. function describeTrait(trait) {
  204. function describeSubmissiveness() {
  205. switch (player.description[trait]) {
  206. case 10: return "Your eyes wet with tears. You stupid, scared. You only make mistake. You want dada. You want someone protect you.";
  207. case 9: return "You feel small, like child boy. But when you real child, father protect you. Nobody protect you now.";
  208. case 8: return rival.name + " stare at you, and " + rivalhe + " know. " + capitalize(rivalhe) + " know you stupid. You make mistake.";
  209. case 7: return "You pause, doubting last action. Did you make mistake? Are you stupid?";
  210. case 6: return "You hesitate, unsure what to do next.";
  211. case 5: return "You plant feet firm in ground. Shaken but ready.";
  212. case 4: return "You stand straight, roll shoulders, stare " + rivalmanlwr + " hard in eye.";
  213. case 3: return "You smile cocky at " + rival.name + ". " + capitalize(rivalhe) + " weak. You strong. You make him your woman.";
  214. case 2: return "You laugh at " + rival.name + ". " + capitalize(rivalhe) + " become like dog to you. All manfolk become like dog to you.";
  215. case 1: return "You roar at " + rival.name + ", beat your chest. He cower before you like dog man!";
  216. }
  217. }
  218. function describeDomesticity() {
  219. switch (player.description[trait]) {
  220. case 10: return "You want not be in forest. You want be in den. Den safe, warm, good. Forest scary and big.";
  221. case 9: return "Sun reaches high point, and you feel strange urgency. You should be back at den, cooking dinner. Chop vegetables, soften meat, boil water, stir patient.";
  222. case 8: return "Strange voice whisper in head. Tell you get back to den, tend to fire, clean floor, cook dinner, wash clothes, patch holes, sort berries, gather nuts.";
  223. case 7: return "You spot cedar berry, very good on meat. Without thinking you swipe handful of them.";
  224. case 6: return "You notice herb plant near foot. Very strange. Father never teach you of herb plants.";
  225. case 5: return "Ears perk up. You hear chitter of squirrels overhead.";
  226. case 4: return "You notice animal tracks everywhere. Once " + rivalmanlwr + " is womanfolk, you go hunt and bring food for everyone.";
  227. case 3: return "Nostrils flare. You catch whiff of musk in air. She-deer nearby.";
  228. case 2: return "You want get bow and stalk through snow, follow track until you kill big she-deer.";
  229. case 1: return "You part lips, move air across tongue like panther. You taste she-deer musk. You want follow trail, but must finish battle.";
  230. }
  231. }
  232. function describeMaternalism() {
  233. switch (player.description[trait]) {
  234. case 10: return "You want cradle baby in arms. You want coo at baby. Your nipples grow big and hard, and they want suckle baby.";
  235. case 9: return "You imagine self swelling with first baby. Without thinking, you cradle belly, but it is flat and you feel strange sadness.";
  236. case 5: return "Being father one day be fun. You play with child, teach him how wrestle. Make funny face. Child laugh easy.";
  237. case 4: return "When you have child, you be good father. You teach how hold bow, how walk quiet.";
  238. case 3: return "You imagine woman swelling with baby. Your baby. You grin satisfaction.";
  239. case 2: return "One day, you be good stern father. You show harshness like Iberninth, and son grow strong to survive.";
  240. case 1: return "You imagine whole tribe of womanfolk. All swelling with baby. All your baby. You father to whole clan!";
  241. }
  242. }
  243. function describeAllure() {
  244. switch (player.description[trait]) {
  245. case 10: return "You moving like she-cat in heat. Gestures slow, sensual, beckoning. You try stop, but within moments you doing it again.";
  246. case 9: return "You give " + rivalmanlwr + " flirt-like smile. Change posture so he get better look at chest. When you realize what you doing, you jerk straight up. " + rival.name + " give you bemused smile.";
  247. case 8: return "Without thinking you bat eyelashes at " + rivalmanlwr + ".";
  248. case 7: return "You think of womanfolk dress. How pretty and delicate and flowing. Blushing, you imagine self wearing their clothes.";
  249. case 6: return "You notice chipped fingernails, dirt underneath. You notice mud on hairy arms. Clothes stained.";
  250. case 5: return "You feel wind on lips, and you think of kiss from womanfolk. Always good.";
  251. case 4: return "You think of first time you have sex. Was slow and gentle and little scared.";
  252. case 3: return "Once, a clanswoman gave you love-handing. Was good.";
  253. case 2: return "You want fuck. Or love-handing. Maybe even you love-hand yourself.";
  254. case 1: return "You stare at " + rivalmanlwr + ". You want " + rivalhim + " ready for fucking.";
  255. }
  256. }
  257. function describeOrientation() {
  258. switch (player.description[trait]) {
  259. case 10: return rival["physique"].penis < 10 ? "You gaze at " + rivalmanlwr + "'s cock, imagining " + rivalhim + " thrusting it deep into you again and again while you bounce around and moan." : "You imagine being with man with big cock, him thrusting it deep into you again and again while you bounce around and moan.";
  260. case 9: return "You keep thinking of penises. Big erect penises.";
  261. case 8: return rival["physique"].penis < 10 ? "You gaze at " + rivalmanlwr + "'s penis, blushing deep as you imagine what it would feel like in your hand. He smirk at you knowing-like." : "You imagine what it would be like to have other man's penis in your hand. In your mouth.";
  262. case 7: return rival["physique"].penis < 10 ? "You find eyes gazing at " + rivalmanlwr + "'s penis." : "You find eyes gazing at " + rivalmanlwr + "'s crotch, remembering his penis.";
  263. case 6: return "You think of men with big arms, hard muscles.";
  264. case 5: return "You imagine threesome. You and other man with one big bottom woman.";
  265. case 4: return "You think of woman's breast. The feel of it in your hand.";
  266. case 3: return "You want throw woman on hay. Ride her from behind while she moan.";
  267. case 2: return "You imagine woman, heavy thighs wrapped around your waist, wet pussy riding up and down your cock, big ass squeezing in your hands.";
  268. case 1: return "You want four woman, all kissing and stroking and sucking and moaning. All their juices and their smells covering you, covering them, until world is warm and sweet and sticky.";
  269. }
  270. }
  271. switch (trait) {
  272. case "submissiveness":
  273. return describeSubmissiveness();
  274. case "domesticity":
  275. return describeDomesticity();
  276. case "maternalism":
  277. return describeMaternalism();
  278. case "allure":
  279. return describeAllure();
  280. case "orientation":
  281. return describeOrientation();
  282. }
  283. }
  284. function describeChange(avatar, trait) {
  285. if (avatar === player) {
  286. var description = "";
  287. var traitFraction = Math.floor(avatar[trait] / 10);
  288. if (traitFraction != avatar.description[trait]) {
  289. avatar.description[trait] = traitFraction;
  290. description = describeTrait(trait);
  291. }
  292. if (description !== undefined && description.length > 0) {
  293. $("#changes").prepend("<p class='change-feminine'>" + description + "</p>");
  294. }
  295. }
  296. }
  297. // Apply a change from combat where
  298. // avatar = affected party
  299. // trait = "submissiveness" etc
  300. // rate = amount
  301. // special
  302. function processAction(avatar, trait, rate, special) {
  303. rate = Math.ceil(rate);
  304. if (rate > 0) {
  305. var resist = rate > 0 ? avatar.Mods["resist" + trait] : 0;
  306. rate = rate - resist;
  307. if (rate < 2) rate = 2; // minimum change
  308. }
  309. //alert(avatar.name + " " + trait + " changes " + rate);
  310. var projectedTotal = avatar[trait] + rate;
  311. if (special === true) {
  312. if (projectedTotal > avatar.maximums[trait]) {
  313. projectedTotal -= avatar.maximums[trait];
  314. projectedTotal /= 2;
  315. avatar.changeNatural(trait, projectedTotal);
  316. avatar[trait] = avatar.maximums[trait];
  317. } else if (projectedTotal < avatar.minimums[trait]) {
  318. projectedTotal = avatar.minimums[trait] - projectedTotal;
  319. projectedTotal /= 2;
  320. avatar.changeNatural(trait, -1 * projectedTotal);
  321. avatar[trait] = avatar.minimums[trait];
  322. } else {
  323. avatar[trait] = projectedTotal;
  324. }
  325. describeChange(avatar, trait);
  326. } else {
  327. if (projectedTotal > avatar.maximums[trait]) {
  328. avatar.changeNatural(trait, 2);
  329. avatar[trait] = avatar.maximums[trait];
  330. } else if (projectedTotal < avatar.minimums[trait]) {
  331. avatar.changeNatural(trait, -2);
  332. avatar[trait] = avatar.minimums[trait];
  333. } else {
  334. avatar[trait] = projectedTotal;
  335. }
  336. }
  337. avatar.capTraits();
  338. }
  339. function Push(trait, avatar) {
  340. this.avatar = avatar;
  341. this.opponent = this.avatar === player ? rival : player;
  342. this.name = "push";
  343. this.vulnerability = "reflect";
  344. this.trait = trait;
  345. this.avatar.currentAction = this;
  346. if (this.avatar[this.trait] > 50) this.avatar.changra -= 13;
  347. else this.avatar.changra -= 7;
  348. this.special = function() {
  349. var opponentActivity = this.avatar[this.trait] > 50 ? "listen to father ancestors" : "siphon masculinity";
  350. var rate;
  351. if (this.avatar[this.trait] > 50) {
  352. rate = standardChange() * (this.avatar[this.trait] / 25);
  353. if (this.avatar.Mods["push" + this.trait] !== 0) rate *= 1 + (0.2 * this.avatar.Mods["push" + this.trait]);
  354. processAction(this.opponent, this.trait, rate, true);
  355. processAction(this.avatar, this.trait, rate * -1, true);
  356. this.avatar[this.trait] = minValue(this.avatar[this.trait], 50);
  357. description += this.avatar === player ? rival.name + " attempt " + opponentActivity + ", but instead " + rivalhe + " vulnerable as you push " + rivalhim + " full of " + this.trait + ". " : "You attempt " + opponentActivity + ", but instead you vulnerable as " + rivalhe + " push you full of " + this.trait + ". ";
  358. } else {
  359. rate = standardChange() * 2;
  360. if (this.avatar.Mods["push" + this.trait] !== 0) rate *= 1 + (0.2 * this.avatar.Mods["push" + this.trait]);
  361. processAction(this.opponent, this.trait, rate, true);
  362. description += this.avatar === player ? rival.name + " attempt " + opponentActivity + ", but instead " + rivalhe + " soak in your mother ancestor's " + this.trait + " very fast. " : "You attempt " + opponentActivity + ", but instead you soak in " + this.trait + " from " + rivalmanlwr + "'s mother ancestors. ";
  363. }
  364. };
  365. this.standard = function() {
  366. var rate;
  367. if (this.avatar[this.trait] > 50) {
  368. rate = standardChange() * (this.avatar[this.trait] / 50);
  369. if (this.avatar.Mods["push" + this.trait] !== 0) rate *= 1 + (0.2 * this.avatar.Mods["push" + this.trait]);
  370. processAction(this.opponent, this.trait, rate);
  371. processAction(this.avatar, this.trait, rate * -1);
  372. this.avatar[this.trait] = minValue(this.avatar[this.trait], 50);
  373. description += this.avatar === player ? "You push " + this.trait + " into " + rivalmanlwr + ". " : rival.name + " push " + this.trait + " into you. ";
  374. } else {
  375. rate = standardChange();
  376. if (this.avatar.Mods["push" + this.trait] !== 0) rate *= 1 + (0.2 * this.avatar.Mods["push" + this.trait]);
  377. processAction(this.opponent, this.trait, rate);
  378. description += this.avatar === player ? "You summon mother ancestors, which fill " + rivalmanlwr + " with " + this.trait + ". " : rival.name + " summon mother ancestors, which whisper to you secrets of " + this.trait + ". ";
  379. }
  380. };
  381. }
  382. function Drain(trait, avatar) {
  383. this.avatar = avatar;
  384. this.opponent = this.avatar === player ? rival : player;
  385. this.name = "drain";
  386. this.vulnerability = "push";
  387. this.trait = trait;
  388. this.avatar.currentAction = this;
  389. if (this.avatar[this.trait] > 50) this.avatar.changra -= 6;
  390. else this.avatar.changra -= 4;
  391. this.special = function() {
  392. if (this.opponent[this.trait] > 50) {
  393. processAction(this.avatar, this.trait, standardChange() * -1, true);
  394. description += this.avatar === player ? rival.name + " attempt reflect, leaving you free to talk to father ancestors about " + switchFemForMascTrait(this.trait) + ". " : "You attempt reflect " + rival.name + "'s attack, leaving " + rivalhim + " free to talk with father ancestors about " + switchFemForMascTrait(this.trait) + ". ";
  395. } else {
  396. var rate = standardChange() * 2;
  397. processAction(this.opponent, this.trait, rate, true);
  398. processAction(this.avatar, this.trait, rate * -1, true);
  399. this.opponent[this.trait] = maxValue(this.opponent[this.trait], 51);
  400. description += this.avatar === player ? rival.name + " attempt reflect, make " + rivalhim + " easy prey as you drain " + rivalhim + " of " + switchFemForMascTrait(this.trait) + ". " : "You attempt reflect, making you easy prey as " + rivalmanlwr + " drain you of " + switchFemForMascTrait(this.trait) + ". ";
  401. }
  402. };
  403. this.standard = function() {
  404. if (this.opponent[this.trait] > 50) {
  405. processAction(this.avatar, this.trait, standardChange() * -1);
  406. description += this.avatar === player ? "You summon father ancestors and learn of " + switchFemForMascTrait(this.trait) + ". " : rival.name + " summon father ancestors and learn of " + switchFemForMascTrait(this.trait) + ". ";
  407. } else {
  408. var rate = standardChange() * 2;
  409. processAction(this.opponent, this.trait, rate);
  410. processAction(this.avatar, this.trait, rate * -1);
  411. this.opponent[this.trait] = maxValue(this.opponent[this.trait], 51);
  412. description += this.avatar === player ? "You drain " + rivalmanlwr + " of " + switchFemForMascTrait(this.trait) + ". " : rival.name + " drain you of " + switchFemForMascTrait(this.trait) + ". ";
  413. }
  414. };
  415. }
  416. function Reflect(avatar) {
  417. this.avatar = avatar;
  418. this.opponent = this.avatar === player ? rival : player;
  419. this.name = "reflect";
  420. this.vulnerability = "drain";
  421. this.avatar.currentAction = this;
  422. this.special = function() {
  423. this.trait = this.opponent.currentAction.trait;
  424. processAction(this.opponent, this.trait, standardChange() * 2, true);
  425. description += this.avatar === player ? rival.name + " attempt give you " + this.trait + ", but you reflect it back at " + rivalhim + ". " : "You attempt give " + rivalmanlwr + " " + this.trait + ", but " + rivalhe + " reflects it back at you. " ;
  426. };
  427. this.standard = function() {
  428. this.avatar.changra += getRandomInt(0, 5);
  429. description += this.avatar === player ? "You attempt reflect " + rivalmanlwr + "'s attack, but " + rivalhe + " no attack. " : rival.name + " attempt reflect your attack, but you no attack. ";
  430. };
  431. }
  432. function Rest(avatar) {
  433. this.avatar = avatar;
  434. this.opponent = this.avatar === player ? rival : player;
  435. this.name = "rest";
  436. this.vulnerability = "";
  437. this.avatar.currentAction = this;
  438. this.standard = function() {
  439. this.avatar.changra += getRandomInt(20, 30);
  440. $.each(AVATAR_TRAITS, function(index, trait) {
  441. if (avatar[trait] < avatar.natural[trait]) {
  442. avatar[trait] += getRandomInt(1, 3);
  443. avatar[trait] = maxValue(avatar[trait], avatar.natural[trait]);
  444. } else if (avatar[trait] > avatar.natural[trait]) {
  445. avatar[trait] -= getRandomInt(1, 3);
  446. avatar[trait] = minValue(avatar[trait], avatar.natural[trait]);
  447. }
  448. });
  449. description += this.avatar === player ? "You rest. " : rival.name + " rest. ";
  450. };
  451. }
  452. function Flee(avatar) {
  453. clearTimeout(autoTimer);
  454. this.avatar = avatar;
  455. this.opponent = this.avatar === player ? rival : player;
  456. this.name = "flee";
  457. this.vulnerability = "";
  458. this.avatar.currentAction = this;
  459. this.standard = function() {
  460. var val = rival.name == ("Rival man" || rival.name == "Rival woman") ? this.opponent.allure : 25;
  461. if (getRandomInt(0, 100) < val) {
  462. alert("You run like she-deer!");
  463. this.avatar.changra -= 15;
  464. Camp();
  465. } else {
  466. this.avatar.changra -= 5;
  467. description += "You attempt escape, but " + rivalmanlwr + " pursue you. ";
  468. if (bAuto) autoTimer = setTimeout(AutoBattleRound, 200);
  469. }
  470. };
  471. }
  472. function Hesitate(avatar) {
  473. this.avatar = avatar;
  474. this.opponent = this.avatar === player ? rival : player;
  475. this.name = "hesitate";
  476. this.vulnerability = "";
  477. this.avatar.currentAction = this;
  478. this.standard = function() {
  479. this.avatar.changra += getRandomInt(15, 20);
  480. description += this.avatar === player ? "You hesitate. " : rival.name + " hesitate. ";
  481. };
  482. }
  483. function processCounts(playerAction) {
  484. pushCount -= 1;
  485. drainCount -= 1;
  486. reflectCount -= 2;
  487. if (playerAction.name == "push") pushCount += 2;
  488. else if (playerAction.name == "drain") drainCount += 2;
  489. else if (playerAction.name == "reflect") reflectCount += 3;
  490. pushCount = minValue(pushCount, 0);
  491. drainCount = minValue(drainCount, 0);
  492. reflectCount = minValue(reflectCount, 0);
  493. }
  494. function rivalTell() {
  495. function accurateTell() {
  496. nAccurateTell = 1;
  497. sTell = nextRivalAction.name;
  498. return rival.getTell(nextRivalAction.name);
  499. }
  500. function deceptiveTell() {
  501. nAccurateTell = 0;
  502. if (nextRivalAction.name === "rest") {
  503. sTell = "push";
  504. return rival.getTell("push");
  505. }
  506. sTell = nextRivalAction.vulnerability;
  507. return rival.getTell(nextRivalAction.vulnerability);
  508. }
  509. var perceptionRate = getPerceptionRate();
  510. // No tell 25 - perception/10
  511. if ((((25 - (player.perception() / 10)) > getRandomInt(0, 100)) && nAccurateTell == undefined) || nAccurateTell == -1) {
  512. nAccurateTell = -1;
  513. sTell = "";
  514. return "";
  515. }
  516. // generate true or deceptive tell based on perception
  517. if (perceptionRate >= getRandomInt(0, 100) || nAccurateTell == 1) {
  518. return accurateTell();
  519. }
  520. if (player.Mods.perception < 4 || nAccurateTell == 0) return deceptiveTell();
  521. nAccurateTell = -1;
  522. sTell = "";
  523. return "";
  524. }
  525. function Round(playerAction)
  526. {
  527. description = "";
  528. rnd++;
  529. if (!bAuto) {
  530. if ((player.submissiveness / 4) > getRandomInt(1, 100) && player.Mods.ironwill < 4) {
  531. if ((player.Mods.ironwill * 25) < getRandomInt(1, 100)) playerAction = new Hesitate(player);
  532. }
  533. }
  534. processRound(playerAction, nextRivalAction);
  535. processCounts(playerAction);
  536. player.capTraits();
  537. rival.capTraits();
  538. redraw();
  539. nextRivalAction = new RivalAction(rival, player);
  540. if (playerDefeated == true) return;
  541. var tell = rivalTell();
  542. nAccurateTell = undefined;
  543. if (!bAuto) {
  544. fillPushColumn();
  545. fillDrainColumn();
  546. fillSupportColumn();
  547. } else {
  548. fillManual();
  549. fillFlee();
  550. }
  551. redraw();
  552. var ret = checkForVictoryButton();
  553. $("#last_action").html("<p class='battle-description'>" + description + "</p><p class='rival-tell'>" + tell + "</p>");
  554. return ret;
  555. }
  556. function AutoBattleRound()
  557. {
  558. // Determine player action
  559. var playeraction = undefined;
  560. var pexp = player.getTrainingRanks() * 5 + player.experience;
  561. var rexp = rival.getTrainingRanks() * 5;
  562. $("#support_controls").html("<h2>Other</h2>");
  563. if ((pexp / rexp * 66) > getRandomInt(0, 100)) {
  564. // Use accurate
  565. if (nAccurateTell == 1) {
  566. /*
  567. Action Vulnerability
  568. ------ -------------
  569. "push" "reflect";
  570. "drain" "push";
  571. "reflect" "drain";
  572. "rest" ""
  573. "hesitate" ""
  574. */
  575. var rtrait = AVATAR_TRAITS[getRandomInt(0, 4)]; //TODO: maybe select based on value etc
  576. if (sTell == "push") playeraction = new Reflect(player);
  577. else if ((sTell == "drain" || sTell == "rest" || sTell == "hesitate") && player.changra > 6) playeraction = new Push(rtrait, player);
  578. else if (sTell == "reflect" && player.changra > 5) playeraction = new Drain(rtrait, player);
  579. }
  580. }
  581. if (playeraction == undefined) playeraction = new RivalAction(player, rival);
  582. if (playerDefeated == true) return;
  583. // Do the round
  584. if (Round(playeraction)) autoTimer = setTimeout(AutoBattleRound, 2000);
  585. else autoTimer = setTimeout(AutoBattleRound, 200);
  586. }
  587. }