Code:////////////Step 1. Add these codes under: ----> Moghunter.parameters = PluginManager.parameters('MOG_BattleHud'); <----////////////
Moghunter.MOGStateTurn = Moghunter.MOGStateTurn || {};
Moghunter.MOGStateTurn.FontType = String(PluginManager.parameters('MOGStateTurn')?.['Font Type'] || 'Trebuchet MS');
Moghunter.MOGStateTurn.FontSize = Number(PluginManager.parameters('MOGStateTurn')?.['Font Size'] || 18);
Moghunter.MOGStateTurn.FontOpacity = Number(PluginManager.parameters('MOGStateTurn')?.['Font Opacity'] || 255);
////////////Step 2. Add these codes under ----> // ♦ ALIAS ♦ Update <---- (optional if you don't have Visustella plugins)////////////
// ==============================
// Window_BattleActor: number follows BHud's actual state icon - SYNCHRONIZED VERSION
// ==============================
(function() {
var ROTATE_TICK = 0; // Perfect synchronization
// Store the original update method
var _orig_WBA_update = Window_BattleActor.prototype.update;
Window_BattleActor.prototype.update = function() {
_orig_WBA_update.call(this);
// Use the engine's actual state icon timing instead of separate fallback
if (!this._bhud_state_timer) this._bhud_state_timer = 0;
this._bhud_state_timer++;
// Only refresh numbers when state icons would actually change
if (this._bhud_state_timer >= ROTATE_TICK) {
this._bhud_state_timer = 0;
// Force refresh of number sprites to match state icon changes
if (this._bhud_numSprites) {
for (var i = 0; i < this._bhud_numSprites.length; i++) {
if (this._bhud_numSprites) {
this.redrawItem(i);
}
}
}
}
// Keep number sprites positioned correctly
if (this._bhud_numSprites) {
var iw = ImageManager.iconWidth || 32;
var ih = ImageManager.iconHeight || iw;
for (var n = 0; n < this._bhud_numSprites.length; n++) {
var s = this._bhud_numSprites[n];
if (!s) continue;
var rect = this.itemRect(n);
s.x = rect.x + rect.width - iw + 5;
s.y = rect.y + Math.floor((rect.height - ih) / 14);
}
}
};
// Get the current displayed icon index from the engine's state icon sprite
function getCurrentStateIconIndex(window, index) {
try {
// Method 1: Try to get from the window's state icon sprite directly
var actor = $gameParty.battleMembers()[index];
if (!actor) return null;
var actorId = actor.actorId();
var stateIconKey = "actor" + actorId + "-stateIcon";
if (window._additionalSprites && window._additionalSprites[stateIconKey]) {
var stateSprite = window._additionalSprites[stateIconKey];
// If the state sprite has a current icon index, use it
if (stateSprite._iconIndex !== undefined) {
return stateSprite._iconIndex;
}
}
// Method 2: Try HUD as fallback
var scene = SceneManager._scene;
if (!scene) return null;
var ss = scene._spriteSetBatHud;
if (!ss) return null;
var huds = ss._battle_hud;
if (!huds || !huds[index]) return null;
var hud = huds[index];
if (!hud._states_data) return null;
return hud._states_data[0] || null;
} catch (e) {
return null;
}
}
// Get the actual icon index that should be displayed right now
function getDisplayedIconIndex(actor) {
if (!actor) return 0;
var icons = actor.allIcons ? actor.allIcons() : [];
if (icons.length === 0) return 0;
// Use slower rotation for state icons
var rotationInterval = 180; // 180 frames = 3 seconds at 60 FPS
var iconIndex = Math.floor(Graphics.frameCount / rotationInterval) % icons.length;
return icons[iconIndex] || icons[0] || 0;
}
// Override drawItem to synchronize number with state icon
var _orig_WBA_drawItem = Window_BattleActor.prototype.drawItem;
Window_BattleActor.prototype.drawItem = function(index) {
_orig_WBA_drawItem.call(this, index);
if (!this._bhud_numSprites) this._bhud_numSprites = [];
var rect = this.itemRect(index);
var iw = ImageManager.iconWidth || 32;
var ih = ImageManager.iconHeight || iw;
var px = rect.x + rect.width - iw - 4;
var py = rect.y + Math.floor((rect.height - ih) / 8);
var spr = this._bhud_numSprites[index];
if (!spr) {
spr = new Sprite(new Bitmap(iw, ih));
this.addChild(spr);
this._bhud_numSprites[index] = spr;
}
spr.x = px;
spr.y = py;
var actor = $gameParty.battleMembers()[index];
if (!actor) {
spr.visible = false;
return;
}
// SYNCHRONIZED: Get the icon index using the same timing as state icons
var iconIndex = getCurrentStateIconIndex(this, index);
// Fallback: Use calculated timing that matches engine behavior
if (iconIndex === null || iconIndex === 0) {
iconIndex = getDisplayedIconIndex(actor);
}
// If still no valid icon, hide the number
if (!iconIndex) {
spr.visible = false;
return;
}
// Compute turns for that specific icon
var turns = findTurnsForIcon(actor, iconIndex);
if (turns === "" || turns === null || turns === undefined || Number(turns) <= 0) {
spr.visible = false;
return;
}
// Draw the number
drawNumberOnSprite(spr, turns, iw);
spr.visible = true;
};
// Helper function to find turns for a specific icon
function findTurnsForIcon(actor, iconIndex) {
var turns = null;
// Check states
if (actor.states) {
var states = actor.states();
for (var i = 0; i < states.length; i++) {
var state = states;
if (state && state.iconIndex === iconIndex) {
turns = actor.stateTurns ? actor.stateTurns(state.id) :
(actor._stateTurns && actor._stateTurns[state.id]) || 0;
if (state.autoRemovalTiming === 0) turns = "";
break;
}
}
}
// Check buffs if no state found
if ((turns === null || Number(turns) <= 0) && actor._buffs) {
for (var j = 0; j < actor._buffs.length; j++) {
if (actor._buffs[j] === 0) continue;
var buffIcon = 0;
if (actor.buffIconIndex) {
try {
buffIcon = actor.buffIconIndex(actor._buffs[j], j) ||
actor.buffIconIndex(j, actor._buffs[j]) || 0;
} catch (e) {
buffIcon = 0;
}
}
if (buffIcon === iconIndex) {
turns = (actor._buffTurns && actor._buffTurns[j]) || 0;
break;
}
}
}
return turns;
}
// Helper function to draw number on sprite
function drawNumberOnSprite(sprite, turns, iconWidth) {
var bmp = sprite.bitmap;
var iw = iconWidth;
bmp.clear();
// Font settings
bmp.fontFace = (Moghunter && Moghunter.MOGStateTurn && Moghunter.MOGStateTurn.FontType) || "Trebuchet MS";
bmp.fontSize = (Moghunter && Moghunter.MOGStateTurn && Number(Moghunter.MOGStateTurn.FontSize)) ||
Math.max(12, Math.floor(iw / 2.5));
var textWidth = iw - 4;
var textHeight = bmp.fontSize + 2;
var textX = 0;
var textY = 2;
// Draw text with shadow
bmp.textColor = "#000000";
bmp.drawText(String(turns), textX + 1, textY + 1, textWidth, textHeight, "right");
bmp.textColor = "#FFFFFF";
bmp.drawText(String(turns), textX, textY, textWidth, textHeight, "right");
}
// Also override refresh to ensure synchronization
var _orig_WBA_refresh = Window_BattleActor.prototype.refresh;
Window_BattleActor.prototype.refresh = function() {
_orig_WBA_refresh.call(this);
// Reset timer on refresh to stay in sync
this._bhud_state_timer = 0;
};
})();
// ==============================
// Fix State Icon Switching Speed in Actor Selection Window
// ==============================
(function() {
// Store the original Sprite_StateIcon update method
var _Sprite_StateIcon_update = Sprite_StateIcon.prototype.update;
// Override with slower rotation speed
Sprite_StateIcon.prototype.update = function() {
// Only call the original update every 3 frames to slow down rotation
if (!this._slowUpdateCounter) this._slowUpdateCounter = 0;
this._slowUpdateCounter++;
// Adjust this number to control state icon switching speed:
// Higher number = slower rotation
if (this._slowUpdateCounter >= 3) {
_Sprite_StateIcon_update.call(this);
this._slowUpdateCounter = 0;
}
};
})();
////////////Step 3. replace all of the below codes under this ----> // * Is Max Cast <----////////////
//==============================
// * Create States
//==============================
Battle_Hud.prototype.create_states = function() {
if (String(Moghunter.bhud_states_visible) != "true") {return};
this.removeChild(this._state_icon);
if (!this._battler) {return};
this._states_data = [0,0,0];
this._state_icon = new Sprite(this._state_img);
this._state_icon.x = this._pos_x + Moghunter.bhud_states_pos_x;
this._state_icon.y = this._pos_y + Moghunter.bhud_states_pos_y;
this._state_icon.visible = true;
this.addChild(this._state_icon);
this.refresh_states();
};
//==============================
// * Create States
//==============================
Battle_Hud.prototype.refresh_states = function() {
this._states_data[0] = 0;
this._states_data[2] = 0;
this._state_icon.visible = true;
var icons = this._battler.allIcons();
if (icons.length == 0) {
this._states_data[1] = 0;
this._state_icon.visible = false;
return;
}
if (icons[this._states_data[1]]) {
this._states_data[0] = icons[this._states_data[1]];
this._state_icon.visible = true;
// FIX: Properly set the icon frame (was missing/misconfigured)
var iconIndex = this._states_data[0];
var sx = iconIndex % 16 * 32;
var sy = Math.floor(iconIndex / 16) * 32;
this._state_icon.setFrame(sx, sy, 32, 32);
// NEW: Add turn number display for Timing Mode
this.update_state_turn_display(this._states_data[1]);
this._battler.need_refresh_bhud_states = false;
};
this._states_data[1] += 1;
if (this._states_data[1] >= icons.length) {
this._states_data[1] = 0;
};
};
//==============================
// display turn numbers in Timing Mode
//==============================
Battle_Hud.prototype.update_state_turn_display = function(iconIndex) {
// Remove any existing turn text
if (this._state_turn_text) {
this._state_icon.removeChild(this._state_turn_text);
}
var icons = this._battler.allIcons();
if (!icons[iconIndex]) return;
// Get the state or buff associated with this icon
var currentIcon = icons[iconIndex];
var turns = 0;
var isState = true;
// Check if it's a state
var states = this._battler.states();
for (var i = 0; i < states.length; i++) {
if (states.iconIndex === currentIcon) {
if (typeof this._battler.stateTurns === 'function') {
turns = this._battler.stateTurns(states.id);
} else {
turns = this._battler._stateTurns[states.id] || 0;
}
// Don't show turns for permanent states
if (states.autoRemovalTiming === 0) {
turns = "";
}
break;
}
}
// If not found in states, check buffs
if (turns === 0 && this._battler._buffs) {
isState = false;
for (var j = 0; j < this._battler._buffs.length; j++) {
if (this._battler._buffs[j] !== 0) {
var buffIcon = 0;
if (typeof this._battler.buffIconIndex === 'function') {
buffIcon = this._battler.buffIconIndex(this._battler._buffs[j], j);
}
if (buffIcon === currentIcon) {
turns = this._battler._buffTurns[j] || 0;
break;
}
}
}
}
// Don't display turn number if turns are empty, zero, or negative
if (turns === "" || turns === null || turns === undefined || Number(turns) <= 0) {
return;
}
// Create turn number display
this._state_turn_text = new Sprite(new Bitmap(32, 32));
this._state_turn_text.x = 8; // Position in bottom-right of icon
this._state_turn_text.y = -6;
var bmp = this._state_turn_text.bitmap;
bmp.fontSize = Moghunter.MOGStateTurn.FontSize;
bmp.fontFace = Moghunter.MOGStateTurn.FontType;
var ctx = bmp.context;
var old = ctx.globalAlpha;
ctx.globalAlpha = (Moghunter.MOGStateTurn.FontOpacity || 255) / 255;
// Draw outline
bmp.textColor = "#3b3b3bff";
bmp.drawText(String(turns), 1, 1, 32, 32, "center");
// Draw main text
bmp.textColor = "#ffffff";
bmp.drawText(String(turns), 0, 0, 32, 32, "center");
ctx.globalAlpha = old;
this._state_icon.addChild(this._state_turn_text);
};
//==============================
// * Update States
//==============================
Battle_Hud.prototype.update_states = function() {
this._states_data[2] += 1;
if (this.need_refresh_states()) {this.refresh_states();};
};
//==============================
// * Need Refresh States
//==============================
Battle_Hud.prototype.need_refresh_states = function() {
if (this._battler.need_refresh_bhud_states) {return true};
if (this._states_data[2] > 60) {return true}; // ← THIS CONTROLS THE SWITCHING SPEED
return false;
};
//==============================
// * Create States 2
//==============================
Battle_Hud.prototype.create_states2 = function() {
if (String(Moghunter.bhud_states_visible) != "true") {return};
this.removeChild(this._state_icon);
if (!this._battler) {return};
this._states_data = [0,0,0];
this._stateIcons = [];
this._state_icon = new Sprite();
this._state_icon.x = this._pos_x + Moghunter.bhud_states_pos_x;
this._state_icon.y = this._pos_y + Moghunter.bhud_states_pos_y;
this._state_icon.visible = true;
this.addChild(this._state_icon);
this.refresh_states2();
};
//==============================
// refresh_states2
//==============================
Battle_Hud.prototype.refresh_states2 = function() {
if (!this._state_icon) return;
if (!this._battler) return;
// authoritative icon list
var all = (typeof this._battler.allIcons === 'function') ? this._battler.allIcons() : [];
// quick exit if no icons
if (!all || all.length === 0) {
// clear previous children if any
if (this._stateIcons) {
for (var r = 0; r < this._stateIcons.length; r++) {
try { this._state_icon.removeChild(this._stateIcons[r]); } catch (e) {}
}
}
this._stateIcons = [];
this._last_icons = [];
this._state_icon.visible = false;
this._battler.need_refresh_bhud_states = false;
return;
}
if (this._last_icons && this._last_icons.length === all.length && !this._battler.need_refresh_bhud_states) {
var same = true;
for (var s = 0; s < all.length; s++) {
if (all !== this._last_icons) { same = false; break; }
}
if (same) {
this._state_icon.visible = true;
this._battler.need_refresh_bhud_states = false;
return;
}
}
// cache current icons and clear flag
this._last_icons = all.slice(0);
this._battler.need_refresh_bhud_states = false;
// remove previous sprites
if (this._stateIcons) {
for (var i = 0; i < this._stateIcons.length; i++) {
try { this._state_icon.removeChild(this._stateIcons); } catch(e) {}
}
}
this._stateIcons = [];
this._state_icon.visible = true;
var w = ImageManager.iconWidth || 32;
// build the data array: states then buffs (compact approach)
var states = (typeof this._battler.states === 'function') ? this._battler.states().filter(function(s){ return s && s.iconIndex > 0; }) : [];
var buffs = this._battler._buffs ? this._battler._buffs.slice(0) : [];
var data = [];
for (var n = 0; n < states.length; n++) data.push([true, states[n]]);
for (n = 0; n < buffs.length; n++) {
if (buffs[n] !== 0) {
var icon = 0;
if (typeof this._battler.buffIconIndex === 'function') {
try { icon = this._battler.buffIconIndex(buffs[n], n) || this._battler.buffIconIndex(n, buffs[n]) || 0; } catch(e) { icon = 0; }
}
data.push([false, icon, n]);
}
}
var icons = data.map(function(obj){ return obj[0] ? obj[1].iconIndex : obj[1]; });
var m = Math.min(Math.max(data.length, 0), Number(Moghunter.bhud_statesMax) || 4);
var align = Number(Moghunter.bhud_statesAlign) || 0;
for (i = 0; i < m; i++) {
var entry = data;
if (!entry) continue;
var iconIndex = icons || 0;
var spr = new Sprite_StateWithTurn(this._state_img, this._battler, entry);
var sx = (iconIndex % 16) * w;
var sy = Math.floor(iconIndex / 16) * w;
spr.setFrame(sx, sy, w, w);
if (align === 1) spr.x = -((w + 5) * i);
else if (align === 2) spr.y = (w + 5) * i;
else if (align === 3) spr.y = -((w + 5) * i);
else spr.x = (w + 5) * i;
this._state_icon.addChild(spr);
this._stateIcons.push(spr);
}
};
//==============================
// update_states2
//==============================
Battle_Hud.prototype.update_states2 = function() {
this._states_data = this._states_data || [0,0,0];
this._states_data[2] = (this._states_data[2] || 0) + 1;
// primary: refresh only if battler flagged a refresh
if (this._battler && this._battler.need_refresh_bhud_states) {
try { this.refresh_states2(); } catch (e) { /* ignore */ }
return;
}
// fallback: long interval refresh (~5 seconds at 60fps)
if (this._states_data[2] % 300 === 0) {
try { this.refresh_states2(); } catch (e) { /* ignore */ }
}
};
//==============================
//ensure HUD refresh when buff/state values change
//==============================
(function() {
var _a = Game_BattlerBase.prototype.addNewState;
Game_BattlerBase.prototype.addNewState = function(id){ _a.call(this, id); this.need_refresh_bhud_states = true; };
var _e = Game_BattlerBase.prototype.eraseState;
Game_BattlerBase.prototype.eraseState = function(id){ _e.call(this, id); this.need_refresh_bhud_states = true; };
if (typeof Game_BattlerBase.prototype.overwriteBuffTurns === 'function') {
var _o = Game_BattlerBase.prototype.overwriteBuffTurns;
Game_BattlerBase.prototype.overwriteBuffTurns = function(p, t){ _o.call(this, p, t); this.need_refresh_bhud_states = true; };
}
if (typeof Game_BattlerBase.prototype.addBuff === 'function') {
var _ab = Game_BattlerBase.prototype.addBuff;
Game_BattlerBase.prototype.addBuff = function(p, t){ _ab.call(this, p, t); this.need_refresh_bhud_states = true; };
}
if (typeof Game_BattlerBase.prototype.removeBuff === 'function') {
var _rb = Game_BattlerBase.prototype.removeBuff;
Game_BattlerBase.prototype.removeBuff = function(p){ _rb.call(this, p); this.need_refresh_bhud_states = true; };
}
})();
//==============================
// Sprite_StateWithTurn
//==============================
function Sprite_StateWithTurn() {
this.initialize.apply(this, arguments);
}
Sprite_StateWithTurn.prototype = Object.create(Sprite.prototype);
Sprite_StateWithTurn.prototype.constructor = Sprite_StateWithTurn;
Sprite_StateWithTurn.prototype.initialize = function(bitmap, actor, data) {
Sprite.prototype.initialize.call(this, bitmap);
this._actor = actor;
this._data = data || [null, 0];
// icon size (do not change these images)
this._iw = ImageManager.iconWidth || 32;
this._ih = ImageManager.iconHeight || 32;
// create a small child sprite to draw the turn number INTO (own bitmap)
this._numSprite = new Sprite(new Bitmap(this._iw, this._ih));
this._numSprite.visible = false;
// default font settings (safe)
this._numSprite.bitmap.fontFace = (Moghunter.MOGStateTurn && Moghunter.MOGStateTurn.FontType) || "Trebuchet MS";
this._numSprite.bitmap.fontSize = (Moghunter.MOGStateTurn && Moghunter.MOGStateTurn.FontSize) || 18;
// keep the number sprite inside the icon bounds (does NOT change icon size)
this._numSprite.x = 0;
this._numSprite.y = 0;
this.addChild(this._numSprite);
this._lastTurn = undefined;
};
Sprite_StateWithTurn.prototype.update = function() {
Sprite.prototype.update.call(this);
if (!this._actor || !this._data) {
if (this._numSprite) this._numSprite.visible = false;
return;
}
// Determine turns (state or buff)
var entry = this._data;
var turns = 0;
if (entry[0] === true) {
var st = entry[1];
if (!st) { this._numSprite.visible = false; return; }
if (typeof this._actor.stateTurns === 'function') {
try { turns = Number(this._actor.stateTurns(st.id)) || 0; } catch(e) { turns = Number((this._actor._stateTurns && this._actor._stateTurns[st.id]) || 0); }
} else { turns = Number((this._actor._stateTurns && this._actor._stateTurns[st.id]) || 0); }
if (st.autoRemovalTiming === 0) turns = "";
} else if (entry[0] === false) {
var p = entry[2];
if (this._actor && this._actor._buffTurns) {
try { turns = Number(this._actor._buffTurns[p]) || 0; } catch(e) { turns = 0; }
} else { turns = 0; }
} else {
this._numSprite.visible = false;
return;
}
// hide for zero/permanent
if (turns === "" || turns === null || turns === undefined || Number(turns) <= 0) {
this._numSprite.visible = false;
this._lastTurn = turns;
return;
}
// avoid unnecessary redraw
if (this._lastTurn !== undefined && this._lastTurn === turns) {
this._numSprite.visible = true;
return;
}
this._lastTurn = turns;
// draw number into the small child bitmap (this does NOT affect other bitmaps)
var bmp = this._numSprite.bitmap;
bmp.clear();
bmp.fontFace = (Moghunter.MOGStateTurn && Moghunter.MOGStateTurn.FontType) || "Trebuchet MS";
bmp.fontSize = (Moghunter.MOGStateTurn && Moghunter.MOGStateTurn.FontSize) || 18;
var ctx = bmp.context;
var oldAlpha = ctx.globalAlpha;
ctx.globalAlpha = ((Moghunter.MOGStateTurn && Moghunter.MOGStateTurn.FontOpacity) || 255) / 255;
bmp.textColor = "#3b3b3bff";
bmp.drawText(String(turns), 1, 1, bmp.width, bmp.height, "center");
bmp.textColor = "#ffffff";
bmp.drawText(String(turns), 0, 0, bmp.width, bmp.height, "center");
ctx.globalAlpha = oldAlpha;
// Position the number visually inside the icon at bottom-right without changing icon bounds
// Tweaks below: adjust px/py for exact pixel placement if needed.
var px = Math.round(bmp.width - 6); // place toward right inside icon
var py = Math.round(bmp.height - 22); // place toward bottom inside icon
// Because the number bitmap is the same size as the icon and drawText uses center,
// we offset by half the bitmap to visually place the number where we want it.
this._numSprite.x = px - (bmp.width / 2);
this._numSprite.y = py - (bmp.height / 2);
this._numSprite.visible = true;
};