diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..e486311 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,12 @@ +{ + "semi": true, + "useTabs": true, + "tabWidth": 4, + "singleQuote": false, + "trailingComma": "es5", + "printWidth": 170, + "quoteProps": "as-needed", + "bracketSpacing": true, + "arrowParens": "avoid" +} + diff --git a/Helpers/utils.js b/Helpers/utils.js index 53701d5..43315c1 100644 --- a/Helpers/utils.js +++ b/Helpers/utils.js @@ -1,14 +1,13 @@ - /** * Rounds a value to a specified number of decimal places. * A placeValue of 1000 corresponds to rounding to 3 decimal places, 100 means 2, and so on. - * + * * @param {*} value Value to be rounded * @param {*} placeValue Number by which to scale rounding by * @returns Rounded result */ export function roundValue(value, placeValue = 1000) { - if(placeValue === 0.0) return value; + if (placeValue === 0.0) return value; return Math.floor(value * placeValue) / placeValue; } @@ -21,14 +20,16 @@ let hasHooked = false; /** * Returns a frame counter starting from the first call of this function (once ig.game exists). - * + * * Useful when you need to measure the number of frames passed, not very helpful if you want the * exact number of total game frames. */ export function getFrameNumber() { - if(!hasHooked && ig.game) { + if (!hasHooked && ig.game) { ig.game.addons.preUpdate.push({ - onPreUpdate: () => { frameNumber += 1; } + onPreUpdate: () => { + frameNumber += 1; + }, }); hasHooked = true; @@ -36,4 +37,3 @@ export function getFrameNumber() { return frameNumber; } - diff --git a/Utilities/ballPrediction.js b/Utilities/ballPrediction.js index 511ac17..77614fa 100644 --- a/Utilities/ballPrediction.js +++ b/Utilities/ballPrediction.js @@ -19,4 +19,5 @@ ig.ENTITY.Crosshair.inject({ _updateCrossHair: function(b, e, g, h, i, j, bouncePoints, maxPoint, maxBounce){ this.parent(b, e, g, h, i, j, BOUNCE_POINTS, MAX_POINT, maxBounce); } -});*/ \ No newline at end of file +});*/ + diff --git a/Utilities/bombTimer.js b/Utilities/bombTimer.js index 886a5ca..74e4156 100644 --- a/Utilities/bombTimer.js +++ b/Utilities/bombTimer.js @@ -14,8 +14,8 @@ sc.BombEntity.inject({ start(...args) { this.parent(...args); - if(sc.options && sc.options.get("show-bomb-timer")) { - const timingText = (this.timer) ? `Time: ${roundValue(this.timer)}` : `Unknown`; + if (sc.options && sc.options.get("show-bomb-timer")) { + const timingText = this.timer ? `Time: ${roundValue(this.timer)}` : `Unknown`; this.bombTimingGui = new sc.SmallEntityBox(this, timingText, this.timer + 3); this.bombTimingGui.stopRumble(); @@ -26,8 +26,8 @@ sc.BombEntity.inject({ enterHeatMode(...args) { this.parent(...args); - if(sc.options && sc.options.get("show-bomb-timer")) { - const timingText = (this.timer) ? `Time: ${roundValue(this.timer)}` : `Unknown`; + if (sc.options && sc.options.get("show-bomb-timer")) { + const timingText = this.timer ? `Time: ${roundValue(this.timer)}` : `Unknown`; this.bombTimingGui = new sc.SmallEntityBox(this, timingText, this.timer + 3); this.bombTimingGui.stopRumble(); @@ -38,10 +38,11 @@ sc.BombEntity.inject({ update() { this.parent(); - if(this.bombTimingGui) { - const timingText = (this.timer) ? `Time: ${roundValue(this.timer)}` : `Unknown`; + if (this.bombTimingGui) { + const timingText = this.timer ? `Time: ${roundValue(this.timer)}` : `Unknown`; this.bombTimingGui.textGui.setText(timingText); } - } -}); \ No newline at end of file + }, +}); + diff --git a/Utilities/finisherIndicator.js b/Utilities/finisherIndicator.js index 0c1cb5f..46b94a2 100644 --- a/Utilities/finisherIndicator.js +++ b/Utilities/finisherIndicator.js @@ -1,6 +1,6 @@ /** * CrossCode Speedrun Utilities - finisherIndicator.js - * + * * HUD Indicator for how early or late the player is on * dash cancelling the bonus hit of a Full Combo */ @@ -36,7 +36,6 @@ let hitTime = null; //The hit time of the 2nd finisher hit let hitFrame = -1; - function resetFinisherStatus() { isInFinisher = false; hitCount = 0; @@ -54,26 +53,23 @@ function resetFinisherStatus() { */ ig.ENTITY.Combatant.inject({ onDamage(damagingEntity, attackInfo, partEntity) { - - if(damagingEntity.getCombatant() === sc.model.player.params.combatant) { - if(isInFinisher) { - if(hitCount === 0) { + if (damagingEntity.getCombatant() === sc.model.player.params.combatant) { + if (isInFinisher) { + if (hitCount === 0) { hitTarget = this; - if(partEntity) { + if (partEntity) { hitTargetPart = partEntity; - } - else { + } else { hitTargetPart = null; } hitCount += 1; - } - else if(hitCount === 1) { + } else if (hitCount === 1) { //Have we hit the same target for this hit? - if(hitTarget && hitTarget === this) { + if (hitTarget && hitTarget === this) { //If this target consists of several parts, have we hit the same part? - if(!hitTargetPart || (hitTargetPart === partEntity)) { + if (!hitTargetPart || hitTargetPart === partEntity) { hitTime = ig.Timer.time; hitFrame = getFrameNumber(); hitCount += 1; @@ -84,7 +80,7 @@ ig.ENTITY.Combatant.inject({ } return this.parent(damagingEntity, attackInfo, partEntity); - } + }, }); /** @@ -94,48 +90,45 @@ ig.ENTITY.Combatant.inject({ */ ig.ENTITY.Player.inject({ startCloseCombatAction(actionKey, input) { - - if(actionKey == "ATTACK_FINISHER") { + if (actionKey == "ATTACK_FINISHER") { isInFinisher = true; - } - else { + } else { resetFinisherStatus(); } - this.parent(actionKey,input); + this.parent(actionKey, input); }, startDash() { - if(this.state == 3 && isInFinisher) { - if(hitTarget && sc.options && sc.options.get("show-finisher-indicator")) { - + if (this.state == 3 && isInFinisher) { + if (hitTarget && sc.options && sc.options.get("show-finisher-indicator")) { let timingText; const frameDelta = getFrameNumber() - hitFrame; //No hit occurred before this dash, early - if(hitFrame < 0) { + if (hitFrame < 0) { timingText = `Early`; } //We dashed on the immediate frame after the hit, perfect - else if((getFrameNumber() - hitFrame) <= 1) { + else if (getFrameNumber() - hitFrame <= 1) { timingText = `Perfect`; } //We were late and want to show time passed - else if(sc.options.get("show-finisher-time")) { + else if (sc.options.get("show-finisher-time")) { timingText = `Late (${roundValue(ig.Timer.time - hitTime)})`; } //We were late and want to show the number of frames late else { - timingText = `Late (${frameDelta - 1} frame${(frameDelta - 1 === 1) ? '' : 's'})`; + timingText = `Late (${frameDelta - 1} frame${frameDelta - 1 === 1 ? "" : "s"})`; } let dashTimingGui = new sc.SmallEntityBox(ig.game.playerEntity, timingText, finisherDisplayTime); dashTimingGui.stopRumble(); ig.gui.addGuiElement(dashTimingGui); - } + } } this.parent(); - } + }, +}); -}); \ No newline at end of file diff --git a/Utilities/freeSP.js b/Utilities/freeSP.js index c65c3e3..e22e3ca 100644 --- a/Utilities/freeSP.js +++ b/Utilities/freeSP.js @@ -1,6 +1,6 @@ /** * CrossCode Speedrun Utilities - freeSP.js - * + * * Hotkey for giving SP, gives points past the regular cap. */ @@ -31,7 +31,7 @@ sc.OPTIONS_DEFINITION["keys-free-sp"] = { type: "CONTROLS", init: { key1: ig.KEY.U, - key2: undefined + key2: undefined, }, cat: sc.OPTION_CATEGORY.CONTROLS, hasDivider: true, @@ -55,9 +55,12 @@ sc.OPTIONS_DEFINITION["free-sp-value"] = { sc.Control.inject({ freeSPPress: function () { return ig.input.pressed("free-sp"); - } + }, }); +export function giveFreeSp() { + ig.game.playerEntity.params.currentSp += sc.options.get("free-sp-value"); +} /** * @inject * Handle execution of keybinds @@ -65,9 +68,9 @@ sc.Control.inject({ ig.ENTITY.Player.inject({ gatherInput(...args) { if (sc.options && sc.control.freeSPPress()) { - this.params.currentSp += sc.options.get("free-sp-value"); + giveFreeSp(); } return this.parent(...args); - } -}); \ No newline at end of file + }, +}); diff --git a/Utilities/gameSpeed.js b/Utilities/gameSpeed.js index 9c12112..4ae5b38 100644 --- a/Utilities/gameSpeed.js +++ b/Utilities/gameSpeed.js @@ -1,38 +1,38 @@ /** * CrossCode Speedrun Utilities - gameSpeed.js - * + * * Hotkey for toggling game speed to a different value. */ sc.GAME_SPEED_PERCENTAGE_VALUES = { - SPEED_10: 0.10, - SPEED_20: 0.20, - SPEED_30: 0.30, - SPEED_40: 0.40, - SPEED_50: 0.50, - SPEED_60: 0.60, - SPEED_70: 0.70, - SPEED_80: 0.80, - SPEED_90: 0.90, - SPEED_100: 1.00, - SPEED_150: 1.50, - SPEED_200: 2.00, - SPEED_250: 2.50, - SPEED_300: 3.00, - SPEED_400: 4.00, - SPEED_500: 5.00, - SPEED_600: 6.00, - SPEED_700: 7.00, - SPEED_800: 8.00, - SPEED_900: 9.00, - SPEED_1000: 10.00 + SPEED_10: 0.1, + SPEED_20: 0.2, + SPEED_30: 0.3, + SPEED_40: 0.4, + SPEED_50: 0.5, + SPEED_60: 0.6, + SPEED_70: 0.7, + SPEED_80: 0.8, + SPEED_90: 0.9, + SPEED_100: 1.0, + SPEED_150: 1.5, + SPEED_200: 2.0, + SPEED_250: 2.5, + SPEED_300: 3.0, + SPEED_400: 4.0, + SPEED_500: 5.0, + SPEED_600: 6.0, + SPEED_700: 7.0, + SPEED_800: 8.0, + SPEED_900: 9.0, + SPEED_1000: 10.0, }; sc.OPTIONS_DEFINITION["keys-toggle-game-speed"] = { type: "CONTROLS", init: { key1: ig.KEY.PERIOD, - key2: undefined + key2: undefined, }, cat: sc.OPTION_CATEGORY.CONTROLS, hasDivider: false, @@ -50,6 +50,11 @@ sc.OPTIONS_DEFINITION["game-speed-value"] = { }; let isToggledSpeed = false; +export function toggleGameSpeed() { + isToggledSpeed = !isToggledSpeed; + + ig.Timer.timeScale = isToggledSpeed ? sc.options.get("game-speed-value") : 1; +} /** * @inject @@ -58,7 +63,7 @@ let isToggledSpeed = false; sc.Control.inject({ toggleGameSpeedPress: function () { return ig.input.pressed("toggle-game-speed"); - } + }, }); /** @@ -68,11 +73,9 @@ sc.Control.inject({ ig.ENTITY.Player.inject({ gatherInput(...args) { if (sc.control.toggleGameSpeedPress() && sc.options) { - isToggledSpeed = !isToggledSpeed; - - ig.Timer.timeScale = isToggledSpeed ? sc.options.get("game-speed-value") : 1; + toggleGameSpeed(); } return this.parent(...args); - } -}); \ No newline at end of file + }, +}); diff --git a/Utilities/healthHotkeys.js b/Utilities/healthHotkeys.js index df60705..9a120f4 100644 --- a/Utilities/healthHotkeys.js +++ b/Utilities/healthHotkeys.js @@ -1,6 +1,6 @@ /** * CrossCode Speedrun Utilities - healthHotkeys.js - * + * * Hotkeys for setting player and enemy health to specific amounts */ @@ -25,28 +25,28 @@ sc.HEALTH_PERCENTAGE_VALUES = { HEALTH_85: 0.85, HEALTH_90: 0.9, HEALTH_95: 0.95, - HEALTH_MAX: 1 + HEALTH_MAX: 1, }; //Targetted Relative Minimum Health //Empty is 0, Next Gate is next gate health to break sc.HEALTH_RELATIVE_MIN_OPTIONS = { EMPTY: 0, - NEXTGATE: 1 + NEXTGATE: 1, }; //Targetted Relative Maximum Health //Empty is 0, Last gate is most recently broken gate sc.HEALTH_RELATIVE_MAX_OPTIONS = { FULL: 0, - LASTGATE: 1 + LASTGATE: 1, }; sc.OPTIONS_DEFINITION["keys-health-player"] = { type: "CONTROLS", init: { key1: ig.KEY._9, - key2: undefined + key2: undefined, }, cat: sc.OPTION_CATEGORY.CONTROLS, hasDivider: false, @@ -67,7 +67,7 @@ sc.OPTIONS_DEFINITION["keys-health-enemy"] = { type: "CONTROLS", init: { key1: ig.KEY._0, - key2: undefined + key2: undefined, }, cat: sc.OPTION_CATEGORY.CONTROLS, hasDivider: false, @@ -111,19 +111,18 @@ sc.Control.inject({ return ig.input.pressed("health-player"); }, - healthEnemyPress: function() { + healthEnemyPress: function () { return ig.input.pressed("health-enemy"); - } + }, }); function getEnemyCandidate() { - let enemyCandidate = null; let enemies = ig.game.getEntitiesByType(ig.ENTITY.Enemy); - for(let i = 0; i < enemies.length; i++) { - if(enemies[i].params.currentHp > 0 && enemies[i].enemyType.boss) { + for (let i = 0; i < enemies.length; i++) { + if (enemies[i].params && enemies[i].params.currentHp > 0 && enemies[i].enemyType.boss) { enemyCandidate = enemies[i]; break; } @@ -133,54 +132,61 @@ function getEnemyCandidate() { } function setCombatantHp(combatant, healthPercentage) { - let newHp = 0; - if(combatant == sc.model.player) { + if (combatant == sc.model.player) { newHp = Math.round(combatant.params.getStat("hp") * healthPercentage); - } - else { - let relativeMinHp = 0, relativeMaxHp = combatant.params.getStat("hp"); + } else { + let relativeMinHp = 0, + relativeMaxHp = combatant.params.getStat("hp"); let hpBreakReached = combatant.hpBreakReached; - if(sc.options.get("health-enemy-relative-min-value") > 0 && hpBreakReached < combatant.enemyType.hpBreaks.length) { + if (sc.options.get("health-enemy-relative-min-value") > 0 && hpBreakReached < combatant.enemyType.hpBreaks.length) { relativeMinHp = combatant.params.getStat("hp") * combatant.enemyType.hpBreaks[hpBreakReached].hp; } - if(sc.options.get("health-enemy-relative-max-value") > 0 && hpBreakReached > 0) { + if (sc.options.get("health-enemy-relative-max-value") > 0 && hpBreakReached > 0) { relativeMaxHp = combatant.params.getStat("hp") * combatant.enemyType.hpBreaks[hpBreakReached - 1].hp; } newHp = Math.round(relativeMinHp + (relativeMaxHp - relativeMinHp) * healthPercentage); - } combatant.params.currentHp = newHp; - sc.Model.notifyObserver(combatant.params, sc.COMBAT_PARAM_MSG.HP_CHANGED) + sc.Model.notifyObserver(combatant.params, sc.COMBAT_PARAM_MSG.HP_CHANGED); + if (combatant == sc.model.player && newHp == 0) { + ig.game.playerEntity.kill(); + } +} + +export function setHealthPlayer() { + setCombatantHp(sc.model.player, sc.options.get("health-player-value")); +} + +export function setHealthEnemy() { + let enemyCandidate = getEnemyCandidate(); + + if (enemyCandidate) { + setCombatantHp(enemyCandidate, sc.options.get("health-enemy-value")); + } } /** * @inject * Handle execution of hotkeys. */ - ig.ENTITY.Player.inject({ +ig.ENTITY.Player.inject({ gatherInput(...args) { - if (sc.options) { if (sc.control.healthPlayerPress()) { - setCombatantHp(sc.model.player, sc.options.get("health-player-value")); + setHealthPlayer(); } - - if (sc.control.healthEnemyPress()) { - let enemyCandidate = getEnemyCandidate(); - - if(enemyCandidate) { - setCombatantHp(enemyCandidate, sc.options.get("health-enemy-value")); - } + if (sc.control.healthEnemyPress()) { + setHealthEnemy(); } } return this.parent(...args); - } -}); \ No newline at end of file + }, +}); diff --git a/Utilities/mobilityCheats.js b/Utilities/mobilityCheats.js index 8ced6f2..4ece0d3 100644 --- a/Utilities/mobilityCheats.js +++ b/Utilities/mobilityCheats.js @@ -1,6 +1,6 @@ /** * CrossCode Speedrun Utilities - mobilityCheats.js - * + * * Hotkeys for moving around including jetpack powers. */ @@ -8,7 +8,7 @@ sc.OPTIONS_DEFINITION["keys-jetpack"] = { type: "CONTROLS", init: { key1: ig.KEY.CTRL, - key2: undefined + key2: undefined, }, cat: sc.OPTION_CATEGORY.CONTROLS, hasDivider: false, @@ -20,7 +20,7 @@ sc.OPTIONS_DEFINITION["keys-jetpack"] = { * Inject hotkeys. */ sc.Control.inject({ - jetpackHold:function () { + jetpackHold: function () { return ig.input.state("jetpack"); }, }); @@ -36,5 +36,6 @@ ig.ENTITY.Player.inject({ } return this.parent(...args); - } -}); \ No newline at end of file + }, +}); + diff --git a/Utilities/saveAnywhere.js b/Utilities/saveAnywhere.js index 39ec14e..a278466 100644 --- a/Utilities/saveAnywhere.js +++ b/Utilities/saveAnywhere.js @@ -1,6 +1,6 @@ /** * CrossCode Speedrun Utilities - saveAnywhere.js - * + * * Toggle for allowing the Save button to always work regardless of if it would normally be disabled. */ @@ -20,9 +20,9 @@ sc.PauseScreenGui.inject({ updateButtons(...args) { this.parent(...args); - if(sc.options && sc.options.get("allow-save-anywhere")) - { + if (sc.options && sc.options.get("allow-save-anywhere")) { this.saveGameButton.setActive(true); } - } -}); \ No newline at end of file + }, +}); + diff --git a/Utilities/saveHotkeys.js b/Utilities/saveHotkeys.js index 06d2831..2a4e62e 100644 --- a/Utilities/saveHotkeys.js +++ b/Utilities/saveHotkeys.js @@ -1,6 +1,6 @@ /** * CrossCode Speedrun Utilities - saveHotkeys.js - * + * * Hotkeys for loading your latest autosave and making quicksaves * for quickly practicing segments repeatedly */ @@ -9,7 +9,7 @@ sc.OPTIONS_DEFINITION["keys-recentsave-load"] = { type: "CONTROLS", init: { key1: ig.KEY.J, - key2: undefined + key2: undefined, }, cat: sc.OPTION_CATEGORY.CONTROLS, hasDivider: false, @@ -20,7 +20,7 @@ sc.OPTIONS_DEFINITION["keys-quick-save"] = { type: "CONTROLS", init: { key1: ig.KEY.K, - key2: undefined + key2: undefined, }, cat: sc.OPTION_CATEGORY.CONTROLS, hasDivider: false, @@ -31,7 +31,7 @@ sc.OPTIONS_DEFINITION["keys-quick-load"] = { type: "CONTROLS", init: { key1: ig.KEY.L, - key2: undefined + key2: undefined, }, cat: sc.OPTION_CATEGORY.CONTROLS, hasDivider: false, @@ -49,13 +49,13 @@ sc.Control.inject({ return ig.input.pressed("recentsave-load"); }, - quickSavePress: function() { + quickSavePress: function () { return ig.input.pressed("quick-save"); }, - quickLoadPress: function() { + quickLoadPress: function () { return ig.input.pressed("quick-load"); - } + }, }); function resetForReload() { @@ -63,39 +63,47 @@ function resetForReload() { sc.model.player.reset(); //Fix PVP arenas carrying through loads - if(sc.pvp && sc.pvp.isActive()) - { + if (sc.pvp && sc.pvp.isActive()) { sc.pvp.onReset(); } } +export function recentSaveLoad() { + ig.storage.loadSlot(ig.storage.lastUsedSlot); + + resetForReload(); +} +export function quickSave() { + currQuickSave = {}; + ig.storage._saveState(currQuickSave); + currQuickSave = new ig.SaveSlot(currQuickSave); +} +export function quickLoad() { + if (currQuickSave) { + ig.storage.loadSlot(currQuickSave); + + resetForReload(); + } +} + /** * @inject * Handle execution of hotkeys. */ ig.ENTITY.Player.inject({ gatherInput(...args) { - if (sc.control.recentsaveLoadPress()) { - ig.storage.loadSlot(ig.storage.lastUsedSlot); - - resetForReload(); + quickLoad(); } if (sc.control.quickSavePress()) { - currQuickSave = {}; - ig.storage._saveState(currQuickSave); - currQuickSave = new ig.SaveSlot(currQuickSave); + quickSave(); } if (sc.control.quickLoadPress()) { - if(currQuickSave) { - ig.storage.loadSlot(currQuickSave); - - resetForReload(); - } + quickLoad(); } return this.parent(...args); - } -}); \ No newline at end of file + }, +}); diff --git a/Utilities/variableDisplay.js b/Utilities/variableDisplay.js index a1ae08d..e3fff5a 100644 --- a/Utilities/variableDisplay.js +++ b/Utilities/variableDisplay.js @@ -71,4 +71,4 @@ function updateDisplay() { ig.game.addons.postUpdate.push({ onPostUpdate: updateDisplay -}); \ No newline at end of file +}); diff --git a/Utilities/widgets.js b/Utilities/widgets.js new file mode 100644 index 0000000..28e951f --- /dev/null +++ b/Utilities/widgets.js @@ -0,0 +1,100 @@ +import { giveFreeSp } from './freeSP.js'; +import { toggleGameSpeed } from './gameSpeed.js'; +import { recentSaveLoad, quickSave, quickLoad } from './saveHotkeys.js'; +import { setHealthEnemy, setHealthPlayer } from './healthHotkeys.js'; + +if (window.nax && nax.ccuilib && nax.ccuilib.QuickRingMenuWidgets) { + nax.ccuilib.QuickRingMenuWidgets.addWidget({ + name: 'speedrun_freesp', + title: 'Give SP', + description: 'Gives the player SP', + pressEvent: () => { + giveFreeSp(); + // ig.game.playerEntity.params.currentSp += sc.options.get('free-sp-value') + }, + image: () => ({ + gfx: new ig.Image('media/gui/menu.png'), + srcPos: { x: 593, y: 18 }, + pos: { x: 11, y: 10 }, + size: { x: 12, y: 12 }, + }), + }); + nax.ccuilib.QuickRingMenuWidgets.addWidget({ + name: 'speedrun_togglegamespeed', + title: 'Toggle game speed', + description: 'Changes the game speed to the value specified in the settings.', + pressEvent: () => toggleGameSpeed(), + image: () => ({ + gfx: new ig.Image('media/gui/speedrunWidgetIcons.png'), + srcPos: { x: 0, y: 0 }, + pos: { x: 9, y: 8 }, + size: { x: 14, y: 16 }, + }), + }); + nax.ccuilib.QuickRingMenuWidgets.addWidget({ + name: 'speedrun_recentSaveLoad', + title: 'Load recent save', + description: 'Loads the recent save.', + pressEvent: () => { + ig.game.setPaused(false); + recentSaveLoad(); + }, + image: () => ({ + gfx: new ig.Image('media/gui/speedrunWidgetIcons.png'), + srcPos: { x: 38, y: 0 }, + pos: { x: 11, y: 8 }, + size: { x: 10, y: 16 }, + }), + }); + nax.ccuilib.QuickRingMenuWidgets.addWidget({ + name: 'speedrun_quickSave', + title: 'Quick save', + description: 'Saves the game', + pressEvent: () => quickSave(), + image: () => ({ + gfx: new ig.Image('media/gui/speedrunWidgetIcons.png'), + srcPos: { x: 15, y: 0 }, + pos: { x: 11, y: 8 }, + size: { x: 10, y: 16 }, + }), + }); + nax.ccuilib.QuickRingMenuWidgets.addWidget({ + name: 'speedrun_quickLoad', + title: 'Load the quick save', + description: 'Loads the quick save.', + pressEvent: () => { + ig.game.setPaused(false); + quickLoad(); + }, + image: () => ({ + gfx: new ig.Image('media/gui/speedrunWidgetIcons.png'), + srcPos: { x: 27, y: 0 }, + pos: { x: 11, y: 8 }, + size: { x: 10, y: 16 }, + }), + }); + nax.ccuilib.QuickRingMenuWidgets.addWidget({ + name: 'speedrun_playerhp', + title: "Set the player's hp", + description: "Set the player's hp.", + pressEvent: () => setHealthPlayer(), + image: () => ({ + gfx: new ig.Image('media/gui/menu.png'), + srcPos: { x: 579, y: 19 }, + pos: { x: 10, y: 11 }, + size: { x: 10, y: 10 }, + }), + }); + nax.ccuilib.QuickRingMenuWidgets.addWidget({ + name: 'speedrun_enemyhp', + title: 'Set the enemiy hp', + description: 'Set the enemy hp.', + pressEvent: () => setHealthEnemy(), + image: () => ({ + gfx: new ig.Image('media/gui/menu.png'), + srcPos: { x: 627, y: 34 }, + pos: { x: 11, y: 11 }, + size: { x: 10, y: 10 }, + }), + }); +} diff --git a/assets/media/gui/speedrunWidgetIcons.png b/assets/media/gui/speedrunWidgetIcons.png new file mode 100644 index 0000000..61c3d8f Binary files /dev/null and b/assets/media/gui/speedrunWidgetIcons.png differ diff --git a/ccmod.json b/ccmod.json index ed41a57..0cba817 100644 --- a/ccmod.json +++ b/ccmod.json @@ -1,15 +1,18 @@ { "id": "yoshi-speedrun-utilities", "version": "1.7.0", - "module": true, "title": "Speedrun Utilities", "description": "Various useful features for speedrunning and debugging.", - "prestart": "prestart.js", - "poststart": "poststart.js", + "repository": "https://github.com/CCDirectLink/cc-speedrun-utilities", + "tags": ["speedrun", "cheats", "widget"], + "authors": ["EpicYoshiMaster", "krypek"], + "icons": { + "24": "icon.png" + }, "dependencies": { "input-api": "^1.0.0" }, - "icons": { - "24": "icon.png" - } -} \ No newline at end of file + "prestart": "prestart.js", + "poststart": "poststart.js" +} + diff --git a/poststart.js b/poststart.js index 937e326..4cf467f 100644 --- a/poststart.js +++ b/poststart.js @@ -1,7 +1,8 @@ /** * CrossCode Speedrun Utilities - * + * * A growing collection of useful features for speedrunning and debugging the game. */ -import './Utilities/variableDisplay.js' \ No newline at end of file +import "./Utilities/variableDisplay.js"; + diff --git a/prestart.js b/prestart.js index 2c1cdbe..7156dd9 100644 --- a/prestart.js +++ b/prestart.js @@ -1,15 +1,16 @@ /** * CrossCode Speedrun Utilities - * + * * A growing collection of useful features for speedrunning and debugging the game. */ -import './Utilities/freeSP.js' -import './Utilities/saveHotkeys.js' -import './Utilities/gameSpeed.js' -import './Utilities/finisherIndicator.js' -import './Utilities/saveAnywhere.js' -import './Utilities/healthHotkeys.js' -import './Utilities/mobilityCheats.js' -import './Utilities/bombTimer.js' -import './Utilities/ballPrediction.js' \ No newline at end of file +import "./Utilities/freeSP.js"; +import "./Utilities/saveHotkeys.js"; +import "./Utilities/gameSpeed.js"; +import "./Utilities/finisherIndicator.js"; +import "./Utilities/saveAnywhere.js"; +import "./Utilities/healthHotkeys.js"; +import "./Utilities/mobilityCheats.js"; +import "./Utilities/bombTimer.js"; +import "./Utilities/ballPrediction.js"; +import "./Utilities/widgets.js";