diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4838480 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.idea/ +.vs/ +*.user +/local + +bin/ +obj/ + +BetterFirstPerson/obj/ +BetterFirstPerson/bin/ \ No newline at end of file diff --git a/BetterFirstPerson.sln b/BetterFirstPerson.sln new file mode 100644 index 0000000..53e4e64 --- /dev/null +++ b/BetterFirstPerson.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35013.160 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BetterFirstPerson", "BetterFirstPerson\BetterFirstPerson.csproj", "{1A273855-C2D0-40BB-B22C-CE17AA4D0A9B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1A273855-C2D0-40BB-B22C-CE17AA4D0A9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A273855-C2D0-40BB-B22C-CE17AA4D0A9B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A273855-C2D0-40BB-B22C-CE17AA4D0A9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A273855-C2D0-40BB-B22C-CE17AA4D0A9B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/BetterFirstPerson/BetterFirstPerson.csproj b/BetterFirstPerson/BetterFirstPerson.csproj new file mode 100644 index 0000000..2643a94 --- /dev/null +++ b/BetterFirstPerson/BetterFirstPerson.csproj @@ -0,0 +1,27 @@ + + + net8.0 + enable + enable + $(AssemblySearchPaths);$(GDWeavePath)/core + + + + + + + + + + + + + + + diff --git a/BetterFirstPerson/BetterFirstPersonMod.cs b/BetterFirstPerson/BetterFirstPersonMod.cs new file mode 100644 index 0000000..de932e3 --- /dev/null +++ b/BetterFirstPerson/BetterFirstPersonMod.cs @@ -0,0 +1,18 @@ +using GDWeave; +using Serilog; +using Serilog.Core; + +namespace BetterFirstPerson; + +public class BetterFirstPersonMod : IMod { + public Config Config; + + public BetterFirstPersonMod(IModInterface modInterface) { + this.Config = modInterface.ReadConfig(); + modInterface.Logger.Information("BetterFirstPerson loaded!"); + + modInterface.RegisterScriptMod(new PlayerPatch(this)); + } + + public void Dispose() {} +} diff --git a/BetterFirstPerson/Config.cs b/BetterFirstPerson/Config.cs new file mode 100644 index 0000000..d5a7566 --- /dev/null +++ b/BetterFirstPerson/Config.cs @@ -0,0 +1,7 @@ +using System.Text.Json.Serialization; + +namespace BetterFirstPerson; + +public class Config { + [JsonInclude] public bool ResetUpDownOnFreecam = false; +} diff --git a/BetterFirstPerson/FirstPersonFix.cs b/BetterFirstPerson/FirstPersonFix.cs new file mode 100644 index 0000000..5259356 --- /dev/null +++ b/BetterFirstPerson/FirstPersonFix.cs @@ -0,0 +1,213 @@ +using GDWeave; +using GDWeave.Godot; +using GDWeave.Godot.Variants; +using GDWeave.Modding; +using Serilog; +using Serilog.Configuration; + +namespace BetterFirstPerson; + +public class PlayerPatch(BetterFirstPersonMod mod) : IScriptMod +{ + public bool ShouldRun(string path) => path == "res://Scenes/Entities/Player/player.gdc"; + + public IEnumerable Modify(string path, IEnumerable tokens) + { + var waiter = new MultiTokenWaiter([ + t => t is IdentifierToken{Name: "skeleton"}, + t => t.Type is TokenType.Period, + t => t is IdentifierToken{Name: "set_bone_custom_pose" }, + t => t.Type is TokenType.ParenthesisOpen, + t => t is ConstantToken{Value: IntVariant{Value:1 } }, + t => t.Type is TokenType.Comma, + t => t.Type is TokenType.BuiltInType, + t => t.Type is TokenType.ParenthesisOpen, + t => t.Type is TokenType.ParenthesisClose, + t => t.Type is TokenType.ParenthesisClose, + t => t.Type is TokenType.Newline, + ], allowPartialMatch: true); + + foreach (var token in tokens) + { + // was useful since GDWeave.Test didn't work for me :p + // mod.logger.Information(token.ToString()); + if (waiter.Check(token)) + { + yield return new Token(TokenType.Newline, 1); + + // fuck me + + // if camera_zoom < 0.5 and not freecamming: + yield return new Token(TokenType.CfIf); + yield return new IdentifierToken(TokenType.Identifier, 32, "camera_zoom"); + yield return new Token(TokenType.OpLess); + yield return new ConstantToken(new RealVariant(0.5)); + yield return new Token(TokenType.OpAnd); + yield return new Token(TokenType.OpNot); + yield return new IdentifierToken(TokenType.Identifier, 134, "freecamming"); + yield return new Token(TokenType.Colon); + yield return new Token(TokenType.Newline, 2); + + // if state != STATES.FISHING and state != STATES.FISHING_STRUGGLE: + yield return new Token(TokenType.CfIf); + yield return new IdentifierToken(TokenType.Identifier, 47, "state"); + yield return new Token(TokenType.OpNotEqual); + yield return new ConstantToken(new IntVariant(1)); // 1 - BUSY + yield return new Token(TokenType.OpAnd); + yield return new IdentifierToken(TokenType.Identifier, 47, "state"); + yield return new Token(TokenType.OpNotEqual); + yield return new ConstantToken(new IntVariant(6)); // 6 - FISHING_CAST + yield return new Token(TokenType.OpAnd); + yield return new IdentifierToken(TokenType.Identifier, 47, "state"); + yield return new Token(TokenType.OpNotEqual); + yield return new ConstantToken(new IntVariant(7)); // 7 - FISHING + yield return new Token(TokenType.OpAnd); + yield return new IdentifierToken(TokenType.Identifier, 47, "state"); + yield return new Token(TokenType.OpNotEqual); + yield return new ConstantToken(new IntVariant(9)); // 9 - FISHING_STRUGGLE + yield return new Token(TokenType.OpAnd); + yield return new IdentifierToken(TokenType.Identifier, 47, "state"); + yield return new Token(TokenType.OpNotEqual); + yield return new ConstantToken(new IntVariant(10)); // 10 - SHOVEL_CAST + yield return new Token(TokenType.OpAnd); + yield return new IdentifierToken(TokenType.Identifier, 47, "state"); + yield return new Token(TokenType.OpNotEqual); + yield return new ConstantToken(new IntVariant(11)); // 11 - SHOVEL_STRUGGLE + + // idk what these are :p + + //yield return new Token(TokenType.OpOr); + //yield return new IdentifierToken(TokenType.Identifier, 47, "state"); + //yield return new Token(TokenType.OpNotEqual); + //yield return new ConstantToken(new IntVariant(12)); // 12 - NET_CAST + //yield return new Token(TokenType.OpOr); + //yield return new IdentifierToken(TokenType.Identifier, 47, "state"); + //yield return new Token(TokenType.OpNotEqual); + //yield return new ConstantToken(new IntVariant(13)); // 13 - NET_STRUGGLE + + yield return new Token(TokenType.OpAnd); + yield return new IdentifierToken(TokenType.Identifier, 47, "state"); + yield return new Token(TokenType.OpNotEqual); + yield return new ConstantToken(new IntVariant(16)); // 16 - SHOVEL_STRUGGLE + + yield return new Token(TokenType.Colon); + yield return new Token(TokenType.Newline, 3); + + // self.rotation.y = camera.rotation.y + yield return new Token(TokenType.Self); + yield return new Token(TokenType.Period); + yield return new IdentifierToken("rotation"); + yield return new Token(TokenType.Period); + yield return new IdentifierToken("y"); + yield return new Token(TokenType.OpAssign); + yield return new IdentifierToken(TokenType.Identifier, 137, "camera"); + yield return new Token(TokenType.Period); + yield return new IdentifierToken(TokenType.Identifier, 286, "rotation"); + yield return new Token(TokenType.Period); + yield return new IdentifierToken(TokenType.Identifier, 288, "y"); + yield return new Token(TokenType.Newline, 3); + + // var back_bend = clamp(camera.rotation.x * 54, -50.0, 50.0) + yield return new Token(TokenType.PrVar); + yield return new IdentifierToken("back_bend"); + yield return new Token(TokenType.OpAssign); + yield return new Token(TokenType.BuiltInFunc, 53); + yield return new Token(TokenType.ParenthesisOpen); + yield return new IdentifierToken(TokenType.Identifier, 137, "camera"); + yield return new Token(TokenType.Period); + yield return new IdentifierToken(TokenType.Identifier, 286, "rotation"); + yield return new Token(TokenType.Period); + yield return new IdentifierToken(TokenType.Identifier, 288, "x"); + yield return new Token(TokenType.OpMul); + yield return new ConstantToken(new IntVariant(54)); + yield return new Token(TokenType.Comma); + yield return new ConstantToken(new RealVariant(-50.0)); + yield return new Token(TokenType.Comma); + yield return new ConstantToken(new RealVariant(50.0)); + yield return new Token(TokenType.ParenthesisClose); + yield return new Token(TokenType.Newline, 3); + + // $body / player_body / Armature / Skeleton / BoneAttachment / Spatial.rotation_degrees = Vector3(0.0, camera.rotation.y, back_bend * 0.7) + yield return new Token(TokenType.Dollar); + yield return new IdentifierToken(TokenType.Identifier, 142, "body"); + yield return new Token(TokenType.OpDiv); + yield return new IdentifierToken(TokenType.Identifier, 144, "player_body"); + yield return new Token(TokenType.OpDiv); + yield return new IdentifierToken(TokenType.Identifier, 145, "Armature"); + yield return new Token(TokenType.OpDiv); + yield return new IdentifierToken(TokenType.Identifier, 146, "Skeleton"); + yield return new Token(TokenType.OpDiv); + yield return new IdentifierToken(TokenType.Identifier, 597, "BoneAttachment"); + yield return new Token(TokenType.OpDiv); + yield return new IdentifierToken(TokenType.Identifier, 598, "Spatial"); + yield return new Token(TokenType.Period); + yield return new IdentifierToken(TokenType.Identifier, 342, "rotation_degrees"); + yield return new Token(TokenType.OpAssign); + yield return new Token(TokenType.BuiltInType, 7); + yield return new Token(TokenType.ParenthesisOpen); + yield return new ConstantToken(new RealVariant(0.0)); + yield return new Token(TokenType.Comma); + yield return new ConstantToken(new RealVariant(0.0)); + yield return new Token(TokenType.Comma); + yield return new IdentifierToken("back_bend"); + yield return new Token(TokenType.OpMul); + yield return new ConstantToken(new RealVariant(0.7)); + yield return new Token(TokenType.ParenthesisClose); + yield return new Token(TokenType.Newline, 3); + + // animation_data["back_bend"] = deg2rad( - back_bend) + yield return new IdentifierToken(TokenType.Identifier, 126, "animation_data"); + yield return new Token(TokenType.BracketOpen); + yield return new ConstantToken(new StringVariant("back_bend")); + yield return new Token(TokenType.BracketClose); + yield return new Token(TokenType.OpAssign); + yield return new Token(TokenType.BuiltInFunc, 43); + yield return new Token(TokenType.ParenthesisOpen); + yield return new Token(TokenType.OpSub); + yield return new IdentifierToken("back_bend"); + yield return new Token(TokenType.ParenthesisClose); + yield return new Token(TokenType.Newline, 1); + + if (mod.Config.ResetUpDownOnFreecam) + { + // else: + yield return new Token(TokenType.CfElse); + yield return new Token(TokenType.Colon); + + yield return new Token(TokenType.Newline, 2); + // if not freecamming: + yield return new Token(TokenType.CfIf); + yield return new Token(TokenType.OpNot); + yield return new IdentifierToken(TokenType.Identifier, 134, "freecamming"); + yield return new Token(TokenType.Colon); + yield return new Token(TokenType.Newline, 3); + + // if animation_data["back_bend"] != 0.0: + yield return new Token(TokenType.CfIf); + yield return new IdentifierToken(TokenType.Identifier, 126, "animation_data"); + yield return new Token(TokenType.BracketOpen); + yield return new ConstantToken(new StringVariant("back_bend")); + yield return new Token(TokenType.BracketClose); + yield return new Token(TokenType.OpNotEqual); + yield return new ConstantToken(new RealVariant(0.0)); + yield return new Token(TokenType.Colon); + yield return new Token(TokenType.Newline, 4); + + // animation_data["back_bend"] = 0.0 + yield return new IdentifierToken(TokenType.Identifier, 126, "animation_data"); + yield return new Token(TokenType.BracketOpen); + yield return new ConstantToken(new StringVariant("back_bend")); + yield return new Token(TokenType.BracketClose); + yield return new Token(TokenType.OpAssign); + yield return new ConstantToken(new RealVariant(0.0)); + yield return new Token(TokenType.Newline, 1); + } + } + else + { + yield return token; + } + } + } + +} \ No newline at end of file diff --git a/BetterFirstPerson/manifest.json b/BetterFirstPerson/manifest.json new file mode 100644 index 0000000..d8ec0aa --- /dev/null +++ b/BetterFirstPerson/manifest.json @@ -0,0 +1,4 @@ +{ + "Id": "BetterFirstPerson", + "AssemblyPath": "BetterFirstPerson.dll" +} diff --git a/README.md b/README.md index 7491bcf..da5b7a7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # BetterFirstPerson -a better first person mod for webfishing \ No newline at end of file +better first person mod for webfishing + +## what does this mod do +makes the character rotate in first person (includes up and down body bending :3) \ No newline at end of file