Compare commits

...

9 Commits
2.3.5 ... 2.3.6

Author SHA1 Message Date
Cmdr McDonald
318e8077d0 Merge branch 'release/2.3.6' 2017-06-24 09:34:37 +01:00
Cmdr McDonald
c8355a532d Bump version 2017-06-24 09:33:21 +01:00
Cmdr McDonald
3686ccd4ed Update Russian translation 2017-06-24 09:24:38 +01:00
Cmdr McDonald
f02db0120a Fix for Spanish translation of Chaff Launcher 2017-06-24 09:18:27 +01:00
Cmdr McDonald
d9ad93d3cd Fix typo causing long range blueprint to not modify shot speed in some circumstances 2017-06-06 11:45:59 +01:00
Cmdr McDonald
77018cc1ad Fix issue where torpedo special effects were not showing 2017-05-30 19:44:35 +01:00
Cmdr McDonald
30a8a29ce3 Update miner role with better defaults 2017-05-30 19:44:11 +01:00
Cmdr McDonald
7b1aa646ac Fix 2017-05-17 20:56:13 +01:00
Cmdr McDonald
49e4409862 Merge branch 'release/2.3.5' into develop 2017-05-17 07:49:06 +01:00
11 changed files with 440 additions and 82 deletions

View File

@@ -1,3 +1,12 @@
#2.3.6
* Update miner role to provide better defaults
* Fix issue where torpedo special effects were not showing
* Fix typo causing long range blueprint to not modify shot speed in some circumstances
* Fix for Spanish translation of Chaff Launcher (thanks to DamonFstr)
* Update for Russian translation (thanks to LeeNTien)
* Use coriolis-data 2.3.6:
* Add shotspeed modifier to cannon/multi-cannon/fragment cannon
#2.3.5
* Ensure that hidden blueprint effects are applied when a blueprint is selected
* Handle display when summary values show thrusters disabled but current mass keeps them enabled

View File

