Skip to content

Instantly share code, notes, and snippets.

@kefavn
Last active July 26, 2022 16:59
Show Gist options
  • Save kefavn/967ba7e2cd2aebecf2fb55ead7b9a02b to your computer and use it in GitHub Desktop.
Save kefavn/967ba7e2cd2aebecf2fb55ead7b9a02b to your computer and use it in GitHub Desktop.
DM stuff
import Ember from 'ember';
const { computed } = Ember;
export default Ember.Component.extend({
displayInternals: computed('model.totalPermutations', 'model.totalEssence', 'model.availableEssence', 'model.totalAttack', 'model.totalMana', 'model.totalMagic', 'model.noxinDamage', 'model.necroDamage', 'model.maxFloorReachable', 'model.noxinMaxFloor', 'model.necroMaxFloor', function() {
return {
totalEssence: this.get('model.totalEssence'),
totalAttack: this.get('model.totalAttack'),
totalMana: this.get('model.totalMana'),
totalMagic: this.get('model.totalMagic'),
totalPermutations: this.get('model.totalPermutations'),
noxinDamage: this.get('model.noxinDamage'),
necroDamage: this.get('model.necroDamage'),
noxinMaxFloor: this.get('model.noxinMaxFloor'),
necroMaxFloor: this.get('model.necroMaxFloor'),
'Max Floor Reachable': this.get('model.maxFloorReachable')
};
}),
});
import Ember from 'ember';
const { computed } = Ember;
export default Ember.Component.extend({
actions: {
changeCurrency(currency, value) {
const totalEssence = this.get('model.totalEssence');
if ( value > 10000 && value > totalEssence ) {
value = totalEssence;
}
currency.set('value', value);
currency.notifyPropertyChange('value');
this.get('model.relics').setEach('availableEssence', value);
}
}
});
import Ember from 'ember';
export default Ember.Component.extend({
actions: {
inputDidChange(value) {
return this.get('didChange')(parseInt(value) || 0);
}
}
});
import Ember from 'ember';
const { isPresent } = Ember;
function filterRelicsByEssence(relics, availableEssence) {
return relics.filter((relic) => {
return relic.get('nextEssence') < availableEssence;
});
};
export default Ember.Component.extend({
actions: {
calculateOptimalLevel() {
const relics = this.get('model.relics');
let availableEssence = this.get('model.currencies.firstObject.value');
let maxDamagePerEssence = 0;
let maxDamagePerEssenceRelic = '';
let maxDamagePerEssenceEssence = 0;
let possibleRelics = filterRelicsByEssence(relics, availableEssence);
while(isPresent(possibleRelics)) {
possibleRelics.forEach((relic) => {
const thisEssence = relic.get('nextEssence');
const originalMaxFloorReachable = this.get('model.maxFloorReachable');
relic.incrementProperty('value');
const maxFloorReachable = this.get('model.maxFloorReachable') - originalMaxFloorReachable;
const ratio = maxFloorReachable / thisEssence;
if (ratio > maxDamagePerEssence) {
maxDamagePerEssence = ratio;
maxDamagePerEssenceRelic = relic;
maxDamagePerEssenceEssence = thisEssence;
}
relic.decrementProperty('value')
});
availableEssence = availableEssence - maxDamagePerEssenceEssence;
maxDamagePerEssenceRelic.incrementProperty('value');
maxDamagePerEssence = 0;
possibleRelics = filterRelicsByEssence(relics, availableEssence);
};
this.set('model.currencies.firstObject.value', availableEssence);
}
}
});
import Ember from 'ember';
const { computed } = Ember;
export default Ember.Controller.extend({
appName: 'DM Calc',
});
import Model from "ember-data/model";
import attr from "ember-data/attr";
import { belongsTo, hasMany } from "ember-data/relationships";
import EmberCPM from 'ember-cpm';
const { computed } = Ember;
const { Macros: { product, sum } } = EmberCPM;
import { floorForNoxinDamage, floorForNecroDamage } from 'app/utils/floor-hp';
export default Model.extend({
relics: hasMany('relic'),
initialStats: hasMany('stat'),
currencies: hasMany('currency'),
relicsMana: computed('relics', 'totalMana', function() {
const relics = this.get('relics');
const mapped = relics.mapBy('totalMana');
console.log(mapped);
return mapped;
}),
relicsTotalMana: computed.sum('relicsMana'),
relicsAttack: computed.mapBy('relics', 'totalAttack'),
relicsTotalAttack: computed.sum('relicsAttack'),
relicsMagic: computed.mapBy('relics', 'totalMagic'),
relicsTotalMagic: computed.sum('relicsMagic'),
relicsEssence: computed.mapBy('relics', 'essenceRequired'),
totalEssence: computed.sum('relicsEssence'),
relicsPermutations: computed.mapBy('relics', 'improvementsLength'),
totalPermutations: computed.sum('relicsPermutations'),
statsTotalMana: computed.filterBy('initialStats', 'mana', 1),
statsTotalAttack: computed.filterBy('initialStats', 'attack', 1),
statsTotalMagic: computed.filterBy('initialStats', 'magic', 1),
totalMana: sum('relicsTotalMana', 'statsTotalMana.firstObject.value'),
totalAttack: sum('relicsTotalAttack', 'statsTotalAttack.firstObject.value'),
totalMagic: sum('relicsTotalMagic', 'statsTotalMagic.firstObject.value'),
noxinDamage: computed('totalAttack', 'totalMagic', function() {
return Math.floor(this.get('totalAttack') * 0.6 * (1 + this.get('totalMagic')/100))
}),
necroDamage: computed('totalAttack', 'totalMagic', 'totalMana', function() {
return Math.floor((this.get('totalMana') * 1.5 + this.get('totalAttack') * 0.9) * (1 + this.get('totalMagic')/100));
}),
noxinMaxFloor: computed('noxinDamage', function() {
return floorForNoxinDamage(this.get('noxinDamage'));
}),
necroMaxFloor: computed('necroDamage', function() {
return floorForNecroDamage(this.get('necroDamage'));
}),
maxFloorReachable: computed('noxinMaxFloor', 'necroMaxFloor', function() {
return Math.min(this.get('noxinMaxFloor'), this.get('necroMaxFloor'));
}),
stateString: computed('[email protected]', '[email protected]', '[email protected]', function() {
const stateString = '';
return stateString;
}),
});
import Model from "ember-data/model";
import attr from "ember-data/attr";
import { belongsTo, hasMany } from "ember-data/relationships";
export default Model.extend({
name: attr('string'),
description: attr('string'),
value: attr('number', { defaultValue: 1 }),
});
import StatModel from "app/models/stat";
import attr from "ember-data/attr";
import { belongsTo, hasMany } from "ember-data/relationships";
import { totalEssenceForRelicLevel, getCostArray, essenceForNextLevel } from 'app/utils/total-essence';
import Ember from 'ember';
const { computed } = Ember;
export default StatModel.extend({
availableEssence: attr('number', {defaultValue: 0}),
level: computed.alias('value'),
essenceRequired: computed('level', function() {
return totalEssenceForRelicLevel(this.get('level'));
}),
nextEssence: computed('level', function() {
return essenceForNextLevel(this.get('level'));
}),
benefit: computed('mana', 'magic', 'attack', function() {
const mana = this.get('mana');
const attack = this.get('attack');
const magic = this.get('magic');
return {
mana,
attack,
magic
}
}),
improvements: computed('level', 'availableEssence', function() {
return getCostArray(this.get('level'), this.get('availableEssence'), this.get('benefit'));
}),
improvementsLength: 1,
});
import Model from "ember-data/model";
import attr from "ember-data/attr";
import { belongsTo, hasMany } from "ember-data/relationships";
import EmberCPM from 'ember-cpm';
const { Macros: { product } } = EmberCPM;
export default Model.extend({
name: attr('string'),
description: attr('string'),
value: attr('number', { defaultValue: 1 }),
mana: attr('number', { defaultValue: 0 }),
attack: attr('number', { defaultValue: 0 }),
magic: attr('number', { defaultValue: 0}),
totalMana: product('mana', 'value'),
totalAttack: product('attack', 'value'),
totalMagic: product('magic', 'value'),
});
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.generateAccount();
},
generateAccount() {
const account = this.store.createRecord('account');
account.get('relics').pushObjects(this.generateRelicModels());
account.get('initialStats').pushObjects(this.generateInitialStatsModels());
account.get('currencies').pushObjects(this.generateCurrencyModels());
return account;
},
generateRelicModels() {
return [
this.store.createRecord('relic', {
name: 'manaRelic',
description: 'Mana (+3 MP)',
value: 375,
mana: 3
}),
this.store.createRecord('relic', {
name: 'magicRelic',
description: 'Magic (+3%)',
value: 375,
magic: 3
}),
this.store.createRecord('relic', {
name: 'mageRelic',
description: 'DM (+2 MP, +2 ATK)',
value: 375,
mana: 2,
attack: 2
}),
this.store.createRecord('relic', {
name: 'attackRelic',
description: 'Attack (+2 ATK)',
value: 375,
attack: 2
}),
]
},
generateInitialStatsModels() {
return [
this.store.createRecord('stat', {
name: 'initialMana',
description: 'Mana (MP)',
value: 215,
mana: 1
}),
this.store.createRecord('stat', {
name: 'initialAttack',
description: 'ATK',
value: 128,
attack: 1
}),
this.store.createRecord('stat', {
name: 'initialMagic',
description: 'Magic%',
value: 163,
magic: 1
})
]
},
generateCurrencyModels() {
return [
this.store.createRecord('currency', {
name: 'availableEssence',
description: 'Essence',
value: 50000
})
]
},
});
<div class="container">
<H1>DM Calc</h1>
<div class="row">
<div class="one-half column">
{{form-component
model=model
}}
</div>
<div class="one-half column">
{{calculation-component
model=model
}}
{{result-component
model=model
}}
</div>
</div>
<div class="row" style="display: none">
<h5>Browser Cache</h5>
<button class="button-primary">Save</button>
<button class="button-primary">Load</button>
<button class="button">Clear</button>
</div>
</div>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<div style="background: #F1F1F1; display: block; padding: 1em; border-radius: 4px;">
{{#each-in displayInternals as |key value|}}
<div class="row">
{{key}}: {{value}}
</div>
{{/each-in}}
</div>
<form>
<h5>Current Relic Levels</h5>
{{#each model.relics as |relic|}}
<div class="row">
<div class="six columns">{{relic.description}}</div>
<div class="two columns">{{number-input readonlyValue=(readonly relic.value) didChange=(action (mut relic.value))}}</div>
</div>
{{/each}}
<h5>Initial Stats (Equipment + Class)</h5>
{{#each model.initialStats as |initialStat|}}
<div class="row">
<div class="six columns">{{initialStat.description}}</div>
<div class="two columns">{{number-input readonlyValue=(readonly initialStat.value) didChange=(action (mut initialStat.value))}}</div>
</div>
{{/each}}
<h5>Currency</h5>
{{#each model.currencies as |currency|}}
<div class="row">
<div class="six columns">{{currency.description}} to Spend</div>
<div class="two columns">{{number-input readonlyValue=(readonly currency.value) didChange=(action 'changeCurrency' currency)}}</div>
</div>
{{/each}}
</form>
<input
type="number"
value={{readonlyValue}}
id={{concat elementId '-input'}}
oninput={{action 'inputDidChange' value="target.value"}}
required=true
>
<div style="margin-top: 2em;">
<button class="button-primary" {{action 'calculateOptimalLevel'}}>Calculate Optimal Relic Level</button>
</div>
{
"version": "0.11.0",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.10.2",
"ember-data": "2.11.0",
"ember-template-compiler": "2.10.2",
"ember-testing": "2.10.2",
"skeleton-css": "https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css"
},
"addons": {
"ember-cpm": "3.0.0"
}
}
const maxBase = 550; // just guessing here
function floorFor10BossDamage(damage) {
return 1 * Math.floor((damage - maxBase) / 4, 0);
};
function floorFor100BossDamage(damage) {
return 1 * Math.floor((damage - 430 - maxBase) / 20, 0);
};
export function floorForNoxinDamage(damage) {
//calculated for two shotting the triple mini-bosses
return Math.floor(floorFor10BossDamage(damage)*2, 1);
};
export function floorForNecroDamage(damage) {
//three shot 100 floor boss
return Math.floor(floorFor100BossDamage(damage)*3, 1);
};
const totalEssenceCache = {0: 0, 1:0};
export function totalEssenceForRelicLevel(level) {
if (level <= 0) {
return 0;
}
if (totalEssenceCache[level]) {
return totalEssenceCache[level];
}
let lastLevelWithCache = level;
while(!totalEssenceCache[lastLevelWithCache] && lastLevelWithCache > 1) {
lastLevelWithCache = lastLevelWithCache - 1;
}
while(lastLevelWithCache <= level) {
const increment = essenceForLevel(lastLevelWithCache);
totalEssenceCache[lastLevelWithCache] = increment + totalEssenceCache[lastLevelWithCache - 1]
lastLevelWithCache = lastLevelWithCache + 1;
}
return totalEssenceCache[level];
};
export function essenceForLevel(level) {
const val = Math.round(Math.pow(level - 1 , 1.3));
return isNaN(val) ? 0 : val;
};
export function essenceForNextLevel(level) {
return essenceForLevel(level + 1);
}
export function getCostArray(level, essence, benefit) {
let totalCost = 0;
const totalBenefits = [];
const costs = [];
while (essenceForNextLevel(level) < essence) {
const increment = essenceForNextLevel(level);
totalCost = totalCost + increment;
essence = essence - increment;
totalBenefits.pushObject(benefit);
costs.pushObject({
level,
cost: totalCost,
benefits: totalBenefits
});
}
return costs;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment