0 of 0

File information

Last updated

Original upload

Created by

RedRoryOTheGlen

Uploaded by

RedRoryOTheGlen

Virus scan

Safe to use

Tags for this mod

About this mod

Adds events to the attack damage formula that mods can subscribe to using DFU's messaging system. Android version also available.

Requirements
Permissions and credits
Changelogs
The mod overrides the vanilla CalculateAttackDamage and SavingThrow formulae to add Events to them. Using DFU's messaging system, other mods can be subscribed to this event which allows them to listen for when attacks or saving throws are made, as well as receive attack information like attacker, target, weapon, element types, effect flags, etc.

Included in the download is a DFMOD for Combat Log. It is an optional demo mod that showcases the functionality of Combat Events by printing specific messages to the HUD when events are called (eg, an attack or saving throw is made).
USAGE

IMPORTANT: THIS MOD SHOULD BE PLACED AT THE VERY START OF YOUR LOAD ORDER! OR AT LEAST AS EARLY AS POSSIBLE! ANY DEPENDENT MODS THAT ARE LOADED BEFORE IT MAY NOT BE ABLE TO SUBSCRIBE TO THE EVENTS DURING INITIALIZATION!

This mod does not do anything by itself and requires other mods to use the functions it brings.

In order to subscribe to the event, your mod must have a method that will be called when the event happens. An example:

//Replace the contents with your own code

//Sample code that prints a message to the pop-up text if the player character is physically attacked
public void OnAttackDamageCalculated(DaggerfallEntity attacker, DaggerfallEntity target, DaggerfallUnityItem weapon, int bodyPart, int damage)
    {
        //if target is not the player, do nothing
        if (target != GameManager.Instance.PlayerEntity)
            return;

        //check if attack hit
if (damage > 0)
DaggerfallUI.Instance.PopupMessage(attacker.Name + " hit the player!");
else
DaggerfallUI.Instance.PopupMessage(attacker.Name + " missed the player!");
    }

//Sample code that prints a message to the pop-up text if the player character makes a saving throw
public void OnSavingThrow(DFCareer.Elements elementType, DFCareer.EffectFlags effectFlags, DaggerfallEntity target, int result)
    {
        //if target is not the player, do nothing
        if (target != GameManager.Instance.PlayerEntity)
            return;

        //check if player successfully saves
if (result == 0)
DaggerfallUI.Instance.PopupMessage("Player saved against " + effectFlags.ToString());
else
DaggerfallUI.Instance.PopupMessage("Player did not save against " + effectFlags.ToString());
    }


After this, all that's left is to use the messaging system to add the method to the Event:
//Put this in Awake or when checking for Mod Compatibility.

        Mod ceh = ModManager.Instance.GetModFromGUID("fb086c76-38e7-4d83-91dc-f29e6f1bb17e");
        if (ceh != null)
        {
ModManager.Instance.SendModMessage(ceh.Title, "onAttackDamageCalculated", (Action)OnAttackDamageCalculated);            ModManager.Instance.SendModMessage(ceh.Title, "onSavingThrow", (Action)OnSavingThrow);
        }

MOD COMPATIBILITY

Remember to make sure that VCEH is loaded BEFORE any mods that are dependent on it.

This mod's functions are required for optional modules in several of my other mods:
Unfortunately, this mod is STRICTLY INCOMPATIBLE with any mods that override the vanilla CalculateAttackDamage formula, like Physical Combat and Armor Overhaul, or the SavingThrow formula. BUT there is a way for overriding mods to use VCEH events if updated. See the "Mirror" method in the next section.

ADDING COMBAT EVENTS TO YOUR OWN MOD

Have a mod that you want to add combat events to? Here's a summary of the changes that VCEH does to the vanilla formula to get you started!

Create your events:
    //Attack event
    //Outputs Attacker, Target, Weapon, Body Part and Damage
    public event Action<DaggerfallEntity, DaggerfallEntity, DaggerfallUnityItem, int, int> OnAttackDamageCalculated;

    //Saving throw event
    //Outputs effect element, effect flags (Paralysis, etc), Target and Result
    public event Action<DFCareer.Elements, DFCareer.EffectFlags, DaggerfallEntity, int> OnSavingThrow;

Set up the message receiver:

void MessageReceiver(string message, object data, DFModMessageCallback callBack)
{
        switch (message)
        {
//Add sender to attack event listeners
case "onAttackDamageCalculated":
OnAttackDamageCalculated += data as Action<DaggerfallEntity, DaggerfallEntity, DaggerfallUnityItem, int, int>; break;

//Add sender to saving throw event listeners
case "onSavingThrow":
OnSavingThrow += data as Action<DFCareer.Elements, DFCareer.EffectFlags, DaggerfallEntity, int>; break;

default:
Debug.LogErrorFormat("{0}: unknown message received ({1}).", this, message); break;
}
}

Add calls to these events in the appropriate formula:

//FormulaHelper.CalculateAttackDamage()... add this right before it returns

        if (Instance.OnAttackDamageCalculated != null)
            Instance.OnAttackDamageCalculated(attacker, target, weapon, struckBodyPart, damage);

        return damage;

AND

//FormulaHelper.SavingThrow()... same as above

//Pre-calculate the result
        int result = Mathf.Clamp(percentDamageOrDuration, 0, 100);

        if (Instance.OnSavingThrow != null)
            Instance.OnSavingThrow(elementType,effectFlags,target,result);

        return result;

Register the formulae and enable the messaging system:
void Awake()
    {
        if (Instance == null)
            Instance = this;

        //Register the custom formulae
        FormulaHelper.RegisterOverride(mod, "CalculateAttackDamage", (Func<DaggerfallEntity, DaggerfallEntity, bool, int, DaggerfallUnityItem, int>)CalculateAttackDamage);
        FormulaHelper.RegisterOverride(mod, "SavingThrow", (Func<DFCareer.Elements, DFCareer.EffectFlags, DaggerfallEntity, int, int>)SavingThrow);

        //Set up the receiver
        mod.MessageReceiver = MessageReceiver;

        mod.IsReady = true;
    }

Optionally, you can "mirror" VCEH's Events, allowing you to make your mod that overrides the combat formula to be compatible with those that require VCEH. For instance, you can make your mod compatible with Shield Widget's and Weapon Widget's Recoil modules.

THIS METHOD REQUIRES VCEH TO BE ENABLED IN THE LOAD ORDER. Simply make sure your mod is loaded AFTER VCEH in order to for your formula to override it.

LINK to a pastebin because Nexus isn't letting me save the mod snippet here.

The mirror code is run in OnNewGameStart and OnLoad to ensure all mods that subscribe to VCEH events have all done so. You can also make a new event to store them in so you can call both VCEH events and your own events together.

The full script can be found here.

ACKNOWLEDGEMENT

Big thanks to TronTravolta from the Lysandus' Tomb DFU Modding Discord server for figuring out how to use System.Action events with the DFU Mod Messaging system. This would not be possible without their efforts.
Thanks to ASphincterSaysWhat for suggesting the option to call VCEH's events from other mods.