diff --git a/mbchc-local.user.js b/mbchc-local.user.js index 0f9e24b..36f6f67 100644 --- a/mbchc-local.user.js +++ b/mbchc-local.user.js @@ -39,6 +39,8 @@ var bcModSdk=function(){"use strict";const o="1.0.2";function e(o){alert("Mod ER RE_ALL_LEFT: /^<+$/, RE_ALL_RIGHT: /^>+$/, RE_CARET: /^\^/, + RE_SPACES: /\s{2,}/g, + RE_LAST_WORD: /(^|\s)([^\s]*)$/, RGB_MUTE: "#6c2132", RGB_POLLY: "#81b1e7", UTC_OFFSET: new Date().getTimezoneOffset() * 60 * 1000, @@ -128,7 +130,7 @@ var bcModSdk=function(){"use strict";const o="1.0.2";function e(o){alert("Mod ER "polish": {"Hands,Boots": {all: "TakeCare"}}, "foot": {"Head,Nose": {others: "Step"}, "Torso,Boots": {others: "MassageFeet"}, "Vulva,VulvaPiercings": {others: "MasturbateFoot"}}, "fist": {"Vulva,Butt": {all: "MasturbateFist"}}, - "fuck": {"Mouth,Vulva,Butt": {others: "PenetrateSlow"}}, + "fuck": {"Mouth,Vulva,Butt": {others: "PenetrateSlow"}}, //peg? "pound": {"Mouth,Vulva,Butt": {others: "PenetrateFast"}}, "tongue": {"Vulva,VulvaPiercings": {others: "MasturbateTongue"}}, "finger": {"Breast,Butt,Vulva,VulvaPiercings": {all: "MasturbateHand"}}, @@ -152,11 +154,6 @@ var bcModSdk=function(){"use strict";const o="1.0.2";function e(o){alert("Mod ER "ItemEars": ["ear", "ears", "earlobe", "earlobes"], "ItemHead": ["head", "face", "hair", "eyes", "forehead"], }, - COMMANDS: [ - { Tag: "mbchc", Description: ": Utility functions (\"/mbchc\" for help)", Action: (argline, cmdline, args) => window.MBCHC.command_mbchc(argline, cmdline, args) }, - { Tag: "activity", Description: "[Message]: Send a custom activity (or \"@@Message\", or \"@Message\" as yourself)", Action: (argline, cmdline, args) => window.MBCHC.command_activity(argline, cmdline, args) }, - { Tag: "do", Description: ": Do an activity, as if clicked on its button (\"/do\" for help)", Action: (argline, cmdline, args) => window.MBCHC.command_do(argline, cmdline, args) }, - ], SUBCOMMANDS_MBCHC: { "versions": {desc: "show the mod versions across the room", cb: mbchc => mbchc.inform(mbchc.gather_versions().map(c => `
${c.name} (${c.cid}): ${c.version}
`).join(""))}, "autohack": {desc: "toggle the autohack feature", cb: mbchc => mbchc.inform(`Autohack is now ${(mbchc.AUTOHACK_ENABLED = !mbchc.AUTOHACK_ENABLED) ? "enabled" : "disabled"}`)}, @@ -214,7 +211,7 @@ var bcModSdk=function(){"use strict";const o="1.0.2";function e(o){alert("Mod ER return(result) }, bg_colour: function() { return(document.getElementById("TextAreaChatLog").dataset.colortheme.startsWith("light") ? this.RGB_POLLY : this.RGB_MUTE) }, - inform: function(html) { window.ChatRoomSendLocal(`
${html}
`, 60000) }, + inform: function(html, timeout = 60000) { window.ChatRoomSendLocal(`
${html}
`, timeout) }, report: function(x) { this.inform(`Error: ${x.toString()}`) if (this.RETHROW) throw x @@ -383,38 +380,70 @@ var bcModSdk=function(){"use strict";const o="1.0.2";function e(o){alert("Mod ER if (!char.MBCHC_LOCAL) char.MBCHC_LOCAL = {} if (!char.MBCHC_LOCAL.TZ) char.MBCHC_LOCAL.TZ = this.find_timezone(char) }, - command_mbchc: function(argline, cmdline, args) { try { - if (args.length < 1) return(this.inform(Object.entries(this.SUBCOMMANDS_MBCHC).map(([cmd, sub]) => `
/mbchc ${cmd} ${sub.args ? Object.keys(sub.args).join(" ") : ""}: ${sub.desc}
`).join(""))) + command_mbchc: function(argline, cmdline, args) { const mbchc = window.MBCHC; try { // `this` is command object + if (args.length < 1) return(mbchc.inform(Object.entries(mbchc.SUBCOMMANDS_MBCHC).map(([cmd, sub]) => `
/mbchc ${cmd} ${sub.args ? Object.keys(sub.args).join(" ") : ""}: ${sub.desc}
`).join(""))) let cmd = String(args.shift()) - let sub = this.ensure(`unknown subcommand "${cmd}"`, () => this.SUBCOMMANDS_MBCHC[cmd]) - sub.cb.call(this, this, args, argline, cmdline) - } catch (x) { this.report(x) } }, - command_activity: function(argline, cmdline, args) { if (!this.empty(argline)) { try { - let message = this.normalise_message(cmdline.replace(this.RE_ACTIVITY, ''), {trim: true, dot: true, up: true}) - this.send_activity(message) - } catch (x) { this.report(x) } } }, - command_do: function(argline, cmdline, args) { try { - if (args.length < 1) return(this.inform("
Usage: /do VERB [ZONE] [TARGET]
Available verbs:
" + Object.keys(this.MAP_ACTIONS).join(", ") + "
Available zones:
" + Object.keys(this.DO_DATA.zones).join(", "))) + let sub = mbchc.ensure(`unknown subcommand "${cmd}"`, () => mbchc.SUBCOMMANDS_MBCHC[cmd]) + sub.cb.call(mbchc, mbchc, args, argline, cmdline) + } catch (x) { mbchc.report(x) } }, + command_activity: function(argline, cmdline, args) { const mbchc = window.MBCHC; if (!mbchc.empty(argline)) { try { // `this` is command object + let message = mbchc.normalise_message(cmdline.replace(mbchc.RE_ACTIVITY, ''), {trim: true, dot: true, up: true}) + mbchc.send_activity(message) + } catch (x) { mbchc.report(x) } } }, + command_do: function(argline, cmdline, args) { const mbchc = window.MBCHC; try { // `this` is command object + if (args.length < 1) return(mbchc.inform("
Usage: /do VERB [ZONE] [TARGET]
Available verbs:
" + Object.keys(mbchc.MAP_ACTIONS).join(", ") + "
Available zones:
" + Object.keys(mbchc.DO_DATA.zones).join(", "))) let [verb, zone, target] = args - if (!this.DO_DATA.verbs[verb]) throw `unknown verb "${verb}"` - let zones = this.DO_DATA.verbs[verb] + let zones = mbchc.ensure(`unknown verb "${verb}"`, () => mbchc.DO_DATA.verbs[verb]) if (1 === Object.keys(zones).length) { if (!target) target = zone - zone = this.MAP_ZONES[Object.keys(zones)[0]][0] + zone = mbchc.MAP_ZONES[Object.keys(zones)[0]][0] } if (!zone) throw "zone missing" - let ag = this.ensure(`unknown zone "${zone}"`, () => this.DO_DATA.zones[zone]) - let types = this.ensure(`zone "${zone}" invalid for "${verb}"`, () => zones[ag]) + let ag = mbchc.ensure(`unknown zone "${zone}"`, () => mbchc.DO_DATA.zones[zone]) + let types = mbchc.ensure(`zone "${zone}" invalid for "${verb}"`, () => zones[ag]) let char = window.Player - if (target && ((types.self.length < 1) || (types.others.length > 0))) char = this.target2char(target) + if (target && ((types.self.length < 1) || (types.others.length > 0))) char = mbchc.target2char(target) let type = char.IsPlayer() ? "self" : "others" let available = window.ActivityAllowedForGroup(char, ag) let toy = window.InventoryGet(window.Player, "ItemHands") if (toy && toy.Asset.Name === "SpankingToys") available.push(window.AssetAllActivities(char.AssetFamily).find(a => a.Name === window.InventorySpankingToysGetActivity(window.Player))) - let actions = this.ensure(`zone "${zone}" invalid for ("${verb}" "${type}")`, () => types[type]) - let action = this.ensure(`invalid action (${verb} ${zone} ${target})`, () => actions.find(name => available.find(a => a.Name === name))) - this.run_activity(char, ag, action) - } catch (x) { this.report(x) } }, + let actions = mbchc.ensure(`zone "${zone}" invalid for ("${verb}" "${type}")`, () => types[type]) + let action = mbchc.ensure(`invalid action (${verb} ${zone} ${target})`, () => actions.find(name => available.find(a => a.Name === name))) + mbchc.run_activity(char, ag, action) + } catch (x) { mbchc.report(x) } }, + complete_common: function() { + let input = document.getElementById("InputChat").value + return([this, input, input.replace(this.RE_SPACES, " ").split(" ")]) + }, + complete: function(options) { + const chat = document.getElementById("InputChat") + if (options.length < 1) { + // TODO: maybe signal no valid options? + return + } + if (options.length > 1) { + // TODO + // autocomplete to common prefix + // better hint: hide on input + // better hint: increase density + this.inform(options.sort().map(s => `
${s}
`).join(""), 10000) + } else { + window.ElementValue("InputChat", chat.value.replace(this.RE_LAST_WORD, `$1${options[0]} `)) + window.ElementFocus("InputChat") + } + }, + complete_mbchc: function(args, locase, cmdline) { const [mbchc, input, tokens] = window.MBCHC.complete_common(); // `this` is command object +//console.debug([input, tokens]) + if (tokens.length < 1) return + if (tokens.length < 2) mbchc.complete([`${mbchc.CommandsKey}${this.Tag}`]) + if (tokens.length < 3) mbchc.complete(Object.keys(mbchc.SUBCOMMANDS_MBCHC).filter(c => c.startsWith(tokens[1]))) // complete subcommand name + }, + complete_do: function(args, locase, cmdline) { const [mbchc, input, tokens] = window.MBCHC.complete_common(); // `this` is command object +//console.debug([input, tokens]) + if (tokens.length < 1) return + if (tokens.length < 2) mbchc.complete([`${mbchc.CommandsKey}${this.Tag}`]) + if (tokens.length < 3) mbchc.complete(Object.keys(mbchc.DO_DATA.verbs).filter(c => c.startsWith(tokens[1]))) // complete verb + }, loader: function() { if (this.remove_load_hook) { this.remove_load_hook() @@ -422,6 +451,11 @@ var bcModSdk=function(){"use strict";const o="1.0.2";function e(o){alert("Mod ER } if (this.LOADED) return // Calculated values + const COMMANDS = [ + { Tag: "mbchc", Description: ": Utility functions (\"/mbchc\" for help)", Action: this.command_mbchc, AutoComplete: this.complete_mbchc }, + { Tag: "activity", Description: "[Message]: Send a custom activity (or \"@@Message\", or \"@Message\" as yourself)", Action: this.command_activity }, + { Tag: "do", Description: ": Do an activity, as if clicked on its button (\"/do\" for help)", Action: this.command_do, AutoComplete: this.complete_do }, + ] this.HIDE_ALL = this.HIDE_SPECIAL.concat(this.HIDE_BODY).concat(this.HIDE_CLOTHES).concat(this.HIDE_ITEMS) this.CommandsKey = CommandsKey /* eslint-disable-line no-undef */ // window.CommandsKey is undefined this.RE_ACTIVITY = RegExp(`^${this.CommandsKey}activity `) @@ -430,7 +464,7 @@ var bcModSdk=function(){"use strict";const o="1.0.2";function e(o){alert("Mod ER this.calculate_maps() this.patch_handheld() window.Player.MBCHC = {VERSION: this.VERSION} - window.CommandCombine(this.COMMANDS) + window.CommandCombine(COMMANDS) this.LOADED = true console.info(this.log(`loaded version ${this.VERSION}`)) } @@ -438,13 +472,13 @@ var bcModSdk=function(){"use strict";const o="1.0.2";function e(o){alert("Mod ER // Hooks window.MBCHC.sdk = window.bcModSdk.registerMod("MBCHC", window.MBCHC.VERSION) - window.MBCHC.sdk.hookFunction("CharacterOnlineRefresh", 0, (args, next) => { - let result = next(args) - window.MBCHC.update_char(args[0]) + window.MBCHC.sdk.hookFunction("CharacterOnlineRefresh", 0, (nextargs, next) => { + let result = next(nextargs) + window.MBCHC.update_char(nextargs[0]) return(result) }) - window.MBCHC.sdk.hookFunction("ChatRoomMessageInvolvesPlayer", 0, (args, next) => { - let data = args[0] + window.MBCHC.sdk.hookFunction("ChatRoomMessageInvolvesPlayer", 0, (nextargs, next) => { + let data = nextargs[0] if (!data.MBCHC_ID) { data.MBCHC_ID = window.MBCHC.NEXT_MESSAGE window.MBCHC.NEXT_MESSAGE += 1 @@ -453,10 +487,10 @@ var bcModSdk=function(){"use strict";const o="1.0.2";function e(o){alert("Mod ER if (("ServerEnter" === data.Content) && ("Action" === data.Type) && (data.Sender === window.Player.cid)) { window.MBCHC.player_enters_room() } if (("MBCHC" === data.Content) && ("Hidden" === data.Type)) { window.MBCHC.receive(data) } } - return(next(args)) + return(next(nextargs)) }) - window.MBCHC.sdk.hookFunction("ChatRoomReceiveSuitcaseMoney", 0, (args, next) => { - let result = next(args) + window.MBCHC.sdk.hookFunction("ChatRoomReceiveSuitcaseMoney", 0, (nextargs, next) => { + let result = next(nextargs) if (window.MBCHC.AUTOHACK_ENABLED && window.MBCHC.LAST_HACKED) { window.CurrentCharacter = window.MBCHC.cid2char(window.MBCHC.LAST_HACKED) window.MBCHC.LAST_HACKED = null @@ -464,17 +498,17 @@ var bcModSdk=function(){"use strict";const o="1.0.2";function e(o){alert("Mod ER } return(result) }) - window.MBCHC.sdk.hookFunction("ChatRoomSendChat", 0, (args, next) => { + window.MBCHC.sdk.hookFunction("ChatRoomSendChat", 0, (nextargs, next) => { let input = window.ElementValue("InputChat") if (!input.startsWith("@@@")) { input = input.replace(window.MBCHC.RE_PREF_ACTIVITY, window.MBCHC.PREF_ACTIVITY) input = input.replace(window.MBCHC.RE_PREF_ACTIVITY_ME, `${window.MBCHC.PREF_ACTIVITY}<${window.Player.cid}:>SourceCharacter `) } window.ElementValue("InputChat", input) - return(next(args)) + return(next(nextargs)) }) - window.MBCHC.sdk.hookFunction("ChatRoomDrawCharacterOverlay", 0, (args, next) => { - let [C, CharX, CharY, Zoom, Pos] = args + window.MBCHC.sdk.hookFunction("ChatRoomDrawCharacterOverlay", 0, (nextargs, next) => { + let [C, CharX, CharY, Zoom, Pos] = nextargs if ((window.ChatRoomHideIconState < 1) && C.MBCHC) { let colour = (C.MBCHC.VERSION === window.Player.MBCHC.VERSION) ? window.MBCHC.RGB_POLLY : window.MBCHC.RGB_MUTE window.DrawRect(CharX + 175 * Zoom, CharY, 50 * Zoom, 50 * Zoom, colour) @@ -484,25 +518,22 @@ var bcModSdk=function(){"use strict";const o="1.0.2";function e(o){alert("Mod ER let text = localtime.toLocaleTimeString([], {hourCycle: "h24", hour: "2-digit"}) window.DrawTextFit(text, CharX + 200 * Zoom, CharY + 25 * Zoom, 46 * Zoom, "white", "black") } - return(next(args)) + return(next(nextargs)) }) - window.MBCHC.sdk.hookFunction("CommandAutoComplete", 0, (args, next) => { - return(next(args)) - }) - window.MBCHC.sdk.hookFunction("ElementCreateInput", 0, (args, next) => { - let [ID, Type, Value, MaxLength] = args - let result = next(args) + window.MBCHC.sdk.hookFunction("ElementCreateInput", 0, (nextargs, next) => { + let [ID, Type, Value, MaxLength] = nextargs + let result = next(nextargs) if (("bce_LayerPriority" === ID) && window.CurrentCharacter && window.CurrentCharacter.FocusGroup && window.InventoryLocked(window.CurrentCharacter, window.CurrentCharacter.FocusGroup.Name, true)) window.ElementSetAttribute(ID, "disabled", true) return(result) }) - window.MBCHC.remove_bce_hook = window.MBCHC.sdk.hookFunction("MainRun", 0, (args, next) => { + window.MBCHC.remove_bce_hook = window.MBCHC.sdk.hookFunction("MainRun", 0, (nextargs, next) => { if (window.bce_ActivityTriggers) window.MBCHC.patch_bce() - return(next(args)) + return(next(nextargs)) }) // MAIN SCREEN TURN ON if (window.MBCHC.need_load_hook(window.CurrentModule, window.CurrentScreen)) { - window.MBCHC.remove_load_hook = window.MBCHC.sdk.hookFunction("AsylumGGTSSAddItems", 0, (args, next) => {window.MBCHC.loader(); return(next(args))}) + window.MBCHC.remove_load_hook = window.MBCHC.sdk.hookFunction("AsylumGGTSSAddItems", 0, (nextargs, next) => {window.MBCHC.loader(); return(next(nextargs))}) } else { window.MBCHC.loader() if (("Online" === window.CurrentModule) && ("ChatRoom" === window.CurrentScreen)) {