@@ -1,6 +1,6 @@
{
"name": "coriolis_shipyard",
"version": "2.3.5",
"version": "2.3.6",
"repository": {
"type": "git",
"url": "https://github.com/EDCD/coriolis"

View File

@@ -88,7 +88,7 @@ export default class ModificationsMenu extends TranslatedComponent {
const translate = language.translate;
const specials = [];
const specialsId = m.missile ? 'specials_' + m.missile : 'specials';
const specialsId = m.missile && Modifications.modules[m.grp]['specials_' + m.missile] ? 'specials_' + m.missile : 'specials';
if (Modifications.modules[m.grp][specialsId] && Modifications.modules[m.grp][specialsId].length > 0) {
const close = this._specialSelected.bind(this, null);
specials.push(<div style={{ cursor: 'pointer' }} key={ 'none' } onClick={ close }>{translate('PHRASE_NO_SPECIAL')}</div>);

View File

@@ -15,6 +15,8 @@ export default class SlotSection extends TranslatedComponent {
static propTypes = {
ship: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired,
onCargoChange: PropTypes.func.isRequired,
onFuelChange: PropTypes.func.isRequired,
code: PropTypes.string.isRequired,
togglePwr: PropTypes.func
};
@@ -129,44 +131,46 @@ export default class SlotSection extends TranslatedComponent {
let { originSlot, targetSlot, copy } = this.state;
let m = originSlot.m;
if (copy) {
// We want to copy the module in to the target slot
if (targetSlot && canMount(this.props.ship, targetSlot, m.grp, m.class)) {
const mCopy = m.clone();
this.props.ship.use(targetSlot, mCopy, false);
// Copy power info
targetSlot.enabled = originSlot.enabled;
targetSlot.priority = originSlot.priority;
this.props.onChange();
}
} else {
// Store power info
const originEnabled = targetSlot.enabled;
const originPriority = targetSlot.priority;
const targetEnabled = originSlot.enabled;
const targetPriority = originSlot.priority;
// We want to move the module in to the target slot, and swap back any module that was originally in the target slot
if (targetSlot && m && canMount(this.props.ship, targetSlot, m.grp, m.class)) {
// Swap modules if possible
if (targetSlot.m && canMount(this.props.ship, originSlot, targetSlot.m.grp, targetSlot.m.class)) {
this.props.ship.use(originSlot, targetSlot.m, true);
this.props.ship.use(targetSlot, m);
// Swap power
originSlot.enabled = originEnabled;
originSlot.priority = originPriority;
targetSlot.enabled = targetEnabled;
targetSlot.priority = targetPriority;
} else { // Otherwise empty the origin slot
// Store power
const targetEnabled = originSlot.enabled;
this.props.ship.use(originSlot, null, true); // Empty but prevent summary update
this.props.ship.use(targetSlot, m);
originSlot.enabled = 0;
originSlot.priority = 0;
targetSlot.enabled = targetEnabled;
targetSlot.priority = targetPriority;
if (targetSlot && originSlot != targetSlot) {
if (copy) {
// We want to copy the module in to the target slot
if (targetSlot && canMount(this.props.ship, targetSlot, m.grp, m.class)) {
const mCopy = m.clone();
this.props.ship.use(targetSlot, mCopy, false);
// Copy power info
targetSlot.enabled = originSlot.enabled;
targetSlot.priority = originSlot.priority;
this.props.onChange();
}
} else {
// Store power info
const originEnabled = targetSlot.enabled;
const originPriority = targetSlot.priority;
const targetEnabled = originSlot.enabled;
const targetPriority = originSlot.priority;
// We want to move the module in to the target slot, and swap back any module that was originally in the target slot
if (targetSlot && m && canMount(this.props.ship, targetSlot, m.grp, m.class)) {
// Swap modules if possible
if (targetSlot.m && canMount(this.props.ship, originSlot, targetSlot.m.grp, targetSlot.m.class)) {
this.props.ship.use(originSlot, targetSlot.m, true);
this.props.ship.use(targetSlot, m);
// Swap power
originSlot.enabled = originEnabled;
originSlot.priority = originPriority;
targetSlot.enabled = targetEnabled;
targetSlot.priority = targetPriority;
} else { // Otherwise empty the origin slot
// Store power
const targetEnabled = originSlot.enabled;
this.props.ship.use(originSlot, null, true); // Empty but prevent summary update
this.props.ship.use(targetSlot, m);
originSlot.enabled = 0;
originSlot.priority = 0;
targetSlot.enabled = targetEnabled;
targetSlot.priority = targetPriority;
}
this.props.onChange();
}
this.props.onChange();
}
}
this.setState({ originSlot: null, targetSlot: null, copy: null });

View File

@@ -28,6 +28,8 @@ export default class StandardSlotSection extends SlotSection {
_optimizeStandard() {
this.props.ship.useLightestStandard();
this.props.onChange();
this.props.onCargoChange(this.props.ship.cargoCapacity);
this.props.onFuelChange(this.props.ship.fuelCapacity);
this._close();
}
@@ -39,6 +41,8 @@ export default class StandardSlotSection extends SlotSection {
_multiPurpose(shielded, bulkheadIndex) {
ShipRoles.multiPurpose(this.props.ship, shielded, bulkheadIndex);
this.props.onChange();
this.props.onCargoChange(this.props.ship.cargoCapacity);
this.props.onFuelChange(this.props.ship.fuelCapacity);
this._close();
}
@@ -49,6 +53,8 @@ export default class StandardSlotSection extends SlotSection {
_optimizeCargo(shielded) {
ShipRoles.trader(this.props.ship, shielded);
this.props.onChange();
this.props.onCargoChange(this.props.ship.cargoCapacity);
this.props.onFuelChange(this.props.ship.fuelCapacity);
this._close();
}
@@ -59,6 +65,8 @@ export default class StandardSlotSection extends SlotSection {
_optimizeMiner(shielded) {
ShipRoles.miner(this.props.ship, shielded);
this.props.onChange();
this.props.onCargoChange(this.props.ship.cargoCapacity);
this.props.onFuelChange(this.props.ship.fuelCapacity);
this._close();
}
@@ -69,6 +77,8 @@ export default class StandardSlotSection extends SlotSection {
_optimizeExplorer(planetary) {
ShipRoles.explorer(this.props.ship, planetary);
this.props.onChange();
this.props.onCargoChange(this.props.ship.cargoCapacity);
this.props.onFuelChange(this.props.ship.fuelCapacity);
this._close();
}
@@ -78,6 +88,8 @@ export default class StandardSlotSection extends SlotSection {
_optimizeRacer() {
ShipRoles.racer(this.props.ship);
this.props.onChange();
this.props.onCargoChange(this.props.ship.cargoCapacity);
this.props.onFuelChange(this.props.ship.fuelCapacity);
this._close();
}

View File

@@ -46,7 +46,7 @@ export const terms = {
'cr': 'Compartimento de carga',
'cs': 'Esc\u00e1ner de carga',
'cells': 'celdas',
'Chaff Launcher': 'Lanzador de birutas',
'Chaff Launcher': 'Lanzador de virutas',
'close': 'Cerrar',
'cc': 'Controlador de Drones de Recogida',
'compare': 'Comparar',

View File

@@ -14,20 +14,315 @@ export const formats = {
};
export const terms = {
// Phrases
PHRASE_BACKUP_DESC: 'Сохраните все данные перед переносом в другой браузер или устройство', // Backup of all Coriolis data to save or transfer to another browser/device
PHRASE_CONFIRMATION: 'Вы уверены?', // Are You Sure?
PHRASE_EXPORT_DESC: 'Детальный JSON-экспорт вашей сборки для использования в других местах и инструментах', // A detailed JSON export of your build for use in other sites and tools
PHRASE_FASTEST_RANGE: 'Последовательные прыжки максимальной дальности', // Consecutive max range jumps
PHRASE_IMPORT: 'Для импорта вставьте код в эту форму', // Paste JSON or import here
PHRASE_LADEN: 'Масса корабля с учётом топлива и грузов', // Ship Mass + Fuel + Cargo
PHRASE_NO_BUILDS: 'Нечего сравнивать', // No builds added to comparison!
PHRASE_NO_RETROCH: 'нет ранних версий сборки\\конфигурации', // No Retrofitting changes
PHRASE_SELECT_BUILDS: 'Выберите конфигурацию для сравнения', // Select Builds to Compare
PHRASE_SG_RECHARGE: 'восстановление с 60% до 100% объема щита', // Time from 50% to 100% Charge
PHRASE_SG_RECOVER: 'восстановление [до 60%] после снятия щита', // Recovery (to 50%) after collapse
PHRASE_UNLADEN: 'Масса корабля без учета топлива и грузов', // Ship Mass excluding Fuel and Cargo
PHRASE_UPDATE_RDY: 'Доступно обновление. Нажмите для обновления.', // Update Available! Click to Refresh
PHRASE_ALT_ALL: 'Alt + Нажатие для заполнения всех слотов',
PHRASE_BACKUP_DESC: 'Сохраните все данные перед переносом в другой браузер или устройство',
PHRASE_CONFIRMATION: 'Вы уверены?',
PHRASE_EXPORT_DESC: 'Детальный JSON-экспорт вашей сборки для использования в других местах и инструментах',
PHRASE_FASTEST_RANGE: 'Последовательные прыжки максимальной дальности',
PHRASE_IMPORT: 'Для импорта вставьте код в эту форму',
PHRASE_LADEN: 'Масса корабля с учётом топлива и грузов',
PHRASE_NO_BUILDS: 'Нечего сравнивать',
PHRASE_NO_RETROCH: 'Нет ранних версий сборки',
PHRASE_SELECT_BUILDS: 'Выберите конфигурацию для сравнения',
PHRASE_SG_RECHARGE: 'Восстановление с 50% до 100% объема щита, учитывая полный аккумулятор СИС в начале',
PHRASE_SG_RECOVER: 'Восстановление с 0% до 50% объема щита, учитывая полный аккумулятор СИС в начале',
PHRASE_UNLADEN: 'Масса корабля без учета топлива и грузов',
PHRASE_UPDATE_RDY: 'Доступна новая версия. Нажмите для обновления.',
PHRASE_ENGAGEMENT_RANGE: 'Дистанция между кораблём и целью',
PHRASE_SELECT_BLUEPRINT: 'Нажмите чтобы выбрать чертёж',
PHRASE_BLUEPRINT_WORST: 'Худшие основные значения для чертежа',
PHRASE_BLUEPRINT_RANDOM: 'Случайный выбор между худшими и лучшими значениями для этого чертежа',
PHRASE_BLUEPRINT_BEST: 'Лучшие основные значения для чертежа',
PHRASE_BLUEPRINT_EXTREME: 'Лучшие положительные и худшие отрицательные основные значения для чертежа',
PHRASE_BLUEPRINT_RESET: 'Убрать все изменения и чертёж',
PHRASE_SELECT_SPECIAL: 'Нажмите чтобы выбрать экспериментальный эффект',
PHRASE_NO_SPECIAL: 'Без экспериментального эффекта',
PHRASE_SHOPPING_LIST: 'Станции что продают эту сборку',
PHRASE_REFIT_SHOPPING_LIST: 'Станции что продают необходимые модули',
PHRASE_TOTAL_EFFECTIVE_SHIELD: 'Общий урон что может быть нанесён в каждым типе, если используются все щитонакопители',
PHRASE_TIME_TO_LOSE_SHIELDS: 'Щиты продержатся',
PHRASE_TIME_TO_RECOVER_SHIELDS: 'Щиты восстановятся за',
PHRASE_TIME_TO_RECHARGE_SHIELDS: 'Щиты будут заряжены за',
PHRASE_SHIELD_SOURCES: 'Подробности энергии щита',
PHRASE_EFFECTIVE_SHIELD: 'Эффективная сила щита против разных типов урона',
PHRASE_ARMOUR_SOURCES: 'Подробности состава брони',
PHRASE_EFFECTIVE_ARMOUR: 'Эффективная сила брони против разных типов урона',
PHRASE_DAMAGE_TAKEN: '% общих повреждений полученных в разных типах урона',
PHRASE_TIME_TO_LOSE_ARMOUR: 'Броня продержится',
PHRASE_MODULE_PROTECTION_EXTERNAL: 'Защита гнёзд',
PHRASE_MODULE_PROTECTION_INTERNAL: 'Защита всех остальных модулей',
PHRASE_SHIELD_DAMAGE: 'Подробности источников поддерживаемого ДПС против щитов',
PHRASE_ARMOUR_DAMAGE: 'Подробности источников поддерживаемого ДПС против брони',
PHRASE_TIME_TO_REMOVE_SHIELDS: 'Снимет щиты за',
TT_TIME_TO_REMOVE_SHIELDS: 'Непрерывным огнём из всех орудий',
PHRASE_TIME_TO_REMOVE_ARMOUR: 'Снимет броню за',
TT_TIME_TO_REMOVE_ARMOUR: 'Непрерывным огнём из всех орудий',
PHRASE_TIME_TO_DRAIN_WEP: 'Опустошит ОРУЖ за',
TT_TIME_TO_DRAIN_WEP: 'Время за которое опустошится аккумулятор ОРУЖ при стрельбе из всех орудий',
TT_TIME_TO_LOSE_SHIELDS: 'Против поддерживаемой стрельбы из всех орудий противника',
TT_TIME_TO_LOSE_ARMOUR: 'Против поддерживаемой стрельбы из всех орудий противника',
TT_MODULE_ARMOUR: 'Броня защищаюшае модули от урона',
TT_MODULE_PROTECTION_EXTERNAL: 'Процент урона перенаправленного от гнёзд на наборы для усиления модулей',
TT_MODULE_PROTECTION_INTERNAL: 'Процент урона перенаправленного от модулей вне гнёзд на наборы для усиления модулей',
TT_EFFECTIVE_SDPS_SHIELDS: 'Реальный поддерживаемый ДПС пока аккумулятор ОРУЖ не пуст',
TT_EFFECTIVENESS_SHIELDS: 'Эффективность в сравнении с попаданием по цели с 0-сопротивляемостью без пунктов в СИС на 0 метрах',
TT_EFFECTIVE_SDPS_ARMOUR: 'Реальный поддерживаемый ДПС пока аккумулятор ОРУЖ не пуст',
TT_EFFECTIVENESS_ARMOUR: 'Эффективность в сравнении с попаданием по цели с 0-сопротивляемостью на 0 метрах',
PHRASE_EFFECTIVE_SDPS_SHIELDS: 'ПДПС против щитов',
PHRASE_EFFECTIVE_SDPS_ARMOUR: 'ПДПС против брони',
TT_SUMMARY_SPEED: 'С полным топливным баком и 4 пунктами в ДВИ',
TT_SUMMARY_SPEED_NONFUNCTIONAL: 'маневровые двигатели выключены или превышена максимальная масса с топливом и грузом',
TT_SUMMARY_BOOST: 'С полным топливным баком и 4 пунктами в ДВИ',
TT_SUMMARY_BOOST_NONFUNCTIONAL: 'Распределитель питания не может обеспечить достаточно энергии для форсажа',
TT_SUMMARY_SHIELDS: 'Чистая сила щита, включая усилители',
TT_SUMMARY_SHIELDS_NONFUNCTIONAL: 'Шитогенератор отсутствует или выключен',
TT_SUMMARY_INTEGRITY: 'Целостность корабля, включая переборки и наборы для усиления корпуса',
TT_SUMMARY_HULL_MASS: 'Масса корпуса без каких-либо модулей',
TT_SUMMARY_UNLADEN_MASS: 'Масса корпуса и модулей без топлива и груза',
TT_SUMMARY_LADEN_MASS: 'Масса корпуса и модулей с топливом и грузом',
TT_SUMMARY_DPS: 'Урон в секунду при стрельбе из всех орудий',
TT_SUMMARY_EPS: 'Расход аккумулятора ОРУЖ в секунду при стрельбе из всех орудий',
TT_SUMMARY_TTD: 'Время расхода аккумулятора ОРУЖ при стрельбе из всех орудий и с 4 пунктами в ОРУЖ',
TT_SUMMARY_MAX_SINGLE_JUMP: 'Самый дальний возможный прыжок без груза и с топливом достаточным только на сам прыжок',
TT_SUMMARY_UNLADEN_SINGLE_JUMP: 'Самый дальний возможный прыжок без груза и с полным топливным баком',
TT_SUMMARY_LADEN_SINGLE_JUMP: 'Самый дальний возможный прыжок с полным грузовым отсеком и с полным топливным баком',
TT_SUMMARY_UNLADEN_TOTAL_JUMP: 'Самая дальняя общая дистанция без груза, с полным топливным баком и при прыжках на максимальное расстояние',
TT_SUMMARY_LADEN_TOTAL_JUMP: 'Самая дальняя общая дистанция с полным грузовым отсеком, с полным топливным баком и при прыжках на максимальное расстояние',
HELP_MODIFICATIONS_MENU: 'Ткните на номер чтобы ввести новое значение, или потяните вдоль полосы для малых изменений',
// Other languages fallback to these values
// Only Translate to other languages if the name is different in-game
am: 'Блок Автом. Полевого Ремонта',
bh: 'Переборки',
bl: 'Пучковый Лазер',
bsg: 'Двухпоточный Щитогенератор',
c: 'Орудие',
cc: 'Контроллер магнитного снаряда для сбора',
ch: 'Разбрасыватель дипольных отражателей',
cr: 'Грузовой стеллаж',
cs: 'Сканер содержимого',
dc: 'Стыковочный компьютер',
ec: 'Электр. противодействие',
fc: 'Залповое орудие',
fh: 'Ангар для истребителя',
fi: 'FSD-перехватчик',
fs: 'Топливозаборник',
fsd: 'Рамочно Сместительный двигатель',
ft: 'Топливный бак',
fx: 'Контроллер магнитного снаряда для топлива',
hb: 'Контроллер магнитного снаряда для взлома трюма',
hr: 'Набор для усиления корпуса',
hs: 'Теплоотводная катапульта',
kw: 'Сканер преступников',
ls: 'Система жизнеобеспечения',
mc: 'Многоствольное орудие',
ml: 'Проходочный лазер',
mr: 'Ракетный лоток',
mrp: 'Набор для усиления модуля',
nl: 'Мины',
pa: 'Ускоритель плазмы',
pas: 'Комплект для сближения с планетой',
pc: 'Контроллер магнитного снаряда для геологоразведки',
pce: 'Каюта пассажира эконом-класса',
pci: 'Каюта пассажира бизнес-класса',
pcm: 'Каюта пассажира первого класса',
pcq: 'Каюта пассажира класса люкс',
pd: 'Распределитель питания',
pl: 'Ипмульсный лазер',
po: 'Точечная оборона',
pp: 'Силовая установка',
psg: 'Призматический щитогенератор',
pv: 'Гараж для планетарного транспорта',
rf: 'Устройство переработки',
rg: 'Электромагнитная пушка',
s: 'Сенсоры',
sb: 'Усилитель щита',
sc: 'Сканер обнаружения',
scb: 'Щитонакопитель',
sg: 'Щитогенератор',
ss: 'Сканер Поверхностей',
t: 'Маневровые двигатели',
tp: 'Торпедная стойка',
ul: 'Пульсирующие лазеры',
ws: 'Сканер следа FSD',
// Items on the outfitting page
// Notification of restricted slot
emptyrestricted: 'пусто (ограниченно)',
'damage dealt to': 'Урон нанесён',
'damage received from': 'Урон получен от',
'against shields': 'Против шитов',
'against hull': 'Против корпуса',
'total effective shield': 'Общие эффективные щиты',
// 'ammo' was overloaded for outfitting page and modul info, so changed to ammunition for outfitting page
ammunition: 'Припасы',
// Unit for seconds
secs: 'с',
rebuildsperbay: 'Построек за полосу',
// Blueprint rolls
worst: 'Худшее',
average: 'Среднее',
random: 'Случайное',
best: 'Лучшее',
extreme: 'Экстремальное',
reset: 'Обнулить',
// Weapon, offence, defence and movement
dpe: 'Урон на МДж энергии',
dps: 'Урон в Секунду',
sdps: 'Поддерживаемый урон в секунду',
dpssdps: 'Урон в секунду (поддерживаемый урон в секунду)',
eps: 'Энергия в секунду',
epsseps: 'Энергия в секунду (поддерживаемая энергия в секунду)',
hps: 'Нагрев в секунду',
hpsshps: 'Heat per second (sustained heat per second)',
'damage by': 'Урон',
'damage from': 'Урон от',
'shield cells': 'Щитонакопители',
'recovery': 'Восстановление',
'recharge': 'Перезарядка',
'engine pips': 'Пункты в двигателе',
'4b': '4 пункта и Форсаж',
'speed': 'Скорость',
'pitch': 'Тангаж',
'roll': 'Крен',
'yaw': 'Рыскание',
'internal protection': 'Внутренняя защита',
'external protection': 'Внешняя защита',
'engagement range': 'Боевое расстояние',
'total': 'Общее',
// Modifications
ammo: 'Макс. боекомплект',
boot: 'Время загрузки',
brokenregen: 'Скорость восстановления при пробое',
burst: 'Длина очереди',
burstrof: 'Скорострельность очереди',
clip: 'Боекомплект',
damage: 'Урон',
distdraw: 'Тяга распределителя',
duration: 'Продолжительность',
eff: 'Эффективность',
engcap: 'Ресурс двигателей',
engrate: 'Перезарядка двигателей',
explres: 'Сопротивление взрывам',
facinglimit: 'Ограничение по направлению',
hullboost: 'Увеличение корпуса',
hullreinforcement: 'Укрепление корпуса',
integrity: 'Целостность',
jitter: 'Дрожание',
kinres: 'Сопротивление китетическому урону',
maxfuel: 'Макс. топлива на прыжок',
mass: 'Масса',
optmass: 'Оптимизированная масса',
optmul: 'Оптимальный усилитель',
pgen: 'Мощность',
piercing: 'Бронебойность',
power: 'Энергопотребление',
protection: 'Защита от повреждений',
range: 'Дальность',
ranget: 'Дальность', // Range in time (for FSD interdictor)
regen: 'Скорость восстановления',
reload: 'Время перезарядки',
rof: 'Скорострельность',
angle: 'Угол сканера',
scanrate: 'Скорость сканера',
scantime: 'Время сканирования',
shield: 'Щит',
shieldboost: 'Усиление щитов',
shieldreinforcement: 'Усилитель щита',
shotspeed: 'Скорость выстрела',
spinup: 'Время раскрутки',
syscap: 'Ресурс систем',
sysrate: 'Перезарядка систем',
thermload: 'Тепловая нагрузка',
thermres: 'Сопротивление термическому урону',
wepcap: 'Орудийный ресурс',
weprate: 'Перезарядка оружия',
// Shield generators use a different terminology
minmass_sg: 'Мин. масса корпуса',
optmass_sg: 'Опт. масса корпуса',
maxmass_sg: 'Макс. масса корпуса',
minmul_sg: 'Минимальная прочность',
optmul_sg: 'Оптимальная прочность',
maxmul_sg: 'Максимальная прочность',
minmass_psg: 'Мин. масса корпуса',
optmass_psg: 'Опт. масса корпуса',
maxmass_psg: 'Макс. масса корпуса',
minmul_psg: 'Минимальная прочность',
optmul_psg: 'Оптимальная прочность',
maxmul_psg: 'Максимальная прочность',
minmass_bsg: 'Мин. масса корпуса',
optmass_bsg: 'Опт. масса корпуса',
maxmass_bsg: 'Макс. масса корпуса',
minmul_bsg: 'Минимальная прочность',
optmul_bsg: 'Оптимальная прочность',
maxmul_bsg: 'Максимальная прочность',
range_s: 'Типовой диапозон выброса',
// Damage types
absolute: 'Общий',
explosive: 'Взрывч.',
kinetic: 'Механич.',
thermal: 'Тепл.',
// Shield sources
generator: 'Генератор',
boosters: 'Усилители',
cells: 'Накопители',
// Armour sources
bulkheads: 'Переборки',
reinforcement: 'Усилители',
// Panel headings and subheadings
'power and costs': 'Энергия и стоимость',
'costs': 'Цены',
'retrofit costs': 'Стоимость модификации',
'reload costs': 'Стоимость перезарядки',
'profiles': 'Графики',
'engine profile': 'Двигатели',
'fsd profile': 'FSD',
'movement profile': 'Движение',
'damage to opponent\'s shields': 'Урон щиту противника',
'damage to opponent\'s hull': 'Урон корпусу противника',
'offence': 'Нападение',
'defence': 'Оборона',
'shield metrics': 'Данные щита',
'raw shield strength': 'Чистая мощность щита',
'shield sources': 'Ресурсы щита',
'damage taken': 'Полученный урон',
'effective shield': 'Эффективный щит',
'armour metrics': 'Данные брони',
'raw armour strength': 'Чистая мощность брони',
'armour sources': 'Ресурсы брони',
'raw module armour': 'Чистая броня модулей',
'effective armour': 'Эффективная броня',
'offence metrics': 'Данные нападения',
'defence metrics': 'Данные обороны',
// Misc items
'fuel carried': 'Топливо на борту',
'cargo carried': 'Груз на борту',
'ship control': 'Управление кораблём',
'opponent': 'Противник',
'opponent\'s shields': 'Щит противника',
'opponent\'s armour': 'Броня противника',
'shield damage sources': 'источники урона по щиту',
'armour damage sources': 'источники урона по броне',
'never': 'Никогда',
'stock': 'базовый',
'boost': 'Форсаж',
// Units / Metrics
'/s': '/с', // Per second
@@ -105,7 +400,7 @@ export const terms = {
DPS: 'УВС', // Damage per second abbreviation
efficiency: 'Эффективность', // Power Plant efficiency
empty: 'пусто',
ENG: 'ДВГ', // Abbreviation - Engine recharge rate for power distributor
ENG: 'ДВИ', // Abbreviation - Engine recharge rate for power distributor
export: 'Экспорт',
forum: 'Форум',
fuel: 'Топливо',
@@ -153,12 +448,12 @@ export const terms = {
speed: 'скорость',
standard: 'Стандартный', // Standard / Common modules (FSD, power plant, life support, etc)
Stock: 'Стандартная комплектация', // Thermal-load abbreviation
SYS: 'СИСТЕМЫ', // Abbreviation - System recharge rate for power distributor
SYS: 'СИС', // Abbreviation - System recharge rate for power distributor
time: 'Время', // time it takes to complete something
total: 'Всего',
type: 'Тип',
unladen: 'Пустой', // No cargo or fuel
URL: 'Ссылка', // Link, Uniform Resource Locator
WEP: 'ОРУДИЯ', // Abbreviation - Weapon recharge rate for power distributor
WEP: 'ОРУЖ', // Abbreviation - Weapon recharge rate for power distributor
yes: 'Да'
};

View File

@@ -446,7 +446,10 @@ export default class OutfittingPage extends Page {
fuel = ship.fuelCapacity;
}
const code = this._fullCode(ship, fuel, cargo);
this.setState({ code, cargo, fuel }, () => this._updateRoute(shipId, buildName, code));
// Only update the state if this really has been updated
if (this.state.code != code || this.state.cargo != cargo || this.state.fuel != fuel) {
this.setState({ code, cargo, fuel }, () => this._updateRoute(shipId, buildName, code));
}
}
/**
@@ -551,7 +554,7 @@ export default class OutfittingPage extends Page {
const internalSlotMarker = `${ship.name}${_iStr}${_pStr}${_mStr}`;
const hardpointsSlotMarker = `${ship.name}${_hStr}${_pStr}${_mStr}`;
const boostMarker = `${ship.canBoost(cargo, fuel)}`;
const shipSummaryMarker = `${ship.name}${_sStr}${_iStr}${_hStr}${_pStr}${_mStr}${ship.ladenMass}${ship.cargo}${ship.fuel}`;
const shipSummaryMarker = `${ship.name}${_sStr}${_iStr}${_hStr}${_pStr}${_mStr}${ship.ladenMass}${cargo}${fuel}`;
return (
<div id='outfit' className={'page'} style={{ fontSize: (sizeRatio * 0.9) + 'em' }}>
@@ -588,10 +591,10 @@ export default class OutfittingPage extends Page {
{/* Main tables */}
<ShipSummaryTable ship={ship} fuel={fuel} cargo={cargo} marker={shipSummaryMarker} />
<StandardSlotSection ship={ship} fuel={fuel} cargo={cargo} code={standardSlotMarker} onChange={shipUpdated} currentMenu={menu} />
<InternalSlotSection ship={ship} code={internalSlotMarker} onChange={shipUpdated} currentMenu={menu} />
<HardpointSlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} currentMenu={menu} />
<UtilitySlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} currentMenu={menu} />
<StandardSlotSection ship={ship} fuel={fuel} cargo={cargo} code={standardSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} />
<InternalSlotSection ship={ship} code={internalSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} />
<HardpointSlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} />
<UtilitySlotSection ship={ship} code={hardpointsSlotMarker} onChange={shipUpdated} onCargoChange={this._cargoUpdated} onFuelChange={this._fuelUpdated} currentMenu={menu} />
{/* Control of ship and opponent */}
<div className='group quarter'>

View File

@@ -693,7 +693,7 @@ export default class Module {
* @return {string} the shot speed for this module
*/
getShotSpeed() {
if (this.blueprint && (this.blueprint.name === 'Focused' || this.blueprintname === 'Long Range')) {
if (this.blueprint && (this.blueprint.name === 'Focused' || this.blueprint.name === 'Long range')) {
// If the modification is focused or long range then the shot speed
// uses the range modifier
const rangemod = this.getModValue('range') / 10000;

View File

@@ -132,6 +132,20 @@ export default class ModuleSet {
return new Module({ template: pd });
};
/** Find the power distributor that matches the requirements
* @param {Object} requirements The requirements to be met (currently only support 'weprate')
* @return {Object} Power distributor
*/
matchingPowerDist(requirements) {
let pd = this.standard[4][0];
for (let p of this.standard[4]) {
if (p.weprate >= requirements.weprate || p.weprate >= pd.weprate) {
pd = p;
}
}
return new Module({ template: pd });
}
/**
* Finds the lightest Thruster that can handle the specified tonnage
* @param {number} ladenMass Ship laden mass (mass + cargo + fuel)

View File

@@ -252,24 +252,6 @@ export function miner(ship, shielded) {
}
}
// Collector limpet controller if there are enough internals left
let collectorLimpetsRequired = Math.max(ship.internal.filter(a => (!a.eligible) || a.eligible.cr).length - 6, 0);
if (collectorLimpetsRequired > 0) {
const collectorOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const collectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.cc)
.sort((a,b) => collectorOrder.indexOf(a.maxClass) - collectorOrder.indexOf(b.maxClass));
for (let i = 0; i < collectorInternals.length && collectorLimpetsRequired > 0; i++) {
if (canMount(ship, collectorInternals[i], 'cc')) {
// Collector only has odd classes
const collectorClass = collectorInternals[i].maxClass % 2 === 0 ? collectorInternals[i].maxClass - 1 : collectorInternals[i].maxClass;
ship.use(collectorInternals[i], ModuleUtils.findInternal('cc', collectorClass, 'A'));
usedSlots.push(collectorInternals[i]);
collectorLimpetsRequired -= collectorInternals[i].m.maximum;
}
}
}
// Dual mining lasers of highest possible class; remove anything else
const miningLaserOrder = [2, 3, 4, 1, 0];
const miningLaserHardpoints = ship.hardpoints.concat().sort(function(a,b) {
@@ -284,6 +266,45 @@ export function miner(ship, shielded) {
}
}
// Number of collector limpets required to be active is a function of the size of the ship and the power of the lasers
const miningLaserDps = ship.hardpoints.filter(h => h.m != null)
.reduce(function(a, b) {
return a + b.m.getDps();
}, 0);
// Find out how many internal slots we have, and their potential cargo size
const potentialCargo = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.cr)
.map(b => Math.pow(2, b.maxClass));
// One collector for each 1.25 DPS, multiply by 1.25 for medium ships and 1.5 for large ships as they have further to travel
// 0 if we only have 1 cargo slot, otherwise minium of 1 and maximum of 6 (excluding size modifier)
const sizeModifier = ship.class == 2 ? 1.2 : ship.class == 3 ? 1.5 : 1;
let collectorLimpetsRequired = potentialCargo.length == 1 ? 0 : Math.ceil(sizeModifier * Math.min(6, Math.floor(miningLaserDps / 1.25)));
console.log(`${collectorLimpetsRequired}`);
if (collectorLimpetsRequired > 0) {
const collectorOrder = [1, 2, 3, 4, 5, 6, 7, 8];
const collectorInternals = ship.internal.filter(a => usedSlots.indexOf(a) == -1)
.filter(a => (!a.eligible) || a.eligible.cc)
.sort((a,b) => collectorOrder.indexOf(a.maxClass) - collectorOrder.indexOf(b.maxClass));
// Always keep at least 2 slots free for cargo racks (1 for shielded)
for (let i = 0; i < collectorInternals.length - (shielded ? 1 : 2) && collectorLimpetsRequired > 0; i++) {
if (canMount(ship, collectorInternals[i], 'cc')) {
// Collector only has odd classes
const collectorClass = collectorInternals[i].maxClass % 2 === 0 ? collectorInternals[i].maxClass - 1 : collectorInternals[i].maxClass;
ship.use(collectorInternals[i], ModuleUtils.findInternal('cc', collectorClass, 'D'));
usedSlots.push(collectorInternals[i]);
collectorLimpetsRequired -= collectorInternals[i].m.maximum;
}
}
}
// Power distributor to power the mining lasers indefinitely
const wepRateRequired = ship.hardpoints.filter(h => h.m != null)
.reduce(function(a, b) {
return a + b.m.getEps();
}, 0);
standardOpts.pd = ship.getAvailableModules().matchingPowerDist({weprate: wepRateRequired}).id;
// Fill the empty internals with cargo racks
for (let i = ship.internal.length; i--;) {
let slot = ship.internal[i];