From 44f0ddcbad2c93a17b94707aa5adb2137edb6dad Mon Sep 17 00:00:00 2001 From: Dan512 Date: Sat, 21 Feb 2026 17:01:24 -0600 Subject: [PATCH 1/3] Add pushable/pullable actor system with collision checks --- appData/engine/engine.json | 563 +++++++++++++++--- .../actor/ActorEditorExtraCollisionFlags.tsx | 40 +- .../editors/actor/ActorEditorProperties.tsx | 13 +- .../editors/actor/ActorEditorScripts.tsx | 115 ++-- .../ActorPrefabEditorExtraCollisionFlags.tsx | 23 +- .../prefab/ActorPrefabEditorProperties.tsx | 12 +- .../prefab/ActorPrefabEditorScripts.tsx | 69 ++- src/lang/en.json | 26 + src/lib/compiler/compileData.ts | 2 +- src/lib/compiler/generateGBVMData.ts | 6 + .../compiler/scriptBuilder/scriptBuilder.ts | 92 +++ src/lib/events/eventIfPulledDirection.js | 98 +++ src/lib/events/eventIfPushedDirection.js | 98 +++ src/shared/lib/resources/types.ts | 2 + src/store/features/engine/engineState.ts | 1 + 15 files changed, 1000 insertions(+), 160 deletions(-) create mode 100644 src/lib/events/eventIfPulledDirection.js create mode 100644 src/lib/events/eventIfPushedDirection.js diff --git a/appData/engine/engine.json b/appData/engine/engine.json index 96cd723f39..84aab9a03b 100644 --- a/appData/engine/engine.json +++ b/appData/engine/engine.json @@ -9,10 +9,22 @@ "group": "GAMETYPE_PLATFORMER", "type": "togglebuttons", "options": [ - ["INPUT_A", "A"], - ["INPUT_B", "B"], - ["INPUT_UP", "FIELD_DIRECTION_UP"], - ["INPUT_DOWN", "FIELD_DIRECTION_DOWN"] + [ + "INPUT_A", + "A" + ], + [ + "INPUT_B", + "B" + ], + [ + "INPUT_UP", + "FIELD_DIRECTION_UP" + ], + [ + "INPUT_DOWN", + "FIELD_DIRECTION_DOWN" + ] ], "cType": "define", "defaultValue": "INPUT_A" @@ -25,10 +37,22 @@ "group": "GAMETYPE_PLATFORMER", "type": "togglebuttons", "options": [ - ["FALSE", "FIELD_NONE"], - ["INPUT_A_PRESSED", "A"], - ["INPUT_B_PRESSED", "B"], - ["INPUT_UP_PRESSED", "FIELD_DIRECTION_UP"] + [ + "FALSE", + "FIELD_NONE" + ], + [ + "INPUT_A_PRESSED", + "A" + ], + [ + "INPUT_B_PRESSED", + "B" + ], + [ + "INPUT_UP_PRESSED", + "FIELD_DIRECTION_UP" + ] ], "cType": "define", "defaultValue": "INPUT_UP_PRESSED" @@ -98,7 +122,6 @@ "max": 768, "editUnits": "subpxVelPrecise" }, - { "key": "plat_grav", "sceneType": "PLATFORM", @@ -112,7 +135,6 @@ "max": 8192, "editUnits": "subpxAccPrecise" }, - { "key": "plat_max_fall_vel", "sceneType": "PLATFORM", @@ -177,10 +199,22 @@ "group": "GAMETYPE_PLATFORMER", "type": "select", "options": [ - ["PLATFORM_CAMERA_LOCK_SCREEN_NONE", "FIELD_NONE"], - ["PLATFORM_CAMERA_LOCK_SCREEN_LEFT", "FIELD_LEFT"], - ["PLATFORM_CAMERA_LOCK_SCREEN_RIGHT", "FIELD_RIGHT"], - ["PLATFORM_CAMERA_LOCK_SCREEN_BOTH", "FIELD_BOTH"] + [ + "PLATFORM_CAMERA_LOCK_SCREEN_NONE", + "FIELD_NONE" + ], + [ + "PLATFORM_CAMERA_LOCK_SCREEN_LEFT", + "FIELD_LEFT" + ], + [ + "PLATFORM_CAMERA_LOCK_SCREEN_RIGHT", + "FIELD_RIGHT" + ], + [ + "PLATFORM_CAMERA_LOCK_SCREEN_BOTH", + "FIELD_BOTH" + ] ], "cType": "UBYTE", "defaultValue": "PLATFORM_CAMERA_LOCK_SCREEN_NONE" @@ -221,8 +255,14 @@ "group": "GAMETYPE_PLATFORMER", "type": "togglebuttons", "options": [ - ["INPUT_A", "A"], - ["INPUT_B", "B"] + [ + "INPUT_A", + "A" + ], + [ + "INPUT_B", + "B" + ] ], "cType": "define", "defaultValue": "INPUT_B", @@ -242,9 +282,18 @@ "group": "GAMETYPE_PLATFORMER", "type": "select", "options": [ - ["RUN_STYLE_DEFAULT", "FIELD_DEFAULT"], - ["RUN_STYLE_SMOOTH", "FIELD_RUN_STYLE_SMOOTH"], - ["RUN_STYLE_INSTANT", "FIELD_INSTANT"] + [ + "RUN_STYLE_DEFAULT", + "FIELD_DEFAULT" + ], + [ + "RUN_STYLE_SMOOTH", + "FIELD_RUN_STYLE_SMOOTH" + ], + [ + "RUN_STYLE_INSTANT", + "FIELD_INSTANT" + ] ], "cType": "define", "defaultValue": "RUN_STYLE_DEFAULT", @@ -336,9 +385,18 @@ "group": "GAMETYPE_PLATFORMER", "type": "togglebuttons", "options": [ - ["INPUT_A", "A"], - ["INPUT_B", "B"], - ["INPUT_UP", "FIELD_DIRECTION_UP"] + [ + "INPUT_A", + "A" + ], + [ + "INPUT_B", + "B" + ], + [ + "INPUT_UP", + "FIELD_DIRECTION_UP" + ] ], "cType": "define", "defaultValue": "INPUT_A", @@ -768,10 +826,22 @@ "group": "GAMETYPE_PLATFORMER", "type": "select", "options": [ - ["DROP_THRU_INPUT_DOWN_HOLD", "FIELD_DOWN_HOLD"], - ["DROP_THRU_INPUT_DOWN_TAP", "FIELD_DOWN_TAP"], - ["DROP_THRU_INPUT_DOWN_JUMP_HOLD", "FIELD_DOWN_AND_JUMP_HOLD"], - ["DROP_THRU_INPUT_DOWN_JUMP_TAP", "FIELD_DOWN_AND_JUMP_TAP"] + [ + "DROP_THRU_INPUT_DOWN_HOLD", + "FIELD_DOWN_HOLD" + ], + [ + "DROP_THRU_INPUT_DOWN_TAP", + "FIELD_DOWN_TAP" + ], + [ + "DROP_THRU_INPUT_DOWN_JUMP_HOLD", + "FIELD_DOWN_AND_JUMP_HOLD" + ], + [ + "DROP_THRU_INPUT_DOWN_JUMP_TAP", + "FIELD_DOWN_AND_JUMP_TAP" + ] ], "cType": "define", "defaultValue": "DROP_THRU_INPUT_DOWN_JUMP_TAP", @@ -836,8 +906,14 @@ "group": "GAMETYPE_PLATFORMER", "type": "select", "options": [ - ["FLOAT_INPUT_HOLD_JUMP", "FIELD_JUMP_HOLD"], - ["FLOAT_INPUT_HOLD_UP", "FIELD_UP_HOLD"] + [ + "FLOAT_INPUT_HOLD_JUMP", + "FIELD_JUMP_HOLD" + ], + [ + "FLOAT_INPUT_HOLD_UP", + "FIELD_UP_HOLD" + ] ], "cType": "define", "defaultValue": "FLOAT_INPUT_HOLD_JUMP", @@ -1050,11 +1126,26 @@ "group": "GAMETYPE_PLATFORMER", "type": "select", "options": [ - ["DASH_INPUT_INTERACT", "FIELD_INTERACT_TAP"], - ["DASH_INPUT_DOUBLE_TAP", "FIELD_DIR_DOUBLE_TAP"], - ["DASH_INPUT_DOWN_JUMP", "FIELD_DOWN_AND_JUMP_TAP"], - ["DASH_INPUT_A", "A"], - ["DASH_INPUT_B", "B"] + [ + "DASH_INPUT_INTERACT", + "FIELD_INTERACT_TAP" + ], + [ + "DASH_INPUT_DOUBLE_TAP", + "FIELD_DIR_DOUBLE_TAP" + ], + [ + "DASH_INPUT_DOWN_JUMP", + "FIELD_DOWN_AND_JUMP_TAP" + ], + [ + "DASH_INPUT_A", + "A" + ], + [ + "DASH_INPUT_B", + "B" + ] ], "cType": "define", "defaultValue": "DASH_INPUT_DOUBLE_TAP", @@ -1074,9 +1165,18 @@ "group": "GAMETYPE_PLATFORMER", "type": "mask", "options": [ - [1, "FIELD_GROUND"], - [2, "FIELD_AIR"], - [4, "FIELD_LADDER"] + [ + 1, + "FIELD_GROUND" + ], + [ + 2, + "FIELD_AIR" + ], + [ + 4, + "FIELD_LADDER" + ] ], "cType": "UBYTE", "defaultValue": 3, @@ -1096,9 +1196,18 @@ "group": "GAMETYPE_PLATFORMER", "type": "mask", "options": [ - [-4, "FIELD_ACTORS"], - [-8, "FIELD_TRIGGERS"], - [-16, "FIELD_WALLS"] + [ + -4, + "FIELD_ACTORS" + ], + [ + -8, + "FIELD_TRIGGERS" + ], + [ + -16, + "FIELD_WALLS" + ] ], "cType": "UBYTE", "defaultValue": 255, @@ -1195,8 +1304,14 @@ "group": "GAMETYPE_PLATFORMER", "type": "mask", "options": [ - [1, "FIELD_GROUND"], - [2, "FIELD_AIR"] + [ + 1, + "FIELD_GROUND" + ], + [ + 2, + "FIELD_AIR" + ] ], "cType": "UBYTE", "defaultValue": 1, @@ -1474,14 +1589,38 @@ "type": "select", "cType": "UBYTE", "options": [ - ["PLATFORM_FALL_STATE", "FIELD_FALL_STATE"], - ["PLATFORM_GROUND_STATE", "FIELD_GROUND_STATE"], - ["PLATFORM_JUMP_STATE", "FIELD_JUMP_STATE"], - ["PLATFORM_DASH_STATE", "FIELD_DASH_STATE"], - ["PLATFORM_LADDER_STATE", "FIELD_LADDER_STATE"], - ["PLATFORM_WALL_STATE", "FIELD_WALL_STATE"], - ["PLATFORM_KNOCKBACK_STATE", "FIELD_KNOCKBACK_STATE"], - ["PLATFORM_BLANK_STATE", "FIELD_BLANK_STATE"] + [ + "PLATFORM_FALL_STATE", + "FIELD_FALL_STATE" + ], + [ + "PLATFORM_GROUND_STATE", + "FIELD_GROUND_STATE" + ], + [ + "PLATFORM_JUMP_STATE", + "FIELD_JUMP_STATE" + ], + [ + "PLATFORM_DASH_STATE", + "FIELD_DASH_STATE" + ], + [ + "PLATFORM_LADDER_STATE", + "FIELD_LADDER_STATE" + ], + [ + "PLATFORM_WALL_STATE", + "FIELD_WALL_STATE" + ], + [ + "PLATFORM_KNOCKBACK_STATE", + "FIELD_KNOCKBACK_STATE" + ], + [ + "PLATFORM_BLANK_STATE", + "FIELD_BLANK_STATE" + ] ], "defaultValue": "PLATFORM_FALL_STATE", "runtimeOnly": true @@ -1494,8 +1633,14 @@ "group": "GAMETYPE_SHMUP", "type": "select", "options": [ - ["MOVEMENT_TYPE_FREE", "FIELD_FREE_MOVEMENT"], - ["MOVEMENT_TYPE_LOCK_PERPENDICULAR", "FIELD_LOCKED_MOVEMENT"] + [ + "MOVEMENT_TYPE_FREE", + "FIELD_FREE_MOVEMENT" + ], + [ + "MOVEMENT_TYPE_LOCK_PERPENDICULAR", + "FIELD_LOCKED_MOVEMENT" + ] ], "cType": "define", "defaultValue": "MOVEMENT_TYPE_FREE" @@ -1521,8 +1666,14 @@ "group": "GAMETYPE_SHMUP", "type": "select", "options": [ - ["ON_PLAYER_COLLISION", "FIELD_ON_PLAYER_COLLISION"], - ["ON_SCREEN_ENTER", "FIELD_ON_SCREEN_ENTER"] + [ + "ON_PLAYER_COLLISION", + "FIELD_ON_PLAYER_COLLISION" + ], + [ + "ON_SCREEN_ENTER", + "FIELD_ON_SCREEN_ENTER" + ] ], "cType": "define", "defaultValue": "ON_PLAYER_COLLISION" @@ -1535,10 +1686,22 @@ "group": "GAMETYPE_SHMUP", "type": "togglebuttons", "options": [ - ["COLLISION_GROUP_NONE", "FIELD_NONE"], - ["COLLISION_GROUP_1", "1"], - ["COLLISION_GROUP_2", "2"], - ["COLLISION_GROUP_3", "3"] + [ + "COLLISION_GROUP_NONE", + "FIELD_NONE" + ], + [ + "COLLISION_GROUP_1", + "1" + ], + [ + "COLLISION_GROUP_2", + "2" + ], + [ + "COLLISION_GROUP_3", + "3" + ] ], "cType": "define", "defaultValue": "COLLISION_GROUP_NONE" @@ -1551,8 +1714,14 @@ "group": "GAMETYPE_TOP_DOWN", "type": "togglebuttons", "options": [ - ["INPUT_A", "A"], - ["INPUT_B", "B"] + [ + "INPUT_A", + "A" + ], + [ + "INPUT_B", + "B" + ] ], "cType": "define", "defaultValue": "INPUT_A" @@ -1565,8 +1734,14 @@ "group": "GAMETYPE_TOP_DOWN", "type": "select", "options": [ - [8, "FIELD_GRID_8PX"], - [16, "FIELD_GRID_16PX"] + [ + 8, + "FIELD_GRID_8PX" + ], + [ + 16, + "FIELD_GRID_16PX" + ] ], "cType": "UBYTE", "defaultValue": 8 @@ -1578,8 +1753,14 @@ "group": "SETTINGS_FADE", "type": "select", "options": [ - [0, "FIELD_FADE_WHITE"], - [1, "FIELD_FADE_BLACK"] + [ + 0, + "FIELD_FADE_WHITE" + ], + [ + 1, + "FIELD_FADE_BLACK" + ] ], "cType": "UBYTE", "defaultValue": 0 @@ -1592,8 +1773,14 @@ "group": "GAMETYPE_ADVENTURE", "type": "togglebuttons", "options": [ - ["INPUT_A", "A"], - ["INPUT_B", "B"] + [ + "INPUT_A", + "A" + ], + [ + "INPUT_B", + "B" + ] ], "cType": "define", "defaultValue": "INPUT_A" @@ -1606,8 +1793,14 @@ "group": "GAMETYPE_ADVENTURE", "type": "select", "options": [ - ["MOVE_TYPE_4_WAY", "FIELD_4_WAY"], - ["MOVE_TYPE_8_WAY", "FIELD_8_WAY"] + [ + "MOVE_TYPE_4_WAY", + "FIELD_4_WAY" + ], + [ + "MOVE_TYPE_8_WAY", + "FIELD_8_WAY" + ] ], "cType": "define", "defaultValue": "MOVE_TYPE_8_WAY" @@ -1620,8 +1813,14 @@ "group": "GAMETYPE_ADVENTURE", "type": "select", "options": [ - ["DIRECTION_TYPE_4_WAY", "FIELD_4_WAY"], - ["DIRECTION_TYPE_HORIZONTAL", "FIELD_HORIZONTAL_ONLY"] + [ + "DIRECTION_TYPE_4_WAY", + "FIELD_4_WAY" + ], + [ + "DIRECTION_TYPE_HORIZONTAL", + "FIELD_HORIZONTAL_ONLY" + ] ], "cType": "define", "defaultValue": "DIRECTION_TYPE_4_WAY" @@ -1714,8 +1913,14 @@ "group": "GAMETYPE_ADVENTURE", "type": "togglebuttons", "options": [ - ["INPUT_A", "A"], - ["INPUT_B", "B"] + [ + "INPUT_A", + "A" + ], + [ + "INPUT_B", + "B" + ] ], "cType": "define", "defaultValue": "INPUT_B", @@ -1820,10 +2025,22 @@ "group": "GAMETYPE_ADVENTURE", "type": "select", "options": [ - ["DASH_INPUT_INTERACT", "FIELD_INTERACT_TAP"], - ["DASH_INPUT_DOUBLE_TAP", "FIELD_DPAD_DOUBLE_TAP"], - ["DASH_INPUT_A", "A"], - ["DASH_INPUT_B", "B"] + [ + "DASH_INPUT_INTERACT", + "FIELD_INTERACT_TAP" + ], + [ + "DASH_INPUT_DOUBLE_TAP", + "FIELD_DPAD_DOUBLE_TAP" + ], + [ + "DASH_INPUT_A", + "A" + ], + [ + "DASH_INPUT_B", + "B" + ] ], "cType": "define", "defaultValue": "DASH_INPUT_DOUBLE_TAP", @@ -1843,9 +2060,18 @@ "group": "GAMETYPE_ADVENTURE", "type": "mask", "options": [ - [-4, "FIELD_ACTORS"], - [-8, "FIELD_TRIGGERS"], - [-16, "FIELD_WALLS"] + [ + -4, + "FIELD_ACTORS" + ], + [ + -8, + "FIELD_TRIGGERS" + ], + [ + -16, + "FIELD_WALLS" + ] ], "cType": "UBYTE", "defaultValue": 255, @@ -1981,6 +2207,91 @@ } ] }, + { + "key": "adv_push_grace_frames", + "sceneType": "ADVENTURE", + "label": "FIELD_PUSH_GRACE_FRAMES", + "description": "FIELD_PUSH_GRACE_FRAMES_DESC", + "group": "GAMETYPE_ADVENTURE", + "type": "slider", + "cType": "UBYTE", + "defaultValue": 4, + "min": 0, + "max": 30, + "indent": 1, + "conditions": [ + { + "key": "FEAT_ADVENTURE_PUSH", + "truthy": true + } + ] + }, + { + "key": "FEAT_ADVENTURE_PULL", + "sceneType": "ADVENTURE", + "label": "FIELD_FEAT_PULL", + "description": "FIELD_FEAT_PULL_DESC", + "group": "GAMETYPE_ADVENTURE", + "type": "checkbox", + "cType": "define", + "isHeading": true, + "defaultValue": 0 + }, + { + "key": "ADVENTURE_PULL_ANIM", + "sceneType": "ADVENTURE", + "label": "FIELD_PULL_ANIM_STATE", + "description": "FIELD_PULL_ANIM_STATE_DESC", + "group": "GAMETYPE_ADVENTURE", + "type": "animationstate", + "cType": "define", + "defaultValue": "", + "indent": 1, + "conditions": [ + { + "key": "FEAT_ADVENTURE_PULL", + "truthy": true + } + ] + }, + { + "key": "adv_pull_delay_frames", + "sceneType": "ADVENTURE", + "label": "FIELD_PULL_DELAY_FRAMES", + "description": "FIELD_PULL_DELAY_FRAMES_DESC", + "group": "GAMETYPE_ADVENTURE", + "type": "slider", + "cType": "UBYTE", + "defaultValue": 5, + "min": 0, + "max": 60, + "indent": 1, + "conditions": [ + { + "key": "FEAT_ADVENTURE_PULL", + "truthy": true + } + ] + }, + { + "key": "adv_pull_grace_frames", + "sceneType": "ADVENTURE", + "label": "FIELD_PULL_GRACE_FRAMES", + "description": "FIELD_PULL_GRACE_FRAMES_DESC", + "group": "GAMETYPE_ADVENTURE", + "type": "slider", + "cType": "UBYTE", + "defaultValue": 4, + "min": 0, + "max": 30, + "indent": 1, + "conditions": [ + { + "key": "FEAT_ADVENTURE_PULL", + "truthy": true + } + ] + }, { "key": "FEAT_ADVENTURE_KNOCKBACK", "sceneType": "ADVENTURE", @@ -2105,12 +2416,30 @@ "type": "select", "cType": "UBYTE", "options": [ - ["ADVENTURE_GROUND_STATE", "FIELD_GROUND_STATE"], - ["ADVENTURE_DASH_STATE", "FIELD_DASH_STATE"], - ["ADVENTURE_KNOCKBACK_STATE", "FIELD_KNOCKBACK_STATE"], - ["ADVENTURE_BLANK_STATE", "FIELD_BLANK_STATE"], - ["ADVENTURE_RUN_STATE", "FIELD_RUN_STATE"], - ["ADVENTURE_PUSH_STATE", "FIELD_PUSH_STATE"] + [ + "ADVENTURE_GROUND_STATE", + "FIELD_GROUND_STATE" + ], + [ + "ADVENTURE_DASH_STATE", + "FIELD_DASH_STATE" + ], + [ + "ADVENTURE_KNOCKBACK_STATE", + "FIELD_KNOCKBACK_STATE" + ], + [ + "ADVENTURE_BLANK_STATE", + "FIELD_BLANK_STATE" + ], + [ + "ADVENTURE_RUN_STATE", + "FIELD_RUN_STATE" + ], + [ + "ADVENTURE_PUSH_STATE", + "FIELD_PUSH_STATE" + ] ], "defaultValue": "ADVENTURE_GROUND_STATE", "runtimeOnly": true @@ -2200,7 +2529,10 @@ { "key": "TOPDOWN", "label": "GAMETYPE_TOP_DOWN", - "files": ["include/states/topdown.h", "src/states/topdown.c"], + "files": [ + "include/states/topdown.h", + "src/states/topdown.c" + ], "collisionTiles": [ { "key": "solid", @@ -2251,21 +2583,28 @@ { "key": "PLATFORM", "label": "GAMETYPE_PLATFORMER", - "files": ["include/states/platform.h", "src/states/platform.c"], + "files": [ + "include/states/platform.h", + "src/states/platform.c" + ], "extraActorCollisionFlags": [ { "key": "solid", "label": "FIELD_IS_SOLID", "description": "FIELD_IS_SOLID_DESC", "setFlag": "solid", - "clearFlags": ["platform"] + "clearFlags": [ + "platform" + ] }, { "key": "platform", "label": "FIELD_IS_PLATFORM", "description": "FIELD_IS_PLATFORM_DESC", "setFlag": "platform", - "clearFlags": ["solid"] + "clearFlags": [ + "solid" + ] } ], "collisionTiles": [ @@ -2387,13 +2726,40 @@ { "key": "ADVENTURE", "label": "GAMETYPE_ADVENTURE", - "files": ["include/states/adventure.h", "src/states/adventure.c"], + "files": [ + "include/states/adventure.h", + "src/states/adventure.c" + ], "extraActorCollisionFlags": [ { "key": "solid", "label": "FIELD_IS_SOLID", "description": "FIELD_IS_SOLID_DESC", "setFlag": "solid" + }, + { + "key": "pushable", + "label": "FIELD_IS_PUSHABLE", + "description": "FIELD_IS_PUSHABLE_DESC", + "setFlag": "pushable", + "conditions": [ + { + "key": "solid", + "truthy": true + } + ] + }, + { + "key": "pullable", + "label": "FIELD_IS_PULLABLE", + "description": "FIELD_IS_PULLABLE_DESC", + "setFlag": "pullable", + "conditions": [ + { + "key": "solid", + "truthy": true + } + ] } ], "collisionTiles": [ @@ -2476,13 +2842,16 @@ "name": "FIELD_COLLISION_SLOPE_BOTTOM_RIGHT", "icon": "0F0F1F3FFEFEFCF0", "group": "corner" - } + } ] }, { "key": "SHMUP", "label": "GAMETYPE_SHMUP", - "files": ["include/states/shmup.h", "src/states/shmup.c"], + "files": [ + "include/states/shmup.h", + "src/states/shmup.c" + ], "collisionTiles": [ { "key": "solid", @@ -2533,7 +2902,10 @@ { "key": "POINTNCLICK", "label": "GAMETYPE_POINT_N_CLICK", - "files": ["include/states/pointnclick.h", "src/states/pointnclick.c"], + "files": [ + "include/states/pointnclick.h", + "src/states/pointnclick.c" + ], "collisionTiles": [ { "key": "solid", @@ -2548,7 +2920,10 @@ { "key": "LOGO", "label": "GAMETYPE_LOGO", - "files": ["include/states/logo.h", "src/states/logo.c"], + "files": [ + "include/states/logo.h", + "src/states/logo.c" + ], "collisionTiles": [ { "key": "solid", @@ -2561,4 +2936,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/src/components/editors/actor/ActorEditorExtraCollisionFlags.tsx b/src/components/editors/actor/ActorEditorExtraCollisionFlags.tsx index f9c9eaf5ea..a92ee18b11 100644 --- a/src/components/editors/actor/ActorEditorExtraCollisionFlags.tsx +++ b/src/components/editors/actor/ActorEditorExtraCollisionFlags.tsx @@ -11,6 +11,7 @@ import { import { sceneSelectors } from "store/features/entities/entitiesState"; import l10n, { L10NKey } from "shared/lib/lang/l10n"; import { ExtraActorCollisionFlagDef } from "store/features/engine/engineState"; +import { CollisionExtraFlag } from "shared/lib/resources/types"; interface ActorEditorExtraCollisionFlagsProps { actor: ActorNormalized; @@ -57,11 +58,22 @@ export const ActorEditorExtraCollisionFlags: FC< return <>; } + // Filter flags based on conditions (e.g. pushable requires solid to be set) + const visibleFlags = extraActorCollisionFlags.filter((flagDef) => { + if (!flagDef.conditions) return true; + return flagDef.conditions.every((cond) => { + const isSet = actor.collisionExtraFlags.includes( + cond.key as CollisionExtraFlag, + ); + return cond.truthy ? isSet : !isSet; + }); + }); + return Array.from({ - length: Math.ceil(extraActorCollisionFlags.length / 2), + length: Math.ceil(visibleFlags.length / 2), }).map((_, rowIndex) => { const startIndex = rowIndex * 2; - const items = extraActorCollisionFlags.slice(startIndex, startIndex + 2); + const items = visibleFlags.slice(startIndex, startIndex + 2); return ( @@ -77,16 +89,24 @@ export const ActorEditorExtraCollisionFlags: FC< } checked={actor.collisionExtraFlags.includes(flagDef.setFlag)} onChange={() => { - onChangeActorProp( - "collisionExtraFlags", - removeArrayElements( - toggleArrayElement( - actor.collisionExtraFlags, - flagDef.setFlag, - ), - flagDef.clearFlags ?? [], + const newFlags = removeArrayElements( + toggleArrayElement( + actor.collisionExtraFlags, + flagDef.setFlag, ), + flagDef.clearFlags ?? [], ); + onChangeActorProp("collisionExtraFlags", newFlags); + // Pushable/pullable actors must not have a collision group set, + // otherwise the collision group handler takes priority + // and the pushed/pulled script never fires. + if ( + (flagDef.setFlag === "pushable" || flagDef.setFlag === "pullable") && + newFlags.includes(flagDef.setFlag as CollisionExtraFlag) && + actor.collisionGroup + ) { + onChangeActorProp("collisionGroup", ""); + } }} /> ))} diff --git a/src/components/editors/actor/ActorEditorProperties.tsx b/src/components/editors/actor/ActorEditorProperties.tsx index 65a14c2c71..64602173bc 100644 --- a/src/components/editors/actor/ActorEditorProperties.tsx +++ b/src/components/editors/actor/ActorEditorProperties.tsx @@ -65,9 +65,18 @@ export const ActorEditorProperties: FC = ({ [onChangeActorProp], ); + const isPushableOrPullable = + (actor?.collisionExtraFlags?.includes("pushable") || + actor?.collisionExtraFlags?.includes("pullable")) && + actor?.collisionExtraFlags?.includes("solid"); + const onChangeCollisionGroup = useCallback( - (e: CollisionGroup) => onChangeActorProp("collisionGroup", e), - [onChangeActorProp], + (e: CollisionGroup) => { + // Pushable/pullable actors must not have a collision group set + if (isPushableOrPullable && e !== "") return; + onChangeActorProp("collisionGroup", e); + }, + [onChangeActorProp, isPushableOrPullable], ); const onlyCurrentSpriteMode = useCallback( diff --git a/src/components/editors/actor/ActorEditorScripts.tsx b/src/components/editors/actor/ActorEditorScripts.tsx index e688246c6e..2cf03cbaa4 100644 --- a/src/components/editors/actor/ActorEditorScripts.tsx +++ b/src/components/editors/actor/ActorEditorScripts.tsx @@ -32,6 +32,8 @@ interface ScriptHandlers { start: ScriptHandler; interact: ScriptHandler; update: ScriptHandler; + pushed: ScriptHandler; + pulled: ScriptHandler; hit: { hitPlayer: ScriptHandler; hit1: ScriptHandler; @@ -50,15 +52,24 @@ type ActorScriptKey = type DefaultTab = "interact" | "start" | "update"; type CollisionTab = "hit" | "start" | "update"; +type PushableTab = "pushed" | "start" | "update"; +type PullableTab = "pulled" | "start" | "update"; +type PushPullTab = "pushed" | "pulled" | "start" | "update"; type HitTab = "hitPlayer" | "hit1" | "hit2" | "hit3"; const getScriptKey = ( - primaryTab: DefaultTab | CollisionTab, + primaryTab: DefaultTab | CollisionTab | PushableTab | PullableTab | PushPullTab, secondaryTab: HitTab, ): ActorScriptKey => { if (primaryTab === "interact") { return "script"; } + if (primaryTab === "pushed") { + return "hit1Script"; + } + if (primaryTab === "pulled") { + return "hit2Script"; + } if (primaryTab === "start") { return "startScript"; } @@ -121,7 +132,53 @@ export const ActorEditorScripts: FC = ({ [], ); - const tabs = Object.keys(actor?.collisionGroup ? collisionTabs : defaultTabs); + const pushableTabs: Record = useMemo( + () => ({ + pushed: l10n("SIDEBAR_ON_PUSHED"), + start: l10n("SIDEBAR_ON_INIT"), + update: l10n("SIDEBAR_ON_UPDATE"), + }), + [], + ); + + const pullableTabs: Record = useMemo( + () => ({ + pulled: l10n("SIDEBAR_ON_PULLED"), + start: l10n("SIDEBAR_ON_INIT"), + update: l10n("SIDEBAR_ON_UPDATE"), + }), + [], + ); + + const pushPullTabs: Record = useMemo( + () => ({ + pushed: l10n("SIDEBAR_ON_PUSHED"), + pulled: l10n("SIDEBAR_ON_PULLED"), + start: l10n("SIDEBAR_ON_INIT"), + update: l10n("SIDEBAR_ON_UPDATE"), + }), + [], + ); + + const isPushable = + actor?.collisionExtraFlags?.includes("pushable") && + actor?.collisionExtraFlags?.includes("solid"); + + const isPullable = + actor?.collisionExtraFlags?.includes("pullable") && + actor?.collisionExtraFlags?.includes("solid"); + + const activeTabs = (isPushable && isPullable) + ? pushPullTabs + : isPushable + ? pushableTabs + : isPullable + ? pullableTabs + : actor?.collisionGroup + ? collisionTabs + : defaultTabs; + + const tabs = Object.keys(activeTabs); const secondaryTabs = Object.keys(hitTabs); const lastScriptTab = useAppSelector((state) => state.editor.lastScriptTab); const lastScriptTabSecondary = useAppSelector( @@ -139,16 +196,14 @@ export const ActorEditorScripts: FC = ({ keyof ScriptHandlers["hit"] >(initialSecondaryTab as keyof ScriptHandlers["hit"]); - // Make sure currently selected script tab is availble - // when collision group is modified otherwise use first available tab + // Make sure currently selected script tab is available + // when collision group or pushable is modified otherwise use first available tab useEffect(() => { - const tabs = Object.keys( - actor?.collisionGroup ? collisionTabs : defaultTabs, - ); + const tabs = Object.keys(activeTabs); if (!tabs.includes(scriptMode)) { setScriptMode(tabs[0] as keyof ScriptHandlers); } - }, [scriptMode, actor?.collisionGroup, collisionTabs, defaultTabs]); + }, [scriptMode, activeTabs]); const dispatch = useAppDispatch(); @@ -230,33 +285,23 @@ export const ActorEditorScripts: FC = ({ return ( <> - {actor.collisionGroup ? ( - - {lockButton} - {scriptButton} - - } - /> - ) : ( - - {lockButton} - {scriptButton} - - } - /> - )} + } + onChange={onChangeScriptMode as (mode: DefaultTab & CollisionTab & PushableTab & PullableTab & PushPullTab) => void} + overflowActiveTab={ + scriptMode === "hit" || + scriptMode === "update" || + (scriptMode as string) === "pushed" || + (scriptMode as string) === "pulled" + } + buttons={ + <> + {lockButton} + {scriptButton} + + } + /> {scriptMode === "hit" && ( { - onChangeActorPrefabProp( - "collisionExtraFlags", - removeArrayElements( - toggleArrayElement( - prefab.collisionExtraFlags, - flagDef.setFlag, - ), - flagDef.clearFlags ?? [], + const newFlags = removeArrayElements( + toggleArrayElement( + prefab.collisionExtraFlags, + flagDef.setFlag, ), + flagDef.clearFlags ?? [], ); + onChangeActorPrefabProp("collisionExtraFlags", newFlags); + // Pushable/pullable actors must not have a collision group set + if ( + (flagDef.setFlag === "pushable" || flagDef.setFlag === "pullable") && + newFlags.includes(flagDef.setFlag as CollisionExtraFlag) && + prefab.collisionGroup + ) { + onChangeActorPrefabProp("collisionGroup", ""); + } }} /> ))} diff --git a/src/components/editors/prefab/ActorPrefabEditorProperties.tsx b/src/components/editors/prefab/ActorPrefabEditorProperties.tsx index dda1b232ef..f09988566a 100644 --- a/src/components/editors/prefab/ActorPrefabEditorProperties.tsx +++ b/src/components/editors/prefab/ActorPrefabEditorProperties.tsx @@ -67,9 +67,17 @@ export const ActorPrefabEditorProperties: FC< [onChangeActorPrefabProp], ); + const isPushableOrPullable = + (prefab?.collisionExtraFlags?.includes("pushable") || + prefab?.collisionExtraFlags?.includes("pullable")) && + prefab?.collisionExtraFlags?.includes("solid"); + const onChangeCollisionGroup = useCallback( - (e: CollisionGroup) => onChangeActorPrefabProp("collisionGroup", e), - [onChangeActorPrefabProp], + (e: CollisionGroup) => { + if (isPushableOrPullable && e !== "") return; + onChangeActorPrefabProp("collisionGroup", e); + }, + [onChangeActorPrefabProp, isPushableOrPullable], ); const onlyCurrentSpriteMode = useCallback( diff --git a/src/components/editors/prefab/ActorPrefabEditorScripts.tsx b/src/components/editors/prefab/ActorPrefabEditorScripts.tsx index c123bca7f5..8ec27ec23e 100644 --- a/src/components/editors/prefab/ActorPrefabEditorScripts.tsx +++ b/src/components/editors/prefab/ActorPrefabEditorScripts.tsx @@ -34,6 +34,8 @@ interface ScriptHandlers { start: ScriptHandler; interact: ScriptHandler; update: ScriptHandler; + pushed: ScriptHandler; + pulled: ScriptHandler; hit: { hitPlayer: ScriptHandler; hit1: ScriptHandler; @@ -52,15 +54,24 @@ type ActorScriptKey = type DefaultTab = "interact" | "start" | "update"; type CollisionTab = "hit" | "start" | "update"; +type PushableTab = "pushed" | "start" | "update"; +type PullableTab = "pulled" | "start" | "update"; +type PushPullTab = "pushed" | "pulled" | "start" | "update"; type HitTab = "hitPlayer" | "hit1" | "hit2" | "hit3"; const getScriptKey = ( - primaryTab: DefaultTab | CollisionTab, + primaryTab: DefaultTab | CollisionTab | PushableTab | PullableTab | PushPullTab, secondaryTab: HitTab, ): ActorScriptKey => { if (primaryTab === "interact") { return "script"; } + if (primaryTab === "pushed") { + return "hit1Script"; + } + if (primaryTab === "pulled") { + return "hit2Script"; + } if (primaryTab === "start") { return "startScript"; } @@ -122,9 +133,53 @@ export const ActorPrefabEditorScripts: FC = ({ [], ); - const tabs = Object.keys( - prefab?.collisionGroup ? collisionTabs : defaultTabs, + const pushableTabs: Record = useMemo( + () => ({ + pushed: l10n("SIDEBAR_ON_PUSHED"), + start: l10n("SIDEBAR_ON_INIT"), + update: l10n("SIDEBAR_ON_UPDATE"), + }), + [], ); + + const pullableTabs: Record = useMemo( + () => ({ + pulled: l10n("SIDEBAR_ON_PULLED"), + start: l10n("SIDEBAR_ON_INIT"), + update: l10n("SIDEBAR_ON_UPDATE"), + }), + [], + ); + + const pushPullTabs: Record = useMemo( + () => ({ + pushed: l10n("SIDEBAR_ON_PUSHED"), + pulled: l10n("SIDEBAR_ON_PULLED"), + start: l10n("SIDEBAR_ON_INIT"), + update: l10n("SIDEBAR_ON_UPDATE"), + }), + [], + ); + + const isPushable = + prefab?.collisionExtraFlags?.includes("pushable") && + prefab?.collisionExtraFlags?.includes("solid"); + + const isPullable = + prefab?.collisionExtraFlags?.includes("pullable") && + prefab?.collisionExtraFlags?.includes("solid"); + + const activeTabs = (isPushable && isPullable) + ? pushPullTabs + : isPushable + ? pushableTabs + : isPullable + ? pullableTabs + : prefab?.collisionGroup + ? collisionTabs + : defaultTabs; + + const tabs = Object.keys(activeTabs); const secondaryTabs = Object.keys(hitTabs); const lastScriptTab = useAppSelector((state) => state.editor.lastScriptTab); const lastScriptTabSecondary = useAppSelector( @@ -143,15 +198,13 @@ export const ActorPrefabEditorScripts: FC = ({ >(initialSecondaryTab as keyof ScriptHandlers["hit"]); // Make sure currently selected script tab is availble - // when collision group is modified otherwise use first available tab + // when collision group or pushable/pullable is modified otherwise use first available tab useEffect(() => { - const tabs = Object.keys( - prefab?.collisionGroup ? collisionTabs : defaultTabs, - ); + const tabs = Object.keys(activeTabs); if (!tabs.includes(scriptMode)) { setScriptMode(tabs[0] as keyof ScriptHandlers); } - }, [scriptMode, prefab?.collisionGroup, collisionTabs, defaultTabs]); + }, [scriptMode, activeTabs]); const dispatch = useAppDispatch(); diff --git a/src/lang/en.json b/src/lang/en.json index d42f3e4faf..6ab06ce3f5 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -84,6 +84,8 @@ "SIDEBAR_ON_HIT": "On Hit", "SIDEBAR_ON_PLAYER_HIT": "On Player Hit", "SIDEBAR_ON_UPDATE": "On Update", + "SIDEBAR_ON_PUSHED": "On Pushed", + "SIDEBAR_ON_PULLED": "On Pulled", "SIDEBAR_SCENES": "Scenes", "SIDEBAR_VARIABLES": "Variables", "SIDEBAR_VARIABLE_USES": "Variable Uses", @@ -118,6 +120,8 @@ "FIELD_DIRECTION": "Direction", "FIELD_DIRECTION_DESC": "The actor direction.", "FIELD_DIRECTION_SCENE_DESC": "The initial player direction.", + "FIELD_HOLD_FRAMES": "Hold Frames", + "FIELD_HOLD_FRAMES_DESC": "Number of frames the player must hold the direction before this condition is true. Set to 0 for immediate.", "FIELD_X": "X", "FIELD_Y": "Y", "FIELD_WIDTH": "Width", @@ -1145,6 +1149,10 @@ "FIELD_DASH_DEADZONE_OVERRIDE_DESC": "Override the camera deadzone distance while dashing, determining how far the player can move from the screen center before the camera follows.", "FIELD_IS_SOLID": "Is Solid", "FIELD_IS_SOLID_DESC": "Sets if player should not be able to walk through this actor.", + "FIELD_IS_PUSHABLE": "Is Pushable", + "FIELD_IS_PUSHABLE_DESC": "Actor can be pushed by the player in Adventure scenes. Requires Is Solid to be enabled. Requires Collision Group set to \"None\".", + "FIELD_IS_PULLABLE": "Is Pullable", + "FIELD_IS_PULLABLE_DESC": "Actor can be pulled by the player in Adventure scenes. Hold the interact button and walk away from the actor. Requires Is Solid to be enabled.", "FIELD_IS_PLATFORM": "Is Platform", "FIELD_IS_PLATFORM_DESC": "Sets if player should be able to stand on this actor like a platform.", "FIELD_PLATFORM_LADDERS_ALLOW_DROP": "Allow Drop From Ladder", @@ -1262,6 +1270,16 @@ "FIELD_PUSH_ANIM_STATE_DESC": "The animation state to use when the player is in the pushing state.", "FIELD_PUSH_DELAY_FRAMES": "Push Delay Frames", "FIELD_PUSH_DELAY_FRAMES_DESC": "The number of frames the player must be pressing against an obstacle before entering the pushing state.", + "FIELD_PUSH_GRACE_FRAMES": "Push Grace Frames", + "FIELD_PUSH_GRACE_FRAMES_DESC": "The number of frames to remain in the push state after the player's position changes (e.g. when a pushed object moves away). Prevents flickering between push and ground animations.", + "FIELD_FEAT_PULL": "Enable Feature: Pulling State", + "FIELD_FEAT_PULL_DESC": "Enables setting player to a pulling state when holding the interact button and walking away from a pullable actor.", + "FIELD_PULL_ANIM_STATE": "Pulling Animation State", + "FIELD_PULL_ANIM_STATE_DESC": "The animation state to use when the player is in the pulling state.", + "FIELD_PULL_DELAY_FRAMES": "Pull Delay Frames", + "FIELD_PULL_DELAY_FRAMES_DESC": "The number of frames the player must hold the interact button and walk away before entering the pulling state.", + "FIELD_PULL_GRACE_FRAMES": "Pull Grace Frames", + "FIELD_PULL_GRACE_FRAMES_DESC": "The number of frames to remain in the pull state after the player's position changes. Prevents flickering between pull and ground animations.", "FIELD_PUSH_STATE": "Pushing", "FIELD_PUSH_START": "Start Pushing State", "FIELD_PUSH_END": "End Pushing State", @@ -1361,6 +1379,10 @@ "EVENT_IF_ACTOR_AT_POSITION_DESC": "Conditionally run part of the script if an actor is at a specified position.", "EVENT_IF_ACTOR_DIRECTION": "If Actor Facing Direction", "EVENT_IF_ACTOR_DIRECTION_DESC": "Conditionally run part of the script if an actor is facing in a specified direction.", + "EVENT_IF_PUSHED_DIRECTION": "If Pushed Direction", + "EVENT_IF_PUSHED_DIRECTION_DESC": "Conditionally run part of the script based on the direction the actor was pushed from and optionally how long the player has been pushing. Only works inside an 'On Pushed' script.", + "EVENT_IF_PULLED_DIRECTION": "If Pulled Direction", + "EVENT_IF_PULLED_DIRECTION_DESC": "Conditionally run part of the script based on the direction the actor was pulled and optionally how long the player has been pulling. Only works inside an 'On Pulled' script.", "EVENT_SET_TRUE": "Variable Set To 'True'", "EVENT_SET_TRUE_DESC": "Set the value of the specified variable to true.", "EVENT_SET_FALSE": "Variable Set To 'False'", @@ -1585,6 +1607,10 @@ "EVENT_IF_EXPRESSION_LABEL": "If {expression}", "EVENT_IF_ACTOR_AT_POSITION_LABEL": "If {actor} At Position {{x},{y}}", "EVENT_IF_ACTOR_DIRECTION_LABEL": "If {actor} Facing {direction}", + "EVENT_IF_PUSHED_DIRECTION_LABEL": "If Pushed {direction}", + "EVENT_IF_PUSHED_DIRECTION_FOR_LABEL": "If Pushed {direction} For {frames} Frames", + "EVENT_IF_PULLED_DIRECTION_LABEL": "If Pulled {direction}", + "EVENT_IF_PULLED_DIRECTION_FOR_LABEL": "If Pulled {direction} For {frames} Frames", "EVENT_IF_ACTOR_RELATIVE_TO_ACTOR_LABEL": "If {actor} {direction} {otherActor}", "EVENT_IF_ACTOR_DISTANCE_FROM_ACTOR_LABEL": "If {actor} is {operator} {distance} tiles from {otherActor}", "EVENT_SWITCH_SCENE_LABEL": "Change Scene To {scene} At {{x},{y}}", diff --git a/src/lib/compiler/compileData.ts b/src/lib/compiler/compileData.ts index 1cfc0bac79..b28a5715f2 100755 --- a/src/lib/compiler/compileData.ts +++ b/src/lib/compiler/compileData.ts @@ -1764,7 +1764,7 @@ const compile = async ( ); }), actors: scene.actors.map((entity, entityIndex) => { - if (!entity.collisionGroup) { + if (!entity.collisionGroup && !entity.collisionExtraFlags?.includes("pushable") && !entity.collisionExtraFlags?.includes("pullable")) { return compileScript( entity.script, "actor", diff --git a/src/lib/compiler/generateGBVMData.ts b/src/lib/compiler/generateGBVMData.ts index aa53e98fd1..34f9c1d16f 100644 --- a/src/lib/compiler/generateGBVMData.ts +++ b/src/lib/compiler/generateGBVMData.ts @@ -232,6 +232,12 @@ export const toASMCollisionGroup = ( if (group === "platform") { return "COLLISION_GROUP_FLAG_PLATFORM"; } + if (group === "pushable") { + return "COLLISION_GROUP_FLAG_PUSHABLE"; + } + if (group === "pullable") { + return "COLLISION_GROUP_FLAG_PULLABLE"; + } return ""; }) .filter((group) => group !== "") diff --git a/src/lib/compiler/scriptBuilder/scriptBuilder.ts b/src/lib/compiler/scriptBuilder/scriptBuilder.ts index 79a72b3378..fc4faacb49 100644 --- a/src/lib/compiler/scriptBuilder/scriptBuilder.ts +++ b/src/lib/compiler/scriptBuilder/scriptBuilder.ts @@ -3897,6 +3897,98 @@ class ScriptBuilder extends ScriptBuilderBase { this._addNL(); }; + ifPushedDirection = ( + direction: string, + holdFrames: number, + truePath: ScriptEvent[] | ScriptBuilderPathFunction = [], + falsePath: ScriptEvent[] | ScriptBuilderPathFunction = [], + ) => { + const pushDirRef = this._declareLocal("push_dir_value", 1, true); + const pushFramesRef = this._declareLocal("push_frames_value", 1, true); + if (!this.includeParams.includes(1)) { + this.includeParams.push(1); + } + if (!this.includeParams.includes(2)) { + this.includeParams.push(2); + } + const trueLabel = this.getNextLabel(); + const falseLabel = this.getNextLabel(); + const endLabel = this.getNextLabel(); + this._addComment(`If Pushed ${direction} for ${holdFrames} frames`); + this._getThreadLocal(pushDirRef, 1); + this._ifConst( + ".NE", + pushDirRef, + direction === "left" + ? ".DIR_LEFT" + : direction === "right" + ? ".DIR_RIGHT" + : direction === "up" + ? ".DIR_UP" + : ".DIR_DOWN", + falseLabel, + 0, + ); + if (holdFrames > 0) { + this._getThreadLocal(pushFramesRef, 2); + this._ifConst(".LT", pushFramesRef, holdFrames, falseLabel, 0); + } + this._jump(trueLabel); + this._label(falseLabel); + this._compilePath(falsePath); + this._jump(endLabel); + this._label(trueLabel); + this._compilePath(truePath); + this._label(endLabel); + this._addNL(); + }; + + ifPulledDirection = ( + direction: string, + holdFrames: number, + truePath: ScriptEvent[] | ScriptBuilderPathFunction = [], + falsePath: ScriptEvent[] | ScriptBuilderPathFunction = [], + ) => { + const pullDirRef = this._declareLocal("pull_dir_value", 1, true); + const pullFramesRef = this._declareLocal("pull_frames_value", 1, true); + if (!this.includeParams.includes(1)) { + this.includeParams.push(1); + } + if (!this.includeParams.includes(2)) { + this.includeParams.push(2); + } + const trueLabel = this.getNextLabel(); + const falseLabel = this.getNextLabel(); + const endLabel = this.getNextLabel(); + this._addComment(`If Pulled ${direction} for ${holdFrames} frames`); + this._getThreadLocal(pullDirRef, 1); + this._ifConst( + ".NE", + pullDirRef, + direction === "left" + ? ".DIR_LEFT" + : direction === "right" + ? ".DIR_RIGHT" + : direction === "up" + ? ".DIR_UP" + : ".DIR_DOWN", + falseLabel, + 0, + ); + if (holdFrames > 0) { + this._getThreadLocal(pullFramesRef, 2); + this._ifConst(".LT", pullFramesRef, holdFrames, falseLabel, 0); + } + this._jump(trueLabel); + this._label(falseLabel); + this._compilePath(falsePath); + this._jump(endLabel); + this._label(trueLabel); + this._compilePath(truePath); + this._label(endLabel); + this._addNL(); + }; + ifDataSaved = ( slot = 0, truePath: ScriptEvent[] | ScriptBuilderPathFunction = [], diff --git a/src/lib/events/eventIfPulledDirection.js b/src/lib/events/eventIfPulledDirection.js new file mode 100644 index 0000000000..d84c59c3b6 --- /dev/null +++ b/src/lib/events/eventIfPulledDirection.js @@ -0,0 +1,98 @@ +const l10n = require("../helpers/l10n").default; + +const id = "EVENT_IF_PULLED_DIRECTION"; +const groups = ["EVENT_GROUP_CONTROL_FLOW"]; +const subGroups = { + EVENT_GROUP_CONTROL_FLOW: "EVENT_GROUP_ACTOR", +}; + +const autoLabel = (fetchArg) => { + const frames = fetchArg("holdFrames"); + if (frames && frames > 0) { + return l10n("EVENT_IF_PULLED_DIRECTION_FOR_LABEL", { + direction: fetchArg("direction"), + frames: String(frames), + }); + } + return l10n("EVENT_IF_PULLED_DIRECTION_LABEL", { + direction: fetchArg("direction"), + }); +}; + +const fields = [ + { + key: "direction", + label: l10n("FIELD_DIRECTION"), + description: l10n("FIELD_DIRECTION_DESC"), + type: "direction", + defaultValue: "left", + width: "50%", + }, + { + key: "holdFrames", + label: l10n("FIELD_HOLD_FRAMES"), + description: l10n("FIELD_HOLD_FRAMES_DESC"), + type: "number", + min: 0, + max: 600, + defaultValue: 0, + width: "50%", + }, + { + key: "true", + label: l10n("FIELD_TRUE"), + description: l10n("FIELD_TRUE_DESC"), + type: "events", + }, + { + key: "__collapseElse", + label: l10n("FIELD_ELSE"), + type: "collapsable", + defaultValue: true, + conditions: [ + { + key: "__disableElse", + ne: true, + }, + ], + }, + { + key: "false", + label: l10n("FIELD_FALSE"), + description: l10n("FIELD_FALSE_DESC"), + conditions: [ + { + key: "__collapseElse", + ne: true, + }, + { + key: "__disableElse", + ne: true, + }, + ], + type: "events", + }, +]; + +const compile = (input, helpers) => { + const { ifPulledDirection } = helpers; + const truePath = input.true; + const falsePath = input.__disableElse ? [] : input.false; + ifPulledDirection( + input.direction, + input.holdFrames || 0, + truePath, + falsePath, + ); +}; + +module.exports = { + id, + description: l10n("EVENT_IF_PULLED_DIRECTION_DESC"), + autoLabel, + groups, + subGroups, + fields, + compile, + isConditional: true, +}; diff --git a/src/lib/events/eventIfPushedDirection.js b/src/lib/events/eventIfPushedDirection.js new file mode 100644 index 0000000000..93a6c46150 --- /dev/null +++ b/src/lib/events/eventIfPushedDirection.js @@ -0,0 +1,98 @@ +const l10n = require("../helpers/l10n").default; + +const id = "EVENT_IF_PUSHED_DIRECTION"; +const groups = ["EVENT_GROUP_CONTROL_FLOW"]; +const subGroups = { + EVENT_GROUP_CONTROL_FLOW: "EVENT_GROUP_ACTOR", +}; + +const autoLabel = (fetchArg) => { + const frames = fetchArg("holdFrames"); + if (frames && frames > 0) { + return l10n("EVENT_IF_PUSHED_DIRECTION_FOR_LABEL", { + direction: fetchArg("direction"), + frames: String(frames), + }); + } + return l10n("EVENT_IF_PUSHED_DIRECTION_LABEL", { + direction: fetchArg("direction"), + }); +}; + +const fields = [ + { + key: "direction", + label: l10n("FIELD_DIRECTION"), + description: l10n("FIELD_DIRECTION_DESC"), + type: "direction", + defaultValue: "left", + width: "50%", + }, + { + key: "holdFrames", + label: l10n("FIELD_HOLD_FRAMES"), + description: l10n("FIELD_HOLD_FRAMES_DESC"), + type: "number", + min: 0, + max: 600, + defaultValue: 0, + width: "50%", + }, + { + key: "true", + label: l10n("FIELD_TRUE"), + description: l10n("FIELD_TRUE_DESC"), + type: "events", + }, + { + key: "__collapseElse", + label: l10n("FIELD_ELSE"), + type: "collapsable", + defaultValue: true, + conditions: [ + { + key: "__disableElse", + ne: true, + }, + ], + }, + { + key: "false", + label: l10n("FIELD_FALSE"), + description: l10n("FIELD_FALSE_DESC"), + conditions: [ + { + key: "__collapseElse", + ne: true, + }, + { + key: "__disableElse", + ne: true, + }, + ], + type: "events", + }, +]; + +const compile = (input, helpers) => { + const { ifPushedDirection } = helpers; + const truePath = input.true; + const falsePath = input.__disableElse ? [] : input.false; + ifPushedDirection( + input.direction, + input.holdFrames || 0, + truePath, + falsePath, + ); +}; + +module.exports = { + id, + description: l10n("EVENT_IF_PUSHED_DIRECTION_DESC"), + autoLabel, + groups, + subGroups, + fields, + compile, + isConditional: true, +}; diff --git a/src/shared/lib/resources/types.ts b/src/shared/lib/resources/types.ts index d1052cac3e..ea784633b2 100644 --- a/src/shared/lib/resources/types.ts +++ b/src/shared/lib/resources/types.ts @@ -58,6 +58,8 @@ export const CollisionExtraFlag = Type.Union( Type.Literal("4"), Type.Literal("solid"), Type.Literal("platform"), + Type.Literal("pushable"), + Type.Literal("pullable"), ], { default: "" }, ); diff --git a/src/store/features/engine/engineState.ts b/src/store/features/engine/engineState.ts index 191e58d4e6..2f7017bc49 100644 --- a/src/store/features/engine/engineState.ts +++ b/src/store/features/engine/engineState.ts @@ -54,6 +54,7 @@ export type ExtraActorCollisionFlagDef = { description?: string; setFlag: CollisionExtraFlag; clearFlags?: CollisionExtraFlag[]; + conditions?: { key: string; truthy: boolean }[]; }; export type SceneTypeSchema = { From 32d82077f8418fc958a7cce7ea93a243ec29532d Mon Sep 17 00:00:00 2001 From: Dan512 Date: Sat, 21 Feb 2026 17:43:53 -0600 Subject: [PATCH 2/3] Fix a bug with pulling / frame delay in Push/Pull system --- appData/engine/engine.json | 38 -------------------------------------- appData/engine/gbvm | 2 +- 2 files changed, 1 insertion(+), 39 deletions(-) diff --git a/appData/engine/engine.json b/appData/engine/engine.json index 84aab9a03b..1b84febe20 100644 --- a/appData/engine/engine.json +++ b/appData/engine/engine.json @@ -2254,44 +2254,6 @@ } ] }, - { - "key": "adv_pull_delay_frames", - "sceneType": "ADVENTURE", - "label": "FIELD_PULL_DELAY_FRAMES", - "description": "FIELD_PULL_DELAY_FRAMES_DESC", - "group": "GAMETYPE_ADVENTURE", - "type": "slider", - "cType": "UBYTE", - "defaultValue": 5, - "min": 0, - "max": 60, - "indent": 1, - "conditions": [ - { - "key": "FEAT_ADVENTURE_PULL", - "truthy": true - } - ] - }, - { - "key": "adv_pull_grace_frames", - "sceneType": "ADVENTURE", - "label": "FIELD_PULL_GRACE_FRAMES", - "description": "FIELD_PULL_GRACE_FRAMES_DESC", - "group": "GAMETYPE_ADVENTURE", - "type": "slider", - "cType": "UBYTE", - "defaultValue": 4, - "min": 0, - "max": 30, - "indent": 1, - "conditions": [ - { - "key": "FEAT_ADVENTURE_PULL", - "truthy": true - } - ] - }, { "key": "FEAT_ADVENTURE_KNOCKBACK", "sceneType": "ADVENTURE", diff --git a/appData/engine/gbvm b/appData/engine/gbvm index 0757ea9ffb..95063444b8 160000 --- a/appData/engine/gbvm +++ b/appData/engine/gbvm @@ -1 +1 @@ -Subproject commit 0757ea9ffb28969beb1f5502337cbd2560b8a34c +Subproject commit 95063444b8c27c3649382e3102249e262a981970 From d269a52392d9095ceaca1d7dddedfe5ace9ddc93 Mon Sep 17 00:00:00 2001 From: Dan512 Date: Sun, 22 Feb 2026 00:58:48 -0600 Subject: [PATCH 3/3] Reformat engine.json to match old version --- appData/engine/engine.json | 450 ++++++++----------------------------- 1 file changed, 91 insertions(+), 359 deletions(-) diff --git a/appData/engine/engine.json b/appData/engine/engine.json index 1b84febe20..36638e5186 100644 --- a/appData/engine/engine.json +++ b/appData/engine/engine.json @@ -9,22 +9,10 @@ "group": "GAMETYPE_PLATFORMER", "type": "togglebuttons", "options": [ - [ - "INPUT_A", - "A" - ], - [ - "INPUT_B", - "B" - ], - [ - "INPUT_UP", - "FIELD_DIRECTION_UP" - ], - [ - "INPUT_DOWN", - "FIELD_DIRECTION_DOWN" - ] + ["INPUT_A", "A"], + ["INPUT_B", "B"], + ["INPUT_UP", "FIELD_DIRECTION_UP"], + ["INPUT_DOWN", "FIELD_DIRECTION_DOWN"] ], "cType": "define", "defaultValue": "INPUT_A" @@ -37,22 +25,10 @@ "group": "GAMETYPE_PLATFORMER", "type": "togglebuttons", "options": [ - [ - "FALSE", - "FIELD_NONE" - ], - [ - "INPUT_A_PRESSED", - "A" - ], - [ - "INPUT_B_PRESSED", - "B" - ], - [ - "INPUT_UP_PRESSED", - "FIELD_DIRECTION_UP" - ] + ["FALSE", "FIELD_NONE"], + ["INPUT_A_PRESSED", "A"], + ["INPUT_B_PRESSED", "B"], + ["INPUT_UP_PRESSED", "FIELD_DIRECTION_UP"] ], "cType": "define", "defaultValue": "INPUT_UP_PRESSED" @@ -199,22 +175,10 @@ "group": "GAMETYPE_PLATFORMER", "type": "select", "options": [ - [ - "PLATFORM_CAMERA_LOCK_SCREEN_NONE", - "FIELD_NONE" - ], - [ - "PLATFORM_CAMERA_LOCK_SCREEN_LEFT", - "FIELD_LEFT" - ], - [ - "PLATFORM_CAMERA_LOCK_SCREEN_RIGHT", - "FIELD_RIGHT" - ], - [ - "PLATFORM_CAMERA_LOCK_SCREEN_BOTH", - "FIELD_BOTH" - ] + ["PLATFORM_CAMERA_LOCK_SCREEN_NONE", "FIELD_NONE"], + ["PLATFORM_CAMERA_LOCK_SCREEN_LEFT", "FIELD_LEFT"], + ["PLATFORM_CAMERA_LOCK_SCREEN_RIGHT", "FIELD_RIGHT"], + ["PLATFORM_CAMERA_LOCK_SCREEN_BOTH", "FIELD_BOTH"] ], "cType": "UBYTE", "defaultValue": "PLATFORM_CAMERA_LOCK_SCREEN_NONE" @@ -255,14 +219,8 @@ "group": "GAMETYPE_PLATFORMER", "type": "togglebuttons", "options": [ - [ - "INPUT_A", - "A" - ], - [ - "INPUT_B", - "B" - ] + ["INPUT_A", "A"], + ["INPUT_B", "B"] ], "cType": "define", "defaultValue": "INPUT_B", @@ -282,18 +240,9 @@ "group": "GAMETYPE_PLATFORMER", "type": "select", "options": [ - [ - "RUN_STYLE_DEFAULT", - "FIELD_DEFAULT" - ], - [ - "RUN_STYLE_SMOOTH", - "FIELD_RUN_STYLE_SMOOTH" - ], - [ - "RUN_STYLE_INSTANT", - "FIELD_INSTANT" - ] + ["RUN_STYLE_DEFAULT", "FIELD_DEFAULT"], + ["RUN_STYLE_SMOOTH", "FIELD_RUN_STYLE_SMOOTH"], + ["RUN_STYLE_INSTANT", "FIELD_INSTANT"] ], "cType": "define", "defaultValue": "RUN_STYLE_DEFAULT", @@ -385,18 +334,9 @@ "group": "GAMETYPE_PLATFORMER", "type": "togglebuttons", "options": [ - [ - "INPUT_A", - "A" - ], - [ - "INPUT_B", - "B" - ], - [ - "INPUT_UP", - "FIELD_DIRECTION_UP" - ] + ["INPUT_A", "A"], + ["INPUT_B", "B"], + ["INPUT_UP", "FIELD_DIRECTION_UP"] ], "cType": "define", "defaultValue": "INPUT_A", @@ -826,22 +766,10 @@ "group": "GAMETYPE_PLATFORMER", "type": "select", "options": [ - [ - "DROP_THRU_INPUT_DOWN_HOLD", - "FIELD_DOWN_HOLD" - ], - [ - "DROP_THRU_INPUT_DOWN_TAP", - "FIELD_DOWN_TAP" - ], - [ - "DROP_THRU_INPUT_DOWN_JUMP_HOLD", - "FIELD_DOWN_AND_JUMP_HOLD" - ], - [ - "DROP_THRU_INPUT_DOWN_JUMP_TAP", - "FIELD_DOWN_AND_JUMP_TAP" - ] + ["DROP_THRU_INPUT_DOWN_HOLD", "FIELD_DOWN_HOLD"], + ["DROP_THRU_INPUT_DOWN_TAP", "FIELD_DOWN_TAP"], + ["DROP_THRU_INPUT_DOWN_JUMP_HOLD", "FIELD_DOWN_AND_JUMP_HOLD"], + ["DROP_THRU_INPUT_DOWN_JUMP_TAP", "FIELD_DOWN_AND_JUMP_TAP"] ], "cType": "define", "defaultValue": "DROP_THRU_INPUT_DOWN_JUMP_TAP", @@ -906,14 +834,8 @@ "group": "GAMETYPE_PLATFORMER", "type": "select", "options": [ - [ - "FLOAT_INPUT_HOLD_JUMP", - "FIELD_JUMP_HOLD" - ], - [ - "FLOAT_INPUT_HOLD_UP", - "FIELD_UP_HOLD" - ] + ["FLOAT_INPUT_HOLD_JUMP", "FIELD_JUMP_HOLD"], + ["FLOAT_INPUT_HOLD_UP", "FIELD_UP_HOLD"] ], "cType": "define", "defaultValue": "FLOAT_INPUT_HOLD_JUMP", @@ -1126,26 +1048,11 @@ "group": "GAMETYPE_PLATFORMER", "type": "select", "options": [ - [ - "DASH_INPUT_INTERACT", - "FIELD_INTERACT_TAP" - ], - [ - "DASH_INPUT_DOUBLE_TAP", - "FIELD_DIR_DOUBLE_TAP" - ], - [ - "DASH_INPUT_DOWN_JUMP", - "FIELD_DOWN_AND_JUMP_TAP" - ], - [ - "DASH_INPUT_A", - "A" - ], - [ - "DASH_INPUT_B", - "B" - ] + ["DASH_INPUT_INTERACT", "FIELD_INTERACT_TAP"], + ["DASH_INPUT_DOUBLE_TAP", "FIELD_DIR_DOUBLE_TAP"], + ["DASH_INPUT_DOWN_JUMP", "FIELD_DOWN_AND_JUMP_TAP"], + ["DASH_INPUT_A", "A"], + ["DASH_INPUT_B", "B"] ], "cType": "define", "defaultValue": "DASH_INPUT_DOUBLE_TAP", @@ -1165,18 +1072,9 @@ "group": "GAMETYPE_PLATFORMER", "type": "mask", "options": [ - [ - 1, - "FIELD_GROUND" - ], - [ - 2, - "FIELD_AIR" - ], - [ - 4, - "FIELD_LADDER" - ] + [1, "FIELD_GROUND"], + [2, "FIELD_AIR"], + [4, "FIELD_LADDER"] ], "cType": "UBYTE", "defaultValue": 3, @@ -1196,18 +1094,9 @@ "group": "GAMETYPE_PLATFORMER", "type": "mask", "options": [ - [ - -4, - "FIELD_ACTORS" - ], - [ - -8, - "FIELD_TRIGGERS" - ], - [ - -16, - "FIELD_WALLS" - ] + [-4, "FIELD_ACTORS"], + [-8, "FIELD_TRIGGERS"], + [-16, "FIELD_WALLS"] ], "cType": "UBYTE", "defaultValue": 255, @@ -1304,14 +1193,8 @@ "group": "GAMETYPE_PLATFORMER", "type": "mask", "options": [ - [ - 1, - "FIELD_GROUND" - ], - [ - 2, - "FIELD_AIR" - ] + [1, "FIELD_GROUND"], + [2, "FIELD_AIR"] ], "cType": "UBYTE", "defaultValue": 1, @@ -1589,38 +1472,14 @@ "type": "select", "cType": "UBYTE", "options": [ - [ - "PLATFORM_FALL_STATE", - "FIELD_FALL_STATE" - ], - [ - "PLATFORM_GROUND_STATE", - "FIELD_GROUND_STATE" - ], - [ - "PLATFORM_JUMP_STATE", - "FIELD_JUMP_STATE" - ], - [ - "PLATFORM_DASH_STATE", - "FIELD_DASH_STATE" - ], - [ - "PLATFORM_LADDER_STATE", - "FIELD_LADDER_STATE" - ], - [ - "PLATFORM_WALL_STATE", - "FIELD_WALL_STATE" - ], - [ - "PLATFORM_KNOCKBACK_STATE", - "FIELD_KNOCKBACK_STATE" - ], - [ - "PLATFORM_BLANK_STATE", - "FIELD_BLANK_STATE" - ] + ["PLATFORM_FALL_STATE", "FIELD_FALL_STATE"], + ["PLATFORM_GROUND_STATE", "FIELD_GROUND_STATE"], + ["PLATFORM_JUMP_STATE", "FIELD_JUMP_STATE"], + ["PLATFORM_DASH_STATE", "FIELD_DASH_STATE"], + ["PLATFORM_LADDER_STATE", "FIELD_LADDER_STATE"], + ["PLATFORM_WALL_STATE", "FIELD_WALL_STATE"], + ["PLATFORM_KNOCKBACK_STATE", "FIELD_KNOCKBACK_STATE"], + ["PLATFORM_BLANK_STATE", "FIELD_BLANK_STATE"] ], "defaultValue": "PLATFORM_FALL_STATE", "runtimeOnly": true @@ -1633,14 +1492,8 @@ "group": "GAMETYPE_SHMUP", "type": "select", "options": [ - [ - "MOVEMENT_TYPE_FREE", - "FIELD_FREE_MOVEMENT" - ], - [ - "MOVEMENT_TYPE_LOCK_PERPENDICULAR", - "FIELD_LOCKED_MOVEMENT" - ] + ["MOVEMENT_TYPE_FREE", "FIELD_FREE_MOVEMENT"], + ["MOVEMENT_TYPE_LOCK_PERPENDICULAR", "FIELD_LOCKED_MOVEMENT"] ], "cType": "define", "defaultValue": "MOVEMENT_TYPE_FREE" @@ -1666,14 +1519,8 @@ "group": "GAMETYPE_SHMUP", "type": "select", "options": [ - [ - "ON_PLAYER_COLLISION", - "FIELD_ON_PLAYER_COLLISION" - ], - [ - "ON_SCREEN_ENTER", - "FIELD_ON_SCREEN_ENTER" - ] + ["ON_PLAYER_COLLISION", "FIELD_ON_PLAYER_COLLISION"], + ["ON_SCREEN_ENTER", "FIELD_ON_SCREEN_ENTER"] ], "cType": "define", "defaultValue": "ON_PLAYER_COLLISION" @@ -1686,22 +1533,10 @@ "group": "GAMETYPE_SHMUP", "type": "togglebuttons", "options": [ - [ - "COLLISION_GROUP_NONE", - "FIELD_NONE" - ], - [ - "COLLISION_GROUP_1", - "1" - ], - [ - "COLLISION_GROUP_2", - "2" - ], - [ - "COLLISION_GROUP_3", - "3" - ] + ["COLLISION_GROUP_NONE", "FIELD_NONE"], + ["COLLISION_GROUP_1", "1"], + ["COLLISION_GROUP_2", "2"], + ["COLLISION_GROUP_3", "3"] ], "cType": "define", "defaultValue": "COLLISION_GROUP_NONE" @@ -1714,14 +1549,8 @@ "group": "GAMETYPE_TOP_DOWN", "type": "togglebuttons", "options": [ - [ - "INPUT_A", - "A" - ], - [ - "INPUT_B", - "B" - ] + ["INPUT_A", "A"], + ["INPUT_B", "B"] ], "cType": "define", "defaultValue": "INPUT_A" @@ -1734,14 +1563,8 @@ "group": "GAMETYPE_TOP_DOWN", "type": "select", "options": [ - [ - 8, - "FIELD_GRID_8PX" - ], - [ - 16, - "FIELD_GRID_16PX" - ] + [8, "FIELD_GRID_8PX"], + [16, "FIELD_GRID_16PX"] ], "cType": "UBYTE", "defaultValue": 8 @@ -1753,14 +1576,8 @@ "group": "SETTINGS_FADE", "type": "select", "options": [ - [ - 0, - "FIELD_FADE_WHITE" - ], - [ - 1, - "FIELD_FADE_BLACK" - ] + [0, "FIELD_FADE_WHITE"], + [1, "FIELD_FADE_BLACK"] ], "cType": "UBYTE", "defaultValue": 0 @@ -1773,14 +1590,8 @@ "group": "GAMETYPE_ADVENTURE", "type": "togglebuttons", "options": [ - [ - "INPUT_A", - "A" - ], - [ - "INPUT_B", - "B" - ] + ["INPUT_A", "A"], + ["INPUT_B", "B"] ], "cType": "define", "defaultValue": "INPUT_A" @@ -1793,14 +1604,8 @@ "group": "GAMETYPE_ADVENTURE", "type": "select", "options": [ - [ - "MOVE_TYPE_4_WAY", - "FIELD_4_WAY" - ], - [ - "MOVE_TYPE_8_WAY", - "FIELD_8_WAY" - ] + ["MOVE_TYPE_4_WAY", "FIELD_4_WAY"], + ["MOVE_TYPE_8_WAY", "FIELD_8_WAY"] ], "cType": "define", "defaultValue": "MOVE_TYPE_8_WAY" @@ -1813,14 +1618,8 @@ "group": "GAMETYPE_ADVENTURE", "type": "select", "options": [ - [ - "DIRECTION_TYPE_4_WAY", - "FIELD_4_WAY" - ], - [ - "DIRECTION_TYPE_HORIZONTAL", - "FIELD_HORIZONTAL_ONLY" - ] + ["DIRECTION_TYPE_4_WAY", "FIELD_4_WAY"], + ["DIRECTION_TYPE_HORIZONTAL", "FIELD_HORIZONTAL_ONLY"] ], "cType": "define", "defaultValue": "DIRECTION_TYPE_4_WAY" @@ -1913,14 +1712,8 @@ "group": "GAMETYPE_ADVENTURE", "type": "togglebuttons", "options": [ - [ - "INPUT_A", - "A" - ], - [ - "INPUT_B", - "B" - ] + ["INPUT_A", "A"], + ["INPUT_B", "B"] ], "cType": "define", "defaultValue": "INPUT_B", @@ -2025,22 +1818,10 @@ "group": "GAMETYPE_ADVENTURE", "type": "select", "options": [ - [ - "DASH_INPUT_INTERACT", - "FIELD_INTERACT_TAP" - ], - [ - "DASH_INPUT_DOUBLE_TAP", - "FIELD_DPAD_DOUBLE_TAP" - ], - [ - "DASH_INPUT_A", - "A" - ], - [ - "DASH_INPUT_B", - "B" - ] + ["DASH_INPUT_INTERACT", "FIELD_INTERACT_TAP"], + ["DASH_INPUT_DOUBLE_TAP", "FIELD_DPAD_DOUBLE_TAP"], + ["DASH_INPUT_A", "A"], + ["DASH_INPUT_B", "B"] ], "cType": "define", "defaultValue": "DASH_INPUT_DOUBLE_TAP", @@ -2060,18 +1841,9 @@ "group": "GAMETYPE_ADVENTURE", "type": "mask", "options": [ - [ - -4, - "FIELD_ACTORS" - ], - [ - -8, - "FIELD_TRIGGERS" - ], - [ - -16, - "FIELD_WALLS" - ] + [-4, "FIELD_ACTORS"], + [-8, "FIELD_TRIGGERS"], + [-16, "FIELD_WALLS"] ], "cType": "UBYTE", "defaultValue": 255, @@ -2378,30 +2150,12 @@ "type": "select", "cType": "UBYTE", "options": [ - [ - "ADVENTURE_GROUND_STATE", - "FIELD_GROUND_STATE" - ], - [ - "ADVENTURE_DASH_STATE", - "FIELD_DASH_STATE" - ], - [ - "ADVENTURE_KNOCKBACK_STATE", - "FIELD_KNOCKBACK_STATE" - ], - [ - "ADVENTURE_BLANK_STATE", - "FIELD_BLANK_STATE" - ], - [ - "ADVENTURE_RUN_STATE", - "FIELD_RUN_STATE" - ], - [ - "ADVENTURE_PUSH_STATE", - "FIELD_PUSH_STATE" - ] + ["ADVENTURE_GROUND_STATE", "FIELD_GROUND_STATE"], + ["ADVENTURE_DASH_STATE", "FIELD_DASH_STATE"], + ["ADVENTURE_KNOCKBACK_STATE", "FIELD_KNOCKBACK_STATE"], + ["ADVENTURE_BLANK_STATE", "FIELD_BLANK_STATE"], + ["ADVENTURE_RUN_STATE", "FIELD_RUN_STATE"], + ["ADVENTURE_PUSH_STATE", "FIELD_PUSH_STATE"] ], "defaultValue": "ADVENTURE_GROUND_STATE", "runtimeOnly": true @@ -2491,10 +2245,7 @@ { "key": "TOPDOWN", "label": "GAMETYPE_TOP_DOWN", - "files": [ - "include/states/topdown.h", - "src/states/topdown.c" - ], + "files": ["include/states/topdown.h", "src/states/topdown.c"], "collisionTiles": [ { "key": "solid", @@ -2545,28 +2296,21 @@ { "key": "PLATFORM", "label": "GAMETYPE_PLATFORMER", - "files": [ - "include/states/platform.h", - "src/states/platform.c" - ], + "files": ["include/states/platform.h", "src/states/platform.c"], "extraActorCollisionFlags": [ { "key": "solid", "label": "FIELD_IS_SOLID", "description": "FIELD_IS_SOLID_DESC", "setFlag": "solid", - "clearFlags": [ - "platform" - ] + "clearFlags": ["platform"] }, { "key": "platform", "label": "FIELD_IS_PLATFORM", "description": "FIELD_IS_PLATFORM_DESC", "setFlag": "platform", - "clearFlags": [ - "solid" - ] + "clearFlags": ["solid"] } ], "collisionTiles": [ @@ -2688,10 +2432,7 @@ { "key": "ADVENTURE", "label": "GAMETYPE_ADVENTURE", - "files": [ - "include/states/adventure.h", - "src/states/adventure.c" - ], + "files": ["include/states/adventure.h", "src/states/adventure.c"], "extraActorCollisionFlags": [ { "key": "solid", @@ -2810,10 +2551,7 @@ { "key": "SHMUP", "label": "GAMETYPE_SHMUP", - "files": [ - "include/states/shmup.h", - "src/states/shmup.c" - ], + "files": ["include/states/shmup.h", "src/states/shmup.c"], "collisionTiles": [ { "key": "solid", @@ -2864,10 +2602,7 @@ { "key": "POINTNCLICK", "label": "GAMETYPE_POINT_N_CLICK", - "files": [ - "include/states/pointnclick.h", - "src/states/pointnclick.c" - ], + "files": ["include/states/pointnclick.h", "src/states/pointnclick.c"], "collisionTiles": [ { "key": "solid", @@ -2882,10 +2617,7 @@ { "key": "LOGO", "label": "GAMETYPE_LOGO", - "files": [ - "include/states/logo.h", - "src/states/logo.c" - ], + "files": ["include/states/logo.h", "src/states/logo.c"], "collisionTiles": [ { "key": "solid", @@ -2898,4 +2630,4 @@ ] } ] -} \ No newline at end of file +}