diff --git a/KOFForever/Config/DefaultEngine.ini b/KOFForever/Config/DefaultEngine.ini index 7bc5b44..6a7e927 100644 --- a/KOFForever/Config/DefaultEngine.ini +++ b/KOFForever/Config/DefaultEngine.ini @@ -36,7 +36,8 @@ r.Editor.SkipSourceControlCheckForEditablePackages = 1 [/Script/Engine.RendererSettings] r.DefaultFeature.AntiAliasing=0 - +r.DefaultFeature.AutoExposure=False +r.DefaultFeature.MotionBlur=False [CoreRedirects] +ClassRedirects=(OldName="/Script/KOFForever.KOFRenderableCharacter",NewName="/Script/KOFForever.KOFBaseCharacter") diff --git a/KOFForever/Config/DefaultGame.ini b/KOFForever/Config/DefaultGame.ini index 8970cc2..a318baa 100644 --- a/KOFForever/Config/DefaultGame.ini +++ b/KOFForever/Config/DefaultGame.ini @@ -9,7 +9,6 @@ SupportContact=kevinporetti@gmail.com CopyrightNotice=A fan game by poret. This game is not affiliated with SNK. This is a fan game which is not being sold or distributed for profit. ProjectDisplayedTitle=NSLOCTEXT("[/Script/EngineSettings]", "F64B16CA410C5695462A51B3C0F03C9C", "{GameName}-{PlatformArchitecture}") ProjectDebugTitleInfo=NSLOCTEXT("[/Script/EngineSettings]", "C2DB330840BAEB6B6D05629B908D8ADD", "{GameName}-{PlatformArchitecture}") -LicensingTerms= [StartupActions] bAddPacks=True diff --git a/KOFForever/Content/Characters/Terry/BP_Terry.uasset b/KOFForever/Content/Characters/Terry/BP_Terry.uasset index db2fc35..9cd6cdb 100644 --- a/KOFForever/Content/Characters/Terry/BP_Terry.uasset +++ b/KOFForever/Content/Characters/Terry/BP_Terry.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57c0b34510c384e3b438b2ad767b822d84c795b7cf5dafa416d333acacc56d52 -size 22440 +oid sha256:63392ea849346fd0c7a7b2392fc705d591d84ded3e2f1543114bcf08641f575f +size 23904 diff --git a/KOFForever/Content/Characters/Terry/BP_Terry_DEPRECATED.uasset b/KOFForever/Content/Characters/Terry/BP_Terry_DEPRECATED.uasset deleted file mode 100644 index d9d17ec..0000000 --- a/KOFForever/Content/Characters/Terry/BP_Terry_DEPRECATED.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dce8bb7e9a7593962050508b0656e7766a0064caf13ff17422a0b456e4823e9e -size 23101 diff --git a/KOFForever/Content/Characters/Terry/Sprites/JumpBack/JumpBack1.uasset b/KOFForever/Content/Characters/Terry/Sprites/JumpBack/JumpBack1.uasset new file mode 100644 index 0000000..22a3ee2 --- /dev/null +++ b/KOFForever/Content/Characters/Terry/Sprites/JumpBack/JumpBack1.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88748c0c8d4017a92d214997680bb1bc929194354521f01972d7b6934b8b6d75 +size 17386 diff --git a/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral.uasset b/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral.uasset new file mode 100644 index 0000000..034fa94 --- /dev/null +++ b/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5720db06075ab380c717a2176c0deae8700b338336d0198105df40b08ac1a341 +size 13962 diff --git a/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral1.uasset b/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral1.uasset new file mode 100644 index 0000000..646ac0d --- /dev/null +++ b/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral1.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52e9d03acf3bc1b163b7c78e142cf4174304f083e8469e8dfcdfea0134eea856 +size 17084 diff --git a/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral2.uasset b/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral2.uasset new file mode 100644 index 0000000..3cc1c53 --- /dev/null +++ b/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral2.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7e72ba0cbb10b8095ea349bdbb34a5b5883da4e3fa0b0e84467c80f367cd66b +size 17103 diff --git a/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral3.uasset b/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral3.uasset new file mode 100644 index 0000000..1dcf8d6 --- /dev/null +++ b/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral3.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4b738ca68a50c34e750f5ad7163ee50a0c7b9e41366dd94b794efd161e7e81e +size 16600 diff --git a/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral4.uasset b/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral4.uasset new file mode 100644 index 0000000..7fdd1d1 --- /dev/null +++ b/KOFForever/Content/Characters/Terry/Sprites/JumpNeutral/JumpNeutral4.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f43349e63ddefc4171de5bee3fcc96a502e33d202428a7869f8f012ad08705c9 +size 15419 diff --git a/KOFForever/Content/Core/BP_DefaultCamera.uasset b/KOFForever/Content/Core/BP_DefaultCamera.uasset index c408c80..ba4894c 100644 --- a/KOFForever/Content/Core/BP_DefaultCamera.uasset +++ b/KOFForever/Content/Core/BP_DefaultCamera.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6e1ed4c6c619bc2c8705abd07d29328d8d0400e48497b1e96256d9cf2842e94 -size 20151 +oid sha256:fa7e90abd3989e1b1fb613d9b25e83827539290d1574c70ef9d8b3c5539f9d17 +size 21495 diff --git a/KOFForever/Content/Core/BP_MainGameMode.uasset b/KOFForever/Content/Core/BP_MainGameMode.uasset deleted file mode 100644 index 9a086bf..0000000 --- a/KOFForever/Content/Core/BP_MainGameMode.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:dd82cb4b7fb7559ddd0fecc987f5e2195e85b14adb5527e6735513d21925d7a1 -size 18404 diff --git a/KOFForever/Content/Core/BP_MainPlayerController.uasset b/KOFForever/Content/Core/BP_MainPlayerController.uasset deleted file mode 100644 index ef30e07..0000000 --- a/KOFForever/Content/Core/BP_MainPlayerController.uasset +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7748be8db03074d17d76aeba1ec5cc29a671ff5601cb8d31520adabf6373505a -size 31949 diff --git a/KOFForever/Content/Debug/BP_DebugGameMode.uasset b/KOFForever/Content/Debug/BP_DebugGameMode.uasset index 1ba6882..52283aa 100644 --- a/KOFForever/Content/Debug/BP_DebugGameMode.uasset +++ b/KOFForever/Content/Debug/BP_DebugGameMode.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa96cd9ed87d1f614ffbc679c9dff7d18d26f517a3b9509fd41ceed0ef40d4c6 -size 18342 +oid sha256:a0933660b2cccf36cb883ef2aaaa38ca7d270ac5eccd1189b2c947a452519aae +size 27219 diff --git a/KOFForever/Content/Maps/Debug/DebugStage.umap b/KOFForever/Content/Maps/Debug/DebugStage.umap index b3044c1..eee87bf 100644 --- a/KOFForever/Content/Maps/Debug/DebugStage.umap +++ b/KOFForever/Content/Maps/Debug/DebugStage.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6164a19e16259a981fedafa4a58f804c2176e471c90e07947cff26e4179660e8 -size 80135 +oid sha256:f91a9907a5d6105606f82f8440a4c434ed841e33969e1da2d27edc2f312d9221 +size 80097 diff --git a/KOFForever/Content/Maps/TrainingStage/TrainingStage.umap b/KOFForever/Content/Maps/TrainingStage/TrainingStage.umap index 374d5d1..9fb57cd 100644 --- a/KOFForever/Content/Maps/TrainingStage/TrainingStage.umap +++ b/KOFForever/Content/Maps/TrainingStage/TrainingStage.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:511505a8c4e20e5f3b1c82b076b3709b1303075a882e0ed00d876c84bd659560 -size 80603 +oid sha256:f594676b21c7a04e101f509bd9bad5587c23d3f4f2c7f807629bfba738855551 +size 80592 diff --git a/KOFForever/Source/KOFForever/KOFForever.Build.cs b/KOFForever/Source/KOFForever/KOFForever.Build.cs index a496457..8cba65c 100644 --- a/KOFForever/Source/KOFForever/KOFForever.Build.cs +++ b/KOFForever/Source/KOFForever/KOFForever.Build.cs @@ -8,7 +8,6 @@ public class KOFForever : ModuleRules { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; - PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Paper2D", "UnrealEd" }); - PrivateDependencyModuleNames.AddRange( new string [] {"FixedPointMath"}); + PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "Paper2D", "UnrealEd", "FixedPointMath" }); } } diff --git a/KOFForever/Source/KOFForever/Private/Camera/KOFDefaultCamera.cpp b/KOFForever/Source/KOFForever/Private/Camera/KOFDefaultCamera.cpp index 69328d1..9e5193e 100644 --- a/KOFForever/Source/KOFForever/Private/Camera/KOFDefaultCamera.cpp +++ b/KOFForever/Source/KOFForever/Private/Camera/KOFDefaultCamera.cpp @@ -4,8 +4,8 @@ #include "DrawDebugHelpers.h" #include "Camera/CameraComponent.h" -#include "Character/KOFBaseCharacter_DEPRECATED.h" -#include "GameModes/KOFDefaultGameMode.h" +#include "Character/KOFBaseCharacter.h" +#include "Game/KOFDefaultGameMode.h" #include "Kismet/GameplayStatics.h" AKOFDefaultCamera::AKOFDefaultCamera() @@ -16,7 +16,7 @@ AKOFDefaultCamera::AKOFDefaultCamera() MaxFOV = 85.0f; GetCameraComponent()->SetFieldOfView(MinFOV); - HeightOffset = 60.0f; + HeightOffset = 160.0f; ZAveragingFactor = 2.0f; MovementYDistanceThreshold = 500.0f; @@ -32,8 +32,8 @@ void AKOFDefaultCamera::Tick(float DeltaSeconds) if(GameMode) { - AKOFBaseCharacter_DEPRECATED* P1 = GameMode->GetP1CurrentCharacter(); - AKOFBaseCharacter_DEPRECATED* P2 = GameMode->GetP2CurrentCharacter(); + AKOFBaseCharacter* P1 = GameMode->GetP1CurrentCharacter(); + AKOFBaseCharacter* P2 = GameMode->GetP2CurrentCharacter(); check(P1); check(P2); @@ -42,7 +42,7 @@ void AKOFDefaultCamera::Tick(float DeltaSeconds) FVector P2Loc = P2->GetActorLocation(); FVector CameraLoc = GetActorLocation(); - float HalfStageLength = GameMode->GetStageLength() / 2.0f; + float HalfStageLength = float(GameMode->GetStageLength()) / 2.0f; FVector MidPoint = FVector(CameraLoc.X, FMath::Clamp((P1Loc.Y + P2Loc.Y) / 2.0f, -HalfStageLength, HalfStageLength), ((P1Loc.Z + P2Loc.Z) / ZAveragingFactor) + HeightOffset); SetActorLocation(MidPoint); @@ -58,8 +58,8 @@ void AKOFDefaultCamera::UpdateCamera() if(GameMode) { - AKOFBaseCharacter_DEPRECATED* P1 = GameMode->GetP1CurrentCharacter(); - AKOFBaseCharacter_DEPRECATED* P2 = GameMode->GetP2CurrentCharacter(); + AKOFBaseCharacter* P1 = GameMode->GetP1CurrentCharacter(); + AKOFBaseCharacter* P2 = GameMode->GetP2CurrentCharacter(); FVector P1Loc = P1->GetActorLocation(); FVector P2Loc = P2->GetActorLocation(); diff --git a/KOFForever/Source/KOFForever/Private/Character/KOFBaseCharacter.cpp b/KOFForever/Source/KOFForever/Private/Character/KOFBaseCharacter.cpp index d46ebc8..5ce62f1 100644 --- a/KOFForever/Source/KOFForever/Private/Character/KOFBaseCharacter.cpp +++ b/KOFForever/Source/KOFForever/Private/Character/KOFBaseCharacter.cpp @@ -1,11 +1,11 @@ // A fan game by poret. This game is not affiliated with SNK. This is a fan game which is not being sold or distributed for profit. +#include "Character/KOFBaseCharacter.h" #include "Character/KOFBaseCharacter.h" -#include "PaperFlipbookComponent.h" #include "Components/InputComponent.h" -#include "KOFForever/KOFTypes.h" +#include "Game/KOFDefaultGameMode.h" // Sets default values AKOFBaseCharacter::AKOFBaseCharacter() @@ -33,17 +33,78 @@ AKOFBaseCharacter::AKOFBaseCharacter() Shadow->bOwnerNoSee = false; Shadow->bAffectDynamicIndirectLighting = true; Shadow->SetupAttachment(Sprite); - //Shadow->SetRelativeLocation(FVector(0.0f, 0.0f, -96.0f)); - Shadow->SetRelativeScale3D(FVector(1.0f, 1.0f, -0.3f)); - Shadow->SetSpriteColor(FLinearColor::Black); + Shadow->SetRelativeLocation(FVector(0.0f, 0.0f, 5.0f)); + Shadow->SetRelativeRotation(FRotator(90.0f, 0.0f, 0.0f)); + Shadow->SetRelativeScale3D(FVector(1.0f, 1.0f, 1.0f)); + Shadow->SetSpriteColor(FColor(0.0f, 0.0f, 0.0f, 128)); } - MaxWalkSpeed = 400; + MaxWalkSpeed = 300; + GravityScale = 2; + VerticalNormalJumpVelocity = 1000; + HorizontalNormalJumpVelocity = MaxWalkSpeed; + /* + VerticalSuperJumpVelocity = 2000; + VerticalNormalHopVelocity = 1000; + VerticalSuperHopVelocity; + HorizontalSuperJumpVelocity; + HorizontalNormalHopVelocity; + HorizontalSuperHopVelocity; + */ + bIsInAir = false; + bIsPossessedByPlayer1; } -void AKOFBaseCharacter::SetPosition(FFixedVector Param) +void AKOFBaseCharacter::Init() { - Position = Param; + Position = FFixedVector(0, bIsPossessedByPlayer1 ? -GameMode->GetStartY() : GameMode->GetStartY(), 0); + SetActorLocation(FVector(Position)); + // eventually character will have a forward and actor rotation will be derived from that + SetActorRotation(FRotator(0.0f, bIsPossessedByPlayer1 ? 90.0f : -90.0f, 0.0f)); + //Shadow->SetRelativeRotation(FRotator(bIsPossessedByPlayer1 ? 90.0f : -90.0f, 0.0f, 0.0f)); +} + +UPaperFlipbook* AKOFBaseCharacter::GetAnimation(FName Key) +{ + return Animations.Contains(Key) ? Animations[Key] : nullptr; +} + +void AKOFBaseCharacter::UpdateAnimation() +{ + // rendering + if(!bIsInAir) + { + if(Direction > 0) + { + SetAnimationFlipbook("WALK_FWD"); + } + else if (Direction < 0) + { + SetAnimationFlipbook("WALK_BACK"); + } + else + { + SetAnimationFlipbook("IDLE"); + } + } + else + { + SetAnimationFlipbook("JUMP_NEUTRAL"); + } +} + +void AKOFBaseCharacter::SetAnimationFlipbook(FName AnimName) +{ + UPaperFlipbook* Anim = GetAnimation(AnimName); + if(Anim) + { + Sprite->SetFlipbook(Anim); + Shadow->SetFlipbook(Anim); + } + else + { + UE_LOG(LogTemp, Error, TEXT("AKOFBaseCharacter::SetAnimationFlipbook - tried to set character animation to %s but the flipbook has not been set for this state."), *AnimName.ToString()); + } } void AKOFBaseCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) @@ -60,17 +121,12 @@ void AKOFBaseCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputCo void AKOFBaseCharacter::ProcessInputs(EVirtualGamePadButton Button) { - /* switch(Button) { - case EVirtualGamePadButton::VGP_Left: - Position = FFixedVector(0, -250, 0); - break; - case EVirtualGamePadButton::VGP_Right: - Position = FFixedVector(0, 250, 0); + case EVirtualGamePadButton::VGP_Up: + Jump(); break; } - */ } void AKOFBaseCharacter::RegisterInput(FName ActionName, EVirtualGamePadButton Button) @@ -92,8 +148,42 @@ void AKOFBaseCharacter::MoveRight(float Axis) void AKOFBaseCharacter::UpdateMovement(FFixed DeltaTime) { - FFixedVector Velocity = FFixedVector(0, Direction * MaxWalkSpeed, 0); + // should have game mode + check(GameMode); + + if(!bIsInAir) // apply walking movement + { + Velocity.Y = Direction * MaxWalkSpeed; + } + else // apply gravity + { + // I keep getting confused with Z being vertical and Y being horizontal + Velocity.Z -= (GameMode->GetGravity() * GravityScale) * DeltaTime; + } + Position += Velocity * DeltaTime; + // clamp + FFixed AdjustedZ = FFixedMath::Clamp(Position.Z, 0, 10000); + FFixed HalfStageLength = GameMode->GetStageLength()/2; + FFixed AdjustedY = FFixedMath::Clamp(Position.Y, -HalfStageLength, HalfStageLength); + Position = FFixedVector(Position.X, AdjustedY, AdjustedZ); + + if(Position.Z <= 0) // hmmmmmmmmmmmmmmm + { + bIsInAir = false; + } +} + +void AKOFBaseCharacter::Jump() +{ + // can't jump if already airborne + if(bIsInAir) + { + return; + } + + Velocity = FFixedVector(0, HorizontalNormalJumpVelocity * Direction, VerticalNormalJumpVelocity); + bIsInAir = true; } // Called when the game starts or when spawned @@ -101,8 +191,10 @@ void AKOFBaseCharacter::BeginPlay() { Super::BeginPlay(); - SetActorLocation(FVector(Position)); - SetActorRotation(FRotator(0.0f, 90.0f, 0.0f)); + // NOTE(kevin): This will only return the game mode if we are the server. Since this game is local only we should always + // be both server and client + GameMode = Cast(GetWorld()->GetAuthGameMode()); + check(GameMode); } // Called every frame @@ -110,9 +202,11 @@ void AKOFBaseCharacter::Tick(float DeltaTime) { Super::Tick(DeltaTime); + // character logic UpdateMovement(FFixed(DeltaTime)); - - // might need some helpers to convert a FFixedVector to a FVector - SetActorRelativeLocation(FVector(Position)); + + SetActorLocation(FVector(Position)); + Shadow->SetWorldLocation(FVector(float(Position.Z), float(Position.Y), 5.0f)); + UpdateAnimation(); } diff --git a/KOFForever/Source/KOFForever/Private/Character/KOFBaseCharacter_DEPRECATED.cpp b/KOFForever/Source/KOFForever/Private/Character/KOFBaseCharacter_DEPRECATED.cpp deleted file mode 100644 index edd9fcb..0000000 --- a/KOFForever/Source/KOFForever/Private/Character/KOFBaseCharacter_DEPRECATED.cpp +++ /dev/null @@ -1,165 +0,0 @@ -// A fan game by poret. This game is not affiliated with SNK. This is a fan game which is not being sold or distributed for profit. - -#include "Character/KOFBaseCharacter_DEPRECATED.h" - -#include "Camera/CameraComponent.h" -#include "Components/CapsuleComponent.h" -#include "GameFramework/CharacterMovementComponent.h" -#include "GameFramework/SpringArmComponent.h" -#include "PaperFlipbookComponent.h" -#include "Componenets/KOFCharacterMovementComponent.h" -#include "GameModes/KOFDefaultGameMode.h" - -DEFINE_LOG_CATEGORY_STATIC(SideScrollerCharacter, Log, All); - -////////////////////////////////////////////////////////////////////////// -// ASideScroller2DCharacter - -AKOFBaseCharacter_DEPRECATED::AKOFBaseCharacter_DEPRECATED(const FObjectInitializer& ObjectInitializer) - : Super(ObjectInitializer.SetDefaultSubobjectClass(ACharacter::CharacterMovementComponentName)) -{ - // Use only Yaw from the controller and ignore the rest of the rotation. - bUseControllerRotationPitch = false; - bUseControllerRotationYaw = false; - bUseControllerRotationRoll = false; - - // Set the size of our collision capsule. - GetCapsuleComponent()->SetCapsuleHalfHeight(96.0f); - GetCapsuleComponent()->SetCapsuleRadius(40.0f); - - GetCharacterMovement()->bOrientRotationToMovement = false; - - // Configure character movement - GetCharacterMovement()->GravityScale = 2.0f; - GetCharacterMovement()->AirControl = 0.0f; - GetCharacterMovement()->JumpZVelocity = 1000.f; - GetCharacterMovement()->GroundFriction = 3.0f; - GetCharacterMovement()->MaxWalkSpeed = 600.0f; - GetCharacterMovement()->MaxFlySpeed = 600.0f; - - // Lock character motion onto the XZ plane, so the character can't move in or out of the screen - GetCharacterMovement()->bConstrainToPlane = true; - GetCharacterMovement()->SetPlaneConstraintNormal(FVector(1.0, 0.0f, 0.0f)); - - // Behave like a traditional 2D platformer character, with a flat bottom instead of a curved capsule bottom - // Note: This can cause a little floating when going up inclines; you can choose the tradeoff between better - // behavior on the edge of a ledge versus inclines by setting this to true or false - GetCharacterMovement()->bUseFlatBaseForFloorChecks = true; - - // TextComponent = CreateDefaultSubobject(TEXT("IncarGear")); - // TextComponent->SetRelativeScale3D(FVector(3.0f, 3.0f, 3.0f)); - // TextComponent->SetRelativeLocation(FVector(35.0f, 5.0f, 20.0f)); - // TextComponent->SetRelativeRotation(FRotator(0.0f, 90.0f, 0.0f)); - // TextComponent->SetupAttachment(RootComponent); - - // Enable replication on the Sprite component so animations show up when networked - GetSprite()->SetIsReplicated(true); - GetSprite()->SetRelativeLocation(FVector(0.0f, 0.0f, -96.0f)); - bReplicates = true; - - // Try to create the sprite component - Shadow = CreateOptionalDefaultSubobject(TEXT("Shadow")); - if (Shadow) - { - Shadow->AlwaysLoadOnClient = true; - Shadow->AlwaysLoadOnServer = true; - Shadow->bOwnerNoSee = false; - Shadow->bAffectDynamicIndirectLighting = true; - Shadow->PrimaryComponentTick.TickGroup = TG_PrePhysics; - Shadow->SetupAttachment(GetCapsuleComponent()); - Shadow->SetRelativeLocation(FVector(0.0f, 0.0f, -96.0f)); - Shadow->SetRelativeScale3D(FVector(1.0f, 1.0f, -0.3f)); - Shadow->SetSpriteColor(FLinearColor::Black); - Shadow->SetTranslucentSortPriority(1000); - } -} - -////////////////////////////////////////////////////////////////////////// -// Animation - -void AKOFBaseCharacter_DEPRECATED::UpdateAnimation() -{ - const FVector PlayerVelocity = GetVelocity(); - const float PlayerSpeedSqr = PlayerVelocity.SizeSquared(); - const float TravelDirection = PlayerVelocity.Y; - - // Are we moving or standing still? - UPaperFlipbook* DesiredAnimation = IdleAnimation; - if(PlayerSpeedSqr > 0.0f) - { - if (TravelDirection > 0.0f) - { - DesiredAnimation = WalkFwdAnimation; - } - else if (TravelDirection < 0.0f) - { - DesiredAnimation = WalkBackAnimation; - } - } - - if( GetSprite()->GetFlipbook() != DesiredAnimation ) - { - GetSprite()->SetFlipbook(DesiredAnimation); - Shadow->SetFlipbook(DesiredAnimation); - } -} - -void AKOFBaseCharacter_DEPRECATED::Tick(float DeltaSeconds) -{ - Super::Tick(DeltaSeconds); - - UpdateCharacter(); -} - -void AKOFBaseCharacter_DEPRECATED::BeginPlay() -{ - Super::BeginPlay(); - - if(Controller) - { - Controller->SetControlRotation(FRotator(0.0f, -90.0f, 0.0)); - } -} - -void AKOFBaseCharacter_DEPRECATED::PostInitializeComponents() -{ - Super::PostInitializeComponents(); - - if (!IsPendingKill()) - { - if (Shadow) - { - // force animation tick after movement component updates - if (Shadow->PrimaryComponentTick.bCanEverTick && GetCharacterMovement()) - { - Shadow->PrimaryComponentTick.AddPrerequisite(GetCharacterMovement(), GetCharacterMovement()->PrimaryComponentTick); - } - } - } -} - -////////////////////////////////////////////////////////////////////////// -// Input - -void AKOFBaseCharacter_DEPRECATED::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) -{ - // Note: the 'Jump' action and the 'MoveRight' axis are bound to actual keys/buttons/sticks in DefaultInput.ini (editable from Project Settings..Input) - PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump); - PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping); - PlayerInputComponent->BindAxis("MoveRight", this, &AKOFBaseCharacter_DEPRECATED::MoveRight); -} - -void AKOFBaseCharacter_DEPRECATED::MoveRight(float Value) -{ - /*UpdateChar();*/ - - // Apply the input to the character motion - AddMovementInput(FVector(0.0f, 1.0f, 0.0f), Value); -} - -void AKOFBaseCharacter_DEPRECATED::UpdateCharacter() -{ - // Update animation to match the motion - UpdateAnimation(); -} - \ No newline at end of file diff --git a/KOFForever/Source/KOFForever/Private/Componenets/KOFCharacterMovementComponent.cpp b/KOFForever/Source/KOFForever/Private/Componenets/KOFCharacterMovementComponent.cpp deleted file mode 100644 index d2f96fb..0000000 --- a/KOFForever/Source/KOFForever/Private/Componenets/KOFCharacterMovementComponent.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// A fan game by poret. This game is not affiliated with SNK. This is a fan game which is not being sold or distributed for profit. - -#include "Componenets/KOFCharacterMovementComponent.h" - -#include "GameModes/KOFDefaultGameMode.h" - -UKOFCharacterMovementComponent::UKOFCharacterMovementComponent() -{ - PrimaryComponentTick.bCanEverTick = true; -} - -void UKOFCharacterMovementComponent::TickComponent(float DeltaTime, ELevelTick TickType, - FActorComponentTickFunction* ThisTickFunction) -{ - Super::TickComponent(DeltaTime, TickType, ThisTickFunction); - - AKOFBaseCharacter_DEPRECATED* Owner = Cast(GetOwner()); - if(!Owner) - { - UE_LOG(LogTemp, Error, TEXT("AKOFCharacterMovementComponent::PostPhysicsTickComponent - could not get the owner")); - return; - } - - AKOFDefaultGameMode* GameMode = Cast(GetWorld()->GetAuthGameMode()); - if(!GameMode) - { - UE_LOG(LogTemp, Error, TEXT("AKOFCharacterMovementComponent::PostPhysicsTickComponent - could not get the game mode")); - return; - } - - AKOFBaseCharacter_DEPRECATED* Opponent = GameMode->GetCurrentOpponent(Owner->IsPossessedByPlayer1()); - if(Opponent) - { - float HalfYDistance = GameMode->GetMaxAllowedDistanceFromOpponent() / 2.0f; - float YMidpoint = (Owner->GetActorLocation().Y + Opponent->GetActorLocation().Y) / 2.0f; - - float AdjustedY = FMath::Clamp(Owner->GetActorLocation().Y, YMidpoint - HalfYDistance, YMidpoint + HalfYDistance); - - FVector CurrentLoc = Owner->GetActorLocation(); - Owner->SetActorLocation(FVector(CurrentLoc.X, AdjustedY, CurrentLoc.Z)); - } - - // clamp to stage bounds - FVector CurrentLoc = Owner->GetActorLocation(); - float HalfStageLength = GameMode->GetStageLength() / 2.0f; - Owner->SetActorLocation(FVector(CurrentLoc.X, - FMath::Clamp(CurrentLoc.Y, -HalfStageLength, HalfStageLength), - CurrentLoc.Z)); -} diff --git a/KOFForever/Source/KOFForever/Private/Game/KOFDefaultGameMode.cpp b/KOFForever/Source/KOFForever/Private/Game/KOFDefaultGameMode.cpp new file mode 100644 index 0000000..b1c3e06 --- /dev/null +++ b/KOFForever/Source/KOFForever/Private/Game/KOFDefaultGameMode.cpp @@ -0,0 +1,68 @@ +// A fan game by poret. This game is not affiliated with SNK. This is a fan game which is not being sold or distributed for profit. + +#include "Game/KOFDefaultGameMode.h" + +#include "Kismet/GameplayStatics.h" + +AKOFDefaultGameMode::AKOFDefaultGameMode() +{ + NumCharactersPerTeam = 3; + + Gravity = 1000; + MaxAllowedDistanceFromOpponent = 700; + StageLength = 2400; + StartY = 150; +} + +void AKOFDefaultGameMode::InitTeams() +{ + for (TSubclassOf CharacterTemplate : P1TeamTemplate) + { + AKOFBaseCharacter* Temp = GetWorld()->SpawnActor(CharacterTemplate); + Temp->SetIsPossessedByPlayer1(true); + Temp->Init(); + if(Temp) + { + P1Team.Add(Temp); + } + } + + for (TSubclassOf CharacterTemplate : P2TeamTemplate) + { + AKOFBaseCharacter* Temp = GetWorld()->SpawnActor(CharacterTemplate); + Temp->SetIsPossessedByPlayer1(false); + Temp->Init(); + if(Temp) + { + P2Team.Add(Temp); + } + } +} + +void AKOFDefaultGameMode::StartPlay() +{ + Super::StartPlay(); + + InitTeams(); + + // is this the right place to do this? + APlayerController* PC1 = UGameplayStatics::GetPlayerController(GetWorld(), 0); + if(PC1) + { + AKOFBaseCharacter* P1 = GetP1CurrentCharacter(); + if(P1) + { + PC1->Possess(P1); + } + } + + APlayerController* PC2 = UGameplayStatics::GetPlayerController(GetWorld(), 1); + if(PC2) + { + AKOFBaseCharacter* P2 = GetP1CurrentCharacter(); + if(P2) + { + PC2->Possess(P2); + } + } +} diff --git a/KOFForever/Source/KOFForever/Private/GameModes/KOFDefaultGameMode.cpp b/KOFForever/Source/KOFForever/Private/GameModes/KOFDefaultGameMode.cpp deleted file mode 100644 index afb96f7..0000000 --- a/KOFForever/Source/KOFForever/Private/GameModes/KOFDefaultGameMode.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// A fan game by poret. This game is not affiliated with SNK. This is a fan game which is not being sold or distributed for profit. - -#include "GameModes/KOFDefaultGameMode.h" - -#include "Kismet/GameplayStatics.h" - -AKOFDefaultGameMode::AKOFDefaultGameMode() -{ - NumCharactersPerTeam = 3; - - MaxAllowedDistanceFromOpponent = 700.0f; - StageLength = 2400.0f; - StartY = 250.0f; -} - -void AKOFDefaultGameMode::InitTeams() -{ - for (TSubclassOf CharacterTemplate : P1TeamTemplate) - { - AKOFBaseCharacter_DEPRECATED* Temp = GetWorld()->SpawnActor(CharacterTemplate, FVector(0.0f, -StartY, 204.6241f), FRotator(0.0f, 90.0f, 0.0f)); - Temp->SetIsPossesedByPlayer1(true); - if(Temp) - { - P1Team.Add(Temp); - } - } - - for (TSubclassOf CharacterTemplate : P2TeamTemplate) - { - AKOFBaseCharacter_DEPRECATED* Temp = GetWorld()->SpawnActor(CharacterTemplate, FVector(0.0f, StartY, 204.6241f), FRotator(0.0f, -90.0f, 0.0f)); - Temp->SetIsPossesedByPlayer1(false); - if(Temp) - { - P2Team.Add(Temp); - } - } -} - -void AKOFDefaultGameMode::StartPlay() -{ - Super::StartPlay(); - - InitTeams(); - - // is this the right place to do this? - APlayerController* PC1 = UGameplayStatics::GetPlayerController(GetWorld(), 0); - if(PC1) - { - AKOFBaseCharacter_DEPRECATED* P1 = GetP1CurrentCharacter(); - if(P1) - { - PC1->Possess(P1); - } - } - - APlayerController* PC2 = UGameplayStatics::GetPlayerController(GetWorld(), 1); - if(PC2) - { - AKOFBaseCharacter_DEPRECATED* P2 = GetP1CurrentCharacter(); - if(P2) - { - PC2->Possess(P2); - } - } -} diff --git a/KOFForever/Source/KOFForever/Public/Character/KOFBaseCharacter.h b/KOFForever/Source/KOFForever/Public/Character/KOFBaseCharacter.h index c84cba9..5745c59 100644 --- a/KOFForever/Source/KOFForever/Public/Character/KOFBaseCharacter.h +++ b/KOFForever/Source/KOFForever/Public/Character/KOFBaseCharacter.h @@ -3,11 +3,16 @@ #pragma once #include "CoreMinimal.h" +#include "PaperFlipbookComponent.h" #include "../../../../Plugins/FixedPointMath/Source/FixedPointMath/Public/FixedVector.h" #include "GameFramework/Actor.h" +#include "KOFForever/KOFTypes.h" #include "KOFBaseCharacter.generated.h" -enum class EVirtualGamePadButton : uint8; +class UPaperFlipbook; + +class AKOFDefaultGameMode; + UCLASS() class KOFFOREVER_API AKOFBaseCharacter : public APawn { @@ -17,29 +22,86 @@ public: // Sets default values for this actor's properties AKOFBaseCharacter(); - void SetPosition(FFixedVector Param); + FORCEINLINE bool IsPossessedByPlayer1() const { return bIsPossessedByPlayer1; } + + FORCEINLINE void SetIsPossessedByPlayer1(bool bIsPlayer1) { bIsPossessedByPlayer1 = bIsPlayer1; } + + void Init(); protected: + // sprite /** The main flipbook representing the character */ - UPROPERTY(Category = Character, VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) - class UPaperFlipbookComponent* Sprite; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Character) + UPaperFlipbookComponent* Sprite; /** * Secondary sprite that is mirrored across the ground axis and set to black to give the effect of a * character's shadow */ - UPROPERTY(Category = Character, VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) - class UPaperFlipbookComponent* Shadow; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Character) + UPaperFlipbookComponent* Shadow; + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Animations") + TMap Animations; + + /** + * @brief Gets a character animation given a state name (i.e. WALKING, IDLE, etc.) + * @param Key Name of the animation + * @return the PaperFlipbook animation or a nullptr if the key does not exist in the animation map + */ + UPaperFlipbook* GetAnimation(FName Key); + + void UpdateAnimation(); + + void SetAnimationFlipbook(FName AnimName); + // movement // need a way to expose this to the editor as a float slider/entry UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Movement") FFixed MaxWalkSpeed; + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Movement") + FFixed GravityScale; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Movement|Jumping") + FFixed VerticalNormalJumpVelocity; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Movement|Jumping") + FFixed VerticalSuperJumpVelocity; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Movement|Jumping") + FFixed VerticalNormalHopVelocity; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Movement|Jumping") + FFixed VerticalSuperHopVelocity; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Movement|Jumping") + FFixed HorizontalNormalJumpVelocity; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Movement|Jumping") + FFixed HorizontalSuperJumpVelocity; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Movement|Jumping") + FFixed HorizontalNormalHopVelocity; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Movement|Jumping") + FFixed HorizontalSuperHopVelocity; + int Direction; FFixedVector Position; + + FFixedVector Velocity; + + void MoveRight(float Axis); + void UpdateMovement(FFixed DeltaTime); + + bool bIsInAir; + + void Jump(); + + // input and control /** * * @param PlayerInputComponent @@ -51,13 +113,16 @@ protected: void RegisterInput(FName ActionName, EVirtualGamePadButton Button); - void MoveRight(float Axis); - - void UpdateMovement(FFixed DeltaTime); + UPROPERTY(BlueprintReadOnly) + bool bIsPossessedByPlayer1; // Called when the game starts or when spawned virtual void BeginPlay() override; +private: + // reference to the game mode to get global game constants + AKOFDefaultGameMode* GameMode; + public: // Called every frame virtual void Tick(float DeltaTime) override; diff --git a/KOFForever/Source/KOFForever/Public/Character/KOFBaseCharacter_DEPRECATED.h b/KOFForever/Source/KOFForever/Public/Character/KOFBaseCharacter_DEPRECATED.h deleted file mode 100644 index deaf3f8..0000000 --- a/KOFForever/Source/KOFForever/Public/Character/KOFBaseCharacter_DEPRECATED.h +++ /dev/null @@ -1,87 +0,0 @@ -// A fan game by poret. This game is not affiliated with SNK. This is a fan game which is not being sold or distributed for profit. - -#pragma once - -#include "CoreMinimal.h" -#include "PaperCharacter.h" -#include "KOFBaseCharacter_DEPRECATED.generated.h" - -class UTextRenderComponent; - -/** - * This class is the default character for SideScroller2D, and it is responsible for all - * physical interaction between the player and the world. - * - * The capsule component (inherited from ACharacter) handles collision with the world - * The CharacterMovementComponent (inherited from ACharacter) handles movement of the collision capsule - * The Sprite component (inherited from APaperCharacter) handles the visuals - */ -UCLASS() -class KOFFOREVER_API AKOFBaseCharacter_DEPRECATED : public APaperCharacter -{ - GENERATED_BODY() - - UTextRenderComponent* TextComponent; - virtual void Tick(float DeltaSeconds) override; - - virtual void BeginPlay() override; - - virtual void PostInitializeComponents() override; -protected: - /** - * Secondary sprite that is mirrored across the ground axis and set to black to give the effect of a - * character's shadow - */ - UPROPERTY(Category = Character, VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true")) - class UPaperFlipbookComponent* Shadow; - - // The animation to play while running around - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Animations) - class UPaperFlipbook* RunningAnimation; - - // The animation to play while running around - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Animations) - class UPaperFlipbook* WalkFwdAnimation; - - // The animation to play while running around - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Animations) - class UPaperFlipbook* WalkBackAnimation; - - // The animation to play while idle (standing still) - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Animations) - class UPaperFlipbook* IdleAnimation; - - UPROPERTY(BlueprintReadOnly) - bool bIsPossesedByPlayer1; - - /** Called to choose the correct animation to play based on the character's movement state */ - void UpdateAnimation(); - - /** Called for side to side input */ - void MoveRight(float Value); - - void UpdateCharacter(); - - // APawn interface - virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override; - // End of APawn interface - -public: - AKOFBaseCharacter_DEPRECATED(const FObjectInitializer& ObjectInitializer); - - FORCEINLINE class UPaperFlipbookComponent* GetShadow() const { return Shadow; } - - /** - * Returns whether or not this player is possessed by player 1 - * - * @returns true is possessed by player 1, false if possessed by player 2 - */ - FORCEINLINE bool IsPossessedByPlayer1() const { return bIsPossesedByPlayer1; } - - /** - * Sets which player this character is possesed by. - * - * @param bIsPlayer1 true is possessed by player 1, false if possessed by player 2 - */ - FORCEINLINE void SetIsPossesedByPlayer1(bool bIsPlayer1) { bIsPossesedByPlayer1 = bIsPlayer1; } -}; diff --git a/KOFForever/Source/KOFForever/Public/Componenets/KOFCharacterMovementComponent.h b/KOFForever/Source/KOFForever/Public/Componenets/KOFCharacterMovementComponent.h deleted file mode 100644 index db7b452..0000000 --- a/KOFForever/Source/KOFForever/Public/Componenets/KOFCharacterMovementComponent.h +++ /dev/null @@ -1,20 +0,0 @@ -// A fan game by poret. This game is not affiliated with SNK. This is a fan game which is not being sold or distributed for profit. - -#pragma once - -#include "CoreMinimal.h" -#include "GameFramework/CharacterMovementComponent.h" -#include "KOFCharacterMovementComponent.generated.h" - -/** - * - */ -UCLASS() -class KOFFOREVER_API UKOFCharacterMovementComponent : public UCharacterMovementComponent -{ - GENERATED_BODY() - - UKOFCharacterMovementComponent(); - - virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override; -}; diff --git a/KOFForever/Source/KOFForever/Public/GameModes/KOFDefaultGameMode.h b/KOFForever/Source/KOFForever/Public/Game/KOFDefaultGameMode.h similarity index 55% rename from KOFForever/Source/KOFForever/Public/GameModes/KOFDefaultGameMode.h rename to KOFForever/Source/KOFForever/Public/Game/KOFDefaultGameMode.h index f3e05aa..6e525fd 100644 --- a/KOFForever/Source/KOFForever/Public/GameModes/KOFDefaultGameMode.h +++ b/KOFForever/Source/KOFForever/Public/Game/KOFDefaultGameMode.h @@ -1,70 +1,82 @@ -// A fan game by poret. This game is not affiliated with SNK. This is a fan game which is not being sold or distributed for profit. - -#pragma once - -#include "CoreMinimal.h" -#include "Character/KOFBaseCharacter_DEPRECATED.h" -#include "GameFramework/GameModeBase.h" -#include "KOFDefaultGameMode.generated.h" - -/** - * - */ -UCLASS() -class KOFFOREVER_API AKOFDefaultGameMode : public AGameModeBase -{ - GENERATED_BODY() - -public: - AKOFDefaultGameMode(); - - TArray& GetP1Team() { return P1Team; } - - TArray& GetP2Team() { return P2Team; } - - // this will need to change when we actually have real time character switching - AKOFBaseCharacter_DEPRECATED* GetP1CurrentCharacter() { return P1Team.Num() > 0 ? P1Team[0] : nullptr; } - - // this will need to change when we actually have real time character switching - AKOFBaseCharacter_DEPRECATED* GetP2CurrentCharacter() { return P2Team.Num() > 0 ? P2Team[0] : nullptr; } - - AKOFBaseCharacter_DEPRECATED* GetCurrentOpponent(bool bIsPlayer1) { return bIsPlayer1 ? GetP2CurrentCharacter() : GetP1CurrentCharacter(); } - - FORCEINLINE float GetMaxAllowedDistanceFromOpponent() { return MaxAllowedDistanceFromOpponent; } - - FORCEINLINE float GetStageLength() { return StageLength; } - -protected: - /** Number of characters on a single player's team */ - UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Settings|Team") - int32 NumCharactersPerTeam; - - /** Max distance the currently controlled player characters can be from one another */ - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Stage") - float MaxAllowedDistanceFromOpponent; - - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Stage") - float StageLength; - - /** Y offset from origin where character's will be spawned */ - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Stage") - float StartY; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Settings|Team") - TArray> P1TeamTemplate; - - /** List of references to the player's team members */ - UPROPERTY(BlueprintReadOnly) - TArray P1Team; - - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Settings|Team") - TArray> P2TeamTemplate; - - /** List of references to the player's team members */ - UPROPERTY(BlueprintReadOnly) - TArray P2Team; - - void InitTeams(); - - virtual void StartPlay() override; -}; +// A fan game by poret. This game is not affiliated with SNK. This is a fan game which is not being sold or distributed for profit. + +#pragma once + +#include "CoreMinimal.h" +#include "Fixed.h" +#include "Character/KOFBaseCharacter.h" +#include "GameFramework/GameModeBase.h" +#include "KOFDefaultGameMode.generated.h" + +/** + * + */ +UCLASS() +class KOFFOREVER_API AKOFDefaultGameMode : public AGameModeBase +{ + GENERATED_BODY() + +public: + AKOFDefaultGameMode(); + + FORCEINLINE FFixed GetGravity() { return Gravity; } + + // team + TArray& GetP1Team() { return P1Team; } + + TArray& GetP2Team() { return P2Team; } + + // this will need to change when we actually have real time character switching + AKOFBaseCharacter* GetP1CurrentCharacter() { return P1Team.Num() > 0 ? P1Team[0] : nullptr; } + + // this will need to change when we actually have real time character switching + AKOFBaseCharacter* GetP2CurrentCharacter() { return P2Team.Num() > 0 ? P2Team[0] : nullptr; } + + AKOFBaseCharacter* GetCurrentOpponent(bool bIsPlayer1) { return bIsPlayer1 ? GetP2CurrentCharacter() : GetP1CurrentCharacter(); } + + FORCEINLINE FFixed GetMaxAllowedDistanceFromOpponent() { return MaxAllowedDistanceFromOpponent; } + + FORCEINLINE FFixed GetStartY() { return StartY; } + + FORCEINLINE FFixed GetStageLength() { return StageLength; } + +protected: + // physics + UPROPERTY(EditDefaultsOnly) + FFixed Gravity; + + // stage + /** Max distance the currently controlled player characters can be from one another */ + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Stage") + FFixed MaxAllowedDistanceFromOpponent; + + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Stage") + FFixed StageLength; + + /** Y offset from origin where character's will be spawned */ + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Settings|Stage") + FFixed StartY; + + // team + /** Number of characters on a single player's team */ + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Settings|Team") + int32 NumCharactersPerTeam; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Settings|Team") + TArray> P1TeamTemplate; + + /** List of references to the player's team members */ + UPROPERTY(BlueprintReadOnly) + TArray P1Team; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Settings|Team") + TArray> P2TeamTemplate; + + /** List of references to the player's team members */ + UPROPERTY(BlueprintReadOnly) + TArray P2Team; + + void InitTeams(); + + virtual void StartPlay() override; +};