Skip to content

Commit c89bd86

Browse files
committed
PluginAdded
1 parent 4eb09d5 commit c89bd86

21 files changed

Lines changed: 1877 additions & 0 deletions
25.7 KB
Binary file not shown.
76.1 KB
Binary file not shown.
77.5 KB
Binary file not shown.

Content/UI/WBP_World_Widget.uasset

59.5 KB
Binary file not shown.

ResourceCompPlugin.uplugin

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"EngineVersion":"5.4",
3+
"FileVersion": 3,
4+
"Version": 1,
5+
"VersionName": "1.0",
6+
"FriendlyName": "Resource Component Plugin",
7+
"Description": "Actor Component that can be used for various resources. Includes a modifiable Health component and a ready-made Health component with UI elements.",
8+
"Category": "LyCH",
9+
"CreatedBy": "LyCH",
10+
"CreatedByURL": "",
11+
"DocsURL": "https://docs.google.com/document/d/1MueuRAWY_xoaRL8tqMC0FaAjy9vT64bCArStPIcOVZU/edit?usp=drive_link",
12+
"MarketplaceURL": "com.epicgames.launcher://ue/marketplace/product/849a9f0fec7040b1b4cca2b5d26a2755",
13+
"SupportURL": "",
14+
"CanContainContent": true,
15+
"IsBetaVersion": false,
16+
"IsExperimentalVersion": false,
17+
"Installed": false,
18+
"Modules": [
19+
{
20+
"Name": "ResourceCompPlugin",
21+
"Type": "Runtime",
22+
"LoadingPhase": "Default",
23+
"PlatformAllowList":["Win64","Mac"]
24+
}
25+
]
26+
}

Resources/Icon128.png

