Pixel Combat+

Makes it easier to create new custom enemies for Idle Pixel

当前为 2024-04-04 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/491625/1354049/Pixel%20Combat%2B.js

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

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址