Makes it easier to create new custom enemies for Idle Pixel
Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greasyfork.org/scripts/491625/1437608/Pixel%20Combat%2B.js
// ==UserScript==
// @name Pixel Combat+
// @namespace http://tampermonkey.net/
// @version 1.0.1
// @description Makes it easier to create new custom enemies for Idle Pixel
// @author Dounford
// @license MIT
// @match *://idle-pixel.com/login/play*
// @grant none
// ==/UserScript==
//Default Enemy
let defaultEnemy = {
name:'Black Cat',
image:"https://raw.githubusercontent.com/Dounford-Felipe/DHP-Pets/main/images/whiteCatMonster.png",
hp:100,
maxHp:100,
accuracy:3,
damage:2,
speed:3,
defence:5,
multiPhase: false,
nextPhase:'',
arrowImunity:false,
magicImunity:false,
needsLight:false,
weakToFire:false,
weakToIce:false,
poisoned: false,
ghost: false,
fish: false,
defender: false,
lootTable:"",
lootFunction: "",
winFunction: "",
abilities:[]
};
/*abilities: [
{type: 'heal', limit: -1, chance: 1, cooldown: 3, min:5,max:20, cd:10},
{type: 'poison', chance: 1, poison:5, cd:5},
{type: 'damage', limit: -1, chance: 0.25, cooldown: 3, min:5,max:20, cd:3},
{type: 'kamikaze', chance: 1, cd: 120},
{type: 'invisibility', limit: -1, chance: 1, cooldown: 30, cd:30},
{type: 'reflect', limit: -1, chance: 1, cooldown: 15, cd:15}
]*/
//[{item:'',image:'',min:1,max:10,chance:'1/x'}]
//Ranged Weapons
const ranged = ['wooden_bow','long_bow','haunted_bow','balista'];
if (!document.getElementById('panel-customCombat')) {
(function PixelCombatPlus() {
'use strict';
const PixelCombatPlus = {
initialize: function () {
PixelCombatPlus.newFightPanel();
PixelCombatPlus.newModals();
if (IdlePixelPlus) {
IdlePixelPlus.panels.customCombat = {id:'customCombat',title:'',content:''}
} else {
const og_switch_panels = window.switch_panels;
window.switch_panels = function(id) {
document.getElementById('panel-customCombat').style.display = "none";
og_switch_panels.apply(this, arguments);
}
}
},
//Fighting toggle
fight: false,
//Hitsplat Maps
hitSplatHero: {},
hitSplatEnemy: {},
//Timer until fight starts
startsIn:0,
//Interval called each second
ticking:0,
ticks: 0,
//Enemy Stats
enemy: {
name:'Test',
image:"",
hp:10,
maxHp:10,
accuracy:3,
damage:2,
speed:3,
defence:5,
multiPhase: false,
nextPhase:'',
arrowImunity:false,
magicImunity:false,
needsLight:false,
weakToFire:false,
weakToIce:false,
poisoned: false,
ghost: false,
fish: false,
defender: false,
lootTable: "",
lootFunction: "",
winFunction: "",
},
//Hero Stats
hero: {
hp:0,
mana:0,
revive:0,
isReflecting:false,
poisoned: false
},
//Spells Cooldown
healCooldown: 0,
fireCooldown: 0,
reflectCooldown: 0,
invisibilityCooldown: 0,
heroIsInvisible: 0,
enemyIsInvisible: 0,
enemyIsCharging: 0,
testFight: function() {
PixelCombatPlus.startFight(defaultEnemy)
},
newModals: function() {
let lootDiv = `<div style="width: 100%; height: 100%; position: absolute;top:0px; display: none;" id="customCombatModalParent">
<div style="background-color: black;opacity: 0.7;width: 100%;height: 100%;position: absolute;" onclick="document.getElementById('customCombatModalParent').style.display='none'"></div>
<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;">
<div class="modal-header">
<h5 class="modal-title text-secondary">LOOT</h5>
<button type="button" class="btn-close" onclick="document.getElementById('customCombatModalParent').style.display = 'none'"></button>
</div>
<div class="modal-body">
<div id="modal-custom-loot-body">
</div>
</div>
<div class="modal-footer">
<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>
</div>
</div>
</div>`
document.getElementById('content').insertAdjacentHTML('beforeend', lootDiv);
},
//Adds the new combat scene
newFightPanel: function () {
let customCombatTab = `<div id="panel-customCombat" style="display:none">
<button onclick="switch_panels('panel-combat')">BACK</button>
<center>
<table>
<tbody>
<tr>
<td class="fight-right-border">
</td>
<td style="padding-top:20px;" class="canvas-fighting-td fight-top-border">
<center>
<span class="hp-progress-bar">
<span id="custom-hero-progress-bar-hp" class="hp-progress-bar-inner" style="width: 100%;"></span>
<div class="progress-bar-label">
<span id="custom_combat_hp">0/0</span>
</div>
</span>
<br>
<span class="mana-progress-bar">
<span id="custom-hero-progress-bar-mana" class="mana-progress-bar-inner" style="width: 100%;"></span>
<div class="progress-bar-label color-cyan">
<span id="custom_combat_mana">0/0</span>
</div>
</span>
</center>
</td>
<td style="padding-bottom:20px;" class="canvas-fighting-td fight-top-border">
<center>
<span class="hp-progress-bar">
<span id="custom-monster-progress-bar-hp" class="hp-progress-bar-inner" style="width: 100%;"></span>
<div class="progress-bar-label">
<span id="custom_combat_monster_hp">0/0</span>
</div>
</span>
<br>
</center>
</td>
<td class="fight-left-border">
</td>
</tr>
<tr>
<td style="vertical-align:top;" class="fight-right-border">
<div class="fighting-hero-stats-area hover shadow" style="border-right:none;">
<span id="custom-fighting-hero-label">Player</span>
</div>
<div class="td-combat-bottom-panel shadow">
<div class="td-combat-stat-entry">
<img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/accuracy_white.png" title="accuracy_white">
<span style="color:white">Accuracy:</span>
<span id="custom_combat_hero_accuracy">0</span>
</div>
<div class="td-combat-stat-entry">
<img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/melee_damage_white.png" title="melee_damage_white">
<span style="color:white">Damage:</span>
<span id="custom_combat_hero_melee_damage">0</span>
</div>
<div class="td-combat-stat-entry">
<img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/arrow_damage_white.png" title="arrow_damage_white">
<span style="color:white">Damage:</span>
<span id="custom_combat_hero_arrow_damage">0</span>
</div>
<div class="td-combat-stat-entry">
<img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/magic_damage_white.png" title="magic_damage_white">
<span style="color:white">Magic:</span>
<span id="custom_combat_hero_magic_bonus">0</span>
</div>
<div class="td-combat-stat-entry">
<img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/speed_white.png" title="speed_white">
<span style="color:white">Speed:</span>
<span id="custom_combat_hero_speed">0</span>
</div>
<div class="td-combat-stat-entry">
<img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/defence_white.png" title="defence_white">
<span style="color:white">Defence:</span>
<span id="custom_combat_hero_defence">0</span>
</div>
</div>
<div style="" id="custom-fighting-spell-heal" onclick="PixelCombatPlus.spell('heal')" class="fighting-spell-area-heal hover shadow">
<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">
<span id="custom-fighting-spell-label-heal" style="color: white;">Heal <span class="color-grey" style="color: rgb(128, 128, 128);">(Q)</span></span>
</div>
<div style="" id="custom-fighting-spell-fire" onclick="PixelCombatPlus.spell('fire')" class="fighting-spell-area-fire hover shadow">
<img id="custom-image-fire_spell_icon" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/fire_spell_icon.png" title="fire_spell_icon" class="">
<span id="custom-fighting-spell-label-fire" style="color: white;">Fire <span class="color-grey" style="color: rgb(128, 128, 128);">(E)</span></span>
</div>
<div style="" id="custom-fighting-spell-reflect" onclick="PixelCombatPlus.spell('reflect')" class="fighting-spell-area-fire hover shadow">
<img id="custom-image-reflect_spell_icon" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/reflect_spell_icon.png" title="reflect_spell_icon" class="">
<span id="custom-fighting-spell-label-reflect" style="color: white;">Reflect <span class="color-grey" style="color: rgb(128, 128, 128);">(E)</span></span>
</div>
<div style="" id="custom-fighting-spell-invisibility" onclick="PixelCombatPlus.spell('invisibility')" class="fighting-spell-area-invisibility hover shadow">
<img id="custom-image-invisibility_spell_icon" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/invisibility_spell_icon.png" title="invisibility_spell_icon" class="">
<span id="custom-fighting-spell-label-invisibility" style="color: white;">Invisibility <span class="color-grey" style="color: rgb(128, 128, 128);">(R)</span></span>
</div>
</td>
<td class="canvas-fighting-td fight-bottom-border">
<div style="display: none;" class="fighting-countdown">FIGHT IN <span id="custom-fighting-countdown">5</span></div>
<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">
</canvas>
</td>
<td class="canvas-fighting-td fight-bottom-border">
<canvas class="canvas-fighting" id="custom-combat-canvas-monster" width="500px" height="600px" original-width="500px" original-height="600px" style="">
</canvas>
</td>
<td style="vertical-align:top;" class="fight-left-border">
<div class="fighting-monster-stats-area hover shadow">
<span id="custom-fighting-monster-label">Enemy Name</span>
</div>
<div class="td-combat-bottom-panel shadow" style="border-left:none;">
<div class="td-combat-stat-entry">
<img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/accuracy_white.png" title="accuracy_white">
<span style="color:white">Accuracy:</span>
<span id="custom_combat_monster_accuracy">0</span>
</div>
<div class="td-combat-stat-entry">
<img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/melee_damage_white.png" title="melee_damage_white">
<span style="color:white">Damage:</span>
<span id="custom_combat_monster_attack">0</span>
</div>
<div class="td-combat-stat-entry">
<img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/speed_white.png" title="speed_white">
<span style="color:white">Speed:</span>
<span id="custom_combat_monster_speed">3</span>
</div>
<div class="td-combat-stat-entry">
<img class="img-15" src="https://d1xsc8x7nc5q8t.cloudfront.net/images/defence_white.png" title="defence_white">
<span style="color:white">Defence:</span>
<span id="custom_combat_monster_defence">0</span>
</div>
</div>
</td>
</tr>
<tr>
<td></td>
<td>
<center>
<!-- presets -->
<div id="custom-combat-presets-area" style="" class="combat-presets-area shadow center">
<img src="https://d1xsc8x7nc5q8t.cloudfront.net/images/combat_presets.png" class="w20" title="combat_presets"> <u class="color-silver">Presets</u><br><br>
<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);">
<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);">
<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);">
<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);">
<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);">
</div>
</center>
<!-- end presets -->
</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</center>
</div>`
document.getElementById('panels').insertAdjacentHTML('beforeend', customCombatTab);
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">
<img src="https://d1xsc8x7nc5q8t.cloudfront.net/images/fight.png" class="w20" title="fight">
<span style="color:red">IN COMBAT!</span>
<span style="color:grey">(Click to resume)</span>
<span class="color-white" id="notification-combat"></span>
</div>`
document.getElementById('notification-combat').insertAdjacentHTML('afterend', combatNot);
PixelCombatPlus.heroCanvas = document.getElementById("custom-combat-canvas-hero");
PixelCombatPlus.heroContext = document.getElementById("custom-combat-canvas-hero").getContext("2d");
PixelCombatPlus.enemyCanvas = document.getElementById("custom-combat-canvas-monster");
PixelCombatPlus.enemyContext = document.getElementById("custom-combat-canvas-monster").getContext("2d");
PixelCombatPlus.enemyImage = new Image();
document.addEventListener('keydown', function(e) {
const chatInput = document.getElementById('chat-area-input');
const customCombatPanel = document.getElementById('panel-customCombat');
if (!chatInput.matches(':focus') && customCombatPanel.style.display !== "none") {
switch (e.keyCode) {
//Presets
case 49: websocket.send('PRESET_LOAD=1~1'); break;
case 50: websocket.send('PRESET_LOAD=2~1'); break;
case 51: websocket.send('PRESET_LOAD=3~1'); break;
case 52: websocket.send('PRESET_LOAD=4~1'); break;
case 53: websocket.send('PRESET_LOAD=5~1'); break;
//Spells
case 81: PixelCombatPlus.spell('heal'); break;
case 87: PixelCombatPlus.spell('fire'); break;
case 69: PixelCombatPlus.spell('reflect'); break;
case 82: PixelCombatPlus.spell('invisibility'); break;
}
}
});
},
//Refresh the presets on the custom combat
refreshPresetIcons: function() {
for(let i = 1; i < 6 ; i++) {
document.getElementById("custom-in-combat-presets-icon-" + i).src = get_image("images/" + Items.getItem("combat_preset_icon_" + i));
document.getElementById("custom-in-combat-presets-icon-" + i).style.backgroundColor = Items.getItemString("combat_preset_color_" + i);
}
},
//Cooldown function
cooldown: function(variable,time,id,defaultText) {
PixelCombatPlus[variable] = time;
if (typeof id == 'string') {
document.getElementById(id).innerHTML = time;
document.getElementById(id).parentNode.style.display = "";
};
if (time > 0) {
setTimeout(function(){
PixelCombatPlus.cooldown(variable,time-1,id,defaultText);
},1000)
} else if (typeof defaultText == 'string') {
if (defaultText == "hide") {
document.getElementById(id).parentNode.style.display = "none";
} else {
document.getElementById(id).innerHTML = defaultText;
}
};
},
//Cooldown function
cooldownAbility: function(index,time) {
if (PixelCombatPlus.fight == false) {PixelCombatPlus.enemy.abilities = []};
if (PixelCombatPlus.enemy.abilities[index] == undefined) {return};
PixelCombatPlus.enemy.abilities[index].cd = time;
if (time > 0) {
setTimeout(function(){
PixelCombatPlus.cooldownAbility(index,time-1);
},1000)
}
},
//Spell Casting Function
spell: function(spellName) {
if (PixelCombatPlus[spellName+'Cooldown'] == 0) {
switch (spellName) {
case "heal":
if (PixelCombatPlus.hero.mana >= 2) {
PixelCombatPlus.hero.mana -= 2;
PixelCombatPlus.hero.hp += 3;
PixelCombatPlus.hero.hp = Math.min(PixelCombatPlus.hero.hp,var_max_hp);
PixelCombatPlus.updateStatsBars();
PixelCombatPlus.addHitSplat("3", 'images/heal_spell.png', 'lime', 'rgba(0,255,0,0.4)', 'blue', 'Hero');
PixelCombatPlus.cooldown('healCooldown',5,'custom-fighting-spell-label-heal','Heal <span class="color-grey" style="color: rgb(128, 128, 128);">(Q)</span>');
}
break;
case "fire":
if (PixelCombatPlus.hero.mana >= 3) {
PixelCombatPlus.hero.mana -= 3;
let fireDamage = Math.floor(Math.random() * 6) + parseInt(var_magic_bonus);
if (PixelCombatPlus.enemy.weakToFire == true) {
fireDamage *= 2
};
if (PixelCombatPlus.enemy.magicImunity == false) {
PixelCombatPlus.enemy.hp -= fireDamage;
PixelCombatPlus.addHitSplat(fireDamage, 'images/fire_icon.png', 'white', 'rgba(255,0,0,0.4)', 'blue', 'Enemy');
} else {
PixelCombatPlus.addHitSplat('IMMUNE', 'images/fire_icon.png', 'white', 'rgba(255,0,0,0.4)', 'blue', 'Enemy');
};
PixelCombatPlus.updateStatsBars();
PixelCombatPlus.cooldown('fireCooldown',5,'custom-fighting-spell-label-fire','Fire <span class="color-grey" style="color: rgb(128, 128, 128);">(W)</span>');
}
break;
case "reflect":
if (PixelCombatPlus.hero.mana >= 1 && PixelCombatPlus.hero.isReflecting == false) {
PixelCombatPlus.hero.mana -= 1;
PixelCombatPlus.hero.isReflecting = true;
PixelCombatPlus.updateStatsBars();
PixelCombatPlus.cooldown('reflectCooldown',30,'custom-fighting-spell-label-reflect','Reflect <span class="color-grey" style="color: rgb(128, 128, 128);">(E)</span>');
}
break;
case "invisibility":
if (PixelCombatPlus.hero.mana >= 2) {
PixelCombatPlus.hero.mana -= 2;
PixelCombatPlus.updateStatsBars();
PixelCombatPlus.cooldown('heroIsInvisible',4);
PixelCombatPlus.cooldown('invisibilityCooldown',30,'custom-fighting-spell-label-invisibility','Invisibility <span class="color-grey" style="color: rgb(128, 128, 128);">(R)</span>');
}
break;
};
}
},
poison: function(receiver,poisonDamage) {
PixelCombatPlus[receiver].hp -= poisonDamage;
PixelCombatPlus.addHitSplat(poisonDamage, 'images/poison.png', 'green', 'rgba(255,0,0,0.4)', 'blue', receiver.charAt(0).toLocaleUpperCase() + receiver.slice(1));
PixelCombatPlus.updateStatsBars();
if (PixelCombatPlus.hero.hp > 0 && PixelCombatPlus.enemy.hp > 0) {setTimeout(function(){PixelCombatPlus.poison(receiver,poisonDamage)},4000)};
},
//Enemy Special Attack
specialAttack: function() {
if (typeof PixelCombatPlus.enemy.abilities == 'object') {
PixelCombatPlus.enemy.abilities.forEach(function(ability,index) {
if (ability.limit == 0 || ability.cd > 0) {
return;
};
const randomChance = Math.random();
if (ability.chance > randomChance) {
switch (ability.type) {
case 'heal':
let healAmount = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min)
PixelCombatPlus.enemy.hp += healAmount;
PixelCombatPlus.enemy.hp = Math.min(PixelCombatPlus.enemy.hp,PixelCombatPlus.enemy.maxHp);
PixelCombatPlus.updateStatsBars();
PixelCombatPlus.addHitSplat(healAmount, 'images/heal_spell.png', 'lime', 'rgba(0,255,0,0.4)', 'blue', 'Enemy');
break;
case 'poison':
if (PixelCombatPlus.hero.poisoned == true) {return}
PixelCombatPlus.hero.poisoned = true;
const poisonDamage = ability.poison || 5
PixelCombatPlus.poison('hero',poisonDamage)
break;
case 'damage':
if (PixelCombatPlus.heroIsInvisible > 0) {
PixelCombatPlus.addHitSplat("MISSED","images/ghost_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
} else {
let damageDone = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min);
if (PixelCombatPlus.hero.isReflecting == true && damageDone > 0) {
PixelCombatPlus.enemy.hp -= damageDone;
PixelCombatPlus.hero.isReflecting = false;
PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
} else {
PixelCombatPlus.hero.hp -= damageDone;
PixelCombatPlus.addHitSplat(damageDone,"images/sword_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
}
PixelCombatPlus.updateStatsBars();
}
break;
case 'chargeDamage':
if (PixelCombatPlus.enemyIsCharging > 0) {return};
PixelCombatPlus.cooldown('enemyIsCharging',4);
setTimeout(function() {
if (PixelCombatPlus.heroIsInvisible > 0) {
PixelCombatPlus.addHitSplat("MISSED","images/ghost_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
} else {
let damageDone = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min);
if (PixelCombatPlus.hero.isReflecting == true && damageDone > 0) {
PixelCombatPlus.enemy.hp -= damageDone;
PixelCombatPlus.hero.isReflecting = false;
PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
} else {
PixelCombatPlus.hero.hp -= damageDone;
PixelCombatPlus.addHitSplat(damageDone,"images/sword_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
}
PixelCombatPlus.updateStatsBars();
}
},4000);
break;
case 'lifeSteal':
if (PixelCombatPlus.heroIsInvisible > 0) {
PixelCombatPlus.addHitSplat("MISSED","images/ghost_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
} else {
let damageDone = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min);
if (PixelCombatPlus.hero.isReflecting == true && damageDone > 0) {
PixelCombatPlus.enemy.hp -= damageDone;
PixelCombatPlus.hero.isReflecting = false;
PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
} else {
PixelCombatPlus.hero.hp -= damageDone;
PixelCombatPlus.enemy.hp += damageDone;
PixelCombatPlus.enemy.hp = Math.min(PixelCombatPlus.enemy.hp,PixelCombatPlus.enemy.maxHp);
PixelCombatPlus.addHitSplat(damageDone,"images/sword_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
PixelCombatPlus.addHitSplat(damageDone, 'images/heal_spell.png', 'lime', 'rgba(0,255,0,0.4)', 'blue', 'Enemy');
}
PixelCombatPlus.updateStatsBars();
};
break;
case 'kamikaze':
PixelCombatPlus.hero.hp = 0;
PixelCombatPlus.endFight();
break;
case "invisibility":
if (PixelCombatPlus.enemyIsInvisible > 0) {return}
let invisibleTime = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min);
PixelCombatPlus.cooldown('enemyIsInvisible',invisibleTime);
break;
case "reflect":
if (PixelCombatPlus.enemy.isReflecting == true) {return};
PixelCombatPlus.enemy.isReflecting = true;
break;
case "fullRestorePlayer":
PixelCombatPlus.hero.hp = var_max_hp; //Set the current hero hp to max
PixelCombatPlus.hero.mana = var_max_mana; //Set the current hero mana to max
PixelCombatPlus.updateStatsBars();
break;
case "restorePlayerHP":
let healAmounts = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min)
PixelCombatPlus.hero.hp += healAmounts;
PixelCombatPlus.hero.hp = Math.min(PixelCombatPlus.hero.hp,var_max_hp);
PixelCombatPlus.updateStatsBars();
PixelCombatPlus.addHitSplat(healAmounts, 'images/heal_spell.png', 'lime', 'rgba(0,255,0,0.4)', 'blue', 'Hero');
break;
case "restorePlayerMana":
let manaAmount = Math.floor(Math.random() * (ability.max - ability.min + 1) + ability.min)
PixelCombatPlus.hero.mana += manaAmount;
PixelCombatPlus.hero.mana = Math.min(PixelCombatPlus.hero.mana,var_max_mana);
PixelCombatPlus.updateStatsBars();
break;
};
if (ability.limit != -1) {
ability.limit--;
};
if (ability.cooldown > 0) {
PixelCombatPlus.cooldownAbility(index,ability.cooldown)
};
};
});
}
},
//Update the stats bar on combat scene
updateStatsBars: function() {
//Hero
document.getElementById("custom_combat_hp").innerHTML = Math.max(0,PixelCombatPlus.hero.hp) + "/" + var_max_hp; //Set the number on the hero hp bar
let heroHpPercentage = PixelCombatPlus.hero.hp / var_max_hp * 100;
document.getElementById("custom-hero-progress-bar-hp").style.width = heroHpPercentage.toFixed() + "%"; // Set the hero hp bar background
//Mana
document.getElementById("custom_combat_mana").innerHTML = Math.max(0,PixelCombatPlus.hero.mana) + "/" + var_max_mana; //Set the number on the hero mana bar
let heroManaPercentage = PixelCombatPlus.hero.mana / var_max_mana * 100;
document.getElementById("custom-hero-progress-bar-mana").style.width = heroManaPercentage.toFixed() + "%"; // Set the mana hp bar background
//Enemy
document.getElementById("custom_combat_monster_hp").innerHTML = Math.max(0,PixelCombatPlus.enemy.hp) + "/" + PixelCombatPlus.enemy.maxHp; //Set the number on the enemy hp bar
let EnemyHpPercentage = PixelCombatPlus.enemy.hp / PixelCombatPlus.enemy.maxHp * 100;
document.getElementById("custom-monster-progress-bar-hp").style.width = EnemyHpPercentage.toFixed() + "%"; // Set the enemy hp bar background
},
//Update the enemy stats mid fight, can be used for pvp
updateEnemyStats: function(foe) {
PixelCombatPlus.enemyImage.src = foe.image;
PixelCombatPlus.enemy.abilities = [];
for (const key in foe) {
PixelCombatPlus.enemy[key] = foe[key];
};
PixelCombatPlus.updateStatsBars();
PixelCombatPlus.enemy.abilities.forEach(function(ability,index) {if (ability.cd > 0){PixelCombatPlus.cooldownAbility(index,ability.cd)}});
document.getElementById("custom-fighting-monster-label").innerText = PixelCombatPlus.enemy.name;
document.getElementById("custom_combat_monster_accuracy").innerText = PixelCombatPlus.enemy.accuracy == -1 ? 1 : PixelCombatPlus.enemy.accuracy;
document.getElementById("custom_combat_monster_attack").innerText = PixelCombatPlus.enemy.damage;
document.getElementById("custom_combat_monster_speed").innerText = PixelCombatPlus.enemy.speed;
document.getElementById("custom_combat_monster_defence").innerText = PixelCombatPlus.enemy.defence;
},
//Define the enemy image
setEnemyImage: function(foe) {
try {
PixelCombatPlus.enemyImage.src = foe;
} catch (error) {
setTimeout(function() {
try {
PixelCombatPlus.enemyImage.src = foe;
} catch (error) {
PixelCombatPlus.setEnemyImage(foe)
}
}, 1000);
}
},
//Starts the fight
startFight: function(foe) {
if (PixelCombatPlus.fight == false) {
//Make sure that there is nothing remaining from the last fight
PixelCombatPlus.enemy.poisoned = false;
PixelCombatPlus.hero.poisoned = false;
PixelCombatPlus.hero.isReflecting = false;
PixelCombatPlus.hitSplatHero = {};
PixelCombatPlus.hitSplatEnemy = {};
PixelCombatPlus.hero.revive = 0;
//Stats Update
PixelCombatPlus.hero.hp = var_max_hp; //Set the current hero hp to max
PixelCombatPlus.hero.mana = var_max_mana; //Set the current hero mana to max
PixelCombatPlus.setEnemyImage(foe.image) //Set the enemy image
for (const key in foe) {PixelCombatPlus.enemy[key] = foe[key]}; //Set the current enemy
PixelCombatPlus.enemy.poisoned = false; //Removes poison
if (PixelCombatPlus.enemy.speed > 6) {PixelCombatPlus.enemy.speed = 6}; // 6 is the max speed
if (PixelCombatPlus.enemy.hp > PixelCombatPlus.enemy.maxHp) {PixelCombatPlus.enemy.hp = PixelCombatPlus.enemy.maxHp}; // Enemy can't have more than max hp
//UI Update
PixelCombatPlus.refreshPresetIcons(); //Load the preset icon and color
PixelCombatPlus.updateStatsBars(); //Updates all stats on UI
//Hero Stats
document.getElementById("custom-fighting-hero-label").innerText = var_username;
document.getElementById("custom_combat_hero_accuracy").innerText = var_accuracy;
document.getElementById("custom_combat_hero_melee_damage").innerText = var_melee_damage;
document.getElementById("custom_combat_hero_arrow_damage").innerText = var_arrow_damage;
document.getElementById("custom_combat_hero_magic_bonus").innerText = var_magic_bonus;
document.getElementById("custom_combat_hero_speed").innerText = var_speed;
document.getElementById("custom_combat_hero_defence").innerText = var_defence;
//Enemy Stats
document.getElementById("custom-fighting-monster-label").innerText = PixelCombatPlus.enemy.name;
document.getElementById("custom_combat_monster_accuracy").innerText = PixelCombatPlus.enemy.accuracy == -1 ? 1 : PixelCombatPlus.enemy.accuracy;
document.getElementById("custom_combat_monster_attack").innerText = PixelCombatPlus.enemy.damage;
document.getElementById("custom_combat_monster_speed").innerText = PixelCombatPlus.enemy.speed;
document.getElementById("custom_combat_monster_defence").innerText = PixelCombatPlus.enemy.defence;
switch_panels('panel-customCombat'); //Go to the fight scene
document.getElementById('menu-bar').style.display = "none"; //Hides lateral bar
document.getElementById('notification-custom-combat').style.display = "" //Shows the combat notification
document.getElementById('notification-custom-combat').style.display = "" //Shows the combat notification
PixelCombatPlus.fight = true; //Starts the fight
PixelCombatPlus.cooldown('startsIn',5,'custom-fighting-countdown','hide'); //Start the timer to fight
PixelCombatPlus.ticking = setInterval(function() {
PixelCombatPlus.tick()
}, 1000 / 60);
setTimeout(function(){
PixelCombatPlus.attack("hero");
PixelCombatPlus.attack("enemy");
PixelCombatPlus.enemy.abilities.forEach(function(ability,index) {if (ability.cd > 0){PixelCombatPlus.cooldownAbility(index,ability.cd)}});
}, 6000);
}
},
//Hit function
hitRate: function(defence,accuracy) {
if (accuracy == -1) {return false};
let hitRandom = Math.random();
let hitChance = 0;
if (((defence / 2) - accuracy) > 4) {
hitChance = 1 / (Math.max(1, ((defence / 2) - accuracy)) + 1);
} else if (((defence / 2) - accuracy) <= 0) {
hitChance = 1;
} else {
hitChance = 1 - (((defence / 2) - accuracy) * 2 / 10);
};
if (PixelCombatPlus.enemy.needsLight == true && !(var_ring_of_light_equipped == 1 || var_shield == 'lantern')) {hitChance = 0.5};
return hitRandom <= hitChance
},
//Attack function
attack: function(attacker){
if (PixelCombatPlus.fight == true) {
if (attacker == "hero") {
//Poison
if (PixelCombatPlus.enemy.poisoned == false && var_weapon.includes('poison')) {
PixelCombatPlus.enemy.poisoned = true;
PixelCombatPlus.poison('enemy',5);
};
//If hit succeed
if (PixelCombatPlus.hitRate(PixelCombatPlus.enemy.defence,var_accuracy)) {
if (PixelCombatPlus.enemyIsInvisible > 0) {
PixelCombatPlus.addHitSplat("MISSED","images/ghost_icon.png","white","rgba(255,0,0,0.6)","blue","Enemy");
} else {
if (ranged.includes(var_weapon)) {
if (PixelCombatPlus.enemy.arrowImunity == true) {
PixelCombatPlus.addHitSplat('IMMUNE', 'images/blocked.png', 'white', 'rgba(255,0,0,0.4)', 'blue', 'Enemy');
} else {
let damageDone = Math.floor(Math.random() * parseInt(var_arrow_damage));
if ((PixelCombatPlus.enemy.weakToFire == true && var_arrows == 'fire_arrows') || (PixelCombatPlus.enemy.weakToIce == true && var_arrows == 'ice_arrows')) {
damageDone *= 2;
}
if (PixelCombatPlus.enemy.isReflecting == true && damageDone > 0) {
PixelCombatPlus.hero.hp -= damageDone;
PixelCombatPlus.enemy.isReflecting = false;
PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Hero');
} else {
PixelCombatPlus.enemy.hp -= damageDone;
PixelCombatPlus.addHitSplat(damageDone, "images/" + Items.getItemString('weapon')+".png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
}
};
} else {
let damageDone = Math.floor(Math.random() * parseInt(var_melee_damage))
if (PixelCombatPlus.enemy.ghost == true) {
if (var_weapon == 'scythe') {damageDone *= 2};
if (var_weapon == 'double_scythe') {damageDone *= 4};
} else if (PixelCombatPlus.enemy.fish == true) {
if (var_weapon.includes('trident')) {damageDone *= 2};
};
if (PixelCombatPlus.enemy.isReflecting == true && damageDone > 0) {
PixelCombatPlus.hero.hp -= damageDone;
PixelCombatPlus.enemy.isReflecting = false;
PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Hero');
} else {
PixelCombatPlus.enemy.hp -= damageDone;
PixelCombatPlus.addHitSplat(damageDone, "images/" + Items.getItemString('weapon')+".png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
if (PixelCombatPlus.enemy.defender == true) {
PixelCombatPlus.hero.hp -= 1;
PixelCombatPlus.addHitSplat(1, "images/" + Items.getItemString('weapon')+".png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Hero');
};
};
};
}
} else {
PixelCombatPlus.addHitSplat("0", "images/blocked.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
};
//Hero attack again
setTimeout(function(){PixelCombatPlus.attack("hero")},(7-var_speed)*1000)
} else {
if (PixelCombatPlus.hitRate(var_defence,PixelCombatPlus.enemy.accuracy)) {
if (PixelCombatPlus.heroIsInvisible > 0) {
PixelCombatPlus.addHitSplat("MISSED","images/ghost_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
} else {
let damageDone = Math.floor(Math.random() * PixelCombatPlus.enemy.damage);
if (PixelCombatPlus.hero.isReflecting == true && damageDone > 0) {
PixelCombatPlus.enemy.hp -= damageDone;
PixelCombatPlus.hero.isReflecting = false;
PixelCombatPlus.addHitSplat(damageDone, "images/reflect_spell.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Enemy');
} else {
PixelCombatPlus.hero.hp -= damageDone;
PixelCombatPlus.addHitSplat(damageDone,"images/sword_icon.png","white","rgba(255,0,0,0.6)","blue","Hero");
}
}
} else {
PixelCombatPlus.addHitSplat("0", "images/blocked.png", 'white', 'rgba(255,0,0,0.6)', 'blue', 'Hero');
};
//Enemy attack again
setTimeout(function(){PixelCombatPlus.attack("enemy")},(7-PixelCombatPlus.enemy.speed)*1000)
}
//Update hps
PixelCombatPlus.updateStatsBars();
}
},
//HitSplat Generator
addHitSplat: function(label, icon, label_color, background_color, border_color, source) {
let splatX = source == "Hero" ? 150 : 200
let splatY = source == 450
let splat = new HitSplat(label, icon, label_color, background_color, border_color, splatX, 450);
let random_key = rand(1,500000);
PixelCombatPlus['hitSplat'+source][random_key] = splat;
setTimeout(
function(){
delete PixelCombatPlus['hitSplat'+source][random_key];
}
,1000)
},
//Evething that should be called each second
tick: function() {
//UI
//Hero Stats
document.getElementById("custom_combat_hero_accuracy").innerText = var_accuracy;
document.getElementById("custom_combat_hero_melee_damage").innerText = var_melee_damage;
document.getElementById("custom_combat_hero_arrow_damage").innerText = var_arrow_damage;
document.getElementById("custom_combat_hero_magic_bonus").innerText = var_magic_bonus;
document.getElementById("custom_combat_hero_speed").innerText = var_speed;
document.getElementById("custom_combat_hero_defence").innerText = var_defence;
PixelCombatPlus.tickCanvas();
PixelCombatPlus.manageHitplats();
PixelCombatPlus.ticks++
if (PixelCombatPlus.ticks == 60) {
if (PixelCombatPlus.enemy.hp <= 0) {
if (PixelCombatPlus.enemy.multiPhase) {
PixelCombatPlus.updateEnemyStats(PixelCombatPlus.enemy.nextPhase)
} else {
PixelCombatPlus.endFight();
}
};
if (PixelCombatPlus.hero.hp <= 0) {
if (var_badge_death_1_hp == 1 && PixelCombatPlus.hero.revive == 0) {
PixelCombatPlus.hero.hp = 1;
PixelCombatPlus.hero.revive = 1;
PixelCombatPlus.updateStatsBars();
} else {
PixelCombatPlus.endFight();
}
};
if(PixelCombatPlus.startsIn <= 0) {PixelCombatPlus.specialAttack()}
PixelCombatPlus.ticks = 0;
};
},
tickCanvas: function() {
PixelCombatPlus.heroContext.clearRect(0, 0, PixelCombatPlus.heroCanvas.width, PixelCombatPlus.heroCanvas.height);
PixelCombatPlus.enemyContext.clearRect(0, 0, PixelCombatPlus.enemyCanvas.width, PixelCombatPlus.enemyCanvas.height);
if (PixelCombatPlus.heroIsInvisible > 0) {
PixelCombatPlus.heroContext.fillStyle = "white";
PixelCombatPlus.heroContext.globalAlpha = 0.1;
PixelCombatPlus.heroContext.fillRect(155, 20, 50, 50);
PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/ghost_icon.png","hero_invisible"), 155, 20);
} else {
PixelCombatPlus.heroContext.globalAlpha = 1.0;
};
if (PixelCombatPlus.enemyIsInvisible > 0) {
PixelCombatPlus.enemyContext.fillStyle = "white";
PixelCombatPlus.enemyContext.globalAlpha = 0.1;
PixelCombatPlus.enemyContext.fillRect(280, 20, 50, 50);
PixelCombatPlus.enemyContext.drawImage(Cache.getImage("images/ghost_icon.png","hero_invisible"), 280, 20);
} else {
PixelCombatPlus.enemyContext.globalAlpha = 1.0;
};
if (PixelCombatPlus.hero.isReflecting == true) {
PixelCombatPlus.heroContext.fillStyle = "white";
PixelCombatPlus.heroContext.fillRect(95, 20, 50, 50);
PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/reflect_spell.png","hero_reflecting"), 95, 20);
};
if (PixelCombatPlus.enemy.isReflecting == true) {
PixelCombatPlus.enemyContext.fillStyle = "white";
PixelCombatPlus.enemyContext.fillRect(170, 20, 50, 50);
PixelCombatPlus.enemyContext.drawImage(Cache.getImage("images/reflect_spell.png","hero_reflecting"), 170, 20);
};
if (PixelCombatPlus.enemyIsCharging > 0) {
PixelCombatPlus.enemyContext.fillStyle = "white";
PixelCombatPlus.enemyContext.fillRect(225, 20, 50, 50);
PixelCombatPlus.enemyContext.fillStyle = "black";
PixelCombatPlus.enemyContext.font = "50px serif";
PixelCombatPlus.enemyContext.fillText(PixelCombatPlus.enemyIsCharging, 238, 60);
};
PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_head_" + Items.getItemString('head')+".png","hero_fighting_head"), 0, 300);
PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_body_" + Items.getItemString('body')+".png","hero_fighting_body"), 0, 300);
PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_gloves_" + Items.getItemString('gloves')+".png","hero_fighting_gloves"), 0, 300);
PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_legs_" + Items.getItemString('legs')+".png","hero_fighting_legs"), 0, 300);
PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_boots_" + Items.getItemString('boots')+".png","hero_fighting_boots"), 0, 300);
PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_amulet_" + Items.getItemString('amulet')+".png","hero_fighting_amulet"), 0, 300);
PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_shield_" + Items.getItemString('shield')+".png","hero_fighting_shield"), 0, 300);
PixelCombatPlus.heroContext.drawImage(Cache.getImage("images/hero_weapon_" + Items.getItemString('weapon')+".png","hero_fighting_weapon"), 0, 300);
if (PixelCombatPlus.enemyImage.height !== 600) {
let newWidth = 200 / (PixelCombatPlus.enemyImage.height / PixelCombatPlus.enemyImage.width)
PixelCombatPlus.enemyContext.drawImage(PixelCombatPlus.enemyImage,(500-newWidth)/2,375,newWidth,200);
} else {
PixelCombatPlus.enemyContext.drawImage(PixelCombatPlus.enemyImage,0,0);
}; //Enemy Image
},
manageHitplats: function() {
for (let key in PixelCombatPlus.hitSplatHero) {
PixelCombatPlus.hitSplatHero[key].draw(PixelCombatPlus.heroContext);
};
for (let key in PixelCombatPlus.hitSplatEnemy) {
PixelCombatPlus.hitSplatEnemy[key].draw(PixelCombatPlus.enemyContext);
};
},
looting: function() {
let lootedItems = [];
let lootedItemsHTML = '';
document.getElementById('modal-custom-loot-body').innerHTML = ''
PixelCombatPlus.enemy.lootTable.forEach(function(loot){
let dropChance = Math.random() * (loot.chance - 1) + 1;
if (loot.chance == dropChance) {
let dropAmount = Math.random() * (loot.max - loot.min) + loot.min;
if (dropAmount == 0) {dropAmount = ''};
lootedItemsHTML += `<div class="loot" style="background-color:#cce6ff">
<img src="${loot.image}" class="w50 me-3">${dropAmount} ${loot.item}
</div>`;
lootedItems.push({item:loot.item,amount:dropAmount});
};
});
document.getElementById('modal-custom-loot-body').insertAdjacentHTML('beforeend', lootedItemsHTML);
document.getElementById('customCombatModalParent').style.display = "";
return lootedItems;
},
endFight: function() {
PixelCombatPlus.fight = false;
clearInterval(PixelCombatPlus.ticking);
PixelCombatPlus.enemy.poisoned = false;
PixelCombatPlus.hero.poisoned = false;
PixelCombatPlus.hero.isReflecting = false;
PixelCombatPlus.hitSplatHero = {};
PixelCombatPlus.hitSplatEnemy = {};
PixelCombatPlus.healCooldown = 0;
PixelCombatPlus.fireCooldown = 0;
PixelCombatPlus.reflectCooldown = 0;
PixelCombatPlus.invisibilityCooldown = 0;
PixelCombatPlus.heroIsInvisible = 0;
PixelCombatPlus.hero.revive = 0;
if (PixelCombatPlus.enemy.hp <= 0) {
if (typeof PixelCombatPlus.enemy.lootTable == 'object') {
PixelCombatPlus.enemy.lootFunction(PixelCombatPlus.looting());
};
if (typeof PixelCombatPlus.enemy.winFunction == 'function') {
PixelCombatPlus.enemy.winFunction();
};
} else if (PixelCombatPlus.hero.hp <= 0) {
console.log('loser');
}
for (const key in defaultEnemy) {
PixelCombatPlus.enemy[key] = defaultEnemy[key];
};
switch_panels('panel-combat');
document.getElementById('notification-custom-combat').style.display = "none" //Hide the combat notification
}
};
window.PixelCombatPlus = PixelCombatPlus;
PixelCombatPlus.initialize();
})()
}