Condition System?

lynnpye

New member
Greetings and such.

Quick question, is there a condition system built into UCC? Something by which an action can apply a lingering effect on the target (and/or the attacker)?

I'm thinking of things like bleeding, setting something on fire, temporary damage buffs (or debuffs).

It looks like I could press the Ability system into service for this but I'm not sure if that's the intended approach.
 

lynnpye

New member
I've gone ahead and rolled my own (btw, I think the link you were looking for was https://opsive.com/support/documentation/ultimate-character-controller/character/effects/ ). I felt I was going to have to do more customization than switching to the Effects system was going to help me with.

I'm adding the concept of damage types, as well as damage modifiers and the like. As a result, I find myself needing to replace portions of the existing code. I was a little disappointed that there was no immediately available hook for damage modifiers (i.e. the ability not to just be informed that an object was hit, but to have a chance to alter the effects of that hit like adjusting the damage amount by a percentage). The code for applying damage is a little deep in the guts and the only options to interact with that portion of code appeared to either be to create an event listener for (I'm at work and don't have the code in front of me, so pardon the naming, please) the "OnObjectHit" event or something to that effect, *OR* to derive from the class in question and override the virtual method, either in the new item ability class (i.e. SpellItem, which is a copy/paste of ShootableWeapon) or in the Projectile class (i.e. SpellProjectile, derived from Projectile and overriding OnCollision).

A DamageType collection, managed alongside others like the Item collection, could allow users to create varying types of damage and expand on that without needing to alter the code. Abilities (including the Item abilities) that cause damage would then have an option to choose one or more damage types and associated damage amounts to apply when a hit takes place. Likewise for Projectiles. Modifications to the existing objects that collect and apply damage (Health, Shield, etc) would be modified to take an additional parameter of DamageType.
 

Justin

Administrator
Staff member
Oops, you're right on the link.

For modifying the damage amount you could subclass the CharacterHealth component and then override the Damage method. This will allow you to change the amount of damage that is applied.
 

lynnpye

New member
Agreed. In fact, what I've done is:

- Subclassed CharacterHealth as AdvancedCharacterHealth. In AdvancedCharacterHealth, as you point out, if I simply wanted straight damage multipliers, I would have just overriden Damage(), specifically the 8 argument version that actually did the work, altering the damage and invoking the base.Damage(). Whenever I create a new NPC, I have to swap out the pre-added CharacterHealth for AdvancedCharacterHealth. However, as I'm looking at adding damage *types* as well, I had to introduce a 9 argument version and then alter where it gets called, which leads me to...

- Subclassed Projectile as SpellProjectile. Here, I override OnCollision(), copying the code (unfortunately) all so that I could get at the call to Health.Damage(). Of course, I'm also now calling hitGameObject.GetCachedParentComponent<AdvancedCharacterHealth>() in order to fetch the AdvancedCharacterHealth. If I were extra careful, I suppose I would check for Health as a fallback, but I don't plan to leave the stock CharacterHealth on any of my targetable creations.

- Subclassed UsableItem as SpellItem, copying ShootableWeapon as a base. I took the lazy approach here. I thought there might be a lot I would have to do here and didn't want to blow away ShootableWeapon to do it. At present, all of my "weapons" are planned to be spells, so I'm fine with this. And of course, I had to alter HitscanFire() in order to make the same change I made in SpellProjectile.OnCollision() to switch to AdvancedCharacterHealth.

- And I've had to modify ItemBuilder to make SpellItem available within your system.

An aside: This, by the way, is one of those personal coder-OCD things that annoyed me... a lot of the code between Projectile.OnCollision() and ShootableWeapon.HitscanFire() is similar in terms of collecting information on the target and applying the damage. It might have been nice to have a DamageManager class that would:
- Have a Damage() method (or suite of Damage(...) methods as currently exists) that accepts the same information and applies damage to the target, from the source, based on provided parameters.
- Add an additional Damage() method that accepts an Object[] userParms or somesuch, to allow passage of arbitrary data into the Damage call, so that...
- Items could be granted an 'additionalDamageParameters' Object[] (again, or something) attribute, which could be populated at design time with anything the developer wanted (in my case, perhaps a ScriptableObject containing the damage type and a list of conditions to apply), which would be passed into that Damage() method and subsequently...
- A developer could listen to a ModifyDamage event, use any userParms data, alter the damage via an out parameter (perhaps even altering the damage type if that were added), as well as...
- The same developer could listen to a PostDamage event, using the same userParms data to apply conditions or any other post-hit effects that aren't "Effects"

In the case where no such additional damage parameters are defined (i.e. the attribute is a null or zero length array), the standard Damage call (i.e. one that doesn't pass the userParms argument) would be made and aside from any overhead related to checking for event listeners, I wouldn't expect the result to take any longer than normal. In the case where more work is done (i.e. there *are* some parameters defined and listeners to use them), that becomes the purview of the developer to optimize.

In this scenario, I as a developer and user of your framework, can expand on the entire damage system without needing modify core pieces of your framework to do so, also allowing me to freely update as you release fixes and the like without having to worry that I'm going to need to very carefully merge such changes into code I've tweaked.
 
Top