Compare commits

..

20 Commits

Author SHA1 Message Date
William Blythe
9abb4f6d05 Merge branch 'develop' into dw2 2019-01-09 09:24:29 +11:00
willyb321
38038fcc32 fix a bug 2018-12-05 07:34:02 +11:00
William Blythe
9fa740f54e more work 2018-12-04 12:01:08 +11:00
William Blythe
d37d69c3a7 add some more guards on ships 2018-11-30 10:59:32 +11:00
William Blythe
78d8779641 add some guards on ships 2018-11-30 10:55:05 +11:00
Willyb321
352023f0fb Start work on roles 2018-11-30 09:08:26 +11:00
willyb321
3ea194d43e Merge branch 'develop' into dw2 2018-11-30 06:56:16 +11:00
willyb321
c6269192f0 mor edw2 2018-11-30 06:52:47 +11:00
willyb321
841e6c3348 More dw2 work, update roles etc 2018-11-30 06:37:09 +11:00
willyb321
0febc581d1 Merge branch 'develop' into dw2 2018-11-30 06:25:41 +11:00
Willyb321
dc6e398526 fighter hangar 2018-11-30 06:23:41 +11:00
Willyb321
cb24c1fc69 more dw2 work 2018-11-30 06:16:21 +11:00
William Blythe
90ad9de831 more dw2 2018-11-28 14:23:01 +11:00
William Blythe
9360b1d574 more dw2 work 2018-11-28 11:31:09 +11:00
William Blythe
08d2573d1f internals 2018-11-28 09:42:21 +11:00
Willyb321
427b9af7de up to shields 2018-11-28 08:25:05 +11:00
William Blythe
318d06d9f9 dw2 build work 2018-11-20 12:18:16 +11:00
William Blythe
1f3c3726f2 Merge branch 'dw2' of github.com:EDCD/coriolis into dw2 2018-11-20 09:29:08 +11:00
William
71beda3a6c Update docker-compose.yml 2018-11-20 08:36:16 +11:00
William
1d6644b531 Update docker-compose.yml 2018-11-20 08:34:53 +11:00
28 changed files with 1234 additions and 1098 deletions

View File

@@ -1,13 +0,0 @@
image: docker:stable
services:
- docker:dind
stages:
- Build image
docker build:
stage: Build image
script:
- img build --build-arg branch=$CI_COMMIT_REF_NAME -t edcd/coriolis:$CI_COMMIT_REF_NAME .
- echo "$REGISTRY_PASSWORD" | img login --username "$REGISTRY_USER" --password-stdin
- img push edcd/coriolis:$CI_COMMIT_REF_NAME

View File

@@ -1,24 +0,0 @@
All Data and [associated JSON](https://github.com/EDCD/coriolis-data) files are intellectual property and copyright of Frontier Developments plc ('Frontier', 'Frontier Developments') and are subject to their
[terms and conditions](https://www.frontierstore.net/terms-and-conditions/).
The code (Javascript, CSS, HTML, and SVG files only) specificially for Coriolis.io is released under the MIT License.
Copyright (c) 2015 Coriolis.io, Colin McLeod
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software (Javascript, CSS, HTML, and SVG files only), and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -10,8 +10,6 @@ services:
- web
labels:
- "traefik.docker.network=web"
- "traefik.frontend.redirect.regex=^https:\/\/coriolis\.edcd\.io\/(.*)"
- "traefik.frontend.redirect.replacement=https://coriolis.io/$1"
- "traefik.enable=true"
- "traefik.basic.frontend.rule=Host:coriolis.io,coriolis.edcd.io"
- "traefik.basic.port=80"
@@ -27,8 +25,6 @@ services:
labels:
- "traefik.docker.network=web"
- "traefik.enable=true"
- "traefik.frontend.redirect.regex=^https:\/\/beta\.coriolis\.edcd\.io\/(.*)"
- "traefik.frontend.redirect.replacement=https://beta.coriolis.io/$1"
- "traefik.basic.frontend.rule=Host:beta.coriolis.io,beta.coriolis.edcd.io"
- "traefik.basic.port=80"
- "traefik.basic.protocol=http"
@@ -47,6 +43,9 @@ services:
- "traefik.basic.port=80"
- "traefik.basic.protocol=http"
networks:
web:
external: true

View File

@@ -52,12 +52,12 @@ export default class Defence extends TranslatedComponent {
* @return {React.Component} contents
*/
render() {
const { opponent, sys, opponentWep } = this.props;
const { ship, sys, opponentWep } = this.props;
const { language, tooltip, termtip } = this.context;
const { formats, translate, units } = language;
const { shield, armour, shielddamage, armourdamage } = this.state;
const pd = opponent.standard[4].m;
const pd = ship.standard[4].m;
const shieldSourcesData = [];
const effectiveShieldData = [];

View File

@@ -121,7 +121,7 @@ export default class HardpointSlot extends Slot {
{m.getShieldBoost() ? <div className={'l'}>+{formats.pct1(m.getShieldBoost())}</div> : null}
{m.getAmmo() ? <div
className={'l'}>{translate('ammunition')}: {formats.int(m.getClip())}/{formats.int(m.getAmmo())}</div> : null}
{m.getReload() ? <div className={'l'}>{translate('wep_reload')}: {formats.round(m.getReload())}{u.s}</div> : null}
{m.getReload() ? <div className={'l'}>{translate('reload')}: {formats.round(m.getReload())}{u.s}</div> : null}
{m.getShotSpeed() ? <div
className={'l'}>{translate('shotspeed')}: {formats.int(m.getShotSpeed())}{u.mps}</div> : null}
{m.getPiercing() ? <div className={'l'}>{translate('piercing')}: {formats.int(m.getPiercing())}</div> : null}

View File

@@ -349,7 +349,7 @@ export default class Header extends TranslatedComponent {
_getShipsMenu() {
let shipList = [];
for (let s of this.shipOrder) {
for (let s in Ships) {
shipList.push(<ActiveLink key={s} href={outfitURL(s)} className='block'>{Ships[s].properties.name}</ActiveLink>);
}

View File

@@ -109,18 +109,17 @@ export default class ModalShoppingList extends TranslatedComponent {
*/
sendToEDEng(event) {
event.preventDefault();
let translate = this.context.language.translate;
const target = event.target;
target.disabled = this.state.blueprints.length > 0;
if (this.state.blueprints.length === 0) {
target.innerText = translate('No modded components.');
target.innerText = 'No modded components.';
target.disabled = true;
setTimeout(() => {
target.innerText = translate('Send to EDEngineer');
target.innerText = 'Send to EDEngineer';
target.disabled = false;
}, 3000);
} else {
target.innerText = translate('Sending...');
target.innerText = 'Sending...';
}
let countSent = 0;
let countTotal = this.state.blueprints.length;
@@ -140,7 +139,7 @@ export default class ModalShoppingList extends TranslatedComponent {
countSent++;
if (countSent === countTotal) {
target.disabled = false;
target.innerText = translate('Send to EDEngineer');
target.innerText = 'Send to EDEngineer';
}
});
}
@@ -231,32 +230,32 @@ export default class ModalShoppingList extends TranslatedComponent {
this.sendToEDEng = this.sendToEDEng.bind(this);
return <div className='modal' onClick={ (e) => e.stopPropagation() }>
<h2>{translate('PHRASE_SHOPPING_MATS')}</h2>
<label>{translate('Grade 1 rolls ')}</label>
<label>Grade 1 rolls </label>
<input id={1} type={'number'} min={0} defaultValue={this.state.matsPerGrade[1]} onChange={this.changeHandler} />
<br/>
<label>{translate('Grade 2 rolls ')}</label>
<label>Grade 2 rolls </label>
<input id={2} type={'number'} min={0} defaultValue={this.state.matsPerGrade[2]} onChange={this.changeHandler} />
<br/>
<label>{translate('Grade 3 rolls ')}</label>
<label>Grade 3 rolls </label>
<input id={3} type={'number'} min={0} value={this.state.matsPerGrade[3]} onChange={this.changeHandler} />
<br/>
<label>{translate('Grade 4 rolls ')}</label>
<label>Grade 4 rolls </label>
<input id={4} type={'number'} min={0} value={this.state.matsPerGrade[4]} onChange={this.changeHandler} />
<br/>
<label>{translate('Grade 5 rolls ')}</label>
<label>Grade 5 rolls </label>
<input id={5} type={'number'} min={0} value={this.state.matsPerGrade[5]} onChange={this.changeHandler} />
<div>
<textarea className='cb json' readOnly value={this.state.matsList} />
</div>
<label hidden={!compatible} className={'l cap'}>{translate('CMDR Name')}</label>
<label hidden={!compatible} className={'l cap'}>CMDR Name </label>
<br/>
<select hidden={!compatible} className={'cmdr-select l cap'} onChange={this.cmdrChangeHandler} defaultValue={this.state.cmdrName}>
{this.state.cmdrs.map(e => <option key={e}>{e}</option>)}
</select>
<br/>
<p hidden={!this.state.failed} id={'failed'} className={'l'}>{translate('PHRASE_FAIL_EDENGINEER')}</p>
<p hidden={compatible} id={'browserbad'} className={'l'}>{translate('PHRASE_FIREFOX_EDENGINEER')}</p>
<button className={'l cb dismiss cap'} disabled={!!this.state.failed || !compatible} onClick={this.sendToEDEng}>{translate('Send to EDEngineer')}</button>
<p hidden={!this.state.failed} id={'failed'} className={'l'}>Failed to send to EDEngineer (Launch EDEngineer and make sure the API is started then refresh the page.)</p>
<p hidden={compatible} id={'browserbad'} className={'l'}>Sending to EDEngineer is not compatible with Firefox's security settings. Please try again with Chrome.</p>
<button className={'l cb dismiss cap'} disabled={!!this.state.failed || !compatible} onClick={this.sendToEDEng}>{translate('Send To EDEngineer')}</button>
<button className={'r dismiss cap'} onClick={this.context.hideModal}>{translate('close')}</button>
</div>;
}

View File

@@ -478,7 +478,7 @@ export default class ModificationsMenu extends TranslatedComponent {
<tbody>
{ showRolls ?
<tr>
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: false }) }> { translate('mroll') }: </td>
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: false }) }> { translate('roll') }: </td>
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 0 }) } style={{ cursor: 'pointer' }} onClick={_rollWorst} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_WORST')} onMouseOut={tooltip.bind(null, null)}> { translate('0%') } </td>
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 50 })} style={{ cursor: 'pointer' }} onClick={_rollFifty} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_FIFTY')} onMouseOut={tooltip.bind(null, null)}> { translate('50%') } </td>
<td tabIndex="0" className={ cn('section-menu button-inline-menu', { active: blueprintCv === 100 })} style={{ cursor: 'pointer' }} onClick={_rollFull} onKeyDown={ this._keyDown } onMouseOver={termtip.bind(null, 'PHRASE_BLUEPRINT_BEST')} onMouseOut={tooltip.bind(null, null)}> { translate('100%') } </td>

