{ rewards && rewards.map((reward, index) =>
{
+ const rewardTypeOptions = (reward.rewardType === 'respect')
+ ? REWARD_TYPES
+ : SELECTABLE_REWARD_TYPES;
+
return (
-
-
-
updateReward(index, e.target.checked, reward.itemCode, reward.probability) } />
-
Badge?
+
+
+
updateReward(index, prevValue => ({ ...prevValue, rewardValue: event.target.value })) } />
+ { uniqueRewards
+ ?
+ Unique
+
+ : updateReward(index, prevValue => ({ ...prevValue, probability: Number(event.target.value) })) } /> }
+ { (reward.rewardType === 'points')
+ ?
+ updateReward(index, prevValue => ({ ...prevValue, pointsType: Number(event.target.value) })) } />
+ :
+ { getExtraFieldLabel(reward.rewardType) }
+
}
+
+ { (index > 0) &&
+ }
- updateReward(index, reward.isBadge, e.target.value, reward.probability) } />
- updateReward(index, reward.isBadge, reward.itemCode, Number(e.target.value)) } />
- { (index > 0) &&
- }
);
}) }
+
+ Extra Currency uses Amount as the quantity and Currency Type as the purse type id. Example: amount 200 + type 105.
+
);
};
diff --git a/src/components/wired/views/actions/WiredActionLayoutView.tsx b/src/components/wired/views/actions/WiredActionLayoutView.tsx
index 23d853a..551da1a 100644
--- a/src/components/wired/views/actions/WiredActionLayoutView.tsx
+++ b/src/components/wired/views/actions/WiredActionLayoutView.tsx
@@ -28,6 +28,7 @@ import { WiredActionMoveAndRotateFurniView } from './WiredActionMoveAndRotateFur
import { WiredActionMoveFurniToView } from './WiredActionMoveFurniToView';
import { WiredActionMoveFurniView } from './WiredActionMoveFurniView';
import { WiredActionMuteUserView } from './WiredActionMuteUserView';
+import { WiredActionRelativeMoveView } from './WiredActionRelativeMoveView';
import { WiredActionResetView } from './WiredActionResetView';
import { WiredActionSetFurniStateToView } from './WiredActionSetFurniStateToView';
import { WiredActionTeleportView } from './WiredActionTeleportView';
@@ -86,6 +87,8 @@ export const WiredActionLayoutView = (code: number) =>
return
;
case WiredActionLayoutCode.MUTE_USER:
return
;
+ case WiredActionLayoutCode.RELATIVE_MOVE:
+ return
;
case WiredActionLayoutCode.RESET:
return
;
case WiredActionLayoutCode.SET_FURNI_STATE:
diff --git a/src/components/wired/views/actions/WiredActionRelativeMoveView.tsx b/src/components/wired/views/actions/WiredActionRelativeMoveView.tsx
new file mode 100644
index 0000000..c6f33a1
--- /dev/null
+++ b/src/components/wired/views/actions/WiredActionRelativeMoveView.tsx
@@ -0,0 +1,120 @@
+import { FC, useEffect, useState } from 'react';
+import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp } from 'react-icons/fa';
+import { LocalizeText, WiredFurniType } from '../../../../api';
+import { Slider, Text } from '../../../../common';
+import { useWired } from '../../../../hooks';
+import { WiredSourcesSelector } from '../WiredSourcesSelector';
+import { WiredActionBaseView } from './WiredActionBaseView';
+
+const MAX_DISTANCE = 20;
+
+const HORIZONTAL_OPTIONS = [
+ { value: 0, icon:
},
+ { value: 1, icon:
}
+];
+
+const VERTICAL_OPTIONS = [
+ { value: 0, icon:
},
+ { value: 1, icon:
}
+];
+
+const normalizeDirection = (value: number, fallback = 1) =>
+{
+ if(value === 0 || value === 1) return value;
+
+ return fallback;
+};
+
+const normalizeDistance = (value: number) =>
+{
+ if(isNaN(value)) return 0;
+
+ return Math.max(0, Math.min(MAX_DISTANCE, value));
+};
+
+export const WiredActionRelativeMoveView: FC<{}> = () =>
+{
+ const { trigger = null, setIntParams = null } = useWired();
+
+ const [horizontalDirection, setHorizontalDirection] = useState(1);
+ const [horizontalDistance, setHorizontalDistance] = useState(0);
+ const [verticalDirection, setVerticalDirection] = useState(1);
+ const [verticalDistance, setVerticalDistance] = useState(0);
+ const [ furniSource, setFurniSource ] = useState
(() =>
+ {
+ if(trigger?.intData?.length > 4) return trigger.intData[4];
+ return (trigger?.selectedItems?.length ?? 0) > 0 ? 100 : 0;
+ });
+
+ useEffect(() =>
+ {
+ if(!trigger) return;
+
+ setHorizontalDirection((trigger.intData.length > 0) ? normalizeDirection(trigger.intData[0], 1) : 1);
+ setHorizontalDistance((trigger.intData.length > 1) ? normalizeDistance(trigger.intData[1]) : 0);
+ setVerticalDirection((trigger.intData.length > 2) ? normalizeDirection(trigger.intData[2], 1) : 1);
+ setVerticalDistance((trigger.intData.length > 3) ? normalizeDistance(trigger.intData[3]) : 0);
+
+ if(trigger.intData.length > 4) setFurniSource(trigger.intData[4]);
+ else setFurniSource((trigger.selectedItems?.length ?? 0) > 0 ? 100 : 0);
+ }, [ trigger ]);
+
+ const save = () => setIntParams([
+ horizontalDirection,
+ horizontalDistance,
+ verticalDirection,
+ verticalDistance,
+ furniSource
+ ]);
+
+ return (
+ }>
+
+
{ LocalizeText('wiredfurni.params.movement.horizontal.selection') }
+
+ { HORIZONTAL_OPTIONS.map(option =>
+ {
+ return (
+
+ );
+ }) }
+
+
{ LocalizeText('wiredfurni.params.movement.horizontal.distance', [ 'distance' ], [ horizontalDistance.toString() ]) }
+
setHorizontalDistance(value as number) } />
+
+
+
{ LocalizeText('wiredfurni.params.movement.vertical.selection') }
+
+ { VERTICAL_OPTIONS.map(option =>
+ {
+ return (
+
+ );
+ }) }
+
+
{ LocalizeText('wiredfurni.params.movement.vertical.distance', [ 'distance' ], [ verticalDistance.toString() ]) }
+
setVerticalDistance(value as number) } />
+
+
+ );
+};
diff --git a/src/components/wired/views/actions/WiredActionSetAltitudeView.tsx b/src/components/wired/views/actions/WiredActionSetAltitudeView.tsx
new file mode 100644
index 0000000..3e4017b
--- /dev/null
+++ b/src/components/wired/views/actions/WiredActionSetAltitudeView.tsx
@@ -0,0 +1,162 @@
+import { FC, useEffect, useMemo, useState } from 'react';
+import { LocalizeText, WiredFurniType } from '../../../../api';
+import { Slider, Text } from '../../../../common';
+import { useWired } from '../../../../hooks';
+import { WiredSourcesSelector } from '../WiredSourcesSelector';
+import { WiredActionBaseView } from './WiredActionBaseView';
+
+const MIN_ALTITUDE = 0;
+const MAX_ALTITUDE = 40;
+const ALTITUDE_STEP = 0.01;
+const ALTITUDE_PATTERN = /^\d*(\.\d{0,2})?$/;
+
+const clampAltitude = (value: number) =>
+{
+ if(isNaN(value)) return MIN_ALTITUDE;
+
+ const clamped = Math.min(MAX_ALTITUDE, Math.max(MIN_ALTITUDE, value));
+
+ return parseFloat(clamped.toFixed(2));
+};
+
+const formatAltitude = (value: number) =>
+{
+ const normalized = clampAltitude(value);
+ const text = normalized.toFixed(2);
+
+ return text.replace(/\.00$/, '').replace(/(\.\d)0$/, '$1');
+};
+
+const parseAltitude = (value: string) =>
+{
+ if(!value || !value.trim().length) return 0;
+
+ const parsed = parseFloat(value);
+
+ if(isNaN(parsed)) return 0;
+
+ return clampAltitude(parsed);
+};
+
+const OPERATOR_OPTIONS = [
+ { value: 0, label: 'wiredfurni.params.operator.0' },
+ { value: 1, label: 'wiredfurni.params.operator.1' },
+ { value: 2, label: 'wiredfurni.params.operator.2' }
+];
+
+const normalizeOperator = (value: number) =>
+{
+ if(value < 0 || value > 2) return 2;
+
+ return value;
+};
+
+export const WiredActionSetAltitudeView: FC<{}> = () =>
+{
+ const { trigger = null, setIntParams = null, setStringParam = null } = useWired();
+
+ const [ operator, setOperator ] = useState(2);
+ const [ furniSource, setFurniSource ] = useState(() =>
+ {
+ if(trigger?.intData?.length > 1) return trigger.intData[1];
+ return (trigger?.selectedItems?.length ?? 0) > 0 ? 100 : 0;
+ });
+ const [ altitude, setAltitude ] = useState(0);
+ const [ altitudeInput, setAltitudeInput ] = useState('0');
+
+ const normalizedAltitudeText = useMemo(() => formatAltitude(altitude), [ altitude ]);
+
+ useEffect(() =>
+ {
+ if(!trigger) return;
+
+ setOperator((trigger.intData.length > 0) ? normalizeOperator(trigger.intData[0]) : 2);
+ setFurniSource((trigger.intData.length > 1) ? trigger.intData[1] : ((trigger.selectedItems?.length ?? 0) > 0 ? 100 : 0));
+
+ const nextAltitude = parseAltitude(trigger.stringData);
+ setAltitude(nextAltitude);
+ setAltitudeInput(formatAltitude(nextAltitude));
+ }, [ trigger ]);
+
+ const updateAltitude = (value: number) =>
+ {
+ const nextValue = clampAltitude(value);
+
+ setAltitude(nextValue);
+ setAltitudeInput(formatAltitude(nextValue));
+ };
+
+ const updateAltitudeInput = (value: string) =>
+ {
+ if(!ALTITUDE_PATTERN.test(value)) return;
+
+ setAltitudeInput(value);
+
+ if(!value.length)
+ {
+ setAltitude(0);
+ return;
+ }
+
+ const parsedValue = parseFloat(value);
+
+ if(isNaN(parsedValue)) return;
+
+ if(parsedValue > MAX_ALTITUDE)
+ {
+ updateAltitude(MAX_ALTITUDE);
+ return;
+ }
+
+ setAltitude(clampAltitude(parsedValue));
+ };
+
+ const save = () =>
+ {
+ setIntParams([
+ operator,
+ furniSource
+ ]);
+
+ setStringParam(normalizedAltitudeText);
+ };
+
+ return (
+ }>
+
+ { OPERATOR_OPTIONS.map(option =>
+ {
+ return (
+
+ setOperator(option.value) } />
+ { LocalizeText(option.label) }
+
+ );
+ }) }
+
+
+ { LocalizeText('wiredfurni.params.setaltitude') }
+ setAltitudeInput(formatAltitude(altitude)) }
+ onChange={ event => updateAltitudeInput(event.target.value) } />
+
+
+ updateAltitude(event as number) } />
+ { normalizedAltitudeText }
+
+
+ );
+};
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 &&
+
}
+
}
+
+ );
+};
diff --git a/src/css/common/Buttons.css b/src/css/common/Buttons.css
index 106a3cc..21d7f1f 100644
--- a/src/css/common/Buttons.css
+++ b/src/css/common/Buttons.css
@@ -24,8 +24,8 @@ input[type=number] {
.btn-primary {
color: #fff;
- background-color: #3c6d82;
- border: 2px solid #1a617f;
+ background-color: var(--ui-btn-primary-bg, #3c6d82);
+ border: 2px solid var(--ui-btn-primary-border, #1a617f);
padding: 0.25rem 0.5rem;
font-size: .7875rem;
border-radius: 0.5rem;
@@ -33,7 +33,7 @@ input[type=number] {
}
.btn-primary:hover {
- border: 2px solid #1a617f;
+ border: 2px solid var(--ui-btn-primary-border, #1a617f);
box-shadow: none!important;
}
@@ -81,16 +81,16 @@ input[type=number] {
.btn-dark {
color: #fff;
- background-color: #212131;
- border: 2px solid #1c1c2a;
+ background-color: var(--ui-dark-bg, #212131);
+ border: 2px solid var(--ui-dark-border, #1c1c2a);
box-shadow: none!important;
border-radius: 8px;
padding: 4px 11px 4px 11px;
}
.btn-dark:hover{
- background-color: #212131;
- border: 2px solid #1c1c2a;
+ background-color: var(--ui-dark-bg, #212131);
+ border: 2px solid var(--ui-dark-border, #1c1c2a);
box-shadow: none!important;
border-radius: 8px;
padding: 4px 11px 4px 11px;
diff --git a/src/css/purse/PurseView.css b/src/css/purse/PurseView.css
index 7134551..69c1732 100644
--- a/src/css/purse/PurseView.css
+++ b/src/css/purse/PurseView.css
@@ -22,7 +22,7 @@
pointer-events: all;
}
.borderhccontent{
- background-color: #212131;
+ background-color: var(--ui-dark-bg, #212131);
border-radius: 0.5rem!important;
border: 2px solid #383853;
height: calc(100% - 3px);
@@ -46,7 +46,7 @@
}
.nitro-purse-seasonal-currency {
- background-color: #212131;
+ background-color: var(--ui-dark-bg, #212131);
background: linear-gradient(to right, #5f5f8d, transparent);
height: 30px;
margin-bottom: 4px;
diff --git a/src/css/room/InfoStand.css b/src/css/room/InfoStand.css
index e44b062..7e1a050 100644
--- a/src/css/room/InfoStand.css
+++ b/src/css/room/InfoStand.css
@@ -27,7 +27,7 @@
width: clamp(160px, 20vw, 190px); /* Responsive width */
z-index: 30;
pointer-events: auto;
- background: #212131;
+ background: var(--ui-dark-bg, #212131);
box-shadow: inset 0 5px rgba(38, 38, 57, 0.6), inset 0 -4px rgba(25, 25, 37, 0.6);
border-radius: 0.5rem;
padding: 10px;
diff --git a/src/css/room/RoomWidgets.css b/src/css/room/RoomWidgets.css
index 093fa67..b4d6ee2 100644
--- a/src/css/room/RoomWidgets.css
+++ b/src/css/room/RoomWidgets.css
@@ -4,7 +4,7 @@
left: 15px;
.nitro-room-tools {
- background: #212131;
+ background: var(--ui-dark-bg, #212131);
box-shadow: inset 0px 5px lighten(rgba(#000, .6), 2.5), inset 0 -4px darken(rgba(#000, .6), 4);
border-top-right-radius: .25rem;
border-bottom-right-radius: .25rem;
@@ -54,7 +54,7 @@
}
.nitro-room-history {
- background: #212131;
+ background: var(--ui-dark-bg, #212131);
box-shadow: inset 0px 5px lighten(rgba(#000, .6), 2.5), inset 0 -4px darken(rgba(#000, .6), 4);
transition: all .2s ease;
width: 150px;
@@ -63,7 +63,7 @@
}
.nitro-room-tools-info {
- background: #212131;
+ background: var(--ui-dark-bg, #212131);
box-shadow: inset 0px 5px lighten(rgba(#000, .6), 2.5), inset 0 -4px darken(rgba(#000, .6), 4);
transition: all .2s ease;
max-width: 250px;
diff --git a/src/hooks/notification/useNotification.ts b/src/hooks/notification/useNotification.ts
index 4cd3f68..41e85d1 100644
--- a/src/hooks/notification/useNotification.ts
+++ b/src/hooks/notification/useNotification.ts
@@ -1,4 +1,4 @@
-import { AchievementNotificationMessageEvent, ActivityPointNotificationMessageEvent, ClubGiftNotificationEvent, ClubGiftSelectedEvent, ConnectionErrorEvent, GetLocalizationManager, GetRoomEngine, GetSessionDataManager, HabboBroadcastMessageEvent, HotelClosedAndOpensEvent, HotelClosesAndWillOpenAtEvent, HotelWillCloseInMinutesEvent, InfoFeedEnableMessageEvent, MaintenanceStatusMessageEvent, ModeratorCautionEvent, ModeratorMessageEvent, MOTDNotificationEvent, NotificationDialogMessageEvent, PetLevelNotificationEvent, PetReceivedMessageEvent, RespectReceivedEvent, RoomEnterEffect, RoomEnterEvent, SimpleAlertMessageEvent, UserBannedMessageEvent, Vector3d } from '@nitrots/nitro-renderer';
+import { AchievementNotificationMessageEvent, ActivityPointNotificationMessageEvent, ClubGiftNotificationEvent, ClubGiftSelectedEvent, ConnectionErrorEvent, GetLocalizationManager, GetRoomEngine, GetSessionDataManager, HabboBroadcastMessageEvent, HotelClosedAndOpensEvent, HotelClosesAndWillOpenAtEvent, HotelWillCloseInMinutesEvent, InfoFeedEnableMessageEvent, MaintenanceStatusMessageEvent, ModeratorCautionEvent, ModeratorMessageEvent, MOTDNotificationEvent, NotificationDialogMessageEvent, PetLevelNotificationEvent, PetReceivedMessageEvent, RespectReceivedEvent, RoomEnterEffect, RoomEnterEvent, SimpleAlertMessageEvent, UserBannedMessageEvent, Vector3d, WiredRewardResultMessageEvent } from '@nitrots/nitro-renderer';
import { useCallback, useState } from 'react';
import { useBetween } from 'use-between';
import { GetConfigurationValue, LocalizeBadgeName, LocalizeText, NotificationAlertItem, NotificationAlertType, NotificationBubbleItem, NotificationBubbleType, NotificationConfirmItem, PlaySound, ProductImageUtility, TradingNotificationType } from '../../api';
@@ -397,6 +397,28 @@ const useNotificationState = () =>
simpleAlert(LocalizeText(parser.alertMessage), NotificationAlertType.DEFAULT, null, null, LocalizeText(parser.titleMessage ? parser.titleMessage : 'notifications.broadcast.title'));
});
+ useMessageEvent(WiredRewardResultMessageEvent, event =>
+ {
+ const parser = event.getParser();
+
+ switch(parser.reason)
+ {
+ case WiredRewardResultMessageEvent.PRODUCT_DONATED_CODE:
+ case WiredRewardResultMessageEvent.BADGE_DONATED_CODE:
+ simpleAlert(LocalizeText('wiredfurni.rewardsuccess.body'), NotificationAlertType.DEFAULT, null, null, LocalizeText('wiredfurni.rewardsuccess.title'));
+ return;
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 8:
+ simpleAlert(LocalizeText(`wiredfurni.rewardfailed.reason.${ parser.reason }`), NotificationAlertType.DEFAULT, null, null, LocalizeText('wiredfurni.rewardfailed.title'));
+ return;
+ }
+ });
+
const onRoomEnterEvent = useCallback(() =>
{
if(modDisclaimerShown) return;
diff --git a/src/hooks/rooms/widgets/useChatWidget.ts b/src/hooks/rooms/widgets/useChatWidget.ts
index d430a38..648a102 100644
--- a/src/hooks/rooms/widgets/useChatWidget.ts
+++ b/src/hooks/rooms/widgets/useChatWidget.ts
@@ -123,9 +123,10 @@ const useChatWidgetState = () =>
text = LocalizeText('widget.chatbubble.handitem', ['username', 'handitem'], [username, LocalizeText(('handitem' + event.extraParam))]);
break;
case RoomSessionChatEvent.CHAT_TYPE_MUTE_REMAINING: {
- const hours = ((event.extraParam > 0) ? Math.floor((event.extraParam / 3600)) : 0).toString();
- const minutes = ((event.extraParam > 0) ? Math.floor((event.extraParam % 3600) / 60) : 0).toString();
- const seconds = (event.extraParam % 60).toString();
+ const remainingSeconds = Math.max(0, event.extraParam);
+ const hours = Math.floor(remainingSeconds / 3600).toString();
+ const minutes = Math.floor((remainingSeconds % 3600) / 60).toString();
+ const seconds = (remainingSeconds % 60).toString();
text = LocalizeText('widget.chatbubble.mutetime', ['hours', 'minutes', 'seconds'], [hours, minutes, seconds]);
break;