16 KB
Loading
Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
// Copyright LyCH. 2024
2+
3+
4+
#include "Components/Health/HealthResource.h"
5+
#include "Interfaces/DamageTypeModificationInterface.h"
6+
#include "Data/DamageModificationData.h"
7+
8+
#include "Net/UnrealNetwork.h"
9+
#include "Kismet/KismetMathLibrary.h"
10+
#include "Kismet/KismetSystemLibrary.h"
11+
12+
//MP Reqs
13+
#include "GameFramework/Pawn.h"
14+
#include "GameFramework/DamageType.h"
15+
#include "Engine.h"
16+
17+
UHealthResource::UHealthResource() {
18+
ResourceName = "Health";
19+
}
20+
void UHealthResource::BeginPlay() {
21+
Super::BeginPlay();
22+
//Self delegates
23+
if (IsServer()) {
24+
OnGenericDamageTaken.AddDynamic(this, &UHealthResource::GenericDamageTaken);
25+
OnPointDamageTaken.AddDynamic(this, &UHealthResource::PointDamageTaken);
26+
OnRadialDamageTaken.AddDynamic(this, &UHealthResource::RadialDamageTaken);
27+
GiveModificationData(DefaultModificationData);
28+
}
29+
//Owner Delegates
30+
BindDamageDelegates();
31+
}
32+
void UHealthResource::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const {
33+
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
34+
DOREPLIFETIME(UHealthResource, ModificationRules);
35+
DOREPLIFETIME(UHealthResource, LastDamageCauser);
36+
DOREPLIFETIME(UHealthResource, LastLocationHitFrom);
37+
}
38+
// Getters
39+
bool UHealthResource::IsServer() const {
40+
return GetOwner()->HasAuthority();
41+
}
42+
bool UHealthResource::IsLocallyControlled() const {
43+
if (Cast<APawn>(GetOwner()))
44+
if (Cast<APawn>(GetOwner())->IsLocallyControlled())
45+
return true;
46+
return false;
47+
}
48+
bool UHealthResource::IsPlayerControlled() const {
49+
if (Cast<APawn>(GetOwner()))
50+
if (Cast<APawn>(GetOwner())->IsPlayerControlled())
51+
return true;
52+
return false;
53+
}
54+
bool UHealthResource::HasModifications(TArray<FName> modificationNames) {
55+
for (FIncomingDamageModification m : ModificationRules) {
56+
if (modificationNames.Contains(m.ModificationName)) {
57+
return true;
58+
}
59+
}
60+
return false;
61+
}
62+
float UHealthResource::GetDirection(const FVector& Direction, const FRotator& BaseRotation) const {
63+
if (Direction.IsNearlyZero()) {
64+
return 0.f;
65+
}
66+
FMatrix RotMatrix = FRotationMatrix(BaseRotation);
67+
FVector ForwardVector = RotMatrix.GetScaledAxis(EAxis::X);
68+
FVector RightVector = RotMatrix.GetScaledAxis(EAxis::Y);
69+
FVector NormalizedVel = Direction.GetSafeNormal2D();
70+
71+
// get a cos(alpha) of forward vector vs velocity
72+
float ForwardCosAngle = FVector::DotProduct(ForwardVector, NormalizedVel);
73+
// now get the alpha and convert to degree
74+
float ForwardDeltaDegree = FMath::RadiansToDegrees(FMath::Acos(ForwardCosAngle));
75+
76+
// depending on where right vector is, flip it
77+
float RightCosAngle = FVector::DotProduct(RightVector, NormalizedVel);
78+
if (RightCosAngle < 0) {
79+
ForwardDeltaDegree *= -1;
80+
}
81+
return ForwardDeltaDegree;
82+
}
83+
float UHealthResource::GetDirectionToLocation(const FVector& Location, const FRotator& BaseRotation) const {
84+
if (!GetOwner())
85+
return 0.f;
86+
87+
FRotator DirectionRot = UKismetMathLibrary::FindLookAtRotation(GetOwner()->GetActorLocation(), Location);
88+
89+
if (DirectionRot.Vector().IsNearlyZero())
90+
return 0.f;
91+
92+
FMatrix RotMatrix = FRotationMatrix(BaseRotation);
93+
FVector ForwardVector = RotMatrix.GetScaledAxis(EAxis::X);
94+
FVector RightVector = RotMatrix.GetScaledAxis(EAxis::Y);
95+
FVector NormalizedVel = DirectionRot.Vector().GetSafeNormal2D();
96+
97+
// get a cos(alpha) of forward vector vs velocity
98+
float ForwardCosAngle = FVector::DotProduct(ForwardVector, NormalizedVel);
99+
// now get the alpha and convert to degree
100+
float ForwardDeltaDegree = FMath::RadiansToDegrees(FMath::Acos(ForwardCosAngle));
101+
102+
// depending on where right vector is, flip it
103+
float RightCosAngle = FVector::DotProduct(RightVector, NormalizedVel);
104+
if (RightCosAngle < 0) {
105+
ForwardDeltaDegree *= -1;
106+
}
107+
return ForwardDeltaDegree;
108+
}
109+
// Modify Damage
110+
float UHealthResource::K2_ModifyDamage_Implementation(float damageReceived, EIncomingDamageChannel damageChannel, const class UDamageType* DamageType, FName boneName, FVector damageOrigin) const {
111+
return ModifyDamage(damageReceived, damageChannel, DamageType, boneName, damageOrigin);
112+
}
113+
float UHealthResource::ModifyDamage(float damageReceived, EIncomingDamageChannel damageChannel, const class UDamageType* DamageType, FName boneName, FVector damageOrigin) const {
114+
float modifiedDamage = damageReceived;
115+
bool bWhiteListedDamageType = true;
116+
bool bCorrectBone = false;
117+
bool bWithinRange = false;
118+
bool bCorrectDamageChannel = false;
119+
for (FIncomingDamageModification modification : ModificationRules) {
120+
bWhiteListedDamageType = ModificationAcceptsDamageType(modification, DamageType);
121+
bCorrectBone = (damageChannel != EIncomingDamageChannel::PointDamage || modification.WhitelistedBoneNames.Num() == 0 || modification.WhitelistedBoneNames.Contains(boneName));
122+
bWithinRange = (modification.MinimumRange <= 0 || (damageOrigin - GetOwner()->GetActorLocation()).Length() >= modification.MinimumRange)
123+
&& (modification.MaximumRange <= 0 || (damageOrigin - GetOwner()->GetActorLocation()).Length() <= modification.MaximumRange);
124+
bCorrectDamageChannel = (damageChannel == modification.DamageChannel || modification.DamageChannel == AllChannels);
125+
if (bWhiteListedDamageType && bWithinRange && bCorrectBone && bCorrectDamageChannel) {
126+
127+
if (modification.ModificationType == EIncomingDamageModificationType::Override_Damage) {
128+
return modification.Magnitude;
129+
}
130+
if (modification.ModificationType == EIncomingDamageModificationType::Modify_From_DamageType) {
131+
if (UKismetSystemLibrary::DoesImplementInterface(DamageType->GetClass()->GetDefaultObject(), UDamageTypeModificationInterface::StaticClass())) {
132+
modifiedDamage = IDamageTypeModificationInterface::Execute_ModifyDamage(DamageType->GetClass()->GetDefaultObject(), damageReceived, GetOwner());
133+
}
134+
}
135+
if (modification.ModificationType == EIncomingDamageModificationType::Add_Damage) {
136+
modifiedDamage = modifiedDamage + modification.Magnitude;
137+
}
138+
if (modification.ModificationType == EIncomingDamageModificationType::Multiply_Damage) {
139+
modifiedDamage = modifiedDamage * modification.Magnitude;
140+
}
141+
}
142+
}
143+
return modifiedDamage;
144+
}
145+
bool UHealthResource::ModificationAcceptsDamageType(FIncomingDamageModification modification, const UDamageType* damageType) const {
146+
if (modification.WhitelistedDamageTypes.Num() <= 0 || modification.WhitelistedDamageTypes.Contains(damageType->GetClass())) { return true; }
147+
148+
if (!modification.bWhitelistChildDamageTypes) { return false; }
149+
150+
for (TSubclassOf<UDamageType> damageClass : modification.WhitelistedDamageTypes) {
151+
if (damageType->GetClass()->IsChildOf(damageClass))
152+
return true;
153+
}
154+
155+
return false;
156+
}
157+
void UHealthResource::GiveModifier(FIncomingDamageModification newModifier, int insertAt) {
158+
if (insertAt >= 0) {
159+
ModificationRules.Insert(newModifier, insertAt);
160+
}
161+
else {
162+
ModificationRules.Add(newModifier);
163+
}
164+
ModificationChanged(newModifier, true);
165+
166+
}
167+
void UHealthResource::GiveModificationData(UDamageModificationData* modificationData, int beginInsertAt) {
168+
if (!IsValid(modificationData)) { return; }
169+
170+
for (int i = 0; i < modificationData->Modifications.Num(); i++) {
171+
if (beginInsertAt < 0) {
172+
GiveModifier(modificationData->Modifications[i]);
173+
}
174+
else {
175+
GiveModifier(modificationData->Modifications[i], beginInsertAt + i);
176+
}
177+
}
178+
ModificationDataAdded(modificationData);
179+
}
180+
void UHealthResource::RemoveModifier(FName modifierName) {
181+
for (int index = 0; index < ModificationRules.Num(); index++) {
182+
if (ModificationRules[index].ModificationName == modifierName) {
183+
const FIncomingDamageModification mod = ModificationRules[index];
184+
ModificationRules.RemoveAt(index);
185+
ModificationChanged(mod, false);
186+
}
187+
}
188+
}
189+
void UHealthResource::ModificationDataAdded_Implementation(const UDamageModificationData* modificationData) {
190+
OnModificationDataAdded.Broadcast(modificationData);
191+
}
192+
void UHealthResource::ModificationChanged_Implementation(FIncomingDamageModification modification, bool bAdded) {
193+
bAdded ? OnModificationAdded.Broadcast(modification) : OnModificationRemoved.Broadcast(modification);
194+
}
195+
// Damage Binders
196+
void UHealthResource::OnAnyDamage(AActor* DamagedActor, float Damage, const UDamageType* DamageType, AController* InstigatedBy, AActor* DamageCauser) {
197+
LastDamageCauser = DamageCauser;
198+
if (bBlockDamage) {
199+
bBlockDamage = false;
200+
return;
201+
}
202+
float modifiedDamage = ModifyDamage(Damage, EIncomingDamageChannel::GenericDamage, DamageType, FName(), DamageCauser->GetActorLocation());
203+
DrainResource(modifiedDamage);
204+
LastLocationHitFrom = DamageCauser->GetActorLocation();
205+
OnGenericDamageTaken.Broadcast(GetOwner(), modifiedDamage, DamageType, InstigatedBy, DamageCauser);
206+
if (bDebug) {
207+
FString debugString = FString(GetNameSafe(this)).Append(": Damage received in Any Damage: ").Append(FString::SanitizeFloat(Damage));
208+
GEngine->AddOnScreenDebugMessage(INDEX_NONE, 1.f, FColor::Green, *debugString);
209+
}
210+
211+
}
212+
void UHealthResource::OnPointDamage(AActor* DamagedActor, float Damage, AController* InstigatedBy, FVector HitLocation, UPrimitiveComponent* HitComponent, FName BoneName, FVector ShotFromDirection, const UDamageType* DamageType, AActor* DamageCauser) {
213+
bBlockDamage = true;
214+
float modifiedDamage = ModifyDamage(Damage, EIncomingDamageChannel::PointDamage, DamageType, BoneName, DamageCauser->GetActorLocation());
215+
DrainResource(modifiedDamage);
216+
LastLocationHitFrom = DamageCauser->GetActorLocation();
217+
OnPointDamageTaken.Broadcast(DamagedActor, modifiedDamage, InstigatedBy, HitLocation, HitComponent, BoneName, ShotFromDirection, DamageType, DamageCauser);
218+
if (bDebug) {
219+
FString debugString = FString(GetNameSafe(this)).Append(": Point Damage: ").Append(FString::SanitizeFloat(modifiedDamage));
220+
GEngine->AddOnScreenDebugMessage(INDEX_NONE, 1.f, FColor::Green, *debugString);
221+
}
222+
223+
}
224+
void UHealthResource::OnRadialDamage(AActor* DamagedActor, float Damage, const UDamageType* DamageType, FVector Origin, const FHitResult& HitInfo, AController* InstigatedBy, AActor* DamageCauser) {
225+
bBlockDamage = true;
226+
float modifiedDamage = ModifyDamage(Damage, EIncomingDamageChannel::RadialDamage, DamageType, FName(), Origin);
227+
DrainResource(modifiedDamage);
228+
LastLocationHitFrom = Origin;
229+
OnRadialDamageTaken.Broadcast(DamagedActor, modifiedDamage, DamageType, Origin, HitInfo, InstigatedBy, DamageCauser);
230+
if (bDebug) {
231+
FString debugString = FString(GetNameSafe(this)).Append(": Radial Damage: ").Append(FString::SanitizeFloat(modifiedDamage));
232+
GEngine->AddOnScreenDebugMessage(INDEX_NONE, 1.f, FColor::Green, *debugString);
233+
}
234+
}
235+
236+
void UHealthResource::K2_BindDamageDelegates_Implementation(){
237+
BindDamageDelegates();
238+
}
239+
void UHealthResource::BindDamageDelegates() {
240+
GetOwner()->OnTakeAnyDamage.AddDynamic(this, &UHealthResource::OnAnyDamage);
241+
GetOwner()->OnTakePointDamage.AddDynamic(this, &UHealthResource::OnPointDamage);
242+
GetOwner()->OnTakeRadialDamage.AddDynamic(this, &UHealthResource::OnRadialDamage);
243+
}
244+
245+
void UHealthResource::GenericDamageTaken_Implementation(AActor* DamagedActor, float Damage, const UDamageType* DamageType, AController* InstigatedBy, AActor* DamageCauser) {
246+
if (!IsServer()) {
247+
OnGenericDamageTaken.Broadcast(DamagedActor, Damage, DamageType, InstigatedBy, DamageCauser);
248+
}
249+
}
250+
void UHealthResource::PointDamageTaken_Implementation(AActor* DamagedActor, float Damage, AController* InstigatedBy, FVector HitLocation, UPrimitiveComponent* HitComponent, FName BoneName, FVector ShotFromDirection, const UDamageType* DamageType, AActor* DamageCauser) {
251+
if (!IsServer()) {
252+
OnPointDamageTaken.Broadcast(DamagedActor, Damage, InstigatedBy, HitLocation, HitComponent, BoneName, ShotFromDirection, DamageType, DamageCauser);
253+
}
254+
}
255+
void UHealthResource::RadialDamageTaken_Implementation(AActor* DamagedActor, float Damage, const UDamageType* DamageType, FVector Origin, const FHitResult& HitInfo, AController* InstigatedBy, AActor* DamageCauser) {
256+
if (!IsServer()) {
257+
OnRadialDamageTaken.Broadcast(DamagedActor, Damage, DamageType, Origin, HitInfo, InstigatedBy, DamageCauser);
258+
}
259+
}
260+

0 commit comments

Comments
 (0)