/* eslint-disable no-unused-expressions */
/**
* @description the main randomizer namespace for the randomizer mod
* contains all methods used by the randomizer mod
* @namespace MATTIE.randomiser
* */
MATTIE.randomiser = MATTIE.randomiser || {};
/**
* @description Contains all configuration settings for the randomizer mod.
* @namespace MATTIE.randomiser.config
* */
MATTIE.randomiser.config = {};
/**
* @description whether to include dungeon knights maps for map randomization.
* !!DANGER!! this will likely result in soft locks, but is funny when it doesn't
* @default false
*/
MATTIE.randomiser.config.includeDungeonKnights;
/**
* @description whether to randomize troops or not
* @default true
* */
MATTIE.randomiser.config.randomizeTroops;
/**
* @description whether to randomize items or not
* @default true
*/
MATTIE.randomiser.config.randomizeItems;
/**
* @description whether to randomize armors or not
* @default true
* */
MATTIE.randomiser.config.randomizeArmors;
/**
* @description whether to randomize weapons or not
* @default true
* */
MATTIE.randomiser.config.randomizeWeapons;
/**
* @description whether to randomize enemies or not. Note that this means randomizing the limbs
* that troops are composed of.
* !!Danger!! this will make the game quite incomprehensible but it shouldn't actually crash
* @default false
*/
MATTIE.randomiser.config.randomizeEnemies;
/**
* @description whether to randomize skills or not
* @default true
*/
MATTIE.randomiser.config.randomizeSkills;
/**
* @description whether to randomize classes or not
* !!DANGER!! tends to break things --if class gets switched with nashrah or test or... then it will break etc...
* @default false
*/
MATTIE.randomiser.config.randomizeClasses;
/**
* @description whether to randomize maps or not
* @default true
* Works as long as you can use the books in your inventory to recover from softlocks
* Ex Altiora lets you use the airship to get un stuck
* and The Seven Lamps of Arcitecture lets you teleport to a new room (sometimes) if you got stuck.
* */
MATTIE.randomiser.config.randomizeMaps;
/**
* @description whether to randomize animations or not
* @default true
* */
MATTIE.randomiser.config.randomizeAnimations;
/**
* @description whether to randomize states or not
* @default true
* */
MATTIE.randomiser.config.randomizeStates;
/**
* @description whether to randomize common events or not
* !!DANGER!! This will crash the game. Its funny but it is not safe and will blow up.
* @default false
* */
MATTIE.randomiser.config.commonEvents = false;
/**
* @description whether to make it so every door you walk through will always lead to a new location instead of having a memory and a set layout of the dungeon.
* @default false
*/
MATTIE.randomiser.config.noFloorMemory = false;
Object.defineProperties(MATTIE.randomiser.config, {
includeDungeonKnights: {
get: () => MATTIE.configGet('includeDungeonKnights', false),
set: (value) => { MATTIE.configSet('includeDungeonKnights', value); },
},
randomizeTroops: {
get: () => MATTIE.configGet('randomizeTroops', true),
set: (value) => { MATTIE.configSet('randomizeTroops', value); },
},
randomizeItems: {
get: () => MATTIE.configGet('randomizeItems', true),
set: (value) => { MATTIE.configSet('randomizeItems', value); },
},
randomizeArmors: {
get: () => MATTIE.configGet('randomizeArmors', true),
set: (value) => { MATTIE.configSet('randomizeArmors', value); },
},
randomizeClasses: {
get: () => MATTIE.configGet('randomizeClasses', false),
set: (value) => { MATTIE.configSet('randomizeClasses', value); },
},
randomizeEnemies: {
get: () => MATTIE.configGet('randomizeEnemies', false),
set: (value) => { MATTIE.configSet('randomizeEnemies', value); },
},
randomizeMaps: {
get: () => MATTIE.configGet('randomizeMaps', true),
set: (value) => { MATTIE.configSet('randomizeMaps', value); },
},
randomizeStates: {
get: () => MATTIE.configGet('randomizeStates', true),
set: (value) => { MATTIE.configSet('randomizeStates', value); },
},
randomizeAnimations: {
get: () => MATTIE.configGet('randomizeAnimations', true),
set: (value) => { MATTIE.configSet('randomizeAnimations', value); },
},
randomizeWeapons: {
get: () => MATTIE.configGet('randomizeWeapons', true),
set: (value) => { MATTIE.configSet('randomizeWeapons', value); },
},
noFloorMemory: {
get: () => MATTIE.configGet('noFloorMemory', false),
set: (value) => { MATTIE.configSet('noFloorMemory', value); },
},
randomizeSkills: {
get: () => MATTIE.configGet('randomizeSkills', true),
set: (value) => { MATTIE.configSet('randomizeSkills', value); },
},
});
MATTIE.static = MATTIE.static || {};
// eslint-disable-next-line import/no-unresolved
const randomizerName = require('./mods/randomiser.json').name;
const params = PluginManager.parameters(randomizerName);
// setup the seed for the rng
if (params.seed === 'random') {
// if random string randomize the seed
MATTIE.util.setSeed(MATTIE.supporters.getRandomSupporter());
} else {
// else use provided
MATTIE.util.setSeed(params.seed);
}
/**
* @description the base filter callback for the shuffle method
* @param {*} e the elemnt to check if it exists
* @param {string} attrib the attribute to use to check if element is defined
* @returns {boolean}
*/
MATTIE.randomiser.baseShuffleFilter = function (e, attrib) {
if (e != null) {
if (typeof e[attrib] != 'undefined') {
if (e[attrib] != '') {
return true;
}
} else {
return true;
}
}
return false;
};
/**
* @description shuffle an array randomly and then ensure that if the elements had an
* id property to fix the id to be the new index
* @param {Array} arr the array to shuffle
* @param {string} attrib the atribute to use to check if an element is defined
* @param {function} filterCb the callback used by the filter method when filtering the original list.
* @param {function} cb (optional) a cb to call on each element after they are shuffled and the element and index are passed to it so (element, index)
* @returns {Array} the shuffled array. Note this method is destructive so the original array is also modified
*/
MATTIE.randomiser.shuffle = function (arr, attrib = 'name', cb = () => {}, filterCb = null) {
if (filterCb === null) {
filterCb = (e) => this.baseShuffleFilter(e, attrib);
}
const realArr = arr.filter(filterCb);
realArr.sort(() => MATTIE.util.seedRandom() - 0.5);
let j = 0;
let i = 0;
arr.map((e) => {
if (filterCb(e) && typeof realArr[i] != 'undefined') {
if (typeof e[attrib] != 'undefined') {
if (e[attrib] != '') {
arr[j] = realArr[i];
i++;
}
} else {
arr[j] = realArr[i];
i++;
}
}
j++;
return null;
});
for (let index = 0; index < arr.length; index++) {
const element = arr[index];
cb(element, index);
if (element) {
if (element.id) {
arr[index].id = index;
}
}
}
return arr;
};
/**
* @description shuffle the troops array and fix ids
*/
MATTIE.randomiser.shuffleTroops = function () {
this.shuffle($dataTroops);
};
/**
* @description shuffle the items array and fix ids
*/
MATTIE.randomiser.shuffleItems = function () {
this.shuffle($dataItems);
};
/**
* @description shuffle the armor array and fix ids
*/
MATTIE.randomiser.shuffleArmors = function () {
this.shuffle($dataArmors);
};
/**
* @description shuffle the armor array and fix ids
*/
MATTIE.randomiser.shuffleWeapons = function () {
this.shuffle($dataWeapons);
};
/**
* @description shuffle the enemies array and fix ids.
* note: because funger stores limbs as enemies this will result in utter chaos with troops being composed of random limbs of random creatures
*/
MATTIE.randomiser.shuffleEnemies = function () {
this.shuffle($dataEnemies);
};
/**
* @description shuffle the skills array and fix ids.
* note: because skills contain both player and enemy skills this will result in very very weird things
*/
MATTIE.randomiser.shuffleSkills = function () {
const excludedSkills = [
1, // player should always be allowed to attack
2, // player should always be allowed to gaurd
11, // player should always be allowed to talk
40, // player should be able to run
];
this.shuffle($dataSkills, 'name', () => {}, (e) => {
const baseFilterRes = this.baseShuffleFilter(e, 'name');
let passes = true;
if (e) {
if (e.id) {
passes = !excludedSkills.includes(e.id);
}
}
return baseFilterRes && passes;
});
};
/**
* @description shuffle the classes array and fix ids.
* note: this will randomize starting abilities and stats IE: merc could have war cry or nash'ra abilities, etc...
*/
MATTIE.randomiser.shuffleClasses = function () {
this.shuffle($dataClasses);
};
/**
* @description shuffle the animations array and fix ids.
* note: Fear and hunger doesn't really use animations the way it should so this might not be as chaotic as expected but will result in very
* very weird things
*/
MATTIE.randomiser.shuffleAnimations = function () {
this.shuffle($dataAnimations);
};
/**
* @description shuffle the common events array and fix ids.
* Note: This will almost certainly break things completely, this is the most likely to crash the game.
*/
MATTIE.randomiser.shuffleCommonEvents = function () {
this.shuffle($dataCommonEvents);
};
/**
* @description shuffle the mapsinfo array and fix ids.
*/
MATTIE.randomiser.shuffleMapInfo = function () {
let excludedMapIds = [0, 78, 19, 60, 79, 81, 82, 83, 84, 74, 183];
excludedMapIds = excludedMapIds.concat(MATTIE.static.maps.menuMaps); // exclude menus
excludedMapIds = excludedMapIds.concat(MATTIE.static.blockingMaps);
if (!MATTIE.randomiser.config.includeDungeonKnights) excludedMapIds = excludedMapIds.concat(MATTIE.static.dungeonKnights);
this.shuffle($dataMapInfos, 'name', (element, index) => {
// if (element) { if (element.id) };
}, (e) => {
const baseFilterRes = this.baseShuffleFilter(e, 'name');
let passes = false;
if (e) {
if (e.id) {
passes = !excludedMapIds.includes(e.id) && !excludedMapIds.includes(parseInt(e.id, 10));
if (passes) {
e.orgId = e.id;
}
}
}
return (baseFilterRes && passes);
});
};
/**
* @description shuffle the maps array and fix ids.
*/
MATTIE.randomiser.shuffleMaps = function () {
const that = this;
this.shuffleMapInfo();
this.idMappings = {};
this.doorMappings = {};
for (let index = 0; index < $dataMapInfos.length; index++) {
const e = $dataMapInfos[index];
if (e) {
if (e.orgId) {
this.idMappings[e.orgId] = e.id;
}
}
}
if (!this.mapsCmdInited) {
const lastFunc = Game_Player.prototype.reserveTransfer;
Game_Player.prototype.reserveTransfer = function (baseMapId, x, y, d, fadeType, letBase = false) {
let mapId = false;
that.oldMapId = $gameMap.mapId();
that.oldX = $gamePlayer.x;
that.oldY = $gamePlayer.y;
that.baseMapId = baseMapId;
if (!letBase) {
mapId = that.idMappings[baseMapId];
}
if (!mapId) mapId = baseMapId;
if (!that.doorMappings[that.oldMapId]) that.doorMappings[that.oldMapId] = {};
if (!that.doorMappings[that.oldMapId][that.oldX]) that.doorMappings[that.oldMapId][that.oldX] = {};
if (!that.doorMappings[that.oldMapId][that.oldX][that.oldY]) that.doorMappings[that.oldMapId][that.oldX][that.oldY] = {};
return lastFunc.call(this, mapId, x, y, d, fadeType);
};
Game_Interpreter.prototype.command201 = function () {
if (MATTIE.randomiser.config.noFloorMemory) MATTIE.randomiser.shuffleMaps();
if (!$gameParty.inBattle() && !$gameMessage.isBusy()) {
var mapId; var x; var
y;
if (this._params[0] === 0) { // Direct designation
mapId = this._params[1];
x = this._params[2];
y = this._params[3];
} else { // Designation with variables
mapId = $gameVariables.value(this._params[1]);
x = $gameVariables.value(this._params[2]);
y = $gameVariables.value(this._params[3]);
}
$gamePlayer.reserveTransfer(mapId, x, y, this._params[4], this._params[5], this._params[6]);
this.setWaitMode('transfer');
this._index++;
}
return false;
};
const lastPerform = Game_Player.prototype.performTransfer;
Game_Player.prototype.performTransfer = function () {
console.log(`mapid:${this._newMapId}\nx:${this._newX}\ny:${this._newY}`);
$gamePlayer.setTransparent(false);
const oldMap = $gameMap.mapId();
const x = $gamePlayer.x;
const y = $gamePlayer.y;
lastPerform.call(this);
setTimeout(() => {
let realSpot;
if (Object.keys(that.doorMappings[that.oldMapId][that.oldX][that.oldY]).length <= 0) {
const spots = MATTIE.betterCrowMauler.CrowController.prototype.getAllTransferPointsOnMap();
const spot = spots[MATTIE.util.randBetween(0, spots.length - 1)];
if (spot) {
console.log('tp to spot:');
console.log(spot);
realSpot = MATTIE.betterCrowMauler.CrowController.prototype.findNearestPassablePoint(50, 50, spot.x, spot.y);
} else {
console.log('middle of map tp');
// eslint-disable-next-line max-len
realSpot = MATTIE.betterCrowMauler.CrowController.prototype.findNearestPassablePoint(50, 50, $gameMap.width() / 2, $gameMap.height() / 2);
}
realSpot.mapId = this._newMapId;
that.doorMappings[that.oldMapId][that.oldX][that.oldY] = realSpot;
} else {
realSpot = that.doorMappings[that.oldMapId][that.oldX][that.oldY];
this._newMapId = realSpot.mapId;
}
$gamePlayer.locate(realSpot.x, realSpot.y);
for (let x1 = -3; x1 < 3; x1++) {
for (let y1 = -3; y1 < 3; y1++) {
const events = $gameMap.eventsXy(realSpot.x + x1, realSpot.y + y1);
events.forEach((event) => {
if (event && event.list) {
event.event().pages.forEach((page) => {
page.list.forEach((cmd) => {
if (cmd.code === MATTIE.static.commands.transferId) {
const obj = {};
obj.x = x;
obj.y = y;
obj.mapId = $gameMap.lastMapId();
cmd.parameters[1] = $gameMap.lastMapId();
cmd.parameters[2] = x;
cmd.parameters[3] = y;
cmd.parameters[6] = true;
if (!that.doorMappings[$gameMap.mapId()]) that.doorMappings[$gameMap.mapId()] = {};
// eslint-disable-next-line max-len
if (!that.doorMappings[$gameMap.mapId()][realSpot.x + x1]) that.doorMappings[$gameMap.mapId()][realSpot.x + x1] = {};
// eslint-disable-next-line max-len
if (!that.doorMappings[$gameMap.mapId()][realSpot.x + x1][realSpot.y + y1]) { that.doorMappings[$gameMap.mapId()][realSpot.x + x1][realSpot.y + y1] = {}; }
that.doorMappings[$gameMap.mapId()][realSpot.x + x1][realSpot.y + y1] = obj;
// mapId = this._params[1];
// x = this._params[2];
// y = this._params[3];
}
});
});
}
});
}
}
}, 500);
};
}
this.mapsCmdInited = true;
// DataManager.loadMapData = function (baseMapId) {
// let mapId = idMappings[baseMapId];
// if (!mapId) mapId = baseMapId;
// if (mapId > 0) {
// var filename = 'Map%1.json'.format((29).padZero(3));
// this._mapLoader = ResourceHandler.createLoader(`data/${filename}`, this.loadDataFile.bind(this, '$dataMap', filename));
// this.loadDataFile('$dataMap', filename);
// } else {
// this.makeEmptyMap();
// }
// };
// Scene_Map.prototype.create = function () {
// Scene_Base.prototype.create.call(this);
// this._transfer = $gamePlayer.isTransferring();
// var baseMapId = this._transfer ? $gamePlayer.newMapId() : $gameMap.mapId();
// let mapId = idMappings[baseMapId];
// if (!mapId) mapId = baseMapId;
// DataManager.loadMapData(mapId);
// };
// Game_Map.prototype.setup = function (baseMapId) {
// let mapId = idMappings[baseMapId];
// if (!mapId) mapId = baseMapId;
// if (!$dataMap) {
// throw new Error('The map data is not available');
// }
// this._mapId = mapId;
// this._tilesetId = $dataMap.tilesetId;
// this._displayX = 0;
// this._displayY = 0;
// this.refereshVehicles();
// this.setupEvents();
// this.setupScroll();
// this.setupParallax();
// this.setupBattleback();
// this._needsRefresh = false;
// };
};
/**
* @description shuffle the states array and fix ids.
* Note: This will break things given the knockout state and resist death state will be shuffled, they will need to be hardcoded to stay put.
*/
MATTIE.randomiser.shuffleStates = function () {
const excludedStates = [1, 13, 36];
this.shuffle($dataMapInfos, 'name', (element, index) => {
// if (element) { if (element.id) };
}, (e) => {
const baseFilterRes = this.baseShuffleFilter(e, 'name');
let passes = false;
if (e) {
if (e.id) {
passes = !excludedStates.includes(e.id) && !excludedStates.includes(parseInt(e.id, 10));
}
}
return (baseFilterRes && passes);
});
};
/**
* @description shuffle the tilesets array and fix ids.
* Note: this shouldn't break anything but will make the game very very ugly and not in a funny way (likely)
*/
MATTIE.randomiser.shuffleTilesets = function () {
this.shuffle($dataTilesets);
};
/**
* @description only randomize in places where it will not cause major issues.
*/
MATTIE.randomiser.safeShuffle = function () {
const that = this;
if (MATTIE.randomiser.config.randomizeStates) this.shuffleStates();
if (MATTIE.randomiser.config.randomizeAnimations) this.shuffleAnimations();
if (MATTIE.randomiser.config.randomizeArmors) this.shuffleArmors();
if (MATTIE.randomiser.config.randomizeClasses) this.shuffleClasses();
if (MATTIE.randomiser.config.randomizeEnemies) this.shuffleEnemies();
if (MATTIE.randomiser.config.randomizeItems) this.shuffleItems();
if (MATTIE.randomiser.config.commonEvents) this.shuffleCommonEvents();
if (MATTIE.randomiser.config.randomizeMaps) {
this.shuffleMaps();
const bookOfLamps = new MATTIE.itemAPI.RunTimeItem();
bookOfLamps.addRecipe([11, 87, 98], 98);
bookOfLamps.addRecipeUnlock(11);
bookOfLamps.addRecipeUnlock(87);
bookOfLamps.setIconIndex(261);
bookOfLamps.setName('The Seven Lamps of Architecture');
bookOfLamps.setDescription('A book that emits the feeling of walls pressing in around you.\nWhen used in moderation can shift reality.');
bookOfLamps.setItemType(2); // set book
bookOfLamps.setCallback(() => {
SceneManager.goto(Scene_Map);
setTimeout(() => {
MATTIE.fxAPI.startScreenShake(10, 10, 5);
MATTIE.fxAPI.startScreenShake(10, 10, 50);
MATTIE.fxAPI.setupTint(100, 255, 100, 200, 10);
const keys = Object.keys(that.idMappings);
const mapId = that.idMappings[keys[MATTIE.util.randBetween(0, keys.length - 1)]];
$gamePlayer.reserveTransfer(mapId, $gameMap.width() / 2, $gameMap.height() / 2);
setTimeout(() => {
$gamePlayer.performTransfer();
}, 500);
}, 200);
});
Input.addKeyBind('', bookOfLamps.cb, 'Seven Lamps', 0);
bookOfLamps.spawn();
const exAltiora = new MATTIE.itemAPI.RunTimeItem();
exAltiora.addRecipe([11, 87, 98], 98);
exAltiora.addRecipeUnlock(11);
exAltiora.addRecipeUnlock(87);
exAltiora.setIconIndex(261);
exAltiora.setName('Ex Altiora');
exAltiora.setDescription('A virgil-style poem intermixed with intricate wood carvings of mountains.\nThe book evokes feelings of vertigo.');
exAltiora.setItemType(2); // set book
exAltiora.setCallback(() => {
SceneManager.goto(Scene_Map);
setTimeout(() => {
var vehicle = $gameMap.vehicle('airship');
if (vehicle) {
vehicle.setLocation($gameMap.mapId(), $gamePlayer.x, $gamePlayer.y);
}
$gamePlayer.getOnOffVehicle();
}, 500);
});
Input.addKeyBind('', exAltiora.cb, 'Ex Altiora', 0);
exAltiora.spawn();
const mapInit = Game_Map.prototype.initialize;
Game_Map.prototype.initialize = function () {
mapInit.call(this);
setTimeout(() => {
$gameParty.gainItem(bookOfLamps._data, 1, false);
$gameParty.gainItem(exAltiora._data, 1, false);
}, 500);
};
}
if (MATTIE.randomiser.config.randomizeSkills) this.shuffleSkills();
if (MATTIE.randomiser.config.randomizeTroops) this.shuffleTroops();
if (MATTIE.randomiser.config.randomizeWeapons) this.shuffleWeapons();
};
MATTIE.randomiser.randomise = function () {
this.safeShuffle();
};
MATTIE.randomiser.randomise();
// supress audio warning
WebAudio.prototype._load = function (url) {
try {
if (WebAudio._context) {
var xhr = new XMLHttpRequest();
if (Decrypter.hasEncryptedAudio) url = Decrypter.extToEncryptExt(url);
xhr.open('GET', url);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
if (xhr.status < 400) {
this._onXhrLoad(xhr);
}
}.bind(this);
// xhr.onerror = this._loader || function () { this._hasError = true; }.bind(this);
xhr.send();
}
} catch (error) {
//
}
};