Interaction, Inventory and Using Items
MedievalCombatProject
Interaction
Interaction is performed using the E key. When the Character is overlapping with an Item, they can press E to Interact with it.
Note: Item
is a C++ class derived from AActor
. It is used as a base class for all items that can be interacted with by the Character.
The Shield
, Weapon
, FoodItem
classes are all children of Item
and override its functions.
For now, Interact
functionality is the same for all Items. Interaction with any Item would Destroy()
it and add a copy into the Character’s
Inventory.
This functionality was done by making a class UInteractInterface
deriving from UE4’s
Interface C++ class.
This InteractInterface has a virtual function Interact(AActor* Interacter)
that gets overriden in Item
like so:
Interact()
void AItem::Interact(AActor* Interacter)
{
// Cast Interacter to Main
AMain* Main = Cast<AMain>(Interacter);
if (Main)
{
Main->ResetIdleTimer();
//Add values to a SlotStructure Object
FSlotStructure SlotStructure;
SlotStructure.ItemStructure = ItemStructure;
SlotStructure.Quantity = 1;
// Add the object to the Inventory
bool Success = Main->Inventory->AddToInventory(SlotStructure);
if (Success)Destroy();
}
}
Inventory menu
The Inventory menu is toggled by the Tab key and shows a grid of the Items that the Character has in its Inventory.
- Inventory menu
Each Item slot on the grid shows a thumbnail image and quantity. When the player hovers the mouse pointer over a slot, an Item tooltip appears next to the pointer to show the Item’s name, description and an Use text (for example: “Click to Eat.”).
Clicking on the Item slot calls a virtual function UseItem()
declared in Item
.
If the Item was labeled as Consumable, it would be spawned with scale (0.0, 0.0, 0.0)
and if labeled as Equippable, (1.0, 1.0, 1.0)
.
A Consumable Item’s Quantity would also be decremented after calling its UseItem()
function.
Following is UseItem()
defined in class Weapon
. Using the Item removes the currently Equipped Weapon and attaches
itself to the required socket.
UseItem()
bool AWeapon::UseItem(AMain* Main)
{
// Call the base function
Super::UseItem(Main);
// If this is a Two-Handed Weapon, remove the equipped Shield, if any
if (bIsTwoHanded)
{
if (Main->EquippedShield)
{
Main->EquippedShield->Destroy();
Main->SetEquippedShield(nullptr);
}
}
Main->SetEquippedWeapon(this);
// Disable collision of the CollisionVolume
CollisionVolume->SetCollisionEnabled(ECollisionEnabled::NoCollision);
CollisionVolume->SetCollisionResponseToAllChannels(ECR_Ignore);
// Set Weapon Instigator
SetInstigator(Main->GetController());
SkeletalMesh->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
SkeletalMesh->SetCollisionResponseToChannel(ECC_Pawn, ECR_Ignore);
SkeletalMesh->SetSimulatePhysics(false);
bShouldRotate = false;
if (!bWeaponParticles)
{
IdleParticlesComponent->Deactivate();
}
// Attach Weapon to Sheath Socket.
Main->TimedSheathe();
// Set bIsWeaponDrawn as false as the Weapon is sheathed.
Main->bIsWeaponDrawn = false;
// If in Combat Mode, draw the weapon.
if (Main->bInCombatMode)
{
Main->DrawWeapon();
}
return true;
}
You can view the code of the project here!
In Action
- Adding and Using Item: Herb
- Adding and Using Item: Bread