View File

@@ -174,7 +174,7 @@ export default class OutfittingSubpages extends TranslatedComponent {
<th style={{ width:'25%' }} className={cn({ active: tab == 'power' })} onClick={this._showTab.bind(this, 'power')} >{translate('power and costs')}</th>
<th style={{ width:'25%' }} className={cn({ active: tab == 'profiles' })} onClick={this._showTab.bind(this, 'profiles')} >{translate('profiles')}</th>
<th style={{ width:'25%' }} className={cn({ active: tab == 'offence' })} onClick={this._showTab.bind(this, 'offence')} >{translate('offence')}</th>
<th style={{ width:'25%' }} className={cn({ active: tab == 'defence' })} onClick={this._showTab.bind(this, 'defence')} >{translate('tab_defence')}</th>
<th style={{ width:'25%' }} className={cn({ active: tab == 'defence' })} onClick={this._showTab.bind(this, 'defence')} >{translate('defence')}</th>
</tr>
</thead>
</table>

View File

@@ -20,16 +20,28 @@ export default class StandardSlotSection extends SlotSection {
super(props, context, 'standard', 'core internal');
this._optimizeStandard = this._optimizeStandard.bind(this);
this._selectBulkhead = this._selectBulkhead.bind(this);
this._showDW2Menu = this._showDW2Menu.bind(this);
this._dw2 = this._dw2.bind(this);
this.selectedRefId = null;
this.firstRefId = 'maxjump';
this.lastRefId = 'racer';
this.lastRefId = 'dw2';
this.state = {
showDW2: false,
DW2Tier: -1,
DW2Eng: -1,
DW2Role: '',
DW2Gfsb: false,
DW2Gpp: false,
DW2Fighter: false
};
}
/**
* Handle focus if the component updates
* @param {Object} prevProps React Component properties
*/
componentDidUpdate(prevProps) {
this._handleSectionFocus(prevProps,this.firstRefId, this.lastRefId);
this._handleSectionFocus(prevProps, this.firstRefId, this.lastRefId);
}
/**
@@ -72,6 +84,114 @@ export default class StandardSlotSection extends SlotSection {
this._close();
}
/**
* DW2 Build
*/
_dw2() {
this.selectedRefId = 'dw2';
this.setState({ showDW2: false });
ShipRoles.dw2Build(this.props.ship, this.state.DW2Tier, this.state.DW2Eng, this.state.DW2Role, this.state.DW2Gfsb, this.state.DW2Gpp, this.state.DW2Fighter);
this.props.ship.updateModificationsString();
this.props.onChange();
this.props.onCargoChange(this.props.ship.cargoCapacity);
this.props.onFuelChange(this.props.ship.fuelCapacity);
this._close();
}
_showDW2Menu(translate) {
return (
<div className='select' onClick={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
<div className='select-group cap'>{translate('Tier')}</div>
<ul id={'tier'}>
<li className={cn({ active: this.state.DW2Tier === 1 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Tier: 1 })} onKeyDown={this._keyDown}
>{translate('1 - Max. Jump Range, Unshielded')}</li>
<li className={cn({ active: this.state.DW2Tier === 2 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Tier: 2 })} onKeyDown={this._keyDown}
>{translate('2 - Max. Jump Range, Minimal Shields')}</li>
<li className={cn({ active: this.state.DW2Tier === 3 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Tier: 3 })} onKeyDown={this._keyDown}
>{translate('3 - Max. Jump Range, Optimal Shields')}</li>
<li className={cn({ active: this.state.DW2Tier === 4 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Tier: 4 })} onKeyDown={this._keyDown}
>{translate('4 - Max. Jump Range, Optimal Shields & Thrusters')}</li>
</ul>
<hr/>
<div className='select-group cap'>{translate('Engineering Level')}</div>
<ul id={'engLevel'}>
<li className={cn({ active: this.state.DW2Eng === 1 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Eng: 1 })} onKeyDown={this._keyDown}
>{translate('No engineering')}</li>
<li className={cn({ active: this.state.DW2Eng === 2 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Eng: 2 })} onKeyDown={this._keyDown}
>{translate('Only Felicity Farseer and Elvira Martuuk')}</li>
<li className={cn({ active: this.state.DW2Eng === 3 }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Eng: 3 })} onKeyDown={this._keyDown}
>{translate('All exploration engineers')}</li>
</ul>
<hr/>
<div className='select-group cap'>{translate('Role')}</div>
<ul id={'role'}>
<li className={cn({ active: this.state.DW2Role === 'exploration' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'exploration' })}
onKeyDown={this._keyDown}
>{translate('Space exploration')}</li>
<li className={cn({ active: this.state.DW2Role === 'surface' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'surface' })}
onKeyDown={this._keyDown}
>{translate('Surface exploration')}</li>
<li className={cn({ active: this.state.DW2Role === 'materialProspector' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'materialProspector' })}
onKeyDown={this._keyDown}
>{translate('Material prospector')}</li>
<li className={cn({ active: this.state.DW2Role === 'propectorMining' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'propectorMining' })}
onKeyDown={this._keyDown}
>{translate('Prospector/Sapper Miner')}</li>
<li className={cn({ active: this.state.DW2Role === 'bigRigMining' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'bigRigMining' })}
onKeyDown={this._keyDown}
>{translate('Big Rig, full mining')}</li>
<li className={cn({ active: this.state.DW2Role === 'fuelRat' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'fuelRat' })} onKeyDown={this._keyDown}
>{translate('Fuel Rat')}</li>
<li className={cn({ active: this.state.DW2Role === 'mechanic' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'mechanic' })} onKeyDown={this._keyDown}
>{translate('Mechanic')}</li>
<li className={cn({ active: this.state.DW2Role === 'trucker' }, 'lc')} tabIndex="0"
onClick={() => this.setState({ DW2Role: 'trucker' })} onKeyDown={this._keyDown}
>{translate('Trucker')}</li>
</ul>
<hr/>
<ul>
<li className={cn({ active: this.state.DW2Gfsb === true }, 'lc')}
onClick={() => this.setState({ DW2Gfsb: this.state.DW2Gfsb !== true })}>
Add Guardian FSD Booster
</li>
</ul>
<ul>
<li className={cn({ active: this.state.DW2Gpp === true }, 'lc')}
onClick={() => this.setState({ DW2Gpp: this.state.DW2Gpp !== true })}>
Add Guardian Power Plant
</li>
</ul>
<ul>
<li className={cn({ active: this.state.DW2Fighter === true }, 'lc')}
onClick={() => this.setState({ DW2Fighter: this.state.DW2Fighter !== true })}>
Add Fighter
</li>
</ul>
<hr/>
<ul>
<li onClick={this._dw2} className={cn('lc')} tabIndex="0"
onKeyDown={this._keyDown}>
<button className="button">Apply</button>
</li>
</ul>
</div>
);
}
/**
* Miner Build
* @param {Boolean} shielded True if shield generator should be included
@@ -177,7 +297,6 @@ export default class StandardSlotSection extends SlotSection {
warning={m => m instanceof Module ? m.getMaxMass() < (ship.unladenMass + cargo + fuel - st[1].m.mass + m.mass) : m.maxmass < (ship.unladenMass + cargo + fuel - st[1].m.mass + m.mass)}
/>;
slots[3] = <StandardSlot
key='fsd'
slot={st[2]}
@@ -232,7 +351,7 @@ export default class StandardSlotSection extends SlotSection {
selected={currentMenu == st[6]}
onChange={this.props.onChange}
ship={ship}
warning= {m => m.fuel < st[2].m.maxfuel} // Show warning when fuel tank is smaller than FSD Max Fuel
warning={m => m.fuel < st[2].m.maxfuel} // Show warning when fuel tank is smaller than FSD Max Fuel
/>;
return slots;
@@ -245,19 +364,34 @@ export default class StandardSlotSection extends SlotSection {
*/
_getSectionMenu(translate) {
let planetaryDisabled = this.props.ship.internal.length < 4;
if (this.state.showDW2 === true) {
return this._showDW2Menu(translate);
}
return <div className='select' onClick={(e) => e.stopPropagation()} onContextMenu={stopCtxPropagation}>
<ul>
<li className='lc' tabIndex="0" onClick={this._optimizeStandard} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['maxjump'] = smRef}>{translate('Maximize Jump Range')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeStandard} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['maxjump'] = smRef}>{translate('Maximize Jump Range')}</li>
</ul>
<div className='select-group cap'>{translate('roles')}</div>
<ul>
<li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, false, 0)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['multipurpose'] = smRef}>{translate('Multi-purpose')}</li>
<li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, true, 2)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['combat'] = smRef}>{translate('Combat')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeCargo.bind(this, true)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['trader'] = smRef}>{translate('Trader')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeExplorer.bind(this, false)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['explorer'] = smRef}>{translate('Explorer')}</li>
<li className={cn('lc', { disabled: planetaryDisabled })} tabIndex={planetaryDisabled ? '' : '0'} onClick={!planetaryDisabled && this._optimizeExplorer.bind(this, true)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['planetary'] = smRef}>{translate('Planetary Explorer')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeMiner.bind(this, true)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['miner'] = smRef}>{translate('Miner')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeRacer.bind(this)} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['racer'] = smRef}>{translate('Racer')}</li>
<li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, false, 0)} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['multipurpose'] = smRef}>{translate('Multi-purpose')}</li>
<li className='lc' tabIndex="0" onClick={this._multiPurpose.bind(this, true, 2)} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['combat'] = smRef}>{translate('Combat')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeCargo.bind(this, true)} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['trader'] = smRef}>{translate('Trader')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeExplorer.bind(this, false)} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['explorer'] = smRef}>{translate('Explorer')}</li>
<li className={cn('lc', { disabled: planetaryDisabled })} tabIndex={planetaryDisabled ? '' : '0'}
onClick={!planetaryDisabled && this._optimizeExplorer.bind(this, true)} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['planetary'] = smRef}>{translate('Planetary Explorer')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeMiner.bind(this, true)} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['miner'] = smRef}>{translate('Miner')}</li>
<li className='lc' tabIndex="0" onClick={this._optimizeRacer.bind(this)} onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['racer'] = smRef}>{translate('Racer')}</li>
<li className='lc' tabIndex="0" onClick={() => this.setState({ showDW2: !this.state.showDW2 })}
onKeyDown={this._keyDown}
ref={smRef => this.sectionRefArr['dw2'] = smRef}>{translate('DW2')}</li>
</ul>
</div>;
}

