+{
+ if(isNaN(value)) return DEFAULT_DURATION;
+
+ return Math.max(MIN_DURATION, Math.min(MAX_DURATION, Math.round(value / STEP_DURATION) * STEP_DURATION));
+};
+
+export const WiredExtraAnimationTimeView: FC<{}> = () =>
+{
+ const { trigger = null, setIntParams = null, setStringParam = null } = useWired();
+ const [ duration, setDuration ] = useState(DEFAULT_DURATION);
+
+ useEffect(() =>
+ {
+ if(!trigger) return;
+
+ setDuration(normalizeDuration((trigger.intData.length > 0) ? trigger.intData[0] : DEFAULT_DURATION));
+ }, [ trigger ]);
+
+ const save = () =>
+ {
+ setIntParams([ normalizeDuration(duration) ]);
+ setStringParam('');
+ };
+
+ return (
+
+
+ { LocalizeText('wiredfurni.params.anim_time.title') }
+ { LocalizeText('wiredfurni.params.anim_time.description') }
+ { LocalizeText('wiredfurni.params.anim_time.value', [ 'ms' ], [ duration.toString() ]) }
+ setDuration(normalizeDuration(Array.isArray(value) ? value[0] : Number(value))) } />
+
+
+ );
+};
diff --git a/src/components/wired/views/extras/WiredExtraMoveCarryUsersView.tsx b/src/components/wired/views/extras/WiredExtraMoveCarryUsersView.tsx
new file mode 100644
index 0000000..2565902
--- /dev/null
+++ b/src/components/wired/views/extras/WiredExtraMoveCarryUsersView.tsx
@@ -0,0 +1,62 @@
+import { FC, useEffect, useState } from 'react';
+import { LocalizeText, WiredFurniType } from '../../../../api';
+import { Text } from '../../../../common';
+import { useWired } from '../../../../hooks';
+import { WiredSourceOption, WiredSourcesSelector } from '../WiredSourcesSelector';
+import { WiredExtraBaseView } from './WiredExtraBaseView';
+
+const CARRY_MODE_DIRECT = 0;
+const CARRY_MODE_SAME_TILE = 1;
+const SOURCE_ALL_ROOM_USERS = 900;
+
+const USER_SOURCES: WiredSourceOption[] = [
+ { value: SOURCE_ALL_ROOM_USERS, label: 'wiredfurni.params.sources.users.900' },
+ { value: 0, label: 'wiredfurni.params.sources.users.0' },
+ { value: 200, label: 'wiredfurni.params.sources.users.200' },
+ { value: 201, label: 'wiredfurni.params.sources.users.201' }
+];
+
+const normalizeCarryMode = (value: number) => ((value === CARRY_MODE_SAME_TILE) ? CARRY_MODE_SAME_TILE : CARRY_MODE_DIRECT);
+const normalizeUserSource = (value: number) => (USER_SOURCES.some(option => option.value === value) ? value : 0);
+
+export const WiredExtraMoveCarryUsersView: FC<{}> = () =>
+{
+ const { trigger = null, setIntParams = null, setStringParam = null } = useWired();
+ const [ carryMode, setCarryMode ] = useState(CARRY_MODE_DIRECT);
+ const [ userSource, setUserSource ] = useState(0);
+
+ useEffect(() =>
+ {
+ if(!trigger) return;
+
+ setCarryMode(normalizeCarryMode((trigger.intData.length > 0) ? trigger.intData[0] : CARRY_MODE_DIRECT));
+ setUserSource(normalizeUserSource((trigger.intData.length > 1) ? trigger.intData[1] : 0));
+ }, [ trigger ]);
+
+ const save = () =>
+ {
+ setIntParams([ normalizeCarryMode(carryMode), normalizeUserSource(userSource) ]);
+ setStringParam('');
+ };
+
+ return (
+ setUserSource(normalizeUserSource(value)) } /> }>
+
+ { LocalizeText('wiredfurni.params.carry_mode') }
+
+
+
+
+ );
+};
diff --git a/src/components/wired/views/extras/WiredExtraMoveNoAnimationView.tsx b/src/components/wired/views/extras/WiredExtraMoveNoAnimationView.tsx
new file mode 100644
index 0000000..0e13527
--- /dev/null
+++ b/src/components/wired/views/extras/WiredExtraMoveNoAnimationView.tsx
@@ -0,0 +1,25 @@
+import { FC } from 'react';
+import { LocalizeText, WiredFurniType } from '../../../../api';
+import { Text } from '../../../../common';
+import { useWired } from '../../../../hooks';
+import { WiredExtraBaseView } from './WiredExtraBaseView';
+
+export const WiredExtraMoveNoAnimationView: FC<{}> = () =>
+{
+ const { setIntParams = null, setStringParam = null } = useWired();
+
+ const save = () =>
+ {
+ setIntParams([]);
+ setStringParam('');
+ };
+
+ return (
+
+
+ { LocalizeText('wiredfurni.params.mov_no_animation.title') }
+ { LocalizeText('wiredfurni.params.mov_no_animation.description') }
+
+
+ );
+};
diff --git a/src/components/wired/views/extras/WiredExtraMovePhysicsView.tsx b/src/components/wired/views/extras/WiredExtraMovePhysicsView.tsx
new file mode 100644
index 0000000..62085e2
--- /dev/null
+++ b/src/components/wired/views/extras/WiredExtraMovePhysicsView.tsx
@@ -0,0 +1,120 @@
+import { FC, useEffect, useMemo, useState } from 'react';
+import { LocalizeText, WiredFurniType } from '../../../../api';
+import { Text } from '../../../../common';
+import { useWired } from '../../../../hooks';
+import { WiredSourceOption, WiredSourcesSelector } from '../WiredSourcesSelector';
+import { WiredExtraBaseView } from './WiredExtraBaseView';
+
+const SOURCE_ALL_ROOM = 900;
+const DEFAULT_SOURCE = 0;
+
+const FURNI_SOURCES: WiredSourceOption[] = [
+ { value: SOURCE_ALL_ROOM, label: 'wiredfurni.params.sources.furni.900' },
+ { value: 0, label: 'wiredfurni.params.sources.furni.0' },
+ { value: 200, label: 'wiredfurni.params.sources.furni.200' },
+ { value: 201, label: 'wiredfurni.params.sources.furni.201' }
+];
+
+const USER_SOURCES: WiredSourceOption[] = [
+ { value: SOURCE_ALL_ROOM, label: 'wiredfurni.params.sources.users.900' },
+ { value: 0, label: 'wiredfurni.params.sources.users.0' },
+ { value: 200, label: 'wiredfurni.params.sources.users.200' },
+ { value: 201, label: 'wiredfurni.params.sources.users.201' }
+];
+
+const normalizeSource = (value: number, options: WiredSourceOption[]) => (options.some(option => option.value === value) ? value : DEFAULT_SOURCE);
+const getFlag = (value: number) => (value === 1);
+
+export const WiredExtraMovePhysicsView: FC<{}> = () =>
+{
+ const { trigger = null, setIntParams = null, setStringParam = null } = useWired();
+ const [ keepAltitude, setKeepAltitude ] = useState(false);
+ const [ moveThroughFurni, setMoveThroughFurni ] = useState(false);
+ const [ moveThroughUsers, setMoveThroughUsers ] = useState(false);
+ const [ blockByFurni, setBlockByFurni ] = useState(false);
+ const [ moveThroughFurniSource, setMoveThroughFurniSource ] = useState(DEFAULT_SOURCE);
+ const [ blockByFurniSource, setBlockByFurniSource ] = useState(DEFAULT_SOURCE);
+ const [ moveThroughUsersSource, setMoveThroughUsersSource ] = useState(DEFAULT_SOURCE);
+
+ useEffect(() =>
+ {
+ if(!trigger) return;
+
+ setKeepAltitude(getFlag(trigger.intData[0] ?? 0));
+ setMoveThroughFurni(getFlag(trigger.intData[1] ?? 0));
+ setMoveThroughUsers(getFlag(trigger.intData[2] ?? 0));
+ setBlockByFurni(getFlag(trigger.intData[3] ?? 0));
+ setMoveThroughFurniSource(normalizeSource((trigger.intData[4] ?? DEFAULT_SOURCE), FURNI_SOURCES));
+ setBlockByFurniSource(normalizeSource((trigger.intData[5] ?? DEFAULT_SOURCE), FURNI_SOURCES));
+ setMoveThroughUsersSource(normalizeSource((trigger.intData[6] ?? DEFAULT_SOURCE), USER_SOURCES));
+ }, [ trigger ]);
+
+ const save = () =>
+ {
+ setIntParams([
+ keepAltitude ? 1 : 0,
+ moveThroughFurni ? 1 : 0,
+ moveThroughUsers ? 1 : 0,
+ blockByFurni ? 1 : 0,
+ normalizeSource(moveThroughFurniSource, FURNI_SOURCES),
+ normalizeSource(blockByFurniSource, FURNI_SOURCES),
+ normalizeSource(moveThroughUsersSource, USER_SOURCES)
+ ]);
+ setStringParam('');
+ };
+
+ const footer = useMemo(() =>
+ {
+ if(!moveThroughFurni && !blockByFurni && !moveThroughUsers) return null;
+
+ return (
+
+ { moveThroughFurni &&
+ setMoveThroughFurniSource(normalizeSource(value, FURNI_SOURCES)) } /> }
+ { blockByFurni &&
+ setBlockByFurniSource(normalizeSource(value, FURNI_SOURCES)) } /> }
+ { moveThroughUsers &&
+ setMoveThroughUsersSource(normalizeSource(value, USER_SOURCES)) } /> }
+
+ );
+ }, [ blockByFurni, blockByFurniSource, moveThroughFurni, moveThroughFurniSource, moveThroughUsers, moveThroughUsersSource ]);
+
+ return (
+
+
+ { LocalizeText('wiredfurni.params.select_options') }
+
+
+
+
+
+
+ );
+};
diff --git a/src/components/wired/views/selectors/WiredSelectorFurniByTypeView.tsx b/src/components/wired/views/selectors/WiredSelectorFurniByTypeView.tsx
index d39b4df..7ee4bff 100644
--- a/src/components/wired/views/selectors/WiredSelectorFurniByTypeView.tsx
+++ b/src/components/wired/views/selectors/WiredSelectorFurniByTypeView.tsx
@@ -12,7 +12,7 @@ export const WiredSelectorFurniByTypeView: FC<{}> = () =>
const [ filterExisting, setFilterExisting ] = useState(false);
const [ invert, setInvert ] = useState(false);
- const { trigger = null, setIntParams, setSelectByType } = useWired();
+ const { trigger = null, setIntParams } = useWired();
useEffect(() =>
{
@@ -24,11 +24,6 @@ export const WiredSelectorFurniByTypeView: FC<{}> = () =>
if(p.length >= 4) setInvert(p[3] === 1);
}, [ trigger ]);
- useEffect(() =>
- {
- setSelectByType(true);
- }, [ setSelectByType ]);
-
const save = useCallback(() =>
{
setIntParams([
diff --git a/src/hooks/wired/useWired.ts b/src/hooks/wired/useWired.ts
index 0fc52c8..e6e3b53 100644
--- a/src/hooks/wired/useWired.ts
+++ b/src/hooks/wired/useWired.ts
@@ -13,7 +13,7 @@ const useWiredState = () =>
const [ furniIds, setFurniIds ] = useState([]);
const [ actionDelay, setActionDelay ] = useState(0);
const [ allowsFurni, setAllowsFurni ] = useState(WiredFurniType.STUFF_SELECTION_OPTION_NONE);
- const [ selectByType, setSelectByType ] = useState(false);
+ const selectByType = false;
const [ neighborhoodTiles, setNeighborhoodTiles ] = useState<{ x: number; y: number }[] | null>(null);
const [ neighborhoodInvert, setNeighborhoodInvert ] = useState(false);
const [ allowedInteractionTypes, setAllowedInteractionTypes ] = useState(null);
@@ -303,7 +303,6 @@ const useWiredState = () =>
return [];
});
setAllowsFurni(WiredFurniType.STUFF_SELECTION_OPTION_NONE);
- setSelectByType(false);
setNeighborhoodTiles(null);
setNeighborhoodInvert(false);
setAllowedInteractionTypes(null);
@@ -311,7 +310,7 @@ const useWiredState = () =>
};
}, [ trigger ]);
- return { trigger, setTrigger, intParams, setIntParams, stringParam, setStringParam, furniIds, setFurniIds, actionDelay, setActionDelay, setAllowsFurni, saveWired, selectObjectForWired, setSelectByType, setNeighborhoodTiles, setNeighborhoodInvert, setAllowedInteractionTypes, setAllowedInteractionErrorKey };
+ return { trigger, setTrigger, intParams, setIntParams, stringParam, setStringParam, furniIds, setFurniIds, actionDelay, setActionDelay, setAllowsFurni, saveWired, selectObjectForWired, setNeighborhoodTiles, setNeighborhoodInvert, setAllowedInteractionTypes, setAllowedInteractionErrorKey };
};
export const useWired = () => useBetween(useWiredState);
diff --git a/vite.config.mjs b/vite.config.mjs
index 772bb5f..8e54d8e 100644
--- a/vite.config.mjs
+++ b/vite.config.mjs
@@ -1,9 +1,15 @@
import react from '@vitejs/plugin-react';
+import { existsSync } from 'fs';
import { resolve } from 'path';
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
-const renderer3 = resolve(__dirname, '..', 'renderer3');
+const rendererCandidates = [
+ resolve(__dirname, '..', 'Nitro_Render_V3'),
+ resolve(__dirname, '..', 'renderer3')
+];
+
+const renderer3 = rendererCandidates.find(path => existsSync(path)) ?? rendererCandidates[0];
export default defineConfig({
plugins: [ react(), tsconfigPaths() ],
@@ -39,7 +45,7 @@ export default defineConfig({
'@nitrots/sound': resolve(renderer3, 'packages/sound/src/index.ts'),
'@nitrots/utils/src': resolve(renderer3, 'packages/utils/src'),
'@nitrots/utils': resolve(renderer3, 'packages/utils/src/index.ts'),
- // Resolve pixi.js and pixi-filters from renderer3's node_modules
+ // Resolve renderer peer dependencies from the renderer workspace
'pixi.js': resolve(renderer3, 'node_modules/pixi.js'),
'pixi-filters': resolve(renderer3, 'node_modules/pixi-filters'),
'howler': resolve(renderer3, 'node_modules/howler'),
@@ -55,7 +61,7 @@ export default defineConfig({
{
if(id.includes('node_modules'))
{
- if(id.includes('@nitrots/nitro-renderer') || id.includes('renderer3')) return 'nitro-renderer';
+ if(id.includes('@nitrots/nitro-renderer') || id.includes('renderer3') || id.includes('Nitro_Render_V3')) return 'nitro-renderer';
return 'vendor';
}