Compare commits

...

28 Commits

Author SHA1 Message Date
Willyb321
3eb26651f7 initial ed-forgr 2018-11-22 09:44:11 +11:00
willyb321
ec0d05e081 add beta resting heat 2018-11-22 07:31:45 +11:00
Willyb321
b3be0bd639 remove logs 2018-11-21 09:00:50 +11:00
Willyb321
529d80682c Merge branch 'develop' of github.com:edcd/coriolis into develop 2018-11-21 08:51:32 +11:00
Willyb321
934de01803 add announcements to actual page 2018-11-21 08:50:53 +11:00
William
3367580d78 Apply diminishing returns for hull resistance modding to all modules (#425)
References #396
2018-11-21 08:38:46 +11:00
felixlinker
fbf59219d0 Apply diminishing returns for hull resistance modding to all modules 2018-11-20 20:57:39 +00:00
William Blythe
77401a3b3f get ready for dw2 site 2018-11-19 09:21:18 +11:00
willyb321
7c587c29aa add build reporter plugin 2018-11-19 07:12:36 +11:00
willyb321
2295dccd82 re-enable bugsnag 2018-11-19 07:10:05 +11:00
willyb321
cc4ad6d132 and a bit moree 2018-11-19 06:58:53 +11:00
willyb321
8a2d27290a add some logging to assist DWE2 people (temp) 2018-11-19 06:58:12 +11:00
willyb321
eda61a8e06 in theory fix guardian pds
Closes #339
2018-11-17 09:26:57 +11:00
William Blythe
71b90eb6f4 maybe an actually good service worker for once 2018-11-13 09:11:43 +11:00
willyb321
4e891f382c prep for import 2018-11-13 06:25:17 +11:00
willyb321
3d3f9e44b5 add damage per shot 2018-11-11 01:57:06 +11:00
willyb321
dd7a133caa add search bar initial
why am i awake its like 2am
2018-11-11 01:31:30 +11:00
willyb321
ae247c4812 support beta flag 2018-11-10 09:39:22 +11:00
William Blythe
6c932f96a6 add fill weapons for AX weps 2018-11-09 11:28:37 +11:00
William Blythe
0ea25692d3 work on sw 2018-11-07 13:09:04 +11:00
William Blythe
8e5dd9fb8d add iframe to allow posting builds 2018-11-05 11:51:50 +11:00
William Blythe
97ce2828e0 mamba prep 2018-11-02 09:57:48 +11:00
William Blythe
6e79ced51e remove halloween 2018-11-01 07:28:54 +11:00
William Blythe
0b10cac85c halloween 2018-10-31 09:20:05 +11:00
Stratos Gerakakis
34c04a6354 Fixed Typo on "Armour Tactics" (#414)
* fix sw not registered

* Fix/no adsense (#412)

* Fixed Type on "Armour Tactics"
2018-10-29 09:14:32 +11:00
William Blythe
4e337c4ca1 add pax tooltip to outfitting too 2018-10-26 09:28:33 +11:00
William Blythe
5048b7e094 add pax tooltip 2018-10-26 09:05:33 +11:00
William Blythe
27fbc1ad66 remove file 2018-10-25 10:36:35 +11:00
27 changed files with 317 additions and 182 deletions

View File

@@ -29,6 +29,20 @@ services:
- "traefik.basic.port=80"
- "traefik.basic.protocol=http"
coriolis_dw2:
image: edcd/coriolis:dw2
restart: always
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
networks:
- web
labels:
- "traefik.docker.network=web"
- "traefik.enable=true"
- "traefik.basic.frontend.rule=Host:dw2.coriolis.io"
- "traefik.basic.port=80"
- "traefik.basic.protocol=http"
networks:
web:
external: true

View File

@@ -54,6 +54,8 @@ http {
location / {
try_files $uri $uri/ /index.html =404;
}
location /iframe.html {
try_files $uri $uri/ /iframe.html =404;
}
}
}

View File

@@ -127,6 +127,7 @@
"coriolis-data": "../coriolis-data",
"d3": "^5.7.0",
"detect-browser": "^3.0.1",
"ed-forge": "^1.3.0",
"fbemitter": "^2.1.1",
"lodash": "^4.17.11",
"lz-string": "^1.4.4",
@@ -135,6 +136,7 @@
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-extras": "^0.7.1",
"react-fuzzy": "^0.5.2",
"react-ga": "^2.5.3",
"react-number-editor": "Athanasius/react-number-editor.git#miggy",
"recharts": "^1.2.0",

View File

@@ -6,6 +6,7 @@ import { EventEmitter } from 'fbemitter';
import { getLanguage } from './i18n/Language';
import Persist from './stores/Persist';
import Announcement from './components/Announcement';
import Header from './components/Header';
import Tooltip from './components/Tooltip';
import ModalExport from './components/ModalExport';
@@ -14,7 +15,6 @@ import ModalImport from './components/ModalImport';
import ModalPermalink from './components/ModalPermalink';
import * as CompanionApiUtils from './utils/CompanionApiUtils';
import * as JournalUtils from './utils/JournalUtils';
import AboutPage from './pages/AboutPage';
import NotFoundPage from './pages/NotFoundPage';
import OutfittingPage from './pages/OutfittingPage';
@@ -349,30 +349,32 @@ export default class Coriolis extends React.Component {
// *Don't* register service worker file in, e.g., a scripts/ sub-directory!
// See https://github.com/slightlyoff/ServiceWorker/issues/468
const self = this;
register('/service-worker.js', {
ready (registration) {
console.log('Service worker is active.')
},
registered (registration) {
console.log('Service worker has been registered.')
},
cached (registration) {
console.log('Content has been cached for offline use.')
},
updatefound (registration) {
console.log('New content is downloading.')
},
updated (registration) {
self.setState({ appCacheUpdate: true });
console.log('New content is available; please refresh.')
},
offline () {
console.log('No internet connection found. App is running in offline mode.')
},
error (error) {
console.error('Error during service worker registration:', error)
}
});
if (process.env.NODE_ENV === 'production') {
register('/service-worker.js', {
ready (registration) {
console.log('Service worker is active.')
},
registered (registration) {
console.log('Service worker has been registered.')
},
cached (registration) {
console.log('Content has been cached for offline use.')
},
updatefound (registration) {
console.log('New content is downloading.')
},
updated (registration) {
self.setState({ appCacheUpdate: true });
console.log('New content is available; please refresh.')
},
offline () {
console.log('No internet connection found. App is running in offline mode.')
},
error (error) {
console.error('Error during service worker registration:', error)
}
});
}
}
window.onerror = this._onError.bind(this);
window.addEventListener('resize', () => this.emitter.emit('windowResize'));
@@ -393,9 +395,10 @@ export default class Coriolis extends React.Component {
return <div style={{ minHeight: '100%' }} onClick={this._closeMenu}
className={this.state.noTouch ? 'no-touch' : null}>
<Header announcements={this.state.announcements} appCacheUpdate={this.state.appCacheUpdate} currentMenu={currentMenu}/>
<Header announcements={this.state.announcements} appCacheUpdate={this.state.appCacheUpdate} currentMenu={currentMenu} />
<div className="announcement-container">{this.state.announcements.map(a => <Announcement text={a.message}/>)}</div>
{this.state.error ? this.state.error : this.state.page ? React.createElement(this.state.page, { currentMenu }) :
<NotFoundPage/>}
<NotFoundPage />}
{this.state.modal}
{this.state.tooltip}
<footer>

View File

@@ -1,5 +1,6 @@
import Persist from './stores/Persist';
import ReactGA from 'react-ga';
ReactGA.initialize('UA-55840909-18');
let standalone = undefined;

View File

@@ -1,34 +0,0 @@
import React, { Component, PropTypes } from 'react';
export default class Ad extends Component {
static propTypes = {
client: PropTypes.string,
slot: PropTypes.string,
format: PropTypes.string,
wrapperDivStyle: PropTypes.object
};
constructor(props) {
super(props);
}
// This code is ran when the component mounts
componentDidMount() {
}
// an outer div for styling purposes
// changed class to ClassName
// changed style from string to an object
render() {
return (
<div style={this.props.wrapperDivStyle}>
<ins
className="adsbygoogle"
style={{ display: 'block' }}
data-ad-client={this.props.client}
data-ad-slot={this.props.slot}
/>
</div>
);
}
}

View File

@@ -25,7 +25,7 @@ export default class Announcement extends React.Component {
* @return {React.Component} A href element
*/
render() {
return <p>{this.props.text}</p>;
return <div className="announcement" >{this.props.text}</div>;
}
}

View File

@@ -5,6 +5,7 @@ import TranslatedComponent from './TranslatedComponent';
import { stopCtxPropagation } from '../utils/UtilityFunctions';
import cn from 'classnames';
import { MountFixed, MountGimballed, MountTurret } from './SvgIcons';
import FuzzySearch from 'react-fuzzy';
const PRESS_THRESHOLD = 500; // mouse/touch down threshold
@@ -39,7 +40,7 @@ const GRPCAT = {
'mc': 'projectiles',
'axmc': 'experimental',
'fc': 'projectiles',
'rfl': 'experimental',
'rfl': 'experimental',
'pa': 'projectiles',
'rg': 'projectiles',
'mr': 'ordnance',
@@ -133,6 +134,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
constructor(props, context) {
super(props);
this._hideDiff = this._hideDiff.bind(this);
this._showSearch = this._showSearch.bind(this);
this.state = this._initState(props, context);
this.slotItems = [];// Array to hold <li> refs.
}
@@ -159,7 +161,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
onSelect(m);
}
);
let fuzzy = [];
if (modules instanceof Array) {
list = buildGroup(modules[0].grp, modules);
} else {
@@ -167,9 +169,11 @@ export default class AvailableModulesMenu extends TranslatedComponent {
// At present time slots with grouped options (Hardpoints and Internal) can be empty
if (m) {
let emptyId = 'empty';
if(this.firstSlotId == null) this.firstSlotId = emptyId;
if (this.firstSlotId == null) this.firstSlotId = emptyId;
let keyDown = this._keyDown.bind(this, onSelect);
list.push(<div className='empty-c upp' key={emptyId} data-id={emptyId} onClick={onSelect.bind(null, null)} onKeyDown={keyDown} tabIndex="0" ref={slotItem => this.slotItems[emptyId] = slotItem} >{translate('empty')}</div>);
list.push(<div className='empty-c upp' key={emptyId} data-id={emptyId} onClick={onSelect.bind(null, null)}
onKeyDown={keyDown} tabIndex="0"
ref={slotItem => this.slotItems[emptyId] = slotItem}>{translate('empty')}</div>);
}
// Need to regroup the modules by our own categorisation
@@ -197,7 +201,8 @@ export default class AvailableModulesMenu extends TranslatedComponent {
if (categories.length === 1) {
// Show category header instead of group header
if (m && grp == m.grp) {
list.push(<div ref={(elem) => this.groupElem = elem} key={category} className={'select-category upp'}>{translate(category)}</div>);
list.push(<div ref={(elem) => this.groupElem = elem} key={category}
className={'select-category upp'}>{translate(category)}</div>);
} else {
list.push(<div key={category} className={'select-category upp'}>{translate(category)}</div>);
}
@@ -208,19 +213,23 @@ export default class AvailableModulesMenu extends TranslatedComponent {
categoryHeader = true;
}
if (m && grp == m.grp) {
list.push(<div ref={(elem) => this.groupElem = elem} key={grp} className={'select-group cap'}>{translate(grp)}</div>);
list.push(<div ref={(elem) => this.groupElem = elem} key={grp}
className={'select-group cap'}>{translate(grp)}</div>);
} else {
list.push(<div key={grp} className={'select-group cap'}>{translate(grp)}</div>);
}
}
list.push(buildGroup(grp, modules[grp]));
for (const i of modules[grp]) {
fuzzy.push({ grp, m: i, name: `${i.class}${i.rating} ${translate(grp)} ${i.mount ? i.mount : ''}` });
}
}
}
}
}
}
let trackingFocus = false;
return { list, currentGroup, trackingFocus };
return { list, currentGroup, fuzzy, trackingFocus };
}
/**
@@ -242,9 +251,11 @@ export default class AvailableModulesMenu extends TranslatedComponent {
const sortedModules = modules.sort(this._moduleOrder);
// Calculate the number of items per class. Used so we don't have long lists with only a few items in each row
const tmp = sortedModules.map((v, i) => v['class']).reduce((count, cls) => { count[cls] = ++count[cls] || 1; return count; }, {});
const tmp = sortedModules.map((v, i) => v['class']).reduce((count, cls) => {
count[cls] = ++count[cls] || 1;
return count;
}, {});
const itemsPerClass = Math.max.apply(null, Object.keys(tmp).map(key => tmp[key]));
let itemsOnThisRow = 0;
@@ -297,22 +308,29 @@ export default class AvailableModulesMenu extends TranslatedComponent {
};
}
switch(m.mount) {
case 'F': mount = <MountFixed className={'lg'} />; break;
case 'G': mount = <MountGimballed className={'lg'}/>; break;
case 'T': mount = <MountTurret className={'lg'}/>; break;
switch (m.mount) {
case 'F':
mount = <MountFixed className={'lg'}/>;
break;
case 'G':
mount = <MountGimballed className={'lg'}/>;
break;
case 'T':
mount = <MountTurret className={'lg'}/>;
break;
}
if (m.name && m.name === prevName) {
// elems.push(<br key={'b' + m.grp + i} />);
itemsOnThisRow = 0;
}
if (itemsOnThisRow == 6 || i > 0 && sortedModules.length > 3 && itemsPerClass > 2 && m.class != prevClass && (m.rating != prevRating || m.mount)) {
elems.push(<br key={'b' + m.grp + i} />);
elems.push(<br key={'b' + m.grp + i}/>);
itemsOnThisRow = 0;
}
let tbIdx = (classes.indexOf('disabled') < 0) ? 0 : undefined;
elems.push(
<li key={m.id} data-id={m.id} className={classes} {...eventHandlers} tabIndex={tbIdx} ref={slotItem => this.slotItems[m.id] = slotItem}>
<li key={m.id} data-id={m.id} className={classes} {...eventHandlers} tabIndex={tbIdx}
ref={slotItem => this.slotItems[m.id] = slotItem}>
{mount}
{(mount ? ' ' : '') + m.class + m.rating + (m.missile ? '/' + m.missile : '') + (m.name ? ' ' + translate(m.name) : '')}
</li>
@@ -340,6 +358,36 @@ export default class AvailableModulesMenu extends TranslatedComponent {
}
}
/**
* Generate tooltip content for the difference between the
* mounted module and the hovered modules
*/
_showSearch() {
return (
<FuzzySearch
list={this.state.fuzzy}
keys={['grp', 'name']}
className={'input'}
width={'100%'}
style={{ padding: 0 }}
onSelect={e => this.props.onSelect.bind(null, e.m)()}
resultsTemplate={(props, state, styles, clickHandler) => {
return state.results.map((val, i) => {
return (
<div
key={i}
className={'lc'}
onClick={() => clickHandler(i)}
>
{val.name}
</div>
);
});
}}
/>
);
}
/**
* Mouse over diff handler
* @param {Function} showDiff diff tooltip callback
@@ -405,7 +453,7 @@ export default class AvailableModulesMenu extends TranslatedComponent {
* @param {Function} select Select module callback
* @param {SytheticEvent} event Event
*/
_keyUp(select,event) {
_keyUp(select, event) {
// nothing here yet
}
@@ -475,12 +523,13 @@ export default class AvailableModulesMenu extends TranslatedComponent {
this.slotItems[this.firstSlotId].focus();
}
}
/**
* Handle focus if the component updates
*
*/
componentWillUnmount() {
if(this.props.slotDiv) {
if (this.props.slotDiv) {
this.props.slotDiv.focus();
}
}
@@ -501,11 +550,12 @@ export default class AvailableModulesMenu extends TranslatedComponent {
render() {
return (
<div ref={node => this.node = node}
className={cn('select', this.props.className)}
onScroll={this._hideDiff}
onClick={(e) => e.stopPropagation() }
onContextMenu={stopCtxPropagation}
className={cn('select', this.props.className)}
onScroll={this._hideDiff}
onClick={(e) => e.stopPropagation()}
onContextMenu={stopCtxPropagation}
>
{this._showSearch()}
{this.state.list}
</div>
);

View File

@@ -2,12 +2,21 @@ import React from 'react';
import cn from 'classnames';
import Slot from './Slot';
import Persist from '../stores/Persist';
import { DamageAbsolute, DamageKinetic, DamageThermal, DamageExplosive, MountFixed, MountGimballed, MountTurret, ListModifications, Modified } from './SvgIcons';
import {
DamageAbsolute,
DamageKinetic,
DamageThermal,
DamageExplosive,
MountFixed,
MountGimballed,
MountTurret,
ListModifications,
Modified
} from './SvgIcons';
import { Modifications } from 'coriolis-data/dist';
import { stopCtxPropagation } from '../utils/UtilityFunctions';
import { blueprintTooltip } from '../utils/BlueprintFunctions';
/**
* Hardpoint / Utility Slot
*/
@@ -27,7 +36,7 @@ export default class HardpointSlot extends Slot {
* @return {string} Label
*/
_getMaxClassLabel(translate) {
return translate(['U','S','M','L','H'][this.props.maxClass]);
return translate(['U', 'S', 'M', 'L', 'H'][this.props.maxClass]);
}
/**
@@ -66,42 +75,73 @@ export default class HardpointSlot extends Slot {
return <div className={className} draggable='true' onDragStart={drag} onDragEnd={drop}>
<div className={'cb'}>
<div className={'l'}>
{m.mount && m.mount == 'F' ? <span onMouseOver={termtip.bind(null, 'fixed')} onMouseOut={tooltip.bind(null, null)}><MountFixed /></span> : ''}
{m.mount && m.mount == 'G' ? <span onMouseOver={termtip.bind(null, 'gimballed')} onMouseOut={tooltip.bind(null, null)}><MountGimballed /></span> : ''}
{m.mount && m.mount == 'T' ? <span onMouseOver={termtip.bind(null, 'turreted')} onMouseOut={tooltip.bind(null, null)}><MountTurret /></span> : ''}
{m.getDamageDist() && m.getDamageDist().K ? <span onMouseOver={termtip.bind(null, 'kinetic')} onMouseOut={tooltip.bind(null, null)}><DamageKinetic /></span> : ''}
{m.getDamageDist() && m.getDamageDist().T ? <span onMouseOver={termtip.bind(null, 'thermal')} onMouseOut={tooltip.bind(null, null)}><DamageThermal /></span> : ''}
{m.getDamageDist() && m.getDamageDist().E ? <span onMouseOver={termtip.bind(null, 'explosive')} onMouseOut={tooltip.bind(null, null)}><DamageExplosive /></span> : ''}
{m.getDamageDist() && m.getDamageDist().A ? <span onMouseOver={termtip.bind(null, 'absolute')} onMouseOut={tooltip.bind(null, null)}><DamageAbsolute /></span> : ''}
{classRating} {translate(m.name || m.grp)}{ m.mods && Object.keys(m.mods).length > 0 ? <span className='r' onMouseOver={termtip.bind(null, modTT)} onMouseOut={tooltip.bind(null, null)}><Modified /></span> : null }
{m.mount && m.mount == 'F' ? <span onMouseOver={termtip.bind(null, 'fixed')}
onMouseOut={tooltip.bind(null, null)}><MountFixed/></span> : ''}
{m.mount && m.mount == 'G' ? <span onMouseOver={termtip.bind(null, 'gimballed')}
onMouseOut={tooltip.bind(null, null)}><MountGimballed/></span> : ''}
{m.mount && m.mount == 'T' ? <span onMouseOver={termtip.bind(null, 'turreted')}
onMouseOut={tooltip.bind(null, null)}><MountTurret/></span> : ''}
{m.getDamageDist() && m.getDamageDist().K ? <span onMouseOver={termtip.bind(null, 'kinetic')}
onMouseOut={tooltip.bind(null, null)}><DamageKinetic/></span> : ''}
{m.getDamageDist() && m.getDamageDist().T ? <span onMouseOver={termtip.bind(null, 'thermal')}
onMouseOut={tooltip.bind(null, null)}><DamageThermal/></span> : ''}
{m.getDamageDist() && m.getDamageDist().E ? <span onMouseOver={termtip.bind(null, 'explosive')}
onMouseOut={tooltip.bind(null, null)}><DamageExplosive/></span> : ''}
{m.getDamageDist() && m.getDamageDist().A ? <span onMouseOver={termtip.bind(null, 'absolute')}
onMouseOut={tooltip.bind(null, null)}><DamageAbsolute/></span> : ''}
{classRating} {translate(m.name || m.grp)}{m.mods && Object.keys(m.mods).length > 0 ? <span className='r'
onMouseOver={termtip.bind(null, modTT)}
onMouseOut={tooltip.bind(null, null)}><Modified/></span> : null}
</div>
<div className={'r'}>{formats.round(m.getMass())}{u.T}</div>
</div>
<div className={'cb'}>
{ m.getDps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'dpssdps' : 'dps')} onMouseOut={tooltip.bind(null, null)}>{translate('DPS')}: {formats.round1(m.getDps())} { m.getClip() ? <span>({formats.round1(m.getSDps()) })</span> : null }</div> : null }
{ m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'epsseps' : 'eps')} onMouseOut={tooltip.bind(null, null)}>{translate('EPS')}: {formats.round1(m.getEps())}{u.MW} { m.getClip() ? <span>({formats.round1((m.getClip() * m.getEps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) }{u.MW})</span> : null }</div> : null }
{ m.getHps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'hpsshps' : 'hps')} onMouseOut={tooltip.bind(null, null)}>{translate('HPS')}: {formats.round1(m.getHps())} { m.getClip() ? <span>({formats.round1((m.getClip() * m.getHps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload())) })</span> : null }</div> : null }
{ m.getDps() && m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, 'dpe')} onMouseOut={tooltip.bind(null, null)}>{translate('DPE')}: {formats.f1(m.getDps() / m.getEps())}</div> : null }
{ m.getRoF() ? <div className={'l'} onMouseOver={termtip.bind(null, 'rof')} onMouseOut={tooltip.bind(null, null)}>{translate('ROF')}: {formats.f1(m.getRoF())}{u.ps}</div> : null }
{ m.getRange() ? <div className={'l'}>{translate('range', m.grp)} {formats.f1(m.getRange() / 1000)}{u.km}</div> : null }
{ m.getScanTime() ? <div className={'l'}>{translate('scantime')} {formats.f1(m.getScanTime())}{u.s}</div> : null }
{ m.getFalloff() ? <div className={'l'}>{translate('falloff')} {formats.round(m.getFalloff() / 1000)}{u.km}</div> : null }
{ 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('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 }
{ m.getJitter() ? <div className={'l'}>{translate('jitter')}: {formats.f2(m.getJitter())}°</div> : null }
{ showModuleResistances && m.getExplosiveResistance() ? <div className='l'>{translate('explres')}: {formats.pct(m.getExplosiveResistance())}</div> : null }
{ showModuleResistances && m.getKineticResistance() ? <div className='l'>{translate('kinres')}: {formats.pct(m.getKineticResistance())}</div> : null }
{ showModuleResistances && m.getThermalResistance() ? <div className='l'>{translate('thermres')}: {formats.pct(m.getThermalResistance())}</div> : null }
{ m.getIntegrity() ? <div className='l'>{translate('integrity')}: {formats.int(m.getIntegrity())}</div> : null }
{ m && validMods.length > 0 ? <div className='r' tabIndex="0" ref={ modButton => this.modButton = modButton }><button tabIndex="-1" onClick={this._toggleModifications.bind(this)} onContextMenu={stopCtxPropagation} onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}><ListModifications /></button></div> : null }
{m.getDps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'dpssdps' : 'dps')}
onMouseOut={tooltip.bind(null, null)}>{translate('DPS')}: {formats.round1(m.getDps())} {m.getClip() ?
<span>({formats.round1(m.getSDps())})</span> : null}</div> : null}
{m.getDamage() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getDamage() ? 'shotdmg' : 'shotdmg')}
onMouseOut={tooltip.bind(null, null)}>{translate('shotdmg')}: {formats.round1(m.getDamage())}</div> : null}
{m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'epsseps' : 'eps')}
onMouseOut={tooltip.bind(null, null)}>{translate('EPS')}: {formats.round1(m.getEps())}{u.MW} {m.getClip() ?
<span>({formats.round1((m.getClip() * m.getEps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload()))}{u.MW})</span> : null}</div> : null}
{m.getHps() ? <div className={'l'} onMouseOver={termtip.bind(null, m.getClip() ? 'hpsshps' : 'hps')}
onMouseOut={tooltip.bind(null, null)}>{translate('HPS')}: {formats.round1(m.getHps())} {m.getClip() ?
<span>({formats.round1((m.getClip() * m.getHps() / m.getRoF()) / ((m.getClip() / m.getRoF()) + m.getReload()))})</span> : null}</div> : null}
{m.getDps() && m.getEps() ? <div className={'l'} onMouseOver={termtip.bind(null, 'dpe')}
onMouseOut={tooltip.bind(null, null)}>{translate('DPE')}: {formats.f1(m.getDps() / m.getEps())}</div> : null}
{m.getRoF() ? <div className={'l'} onMouseOver={termtip.bind(null, 'rof')}
onMouseOut={tooltip.bind(null, null)}>{translate('ROF')}: {formats.f1(m.getRoF())}{u.ps}</div> : null}
{m.getRange() ? <div
className={'l'}>{translate('range', m.grp)} {formats.f1(m.getRange() / 1000)}{u.km}</div> : null}
{m.getScanTime() ? <div
className={'l'}>{translate('scantime')} {formats.f1(m.getScanTime())}{u.s}</div> : null}
{m.getFalloff() ? <div
className={'l'}>{translate('falloff')} {formats.round(m.getFalloff() / 1000)}{u.km}</div> : null}
{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('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}
{m.getJitter() ? <div className={'l'}>{translate('jitter')}: {formats.f2(m.getJitter())}°</div> : null}
{showModuleResistances && m.getExplosiveResistance() ? <div
className='l'>{translate('explres')}: {formats.pct(m.getExplosiveResistance())}</div> : null}
{showModuleResistances && m.getKineticResistance() ? <div
className='l'>{translate('kinres')}: {formats.pct(m.getKineticResistance())}</div> : null}
{showModuleResistances && m.getThermalResistance() ? <div
className='l'>{translate('thermres')}: {formats.pct(m.getThermalResistance())}</div> : null}
{m.getIntegrity() ? <div className='l'>{translate('integrity')}: {formats.int(m.getIntegrity())}</div> : null}
{m && validMods.length > 0 ? <div className='r' tabIndex="0" ref={modButton => this.modButton = modButton}>
<button tabIndex="-1" onClick={this._toggleModifications.bind(this)} onContextMenu={stopCtxPropagation}
onMouseOver={termtip.bind(null, 'modifications')} onMouseOut={tooltip.bind(null, null)}>
<ListModifications/></button>
</div> : null}
</div>
</div>;
} else {
return <div className={'empty'}>{translate('empty')}</div>;
return <div className={'empty'}>{translate('empty')}</div>;
}
}

View File

@@ -153,6 +153,15 @@ export default class HardpointSlotSection extends SlotSection {
<ul>
<li className='lc' tabIndex='0' onClick={_fill.bind(this, 'nl', 'F')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['nl-F'] = smRef}>{translate('nl')}</li>
</ul>
<div className='select-group cap'>{translate('ggc')}</div>
<ul>
<li className='lc' tabIndex='0' onClick={_fill.bind(this, 'ggc', 'F')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['ggc-F'] = smRef}>{translate('ggc')}</li>
</ul>
<div className='select-group cap'>{translate('rfl')}</div>
<ul>
<li className='c' tabIndex='0' onClick={_fill.bind(this, 'rfl', 'F')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['rfl-F'] = smRef}><MountFixed className='lg'/></li>
<li className='c' tabIndex='0' onClick={_fill.bind(this, 'rfl', 'T')} onKeyDown={this._keyDown} ref={smRef => this.sectionRefArr['rfl-T'] = smRef}><MountTurret className='lg'/></li>
</ul>
</div>;
}

View File

@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import TranslatedComponent from './TranslatedComponent';
import { orbisUpload } from '../utils/ShortenUrl';
import { orbisUpload, API_ORBIS_BASE_URL } from '../utils/ShortenUrl';
import Persist from '../stores/Persist';
/**
@@ -52,7 +52,7 @@ export default class ModalOrbis extends TranslatedComponent {
* @returns {Object} auth status
*/
getOrbisAuthStatus() {
return fetch('https://orbis.zone/api/checkauth', {
return fetch(`${API_ORBIS_BASE_URL}/api/checkauth`, {
credentials: 'include',
mode: 'cors'
})
@@ -104,7 +104,7 @@ export default class ModalOrbis extends TranslatedComponent {
<label>Orbis auth status: </label>
<input value={this.state.authenticatedStatus} readOnly size={25} onFocus={ (e) => e.target.select() }/>
<br/><br/>
<a className='button' href="https://orbis.zone/api/auth">Log in / signup to Orbis</a>
<a className='button' href={`${API_ORBIS_BASE_URL}/api/checkauth`}>Log in / signup to Orbis</a>
<br/><br/>
<h3 >{translate('Orbis link')}</h3>
<input value={this.state.orbisUrl} readOnly size={25} onFocus={ (e) => e.target.select() }/>

View File

@@ -52,6 +52,7 @@ export default class ShipSummaryTable extends TranslatedComponent {
const boostTooltip = canBoost ? 'TT_SUMMARY_BOOST' : canThrust ? 'TT_SUMMARY_BOOST_NONFUNCTIONAL' : 'TT_SUMMARY_SPEED_NONFUNCTIONAL';
const sgMetrics = Calc.shieldMetrics(ship, pips.sys);
const shipBoost = canBoost ? Calc.calcBoost(ship) : 'No Boost';
const restingHeat = Math.sqrt(((ship.standard[0].m.pgen * ship.standard[0].m.eff) / ship.heatCapacity) / 0.2);
const armourMetrics = Calc.armourMetrics(ship);
let shieldColour = 'blue';
if (shieldGenerator && shieldGenerator.m.grp === 'psg') {
@@ -78,13 +79,14 @@ export default class ShipSummaryTable extends TranslatedComponent {
<th rowSpan={2}>{translate('TTD')}</th>
{/* <th onMouseEnter={termtip.bind(null, 'heat per second')} onMouseLeave={hide} rowSpan={2}>{translate('HPS')}</th> */}
<th rowSpan={2}>{translate('cargo')}</th>
<th rowSpan={2}>{translate('pax')}</th>
<th rowSpan={2} onMouseEnter={termtip.bind(null, 'passenger capacity', { cap: 0 })} onMouseLeave={hide}>{translate('pax')}</th>
<th rowSpan={2}>{translate('fuel')}</th>
<th colSpan={3}>{translate('mass')}</th>
<th onMouseEnter={termtip.bind(null, 'hull hardness', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('hrd')}</th>
<th rowSpan={2}>{translate('crew')}</th>
<th onMouseEnter={termtip.bind(null, 'mass lock factor', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('MLF')}</th>
<th onMouseEnter={termtip.bind(null, 'TT_SUMMARY_BOOST_TIME', { cap: 0 })} onMouseLeave={hide} rowSpan={2}>{translate('boost time')}</th>
<th rowSpan={2}>{translate('resting heat (Beta)')}</th>
</tr>
<tr>
<th className='lft'>{translate('max')}</th>
@@ -122,6 +124,7 @@ export default class ShipSummaryTable extends TranslatedComponent {
<td>{ship.crew}</td>
<td>{ship.masslock}</td>
<td>{shipBoost !== 'No Boost' ? formats.time(shipBoost) : 'No Boost'}</td>
<td>{formats.pct(restingHeat)}</td>
</tr>
</tbody>
</table>

File diff suppressed because one or more lines are too long

View File

@@ -682,7 +682,32 @@ export default class OutfittingPage extends Page {
*/
_genOrbis() {
const data = {};
const {Ship, Module, Factory} = require('ed-forge');
const forgeShip = Factory.newShip(this.state.ship.id);
console.log(forgeShip);
const ship = this.state.ship;
const forgeOrder = {
0: 'bh',
1: 'pp',
2: 't',
3: 'fsd',
4: 'ls',
5: 'pd',
6: 's',
7: 'ft'
}
ship.standard.forEach((standard, idx) => {
console.log(standard)
const mod = Factory.newModule(standard.m.symbol, standard.m.class.toString(), standard.m.rating.toString());
console.log(mod);
const coreIdx = Object.entries(forgeOrder).findIndex(e => e[1] === standard.m.grp);
console.log(coreIdx)
console.log(forgeShip.getCoreModules())
forgeShip.getCoreModules()[coreIdx].setItem(standard.m.symbol);
if (standard.m.blueprint) {
console.log(standard.m.blueprint)
}
});
ship.coriolisId = ship.id;
data.coriolisShip = ship;
data.url = window.location.href;

View File

@@ -61,6 +61,7 @@ function shipSummary(shipId, shipData) {
id: shipId,
hpCount: 0,
intCount: 0,
beta: shipData.beta,
maxCargo: 0,
maxPassengers: 0,
hp: [0, 0, 0, 0, 0], // Utility, Small, Medium, Large, Huge
@@ -318,7 +319,7 @@ export default class ShipyardPage extends Page {
onMouseEnter={noTouch && this._highlightShip.bind(this, s.id)}
>
<td className="le">
<Link href={'/outfit/' + s.id}>{s.name}</Link>
<Link href={'/outfit/' + s.id}>{s.name} {s.beta === true ? '(Beta)' : null}</Link>
</td>
</tr>
);
@@ -451,10 +452,10 @@ export default class ShipyardPage extends Page {
<th className="sortable" onClick={sortShips('maxCargo')}>
{translate('cargo')}
</th>
<th className="sortable" onClick={sortShips('maxPassengers')}>
<th className="sortable" onClick={sortShips('maxPassengers')} onMouseEnter={termtip.bind(null, 'passenger capacity')}
onMouseLeave={hide}>
{translate('pax')}
</th>
<th className="lft" colSpan={7}>
{translate('core module classes')}
</th>

View File

@@ -41,6 +41,7 @@ export default class Module {
* @return {object} The value of the modification. If it is a numeric value then it is returned as an integer value scaled so that 1.23% == 123
*/
getModValue(name, raw) {
let baseVal = this[name];
let result = this.mods && this.mods[name] ? this.mods[name] : null;
if ((!raw) && this.blueprint && this.blueprint.special) {
@@ -51,13 +52,8 @@ export default class Module {
const modification = Modifications.modifications[name];
const multiplier = modification.type === 'percentage' ? 10000 : 100;
if (name === 'explres' || name === 'kinres' || name === 'thermres' || name === 'causres') {
// Resistance modifications in itself are additive, however their
// special effects are multiplicative. They affect the overall result
// by (special effect resistance) * (damage mult after modification),
// i. e. we need to apply the special effect as a multiplier to the
// overall result and then calculate the difference.
let baseMult = this[name] ? 1 - this[name] : 1;
result = (baseMult - (baseMult - result / multiplier) * (1 - modifierActions[name] / 100)) * multiplier;
// Apply resistance modding mechanisms to special effects subsequently
result = result + modifierActions[name] * (1 - (this[name] + result / multiplier)) * 100;
} else if (modification.method === 'additive') {
result = result + modifierActions[name] * 100;
} else if (modification.method === 'overwrite') {
@@ -75,15 +71,6 @@ export default class Module {
}
}
// Resistance modding for hull reinforcement packages has additional
// diminishing returns implemented. The mod value gets lowered by
// the amount of base resistance the hrp has.
if (!isNaN(result) && this.grp === 'hr' &&
(name === 'kinres' || name === 'thermres' || name === 'explres')) {
let baseRes = this[name];
result = result * (1 - baseRes);
}
// Sanitise the resultant value to 4dp equivalent
return isNaN(result) ? result : Math.round(result);
}
@@ -108,11 +95,11 @@ export default class Module {
// This special effect modifies the value being set, so we need to revert it prior to storing the value
const modification = Modifications.modifications[name];
if (name === 'explres' || name === 'kinres' || name === 'thermres' || name === 'causres') {
// Resistance modifications in itself are additive but their
// experimentals are applied multiplicatively therefor we must handle
// them differently here (cf. documentation in getModValue).
let baseMult = (this[name] ? 1 - this[name] : 1);
value = ((baseMult - value / 10000) / (1 - modifierActions[name] / 100) - baseMult) * -10000;
let res = (this[name] ? this[name] : 0) + value / 10000;
let experimental = modifierActions[name] / 100;
value = (experimental - res) / (experimental - 1) - this[name];
value *= 10000;
// value = ((baseMult - value / 10000) / (1 - modifierActions[name] / 100) - baseMult) * -10000;
} else if (modification.method === 'additive') {
value = value - modifierActions[name];
} else if (modification.method === 'overwrite') {
@@ -177,10 +164,6 @@ export default class Module {
baseValue = 0;
}
modValue = value - baseValue;
if (this.grp === 'hr' &&
(name === 'kinres' || name === 'thermres' || name === 'explres')) {
modValue = modValue / (1 - baseValue);
}
} else if (name === 'shieldboost' || name === 'hullboost') {
modValue = (1 + value) / (1 + baseValue) - 1;
} else { // multiplicative

View File

@@ -63,7 +63,10 @@ export function standard(type, id) {
if (!isNaN(type)) {
type = StandardArray[type];
}
let s = Modules.standard[type].find(e => e.id == id || (e.class == id.charAt(0) && e.rating == id.charAt(1)));
let s = Modules.standard[type].find(e => e.id === id);
if (!s) {
s = Modules.standard[type].find(e => (e.class == id.charAt(0) && e.rating == id.charAt(1)));
}
if (s) {
s = new Module({ template: s });
}

View File

@@ -505,6 +505,11 @@ export default class Ship {
if (isAbsolute) {
m.setPretty(name, value, sentfromui);
} else {
// Resistance modifiers scale with the base value
if (name == 'kinres' || name == 'thermres' || name == 'causres' || name == 'explres') {
let baseValue = m.get(name, false);
value = (1 - baseValue) * value;
}
m.setModValue(name, value, sentfromui);
}
@@ -1501,7 +1506,7 @@ export default class Ship {
} else {
buffer.writeInt32LE(slotMod.value, curpos);
}
// const modification = _.find(Modifications.modifications, function(o) { return o.id === slotMod.id; });
const modification = _.find(Modifications.modifications, function(o) { return o.id === slotMod.id; });
// console.log('ENCODE Slot ' + i + ': ' + modification.name + ' = ' + slotMod.value);
curpos += 4;
}
@@ -1514,6 +1519,7 @@ export default class Ship {
}
this.serialized.modifications = zlib.gzipSync(buffer).toString('base64');
// console.log(this.serialized.modifications)
} else {
this.serialized.modifications = null;
}

View File

@@ -30,6 +30,8 @@ export const SHIP_FD_NAME_TO_CORIOLIS_NAME = {
'Hauler': 'hauler',
'Independant_Trader': 'keelback',
'Krait_MkII': 'krait_mkii',
'Mamba': 'mamba',
'Krait_Light': 'krait_phantom',
'Orca': 'orca',
'Python': 'python',
'SideWinder': 'sidewinder',

View File

@@ -105,7 +105,7 @@ function orbisShorten(url, success, error) {
}
}
const API_ORBIS = 'https://orbis.zone/api/builds/add';
export const API_ORBIS_BASE_URL = process.env.NODE_ENV === 'development' ? 'http://localhost:3030' : 'https://orbis.zone';
/**
* Upload to Orbis
* @param {object} ship The URL to shorten
@@ -117,7 +117,7 @@ export function orbisUpload(ship, creds) {
if (window.navigator.onLine) {
try {
agent
.post(API_ORBIS)
.post(`${API_ORBIS_BASE_URL}/api/builds/add`)
.withCredentials()
.redirects(0)
.set('Content-Type', 'application/json')

9
src/iframe.html Normal file
View File

@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<script src="xdLocalStoragePostMessageApi.min.js"></script>
</head>
<body>
This is the magical iframe
</body>
</html>

View File

@@ -171,3 +171,16 @@ footer {
text-align: right;
}
}
.announcement-container {
display: flex;
align-items: center;
padding-top: 10px;
justify-content: center;
flex-flow: row wrap;
}
.announcement {
border: 1px @secondary solid;
padding: 10px;
}

View File

@@ -22,6 +22,15 @@ select {
}
}
.react-fuzzy-search > * {
padding: 0 !important;
color: @primary;
& > input {
border: 1px solid @primary !important;
color: @primary-bg;
}
}
.cmdr-select {
border: 1px solid @primary;
padding: 0.5em 0.5em;

View File

@@ -2,6 +2,15 @@ console.log('Hello from sw.js');
if (workbox) {
console.log('Yay! Workbox is loaded 🎉');
workbox.precaching.precacheAndRoute(self.__precacheManifest);
workbox.routing.registerNavigationRoute('/index.html');
workbox.routing.registerRoute(
new RegExp('/(.*?)'),
workbox.strategies.staleWhileRevalidate()
);
workbox.routing.registerRoute(
new RegExp('https://fonts.(?:googleapis|gstatic).com/(.*)'),
workbox.strategies.cacheFirst({
@@ -40,23 +49,3 @@ self.addEventListener('message', event => {
break;
}
});
const OFFLINE_URL = '/';
self.addEventListener('fetch', function(event) {
console.log('Handling fetch event for', event.request.url);
event.respondWith(
caches.match(event.request).then(function(response) {
if (response) {
return response;
}
return fetch(event.request)
.then(function(response) {
return response;
})
.catch(function(error) {
return caches.match(OFFLINE_URL);
});
})
);
});

View File

@@ -0,0 +1 @@
"use strict";window.XdUtils=window.XdUtils||function(){function a(a,b){var c,d=b||{};for(c in a)a.hasOwnProperty(c)&&(d[c]=a[c]);return d}return{extend:a}}(),function(){function a(a,b){var c=XdUtils.extend(b,l);c.id=a,parent.postMessage(JSON.stringify(c),"*")}function b(b,c){a(b,{key:c,value:localStorage.getItem(c)})}function c(b,c,d){localStorage.setItem(c,d),a(b,{success:localStorage.getItem(c)===d})}function d(b,c){localStorage.removeItem(c),a(b,{})}function e(b,c){a(b,{key:localStorage.key(c)})}function f(b){a(b,{size:JSON.stringify(localStorage).length})}function g(b){a(b,{length:localStorage.length})}function h(b){localStorage.clear(),a(b,{})}function i(a){var i;try{i=JSON.parse(a.data)}catch(a){}i&&i.namespace===k&&("set"===i.action?c(i.id,i.key,i.value):"get"===i.action?b(i.id,i.key):"remove"===i.action?d(i.id,i.key):"key"===i.action?e(i.id,i.key):"size"===i.action?f(i.id):"length"===i.action?g(i.id):"clear"===i.action&&h(i.id))}function j(){var a={namespace:k,id:"iframe-ready"};parent.postMessage(JSON.stringify(a),"*")}var k="cross-domain-local-message",l={namespace:k};window.addEventListener?window.addEventListener("message",i,!1):window.attachEvent("onmessage",i),j()}();

View File

@@ -22,9 +22,6 @@ module.exports = {
},
optimization: {
minimize: false,
splitChunks: {
chunks: 'all'
}
},
output: {
path: path.join(__dirname, 'build'),
@@ -32,7 +29,7 @@ module.exports = {
publicPath: '/'
},
plugins: [
new CopyWebpackPlugin(['src/.htaccess']),
new CopyWebpackPlugin(['src/.htaccess', 'src/iframe.html', 'src/xdLocalStoragePostMessageApi.min.js']),
// new webpack.optimize.CommonsChunkPlugin({
// name: 'lib',
// filename: 'lib.js'

View File

@@ -4,7 +4,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { InjectManifest } = require('workbox-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { BugsnagSourceMapUploaderPlugin } = require('webpack-bugsnag-plugins');
const { BugsnagSourceMapUploaderPlugin, BugsnagBuildReporterPlugin } = require('webpack-bugsnag-plugins');
const pkgJson = require('./package');
const buildDate = new Date();
@@ -30,7 +30,7 @@ module.exports = {
}
},
plugins: [
new CopyWebpackPlugin(['src/.htaccess', { from: 'src/schemas', to: 'schemas' }, {from: 'src/images/logo/*', flatten: true, to: ''}]),
new CopyWebpackPlugin(['src/.htaccess', { from: 'src/schemas', to: 'schemas' }, {from: 'src/images/logo/*', flatten: true, to: ''}, 'src/iframe.html', 'src/xdLocalStoragePostMessageApi.min.js']),
// new webpack.optimize.CommonsChunkPlugin({
// name: 'lib',
// filename: 'lib.[chunkhash:6].js'
@@ -48,10 +48,15 @@ module.exports = {
disable: false,
allChunks: true
}),
// new BugsnagSourceMapUploaderPlugin({
// apiKey: 'ba9fae819372850fb660755341fa6ef5',
// appVersion: `${pkgJson.version}-${buildDate.toISOString()}`
// }),
new BugsnagBuildReporterPlugin({
apiKey: 'ba9fae819372850fb660755341fa6ef5',
appVersion: `${pkgJson.version}-${buildDate.toISOString()}`
}, { /* opts */ }),
new BugsnagSourceMapUploaderPlugin({
apiKey: 'ba9fae819372850fb660755341fa6ef5',
overwrite: true,
appVersion: `${pkgJson.version}-${buildDate.toISOString()}`
}),
new InjectManifest({
swSrc: './src/sw.js',
importWorkboxFrom: 'cdn',