View File

@@ -7,12 +7,8 @@ import * as IT from './it';
import * as RU from './ru';
import * as PL from './pl';
import * as PT from './pt';
import * as CN from './cn';
import * as d3 from 'd3';
const owofy = require("owofy");
let fallbackTerms = EN.terms;
/**
@@ -31,7 +27,6 @@ export function getLanguage(langCode) {
case 'ru': lang = RU; break;
case 'pl': lang = PL; break;
case 'pt': lang = PT; break;
case 'cn': lang = CN; break;
default:
lang = EN;
}
@@ -42,14 +37,7 @@ export function getLanguage(langCode) {
const round = function(x, n) { const ten_n = Math.pow(10,n); return Math.round(x * ten_n) / ten_n; };
if(lang === EN) {
translate = (t, x) => {
if (currentTerms[t + '_' + x]) {
return owofy(currentTerms[t + '_' + x])
} else if (currentTerms[t]) {
return owofy(currentTerms[t])
}
return t;
};
translate = (t, x) => { return currentTerms[t + '_' + x] || currentTerms[t] || t; };
} else {
translate = (t, x) => { return currentTerms[t + '_' + x] || currentTerms[t] || fallbackTerms[t + '_' + x] || fallbackTerms[t] || t; };
}
@@ -106,6 +94,5 @@ export const Languages = {
fr: 'Français',
ru: 'ру́сский',
pl: 'polski',
pt: 'português',
cn: '中文'
pt: 'português'
};

View File

@@ -1,16 +0,0 @@
export const formats = {
decimal: '.',
thousands: ',',
grouping: [3],
currency: ['¥', ''],
dateTime: '%a %b %e %X %Y',
date: '%Y年%m月%d日',
time: '%H:%M:%S',
periods: ['AM', 'PM'],
days: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'],
shortDays: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
shortMonths: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
};
export { default as terms } from './cn.json';

File diff suppressed because one or more lines are too long

View File

@@ -81,8 +81,6 @@
"TT_SUMMARY_UNLADEN_TOTAL_JUMP": "Farthest possible range with no cargo, a full fuel tank, and jumping as far as possible each time",
"TT_SUMMARY_LADEN_TOTAL_JUMP": "Farthest possible range with full cargo, a full fuel tank, and jumping as far as possible each time",
"HELP_MODIFICATIONS_MENU": "Click on a number to enter a new value, or drag along the bar for small changes",
"PHRASE_FAIL_EDENGINEER": "Failed to send to EDEngineer (Launch EDEngineer and make sure the API is started then refresh the page.)",
"PHRASE_FIREFOX_EDENGINEER": "Sending to EDEngineer is not compatible with Firefox's security settings. Please try again with Chrome.",
"am": "Auto Field-Maintenance Unit",
"bh": "Bulkheads",
"bl": "Beam Laser",
@@ -174,7 +172,6 @@
"ammunition": "Ammo",
"secs": "s",
"rebuildsperbay": "Rebuilds per bay",
"mroll": "Roll",
"worst": "Worst",
"average": "Average",
"random": "Random",
@@ -323,7 +320,6 @@
"never": "never",
"stock": "stock",
"boost": "boost",
"tab_defence": "defence",
"federation rank 1": "Recruit",
"federation rank 2": "Cadet",
"federation rank 3": "Midshipman",

View File

@@ -6,7 +6,6 @@ import Ship from '../shipyard/Ship';
import * as ModuleUtils from '../shipyard/ModuleUtils';
import { SizeMap } from '../shipyard/Constants';
import Link from '../components/Link';
const owofy = require("owofy");
/**
* Counts the hardpoints by class/size
@@ -178,13 +177,13 @@ export default class ShipyardPage extends Page {
return (
<tr
key={s.id}
style={{ height: "1.5em" }}
style={{ height: '1.5em' }}
className={cn({
highlighted: noTouch && this.state.shipId === s.id
highlighted: noTouch && this.state.shipId === s.id,
})}
onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)}
>
<td className="ri">{owofy(s.manufacturer)}</td>
<td className="ri">{s.manufacturer}</td>
<td className="ri">{fInt(s.retailCost)}</td>
<td className="ri cap">{translate(SizeMap[s.class])}</td>
<td className="ri">{fInt(s.crew)}</td>
@@ -303,12 +302,13 @@ export default class ShipyardPage extends Page {
onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)}
>
<td className="le">
<Link href={'/outfit/' + s.id}>{owofy(s.name)} {s.beta === true ? '(Beta)' : null}</Link>
<Link href={'/outfit/' + s.id}>{s.name} {s.beta === true ? '(Beta)' : null}</Link>
</td>
</tr>
);
i++;
}
return (
<div className="page" style={{ fontSize: sizeRatio + 'em' }}>
<div
@@ -595,7 +595,6 @@ export default class ShipyardPage extends Page {
{detailRows}
</tbody>
</table>
</div>
</div>
</div>

View File

@@ -167,7 +167,7 @@ export default class Module {
} else if (name === 'shieldboost' || name === 'hullboost') {
modValue = (1 + value) / (1 + baseValue) - 1;
} else { // multiplicative
modValue = baseValue == 0 ? 0 : value / baseValue - 1;
modValue = value / baseValue - 1;
}
if (modification.type === 'percentage') {
@@ -703,7 +703,8 @@ export default class Module {
let result = 0;
if (this['maxmass']) {
result = this['maxmass'];
if (result && modified) {
// max mass is only modified for non-shield boosters
if (result && modified && this.grp !== 'sg') {
let mult = this.getModValue('optmass') / 10000;
if (mult) { result = result * (1 + mult); }
}

View File

@@ -164,13 +164,13 @@ export default class ModuleSet {
/**
* Finds the lightest usable Shield Generator
* @param {number} hullMass Ship hull mass
* @return {Object} Thruster
* @param {string} rating The optional rating of the shield
* @return {Object} Shield Generator
*/
lightestShieldGenerator(hullMass) {
lightestShieldGenerator(hullMass, rating) {
let sg = this.internal.sg[0];
for (let s of this.internal.sg) {
if (s.mass < sg.mass && s.maxmass > hullMass) {
if ((!rating || rating === s.rating) && s.mass <= sg.mass && s.maxmass > hullMass) {
sg = s;
}
}

View File

@@ -1308,7 +1308,7 @@ export default class Ship {
let fsd = this.standard[2].m; // Frame Shift Drive;
let { unladenMass, fuelCapacity } = this;
this.unladenRange = this.calcUnladenRange(); // Includes fuel weight for jump
this.fullTankRange = Calc.jumpRange(unladenMass + fuelCapacity, fsd, fuelCapacity, this); // Full Tank
this.fullTankRange = Calc.jumpRange(unladenMass + fuelCapacity, fsd, this); // Full Tank
this.ladenRange = this.calcLadenRange(); // Includes full tank and caro
this.unladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity, fsd, fuelCapacity, this);
this.ladenFastestRange = Calc.totalJumpRange(unladenMass + this.fuelCapacity + this.cargoCapacity, fsd, fuelCapacity, this);

View File

@@ -1,5 +1,7 @@
import * as ModuleUtils from './ModuleUtils';
import { Modifications } from 'coriolis-data/dist';
import { canMount } from '../utils/SlotFunctions';
import { getBlueprint, setPercent } from '../utils/BlueprintFunctions';
/**
* Standard / typical role for multi-purpose or combat (if shielded with better bulkheads)
@@ -14,7 +16,7 @@ export function multiPurpose(ship, shielded, bulkheadIndex) {
.useBulkhead(bulkheadIndex);
if (shielded) {
ship.internal.some(function(slot) {
ship.internal.some(function (slot) {
if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield
ship.use(slot, ModuleUtils.findInternal('sg', slot.maxClass, 'A'));
ship.setSlotEnabled(slot, true);
@@ -24,6 +26,577 @@ export function multiPurpose(ship, shielded, bulkheadIndex) {
}
}
/**
* Distant Worlds 2 role
* Tiers:
* 1- Max. Jump Range, Unshielded
* 2- Max. Jump Range, Minimal Shields
* 3- Max. Jump Range, Optimal Shields
* 4- Max. Jump Range, Optimal Shields & Thrusters
*
* Engineering level:
* No engineering
* Only Felicity Farseer and Elvira Martuuk
* All exploration related engineers
*
* Role
* Exploration
* Surface exploration
* Big Rig, full mining
* Saper / Prospector mining
* Fuel rat
* Repair rat
* Mechanic
* Trucker
*
* @param ship {Ship} Ship instance
* @param tier {Number}
* @param engineeringLevel {Number}
* @param role {String}
* @param gfsb {Boolean} add Guardian FSD Booster
* @param gpp {Boolean} add Guardian Power Plant
* @param fighter {Boolean} add fighter if supported
*/
export function dw2Build(ship, tier, engineeringLevel, role, gfsb, gpp, fighter) {
ship
.emptyInternal()
.emptyHardpoints()
.emptyUtility();
const fsd = ModuleUtils.findStandard('fsd', ship.standard[2].maxClass, 'A');
ship.use(ship.standard[2], fsd);
ship.use(ship.standard[3], ModuleUtils.findStandard('ls', ship.standard[3].maxClass, 'D'));
ship.use(ship.standard[4], ModuleUtils.findStandard('pd', 1, 'D'));
ship.use(ship.standard[5], ModuleUtils.findStandard('s', ship.standard[5].maxClass, 'D'));
const fuelNeeded = ship.standard[2].m.maxfuel * 2;
const fuelTank = ship.availCS.standard[6]
.filter(e => e.fuel)
.filter(e => e.fuel >= fuelNeeded);
ship.use(ship.standard[6], fuelTank[0]);
ship.useBulkhead(0, false);
if (engineeringLevel === 2) {
const bp = getBlueprint('FSD_LongRange', ship.standard[2]);
bp.grade = 5;
bp.special = Modifications.specials['special_fsd_heavy'];
ship.standard[2].m.blueprint = bp;
setPercent(ship, ship.standard[2].m, 100);
// Sensors G3 LW
const sBP = getBlueprint('Sensor_Sensor_LightWeight', ship.standard[5]);
sBP.grade = 3;
ship.standard[5].m.blueprint = sBP;
setPercent(ship, ship.standard[5].m, 100);
} else if (engineeringLevel === 3) {
// Armour G5 HD + Deep Plating
const armourBP = getBlueprint('Armour_HeavyDuty', ship.bulkheads);
armourBP.grade = 5;
armourBP.special = Modifications.specials['special_armour_chunky'];
ship.bulkheads.m.blueprint = armourBP;
setPercent(ship, ship.bulkheads.m, 100);
// FSD G5 IR + Mass Manager
const fsdBP = getBlueprint('FSD_LongRange', ship.standard[2]);
fsdBP.grade = 5;
fsdBP.special = Modifications.specials['special_fsd_heavy'];
ship.standard[2].m.blueprint = fsdBP;
setPercent(ship, ship.standard[2].m, 100);
// LS G4 LW
const lsBP = getBlueprint('LifeSupport_LightWeight', ship.standard[3]);
lsBP.grade = 4;
ship.standard[3].m.blueprint = lsBP;
setPercent(ship, ship.standard[3].m, 100);
// Sensors G5 LW
const sBP = getBlueprint('Sensor_Sensor_LightWeight', ship.standard[5]);
sBP.grade = 5;
ship.standard[5].m.blueprint = sBP;
setPercent(ship, ship.standard[5].m, 100);
}
if (ship.id === 'imperial_clipper') {
const fs = ModuleUtils.findInternal('fs', 4, 'A');
const slot = ship.internal.filter(a => a.maxClass === 4)[0];
ship.use(slot, fs);
} else if (ship.id === 'imperial_cutter') {
const fs = ModuleUtils.findInternal('fs', 6, 'A');
const slot = ship.internal.filter(a => a.maxClass === 6)[0];
ship.use(slot, fs);
} else if (fsd.class === 2 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 2, 'A');
let slot = ship.internal.filter(a => a.maxClass >= 2).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot.m) {
fs = ModuleUtils.findInternal('fs', 1, 'A');
slot = ship.internal.filter(a => a.maxClass === 1)[0];
ship.use(slot, fs);
} else {
ship.use(slot, fs);
}
} else if (fsd.class === 3 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 3, 'B');
let slot = ship.internal.filter(a => a.maxClass >= 3).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot.m) {
fs = ModuleUtils.findInternal('fs', 2, 'A');
slot = ship.internal.filter(a => a.maxClass === 2)[0];
ship.use(slot, fs);
} else {
ship.use(slot, fs);
}
} else if (fsd.class === 4 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 4, 'b');
let slot = ship.internal.filter(a => a.maxClass >= 4).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot.m) {
fs = ModuleUtils.findInternal('fs', 3, 'A');
slot = ship.internal.filter(a => a.maxClass === 3)[0];
ship.use(slot, fs);
} else {
ship.use(slot, fs);
}
} else if (fsd.class === 5 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 5, 'B');
let slot = ship.internal.filter(a => a.maxClass >= 5).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot.m) {
fs = ModuleUtils.findInternal('fs', 4, 'A');
slot = ship.internal.filter(a => a.maxClass === 4).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (fs) {
ship.use(slot, fs);
}
} else {
if (fs) {
ship.use(slot, fs);
}
}
} else if (fsd.class === 6 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 6, 'B');
let slot = ship.internal.filter(a => a.maxClass >= 6)
.filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot.m) {
fs = ModuleUtils.findInternal('fs', 5, 'A');
slot = ship.internal.filter(a => a.maxClass === 5)[0];
if (fs) {
ship.use(slot, fs);
}
} else {
if (fs) {
ship.use(slot, fs);
}
}
} else if (fsd.class === 7 && fsd.rating === 'A') {
let fs = ModuleUtils.findInternal('fs', 7, 'B');
let slot = ship.internal.filter(a => a.maxClass >= 7).filter(a => a.maxClass >= fs.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (slot && slot.m) {
fs = ModuleUtils.findInternal('fs', 6, 'A');
slot = ship.internal.filter(a => a.maxClass === 6)[0];
if (fs) {
ship.use(slot, fs);
}
} else {
if (fs) {
ship.use(slot, fs);
}
}
}
if (tier !== 1) {
const fuelNeeded = ship.standard[2].m.maxfuel * 3;
const fuelTank = ship.availCS.standard[6]
.filter(e => e.fuel)
.filter(e => e.fuel >= fuelNeeded);
if (fuelTank[0]) {
ship.use(ship.standard[6], fuelTank[0]);
}
}
if (tier === 2) {
if (ship.id === 'alliance_chieftain' || ship.id === 'alliance_crusader' || ship.id === 'federal_gunship' || ship.id === 'vulture') {
const hrp = ModuleUtils.findInternal('hrp', 3, 'D');
const slot = ship.internal.filter(e => e.eligible && e.maxClass === 3);
if (hrp) {
ship.use(slot, hrp);
}
} else {
const sg = ship.getAvailableModules().lightestShieldGenerator(ship.ladenMass);
const slot = ship.internal.filter(a => !a.m)
.filter(a => a.maxClass >= sg.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (sg) {
ship.use(slot, sg);
}
if (engineeringLevel === 2) {
// ELP G3
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
shieldBP.grade = 3;
ship.findShieldGenerator().blueprint = shieldBP;
setPercent(ship, ship.findShieldGenerator(), 100);
} else if (engineeringLevel === 3) {
// ELP G5
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
shieldBP.grade = 5;
ship.findShieldGenerator().blueprint = shieldBP;
setPercent(ship, ship.findShieldGenerator(), 100);
}
// const shieldOrder = [1, 2, 3, 4, 5, 6, 7, 8].reverse();
// const shieldInternals = ship.internal.filter(a => !a.m)
// .filter(a => (!a.eligible) || a.eligible.sg)
// .filter(a => a.maxClass >= sg.class)
// .sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
// for (let i = 0; i < shieldInternals.length; i++) {
// if (canMount(ship, shieldInternals[i], 'sg')) {
// ship.use(shieldInternals[i], sg);
// break;
// }
// }
}
} else if (tier === 3 || tier === 4) {
const sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass, 'A');
const slot = ship.internal.filter(a => !a.m)
.filter(a => a.maxClass >= sg.class)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
if (sg) {
ship.use(slot, sg);
}
if (engineeringLevel === 1) {
// ELP G3
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
shieldBP.grade = 3;
shieldBP.special = Modifications.specials['special_shield_lightweight'];
ship.findShieldGenerator().blueprint = shieldBP;
setPercent(ship, ship.findShieldGenerator(), 100);
} else if (engineeringLevel === 2) {
// ELP G5
const shieldBP = getBlueprint('ShieldGenerator_Optimised', ship.findShieldGenerator());
shieldBP.grade = 5;
shieldBP.special = Modifications.specials['special_shield_lightweight'];
ship.findShieldGenerator().blueprint = shieldBP;
setPercent(ship, ship.findShieldGenerator(), 100);
}
}
if (tier === 4) {
let t;
if (canMount(ship, ship.standard[1], 't', ship.standard[1].maxClass - 1)) {
t = ModuleUtils.findStandard('t', ship.standard[1].maxClass - 1, 'A');
} else {
t = ModuleUtils.findStandard('t', ship.standard[1].maxClass, 'A');
}
if (t) {
ship.use(ship.standard[1], t);
}
if (engineeringLevel === 1) {
// DD G3
const tBP = getBlueprint('Engine_Dirty', ship.standard[1]);
tBP.grade = 3;
tBP.special = Modifications.specials['special_engine_lightweight'];
ship.standard[1].m.blueprint = tBP;
setPercent(ship, ship.standard[1].m, 100);
} else if (engineeringLevel === 2) {
// DD G5
const tBP = getBlueprint('Engine_Dirty', ship.standard[1]);
tBP.grade = 5;
tBP.special = Modifications.specials['special_engine_lightweight'];
ship.standard[1].m.blueprint = tBP;
setPercent(ship, ship.standard[1].m, 100);
}
}
if (tier === 4 || tier === 3) {
if (engineeringLevel === 3) {
const pd = ship.availCS.standard[4]
.filter(d => d.rating === 'D')
.filter(d => (d.engcap * 1.728) >= ship.boostEnergy)
.sort((a, b) => a.class.toString().localeCompare(b.class.toString()))[0];
if (pd) {
ship.use(ship.standard[4], pd);
}
// CE G5
const pdBP = getBlueprint('PowerDistributor_HighFrequency', ship.standard[4]);
pdBP.grade = 5;
pdBP.special = Modifications.specials['special_powerdistributor_capacity'];
ship.standard[4].m.blueprint = pdBP;
setPercent(ship, ship.standard[4].m, 100);
} else {
const pd = ship.availCS.standard[4]
.filter(d => d.rating === 'D')
.sort((a, b) => a.engcap > b.engcap)
[0];
if (pd) {
ship.use(ship.standard[4], pd);
}
}
} else if (tier === 4) {
if (engineeringLevel === 3) {
const pd = ship.availCS.standard[4]
.filter(d => d.rating === 'D')
.sort((a, b) => b.class.toString().localeCompare(a.class.toString()))[0];
if (pd) {
ship.use(ship.standard[4], pd);
}
// CE G5
const pdBP = getBlueprint('PowerDistributor_HighFrequency', ship.standard[4]);
pdBP.grade = 5;
pdBP.special = Modifications.specials['special_powerdistributor_capacity'];
ship.standard[4].m.blueprint = pdBP;
setPercent(ship, ship.standard[4].m, 100);
} else {
const pd = ship.availCS.standard[4]
.filter(d => d.rating === 'D')
.sort((a, b) => b.class.toString().localeCompare(a.class.toString()))[0];
if (pd) {
ship.use(ship.standard[4], pd);
}
}
}
if (ship.fighterHangars && fighter) {
const slot = ship.internal.filter(s => s.maxClass >= 5 && !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))
[0];
const mod = ModuleUtils.findInternal('fh', 5, 'D');
if (slot && mod) {
ship.use(slot, mod);
}
}
if (tier === 1) {
const pd = ModuleUtils.findStandard('pd', 1, 'D');
if (pd) {
ship.use(ship.standard[4]);
}
}
let dssPriority = 0;
let srvPriority = 0;
let afmu = true;
let cargo = false;
let miningLaserPriority = 0;
let refinery = false;
let collector = false;
let prospector = false;
let miningTools = false;
let refuelLimpets = false;
let repairLimpets = false;
console.log(role);
if (role === 'exploration') {
dssPriority = 2;
afmu = true;
} else if (role === 'surface') {
dssPriority = 2;
srvPriority = 2;
} else if (role === 'materialProspector') {
miningLaserPriority = 2;
srvPriority = 1;
} else if (role === 'propectorMining') {
dssPriority = 1;
prospector = true;
miningLaserPriority = 1;
cargo = true;
miningTools = true;
} else if (role === 'bigRigMining') {
dssPriority = 1;
miningLaserPriority = 2;
cargo = true;
collector = true;
refinery = true;
miningTools = true;
} else if (role === 'fuelRat') {
refuelLimpets = true;
cargo = true;
srvPriority = 1;
} else if (role === 'mechanic') {
repairLimpets = true;
cargo = true;
srvPriority = 1;
} else if (role === 'trucker') {
cargo = true;
}
if (dssPriority === 2) {
const mod = ModuleUtils.findModule('ss', '2i');
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
console.log(slot);
console.log(mod);
ship.use(slot, mod);
}
if (srvPriority === 2) {
let mod;
let slot = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 6)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
if (slot) {
mod = ModuleUtils.findModule('pv', 'v2');
ship.use(slot, mod);
} else if (!slot) {
slot = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 4)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
if (slot) {
mod = ModuleUtils.findModule('pv', 'v4');
ship.use(slot, mod);
} else {
slot = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 2)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
if (slot) {
mod = ModuleUtils.findModule('pv', 'v6');
ship.use(slot, mod);
}
}
}
}
if (cargo === true) {
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => b.maxClass.toString().localeCompare(a.maxClass.toString()))[0];
const mod = ModuleUtils.findInternal('cr', slot.maxClass, 'E');
ship.use(slot, mod);
}
if (refuelLimpets === true) {
const mod = ModuleUtils.findModule('fx', 'F4');
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
ship.use(mod, slot);
}
if (repairLimpets === true) {
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
let mod;
if (slot.maxClass >= 3) {
mod = ModuleUtils.findModule('rpl', '9e');
} else {
mod = ModuleUtils.findModule('rpl', '9s');
}
ship.use(mod, slot);
}
if (prospector === true) {
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
let mod;
if (slot.maxClass >= 3) {
mod = ModuleUtils.findModule('pc', 'P9');
} else {
mod = ModuleUtils.findModule('pc', 'P4');
}
ship.use(mod, slot);
}
if (collector === true) {
const slots = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()));
if (slots.length >= 2) {
let slot = slots.find(s => s.maxClass >= 5);
let mod;
if (slot) {
mod = ModuleUtils.findInternal('cc', slot.maxClass, 'D');
} else if (slots.find(s => s.maxClass <= 4)) {
slot = slots.find(s => s.maxClass <= 4);
mod = ModuleUtils.findInternal('cc', slot.maxClass, 'D');
}
ship.use(slot, mod);
}
}
if (refinery === true) {
const slots = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 4)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
if (slots) {
const mod = ModuleUtils.findInternal('rf', 4, 'A');
ship.use(slots, mod);
} else {
const slot = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass <= 3)
.sort((a, b) => b.maxClass.toString().localeCompare(a.maxClass.toString()))[0];
const mod = ModuleUtils.findInternal('rf', slot.maxClass, 'A');
ship.use(slots, mod);
}
}
if (dssPriority === 1) {
const slot = ship.internal.filter(s => !s.m)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()))[0];
const dss = ModuleUtils.findInternal('ss', 1, 'C')
if (slot) {
ship.use(slot, dss);
}
}
if (srvPriority === 1) {
const slot = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 2)
.sort((a, b) => a.maxClass.toString().localeCompare(b.maxClass.toString()));
if (slot.find(s => s.maxClass >= 4)) {
const slot = slot.find(s => s.maxClass >= 4);
const srv = ModuleUtils.findInternal('pv', 4, 'G')
ship.use(slot, srv);
} else if (slot.find(s => s.maxClass >= 2)) {
const slot = slot.find(s => s.maxClass >= 2);
const srv = ModuleUtils.findInternal('pv', 2, 'G')
ship.use(slot, srv);
}
}
if (gfsb === true) {
const slots = ship.internal.filter(s => !s.m)
.filter(s => s.maxClass >= 1)
.sort((a, b) => b.maxClass.toString().localeCompare(a.maxClass.toString()));
if (slots.find(s => s.maxClass >= 5)) {
const mod = ModuleUtils.findInternal('gfsb', 5, 'H');
ship.use(slots.find(s => s.maxClass >= 5), mod)
} else if (slots.find(s => s.maxClass >= 4)) {
const mod = ModuleUtils.findInternal('gfsb', 4, 'H');
ship.use(slots.find(s => s.maxClass >= 4), mod)
} else if (slots.find(s => s.maxClass >= 3)) {
const mod = ModuleUtils.findInternal('gfsb', 3, 'H');
ship.use(slots.find(s => s.maxClass >= 3), mod)
} else if (slots.find(s => s.maxClass >= 2)) {
const mod = ModuleUtils.findInternal('gfsb', 2, 'H');
ship.use(slots.find(s => s.maxClass >= 2), mod)
} else if (slots.find(s => s.maxClass >= 1)) {
const mod = ModuleUtils.findInternal('gfsb', 1, 'H');
ship.use(slots.find(s => s.maxClass >= 1), mod)
}
}
// const pp = ship.getAvailableModules().lightestPowerPlant(Math.max(ship.powerRetracted, ship.powerDeployed), 'A');
// const t = ship.getAvailableModules().lightestThruster(ship.ladenMass);
// ship.use(ship.standard[0], pp);
// ship.use(ship.standard[1], t);
// ship.useLightestStandard(standardOpts);
ship.updatePowerGenerated()
.updatePowerUsed()
.recalculateMass()
.updateJumpStats()
.recalculateShield()
.recalculateShieldCells()
.recalculateArmour()
.recalculateDps()
.recalculateEps()
.recalculateHps()
.updateMovement()
.updateModificationsString();
}
/**
* Trader Role
* @param {Ship} ship Ship instance
@@ -36,7 +609,7 @@ export function trader(ship, shielded, standardOpts) {
let sg = ship.getAvailableModules().lightestShieldGenerator(ship.hullMass);
ship.useStandard('A')
.use(ship.standard[3], ModuleUtils.standard(3, ship.standard[3].maxClass + 'D')) // D Life Support
.use(ship.standard[1], ModuleUtils.standard(1, ship.standard[1].maxClass + 'D')) // D Life Support
.use(ship.standard[1], ModuleUtils.standard(1, ship.standard[1].maxClass + 'D')) // D Power Plant
.use(ship.standard[4], ModuleUtils.standard(4, ship.standard[4].maxClass + 'D')) // D Life Support
.use(ship.standard[5], ModuleUtils.standard(5, ship.standard[5].maxClass + 'D')); // D Sensors
@@ -45,7 +618,7 @@ export function trader(ship, shielded, standardOpts) {
.filter(a => (!a.eligible) || a.eligible.sg)
.filter(a => a.maxClass >= sg.class)
.sort((a, b) => shieldOrder.indexOf(a.maxClass) - shieldOrder.indexOf(b.maxClass));
shieldInternals.some(function(slot) {
shieldInternals.some(function (slot) {
if (canMount(ship, slot, 'sg')) { // Assuming largest slot can hold an eligible shield
const shield = ModuleUtils.findInternal('sg', slot.maxClass, 'A');
if (shield && shield.maxmass > ship.hullMass) {
@@ -269,7 +842,7 @@ export function miner(ship, shielded) {
// 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) {
const miningLaserHardpoints = ship.hardpoints.concat().sort(function (a, b) {
return miningLaserOrder.indexOf(a.maxClass) - miningLaserOrder.indexOf(b.maxClass);
});
for (let s of miningLaserHardpoints) {
@@ -283,7 +856,7 @@ 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) {
.reduce(function (a, b) {
return a + b.m.getDps();
}, 0);
// Find out how many internal slots we have, and their potential cargo size
@@ -314,7 +887,7 @@ export function miner(ship, shielded) {
// Power distributor to power the mining lasers indefinitely
const wepRateRequired = ship.hardpoints.filter(h => h.m != null)
.reduce(function(a, b) {
.reduce(function (a, b) {
return a + b.m.getEps();
}, 0);
standardOpts.pd = ship.getAvailableModules().matchingPowerDist({ weprate: wepRateRequired }).id;

View File

@@ -145,11 +145,11 @@ export function diffDetails(language, m, mm) {
if (m.grp === 'pp') {
let mPowerGeneration = m.pgen || 0;
let mmPowerGeneration = mm ? mm.getPowerGeneration() : 0;
if (mPowerGeneration != mmPowerGeneration) propDiffs.push(<div key='pgen'>{translate('pgen')}: <span className={diffClass(mPowerGeneration, mmPowerGeneration)}>{diff(formats.round, mPowerGeneration, mmPowerGeneration)}{units.MW}</span></div>);
if (mPowerGeneration != mmPowerGeneration) propDiffs.push(<div key='pgen'>{translate('pgen')}: <span className={diffClass(mPowerGeneration, mmPowerGeneration)}>{diff(formats.round, mPowerGeneration, mmPowerGeneration)}{units.MJ}</span></div>);
} else {
let mPowerUsage = m.power || 0;
let mmPowerUsage = mm ? mm.getPowerUsage() || 0 : 0;
if (mPowerUsage != mmPowerUsage) propDiffs.push(<div key='power'>{translate('power')}: <span className={diffClass(mPowerUsage, mmPowerUsage, true)}>{diff(formats.round, mPowerUsage, mmPowerUsage)}{units.MW}</span></div>);
if (mPowerUsage != mmPowerUsage) propDiffs.push(<div key='power'>{translate('power')}: <span className={diffClass(mPowerUsage, mmPowerUsage, true)}>{diff(formats.round, mPowerUsage, mmPowerUsage)}{units.MJ}</span></div>);
}
let mDps = m.damage * (m.rpshot || 1) * (m.rof || 1);

View File

@@ -1,61 +0,0 @@
.clippy, .clippy-balloon {
position: fixed;
z-index: 1000;
cursor: pointer;
}
.clippy-balloon {
background: #FFC;
color: black;
padding: 8px;
border: 1px solid black;
border-radius: 5px;
}
.clippy-content {
max-width: 200px;
min-width: 120px;
font-family: "Microsoft Sans", sans-serif;
font-size: 10pt;
}
.clippy-tip {
width: 10px;
height: 16px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAgCAMAAAAlvKiEAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAlQTFRF///MAAAA////52QwgAAAAAN0Uk5T//8A18oNQQAAAGxJREFUeNqs0kEOwCAIRFHn3//QTUU6xMyyxii+jQosrTPkyPEM6IN3FtzIRk1U4dFeKWQiH6pRRowMVKEmvronEynkwj0uZJgR22+YLopPSo9P34wJSamLSU7lSIWLJU7NkNomNlhqxUeAAQC+TQLZyEuJBwAAAABJRU5ErkJggg==) no-repeat;
position: absolute;
}
.clippy-top-left .clippy-tip {
top: 100%;
margin-top: 0px;
left: 100%;
margin-left: -50px;
}
.clippy-top-right .clippy-tip {
top: 100%;
margin-top: 0px;
left: 0;
margin-left: 50px;
background-position: -10px 0;
}
.clippy-bottom-right .clippy-tip {
top: 0;
margin-top: -16px;
left: 0;
margin-left: 50px;
background-position: -10px -16px;
}
.clippy-bottom-left .clippy-tip {
top: 0;
margin-top: -16px;
left: 100%;
margin-left: -50px;
background-position: 0px -16px;
}

1
src/clippy.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
<!DOCTYPE html>
<html>
<head>
<head>
<title>Coriolis EDCD Edition</title>
<meta charset="UTF-8">
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[0] %>">
@@ -34,8 +34,7 @@
</script>
<% if (htmlWebpackPlugin.options.uaTracking) { %>
<script>
window.ga = window.ga || function() {(ga.q = ga.q || []).push(arguments);};
ga.l = +new Date;
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', '<%- htmlWebpackPlugin.options.uaTracking %>', 'auto');
ga('send', 'pageview');
</script>
@@ -56,47 +55,18 @@
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
</script>-->
</script>-->
<!-- End Piwik Code -->
<!-- Bugsnag -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
<script src="https://d2wy8f7a9ursnm.cloudfront.net/v5.0.0/bugsnag.min.js"></script>
<script src="/clippy.min.js"></script>
<script type="text/javascript">
const advice = ['When all else fails, Put a docking computer in every slot. My name is Clippy.',
'Fly in a stright line and roll, your evasion increases by 200%!',
'Boost!!!',
'If you are running out of power, consider deactivating thrusters!',
'Make sure to set fire-groups for your SCBs!',
'If you find yourself dying often - git gud!',
'Remember, shield boosters increase skill!',
'Remember, B rated drives offer greater speed!',
'Point directly into the jet cone and full throttle for optimal FSD boost.',
'Raxxla can only be found in open play.',
'Try silent running when under focus to drop aggro, and reboot when your opponents lose sight of you!'];
clippy.load('Clippy', function(agent) {
// do anything with the loaded agent
agent.show();
setInterval(() => {
agent.animate();
const toSpeak = advice[Math.random() * advice.length >> 0];
agent.speak(toSpeak);
}, (20000));
setInterval(() => {
agent.animate();
agent.speak('@everyone FDL. :pray:');
}, (69000));
});
</script>
<script>
window.bugsnagClient = bugsnag('ba9fae819372850fb660755341fa6ef5', { appVersion: window.BUGSNAG_VERSION || undefined });
window.Bugsnag = window.bugsnagClient;
window.bugsnagClient = bugsnag('ba9fae819372850fb660755341fa6ef5', {appVersion: window.BUGSNAG_VERSION || undefined})
window.Bugsnag = window.bugsnagClient
</script>
</head>
<body style="background-color:#000;">
<section id="coriolis"></section>
</head>
<body style="background-color:#000;">
<section id="coriolis"></section>
</body>
</html>
</body>
</html>

View File

@@ -184,5 +184,3 @@ footer {
border: 1px @secondary solid;
padding: 10px;
}
@import "../../node_modules/clippy.js/build/clippy.css";

View File

@@ -6,8 +6,8 @@
// Foreground colors
@fg: #CCC;
@muted: #999;
@primary: #e64980; // Light Orange
@secondary: #9775fa; // Light blue
@primary: #FF8C0D; // Light Orange
@secondary: #1FB0FF; // Light blue
@warning: #FF3B00; // Dark Orange
@disabled: #555; // Light grey
@success: #71a052; // Green

View File

@@ -30,7 +30,7 @@ module.exports = {
publicPath: '/'
},
plugins: [
new CopyWebpackPlugin(['src/.htaccess', 'src/iframe.html', 'src/xdLocalStoragePostMessageApi.min.js', 'src/clippy.min.js']),
new CopyWebpackPlugin(['src/.htaccess', 'src/iframe.html', 'src/xdLocalStoragePostMessageApi.min.js']),
// new webpack.optimize.CommonsChunkPlugin({
// name: 'lib',
// filename: 'lib.js'

View File

@@ -32,7 +32,7 @@ module.exports = {
from: 'src/images/logo/*',
flatten: true,
to: ''
}, 'src/iframe.html', 'src/xdLocalStoragePostMessageApi.min.js', 'src/clippy.min.js']),
}, 'src/iframe.html', 'src/xdLocalStoragePostMessageApi.min.js']),
// new webpack.optimize.CommonsChunkPlugin({
// name: 'lib',
// filename: 'lib.[chunkhash:6].js'