Combat Overhaul Alpha

Show off your mod creations or just a work in progress.
Post Reply
DFIronman
Posts: 84
Joined: Sat Aug 24, 2019 12:48 am

Re: Combat Overhaul Alpha

Post by DFIronman »

Hey, l3lessed, there was an issue with the old code I provided that was causing problems on reload due to SerializablePlayer's reference to playerMouseLook not being updated. I thought you should see the updated version if you decide to create this as a mod instead of as a custom build. I'm not trying to beat a dead horse here - the custom build may be the best way to go, just wanted to keep everything updated. The rest of this post is something of an in-depth rehash of what I posted the other day in this topic, for you or anyone else who might be interested.

From my understanding, since every script is a Component, you should be able to fully override any script you want from the game as long as you replace it properly on the relevant game objects AND update any fields that reference the component (like I had to do to SerializablePlayer in my UpdateIronmanMouseLook() code). Once everything is initialized, there should be no extra Reflection cost (except for any calls where you'd have to modify private variables or skip the parent class, which would cause infinite recursion in your derived classes if you did not skip the parent).

All you need to do is derive your custom script from the original one and include your version of whichever functions you needed to modify. You'll want to skip a level above the parent class for anything that makes a function call from base. I was able to do that with a class that inherits from DaggerfallUnitySaveGameWindow (which, in turn, inherits from DaggerfallPopupWindow) as follows:

Code: Select all

public class IronmanSaveGameWindow : DaggerfallUnitySaveGameWindow
{
        private readonly IntPtr DaggerfallPopupWindowUpdatePtr = IntPtr.Zero;
        private readonly Action DaggerfallPopupWindowUpdate = null;

        public IronmanSaveGameWindow(IUserInterfaceManager uiManager, Modes mode, DaggerfallBaseWindow previous = null, bool displayMostRecentChar = false)
            : base(uiManager, mode, previous, displayMostRecentChar)
        {
            DaggerfallPopupWindowUpdatePtr = this.GetType().BaseType.BaseType.GetMethod("Update").MethodHandle.GetFunctionPointer();
            DaggerfallPopupWindowUpdate = (Action)Activator.CreateInstance(typeof(Action), this, DaggerfallPopupWindowUpdatePtr);
        }
            
       public override void Update()
        {
            DaggerfallPopupWindowUpdate();
        }
}
That call does slow down execution of the frame, but only by 1/10th of a millisecond (on my fairly basic laptop). I'm not sure if that's due to the Reflection call itself or because of the Update() chain that gets executed as a result of it. Reflection calls on fields are certainly faster. I haven't benchmarked the difference between the DaggerfallPopUpWindowUpdate() call and a Reflection call on a simpler function.

A quick search reveals that WeaponManager.cs and FPSWeapon.cs don't make any calls to their parent class via "base" at all, which means that a mod version of this may not incur any performance hit at all (excluding any cost for modifying private fields) if the other scripts you're modifying are the same way.

Code: Select all

        private static IronmanPlayerMouseLook IPML;
        protected static void UpdateIronmanMouseLook()
        {
            if (IPML == null)
            {
                GameObject camera = GameManager.Instance.MainCameraObject;
                camera.AddComponent<IronmanPlayerMouseLook>();
                Debug.Log("UpdateIronmanMouseLook(): Added IronmanPlayerMouseLook to a Camera");

                PlayerMouseLook PML = camera.GetComponent<PlayerMouseLook>();
                IPML = camera.GetComponent<IronmanPlayerMouseLook>();

                // Copy the state of the PlayerMouseLook component to the new IronmanPlayerMouseLook component
                FieldInfo[] fields = PML.GetType().GetFields();
                foreach (FieldInfo field in fields)
                    field.SetValue(IPML, field.GetValue(PML));

                Debug.Log("UpdateIronmanMouseLook(): Copied PlayerMouseLook fields to IronmanPlayerMouseLook");

                foreach (Component c in camera.GetComponents<PlayerMouseLook>())
                {
                    if (!(c is IronmanPlayerMouseLook))
                    {
                        Debug.Log("UpdateIronmanMouseLook(): Destroying <PlayerMouseLook>");
                        Destroy(c);
                    }
                    else
                    {
                        Debug.Log("UpdateIronmanMouseLook(): Assigning IronmanPlayerMouseLook to GameManager.Instance.PlayerMouseLook");
                        GameManager.Instance.PlayerMouseLook = IPML;
                    }
                }

                GameObject PA = GameObject.Find("PlayerAdvanced");
                if (PA == null)
                    Debug.LogError("UpdateIronmanMouseLook(): Couldn't find PlayerAdvanced GameObject! This will cause problems!");
                else
                {
                    SerializablePlayer SP = PA.GetComponent<SerializablePlayer>();

                    if (SP == null)
                        Debug.LogError("UpdateIronmanMouseLook(): Couldn't find SerializablePlayer component on PlayerAdvanced! This will cause problems!");
                    else
                    {
                        SP.SetFieldValue("playerMouseLook", IPML);
                        Debug.Log("UpdateIronmanMouseLook(): Assigned IPML to SerializablePlayer's playerMouseLook field.");
                    }
                }
            }

            Debug.Log("UpdateIronmanMouseLook(): Exiting function.");
        }
The example code uses my ReflectionHelper extension class (here), so you may want that. If you decide to try a mod version, feel free to ask if you need any help with getting it to work.

Great work on this so far - it's really coming together!

l3lessed
Posts: 1400
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Combat Overhaul Alpha

Post by l3lessed »

Thanks for all the info. That is so helpful.

I'm excited to see what I can do the reflectionhelper. Will be interesting to see if it can hijhack the animation system with reflection; I can see how I may be able to do it in my head, if I can kill the fpsweapon animation update loop and then initiate my own through my mod script file. Just little unsure if the animation loop can be stopped mid-sequence from outside the script without any modifications.

I can see, theoretically, how I could probably run everything else through a reflection mod, including the itemrange (Just create my own version of the itemtemplate file, but just for weapon range numbers.)
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

DFIronman
Posts: 84
Joined: Sat Aug 24, 2019 12:48 am

Re: Combat Overhaul Alpha

Post by DFIronman »

Barring any issues being caused as a result of this, you should be able to just destroy the FPSWeapon component at mod startup (if it's on a GameObject, which I think it is), and add your own derived version of it. You don't have to worry about interrupting the loop, unless something vital is happening with it.

Be sure to implement this slowly as it's easy to cause issues. Like I said in my last post, I had a problem with a field in SerializablePlayer that caused an infinite loop in Unity itself (not the scripts), with no useful feedback. I only fixed it through guesswork. You'll need to search through the source code and replace every persistent instance of FPSWeapon and whichever other scripts with your own versions.

And you're right about the ItemTemplate file. I don't know how many scripts dynamically generate objects based off of it, but unless there's a better way, you'll either have to make derived versions of those scripts or constantly scan for new ItemTemplate Components, copy the fields to a new Component instantiated from your derived version, and replace the ItemTemplate Component with yours. The good (or bad) news is that you only need to do that for the ItemTemplate Components that are relevant to you.

If I understand properly, you're just replacing ItemTemplate for weapons, so you can accomplish that with a one-time check on item equip. That might cause the item to flicker for a frame as it gets replaced, however, so you may have to find a better way for a seamless experience. Maybe try adding an event to the inventory menu's OnClick method (copy it, null it out, and insert your event first, then the originals). The flicker may not be noticeable then. You'll also probably need to replace items via SaveLoadHandler's OnLoad event if you go this route.

Careful though, because replacing items may cause issues with quests and other things that are expecting a specific item (shop inventory?) - you'll have to do a lot of checking around. Maybe there's a way to see everything that is referencing a particular Component? Be sure, especially, to test saving and loading, starting a new game after a reload, completing a weapon-based quest after a reload (Jay_H may be willing to make a test quest for you), etc.

l3lessed
Posts: 1400
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Combat Overhaul Alpha

Post by l3lessed »

Honestly, I haven't looked closely into the reflection system. I wanted to hop right into the engine as is and learn from there. Know its going to create more work/redundant work for me in the long run, but whatever, I learn faster and better just getting into a system, breaking it apart, and figuring out what it can do.

However, if I can destroy whole script file instances and replace them, then yes, this should be easy. I'll finish my current build in with the modified base script files. Once its stable, I'll then duplicate them, rename them for the mod, destroy all the original scripts via reflection system, and then just load my modded versions via reflection system. This should not cause any issues, I would think, as long as I name them the same as the originals they are loading over. This way, I'm not overriding or deleting the original files, but I'm still keeping the exact same file name/structure and don't accidental causes a systematic meltdown when one script can't be referenced properly. Knowing more than me about reflection, could this work? Could I take the base files I have modified, duplicate them, and then combine them into a mod file or can mod files not have the same name as base script files (even if they are to replace them entirely)?

Yeah, I hit a few loop engine bugs I had to track down line by line myself. Thankfully, I have programmed a good amount in basic file editing programs that don't give any real bug/coding error feedback, so pretty use to line tracking these things.

I'm using itemtemplate to store the base range for the weapon. I then put a getrange method into itemhelper to pull the range from the itemtemplate and assign it to the weapon when called, which is right before isAttacking bool is triggered. This theoretically allows dynamic ranges for attacks if wanted. Just add whatever triggers and modifiers you want into getrange, and item range can change on the fly. Anyways, the getrange method would be easy to move from itemhelper to its own file.

As for quests, I hadn't thought about this. However, I'm not changing anything about the item id or name. I'm only adding an extra float point value to its instance. And, if the item has no range, I've defaulted it to classic numbers. Hopefully that stops it from breaking any quests, parts of the game, or mods.
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

DFIronman
Posts: 84
Joined: Sat Aug 24, 2019 12:48 am

Re: Combat Overhaul Alpha

Post by DFIronman »

13lessed wrote:This should not cause any issues, I would think, as long as I name them the same as the originals they are loading over.
I don't think that would be helpful. First, they'd be considered entirely different classes because I assume you'd put them in a different namespace. If they're in the same namespace as the originals, the mod almost certainly won't compile due to conflicts with the original classes in the DFUnity executable (something like, "error: class already defined"). Once your mod throws an exception that hasn't been caught, it won't be loaded - which is moot, because it can't compile to begin with. I would rename your files and classes. Something like "CO_FPSWeapon," "CO_WeaponManager," etc. or whatever works for you.

13lessed wrote:Could I take the base files I have modified, duplicate them, and then combine them into a mod file or can mod files not have the same name as base script files (even if they are to replace them entirely)?
Just including this for clarity, but no, I don't believe that you can do that. I would be extremely surprised if there were not a conflict, but even if there weren't, you'd still have to update all fields and/or properties that retain references to the original scripts that you're modding. Check out my UpdateIronmanMouseLook() example again, along with the original SerializablePlayer.cs, for an example of updating a field that retained a reference to a Component/script that I had to override.

13lessed wrote:As for quests, I hadn't thought about this. However, I'm not changing anything about the item id or name. I'm only adding an extra float point value to its instance.
This may be fine if you're somehow doing it at runtime and not making any modifications to the code of a struct or class. If you added a field like "public float xyz" into the actual code of the script, you're out of luck and will have to take measures to ensure that your changes are recognized by the game. The issue isn't how many or what kind of changes you've made to a script, but that you made any change whatsoever. You need to get the game to recognize that.

Am I right in that you modified the code of the ItemTemplate struct? If so, we'll need to figure out some way to override the original (or ask Interkarma or someone to add a range entry to the ItemTemplate struct). Failing that, instead of modifying the struct, you could always just beef up your GetRange() method to return a result based on the type of weapon that is passed to it and hard-code your range values.

All Claymores are the same length for the purposes of the game, right? Just create a mapping of "item_index->range" and have GetRange() return a range based on the weapon's index (or weapon name, if you prefer). See ItemTemplates.txt if you haven't already.

l3lessed
Posts: 1400
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Combat Overhaul Alpha

Post by l3lessed »

Thanks for all the info ironman. Should be a fun time trying to get this exported to the reflection system. :lol:

Well, offset raycast are in. Once I figured out how to properly rotate angles based on camera positioning, was able to put in proper synced hit collision pretty quickly for the sword animations. Dropped a video explaining the code and showing it in action. Got to now create a raycast offset loop for the rest of the weapon animations, but shouldn't be to hard now I got the process down.

I'm also thinking about trying to remove default spherecast method, now that we don't need an exaggerated hitbox to make up for only using 1 raycast for hit detection. This would fix a large issue complained about in the current build, where you can't shoot easily through doors and cages because the spherecast is larger than the object gaps.

Sorry, first time using mic audio. Not best quality.
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

DFIronman
Posts: 84
Joined: Sat Aug 24, 2019 12:48 am

Re: Combat Overhaul Alpha

Post by DFIronman »

Sure thing, man. I'm really looking forward to seeing this mod/build in action! Also, I heavily modified the ReflectionHelper extension class to be much, much faster. Problem is, it works great in the Unity Editor, but does not when the game loads the mod. Been spending my free time yesterday and today on making this faster and keep hitting these brick walls haha.

If I get it working, I'll post the new version of it for you to use.

User avatar
Sandman
Posts: 7
Joined: Sat Aug 31, 2019 7:01 pm

Re: Combat Overhaul Alpha

Post by Sandman »

Hi, l3lessed. As far as I know, in Daggerfall all weapon types have no differences, except damage and a required skill, and I think it would be great if somebody will make mod what brings the differences. I'm writing it here because a purpose of your mod is suited to my idea.
For example: axes can cause bleeding, blunt weapons have higher armor piercing than other weapon, blades are dangerous for defenseless enemies, etc. May be, balancing this will take too much time, but it's worth it. In original Daggerfall the best weapon is Dai-Katan, and it makes other weapon skills useless - only blunt weapon does double damage to skeletons, and blades half.

l3lessed
Posts: 1400
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Combat Overhaul Alpha

Post by l3lessed »

I'm putting in weapon ranges and speeds. Its already it actually. This helps with the issue your talking about already. Large weapons, like the dia-katana, are harder to use indoors. They are slower, and hit walls more.

Damage type modifiers could be done. Like you said, its a question of balance and if it is it worth it.

Development has slowed some because of personal life, so this would need to take a backseat. I still have a ton of work on ray casting alignments, animation refining, debugging, optimization, and so on.

Thanks for the suggestions. I'll get there at some point.
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

l3lessed
Posts: 1400
Joined: Mon Aug 12, 2019 4:32 pm
Contact:

Re: Combat Overhaul Alpha

Post by l3lessed »

Still working on this slowly. I have less work and personal time to focus on this, and coding and modding has always been a extra-time hobby thing for me.

However, still making progress. The thing slowing me down the most right now is getting smooth animations in for certain weapons, especially the flail. Because of the animation having more moving/dynamic parts in the sprite, it is making it trickier to deal with the screen cutoff issues for certain animtaions, especially the down one. But, I'm getting it figured out by hijacking whatever frames I need from the other attack animations and mixing and matching them during the animation loop, just much harder than the more static looking animations.

However, I am almost there with the flail.

So, at that point, smooth animations with aligned raycast trace will be done for the swords, staffs, hammers, flails, and mace. That leaves daggers and fists.

I've also optimized the weapon bob. It is now moved into a different section of the fpsweapon script that uses the built in animation offset float points. This also makes the weapon bob position stay in its location instead of resetting to default position when you stop moving; I may change this back to simulate the player going into an attack stance when not moving. I've also defaulted the idle sprites/animations to the original idle sprite so that weapon bobs will work properly with the enchanted versions of the weapons too.
My Daggerfall Mod Github: l3lessed DFU Mod Github

My Beth Mods: l3lessed Nexus Page

Daggerfall Unity mods: Combat Overhaul Mod

Enjoy the free work I'm doing? Consider lending your support.

Post Reply