From 2bd6f60ebc2ca30b453015815e6d43e572a61928 Mon Sep 17 00:00:00 2001 From: Axanery <41282531+Axanery@users.noreply.github.com> Date: Fri, 22 Dec 2023 02:22:37 -0600 Subject: [PATCH 01/23] Add Animator, View, Draw Functions --- guides/Documentation.htm | 77 +++++++++++++- source/Engine/Application.cpp | 10 +- source/Engine/Bytecode/Compiler.cpp | 2 +- source/Engine/Bytecode/StandardLibrary.cpp | 112 ++++++++++++++++++++- source/Engine/Scene.cpp | 2 +- 5 files changed, 194 insertions(+), 9 deletions(-) diff --git a/guides/Documentation.htm b/guides/Documentation.htm index af760d2f..b889433f 100644 --- a/guides/Documentation.htm +++ b/guides/Documentation.htm @@ -158,6 +158,7 @@

Animator

Class methods:

+

+

View.AdjustX

+ View.AdjustX(viewInde, ) +
Adjusts the x - axis position of the camera for the specified view by an amount.
+
Parameters:
+ +

+

+

View.AdjustY

+ View.AdjustY(viewIndex, y) +
Adjusts the y-axis position of the camera for the specified view by an amount.
+
Parameters:
+ +

+

+

View.AdjustX

+ View.AdjustX(viewIndex, z) +
Adjusts the z-axis position of the camera for the specified view by an amount.
+
Parameters:
+ +

View.SetAngle

View.SetAngle(viewIndex, x, y, z) @@ -8962,7 +9037,7 @@

XML.Parse

Returns:
Returns a Map value if the text can be decoded, otherwise returns null.

-

661 out of 720 functions have descriptions.

+

669 out of 728 functions have descriptions.


Instance methods

