-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b771ee8
Showing
16 changed files
with
587 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# c# | ||
bin | ||
obj | ||
|
||
# gd | ||
.import | ||
.mono |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# WebWardrobe | ||
|
||
Easily store and switch between different outfits!\ | ||
[<img src="res/switch.gif" width="550"/>](res/switch.gif)\ | ||
<sub>A [WEBFISHING](https://store.steampowered.com/app/3146520/WEBFISHING/) mod using [GDWeave](https://github.com/NotNite/GDWeave/), with a combination of `C#` and `GDScript`.</sub> | ||
|
||
## Files | ||
Your saved outfits are put in your save file directory, in a separate file called `outfits.json`. *Your original save file is safe!*\*\ | ||
<sub>* Your last applied outfit will be saved to your player file</sub> | ||
|
||
## Installation | ||
> **NOTE:** GDWeave is required to use the mod, which can be found [here](https://github.com/NotNite/GDWeave/) if you do not have it yet. | ||
[Download the latest release](https://github.com/Nowaha/WebWardrobe/releases/latest/download/WebWardrobe.zip) and extract it inside of your `GDWeave/mods` folder, so that it exists as its own folder in there alongside your other mods. | ||
|
||
You should end up with this structure: | ||
``` | ||
GDWeave/ | ||
mods/ | ||
WebWardrobe/ | ||
manifest.json | ||
WebWardrobe.dll | ||
WebWardrobe.pck | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebWardrobe", "WebWardrobe\WebWardrobe.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 | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
using GDWeave.Godot; | ||
using GDWeave.Godot.Variants; | ||
using GDWeave.Modding; | ||
|
||
namespace WebWardrobe; | ||
|
||
internal class CosmeticMenuMod : IScriptMod | ||
{ | ||
public bool ShouldRun(string path) => path == "res://Scenes/HUD/CosmeticMenu/cosmetic_menu.gdc"; | ||
|
||
public IEnumerable<Token> Modify(string path, IEnumerable<Token> tokens) | ||
{ | ||
// $HBoxContainer / misc.modulate = Color(0.7, 0.7, 0.7) if category != "misc" else Color(1.0, 1.0, 1.0) | ||
var test = new MultiTokenWaiter([ | ||
t => t is IdentifierToken { Name: "misc" }, | ||
t => t is IdentifierToken { Name: "modulate" }, | ||
t => t.Type == TokenType.Newline, | ||
], allowPartialMatch: true); | ||
|
||
foreach (var token in tokens) | ||
{ | ||
if (test.Check(token)) | ||
{ | ||
yield return token; | ||
|
||
// $HBoxContainer / outfits.modulate = Color(0.7, 0.7, 0.7) if category != "outfits" else Color(1.0, 1.0, 1.0) | ||
yield return new Token(TokenType.Dollar); | ||
yield return new IdentifierToken("HBoxContainer"); | ||
yield return new Token(TokenType.OpDiv); | ||
yield return new IdentifierToken("outfits"); | ||
yield return new Token(TokenType.Period); | ||
yield return new IdentifierToken("modulate"); | ||
yield return new Token(TokenType.OpAssign); | ||
yield return new Token(TokenType.BuiltInType, 14); // Color | ||
yield return new Token(TokenType.ParenthesisOpen); | ||
yield return new ConstantToken(new RealVariant(0.7)); | ||
yield return new Token(TokenType.Comma); | ||
yield return new ConstantToken(new RealVariant(0.7)); | ||
yield return new Token(TokenType.Comma); | ||
yield return new ConstantToken(new RealVariant(0.7)); | ||
yield return new Token(TokenType.ParenthesisClose); | ||
yield return new Token(TokenType.CfIf); | ||
yield return new IdentifierToken("category"); | ||
yield return new Token(TokenType.OpNotEqual); | ||
yield return new ConstantToken(new StringVariant("outfits")); | ||
yield return new Token(TokenType.CfElse); | ||
yield return new Token(TokenType.BuiltInType, 14); // Color | ||
yield return new Token(TokenType.ParenthesisOpen); | ||
yield return new ConstantToken(new RealVariant(1.0)); | ||
yield return new Token(TokenType.Comma); | ||
yield return new ConstantToken(new RealVariant(1.0)); | ||
yield return new Token(TokenType.Comma); | ||
yield return new ConstantToken(new RealVariant(1.0)); | ||
yield return new Token(TokenType.ParenthesisClose); | ||
yield return new Token(TokenType.Newline, 1); | ||
} | ||
else | ||
{ | ||
// return the original token | ||
yield return token; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
using GDWeave.Godot; | ||
using GDWeave.Godot.Variants; | ||
using GDWeave.Modding; | ||
|
||
namespace WebWardrobe; | ||
|
||
internal class HudMod : IScriptMod | ||
{ | ||
public bool ShouldRun(string path) => path == "res://Scenes/HUD/playerhud.gdc"; | ||
|
||
public IEnumerable<Token> Modify(string path, IEnumerable<Token> tokens) | ||
{ | ||
var topOfFile = new MultiTokenWaiter([ | ||
t => t.Type == TokenType.Newline, | ||
t => t.Type == TokenType.Newline, | ||
], allowPartialMatch: true); | ||
|
||
// if popups == [] and not OptionsMenu.open: | ||
var check = new MultiTokenWaiter([ | ||
t => t.Type == TokenType.CfIf, | ||
t => t is IdentifierToken { Name: "popups" }, | ||
t => t.Type == TokenType.OpEqual, | ||
t => t.Type == TokenType.OpAnd, | ||
t => t.Type == TokenType.OpNot, | ||
t => t is IdentifierToken { Name: "open" } | ||
], allowPartialMatch: true); | ||
|
||
foreach (var token in tokens) | ||
{ | ||
if (topOfFile.Check(token)) | ||
{ | ||
yield return token; | ||
|
||
// var typing = false | ||
yield return new Token(TokenType.PrVar); | ||
yield return new IdentifierToken("typing"); | ||
yield return new Token(TokenType.OpAssign); | ||
yield return new ConstantToken(new BoolVariant(false)); | ||
yield return new Token(TokenType.Newline); | ||
} else if (check.Check(token)) | ||
{ | ||
yield return token; | ||
|
||
// and not typing | ||
yield return new Token(TokenType.OpAnd); | ||
yield return new Token(TokenType.OpNot); | ||
yield return new IdentifierToken("typing"); | ||
} | ||
else | ||
{ | ||
// return the original token | ||
yield return token; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using GDWeave; | ||
|
||
namespace WebWardrobe; | ||
|
||
public class Mod : IMod { | ||
|
||
public Mod(IModInterface modInterface) { | ||
modInterface.RegisterScriptMod(new HudMod()); | ||
modInterface.RegisterScriptMod(new CosmeticMenuMod()); | ||
} | ||
|
||
public void Dispose() { | ||
// Cleanup anything you do here | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
<AssemblySearchPaths>$(AssemblySearchPaths);$(GDWeavePath)/core</AssemblySearchPaths> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<Reference Include="GDWeave" Private="false"/> | ||
<Reference Include="Serilog" Private="false"/> | ||
</ItemGroup> | ||
|
||
<Target | ||
Name="PostBuild" | ||
AfterTargets="PostBuildEvent" | ||
Condition="'$(GDWeavePath)' != ''"> | ||
<Exec | ||
Command="xcopy /Y /I "$(TargetDir)" "$(GDWeavePath)/mods/$(AssemblyName)"" | ||
Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))'" | ||
/> | ||
</Target> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 17 | ||
VisualStudioVersion = 17.5.002.0 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebWardrobe", "WebWardrobe.csproj", "{20661229-EA27-4911-9CC9-40B0C55B92E2}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{20661229-EA27-4911-9CC9-40B0C55B92E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{20661229-EA27-4911-9CC9-40B0C55B92E2}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{20661229-EA27-4911-9CC9-40B0C55B92E2}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{20661229-EA27-4911-9CC9-40B0C55B92E2}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {D13EFD86-374A-417A-BC9F-F6F1A7F98DE0} | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
[preset.0] | ||
|
||
name="Windows Desktop" | ||
platform="Windows Desktop" | ||
runnable=true | ||
custom_features="" | ||
export_filter="all_resources" | ||
include_filter="" | ||
exclude_filter="" | ||
export_path="" | ||
script_export_mode=1 | ||
script_encryption_key="" | ||
|
||
[preset.0.options] | ||
|
||
custom_template/debug="" | ||
custom_template/release="" | ||
binary_format/64_bits=true | ||
binary_format/embed_pck=false | ||
texture_format/bptc=false | ||
texture_format/s3tc=true | ||
texture_format/etc=false | ||
texture_format/etc2=false | ||
texture_format/no_bptc_fallbacks=true | ||
codesign/enable=false | ||
codesign/identity_type=0 | ||
codesign/identity="" | ||
codesign/password="" | ||
codesign/timestamp=true | ||
codesign/timestamp_server_url="" | ||
codesign/digest_algorithm=1 | ||
codesign/description="" | ||
codesign/custom_options=PoolStringArray( ) | ||
application/modify_resources=true | ||
application/icon="" | ||
application/file_version="" | ||
application/product_version="" | ||
application/company_name="" | ||
application/product_name="" | ||
application/file_description="" | ||
application/copyright="" | ||
application/trademarks="" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
extends Node | ||
|
||
var saved_outfits: Dictionary = {} | ||
|
||
const file_path = "user://outfits.json" | ||
|
||
func _ready(): | ||
load_outfits_from_file() | ||
|
||
func load_outfit(name: String) -> bool: | ||
if not saved_outfits.has(name): return false | ||
|
||
var player = find_player() | ||
if player == null: return false | ||
|
||
PlayerData.cosmetics_equipped = saved_outfits[name].duplicate() | ||
player._change_cosmetics() | ||
return true | ||
|
||
func save_outfit(name: String) -> bool: | ||
saved_outfits[name] = PlayerData.cosmetics_equipped.duplicate() | ||
save_outfits_to_file() | ||
return true | ||
|
||
func del_outfit(name: String): | ||
saved_outfits.erase(name) | ||
|
||
func _input(event): | ||
if Input.is_action_just_pressed("menu_open"): | ||
inject() | ||
|
||
func inject(): | ||
var player = find_player() | ||
if player == null: return | ||
|
||
var hud: Node = player.hud | ||
if hud == null: return | ||
|
||
var main: Node = hud.get_child(0) | ||
if main == null: return | ||
|
||
var outfit: Node = main.find_node("outfit") | ||
|
||
var button_container: HBoxContainer = outfit.get_child(1) | ||
if button_container.get_child_count() != 4: return | ||
|
||
var outfit_button: Button = create_button("outfits", "OUTFITS") | ||
outfit_button.modulate = Color(0.7, 0.7, 0.7) | ||
outfit_button.size_flags_horizontal = 3 | ||
outfit_button.connect("pressed", self, "_button_clicked", [outfit]) | ||
button_container.add_child(outfit_button) | ||
|
||
var tabs: Node = outfit.get_child(2).get_child(0) | ||
|
||
var outfits_tab = load("res://mods/WebWardrobe/outfits.tscn").instance() | ||
outfits_tab.name = "outfits" | ||
outfits_tab._setup(self) | ||
tabs.add_child(outfits_tab) | ||
|
||
|
||
func _button_clicked(menu): | ||
menu._change_tab("outfits") | ||
|
||
|
||
|
||
|
||
|
||
# Utils | ||
func find_player() -> Node: | ||
var nodes = get_tree().get_nodes_in_group("player") | ||
|
||
if nodes.empty(): return null | ||
return nodes[0] | ||
|
||
func create_button(name: String, text: String = name) -> Button: | ||
var button: Button = Button.new() | ||
button.name = name | ||
button.text = text | ||
return button | ||
|
||
func save_outfits_to_file() -> void: | ||
var file = File.new() | ||
if file.open(file_path, File.WRITE) == OK: | ||
var json = to_json(saved_outfits) | ||
file.store_string(json) | ||
file.close() | ||
print("Saved outfits to file!") | ||
else: | ||
print("Failed to save outfits") | ||
|
||
func load_outfits_from_file() -> void: | ||
var file = File.new() | ||
if file.open(file_path, File.READ) == OK: | ||
var json = file.get_as_text() | ||
saved_outfits = parse_json(json) | ||
file.close() | ||
print("Loaded outfits from file!") | ||
else: | ||
print("Failed to load outfits") |
Oops, something went wrong.