Gestion de personnage et de pool de personnage en javascript vanilla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

l5r.js 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. var stances = ["attack", "full attack", "defense", "full defense", "center"];
  2. class Characters {
  3. constructor(){}
  4. pool = [];
  5. elements = ["Character", "Samourai"];
  6. at( index ){
  7. return this.pool[ index ];
  8. }
  9. elementsType = Character;
  10. create( json ){
  11. let charac = new Character();
  12. if( typeof json === "Object" )
  13. charac.fromJson( json ) ;
  14. this.add( charac );
  15. }
  16. createCharacter( aRole, gender, name, familly,experience, gempukku, skills ){
  17. let character = new Character( aRole, gender, name, familly, school, experience, gempukku, skills );
  18. this.add( character );
  19. }
  20. createSamourai( aRole, gender, name, familly, school, experience, gempukku, skills ){
  21. let samourai = new Samourai( aRole, gender, name, familly, school, experience, gempukku, skills );
  22. this.add( samourai );
  23. }
  24. fromJson( json ){
  25. let data = JSON.parse(json);
  26. for( prop in data){
  27. this[ prop ] = data[ prop ];
  28. }
  29. }
  30. add(character){
  31. if( this.elements.includes( character.constructor.name )){
  32. this.pool.push( character );
  33. }
  34. }
  35. indexOf( character ){
  36. if( this.elements.includes( character.constructor.name )){
  37. for(let i = 0; i < this.pool.length ; i++){
  38. if( character == this.pool[ i ] )
  39. return i;
  40. }
  41. }
  42. }
  43. getByName( name ){
  44. for(let i = 0; i < this.pool.length ; i++){
  45. if( this.pool[i].getName() == name)
  46. return this.pool[i];
  47. }
  48. }
  49. getIndexByName( name ){
  50. for(let i = 0; i < this.pool.length ; i++){
  51. if( this.pool[i].getName() == name)
  52. return i;
  53. }
  54. }
  55. size(){
  56. return this.pool.length;
  57. }
  58. }
  59. class Character {
  60. constructor( aRole, skills, gender, name, experience, gempukku ){
  61. if( aRole in roleSkills )
  62. this.role = aRole;
  63. else
  64. this.role = randomFromAssociative(roleSkills);
  65. this.gempukku = gempukku || 0;
  66. this.stamina = (this.rank() < 1)? 1 : 2 ;
  67. this.willpower = (this.rank() < 1)? 1 : 2 ;
  68. this.perception = (this.rank() < 1)? 1 : 2 ;
  69. this.strength = (this.rank() < 1)? 1 : 2 ;
  70. this.reflexes = (this.rank() < 1)? 1 : 2 ;
  71. this.awarness = (this.rank() < 1)? 1 : 2 ;
  72. this.agility = (this.rank() < 1)? 1 : 2 ;
  73. this.intelligence = (this.rank() < 1)? 1 : 2 ;
  74. this.void = (this.rank() < 1)? 1 : 2 ;
  75. this.skills = ( typeof skills === "object")? skills : {};
  76. this.gender = (typeof gender !== "undefined")? gender : r_gender();
  77. this.name = (name !== "undefined")? { "name" : name, "gender" : gender}: names.randomFromFilters([{ filter : "gender", value : this.gender },{ filter : "gender", value : "n" }]) ;
  78. this.experience = (typeof experience === "undefined")? 25 : experience ;
  79. this.expandedExperience = 0;
  80. this.malus = 0 ;
  81. this.actualizeWounds();
  82. this.currentWounds = this.maxWounds;
  83. }
  84. earth () { return ( this.stamina < this.willpower)? this.stamina : this.willpower ;}
  85. water () { return ( this.strength < this.perception)? this.strength : this.perception ;}
  86. air () { return ( this.reflexes < this.awarness)? this.reflexes : this.awarness ;}
  87. fire () { return ( this.agility < this.intelligence)? this.agility : this.intelligence ;}
  88. insight(){
  89. let resultat = (this.earth() + this.water() + this.air() + this.fire() + this.void) * 10 ;
  90. if(typeof this.skills == "object")
  91. for(let i in this.skills)
  92. resultat += parseInt(this.skills[i]);
  93. return resultat;
  94. }
  95. rank(){
  96. let insight = this.insight();
  97. switch( insight ){
  98. case( !this.gempukku ):
  99. return 0;
  100. break;
  101. case ( insight > 150 ):
  102. return 1;
  103. default :
  104. return Math.round((insight - 125)/25);
  105. }
  106. }
  107. skills = {};
  108. weapons = {
  109. "wakizachi" : weapons["wakizachi"]
  110. };
  111. armors = [];
  112. equippedArmor = "kimono";
  113. equippedArrow = "willow leaf";
  114. rollMade = {};
  115. getTN(){
  116. let armorTN = 0;
  117. let modifier = 0;
  118. switch(this.stance){
  119. case "full attack":
  120. modifier = -10;
  121. break;
  122. case "full defense":
  123. modifier = this.rollMade["defense"];
  124. break;
  125. case "defense":
  126. modifier = this.air() + this.getSkillRank( 'defense' );
  127. break;
  128. }
  129. if ( typeof armors[ this.equippedArmor ].TN !== "undefined")
  130. armorTN = armors[ this.equippedArmor ].TN;
  131. return 5 + armorTN + (this.reflexes * 5) + modifier;
  132. }
  133. naturalDR = 0;
  134. getName(){
  135. return capitalize( this.name.familly ) + " " + capitalize( this.name.name );
  136. }
  137. dr(){
  138. let armorDR = 0;
  139. for (var armor in this.equippedArmor)
  140. if ( typeof armor.DR !== "undefined")
  141. armorDR = armor.DR;
  142. return this.naturalDR + armorDR;
  143. }
  144. addWeapon( weapon ){
  145. if( typeof this.weapons[ weapon ] === "objects" )
  146. return null;
  147. this.weapons[ weapon ] = weapons[ weapon ];
  148. };
  149. advantages = [];
  150. addAdvantages ( newAdvantage ){
  151. if( typeof this.advantages.find(element => element == newAdvantage ) === "undefined" ){
  152. return null;
  153. }
  154. let cost;
  155. for( advantage in advantages[ newAdvantage ] )
  156. if( this.name.familly in advantages[ newAdvantage ] ){
  157. cost = advantages[ newAdvantage ][ this.name.familly ];
  158. } else if ( this.clan in advantages[ newAdvantage ] ){
  159. advantages[ newAdvantage ][ this.clan ];
  160. } else if ( this.clan in advantages[ newAdvantage ] ){
  161. advantages[ newAdvantage ][ this.role ];
  162. } else {
  163. cost = advantages[ newAdvantage ][ "default" ];
  164. }
  165. }
  166. hasAdvantage( advantage){
  167. if( typeof this.advantages.find(element => element == advantage ) === "undefined" ){
  168. return 0;
  169. }
  170. return 1;
  171. }
  172. attack(){
  173. let modifier_r = 0;
  174. let modifier_k = 0;
  175. if( this.stance = "full attack"){
  176. modifier_r = 2;
  177. modifier_k = 1;
  178. }
  179. if( (typeof defaultAttacks === "undefined") ||
  180. (typeof defaultAttacks.expandedExperience === "undefined") ||
  181. (defaultAttacks.expandedExperience < this.expandedExperience)){
  182. let attack = Object.keys(this.updateAttacks())[0];
  183. if( attack == "jiujutsu" ){
  184. return {"r" : this.strength + modifier_r, "k" : 1 + modifier_k};
  185. }else{
  186. let skill = 0;
  187. if((skill = this.skills[ this.weapons[ attack ].skill ]) in this.skills){
  188. return {"r" : skill[0] + modifier_r, "k" : skill[1] + modifier_k};
  189. }
  190. return {"r" : this[skills[weapons[ attack ].skill].trait] + modifier_r, "k" : this[skills[weapons[ attack ].skill].trait] + modifier_k, "x" : 11};
  191. }
  192. }
  193. return { "r" : this.defaultAttacks[ Object.keys(this.defaultAttacks)[0] ]['attack'].r + modifier_r,
  194. "k" : this.defaultAttacks[ Object.keys(this.defaultAttacks)[0] ]['attack'].k + modifier_k };
  195. }
  196. attackFromWeapon( weapon ){
  197. let trait = parseInt( this[skills[ this.weapons[weapon].skill ].trait], 10);
  198. let skill = parseInt( this.skills[ this.weapons[weapon].skill ], 10) || 0;
  199. return({ "r" : trait + skill, "k" : trait, "x" : (skill)? 10: 11});
  200. }
  201. damageFromWeapon( weapon ){
  202. if( weapons[ weapon ].type == "bow"){
  203. let arrow = arrows[ this.equippedArrow ];
  204. return {
  205. "r" : arrow.r + ( weapon.strength <= this.strength )? weapon.strength : this.strength,
  206. "k" : arrow.k}
  207. }
  208. return({ "r" : parseInt(this.strength, 10) + parseInt(weapons[ weapon ].damage.split("G")[0], 10) ,
  209. "k" : parseInt(weapons[ weapon ].damage.split("G")[1], 10) });
  210. }
  211. damage(){
  212. if( (typeof defaultAttacks === "undefined") ||
  213. (typeof defaultAttacks.expandedExperience === "undefined") ||
  214. (defaultAttacks.expandedExperience < this.expandedExperience)){
  215. let weapon = Object.keys(this.updateAttacks())[0]
  216. if( weapon == "jiujutsu")
  217. return {"r" : this.strength, "k" : 1};
  218. else if( weapon.type == "bow"){
  219. let arrow = arrows[ this.equippedArrow ];
  220. return {
  221. "r" : arrow.r + ( bow_strength <= this.strength )? weapon.strength : this.strength,
  222. "k" : arrow.k
  223. }
  224. }else{
  225. let damage = weapons[ weapon ]['damage'].split("G");
  226. return {"r" :damage[0], "k" : damage[1]};
  227. }
  228. }
  229. return this.defaultAttacks[ (Object.keys( this.defaultAttacks)[0]) ];
  230. }
  231. initiative(){
  232. return { "r" : this.rank() + this.reflexes , "k" : this.reflexes };
  233. }
  234. getAttack(){
  235. let roll = this.attack();
  236. let modifier_r = 0;
  237. let modifier_k = 0;
  238. if( this.stance = "full attack"){
  239. modifier_r = 2;
  240. modifier_k = 1;
  241. }
  242. return RNG.rk10(roll.r, roll.k, this.malus);
  243. }
  244. getInitiative(){
  245. let roll = this.initiative();
  246. return RNG.rk10(roll.r, roll.k);
  247. }
  248. getDamage(){
  249. let roll = this.damage();
  250. return RNG.rk10(roll.r, roll.k);
  251. }
  252. getSkillRank( aSkill ){
  253. return this.skills[ aSkill ] || 0;
  254. }
  255. allAttacks(){
  256. let result = {};
  257. if( "jiujutsu" in this.skills ){
  258. result['jiujutsu'] = { "attack" : { "r" : parseInt(this.agility, 10) + parseInt(this.skills[ 'jiujutsu' ], 10), "k": this.agility }, "damage" : { "r" : this.strength, "k" : 1} };
  259. }
  260. for(let i in this.weapons){
  261. result[ i ] = { "attack" : this.attackFromWeapon( i ), "damage" : this.damageFromWeapon( i ) };
  262. }
  263. /*(result)*/
  264. return result;
  265. }
  266. attacking( charac ){
  267. if( this.getAttack() > charac.getTN()){
  268. charac.getWounded ( this.getDamage() );
  269. }
  270. }
  271. defaultAttacks = {};
  272. attacks(){
  273. if( (typeof defaultAttacks === "undefined") ||
  274. (typeof defaultAttacks.expandedExperience === "undefined") ||
  275. (defaultAttacks.expandedExperience < this.expandedExperience))
  276. return this.updateAttacks();
  277. return this.defaultAttacks[1]['attack'];
  278. }
  279. updateAttacks(){
  280. let bestAttack = 0;
  281. let bestDamage = 0;
  282. let attacks = this.allAttacks();
  283. for(let i in attacks){
  284. if( !bestAttack )
  285. bestAttack = i ;
  286. if( (attacks[i].k > attacks[ bestAttack ].k ) ||
  287. ((attacks[i].k = attacks[ bestAttack ]) && (attacks[i].r < attacks[ bestAttack ].r )) ||
  288. ( attacks[i].r < (attacks[ bestAttack ].r + 2 ))){
  289. bestAttack = i ;
  290. };
  291. if( !bestDamage )
  292. bestDamage = i ;
  293. if( (attacks[i].k > attacks[ bestDamage ].k ) ||
  294. ((attacks[i].k = attacks[ bestDamage ]) && (attacks[i].r < attacks[ bestDamage ]).r ) ||
  295. ( attacks[i].r < (attacks[ bestDamage ].r + 2 ))){
  296. bestDamage = i ;
  297. };
  298. if( !bestDamage )
  299. bestDamage = i ;
  300. }
  301. this.defaultAttacks[bestAttack] = attacks[ bestAttack ];
  302. this.defaultAttacks[bestDamage] = attacks[ bestDamage ];
  303. this.defaultAttacks['expandedExperience'] = this.expandedExperience;
  304. return this.defaultAttacks;
  305. }
  306. expanseExperience( value ){
  307. if(!this.experience){
  308. this.experience = 0;
  309. return 0;
  310. }else if ( value > this.experience){
  311. return 0;
  312. }
  313. if( typeof value == "undefined"){
  314. this.experience = this.experience - 1;
  315. this.expandedExperience = this.expandedExperience + 1;
  316. }else{
  317. this.experience = this.experience - value;
  318. this.expandedExperience = this.expandedExperience + value;
  319. }
  320. return value || 1;
  321. }
  322. increaseSkill( skill ){
  323. if(( typeof this.skills[ skill ] === "number" ) && ( this.skills[ skill ] < 10 )){
  324. var cost = this.skills[ skill ] + 1;
  325. if( (this.experience - cost) >= 0 ){
  326. this.expanseExperience( cost );
  327. return this.skills[ skill ]++;
  328. }
  329. } else {
  330. if( this.experience > 0){
  331. this.expanseExperience();
  332. return this.skills[ skill ] = 1;
  333. }
  334. }
  335. return 0;
  336. }
  337. increaseTrait( trait ){
  338. let factor = ( trait == "void")? 12 : 6 ;
  339. let cost = (this[ trait ] + 1) * factor;
  340. this.actualizeWounds();
  341. if(this.expanseExperience( cost ))
  342. this[ trait ]++;
  343. };
  344. actualizeWounds(){
  345. this.maxWounds = 17 * this.earth();
  346. return this.fullHeal;
  347. };
  348. fullHeal(){
  349. return this.currentWounds = this.maxWounds;
  350. }
  351. actualizeMalus(){
  352. switch(this.state){
  353. case "healthy" :
  354. this.malus = 0;
  355. break;
  356. case "nicked" :
  357. this.malus = ( this.hasAdvantage( "strength of the earth" ) )? 0 : 3 ;
  358. break;
  359. case "grazed" :
  360. this.malus = ( this.hasAdvantage( "strength of the earth" ) )? 2 : 5 ;
  361. break;
  362. case "hurt" :
  363. this.malus = ( this.hasAdvantage( "strength of the earth" ) )? 7 : 10 ;
  364. break;
  365. case "injured" :
  366. this.malus = ( this.hasAdvantage( "strength of the earth" ) )? 12 : 15 ;
  367. break;
  368. case "crippled" :
  369. this.malus = ( this.hasAdvantage( "strength of the earth" ) )? 17 : 20 ;
  370. break;
  371. case "down" :
  372. this.malus = ( this.hasAdvantage( "strength of the earth" ) )? 37 : 40 ;
  373. break;
  374. case "out" :
  375. this.malus = 100 ;
  376. break;
  377. case "dead" :
  378. this.malus = 1000 ;
  379. break;
  380. }
  381. };
  382. getWounded( wounds ){
  383. let inflicted = wounds - this.dr();
  384. this.currentWounds = this.currentWounds - inflicted;
  385. if( this.currentWounds < 1 )
  386. this.state = "dead";
  387. else if( this.currentWounds < (5 * this.earth()) )
  388. this.state = "out";
  389. else if( this.currentWounds < (7 * this.earth()) )
  390. this.state = "down";
  391. else if( this.currentWounds < (9 * this.earth()) )
  392. this.state = "crippled";
  393. else if( this.currentWounds < (11 * this.earth()) )
  394. this.state = "injured";
  395. else if( this.currentWounds < (13 * this.earth()) )
  396. this.state = "hurt";
  397. else if( this.currentWounds < (15 * this.earth()) )
  398. this.state = "grazed";
  399. else if( this.currentWounds < (17 * this.earth()) )
  400. this.state = "nicked";
  401. else if( this.currentWounds < (7 * this.earth()) )
  402. this.state = "healthy";
  403. this.actualizeMalus();
  404. return inflicted;
  405. }
  406. getHeal( value ){
  407. this.currentWounds = ( value < this.maxWounds)? this.currentWounds + value : this.maxWounds;
  408. this.actualizeMalus();
  409. }
  410. fullHeal(){
  411. this.currentWounds = this.maxWounds;
  412. this.actualizeMalus();
  413. }
  414. generate( level, role ){
  415. this.role =( typeof role === "undefined" )? this.role : role ;
  416. this.experience = 25 + Math.round(level * 30 + Math.pow(15, level/10));
  417. this.randomTraits( level );
  418. this.randomSkill( level );
  419. this.armedFromSkills();
  420. }
  421. getWeaponsKeyword( keyword ){
  422. let result = [];
  423. for(let i = 0; i < weapons.length ; i++){
  424. if( keyword in weapons[i].keyword )
  425. result.push( weapons[i] );
  426. }
  427. return result ;
  428. }
  429. getWeaponKeyword( keyword ){
  430. let weapons = getWeaponsKeyword( keyword );
  431. let hasIt = 1;
  432. while( hasIt ){
  433. let index = random( weapons.length );
  434. hasIt = this.weapons[ weapons[ index ] ];
  435. if( !hasIt )
  436. this.weapons.push( weapons[ index ] );
  437. }
  438. }
  439. getRandomWeaponFromSkill( skill ){
  440. if( typeof skill == "unsigned") return null;
  441. let results = {};
  442. let atLeastOne = false;
  443. for(let weapon in weapons){
  444. if((typeof weapon != "undefined") && (typeof weapons[weapon].skill != "undefined")){
  445. if(weapons[weapon].skill == skill){
  446. atLeastOne = true;
  447. results[weapon] = weapons[weapon];
  448. }
  449. }
  450. }
  451. return ( atLeastOne)? randomFromAssociative( results ) : null ;
  452. }
  453. getWeaponsFromSkills( skills ){
  454. let result = {};
  455. for(let skill in skills){
  456. let weapon = this.getRandomWeaponFromSkill( skill );
  457. if(weapon)
  458. Object.assign( result, weapon );
  459. }
  460. return result;
  461. }
  462. armedFromSkills(){
  463. Object.assign( this.weapons, this.getWeaponsFromSkills( this.skills )) ;
  464. }
  465. allSkills(){
  466. let skillList = roleSkills[ this.role ];
  467. for(let skill in skillList){
  468. skillList[skill].occurrence *= 10;
  469. }
  470. return Object.assign({}, skillList, skills);
  471. }
  472. randomSkill(){
  473. let hasMain = 0;
  474. let skill ;
  475. let skillList = this.allSkills();
  476. while( this.experience > 2 ){
  477. skill = randomFromWeight( skillList );
  478. if( hasMain ){
  479. if( skill == hasMain ){
  480. if(!this.increaseSkill( Object.keys(skill)[0] )){
  481. skill = Object.keys( randomFromWeight( skillList ))[0];
  482. for(let i = 0 ; !this.increaseSkill( skill ) && (i < arrayLength( skillList)); i++ ){
  483. skill = Object.keys( randomFromWeight( skillList ))[0];
  484. };
  485. };
  486. }
  487. } else if( typeof skill.main !== "undefined"){
  488. hasMain = skill;
  489. this.increaseSkill( Object.keys(skill)[0] ) ;
  490. } else {
  491. this.increaseSkill( Object.keys(skill)[0] ) ;
  492. }
  493. }
  494. }
  495. randomTraits( level ){
  496. let pass = level * random(2) + random(2);
  497. switch( this.role ){
  498. case "bushi" :
  499. while(pass){
  500. let asset = random(3);
  501. switch( asset ){
  502. case 0 :
  503. if( this.experience >= ((6 * this.increaseTrait("stamina") + (6 * this.increaseTrait("willpower"))))){
  504. this.increaseTrait("willpower");
  505. this.increaseTrait("stamina");
  506. }else
  507. this.increaseTrait("void")
  508. break;
  509. case 1 :
  510. this.increaseTrait("strength") ;
  511. break;
  512. case 2 :
  513. this.increaseTrait("reflexes");
  514. break;
  515. case 3 :
  516. this.increaseTrait("agility");
  517. break;
  518. };
  519. pass--;
  520. }
  521. break;
  522. case "shugenja" :
  523. switch( random(3) ){
  524. case 0 :
  525. while(pass){
  526. this.increaseTrait("stamina") ;
  527. this.increaseTrait("willpower");}
  528. break;
  529. case 1 :
  530. while(pass){
  531. this.increaseTrait("perception");
  532. this.increaseTrait("strength") ;}
  533. break;
  534. case 2 :
  535. while(pass){
  536. this.increaseTrait("reflexes") ;
  537. this.increaseTrait("awarness") ;}
  538. break;
  539. case 3 :
  540. while(pass){
  541. this.increaseTrait("intelligence") ;
  542. this.increaseTrait("agility") ;}
  543. break;
  544. }
  545. break;
  546. case "monk" :
  547. while(pass){
  548. let asset = random(3);
  549. switch( asset ){
  550. case 0 :
  551. this.increaseTrait("void") ;
  552. break;
  553. case 1 :
  554. this.increaseTrait("strength") ;
  555. this.increaseTrait("agility");
  556. break;
  557. case 2 :
  558. this.increaseTrait("awarness");
  559. this.increaseTrait("reflexes");
  560. break;
  561. case 3 :
  562. this.increaseTrait("void");
  563. this.increaseTrait("strength");
  564. break;
  565. };
  566. pass--;
  567. }
  568. break;
  569. case "scout" :
  570. while(pass){
  571. let asset = random(2);
  572. switch( asset ){
  573. case 0 :
  574. this.increaseTrait("perception");
  575. this.increaseTrait("strength");
  576. break;
  577. case 1 :
  578. this.increaseTrait("agility");
  579. break;
  580. case 2 :
  581. this.increaseTrait("reflexes");
  582. break;
  583. };
  584. pass--;
  585. }
  586. break;
  587. case "ninja" :
  588. while(pass){
  589. let asset = random(2);
  590. switch( asset ){
  591. case 0 :
  592. this.increaseTrait("void")
  593. break;
  594. case 1 :
  595. this.increaseTrait("agility") ;
  596. break;
  597. case 2 :
  598. this.increaseTrait("reflexes");
  599. break;
  600. };
  601. pass--;
  602. }
  603. break;
  604. }
  605. this.actualizeWounds();
  606. }
  607. getWounds(){
  608. return this.currentWounds ;
  609. }
  610. stance = "attack";
  611. switchStance( aStance ){
  612. if( stances.includes( aStance ) ){
  613. this.stance = aStance;
  614. }else if( typeof aStance === "undefined" ){
  615. let nextStanceIndex = stances.indexOf( this.stance ) + 1;
  616. nextStanceIndex = (nextStanceIndex >= stances.length )? 0 : nextStanceIndex;
  617. this.stance = stances[ nextStanceIndex ];
  618. }
  619. if( this.stance == "full defense")
  620. this.rollMade["defense"] = this.skillRoll( "defense" ) ;
  621. }
  622. skillRoll( skill ){
  623. let skillRank = this.getSkillRank( "defense" );
  624. let traitRank = this[ skills[skill].trait ];
  625. return RNG.rk10( traitRank + skillRank, traitRank );
  626. }
  627. }
  628. var RNG = new RandomGenerator(4);
  629. function characterFromJSON( json ){
  630. let result = new Character();
  631. let data = JSON.parse(json);
  632. for( prop in data){
  633. result[ prop ] = data[ prop ];
  634. }
  635. return result;
  636. }
  637. function fight(charac1, charac2){
  638. let result = {
  639. "attacker" : charac1.initiative(),
  640. "defender" : charac2.initiative()
  641. };
  642. let first = ( charac1.initiative() + (charac1.water/10) > charac1.initiative() + (charac1.water()/10))? charac1 : charac2 ;
  643. let second = ( charac1 == first)? charac2 : charac1 ;
  644. let winner = 0
  645. let round = 0;
  646. while( !winner ){
  647. round++;
  648. result[round] = {
  649. "attack" : {
  650. "attacker" : first.attack(),
  651. "defender" : second.attack()
  652. },
  653. "damage" : {
  654. "attacker" : first.damage(),
  655. "defender" : second.damage()
  656. }
  657. };
  658. result[round]["wounds"] = {
  659. "attacker" : ( result[round]['attack']['attacker'] >= second.getTN() )? second.getWounded( result[round]['damage']['attacker'] ) : 0,
  660. "defender" : (( result[round]['attack']['defender'] >= first.getTN() ) && second.malus < 100)? first.getWounded( result[round]['damage']['defender'] ) : 0,
  661. }
  662. if( second.malus > 99 ){
  663. winner = first;
  664. } else if( first.malus > 99 )
  665. winner = second;
  666. }
  667. result['winner'] = winner ;
  668. result['winner_side'] = (winner == charac1)? "attacker": "defender";
  669. return result;
  670. }
  671. class Samourai extends Character {
  672. constructor( aRole, gender, name, familly, school, experience, gempukku, skills){
  673. super( aRole, skills, gender, name, experience, gempukku );
  674. this.setFamilly( familly );
  675. this.setBasicSchool( school );
  676. this.autoWearArmor();
  677. }
  678. setFamilly( familly_name ){
  679. let familly = famillies[ familly_name ];
  680. this[ familly.trait ]++;
  681. this.name['familly'] = familly_name;
  682. }
  683. setBasicSchool( school_name ){
  684. let school = basicSchool[ school_name ];
  685. this[ school.trait ]++;
  686. for(let i = 0 ; i < school.outfit.weapon.length ; i++){
  687. let weapon = (school.outfit.weapon[ i ] == "any")? Object.keys( randomFromAssociative( weapons ) ) : school.outfit.weapon[ i ];
  688. if( !(weapon in this.weapons) )
  689. this.weapons[ weapon ] = weapons[ weapon ];
  690. }
  691. this.armors = school.outfit.armor || this.armors;
  692. }
  693. autoWearArmor(){
  694. let maxArmor = "kimono";
  695. for(let i = 0 ; i < this.armors.length ; i++){
  696. if( armors[ this.armors[ i ] ].TN > armors[ maxArmor ].TN ){
  697. maxArmor = this.armors[i];
  698. }
  699. };
  700. this.equippedArmor = maxArmor;
  701. }
  702. }