add treasure system
This commit is contained in:
325
src/services/treasureData.ts
Normal file
325
src/services/treasureData.ts
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
import { IndividualTreasureTable, HoardTresureTable } from './treasureService';
|
||||||
|
|
||||||
|
let individualTreasureData: IndividualTreasureTable[] = [
|
||||||
|
{
|
||||||
|
name: 'Individual Treasure: Challence 0-4',
|
||||||
|
notes: '',
|
||||||
|
tags: ['Individual Treasure', 'CR0','CR1','CR2', 'CR3', 'CR4', 'Challenge 0-4', 'treasure'],
|
||||||
|
dice: [100],
|
||||||
|
possibleCoinRewards: [
|
||||||
|
{
|
||||||
|
keys: [1,30],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'CP',
|
||||||
|
rollCount: 5,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 1,
|
||||||
|
avg: 17
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [31,60],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'SP',
|
||||||
|
rollCount: 4,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 1,
|
||||||
|
avg: 14
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [61,70],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'EP',
|
||||||
|
rollCount: 3,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 1,
|
||||||
|
avg: 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [71,95],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 3,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 1,
|
||||||
|
avg: 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [96,100],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'PP',
|
||||||
|
rollCount: 1,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 1,
|
||||||
|
avg: 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Individual Treasure: Challence 5-10',
|
||||||
|
notes: '',
|
||||||
|
tags: ['Individual Treasure', 'CR5','CR6','CR7', 'CR8', 'CR9', 'CR10', 'Challenge 5-10', 'treasure'],
|
||||||
|
dice: [100],
|
||||||
|
possibleCoinRewards: [
|
||||||
|
{
|
||||||
|
keys: [1,30],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'CP',
|
||||||
|
rollCount: 4,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 100,
|
||||||
|
avg: 1400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'EP',
|
||||||
|
rollCount: 1,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 10,
|
||||||
|
avg: 35
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [31,60],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'SP',
|
||||||
|
rollCount: 6,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 10,
|
||||||
|
avg: 210
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 2,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 10,
|
||||||
|
avg: 70
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [61,70],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'EP',
|
||||||
|
rollCount: 3,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 10,
|
||||||
|
avg: 105
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 2,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 10,
|
||||||
|
avg: 70
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [71,95],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 4,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 10,
|
||||||
|
avg: 140
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [96,100],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 2,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 10,
|
||||||
|
avg: 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'PP',
|
||||||
|
rollCount: 2,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 1,
|
||||||
|
avg: 10
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Individual Treasure: Challence 11-16',
|
||||||
|
notes: '',
|
||||||
|
tags: ['Individual Treasure', 'CR11', 'CR12', 'CR13', 'CR14', 'CR15', 'CR16', 'Challenge 11-16', 'treasure'],
|
||||||
|
dice: [100],
|
||||||
|
possibleCoinRewards: [
|
||||||
|
{
|
||||||
|
keys: [1,20],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'SP',
|
||||||
|
rollCount: 4,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 100,
|
||||||
|
avg: 1400
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 1,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 100,
|
||||||
|
avg: 350
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [21,35],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'EP',
|
||||||
|
rollCount: 1,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 100,
|
||||||
|
avg: 350
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 1,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 100,
|
||||||
|
avg: 350
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [36,75],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 2,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 100,
|
||||||
|
avg: 700
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'PP',
|
||||||
|
rollCount: 1,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 10,
|
||||||
|
avg: 35
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [76,100],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 2,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 100,
|
||||||
|
avg: 700
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'EP',
|
||||||
|
rollCount: 2,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 10,
|
||||||
|
avg: 70
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Individual Treasure: Challence 17+',
|
||||||
|
notes: '',
|
||||||
|
tags: ['Individual Treasure', 'CR17', 'CR18', 'CR19', 'CR20', 'CR21', 'CR22', 'Challenge 17+', 'treasure'],
|
||||||
|
dice: [100],
|
||||||
|
possibleCoinRewards: [
|
||||||
|
{
|
||||||
|
keys: [1,15],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'EP',
|
||||||
|
rollCount: 2,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 1000,
|
||||||
|
avg: 7000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 8,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 100,
|
||||||
|
avg: 2800
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [16,55],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 1,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 1000,
|
||||||
|
avg: 3500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'PP',
|
||||||
|
rollCount: 1,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 100,
|
||||||
|
avg: 350
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: [56,100],
|
||||||
|
coinCalc: [
|
||||||
|
{
|
||||||
|
type: 'GP',
|
||||||
|
rollCount: 1,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 1000,
|
||||||
|
avg: 3500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'PP',
|
||||||
|
rollCount: 2,
|
||||||
|
diceType: 6,
|
||||||
|
multiplier: 100,
|
||||||
|
avg: 700
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let hoardTreasureData: HoardTresureTable[] = [
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
export {
|
||||||
|
individualTreasureData
|
||||||
|
}
|
194
src/services/treasureService.ts
Normal file
194
src/services/treasureService.ts
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
import { d } from './dice';
|
||||||
|
import { individualTreasureData } from './treasureData';
|
||||||
|
|
||||||
|
class TreasureService {
|
||||||
|
private individualRewardsTables: RandomIndividualTreasureTable[] = [];
|
||||||
|
private tableByName: {[tableName: string]: RandomIndividualTreasureTable} = {};
|
||||||
|
private tablesByTags: {[tagName: string]: RandomIndividualTreasureTable[]} = {};
|
||||||
|
private tags: Set<string> = new Set();
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
console.time('TreasureServiceStartup');
|
||||||
|
for (let i in individualTreasureData) {
|
||||||
|
let table = individualTreasureData[i];
|
||||||
|
let randomTable: RandomIndividualTreasureTable = new RandomIndividualTreasureTable(table);
|
||||||
|
this.individualRewardsTables.push(randomTable);
|
||||||
|
this.tableByName[table.name] = randomTable;
|
||||||
|
if (table.tags) {
|
||||||
|
for (let j in table.tags) {
|
||||||
|
let tag: string = table.tags[j];
|
||||||
|
if (!this.tablesByTags[tag]) {
|
||||||
|
this.tablesByTags[tag] = [];
|
||||||
|
}
|
||||||
|
this.tags.add(tag);
|
||||||
|
this.tablesByTags[tag].push(randomTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.timeEnd('TreasureServiceStartup');
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTablesWithTag(tag: string) {
|
||||||
|
return this.tablesByTags[tag];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTable(name: string) {
|
||||||
|
return this.tableByName[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTags() {
|
||||||
|
return this.tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public searchForTable(search: string) {
|
||||||
|
let answer = this.individualRewardsTables.filter((table: RandomIndividualTreasureTable) => {
|
||||||
|
return table.name.toLowerCase().indexOf(search.toLowerCase()) !== -1 || table.getTags().join(' ').toLowerCase().indexOf(search.toLowerCase()) !== -1;
|
||||||
|
}).map((table: RandomIndividualTreasureTable) => {
|
||||||
|
let score = search.length / table.name.length;
|
||||||
|
return {
|
||||||
|
table: table,
|
||||||
|
score: score
|
||||||
|
};
|
||||||
|
}).sort((a: {table: RandomIndividualTreasureTable, score: number}, b: {table: RandomIndividualTreasureTable, score: number}) => {
|
||||||
|
return a.score - b.score;
|
||||||
|
}).map((tableScore: {table: RandomIndividualTreasureTable, score: number}) => {
|
||||||
|
return tableScore.table;
|
||||||
|
});
|
||||||
|
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RandomIndividualTreasureTable {
|
||||||
|
public name: string;
|
||||||
|
public dice: number[];
|
||||||
|
private indexedResults: CoinRewards[] = [];
|
||||||
|
private config: IndividualTreasureTable;
|
||||||
|
|
||||||
|
constructor(config: IndividualTreasureTable) {
|
||||||
|
this.name = config.name;
|
||||||
|
this.dice = config.dice;
|
||||||
|
this.constructIndex(config.possibleCoinRewards);
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public roll(input?: number) {
|
||||||
|
let testRoll: number = this.getRoll();
|
||||||
|
if (!this.isValidInput(testRoll)) {
|
||||||
|
console.log(testRoll);
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
if (!input || !this.isValidInput(input)) {
|
||||||
|
input = this.getRoll();
|
||||||
|
}
|
||||||
|
return this.indexedResults[input - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPossibleRewards() {
|
||||||
|
return this.config.possibleCoinRewards;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTags() {
|
||||||
|
return this.config.tags || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public getNotes() {
|
||||||
|
return this.config.notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getRoll(): number {
|
||||||
|
let answer: number = 0;
|
||||||
|
for (let i in this.dice) {
|
||||||
|
answer = answer + d(this.dice[i]);
|
||||||
|
}
|
||||||
|
return answer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private isValidInput(input: number) {
|
||||||
|
return typeof this.indexedResults[input - 1] !== 'undefined';
|
||||||
|
}
|
||||||
|
|
||||||
|
private constructIndex(coinRewards: CoinRewards[]) {
|
||||||
|
for (let resultIndex in coinRewards) {
|
||||||
|
let keys: number[] = coinRewards[resultIndex].keys;
|
||||||
|
for (let r = Math.min(...keys); r <= Math.max(...keys); r++) {
|
||||||
|
this.indexedResults.push(coinRewards[resultIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChallengeRating = '0-4' | '5-10' | '11-16' | '17+';
|
||||||
|
|
||||||
|
interface CoinResult {
|
||||||
|
type: 'CP' | 'SP' | 'EP' | 'GP' | 'PP';
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CoinCalc {
|
||||||
|
type: 'CP' | 'SP' | 'EP' | 'GP' | 'PP';
|
||||||
|
rollCount: number;
|
||||||
|
diceType: number;
|
||||||
|
multiplier: number;
|
||||||
|
avg: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CoinRewards {
|
||||||
|
keys: number[];
|
||||||
|
coinCalc: CoinCalc[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GemArtCalc {
|
||||||
|
tableName: string;
|
||||||
|
rollCount: number;
|
||||||
|
diceType: number;
|
||||||
|
avg: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GemArtResult {
|
||||||
|
tableName: string;
|
||||||
|
amount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MagicItemCalc {
|
||||||
|
tableName: string;
|
||||||
|
rollCount: number;
|
||||||
|
diceType: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MagicItemResult {
|
||||||
|
tableName: string;
|
||||||
|
numberOfRoles: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OtherRewards {
|
||||||
|
keys: number[];
|
||||||
|
gemArt: GemArtCalc;
|
||||||
|
magicItem: MagicItemCalc[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IndividualTreasureTable {
|
||||||
|
name: string;
|
||||||
|
notes?: string;
|
||||||
|
tags?: string[];
|
||||||
|
dice: number[];
|
||||||
|
possibleCoinRewards: CoinRewards[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HoardTresureTable {
|
||||||
|
name: string;
|
||||||
|
notes?: string;
|
||||||
|
tags?: string[];
|
||||||
|
dice: number[];
|
||||||
|
coinRewards: CoinRewards;
|
||||||
|
possibleRewards: OtherRewards[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const treasureService: TreasureService = new TreasureService();
|
||||||
|
|
||||||
|
export {
|
||||||
|
HoardTresureTable,
|
||||||
|
IndividualTreasureTable,
|
||||||
|
RandomIndividualTreasureTable,
|
||||||
|
treasureService,
|
||||||
|
}
|
Reference in New Issue
Block a user