diff --git a/source/Engine/Application.cpp b/source/Engine/Application.cpp index 5935773b..b4ad77e6 100644 --- a/source/Engine/Application.cpp +++ b/source/Engine/Application.cpp @@ -1408,7 +1408,7 @@ PUBLIC STATIC void Application::LoadSceneInfo() { if (stgElement->attributes.Exists("folder")) XMLParser::CopyTokenToString(stgElement->attributes.Get("folder"), scene.folder, sizeof(scene.folder)); else - // Accounts for scenes placed in the root of the Scenes folder if the file type is not "bin" + // Accounts for scenes placed in the root of the Scenes folder scene.folder[0] = '\0'; if (stgElement->attributes.Exists("id")) @@ -1426,6 +1426,14 @@ PUBLIC STATIC void Application::LoadSceneInfo() { else snprintf(scene.fileType, sizeof(scene.fileType), "bin"); + if (stgElement->attributes.Exists("filter")) + Scene::Filter = XMLParser::TokenToNumber(stgElement->attributes.Get("filter")); + else + Scene::Filter = 0xFF; + if (Scene::Filter == 0x00) + Scene::Filter = 0xFF; + + Scene::ListData.push_back(scene); category.sceneCount++; Scene::StageCount++; diff --git a/source/Engine/Bytecode/Compiler.cpp b/source/Engine/Bytecode/Compiler.cpp index 0f177b92..435087b3 100644 --- a/source/Engine/Bytecode/Compiler.cpp +++ b/source/Engine/Bytecode/Compiler.cpp @@ -1441,7 +1441,7 @@ PUBLIC void Compiler::GetUnary(bool canAssign) { case TOKEN_LOGICAL_NOT: EmitByte(OP_LG_NOT); break; case TOKEN_TYPEOF: EmitByte(OP_TYPEOF); break; - // HACK: replace these with prefix version of OP + // TODO: replace these with prefix version of OP // case TOKEN_INCREMENT: EmitByte(OP_INCREMENT); break; // case TOKEN_DECREMENT: EmitByte(OP_DECREMENT); break; default: diff --git a/source/Engine/Bytecode/StandardLibrary.cpp b/source/Engine/Bytecode/StandardLibrary.cpp index d6c27875..35925cb2 100644 --- a/source/Engine/Bytecode/StandardLibrary.cpp +++ b/source/Engine/Bytecode/StandardLibrary.cpp @@ -469,6 +469,21 @@ VMValue Animator_Create(int argCount, VMValue* args, Uint32 threadID) { return INTEGER_VAL((int)index); } +/*** + * Animator.Remove + * \desc Removes an animator. + * \param animator (Integer): The index of the animator. + * \ns Animator + */ +VMValue Animator_Remove(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(1); + int animator = GET_ARG(0, GetInteger); + if (!Scene::AnimatorList[animator]) + return NULL_VAL; + delete Scene::AnimatorList[animator]; + Scene::AnimatorList[animator] = NULL; + return NULL_VAL; +} /*** * Animator.SetAnimation * \desc Sets the current animation and frame of an animator. @@ -4578,7 +4593,8 @@ VMValue Draw_UseStrokeSmoothing(int argCount, VMValue* args, Uint32 threadID) { */ VMValue Draw_SetClip(int argCount, VMValue* args, Uint32 threadID) { CHECK_ARGCOUNT(4); - Graphics::SetClip((int)GET_ARG(0, GetDecimal), (int)GET_ARG(1, GetDecimal), (int)GET_ARG(2, GetDecimal), (int)GET_ARG(3, GetDecimal)); + if (GET_ARG(2, GetDecimal) > 0.0 && GET_ARG(3, GetDecimal) > 0.0) + Graphics::SetClip((int)GET_ARG(0, GetDecimal), (int)GET_ARG(1, GetDecimal), (int)GET_ARG(2, GetDecimal), (int)GET_ARG(3, GetDecimal)); return NULL_VAL; } /*** @@ -4591,6 +4607,46 @@ VMValue Draw_ClearClip(int argCount, VMValue* args, Uint32 threadID) { Graphics::ClearClip(); return NULL_VAL; } +/*** + * Draw.GetClipX + * \desc Gets the X position in which drawing starts to occur. + * \return The X position if clipping is enabled, else 0. + * \ns Draw + */ +VMValue Draw_GetClipX(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(0); + return Graphics::CurrentClip.Enabled ? INTEGER_VAL((int)Graphics::CurrentClip.X) : INTEGER_VAL(0); +} +/*** + * Draw.GetClipY + * \desc Gets the Y position in which drawing starts to occur. + * \return The Y position if clipping is enabled, else 0. + * \ns Draw + */ +VMValue Draw_GetClipY(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(0); + return Graphics::CurrentClip.Enabled ? INTEGER_VAL((int)Graphics::CurrentClip.Y) : INTEGER_VAL(0); +} +/*** + * Draw.GetClipWidth + * \desc Gets the width in which drawing occurs. + * \return The width if clipping is enabled, else 0. + * \ns Draw + */ +VMValue Draw_GetClipWidth(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(0); + return Graphics::CurrentClip.Enabled ? INTEGER_VAL((int)Graphics::CurrentClip.Width) : INTEGER_VAL(0); +} +/*** + * Draw.GetClipHeight + * \desc Gets the height in which drawing occurs. + * \return The height if clipping is enabled, else 0. + * \ns Draw + */ +VMValue Draw_GetClipHeight(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(0); + return Graphics::CurrentClip.Enabled ? INTEGER_VAL((int)Graphics::CurrentClip.Height) : INTEGER_VAL(0); +} /*** * Draw.Save @@ -8443,8 +8499,8 @@ VMValue Scene_ObjectTileCollision(int argCount, VMValue* args, Uint32 threadID) int cLayers = GET_ARG(1, GetInteger); int cMode = GET_ARG(2, GetInteger); int cPlane = GET_ARG(3, GetInteger); - int xOffset = GET_ARG(4, GetDecimal); - int yOffset = GET_ARG(5, GetDecimal); + int xOffset = (int)GET_ARG(4, GetDecimal); + int yOffset = (int)GET_ARG(5, GetDecimal); int setPos = GET_ARG(6, GetInteger); auto ent = (Entity*)entity->EntityPtr; @@ -8470,8 +8526,8 @@ VMValue Scene_ObjectTileGrip(int argCount, VMValue* args, Uint32 threadID) { int cLayers = GET_ARG(1, GetInteger); int cMode = GET_ARG(2, GetInteger); int cPlane = GET_ARG(3, GetInteger); - float xOffset = GET_ARG(4, GetDecimal); - float yOffset = GET_ARG(5, GetDecimal); + int xOffset = (int)GET_ARG(4, GetDecimal); + int yOffset = (int)GET_ARG(5, GetDecimal); float tolerance = GET_ARG(6, GetDecimal); auto ent = (Entity*)entity->EntityPtr; @@ -13642,6 +13698,48 @@ VMValue View_SetPosition(int argCount, VMValue* args, Uint32 threadID) { Scene::Views[view_index].Z = GET_ARG(3, GetDecimal); return NULL_VAL; } +/*** +* View.AdjustX +* \desc Adjusts the x - axis position of the camera for the specified view by an amount. +* \param viewIndex(Integer) : Index of the view. +* \param x(Number) : Desired X adjust amount. +* \ns View +*/ +VMValue View_AdjustX(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(2); + int view_index = GET_ARG(0, GetInteger); + CHECK_VIEW_INDEX(); + Scene::Views[view_index].X += GET_ARG(1, GetDecimal); + return NULL_VAL; +} +/*** +* View.AdjustY +* \desc Adjusts the y-axis position of the camera for the specified view by an amount. +* \param viewIndex (Integer): Index of the view. +* \param y (Number): Desired Y adjust amount. +* \ns View +*/ +VMValue View_AdjustY(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(2); + int view_index = GET_ARG(0, GetInteger); + CHECK_VIEW_INDEX(); + Scene::Views[view_index].Y += GET_ARG(1, GetDecimal); + return NULL_VAL; +} +/*** +* View.AdjustX +* \desc Adjusts the z-axis position of the camera for the specified view by an amount. +* \param viewIndex (Integer): Index of the view. +* \param z (Number): Desired Z adjust amount. +* \ns View +*/ +VMValue View_AdjustZ(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(2); + int view_index = GET_ARG(0, GetInteger); + CHECK_VIEW_INDEX(); + Scene::Views[view_index].Z += GET_ARG(1, GetDecimal); + return NULL_VAL; +} /*** * View.SetAngle * \desc Sets the angle of the camera for the specified view. @@ -14395,6 +14493,7 @@ PUBLIC STATIC void StandardLibrary::Link() { // #region Animator INIT_CLASS(Animator); DEF_NATIVE(Animator, Create); + DEF_NATIVE(Animator, Remove); DEF_NATIVE(Animator, SetAnimation); DEF_NATIVE(Animator, Animate); DEF_NATIVE(Animator, GetSprite); @@ -16202,6 +16301,9 @@ PUBLIC STATIC void StandardLibrary::Link() { DEF_NATIVE(View, SetY); DEF_NATIVE(View, SetZ); DEF_NATIVE(View, SetPosition); + DEF_NATIVE(View, AdjustX); + DEF_NATIVE(View, AdjustY); + DEF_NATIVE(View, AdjustZ); DEF_NATIVE(View, SetAngle); DEF_NATIVE(View, SetSize); DEF_NATIVE(View, SetOutputX); diff --git a/source/Engine/Scene.cpp b/source/Engine/Scene.cpp index d25b78b2..4f6bfe5c 100644 --- a/source/Engine/Scene.cpp +++ b/source/Engine/Scene.cpp @@ -3572,7 +3572,7 @@ PUBLIC STATIC bool Scene::ObjectTileCollision(Entity* entity, int cLayers, int c } } -PUBLIC STATIC bool Scene::ObjectTileGrip(Entity* entity, int cLayers, int cMode, int cPlane, float xOffset, float yOffset, float tolerance) { +PUBLIC STATIC bool Scene::ObjectTileGrip(Entity* entity, int cLayers, int cMode, int cPlane, int xOffset, int yOffset, float tolerance) { int layerID = 1; bool collided = false; int posX = xOffset + entity->X; From c254d6b6b929ae5a3f9ee02cd4633ca25b6a452a Mon Sep 17 00:00:00 2001 From: Axanery <41282531+Axanery@users.noreply.github.com> Date: Fri, 22 Dec 2023 02:37:05 -0600 Subject: [PATCH 02/23] Add Draw methods to definitions --- source/Engine/Bytecode/StandardLibrary.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/Engine/Bytecode/StandardLibrary.cpp b/source/Engine/Bytecode/StandardLibrary.cpp index ae0a1e69..e7963d40 100644 --- a/source/Engine/Bytecode/StandardLibrary.cpp +++ b/source/Engine/Bytecode/StandardLibrary.cpp @@ -15193,6 +15193,10 @@ PUBLIC STATIC void StandardLibrary::Link() { DEF_NATIVE(Draw, UseStrokeSmoothing); DEF_NATIVE(Draw, SetClip); DEF_NATIVE(Draw, ClearClip); + DEF_NATIVE(Draw, GetClipX); + DEF_NATIVE(Draw, GetClipY); + DEF_NATIVE(Draw, GetClipWidth); + DEF_NATIVE(Draw, GetClipHeight); DEF_NATIVE(Draw, Save); DEF_NATIVE(Draw, Scale); DEF_NATIVE(Draw, Rotate); From 69685dbd57195a6c26495b29829638f10891257e Mon Sep 17 00:00:00 2001 From: Axanery <41282531+Axanery@users.noreply.github.com> Date: Thu, 29 Feb 2024 02:47:52 -0500 Subject: [PATCH 03/23] Fix documentation --- guides/Documentation.htm | 1344 ++++++++++++++++---------------------- 1 file changed, 577 insertions(+), 767 deletions(-) diff --git a/guides/Documentation.htm b/guides/Documentation.htm index deff94ff..a4679101 100644 --- a/guides/Documentation.htm +++ b/guides/Documentation.htm @@ -72,9 +72,12 @@

Namespaces

  • Number
  • Object
  • Palette
  • +
  • RSDK.Math
  • +
  • RSDK.Matrix
  • Resources
  • Scene
  • Scene3D
  • +
  • SceneList
  • Serializer
  • Settings
  • Shader
  • @@ -126,7 +129,9 @@

    Enums

  • StencilOp_*
  • StencilTest_*
  • TILECOLLISION_*
  • +
  • TimeOfDay_*
  • TintMode_*
  • +
  • Weekday_*
  • Constants

    @@ -748,15 +709,6 @@

    Matrix

  • Matrix.Translate
  • Matrix.Scale
  • Matrix.Rotate
  • -
  • Matrix.Create256
  • -
  • Matrix.Identity256
  • -
  • Matrix.Multiply256
  • -
  • Matrix.Translate256
  • -
  • Matrix.Scale256
  • -
  • Matrix.RotateX256
  • -
  • Matrix.RotateY256
  • -
  • Matrix.RotateZ256
  • -
  • Matrix.Rotate256
  • @@ -832,6 +784,44 @@

    Palette

  • Palette.SetPaletteIndexLines
  • +

    +

    RSDK.Math

    + Class methods: + +

    +

    +

    RSDK.Matrix

    + Class methods: + +

    Resources

    Class methods: @@ -886,6 +876,8 @@

    Scene

  • Scene.GetLayerOffsetX
  • Scene.GetLayerOffsetY
  • Scene.GetLayerDrawGroup
  • +
  • Scene.GetLayerHorizontalRepeat
  • +
  • Scene.GetLayerVerticalRepeat
  • Scene.GetTilesetCount
  • Scene.GetTilesetIndex
  • Scene.GetTilesetName
  • @@ -894,7 +886,6 @@

    Scene

  • Scene.GetTilesetPaletteIndex
  • Scene.GetTileWidth
  • Scene.GetTileHeight
  • -
  • Scene.GetTileSize
  • Scene.GetTileID
  • Scene.GetTileFlipX
  • Scene.GetTileFlipY
  • @@ -947,6 +938,8 @@

    Scene

  • Scene.SetLayerDrawGroup
  • Scene.SetLayerDrawBehavior
  • Scene.SetLayerRepeat
  • +
  • Scene.SetLayerHorizontalRepeat
  • +
  • Scene.SetLayerVerticalRepeat
  • Scene.SetDrawGroupCount
  • Scene.SetDrawGroupEntityDepthSorting
  • Scene.SetLayerBlend
  • @@ -994,6 +987,23 @@

    Scene3D

  • Scene3D.Clear
  • +

    +

    SceneList

    + Class methods: + +

    Serializer

    Class methods: @@ -1093,6 +1103,8 @@

    Sprite

  • Sprite.GetFrameOffsetX
  • Sprite.GetFrameOffsetY
  • Sprite.GetFrameHitbox
  • +
  • Sprite.MakePalettized
  • +
  • Sprite.MakeNonPalettized
  • @@ -1332,13 +1344,14 @@

    Instance

  • instance.SetAnimation
  • instance.ResetAnimation
  • instance.Animate
  • +
  • instance.GetIDWithinClass
  • instance.AddToRegistry
  • instance.RemoveFromRegistry
  • instance.ApplyMotion
  • instance.InView
  • instance.CollidedWithObject
  • instance.GetHitboxFromSprite
  • -
  • instance.GetHitboxFromSprite
  • +
  • instance.ReturnHitboxFromSprite
  • instance.CollideWithObject
  • instance.SolidCollideWithObject
  • instance.TopSolidCollideWithObject
  • @@ -1406,6 +1419,10 @@

    Instance

  • instance.HitboxH
  • instance.HitboxOffX
  • instance.HitboxOffY
  • +
  • instance.HitboxLeft
  • +
  • instance.HitboxTop
  • +
  • instance.HitboxRight
  • +
  • instance.HitboxBottom
  • instance.FlipFlag
  • instance.VelocityX
  • instance.VelocityX
  • @@ -1736,6 +1753,15 @@

    TILECOLLISION_*

  • TILECOLLISION_UP
  • +

    +

    TimeOfDay_*

    + +

    TintMode_*

    +

    +

    Weekday_*

    + +

    Constants

    Globals


    @@ -2008,6 +2046,48 @@

    Animator.AdjustDuration

  • amount (Integer): The amount to adjust the animator's duration.
  • +

    +

    Application.GetEngineVersionString

    + Application.GetEngineVersionString() +
    Gets the engine version string.
    +
    Returns:
    +
    Returns a String value.
    +

    +

    +

    Application.GetEngineVersionMajor

    + Application.GetEngineVersionMajor() +
    Gets the major engine version.
    +
    Returns:
    +
    Returns an Integer value.
    +

    +

    +

    Application.GetEngineVersionMinor

    + Application.GetEngineVersionMinor() +
    Gets the minor engine version.
    +
    Returns:
    +
    Returns an Integer value.
    +

    +

    +

    Application.GetEngineVersionPatch

    + Application.GetEngineVersionPatch() +
    Gets the minor engine version.
    +
    Returns:
    +
    Returns an Integer value.
    +

    +

    +

    Application.GetEngineVersionPrerelease

    + Application.GetEngineVersionPrerelease() +
    Gets the prerelease engine version.
    +
    Returns:
    +
    Returns a String value, or null.
    +

    +

    +

    Application.GetEngineVersionCodename

    + Application.GetEngineVersionCodename() +
    Gets the engine version codename.
    +
    Returns:
    +
    Returns a String value, or null.
    +

    Application.GetFPS

    Application.GetFPS() @@ -2051,20 +2131,20 @@

    Application.GetGameTitleShort

    Application.GetGameTitleShort()
    Gets the short game title of the application.

    -

    -

    Application.GetVersion

    - Application.GetVersion() +

    +

    Application.GetGameVersion

    + Application.GetGameVersion()
    Gets the version of the application.

    -

    -

    Application.GetDescription

    - Application.GetDescription() -
    Gets the description of the application.
    +

    +

    Application.GetGameDescription

    + Application.GetGameDescription() +
    Gets the description of the game.

    Application.SetGameTitle

    Application.SetGameTitle(title) -
    Sets the game title of the application.
    +
    Sets the title of the game.
    Parameters:

    -

    -

    Weekday_*

    +

    +

    WEEKDAY_*

    Constants

    @@ -6528,7 +6526,7 @@

    Scene.GetDrawGroupEntityDepthSorting

    Scene.GetListPos

    Scene.GetListPos() -
    Gets the current list position of the scene. (Deprecated)
    +
    Gets the current list position of the scene.
    Returns:
    Returns an Integer value.

    @@ -6567,20 +6565,6 @@

    Scene.GetActiveCategory

    Returns:
    Returns an Integer value.

    -

    -

    Scene.GetCategoryCount

    - Scene.GetCategoryCount() -
    Gets the amount of categories in the scene list. (Deprecated; use SceneList.GetCategoryCount instead.)
    -
    Returns:
    -
    Returns an Integer value.
    -

    -

    -

    Scene.GetStageCount

    - Scene.GetStageCount() -
    Gets the amount of stages in the scene list. (Deprecated; use SceneList.GetSceneCount instead.)
    -
    Returns:
    -
    Returns an Integer value.
    -

    Scene.GetDebugMode

    Scene.GetDebugMode() @@ -6688,14 +6672,14 @@

    Scene.GetTileAnimSequenceFrame

    Scene.CheckValidScene

    Scene.CheckValidScene() -
    Checks whether the scene list's position is within the list's size, if a scene list is loaded. (Deprecated)
    +
    Checks whether the scene list's position is within the list's size, if a scene list is loaded.
    Returns:
    Returns a Boolean value.

    Scene.CheckSceneFolder

    Scene.CheckSceneFolder(folder) -
    Checks whether the current scene's folder matches the string to check, if a scene list is loaded. (Deprecated)
    +
    Checks whether the current scene's folder matches the string to check, if a scene list is loaded.
    Parameters:

    +

    +

    instance.ReturnHitboxFromSprite

    + instance.ReturnHitboxFromSprite(sprite, animation, frame, hitbox) +
    Gets the hitbox in the specified sprite's animation, frame and hitbox ID.
    +
    Parameters:
    + +
    Returns:
    +
    Returns an array containing the hitbox top, left, right and bottom sides in that order.
    +

    instance.CollideWithObject

    instance.CollideWithObject(other) @@ -9726,7 +9874,7 @@

    instance.StopAllSounds

    instance.StopAllSounds()
    Stops all sounds the entity is playing.

    -

    24 out of 24 methods have descriptions.

    +

    25 out of 25 methods have descriptions.


    Instance fields

    @@ -9816,6 +9964,12 @@

    instance.Alpha

    Default: 0.0
    A field that may be used in instance.Render for changing the opacity of a sprite.

    +

    +

    instance.BlendMode

    +
    Type: Integer
    +
    Default: BlendMode_NORMAL
    +
    A field that may be used in instance.Render for changing the BlendMode of a sprite.
    +

    instance.Priority

    Type: Integer
    @@ -10184,7 +10338,7 @@

    instance.Persistence

    Default: Persistence_NONE
    Whether the entity persists between scenes.

    -

    73 out of 77 fields have descriptions.

    +

    74 out of 78 fields have descriptions.


    Enums

    diff --git a/source/Engine/Bytecode/ScriptEntity.cpp b/source/Engine/Bytecode/ScriptEntity.cpp index bcd8073a..4a8ac750 100644 --- a/source/Engine/Bytecode/ScriptEntity.cpp +++ b/source/Engine/Bytecode/ScriptEntity.cpp @@ -194,6 +194,14 @@ PUBLIC void ScriptEntity::LinkFields() { */ LINK_DEC(Alpha); /*** + * \field BlendMode + * \type Integer + * \default BlendMode_NORMAL + * \ns Instance + * \desc A field that may be used in for changing the BlendMode of a sprite. + */ + LINK_INT(BlendMode); + /*** * \field Priority * \type Integer * \default 0 diff --git a/source/Engine/Bytecode/StandardLibrary.cpp b/source/Engine/Bytecode/StandardLibrary.cpp index ab8ce491..8ee5120a 100644 --- a/source/Engine/Bytecode/StandardLibrary.cpp +++ b/source/Engine/Bytecode/StandardLibrary.cpp @@ -1105,93 +1105,6 @@ VMValue Application_GetCursorVisible(int argCount, VMValue* args, Uint32 threadI } // #endregion -// #region Audio -/*** - * Audio.GetMasterVolume - * \desc Gets the master volume of the audio mixer. - * \return The master volume, from 0 to 100. - * \ns Audio - */ -VMValue Audio_GetMasterVolume(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(0); - return INTEGER_VAL(Application::MasterVolume); -} -/*** - * Audio.GetMusicVolume - * \desc Gets the music volume of the audio mixer. - * \return The music volume, from 0 to 100. - * \ns Audio - */ -VMValue Audio_GetMusicVolume(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(0); - return INTEGER_VAL(Application::MusicVolume); -} -/*** - * Audio.GetSoundVolume - * \desc Gets the sound effect volume of the audio mixer. - * \return The sound effect volume, from 0 to 100. - * \ns Audio - */ -VMValue Audio_GetSoundVolume(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(0); - return INTEGER_VAL(Application::SoundVolume); -} -/*** - * Audio.SetMasterVolume - * \desc Sets the master volume of the audio mixer. - * \param volume (Integer): The master volume, from 0 to 100. - * \ns Audio - */ -VMValue Audio_SetMasterVolume(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(1); - int volume = GET_ARG(0, GetInteger); - if (volume < 0) { - THROW_ERROR("Volume cannot be lower than 0."); - } else if (volume > 100) { - THROW_ERROR("Volume cannot be higher than 100."); - } else - Application::SetMasterVolume(volume); - - return NULL_VAL; -} -/*** - * Audio.SetMusicVolume - * \desc Sets the music volume of the audio mixer. - * \param volume (Integer): The music volume, from 0 to 100. - * \ns Audio - */ -VMValue Audio_SetMusicVolume(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(1); - int volume = GET_ARG(0, GetInteger); - if (volume < 0) { - THROW_ERROR("Volume cannot be lower than 0."); - } else if (volume > 100) { - THROW_ERROR("Volume cannot be higher than 100."); - } else - Application::SetMusicVolume(volume); - - return NULL_VAL; -} -/*** - * Audio.SetSoundVolume - * \desc Sets the sound effect volume of the audio mixer. - * \param volume (Integer): The sound effect volume, from 0 to 100. - * \ns Audio - */ -VMValue Audio_SetSoundVolume(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(1); - int volume = GET_ARG(0, GetInteger); - if (volume < 0) { - THROW_ERROR("Volume cannot be lower than 0."); - } else if (volume > 100) { - THROW_ERROR("Volume cannot be higher than 100."); - } else - Application::SetSoundVolume(volume); - - return NULL_VAL; -} -// #endregion - // #region Array /*** * Array.Create @@ -1455,8 +1368,9 @@ VMValue Array_Sort(int argCount, VMValue* args, Uint32 threadID) { return AS_INTEGER(result) == 1; return false; - }); - } else { + }); + } + else { std::stable_sort(array->Values->begin(), array->Values->end(), [array](const VMValue& a, const VMValue& b) { if (IS_NOT_NUMBER(a) || IS_NOT_NUMBER(b)) { return false; @@ -1467,7 +1381,7 @@ VMValue Array_Sort(int argCount, VMValue* args, Uint32 threadID) { else { return AS_INTEGER(a) < AS_INTEGER(b); } - }); + }); } ScriptManager::Unlock(); @@ -1476,6 +1390,316 @@ VMValue Array_Sort(int argCount, VMValue* args, Uint32 threadID) { } // #endregion +// #region Audio +/*** + * Audio.GetMasterVolume + * \desc Gets the master volume of the audio mixer. + * \return The master volume, from 0 to 100. + * \ns Audio + */ +VMValue Audio_GetMasterVolume(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(0); + return INTEGER_VAL(Application::MasterVolume); +} +/*** + * Audio.GetMusicVolume + * \desc Gets the music volume of the audio mixer. + * \return The music volume, from 0 to 100. + * \ns Audio + */ +VMValue Audio_GetMusicVolume(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(0); + return INTEGER_VAL(Application::MusicVolume); +} +/*** + * Audio.GetSoundVolume + * \desc Gets the sound effect volume of the audio mixer. + * \return The sound effect volume, from 0 to 100. + * \ns Audio + */ +VMValue Audio_GetSoundVolume(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(0); + return INTEGER_VAL(Application::SoundVolume); +} +/*** + * Audio.SetMasterVolume + * \desc Sets the master volume of the audio mixer. + * \param volume (Integer): The master volume, from 0 to 100. + * \ns Audio + */ +VMValue Audio_SetMasterVolume(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(1); + int volume = GET_ARG(0, GetInteger); + if (volume < 0) { + THROW_ERROR("Volume cannot be lower than 0."); + } else if (volume > 100) { + THROW_ERROR("Volume cannot be higher than 100."); + } else + Application::SetMasterVolume(volume); + + return NULL_VAL; +} +/*** + * Audio.SetMusicVolume + * \desc Sets the music volume of the audio mixer. + * \param volume (Integer): The music volume, from 0 to 100. + * \ns Audio + */ +VMValue Audio_SetMusicVolume(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(1); + int volume = GET_ARG(0, GetInteger); + if (volume < 0) { + THROW_ERROR("Volume cannot be lower than 0."); + } else if (volume > 100) { + THROW_ERROR("Volume cannot be higher than 100."); + } else + Application::SetMusicVolume(volume); + + return NULL_VAL; +} +/*** + * Audio.SetSoundVolume + * \desc Sets the sound effect volume of the audio mixer. + * \param volume (Integer): The sound effect volume, from 0 to 100. + * \ns Audio + */ +VMValue Audio_SetSoundVolume(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(1); + int volume = GET_ARG(0, GetInteger); + if (volume < 0) { + THROW_ERROR("Volume cannot be lower than 0."); + } else if (volume > 100) { + THROW_ERROR("Volume cannot be higher than 100."); + } else + Application::SetSoundVolume(volume); + + return NULL_VAL; +} +// #endregion + +// #region Collision +/*** + * Collision.ProcessObjectMovement + * \desc Processes movement of an instance with an outer hitbox and an inner hitbox. + * \param entity (Instance): The instance to move. + * \param outer (Array): Array containing the outer hitbox. + * \param inner (Array): Array containing the inner hitbox. + * \ns Collision + */ +VMValue Collision_ProcessObjectMovement(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(3); + ObjInstance* entity = GET_ARG(0, GetInstance); + ObjArray* outer = GET_ARG(1, GetArray); + ObjArray* inner = GET_ARG(2, GetArray); + + CollisionBox outerBox; + CollisionBox innerBox; + + if (entity && outer && inner) { + auto ent = (Entity*)entity->EntityPtr; + + outerBox.Left = AS_INTEGER(ScriptManager::CastValueAsInteger((*outer->Values)[0])); + outerBox.Top = AS_INTEGER(ScriptManager::CastValueAsInteger((*outer->Values)[1])); + outerBox.Right = AS_INTEGER(ScriptManager::CastValueAsInteger((*outer->Values)[2])); + outerBox.Bottom = AS_INTEGER(ScriptManager::CastValueAsInteger((*outer->Values)[3])); + + innerBox.Left = AS_INTEGER(ScriptManager::CastValueAsInteger((*inner->Values)[0])); + innerBox.Top = AS_INTEGER(ScriptManager::CastValueAsInteger((*inner->Values)[1])); + innerBox.Right = AS_INTEGER(ScriptManager::CastValueAsInteger((*inner->Values)[2])); + innerBox.Bottom = AS_INTEGER(ScriptManager::CastValueAsInteger((*inner->Values)[3])); + + Scene::ProcessObjectMovement(ent, &outerBox, &innerBox); + } + return NULL_VAL; +} +/*** + * Collision.ObjectTileCollision + * \desc Checks tile collision based on where an instance should check. + * \param entity (Instance): The instance to base the values on. + * \param cLayers (Bitfield): Which layers the entity can collide with. + * \param cMode (Integer): Collision mode of the entity (floor, left wall, roof, right wall). + * \param cPlane (Integer): Collision plane to get the collision of (A or B). + * \param xOffset (Number): How far from the entity's X value to start from. + * \param yOffset (Number): How far from the entity's Y value to start from. + * \param setPos (Boolean): Whether to set the entity's position if collision is found. + * \return Returns whether the instance has collided with a tile. + * \ns Collision + */ +VMValue Collision_ObjectTileCollision(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(7); + ObjInstance* entity = GET_ARG(0, GetInstance); + int cLayers = GET_ARG(1, GetInteger); + int cMode = GET_ARG(2, GetInteger); + int cPlane = GET_ARG(3, GetInteger); + int xOffset = (int)GET_ARG(4, GetDecimal); + int yOffset = (int)GET_ARG(5, GetDecimal); + int setPos = GET_ARG(6, GetInteger); + + auto ent = (Entity*)entity->EntityPtr; + + return INTEGER_VAL(Scene::ObjectTileCollision(ent, cLayers, cMode, cPlane, xOffset, yOffset, setPos)); +} +/*** + * Collision.ObjectTileGrip + * \desc Keeps an instance gripped to tile collision based on where an instance should check. + * \param entity (Instance): The instance to move. + * \param cLayers (Bitfield): Which layers the entity can collide with. + * \param cMode (Integer): Collision mode of the entity (floor, left wall, roof, right wall). + * \param cPlane (Integer): Collision plane to get the collision of (A or B). + * \param xOffset (Decimal): How far from the entity's X value to start from. + * \param yOffset (Decimal): How far from the entity's Y value to start from. + * \param tolerance (Decimal): How far of a tolerance the entity should check for. + * \return Returns whether to grip the instance. + * \ns Collision + */ +VMValue Collision_ObjectTileGrip(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(7); + ObjInstance* entity = GET_ARG(0, GetInstance); + int cLayers = GET_ARG(1, GetInteger); + int cMode = GET_ARG(2, GetInteger); + int cPlane = GET_ARG(3, GetInteger); + int xOffset = (int)GET_ARG(4, GetDecimal); + int yOffset = (int)GET_ARG(5, GetDecimal); + float tolerance = GET_ARG(6, GetDecimal); + + auto ent = (Entity*)entity->EntityPtr; + + return INTEGER_VAL(Scene::ObjectTileGrip(ent, cLayers, cMode, cPlane, xOffset, yOffset, tolerance)); +} +/*** + * Collision.CheckObjectCollisionTouch + * \desc Checks if an instance is touching another instance with their respective hitboxes. + * \param thisEntity (Instance): The first instance to check. + * \param thisHitbox (Array): Array containing the first entity's hitbox. + * \param otherEntity (Instance): The other instance to check. + * \param otherHitbox (Array): Array containing the other entity's hitbox. + * \return Returns a Boolean value whether the entities are touching. + * \ns Collision + */ +VMValue Collision_CheckObjectCollisionTouch(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(4); + ObjInstance* thisEntity = GET_ARG(0, GetInstance); + ObjArray* thisHitbox = GET_ARG(1, GetArray); + ObjInstance* otherEntity = GET_ARG(2, GetInstance); + ObjArray* otherHitbox = GET_ARG(3, GetArray); + + auto thisEnt = (Entity*)thisEntity->EntityPtr; + auto otherEnt = (Entity*)otherEntity->EntityPtr; + + CollisionBox thisBox; + CollisionBox otherBox; + + thisBox.Left = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[0])); + thisBox.Top = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[1])); + thisBox.Right = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[2])); + thisBox.Bottom = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[3])); + + otherBox.Left = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[0])); + otherBox.Top = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[1])); + otherBox.Right = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[2])); + otherBox.Bottom = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[3])); + + + return INTEGER_VAL(!!Scene::CheckObjectCollisionTouch(thisEnt, &thisBox, otherEnt, &otherBox)); +} +/*** + * Collision.CheckObjectCollisionCircle + * \desc Checks if an instance is touching another instance with within their respective radii. + * \param thisEnity (Instance): The first instance to check. + * \param thisRadius (Decimal): Radius of the first entity to check. + * \param otherEntity (Instance): The other instance to check. + * \param otherRadius (Array): Radius of the other entity to check. + * \return Returns a Boolean value whether the entities have collided. + * \ns Collision + */ +VMValue Collision_CheckObjectCollisionCircle(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(4); + ObjInstance* thisEntity = GET_ARG(0, GetInstance); + float thisRadius = GET_ARG(1, GetDecimal); + ObjInstance* otherEntity = GET_ARG(2, GetInstance); + float otherRadius = GET_ARG(3, GetDecimal); + + auto thisEnt = (Entity*)thisEntity->EntityPtr; + auto otherEnt = (Entity*)otherEntity->EntityPtr; + + return INTEGER_VAL(!!Scene::CheckObjectCollisionCircle(thisEnt, thisRadius, otherEnt, otherRadius)); +} +/*** + * Collision.CheckObjectCollisionBox + * \desc Checks if an instance is touching another instance with their respective hitboxes and sets the values of the other instance if specified. + * \param thisEnity (Instance): The first instance to check. + * \param thisHitbox (Array): Array containing the first entity's hitbox. + * \param otherEntity (Instance): The other instance to check. + * \param otherHitbox (Array): Array containing the other entity's hitbox. + * \param setValues (Boolean): Whether to set the values of the other entity. + * \return Returns the side the entities are colliding on. + * \ns Collision + */ +VMValue Collision_CheckObjectCollisionBox(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(5); + ObjInstance* thisEntity = GET_ARG(0, GetInstance); + ObjArray* thisHitbox = GET_ARG(1, GetArray); + ObjInstance* otherEntity = GET_ARG(2, GetInstance); + ObjArray* otherHitbox = GET_ARG(3, GetArray); + bool setValues = !!GET_ARG(4, GetInteger); + + auto thisEnt = (Entity*)thisEntity->EntityPtr; + auto otherEnt = (Entity*)otherEntity->EntityPtr; + + CollisionBox thisBox; + CollisionBox otherBox; + + thisBox.Left = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[0])); + thisBox.Top = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[1])); + thisBox.Right = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[2])); + thisBox.Bottom = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[3])); + + otherBox.Left = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[0])); + otherBox.Top = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[1])); + otherBox.Right = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[2])); + otherBox.Bottom = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[3])); + + return INTEGER_VAL(Scene::CheckObjectCollisionBox(thisEnt, &thisBox, otherEnt, &otherBox, setValues)); +} +/*** + * Collision.CheckObjectCollisionPlatform + * \desc Checks if an instance is touching the top of another instance with their respective hitboxes and sets the values of the other instance if specified. + * \param thisEnity (Instance): The first instance to check. + * \param thisHitbox (Array): Array containing the first entity's hitbox. + * \param otherEntity (Instance): The other instance to check whether it is on top of the first instance. + * \param otherHitbox (Array): Array containing the other entity's hitbox. + * \param setValues (Boolean): Whether to set the values of the other entity. + * \return Returns a Boolean value whether the entities have collided. + * \ns Collision + */ +VMValue Collision_CheckObjectCollisionPlatform(int argCount, VMValue* args, Uint32 threadID) { + CHECK_ARGCOUNT(5); + ObjInstance* thisEntity = GET_ARG(0, GetInstance); + ObjArray* thisHitbox = GET_ARG(1, GetArray); + ObjInstance* otherEntity = GET_ARG(2, GetInstance); + ObjArray* otherHitbox = GET_ARG(3, GetArray); + bool setValues = !!GET_ARG(4, GetInteger); + + auto thisEnt = (Entity*)thisEntity->EntityPtr; + auto otherEnt = (Entity*)otherEntity->EntityPtr; + + CollisionBox thisBox; + CollisionBox otherBox; + + thisBox.Left = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[0])); + thisBox.Top = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[1])); + thisBox.Right = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[2])); + thisBox.Bottom = AS_INTEGER(ScriptManager::CastValueAsInteger((*thisHitbox->Values)[3])); + + otherBox.Left = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[0])); + otherBox.Top = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[1])); + otherBox.Right = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[2])); + otherBox.Bottom = AS_INTEGER(ScriptManager::CastValueAsInteger((*otherHitbox->Values)[3])); + + return INTEGER_VAL(!!Scene::CheckObjectCollisionPlatform(thisEnt, &thisBox, otherEnt, &otherBox, setValues)); +} +// #endregion + // #region Controller #define CHECK_CONTROLLER_INDEX(idx) \ if (InputManager::NumControllers == 0) { \ @@ -15512,16 +15736,6 @@ PUBLIC STATIC void StandardLibrary::Link() { DEF_ENUM_CLASS(KeyBind, DevQuit); // #endregion - // #region Audio - INIT_CLASS(Audio); - DEF_NATIVE(Audio, GetMasterVolume); - DEF_NATIVE(Audio, GetMusicVolume); - DEF_NATIVE(Audio, GetSoundVolume); - DEF_NATIVE(Audio, SetMasterVolume); - DEF_NATIVE(Audio, SetMusicVolume); - DEF_NATIVE(Audio, SetSoundVolume); - // #endregion - // #region Array INIT_CLASS(Array); DEF_NATIVE(Array, Create); @@ -15537,6 +15751,27 @@ PUBLIC STATIC void StandardLibrary::Link() { DEF_NATIVE(Array, Sort); // #endregion + // #region Audio + INIT_CLASS(Audio); + DEF_NATIVE(Audio, GetMasterVolume); + DEF_NATIVE(Audio, GetMusicVolume); + DEF_NATIVE(Audio, GetSoundVolume); + DEF_NATIVE(Audio, SetMasterVolume); + DEF_NATIVE(Audio, SetMusicVolume); + DEF_NATIVE(Audio, SetSoundVolume); + // #endregion + + // #region Collision + INIT_CLASS(Collision); + DEF_NATIVE(Collision, ProcessObjectMovement); + DEF_NATIVE(Collision, ObjectTileCollision); + DEF_NATIVE(Collision, ObjectTileGrip); + DEF_NATIVE(Collision, CheckObjectCollisionTouch); + DEF_NATIVE(Collision, CheckObjectCollisionCircle); + DEF_NATIVE(Collision, CheckObjectCollisionBox); + DEF_NATIVE(Collision, CheckObjectCollisionPlatform); + // #endregion + // #region Controller INIT_CLASS(Controller); DEF_NATIVE(Controller, GetCount); @@ -16851,13 +17086,6 @@ PUBLIC STATIC void StandardLibrary::Link() { // #region Scene INIT_CLASS(Scene); - DEF_NATIVE(Scene, ProcessObjectMovement); - DEF_NATIVE(Scene, ObjectTileCollision); - DEF_NATIVE(Scene, ObjectTileGrip); - DEF_NATIVE(Scene, CheckObjectCollisionTouch); - DEF_NATIVE(Scene, CheckObjectCollisionCircle); - DEF_NATIVE(Scene, CheckObjectCollisionBox); - DEF_NATIVE(Scene, CheckObjectCollisionPlatform); DEF_NATIVE(Scene, Load); DEF_NATIVE(Scene, Change); DEF_NATIVE(Scene, LoadTileCollisions); diff --git a/source/Engine/Types/Entity.cpp b/source/Engine/Types/Entity.cpp index 525e1f62..28a7908b 100644 --- a/source/Engine/Types/Entity.cpp +++ b/source/Engine/Types/Entity.cpp @@ -58,6 +58,7 @@ class Entity { float ScaleY = 1.0; float Rotation = 0.0; float Alpha = 1.0; + int BlendMode = BlendMode_NORMAL; int AutoPhysics = false; int Priority = 0; From 495908963c235ccfe67d4fff69b3b8bab36dc08a Mon Sep 17 00:00:00 2001 From: Axanery <41282531+Axanery@users.noreply.github.com> Date: Mon, 24 Jun 2024 23:58:21 -0500 Subject: [PATCH 22/23] Made some Math functions respect the number type --- source/Engine/Bytecode/StandardLibrary.cpp | 283 +-------------------- 1 file changed, 14 insertions(+), 269 deletions(-) diff --git a/source/Engine/Bytecode/StandardLibrary.cpp b/source/Engine/Bytecode/StandardLibrary.cpp index 8ee5120a..7ea9442f 100644 --- a/source/Engine/Bytecode/StandardLibrary.cpp +++ b/source/Engine/Bytecode/StandardLibrary.cpp @@ -6675,7 +6675,7 @@ VMValue Math_Direction(int argCount, VMValue* args, Uint32 threadID) { */ VMValue Math_Abs(int argCount, VMValue* args, Uint32 threadID) { CHECK_ARGCOUNT(1); - return DECIMAL_VAL(Math::Abs(GET_ARG(0, GetDecimal))); + return IS_INTEGER(args[0]) ? INTEGER_VAL((int)Math::Abs(GET_ARG(0, GetDecimal))) : DECIMAL_VAL(Math::Abs(GET_ARG(0, GetDecimal))); } /*** * Math.Min @@ -6687,8 +6687,10 @@ VMValue Math_Abs(int argCount, VMValue* args, Uint32 threadID) { */ VMValue Math_Min(int argCount, VMValue* args, Uint32 threadID) { CHECK_ARGCOUNT(2); - // respect the type of number - return DECIMAL_VAL(Math::Min(GET_ARG(0, GetDecimal), GET_ARG(1, GetDecimal))); + if (IS_INTEGER(args[0]) && IS_INTEGER(args[1])) + return INTEGER_VAL((int)Math::Min(GET_ARG(0, GetDecimal), GET_ARG(1, GetDecimal))); + else + return DECIMAL_VAL(Math::Min(GET_ARG(0, GetDecimal), GET_ARG(1, GetDecimal))); } /*** * Math.Max @@ -6700,7 +6702,10 @@ VMValue Math_Min(int argCount, VMValue* args, Uint32 threadID) { */ VMValue Math_Max(int argCount, VMValue* args, Uint32 threadID) { CHECK_ARGCOUNT(2); - return DECIMAL_VAL(Math::Max(GET_ARG(0, GetDecimal), GET_ARG(1, GetDecimal))); + if (IS_INTEGER(args[0]) && IS_INTEGER(args[1])) + return INTEGER_VAL((int)Math::Max(GET_ARG(0, GetDecimal), GET_ARG(1, GetDecimal))); + else + return DECIMAL_VAL(Math::Max(GET_ARG(0, GetDecimal), GET_ARG(1, GetDecimal))); } /*** * Math.Clamp @@ -6713,7 +6718,10 @@ VMValue Math_Max(int argCount, VMValue* args, Uint32 threadID) { */ VMValue Math_Clamp(int argCount, VMValue* args, Uint32 threadID) { CHECK_ARGCOUNT(3); - return DECIMAL_VAL(Math::Clamp(GET_ARG(0, GetDecimal), GET_ARG(1, GetDecimal), GET_ARG(2, GetDecimal))); + if (IS_INTEGER(args[0]) && IS_INTEGER(args[1]) && IS_INTEGER(args[2])) + return INTEGER_VAL((int)Math::Clamp(GET_ARG(0, GetDecimal), GET_ARG(1, GetDecimal), GET_ARG(2, GetDecimal))); + else + return DECIMAL_VAL(Math::Clamp(GET_ARG(0, GetDecimal), GET_ARG(1, GetDecimal), GET_ARG(2, GetDecimal))); } /*** * Math.ToFixed @@ -7109,7 +7117,7 @@ VMValue Math_RadianToInteger(int argCount, VMValue* args, Uint32 threadID) { } /*** * RSDK.Math.IntegerToRadian - * \desc Gets the radia Decimal conversion of an integer, based on 256. + * \desc Gets the radian Decimal conversion of an integer, based on 256. * \param integer (Integer): Integer value to convert. * \return A radia Decimal value of the converted integer. * \ns RSDK.Math @@ -9116,269 +9124,6 @@ VMValue Resources_ReadAllText(int argCount, VMValue* args, Uint32 threadID) { // #region Scene #define CHECK_TILE_LAYER_POS_BOUNDS() if (layer < 0 || layer >= (int)Scene::Layers.size() || x < 0 || y < 0 || x >= Scene::Layers[layer].Width || y >= Scene::Layers[layer].Height) return NULL_VAL; -/*** - * Scene.ProcessObjectMovement - * \desc Processes movement of an instance with an outer hitbox and an inner hitboxe. - * \param entity (Instance): The instance to move. - * \param outer (Array): Array containing the outer hitbox. - * \param inner (Array): Array containing the inner hitbox. - * \ns Scene - */ -VMValue Scene_ProcessObjectMovement(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(3); - ObjInstance* entity = GET_ARG(0, GetInstance); - ObjArray* outer = GET_ARG(1, GetArray); - ObjArray* inner = GET_ARG(2, GetArray); - - CollisionBox outerBox; - CollisionBox innerBox; - - if (entity && outer && inner) { - auto ent = (Entity*)entity->EntityPtr; - - outerBox.Left = (int)AS_DECIMAL((*outer->Values)[0]); - outerBox.Top = (int)AS_DECIMAL((*outer->Values)[1]); - outerBox.Right = (int)AS_DECIMAL((*outer->Values)[2]); - outerBox.Bottom = (int)AS_DECIMAL((*outer->Values)[3]); - - innerBox.Left = (int)AS_DECIMAL((*inner->Values)[0]); - innerBox.Top = (int)AS_DECIMAL((*inner->Values)[1]); - innerBox.Right = (int)AS_DECIMAL((*inner->Values)[2]); - innerBox.Bottom = (int)AS_DECIMAL((*inner->Values)[3]); - Scene::ProcessObjectMovement(ent, &outerBox, &innerBox); - } - return NULL_VAL; -} -/*** - * Scene.ObjectTileCollision - * \desc Checks tile collision based on where an instance should check. - * \param entity (Instance): The instance to base the values on. - * \param cLayers (Bitfield): Which layers the entity can collide with. - * \param cMode (Integer): Collision mode of the entity (floor, left wall, roof, right wall). - * \param cPlane (Integer): Collision plane to get the collision of (A or B). - * \param xOffset (Number): How far from the entity's X value to start from. - * \param yOffset (Number): How far from the entity's Y value to start from. - * \param setPos (Boolean): Whether to set the entity's position if collision is found. - * \return Returns whether the instance has collided with a tile. - * \ns Scene - */ -VMValue Scene_ObjectTileCollision(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(7); - ObjInstance* entity = GET_ARG(0, GetInstance); - int cLayers = GET_ARG(1, GetInteger); - int cMode = GET_ARG(2, GetInteger); - int cPlane = GET_ARG(3, GetInteger); - int xOffset = (int)GET_ARG(4, GetDecimal); - int yOffset = (int)GET_ARG(5, GetDecimal); - int setPos = GET_ARG(6, GetInteger); - - auto ent = (Entity*)entity->EntityPtr; - - return INTEGER_VAL(Scene::ObjectTileCollision(ent, cLayers, cMode, cPlane, xOffset, yOffset, setPos)); -} -/*** - * Scene.ObjectTileGrip - * \desc Keeps an instance gripped to tile collision based on where an instance should check. - * \param entity (Instance): The instance to move. - * \param cLayers (Bitfield): Which layers the entity can collide with. - * \param cMode (Integer): Collision mode of the entity (floor, left wall, roof, right wall). - * \param cPlane (Integer): Collision plane to get the collision of (A or B). - * \param xOffset (Decimal): How far from the entity's X value to start from. - * \param yOffset (Decimal): How far from the entity's Y value to start from. - * \param tolerance (Decimal): How far of a tolerance the entity should check for. - * \return Returns whether to grip the instance. - * \ns Scene - */ -VMValue Scene_ObjectTileGrip(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(7); - ObjInstance* entity = GET_ARG(0, GetInstance); - int cLayers = GET_ARG(1, GetInteger); - int cMode = GET_ARG(2, GetInteger); - int cPlane = GET_ARG(3, GetInteger); - int xOffset = (int)GET_ARG(4, GetDecimal); - int yOffset = (int)GET_ARG(5, GetDecimal); - float tolerance = GET_ARG(6, GetDecimal); - - auto ent = (Entity*)entity->EntityPtr; - - return INTEGER_VAL(Scene::ObjectTileGrip(ent, cLayers, cMode, cPlane, xOffset, yOffset, tolerance)); -} -/*** - * Scene.CheckObjectCollisionTouch - * \desc Checks if an instance is touching another instance with their respective hitboxes. - * \param thisEntity (Instance): The first instance to check. - * \param thisHitbox (Array): Array containing the first entity's hitbox. - * \param otherEntity (Instance): The other instance to check. - * \param otherHitbox (Array): Array containing the other entity's hitbox. - * \return Returns a Boolean value whether the entities are touching. - * \ns Scene - */ -VMValue Scene_CheckObjectCollisionTouch(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(4); - ObjInstance* thisEntity = GET_ARG(0, GetInstance); - ObjArray* thisHitbox = GET_ARG(1, GetArray); - ObjInstance* otherEntity = GET_ARG(2, GetInstance); - ObjArray* otherHitbox = GET_ARG(3, GetArray); - - auto thisEnt = (Entity*)thisEntity->EntityPtr; - auto otherEnt = (Entity*)otherEntity->EntityPtr; - - CollisionBox thisBox; - CollisionBox otherBox; - - if (IS_INTEGER((*thisHitbox->Values)[0])) { - thisBox.Left = AS_INTEGER((*thisHitbox->Values)[0]); - thisBox.Top = AS_INTEGER((*thisHitbox->Values)[1]); - thisBox.Right = AS_INTEGER((*thisHitbox->Values)[2]); - thisBox.Bottom = AS_INTEGER((*thisHitbox->Values)[3]); - } - else { - thisBox.Left = (int)AS_DECIMAL((*thisHitbox->Values)[0]); - thisBox.Top = (int)AS_DECIMAL((*thisHitbox->Values)[1]); - thisBox.Right = (int)AS_DECIMAL((*thisHitbox->Values)[2]); - thisBox.Bottom = (int)AS_DECIMAL((*thisHitbox->Values)[3]); - } - - if (IS_INTEGER((*otherHitbox->Values)[0])) { - otherBox.Left = AS_INTEGER((*otherHitbox->Values)[0]); - otherBox.Top = AS_INTEGER((*otherHitbox->Values)[1]); - otherBox.Right = AS_INTEGER((*otherHitbox->Values)[2]); - otherBox.Bottom = AS_INTEGER((*otherHitbox->Values)[3]); - } - else { - otherBox.Left = (int)AS_DECIMAL((*otherHitbox->Values)[0]); - otherBox.Top = (int)AS_DECIMAL((*otherHitbox->Values)[1]); - otherBox.Right = (int)AS_DECIMAL((*otherHitbox->Values)[2]); - otherBox.Bottom = (int)AS_DECIMAL((*otherHitbox->Values)[3]); - } - return INTEGER_VAL(!!Scene::CheckObjectCollisionTouch(thisEnt, &thisBox, otherEnt, &otherBox)); -} -/*** - * Scene.CheckObjectCollisionCircle - * \desc Checks if an instance is touching another instance with within their respective radii. - * \param thisEnity (Instance): The first instance to check. - * \param thisRadius (Decimal): Radius of the first entity to check. - * \param otherEntity (Instance): The other instance to check. - * \param otherRadius (Array): Radius of the other entity to check. - * \return Returns a Boolean value whether the entities have collided. - * \ns Scene - */ -VMValue Scene_CheckObjectCollisionCircle(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(4); - ObjInstance* thisEntity = GET_ARG(0, GetInstance); - float thisRadius = GET_ARG(1, GetDecimal); - ObjInstance* otherEntity = GET_ARG(2, GetInstance); - float otherRadius = GET_ARG(3, GetDecimal); - - auto thisEnt = (Entity*)thisEntity->EntityPtr; - auto otherEnt = (Entity*)otherEntity->EntityPtr; - - return INTEGER_VAL(!!Scene::CheckObjectCollisionCircle(thisEnt, thisRadius, otherEnt, otherRadius)); -} -/*** - * Scene.CheckObjectCollisionBox - * \desc Checks if an instance is touching another instance with their respective hitboxes and sets the values of the other instance if specified. - * \param thisEnity (Instance): The first instance to check. - * \param thisHitbox (Array): Array containing the first entity's hitbox. - * \param otherEntity (Instance): The other instance to check. - * \param otherHitbox (Array): Array containing the other entity's hitbox. - * \param setValues (Boolean): Whether to set the values of the other entity. - * \return Returns the side the entities are colliding on. - * \ns Scene - */ -VMValue Scene_CheckObjectCollisionBox(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(5); - ObjInstance* thisEntity = GET_ARG(0, GetInstance); - ObjArray* thisHitbox = GET_ARG(1, GetArray); - ObjInstance* otherEntity = GET_ARG(2, GetInstance); - ObjArray* otherHitbox = GET_ARG(3, GetArray); - bool setValues = !!GET_ARG(4, GetInteger); - - auto thisEnt = (Entity*)thisEntity->EntityPtr; - auto otherEnt = (Entity*)otherEntity->EntityPtr; - - CollisionBox thisBox; - CollisionBox otherBox; - - if (IS_INTEGER((*thisHitbox->Values)[0])) { - thisBox.Left = AS_INTEGER((*thisHitbox->Values)[0]); - thisBox.Top = AS_INTEGER((*thisHitbox->Values)[1]); - thisBox.Right = AS_INTEGER((*thisHitbox->Values)[2]); - thisBox.Bottom = AS_INTEGER((*thisHitbox->Values)[3]); - } - else { - thisBox.Left = (int)AS_DECIMAL((*thisHitbox->Values)[0]); - thisBox.Top = (int)AS_DECIMAL((*thisHitbox->Values)[1]); - thisBox.Right = (int)AS_DECIMAL((*thisHitbox->Values)[2]); - thisBox.Bottom = (int)AS_DECIMAL((*thisHitbox->Values)[3]); - } - - if (IS_INTEGER((*otherHitbox->Values)[0])) { - otherBox.Left = AS_INTEGER((*otherHitbox->Values)[0]); - otherBox.Top = AS_INTEGER((*otherHitbox->Values)[1]); - otherBox.Right = AS_INTEGER((*otherHitbox->Values)[2]); - otherBox.Bottom = AS_INTEGER((*otherHitbox->Values)[3]); - } - else { - otherBox.Left = (int)AS_DECIMAL((*otherHitbox->Values)[0]); - otherBox.Top = (int)AS_DECIMAL((*otherHitbox->Values)[1]); - otherBox.Right = (int)AS_DECIMAL((*otherHitbox->Values)[2]); - otherBox.Bottom = (int)AS_DECIMAL((*otherHitbox->Values)[3]); - } - return INTEGER_VAL(Scene::CheckObjectCollisionBox(thisEnt, &thisBox, otherEnt, &otherBox, setValues)); -} -/*** - * Scene.CheckObjectCollisionPlatform - * \desc Checks if an instance is touching the top of another instance with their respective hitboxes and sets the values of the other instance if specified. - * \param thisEnity (Instance): The first instance to check. - * \param thisHitbox (Array): Array containing the first entity's hitbox. - * \param otherEntity (Instance): The other instance to check whether it is on top of the first instance. - * \param otherHitbox (Array): Array containing the other entity's hitbox. - * \param setValues (Boolean): Whether to set the values of the other entity. - * \return Returns a Boolean value whether the entities have collided. - * \ns Scene - */ -VMValue Scene_CheckObjectCollisionPlatform(int argCount, VMValue* args, Uint32 threadID) { - CHECK_ARGCOUNT(5); - ObjInstance* thisEntity = GET_ARG(0, GetInstance); - ObjArray* thisHitbox = GET_ARG(1, GetArray); - ObjInstance* otherEntity = GET_ARG(2, GetInstance); - ObjArray* otherHitbox = GET_ARG(3, GetArray); - bool setValues = !!GET_ARG(4, GetInteger); - - auto thisEnt = (Entity*)thisEntity->EntityPtr; - auto otherEnt = (Entity*)otherEntity->EntityPtr; - - CollisionBox thisBox; - CollisionBox otherBox; - - if (IS_INTEGER((*thisHitbox->Values)[0])) { - thisBox.Left = AS_INTEGER((*thisHitbox->Values)[0]); - thisBox.Top = AS_INTEGER((*thisHitbox->Values)[1]); - thisBox.Right = AS_INTEGER((*thisHitbox->Values)[2]); - thisBox.Bottom = AS_INTEGER((*thisHitbox->Values)[3]); - } - else { - thisBox.Left = (int)AS_DECIMAL((*thisHitbox->Values)[0]); - thisBox.Top = (int)AS_DECIMAL((*thisHitbox->Values)[1]); - thisBox.Right = (int)AS_DECIMAL((*thisHitbox->Values)[2]); - thisBox.Bottom = (int)AS_DECIMAL((*thisHitbox->Values)[3]); - } - - if (IS_INTEGER((*otherHitbox->Values)[0])) { - otherBox.Left = AS_INTEGER((*otherHitbox->Values)[0]); - otherBox.Top = AS_INTEGER((*otherHitbox->Values)[1]); - otherBox.Right = AS_INTEGER((*otherHitbox->Values)[2]); - otherBox.Bottom = AS_INTEGER((*otherHitbox->Values)[3]); - } - else { - otherBox.Left = (int)AS_DECIMAL((*otherHitbox->Values)[0]); - otherBox.Top = (int)AS_DECIMAL((*otherHitbox->Values)[1]); - otherBox.Right = (int)AS_DECIMAL((*otherHitbox->Values)[2]); - otherBox.Bottom = (int)AS_DECIMAL((*otherHitbox->Values)[3]); - } - return INTEGER_VAL(!!Scene::CheckObjectCollisionPlatform(thisEnt, &thisBox, otherEnt, &otherBox, setValues)); -} /*** * Scene.Load * \desc Changes the active scene. If a path to a resource is provided, the active scene is changed to the one in the specified resource file. Otherwise, the active scene is changed to the currently set entry in the scene list, if it exists (see .) From 0a0ea4f43944fd9b22a8ba2c2003adb3843d8cb7 Mon Sep 17 00:00:00 2001 From: Axanery <41282531+Axanery@users.noreply.github.com> Date: Tue, 25 Jun 2024 03:08:20 -0500 Subject: [PATCH 23/23] Update vcxproj to allow for x64 builds --- VisualC/HatchGameEngine.vcxproj | 15 ++++++++-- VisualC/HatchGameEngine.vcxproj.filters | 36 ++++++++++++++++++++++-- meta/win/lib/msvc/x64/SDL2.lib | Bin 183824 -> 183824 bytes meta/win/lib/msvc/x64/SDL2main.lib | Bin 0 -> 56982 bytes meta/win/lib/msvc/x64/freetype.lib | Bin 0 -> 49398 bytes 5 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 meta/win/lib/msvc/x64/SDL2main.lib create mode 100644 meta/win/lib/msvc/x64/freetype.lib diff --git a/VisualC/HatchGameEngine.vcxproj b/VisualC/HatchGameEngine.vcxproj index 0cf4a9a5..f707bcad 100644 --- a/VisualC/HatchGameEngine.vcxproj +++ b/VisualC/HatchGameEngine.vcxproj @@ -80,6 +80,7 @@ $(SolutionDir)..\meta\win\include;$(SolutionDir)..\include;$(SolutionDir)..\source;$(IncludePath) $(SolutionDir)..\meta\win\lib\msvc\x64;$(LibraryPath) + true @@ -129,7 +130,8 @@ CD .. - stdcpp17 + stdcpp20 + WIN32;TARGET_NAME="$(ProjectName)";GLEW_STATIC;USING_OPENGL;USING_FREETYPE;_DEBUG;_WINDOWS;DEBUG;%(PreprocessorDefinitions) CD "..\tools" @@ -139,10 +141,15 @@ CD .. copy "$(TargetPath)" "$(SolutionDir)..\builds\win\$(TargetName)-Debug.exe" + + Ws2_32.lib;Wldap32.lib;Advapi32.lib;Crypt32.lib;Normaliz.lib;legacy_stdio_definitions.lib;glew32s.lib;opengl32.lib;freetype.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + - stdcpp17 + stdcpp20 + WIN32;TARGET_NAME="$(ProjectName)";GLEW_STATIC;USING_OPENGL;USING_FREETYPE;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) CD "..\tools" @@ -152,6 +159,10 @@ CD .. copy "$(TargetPath)" "$(SolutionDir)..\builds\win\$(TargetName)-Release.exe" + + Windows + Ws2_32.lib;Wldap32.lib;Advapi32.lib;Crypt32.lib;Normaliz.lib;legacy_stdio_definitions.lib;glew32s.lib;opengl32.lib;freetype.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + diff --git a/VisualC/HatchGameEngine.vcxproj.filters b/VisualC/HatchGameEngine.vcxproj.filters index 602081df..f3430835 100644 --- a/VisualC/HatchGameEngine.vcxproj.filters +++ b/VisualC/HatchGameEngine.vcxproj.filters @@ -381,6 +381,36 @@ Source Files\External Libs + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -464,9 +494,6 @@ Header Files - - Header Files - Header Files @@ -494,6 +521,9 @@ Source Files\External Libs + + Header Files + diff --git a/meta/win/lib/msvc/x64/SDL2.lib b/meta/win/lib/msvc/x64/SDL2.lib index 7257de6383ca5732a50a1df3f41f2447a2625d1c..06fb7e2c66e694fe4ca30eab519289d1dd874898 100644 GIT binary patch delta 136 zcmbO*hkL>t?uIRld5N4%@1;+(F)}c4Oh1{zXf}OqB4YuI27_?Rbj2jba3&zVAeB*S z`jjNbA1u9rI)|rENM>w?D^Qt?uIRld5N5B8|>b)F)}c4Oh1{zXf}OqB4YuIEW^pt>555=;Y>h!K`Nuv z^eIVoF^=`dt&2}?O`n*|C_nv43S&21tujn) NJJ7`K3sRX1G5{gAF|Pms diff --git a/meta/win/lib/msvc/x64/SDL2main.lib b/meta/win/lib/msvc/x64/SDL2main.lib new file mode 100644 index 0000000000000000000000000000000000000000..0fe5beec61a31e87abe668278cb760f9acffec36 GIT binary patch literal 56982 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 literal 0 HcmV?d00001 diff --git a/meta/win/lib/msvc/x64/freetype.lib b/meta/win/lib/msvc/x64/freetype.lib new file mode 100644 index 0000000000000000000000000000000000000000..f2e849f7ac2e4ea38aa8ce32c3b0537ca49cb02b GIT binary patch literal 49398 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 literal 0 HcmV?d00001