ShooterPickup.cpp
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#include "ShooterGame.h"
#include "Pickups/ShooterPickup.h"
#include "Particles/ParticleSystemComponent.h"
AShooterPickup::AShooterPickup(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
UCapsuleComponent* CollisionComp = ObjectInitializer.CreateDefaultSubobject<UCapsuleComponent>(this, TEXT("CollisionComp"));
CollisionComp->InitCapsuleSize(40.0f, 50.0f);
CollisionComp->SetCollisionObjectType(COLLISION_PICKUP);
CollisionComp->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
CollisionComp->SetCollisionResponseToAllChannels(ECR_Ignore);
CollisionComp->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
RootComponent = CollisionComp;
PickupPSC = ObjectInitializer.CreateDefaultSubobject<UParticleSystemComponent>(this, TEXT("PickupFX"));
PickupPSC->bAutoActivate = false;
PickupPSC->bAutoDestroy = false;
PickupPSC->SetupAttachment(RootComponent);
RespawnTime = 10.0f;
bIsActive = false;
PickedUpBy = NULL;
SetRemoteRoleForBackwardsCompat(ROLE_SimulatedProxy);
bReplicates = true;
}
void AShooterPickup::BeginPlay()
{
Super::BeginPlay();
RespawnPickup();
// register on pickup list (server only), don't care about unregistering (in FinishDestroy) - no streaming
AShooterGameMode* GameMode = GetWorld()->GetAuthGameMode<AShooterGameMode>();
if (GameMode)
{
GameMode->LevelPickups.Add(this);
}
}
void AShooterPickup::NotifyActorBeginOverlap(class AActor* Other)
{
Super::NotifyActorBeginOverlap(Other);
PickupOnTouch(Cast<AShooterCharacter>(Other));
}
bool AShooterPickup::CanBePickedUp(class AShooterCharacter* TestPawn) const
{
return TestPawn && TestPawn->IsAlive();
}
void AShooterPickup::GivePickupTo(class AShooterCharacter* Pawn)
{
}
void AShooterPickup::PickupOnTouch(class AShooterCharacter* Pawn)
{
if (bIsActive && Pawn && Pawn->IsAlive() && !IsPendingKill())
{
if (CanBePickedUp(Pawn))
{
GivePickupTo(Pawn);
PickedUpBy = Pawn;
if (!IsPendingKill())
{
bIsActive = false;
OnPickedUp();
if (RespawnTime > 0.0f)
{
GetWorldTimerManager().SetTimer(TimerHandle_RespawnPickup, this, &AShooterPickup::RespawnPickup, RespawnTime, false);
}
}
}
}
}
void AShooterPickup::RespawnPickup()
{
bIsActive = true;
PickedUpBy = NULL;
OnRespawned();
TSet<AActor*> OverlappingPawns;
GetOverlappingActors(OverlappingPawns, AShooterCharacter::StaticClass());
for (AActor* OverlappingPawn : OverlappingPawns)
{
PickupOnTouch(CastChecked<AShooterCharacter>(OverlappingPawn));
}
}
void AShooterPickup::OnPickedUp()
{
if (RespawningFX)
{
PickupPSC->SetTemplate(RespawningFX);
PickupPSC->ActivateSystem();
}
else
{
PickupPSC->DeactivateSystem();
}
if (PickupSound && PickedUpBy)
{
UGameplayStatics::SpawnSoundAttached(PickupSound, PickedUpBy->GetRootComponent());
}
OnPickedUpEvent();
}
void AShooterPickup::OnRespawned()
{
if (ActiveFX)
{
PickupPSC->SetTemplate(ActiveFX);
PickupPSC->ActivateSystem();
}
else
{
PickupPSC->DeactivateSystem();
}
const bool bJustSpawned = CreationTime <= (GetWorld()->GetTimeSeconds() + 5.0f);
if (RespawnSound && !bJustSpawned)
{
UGameplayStatics::PlaySoundAtLocation(this, RespawnSound, GetActorLocation());
}
OnRespawnEvent();
}
void AShooterPickup::OnRep_IsActive()
{
if (bIsActive)
{
OnRespawned();
}
else
{
OnPickedUp();
}
}
void AShooterPickup::GetLifetimeReplicatedProps( TArray< FLifetimeProperty > & OutLifetimeProps ) const
{
Super::GetLifetimeReplicatedProps( OutLifetimeProps );
DOREPLIFETIME( AShooterPickup, bIsActive );
DOREPLIFETIME( AShooterPickup, PickedUpBy );
}
ShooterPickup_Ammo.cpp
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#include "ShooterGame.h"
#include "Pickups/ShooterPickup_Ammo.h"
#include "Weapons/ShooterWeapon.h"
AShooterPickup_Ammo::AShooterPickup_Ammo(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
AmmoClips = 2;
}
bool AShooterPickup_Ammo::IsForWeapon(UClass* WeaponClass)
{
return WeaponType->IsChildOf(WeaponClass);
}
bool AShooterPickup_Ammo::CanBePickedUp(AShooterCharacter* TestPawn) const
{
AShooterWeapon* TestWeapon = (TestPawn ? TestPawn->FindWeapon(WeaponType) : NULL);
if (bIsActive && TestWeapon)
{
return TestWeapon->GetCurrentAmmo() < TestWeapon->GetMaxAmmo();
}
return false;
}
void AShooterPickup_Ammo::GivePickupTo(class AShooterCharacter* Pawn)
{
AShooterWeapon* Weapon = (Pawn ? Pawn->FindWeapon(WeaponType) : NULL);
if (Weapon)
{
int32 Qty = AmmoClips * Weapon->GetAmmoPerClip();
Weapon->GiveAmmo(Qty);
// Fire event for collected ammo
if (Pawn)
{
const auto Events = Online::GetEventsInterface();
const auto Identity = Online::GetIdentityInterface();
if (Events.IsValid() && Identity.IsValid())
{
AShooterPlayerController* PC = Cast<AShooterPlayerController>(Pawn->Controller);
if (PC)
{
ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(PC->Player);
if (LocalPlayer)
{
const int32 UserIndex = LocalPlayer->GetControllerId();
TSharedPtr<const FUniqueNetId> UniqueID = Identity->GetUniquePlayerId(UserIndex);
if (UniqueID.IsValid())
{
FVector Location = Pawn->GetActorLocation();
FOnlineEventParms Params;
Params.Add( TEXT( "SectionId" ), FVariantData( (int32)0 ) ); // unused
Params.Add( TEXT( "GameplayModeId" ), FVariantData( (int32)1 ) ); // @todo determine game mode (ffa v tdm)
Params.Add( TEXT( "DifficultyLevelId" ), FVariantData( (int32)0 ) ); // unused
Params.Add( TEXT( "ItemId" ), FVariantData( (int32)Weapon->GetAmmoType() + 1 ) ); // @todo come up with a better way to determine item id, currently health is 0 and ammo counts from 1
Params.Add( TEXT( "AcquisitionMethodId" ), FVariantData( (int32)0 ) ); // unused
Params.Add( TEXT( "LocationX" ), FVariantData( Location.X ) );
Params.Add( TEXT( "LocationY" ), FVariantData( Location.Y ) );
Params.Add( TEXT( "LocationZ" ), FVariantData( Location.Z ) );
Params.Add( TEXT( "ItemQty" ), FVariantData( (int32)Qty ) );
Events->TriggerEvent(*UniqueID, TEXT("CollectPowerup"), Params);
}
}
}
}
}
}
}
ShooterPickup_Health.cpp
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#include "ShooterGame.h"
#include "Pickups/ShooterPickup_Health.h"
AShooterPickup_Health::AShooterPickup_Health(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
Health = 50;
}
bool AShooterPickup_Health::CanBePickedUp(class AShooterCharacter* TestPawn) const
{
return TestPawn && (TestPawn->Health < TestPawn->GetMaxHealth());
}
void AShooterPickup_Health::GivePickupTo(class AShooterCharacter* Pawn)
{
if (Pawn)
{
Pawn->Health = FMath::Min(FMath::TruncToInt(Pawn->Health) + Health, Pawn->GetMaxHealth());
// Fire event for collected health
const auto Events = Online::GetEventsInterface();
const auto Identity = Online::GetIdentityInterface();
if (Events.IsValid() && Identity.IsValid())
{
AShooterPlayerController* PC = Cast<AShooterPlayerController>(Pawn->Controller);
if (PC)
{
ULocalPlayer* LocalPlayer = Cast<ULocalPlayer>(PC->Player);
if (LocalPlayer)
{
const int32 UserIndex = LocalPlayer->GetControllerId();
TSharedPtr<const FUniqueNetId> UniqueID = Identity->GetUniquePlayerId(UserIndex);
if (UniqueID.IsValid())
{
FVector Location = Pawn->GetActorLocation();
FOnlineEventParms Params;
Params.Add( TEXT( "SectionId" ), FVariantData( (int32)0 ) ); // unused
Params.Add( TEXT( "GameplayModeId" ), FVariantData( (int32)1 ) ); // @todo determine game mode (ffa v tdm)
Params.Add( TEXT( "DifficultyLevelId" ), FVariantData( (int32)0 ) ); // unused
Params.Add( TEXT( "ItemId" ), FVariantData( (int32)0 ) ); // @todo come up with a better way to determine item id, currently health is 0 and ammo counts from 1
Params.Add( TEXT( "AcquisitionMethodId" ), FVariantData( (int32)0 ) ); // unused
Params.Add( TEXT( "LocationX" ), FVariantData( Location.X ) );
Params.Add( TEXT( "LocationY" ), FVariantData( Location.Y ) );
Params.Add( TEXT( "LocationZ" ), FVariantData( Location.Z ) );
Params.Add( TEXT( "ItemQty" ), FVariantData( (int32)Health ) );
Events->TriggerEvent(*UniqueID, TEXT("CollectPowerup"), Params);
}
}
}
}
}
}