More generic damage handling system

So here is a thing. The damage system provided in engine right now is not really flexible or generic. It’s leftover from shooter times, where you needed to damage only single property, and where there was no reflection to easily find functions or properties in class.

I’m curious what do you guys think about:

  1. Removing all damage oriented things from actor.
  2. Moving them into their own component.
  3. Utilizing code reflection to find property in component and apply modification to it. There it doesn’t need to be damage. It can be any mathematical operation.
  4. Dunno what to do about DamageTypes. The idea is in general good, but name DamageType would be misleading. One thing that should be done, that this class should be extensible in blueprint using event graph.

I have most of this things done, if anyone is interested I might revise it to strip it of any features, which are not about damage handling, and make pull request for consideration.

The damage code in actor is something we discussed internally quite a lot in the early UE4 days. We have some functionality now that we didn’t then, so perhaps moving damage support to a component or an interface is more viable now, but it’s not a high priority item at the moment I’m afraid.

That said, the current damage system was designed with extensibility in mind. Have a look at the recent blog post on damage for more details.

Oh, and if you find you have a use case that isn’t supported with the current system, I’d love to hear more about it. :slight_smile:

Ability to damage multiple properties at once. Like Health, Energy and Constitution. First I tried to hack it around using DamageTypes and by including in damage type formula that actually did damage to actor. It had two major flaws. DamageType can’t be extended using Blueprint graph. Second, you would need myriad of possible damage type combinations to cover all cases.

I really had spend some time tried to hack it around, but in the end I just decided it will be much easier to create my own damage system, pulling things from there original where it makes sense. It’s not as fleshed out with data structures and events, but it does thing I need it to.
With reflection I just specify name of property to damage and that’s all. Or with another function I can specify array of names. Or I can just chain first function with different parameters in blueprint.

i think you can create a nex variable call it energy or wathever you like to and you the if statement to do somthing like (if health <50 then energy =40…) or create a variable and make it for example energy =2* health…)
correct me if i made a mistake and excuse my english^^

And create one huge if mess in single function ? :smiley:

Besides, TakeDamage function take paramter to specify which property you want to damage.

^^ i thought about that too^^ it is not the best solution but for example energy loss don’t kill really it only makes you tired and if you don’t have energy at all you start losing health point so you can make it easier make a variable energy that start by 1000 and loss -5 per second (example) and you make fewer if (if energy <500 walking speed -=5 if energy <200 make an effect on the screen to fell tired and if energy =0 then life loose 5 per second until the character dies …^^

Try creating your own event type based on FDamageEvent.

struct FMyDamageEvent : public FDamageEvent
	float HealthDamage;
	float EnergyDamage;
	float ConstitutionDamage;
	// whatever other info you need to describe the damage

Then in your AMyActor::TakeDamage() function, you can unpack the event and handle the damage however you want.

It’s actually nice idea but it have two possible flaws that I tried to avoid:

  1. I have to create struct for each possible combination of damaged attributes.
  2. I have to create super struct containing all possible information about damageable attributes. And working with such big structs is nightmare inside blueprint (that is where I want to make majority of the game logic). With 5 or so no problem. But if you have more than 15 of them ?

Also creating my struct for it, also invalidate structs lower in hierarchy like FRadialDamageEvent.

Though I will remember to check it back when fleshing out my component based implementation (;.

Can you create a single struct with the superset of all damageable attributes? If one of the attributes is zero, that means it wasn’t damaged.

You should be able to determine the event type at runtime and make decisions on how to handle it (see the IsOfType() function). Having a new event type should in no way obstruct usage of the other event types.

Yeah I pointed it in second point actually. But I once tried to work with big struct in blueprint and it was not pleasant experience ;).

I know. But what if I want apply radial damage to multiple attributes ?

Now my workflow using blueprint looks like this:

  1. Use static function that, takes Attribute Name, Mod Value, and type of operation to perform (add, subtract, multiply, etc). And just fire it.

  2. Or instead specify effect that will do something to provided values before applying damage. You can specify multiple attributes to damage each with individual mod value and operation type in single batch.

  3. At one point I used structs to group data, but it wasn’t that good thought off and it created more mess than it was worth it. But idea is worth exploring for Delegates usage.

Internally it call simple functions that simply perform math operation on provided attributes.

Subclass the existing FRadialDamageEvent to add the data you need?

Yeah, I can see how that would be unwieldy. But I’m also not surprised that a complex damage model would result in a complex API. You could maybe wrap certain common combinations in BP macros to help clean things up, but that’s really just a visual bandaid.

Glad to see you found an approach that’s working for you though!