Skip to content

Instantly share code, notes, and snippets.

@huzpsb
Created September 29, 2024 10:31
Show Gist options
  • Save huzpsb/607e1f7751d66f6168ec99c328236826 to your computer and use it in GitHub Desktop.
Save huzpsb/607e1f7751d66f6168ec99c328236826 to your computer and use it in GitHub Desktop.
awMazing
// ==UserScript==
// @name AwMazing
// @description Aw's script for BC map mode
// @version Full_0
// @namespace awaqwq_awmazing
// @match *://*/*BondageClub*
// @grant GM_registerMenuCommand
// ==/UserScript==
(function () {
// == Engine of the world ==
// Passable tiles
const matFloorWood = 100
const matFloorStone = 110
const matFloorGravel = 230
const matFloorStoneBrick = 115
const matFloorConcreteBlack = 235
const matFloorConcreteWhite = 240
const matFloorConcreteGrey = 250
const matFloorPadModern = 120
const matFloorPadTraditional = 140
const matFloorSandRed = 130
const matFloorSandYellow = 220
const matFloorSandBlue = 131
const matFloorSandBrown = 132
const matFloorGrassWilted = 200
const matFloorGrassNormal = 210
const matFloorGrassLush = 230
// Impassable tiles
const matWallBrickWood = 1000
const matWallBrickStone = 1030
const matWallPlankRed = 1040
const matWallPlankBrown = 1001
const matWallPlankYellow = 1010
const matWallPlankStone = 1050
const matWallSmoothPaper = 1020
const matWallSmoothPink = 1060
const matWallSmoothWhite = 1070
const matWallPad = 1080
// Water tiles
const matWaterNormal = 2000
const matWaterClear = 2010
const matWaterDeep = 2020
const matWaterGreen = 2025
awSetBlock = function (X, Y, Value) {
if (X < 0 || X >= ChatRoomMapViewHeight || Y < 0 || Y >= ChatRoomMapViewWidth) {
return
}
const pos = X + Y * ChatRoomMapViewWidth
ChatRoomData.MapData.Tiles = ChatRoomData.MapData.Tiles.substring(0, pos) + String.fromCharCode(Value) + ChatRoomData.MapData.Tiles.substring(pos + 1);
ChatRoomMapViewUpdateFlag()
}
// Entities
const entityNone = 100
// Normal Doors
const entityDoorWoodOpen = 4010
const entityDoorWoodNormal = 4011
const entityDoorSteelNormal = 4020
// Lockable Doors & Keys
const entityDoorWoodOwner = 4012
const entityDoorWoodBronze = 4013
const entityDoorWoodSilver = 4014
const entityDoorWoodGolden = 4015
const entityKeyBronze = 160
const entityKeySilver = 162
const entityKeyGolden = 164
const entityDoorSteelUp = 4021
const entityDoorSteelDown = 4022
// Entrance & Exit
const entityEntrance = 110
const entityExit = 115
// Accessories
const entityBed = 120
const entityPillow = 130
const entityDesk = 140
const entityChairSimple = 151
const entityChairFancy = 150
const entityComputer = 210
const entitySeatWithDesk = 220
const entityCookingTable = 250
const entityWashingMachine = 260
const entityLaundryDesk = 270
const entityLaundryShelf = 300
const entityChairLow = 310
const entityBonsai = 320
const entityFridge = 350
// Accessories - Wedding on beach (Activity #1)
const entityWeddingBalloonColorful = 510
const entityWeddingBalloonRed = 511
const entityWeddingCake = 520
const entityWeddingDoor = 521
const entityWeddingBonsai = 530
const entityWeddingUmbrella = 560
const entityWeddingBed = 570
// Accessories - Camping in the woods (Activity #2)
const entityCampFire = 610
const entityCampSeatLog = 620
const entityCampSeatFoldable = 650
const entityCampTent = 630
const entityCampSleepingBag = 640
const entityCampBlockOne = 660
const entityCampBlockTwo = 670
const entityCampBlockThree = 680
// Accessories - R18
const entityR18Cage = 1010
const entityR18XCross = 1020
const entityR18Bed = 1030
const entityR18Chair = 1040
const entityR18LockerIron = 1050
const entityR18LockerWood = 1060
const entityR18Coffin = 1070
const entityR18BodyShowcase = 1080
awR18AutoApply = function (p, e) {
switch (e) {
default:
return false
case entityR18Cage:
InventoryWear(p, 'LeatherArmbinder', 'ItemArms', '#202020', 114514)
InventoryWear(p, 'Kennel', 'ItemDevices', null, 114514)
p.Appearance.forEach(i => {
if (i.Asset.Name === 'Kennel') {
i.Property.TypeRecord.d = 1
}
})
ChatRoomCharacterUpdate(p)
return true
case entityR18XCross:
InventoryWear(p, 'X-Cross', 'ItemDevices', null, 114514)
ChatRoomCharacterUpdate(p)
return true
case entityR18Bed:
InventoryWear(p, 'BondageBench', 'ItemDevices', null, 114514)
p.Appearance.forEach(i => {
if (i.Asset.Name === 'BondageBench') {
i.Property.TypeRecord.typed = 4
}
})
ChatRoomCharacterUpdate(p)
return true
case entityR18Chair:
InventoryWear(p, 'LeatherArmbinder', 'ItemArms', '#202020', 114514)
InventoryWear(p, 'Trolley', 'ItemDevices', null, 114514)
p.Appearance.forEach(i => {
if (i.Asset.Name === 'Trolley') {
i.Property.TypeRecord.typed = 1
}
})
ChatRoomCharacterUpdate(p)
return true
case entityR18LockerIron:
InventoryWear(p, 'LeatherArmbinder', 'ItemArms', '#202020', 114514)
InventoryWear(p, 'Locker', 'ItemDevices', null, 114514)
p.Appearance.forEach(i => {
if (i.Asset.Name === 'Locker') {
i.Property.TypeRecord.typed = 1
i.Property.Opacity = 1
}
})
ChatRoomCharacterUpdate(p)
return true
case entityR18LockerWood:
InventoryWear(p, 'LeatherArmbinder', 'ItemArms', '#202020', 114514)
InventoryWear(p, 'WoodenBox', 'ItemDevices', null, 114514)
p.Appearance.forEach(i => {
if (i.Asset.Name === 'WoodenBox') {
i.Property.Opacity = 1
}
})
ChatRoomCharacterUpdate(p)
return true
case entityR18Coffin:
InventoryWear(p, 'LeatherArmbinder', 'ItemArms', '#202020', 114514)
InventoryWear(p, 'Coffin', 'ItemDevices', null, 114514)
p.Appearance.forEach(i => {
if (i.Asset.Name === 'Coffin') {
i.Property.TypeRecord.typed = 1
}
})
ChatRoomCharacterUpdate(p)
return true
case entityR18BodyShowcase:
InventoryWear(p, 'TheDisplayFrame', 'ItemDevices', null, 114514)
ChatRoomCharacterUpdate(p)
return true
}
}
// Accessories Impassable
const entityImpassableStone = 2005
const entityImpassableCarvedStone = 2010
const entityImpassableWineRack = 2020
const entityImpassableBars = 2030
const entityImpassableRailings = 2031
const entityImpassableTreeNormal = 2040
const entityImpassableTreePine = 2050
const entityImpassableTreeCoconut = 2055
const entityImpassableTreeXmas = 2060
const entityImpassableGlass = 2070
// Accessories On-wall
const entityOnWallPainting = 3010
const entityOnWallMirror = 3020
const entityOnWallLight = 3030
const entityOnWallWhip = 3040
const entityOnWallFurnace = 3050
const entityOnWallShield = 3100
const entityOnWallSword = 3110
const entityOnWallBlackboard = 3200
const entityOnWallFirstAid = 3250
const entityOnWallE = 3260
awSetEntity = function (X, Y, Value) {
if (X < 0 || X >= ChatRoomMapViewHeight || Y < 0 || Y >= ChatRoomMapViewWidth) {
return
}
const pos = X + Y * ChatRoomMapViewWidth
ChatRoomData.MapData.Objects = ChatRoomData.MapData.Objects.substring(0, pos) + String.fromCharCode(Value) + ChatRoomData.MapData.Objects.substring(pos + 1);
ChatRoomMapViewUpdateFlag()
}
// Room-related constants
const xDefaultSpawn = 20
const yDefaultSpawn = 20
const xMaxRoomSize = 40
const yMaxRoomSize = 40
awClearRoom = function () {
for (let X = 0; X < ChatRoomMapViewHeight; X++) {
for (let Y = 0; Y < ChatRoomMapViewWidth; Y++) {
let mat = (X % 5 === 2 && Y % 5 === 2) ? matFloorGravel : matFloorWood
awSetBlock(X, Y, mat)
awSetEntity(X, Y, entityNone)
}
}
}
// == Event Handler ==
EmitMapMoveEvent = null
EmitMapMoveEvent0 = function (e) {
for (let C of ChatRoomCharacter) {
if (C.MemberNumber === e.player) {
e.playerObj = C
break
}
}
if (EmitMapMoveEvent !== null) {
EmitMapMoveEvent(e)
} else {
if (e.isSelf) {
console.log(e)
}
}
}
ChatRoomMapViewSyncMapData0 = ChatRoomMapViewSyncMapData
ChatRoomMapViewSyncMapData = function (d) {
ChatRoomMapViewSyncMapData0(d)
let dPlayer = d.MemberNumber
let dPosX = d.MapData.X
let dPosY = d.MapData.Y
let dDestMat = ChatRoomData.MapData.Tiles.charCodeAt(dPosX + dPosY * ChatRoomMapViewWidth)
let dObj = ChatRoomData.MapData.Objects.charCodeAt(dPosX + dPosY * ChatRoomMapViewWidth)
let moveEvent = {
player: dPlayer,
posX: dPosX,
posY: dPosY,
destMat: dDestMat,
destObj: dObj,
isSelf: false
}
EmitMapMoveEvent0(moveEvent)
}
oldX = -1
oldY = -1
ChatRoomMapViewUpdatePlayerSync0 = ChatRoomMapViewUpdatePlayerSync
ChatRoomMapViewUpdatePlayerSync = function () {
let newX = Player.MapData.Pos.X
let newY = Player.MapData.Pos.Y
ChatRoomMapViewUpdatePlayerSync0()
if (oldX !== newX || oldY !== newY) {
oldX = newX
oldY = newY
let newMat = ChatRoomData.MapData.Tiles.charCodeAt(newX + newY * ChatRoomMapViewWidth)
let newObj = ChatRoomData.MapData.Objects.charCodeAt(newX + newY * ChatRoomMapViewWidth)
let moveEvent = {
player: Player.MemberNumber,
posX: newX,
posY: newY,
destMat: newMat,
destObj: newObj,
isSelf: true
}
EmitMapMoveEvent0(moveEvent)
}
}
// == World Gen ==
let RandomChoice = function (choices) {
return choices[Math.floor(Math.random() * choices.length)];
}
let RandomInt = function (min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
let RandomR18Ent = function () {
const R18e = [
entityR18Cage,
entityR18XCross,
entityR18Bed,
entityR18Chair,
entityR18LockerIron,
entityR18LockerWood,
entityR18Coffin,
entityR18BodyShowcase
]
return RandomChoice(R18e)
}
let RandomIndoorAccPack = function () {
const accPack = [
[entityBed, entityPillow, entityChairSimple, entityDesk], // Bedroom
[entityDesk, entityChairFancy, entityBonsai], // Office
[entityComputer, entitySeatWithDesk, entityChairLow], // Computer Room
[entityCookingTable, entityFridge, entityChairLow], // Kitchen
[entityWashingMachine, entityLaundryDesk, entityLaundryShelf], // Laundry
[entityWeddingBalloonColorful, entityWeddingBalloonRed, entityWeddingCake, entityWeddingDoor, entityWeddingBonsai, entityWeddingUmbrella, entityWeddingBed], // Wedding
]
return RandomChoice(accPack)
}
let RandomOutdoorAccPack = function () {
return [entityCampFire, entityCampSeatLog, entityCampSeatFoldable, entityCampTent, entityCampSleepingBag, entityCampBlockOne, entityCampBlockTwo, entityCampBlockThree]
}
let RandomIndoorBackPack = function () {
const backPack = [
{
ground: [matFloorPadModern, matFloorPadTraditional], wall: [matWallPad]
},
{
ground: [matFloorSandRed, matFloorSandYellow, matFloorSandBlue, matFloorSandBrown],
wall: [matWallBrickWood, matWallBrickStone]
},
{
ground: [matFloorConcreteBlack, matFloorConcreteWhite, matFloorConcreteGrey],
wall: [matWallSmoothPaper, matWallSmoothPink, matWallSmoothWhite]
},
{
ground: [matFloorStone, matFloorStoneBrick],
wall: [matWallPlankRed, matWallPlankBrown, matWallPlankYellow, matWallPlankStone]
}
]
const randomPack = RandomChoice(backPack)
return {
ground: RandomChoice(randomPack.ground),
wall: RandomChoice(randomPack.wall)
}
}
let RandomOutdoorBackPack = function () {
const randomPack = {
ground: [matFloorGrassWilted, matFloorGrassNormal, matFloorGrassLush],
wall: [matWallBrickStone, matWallBrickWood]
}
return {
ground: RandomChoice(randomPack.ground),
wall: RandomChoice(randomPack.wall)
}
}
let RandomWaterPack = function () {
return [matWaterNormal, matWaterClear, matWaterDeep, matWaterGreen]
}
let RandomOnWall = function () {
const ow = [entityOnWallPainting, entityOnWallMirror, entityOnWallLight, entityOnWallWhip, entityOnWallFurnace, entityOnWallShield, entityOnWallSword, entityOnWallBlackboard, entityOnWallFirstAid, entityOnWallE]
return RandomChoice(ow)
}
let RandomDoor = function () {
const door = [entityDoorWoodOpen, entityDoorWoodNormal, entityDoorSteelNormal]
return RandomChoice(door)
}
let RandomPackWithAcc = function () {
if (Math.random() > 0.3) {
const pack = RandomIndoorBackPack()
const accPack = RandomIndoorAccPack()
return {
pack: pack,
acc: accPack,
indoor: true
}
} else {
const pack = RandomOutdoorBackPack()
const accPack = RandomOutdoorAccPack()
return {
pack: pack,
acc: accPack,
indoor: false
}
}
}
let populateRoom = function (xf, yf, xt, yt) {
const pair = RandomPackWithAcc()
const pack = pair.pack
const accPack = pair.acc
for (let x = xf; x <= xt; x++) {
awSetBlock(x, yf, pack.wall)
}
let doorX = RandomInt(xf, xt)
if (yf === 0) {
doorX = -1
}
for (let x = xf; x <= xt; x++) {
if (x === doorX) {
awSetEntity(x, yf, RandomDoor())
} else {
if (Math.random() > 0.7) {
awSetEntity(x, yf, RandomOnWall())
}
}
}
for (let x = xf; x <= xt; x++) {
for (let y = yf + 1; y <= yt; y++) {
awSetBlock(x, y, pack.ground)
}
}
const accCount = RandomInt(15, 30)
for (let i = 0; i < accCount; i++) {
const acc = RandomChoice(accPack)
const ax = RandomInt(xf, xt)
const ay = RandomInt(yf + 1, yt)
awSetEntity(ax, ay, acc)
}
const accR18Count = RandomInt(5, 10)
for (let i = 0; i < accR18Count; i++) {
const ax = RandomInt(xf, xt)
const ay = RandomInt(yf + 2, yt - 1)
awSetEntity(ax, ay, RandomR18Ent())
}
if (!pair.indoor) {
const water = RandomChoice(RandomWaterPack())
const waterCenterX = RandomInt(xf + 1, xt - 1)
const waterCenterY = RandomInt(yf + 1, yt - 1)
for (let x = xf + 1; x <= xt - 1; x++) {
for (let y = yf + 1; y <= yt - 1; y++) {
const huffmanDist = Math.abs(x - waterCenterX) + Math.abs(y - waterCenterY) + Math.floor(Math.random() * 3)
if (huffmanDist < 6) {
awSetBlock(x, y, water)
}
}
}
}
}
let chatSend = function (m) {
ServerSend('ChatRoomChat', {
Content: m,
Type: 'Chat',
})
}
let doPopulate = function () {
chatSend("( Attention, please! The map is refreshing...")
awClearRoom()
let pDiv = [0, 13, 26, 39]
const wallMat = RandomIndoorBackPack().wall
for (let x = 1; x <= 2; x++) {
for (let y = 0; y <= 38; y++) {
awSetBlock(pDiv[x], y, wallMat)
}
}
for (let xIdx = 0; xIdx <= 2; xIdx++) {
for (let yIdx = 0; yIdx <= 2; yIdx++) {
let xF = pDiv[xIdx]
xF = (xF === 0) ? 0 : xF + 1;
let xT = pDiv[xIdx + 1]
xT = (xT === 39) ? 39 : xT - 1;
console.log(xF, pDiv[yIdx], xT, pDiv[yIdx + 1])
populateRoom(xF, pDiv[yIdx], xT, pDiv[yIdx + 1])
}
}
}
GM_registerMenuCommand('Map_export', () => {
const dict = {};
dict.mp = ChatRoomData.MapData.Tiles;
dict.cr = ChatRoomData.MapData.Objects;
ChatRoomSendLocal('AwMazing> Done! To import, press F12 and paste the following code.\n' +
'let encodedDict = "' +
btoa(encodeURI(JSON.stringify(dict))) +
'";fetch(\'https://huzpsb.github.io/roomimport.js?\' + new Date().getTime()).then(response => response.text()).then(code => {eval(code);}).catch(error => console.error(error));'
)
}
);
GM_registerMenuCommand('Map_generate (Random RP)', () => {
doPopulate();
}
);
GM_registerMenuCommand('Bot_toggle', () => {
if (EmitMapMoveEvent) {
EmitMapMoveEvent = null;
ChatRoomSendLocal('[DEBUG] Bot is now off.')
} else {
EmitMapMoveEvent = function (e) {
if (awR18AutoApply(e.playerObj, e.destObj)) {
ChatRoomSendLocal('[DEBUG] ' + e.playerObj.Name + ' triggered the trap!')
}
}
ChatRoomSendLocal('[DEBUG] Bot is now on.')
}
});
}
)();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment