Mediawiki:scmcchemistry.js
| Строка 2: | Строка 2: | ||
* Интерактивный каталог химии SSMC. | * Интерактивный каталог химии SSMC. | ||
* Страница: MC:Химия | * Страница: MC:Химия | ||
* Данные: | * Данные: DeferW/ssmc-wiki-data | ||
*/ | */ | ||
(function () { | (function () { | ||
| Строка 20: | Строка 20: | ||
]; | ]; | ||
var | var DAMAGE_LABELS = { | ||
Airloss: 'урона от кислородного голодания', | |||
Asphyxiation: 'урона от кислородного голодания', | |||
Bloodloss: 'урона от кровопотери', | |||
Blunt: 'тупого урона', | |||
Brute: 'механического урона', | |||
Burn: 'термического урона', | |||
Caustic: 'кислотного урона', | |||
Cellular: 'клеточного урона', | |||
Cold: 'холодового урона', | |||
Genetic: 'генетического урона', | |||
Heat: 'ожогового урона', | |||
Piercing: 'колотого урона', | |||
Poison: 'токсического урона', | |||
Radiation: 'радиационного урона', | |||
Slash: 'режущего урона', | |||
Toxin: 'токсического урона' | |||
}; | }; | ||
var | var STATUS_LABELS = { | ||
Jitter: 'дрожь', | |||
RMCUnconscious: 'потерю сознания', | |||
StatusEffectSeeingRainbow: 'галлюцинации', | |||
Unconscious: 'потерю сознания' | |||
}; | |||
var EMOTE_LABELS = { | |||
Gasp: 'судорожный вдох', | |||
Laugh: 'смех', | |||
Scream: 'крик', | |||
Yawn: 'зевоту' | |||
}; | |||
var PLANT_ATTRIBUTE_LABELS = { | |||
PlantAdjustGrowth: 'возраст растения', | |||
PlantAdjustHealth: 'здоровье растения', | |||
PlantAdjustMutationLevel: 'уровень мутации', | |||
PlantAdjustMutationMod: 'модификатор мутации', | |||
PlantAdjustNutrition: 'уровень питания', | |||
PlantAdjustPests: 'уровень вредителей', | |||
PlantAdjustPotency: 'потенцию растения', | |||
PlantAdjustToxins: 'уровень токсинов', | |||
PlantAdjustWater: 'уровень воды', | |||
PlantAdjustWeeds: 'уровень сорняков', | |||
PlantAffectGrowth: 'возраст растения' | |||
}; | }; | ||
| Строка 126: | Строка 115: | ||
function formatAmount(value) { | function formatAmount(value) { | ||
return formatNumber(value) + ' ед.'; | return formatNumber(value) + ' ед.'; | ||
} | |||
function capitalizeFirst(value) { | |||
var text = String(value || ''); | |||
if (!text) { | |||
return text; | |||
} | |||
return text.charAt(0).toLocaleUpperCase('ru-RU') + text.slice(1); | |||
} | |||
function finishSentence(value) { | |||
var text = capitalizeFirst(String(value || '').trim()); | |||
if (!text || /[.!?]$/.test(text)) { | |||
return text; | |||
} | |||
return text + '.'; | |||
} | } | ||
| Строка 203: | Строка 212: | ||
return state.data.guides[tabId] || []; | return state.data.guides[tabId] || []; | ||
} | |||
function effectValue(effect) { | |||
var value = effect && effect.value; | |||
return value && typeof value === 'object' ? value : {}; | |||
} | |||
function lowerFirst(value) { | |||
var text = String(value || ''); | |||
return text ? text.charAt(0).toLocaleLowerCase('ru-RU') + text.slice(1) : text; | |||
} | |||
function withChance(text, probability) { | |||
if (typeof probability !== 'number' || probability >= 1) { | |||
return finishSentence(text); | |||
} | |||
return finishSentence('С шансом ' + formatNumber(probability * 100) + '% ' + lowerFirst(text)); | |||
} | } | ||
function conditionText(condition) { | function conditionText(condition) { | ||
var type = tagName(condition && condition.yamlTag); | var type = tagName(condition && condition.yamlTag); | ||
var value = condition | var value = effectValue(condition); | ||
if (type === 'ReagentThreshold') { | if (type === 'ReagentThreshold') { | ||
| Строка 215: | Строка 241: | ||
} | } | ||
if (value.min !== undefined) { | if (value.min !== undefined) { | ||
return 'от ' + formatAmount(value.min) + ' в организме'; | return 'при количестве от ' + formatAmount(value.min) + ' в организме'; | ||
} | } | ||
if (value.max !== undefined) { | if (value.max !== undefined) { | ||
return 'до ' + formatAmount(value.max) + ' в организме'; | return 'при количестве до ' + formatAmount(value.max) + ' в организме'; | ||
} | } | ||
} | } | ||
if (type === 'Temperature') { | if (type === 'Temperature') { | ||
if (value.min !== undefined && value.max !== undefined) { | |||
return 'при температуре от ' + formatNumber(value.min) + ' до ' + formatNumber(value.max) + ' K'; | |||
} | |||
if (value.min !== undefined) { | if (value.min !== undefined) { | ||
return 'при температуре не ниже ' + formatNumber(value.min) + ' K'; | return 'при температуре не ниже ' + formatNumber(value.min) + ' K'; | ||
| Строка 232: | Строка 261: | ||
if (type === 'MobStateCondition') { | if (type === 'MobStateCondition') { | ||
return value.mobstate === 'Critical' ? 'в критическом состоянии' : ' | return value.mobstate === 'Critical' ? 'в критическом состоянии' : 'в состоянии «' + (value.mobstate || 'неизвестно') + '»'; | ||
} | } | ||
if (type === 'OrganType') { | if (type === 'OrganType') { | ||
return (value.shouldHave === false ? 'кроме типа ' : 'для типа ') + (value.type || 'неизвестно'); | return (value.shouldHave === false ? 'кроме организмов типа ' : 'для организмов типа ') + (value.type || 'неизвестно'); | ||
} | } | ||
return type ? ' | return type ? 'при выполнении условия «' + type + '»' : ''; | ||
} | |||
function thresholdMinimum(effect) { | |||
var conditions = effectValue(effect).conditions; | |||
var minimum = null; | |||
if (!Array.isArray(conditions)) { | |||
return minimum; | |||
} | |||
conditions.forEach(function (condition) { | |||
if (tagName(condition && condition.yamlTag) !== 'ReagentThreshold') { | |||
return; | |||
} | |||
var value = effectValue(condition); | |||
if (typeof value.min === 'number' && (minimum === null || value.min > minimum)) { | |||
minimum = value.min; | |||
} | |||
}); | |||
return minimum; | |||
} | } | ||
function | function effectTier(effect, reagent) { | ||
var | var minimum = thresholdMinimum(effect); | ||
var properties = reagent.properties || {}; | |||
if ( | if (minimum === null) { | ||
return ''; | return 'normal'; | ||
} | |||
if (typeof properties.criticalOverdose === 'number' && minimum >= properties.criticalOverdose) { | |||
return 'critical'; | |||
} | |||
if (typeof properties.overdose === 'number' && minimum >= properties.overdose) { | |||
return 'overdose'; | |||
} | } | ||
return 'normal'; | |||
} | |||
function remainingConditions(effect, reagent) { | |||
var conditions = effectValue(effect).conditions; | |||
if (!Array.isArray(conditions)) { | |||
return []; | |||
} | |||
if ( | return conditions.map(function (condition) { | ||
return; | if (tagName(condition && condition.yamlTag) === 'ReagentThreshold' && effectTier(effect, reagent) !== 'normal') { | ||
return ''; | |||
} | } | ||
return conditionText(condition); | |||
}).filter(Boolean); | |||
} | |||
function damageChanges(damage, equalGroups) { | |||
var entries = []; | |||
if (equalGroups && Array.isArray(damage)) { | |||
damage.forEach(function (entry) { | |||
var key = Object.keys(entry || {})[0]; | |||
if (key) { | |||
entries.push({ id: key, amount: entry[key] }); | |||
} | |||
}); | |||
} else if (damage && typeof damage === 'object') { | |||
['groups', 'types'].forEach(function (key) { | |||
var values = damage[key]; | |||
if (!values || typeof values !== 'object') { | |||
return; | |||
} | |||
Object.keys(values).forEach(function (damageId) { | |||
entries.push({ id: damageId, amount: values[damageId] }); | |||
}); | |||
}); | }); | ||
} | |||
return entries.map(function (entry) { | |||
var action = entry.amount < 0 ? 'Лечит' : 'Наносит'; | |||
return action + ' ' + formatNumber(Math.abs(entry.amount)) + ' ед. ' + (DAMAGE_LABELS[entry.id] || ('урона типа «' + entry.id + '»')) + ' в секунду'; | |||
}); | }); | ||
} | |||
return | function doseDescription(tier, text) { | ||
return { tier: tier, text: finishSentence(text) }; | |||
} | } | ||
function | function addDoseEffects(result, reagent, overdoseText, criticalText) { | ||
if (! | var properties = reagent.properties || {}; | ||
if (properties.overdose !== undefined && overdoseText) { | |||
result.push(doseDescription('overdose', overdoseText)); | |||
} | |||
if (properties.criticalOverdose !== undefined && criticalText) { | |||
result.push(doseDescription('critical', criticalText)); | |||
} | } | ||
} | |||
function rmcEffectDescriptions(type, value, reagent) { | |||
var result = []; | |||
var potency = Number(value.potency || 0); | |||
var actual = potency * 0.5; | |||
var perSecond = potency * 0.25; | |||
var healing; | |||
if (type === 'Neogenetic') { | |||
healing = perSecond * (actual > 2 ? 1.5 : 1); | |||
result.push(doseDescription('normal', 'Лечит ' + formatNumber(healing) + ' ед. механического урона в секунду')); | |||
addDoseEffects(result, reagent, | |||
'Наносит ' + formatNumber(perSecond) + ' ед. ожогового урона в секунду', | |||
'Дополнительно наносит ' + formatNumber(perSecond * 5) + ' ед. ожогового и ' + formatNumber(perSecond * 2) + ' ед. токсического урона в секунду'); | |||
return result; | |||
} | |||
if (type === 'Anticorrosive') { | |||
healing = perSecond * (actual > 2 ? 1.5 : 1); | |||
result.push(doseDescription('normal', 'Лечит ' + formatNumber(healing) + ' ед. термического урона в секунду')); | |||
addDoseEffects(result, reagent, | |||
'Наносит по ' + formatNumber(perSecond) + ' ед. тупого и токсического урона в секунду', | |||
'Дополнительно наносит по ' + formatNumber(perSecond * 5) + ' ед. тупого и токсического урона в секунду'); | |||
return result; | |||
} | |||
if ( | if (type === 'Biocidic') { | ||
result.push(doseDescription('normal', 'Наносит ' + formatNumber(perSecond) + ' ед. механического урона в секунду')); | |||
addDoseEffects(result, reagent, | |||
'Наносит ' + formatNumber(perSecond * 2) + ' ед. механического урона в секунду', | |||
'Дополнительно наносит ' + formatNumber(perSecond * 5) + ' ед. механического урона в секунду'); | |||
return result; | |||
} | } | ||
if ( | |||
if (type === 'Antitoxic') { | |||
result.push(doseDescription('normal', 'Лечит по ' + formatNumber(perSecond * 2) + ' ед. токсического и генетического урона в секунду; удаляет 0,125 ед. токсичных веществ из крови в секунду')); | |||
addDoseEffects(result, reagent, '', 'Дополнительно даёт 5% шанс потерять сознание на 10 секунд'); | |||
return result; | |||
} | } | ||
if ( | |||
if (type === 'Oxygenating') { | |||
result.push(doseDescription('normal', actual >= 3 | |||
? 'Полностью лечит урон от кислородного голодания и удаляет ' + formatAmount(perSecond) + ' Лексорина из крови в секунду' | |||
: 'Лечит ' + formatNumber(perSecond) + ' ед. урона от кислородного голодания и удаляет ' + formatAmount(perSecond) + ' Лексорина из крови в секунду')); | |||
addDoseEffects(result, reagent, | |||
'Наносит ' + formatNumber(perSecond * 0.5) + ' ед. токсического урона в секунду', | |||
'Дополнительно наносит ' + formatNumber(perSecond) + ' ед. тупого и ' + formatNumber(perSecond * 2) + ' ед. токсического урона в секунду'); | |||
return result; | |||
} | } | ||
if ( | |||
if (type === 'Electrogenetic') { | |||
result.push(doseDescription('normal', 'При дефибрилляции лечит по ' + formatNumber(potency * 10) + ' ед. механического, термического и токсического урона; расходует 1 ед. препарата')); | |||
return result; | |||
} | } | ||
if ( | |||
if (type === 'Antihallucinogenic') { | |||
result.push(doseDescription('normal', 'Удаляет по 2,5 ед. Токсина «Разрушитель разума» и космических наркотиков из крови; сокращает галлюцинации на ' + formatNumber(perSecond * 10) + ' сек. каждую секунду')); | |||
addDoseEffects(result, reagent, | |||
'Наносит ' + formatNumber(perSecond) + ' ед. токсического урона в секунду', | |||
'Дополнительно наносит по ' + formatNumber(perSecond) + ' ед. тупого и ожогового урона, а также ' + formatNumber(perSecond * 3) + ' ед. токсического урона в секунду'); | |||
return result; | |||
} | } | ||
if ( | |||
if (type === 'Focusing') { | |||
result.push(doseDescription('normal', 'Удаляет ' + formatAmount(perSecond) + ' алкоголя из крови и сокращает опьянение, заикание и дрожь на ' + formatNumber(perSecond * 2) + ' сек. каждую секунду' + (actual >= 3 ? '; также снимает немоту и слепоту' : ''))); | |||
addDoseEffects(result, reagent, | |||
'Наносит ' + formatNumber(perSecond) + ' ед. токсического урона в секунду', | |||
'Дополнительно наносит ' + formatNumber(perSecond * 3) + ' ед. токсического урона в секунду'); | |||
return result; | |||
} | } | ||
if (type === ' | |||
if (type === 'Thermostabilizing') { | |||
result.push(doseDescription('normal', 'Возвращает температуру тела к норме, изменяя её примерно на ' + formatNumber(perSecond * 60) + ' K в секунду')); | |||
addDoseEffects(result, reagent, | |||
'Вызывает потерю сознания на 40 секунд', | |||
'Дополнительно даёт 5% шанс потерять сознание на 10 секунд'); | |||
return result; | |||
} | } | ||
if (type === ' | |||
if (type === 'Hemogenic') { | |||
result.push(doseDescription('normal', 'Если персонаж не голоден, восстанавливает ' + formatNumber(perSecond) + ' сл крови и расходует ' + formatNumber(perSecond) + ' ед. питания в секунду')); | |||
if (actual > 3) { | |||
if ( | result.push(doseDescription('normal', 'При избытке крови наносит ' + formatNumber(perSecond) + ' ед. тупого и ' + formatNumber(perSecond * 2) + ' ед. урона от кислородного голодания в секунду, а также замедляет')); | ||
} | } | ||
addDoseEffects(result, reagent, | |||
'Наносит ' + formatNumber(perSecond) + ' ед. токсического урона в секунду', | |||
'Дополнительно расходует ' + formatNumber(perSecond * 5) + ' ед. питания в секунду'); | |||
return result; | |||
} | |||
if (type === 'Ketogenic') { | |||
result.push(doseDescription('normal', 'Расходует ' + formatNumber(perSecond * 5) + ' ед. питания в секунду и ускоряет выведение алкоголя')); | |||
addDoseEffects(result, reagent, | |||
'Дополнительно расходует ' + formatNumber(perSecond * 5) + ' ед. питания, наносит ' + formatNumber(perSecond) + ' ед. токсического урона в секунду и даёт ' + formatNumber(actual * 2.5) + '% шанс рвоты', | |||
'Вызывает потерю сознания на 40 секунд'); | |||
return result; | |||
} | |||
if (type === 'Nutritious') { | |||
var nutrition = ((Number(value.nutFactor || 0) * Number(value.nutMetabolism || 0)) + potency) * actual; | |||
result.push(doseDescription('normal', 'Восстанавливает ' + formatNumber(nutrition) + ' ед. питания за цикл метаболизма')); | |||
return result; | |||
} | |||
if (type === 'Toxic') { | |||
result.push(doseDescription('normal', 'Наносит ' + formatNumber(perSecond) + ' ед. токсического урона в секунду')); | |||
addDoseEffects(result, reagent, | |||
'Наносит ' + formatNumber(perSecond * 2) + ' ед. токсического урона в секунду', | |||
'Дополнительно наносит ' + formatNumber(perSecond * 5) + ' ед. токсического урона в секунду'); | |||
return result; | |||
} | |||
if (type === 'Corrosive') { | |||
result.push(doseDescription('normal', 'Наносит ' + formatNumber(perSecond) + ' ед. кислотного урона в секунду')); | |||
addDoseEffects(result, reagent, | |||
'Наносит ' + formatNumber(perSecond * 2) + ' ед. кислотного урона в секунду', | |||
'Дополнительно наносит ' + formatNumber(perSecond * 5) + ' ед. кислотного урона в секунду'); | |||
return result; | |||
} | |||
if (type === 'Hypoxemic') { | |||
result.push(doseDescription('normal', 'Наносит ' + formatNumber(perSecond * 2) + ' ед. урона от кислородного голодания в секунду и даёт 10% шанс судорожного вдоха')); | |||
addDoseEffects(result, reagent, | |||
'Наносит по ' + formatNumber(perSecond) + ' ед. тупого и токсического урона, а также ' + formatNumber(perSecond * 5) + ' ед. урона от кислородного голодания в секунду', | |||
'Дополнительно наносит ' + formatNumber(perSecond * 5) + ' ед. тупого и ' + formatNumber(perSecond * 2) + ' ед. токсического урона в секунду'); | |||
return result; | |||
} | |||
if (type === 'Carcinogenic') { | |||
result.push(doseDescription('normal', 'Наносит ' + formatNumber(perSecond * 0.5) + ' ед. клеточного урона в секунду')); | |||
addDoseEffects(result, reagent, | |||
'Наносит ' + formatNumber(perSecond * 2) + ' ед. клеточного урона в секунду', | |||
'Дополнительно наносит ' + formatNumber(perSecond * 2) + ' ед. тупого урона в секунду'); | |||
return result; | |||
} | |||
if (type === 'Oxidizing') { | |||
result.push(doseDescription('normal', 'Наносит ' + formatNumber(perSecond) + ' ед. ожогового урона в секунду; в огненной смеси повышает интенсивность, но уменьшает длительность и радиус')); | |||
addDoseEffects(result, reagent, | |||
'Наносит ' + formatNumber(perSecond * 2) + ' ед. ожогового урона в секунду', | |||
'Дополнительно наносит ' + formatNumber(perSecond * 5) + ' ед. ожогового урона в секунду'); | |||
return result; | |||
} | } | ||
if (type === ' | |||
if (type === 'Fueling') { | |||
result.push(doseDescription('normal', 'Повышает воспламеняемость тела на ' + formatNumber(perSecond) + ' ед. в секунду; в огненной смеси увеличивает длительность и радиус, но снижает интенсивность')); | |||
addDoseEffects(result, reagent, | |||
'Повышает воспламеняемость тела на ' + formatNumber(perSecond * 2) + ' ед. в секунду', | |||
'Поджигает тело с высокой интенсивностью'); | |||
return result; | |||
} | } | ||
if (type === ' | |||
if (type === 'Flowing') { | |||
result.push(doseDescription('normal', 'Делает огненную смесь более текучей: увеличивает радиус, но снижает интенсивность и длительность горения')); | |||
return result; | |||
} | } | ||
if (type === ' | |||
if (type === 'Viscous') { | |||
result.push(doseDescription('normal', 'Замедляет движение на ' + formatNumber(perSecond) + ' сек. за каждый цикл и уменьшает радиус огненной смеси')); | |||
addDoseEffects(result, reagent, | |||
'Сильно замедляет движение на ' + formatNumber(perSecond * 2) + ' сек. за каждый цикл', | |||
'Практически останавливает движение на ' + formatNumber(perSecond * 3) + ' сек. за каждый цикл'); | |||
return result; | |||
} | } | ||
return | return null; | ||
} | } | ||
function | function genericEffectDescription(effect, reagent) { | ||
var type = tagName(effect && effect.yamlTag); | var type = tagName(effect && effect.yamlTag); | ||
var value = effect | var value = effectValue(effect); | ||
var | var probability = value.probability; | ||
var | var tier = effectTier(effect, reagent); | ||
var | var conditions = remainingConditions(effect, reagent); | ||
var | var text = ''; | ||
if (probability === 0) { | |||
return []; | |||
} | |||
var rmc = rmcEffectDescriptions(type, value, reagent); | |||
if (rmc) { | |||
return rmc; | |||
} | |||
if ( | if (type === 'HealthChange' || type === 'EqualHealthChange') { | ||
text = damageChanges(value.damage, type === 'EqualHealthChange').join('; '); | |||
} else if (type === 'AdjustReagent' && value.reagent) { | |||
text = (value.amount >= 0 ? 'Добавляет ' : 'Удаляет ') + formatAmount(Math.abs(value.amount || 0)) + ' реагента «' + capitalizeFirst(reagentName(value.reagent)) + '» за цикл метаболизма'; | |||
} else if (type === 'MovespeedModifier') { | |||
var walk = Math.round((Number(value.walkSpeedModifier || 1) - 1) * 100); | |||
var sprint = Math.round((Number(value.sprintSpeedModifier || 1) - 1) * 100); | |||
text = 'Изменяет скорость ходьбы на ' + (walk >= 0 ? '+' : '') + walk + '% и бега на ' + (sprint >= 0 ? '+' : '') + sprint + '%'; | |||
} else if (type === 'GenericStatusEffect') { | |||
var status = STATUS_LABELS[value.key] || value.key || 'неизвестный статус'; | |||
text = value.type === 'Remove' | |||
? 'Сокращает ' + status + ' на ' + formatNumber(value.time || 2) + ' сек.' | |||
: 'Вызывает ' + status + ' на ' + formatNumber(value.time || 2) + ' сек.'; | |||
} else if (type === 'ModifyStatusEffect') { | |||
var modifiedStatus = STATUS_LABELS[value.effectProto] || value.effectProto || 'неизвестный статус'; | |||
text = value.type === 'Remove' | |||
? 'Сокращает ' + modifiedStatus + ' на ' + formatNumber(value.time || 2) + ' сек.' | |||
: 'Вызывает ' + modifiedStatus + ' на ' + formatNumber(value.time || 2) + ' сек.'; | |||
} else if (type === 'Jitter') { | |||
text = 'Вызывает дрожь на ' + formatNumber(value.time || 2) + ' сек.'; | |||
} else if (type === 'Emote') { | |||
text = 'Вызывает ' + (EMOTE_LABELS[value.emote] || ('эмоцию «' + (value.emote || 'неизвестно') + '»')); | |||
} else if (type === 'ChemVomit') { | |||
text = 'Вызывает рвоту'; | |||
} else if (type === 'Drunk') { | |||
text = 'Добавляет ' + formatNumber(value.boozePower || 3) + ' сек. опьянения за цикл метаболизма'; | |||
} else if (type === 'SatiateHunger') { | |||
text = 'Восстанавливает ' + formatNumber(value.factor !== undefined ? value.factor : 3) + ' ед. насыщения за цикл метаболизма'; | |||
} else if (type === 'SatiateThirst') { | |||
text = 'Восстанавливает ' + formatNumber(value.factor !== undefined ? value.factor : 3) + ' ед. жажды за цикл метаболизма'; | |||
} else if (type === 'ChemHealEyeDamage') { | |||
text = 'Лечит повреждения глаз'; | |||
} else if (type === 'CauseZombieInfection') { | |||
text = 'Заражает зомби-инфекцией'; | |||
} else if (type === 'CureZombieInfection') { | |||
text = value.innoculate ? 'Лечит зомби-инфекцию и создаёт иммунитет' : 'Лечит зомби-инфекцию'; | |||
} else if (type === 'FlammableReaction') { | |||
text = 'Покрывает цель горючим; интенсивность составляет ' + formatNumber(Number(value.multiplier || 1) * 100) + '% от стандартной'; | |||
} else if (type === 'PopupMessage') { | |||
text = value.messages && value.messages.indexOf('rmc-body-stings') !== -1 | |||
? 'Вызывает болезненное жжение' | |||
: 'Вызывает заметное субъективное ощущение действия препарата'; | |||
} else { | |||
text = 'Дополнительный игровой эффект «' + (type || 'неизвестно') + '»'; | |||
} | } | ||
if (conditions.length) { | if (conditions.length) { | ||
text += ' (' + conditions.join(', ') + ')'; | |||
} | } | ||
return [doseDescription(tier, withChance(text, probability))]; | |||
} | |||
function renderEffectText(text) { | |||
var item = element('li', 'scmc-chem__effect'); | |||
item.appendChild(element('span', 'scmc-chem__effect-name', finishSentence(text))); | |||
return item; | return item; | ||
} | |||
function tierTitle(tier, reagent) { | |||
var properties = reagent.properties || {}; | |||
if (tier === 'overdose') { | |||
return 'Передозировка' + (properties.overdose !== undefined ? ' · от ' + formatAmount(properties.overdose) : ''); | |||
} | |||
if (tier === 'critical') { | |||
return 'Критическая передозировка' + (properties.criticalOverdose !== undefined ? ' · от ' + formatAmount(properties.criticalOverdose) : ''); | |||
} | |||
return 'Обычная доза'; | |||
} | |||
function appendEffectTier(group, tier, effects, reagent) { | |||
if (!effects.length) { | |||
return; | |||
} | |||
var tierBlock = element('div', 'scmc-chem__effect-tier scmc-chem__effect-tier--' + tier); | |||
tierBlock.appendChild(element('div', 'scmc-chem__effect-tier-title', tierTitle(tier, reagent))); | |||
var list = element('ul', 'scmc-chem__effect-list'); | |||
effects.forEach(function (description) { | |||
list.appendChild(renderEffectText(description.text)); | |||
}); | |||
tierBlock.appendChild(list); | |||
group.appendChild(tierBlock); | |||
} | } | ||
| Строка 354: | Строка 649: | ||
var block = element('div', 'scmc-chem__card-section'); | var block = element('div', 'scmc-chem__card-section'); | ||
var hasContent = false; | |||
block.appendChild(element('h4', 'scmc-chem__card-subtitle', 'Воздействие')); | block.appendChild(element('h4', 'scmc-chem__card-subtitle', 'Воздействие')); | ||
Object.keys(metabolisms).forEach(function (metabolismId) { | Object.keys(metabolisms).forEach(function (metabolismId) { | ||
var metabolism = metabolisms[metabolismId] || {}; | var metabolism = metabolisms[metabolismId] || {}; | ||
var tiers = { normal: [], overdose: [], critical: [] }; | |||
(metabolism.effects || []).forEach(function (effect) { | |||
genericEffectDescription(effect, reagent).forEach(function (description) { | |||
tiers[description.tier].push(description); | |||
}); | |||
}); | |||
if (!tiers.normal.length && !tiers.overdose.length && !tiers.critical.length) { | |||
return; | |||
} | |||
var group = element('div', 'scmc-chem__metabolism'); | var group = element('div', 'scmc-chem__metabolism'); | ||
var title = METABOLISM_LABELS[metabolismId] || metabolismId; | var title = METABOLISM_LABELS[metabolismId] || metabolismId; | ||
if (metabolism.metabolismRate !== undefined) { | if (metabolism.metabolismRate !== undefined) { | ||
title += ' · ' + formatAmount(metabolism.metabolismRate) + '/сек.'; | title += ' · расход ' + formatAmount(metabolism.metabolismRate) + '/сек.'; | ||
} | } | ||
group.appendChild(element('div', 'scmc-chem__metabolism-title', title)); | group.appendChild(element('div', 'scmc-chem__metabolism-title', title)); | ||
appendEffectTier(group, 'normal', tiers.normal, reagent); | |||
appendEffectTier(group, 'overdose', tiers.overdose, reagent); | |||
appendEffectTier(group, 'critical', tiers.critical, reagent); | |||
block.appendChild(group); | |||
hasContent = true; | |||
}); | |||
return hasContent ? block : null; | |||
} | |||
function plantEffectText(effect) { | |||
var type = tagName(effect && effect.yamlTag); | |||
var value = effectValue(effect); | |||
var probability = value.probability; | |||
var amount = Number(value.amount !== undefined ? value.amount : 1); | |||
var attribute = PLANT_ATTRIBUTE_LABELS[type]; | |||
var text; | |||
if ( | if (probability === 0) { | ||
return ''; | |||
} | |||
if (attribute) { | |||
if (type === 'PlantAdjustHealth') { | |||
text = amount >= 0 | |||
? 'Восстанавливает здоровье растения на ' + formatNumber(amount) | |||
: 'Снижает здоровье растения на ' + formatNumber(Math.abs(amount)); | |||
} else { | |||
text = (amount >= 0 ? 'Повышает ' : 'Снижает ') + attribute + ' на ' + formatNumber(Math.abs(amount)); | |||
} | } | ||
} else if (type === 'PlantCryoxadone') { | |||
text = 'Омолаживает растение с учётом его возраста и времени роста'; | |||
} else if (type === 'PlantPhalanximine') { | |||
text = 'Возвращает жизнеспособность растению, погибшему из-за мутации'; | |||
} else if (type === 'PlantDiethylamine') { | |||
text = 'Повышает продолжительность жизни или базовое здоровье растения; шанс 10% на единицу реагента'; | |||
} else if (type === 'PlantRestoreSeeds') { | |||
text = 'Восстанавливает семена растения'; | |||
} else if (type === 'PlantDestroySeeds') { | |||
text = 'Уничтожает семена растения'; | |||
} else { | |||
text = 'Дополнительный растительный эффект «' + (type || 'неизвестно') + '»'; | |||
} | |||
return withChance(text, probability); | |||
} | |||
function renderPlantMetabolism(reagent) { | |||
var effects = reagent.properties && reagent.properties.plantMetabolism; | |||
block.appendChild(group); | if (!Array.isArray(effects) || !effects.length) { | ||
return null; | |||
} | |||
var descriptions = effects.map(plantEffectText).filter(Boolean); | |||
if (!descriptions.length) { | |||
return null; | |||
} | |||
var block = element('div', 'scmc-chem__card-section'); | |||
block.appendChild(element('h4', 'scmc-chem__card-subtitle', 'Метаболизм растений')); | |||
var group = element('div', 'scmc-chem__metabolism'); | |||
group.appendChild(element('div', 'scmc-chem__metabolism-title', '1 ед. реагента каждые 3 секунды (базово)')); | |||
var list = element('ul', 'scmc-chem__effect-list'); | |||
descriptions.forEach(function (description) { | |||
list.appendChild(renderEffectText(description)); | |||
}); | }); | ||
group.appendChild(list); | |||
block.appendChild(group); | |||
return block; | return block; | ||
} | } | ||
| Строка 393: | Строка 758: | ||
row, | row, | ||
dot, | dot, | ||
element('span', 'scmc-chem__mixture-name', item.name || reagentName(item.id)), | element('span', 'scmc-chem__mixture-name', capitalizeFirst(item.name || reagentName(item.id))), | ||
element('span', 'scmc-chem__mixture-amount', formatAmount(item.amount)) | element('span', 'scmc-chem__mixture-amount', formatAmount(item.amount)) | ||
); | ); | ||
| Строка 493: | Строка 858: | ||
append( | append( | ||
heading, | heading, | ||
element('span', 'scmc-chem__card-name', entry.name || (reagent && reagent.name) || entry.id), | element('span', 'scmc-chem__card-name', capitalizeFirst(entry.name || (reagent && reagent.name) || entry.id)), | ||
element('code', 'scmc-chem__card-id', entry.id) | element('code', 'scmc-chem__card-id', entry.id) | ||
); | ); | ||
| Строка 514: | Строка 879: | ||
if (reagent.description) { | if (reagent.description) { | ||
body.appendChild(element('p', 'scmc-chem__description', reagent.description)); | body.appendChild(element('p', 'scmc-chem__description', capitalizeFirst(reagent.description))); | ||
} | } | ||
append(body, renderDoseBadges(reagent), renderRecipes(entry.id), renderMetabolisms(reagent)); | append(body, renderDoseBadges(reagent), renderRecipes(entry.id), renderMetabolisms(reagent), renderPlantMetabolism(reagent)); | ||
if (!body.childNodes.length) { | if (!body.childNodes.length) { | ||
| Строка 551: | Строка 916: | ||
function renderSection(group) { | function renderSection(group) { | ||
var section = element('section', 'scmc-chem__section'); | var section = element('section', 'scmc-chem__section'); | ||
var title = group.path[group.path.length - 1] || 'Без раздела'; | var title = capitalizeFirst(group.path[group.path.length - 1] || 'Без раздела'); | ||
var heading = element('div', 'scmc-chem__section-heading'); | var heading = element('div', 'scmc-chem__section-heading'); | ||
| Строка 557: | Строка 922: | ||
if (group.path.length > 1) { | if (group.path.length > 1) { | ||
heading.appendChild(element('div', 'scmc-chem__breadcrumbs', group.path.slice(0, -1).join(' › '))); | heading.appendChild(element('div', 'scmc-chem__breadcrumbs', group.path.slice(0, -1).map(capitalizeFirst).join(' › '))); | ||
} | } | ||