I am modifying the first person shooter’s onfire() function so that it is run on the server…
I get compiler errors, which make no sense to me…
ERROR:
Severity Code Description Project File Line Suppression State
Error LNK2005 "public: void __cdecl AMyProjectCharacter::OnFire(void)" (?OnFire@AMyProjectCharacter@@QEAAXXZ) already defined in MyProjectCharacter.cpp.obj MyProject C:\Users\Simon\Documents\Unreal Projects\MyProject\Intermediate\ProjectFiles\MyProject.generated.cpp.obj 1
Error LNK1169 one or more multiply defined symbols found MyProject C:\Users\Simon\Documents\Unreal Projects\MyProject\Binaries\Win64\UE4Editor-MyProject.dll 1
Error Failed to produce item: C:\Users\Simon\Documents\Unreal Projects\MyProject\Binaries\Win64\UE4Editor-MyProject.dll MyProject C:\Users\Simon\Documents\Unreal Projects\MyProject\Intermediate\ProjectFiles\ERROR 1
Error MSB3073 The command ""C:\Program Files (x86)\Epic Games\4.11\Engine\Build\BatchFiles\Build.bat" MyProjectEditor Win64 Development "C:\Users\Simon\Documents\Unreal Projects\MyProject\MyProject.uproject" -waitmutex -2015" exited with code -1. MyProject C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.MakeFile.Targets 37
OUTPUT:
1>------ Build started: Project: UE4, Configuration: BuiltWithUnrealBuildTool Win32 ------
2>------ Build started: Project: MyProject, Configuration: Development_Editor x64 ------
2> Parsing headers for MyProjectEditor
2> Running UnrealHeaderTool "C:\Users\Simon\Documents\Unreal Projects\MyProject\MyProject.uproject" "C:\Users\Simon\Documents\Unreal Projects\MyProject\Intermediate\Build\Win64\MyProjectEditor\Development\UnrealHeaderTool.manifest" -LogCmds="loginit warning, logexit warning, logdatabase error" -Unattended -WarningsAsErrors -installed
2> Reflection code generated for MyProjectEditor in 2.066397 seconds
2> Performing 4 actions (4 in parallel)
2> MyProjectCharacter.cpp
2> MyProject.generated.cpp
2> MyProjectGameMode.cpp
2> [4/4] Link UE4Editor-MyProject.dll
2>MyProject.generated.cpp.obj : error LNK2005: "public: void __cdecl AMyProjectCharacter::OnFire(void)" (?OnFire@AMyProjectCharacter@@QEAAXXZ) already defined in MyProjectCharacter.cpp.obj
2> Creating library C:\Users\Simon\Documents\Unreal Projects\MyProject\Intermediate\Build\Win64\UE4Editor\Development\UE4Editor-MyProject.lib and object C:\Users\Simon\Documents\Unreal Projects\MyProject\Intermediate\Build\Win64\UE4Editor\Development\UE4Editor-MyProject.exp
2>C:\Users\Simon\Documents\Unreal Projects\MyProject\Binaries\Win64\UE4Editor-MyProject.dll : fatal error LNK1169: one or more multiply defined symbols found
2> -------- End Detailed Actions Stats -----------------------------------------------------------
2>ERROR : UBT error : Failed to produce item: C:\Users\Simon\Documents\Unreal Projects\MyProject\Binaries\Win64\UE4Editor-MyProject.dll
2> Total build time: 4.02 seconds
2>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.MakeFile.Targets(37,5): error MSB3073: The command ""C:\Program Files (x86)\Epic Games\4.11\Engine\Build\BatchFiles\Build.bat" MyProjectEditor Win64 Development "C:\Users\Simon\Documents\Unreal Projects\MyProject\MyProject.uproject" -waitmutex -2015" exited with code -1.
========== Build: 1 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
MyProjectCharacter.h
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "GameFramework/Character.h"
#include "MyProjectCharacter.generated.h"
class UInputComponent;
UCLASS(config = Game)
class AMyProjectCharacter : public ACharacter
{
GENERATED_BODY()
/** Pawn mesh: 1st person view (arms; seen only by self) */
UPROPERTY(VisibleDefaultsOnly, Category = Mesh)
class USkeletalMeshComponent* Mesh1P;
/** Gun mesh: 1st person view (seen only by self) */
UPROPERTY(VisibleDefaultsOnly, Category = Mesh)
class USkeletalMeshComponent* FP_Gun;
/** Location on gun mesh where projectiles should spawn. */
UPROPERTY(VisibleDefaultsOnly, Category = Mesh)
class USceneComponent* FP_MuzzleLocation;
/** First person camera */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
class UCameraComponent* FirstPersonCameraComponent;
//UFUNCTION(NetMulticast)
//void SetProjectile();
public:
AMyProjectCharacter();
virtual void BeginPlay();
/** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
float BaseTurnRate;
/** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera)
float BaseLookUpRate;
/** Gun muzzle's offset from the characters location */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay)
FVector GunOffset;
/** Projectile class to spawn */
UPROPERTY(EditDefaultsOnly, Category = Projectile)
TSubclassOf<class AMyProjectProjectile> ProjectileClass;
/** Sound to play each time we fire */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay)
class USoundBase* FireSound;
/** AnimMontage to play each time we fire */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay)
class UAnimMontage* FireAnimation;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Faction, Replicated)
UMaterial *FactionColor;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Faction, Replicated)
UMaterial *FactionDecal;
protected:
/** Fires a projectile. */
UFUNCTION(Server, Reliable, WithValidation)
void OnFire();
void OnFire_Implementation();
bool OnFire_Validate();
/** Handles moving forward/backward */
void MoveForward(float Val);
/** Handles stafing movement, left and right */
void MoveRight(float Val);
/**
* Called via input to turn at a given rate.
* @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
*/
void TurnAtRate(float Rate);
/**
* Called via input to turn look up/down at a given rate.
* @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
*/
void LookUpAtRate(float Rate);
struct TouchData
{
TouchData() { bIsPressed = false; Location = FVector::ZeroVector; }
bool bIsPressed;
ETouchIndex::Type FingerIndex;
FVector Location;
bool bMoved;
};
void BeginTouch(const ETouchIndex::Type FingerIndex, const FVector Location);
void EndTouch(const ETouchIndex::Type FingerIndex, const FVector Location);
void TouchUpdate(const ETouchIndex::Type FingerIndex, const FVector Location);
TouchData TouchItem;
protected:
// APawn interface
virtual void SetupPlayerInputComponent(UInputComponent* InputComponent) override;
// End of APawn interface
/*
* Configures input for touchscreen devices if there is a valid touch interface for doing so
*
* @param InputComponent The input component pointer to bind controls to
* @returns true if touch controls were enabled.
*/
bool EnableTouchscreenMovement(UInputComponent* InputComponent);
public:
/** Returns Mesh1P subobject **/
FORCEINLINE class USkeletalMeshComponent* GetMesh1P() const { return Mesh1P; }
/** Returns FirstPersonCameraComponent subobject **/
FORCEINLINE class UCameraComponent* GetFirstPersonCameraComponent() const { return FirstPersonCameraComponent; }
};
MyProjectCharacter.cpp
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#include "MyProject.h"
#include "MyProjectCharacter.h"
#include "MyProjectProjectile.h"
#include "Animation/AnimInstance.h"
#include "GameFramework/InputSettings.h"
#include "UnrealNetwork.h"
DEFINE_LOG_CATEGORY_STATIC(LogFPChar, Warning, All);
//////////////////////////////////////////////////////////////////////////
// AMyProjectCharacter
AMyProjectCharacter::AMyProjectCharacter()
{
// Set size for collision capsule
GetCapsuleComponent()->InitCapsuleSize(55.f, 96.0f);
// set our turn rates for input
BaseTurnRate = 45.f;
BaseLookUpRate = 45.f;
// Create a CameraComponent
FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCameraComponent->AttachParent = GetCapsuleComponent();
FirstPersonCameraComponent->RelativeLocation = FVector(-39.56f, 1.75f, 64.f); // Position the camera
FirstPersonCameraComponent->bUsePawnControlRotation = true;
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true);
Mesh1P->AttachParent = FirstPersonCameraComponent;
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
Mesh1P->RelativeRotation = FRotator(1.9f, -19.19f, 5.2f);
Mesh1P->RelativeLocation = FVector(-0.5f, -4.4f, -155.7f);
// Create a gun mesh component
FP_Gun = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FP_Gun"));
FP_Gun->SetOnlyOwnerSee(true); // only the owning player will see this mesh
FP_Gun->bCastDynamicShadow = false;
FP_Gun->CastShadow = false;
//FP_Gun->AttachTo(Mesh1P, TEXT("GripPoint"), EAttachLocation::SnapToTargetIncludingScale, true);
FP_MuzzleLocation = CreateDefaultSubobject<USceneComponent>(TEXT("MuzzleLocation"));
FP_MuzzleLocation->AttachTo(FP_Gun);
FP_MuzzleLocation->SetRelativeLocation(FVector(0.2f, 48.4f, -10.6f));
FP_MuzzleLocation = nullptr; //Remove Muzzle
// Default offset from the character location for projectiles to spawn
GunOffset = FVector(100.0f, 30.0f, 10.0f);
bReplicates = true;
// Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P are set in the
// derived blueprint asset named MyCharacter (to avoid direct content references in C++)
}
void AMyProjectCharacter::BeginPlay()
{
// Call the base class
Super::BeginPlay();
FP_Gun->AttachTo(Mesh1P, TEXT("GripPoint"), EAttachLocation::SnapToTargetIncludingScale, true); //Attach gun mesh component to Skeleton, doing it here because the skelton is not yet created in the constructor
}
//////////////////////////////////////////////////////////////////////////
// Input
void AMyProjectCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
// set up gameplay key bindings
check(InputComponent);
InputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
InputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
//InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AMyProjectCharacter::TouchStarted);
if (EnableTouchscreenMovement(InputComponent) == false)
{
InputComponent->BindAction("Fire", IE_Pressed, this, &AMyProjectCharacter::OnFire);
}
InputComponent->BindAxis("MoveForward", this, &AMyProjectCharacter::MoveForward);
InputComponent->BindAxis("MoveRight", this, &AMyProjectCharacter::MoveRight);
// We have 2 versions of the rotation bindings to handle different kinds of devices differently
// "turn" handles devices that provide an absolute delta, such as a mouse.
// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
InputComponent->BindAxis("TurnRate", this, &AMyProjectCharacter::TurnAtRate);
InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
InputComponent->BindAxis("LookUpRate", this, &AMyProjectCharacter::LookUpAtRate);
}
/*void AMyProjectCharacter::SetProjectile()
{
if (FactionColor != NULL)
{
//p->ProjectileStaticMesh->SetMaterial(0, FactionColor);
}
if (FactionDecal != NULL)
{
//p->FactionDecal = FactionDecal;
}
}*/
void AMyProjectCharacter::OnFire()
{
// try and fire a projectile
if (ProjectileClass != NULL)
{
const FRotator SpawnRotation = GetControlRotation();
// MuzzleOffset is in camera space, so transform it to world space before offsetting from the character location to find the final muzzle position
const FVector SpawnLocation = ((FP_MuzzleLocation != nullptr) ? FP_MuzzleLocation->GetComponentLocation() : GetActorLocation()) + SpawnRotation.RotateVector(GunOffset);
UWorld* const World = GetWorld();
if (World != NULL)
{
// spawn the projectile at the muzzle
AMyProjectProjectile *projectile = World->SpawnActor<AMyProjectProjectile>(ProjectileClass, SpawnLocation, SpawnRotation);
if (FactionColor != NULL)
{
projectile->ProjectileStaticMesh->SetMaterial(0, FactionColor);
}
if (FactionDecal != NULL)
{
projectile->FactionDecal = FactionDecal;
}
}
}
// try and play the sound if specified
if (FireSound != NULL)
{
UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());
}
// try and play a firing animation if specified
if (FireAnimation != NULL)
{
// Get the animation object for the arms mesh
UAnimInstance* AnimInstance = Mesh1P->GetAnimInstance();
if (AnimInstance != NULL)
{
AnimInstance->Montage_Play(FireAnimation, 1.f);
}
}
}
void AMyProjectCharacter::OnFire_Implementation()
{
}
bool AMyProjectCharacter::OnFire_Validate()
{
return true;
}
void AMyProjectCharacter::BeginTouch(const ETouchIndex::Type FingerIndex, const FVector Location)
{
if (TouchItem.bIsPressed == true)
{
return;
}
TouchItem.bIsPressed = true;
TouchItem.FingerIndex = FingerIndex;
TouchItem.Location = Location;
TouchItem.bMoved = false;
}
void AMyProjectCharacter::EndTouch(const ETouchIndex::Type FingerIndex, const FVector Location)
{
if (TouchItem.bIsPressed == false)
{
return;
}
if ((FingerIndex == TouchItem.FingerIndex) && (TouchItem.bMoved == false))
{
OnFire();
}
TouchItem.bIsPressed = false;
}
void AMyProjectCharacter::TouchUpdate(const ETouchIndex::Type FingerIndex, const FVector Location)
{
if ((TouchItem.bIsPressed == true) && (TouchItem.FingerIndex == FingerIndex))
{
if (TouchItem.bIsPressed)
{
if (GetWorld() != nullptr)
{
UGameViewportClient* ViewportClient = GetWorld()->GetGameViewport();
if (ViewportClient != nullptr)
{
FVector MoveDelta = Location - TouchItem.Location;
FVector2D ScreenSize;
ViewportClient->GetViewportSize(ScreenSize);
FVector2D ScaledDelta = FVector2D(MoveDelta.X, MoveDelta.Y) / ScreenSize;
if (FMath::Abs(ScaledDelta.X) >= 4.0 / ScreenSize.X)
{
TouchItem.bMoved = true;
float Value = ScaledDelta.X * BaseTurnRate;
AddControllerYawInput(Value);
}
if (FMath::Abs(ScaledDelta.Y) >= 4.0 / ScreenSize.Y)
{
TouchItem.bMoved = true;
float Value = ScaledDelta.Y * BaseTurnRate;
AddControllerPitchInput(Value);
}
TouchItem.Location = Location;
}
TouchItem.Location = Location;
}
}
}
}
void AMyProjectCharacter::MoveForward(float Value)
{
if (Value != 0.0f)
{
// add movement in that direction
AddMovementInput(GetActorForwardVector(), Value);
}
}
void AMyProjectCharacter::MoveRight(float Value)
{
if (Value != 0.0f)
{
// add movement in that direction
AddMovementInput(GetActorRightVector(), Value);
}
}
void AMyProjectCharacter::TurnAtRate(float Rate)
{
// calculate delta for this frame from the rate information
AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());
}
void AMyProjectCharacter::LookUpAtRate(float Rate)
{
// calculate delta for this frame from the rate information
AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
}
bool AMyProjectCharacter::EnableTouchscreenMovement(class UInputComponent* InputComponent)
{
bool bResult = false;
if (FPlatformMisc::GetUseVirtualJoysticks() || GetDefault<UInputSettings>()->bUseMouseForTouch)
{
bResult = true;
InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AMyProjectCharacter::BeginTouch);
InputComponent->BindTouch(EInputEvent::IE_Released, this, &AMyProjectCharacter::EndTouch);
InputComponent->BindTouch(EInputEvent::IE_Repeat, this, &AMyProjectCharacter::TouchUpdate);
}
return bResult;
}
void AMyProjectCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty > & OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AMyProjectCharacter, FactionColor);
DOREPLIFETIME(AMyProjectCharacter, FactionDecal);
}