Hello,
I’m currently trying to implement a weapon system, in which the player throughout the game, will be able to pickup very specific weapons, that’ll be available to them for the rest of the game. I suppose this is a very Doom Eternal’ish implementation of a weapon system. I’d love some feedback on the system, and some guidance on how you would build it.
Implementation and idea so far
I’m thinking the the following implementation is a way to build the weapon system:
- Custom
ACharacter
child class that has the definition of the weapons in multiple struct properties - Pickup actor to enable the weapon for the player
USkeletalMeshComponent
to switch weapon mesh when the player switches weapon- Base weapon actor class, with function such as
Fire
,Reload
, etc.
With this system
Code so far
So far, I’ve created the following code for the system:
EWeaponType and FWeaponDetails
UENUM()
enum EWeaponType
{
SMG = 1 UMETA(DisplayName = "SMG"),
Shotgun = 2 UMETA(DisplayName = "Shotgun"),
RocketLauncher = 3 UMETA(DisplayName = "Rocket launcher")
};
USTRUCT(BlueprintType)
struct FWeaponDetails
{
GENERATED_BODY()
// Name of the given weapon.
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
FString Name;
// Type of weapon.
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TEnumAsByte<EWeaponType> WeaponType;
// Mesh to use on pickup as well as on equip.
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TObjectPtr<USkeletalMesh> Mesh;
// Actor class reference.
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
TSubclassOf<AWeapon> WeaponClass;
// Whether the weapon is available for the player to use or not
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
bool bIsAvailable;
};
CustomPlayerCharacter.h
// SMG info.
UPROPERTY(/*...*/)
FUnnamedWeaponDetails SMG;
// Shotgun info.
UPROPERTY(/*...*/)
FUnnamedWeaponDetails Shotgun;
// Rocket Launcher info.
UPROPERTY(/*...*/)
FUnnamedWeaponDetails RocketLeauncher;
// Weapon details of the currently equipped weapon.
UPROPERTY()
FUnnamedWeaponDetails EquippedWeaponDetails;
// Currently equipped weapon, if any.
UPROPERTY()
ACustomWeapon* EquippedWeapon;
// Add weapon to the player's weapon arsenal and equip it.
// Returns true if the weapon could be added, false if the weapon is already in the player's arsenal.
bool EnableWeapon(EWeaponType WeaponType, bool bEquipIfPossible);
// Equip the given weapon if it's available to the player.
void EquipWeapon(FWeaponDetails& Weapon);
// Get weapon details struct by the given type.
bool GetWeaponDetailsByType(EWeaponType WeaponType, FWeaponDetails& Weapon) const;
CustomPlayerCharacter.cpp
bool AUnnamedCharacter::EnableWeapon(EWeaponType WeaponType, bool bEquipIfPossible)
{
FUnnamedWeaponDetails WeaponDetails;
if (!GetWeaponDetailsByType(WeaponType, WeaponDetails))
{
// Weapon type does not exist on the player.
return false;
}
// Make this weapon available to the player.
WeaponDetails.bIsAvailable = true;
// Equip if requested.
if(bEquipIfPossible)
EquipWeapon(WeaponDetails);
return true;
}
void ACustomPlayerCharacter::EquipWeapon(FWeaponDetails& Weapon)
{
// Weapon is not yet available to the player.
if (!Weapon.bIsAvailable)
return;
// Weapon is already equipped.
if (EquippedWeaponDetails == Weapon)
return;
EquippedWeaponDetails = Weapon;
//... Spawn weapon and attach to player skeletal mesh bone, etc.
}
bool ACustomPlayerCharacter::GetWeaponDetailsByType(EWeaponType WeaponType, FWeaponDetails& Weapon) const
{
switch (WeaponType)
{
case EWeaponType::SMG:
Weapon = SMG;
return true;
case EWeaponType::Shotgun:
Weapon = Shotgun;
return true;
case EWeaponType::RocketLauncher:
Weapon = RocketLeauncher;
return true;
}
return false;
}
I know that I may be asking for a lot, but I’m hoping that some of you may shed some light on the concept, and give me some feedback before i delve further down this rabbit hole
Thanks in advance!