mirror of
https://gitgud.io/BondageProjects/Bondage-College.git
synced 2026-04-28 04:19:50 +00:00
3279 lines
119 KiB
JavaScript
3279 lines
119 KiB
JavaScript
// @ts-strict-ignore
|
|
"use strict";
|
|
|
|
// Disable interpolation when scaling, will make texture be pixelated
|
|
PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.LINEAR;
|
|
|
|
let CanvasWidth = 2000;
|
|
let CanvasHeight = 1000;
|
|
let KDStartTime = 0;
|
|
|
|
/** These languages have characters which are rendered bigger than English. */
|
|
let KDBigLanguages = ["CN", "KR", "JP"];
|
|
let KDBigLanguages2 = ["Chinese", "Korean", "Japanese"];
|
|
/** Language List */
|
|
let KDLanguages = ["", "CN", "KR", "JP", "ES"];
|
|
|
|
let KinkyDungeonPlayerNeedsRefresh = false;
|
|
let KinkyDungeonNextRefreshCheck = 0;
|
|
|
|
// Check URL to see if indev branch
|
|
const pp = new URLSearchParams(window.location.search);
|
|
let param_branch = pp.has('branch') ? pp.get('branch') : "";
|
|
let param_test = pp.has('test') ? pp.get('test') : "";
|
|
let param_localhost = pp.has('localhost') ? pp.get('localhost') : "";
|
|
let TestMode = param_test || param_branch || param_localhost || ServerURL == 'https://bc-server-test.herokuapp.com/';
|
|
|
|
let KDDebugMode = false;
|
|
let KDDebug = false;
|
|
let KDDebugPerks = false;
|
|
let KDDebugGold = false;
|
|
|
|
let KDAllModFiles = [];
|
|
let KDModFiles = {};
|
|
|
|
let KinkyDungeonPerksConfig = "1";
|
|
|
|
let KDUnlockedPerks = [];
|
|
|
|
let KinkyDungeonBackground = "BrickWall";
|
|
/**
|
|
* @type {Character}
|
|
*/
|
|
let KinkyDungeonPlayer = null;
|
|
let KinkyDungeonState = "Consent";
|
|
|
|
let KinkyDungeonRep = 0; // Variable to store max level to avoid losing it if the server doesnt take the rep update
|
|
|
|
function KDSetDefaultKeybindings() {
|
|
KinkyDungeonKeybindingsTemp = Object.assign({}, KDDefaultKB);
|
|
}
|
|
|
|
let KinkyDungeonKeybindings = null;
|
|
let KinkyDungeonKeybindingsTemp = null;
|
|
let KinkyDungeonKeybindingCurrentKey = "";
|
|
let KinkyDungeonKeybindingCurrentKeyRelease = "";
|
|
|
|
let KinkyDungeonNewGame = 0;
|
|
|
|
let KinkyDungeonGameRunning = false;
|
|
|
|
let KDLose = false;
|
|
|
|
|
|
let KDLoadingFinished = false;
|
|
let KDLoadingDone = 1;
|
|
let KDLoadingMax = 1;
|
|
|
|
//let KinkyDungeonKeyLower = [87+32, 65+32, 83+32, 68+32, 81+32, 45+32, 90+32, 43+32]; // WASD
|
|
let KinkyDungeonKey = ['KeyW', 'KeyA', 'KeyS', 'KeyD', 'KeyQ', 'KeyE', 'KeyZ', 'KeyC'];
|
|
//let KinkyDungeonKeyNumpad = [56, 52, 50, 54, 55, 57, 49, 51]; // Numpad
|
|
let KinkyDungeonKeySpell = ['Digit1', 'Digit2', 'Digit3', 'Digit4', 'Digit5', 'Digit6', 'Digit7']; // 1 2 3 4 5 6 7
|
|
let KinkyDungeonKeyWait = ['KeyX'];
|
|
let KinkyDungeonKeySkip = ['Space'];
|
|
let KinkyDungeonKeyEnter = ['Enter'];
|
|
let KinkyDungeonKeySprint = ['ShiftLeft'];
|
|
let KinkyDungeonKeyWeapon = ['KeyF'];
|
|
let KinkyDungeonKeyUpcast = ['KeyR', 'ControlLeft'];
|
|
let KinkyDungeonKeyMenu = ['KeyT', 'KeyI', 'KeyG', 'KeyM', 'KeyL']; // QuikInv, Inventory, Reputation, Magic, Log
|
|
let KinkyDungeonKeyToggle = ['Backquote', 'KeyB', 'KeyV', 'KeyN', 'Comma', 'Slash']; // Log, Passing, Door, Auto Struggle, Auto Pathfind
|
|
let KinkyDungeonKeySpellPage = ['Backquote'];
|
|
let KinkyDungeonKeySwitchWeapon = ['ControlRight'];
|
|
|
|
let KDLoadingTextKeys = {};
|
|
|
|
|
|
let KinkyDungeonGraphicsQuality = true;
|
|
|
|
let KDToggles = {
|
|
VibeSounds: true,
|
|
Music: true,
|
|
Sound: true,
|
|
Drool: true,
|
|
DrawArmor: true,
|
|
TurnCounter: true,
|
|
ShowNPCStatuses: true,
|
|
StunFlash: true,
|
|
ArousalHearts: true,
|
|
VibeHearts: true,
|
|
FancyWalls: true,
|
|
};
|
|
|
|
let KDDefaultKB = {
|
|
Down: KinkyDungeonKey[2],
|
|
DownLeft: KinkyDungeonKey[6],
|
|
DownRight: KinkyDungeonKey[7],
|
|
Left: KinkyDungeonKey[1],
|
|
Right: KinkyDungeonKey[3],
|
|
Up: KinkyDungeonKey[0],
|
|
UpLeft: KinkyDungeonKey[4],
|
|
UpRight: KinkyDungeonKey[5],
|
|
|
|
Spell1: KinkyDungeonKeySpell[0],
|
|
Spell2: KinkyDungeonKeySpell[1],
|
|
Spell3: KinkyDungeonKeySpell[2],
|
|
Spell4: KinkyDungeonKeySpell[3],
|
|
Spell5: KinkyDungeonKeySpell[4],
|
|
Spell6: KinkyDungeonKeySpell[5],
|
|
Spell7: KinkyDungeonKeySpell[6],
|
|
SpellWeapon: KinkyDungeonKeyWeapon[0],
|
|
|
|
Wait: KinkyDungeonKeyWait[0],
|
|
Skip: KinkyDungeonKeySkip[0],
|
|
Enter: KinkyDungeonKeyEnter[0],
|
|
Sprint: KinkyDungeonKeySprint[0],
|
|
|
|
SpellPage: KinkyDungeonKeySpellPage[0],
|
|
SwitchWeapon: KinkyDungeonKeySwitchWeapon[0],
|
|
|
|
QInventory: KinkyDungeonKeyMenu[0],
|
|
Inventory: KinkyDungeonKeyMenu[1],
|
|
Reputation: KinkyDungeonKeyMenu[2],
|
|
Magic: KinkyDungeonKeyMenu[3],
|
|
Log: KinkyDungeonKeyMenu[4],
|
|
|
|
Upcast: KinkyDungeonKeyUpcast[0],
|
|
UpcastCancel: KinkyDungeonKeyUpcast[1],
|
|
|
|
MsgLog: KinkyDungeonKeyToggle[0],
|
|
Pass: KinkyDungeonKeyToggle[1],
|
|
Door: KinkyDungeonKeyToggle[2],
|
|
AStruggle: KinkyDungeonKeyToggle[3],
|
|
APathfind: KinkyDungeonKeyToggle[4],
|
|
AInspect: KinkyDungeonKeyToggle[5],
|
|
};
|
|
|
|
let KinkyDungeonRootDirectory = "Screens/MiniGame/KinkyDungeon/";
|
|
/** @type {Character} */
|
|
let KinkyDungeonPlayerCharacter = null; // Other player object
|
|
let KinkyDungeonGameData = null; // Data sent by other player
|
|
let KinkyDungeonGameDataNullTimer = 4000; // If data is null, we query this often
|
|
let KinkyDungeonGameDataNullTimerTime = 0;
|
|
let KinkyDungeonStreamingPlayers = []; // List of players to stream to
|
|
|
|
let KinkyDungeonInitTime = 0;
|
|
|
|
let KinkyDungeonSleepTime = 0;
|
|
let KinkyDungeonFreezeTime = 1000;
|
|
let KinkyDungeonPlaySelfTime = 300;
|
|
let KinkyDungeonOrgasmTime = 1000;
|
|
let KinkyDungeonAutoWait = false;
|
|
let KinkyDungeonAutoWaitStruggle = false;
|
|
|
|
let KinkyDungeonConfigAppearance = false;
|
|
|
|
const Consumable = "consumable";
|
|
const Restraint = "restraint";
|
|
const LooseRestraint = "looserestraint";
|
|
const Outfit = "outfit";
|
|
const Accessory = "accessory";
|
|
const Weapon = "weapon";
|
|
const Misc = "misc";
|
|
|
|
/** @type {Map<string, any>} */
|
|
let KinkyDungeonStatsChoice = new Map();
|
|
|
|
let KDJourney = "";
|
|
|
|
let KDOptOut = false;
|
|
|
|
/**
|
|
* @typedef {{
|
|
* KeysNeeded: boolean,
|
|
* PoolUses: number,
|
|
* PoolUsesGrace: number,
|
|
* JailRemoveRestraintsTimer: number;
|
|
* KinkyDungeonSpawnJailers: number;
|
|
* KinkyDungeonSpawnJailersMax: number;
|
|
* KinkyDungeonLeashedPlayer: number;
|
|
* KinkyDungeonLeashingEnemy: number;
|
|
* KinkyDungeonJailGuard: number;
|
|
* KinkyDungeonGuardTimer: number;
|
|
* KinkyDungeonGuardTimerMax: number;
|
|
* KinkyDungeonGuardSpawnTimer: number;
|
|
* KinkyDungeonGuardSpawnTimerMax: number;
|
|
* KinkyDungeonGuardSpawnTimerMin: number;
|
|
* KinkyDungeonMaxPrisonReduction: number;
|
|
* KinkyDungeonPrisonReduction: number;
|
|
* KinkyDungeonPrisonExtraGhostRep: number;
|
|
* PrisonGoodBehaviorFromLeash: number;
|
|
* KinkyDungeonJailTourTimer: number;
|
|
* KinkyDungeonJailTourTimerMin: number;
|
|
* KinkyDungeonJailTourTimerMax: number;
|
|
* KinkyDungeonPenanceCostCurrent: number;
|
|
* KinkyDungeonAngel: number;
|
|
* KDPenanceStage: number;
|
|
* KDPenanceStageEnd: number;
|
|
* AngelCurrentRep: string;
|
|
* KDPenanceMode: string;
|
|
* OrgasmStage: number;
|
|
* OrgasmTurns: number;
|
|
* OrgasmStamina: number;
|
|
* SleepTurns: number;
|
|
* PlaySelfTurns: number;
|
|
* RescueFlag: boolean;
|
|
* KinkyDungeonPenance: boolean;
|
|
* GuardApplyTime: number;
|
|
* WarningLevel: number;
|
|
* AncientEnergyLevel: number;
|
|
* OrigEnergyLevel: number;
|
|
* LastMP: number;
|
|
* LastAP: number;
|
|
* LastSP: number;
|
|
* LastWP: number;
|
|
* Outfit: string,
|
|
* Champion: string,
|
|
* ChampionCurrent: number,
|
|
* JailPoints: KDJailPoint[],
|
|
* LastMapSeed: string,
|
|
* AlreadyOpened: {x: number, y:number}[],
|
|
* Journey: string,
|
|
* CheckpointIndices: number[],
|
|
* PrisonerState: string,
|
|
* TimesJailed: number,
|
|
* JailTurns: number,
|
|
* JailKey: boolean,
|
|
* CurrentDialog: string,
|
|
* CurrentDialogStage: string,
|
|
* OrgasmNextStageTimer: number,
|
|
* DistractionCooldown: number,
|
|
* ConfirmAttack: boolean,
|
|
* CurrentDialogMsg: string,
|
|
* CurrentDialogMsgSpeaker: string,
|
|
* CurrentDialogMsgPersonality: string,
|
|
* CurrentDialogMsgID: number,
|
|
* CurrentDialogMsgData: Record<string, string>,
|
|
* CurrentDialogMsgValue: Record<string, number>,
|
|
* AlertTimer: number,
|
|
* RespawnQueue: {enemy: string, faction: string}[],
|
|
* HeartTaken: boolean,
|
|
* CurrentVibration: KinkyVibration,
|
|
* Edged: boolean,
|
|
* TimeSinceLastVibeStart: Record<string, number>,
|
|
* TimeSinceLastVibeEnd: Record<string, number>,
|
|
* OfferFatigue: number,
|
|
* Favors: Record<string, number>,
|
|
* RoomType: string,
|
|
* MapMod: string,
|
|
* HunterTimer: number,
|
|
* Hunters: number[],
|
|
* Quests: string[],
|
|
* MapFaction: string,
|
|
* PriorJailbreaks: number,
|
|
* PriorJailbreaksDecay: number,
|
|
* PreviousWeapon: string,
|
|
* StaminaPause: number,
|
|
* StaminaSlow: number,
|
|
* ManaSlow: number,
|
|
* TempFlagFloorTicks: Record<string, number>,
|
|
* KneelTurns: number,
|
|
* HiddenSpellPages : Record<string, boolean>,
|
|
* KeyringLocations : {x: number, y: number}[],
|
|
* HiddenItems : Record<string, boolean>,
|
|
* ItemPriority : Record<string, number>,
|
|
* CagedTime : number,
|
|
* ShopItems: shopItem[],
|
|
* DelayedActions: KDDelayedAction[],
|
|
* JailFaction: string[],
|
|
* GuardFaction: string[],
|
|
* OfferCount: number,
|
|
* MainPath: string,
|
|
* ShortcutPath: string,
|
|
* ItemID: number,
|
|
* ShopkeeperFee: number,
|
|
* DollCount: number,
|
|
* ChestsGenerated: string[],
|
|
* DollRoomCount: number,
|
|
* CollectedHearts: number,
|
|
* CollectedOrbs: number,
|
|
* otherPlaying: number,
|
|
* Training: Record<string, KDTrainingRecord>,
|
|
* QuickLoadout: KDPresetLoadout[],
|
|
|
|
*}} KDGameDataBase
|
|
*/
|
|
let KDGameDataBase = {
|
|
Training: {},
|
|
CollectedOrbs: 0,
|
|
CollectedHearts: 0,
|
|
DollRoomCount: 0,
|
|
ChestsGenerated: [],
|
|
MainPath: 'grv',
|
|
ShortcutPath: 'grv',
|
|
DollCount: 0,
|
|
|
|
CagedTime: 0,
|
|
HiddenItems: {},
|
|
ItemPriority: {},
|
|
KeyringLocations: [],
|
|
HiddenSpellPages: {},
|
|
PriorJailbreaks: 0,
|
|
PriorJailbreaksDecay: 0,
|
|
MapFaction: "",
|
|
KeysNeeded: false,
|
|
RoomType: "",
|
|
MapMod: "",
|
|
|
|
Quests: [],
|
|
|
|
HunterTimer: 0,
|
|
Hunters: [],
|
|
|
|
AlertTimer: 0,
|
|
OrgasmNextStageTimer: 0,
|
|
DistractionCooldown: 0,
|
|
|
|
PoolUses: 0,
|
|
PoolUsesGrace: 3,
|
|
JailRemoveRestraintsTimer: 0,
|
|
KinkyDungeonSpawnJailers: 0,
|
|
KinkyDungeonSpawnJailersMax: 5,
|
|
KinkyDungeonLeashedPlayer: 0,
|
|
KinkyDungeonLeashingEnemy: 0,
|
|
|
|
KinkyDungeonJailGuard: 0,
|
|
KinkyDungeonGuardTimer: 0,
|
|
KinkyDungeonGuardTimerMax: 28,
|
|
KinkyDungeonGuardSpawnTimer: 0,
|
|
KinkyDungeonGuardSpawnTimerMax: 80,
|
|
KinkyDungeonGuardSpawnTimerMin: 50,
|
|
KinkyDungeonMaxPrisonReduction: 10,
|
|
KinkyDungeonPrisonReduction: 0,
|
|
KinkyDungeonPrisonExtraGhostRep: 0,
|
|
PrisonGoodBehaviorFromLeash: 0,
|
|
|
|
KinkyDungeonJailTourTimer: 0,
|
|
KinkyDungeonJailTourTimerMin: 20,
|
|
KinkyDungeonJailTourTimerMax: 40,
|
|
|
|
KinkyDungeonPenanceCostCurrent: 100,
|
|
|
|
KinkyDungeonAngel: 0,
|
|
KDPenanceStage: 0,
|
|
KDPenanceStageEnd: 0,
|
|
AngelCurrentRep: "",
|
|
KDPenanceMode: "",
|
|
|
|
OrgasmStage: 0,
|
|
OrgasmTurns: 0,
|
|
OrgasmStamina: 0,
|
|
|
|
KinkyDungeonPenance: false,
|
|
|
|
RescueFlag: false,
|
|
|
|
SleepTurns: 0,
|
|
PlaySelfTurns: 0,
|
|
GuardApplyTime: 0,
|
|
|
|
AncientEnergyLevel: 0,
|
|
OrigEnergyLevel: 0,
|
|
LastAP: 0,
|
|
LastSP: KDMaxStatStart,
|
|
LastMP: KDMaxStatStart,
|
|
LastWP: KDMaxStatStart,
|
|
|
|
Outfit: "Default",
|
|
|
|
Champion: "",
|
|
ChampionCurrent: 0,
|
|
|
|
JailPoints: [],
|
|
|
|
WarningLevel: 0,
|
|
LastMapSeed: "",
|
|
|
|
AlreadyOpened: [],
|
|
Journey: "",
|
|
CheckpointIndices: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20],
|
|
|
|
TempFlagFloorTicks: {},
|
|
|
|
// "" = not a prisoner
|
|
// "jail" = must remain in cell
|
|
// "parole" = can roam but not allowed to take most actions
|
|
PrisonerState: "",
|
|
TimesJailed: 0,
|
|
JailTurns: 0,
|
|
JailKey: false,
|
|
|
|
CurrentDialog: "",
|
|
CurrentDialogStage: "",
|
|
CurrentDialogMsg: "",
|
|
CurrentDialogMsgSpeaker: "",
|
|
CurrentDialogMsgPersonality: "",
|
|
CurrentDialogMsgData: {},
|
|
CurrentDialogMsgValue: {},
|
|
CurrentDialogMsgID: -1,
|
|
|
|
ConfirmAttack: false,
|
|
RespawnQueue: [],
|
|
HeartTaken: false,
|
|
|
|
CurrentVibration: null,
|
|
Edged: false,
|
|
TimeSinceLastVibeStart: {},
|
|
TimeSinceLastVibeEnd: {},
|
|
|
|
OfferFatigue: 0,
|
|
|
|
Favors: {},
|
|
PreviousWeapon: null,
|
|
QuickLoadout: [],
|
|
|
|
StaminaPause: 0,
|
|
StaminaSlow: 0,
|
|
ManaSlow: 0,
|
|
KneelTurns: 0,
|
|
ShopItems: [],
|
|
DelayedActions: [],
|
|
JailFaction: [],
|
|
GuardFaction: [],
|
|
|
|
OfferCount: 0,
|
|
|
|
ItemID: 0,
|
|
ShopkeeperFee: 0,
|
|
otherPlaying: 0,
|
|
};
|
|
/**
|
|
* @type {KDGameDataBase}
|
|
*/
|
|
let KDGameData = Object.assign({}, KDGameDataBase);
|
|
/*{
|
|
KinkyDungeonSpawnJailers: 0,
|
|
KinkyDungeonSpawnJailersMax: 5,
|
|
KinkyDungeonLeashedPlayer: 0,
|
|
KinkyDungeonLeashingEnemy: 0,
|
|
|
|
KinkyDungeonJailGuard: 0,
|
|
KinkyDungeonGuardTimer: 0,
|
|
KinkyDungeonGuardTimerMax: 22,
|
|
KinkyDungeonGuardSpawnTimer: 0,
|
|
KinkyDungeonGuardSpawnTimerMax: 20,
|
|
KinkyDungeonGuardSpawnTimerMin: 6,
|
|
KinkyDungeonMaxPrisonReduction: 10,
|
|
KinkyDungeonPrisonReduction: 0,
|
|
KinkyDungeonPrisonExtraGhostRep: 0,
|
|
|
|
KinkyDungeonJailTourTimer: 0,
|
|
KinkyDungeonJailTourTimerMin: 20,
|
|
KinkyDungeonJailTourTimerMax: 40,
|
|
|
|
KinkyDungeonPenanceCostCurrent: 100,
|
|
|
|
KinkyDungeonAngel: 0,
|
|
KDPenanceStage: 0,
|
|
KDPenanceStageEnd: 0,
|
|
AngelCurrentRep: "",
|
|
KDPenanceMode: "",
|
|
|
|
KinkyDungeonPenance: false,
|
|
};*/
|
|
|
|
let KDLeashingEnemy = null;
|
|
function KinkyDungeonLeashingEnemy() {
|
|
if (KDGameData.KinkyDungeonLeashingEnemy) {
|
|
if (!KDLeashingEnemy) {
|
|
KDLeashingEnemy = KinkyDungeonFindID(KDGameData.KinkyDungeonLeashingEnemy);
|
|
}
|
|
} else if (!KDIsPlayerTethered(KinkyDungeonPlayerEntity)) {
|
|
KDLeashingEnemy = null;
|
|
}
|
|
return KDLeashingEnemy;
|
|
}
|
|
let KDJailGuard = null;
|
|
|
|
/**
|
|
*
|
|
* @returns {entity}
|
|
*/
|
|
function KinkyDungeonJailGuard() {
|
|
if (KDGameData.KinkyDungeonJailGuard) {
|
|
if (!KDJailGuard) {
|
|
KDJailGuard = KinkyDungeonFindID(KDGameData.KinkyDungeonJailGuard);
|
|
}
|
|
} else {
|
|
KDJailGuard = null;
|
|
}
|
|
return KDJailGuard;
|
|
}
|
|
let KDAngel = null;
|
|
function KinkyDungeonAngel() {
|
|
if (KDGameData.KinkyDungeonAngel) {
|
|
if (!KDAngel) {
|
|
KDAngel = KinkyDungeonFindID(KDGameData.KinkyDungeonAngel);
|
|
}
|
|
} else {
|
|
KDAngel = null;
|
|
}
|
|
return KDAngel;
|
|
}
|
|
|
|
function KDUnlockPerk(Perk) {
|
|
if (Perk && !KDUnlockedPerks.includes(Perk)) KDUnlockedPerks.push(Perk);
|
|
KDLoadPerks();
|
|
localStorage.setItem("KDUnlockedPerks", JSON.stringify(KDUnlockedPerks));
|
|
}
|
|
|
|
function KDLoadPerks() {
|
|
|
|
KDCategories = Object.assign([], KDCategoriesStart);
|
|
for (let c of KDCategories) {
|
|
c.buffs = [];
|
|
c.debuffs = [];
|
|
}
|
|
|
|
for (let stat of Object.entries(KinkyDungeonStatsPresets)) {
|
|
for (let c of KDCategories) {
|
|
if (stat[1].category == c.name) {
|
|
if (!stat[1].buff && (stat[1].debuff || KDGetPerkCost(stat[1]) < 0))
|
|
c.debuffs.push(stat);
|
|
else
|
|
c.buffs.push(stat);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (localStorage.getItem("KDUnlockedPerks")) {
|
|
let perks = /** @type {any[]} */ (JSON.parse(localStorage.getItem("KDUnlockedPerks")));
|
|
if (perks) {
|
|
for (let p of perks) {
|
|
if (!KDUnlockedPerks.includes(p)) {
|
|
KDUnlockedPerks.push(p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {any[]} list
|
|
* @return {Record<any, any>}
|
|
*/
|
|
function KDMapInit(list) {
|
|
let map = {};
|
|
for (let l of list) {
|
|
map[l] = true;
|
|
}
|
|
return map;
|
|
}
|
|
|
|
function KDistEuclidean(x, y) {
|
|
return Math.sqrt(x*x + y*y);
|
|
}
|
|
|
|
function KDistChebyshev(x, y) {
|
|
return Math.max(Math.abs(x), Math.abs(y));
|
|
}
|
|
|
|
function KDLoadToggles() {
|
|
let loaded = localStorage.getItem("KDToggles") ? JSON.parse(localStorage.getItem("KDToggles")) : {};
|
|
for (let t of Object.keys(KDToggles)) {
|
|
if (loaded[t] != undefined)
|
|
KDToggles[t] = loaded[t];
|
|
}
|
|
|
|
if (!Player.GraphicsSettings) {
|
|
// @ts-ignore
|
|
Player.GraphicsSettings = {AnimationQuality: 0};
|
|
}
|
|
}
|
|
function KDSaveToggles() {
|
|
localStorage.setItem("KDToggles", JSON.stringify(KDToggles));
|
|
}
|
|
|
|
/**
|
|
* Loads the kinky dungeon game
|
|
* @type {ScreenLoadHandler}
|
|
*/
|
|
async function KinkyDungeonLoad() {
|
|
KinkyDungeonSetupCrashHandler();
|
|
KDStartTime = CommonTime();
|
|
|
|
for (let entry of Object.entries(KDLoadingTextKeys)) {
|
|
addTextKey(entry[0], entry[1]);
|
|
}
|
|
|
|
KDLoadPerks();
|
|
|
|
CurrentDarkFactor = 0;
|
|
|
|
KinkyDungeonPlayerNeedsRefresh = false;
|
|
|
|
KinkyDungeonInitTime = CommonTime();
|
|
KinkyDungeonGameKey.load();
|
|
|
|
if (!KinkyDungeonIsPlayer()) KinkyDungeonGameRunning = false;
|
|
//if (!KDPatched && KinkyDungeonState == 'Consent') KinkyDungeonState = "Menu";
|
|
//if (!Player.KinkyDungeonSave) Player.KinkyDungeonSave = {};
|
|
|
|
if (!KinkyDungeonGameRunning) {
|
|
if (!KinkyDungeonPlayer) { // new game
|
|
KDrandomizeSeed(false);
|
|
if (KDPatched) {
|
|
KinkyDungeonPlayer = suppressCanvasUpdate(() => CharacterLoadNPC("NPC_Avatar"));
|
|
} else {
|
|
KinkyDungeonPlayer = CharacterLoadNPC("NPC_Avatar");
|
|
}
|
|
KinkyDungeonPlayer.Type = "simple";
|
|
// @ts-ignore
|
|
KinkyDungeonPlayer.OnlineSharedSettings = {BlockBodyCosplay: true, };
|
|
|
|
KDLoadToggles();
|
|
|
|
KinkyDungeonBones = localStorage.getItem("KinkyDungeonBones") != undefined ? localStorage.getItem("KinkyDungeonBones") : KinkyDungeonBones;
|
|
|
|
if (localStorage.getItem("KDResolution")) {
|
|
let parsed = parseInt(localStorage.getItem("KDResolution"));
|
|
if (parsed != undefined) {
|
|
KDResolutionListIndex = parsed;
|
|
KDResolution = KDResolutionList[KDResolutionListIndex];
|
|
}
|
|
}
|
|
if (localStorage.getItem("KDVibeVolume")) {
|
|
let parsed = parseInt(localStorage.getItem("KDVibeVolume"));
|
|
if (parsed != undefined) {
|
|
KDVibeVolumeListIndex = parsed;
|
|
KDVibeVolume = KDVibeVolumeList[KDVibeVolumeListIndex];
|
|
}
|
|
}
|
|
if (localStorage.getItem("KDMusicVolume")) {
|
|
let parsed = parseInt(localStorage.getItem("KDMusicVolume"));
|
|
if (parsed != undefined) {
|
|
KDMusicVolumeListIndex = parsed;
|
|
KDMusicVolume = KDMusicVolumeList[KDMusicVolumeListIndex];
|
|
}
|
|
}
|
|
if (localStorage.getItem("KDAnimSpeed")) {
|
|
let parsed = parseInt(localStorage.getItem("KDAnimSpeed"));
|
|
if (parsed != undefined) {
|
|
KDAnimSpeedListIndex = parsed;
|
|
KDAnimSpeed = KDAnimSpeedList[KDAnimSpeedListIndex] || 0;
|
|
}
|
|
}
|
|
|
|
KinkyDungeonSexyMode = localStorage.getItem("KinkyDungeonSexyMode") != undefined ? localStorage.getItem("KinkyDungeonSexyMode") == "True" : true;
|
|
KinkyDungeonClassMode = localStorage.getItem("KinkyDungeonClassMode") != undefined ? localStorage.getItem("KinkyDungeonClassMode") : "Mage";
|
|
KinkyDungeonSexyPiercing = localStorage.getItem("KinkyDungeonSexyPiercing") != undefined ? localStorage.getItem("KinkyDungeonSexyPiercing") == "True" : false;
|
|
KinkyDungeonSexyPlug = localStorage.getItem("KinkyDungeonSexyPlug") != undefined ? localStorage.getItem("KinkyDungeonSexyPlug") == "True" : false;
|
|
|
|
KinkyDungeonSaveMode = localStorage.getItem("KinkyDungeonSaveMode") != undefined ? localStorage.getItem("KinkyDungeonSaveMode") == "True" : false;
|
|
KinkyDungeonRandomMode = localStorage.getItem("KinkyDungeonRandomMode") != undefined ? localStorage.getItem("KinkyDungeonRandomMode") == "True" : false;
|
|
KinkyDungeonEasyMode = localStorage.getItem("KinkyDungeonEasyMode") != undefined ? parseInt(localStorage.getItem("KinkyDungeonEasyMode")) || 0 : 0;
|
|
|
|
KinkyDungeonNewDress = true;
|
|
KDCurrentOutfit = parseInt(localStorage.getItem("kdcurrentoutfit") || 0);
|
|
let appearance = LZString.decompressFromBase64(localStorage.getItem("kinkydungeonappearance" + KDCurrentOutfit));
|
|
if (!appearance || StandalonePatched) {
|
|
const app = CommonJSONParse(appearance || "{}");
|
|
if (!CommonIsArray(app) || !CommonIsObject(app[0]) || !("Asset" in app[0])) {
|
|
KinkyDungeonNewDress = false;
|
|
appearance = CharacterAppearanceStringify(KinkyDungeonPlayerCharacter ?? Player);
|
|
}
|
|
}
|
|
|
|
CharacterAppearanceRestore(KinkyDungeonPlayer, appearance);
|
|
|
|
if (KDPatched)
|
|
suppressCanvasUpdate(() => CharacterReleaseTotal(KinkyDungeonPlayer));
|
|
else
|
|
CharacterReleaseTotal(KinkyDungeonPlayer);
|
|
|
|
|
|
CharacterRefresh(KinkyDungeonPlayer);
|
|
|
|
|
|
KinkyDungeonInitializeDresses();
|
|
KinkyDungeonDressSet();
|
|
|
|
if (KDPatched)
|
|
suppressCanvasUpdate(() => CharacterNaked(KinkyDungeonPlayer));
|
|
else
|
|
CharacterNaked(KinkyDungeonPlayer);
|
|
|
|
KinkyDungeonCheckClothesLoss = true;
|
|
KinkyDungeonDressPlayer();
|
|
|
|
KDInitProtectedGroups();
|
|
|
|
}
|
|
|
|
if (localStorage.getItem("KinkyDungeonKeybindings") && JSON.parse(localStorage.getItem("KinkyDungeonKeybindings"))) {
|
|
KinkyDungeonKeybindings = JSON.parse(localStorage.getItem("KinkyDungeonKeybindings"));
|
|
KinkyDungeonKeybindingsTemp = {};
|
|
Object.assign(KinkyDungeonKeybindingsTemp, KinkyDungeonKeybindings);
|
|
console.log(KinkyDungeonKeybindings);
|
|
}
|
|
else console.log("Failed to load keybindings");
|
|
|
|
if (KinkyDungeonIsPlayer()) {
|
|
//if (!KDPatched && KinkyDungeonState == "Consent")
|
|
//KinkyDungeonState = "Menu";
|
|
KinkyDungeonGameData = null;
|
|
|
|
// @ts-expect-error
|
|
CharacterAppearancePreviousEmoticon = WardrobeGetExpression(Player).Emoticon;
|
|
CharacterSetFacialExpression(Player, "Emoticon", "Gaming");
|
|
} else {
|
|
KinkyDungeonState = "Game";
|
|
if (!KinkyDungeonGameData) {
|
|
MiniGameKinkyDungeonLevel = 1;
|
|
KinkyDungeonInitialize(1);
|
|
}
|
|
}
|
|
|
|
for (const group of KinkyDungeonStruggleGroupsBase) {
|
|
if (group == "ItemM") {
|
|
if (InventoryGet(Player, "ItemMouth"))
|
|
KinkyDungeonRestraintsLocked.push("ItemMouth");
|
|
if (InventoryGet(Player, "ItemMouth2"))
|
|
KinkyDungeonRestraintsLocked.push("ItemMouth2");
|
|
if (InventoryGet(Player, "ItemMouth3"))
|
|
KinkyDungeonRestraintsLocked.push("ItemMouth3");
|
|
}
|
|
if (group == "ItemH") {
|
|
if (InventoryGet(Player, "ItemHood"))
|
|
KinkyDungeonRestraintsLocked.push("ItemHood");
|
|
if (InventoryGet(Player, "ItemHead"))
|
|
KinkyDungeonRestraintsLocked.push("ItemHead");
|
|
}
|
|
|
|
// @ts-expect-error
|
|
if (InventoryGet(Player, group))
|
|
KinkyDungeonRestraintsLocked.push(group);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Restricts Devious Dungeon Challenge to only occur when inside the arcade
|
|
* @returns {boolean} - If the player is in the arcade
|
|
*/
|
|
function KinkyDungeonDeviousDungeonAvailable() {
|
|
return KinkyDungeonIsPlayer() && (DialogGamingReturnScreen?.[1] == "Arcade" || MiniGameReturnFunction == "ArcadeKinkyDungeonEnd") && !KDPatched;
|
|
}
|
|
|
|
/**
|
|
* Returns whether or not the player is the one playing, which determines whether or not to draw the UI and struggle groups
|
|
* @returns {boolean} - If the player is the game player
|
|
*/
|
|
function KinkyDungeonIsPlayer() {
|
|
return (!KinkyDungeonPlayerCharacter || KinkyDungeonPlayerCharacter == Player) ;
|
|
}
|
|
|
|
/**
|
|
* Runs the kinky dungeon game and draws its components on screen
|
|
* @returns {void} - Nothing
|
|
*/
|
|
|
|
let KinkyDungeonCreditsPos = 0;
|
|
let KDMaxPatronPerPage = 4;
|
|
let KDMaxPatron = 5;
|
|
let KinkyDungeonPatronPos = 0;
|
|
let KinkyDungeonFastWait = true;
|
|
let KinkyDungeonTempWait = false;
|
|
let KinkyDungeonSexyMode = false;
|
|
let KinkyDungeonClassMode = "Mage";
|
|
let KinkyDungeonRandomMode = false;
|
|
let KinkyDungeonEasyMode = 0;
|
|
let KinkyDungeonSaveMode = false;
|
|
let KinkyDungeonSexyPiercing = false;
|
|
let KinkyDungeonSexyPlug = false;
|
|
let KDOldValue = "";
|
|
let KDOriginalValue = "";
|
|
|
|
let KDRestart = false;
|
|
|
|
let fpscounter = 0;
|
|
let lastfps = 0;
|
|
let dispfps = 60;
|
|
|
|
let KDMarkAsCache = [];
|
|
|
|
let lastGlobalRefresh = 0;
|
|
let GlobalRefreshInterval = 1000;
|
|
let KDGlobalRefresh = false;
|
|
|
|
function KinkyDungeonRun() {
|
|
|
|
if (KinkyDungeonPlayer?.Appearance) {
|
|
for (let A = 0; A < KinkyDungeonPlayer.Appearance.length; A++) {
|
|
if (KinkyDungeonPlayer.Appearance[A]?.Asset?.Name?.includes("Penis")) {
|
|
KinkyDungeonPlayer.Appearance.splice(A, 1);
|
|
A--;
|
|
}
|
|
}
|
|
}
|
|
if (StandalonePatched && KDCurrentModels) {
|
|
let refresh = false;
|
|
if (CommonTime() > lastGlobalRefresh + GlobalRefreshInterval) {
|
|
lastGlobalRefresh = CommonTime();
|
|
refresh = true;
|
|
}
|
|
|
|
for (let MC of KDCurrentModels.values()) {
|
|
|
|
|
|
// Cull containers that werent drawn this turn
|
|
for (let Container of MC.Containers.entries()) {
|
|
|
|
if (!MC.ContainersDrawn.has(Container[0]) && Container[1]) {
|
|
Container[1].Container.parent.removeChild(Container[1].Container);
|
|
MC.Containers.delete(Container[0]);
|
|
Container[1].Container.destroy();
|
|
} else if (refresh)
|
|
MC.Update.delete(Container[0]);
|
|
}
|
|
|
|
MC.ContainersDrawn.clear();
|
|
}
|
|
}
|
|
|
|
|
|
// Override right click and make it trigger the Skip key
|
|
// Normally we don't override right click on websites but this is a game
|
|
if (!CommonIsMobile)
|
|
document.addEventListener('contextmenu', event => {
|
|
if (CommonIsMobile) {
|
|
// Nothing!!
|
|
} else if (document.activeElement === null || document.activeElement === document.body) {
|
|
event.preventDefault();
|
|
let code = KinkyDungeonKeySkip[0];
|
|
if (!KinkyDungeonKeybindingCurrentKey) {
|
|
KinkyDungeonKeybindingCurrentKey = code;
|
|
KDLastKeyTime[KinkyDungeonKeybindingCurrentKey] = CommonTime() + 100;
|
|
// We also press it for 100 msec
|
|
(async function() {
|
|
KinkyDungeonGameKey.keyPressed[9] = true;
|
|
await CommonSleep(100);
|
|
KinkyDungeonGameKey.keyPressed[9] = false;
|
|
})();
|
|
}
|
|
}
|
|
});
|
|
|
|
// Reset the sprites drawn cache
|
|
kdSpritesDrawn = new Map();
|
|
|
|
KDLastButtonsCache = KDButtonsCache;
|
|
KDButtonsCache = {};
|
|
KDUpdateVibeSounds();
|
|
KDUpdateMusic();
|
|
|
|
if (!KDPatched)
|
|
DrawButtonVis(1885, 25, 90, 90, "", "#ffffff", KinkyDungeonRootDirectory + "UI/Exit.png");
|
|
|
|
// eslint-disable-next-line no-constant-condition
|
|
if (true || KDToggles.Fullscreen) {
|
|
KinkyDungeonGridWidthDisplay = 2000/KinkyDungeonGridSizeDisplay;//17;
|
|
KinkyDungeonGridHeightDisplay = 1000/KinkyDungeonGridSizeDisplay;//9;
|
|
canvasOffsetX = 0;
|
|
canvasOffsetY = 0;
|
|
KinkyDungeonCanvas.width = 2000;
|
|
KinkyDungeonCanvas.height = 1000;
|
|
} else {
|
|
|
|
KinkyDungeonGridWidthDisplay = 16;
|
|
KinkyDungeonGridHeightDisplay = 9;
|
|
canvasOffsetX = canvasOffsetX_ui;
|
|
canvasOffsetY = canvasOffsetY_ui;
|
|
KinkyDungeonCanvas.width = KinkyDungeonGridSizeDisplay * KinkyDungeonGridWidthDisplay;
|
|
KinkyDungeonCanvas.height = KinkyDungeonGridSizeDisplay * KinkyDungeonGridHeightDisplay;
|
|
}
|
|
// Check to see whether the player (outside of KD) needs a refresh
|
|
KinkyDungeonCheckPlayerRefresh();
|
|
|
|
|
|
if ((KinkyDungeonState != "Game" || KinkyDungeonDrawState != "Game") && KinkyDungeonState != "TileEditor") {
|
|
let BG = (KinkyDungeonState == "Consent" || KinkyDungeonState == "Logo") ? "Logo" : "BrickWall";
|
|
if (StandalonePatched) {
|
|
KDDraw(kdcanvas, kdpixisprites, "bg", "Backgrounds/" + BG + ".png", 0, 0, CanvasWidth, CanvasHeight, undefined, {
|
|
zIndex: -115,
|
|
});
|
|
} else {
|
|
DrawImage("Backgrounds/" + BG + ".png", 0, 0);
|
|
}
|
|
kdgameboard.visible = false;
|
|
kdgamefog.visible = false;
|
|
} else {
|
|
kdgameboard.visible = true;
|
|
kdgamefog.visible = KinkyDungeonState != "TileEditor";
|
|
}
|
|
// Draw the characters
|
|
if (KinkyDungeonState != "Consent" && (KinkyDungeonState != "Game" || KinkyDungeonDrawState != "Game") && KinkyDungeonState != "Stats" && KinkyDungeonState != "TileEditor")
|
|
DrawCharacter(KinkyDungeonPlayer, 0, 0, 1);
|
|
|
|
|
|
if (KinkyDungeonState == "Mods") {
|
|
|
|
DrawButtonKDEx("mods_back", (bdata) => {
|
|
KinkyDungeonState = "Menu";
|
|
KDExecuteMods();
|
|
return true;
|
|
}, true, 975, 850, 350, 64, TextGet("KinkyDungeonLoadBack"), "#ffffff", "");
|
|
|
|
DrawButtonKDEx("mods_load", (bdata) => {
|
|
getFileInput();
|
|
return true;
|
|
}, true, 975, 250, 350, 64, TextGet("KinkyDungeonLoadMod"), "#ffffff", "");
|
|
DrawTextKD(TextGet("KinkyDungeonLoadModWarning1"), 1175, 100, "#ffffff", KDTextGray2);
|
|
DrawTextKD(TextGet("KinkyDungeonLoadModWarning2"), 1175, 150, "#ffffff", KDTextGray2);
|
|
|
|
KDDrawMods();
|
|
|
|
} else if (KinkyDungeonState == "Credits") {
|
|
let credits = TextGet("KinkyDungeonCreditsList" + KinkyDungeonCreditsPos).split('|');
|
|
let i = 0;
|
|
for (let c of credits) {
|
|
DrawTextKD(c, 550, 25 + 40 * i, "#ffffff", KDTextGray2, undefined, "left");
|
|
i++;
|
|
}
|
|
|
|
DrawButtonVis(1870, 930, 110, 64, TextGet("KinkyDungeonBack"), "#ffffff", "");
|
|
DrawButtonVis(1730, 930, 110, 64, TextGet("KinkyDungeonNext"), "#ffffff", "");
|
|
} else if (KinkyDungeonState == "Patrons") {
|
|
for (let x = KinkyDungeonPatronPos * KDMaxPatronPerPage; x < KinkyDungeonPatronPos * KDMaxPatronPerPage + KDMaxPatronPerPage && x <= KDMaxPatron; x++) {
|
|
let credits = TextGet("KinkyDungeonPatronsList" + x).split('|');
|
|
let i = 0;
|
|
for (let c of credits) {
|
|
DrawTextKD(c, 550 + 350 * (x - KinkyDungeonPatronPos * KDMaxPatronPerPage), 25 + 40 * i, "#ffffff", KDTextGray2, undefined, "left");
|
|
i++;
|
|
}
|
|
}
|
|
|
|
|
|
DrawButtonVis(1870, 930, 110, 64, TextGet("KinkyDungeonBack"), "#ffffff", "");
|
|
DrawButtonVis(1730, 930, 110, 64, TextGet("KinkyDungeonNext"), "#ffffff", "");
|
|
//DrawButtonVis(1730, 930, 110, 64, TextGet("KinkyDungeonNext"), "#ffffff", "");
|
|
} else if (KinkyDungeonState == "Menu") {
|
|
KinkyDungeonGameFlag = false;
|
|
DrawCheckboxVis(1700, 100, 64, 64, TextGet("KDToggleSound"), KDToggles.Sound, false, "#ffffff");
|
|
// Draw temp start screen
|
|
if (KDLose) {
|
|
DrawTextKD(TextGet("End"), 1000, 250, "#ffffff", KDTextGray2);
|
|
//DrawTextKD(TextGet("End2"), 1000, 310, "#ffffff", KDTextGray2);
|
|
DrawTextKD(TextGet("End3"), 1000, 290, "#ffffff", KDTextGray2);
|
|
} else if (!KDPatched) {
|
|
//DrawTextKD(TextGet("Intro"), 1250, 250, "#ffffff", KDTextGray2);
|
|
//DrawTextKD(TextGet("Intro2"), 1250, 300, "#ffffff", KDTextGray2);
|
|
//DrawTextKD(TextGet("Intro3"), 1250, 350, "#ffffff", KDTextGray2);
|
|
DrawTextKD(TextGet("Intro4BC"), 1000, 960, "#ffffff", KDTextGray2);
|
|
}
|
|
|
|
let str = TextGet("KinkyDungeon");
|
|
DrawTextKD(str.substring(0, Math.min(str.length, Math.round((CommonTime()-KDStartTime)/100))), 1000, 80, "#ffffff", KDTextGray2, 84);
|
|
DrawTextKD(TextGet("KDLogo2"), 1000, 180, "#ffffff", KDTextGray2);
|
|
//DrawTextKD(TextGet("KinkyDungeon"), 1000, 200, "#ffffff", KDTextGray2);
|
|
|
|
if (ArcadeDeviousChallenge && KinkyDungeonDeviousDungeonAvailable() && !KDPatched)
|
|
DrawTextKD(TextGet("DeviousChallenge"), 1000, 925, "#ffffff", KDTextGray2);
|
|
|
|
|
|
DrawButtonKDEx("GameContinue", () => {
|
|
KinkyDungeonStartNewGame(true);
|
|
return true;
|
|
}, true, 1000-350/2, 360, 350, 64, TextGet("GameContinue"), localStorage.getItem('KinkyDungeonSave') ? "#ffffff" : "pink", "");
|
|
DrawButtonKDEx("GameStart", () => {
|
|
KinkyDungeonState = "Diff";
|
|
KinkyDungeonLoadStats();
|
|
return true;
|
|
}, true, 1000-350/2, 440, 350, 64, TextGet("GameStart"), "#ffffff", "");
|
|
DrawButtonKDEx("LoadGame", () => {
|
|
KinkyDungeonState = "Load";
|
|
ElementCreateTextArea("saveInputField");
|
|
return true;
|
|
}, true, 1000-350/2, 520, 350, 64, TextGet("LoadGame"), "#ffffff", "");
|
|
DrawButtonKDEx("GameConfigKeys", () => {
|
|
KinkyDungeonState = "Keybindings";
|
|
|
|
if (!KinkyDungeonKeybindings)
|
|
KDSetDefaultKeybindings();
|
|
else {
|
|
KinkyDungeonKeybindingsTemp = {};
|
|
Object.assign(KinkyDungeonKeybindingsTemp, KinkyDungeonKeybindings);
|
|
}
|
|
return true;
|
|
}, true, 1000-350/2, 600, 350, 64, TextGet("GameConfigKeys"), "#ffffff", "");
|
|
DrawButtonKDEx("GameToggles", () => {
|
|
KinkyDungeonState = "Toggles";
|
|
return true;
|
|
}, true, 1000-350/2, 680, 350, 64, TextGet("GameToggles"), "#ffffff", "");
|
|
|
|
if (TestMode) {
|
|
DrawButtonKDEx("TileEditor", () => {
|
|
KDInitTileEditor();
|
|
KinkyDungeonState = "TileEditor";
|
|
return true;
|
|
}, true, 1000-350/2, 760, 350, 64, "Tile Editor", "#ffffff", "");
|
|
}
|
|
|
|
if (!StandalonePatched) {
|
|
|
|
DrawButtonVis(460, 942, 220, 50, TextGet((KinkyDungeonReplaceConfirm > 0 ) ? "KinkyDungeonConfirm" : "KinkyDungeonDressPlayerReset"), "#ffffff", "");
|
|
DrawButtonVis(690, 942, 150, 50, TextGet("KinkyDungeonDressPlayerImport"), "#ffffff", "");
|
|
}
|
|
|
|
|
|
DrawButtonKDEx("GoToWardrobe", (bdata) => {
|
|
|
|
if (StandalonePatched) {
|
|
KinkyDungeonState = "Wardrobe";
|
|
KDPlayerSetPose = false;
|
|
KDInitCurrentPose();
|
|
KinkyDungeonInitializeDresses();
|
|
KDUpdateModelList();
|
|
KDRefreshOutfitInfo();
|
|
let orig = localStorage.getItem("kinkydungeonappearance" + KDCurrentOutfit);
|
|
let current = LZString.compressToBase64(CharacterAppearanceStringify(KinkyDungeonPlayer));
|
|
if (orig != current) KDOriginalValue = orig;
|
|
}
|
|
let appearance = LZString.decompressFromBase64(localStorage.getItem("kinkydungeonappearance" + KDCurrentOutfit));
|
|
if (appearance) {
|
|
CharacterAppearanceRestore(KinkyDungeonPlayer, appearance);
|
|
CharacterRefresh(KinkyDungeonPlayer);
|
|
}
|
|
// @ts-expect-error
|
|
KinkyDungeonPlayer.OnlineSharedSettings = {AllowFullWardrobeAccess: true};
|
|
KinkyDungeonNewDress = true;
|
|
if (KDPatched && !StandalonePatched) {
|
|
// Give all of the items
|
|
|
|
for (let A = 0; A < Asset.length; A++)
|
|
|
|
if ((Asset[A] != null) && (Asset[A].Group != null) && !InventoryAvailable(Player, Asset[A].Name, Asset[A].Group.Name))
|
|
|
|
InventoryAdd(Player, Asset[A].Name, Asset[A].Group.Name);
|
|
}
|
|
|
|
CharacterReleaseTotal(KinkyDungeonPlayer);
|
|
KinkyDungeonDressPlayer();
|
|
// @ts-expect-error
|
|
KinkyDungeonPlayer.OnlineSharedSettings = {BlockBodyCosplay: false, AllowFullWardrobeAccess: true};
|
|
if (!StandalonePatched) {
|
|
if (!KDPatched)
|
|
MainCanvas.textAlign = "center";
|
|
CharacterAppearanceLoadCharacter(KinkyDungeonPlayer);
|
|
}
|
|
KinkyDungeonConfigAppearance = true;
|
|
if (appearance) {
|
|
CharacterAppearanceRestore(KinkyDungeonPlayer, appearance);
|
|
CharacterRefresh(KinkyDungeonPlayer);
|
|
}
|
|
return true;
|
|
}, true, 30, 942, 440, 50, TextGet("KinkyDungeonDressPlayer"), "#ffffff", "");
|
|
|
|
|
|
DrawButtonVis(1850, 942, 135, 50, TextGet("KinkyDungeonCredits"), "#ffffff", "");
|
|
DrawButtonVis(1700, 942, 135, 50, TextGet("KinkyDungeonPatrons"), "#ffffff", "");
|
|
|
|
DrawButtonKDEx("Deviantart", (bdata) => {
|
|
let url = 'https://www.deviantart.com/ada18980';
|
|
window.open(url, '_blank');
|
|
return true;
|
|
}, true, 1700, 694, 280, 50, TextGet("KinkyDungeonDeviantart"), "#ffffff", "");
|
|
|
|
DrawButtonKDEx("Patreon", (bdata) => {
|
|
let url = 'https://www.patreon.com/ada18980';
|
|
KDSendEvent('patreon');
|
|
window.open(url, '_blank');
|
|
return true;
|
|
}, true, 1700, 754, 280, 50, TextGet("KinkyDungeonPatreon"), "#ffeecc", "");
|
|
|
|
|
|
if (KDPatched || StandalonePatched) {
|
|
DrawTextKD(TextGet("Language") + " ->", 1675, 898, "#ffffff", KDTextGray2, undefined, "right");
|
|
DrawButtonVis(1700, 874, 280, 50, localStorage.getItem("BondageClubLanguage") || "EN", "#ffffff", "");
|
|
}
|
|
|
|
if (KDPatched) {
|
|
|
|
DrawButtonKDEx("mods_button", (bdata) => {
|
|
KinkyDungeonState = "Mods";
|
|
return true;
|
|
}, !KDModsLoaded, 1700, 814, 280, 50, TextGet(!KDModsLoaded ? "KDMods" : "KDModsLoaded"), "#ffffff", "");
|
|
}
|
|
|
|
if (KDRestart)
|
|
DrawTextKD(TextGet("RestartNeeded" + (localStorage.getItem("BondageClubLanguage") || "EN")), 1840, 600, "#ffffff", KDTextGray2);
|
|
} else if (KinkyDungeonState == "Consent") {
|
|
let str = TextGet("KinkyDungeon");
|
|
DrawTextKD(str.substring(0, Math.min(str.length, Math.round((CommonTime()-KDStartTime)/100))), 1000, 80, "#ffffff", KDTextGray2, 84);
|
|
DrawTextKD(TextGet("KDLogo2"), 1000, 180, "#ffffff", KDTextGray2);
|
|
|
|
if (!KDLoadingFinished) {
|
|
DrawTextKD(TextGet("KDLoading") + Math.round(100 * KDLoadingDone / KDLoadingMax) + "%", 1000, 950, "#ffffff", KDTextGray2);
|
|
} else {
|
|
|
|
if (KDPatched) {
|
|
DrawButtonVis(1000-450/2, 720, 450, 64, TextGet("KDOptIn"), KDLoadingFinished ? "#ffffff" : "#888888", "");
|
|
DrawButtonVis(1000-450/2, 820, 450, 64, TextGet("KDOptOut"), KDLoadingFinished ? "#ffffff" : "#888888", "");
|
|
|
|
DrawTextKD(TextGet("KinkyDungeonConsent"), 1000, 450, "#ffffff", KDTextGray2);
|
|
DrawTextKD(TextGet("KinkyDungeonConsent2"), 1000, 500, "#ffffff", KDTextGray2);
|
|
DrawTextKD(TextGet("KinkyDungeonConsent3"), 1000, 550, "#ffffff", KDTextGray2);
|
|
} else {
|
|
DrawButtonVis(1000-450/2, 820, 450, 64, TextGet("KDStartGame"), KDLoadingFinished ? "#ffffff" : "#888888", "");
|
|
}
|
|
|
|
}
|
|
if (KDLoadingDone >= KDLoadingMax) {
|
|
|
|
/*for (let c of PIXI.Cache._cache.keys()) {
|
|
KDTex(c);
|
|
}*/
|
|
KDLoadingFinished = true;
|
|
}
|
|
|
|
} else if (KinkyDungeonState == "TileEditor") {
|
|
KDDrawTileEditor();
|
|
} else if (KinkyDungeonState == "Load") {
|
|
DrawButtonVis(875, 750, 350, 64, TextGet("KinkyDungeonLoadConfirm"), "#ffffff", "");
|
|
DrawButtonVis(1275, 750, 350, 64, TextGet("KinkyDungeonLoadBack"), "#ffffff", "");
|
|
|
|
ElementPosition("saveInputField", 1250, 550, 1000, 230);
|
|
} else if (KinkyDungeonState == "LoadOutfit") {
|
|
DrawButtonVis(875, 750, 350, 64, TextGet("LoadOutfit"), "#ffffff", "");
|
|
DrawButtonVis(1275, 750, 350, 64, TextGet("KDWardrobeBackTo" + (StandalonePatched ? "Wardrobe" : "Menu")), "#ffffff", "");
|
|
|
|
let newValue = ElementValue("saveInputField");
|
|
if (newValue != KDOldValue) {
|
|
let decompressed = LZString.decompressFromBase64(ElementValue("saveInputField"));
|
|
if (decompressed) {
|
|
let origAppearance = KinkyDungeonPlayer.Appearance;
|
|
try {
|
|
console.log("Trying BC code...");
|
|
CharacterAppearanceRestore(KinkyDungeonPlayer, decompressed);
|
|
CharacterRefresh(KinkyDungeonPlayer);
|
|
KDOldValue = newValue;
|
|
KDInitProtectedGroups();
|
|
|
|
if (KinkyDungeonPlayer.Appearance.length == 0)
|
|
throw new DOMException();
|
|
} catch (e) {
|
|
console.log("Trying BCX code...");
|
|
// If we fail, it might be a BCX code. try it!
|
|
KinkyDungeonPlayer.Appearance = origAppearance;
|
|
try {
|
|
let parsed = JSON.parse(decompressed);
|
|
if (CommonIsArray(parsed) && parsed.length > 0) {
|
|
if (!StandalonePatched) {
|
|
for (let g of parsed) {
|
|
if (CommonIsObject(g)) {
|
|
InventoryWear(KinkyDungeonPlayer, g.Name, g.Group, g.Color);
|
|
}
|
|
}
|
|
CharacterRefresh(KinkyDungeonPlayer);
|
|
ElementValue("saveInputField", LZString.compressToBase64(CharacterAppearanceStringify(KinkyDungeonPlayer)));
|
|
}
|
|
KDOldValue = newValue;
|
|
KDInitProtectedGroups();
|
|
} else {
|
|
console.log("Invalid code. Maybe its corrupt?");
|
|
}
|
|
} catch (error) {
|
|
console.log("Invalid code.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ElementPosition("saveInputField", 1250, 550, 1000, 230);
|
|
} else if (KinkyDungeonState == "Journey") {
|
|
DrawTextKD(TextGet("KinkyDungeonJourney"), 1250, 300, "#ffffff", KDTextGray2);
|
|
DrawButtonVis(875, 350, 750, 64, TextGet("KinkyDungeonJourney0"), "#ffffff", "");
|
|
DrawButtonVis(875, 450, 750, 64, TextGet("KinkyDungeonJourney1"), "#ffffff", "");
|
|
DrawButtonVis(875, 550, 750, 64, TextGet("KinkyDungeonJourney2"), "#ffffff", "");
|
|
DrawButtonVis(1075, 850, 350, 64, TextGet("KinkyDungeonLoadBack"), "#ffffff", "");
|
|
|
|
} else if (KinkyDungeonState == "Diff") {
|
|
DrawTextKD(TextGet("KinkyDungeonDifficulty"), 1250, 170, "#ffffff", KDTextGray2);
|
|
//DrawButtonVis(875, 350, 750, 64, TextGet("KinkyDungeonDifficulty0"), "#ffffff", "");
|
|
//DrawButtonVis(875, 450, 750, 64, TextGet("KinkyDungeonDifficulty3"), "#ffffff", "");
|
|
//DrawButtonVis(875, 550, 750, 64, TextGet("KinkyDungeonDifficulty1"), "#ffffff", "");
|
|
DrawButtonKDEx("startQuick", () => {
|
|
KinkyDungeonStatsChoice = new Map();
|
|
KDUpdatePlugSettings();
|
|
KDLose = false;
|
|
KinkyDungeonStartNewGame();
|
|
return true;
|
|
}, true, 875, 650, 750, 64, TextGet("KinkyDungeonStartGameQuick"), "#ffffff", "");
|
|
DrawButtonKDEx("startGame", () => {
|
|
KinkyDungeonState = "Stats";
|
|
KDUpdatePlugSettings();
|
|
return true;
|
|
}, true, 875, 720, 750, 64, TextGet("KinkyDungeonStartGameAdv"), "#ffffff", "");
|
|
|
|
|
|
|
|
if (MouseIn(875, 650, 750, 64)) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonStartGameDesc"), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
if (MouseIn(875, 720, 750, 64)) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonStartGameDescAdc"), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
DrawButtonVis(1075, 850, 350, 64, TextGet("KinkyDungeonLoadBack"), "#ffffff", "");
|
|
|
|
|
|
let buttonswidth = 168;
|
|
let buttonsheight = 50;
|
|
let buttonspad = 25;
|
|
let buttonsypad = 10;
|
|
let buttonsstart = 875;
|
|
let X = 0;
|
|
let Y = 0;
|
|
|
|
DrawTextFitKD(TextGet("KDClasses"), 875 - 50, 210 + 22, 300, "#ffffff", KDTextGray1, undefined, "right");
|
|
|
|
let classCount = Object.keys(KDClassStart).length;
|
|
for (let i = 0; i < classCount; i++) {
|
|
X = i % 4;
|
|
Y = Math.floor(i / 4);
|
|
|
|
DrawButtonKDEx("Class" + i, (bdata) => {
|
|
KinkyDungeonClassMode = Object.keys(KDClassStart)[i];
|
|
localStorage.setItem("KinkyDungeonClassMode", "" + KinkyDungeonClassMode);
|
|
return true;
|
|
}, (!KDClassReqs[Object.keys(KDClassStart)[i]]) || KDClassReqs[Object.keys(KDClassStart)[i]](),
|
|
buttonsstart + (buttonspad + buttonswidth) * X, 210 + Y*(buttonsheight + buttonsypad), buttonswidth, buttonsheight, TextGet("KinkyDungeonClassMode" + i),
|
|
((!KDClassReqs[Object.keys(KDClassStart)[i]]) || KDClassReqs[Object.keys(KDClassStart)[i]]()) ?
|
|
(KinkyDungeonClassMode == Object.keys(KDClassStart)[i] ? "#ffffff" : "#888888")
|
|
: "#ff5555", "");
|
|
if (MouseIn(buttonsstart + (buttonspad + buttonswidth) * X, 210 + Y*(buttonsheight + buttonsypad), buttonswidth, buttonsheight)) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonClassModeDesc" + i), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DrawTextFitKD(TextGet("KDSexyMode"), 875 - 50, 350 + 22, 300, "#ffffff", KDTextGray1, undefined, "right");
|
|
|
|
|
|
DrawButtonKDEx("KinkyDungeonSexyMode0", (bdata) => {
|
|
KinkyDungeonSexyMode = false;
|
|
KDUpdatePlugSettings();
|
|
localStorage.setItem("KinkyDungeonSexyMode", KinkyDungeonSexyMode ? "True" : "False");
|
|
return true;
|
|
}, true, 875, 350, 275, 50, TextGet("KinkyDungeonSexyMode0"), !KinkyDungeonSexyMode ? "#ffffff" : "#888888", "");
|
|
if (MouseInKD("KinkyDungeonSexyMode0")) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonSexyModeDesc0"), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
|
|
DrawButtonKDEx("KinkyDungeonSexyMode1", (bdata) => {
|
|
KinkyDungeonSexyMode = true;
|
|
KDUpdatePlugSettings();
|
|
localStorage.setItem("KinkyDungeonSexyMode", KinkyDungeonSexyMode ? "True" : "False");
|
|
return true;
|
|
}, true, 1175, 350, 275, 50, TextGet("KinkyDungeonSexyMode1"), KinkyDungeonSexyMode ? "#ffffff" : "#888888", "");
|
|
if (MouseInKD("KinkyDungeonSexyMode1")) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonSexyModeDesc1"), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
|
|
DrawTextFitKD(TextGet("KDRandomMode"), 875 - 50, 410 + 22, 300, "#ffffff", KDTextGray1, undefined, "right");
|
|
|
|
|
|
DrawButtonKDEx("KinkyDungeonRandomMode0", (bdata) => {
|
|
KinkyDungeonRandomMode = false;
|
|
localStorage.setItem("KinkyDungeonRandomMode", KinkyDungeonRandomMode ? "True" : "False");
|
|
return true;
|
|
}, true, 875, 410, 275, 50, TextGet("KinkyDungeonRandomMode0"), !KinkyDungeonRandomMode ? "#ffffff" : "#888888", "");
|
|
if (MouseInKD("KinkyDungeonRandomMode0")) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonRandomModeDesc0"), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
|
|
DrawButtonKDEx("KinkyDungeonRandomMode1", (bdata) => {
|
|
KinkyDungeonRandomMode = true;
|
|
localStorage.setItem("KinkyDungeonRandomMode", KinkyDungeonRandomMode ? "True" : "False");
|
|
return true;
|
|
}, true, 1175, 410, 275, 50, TextGet("KinkyDungeonRandomMode1"), KinkyDungeonRandomMode ? "#ffffff" : "#888888", "");
|
|
if (MouseInKD("KinkyDungeonRandomMode1")) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonRandomModeDesc1"), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
|
|
DrawTextFitKD(TextGet("KDSaveMode"), 875 - 50, 470 + 22, 300, "#ffffff", KDTextGray1, undefined, "right");
|
|
|
|
|
|
DrawButtonKDEx("KinkyDungeonSaveMode0", (bdata) => {
|
|
KinkyDungeonSaveMode = false;
|
|
localStorage.setItem("KinkyDungeonSaveMode", KinkyDungeonSaveMode ? "True" : "False");
|
|
return true;
|
|
}, true, 875, 470, 275, 50, TextGet("KinkyDungeonSaveMode0"), !KinkyDungeonSaveMode ? "#ffffff" : "#888888", "");
|
|
if (MouseInKD("KinkyDungeonSaveMode0")) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonSaveModeDesc0"), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
|
|
DrawButtonKDEx("KinkyDungeonSaveMode1", (bdata) => {
|
|
KinkyDungeonSaveMode = true;
|
|
localStorage.setItem("KinkyDungeonSaveMode", KinkyDungeonSaveMode ? "True" : "False");
|
|
return true;
|
|
}, true, 1175, 470, 275, 50, TextGet("KinkyDungeonSaveMode1"), KinkyDungeonSaveMode ? "#ffffff" : "#888888", "");
|
|
if (MouseInKD("KinkyDungeonSaveMode1")) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonSaveModeDesc1"), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
|
|
|
|
DrawTextFitKD(TextGet("KDEasyMode"), 875 - 50, 530 + 22, 300, "#ffffff", KDTextGray1, undefined, "right");
|
|
|
|
|
|
DrawButtonKDEx("KinkyDungeonEasyMode0", (bdata) => {
|
|
KinkyDungeonEasyMode = 0;
|
|
localStorage.setItem("KinkyDungeonEasyMode", KinkyDungeonEasyMode ? "True" : "False");
|
|
return true;
|
|
}, true, 1075, 530, 175, 50, TextGet("KinkyDungeonEasyMode0"), KinkyDungeonEasyMode == 0 ? "#ffffff" : "#888888", "");
|
|
if (MouseInKD("KinkyDungeonEasyMode0")) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonEasyModeDesc0"), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
|
|
DrawButtonKDEx("KinkyDungeonEasyMode1", (bdata) => {
|
|
KinkyDungeonEasyMode = 1;
|
|
localStorage.setItem("KinkyDungeonEasyMode", KinkyDungeonEasyMode ? "True" : "False");
|
|
return true;
|
|
}, true, 1275, 530, 175, 50, TextGet("KinkyDungeonEasyMode1"), KinkyDungeonEasyMode == 1 ? "#ffffff" : "#888888", "");
|
|
if (MouseInKD("KinkyDungeonEasyMode1")) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonEasyModeDesc1"), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
|
|
DrawButtonKDEx("KinkyDungeonEasyMode2", (bdata) => {
|
|
KinkyDungeonEasyMode = 2;
|
|
localStorage.setItem("KinkyDungeonEasyMode", KinkyDungeonEasyMode ? "True" : "False");
|
|
return true;
|
|
}, true, 875, 530, 175, 50, TextGet("KinkyDungeonEasyMode2"), KinkyDungeonEasyMode == 2 ? "#ffffff" : "#888888", "");
|
|
if (MouseInKD("KinkyDungeonEasyMode2")) {
|
|
DrawTextFitKD(TextGet("KinkyDungeonEasyModeDesc2"), 1250, 80, 1000, "#ffffff", KDTextGray0);
|
|
}
|
|
|
|
if (KinkyDungeonSexyMode) {
|
|
|
|
DrawCheckboxKDEx("KinkyDungeonSexyPlugs", (bdata) => {
|
|
KinkyDungeonSexyPlug = !KinkyDungeonSexyPlug;
|
|
localStorage.setItem("KinkyDungeonSexyPlug", KinkyDungeonSexyPlug ? "True" : "False");
|
|
return true;
|
|
}, true, 1500, 350, 64, 64, TextGet("KinkyDungeonSexyPlugs"), KinkyDungeonSexyPlug, false, "#ffffff");
|
|
|
|
DrawCheckboxKDEx("KinkyDungeonSexyPiercings", (bdata) => {
|
|
KinkyDungeonSexyPiercing = !KinkyDungeonSexyPiercing;
|
|
localStorage.setItem("KinkyDungeonSexyPiercing", KinkyDungeonSexyPiercing ? "True" : "False");
|
|
return true;
|
|
}, true, 1500, 430, 64, 64, TextGet("KinkyDungeonSexyPiercings"), KinkyDungeonSexyPiercing, false, "#ffffff");
|
|
}
|
|
|
|
|
|
} else if (KinkyDungeonState == "Wardrobe") {
|
|
KDDrawWardrobe("menu");
|
|
} else if (KinkyDungeonState == "Stats") {
|
|
|
|
let tooltip = KinkyDungeonDrawPerks(false);
|
|
DrawTextKD(TextGet("KinkyDungeonStats"), 1000, 30, "#ffffff", KDTextGray2);
|
|
DrawTextKD(TextGet("KinkyDungeonStats2"), 1000, 80, "#ffffff", KDTextGray2);
|
|
if (!tooltip) {
|
|
let points = KinkyDungeonGetStatPoints(KinkyDungeonStatsChoice);
|
|
let hardmode = points >= KDHardModeThresh ? TextGet("KDHardMode") : "";
|
|
DrawTextKD(TextGet("KinkyDungeonStatPoints").replace("AMOUNT", "" + points) + hardmode, 1000, 150, "#ffffff", KDTextGray2);
|
|
}
|
|
|
|
DrawButtonKDEx("KDPerksStart", (bdata) => {
|
|
if (KinkyDungeonGetStatPoints(KinkyDungeonStatsChoice) >= 0) {
|
|
//KinkyDungeonState = "Diff";
|
|
KDLose = false;
|
|
KinkyDungeonStartNewGame();
|
|
}
|
|
return true;
|
|
}, true, 875, 920, 350, 64, TextGet("KinkyDungeonStartGame"), KinkyDungeonGetStatPoints(KinkyDungeonStatsChoice) >= 0 ? "#ffffff" : "pink", "");
|
|
|
|
DrawButtonKDEx("KDPerksBack", (bdata) => {
|
|
KinkyDungeonState = "Menu";
|
|
return true;
|
|
}, true, 1275, 920, 350, 64, TextGet("KinkyDungeonLoadBack"), "#ffffff", "");
|
|
|
|
DrawButtonKDEx("KDPerksClear", (bdata) => {
|
|
KinkyDungeonStatsChoice = new Map();
|
|
KDUpdatePlugSettings();
|
|
return true;
|
|
}, true, 40, 920, 190, 64, TextGet("KinkyDungeonClearAll"), "#ffffff", "");
|
|
|
|
DrawButtonKDEx("KDPerkConfig1", (bdata) => {
|
|
KinkyDungeonPerksConfig = "1";
|
|
KinkyDungeonLoadStats();
|
|
KDUpdatePlugSettings();
|
|
return true;
|
|
}, true, 270, 930, 100, 54, TextGet("KinkyDungeonConfig") + "1", KinkyDungeonPerksConfig == "1" ? "#ffffff" : "#888888", "");
|
|
|
|
DrawButtonKDEx("KDPerkConfig2", (bdata) => {
|
|
KinkyDungeonPerksConfig = "2";
|
|
KinkyDungeonLoadStats();
|
|
KDUpdatePlugSettings();
|
|
return true;
|
|
}, true, 380, 930, 100, 54, TextGet("KinkyDungeonConfig") + "2", KinkyDungeonPerksConfig == "2" ? "#ffffff" : "#888888", "");
|
|
|
|
DrawButtonKDEx("KDPerkConfig3", (bdata) => {
|
|
KinkyDungeonPerksConfig = "3";
|
|
KinkyDungeonLoadStats();
|
|
KDUpdatePlugSettings();
|
|
return true;
|
|
}, true, 490, 930, 100, 54, TextGet("KinkyDungeonConfig") + "3", KinkyDungeonPerksConfig == "3" ? "#ffffff" : "#888888", "");
|
|
|
|
|
|
let TF = KDTextField("PerksFilter", 600, 930, 210, 54, "text", "", "45");
|
|
if (TF.Created) {
|
|
|
|
TF.Element.oninput = (event) => {
|
|
KDPerksFilter = ElementValue("PerksFilter");
|
|
};
|
|
}
|
|
DrawTextFitKD(TextGet("KinkyDungeonFilter"), 600 + 210/2, 930 + 54/2, 210, "#aaaaaa");
|
|
|
|
|
|
DrawButtonKDEx("copyperks", (bdata) => {
|
|
let txt = "";
|
|
for (let k of KinkyDungeonStatsChoice.keys()) {
|
|
if (!k.startsWith("arousal") && !k.endsWith("Mode")) txt += (txt ? "\n" : "") + k;
|
|
}
|
|
navigator.clipboard.writeText(txt);
|
|
return true;
|
|
}, true, 1850, 930, 140, 54, TextGet("KinkyDungeonCopyPerks"), "#ffffff", "");
|
|
|
|
|
|
DrawButtonKDEx("pasteperks", (bdata) => {
|
|
navigator.clipboard.readText()
|
|
.then(text => {
|
|
let list = text.split('\n');
|
|
let changed = 1;
|
|
let iter = 0;
|
|
while (changed > 0 && iter < 1000) {
|
|
changed = 0;
|
|
for (let l of list) {
|
|
let lp = l.replace('\r','');// List processed
|
|
// Find the perk that matches the name
|
|
for (let perk of Object.entries(KinkyDungeonStatsPresets)) {
|
|
if (perk[0] == lp && KDValidatePerk(perk[1])) {
|
|
KinkyDungeonStatsChoice.set(perk[0], true);
|
|
changed += 1;
|
|
}// else if (KinkyDungeonStatsChoice.get(perk[0])) KinkyDungeonStatsChoice.delete(perk[0])
|
|
}
|
|
}
|
|
iter += 1;
|
|
}
|
|
})
|
|
.catch(err => {
|
|
console.error('Failed to read clipboard contents: ', err);
|
|
});
|
|
return true;
|
|
}, true, 1700, 930, 140, 54, TextGet("KinkyDungeonPastePerks"), "#ffffff", "");
|
|
|
|
|
|
if (KinkyDungeonKeybindingCurrentKey && KinkyDungeonGameKeyDown()) {
|
|
if (KinkyDungeonKeybindingCurrentKey)
|
|
KDLastKeyTime[KinkyDungeonKeybindingCurrentKey] = CommonTime();
|
|
KinkyDungeonKeybindingCurrentKey = '';
|
|
}
|
|
} else if (KinkyDungeonState == "Save") {
|
|
// Draw temp start screen
|
|
DrawTextKD(TextGet("KinkyDungeonSaveIntro0"), 1250, 350, "#ffffff", KDTextGray2);
|
|
DrawTextKD(TextGet("KinkyDungeonSaveIntro"), 1250, 475, "#ffffff", KDTextGray2);
|
|
DrawTextKD(TextGet("KinkyDungeonSaveIntro2"), 1250, 550, "#ffffff", KDTextGray2);
|
|
DrawTextKD(TextGet("KinkyDungeonSaveIntro3"), 1250, 625, "#ffffff", KDTextGray2);
|
|
DrawTextKD(TextGet("KinkyDungeonSaveIntro4"), 1250, 700, "#ffffff", KDTextGray2);
|
|
|
|
ElementPosition("saveDataField", 1250, 150, 1000, 230);
|
|
|
|
//DrawButtonVis(875, 750, 350, 64, TextGet("KinkyDungeonGameSave"), "#ffffff", "");
|
|
DrawButtonVis(1075, 750, 350, 64, TextGet("KinkyDungeonGameContinue"), "#ffffff", "");
|
|
} else if (KinkyDungeonState == "Game") {
|
|
KinkyDungeonGameRunning = true;
|
|
KinkyDungeonGameFlag = true;
|
|
KinkyDungeonDrawGame();
|
|
if (KinkyDungeonInputQueue.length < 1) {
|
|
let _CharacterRefresh = CharacterRefresh;
|
|
let _CharacterAppearanceBuildCanvas = CharacterAppearanceBuildCanvas;
|
|
// @ts-expect-error
|
|
CharacterRefresh = () => {KDRefresh = true;};
|
|
// @ts-expect-error
|
|
CharacterAppearanceBuildCanvas = () => {};
|
|
|
|
|
|
if (KDGameData.SleepTurns > 0) {
|
|
if (CommonTime() > KinkyDungeonSleepTime) {
|
|
KDGameData.SleepTurns -= 1;
|
|
if (KinkyDungeonAggressive())
|
|
KinkyDungeonTotalSleepTurns += 1;
|
|
if (KinkyDungeonStatStamina >= KinkyDungeonStatStaminaMax && KinkyDungeonStatWill >= KinkyDungeonStatWillMax) {
|
|
KDGameData.SleepTurns = 0;
|
|
}
|
|
// Decrease offer fatigue
|
|
KDIncreaseOfferFatigue(-1);
|
|
KDSendInput("tick", {delta: 1, sleep: true}, false, true);
|
|
KinkyDungeonSleepTime = CommonTime() + 10;
|
|
}
|
|
if (KDGameData.SleepTurns == 0) {
|
|
KinkyDungeonChangeStamina(0);
|
|
KinkyDungeonChangeWill(0);
|
|
KDGameData.KneelTurns = 1;
|
|
}
|
|
} else if (KDGameData.PlaySelfTurns > 0) {
|
|
if (CommonTime() > KinkyDungeonSleepTime) {
|
|
KDSendInput("tick", {delta: 1}, false, true);
|
|
KDGameData.PlaySelfTurns -= 1;
|
|
KinkyDungeonSleepTime = CommonTime() + (KinkyDungeonFlags.get("PlayerOrgasm") ? KinkyDungeonOrgasmTime : KinkyDungeonPlaySelfTime) * (0.25 + KDAnimSpeed * 0.75);
|
|
}
|
|
if (KDGameData.SleepTurns == 0) {
|
|
KinkyDungeonChangeStamina(0);
|
|
}
|
|
} else if (KinkyDungeonStatFreeze > 0) {
|
|
if (CommonTime() > KinkyDungeonSleepTime) {
|
|
KinkyDungeonStatFreeze -= 1;
|
|
KDSendInput("tick", {delta: 1, NoUpdate: false, NoMsgTick: true}, false, true);
|
|
KinkyDungeonSleepTime = CommonTime() + KinkyDungeonFreezeTime * (0.25 + KDAnimSpeed * 0.75);
|
|
}
|
|
} else if (KinkyDungeonSlowMoveTurns > 0) {
|
|
if (CommonTime() > KinkyDungeonSleepTime) {
|
|
KinkyDungeonSlowMoveTurns -= 1;
|
|
KDSendInput("tick", {delta: 1, NoUpdate: false, NoMsgTick: true}, false, true);
|
|
KinkyDungeonSleepTime = CommonTime() + 150 * (0.25 + KDAnimSpeed * 0.75);
|
|
}
|
|
} else if (KinkyDungeonFastMove && KinkyDungeonFastMovePath && KinkyDungeonFastMovePath.length > 0) {
|
|
if (CommonTime() > KinkyDungeonSleepTime) {
|
|
if (KinkyDungeonFastMovePath.length > 0) {
|
|
let next = KinkyDungeonFastMovePath[0];
|
|
KinkyDungeonFastMovePath.splice(0, 1);
|
|
if (Math.max(Math.abs(next.x-KinkyDungeonPlayerEntity.x), Math.abs(next.y-KinkyDungeonPlayerEntity.y)) < 1.5)
|
|
KDSendInput("move", {dir: {x:next.x-KinkyDungeonPlayerEntity.x, y:next.y-KinkyDungeonPlayerEntity.y}, delta: 1, AllowInteract: true, AutoDoor: KinkyDungeonToggleAutoDoor, AutoPass: KinkyDungeonToggleAutoPass, sprint: KinkyDungeonToggleAutoSprint, SuppressSprint: KinkyDungeonSuppressSprint}, false, true);
|
|
else KinkyDungeonFastMovePath = [];
|
|
}
|
|
KinkyDungeonSleepTime = CommonTime() + 100 * (0.25 + KDAnimSpeed * 0.75);
|
|
}
|
|
} else if (KinkyDungeonFastStruggle && KinkyDungeonFastStruggleType && KinkyDungeonFastStruggleGroup) {
|
|
if (CommonTime() > KinkyDungeonSleepTime) {
|
|
let result = KDSendInput("struggle", {group: KinkyDungeonFastStruggleGroup, type: KinkyDungeonFastStruggleType}, false, true);
|
|
if (result != "Fail" || !KinkyDungeonHasStamina(2.5)) {
|
|
KinkyDungeonFastStruggleType = "";
|
|
KinkyDungeonFastStruggleGroup = "";
|
|
}
|
|
KinkyDungeonSleepTime = CommonTime() + 250 * (0.25 + KDAnimSpeed * 0.75);
|
|
}
|
|
} else if (KinkyDungeonAutoWait) {
|
|
if (CommonTime() > KinkyDungeonSleepTime) {
|
|
let lastStamina = KinkyDungeonStatStamina;
|
|
KDSendInput("move", {dir: {x:0, y: 0, delta: 0}, delta: 1, AllowInteract: true, AutoDoor: KinkyDungeonToggleAutoDoor, AutoPass: KinkyDungeonToggleAutoPass, sprint: KinkyDungeonToggleAutoSprint, SuppressSprint: KinkyDungeonSuppressSprint}, false, true);
|
|
if (KinkyDungeonFastStruggle && KinkyDungeonStatStamina == KinkyDungeonStatStaminaMax && lastStamina < KinkyDungeonStatStamina) {
|
|
if (KinkyDungeonTempWait && !KDGameData.KinkyDungeonLeashedPlayer && !KinkyDungeonInDanger())
|
|
KDDisableAutoWait();
|
|
}
|
|
KinkyDungeonSleepTime = CommonTime() + (KinkyDungeonFastWait ? 100 : 300);
|
|
}
|
|
} else if (KinkyDungeonAutoWaitStruggle) {
|
|
if (CommonTime() > KinkyDungeonSleepTime) {
|
|
//KDSendInput("move", {dir: {x:0, y: 0, delta: 0}, delta: 1, AllowInteract: true, AutoDoor: KinkyDungeonToggleAutoDoor, AutoPass: KinkyDungeonToggleAutoPass, sprint: KinkyDungeonToggleAutoSprint, SuppressSprint: KinkyDungeonSuppressSprint}, false, true);
|
|
|
|
if (!(KDGameData.DelayedActions?.length > 0)) {
|
|
KDHandleAutoStruggle(KinkyDungeonPlayerEntity);
|
|
}
|
|
if (KinkyDungeonInDanger())
|
|
KDDisableAutoWait();
|
|
KinkyDungeonSleepTime = CommonTime() + (300 + Math.min(1200, KDAutoStruggleData.lastDelay * 270)) * (0.5 + KDAnimSpeed * 0.5);
|
|
}
|
|
} else KinkyDungeonSleepTime = CommonTime() + 100;
|
|
// @ts-expect-error
|
|
CharacterRefresh = _CharacterRefresh;
|
|
// @ts-expect-error
|
|
CharacterAppearanceBuildCanvas = _CharacterAppearanceBuildCanvas;
|
|
} else KinkyDungeonSleepTime = CommonTime() + 100;
|
|
|
|
} else if (KinkyDungeonState == "End") {
|
|
KinkyDungeonGameRunning = false;
|
|
// Draw temp start screen
|
|
DrawTextKD(TextGet("EndWin"), 1250, 400, "#ffffff", KDTextGray2);
|
|
DrawTextKD(TextGet("EndWin2"), 1250, 500, "#ffffff", KDTextGray2);
|
|
|
|
DrawButtonVis(1075, 650, 350, 64, TextGet("KinkyDungeonNewGamePlus"), "#ffffff", "");
|
|
DrawButtonVis(1075, 750, 350, 64, TextGet("GameReturnToMenu"), "#ffffff", "");
|
|
} else if (KinkyDungeonState == "Keybindings") {
|
|
// Draw temp start screen
|
|
DrawButtonKDEx("KBBack", () => {
|
|
KinkyDungeonKeybindings = KinkyDungeonKeybindingsTemp;
|
|
if (KinkyDungeonGameFlag) {
|
|
KinkyDungeonState = "Game";
|
|
if (KinkyDungeonKeybindings) {
|
|
KDCommitKeybindings();
|
|
}
|
|
} else KinkyDungeonState = "Menu";
|
|
localStorage.setItem("KinkyDungeonKeybindings", JSON.stringify(KinkyDungeonKeybindings));
|
|
//ServerAccountUpdate.QueueData({ KinkyDungeonKeybindings: KinkyDungeonKeybindings });
|
|
return true;
|
|
}, true, 1450, 780, 350, 64, TextGet("GameReturnToMenu"), "#ffffff", "");
|
|
|
|
// Draw temp start screen
|
|
DrawButtonKDEx("KBBack2", () => {
|
|
KinkyDungeonKeybindingsTemp = Object.assign({}, KinkyDungeonKeybindingsTemp);
|
|
if (KinkyDungeonGameFlag) {
|
|
KinkyDungeonState = "Game";
|
|
} else KinkyDungeonState = "Menu";
|
|
//ServerAccountUpdate.QueueData({ KinkyDungeonKeybindings: KinkyDungeonKeybindings });
|
|
return true;
|
|
}, true, 1450, 700, 350, 64, TextGet("GameReturnToMenu2"), "#ffffff", "");
|
|
|
|
// Draw key buttons
|
|
DrawButtonKDEx("KBUp", () => {KinkyDungeonKeybindingsTemp.Up = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1075, 100, 300, 50, TextGet("KinkyDungeonKeyUp") + ": '" + (KinkyDungeonKeybindingsTemp.Up) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBDown", () => {KinkyDungeonKeybindingsTemp.Down = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1075, 160, 300, 50, TextGet("KinkyDungeonKeyDown") + ": '" + (KinkyDungeonKeybindingsTemp.Down) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBLeft", () => {KinkyDungeonKeybindingsTemp.Left = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1075, 220, 300, 50, TextGet("KinkyDungeonKeyLeft") + ": '" + (KinkyDungeonKeybindingsTemp.Left) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBRight", () => {KinkyDungeonKeybindingsTemp.Right = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1075, 280, 300, 50, TextGet("KinkyDungeonKeyRight") + ": '" + (KinkyDungeonKeybindingsTemp.Right) + "'", "#ffffff", "");
|
|
|
|
DrawButtonKDEx("KBUpLleft", () => {KinkyDungeonKeybindingsTemp.UpLeft = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1075, 340, 300, 50, TextGet("KinkyDungeonKeyUpLeft") + ": '" + (KinkyDungeonKeybindingsTemp.UpLeft) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBUpRight", () => {KinkyDungeonKeybindingsTemp.UpRight = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1075, 400, 300, 50, TextGet("KinkyDungeonKeyUpRight") + ": '" + (KinkyDungeonKeybindingsTemp.UpRight) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBDownLeft", () => {KinkyDungeonKeybindingsTemp.DownLeft = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1075, 460, 300, 50, TextGet("KinkyDungeonKeyDownLeft") + ": '" + (KinkyDungeonKeybindingsTemp.DownLeft) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBDownRight", () => {KinkyDungeonKeybindingsTemp.DownRight = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1075, 520, 300, 50, TextGet("KinkyDungeonKeyDownRight") + ": '" + (KinkyDungeonKeybindingsTemp.DownRight) + "'", "#ffffff", "");
|
|
|
|
DrawButtonKDEx("KBWait", () => {KinkyDungeonKeybindingsTemp.Wait = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1075, 600, 300, 50, TextGet("KinkyDungeonKeyWait") + ": '" + (KinkyDungeonKeybindingsTemp.Wait) + "'", "#ffffff", "");
|
|
|
|
DrawButtonKDEx("KBSpell1", () => {KinkyDungeonKeybindingsTemp.Spell1 = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 100, 300, 50, TextGet("KinkyDungeonKeySpell1") + ": '" + (KinkyDungeonKeybindingsTemp.Spell1) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBSpell2", () => {KinkyDungeonKeybindingsTemp.Spell2 = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 160, 300, 50, TextGet("KinkyDungeonKeySpell2") + ": '" + (KinkyDungeonKeybindingsTemp.Spell2) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBSpell3", () => {KinkyDungeonKeybindingsTemp.Spell3 = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 220, 300, 50, TextGet("KinkyDungeonKeySpell3") + ": '" + (KinkyDungeonKeybindingsTemp.Spell3) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBSpell4", () => {KinkyDungeonKeybindingsTemp.Spell4 = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 280, 300, 50, TextGet("KinkyDungeonKeySpell4") + ": '" + (KinkyDungeonKeybindingsTemp.Spell4) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBSpell5", () => {KinkyDungeonKeybindingsTemp.Spell5 = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 340, 300, 50, TextGet("KinkyDungeonKeySpell5") + ": '" + (KinkyDungeonKeybindingsTemp.Spell5) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBSpell6", () => {KinkyDungeonKeybindingsTemp.Spell6 = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 400, 300, 50, TextGet("KinkyDungeonKeySpell6") + ": '" + (KinkyDungeonKeybindingsTemp.Spell6) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBSpell7", () => {KinkyDungeonKeybindingsTemp.Spell7 = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 460, 300, 50, TextGet("KinkyDungeonKeySpell7") + ": '" + (KinkyDungeonKeybindingsTemp.Spell7) + "'", "#ffffff", "");
|
|
|
|
DrawButtonKDEx("KBSpellPage", () => {KinkyDungeonKeybindingsTemp.SpellPage = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 520, 300, 50, TextGet("KinkyDungeonKeySpellPage") + ": '" + (KinkyDungeonKeybindingsTemp.SpellPage) + "'", "#ffffff", "");
|
|
|
|
DrawButtonKDEx("KBUpcast", () => {KinkyDungeonKeybindingsTemp.Upcast = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 580, 300, 50, TextGet("KinkyDungeonKeyUpcast") + ": '" + (KinkyDungeonKeybindingsTemp.Upcast) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBUpcastCancel", () => {KinkyDungeonKeybindingsTemp.UpcastCancel = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 640, 300, 50, TextGet("KinkyDungeonKeyUpcastCancel") + ": '" + (KinkyDungeonKeybindingsTemp.UpcastCancel) + "'", "#ffffff", "");
|
|
|
|
DrawButtonKDEx("KBSwitchWeapon", () => {KinkyDungeonKeybindingsTemp.SwitchWeapon = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 700, 300, 50, TextGet("KinkyDungeonKeySwitchWeapon") + ": '" + (KinkyDungeonKeybindingsTemp.SwitchWeapon) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBSpellWeapon", () => {KinkyDungeonKeybindingsTemp.SpellWeapon = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
675, 760, 300, 50, TextGet("KinkyDungeonKeySpellWeapon") + ": '" + (KinkyDungeonKeybindingsTemp.SpellWeapon) + "'", "#ffffff", "");
|
|
|
|
DrawButtonKDEx("KBSkip", () => {KinkyDungeonKeybindingsTemp.Skip = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1075, 680, 300, 50, TextGet("KinkyDungeonKeySkip") + ": '" + (KinkyDungeonKeybindingsTemp.Skip) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBEnter", () => {KinkyDungeonKeybindingsTemp.Enter = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1075, 740, 300, 50, TextGet("KinkyDungeonKeyEnter") + ": '" + (KinkyDungeonKeybindingsTemp.Enter) + "'", "#ffffff", "");
|
|
|
|
|
|
DrawButtonKDEx("KBMsgLog", () => {KinkyDungeonKeybindingsTemp.MsgLog = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 100, 300, 38, TextGet("KinkyDungeonKeyMsgLog") + ": '" + (KinkyDungeonKeybindingsTemp.MsgLog) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBDoor", () => {KinkyDungeonKeybindingsTemp.Door = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 145, 300, 38, TextGet("KinkyDungeonKeyDoor") + ": '" + (KinkyDungeonKeybindingsTemp.Door) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBPass", () => {KinkyDungeonKeybindingsTemp.Pass = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 190, 300, 38, TextGet("KinkyDungeonKeyPass") + ": '" + (KinkyDungeonKeybindingsTemp.Pass) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBAStruggle", () => {KinkyDungeonKeybindingsTemp.AStruggle = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 235, 300, 38, TextGet("KinkyDungeonKeyAStruggle") + ": '" + (KinkyDungeonKeybindingsTemp.AStruggle) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBAPathfind", () => {KinkyDungeonKeybindingsTemp.APathfind = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 280, 300, 38, TextGet("KinkyDungeonKeyAPathfind") + ": '" + (KinkyDungeonKeybindingsTemp.APathfind) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBASprint", () => {KinkyDungeonKeybindingsTemp.Sprint = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 325, 300, 38, TextGet("KinkyDungeonKeySprint") + ": '" + (KinkyDungeonKeybindingsTemp.Sprint) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBInspect", () => {KinkyDungeonKeybindingsTemp.AInspect = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 370, 300, 38, TextGet("KinkyDungeonKeyInspect") + ": '" + (KinkyDungeonKeybindingsTemp.AInspect) + "'", "#ffffff", "");
|
|
|
|
DrawButtonKDEx("KBQInventory", () => {KinkyDungeonKeybindingsTemp.QInventory = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 425, 300, 45, TextGet("KinkyDungeonKeyQInventory") + ": '" + (KinkyDungeonKeybindingsTemp.QInventory) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBInventory", () => {KinkyDungeonKeybindingsTemp.Inventory = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 475, 300, 45, TextGet("KinkyDungeonKeyInventory") + ": '" + (KinkyDungeonKeybindingsTemp.Inventory) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBReputation", () => {KinkyDungeonKeybindingsTemp.Reputation = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 525, 300, 45, TextGet("KinkyDungeonKeyReputation") + ": '" + (KinkyDungeonKeybindingsTemp.Reputation) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBMagic", () => {KinkyDungeonKeybindingsTemp.Magic = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 575, 300, 45, TextGet("KinkyDungeonKeyMagic") + ": '" + (KinkyDungeonKeybindingsTemp.Magic) + "'", "#ffffff", "");
|
|
DrawButtonKDEx("KBLog", () => {KinkyDungeonKeybindingsTemp.Log = KinkyDungeonKeybindingCurrentKey; return true;}, KinkyDungeonKeybindingCurrentKey != '',
|
|
1475, 625, 300, 45, TextGet("KinkyDungeonKeyLog") + ": '" + (KinkyDungeonKeybindingsTemp.Log) + "'", "#ffffff", "");
|
|
|
|
if (KinkyDungeonKeybindingCurrentKey)
|
|
DrawTextKD(TextGet("KinkyDungeonCurrentPress") + ": '" + (KinkyDungeonKeybindingCurrentKey) + "'", 1250, 900, "#ffffff", KDTextGray2);
|
|
|
|
DrawTextKD(TextGet("KinkyDungeonCurrentPressInfo"), 1250, 950, "#ffffff", KDTextGray2);
|
|
} else if (KinkyDungeonState == "Toggles") {
|
|
|
|
let XX = 840;
|
|
let YYstart = 200;
|
|
let YYmax = 680;
|
|
let YY = YYstart;
|
|
let YYd = 70;
|
|
let XXd = 400;
|
|
let toggles = Object.keys(KDToggles);
|
|
//MainCanvas.textAlign = "left";
|
|
for (let toggle of toggles) {
|
|
// Draw temp start screen
|
|
DrawCheckboxKDEx("toggle" + toggle, () => {
|
|
KDToggles[toggle] = !KDToggles[toggle];
|
|
KDSaveToggles();
|
|
return true;
|
|
}, true, XX, YY, 64, 64, TextGet("KDToggle" + toggle), KDToggles[toggle], false, "#ffffff", undefined, {
|
|
maxWidth: 300,
|
|
});
|
|
|
|
YY += YYd;
|
|
if (YY > YYmax) {
|
|
YY = YYstart;
|
|
XX += XXd;
|
|
}
|
|
}
|
|
//MainCanvas.textAlign = "center";
|
|
|
|
YY = YYstart;
|
|
|
|
if (StandalonePatched) {
|
|
DrawBackNextButtonVis(450, YY, 350, 64, TextGet("KDResolution" + (KDResolutionConfirm ? "Confirm" : "")) + " " + Math.round(KDResolution * 100) + "%", "#ffffff", "",
|
|
() => KDResolutionList[(KDResolutionListIndex + KDResolutionList.length - 1) % KDResolutionList.length] * 100 + "%",
|
|
() => KDResolutionList[(KDResolutionListIndex + 1) % KDResolutionList.length] * 100 + "%");
|
|
YY += YYd * 2;
|
|
}
|
|
|
|
DrawBackNextButtonVis(450, YY, 350, 64, TextGet("KDVibeVolume") + " " + (KDVibeVolume * 100 + "%"), "#ffffff", "",
|
|
() => KDVibeVolumeList[(KDVibeVolumeListIndex + KDVibeVolumeList.length - 1) % KDVibeVolumeList.length] * 100 + "%",
|
|
() => KDVibeVolumeList[(KDVibeVolumeListIndex + 1) % KDVibeVolumeList.length] * 100 + "%");
|
|
YY += YYd;
|
|
DrawBackNextButtonVis(450, YY, 350, 64, TextGet("KDMusicVolume") + " " + (KDMusicVolume * 100 + "%"), "#ffffff", "",
|
|
() => KDMusicVolumeList[(KDMusicVolumeListIndex + KDMusicVolumeList.length - 1) % KDMusicVolumeList.length] * 100 + "%",
|
|
() => KDMusicVolumeList[(KDMusicVolumeListIndex + 1) % KDMusicVolumeList.length] * 100 + "%");
|
|
YY += YYd;
|
|
DrawBackNextButtonVis(450, YY, 350, 64, TextGet("KDSfxVolume") + " " + (KDSfxVolume * 100 + "%"), "#ffffff", "",
|
|
() => KDSfxVolumeList[(KDSfxVolumeListIndex + KDSfxVolumeList.length - 1) % KDSfxVolumeList.length] * 100 + "%",
|
|
() => KDSfxVolumeList[(KDSfxVolumeListIndex + 1) % KDSfxVolumeList.length] * 100 + "%");
|
|
YY += YYd;
|
|
DrawBackNextButtonVis(450, YY, 350, 64, TextGet("KDAnimSpeed") + " " + (KDAnimSpeed * 100 + "%"), "#ffffff", "",
|
|
() => KDAnimSpeedList[(KDAnimSpeedListIndex + KDAnimSpeedList.length - 1) % KDAnimSpeedList.length] * 100 + "%",
|
|
() => KDAnimSpeedList[(KDAnimSpeedListIndex + 1) % KDAnimSpeedList.length] * 100 + "%");
|
|
YY += YYd;
|
|
|
|
|
|
|
|
|
|
DrawButtonKDEx("KBBackOptions", () => {
|
|
KinkyDungeonKeybindingsTemp = Object.assign({}, KinkyDungeonKeybindingsTemp);
|
|
if (KinkyDungeonGameFlag) {
|
|
KinkyDungeonState = "Game";
|
|
} else KinkyDungeonState = "Menu";
|
|
//ServerAccountUpdate.QueueData({ KinkyDungeonKeybindings: KinkyDungeonKeybindings });
|
|
return true;
|
|
}, true, 975, 780, 550, 64, TextGet("GameReturnToMenuFromOptions"), "#ffffff", "");
|
|
|
|
}
|
|
|
|
// Cull temp elements
|
|
KDCullTempElements();
|
|
|
|
//if (KDDebugMode) {
|
|
//DrawTextKD(dispfps, 20, 20, "#ffffff", undefined, undefined, "left");
|
|
//}
|
|
// Cull the sprites that werent rendered or updated this frame
|
|
KDCullSprites();
|
|
|
|
if (!StandalonePatched) {
|
|
if (!pixiview) pixiview = KinkyDungeonGetCanvas("MainCanvas");
|
|
if (!pixirenderer) {
|
|
if (pixiview) {
|
|
pixirenderer = new PIXI.CanvasRenderer({
|
|
width: pixiview.width,
|
|
height: pixiview.height,
|
|
view: pixiview,
|
|
antialias: true,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
KDDrawDelta = performance.now() - lastfps;
|
|
fpscounter++;
|
|
if (fpscounter > 10) {
|
|
fpscounter = 0;
|
|
dispfps = Math.round(1000 / Math.max(KDDrawDelta, 1));
|
|
}
|
|
|
|
lastfps = performance.now();
|
|
KDUpdateParticles(KDDrawDelta);
|
|
|
|
if (StandalonePatched) {
|
|
/*if (KinkyDungeonState == "Game") {
|
|
if (!kdTrackGameParticles) {
|
|
kdcanvas.addChild(kdparticles);
|
|
kdTrackGameParticles = true;
|
|
}
|
|
} else {
|
|
if (kdTrackGameParticles) {
|
|
kdcanvas.removeChild(kdparticles);
|
|
kdTrackGameParticles = false;
|
|
}
|
|
}*/
|
|
} else {
|
|
// Draw the context layer even if we haven't updated it
|
|
if (pixirenderer) {
|
|
pixirenderer.render(kdcanvas, {
|
|
clear: false,
|
|
});
|
|
pixirenderer.render(kdui, {
|
|
clear: false,
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//MainCanvas.textBaseline = "middle";
|
|
|
|
KDLastButtonsCache = {};
|
|
MouseClicked = false;
|
|
|
|
if ((!KDDebugMode && KinkyDungeonDrawState == "Restart") || (KDDebugMode && (KinkyDungeonDrawState != "Restart" || KinkyDungeonState != "Game"))) {
|
|
ElementRemove("DebugEnemy");
|
|
ElementRemove("DebugItem");
|
|
}
|
|
}
|
|
|
|
let KDDrawDelta = 0;
|
|
|
|
let kdTrackGameBoard = false;
|
|
let kdTrackGameFog = false;
|
|
let kdTrackGameParticles = false;
|
|
|
|
function KDCullSprites() {
|
|
for (let sprite of kdpixisprites.entries()) {
|
|
if (!kdSpritesDrawn.has(sprite[0])) {
|
|
sprite[1].parent.removeChild(sprite[1]);
|
|
if (kdprimitiveparams.has(sprite[0])) kdprimitiveparams.delete(sprite[0]);
|
|
kdpixisprites.delete(sprite[0]);
|
|
sprite[1].destroy();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @type {Record<string, {Left: number, Top: number, Width: number, Height: number, enabled: boolean, func?: (bdata: any) => boolean}>}
|
|
*/
|
|
let KDButtonsCache = {
|
|
|
|
};
|
|
/**
|
|
* @type {Record<string, {Left: number, Top: number, Width: number, Height: number, enabled: boolean, func?: (bdata: any) => boolean}>}
|
|
*/
|
|
let KDLastButtonsCache = {
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Draws a button component
|
|
* @param {string} name - Name of the button element
|
|
* @param {boolean} enabled - Whether or not you can click on it
|
|
* @param {number} Left - Position of the component from the left of the canvas
|
|
* @param {number} Top - Position of the component from the top of the canvas
|
|
* @param {number} Width - Width of the component
|
|
* @param {number} Height - Height of the component
|
|
* @param {string} Label - Text to display in the button
|
|
* @param {string} Color - Color of the component
|
|
* @param {string} [Image] - URL of the image to draw inside the button, if applicable
|
|
* @param {string} [HoveringText] - Text of the tooltip, if applicable
|
|
* @param {boolean} [Disabled] - Disables the hovering options if set to true
|
|
* @param {boolean} [NoBorder] - Disables the border and stuff
|
|
* @returns {void} - Nothing
|
|
*/
|
|
function DrawButtonKD(name, enabled, Left, Top, Width, Height, Label, Color, Image, HoveringText, Disabled, NoBorder) {
|
|
DrawButtonVis(Left, Top, Width, Height, Label, Color, Image, HoveringText, Disabled, NoBorder);
|
|
KDButtonsCache[name] = {
|
|
Left,
|
|
Top,
|
|
Width,
|
|
Height,
|
|
enabled,
|
|
};
|
|
}
|
|
|
|
|
|
/**
|
|
* Draws a button component
|
|
* @param {string} name - Name of the button element
|
|
* @param {(bdata: any) => boolean} func - Whether or not you can click on it
|
|
* @param {boolean} enabled - Whether or not you can click on it
|
|
* @param {number} Left - Position of the component from the left of the canvas
|
|
* @param {number} Top - Position of the component from the top of the canvas
|
|
* @param {number} Width - Width of the component
|
|
* @param {number} Height - Height of the component
|
|
* @param {string} Label - Text to display in the button
|
|
* @param {string} Color - Color of the component
|
|
* @param {string} [Image] - URL of the image to draw inside the button, if applicable
|
|
* @param {string} [HoveringText] - Text of the tooltip, if applicable
|
|
* @param {boolean} [Disabled] - Disables the hovering options if set to true
|
|
* @param {boolean} [NoBorder] - Disables border
|
|
* @param {string} [FillColor] - BG color
|
|
* @param {number} [FontSize] - Font size
|
|
* @param {boolean} [ShiftText] - Shift text to make room for the button
|
|
* @param {object} [options] - Additional options
|
|
* @param {boolean} [options.noTextBG] - Dont show text backgrounds
|
|
* @param {number} [options.alpha] - Dont show text backgrounds
|
|
* @param {number} [options.zIndex] - zIndex
|
|
* @param {boolean} [options.scaleImage] - zIndex
|
|
* @returns {void} - Nothing
|
|
*/
|
|
function DrawButtonKDEx(name, func, enabled, Left, Top, Width, Height, Label, Color, Image, HoveringText, Disabled, NoBorder, FillColor, FontSize, ShiftText, options) {
|
|
DrawButtonVis(Left, Top, Width, Height, Label, Color, Image, HoveringText, Disabled, NoBorder, FillColor, FontSize, ShiftText, undefined, options?.zIndex, options);
|
|
KDButtonsCache[name] = {
|
|
Left,
|
|
Top,
|
|
Width,
|
|
Height,
|
|
enabled,
|
|
func,
|
|
};
|
|
}
|
|
|
|
|
|
/**
|
|
* Draws a button component
|
|
* @param {any} Container - Container to draw to
|
|
* @param {string} name - Name of the button element
|
|
* @param {(bdata: any) => boolean} func - Whether or not you can click on it
|
|
* @param {boolean} enabled - Whether or not you can click on it
|
|
* @param {number} Left - Position of the component from the left of the canvas
|
|
* @param {number} Top - Position of the component from the top of the canvas
|
|
* @param {number} Width - Width of the component
|
|
* @param {number} Height - Height of the component
|
|
* @param {string} Label - Text to display in the button
|
|
* @param {string} Color - Color of the component
|
|
* @param {string} [Image] - URL of the image to draw inside the button, if applicable
|
|
* @param {string} [HoveringText] - Text of the tooltip, if applicable
|
|
* @param {boolean} [Disabled] - Disables the hovering options if set to true
|
|
* @param {boolean} [NoBorder] - Disables border
|
|
* @param {string} [FillColor] - BG color
|
|
* @param {number} [FontSize] - Font size
|
|
* @param {boolean} [ShiftText] - Shift text to make room for the button
|
|
* @param {object} [options] - Additional options
|
|
* @param {boolean} [options.noTextBG] - Dont show text backgrounds
|
|
* @param {number} [options.alpha] - Dont show text backgrounds
|
|
* @param {number} [options.zIndex] - zIndex
|
|
* @param {boolean} [options.unique] - This button is unique, so X and Y are not differentiators
|
|
* @returns {void} - Nothing
|
|
*/
|
|
function DrawButtonKDExTo(Container, name, func, enabled, Left, Top, Width, Height, Label, Color, Image, HoveringText, Disabled, NoBorder, FillColor, FontSize, ShiftText, options) {
|
|
DrawButtonVisTo(Container, Left, Top, Width, Height, Label, Color, Image, HoveringText, Disabled, NoBorder, FillColor, FontSize, ShiftText, undefined, options?.zIndex, options);
|
|
KDButtonsCache[name] = {
|
|
Left,
|
|
Top,
|
|
Width,
|
|
Height,
|
|
enabled,
|
|
func,
|
|
};
|
|
}
|
|
|
|
function KDProcessButtons() {
|
|
for (let button of Object.entries(KDButtonsCache)) {
|
|
if (button[1].enabled && button[1].func) {
|
|
if (MouseInKD(button[0])) {
|
|
return button[1].func();
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Buttons are clickable one frame later, please factor this in to UI design (especially when enforcing validation)
|
|
* @param {string} name
|
|
* @returns {boolean}
|
|
*/
|
|
function KDClickButton(name) {
|
|
let button = KDButtonsCache[name] || KDLastButtonsCache[name];
|
|
if (button && button.enabled) {
|
|
return button.func();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function MouseInKD(name) {
|
|
let button = KDButtonsCache[name];
|
|
if (button && button.enabled) {
|
|
return MouseIn(button.Left, button.Top, button.Width, button.Height);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function KinkyDungeonGetTraitsCount() {
|
|
return Array.from(KinkyDungeonStatsChoice.keys()).filter((element) => {return !element.includes('arousalMode');}).length;
|
|
}
|
|
|
|
function KDSendTrait(trait) {
|
|
if (window.dataLayer)
|
|
window.dataLayer.push({
|
|
'event':'trait',
|
|
'traitType':trait,
|
|
'journey':KDJourney,
|
|
});
|
|
}
|
|
|
|
function KDSendSpell(spell) {
|
|
if (window.dataLayer)
|
|
window.dataLayer.push({
|
|
'event':'spell',
|
|
'spellType':spell,
|
|
'currentLevel':MiniGameKinkyDungeonLevel,
|
|
'currentCheckpoint':MiniGameKinkyDungeonCheckpoint,
|
|
'journey':KDJourney,
|
|
});
|
|
}
|
|
|
|
function KDSendSpellCast(spell) {
|
|
if (window.dataLayer)
|
|
window.dataLayer.push({
|
|
'event':'spellCast',
|
|
'spellType':spell,
|
|
'currentLevel':MiniGameKinkyDungeonLevel,
|
|
'currentCheckpoint':MiniGameKinkyDungeonCheckpoint,
|
|
'journey':KDJourney,
|
|
});
|
|
}
|
|
function KDSendWeapon(weapon) {
|
|
if (window.dataLayer)
|
|
window.dataLayer.push({
|
|
'event':'weapon',
|
|
'weapon':weapon,
|
|
'currentLevel':MiniGameKinkyDungeonLevel,
|
|
'currentCheckpoint':MiniGameKinkyDungeonCheckpoint,
|
|
'journey':KDJourney,
|
|
});
|
|
}
|
|
|
|
function KDSendStatus(type, data, data2) {
|
|
if (window.dataLayer && !KDOptOut) {
|
|
window.dataLayer.push({
|
|
'event':'gameStatus',
|
|
'currentLevel':MiniGameKinkyDungeonLevel,
|
|
'currentCheckpoint':MiniGameKinkyDungeonCheckpoint,
|
|
'difficulty':KinkyDungeonStatsChoice.get("randomMode"),
|
|
'newgameplus':KinkyDungeonNewGame,
|
|
'statusType':type,
|
|
'aroused':KinkyDungeonStatsChoice.get("arousalMode") ? 'yes' : 'no',
|
|
'traitscount':KinkyDungeonGetTraitsCount(),
|
|
'gold':Math.round(KinkyDungeonGold / 100) * 100,
|
|
'spellType': type == 'learnspell' ? data : undefined,
|
|
'goddess': type == 'goddess' ? data : undefined,
|
|
'helpType': type == 'goddess' ? data2 : undefined,
|
|
'restraint': (type == 'escape' || type == 'bound') ? data : undefined,
|
|
'method': type == 'escape' ? data2 : undefined,
|
|
'attacker': type == 'bound' ? data2 : undefined,
|
|
'prisonerstate': KDGameData.PrisonerState,
|
|
});
|
|
if (type == 'nextLevel' && !KinkyDungeonStatsChoice.get("randomMode")) {
|
|
for (let s of KinkyDungeonSpells) {
|
|
KDSendSpell(s.name);
|
|
}
|
|
KDSendWeapon((KinkyDungeonPlayerDamage && KinkyDungeonPlayerDamage.name) ? KinkyDungeonPlayerDamage.name : 'unarmed');
|
|
}
|
|
}
|
|
}
|
|
function KDSendEvent(type) {
|
|
if (window.dataLayer && !KDOptOut)
|
|
if (type == 'newGame') {
|
|
window.dataLayer.push({
|
|
'event':type,
|
|
'aroused':KinkyDungeonStatsChoice.get("arousalMode") ? 'yes' : 'no',
|
|
'traitscount':KinkyDungeonGetTraitsCount(),
|
|
'journey':KDJourney,
|
|
});
|
|
for (let s of KinkyDungeonStatsChoice.keys()) {
|
|
if (KinkyDungeonStatsChoice.get(s))
|
|
KDSendTrait(s);
|
|
}
|
|
} else if (type == 'jail') {
|
|
window.dataLayer.push({
|
|
'event':type,
|
|
'currentLevel':MiniGameKinkyDungeonLevel,
|
|
'alreadyInJail':KinkyDungeonInJail(KDJailFilters) ? 'true' : 'false',
|
|
'currentCheckpoint':MiniGameKinkyDungeonCheckpoint,
|
|
'difficulty':KinkyDungeonStatsChoice.get("randomMode"),
|
|
'newgameplus':KinkyDungeonNewGame,
|
|
'aroused':KinkyDungeonStatsChoice.get("arousalMode") ? 'yes' : 'no',
|
|
'traitscount':KinkyDungeonGetTraitsCount(),
|
|
'gold':Math.round(KinkyDungeonGold / 100) * 100,
|
|
'journey':KDJourney,
|
|
});
|
|
} else if (type == 'loadGame') {
|
|
window.dataLayer.push({
|
|
'event':type,
|
|
'currentLevel':MiniGameKinkyDungeonLevel,
|
|
'currentCheckpoint':MiniGameKinkyDungeonCheckpoint,
|
|
'difficulty':KinkyDungeonStatsChoice.get("randomMode"),
|
|
'newgameplus':KinkyDungeonNewGame,
|
|
'aroused':KinkyDungeonStatsChoice.get("arousalMode") ? 'yes' : 'no',
|
|
'traitscount':KinkyDungeonGetTraitsCount(),
|
|
'gold':Math.round(KinkyDungeonGold / 100) * 100,
|
|
'journey':KDJourney,
|
|
});
|
|
} else if (type == 'patreon') {
|
|
window.dataLayer.push({
|
|
'event':type,
|
|
});
|
|
} else if (type == 'optout' || type == 'optin') {
|
|
window.dataLayer.push({
|
|
'event':type,
|
|
});
|
|
}
|
|
}
|
|
|
|
function KinkyDungeonLoadStats() {
|
|
KinkyDungeonStatsChoice = new Map();
|
|
let statsChoice = localStorage.getItem('KinkyDungeonStatsChoice' + KinkyDungeonPerksConfig);
|
|
if (statsChoice) {
|
|
let statsArray = JSON.parse(statsChoice);
|
|
if (CommonIsArray(statsArray)) {
|
|
for (let s of statsArray) {
|
|
if (typeof s === "string" && !s.includes('arousalMode') && KinkyDungeonStatsPresets[s] && KDValidatePerk(KinkyDungeonStatsPresets[s]))
|
|
KinkyDungeonStatsChoice.set(s, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let KinkyDungeonGameFlag = false;
|
|
|
|
let KDDefaultJourney = ["grv", "cat", "jng", "tmp", "bel"];
|
|
let KDDefaultAlt = ["tmb", "lib", "cry", "ore", "bel"];
|
|
|
|
function KDInitializeJourney(Journey) {
|
|
/**
|
|
* @type {Record<string, string>}
|
|
*/
|
|
let newIndex = {};
|
|
|
|
for (let map of KDDefaultJourney) {
|
|
newIndex[map] = map;
|
|
}
|
|
for (let map of KDDefaultAlt) {
|
|
newIndex[map] = map;
|
|
}
|
|
|
|
if (Journey)
|
|
KDGameData.Journey = Journey;
|
|
// Option to shuffle the dungeon types besides the initial one (graveyard)
|
|
if (KDGameData.Journey == "Random") {
|
|
/* Randomize array in-place using Durstenfeld shuffle algorithm */
|
|
// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
|
|
let randList = Array.from(Object.keys(newIndex));
|
|
for (let i = randList.length - 1; i >= 0; i--) {
|
|
let j = Math.floor(KDRandom() * (i + 1));
|
|
let temp = randList[i];
|
|
randList[i] = randList[j];
|
|
randList[j] = temp;
|
|
}
|
|
let ii = 0;
|
|
for (let index of Object.keys(newIndex)) {
|
|
newIndex[index] = randList[ii];
|
|
ii++;
|
|
}
|
|
|
|
} else if (KDGameData.Journey == "Harder") {
|
|
for (let i = 0; i < KDDefaultJourney.length; i++) {
|
|
newIndex[KDDefaultAlt[i]] = KDDefaultJourney[i];
|
|
newIndex[KDDefaultJourney[i]] = KDDefaultAlt[i];
|
|
}
|
|
} else if (KDGameData.Journey == "Explorer") {
|
|
newIndex.grv = 'jng';
|
|
newIndex.tmb = 'cry';
|
|
newIndex.cat = 'grv';
|
|
newIndex.lib = 'cat';
|
|
newIndex.jng = 'tmp';
|
|
newIndex.cry = 'lib';
|
|
newIndex.tmp = 'ore';
|
|
newIndex.ore = 'tmb';
|
|
newIndex.bel = 'bel';
|
|
} else if (KDGameData.Journey == "Doll") {
|
|
newIndex.grv = 'tmp';
|
|
newIndex.tmb = 'bel';
|
|
newIndex.cat = 'bel';
|
|
newIndex.lib = 'ore';
|
|
newIndex.jng = 'bel';
|
|
newIndex.cry = 'lib';
|
|
newIndex.tmp = 'cry';
|
|
newIndex.ore = 'tmb';
|
|
newIndex.bel = 'cat';
|
|
} else if (KDGameData.Journey == "Temple") {
|
|
newIndex.grv = 'tmp';
|
|
newIndex.tmb = 'ore';
|
|
newIndex.cat = 'lib';
|
|
newIndex.lib = 'ore';
|
|
newIndex.jng = 'tmb';
|
|
newIndex.cry = 'bel';
|
|
newIndex.tmp = 'cat';
|
|
newIndex.ore = 'cry';
|
|
newIndex.bel = 'jng';
|
|
} else if (KDGameData.Journey == "Test") {
|
|
newIndex.grv = 'bel';
|
|
newIndex.tmb = 'bel';
|
|
}
|
|
|
|
KinkyDungeonMapIndex = newIndex;
|
|
}
|
|
|
|
|
|
|
|
function KDCommitKeybindings() {
|
|
KinkyDungeonKey = [KinkyDungeonKeybindings.Up, KinkyDungeonKeybindings.Left, KinkyDungeonKeybindings.Down, KinkyDungeonKeybindings.Right, KinkyDungeonKeybindings.UpLeft, KinkyDungeonKeybindings.UpRight, KinkyDungeonKeybindings.DownLeft, KinkyDungeonKeybindings.DownRight]; // WASD
|
|
KinkyDungeonGameKey.KEY_UP = (KinkyDungeonKeybindings.Up);
|
|
KinkyDungeonGameKey.KEY_DOWN = (KinkyDungeonKeybindings.Down);
|
|
KinkyDungeonGameKey.KEY_LEFT = (KinkyDungeonKeybindings.Left);
|
|
KinkyDungeonGameKey.KEY_RIGHT = (KinkyDungeonKeybindings.Right);
|
|
KinkyDungeonGameKey.KEY_UPLEFT = (KinkyDungeonKeybindings.UpLeft);
|
|
KinkyDungeonGameKey.KEY_DOWNLEFT = (KinkyDungeonKeybindings.DownLeft);
|
|
KinkyDungeonGameKey.KEY_UPRIGHT = (KinkyDungeonKeybindings.UpRight);
|
|
KinkyDungeonGameKey.KEY_DOWNRIGHT = (KinkyDungeonKeybindings.DownRight);
|
|
|
|
//let KinkyDungeonKeyNumpad = [56, 52, 50, 54, 55, 57, 49, 51]; // Numpad
|
|
KinkyDungeonKeySpell = [
|
|
KinkyDungeonKeybindings.Spell1,
|
|
KinkyDungeonKeybindings.Spell2,
|
|
KinkyDungeonKeybindings.Spell3,
|
|
KinkyDungeonKeybindings.Spell4,
|
|
KinkyDungeonKeybindings.Spell5,
|
|
KinkyDungeonKeybindings.Spell6,
|
|
KinkyDungeonKeybindings.Spell7,
|
|
]; // ! @ #
|
|
KinkyDungeonKeyWait = [KinkyDungeonKeybindings.Wait];
|
|
KinkyDungeonKeySkip = [KinkyDungeonKeybindings.Skip];
|
|
KinkyDungeonKeyUpcast = [KinkyDungeonKeybindings.Upcast, KinkyDungeonKeybindings.UpcastCancel];
|
|
KinkyDungeonKeyWeapon = [KinkyDungeonKeybindings.SpellWeapon]; // 8 (57)
|
|
KinkyDungeonKeyMenu = [
|
|
KinkyDungeonKeybindings.QInventory,
|
|
KinkyDungeonKeybindings.Inventory,
|
|
KinkyDungeonKeybindings.Reputation,
|
|
KinkyDungeonKeybindings.Magic,
|
|
KinkyDungeonKeybindings.Log,
|
|
];
|
|
KinkyDungeonKeyToggle = [
|
|
KinkyDungeonKeybindings.MsgLog,
|
|
KinkyDungeonKeybindings.Pass,
|
|
KinkyDungeonKeybindings.Door,
|
|
KinkyDungeonKeybindings.AStruggle,
|
|
KinkyDungeonKeybindings.APathfind,
|
|
KinkyDungeonKeybindings.AInspect,
|
|
];
|
|
|
|
KinkyDungeonKeyEnter = [KinkyDungeonKeybindings.Enter];
|
|
KinkyDungeonKeySpellPage = [KinkyDungeonKeybindings.SpellPage];
|
|
KinkyDungeonKeySwitchWeapon = [KinkyDungeonKeybindings.SwitchWeapon];
|
|
KinkyDungeonKeySprint = [KinkyDungeonKeybindings.Sprint];
|
|
|
|
KinkyDungeonGameKey.KEY_WAIT = (KinkyDungeonKeybindings.Wait);
|
|
KinkyDungeonGameKey.KEY_SKIP = (KinkyDungeonKeybindings.Skip);
|
|
}
|
|
|
|
let afterLoaded = false;
|
|
|
|
/**
|
|
* Dummy function. You can modify this function as part of your mod like so:
|
|
* function _KDModsAfterLoad = KDModsAfterLoad;
|
|
* KDModsAfterLoad = () => {
|
|
* [Your stuff here]
|
|
* _KDModsAfterLoad();
|
|
* }
|
|
* It is declared with `let` intentionally to allow the above, without suggesting a type error
|
|
*/
|
|
let KDModsAfterLoad = () => {};
|
|
|
|
function KinkyDungeonStartNewGame(Load) {
|
|
KinkyDungeonNewGame = 0;
|
|
let cp = KinkyDungeonMapIndex.grv;
|
|
KinkyDungeonInitialize(1, Load);
|
|
MiniGameKinkyDungeonCheckpoint = "grv";
|
|
KinkyDungeonGrid = "";
|
|
if (Load) {
|
|
KinkyDungeonLoadGame();
|
|
KDSendEvent('loadGame');
|
|
} else {
|
|
KDSendEvent('newGame');
|
|
KDGameData.RoomType = KinkyDungeonStatsChoice.get("easyMode") ? "ShopStart" : "JourneyFloor";
|
|
MiniGameKinkyDungeonLevel = 0;
|
|
KDInitializeJourney("");
|
|
if (KDTileToTest) {
|
|
KinkyDungeonMapIndex.grv = cp;
|
|
}
|
|
}
|
|
if (!KinkyDungeonGrid)
|
|
KinkyDungeonCreateMap(KinkyDungeonMapParams[KinkyDungeonMapIndex[MiniGameKinkyDungeonCheckpoint]], MiniGameKinkyDungeonLevel, false, Load);
|
|
KinkyDungeonState = "Game";
|
|
|
|
if (KinkyDungeonKeybindings) {
|
|
KDCommitKeybindings();
|
|
}
|
|
if (KDToggles.Sound) AudioPlayInstantSoundKD(KinkyDungeonRootDirectory + "Audio/StoneDoor_Close.ogg");
|
|
}
|
|
|
|
function KDUpdatePlugSettings() {
|
|
KinkyDungeonStatsChoice.set("arousalMode", KinkyDungeonSexyMode ? true : undefined);
|
|
KinkyDungeonStatsChoice.set("arousalModePlug", KinkyDungeonSexyPlug ? true : undefined);
|
|
KinkyDungeonStatsChoice.set("arousalModePiercing", KinkyDungeonSexyPiercing ? true : undefined);
|
|
|
|
KinkyDungeonStatsChoice.set("randomMode", KinkyDungeonRandomMode ? true : undefined);
|
|
KinkyDungeonStatsChoice.set("saveMode", KinkyDungeonSaveMode ? true : undefined);
|
|
KinkyDungeonStatsChoice.set("easyMode", KinkyDungeonEasyMode == 1 ? true : undefined);
|
|
KinkyDungeonStatsChoice.set("norescueMode", KinkyDungeonEasyMode == 2 ? true : undefined);
|
|
|
|
|
|
if (KDClassReqs[KinkyDungeonClassMode] && !KDClassReqs[KinkyDungeonClassMode]()) {
|
|
// disable the class if we don't meet its requirements
|
|
KinkyDungeonClassMode = "Peasant";
|
|
}
|
|
let classCount = Object.keys(KDClassStart).length;
|
|
for (let i = 0; i < classCount; i++) {
|
|
KinkyDungeonStatsChoice.set("classMode", KinkyDungeonClassMode == Object.keys(KDClassStart)[i] ? true : undefined);
|
|
}
|
|
let points = KinkyDungeonGetStatPoints(KinkyDungeonStatsChoice);
|
|
KinkyDungeonStatsChoice.set("hardMode", points >= KDHardModeThresh ? true : undefined);
|
|
|
|
}
|
|
|
|
let KDHardModeThresh = 10;
|
|
|
|
function KinkyDungeonHandleClick() {
|
|
if (KDProcessButtons()) return true;
|
|
|
|
if (MouseIn(1885, 25, 90, 90) && (!KDPatched)) {
|
|
ElementRemove("saveDataField");
|
|
ElementRemove("saveInputField");
|
|
KinkyDungeonExit();
|
|
return true;
|
|
}
|
|
if (KinkyDungeonState == "Credits") {
|
|
if (MouseIn(1870, 930, 110, 64)) {
|
|
KinkyDungeonState = "Menu";
|
|
return true;
|
|
}
|
|
if (MouseIn(1730, 930, 110, 64)) {
|
|
if (KinkyDungeonCreditsPos < 1) KinkyDungeonCreditsPos += 1;
|
|
else KinkyDungeonCreditsPos = 0;
|
|
}
|
|
} if (KinkyDungeonState == "Patrons") {
|
|
if (MouseIn(1870, 930, 110, 64)) {
|
|
KinkyDungeonState = "Menu";
|
|
return true;
|
|
}
|
|
if (MouseIn(1730, 930, 110, 64)) {
|
|
if (KinkyDungeonPatronPos < 1) KinkyDungeonPatronPos += 1;
|
|
else KinkyDungeonPatronPos = 0;
|
|
}
|
|
} else if (KinkyDungeonState == "Journey") {
|
|
if (MouseIn(875, 350, 750, 64)) {
|
|
KDJourney = "";
|
|
KinkyDungeonState = "Stats";
|
|
return true;
|
|
} else if (MouseIn(875, 450, 750, 64)) {
|
|
KDJourney = "Random";
|
|
KinkyDungeonState = "Stats";
|
|
return true;
|
|
} else if (MouseIn(875, 550, 750, 64)) {
|
|
KDJourney = "Harder";
|
|
KinkyDungeonState = "Stats";
|
|
return true;
|
|
} else if (MouseIn(1075, 850, 350, 64)) {
|
|
KinkyDungeonState = "Menu";
|
|
return true;
|
|
}
|
|
} else if (KinkyDungeonState == "Diff") {
|
|
|
|
KDUpdatePlugSettings();
|
|
if (MouseIn(1075, 850, 350, 64)) {
|
|
KinkyDungeonState = "Menu";
|
|
return true;
|
|
}
|
|
} else if (KinkyDungeonState == "Stats") {
|
|
|
|
// Removed and moved to DrawButtonKDEx
|
|
} else if (KinkyDungeonState == "TileEditor") {
|
|
KDHandleTileEditor();
|
|
} else if (KinkyDungeonState == "Load"){
|
|
if (MouseIn(875, 750, 350, 64)) {
|
|
KinkyDungeonNewGame = 0;
|
|
KinkyDungeonGrid = "";
|
|
KinkyDungeonInitialize(1, true);
|
|
MiniGameKinkyDungeonCheckpoint = "grv";
|
|
if (KinkyDungeonLoadGame(ElementValue("saveInputField"))) {
|
|
KDSendEvent('loadGame');
|
|
//KDInitializeJourney(KDJourney);
|
|
if (KinkyDungeonGrid == "") KinkyDungeonCreateMap(KinkyDungeonMapParams[KinkyDungeonMapIndex[MiniGameKinkyDungeonCheckpoint]], MiniGameKinkyDungeonLevel, false, true);
|
|
ElementRemove("saveInputField");
|
|
KinkyDungeonState = "Game";
|
|
|
|
if (KinkyDungeonKeybindings) {
|
|
KDCommitKeybindings();
|
|
}
|
|
}
|
|
return true;
|
|
} else if (MouseIn(1275, 750, 350, 64)) {
|
|
KinkyDungeonState = "Menu";
|
|
ElementRemove("saveInputField");
|
|
return true;
|
|
}
|
|
} else if (KinkyDungeonState == "LoadOutfit"){
|
|
if (MouseIn(875, 750, 350, 64)) {
|
|
if (StandalonePatched) {
|
|
KDSaveCodeOutfit();
|
|
KinkyDungeonState = "Wardrobe";
|
|
|
|
} else {
|
|
let decompressed = LZString.decompressFromBase64(ElementValue("saveInputField"));
|
|
if (decompressed) {
|
|
let origAppearance = KinkyDungeonPlayer.Appearance;
|
|
try {
|
|
CharacterAppearanceRestore(KinkyDungeonPlayer, decompressed);
|
|
CharacterRefresh(KinkyDungeonPlayer);
|
|
KDInitProtectedGroups();
|
|
} catch (e) {
|
|
// If we fail, it might be a BCX code. try it!
|
|
KinkyDungeonPlayer.Appearance = origAppearance;
|
|
try {
|
|
let parsed = JSON.parse(decompressed);
|
|
if (CommonIsArray(parsed)) {
|
|
if (!StandalonePatched) {
|
|
for (let g of parsed) {
|
|
if (CommonIsObject(g)) {
|
|
InventoryWear(KinkyDungeonPlayer, g.Name, g.Group, g.Color);
|
|
}
|
|
}
|
|
CharacterRefresh(KinkyDungeonPlayer);
|
|
}
|
|
KDInitProtectedGroups();
|
|
} else {
|
|
console.log("Invalid code. Maybe its corrupt?");
|
|
}
|
|
} catch (error) {
|
|
console.log("Invalid code.");
|
|
}
|
|
}
|
|
}
|
|
|
|
KinkyDungeonDressPlayer();
|
|
KinkyDungeonNewDress = true;
|
|
KinkyDungeonState = "Menu";
|
|
}
|
|
// Return to menu
|
|
ElementRemove("saveInputField");
|
|
return true;
|
|
} else if (MouseIn(1275, 750, 350, 64)) {
|
|
if (StandalonePatched) {
|
|
KDRestoreOutfit();
|
|
KinkyDungeonState = "Wardrobe";
|
|
} else {
|
|
KinkyDungeonState = "Menu";
|
|
}
|
|
ElementRemove("saveInputField");
|
|
return true;
|
|
}
|
|
} else if (KinkyDungeonState == "Consent") {
|
|
if (KDLoadingFinished) {
|
|
if (MouseIn(1000-450/2, 720, 450, 64)) {
|
|
KinkyDungeonState = "Menu";
|
|
if (KDPatched) {
|
|
KDSendEvent('optin');
|
|
} else {
|
|
KDOptOut = true;
|
|
}
|
|
|
|
CharacterReleaseTotal(KinkyDungeonPlayer);
|
|
KinkyDungeonDressSet();
|
|
CharacterNaked(KinkyDungeonPlayer);
|
|
KinkyDungeonInitializeDresses();
|
|
KinkyDungeonCheckClothesLoss = true;
|
|
KinkyDungeonDressPlayer();
|
|
KDInitProtectedGroups();
|
|
CharacterRefresh(KinkyDungeonPlayer);
|
|
|
|
return true;
|
|
} else if (MouseIn(1000-450/2, 820, 450, 64)) {
|
|
if (KDPatched) {
|
|
KDSendEvent('optout');
|
|
}
|
|
KDOptOut = true;
|
|
KinkyDungeonState = "Menu";
|
|
|
|
CharacterReleaseTotal(KinkyDungeonPlayer);
|
|
KinkyDungeonDressSet();
|
|
CharacterNaked(KinkyDungeonPlayer);
|
|
KinkyDungeonInitializeDresses();
|
|
KinkyDungeonCheckClothesLoss = true;
|
|
KinkyDungeonDressPlayer();
|
|
KDInitProtectedGroups();
|
|
CharacterRefresh(KinkyDungeonPlayer);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
} else if (KinkyDungeonState == "Menu" || KinkyDungeonState == "Lose") {
|
|
|
|
if (MouseIn(1700, 100, 64, 64)) {
|
|
KDToggles.Sound = !KDToggles.Sound;
|
|
KDSaveToggles();
|
|
}
|
|
|
|
if (MouseIn(1700, 874, 280, 50)) {
|
|
let langIndex = KDLanguages.indexOf(localStorage.getItem("BondageClubLanguage")) || 0;
|
|
let newIndex = (langIndex + 1) % KDLanguages.length;
|
|
localStorage.setItem("BondageClubLanguage", KDLanguages[newIndex]);
|
|
KDRestart = true;
|
|
return true;
|
|
}
|
|
if (!StandalonePatched) {
|
|
if (MouseIn(690, 930, 150, 64)) {
|
|
KinkyDungeonState = "LoadOutfit";
|
|
|
|
KDOriginalValue = LZString.compressToBase64(CharacterAppearanceStringify(KinkyDungeonPlayer));
|
|
CharacterReleaseTotal(KinkyDungeonPlayer);
|
|
ElementCreateTextArea("saveInputField");
|
|
ElementValue("saveInputField", LZString.compressToBase64(CharacterAppearanceStringify(KinkyDungeonPlayer)));
|
|
|
|
KinkyDungeonConfigAppearance = true;
|
|
return true;
|
|
} else if (MouseIn(460, 930, 220, 64)) {
|
|
if (KinkyDungeonReplaceConfirm > 0) {
|
|
KinkyDungeonDresses.Default = KinkyDungeonDefaultDefaultDress;
|
|
CharacterAppearanceRestore(KinkyDungeonPlayer, CharacterAppearanceStringify(KinkyDungeonPlayerCharacter ? KinkyDungeonPlayerCharacter : Player));
|
|
CharacterReleaseTotal(KinkyDungeonPlayer);
|
|
KinkyDungeonSetDress("Default", "Default");
|
|
KinkyDungeonDressPlayer();
|
|
KDInitProtectedGroups();
|
|
KinkyDungeonConfigAppearance = true;
|
|
return true;
|
|
} else {
|
|
KinkyDungeonReplaceConfirm = 2;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (MouseIn(1850, 930, 135, 64)) {
|
|
KinkyDungeonState = "Credits";
|
|
return true;
|
|
}
|
|
if (MouseIn(1700, 930, 135, 64)) {
|
|
KinkyDungeonState = "Patrons";
|
|
return true;
|
|
}
|
|
} else if (KinkyDungeonState == "Save") {
|
|
if (!KinkyDungeonIsPlayer()) KinkyDungeonState = "Game";
|
|
if (MouseIn(875, 750, 350, 64)) {
|
|
KinkyDungeonState = "Game";
|
|
ElementRemove("saveDataField");
|
|
return true;
|
|
} else if (MouseIn(1275, 750, 350, 64)) {
|
|
KinkyDungeonState = "Game";
|
|
ElementRemove("saveDataField");
|
|
return true;
|
|
}
|
|
} else if (KinkyDungeonState == "Game") {
|
|
if (KinkyDungeonIsPlayer()) KinkyDungeonClickGame();
|
|
} else if (KinkyDungeonState == "Keybindings") {
|
|
// Replaced by DrawButtonKDEx
|
|
} else if (KinkyDungeonState == "Toggles") {
|
|
let YYstart = 200;
|
|
let YY = YYstart;
|
|
let YYd = 70;
|
|
|
|
YY = YYstart;
|
|
|
|
|
|
if (StandalonePatched) {
|
|
if (MouseIn(450, YY, 350, 64)) {
|
|
if (MouseX <= 450 + 350/2) KDResolutionListIndex = (KDResolutionList.length + KDResolutionListIndex - 1) % KDResolutionList.length;
|
|
else KDResolutionListIndex = (KDResolutionListIndex + 1) % KDResolutionList.length;
|
|
KDResolution = KDResolutionList[KDResolutionListIndex];
|
|
KDResolutionConfirm = true;
|
|
localStorage.setItem("KDResolution", "" + KDResolutionListIndex);
|
|
}
|
|
YY += YYd*2;
|
|
}
|
|
|
|
if (MouseIn(450, YY, 350, 64)) {
|
|
if (MouseX <= 450 + 350/2) KDVibeVolumeListIndex = (KDVibeVolumeList.length + KDVibeVolumeListIndex - 1) % KDVibeVolumeList.length;
|
|
else KDVibeVolumeListIndex = (KDVibeVolumeListIndex + 1) % KDVibeVolumeList.length;
|
|
KDVibeVolume = KDVibeVolumeList[KDVibeVolumeListIndex];
|
|
localStorage.setItem("KDVibeVolume", "" + KDVibeVolumeListIndex);
|
|
}
|
|
YY += YYd;
|
|
if (MouseIn(450, YY, 350, 64)) {
|
|
if (MouseX <= 450 + 350/2) KDMusicVolumeListIndex = (KDMusicVolumeList.length + KDMusicVolumeListIndex - 1) % KDMusicVolumeList.length;
|
|
else KDMusicVolumeListIndex = (KDMusicVolumeListIndex + 1) % KDMusicVolumeList.length;
|
|
KDMusicVolume = KDMusicVolumeList[KDMusicVolumeListIndex];
|
|
localStorage.setItem("KDMusicVolume", "" + KDMusicVolumeListIndex);
|
|
}
|
|
YY += YYd;
|
|
if (MouseIn(450, YY, 350, 64)) {
|
|
if (MouseX <= 450 + 350/2) KDSfxVolumeListIndex = (KDSfxVolumeList.length + KDSfxVolumeListIndex - 1) % KDSfxVolumeList.length;
|
|
else KDSfxVolumeListIndex = (KDSfxVolumeListIndex + 1) % KDSfxVolumeList.length;
|
|
KDSfxVolume = KDSfxVolumeList[KDSfxVolumeListIndex];
|
|
localStorage.setItem("KDSfxVolume", "" + KDSfxVolumeListIndex);
|
|
}
|
|
YY += YYd;
|
|
if (MouseIn(450, YY, 350, 64)) {
|
|
if (MouseX <= 450 + 350/2) KDAnimSpeedListIndex = (KDAnimSpeedList.length + KDAnimSpeedListIndex - 1) % KDAnimSpeedList.length;
|
|
else KDAnimSpeedListIndex = (KDAnimSpeedListIndex + 1) % KDAnimSpeedList.length;
|
|
KDAnimSpeed = KDAnimSpeedList[KDAnimSpeedListIndex] || 0;
|
|
localStorage.setItem("KDAnimSpeed", "" + KDAnimSpeedListIndex);
|
|
}
|
|
YY += YYd;
|
|
} else if (KinkyDungeonState == "End") {
|
|
if (MouseIn(1075, 650, 350, 64)) {
|
|
KinkyDungeonState = "Game";
|
|
KinkyDungeonNewGamePlus();
|
|
return true;
|
|
} if (MouseIn(1075, 750, 350, 64)) {
|
|
KinkyDungeonState = "Menu";
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Handles clicks during the kinky dungeon game
|
|
* @returns {void} - Nothing
|
|
*/
|
|
function KinkyDungeonClick() {
|
|
if (KinkyDungeonHandleClick()) {
|
|
if (KDToggles.Sound) AudioPlayInstantSoundKD(KinkyDungeonRootDirectory + "Audio/Click.ogg");
|
|
}
|
|
if (KinkyDungeonReplaceConfirm > 0) KinkyDungeonReplaceConfirm -= 1;
|
|
}
|
|
|
|
/**
|
|
* Handles exit during the kinky dungeon game
|
|
* @type {ScreenExitHandler}
|
|
*/
|
|
function KinkyDungeonExit() {
|
|
KinkyDungeonGameKey.removeKeyListener();
|
|
CommonDynamicFunction(MiniGameReturnFunction + "()");
|
|
|
|
// Refresh the player character if needed
|
|
if (ArcadeDeviousChallenge && KinkyDungeonPlayerNeedsRefresh) {
|
|
if (ServerPlayerIsInChatRoom()) {
|
|
ChatRoomCharacterUpdate(Player);
|
|
} else {
|
|
CharacterRefresh(Player);
|
|
}
|
|
}
|
|
|
|
if (CharacterAppearancePreviousEmoticon) {
|
|
CharacterSetFacialExpression(Player, "Emoticon", CharacterAppearancePreviousEmoticon);
|
|
CharacterAppearancePreviousEmoticon = "";
|
|
}
|
|
|
|
if (MiniGameKinkyDungeonLevel > Math.max(KinkyDungeonRep, ReputationGet("Gaming")) || Math.max(KinkyDungeonRep, ReputationGet("Gaming")) > KinkyDungeonMaxLevel) {
|
|
KinkyDungeonRep = Math.max(KinkyDungeonRep, MiniGameKinkyDungeonLevel);
|
|
DialogSetReputation("Gaming", KinkyDungeonRep);
|
|
}
|
|
|
|
if (ServerPlayerIsInChatRoom() && KinkyDungeonState != "Menu" && KDLose) {
|
|
let Dictionary = [
|
|
{ Tag: "SourceCharacter", Text: CharacterNickname(Player), MemberNumber: Player.MemberNumber },
|
|
{ Tag: "KinkyDungeonLevel", Text: String(MiniGameKinkyDungeonLevel)},
|
|
];
|
|
ChatRoomPublishCustomAction("KinkyDungeonLose", false, Dictionary);
|
|
}
|
|
CharacterRefresh(Player, true);
|
|
|
|
KinkyDungeonTeardownCrashHandler();
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Handles key presses during the mini game. (Both keyboard and mobile)
|
|
* @type {KeyboardEventListener}
|
|
*/
|
|
function KinkyDungeonKeyDown(event) {
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
let mouseDown = false;
|
|
let MouseClicked = false;
|
|
|
|
window.addEventListener('mousedown', function() {
|
|
mouseDown = true;
|
|
MouseClicked = true;
|
|
});
|
|
window.addEventListener('touchstart', function() {
|
|
MouseClicked = true;
|
|
});
|
|
window.addEventListener('mouseup', function() {
|
|
mouseDown = false;
|
|
});
|
|
|
|
/**
|
|
* Game keyboard input handler object: Handles keyboard inputs.
|
|
* @constant
|
|
* @type {object} - The game keyboard input handler object. Contains the functions and properties required to handle key press events.
|
|
*/
|
|
let KinkyDungeonGameKey = {
|
|
keyPressed : [false, false, false, false, false, false, false, false, false],
|
|
|
|
KEY_UP : 'KeyB',
|
|
KEY_DOWN : 'KeyV',
|
|
KEY_LEFT : 'KeyC',
|
|
KEY_RIGHT : 'KeyX',
|
|
KEY_UPLEFT : 'KeyC',
|
|
KEY_UPRIGHT : 'KeyB',
|
|
KEY_DOWNLEFT : 'KeyX',
|
|
KEY_DOWNRIGHT : 'KeyV',
|
|
KEY_WAIT : 'KeyV',
|
|
KEY_SKIP : 'KeyEnter',
|
|
|
|
load : function(){
|
|
KinkyDungeonGameKey.keyPressed = [false, false, false, false, false, false, false, false, false];
|
|
KinkyDungeonGameKey.addKeyListener();
|
|
},
|
|
|
|
addKeyListener : function () {
|
|
window.addEventListener('keydown', KinkyDungeonGameKey.keyDownEvent);
|
|
window.addEventListener('keyup', KinkyDungeonGameKey.keyUpEvent);
|
|
},
|
|
removeKeyListener : function () {
|
|
window.removeEventListener('keydown', KinkyDungeonGameKey.keyDownEvent);
|
|
window.removeEventListener('keyup', KinkyDungeonGameKey.keyUpEvent);
|
|
},
|
|
keyDownEvent : {
|
|
handleEvent : function (event) {
|
|
let code = event.code;
|
|
if (!KDLastKeyTime[code]) {
|
|
KinkyDungeonKeybindingCurrentKey = code;
|
|
KDLastKeyTime[KinkyDungeonKeybindingCurrentKey] = CommonTime();
|
|
}
|
|
switch(code){
|
|
case KinkyDungeonGameKey.KEY_UP:
|
|
if(!KinkyDungeonGameKey.keyPressed[0]){
|
|
KinkyDungeonGameKey.keyPressed[0] = true;
|
|
}
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_DOWN:
|
|
if(!KinkyDungeonGameKey.keyPressed[1]){
|
|
KinkyDungeonGameKey.keyPressed[1] = true;
|
|
}
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_LEFT:
|
|
if(!KinkyDungeonGameKey.keyPressed[2]){
|
|
KinkyDungeonGameKey.keyPressed[2] = true;
|
|
}
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_RIGHT:
|
|
if(!KinkyDungeonGameKey.keyPressed[3]){
|
|
KinkyDungeonGameKey.keyPressed[3] = true;
|
|
}
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_UPLEFT:
|
|
if(!KinkyDungeonGameKey.keyPressed[4]){
|
|
KinkyDungeonGameKey.keyPressed[4] = true;
|
|
}
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_UPRIGHT:
|
|
if(!KinkyDungeonGameKey.keyPressed[5]){
|
|
KinkyDungeonGameKey.keyPressed[5] = true;
|
|
}
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_DOWNLEFT:
|
|
if(!KinkyDungeonGameKey.keyPressed[6]){
|
|
KinkyDungeonGameKey.keyPressed[6] = true;
|
|
}
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_DOWNRIGHT:
|
|
if(!KinkyDungeonGameKey.keyPressed[7]){
|
|
KinkyDungeonGameKey.keyPressed[7] = true;
|
|
}
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_WAIT:
|
|
if(!KinkyDungeonGameKey.keyPressed[8]){
|
|
KinkyDungeonGameKey.keyPressed[8] = true;
|
|
}
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_SKIP:
|
|
if(!KinkyDungeonGameKey.keyPressed[9]){
|
|
KinkyDungeonGameKey.keyPressed[9] = true;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
keyUpEvent : {
|
|
handleEvent : function (event) {
|
|
let code = event.code;
|
|
KinkyDungeonKeybindingCurrentKeyRelease = code;
|
|
if (KinkyDungeonKeybindingCurrentKeyRelease) KinkyDungeonGameKeyUp(KDLastKeyTime[KinkyDungeonKeybindingCurrentKeyRelease]);
|
|
if (KDLastKeyTime[code]) delete KDLastKeyTime[code];
|
|
KinkyDungeonKeybindingCurrentKeyRelease = '';
|
|
switch(code){
|
|
case KinkyDungeonGameKey.KEY_UP:
|
|
if (KinkyDungeonGameKey.keyPressed[0]) KinkyDungeonLastMoveTimerStart = 0;
|
|
KinkyDungeonGameKey.keyPressed[0] = false;
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_DOWN:
|
|
if (KinkyDungeonGameKey.keyPressed[1]) KinkyDungeonLastMoveTimerStart = 0;
|
|
KinkyDungeonGameKey.keyPressed[1] = false;
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_LEFT:
|
|
if (KinkyDungeonGameKey.keyPressed[2]) KinkyDungeonLastMoveTimerStart = 0;
|
|
KinkyDungeonGameKey.keyPressed[2] = false;
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_RIGHT:
|
|
if (KinkyDungeonGameKey.keyPressed[3]) KinkyDungeonLastMoveTimerStart = 0;
|
|
KinkyDungeonGameKey.keyPressed[3] = false;
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_UPLEFT:
|
|
if (KinkyDungeonGameKey.keyPressed[4]) KinkyDungeonLastMoveTimerStart = 0;
|
|
KinkyDungeonGameKey.keyPressed[4] = false;
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_UPRIGHT:
|
|
if (KinkyDungeonGameKey.keyPressed[5]) KinkyDungeonLastMoveTimerStart = 0;
|
|
KinkyDungeonGameKey.keyPressed[5] = false;
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_DOWNLEFT:
|
|
if (KinkyDungeonGameKey.keyPressed[6]) KinkyDungeonLastMoveTimerStart = 0;
|
|
KinkyDungeonGameKey.keyPressed[6] = false;
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_DOWNRIGHT:
|
|
if (KinkyDungeonGameKey.keyPressed[7]) KinkyDungeonLastMoveTimerStart = 0;
|
|
KinkyDungeonGameKey.keyPressed[7] = false;
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_WAIT:
|
|
if (KinkyDungeonGameKey.keyPressed[8]) KinkyDungeonLastMoveTimerStart = 0;
|
|
KinkyDungeonGameKey.keyPressed[8] = false;
|
|
break;
|
|
case KinkyDungeonGameKey.KEY_SKIP:
|
|
if (KinkyDungeonGameKey.keyPressed[9]) KinkyDungeonLastMoveTimerStart = 0;
|
|
KinkyDungeonGameKey.keyPressed[9] = false;
|
|
break;
|
|
}
|
|
|
|
}
|
|
},
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* Outputs a savegame
|
|
* @returns {KinkyDungeonSave} - Saved game object
|
|
*/
|
|
function KinkyDungeonGenerateSaveData() {
|
|
/** @type {KinkyDungeonSave} */
|
|
let save = {};
|
|
save.level = MiniGameKinkyDungeonLevel;
|
|
save.checkpoint = MiniGameKinkyDungeonCheckpoint;
|
|
save.rep = KinkyDungeonGoddessRep;
|
|
save.costs = KinkyDungeonShrineCosts;
|
|
save.pcosts = KinkyDungeonPenanceCosts;
|
|
save.dress = KinkyDungeonCurrentDress;
|
|
save.gold = KinkyDungeonGold;
|
|
save.points = KinkyDungeonSpellPoints;
|
|
save.id = KinkyDungeonEnemyID;
|
|
save.choices = KinkyDungeonSpellChoices;
|
|
save.choices2 = KinkyDungeonSpellChoicesToggle;
|
|
save.buffs = KinkyDungeonPlayerBuffs;
|
|
save.lostitems = KinkyDungeonLostItems;
|
|
save.grounditems = KinkyDungeonGroundItems;
|
|
save.rescued = KinkyDungeonRescued;
|
|
save.aid = KinkyDungeonAid;
|
|
save.seed = KinkyDungeonSeed;
|
|
save.statchoice = Array.from(KinkyDungeonStatsChoice);
|
|
save.mapIndex = KinkyDungeonMapIndex;
|
|
save.flags = Array.from(KinkyDungeonFlags);
|
|
save.faction = KinkyDungeonFactionRelations;
|
|
save.perks = KDUnlockedPerks;
|
|
|
|
let spells = [];
|
|
/**@type {item[]} */
|
|
let newInv = [];
|
|
|
|
for (let inv of KinkyDungeonFullInventory()) {
|
|
let item = Object.assign({}, inv);
|
|
newInv.push(item);
|
|
}
|
|
|
|
for (let spell of KinkyDungeonSpells) {
|
|
spells.push(spell.name);
|
|
}
|
|
|
|
save.spells = spells;
|
|
save.inventory = newInv;
|
|
save.KDGameData = KDGameData;
|
|
save.KDEventData = KDEventData;
|
|
|
|
save.KinkyDungeonEffectTiles = KinkyDungeonEffectTiles;
|
|
save.KinkyDungeonTiles = KinkyDungeonTiles;
|
|
save.KinkyDungeonTilesSkin = KinkyDungeonTilesSkin;
|
|
save.KinkyDungeonTilesMemory = KinkyDungeonTilesMemory;
|
|
save.KinkyDungeonRandomPathablePoints = KinkyDungeonRandomPathablePoints;
|
|
save.KinkyDungeonPlayerEntity = KinkyDungeonPlayerEntity;
|
|
save.KinkyDungeonEntities = KinkyDungeonEntities;
|
|
save.KinkyDungeonBullets = KinkyDungeonBullets;
|
|
save.KinkyDungeonGrid = KinkyDungeonGrid;
|
|
save.KinkyDungeonGridWidth = KinkyDungeonGridWidth;
|
|
save.KinkyDungeonGridHeight = KinkyDungeonGridHeight;
|
|
save.KinkyDungeonFogGrid = KinkyDungeonFogGrid;
|
|
save.KinkyDungeonEndPosition = KinkyDungeonEndPosition;
|
|
save.KinkyDungeonStartPosition = KinkyDungeonStartPosition;
|
|
|
|
save.stats = {
|
|
picks: KinkyDungeonLockpicks,
|
|
keys: KinkyDungeonRedKeys,
|
|
bkeys: KinkyDungeonBlueKeys,
|
|
mana: KinkyDungeonStatMana,
|
|
manapool: KinkyDungeonStatManaPool,
|
|
stamina: KinkyDungeonStatStamina,
|
|
willpower: KinkyDungeonStatWill,
|
|
distraction: KinkyDungeonStatDistraction,
|
|
distractionlower: KinkyDungeonStatDistractionLower,
|
|
wep: KinkyDungeonPlayerWeapon,
|
|
npp: KinkyDungeonNewGame,
|
|
diff: KinkyDungeonStatsChoice.get("randomMode"),
|
|
};
|
|
return save;
|
|
}
|
|
|
|
function KinkyDungeonSaveGame(ToString) {
|
|
let save = KinkyDungeonGenerateSaveData();
|
|
|
|
let data = KinkyDungeonCompressSave(save);
|
|
if (!ToString) {
|
|
//Player.KinkyDungeonSave = saveData.KinkyDungeonSave;
|
|
//ServerAccountUpdate.QueueData(saveData);
|
|
localStorage.setItem('KinkyDungeonSave', data);
|
|
}
|
|
return data;
|
|
}
|
|
|
|
function KinkyDungeonCompressSave(save) {
|
|
return LZString.compressToBase64(JSON.stringify(save));
|
|
}
|
|
|
|
// N4IgNgpgbhYgXARgDQgMYAsJoNYAcB7ASwDsAXBABlQCcI8FQBxDAgZwvgFoBWakAAo0ibAiQg0EvfgBkIAQzJZJ8fgFkIZeXFWoASgTwQqqAOpEwO/gFFIAWwjk2JkAGExAKwCudFwElLLzYiMSoAX1Q0djJneGAIkAIaACNYgG0AXUisDnSskAATOjZYkAARCAAzeS8wClQAcwIwApdCUhiEAGZUSBgwWNBbCAcnBBQ3Tx9jJFQAsCCQknGEtiNLPNRSGHIkgE8ENNAokjYvO3lkyEYQEnkHBEECMiW1eTuQBIBHL3eXsgOSAixzEZwuVxmoDuD3gTxeYgAylo7KR5J9UD8/kQAStkCDTudLtc4rd7jM4UsAGLCBpEVrfX7kbGAxDAkAAdwUhGWJOh5IA0iQiJVjGE2cUyDR5B0bnzHmUvGgyAAVeRGOQNZwJF4NDBkcQlca9Ai4R7o0ASqUy3lk+WKlVqiCUiCaNTnOwHbVEXX6iCG2bgE04M1hDJhIA=
|
|
function KinkyDungeonLoadGame(String) {
|
|
let str = String ? LZString.decompressFromBase64(String.trim()) : (localStorage.getItem('KinkyDungeonSave') ? LZString.decompressFromBase64(localStorage.getItem('KinkyDungeonSave')) : "");
|
|
if (str) {
|
|
let saveData = JSON.parse(str);
|
|
if (CommonIsObject(saveData)
|
|
&& saveData.spells != undefined
|
|
&& saveData.level != undefined
|
|
&& saveData.checkpoint != undefined
|
|
&& saveData.inventory != undefined
|
|
&& saveData.costs != undefined
|
|
&& saveData.rep != undefined
|
|
&& saveData.dress != undefined) {
|
|
|
|
KDPathfindingCacheFails = 0;
|
|
KDPathfindingCacheHits = 0;
|
|
KDPathCache = new Map();
|
|
KDThoughtBubbles = new Map();
|
|
|
|
KinkyDungeonEntities = [];
|
|
KDUpdateEnemyCache = true;
|
|
if (saveData.flags && saveData.flags.length) KinkyDungeonFlags = new Map(saveData.flags);
|
|
MiniGameKinkyDungeonLevel = saveData.level;
|
|
if (Array.from(Object.keys(KinkyDungeonMapIndex)).includes(saveData.checkpoint))
|
|
MiniGameKinkyDungeonCheckpoint = saveData.checkpoint;
|
|
else MiniGameKinkyDungeonCheckpoint = "grv";
|
|
KinkyDungeonShrineCosts = saveData.costs;
|
|
KinkyDungeonGoddessRep = saveData.rep;
|
|
KinkyDungeonCurrentDress = saveData.dress;
|
|
KDGameData.KinkyDungeonSpawnJailers = 0;
|
|
KDGameData.KinkyDungeonSpawnJailersMax = 0;
|
|
if (saveData.seed) KDsetSeed(saveData.seed);
|
|
if (saveData.pcosts) KinkyDungeonPenanceCosts = saveData.pcosts;
|
|
if (saveData.choices) KinkyDungeonSpellChoices = saveData.choices;
|
|
if (saveData.choices2) KinkyDungeonSpellChoicesToggle = saveData.choices2;
|
|
if (saveData.buffs) KinkyDungeonPlayerBuffs = saveData.buffs;
|
|
if (saveData.gold != undefined) KinkyDungeonGold = saveData.gold;
|
|
if (saveData.id != undefined) KinkyDungeonEnemyID = saveData.id;
|
|
if (saveData.points != undefined) KinkyDungeonSpellPoints = saveData.points;
|
|
if (saveData.lostitems != undefined) KinkyDungeonLostItems = saveData.lostitems;
|
|
if (saveData.rescued != undefined) KinkyDungeonRescued = saveData.rescued;
|
|
if (saveData.aid != undefined) KinkyDungeonAid = saveData.aid;
|
|
if (saveData.grounditems) KinkyDungeonGroundItems = saveData.grounditems;
|
|
if (saveData.stats) {
|
|
if (saveData.stats.picks != undefined) KinkyDungeonLockpicks = saveData.stats.picks;
|
|
if (saveData.stats.keys != undefined) KinkyDungeonRedKeys = saveData.stats.keys;
|
|
if (saveData.stats.bkeys != undefined) KinkyDungeonBlueKeys = saveData.stats.bkeys;
|
|
if (saveData.stats.mana != undefined) KinkyDungeonStatMana = saveData.stats.mana;
|
|
if (saveData.stats.manapool != undefined) KinkyDungeonStatManaPool = saveData.stats.manapool;
|
|
if (saveData.stats.stamina != undefined) KinkyDungeonStatStamina = saveData.stats.stamina;
|
|
if (saveData.stats.willpower != undefined) KinkyDungeonStatWill = saveData.stats.willpower;
|
|
if (saveData.stats.distraction != undefined) KinkyDungeonStatDistraction = saveData.stats.distraction;
|
|
if (saveData.stats.distractionlower != undefined) KinkyDungeonStatDistractionLower = saveData.stats.distractionlower;
|
|
if (saveData.stats.wep != undefined) KDSetWeapon(saveData.stats.wep);
|
|
if (saveData.stats.npp != undefined) KinkyDungeonNewGame = saveData.stats.npp;
|
|
|
|
|
|
KDOrigStamina = KinkyDungeonStatStamina*10;
|
|
KDOrigWill = KinkyDungeonStatWill*10;
|
|
KDOrigMana = KinkyDungeonStatMana*10;
|
|
KDOrigDistraction = KinkyDungeonStatDistraction*10;
|
|
}
|
|
KDGameData = CommonCloneDeep(KDGameDataBase);
|
|
if (saveData.KDGameData != undefined) KDGameData = Object.assign({}, saveData.KDGameData);
|
|
KDEventData = CommonCloneDeep(KDEventDataBase);
|
|
if (saveData.KDEventData != undefined) KDEventData = Object.assign({}, saveData.KDEventData);
|
|
|
|
if (saveData.statchoice != undefined) KinkyDungeonStatsChoice = new Map(saveData.statchoice);
|
|
if (saveData.faction != undefined) KinkyDungeonFactionRelations = saveData.faction;
|
|
KDInitFactions();
|
|
if (typeof KDGameData.TimeSinceLastVibeStart === "number") KDGameData.TimeSinceLastVibeStart = {};
|
|
if (typeof KDGameData.TimeSinceLastVibeEnd === "number") KDGameData.TimeSinceLastVibeEnd = {};
|
|
|
|
if (!KDGameData.AlreadyOpened) KDGameData.AlreadyOpened = [];
|
|
|
|
if (saveData.perks) {
|
|
KDUnlockedPerks = saveData.perks;
|
|
KDLoadPerks();
|
|
}
|
|
KDUnlockPerk();
|
|
|
|
KDInitInventory();
|
|
for (let item of saveData.inventory) {
|
|
if (item.type == Restraint) {
|
|
let restraint = KinkyDungeonGetRestraintByName(item.name);
|
|
if (restraint) {
|
|
KinkyDungeonAddRestraint(restraint, 0, true, item.lock, undefined, undefined, undefined, undefined, item.faction); // Add the item
|
|
let createdrestraint = KinkyDungeonGetRestraintItem(restraint.Group);
|
|
if (createdrestraint) createdrestraint.lock = item.lock; // Lock if applicable
|
|
if (createdrestraint) createdrestraint.events = item.events; // events if applicable
|
|
KinkyDungeonInventoryAdd(item);
|
|
}
|
|
} else {
|
|
if (item.type != LooseRestraint || KDRestraint(item) != undefined)
|
|
KinkyDungeonInventoryAdd(item);
|
|
}
|
|
}
|
|
|
|
KinkyDungeonSpells = [];
|
|
for (let spell of saveData.spells) {
|
|
let sp = KinkyDungeonFindSpell(spell);
|
|
if (sp) KinkyDungeonSpells.push(sp);
|
|
}
|
|
|
|
|
|
if (saveData.KinkyDungeonEffectTiles) KinkyDungeonEffectTiles = saveData.KinkyDungeonEffectTiles;
|
|
if (saveData.KinkyDungeonTiles) KinkyDungeonTiles = saveData.KinkyDungeonTiles;
|
|
if (saveData.KinkyDungeonTilesSkin) KinkyDungeonTilesSkin = saveData.KinkyDungeonTilesSkin;
|
|
if (saveData.KinkyDungeonTilesMemory) KinkyDungeonTilesMemory = saveData.KinkyDungeonTilesMemory;
|
|
if (saveData.KinkyDungeonRandomPathablePoints) KinkyDungeonRandomPathablePoints = saveData.KinkyDungeonRandomPathablePoints;
|
|
if (saveData.KinkyDungeonPlayerEntity) KinkyDungeonPlayerEntity = saveData.KinkyDungeonPlayerEntity;
|
|
if (saveData.KinkyDungeonEntities) KinkyDungeonEntities = saveData.KinkyDungeonEntities;
|
|
KDUpdateEnemyCache = true;
|
|
if (saveData.KinkyDungeonBullets) KinkyDungeonBullets = saveData.KinkyDungeonBullets;
|
|
if (saveData.KinkyDungeonStartPosition) KinkyDungeonStartPosition = saveData.KinkyDungeonStartPosition;
|
|
if (saveData.KinkyDungeonEndPosition) KinkyDungeonEndPosition = saveData.KinkyDungeonEndPosition;
|
|
if (saveData.KinkyDungeonGrid) {
|
|
KinkyDungeonGrid = saveData.KinkyDungeonGrid;
|
|
KinkyDungeonGridWidth = saveData.KinkyDungeonGridWidth;
|
|
KinkyDungeonGridHeight = saveData.KinkyDungeonGridHeight;
|
|
}
|
|
KinkyDungeonResetFog();
|
|
|
|
if (saveData.KinkyDungeonFogGrid) KinkyDungeonFogGrid = saveData.KinkyDungeonFogGrid;
|
|
|
|
KinkyDungeonSetMaxStats();
|
|
KinkyDungeonCheckClothesLoss = true;
|
|
KDNaked = false;
|
|
KinkyDungeonDressPlayer();
|
|
KDRefresh = true;
|
|
KDUpdateEnemyCache = true;
|
|
if (KDGameData.Journey)
|
|
KDJourney = KDGameData.Journey;
|
|
if (saveData.mapIndex && !saveData.mapIndex.length) KinkyDungeonMapIndex = saveData.mapIndex;
|
|
|
|
if (String)
|
|
localStorage.setItem('KinkyDungeonSave', String);
|
|
|
|
if (saveData.KDGameData && saveData.KDGameData.LastMapSeed) KDsetSeed(saveData.KDGameData.LastMapSeed);
|
|
|
|
if (!KinkyDungeonMapIndex[KDGameData.MainPath] || !KinkyDungeonMapIndex[KDGameData.ShortcutPath])
|
|
KDInitializeJourney(KDGameData.Journey);
|
|
|
|
if (saveData.KinkyDungeonGrid) {
|
|
KDUpdateVision();
|
|
}
|
|
KinkyDungeonFloaters = [];
|
|
KinkyDungeonAdvanceTime(0, true, true);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
let KinkyDungeonSeed = (Math.random() * 4294967296).toString();
|
|
let KDRandom = sfc32(xmur3(KinkyDungeonSeed)(), xmur3(KinkyDungeonSeed)(), xmur3(KinkyDungeonSeed)(), xmur3(KinkyDungeonSeed)());
|
|
|
|
/**
|
|
*
|
|
* @param {boolean} Native Decides whether or not to use native KDRandom to randomize
|
|
*/
|
|
function KDrandomizeSeed(Native) {
|
|
let rand = Native ? KDRandom : () => {return Math.random();};
|
|
KinkyDungeonSeed = (rand() * 4294967296).toString();
|
|
for (let i = 0; i < 20; i++) {
|
|
let index = rand() * KinkyDungeonSeed.length;
|
|
KinkyDungeonSeed = KinkyDungeonSeed.replaceAt(index, String.fromCharCode(65 + Math.floor(rand()*50)) + String.fromCharCode(65 + Math.floor(rand()*50)));
|
|
}
|
|
KDRandom = sfc32(xmur3(KinkyDungeonSeed)(), xmur3(KinkyDungeonSeed)(), xmur3(KinkyDungeonSeed)(), xmur3(KinkyDungeonSeed)());
|
|
for (let i = 0; i < 1000; i++) {
|
|
KDRandom();
|
|
}
|
|
}
|
|
|
|
function KDsetSeed(string) {
|
|
KinkyDungeonSeed = string;
|
|
KDRandom = sfc32(xmur3(KinkyDungeonSeed)(), xmur3(KinkyDungeonSeed)(), xmur3(KinkyDungeonSeed)(), xmur3(KinkyDungeonSeed)());
|
|
for (let i = 0; i < 1000; i++) {
|
|
KDRandom();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* It takes a string and returns a function that returns a random number
|
|
* @param str - The string to hash.
|
|
* @returns A function that returns a random number.
|
|
*/
|
|
function xmur3(str) {
|
|
let h = 1779033703 ^ str.length;
|
|
for(let i = 0; i < str.length; i++) {
|
|
h = Math.imul(h ^ str.charCodeAt(i), 3432918353);
|
|
h = h << 13 | h >>> 19;
|
|
} return function() {
|
|
h = Math.imul(h ^ (h >>> 16), 2246822507);
|
|
h = Math.imul(h ^ (h >>> 13), 3266489909);
|
|
return (h ^= h >>> 16) >>> 0;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* It takes four 32-bit integers and returns a function that returns a random number between 0 and 1
|
|
* @param a - The first parameter.
|
|
* @param b - 0x9e3779b9
|
|
* @param c - 0x9e3779b9
|
|
* @param d - The seed.
|
|
* @returns A function that returns a random number between 0 and 1.
|
|
*/
|
|
function sfc32(a, b, c, d) {
|
|
return function() {
|
|
a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0;
|
|
let t = (a + b) | 0;
|
|
a = b ^ b >>> 9;
|
|
b = c + (c << 3) | 0;
|
|
c = (c << 21 | c >>> 11);
|
|
d = d + 1 | 0;
|
|
t = t + d | 0;
|
|
c = c + t | 0;
|
|
return (t >>> 0) / 4294967296;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @type {Map<string, HTMLAudioElement>}
|
|
*/
|
|
let kdSoundCache = new Map();
|
|
|
|
/**
|
|
*
|
|
* @param {string} Path
|
|
* @param {number} [volume]
|
|
*/
|
|
function AudioPlayInstantSoundKD(Path, volume) {
|
|
const vol = KDSfxVolume * (volume != null ? volume : Player.AudioSettings.Volume);
|
|
if (vol > 0) {
|
|
let src = KDModFiles[Path] || Path;
|
|
let audio = kdSoundCache.has(src) ? kdSoundCache.get(src) : new Audio();
|
|
if (!kdSoundCache.has(src)) {
|
|
audio.src = src;
|
|
kdSoundCache.set(src, audio);
|
|
} else {
|
|
audio.pause();
|
|
audio.currentTime = 0;
|
|
}
|
|
audio.volume = Math.min(vol, 1);
|
|
audio.play();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* From https://gist.github.com/hyamamoto/fd435505d29ebfa3d9716fd2be8d42f0
|
|
*/
|
|
function hashCode(s) {
|
|
let h = 0;
|
|
for(let i = 0; i < s.length; i++)
|
|
h = Math.imul(31, h) + s.charCodeAt(i) | 0;
|
|
return h;
|
|
}
|
|
|
|
function TextGetKD(Text) {
|
|
if (TextGet(Text))
|
|
return TextGet(Text);
|
|
else return KDLoadingTextKeys[Text] || "Missing text";
|
|
}
|
|
|
|
|
|
function KinkyDungeonCheckPlayerRefresh() {
|
|
if (!ArcadeDeviousChallenge || CommonTime() < KinkyDungeonNextRefreshCheck) {
|
|
return;
|
|
}
|
|
|
|
// We've exceeded the refresh check time - check again in 1 second
|
|
KinkyDungeonNextRefreshCheck = CommonTime() + 1000;
|
|
|
|
if (!KinkyDungeonPlayerNeedsRefresh) {
|
|
return;
|
|
}
|
|
|
|
KinkyDungeonPlayerNeedsRefresh = false;
|
|
|
|
if (ServerPlayerIsInChatRoom()) {
|
|
ChatRoomCharacterUpdate(Player);
|
|
} else {
|
|
CharacterRefresh(Player);
|
|
}
|
|
}
|
|
|
|
function CJKcheck(text,p = 0,o = "search"){
|
|
if (o == "search")
|
|
{
|
|
//Find all English characters and space
|
|
if (p == 1){ return text.match(/[a-zA-Z0-9\s\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+/g);}
|
|
//Find all characters except English characters
|
|
if (p == 2){ return text.match(/^[a-zA-Z\s\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F]+$/g);}
|
|
//Find all CJK Symbols and Punctuation
|
|
if (p == 3){ return text.match(/[\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\uff1f\uff01\uffe5\u3000-\u303f]+/g);}
|
|
//Find all CJK characters
|
|
else { return text.match(/[\u3000-\u9fff\ue000-\uf8ff\uff01-\uffdc\uac00-\ud7af]+/g);}
|
|
} else if (o == "test")
|
|
{
|
|
//Check CJK Symbols and Punctuation
|
|
if (p == 3){ return (/[\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\uff1f\uff01\uffe5\u3000-\u303f]+/g).test(text);}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {string} id
|
|
* @returns {HTMLCanvasElement}
|
|
*/
|
|
function KinkyDungeonGetCanvas(id) {
|
|
const canvas = document.getElementById(id);
|
|
if (!(canvas instanceof HTMLCanvasElement)) throw new Error(`Not a canvas element: ${canvas.id}`);
|
|
return canvas;
|
|
}
|