Page 1 of 19

Combat Overhaul Alpha

Posted: Fri Aug 16, 2019 7:54 pm
by l3lessed
Hey everyone, if you haven't noticed me, I've been fiddling away under modder discussion. I have been digging into and researching the weapon and combat system in Daggerfall in order to start developing a combat overhaul mod. I am in the very early stages, so nothing is set. However, I am at a point where I need to start tracking development of features and coding. So, this topic will be that area. I plan to leave it open as of now for general discussion about the mod. Follow the post below for features and current progress.

Important Contributors/Co-Developers

- Olgimpy: Created the beautiful custom shields for the shield module.
- Daggerdude: Updatedthe beautiful custom shields for the shield module.

Current Unity Build Base: 10.23

6/27/20, 11:29PM Pacific
(Shield Module Finished. Moving on to Parry module, then damage/armor overhaul, then first release.)

Features RoadMap
  • ItemTemplate baseRange Variable (Finished) - I have added a baseRange variable to the itemTemplate file to store an items potential range. Think of this as a value you can use to define the range an item will affect. I'm using this for melee combat, to dynamically assign the reach of each weapon, so weapons have different attack ranges. However, you could use this for anything you need a range value attached to, say a magical affect area or a cast rang or any other possibility you can think of for range; you could assign it to spherecasts to create area affect stuff. You can access this value through the itemHelper.cs script and the getRange() method. You can also access and read it out in UI's using the %ft variable within strings.
  • Dynamic Weapon Range (Finished) - Each weapon has a unique float point value assigned to it to simulate a unique attack range. Currently is pulled from itemtemplate through the itemHelper.cs and assigned in the weaponManager.cs anytime you attack. Fists are defaulted to the classic range of 2.25f. Any weapon with 0 range does not show and is broken/bugged. Ensure weapons have a range value of some sort for them to show in fps mode. There is a built in if - then error catcher, but please do not rely on it. Set your base range in your itemtemplate file.
  • Debug Raycasting Added: (Finished) - I added a simple unity debug raycasting line into the Weaponmanager script. You will now be able to see the raycast of a weapon attack in the unity engine within the scene window. This is not built into the DF engine, so it will not show up dynamically in game. I do not plan on adding it into the df engine either.
  • Dynamic Weapon Stamina Cost (Finished) - Stamina cost for swings is now based on the items weight and range to give weapons more variety and feel. Current formula is simple; ((range+weight)*2). This gives a range of 5 to 17 cost depending on the size and weight of the weapon. Will probably refine formula further later on.
  • Dynamic Raycasts/Spherecasts(Finished) - Traditional raycasts in most classic games used single raycasts to save on cpu demand, so raycasts would draw one long line instantly for the raycast check. This was effective, but did not simulate real life well, as everything has to move in physical space over time to simulate physics. I have added raycasts that can grow overtime to simulate an attack moving through space. Stabs hitdetect now moves outward overtime from the player increasing in length until it reaches the weapons attack length,
  • Dynamic Weapon Speed (Finished) - I have inserted in a public variable into the fpsWeapon script to allow easy manipulation of attack speeds/animations. It can be accessed and set through the fpsWeapon.cs object via .AttackSpeed method. Large weapons feel heavier and slower, small weapons feel lighter and faster.
  • Movement Based Attack Types (Finished) - Currently finished a simple movement based attack system. Each strafe key initiates the attack based on that direction. As an example, left strafe = MouseDirection.left. If you're standing still and not moving at all, attacks go back to classic random choice.
  • Slower Attack Movement(Finished) - Finished a simple attack movement modifier. You know have your movement reduced by 60% while attacking. I may try to tie it to the current animation frame to create a more realistic feel to movement while swinging.
  • Combat/Unsheathed Stance Slowdown(Finished) - When you go into combat stance/sheathed state, you will move 15% slower, as your more focused on your senses and muscle memory. Sprinting/crouching bonus/debuff will still be applied, but then debuffed by the 15% penalty when in combat/unsheathed mode. So trying to be in a combat stance and sneak at the same time is going to go even slower, as it should. Have you ever tried to sneak while staying in a combat ready, muscle memory, heightened senses state? Yeah, not so easy to do and maintain.
  • Weapon Collision Simulation/Feedback(Finished) - DF engine begins sending out raycasts on every frame. Once it hits an object, the raycasts stop. A bool trigger then tells the animation system to replay the animation backwards at an accelerated rate. This simulates a hit and collision. Marking it as finished, but plan on smoothing animations at some point.
  • Multiple Raycast Code(Finished) - I have inserted in a coding loop so hit detect raycasts will continually shoot out from the players camera, using the weapons range, to simulate actual weapon swings from beginning to end. Currently raycast stops on first object hit detection. Uses weapons animation time to sync raycast and time their shots (shoots about 30 within a normal animation). As each raycast is shot, a lerp vector transform moves it along a defined axis based on the animation time. Once an object is hit, raycast stop, fps collision animation begins, and player sets back to idle. Marked as finished, even though I have to refine the vector offsets for the stab and down animations.
  • High/Smooth FPS Attack Animations(Finished) - Hijacked animation coroutine, added a for loop that uses mathf.lerp calculator to scale smooth animation simulation no matter the attack speed. *All weapons have been finished.* I've finished all weapon attack animations covering the four base attacks I'm using (left, right, stab, and down). I do need to wrap up fists attacks, redo stab, and do more refinement to minimize a few weapons with noticeable frame skipping, but I'm still marking it as finished. It is in a playable, immersive state.
  • Weapon Movement Bob(Finished) -This is supposed to simulate the natural bob running with a weapon would cause. It is tied directly into the frame animation offset variable, which creates nice little side effects, like slower bobbing on stride/run and faster bobs on small movements, like side or back stepping. It works with all weapons, including magical ones and the fists. I'm marking it as finished.
  • Range & Inertia UI Readouts(Finished) - If an item has a range, the players inventory will display it after the normal ui readout. Upon opening the item info panel, the player will see the normal information, item range, and item inertia..
  • Realistic Dodge Module(1.0A) - the dodge system is traditionally based on random roles to calculate if a hit is dodged by the player/enemy. This leads to confusing combat and engagement at times, as a series of bad rolls can make enemies hard to plan for and ruin a well thought out battle/fight. I've started work on a dodge script that will hopefully allow the player/enemy to mimic a real dodge. For the player, random roll dodging will be removed and the dodge will be completely player controlled; The players tied agility will affect its usefulness/effectiveness; the more the player has in Agility, the less fatigue the dodge will cost, the further you can dodge, and the longer you can dodge. For enemies, I will for now keep the random roll system, so you can still randomly have your attacks dodged; however, the enemy will actually move a direction and stop any attack momentarily to mimic the look of an actual dodge and make them reset momentarily their attack on you.
  • Shield Module(3.0) - I created a custom rect script to import and render png files into the default engine from a basic loose file directory; I coupled this with a float return lerp calculator routine I created. Now we can import any shield (or any png file) into the engine, render it, and give it offset animations. With Daggerdudes amazing assist on the art side, I used this to create a beautiful classic shield and give it all the animations needed for a shield. This includes walking bob, on hit recoil, raising, lowering, and a passive hold. It will absorb all incoming physical damage. I'll be adding some more features and shield art and tracking it on its own thread.
  • Unique Item ID Ranges(Started) - I mimicked the weight float point system, as it allows for tons of customization of the value and easy access for ui read outs on the fly. However, to get the system in and tested. I shortcutted the weaponManager.cs script right to the template to retrieve the weapon range instead of creating a unique instance of the weapon and assigning a value to that. This will limit all weapons to their item template value no matter what you do currently. I do plan on implementing the uniqie item range values into weaponcombat.cs later on. This will allow for each item to have custom range values in case any modder ever wants to do interesting things with this value, like create enchantments that increase range.
  • Blade Variations(Not Started) - All differing blade types use the same sprite for their animations. This leads to tantos looking the same as dia-katanas on screen. We can modify their size by changing the render size through brute force code to setup differing sized blades for the differing weapons.
  • Movement Modifiers Tied to Weapons(Not Started) - I want movement modifiers for the unsheathed and attack reductions to vary some based on the weapons range and weight to simulate weight and physics of running with said weapon.
  • Recoil Specific Animations(Not Started) - Recoil animations are pretty sad right now; it is a rewind of the base animations backwards from object hit. We can improve this, and possibly make recoil animations for hitting an enemy versus a solid object, like a wall, prop, or asset.
