249 lines
8.4 KiB
JavaScript
249 lines
8.4 KiB
JavaScript
// Dataviewjs не поддерживает импорты, кроме таких. Для обхода ограничения внутренние объекты прописываем в поля `dv`
|
||
await dv.view("scripts/henchmen/languages");
|
||
await dv.view("scripts/henchmen/norminv");
|
||
await dv.view("scripts/henchmen/races");
|
||
await dv.view("scripts/henchmen/abilities");
|
||
await dv.view("scripts/henchmen/skills");
|
||
await dv.view("scripts/henchmen/classes");
|
||
await dv.view("scripts/henchmen/backgrounds");
|
||
await dv.view("scripts/henchmen/ages");
|
||
await dv.view("scripts/henchmen/psychoTypes");
|
||
|
||
|
||
// Константы
|
||
const maxCount = 1000;
|
||
const degree = 0.7;
|
||
|
||
// Параметры фита нормальным распределением
|
||
const I_μ_a = 201.7348602;
|
||
const II_μ_a = 52.38963682;
|
||
const III_μ_a = 17.94924525;
|
||
const IV_μ_a = 7.481035692;
|
||
const V_μ_a = 3.492919247;
|
||
const VI_μ_a = 1.497346392;
|
||
let muAs = [I_μ_a, II_μ_a, III_μ_a, IV_μ_a, V_μ_a, VI_μ_a];
|
||
|
||
const I_μ_b = -1.445350459;
|
||
const II_μ_b = -1.411086938;
|
||
const III_μ_b = -1.350400144;
|
||
const IV_μ_b = -1.148846596;
|
||
const V_μ_b = -1.215297703;
|
||
const VI_μ_b = -1.421497636;
|
||
let muBs = [I_μ_b, II_μ_b, III_μ_b, IV_μ_b, V_μ_b, VI_μ_b];
|
||
|
||
const I_σ_a = 57.62483553;
|
||
const II_σ_a = 12.84292177;
|
||
const III_σ_a = 4.541993632;
|
||
const IV_σ_a = 1.906368905;
|
||
const V_σ_a = 1.667679638;
|
||
const VI_σ_a = 0.5420709982;
|
||
let muSigmaAs = [I_σ_a, II_σ_a, III_σ_a, IV_σ_a, V_σ_a, VI_σ_a];
|
||
|
||
const I_σ_b = -1.514703422;
|
||
const II_σ_b = -1.166486302;
|
||
const III_σ_b = -0.9321346977;
|
||
const IV_σ_b = -0.9380410427;
|
||
const V_σ_b = -0.6880944825;
|
||
const VI_σ_b = -0.3555551311;
|
||
let muSigmaBs = [I_σ_b, II_σ_b, III_σ_b, IV_σ_b, V_σ_b, VI_σ_b];
|
||
|
||
// Constans
|
||
let alignments = ["LG", "LN", "LE", "NG", "TN", "NE", "CG", "CN", "CE"];
|
||
|
||
|
||
function getRandomGender() {
|
||
return Math.random() < 0.68 ? "M" : "F";
|
||
}
|
||
|
||
function formatLanguages(languages) {
|
||
return languages
|
||
.map((lang) => {
|
||
let result = `${lang.name} [${lang.alphabet}`;
|
||
if (lang.speakers) {
|
||
result += `; ${lang.speakers}`;
|
||
}
|
||
result += "]";
|
||
return result;
|
||
})
|
||
.join(", ");
|
||
}
|
||
|
||
function recalc_generateHenchmen(maxCount, muA, muB, sigmaA, sigmaB, degree) {
|
||
// Функция для броска кубиков 3d6
|
||
// Переменная для хранения итогового текста
|
||
var resultText = "";
|
||
|
||
// Проход по уровням от 3 до 10
|
||
for (var level = 1; level < 8; level++) {
|
||
let mu = muA * Math.exp(muB * level ** degree);
|
||
let sigma = sigmaA * Math.exp(sigmaB * level ** degree);
|
||
|
||
var hench_count = recalc_countFromNormalDistribution(mu, sigma);
|
||
|
||
if (hench_count > 0) {
|
||
if (level !== "" && hench_count !== "") {
|
||
// Минимум между BN и maxCount
|
||
var minHenchCount = Math.min(hench_count, maxCount);
|
||
|
||
// Текст для текущего уровня
|
||
var levelText = "### Level " + level + " (" + minHenchCount + "):\n";
|
||
|
||
// Генерируем строки для персонажей (персонаж1, персонаж2, и т.д.)
|
||
for (var j = 1; j <= minHenchCount; j++) {
|
||
var alignmentIndex = Math.floor(Math.random() * alignments.length);
|
||
var randomAlignment = alignments[alignmentIndex];
|
||
|
||
let race = dv.races.selectRandomRaceAndSubrace(dv.races.races);
|
||
let raceString = "**";
|
||
// Проверка на совпадение расы и подрасы
|
||
if (race.race === race.subrace || !race.subrace) {
|
||
raceString += race.race; // Если совпадает, возвращаем только расу
|
||
} else {
|
||
raceString += `${race.subrace} ${race.race}`; // Если разные, возвращаем в формате "раса подраса"
|
||
}
|
||
raceString += "**";
|
||
|
||
let gender = getRandomGender();
|
||
|
||
let fullNameObject = dv.races.getName(race, gender);
|
||
let fullName = fullNameObject.name;
|
||
|
||
let knownLanguagesFromRace = dv.races.getLanguages(
|
||
race,
|
||
fullNameObject
|
||
);
|
||
raceString += " (" + formatLanguages(knownLanguagesFromRace) + ")";
|
||
|
||
var randomClass = dv.classes.getRandomClass();
|
||
|
||
let abilityScores = dv.abilities.getAbilityScores(randomClass);
|
||
|
||
const [ageCategory, ageExplanation, agedAbilityScores] = dv.ages.getAgeAndModifyAbilities(abilityScores);
|
||
let ageString = "**" + ageCategory + "** (" + ageExplanation + ")";
|
||
|
||
let background = dv.backgrounds.getBackground(randomClass);
|
||
let backgroundString =
|
||
background.name +
|
||
" (" +
|
||
background.skills.join(", ") +
|
||
", " +
|
||
background.tools.join(", ") +
|
||
", " +
|
||
formatLanguages(background.languages) +
|
||
")";
|
||
|
||
let chosenClassSkills = dv.backgrounds.getClassSkillsWithBackground(
|
||
randomClass,
|
||
background
|
||
);
|
||
let chosenClassSkillsString = chosenClassSkills.join(", ");
|
||
|
||
// Формируем текст с атрибутами
|
||
var attributes =
|
||
"Str " +
|
||
agedAbilityScores["Strength"] +
|
||
", Dex " +
|
||
agedAbilityScores["Dexterity"] +
|
||
", Con " +
|
||
agedAbilityScores["Constitution"] +
|
||
", Int " +
|
||
agedAbilityScores["Intelligence"] +
|
||
", Wis " +
|
||
agedAbilityScores["Wisdom"] +
|
||
", Cha " +
|
||
agedAbilityScores["Charisma"];
|
||
|
||
let psychoType = dv.psychoTypes.getPsychosocialTypeAndArchetype();
|
||
let psychoTypeString = "temperament: " + psychoType.temperament.name + ", " +
|
||
"psychosocial type: " + psychoType.psychosocialType.name + ", " +
|
||
"archetype by C.Jung: " + psychoType.archetype.name;
|
||
|
||
// Добавляем строку для персонажа с атрибутами
|
||
levelText +=
|
||
"#" +
|
||
j +
|
||
" - **" +
|
||
randomClass +
|
||
"** lvl " +
|
||
level +
|
||
"; " +
|
||
gender +
|
||
"; " +
|
||
fullName +
|
||
"; race: " +
|
||
raceString +
|
||
"; age: " +
|
||
ageString +
|
||
"; " +
|
||
attributes +
|
||
"; al " +
|
||
randomAlignment +
|
||
"; class skills: " +
|
||
chosenClassSkillsString +
|
||
"; background: " +
|
||
backgroundString +
|
||
"; " +
|
||
psychoTypeString +
|
||
".\n";
|
||
}
|
||
|
||
// Добавляем результат для текущего уровня в итоговый текст
|
||
resultText += levelText + "\n";
|
||
}
|
||
resultText += "---\n";
|
||
}
|
||
}
|
||
|
||
// Возвращаем итоговый текст
|
||
return resultText;
|
||
}
|
||
|
||
function recalc_generateNormalRandom(mu, sigma) {
|
||
return dv.norminv.generateNormalRandom(mu, sigma);
|
||
}
|
||
|
||
// =IF(μ >= 1, FLOOR(μ + σ * NORMINV(RAND(), 0, 1)), IF(RAND() <= μ, 1, 0))
|
||
function recalc_countFromNormalDistribution(mu, sigma) {
|
||
const rand = Math.random();
|
||
if (mu >= 1) {
|
||
return Math.floor(dv.norminv.generateNormalRandom(mu, sigma));
|
||
// return Math.floor(mu + sigma * norminv(rand));
|
||
} else {
|
||
return rand <= mu ? 1 : 0;
|
||
}
|
||
}
|
||
|
||
// Функция для отображения таблицы
|
||
function show_table(dv, marketLevel, basePath) {
|
||
/*// Отображаем таблицу с найденными локациями
|
||
dv.table(["Image", "Name", "Main Info"], getDescendantLocations(dv, targetLocations, basePath)); // Изменен порядок колонок*/
|
||
|
||
let curMarketMuA = muAs[marketLevel - 1];
|
||
let curMarketMuB = muBs[marketLevel - 1];
|
||
let curMarketSigmaA = muSigmaAs[marketLevel - 1];
|
||
let curMarketSigmaB = muSigmaBs[marketLevel - 1];
|
||
|
||
// Вызов функции с подстановкой значений
|
||
const result = recalc_generateHenchmen(
|
||
maxCount,
|
||
curMarketMuA,
|
||
curMarketMuB,
|
||
curMarketSigmaA,
|
||
curMarketSigmaB,
|
||
degree
|
||
);
|
||
|
||
dv.span(result);
|
||
}
|
||
|
||
// Функция для запуска отображения таблицы
|
||
function run_show_table(...args) {
|
||
let dv = args[0].arg1;
|
||
//let targetLocations = args[0].arg2;
|
||
let marketLevel = args[0].arg2;
|
||
let basePath = this.app.vault.adapter.basePath; // Получаем базовый путь к хранилищу
|
||
show_table(dv, marketLevel, basePath);
|
||
}
|
||
|
||
run_show_table(input);
|