diff --git a/Content/EnemyPawn_BP.uasset b/Content/EnemyPawn_BP.uasset index 803d993..a84c273 100755 Binary files a/Content/EnemyPawn_BP.uasset and b/Content/EnemyPawn_BP.uasset differ diff --git a/Content/GameModeBase_BP.uasset b/Content/GameModeBase_BP.uasset index 6ed972f..d40b284 100755 Binary files a/Content/GameModeBase_BP.uasset and b/Content/GameModeBase_BP.uasset differ diff --git a/Content/HUDWidget.uasset b/Content/HUDWidget.uasset new file mode 100755 index 0000000..ed06e8b Binary files /dev/null and b/Content/HUDWidget.uasset differ diff --git a/Content/PlayerHUD.uasset b/Content/PlayerHUD.uasset new file mode 100755 index 0000000..a4e687b Binary files /dev/null and b/Content/PlayerHUD.uasset differ diff --git a/Content/PlayerPawn_BP.uasset b/Content/PlayerPawn_BP.uasset index 8df6b1e..73623e8 100755 Binary files a/Content/PlayerPawn_BP.uasset and b/Content/PlayerPawn_BP.uasset differ diff --git a/Content/PresidentPawn.uasset b/Content/PresidentPawn.uasset index a494131..4bcc68f 100755 Binary files a/Content/PresidentPawn.uasset and b/Content/PresidentPawn.uasset differ diff --git a/Content/TestMap.umap b/Content/TestMap.umap index d5b6a53..65c390a 100755 Binary files a/Content/TestMap.umap and b/Content/TestMap.umap differ diff --git a/Content/TestMap_BuiltData.uasset b/Content/TestMap_BuiltData.uasset index 3ca70ce..41c0eea 100755 Binary files a/Content/TestMap_BuiltData.uasset and b/Content/TestMap_BuiltData.uasset differ diff --git a/Source/PresidentsBrigade/BasePawn.cpp b/Source/PresidentsBrigade/BasePawn.cpp index e99383a..6837128 100755 --- a/Source/PresidentsBrigade/BasePawn.cpp +++ b/Source/PresidentsBrigade/BasePawn.cpp @@ -8,7 +8,6 @@ #include "Kismet/KismetSystemLibrary.h" #include "Util.h" -#define LogInfo(Msg) Util::log_info(TEXT("ABasePawn"), Msg) #define LogError(Msg) Util::log_error(TEXT("ABasePawn"), Msg) // Sets default values @@ -71,7 +70,6 @@ void ABasePawn::handle_hit( { // Update current health. current_health -= damage_class_map[other_class]; - LogInfo(FString::Printf(TEXT("Total health %d"), current_health)); } } @@ -102,10 +100,10 @@ void ABasePawn::Tick(float DeltaTime) /* * Handle death. */ - if (current_health <= 0) + if (current_health <= 0 && !death_handled) { handle_death(); - current_health = max_health; + death_handled = true; } } @@ -155,10 +153,9 @@ void ABasePawn::shoot() if (use_aim_assist) { float assist_yaw; - const bool succeess = aim_assist(player_location, rotator, assist_yaw); - if (assist_yaw) + const bool success = aim_assist(player_location, rotator, assist_yaw); + if (success) { - LogInfo("Aim assist activated!"); rotator.Yaw = assist_yaw; } } @@ -272,4 +269,4 @@ void ABasePawn::destroy_self() * Remove thyself from this world. */ Destroy(); -} \ No newline at end of file +} diff --git a/Source/PresidentsBrigade/BasePawn.h b/Source/PresidentsBrigade/BasePawn.h index 5ff7733..4f4a392 100755 --- a/Source/PresidentsBrigade/BasePawn.h +++ b/Source/PresidentsBrigade/BasePawn.h @@ -8,6 +8,8 @@ #include "Kismet/KismetMathLibrary.h" #include "BasePawn.generated.h" +#define LogInfo(Msg) Util::log_info(TEXT("ABasePawn"), Msg) + class UFloatingPawnMovement; UCLASS() @@ -21,6 +23,16 @@ public: FVector get_location() const; + FORCEINLINE float get_current_health_percentage() const + { + if (max_health == 0) + { + return 0; + } + + return (current_health * 1.0f) / max_health; + } + // Called every frame virtual void Tick(float DeltaTime) override; virtual void handle_move_right(float axis); @@ -141,6 +153,11 @@ protected: */ int32 current_health; + /** + * Death handled. + */ + bool death_handled; + /** * Current ammo. */ diff --git a/Source/PresidentsBrigade/PlayerPawn.cpp b/Source/PresidentsBrigade/PlayerPawn.cpp index e64c883..d380883 100755 --- a/Source/PresidentsBrigade/PlayerPawn.cpp +++ b/Source/PresidentsBrigade/PlayerPawn.cpp @@ -6,6 +6,7 @@ #include "GameFramework/FloatingPawnMovement.h" #include "Math/UnrealMathUtility.h" #include "Util.h" +#include "EngineUtils.h" #define LogInfo(Msg) Util::log_info(TEXT("APlayerPawn"), Msg) #define LogError(Msg) Util::log_error(TEXT("APlayerPawn"), Msg) @@ -68,24 +69,29 @@ void APlayerPawn::handle_overlap( } other_actor->Destroy(); - LogInfo(FString::Printf(TEXT("Total ammo %d"), current_ammo)); } } void APlayerPawn::Tick(float delta_time) { Super::Tick(delta_time); - if (cooldown_wait_s <= cooldown_threshold_s) + if (!init) + { + president_ref = get_president(); + init = true; + } + + if (cooldown_wait_s < cooldown_threshold_s) { cooldown_wait_s += delta_time; } - if (reset_wait_s <= reset_threshold_s) + if (reset_wait_s < reset_threshold_s) { reset_wait_s += delta_time; } - if (reset_wait_s > reset_threshold_s) + if (reset_wait_s >= reset_threshold_s) { reset_boost(); } @@ -102,10 +108,9 @@ void APlayerPawn::Tick(float delta_time) void APlayerPawn::boost() { - const bool boost_allowed = cooldown_wait_s > cooldown_threshold_s; + const bool boost_allowed = cooldown_wait_s >= cooldown_threshold_s; if (!boost_allowed) { - LogError("Cannot boost! You're on cooldown"); return; } @@ -180,4 +185,39 @@ void APlayerPawn::respawn() EnableInput(controller); player_mesh->SetHiddenInGame(false); collision->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics); + current_health = max_health; + death_handled = false; +} + +/** + * Helper function to find president in level. + */ +ABasePawn* APlayerPawn::get_president() const +{ + ABasePawn* found = nullptr; + for (TActorIterator iterator(GetWorld()); iterator; ++iterator) + { + AActor* actor = *iterator; + if (actor && actor != this) + { + UClass* actor_class = actor->GetClass(); + if (actor_class == (*president_class)) + { + if (found) + { + LogError("Multiple presidents found!"); + break; + } + + found = Cast(actor); + } + } + } + + if (!found) + { + // LogError("No president found!"); + } + + return found; } \ No newline at end of file diff --git a/Source/PresidentsBrigade/PlayerPawn.h b/Source/PresidentsBrigade/PlayerPawn.h index 66ca0e6..57c85de 100755 --- a/Source/PresidentsBrigade/PlayerPawn.h +++ b/Source/PresidentsBrigade/PlayerPawn.h @@ -23,6 +23,46 @@ public: // Called to bind functionality to input virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + + UFUNCTION(BlueprintCallable) + FORCEINLINE float get_president_health() const + { + if (president_ref) + { + return president_ref->get_current_health_percentage(); + } + + return 0; + } + + UFUNCTION(BlueprintCallable) + FORCEINLINE float get_boost_cooldown_percentage() const + { + if (reset_wait_s < reset_threshold_s) + { + return 0; + } + + if (cooldown_wait_s >= cooldown_threshold_s) + { + return 1.0f; + } + + return cooldown_wait_s / cooldown_threshold_s; + } + + UFUNCTION(BlueprintCallable) + FORCEINLINE int32 get_current_ammo() const + { + return current_ammo; + } + + UFUNCTION(BlueprintCallable) + FORCEINLINE int32 get_max_ammo() const + { + return max_ammo; + } + protected: virtual void BeginPlay() override; virtual void destroy_self() override; @@ -42,6 +82,9 @@ protected: UPROPERTY(EditAnywhere, Category = "Player") TMap ammo_class_map; + UPROPERTY(EditAnywhere, Category = "Player") + TSubclassOf president_class; + /** * Multiplier to apply to current speed while boosting. Applies to max speed and accleration. */ @@ -74,6 +117,7 @@ private: void boost(); void reset_boost(); void respawn(); + ABasePawn* get_president() const; /** * Default max speed. Cached when boost is called. @@ -99,4 +143,14 @@ private: * Time waiting for respawn. */ float respawn_wait_s; + + /** + * True after post tick initialization. + */ + bool init; + + /** + * Cached reference to the president. + */ + ABasePawn* president_ref; }; diff --git a/todo.txt b/todo.txt index 4511037..73ae9ad 100644 --- a/todo.txt +++ b/todo.txt @@ -18,10 +18,8 @@ xAdd auto aim xAdd art x Car models x Street shader -Add HUD UI +xAdd HUD UI for single player. Add sounds -Add win condition - - Time based. Keep president alive until he reaches destination. Add juice Add muzzle on shoot Camera zoom out based on screen size? Looks too small when I shrink the window @@ -29,8 +27,11 @@ Add juice Improve street shader Screen shake on zoom Particle effect on brake +Add win condition + - Time based. Keep president alive until he reaches destination. Add menu Add local multiplayer x Blueprint - C++ + - HUD UI for multiplayer Add netcode