您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Revamps the chat and visual features of dueling.
// ==UserScript== // @name DuelingNexus Chat Improvements Plugin // @namespace https://duelingnexus.com/ // @version 0.6.2 // @description Revamps the chat and visual features of dueling. // @author Sock#3222 // @grant none // @match https://duelingnexus.com/game/* // ==/UserScript== // TODO: add github link let makeReadOnly = function (obj, prop) { let val = obj[prop]; delete obj[prop]; Object.defineProperty(obj, prop, { value: val, writable: false, enumerable: true, configurable: true, }); return val; } let ChatImprovements = { log: [], storage: { _cache: null, get: null, set: null, }, }; const LOCAL_STORAGE_KEY = "ChatImprovementsCache"; let updateLocalStorage = function () { let json = JSON.stringify(ChatImprovements.storage._cache); localStorage.setItem("ChatImprovementsCache", json); }; let checkCache = function () { if(ChatImprovements.storage._cache) { return; } let localCopy; try { localCopy = localStorage.getItem(LOCAL_STORAGE_KEY); localCopy = JSON.parse(localCopy) } catch(e) { console.error("Error parsing local copy:", localCopy); } ChatImprovements.storage._cache = localCopy || {}; updateLocalStorage(); }; ChatImprovements.storage.set = function (item, value) { checkCache(); ChatImprovements.storage._cache[item] = value; updateLocalStorage(); return value; }; ChatImprovements.storage.get = function (item) { checkCache(); return ChatImprovements.storage._cache[item]; }; ChatImprovements.storage.clear = function (item) { checkCache(); ChatImprovements.storage._cache = {}; updateLocalStorage(); }; // standard getter/setter properties let defaultProperties = { playSounds: true, temporaryChat: true, showOptions: false, showNormalEvents: true, showChainEvents: true, }; for(let [prop, defaultValue] of Object.entries(defaultProperties)) { // define if unset (inital run) if(typeof ChatImprovements.storage.get(prop) === "undefined") { ChatImprovements.storage.set(prop, defaultValue); } // getter & setter Object.defineProperty(ChatImprovements, prop, { get: function () { return ChatImprovements.storage.get(prop); }, set: function (value) { return ChatImprovements.storage.set(prop, value); }, }); } makeReadOnly(ChatImprovements, "log"); window.ChatImprovements = ChatImprovements; let waitFrame = function () { return new Promise(resolve => { requestAnimationFrame(resolve); //faster than set time out }); }; const waitForElementJQuery = async function (selector, source = $("body")) { let query; while (source.find(selector).length === 0) { await waitFrame(); } return query; }; let onload = function () { // css $("head").append($(`<style> #ci-ext-misc { float: left; width: 25%; overflow-x: hidden; overflow-y: auto; box-sizing: border-box; } #card-column { float: none; width: auto; } #ci-ext-misc-sections > div { overflow-x: hidden; overflow-y: auto; box-sizing: border-box; } #ci-ext-misc-sections > div:hover { z-index: 10; } #ci-ext-log > p, #ci-ext-event-log > p { padding: 0; margin: 3px; } #ci-ext-event-log .interact-name { cursor: pointer; } #ci-ext-log, #ci-ext-event-log, #ci-ext-options { background: rgb(0, 0, 0); background: rgba(0, 0, 0, 0.7); } @keyframes fullScale { from { transform: scale(1); } to { transform: scale(2); } } .material-preview { margin: 3px; } #ci-ext-misc-buttons { display: flex; justify-content: space-between; } #ci-ext-misc-buttons > button { flex-grow: 1; flex-basis: 0; } </style>`)); // TODO: move chaining options on bottom right // TODO: add hide options for sleeves/avatars // boilerplate const globalOptions = f; const playSound = Q; const sendEvent = K; const gameChatContent = $("#game-chat-content"); const gameChatTextbox = $("#game-chat-textbox"); const gameChatArea = $("#game-chat-area"); const showCardInColumn = Cc; const SECONDS = 1000; const monsterTypeMap = {}; for(let key in Wf) { let value = Wf[key]; monsterTypeMap[value] = parseInt(key, 10); } window.monsterTypeMap = monsterTypeMap; const isTrapCard = (card) => card.type & monsterTypeMap["Trap"]; const isSpellCard = (card) => card.type & monsterTypeMap["Spell"]; const isMonster = (card) => !isTrapCard(card) && !isSpellCard(card); const isToken = (card) => card.type & monsterTypeMap["Token"]; const isXyzMonster = (card) => card.type & monsterTypeMap["Xyz"]; const isPendulumMonster = (card) => card.type & monsterTypeMap["Pendulum"]; const isLinkMonster = (card) => card.type & monsterTypeMap["Link"]; const isFusionMonster = (card) => card.type & monsterTypeMap["Fusion"]; const isRitualMonster = (card) => isMonster(card) && (card.type & monsterTypeMap["Ritual"]); const isSynchroMonster = (card) => card.type & monsterTypeMap["Synchro"]; const isNormalMonster = (card) => card.type & monsterTypeMap["Normal"]; gameChatContent.css("overflow-y", "auto") // .css("height", "230px") // .css("background-color", "transparent"); // gameChatArea.css("background-color", "rgba(0, 0, 0)") // .css("background-color", "rgba(0, 0, 0, 0.7)"); let chatLog = $("<div id=ci-ext-log>"); let chatEventLog = $("<div id=ci-ext-event-log>"); /**/ Gb.GameSet = window.Td = function Td(a) { Q("set"); // console.log("Td", a); }; Gb.GameSummoning = window.Ud = function Ud(a) { xc(a.cardCode, function() { Q("summon"); // console.log("Ud", a); kf(a.cardCode); }); return true; } Gb.GameSpSummoning = window.Vd = function Vd(a) { xc(a.cardCode, function() { Q("summon-special"); // console.log("Vd", a); kf(a.cardCode); }); return true; } Gb.GameFlipSummoning = window.Wd = function Wd(a) { xc(a.cardCode, function() { Q("summon-flip"); // console.log("Wd", a); kf(a.cardCode); }); return true; } const CHAIN_SYMBOL = "\uD83D\uDD17"; Gb.GameChaining = window.Xd = function Xd(a) { xc(a.cardCode, function() { Q("activate"); let cardName = a.cardCode ? "#@" + a.cardCode : "A card"; // console.log("!!!!", cardName); // notifyEvent(" of " + cardName + " was activated (from " + GameLocations[a.location]); let message = `Chain Link ${a.chainCount}: ${cardName}` if(a.chainCount > 1) { message = CHAIN_SYMBOL + " " + message; } notifyEvent(message, Events.CHAIN); kf(a.cardCode); }); return true; } /* GameDamage: Yd, GameRecover: Zd, GamePayLpCost: $d, GameLpUpdate: ae, GameAttack: be, GameBattle: ce, GameReloadField: de, GameTagSwap: ee, GameFieldDisabled: fe, GameWaiting: ge, GameEquip: he, GameBecomeTarget: ie, GameWin: je, GameTossCoin: ke, GameTossDice: le, GameAddCounter: me, GameRemoveCounter: ne, GameConfirmCards: oe, GameConfirmDeckTop: pe, GameDeckTop: qe, GameRetry: re, GameSelectIdleCommand: se, GameSelectBattleCommand: te, GameSelectCard: ue, GameSelectUnselect: ve, GameSortCards: we, GameSelectTribute: xe, GameSelectYesNo: ye, GameSelectEffectYesNo: ze, GameSelectChain: Ae, GameSelectPosition: Be, GameSelectOption: Ce, GameSelectSum: De, GameSelectPlace: Ee, GameSelectCounter: Fe, GameAnnounceAttrib: Ge, GameAnnounceRace: He, GameAnnounceNumber: Ie, GameAnnounceCard: Je */ let eventTypeList = [ ]; let timestamp = function () { let now = new Date(); return [ now.getHours(), now.getMinutes(), now.getSeconds() ].map(time => time.toString().padStart(2, "0")).join(":"); } const scrollToBottom = function (el) { el = $(el); el.animate({ scrollTop: el.prop("scrollHeight") }, 150); } const MESSAGE_PARSE_REGEX = /#@(\d+)|.+?/g; let colorOfCard = function (card) { if(isTrapCard(card)) { return "#BC5A84"; } else if(isSpellCard(card)) { return "#1D9E74"; } else { return "#B83D00"; } } let displayMessage = function (content, color, ...kinds) { //showCardInColumn let matches; let message = $("<p>"); while(matches = MESSAGE_PARSE_REGEX.exec(content)) { let id = parseInt(matches[1]); let card = X[id]; if(id && card) { let interactive = $("<span>") .css("color", "white") .css("background-color", colorOfCard(card)) .data("id", id) .addClass("interact-name"); interactive.hover(function () { showCardInColumn(id); }); interactive.text('"' + card.name + '"'); message.append(interactive); } else { message.append(matches[0]); } } for(let kind of kinds) { message.addClass(kind); } if(color) { message.css("color", color); } gameChatContent.append(message); let copy = message.clone(true); if(kinds.indexOf("notified-event") !== -1) { $(".interact-name", copy).unbind().click(function () { showCardInColumn($(this).data("id")); showCardColumn.click(); }); chatEventLog.append(copy); } else { chatLog.append(copy); } // scroll to message scrollToBottom(chatLog); scrollToBottom(gameChatContent); // handle UI if(ChatImprovements.temporaryChat) { if(gameChatContent.children().length > 10) { gameChatArea.find("p:first").remove(); } setTimeout(function() { message.remove(); }, 10 * SECONDS); } return message; } ChatImprovements.displayMessage = displayMessage; // overwrite send message window.td = displayMessage; let unifyMessage = function (message) { return timestamp() + " " + message; } let displayOpponentsMessage = function (a) { if(ChatImprovements.playSounds) { playSound("chat-message"); } let playerId = a.playerId; let message = a.message; let color; if(0 <= playerId && 3 >= playerId) { let name = B[playerId].name; message = "[" + name + "]: " + message; } else { color = "yellow"; } message = unifyMessage(message); displayMessage(message, color); } gameChatTextbox.unbind(); gameChatTextbox.keyup(function(ev) { if(ev.keyCode == 13) { let message = gameChatTextbox.val(); gameChatTextbox.val(""); sendEvent({ type: "SendChatMessage", message: message }); message = unifyMessage("[" + Ib + "]: " + message); // TODO: assign each person a different color? if(4 > A) { displayMessage(message); } else { displayMessage(message, "yellow"); } } }); // create sections let miscContainer = $("<div id=ci-ext-misc>"); let miscSections = $("<div id=ci-ext-misc-sections>"); let optionsColumn = $("<div id=ci-ext-options>"); let cardColumn = $("#card-column"); let gameContainer = $("#game-container"); gameContainer.prepend(miscContainer); class GameOption { constructor(tag, id, option, type, info = {}) { this.tag = tag; this.id = id; this.option = option; this.type = type; this.isBaseOption = !!info.isBaseOption; this.showValue = !!info.showValue; this.decoration = info.decoration || (() => ""); this.resolveOnLoad = info.resolveOnLoad; this.resolve = info.resolve; if(this.resolve) { this.resolve = this.resolve.bind(this); } if(this.isRange) { this.min = info.min; this.max = info.max; } } get isRange() { return this.type === "range"; } get isCheckbox() { return this.type === "checkbox"; } toElement(formatTable = true) { let base = $("<input>"); base.attr("id", id) .attr("type", this.type); if(this.isRange) { base.attr("min", this.min) .attr("max", this.max); } let currentValue; if(this.isBaseOption) { currentValue = globalOptions.options[this.option]; } else { currentValue = ChatImprovements[this.option]; } if(this.isCheckbox) { base.prop("checked", currentValue); } else { base.val(currentValue); } base.data("option", this.option); let onValueChange = () => { let option = this.option; let value = this.isCheckbox ? base.prop("checked") : base.val(); if(this.isBaseOption) { globalOptions.options[option] = value; globalOptions.save(); // NOTE: can break jd && jd(option, value); } else { ChatImprovements[option] = value; } if(updateValueTd) { updateValueTd.text(this.decoration(value)); } if(this.resolve) { this.resolve(value); } }; let updateValueTd; if(this.showValue) { updateValueTd = $("<td>"); // DRY broken here a bit updateValueTd.text(this.decoration(currentValue)) .css("cursor", "pointer"); updateValueTd.click(() => { let newValue = prompt("Enter the new value for \"" + this.tag + "\":"); if(newValue !== null) { base.val(newValue); onValueChange(); } }); } base.change(onValueChange); if(!formatTable) { return base; } let tr = $("<tr>"); tr.append($("<td>").text(this.tag)); tr.append($("<td>").append(base)); if(this.showValue) { tr.append(updateValueTd); } return tr; } } /* var a = $(this).data("option"), b = $(this).val(); $("#options-" + a + "-value").text(b + "%"); f.options[a] = b; f.save(); jd && jd(a, b) */ // initialize options column let optionsColumnInfo = [ [ "Game Options", new GameOption( "Sounds volume", "ci-ext-option-sounds-volume", "sounds", "range", { min: 0, max: 100, isBaseOption: true, showValue: true, decoration: (x) => `${x}%`, } ), new GameOption( "Music volume", "ci-ext-option-music-volume", "music", "range", { min: 0, max: 100, isBaseOption: true, showValue: true, decoration: (x) => `${x}%`, } ), new GameOption( "Animations speed", "ci-ext-option-animation-speed", "speed", "range", { min: 0, max: 500, isBaseOption: true, showValue: true, decoration: (x) => `${x}%`, } ), ], [ new GameOption( "Place monsters automatically", "ci-ext-option-auto-place-monsters", "auto-place-monsters", "checkbox", { isBaseOption: true, } ), new GameOption( "Place spells automatically", "ci-ext-option-auto-place-spells", "auto-place-spells", "checkbox", { isBaseOption: true, } ), new GameOption( "Temporary chat", "ci-ext-option-temporary-chat", "temporaryChat", "checkbox", { resolve: function () { // TODO: hide existing chat } } ), new GameOption( "Play chat sounds", "ci-ext-option-chat-sounds", "playSounds", "checkbox", ), new GameOption( "Show options", "ci-ext-option-show-options", "showOptions", "checkbox", { resolve: function (value) { console.log("Resolving showOptions value", value); $("#options-show-button").toggle(value); return this; }, resolveOnLoad: true, } ), ], [ "Event Filters", new GameOption( "Show normal events", "ci-ext-option-hide-all-events", "showNormalEvents", "checkbox", ), new GameOption( "Show chaining events", "ci-ext-option-hide-all-events", "showChainEvents", "checkbox", ), ] ]; for(let stratum of optionsColumnInfo) { let table = $("<table>"); while(stratum.length && typeof stratum[0] === "string") { let title = stratum.shift(); optionsColumn.append($("<h2>").text(title)); } for(let option of stratum) { let tr = option.toElement(true); if(option.resolveOnLoad) { console.log(tr); option.resolve(); } table.append(tr); } optionsColumn.append(table); } /*.click(function() { var a = $(this).data("option"), b = $(this).val(); $("#options-" + a + "-value").text(b + "%"); f.options[a] = b; f.save(); if(jd) { jd(a, b); } })*/ let miscSectionButtons = $("<div id=ci-ext-misc-buttons>"); // moved earlier for hideMiscBut let minimizeToggle = $("<button class=engine-button title=minimize>−</button>") .data("toggled", false) .click(function () { let toggled = $(this).data("toggled"); gameChatContent.toggle(toggled); gameChatTextbox.toggle(toggled); toggled = !toggled; $(this).data("toggled", toggled); scrollToBottom(gameChatContent); }); const hideMiscBut = function (but) { return function (ev) { for(let child of miscSections.children()) { let isVisible = child.id === but; $(child).toggle(isVisible); if(isVisible) { scrollToBottom(child); } } gameChatContent.toggle(but !== "ci-ext-log" && but !== "ci-ext-event-log" && !minimizeToggle.data("toggled")); }; }; // button toggles for sections let showCardColumn = $("<button id=ci-ext-show-card-column class=engine-button>Card Info</button>"); let showChatLog = $("<button id=ci-ext-show-chat-log class=engine-button>Chat Log</button>"); let showEventLog = $("<button id=ci-ext-show-event-log class=engine-button>Event Log</button>"); let showOptions = $("<button id=ci-ext-show-options class=engine-button>Options</button>"); showCardColumn.click(hideMiscBut("card-column")); showChatLog.click(hideMiscBut("ci-ext-log")); showEventLog.click(hideMiscBut("ci-ext-event-log")); showOptions.click(hideMiscBut("ci-ext-options")); miscSectionButtons.append(showCardColumn, showChatLog, showEventLog, showOptions); miscContainer.append(miscSectionButtons); cardColumn.detach(); miscSections.append(cardColumn); miscSections.append(chatLog); miscSections.append(chatEventLog); miscSections.append(optionsColumn); showCardColumn.click(); miscContainer.append(miscSections); // update ui // TODO: toggle even newly inserted messages // let updateMuteToggleText; // let muteToggle = $("<button class=engine-button></button>") // .click(function () { // ChatImprovements.playSounds = !ChatImprovements.playSounds; // updateMuteToggleText(); // }) // .css("float", "right"); // updateMuteToggleText = function () { // muteToggle.text(ChatImprovements.playSounds ? "Mute" : "Unmute"); // }; // updateMuteToggleText(); // let updateNotificationToggleText; // let notificationToggle = $("<button class=engine-button></button>") // .click(function () { // ChatImprovements.showEvents = !ChatImprovements.showEvents; // updateNotificationToggleText(); // $("#game-chat-area .notified-event").toggle(ChatImprovements.showEvents); // }) // .css("float", "right"); // updateNotificationToggleText = function () { // notificationToggle.text(ChatImprovements.showEvents ? "Hide events" : "Show events"); // }; // updateNotificationToggleText(); // let gameChatArea.prepend( minimizeToggle, /*muteToggle,*/ /*notificationToggle*/ ); // listeners[type] = [...]; let listeners = {}; ChatImprovements.addEventListener = function (ev, cb) { // TODO: verify listeners[ev] = listeners[ev] || []; listeners[ev].push(cb); } // reference const log = ChatImprovements.log; rb.shift = function (...args) { let res = Array.prototype.shift.apply(rb, args); log.push(res); if(typeof res.length !== "undefined") { alert("whoa! unexpected arguments passed to sb.shift!"); } let eventType = res.type; if(listeners[eventType]) { for(let cb of listeners[eventType]) { cb(res); } } return res; } const Events = { CHAIN: "chain", NORMAL: "normal", }; const notificationColors = { [Events.NORMAL]: "#00FF00", [Events.CHAIN]: "#AAFFAA", }; const notificationPrefixes = { [Events.NORMAL]: "Event: ", [Events.CHAIN]: "", }; const eventEnabledKeys = { [Events.NORMAL]: "showNormalEvents", [Events.CHAIN]: "showChainEvents", }; const notifyEvent = function (event, kind = Events.NORMAL) { let prefix = notificationPrefixes[kind]; let color = notificationColors[kind]; let message = displayMessage(prefix + event, color, "notified-event", "event-" + kind); let enabledKey = eventEnabledKeys[kind]; message.toggle(ChatImprovements[enabledKey]); }; const GameLocations = { TOKEN_PILE: 0, DECK: 1, HAND: 2, FIELD_MONSTER: 4, FIELD_SPELLTRAP: 8, FIELD: 4 | 8, GY: 16, BANISHED: 32, EXTRA_DECK: 64, XYZ_MATERIAL: 128, }; const LocationNames = { [GameLocations.TOKEN_PILE]: "token pile", [GameLocations.DECK]: "the Deck", [GameLocations.HAND]: "the hand", [GameLocations.FIELD_MONSTER]: "a Monster Zone", [GameLocations.FIELD_SPELLTRAP]: "a Spell & Trap Zone", [GameLocations.GY]: "the GY", [GameLocations.BANISHED]: "being banished", [GameLocations.EXTRA_DECK]: "the Extra Deck", 192: " an Xyz Monster [bugged response, please report!]", }; let cardCodeToSkip = null; let movedFromTo = function (move, start, end) { return (move.previousLocation & start) !== 0 && (move.currentLocation & end) !== 0; } ChatImprovements.addEventListener("GameMove", function (move) { let cardName = move.cardCode ? "#@" + move.cardCode : "A card"; if(move.cardCode) { cardCodeToSkip = move.cardCode; } // sent to GY if(movedFromTo(move, GameLocations.XYZ_MATERIAL, GameLocations.GY) || movedFromTo(move, GameLocations.XYZ_MATERIAL, GameLocations.BANISHED)) { status = "was detached as Xyz Material" } else if(move.currentLocation === GameLocations.GY) { status = "was sent to the GY from " + LocationNames[move.previousLocation]; } // returned to the deck else if(move.currentLocation === GameLocations.DECK) { status = "was shuffled/placed into the Deck from " + LocationNames[move.previousLocation]; } // returned to the extra deck else if(move.currentLocation === GameLocations.EXTRA_DECK) { status = "was returned to the Extra Deck from " + LocationNames[move.previousLocation]; } // attached as xyz material? else if(move.currentLocation & GameLocations.XYZ_MATERIAL) { status = "was attached as Xyz Material from " + LocationNames[move.previousLocation]; } // banished else if(move.currentLocation === GameLocations.BANISHED) { status = "was banished from " + LocationNames[move.previousLocation]; } // sent to hand else if(movedFromTo(move, GameLocations.GY, GameLocations.HAND)) { // console.log("why??????"); status = "was returned from the GY to the hand"; } else if(movedFromTo(move, GameLocations.DECK, GameLocations.HAND)) { status = "was added from the Deck to the hand"; } else if(movedFromTo(move, GameLocations.BANISHED, GameLocations.HAND)) { status = "was added to the hand from being banished"; } else if(movedFromTo(move, GameLocations.FIELD, GameLocations.HAND)) { status = "was returned from the field to the hand"; } else if(movedFromTo(move, GameLocations.EXTRA_DECK, GameLocations.HAND)) { status = "was added to the hand from the face-up Extra Deck"; } // monster summons else if(move.currentLocation === GameLocations.FIELD_MONSTER) { status = "was Summoned from " + LocationNames[move.previousLocation]; } // spell card activations else if(move.currentLocation === GameLocations.FIELD_SPELLTRAP) { // TODO: set vs. activate console.log(move); status = "was activated/set from " + LocationNames[move.previousLocation]; } else if(movedFromTo(move, GameLocations.FIELD, GameLocations.TOKEN_PILE)) { status = "was removed from the field"; } else { // 0 from 4 status = "- UNSURE!! " + move.currentLocation + " from " + move.previousLocation; } notifyEvent(cardName + " " + status); // TODO: more }); ChatImprovements.addEventListener("cfReveal", function (code) { if(code && code !== cardCodeToSkip) { notifyEvent("Revealed #@" + code); } cardCodeToSkip = null; }); ChatImprovements.addEventListener("targetCardAnimation", function (code) { if(code) { notifyEvent("Targeted #@" + code); } }); // redefine window resizing window.Wb = function Wb() { var a = $("#ci-ext-misc-sections").position().top; // originally: - 24 const offset = 37; $("#ci-ext-misc-sections div") .css("max-height", $(window).height() - a - offset); $("#game-siding-column") .css("max-height", $(window).height() - a - offset); a = 4 === Ab ? 7 : 6; var b = $(window).width() - $("#ci-ext-misc").width() - 50, // c = $(window).height();// - $("#game-chat-area").height() - 8 - 48; c = $(window).height() - $("#game-chat-textbox").outerHeight() - 8 - 48; 9 * c / a < b ? ($("#game-field").css("height", c + "px"), b = c / a, $("#game-field").css("width", 9 * b + "px")) : ($("#game-field").css("width", b + "px"), b /= 9, $("#game-field").css("height", b * a + "px")); $(".game-field-zone").css("width", b + "px").css("height", b + "px"); $(".game-field-hand").css("width", 5 * b + "px").css("height", b + "px"); Cb = b; Db = Math.floor(.95 * b); E = 177 * Db / 254; Zc(m[0]); Zc(m[1]); $("#game-position-atk-up").css("width", E); $("#game-position-atk-up").css("height", Db); $("#game-position-atk-up").css("margin-right", Db - E + 3); $("#game-position-atk-down").css("width", E); $("#game-position-atk-down").css("height", Db); $("#game-position-atk-down").css("margin-right", Db - E + 3); $("#game-position-def-up").css("width", E); $("#game-position-def-up").css("height", Db); $("#game-position-def-up").css("margin-right", Db - E + 3); $("#game-position-def-down").css("width", E); $("#game-position-def-down").css("height", Db); $(".game-selection-card-image").css("width", E); zb && $c(); } window.qf = function qf(a, b) { if(listeners["targetCardAnimation"]) { for(let cb of listeners["targetCardAnimation"]) { cb(a.code); } } let originalZ = a.a.css("z-index"); a.a.css("z-index", 10000) .css("animation", "fullScale " + (600 * C) + "ms"); a.a.animate({ opacity: .5 }, { duration: 100 * C }).animate({ opacity: 1 }, { duration: 100 * C }).animate({ opacity: .5 }, { duration: 100 * C }).animate({ opacity: 1 }, { duration: 100 * C }).animate({ opacity: .5 }, { duration: 100 * C }).animate({ opacity: 1 }, { duration: 100 * C, complete: function () { a.a.css("animation", "") .css("z-index", originalZ); if(b) { b(); } } }); }; window.df = function df(a, b, c, d, e) { if(listeners["cfReveal"]) { for(let cb of listeners["cfReveal"]) { cb(b); } } var g = a.a.offset(), k = a.location & O.j || c & 5 ? b : 0, w = hg(a.controller, a.location, c) - a.va, F = false; if(a.Kb !== k) { F = true; } if(null !== a.b) { a.b.hide(); a.K.hide(); } a.code = b; a.position = c; $("<div />").animate({ height: 1 }, { duration: d, step: function(b, c) { b = c.pos; c = "translate("; c += (a.ta.left - g.left) * (1 - b); c += "px, "; c += (a.ta.top - g.top) * (1 - b); c += "px)"; c += " rotate(" + (a.va + w * b) + "deg)"; if(F) { if(.5 < b) { ig(a, k); } c += " scalex(" + Math.abs(1 - 2 * b) + ")"; } a.a.css("transform", c) }, complete: function() { null !== a.b && (a.b.show(), a.K.show()); a.a.css("position", ""); nf(a); e() } }) } // re-add listener // remove current resize listener // $(window).off("resize", Vb); // $(window).resize(Vb); Fb.ChatMessageReceived = window.qd = displayOpponentsMessage; console.info("ChatImprovements plugin loaded!"); // let overlayExtension; $(".game-field-zone").on("mouseover", function (ev) { let player = $(this).data("player"); let location = $(this).data("location"); let index = $(this).data("index"); let card = T(player, location, index); if(!card) return; let overlays = card.l; if(!overlayExtension) { overlayExtension = $("<p id=game-tooltip-overlay-extension></p>"); $("#game-tooltip .card-if-monster").append(overlayExtension); } if(overlays && overlays.length) { $(overlayExtension).empty(); let { width, height } = this.querySelector("img"); console.log("width, height:", width, height); let plural = overlays.length === 1 ? "" : "s"; let msg = "[" + overlays.length.toString() + " material" + plural + "]\n"; $(overlayExtension).append($("<p>" + msg + "</p>")); for(let overlay of overlays) { let imgSrc = ra(overlay.code); let img = $("<img class=material-preview src='" + imgSrc + "' width=" + width + " height=" + height + ">"); // img.width = width; // img.height = height; $(overlayExtension).append(img); } $(overlayExtension).show(); } else { $(overlayExtension).hide(); } }); $(".game-field-zone").on("mouseout", function (ev) { $(overlayExtension).hide(); }); }; waitForElementJQuery("#game-room-container:visible, #game-field:visible").then(() => { onload(); }); // on-load stuff