I have several DamageTypes. I want to do something special for Character depending on what DamageType have taken.
Now I use this code for solve my problem. But I don’t want to use IF statements + casting!
float ABaseCharacter::TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, class AActor* DamageCauser)
{
UDamageType *DamageType = Cast<UMyDamageType1>(DamageEvent.DamageTypeClass->GetDefaultObject());
if (DamageType){
//do something
}
DamageType = Cast<UMyDamageType2>(DamageEvent.DamageTypeClass->GetDefaultObject());
if (DamageType){
//do something
}
// and there will be many same code (copy-paste) because
// I need to find what DamageType I got.
return Damage;
}
Is there more elegant solution?
Simple answer is not really. If you want a switch you’d have to put an Int based type inside the base damage type class or a single subclass.
Okay, for example I have 3 classes Dtype1,Dtype2,Dtype3
Each class have public int field which identify class.
In TakeDamage I receive DamageEvent and I don’t know what type is it. I can write something like:
float ABaseCharacter::TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, class AActor* DamageCauser)
{
auto DamageVarible = DamageEvent.DamageTypeClass->GetDefaultObject()); // I got the object reference. But I can't get field from it because it need casting in type, which I don't know.
}
So the field in class does not help to identify it.
I don’t know how this help me. Can you explain?
Hey you can do something like this, to get the Base class and then check the class type.
e.g:
UDamageType* DmgType = Cast<UDamageType>(DamageEvent.DamageTypeClass->GetDefaultObject());
if (DmgType)
{
// Switch or else if statments.
if (DmgType->IsA(USomeDamageType::StaticClass()))
{
}
else if (DmgType->IsA(USomeOtherDamageType::StaticClass()))
{
}
}
Also you can get it directly like this.
USomeDamageType* DmgType = DamageEvent.DamageTypeClass->GetDefaultObject<USomeDamageType>();
Hope it helps.
Do you know, is it possible to get field’s value from DamageVarible?
float ABaseCharacter::TakeDamage(float Damage, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, class AActor* DamageCauser)
{
auto DamageVarible = DamageEvent.DamageTypeClass->GetDefaultObject()); // I got the object reference. But I can't get field from it because it need casting in type, which I don't know.
}
If i can automatically cast or receive by TakeDamage the object of class from which I can get field’s value…
Ok i don`t understand what you mean by that.
Are you trying to access propertys spesific to a UDamageType without casting it?
Yes! Is it possible if I don’t know type?
What I would do is create a MyDamageClass which has an int in it that tells you what type it is. Then for your actual damage types, use this MyDamageClass as a parent. You should then be able to do something like
UMyDamageClass * dmg = Cast <UMyDamageClass> ( GivenObject);
and then call dmg->MyType as part of a switch.
Well with out casting to atleast a base class I will say no.
How ever when debugging I did see the members for the damage type in ClassDefaultObject member.
So the data is there somewhere in memory, but if you can safely access it i have no idea.
*
I think a better method is having your Damage types derived from one class.
With some virtual methods in them, so you don`t have to worry about the type.
Just have your class do its own thing and all you do is call the method`s.*
Thanks all. I’v solved my problem my use polymorphysm. I create virtual function in base class. And override it in derived classes. Then I can easily access to it by using:
UMyBaseDamageType *DamageType = Cast<UMyBaseDamageType>(DamageEvent.DamageTypeClass->GetDefaultObject());
DamageType->ProcessDamage();
And the ProcessDamage() implementation depends on which class I’v received from DamageEvent
1 Like