//import './App.css'; Old CSS
import './reset.css'; // Generic reset
import './style.css'; // The new new
import React, {useState,useEffect,useRef,useReducer} from 'react';
import useGlobalKeyDown from 'react-global-key-down-hook'
import Modal from 'react-modal'
import Tooltip from "react-simple-tooltip" //Mess with all tooltip props here: https://cedricdelpoux.github.io/react-simple-tooltip/
import {XSquare, XSquareFill, PlusCircle} from 'react-bootstrap-icons'
import {
HashRouter,
Switch,
Route
} from "react-router-dom";
import { HashLink as Link } from 'react-router-hash-link';
import TestHeader from './TestHeader'; // Test Header!
import TestPanel from './TestPanel'; // Dudley's Test Panel
const axios = require('axios');
const parse = require('csv-parse/lib/sync')
const BACKEND_URL = process.env.REACT_APP_GITPOD_WORKSPACE_URL||process.env.REACT_APP_BACKEND_URL||'https://projectdivar.com:4504'; //You can specify a .env file locally with REACT_APP_BACKEND_URL defining a URL to retrieve data from.
/*
Damage types
const MELEE_DMG = 0
const RANGE_DMG = 1
const TECH_DMG = 2
Art properties
const NORMAL = 0
const PHOTON_ART = 1
const WEAPON_ACTION = 2
const STEP_COUNTER = 3
const PARRY_COUNTER = 4
//NOT USED YET*/
function Col(p) {
return
{p.children}
}
function Box(p) {
return <>
>
}
function EditBox(p) {
useEffect(()=>{
var timer1 = setTimeout(()=>{document.getElementById("editBox").focus()},100)
return () => {
clearTimeout(timer1);
};
})
return {
if (e.key==="Enter") {p.setEdit(false)}
else if (e.key==="Escape") {p.setEdit(false)}
}} maxLength={p.maxlength?p.maxlength:20} onBlur={()=>{p.setEdit(false)}} value={p.value} onChange={(f)=>{f.currentTarget.value.length>0?p.setName(f.currentTarget.value):p.setName(p.originalName)}}>
}
function EditableBox(p) {
const [edit,setEdit] = useState(false)
useEffect(()=>{
if (p.callback) {
p.callback()
}
},[edit,p])
return <>
{setEdit(true)}}>
{edit?
:<>{p.data}>}
>
}
const CLASSES = {
HUNTER:{
name:"Hunter",
icon:process.env.PUBLIC_URL+"/icons/UINGSClassHu.png"
},
FIGHTER:{
name:"Fighter",
icon:process.env.PUBLIC_URL+"/icons/UINGSClassFi.png"
},
RANGER:{
name:"Ranger",
icon:process.env.PUBLIC_URL+"/icons/UINGSClassRa.png"
},
GUNNER:{
name:"Gunner",
icon:process.env.PUBLIC_URL+"/icons/UINGSClassGu.png"
},
FORCE:{
name:"Force",
icon:process.env.PUBLIC_URL+"/icons/UINGSClassFo.png"
},
TECHTER:{
name:"Techter",
icon:process.env.PUBLIC_URL+"/icons/UINGSClassTe.png"
}
}
const EFFECTS = {
"Food Boost Effect":{
perks:[
"[Meat] Potency +10.0%",
"[Crisp] Potency to Weak Point +5.0%"
],
icon:process.env.PUBLIC_URL+"/icons/TQ8EBW2.png"
},
"Shifta / Deband":{
perks:[
"Potency +5.0%",
"Damage Resistance +10.0%"
],
icon:process.env.PUBLIC_URL+"/icons/VIYYNIm.png"
},
"Region Mag Boost":{
perks:[
"Potency +5.0%",
],
icon:process.env.PUBLIC_URL+"/icons/N6M74Qr.png"
},
}
const EQUIPMENT = {
"Ophistia Shooter":{
icon:process.env.PUBLIC_URL+"/icons/uc1iBck.png"
},
"Klauzdyne":{
icon:process.env.PUBLIC_URL+"/icons/uldt9lR.png"
},
"Klauznum":{
icon:process.env.PUBLIC_URL+"/icons/F0t58xP.png"
},
"Klauzment":{
icon:process.env.PUBLIC_URL+"/icons/20M6Z7t.png"
}
}
const ABILITIES = {
"Wellspring Unit Lv.3":{
icon:process.env.PUBLIC_URL+"/icons/NGSUIItemPotentialAbility.png"
},
"Fixa Fatale Lv.5":{
icon:process.env.PUBLIC_URL+"/icons/UINGSItemPresetAbility.png"
}
}
const ABILITY_DEFAULT_ICON = process.env.PUBLIC_URL+"/icons/UINGSItemSpecialAbility.png"
/**
* Hook that alerts clicks outside of the passed ref
*/
function useOutsideAlerter(ref,setEdit) {
useEffect(() => {
/**
* Alert if clicked on outside of element
*/
function handleClickOutside(event) {
if (ref.current && !ref.current.contains(event.target)) {
setEdit(false)
}
}
// Bind the event listener
document.addEventListener("mousedown", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref,setEdit]);
}
function Class(p) {
const class_obj = CLASSES[p.name]
return <>
{class_obj.name}>
}
function ClassSelector(p){
const wrapperRef = useRef(null);
useOutsideAlerter(wrapperRef,p.setEdit);
return
Class Selector
{Object.keys(CLASSES).map((cl,i)=>{
return
})}
}
function EditableClass(p){
const [edit,setEdit] = useState(false)
return <>{setEdit(!edit)}}>
{edit&&}
>
}
function Table(p) {
return
{p.children}
}
function MainBox(p) {
return
}>Lv.20
>}>Lv.15
}
function StatsBox(p) {
return
+{p.weaponUp1*100}%>}>
+{p.weaponUp2*100}%
+{p.weaponUp3*100}%>}>
}
function EffectListing(p) {
return {p.name}
{EFFECTS[p.name].perks.map((perk,i)=>{
return
{perk}
})}
}
function PageControlButton(p) {
return {p.setCurrentPage(p.page)}} className={(p.currentPage===p.page)?"selected":""}>{p.pageName?p.pageName:p.page}
}
function PageControl(p) {
var pages = []
for (var i=0;i)
}
return
{pages.map((page,i)=>{return {page}})}
}
function EffectsBox(p) {
const [currentPage,setCurrentPage]=useState(1)
return
Effect Name
{
currentPage===1?
{p.effectList.map((ef,i)=>{
return
})}
:
<>>
}
}
function EquipBox(p) {
return
Weapon
![]({EQUIPMENT[p.weapon].icon})
{p.weapon}+{p.weaponEnhancementLv}
Slot 1
![]({EQUIPMENT[p.armorSlot1].icon})
{p.armorSlot1}+{p.armorSlot1EnhancementLv}
Slot 2
![]({EQUIPMENT[p.armorSlot2].icon})
{p.armorSlot2}+{p.armorSlot2EnhancementLv}
Slot 3
![]({EQUIPMENT[p.armorSlot3].icon})
{p.armorSlot3}+{p.armorSlot3EnhancementLv}
}
function EquippedWeaponBox(p) {
const [currentPage,setCurrentPage] = useState(1)
const [selectedEquip,setSelectedEquip] = useState(p.weapon)
const [selectedEquipEnhancementLv,setSelectedEquipEnhancementLv] = useState(p.weaponEnhancementLv)
const [selectedEquipAbilities,setSelectedEquipAbilities] = useState(p.weaponAbilityList)
useEffect(()=>{
switch (currentPage) {
case 2:
setSelectedEquip(p.armorSlot1)
setSelectedEquipEnhancementLv(p.armorSlot1EnhancementLv)
setSelectedEquipAbilities(p.armorSlot1AbilityList)
break;
case 3:
setSelectedEquip(p.armorSlot2)
setSelectedEquipEnhancementLv(p.armorSlot2EnhancementLv)
setSelectedEquipAbilities(p.armorSlot2AbilityList)
break;
case 4:
setSelectedEquip(p.armorSlot3)
setSelectedEquipEnhancementLv(p.armorSlot3EnhancementLv)
setSelectedEquipAbilities(p.armorSlot3AbilityList)
break;
default:{
setSelectedEquip(p.weapon)
setSelectedEquipEnhancementLv(p.weaponEnhancementLv)
setSelectedEquipAbilities(p.weaponAbilityList)
}
}
},[currentPage,p.armorSlot1,p.armorSlot1EnhancementLv,p.armorSlot1AbilityList,p.armorSlot2,p.armorSlot2EnhancementLv,p.armorSlot2AbilityList,p.armorSlot3,p.armorSlot3EnhancementLv,p.armorSlot3AbilityList,p.weapon,p.weaponEnhancementLv,p.weaponAbilityList])
return
{selectedEquip}+{selectedEquipEnhancementLv}
Ability Details
{
selectedEquipAbilities?selectedEquipAbilities.map((ability,i)=>{
return
{ability}
}):<>>
}
Properties
- Enhancement Lv. +{selectedEquipEnhancementLv}
- Multi-Weapon -
- Element -
}
function DamageBox(p) {
const [currentPage,setCurrentPage] = useState(1)
return
{
currentPage===1&&
{p.criticalHitRate*100}%
{p.criticalMultiplier*100}%
{p.midRange}
{p.critical}
{p.effective}
}
}
function ListRow(p) {
return
{p.title} |
{p.content} |
{p.children} |
}
function PopupWindow(p) {
return {p.setModalOpen(false)}} shouldFocusAfterRender={true} shouldCloseOnOverlayClick={true} shouldCloseOnEsc={true}>
{p.title}{p.setModalOpen(false)}} className="modalCloseButton"/>
{p.children}
}
function InputBox(p) {
const [value,setValue] = useState(p.value)
const [failed,setFailed] = useState(false)
const [sending,setSending] = useState(false)
function changeFunc(f){setValue(f.currentTarget.value)
if (p.callback4) {
p.callback4(f.currentTarget.value)
}}
function blurFunc(f){
if (p.callback) {
setSending(true)
setFailed(false)
p.callback(f.currentTarget.value)
.then(()=>{setFailed(false)})
.catch(()=>{setFailed(true)})
.then(()=>{setSending(false)})}
else
if (p.callback3) {
p.callback3(f.currentTarget.value)
}}
function keydownFunc(f){
if (p.callback2) {
p.callback2(f,value)
}
}
return p.data?:{keydownFunc(f)}} onChange={(f)=>{changeFunc(f)}} onBlur={(f)=>{blurFunc(f)}}/>
}
function TableEditor(p) {
const initialVals={}
function updateVals(state,update) {
if (update==='Clear') {
return initialVals
}
state[update.field]=update.value
return state
}
const [fields,setFields] = useState([])
const [data,setData] = useState([])
const [update,setUpdate] = useState(false)
const [submitVals,setSubmitVal] = useReducer(updateVals,initialVals)
const [loading,setLoading] = useState(false)
const [dependencies,setDependencies] = useState([])
const [importAllowed,setImportAllowed] = useState(false)
const [fileData,setFileData] = useState(undefined)
const [lockSubmission,setLockSubmission] = useState(false)
function SubmitBoxes() {
if (!lockSubmission) {
setLockSubmission(true)
axios.post(BACKEND_URL+p.path,submitVals)
.then(()=>{
setSubmitVal("Clear")
setUpdate(true)
})
.catch((err)=>{
alert(JSON.stringify(err.response.data))
})
.then(()=>{
setLockSubmission(false)
})
}
}
useGlobalKeyDown(()=>{
SubmitBoxes()
},['Enter'])
useEffect(()=>{
setUpdate(true)
},[p.path])
useEffect(()=>{
var promises=[]
parse(fileData,{columns:true,skip_empty_lines:true}).forEach((entry)=>{
promises.push(axios.post(BACKEND_URL+p.path,entry))
})
Promise.allSettled(promises)
.then(()=>{
setUpdate(true)
})
},[fileData,p.path])
useEffect(()=>{
for (var col of fields) {
if (col.name==="name") {
setImportAllowed(true)
break;
}
}
},[fields])
useEffect(()=>{
if (update) {
setLoading(true)
var dependency_map = {}
axios.get(BACKEND_URL+p.path)
.then((data)=>{
var cols = data.data.fields
var rows = data.data.rows
setFields(cols.filter((col,i)=>col.name!=="id"&&!(i===0&&col.name==="name")))
var promise_list = []
cols.filter((col)=>col.name!=="id"&&col.name.includes("_id")).forEach((col)=>{
promise_list.push(axios.get(BACKEND_URL+"/"+col.name.replace("_id",""))
.then((data)=>{
dependency_map[col.name]=data.data.rows.sort((a,b)=>b.id-a.id)
}))
})
setData(rows)
return Promise.allSettled(promise_list)
})
.then(()=>{
setDependencies(dependency_map)
setLoading(false)
})
setUpdate(false)
}
},[update,p.path])
return <>
{!loading?
:
}
>
}
function AdminPanel(p) {
return
Class
Class Data
Class-Weapon Compatibility
Class Skills
Class Skill Data
Weapons
Weapon Existence Data
Weapon Types
Class-Weapon Compatibility
Photon Arts
Armor
Potentials
Potential Data
Builds
Skills
Skill Types
Skill Data
Photon Arts
Class Skills
Class Skill Data
Augments
Augment Types
Enemy Data
Food
Food Multipliers
Roles
Users
Database Audit
}
function EditStatBox(p) {
const [value,setValue] = useState(p.value)
useEffect(()=>{
setValue(p.value)
},[p.value])
return <>{setValue(f.currentTarget.value);p.callback(f.currentTarget.value)}}/> ({value})
>
}
function DamageCalculator(p) {
const [augmentData,setAugmentData] = useState({})
//const [update,setUpdate] = useState(false)
useEffect(()=>{
axios.get(BACKEND_URL+"/augment")
.then((data)=>{
var augmentData = {}
data.data.rows.forEach((entry)=>{augmentData[entry.name]=entry})
setAugmentData(augmentData)
})
},[])
const character = {
weapon:{
augments:["1","2"]
},
armor1:{
augments:["2"]
},
armor2:{
augments:[]
},
armor3:{
augments:[]
}
}
useEffect(()=>{
if (Object.keys(augmentData).length>0) {
var searchFields = [{field:"variance",variable:0},{field:"mel_dmg",variable:0}]
for (var equip of [character.weapon,character.armor1,character.armor2,character.armor3]) {
for (var field of searchFields) {
for (var i=0;i{
setWeaponTotalAtk(Number(weaponBaseAtk)+Number(weaponEnhanceLvl))
},[weaponBaseAtk,weaponEnhanceLvl])
const [dmgVariance,setDmgVariance] = useState(1)
const [weaponDmgVariance,setWeaponDmgVariance] = useState(1)
const [augDmgVariance,setAugDmgVariance] = useState(1)
useEffect(()=>{
setDmgVariance(Number(weaponDmgVariance)+Number(augDmgVariance))
},[weaponDmgVariance,augDmgVariance])
const [baseAtk,setBaseAtk] = useState(100)
const [enemyDef,setEnemyDef] = useState(5)
const [multipliers,setMultipliers] = useState(1)
useEffect(()=>{
setRawDmg(((Number(weaponTotalAtk)*Number(dmgVariance))+Number(baseAtk)-Number(enemyDef))*Number(multipliers)/5)
},[weaponTotalAtk,dmgVariance,baseAtk,enemyDef,multipliers])
const [atkmult,setAtkMult] = useState(1);
const [partmult,setPartMult] = useState(1);
const [elementalWeaknessMult,setElementalWeaknessMult] = useState(1.2)
const [mainClassWeaponBoost,setMainClassWeaponBoost] = useState(1.1)
const [classSkillMult,setClassSkillMult] = useState(1)
const [equipMult,setEquipMult] = useState(1)
const [augmentEquipMult,setAugmentEquipMult] = useState(1)
const [potencyFloorEquipMult,setPotencyFloorEquipMult] = useState(1)
const [elementalWeaponEquipMult,setElementalWeaponEquipMult] = useState(1.1)
const [critMult,setCritMult] = useState(1.2)
const [appropriateDistance,setAppropriateDistance] = useState(1)
const [foodBoost,setFoodBoost] = useState(1)
const [fieldEffects,setFieldEffects] = useState(1.05)
const [statusAilments,setStatusAilments] = useState(1)
const [enemyCorrectionMult,setEnemyCorrectionMult] = useState(1)
const [highLevelEnemy,setHighLevelEnemy] = useState(1)
useEffect(()=>{
setMultipliers(Number(atkmult)*Number(partmult)*Number(elementalWeaknessMult)*Number(mainClassWeaponBoost)*Number(classSkillMult)*Number(equipMult)*Number(augmentEquipMult)*Number(potencyFloorEquipMult)*Number(elementalWeaponEquipMult)*Number(critMult)*Number(appropriateDistance)*Number(foodBoost)*Number(fieldEffects)*Number(statusAilments)*Number(enemyCorrectionMult)*Number(highLevelEnemy))
},[atkmult,partmult,elementalWeaknessMult,mainClassWeaponBoost,classSkillMult,equipMult,augmentEquipMult,potencyFloorEquipMult,elementalWeaponEquipMult,critMult,appropriateDistance,foodBoost,fieldEffects,statusAilments,enemyCorrectionMult,highLevelEnemy])
return <>
Weapon Total Atk:
{setWeaponTotalAtk(val)}}/>
- ●Weapon Base Atk:{setWeaponBaseAtk(val)}}/>
- ●Weapon Enhance Lvl:{setWeaponEnhanceLvl(val)}}/>
Damage Variance:{setDmgVariance(val)}}/>
- ●Weapon Damage Variance:{setWeaponDmgVariance(val)}}/>
- ●Augment Damage Variance:{setAugDmgVariance(val)}}/>
Base Attack:{setBaseAtk(val)}}/>
Enemy Defense:{setEnemyDef(val)}}/>
Multipliers:{setMultipliers(val)}}/>
- ●Atk Mult:{setAtkMult(val)}}/>
- ●Part Mult:{setPartMult(val)}}/>
- ●Elemental Weakness Mult:{setElementalWeaknessMult(val)}}/>
- ●Main Class Weapon Boost:{setMainClassWeaponBoost(val)}}/>
- ●Class Skill Mult:{setClassSkillMult(val)}}/>
- ●Equip Mult:{setEquipMult(val)}}/>
-
- ●Augment Equip Mult:{setAugmentEquipMult(val)}}/>
- ●Potency Floor Equip Mult:{setPotencyFloorEquipMult(val)}}/>
- ●Elemental Weapon Equip Mult:{setElementalWeaponEquipMult(val)}}/>
- ●Crit Mult:{setCritMult(val)}}/>
- ●Appropriate Distance:{setAppropriateDistance(val)}}/>
- ●Food Boost:{setFoodBoost(val)}}/>
- ●Field Effects:{setFieldEffects(val)}}/>
- ●Status Ailments:{setStatusAilments(val)}}/>
- ●Enemy Correction Multiplier:{setEnemyCorrectionMult(val)}}/>
- ●High Level Enemy:{setHighLevelEnemy(val)}}/>
Raw Dmg:{rawDmg}
>
}
function TooltipTest(p) {
return <>This is some tooltip info!>
}
function App() {
const [author,setAuthor] = useState("Dudley")
const [buildName,setBuildName] = useState("Fatimah")
const [className,setClassName] = useState("RANGER")
const [secondaryClassName,setSecondaryClassName] = useState("FORCE")
const [bp,setBP] = useState(1344)
const [hp,setHP] = useState(289)
const [pp,setPP] = useState(100)
const [def,setDef] = useState(402)
const [weaponUp1,setWeaponUp1] = useState(0.34)
const [weaponUp2,setWeaponUp2] = useState(0.34)
const [weaponUp3,setWeaponUp3] = useState(0.34)
const [damageResist,setDamageResist] = useState(0.18)
const [effectList,setEffectList] = useState([
"Food Boost Effect",
"Shifta / Deband",
"Region Mag Boost"
])
const [weapon,setWeapon] = useState("Ophistia Shooter")
const [armorSlot1,setArmorSlot1] = useState("Klauzdyne")
const [armorSlot2,setArmorSlot2] = useState("Klauznum")
const [armorSlot3,setArmorSlot3] = useState("Klauzment")
const [weaponEnhancementLv,setWeaponEnhancementLv] = useState(35)
const [armorSlot1EnhancementLv,setArmorSlot1EnhancementLv] = useState(10)
const [armorSlot2EnhancementLv,setArmorSlot2EnhancementLv] = useState(10)
const [armorSlot3EnhancementLv,setArmorSlot3EnhancementLv] = useState(10)
const [weaponAbilityList,setWeaponAbilityList] = useState([
"Wellspring Unit Lv.3",
"Fixa Fatale Lv.5",
"Legaro S Attack II",
"Legaro S Efficiet",
"Legaro S Efficiet",
"Legaro Souls 2",
"Legaro Reverij",
"Legaro Factalz",
"Legaro Crakus",
"Legaro Attack Vaz III",
])
const [armor1AbilityList,setArmor1AbilityList] = useState([])
const [armor2AbilityList,setArmor2AbilityList] = useState([])
const [armor3AbilityList,setArmor3AbilityList] = useState([])
const [criticalHitRate,setCriticalHitRate] = useState(0.05)
const [criticalMultiplier,setCriticalMultiplier] = useState(1.2)
const [midRange,setMidRange] = useState(126)
const [critical,setCritical] = useState(152)
const [effective,setEffective] = useState(127)
const [modalOpen,setModalOpen] = useState(true)
return (
<>
Modal content goes here.{BACKEND_URL}
}
>Mouseover Me!
>
);
}
export default App;