General Bugfix & Code Changes
  • FPS Console Command Script: I created a script file to enable some basic console commands for controlling and manipulating the FPSWeapon script. I do not recommend changes these. Doing say risks animation and raycast bugs appearing as these are finally tuned to the engine limits and animations system.

    - OffsetDistance: This is a float value that changes animation offset distance. Default value varies between .2 and .28 depending on the weapon being used. Higher values faster offset moves.
    - DisableSmoothAnimations: This enables and disables the default or improved animation system.
    - ChangeAttackSpeed: This subtracts or adds a certain float value from the default animation attack speed; Use .01 increments.
    -ChangeHorPos: Changes start and end position of hit arc detection; starts at 45 degree and does 90 degree arc to end at 45 degrees on opposite side. (-start float -end float).
    -ChangeRaycastLerp; Changes how slow or fast the hit arc is drawn. Default is .188f. Recommend .01f increments.
    -ChangeMovementMods; Multiplies base movement speed for sheathed and attack animations. Default is -sheathed .85f -attack .4f. Set values to 1 to disable any movement reduction. (-sheathed float -attack float).
  • All Weapon Stats Calculate Once/Before All Attack Code: I moved all weapon states and debug message code to run once, right after the weaponManager.cs detects a player attempting an attack. I believe this should stop any bugs having to do with weapon numbers being assigned after the swing and animation code executes.
    Weapon Range Code Improvement: Weapon range was original being calculated every frame. This seemed off for multiple reasons. The first being that range was originally set as a unchangeable constant float variable of 2.25f; so, why does the engine need the number continually updated, if it never will change by design. Two, the raycasting code only shoots out one spherical ray on every attack, which pulls the range value to figure out the rays distance; So, why does it need to continually know the range every processed frame? I think this was done originally to allow for dynamic range affects and other mechanics, but they never got to any of it and rammed this constant value in. This ultimately seems like a waste of cpu cycles/frames. I have moved the range value pull from a constant method into the attack boolean trigger. Now, it only grabs this value on every successful attack trigger. This should free up some cpu cycles/frames.
  • Added Debug Messages: Needed to know exactly what was happening with the back-end combat system while playing a game for better coding and number tweaking. I have programmed in three different debug messages. One reads out the current weapons range, the next is the current weapons fatigue cost, and the last one will appear when you make contact with an enemy hitbox and verify if you successfully rolled a hit or did not. The last one is critical, as it was hard to know if my code was broken or if I had just missed a hit chance roll in the back-end engine. The first two debug readouts can be found in the weaponManager.cs, right by where it assigns the range and staminafatigue value. The last one is embedded in the formulahelper.cs, way down by the melee hit chance detection code.
