├── .gitignore ├── Content └── Blueprints │ ├── Abilities │ ├── AbilityTest.uasset │ └── Channeled_Ability.uasset │ ├── Attribute.uasset │ ├── Attributes │ └── Sample_Human_attributes.uasset │ ├── AttributesEnum.uasset │ ├── AttributesMetaData.uasset │ ├── BP_Attributes.uasset │ ├── DamageTypes │ └── DamageType_Health.uasset │ ├── Effects │ ├── Actors │ │ ├── BPA_EffectFire.uasset │ │ └── BPA_ProjectileSpawner.uasset │ ├── BP_SpellCostBase.uasset │ ├── DamagePure.uasset │ ├── EffectSpread.uasset │ ├── HealEffect.uasset │ ├── IncomingEffect.uasset │ ├── LifeSteal.uasset │ ├── ModifierEffect.uasset │ ├── ModifierEffect_2.uasset │ └── OMHPeriodicEffect.uasset │ ├── HUD │ └── BP_RPGHUD.uasset │ ├── Items │ └── BP_RedChest.uasset │ ├── MyCharacter.uasset │ ├── NewBehaviorTree.uasset │ ├── NewBlueprint.uasset │ ├── Projectiles │ └── BP_TestProjectile.uasset │ ├── Tags.uasset │ └── Weapons │ └── BP_TestWeapon.uasset ├── LICENSE ├── README.md └── Source ├── RPG.Target.cs ├── RPG ├── Game │ ├── Abilities │ │ ├── GameAbility.cpp │ │ └── GameAbility.h │ ├── BlueprintLibrary │ │ ├── DamagefunctionStatics.cpp │ │ └── DamagefunctionStatics.h │ ├── Components │ │ ├── RPGAttributeBaseComponent.cpp │ │ ├── RPGAttributeBaseComponent.h │ │ ├── RPGEquipmentManagerComponent.cpp │ │ └── RPGEquipmentManagerComponent.h │ ├── DamageTypes │ │ ├── RPGDamageHealth.cpp │ │ ├── RPGDamageHealth.h │ │ ├── RPGDamageType.cpp │ │ └── RPGDamageType.h │ ├── Effects │ │ ├── EffectActors │ │ │ ├── RPGProjectileSpawner.cpp │ │ │ └── RPGProjectileSpawner.h │ │ ├── GameEffect.cpp │ │ ├── GameEffect.h │ │ ├── RPGEffectActor.cpp │ │ └── RPGEffectActor.h │ ├── GameAttributes.cpp │ ├── GameAttributes.h │ ├── HUD │ │ ├── RPGHUD.cpp │ │ └── RPGHUD.h │ ├── Items │ │ ├── RPGItem.cpp │ │ ├── RPGItem.h │ │ ├── RPGWeaponBase.cpp │ │ └── RPGWeaponBase.h │ ├── RPGCharacter.cpp │ ├── RPGCharacter.h │ ├── RPGEngine.cpp │ ├── RPGEngine.h │ ├── RPGEngineEditor.cpp │ ├── RPGEngineEditor.h │ ├── RPGGameMode.cpp │ ├── RPGGameMode.h │ ├── RPGPlayerController.cpp │ ├── RPGPlayerController.h │ ├── RPGProjectile.cpp │ ├── RPGProjectile.h │ └── Shared │ │ ├── RPGAttributeStructs.h │ │ └── RPGEnums.h ├── Public │ ├── RPG.cpp │ └── RPG.h ├── RPG.Build.cs ├── RPGSystem │ ├── Abilities │ │ ├── RPGAbilityBase.cpp │ │ └── RPGAbilityBase.h │ ├── BlueprintLibrary │ │ ├── RPGAttributeBPLibrary.cpp │ │ ├── RPGAttributeBPLibrary.h │ │ ├── RPGCreateNewObject.cpp │ │ ├── RPGCreateNewObject.h │ │ ├── RPGEffectBPLibrary.cpp │ │ └── RPGEffectBPLibrary.h │ ├── Components │ │ ├── RPGAbilityManagerComponent.cpp │ │ ├── RPGAbilityManagerComponent.h │ │ ├── RPGAttributeComponent.cpp │ │ └── RPGAttributeComponent.h │ ├── Effects │ │ ├── RPGEffectAreaSpread.cpp │ │ ├── RPGEffectAreaSpread.h │ │ ├── RPGEffectBase.cpp │ │ ├── RPGEffectBase.h │ │ ├── RPGEffectCombat.cpp │ │ ├── RPGEffectCombat.h │ │ ├── RPGEffectInstant.cpp │ │ ├── RPGEffectInstant.h │ │ ├── RPGEffectModifier.cpp │ │ ├── RPGEffectModifier.h │ │ ├── RPGEffectPeriodic.cpp │ │ ├── RPGEffectPeriodic.h │ │ ├── RPGEffectUtility.cpp │ │ └── RPGEffectUtility.h │ ├── RPGAttributeBase.cpp │ ├── RPGAttributeBase.h │ └── Structs │ │ ├── RPGSystemSructs.cpp │ │ └── RPGSystemSructs.h └── Resources │ └── Windows │ ├── RPG.ico │ └── RPG.rc └── RPGEditor.Target.cs /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Compiled Dynamic libraries 8 | *.so 9 | *.dylib 10 | *.dll 11 | 12 | # Compiled Static libraries 13 | *.lai 14 | *.la 15 | *.a 16 | *.lib 17 | 18 | # Executables 19 | *.exe 20 | *.out 21 | *.app 22 | -------------------------------------------------------------------------------- /Content/Blueprints/Abilities/AbilityTest.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Abilities/AbilityTest.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Abilities/Channeled_Ability.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Abilities/Channeled_Ability.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Attribute.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Attribute.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Attributes/Sample_Human_attributes.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Attributes/Sample_Human_attributes.uasset -------------------------------------------------------------------------------- /Content/Blueprints/AttributesEnum.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/AttributesEnum.uasset -------------------------------------------------------------------------------- /Content/Blueprints/AttributesMetaData.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/AttributesMetaData.uasset -------------------------------------------------------------------------------- /Content/Blueprints/BP_Attributes.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/BP_Attributes.uasset -------------------------------------------------------------------------------- /Content/Blueprints/DamageTypes/DamageType_Health.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/DamageTypes/DamageType_Health.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Effects/Actors/BPA_EffectFire.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Effects/Actors/BPA_EffectFire.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Effects/Actors/BPA_ProjectileSpawner.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Effects/Actors/BPA_ProjectileSpawner.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Effects/BP_SpellCostBase.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Effects/BP_SpellCostBase.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Effects/DamagePure.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Effects/DamagePure.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Effects/EffectSpread.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Effects/EffectSpread.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Effects/HealEffect.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Effects/HealEffect.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Effects/IncomingEffect.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Effects/IncomingEffect.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Effects/LifeSteal.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Effects/LifeSteal.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Effects/ModifierEffect.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Effects/ModifierEffect.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Effects/ModifierEffect_2.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Effects/ModifierEffect_2.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Effects/OMHPeriodicEffect.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Effects/OMHPeriodicEffect.uasset -------------------------------------------------------------------------------- /Content/Blueprints/HUD/BP_RPGHUD.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/HUD/BP_RPGHUD.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Items/BP_RedChest.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Items/BP_RedChest.uasset -------------------------------------------------------------------------------- /Content/Blueprints/MyCharacter.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/MyCharacter.uasset -------------------------------------------------------------------------------- /Content/Blueprints/NewBehaviorTree.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/NewBehaviorTree.uasset -------------------------------------------------------------------------------- /Content/Blueprints/NewBlueprint.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/NewBlueprint.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Projectiles/BP_TestProjectile.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Projectiles/BP_TestProjectile.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Tags.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Tags.uasset -------------------------------------------------------------------------------- /Content/Blueprints/Weapons/BP_TestWeapon.uasset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Content/Blueprints/Weapons/BP_TestWeapon.uasset -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Lukasz 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Please use this instead: 2 | https://github.com/iniside/ActionRPGGame 3 | 4 | As this project is no longer under active development. 5 | 6 | 7 | RPGFramework 8 | ============ 9 | 10 | Basic RPG Game framework for Unreal Engine 4 11 | -------------------------------------------------------------------------------- /Source/RPG.Target.cs: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class RPGTarget : TargetRules 7 | { 8 | public RPGTarget(TargetInfo Target) 9 | { 10 | Type = TargetType.Game; 11 | } 12 | 13 | // 14 | // TargetRules interface. 15 | // 16 | 17 | public override void SetupBinaries( 18 | TargetInfo Target, 19 | ref List OutBuildBinaryConfigurations, 20 | ref List OutExtraModuleNames 21 | ) 22 | { 23 | OutExtraModuleNames.Add("RPG"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Source/RPG/Game/Abilities/GameAbility.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | #include "RPG.h" 4 | #include "../Components/RPGAttributeBaseComponent.h" 5 | #include "../Components/RPGEquipmentManagerComponent.h" 6 | #include "../RPGPlayerController.h" 7 | #include "../RPGCharacter.h" 8 | #include "../Items/RPGWeaponBase.h" 9 | #include "../Shared/RPGEnums.h" 10 | #include "GameAbility.h" 11 | 12 | 13 | UGameAbility::UGameAbility(const class FPostConstructInitializeProperties& PCIP) 14 | : Super(PCIP) 15 | { 16 | 17 | } 18 | 19 | void UGameAbility::Tick(float DeltaTime) 20 | { 21 | Super::Tick(DeltaTime); 22 | } 23 | 24 | /* 25 | If there is no component on actor then we don't initialize 26 | because powers need attributes to work properly. 27 | */ 28 | void UGameAbility::Initialize(APawn* owner, AController* instigator) 29 | { 30 | Super::Initialize(owner, instigator); 31 | if (AbilityOwner) 32 | { 33 | if (GetWorld()) 34 | { 35 | if (OwnerAttributeComp.IsValid()) 36 | { 37 | OwnerAttributes = Cast(OwnerAttributeComp.Get()); 38 | } 39 | EquipComp = AbilityOwner->FindComponentByClass(); 40 | 41 | if (OwnerAttributes.IsValid() && EquipComp.IsValid()) 42 | { 43 | IsAbilityInitialized = true; 44 | return; 45 | } 46 | IsAbilityInitialized = false; 47 | } 48 | IsAbilityInitialized = false; 49 | } 50 | IsAbilityInitialized = false; 51 | } 52 | 53 | void UGameAbility::InputPressed() 54 | { 55 | bool haveRequiredWeapon = false; 56 | if (IsAbilityInitialized) 57 | { 58 | //if (!CalculateFinalCost(BaseEnergyCost, BaseHealthCost, BaseStaminaCost)) 59 | //return; 60 | /* 61 | We assign weapon on button press, to make sure that when player changed weapon 62 | we can check if there is required weapon. 63 | */ 64 | MainHand = EquipComp->MainWeapon; 65 | OffHand = EquipComp->OffHandWeapon; 66 | 67 | if (MainHand) 68 | { 69 | if (MainHand->WeaponType == RequiredWeapon) 70 | { 71 | //we could add return here. If have one weapon 72 | //we don't need to check for second one. 73 | haveRequiredWeapon = true; 74 | } 75 | else 76 | { 77 | UE_LOG(LogTemp, Warning, TEXT("You don't have needed weapon")); 78 | return; 79 | } 80 | } 81 | if (OffHand) 82 | { 83 | if (OffHand->WeaponType == RequiredWeapon) 84 | { 85 | haveRequiredWeapon = true; 86 | } 87 | else if (!haveRequiredWeapon) //we need at least one compatibile weapon. 88 | { 89 | UE_LOG(LogTemp, Warning, TEXT("You don't have needed weapon")); 90 | return; 91 | } 92 | } 93 | Super::InputPressed(); 94 | } 95 | } 96 | 97 | void UGameAbility::InputReleased() 98 | { 99 | Super::InputReleased(); 100 | //if (AbilityCastType == ECastType::Channeled) 101 | //{ 102 | // OnAbilityStop(); 103 | // isChanneled = false; 104 | //} 105 | } 106 | 107 | bool UGameAbility::CalculateFinalCost(float energyCost, float healthCost, float staminaCost) 108 | { 109 | float FinalEnergyCost = energyCost; //make some clever calculations based on various attributes; 110 | float FinalHealthCost = healthCost; 111 | float FinalStaminaCost = staminaCost; 112 | //now we check: 113 | //if we got this far, there is no chance that component is null. 114 | //if ((OwnerAttributes->GetEnergy() >= FinalEnergyCost) && 115 | // (OwnerAttributes->GetHealth() >= FinalHealthCost) && 116 | // (OwnerAttributes->GetStamina() >= FinalStaminaCost) 117 | // ) 118 | //{ 119 | // OwnerAttributes->SubtractEnergy(FinalEnergyCost); 120 | // OwnerAttributes->SubtractHealth(FinalHealthCost); 121 | // OwnerAttributes->SubtractStamina(FinalStaminaCost); 122 | // return true; 123 | //} 124 | 125 | //if (OwnerAttributeComp->GetHealth() >= FinalHealthCost) 126 | //{ 127 | // OwnerAttributeComp->SubtractHealth(FinalHealthCost); 128 | //} 129 | 130 | //if (OwnerAttributeComp->GetStamina() >= FinalStaminaCost) 131 | //{ 132 | // OwnerAttributeComp->SubtractStamina(FinalStaminaCost); 133 | //} 134 | return false; 135 | } 136 | 137 | FHitResult UGameAbility::GetHitResult(float Range, FName StartSocket) 138 | { 139 | const FVector Origin = GetCastingLocation(StartSocket); 140 | const FVector ShootDir = GetCameraAim(); 141 | 142 | const FVector StartTrace = GetCameraDamageStarLocation(ShootDir); 143 | const FVector EndTrace = (StartTrace + ShootDir * Range); 144 | FHitResult Impact = RangedPowerTrace(StartTrace, EndTrace); 145 | 146 | DrawDebugLine(GetWorld(), StartTrace, EndTrace, FColor::Black, true, 10.0f, 0.0f, 1.0f); 147 | 148 | if (Impact.GetActor()) 149 | { 150 | float impactLen; 151 | FVector impactDir; 152 | const FVector AdjustedDir = (Impact.ImpactPoint - Origin).SafeNormal(); 153 | Impact.ImpactPoint.ToDirectionAndLength(impactDir, impactLen); 154 | FHitResult hitResult = RangedPowerTrace(Origin, Impact.ImpactPoint); //Origin + impactDir*range); 155 | DrawDebugLine(GetWorld(), Origin, Impact.ImpactPoint, FColor::Blue, true, 10.0f, 0.0f, 1.0f); 156 | 157 | TargetAttributes = Impact.Actor->FindComponentByClass(); 158 | 159 | if (hitResult.GetActor()) 160 | { 161 | DrawDebugLine(GetWorld(), Origin, Impact.ImpactPoint, FColor::Red, true, 10.0f, 0.0f, 1.0f); 162 | return hitResult; 163 | } 164 | return Impact; 165 | } 166 | return Impact; 167 | } 168 | 169 | AActor* UGameAbility::GetActorHit(float Range, FName StartSocket) 170 | { 171 | FVector Origin = GetCastingLocation(StartSocket); 172 | const FVector ShootDir = GetCameraAim(); 173 | 174 | FVector StartTrace = GetCameraDamageStarLocation(ShootDir); 175 | const FVector EndTrace = (StartTrace + ShootDir * Range); 176 | FHitResult Impact = RangedPowerTrace(StartTrace, EndTrace); 177 | 178 | DrawDebugLine(GetWorld(), StartTrace, EndTrace, FColor::Black, true, 10.0f, 0.0f, 1.0f); 179 | 180 | if (Impact.GetActor()) 181 | { 182 | float impactLen; 183 | FVector impactDir; 184 | const FVector AdjustedDir = (Impact.ImpactPoint - Origin).SafeNormal(); 185 | Impact.ImpactPoint.ToDirectionAndLength(impactDir, impactLen); 186 | FHitResult hitResult = RangedPowerTrace(Origin, Impact.ImpactPoint); //Origin + impactDir*range); 187 | DrawDebugLine(GetWorld(), Origin, Impact.ImpactPoint, FColor::Blue, true, 10.0f, 0.0f, 1.0f); 188 | 189 | SetTargetAttributes(Impact.GetActor()); 190 | 191 | if (hitResult.GetActor()) 192 | { 193 | DrawDebugLine(GetWorld(), Origin, Impact.ImpactPoint, FColor::Red, true, 10.0f, 0.0f, 1.0f); 194 | return hitResult.GetActor(); 195 | } 196 | return Impact.GetActor(); 197 | } 198 | return nullptr; 199 | } 200 | 201 | void UGameAbility::SetTargetAttributes(AActor* targetActor) 202 | { 203 | if (targetActor) 204 | { 205 | TArray attributeComps; 206 | targetActor->GetComponents(attributeComps); 207 | for (URPGAttributeBaseComponent* attrComp : attributeComps) 208 | { 209 | TargetAttributes = attrComp; 210 | return; 211 | } 212 | } 213 | } 214 | 215 | void UGameAbility::SpawnTrailEffect(UParticleSystem* trailFX, float trailSpeed, FName trailSpeedParam, FHitResult target, FName SocketName) 216 | { 217 | FVector Origin = GetCastingLocation(SocketName); 218 | if (target.GetActor()) 219 | { 220 | if (trailFX) 221 | { 222 | UParticleSystemComponent* TrailPSC = UGameplayStatics::SpawnEmitterAtLocation(AbilityOwner, trailFX, Origin); 223 | if (TrailPSC) 224 | { 225 | const FVector AdjustedDir = (target.ImpactPoint - Origin).SafeNormal(); 226 | FVector ParticleSpeed = AdjustedDir * trailSpeed; 227 | TrailPSC->SetVectorParameter(trailSpeedParam, ParticleSpeed); 228 | } 229 | } 230 | } 231 | } 232 | 233 | 234 | FVector UGameAbility::GetCameraDamageStarLocation(const FVector& AimDir) const 235 | { 236 | FVector OutStartTrace = FVector::ZeroVector; 237 | if (Instigator) 238 | { 239 | FRotator UnusedRot; 240 | Instigator->GetPlayerViewPoint(OutStartTrace, UnusedRot); 241 | OutStartTrace = OutStartTrace + AimDir * ((AbilityOwner->GetActorLocation() - OutStartTrace) | AimDir); 242 | //OutStartTrace = OutStartTrace + AimDir * ((Instigator->GetActorLocation() - OutStartTrace)); 243 | } 244 | return OutStartTrace; 245 | } 246 | 247 | FVector UGameAbility::GetCameraAim() const 248 | { 249 | FVector FinalAim = FVector::ZeroVector; 250 | 251 | if (Instigator) 252 | { 253 | FVector CamLoc; 254 | FRotator CamRot; 255 | Instigator->GetPlayerViewPoint(CamLoc, CamRot); 256 | FinalAim = CamRot.Vector(); 257 | } 258 | else if (AbilityOwner) 259 | { 260 | FinalAim = AbilityOwner->GetBaseAimRotation().Vector(); 261 | } 262 | return FinalAim; 263 | } 264 | 265 | USkeletalMeshComponent* UGameAbility::GetWeaponMesh() const 266 | { 267 | if (AbilityOwner) 268 | { 269 | 270 | /* 271 | We check both main hand and offhand for weapon. As both can be used 272 | to use any power. 273 | */ 274 | if (MainHand) 275 | { 276 | return MainHand->WeaponMesh; 277 | } 278 | else if (OffHand) 279 | { 280 | return OffHand->WeaponMesh; 281 | } 282 | return nullptr; 283 | } 284 | return NULL; 285 | } 286 | 287 | FVector UGameAbility::GetCastingLocation(FName SocketName) const 288 | { 289 | const USkeletalMeshComponent* weapon = GetWeaponMesh(); 290 | if (weapon) 291 | { 292 | return weapon->GetSocketLocation(SocketName); 293 | } 294 | //if (MainCasterWeapon.IsValid()) 295 | //{ 296 | // return MainCasterWeapon->WeaponMesh->GetSocketLocation(SocketName); 297 | //} 298 | return FVector(0, 0, 0); 299 | } 300 | 301 | FVector UGameAbility::GetMuzzleDirection() 302 | { 303 | //USkeletalMeshComponent* UseMesh = GetWeaponMesh(); 304 | return GetWeaponMesh()->GetSocketRotation("MuzzleFlashSocket").Vector(); 305 | } 306 | 307 | FHitResult UGameAbility::RangedPowerTrace(const FVector& StartTrace, const FVector& EndTrace) const 308 | { 309 | FHitResult Hit(ForceInit); 310 | 311 | static FName PowerTag = FName(TEXT("PowerTrace")); 312 | FCollisionQueryParams TraceParams(PowerTag, false, AbilityOwner); 313 | TraceParams.bTraceComplex = false; 314 | TraceParams.bTraceAsyncScene = false; 315 | TraceParams.bReturnPhysicalMaterial = true; 316 | 317 | bool traceResult = GetWorld()->LineTraceSingle(Hit, StartTrace, EndTrace, ECollisionChannel::ECC_WorldDynamic, TraceParams); 318 | 319 | return Hit; 320 | } 321 | 322 | void UGameAbility::GetTableRow(UDataTable* Data, FName RowID, FAttributeData& OutData) 323 | { 324 | if (Data) 325 | { 326 | FAttributeData* tempRow = NULL; 327 | tempRow = Data->FindRow(RowID, "ContextString"); 328 | if (tempRow) 329 | { 330 | OutData = *tempRow; 331 | } 332 | //return tempRow; 333 | } 334 | } -------------------------------------------------------------------------------- /Source/RPG/Game/Abilities/GameAbility.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "Object.h" 5 | #include "../RPGSystem/Abilities/RPGAbilityBase.h" 6 | #include "../Shared/RPGEnums.h" 7 | #include "GameAbility.generated.h" 8 | 9 | UCLASS(BlueprintType, Blueprintable) 10 | class UGameAbility : public URPGAbilityBase 11 | { 12 | GENERATED_UCLASS_BODY() 13 | 14 | virtual void Tick(float DeltaTime) OVERRIDE; 15 | 16 | virtual void InputPressed() OVERRIDE; 17 | virtual void InputReleased() OVERRIDE; 18 | protected: 19 | virtual void Initialize(APawn* owner, AController* instigator) OVERRIDE; 20 | 21 | public: 22 | UPROPERTY(EditAnywhere, Category = "Ability Requierments") 23 | TEnumAsByte RequiredWeapon; 24 | 25 | UPROPERTY(EditAnywhere, Category = "Ability Requierments") 26 | bool CostPerTick; 27 | 28 | public: 29 | 30 | UFUNCTION(BlueprintCallable, Category = "Ability|Helpers") 31 | FHitResult GetHitResult(float Range, FName StartSocke); 32 | 33 | UFUNCTION(BlueprintCallable, Category = "Ability|Helpers") 34 | AActor* GetActorHit(float Range, FName StartSocke); 35 | 36 | UFUNCTION(BlueprintCallable, Category = "Ability|Helpers") 37 | void SpawnTrailEffect(UParticleSystem* trailFX, float trailSpeed, FName trailSpeedParam, FHitResult target, FName SocketName); 38 | 39 | UFUNCTION(BlueprintCallable, Category = "Ability|Data") 40 | void GetTableRow(UDataTable* Data, FName RowID, FAttributeData& OutData); 41 | 42 | protected: 43 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ability|Cost") 44 | float BaseHealthCost; 45 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ability|Cost") 46 | float BaseEnergyCost; 47 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ability|Cost") 48 | float BaseStaminaCost; 49 | 50 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ability|Cost") 51 | float PeriodicBaseHealthCost; 52 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ability|Cost") 53 | float PeriodicBaseEnergyCost; 54 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Ability|Cost") 55 | float PeriodicBaseStaminaCost; 56 | protected: 57 | UPROPERTY(BlueprintReadOnly, Category = "Ability") 58 | TWeakObjectPtr OwnerAttributes; 59 | 60 | //UPROPERTY(BlueprintReadOnly, Category = "Ability") 61 | //TWeakObjectPtr TargetAttributes; 62 | 63 | TWeakObjectPtr EquipComp; 64 | class ARPGWeaponBase* MainHand; 65 | class ARPGWeaponBase* OffHand; 66 | /* 67 | Calculates final cost of ability. 68 | If the final cost if bigger than remainin resource it return false; 69 | If return true, it also subtract cost from character energy pool. 70 | */ 71 | bool CalculateFinalCost(float energyCost, float healthCost, float staminaCost); 72 | UFUNCTION(BlueprintCallable, Category = "Ability|Helpers") 73 | FVector GetCameraAim() const; 74 | 75 | private: 76 | FHitResult RangedPowerTrace(const FVector& StartTrace, const FVector& EndTrace) const; 77 | FVector GetCameraDamageStarLocation(const FVector& AimDir) const; 78 | 79 | USkeletalMeshComponent* GetWeaponMesh() const; 80 | FVector GetCastingLocation(FName SocketName) const; 81 | FVector GetMuzzleDirection(); 82 | void SetTargetAttributes(AActor* targetActor); 83 | }; 84 | -------------------------------------------------------------------------------- /Source/RPG/Game/BlueprintLibrary/DamagefunctionStatics.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "../Components/RPGAttributeBaseComponent.h" 5 | #include "DamagefunctionStatics.h" 6 | 7 | 8 | UDamagefunctionStatics::UDamagefunctionStatics(const class FPostConstructInitializeProperties& PCIP) 9 | : Super(PCIP) 10 | { 11 | 12 | } 13 | 14 | 15 | float UDamagefunctionStatics::SpellDamage(AActor* Target, AActor* Owner, float InputValue) 16 | { 17 | TWeakObjectPtr TargetAttr = Target->FindComponentByClass(); 18 | TWeakObjectPtr OwnerAttr = Owner->FindComponentByClass(); 19 | 20 | if (!OwnerAttr.IsValid() || !TargetAttr.IsValid()) 21 | return 0; 22 | 23 | 24 | /* 25 | This is really simplified. I haven't really thought about any forumlas yet 26 | but you got the idea. Just remember the order in which you perform calculations is crucial. 27 | */ 28 | 29 | InputValue = InputValue + (OwnerAttr->GetIntelligence() / 2); 30 | 31 | //now we can do some defense for example: 32 | 33 | InputValue = InputValue - (TargetAttr->GetIntelligence() / 4); 34 | 35 | return InputValue; 36 | } 37 | 38 | //this is just for checking chaining in blueprint. Have fun! 39 | float UDamagefunctionStatics::FireDamage(AActor* Target, AActor* Owner, float InputValue) 40 | { 41 | TWeakObjectPtr TargetAttr = Target->FindComponentByClass(); 42 | TWeakObjectPtr OwnerAttr = Owner->FindComponentByClass(); 43 | 44 | if (!OwnerAttr.IsValid() || !TargetAttr.IsValid()) 45 | return 0; 46 | InputValue = InputValue + (OwnerAttr->GetIntelligence() / 5); 47 | 48 | return InputValue; 49 | } -------------------------------------------------------------------------------- /Source/RPG/Game/BlueprintLibrary/DamagefunctionStatics.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "../RPGSystem/RPGAttributeBase.h" 5 | #include "DamagefunctionStatics.generated.h" 6 | 7 | /* 8 | Purpose Of this class is very simple. 9 | Add all static damage, healing, whatever calculations here in form of static functions. 10 | So you can have base functions for generic calculation of things like Spell Damage, Fire Damage, 11 | Physical Damage bla bla, you got the idea. 12 | 13 | The impportant part is that functions can be chained togather. So you can create something like 14 | Spell Fire Damage. So you first call function that calculate Spell Damage, and then you plug result 15 | of it to Fire Damage function, and then.. You got the point. 16 | 17 | This is extremly game specific. As each game can have it's own damage calulation formulas. 18 | Never the less coding these functions is very easy, and literally everybody should be able to handle it. 19 | Just open this file, copy existing function, change body of function to make calculations you need, 20 | return result. 21 | 22 | You can also scrap this, and just make static function library purely in blueprint. Up to you. 23 | It's mainly to present idea, of how this can be handled. 24 | */ 25 | /* 26 | AActor* Target - Target of Ability, effect, something, you want to use his attributes in calculations; 27 | AActor* Owner - Who owns/used/caused ability, effect or soemthing, you want to take his his attributes as well. 28 | 29 | For sake of simplicity we will use our customized AttributeComponent, so we don't have 30 | to get attribtues by reflection, we can simply get them by pointer. 31 | 32 | */ 33 | 34 | 35 | UCLASS() 36 | class UDamagefunctionStatics : public UBlueprintFunctionLibrary 37 | { 38 | GENERATED_UCLASS_BODY() 39 | 40 | UFUNCTION(BlueprintPure, Category = "Game|Damage Functions") 41 | static float SpellDamage(AActor* Target, AActor* Owner, float InputValue); 42 | 43 | UFUNCTION(BlueprintPure, Category = "Game|Damage Functions") 44 | static float FireDamage(AActor* Target, AActor* Owner, float InputValue); 45 | }; 46 | -------------------------------------------------------------------------------- /Source/RPG/Game/Components/RPGAttributeBaseComponent.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "RPG.h" 5 | #include "../GameAttributes.h" 6 | #include "RPGAttributeBaseComponent.h" 7 | 8 | URPGAttributeBaseComponent::URPGAttributeBaseComponent(const class FPostConstructInitializeProperties& PCIP) 9 | : Super(PCIP) 10 | { 11 | PrimaryComponentTick.bCanEverTick = true; 12 | bWantsInitializeComponent = true; 13 | 14 | 15 | } 16 | void URPGAttributeBaseComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) 17 | { 18 | Super::TickComponent(DeltaTime, TickType, ThisTickFunction); 19 | 20 | if (CanRegenerateHealth) 21 | { 22 | if (Health < GetMaxHealth()) 23 | { 24 | currentHealthRegenInterval += DeltaTime; 25 | if (currentHealthRegenInterval >= HealthRegenInterval) 26 | { 27 | Health += HealthRegenValue; 28 | currentHealthRegenInterval = 0; 29 | } 30 | } 31 | } 32 | if (CanRegenerateEnergy) 33 | { 34 | if (Energy < GetMaxEnergy()) 35 | { 36 | currentEnergyRegenInterval += DeltaTime; 37 | if (currentHealthRegenInterval >= EnergyRegenInterval) 38 | { 39 | Energy += EnergyRegenValue; 40 | currentEnergyRegenInterval = 0; 41 | } 42 | } 43 | } 44 | if (CanRegenerateStamina) 45 | { 46 | if (Energy < GetMaxStamina()) 47 | { 48 | currentStaminaRegenInterval += DeltaTime; 49 | if (currentStaminaRegenInterval >= StaminaRegenInterval) 50 | { 51 | Stamina += StaminaRegenValue; 52 | currentStaminaRegenInterval = 0; 53 | } 54 | } 55 | } 56 | } 57 | void URPGAttributeBaseComponent::InitializeComponent() 58 | { 59 | Super::InitializeComponent(); 60 | SetConsitutionMod(); 61 | SetIntelligenceMod(); 62 | SetEnduranceMod(); 63 | Health = GetMaxHealth(); 64 | Energy = GetMaxEnergy(); 65 | Stamina = GetMaxStamina(); 66 | } 67 | void URPGAttributeBaseComponent::OnRegister() 68 | { 69 | Super::OnRegister(); 70 | SetConsitutionMod(); 71 | SetIntelligenceMod(); 72 | SetEnduranceMod(); 73 | SetMaxHealth(); 74 | SetMaxEnergy(); 75 | SetMaxStamina(); 76 | //SetSpellCritChance(); 77 | } 78 | void URPGAttributeBaseComponent::PostInitProperties() 79 | { 80 | Super::PostInitProperties(); 81 | } 82 | -------------------------------------------------------------------------------- /Source/RPG/Game/Components/RPGAttributeBaseComponent.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | //#include "RPG.h" 5 | #include "../../RPGSystem/Components/RPGAttributeComponent.h" 6 | #include "RPGAttributeBaseComponent.generated.h" 7 | /* 8 | In derived class we declare all needed attributes. 9 | It would be good idea to group them into Structs later. 10 | It could also be done as seprate object, although this approach is less blueprint friendly. 11 | */ 12 | UENUM() 13 | enum EAttributeNames 14 | { 15 | Health, 16 | Energy, 17 | Stamina 18 | }; 19 | UCLASS(meta = (BlueprintSpawnableComponent), hidecategories = (Object, LOD, Lighting, Transform, Sockets, TextureStreaming)) 20 | class URPGAttributeBaseComponent : public URPGAttributeComponent 21 | { 22 | GENERATED_UCLASS_BODY() 23 | 24 | virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) OVERRIDE; 25 | virtual void InitializeComponent() OVERRIDE; 26 | virtual void OnRegister() OVERRIDE; 27 | virtual void PostInitProperties() OVERRIDE; 28 | protected: 29 | 30 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 31 | float Health; 32 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Derived Attributes") 33 | float MaxHealth; 34 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 35 | float HealthBase; 36 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 37 | float HealthPerAttribute; 38 | 39 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 40 | float Energy; 41 | UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 42 | float MaxEnergy; 43 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 44 | float EnergyBase; 45 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 46 | float EnergyPerAttribute; 47 | 48 | 49 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 50 | float Stamina; 51 | UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 52 | float MaxStamina; 53 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 54 | float StaminaBase; 55 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 56 | float StaminaPerAttribute; 57 | 58 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 59 | float Constitution; 60 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 61 | float ConstitutionMod; 62 | 63 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 64 | float Strenght; 65 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 66 | float StrenghtMod; 67 | 68 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 69 | float Thoughness; 70 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 71 | float ThougnessMod; 72 | 73 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 74 | float Endurance; 75 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 76 | float EnduranceMod; 77 | 78 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 79 | float Intelligence; 80 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 81 | float IntelligenceMod; 82 | 83 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 84 | float WillPower; 85 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 86 | float WillPowerMod; 87 | 88 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 89 | float Magic; 90 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 91 | float MagicMod; 92 | 93 | 94 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Derived Attributes") 95 | float SpellCritChance; 96 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Derived Attributes") 97 | float SpellCritMultiply; 98 | 99 | UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 100 | float CritChance; 101 | UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 102 | float CritMultiply; 103 | 104 | 105 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 106 | bool CanRegenerateHealth; 107 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 108 | float HealthRegenInterval; 109 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 110 | float HealthRegenValue; 111 | 112 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 113 | bool CanRegenerateEnergy; 114 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 115 | float EnergyRegenInterval; 116 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 117 | float EnergyRegenValue; 118 | 119 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 120 | bool CanRegenerateStamina; 121 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 122 | float StaminaRegenInterval; 123 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 124 | float StaminaRegenValue; 125 | 126 | UPROPERTY(BlueprintReadOnly, Category = "Attributes|Weight") 127 | float EquipmentWeight; 128 | 129 | float SpellCastingSpeed; 130 | float SpellBaseCost; 131 | float AbilityWeightCostMod; 132 | 133 | private: 134 | float currentHealthRegenInterval; 135 | float currentEnergyRegenInterval; 136 | float currentStaminaRegenInterval; 137 | float value; 138 | public: 139 | 140 | FORCEINLINE float GetHealth() { return Health; }; 141 | FORCEINLINE void SetHealth(float value) { Health = value; }; 142 | FORCEINLINE void SubtractHealth(float value) { Health -= value; }; 143 | FORCEINLINE float GetMaxHealth() { return MaxHealth; }; 144 | FORCEINLINE void SetMaxHealth() { MaxHealth = HealthBase + (Constitution * HealthPerAttribute); }; 145 | 146 | FORCEINLINE float GetEnergy() { return Energy; }; 147 | FORCEINLINE void SetEnergy(float value) { Energy = value; }; 148 | FORCEINLINE void SubtractEnergy(float value) { Energy -= value; }; 149 | FORCEINLINE float GetMaxEnergy() { return MaxEnergy; }; 150 | FORCEINLINE void SetMaxEnergy() { MaxEnergy = EnergyBase + (IntelligenceMod * EnergyPerAttribute); }; 151 | 152 | FORCEINLINE float GetStamina() { return Stamina; }; 153 | FORCEINLINE void SubtractStamina(float value) { Stamina -= value; }; 154 | FORCEINLINE float GetMaxStamina() { return MaxStamina; }; 155 | FORCEINLINE void SetMaxStamina() { MaxStamina = StaminaBase + (EnduranceMod * StaminaPerAttribute); }; 156 | 157 | 158 | FORCEINLINE float GetConstitution() { return Constitution; }; 159 | FORCEINLINE void SetConstitution(float value) { Constitution = value; }; 160 | FORCEINLINE void SubtractConstitution(float value) { Constitution -= value; }; 161 | FORCEINLINE void AddConstitution(float value) { Constitution += value; }; 162 | FORCEINLINE void SetConsitutionMod() { ConstitutionMod = (Constitution - 10) / 2; }; 163 | FORCEINLINE float GetConsitutionMod() { return ConstitutionMod; }; 164 | 165 | 166 | FORCEINLINE float GetIntelligence() { return Intelligence; }; 167 | FORCEINLINE void SetIntelligenceMod(){ IntelligenceMod = (Intelligence - 10) / 2; }; 168 | FORCEINLINE float GetIntelligenceMod(){ return IntelligenceMod; }; 169 | 170 | FORCEINLINE void SetEnduranceMod(){ EnduranceMod = (Endurance - 10) / 2; }; 171 | FORCEINLINE float GetEnduranceMod(){ return EnduranceMod; }; 172 | 173 | FORCEINLINE bool SpellCritted() { 174 | float rngNum = FMath::FRandRange(1, 100); 175 | /* 176 | */ 177 | if (SpellCritChance >= rngNum) 178 | return true; 179 | return false; 180 | } 181 | //this is dumb implementation we need to account for other attributes like SpellCritChance as well ;) 182 | FORCEINLINE void SetSpellCritChance() { SpellCritChance = IntelligenceMod * 2; }; 183 | }; 184 | 185 | /* 186 | this is pseudocode for calculating spellDamage; 187 | DamageType_Spell(AttributeComponent* attribute, Blueprint) 188 | { 189 | //order in which calculations are made is crucial! 190 | 191 | int32 finalDamage = Blueprint * attribute->SpellDamage; 192 | if(rand() < attribute->CritChange) 193 | { 194 | finalDamage *= CritMultiply; 195 | } 196 | 197 | //SpellProtection: 198 | finalDamage = finalDamage - (finalDamage * SpellProtection(0-1)); 199 | 200 | //armorProtection 201 | finalDamage = finalDamage - armor; 202 | 203 | attribute->Health -= finalDamage; 204 | } 205 | */ -------------------------------------------------------------------------------- /Source/RPG/Game/Components/RPGEquipmentManagerComponent.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "../RPGCharacter.h" 5 | #include "../Components/RPGAttributeBaseComponent.h" 6 | #include "RPGEquipmentManagerComponent.h" 7 | 8 | 9 | 10 | URPGEquipmentManagerComponent::URPGEquipmentManagerComponent(const class FPostConstructInitializeProperties& PCIP) 11 | : Super(PCIP) 12 | { 13 | 14 | } 15 | 16 | void URPGEquipmentManagerComponent::OnComponentCreated() 17 | { 18 | Super::OnComponentCreated(); 19 | EquipmentOwner = GetOwner(); 20 | 21 | if (EquipmentOwner) 22 | { 23 | TArray attributeComps; 24 | EquipmentOwner->GetComponents(attributeComps); 25 | for (URPGAttributeBaseComponent* attrComp : attributeComps) 26 | { 27 | attributeComp = attrComp; 28 | break; 29 | } 30 | 31 | TArray skeletalMeshComps; 32 | EquipmentOwner->GetComponents(skeletalMeshComps); 33 | for (USkeletalMeshComponent* skelComp : skeletalMeshComps) 34 | { 35 | if (skelComp->GetName() == "ChestMesh") 36 | { 37 | ChestSlotComp = skelComp; 38 | } 39 | if (skelComp->GetName() == "FootMesh") 40 | { 41 | FootSlotComp = skelComp; 42 | } 43 | if (skelComp->GetName() == "HeadMesh") 44 | { 45 | HeadSlotComp = skelComp; 46 | } 47 | } 48 | } 49 | } 50 | 51 | void URPGEquipmentManagerComponent::InitializeComponent() 52 | { 53 | Super::InitializeComponent(); 54 | EquipmentOwner = GetOwner(); 55 | } 56 | void URPGEquipmentManagerComponent::SetCharacterStats(ARPGItem* item) 57 | { 58 | if (item && attributeComp) 59 | { 60 | if(EquipedItems.Num() > 0) 61 | { 62 | if(item->Constitution != 0) //add checks for the rest of the stats. 63 | { 64 | EquipedItems.Sort(URPGEquipmentManagerComponent::ConstPredicate); //sort array so the item with highest stat currently equiped is first 65 | 66 | if(item->Constitution > EquipedItems[0]->Constitution) 67 | { 68 | //attributeComp->SubtractConstitution(EquipedItems[0]->Constitution); 69 | //attributeComp->AddConstitution(item->Constitution); 70 | } 71 | } 72 | } 73 | else if (EquipedItems.Num() == 0) 74 | { 75 | if(item->Constitution != 0) 76 | { 77 | //attributeComp->AddConstitution(item->Constitution); 78 | } 79 | } 80 | } 81 | } 82 | 83 | void URPGEquipmentManagerComponent::EquipChestItem(ARPGItem* item) 84 | { 85 | if (item && ChestSlotComp) 86 | { 87 | if(item->ItemType == EItemType::Item_Chest) //make sure item is of right type. Just in case. Could be removed later as this check is redundant 88 | { 89 | if(!ChestSlot) //check if something is equiped in target slot 90 | { 91 | if(EquipedItems.Num() == 0) //if there is no item equiped 92 | { 93 | //we can just assign stats from item to the character 94 | SetCharacterStats(item); 95 | ChestSlot = item; //the assign item to the slot 96 | ChestSlotComp->SetSkeletalMesh(item->ChestMesh); 97 | EquipedItems.AddUnique(ChestSlot); //and add to array 98 | return; 99 | } 100 | else //otherwise 101 | { 102 | SetCharacterStats(item); //we check if the current item have higher stat that current equiped 103 | ChestSlot = item; //we just assign our item to the slot 104 | ChestSlotComp->SetSkeletalMesh(item->ChestMesh); 105 | EquipedItems.AddUnique(ChestSlot); //and add to array 106 | } 107 | } 108 | else //something is equiped in chest slot! 109 | { 110 | if(EquipedItems.Num() > 0) //so we assume that array contain more than 0 elements 111 | { 112 | SetCharacterStats(item); //check if the current item have better stat than old ones 113 | EquipedItems.RemoveSingle(ChestSlot); //remove our old item from array 114 | ChestSlot = item; //asign new item 115 | ChestSlotComp->SetSkeletalMesh(item->ChestMesh); 116 | EquipedItems.AddUnique(ChestSlot); //and add it to array 117 | } 118 | } 119 | } 120 | } 121 | } 122 | 123 | void URPGEquipmentManagerComponent::EquipFootItem(ARPGItem* item) 124 | { 125 | if (item && FootSlotComp) 126 | { 127 | if(item->ItemType == EItemType::Item_Foot) //make sure item is of right type. Just in case. Could be removed later as this check is redundant 128 | { 129 | if(!FootSlot) //check if something is equiped in target slot 130 | { 131 | if(EquipedItems.Num() == 0) //if there is no item equiped 132 | { 133 | //we can just assign stats from item to the character 134 | SetCharacterStats(item); 135 | FootSlot = item; //the assign item to the slot 136 | EquipedItems.AddUnique(FootSlot); //and add to array 137 | return; 138 | } 139 | else //otherwise 140 | { 141 | SetCharacterStats(item); //we check if the current item have higher stat that current equiped 142 | FootSlot = item; //we just assign our item to the slot 143 | EquipedItems.AddUnique(FootSlot); //and add to array 144 | } 145 | } 146 | else //something is equiped in chest slot! 147 | { 148 | if(EquipedItems.Num() > 0) //so we assume that array contain more than 0 elements 149 | { 150 | SetCharacterStats(item); //check if the current item have better stat than old ones 151 | EquipedItems.RemoveSingle(FootSlot); //remove our old item from array 152 | FootSlot = item; //asign new item 153 | EquipedItems.AddUnique(FootSlot); //and add it to array 154 | } 155 | } 156 | } 157 | } 158 | } 159 | 160 | void URPGEquipmentManagerComponent::EquipItem(TSubclassOf item) 161 | { 162 | if(item) 163 | { 164 | FActorSpawnParameters SpawnInfo; 165 | SpawnInfo.bNoCollisionFail = true; 166 | ARPGItem* itemBase = GetWorld()->SpawnActor(item, SpawnInfo); 167 | itemBase->ItemOwner = NULL; //we assign current character as owner to item, it might be better to use GetOwner()! as item is either eequiped on character or not. 168 | itemBase->InitializeItem(); 169 | 170 | //note this currently assume that stats NEVER stack 171 | //actualy negative with positive stats could stack. If there +9 con and -3 con, the end result stat will be +6 con; 172 | //note add UnEquipItem method to handle stat subtraction! 173 | if(itemBase->ItemType == EItemType::Item_Chest) 174 | { 175 | EquipChestItem(itemBase); 176 | } 177 | if(itemBase->ItemType == EItemType::Item_Foot) 178 | { 179 | EquipFootItem(itemBase); 180 | } 181 | } 182 | } 183 | 184 | void URPGEquipmentManagerComponent::UnEquipItem(ARPGItem* item) 185 | { 186 | if (item && attributeComp) 187 | { 188 | if(item->Constitution != 0) 189 | { 190 | //attributeComp->SubtractConstitution(item->Constitution); 191 | if(EquipedItems.Num() > 0) 192 | { 193 | for(ARPGItem* itemInArray : EquipedItems) 194 | { 195 | 196 | } 197 | } 198 | } 199 | EquipedItems.RemoveSingle(item); 200 | } 201 | } 202 | 203 | void URPGEquipmentManagerComponent::EquipWeapon(TSubclassOf weapon, FName SocketName, TEnumAsByte itemSlot) 204 | { 205 | if(weapon) 206 | { 207 | FActorSpawnParameters SpawnInfo; 208 | SpawnInfo.bNoCollisionFail = true; 209 | ARPGWeaponBase* weaponBase = GetWorld()->SpawnActor(weapon, SpawnInfo); 210 | MainWeapon = weaponBase; 211 | switch (itemSlot) 212 | { 213 | case EItemSlot::ChestSlot: 214 | { 215 | //USkeletalMeshComponent* PawnMesh = characterToAttach->Mesh; 216 | USkeletalMeshComponent* weaponMesh = MainWeapon->WeaponMesh; 217 | // USkeletalMesh* weaponMesh = MainWeapon->WeaponMesh; 218 | //characterToAttach->SomeMesh->SetSkeletalMesh(weaponMesh); 219 | weaponMesh->AttachTo(ChestSlotComp, SocketName); 220 | weaponMesh->SetHiddenInGame(false); 221 | break; 222 | } 223 | case EItemSlot::HeadSlot: 224 | { 225 | //USkeletalMeshComponent* PawnMesh = characterToAttach->Mesh; 226 | USkeletalMeshComponent* weaponMesh = MainWeapon->WeaponMesh; 227 | // USkeletalMesh* weaponMesh = MainWeapon->WeaponMesh; 228 | //characterToAttach->SomeMesh->SetSkeletalMesh(weaponMesh); 229 | weaponMesh->AttachTo(HeadSlotComp, SocketName); 230 | weaponMesh->SetHiddenInGame(false); 231 | break; 232 | } 233 | default: 234 | break; 235 | } 236 | 237 | 238 | } 239 | } 240 | 241 | -------------------------------------------------------------------------------- /Source/RPG/Game/Components/RPGEquipmentManagerComponent.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | //#include "RPG.h" 5 | //#include "../RPGCharacter.h" 6 | #include "../Items/RPGWeaponBase.h" 7 | #include "../Items/RPGItem.h" 8 | #include "RPGEquipmentManagerComponent.generated.h" 9 | 10 | UENUM() 11 | enum EItemSlot 12 | { 13 | ChestSlot, 14 | HeadSlot, 15 | LegSlot, 16 | FootSlot, 17 | HandSlot, 18 | ShoulderSlot 19 | }; 20 | 21 | /** 22 | * 23 | */ 24 | UCLASS() 25 | class URPGEquipmentManagerComponent : public UActorComponent 26 | { 27 | GENERATED_UCLASS_BODY() 28 | 29 | public: 30 | 31 | virtual void OnComponentCreated() OVERRIDE; 32 | 33 | virtual void InitializeComponent() OVERRIDE; 34 | 35 | UPROPERTY() 36 | class ARPGWeaponBase* MainWeapon; 37 | UPROPERTY() 38 | class ARPGWeaponBase* OffHandWeapon; 39 | 40 | /* 41 | Secondary set for equiped weapons. 42 | Weapon in this set are, not technically equiped, so they can't be used. 43 | But they are stored here, for quick switching between various sets. 44 | */ 45 | UPROPERTY() 46 | ARPGWeaponBase* MainWeaponSet2; 47 | UPROPERTY() 48 | ARPGWeaponBase* OffHandWeaponSet2; 49 | 50 | UPROPERTY() 51 | ARPGItem* ChestSlot; 52 | 53 | UPROPERTY() 54 | ARPGItem* HeadSlot; 55 | 56 | UPROPERTY() 57 | ARPGItem* LegSlot; 58 | 59 | UPROPERTY() 60 | ARPGItem* FootSlot; 61 | 62 | UPROPERTY() 63 | ARPGItem* HandsSlot; 64 | 65 | UPROPERTY() 66 | ARPGItem* ShouldersSlot; 67 | 68 | 69 | 70 | UPROPERTY() 71 | TArray EquipedItems; 72 | 73 | UFUNCTION(BlueprintCallable, Category=CharacterEquipment) 74 | void EquipItem(TSubclassOf item); 75 | 76 | UFUNCTION(BlueprintCallable, Category=CharacterEquipment) 77 | void UnEquipItem(ARPGItem* item); 78 | 79 | UFUNCTION(BlueprintCallable, Category=CharacterEquipment) 80 | void EquipWeapon(TSubclassOf weapon, FName SocketName, TEnumAsByte itemSlot); 81 | 82 | private: 83 | void SetCharacterStats(ARPGItem* item); 84 | void EquipChestItem(ARPGItem* item); 85 | void EquipFootItem(ARPGItem* item); 86 | 87 | uint8 EquipedItemsCount; 88 | AActor* EquipmentOwner; 89 | 90 | class URPGAttributeBaseComponent* attributeComp; 91 | class USkeletalMeshComponent* ChestSlotComp; 92 | class USkeletalMeshComponent* FootSlotComp; 93 | class USkeletalMeshComponent* HeadSlotComp; 94 | inline static bool ConstPredicate (const ARPGItem& ip1, const ARPGItem& ip2) 95 | { 96 | return (ip1.Constitution > ip2.Constitution); 97 | } 98 | }; 99 | 100 | struct FConstitutionPredicate 101 | { 102 | inline bool operator() (ARPGItem& ip1, ARPGItem& ip2) 103 | { 104 | return (ip1.Constitution < ip2.Constitution); 105 | } 106 | }; -------------------------------------------------------------------------------- /Source/RPG/Game/DamageTypes/RPGDamageHealth.cpp: -------------------------------------------------------------------------------- 1 | #include "RPG.h" 2 | #include "../RPGCharacter.h" 3 | #include "../Components/RPGAttributeBaseComponent.h" 4 | #include "RPGDamageHealth.h" 5 | 6 | URPGDamageHealth::URPGDamageHealth(const class FPostConstructInitializeProperties& PCIP) 7 | : Super(PCIP) 8 | { 9 | } 10 | 11 | float URPGDamageHealth::DealDamage(ARPGCharacter* causer, float damageAmount) 12 | { 13 | if(DamageTarget) 14 | { 15 | /* 16 | so final equation should look differently. 17 | first we should calculate damage, by using any modifiers to the damageAmount input, we see fit. 18 | and then subtract health from character (or anything else for that matter) 19 | */ 20 | //if (DamageCauser->SpellCritted()) 21 | //{ 22 | // DamageTarget->SubtractHealth(damageAmount*2); 23 | // return 0; 24 | //} 25 | //DamageTarget->SubtractHealth(damageAmount); 26 | /* 27 | this is very ugly hack, so we can pass how much damage we have dealth to target back to the caster. 28 | It should be moved into data structure. Possibily accessed trough getter/setter 29 | but for now it should work. 30 | */ 31 | //causer->DamageCaused = damage; 32 | /* 33 | We could also use data structure to pass to causer, health of target, to display on UI. It should be probably Array of simple data struct. 34 | */ 35 | return damageAmount; 36 | } 37 | return 0; 38 | } 39 | 40 | /* 41 | this is pseudocode for calculating spellDamage; 42 | DamageType_Spell(AttributeComponent* attribute, Blueprint) 43 | { 44 | //order in which calculations are made is crucial! 45 | 46 | int32 finalDamage = Blueprint * attribute->SpellDamage; 47 | if(rand() < attribute->CritChange) 48 | { 49 | finalDamage *= CritMultiply; 50 | } 51 | 52 | //SpellProtection: 53 | finalDamage = finalDamage - (finalDamage * SpellProtection(0-1)); 54 | 55 | //armorProtection 56 | finalDamage = finalDamage - armor; 57 | 58 | attribute->Health -= finalDamage; 59 | } 60 | */ -------------------------------------------------------------------------------- /Source/RPG/Game/DamageTypes/RPGDamageHealth.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "RPGDamageType.h" 3 | #include "RPGDamageHealth.generated.h" 4 | 5 | UCLASS(MinimalAPI, const, Blueprintable, BlueprintType) 6 | class URPGDamageHealth : public URPGDamageType 7 | { 8 | GENERATED_UCLASS_BODY() 9 | 10 | 11 | virtual float DealDamage(class ARPGCharacter* causer, float damageAmount) OVERRIDE; 12 | }; -------------------------------------------------------------------------------- /Source/RPG/Game/DamageTypes/RPGDamageType.cpp: -------------------------------------------------------------------------------- 1 | #include "RPG.h" 2 | #include "../Components/RPGAttributeBaseComponent.h" 3 | #include "RPGDamageType.h" 4 | 5 | URPGDamageType::URPGDamageType(const class FPostConstructInitializeProperties& PCIP) 6 | : Super(PCIP) 7 | { 8 | } 9 | 10 | float URPGDamageType::DealDamage(ARPGCharacter* causer, float damageAmount) 11 | { 12 | return 0; 13 | } -------------------------------------------------------------------------------- /Source/RPG/Game/DamageTypes/RPGDamageType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "RPGDamageType.generated.h" 3 | /** 4 | Why bother with implementing damage types ? Game can perfectly work without them, here are my reason s why I decided to use them: 5 | 1. There are many system already implemented that handle damage dealing directly in engine. Various events, that take place when 6 | actor is hit and take damage. It's possible to recreate these systems, but why invent whell from scratch again ? 7 | 2. Damage doesn't mean, it hurt actor health. Damage mean everything that takes place in actor TakeDamage(). 8 | TakeDamage() on it's own is pretty limited, as it can take only single float value (for damage), and by extension can damage only 9 | single character property 10 | 3. To mitigate this limitation I decided to use damage type. Each damage type implement it's own damage dealing method. 11 | This method MUST be overrided in all class derived from URPGDamageType, as default implementation is not provided (and should not 12 | be provided!) 13 | 4. The amount of final damage that actor (character) will take is determined in two stages. 14 | 4a. In blueprint, there is set per-power forumla, that will calculate ability/power damage. For example magic*5 + int. 15 | 4b. In damage type we will calculate rest of affecting properties. Like resistance value, bonus damage 16 | by target of appiled by caster), armor reduction etc. 17 | 4c. It is entirely possible to make part b in blueprint. But it will introduce another complexity that will need to be taken care of, 18 | and more oppurtinties to make mistakes. You can forgot to add nessesary mechanics to ability. Although it's viable 19 | to make specific cases when blueprint will handle entire logic. 20 | 4d. It's also worth noting that system should be able to response for real-time changes. For example presitent effects can modify 21 | outgoing damage or damage taken, by flat values (+20, -10) or by precentage. 22 | All of these effects are stored within data structures (structs) in Common/RPGCharacterStructs.h (might change!). 23 | All character should have these included. These structs provide all possible modifications that can be run. 24 | Damage calculations should be constructed in the way, that they can take care of 0 values in these structs. 25 | 26 | Please note it is unrealistic that damage type will predict what data will be. It will work only on data that was passed on it 27 | during calling DealDamage()!. To specific data, that is hold in memorry for affected actor in specific struct. There will be small delays in calling code. It shouldn't be big issue, 28 | but if 0.1-1ms delay is issue, you should consider creating some kind queue and buffer mechanism, that will make sure 29 | that right data will be passed to function. 30 | 31 | To make example: 32 | Target character have temporary debuff that will increase incoming magical damage by 30%, it lasts for 15s. How do we handle it ? 33 | And have 30% resitance (reduction) to magic damage. 34 | For example Magic Missle do 10 base damage. 35 | Here is example formula 36 | FinalDamage = (10 * 0.3) + 10 = 13 37 | FinalDamage = 13 - (13 *0.3) = 9.1 38 | So character will take 9.1 dmage. 39 | It's important to be consistent and/or implement different cases. For example one might first apply damage reduction from target 40 | and then apply bonus damage to get final result. 41 | Although most player will expect shown above behavior as more logical. 42 | 43 | DamageTypes are also used to apply damage to attributes. Like magic, intelligence, strenght constitiun. Can be used 44 | reduce character movment speed etc. It is all done with combination of data structs and implementing DealDamage function. 45 | 46 | */ 47 | UCLASS(MinimalAPI, const, Blueprintable, BlueprintType) 48 | class URPGDamageType : public UDamageType 49 | { 50 | GENERATED_UCLASS_BODY() 51 | 52 | UFUNCTION() 53 | virtual float DealDamage(class ARPGCharacter* causer, float damageAmount); 54 | 55 | FORCEINLINE void SetDamageTarget(URPGAttributeBaseComponent* target) { DamageTarget = target; }; 56 | FORCEINLINE void SetDamageCauser(URPGAttributeBaseComponent* causer) { DamageCauser = causer; }; 57 | 58 | UPROPERTY(EditAnywhere, BlueprintReadWrite, EditInline, Category = "Lol") 59 | float BaseDamage; 60 | protected: 61 | class URPGAttributeBaseComponent* DamageTarget; 62 | class URPGAttributeBaseComponent* DamageCauser; 63 | }; -------------------------------------------------------------------------------- /Source/RPG/Game/Effects/EffectActors/RPGProjectileSpawner.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "../../RPGProjectile.h" 5 | #include "RPGProjectileSpawner.h" 6 | 7 | 8 | ARPGProjectileSpawner::ARPGProjectileSpawner(const class FPostConstructInitializeProperties& PCIP) 9 | : Super(PCIP) 10 | { 11 | PrimaryActorTick.bCanEverTick = true; 12 | } 13 | 14 | void ARPGProjectileSpawner::Tick(float DeltaTime) 15 | { 16 | Super::Tick(DeltaTime); 17 | } 18 | 19 | void ARPGProjectileSpawner::OnConstruction(const FTransform& Transform) 20 | { 21 | Super::OnConstruction(Transform); 22 | OnSpawned(); 23 | } 24 | 25 | void ARPGProjectileSpawner::SpawnProjectile() 26 | { 27 | FVector currentLocation = GetActorLocation(); 28 | DrawDebugSphere(GetWorld(), currentLocation, Radius, 32, FColor::Yellow, false, 10.0f); 29 | if (Projectile) 30 | { 31 | 32 | FVector ImpactVector = FVector::ZeroVector; 33 | FVector StartVector; 34 | 35 | //StartVector.Z = Impact.ImpactPoint.Z + StartHeight; 36 | //StartVector.X = Impact.ImpactPoint.X; 37 | //StartVector.Y = Impact.ImpactPoint.Y; 38 | float x = FMath::RandRange((-1) * Radius, Radius); 39 | float y = FMath::RandRange((-1) * Radius, Radius); 40 | currentLocation.X = FMath::Clamp(currentLocation.X + x, (currentLocation.X - Radius - 50), (currentLocation.X + Radius + 50)); 41 | currentLocation.Y = FMath::Clamp(currentLocation.Y + y, (currentLocation.Y - Radius - 50), (currentLocation.Y + Radius + 50)); 42 | //ImpactVector = Impact.ImpactPoint; 43 | //ImpactVector.Z = Impact.ImpactPoint.Z + StartHeight; 44 | //ImpactVector.X = FMath::Clamp(Impact.ImpactPoint.X + FMath::RandRange((-1) * Radius, Radius), (Impact.ImpactPoint.X - Radius), (Impact.ImpactPoint.X + Radius)); 45 | //ImpactVector.Y = FMath::Clamp(Impact.ImpactPoint.Y + FMath::RandRange((-1) * Radius, Radius), (Impact.ImpactPoint.Y - Radius), (Impact.ImpactPoint.Y + Radius)); 46 | //ImpactVector = ImpactVector + FVector(0, 0, -3000); 47 | //FVector EndTrace = ImpactVector*1000; 48 | FVector AdjustedDir = (ImpactVector - StartVector).SafeNormal(); 49 | DrawDebugLine(GetWorld(), currentLocation, ImpactVector, FColor::Blue, false, 10.0f, 0.0f, 2.0f); 50 | //Impact.ImpactPoint.Y = Impact.ImpactPoint.Y + 500.0f; 51 | //Impact.ImpactPoint.X = Impact.ImpactPoint.X + 500.0f; 52 | //FHitResult ProperHit = RangedPowerTrace(StartVector, ImpactVector); 53 | 54 | //DrawDebugLine(GetWorld(), StartVector, ProperHit.ImpactPoint, FColor::Green, false, 10.0f, 0.0f, 2.0f); 55 | FTransform SpawnTM(FRotator(0, 0, 0), StartVector); 56 | //FTransform SpawnTM(ProperHit.ImpactPoint.Rotation(), StartVector); 57 | ARPGProjectile* proj = Cast(UGameplayStatics::BeginSpawningActorFromClass(this, Projectile, SpawnTM)); 58 | if (proj) 59 | { 60 | //proj->Instigator = PowerOwner; 61 | //proj->SetOwner(PowerOwner); 62 | //ProperHit.ImpactPoint; 63 | //ImpactVector.Z = ImpactVector.Z * (-1); 64 | //FVector AdjustedDir = (ProperHit.ImpactPoint - StartVector).SafeNormal(); 65 | //ProperHit.ImpactNormal = ProperHit.ImpactNormal * (-1); 66 | 67 | //proj->InitVelocity(ProperHit.ImpactNormal); 68 | //DrawDebugSphere(GetWorld(), StartVector, proj->CollisionSphereRadius, 32, FColor::Red, false, 10.0f); 69 | UGameplayStatics::FinishSpawningActor(proj, SpawnTM); 70 | } 71 | } 72 | } 73 | 74 | void ARPGProjectileSpawner::SetSpawnLocation(FVector location) 75 | { 76 | SpawnLocation = location; 77 | } -------------------------------------------------------------------------------- /Source/RPG/Game/Effects/EffectActors/RPGProjectileSpawner.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "GameFramework/Actor.h" 6 | #include "../RPGEffectActor.h" 7 | #include "RPGProjectileSpawner.generated.h" 8 | 9 | /** 10 | * Base class for presitent actor effect, 11 | * Actor effect is usually spawned by power (or other effect) 12 | * Actor effect can presist set amount of time or idefinetly (until destruction by other actors) 13 | * Actor effect might have health. 14 | * actor effect is always spawned on level with static mesh or with other indicator that 15 | * it is in place. 16 | * Effect Actor might have component, that will add combo field. 17 | * combo field is special componenent with it's own collision channel (overlap). 18 | * when two combo componenets overlap, they remove both effects and spawn new one 19 | * which is defined by designer 20 | * There are special cases that do not remove combo field, but instead transfer it effect further 21 | * (like projectile, whirlwind or wind). 22 | */ 23 | /* 24 | * key difference between Object Effect and Actor Effect is 25 | * that actor exisits completly on it's own, and doesn't need to be attached 26 | * to other actor. 27 | * it can interact with any other actor, using all available unreal systems. 28 | */ 29 | 30 | UCLASS() 31 | class ARPGProjectileSpawner : public ARPGEffectActor 32 | { 33 | GENERATED_UCLASS_BODY() 34 | 35 | UPROPERTY(EditAnywhere, Category = BasicProperties) 36 | float Radius; 37 | 38 | UPROPERTY(EditAnywhere, Category = Projectile) 39 | TSubclassOf Projectile; 40 | 41 | //how much time passes between projectile spawns. 42 | UPROPERTY(EditAnywhere, Category = BasicProperties) 43 | float TimeInterval; 44 | 45 | void Tick(float DeltaTime) OVERRIDE; 46 | 47 | UFUNCTION(BlueprintCallable, Category = ProjectileSpanwer) 48 | void SpawnProjectile(); 49 | 50 | void OnConstruction(const FTransform& Transform) OVERRIDE; 51 | 52 | UFUNCTION(BlueprintImplementableEvent, Category = Events) 53 | void OnSpawned(); 54 | 55 | FVector SpawnLocation; 56 | 57 | void SetSpawnLocation(FVector location); 58 | }; 59 | -------------------------------------------------------------------------------- /Source/RPG/Game/Effects/GameEffect.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | #include "RPG.h" 4 | #include "../Components/RPGAttributeBaseComponent.h" 5 | #include "GameEffect.h" 6 | 7 | 8 | UGameEffect::UGameEffect(const class FPostConstructInitializeProperties& PCIP) 9 | : Super(PCIP) 10 | { 11 | 12 | 13 | } 14 | 15 | void UGameEffect::PreInitialize() 16 | { 17 | switch (EffectType) 18 | { 19 | case EEffectType::Hex: 20 | OwnedTags.AddTag("Hex"); 21 | default: 22 | break; 23 | } 24 | } 25 | bool UGameEffect::Initialize() 26 | { 27 | return Super::Initialize(); 28 | //IsEffectActive = false; 29 | //if (Target) 30 | //{ 31 | // if (GetWorld()) 32 | // { 33 | // TArray attributeComps; 34 | // Target->GetComponents(attributeComps); 35 | // for (URPGAttributeBaseComponent* attrComp : attributeComps) 36 | // { 37 | // TargetAttributes = attrComp; 38 | // break; 39 | // } 40 | // TArray causedByAttributeComps; 41 | // CausedBy->GetComponents(causedByAttributeComps); 42 | // for (URPGAttributeBaseComponent* attrComp : causedByAttributeComps) 43 | // { 44 | // CauserAttributes = attrComp; 45 | // break; 46 | // } 47 | // if (TargetAttributes) 48 | // { 49 | // OnEffectAppiled(); 50 | // IsEffectActive = true; 51 | // return true; 52 | // } 53 | // return false; 54 | // } 55 | // return false; 56 | //} 57 | //return false; 58 | } 59 | 60 | void UGameEffect::SetTargetAttributeUpdate() 61 | { 62 | //TargetHealth = TargetAttributes->GetHealth(); 63 | //TargetEnergy = TargetAttributes->GetEnergy(); 64 | //TargetStamina = TargetAttributes->GetStamina(); 65 | } -------------------------------------------------------------------------------- /Source/RPG/Game/Effects/GameEffect.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "Object.h" 5 | #include "Tickable.h" 6 | #include "../../RPGSystem/Effects/RPGEffectBase.h" 7 | #include "../Shared/RPGEnums.h" 8 | #include "GameEffect.generated.h" 9 | 10 | UCLASS(Blueprintable, BlueprintType) 11 | class UGameEffect : public URPGEffectBase 12 | { 13 | GENERATED_UCLASS_BODY() 14 | 15 | virtual void PreInitialize() OVERRIDE; 16 | virtual bool Initialize() OVERRIDE; 17 | 18 | UPROPERTY(EditAnywhere, Category = "Effect Type") 19 | TEnumAsByte EffectType; 20 | 21 | protected: 22 | 23 | UPROPERTY(BlueprintReadOnly, Category = "Effect|Target|Attributes") 24 | float TargetHealth; 25 | UPROPERTY(BlueprintReadOnly, Category = "Effect|Target|Attributes") 26 | float TargetEnergy; 27 | UPROPERTY(BlueprintReadOnly, Category = "Effect|Target|Attributes") 28 | float TargetStamina; 29 | 30 | private: 31 | void SetTargetAttributeUpdate(); 32 | }; 33 | -------------------------------------------------------------------------------- /Source/RPG/Game/Effects/RPGEffectActor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "RPGEffectActor.h" 5 | 6 | 7 | ARPGEffectActor::ARPGEffectActor(const class FPostConstructInitializeProperties& PCIP) 8 | : Super(PCIP) 9 | { 10 | 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /Source/RPG/Game/Effects/RPGEffectActor.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "GameFramework/Actor.h" 6 | #include "RPGEffectActor.generated.h" 7 | 8 | /** 9 | * Base class for presitent actor effect, 10 | * Actor effect is usually spawned by power (or other effect) 11 | * Actor effect can presist set amount of time or idefinetly (until destruction by other actors) 12 | * Actor effect might have health. 13 | * actor effect is always spawned on level with static mesh or with other indicator that 14 | * it is in place. 15 | * Effect Actor might have component, that will add combo field. 16 | * combo field is special componenent with it's own collision channel (overlap). 17 | * when two combo componenets overlap, they remove both effects and spawn new one 18 | * which is defined by designer 19 | * There are special cases that do not remove combo field, but instead transfer it effect further 20 | * (like projectile, whirlwind or wind). 21 | */ 22 | /* 23 | * key difference between Object Effect and Actor Effect is 24 | * that actor exisits completly on it's own, and doesn't need to be attached 25 | * to other actor. 26 | * it can interact with any other actor, using all available unreal systems. 27 | */ 28 | UENUM() 29 | enum EComboType 30 | { 31 | Fire, 32 | Oil 33 | }; 34 | 35 | UCLASS() 36 | class ARPGEffectActor : public AActor 37 | { 38 | GENERATED_UCLASS_BODY() 39 | /** 40 | * 1. if(ObjectType == ComboEffector) 41 | * 2. if(ObjectType == ComboField) 42 | * 3. create Event OnComboCreated 43 | * 4. Send both types trough event delegate. 44 | */ 45 | 46 | /* 47 | Is effect combo field. 48 | */ 49 | UPROPERTY(EditAnywhere, Category = BaseProperties) 50 | bool IsComboField; 51 | 52 | UPROPERTY(EditAnywhere, Category = BaseProperties) 53 | TEnumAsByte ComboFieldType; 54 | 55 | //void OnComboTriggered() 56 | 57 | //void SelfDestroy() 58 | 59 | //void SpawnComboEffect() 60 | }; 61 | -------------------------------------------------------------------------------- /Source/RPG/Game/GameAttributes.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "GameAttributes.h" 5 | 6 | 7 | UGameAttributes::UGameAttributes(const class FPostConstructInitializeProperties& PCIP) 8 | : Super(PCIP) 9 | { 10 | 11 | } 12 | 13 | 14 | -------------------------------------------------------------------------------- /Source/RPG/Game/GameAttributes.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "../RPGSystem/RPGAttributeBase.h" 5 | #include "GameAttributes.generated.h" 6 | 7 | 8 | UCLASS() 9 | class UGameAttributes : public URPGAttributeBase 10 | { 11 | GENERATED_UCLASS_BODY() 12 | 13 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "OMFG") 14 | //float ZajeKurwenFaktenStycznie; 15 | 16 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, EditInline, Category = "Derived Attributes") 17 | //float Health; 18 | //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Derived Attributes") 19 | // float MaxHealth; 20 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 21 | // float HealthBase; 22 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 23 | // float HealthPerAttribute; 24 | 25 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, EditInline, Category = "Derived Attributes") 26 | // float Energy; 27 | //UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 28 | // float MaxEnergy; 29 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 30 | // float EnergyBase; 31 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 32 | // float EnergyPerAttribute; 33 | 34 | 35 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, EditInline, Category = "Derived Attributes") 36 | // float Stamina; 37 | //UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 38 | // float MaxStamina; 39 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 40 | // float StaminaBase; 41 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 42 | // float StaminaPerAttribute; 43 | 44 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 45 | // float Constitution; 46 | //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 47 | // float ConstitutionMod; 48 | 49 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 50 | // float Strenght; 51 | //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 52 | // float StrenghtMod; 53 | 54 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 55 | // float Thoughness; 56 | //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 57 | // float ThougnessMod; 58 | 59 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 60 | // float Endurance; 61 | //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 62 | // float EnduranceMod; 63 | 64 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 65 | // float Intelligence; 66 | //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 67 | // float IntelligenceMod; 68 | 69 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 70 | // float WillPower; 71 | //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 72 | // float WillPowerMod; 73 | 74 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 75 | // float Magic; 76 | //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Base Attributes") 77 | // float MagicMod; 78 | 79 | 80 | //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Derived Attributes") 81 | // float SpellCritChance; 82 | //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Derived Attributes") 83 | // float SpellCritMultiply; 84 | 85 | //UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 86 | // float CritChance; 87 | //UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Derived Attributes") 88 | // float CritMultiply; 89 | 90 | 91 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 92 | // bool CanRegenerateHealth; 93 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 94 | // float HealthRegenInterval; 95 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 96 | // float HealthRegenValue; 97 | 98 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 99 | // bool CanRegenerateEnergy; 100 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 101 | // float EnergyRegenInterval; 102 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 103 | // float EnergyRegenValue; 104 | 105 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 106 | // bool CanRegenerateStamina; 107 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 108 | // float StaminaRegenInterval; 109 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health Regeneration") 110 | // float StaminaRegenValue; 111 | }; 112 | -------------------------------------------------------------------------------- /Source/RPG/Game/HUD/RPGHUD.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "../RPGCharacter.h" 5 | #include "../RPGPlayerController.h" 6 | #include "RPGHUD.h" 7 | 8 | 9 | ARPGHUD::ARPGHUD(const class FPostConstructInitializeProperties& PCIP) 10 | : Super(PCIP) 11 | { 12 | static ConstructorHelpers::FObjectFinder CrosshairTexObj(TEXT("Texture2D'/Game/SharedAssets/HUD/crosshair.crosshair'")); 13 | CrosshairTex = CrosshairTexObj.Object; 14 | } 15 | 16 | void ARPGHUD::ProjectCorsshairToHit(FVector hitLocation) 17 | { 18 | if(!Canvas) 19 | return; 20 | 21 | CrosshairCenter3D += Canvas->Project(hitLocation); 22 | } 23 | void ARPGHUD::DrawHUD() 24 | { 25 | Super::DrawHUD(); 26 | 27 | // find center of the screen/Canvas 28 | const FVector2D Center(Canvas->ClipX * 0.5f, Canvas->ClipY * 0.5f); 29 | 30 | CrosshairCenter = Center; 31 | 32 | 33 | if(CrosshairTex && Canvas) 34 | { 35 | FVector2D CrosshairDrawStart(CrosshairCenter); 36 | CrosshairDrawStart.X -= CrosshairTex->GetSurfaceWidth() * 0.5f; 37 | CrosshairDrawStart.Y -= CrosshairTex->GetSurfaceHeight() * 0.5f; 38 | 39 | 40 | FCanvasTileItem TileItem (CrosshairDrawStart, CrosshairTex->Resource, FLinearColor::Red); 41 | TileItem.BlendMode = SE_BLEND_Translucent; 42 | Canvas->DrawItem(TileItem); 43 | } 44 | 45 | } 46 | 47 | FVector ARPGHUD::GetStartLocation(const FVector& AimDir) const 48 | { 49 | ARPGPlayerController* PC = Cast(GetOwningPlayerController()); 50 | FVector OutStartTrace = FVector::ZeroVector; 51 | if(!GetOwningPawn()) 52 | return OutStartTrace; 53 | 54 | if(PC) 55 | { 56 | 57 | FRotator UnusedRot; 58 | PC->GetPlayerViewPoint(OutStartTrace, UnusedRot); 59 | OutStartTrace = OutStartTrace + AimDir * ((GetOwningPawn()->GetActorLocation() - OutStartTrace) | AimDir); 60 | //OutStartTrace = OutStartTrace + AimDir * ((Instigator->GetActorLocation() - OutStartTrace)); 61 | } 62 | return OutStartTrace; 63 | } 64 | 65 | FVector ARPGHUD::GetCameraAim() const 66 | { 67 | ARPGPlayerController* PC = Cast(GetOwningPlayerController()); 68 | FVector FinalAim = FVector::ZeroVector; 69 | 70 | if(PC) 71 | { 72 | FVector CamLoc; 73 | FRotator CamRot; 74 | PC->GetPlayerViewPoint(CamLoc, CamRot); 75 | FinalAim = CamRot.Vector(); 76 | } 77 | else if(GetOwningPawn()) 78 | { 79 | FinalAim = GetOwningPawn()->GetBaseAimRotation().Vector(); 80 | } 81 | return FinalAim; 82 | } 83 | 84 | FHitResult ARPGHUD::HUDHitResult(const FVector& StartTrace, const FVector& EndTrace) const 85 | { 86 | FHitResult Hit(ForceInit); 87 | if(!GetOwningPawn()) 88 | return Hit; 89 | 90 | 91 | static FName PowerTag = FName(TEXT("PowerTrace")); 92 | FCollisionQueryParams TraceParams(PowerTag, false, GetOwningPawn()); 93 | TraceParams.bTraceComplex = false; 94 | TraceParams.bTraceAsyncScene = false; 95 | TraceParams.bReturnPhysicalMaterial = true; 96 | bool traceResult = GetWorld()->LineTraceSingle(Hit, StartTrace, EndTrace, ECollisionChannel::ECC_Pawn, TraceParams); 97 | return Hit; 98 | } 99 | 100 | AActor* ARPGHUD::GetHUDHitActor() 101 | { 102 | AActor* actor = nullptr; 103 | 104 | //FVector Origin = GetCastingLocation(); 105 | const FVector ShootDir = GetCameraAim(); 106 | FVector StartTrace = GetStartLocation(ShootDir); 107 | 108 | const FVector EndTrace = (StartTrace + ShootDir * 10000.0f); 109 | FHitResult Impact = HUDHitResult(StartTrace, EndTrace); 110 | if (Impact.GetActor()) 111 | { 112 | return Impact.GetActor(); 113 | } 114 | return actor; 115 | } 116 | 117 | float ARPGHUD::GetTargetHealth() 118 | { 119 | return 0; 120 | } -------------------------------------------------------------------------------- /Source/RPG/Game/HUD/RPGHUD.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "RPGHUD.generated.h" 6 | 7 | /** 8 | * 9 | */ 10 | UCLASS() 11 | class ARPGHUD : public AHUD 12 | { 13 | GENERATED_UCLASS_BODY() 14 | 15 | virtual void DrawHUD() OVERRIDE; 16 | 17 | public: 18 | FVector2D CrosshairCenter; 19 | FVector CrosshairCenter3D; 20 | 21 | UPROPERTY(BlueprintReadOnly, Category=HUDNative) 22 | class ARPGCharacter* CharOwner; 23 | void ProjectCorsshairToHit(FVector hitLocation); 24 | protected: 25 | 26 | UFUNCTION(BlueprintCallable, Category = HUDHelpers) 27 | AActor* GetHUDHitActor(); 28 | UFUNCTION(BlueprintCallable, Category = "RPGHUD|Helpers") 29 | float GetTargetHealth(); 30 | 31 | 32 | private: 33 | FVector GetStartLocation(const FVector& AimDir) const; 34 | FVector GetCameraAim() const; 35 | FHitResult HUDHitResult(const FVector& StartTrace, const FVector& EndTrace) const; 36 | 37 | class URPGAttributeComponent* TargetAttributeComponent; 38 | 39 | UTexture2D* CrosshairTex; 40 | }; 41 | -------------------------------------------------------------------------------- /Source/RPG/Game/Items/RPGItem.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "RPGItem.h" 5 | 6 | 7 | ARPGItem::ARPGItem(const class FPostConstructInitializeProperties& PCIP) 8 | : Super(PCIP) 9 | { 10 | PrimaryActorTick.bCanEverTick = true; 11 | } 12 | 13 | 14 | void ARPGItem::OnItemProc_Implementation() 15 | { 16 | } 17 | 18 | void ARPGItem::InitializeItem() 19 | { 20 | SpawnDefaultEffectList(); 21 | } 22 | 23 | void ARPGItem::Tick(float DeltaSeconds) 24 | { 25 | Super::Tick(DeltaSeconds); 26 | if(ItemOwner) //check if item is owned by character 27 | { 28 | //if(ItemEffects.Num() > 0) //if there any effects assigned to item 29 | //{ 30 | // for(URPGItemEffect* effect : ItemEffects) //for effect 31 | // { 32 | // effect->OnAttributeChange(effect->CurrentCharacterAttributes); //we activate event that will send current character attributes to effect 33 | // //it's not finished, and it should be REVISED 34 | // effect->OnEffectTick(); 35 | // } 36 | //} 37 | } 38 | } 39 | 40 | void ARPGItem::SpawnDefaultEffectList() 41 | { 42 | //if(DefaultEffectList.Num() > 0) 43 | //{ 44 | // for(int32 i = 0; i < DefaultEffectList.Num(); i++) 45 | // { 46 | // URPGItemEffect* itemEffect = ConstructObject(DefaultEffectList[i]); 47 | // AddEffect(itemEffect); 48 | // } 49 | //} 50 | } 51 | 52 | //void ARPGItem::AddEffect(URPGItemEffect* itemEffect) 53 | //{ 54 | // if(itemEffect) 55 | // { 56 | // itemEffect->Initialize(ItemOwner); 57 | // ItemEffects.AddUnique(itemEffect); 58 | // } 59 | //} 60 | 61 | //bool ARPGItem::ConstituionPredicate(const ARPGItem& ip1, const ARPGItem& ip2) const 62 | //{ 63 | // return ip1.Attributes.Constitution < ip2.Attributes.Constitution; 64 | //} -------------------------------------------------------------------------------- /Source/RPG/Game/Items/RPGItem.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | //#include "../Common/RPGCharacterAttributes.h" 5 | #include "../RPGCharacter.h" 6 | //#include "Items/RPGItemEffect.h" 7 | #include "RPGItem.generated.h" 8 | 9 | /** 10 | * 11 | */ 12 | 13 | UENUM() 14 | enum EItemType 15 | { 16 | Item_Chest, 17 | Item_Head, 18 | Item_Legs, 19 | Item_Foot, 20 | Item_Hands, 21 | Item_Shoulders, 22 | Item_MainWeapon, 23 | Item_OffHandWeapon, 24 | }; 25 | 26 | 27 | UCLASS() 28 | class ARPGItem : public AActor 29 | { 30 | GENERATED_UCLASS_BODY() 31 | 32 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Attributes") 33 | TEnumAsByte ItemType; 34 | 35 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Attributes") 36 | ARPGCharacter* ItemOwner; 37 | 38 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Attributes") 39 | USkeletalMesh* ChestMesh; 40 | 41 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Attributes") 42 | float Constitution; 43 | 44 | /* 45 | Weight. We assume that one unit of weight is 1kg. Usefull 46 | if want to incorporate physics and or calculating total character weight. 47 | */ 48 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item|Attributes") 49 | float Weight; 50 | 51 | /** 52 | Arbitary number of effects that this item can apply to character. 53 | Please do not overuse it. Thanks ;) 54 | */ 55 | 56 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=ItemEffects) 57 | //TArray > DefaultEffectList; 58 | //UPROPERTY() 59 | //TArray ItemEffects; 60 | 61 | /** 62 | Trigger special item effect, on ability activation/tick. We will call this event regardless and whether it do something or no, depends on item implmenentation. 63 | */ 64 | UFUNCTION(BlueprintNativeEvent, Category=ItemEvent) 65 | void OnItemProc(); 66 | 67 | virtual void Tick(float DeltaSeconds) OVERRIDE; 68 | 69 | void InitializeItem(); 70 | /*bool ConstituionPredicate(const ARPGItem& ip1, const ARPGItem& ip2);*/ 71 | private: 72 | void SpawnDefaultEffectList(); 73 | //void AddEffect(URPGItemEffect* itemEffect); 74 | }; 75 | -------------------------------------------------------------------------------- /Source/RPG/Game/Items/RPGWeaponBase.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "RPGWeaponBase.h" 5 | 6 | 7 | ARPGWeaponBase::ARPGWeaponBase(const class FPostConstructInitializeProperties& PCIP) 8 | : Super(PCIP) 9 | { 10 | ArrowComp = PCIP.CreateDefaultSubobject(this, TEXT("ArrowComp")); 11 | WeaponMesh = PCIP.CreateDefaultSubobject(this, TEXT("WeaponMesh")); 12 | WeaponMesh->AttachParent = ArrowComp; 13 | 14 | } 15 | 16 | 17 | -------------------------------------------------------------------------------- /Source/RPG/Game/Items/RPGWeaponBase.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "../Shared/RPGEnums.h" 5 | #include "RPGWeaponBase.generated.h" 6 | 7 | /* 8 | Weapon Types. 9 | If there is new weapon. Add it here. 10 | */ 11 | 12 | 13 | /** 14 | * It should derive from ARPGItem, as it is base class for equipable items! 15 | */ 16 | UCLASS(Blueprintable) 17 | class ARPGWeaponBase : public AActor 18 | { 19 | GENERATED_UCLASS_BODY() 20 | 21 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=WeaponMesh) 22 | TSubobjectPtr WeaponMesh; 23 | //UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=WeaponMesh) 24 | //USkeletalMesh* WeaponMesh; 25 | TSubobjectPtr ArrowComp; 26 | 27 | UPROPERTY(EditAnywhere, Category=WeaponBaseProperties) 28 | TEnumAsByte WeaponType; 29 | }; 30 | -------------------------------------------------------------------------------- /Source/RPG/Game/RPGCharacter.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "RPGPlayerController.h" 5 | #include "Components/RPGEquipmentManagerComponent.h" 6 | #include "../RPGSystem/Components/RPGAbilityManagerComponent.h" 7 | #include "Components/RPGAttributeBaseComponent.h" 8 | #include "Abilities/GameAbility.h" 9 | #include "DamageTypes/RPGDamageType.h" 10 | #include "RPGCharacter.h" 11 | 12 | ////////////////////////////////////////////////////////////////////////// 13 | // ARPGCharacter 14 | 15 | ARPGCharacter::ARPGCharacter(const class FPostConstructInitializeProperties& PCIP) 16 | : Super(PCIP) 17 | { 18 | // Set size for collision capsule 19 | CapsuleComponent->InitCapsuleSize(42.f, 96.0f); 20 | LowOffset = FVector(-380.0f, 35.0f, 15.0f); 21 | MidOffset = FVector(-380.0f, 35.0f, 60.0f); 22 | HighOffset = FVector(-380.0f, 35.0f, 150.0f); //x,y,z 23 | 24 | // Create a camera boom (pulls in towards the player if there is a collision) 25 | CameraBoom = PCIP.CreateDefaultSubobject(this, TEXT("CameraBoom")); 26 | CameraBoom->AttachTo(RootComponent); 27 | CameraBoom->TargetArmLength = 300.0f; // The camera follows at this distance behind the character 28 | CameraBoom->bUseControllerViewRotation = true; // Rotate the arm based on the controller 29 | CameraBoom->SocketOffset = FVector(0.0f, 50.0f, 100.0f); 30 | // Create a follow camera 31 | FollowCamera = PCIP.CreateDefaultSubobject(this, TEXT("FollowCamera")); 32 | FollowCamera->AttachTo(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation 33 | FollowCamera->bUseControllerViewRotation = false; // Camera does not rotate relative to arm 34 | // set our turn rates for input 35 | //BaseTurnRate = 45.f; 36 | //BaseLookUpRate = 45.f; 37 | PrimaryActorTick.bCanEverTick = true; 38 | 39 | /* 40 | Items slots. 41 | */ 42 | EquipmentManager = PCIP.CreateDefaultSubobject(this, TEXT("EquipmentManager")); 43 | ChestMesh = PCIP.CreateDefaultSubobject(this, TEXT("ChestMesh")); 44 | ChestMesh->AttachParent = Mesh; 45 | ChestMesh->SetMasterPoseComponent(Mesh); 46 | 47 | HeadMesh = PCIP.CreateDefaultSubobject(this, TEXT("HeadMesh")); 48 | HeadMesh->AttachParent = Mesh; 49 | HeadMesh->SetMasterPoseComponent(Mesh); 50 | 51 | LegMesh = PCIP.CreateDefaultSubobject(this, TEXT("LegMesh")); 52 | LegMesh->AttachParent = Mesh; 53 | LegMesh->SetMasterPoseComponent(Mesh); 54 | 55 | FootMesh = PCIP.CreateDefaultSubobject(this, TEXT("FootMesh")); 56 | FootMesh->AttachParent = Mesh; 57 | FootMesh->SetMasterPoseComponent(Mesh); 58 | 59 | HandsMesh = PCIP.CreateDefaultSubobject(this, TEXT("HandsMesh")); 60 | HandsMesh->AttachParent = Mesh; 61 | HandsMesh->SetMasterPoseComponent(Mesh); 62 | 63 | ShouldersMesh = PCIP.CreateDefaultSubobject(this, TEXT("ShouldersMesh")); 64 | ShouldersMesh->AttachParent = Mesh; 65 | ShouldersMesh->SetMasterPoseComponent(Mesh); 66 | 67 | AbilityManager = PCIP.CreateDefaultSubobject(this, TEXT("AbilityManager")); 68 | AbilityManager->bAutoActivate = true; 69 | 70 | 71 | Attributes = PCIP.CreateDefaultSubobject(this, TEXT("Attributes")); 72 | Attributes->bAutoActivate = true; 73 | Attributes->Activate(); 74 | 75 | // Configure character movement 76 | CharacterMovement->bOrientRotationToMovement = true; // Character moves in the direction of input... 77 | 78 | } 79 | void ARPGCharacter::CalcCamera(float DeltaTime, struct FMinimalViewInfo& OutResult) 80 | { 81 | Super::CalcCamera(DeltaTime, OutResult); 82 | //FVector Loc, Pos, HitLocation, HitNormal, EyeLoc, FinalPos; 83 | //FRotator Rot, EyeRot; 84 | //FPOV OrigPOV; 85 | ////It should be header file, but for now it will work. 86 | ////FVector LowOffset = FVector(-380.0f,35.0f, 15.0f); 87 | ////FVector MidOffset = FVector(-380.0f,35.0f, 60.0f); 88 | ////FVector HighOffset = FVector(-380.0f,35.0f,150.0f); //x,y,z 89 | 90 | ////for some reason using blueprint Offset doesn't work. 91 | ////so we redecalre it locally and assign value trough blueprint. 92 | //FVector LowOffset = this->LowOffset; 93 | //FVector MidOffset = this->MidOffset; 94 | //FVector HighOffset = this->HighOffset; //x,y,z 95 | ////APlayerController* PC; 96 | ////int32 sizeX, sizeY; 97 | 98 | ////if(OutVT.Target) 99 | ////{ 100 | //// PC = Cast(OutVT.Target->GetInstigatorController()); 101 | //// PC->GetViewportSize(sizeX, sizeY); 102 | //// float aspectRatio = 0.0f; 103 | //// aspectRatio = (float)sizeX / (float)sizeY; 104 | //// if(aspectRatio >= 1.333f && aspectRatio < 1.777f) 105 | //// { 106 | //// LowOffset = FVector(-100.0f,10.0f, 5.0f); 107 | //// MidOffset = FVector(-100.0f,10.0f, 0.0f); 108 | //// HighOffset = FVector(-110.0f,10.0f,80.0f); 109 | //// } 110 | //// else if (aspectRatio > 1.76f) 111 | //// { 112 | //// LowOffset = FVector(-120.0f,10.0f, 5.0f); 113 | //// MidOffset = FVector(-200.0f,10.0f, 0.0f); 114 | //// HighOffset = FVector(-190.0f,10.0f,70.0f); 115 | //// } 116 | //// else 117 | //// { 118 | //// LowOffset = FVector(-120.0f,10.0f, 5.0f); 119 | //// MidOffset = FVector(-200.0f,10.0f, 0.0f); 120 | //// HighOffset = FVector(-180.0f,10.0f,80.0f); 121 | //// } 122 | ////} 123 | 124 | 125 | //FVector FinalOffset = MidOffset; 126 | 127 | //float pitchXX = 0; 128 | //float pitchZZ = 0; 129 | ////OrigPOV = OutVT.POV; 130 | ////OutVT.Target->GetActorEyesViewPoint(EyeLoc, EyeRot); 131 | //this->GetActorEyesViewPoint(EyeLoc, EyeRot); 132 | //Loc = this->GetActorLocation(); 133 | ////normalize axis to space between -180 and 180, 134 | //// we need because by default rotator is between 0 and 360 135 | //float normalizedEyeRotPitch = EyeRot.NormalizeAxis(EyeRot.Pitch); 136 | ////we do everything in Absolute numbers and then just multipli by -/+1 137 | ////looking up 138 | //if (EyeRot.NormalizeAxis(EyeRot.Pitch) > 0.0f) 139 | //{ 140 | // //FinalOffset = LowOffset; 141 | // float offsetX = FMath::Abs(LowOffset.X) / LowOffset.X; 142 | // float offsetZ = FMath::Abs(LowOffset.Z) / LowOffset.Z; 143 | 144 | // //HighOffset.X = math.Abs(HighOffset.X); 145 | // //HighOffset.Z = math.Abs(HighOffset.Z); 146 | // LowOffset = LowOffset.GetAbs(); 147 | // MidOffset = MidOffset.GetAbs(); 148 | // FinalOffset = FinalOffset.GetAbs(); //we convert to absolute number everything is + 149 | 150 | // float pitchX = (LowOffset.X - MidOffset.X) / 60; //-? 151 | // pitchXX = pitchX * normalizedEyeRotPitch; // - 152 | // pitchXX = FMath::Abs(pitchXX); // make sure result is + 153 | // float pitchZ = (LowOffset.Z - MidOffset.Z) / 60; //180 / -60 //- 154 | // pitchZZ = pitchZ * normalizedEyeRotPitch; // - 155 | // pitchZZ = FMath::Abs(pitchZZ); //make sure it is + 156 | 157 | // FinalOffset.X = FinalOffset.X + (pitchXX); 158 | // FinalOffset.X = FMath::Clamp(FinalOffset.X, LowOffset.X, MidOffset.X) * offsetX;//we have issue here what if the values will be positive ? 159 | // FinalOffset.Z = FinalOffset.Z + (pitchZZ); 160 | // if (LowOffset.Z > MidOffset.Z)//guess other offset adjustments also would need that. 161 | // { 162 | // FinalOffset.Z = FMath::Clamp(FinalOffset.Z, MidOffset.Z, LowOffset.Z) * offsetZ; 163 | // } 164 | // else 165 | // { 166 | // FinalOffset.Z = FMath::Clamp(FinalOffset.Z, LowOffset.Z, MidOffset.Z) * offsetZ; 167 | // } 168 | // FinalOffset.Y = LowOffset.Y; 169 | //} //looking down 170 | //else if (EyeRot.NormalizeAxis(EyeRot.Pitch) < 0.0f) 171 | //{ 172 | // float offsetX = FMath::Abs(HighOffset.X) / HighOffset.X; 173 | // float offsetZ = FMath::Abs(HighOffset.Z) / HighOffset.Z; 174 | 175 | // //HighOffset.X = math.Abs(HighOffset.X); 176 | // //HighOffset.Z = math.Abs(HighOffset.Z); 177 | // HighOffset = HighOffset.GetAbs(); 178 | // MidOffset = MidOffset.GetAbs(); 179 | // FinalOffset = FinalOffset.GetAbs(); //we convert to absolute number everything is + 180 | 181 | // float pitchX = (HighOffset.X - MidOffset.X) / -60; //-? 182 | // pitchXX = pitchX * normalizedEyeRotPitch; // - 183 | // pitchXX = FMath::Abs(pitchXX); // make sure result is + 184 | // float pitchZ = (HighOffset.Z - MidOffset.Z) / -60; //180 / -60 //- 185 | // pitchZZ = pitchZ * normalizedEyeRotPitch; // - 186 | // pitchZZ = FMath::Abs(pitchZZ); 187 | 188 | // FinalOffset.X = FinalOffset.X + (pitchXX); 189 | // FinalOffset.X = FMath::Clamp(FinalOffset.X, MidOffset.X, HighOffset.X) * offsetX;//we have issue here what if the values will be positive ? 190 | // FinalOffset.Z = FinalOffset.Z + (pitchZZ); 191 | // FinalOffset.Z = FMath::Clamp(FinalOffset.Z, MidOffset.Z, HighOffset.Z) * offsetZ; 192 | // FinalOffset.Y = HighOffset.Y; 193 | //} //looking directly straight pitch = 0, dunno if that ever happen. 194 | //else 195 | //{ 196 | // FinalOffset = MidOffset; 197 | //} 198 | 199 | //FinalPos = EyeLoc; 200 | ////FinalOffset = FinalOffset.SafeNormal(); 201 | //FinalPos += FRotationMatrix(EyeRot).TransformVector(FinalOffset); 202 | ////FinalPos += FRotationMatrix(EyeRot).TransformPosition(FinalOffset); 203 | //OutResult.Location = FinalPos; 204 | //OutResult.Rotation = EyeRot; 205 | //OutResult.AspectRatio = 1.7777779; 206 | //OutResult.bConstrainAspectRatio = true; 207 | ///*OutVT.POV.Location = FinalPos; 208 | //OutVT.POV.Rotation = EyeRot;*/ 209 | } 210 | 211 | ////////////////////////////////////////////////////////////////////////// 212 | // Input 213 | 214 | void ARPGCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent) 215 | { 216 | // Set up gameplay key bindings 217 | check(InputComponent); 218 | InputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump); 219 | InputComponent->BindAction("ActionButtonOne", IE_Pressed, this, &ARPGCharacter::ActionButtonOne); 220 | InputComponent->BindAction("ActionButtonOne", IE_Released, this, &ARPGCharacter::ActionButtonOneReleased); 221 | InputComponent->BindAction("ActionButtonTwo", IE_Pressed, this, &ARPGCharacter::ActionButtonTwo); 222 | InputComponent->BindAxis("MoveForward", this, &ARPGCharacter::MoveForward); 223 | InputComponent->BindAxis("MoveRight", this, &ARPGCharacter::MoveRight); 224 | 225 | // We have 2 versions of the rotation bindings to handle different kinds of devices differently 226 | // "turn" handles devices that provide an absolute delta, such as a mouse. 227 | // "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick 228 | InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput); 229 | //InputComponent->BindAxis("TurnRate", this, &ARPGCharacter::TurnAtRate); 230 | InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput); 231 | //InputComponent->BindAxis("LookUpRate", this, &ARPGCharacter::LookUpAtRate); 232 | 233 | //// handle touch devices 234 | //InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &ARPGCharacter::TouchStarted); 235 | } 236 | 237 | void ARPGCharacter::PostInitProperties() 238 | { 239 | Super::PostInitProperties(); 240 | } 241 | void ARPGCharacter::PostLoad() 242 | { 243 | Super::PostLoad(); 244 | } 245 | void ARPGCharacter::OnConstruction(const FTransform& Transform) 246 | { 247 | Super::OnConstruction(Transform); 248 | 249 | } 250 | void ARPGCharacter::BeginPlay() 251 | { 252 | Super::BeginPlay(); 253 | } 254 | void ARPGCharacter::Tick(float DeltaSeconds) 255 | { 256 | Super::Tick(DeltaSeconds); 257 | } 258 | void ARPGCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location) 259 | { 260 | // jump, but only on the first touch 261 | if (FingerIndex == ETouchIndex::Touch1) 262 | { 263 | Jump(); 264 | } 265 | } 266 | 267 | //void ARPGCharacter::TurnAtRate(float Rate) 268 | //{ 269 | // // calculate delta for this frame from the rate information 270 | // AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds()); 271 | //} 272 | // 273 | //void ARPGCharacter::LookUpAtRate(float Rate) 274 | //{ 275 | // // calculate delta for this frame from the rate information 276 | // AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds()); 277 | //} 278 | 279 | void ARPGCharacter::MoveForward(float Value) 280 | { 281 | if ((Controller != NULL) && (Value != 0.0f)) 282 | { 283 | FRotator Rotation = GetBaseAimRotation(); 284 | 285 | FVector Location; //not used, just need for below. 286 | //Controller->GetPlayerViewPoint(Location, Rotation); 287 | Rotation.Normalize(); 288 | FRotator YawRotation(0, Rotation.Yaw, 0); 289 | //const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis( EAxis::X ); 290 | const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X); 291 | AddMovementInput(Direction, Value); 292 | } 293 | } 294 | 295 | void ARPGCharacter::MoveRight(float Value) 296 | { 297 | if ( (Controller != NULL) && (Value != 0.0f) ) 298 | { 299 | // find out which way is right 300 | //const FRotator Rotation = Controller->GetPlayerViewPoint(); 301 | FRotator Rotation; 302 | FVector Location; //not used, just need for below. 303 | Controller->GetPlayerViewPoint(Location, Rotation); 304 | Rotation.Normalize(); 305 | FRotator YawRotation(0, Rotation.Yaw, 0); 306 | 307 | // get right vector 308 | //const FVector Direction = FRotationMatrix(YawRotation).GetScaledAxis(EAxis::Y); 309 | const FVector Direction = FRotationMatrix(YawRotation).GetScaledAxis(EAxis::Y); 310 | // add movement in that direction 311 | AddMovementInput(Direction, Value); 312 | } 313 | } 314 | 315 | float ARPGCharacter::TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, class AActor* DamageCauser) 316 | { 317 | URPGDamageType* damage = ConstructObject(DamageEvent.DamageTypeClass); 318 | ARPGCharacter* Causer = Cast(DamageCauser); 319 | damage->SetDamageTarget(Attributes); 320 | 321 | damage->SetDamageCauser(Causer->Attributes); 322 | 323 | damage->DealDamage(Causer, DamageAmount); 324 | return 0; 325 | } 326 | 327 | void ARPGCharacter::ActionButtonOne() 328 | { 329 | ARPGPlayerController* PC = Cast(Controller); 330 | if (PC) 331 | { 332 | AbilityManager->GetButtonOne()->InputPressed(); 333 | OnCharacterCast.Broadcast(); 334 | } 335 | } 336 | 337 | void ARPGCharacter::ActionButtonOneReleased() 338 | { 339 | ARPGPlayerController* PC = Cast(Controller); 340 | if (PC) 341 | { 342 | AbilityManager->GetButtonOne()->InputReleased(); 343 | } 344 | } 345 | 346 | void ARPGCharacter::ActionButtonTwo() 347 | { 348 | //ARPGPlayerController* PC = Cast(Controller); 349 | //if (PC) 350 | //{ 351 | // if (ActionButtonTwoObj != NULL) 352 | // { 353 | // ActionButtonTwoObj->OnCastStart(); 354 | // OnCharacterCast.Broadcast(); 355 | // } 356 | //} 357 | } 358 | 359 | void ARPGCharacter::SetWalkingSpeed() 360 | { 361 | CharacterMovement->MaxWalkSpeed = 440.0f; 362 | } -------------------------------------------------------------------------------- /Source/RPG/Game/RPGCharacter.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "GameFramework/SpringArmComponent.h" 5 | #include "RPGCharacter.generated.h" 6 | 7 | DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnCharacterCast); 8 | 9 | UCLASS(config=Game) 10 | class ARPGCharacter : public ACharacter 11 | { 12 | GENERATED_UCLASS_BODY() 13 | public: 14 | virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, class AActor* DamageCauser) OVERRIDE; 15 | //Item Slots 16 | public: 17 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = CharacterItems) 18 | TSubobjectPtr ChestMesh; 19 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = CharacterItems) 20 | TSubobjectPtr HeadMesh; 21 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = CharacterItems) 22 | TSubobjectPtr LegMesh; 23 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = CharacterItems) 24 | TSubobjectPtr FootMesh; 25 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = CharacterItems) 26 | TSubobjectPtr HandsMesh; 27 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = CharacterItems) 28 | TSubobjectPtr ShouldersMesh; 29 | 30 | //Manager Components 31 | public: 32 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera) 33 | TSubobjectPtr CameraBoom; 34 | 35 | /** Follow camera */ 36 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera) 37 | TSubobjectPtr FollowCamera; 38 | 39 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Componenets) 40 | TSubobjectPtr EquipmentManager; 41 | 42 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Componenets) 43 | TSubobjectPtr AbilityManager; 44 | 45 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Componenets) 46 | TSubobjectPtr Attributes; 47 | //Action Buttons 48 | public: 49 | UFUNCTION() 50 | void ActionButtonOne(); 51 | UFUNCTION() 52 | void ActionButtonOneReleased(); 53 | 54 | //UPROPERTY(BlueprintReadOnly, Transient, Category = ActionBar) 55 | // URPGPowerBase* ActionButtonOneObj; 56 | 57 | UFUNCTION() 58 | void ActionButtonTwo(); 59 | //UPROPERTY(Transient) 60 | // URPGPowerBase* ActionButtonTwoObj; 61 | 62 | //events 63 | public: 64 | UPROPERTY(BlueprintAssignable, Category = "RPGCharacter") 65 | FOnCharacterCast OnCharacterCast; 66 | 67 | //overrrides 68 | public: 69 | virtual void PostInitProperties() OVERRIDE; 70 | virtual void PostLoad() OVERRIDE; 71 | virtual void Tick(float DeltaSeconds) OVERRIDE; 72 | virtual void OnConstruction(const FTransform& Transform) OVERRIDE; 73 | virtual void BeginPlay() OVERRIDE; 74 | protected: 75 | 76 | /** Called for forwards/backward input */ 77 | void MoveForward(float Value); 78 | 79 | /** Called for side to side input */ 80 | void MoveRight(float Value); 81 | 82 | /** 83 | * Called via input to turn at a given rate. 84 | * @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate 85 | */ 86 | //void TurnAtRate(float Rate); 87 | 88 | /** 89 | * Called via input to turn look up/down at a given rate. 90 | * @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate 91 | */ 92 | /*void LookUpAtRate(float Rate);*/ 93 | 94 | /** Handler for when a touch input begins. */ 95 | void TouchStarted(ETouchIndex::Type FingerIndex, FVector Location); 96 | UPROPERTY(EditAnywhere, Category = CameraOffsets) 97 | FVector LowOffset; 98 | UPROPERTY(EditAnywhere, Category = CameraOffsets) 99 | FVector MidOffset; 100 | UPROPERTY(EditAnywhere, Category = CameraOffsets) 101 | FVector HighOffset; 102 | protected: 103 | // APawn interface 104 | virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) OVERRIDE; 105 | virtual void CalcCamera(float DeltaTime, struct FMinimalViewInfo& OutResult) OVERRIDE; 106 | // End of APawn interface 107 | 108 | public: 109 | 110 | void SetWalkingSpeed(); 111 | }; 112 | 113 | -------------------------------------------------------------------------------- /Source/RPG/Game/RPGEngine.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "GameplayTagsModule.h" 5 | #include "GameplayTags.h" 6 | #include "RPGEngine.h" 7 | 8 | 9 | URPGEngine::URPGEngine(const class FPostConstructInitializeProperties& PCIP) 10 | : Super(PCIP) 11 | { 12 | 13 | } 14 | 15 | void URPGEngine::Init(IEngineLoop* InEngineLoop) 16 | { 17 | Super::Init(InEngineLoop); 18 | 19 | IGameplayTagsModule& GameplayTagsModule = IGameplayTagsModule::Get(); 20 | GameplayTagsModule.GetGameplayTagsManager().LoadGameplayTagTable("/Game/Blueprints/Tags.Tags"); 21 | } 22 | -------------------------------------------------------------------------------- /Source/RPG/Game/RPGEngine.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "Engine.h" 5 | #include "RPGEngine.generated.h" 6 | 7 | UCLASS() 8 | class URPGEngine : public UGameEngine 9 | { 10 | GENERATED_UCLASS_BODY() 11 | 12 | virtual void Init(IEngineLoop* InEngineLoop) OVERRIDE; 13 | }; 14 | -------------------------------------------------------------------------------- /Source/RPG/Game/RPGEngineEditor.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "GameplayTagsModule.h" 5 | #include "GameplayTags.h" 6 | #include "RPGEngineEditor.h" 7 | 8 | 9 | URPGEngineEditor::URPGEngineEditor(const class FPostConstructInitializeProperties& PCIP) 10 | : Super(PCIP) 11 | { 12 | 13 | } 14 | //bool URPGEngineEditor::Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar) 15 | //{ 16 | // return Super::Exec(InWorld, Cmd, Ar); 17 | //} 18 | void URPGEngineEditor::Init(IEngineLoop* InEngineLoop) 19 | { 20 | Super::Init(InEngineLoop); 21 | //DataTable'/Game/Blueprints/MyTags.MyTags' 22 | //DataTable'/Game/Blueprints/Tags.Tags' 23 | IGameplayTagsModule& GameplayTagsModule = IGameplayTagsModule::Get(); 24 | GameplayTagsModule.GetGameplayTagsManager().LoadGameplayTagTable("/Game/Blueprints/Tags.Tags"); 25 | } 26 | -------------------------------------------------------------------------------- /Source/RPG/Game/RPGEngineEditor.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "Engine.h" 5 | #include "UnrealEd.h" 6 | #include "RPGEngineEditor.generated.h" 7 | 8 | UCLASS() 9 | class URPGEngineEditor : public UUnrealEdEngine 10 | { 11 | GENERATED_UCLASS_BODY() 12 | 13 | //virtual bool Exec(UWorld* InWorld, const TCHAR* Cmd, FOutputDevice& Ar = *GLog) OVERRIDE; 14 | 15 | virtual void Init(IEngineLoop* InEngineLoop) OVERRIDE; 16 | }; 17 | -------------------------------------------------------------------------------- /Source/RPG/Game/RPGGameMode.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "RPGPlayerController.h" 5 | #include "RPGGameMode.h" 6 | 7 | ARPGGameMode::ARPGGameMode(const class FPostConstructInitializeProperties& PCIP) 8 | : Super(PCIP) 9 | { 10 | PlayerControllerClass = ARPGPlayerController::StaticClass(); 11 | // set default pawn class to our Blueprinted character 12 | static ConstructorHelpers::FObjectFinder PlayerPawnBPClass(TEXT("Class'/Game/Blueprints/MyCharacter.MyCharacter_C'")); 13 | static ConstructorHelpers::FObjectFinder TheHUDOb(TEXT("Blueprint'/Game/Blueprints/HUD/BP_RPGHUD.BP_RPGHUD'")); 14 | if (PlayerPawnBPClass.Object != NULL) 15 | { 16 | DefaultPawnClass = PlayerPawnBPClass.Object; 17 | 18 | } 19 | if (TheHUDOb.Object != NULL) 20 | { 21 | HUDClass = (UClass*)TheHUDOb.Object->GeneratedClass; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Source/RPG/Game/RPGGameMode.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | 4 | #include "RPGGameMode.generated.h" 5 | 6 | UCLASS(minimalapi) 7 | class ARPGGameMode : public AGameMode 8 | { 9 | GENERATED_UCLASS_BODY() 10 | 11 | }; 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Source/RPG/Game/RPGPlayerController.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "RPGPlayerController.h" 5 | 6 | 7 | ARPGPlayerController::ARPGPlayerController(const class FPostConstructInitializeProperties& PCIP) 8 | : Super(PCIP) 9 | { 10 | 11 | } 12 | 13 | void ARPGPlayerController::BeginPlay() 14 | { 15 | Super::BeginPlay(); 16 | PlayerCameraManager->ViewPitchMax = 70.0f; 17 | PlayerCameraManager->ViewPitchMin = -70.0f; 18 | } 19 | void ARPGPlayerController::PrintAllActorsLocations() 20 | { 21 | //EngineUtils.h 22 | FActorIterator AllActorsItr = FActorIterator(GetWorld()); 23 | 24 | //While not reached end (overloaded bool operator) 25 | while (AllActorsItr) 26 | { 27 | ClientMessage(AllActorsItr->GetClass()->GetDesc()); 28 | ClientMessage(AllActorsItr->GetActorLocation().ToString()); 29 | 30 | //next actor 31 | ++AllActorsItr; 32 | } 33 | } 34 | 35 | //TSubobjectPtr ARPGPlayerController::GetCharacterPowerManager() 36 | //{ 37 | // ARPGCharacter* GC = Cast(GetCharacter()); 38 | // if(GC) 39 | // { 40 | // return GC->PowerManager; 41 | // } 42 | // return nullptr; 43 | //} -------------------------------------------------------------------------------- /Source/RPG/Game/RPGPlayerController.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "RPGPlayerController.generated.h" 5 | 6 | /** 7 | * 8 | */ 9 | UCLASS() 10 | class ARPGPlayerController : public APlayerController 11 | { 12 | GENERATED_UCLASS_BODY() 13 | 14 | void PrintAllActorsLocations(); 15 | virtual void BeginPlay() OVERRIDE; 16 | //TSubobjectPtr GetCharacterPowerManager(); 17 | }; 18 | -------------------------------------------------------------------------------- /Source/RPG/Game/RPGProjectile.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "RPGProjectile.h" 5 | #include "RPGPlayerController.h" 6 | 7 | ARPGProjectile::ARPGProjectile(const class FPostConstructInitializeProperties& PCIP) 8 | : Super(PCIP) 9 | { 10 | CollisionSphereRadius = 5; 11 | ProjectileAcceleration = 1.04; 12 | ProjectileLifeTime = 10; 13 | CollisionComp = PCIP.CreateDefaultSubobject(this, TEXT("SphereComp")); 14 | CollisionComp->InitSphereRadius(CollisionSphereRadius); 15 | CollisionComp->AlwaysLoadOnClient = true; 16 | CollisionComp->AlwaysLoadOnServer = true; 17 | CollisionComp->bTraceComplexOnMove = true; 18 | CollisionComp->BodyInstance.SetCollisionEnabled(ECollisionEnabled::QueryOnly); 19 | CollisionComp->BodyInstance.SetResponseToAllChannels(ECR_Ignore); 20 | CollisionComp->SetCollisionObjectType(ECC_Pawn); 21 | CollisionComp->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block); 22 | CollisionComp->SetCollisionResponseToChannel(ECC_WorldDynamic, ECR_Block); 23 | CollisionComp->SetCollisionResponseToChannel(ECC_Pawn, ECR_Block); 24 | RootComponent = CollisionComp; 25 | 26 | //Add Collision 27 | 28 | 29 | ParticleComp = PCIP.CreateDefaultSubobject(this, TEXT("ParticleComp")); 30 | ParticleComp->bAutoActivate = true; 31 | ParticleComp->bAutoDestroy = false; 32 | ParticleComp->AttachParent = RootComponent; 33 | 34 | MovementComp = PCIP.CreateDefaultSubobject(this, TEXT("ProjectileComp")); 35 | MovementComp->UpdatedComponent = CollisionComp; 36 | 37 | //Proj Speed 38 | MovementComp->InitialSpeed = 1000; 39 | MovementComp->MaxSpeed = 2000; 40 | 41 | MovementComp->bRotationFollowsVelocity = true; 42 | 43 | //add movement component 44 | 45 | //tick 46 | PrimaryActorTick.bCanEverTick = true; 47 | PrimaryActorTick.TickGroup = TG_PrePhysics; 48 | 49 | 50 | 51 | //ProjectileMovementComponent Settings 52 | 53 | //No gravity 54 | MovementComp->ProjectileGravityScale = 0; 55 | 56 | //Bounces 57 | MovementComp->BounceVelocityStopSimulatingThreshold = 5; //uu/sec 58 | MovementComp->bShouldBounce = 0; 59 | MovementComp->Friction = 0; 60 | MovementComp->Bounciness=0; 61 | } 62 | 63 | void ARPGProjectile::PostInitializeComponents() 64 | { 65 | Super::PostInitializeComponents(); 66 | 67 | //MovementComp->OnProjectileStop.AddDynamic(this, &ARPGProjectile::OnImpact); 68 | CollisionComp->MoveIgnoreActors.Add(Instigator); 69 | 70 | SetLifeSpan(10); 71 | MyController = Cast(GetInstigatorController()); 72 | 73 | } 74 | 75 | void ARPGProjectile::InitVelocity(FVector& ShootDirection) 76 | { 77 | if (MovementComp) 78 | { 79 | MovementComp->Velocity = ShootDirection * MovementComp->InitialSpeed; 80 | } 81 | } 82 | 83 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 84 | //Projectile Bounce Delegate 85 | void ARPGProjectile::OnBounce(FHitResult const& HitResult) 86 | { 87 | ARPGPlayerController* PC = Cast(GetInstigatorController()); 88 | if (PC) PC->ClientMessage("Bounce!!"); 89 | 90 | //Get Hit Actor 91 | AActor* HitActor = HitResult.GetActor(); 92 | if (!HitActor) return; 93 | 94 | //hit a pawn? Then do impact 95 | if (HitActor->IsA(APawn::StaticClass())) 96 | { 97 | //do impact 98 | OnImpact(HitResult); 99 | } 100 | } 101 | 102 | //Projectile Stop Delegate 103 | void ARPGProjectile::OnImpact(FHitResult const& HitResult) 104 | { 105 | if (Role == ROLE_Authority && !bExploded) 106 | { 107 | Explode(HitResult); 108 | DisableAndDestroy(); 109 | } 110 | } 111 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 112 | 113 | 114 | void ARPGProjectile::Explode(const FHitResult& Impact) 115 | { 116 | // effects and damage origin shouldn't be placed inside mesh at impact point 117 | const FVector NudgedImpactLocation = Impact.ImpactPoint + Impact.ImpactNormal * 10.0f; 118 | 119 | //Spawn Emitter At Impact Location 120 | if (ExplosionTemplate) 121 | { 122 | UGameplayStatics::SpawnEmitterAtLocation( 123 | Impact.GetActor(), 124 | ExplosionTemplate, 125 | NudgedImpactLocation, 126 | Impact.ImpactNormal.Rotation(), 127 | false); //auto destroy when explosion finishes 128 | } 129 | 130 | 131 | bExploded = true; 132 | } 133 | 134 | void ARPGProjectile::DisableAndDestroy() 135 | { 136 | SetActorHiddenInGame(true); 137 | MovementComp->StopMovementImmediately(); 138 | 139 | // give clients some time to show explosion 140 | SetLifeSpan( 1.0f ); 141 | } 142 | 143 | void ARPGProjectile::OnRep_Exploded() 144 | { 145 | static FName PowerTag = FName(TEXT("PowerTrace")); 146 | FCollisionQueryParams TraceParams(PowerTag, false); 147 | TraceParams.bTraceComplex = false; 148 | TraceParams.bTraceAsyncScene = false; 149 | TraceParams.bReturnPhysicalMaterial = true; 150 | FVector ProjDirection = GetActorRotation().Vector(); 151 | 152 | const FVector StartTrace = GetActorLocation() - ProjDirection * 200; 153 | const FVector EndTrace = GetActorLocation() + ProjDirection * 150; 154 | FHitResult Impact; 155 | bool hitResult = GetWorld()->LineTraceSingle(Impact, StartTrace, EndTrace, ECollisionChannel::ECC_Pawn, FCollisionQueryParams(TEXT("ProjClient"), true, Instigator)); 156 | if (!hitResult) 157 | { 158 | // failsafe 159 | Impact.ImpactPoint = GetActorLocation(); 160 | Impact.ImpactNormal = -ProjDirection; 161 | } 162 | 163 | Explode(Impact); 164 | } 165 | 166 | void ARPGProjectile::PostNetReceiveVelocity(const FVector& NewVelocity) 167 | { 168 | if (MovementComp) 169 | { 170 | MovementComp->Velocity = NewVelocity; 171 | } 172 | } 173 | //void ARPGProjectile::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const 174 | //{ 175 | // Super::GetLifetimeReplicatedProps(OutLifetimeProps); 176 | // 177 | // DOREPLIFETIME(ARPGProjectile, bExploded); 178 | //} 179 | //``` 180 | void ARPGProjectile::Tick(float DeltaSeconds) 181 | { 182 | Super::Tick(DeltaSeconds); 183 | 184 | if (bExploded) return; 185 | if (!MovementComp) return; 186 | //~~~~~~~~~~~~~~~~~~~~~~~~ 187 | 188 | //Acceleration, server side only 189 | if (Role == ROLE_Authority) 190 | { 191 | /** Current velocity of moved component, replicated to clients using Actor ReplicatedMovement property. */ 192 | MovementComp->Velocity *= ProjectileAcceleration; 193 | } 194 | } -------------------------------------------------------------------------------- /Source/RPG/Game/RPGProjectile.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | //#include "RPGPlayerController.h" 5 | #include "RPGProjectile.generated.h" 6 | 7 | /** 8 | * Base projectile class. 9 | * as with everything in this project implement only helper functions, 10 | * and leave game logic/mechanics to blueprints. 11 | * Projectiles are physical actors, that have travel speed, can collide with arbitary objects on path, 12 | * can bounce, track objects, and hell know what else... 13 | * Projectiles are spawned by weapons and powers. 14 | */ 15 | UCLASS() 16 | class ARPGProjectile : public AActor 17 | { 18 | GENERATED_UCLASS_BODY() 19 | /** initial setup */ 20 | virtual void PostInitializeComponents() OVERRIDE; 21 | 22 | /** setup velocity */ 23 | void InitVelocity(FVector& ShootDirection); 24 | 25 | /** handle hit */ 26 | //UFUNCTION() 27 | void OnImpact(FHitResult const& HitResult); 28 | 29 | /** Bounces */ 30 | void OnBounce(FHitResult const& HitResult); 31 | 32 | UFUNCTION(BlueprintImplementableEvent, Category=ProjectileEvents) 33 | void OnProjectileImpact(); 34 | UFUNCTION(BlueprintImplementableEvent, Category=ProjectileEvents) 35 | void OnProjectileDestroyed(); 36 | UFUNCTION(BlueprintImplementableEvent, Category=ProjectileEvents) 37 | void OnProjectileSpawned(); 38 | 39 | public: 40 | 41 | /** Projectile Lifetime in Seconds */ 42 | UPROPERTY(EditDefaultsOnly, Category=ProjectileNativeProperties) 43 | float ProjectileLifeTime; 44 | 45 | /** Collision Radius */ 46 | UPROPERTY(EditDefaultsOnly, Category=ProjectileNativeProperties) 47 | float CollisionSphereRadius; 48 | 49 | /** Acceleration Multiplier EVERY TICK, can increase velocity up to VictoryProjMaxSpeed*/ 50 | UPROPERTY(EditDefaultsOnly, Category=ProjectileNativeProperties) 51 | float ProjectileAcceleration; 52 | 53 | void InitializeProjectile(); 54 | 55 | protected: 56 | 57 | //Tick 58 | virtual void Tick(float DeltaSeconds) OVERRIDE; 59 | 60 | /** movement component */ 61 | UPROPERTY(VisibleDefaultsOnly, Category=ProjMovement) 62 | TSubobjectPtr MovementComp; 63 | 64 | /** collisions */ 65 | UPROPERTY(VisibleDefaultsOnly, Category=ProjCollision) 66 | TSubobjectPtr CollisionComp; 67 | 68 | UPROPERTY(VisibleDefaultsOnly, Category=Projectile) 69 | TSubobjectPtr ParticleComp; 70 | 71 | /** effects for explosion */ 72 | UPROPERTY(EditDefaultsOnly, Category=Effects) 73 | UParticleSystem* ExplosionTemplate; 74 | 75 | /* 76 | Particle Spawned when projectile is moving. 77 | We assume particle, since it is most universal actor. 78 | */ 79 | UPROPERTY(EditDefaultsOnly, Category=Effects) 80 | UParticleSystem* FXProjectileTravel; 81 | 82 | /** Owning controller */ 83 | 84 | /* 85 | We need access to shooter character properties, 86 | so we can setup thing like damage if we so desire. 87 | Besides it will give us direct access to information, who shot projectile 88 | if we need it on impact, or on actor who will be hit. 89 | */ 90 | UPROPERTY(BlueprintReadWrite, Category=NativeHelpers) 91 | class ARPGCharacter* ProjectileShooter; 92 | 93 | class ARPGPlayerController* MyController; 94 | 95 | /** did it explode? */ 96 | UPROPERTY(Transient) 97 | bool bExploded; 98 | 99 | /** [client] explosion happened */ 100 | UFUNCTION() 101 | void OnRep_Exploded(); 102 | 103 | /** trigger explosion */ 104 | void Explode(const FHitResult& Impact); 105 | 106 | /** shutdown projectile and prepare for destruction */ 107 | void DisableAndDestroy(); 108 | 109 | /** update velocity on client */ 110 | virtual void PostNetReceiveVelocity(const FVector& NewVelocity) OVERRIDE; 111 | 112 | }; 113 | -------------------------------------------------------------------------------- /Source/RPG/Game/Shared/RPGAttributeStructs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | //#include "RPG.h" 3 | #include "RPGAttributeStructs.generated.h" 4 | 5 | USTRUCT(BlueprintType, Blueprintable) 6 | struct FAttributeBase 7 | { 8 | GENERATED_USTRUCT_BODY() 9 | 10 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 11 | float Health; 12 | 13 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 14 | float Energy; 15 | 16 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Base Attributes") 17 | float Stamina; 18 | }; -------------------------------------------------------------------------------- /Source/RPG/Game/Shared/RPGEnums.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | //#include "RPG.h" 3 | #include "RPGEnums.generated.h" 4 | 5 | /* 6 | I'm honestly not sure if enum is right choice here. 7 | It might better to create subclass for each of the effect types as it would allow bigger flexibility, 8 | and then just compare types of class to check what to do with them. 9 | But on other hand comparing types on runtime is very bad practice and should be avoided. 10 | For example Effect might be Hex amd Damage Over Time at the same time, but we must choose only from one. 11 | On other hand it might be not that bad, since designer who will create effect in blueprint will be 12 | forced to be very specfici about effect he create, and stick to guideline about what each type of 13 | effect should do. 14 | Besides, effects can be nested (one effect can apply another effect, etc). 15 | 16 | In any case this enum is directly tied to Common/RPGCharacterStructs.h, and struct FEffectsOnCharacter. 17 | Properties of this struct should match enum values! - UPDATE THIS COMMENT IF IT CHANGE! 18 | */ 19 | UENUM() 20 | enum EWeaponType 21 | { 22 | Staff, 23 | MachineGun, 24 | OneHandedSword, 25 | HandGun, 26 | HeavyMachineGun, 27 | TwoHandedSword, 28 | Dagger, 29 | Bow, 30 | Crossbow 31 | }; 32 | 33 | UENUM() 34 | enum EEffectType 35 | { 36 | Hex, 37 | Curse, 38 | Enchantment 39 | }; 40 | 41 | USTRUCT(BlueprintType, Blueprintable) 42 | struct FAttributeData : public FTableRowBase 43 | { 44 | GENERATED_USTRUCT_BODY() 45 | 46 | public: 47 | 48 | FAttributeData() 49 | : Attribute(""), 50 | AttributeValue(0) 51 | {} 52 | 53 | /** The 'Name' column is the same as the XP Level */ 54 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = LevelUp) 55 | FName Attribute; 56 | 57 | /** This was the old property name (represented total XP) */ 58 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = LevelUp) 59 | float AttributeValue; 60 | }; -------------------------------------------------------------------------------- /Source/RPG/Public/RPG.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | //#include "RPG.generated.inl" 5 | 6 | IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, RPG, "RPG" ); 7 | -------------------------------------------------------------------------------- /Source/RPG/Public/RPG.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #ifndef __RPG_H__ 4 | #define __RPG_H__ 5 | 6 | #include "Engine.h" 7 | //#include "EngineUserInterfaceClasses.h" 8 | //#include "EngineKismetLibraryClasses.h" 9 | //#include "EngineDecalClasses.h" 10 | #include "Kismet/KismetSystemLibrary.h" 11 | #include "ParticleDefinitions.h" 12 | #include "RPGClasses.h" 13 | #endif 14 | 15 | #define COLLISION_COMBO ECC_GameTraceChannel1 -------------------------------------------------------------------------------- /Source/RPG/RPG.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | 5 | public class RPG : ModuleRules 6 | { 7 | public RPG(TargetInfo Target) 8 | { 9 | PublicIncludePaths.AddRange( 10 | new string[] { 11 | // ... add public include paths required here ... 12 | } 13 | ); 14 | PrivateIncludePaths.AddRange( 15 | new string[] { 16 | // "Runtime/GameplayTags/Private", 17 | // ... add other private include paths required here ... 18 | } 19 | ); 20 | PublicDependencyModuleNames.AddRange(new string[] 21 | { 22 | "Core", 23 | "CoreUObject", 24 | "Engine", 25 | "InputCore", 26 | "UnrealEd", 27 | "GameplayTags" 28 | }); 29 | 30 | PrivateDependencyModuleNames.AddRange(new string[] { "Slate" }); 31 | 32 | DynamicallyLoadedModuleNames.Add("EditorStyle"); 33 | 34 | PrivateIncludePathModuleNames.AddRange(new string[]{ 35 | "EditorStyle", 36 | "GameplayTags" 37 | }); 38 | 39 | if (UEBuildConfiguration.bBuildEditor == true) 40 | { 41 | //PrivateDependencyModuleNames.Add("GameplayTagsEditor"); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Abilities/RPGAbilityBase.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | #include "RPG.h" 4 | #include "../Components/RPGAttributeComponent.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "../Effects/RPGEffectBase.h" 7 | #include "../Effects/RPGEffectInstant.h" 8 | #include "../Effects/RPGEffectPeriodic.h" 9 | #include "../Effects/RPGEffectModifier.h" 10 | #include "../Effects/RPGEffectAreaSpread.h" 11 | #include "GameplayTagContainer.h" 12 | #include "RPGAbilityBase.h" 13 | 14 | 15 | URPGAbilityBase::URPGAbilityBase(const class FPostConstructInitializeProperties& PCIP) 16 | : Super(PCIP) 17 | { 18 | isOnCooldown = false; 19 | isChanneled = false; 20 | isCasted = false; 21 | } 22 | 23 | void URPGAbilityBase::Tick(float DeltaTime) 24 | { 25 | if (isOnCooldown) 26 | { 27 | currentCooldownTime += DeltaTime; 28 | if (currentCooldownTime >= AbilityCooldownTime) 29 | { 30 | currentCooldownTime = 0; 31 | isOnCooldown = false; 32 | } 33 | } 34 | 35 | if (isChanneled) 36 | { 37 | currentIntervalTime += DeltaTime; 38 | if (currentIntervalTime >= ChannelInterval) 39 | { 40 | currentIntervalTime = 0; 41 | OnAbilityStart(); 42 | } 43 | } 44 | 45 | if (isCasted) 46 | { 47 | currentCastTime += DeltaTime; 48 | if (currentCastTime >= MaxCastTime) 49 | { 50 | currentCastTime = 0; 51 | isCasted = false; 52 | OnAbilityStart(); 53 | } 54 | } 55 | if (isCharged) 56 | { 57 | currentChargeTime += DeltaTime; 58 | if (currentChargeTime >= MaxCastTime) 59 | { 60 | currentChargeTime = 0; 61 | isCharged = false; 62 | OnAbilityStart(); 63 | } 64 | } 65 | } 66 | 67 | bool URPGAbilityBase::IsTickable() const 68 | { 69 | if (AbilityOwner) 70 | { 71 | if (GetWorld()) 72 | { 73 | return true; 74 | } 75 | return false; 76 | } 77 | return false; 78 | } 79 | TStatId URPGAbilityBase::GetStatId() const 80 | { 81 | return this->GetStatID(); 82 | } 83 | 84 | UWorld* URPGAbilityBase::GetWorld() const 85 | { 86 | if (!AbilityOwner) 87 | return NULL; 88 | UWorld* const World = GEngine->GetWorldFromContextObject(AbilityOwner); 89 | return World ? World : nullptr; 90 | } 91 | 92 | /* 93 | If there is no component on actor then we don't initialize 94 | because powers need attributes to work properly. 95 | */ 96 | void URPGAbilityBase::Initialize(APawn* owner, AController* instigator) 97 | { 98 | AbilityOwner = owner; 99 | Instigator = instigator; 100 | 101 | if (AbilityOwner) 102 | { 103 | if (GetWorld()) 104 | { 105 | OwnerAttributeComp = AbilityOwner->FindComponentByClass(); 106 | if (OwnerAttributeComp.IsValid()) 107 | { 108 | IsAbilityInitialized = true; 109 | OnAbilityInitialized(); 110 | return; 111 | } 112 | IsAbilityInitialized = false; 113 | } 114 | IsAbilityInitialized = false; 115 | } 116 | IsAbilityInitialized = false; 117 | } 118 | 119 | void URPGAbilityBase::InputPressed() 120 | { 121 | bool haveRequiredWeapon = false; 122 | 123 | 124 | if (!CheckAbilityCost()) 125 | return; 126 | 127 | if (IsAbilityInitialized) 128 | { 129 | /* 130 | in reality we need more sophisitacted cooldown handling. If user for example 131 | cancel ability withing first 0.75 seconds cooldown will be shorter. 132 | */ 133 | if (!isOnCooldown) 134 | { 135 | if (AbilityCastType == ECastType::Casted) 136 | { 137 | isCasted = true; 138 | isOnCooldown = true; 139 | } 140 | if (AbilityCastType == ECastType::Casted_Charged) 141 | { 142 | isCharged = true; 143 | isOnCooldown = true; 144 | } 145 | if (AbilityCastType == ECastType::Channeled) 146 | { 147 | OnAbilityStart(); 148 | isChanneled = true; 149 | isOnCooldown = true; 150 | } 151 | } 152 | } 153 | } 154 | 155 | void URPGAbilityBase::InputReleased() 156 | { 157 | if (AbilityCastType == ECastType::Channeled) 158 | { 159 | OnAbilityStop(); 160 | isChanneled = false; 161 | } 162 | } 163 | 164 | bool URPGAbilityBase::CheckAbilityCost() 165 | { 166 | 167 | for (FModdableAttributes& cost : AttributeCost) 168 | { 169 | if (OwnerAttributeComp->IsSmaller(cost.AttributeName, cost.ModValue)) 170 | { 171 | return false; 172 | } 173 | } 174 | 175 | OwnerAttributeComp->ModifyAttributeList(AttributeCost, EAttributeOperation::Attribute_Subtract); 176 | return true; 177 | } 178 | 179 | float URPGAbilityBase::GetOwnerAttribute(FName AttributeName) 180 | { 181 | return OwnerAttributeComp->GetNumericValue(AttributeName); 182 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Abilities/RPGAbilityBase.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "Object.h" 5 | #include "GameplayTagContainer.h" 6 | #include "../Effects/RPGEffectBase.h" 7 | #include "../Structs/RPGSystemSructs.h" 8 | #include "RPGAbilityBase.generated.h" 9 | 10 | /** 11 | * This is base class for all powers in game. 12 | * Power is an action that can be performed by pawn, if said pawn have PowerManagerComponent. 13 | * like casting spell, throwing granade, shooting weapon, swinging sword. 14 | Well, maybe those be better implemented in RPGWeapon ;) 15 | * but any special action like whirlwind sword, is essentialy power that trigger special animation, 16 | have set duration (how long will character whirlwind ?), cost (how much endurance?) 17 | * cooldown (how long before I can use it again) and other costs defined. 18 | * power can also require character to have special weapon equiped, in order to use it. 19 | * powers are never placed directly in level. The class is data holder as well as contains 20 | common function needed to perform power. 21 | * power logic/behavior should be defined withing blueprint, which will derive 22 | from appropriate Power class. 23 | */ 24 | /* TODO 25 | 1. Add cast time handling (time between button press by player and triggering action). - semi done 26 | 2. Add resource cost handling. - done 27 | 3. Add weapon requierment. - semi done 28 | 4. Add attribute requirment. 29 | 5. Add cooldown handling (time after which power can be used again). - done 30 | 6. Add projectile shooting. 31 | 7. Add types of power, by enum. 32 | 8. Add mele type functions. Or create another power down the line in class hierarchy. 33 | 9. 34 | */ 35 | //weapon that is required to use ability. 36 | 37 | /* 38 | Should we take resource cost on cast start or on cast finish ? 39 | Start seems better, for sole reason is less forgiving ;) 40 | */ 41 | UENUM() 42 | enum ECastType 43 | { 44 | Casted, 45 | Casted_Charged, 46 | Channeled, 47 | Instant 48 | }; 49 | 50 | UCLASS(BlueprintType, Blueprintable) 51 | class URPGAbilityBase : public UObject, public FTickableGameObject 52 | { 53 | GENERATED_UCLASS_BODY() 54 | 55 | virtual void Tick(float DeltaTime) OVERRIDE; 56 | virtual bool IsTickable() const OVERRIDE; 57 | virtual TStatId GetStatId() const OVERRIDE; 58 | 59 | virtual class UWorld* GetWorld() const OVERRIDE; 60 | /* 61 | Launch Order: 62 | 1. When player press input button StartAbility() is fired. 63 | 2. StartAbility() call Initialize(). If you override StartAbility() 64 | Completly, you should make sure to Override Initialize() and add it to StartAbility(); 65 | 3. When Initialize() is passed, StartAbility() check is ability is on Cooldown, 66 | and then check how it should be casted. 67 | */ 68 | /* 69 | */ 70 | virtual void InputPressed(); 71 | virtual void InputReleased(); 72 | 73 | UFUNCTION(BlueprintImplementableEvent, Category = "Ability|Events") 74 | void OnAbilityStart(); 75 | UFUNCTION(BlueprintImplementableEvent, Category = "Ability|Events") 76 | void OnAbilityStop(); 77 | 78 | UFUNCTION(BlueprintImplementableEvent, Category = "Ability|Events") 79 | void OnAbilityInitialized(); 80 | /* 81 | Call only when ability is equiped for use. Ie. dragged to hotbar, or prepared from spellbook. 82 | Assign any properties that are needed prior ability can be used. 83 | For example check for componenets. 84 | */ 85 | virtual void Initialize(APawn* owner, AController* instigator); 86 | //should it be here or move it game specific ? 87 | 88 | protected: 89 | UPROPERTY(EditAnywhere, Category = "Ability Properties") 90 | float MaxCastTime; 91 | 92 | UPROPERTY(EditAnywhere, Category = "Ability Properties") 93 | float ChannelInterval; 94 | 95 | UPROPERTY(EditAnywhere, Category = "Ability Properties") 96 | float MaxOverCastTime; 97 | 98 | UPROPERTY(EditAnywhere, Category = "Ability Properties") 99 | float AbilityCooldownTime; 100 | 101 | UPROPERTY(EditAnywhere, Category = "Ability Properties") 102 | TArray AttributeCost; 103 | 104 | 105 | 106 | //class TWeakObjectPtr AbilityCost; 107 | 108 | private: 109 | bool CheckAbilityCost(); 110 | public: 111 | /* 112 | Effect for handling casting (using) ability. 113 | */ 114 | FGameplayTagContainer AbilityTags; 115 | 116 | private: 117 | bool isChanneled; 118 | bool isCasted; 119 | bool isOnCooldown; 120 | bool isCharged; 121 | float currentIntervalTime; 122 | float currentCooldownTime; 123 | float currentCastTime; 124 | float currentChargeTime; 125 | protected: 126 | bool IsAbilityInitialized; 127 | public: 128 | UPROPERTY(EditAnywhere, Category = "Ability Properties") 129 | TEnumAsByte AbilityCastType; 130 | public: 131 | void FORCEINLINE SetAbilityOwner(APawn* Owner) { AbilityOwner = Owner; }; 132 | void FORCEINLINE SetInstigator(AController* instigator) { Instigator = instigator; }; 133 | 134 | protected: 135 | void CacheInstantEffects(); 136 | 137 | UFUNCTION(BlueprintPure, Category = "RPG|Ability") 138 | float GetOwnerAttribute(FName AttributeName); 139 | 140 | /* 141 | maybe change it to APawn ? 142 | Most actors are static anyway, and they do not 143 | posses all the functionality needed for Ability to be 144 | correctly used in the first place. 145 | */ 146 | UPROPERTY(BlueprintReadOnly, Category = "Ability") 147 | APawn* AbilityOwner; 148 | 149 | UPROPERTY(BlueprintReadOnly, Category = "Ability") 150 | AController* Instigator; 151 | 152 | UPROPERTY(BlueprintReadOnly, Category = "Attributes") 153 | TWeakObjectPtr OwnerAttributeComp; 154 | 155 | UPROPERTY(BlueprintReadOnly, Category = "Attributes") 156 | TWeakObjectPtr TargetAttributes; 157 | 158 | //UPROPERTY(BlueprintReadOnly, Category = "Ability") 159 | // AActor* AbilityTarget; 160 | 161 | }; 162 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/BlueprintLibrary/RPGAttributeBPLibrary.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "RPG.h" 3 | #include "../Effects/RPGEffectBase.h" 4 | #include "../Components/RPGAttributeComponent.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "RPGAttributeBPLibrary.h" 7 | 8 | URPGAttributeBPLibrary::URPGAttributeBPLibrary(const class FPostConstructInitializeProperties& PCIP) 9 | : Super(PCIP) 10 | { 11 | 12 | } 13 | 14 | 15 | bool URPGAttributeBPLibrary::CompareAttributeBetweenActors(AActor* ActorA, AActor* ActorB, FName AttributeName) 16 | { 17 | if (ActorA && ActorB) 18 | { 19 | /*TArray ActorAAttributes; 20 | URPGAttributeComponent* ActorAAttribute = NULL;*/ 21 | URPGAttributeComponent* ActorAAttribute = ActorA->FindComponentByClass(); 22 | //for (URPGAttributeComponent* effectMngComp : ActorAAttributes) 23 | //{ 24 | // ActorAAttribute = effectMngComp; 25 | // break; 26 | //} 27 | 28 | //TArray ActorBAttributes; 29 | //URPGAttributeComponent* ActorBAttribute = NULL; 30 | URPGAttributeComponent* ActorBAttribute = ActorB->FindComponentByClass(); 31 | //for (URPGAttributeComponent* effectMngComp : ActorBAttributes) 32 | //{ 33 | // ActorBAttribute = effectMngComp; 34 | // break; 35 | //} 36 | 37 | if (ActorAAttribute && ActorBAttribute) 38 | { 39 | float ActorAAttributeValue = 0; 40 | float ActorBAttributeValue = 0; 41 | 42 | ActorAAttributeValue = ActorAAttribute->GetNumericValue(AttributeName); 43 | ActorBAttributeValue = ActorBAttribute->GetNumericValue(AttributeName); 44 | 45 | if (ActorAAttributeValue > ActorBAttributeValue) 46 | { 47 | return true; 48 | } 49 | return false; 50 | } 51 | } 52 | return false; 53 | } 54 | 55 | TArray URPGAttributeBPLibrary::ModifyAttributeSpec(TArray AttributeSpecIn, FName AttributeName, float ModValue, EAttributeOperation OperationType) 56 | { 57 | if (AttributeSpecIn.Num() > 0) 58 | { 59 | for (FAttributeSpec& spec : AttributeSpecIn) 60 | { 61 | if (spec.AttributeModList.Num() > 0) 62 | { 63 | for (FModdableAttributes& modAtr : spec.AttributeModList) 64 | { 65 | //that could moved into seprate function. 66 | if (modAtr.AttributeName == AttributeName) 67 | { 68 | switch (OperationType) 69 | { 70 | case EAttributeOperation::Attribute_Add: 71 | modAtr.ModValue += ModValue; 72 | break; 73 | case EAttributeOperation::Attribute_Subtract: 74 | modAtr.ModValue -= ModValue; 75 | break; 76 | case EAttributeOperation::Attribute_Multiply: 77 | modAtr.ModValue *= ModValue; 78 | break; 79 | case EAttributeOperation::Attribute_Divide: 80 | modAtr.ModValue /= ModValue; 81 | break; 82 | case EAttributeOperation::Attribute_Set: 83 | modAtr.ModValue = ModValue; 84 | break; 85 | default: 86 | break; 87 | } 88 | } 89 | } 90 | 91 | } 92 | //AttributeSpecOut.SetAttributeSpec(spec); 93 | } 94 | } 95 | 96 | return AttributeSpecIn; 97 | } 98 | 99 | FEffectSpec URPGAttributeBPLibrary::ModifyEffectSpec(FEffectSpec EffectSpecIn, FGameplayTagContainer RequiredTags, FName AttributeName, float ModValue, EAttributeOperation OperationType) 100 | { 101 | //for (FAttributeSpec& attrSpec : EffectSpecIn.AttributeSpecList) 102 | //{ 103 | // //if (attrSpec.OwnedTags.HasTag(TargetTag)) 104 | // //{ 105 | // for (FModdableAttributes& modAtr : attrSpec.AttributeModList) 106 | // { 107 | // if (modAtr.AttributeName == AttributeName) 108 | // { 109 | // switch (OperationType) 110 | // { 111 | // case EAttributeOperation::Attribute_Add: 112 | // modAtr.ModValue += ModValue; 113 | // break; 114 | // case EAttributeOperation::Attribute_Subtract: 115 | // modAtr.ModValue -= ModValue; 116 | // break; 117 | // case EAttributeOperation::Attribute_Multiply: 118 | // modAtr.ModValue *= ModValue; 119 | // break; 120 | // case EAttributeOperation::Attribute_Divide: 121 | // modAtr.ModValue /= ModValue; 122 | // break; 123 | // case EAttributeOperation::Attribute_Set: 124 | // modAtr.ModValue = ModValue; 125 | // break; 126 | // default: 127 | // break; 128 | // } 129 | // } 130 | // } 131 | // //} 132 | //} 133 | 134 | return EffectSpecIn; 135 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/BlueprintLibrary/RPGAttributeBPLibrary.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | //#include "RPG.h" 3 | #include "../Effects/RPGEffectBase.h" 4 | #include "../Structs/RPGSystemSructs.h" 5 | #include "RPGAttributeBPLibrary.generated.h" 6 | 7 | 8 | 9 | UCLASS() 10 | class URPGAttributeBPLibrary : public UBlueprintFunctionLibrary 11 | { 12 | GENERATED_UCLASS_BODY() 13 | 14 | public: 15 | 16 | /* 17 | Compare Attribute between actors: 18 | ActorA > ActorB 19 | */ 20 | UFUNCTION(BlueprintCallable, Category = "Attributes|Static") 21 | static bool CompareAttributeBetweenActors(AActor* ActorA, AActor* ActorB, FName AttributeName); 22 | 23 | UFUNCTION(BlueprintCallable, Category = "Attributes|Static") 24 | static TArray ModifyAttributeSpec(TArray AttributeSpecIn, FName AttributeName, float ModValue, EAttributeOperation OperationType); 25 | 26 | UFUNCTION(BlueprintPure, Category = "Attributes|Static") 27 | static FEffectSpec ModifyEffectSpec(FEffectSpec EffectSpecIn, FGameplayTagContainer RequiredTags, FName AttributeName, float ModValue, EAttributeOperation OperationType); 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/BlueprintLibrary/RPGCreateNewObject.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "RPG.h" 3 | #include "RPGCreateNewObject.h" 4 | 5 | URPGCreateNewObject::URPGCreateNewObject(const class FPostConstructInitializeProperties& PCIP) 6 | : Super(PCIP) 7 | { 8 | 9 | } 10 | 11 | UObject* URPGCreateNewObject::NewObjectFromBlueprint(UObject* WorldContextObject, TSubclassOf UC) 12 | { 13 | UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject); 14 | UObject* tempObject = StaticConstructObject(UC); 15 | 16 | return tempObject; 17 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/BlueprintLibrary/RPGCreateNewObject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | //#include "RPG.h" 3 | #include "RPGCreateNewObject.generated.h" 4 | 5 | 6 | 7 | UCLASS() 8 | class URPGCreateNewObject : public UEdGraphNode 9 | { 10 | GENERATED_UCLASS_BODY() 11 | 12 | public: 13 | UFUNCTION(BlueprintPure, meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", FriendlyName = "Create Object From Blueprint", CompactNodeTitle = "Create", Keywords = "new create blueprint"), Category = Game) 14 | static UObject* NewObjectFromBlueprint(UObject* WorldContextObject, TSubclassOf UC); 15 | 16 | 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/BlueprintLibrary/RPGEffectBPLibrary.cpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "RPG.h" 3 | #include "../Effects/RPGEffectBase.h" 4 | #include "../Effects/RPGEffectInstant.h" 5 | #include "../Effects/RPGEffectPeriodic.h" 6 | #include "../Effects/RPGEffectModifier.h" 7 | #include "../Components/RPGAttributeComponent.h" 8 | #include "RPGEffectBPLibrary.h" 9 | 10 | URPGEffectBPLibrary::URPGEffectBPLibrary(const class FPostConstructInitializeProperties& PCIP) 11 | : Super(PCIP) 12 | { 13 | 14 | } 15 | 16 | URPGEffectInstant* URPGEffectBPLibrary::CreateInstantEffect(AActor* EffectTarget, AActor* EffectCausedBy, TSubclassOf InstantEffectIn, TArray ModAttributesIn, FName AttributeName, float AttributeValue) 17 | { 18 | TWeakObjectPtr attrComp = EffectTarget->FindComponentByClass(); 19 | 20 | if (!attrComp.IsValid()) 21 | return NULL; 22 | 23 | TWeakObjectPtr tempEff = ConstructObject(InstantEffectIn); 24 | 25 | tempEff->SetTarget(EffectTarget); 26 | tempEff->SetCauser(EffectCausedBy); 27 | tempEff->AttributesToChange = ModAttributesIn; 28 | tempEff->AttributeName = AttributeName; 29 | tempEff->AttributeValue = AttributeValue; 30 | return tempEff.Get(); 31 | } 32 | 33 | URPGEffectPeriodic* URPGEffectBPLibrary::CreatePeriodicEffect(AActor* EffectTarget, AActor* EffectCausedBy, TSubclassOf PeriodicEffectIn, float PeriodLenght, float PeriodCount) 34 | { 35 | TWeakObjectPtr attrComp = EffectTarget->FindComponentByClass(); 36 | 37 | if (!attrComp.IsValid()) 38 | return NULL; 39 | 40 | TWeakObjectPtr tempEff = ConstructObject(PeriodicEffectIn); 41 | 42 | tempEff->SetTarget(EffectTarget); 43 | tempEff->SetCauser(EffectCausedBy); 44 | tempEff->SetPeriodCount(PeriodCount); 45 | tempEff->SetPeriodLenght(PeriodLenght); 46 | return tempEff.Get(); 47 | } 48 | 49 | URPGEffectModifier* URPGEffectBPLibrary::CreateModifierEffect(TSubclassOf EffectIn) 50 | { 51 | TWeakObjectPtr tempEff = ConstructObject(EffectIn); 52 | 53 | return tempEff.Get(); 54 | } 55 | 56 | void URPGEffectBPLibrary::Applyffect(class URPGEffectInstant* EffectIn) 57 | { 58 | if (!EffectIn) 59 | return; 60 | 61 | EffectIn->PreInitialize(); 62 | EffectIn->Initialize(); 63 | } 64 | 65 | void URPGEffectBPLibrary::ApplyPeriodicEffect(class URPGEffectPeriodic* EffectIn, TArray EffectsToApply) 66 | { 67 | TWeakObjectPtr attrComp = EffectIn->GetTarget()->FindComponentByClass(); 68 | if (!attrComp.IsValid()) 69 | return; 70 | 71 | EffectIn->EffectsToApply = EffectsToApply; 72 | EffectIn->PreInitialize(); 73 | EffectIn->Initialize(); 74 | 75 | attrComp->ApplyPeriodicEffect(EffectIn); 76 | } 77 | 78 | URPGEffectInstant* URPGEffectBPLibrary::ModifyEffect(class URPGEffectModifier* ModifierEffect, class URPGEffectInstant* EffectToMod) 79 | { 80 | if (!ModifierEffect && !EffectToMod) 81 | return EffectToMod; 82 | 83 | ModifierEffect->AttributeValue = EffectToMod->AttributeValue; 84 | 85 | ModifierEffect->PreInitialize(); 86 | ModifierEffect->Initialize(); 87 | 88 | EffectToMod->AttributeValue = ModifierEffect->AttributeValue; 89 | 90 | return EffectToMod; 91 | } 92 | 93 | void URPGEffectBPLibrary::ApplyInstantEffects(AActor* EffectTarget, AActor* EffectCausedBy, TArray InstantEffectSpecs, TArray AttributeSpecs) 94 | { 95 | if (!EffectTarget && !EffectCausedBy) 96 | return; 97 | 98 | URPGAttributeComponent* attrComp = EffectTarget->FindComponentByClass(); 99 | 100 | if (!attrComp) 101 | return; 102 | 103 | for (FEffectInstant& instEff : InstantEffectSpecs) 104 | { 105 | if (instEff.DoesCauserIsTarget) 106 | { 107 | instEff.InitializeInstantEffect(EffectCausedBy, EffectCausedBy); 108 | } 109 | else 110 | { 111 | instEff.InitializeInstantEffect(EffectTarget, EffectCausedBy); 112 | } 113 | 114 | for (FAttributeSpec& attrSpec : AttributeSpecs) 115 | { 116 | if (instEff.EffectInstant->OwnedTags.HasAnyTag(attrSpec.RequiredTags)) 117 | { 118 | instEff.EffectInstant->AttributeSpec = attrSpec; 119 | } 120 | } 121 | attrComp->ApplyInstantEffect(instEff); 122 | } 123 | } 124 | 125 | void URPGEffectBPLibrary::ApplyEffectPeriodc(AActor* target, AActor* causedBy, int32 HowManyToApply, TSubclassOf PeriodicEffectIn) 126 | { 127 | if (target && causedBy) 128 | { 129 | URPGAttributeComponent* attrComp = target->FindComponentByClass(); 130 | TWeakObjectPtr tempEff = ConstructObject(PeriodicEffectIn); 131 | if (!attrComp) 132 | return; 133 | 134 | tempEff->SetTarget(target); 135 | tempEff->SetCauser(causedBy); 136 | 137 | //EffectSpec.InitializePeriodicEffect(target, causedBy); 138 | 139 | //EffectSpec.EffectPeriod->CacheInstantEffects(instEffect); 140 | 141 | tempEff->PreInitialize(); 142 | tempEff->Initialize(); 143 | 144 | attrComp->ApplyPeriodicEffect(tempEff.Get()); 145 | } 146 | } 147 | 148 | void URPGEffectBPLibrary::ApplyDamage(AActor* Target, AActor* CausedBy, float DamageAmount, FName AttributeName) 149 | { 150 | TWeakObjectPtr attrComp = Target->FindComponentByClass(); 151 | 152 | if (!attrComp.IsValid()) 153 | return; 154 | 155 | attrComp->TakeDamage(DamageAmount, AttributeName, CausedBy); 156 | } 157 | 158 | void URPGEffectBPLibrary::LoopTestFunction(TSubclassOf EffectIn) 159 | { 160 | URPGEffectBase* effectTemp; 161 | for (int i = 0; i < 100000; i++) 162 | { 163 | effectTemp = ConstructObject(EffectIn); 164 | } 165 | } 166 | 167 | void URPGEffectBPLibrary::ApplyEffectRadial(AActor* CausedBy, FVector HitLocation, float Radius, int32 MaxTargets, FEffectSpec EffectSpec) 168 | { 169 | 170 | } 171 | 172 | void URPGEffectBPLibrary::ApplyEffectInLine(AActor* CausedBy, FVector StartLocation, float Lenght, TSubclassOf Effect) 173 | { 174 | 175 | } 176 | 177 | void URPGEffectBPLibrary::ModifyIncomingEffect(FGameplayTagContainer IncomingEffect, FGameplayTagContainer ModifierEffect) 178 | { 179 | //if (!IncomingEffect.EffectInstant.IsValid() && !ModifierEffect.EffectInstant.IsValid()) 180 | // return IncomingEffect; 181 | 182 | //IncomingEffect.EffectInstant->AttributeSpec = ModifierEffect.EffectInstant->AttributeSpec; 183 | 184 | //return IncomingEffect; 185 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/BlueprintLibrary/RPGEffectBPLibrary.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | //#include "RPG.h" 3 | #include "../Effects/RPGEffectBase.h" 4 | #include "RPGEffectBPLibrary.generated.h" 5 | 6 | 7 | 8 | UCLASS() 9 | class URPGEffectBPLibrary : public UBlueprintFunctionLibrary 10 | { 11 | GENERATED_UCLASS_BODY() 12 | 13 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect|Static") 14 | static class URPGEffectInstant* CreateInstantEffect(AActor* EffectTarget, AActor* EffectCausedBy, TSubclassOf InstantEffectIn, TArray ModAttributesIn, FName AttributeName, float AttributeValue); 15 | 16 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect|Static") 17 | static class URPGEffectPeriodic* CreatePeriodicEffect(AActor* EffectTarget, AActor* EffectCausedBy, TSubclassOf PeriodicEffectIn, float PeriodLenght, float PeriodCount); 18 | 19 | UFUNCTION(BlueprintPure, Category = "RPG|Effect|Static") 20 | static class URPGEffectModifier* CreateModifierEffect(TSubclassOf EffectIn); 21 | 22 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect|Static") 23 | static void Applyffect(class URPGEffectInstant* EffectIn); 24 | 25 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect|Static") 26 | static void ApplyPeriodicEffect(class URPGEffectPeriodic* EffectIn, TArray EffectsToApply); 27 | 28 | UFUNCTION(BlueprintPure, Category = "RPG|Effect|Static") 29 | static class URPGEffectInstant* ModifyEffect(class URPGEffectModifier* ModifierEffect, class URPGEffectInstant* EffectToMod); 30 | 31 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect|Static") 32 | static void ApplyDamage(AActor* Target, AActor* CausedBy, float DamageAmount, FName AttributeName); 33 | 34 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect|Static") 35 | static void ApplyInstantEffects(AActor* EffectTarget, AActor* EffectCausedBy, TArray InstantEffectSpecs, TArray AttributeSpecs); 36 | 37 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect|Static") 38 | static void LoopTestFunction(TSubclassOf EffectIn); 39 | 40 | /* 41 | target - who will receive effect. 42 | causedBy - who caused, to target recive effect. 43 | HowManyToApply - how many effects apply to target. 44 | EffectSpec - Periodic effect to apply. 45 | EffectInstantSpec - instant effects that will appiled by periodic effect. 46 | AttributeSpec - Attributes that will be modified by periodic and instant effects. 47 | */ 48 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect|Static") 49 | static void ApplyEffectPeriodc(AActor* target, AActor* causedBy, int32 HowManyToApply, TSubclassOf PeriodicEffectIn); 50 | 51 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect|Static") 52 | static void ApplyEffectRadial(AActor* CausedBy, FVector HitLocation, float Radius, int32 MaxTargets, FEffectSpec EffectSpec); 53 | 54 | /* 55 | Apply effect to all actors in line. Starting from actor that used it. 56 | */ 57 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect|Static") 58 | static void ApplyEffectInLine(AActor* CausedBy, FVector StartLocation, float Lenght, TSubclassOf Effect); 59 | 60 | 61 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect|Static") 62 | static void ModifyIncomingEffect(FGameplayTagContainer IncomingEffect, FGameplayTagContainer ModifierEffect); 63 | }; 64 | 65 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Components/RPGAbilityManagerComponent.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "../Abilities/RPGAbilityBase.h" 5 | #include "RPGAbilityManagerComponent.h" 6 | 7 | 8 | 9 | URPGAbilityManagerComponent::URPGAbilityManagerComponent(const class FPostConstructInitializeProperties& PCIP) 10 | : Super(PCIP) 11 | { 12 | 13 | } 14 | 15 | void URPGAbilityManagerComponent::AddPower(TSubclassOf ability, APawn* Owner) 16 | { 17 | if (ability && Owner) 18 | { 19 | URPGAbilityBase* abilityObj = ConstructObject(ability); 20 | 21 | abilityObj->Initialize(Owner, Owner->Controller); 22 | 23 | //abilityObj->SetPowerOner(MyPawn); 24 | //powerObj->SetMainCasterWeapon(MyPawn->EquipmentManager->MainWeapon); 25 | //powerObj->SetMainCasterWeapon(comp->MainWeapon); 26 | AbilityList.AddUnique(abilityObj); 27 | /* 28 | this should be handled by drag&drop UI 29 | where user just drag ability from ability inventory to hot bar 30 | 31 | in more elaborate scenario there can be more layers to it. Like dragging 32 | Spells to spell slots (to prepare them) 33 | and then dragging prepared spells to hotbar. 34 | Either way this is just debug solution that should be changed. 35 | */ 36 | if (!AbilityButtonOneObj) 37 | { 38 | AbilityButtonOneObj = abilityObj; 39 | } 40 | } 41 | } 42 | 43 | URPGAbilityBase* URPGAbilityManagerComponent::GetButtonOne() 44 | { 45 | if (AbilityButtonOneObj) 46 | { 47 | return AbilityButtonOneObj; 48 | } 49 | return NULL; 50 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Components/RPGAbilityManagerComponent.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | //#include "RPG.h" 5 | #include "RPGAbilityManagerComponent.generated.h" 6 | 7 | //DECLARE_DELEGATE_RetVal(URPGPowerBase, FOnNewPowerAdded); 8 | /** 9 | * 10 | */ 11 | UCLASS() 12 | class URPGAbilityManagerComponent : public UActorComponent 13 | { 14 | GENERATED_UCLASS_BODY() 15 | 16 | /* we might want to make it private or protected and do not expose to blueprint 17 | and only interaction troug equip/remove/get power/s */ 18 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Ability|Manager") 19 | TArray AbilityList; 20 | 21 | /* 22 | Stub function. Just for testing, probably will need change o removed, do not overuse it! 23 | */ 24 | UFUNCTION(BlueprintCallable, Category="Ability|Manager") 25 | void AddPower(TSubclassOf ability, APawn* Owner); 26 | 27 | 28 | 29 | public: 30 | class URPGAbilityBase* GetButtonOne(); 31 | protected: 32 | UPROPERTY(BlueprintReadOnly, Category = "Ability") 33 | class URPGAbilityBase* AbilityButtonOneObj; 34 | }; -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Components/RPGAttributeComponent.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "RPG.h" 5 | #include "../Effects/RPGEffectBase.h" 6 | #include "../Effects/RPGEffectInstant.h" 7 | #include "../Effects/RPGEffectPeriodic.h" 8 | #include "../RPGAttributeBase.h" 9 | #include "RPGAttributeComponent.h" 10 | 11 | URPGAttributeComponent::URPGAttributeComponent(const class FPostConstructInitializeProperties& PCIP) 12 | : Super(PCIP) 13 | { 14 | PrimaryComponentTick.bCanEverTick = true; 15 | bWantsInitializeComponent = true; 16 | } 17 | void URPGAttributeComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) 18 | { 19 | Super::TickComponent(DeltaTime, TickType, ThisTickFunction); 20 | } 21 | 22 | void URPGAttributeComponent::InitializeComponent() 23 | { 24 | Super::InitializeComponent(); 25 | } 26 | void URPGAttributeComponent::OnRegister() 27 | { 28 | Super::OnRegister(); 29 | } 30 | 31 | void URPGAttributeComponent::TakeDamage(float DamageAmount, FName AttributeName, AActor* CausedBy) 32 | { 33 | ChangeAttribute(AttributeName, DamageAmount, EAttributeOperation::Attribute_Subtract); 34 | } 35 | 36 | void URPGAttributeComponent::ApplyPeriodicEffect(class URPGEffectPeriodic* PeriodicEffect) 37 | { 38 | 39 | //OnRecivedEffect.Broadcast(EffectSpec.Target, EffectSpec.EffectPeriod->GetClass()); 40 | SetPeriodicEffect(PeriodicEffect); 41 | return; 42 | } 43 | 44 | void URPGAttributeComponent::SetPeriodicEffect(class URPGEffectPeriodic* newEffect) 45 | { 46 | 47 | //if effect has been found on array 48 | //we will check if it have special properties 49 | //some effects will not be appiled multiple times 50 | //instead they can have their duration extended 51 | //or can be reseted. depends on designer choices. 52 | if (PeriodicEffectsList.Num() > 0) 53 | { 54 | URPGEffectPeriodic* firstMatch = NULL; 55 | for (auto it = PeriodicEffectsList.CreateIterator(); it; ++it) 56 | { 57 | URPGEffectPeriodic* match = PeriodicEffectsList[it.GetIndex()]; 58 | if (match->OwnedTags == newEffect->OwnedTags) 59 | { 60 | firstMatch = match; 61 | break; 62 | } 63 | } 64 | 65 | if (firstMatch) 66 | { 67 | //if effect have stackable duration 68 | if (firstMatch->StackDuration == true) 69 | { 70 | //we simply get duration of current effect on array 71 | //and add new duration to total pool. 72 | firstMatch->TotalDuration += newEffect->TotalDuration; 73 | return; 74 | } 75 | 76 | /* 77 | Default behavior 78 | if the effect is on the list 79 | we remove it from it 80 | and then apply it again. 81 | This way we reset current effect, so we won't end up with multiple effects doing 82 | the same thing. 83 | */ 84 | RemoveEffect(firstMatch); 85 | PeriodicEffectsList.Add(newEffect); 86 | } 87 | } 88 | 89 | 90 | 91 | //GetWorld()->GetTimerManager().SetTimer(newEffect->EffectTimerDel, newEffect->PeriodLenght, true); 92 | 93 | PeriodicEffectsList.Add(newEffect); 94 | } 95 | 96 | void URPGAttributeComponent::ApplyInstantEffects(TArray EffectSpec, class URPGEffectPeriodic* ParentEffect) 97 | { 98 | /* 99 | If we have parent effect, this means that incoming effects has been appiled from withing effect. 100 | Check parent effect if it does have cached version of effects, 101 | so instead of making new object we will just retrive pointer to it 102 | */ 103 | if (CheckParentEffect(ParentEffect)) 104 | return; 105 | 106 | // Cache effects 107 | for (FEffectInstant& effectSpec : EffectSpec) 108 | { 109 | //effectSpec.SetInstantEffect(); 110 | 111 | if (!effectSpec.EffectInstant.IsValid()) 112 | return; 113 | 114 | if (!ParentEffect) 115 | return; 116 | 117 | if (effectSpec.DoesCauserIsTarget) 118 | { 119 | //effectSpec.CausedBy = ParentEffect->GetCausedBy(); 120 | //effectSpec.Target = ParentEffect->GetCausedBy(); 121 | effectSpec.EffectInstant->SetTarget(ParentEffect->GetCausedBy()); 122 | } 123 | } 124 | 125 | //one time action, we should never get here second time. 126 | //Run cached effects for first time. 127 | if (CheckParentEffect(ParentEffect)) 128 | return; 129 | } 130 | 131 | void URPGAttributeComponent::ApplyInstantEffect(FEffectInstant InstantEffectSpec) 132 | { 133 | InstantEffectSpec.EffectInstant->PreInitialize(); 134 | InstantEffectSpec.EffectInstant->Initialize(); 135 | } 136 | 137 | bool URPGAttributeComponent::CheckParentEffect(class URPGEffectPeriodic* ParentEffect) 138 | { 139 | //if (ParentEffect) 140 | //{ 141 | // if (ParentEffect->CachedEffectInstantSpec.Num() > 0) 142 | // { 143 | // for (FEffectInstant& effect : ParentEffect->CachedEffectInstantSpec) 144 | // { 145 | // if (effect.EffectInstant.IsValid()) 146 | // { 147 | // effect.EffectInstant->PreInitialize(); 148 | // effect.EffectInstant->Initialize(); 149 | // OnRecivedEffect.Broadcast(effect.EffectInstant->GetTarget(), effect.EffectInstant->GetClass()); 150 | // } 151 | // } 152 | // return true; 153 | // } 154 | //} 155 | return false; 156 | } 157 | 158 | void URPGAttributeComponent::RemoveEffect(class URPGEffectPeriodic* effectToRemove) 159 | { 160 | if (effectToRemove) 161 | { 162 | effectToRemove->Deinitialize(); //deinitialize effect so it no longer ticks 163 | OnEffectRemoved.Broadcast(effectToRemove->GetTarget(), effectToRemove->GetClass()); 164 | int32 element = PeriodicEffectsList.Find(effectToRemove); 165 | //DestroyEffect(EffectsList[element]); 166 | PeriodicEffectsList.RemoveSingle(effectToRemove); 167 | } 168 | } 169 | 170 | //void URPGAttributeComponent::DestroyEffect(class URPGEffectPeriodic* EffectToDestroy) 171 | //{ 172 | // if (EffectToDestroy) 173 | // { 174 | // if (EffectToDestroy->IsValidLowLevel()) 175 | // { 176 | // EffectToDestroy->ConditionalBeginDestroy(); 177 | // EffectToDestroy = NULL; 178 | // } 179 | // } 180 | // GetWorld()->ForceGarbageCollection(true); 181 | //} 182 | 183 | void URPGAttributeComponent::OnEffectAppiledToMe_Implementation() 184 | { 185 | //nothing 186 | } 187 | 188 | UProperty* URPGAttributeComponent::GetAttribute(FName AtributeName, TSubclassOf AttributeClass) 189 | { 190 | /* 191 | if we have already pointer to property 192 | and that property is the same as requested attribute 193 | we just return old pointer. 194 | */ 195 | if (cachedProperty) 196 | { 197 | if (cachedProperty->GetFName() == AtributeName) 198 | { 199 | return cachedProperty; 200 | } 201 | } 202 | if ((!cachedProperty) || cachedProperty) 203 | { 204 | //UProperty* temp = NULL; 205 | cachedProperty = FindFieldChecked(AttributeClass, AtributeName); 206 | //AttributeProp.SetAttribute(cachedProperty; 207 | return cachedProperty; 208 | } 209 | return cachedProperty; 210 | } 211 | 212 | float URPGAttributeComponent::GetNumericValue(FName AttributeName) 213 | { 214 | if (!AttributeName.IsNone()) 215 | { 216 | UNumericProperty* NumericProperty = CastChecked(GetAttribute(AttributeName, this->GetClass())); 217 | void* ValuePtr = NumericProperty->ContainerPtrToValuePtr(this); 218 | float tempVal = 0; 219 | tempVal = NumericProperty->GetFloatingPointPropertyValue(ValuePtr); 220 | return tempVal; 221 | } 222 | return 0; 223 | } 224 | 225 | void URPGAttributeComponent::SetNumericValue(float value, FName AttributeName) 226 | { 227 | if (!AttributeName.IsNone()) 228 | { 229 | UNumericProperty* NumericProperty = CastChecked(GetAttribute(AttributeName, this->GetClass())); 230 | void* ValuePtr = NumericProperty->ContainerPtrToValuePtr(this); 231 | NumericProperty->SetFloatingPointPropertyValue(ValuePtr, value); 232 | OnAttributeChange.Broadcast(AttributeName, value); 233 | } 234 | } 235 | 236 | bool URPGAttributeComponent::IsSmaller(FName AttributeName, float SmallerThan) 237 | { 238 | float tempValue = GetNumericValue(AttributeName); 239 | if (tempValue > SmallerThan) 240 | { 241 | return false; 242 | } 243 | return true; 244 | } 245 | 246 | bool URPGAttributeComponent::IsEqual(FName AttributeName, float EqualValue) 247 | { 248 | float tempValue = GetNumericValue(AttributeName); 249 | if (tempValue == EqualValue) 250 | { 251 | return true; 252 | } 253 | return false; 254 | } 255 | 256 | bool URPGAttributeComponent::Compare(FName AttributeA, FName AttributeB) 257 | { 258 | if (GetNumericValue(AttributeA) > GetNumericValue(AttributeB)) 259 | return true; 260 | 261 | return false; 262 | } 263 | 264 | void URPGAttributeComponent::ChangeAttribute(FName AttributeName, float ModValue, TEnumAsByte OperationType) 265 | { 266 | float AttributeValue = GetNumericValue(AttributeName); 267 | switch (OperationType) 268 | { 269 | case EAttributeOperation::Attribute_Add: 270 | AttributeValue += ModValue; 271 | SetNumericValue(AttributeValue, AttributeName); 272 | return; 273 | case EAttributeOperation::Attribute_Subtract: 274 | AttributeValue -= ModValue; 275 | SetNumericValue(AttributeValue, AttributeName); 276 | return; 277 | case EAttributeOperation::Attribute_Multiply: 278 | AttributeValue *= ModValue; 279 | SetNumericValue(AttributeValue, AttributeName); 280 | return; 281 | case EAttributeOperation::Attribute_Divide: 282 | AttributeValue = (AttributeValue / ModValue); 283 | SetNumericValue(AttributeValue, AttributeName); 284 | return; 285 | case EAttributeOperation::Attribute_Set: 286 | AttributeValue = ModValue; 287 | SetNumericValue(AttributeValue, AttributeName); 288 | return; 289 | default: 290 | return; 291 | } 292 | } 293 | 294 | void URPGAttributeComponent::ModifyAttribute(FModdableAttributes AttributeMod, TEnumAsByte OperationType) 295 | { 296 | float AttributeValue = 0; 297 | AttributeValue = GetNumericValue(AttributeMod.AttributeName); 298 | 299 | switch (OperationType) 300 | { 301 | case EAttributeOperation::Attribute_Add: 302 | AttributeValue += AttributeMod.ModValue; 303 | SetNumericValue(AttributeValue, AttributeMod.AttributeName); 304 | return; 305 | case EAttributeOperation::Attribute_Subtract: 306 | AttributeValue -= AttributeMod.ModValue; 307 | SetNumericValue(AttributeValue, AttributeMod.AttributeName); 308 | return; 309 | case EAttributeOperation::Attribute_Multiply: 310 | AttributeValue *= AttributeMod.ModValue; 311 | SetNumericValue(AttributeValue, AttributeMod.AttributeName); 312 | return; 313 | case EAttributeOperation::Attribute_Divide: 314 | AttributeValue = (AttributeValue / AttributeMod.ModValue); 315 | SetNumericValue(AttributeValue, AttributeMod.AttributeName); 316 | return; 317 | case EAttributeOperation::Attribute_Set: 318 | AttributeValue = AttributeMod.ModValue; 319 | SetNumericValue(AttributeValue, AttributeMod.AttributeName); 320 | return; 321 | default: 322 | return; 323 | } 324 | } 325 | 326 | void URPGAttributeComponent::ModifyAttributeList(TArray Attributes, TEnumAsByte OperationType) 327 | { 328 | if (Attributes.Num() > 0) 329 | { 330 | for (int32 Index = 0; Index < Attributes.Num(); Index++) 331 | { 332 | float AttributeValue = 0; 333 | AttributeValue = GetNumericValue(Attributes[Index].AttributeName); 334 | 335 | switch (OperationType) 336 | { 337 | case EAttributeOperation::Attribute_Add: 338 | AttributeValue += Attributes[Index].ModValue; 339 | SetNumericValue(AttributeValue, Attributes[Index].AttributeName); 340 | break; 341 | case EAttributeOperation::Attribute_Subtract: 342 | AttributeValue -= Attributes[Index].ModValue; 343 | SetNumericValue(AttributeValue, Attributes[Index].AttributeName); 344 | break; 345 | case EAttributeOperation::Attribute_Multiply: 346 | AttributeValue *= Attributes[Index].ModValue; 347 | SetNumericValue(AttributeValue, Attributes[Index].AttributeName); 348 | break; 349 | case EAttributeOperation::Attribute_Divide: 350 | AttributeValue = (AttributeValue / Attributes[Index].ModValue); 351 | SetNumericValue(AttributeValue, Attributes[Index].AttributeName); 352 | break; 353 | case EAttributeOperation::Attribute_Set: 354 | AttributeValue = Attributes[Index].ModValue; 355 | SetNumericValue(AttributeValue, Attributes[Index].AttributeName); 356 | break; 357 | default: 358 | return; 359 | } 360 | } 361 | } 362 | } 363 | 364 | float URPGAttributeComponent::AttributeOperation(FName AttributeName, float Value, TEnumAsByte OperationType) 365 | { 366 | 367 | float AttributeValue = GetNumericValue(AttributeName); 368 | 369 | switch (OperationType) 370 | { 371 | case EAttributeOperation::Attribute_Add: 372 | return AttributeValue += Value; 373 | case EAttributeOperation::Attribute_Subtract: 374 | return AttributeValue -= Value; 375 | case EAttributeOperation::Attribute_Multiply: 376 | return AttributeValue *= Value; 377 | case EAttributeOperation::Attribute_Divide: 378 | return AttributeValue /= Value; 379 | case EAttributeOperation::Attribute_Set: 380 | return AttributeValue = Value; 381 | default: 382 | return 0; 383 | } 384 | } 385 | 386 | TArray URPGAttributeComponent::GetAttributeList() 387 | { 388 | TArray tempAttributes; 389 | 390 | return tempAttributes; 391 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Components/RPGAttributeComponent.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | //#include "RPG.h" 5 | #include "GameplayTagContainer.h" 6 | #include "../Structs/RPGSystemSructs.h" 7 | #include "RPGAttributeComponent.generated.h" 8 | 9 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnRecievedEffect, class AActor*, WhoRecievedEffect, TSubclassOf, Effect); 10 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnAttributeChange, FName, AttributeName, float, NewValue); 11 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnEffectRemoved, class AActor*, EffectTarget, TSubclassOf, Effect); 12 | //DECLARE_DELEGATE_RetVal(URPGPowerBase, FOnNewPowerAdded); 13 | /** 14 | * Idea for this, come from Epic source (you can look it Runtime/Skillsystem). 15 | * It is supposed to completly decouple attributes from actor, and by extensions 16 | * decouple things like Effects, Powers, Deadth from pawn as well. 17 | * all those things should just check if actor have this component. 18 | * if it doesn't they simply ignore actor, as they can't affect it. 19 | * Things to consider: 20 | * Damage handling - I still wan't to make use of Unreal systems. Like TakeDamage, and DamgeType 21 | * I can't see how I could use TakeDamage, without coupling again component to Pawn 22 | * so component will probably need to have it's own Damage handling logic, along with events 23 | * and blueprint functions. 24 | * Damage types can be probably still levelraged, to calculate damage 25 | * but that would mean that all damage types with RPG* would be coupled to this component 26 | * and attributes it contain. Not very flexible system, but greatly simplify design. 27 | * and attributes could be simply modified by modifying this component. 28 | * 29 | * Attributes - should they be hard coded to this component 30 | * or they should be declared as separate class(es) 31 | * and component would only hold array of them. 32 | * 33 | * Should effect compoentn be merged with Attributes ? 34 | * those component are pretty interconnected anyway... 35 | * Effects in the essence, modify attributes 36 | */ 37 | 38 | USTRUCT() 39 | struct FAttributeEffectEvent 40 | { 41 | GENERATED_USTRUCT_BODY() 42 | 43 | UPROPERTY() 44 | AActor* ActorHit; 45 | 46 | UPROPERTY() 47 | TSubclassOf EffectClass; 48 | }; 49 | 50 | USTRUCT() 51 | struct FAttributeRadialEffectEvent 52 | { 53 | GENERATED_USTRUCT_BODY() 54 | 55 | UPROPERTY() 56 | TArray ActorHits; 57 | 58 | UPROPERTY() 59 | TSubclassOf EffectClass; 60 | }; 61 | 62 | UCLASS(meta = (BlueprintSpawnableComponent), hidecategories = (Object, LOD, Lighting, Transform, Sockets, TextureStreaming)) 63 | class URPGAttributeComponent : public UActorComponent 64 | { 65 | GENERATED_UCLASS_BODY() 66 | 67 | virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) OVERRIDE; 68 | virtual void InitializeComponent() OVERRIDE; 69 | virtual void OnRegister() OVERRIDE; 70 | 71 | public: 72 | virtual void TakeDamage(float DamageAmount, FName AttributeName, AActor* CausedBy); 73 | 74 | UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = AttributeEvents) 75 | void OnDamageAppiled(); 76 | 77 | UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category = AttributeEvents) 78 | void OnActorDeath(); 79 | 80 | public: 81 | 82 | UPROPERTY(BlueprintCallable, BlueprintAssignable, Category = "Attributes") 83 | FOnRecievedEffect OnRecivedEffect; 84 | 85 | UPROPERTY(BlueprintCallable, BlueprintAssignable, Category = "Attributes") 86 | FOnAttributeChange OnAttributeChange; 87 | 88 | UPROPERTY(BlueprintCallable, BlueprintAssignable, Category = "Attributes") 89 | FOnEffectRemoved OnEffectRemoved; 90 | 91 | UFUNCTION(BlueprintNativeEvent, Category = "Attributes") 92 | void OnEffectAppiledToMe(); 93 | 94 | UPROPERTY(BlueprintReadWrite, Category = "Effects") 95 | TArray PeriodicEffectsList; 96 | FORCEINLINE TArray GetEffects() { return PeriodicEffectsList; }; 97 | public: 98 | void RemoveEffect(class URPGEffectPeriodic* effectToRemove); 99 | 100 | /* 101 | Periodic Effects 102 | */ 103 | virtual void ApplyPeriodicEffect(class URPGEffectPeriodic* PeriodicEffect); 104 | 105 | /* 106 | Instant Effects 107 | */ 108 | public: 109 | virtual void ApplyInstantEffects(TArray EffectSpec, class URPGEffectPeriodic* ParentEffect); 110 | 111 | virtual void ApplyInstantEffect(FEffectInstant InstantEffectSpec); 112 | 113 | private: 114 | bool CheckParentEffect(class URPGEffectPeriodic* ParentEffect); 115 | 116 | public: 117 | UProperty* GetAttribute(FName AtributeName, TSubclassOf AttributeClass); 118 | 119 | UFUNCTION(BlueprintPure, Category = "Attributes") 120 | float GetNumericValue(FName AttributeName); 121 | 122 | UFUNCTION(BlueprintCallable, Category = "Attributes") 123 | void SetNumericValue(float value, FName AttributeName); 124 | 125 | UFUNCTION(BlueprintCallable, Category = "Attributes") 126 | bool IsSmaller(FName AttributeName, float SmallerThan); 127 | 128 | UFUNCTION(BlueprintCallable, Category = "Attributes") 129 | bool IsEqual(FName AttributeName, float EqualValue); 130 | 131 | /* 132 | Is A > B 133 | */ 134 | UFUNCTION(BlueprintCallable, Category = "Attributes") 135 | bool Compare(FName AttributeA, FName AttributeB); 136 | 137 | UFUNCTION(BlueprintCallable, Category = "Attributes") 138 | void ChangeAttribute(FName AttributeName, float ModValue, TEnumAsByte OperationType); 139 | 140 | UFUNCTION(BlueprintCallable, Category = "Attributes") 141 | void ModifyAttribute(FModdableAttributes AttributeMod, TEnumAsByte OperationType); 142 | 143 | UFUNCTION(BlueprintCallable, Category = "Attributes") 144 | void ModifyAttributeList(TArray Attributes, TEnumAsByte OperationType); 145 | 146 | /* 147 | Doesn't modify attribute. Just find it, add Value and return result for further use. 148 | */ 149 | UFUNCTION(BlueprintCallable, Category = "Attributes") 150 | float AttributeOperation(FName AttributeName, float Value, TEnumAsByte OperationType); 151 | 152 | /* 153 | Get list of attributes along with their values 154 | */ 155 | UFUNCTION(BlueprintCallable, Category = "Attributes") 156 | TArray GetAttributeList(); 157 | 158 | protected: 159 | //void DestroyEffect(class URPGEffectBase* EffectToDestroy); 160 | void SetPeriodicEffect(class URPGEffectPeriodic* newEffect); 161 | 162 | private: 163 | UProperty* cachedProperty; 164 | //void GetOrCreateAttribute(); 165 | }; 166 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectAreaSpread.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | #include "RPG.h" 4 | #include "../Components/RPGAttributeComponent.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "GameplayTagsManager.h" 7 | #include "GameplayTagsModule.h" 8 | #include "RPGEffectAreaSpread.h" 9 | 10 | 11 | URPGEffectAreaSpread::URPGEffectAreaSpread(const class FPostConstructInitializeProperties& PCIP) 12 | : Super(PCIP) 13 | { 14 | 15 | } 16 | 17 | void URPGEffectAreaSpread::PreInitialize() 18 | { 19 | 20 | } 21 | 22 | 23 | //Modifier effect is always initialized. 24 | //Because it's only task is to modify other effects, it doesn't care about actors. 25 | bool URPGEffectAreaSpread::Initialize() 26 | { 27 | IsInitialized = true; 28 | OnEffectAppiled(); 29 | return true; 30 | } 31 | 32 | void URPGEffectAreaSpread::Deinitialize() 33 | { 34 | OnEffectEnd(); 35 | } 36 | 37 | //TArray URPGEffectAreaSpread::SpreadEffect() 38 | //{ 39 | // TArray ActorHits; 40 | // if ((!GetWorld())) 41 | // return ActorHits; 42 | // 43 | // float TargetCounter = 0; 44 | // //EffectSpec.SetEffect(); 45 | // 46 | // FCollisionQueryParams SphereParams(this->GetFName(), false, CausedBy); 47 | // //make sure we have world 48 | // 49 | // TArray Overlaps; 50 | // GetWorld()->OverlapMulti(Overlaps, HitLocation, FQuat::Identity, FCollisionShape::MakeSphere(Radius), SphereParams, FCollisionObjectQueryParams(FCollisionObjectQueryParams::InitType::AllDynamicObjects)); 51 | // 52 | // 53 | // for (FOverlapResult& overlap : Overlaps) 54 | // { 55 | // ActorHits.AddUnique(overlap.GetActor()); 56 | // } 57 | // 58 | // if (ActorHits.Num() > 0) 59 | // { 60 | // int32 TargetCounter = 0; 61 | // if (MaxTargets > TargetCounter) 62 | // { 63 | // TargetCounter++; 64 | // for (AActor* ActorHit : ActorHits) 65 | // { 66 | // URPGAttributeComponent* HitActorAttribute = ActorHit->FindComponentByClass(); 67 | // 68 | // if (HitActorAttribute) 69 | // { 70 | // //EffectToSpread->SetCauser(CausedBy); 71 | // EffectToSpread->SetTarget(ActorHit); 72 | // 73 | // EffectToSpread->PreInitialize(); 74 | // EffectToSpread->Initialize(); 75 | // } 76 | // } 77 | // 78 | // } 79 | // } 80 | // 81 | // return ActorHits; 82 | //} 83 | // 84 | //TArray URPGEffectAreaSpread::SpreadEffectThroughActors(TArray TargetActors) 85 | //{ 86 | // //all actors that have been hit by this spreadl 87 | // TArray TotalActorHits; 88 | // if (!GetWorld()) 89 | // return TotalActorHits; 90 | // 91 | // //EffectSpec.SetEffect(); 92 | // 93 | // 94 | // //make sure we have world 95 | // float TargetCounter = 0; 96 | // for (AActor* SpreadFrom : TargetActors) 97 | // { 98 | // FCollisionQueryParams SphereParams(this->GetFName(), false, SpreadFrom); 99 | // TArray Overlaps; 100 | // GetWorld()->OverlapMulti(Overlaps, SpreadFrom->GetActorLocation(), FQuat::Identity, FCollisionShape::MakeSphere(Radius), SphereParams, FCollisionObjectQueryParams(FCollisionObjectQueryParams::InitType::AllDynamicObjects)); 101 | // 102 | // //actor that have been hit only trough previous actor; 103 | // TArray ActorHits; 104 | // 105 | // for (FOverlapResult& overlap : Overlaps) 106 | // { 107 | // TotalActorHits.AddUnique(overlap.GetActor()); 108 | // ActorHits.AddUnique(overlap.GetActor()); 109 | // } 110 | // 111 | // if (ActorHits.Num() > 0) 112 | // { 113 | // int32 TargetCounter = 0; 114 | // if (MaxTargets > TargetCounter) 115 | // { 116 | // TargetCounter++; 117 | // for (AActor* ActorHit : ActorHits) 118 | // { 119 | // URPGAttributeComponent* HitActorAttribute = ActorHit->FindComponentByClass(); 120 | // 121 | // if (HitActorAttribute) 122 | // { 123 | // //EffectToSpread->SetCauser(CausedBy); 124 | // EffectToSpread->SetTarget(ActorHit); 125 | // 126 | // EffectToSpread->PreInitialize(); 127 | // EffectToSpread->Initialize(); 128 | // } 129 | // } 130 | // 131 | // } 132 | // } 133 | // } 134 | // 135 | // return TotalActorHits; 136 | //} 137 | 138 | UWorld* URPGEffectAreaSpread::GetWorld() const 139 | { 140 | if (EffectToSpread.IsValid()) 141 | { 142 | UWorld* const world = GEngine->GetWorldFromContextObject(EffectToSpread.Get()); 143 | return world ? world : NULL; 144 | } 145 | return NULL; 146 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectAreaSpread.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "GameplayTagContainer.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "RPGEffectBase.h" 7 | #include "RPGEffectUtility.h" 8 | #include "RPGEffectAreaSpread.generated.h" 9 | 10 | UCLASS(Blueprintable, BlueprintType, MinimalAPI) 11 | class URPGEffectAreaSpread : public URPGEffectUtility 12 | { 13 | GENERATED_UCLASS_BODY() 14 | 15 | public: 16 | virtual void PreInitialize() OVERRIDE; 17 | virtual bool Initialize() OVERRIDE; 18 | 19 | virtual void Deinitialize() OVERRIDE; 20 | 21 | TWeakObjectPtr EffectToSpread; 22 | 23 | TArray> EffectsToSpred; 24 | 25 | FVector HitLocation; 26 | 27 | float Radius; 28 | 29 | float MaxTargets; 30 | 31 | //UFUNCTION(BlueprintCallable, Category = "RPG|Effect") 32 | // TArray SpreadEffect(); 33 | 34 | //UFUNCTION(blueprintCallable, Category = "RPG|Effect") 35 | // TArray SpreadEffectThroughActors(TArray TargetActors); 36 | 37 | virtual class UWorld* GetWorld() const OVERRIDE; 38 | }; 39 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectBase.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | #include "RPG.h" 4 | #include "../Components/RPGAttributeComponent.h" 5 | #include "RPGEffectPeriodic.h" 6 | #include "GameplayTagsManager.h" 7 | #include "GameplayTagsModule.h" 8 | #include "RPGEffectBase.h" 9 | 10 | URPGEffectBase::URPGEffectBase(const class FPostConstructInitializeProperties& PCIP) 11 | : Super(PCIP) 12 | { 13 | 14 | } 15 | 16 | 17 | void URPGEffectBase::PreInitialize() 18 | { 19 | 20 | } 21 | 22 | bool URPGEffectBase::Initialize() 23 | { 24 | if (Target) 25 | { 26 | URPGAttributeComponent* attributeComp = Target->FindComponentByClass(); 27 | 28 | URPGAttributeComponent* CausedByAttribute = CausedBy->FindComponentByClass(); 29 | 30 | if (attributeComp && CausedByAttribute) 31 | { 32 | TargetAttributes = attributeComp; 33 | CauserAttributes = CausedByAttribute; 34 | IsInitialized = true; 35 | return true; 36 | } 37 | } 38 | return false; 39 | } 40 | 41 | void URPGEffectBase::Deinitialize() 42 | { 43 | 44 | } 45 | 46 | //void URPGEffectBase::SpreadEffect(URPGEffectBase* EffectToSpread, FVector HitLocation, float Radius, int32 MaxTargets) 47 | //{ 48 | // TArray ActorHits; 49 | // if ((!GetWorld())) 50 | // return;// ActorHits; 51 | // 52 | // float TargetCounter = 0; 53 | // //EffectSpec.SetEffect(); 54 | // 55 | // FCollisionQueryParams SphereParams(this->GetFName(), false, CausedBy); 56 | // //make sure we have world 57 | // 58 | // TArray Overlaps; 59 | // GetWorld()->OverlapMulti(Overlaps, HitLocation, FQuat::Identity, FCollisionShape::MakeSphere(Radius), SphereParams, FCollisionObjectQueryParams(FCollisionObjectQueryParams::InitType::AllDynamicObjects)); 60 | // 61 | // 62 | // for (FOverlapResult& overlap : Overlaps) 63 | // { 64 | // ActorHits.AddUnique(overlap.GetActor()); 65 | // } 66 | // 67 | // if (ActorHits.Num() > 0) 68 | // { 69 | // int32 TargetCounter = 0; 70 | // if (MaxTargets > TargetCounter) 71 | // { 72 | // TargetCounter++; 73 | // for (AActor* ActorHit : ActorHits) 74 | // { 75 | // URPGAttributeComponent* HitActorAttribute = ActorHit->FindComponentByClass(); 76 | // 77 | // if (HitActorAttribute) 78 | // { 79 | // //EffectToSpread->SetCauser(CausedBy); 80 | // EffectToSpread->SetTarget(ActorHit); 81 | // 82 | // EffectToSpread->PreInitialize(); 83 | // EffectToSpread->Initialize(); 84 | // } 85 | // } 86 | // 87 | // } 88 | // } 89 | // 90 | //} 91 | 92 | int32 URPGEffectBase::RemoveEffect(FName Tag, int32 Count, class URPGAttributeComponent* TargetToRemoveEffects) 93 | { 94 | int32 effectCounter = 0; 95 | int32 effectsRemoved = 0; 96 | if (TargetToRemoveEffects) 97 | { 98 | if (TargetToRemoveEffects->GetEffects().Num() > 0) 99 | { 100 | for (auto It = TargetToRemoveEffects->GetEffects().CreateIterator(); It; ++It) 101 | { 102 | if (Count >= effectCounter) 103 | { 104 | //URPGEffectBase* tempEffect = TargetToRemoveEffects->GetEffects()[It.GetIndex()]; 105 | //if (tempEffect->OwnedTags.HasTag(Tag)) 106 | //{ 107 | // tempEffect->SelfRemoveEffect(); 108 | // effectsRemoved++; 109 | //} 110 | effectCounter++; 111 | } 112 | } 113 | } 114 | } 115 | return effectsRemoved; 116 | } 117 | 118 | void URPGEffectBase::ChangeAttribute(TEnumAsByte OperationType) 119 | { 120 | TargetAttributes->ChangeAttribute(AttributeName, AttributeValue, OperationType); 121 | } 122 | 123 | void URPGEffectBase::ApplyToTarget(FAttributeSpec AttributeSpecIn, TEnumAsByte OperationType) 124 | { 125 | for (FModdableAttributes& modAttr : AttributeSpecIn.AttributeModList) 126 | { 127 | TargetAttributes->ModifyAttribute(modAttr, OperationType); 128 | } 129 | } 130 | 131 | void URPGEffectBase::ApplyToTargetList(TArray AttributeMod, TEnumAsByte OperationType) 132 | { 133 | for (FModdableAttributes& modAttr : AttributeMod) 134 | { 135 | TargetAttributes->ModifyAttribute(modAttr, OperationType); 136 | } 137 | } 138 | 139 | TArray URPGEffectBase::ModifyAttribute(TArray AttributeMod, FName AttributeNameIn, float ModifyValue, EAttributeOperation OperationType) 140 | { 141 | for (FModdableAttributes& modAttr : AttributeMod) 142 | { 143 | if (modAttr.AttributeName == AttributeName) 144 | { 145 | modAttr.ModValue = ModifyAttributeSpecHelper(ModifyValue, modAttr.ModValue, OperationType); 146 | } 147 | } 148 | return AttributeMod; 149 | } 150 | 151 | float URPGEffectBase::ModifyAttributeSpecHelper(float AttributeValue, float ModValue, EAttributeOperation OperationType) 152 | { 153 | switch (OperationType) 154 | { 155 | case EAttributeOperation::Attribute_Add: 156 | return AttributeValue += ModValue; 157 | case EAttributeOperation::Attribute_Subtract: 158 | return AttributeValue -= ModValue; 159 | case EAttributeOperation::Attribute_Multiply: 160 | return AttributeValue *= ModValue; 161 | case EAttributeOperation::Attribute_Divide: 162 | return AttributeValue /= ModValue; 163 | case EAttributeOperation::Attribute_Set: 164 | return AttributeValue = ModValue; 165 | default: 166 | return 0; 167 | } 168 | return 0; 169 | } 170 | 171 | float URPGEffectBase::GetTargetAttributeValue(FName AttributeNameIn) 172 | { 173 | return TargetAttributes->GetNumericValue(AttributeNameIn); 174 | } 175 | 176 | float URPGEffectBase::GetCauserAttributeValue(FName AttributeNameIn) 177 | { 178 | return CauserAttributes->GetNumericValue(AttributeNameIn); 179 | } 180 | 181 | TArray < TWeakObjectPtr > URPGEffectBase::GetModificableEffects() 182 | { 183 | TArray < TWeakObjectPtr > tempArray; 184 | 185 | if (TargetAttributes) 186 | { 187 | for (auto It = TargetAttributes->GetEffects().CreateIterator(); It; ++It) 188 | { 189 | //TWeakObjectPtr tempEffect = TargetAttributes->GetEffects()[It.GetIndex()]; 190 | 191 | //if (tempEffect->OwnedTags.HasAnyTag(OwnedTags)) 192 | //{ 193 | // tempArray.Add(tempEffect); 194 | //} 195 | } 196 | return tempArray; 197 | } 198 | 199 | return tempArray; 200 | } 201 | 202 | TArray URPGEffectBase::SpreadEffect(URPGEffectBase* EffectIn, FVector FromLoc, float Radius, int32 MaxTargets) 203 | { 204 | TArray ActorHits; 205 | if ((!GetWorld())) 206 | return ActorHits; 207 | 208 | TWeakObjectPtr PeriodicEffect = Cast(EffectIn); 209 | 210 | float TargetCounter = 0; 211 | //EffectSpec.SetEffect(); 212 | 213 | FCollisionQueryParams SphereParams(this->GetFName(), false, CausedBy); 214 | //make sure we have world 215 | 216 | TArray Overlaps; 217 | GetWorld()->OverlapMulti(Overlaps, FromLoc, FQuat::Identity, FCollisionShape::MakeSphere(Radius), SphereParams, FCollisionObjectQueryParams(FCollisionObjectQueryParams::InitType::AllDynamicObjects)); 218 | 219 | 220 | for (FOverlapResult& overlap : Overlaps) 221 | { 222 | ActorHits.AddUnique(overlap.GetActor()); 223 | } 224 | 225 | if (ActorHits.Num() > 0) 226 | { 227 | int32 TargetCounter = 0; 228 | if (MaxTargets > TargetCounter) 229 | { 230 | TargetCounter++; 231 | for (AActor* ActorHit : ActorHits) 232 | { 233 | URPGAttributeComponent* HitActorAttribute = ActorHit->FindComponentByClass(); 234 | 235 | if (HitActorAttribute) 236 | { 237 | if (PeriodicEffect.IsValid()) 238 | { 239 | PeriodicEffect->SetTarget(ActorHit); 240 | PeriodicEffect->PreInitialize(); 241 | PeriodicEffect->Initialize(); 242 | HitActorAttribute->ApplyPeriodicEffect(PeriodicEffect.Get()); 243 | continue; 244 | } 245 | EffectIn->SetTarget(ActorHit); 246 | 247 | EffectIn->PreInitialize(); 248 | EffectIn->Initialize(); 249 | } 250 | } 251 | 252 | } 253 | } 254 | 255 | return ActorHits; 256 | } 257 | 258 | TArray URPGEffectBase::SpreadEffects(TArray EffectsIn, FVector FromLoc, float Radius, int32 MaxTargets) 259 | { 260 | TArray ActorHits; 261 | if ((!GetWorld())) 262 | return ActorHits; 263 | 264 | //TWeakObjectPtr PeriodicEffect = Cast(EffectIn); 265 | 266 | float TargetCounter = 0; 267 | //EffectSpec.SetEffect(); 268 | 269 | FCollisionQueryParams SphereParams(this->GetFName(), false, CausedBy); 270 | //make sure we have world 271 | 272 | TArray Overlaps; 273 | GetWorld()->OverlapMulti(Overlaps, FromLoc, FQuat::Identity, FCollisionShape::MakeSphere(Radius), SphereParams, FCollisionObjectQueryParams(FCollisionObjectQueryParams::InitType::AllDynamicObjects)); 274 | 275 | 276 | for (FOverlapResult& overlap : Overlaps) 277 | { 278 | ActorHits.AddUnique(overlap.GetActor()); 279 | } 280 | 281 | if (ActorHits.Num() > 0) 282 | { 283 | int32 TargetCounter = 0; 284 | if (MaxTargets > TargetCounter) 285 | { 286 | TargetCounter++; 287 | for (AActor* ActorHit : ActorHits) 288 | { 289 | URPGAttributeComponent* HitActorAttribute = ActorHit->FindComponentByClass(); 290 | 291 | if (HitActorAttribute) 292 | { 293 | for (URPGEffectBase* effect : EffectsIn) 294 | { 295 | TWeakObjectPtr periodicEffect = Cast(effect); 296 | 297 | if (periodicEffect.IsValid()) 298 | { 299 | periodicEffect->SetTarget(ActorHit); 300 | periodicEffect->SetCauser(CausedBy); 301 | periodicEffect->PreInitialize(); 302 | periodicEffect->Initialize(); 303 | 304 | HitActorAttribute->ApplyPeriodicEffect(periodicEffect.Get()); 305 | continue; 306 | } 307 | 308 | 309 | effect->SetTarget(ActorHit); 310 | effect->SetCauser(CausedBy); 311 | effect->PreInitialize(); 312 | effect->Initialize(); 313 | } 314 | } 315 | } 316 | 317 | } 318 | } 319 | 320 | return ActorHits; 321 | } 322 | 323 | UWorld* URPGEffectBase::GetWorld() const 324 | { 325 | if (Target) 326 | { 327 | UWorld* const world = GEngine->GetWorldFromContextObject(Target); 328 | return world ? world : NULL; 329 | } 330 | return NULL; 331 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectBase.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "Object.h" 5 | #include "Tickable.h" 6 | #include "GameplayTagContainer.h" 7 | #include "../Structs/RPGSystemSructs.h" 8 | #include "RPGEffectBase.generated.h" 9 | 10 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnEffectActivation, TSubclassOf, EffectClass, bool, IsEffectActive); 11 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnEffectDeactivation, TSubclassOf, EffectClass, bool, IsEffectActive); 12 | DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnEffectPeriod); 13 | UENUM() 14 | enum EApplicationType 15 | { 16 | InstantApplication, 17 | Periodic, 18 | Infinite 19 | }; 20 | 21 | UENUM() 22 | enum EEffectDuration 23 | { 24 | InfiniteDuration, 25 | Period 26 | }; 27 | 28 | UCLASS(Blueprintable, BlueprintType, MinimalAPI) 29 | class URPGEffectBase : public UObject 30 | { 31 | GENERATED_UCLASS_BODY() 32 | 33 | public: 34 | UPROPERTY(EditAnywhere, Category = "Base Properties") 35 | TEnumAsByte ApplicationType; 36 | 37 | /* 38 | My Tags; 39 | */ 40 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tags") 41 | FGameplayTagContainer OwnedTags; 42 | 43 | /* 44 | Effect that I try to affect must have these tags. 45 | Check modified effect OwnedTags; 46 | */ 47 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tags") 48 | FGameplayTagContainer RequiredTags; 49 | 50 | /* 51 | Effect with those tags should be ignored by this effect 52 | Check modified effect OwnedTags; 53 | */ 54 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tags") 55 | FGameplayTagContainer IgnoredTags; 56 | 57 | UPROPERTY(EditAnywhere, Category = "Effect Type") 58 | TEnumAsByte EffectApplicationType; 59 | 60 | UPROPERTY(BlueprintCallable, BlueprintAssignable, Category = "RPG|Effect") 61 | FOnEffectActivation OnEffectActivation; 62 | 63 | UPROPERTY(BlueprintCallable, BlueprintAssignable, Category = "RPG|Effect") 64 | FOnEffectDeactivation OnEffectDeactivation; 65 | 66 | //make it protected. Later. Maybe. 67 | UPROPERTY(BlueprintReadWrite, Category = "Attributes") 68 | FAttributeSpec AttributeSpec; 69 | 70 | UPROPERTY(BlueprintReadWrite, Category = "Attributes") 71 | TArray AttributesToChange; 72 | 73 | /* 74 | Attributes 75 | */ 76 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes") 77 | FName AttributeName; 78 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes") 79 | float AttributeValue; 80 | 81 | UPROPERTY(BlueprintReadOnly, Category = "Effects") 82 | TArray EffectsToApply; 83 | protected: 84 | /** 85 | Target affected by appiled effect 86 | */ 87 | UPROPERTY(BlueprintReadWrite, Category= "Actors") 88 | AActor* Target; //maybe change it to RPGCharacter ? 89 | 90 | /** 91 | Who appiled effect to target. 92 | */ 93 | UPROPERTY(BlueprintReadWrite, Category= "Actors") 94 | AActor* CausedBy; 95 | 96 | /* 97 | Who originally appiled effect. 98 | */ 99 | UPROPERTY(BlueprintReadOnly, Category = "Actors") 100 | AActor* Instigator; 101 | 102 | UPROPERTY() 103 | bool IsEffectActive; 104 | 105 | UPROPERTY(BlueprintReadOnly, Category="Attributes") 106 | class URPGAttributeComponent* TargetAttributes; 107 | 108 | UPROPERTY(BlueprintReadOnly, Category = "Attributes") 109 | class URPGAttributeComponent* CauserAttributes; 110 | 111 | UPROPERTY() 112 | bool IsInitialized; 113 | 114 | public: 115 | FORCEINLINE void SetTarget(AActor* target) { Target = target; }; 116 | FORCEINLINE AActor* GetTarget() { return Target; }; 117 | 118 | FORCEINLINE void SetCauser(AActor* causer) { CausedBy = causer; }; 119 | FORCEINLINE AActor* GetCausedBy() { return CausedBy; }; 120 | 121 | FORCEINLINE bool GetIsInitialized() { return IsInitialized; }; 122 | 123 | /** 124 | Do preinitialization taks. Like assign tags. 125 | Anything that do not invovlve Target or CausedBy can be setup here. 126 | */ 127 | virtual void PreInitialize(); 128 | virtual bool Initialize(); 129 | 130 | /** 131 | Deinitialaize effect, effecticly setting it all ticking properties to 0 or false 132 | */ 133 | virtual void Deinitialize(); 134 | 135 | /* 136 | Allow to spread another effect from effect in radius around where the effect is active. 137 | Use it instead of static version, for safety and predictable results! 138 | */ 139 | //UFUNCTION(BlueprintCallable, Category = "RPG|Effect") 140 | // void SpreadEffect(URPGEffectBase* EffectToSpread, FVector HitLocation, float Radius, int32 MaxTargets); 141 | /* 142 | Function remove effects as "frist come, first serve" 143 | Return how many effects has been removed; 144 | */ 145 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect") 146 | int32 RemoveEffect(FName Tag, int32 Count, class URPGAttributeComponent* TargetToRemoveEffects); 147 | 148 | public: 149 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect") 150 | void ChangeAttribute(TEnumAsByte OperationType); 151 | 152 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect") 153 | void ApplyToTarget(FAttributeSpec AttributeSpecIn, TEnumAsByte OperationType); 154 | 155 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect") 156 | void ApplyToTargetList(TArray AttributeMod, TEnumAsByte OperationType); 157 | 158 | UFUNCTION(BlueprintPure, Category = "RPG|Effect") 159 | TArray ModifyAttribute(TArray AttributeMod, FName AttributeNameIn, float ModifyValue, EAttributeOperation OperationType); 160 | 161 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect") 162 | TArray SpreadEffect(URPGEffectBase* EffectIn, FVector FromLoc, float Radius, int32 MaxTargets); 163 | 164 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect") 165 | TArray SpreadEffects(TArray EffectsIn, FVector FromLoc, float Radius, int32 MaxTargets); 166 | 167 | /* 168 | Easier access, for polling target attribute. 169 | */ 170 | UFUNCTION(BlueprintPure, Category = "RPG|Effect") 171 | float GetTargetAttributeValue(FName AttributeNameIn); 172 | 173 | UFUNCTION(BlueprintPure, Category = "RPG|Effect") 174 | float GetCauserAttributeValue(FName AttributeNameIn); 175 | 176 | protected: 177 | float ModifyAttributeSpecHelper(float AttributeValue, float ModValue, EAttributeOperation OperationType); 178 | public: 179 | /* 180 | Get Array of effects from target, which Owns any of Required Tags. 181 | These effects can be modified, though dunno how... 182 | */ 183 | TArray < TWeakObjectPtr > GetModificableEffects(); 184 | 185 | UFUNCTION(BlueprintImplementableEvent, Category = "RPG|Effect") 186 | void OnEffectPreInitialized(); 187 | 188 | UFUNCTION(BlueprintImplementableEvent, Category = "RPG|Effect") 189 | void OnEffectInitialized(); 190 | 191 | UFUNCTION(BlueprintImplementableEvent, Category = "RPG|Effect") 192 | void OnEffectPostInitialized(); 193 | 194 | UFUNCTION(BlueprintImplementableEvent, Category = "RPG|Effect") 195 | void OnEffectDeinitialized(); 196 | 197 | UFUNCTION(BlueprintImplementableEvent, Category = "RPG|Effect") 198 | void OnEffectAppiled(); 199 | 200 | UFUNCTION(BlueprintImplementableEvent, Category = "RPG|Effect") 201 | void OnEffectEnd(); 202 | 203 | UFUNCTION(BlueprintImplementableEvent, Category = "RPG|Effect") 204 | void OnEffectPeriod(); 205 | 206 | UFUNCTION(BlueprintImplementableEvent, Category = "RPG|Effect") 207 | void OnValueChanged(); 208 | 209 | UFUNCTION(BlueprintImplementableEvent, Category = "RPG|Effect") 210 | void OnEffectTick(); 211 | 212 | protected: 213 | virtual class UWorld* GetWorld() const OVERRIDE; 214 | }; 215 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectCombat.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | #include "RPG.h" 4 | #include "../Components/RPGAttributeComponent.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "GameplayTagsManager.h" 7 | #include "GameplayTagsModule.h" 8 | #include "RPGEffectCombat.h" 9 | 10 | 11 | URPGEffectCombat::URPGEffectCombat(const class FPostConstructInitializeProperties& PCIP) 12 | : Super(PCIP) 13 | { 14 | 15 | } 16 | 17 | void URPGEffectCombat::PreInitialize() 18 | { 19 | 20 | } 21 | 22 | 23 | //Modifier effect is always initialized. 24 | //Because it's only task is to modify other effects, it doesn't care about actors. 25 | bool URPGEffectCombat::Initialize() 26 | { 27 | return Super::Initialize(); 28 | } 29 | 30 | void URPGEffectCombat::Deinitialize() 31 | { 32 | OnEffectEnd(); 33 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectCombat.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "GameplayTagContainer.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "RPGEffectBase.h" 7 | #include "RPGEffectCombat.generated.h" 8 | 9 | UCLASS(Blueprintable, BlueprintType, MinimalAPI) 10 | class URPGEffectCombat : public URPGEffectBase 11 | { 12 | GENERATED_UCLASS_BODY() 13 | 14 | public: 15 | virtual void PreInitialize() OVERRIDE; 16 | virtual bool Initialize() OVERRIDE; 17 | 18 | virtual void Deinitialize() OVERRIDE; 19 | }; 20 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectInstant.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | #include "RPG.h" 4 | #include "../Components/RPGAttributeComponent.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "GameplayTagsManager.h" 7 | #include "GameplayTagsModule.h" 8 | #include "RPGEffectInstant.h" 9 | 10 | 11 | URPGEffectInstant::URPGEffectInstant(const class FPostConstructInitializeProperties& PCIP) 12 | : Super(PCIP) 13 | { 14 | 15 | } 16 | 17 | void URPGEffectInstant::PreInitialize() 18 | { 19 | 20 | } 21 | 22 | bool URPGEffectInstant::Initialize() 23 | { 24 | if (EffectApplicationType == EEffectApplicationType::Effect_ModEffect) 25 | { 26 | IsInitialized = true; 27 | OnEffectAppiled(); 28 | return true; 29 | } 30 | 31 | Super::Initialize(); 32 | if (Target) 33 | { 34 | OnEffectAppiled(); 35 | 36 | OnEffectActivation.Broadcast(this->GetClass(), IsEffectActive); 37 | 38 | return true; 39 | } 40 | return false; 41 | } 42 | 43 | void URPGEffectInstant::Deinitialize() 44 | { 45 | OnEffectEnd(); 46 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectInstant.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "GameplayTagContainer.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "RPGEffectBase.h" 7 | #include "RPGEffectCombat.h" 8 | #include "RPGEffectInstant.generated.h" 9 | 10 | UCLASS(Blueprintable, BlueprintType, MinimalAPI) 11 | class URPGEffectInstant : public URPGEffectCombat 12 | { 13 | GENERATED_UCLASS_BODY() 14 | 15 | public: 16 | virtual void PreInitialize() OVERRIDE; 17 | virtual bool Initialize() OVERRIDE; 18 | 19 | virtual void Deinitialize() OVERRIDE; 20 | }; 21 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectModifier.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | #include "RPG.h" 4 | #include "../Components/RPGAttributeComponent.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "GameplayTagsManager.h" 7 | #include "GameplayTagsModule.h" 8 | #include "RPGEffectModifier.h" 9 | 10 | 11 | URPGEffectModifier::URPGEffectModifier(const class FPostConstructInitializeProperties& PCIP) 12 | : Super(PCIP) 13 | { 14 | 15 | } 16 | 17 | void URPGEffectModifier::PreInitialize() 18 | { 19 | 20 | } 21 | 22 | 23 | //Modifier effect is always initialized. 24 | //Because it's only task is to modify other effects, it doesn't care about actors. 25 | bool URPGEffectModifier::Initialize() 26 | { 27 | IsInitialized = true; 28 | OnEffectAppiled(); 29 | return true; 30 | } 31 | 32 | void URPGEffectModifier::Deinitialize() 33 | { 34 | OnEffectEnd(); 35 | } 36 | 37 | void URPGEffectModifier::StoreAttributeSpec(TArray ModdableAttributes) 38 | { 39 | AttributesToChange = ModdableAttributes; 40 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectModifier.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "GameplayTagContainer.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "RPGEffectBase.h" 7 | #include "RPGEffectModifier.generated.h" 8 | 9 | UCLASS(Blueprintable, BlueprintType, MinimalAPI) 10 | class URPGEffectModifier : public URPGEffectBase 11 | { 12 | GENERATED_UCLASS_BODY() 13 | 14 | public: 15 | virtual void PreInitialize() OVERRIDE; 16 | virtual bool Initialize() OVERRIDE; 17 | 18 | virtual void Deinitialize() OVERRIDE; 19 | 20 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect") 21 | void StoreAttributeSpec(TArray ModdableAttributes); 22 | }; 23 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectPeriodic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | #include "RPG.h" 4 | #include "../Components/RPGAttributeComponent.h" 5 | #include "GameplayTagsManager.h" 6 | #include "GameplayTagsModule.h" 7 | #include "RPGEffectInstant.h" 8 | #include "RPGEffectPeriodic.h" 9 | 10 | URPGEffectPeriodic::URPGEffectPeriodic(const class FPostConstructInitializeProperties& PCIP) 11 | : Super(PCIP) 12 | { 13 | 14 | } 15 | 16 | void URPGEffectPeriodic::Tick(float DeltaTime) 17 | { 18 | currentPeriodTime += DeltaTime; 19 | if (currentPeriodTime >= PeriodLenght) 20 | { 21 | OnEffectPeriodHit.Broadcast(); 22 | OnEffectPeriod(); 23 | currentPeriodTime = 0; 24 | } 25 | //if (ApplicationType != EApplicationType::Infinite) 26 | //{ 27 | CurrentDuration += DeltaTime; 28 | if (CurrentDuration >= TotalDuration) 29 | { 30 | CurrentDuration = 0; 31 | SelfRemoveEffect(); 32 | } 33 | //} 34 | OnEffectTick(); //this will tick every frame. 35 | } 36 | bool URPGEffectPeriodic::IsTickable() const 37 | { 38 | //UWorld* world = GetCurrentWorld(); 39 | if (IsEffectActive) 40 | { 41 | if (Target) 42 | { 43 | if (GetWorld()) 44 | { 45 | return true; 46 | } 47 | return false; 48 | } 49 | return false; 50 | } 51 | return false; 52 | } 53 | 54 | TStatId URPGEffectPeriodic::GetStatId() const 55 | { 56 | return this->GetStatID(); 57 | } 58 | 59 | void URPGEffectPeriodic::PreInitialize() 60 | { 61 | OnEffectPreInitialized(); 62 | } 63 | 64 | bool URPGEffectPeriodic::Initialize() 65 | { 66 | Super::Initialize(); 67 | if (Target) 68 | { 69 | TotalDuration = PeriodLenght * PeriodsCount; 70 | 71 | IsEffectActive = true; 72 | 73 | OnEffectActivation.Broadcast(this->GetClass(), IsEffectActive); 74 | OnEffectAppiled(); 75 | 76 | OnEffectInitialized(); 77 | 78 | OnEffectPostInitialized(); 79 | return true; 80 | } 81 | return false; 82 | } 83 | 84 | void URPGEffectPeriodic::Deinitialize() 85 | { 86 | OnEffectDeinitialized(); 87 | OnEffectEnd(); 88 | IsEffectActive = false; 89 | PeriodLenght = 0; 90 | TotalDuration = 0; 91 | } 92 | 93 | void URPGEffectPeriodic::SelfRemoveEffect() 94 | { 95 | OnEffectEnd(); //we give chance to excute any logic before effect is completly removed 96 | //if (ApplicationType != EApplicationType::InstantApplication) 97 | //{ 98 | TargetAttributes->RemoveEffect(this); 99 | //} 100 | } 101 | 102 | void URPGEffectPeriodic::RunEffects() 103 | { 104 | for (URPGEffectBase* effect : EffectsToApply) 105 | { 106 | effect->PreInitialize(); 107 | effect->Initialize(); 108 | } 109 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectPeriodic.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "Object.h" 5 | #include "Tickable.h" 6 | #include "GameplayTagContainer.h" 7 | #include "../Structs/RPGSystemSructs.h" 8 | #include "RPGEffectBase.h" 9 | #include "RPGEffectCombat.h" 10 | #include "RPGEffectPeriodic.generated.h" 11 | 12 | UCLASS(Blueprintable, BlueprintType, MinimalAPI) 13 | class URPGEffectPeriodic : public URPGEffectCombat, public FTickableGameObject 14 | { 15 | GENERATED_UCLASS_BODY() 16 | 17 | virtual void Tick(float DeltaTime) OVERRIDE; 18 | virtual bool IsTickable() const OVERRIDE; 19 | virtual TStatId GetStatId() const OVERRIDE; 20 | 21 | protected: 22 | 23 | UPROPERTY(BlueprintReadOnly, Category = "RPG|Effect") 24 | float CurrentDuration; 25 | 26 | UPROPERTY(EditAnywhere, Category = "Periodic Effect") 27 | float PeriodLenght; 28 | 29 | UPROPERTY(EditAnywhere, Category = "Periodic Effect") 30 | float PeriodsCount; 31 | 32 | public: 33 | FORCEINLINE void SetPeriodLenght(float value) { PeriodLenght = value; }; 34 | FORCEINLINE void SetPeriodCount(float value) { PeriodsCount = value; }; 35 | 36 | UPROPERTY(EditAnywhere, Category = "Base Properties") 37 | bool StackDuration; 38 | 39 | UPROPERTY() 40 | float TotalDuration; 41 | 42 | UPROPERTY(BlueprintCallable, BlueprintAssignable, Category = "Effect") 43 | FOnEffectPeriod OnEffectPeriodHit; 44 | 45 | private: 46 | float currentPeriodTime; 47 | public: 48 | virtual void PreInitialize() OVERRIDE; 49 | virtual bool Initialize() OVERRIDE; 50 | 51 | virtual void Deinitialize() OVERRIDE; 52 | 53 | /* 54 | Possibly move these up in hierarchy ? 55 | */ 56 | /* 57 | Cache Instant effects to array. Do it before using, 58 | */ 59 | UFUNCTION(BlueprintCallable, Category = "RPG|Effect") 60 | void RunEffects(); 61 | protected: 62 | void SelfRemoveEffect(); 63 | }; 64 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectUtility.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | #pragma once 3 | #include "RPG.h" 4 | #include "../Components/RPGAttributeComponent.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "GameplayTagsManager.h" 7 | #include "GameplayTagsModule.h" 8 | #include "RPGEffectUtility.h" 9 | 10 | 11 | URPGEffectUtility::URPGEffectUtility(const class FPostConstructInitializeProperties& PCIP) 12 | : Super(PCIP) 13 | { 14 | 15 | } 16 | 17 | void URPGEffectUtility::PreInitialize() 18 | { 19 | 20 | } 21 | 22 | 23 | //Modifier effect is always initialized. 24 | //Because it's only task is to modify other effects, it doesn't care about actors. 25 | bool URPGEffectUtility::Initialize() 26 | { 27 | IsInitialized = true; 28 | OnEffectAppiled(); 29 | return true; 30 | } 31 | 32 | void URPGEffectUtility::Deinitialize() 33 | { 34 | OnEffectEnd(); 35 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Effects/RPGEffectUtility.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2013 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "GameplayTagContainer.h" 5 | #include "../Structs/RPGSystemSructs.h" 6 | #include "RPGEffectBase.h" 7 | #include "RPGEffectUtility.generated.h" 8 | 9 | UCLASS(Blueprintable, BlueprintType, MinimalAPI) 10 | class URPGEffectUtility : public URPGEffectBase 11 | { 12 | GENERATED_UCLASS_BODY() 13 | 14 | public: 15 | virtual void PreInitialize() OVERRIDE; 16 | virtual bool Initialize() OVERRIDE; 17 | 18 | virtual void Deinitialize() OVERRIDE; 19 | }; 20 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/RPGAttributeBase.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #include "RPG.h" 4 | #include "RPGAttributeBase.h" 5 | 6 | URPGAttributeBase::URPGAttributeBase(const class FPostConstructInitializeProperties& PCIP) 7 | : Super(PCIP) 8 | { 9 | //InitializeAttributesFromDataTable(); 10 | } 11 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/RPGAttributeBase.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | 5 | #include "RPGAttributeBase.generated.h" 6 | 7 | 8 | UCLASS(BlueprintType, Blueprintable, DefaultToInstanced) 9 | class URPGAttributeBase : public UObject 10 | { 11 | GENERATED_UCLASS_BODY() 12 | 13 | 14 | }; 15 | -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Structs/RPGSystemSructs.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "RPG.h" 5 | #include "GameplayTags.h" 6 | #include "GameplayTagContainer.h" 7 | #include "../Effects/RPGEffectBase.h" 8 | #include "../Effects/RPGEffectInstant.h" 9 | #include "../Effects/RPGEffectPeriodic.h" 10 | #include "../Effects/RPGEffectModifier.h" 11 | #include "RPGSystemSructs.h" 12 | 13 | 14 | FAttributeSpec& FAttributeSpec::operator=(FAttributeSpec const& Other) 15 | { 16 | if (this == &Other) 17 | { 18 | return *this; 19 | } 20 | AttributeModList = Other.AttributeModList; 21 | OwnedTags.Tags = Other.OwnedTags.Tags; 22 | RequiredTags.Tags = Other.OwnedTags.Tags; 23 | return *this; 24 | } 25 | 26 | void FEffectModifier::InitializeModifierEffect() 27 | { 28 | if (ModifierEffect.IsValid()) 29 | return; 30 | 31 | if (ModifierEffectClass) 32 | { 33 | ModifierEffect = ConstructObject(ModifierEffectClass); 34 | } 35 | } 36 | 37 | bool FEffectModifier::operator==(const FEffectModifier & spec) const 38 | { 39 | return ModifierEffect == spec.ModifierEffect; 40 | } 41 | 42 | void FEffectInstant::InitializeInstantEffect(AActor* Target, AActor* CausedBy) 43 | { 44 | if (EffectInstant.IsValid()) 45 | return; 46 | 47 | if (EffectInstantClass) 48 | { 49 | EffectInstant = ConstructObject(EffectInstantClass); 50 | if (EffectInstant.IsValid()) 51 | { 52 | EffectInstant->SetTarget(Target); 53 | EffectInstant->SetCauser(CausedBy); 54 | //EffectInstant->SetAttributeSpecList(AttributeSpecList); 55 | 56 | //Am I sure I want to do it, this way ? 57 | EffectInstant->OwnedTags.AppendTags(OwnedTags); 58 | 59 | } 60 | } 61 | } 62 | 63 | bool FEffectInstant::operator==(const FEffectInstant& spec) const 64 | { 65 | return EffectInstantClass == spec.EffectInstantClass; 66 | } 67 | 68 | void FEffectInstant::SetAttributeSpecFromParent(TArray attrSpec) 69 | { 70 | //AttributeSpecList = attrSpec; 71 | //EffectInstant->SetAttributeSpecList(attrSpec); 72 | } 73 | 74 | void FEffectSpec::ModifyAttributeSpec(FName AttributeName, float ModifyValue, EAttributeOperation OperationType) 75 | { 76 | 77 | } 78 | 79 | void FEffectPeriodic::InitializePeriodicEffect(AActor* Target, AActor* CausedBy) 80 | { 81 | if (EffectPeriod.IsValid()) 82 | return; 83 | 84 | if (EffectPeriodClass) 85 | { 86 | EffectPeriod = ConstructObject(EffectPeriodClass); 87 | if (EffectPeriod.IsValid()) 88 | { 89 | EffectPeriod->SetTarget(Target); 90 | EffectPeriod->SetCauser(CausedBy); 91 | 92 | EffectPeriod->SetPeriodLenght(PeriodLenght); 93 | EffectPeriod->SetPeriodCount(PeriodCount); 94 | 95 | //Effect->SetAttributeToModify(AttributeToMod); 96 | //EffectPeriod->SetAttributeSpecList(AttributeSpecList); 97 | 98 | } 99 | } 100 | } 101 | 102 | bool FEffectPeriodic::operator==(const FEffectPeriodic& spec) const 103 | { 104 | return EffectPeriodClass == spec.EffectPeriodClass; 105 | } 106 | 107 | void FEffectCache::CacheInstantEffects(FEffectInstant InstantEffect) 108 | { 109 | InstantEffectsCache.AddUnique(InstantEffect); 110 | } 111 | 112 | void FEffectCache::ModifyCachedInstanEffects(FGameplayTagContainer RequiredTag, FName AttributeName, float ModValue) 113 | { 114 | for (FEffectInstant& effInst : InstantEffectsCache) 115 | { 116 | if (effInst.OwnedTags.HasAnyTag(RequiredTag)) 117 | { 118 | for (FModdableAttributes& modAttr : effInst.EffectInstant->AttributeSpec.AttributeModList) 119 | { 120 | if (modAttr.AttributeName == AttributeName) 121 | { 122 | modAttr.ModValue += ModValue; 123 | } 124 | } 125 | } 126 | } 127 | } 128 | 129 | bool FEffectCache::ApplyCachedInstantEffects(AActor* EffectTarget, AActor* EffectCausedBy) 130 | { 131 | if (InstantEffectsCache.Num() > 0) 132 | { 133 | for (FEffectInstant& instEff : InstantEffectsCache) 134 | { 135 | if (instEff.EffectInstant->EffectApplicationType == EEffectApplicationType::Effect_Target) 136 | { 137 | if (instEff.DoesCauserIsTarget) 138 | { 139 | instEff.EffectInstant->SetCauser(EffectCausedBy); 140 | instEff.EffectInstant->SetTarget(EffectCausedBy); 141 | } 142 | else 143 | { 144 | instEff.EffectInstant->SetCauser(EffectCausedBy); 145 | instEff.EffectInstant->SetTarget(EffectTarget); 146 | } 147 | instEff.EffectInstant->PreInitialize(); 148 | instEff.EffectInstant->Initialize(); 149 | } 150 | } 151 | return true; 152 | } 153 | return false; 154 | } 155 | 156 | float FEffectCache::ModifyAttributeSpecHelper(float AttributeValue, float ModValue, EAttributeOperation OperationType) 157 | { 158 | switch (OperationType) 159 | { 160 | case EAttributeOperation::Attribute_Add: 161 | return AttributeValue += ModValue; 162 | case EAttributeOperation::Attribute_Subtract: 163 | return AttributeValue -= ModValue; 164 | case EAttributeOperation::Attribute_Multiply: 165 | return AttributeValue *= ModValue; 166 | case EAttributeOperation::Attribute_Divide: 167 | return AttributeValue /= ModValue; 168 | case EAttributeOperation::Attribute_Set: 169 | return AttributeValue = ModValue; 170 | default: 171 | return 0; 172 | } 173 | return 0; 174 | } -------------------------------------------------------------------------------- /Source/RPG/RPGSystem/Structs/RPGSystemSructs.h: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #pragma once 4 | #include "GameplayTags.h" 5 | #include "GameplayTagContainer.h" 6 | #include "RPGSystemSructs.generated.h" 7 | 8 | UENUM() 9 | enum EAttributeOperation 10 | { 11 | Attribute_Add, 12 | Attribute_Subtract, 13 | Attribute_Multiply, 14 | Attribute_Divide, 15 | Attribute_Set 16 | }; 17 | 18 | UENUM() 19 | enum EEffectApplicationType 20 | { 21 | Effect_ModEffect, 22 | Effect_Target 23 | }; 24 | 25 | USTRUCT(BlueprintType, Blueprintable) 26 | struct FModdableAttributes 27 | { 28 | GENERATED_USTRUCT_BODY() 29 | 30 | FModdableAttributes() {} 31 | 32 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes") 33 | FName AttributeName; 34 | 35 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes") 36 | float ModValue; 37 | 38 | UPROPERTY(EditAnywhere, Category = "Attributes") 39 | TEnumAsByte AttributeOperation; 40 | 41 | FModdableAttributes& operator=(FModdableAttributes const& modAtr) 42 | { 43 | if (this == &modAtr) 44 | { 45 | return *this; 46 | } 47 | AttributeName = modAtr.AttributeName; 48 | ModValue = modAtr.ModValue; 49 | 50 | return *this; 51 | } 52 | 53 | void operator+=(FModdableAttributes const& modAtr) 54 | { 55 | //if (this == &modAtr) 56 | //{ 57 | // return *this; 58 | //} 59 | ModValue += modAtr.ModValue; 60 | 61 | //return *this; 62 | } 63 | }; 64 | 65 | USTRUCT(BlueprintType, Blueprintable) 66 | struct FAttribute 67 | { 68 | GENERATED_USTRUCT_BODY() 69 | 70 | FAttribute() {} 71 | 72 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attribute") 73 | FName AttributeName; 74 | 75 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attribute") 76 | float AttributeValue; 77 | 78 | FAttribute& operator=(FAttribute const& Other) 79 | { 80 | if (this == &Other) 81 | { 82 | return *this; 83 | } 84 | 85 | AttributeName = Other.AttributeName; 86 | AttributeValue = Other.AttributeValue; 87 | } 88 | 89 | bool operator==(const FAttribute& Other) const 90 | { 91 | return ((AttributeName == Other.AttributeName) && (AttributeValue == Other.AttributeValue)); 92 | } 93 | 94 | void operator+=(FAttribute const& Other) 95 | { 96 | AttributeValue += Other.AttributeValue; 97 | } 98 | }; 99 | 100 | USTRUCT(BlueprintType, Blueprintable) 101 | struct FAttributeSpec 102 | { 103 | GENERATED_USTRUCT_BODY() 104 | 105 | FAttributeSpec() { } 106 | 107 | public: 108 | UPROPERTY(EditAnywhere, Category = "Attribute") 109 | FGameplayTagContainer OwnedTags; 110 | /* 111 | Use this attribute Mod, only with effect that own this tag. 112 | */ 113 | UPROPERTY(EditAnywhere, Category = "Attribute") 114 | FGameplayTagContainer RequiredTags; 115 | 116 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attribute") 117 | TArray AttributeModList; 118 | 119 | FAttributeSpec& operator=(FAttributeSpec const& Other); 120 | 121 | void operator+=(FAttributeSpec const& Other) 122 | { 123 | //if (this == &Other) 124 | //{ 125 | // return *this; 126 | //} 127 | AttributeModList += Other.AttributeModList; 128 | } 129 | 130 | 131 | void SetAttributeSpec(FAttributeSpec const& Other) 132 | { 133 | AttributeModList = Other.AttributeModList; 134 | } 135 | }; 136 | 137 | /* 138 | Select to whom apply effect based on Tags (or something like that). 139 | When we apply sub effects from one master effects, we need a way to automatically determine who will be target. 140 | For example in LifeSteal effect, Heal effect target should to be set LifeStealEffect CausedBy actor. 141 | */ 142 | /* 143 | Add derived struct. Maybe ? That derived struct would contain TSubclassOf or Perdiodic, along with 144 | weak pointer. 145 | Functions that deal with respectable effects would be easier to deal with, and less prone to make any kind of mistake. 146 | */ 147 | /* 148 | Add struct that will hold effects and their tags. Remove tag from effect itself. I think. 149 | */ 150 | USTRUCT(BlueprintType, Blueprintable) 151 | struct FEffectSpec 152 | { 153 | GENERATED_USTRUCT_BODY() 154 | 155 | UPROPERTY(EditAnywhere, Category = "Target") 156 | bool DoesCauserIsTarget; 157 | 158 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Tags") 159 | FGameplayTagContainer OwnedTags; 160 | 161 | void ModifyAttributeSpec(FName AttributeName, float ModifyValue, EAttributeOperation OperationType); 162 | }; 163 | 164 | USTRUCT(BlueprintType, Blueprintable) 165 | struct FEffectModifier : public FEffectSpec 166 | { 167 | GENERATED_USTRUCT_BODY() 168 | 169 | FEffectModifier() 170 | {} 171 | 172 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes") 173 | TSubclassOf ModifierEffectClass; 174 | 175 | UPROPERTY() 176 | TWeakObjectPtr ModifierEffect; 177 | 178 | void InitializeModifierEffect(); 179 | bool operator==(const FEffectModifier & spec) const; 180 | }; 181 | 182 | USTRUCT(BlueprintType, Blueprintable) 183 | struct FEffectInstant : public FEffectSpec 184 | { 185 | GENERATED_USTRUCT_BODY() 186 | 187 | FEffectInstant() 188 | {} 189 | 190 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes") 191 | TSubclassOf EffectInstantClass; 192 | 193 | UPROPERTY() 194 | TWeakObjectPtr EffectInstant; 195 | 196 | void InitializeInstantEffect(AActor* Target, AActor* CausedBy); 197 | void SetAttributeSpecFromParent(TArray attrSpec); 198 | bool operator==(const FEffectInstant & spec) const; 199 | }; 200 | 201 | USTRUCT(BlueprintType, Blueprintable) 202 | struct FEffectPeriodic : public FEffectSpec 203 | { 204 | GENERATED_USTRUCT_BODY() 205 | 206 | FEffectPeriodic() 207 | {} 208 | 209 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Attributes") 210 | TSubclassOf EffectPeriodClass; 211 | 212 | TWeakObjectPtr EffectPeriod; 213 | 214 | UPROPERTY(EditAnywhere, Category = "Duration") 215 | float PeriodLenght; 216 | 217 | UPROPERTY(EditAnywhere, Category = "Duration") 218 | float PeriodCount; 219 | 220 | /* 221 | Effects that going to be automatically cached and appiled by owning periodic effect. 222 | Specified in EffectPeriodClass. 223 | How these effects are appiled is up to effect implementation. 224 | */ 225 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Instant Effects") 226 | TArray InstantEffectsToApply; 227 | 228 | void InitializePeriodicEffect(AActor* Target, AActor* CausedBy); 229 | 230 | bool operator==(const FEffectPeriodic& spec) const; 231 | }; 232 | 233 | USTRUCT() 234 | struct FEffectCache 235 | { 236 | GENERATED_USTRUCT_BODY() 237 | 238 | UPROPERTY() 239 | TArray InstantEffectsCache; 240 | 241 | UPROPERTY() 242 | TArray PeriodicEffectsCache; 243 | 244 | void CacheInstantEffects(FEffectInstant InstantEffect); 245 | 246 | void ModifyCachedInstanEffects(FGameplayTagContainer RequiredTag, FName AttributeName, float ModValue); 247 | 248 | bool ApplyCachedInstantEffects(AActor* EffectTarget, AActor* EffectCausedBy); 249 | 250 | private: 251 | float ModifyAttributeSpecHelper(float AttributeValue, float ModValue, EAttributeOperation OperationType); 252 | }; 253 | 254 | USTRUCT(BlueprintType, Blueprintable) 255 | struct FEffectInfo 256 | { 257 | GENERATED_USTRUCT_BODY() 258 | 259 | /* 260 | My Tags; 261 | */ 262 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tags") 263 | FGameplayTagContainer OwnedTags; 264 | 265 | /* 266 | Effect that I try to affect must have these tags. 267 | Check modified effect OwnedTags; 268 | */ 269 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tags") 270 | FGameplayTagContainer RequiredTags; 271 | 272 | /* 273 | Effect with those tags should be ignored by this effect 274 | Check modified effect OwnedTags; 275 | */ 276 | UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Tags") 277 | FGameplayTagContainer IgnoredTags; 278 | 279 | }; -------------------------------------------------------------------------------- /Source/RPG/Resources/Windows/RPG.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iniside/RPGFramework/72c83cd9a814ac18b19cfaa7fadbee88417f64e3/Source/RPG/Resources/Windows/RPG.ico -------------------------------------------------------------------------------- /Source/RPG/Resources/Windows/RPG.rc: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | #define XSTR(s) #s 4 | #define STRINGIFY(s) XSTR(s) 5 | 6 | #define APSTUDIO_READONLY_SYMBOLS 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // 9 | // Generated from the TEXTINCLUDE 2 resource. 10 | // 11 | #include 12 | #include "Runtime/Launch/Resources/Version.h" 13 | 14 | ///////////////////////////////////////////////////////////////////////////// 15 | #undef APSTUDIO_READONLY_SYMBOLS 16 | 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | // English (U.S.) resources 20 | 21 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 22 | #ifdef _WIN32 23 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 24 | #pragma code_page(1252) 25 | #endif //_WIN32 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | // 29 | // Version 30 | // 31 | 32 | VS_VERSION_INFO VERSIONINFO 33 | FILEVERSION ENGINE_MAJOR_VERSION,ENGINE_MINOR_VERSION,ENGINE_PATCH_VERSION,0 34 | PRODUCTVERSION ENGINE_MAJOR_VERSION,ENGINE_MINOR_VERSION,ENGINE_PATCH_VERSION,0 35 | FILEFLAGSMASK 0x17L 36 | #ifdef _DEBUG 37 | FILEFLAGS 0x1L 38 | #else 39 | FILEFLAGS 0x0L 40 | #endif 41 | FILEOS 0x4L 42 | FILETYPE 0x2L 43 | FILESUBTYPE 0x0L 44 | BEGIN 45 | BLOCK "StringFileInfo" 46 | BEGIN 47 | BLOCK "040904b0" 48 | BEGIN 49 | VALUE "CompanyName", EPIC_COMPANY_NAME 50 | VALUE "LegalCopyright", EPIC_COPYRIGHT_STRING 51 | VALUE "ProductName", EPIC_PRODUCT_NAME 52 | VALUE "ProductVersion", ENGINE_VERSION_STRING 53 | VALUE "FileDescription", "RPG" 54 | VALUE "InternalName", "RPG" 55 | VALUE "OriginalFilename", "RPG.exe" 56 | END 57 | END 58 | BLOCK "VarFileInfo" 59 | BEGIN 60 | VALUE "Translation", 0x409, 1200 61 | END 62 | END 63 | 64 | ///////////////////////////////////////////////////////////////////////////// 65 | // 66 | // Icon 67 | // 68 | 69 | // Icon with lowest ID value placed first to ensure application icon 70 | // remains consistent on all systems. 71 | IDICON_UE4Game ICON "RPG.ico" 72 | 73 | #endif // English (U.S.) resources 74 | ///////////////////////////////////////////////////////////////////////////// 75 | 76 | 77 | 78 | //#ifndef APSTUDIO_INVOKED 79 | ///////////////////////////////////////////////////////////////////////////// 80 | // 81 | // Generated from the TEXTINCLUDE 3 resource. 82 | // 83 | 84 | 85 | ///////////////////////////////////////////////////////////////////////////// 86 | //#endif // not APSTUDIO_INVOKED 87 | -------------------------------------------------------------------------------- /Source/RPGEditor.Target.cs: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved. 2 | 3 | using UnrealBuildTool; 4 | using System.Collections.Generic; 5 | 6 | public class RPGEditorTarget : TargetRules 7 | { 8 | public RPGEditorTarget(TargetInfo Target) 9 | { 10 | Type = TargetType.Editor; 11 | } 12 | 13 | // 14 | // TargetRules interface. 15 | // 16 | 17 | public override void SetupBinaries( 18 | TargetInfo Target, 19 | ref List OutBuildBinaryConfigurations, 20 | ref List OutExtraModuleNames 21 | ) 22 | { 23 | OutExtraModuleNames.Add("RPG"); 24 | } 25 | } 26 | --------------------------------------------------------------------------------