diff --git a/package.json b/package.json
index f0302f9348..ef29b3874f 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"homepage": "https://frzyc.github.io/genshin-optimizer/",
"name": "genshin-optimizer",
- "version": "2.3.2",
+ "version": "2.4.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.32",
diff --git a/src/App.js b/src/App.js
index ab58a9118b..7f54518ae5 100644
--- a/src/App.js
+++ b/src/App.js
@@ -26,6 +26,8 @@ function App() {
Genshin Optimizer
+
+
+
diff --git a/src/Artifact/Artifact.js b/src/Artifact/Artifact.js
index 78db70a38a..3b8a05d5d0 100644
--- a/src/Artifact/Artifact.js
+++ b/src/Artifact/Artifact.js
@@ -4,7 +4,8 @@ import CharacterDatabase from '../Character/CharacterDatabase';
import SlotIcon from '../Components/SlotIcon';
import { ArtifactMainSlotKeys, ArtifactMainStatsData, ArtifactSetsData, ArtifactSlotsData, ArtifactStarsData, ArtifactSubStatsData } from '../Data/ArtifactData';
import Stat from '../Stat';
-import { clampPercent, closeEnoughFloat, closeEnoughInt, deepClone } from '../Util';
+import ArtifactConditionals from '../Util/ArtifactConditionals';
+import { clamp, clampPercent, closeEnoughFloat, closeEnoughInt, deepClone } from '../Util/Util';
import ArtifactBase from './ArtifactBase';
import ArtifactDatabase from './ArtifactDatabase';
@@ -145,36 +146,96 @@ export default class Artifact {
}
static setToSlots = ArtifactBase.setToSlots;
+
+ static getArtifactSets = (setKey, defVal = null) =>
+ ArtifactSetsData?.[setKey]?.sets || defVal
+ static getArtifactSetNumStats = (setKey, setNumKey, defVal = null) =>
+ this.getArtifactSets(setKey)?.[setNumKey]?.stats || defVal
+
+ static getArtifactConditionalStats = (setKey, setNumKey, conditionalNum, defVal = null) => {
+ if (!conditionalNum) return defVal
+ let conditional = ArtifactSetsData[setKey].sets[setNumKey].conditional
+ if (!conditional) return defVal
+ if (Array.isArray(conditional)) {
+ //multiconditional
+ let selectedConditionalNum = conditionalNum
+ let selectedConditional = null
+ for (const curConditional of conditional) {
+ if (selectedConditionalNum > curConditional.maxStack) selectedConditionalNum -= curConditional.maxStack
+ else {
+ selectedConditional = curConditional;
+ break;
+ }
+ }
+ if (!selectedConditional) return defVal
+ let stacks = clamp(selectedConditionalNum, 1, selectedConditional.maxStack)
+ return Object.fromEntries(Object.entries(selectedConditional.stats).map(([key, val]) => [key, val * stacks]))
+ } else if (conditional.maxStack > 1) {
+ //condtional with stacks
+ let stacks = clamp(conditionalNum, 1, conditional.maxStack)
+ return Object.fromEntries(Object.entries(conditional.stats).map(([key, val]) => [key, val * stacks]))
+ } else if (conditional.maxStack === 1)
+ //boolean conditional
+ return conditional.stats
+ return defVal
+ }
+ static getArtifactSetEffectsStats = (setToSlots) => {
+ let artifactSetEffect = []
+ Object.entries(setToSlots).forEach(([setKey, artArr]) =>
+ ArtifactSetsData?.[setKey]?.sets && Object.entries(ArtifactSetsData[setKey].sets).forEach(([setNumKey, value]) =>
+ parseInt(setNumKey) <= artArr.length && value.stats && Object.keys(value.stats).length &&
+ Object.entries(value.stats).forEach(([key, statVal]) =>
+ artifactSetEffect.push({ key, statVal }))))
+ return artifactSetEffect
+ }
static getArtifactSetEffects = (setToSlots) => {
let artifactSetEffect = {}
- Object.entries(setToSlots).forEach(([setKey, arr]) => {
- let numArts = arr.length;
- if (ArtifactSetsData[setKey] && ArtifactSetsData[setKey].sets) {
- Object.entries(ArtifactSetsData[setKey].sets).forEach(([num, value]) => {
- if (parseInt(num) <= numArts) {
- !artifactSetEffect[setKey] && (artifactSetEffect[setKey] = {})
- artifactSetEffect[setKey][num] = deepClone(value);
- }
- })
+ Object.entries(setToSlots).forEach(([setKey, artArr]) => {
+ if (ArtifactSetsData?.[setKey]?.sets) {
+ let setNumKeys = Object.keys(ArtifactSetsData[setKey].sets).filter(setNumKey => parseInt(setNumKey) <= artArr.length)
+ if (setNumKeys.length)
+ artifactSetEffect[setKey] = setNumKeys
}
})
return artifactSetEffect
}
- static getAllArtifactSetEffectsObj = (conditionals) => {
+
+ static getArtifactSetEffectText = (setKey, setNumKey, charFinalStats, defVal = "") => {
+ let setEffectText = ArtifactSetsData?.[setKey]?.sets?.[setNumKey]?.text
+ if (!setEffectText) return defVal
+ if (typeof setEffectText === "string")
+ return setEffectText
+ else if (typeof setEffectText === "function")
+ return setEffectText(charFinalStats || {})
+ return defVal
+ }
+ static getArtifactSetEffectConditional = (setKey, setNumKey, defVal = null) =>
+ ArtifactSetsData?.[setKey]?.sets?.[setNumKey]?.conditional || defVal
+
+ static getAllArtifactSetEffectsObj = (artifactConditionals) => {
let ArtifactSetEffectsObj = {};
- Object.entries(ArtifactSetsData).forEach(([key, setObj]) => {
+ Object.entries(ArtifactSetsData).forEach(([setKey, setObj]) => {
let setEffect = {}
let hasSetEffect = false
if (setObj.sets)
Object.entries(setObj.sets).forEach(([setNumKey, setEffectObj]) => {
- //TODO conditionals
if (setEffectObj.stats && Object.keys(setEffectObj.stats).length > 0) {
setEffect[setNumKey] = deepClone(setEffectObj.stats)
hasSetEffect = true
}
+ if (setEffectObj.conditional) {
+ let conditionalNum = ArtifactConditionals.getConditionalNum(artifactConditionals, setKey, setNumKey)
+ if (conditionalNum) {
+ let condStats = this.getArtifactConditionalStats(setKey, setNumKey, conditionalNum)
+ if (condStats) {
+ setEffect[setNumKey] = deepClone(condStats)
+ hasSetEffect = true
+ }
+ }
+ }
})
if (hasSetEffect)
- ArtifactSetEffectsObj[key] = setEffect;
+ ArtifactSetEffectsObj[setKey] = setEffect;
})
return ArtifactSetEffectsObj
}
diff --git a/src/Artifact/ArtifactBase.js b/src/Artifact/ArtifactBase.js
index d5fc7efae4..98e19a9bd8 100644
--- a/src/Artifact/ArtifactBase.js
+++ b/src/Artifact/ArtifactBase.js
@@ -2,6 +2,7 @@ export default class ArtifactBase {
//do not instantiate.
constructor() { if (this instanceof ArtifactBase) throw Error('A static class cannot be instantiated.'); }
+ //returns {setKey:[slotKey...]}
static setToSlots = (artifacts) => {
let setToSlots = {};
Object.entries(artifacts).forEach(([key, art]) => {
@@ -9,6 +10,6 @@ export default class ArtifactBase {
if (setToSlots[art.setKey]) setToSlots[art.setKey].push(key)
else setToSlots[art.setKey] = [key]
})
- return setToSlots //{setKey:[slotKey...]}
+ return setToSlots
}
}
\ No newline at end of file
diff --git a/src/Artifact/ArtifactDatabase.js b/src/Artifact/ArtifactDatabase.js
index 01f346911a..7de9509a1c 100644
--- a/src/Artifact/ArtifactDatabase.js
+++ b/src/Artifact/ArtifactDatabase.js
@@ -1,4 +1,4 @@
-import { deepClone, loadFromLocalStorage, saveToLocalStorage } from "../Util";
+import { deepClone, loadFromLocalStorage, saveToLocalStorage } from "../Util/Util";
var initiated = false
var artifactDatabase = {};
var artIdIndex = 1;
diff --git a/src/Artifact/ArtifactDisplay.js b/src/Artifact/ArtifactDisplay.js
index fe3fc8db9f..c1d5bd7e49 100644
--- a/src/Artifact/ArtifactDisplay.js
+++ b/src/Artifact/ArtifactDisplay.js
@@ -12,12 +12,12 @@ import { Stars } from '../Components/StarDisplay';
import { ArtifactStarsData, ArtifactSubStatsData } from '../Data/ArtifactData';
import { DatabaseInitAndVerify } from '../DatabaseUtil';
import Stat from '../Stat';
-import { deepClone } from '../Util';
import Artifact from './Artifact';
import ArtifactCard from './ArtifactCard';
import ArtifactDatabase from './ArtifactDatabase';
import ArtifactEditor from './ArtifactEditor';
import ReactGA from 'react-ga';
+import { deepClone } from '../Util/Util';
export default class ArtifactDisplay extends React.Component {
constructor(props) {
diff --git a/src/Artifact/ArtifactEditor.js b/src/Artifact/ArtifactEditor.js
index 10fc4bd1c8..7f9ead20f3 100644
--- a/src/Artifact/ArtifactEditor.js
+++ b/src/Artifact/ArtifactEditor.js
@@ -6,7 +6,7 @@ import { FloatFormControl, IntFormControl } from '../Components/CustomFormContro
import { Stars } from '../Components/StarDisplay';
import { ArtifactSetsData, ArtifactSlotsData, ArtifactStarsData, ArtifactSubStatsData } from '../Data/ArtifactData';
import Stat from '../Stat';
-import { deepClone, getArrLastElement, getRandomElementFromArray, getRandomIntInclusive } from '../Util';
+import { deepClone, getArrLastElement, getRandomElementFromArray, getRandomIntInclusive } from '../Util/Util';
import Artifact from './Artifact';
import ArtifactDatabase from './ArtifactDatabase';
import PercentBadge from './PercentBadge';
@@ -298,12 +298,12 @@ export default class ArtifactEditor extends React.Component {
Substat Efficiency
- Every time 4 artifact upgrades, you get a substat roll. The substat efficiency calculates as a percentage how high the substat rolled. The Maximum Substat Efficiency of an artifact calculates the efficiency if the remaining upgrades rolled maximum.
+ Every 4 artifact upgrades, you get a substat roll. The substat efficiency calculates as a percentage how high the substat rolled. The Maximum Substat Efficiency of an artifact calculates the efficiency if the remaining upgrades rolled maximum.
}
diff --git a/src/Build/BuildDisplay.js b/src/Build/BuildDisplay.js
index 1cd41e3c4b..ad3f918bdf 100644
--- a/src/Build/BuildDisplay.js
+++ b/src/Build/BuildDisplay.js
@@ -2,20 +2,23 @@ import { faSortAmountDownAlt, faSortAmountUp } from '@fortawesome/free-solid-svg
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React from 'react';
import { Alert, Badge, Button, ButtonGroup, Card, Col, Container, Dropdown, DropdownButton, ListGroup, Modal, Row } from 'react-bootstrap';
+import ReactGA from 'react-ga';
// eslint-disable-next-line
import Worker from "worker-loader!./BuildWorker.js";
import Artifact from '../Artifact/Artifact';
-import { ArtifactSetsData, ArtifactSlotsData } from '../Data/ArtifactData';
import ArtifactDatabase from '../Artifact/ArtifactDatabase';
import Character from '../Character/Character';
+import CharacterCard from '../Character/CharacterCard';
import CharacterDatabase from '../Character/CharacterDatabase';
import CharacterDisplayCard from '../Character/CharacterDisplayCard';
+import ConditionalSelector from '../Components/ConditionalSelector';
+import { ArtifactSlotsData } from '../Data/ArtifactData';
import { DatabaseInitAndVerify } from '../DatabaseUtil';
import Stat from '../Stat';
-import { deepClone, loadFromLocalStorage, saveToLocalStorage } from '../Util';
-import Build from './Build';
-import ReactGA from 'react-ga';
+import ArtifactConditionals from '../Util/ArtifactConditionals';
+import { deepClone, loadFromLocalStorage, saveToLocalStorage } from '../Util/Util';
import Weapon from '../Weapon/Weapon';
+import Build from './Build';
export default class BuildDisplay extends React.Component {
constructor(props) {
@@ -42,6 +45,7 @@ export default class BuildDisplay extends React.Component {
gobletMainKey: "",
circletMainkey: "",
setFilters: [{ key: "", num: 0 }, { key: "", num: 0 }, { key: "", num: 0 }],
+ artifactConditionals: [],//{ setKey: "", setNumKey: "", conditionalNum: 0 }
mainStat: ["", "", ""],
buildFilterKey: "atk",
asending: false,
@@ -87,25 +91,28 @@ export default class BuildDisplay extends React.Component {
return { mainStat }
})
}
- changeSetFilterKey = (index, newkey, setsNumArr) => {
- if (this.state.setFilters[index].key === newkey) return
- this.setState((state) => {
- let setFilters = deepClone(state.setFilters);
- let num = 0
- if (setsNumArr && setsNumArr[0])
- num = parseInt(setsNumArr[0])
- setFilters[index] = { key: newkey, num }
- return { setFilters }
- })
- }
+ changeSetFilterKey = (index, newkey, setsNumArr) => this.setState(state => {
+ let oldKey = state.setFilters[index].key
+ if (oldKey === newkey) return
+ //remove conditionals with that key
+ let artifactConditionals = state.artifactConditionals ? state.artifactConditionals.filter(artifactCond => artifactCond.setKey !== oldKey) : []
+ let setFilters = state.setFilters;
+ let num = 0
+ //automatically select the 1st element from setsNumArr
+ if (setsNumArr && setsNumArr[0])
+ num = parseInt(setsNumArr[0])
+ setFilters[index] = { key: newkey, num }
+ return { setFilters, artifactConditionals }
+ })
+
dropdownitemsForStar = (star, index) =>
- Artifact.getArtifactSetsByMaxStarEntries(star).map(([key, setobj]) => {
- if (this.state.setFilters.some(filter => filter.key === key)) return false;
- let setsNumArr = Object.keys(ArtifactSetsData[key].sets)
+ Artifact.getArtifactSetsByMaxStarEntries(star).map(([setKey, setobj]) => {
+ if (this.state.setFilters.some(filter => filter.key === setKey)) return false;
+ let setsNumArr = Object.keys(Artifact.getArtifactSets(setKey))
let artsAccountedOther = this.state.setFilters.reduce((accu, cur, ind) => (cur.key && ind !== index) ? accu + cur.num : accu, 0)
if (setsNumArr.every(num => parseInt(num) + artsAccountedOther > 5)) return false;
- return ( this.changeSetFilterKey(index, key, setsNumArr)}
+ return ( this.changeSetFilterKey(index, setKey, setsNumArr)}
>
{setobj.name}
)
@@ -113,12 +120,12 @@ export default class BuildDisplay extends React.Component {
generateBuilds = (split, artifactSetPerms) => {
this.setState({ generatingBuilds: true, builds: [] })
- let { setFilters, asending, buildFilterKey, maxBuildsToShow } = this.state
+ let { setFilters, asending, buildFilterKey, maxBuildsToShow, artifactConditionals } = this.state
let character = CharacterDatabase.getCharacter(this.state.selectedCharacterId)
let weaponStats = Weapon.createWeaponBundle(character)
let initialStats = Character.calculateCharacterWithWeaponStats(character, weaponStats)
- let artifactSetEffects = Artifact.getAllArtifactSetEffectsObj()
+ let artifactSetEffects = Artifact.getAllArtifactSetEffectsObj(artifactConditionals)
let splitArtifacts = deepClone(split)
//add mainStatVal to each artifact, TODO add main stat assuming fully leveled up
Object.values(splitArtifacts).forEach(artArr => {
@@ -141,7 +148,7 @@ export default class BuildDisplay extends React.Component {
label: Build.calculateTotalBuildNumber(split, artifactSetPerms, this.state.setFilters)
})
let builds = e.data.builds.map(obj =>
- Character.calculateBuildWithObjs(initialStats, obj.artifacts))
+ Character.calculateBuildWithObjs(artifactConditionals, initialStats, obj.artifacts))
this.setState({ builds, generatingBuilds: false })
}
@@ -161,86 +168,133 @@ export default class BuildDisplay extends React.Component {
: (totBuildNumber > this.state.maxBuildsToGenerate ?
Current configuration will generate {totBuildNumber} builds for {characterName}. Please restrict artifact configuration to reduce builds to less than {this.state.maxBuildsToGenerate}, or your browser might crash. :
Current configuration will generate {totBuildNumber} builds for {characterName}.)
+ let characterDropDown =
+ this.setState({ selectedCharacterId: "", builds: [] })}>No Character
+ {Object.values(charlist).map((char, i) =>
+ this.setState({ selectedCharacterId: char.id, builds: [] })}
+ >
+ {char.name}
+ )}
+
return
Build Generator
-
-
- {/* Character picker */}
-
-
- this.setState({ selectedCharacterId: "", builds: [] })}>
- No Character
-
- {Object.values(charlist).map((char, i) =>
- this.setState({ selectedCharacterId: char.id, builds: [] })}
- >
- {char.name}
- )}
-
-
- {/* Artifact set picker */}
- {this.state.setFilters.map((setFilter, index) =>
-
-
- {/* Artifact set */}
-
- this.changeSetFilterKey(index, "")}>
- Unselect Artifact
-
- Max Rarity 🟊🟊🟊🟊🟊
- {this.dropdownitemsForStar(5, index)}
-
- Max Rarity 🟊🟊🟊🟊
- {this.dropdownitemsForStar(4, index)}
-
- Max Rarity 🟊🟊🟊
- {this.dropdownitemsForStar(3, index)}
+
+
+ {/* character selection */}
+ {this.state.selectedCharacterId ? :
+
+
+ {characterDropDown}
+
+ }
+ {/* main stat selector */}
+
+ Artifact Main Stat (Optional)
+
+ {BuildDisplay.artifactsSlotsToSelectMainStats.map((slotKey, index) =>
+ (
+
+ {Artifact.getArtifactSlotNameWithIcon(slotKey)}
+
+
+ this.changeMainStat(index, "")} >No MainStat
+ {ArtifactSlotsData[slotKey].stats.map(mainStatKey =>
+ this.changeMainStat(index, mainStatKey)} key={mainStatKey}>
+ {Stat.getStatNameWithPercent(mainStatKey)}
+
+ )}
- {/* set number */}
- = 5}
- >
- {setFilter.key && Artifact.getArtifactSetEffectsObj(setFilter.key) && Object.keys(Artifact.getArtifactSetEffectsObj(setFilter.key)).map(num => {
- let artsAccountedOther = this.state.setFilters.reduce((accu, cur) => (cur.key && cur.key !== setFilter.key) ? accu + cur.num : accu, 0)
- return (parseInt(num) + artsAccountedOther <= 5) &&
- ( this.setState((state) => {
- let setFilters = deepClone(state.setFilters);
- setFilters[index].num = parseInt(num)
- return { setFilters }
- })}
- >
- {`${num}-set`}
- )
- })}
-
-
-
- )}
+
))}
+
+
-
- Artifact Main Stat (Optional)
- {BuildDisplay.artifactsSlotsToSelectMainStats.map((slotKey, index) =>
- (
-
- {Artifact.getArtifactSlotNameWithIcon(slotKey)}
-
-
- this.changeMainStat(index, "")} >No MainStat
- {ArtifactSlotsData[slotKey].stats.map(mainStatKey =>
- this.changeMainStat(index, mainStatKey)} key={mainStatKey}>
- {Stat.getStatNameWithPercent(mainStatKey)}
+
+ {/* Artifact set picker */}
+ {this.state.setFilters.map((setFilter, index) => {
+ let { key: setKey, num } = setFilter
+ let { artifactConditionals } = this.state
+ return (
+
+
+
+ {/* Artifact set */}
+
+ this.changeSetFilterKey(index, "")}>
+ Unselect Artifact
- )}
-
-
))}
-
+ Max Rarity 🟊🟊🟊🟊🟊
+ {this.dropdownitemsForStar(5, index)}
+
+ Max Rarity 🟊🟊🟊🟊
+ {this.dropdownitemsForStar(4, index)}
+
+ Max Rarity 🟊🟊🟊
+ {this.dropdownitemsForStar(3, index)}
+
+ {/* set number */}
+ = 5}
+ >
+ {setFilter.key && Artifact.getArtifactSetEffectsObj(setFilter.key) && Object.keys(Artifact.getArtifactSetEffectsObj(setFilter.key)).map(num => {
+ let artsAccountedOther = this.state.setFilters.reduce((accu, cur) => (cur.key && cur.key !== setFilter.key) ? accu + cur.num : accu, 0)
+ return (parseInt(num) + artsAccountedOther <= 5) &&
+ ( this.setState((state) => {
+ let setFilters = deepClone(state.setFilters);
+ setFilters[index].num = parseInt(num)
+ return { setFilters }
+ })}
+ >
+ {`${num}-set`}
+ )
+ })}
+
+
+
+ {setFilter.key ?
+ {Object.keys(Artifact.getArtifactSets(setKey)).filter(setNkey => parseInt(setNkey) <= num).map(setNumKey => {
+ let setStats = Artifact.getArtifactSetNumStats(setKey, setNumKey)
+ let conditionalNum = 0;
+ let conditional = Artifact.getArtifactSetEffectConditional(setKey, setNumKey)
+ if (conditional) {
+ conditionalNum = ArtifactConditionals.getConditionalNum(artifactConditionals, setKey, setNumKey)
+ let conditionalStats = Artifact.getArtifactConditionalStats(setKey, setNumKey, conditionalNum)
+ if (conditionalStats) {
+ if (!setStats) setStats = {}
+ Object.entries(conditionalStats).forEach(([statKey, val]) =>
+ setStats[statKey] = (setStats[statKey] || 0) + val)
+ }
+ }
+ let setStateArtifactConditional = (conditionalNum) => this.setState(state =>
+ ({ artifactConditionals: ArtifactConditionals.setConditional(state.artifactConditionals, setKey, setNumKey, conditionalNum) }))
+ let conditionalElement = {setNumKey}-Set}
+ />
+ return
+ {conditionalElement} {Artifact.getArtifactSetEffectText(setKey, setNumKey)}
+ {setStats ?
+ {Object.entries(setStats).map(([statKey, val]) =>
+ {Stat.getStatName(statKey)}: {val}{Stat.getStatUnit(statKey)})}
+
: null}
+
+ })}
+
: null}
+
+ )
+ })}
+
-
+
+ {this.state.selectedCharacterId && buildAlert}
+
+
-
- {this.state.selectedCharacterId && buildAlert}
-
}
diff --git a/src/Character/Character.js b/src/Character/Character.js
index 502fadee6f..42137e61fa 100644
--- a/src/Character/Character.js
+++ b/src/Character/Character.js
@@ -3,7 +3,7 @@ import ArtifactDatabase from "../Artifact/ArtifactDatabase";
import Assets from "../Assets/Assets";
import { CharacterData, characterStatBase, ElementalData, LevelsData } from "../Data/CharacterData";
import Stat from "../Stat";
-import { deepClone } from "../Util";
+import { deepClone } from "../Util/Util";
import Weapon from "../Weapon/Weapon";
import CharacterDatabase from "./CharacterDatabase";
@@ -96,15 +96,16 @@ export default class Character {
CharacterDatabase.removeCharacterById(characterId)
}
- static calculateBuild = (character, artifacts) => {
+ static calculateBuild = (character) => {
+ let artifacts = Object.fromEntries(Object.entries(character.equippedArtifacts).map(([key, artid]) => [key, ArtifactDatabase.getArtifact(artid)]))
let weaponStats = Weapon.createWeaponBundle(character)
let initialStats = Character.calculateCharacterWithWeaponStats(character, weaponStats)
- return this.calculateBuildWithObjs(initialStats, artifacts)
+ return this.calculateBuildWithObjs(character.artifactConditionals, initialStats, artifacts)
}
- //buildworker doesn't have access to the database, so we need to feed in the objs
- static calculateBuildWithObjs = (charAndWeapon, artifacts) => {
+
+ static calculateBuildWithObjs = (artifactConditionals, charAndWeapon, artifacts) => {
let setToSlots = Artifact.setToSlots(artifacts)
- let artifactSetEffect = Artifact.getArtifactSetEffects(setToSlots)
+ let artifactSetEffectsStats = Artifact.getArtifactSetEffectsStats(setToSlots)
let stats = deepClone(charAndWeapon)
//add artifact and artifactsets
@@ -117,10 +118,12 @@ export default class Character {
substat && substat.key && (stats[substat.key] = (stats[substat.key] || 0) + substat.value))
})
//setEffects
- Object.values(artifactSetEffect).forEach(setEffects =>
- Object.values(setEffects).forEach(setEffect =>
- setEffect.stats && Object.entries(setEffect.stats).forEach(([key, statVal]) =>
- stats[key] = (stats[key] || 0) + statVal)))
+ artifactSetEffectsStats.forEach(stat => stats[stat.key] = (stats[stat.key] || 0) + stat.statVal)
+ //setEffects conditionals
+ artifactConditionals && artifactConditionals.forEach(conditional => {
+ let condStats = Artifact.getArtifactConditionalStats(conditional.setKey, conditional.setNumKey, conditional.conditionalNum)
+ if (condStats) Object.entries(condStats).forEach(([statKey, val]) => stats[statKey] = (stats[statKey] || 0) + val)
+ })
let arrKey = ["hp", "def", "atk"]
arrKey.forEach(key => {
@@ -139,9 +142,9 @@ export default class Character {
return {
artifactIds: Object.fromEntries(Object.entries(artifacts).map(([key, val]) => [key, val?.id])),
- artifactSetEffect,
setToSlots,
- finalStats: stats
+ finalStats: stats,
+ artifactConditionals
}
}
static calculateCharacterWithWeaponStats = (character, weaponStats) => {
diff --git a/src/Character/CharacterCard.js b/src/Character/CharacterCard.js
index 7808f3eaf6..df2536c240 100644
--- a/src/Character/CharacterCard.js
+++ b/src/Character/CharacterCard.js
@@ -1,48 +1,40 @@
-import { faDice, faDiceD20, faEdit, faFistRaised, faMagic, faShieldAlt, faSync, faTint, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
+import { faEdit, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React from 'react';
-import { Image } from 'react-bootstrap';
+import { Badge, Image } from 'react-bootstrap';
import Button from 'react-bootstrap/Button';
import Card from 'react-bootstrap/Card';
import Col from 'react-bootstrap/Col';
import Row from 'react-bootstrap/Row';
import { Link } from 'react-router-dom';
import Artifact from '../Artifact/Artifact';
-import ArtifactDatabase from '../Artifact/ArtifactDatabase';
import Assets from '../Assets/Assets';
import { Stars } from '../Components/StarDisplay';
+import { StatIconEle } from '../Components/StatIcon';
import Stat from '../Stat';
import Weapon from '../Weapon/Weapon';
import Character from './Character';
import CharacterDatabase from './CharacterDatabase';
export default function CharacterCard(props) {
- if (!props.characterData) return null;
- let { characterData: { id, characterKey, name, equippedArtifacts, weapon, constellation } } = props
- let { characterData } = props
+ let { characterId } = props
+ let character = CharacterDatabase.getCharacter(characterId)
+ if (!character) return null;
+ let build = Character.calculateBuild(character)
+ let { setToSlots } = build
+
+ let { characterKey, name, weapon, constellation } = character
let elementKey = Character.getElementalKey(characterKey)
let weaponTypeKey = Character.getWeaponTypeKey(characterKey)
- let character = CharacterDatabase.getCharacter(id)
- let artifacts = Object.fromEntries(Object.entries(equippedArtifacts).map(([key, artid]) => [key, ArtifactDatabase.getArtifact(artid)]))
- let build = Character.calculateBuild(character, artifacts)
- let { artifactSetEffect } = build
- const statIcon = {
- hp: faTint,
- atk: faFistRaised,
- def: faShieldAlt,
- ele_mas: faMagic,
- crit_rate: faDice,
- crit_dmg: faDiceD20,
- ener_rech: faSync,
- }
let weaponName = Weapon.getWeaponName(weapon.key)
- let weaponMainVal = Weapon.getWeaponMainStatValWithOverride(characterData?.weapon)
+ let weaponMainVal = Weapon.getWeaponMainStatValWithOverride(weapon)
let weaponSubKey = Weapon.getWeaponSubStatKey(weapon.key)
- let weaponSubVal = Weapon.getWeaponSubStatValWithOverride(characterData?.weapon)
+ let weaponSubVal = Weapon.getWeaponSubStatValWithOverride(weapon)
let weaponLevelName = Weapon.getLevelName(weapon.levelKey)
let weaponPassiveName = Weapon.getWeaponPassiveName(weapon.key)
- return (
+ const statkeys = ["hp", "atk", "def", "ele_mas", "crit_rate", "crit_dmg", "ener_rech",]
+ return (
-
+ {props.header ? props.header :
{name}
@@ -58,7 +50,7 @@ export default function CharacterCard(props) {
-
+
}
@@ -68,7 +60,7 @@ export default function CharacterCard(props) {
{Character.getName(characterKey)}
- {`Lvl. ${Character.getLevelWithOverride(characterData)} C${constellation}`}
+ {`Lvl. ${Character.getLevelWithOverride(character)} C${constellation}`}
@@ -79,20 +71,19 @@ export default function CharacterCard(props) {
- {Object.entries(artifactSetEffect).map(([key, obj]) => {
+ {Object.entries(Artifact.getArtifactSetEffects(setToSlots)).map(([key, arr]) => {
let artifactSetName = Artifact.getArtifactSetName(key)
- let highestNum = Math.max(...Object.keys(obj))
- return {artifactSetName}({highestNum})
+ let highestNum = Math.max(...arr)
+ return {artifactSetName} {highestNum}
})}
- {Object.keys(statIcon).map(statKey => {
- // let statVal = Character.getStatValueWithOverride(characterData, statKey)
+ {statkeys.map(statKey => {
let unit = Stat.getStatUnit(statKey)
let statVal = build.finalStats[statKey]
return
- {statIcon[statKey] && } {Stat.getStatName(statKey)}
+ {StatIconEle(statKey)} {Stat.getStatName(statKey)}
{statVal?.toFixed(Stat.fixedUnit(statKey)) + unit}
@@ -100,13 +91,13 @@ export default function CharacterCard(props) {
})}
-
+ {props.footer &&
-
+ }
)
}
\ No newline at end of file
diff --git a/src/Character/CharacterDatabase.js b/src/Character/CharacterDatabase.js
index 8d34db8e6c..febbd7bde1 100644
--- a/src/Character/CharacterDatabase.js
+++ b/src/Character/CharacterDatabase.js
@@ -1,4 +1,4 @@
-import { deepClone, loadFromLocalStorage, saveToLocalStorage } from "../Util";
+import { deepClone, loadFromLocalStorage, saveToLocalStorage } from "../Util/Util";
var initiated = false
var characterDatabase = {};
var charIdIndex = 1;
diff --git a/src/Character/CharacterDisplay.js b/src/Character/CharacterDisplay.js
index a2a07a2370..8468dbe1de 100644
--- a/src/Character/CharacterDisplay.js
+++ b/src/Character/CharacterDisplay.js
@@ -67,7 +67,8 @@ export default class CharacterDisplay extends React.Component {
{charIdList.map(id =>
this.deleteCharacter(id)}
onEdit={() => this.editCharacter(id)}
/>
diff --git a/src/Character/CharacterDisplay/CharacterArtifactPane.js b/src/Character/CharacterDisplay/CharacterArtifactPane.js
index e062dcfcd4..b8074dd339 100644
--- a/src/Character/CharacterDisplay/CharacterArtifactPane.js
+++ b/src/Character/CharacterDisplay/CharacterArtifactPane.js
@@ -1,18 +1,20 @@
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import React, { useState } from 'react';
import { Accordion, Badge, Button, Card, Col, Row } from 'react-bootstrap';
import Artifact from '../../Artifact/Artifact';
import ArtifactCard from '../../Artifact/ArtifactCard';
-import StatIcon from '../../Components/StatIcon';
+import ConditionalSelector from '../../Components/ConditionalSelector';
+import { StatIconEle } from '../../Components/StatIcon';
import Stat from "../../Stat";
+import ArtifactConditionals from '../../Util/ArtifactConditionals';
import Character from "../Character";
function CharacterArtifactPane(props) {
let [showOther, setShowOther] = useState(false)
- let { character: { characterKey, compareAgainstEquipped }, equippedBuild, newBuild, editable, forceUpdate } = props
+ let { character: { characterKey, compareAgainstEquipped, artifactConditionals }, equippedBuild, newBuild, editable, forceUpdate, setState } = props
let { character } = props
//choose which one to display stats for
let build = newBuild ? newBuild : equippedBuild
+ if (newBuild) artifactConditionals = newBuild.artifactConditionals
let eleKey = Character.getElementalKey(characterKey)
const statKeys = ["hp", "atk", "def", "ele_mas", "crit_rate", "crit_dmg", "crit_multi", "ener_rech", "heal_bonu", "phy_dmg", "phy_atk",]
statKeys.push(`${eleKey}_ele_dmg`)
@@ -31,7 +33,7 @@ function CharacterArtifactPane(props) {
let buildDiff = (build?.finalStats?.[statKey] || 0) - statVal
return
- {StatIcon[statKey] ? : null} {Stat.getStatName(statKey)}
+ {StatIconEle(statKey)} {Stat.getStatName(statKey)}
{statVal?.toFixed(Stat.fixedUnit(statKey)) + unit}
{buildDiff ? 0 ? "text-success" : "text-danger"}> {buildDiff > 0 && "+"}{buildDiff?.toFixed(Stat.fixedUnit(statKey)) + unit} : null}
@@ -44,13 +46,15 @@ function CharacterArtifactPane(props) {
let buildDiff = (newBuild?.finalStats?.[statKey] || 0) - (equippedBuild?.finalStats?.[statKey] || 0)
return
- {StatIcon[statKey] ? : null} {Stat.getStatName(statKey)}
+ {StatIconEle(statKey)} {Stat.getStatName(statKey)}
{statVal?.toFixed(Stat.fixedUnit(statKey)) + unit}
{buildDiff ? 0 ? "text-success" : "text-danger"}> ({buildDiff > 0 ? "+" : ""}{buildDiff?.toFixed(Stat.fixedUnit(statKey)) + unit}) : null}
}
+ const setStateArtifactConditional = (setKey, setNumKey, conditionalNum) => setState(state =>
+ ({ artifactConditionals: ArtifactConditionals.setConditional(state.artifactConditionals, setKey, setNumKey, conditionalNum) }))
return <>
@@ -98,12 +102,37 @@ function CharacterArtifactPane(props) {
Artifact Set Effects
- {Object.entries(build.artifactSetEffect).map(([setKey, effects]) =>
+ {Object.entries(Artifact.getArtifactSetEffects(build.setToSlots)).map(([setKey, setNumKeyArr]) =>
{Artifact.getArtifactSetName(setKey)}
- {Object.entries(effects).map(([num, effect]) => {
- return {num}-Set {effect.text}
+ {setNumKeyArr.map(setNumKey => {
+ let setStats = Artifact.getArtifactSetNumStats(setKey, setNumKey)
+ let conditionalNum = 0;
+ let conditional = Artifact.getArtifactSetEffectConditional(setKey, setNumKey)
+ if (conditional) {
+ conditionalNum = ArtifactConditionals.getConditionalNum(artifactConditionals, setKey, setNumKey)
+ let conditionalStats = Artifact.getArtifactConditionalStats(setKey, setNumKey, conditionalNum)
+ if (conditionalStats) {
+ if (!setStats) setStats = {}
+ Object.entries(conditionalStats).forEach(([statKey, val]) =>
+ setStats[statKey] = (setStats[statKey] || 0) + val)
+ }
+ }
+ let conditionalElement = setStateArtifactConditional(setKey, setNumKey, cnum)}
+ defEle={{setNumKey}-Set}
+ />
+ return
+ {conditionalElement} {Artifact.getArtifactSetEffectText(setKey, setNumKey, build.finalStats)}
+ {setStats ?
+ {Object.entries(setStats).map(([statKey, val]) =>
+ {Stat.getStatName(statKey)}: {val}{Stat.getStatUnit(statKey)})}
+
: null}
+
})}
diff --git a/src/Character/CharacterDisplay/CharacterOverviewPane.js b/src/Character/CharacterDisplay/CharacterOverviewPane.js
index f4e3e59937..d262a394bc 100644
--- a/src/Character/CharacterDisplay/CharacterOverviewPane.js
+++ b/src/Character/CharacterDisplay/CharacterOverviewPane.js
@@ -1,11 +1,12 @@
-import { faCheckSquare, faEdit, faGavel, faQuoteLeft, faSave, faSquare } from "@fortawesome/free-solid-svg-icons"
+import { faEdit, faGavel, faQuoteLeft, faSave } from "@fortawesome/free-solid-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import React, { useState } from "react"
-import { Badge, Button, Card, Col, Dropdown, DropdownButton, Image, InputGroup, OverlayTrigger, Row, Tooltip } from "react-bootstrap"
+import { Button, Card, Col, Dropdown, DropdownButton, Image, InputGroup, OverlayTrigger, Row, Tooltip } from "react-bootstrap"
import Assets from "../../Assets/Assets"
+import ConditionalSelector from "../../Components/ConditionalSelector"
import { FloatFormControl, IntFormControl } from "../../Components/CustomFormControl"
import { Stars } from "../../Components/StarDisplay"
-import StatIcon from "../../Components/StatIcon"
+import StatIcon, { StatIconEle } from "../../Components/StatIcon"
import { CharacterSpecializedStatKey } from "../../Data/CharacterData"
import { LevelNameData } from "../../Data/WeaponData"
import Stat from "../../Stat"
@@ -105,68 +106,14 @@ function WeaponStatsEditorCard(props) {
let weaponPassiveName = Weapon.getWeaponPassiveName(weapon.key)
let weaponBonusStats = Weapon.getWeaponBonusStat(weapon.key, weapon.refineIndex)
let conditionalStats = Weapon.getWeaponConditionalStat(weapon.key, weapon.refineIndex, weapon.conditionalNum)
- let conditionalEle = (() => {
- let conditional = Weapon.getWeaponConditional(weapon.key)
- if (!conditional) return {weaponPassiveName}
- let conditionalNum = weapon.conditionalNum;
- if (Array.isArray(conditional)) {
- let selectedConditionalNum = conditionalNum
- let selectedConditional
- for (const curConditional of conditional) {
- if (selectedConditionalNum > curConditional.maxStack) selectedConditionalNum -= curConditional.maxStack
- else {
- selectedConditional = curConditional;
- break;
- }
- }
- if (!selectedConditional) selectedConditionalNum = 0
- //TODO multi conditional
- let text = selectedConditionalNum === 0 ? "Not Active" :
- (selectedConditional.condition + (selectedConditional.maxStack > 1 ? (`: ${selectedConditionalNum} stack${selectedConditionalNum > 1 ? "s" : ""}`) : ""))
- let badge = {text}
- let count = 0;
- return
-
- {weaponPassiveName} {badge}
-
-
- setStateWeapon("conditionalNum", 0)}>
- Not Active
-
- {conditional.map(condial =>
- {[...Array(condial.maxStack).keys()].map(v => v + 1).map(stack => {
- let tempcount = ++count
- return setStateWeapon("conditionalNum", tempcount)}>
- {condial.condition}{selectedConditional.maxStack > 1 ? `: ${stack} stack${stack > 1 ? "s" : ""}` : ""}
-
- })}
- )}
-
-
- } else if (conditional.maxStack > 1) {
- //stacking conditional
- let badge = {conditionalNum > 0 ? `${conditionalNum} stack${conditionalNum > 1 ? "s" : ""}` : "Not Active"}
- return
-
- {weaponPassiveName} {badge}
-
-
- setStateWeapon("conditionalNum", 0)}>
- Not Active
-
- {[...Array(conditional.maxStack).keys()].map(v => v + 1).map(stack =>
- setStateWeapon("conditionalNum", stack)}>
- {`${stack} stack${stack > 1 ? "s" : ""}`}
- )}
-
-
- } else if (conditional.maxStack === 1) {
- //single boolean conditional
- return
- }
- })()
+ let conditional = Weapon.getWeaponConditional(weapon.key)
+ let conditionalNum = weapon.conditionalNum;
+ let conditionalEle = setStateWeapon("conditionalNum", cnum)}
+ defEle={{weaponPassiveName}
}
+ />
return
@@ -240,7 +187,7 @@ function WeaponStatsEditorCard(props) {
{subStatKey &&
{StatIcon[subStatKey] ? : null}{Stat.getStatName(subStatKey)}
}
+ name={{StatIconEle(subStatKey)}{Stat.getStatName(subStatKey)}}
placeholder="Weapon Substat"
value={weaponDisplaySubVal}
percent={Stat.getStatUnit(subStatKey) === "%"}
@@ -321,7 +268,7 @@ function MainStatsCard(props) {
let unit = Stat.getStatUnit(statKey)
let buildDiff = (build?.finalStats?.[statKey] || 0) - statVal
return
- {StatIcon[statKey] ? : null} {Stat.getStatName(statKey)}
+ {StatIconEle(statKey)} {Stat.getStatName(statKey)}
{statVal?.toFixed(Stat.fixedUnit(statKey)) + unit}
{buildDiff ? 0 ? "text-success" : "text-danger"}> {buildDiff > 0 && "+"}{buildDiff?.toFixed(Stat.fixedUnit(statKey)) + unit} : null}
@@ -334,7 +281,7 @@ function MainStatsCard(props) {
let buildDiff = (newBuild?.finalStats?.[statKey] || 0) - (equippedBuild?.finalStats?.[statKey] || 0)
return
- {StatIcon[statKey] ? : null} {Stat.getStatName(statKey)}
+ {StatIconEle(statKey)} {Stat.getStatName(statKey)}
{statVal?.toFixed(Stat.fixedUnit(statKey)) + unit}
{buildDiff ? 0 ? "text-success" : "text-danger"}> ({buildDiff > 0 && "+"}{buildDiff?.toFixed(Stat.fixedUnit(statKey)) + unit}) : null}
diff --git a/src/Character/CharacterDisplayCard.js b/src/Character/CharacterDisplayCard.js
index 18926c2125..1d1149fc86 100644
--- a/src/Character/CharacterDisplayCard.js
+++ b/src/Character/CharacterDisplayCard.js
@@ -7,16 +7,15 @@ import Card from 'react-bootstrap/Card';
import Col from 'react-bootstrap/Col';
import DropdownToggle from 'react-bootstrap/esm/DropdownToggle';
import Row from 'react-bootstrap/Row';
-import ArtifactDatabase from '../Artifact/ArtifactDatabase';
import { WeaponLevelKeys } from '../Data/WeaponData';
import { DatabaseInitAndVerify } from '../DatabaseUtil';
-import { deepClone, getRandomElementFromArray } from '../Util';
+import { deepClone, getRandomElementFromArray } from '../Util/Util';
+import Weapon from '../Weapon/Weapon';
import Character from './Character';
import CharacterDatabase from './CharacterDatabase';
import CharacterArtifactPane from './CharacterDisplay/CharacterArtifactPane';
import CharacterOverviewPane from './CharacterDisplay/CharacterOverviewPane';
import CharacterTalentPane from './CharacterDisplay/CharacterTalentPane';
-import Weapon from '../Weapon/Weapon'
const CustomMenu = React.forwardRef(
({ children, style, className, 'aria-labelledby': labeledBy }, ref) => {
@@ -51,6 +50,7 @@ export default class CharacterDisplayCard extends React.Component {
levelKey: "L1",//combination of level and ascension
overrideLevel: 0,
equippedArtifacts: {},
+ artifactConditionals: [],
baseStatOverrides: {},//overriding the baseStat
weapon: {
key: "",
@@ -128,9 +128,8 @@ export default class CharacterDisplayCard extends React.Component {
render() {
let { footer, newBuild, editable } = this.props
let character = this.state
- let { characterKey, equippedArtifacts, levelKey, compareAgainstEquipped } = this.state
- let equippedArtifactsObjs = Object.fromEntries(Object.entries(equippedArtifacts).map(([key, artid]) => [key, ArtifactDatabase.getArtifact(artid)]))
- let equippedBuild = Character.calculateBuild(this.state, equippedArtifactsObjs)
+ let { characterKey, levelKey, compareAgainstEquipped } = this.state
+ let equippedBuild = Character.calculateBuild(this.state)
let HeaderIconDisplay =
{Character.getName(characterKey)}
@@ -229,7 +228,7 @@ export default class CharacterDisplayCard extends React.Component {
/>
-
+
{newBuild ?
diff --git a/src/Components/ConditionalSelector.js b/src/Components/ConditionalSelector.js
new file mode 100644
index 0000000000..6111acaadd
--- /dev/null
+++ b/src/Components/ConditionalSelector.js
@@ -0,0 +1,71 @@
+import { faCheckSquare, faSquare } from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import React from 'react';
+import { Badge, Button, Dropdown } from 'react-bootstrap';
+
+export default function ConditionalSelector(props) {
+ let { conditional, conditionalNum, setConditional, defEle, disabled } = props
+ if (!conditional) return defEle
+ if (Array.isArray(conditional)) {
+ let selectedConditionalNum = conditionalNum
+ let selectedConditional = null
+ for (const curConditional of conditional) {
+ if (selectedConditionalNum > curConditional.maxStack) selectedConditionalNum -= curConditional.maxStack
+ else {
+ selectedConditional = curConditional;
+ break;
+ }
+ }
+ if (!selectedConditional) {
+ selectedConditionalNum = 0
+ selectedConditional = conditional[0]
+ }
+
+ //multi conditional
+ let text = selectedConditionalNum === 0 ? "Not Active" :
+ (selectedConditional.condition + (selectedConditional.maxStack > 1 ? (`: ${selectedConditionalNum} stack${selectedConditionalNum > 1 ? "s" : ""}`) : ""))
+ let badge = {text}
+ let count = 0;
+ return
+
+ {defEle} {badge}
+
+
+ setConditional(0)}>
+ Not Active
+
+ {conditional.map(condial =>
+ {[...Array(condial.maxStack).keys()].map(v => v + 1).map(stack => {
+ let tempcount = ++count
+ return setConditional(tempcount)}>
+ {condial.condition}{selectedConditional.maxStack > 1 ? `: ${stack} stack${stack > 1 ? "s" : ""}` : ""}
+
+ })}
+ )}
+
+
+ } else if (conditional.maxStack > 1) {
+ //stacking conditional
+ let badge = {conditionalNum > 0 ? `${conditionalNum} stack${conditionalNum > 1 ? "s" : ""}` : "Not Active"}
+ return
+
+ {defEle} {badge}
+
+
+ setConditional(0)}>
+ Not Active
+
+ {[...Array(conditional.maxStack).keys()].map(v => v + 1).map(stack =>
+ setConditional(stack)}>
+ {`${stack} stack${stack > 1 ? "s" : ""}`}
+ )}
+
+
+ } else if (conditional.maxStack === 1) {
+ //single boolean conditional
+ return
+ }
+
+}
\ No newline at end of file
diff --git a/src/Components/StatIcon.js b/src/Components/StatIcon.js
index 91776be713..b603439896 100644
--- a/src/Components/StatIcon.js
+++ b/src/Components/StatIcon.js
@@ -1,13 +1,25 @@
import { faDice, faDiceD20, faFirstAid, faFistRaised, faMagic, faShieldAlt, faSync, faTint } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
const StatIcon = {
hp: faTint,
+ hp_: faTint,
atk: faFistRaised,
+ atk_: faFistRaised,
def: faShieldAlt,
+ def_: faShieldAlt,
ele_mas: faMagic,
crit_rate: faDice,
crit_dmg: faDiceD20,
ener_rech: faSync,
heal_bonu: faFirstAid,
}
-export default StatIcon
\ No newline at end of file
+
+const StatIconEle = (statKey) =>
+ StatIcon[statKey] ? : null
+
+export default StatIcon
+
+export {
+ StatIconEle
+}
\ No newline at end of file
diff --git a/src/Data/Artifacts/Adventurer/Adventurer.js b/src/Data/Artifacts/Adventurer/Adventurer.js
index 2e6d31165b..9f85851311 100644
--- a/src/Data/Artifacts/Adventurer/Adventurer.js
+++ b/src/Data/Artifacts/Adventurer/Adventurer.js
@@ -3,6 +3,7 @@ import plume from './Item_Adventurer\'s_Tail_Feather.png'
import sands from './Item_Adventurer\'s_Pocket_Watch.png'
import goblet from './Item_Adventurer\'s_Golden_Goblet.png'
import circlet from './Item_Adventurer\'s_Bandana.png'
+import WeaponPercent from '../../../Components/WeaponPercent'
let artifact = {
name: "Adventurer", rarity: [3],
pieces: {
@@ -25,8 +26,7 @@ let artifact = {
stats: { hp: 1000 }
},
4: {
- text: "Opening chest regenerates 30% Max HP over 5s.",
- stats: {}
+ text: (charFinalStats)=>Opening chest regenerates 30% Max HP{WeaponPercent(30, charFinalStats.hp)} over 5s.,
}
}
}
diff --git a/src/Data/Artifacts/ArchaicPetra/ArchaicPetra.js b/src/Data/Artifacts/ArchaicPetra/ArchaicPetra.js
index ba631c1aec..a5a5c84d56 100644
--- a/src/Data/Artifacts/ArchaicPetra/ArchaicPetra.js
+++ b/src/Data/Artifacts/ArchaicPetra/ArchaicPetra.js
@@ -25,8 +25,40 @@ let artifact = {
stats: { geo_ele_dmg: 15 }
},
4: {
- text: "Upon obtaining a crystal created through a Geo Elemental Reaction, all party members gain 35% RES to that particular element for 10s. Only one form of Elemental RES can be gained in this manner at any one time. Upon obtaining a crystal created through a Geo Elemental Reaction, all party members gain 35% RES to that particular element for 10s. Only one form of Elemental RES can be gained in this manner at any one time.",
- stats: {}
+ text: "Upon obtaining an Elemental Shard created through a Crystallize Reaction, all party members gain 35% DMG to that particular element for 10s. Only one form of Elemental DMG can be gained in this manner at any one time.",
+ conditional: [{//TODO all party conditional
+ type: "artifact",
+ condition:"Pyro",
+ sourceKey: "ArchaicPetra_4",
+ maxStack: 1,
+ stats: {
+ pyro_ele_dmg: 35,
+ }
+ },{
+ type: "artifact",
+ condition:"Electro",
+ sourceKey: "ArchaicPetra_4",
+ maxStack: 1,
+ stats: {
+ electro_ele_dmg: 35,
+ }
+ },{
+ type: "artifact",
+ condition:"Hydro",
+ sourceKey: "ArchaicPetra_4",
+ maxStack: 1,
+ stats: {
+ hydro_ele_dmg: 35,
+ }
+ },{
+ type: "artifact",
+ condition:"Cryo",
+ sourceKey: "ArchaicPetra_4",
+ maxStack: 1,
+ stats: {
+ cryo_ele_dmg: 35,
+ }
+ }]
}
}
}
diff --git a/src/Data/Artifacts/Berserker/Berserker.js b/src/Data/Artifacts/Berserker/Berserker.js
index 1214412217..699d5c5732 100644
--- a/src/Data/Artifacts/Berserker/Berserker.js
+++ b/src/Data/Artifacts/Berserker/Berserker.js
@@ -4,7 +4,7 @@ import sands from './Item_Berserker\'s_Timepiece.png'
import goblet from './Item_Berserker\'s_Bone_Goblet.png'
import circlet from './Item_Berserker\'s_Battle_Mask.png'
let artifact = {
- name: "Berserker", rarity: [3, 4],
+ name: "Berserker", rarity: [3, 4],
pieces: {
flower: "Berserker's Rose",
plume: "Berserker's Indigo Feather",
@@ -26,7 +26,14 @@ let artifact = {
},
4: {
text: "When HP is below 70%, CRIT Rate increases by an additional 24%.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "Berserker_4",
+ maxStack: 1,
+ stats: {
+ crit_rate: 24,
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/BlizzardStrayer/BlizzardStrayer.js b/src/Data/Artifacts/BlizzardStrayer/BlizzardStrayer.js
index c0d08c309a..fd5d02c0f6 100644
--- a/src/Data/Artifacts/BlizzardStrayer/BlizzardStrayer.js
+++ b/src/Data/Artifacts/BlizzardStrayer/BlizzardStrayer.js
@@ -26,7 +26,23 @@ let artifact = {//Icebreaker
},
4: {
text: "When a character attacks an enemy affected by Cryo, their CRIT Rate is increased by 20%. If the enemy is Frozen, CRIT Rate is increased by an additional 20%",
- stats: {}
+ conditional: [{
+ type: "artifact",
+ sourceKey: "BlizzardStrayer_4",
+ condition: "Enemy affected by Cryo",
+ maxStack: 1,
+ stats: {
+ crit_rate: 20,
+ }
+ }, {
+ type: "artifact",
+ sourceKey: "BlizzardStrayer_4",
+ condition: "Frozen Enemy",
+ maxStack: 1,
+ stats: {
+ crit_rate: 40,
+ }
+ }]
}
}
}
diff --git a/src/Data/Artifacts/BloodstainedChivalry/BloodstainedChivalry.js b/src/Data/Artifacts/BloodstainedChivalry/BloodstainedChivalry.js
index 215c798a85..d41e86ec15 100644
--- a/src/Data/Artifacts/BloodstainedChivalry/BloodstainedChivalry.js
+++ b/src/Data/Artifacts/BloodstainedChivalry/BloodstainedChivalry.js
@@ -4,7 +4,7 @@ import sands from './Item_Bloodstained_Final_Hour.png'
import goblet from './Item_Bloodstained_Chevalier\'s_Goblet.png'
import circlet from './Item_Bloodstained_Iron_Mask.png'
let artifact = {
- name: "Bloodstained Chivalry", rarity: [4, 5],
+ name: "Bloodstained Chivalry", rarity: [4, 5],
pieces: {
flower: "Bloodstained Flower of Iron",
plume: "Bloodstained Black Plume",
@@ -26,7 +26,15 @@ let artifact = {
},
4: {
text: "After defeating an opponent, increases Charged Attack DMG by 50%, and reduces its Stamina cost to 0 for 10s.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "BloodstainedChivalry_4",
+ maxStack: 1,
+ stats: {
+ char_atk_dmg: 50,
+ stamina_dec: 100,
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/BraveHeart/BraveHeart.js b/src/Data/Artifacts/BraveHeart/BraveHeart.js
index b5dc6a4af7..74dba8fce1 100644
--- a/src/Data/Artifacts/BraveHeart/BraveHeart.js
+++ b/src/Data/Artifacts/BraveHeart/BraveHeart.js
@@ -26,7 +26,14 @@ let artifact = {
},
4: {
text: "Increases DMG by 30% against enemies with more than 50% HP.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "BraveHeart_4",
+ maxStack: 1,
+ stats: {
+ dmg: 30,
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/CrimsonWitchOfFlames/CrimsonWitchOfFlames.js b/src/Data/Artifacts/CrimsonWitchOfFlames/CrimsonWitchOfFlames.js
index 5831a376aa..e5733adc5f 100644
--- a/src/Data/Artifacts/CrimsonWitchOfFlames/CrimsonWitchOfFlames.js
+++ b/src/Data/Artifacts/CrimsonWitchOfFlames/CrimsonWitchOfFlames.js
@@ -26,7 +26,20 @@ let artifact = {
},
4: {
text: "Increases Overloaded and Burning DMG by 40%. Increases Vaporize and Melt DMG by 15%. Using an Elemental Skill increases 2-Piece Set effects by 50% for 10s. Max 3 stacks.",
- stats: {}
+ stats: {
+ overloaded_dmg: 40,
+ burning_dmg: 40,
+ vaporize_dmg: 15,
+ melt_dmg: 15,
+ },
+ conditional: {
+ type: "artifact",
+ sourceKey: "CrimsonWitchOfFlames_4",
+ maxStack: 3,
+ stats: {
+ pyro_ele_dmg: 15
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/DefendersWill/DefendersWill.js b/src/Data/Artifacts/DefendersWill/DefendersWill.js
index 7cb99c2b64..548b6a8493 100644
--- a/src/Data/Artifacts/DefendersWill/DefendersWill.js
+++ b/src/Data/Artifacts/DefendersWill/DefendersWill.js
@@ -26,7 +26,57 @@ let artifact = {
},
4: {
text: "Increases Elemental RES by 30% for each element present in the party.",
- stats: {}
+ conditional: [//TODO all party conditional
+ {
+ type: "artifact",
+ condition: "Anemo",
+ sourceKey: "DefendersWill_4",
+ maxStack: 1,
+ stats: {
+ aneme_ele_res: 30
+ }
+ }, {
+ type: "artifact",
+ condition: "Geo",
+ sourceKey: "DefendersWill_4",
+ maxStack: 1,
+ stats: {
+ geo_ele_res: 30
+ }
+ }, {
+ type: "artifact",
+ condition: "Electro",
+ sourceKey: "DefendersWill_4",
+ maxStack: 1,
+ stats: {
+ electro_ele_res: 30
+ }
+ }, {
+ type: "artifact",
+ condition: "Hydro",
+ sourceKey: "DefendersWill_4",
+ maxStack: 1,
+ stats: {
+ hydro_ele_res: 30
+ }
+ }, {
+ type: "artifact",
+ condition: "pyro",
+ sourceKey: "DefendersWill_4",
+ maxStack: 1,
+ stats: {
+ pyro_ele_res: 30
+ }
+ }, {
+ type: "artifact",
+ condition: "Cryo",
+ sourceKey: "DefendersWill_4",
+ maxStack: 1,
+ stats: {
+ cryo_ele_res: 30
+ }
+ },
+ ]
}
}
}
diff --git a/src/Data/Artifacts/Gambler/Gambler.js b/src/Data/Artifacts/Gambler/Gambler.js
index 1100870035..d029aa55ce 100644
--- a/src/Data/Artifacts/Gambler/Gambler.js
+++ b/src/Data/Artifacts/Gambler/Gambler.js
@@ -26,7 +26,14 @@ let artifact = {
},
4: {
text: "Defeating an enemy has 100% chance to remove Elemental Skill CD. Can only occur once every 15s.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "Gambler_4",
+ maxStack: 1,
+ stats: {
+ skill_cd_red: 100,
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/GladiatorsFinale/GladiatorsFinale.js b/src/Data/Artifacts/GladiatorsFinale/GladiatorsFinale.js
index 41b34e472a..cb664bb31e 100644
--- a/src/Data/Artifacts/GladiatorsFinale/GladiatorsFinale.js
+++ b/src/Data/Artifacts/GladiatorsFinale/GladiatorsFinale.js
@@ -26,7 +26,14 @@ let artifact = {
},
4: {
text: "If the wielder of this artifact set uses a Sword, Claymore or Polearm, increases their Normal Attack DMG by 35%.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "GladiatorsFinale_4",
+ maxStack: 1,
+ stats: {
+ norm_atk_dmg: 35
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/HeartOfDepth/HeartOfDepth.js b/src/Data/Artifacts/HeartOfDepth/HeartOfDepth.js
index c1ca5d4c85..f3e015d440 100644
--- a/src/Data/Artifacts/HeartOfDepth/HeartOfDepth.js
+++ b/src/Data/Artifacts/HeartOfDepth/HeartOfDepth.js
@@ -26,7 +26,15 @@ let artifact = {//Ocean Conqueror
},
4: {
text: "After using Elemental Skill, increases Normal Attack and Charged Attack DMG by 30% for 15s",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "HeartOfDepth_4",
+ maxStack: 1,
+ stats: {
+ norm_atk_dmg: 30,
+ char_atk_dmg: 30
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/Instructor/Instructor.js b/src/Data/Artifacts/Instructor/Instructor.js
index 0a2007cf3f..40bc99b1c7 100644
--- a/src/Data/Artifacts/Instructor/Instructor.js
+++ b/src/Data/Artifacts/Instructor/Instructor.js
@@ -26,7 +26,14 @@ let artifact = {
},
4: {
text: "After using Elemental Skill, increases all party members' Elemental Mastery by 120 for 8s.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "Instructor_4",
+ maxStack: 1,
+ stats: {
+ ele_mas: 120,//TODO all party conditional
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/Lavawalker/Lavawalker.js b/src/Data/Artifacts/Lavawalker/Lavawalker.js
index 9d6181be53..7e222d4833 100644
--- a/src/Data/Artifacts/Lavawalker/Lavawalker.js
+++ b/src/Data/Artifacts/Lavawalker/Lavawalker.js
@@ -26,7 +26,14 @@ let artifact = {
},
4: {
text: "Increases DMG against enemies that are Burning or affected by Pyro by 35%.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "Lavawalker_4",
+ maxStack: 1,
+ stats: {
+ dmg: 35,
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/LuckyDog/LuckyDog.js b/src/Data/Artifacts/LuckyDog/LuckyDog.js
index d5dd69a696..f1ce55ab8d 100644
--- a/src/Data/Artifacts/LuckyDog/LuckyDog.js
+++ b/src/Data/Artifacts/LuckyDog/LuckyDog.js
@@ -26,7 +26,6 @@ let artifact = {
},
4: {
text: "Picking up Mora restores 300 HP.",
- stats: {}
}
}
}
diff --git a/src/Data/Artifacts/MaidenBeloved/MaidenBeloved.js b/src/Data/Artifacts/MaidenBeloved/MaidenBeloved.js
index 35e6e5277f..0c82ff4faf 100644
--- a/src/Data/Artifacts/MaidenBeloved/MaidenBeloved.js
+++ b/src/Data/Artifacts/MaidenBeloved/MaidenBeloved.js
@@ -26,7 +26,14 @@ let artifact = {
},
4: {
text: "Using an Elemental Skill or Burst increases healing received by all party members by 20% for 10s.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "MaidenBeloved_4",
+ maxStack: 1,
+ stats: {
+ inc_heal: 20,//TODO party conditional
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/MartialArtist/MartialArtist.js b/src/Data/Artifacts/MartialArtist/MartialArtist.js
index 361db87e4e..10c49a8e0e 100644
--- a/src/Data/Artifacts/MartialArtist/MartialArtist.js
+++ b/src/Data/Artifacts/MartialArtist/MartialArtist.js
@@ -29,7 +29,15 @@ let artifact = {
},
4: {
text: "After using Elemental Skill, increases Normal Attack and Charged Attack DMG by 25% for 8s.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "MartialArtist_4",
+ maxStack: 1,
+ stats: {
+ norm_atk_dmg: 25,
+ char_atk_dmg: 25
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/NoblesseOblige/NoblesseOblige.js b/src/Data/Artifacts/NoblesseOblige/NoblesseOblige.js
index 4726fb4b7a..95fe1f41e6 100644
--- a/src/Data/Artifacts/NoblesseOblige/NoblesseOblige.js
+++ b/src/Data/Artifacts/NoblesseOblige/NoblesseOblige.js
@@ -26,7 +26,14 @@ let artifact = {
},
4: {
text: "Using an Elemental Burst increase all party members' ATK by 20% for 12s. This effect cannot stack.",
- stats: {}
+ conditional: {//TODO party conditional
+ type: "artifact",
+ sourceKey: "NoblesseOblige_4",
+ maxStack: 1,
+ stats: {
+ atk_: 20,
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/PrayersForDestiny/PrayersForDestiny.js b/src/Data/Artifacts/PrayersForDestiny/PrayersForDestiny.js
index d7f4bff3d7..25b33cac34 100644
--- a/src/Data/Artifacts/PrayersForDestiny/PrayersForDestiny.js
+++ b/src/Data/Artifacts/PrayersForDestiny/PrayersForDestiny.js
@@ -10,7 +10,7 @@ let artifact = {
sets: {
1: {
text: "Affected by Hydro for 40% less time.",
- stats: {}
+ stats: {}//TODO element affect reduction stat
}
}
}
diff --git a/src/Data/Artifacts/PrayersForIllumination/PrayersForIllumination.js b/src/Data/Artifacts/PrayersForIllumination/PrayersForIllumination.js
index a6940c8aea..49beeba9f9 100644
--- a/src/Data/Artifacts/PrayersForIllumination/PrayersForIllumination.js
+++ b/src/Data/Artifacts/PrayersForIllumination/PrayersForIllumination.js
@@ -10,7 +10,7 @@ let artifact = {
sets: {
1: {
text: "Affected by Pyro for 40% less time.",
- stats: {}
+ stats: {}//TODO element affect reduction stat
}
}
}
diff --git a/src/Data/Artifacts/PrayersForWisdom/PrayersForWisdom.js b/src/Data/Artifacts/PrayersForWisdom/PrayersForWisdom.js
index b6154cb711..e276247c05 100644
--- a/src/Data/Artifacts/PrayersForWisdom/PrayersForWisdom.js
+++ b/src/Data/Artifacts/PrayersForWisdom/PrayersForWisdom.js
@@ -10,7 +10,7 @@ let artifact = {
sets: {
1: {
text: "Affected by Electro for 40% less time.",
- stats: {}
+ stats: {}//TODO element affect reduction stat
}
}
}
diff --git a/src/Data/Artifacts/PrayersToSpringtime/PrayersToSpringtime.js b/src/Data/Artifacts/PrayersToSpringtime/PrayersToSpringtime.js
index bfe4b899dc..bb59ea1b34 100644
--- a/src/Data/Artifacts/PrayersToSpringtime/PrayersToSpringtime.js
+++ b/src/Data/Artifacts/PrayersToSpringtime/PrayersToSpringtime.js
@@ -10,7 +10,7 @@ let artifact = {
sets: {
1: {
text: "Affected by Cryo for 40% less time.",
- stats: {}
+ stats: {}//TODO element affect reduction stat
}
}
}
diff --git a/src/Data/Artifacts/ResolutionOfSojourner/ResolutionOfSojourner.js b/src/Data/Artifacts/ResolutionOfSojourner/ResolutionOfSojourner.js
index ad27e527a8..15753874e8 100644
--- a/src/Data/Artifacts/ResolutionOfSojourner/ResolutionOfSojourner.js
+++ b/src/Data/Artifacts/ResolutionOfSojourner/ResolutionOfSojourner.js
@@ -26,7 +26,7 @@ let artifact = {
},
4: {
text: "Increases Charged Attack CRIT Rate by 30%.",
- stats: {}
+ stats: { char_atk_crit_rate: 30 }
}
}
}
diff --git a/src/Data/Artifacts/RetracingBolide/RetracingBolide.js b/src/Data/Artifacts/RetracingBolide/RetracingBolide.js
index 87332eb375..02132b9bc1 100644
--- a/src/Data/Artifacts/RetracingBolide/RetracingBolide.js
+++ b/src/Data/Artifacts/RetracingBolide/RetracingBolide.js
@@ -26,7 +26,15 @@ let artifact = {
},
4: {
text: "Gain an additional 40% Normal and Charged Attack DMG while under the protection of a shield.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "RetracingBolide_4",
+ maxStack: 1,
+ stats: {
+ norm_atk_dmg: 40,
+ char_atk_dmg: 40
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/Scholar/Scholar.js b/src/Data/Artifacts/Scholar/Scholar.js
index 45d1100813..8353a902f1 100644
--- a/src/Data/Artifacts/Scholar/Scholar.js
+++ b/src/Data/Artifacts/Scholar/Scholar.js
@@ -26,7 +26,6 @@ let artifact = {
},
4: {
text: "Gaining Elemental Particles or Orbs gives 3 Energy to all party members who have a bow or a catalyst equipped. Can only occur once every 3s.",
- stats: {}
}
}
}
diff --git a/src/Data/Artifacts/TheExile/TheExile.js b/src/Data/Artifacts/TheExile/TheExile.js
index d408f13871..9a931f8047 100644
--- a/src/Data/Artifacts/TheExile/TheExile.js
+++ b/src/Data/Artifacts/TheExile/TheExile.js
@@ -26,7 +26,6 @@ let artifact = {
},
4: {
text: "Using an Elemental Burst regenerates 2 Energy for other party members every 2s for 6s. This effect cannot stack.",
- stats: {}
}
}
}
diff --git a/src/Data/Artifacts/ThunderingFury/ThunderingFury.js b/src/Data/Artifacts/ThunderingFury/ThunderingFury.js
index 6f6476ec35..ff13287708 100644
--- a/src/Data/Artifacts/ThunderingFury/ThunderingFury.js
+++ b/src/Data/Artifacts/ThunderingFury/ThunderingFury.js
@@ -25,7 +25,11 @@ let artifact = {
},
4: {
text: "Increases damage caused by Overloaded, Electro-Charged, and Superconduct DMG by 40%. Triggering such effects decreases Elemental Skill CD by 1s. Can only occur once every 0.8s.",
- stats: {}
+ stats: {
+ overloaded_dmg: 40,
+ electro_charged_dmg: 40,
+ superconduct_dmg: 40
+ }
}
}
}
diff --git a/src/Data/Artifacts/Thundersoother/Thundersoother.js b/src/Data/Artifacts/Thundersoother/Thundersoother.js
index aa266be6cf..90d7c3502f 100644
--- a/src/Data/Artifacts/Thundersoother/Thundersoother.js
+++ b/src/Data/Artifacts/Thundersoother/Thundersoother.js
@@ -26,7 +26,14 @@ let artifact = {
},
4: {
text: "Increases DMG against enemies affected by Electro by 35%.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "Thundersoother_4",
+ maxStack: 1,
+ stats: {
+ dmg: 35,
+ }
+ }
}
}
}
diff --git a/src/Data/Artifacts/TinyMiracle/TinyMiracle.js b/src/Data/Artifacts/TinyMiracle/TinyMiracle.js
index 116c78c43b..25d2f59a13 100644
--- a/src/Data/Artifacts/TinyMiracle/TinyMiracle.js
+++ b/src/Data/Artifacts/TinyMiracle/TinyMiracle.js
@@ -33,7 +33,57 @@ let artifact = {
},
4: {
text: "Incoming elemental DMG increases corresponding Elemental RES by 30% for 10s. Can only occur once every 10s.",
- stats: {}
+ conditional: [
+ {
+ type: "artifact",
+ condition: "Anemo",
+ sourceKey: "TinyMiracle_4",
+ maxStack: 1,
+ stats: {
+ anemo_ele_res: 30
+ }
+ }, {
+ type: "artifact",
+ condition: "Geo",
+ sourceKey: "TinyMiracle_4",
+ maxStack: 1,
+ stats: {
+ geo_ele_res: 30
+ }
+ }, {
+ type: "artifact",
+ condition: "Electro",
+ sourceKey: "TinyMiracle_4",
+ maxStack: 1,
+ stats: {
+ electro_ele_res: 30
+ }
+ }, {
+ type: "artifact",
+ condition: "Hydro",
+ sourceKey: "TinyMiracle_4",
+ maxStack: 1,
+ stats: {
+ hydro_ele_res: 30
+ }
+ }, {
+ type: "artifact",
+ condition: "pyro",
+ sourceKey: "TinyMiracle_4",
+ maxStack: 1,
+ stats: {
+ pyro_ele_res: 30
+ }
+ }, {
+ type: "artifact",
+ condition: "Cryo",
+ sourceKey: "TinyMiracle_4",
+ maxStack: 1,
+ stats: {
+ cryo_ele_res: 30
+ }
+ },
+ ]
}
}
}
diff --git a/src/Data/Artifacts/TravelingDoctor/TravelingDoctor.js b/src/Data/Artifacts/TravelingDoctor/TravelingDoctor.js
index 6e138de948..cdb29bd65b 100644
--- a/src/Data/Artifacts/TravelingDoctor/TravelingDoctor.js
+++ b/src/Data/Artifacts/TravelingDoctor/TravelingDoctor.js
@@ -3,6 +3,7 @@ import plume from './Item_Traveling_Doctor\'s_Owl_Feather.png'
import sands from './Item_Traveling_Doctor\'s_Pocket_Watch.png'
import goblet from './Item_Traveling_Doctor\'s_Medicine_Pot.png'
import circlet from './Item_Traveling_Doctor\'s_Handkerchief.png'
+import WeaponPercent from '../../../Components/WeaponPercent'
let artifact = {
name: "Traveling Doctor", rarity: [3],
pieces: {
@@ -25,8 +26,7 @@ let artifact = {
stats: { inc_heal: 20 }
},
4: {
- text: "Using Elemental Burst restores 20% HP.",
- stats: {}
+ text: (charFinalStats) => Using Elemental Burst restores 20% HP{WeaponPercent(20, charFinalStats.hp)}.,
}
}
}
diff --git a/src/Data/Artifacts/ViridescentVenerer/ViridescentVenerer.js b/src/Data/Artifacts/ViridescentVenerer/ViridescentVenerer.js
index fb4db496b4..0036a82cda 100644
--- a/src/Data/Artifacts/ViridescentVenerer/ViridescentVenerer.js
+++ b/src/Data/Artifacts/ViridescentVenerer/ViridescentVenerer.js
@@ -25,7 +25,7 @@ let artifact = {
},
4: {
text: "Increases Swirl DMG by 60%. Decreases opponent's Elemental RES to the element infused in the Swirl by 40% for 10s.",
- stats: {}
+ stats: { swirl_dmg: 60 }//TODO enemy resistance
}
}
}
diff --git a/src/Data/Artifacts/WanderersTroupe/WanderersTroupe.js b/src/Data/Artifacts/WanderersTroupe/WanderersTroupe.js
index 3486a5cb46..d2e2257628 100644
--- a/src/Data/Artifacts/WanderersTroupe/WanderersTroupe.js
+++ b/src/Data/Artifacts/WanderersTroupe/WanderersTroupe.js
@@ -28,7 +28,14 @@ let artifact = {
},
4: {
text: "Increases Charged Attack DMG by 35% if the character uses a Catalyst or Bow.",
- stats: {}
+ conditional: {
+ type: "artifact",
+ sourceKey: "WanderersTroupe_4",
+ maxStack: 1,
+ stats: {
+ char_atk_dmg: 35,
+ }
+ }
}
}
}
diff --git a/src/Data/Weapons/Bow/SacrificialBow.js b/src/Data/Weapons/Bow/SacrificialBow.js
index 3c871a9185..a44a13e914 100644
--- a/src/Data/Weapons/Bow/SacrificialBow.js
+++ b/src/Data/Weapons/Bow/SacrificialBow.js
@@ -12,5 +12,13 @@ const weapon = {
subStatKey: "ener_rech",
sub: [6.7, 7.7, 9.1, 10.4, 11.8, 11.8, 13.1, 14.5, 15.8, 17.2, 17.2, 18.5, 19.9, 19.9, 21.2, 22.6, 22.6, 23.9, 25.2, 25.2, 26.6, 27.9, 27.9, 29.3, 30.6],
},
+ conditional: {
+ type: "weapon",
+ sourceKey: "SacrificialBow",
+ maxStack: 1,
+ stats: () => ({
+ red_cd: 100
+ })
+ }
}
export default weapon
\ No newline at end of file
diff --git a/src/Data/Weapons/Catalyst/SacrificialFragments.js b/src/Data/Weapons/Catalyst/SacrificialFragments.js
index f4193fd69a..116865c10b 100644
--- a/src/Data/Weapons/Catalyst/SacrificialFragments.js
+++ b/src/Data/Weapons/Catalyst/SacrificialFragments.js
@@ -12,5 +12,13 @@ const weapon = {
subStatKey: "ele_mas",
sub: [48, 56, 65, 75, 85, 85, 95, 104, 114, 124, 124, 133, 143, 143, 153, 162, 162, 172, 182, 182, 191, 201, 201, 211, 221],
},
+ conditional: {
+ type: "weapon",
+ sourceKey: "SacrificialFragments",
+ maxStack: 1,
+ stats: () => ({
+ red_cd: 100
+ })
+ }
}
export default weapon
\ No newline at end of file
diff --git a/src/Data/Weapons/Claymore/SacrificialGreatsword.js b/src/Data/Weapons/Claymore/SacrificialGreatsword.js
index 72f0c9d028..8a2c9e234f 100644
--- a/src/Data/Weapons/Claymore/SacrificialGreatsword.js
+++ b/src/Data/Weapons/Claymore/SacrificialGreatsword.js
@@ -11,6 +11,14 @@ const weapon = {
main: [44, 59, 79, 99, 119, 144, 165, 185, 205, 226, 252, 273, 293, 319, 340, 361, 387, 408, 429, 455, 476, 497, 523, 544, 565],
subStatKey: "ener_rech",
sub: [6.7, 7.7, 9.1, 10.4, 11.8, 11.8, 13.1, 14.5, 15.8, 17.2, 17.2, 18.5, 19.9, 19.9, 21.2, 22.6, 22.6, 23.9, 25.2, 25.2, 26.6, 27.9, 27.9, 29.3, 30.6],
+ },
+ conditional: {
+ type: "weapon",
+ sourceKey: "SacrificialGreatsword",
+ maxStack: 1,
+ stats: () => ({
+ red_cd: 100
+ })
}
}
export default weapon
\ No newline at end of file
diff --git a/src/Data/Weapons/Sword/SacrificialSword.js b/src/Data/Weapons/Sword/SacrificialSword.js
index aedeca9cb2..a46dde15da 100644
--- a/src/Data/Weapons/Sword/SacrificialSword.js
+++ b/src/Data/Weapons/Sword/SacrificialSword.js
@@ -11,6 +11,14 @@ const weapon = {
main: [41, 54, 69, 84, 99, 125, 140, 155, 169, 184, 210, 224, 238, 264, 278, 293, 319, 333, 347, 373, 387, 401, 427, 440, 454],
subStatKey: "ener_rech",
sub: [13.3, 15.5, 18.2, 20.9, 23.6, 23.6, 26.3, 28.9, 31.6, 34.3, 34.3, 37, 39.7, 39.7, 42.4, 45.1, 45.1, 47.8, 50.5, 50.5, 53.2, 55.9, 55.9, 58.6, 61.3],
+ },
+ conditional: {
+ type: "weapon",
+ sourceKey: "SacrificialSword",
+ maxStack: 1,
+ stats: () => ({
+ red_cd: 100
+ })
}
}
export default weapon
\ No newline at end of file
diff --git a/src/Home/art_editor.png b/src/Home/art_editor.png
index 13594ee0ab..86e1230218 100644
Binary files a/src/Home/art_editor.png and b/src/Home/art_editor.png differ
diff --git a/src/Stat.js b/src/Stat.js
index 91f4f6ad3b..1169aca59b 100644
--- a/src/Stat.js
+++ b/src/Stat.js
@@ -72,18 +72,33 @@ const StatData = {
inc_heal: { name: "Incoming Healing Bonus", unit: "%" },
pow_shield: { name: "Powerful Shield", unit: "%" },
red_cd: { name: "Reduce CD", unit: "%" },
- //helper stats
+ //auto
norm_atk_dmg: { name: "Normal Attack DMG", unit: "%" },
char_atk_dmg: { name: "Charged Attack DMG", unit: "%" },
+ norm_atk_crit_rate: { name: "Nomral Attack CRIT Rate", unit: "%" },
+ char_atk_crit_rate: { name: "Charged Attack CRIT Rate", unit: "%" },
+ //skill
skill_dmg: { name: "Ele. Skill DMG", unit: "%" },
burst_dmg: { name: "Ele. Burst DMG", unit: "%" },
skill_crit_rate: { name: "Ele. Skill CRIT Rate", unit: "%" },
burst_crit_rate: { name: "Ele. Burst CRIT Rate", unit: "%" },
+ skill_cd_red: { name: "Ele. Skill CD Red.", unit: "%" },
+ burst_cd_red: { name: "Ele. Burst CD Red.", unit: "%" },
+
crit_multi: { name: "Crit Multiplier" },
dmg: { name: "All DMG", unit: "%" },//general all damage increase
move_spd: { name: "Movement SPD", unit: "%" },
atk_spd: { name: "ATK SPD", unit: "%" },
- weakspot_dmg: { name: "Weakspot DMG", unit: "%" }
+ weakspot_dmg: { name: "Weakspot DMG", unit: "%" },
+ stamina_dec: { name: "Stamina Consmption Dec.", unit: "%" },
+ //elemental
+ overloaded_dmg: { name: "Overloaded DMG", unit: "%" },
+ electro_charged_dmg: { name: "Electro-Charged DMG", unit: "%" },
+ superconduct_dmg: { name: "Superconduct DMG", unit: "%" },
+ burning_dmg: { name: "Overloaded DMG", unit: "%" },
+ vaporize_dmg: { name: "Vaporize DMG", unit: "%" },
+ melt_dmg: { name: "Melt DMG", unit: "%" },
+ swirl_dmg:{ name: "Swirl DMG", unit: "%" },
};
export {
diff --git a/src/Util/ArtifactConditionals.js b/src/Util/ArtifactConditionals.js
new file mode 100644
index 0000000000..b4c44ba2ba
--- /dev/null
+++ b/src/Util/ArtifactConditionals.js
@@ -0,0 +1,23 @@
+export default class ArtifactConditionals {
+ constructor() { if (this instanceof ArtifactConditionals) throw Error('A static class cannot be instantiated.'); }
+ static getConditionalNum(artifactConditionals, setKey, setNumKey) {
+ if (artifactConditionals)
+ return artifactConditionals.find(charConditional =>
+ charConditional.setKey === setKey && charConditional.setNumKey === setNumKey)?.conditionalNum || 0
+ }
+ static setConditional(artifactConditionals, setKey, setNumKey, conditionalNum) {
+ if (!artifactConditionals) artifactConditionals = []
+ let index = artifactConditionals.findIndex(artCond => artCond.setKey === setKey && artCond.setNumKey === setNumKey)
+ if (!conditionalNum && index >= 0) {
+ //setting conditionalNum to 0 deletes the element
+ artifactConditionals.splice(index, 1);
+ } else {
+ let newArtCond = { setKey, setNumKey, conditionalNum }
+ if (index >= 0)
+ artifactConditionals[index] = newArtCond
+ else
+ artifactConditionals.push(newArtCond)
+ }
+ return artifactConditionals
+ }
+}
\ No newline at end of file
diff --git a/src/Util.js b/src/Util/Util.js
similarity index 100%
rename from src/Util.js
rename to src/Util/Util.js
diff --git a/src/Weapon/Weapon.js b/src/Weapon/Weapon.js
index 0141490766..433ccabfc3 100644
--- a/src/Weapon/Weapon.js
+++ b/src/Weapon/Weapon.js
@@ -1,5 +1,5 @@
import { WeaponData, LevelNameData, WeaponLevelKeys, WeaponTypeData } from '../Data/WeaponData.js'
-import { clamp } from '../Util.js';
+import { clamp } from '../Util/Util.js';
export default class Weapon {
//do not instantiate.
constructor() { if (this instanceof Weapon) throw Error('A static class cannot be instantiated.'); }
@@ -34,7 +34,7 @@ export default class Weapon {
if (Array.isArray(conditional)) {
//multiple conditionals
let selectedConditionalNum = conditionalNum
- let selectedConditional
+ let selectedConditional = null
for (const curConditional of conditional) {
if (selectedConditionalNum > curConditional.maxStack) selectedConditionalNum -= curConditional.maxStack
else {