142 lines
4.8 KiB
TypeScript
142 lines
4.8 KiB
TypeScript
import * as React from 'react'
|
|
|
|
import type { Action, ActionHash } from '@lastres/action'
|
|
import type { TalkNPCs, TalkNPC } from '@lastres/talk-npc'
|
|
|
|
import OutputPacketExecuteAction from '@lastres/output-packet/execute_action'
|
|
import OutputPacketTalk from '@lastres/output-packet/talk';
|
|
|
|
import PresentationItem from '@lastres/components/presentation-item'
|
|
import Presentation from '@lastres/components/presentation'
|
|
|
|
export interface BottomPanelProps {
|
|
websocket: WebSocket | null
|
|
actionHash: ActionHash | null
|
|
talkNPCs: TalkNPCs | null
|
|
}
|
|
|
|
export interface Style {
|
|
background?: string
|
|
}
|
|
|
|
export default function BottomPanel (props: BottomPanelProps): JSX.Element {
|
|
const actionHash = props.actionHash
|
|
function printListActions(): JSX.Element {
|
|
if (actionHash === null) {
|
|
return <></>
|
|
}
|
|
const listOfActionKeys = Object.keys(actionHash).sort((a, b) => {
|
|
const isDisabledComparisionValue: number = +actionHash[a].is_disabled - +actionHash[b].is_disabled
|
|
if (isDisabledComparisionValue !== 0) {
|
|
return isDisabledComparisionValue
|
|
}
|
|
if (actionHash[a].name < actionHash[b].name) {
|
|
return -1
|
|
}
|
|
if (actionHash[a].name > actionHash[b].name) {
|
|
return 1
|
|
}
|
|
return 0
|
|
})
|
|
function printDisabledReason (action: Action): JSX.Element {
|
|
if (!action.is_disabled || action.disabled_reason === null) {
|
|
return <></>
|
|
}
|
|
return (
|
|
<p className="disabled-reason" style={{ color: 'red' }}>{action.disabled_reason}</p>
|
|
)
|
|
}
|
|
return <>
|
|
<p>Acciones disponibles.</p>
|
|
{
|
|
listOfActionKeys.map((key) => {
|
|
const style: Style = {}
|
|
const action = actionHash[key]
|
|
if (action.is_disabled) {
|
|
style.background = 'lightgray'
|
|
}
|
|
function onClick (): void {
|
|
if (action.is_disabled) {
|
|
return
|
|
}
|
|
if (props.websocket !== null) {
|
|
new OutputPacketExecuteAction(action.identifier)
|
|
.send(props.websocket)
|
|
}
|
|
}
|
|
return <a onClick={onClick} className="action" style={style} key={action.identifier}>
|
|
<p>{action.name}</p>
|
|
{
|
|
printDisabledReason(action)
|
|
}
|
|
</a>
|
|
})
|
|
}
|
|
</>
|
|
}
|
|
function printAvatar (npc: TalkNPC): JSX.Element {
|
|
if (npc.icon === undefined) {
|
|
return <></>
|
|
}
|
|
return <div className="avatar">
|
|
<img src={npc.icon}/><div className="shadow"/>
|
|
</div>
|
|
}
|
|
|
|
function onWordlesslyTalk (npc: TalkNPC): void {
|
|
if (props.websocket === null) {
|
|
return
|
|
}
|
|
new OutputPacketTalk(npc.identifier).send(props.websocket)
|
|
}
|
|
function printTalkNpcs (): JSX.Element {
|
|
const npcs = props.talkNPCs
|
|
if (npcs === null) {
|
|
return <></>
|
|
}
|
|
return (
|
|
<>
|
|
{
|
|
Object.keys(npcs).map((identifier) => {
|
|
const npc = npcs[identifier]
|
|
return <div key={npc.identifier} className="talk-npc">
|
|
<div className="detail">
|
|
<div className="name-container">
|
|
{
|
|
printAvatar(npc)
|
|
}
|
|
<div className="name">
|
|
<p>{npc.name}</p>
|
|
</div>
|
|
</div>
|
|
<div className="buttons">
|
|
<button onClick={() => {
|
|
onWordlesslyTalk(npc)
|
|
}}>Hablar</button>
|
|
<button>Decir palabra</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
})
|
|
}
|
|
</>
|
|
)
|
|
}
|
|
return (
|
|
<Presentation>
|
|
<PresentationItem>
|
|
{
|
|
printListActions()
|
|
}
|
|
</PresentationItem>
|
|
<PresentationItem>
|
|
{
|
|
printTalkNpcs()
|
|
}
|
|
</PresentationItem>
|
|
<PresentationItem>
|
|
</PresentationItem>
|
|
</Presentation>
|
|
)
|
|
}
|