NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Kamihime Project R - Display battle status info // @description Displays battle status turns left, time left, stacks and details info popup. // @updateURL https://openuserjs.org/meta/nike/Kamihime_Project_R_-_Display_battle_status_info.meta.js // @license MIT // @match https://gnkh-api-r.prod.nkh.dmmgames.com/front/cocos2d-proj/components-pc/game/app.html // @run-at document-start // ==/UserScript== (function() { var interval = setInterval(function() { if (typeof kh !== 'undefined' && kh.StatusEffectIcon && kh.StatusEffectIconHandler) { clearInterval(interval); if (kh.iconUpdate) { return; } kh.status_database = new Map() // ATK UP kh.status_database.set(5, { info: "B Frame", subscript: "B" }) kh.status_database.set(6, { info: "A Frame", subscript: "A" }) kh.status_database.set(7, { info: "C Frame", subscript: "C" }) kh.status_database.set(9, { info: "Stacking Frame", }) kh.status_database.set(40001, { info: "S/B Frame", subscript: "S" }) // ATK DOWN kh.status_database.set(10, { info: "A Frame", subscript: "A" }) kh.status_database.set(11, { info: "C Frame", subscript: "C" }) kh.status_database.set(12, { info: "B Frame", subscript: "B" }) kh.status_database.set(40002, { info: "S/B Frame", subscript: "S" }) // DEF UP kh.status_database.set(13, { info: "C Frame", subscript: "C" }) kh.status_database.set(14, { info: "A Frame", subscript: "A" }) kh.status_database.set(15, { info: "B Frame", subscript: "B" }) kh.status_database.set(74, { info: "D Frame", subscript: "D" }) kh.status_database.set(1213, { info: "E Frame", subscript: "E" }) kh.status_database.set(164, { info: "Stacking Frame" }) kh.status_database.set(40003, { info: "S/B Frame", subscript: "S" }) // DEF DOWN kh.status_database.set(16, { info: "A Frame", subscript: "A" }) kh.status_database.set(17, { info: "C Frame", subscript: "C" }) kh.status_database.set(18, { info: "B Frame", subscript: "B" }) kh.status_database.set(40004, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(158, { info: "Stacking Frame", }) // ABILITY DMG kh.status_database.set(19, { info: "A Frame", subscript: "A" }) kh.status_database.set(20, { info: "Stacking Frame", }) kh.status_database.set(96, { info: "Stacking Frame (2)", }) kh.status_database.set(1314, { info: "Medea", subscript: "M" }) // ELEMENTAL ATK UP - FIRE kh.status_database.set(101, { info: "A Frame", subscript: "A" }) kh.status_database.set(40009, { info: "S/B Frame", subscript: "S" }) // ELEMENTAL ATK UP - WATER kh.status_database.set(102, { info: "A Frame", subscript: "A" }) kh.status_database.set(40010, { info: "S/B Frame", subscript: "S" }) // ELEMENTAL ATK UP - WIND kh.status_database.set(103, { info: "A Frame", subscript: "A" }) kh.status_database.set(40011, { info: "S/B Frame", subscript: "S" }) // ELEMENTAL ATK UP - THUNDER kh.status_database.set(104, { info: "A Frame", subscript: "A" }) kh.status_database.set(40012, { info: "S/B Frame", subscript: "S" }) // ELEMENTAL ATK UP - LIGHT kh.status_database.set(105, { info: "A Frame", subscript: "A" }) kh.status_database.set(40013, { info: "S/B Frame", subscript: "S" }) // ELEMENTAL ATK UP - DARK kh.status_database.set(106, { info: "A Frame", subscript: "A" }) kh.status_database.set(40014, { info: "S/B Frame", subscript: "S" }) // DA kh.status_database.set(23, { info: "A Frame", subscript: "A" }) kh.status_database.set(196, { info: "B Frame", subscript: "B" }) kh.status_database.set(168, { info: "Stacking Frame", }) kh.status_database.set(40005, { info: "S/B Frame", subscript: "S" }) // TA kh.status_database.set(24, { info: "A Frame", subscript: "A" }) kh.status_database.set(169, { info: "Stacking Frame", }) kh.status_database.set(40006, { info: "S/B Frame", subscript: "S" }) // BURST DMG kh.status_database.set(137, { info: "A Frame", subscript: "A" }) kh.status_database.set(88, { info: "Stacking Frame", }) kh.status_database.set(157, { info: "Stacking Frame (2)", }) kh.status_database.set(183, { info: "S/B Frame", subscript: "S" }) // CRIT kh.status_database.set(139, { info: "A Frame", subscript: "A" }) kh.status_database.set(170, { info: "Stacking Frame", }) // AFFLICTION RATE UP kh.status_database.set(242, { info: "A Frame", subscript: "A" }) kh.status_database.set(419, { info: "Stacking Frame", }) // DMG CUT kh.status_database.set(1019, { info: "A Frame", subscript: "A" }) kh.status_database.set(37, { info: "B/Stacking Frame", }) kh.status_database.set(38, { info: "C Frame", subscript: "C" }) // ELEMENTAL RES kh.status_database.set(113, { info: "A Frame", subscript: "A" }) kh.status_database.set(114, { info: "A Frame", subscript: "A" }) kh.status_database.set(115, { info: "A Frame", subscript: "A" }) kh.status_database.set(116, { info: "A Frame", subscript: "A" }) kh.status_database.set(117, { info: "A Frame", subscript: "A" }) kh.status_database.set(118, { info: "A Frame", subscript: "A" }) kh.status_database.set(505, { info: "A Frame", subscript: "A" }) kh.status_database.set(40015, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40016, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40017, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40018, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40019, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40020, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40039, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(107, { info: "A Frame", subscript: "A" }) kh.status_database.set(108, { info: "A Frame", subscript: "A" }) kh.status_database.set(109, { info: "A Frame", subscript: "A" }) kh.status_database.set(110, { info: "A Frame", subscript: "A" }) kh.status_database.set(111, { info: "A Frame", subscript: "A" }) kh.status_database.set(112, { info: "A Frame", subscript: "A" }) kh.status_database.set(119, { info: "A Frame", subscript: "A" }) kh.status_database.set(120, { info: "A Frame", subscript: "A" }) kh.status_database.set(121, { info: "A Frame", subscript: "A" }) kh.status_database.set(122, { info: "A Frame", subscript: "A" }) kh.status_database.set(123, { info: "A Frame", subscript: "A" }) kh.status_database.set(124, { info: "A Frame", subscript: "A" }) kh.status_database.set(40021, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40022, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40023, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40024, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40025, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40026, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(476, { info: "A Frame", subscript: "A" }) kh.status_database.set(477, { info: "A Frame", subscript: "A" }) kh.status_database.set(40026, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(5068, { subscriptDescription: 1 }) kh.status_database.set(1876, { subscriptDescription: 2 }) kh.status_database.set(1118, { info: "Perseus", subscript: "P" }) kh.status_database.set(1119, { info: "Perseus", subscript: "P" }) // NATK DMG kh.status_database.set(238, { info: "A Frame", subscript: "A" }) kh.status_database.set(388, { info: "Stacking Frame" }) // MAX BURST DMG kh.status_database.set(152, { info: "A Frame", subscript: "A" }) kh.status_database.set(162, { info: "Stacking Frame" }) kh.status_database.set(521, { info: "Charlemagne", subscript: "CH" }) kh.status_database.set(40036, { info: "S/B Frame", subscript: "S" }) // MAX ABI DMG kh.status_database.set(188, { info: "A Frame", subscript: "A" }) kh.status_database.set(194, { info: "Stacking Frame" }) kh.status_database.set(327, { info: "Unknown frame" }) kh.status_database.set(1313, { info: "Medea's 3rd ability", subscript: "M" }) kh.status_database.set(1051, { info: "Medea passive" }) kh.status_database.set(40038, { info: "S/B Frame", subscript: "S" }) // MAX NATK DMG kh.status_database.set(185, { info: "A Frame", subscript: "A" }) kh.status_database.set(198, { info: "Unknown Frame" }) kh.status_database.set(40037, { info: "S/B Frame", subscript: "S" }) // DA / TA kh.status_database.set(25, { info: "A Frame", subscript: "A" }) kh.status_database.set(26, { info: "A Frame", subscript: "A" }) kh.status_database.set(40007, { info: "S/B Frame", subscript: "S" }) kh.status_database.set(40008, { info: "S/B Frame", subscript: "S" }) // AFFLICTION RST DOWN kh.status_database.set(22, { info: "A Frame", subscript: "A" }) kh.status_database.set(214, { info: "Stacking Frame" }) kh.status_database.set(1461, { info: "Thanatos", subscript: "T" }) // Special attack kh.status_database.set(276, { info: "A Frame", subscript: "A" }) kh.status_database.set(254, { info: "Stacking Frame" }) kh.status_database.set(40033, { info: "S/B Frame", subscript: "S" }) kh.updateDetailsLabel = function(text, subText, x, y) { var bw = kh.createInstance("battleWorld") var detailsLabelFrame = bw.UIFrontLayer.seekWidgetByName("details_label_frame") var detailsLabel; var background; var additionalLabel; if (!detailsLabelFrame) { detailsLabelFrame = new ccui.Layout() detailsLabelFrame.setName("details_label_frame") bw.UIFrontLayer.addChild(detailsLabelFrame) detailsLabel = detailsLabelFrame.seekWidgetByName("details_label") if (!detailsLabel) { detailsLabel = new ccui.Text() detailsLabelFrame.addChild(detailsLabel) } detailsLabel.setName("details_label") additionalLabel = detailsLabelFrame.seekWidgetByName("additional_label") if (!additionalLabel) { additionalLabel = new ccui.Text() additionalLabel.setName("additional_label") detailsLabelFrame.addChild(additionalLabel) } background = detailsLabelFrame.seekWidgetByName("details_label_background") if (!background) { background = new cc.LayerColor() background.setName("details_label_background") background.setAnchorPoint(0.5, 0.5); background.setZOrder(-1) detailsLabelFrame.addChild(background) } } else { background = detailsLabelFrame.seekWidgetByName("details_label_background") detailsLabel = detailsLabelFrame.seekWidgetByName("details_label") additionalLabel = detailsLabelFrame.seekWidgetByName("additional_label") } if (!text) { detailsLabelFrame.setVisible(false) return } detailsLabelFrame.setVisible(true) detailsLabel.setAnchorPoint(0.5, 0.0); detailsLabel.setFontSize(12); detailsLabel.setFontName("GameFont"); detailsLabel.setText(text) additionalLabel.setPosition(0, -20); additionalLabel.setAnchorPoint(0.5, 0.0); additionalLabel.setFontSize(12); additionalLabel.setText(subText ? subText : "") additionalLabel.setFontName("GameFont"); detailsLabelFrame.setAnchorPoint(0.0, 0.0); var backgroundWidth = 0 var marginH = 16 var marginV = 0 if (text && detailsLabel.getContentSize().width > backgroundWidth) { backgroundWidth = detailsLabel.getContentSize().width + marginH } if (subText && additionalLabel.getContentSize().width > backgroundWidth) { backgroundWidth = additionalLabel.getContentSize().width + marginH } var backgroundHeight = detailsLabel.getContentSize().height + (subText ? 20 + additionalLabel.getContentSize().height : 0) + marginV var noSubTextSizeOffset = subText ? 0 : 16 var noSubTextPositionOffset = subText ? 0 : 2 background.setContentSize(backgroundWidth, backgroundHeight + noSubTextSizeOffset) var backgroundXPosition = -backgroundWidth / 2 background.setPosition(backgroundXPosition, -backgroundHeight / 2 + noSubTextPositionOffset) var minX = 0 var maxX = 960 if (x + backgroundXPosition <= minX) { x = -backgroundXPosition } if (x - backgroundXPosition >= maxX) { x = maxX + backgroundXPosition } detailsLabelFrame.setPosition(x, y); } let isReallyVisible = (node) => { if (!node) { return true } return node.isVisible() && isReallyVisible(node.parent) } kh.StatusEffectIcon.prototype.init = function(widget) { this._widget = widget; var level_label_name = this._widget.name.replace("status", "status_level") var levelLabel = this._widget.parent.getChildByName(level_label_name) if (levelLabel) { this._levelLabel = levelLabel } else { var level_text = new ccui.Text(); level_text.setName(level_label_name); level_text.setFontSize(10); level_text.enableOutline(cc.color(0, 0, 32), 2); level_text.setFontName("GameFont"); this._widget.parent.addChild(level_text); this._levelLabel = level_text } var turn_label_name = this._widget.name.replace("status", "status_turn") var turnLabel = this._widget.parent.getChildByName(turn_label_name) if (turnLabel) { this._turnLabel = turnLabel } else { var turn_text = new ccui.Text(); turn_text.setName(turn_label_name); turn_text.setFontSize(10); turn_text.enableOutline(cc.color(32, 0, 0), 2); turn_text.setFontName("GameFont"); this._widget.parent.addChild(turn_text); this._turnLabel = turn_text } var time_label_name = this._widget.name.replace("status", "status_time") var timeLabel = this._widget.parent.getChildByName(time_label_name) if (timeLabel) { this._timeLabel = timeLabel } else { var time_text = new ccui.Text(); time_text.setName(time_label_name); time_text.setFontSize(10); time_text.enableOutline(cc.color(0, 0, 0), 2); time_text.setFontName("GameFont"); this._widget.parent.addChild(time_text); this._timeLabel = time_text } this.wasMoveover = false cc.eventManager.addListener({ event: cc.EventListener.MOUSE, onMouseMove: (event) => { if (this._statusEffect != null) { var target = event.getCurrentTarget(); var targetPos = target.convertToWorldSpace(target.position) var iconSize = 18 var rect = cc.rect(targetPos.x, targetPos.y, iconSize, iconSize); if (cc.rectContainsPoint(rect, event.getLocation()) && isReallyVisible(this._widget)) { this.wasMoveover = true var subText = null var subTexts = [] if (!this._widget) return; let bw = null; try { bw = kh.createInstance("battleWorld") } catch (ex) { return; } if (!bw?.battleUI) { return; } var enemyIndex = bw.enemyStatusBarList.findIndex((e) => e?._statusEffectIconHandler?._iconViewList?.find((i) => i._widget === this._widget) !== undefined) var characterIndex = bw?.characterPanelList.findIndex((e) => e?._card?.statusEffectIconHandler?._iconViewList?.find((i) => i._widget === this._widget) !== undefined) var characterPanelIndex = bw?.characterPanelList.findIndex((e) => e?._statusPanel._card?.statusEffectIconHandler?._iconViewList?.find((i) => i._widget === this._widget) !== undefined) if (enemyIndex === -1) { enemyIndex = undefined } if (characterIndex === -1) { characterIndex = undefined } if (characterPanelIndex === -1) { characterPanelIndex = undefined } obj = [ this._statusEffect?._enemies[enemyIndex], this._statusEffect?._characters[characterIndex] || this._statusEffect?._characters[characterPanelIndex] ].filter(x => x)[0]?.[0] if (obj) { var details = kh.status_database.get(this._statusEffect._id) if (details?.info) { subTexts.push(details.info) } if (obj.level) { subTexts.push(obj.level + " Stacks") } if (obj.turn) { subTexts.push(obj.turn + " Turns") } if (obj.seconds) { subTexts.push(obj.seconds.get() ? (obj.seconds.get() + "s") : "Expired") } if (subTexts.length > 0) { subText = subTexts.join(", ") } else { subText = null } kh.updateDetailsLabel(this._statusEffect._description, subText, targetPos.x + iconSize / 2, targetPos.y - 30) } } else if (this.wasMoveover) { this.wasMoveover = false kh.updateDetailsLabel(null, null, 0, 0) } } } }, widget); return this; } kh.StatusEffectIcon.prototype.draw = function(statusEffect) { this._statusEffect = statusEffect; if (this._statusEffect == null) { this._texture = null; this._widget.setVisible(false); this._levelLabel?.setVisible(false) this._turnLabel?.setVisible(false) this._timeLabel?.setVisible(false) return; } this._texture = kh.generateStatusIconPath(statusEffect.getType()); this._widget.setVisible(true); this._levelLabel?.setVisible(true) this._turnLabel?.setVisible(true) this._timeLabel?.setVisible(true) this._drawTexture(); } kh.iconUpdate = () => { let bw = null; try { bw = kh.createInstance("battleWorld") } catch (ex) { return; } if (!bw?.battleUI) { return; } // get all current icons let icons = [ ...bw?.enemyStatusBarList?.map( x => x?._statusEffectIconHandler?._iconViewList ), ...bw?.characterPanelList?.map( x => x?._card?.statusEffectIconHandler?._iconViewList ), ...bw?.characterPanelList?.map( x => x?._statusPanel._card?.statusEffectIconHandler?._iconViewList ), ] let thousandsFormatter = function(num) { return Math.abs(num) > 999 ? Math.sign(num) * ((Math.abs(num) / 1000).toFixed(1)) + 'k' : Math.sign(num) * Math.abs(num) } // stack type update functions let level = (icon) => { if (icon.obj?.level == null) { let databaseEntry = kh.status_database.get(icon?._statusEffect?._id) let subscript = databaseEntry?.subscript let subscriptDescription = databaseEntry?.subscriptDescription if (subscript) { icon._levelLabel?.setPosition(icon._widget.x - 8, icon._widget.y - 6); icon._levelLabel?.setText(subscript) } else if (subscriptDescription) { icon._levelLabel?.setPosition(icon._widget.x - 8, icon._widget.y - 6); let intValue if(subscriptDescription == 1) { intValue = parseInt(icon._statusEffect?._description?.replace(/\D/g, '')) } if(subscriptDescription == 2) { intValue = parseInt(icon._statusEffect?._description?.replace("Follow up deleted with 25,000,000 ", '').replace(/\D/g, '')) } let subscript if (!isNaN(intValue)) { subscript = (intValue / 1000000).toFixed(1) icon._levelLabel?.setText(subscript) } else { icon._levelLabel?.setText(""); } } else { icon._levelLabel?.setText(""); } return; } icon._levelLabel?.setPosition(icon._widget.x - 8, icon._widget.y - 6); icon._levelLabel?.setText(thousandsFormatter(icon.obj.level)) return }; let turn = (icon) => { if (icon.obj?.turn == null) { icon._turnLabel?.setText(""); return; } icon._turnLabel?.setPosition(icon._widget.x - 8, icon._widget.y + 8); icon._turnLabel?.setText(icon.obj?.turn.toString()) return }; let seconds = (icon) => { if (icon.obj?.seconds == null) { icon._timeLabel?.setText(""); return; } icon._timeLabel?.setPosition(icon._widget.x - 8, icon._widget.y + 8); let timeStamp = Math.ceil(icon.obj?.seconds?.get() / 10) || "X"; icon._timeLabel?.setText(timeStamp.toString()) if (timeStamp == "X") { icon._timeLabel?.setTextColor(cc.color(255, 150, 150)) } else { icon._timeLabel?.setTextColor(cc.color(150, 255, 150)) } } // update each icon icons.forEach(array => array?.forEach(icon => { if (!icon?._statusEffect) { icon._levelLabel?.setText(""); icon._turnLabel?.setText(""); icon._idLabel?.setText(""); icon._timeLabel?.setText(""); return; } if (!icon?._widget) return; var enemyIndex = bw.enemyStatusBarList.findIndex((e) => e?._statusEffectIconHandler?._iconViewList?.find((i) => i._widget === icon._widget) !== undefined) var characterIndex = bw?.characterPanelList.findIndex((e) => e?._card?.statusEffectIconHandler?._iconViewList?.find((i) => i._widget === icon._widget) !== undefined) var characterPanelIndex = bw?.characterPanelList.findIndex((e) => e?._statusPanel._card?.statusEffectIconHandler?._iconViewList?.find((i) => i._widget === icon._widget) !== undefined) if (enemyIndex === -1) { enemyIndex = undefined } if (characterIndex === -1) { characterIndex = undefined } if (characterPanelIndex === -1) { characterPanelIndex = undefined } icon.obj = [ icon._statusEffect?._enemies[enemyIndex], icon._statusEffect?._characters[characterIndex] || icon._statusEffect?._characters[characterPanelIndex] ].filter(x => x)[0]?.[0] var methods = [level, turn, seconds] methods.forEach((f) => { if (icon) { f(icon, icon?._statusEffect) } }) })) } setInterval(kh.iconUpdate, 500) } }, 10); })();