From dbfcae523105ad87d17e45918cda5c5bc7862720 Mon Sep 17 00:00:00 2001 From: Lorenzune Date: Tue, 17 Mar 2026 01:34:33 +0100 Subject: [PATCH] feat(wired): add leave/click/action/short-period trigger views - add UI for wf_trg_leave_room, wf_trg_stuff_state, wf_trg_period_short, wf_trg_click_furni, wf_trg_click_tile, wf_trg_click_user and wf_trg_user_performs_action\n- add state snapshot mode options for wf_trg_stuff_state\n- add sign and dance filters for wf_trg_user_performs_action --- src/api/wired/WiredTriggerLayoutCode.ts | 6 + .../WiredTriggerAvatarLeaveRoomView.tsx | 39 +++++++ .../triggers/WiredTriggerClickFurniView.tsx | 8 ++ .../triggers/WiredTriggerClickTileView.tsx | 20 ++++ .../triggers/WiredTriggerClickUserView.tsx | 8 ++ ...redTriggerExecutePeriodicallyShortView.tsx | 32 ++++++ .../views/triggers/WiredTriggerLayoutView.tsx | 18 +++ .../triggers/WiredTriggerToggleFurniView.tsx | 34 +++++- .../WiredTriggerUserPerformsActionView.tsx | 103 ++++++++++++++++++ 9 files changed, 264 insertions(+), 4 deletions(-) create mode 100644 src/components/wired/views/triggers/WiredTriggerAvatarLeaveRoomView.tsx create mode 100644 src/components/wired/views/triggers/WiredTriggerClickFurniView.tsx create mode 100644 src/components/wired/views/triggers/WiredTriggerClickTileView.tsx create mode 100644 src/components/wired/views/triggers/WiredTriggerClickUserView.tsx create mode 100644 src/components/wired/views/triggers/WiredTriggerExecutePeriodicallyShortView.tsx create mode 100644 src/components/wired/views/triggers/WiredTriggerUserPerformsActionView.tsx diff --git a/src/api/wired/WiredTriggerLayoutCode.ts b/src/api/wired/WiredTriggerLayoutCode.ts index 683ff04..ac80e07 100644 --- a/src/api/wired/WiredTriggerLayoutCode.ts +++ b/src/api/wired/WiredTriggerLayoutCode.ts @@ -15,4 +15,10 @@ export class WiredTriggerLayout public static BOT_REACHED_STUFF: number = 13; public static BOT_REACHED_AVATAR: number = 14; public static RECEIVE_SIGNAL: number = 15; + public static AVATAR_LEAVES_ROOM: number = 16; + public static EXECUTE_PERIODICALLY_SHORT: number = 17; + public static CLICK_FURNI: number = 18; + public static CLICK_TILE: number = 19; + public static CLICK_USER: number = 20; + public static USER_PERFORMS_ACTION: number = 21; } diff --git a/src/components/wired/views/triggers/WiredTriggerAvatarLeaveRoomView.tsx b/src/components/wired/views/triggers/WiredTriggerAvatarLeaveRoomView.tsx new file mode 100644 index 0000000..36a773e --- /dev/null +++ b/src/components/wired/views/triggers/WiredTriggerAvatarLeaveRoomView.tsx @@ -0,0 +1,39 @@ +import { FC, useEffect, useState } from 'react'; +import { LocalizeText, WiredFurniType } from '../../../../api'; +import { Text } from '../../../../common'; +import { useWired } from '../../../../hooks'; +import { NitroInput } from '../../../../layout'; +import { WiredTriggerBaseView } from './WiredTriggerBaseView'; + +export const WiredTriggerAvatarLeaveRoomView: FC<{}> = props => +{ + const [ username, setUsername ] = useState(''); + const [ avatarMode, setAvatarMode ] = useState(0); + const { trigger = null, setStringParam = null } = useWired(); + + const save = () => setStringParam((avatarMode === 1) ? username : ''); + + useEffect(() => + { + setUsername(trigger.stringData); + setAvatarMode(trigger.stringData ? 1 : 0); + }, [ trigger ]); + + return ( + +
+ { LocalizeText('wiredfurni.params.picktriggerer') } +
+ setAvatarMode(0) } /> + { LocalizeText('wiredfurni.params.anyavatar') } +
+
+ setAvatarMode(1) } /> + { LocalizeText('wiredfurni.params.certainavatar') } +
+ { (avatarMode === 1) && + setUsername(event.target.value) } /> } +
+
+ ); +}; diff --git a/src/components/wired/views/triggers/WiredTriggerClickFurniView.tsx b/src/components/wired/views/triggers/WiredTriggerClickFurniView.tsx new file mode 100644 index 0000000..db8fbea --- /dev/null +++ b/src/components/wired/views/triggers/WiredTriggerClickFurniView.tsx @@ -0,0 +1,8 @@ +import { FC } from 'react'; +import { WiredFurniType } from '../../../../api'; +import { WiredTriggerBaseView } from './WiredTriggerBaseView'; + +export const WiredTriggerClickFurniView: FC<{}> = () => +{ + return ; +}; diff --git a/src/components/wired/views/triggers/WiredTriggerClickTileView.tsx b/src/components/wired/views/triggers/WiredTriggerClickTileView.tsx new file mode 100644 index 0000000..5a1fdc7 --- /dev/null +++ b/src/components/wired/views/triggers/WiredTriggerClickTileView.tsx @@ -0,0 +1,20 @@ +import { FC, useEffect } from 'react'; +import { WiredFurniType } from '../../../../api'; +import { useWired } from '../../../../hooks'; +import { WiredTriggerBaseView } from './WiredTriggerBaseView'; + +const CLICK_TILE_INTERACTION_TYPES = [ 'room_invisible_click_tile' ]; + +export const WiredTriggerClickTileView: FC<{}> = () => +{ + const { setAllowedInteractionTypes } = useWired(); + + useEffect(() => + { + setAllowedInteractionTypes(CLICK_TILE_INTERACTION_TYPES); + + return () => setAllowedInteractionTypes(null); + }, [ setAllowedInteractionTypes ]); + + return ; +}; diff --git a/src/components/wired/views/triggers/WiredTriggerClickUserView.tsx b/src/components/wired/views/triggers/WiredTriggerClickUserView.tsx new file mode 100644 index 0000000..f3f2222 --- /dev/null +++ b/src/components/wired/views/triggers/WiredTriggerClickUserView.tsx @@ -0,0 +1,8 @@ +import { FC } from 'react'; +import { WiredFurniType } from '../../../../api'; +import { WiredTriggerBaseView } from './WiredTriggerBaseView'; + +export const WiredTriggerClickUserView: FC<{}> = () => +{ + return ; +}; diff --git a/src/components/wired/views/triggers/WiredTriggerExecutePeriodicallyShortView.tsx b/src/components/wired/views/triggers/WiredTriggerExecutePeriodicallyShortView.tsx new file mode 100644 index 0000000..642b5cd --- /dev/null +++ b/src/components/wired/views/triggers/WiredTriggerExecutePeriodicallyShortView.tsx @@ -0,0 +1,32 @@ +import { FC, useEffect, useState } from 'react'; +import { LocalizeText, WiredFurniType } from '../../../../api'; +import { Slider, Text } from '../../../../common'; +import { useWired } from '../../../../hooks'; +import { WiredTriggerBaseView } from './WiredTriggerBaseView'; + +export const WiredTriggeExecutePeriodicallyShortView: FC<{}> = () => +{ + const [ time, setTime ] = useState(10); + const { trigger = null, setIntParams = null } = useWired(); + + const save = () => setIntParams([ time ]); + + useEffect(() => + { + setTime((trigger.intData.length > 0) ? trigger.intData[0] : 10); + }, [ trigger ]); + + return ( + +
+ { LocalizeText('wiredfurni.params.settime', [ 'seconds' ], [ ((time * 50) / 1000).toFixed(2) ]) } + { `${ time * 50 } ms` } + setTime(event) } /> +
+
+ ); +}; diff --git a/src/components/wired/views/triggers/WiredTriggerLayoutView.tsx b/src/components/wired/views/triggers/WiredTriggerLayoutView.tsx index 229464f..3b152fb 100644 --- a/src/components/wired/views/triggers/WiredTriggerLayoutView.tsx +++ b/src/components/wired/views/triggers/WiredTriggerLayoutView.tsx @@ -1,14 +1,20 @@ import { WiredTriggerLayout } from '../../../../api'; import { WiredTriggerAvatarEnterRoomView } from './WiredTriggerAvatarEnterRoomView'; +import { WiredTriggerAvatarLeaveRoomView } from './WiredTriggerAvatarLeaveRoomView'; import { WiredTriggerAvatarSaysSomethingView } from './WiredTriggerAvatarSaysSomethingView'; import { WiredTriggerAvatarWalksOffFurniView } from './WiredTriggerAvatarWalksOffFurniView'; import { WiredTriggerAvatarWalksOnFurniView } from './WiredTriggerAvatarWalksOnFurni'; import { WiredTriggerBotReachedAvatarView } from './WiredTriggerBotReachedAvatarView'; import { WiredTriggerBotReachedStuffView } from './WiredTriggerBotReachedStuffView'; +import { WiredTriggerClickFurniView } from './WiredTriggerClickFurniView'; +import { WiredTriggerClickTileView } from './WiredTriggerClickTileView'; +import { WiredTriggerClickUserView } from './WiredTriggerClickUserView'; import { WiredTriggerCollisionView } from './WiredTriggerCollisionView'; +import { WiredTriggerUserPerformsActionView } from './WiredTriggerUserPerformsActionView'; import { WiredTriggeExecuteOnceView } from './WiredTriggerExecuteOnceView'; import { WiredTriggeExecutePeriodicallyLongView } from './WiredTriggerExecutePeriodicallyLongView'; import { WiredTriggeExecutePeriodicallyView } from './WiredTriggerExecutePeriodicallyView'; +import { WiredTriggeExecutePeriodicallyShortView } from './WiredTriggerExecutePeriodicallyShortView'; import { WiredTriggerGameEndsView } from './WiredTriggerGameEndsView'; import { WiredTriggerGameStartsView } from './WiredTriggerGameStartsView'; import { WiredTriggeScoreAchievedView } from './WiredTriggerScoreAchievedView'; @@ -21,6 +27,8 @@ export const WiredTriggerLayoutView = (code: number) => { case WiredTriggerLayout.AVATAR_ENTERS_ROOM: return ; + case WiredTriggerLayout.AVATAR_LEAVES_ROOM: + return ; case WiredTriggerLayout.AVATAR_SAYS_SOMETHING: return ; case WiredTriggerLayout.AVATAR_WALKS_OFF_FURNI: @@ -31,12 +39,22 @@ export const WiredTriggerLayoutView = (code: number) => return ; case WiredTriggerLayout.BOT_REACHED_STUFF: return ; + case WiredTriggerLayout.CLICK_FURNI: + return ; + case WiredTriggerLayout.CLICK_TILE: + return ; + case WiredTriggerLayout.CLICK_USER: + return ; + case WiredTriggerLayout.USER_PERFORMS_ACTION: + return ; case WiredTriggerLayout.COLLISION: return ; case WiredTriggerLayout.EXECUTE_ONCE: return ; case WiredTriggerLayout.EXECUTE_PERIODICALLY: return ; + case WiredTriggerLayout.EXECUTE_PERIODICALLY_SHORT: + return ; case WiredTriggerLayout.EXECUTE_PERIODICALLY_LONG: return ; case WiredTriggerLayout.GAME_ENDS: diff --git a/src/components/wired/views/triggers/WiredTriggerToggleFurniView.tsx b/src/components/wired/views/triggers/WiredTriggerToggleFurniView.tsx index 4748481..01cb8a4 100644 --- a/src/components/wired/views/triggers/WiredTriggerToggleFurniView.tsx +++ b/src/components/wired/views/triggers/WiredTriggerToggleFurniView.tsx @@ -1,8 +1,34 @@ -import { FC } from 'react'; -import { WiredFurniType } from '../../../../api'; +import { FC, useEffect, useState } from 'react'; +import { LocalizeText, WiredFurniType } from '../../../../api'; +import { Text } from '../../../../common'; +import { useWired } from '../../../../hooks'; import { WiredTriggerBaseView } from './WiredTriggerBaseView'; -export const WiredTriggerToggleFurniView: FC<{}> = props => +export const WiredTriggerToggleFurniView: FC<{}> = () => { - return ; + const [ triggerMode, setTriggerMode ] = useState(0); + const { trigger = null, setIntParams = null } = useWired(); + + const save = () => setIntParams([ triggerMode ]); + + useEffect(() => + { + setTriggerMode((trigger?.intData?.length > 0) ? trigger.intData[0] : 0); + }, [ trigger ]); + + return ( + +
+ { LocalizeText('wiredfurni.params.condition.state') } +
+ setTriggerMode(1) } /> + { LocalizeText('wiredfurni.params.state_trigger.1') } +
+
+ setTriggerMode(0) } /> + { LocalizeText('wiredfurni.params.state_trigger.0') } +
+
+
+ ); }; diff --git a/src/components/wired/views/triggers/WiredTriggerUserPerformsActionView.tsx b/src/components/wired/views/triggers/WiredTriggerUserPerformsActionView.tsx new file mode 100644 index 0000000..5e68651 --- /dev/null +++ b/src/components/wired/views/triggers/WiredTriggerUserPerformsActionView.tsx @@ -0,0 +1,103 @@ +import { FC, useEffect, useState } from 'react'; +import { LocalizeText, WiredFurniType } from '../../../../api'; +import { Text } from '../../../../common'; +import { useWired } from '../../../../hooks'; +import { WiredTriggerBaseView } from './WiredTriggerBaseView'; + +const ACTION_WAVE = 1; +const ACTION_BLOW_KISS = 2; +const ACTION_LAUGH = 3; +const ACTION_AWAKE = 4; +const ACTION_RELAX = 5; +const ACTION_SIT = 6; +const ACTION_STAND = 7; +const ACTION_LAY = 8; +const ACTION_SIGN = 9; +const ACTION_DANCE = 10; +const ACTION_THUMB_UP = 11; + +const ACTION_OPTIONS = [ + { value: ACTION_WAVE, label: 'widget.memenu.wave' }, + { value: ACTION_BLOW_KISS, label: 'widget.memenu.blow' }, + { value: ACTION_LAUGH, label: 'widget.memenu.laugh' }, + { value: ACTION_THUMB_UP, label: 'widget.memenu.thumb' }, + { value: ACTION_AWAKE, label: 'wiredfurni.params.action.4' }, + { value: ACTION_RELAX, label: 'avatar.widget.random_walk' }, + { value: ACTION_SIT, label: 'widget.memenu.sit' }, + { value: ACTION_STAND, label: 'widget.memenu.stand' }, + { value: ACTION_LAY, label: 'wiredfurni.params.action.8' }, + { value: ACTION_SIGN, label: 'widget.memenu.sign' }, + { value: ACTION_DANCE, label: 'widget.memenu.dance' } +]; + +const SIGN_OPTIONS = Array.from({ length: 18 }, (_, value) => ({ + value, + label: `wiredfurni.params.action.sign.${ value }` +})); + +const DANCE_OPTIONS = [ + { value: 1, label: 'widget.memenu.dance1' }, + { value: 2, label: 'widget.memenu.dance2' }, + { value: 3, label: 'widget.memenu.dance3' }, + { value: 4, label: 'widget.memenu.dance4' } +]; + +export const WiredTriggerUserPerformsActionView: FC<{}> = () => +{ + const [ selectedAction, setSelectedAction ] = useState(ACTION_WAVE); + const [ signFilterEnabled, setSignFilterEnabled ] = useState(false); + const [ signId, setSignId ] = useState(0); + const [ danceFilterEnabled, setDanceFilterEnabled ] = useState(false); + const [ danceId, setDanceId ] = useState(1); + const { trigger = null, setIntParams = null } = useWired(); + + const save = () => setIntParams([ + selectedAction, + signFilterEnabled ? 1 : 0, + signId, + danceFilterEnabled ? 1 : 0, + danceId + ]); + + useEffect(() => + { + setSelectedAction((trigger?.intData?.length > 0) ? trigger.intData[0] : ACTION_WAVE); + setSignFilterEnabled((trigger?.intData?.length > 1) ? (trigger.intData[1] === 1) : false); + setSignId((trigger?.intData?.length > 2) ? trigger.intData[2] : 0); + setDanceFilterEnabled((trigger?.intData?.length > 3) ? (trigger.intData[3] === 1) : false); + setDanceId((trigger?.intData?.length > 4) ? trigger.intData[4] : 1); + }, [ trigger ]); + + return ( + +
+ Action + +
+ { (selectedAction === ACTION_SIGN) && +
+
+ setSignFilterEnabled(event.target.checked) } /> + { LocalizeText('wiredfurni.params.sign_filter') } +
+ { signFilterEnabled && + } +
} + { (selectedAction === ACTION_DANCE) && +
+
+ setDanceFilterEnabled(event.target.checked) } /> + { LocalizeText('wiredfurni.params.dance_filter') } +
+ { danceFilterEnabled && + } +
} +
+ ); +};