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
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.
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.
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.