Jump to content

Sqeegie

Members
  • Posts

    11
  • Joined

Posts posted by Sqeegie

  1. You would likely need to create a custom block functionality via a C# mod and hook your custom-defined block into it. I would look at SphereII's SCore or a similar mod for examples of how to implement blocks with custom functionality.

     

    For the actual repair code, I would probably do something like:

    1. Build and maintain an affected blocklist (mimic a landclaim block?)
    2. Schedule repair updates (mimic a growing plant block?)
    3. Repair affected blocks (mimic ItemActionRepair?)
  2. It looks like the camera jolt for head impact is hardcoded into the game. It's mainly controlled by the vp_FPCamera.OnMessage_HeadImpact() handler, which is triggered whenever the player takes damage or on an upward collision. I don't believe an XML mod has the capability of changing this, but a C# mod can. Here is proof of concept that should do the trick.

     

    PoC:

    Spoiler
    using HarmonyLib;
    using System.Reflection;
    
    /* .NET Framework 4.5
     * 
     * References:
     *  - 0Harmony.dll
     *  - Assembly-CSharp.dll
     *  - LogLibrary.dll
     */
    
    public class PeskyCameraJolt : IModApi
    {
        public void InitMod(Mod _modInstance)
        {
            Harmony harmony = new Harmony(base.GetType().ToString());
            harmony.PatchAll(Assembly.GetExecutingAssembly());
    
            Log.Out("[MODS] [PeskyCameraJolt] Loaded!");
        }
    
    }
    
    [HarmonyPatch(typeof(vp_FPCamera), "OnMessage_HeadImpact")]
    class HeadImpactPatch
    {
        static bool Prefix(float impact)
        {
            if (GameManager.Instance.World.GetPrimaryPlayer().vp_FPController.HeadContact) // Only skip head impact when there is head contact (i.e. collision)
            {
                return false;
            }
            return true;
        }
    }

     

     

    Compiled version (A21): https://drive.google.com/file/d/1JTLliaC0uYWvgMBfK0D0Z7_4Z6Q4H6wG

  3. Instead of permanently removing blocks/POIs or dealing with regenerating the world, I would propose a relatively simpler approach by just setting traders closed and preventing them from opening again. This would be done by creating a C# mod for the server (or client for singleplayer) by using Harmony to detour TraderArea.SetClosed(World _world, bool _bClosed, bool playSound = false) method and changing the passed _bClosed argument to always be true.

     

    PoC:

    Spoiler
    using HarmonyLib;
    using System.Reflection;
    
    /* .NET Framework 4.5
     * 
     * References:
     *  - 0Harmony.dll
     *  - Assembly-CSharp.dll
     *  - LogLibrary.dll
     */
    
    public class PeskyTrader : IModApi
    {
        public void InitMod(Mod _modInstance)
        {
            Harmony harmony = new Harmony(base.GetType().ToString());
            harmony.PatchAll(Assembly.GetExecutingAssembly());
    
            Log.Out("[MODS] [PeskyTrader] Loaded!");
        }
    }
    
    [HarmonyPatch(typeof(TraderArea), "SetClosed")]
    class TraderAreaPatch
    {
        static void Prefix(World _world, ref bool _bClosed, bool playSound = false)
        {
            _bClosed = true;
        }
    }

     

     

    Compiled version (A21): https://drive.google.com/file/d/1Fgp27a_DrV1HU-7NTkYaKaS_lNEBNQts (extract and plop into the mods folder).

  4. For multiplayer, there is a server config that handles player safe zones based on their level, time playing, and if they have placed any beds (spawn points). It adds a "lock" to any chunks the player enters, which delays all enemy spawning until the safe zone timer runs out.

     

    <property name="PlayerSafeZoneLevel" value="5" /> <!-- If a player is less or equal this level he will create a safe zone (no enemies) when spawned -->
    <property name="PlayerSafeZoneHours" value="5" /> <!-- Hours in world time this safe zone exists -->

     

  5. HeatMapStrength is stored (and parsed) as a float, which can be any number +-3.402823E+38. However, the game ignores it if it's a negative number. The HeatMapTime is stored (and parsed) as a uint, which can be any integer from 0 to 4294967295. There don't appear to be any other modifications or clamping to these besides what I've already mentioned.

  6. Block placing speed is a hardcoded constant set based on the world's gamemode (creative, editworld, survival, etc.). For example, these are the settings set in the GameManager.createWorld() function when initially loading a creative world:

     

    Constants.cDigAndBuildDistance = 25f;
    Constants.cBuildIntervall = 0.2f;
    Constants.cCollectItemDistance = 25f;

     

    The key constant here is the cBuildIntervall. The default build interval for survival is 0.5f. Luckily, there is an ingame console command that you can use to set these three constants to "editworld" values (50f, 0.2f, 50f). Just open the ingame console (F1) and execute the command "zz fr" (which stands for dynamic mesh farreach).

     

    The only other ways to change this (that I know of) would be to change the world's gamemode or create a C# mod that modifies these constants.

  7. I'm not sure how to do this in XML, but it can easily be done in C#. Here is an example for A21 that disables console commands and creative/debug menus in single player.

     

    PoC:

    Spoiler
    using UnityEngine; 
    using UnityEngine.UI;
    using HarmonyLib;
    using System.Reflection;
    
    /* .NET Framework 4.5
     * 
     * References:
     *  - 0Harmony.dll
     *  - Assembly-CSharp.dll
     *  - LogLibrary.dll
     *  - UnityEngine.CoreModule.dll
     *  - UnityEngine.UI.dll
     */
    
    public class PeskyConsole : IModApi
    {
        public void InitMod(Mod _modInstance)
        {
            if (!GameObject.FindObjectOfType<PeskyConsoleMB>())
                new GameObject().AddComponent<PeskyConsoleMB>();
    
            Harmony harmony = new Harmony(base.GetType().ToString());
            harmony.PatchAll(Assembly.GetExecutingAssembly());
    
            Log.Out("[MODS] [PeskyConsole] Loaded!");
        }
    }
    
    public class PeskyConsoleMB : MonoBehaviour
    {
        public void Update()
        {
            if (ConnectionManager.Instance.IsSinglePlayer)
            {
                bool cm = GamePrefs.GetBool(EnumGamePrefs.CreativeMenuEnabled);
                bool dm = GamePrefs.GetBool(EnumGamePrefs.DebugMenuEnabled);
                if (cm || dm)
                {
                    GamePrefs.Set(EnumGamePrefs.CreativeMenuEnabled, false);
                    GamePrefs.Set(EnumGamePrefs.DebugMenuEnabled, false);
                    GamePrefs.Instance.Save();
                }
            }
        }
    }
    
    [HarmonyPatch(typeof(GUIWindowConsole), "EnterCommand")]
    class ConsoleCommandPatch
    {
        static bool Prefix(ref InputField ___commandField, string _command)
        {
            if (ConnectionManager.Instance.IsSinglePlayer)
            {
                Log.Out("[MODS] [PeskyConsole] " + GameManager.Instance.World.GetPrimaryPlayer().EntityName + " is not in the sudoers file. This incident will be reported.");
                ___commandField.text = "";
                ___commandField.Select();
                ___commandField.ActivateInputField();
                return false;
            }
            return true;
        }
    }

     

     

    Compiled version: https://drive.google.com/file/d/1uY4gYiSgL340dbb1SOk1vjB-O2nzbRiB (extract and dump into the mods folder).

  8. There is no documentation for ModAPI except for the stuff fellow modders have gathered and posted around. The official ModAPI is very barebones, there isn't a huge list of premade methods and capability built-in. It only provides a few ModEvents and a way to initialize custom code. The rest is left up to the modder to implement. There are several primary methods we use to add our custom functionality using the ModAPI, all through the provided InitMod entrypoint:

    1. Register a handler for one of the build-in ModEvents.

    2. Patch/hook a game method via the Harmony library.

    3. Run custom code directly and/or add a new Unity GameObject to capitalize on its events.

     

    Using a tool like dnSpy, we can decompile and read the game's code to determine how it works, and based on that, we can figure out how we need to adjust it in order to add our desired functionality.

     

    For your questions:

    1. As commented previously, there is the "say" command built-in the game. We can take a look at how the game executes this command natively and use the same methodology to do it ourselves in a ModAPI mod. Open the Assembly-CSharp.dll using dnSpy and find the class that handles the "say" console command. It may take some digging to find it. In this case, I found it under the ConsoleCmdServerMessage class. Reading the code, the key line that stands out is:
      GameManager.Instance.ChatMessageServer(null, EChatType.Global, -1, msg, "Server", false, null);

      Taking a closer look at this method reveals the parameters:
      ChatMessageServer(ClientInfo _cInfo, EChatType _chatType, int _senderEntityId, string _msg, string _mainName, bool _localizeMain, List<int> _recipientEntityIds)

       
    2. The game already tracks clients/players. Depending on how you want player information you want, there are different ways to fetch it. Just browsing through the code a little gives me a few options, there are probably more.
      GameManager.Instance.World.GetPlayers()
      SingletonMonoBehaviour<ConnectionManager>.Instance.Clients


      ServerTools mod already does a bunch of work with chat messages and fetching player information. I would recommend browsing its source https://github.com/dmustanger/7dtd-ServerTools/ and don't try reinventing the wheel.
       

    3. Absolutely, but it might not be as simple as you might hope. I would look into the XUiC_RecipeStack and XUiC_CraftingQueue classes. You might be able to do it by hooking (prefixing) the XUiC_RecipeStack.SetRecipe method and clamping the craftTime argument, but that's just a guess.

  9. Here is your "little mod." Just extract and dump the mod into the Mods folder.

     

    Complied version: https://drive.google.com/file/d/1AvV2m6j9mPg-izP2TkFgnTqXOJUZqw8K

     

    Source:

    public class PeskyVersion : IModApi
    {
        public void InitMod(Mod _modInstance)
        {
            Log.Out("[PeskyVersion] Getting rid of that pesky version label. . .");
    
            NGUIWindowManager nGUIWindowManager = UnityEngine.Object.FindObjectOfType<NGUIWindowManager>();
            nGUIWindowManager.Close(EnumNGUIWindow.Version);
        }
    }
×
×
  • Create New...