Threads Related To This Mods Work
  • In-depth project and discussion on combat and animation system and related code: viewtopic.php?f=14&t=2533
  • A very in-depth breakdown of the combat system and animation system and how they work together to create what happens on the screen: viewtopic.php?f=22&t=2508
  • In-depth discussion, with visual flow chart, of the fps animation system and all related script files the control and run it: viewtopic.php?f=22&t=2554
Project Github

Re: Combat Overhaul Alpha

Posted: Fri Aug 16, 2019 9:57 pm
by l3lessed
Here are screenshots of features in action.

Youtube video of smooth attack animations.

Youtube video of weapon movement bob.

Youtube video of all features in action, and some peaks at my c# coding.

Youtube video of multiraycasting with coding.

Youtube video of weapon collision system with synced animations; includes short code explanation.

Re: Combat Overhaul Alpha

Posted: Sat Aug 17, 2019 9:58 am
by King of Worms
Looks promissing, will observe :)

Re: Combat Overhaul Alpha

Posted: Sat Aug 17, 2019 10:20 am
by ShortBeard
This looks like a great idea!

Have you thought about throwing this project up onto GitHub if it already isn't? I'm sure quite a few modders would love to help out on this, especially if the mod is ultimately intended to completely overhaul the combat system. I'm not sure if it has already been mentioned or if someone has done a mod on it, but I always thought it would be a cool idea if in combat you could manually right click to block, like the more modern elder scrolls titles.

Re: Combat Overhaul Alpha

Posted: Sat Aug 17, 2019 1:21 pm
by Midknightprince
Amazing, I love you guys...sob.... :D

Re: Combat Overhaul Alpha

Posted: Wed Aug 21, 2019 3:48 pm
by l3lessed
I have thrown up a number of updates since first posting this.

Current putting collision work on hold, as I need to figure out how to handle animations using the current animation system and code changes. I do not want to dump a ton of time into features that will either not be supported by other creators and community members or will be replaced, if anyone gets to 3d fps models and attack animations.

