Pixel Combat+

Makes it easier to create new custom enemies for Idle Pixel

This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greatest.deepsurf.us/scripts/491625/1437608/Pixel%20Combat%2B.js

  1. // ==UserScript==
  2. // @name Pixel Combat+
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.0.1
  5. // @description Makes it easier to create new custom enemies for Idle Pixel
  6. // @author Dounford
  7. // @license MIT
  8. // @match *://idle-pixel.com/login/play*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. //Default Enemy
  13. let defaultEnemy = {
  14. name:'Black Cat',
  15. image:"https://raw.githubusercontent.com/Dounford-Felipe/DHP-Pets/main/images/whiteCatMonster.png",
  16. hp:100,
  17. maxHp:100,
  18. accuracy:3,
  19. damage:2,
  20. speed:3,
  21. defence:5,
  22. multiPhase: false,
  23. nextPhase:'',
  24. arrowImunity:false,
  25. magicImunity:false,
  26. needsLight:false,
  27. weakToFire:false,
  28. weakToIce:false,
  29. poisoned: false,
  30. ghost: false,
  31. fish: false,
  32. defender: false,
  33. lootTable:"",
  34. lootFunction: "",
  35. winFunction: "",
  36. abilities:[]
  37. };
  38. /*abilities: [
  39. {type: 'heal', limit: -1, chance: 1, cooldown: 3, min:5,max:20, cd:10},
  40. {type: 'poison', chance: 1, poison:5, cd:5},
  41. {type: 'damage', limit: -1, chance: 0.25, cooldown: 3, min:5,max:20, cd:3},
  42. {type: 'kamikaze', chance: 1, cd: 120},
  43. {type: 'invisibility', limit: -1, chance: 1, cooldown: 30, cd:30},
  44. {type: 'reflect', limit: -1, chance: 1, cooldown: 15, cd:15}
  45. ]*/
  46. //[{item:'',image:'',min:1,max:10,chance:'1/x'}]
  47. //Ranged Weapons
  48. const ranged = ['wooden_bow','long_bow','haunted_bow','balista'];
  49. if (!document.getElementById('panel-customCombat')) {
  50. (function PixelCombatPlus() {
  51. 'use strict';
  52. const PixelCombatPlus = {
  53. initialize: function () {
  54. PixelCombatPlus.newFightPanel();
  55. PixelCombatPlus.newModals();
  56. if (IdlePixelPlus) {
  57. IdlePixelPlus.panels.customCombat = {id:'customCombat',title:'',content:''}
  58. } else {
  59. const og_switch_panels = window.switch_panels;
  60. window.switch_panels = function(id) {
  61. document.getElementById('panel-customCombat').style.display = "none";
  62. og_switch_panels.apply(this, arguments);
  63. }
  64. }
  65. },
  66. //Fighting toggle
  67. fight: false,
  68. //Hitsplat Maps
  69. hitSplatHero: {},
  70. hitSplatEnemy: {},
  71. //Timer until fight starts
  72. startsIn:0,
  73. //Interval called each second
  74. ticking:0,
  75. ticks: 0,
  76. //Enemy Stats
  77. enemy: {
  78. name:'Test',
  79. image:"",
  80. hp:10,
  81. maxHp:10,
  82. accuracy:3,
  83. damage:2,
  84. speed:3,
  85. defence:5,
  86. multiPhase: false,
  87. nextPhase:'',
  88. arrowImunity:false,
  89. magicImunity:false,
  90. needsLight:false,
  91. weakToFire:false,
  92. weakToIce:false,
  93. poisoned: false,
  94. ghost: false,
  95. fish: false,
  96. defender: false,
  97. lootTable: "",
  98. lootFunction: "",
  99. winFunction: "",
  100. },
  101. //Hero Stats
  102. hero: {
  103. hp:0,
  104. mana:0,
  105. revive:0,
  106. isReflecting:false,
  107. poisoned: false
  108. },
  109. //Spells Cooldown
  110. healCooldown: 0,
  111. fireCooldown: 0,
  112. reflectCooldown: 0,
  113. invisibilityCooldown: 0,
  114. heroIsInvisible: 0,
  115. enemyIsInvisible: 0,
  116. enemyIsCharging: 0,
  117. testFight: function() {
  118. PixelCombatPlus.startFight(defaultEnemy)
  119. },
  120. newModals: function() {
  121. let lootDiv = `<div style="width: 100%; height: 100%; position: absolute;top:0px; display: none;" id="customCombatModalParent">
  122. <div style="background-color: black;opacity: 0.7;width: 100%;height: 100%;position: absolute;" onclick="document.getElementById('customCombatModalParent').style.display='none'"></div>
  123. <div class="modal-content" id="customCombatModal" style="z-index: 11;position: sticky;right: 0px;left: 0px;margin-right: auto;margin-left: auto;width: 35%;border-radius: 5px;top: 100px;">
  124. <div class="modal-header">
  125. <h5 class="modal-title text-secondary">LOOT</h5>
  126. <button type="button" class="btn-close" onclick="document.getElementById('customCombatModalParent').style.display = 'none'"></button>
  127. </div>
  128. <div class="modal-body">
  129. <div id="modal-custom-loot-body">
  130. </div>
  131. </div>
  132. <div class="modal-footer">
  133. <button onclick="document.getElementById('customCombatModalParent').style.display = 'none'" id="modal-custom-loot-collect-button" class="background-primary"><span class="font-pixel hover">Collect Loot</span></button>
  134. </div>
  135. </div>
  136. </div>`
  137. document.getElementById('content').insertAdjacentHTML('beforeend', lootDiv);
  138. },
  139. //Adds the new combat scene
  140. newFightPanel: function () {
  141. let customCombatTab = `<div id="panel-customCombat" style="display:none">
  142. <button onclick="switch_panels('panel-combat')">BACK</button>
  143. <center>
  144. <table>
  145. <tbody>
  146. <tr>
  147. <td class="fight-right-border">
  148. </td>
  149. <td style="padding-top:20px;" class="canvas-fighting-td fight-top-border">
  150. <center>
  151. <span class="hp-progress-bar">
  152. <span id="custom-hero-progress-bar-hp" class="hp-progress-bar-inner" style="width: 100%;"></span>
  153. <div class="progress-bar-label">
  154. <span id="custom_combat_hp">0/0</span>
  155. </div>
  156. </span>
  157. <br>
  158. <span class="mana-progress-bar">
  159. <span id="custom-hero-progress-bar-mana" class="mana-progress-bar-inner" style="width: 100%;"></span>
  160. <div class="progress-bar-label color-cyan">
  161. <span id="custom_combat_mana">0/0</span>
  162. </div>
  163. </span>
  164. </center>
  165. </td>
  166. <td style="padding-bottom:20px;" class="canvas-fighting-td fight-top-border">
  167. <center>
  168. <span class="hp-progress-bar">
  169. <span id="custom-monster-progress-bar-hp" class="hp-progress-bar-inner" style="width: 100%;"></span>
  170. <div class="progress-bar-label">
  171. <span id="custom_combat_monster_hp">0/0</span>
  172. </div>
  173. </span>
  174. <br>
  175. </center>
  176. </td>
  177. <td class="fight-left-border">
  178. </td>
  179. </tr>
  180. <tr>
  181. <td style="vertical-align:top;" class="fight-right-border">
  182. <div class="fighting-hero-stats-area hover shadow" style="border-right:none;">
  183. <span id="custom-fighting-hero-label">Player</span>
  184. </div>
  185. <div class="td-combat-bottom-panel shadow">
  186. <div class="td-combat-stat-entry">
  187. <img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/accuracy_white.png" title="accuracy_white">
  188. <span style="color:white">Accuracy:</span>
  189. <span id="custom_combat_hero_accuracy">0</span>
  190. </div>
  191. <div class="td-combat-stat-entry">
  192. <img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/melee_damage_white.png" title="melee_damage_white">
  193. <span style="color:white">Damage:</span>
  194. <span id="custom_combat_hero_melee_damage">0</span>
  195. </div>
  196. <div class="td-combat-stat-entry">
  197. <img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/arrow_damage_white.png" title="arrow_damage_white">
  198. <span style="color:white">Damage:</span>
  199. <span id="custom_combat_hero_arrow_damage">0</span>
  200. </div>
  201. <div class="td-combat-stat-entry">
  202. <img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/magic_damage_white.png" title="magic_damage_white">
  203. <span style="color:white">Magic:</span>
  204. <span id="custom_combat_hero_magic_bonus">0</span>
  205. </div>
  206. <div class="td-combat-stat-entry">
  207. <img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/speed_white.png" title="speed_white">
  208. <span style="color:white">Speed:</span>
  209. <span id="custom_combat_hero_speed">0</span>
  210. </div>
  211. <div class="td-combat-stat-entry">
  212. <img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/defence_white.png" title="defence_white">
  213. <span style="color:white">Defence:</span>
  214. <span id="custom_combat_hero_defence">0</span>
  215. </div>
  216. </div>
  217. <div style="" id="custom-fighting-spell-heal" onclick="PixelCombatPlus.spell('heal')" class="fighting-spell-area-heal hover shadow">
  218. <img id="custom-image-heal_spell_icon" src="https://idlepixel.s3.us-east-2.amazonaws.com/images/heal_spell_icon.png" title="heal_spell_icon">
  219. <span id="custom-fighting-spell-label-heal" style="color: white;">Heal <span class="color-grey" style="color: rgb(128, 128, 128);">(Q)</span></span>
  220. </div>
  221. <div style="" id="custom-fighting-spell-fire" onclick="PixelCombatPlus.spell('fire')" class="fighting-spell-area-fire hover shadow">
  222. <img id="custom-image-fire_spell_icon" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/fire_spell_icon.png" title="fire_spell_icon" class="">
  223. <span id="custom-fighting-spell-label-fire" style="color: white;">Fire <span class="color-grey" style="color: rgb(128, 128, 128);">(E)</span></span>
  224. </div>
  225. <div style="" id="custom-fighting-spell-reflect" onclick="PixelCombatPlus.spell('reflect')" class="fighting-spell-area-fire hover shadow">
  226. <img id="custom-image-reflect_spell_icon" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/reflect_spell_icon.png" title="reflect_spell_icon" class="">
  227. <span id="custom-fighting-spell-label-reflect" style="color: white;">Reflect <span class="color-grey" style="color: rgb(128, 128, 128);">(E)</span></span>
  228. </div>
  229. <div style="" id="custom-fighting-spell-invisibility" onclick="PixelCombatPlus.spell('invisibility')" class="fighting-spell-area-invisibility hover shadow">
  230. <img id="custom-image-invisibility_spell_icon" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/invisibility_spell_icon.png" title="invisibility_spell_icon" class="">
  231. <span id="custom-fighting-spell-label-invisibility" style="color: white;">Invisibility <span class="color-grey" style="color: rgb(128, 128, 128);">(R)</span></span>
  232. </div>
  233. </td>
  234. <td class="canvas-fighting-td fight-bottom-border">
  235. <div style="display: none;" class="fighting-countdown">FIGHT IN <span id="custom-fighting-countdown">5</span></div>
  236. <canvas class="canvas-fighting" style="margin-left:100px;margin-right:100px" id="custom-combat-canvas-hero" width="300px" height="600px" original-width="300px" original-height="600px">
  237. </canvas>
  238. </td>
  239. <td class="canvas-fighting-td fight-bottom-border">
  240. <canvas class="canvas-fighting" id="custom-combat-canvas-monster" width="500px" height="600px" original-width="500px" original-height="600px" style="">
  241. </canvas>
  242. </td>
  243. <td style="vertical-align:top;" class="fight-left-border">
  244. <div class="fighting-monster-stats-area hover shadow">
  245. <span id="custom-fighting-monster-label">Enemy Name</span>
  246. </div>
  247. <div class="td-combat-bottom-panel shadow" style="border-left:none;">
  248. <div class="td-combat-stat-entry">
  249. <img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/accuracy_white.png" title="accuracy_white">
  250. <span style="color:white">Accuracy:</span>
  251. <span id="custom_combat_monster_accuracy">0</span>
  252. </div>
  253. <div class="td-combat-stat-entry">
  254. <img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/melee_damage_white.png" title="melee_damage_white">
  255. <span style="color:white">Damage:</span>
  256. <span id="custom_combat_monster_attack">0</span>
  257. </div>
  258. <div class="td-combat-stat-entry">
  259. <img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/speed_white.png" title="speed_white">
  260. <span style="color:white">Speed:</span>
  261. <span id="custom_combat_monster_speed">3</span>
  262. </div>
  263. <div class="td-combat-stat-entry">
  264. <img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/defence_white.png" title="defence_white">
  265. <span style="color:white">Defence:</span>
  266. <span id="custom_combat_monster_defence">0</span>
  267. </div>
  268. </div>
  269. </td>
  270. </tr>
  271. <tr>
  272. <td></td>
  273. <td>
  274. <center>
  275. <!-- presets -->
  276. <div id="custom-combat-presets-area" style="" class="combat-presets-area shadow center">
  277. <img src="https://d1xsc8x7nc5q8t.cloudfront.net/images/combat_presets.png" class="w20" title="combat_presets"> <u class="color-silver">Presets</u><br><br>
  278. <img data-tooltip="combat-preset-1" id="custom-in-combat-presets-icon-1" onclick="websocket.send('PRESET_LOAD=1~1')" class="combat-presets-combat-icon hover w30" src="" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-html="true" title="" data-bs-original-title="<span class='color-primary'>PRESETS</span><br /><br />Press 1 to quickload." aria-label="<span class='color-primary'>PRESETS</span><br /><br />Press 1 to quickload." style="background-color: rgb(219, 255, 220);">
  279. <img data-tooltip="combat-preset-2" id="custom-in-combat-presets-icon-2" onclick="websocket.send('PRESET_LOAD=2~1')" class="combat-presets-combat-icon hover w30" src="" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-html="true" title="" data-bs-original-title="<span class='color-primary'>PRESETS</span><br /><br />Press 2 to quickload." aria-label="<span class='color-primary'>PRESETS</span><br /><br />Press 2 to quickload." style="background-color: rgb(117, 126, 255);">
  280. <img data-tooltip="combat-preset-3" id="custom-in-combat-presets-icon-3" onclick="websocket.send('PRESET_LOAD=3~1')" class="combat-presets-combat-icon hover w30" src="" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-html="true" title="" data-bs-original-title="<span class='color-primary'>PRESETS</span><br /><br />Press 3 to quickload." aria-label="<span class='color-primary'>PRESETS</span><br /><br />Press 3 to quickload." style="background-color: rgb(219, 255, 220);">
  281. <img data-tooltip="combat-preset-4" id="custom-in-combat-presets-icon-4" onclick="websocket.send('PRESET_LOAD=4~1')" class="combat-presets-combat-icon hover w30" src="" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-html="true" title="" data-bs-original-title="<span class='color-primary'>PRESETS</span><br /><br />Press 4 to quickload." aria-label="<span class='color-primary'>PRESETS</span><br /><br />Press 4 to quickload." style="background-color: rgb(255, 87, 87);">
  282. <img data-tooltip="combat-preset-5" id="custom-in-combat-presets-icon-5" onclick="websocket.send('PRESET_LOAD=5~1')" class="combat-presets-combat-icon hover w30" src="" data-bs-toggle="tooltip" data-bs-placement="right" data-bs-html="true" title="" data-bs-original-title="<span class='color-primary'>PRESETS</span><br /><br />Press 5 to quickload." aria-label="<span class='color-primary'>PRESETS</span><br /><br />Press 5 to quickload." style="background-color: rgb(219, 255, 220);">
  283. </div>
  284. </center>
  285. <!-- end presets -->
  286. </td>
  287. <td></td>
  288. <td></td>
  289. </tr>
  290. </tbody>
  291. </table>
  292. </center>
  293. </div>`
  294. document.getElementById('panels').insertAdjacentHTML('beforeend', customCombatTab);
  295. let combatNot = `<div id="notification-custom-combat" style="display: none;" onclick="switch_panels('panel-customCombat');document.getElementById('menu-bar').style.display = 'none';" class="notification hover">
  296. <img src="https://d1xsc8x7nc5q8t.cloudfront.net/images/fight.png" class="w20" title="fight">
  297. <span style="color:red">IN COMBAT!</span>
  298. <span style="color:grey">(Click to resume)</span>
  299. <span class="color-white" id="notification-combat"></span>
  300. </div>`
  301. document.getElementById('notification-combat').insertAdjacentHTML('afterend', combatNot);
  302. PixelCombatPlus.heroCanvas = document.getElementById("custom-combat-canvas-hero");
  303. PixelCombatPlus.heroContext = document.getElementById("custom-combat-canvas-hero").getContext("2d");
  304. PixelCombatPlus.enemyCanvas = document.getElementById("custom-combat-canvas-monster");
  305. PixelCombatPlus.enemyContext = document.getElementById("custom-combat-canvas-monster").getContext("2d");
  306. PixelCombatPlus.enemyImage = new Image();
  307. document.addEventListener('keydown', function(e) {
  308. const chatInput = document.getElementById('chat-area-input');
  309. const customCombatPanel = document.getElementById('panel-customCombat');
  310. if (!chatInput.matches(':focus') && customCombatPanel.style.display !== "none") {
  311. switch (e.keyCode) {
  312. //Presets
  313. case 49: websocket.send('PRESET_LOAD=1~1'); break;
  314. case 50: websocket.send('PRESET_LOAD=2~1'); break;
  315. case 51: websocket.send('PRESET_LOAD=3~1'); break;
  316. case 52: websocket.send('PRESET_LOAD=4~1'); break;
  317. case 53: websocket.send('PRESET_LOAD=5~1'); break;
  318. //Spells
  319. case 81: PixelCombatPlus.spell('heal'); break;
  320. case 87: PixelCombatPlus.spell('fire'); break;
  321. case 69: PixelCombatPlus.spell('reflect'); break;
  322. case 82: PixelCombatPlus.spell('invisibility'); break;
  323. }
  324. }
  325. });
  326. },
  327. //Refresh the presets on the custom combat
  328. refreshPresetIcons: function() {
  329. for(let i = 1; i < 6 ; i++) {
  330. document.getElementById("custom-in-combat-presets-icon-" + i).src = get_image("images/" + Items.getItem("combat_preset_icon_" + i));
  331. document.getElementById("custom-in-combat-presets-icon-" + i).style.backgroundColor = Items.getItemString("combat_preset_color_" + i);
  332. }
  333. },
  334. //Cooldown function
  335. cooldown: function(variable,time,id,defaultText) {
  336. PixelCombatPlus[variable] = time;
  337. if (typeof id == 'string') {
  338. document.getElementById(id).innerHTML = time;
  339. document.getElementById(id).parentNode.style.display = "";
  340. };
  341. if (time > 0) {
  342. setTimeout(function(){
  343. PixelCombatPlus.cooldown(variable,time-1,id,defaultText);
  344. },1000)
  345. } else if (typeof defaultText == 'string') {
  346. if (defaultText == "hide") {
  347. document.getElementById(id).parentNode.style.display = "none";
  348. } else {
  349. document.getElementById(id).innerHTML = defaultText;
  350. }
  351. };
  352. },
  353. //Cooldown function
  354. cooldownAbility: function(index,time) {
  355. if (PixelCombatPlus.fight == false) {PixelCombatPlus.enemy.abilities = []};
  356. if (PixelCombatPlus.enemy.abilities[index] == undefined) {return};
  357. PixelCombatPlus.enemy.abilities[index].cd = time;
  358. if (time > 0) {
  359. setTimeout(function(){
  360. PixelCombatPlus.cooldownAbility(index,time-1);
  361. },1000)
  362. }
  363. },
  364. //Spell Casting Function
  365. spell: function(spellName) {
  366. if (PixelCombatPlus[spellName+'Cooldown'] == 0) {
  367. switch (spellName) {
  368. case "heal":
  369. if (PixelCombatPlus.hero.mana >= 2) {
  370. PixelCombatPlus.hero.mana -= 2;
  371. PixelCombatPlus.hero.hp += 3;
  372. PixelCombatPlus.hero.hp = Math.min(PixelCombatPlus.hero.hp,var_max_hp);
  373. PixelCombatPlus.updateStatsBars();
  374. PixelCombatPlus.addHitSplat("3", 'images/heal_spell.png', 'lime', 'rgba(0,255,0,0.4)', 'blue', 'Hero');
  375. PixelCombatPlus.cooldown('healCooldown',5,'custom-fighting-spell-label-heal','Heal <span class="color-grey" style="color: rgb(128, 128, 128);">(Q)</span>');
  376. }
  377. break;
  378. case "fire":
  379. if (PixelCombatPlus.hero.mana >= 3) {
  380. PixelCombatPlus.hero.mana -= 3;
  381. let fireDamage = Math.floor(Math.random() * 6) + parseInt(var_magic_bonus);
  382. if (PixelCombatPlus.enemy.weakToFire == true) {
  383. fireDamage *= 2
  384. };
  385. if (PixelCombatPlus.enemy.magicImunity == false) {
  386. PixelCombatPlus.enemy.hp -= fireDamage;
  387. PixelCombatPlus.addHitSplat(fireDamage, 'images/fire_icon.png', 'white', 'rgba(255,0,0,0.4)', 'blue', 'Enemy');
  388. } else {
  389. PixelCombatPlus.addHitSplat('IMMUNE', 'images/fire_icon.png', 'white', 'rgba(255,0,0,0.4)', 'blue', 'Enemy');
  390. };
  391. PixelCombatPlus.updateStatsBars();
  392. PixelCombatPlus.cooldown('fireCooldown',5,'custom-fighting-spell-label-fire','Fire <span class="color-grey" style="color: rgb(128, 128, 128);">(W)</span>');
  393. }
  394. break;
  395. case "reflect":
  396. if (PixelCombatPlus.hero.mana >= 1 && PixelCombatPlus.hero.isReflecting == false) {
  397. PixelCombatPlus.hero.mana -= 1;
  398. PixelCombatPlus.hero.isReflecting = true;
  399. PixelCombatPlus.updateStatsBars();
  400. PixelCombatPlus.cooldown('reflectCooldown',30,'custom-fighting-spell-label-reflect','Reflect <span class="color-grey" style="color: rgb(128, 128, 128);">(E)</span>');
  401. }
  402. break;
  403. case "invisibility":
  404. if (PixelCombatPlus.hero.mana >= 2) {
  405. PixelCombatPlus.hero.mana -= 2;
  406. PixelCombatPlus.updateStatsBars();
  407. PixelCombatPlus.cooldown('heroIsInvisible',4);
  408. PixelCombatPlus.cooldown('invisibilityCooldown',30,'custom-fighting-spell-label-invisibility','Invisibility <span class="color-grey" style="color: rgb(128, 128, 128);">(R)</span>');
  409. }
  410. break;
  411. };
  412. }
  413. },
  414. poison: function(receiver,poisonDamage) {
  415. PixelCombatPlus[receiver].hp -= poisonDamage;
  416. PixelCombatPlus.addHitSplat(poisonDamage, 'images/poison.png', 'green', 'rgba(255,0,0,0.4)', 'blue', receiver.charAt(0).toLocaleUpperCase() + receiver.slice(1));
  417. PixelCombatPlus.updateStatsBars();
  418. if (PixelCombatPlus.hero.hp > 0 && PixelCombatPlus.enemy.hp > 0) {setTimeout(function(){PixelCombatPlus.poison(receiver,poisonDamage)},4000)};
  419. },
  420. //Enemy Special Attack
  421. specialAttack: function() {
  422. if (typeof PixelCombatPlus.enemy.abilities == 'object') {
  423. PixelCombatPlus.enemy.abilities.forEach(function(ability,index) {
  424. if (ability.limit == 0 || ability.cd > 0) {
  425. return;
  426. };
  427. const randomChance = Math.random();
  428. if (ability.chance > randomChance) {
  429. switch (ability.type) {
  430. case 'heal':
  431. let healAmount = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min)
  432. PixelCombatPlus.enemy.hp += healAmount;
  433. PixelCombatPlus.enemy.hp = Math.min(PixelCombatPlus.enemy.hp,PixelCombatPlus.enemy.maxHp);
  434. PixelCombatPlus.updateStatsBars();
  435. PixelCombatPlus.addHitSplat(healAmount, 'images/heal_spell.png', 'lime', 'rgba(0,255,0,0.4)', 'blue', 'Enemy');
  436. break;
  437. case 'poison':
  438. if (PixelCombatPlus.hero.poisoned == true) {return}
  439. PixelCombatPlus.hero.poisoned = true;
  440. const poisonDamage = ability.poison || 5
  441. PixelCombatPlus.poison('hero',poisonDamage)
  442. break;
  443. case 'damage':
  444. if (PixelCombatPlus.heroIsInvisible > 0) {
  445. PixelCombatPlus.addHitSplat("MISSED","images/ghost_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
  446. } else {
  447. let damageDone = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min);
  448. if (PixelCombatPlus.hero.isReflecting == true && damageDone > 0) {
  449. PixelCombatPlus.enemy.hp -= damageDone;
  450. PixelCombatPlus.hero.isReflecting = false;
  451. PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
  452. } else {
  453. PixelCombatPlus.hero.hp -= damageDone;
  454. PixelCombatPlus.addHitSplat(damageDone,"images/sword_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
  455. }
  456. PixelCombatPlus.updateStatsBars();
  457. }
  458. break;
  459. case 'chargeDamage':
  460. if (PixelCombatPlus.enemyIsCharging > 0) {return};
  461. PixelCombatPlus.cooldown('enemyIsCharging',4);
  462. setTimeout(function() {
  463. if (PixelCombatPlus.heroIsInvisible > 0) {
  464. PixelCombatPlus.addHitSplat("MISSED","images/ghost_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
  465. } else {
  466. let damageDone = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min);
  467. if (PixelCombatPlus.hero.isReflecting == true && damageDone > 0) {
  468. PixelCombatPlus.enemy.hp -= damageDone;
  469. PixelCombatPlus.hero.isReflecting = false;
  470. PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
  471. } else {
  472. PixelCombatPlus.hero.hp -= damageDone;
  473. PixelCombatPlus.addHitSplat(damageDone,"images/sword_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
  474. }
  475. PixelCombatPlus.updateStatsBars();
  476. }
  477. },4000);
  478. break;
  479. case 'lifeSteal':
  480. if (PixelCombatPlus.heroIsInvisible > 0) {
  481. PixelCombatPlus.addHitSplat("MISSED","images/ghost_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
  482. } else {
  483. let damageDone = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min);
  484. if (PixelCombatPlus.hero.isReflecting == true && damageDone > 0) {
  485. PixelCombatPlus.enemy.hp -= damageDone;
  486. PixelCombatPlus.hero.isReflecting = false;
  487. PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
  488. } else {
  489. PixelCombatPlus.hero.hp -= damageDone;
  490. PixelCombatPlus.enemy.hp += damageDone;
  491. PixelCombatPlus.enemy.hp = Math.min(PixelCombatPlus.enemy.hp,PixelCombatPlus.enemy.maxHp);
  492. PixelCombatPlus.addHitSplat(damageDone,"images/sword_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
  493. PixelCombatPlus.addHitSplat(damageDone, 'images/heal_spell.png', 'lime', 'rgba(0,255,0,0.4)', 'blue', 'Enemy');
  494. }
  495. PixelCombatPlus.updateStatsBars();
  496. };
  497. break;
  498. case 'kamikaze':
  499. PixelCombatPlus.hero.hp = 0;
  500. PixelCombatPlus.endFight();
  501. break;
  502. case "invisibility":
  503. if (PixelCombatPlus.enemyIsInvisible > 0) {return}
  504. let invisibleTime = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min);
  505. PixelCombatPlus.cooldown('enemyIsInvisible',invisibleTime);
  506. break;
  507. case "reflect":
  508. if (PixelCombatPlus.enemy.isReflecting == true) {return};
  509. PixelCombatPlus.enemy.isReflecting = true;
  510. break;
  511. case "fullRestorePlayer":
  512. PixelCombatPlus.hero.hp = var_max_hp; //Set the current hero hp to max
  513. PixelCombatPlus.hero.mana = var_max_mana; //Set the current hero mana to max
  514. PixelCombatPlus.updateStatsBars();
  515. break;
  516. case "restorePlayerHP":
  517. let healAmounts = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min)
  518. PixelCombatPlus.hero.hp += healAmounts;
  519. PixelCombatPlus.hero.hp = Math.min(PixelCombatPlus.hero.hp,var_max_hp);
  520. PixelCombatPlus.updateStatsBars();
  521. PixelCombatPlus.addHitSplat(healAmounts, 'images/heal_spell.png', 'lime', 'rgba(0,255,0,0.4)', 'blue', 'Hero');
  522. break;
  523. case "restorePlayerMana":
  524. let manaAmount = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min)
  525. PixelCombatPlus.hero.mana += manaAmount;
  526. PixelCombatPlus.hero.mana = Math.min(PixelCombatPlus.hero.mana,var_max_mana);
  527. PixelCombatPlus.updateStatsBars();
  528. break;
  529. };
  530. if (ability.limit != -1) {
  531. ability.limit--;
  532. };
  533. if (ability.cooldown > 0) {
  534. PixelCombatPlus.cooldownAbility(index,ability.cooldown)
  535. };
  536. };
  537. });
  538. }
  539. },
  540.  
  541. //Update the stats bar on combat scene
  542. updateStatsBars: function() {
  543. //Hero
  544. document.getElementById("custom_combat_hp").innerHTML = Math.max(0,PixelCombatPlus.hero.hp) + "/" + var_max_hp; //Set the number on the hero hp bar
  545. let heroHpPercentage = PixelCombatPlus.hero.hp / var_max_hp * 100;
  546. document.getElementById("custom-hero-progress-bar-hp").style.width = heroHpPercentage.toFixed() + "%"; // Set the hero hp bar background
  547. //Mana
  548. document.getElementById("custom_combat_mana").innerHTML = Math.max(0,PixelCombatPlus.hero.mana) + "/" + var_max_mana; //Set the number on the hero mana bar
  549. let heroManaPercentage = PixelCombatPlus.hero.mana / var_max_mana * 100;
  550. document.getElementById("custom-hero-progress-bar-mana").style.width = heroManaPercentage.toFixed() + "%"; // Set the mana hp bar background
  551. //Enemy
  552. document.getElementById("custom_combat_monster_hp").innerHTML = Math.max(0,PixelCombatPlus.enemy.hp) + "/" + PixelCombatPlus.enemy.maxHp; //Set the number on the enemy hp bar
  553. let EnemyHpPercentage = PixelCombatPlus.enemy.hp / PixelCombatPlus.enemy.maxHp * 100;
  554. document.getElementById("custom-monster-progress-bar-hp").style.width = EnemyHpPercentage.toFixed() + "%"; // Set the enemy hp bar background
  555. },
  556. //Update the enemy stats mid fight, can be used for pvp
  557. updateEnemyStats: function(foe) {
  558. PixelCombatPlus.enemyImage.src = foe.image;
  559. PixelCombatPlus.enemy.abilities = [];
  560. for (const key in foe) {
  561. PixelCombatPlus.enemy[key] = foe[key];
  562. };
  563. PixelCombatPlus.updateStatsBars();
  564. PixelCombatPlus.enemy.abilities.forEach(function(ability,index) {if (ability.cd > 0){PixelCombatPlus.cooldownAbility(index,ability.cd)}});
  565. document.getElementById("custom-fighting-monster-label").innerText = PixelCombatPlus.enemy.name;
  566. document.getElementById("custom_combat_monster_accuracy").innerText = PixelCombatPlus.enemy.accuracy == -1 ? 1 : PixelCombatPlus.enemy.accuracy;
  567. document.getElementById("custom_combat_monster_attack").innerText = PixelCombatPlus.enemy.damage;
  568. document.getElementById("custom_combat_monster_speed").innerText = PixelCombatPlus.enemy.speed;
  569. document.getElementById("custom_combat_monster_defence").innerText = PixelCombatPlus.enemy.defence;
  570. },
  571. //Define the enemy image
  572. setEnemyImage: function(foe) {
  573. try {
  574. PixelCombatPlus.enemyImage.src = foe;
  575. } catch (error) {
  576. setTimeout(function() {
  577. try {
  578. PixelCombatPlus.enemyImage.src = foe;
  579. } catch (error) {
  580. PixelCombatPlus.setEnemyImage(foe)
  581. }
  582. }, 1000);
  583. }
  584. },
  585. //Starts the fight
  586. startFight: function(foe) {
  587. if (PixelCombatPlus.fight == false) {
  588. //Make sure that there is nothing remaining from the last fight
  589. PixelCombatPlus.enemy.poisoned = false;
  590. PixelCombatPlus.hero.poisoned = false;
  591. PixelCombatPlus.hero.isReflecting = false;
  592. PixelCombatPlus.hitSplatHero = {};
  593. PixelCombatPlus.hitSplatEnemy = {};
  594. PixelCombatPlus.hero.revive = 0;
  595. //Stats Update
  596. PixelCombatPlus.hero.hp = var_max_hp; //Set the current hero hp to max
  597. PixelCombatPlus.hero.mana = var_max_mana; //Set the current hero mana to max
  598. PixelCombatPlus.setEnemyImage(foe.image) //Set the enemy image
  599. for (const key in foe) {PixelCombatPlus.enemy[key] = foe[key]}; //Set the current enemy
  600. PixelCombatPlus.enemy.poisoned = false; //Removes poison
  601. if (PixelCombatPlus.enemy.speed > 6) {PixelCombatPlus.enemy.speed = 6}; // 6 is the max speed
  602. if (PixelCombatPlus.enemy.hp > PixelCombatPlus.enemy.maxHp) {PixelCombatPlus.enemy.hp = PixelCombatPlus.enemy.maxHp}; // Enemy can't have more than max hp
  603. //UI Update
  604. PixelCombatPlus.refreshPresetIcons(); //Load the preset icon and color
  605. PixelCombatPlus.updateStatsBars(); //Updates all stats on UI
  606. //Hero Stats
  607. document.getElementById("custom-fighting-hero-label").innerText = var_username;
  608. document.getElementById("custom_combat_hero_accuracy").innerText = var_accuracy;
  609. document.getElementById("custom_combat_hero_melee_damage").innerText = var_melee_damage;
  610. document.getElementById("custom_combat_hero_arrow_damage").innerText = var_arrow_damage;
  611. document.getElementById("custom_combat_hero_magic_bonus").innerText = var_magic_bonus;
  612. document.getElementById("custom_combat_hero_speed").innerText = var_speed;
  613. document.getElementById("custom_combat_hero_defence").innerText = var_defence;
  614. //Enemy Stats
  615. document.getElementById("custom-fighting-monster-label").innerText = PixelCombatPlus.enemy.name;
  616. document.getElementById("custom_combat_monster_accuracy").innerText = PixelCombatPlus.enemy.accuracy == -1 ? 1 : PixelCombatPlus.enemy.accuracy;
  617. document.getElementById("custom_combat_monster_attack").innerText = PixelCombatPlus.enemy.damage;
  618. document.getElementById("custom_combat_monster_speed").innerText = PixelCombatPlus.enemy.speed;
  619. document.getElementById("custom_combat_monster_defence").innerText = PixelCombatPlus.enemy.defence;
  620. switch_panels('panel-customCombat'); //Go to the fight scene
  621. document.getElementById('menu-bar').style.display = "none"; //Hides lateral bar
  622. document.getElementById('notification-custom-combat').style.display = "" //Shows the combat notification
  623. document.getElementById('notification-custom-combat').style.display = "" //Shows the combat notification
  624. PixelCombatPlus.fight = true; //Starts the fight
  625.  
  626. PixelCombatPlus.cooldown('startsIn',5,'custom-fighting-countdown','hide'); //Start the timer to fight
  627. PixelCombatPlus.ticking = setInterval(function() {
  628. PixelCombatPlus.tick()
  629. }, 1000 / 60);
  630. setTimeout(function(){
  631. PixelCombatPlus.attack("hero");
  632. PixelCombatPlus.attack("enemy");
  633. PixelCombatPlus.enemy.abilities.forEach(function(ability,index) {if (ability.cd > 0){PixelCombatPlus.cooldownAbility(index,ability.cd)}});
  634. }, 6000);
  635. }
  636. },
  637. //Hit function
  638. hitRate: function(defence,accuracy) {
  639. if (accuracy == -1) {return false};
  640. let hitRandom = Math.random();
  641. let hitChance = 0;
  642. if (((defence / 2) - accuracy) > 4) {
  643. hitChance = 1 / (Math.max(1, ((defence / 2) - accuracy)) + 1);
  644. } else if (((defence / 2) - accuracy) <= 0) {
  645. hitChance = 1;
  646. } else {
  647. hitChance = 1 - (((defence / 2) - accuracy) * 2 / 10);
  648. };
  649. if (PixelCombatPlus.enemy.needsLight == true && !(var_ring_of_light_equipped == 1 || var_shield == 'lantern')) {hitChance = 0.5};
  650. return hitRandom <= hitChance
  651. },
  652. //Attack function
  653. attack: function(attacker){
  654. if (PixelCombatPlus.fight == true) {
  655. if (attacker == "hero") {
  656. //Poison
  657. if (PixelCombatPlus.enemy.poisoned == false && var_weapon.includes('poison')) {
  658. PixelCombatPlus.enemy.poisoned = true;
  659. PixelCombatPlus.poison('enemy',5);
  660. };
  661. //If hit succeed
  662. if (PixelCombatPlus.hitRate(PixelCombatPlus.enemy.defence,var_accuracy)) {
  663. if (PixelCombatPlus.enemyIsInvisible > 0) {
  664. PixelCombatPlus.addHitSplat("MISSED","images/ghost_icon.png","white","rgba(255,0,0,0.6)","blue","Enemy");
  665. } else {
  666. if (ranged.includes(var_weapon)) {
  667. if (PixelCombatPlus.enemy.arrowImunity == true) {
  668. PixelCombatPlus.addHitSplat('IMMUNE', 'images/blocked.png', 'white', 'rgba(255,0,0,0.4)', 'blue', 'Enemy');
  669. } else {
  670. let damageDone = Math.floor(Math.random() * parseInt(var_arrow_damage));
  671. if ((PixelCombatPlus.enemy.weakToFire == true && var_arrows == 'fire_arrows') || (PixelCombatPlus.enemy.weakToIce == true && var_arrows == 'ice_arrows')) {
  672. damageDone *= 2;
  673. }
  674. if (PixelCombatPlus.enemy.isReflecting == true && damageDone > 0) {
  675. PixelCombatPlus.hero.hp -= damageDone;
  676. PixelCombatPlus.enemy.isReflecting = false;
  677. PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Hero');
  678. } else {
  679. PixelCombatPlus.enemy.hp -= damageDone;
  680. PixelCombatPlus.addHitSplat(damageDone, "images/" + Items.getItemString('weapon')+".png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
  681. }
  682. };
  683. } else {
  684. let damageDone = Math.floor(Math.random() * parseInt(var_melee_damage))
  685. if (PixelCombatPlus.enemy.ghost == true) {
  686. if (var_weapon == 'scythe') {damageDone *= 2};
  687. if (var_weapon == 'double_scythe') {damageDone *= 4};
  688. } else if (PixelCombatPlus.enemy.fish == true) {
  689. if (var_weapon.includes('trident')) {damageDone *= 2};
  690. };
  691. if (PixelCombatPlus.enemy.isReflecting == true && damageDone > 0) {
  692. PixelCombatPlus.hero.hp -= damageDone;
  693. PixelCombatPlus.enemy.isReflecting = false;
  694. PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Hero');
  695. } else {
  696. PixelCombatPlus.enemy.hp -= damageDone;
  697. PixelCombatPlus.addHitSplat(damageDone, "images/" + Items.getItemString('weapon')+".png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
  698. if (PixelCombatPlus.enemy.defender == true) {
  699. PixelCombatPlus.hero.hp -= 1;
  700. PixelCombatPlus.addHitSplat(1, "images/" + Items.getItemString('weapon')+".png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Hero');
  701. };
  702. };
  703. };
  704. }
  705. } else {
  706. PixelCombatPlus.addHitSplat("0", "images/blocked.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
  707. };
  708. //Hero attack again
  709. setTimeout(function(){PixelCombatPlus.attack("hero")},(7-var_speed)*1000)
  710. } else {
  711. if (PixelCombatPlus.hitRate(var_defence,PixelCombatPlus.enemy.accuracy)) {
  712. if (PixelCombatPlus.heroIsInvisible > 0) {
  713. PixelCombatPlus.addHitSplat("MISSED","images/ghost_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
  714. } else {
  715. let damageDone = Math.floor(Math.random() * PixelCombatPlus.enemy.damage);
  716. if (PixelCombatPlus.hero.isReflecting == true && damageDone > 0) {
  717. PixelCombatPlus.enemy.hp -= damageDone;
  718. PixelCombatPlus.hero.isReflecting = false;
  719. PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
  720. } else {
  721. PixelCombatPlus.hero.hp -= damageDone;
  722. PixelCombatPlus.addHitSplat(damageDone,"images/sword_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
  723. }
  724. }
  725. } else {
  726. PixelCombatPlus.addHitSplat("0", "images/blocked.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Hero');
  727. };
  728. //Enemy attack again
  729. setTimeout(function(){PixelCombatPlus.attack("enemy")},(7-PixelCombatPlus.enemy.speed)*1000)
  730. }
  731. //Update hps
  732. PixelCombatPlus.updateStatsBars();
  733. }
  734. },
  735. //HitSplat Generator
  736. addHitSplat: function(label, icon, label_color, background_color, border_color, source) {
  737. let splatX = source == "Hero" ? 150 : 200
  738. let splatY = source == 450
  739. let splat = new HitSplat(label, icon, label_color, background_color, border_color, splatX, 450);
  740.  
  741. let random_key = rand(1,500000);
  742. PixelCombatPlus['hitSplat'+source][random_key] = splat;
  743.  
  744. setTimeout(
  745. function(){
  746. delete PixelCombatPlus['hitSplat'+source][random_key];
  747. }
  748. ,1000)
  749. },
  750. //Evething that should be called each second
  751. tick: function() {
  752. //UI
  753. //Hero Stats
  754. document.getElementById("custom_combat_hero_accuracy").innerText = var_accuracy;
  755. document.getElementById("custom_combat_hero_melee_damage").innerText = var_melee_damage;
  756. document.getElementById("custom_combat_hero_arrow_damage").innerText = var_arrow_damage;
  757. document.getElementById("custom_combat_hero_magic_bonus").innerText = var_magic_bonus;
  758. document.getElementById("custom_combat_hero_speed").innerText = var_speed;
  759. document.getElementById("custom_combat_hero_defence").innerText = var_defence;
  760. PixelCombatPlus.tickCanvas();
  761. PixelCombatPlus.manageHitplats();
  762. PixelCombatPlus.ticks++
  763. if (PixelCombatPlus.ticks == 60) {
  764. if (PixelCombatPlus.enemy.hp <= 0) {
  765. if (PixelCombatPlus.enemy.multiPhase) {
  766. PixelCombatPlus.updateEnemyStats(PixelCombatPlus.enemy.nextPhase)
  767. } else {
  768. PixelCombatPlus.endFight();
  769. }
  770. };
  771. if (PixelCombatPlus.hero.hp <= 0) {
  772. if (var_badge_death_1_hp == 1 && PixelCombatPlus.hero.revive == 0) {
  773. PixelCombatPlus.hero.hp = 1;
  774. PixelCombatPlus.hero.revive = 1;
  775. PixelCombatPlus.updateStatsBars();
  776. } else {
  777. PixelCombatPlus.endFight();
  778. }
  779. };
  780. if(PixelCombatPlus.startsIn <= 0) {PixelCombatPlus.specialAttack()}
  781. PixelCombatPlus.ticks = 0;
  782. };
  783. },
  784. tickCanvas: function() {
  785. PixelCombatPlus.heroContext.clearRect(0, 0, PixelCombatPlus.heroCanvas.width, PixelCombatPlus.heroCanvas.height);
  786. PixelCombatPlus.enemyContext.clearRect(0, 0, PixelCombatPlus.enemyCanvas.width, PixelCombatPlus.enemyCanvas.height);
  787. if (PixelCombatPlus.heroIsInvisible > 0) {
  788. PixelCombatPlus.heroContext.fillStyle = "white";
  789. PixelCombatPlus.heroContext.globalAlpha = 0.1;
  790. PixelCombatPlus.heroContext.fillRect(155, 20, 50, 50);
  791. PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/ghost_icon.png","hero_invisible"), 155, 20);
  792. } else {
  793. PixelCombatPlus.heroContext.globalAlpha = 1.0;
  794. };
  795. if (PixelCombatPlus.enemyIsInvisible > 0) {
  796. PixelCombatPlus.enemyContext.fillStyle = "white";
  797. PixelCombatPlus.enemyContext.globalAlpha = 0.1;
  798. PixelCombatPlus.enemyContext.fillRect(280, 20, 50, 50);
  799. PixelCombatPlus.enemyContext.drawImage(Cache.getImage("images/ghost_icon.png","hero_invisible"), 280, 20);
  800. } else {
  801. PixelCombatPlus.enemyContext.globalAlpha = 1.0;
  802. };
  803. if (PixelCombatPlus.hero.isReflecting == true) {
  804. PixelCombatPlus.heroContext.fillStyle = "white";
  805. PixelCombatPlus.heroContext.fillRect(95, 20, 50, 50);
  806. PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/reflect_spell.png","hero_reflecting"), 95, 20);
  807. };
  808. if (PixelCombatPlus.enemy.isReflecting == true) {
  809. PixelCombatPlus.enemyContext.fillStyle = "white";
  810. PixelCombatPlus.enemyContext.fillRect(170, 20, 50, 50);
  811. PixelCombatPlus.enemyContext.drawImage(Cache.getImage("images/reflect_spell.png","hero_reflecting"), 170, 20);
  812. };
  813. if (PixelCombatPlus.enemyIsCharging > 0) {
  814. PixelCombatPlus.enemyContext.fillStyle = "white";
  815. PixelCombatPlus.enemyContext.fillRect(225, 20, 50, 50);
  816. PixelCombatPlus.enemyContext.fillStyle = "black";
  817. PixelCombatPlus.enemyContext.font = "50px serif";
  818. PixelCombatPlus.enemyContext.fillText(PixelCombatPlus.enemyIsCharging, 238, 60);
  819. };
  820. PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_head_" + Items.getItemString('head')+".png","hero_fighting_head"), 0, 300);
  821. PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_body_" + Items.getItemString('body')+".png","hero_fighting_body"), 0, 300);
  822. PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_gloves_" + Items.getItemString('gloves')+".png","hero_fighting_gloves"), 0, 300);
  823. PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_legs_" + Items.getItemString('legs')+".png","hero_fighting_legs"), 0, 300);
  824. PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_boots_" + Items.getItemString('boots')+".png","hero_fighting_boots"), 0, 300);
  825. PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_amulet_" + Items.getItemString('amulet')+".png","hero_fighting_amulet"), 0, 300);
  826. PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_shield_" + Items.getItemString('shield')+".png","hero_fighting_shield"), 0, 300);
  827. PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_weapon_" + Items.getItemString('weapon')+".png","hero_fighting_weapon"), 0, 300);
  828. if (PixelCombatPlus.enemyImage.height !== 600) {
  829. let newWidth = 200 / (PixelCombatPlus.enemyImage.height / PixelCombatPlus.enemyImage.width)
  830. PixelCombatPlus.enemyContext.drawImage(PixelCombatPlus.enemyImage,(500-newWidth)/2,375,newWidth,200);
  831. } else {
  832. PixelCombatPlus.enemyContext.drawImage(PixelCombatPlus.enemyImage,0,0);
  833. }; //Enemy Image
  834. },
  835. manageHitplats: function() {
  836. for (let key in PixelCombatPlus.hitSplatHero) {
  837. PixelCombatPlus.hitSplatHero[key].draw(PixelCombatPlus.heroContext);
  838. };
  839. for (let key in PixelCombatPlus.hitSplatEnemy) {
  840. PixelCombatPlus.hitSplatEnemy[key].draw(PixelCombatPlus.enemyContext);
  841. };
  842. },
  843. looting: function() {
  844. let lootedItems = [];
  845. let lootedItemsHTML = '';
  846. document.getElementById('modal-custom-loot-body').innerHTML = ''
  847. PixelCombatPlus.enemy.lootTable.forEach(function(loot){
  848. let dropChance = Math.random() * (loot.chance - 1) + 1;
  849. if (loot.chance == dropChance) {
  850. let dropAmount = Math.random() * (loot.max - loot.min) + loot.min;
  851. if (dropAmount == 0) {dropAmount = ''};
  852. lootedItemsHTML += `<div class="loot" style="background-color:#cce6ff">
  853. <img src="${loot.image}" class="w50 me-3">${dropAmount} ${loot.item}
  854. </div>`;
  855. lootedItems.push({item:loot.item,amount:dropAmount});
  856. };
  857. });
  858. document.getElementById('modal-custom-loot-body').insertAdjacentHTML('beforeend', lootedItemsHTML);
  859. document.getElementById('customCombatModalParent').style.display = "";
  860. return lootedItems;
  861. },
  862. endFight: function() {
  863. PixelCombatPlus.fight = false;
  864. clearInterval(PixelCombatPlus.ticking);
  865. PixelCombatPlus.enemy.poisoned = false;
  866. PixelCombatPlus.hero.poisoned = false;
  867. PixelCombatPlus.hero.isReflecting = false;
  868. PixelCombatPlus.hitSplatHero = {};
  869. PixelCombatPlus.hitSplatEnemy = {};
  870. PixelCombatPlus.healCooldown = 0;
  871. PixelCombatPlus.fireCooldown = 0;
  872. PixelCombatPlus.reflectCooldown = 0;
  873. PixelCombatPlus.invisibilityCooldown = 0;
  874. PixelCombatPlus.heroIsInvisible = 0;
  875. PixelCombatPlus.hero.revive = 0;
  876. if (PixelCombatPlus.enemy.hp <= 0) {
  877. if (typeof PixelCombatPlus.enemy.lootTable == 'object') {
  878. PixelCombatPlus.enemy.lootFunction(PixelCombatPlus.looting());
  879. };
  880. if (typeof PixelCombatPlus.enemy.winFunction == 'function') {
  881. PixelCombatPlus.enemy.winFunction();
  882. };
  883. } else if (PixelCombatPlus.hero.hp <= 0) {
  884. console.log('loser');
  885. }
  886. for (const key in defaultEnemy) {
  887. PixelCombatPlus.enemy[key] = defaultEnemy[key];
  888. };
  889. switch_panels('panel-combat');
  890. document.getElementById('notification-custom-combat').style.display = "none" //Hide the combat notification
  891. }
  892. };
  893. window.PixelCombatPlus = PixelCombatPlus;
  894. PixelCombatPlus.initialize();
  895. })()
  896. }