From f8401de9f8df807333da7ee0b70a9b7651e937f4 Mon Sep 17 00:00:00 2001 From: Benjamyn Love Date: Tue, 27 Aug 2024 12:39:08 +1000 Subject: [PATCH] Updated to 3.0.1 and refactored a lot --- Looplicator/Scripts/main.lua | 215 +++++++++++++++++++++ README.md | 11 +- Scripts/main.lua | 335 --------------------------------- TestGround/Scripts/main.lua | 107 +++++++++++ shared/BenUtils/BenUtils.lua | 87 +++++++++ shared/UEHelpers/UEHelpers.lua | 113 +++++++++++ 6 files changed, 532 insertions(+), 336 deletions(-) create mode 100644 Looplicator/Scripts/main.lua delete mode 100644 Scripts/main.lua create mode 100644 TestGround/Scripts/main.lua create mode 100644 shared/BenUtils/BenUtils.lua create mode 100644 shared/UEHelpers/UEHelpers.lua diff --git a/Looplicator/Scripts/main.lua b/Looplicator/Scripts/main.lua new file mode 100644 index 0000000..6fee3d7 --- /dev/null +++ b/Looplicator/Scripts/main.lua @@ -0,0 +1,215 @@ +local UtilLib = require("BenUtils") +local BenUtils = UtilLib.new() + +-- Globals +LOOPLICATOR_PRE_ID = 0 +LOOPLICATOR_POST_ID = 0 +LOOPLICATOR_MULITPLIER = 2 +LOOPLICATOR_ROUNDS = 10 +LOOPLICATOR_XL_COST = 1 +LOOPLICATOR_ALL_MODS = false +LOOPLICATOR_NUM_MODS = 3 + +-- End Globals + +-- Internal functions + +---@param pre number +---@param post number +local function SetLooplicatorHookIds(pre, post) + ModRef:SetSharedVariable("LooplicatorPreID", pre) + ModRef:SetSharedVariable("LooplicatorPostID", post) +end + +local function GetLooplicatorHookIds() + local pre = ModRef:GetSharedVariable("LooplicatorPreID") + local post = ModRef:GetSharedVariable("LooplicatorPostID") + return pre, post +end + +local function GetIsActive() + return ModRef:GetSharedVariable("LooplicatorEnabled") +end + +local function SetIsActive(active) + ModRef:SetSharedVariable("LooplicatorEnabled", active) +end + +-- End internal functions + +-- Mod functions + +---@param PlayerName string +function LooplicatorSettings(PlayerName, ...) + print("[BenUtil] Got chat command loopset from " .. PlayerName) + ---@class player ACrabPC + local player = FindFirstOf("CrabPC") + player:ServerSendChatMessage(BenUtils.StringToFString("Looplicator settings:")) + player:ServerSendChatMessage(BenUtils.StringToFString(string.format("Enabled: %s", tostring(LOOPLICATOR_POST_ID > 0)))) + player:ServerSendChatMessage(BenUtils.StringToFString(string.format("Num of rounds: %d", LOOPLICATOR_ROUNDS))) + player:ServerSendChatMessage(BenUtils.StringToFString(string.format("XL cost: %d", LOOPLICATOR_XL_COST))) + player:ServerSendChatMessage(BenUtils.StringToFString(string.format("Multiply all mods: %s", + tostring(LOOPLICATOR_ALL_MODS)))) + player:ServerSendChatMessage(BenUtils.StringToFString(string.format("Num of mods to Multiply: %d", + LOOPLICATOR_NUM_MODS))) +end + +function looplicator() + local gamestate = FindFirstOf("CrabGS") + local player = FindFirstOf("CrabPC") + + local island_num = gamestate.CurrentIsland + if island_num % (LOOPLICATOR_ROUNDS) == 0.00 then + gamestate.XLLevel = 1 + player:ServerSendChatMessage(BenUtils.StringToFString("Looplicator Challenge Round")) + player:ServerSendChatMessage(BenUtils.StringToFString("All Items will double their levels next round")) + player:ServerSendChatMessage(BenUtils.StringToFString("If you win that is!")) + end + -- This checks to see if the last round was divisble by 10 + if island_num ~= 1 and (island_num - 1) % LOOPLICATOR_ROUNDS == 0.00 then + print("[BenUtils] Triggered Looplicator, doubling levels of all perks") + local crabs = FindAllOf("CrabPS") + + if crabs then + if LOOPLICATOR_ALL_MODS then + ---@param v ACrabPS + for i, v in ipairs(crabs) do + ---@param wmod FCrabWeaponMod + v.WeaponMods:ForEach(function(index, wmod) + ---@class mod FCrabWeaponMod + local mod = wmod:get() + if mod.InventoryInfo.Level ~= 255 then + if mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER < 255 then + mod.InventoryInfo.Level = mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER + else + mod.InventoryInfo.Level = 255 + end + end + end) + ---@param wmod FCrabAbilityMod + v.AbilityMods:ForEach(function(index, wmod) + ---@class mod FCrabAbilityMod + local mod = wmod:get() + if mod.InventoryInfo.Level ~= 255 then + if mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER < 255 then + mod.InventoryInfo.Level = mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER + else + mod.InventoryInfo.Level = 255 + end + end + end) + ---@param wmod FCrabMeleeMod + v.MeleeMods:ForEach(function(index, wmod) + ---@class mod FCrabMeleeMod + local mod = wmod:get() + if mod.InventoryInfo.Level ~= 255 then + if mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER < 255 then + mod.InventoryInfo.Level = mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER + else + mod.InventoryInfo.Level = 255 + end + end + end) + ---@param wmod FCrabPerk + v.Perks:ForEach(function(index, wmod) + ---@class mod FCrabPerk + local mod = wmod:get() + if mod.InventoryInfo.Level ~= 255 then + if mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER < 255 then + mod.InventoryInfo.Level = mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER + else + mod.InventoryInfo.Level = 255 + end + end + end) + end + else + ---@type table + + for i, v in ipairs(crabs) do + local mods = {} + print(string.format("Crab with ID: %s", v.PlayerNamePrivate:ToString())) + ---@param wmod FCrabWeaponMod + v.WeaponMods:ForEach(function(index, wmod) + ---@class mod FCrabWeaponMod + local mod = wmod:get() + table.insert(mods, mod) + end) + ---@param wmod FCrabAbilityMod + v.AbilityMods:ForEach(function(index, wmod) + ---@class mod FCrabAbilityMod + local mod = wmod:get() + table.insert(mods, mod) + end) + ---@param wmod FCrabMeleeMod + v.MeleeMods:ForEach(function(index, wmod) + ---@class mod FCrabMeleeMod + local mod = wmod:get() + table.insert(mods, mod) + end) + ---@param wmod FCrabPerk + v.Perks:ForEach(function(index, wmod) + ---@class mod FCrabPerk + local mod = wmod:get() + table.insert(mods, mod) + end) + -- Shuffle the mods table so the mods are more random + BenUtils.ShuffleInPlace(mods) + ---@type table + local to_upgrade = {} + for index, mod in ipairs(mods) do + if #to_upgrade < LOOPLICATOR_NUM_MODS then + if math.random(2) == 1 then + print(string.format("Upgrading mod with index %d", index)) + table.insert(to_upgrade, mod) + end + end + end + print(string.format("We have %s mods to upgrade", #to_upgrade)) + for index, mod in ipairs(to_upgrade) do + if mod.InventoryInfo.Level ~= 255 then + if mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER < 255 then + mod.InventoryInfo.Level = mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER + else + mod.InventoryInfo.Level = 255 + end + end + end + end + end + end + end +end + +function ToggleLooplicator() + ---@type AcrabPC + local player = FindFirstOf("CrabPC") + if LOOPLICATOR_POST_ID == 0 and LOOPLICATOR_POST_ID == 0 then + LOOPLICATOR_PRE_ID, LOOPLICATOR_POST_ID = RegisterHook("/Script/CrabChampions.CrabPC:ClientOnEnteredPortal", + looplicator) + player:ServerSendChatMessage(BenUtils.StringToFString("Enabling looplicator")) + else + UnregisterHook("/Script/CrabChampions.CrabPC:ClientOnEnteredPortal", LOOPLICATOR_PRE_ID, LOOPLICATOR_POST_ID) + LOOPLICATOR_PRE_ID = 0 + LOOPLICATOR_POST_ID = 0 + player:ServerSendChatMessage(BenUtils.StringToFString("Disabling looplicator")) + end +end + +-- End mod functions + +-- Register Hooks and Commands +RegisterKeyBind(Key.F3, function() + print("[BenUtils] Enabled Looplicator\n") + ExecuteInGameThread(function() + ToggleLooplicator() + end) +end) + +BenUtils.RegisterCommand("looplicator", ToggleLooplicator) +BenUtils.RegisterCommand("loopset", LooplicatorSettings) +-- End Register Hooks and Commands + +-- -- Set init values here +-- SetIsActive(false) +-- -- End init values diff --git a/README.md b/README.md index dbfd2f2..5161fa4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,13 @@ # Crab Champions Utilities Mod -This uses [UE4SS 2.5.2](https://github.com/UE4SS-RE/RE-UE4SS) +This uses [UE4SS 3.0.1](https://github.com/UE4SS-RE/RE-UE4SS) +You might need to use the experimental version [here](https://objects.githubusercontent.com/github-production-release-asset-2e65be/561442199/91ba6ac9-b885-4c12-af1d-d4e1b40bc1a8?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=releaseassetproduction%2F20240824%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240824T055629Z&X-Amz-Expires=300&X-Amz-Signature=1fbfb07bfdcef82c9dfd53f76c7897ee6469b4499afe74ab91c2df558dc958ab&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=561442199&response-content-disposition=attachment%3B%20filename%3DzDEV-UE4SS_v3.0.1-54-g3976965.zip&response-content-type=application%2Foctet-stream) + +If your game crashes on boot then change the setting `bUseUObjectArrayCache = true` to `bUseUObjectArrayCache = false` in `UE4SS-settings.ini` + +Structure: + - shared/BenUtils (Shared library of general use functions) + - Looplicator (Looplicator mod see readme in directory) + - TestGround (Testing file for mod development) + - UEHelpers (Updated UEHelpers class for UKismetTextLibrary support) diff --git a/Scripts/main.lua b/Scripts/main.lua deleted file mode 100644 index db7823b..0000000 --- a/Scripts/main.lua +++ /dev/null @@ -1,335 +0,0 @@ -print("[BenUtils] Loaded and waiting!") - ---- Swapping to use register/unregister --- Disable looplicator by default --- LOOPLICATOR_ENABLED = false --- - - --- Globals -LOOPLICATOR_PRE_ID = 0 -LOOPLICATOR_POST_ID = 0 -LOOPLICATOR_MULITPLIER = 2 -LOOPLICATOR_ROUNDS = 10 -LOOPLICATOR_XL_COST = 1 - -COMMANDS_REGISTERED = {} --- End Globals - ----@param command string ----@param callback function -function RegisterCommand(command, callback) - COMMANDS_REGISTERED[command] = callback - print(string.format("[BenUtils] Registered command %s", command)) -end - -function FindKeyTodem() - print("test") - ---@type table - local todems = FindAllOf("CrabTotem") - print("Found " .. #todems .. " todems") - for i, item in ipairs(todems) do - if item.TotemType == 3 then - return item - end - end -end - ----@param PlayerName string -function GetPlayerStateByName(PlayerName) - local crabs = FindAllOf("CrabPS") - for _, v in ipairs(crabs) do - -- local crab = v:get() - if v.PlayerNamePrivate:ToString() == PlayerName then - return v - end - end - return nil -end - -function LookupCCWeaponByName(itemname) - -end - -function LookupCCPerkByName(itemname) - ---@type table - local perks = FindAllOf("CrabPerkDA") - print("Found " .. #perks .. " perks") - for i, item in ipairs(perks) do - if item.Name:ToString() == itemname then - return item - end - end - return nil -end - -function LookupCCAbilityByName(itemname) - -end - -function LookupCCMeleeByName(itemname) - -end - -function LookupCCArtifactByName(itemname) - -end - --- Force UI Refresh? ACrabPC:ClientRefreshPSUI - ----@param CRAB ACrabInteractPickup ----@param nim any -function CheckReturnedSelf(CRAB, nim) - -- print(string.format("You have: %d crystals\n", CRAB.Keys)) - print(nim.PickupInfo.PickupDA.Name:ToString()) -end - -function SetScaleMultiplier() - ---@param crab ACrabPS - local crab = FindFirstOf("CrabPS") - print(type(crab)) - if crab then - print(string.format("[BenUtils] The current ScaleMultiplier is: %.3f", crab.ScaleMultiplier)) - end -end - -function GiveInitialStreamerLoot() - -- Get a copy of the game state and a list of players and the StreamerLoot item - local streamerloot = LookupCCPerkByName("Streamer Loot") - local gamestate = FindFirstOf("CrabGS") - local crabs = FindAllOf("CrabPS") - local crabss = FindAllOf("CrabPC") - local key_totem = FindKeyTodem() - crabs[1].Crystals = 10000000000 - crabss[1]:ClientRefreshPSUI() - ---@param v ACrabPS - -- for i, v in ipairs(crabs) do - -- v.ServerSpawnKeyTotemPickup(key_totem,) - - -- print(string.format("%d", x.TotemType)) - -- end -end - ----@param PlayerName string -function GiveCrystalsToPlayer(PlayerName, ...) - local args = table.pack(...) - ---@type ACrabPS - local player = GetPlayerStateByName(PlayerName) - if player and #args == 1 then - player.Crystals = tonumber(args[1]) or player.Crystals - end -end - -function GibCrystals() - local crabs = FindAllOf("CrabPS") - - if crabs then - ---@param v ACrabPS - for i, v in ipairs(crabs) do - v.Crystals = 10000000 - end - end -end - -function SetAllPerks100() - local crabs = FindAllOf("CrabPS") - - if crabs then - ---@param v ACrabPS - for i, v in ipairs(crabs) do - print(string.format("Crab with ID: %s", v.PlayerNamePrivate:ToString())) - if v.PlayerNamePrivate:ToString() == "Aztec" then - ---@param wmod FCrabWeaponMod - v.WeaponMods:ForEach(function(index, wmod) - ---@class mod FCrabWeaponMod - local mod = wmod:get() - if mod.InventoryInfo.Level <= 100 then - mod.InventoryInfo.Level = 100 - end - end) - ---@param wmod FCrabAbilityMod - v.AbilityMods:ForEach(function(index, wmod) - ---@class mod FCrabAbilityMod - local mod = wmod:get() - if mod.InventoryInfo.Level <= 100 then - mod.InventoryInfo.Level = 100 - end - end) - ---@param wmod FCrabMeleeMod - v.MeleeMods:ForEach(function(index, wmod) - ---@class mod FCrabMeleeMod - local mod = wmod:get() - if mod.InventoryInfo.Level <= 100 then - mod.InventoryInfo.Level = 100 - end - end) - ---@param wmod FCrabPerk - v.Perks:ForEach(function(index, wmod) - ---@class mod FCrabPerk - local mod = wmod:get() - if mod.InventoryInfo.Level <= 100 then - mod.InventoryInfo.Level = 100 - end - end) - end - end - end -end - -function looplicator() - local gamestate = FindFirstOf("CrabGS") - - local island_num = gamestate.CurrentIsland - if island_num % (LOOPLICATOR_ROUNDS) == 0.00 then - gamestate.XLLevel = 1 - end - -- This checks to see if the last round was divisble by 10 - if island_num ~= 1 and (island_num - 1) % LOOPLICATOR_ROUNDS == 0.00 then - print("[BenUtils] Triggered Looplicator, doubling levels of all perks") - local crabs = FindAllOf("CrabPS") - - if crabs then - ---@param v ACrabPS - for i, v in ipairs(crabs) do - ---@param wmod FCrabWeaponMod - v.WeaponMods:ForEach(function(index, wmod) - ---@class mod FCrabWeaponMod - local mod = wmod:get() - if mod.InventoryInfo.Level ~= 255 then - if mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER < 255 then - mod.InventoryInfo.Level = mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER - else - mod.InventoryInfo.Level = 255 - end - end - end) - ---@param wmod FCrabAbilityMod - v.AbilityMods:ForEach(function(index, wmod) - ---@class mod FCrabAbilityMod - local mod = wmod:get() - if mod.InventoryInfo.Level ~= 255 then - if mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER < 255 then - mod.InventoryInfo.Level = mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER - else - mod.InventoryInfo.Level = 255 - end - end - end) - ---@param wmod FCrabMeleeMod - v.MeleeMods:ForEach(function(index, wmod) - ---@class mod FCrabMeleeMod - local mod = wmod:get() - if mod.InventoryInfo.Level ~= 255 then - if mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER < 255 then - mod.InventoryInfo.Level = mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER - else - mod.InventoryInfo.Level = 255 - end - end - end) - ---@param wmod FCrabPerk - v.Perks:ForEach(function(index, wmod) - ---@class mod FCrabPerk - local mod = wmod:get() - if mod.InventoryInfo.Level ~= 255 then - if mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER < 255 then - mod.InventoryInfo.Level = mod.InventoryInfo.Level * LOOPLICATOR_MULITPLIER - else - mod.InventoryInfo.Level = 255 - end - end - end) - end - end - end -end - -function enable_looplicator() - if LOOPLICATOR_POST_ID == 0 and LOOPLICATOR_POST_ID == 0 then - LOOPLICATOR_PRE_ID, LOOPLICATOR_POST_ID = RegisterHook("/Script/CrabChampions.CrabPC:ClientOnEnteredPortal", - looplicator) - else - UnregisterHook("/Script/CrabChampions.CrabPC:ClientOnEnteredPortal", LOOPLICATOR_PRE_ID, LOOPLICATOR_POST_ID) - LOOPLICATOR_PRE_ID = 0 - LOOPLICATOR_POST_ID = 0 - end -end - ----@param PlayerName string -function RollTheDice(PlayerName, ...) - print("[BenUtil] Got chat command rtd from " .. PlayerName) - local args = table.pack(...) - for k, v in ipairs(args) do - print(string.format("[BenUtil] Arg: %s", v)) - end - -- print(string.format("[BenUtil] %d arguments sent", args.n)) -end - ----@param PlayerName FString ----@param ChatMessage FString -function ParseChatCommand(self, PlayerName, ChatMessage) - local playername = PlayerName:get() - local chatmessage = ChatMessage:get() - local firstchar = string.sub(chatmessage:ToString(), 1, 1) - ---@type table - local command = {} - if firstchar == "/" then - for i in string.gmatch(chatmessage:ToString(), "%S+") do - table.insert(command, i) - end - local cmd = string.sub(command[1], 2, #command[1]) - -- local args = table.remove(command, 1) - if COMMANDS_REGISTERED[cmd] then - COMMANDS_REGISTERED[cmd](playername:ToString(), table.unpack(command, 2, #command)) - end - end -end - ----@param KeyTotem ACrabTotem -function TestThing(self, KeyTotem) - local test = KeyTotem:get() - print(string.format("%d", test.NumBuffs)) - print(string.format("%d", test.NumDeBuffs)) - print(string.format("%d", test.Cost)) -end - ----@param NextIslandInfo FCrabNextIslandInfo -function TestThing2(self, NextIslandInfo) - local test = NextIslandInfo:get() - print(string.format("%d", test.CurrentIsland)) - -- print(string.format("%d", test.NumDeBuffs)) - -- print(string.format("%d", test.Cost)) -end - --- RegisterKeyBind(Key.F1, function() --- print("[BenUtils] Set Perks to 100\n") --- ExecuteInGameThread(function() --- SetAllPerks100() --- end) --- end) - --- RegisterKeyBind(Key.F2, function() --- print("[BenUtils] Money Money Money\n") --- ExecuteInGameThread(function() --- GibCrystals() --- end) --- end) - -RegisterKeyBind(Key.F3, function() - print("[BenUtils] Enabled Looplicator\n") - ExecuteInGameThread(function() - enable_looplicator() - end) -end) - --- RegisterHook("/Script/CrabChampions.CrabPC:ClientOnInteractedWithKeyTotem", TestThing) --- RegisterHook("/Script/CrabChampions.CrabPC:ClientOnEnteredPortal", TestThing2) -RegisterHook("/Script/CrabChampions.CrabPC:ClientOnReceivedChatMessage", ParseChatCommand) -RegisterCommand("rtd", RollTheDice) -RegisterCommand("dosh", GiveCrystalsToPlayer) --- RegisterHook("/Script/CrabChampions.CrabPC:ClientOnInteractedWithKeyTotem", TestThing); --- NotifyOnNewObject("/Script/Engine.Actor", function(ConstructedObject) --- print(string.format("Constructed: %s\n", ConstructedObject:GetFullName())) --- end) - ---- CrabInteractPickup /Game/Island/Persistent.Persistent:PersistentLevel.CrabInteractPickup_2147481644 diff --git a/TestGround/Scripts/main.lua b/TestGround/Scripts/main.lua new file mode 100644 index 0000000..56b9d10 --- /dev/null +++ b/TestGround/Scripts/main.lua @@ -0,0 +1,107 @@ +local UtilLib = require("BenUtils") +local BenUtils = UtilLib.new() + +-- Globals + +-- End Globals + +-- Utility Functions +-- End utility functions + +-- Mod functions + +---@param PlayerName string +function GiveCrystalsToPlayer(PlayerName, ...) + local args = table.pack(...) + ---@type ACrabPS + local player = BenUtils.GetPlayerStateByName(PlayerName) + if player and #args == 1 then + player.Crystals = tonumber(args[1]) or player.Crystals + end +end + +function SetAllPerks100() + local crabs = FindAllOf("CrabPS") + + if crabs then + ---@param v ACrabPS + for i, v in ipairs(crabs) do + print(string.format("Crab with ID: %s", v.PlayerNamePrivate:ToString())) + if v.PlayerNamePrivate:ToString() == "Aztec" then + ---@param wmod FCrabWeaponMod + v.WeaponMods:ForEach(function(index, wmod) + ---@class mod FCrabWeaponMod + local mod = wmod:get() + if mod.InventoryInfo.Level <= 100 then + mod.InventoryInfo.Level = 100 + end + end) + ---@param wmod FCrabAbilityMod + v.AbilityMods:ForEach(function(index, wmod) + ---@class mod FCrabAbilityMod + local mod = wmod:get() + if mod.InventoryInfo.Level <= 100 then + mod.InventoryInfo.Level = 100 + end + end) + ---@param wmod FCrabMeleeMod + v.MeleeMods:ForEach(function(index, wmod) + ---@class mod FCrabMeleeMod + local mod = wmod:get() + if mod.InventoryInfo.Level <= 100 then + mod.InventoryInfo.Level = 100 + end + end) + ---@param wmod FCrabPerk + v.Perks:ForEach(function(index, wmod) + ---@class mod FCrabPerk + local mod = wmod:get() + if mod.InventoryInfo.Level <= 100 then + mod.InventoryInfo.Level = 100 + end + end) + end + end + end +end + +---@param PlayerName string +function RollTheDice(PlayerName, ...) + print("[BenUtil] Got chat command rtd from " .. PlayerName) + local args = table.pack(...) + for k, v in ipairs(args) do + print(string.format("[BenUtil] Arg: %s", v)) + end + -- print(string.format("[BenUtil] %d arguments sent", args.n)) + ---@type ACrabPC + local player = FindFirstOf("CrabPC") + player:ServerSendChatMessage(BenUtils.StringToFString("You rolled the dice")) +end + +-- End mod functions + +-- Register Hooks and Keybinds + +RegisterKeyBind(Key.F1, function() + ExecuteInGameThread(function() + local msg = BenUtils.StringToFString("Fuck cheese") + ---@type ACrabPC + local player = FindFirstOf("CrabPC") + player:ServerSendChatMessage(msg) + end) +end) + +-- RegisterKeyBind(Key.F2, function() +-- print("[BenUtils] Money Money Money\n") +-- ExecuteInGameThread(function() +-- GibCrystals() +-- end) +-- end) + + + +BenUtils.RegisterCommand("rtd", RollTheDice) +BenUtils.RegisterCommand("dosh", GiveCrystalsToPlayer) +BenUtils.RegisterCommand("cheat", SetAllPerks100) + +-- Finish Hooks and Keybinds diff --git a/shared/BenUtils/BenUtils.lua b/shared/BenUtils/BenUtils.lua new file mode 100644 index 0000000..dafc606 --- /dev/null +++ b/shared/BenUtils/BenUtils.lua @@ -0,0 +1,87 @@ +---@class BenUtils +local BenUtils = {} +BenUtils.__index = BenUtils + +local UEHelpers = require("UEHelpers") +local TextLib = UEHelpers:GetKismetTextLibrary() + +-- Globals +local commands_registered = {} + +-- End Globals + +-- Internal functions + + +-- End internal functions + +-- Utility Functions + +---@return self +function BenUtils.new() + local self = setmetatable({}, BenUtils) + return self +end + +function BenUtils.ShuffleInPlace(t) + for i = #t, 2, -1 do + local j = math.random(i) + t[i], t[j] = t[j], t[i] + end +end + +---@param command string +---@param callback function +function BenUtils.RegisterCommand(command, callback) + commands_registered[command] = callback + -- AddRegisteredCommand(command, callback) + print(string.format("[BenUtils] Registered command %s", command)) +end + +---@param PlayerName string +function BenUtils.GetPlayerStateByName(PlayerName) + local crabs = FindAllOf("CrabPS") + for _, v in ipairs(crabs) do + -- local crab = v:get() + if v.PlayerNamePrivate:ToString() == PlayerName then + return v + end + end + return nil +end + +---@param input string +function BenUtils.StringToFString(input) + -- I have to first convert the input to an FText + -- Then I can call the Conv_TextToString function to get an FSTring + local ftext_obj = FText(input) + return TextLib:Conv_TextToString(ftext_obj) +end + +---@param PlayerName FString +---@param ChatMessage FString +function BenUtils.ParseChatCommand(self, PlayerName, ChatMessage) + local playername = PlayerName:get() + local chatmessage = ChatMessage:get() + local firstchar = string.sub(chatmessage:ToString(), 1, 1) + ---@type table + local command = {} + if firstchar == "/" then + for i in string.gmatch(chatmessage:ToString(), "%S+") do + table.insert(command, i) + end + local cmd = string.sub(command[1], 2, #command[1]) + -- local args = table.remove(command, 1) + if commands_registered[cmd] then + commands_registered[cmd](playername:ToString(), table.unpack(command, 2, #command)) + end + end +end + +-- End utility functions + +-- Register Util hooks here +RegisterHook("/Script/CrabChampions.CrabPC:ClientOnReceivedChatMessage", BenUtils.ParseChatCommand) +-- End registry hooks + +return BenUtils diff --git a/shared/UEHelpers/UEHelpers.lua b/shared/UEHelpers/UEHelpers.lua new file mode 100644 index 0000000..4558551 --- /dev/null +++ b/shared/UEHelpers/UEHelpers.lua @@ -0,0 +1,113 @@ +local UEHelpers = {} +-- Uncomment the below require to use the Lua VM profiler on these functions +-- local jsb = require "jsbProfi" + +-- Version 1 does not exist, we start at version 2 because the original version didn't have a version at all. +local Version = 2 + +-- Functions local to this module, do not attempt to use! +local CacheDefaultObject = function(ObjectFullName, VariableName, ForceInvalidateCache) + local DefaultObject + + if not ForceInvalidateCache then + DefaultObject = ModRef:GetSharedVariable(VariableName) + if DefaultObject and DefaultObject:IsValid() then return DefaultObject end + end + + DefaultObject = StaticFindObject(ObjectFullName) + ModRef:SetSharedVariable(VariableName, DefaultObject) + if not DefaultObject:IsValid() then error(string.format("%s not found", ObjectFullName)) end + + return DefaultObject +end + +-- Everything in this section can be used in any mod that requires this module. +-- Exported functions -> START + +function UEHelpers.GetUEHelpersVersion() + return Version +end + +--- Returns the first valid PlayerController that is currently controlled by a player. +---@return APlayerController +local PlayerController = nil +function UEHelpers.GetPlayerController() + if PlayerController and PlayerController:IsValid() then return PlayerController end + -- local PlayerControllers = jsb.simpleBench("findallof", FindAllOf, "Controller") + -- Uncomment line above and comment line below to profile this function + local PlayerControllers = FindAllOf("PlayerController") or FindAllOf("Controller") + if not PlayerControllers then return Print("No PlayerControllers found\n") end + for _, Controller in pairs(PlayerControllers or {}) do + if Controller.Pawn:IsValid() and Controller.Pawn:IsPlayerControlled() then + PlayerController = Controller + break + -- else + -- print("Not valid or not player controlled\n") + end + end + if PlayerController and PlayerController:IsValid() then + return PlayerController + end + error("No PlayerController found\n") +end + +--- Returns the UWorld that the player is currenlty in. +---@return UWorld +function UEHelpers.GetWorld() + return UEHelpers.GetPlayerController():GetWorld() +end + +--- Returns the UGameViewportClient for the player. +---@return AActor +function UEHelpers.GetGameViewportClient() + return UEHelpers.GetPlayerController().Player.ViewportClient +end + +--- Returns an object that's useable with UFunctions that have a WorldContextObject param. +--- Prefer to use an actor that you already have access to whenever possible over this function. +---@return AActor +function UEHelpers.GetWorldContextObject() + return UEHelpers.GetPlayerController() +end + +function UEHelpers.GetGameplayStatics(ForceInvalidateCache) + return CacheDefaultObject("/Script/Engine.Default__GameplayStatics", "UEHelpers_GameplayStatics", + ForceInvalidateCache) +end + +function UEHelpers.GetKismetSystemLibrary(ForceInvalidateCache) + return CacheDefaultObject("/Script/Engine.Default__KismetSystemLibrary", "UEHelpers_KismetSystemLibrary", + ForceInvalidateCache) +end + +function UEHelpers.GetKismetMathLibrary(ForceInvalidateCache) + return CacheDefaultObject("/Script/Engine.Default__KismetMathLibrary", "UEHelpers_KismetMathLibrary", + ForceInvalidateCache) +end + +function UEHelpers.GetKismetMathLibrary(ForceInvalidateCache) + return CacheDefaultObject("/Script/Engine.Default__KismetMathLibrary", "UEHelpers_KismetMathLibrary", + ForceInvalidateCache) +end + +function UEHelpers.GetKismetTextLibrary(ForceInvalidateCache) + return CacheDefaultObject("/Script/Engine.Default__KismetTextLibrary", "UEHelpers_KismetTextLibrary", + ForceInvalidateCache) +end + +function UEHelpers.GetGameMapsSettings(ForceInvalidateCache) + return CacheDefaultObject("/Script/EngineSettings.Default__GameMapsSettings", "UEHelpers_GameMapsSettings", + ForceInvalidateCache) +end + +function UEHelpers.FindOrAddFName(Name) + local NameFound = FName(Name, EFindName.FNAME_Find) + if NameFound == NAME_None then + NameFound = FName(Name, EFindName.FNAME_Add) + end + return NameFound +end + +-- Exported functions -> END + +return UEHelpers