I have decided to begin work instead on a raycast array to create a store a set of raycast that will fire on each weapon attack animation frame and will follow the weapons animation; this should simulate an actual hit path for the weapon versus the current single raycast from screen center.

After that, selectable attacks will be fully finished.

Then probably first release.

Here is a video of my last build and code

Re: Combat Overhaul Alpha

Posted: Sun Aug 25, 2019 6:18 am
by l3lessed
Multi-raycast hit detection code is in. It is in alpha, so has a known bug and is not optimized.

It is pretty simple in how it operates. Took little messing with the weaponManager.cs switches, but it checks for when the attack state is initiated. When this happens, it starts a if then switch that activates anytime the attack animation is between number 1 and 4. When activated, it begins sending out raycasts every frame from the camera direction outward trying to detect what it is hitting and if it is a successful hit.

Currently it keeps going running, even after an initial hit, so broken in a way. When you attack, you can do ten+ attack on an enemy within a second. But hey, the basic setup is there.

I plan on adding a time switch to possible minimize the amount of raycast draws, as we probably don't need one every single frame. I also will add a proper hit detection switch, so the raycasts stop going after a successful hit. This will save raycasts and also stop from multiple enemy hit bug. Then just need a parry/recoil animation.

Re: Combat Overhaul Alpha

Posted: Sun Aug 25, 2019 8:37 am
by DFIronman
This is incredibly cool! Is this going to be a custom build of Daggerfall Unity then? Or are you able to package it as a .dfmod?

Re: Combat Overhaul Alpha

Posted: Sun Aug 25, 2019 7:33 pm
by l3lessed
Right now, It is being constructed as a custom build. Being new to c# and the unity engine, I found it easier to read and work off the games base script files. This makes it easier for me to see if certain features are even worth trying to create.

So, as of now, first release will be a custom build DF. I'll provide both the unity build files in a github, and the prebuild game.

Once I get the base systems setup and running, I'll then try to see if I can move them to their own seperate script files that can be packaged as a stand alone mod. However, I do not know if this will be possible if I can't inject certain objects/instances into the main script files using a mod script file, specifically item range. Since my custom item range uses the itemtemplate file, it adds a layer to injecting the assets that I do now know can be overcome without modifying the base engine.

However, once the mod features are largely all in and running without any large scale bugs, I plan on seeing if I can move much of my code to its own script files, and instead use instance/object injects into the main script files. If so, then yes, I will release this at some point as a stand alone mod. I would prefer it to be that way if possible at all.

If not, then yes, this will be a custom DF unity Engine built around more modern concepts of game theory and systems and edging towards a more realistic feel to much of the game mechanics. I'm currently focused on combat, but plan on moving into other things, like weather and exposure simulations, good fleshed out needs system, and so on.

Re: Combat Overhaul Alpha

Posted: Mon Aug 26, 2019 4:18 am
by DFIronman
Well, you're doing some very cool stuff. As luck would have it, I had to override the behavior of PlayerMouseLook for my Ironman mod, which is very similar to what you're doing (modifying the game engine). Using some Reflection and Unity's ability to Destroy/Add components at runtime, I was able to do what I needed to do.

Here are the steps I took:
  • I made a new class, IronmanPlayerMouseLook, deriving directly from PlayerMouseLook.
  • I copied the code of the function from PlayerMouseLook that I needed to modify to my class and made my adjustments.
  • I then created a function in my main mod component that allowed me to substitute PlayerMouseLook with my own version.
Even though it took me probably three hours to figure out, it's actually fairly simple to do. I'm including the code of the function that I used to replace PlayerMouseLook.

Code: Select all

	private static IronmanPlayerMouseLook IPML;
        protected static void UpdateIronmanMouseLook()
            if (IPML == null)
                GameObject camera = GameManager.Instance.MainCameraObject;
                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>");
                        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!");
                    SerializablePlayer SP = PA.GetComponent<SerializablePlayer>();

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

            Debug.Log("UpdateIronmanMouseLook(): Exiting function.");
Edit: Also, if you take a look at this post, you'll see a lot of info about using Reflection in the game. The downside is that it is slower, but depending on how you use it, it won't necessarily be noticeable. Even in a very heavy-use scenario, it should still be much faster than the Morrowind/Oblivion/Skyrim scripting systems.

Edit 2: Updated the code for this to fix a bug. This requires the ReflectionHelper extension class I wrote, available here.