Repository: SM64-TAS-ABC/STROOP
Branch: dev
Commit: 5de958448a0c
Files: 652
Total size: 15.8 MB
Directory structure:
gitextract_wl97lnnh/
├── .gitattributes
├── .gitignore
├── Directory.Build.props
├── README.md
├── STROOP/
│ ├── App.config
│ ├── Calculators/
│ │ ├── AirMovementCalculator.cs
│ │ ├── BobombState.cs
│ │ ├── CalculatorMain.cs
│ │ ├── CalculatorUtilities.cs
│ │ ├── GroundMovementCalculator.cs
│ │ ├── HolpCalculator.cs
│ │ ├── Input.cs
│ │ ├── LoadingZoneMain.cs
│ │ ├── MarioState.cs
│ │ ├── MutableMarioState.cs
│ │ ├── ObjectCalculator.cs
│ │ ├── OverflowJumpCalculator.cs
│ │ ├── PendulumData.cs
│ │ ├── PendulumMain.cs
│ │ ├── PunchRecoilCalculator.cs
│ │ ├── SlideCalculator.cs
│ │ ├── SlidingMarioState.cs
│ │ ├── WallDisplacementCalculator.cs
│ │ ├── WaterLevelCalculator.cs
│ │ ├── WaterMain.cs
│ │ └── WaterState.cs
│ ├── Config/
│ │ ├── ActionsData.xml
│ │ ├── AreaData.xml
│ │ ├── CamHackData.xml
│ │ ├── CameraData.xml
│ │ ├── CellsData.xml
│ │ ├── Config.xml
│ │ ├── CourseData.xml
│ │ ├── CustomData.xml
│ │ ├── DebugData.xml
│ │ ├── FileData.xml
│ │ ├── FileImageAssociations.xml
│ │ ├── Hacks.xml
│ │ ├── HudData.xml
│ │ ├── InputData.xml
│ │ ├── InputImageAssociations.xml
│ │ ├── KoopaTheQuick1Waypoints.xml
│ │ ├── KoopaTheQuick2Waypoints.xml
│ │ ├── MainSaveData.xml
│ │ ├── MapAssociations.xml
│ │ ├── MapVars.xml
│ │ ├── MarioActions.xml
│ │ ├── MarioAnimations.xml
│ │ ├── MarioData.xml
│ │ ├── MarioStateData.xml
│ │ ├── MhsData.xml
│ │ ├── MiscData.xml
│ │ ├── Missions.xml
│ │ ├── MusicData.xml
│ │ ├── MusicData2.xml
│ │ ├── ObjectAssociations.xml
│ │ ├── ObjectData.xml
│ │ ├── OptionsData.xml
│ │ ├── PaintingData.xml
│ │ ├── PendulumSwings.xml
│ │ ├── PuData.xml
│ │ ├── QuarterFrameData.xml
│ │ ├── RacingPenguinWaypoints.xml
│ │ ├── SavedSettings.xml
│ │ ├── ScriptData.xml
│ │ ├── SnowData.xml
│ │ ├── TasData.xml
│ │ ├── TriangleInfo.xml
│ │ ├── TrianglesData.xml
│ │ ├── TtmBowlingBallPoints.xml
│ │ ├── WarpData.xml
│ │ └── WaterData.xml
│ ├── Controls/
│ │ ├── BetterContextMenuStrip.cs
│ │ ├── BetterSplitContainer.cs
│ │ ├── BetterTextbox.cs
│ │ ├── BinaryButton.cs
│ │ ├── BorderedTableLayoutPanel.cs
│ │ ├── CarretlessTextBox.cs
│ │ ├── CoinRingDisplayPanel.cs
│ │ ├── ColorSelector.Designer.cs
│ │ ├── ColorSelector.cs
│ │ ├── ColorSelector.resx
│ │ ├── DoubleBufferedTableLayoutPanel.cs
│ │ ├── FileBinaryPictureBox.cs
│ │ ├── FileCoinScoreTextbox.cs
│ │ ├── FileCourseLabel.cs
│ │ ├── FileHatLocationPictureBox.cs
│ │ ├── FileHatPositionTextbox.cs
│ │ ├── FileKeyDoorPictureBox.cs
│ │ ├── FilePictureBox.cs
│ │ ├── FileStarPictureBox.cs
│ │ ├── FileTextbox.cs
│ │ ├── InputDisplayPanel.cs
│ │ ├── IntPictureBox.cs
│ │ ├── MainSaveTextbox.cs
│ │ ├── ModelGraphics.cs
│ │ ├── NoTearFlowLayoutPanel.cs
│ │ ├── ObjectSlot.cs
│ │ ├── ObjectSlotFlowLayoutPanel.cs
│ │ ├── PanelEx.cs
│ │ ├── RichTextBoxEx.cs
│ │ ├── TabControlEx.cs
│ │ ├── TrackBarEx.cs
│ │ ├── TransparentTextbox.cs
│ │ ├── VarHackContainer.Designer.cs
│ │ ├── VarHackContainer.cs
│ │ ├── VarHackContainer.resx
│ │ ├── VarHackContainerDefaults.cs
│ │ ├── VarHackFlowLayoutPanel.cs
│ │ ├── WatchVariable.cs
│ │ ├── WatchVariableAddressWrapper.cs
│ │ ├── WatchVariableAngleWrapper.cs
│ │ ├── WatchVariableBooleanWrapper.cs
│ │ ├── WatchVariableControl.Designer.cs
│ │ ├── WatchVariableControl.cs
│ │ ├── WatchVariableControl.resx
│ │ ├── WatchVariableControlPrecursor.cs
│ │ ├── WatchVariableControlSettings.cs
│ │ ├── WatchVariableFlowLayoutPanel.cs
│ │ ├── WatchVariableLock.cs
│ │ ├── WatchVariableNumberWrapper.cs
│ │ ├── WatchVariableObjectWrapper.cs
│ │ ├── WatchVariableStringWrapper.cs
│ │ ├── WatchVariableTriangleWrapper.cs
│ │ └── WatchVariableWrapper.cs
│ ├── EmbeddedResources/
│ │ ├── Python.xshd
│ │ └── decompile.py
│ ├── Enums/
│ │ ├── AddToTabTypeEnum.cs
│ │ ├── AggregateMathOperation.cs
│ │ ├── AngleUnitType.cs
│ │ ├── BaseAddressTypeEnum.cs
│ │ ├── BinaryMathOperation.cs
│ │ ├── CamHackMode.cs
│ │ ├── CellSelectionType.cs
│ │ ├── CoinParamsOrder.cs
│ │ ├── CompassPosition.cs
│ │ ├── Coordinate.cs
│ │ ├── CoordinateAngle.cs
│ │ ├── CoordinateSystem.cs
│ │ ├── CopyTypeEnum.cs
│ │ ├── EndiannessType.cs
│ │ ├── FileType.cs
│ │ ├── FrameInputRelationType.cs
│ │ ├── HatLocation.cs
│ │ ├── InputDisplayTypeEnum.cs
│ │ ├── Map3DCameraMode.cs
│ │ ├── MapTrackerIconType.cs
│ │ ├── MapTrackerOrderType.cs
│ │ ├── MapTrackerVisibilityType.cs
│ │ ├── MapType.cs
│ │ ├── MouseEvent.cs
│ │ ├── PaintingListTypeEnum.cs
│ │ ├── PositionControllerRelativity.cs
│ │ ├── ReadWriteMode.cs
│ │ ├── RelativeDirection.cs
│ │ ├── RomVersion.cs
│ │ ├── RomVersionSelection.cs
│ │ ├── TriangleClassification.cs
│ │ ├── TriangleClassificationExtended.cs
│ │ ├── TriangleVertexOffset.cs
│ │ ├── VariableGroup.cs
│ │ └── WatchVariableSubclass.cs
│ ├── Extensions/
│ │ ├── BitmapExtensions.cs
│ │ ├── ColorExtensions.cs
│ │ ├── ControlCollectionsExtensions.cs
│ │ ├── FormExtensions.cs
│ │ ├── IEnumerableExtensions.cs
│ │ ├── RectangleExtensions.cs
│ │ ├── RichTextBoxExtensions.cs
│ │ └── SizeExtensions.cs
│ ├── Forms/
│ │ ├── ActionForm.Designer.cs
│ │ ├── ActionForm.cs
│ │ ├── ActionForm.resx
│ │ ├── CoinRingDisplayForm.Designer.cs
│ │ ├── CoinRingDisplayForm.cs
│ │ ├── CoinRingDisplayForm.resx
│ │ ├── FormManager.cs
│ │ ├── IUpdatableForm.cs
│ │ ├── ImageForm.Designer.cs
│ │ ├── ImageForm.cs
│ │ ├── ImageForm.resx
│ │ ├── InfoForm.Designer.cs
│ │ ├── InfoForm.cs
│ │ ├── InfoForm.resx
│ │ ├── LoadingForm.Designer.cs
│ │ ├── LoadingForm.cs
│ │ ├── LoadingForm.resx
│ │ ├── MainLoadingForm.Designer.cs
│ │ ├── MainLoadingForm.cs
│ │ ├── MainLoadingForm.resx
│ │ ├── MapPopOutForm.Designer.cs
│ │ ├── MapPopOutForm.cs
│ │ ├── MapPopOutForm.resx
│ │ ├── SelectionForm.Designer.cs
│ │ ├── SelectionForm.cs
│ │ ├── SelectionForm.resx
│ │ ├── StroopMainForm.Designer.cs
│ │ ├── StroopMainForm.cs
│ │ ├── StroopMainForm.resx
│ │ ├── TabForm.Designer.cs
│ │ ├── TabForm.cs
│ │ ├── TabForm.resx
│ │ ├── TriangleListForm.Designer.cs
│ │ ├── TriangleListForm.cs
│ │ ├── TriangleListForm.resx
│ │ ├── ValueForm.Designer.cs
│ │ ├── ValueForm.cs
│ │ ├── ValueForm.resx
│ │ ├── ValueSplitForm.Designer.cs
│ │ ├── ValueSplitForm.cs
│ │ ├── ValueSplitForm.resx
│ │ ├── VariableBitForm.Designer.cs
│ │ ├── VariableBitForm.cs
│ │ ├── VariableBitForm.resx
│ │ ├── VariableControllerForm.Designer.cs
│ │ ├── VariableControllerForm.cs
│ │ ├── VariableControllerForm.resx
│ │ ├── VariableCreationForm.Designer.cs
│ │ ├── VariableCreationForm.cs
│ │ ├── VariableCreationForm.resx
│ │ ├── VariablePopOutForm.Designer.cs
│ │ ├── VariablePopOutForm.cs
│ │ ├── VariablePopOutForm.resx
│ │ ├── VariableTripletControllerForm.Designer.cs
│ │ ├── VariableTripletControllerForm.cs
│ │ ├── VariableTripletControllerForm.resx
│ │ ├── VariableViewerForm.Designer.cs
│ │ ├── VariableViewerForm.cs
│ │ └── VariableViewerForm.resx
│ ├── Licenses.txt
│ ├── LoadingHandler.cs
│ ├── M64/
│ │ ├── M64CopiedData.cs
│ │ ├── M64CopiedFrame.cs
│ │ ├── M64File.cs
│ │ ├── M64Header.cs
│ │ ├── M64InputCell.cs
│ │ ├── M64InputFrame.cs
│ │ ├── M64Stats.cs
│ │ └── M64Utilities.cs
│ ├── Managers/
│ │ ├── ActionsManager.cs
│ │ ├── AreaManager.cs
│ │ ├── CamHackManager.cs
│ │ ├── CameraManager.cs
│ │ ├── CellsManager.cs
│ │ ├── CoinManager.cs
│ │ ├── CustomManager.cs
│ │ ├── DataManager.cs
│ │ ├── DebugManager.cs
│ │ ├── DisassemblyManager.cs
│ │ ├── FileManager.cs
│ │ ├── GfxManager.cs
│ │ ├── HackManager.cs
│ │ ├── HudManager.cs
│ │ ├── IVariableAdder.cs
│ │ ├── InputManager.cs
│ │ ├── M64Manager.cs
│ │ ├── MainSaveManager.cs
│ │ ├── MapManager.cs
│ │ ├── MarioManager.cs
│ │ ├── MemoryManager.cs
│ │ ├── MiscManager.cs
│ │ ├── ModelManager.cs
│ │ ├── MusicManager.cs
│ │ ├── ObjectManager.cs
│ │ ├── ObjectSlotsManager.cs
│ │ ├── OptionsManager.cs
│ │ ├── PaintingManager.cs
│ │ ├── PuManager.cs
│ │ ├── QuarterFrameManager.cs
│ │ ├── ScriptManager.cs
│ │ ├── SearchManager.cs
│ │ ├── SnowManager.cs
│ │ ├── SoundManager.cs
│ │ ├── TasManager.cs
│ │ ├── TestingManager.cs
│ │ ├── TriangleManager.cs
│ │ ├── VarHackManager.cs
│ │ ├── VariableAdder.cs
│ │ ├── WarpManager.cs
│ │ ├── WatchVariableControlSettingsManager.cs
│ │ ├── WatchVariableLockManager.cs
│ │ └── WaterManager.cs
│ ├── Map/
│ │ ├── Map3D/
│ │ │ ├── Map3DCamera.cs
│ │ │ ├── Map3DGraphics.cs
│ │ │ └── Map3DVertex.cs
│ │ ├── MapDrawType.cs
│ │ ├── MapGraphics.cs
│ │ ├── MapGui.cs
│ │ ├── MapObject.cs
│ │ ├── MapObjectAggregatedPath.cs
│ │ ├── MapObjectAllMapObjectsWithName.cs
│ │ ├── MapObjectAllObjectCeiling.cs
│ │ ├── MapObjectAllObjectFloor.cs
│ │ ├── MapObjectAllObjectWall.cs
│ │ ├── MapObjectAllObjectsWithName.cs
│ │ ├── MapObjectAngleRange.cs
│ │ ├── MapObjectArrow.cs
│ │ ├── MapObjectBackground.cs
│ │ ├── MapObjectBounds.cs
│ │ ├── MapObjectBranchPath.cs
│ │ ├── MapObjectCUpFloor.cs
│ │ ├── MapObjectCamera.cs
│ │ ├── MapObjectCameraFocus.cs
│ │ ├── MapObjectCameraView.cs
│ │ ├── MapObjectCeiling.cs
│ │ ├── MapObjectCellGridlines.cs
│ │ ├── MapObjectCircle.cs
│ │ ├── MapObjectCoffinBox.cs
│ │ ├── MapObjectCompass.cs
│ │ ├── MapObjectCoordinateLabels.cs
│ │ ├── MapObjectCorkBoxTester.cs
│ │ ├── MapObjectCurrentBackground.cs
│ │ ├── MapObjectCurrentCell.cs
│ │ ├── MapObjectCurrentLevel.cs
│ │ ├── MapObjectCurrentUnit.cs
│ │ ├── MapObjectCustomBackground.cs
│ │ ├── MapObjectCustomCeiling.cs
│ │ ├── MapObjectCustomCylinder.cs
│ │ ├── MapObjectCustomCylinderPoints.cs
│ │ ├── MapObjectCustomFloor.cs
│ │ ├── MapObjectCustomGridlines.cs
│ │ ├── MapObjectCustomIconPoints.cs
│ │ ├── MapObjectCustomLevel.cs
│ │ ├── MapObjectCustomPositionAngle.cs
│ │ ├── MapObjectCustomPositionAngleArrow.cs
│ │ ├── MapObjectCustomSphere.cs
│ │ ├── MapObjectCustomSpherePoints.cs
│ │ ├── MapObjectCustomUnitPoints.cs
│ │ ├── MapObjectCustomWall.cs
│ │ ├── MapObjectCylinder.cs
│ │ ├── MapObjectDrawDistanceSphere.cs
│ │ ├── MapObjectDrawing.cs
│ │ ├── MapObjectEffectiveHitboxCylinder.cs
│ │ ├── MapObjectEffectiveHitboxHurtboxCylinder.cs
│ │ ├── MapObjectEffectiveHurtboxCylinder.cs
│ │ ├── MapObjectFacingDivider.cs
│ │ ├── MapObjectFloatGridlines.cs
│ │ ├── MapObjectFloor.cs
│ │ ├── MapObjectFlyGuyZoneDividers.cs
│ │ ├── MapObjectGhost.cs
│ │ ├── MapObjectGridlines.cs
│ │ ├── MapObjectHitboxCylinder.cs
│ │ ├── MapObjectHitboxTriangle.cs
│ │ ├── MapObjectHolp.cs
│ │ ├── MapObjectHolpDisplayer.cs
│ │ ├── MapObjectHome.cs
│ │ ├── MapObjectHomeLine.cs
│ │ ├── MapObjectHorizontalTriangle.cs
│ │ ├── MapObjectHoverData.cs
│ │ ├── MapObjectHoverDataEnum.cs
│ │ ├── MapObjectHurtboxCylinder.cs
│ │ ├── MapObjectIcon.cs
│ │ ├── MapObjectIconPoint.cs
│ │ ├── MapObjectIconRectangle.cs
│ │ ├── MapObjectIwerlipses.cs
│ │ ├── MapObjectLedgeGrabChecker.cs
│ │ ├── MapObjectLevel.cs
│ │ ├── MapObjectLevelCeiling.cs
│ │ ├── MapObjectLevelFloor.cs
│ │ ├── MapObjectLevelTriangleInterface.cs
│ │ ├── MapObjectLevelWall.cs
│ │ ├── MapObjectLine.cs
│ │ ├── MapObjectLineSegment.cs
│ │ ├── MapObjectMario.cs
│ │ ├── MapObjectMarioCeiling.cs
│ │ ├── MapObjectMarioFacingArrow.cs
│ │ ├── MapObjectMarioFloor.cs
│ │ ├── MapObjectMarioFloorArrow.cs
│ │ ├── MapObjectMarioIntendedArrow.cs
│ │ ├── MapObjectMarioMovingArrow.cs
│ │ ├── MapObjectMarioSlidingArrow.cs
│ │ ├── MapObjectMarioSpeedArrow.cs
│ │ ├── MapObjectMarioTwirlArrow.cs
│ │ ├── MapObjectMarioWall.cs
│ │ ├── MapObjectNextPositions.cs
│ │ ├── MapObjectOJPosition.cs
│ │ ├── MapObjectObject.cs
│ │ ├── MapObjectObjectAngleToMarioArrow.cs
│ │ ├── MapObjectObjectCeiling.cs
│ │ ├── MapObjectObjectCustomArrow.cs
│ │ ├── MapObjectObjectFacingArrow.cs
│ │ ├── MapObjectObjectFloor.cs
│ │ ├── MapObjectObjectGraphicsArrow.cs
│ │ ├── MapObjectObjectGraphicsTriangles.cs
│ │ ├── MapObjectObjectMovingArrow.cs
│ │ ├── MapObjectObjectSpeedArrow.cs
│ │ ├── MapObjectObjectTargetArrow.cs
│ │ ├── MapObjectObjectWall.cs
│ │ ├── MapObjectOffsetPositionAngle.cs
│ │ ├── MapObjectPath.cs
│ │ ├── MapObjectPathSegment.cs
│ │ ├── MapObjectPoint.cs
│ │ ├── MapObjectPreviousPositions.cs
│ │ ├── MapObjectPuGridlines.cs
│ │ ├── MapObjectPunchDetector.cs
│ │ ├── MapObjectPunchFloor.cs
│ │ ├── MapObjectPushHitboxCylinder.cs
│ │ ├── MapObjectPyramidNormal.cs
│ │ ├── MapObjectPyramidNormalTarget.cs
│ │ ├── MapObjectPyramidPlatformNormals.cs
│ │ ├── MapObjectQuad.cs
│ │ ├── MapObjectRenderTable.cs
│ │ ├── MapObjectScuttlebugLungingArrow.cs
│ │ ├── MapObjectSector.cs
│ │ ├── MapObjectSelf.cs
│ │ ├── MapObjectSettings.cs
│ │ ├── MapObjectSettingsAccumulator.cs
│ │ ├── MapObjectSlidePositions.cs
│ │ ├── MapObjectSphere.cs
│ │ ├── MapObjectSquishCancelSpots.cs
│ │ ├── MapObjectSwooperEffectiveTargetArrow.cs
│ │ ├── MapObjectTangibilitySphere.cs
│ │ ├── MapObjectTriangle.cs
│ │ ├── MapObjectUnitGridlines.cs
│ │ ├── MapObjectWall.cs
│ │ ├── MapObjectWaters.cs
│ │ ├── MapSemaphore.cs
│ │ ├── MapSemaphoreManager.cs
│ │ ├── MapTracker.Designer.cs
│ │ ├── MapTracker.cs
│ │ ├── MapTracker.resx
│ │ ├── MapTrackerFlowLayoutPanel.cs
│ │ └── MapUtilities.cs
│ ├── Models/
│ │ ├── ByteModel.cs
│ │ ├── CameraDataModel.cs
│ │ ├── DataModels.cs
│ │ ├── IUpdatableDataModel.cs
│ │ ├── LevelDataModel.cs
│ │ ├── MarioDataModel.cs
│ │ ├── ObjectDataModel.cs
│ │ ├── ObjectProcessorDataModel.cs
│ │ ├── PanModel.cs
│ │ ├── TriangleDataModel.cs
│ │ ├── TriangleDataModelCustom.cs
│ │ ├── TriangleDataModelFull.cs
│ │ ├── TriangleDataModelLazy.cs
│ │ └── TriangleMapData.cs
│ ├── Program.cs
│ ├── Properties/
│ │ ├── AssemblyInfo.cs
│ │ ├── Resources.Designer.cs
│ │ ├── Resources.resx
│ │ ├── Settings.Designer.cs
│ │ └── Settings.settings
│ ├── Resources/
│ │ ├── Hacks/
│ │ │ ├── Camera45Hack.hck
│ │ │ ├── CameraControl.hck
│ │ │ ├── DisplayVariable.hck
│ │ │ ├── DisplayVariable2.hck
│ │ │ ├── HitboxViewJ.hck
│ │ │ ├── HitboxViewU.hck
│ │ │ ├── NumRngUsagesJ.hck
│ │ │ ├── NumRngUsagesU.hck
│ │ │ ├── ObjectGraphicsTriangles.hck
│ │ │ ├── ObjectGraphicsTrianglesCameraPov.hck
│ │ │ ├── PreviousPositionsHackJ.hck
│ │ │ ├── PreviousPositionsHackU.hck
│ │ │ ├── PuVisible.hck
│ │ │ ├── QFrameInfoHack.hck
│ │ │ ├── RcpCrashJ.hck
│ │ │ ├── RcpCrashU.hck
│ │ │ ├── ReenableDebugControlsJ.hck
│ │ │ ├── ReenableDebugControlsU.hck
│ │ │ └── SpawnHack.hck
│ │ ├── Scripts/
│ │ │ ├── FrameProc.src64
│ │ │ ├── ObjectEndProc.src64
│ │ │ └── ObjectStartProc.src64
│ │ └── Shaders/
│ │ ├── FragmentShader.glsl
│ │ └── VertexShader.glsl
│ ├── STROOP.csproj
│ ├── Script/
│ │ ├── ScriptEngine.cs
│ │ └── TokenScript.cs
│ ├── Structs/
│ │ ├── ActionTable.cs
│ │ ├── AnimationTable.cs
│ │ ├── BehaviorCriteria.cs
│ │ ├── Configurations/
│ │ │ ├── AreaConfig.cs
│ │ │ ├── CamHackConfig.cs
│ │ │ ├── CameraConfig.cs
│ │ │ ├── Config.cs
│ │ │ ├── DebugConfig.cs
│ │ │ ├── FileConfig.cs
│ │ │ ├── GhostHackConfig.cs
│ │ │ ├── GotoRetrieveConfig.cs
│ │ │ ├── HackConfig.cs
│ │ │ ├── HudConfig.cs
│ │ │ ├── InputConfig.cs
│ │ │ ├── LockConfig.cs
│ │ │ ├── M64Config.cs
│ │ │ ├── MainSaveConfig.cs
│ │ │ ├── MapConfig.cs
│ │ │ ├── MappingConfig.cs
│ │ │ ├── MarioConfig.cs
│ │ │ ├── MarioObjectConfig.cs
│ │ │ ├── MiscConfig.cs
│ │ │ ├── ObjectConfig.cs
│ │ │ ├── ObjectSlotsConfig.cs
│ │ │ ├── OptionsConfig.cs
│ │ │ ├── OverlayConfig.cs
│ │ │ ├── PaintingConfig.cs
│ │ │ ├── PositionControllerRelativityConfig.cs
│ │ │ ├── RefreshRateConfig.cs
│ │ │ ├── RomVersionConfig.cs
│ │ │ ├── SavedSettingsConfig.cs
│ │ │ ├── SnowConfig.cs
│ │ │ ├── SpecialConfig.cs
│ │ │ ├── TableConfig.cs
│ │ │ ├── TestingConfig.cs
│ │ │ ├── TriangleConfig.cs
│ │ │ ├── TriangleOffsetsConfig.cs
│ │ │ ├── TtcObjectConfig.cs
│ │ │ ├── VarHackConfig.cs
│ │ │ └── WaypointConfig.cs
│ │ ├── CourseDataTable.cs
│ │ ├── Emulator.cs
│ │ ├── FlyGuyDataTable.cs
│ │ ├── GameScript.cs
│ │ ├── Gui/
│ │ │ ├── FileImageGui.cs
│ │ │ ├── InputImageGui.cs
│ │ │ ├── M64Gui.cs
│ │ │ └── ObjectSlotManagerGui.cs
│ │ ├── InputFrame.cs
│ │ ├── Map/
│ │ │ ├── BackgroundImage.cs
│ │ │ ├── MapAssociations.cs
│ │ │ └── MapLayout.cs
│ │ ├── MissionTable.cs
│ │ ├── MusicEntry.cs
│ │ ├── MusicTable.cs
│ │ ├── ObjectAngleTable.cs
│ │ ├── ObjectAssociations.cs
│ │ ├── ObjectBehaviorAssociation.cs
│ │ ├── PendulumSwingTable.cs
│ │ ├── PendulumVertexTable.cs
│ │ ├── PointTable.cs
│ │ ├── ProcessSelection.cs
│ │ ├── PushHitbox.cs
│ │ ├── RomHack.cs
│ │ ├── SpawnHack.cs
│ │ ├── TriangleInfoTable.cs
│ │ ├── TrigTable.cs
│ │ └── WaypointTable.cs
│ ├── TTC/
│ │ ├── TTCAmp.cs
│ │ ├── TTCBobomb.cs
│ │ ├── TTCCog.cs
│ │ ├── TTCDust.cs
│ │ ├── TTCElevator.cs
│ │ ├── TTCHand.cs
│ │ ├── TTCMain.cs
│ │ ├── TTCObject.cs
│ │ ├── TTCPendulum.cs
│ │ ├── TTCPitBlock.cs
│ │ ├── TTCPusher.cs
│ │ ├── TTCRNG.cs
│ │ ├── TTCRotatingBlock.cs
│ │ ├── TTCRotatingTriangularPrism.cs
│ │ ├── TTCSpinner.cs
│ │ ├── TTCSpinningTriangle.cs
│ │ ├── TTCThwomp.cs
│ │ ├── TTCTreadmill.cs
│ │ ├── TTCWheel.cs
│ │ ├── TtcPendulum2.cs
│ │ ├── TtcPendulumBad.cs
│ │ ├── TtcRng2.cs
│ │ ├── TtcSaveState.cs
│ │ ├── TtcSaveStateByteIterator.cs
│ │ ├── TtcSimulation.cs
│ │ └── TtcUtilities.cs
│ ├── Utilities/
│ │ ├── AnimationUtilities.cs
│ │ ├── AreaUtilities.cs
│ │ ├── BehaviorDecoder.cs
│ │ ├── BitfsPlatformGroupTable.cs
│ │ ├── BoolUtilities.cs
│ │ ├── ButtonUtilities.cs
│ │ ├── CamHackUtilities.cs
│ │ ├── CellSnapshot.cs
│ │ ├── CellUtilities.cs
│ │ ├── CogUtilities.cs
│ │ ├── CoinMovementCalculator.cs
│ │ ├── CoinObject.cs
│ │ ├── CoinTrajectoryFilter.cs
│ │ ├── CoinTrajejctory.cs
│ │ ├── ColorUtilities.cs
│ │ ├── ControlUtilities.cs
│ │ ├── CopyUtilities.cs
│ │ ├── CorkBox.cs
│ │ ├── CorkBoxUtilities.cs
│ │ ├── DecompilerFunctionUtilities.cs
│ │ ├── DemoCounterUtilities.cs
│ │ ├── DialogUtilities.cs
│ │ ├── DictionaryUtilities.cs
│ │ ├── EasingUtilities.cs
│ │ ├── EndianUtilities.cs
│ │ ├── EndiannessUtilities.cs
│ │ ├── EnumUtilities.cs
│ │ ├── ExtendedLevelBoundariesUtilities.cs
│ │ ├── Fast3DDecoder.cs
│ │ ├── FlyingUtilities.cs
│ │ ├── HelpfulHintUtilities.cs
│ │ ├── HexUtilities.cs
│ │ ├── ImageUtilities.cs
│ │ ├── InGameFunctionCall.cs
│ │ ├── InGameTrigUtilities.cs
│ │ ├── Kernal32NativeMethods.cs
│ │ ├── KeyboardUtilities.cs
│ │ ├── LazyImage.cs
│ │ ├── MathOperationUtilities.cs
│ │ ├── MoreMath.cs
│ │ ├── MupenUtilities.cs
│ │ ├── N64Disassembler.cs
│ │ ├── ObjectOrderingUtilities.cs
│ │ ├── ObjectRngUtilities.cs
│ │ ├── ObjectSnapshot.cs
│ │ ├── ObjectUtilities.cs
│ │ ├── ParsingUtilities.cs
│ │ ├── PasteUtilities.cs
│ │ ├── PlushUtilities.cs
│ │ ├── PositionAngle.cs
│ │ ├── ProcessGroupUtilities.cs
│ │ ├── PuUtilities.cs
│ │ ├── RngIndexer.cs
│ │ ├── ScriptParser.cs
│ │ ├── SegmentationUtilities.cs
│ │ ├── SkribblioUtilities.cs
│ │ ├── Stream/
│ │ │ ├── BaseProcessIO.cs
│ │ │ ├── DolphinProcessIO.cs
│ │ │ ├── IEmuRamIO.cs
│ │ │ ├── ProcessStream.cs
│ │ │ ├── StFileIO.cs
│ │ │ └── WindowsProcessIO.cs
│ │ ├── StringUtilities.cs
│ │ ├── SubtitleUtilities.cs
│ │ ├── TestUtilities.cs
│ │ ├── TestUtilities2.cs
│ │ ├── TrackPlatform.cs
│ │ ├── TrackPlatformTable.cs
│ │ ├── TriangleUtilities.cs
│ │ ├── TtcSpeedSettingUtilities.cs
│ │ ├── TypeUtilities.cs
│ │ ├── VarHackSpecialUtilities.cs
│ │ ├── WatchVariableCoordinateManager.cs
│ │ ├── WatchVariableSelectionUtilities.cs
│ │ ├── WatchVariableSpecialDictionary.cs
│ │ ├── WatchVariableSpecialUtilities.cs
│ │ ├── WatchVariableUtilities.cs
│ │ ├── WaterUtilities.cs
│ │ ├── XmlConfigParser.cs
│ │ └── ZipUtilities.cs
│ └── app.manifest
├── STROOP.sln
├── STROOPUnitTests/
│ ├── Mocks/
│ │ └── MockEmuIO.cs
│ ├── ProcessStreamTests.cs
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ ├── STROOPUnitTests.csproj
│ └── app.config
└── azure-pipelines.yml
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
[Xx]64/
[Xx]86/
[Bb]uild/
Windows Build/
bld/
[Bb]in/
[Oo]bj/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Un-comment the next line if you do not want to checkin
# your web deploy settings because they may include unencrypted
# passwords
#*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Microsoft Azure ApplicationInsights config file
ApplicationInsights.config
# Windows Store app package directory
AppPackages/
BundleArtifacts/
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# LightSwitch generated files
GeneratedArtifacts/
ModelManifest.xml
# Paket dependency manager
.paket/paket.exe
# FAKE - F# Make
.fake/
# Temp csproj
*tmp.csproj
================================================
FILE: Directory.Build.props
================================================
$(DefineConstants);TRACE
prompt
7.1
true
full
$(DefineConstants);DEBUG
false
pdbonly
true
================================================
FILE: README.md
================================================
# STROOP
*SuperMario64 Technical Runtime Observer and Object Processor*
STROOP is a diagnostic tool for Super Mario 64 that displays and allows for simple editing of various game values and information. It can connect to a running emulator and update values in real time. Some core features include views of loaded/unloaded objects, Mario structure variables, camera + HUD values, an overhead map display, and many more.
## Downloading STROOP
The latest release of STROOP can be downloaded from our [Releases Page](https://github.com/SM64-TAS-ABC/STROOP/releases). From here .zip files of recent builds can be found. The files can then be extracted and stroop.exe can be started.
Latest development builds with the newest features, bug fixes can be found on the continuous [Development Release](https://github.com/SM64-TAS-ABC/STROOP/releases/vDev). Likewise, stroop.exe can be started.
## Requirements
As of the current build, STROOP has the following system requirements:
* Windows 10 / Windows 8.1 / Windows 8 / Windows 7 64-bit or 32-bit
* OpenGL 3.0 or greater (3.0 requirement for map tab, 1.0 requirement for model tab only)
* .NET Framework 4.6.1 (See [.NET Framework System Requirements](https://msdn.microsoft.com/en-us/library/8z6watww(v=vs.110).aspx) for more information)
* Supported Emulators
* Mupen
* Bizhawk
* Nemu
* Mupen64Plus
* Project64
* Dolphin
* 64 Marios (Must be super)
* Marios must be American, Japanese, PAL, or Shindou
## Building
Requirements:
* Visual Studio *(2017 recommended)*
OpenTK is a prerequisite for building STROOP. This is easiest installed by using the NuGet package manager. STROOP can be easily built from the source code by opening up the solution file in Visual Studio and performing a build.
================================================
FILE: STROOP/App.config
================================================
================================================
FILE: STROOP/Calculators/AirMovementCalculator.cs
================================================
using STROOP.Forms;
using STROOP.Managers;
using STROOP.Models;
using STROOP.Structs.Configurations;
using STROOP.Utilities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STROOP.Structs
{
public static class AirMovementCalculator
{
public static MarioState ApplyInput(MarioState marioState, Input input, int numQSteps = 4, List wallTris = null, List quarterSteps = null, bool resetHSpeedOnWalls = false)
{
MarioState withHSpeed = ComputeAirHSpeed(marioState, input);
MarioState moved = AirMove(withHSpeed, numQSteps, wallTris, quarterSteps, resetHSpeedOnWalls);
MarioState withYSpeed = ComputeAirYSpeed(moved);
return withYSpeed;
}
public static MarioState ApplyInput(MarioState marioState, int angleDiff, int numQSteps = 4, List wallTris = null, List quarterSteps = null, bool resetHSpeedOnWalls = false)
{
MarioState withHSpeed = ComputeAirHSpeed(marioState, angleDiff);
MarioState moved = AirMove(withHSpeed, numQSteps, wallTris, quarterSteps, resetHSpeedOnWalls);
MarioState withYSpeed = ComputeAirYSpeed(moved);
return withYSpeed;
}
public static MarioState ApplyInput(MarioState marioState, RelativeDirection direction, int numQSteps = 4)
{
MarioState withHSpeed = ComputeAirHSpeed(marioState, direction);
MarioState moved = AirMove(withHSpeed, numQSteps);
MarioState withYSpeed = ComputeAirYSpeed(moved);
return withYSpeed;
}
public static MarioState ApplyInputRepeatedly(MarioState marioState, RelativeDirection direction, int numQSteps)
{
int numFrames = numQSteps / 4;
int remainderQSteps = numQSteps % 4;
for (int i = 0; i < numFrames; i++)
{
marioState = ApplyInput(marioState, direction);
}
return remainderQSteps == 0 ? marioState : ApplyInput(marioState, direction, remainderQSteps);
}
public static MarioState AirMove(MarioState initialState, int numQSteps = 4, List wallTris = null, List quarterSteps = null, bool resetHSpeedOnWalls = false)
{
bool resetHSpeed = false;
float newX = initialState.X;
float newY = initialState.Y;
float newZ = initialState.Z;
if (wallTris != null)
{
bool collidedWithWall;
(newX, newZ, collidedWithWall) = WallDisplacementCalculator.HandleWallDisplacement2(newX, newY, newZ, wallTris, 50, 60);
if (collidedWithWall && resetHSpeedOnWalls) resetHSpeed = true;
}
for (int i = 0; i < numQSteps; i++)
{
newX += initialState.XSpeed / 4;
newY += initialState.YSpeed / 4;
newZ += initialState.ZSpeed / 4;
if (wallTris != null)
{
bool collidedWithWall1;
bool collidedWithWall2;
(newX, newZ, collidedWithWall1) = WallDisplacementCalculator.HandleWallDisplacement2(newX, newY, newZ, wallTris, 50, 150);
(newX, newZ, collidedWithWall2) = WallDisplacementCalculator.HandleWallDisplacement2(newX, newY, newZ, wallTris, 50, 30);
if (collidedWithWall1 && resetHSpeedOnWalls) resetHSpeed = true;
if (collidedWithWall2 && resetHSpeedOnWalls) resetHSpeed = true;
}
if (quarterSteps != null)
{
quarterSteps.Add(
new MarioState(
newX,
newY,
newZ,
initialState.XSpeed,
initialState.YSpeed,
initialState.ZSpeed,
initialState.HSpeed,
initialState.SlidingSpeedX,
initialState.SlidingSpeedZ,
initialState.SlidingAngle,
initialState.MarioAngle,
initialState.CameraAngle,
initialState.PreviousState,
initialState.LastInput,
initialState.Index));
}
}
return new MarioState(
newX,
newY,
newZ,
initialState.XSpeed,
initialState.YSpeed,
initialState.ZSpeed,
resetHSpeed ? 0 : initialState.HSpeed,
initialState.SlidingSpeedX,
initialState.SlidingSpeedZ,
initialState.SlidingAngle,
initialState.MarioAngle,
initialState.CameraAngle,
initialState.PreviousState,
initialState.LastInput,
initialState.Index);
}
// update_air_without_turn
private static MarioState ComputeAirHSpeed(MarioState initialState, int angleDiff)
{
bool longJump = false;
int maxSpeed = longJump ? 48 : 32;
ushort marioAngle = initialState.MarioAngle;
int deltaAngleIntendedFacing = angleDiff;
float inputScaledMagnitude = 32;
float perpSpeed = 0;
float newHSpeed = ApproachHSpeed(initialState.HSpeed, 0, 0.35f, 0.35f);
if (inputScaledMagnitude > 0)
{
newHSpeed += (inputScaledMagnitude / 32) * 1.5f * InGameTrigUtilities.InGameCosine(deltaAngleIntendedFacing);
perpSpeed = InGameTrigUtilities.InGameSine(deltaAngleIntendedFacing) * (inputScaledMagnitude / 32) * 10;
}
if (newHSpeed > maxSpeed) newHSpeed -= 1;
if (newHSpeed < -16) newHSpeed += 2;
float newSlidingXSpeed = InGameTrigUtilities.InGameSine(marioAngle) * newHSpeed;
float newSlidingZSpeed = InGameTrigUtilities.InGameCosine(marioAngle) * newHSpeed;
newSlidingXSpeed += perpSpeed * InGameTrigUtilities.InGameSine(marioAngle + 0x4000);
newSlidingZSpeed += perpSpeed * InGameTrigUtilities.InGameCosine(marioAngle + 0x4000);
float newXSpeed = newSlidingXSpeed;
float newZSpeed = newSlidingZSpeed;
return new MarioState(
initialState.X,
initialState.Y,
initialState.Z,
newXSpeed,
initialState.YSpeed,
newZSpeed,
newHSpeed,
initialState.SlidingSpeedX,
initialState.SlidingSpeedZ,
initialState.SlidingAngle,
initialState.MarioAngle,
initialState.CameraAngle,
initialState,
new Input(angleDiff, 0),
initialState.Index + 1);
}
// update_air_without_turn
private static MarioState ComputeAirHSpeed(MarioState initialState, Input input)
{
bool longJump = false;
int maxSpeed = longJump ? 48 : 32;
ushort marioAngle = initialState.MarioAngle;
ushort yawIntended = MoreMath.CalculateAngleFromInputs(input.X, input.Y, initialState.CameraAngle);
int deltaAngleIntendedFacing = yawIntended - marioAngle;
float inputScaledMagnitude = input.GetScaledMagnitude();
float perpSpeed = 0;
float newHSpeed = ApproachHSpeed(initialState.HSpeed, 0, 0.35f, 0.35f);
if (inputScaledMagnitude > 0)
{
newHSpeed += (inputScaledMagnitude / 32) * 1.5f * InGameTrigUtilities.InGameCosine(deltaAngleIntendedFacing);
perpSpeed = InGameTrigUtilities.InGameSine(deltaAngleIntendedFacing) * (inputScaledMagnitude / 32) * 10;
}
if (newHSpeed > maxSpeed) newHSpeed -= 1;
if (newHSpeed < -16) newHSpeed += 2;
float newSlidingXSpeed = InGameTrigUtilities.InGameSine(marioAngle) * newHSpeed;
float newSlidingZSpeed = InGameTrigUtilities.InGameCosine(marioAngle) * newHSpeed;
newSlidingXSpeed += perpSpeed * InGameTrigUtilities.InGameSine(marioAngle + 0x4000);
newSlidingZSpeed += perpSpeed * InGameTrigUtilities.InGameCosine(marioAngle + 0x4000);
float newXSpeed = newSlidingXSpeed;
float newZSpeed = newSlidingZSpeed;
return new MarioState(
initialState.X,
initialState.Y,
initialState.Z,
newXSpeed,
initialState.YSpeed,
newZSpeed,
newHSpeed,
initialState.SlidingSpeedX,
initialState.SlidingSpeedZ,
initialState.SlidingAngle,
initialState.MarioAngle,
initialState.CameraAngle,
initialState,
input,
initialState.Index + 1);
}
// update_air_without_turn
private static MarioState ComputeAirHSpeed(MarioState initialState, RelativeDirection direction)
{
bool longJump = false;
int maxSpeed = longJump ? 48 : 32;
ushort marioAngle = initialState.MarioAngle;
int deltaAngleIntendedFacing;
switch (direction)
{
case RelativeDirection.Forward:
deltaAngleIntendedFacing = 0;
break;
case RelativeDirection.Backward:
deltaAngleIntendedFacing = 32768;
break;
case RelativeDirection.Left:
deltaAngleIntendedFacing = 16384;
break;
case RelativeDirection.Right:
deltaAngleIntendedFacing = 49152;
break;
case RelativeDirection.Center:
deltaAngleIntendedFacing = 0;
break;
default:
throw new ArgumentOutOfRangeException();
}
float inputScaledMagnitude = direction == RelativeDirection.Center ? 0 : 32;
float perpSpeed = 0;
float newHSpeed = ApproachHSpeed(initialState.HSpeed, 0, 0.35f, 0.35f);
if (inputScaledMagnitude > 0)
{
newHSpeed += (inputScaledMagnitude / 32) * 1.5f * InGameTrigUtilities.InGameCosine(deltaAngleIntendedFacing);
perpSpeed = InGameTrigUtilities.InGameSine(deltaAngleIntendedFacing) * (inputScaledMagnitude / 32) * 10;
}
if (newHSpeed > maxSpeed) newHSpeed -= 1;
if (newHSpeed < -16) newHSpeed += 2;
float newSlidingXSpeed = InGameTrigUtilities.InGameSine(marioAngle) * newHSpeed;
float newSlidingZSpeed = InGameTrigUtilities.InGameCosine(marioAngle) * newHSpeed;
newSlidingXSpeed += perpSpeed * InGameTrigUtilities.InGameSine(marioAngle + 0x4000);
newSlidingZSpeed += perpSpeed * InGameTrigUtilities.InGameCosine(marioAngle + 0x4000);
float newXSpeed = newSlidingXSpeed;
float newZSpeed = newSlidingZSpeed;
return new MarioState(
initialState.X,
initialState.Y,
initialState.Z,
newXSpeed,
initialState.YSpeed,
newZSpeed,
newHSpeed,
initialState.SlidingSpeedX,
initialState.SlidingSpeedZ,
initialState.SlidingAngle,
initialState.MarioAngle,
initialState.CameraAngle,
initialState,
null,
initialState.Index + 1);
}
private static float ComputeAirHSpeed(float initialHSpeed)
{
int maxSpeed = 32;
float newHSpeed = ApproachHSpeed(initialHSpeed, 0, 0.35f, 0.35f);
if (newHSpeed > maxSpeed) newHSpeed -= 1;
if (newHSpeed < -16) newHSpeed += 2;
return newHSpeed;
}
public static float ComputePosition(float position, float hSpeed, int frames)
{
for (int i = 0; i < frames; i++)
{
hSpeed = ComputeAirHSpeed(hSpeed);
position += hSpeed;
}
return position;
}
private static MarioState ComputeAirYSpeed(MarioState initialState)
{
float newYSpeed = Math.Max(initialState.YSpeed - 4, -75);
return new MarioState(
initialState.X,
initialState.Y,
initialState.Z,
initialState.XSpeed,
newYSpeed,
initialState.ZSpeed,
initialState.HSpeed,
initialState.SlidingSpeedX,
initialState.SlidingSpeedZ,
initialState.SlidingAngle,
initialState.MarioAngle,
initialState.CameraAngle,
initialState.PreviousState,
initialState.LastInput,
initialState.Index);
}
private static float ApproachHSpeed(float speed, float maxSpeed, float increase, float decrease)
{
if (speed < maxSpeed)
return Math.Min(maxSpeed, speed + increase);
else
return Math.Max(maxSpeed, speed - decrease);
}
}
}
================================================
FILE: STROOP/Calculators/BobombState.cs
================================================
using STROOP.Forms;
using STROOP.Managers;
using STROOP.Structs.Configurations;
using STROOP.Utilities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STROOP.Structs
{
public class BobombState
{
public float X;
public float Y;
public float Z;
public float XSpeed;
public float YSpeed;
public float ZSpeed;
public float HSpeed;
public ushort Yaw;
public float HomeX;
public float HomeY;
public float HomeZ;
public int Timer;
public BobombState(
float x,
float y,
float z,
float xSpeed,
float ySpeed,
float zSpeed,
float hSpeed,
ushort yaw,
float homeX,
float homeY,
float homeZ)
{
X = x;
Y = y;
Z = z;
XSpeed = xSpeed;
YSpeed = ySpeed;
ZSpeed = zSpeed;
HSpeed = hSpeed;
Yaw = yaw;
HomeX = homeX;
HomeY = homeY;
HomeZ = homeZ;
Timer = 0;
}
public void bobomb_act_patrol()
{
HSpeed = 5.0f;
object_step();
obj_return_home_if_safe();
Timer++;
}
public void object_step()
{
float objVelX = HSpeed * InGameTrigUtilities.InGameSine(Yaw);
float objVelZ = HSpeed * InGameTrigUtilities.InGameCosine(Yaw);
calc_new_obj_vel_and_pos_y(objVelX, objVelZ);
obj_update_pos_vel_xz();
}
void calc_new_obj_vel_and_pos_y(float objVelX, float objVelZ) {
float floor_nX = 0;
float floor_nY = 1;
float floor_nZ = 0;
// Caps vertical speed with a "terminal velocity".
YSpeed -= 2.5f;
if (YSpeed > 75.0)
{
YSpeed = 75.0f;
}
if (YSpeed < -75.0)
{
YSpeed = -75.0f;
}
float floorY = Y;
Y += YSpeed;
//Snap the object up to the floor.
if (Y < floorY)
{
Y = floorY;
// Bounces an object if the ground is hit fast enough.
if (YSpeed < -17.5)
{
YSpeed = -(YSpeed / 2);
}
else
{
YSpeed = 0;
}
}
//! (Obj Position Crash) If you got an object with height past 2^31, the game would crash.
if ((int)Y >= (int)floorY && (int)Y < (int)floorY + 37)
{
// Adds horizontal component of gravity for horizontal speed.
objVelX += floor_nX * (floor_nX * floor_nX + floor_nZ * floor_nZ)
/ (floor_nX * floor_nX + floor_nY * floor_nY + floor_nZ * floor_nZ) * 2.5f
* 2;
objVelZ += floor_nZ * (floor_nX * floor_nX + floor_nZ * floor_nZ)
/ (floor_nX * floor_nX + floor_nY * floor_nY + floor_nZ * floor_nZ) * 2.5f
* 2;
if (objVelX < 0.000001 && objVelX > -0.000001)
{
objVelX = 0;
}
if (objVelZ < 0.000001 && objVelZ > -0.000001)
{
objVelZ = 0;
}
if (objVelX != 0 || objVelZ != 0)
{
Yaw = InGameTrigUtilities.InGameATan(objVelZ, objVelX);
}
HSpeed = (float)Math.Sqrt(objVelX * objVelX + objVelZ * objVelZ) * 0.8f;
}
}
public void obj_update_pos_vel_xz()
{
float xVel = HSpeed * InGameTrigUtilities.InGameSine(Yaw);
float zVel = HSpeed * InGameTrigUtilities.InGameCosine(Yaw);
X += xVel;
Z += zVel;
}
public void obj_return_home_if_safe() {
float homeDistX = HomeX - X;
float homeDistZ = HomeZ - Z;
short angleTowardsHome = (short)InGameTrigUtilities.InGameATan(homeDistZ, homeDistX);
Yaw = (ushort)approach_s16_symmetric((short)Yaw, angleTowardsHome, 320);
}
public short approach_s16_symmetric(short value, short target, short increment)
{
short dist = MoreMath.NormalizeAngleShort(target - value);
if (dist >= 0)
{
if (dist > increment)
{
value += increment;
}
else
{
value = target;
}
}
else
{
if (dist < -increment)
{
value -= increment;
}
else
{
value = target;
}
}
return value;
}
public override string ToString()
{
return string.Format(
"[{13}] pos=({0},{1},{2}) speed=({3},{4},{5}) hSpeed={6} yaw={7} home=({8},{9},{10}) distFromHome={11} angleFromHome={12}",
(double)X, (double)Y, (double)Z,
(double)XSpeed, (double)YSpeed, (double)ZSpeed,
(double)HSpeed, Yaw,
(double)HomeX, (double)HomeY, (double)HomeZ,
MoreMath.GetDistanceBetween(HomeX, HomeZ, X, Z),
MoreMath.AngleTo_AngleUnitsRounded(HomeX, HomeZ, X, Z), Timer);
}
}
}
================================================
FILE: STROOP/Calculators/CalculatorMain.cs
================================================
using STROOP.Forms;
using STROOP.Managers;
using STROOP.Models;
using STROOP.Structs.Configurations;
using STROOP.Utilities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STROOP.Structs
{
public static class CalculatorMain
{
public static void CalculateMovementForBitsHolp()
{
float startX = 435.913696289063f;
float startY = 4474f;
float startZ = -1854.50500488281f;
float startXSpeed = -16.1702556610107f;
float startYSpeed = -75f;
float startZSpeed = -17.676326751709f;
float startHSpeed = 23.8997459411621f;
ushort marioAngle = 39780;
ushort cameraAngle = 16384;
float goalX = 392.857605f;
float goalY = 4249f;
float goalZ = -1901.016846f;
int xInput = -56;
int zInput = -31;
int xRadius = 10;
int zRadius = 10;
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
0,
0,
0,
marioAngle,
cameraAngle,
null,
null,
0);
int lastIndex = -1;
List inputs = CalculatorUtilities.GetInputRange(xInput - xRadius, xInput + xRadius, zInput - zRadius, zInput + zRadius);
float bestDiff = float.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
HashSet alreadySeen = new HashSet();
queue.Enqueue(startState);
alreadySeen.Add(startState);
while (queue.Count != 0)
{
MarioState dequeue = queue.Dequeue();
List nextStates = inputs.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input));
foreach (MarioState state in nextStates)
{
if (alreadySeen.Contains(state)) continue;
if (state.Index > 3) continue;
if (state.Index != lastIndex)
{
lastIndex = state.Index;
System.Diagnostics.Trace.WriteLine("Now at index " + lastIndex);
}
if (state.Index == 3)
{
float diff = (float)MoreMath.GetDistanceBetween(state.X, state.Z, goalX, goalZ);
if (diff < bestDiff)
{
bestDiff = diff;
bestState = state;
System.Diagnostics.Trace.WriteLine("Diff of " + bestDiff + " is: " + bestState.GetLineage());
}
}
alreadySeen.Add(state);
queue.Enqueue(state);
}
}
System.Diagnostics.Trace.WriteLine("Done");
}
public static void CalculateMovementForWfHolp()
{
float startX = 310.128448486328f;
float startY = 4384f;
float startZ = -1721.65405273438f;
float startXSpeed = 15.5246114730835f;
float startYSpeed = -24f;
float startZSpeed = -12.4710474014282f;
float startHSpeed = 19.8780212402344f;
ushort marioAngle = 24066;
Dictionary cameraAngles =
new Dictionary()
{
//[0] = 32707,
[0] = 32768,
[1] = 32839,
[2] = 32900,
[3] = 32972,
[4] = 33063,
[5] = 33135,
[6] = 33216,
};
float goalX = 374.529907226563f;
float goalY = 4264f;
float goalZ = -1773.07543945313f;
int xInput = -45;
int zInput = -27;
int xRadius = 5;
int zRadius = 5;
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
0,
0,
0,
marioAngle,
cameraAngles[0],
null,
null,
0);
int lastIndex = -1;
List inputs = CalculatorUtilities.GetInputRange(xInput - xRadius, xInput + xRadius, zInput - zRadius, zInput + zRadius);
float bestDiff = float.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
HashSet alreadySeen = new HashSet();
queue.Enqueue(startState);
alreadySeen.Add(startState);
while (queue.Count != 0)
{
MarioState dequeue = queue.Dequeue();
List nextStates = inputs.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input));
nextStates = nextStates.ConvertAll(state => state.WithCameraAngle(cameraAngles[state.Index]));
foreach (MarioState state in nextStates)
{
if (alreadySeen.Contains(state)) continue;
if (state.Index > 4) continue;
if (state.Index != lastIndex)
{
lastIndex = state.Index;
System.Diagnostics.Trace.WriteLine("Now at index " + lastIndex);
}
if (state.Index == 4)
{
float diff = (float)MoreMath.GetDistanceBetween(state.X, state.Z, goalX, goalZ);
if (diff < bestDiff)
{
bestDiff = diff;
bestState = state;
System.Diagnostics.Trace.WriteLine("Diff of " + bestDiff + " is: " + bestState.GetLineage());
}
}
alreadySeen.Add(state);
queue.Enqueue(state);
}
}
System.Diagnostics.Trace.WriteLine("Done");
}
public static void CalculateMovementForBully()
{
/*
float startX = -6842.04736328125f;
float startY = 2358;
float startZ = -506.698120117188f;
float startXSpeed = -34.6734008789063f;
float startYSpeed = -74;
float startZSpeed = 0;
float startHSpeed = 34.6734008789063f;
*/
float startX = -8172.14892578125f;
float startY = -47.4696655273438f;
float startZ = -507.290283203125f;
float startXSpeed = -3.33430767059326f;
float startYSpeed = -75;
float startZSpeed = 0;
float startHSpeed = 3.33430767059326f;
float goalX = -8171.970703125f;
float goalZ = -507.2902832031f;
ushort marioAngle = 49152;
ushort cameraAngle = 32768;
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
0,
0,
0,
marioAngle,
cameraAngle,
null,
null,
0);
int lastIndex = -1;
List inputs = CalculatorUtilities.GetInputRange(-70, 70, 0, 0);
float bestDiff = float.MaxValue;
Queue queue = new Queue();
HashSet alreadySeen = new HashSet();
queue.Enqueue(startState);
while (queue.Count != 0)
{
MarioState dequeue = queue.Dequeue();
List nextStates = inputs.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input));
foreach (MarioState state in nextStates)
{
if (alreadySeen.Contains(state)) continue;
float threshold = 10f / (state.Index * state.Index);
if (state.Index != lastIndex)
{
lastIndex = state.Index;
System.Diagnostics.Trace.WriteLine("Now at index " + lastIndex + " with threshold " + threshold);
}
float diff = (float)MoreMath.GetDistanceBetween(state.X, state.Z, goalX, goalZ);
if (diff > threshold) continue;
if (diff < bestDiff)
{
bestDiff = diff;
System.Diagnostics.Trace.WriteLine("New best diff of " + diff);
}
//System.Diagnostics.Trace.WriteLine(diff + " < " + threshold + " at index " + state.Index);
if (diff == 0 && Math.Abs(state.HSpeed) < 0.2)
{
System.Diagnostics.Trace.WriteLine("");
System.Diagnostics.Trace.WriteLine(state.GetLineage());
return;
}
alreadySeen.Add(state);
queue.Enqueue(state);
}
}
System.Diagnostics.Trace.WriteLine("FAILED");
}
public static void CalculateMovementForWallGap()
{
float startX = -258.926910400391f;
float startY = 2373f;
float startZ = 5770.876953125f;
float startXSpeed = 30.5356960296631f;
float startYSpeed = -10f;
float startZSpeed = 0f;
float startHSpeed = 30.5356960296631f;
float goalX = -89.956619262695313f;
int listLength = 1000;
List floats = new List();
List counts = new List();
float f = goalX;
for (int i = 0; i < listLength; i++)
{
floats.Add(f);
f += 0.00001f;
counts.Add(0);
}
ushort marioAngle = 16384;
ushort cameraAngle = 49152;
int inputRadius = 8;
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
0,
0,
0,
marioAngle,
cameraAngle,
null,
null,
0);
int lastIndex = -1;
List inputs = CalculatorUtilities.GetInputRange(0, 0, -38 - inputRadius, -38 + inputRadius);
float bestDiff = float.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
HashSet alreadySeen = new HashSet();
queue.Enqueue(startState);
alreadySeen.Add(startState);
while (queue.Count != 0)
{
MarioState dequeue = queue.Dequeue();
List nextStates = inputs.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input));
foreach (MarioState state in nextStates)
{
if (alreadySeen.Contains(state)) continue;
if (state.Index > lastIndex)
{
lastIndex = state.Index;
Config.Print("Now at index " + state.Index + " with queue size " + queue.Count);
/*
if (queue.Count > 100000)
{
Config.Print("Commence pruning");
List states = queue.ToList();
queue.Clear();
Random random = new Random();
while (queue.Count < 100000)
{
int index = random.Next(0, states.Count);
MarioState enqueue = states[index];
states.RemoveAt(index);
queue.Enqueue(enqueue);
}
Config.Print("Now at index " + state.Index + " with queue size " + queue.Count);
}
*/
}
int numFramesRemaining = ((int)state.YSpeed + 34) / 4;
float expectedX = AirMovementCalculator.ComputePosition(state.X, state.XSpeed, numFramesRemaining);
float expectedDiff = Math.Abs(expectedX - goalX);
float threshold = (float)Math.Pow(2, numFramesRemaining) * 2;
if (expectedDiff > threshold) continue;
if (state.YSpeed == -34)
{
float diff = Math.Abs(state.X - goalX);
if (diff <= bestDiff / 1.1f || diff == 0)
{
bestDiff = diff;
bestState = state;
Config.Print("New best diff of " + diff + " with state:\r\n" + state.GetLineage());
}
for (int i = 0; i < floats.Count; i++)
{
if (state.X == floats[i]) counts[i]++;
}
}
else
{
queue.Enqueue(state);
alreadySeen.Add(state);
}
}
}
Config.Print("END");
for (int i = 0; i < floats.Count; i++)
{
Config.Print(i + "\t" + counts[i] + "\t" + floats[i]);
}
}
public static void CalculateMovementForTtmHolp()
{
float startX = 1094.12268066406f;
float startY = -476.171997070313f;
float startZ = -3675.9716796875f;
float startXSpeed = -6.70571994781494f;
float startYSpeed = -52f;
float startZSpeed = -0.628647029399872f;
float startHSpeed = -6.70173645019531f;
ushort marioAngle = 16455;
Dictionary cameraAngles =
new Dictionary()
{
[0] = 28563,
[1] = 28552,
[2] = 28548,
[3] = 28533,
[4] = 28524,
[5] = 28514,
[6] = 28500,
};
float goalX = 1060.860229f;
float goalY = -5001.017029f;
float goalZ = -3678.57666f;
int xInput = 56;
int zInput = 22;
int xRadius = 5;
int zRadius = 5;
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
0,
0,
0,
marioAngle,
cameraAngles[0],
null,
null,
0);
int lastIndex = -1;
List inputs = CalculatorUtilities.GetInputRange(xInput - xRadius, xInput + xRadius, zInput - zRadius, zInput + zRadius);
float bestDiff = float.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
HashSet alreadySeen = new HashSet();
queue.Enqueue(startState);
alreadySeen.Add(startState);
while (queue.Count != 0)
{
MarioState dequeue = queue.Dequeue();
List nextStates = inputs.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input));
nextStates = nextStates.ConvertAll(state => state.WithCameraAngle(cameraAngles[state.Index]));
foreach (MarioState state in nextStates)
{
if (alreadySeen.Contains(state)) continue;
if (state.Index > 4) continue;
if (state.Index != lastIndex)
{
lastIndex = state.Index;
System.Diagnostics.Trace.WriteLine("Now at index " + lastIndex);
}
if (state.Index == 4)
{
float diff = (float)MoreMath.GetDistanceBetween(state.X, state.Z, goalX, goalZ);
if (diff > 1 ? diff < bestDiff * 0.5 : diff < bestDiff)
{
bestDiff = diff;
bestState = state;
System.Diagnostics.Trace.WriteLine("Diff of " + bestDiff + " is: " + bestState.GetLineage());
}
}
alreadySeen.Add(state);
queue.Enqueue(state);
}
}
System.Diagnostics.Trace.WriteLine("Done");
}
public static List<(float, float)> GetSuccessFloatPositions()
{
// initial
float startX = -1378.91674804688f;
float startY = -2434f;
float startZ = -1423.35168457031f;
float startXSpeed = 0f;
float startYSpeed = 20f;
float startZSpeed = 0f;
float startHSpeed = 0f;
// after all 4 q steps (no wall displacement)
float endX = -1376.13940429688f;
float endY = -2414f;
float endZ = -1423.66223144531f;
float endXSpeed = 2.7774920463562f;
float endYSpeed = 16f;
float endZSpeed = -0.310500144958496f;
float endHSpeed = -1.45670866966248f;
// after 1 q step (no wall displacement)
float qstepX = -1378.22241210938f;
float qstepY = -2429f;
float qstepZ = -1423.42932128906f;
float qstepXSpeed = 2.7774920463562f;
float qstepYSpeed = -4f;
float qstepZSpeed = -0.310500144958496f;
float qstepHSpeed = -1.45670866966248f;
// after 1 q step and wall displacement
float displacedX = -1307.73107910156f;
float displacedY = -2429f;
float displacedZ = -1353.11071777344f;
float displacedXSpeed = 0f;
float displacedYSpeed = -4f;
float displacedZSpeed = 0f;
float displacedHSpeed = 0f;
// closest starting position that works
float closestX = -1378.91381835938f;
float closestY = -2434f;
float closestZ = -1423.34875488281f;
float closestXSpeed = -3.67686033248901f;
float closestYSpeed = 0f;
float closestZSpeed = -4.74138116836548f;
float closestHSpeed = 6f;
// farthest starting position that is within range (doesn't work)
float farthestX = -1379.22241210938f;
float farthestY = -2434f;
float farthestZ = -1423.65734863281f;
float farthestXSpeed = 0f;
float farthestYSpeed = 0f;
float farthestZSpeed = 0f;
float farthestHSpeed = 0f;
ushort marioAngle = 39655;
ushort cameraAngle = 7142;
TriangleDataModel tri = TriangleDataModel.CreateLazy(0x8015F910);
List<(float, float)> successPositions = new List<(float, float)>();
int numAttempts = 0;
int numSuccesses = 0;
for (float lineX = closestX, lineZ = closestZ; lineX >= farthestX; lineX -= 0.0001f, lineZ -= 0.0001f)
{
List pointXs = new List();
float temp = lineX;
pointXs.Add(temp);
temp = lineX;
for (int i = 0; i < 10; i++)
{
temp -= 0.0001f;
pointXs.Add(temp);
}
temp = lineX;
for (int i = 0; i < 10; i++)
{
temp += 0.0001f;
pointXs.Add(temp);
}
float pointZ = lineZ;
foreach (float pointX in pointXs)
{
MarioState pointState = new MarioState(
pointX,
startY,
pointZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
0,
0,
0,
marioAngle,
cameraAngle,
null,
null,
0);
Input input = new Input(32, -124);
MarioState movedState = AirMovementCalculator.ApplyInput(pointState, input, 1);
(float dispX, float dispZ) = WallDisplacementCalculator.HandleWallDisplacement(
movedState.X, movedState.Y, movedState.Z, tri, 50, 150);
bool match = dispX == displacedX && dispZ == displacedZ;
if (match)
{
successPositions.Add((pointX, pointZ));
/*
Config.Print(
"({0},{1}) => ({2},{3}) match={4}",
(double)pointX, (double)pointZ, (double)dispX, (double)dispZ, match);
*/
}
numAttempts++;
if (match) numSuccesses++;
}
}
/*
Config.Print("numAttempts = " + numAttempts);
Config.Print("numSuccesses = " + numSuccesses);
*/
successPositions.Sort((a, b) => Math.Sign(a.Item1 - b.Item1));
return successPositions;
}
public static void TestWalkingCode()
{
float startX = -7390.01953125f;
float startY = -3153f;
float startZ = 3936.21435546875f;
float startXSpeed = 7.88103151321411f;
float startYSpeed = 0f;
float startZSpeed = -15.0203580856323f;
float startHSpeed = 16.9623641967773f;
ushort startMarioAngle = 27738;
ushort startCameraAngle = 0;
MarioState marioState = new MarioState(
startX, startY, startZ,
startXSpeed, startYSpeed, startZSpeed, startHSpeed,
0, 0, 0,
startMarioAngle, startCameraAngle, null, null, 0);
Input input = new Input(23, 26);
for (int i = 0; i < 10; i++)
{
Config.Print(i + ": " + marioState);
marioState = GroundMovementCalculator.ApplyInput(marioState, input);
}
}
public static void TestGetRelativePosition()
{
float marioX = -1431.61889648438f;
float marioY = -4003f;
float marioZ = -1318.10009765625f;
ushort marioAngle = 53906;
(float x, float y, float z) = ObjectCalculator.GetRelativePosition(
marioX, marioY, marioZ, marioAngle, 0, 60, 100);
Config.Print("{0},{1},{2}", (double)x, (double)y, (double)z);
}
public static void TestGetObjectDisplacement()
{
float marioX = -1462.44079589844f;
float marioY = -4003f;
float marioZ = -1196.89099121094f;
float marioRadius = 37;
float bobombX = -1538.07922363281f;
float bobombY = -4003f;
float bobombZ = -1257.61840820313f;
float bobombRadius = 65 * 1.2f;
float padding = -5;
(float x, float z) = ObjectCalculator.GetHardObjectDisplacement(
marioX, marioZ, marioRadius, 0, bobombX, bobombZ, bobombRadius, padding);
Config.Print("{0},{1}", (double)x, (double)z);
}
public static void TestCombined()
{
float marioX = -918.42724609375f;
float marioY = -2434f;
float marioZ = -1730.48791503906f;
float marioXSpeed = 1.16657888889313f;
float marioYSpeed = 0f;
float marioZSpeed = 5.46906852722168f;
float marioHSpeed = 5.59210300445557f;
ushort marioAngle = 2206;
ushort cameraAngle = 4132;
float objX = -897.566040039063f;
float objZ = -1632.68811035156f;
int inputX = -14;
int inputY = -48;
MarioState marioState = new MarioState(
marioX, marioY, marioZ,
marioXSpeed, marioYSpeed, marioZSpeed, marioHSpeed,
0, 0, 0,
marioAngle, cameraAngle, null, null, 0);
Input input = new Input(inputX, inputY);
// walking
MarioState afterWalkingTemp = GroundMovementCalculator.ApplyInput(marioState, input);
MarioState afterWalking = afterWalkingTemp.WithPosition(marioState.X, marioState.Y, marioState.Z);
// displacement
(float afterDisplacementX, float afterDisplacementZ) =
ObjectCalculator.GetHardObjectDisplacement(
afterWalking.X, afterWalking.Z, 37, afterWalking.MarioAngle,
objX, objZ, 65 * 1.2f, -5);
// relative position
(float relX, float relY, float relZ) = ObjectCalculator.GetRelativePosition(
afterDisplacementX, afterWalking.Y, afterDisplacementZ,
afterWalking.MarioAngle, 0, 60, 100);
MarioState finalState = new MarioState(
afterDisplacementX, afterWalking.Y, afterDisplacementZ,
afterWalking.XSpeed, afterWalking.YSpeed, afterWalking.ZSpeed, afterWalking.HSpeed,
afterWalking.SlidingSpeedX, afterWalking.SlidingSpeedZ, afterWalking.SlidingAngle,
afterWalking.MarioAngle, cameraAngle, null, null, 0);
Config.Print(finalState);
Config.Print("{0},{1},{2}", (double)relX, (double)relY, (double)relZ);
}
public static void TestMovementTowardsSpot()
{
float startX = -1323.72937011719f;
float startY = -2434f;
float startZ = -1579.7392578125f;
float startXSpeed = 2.64395904541016f;
float startYSpeed = 0f;
float startZSpeed = -11.6073894500732f;
float startHSpeed = 11.9047050476074f;
ushort startAngle = 30442;
List cameraAngles = new List()
{
7997,
8089,
8185,
8276,
8364,
8454,
8546,
8640,
8704,
8983,
9007,
9007,
9007,
9050,
9138,
9225,
9249,
9249,
9249,
9249,
9249,
9249,
9249,
};
int INDEX_START = 0;
float objStartX = -1301.52001953125f;
float objStartZ = -1677.24182128906f;
int inputX = 127;
int inputY = 87;
MarioState marioState = new MarioState(
startX, startY, startZ,
startXSpeed, startYSpeed, startZSpeed, startHSpeed,
0, 0, 0,
startAngle, cameraAngles[INDEX_START], null, null, 0);
MarioBobombState marioBobombState = new MarioBobombState(
marioState, objStartX, objStartZ);
Input input = new Input(inputX, inputY);
MarioBobombState prevMarioBobombState = null;
for (int i = INDEX_START + 1; i < 9; i++)
{
ushort nextCameraAngle = cameraAngles[i];
prevMarioBobombState = marioBobombState;
marioBobombState = ApplyInputToMarioBobombState(marioBobombState, input, nextCameraAngle);
}
Config.Print(marioBobombState);
MarioState m = prevMarioBobombState.MarioState;
(float holpX, float holpY, float holpZ) = HolpCalculator.GetHolpForWalking(58, m.X, m.Y, m.Z, m.MarioAngle);
MarioState m2 = marioBobombState.MarioState;
float marioX = m2.X;
float marioY = m2.Y;
float marioZ = m2.Z;
ushort marioAngle = m2.MarioAngle;
float marioRadius = 37;
float bobombX = holpX;
float bobombY = holpY;
float bobombZ = holpZ;
float padding = -5;
for (int i = 1; i <= 4; i++)
{
if (i == 2)
{
ushort bobombAngle = m.MarioAngle;
float delX = 5 * InGameTrigUtilities.InGameSine(bobombAngle);
float delZ = 5 * InGameTrigUtilities.InGameCosine(bobombAngle);
bobombX += delX;
bobombZ += delZ;
}
float bobombRadius = 65 * (1f + 0.2f * i);
(marioX, marioZ) = ObjectCalculator.GetHardObjectDisplacement(
marioX, marioZ, marioRadius, 0, bobombX, bobombZ, bobombRadius, padding);
Config.Print("{0}: ({1},{2})", i, (double)marioX, (double)marioZ);
}
}
public static bool IsInSortedPositions(
List<(float, float)> positions, (float, float) position)
{
return IsInSortedPositions(positions, position, 0, positions.Count - 1);
}
public static bool IsInSortedPositions(
List<(float, float)> positions, (float, float) position, int startIndex, int endIndex)
{
if (startIndex > endIndex) return false;
int midIndex = (startIndex + endIndex) / 2;
(float midValue1, float midValue2) = positions[midIndex];
if (position.Item1 > midValue1)
{
return IsInSortedPositions(positions, position, midIndex + 1, endIndex);
}
else if (position.Item1 < midValue1)
{
return IsInSortedPositions(positions, position, startIndex, midIndex - 1);
}
else
{
return position.Item2 == midValue2;
}
}
public static float IsInSortedPositions2(
List<(float, float)> positions, (float, float) position)
{
return IsInSortedPositions2(positions, position, 0, positions.Count - 1);
}
public static float IsInSortedPositions2(
List<(float, float)> positions, (float, float) position, int startIndex, int endIndex)
{
if (startIndex > endIndex) return float.MaxValue;
int midIndex = (startIndex + endIndex) / 2;
(float midValue1, float midValue2) = positions[midIndex];
if (position.Item1 > midValue1)
{
return IsInSortedPositions2(positions, position, midIndex + 1, endIndex);
}
else if (position.Item1 < midValue1)
{
return IsInSortedPositions2(positions, position, startIndex, midIndex - 1);
}
else
{
return Math.Abs(position.Item2 - midValue2);
}
}
public static List GetAngleDiffs(int mid, int range, int multiplier = 1)
{
List angleDiffs = new List();
for (int i = -1 * range; i <= range; i++)
{
int angleDiff = mid + i * multiplier * 16;
angleDiffs.Add(angleDiff);
}
return angleDiffs;
}
public static List> GetAngleDiffsList(int length, int mid, int range)
{
List angleDiffs = new List();
for (int i = -1 * range; i <= range; i++)
{
int angleDiff = mid + i * 16;
angleDiffs.Add(angleDiff);
}
List> output = new List>();
GetAngleDiffsListRecursion(output, new List(), length, angleDiffs);
return output;
}
public static void GetAngleDiffsListRecursion(
List> output, List state, int length, List values)
{
if (state.Count == length)
{
List temp = new List(state);
output.Add(temp);
return;
}
foreach (int value in values)
{
state.Add(value);
GetAngleDiffsListRecursion(output, state, length, values);
state.RemoveAt(state.Count - 1);
}
}
public static void TestBruteForceMovingToSpot()
{
Config.Print("START BRUTE FORCE");
List<(float, float)> successPositions = GetSuccessFloatPositions();
bool boolValue = IsInSortedPositions(
successPositions, (-1379.0001f, 0f));
List> angleDiffsList = GetAngleDiffsList(7, 96, 5);
angleDiffsList.ForEach(list => list.Add(0));
// List angleDiffs = new List() { 89, 92, 96, 91, 88, 90, 92, 2048 };
//float minDiff = float.MaxValue;
for (int i = 0; i < angleDiffsList.Count; i++)
{
List angleDiffs = angleDiffsList[i];
(float x, float z) = MoveIntoSpot(angleDiffs);
float diff = IsInSortedPositions2(successPositions, (x, z));
if (diff < 0.0002f)
{
Config.Print("{0}: [{1}] ({2},{3})", i, (double)diff, (double)x, (double)z);
MoveIntoSpot(angleDiffs, true);
Config.Print();
}
}
Config.Print("END BRUTE FORCE");
}
public static (float x, float z) MoveIntoSpot(List angleDiffs, bool print = false)
{
float startX = -1323.72937011719f;
float startY = -2434f;
float startZ = -1579.7392578125f;
float startXSpeed = 2.64395904541016f;
float startYSpeed = 0f;
float startZSpeed = -11.6073894500732f;
float startHSpeed = 11.9047050476074f;
ushort startAngle = 30442;
float objStartX = -1301.52001953125f;
float objStartZ = -1677.24182128906f;
MarioState marioState = new MarioState(
startX, startY, startZ,
startXSpeed, startYSpeed, startZSpeed, startHSpeed,
0, 0, 0,
startAngle, 0, null, null, 0);
MarioBobombState marioBobombState = new MarioBobombState(
marioState, objStartX, objStartZ);
MarioBobombState prevMarioBobombState = null;
for (int i = 0; i < 8; i++)
{
prevMarioBobombState = marioBobombState;
marioBobombState = ApplyInputToMarioBobombState(marioBobombState, angleDiffs[i]);
if (print)
{
//Config.Print((43226 + i) + ": " + marioBobombState);
Config.Print(
"{0} {1} {2} {3} {4}",
(43227 + i),
(double)marioBobombState.MarioState.X,
(double)marioBobombState.MarioState.Y,
(double)marioBobombState.MarioState.Z,
(double)marioBobombState.MarioState.MarioAngle);
}
}
//Config.Print(marioBobombState);
MarioState m = prevMarioBobombState.MarioState;
(float holpX, float holpY, float holpZ) = HolpCalculator.GetHolpForWalking(58, m.X, m.Y, m.Z, m.MarioAngle);
MarioState m2 = marioBobombState.MarioState;
float marioX = m2.X;
float marioY = m2.Y;
float marioZ = m2.Z;
ushort marioAngle = m2.MarioAngle;
float marioRadius = 37;
float bobombX = holpX;
float bobombY = holpY;
float bobombZ = holpZ;
float padding = -5;
for (int i = 1; i <= 4; i++)
{
if (i == 2)
{
ushort bobombAngle = m.MarioAngle;
float delX = 5 * InGameTrigUtilities.InGameSine(bobombAngle);
float delZ = 5 * InGameTrigUtilities.InGameCosine(bobombAngle);
bobombX += delX;
bobombZ += delZ;
}
float bobombRadius = 65 * (1f + 0.2f * i);
(marioX, marioZ) = ObjectCalculator.GetHardObjectDisplacement(
marioX, marioZ, marioRadius, 0, bobombX, bobombZ, bobombRadius, padding);
//Config.Print("{0}: ({1},{2})", i, (double)marioX, (double)marioZ);
if (print)
{
if (i == 1)
{
for (int j = 0; j < 4; j++)
{
Config.Print(
"{0} {1} {2} {3} {4}",
43235 + j,
(double)marioX,
(double)m2.Y,
(double)marioZ,
(double)m2.MarioAngle);
}
}
else
{
Config.Print(
"{0} {1} {2} {3} {4}",
43237 + i,
(double)marioX,
(double)m2.Y,
(double)marioZ,
(double)m2.MarioAngle);
}
}
}
return (marioX, marioZ);
}
public class MarioBobombState
{
public readonly MarioState MarioState;
public readonly float ObjX;
public readonly float ObjZ;
public MarioBobombState(MarioState marioState, float objX, float objZ)
{
MarioState = marioState;
ObjX = objX;
ObjZ = objZ;
}
public override string ToString()
{
return String.Format("{0} obj=({1},{2})", MarioState, (double)ObjX, (double)ObjZ);
}
}
public static MarioBobombState ApplyInputToMarioBobombState(
MarioBobombState initialState, Input input, ushort nextCameraAngle)
{
// get vars
MarioState marioState = initialState.MarioState;
float objX = initialState.ObjX;
float objZ = initialState.ObjZ;
// walking
MarioState afterWalkingTemp = GroundMovementCalculator.ApplyInput(marioState, input);
// doesn't move due to ceiling
MarioState afterWalking = afterWalkingTemp.WithPosition(marioState.X, marioState.Y, marioState.Z);
// displacement
(float afterDisplacementX, float afterDisplacementZ) =
ObjectCalculator.GetHardObjectDisplacement(
afterWalking.X, afterWalking.Z, 37, afterWalking.MarioAngle,
objX, objZ, 65 * 1.2f, -5);
// relative position
(float relX, float relY, float relZ) = ObjectCalculator.GetRelativePosition(
afterDisplacementX, afterWalking.Y, afterDisplacementZ,
afterWalking.MarioAngle, 0, 60, 100);
MarioState finalMarioState = new MarioState(
afterDisplacementX, afterWalking.Y, afterDisplacementZ,
afterWalking.XSpeed, afterWalking.YSpeed, afterWalking.ZSpeed, afterWalking.HSpeed,
afterWalking.SlidingSpeedX, afterWalking.SlidingSpeedZ, afterWalking.SlidingAngle,
afterWalking.MarioAngle, nextCameraAngle, null, null, 0);
MarioBobombState finalMarioBobombState = new MarioBobombState(finalMarioState, relX, relZ);
return finalMarioBobombState;
}
public static MarioBobombState ApplyInputToMarioBobombState(
MarioBobombState initialState, int angleDiff)
{
// get vars
MarioState marioState = initialState.MarioState;
float objX = initialState.ObjX;
float objZ = initialState.ObjZ;
// walking
MarioState afterWalkingTemp = GroundMovementCalculator.ApplyInput(marioState, angleDiff);
// doesn't move due to ceiling
MarioState afterWalking = afterWalkingTemp.WithPosition(marioState.X, marioState.Y, marioState.Z);
// displacement
(float afterDisplacementX, float afterDisplacementZ) =
ObjectCalculator.GetHardObjectDisplacement(
afterWalking.X, afterWalking.Z, 37, afterWalking.MarioAngle,
objX, objZ, 65 * 1.2f, -5);
// relative position
(float relX, float relY, float relZ) = ObjectCalculator.GetRelativePosition(
afterDisplacementX, afterWalking.Y, afterDisplacementZ,
afterWalking.MarioAngle, 0, 60, 100);
MarioState finalMarioState = new MarioState(
afterDisplacementX, afterWalking.Y, afterDisplacementZ,
afterWalking.XSpeed, afterWalking.YSpeed, afterWalking.ZSpeed, afterWalking.HSpeed,
afterWalking.SlidingSpeedX, afterWalking.SlidingSpeedZ, afterWalking.SlidingAngle,
afterWalking.MarioAngle, 0, null, null, 0);
MarioBobombState finalMarioBobombState = new MarioBobombState(finalMarioState, relX, relZ);
return finalMarioBobombState;
}
public static void CalculateTylerChallenge()
{
float startX = 0f;
float startY = 251.947235107422f;
float startZ = -12.3211631774902f;
float startXSpeed = 0f;
float startYSpeed = 7.99412536621094f;
float startZSpeed = 2.85620307922363f;
float startHSpeed = 2.85620307922363f;
ushort marioAngle = 0;
ushort cameraAngle = 32768;
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
0,
0,
0,
marioAngle,
cameraAngle,
null,
null,
0);
int lastIndex = -1;
List inputs = CalculatorUtilities.GetInputRange(0, 0, -65, 65);
float bestDiff = 1;
Queue queue = new Queue();
HashSet alreadySeen = new HashSet();
queue.Enqueue(startState);
while (queue.Count != 0)
{
MarioState dequeue = queue.Dequeue();
List nextStates = inputs.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input));
foreach (MarioState state in nextStates)
{
if (alreadySeen.Contains(state)) continue;
if (state.Index != lastIndex)
{
if (state.Index == 5) return;
lastIndex = state.Index;
Config.Print("Now at index " + lastIndex);
}
float diff = (float)MoreMath.GetDistanceBetween(state.X, state.Z, 0, 0);
if (diff < bestDiff)
{
bestDiff = diff;
Config.Print("New best diff of " + diff);
Config.Print(state.GetLineage());
Config.Print();
}
alreadySeen.Add(state);
queue.Enqueue(state);
}
}
Config.Print("FAILED");
}
public static void TestButtSlide()
{
float startX = 3182.2568359375f;
float startY = 2087.14599609375f;
float startZ = -1143.09411621094f;
float startXSpeed = -4.60398626327515f;
float startYSpeed = 0f;
float startZSpeed = 16.3799514770508f;
float startHSpeed = 17.014684677124f;
float startXSlidingSpeed = -4.60398626327515f;
float startZSlidingSpeed = 16.3799514770508f;
ushort startYawMoving = 62676;
ushort startYawFacing = 62676;
ushort startCentAngle = 19725;
float goalY = 2322.00244140625f;
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
startXSlidingSpeed,
startZSlidingSpeed,
startYawMoving,
startYawFacing,
startCentAngle,
null,
null,
0);
startState = MarioState.CreateMarioState();
Input input = new Input(0, 0);
TriangleDataModel floor = TriangleDataModel.CreateLazy(0x80198DA0);
TriangleDataModel wall = TriangleDataModel.CreateLazy(0x801962E0);
List walls = new List() { wall };
/////////////////////////////////
int indexRadius = 10;
int spreadMultiplier = 20;
/////////////////////////////////
List angleDiffs = Enumerable.Range(0, 2 * indexRadius + 1).ToList().ConvertAll(
index => spreadMultiplier * 16 * (index - indexRadius));
Queue queue = new Queue();
queue.Enqueue(startState);
float bestMin = float.MaxValue;
int currentIndex = 0;
while (queue.Count > 0)
{
MarioState dequeue = queue.Dequeue();
if (dequeue.Index != currentIndex)
{
currentIndex = dequeue.Index;
Config.Print("now at index " + currentIndex);
}
List heights = GetPossibleHeights(dequeue.Y, dequeue.HSpeed);
float min = heights.Min(height => Math.Abs(height - goalY));
if (min < bestMin)
{
bestMin = min;
Config.Print("new best min of " + min + " using " + dequeue.GetLineage());
}
if (dequeue.Index >= 4) continue;
List successors = angleDiffs.ConvertAll(
angleDiff => GroundMovementCalculator.PerformButtSlide(dequeue, angleDiff, floor, walls));
successors.ForEach(successor => queue.Enqueue(successor));
}
Config.Print("DONE");
}
private static List GetPossibleHeights(float initialY, float hSpeed)
{
float initialYSpeed = 42 + hSpeed / 4;
List heights = new List();
for (int numAHeldFrames = 1; numAHeldFrames < 20; numAHeldFrames++)
{
float y = initialY;
float ySpeed = initialYSpeed;
for (int frame = 0; y >= initialY; frame++)
{
y += ySpeed / 4;
if (ySpeed < 0) heights.Add(y);
y += ySpeed / 4;
if (ySpeed < 0) heights.Add(y);
y += ySpeed / 4;
if (ySpeed < 0) heights.Add(y);
y += ySpeed / 4;
if (ySpeed < 0) heights.Add(y);
if (frame >= numAHeldFrames && ySpeed > 20) // fast gravity
{
ySpeed /= 4;
}
else // slow gravity
{
ySpeed -= 4;
if (ySpeed < -75) ySpeed = -75;
}
}
}
return heights;
}
public static void CalculateMovementForCcmWallGap()
{
float startX = 3122f;
float startY = 2294.47412109375f;
float startZ = -904.069885253906f;
float startXSpeed = -5.59027242660522f;
float startYSpeed = 25.04638671875f;
float startZSpeed = 10.3451957702637f;
float startHSpeed = 11.6010656356812f;
float startXSlidingSpeed = -5.59027242660522f;
float startZSlidingSpeed = 10.3451957702637f;
ushort startYawMoving = 62083;
ushort startYawFacing = 62083;
ushort startCentAngle = 20073;
Dictionary cameraAngles =
new Dictionary()
{
[0] = 20073,
[1] = 20081,
[2] = 20097,
[3] = 20102,
[4] = 20115,
[5] = 20128,
[6] = 20140,
};
float goalX = 3122;
float goalY = 2322.00244140625f;
float goalZ = -854.901306152344f;
int xInput = -19;
int zInput = 18;
int xRadius = 5;
int zRadius = 5;
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
startXSlidingSpeed,
startZSlidingSpeed,
startYawMoving,
startYawFacing,
startCentAngle,
null,
null,
0);
int lastIndex = -1;
List inputs = CalculatorUtilities.GetInputRange(xInput - xRadius, xInput + xRadius, zInput - zRadius, zInput + zRadius);
float bestDiff = float.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
queue.Enqueue(startState);
while (queue.Count > 0)
{
MarioState dequeue = queue.Dequeue();
int numQSteps = dequeue.Index == 4 ? 3 : 4;
List nextStates = inputs.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input, numQSteps));
nextStates = nextStates.ConvertAll(state => state.WithCameraAngle(cameraAngles[state.Index]));
foreach (MarioState state in nextStates)
{
if (state.Index > 5) continue;
if (state.Index != lastIndex)
{
lastIndex = state.Index;
Config.Print("Now at index " + lastIndex);
}
if (state.Index == 5)
{
float diff = (float)MoreMath.GetDistanceBetween(state.X, state.Z, goalX, goalZ);
if (diff < bestDiff)
{
bestDiff = diff;
bestState = state;
Config.Print("Diff of " + bestDiff + " is: " + bestState.GetLineage());
}
}
queue.Enqueue(state);
}
}
Config.Print("DONE");
}
public static void CalculateMovementForBobombSoftlock()
{
float startX = -5867.13623046875f;
float startY = 380.164794921875f;
float startZ = 5501.29931640625f;
float startXSpeed = 0.593941569328308f;
float startYSpeed = -1.07592010498047f;
float startZSpeed = 3.81162405014038f;
float startHSpeed = 3.17501330375671f;
float startXSlidingSpeed = 0.593941569328308f;
float startZSlidingSpeed = 3.81162405014038f;
ushort startYawMoving = 60856;
ushort startYawFacing = 60856;
ushort startCentAngle = 47052;
Dictionary cameraAngles =
new Dictionary()
{
[0] = 47052,
[1] = 47052,
[2] = 47052,
[3] = 47052,
[4] = 47072,
[5] = 47072,
[6] = 47072,
[7] = 47072,
[8] = 47072,
[9] = 47072,
[10] = 47072,
};
float goalX = -5857.476563f;
float goalY = 128f;
float goalZ = 5512.975098f;
int xInput = -16;
int zInput = 45;
int xRadius = 3;
int zRadius = 3;
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
startXSlidingSpeed,
startZSlidingSpeed,
startYawMoving,
startYawFacing,
startCentAngle,
null,
null,
0);
int lastIndex = -1;
List inputs = CalculatorUtilities.GetInputRange(xInput - xRadius, xInput + xRadius, zInput - zRadius, zInput + zRadius);
float bestDiff = float.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
queue.Enqueue(startState);
while (queue.Count > 0)
{
MarioState dequeue = queue.Dequeue();
if (dequeue.Index != lastIndex)
{
lastIndex = dequeue.Index;
Config.Print("Now at index " + lastIndex);
}
if (dequeue.Index == 4)
{
MarioState state5 = AirMovementCalculator.ApplyInput(dequeue, new Input(0, 0));
MarioState state6 = AirMovementCalculator.ApplyInput(state5, new Input(0, 0));
MarioState state7 = AirMovementCalculator.ApplyInput(state6, new Input(0, 0));
MarioState state8 = AirMovementCalculator.ApplyInput(state7, new Input(0, 0));
MarioState state9 = AirMovementCalculator.ApplyInput(state8, new Input(0, 0));
MarioState state10 = AirMovementCalculator.ApplyInput(state9, new Input(0, 0));
MarioState state11 = AirMovementCalculator.ApplyInput(state10, new Input(0, 0));
if (state11.HSpeed != 0) continue;
float diff = (float)MoreMath.GetDistanceBetween(state11.X, state11.Z, goalX, goalZ);
if (diff < bestDiff)
{
bestDiff = diff;
bestState = state11;
Config.Print("Diff of " + bestDiff + " is: " + bestState.GetLineage());
}
continue;
}
List nextStates = inputs.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input));
nextStates = nextStates.ConvertAll(state => state.WithCameraAngle(cameraAngles[state.Index]));
nextStates = ControlUtilities.Randomize(nextStates);
nextStates.ForEach(state => queue.Enqueue(state));
}
Config.Print("DONE");
}
public static void CalculateMovementForBobombSoftlockGoomba()
{
float startX = -5504.3388671875f;
float startY = 368.588073730469f;
float startZ = 5443.33837890625f;
float startXSpeed = 1.67060232162476f;
float startYSpeed = -18.9632110595703f;
float startZSpeed = 15.7245416641235f;
float startHSpeed = 15.8130369186401f;
float startXSlidingSpeed = 1.67060232162476f;
float startZSlidingSpeed = 15.7245416641235f;
ushort startYawMoving = 1106;
ushort startYawFacing = 1106;
ushort startCentAngle = 1106;
Dictionary cameraAngles =
new Dictionary()
{
[0] = 1106,
[1] = 1106,
[2] = 1106,
[3] = 1106,
[4] = 1106,
[5] = 1106,
};
float goalX = -5496.86669921875f;
float goalY = 268.735046386719f;
float goalZ = 5506.06005859375f;
int xInput = 0;
int zInput = -38;
int xRadius = 9;
int zRadius = 4;
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
startXSlidingSpeed,
startZSlidingSpeed,
startYawMoving,
startYawFacing,
startCentAngle,
null,
null,
0);
int lastIndex = -1;
List inputs = CalculatorUtilities.GetInputRange(xInput - xRadius, xInput + xRadius, zInput - zRadius, zInput + zRadius);
float bestDiff = float.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
queue.Enqueue(startState);
while (queue.Count > 0)
{
MarioState dequeue = queue.Dequeue();
if (dequeue.Index != lastIndex)
{
lastIndex = dequeue.Index;
Config.Print("Now at index " + lastIndex);
}
if (dequeue.Index == 4)
{
float diff = Math.Abs(dequeue.Z - goalZ);
if (diff <= bestDiff)
{
bestDiff = diff;
bestState = dequeue;
Config.Print("Diff of " + bestDiff + " is: " + bestState.GetLineage());
}
continue;
}
List nextStates = inputs.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input));
nextStates = nextStates.ConvertAll(state => state.WithCameraAngle(cameraAngles[state.Index]));
nextStates = ControlUtilities.Randomize(nextStates);
nextStates.ForEach(state => queue.Enqueue(state));
}
Config.Print("DONE");
}
public static void CalculateMovementForLLLPoleSoftlock()
{
float startX = 1280.70056152344f;
float startY = 4464.54296875f;
float startZ = -2482.5f;
float startXSpeed = 13.7614297866821f;
float startYSpeed = 14f;
float startZSpeed = -15.9914541244507f;
float startHSpeed = 18.5792484283447f;
float startXSlidingSpeed = 13.7614297866821f;
float startZSlidingSpeed = -15.9914541244507f;
ushort startYawMoving = 59938;
ushort startYawFacing = 20218;
ushort startCentAngle = 59680;
float poleX = 1413f;
float poleY = 3222f;
float poleZ = -2190f;
uint wallAddress = 0x8019AB30;
List walls = new List() { TriangleDataModel.CreateLazy(wallAddress) };
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
startXSlidingSpeed,
startZSlidingSpeed,
startYawMoving,
startYawFacing,
startCentAngle,
null,
null,
0);
int lastIndex = -1;
List angleDiffs = GetAngleDiffs(14500, 14, 3);
//List angleDiffs = GetAngleDiffs((int)SpecialConfig.CustomX, 0);
float bestDiff = float.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
queue.Enqueue(startState);
List<(float x, float y, float z)> endingPositions = new List<(float x, float y, float z)>();
while (queue.Count > 0)
{
MarioState dequeue = queue.Dequeue();
if (dequeue.Index != lastIndex)
{
lastIndex = dequeue.Index;
Config.Print("Now at index " + lastIndex);
}
if (dequeue.Index == 4)
{
dequeue = dequeue.WithDive();
}
if (dequeue.Index == 5)
{
(double sidewaysDist, double forwardsDist) =
MoreMath.GetSidewaysAndForwardsDist(poleX, poleZ, dequeue.X, dequeue.Z, 34384);
float goalSideways = -0.0041583f;
//float diff = (float)Math.Abs(sidewaysDist - goalSideways);
float diff = (float)MoreMath.GetDistanceBetween(dequeue.X, dequeue.Z, 1355.78442382813, -2556.30688476563);
//float threshold = 0.002f;
float threshold = bestDiff;
if (diff <= threshold && !endingPositions.Contains((dequeue.X, dequeue.Y, dequeue.Z)))
{
endingPositions.Add((dequeue.X, dequeue.Y, dequeue.Z));
bestDiff = diff;
bestState = dequeue;
Config.Print("Diff of " + bestDiff + " is: " + bestState.GetLineage());
//Config.Print("{0},{1},{2}", (double)dequeue.X, (double)dequeue.Y, (double)dequeue.Z);
}
continue;
}
List nextStates = angleDiffs.ConvertAll(
angleDiff => AirMovementCalculator.ApplyInput(dequeue, angleDiff, wallTris: walls));
nextStates = ControlUtilities.Randomize(nextStates);
nextStates.ForEach(state => queue.Enqueue(state));
}
Config.Print("DONE");
}
public static void CalculateMovementForCCMPenguinSoftlock()
{
float startX = 3170.953125f;
float startY = -4382f;
float startZ = -370.703369140625f;
float startXSpeed = 1.92227721214294f;
float startYSpeed = -42f;
float startZSpeed = 8.9207706451416f;
float startHSpeed = -0.620457470417023f;
float startXSlidingSpeed = 1.92227721214294f;
float startZSlidingSpeed = 8.9207706451416f;
ushort startYawMoving = 33417;
ushort startYawFacing = 50668;
ushort startCentAngle = 28319;
float penguinX = 3211.611328125f;
float penguinY = -4806.134765625f;
float penguinZ = -460.21923828125f;
uint wallAddress1 = 0x8019B470;
uint wallAddress2 = 0x8019B2F0;
List walls =
new List()
{
TriangleDataModel.CreateLazy(wallAddress1),
TriangleDataModel.CreateLazy(wallAddress2),
};
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
startXSlidingSpeed,
startZSlidingSpeed,
startYawMoving,
startYawFacing,
startCentAngle,
null,
null,
0);
int lastIndex = -1;
List angleDiffs = GetAngleDiffs(-2800, 5, 3);
//List angleDiffs = GetAngleDiffs((int)SpecialConfig.CustomX, 0);
float bestDiff = float.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
queue.Enqueue(startState);
List<(float x, float y, float z)> endingPositions = new List<(float x, float y, float z)>();
while (queue.Count > 0)
{
MarioState dequeue = queue.Dequeue();
if (dequeue.Index != lastIndex)
{
lastIndex = dequeue.Index;
Config.Print("Now at index " + lastIndex);
}
if (dequeue.Index == 4)
{
dequeue = dequeue.WithDive();
}
if (dequeue.Index == 6)
{
float xDistToMario = -1 * (dequeue.X - penguinX);
float zDistToMario = dequeue.Z - penguinZ;
float diff = Math.Abs(xDistToMario - zDistToMario);
//float threshold = 0.002f;
float threshold = bestDiff;
if (diff <= threshold && !endingPositions.Contains((dequeue.X, dequeue.Y, dequeue.Z)))
{
endingPositions.Add((dequeue.X, dequeue.Y, dequeue.Z));
bestDiff = diff;
bestState = dequeue;
Config.Print("Diff of " + bestDiff + " is: " + bestState.GetLineage());
//Config.Print("{0},{1},{2}", (double)dequeue.X, (double)dequeue.Y, (double)dequeue.Z);
}
continue;
}
List nextStates = angleDiffs.ConvertAll(
angleDiff => AirMovementCalculator.ApplyInput(dequeue, angleDiff, wallTris: walls));
nextStates = ControlUtilities.Randomize(nextStates);
nextStates.ForEach(state => queue.Enqueue(state));
}
Config.Print("DONE");
}
public static void TestBobomb()
{
BobombState bobomb = new BobombState(
x: -1900,
y: 0,
z: 3450,
xSpeed: 0,
ySpeed: 0,
zSpeed: 0,
hSpeed: 0,
yaw: 0,
homeX: -1900,
homeY: 0,
homeZ: 3450);
for (int i = 0; i < 1000; i++)
{
Config.Print("i={0} bobomb={1}", i, bobomb);
bobomb.bobomb_act_patrol();
}
}
public static void TestBobomb3()
{
//// x=-1900 z=3450 yaw=23040 lastChangeTime=7069 mins=3 bestMins=3
//BobombState bobomb = new BobombState(
// x: -1900,
// y: 0,
// z: 3450,
// xSpeed: 0,
// ySpeed: 0,
// zSpeed: 0,
// hSpeed: 0,
// yaw: 9216,
// homeX: -1900,
// homeY: 0,
// homeZ: 3450);
//for (int i = 0; i < 10000; i++)
//{
// Config.Print("{0}: {1}", i, bobomb);
// bobomb.bobomb_act_patrol();
//}
BobombState bobomb2 = new BobombState(
x: -1900,
y: 0,
z: 3450,
xSpeed: 0,
ySpeed: 0,
zSpeed: 0,
hSpeed: 0,
yaw: 9216,
homeX: -1900,
homeY: 0,
homeZ: 3450);
int lastChangeTime = GetLastAngleChangeTime(bobomb2, 10000);
Config.Print("lastChangeTime=" + lastChangeTime);
}
public static void TestBobomb2()
{
List superlatives = new List();
int bestMins = 0;
for (int xDiff = 0; xDiff < 100; xDiff += 20)
{
for (int zDiff = 0; zDiff < 100; zDiff += 20)
{
for (int yaw = 0; yaw < 65536; yaw += 512)
{
float x = -1900 + xDiff;
float z = 3450 + zDiff;
BobombState bobomb = new BobombState(
x: x,
y: 0,
z: z,
xSpeed: 0,
ySpeed: 0,
zSpeed: 0,
hSpeed: 0,
yaw: (ushort)yaw,
homeX: x,
homeY: 0,
homeZ: z);
int lastChangeTime = GetLastAngleChangeTime(bobomb, 10000);
int mins = lastChangeTime / 30 / 60;
if (mins > bestMins)
{
bestMins = mins;
}
string output = string.Format(
"x={0} z={1} yaw={2} lastChangeTime={3} mins={4} bestMins={5}",
x, z, yaw, lastChangeTime, mins, bestMins);
Config.Print(output);
if (mins > 10)
{
superlatives.Add(output);
}
}
}
}
Config.Print("SUPERLATIVES START");
superlatives.ForEach(output => Config.Print(output));
Config.Print("SUPERLATIVES END");
}
public static int GetLastAngleChangeTime(BobombState bobomb, int numIterations)
{
List previousAngles = new List();
int lastAngleChangeTime = 0;
int lastTimer = 0;
for (int i = 0; i < numIterations; i++)
{
ushort angle = GetAngleToFarPoint(bobomb);
bool alreadyHaveIt = previousAngles.Any(prevAngle => MoreMath.GetAngleDistance(angle, prevAngle) < 5000);
//Config.Print(
// "Does {0} contain anything close to {1}? {2}",
// previousAngles.Count == 0 ? "{}" : "{" + string.Join(",", previousAngles) + "}",
// angle,
// alreadyHaveIt);
if (!alreadyHaveIt)
{
previousAngles.Add(angle);
lastAngleChangeTime = i;
lastTimer = bobomb.Timer;
}
}
return lastTimer;
}
public static ushort GetAngleToFarPoint(BobombState bobomb)
{
List<(float x, float y, float z, double dist)> dists = new List<(float x, float y, float z, double dist)>();
while (true)
{
bobomb.bobomb_act_patrol();
//Config.Print("bobomb = " + bobomb);
double dist = MoreMath.GetDistanceBetween(bobomb.HomeX, bobomb.HomeZ, bobomb.X, bobomb.Z);
dists.Add((bobomb.X, bobomb.Y, bobomb.Z, dist));
if (dists.Count >= 4) dists.RemoveAt(0);
if (dists.Count == 3)
{
double dist1 = dists[0].dist;
double dist2 = dists[1].dist;
double dist3 = dists[2].dist;
if (dist2 > dist1 && dist2 > dist3 && dist2 > 200)
{
return MoreMath.AngleTo_AngleUnitsRounded(
bobomb.HomeX, bobomb.HomeZ, dists[1].x, dists[1].z);
}
}
}
}
public static void TestX()
{
float startX = -2474.70849609375f;
float startY = -1909.26416015625f;
float startZ = 3520.89599609375f;
float startXSpeed = 9.54115295410156f;
float startYSpeed = 2.07013988494873f;
float startZSpeed = 0f;
float startHSpeed = 9.54115295410156f;
float startXSlidingSpeed = 9.54115295410156f;
float startZSlidingSpeed = 0f;
ushort startYawMoving = 16384;
ushort startYawFacing = 16384;
ushort startCentAngle = 49152;
float goalX = -2436.54248046875f;
float goalZ = 4730.4560546875f;
int xInput = 0;
int zInput = 25;
int xRadius = 0;
int zRadius = 15;
List inputs = CalculatorUtilities.GetInputRange(xInput - xRadius, xInput + xRadius, zInput - zRadius, zInput + zRadius);
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
startXSlidingSpeed,
startZSlidingSpeed,
startYawMoving,
startYawFacing,
startCentAngle,
null,
null,
0);
int counter = 0;
int lastIndex = -1;
float bestDiff = float.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
queue.Enqueue(startState);
while (queue.Count > 0)
{
MarioState dequeue = queue.Dequeue();
if (dequeue.Index != lastIndex)
{
lastIndex = dequeue.Index;
Config.Print("Now at index " + lastIndex);
}
if (dequeue.Index == 4)
{
counter++;
float diff = Math.Abs(dequeue.X - goalX);
if (diff <= bestDiff)
{
bestDiff = diff;
bestState = dequeue;
Config.Print("Diff of " + bestDiff + " is: " + bestState.GetLineage());
}
continue;
}
List nextStates = inputs.ConvertAll(
input => AirMovementCalculator.ApplyInput(dequeue, input));
nextStates = ControlUtilities.Randomize(nextStates);
nextStates.ForEach(state => queue.Enqueue(state));
}
Config.Print("DONE having considered " + counter + " paths");
}
public static void TestZ()
{
float startX = -2436.54248046875f;
float startY = -1835.79418945313f;
float startZ = 4651.9716796875f;
float startXSpeed = 0f;
float startYSpeed = 18.0824966430664f;
float startZSpeed = 18.9386978149414f;
float startHSpeed = 18.9386978149414f;
float startXSlidingSpeed = 0f;
float startZSlidingSpeed = 18.9386978149414f;
ushort startYawMoving = 0;
ushort startYawFacing = 0;
ushort startCentAngle = 32768;
float goalX = -2436.54248046875f;
float goalZ = 4730.4560546875f;
int xInput = 0;
int zInput = 42;
int xRadius = 0;
int zRadius = 15;
List inputs = CalculatorUtilities.GetInputRange(xInput - xRadius, xInput + xRadius, zInput - zRadius, zInput + zRadius);
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
startXSlidingSpeed,
startZSlidingSpeed,
startYawMoving,
startYawFacing,
startCentAngle,
null,
null,
0);
int counter = 0;
int lastIndex = -1;
float bestDiff = float.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
queue.Enqueue(startState);
while (queue.Count > 0)
{
MarioState dequeue = queue.Dequeue();
if (dequeue.Index != lastIndex)
{
lastIndex = dequeue.Index;
Config.Print("Now at index " + lastIndex);
}
if (dequeue.Index == 4)
{
counter++;
float diff = Math.Abs(dequeue.Z - goalZ);
if (diff <= bestDiff)
{
bestDiff = diff;
bestState = dequeue;
Config.Print("Diff of " + bestDiff + " is: " + bestState.GetLineage());
}
continue;
}
List nextStates = inputs.ConvertAll(
input => AirMovementCalculator.ApplyInput(dequeue, input));
nextStates = ControlUtilities.Randomize(nextStates);
nextStates.ForEach(state => queue.Enqueue(state));
}
Config.Print("DONE having considered " + counter + " paths");
}
public static void TestBitfsPosition1()
{
float startX = -2320.41186523438f;
float startY = -2845.64770507813f;
float startZ = -715f;
float startXSpeed = 22.2516231536865f;
float startYSpeed = -22f;
float startZSpeed = 0f;
float startHSpeed = 22.2516231536865f;
float startXSlidingSpeed = 22.2516231536865f;
float startZSlidingSpeed = 0f;
ushort startYawMoving = 16384;
ushort startYawFacing = 16384;
ushort startCentAngle = 49152;
float goalX = -2250.10009765625f;
float goalZ = -715f;
int xInput = 0;
int zInput = 40;
int xRadius = 0;
int zRadius = 25;
List inputs = CalculatorUtilities.GetInputRange(xInput - xRadius, xInput + xRadius, -20, 75);
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
startXSlidingSpeed,
startZSlidingSpeed,
startYawMoving,
startYawFacing,
startCentAngle,
null,
null,
0);
int counter = 0;
int lastIndex = -1;
double bestDiff = double.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
queue.Enqueue(startState);
while (queue.Count > 0)
{
MarioState dequeue = queue.Dequeue();
if (dequeue.Index != lastIndex)
{
lastIndex = dequeue.Index;
Config.Print("Now at index " + lastIndex);
}
if (dequeue.Index == 4)
{
counter++;
double diff = Math.Abs(dequeue.X - goalX);
if (diff < bestDiff)
{
bestDiff = diff;
bestState = dequeue;
Config.Print("Diff of " + bestDiff + " is: " + bestState.GetLineage());
}
continue;
}
int numQSteps = dequeue.Index == 3 ? 1 : 4;
List nextStates = inputs.ConvertAll(
input => AirMovementCalculator.ApplyInput(dequeue, input, numQSteps: numQSteps));
nextStates = ControlUtilities.Randomize(nextStates);
nextStates.ForEach(state => queue.Enqueue(state));
}
Config.Print("DONE having considered " + counter + " paths");
}
public static void TestTtcTreadmillPosition()
{
float startX = 2031f;
float startY = -2523.00024414063f;
float startZ = -444.763092041016f;
float startXSpeed = 0f;
float startYSpeed = -24f;
float startZSpeed = 0f;
float startHSpeed = 0f;
float startXSlidingSpeed = 0f;
float startZSlidingSpeed = 0f;
ushort startYawMoving = 16403;
ushort startYawFacing = 16403;
ushort startCentAngle = 53619;
ushort centAngle2 = 53629;
float goalX = 2031f;
float goalY = -2554.00024414063f;
float goalZ = -439.64697265625f;
List inputs1 = CalculatorUtilities.GetInputRange(0, 70, -70, 70);
List inputs2 = CalculatorUtilities.GetInputRange(0, 127, -70, 70);
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
startXSlidingSpeed,
startZSlidingSpeed,
startYawMoving,
startYawFacing,
startCentAngle,
null,
null,
0);
int counter = 0;
int lastIndex = -1;
double bestDiff = double.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
queue.Enqueue(startState);
while (queue.Count > 0)
{
MarioState dequeue = queue.Dequeue();
if (dequeue.Index != lastIndex)
{
lastIndex = dequeue.Index;
Config.Print("Now at index " + lastIndex);
}
if (dequeue.Index == 1)
{
double diff = Math.Abs(dequeue.Z - goalZ);
if (diff > 3) continue;
if (dequeue.Z > -441) continue;
}
if (dequeue.Index == 2)
{
counter++;
double diff = Math.Abs(dequeue.Z - goalZ);
if (diff == 0 && dequeue.X >= 2031 && dequeue.XSpeed > 0)
{
bestDiff = diff;
bestState = dequeue;
Config.Print("Diff of " + bestDiff + " is: " + bestState.GetLineage());
Config.Print();
}
continue;
}
List nextStates;
if (dequeue.Index == 0)
{
nextStates = inputs1.ConvertAll(
input => AirMovementCalculator.ApplyInput(dequeue, input, numQSteps: 4));
nextStates = nextStates.ConvertAll(state => state.WithCameraAngle(centAngle2));
}
else // dequeue.Index == 1
{
nextStates = inputs2.ConvertAll(
input => AirMovementCalculator.ApplyInput(dequeue, input, numQSteps: 1));
}
nextStates = ControlUtilities.Randomize(nextStates);
nextStates.ForEach(state => queue.Enqueue(state));
}
Config.Print("DONE having considered " + counter + " paths");
}
public static void TestPendulumLanding()
{
float startX = -1640.13903808594f;
float startY = 568.999877929688f;
float startZ = -804.69677734375f;
float startXSpeed = -23.9479904174805f;
float startYSpeed = -38f;
float startZSpeed = -9.76013565063477f;
float startHSpeed = 23.850606918335f;
float startXSlidingSpeed = -23.9479904174805f;
float startZSlidingSpeed = -9.76013565063477f;
ushort startYawMoving = 40982;
ushort startYawFacing = 40982;
ushort startCentAngle = 15763;
ushort centAngle2 = 15703;
ushort centAngle3 = 15571;
TriangleDataModel tri = TriangleDataModel.CreateCustom(-1747, 426, -781, -1342, 764, -1187, -1370, 764, -1214);
int goalX = -1719;
float goalZ = -869.552673339844f;
int radius = 5;
List inputs1 = CalculatorUtilities.GetInputRange(-128, -128 + 2 * radius, 109 - radius, 109 + radius);
List inputs2 = CalculatorUtilities.GetInputRange(-47 - radius, -47 + radius, -52 - radius, -52 + radius);
List inputs3 = CalculatorUtilities.GetInputRange(-47 - radius, -47 + radius, -52 - radius, -52 + radius);
MarioState startState = new MarioState(
startX,
startY,
startZ,
startXSpeed,
startYSpeed,
startZSpeed,
startHSpeed,
startXSlidingSpeed,
startZSlidingSpeed,
startYawMoving,
startYawFacing,
startCentAngle,
null,
null,
0);
int counter = 0;
int lastIndex = -1;
double bestDiff = double.MaxValue;
MarioState bestState = null;
Queue queue = new Queue();
queue.Enqueue(startState);
while (queue.Count > 0)
{
MarioState dequeue = queue.Dequeue();
if (dequeue.Index != lastIndex)
{
lastIndex = dequeue.Index;
Config.Print("Now at index " + lastIndex);
}
if (dequeue.Index == 3)
{
counter++;
float? y = tri.GetTruncatedHeightOnTriangleIfInsideTriangle(dequeue.X, dequeue.Z);
if (!y.HasValue) continue;
MarioState afterPunch = DoPunchFrames(dequeue);
double zDiff = Math.Abs(afterPunch.Z - goalZ);
int xDiff = (int)afterPunch.X - goalX;
if (zDiff == 0 && xDiff == 0)
{
bestDiff = zDiff;
bestState = dequeue;
Config.Print("Diff of " + bestDiff + " is: " + bestState.GetLineage());
Config.Print();
}
continue;
}
List nextStates = null;
if (dequeue.Index == 0)
{
nextStates = inputs1.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input, numQSteps: 4));
nextStates = nextStates.ConvertAll(state => state.WithCameraAngle(centAngle2));
}
if (dequeue.Index == 1)
{
nextStates = inputs2.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input, numQSteps: 4));
nextStates = nextStates.ConvertAll(state => state.WithCameraAngle(centAngle3));
}
if (dequeue.Index == 2)
{
nextStates = inputs3.ConvertAll(input => AirMovementCalculator.ApplyInput(dequeue, input, numQSteps: 3));
}
nextStates.ForEach(state => queue.Enqueue(state));
}
Config.Print("DONE having considered " + counter + " paths");
}
public static MarioState DoPunchFrames(MarioState marioState)
{
TriangleDataModel tri1 = TriangleDataModel.CreateCustom(-1739, 405, -790, -1370, 764, -1214, -1766, 405, -818);
TriangleDataModel tri2 = TriangleDataModel.CreateCustom(-1729, 383, -800, -1371, 763, -1213, -1756, 383, -828);
TriangleDataModel tri3 = TriangleDataModel.CreateCustom(-1717, 358, -812, -1371, 763, -1213, -1744, 358, -839);
TriangleDataModel tri4 = TriangleDataModel.CreateCustom(-1652, 235, -810, -1746, 235, -904, -1753, 312, -898);
MutableMarioState mutableMarioState = marioState.GetMutableMarioState(new Input(0, 0));
apply_slope_decel(mutableMarioState, 0.5f, tri1);
for (int i = 0; i < 4; i++)
{
mutableMarioState.X += tri1.NormY * (mutableMarioState.XSpeed / 4.0f);
mutableMarioState.Z += tri1.NormY * (mutableMarioState.ZSpeed / 4.0f);
}
apply_slope_decel(mutableMarioState, 0.5f, tri2);
for (int i = 0; i < 4; i++)
{
mutableMarioState.X += tri2.NormY * (mutableMarioState.XSpeed / 4.0f);
mutableMarioState.Z += tri2.NormY * (mutableMarioState.ZSpeed / 4.0f);
}
apply_slope_decel(mutableMarioState, 0.5f, tri3);
for (int i = 0; i < 2; i++)
{
mutableMarioState.X += tri3.NormY * (mutableMarioState.XSpeed / 4.0f);
mutableMarioState.Z += tri3.NormY * (mutableMarioState.ZSpeed / 4.0f);
}
for (int i = 0; i < 2; i++)
{
mutableMarioState.X += tri4.NormY * (mutableMarioState.XSpeed / 4.0f);
mutableMarioState.Z += tri4.NormY * (mutableMarioState.ZSpeed / 4.0f);
}
return mutableMarioState.GetMarioState(marioState.PreviousState, marioState.LastInput);
}
public static void apply_slope_decel(MutableMarioState marioState, float decelCoef, TriangleDataModel floor)
{
float decel = decelCoef * 2.0f;
marioState.HSpeed = CalculatorUtilities.ApproachFloat(marioState.HSpeed, 0.0f, decel, decel);
apply_slope_accel(marioState, floor);
}
public static void apply_slope_accel(MutableMarioState marioState, TriangleDataModel floor) {
float steepness = (float)Math.Sqrt(floor.NormX * floor.NormX + floor.NormZ * floor.NormZ);
int floorAngle = InGameTrigUtilities.InGameATan(floor.NormZ, floor.NormX);
short floorDYaw = MoreMath.NormalizeAngleShort(floorAngle - marioState.MarioAngle);
if (mario_floor_is_slope(floor)) {
float slopeAccel = 1.7f;
if (floorDYaw > -0x4000 && floorDYaw< 0x4000) {
marioState.HSpeed += slopeAccel* steepness;
} else {
marioState.HSpeed -= slopeAccel* steepness;
}
}
marioState.SlidingAngle = marioState.MarioAngle;
marioState.SlidingSpeedX = marioState.HSpeed * InGameTrigUtilities.InGameSine(marioState.MarioAngle);
marioState.SlidingSpeedZ = marioState.HSpeed * InGameTrigUtilities.InGameCosine(marioState.MarioAngle);
marioState.XSpeed = marioState.SlidingSpeedX;
marioState.YSpeed = 0.0f;
marioState.ZSpeed = marioState.SlidingSpeedZ;
}
public static bool mario_floor_is_slope(TriangleDataModel tri) {
float normY = 0.9659258f;
return tri.NormY <= normY;
}
}
}
================================================
FILE: STROOP/Calculators/CalculatorUtilities.cs
================================================
using STROOP.Forms;
using STROOP.Managers;
using STROOP.Structs.Configurations;
using STROOP.Utilities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STROOP.Structs
{
public static class CalculatorUtilities
{
public static List GetAllInputs()
{
return GetInputRange(-128, 127, -128, 127);
}
public static List GetInputRange(int minX, int maxX, int minZ, int maxZ)
{
List output = new List();
for (int x = minX; x <= maxX; x++)
{
if (MoreMath.InputIsInDeadZone(x)) continue;
for (int z = minZ; z <= maxZ; z++)
{
if (MoreMath.InputIsInDeadZone(z)) continue;
output.Add(new Input(x, z));
}
}
return output;
}
public static int ApproachInt(int current, int target, int inc, int dec)
{
if (current < target)
{
current += inc;
if (current > target)
current = target;
}
else
{
current -= dec;
if (current < target)
current = target;
}
return current;
}
public static float ApproachFloat(float current, float target, float inc, float dec)
{
if (current < target)
{
current += inc;
if (current > target)
{
current = target;
}
}
else
{
current -= dec;
if (current < target)
{
current = target;
}
}
return current;
}
}
}
================================================
FILE: STROOP/Calculators/GroundMovementCalculator.cs
================================================
using STROOP.Forms;
using STROOP.Managers;
using STROOP.Models;
using STROOP.Structs.Configurations;
using STROOP.Utilities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STROOP.Structs
{
public static class GroundMovementCalculator
{
// act_hold_walking
public static MarioState ApplyInput(MarioState initialState, Input input)
{
MutableMarioState mutableMarioState = initialState.GetMutableMarioState(input);
mutableMarioState.IntendedMagnitude *= 0.4f;
UpdateWalkingSpeed(mutableMarioState);
PerformGroundStep(mutableMarioState);
MarioState finalState = mutableMarioState.GetMarioState(initialState, input);
return finalState;
}
public static MarioState ApplyInput(MarioState initialState, int angleDiff)
{
MutableMarioState mutableMarioState = initialState.GetMutableMarioState(angleDiff);
mutableMarioState.IntendedMagnitude *= 0.4f;
UpdateWalkingSpeed(mutableMarioState);
PerformGroundStep(mutableMarioState);
MarioState finalState = mutableMarioState.GetMarioState(initialState, null);
return finalState;
}
// update_walking_speed
private static void UpdateWalkingSpeed(MutableMarioState marioState)
{
float maxTargetSpeed;
float targetSpeed;
bool slowSurface = false;
if (slowSurface)
maxTargetSpeed = 24.0f;
else
maxTargetSpeed = 32.0f;
targetSpeed = marioState.IntendedMagnitude < maxTargetSpeed ? marioState.IntendedMagnitude : maxTargetSpeed;
if (marioState.HSpeed <= 0.0f)
marioState.HSpeed += 1.1f;
else if (marioState.HSpeed <= targetSpeed)
marioState.HSpeed += 1.1f - marioState.HSpeed / 43.0f;
else
marioState.HSpeed -= 1.0f;
if (marioState.HSpeed > 48.0f)
marioState.HSpeed = 48.0f;
marioState.MarioAngle = MoreMath.NormalizeAngleUshort(
marioState.IntendedAngle - CalculatorUtilities.ApproachInt(
MoreMath.NormalizeAngleShort(marioState.IntendedAngle - marioState.MarioAngle), 0, 0x800, 0x800));
ApplySlopeAccel(marioState);
}
// apply_slope_accel
private static void ApplySlopeAccel(MutableMarioState marioState)
{
marioState.XSpeed = marioState.HSpeed * InGameTrigUtilities.InGameSine(marioState.MarioAngle);
marioState.YSpeed = 0.0f;
marioState.ZSpeed = marioState.HSpeed * InGameTrigUtilities.InGameCosine(marioState.MarioAngle);
}
// perform_ground_step
private static void PerformGroundStep(MutableMarioState marioState)
{
for (int i = 0; i < 4; i++)
{
marioState.X = marioState.X + marioState.XSpeed / 4.0f;
marioState.Z = marioState.Z + marioState.ZSpeed / 4.0f;
}
}
public static MarioState PerformButtSlide(MarioState marioState, Input input, TriangleDataModel floor, List walls)
{
MutableMarioState mutableMarioState = marioState.GetMutableMarioState(input);
common_slide_action_with_jump(mutableMarioState, floor, walls);
return mutableMarioState.GetMarioState(marioState, input);
}
public static MarioState PerformButtSlide(MarioState marioState, int angleDiff, TriangleDataModel floor, List walls)
{
MutableMarioState mutableMarioState = marioState.GetMutableMarioState(angleDiff);
common_slide_action_with_jump(mutableMarioState, floor, walls);
return mutableMarioState.GetMarioState(marioState, new Input(angleDiff, 0));
}
private static void common_slide_action_with_jump(MutableMarioState marioState, TriangleDataModel floor, List walls)
{
update_sliding(marioState, 4.0f, floor, walls);
common_slide_action(marioState, floor, walls);
}
private static void update_sliding(MutableMarioState marioState, float stopSpeed, TriangleDataModel floor, List walls)
{
short intendedDYaw = MoreMath.NormalizeAngleShort(marioState.IntendedAngle - marioState.SlidingAngle);
float forward = InGameTrigUtilities.InGameCosine(intendedDYaw);
float sideward = InGameTrigUtilities.InGameSine(intendedDYaw);
//! 10k glitch
if (forward < 0.0f && marioState.HSpeed >= 0.0f)
{
forward *= 0.5f + 0.5f * marioState.HSpeed / 100.0f;
}
float accel;
float lossFactor;
int floorClass = 0x13;
switch (floorClass)
{
case 0x0013:
accel = 10.0f;
lossFactor = marioState.IntendedMagnitude / 32.0f * forward * 0.02f + 0.98f;
break;
case 0x0014:
accel = 8.0f;
lossFactor = marioState.IntendedMagnitude / 32.0f * forward * 0.02f + 0.96f;
break;
default:
accel = 7.0f;
lossFactor = marioState.IntendedMagnitude / 32.0f * forward * 0.02f + 0.92f;
break;
case 0x0015:
accel = 5.0f;
lossFactor = marioState.IntendedMagnitude / 32.0f * forward * 0.02f + 0.92f;
break;
}
float oldSpeed = (float)Math.Sqrt(
marioState.SlidingSpeedX * marioState.SlidingSpeedX +
marioState.SlidingSpeedZ * marioState.SlidingSpeedZ);
//! This is attempting to use trig derivatives to rotate mario's speed.
// It is slightly off/asymmetric since it uses the new X speed, but the old
// Z speed.
marioState.SlidingSpeedX += marioState.SlidingSpeedZ * (marioState.IntendedMagnitude / 32.0f) * sideward * 0.05f;
marioState.SlidingSpeedZ -= marioState.SlidingSpeedX * (marioState.IntendedMagnitude / 32.0f) * sideward * 0.05f;
float newSpeed = (float)Math.Sqrt(
marioState.SlidingSpeedX * marioState.SlidingSpeedX +
marioState.SlidingSpeedZ * marioState.SlidingSpeedZ);
if (oldSpeed > 0.0f && newSpeed > 0.0f)
{
marioState.SlidingSpeedX = marioState.SlidingSpeedX * oldSpeed / newSpeed;
marioState.SlidingSpeedZ = marioState.SlidingSpeedZ * oldSpeed / newSpeed;
}
update_sliding_angle(marioState, accel, lossFactor, floor, walls);
}
private static void update_sliding_angle(MutableMarioState marioState, float accel, float lossFactor, TriangleDataModel floor, List walls)
{
short slopeAngle = MoreMath.NormalizeAngleShort(InGameTrigUtilities.InGameATan(floor.NormZ, floor.NormX));
float steepness = (float)Math.Sqrt(floor.NormX * floor.NormX + floor.NormZ * floor.NormZ);
marioState.SlidingSpeedX += accel * steepness * InGameTrigUtilities.InGameSine(slopeAngle);
marioState.SlidingSpeedZ += accel * steepness * InGameTrigUtilities.InGameCosine(slopeAngle);
marioState.SlidingSpeedX *= lossFactor;
marioState.SlidingSpeedZ *= lossFactor;
marioState.SlidingAngle = InGameTrigUtilities.InGameATan(marioState.SlidingSpeedZ, marioState.SlidingSpeedX);
short facingDYaw = MoreMath.NormalizeAngleShort(marioState.MarioAngle - marioState.SlidingAngle);
int newFacingDYaw = facingDYaw;
//! -0x4000 not handled - can slide down a slope while facing perpendicular to it
if (newFacingDYaw > 0 && newFacingDYaw <= 0x4000) {
if ((newFacingDYaw -= 0x200) < 0) {
newFacingDYaw = 0;
}
} else if (newFacingDYaw > -0x4000 && newFacingDYaw < 0) {
if ((newFacingDYaw += 0x200) > 0) {
newFacingDYaw = 0;
}
} else if (newFacingDYaw > 0x4000 && newFacingDYaw < 0x8000) {
if ((newFacingDYaw += 0x200) > 0x8000) {
newFacingDYaw = 0x8000;
}
} else if (newFacingDYaw > -0x8000 && newFacingDYaw < -0x4000) {
if ((newFacingDYaw -= 0x200) < -0x8000) {
newFacingDYaw = -0x8000;
}
}
marioState.MarioAngle = MoreMath.NormalizeAngleUshort(marioState.SlidingAngle + newFacingDYaw);
marioState.XSpeed = marioState.SlidingSpeedX;
marioState.YSpeed = 0.0f;
marioState.ZSpeed = marioState.SlidingSpeedZ;
//! Speed is capped a frame late (butt slide HSG)
marioState.HSpeed = (float)Math.Sqrt(
marioState.SlidingSpeedX * marioState.SlidingSpeedX +
marioState.SlidingSpeedZ * marioState.SlidingSpeedZ);
if (marioState.HSpeed > 100.0f) {
marioState.SlidingSpeedX = marioState.SlidingSpeedX * 100.0f / marioState.HSpeed;
marioState.SlidingSpeedZ = marioState.SlidingSpeedZ * 100.0f / marioState.HSpeed;
}
if (newFacingDYaw < -0x4000 || newFacingDYaw > 0x4000) {
marioState.HSpeed *= -1.0f;
}
}
private static void common_slide_action(
MutableMarioState marioState, TriangleDataModel floor, List walls)
{
perform_ground_step(marioState, floor, walls);
// TODO: confirm that result doesn't matter
}
private static void perform_ground_step(
MutableMarioState marioState, TriangleDataModel floor, List walls)
{
for (int i = 0; i < 4; i++)
{
float intendedPosX = marioState.X + floor.NormY * (marioState.XSpeed / 4.0f);
float intendedPosZ = marioState.Z + floor.NormY * (marioState.ZSpeed / 4.0f);
float intendedPosY = marioState.Y;
perform_ground_quarter_step(
marioState, intendedPosX, intendedPosY, intendedPosZ, floor, walls);
}
}
private static void perform_ground_quarter_step(
MutableMarioState marioState, float intendedPosX, float intendedPosY, float intendedPosZ,
TriangleDataModel floor, List walls)
{
(intendedPosX, intendedPosZ) =
WallDisplacementCalculator.HandleWallDisplacement(
intendedPosX, intendedPosY, intendedPosZ, walls, 50, 60);
float floorHeight = floor.GetTruncatedHeightOnTriangle(intendedPosX, intendedPosZ);
marioState.X = intendedPosX;
marioState.Y = floorHeight;
marioState.Z = intendedPosZ;
}
}
}
================================================
FILE: STROOP/Calculators/HolpCalculator.cs
================================================
using STROOP.Forms;
using STROOP.Managers;
using STROOP.Models;
using STROOP.Structs.Configurations;
using STROOP.Utilities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STROOP.Structs
{
public static class HolpCalculator
{
private static List<(int, double, double, double)> _dataForWalking = new List<(int, double, double, double)>()
{
(0,-13.852560043335,82.7928466796875,43.2764892578125),
(1,-13.8603839874268,84.1005249023438,43.2064208984375),
(2,-13.8159141540527,84.2417602539063,43.1217041015625),
(3,-13.8067932128906,84.3388061523438,43.032958984375),
(4,-13.8156032562256,84.4673461914063,42.8843994140625),
(5,-13.8143367767334,84.3573608398438,42.7357177734375),
(6,-13.8485641479492,84.4801635742188,42.5528564453125),
(7,-13.913293838501,84.3718872070313,42.3017578125),
(8,-13.9324378967285,84.2554931640625,42.12255859375),
(9,-14.0344524383545,83.8282470703125,41.887451171875),
(10,-14.1320991516113,83.65185546875,41.6539306640625),
(11,-14.2047386169434,83.2032470703125,41.481689453125),
(12,-14.3437423706055,82.9824829101563,41.230224609375),
(13,-14.4278945922852,82.4707641601563,41.1116943359375),
(14,-14.6146621704102,81.8866577148438,40.9158935546875),
(15,-14.7635688781738,81.2904663085938,40.7923583984375),
(16,-14.983922958374,80.6292724609375,40.6275634765625),
(17,-15.2353763580322,79.8695678710938,40.525634765625),
(18,-15.4751510620117,79.0504760742188,40.5074462890625),
(19,-15.7339839935303,78.1624145507813,40.528564453125),
(20,-16.0744380950928,77.209716796875,40.4693603515625),
(21,-16.350076675415,76.2724609375,40.4874267578125),
(22,-16.6590099334717,75.2498779296875,40.524169921875),
(23,-16.9654483795166,74.2208862304688,40.5496826171875),
(24,-17.286901473999,73.1162719726563,40.60302734375),
(25,-17.5732021331787,72.0418090820313,40.662109375),
(26,-17.8684062957764,70.9493408203125,40.6968994140625),
(27,-18.1436023712158,70.1430053710938,40.7091064453125),
(28,-18.4258403778076,69.06982421875,40.7000732421875),
(29,-18.6577587127686,68.073974609375,40.6951904296875),
(30,-18.8827457427979,66.8560180664063,40.662353515625),
(31,-19.0599193572998,65.9683227539063,40.640380859375),
(32,-19.2313365936279,65.8605346679688,40.594970703125),
(33,-19.3553791046143,66.3665161132813,40.5447998046875),
(34,-19.4837818145752,67.1422729492188,40.4661865234375),
(35,-19.5892887115479,67.9154052734375,40.43017578125),
(36,-19.659029006958,69.2606811523438,40.4078369140625),
(37,-19.7250804901123,70.356201171875,40.3907470703125),
(38,-19.7577571868896,71.4926147460938,40.40869140625),
(39,-19.7571697235107,72.4199829101563,40.462158203125),
(40,-19.7728824615479,73.1315307617188,40.45849609375),
(41,-19.7376079559326,73.8190307617188,40.5723876953125),
(42,-19.7122821807861,74.5830078125,40.6121826171875),
(43,-19.6650981903076,75.282958984375,40.739013671875),
(44,-19.57346534729,75.8268432617188,40.88525390625),
(45,-19.4797077178955,76.1210327148438,41.033203125),
(46,-19.3439426422119,76.4605102539063,41.2265625),
(47,-19.2333011627197,76.2872314453125,41.37890625),
(48,-19.0889110565186,76.1022338867188,41.597900390625),
(49,-18.9064617156982,75.9515380859375,41.857421875),
(50,-18.7486705780029,75.5679321289063,42.0560302734375),
(51,-18.5583438873291,75.1459350585938,42.33203125),
(52,-18.3875865936279,74.7825317382813,42.52978515625),
(53,-18.1501483917236,74.1698608398438,42.83203125),
(54,-17.9086894989014,73.806396484375,43.1324462890625),
(55,-17.7250003814697,73.1712646484375,43.34814453125),
(56,-17.4643001556396,72.8579711914063,43.6300048828125),
(57,-17.1985988616943,72.2935791015625,43.9110107421875),
(58,-16.9619617462158,71.688720703125,44.1668701171875),
(59,-16.7159366607666,71.3931274414063,44.3900146484375),
(60,-16.4704761505127,70.817626953125,44.6248779296875),
(61,-16.1780300140381,70.2903442382813,44.8857421875),
(62,-15.9158897399902,70.0347900390625,45.0811767578125),
(63,-15.6951370239258,69.4375,45.2755126953125),
(64,-15.4251079559326,69.2108764648438,45.447509765625),
(65,-15.1985931396484,68.4242553710938,45.596435546875),
(66,-14.9584121704102,67.7183227539063,45.701416015625),
(67,-14.7734146118164,67.4125366210938,45.7999267578125),
(68,-14.5395526885986,68.2246704101563,45.871826171875),
(69,-14.385705947876,70.1324462890625,45.7674560546875),
(70,-14.2014904022217,72.6931762695313,45.574951171875),
(71,-14.1282138824463,75.119140625,45.1312255859375),
(72,-13.9819869995117,77.0831298828125,44.716552734375),
(73,-13.9631118774414,78.2352905273438,44.156494140625),
(74,-13.8647117614746,79.316162109375,43.736083984375),
(75,-13.8919486999512,80.1707763671875,43.3465576171875),
};
private static List<(int, double, double, double)> _dataForStanding = new List<(int, double, double, double)>()
{
(0,-14.9768142700195,70.0527954101563,46.1116943359375),
(1,-15.0781002044678,68.8441772460938,46.2886962890625),
(2,-15.1815433502197,67.6535034179688,46.4891357421875),
(3,-15.2864570617676,66.4968872070313,46.6727294921875),
(4,-15.4240989685059,65.3958129882813,46.7882080078125),
(5,-15.5248756408691,64.2696533203125,46.9483642578125),
(6,-15.6575241088867,63.5349731445313,47.0325927734375),
(7,-15.7512474060059,62.8151245117188,47.1492919921875),
(8,-15.8002777099609,62.2562866210938,47.2369384765625),
(9,-15.8486957550049,62.0972290039063,47.2794189453125),
(10,-15.8909912109375,62.0515747070313,47.27490234375),
(11,-15.8591861724854,62.265380859375,47.27587890625),
(12,-15.859338760376,62.816650390625,47.187744140625),
(13,-15.7759399414063,63.7854614257813,47.0892333984375),
(14,-15.6890602111816,64.8377685546875,46.96875),
(15,-15.5938949584961,65.9906616210938,46.784423828125),
(16,-15.4942493438721,67.1390991210938,46.58642578125),
(17,-15.3519325256348,67.94384765625,46.4541015625),
(18,-15.2373886108398,69.06005859375,46.2559814453125),
(19,-15.1235389709473,69.7003173828125,46.1351318359375),
(20,-14.9768142700195,70.0527954101563,46.1116943359375),
(21,-14.8577976226807,70.2546997070313,46.1241455078125),
(22,-14.7283592224121,70.18115234375,46.167236328125),
(23,-14.5577449798584,69.81005859375,46.2996826171875),
(24,-14.3835906982422,69.622314453125,46.4842529296875),
(25,-14.2441596984863,69.1331787109375,46.658935546875),
(26,-14.0631008148193,68.68505859375,46.8543701171875),
(27,-13.9271926879883,68.18115234375,47.030517578125),
(28,-13.8096122741699,67.6304931640625,47.2154541015625),
(29,-13.7399406433105,67.3751220703125,47.305908203125),
(30,-13.7294921875,67.3475952148438,47.339111328125),
(31,-13.7399406433105,67.3751220703125,47.305908203125),
(32,-13.8096122741699,67.6304931640625,47.2154541015625),
(33,-13.9271926879883,68.18115234375,47.030517578125),
(34,-14.0631008148193,68.68505859375,46.8543701171875),
(35,-14.2348442077637,69.1707763671875,46.6429443359375),
(36,-14.3747138977051,69.6599731445313,46.4674072265625),
(37,-14.5577449798584,69.81005859375,46.2996826171875),
(38,-14.7283592224121,70.18115234375,46.167236328125),
(39,-14.8577976226807,70.2546997070313,46.1241455078125),
(40,-14.9768142700195,70.0527954101563,46.1116943359375),
(41,-15.1239433288574,69.745849609375,46.1343994140625),
(42,-15.2446212768555,69.0670776367188,46.2738037109375),
(43,-15.3988609313965,68.053955078125,46.4130859375),
(44,-15.5546684265137,67.1847534179688,46.6026611328125),
(45,-15.6641502380371,66.0863647460938,46.8216552734375),
(46,-15.8019599914551,65.0361328125,46.9552001953125),
(47,-15.900447845459,64.0007934570313,47.117431640625),
(48,-15.9886722564697,63.0756225585938,47.221923828125),
(49,-16.0358943939209,62.5552368164063,47.295654296875),
(50,-16.0395030975342,62.44921875,47.343505859375),
(51,-16.0358943939209,62.5552368164063,47.295654296875),
(52,-15.9487285614014,63.134521484375,47.245361328125),
(53,-15.8516540527344,64.1402587890625,47.10791015625),
(54,-15.7057952880859,65.27294921875,46.9495849609375),
(55,-15.5549392700195,66.400390625,46.7799072265625),
(56,-15.3991146087646,67.5536499023438,46.5782470703125),
(57,-15.238431930542,68.4193725585938,46.3848876953125),
(58,-15.1240825653076,69.3726806640625,46.22314453125),
(59,-15.0214500427246,69.9351196289063,46.13720703125),
(60,-14.9768142700195,70.0527954101563,46.1116943359375),
};
private static Dictionary _dictionaryForWalking;
private static Dictionary _dictionaryForStanding;
public static readonly int WALKING_COUNT = 76;
public static readonly int STANDING_COUNT = 61;
static HolpCalculator()
{
_dictionaryForWalking = new Dictionary();
foreach ((int index, double x, double y, double z) in _dataForWalking)
{
_dictionaryForWalking[index] = (x, y, z);
}
_dictionaryForStanding = new Dictionary();
foreach ((int index, double x, double y, double z) in _dataForStanding)
{
_dictionaryForStanding[index] = (x, y, z);
}
}
public static (float x, float y, float z) GetHolpForWalking(int index)
{
if (!_dictionaryForWalking.ContainsKey(index)) return (float.NaN, float.NaN, float.NaN);
(double xOffset, double yOffset, double zOffset) = _dictionaryForWalking[index];
return ((float)xOffset, (float)yOffset, (float)zOffset);
}
public static (float x, float y, float z) GetHolpForStanding(int index)
{
if (!_dictionaryForStanding.ContainsKey(index)) return (float.NaN, float.NaN, float.NaN);
(double xOffset, double yOffset, double zOffset) = _dictionaryForStanding[index];
return ((float)xOffset, (float)yOffset, (float)zOffset);
}
public static (float x, float y, float z) GetHolpForWalking(
int index, float marioX, float marioY, float marioZ, ushort marioAngle)
{
if (!_dictionaryForWalking.ContainsKey(index)) return (float.NaN, float.NaN, float.NaN);
(double xOffset, double yOffset, double zOffset) = _dictionaryForWalking[index];
double vectorMagnitude = MoreMath.GetHypotenuse(xOffset, zOffset);
double vectorAngle = MoreMath.AngleTo_AngleUnits(xOffset, zOffset);
double rotatedAngle = vectorAngle + MoreMath.NormalizeAngleTruncated(marioAngle);
(double rotatedX, double rotatedZ) = MoreMath.GetComponentsFromVector(vectorMagnitude, rotatedAngle);
double offsetX = rotatedX + marioX;
double offsetY = yOffset + marioY;
double offsetZ = rotatedZ + marioZ;
return ((float)offsetX, (float)offsetY, (float)offsetZ);
}
public static (float x, float y, float z) GetHolpForStanding(
int index, float marioX, float marioY, float marioZ, ushort marioAngle)
{
if (!_dictionaryForStanding.ContainsKey(index)) return (float.NaN, float.NaN, float.NaN);
(double xOffset, double yOffset, double zOffset) = _dictionaryForStanding[index];
double vectorMagnitude = MoreMath.GetHypotenuse(xOffset, zOffset);
double vectorAngle = MoreMath.AngleTo_AngleUnits(xOffset, zOffset);
double rotatedAngle = vectorAngle + MoreMath.NormalizeAngleTruncated(marioAngle);
(double rotatedX, double rotatedZ) = MoreMath.GetComponentsFromVector(vectorMagnitude, rotatedAngle);
double offsetX = rotatedX + marioX;
double offsetY = yOffset + marioY;
double offsetZ = rotatedZ + marioZ;
return ((float)offsetX, (float)offsetY, (float)offsetZ);
}
}
}
================================================
FILE: STROOP/Calculators/Input.cs
================================================
using STROOP.Forms;
using STROOP.Managers;
using STROOP.Structs.Configurations;
using STROOP.Utilities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STROOP.Structs
{
// Y value is inputted and stored in sm64 convention
// Y value is displayed in mupen convention
public class Input
{
public static bool USE_TAS_INPUT_Y = true;
public readonly int X;
public readonly int Y;
public Input(int x, int y)
{
X = x;
Y = y;
}
public float GetScaledMagnitude()
{
return MoreMath.GetScaledInputMagnitude(X, Y, false);
}
public override string ToString()
{
return String.Format("({0},{1})", X, (USE_TAS_INPUT_Y ? -1 : 1) * Y);
}
}
}
================================================
FILE: STROOP/Calculators/LoadingZoneMain.cs
================================================
using STROOP.Forms;
using STROOP.Managers;
using STROOP.Models;
using STROOP.Structs.Configurations;
using STROOP.Ttc;
using STROOP.Utilities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STROOP.Structs
{
public static class LoadingZoneMain
{
public static Random r = new Random();
public static Dictionary BaseUnloadStrategy =
new Dictionary()
{
[UnloadableId.LOADED_ALWAYS] = false, // do not change
[UnloadableId.SKEETER_CLOSE] = false,
[UnloadableId.SKEETER_FAR] = true,
[UnloadableId.CORK_BOX_EXPRESS_ELEVATOR] = false,
[UnloadableId.CORK_BOX_EDGE_1] = false,
[UnloadableId.CORK_BOX_EDGE_2] = false,
[UnloadableId.CORK_BOX_EDGE_3] = false,
[UnloadableId.CORK_BOX_EDGE_4] = false,
[UnloadableId.CORK_BOX_BIG] = false,
[UnloadableId.BLUE_COIN] = true,
[UnloadableId.ITEM_BLOCK_PENTAGON_PLATFORM] = false,
[UnloadableId.ITEM_BLOCK_EXPRESS_ELEVATOR] = false,
[UnloadableId.ITEM_BLOCK_SLIDE_KICK] = false,
[UnloadableId.ITEM_BLOCK_HIGH_CORNER] = false,
[UnloadableId.ONE_UP_TUNNEL_1] = false,
[UnloadableId.ONE_UP_TUNNEL_2] = false,
[UnloadableId.SECRET_EXPRESS_ELEVATOR] = false,
[UnloadableId.SECRET_BLOCK_HOLE] = false,
[UnloadableId.SECRET_PENTAGON_PLATFORM] = false,
[UnloadableId.SECRET_HIGH_CORNER] = false,
[UnloadableId.SECRET_WATER_BLOCK] = false,
};
public static Dictionary UnloadStrategy;
public static List<(int numBubbles, bool bubbleSpawnerPresent)> BubbleConfigurations =
new List<(int numBubbles, bool bubbleSpawnerPresent)>()
{
(5, true),
(6, false),
(6, true),
(7, false),
(7, true),
(8, false),
(8, true),
(9, false),
(9, true),
(10, false),
(10, true),
(11, false),
(11, true),
(12, false),
(12, true),
(13, false),
(13, true),
(14, false),
(14, true),
(15, false),
(15, true),
};
public static List<(int numBubbles, bool bubbleSpawnerPresent)> BubbleConfigurationsSimplified =
new List<(int numBubbles, bool bubbleSpawnerPresent)>()
{
(5, true),
(6, true),
(7, true),
(8, true),
(9, true),
(10, true),
(11, true),
(12, true),
(13, true),
(14, true),
(15, true),
};
public class LoadingZoneState
{
public readonly int Frame;
public readonly List LoadingZoneFrames;
public LoadingZoneState(
int frame,
List loadingZoneFrames)
{
Frame = frame;
LoadingZoneFrames = loadingZoneFrames;
}
public List GetSuccessors()
{
List output = new List();
int remainingFrames = 17 - Frame;
for (int i = 2; i <= remainingFrames; i++)
{
LoadingZoneState state = new LoadingZoneState(
Frame + i, LoadingZoneFrames.Concat(new List() { i }).ToList());
output.Add(state);
}
return output;
}
}
public static List GetRngIndexes()
{
List> loadingZoneFramesList = new List>()
{
//new List() { 1,2,2,2,2,7,1 },
new List() { 1,2,4,2,2,4,2 },
//new List() { 1,2,4,2,2,5,1 },
//new List() { 1,2,4,3,2,4,1 },
//new List() { 1,2,5,2,2,4,1 },
//new List() { 1,3,4,2,2,4,1 },
};
GenerateUnloadStrategy();
bool isBubbleSpawnerPresent = true;
int numInitialBubbles = 5;
List rngIndexes = new List();
for (int rngIndex = 0; rngIndex < 65114; rngIndex++)
{
foreach (List loadingZoneFrames in loadingZoneFramesList)
{
int rngValue = RngIndexer.GetRngValue(rngIndex);
(bool success, int result, ObjName objName, int numTransitions, int numFrames) =
Simulate(ObjName.CORK_BOX_WHITE_BUILDING, loadingZoneFrames, rngValue, isBubbleSpawnerPresent, numInitialBubbles, false);
if (success)
{
rngIndexes.Add(rngIndex);
break;
}
}
}
return rngIndexes;
}
public static void Run5()
{
Config.Print("START");
List> loadingZoneFramesList = new List>()
{
//new List() { 1,2,2,2,2,7,1 },
new List() { 1,2,4,2,2,4,2 },
//new List() { 1,2,4,2,2,5,1 },
//new List() { 1,2,4,3,2,4,1 },
//new List() { 1,2,5,2,2,4,1 },
//new List() { 1,3,4,2,2,4,1 },
};
GenerateUnloadStrategy();
bool isBubbleSpawnerPresent = false;
int numInitialBubbles = 6;
int rngIndex = 17551;
//for (int rngIndex = 0; rngIndex < 65114; rngIndex++)
{
foreach (List loadingZoneFrames in loadingZoneFramesList)
{
int rngValue = RngIndexer.GetRngValue(rngIndex);
(bool success, int result, ObjName objName, int numTransitions, int numFrames) =
Simulate(ObjName.CORK_BOX_WHITE_BUILDING, loadingZoneFrames, rngValue, isBubbleSpawnerPresent, numInitialBubbles, true);
string instructions = FormatLoadingZoneFrames(loadingZoneFrames);
if (success)
{
Config.Print("-------------------------------------");
Config.Print("objName = " + objName);
Config.Print("numFrames = " + numFrames);
Config.Print("numTransitions = " + numTransitions);
Config.Print("loadingZoneFrames = " + string.Join(",", loadingZoneFrames));
Config.Print("rngIndex = " + rngIndex);
Config.Print("rngValue = " + rngValue);
Config.Print("isBubbleSpawnerPresent = " + isBubbleSpawnerPresent);
Config.Print("numInitialBubbles = " + numInitialBubbles);
Config.Print(instructions);
Config.Print("-------------------------------------");
}
}
}
Config.Print("DONE");
}
public static void Run4()
{
Config.Print("START");
Queue queue = new Queue();
List allStates = new List();
LoadingZoneState initialState = new LoadingZoneState(1, new List() { 1 });
queue.Enqueue(initialState);
allStates.Add(initialState);
while (queue.Count > 0)
{
LoadingZoneState dequeue = queue.Dequeue();
List successors = dequeue.GetSuccessors();
foreach (LoadingZoneState successor in successors)
{
queue.Enqueue(successor);
allStates.Add(successor);
}
}
List bubbleSpawnerMaxTimers = new List() { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
GenerateUnloadStrategy();
foreach (var bubbleConfiguration in BubbleConfigurationsSimplified)
{
foreach (LoadingZoneState state in allStates)
{
(bool success, int result, ObjName objName, int numTransitions, int numFrames) =
Simulate(
ObjName.CORK_BOX_WHITE_BUILDING,
state.LoadingZoneFrames,
bubbleSpawnerMaxTimers,
bubbleConfiguration.bubbleSpawnerPresent,
bubbleConfiguration.numBubbles,
false);
if (success && numFrames <= 17)
{
Config.Print("new List() { " + string.Join(",", state.LoadingZoneFrames) + " },");
Config.Print("bubbleConfiguration.bubbleSpawnerPresent = " + bubbleConfiguration.bubbleSpawnerPresent);
Config.Print("bubbleConfiguration.numBubbles = " + bubbleConfiguration.numBubbles);
Config.Print();
}
}
}
Config.Print("DONE");
}
public static void Run3()
{
Config.Print("START");
Queue queue = new Queue();
List allStates = new List();
LoadingZoneState initialState = new LoadingZoneState(1, new List() { 1 });
queue.Enqueue(initialState);
allStates.Add(initialState);
while (queue.Count > 0)
{
LoadingZoneState dequeue = queue.Dequeue();
List successors = dequeue.GetSuccessors();
foreach (LoadingZoneState successor in successors)
{
queue.Enqueue(successor);
allStates.Add(successor);
}
}
List bubbleSpawnerMaxTimers = new List() { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
int numNull = BaseUnloadStrategy.Values.ToList().FindAll(b => b == null).Count;
List> boolsList = GenerateBoolLists(numNull);
boolsList = boolsList.FindAll(list => list.Count(b => b) <= 4);
boolsList.Sort((b1, b2) =>
{
int c1 = b1.Count(b => b);
int c2 = b2.Count(b => b);
return c1.CompareTo(c2);
});
int minFrames = int.MaxValue;
int counter = 0;
foreach (List bools in boolsList)
{
bool boolsSuccess = false;
if (counter % 100 == 0)
{
Config.Print(counter + " / " + boolsList.Count);
Config.Print();
}
counter++;
GenerateUnloadStrategy(bools);
foreach (var bubbleConfiguration in BubbleConfigurationsSimplified)
{
foreach (LoadingZoneState state in allStates)
{
(bool success, int result, ObjName objName, int numTransitions, int numFrames) =
Simulate(
ObjName.CORK_BOX_WHITE_BUILDING,
state.LoadingZoneFrames,
bubbleSpawnerMaxTimers,
bubbleConfiguration.bubbleSpawnerPresent,
bubbleConfiguration.numBubbles,
false);
if (success && numFrames <= 17)
{
Config.Print("success = " + success);
Config.Print("result = " + result);
Config.Print("objName = " + objName);
Config.Print("numTransitions = " + numTransitions);
Config.Print("numFrames = " + numFrames);
Config.Print("bools = " + string.Join(",", bools));
Config.Print("loadingZoneFrames = " + string.Join(",", state.LoadingZoneFrames));
Config.Print("bubbleSpawnerMaxTimers = " + string.Join(",", bubbleSpawnerMaxTimers));
Config.Print("bubbleSpawnerPresent = " + bubbleConfiguration.bubbleSpawnerPresent);
Config.Print("numBubbles = " + bubbleConfiguration.numBubbles);
List ids = BaseUnloadStrategy.ToList().FindAll(p => p.Value == null).ConvertAll(p => p.Key);
List unloaded = new List();
for (int i = 0; i < bools.Count; i++)
{
if (bools[i]) unloaded.Add(ids[i]);
}
Config.Print("unloadedObjs = " + string.Join(",", unloaded));
Config.Print("unloadedCount = " + unloaded.Count);
Config.Print();
minFrames = Math.Min(minFrames, numFrames);
boolsSuccess = true;
}
if (boolsSuccess) break;
}
if (boolsSuccess) break;
}
if (boolsSuccess) continue;
}
Config.Print("MIN FRAMES = " + minFrames);
Config.Print("DONE");
}
public static void Run()
{
Config.Print("STARTING...");
HashSet instructionList = new HashSet();
while (true)
{
GenerateUnloadStrategy();
List loadingZoneFrames = GenerateRandomLoadingZoneFrames();
int rngIndex = RngIndexer.GetRngIndex();
int rng = RngIndexer.GetRngValue();
foreach (bool isBubbleSpawnerPresent in new List() { false })
{
for (int numInitialBubbles = 7; numInitialBubbles <= 7; numInitialBubbles++)
{
(bool success, int result, ObjName objName, int numTransitions, int numFrames) =
Simulate(ObjName.STAR, loadingZoneFrames, rng, isBubbleSpawnerPresent, numInitialBubbles, false);
string instructions = FormatLoadingZoneFrames(loadingZoneFrames);
if (success && !instructionList.Contains(instructions))
{
instructionList.Add(instructions);
Config.Print("-------------------------------------");
Config.Print("objName = " + objName);
Config.Print("numFrames = " + numFrames);
Config.Print("numTransitions = " + numTransitions);
Config.Print("loadingZoneFrames = " + string.Join(",", loadingZoneFrames));
Config.Print("rngIndex = " + rngIndex);
Config.Print("rng = " + rng);
Config.Print("isBubbleSpawnerPresent = " + isBubbleSpawnerPresent);
Config.Print("numInitialBubbles = " + numInitialBubbles);
Config.Print(instructions);
Config.Print(DictionaryUtilities.GetString(UnloadStrategy));
Config.Print("-------------------------------------");
}
}
}
}
}
public static void Test()
{
for (int rngIndex = 0; rngIndex < 65114; rngIndex++)
{
bool success1 = Run(rngIndex, false, 7, 1, false);
bool success2 = Run(rngIndex, true, 6, 1, false);
if (success1) Config.Print("success1 " + rngIndex);
if (success2) Config.Print("success2 " + rngIndex);
}
}
public static bool Run(int rngIndex, bool isBubbleSpawnerPresent, int numInitialBubbles, int numTries, bool print)
{
for (int i = 0; i < numTries; i++)
{
GenerateUnloadStrategy();
List loadingZoneFrames = new List() { 1, 2, 4, 2, 3, 10, 2, 8, 7, 10, 6, 5, 3, 10, 11, 9 }; //GenerateRandomLoadingZoneFrames();
int rng = RngIndexer.GetRngValue(rngIndex);
(bool success, int result, ObjName objName, int numTransitions, int numFrames) =
Simulate(ObjName.STAR, loadingZoneFrames, rng, isBubbleSpawnerPresent, numInitialBubbles, false);
string instructions = FormatLoadingZoneFrames(loadingZoneFrames);
if (success)
{
if (print)
{
Config.Print("-------------------------------------");
Config.Print("objName = " + objName);
Config.Print("numFrames = " + numFrames);
Config.Print("numTransitions = " + numTransitions);
Config.Print("loadingZoneFrames = " + string.Join(",", loadingZoneFrames));
Config.Print("rngIndex = " + rngIndex);
Config.Print("rng = " + rng);
Config.Print("isBubbleSpawnerPresent = " + isBubbleSpawnerPresent);
Config.Print("numInitialBubbles = " + numInitialBubbles);
Config.Print(instructions);
Config.Print(DictionaryUtilities.GetString(UnloadStrategy));
Config.Print("-------------------------------------");
}
return true;
}
}
return false;
}
public static void Run2()
{
HashSet results = new HashSet();
HashSet instructionList = new HashSet();
while (true)
{
GenerateUnloadStrategy();
List loadingZoneFrames = GenerateRandomLoadingZoneFrames();
List bubbleSpawnerMaxTimers = GenerateRandomBubbleSpawnerMaxTimers();
foreach ((int numInitialBubbles, bool isBubbleSpawnerPresent) in BubbleConfigurations)
{
(bool success, int result, ObjName objName, int numTransitions, int numFrames) =
Simulate(ObjName.STAR, loadingZoneFrames, bubbleSpawnerMaxTimers, isBubbleSpawnerPresent, numInitialBubbles, false);
if (!results.Contains(result))
{
Config.Print(result + " " + objName);
results.Add(result);
}
string instructions = FormatLoadingZoneFrames(loadingZoneFrames);
if (success)
{
instructionList.Add(instructions);
Config.Print("-------------------------------------");
Config.Print("objName = " + objName);
Config.Print("numFrames = " + numFrames);
Config.Print("numTransitions = " + numTransitions);
Config.Print("loadingZoneFrames = " + string.Join(",", loadingZoneFrames));
Config.Print("bubbleSpawnerMaxTimers = " + string.Join(",", bubbleSpawnerMaxTimers));
Config.Print("isBubbleSpawnerPresent = " + isBubbleSpawnerPresent);
Config.Print("numInitialBubbles = " + numInitialBubbles);
Config.Print(instructions);
Config.Print(DictionaryUtilities.GetString(UnloadStrategy));
Config.Print("-------------------------------------");
}
}
}
}
public static List> GenerateBoolLists(int size)
{
List> output = new List>() { new List() { } };
for (int i = 0; i < size; i++)
{
output = output.SelectMany(b => new List>()
{
b.Concat(new List() { false }).ToList(),
b.Concat(new List() { true }).ToList(),
}).ToList();
}
return output;
}
public static void GenerateUnloadStrategy()
{
UnloadStrategy = new Dictionary();
foreach (UnloadableId key in BaseUnloadStrategy.Keys)
{
bool? valueNullable = BaseUnloadStrategy[key];
bool value = valueNullable ?? (r.Next(0, 2) == 0 ? false : true);
UnloadStrategy[key] = value;
}
}
public static void GenerateUnloadStrategy(List bools)
{
UnloadStrategy = new Dictionary();
int counter = 0;
foreach (UnloadableId key in BaseUnloadStrategy.Keys)
{
bool? valueNullable = BaseUnloadStrategy[key];
bool value = valueNullable ?? bools[counter++];
UnloadStrategy[key] = value;
}
}
public static List GenerateRandomLoadingZoneFrames()
{
List loadingZoneFrames = new List() { 1 };
int max = r.Next(2, 24);
for (int i = 0; i < 15; i++)
{
loadingZoneFrames.Add(r.Next(2, max));
}
return loadingZoneFrames;
}
public static List GenerateRandomBubbleSpawnerMaxTimers()
{
List bubbleSpawnerMaxTimers = new List();
int max = r.Next(2, 7);
for (int i = 0; i < 15; i++)
{
bubbleSpawnerMaxTimers.Add(r.Next(2, max));
}
return bubbleSpawnerMaxTimers;
}
public static string FormatLoadingZoneFrames(List loadingZoneFrames)
{
List outputList = new List();
bool rightwards = true;
int frame = 1904;
for (int i = 1; i < 11 && i < loadingZoneFrames.Count; i++)
{
int frames = loadingZoneFrames[i];
frame += frames;
rightwards = !rightwards;
string output = frame + " " + (rightwards ? "RIGHT" : "LEFT");
outputList.Add(output);
}
return string.Join("\r\n", outputList);
}
public static void RunTest()
{
List loadingZoneFrames = new List() { 1, 2, 3, 3, 10 };
List bubbleSpawnerMaxTimers = new List() { 10, 2, 3, 3, 9, 5 };
bool isBubbleSpawnerPresent = true;
int numInitialBubbles = 7;
Simulate(ObjName.STAR, loadingZoneFrames, bubbleSpawnerMaxTimers, isBubbleSpawnerPresent, numInitialBubbles, true);
}
public static void RunTest2()
{
List loadingZoneFrames = new List() { 1, 2, 3, 3, 10 };
int rng = 24331;
bool isBubbleSpawnerPresent = true;
int numInitialBubbles = 7;
Simulate(ObjName.STAR, loadingZoneFrames, rng, isBubbleSpawnerPresent, numInitialBubbles, true);
}
public static (bool success, int result, ObjName objName, int numTransitions, int numFrames) Simulate(
ObjName objName,
List loadingZoneFrames,
List bubbleSpawnerMaxTimers,
bool isBubbleSpawnerPresent,
int numInitialBubbles,
bool shouldPrint)
{
FrameTracker frameTracker = new FrameTracker(loadingZoneFrames);
BubbleTracker bubbleTracker = new BubbleTracker(bubbleSpawnerMaxTimers);
ObjSlotManager objSlotManager = InitializeObjSlotManager(isBubbleSpawnerPresent, numInitialBubbles, bubbleTracker);
return Simulate(objName, frameTracker, objSlotManager, shouldPrint);
}
public static (bool success, int result, ObjName objName, int numTransitions, int numFrames) Simulate(
ObjName objName,
List loadingZoneFrames,
int rng,
bool isBubbleSpawnerPresent,
int numInitialBubbles,
bool shouldPrint)
{
FrameTracker frameTracker = new FrameTracker(loadingZoneFrames);
TtcRng ttcRng = new TtcRng((ushort)rng);
ObjSlotManager objSlotManager = InitializeObjSlotManager(isBubbleSpawnerPresent, numInitialBubbles, ttcRng);
return Simulate(objName, frameTracker, objSlotManager, shouldPrint);
}
public static (bool success, int result, ObjName objName, int numTransitions, int numFrames) Simulate(
ObjName objName,
FrameTracker frameTracker,
ObjSlotManager objSlotManager,
bool shouldPrint)
{
int startFrame = 7797;
int frame = 0;
bool isTownLoaded = false;
int numFramesAreaLoaded = 0;
int numTransitions = 0;
ObjSlot heldSlot = objSlotManager.FindSlot(ObjName.CHUCKYA);
void print()
{
Config.Print(
"FRAME=" + (startFrame + frame) +
" isTownLoaded=" + isTownLoaded +
" numFramesAreaLoaded=" + numFramesAreaLoaded);
Config.Print(objSlotManager);
Config.Print();
}
if (shouldPrint) print();
(bool success, int result, ObjName objName, int numTransitions, int numFrames) returnValue = (false, -1, ObjName.UNKNOWN, numTransitions, -1);
while (true)
{
bool? shouldLoadTown = frameTracker.AdvanceFrame();
if (shouldLoadTown.HasValue)
{
PassThroughLoadingZone(objSlotManager, shouldLoadTown.Value);
isTownLoaded = shouldLoadTown.Value;
numFramesAreaLoaded = 0;
numTransitions++;
}
frame++;
numFramesAreaLoaded++;
if (isTownLoaded && numFramesAreaLoaded == 2)
{
LoadYellowCoins(objSlotManager);
}
objSlotManager.FrameAdvance();
if (shouldPrint) print();
if (isTownLoaded && heldSlot.Color != ObjSlotColor.GREY)
{
returnValue = (false, objSlotManager.GetCurrentSlotIndex(heldSlot), heldSlot.ObjName, numTransitions, frame);
if (heldSlot.ObjName == objName)
{
return (true, heldSlot.InitialIndex, heldSlot.ObjName, numTransitions, frame);
}
}
if (frame == 24) break;
}
return returnValue;
}
public static void PassThroughLoadingZone(ObjSlotManager objSlotManager, bool loadsTown)
{
UnloadEverything(objSlotManager);
Load(objSlotManager, loadsTown ? area2ObjData : area1ObjData);
}
public static void UnloadEverything(ObjSlotManager objSlotManager)
{
objSlotManager.UnloadColor(ObjSlotColor.GREEN);
objSlotManager.UnloadColor(ObjSlotColor.BLUE);
objSlotManager.UnloadColor(ObjSlotColor.PURPLE);
objSlotManager.UnloadColor(ObjSlotColor.RED);
objSlotManager.UnloadColor(ObjSlotColor.ORANGE);
objSlotManager.UnloadColor(ObjSlotColor.PINK);
objSlotManager.UnloadColor(ObjSlotColor.BROWN);
}
public static void Load(ObjSlotManager objSlotManager, List<(ObjName objName, ObjSlotColor color, UnloadableId id)> objData)
{
foreach (var data in objData)
{
if (UnloadStrategy[data.id]) continue;
objSlotManager.Load(data);
}
}
public static void LoadYellowCoins(ObjSlotManager objSlotManager)
{
for (int i = 0; i < 5; i++)
{
objSlotManager.Load((ObjName.YELLOW_COIN, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS));
}
}
public static ObjSlotManager InitializeObjSlotManager(
bool isBubbleSpawnerPresent,
int numInitialBubbles,
TtcRng rng)
{
ObjSlotManager objSlotManager = new RngObjSlotManager(rng);
return InitializeBubbleObjSlotManager(objSlotManager, isBubbleSpawnerPresent, numInitialBubbles);
}
public static ObjSlotManager InitializeObjSlotManager(
bool isBubbleSpawnerPresent,
int numInitialBubbles,
BubbleTracker bubbleTracker)
{
ObjSlotManager objSlotManager = new BubbleObjSlotManager(bubbleTracker);
return InitializeBubbleObjSlotManager(objSlotManager, isBubbleSpawnerPresent, numInitialBubbles);
}
public static ObjSlotManager InitializeBubbleObjSlotManager(
ObjSlotManager objSlotManager,
bool isBubbleSpawnerPresent,
int numInitialBubbles)
{
int counter = 0;
foreach (var data in initialObjData)
{
if (UnloadStrategy[data.id]) continue;
objSlotManager.AddToEndOfList(new ObjSlot(counter++, data.objName, data.color));
}
if (isBubbleSpawnerPresent)
{
objSlotManager.AddToEndOfList(new ObjSlot(counter++, ObjName.BUBBLE_SPAWNER, ObjSlotColor.PURPLE));
}
for (int i = 0; i < numInitialBubbles; i++)
{
objSlotManager.AddToEndOfList(new ObjSlot(counter++, ObjName.BUBBLE, ObjSlotColor.BROWN));
}
while (counter < 240)
{
objSlotManager.AddToEndOfList(new ObjSlot(counter++, ObjName.UNKNOWN, ObjSlotColor.GREY));
}
return objSlotManager;
}
public enum ObjSlotColor
{
PINK,
RED,
ORANGE,
YORANGE,
GREEN,
BLUE,
PURPLE,
BROWN,
GREY,
};
public enum ObjName
{
COIN_RING,
COIN_LINE,
SIGN,
BLUE_COIN_BLOCK,
ITEM_BLOCK,
CANNON_LID,
PUSHABLE_BLOCK,
CORK_BOX,
CORK_BOX_RED_ROOF,
CORK_BOX_WHITE_BUILDING,
SWITCH,
ROTATING_PLATFORM,
LONG_WOODEN_BOARD,
EXPRESS_ELEVATOR,
HIDDEN_WOODEN_BLOCK,
CRYSTAL_TAP,
ARROW_LIFT,
SHORT_WOODEN_BOARD,
MARIO,
BOB_OMB_BUDDY,
AMP,
HEAVE_HO,
CHUCKYA,
FIRE_SPITTER,
SKEETER,
HEAVE_HO_ANCHOR,
CHUCKYA_ANCHOR,
BLUE_COIN,
ONE_UP,
SECRET,
STAR,
SECRET_STAR_SPAWNER,
TELEPORTER,
WATER_LEVEL_MANAGER,
MARIO_SPAWNER,
METAL_CAP_BLOCK,
VANISH_CAP_BLOCK,
TREE,
POLE,
RED_COIN,
ONE_UP_ACTIVATOR,
RED_COIN_STAR_SPAWNER,
YELLOW_COIN,
STAR_MARKER,
BUBBLE_SPAWNER,
BUBBLE,
UNKNOWN,
};
public enum UnloadableId
{
LOADED_ALWAYS,
SKEETER_CLOSE,
SKEETER_FAR,
CORK_BOX_EXPRESS_ELEVATOR,
CORK_BOX_EDGE_1,
CORK_BOX_EDGE_2,
CORK_BOX_EDGE_3,
CORK_BOX_EDGE_4,
CORK_BOX_BIG,
BLUE_COIN,
ITEM_BLOCK_PENTAGON_PLATFORM,
ITEM_BLOCK_EXPRESS_ELEVATOR,
ITEM_BLOCK_SLIDE_KICK,
ITEM_BLOCK_HIGH_CORNER,
ONE_UP_TUNNEL_1,
ONE_UP_TUNNEL_2,
SECRET_EXPRESS_ELEVATOR,
SECRET_BLOCK_HOLE,
SECRET_PENTAGON_PLATFORM,
SECRET_HIGH_CORNER,
SECRET_WATER_BLOCK,
};
public class ObjSlot
{
public readonly int InitialIndex;
public ObjName ObjName;
public ObjSlotColor Color;
public int Timer;
public int BubbleSpawnerMaxTimer;
public int BobombBuddyBlinkingTimer;
public bool ShouldUnload;
public ObjSlot(int initialIndex, ObjName objName, ObjSlotColor color)
{
InitialIndex = initialIndex;
ObjName = objName;
Color = color;
Timer = 0;
BubbleSpawnerMaxTimer = 0;
BobombBuddyBlinkingTimer = 0;
ShouldUnload = false;
}
public void Apply((ObjName objName, ObjSlotColor color, UnloadableId id) data)
{
ObjName = data.objName;
Color = data.color;
}
public override string ToString()
{
return string.Format(
"({0},{1},{2}____{3},{4},{5},{6})",
InitialIndex, ObjName, Color,
Timer, BubbleSpawnerMaxTimer, BobombBuddyBlinkingTimer, ShouldUnload);
}
public void Reset()
{
Timer = 0;
BubbleSpawnerMaxTimer = 0;
BobombBuddyBlinkingTimer = 0;
ShouldUnload = false;
}
public void FrameAdvance(RngObjSlotManager rngObjSlotManager, TtcRng rng)
{
if (Color == ObjSlotColor.GREY) return;
switch (ObjName)
{
case ObjName.ARROW_LIFT:
if (Timer == 0)
{
rng.PollRNG();
}
break;
case ObjName.AMP:
if (Timer == 0)
{
rng.PollRNG();
}
break;
case ObjName.BUBBLE_SPAWNER:
if (Timer == 0)
{
BubbleSpawnerMaxTimer = 2 + (int)(9 * rng.PollFloat());
}
if (Timer == BubbleSpawnerMaxTimer)
{
rngObjSlotManager.LoadBubble();
ShouldUnload = true;
}
break;
case ObjName.BUBBLE:
if (Timer == 0)
{
rng.PollRNG(9);
}
else
{
rng.PollRNG(2);
}
break;
case ObjName.BOB_OMB_BUDDY:
if (BobombBuddyBlinkingTimer > 0)
{
BobombBuddyBlinkingTimer = (BobombBuddyBlinkingTimer + 1) % 16;
}
else
{
if (rng.PollRNG() <= 655)
{
BobombBuddyBlinkingTimer++;
}
}
break;
}
Timer++;
}
}
public abstract class ObjSlotManager
{
protected readonly Dictionary> _dictionary;
protected readonly List _colors;
public ObjSlotManager()
{
_dictionary = new Dictionary>();
_colors = EnumUtilities.GetEnumValues(typeof(ObjSlotColor));
foreach (ObjSlotColor color in _colors)
{
_dictionary[color] = new List();
}
}
public void AddToEndOfList(ObjSlot objSlot)
{
_dictionary[objSlot.Color].Add(objSlot);
objSlot.Reset();
}
public void AddToStartOfList(ObjSlot objSlot)
{
_dictionary[objSlot.Color].Insert(0, objSlot);
}
public void UnloadColor(ObjSlotColor color)
{
List listToUnload = _dictionary[color];
while (listToUnload.Count > 0)
{
ObjSlot objSlot = listToUnload[0];
listToUnload.RemoveAt(0);
objSlot.Color = ObjSlotColor.GREY;
AddToStartOfList(objSlot);
}
}
public void Load((ObjName objName, ObjSlotColor color, UnloadableId id) data)
{
List unloadedSlots = _dictionary[ObjSlotColor.GREY];
ObjSlot objSlot = unloadedSlots[0];
unloadedSlots.RemoveAt(0);
objSlot.Apply(data);
AddToEndOfList(objSlot);
PostLoad(data);
}
public abstract void PostLoad((ObjName objName, ObjSlotColor color, UnloadableId id) data);
public void Unload(ObjSlot objSlot)
{
List listToUnloadFrom = _dictionary[objSlot.Color];
listToUnloadFrom.Remove(objSlot);
objSlot.Color = ObjSlotColor.GREY;
AddToStartOfList(objSlot);
}
public abstract void FrameAdvance();
public ObjSlot FindSlot(ObjName objName)
{
foreach (ObjSlotColor color in _colors)
{
foreach (ObjSlot objSlot in _dictionary[color])
{
if (objSlot.ObjName == objName) return objSlot;
}
}
return null;
}
public int GetCurrentSlotIndex(ObjSlot goalObjSlot)
{
int counter = 0;
foreach (ObjSlotColor color in _colors)
{
foreach (ObjSlot objSlot in _dictionary[color])
{
if (objSlot == goalObjSlot) return counter;
counter++;
}
}
return -1;
}
public override string ToString()
{
List strings = new List();
strings.Add(GetFirstLineForToString());
foreach (ObjSlotColor color in _colors)
{
foreach (ObjSlot objSlot in _dictionary[color])
{
strings.Add(objSlot.ToString());
}
}
return string.Join("\r\n", strings);
}
public abstract string GetFirstLineForToString();
}
public class BubbleObjSlotManager : ObjSlotManager
{
private readonly BubbleTracker _bubbleTracker;
private int bubbleSpawnerMaxTimer;
private int bubbleSpawnerTimer;
public BubbleObjSlotManager(BubbleTracker bubbleTracker)
: base()
{
_bubbleTracker = bubbleTracker;
bubbleSpawnerMaxTimer = int.MaxValue;
bubbleSpawnerTimer = 0;
}
public override void PostLoad((ObjName objName, ObjSlotColor color, UnloadableId id) data)
{
if (data.objName == ObjName.BUBBLE_SPAWNER)
{
bubbleSpawnerMaxTimer = _bubbleTracker.GetNextMaxTimer();
bubbleSpawnerTimer = 0;
}
}
public override void FrameAdvance()
{
ObjSlot bubbleSpawner = _dictionary[ObjSlotColor.PURPLE].FirstOrDefault(
objSlot => objSlot.ObjName == ObjName.BUBBLE_SPAWNER);
if (bubbleSpawner == null)
{
Load((ObjName.BUBBLE_SPAWNER, ObjSlotColor.PURPLE, UnloadableId.LOADED_ALWAYS));
bubbleSpawnerTimer++;
}
else
{
bubbleSpawnerTimer++;
if (bubbleSpawnerTimer > bubbleSpawnerMaxTimer)
{
Load((ObjName.BUBBLE, ObjSlotColor.BROWN, UnloadableId.LOADED_ALWAYS));
Unload(bubbleSpawner);
}
}
}
public override string GetFirstLineForToString()
{
return string.Format("timer={0} maxTimer={1}", bubbleSpawnerTimer, bubbleSpawnerMaxTimer);
}
}
public class RngObjSlotManager : ObjSlotManager
{
private readonly TtcRng _rng;
public RngObjSlotManager(TtcRng rng)
: base()
{
_rng = rng;
}
public override void PostLoad((ObjName objName, ObjSlotColor color, UnloadableId id) data)
{
}
public override void FrameAdvance()
{
ObjSlot bubbleSpawner = _dictionary[ObjSlotColor.PURPLE].FirstOrDefault(
objSlot => objSlot.ObjName == ObjName.BUBBLE_SPAWNER);
if (bubbleSpawner == null)
{
Load((ObjName.BUBBLE_SPAWNER, ObjSlotColor.PURPLE, UnloadableId.LOADED_ALWAYS));
}
List objSlotsToUnload = new List();
foreach (ObjSlotColor color in _colors)
{
foreach (ObjSlot objSlot in _dictionary[color])
{
objSlot.FrameAdvance(this, _rng);
if (objSlot.ShouldUnload)
{
objSlotsToUnload.Add(objSlot);
}
}
}
foreach (ObjSlot objSlot in objSlotsToUnload)
{
Unload(objSlot);
}
}
public void LoadBubble()
{
Load((ObjName.BUBBLE, ObjSlotColor.BROWN, UnloadableId.LOADED_ALWAYS));
}
public override string GetFirstLineForToString()
{
return string.Format("index={0} value={1}", _rng.GetIndex(), _rng.GetRng());
}
}
public class FrameTracker
{
private readonly List _loadingZoneFrames;
private bool _isTownLoaded;
public FrameTracker(List loadingZoneFrames)
{
_loadingZoneFrames = new List(loadingZoneFrames);
_isTownLoaded = false;
}
public bool? AdvanceFrame()
{
if (_loadingZoneFrames.Count == 0) return null;
if (_loadingZoneFrames[0] > 1)
{
_loadingZoneFrames[0]--;
return null;
}
else
{
_loadingZoneFrames.RemoveAt(0);
_isTownLoaded = !_isTownLoaded;
return _isTownLoaded;
}
}
}
public class BubbleTracker
{
private readonly List _bubbleSpawnerMaxTimers;
public BubbleTracker(List bubbleSpawnerMaxTimers)
{
_bubbleSpawnerMaxTimers = new List(bubbleSpawnerMaxTimers);
}
public int GetNextMaxTimer()
{
if (_bubbleSpawnerMaxTimers.Count == 0) return int.MaxValue;
int firstValue = _bubbleSpawnerMaxTimers[0];
_bubbleSpawnerMaxTimers.RemoveAt(0);
return firstValue;
}
}
public static List<(ObjName objName, ObjSlotColor color, UnloadableId id)> initialObjData =
new List<(ObjName objName, ObjSlotColor color, UnloadableId id)>()
{
(ObjName.COIN_RING, ObjSlotColor.PINK, UnloadableId.LOADED_ALWAYS),
(ObjName.COIN_LINE, ObjSlotColor.PINK, UnloadableId.LOADED_ALWAYS),
(ObjName.COIN_LINE, ObjSlotColor.PINK, UnloadableId.LOADED_ALWAYS),
(ObjName.SIGN, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.BLUE_COIN_BLOCK, ObjSlotColor.RED, UnloadableId.BLUE_COIN),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CANNON_LID, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.PUSHABLE_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.PUSHABLE_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_EXPRESS_ELEVATOR),
(ObjName.SWITCH, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_EDGE_4),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_EDGE_3),
(ObjName.PUSHABLE_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_BIG),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.ITEM_BLOCK_PENTAGON_PLATFORM),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.ITEM_BLOCK_EXPRESS_ELEVATOR),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_EDGE_2),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.ITEM_BLOCK_SLIDE_KICK),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.ITEM_BLOCK_HIGH_CORNER),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SIGN, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_EDGE_1),
(ObjName.ROTATING_PLATFORM, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.LONG_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.LONG_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.EXPRESS_ELEVATOR, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.EXPRESS_ELEVATOR, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.HIDDEN_WOODEN_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.HIDDEN_WOODEN_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.HIDDEN_WOODEN_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.HIDDEN_WOODEN_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.HIDDEN_WOODEN_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SWITCH, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.ARROW_LIFT, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.ARROW_LIFT, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.ARROW_LIFT, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.ARROW_LIFT, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.ARROW_LIFT, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SHORT_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SHORT_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SHORT_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SHORT_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.MARIO, ObjSlotColor.YORANGE, UnloadableId.LOADED_ALWAYS),
(ObjName.BOB_OMB_BUDDY, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.AMP, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.AMP, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.AMP, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.HEAVE_HO, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.HEAVE_HO, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.CHUCKYA, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.HEAVE_HO, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.AMP, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.AMP, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.SKEETER, ObjSlotColor.GREEN, UnloadableId.SKEETER_FAR),
(ObjName.SKEETER, ObjSlotColor.GREEN, UnloadableId.SKEETER_CLOSE),
(ObjName.HEAVE_HO_ANCHOR, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.HEAVE_HO_ANCHOR, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.CHUCKYA_ANCHOR, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.HEAVE_HO_ANCHOR, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.ONE_UP, ObjSlotColor.BLUE, UnloadableId.ONE_UP_TUNNEL_2),
(ObjName.ONE_UP, ObjSlotColor.BLUE, UnloadableId.ONE_UP_TUNNEL_1),
(ObjName.SECRET, ObjSlotColor.BLUE, UnloadableId.SECRET_EXPRESS_ELEVATOR),
(ObjName.SECRET, ObjSlotColor.BLUE, UnloadableId.SECRET_BLOCK_HOLE),
(ObjName.SECRET, ObjSlotColor.BLUE, UnloadableId.SECRET_PENTAGON_PLATFORM),
(ObjName.SECRET, ObjSlotColor.BLUE, UnloadableId.SECRET_HIGH_CORNER),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.SECRET, ObjSlotColor.BLUE, UnloadableId.SECRET_WATER_BLOCK),
(ObjName.STAR, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.SECRET_STAR_SPAWNER, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.TELEPORTER, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.TELEPORTER, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.WATER_LEVEL_MANAGER, ObjSlotColor.PURPLE, UnloadableId.LOADED_ALWAYS),
(ObjName.MARIO_SPAWNER, ObjSlotColor.PURPLE, UnloadableId.LOADED_ALWAYS),
};
public static List<(ObjName objName, ObjSlotColor color, UnloadableId id)> area1ObjData =
new List<(ObjName objName, ObjSlotColor color, UnloadableId id)>()
{
(ObjName.SIGN, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.BOB_OMB_BUDDY, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.COIN_RING, ObjSlotColor.PINK, UnloadableId.LOADED_ALWAYS),
(ObjName.COIN_LINE, ObjSlotColor.PINK, UnloadableId.LOADED_ALWAYS),
(ObjName.BLUE_COIN_BLOCK, ObjSlotColor.RED, UnloadableId.BLUE_COIN),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.AMP, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.AMP, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.AMP, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.HEAVE_HO, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.HEAVE_HO, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.CANNON_LID, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.PUSHABLE_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.ONE_UP, ObjSlotColor.BLUE, UnloadableId.ONE_UP_TUNNEL_2),
(ObjName.ONE_UP, ObjSlotColor.BLUE, UnloadableId.ONE_UP_TUNNEL_1),
(ObjName.CHUCKYA, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.HEAVE_HO, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.PUSHABLE_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SECRET, ObjSlotColor.BLUE, UnloadableId.SECRET_EXPRESS_ELEVATOR),
(ObjName.SECRET, ObjSlotColor.BLUE, UnloadableId.SECRET_BLOCK_HOLE),
(ObjName.SECRET, ObjSlotColor.BLUE, UnloadableId.SECRET_PENTAGON_PLATFORM),
(ObjName.SECRET, ObjSlotColor.BLUE, UnloadableId.SECRET_HIGH_CORNER),
(ObjName.AMP, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_EXPRESS_ELEVATOR),
(ObjName.SWITCH, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_EDGE_4),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_EDGE_3),
(ObjName.PUSHABLE_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_BIG),
(ObjName.AMP, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.BLUE_COIN, ObjSlotColor.BLUE, UnloadableId.BLUE_COIN),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.ITEM_BLOCK_PENTAGON_PLATFORM),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.ITEM_BLOCK_EXPRESS_ELEVATOR),
(ObjName.SECRET, ObjSlotColor.BLUE, UnloadableId.SECRET_WATER_BLOCK),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_EDGE_2),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.ITEM_BLOCK_SLIDE_KICK),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.ITEM_BLOCK_HIGH_CORNER),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.COIN_LINE, ObjSlotColor.PINK, UnloadableId.LOADED_ALWAYS),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SIGN, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.CORK_BOX_EDGE_1),
(ObjName.SKEETER, ObjSlotColor.GREEN, UnloadableId.SKEETER_FAR),
(ObjName.SKEETER, ObjSlotColor.GREEN, UnloadableId.SKEETER_CLOSE),
(ObjName.ROTATING_PLATFORM, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.LONG_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.LONG_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.EXPRESS_ELEVATOR, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.EXPRESS_ELEVATOR, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.HIDDEN_WOODEN_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.HIDDEN_WOODEN_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.HIDDEN_WOODEN_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.HIDDEN_WOODEN_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.HIDDEN_WOODEN_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SWITCH, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.WATER_LEVEL_MANAGER, ObjSlotColor.PURPLE, UnloadableId.LOADED_ALWAYS),
(ObjName.ARROW_LIFT, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.ARROW_LIFT, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.ARROW_LIFT, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.ARROW_LIFT, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.ARROW_LIFT, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SHORT_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SHORT_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SHORT_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.SHORT_WOODEN_BOARD, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.STAR, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.SECRET_STAR_SPAWNER, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.TELEPORTER, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.TELEPORTER, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.MARIO_SPAWNER, ObjSlotColor.PURPLE, UnloadableId.LOADED_ALWAYS),
(ObjName.BUBBLE_SPAWNER, ObjSlotColor.PURPLE, UnloadableId.LOADED_ALWAYS),
(ObjName.HEAVE_HO_ANCHOR, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.HEAVE_HO_ANCHOR, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.CHUCKYA_ANCHOR, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.HEAVE_HO_ANCHOR, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
};
public static List<(ObjName objName, ObjSlotColor color, UnloadableId id)> area2ObjData =
new List<(ObjName objName, ObjSlotColor color, UnloadableId id)>()
{
(ObjName.TREE, ObjSlotColor.ORANGE, UnloadableId.LOADED_ALWAYS),
(ObjName.TREE, ObjSlotColor.ORANGE, UnloadableId.LOADED_ALWAYS),
(ObjName.RED_COIN, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.RED_COIN, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.RED_COIN, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.RED_COIN, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.RED_COIN, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.RED_COIN, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.RED_COIN, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.RED_COIN, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.COIN_RING, ObjSlotColor.PINK, UnloadableId.LOADED_ALWAYS),
(ObjName.ONE_UP_ACTIVATOR, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.ONE_UP_ACTIVATOR, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.ONE_UP_ACTIVATOR, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.ONE_UP_ACTIVATOR, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.ONE_UP, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.METAL_CAP_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.VANISH_CAP_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.COIN_LINE, ObjSlotColor.PINK, UnloadableId.LOADED_ALWAYS),
(ObjName.SKEETER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.SKEETER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.SWITCH, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.VANISH_CAP_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.FIRE_SPITTER, ObjSlotColor.GREEN, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX_RED_ROOF, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX_WHITE_BUILDING, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CORK_BOX, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.COIN_LINE, ObjSlotColor.PINK, UnloadableId.LOADED_ALWAYS),
(ObjName.COIN_LINE, ObjSlotColor.PINK, UnloadableId.LOADED_ALWAYS),
(ObjName.ITEM_BLOCK, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.POLE, ObjSlotColor.ORANGE, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.CRYSTAL_TAP, ObjSlotColor.RED, UnloadableId.LOADED_ALWAYS),
(ObjName.WATER_LEVEL_MANAGER, ObjSlotColor.PURPLE, UnloadableId.LOADED_ALWAYS),
(ObjName.STAR, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.RED_COIN_STAR_SPAWNER, ObjSlotColor.BLUE, UnloadableId.LOADED_ALWAYS),
(ObjName.BUBBLE_SPAWNER, ObjSlotColor.PURPLE, UnloadableId.LOADED_ALWAYS),
(ObjName.STAR_MARKER, ObjSlotColor.PURPLE, UnloadableId.LOADED_ALWAYS),
};
}
}
================================================
FILE: STROOP/Calculators/MarioState.cs
================================================
using STROOP.Forms;
using STROOP.Managers;
using STROOP.Structs.Configurations;
using STROOP.Utilities;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace STROOP.Structs
{
public class MarioState
{
public readonly float X;
public readonly float Y;
public readonly float Z;
public readonly float XSpeed;
public readonly float YSpeed;
public readonly float ZSpeed;
public readonly float HSpeed;
public readonly float SlidingSpeedX;
public readonly float SlidingSpeedZ;
public readonly ushort SlidingAngle;
public readonly ushort MarioAngle;
public readonly ushort CameraAngle;
public readonly MarioState PreviousState;
public readonly Input LastInput;
public readonly int Index;
public MarioState(
float x, float y, float z,
float xSpeed, float ySpeed, float zSpeed, float hSpeed,
float slidingSpeedX, float slidingSpeedZ, ushort slidingAngle,
ushort marioAngle, ushort cameraAngle,
MarioState previousState, Input lastInput, int index)
{
X = x;
Y = y;
Z = z;
XSpeed = xSpeed;
YSpeed = ySpeed;
ZSpeed = zSpeed;
HSpeed = hSpeed;
SlidingSpeedX = slidingSpeedX;
SlidingSpeedZ = slidingSpeedZ;
SlidingAngle = slidingAngle;
MarioAngle = marioAngle;
CameraAngle = cameraAngle;
PreviousState = previousState;
LastInput = lastInput;
Index = index;
}
public static MarioState CreateMarioState()
{
return new MarioState(
x: Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.XOffset),
y: Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.YOffset),
z: Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.ZOffset),
xSpeed: Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.XSpeedOffset),
ySpeed: Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.YSpeedOffset),
zSpeed: Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.ZSpeedOffset),
hSpeed: Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.HSpeedOffset),
slidingSpeedX: Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.SlidingSpeedXOffset),
slidingSpeedZ: Config.Stream.GetFloat(MarioConfig.StructAddress + MarioConfig.SlidingSpeedZOffset),
slidingAngle: Config.Stream.GetUShort(MarioConfig.StructAddress + MarioConfig.SlidingYawOffset),
marioAngle: Config.Stream.GetUShort(MarioConfig.StructAddress + MarioConfig.FacingYawOffset),
cameraAngle: Config.Stream.GetUShort(CameraConfig.StructAddress + CameraConfig.CentripetalAngleOffset),
previousState: null,
lastInput: null,
index: 0);
}
public MutableMarioState GetMutableMarioState(Input input)
{
return new MutableMarioState(
X, Y, Z,
XSpeed, YSpeed, ZSpeed, HSpeed,
SlidingSpeedX, SlidingSpeedZ, SlidingAngle,
MarioAngle, CameraAngle, input);
}
public MutableMarioState GetMutableMarioState(int angleDiff)
{
return new MutableMarioState(
X, Y, Z,
XSpeed, YSpeed, ZSpeed, HSpeed,
SlidingSpeedX, SlidingSpeedZ, SlidingAngle,
MarioAngle, angleDiff);
}
public override string ToString()
{
return String.Format(
"pos=({0},{1},{2}) spd=({3},{4},{5}) slide=({6},{7}) slideAngle={8} hspd={9} angle={10}",
(double)X, (double)Y, (double)Z,
(double)XSpeed, (double)YSpeed, (double)ZSpeed,
(double)SlidingSpeedX, (double)SlidingSpeedZ, SlidingAngle,
(double)HSpeed, MarioAngle);
}
public string ToStringWithInput()
{
string inputString = LastInput != null ? LastInput + " to " : "";
return inputString + ToString();
}
private List