Implement crouch and prone stances
This commit is contained in:
@@ -375,7 +375,7 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
|
|||||||
- [x] Define real-world baseline walking speed. Decision: baseline adult walking speed is `1.4 m/s` (`140 Unreal units/s`), with MVP tuning allowance up to about `1.6 m/s` for brisk walking. Movement speed does not scale with the `4 real hours = 1 in-game day` calendar.
|
- [x] Define real-world baseline walking speed. Decision: baseline adult walking speed is `1.4 m/s` (`140 Unreal units/s`), with MVP tuning allowance up to about `1.6 m/s` for brisk walking. Movement speed does not scale with the `4 real hours = 1 in-game day` calendar.
|
||||||
- [x] Define real-world baseline running speed. Decision: sustainable adult running target is `3.0 m/s` (`300 Unreal units/s`); MVP sprint is a short burst at `5.5 m/s` (`550 Unreal units/s`) with stamina limits. Movement speed does not scale with the calendar.
|
- [x] Define real-world baseline running speed. Decision: sustainable adult running target is `3.0 m/s` (`300 Unreal units/s`); MVP sprint is a short burst at `5.5 m/s` (`550 Unreal units/s`) with stamina limits. Movement speed does not scale with the calendar.
|
||||||
- [x] Connect movement speed to age, condition, strength, endurance, hunger, thirst, injury, carried weight, and terrain. Implemented with live survival/inventory modifiers plus replicated age, condition, strength, endurance, and terrain hooks.
|
- [x] Connect movement speed to age, condition, strength, endurance, hunger, thirst, injury, carried weight, and terrain. Implemented with live survival/inventory modifiers plus replicated age, condition, strength, endurance, and terrain hooks.
|
||||||
- [ ] Implement crouching if needed.
|
- [x] Implement crouching and prone movement stances. Decision: `C` toggles crouch at `55%` movement speed and `Z` toggles prone at `25%` movement speed. Gamepad mappings are Right Shoulder for crouch and Left Shoulder for prone. Sprint is disabled while crouched or prone.
|
||||||
- [x] Implement jumping if needed.
|
- [x] Implement jumping if needed.
|
||||||
- [x] Implement interaction trace.
|
- [x] Implement interaction trace.
|
||||||
- [ ] Implement interact prompt.
|
- [ ] Implement interact prompt.
|
||||||
@@ -1465,4 +1465,4 @@ Earliest incomplete foundation items:
|
|||||||
|
|
||||||
Immediate next item:
|
Immediate next item:
|
||||||
|
|
||||||
- [ ] Implement crouching if needed.
|
- [ ] Implement interact prompt.
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -116,6 +116,26 @@ Later movement work should separate:
|
|||||||
- injury/load/terrain modifiers;
|
- injury/load/terrain modifiers;
|
||||||
- skill, age, care history, and condition effects.
|
- skill, age, care history, and condition effects.
|
||||||
|
|
||||||
|
## MVP Stance Movement
|
||||||
|
|
||||||
|
The first stance pass supports crouch and prone as low-movement modes that keep
|
||||||
|
the same real-distance philosophy as walking and sprinting.
|
||||||
|
|
||||||
|
Current defaults:
|
||||||
|
|
||||||
|
- crouch toggles with `C` or gamepad Right Shoulder;
|
||||||
|
- prone toggles with `Z` or gamepad Left Shoulder;
|
||||||
|
- crouch uses `55%` of the current movement speed;
|
||||||
|
- prone uses `25%` of the current movement speed;
|
||||||
|
- sprint cannot start while crouched or prone;
|
||||||
|
- entering prone exits crouch so the player has one active low stance at a
|
||||||
|
time.
|
||||||
|
|
||||||
|
The MVP prone state is replicated and affects movement speed. Dedicated prone
|
||||||
|
animation, capsule resizing, crawl-specific collision, stealth/noise, and
|
||||||
|
surface-specific crawl penalties are reserved for later animation and traversal
|
||||||
|
passes.
|
||||||
|
|
||||||
## Movement Modifier Implementation
|
## Movement Modifier Implementation
|
||||||
|
|
||||||
MVP movement speed is now calculated as:
|
MVP movement speed is now calculated as:
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
import unreal
|
||||||
|
|
||||||
|
|
||||||
|
STANCE_DEFAULTS = {
|
||||||
|
"CrouchSpeedMultiplier": 0.55,
|
||||||
|
"ProneSpeedMultiplier": 0.25,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def load(path):
|
||||||
|
asset = unreal.EditorAssetLibrary.load_asset(path)
|
||||||
|
if not asset:
|
||||||
|
raise RuntimeError(f"Could not load {path}")
|
||||||
|
return asset
|
||||||
|
|
||||||
|
|
||||||
|
def create_input_action(path):
|
||||||
|
existing = unreal.EditorAssetLibrary.load_asset(path)
|
||||||
|
if existing:
|
||||||
|
return existing
|
||||||
|
|
||||||
|
template_path = "/Game/Input/Actions/IA_Interact"
|
||||||
|
template = unreal.EditorAssetLibrary.load_asset(template_path)
|
||||||
|
if not template:
|
||||||
|
template_path = "/Game/Input/Actions/IA_Jump"
|
||||||
|
template = unreal.EditorAssetLibrary.load_asset(template_path)
|
||||||
|
if not template:
|
||||||
|
raise RuntimeError("Could not load an input action template")
|
||||||
|
|
||||||
|
action = unreal.EditorAssetLibrary.duplicate_asset(template_path, path)
|
||||||
|
if not action:
|
||||||
|
raise RuntimeError(f"Could not create {path}")
|
||||||
|
return action
|
||||||
|
|
||||||
|
|
||||||
|
def set_boolean_value_type(action):
|
||||||
|
action.set_editor_property("value_type", unreal.InputActionValueType.BOOLEAN)
|
||||||
|
try:
|
||||||
|
action.set_editor_property("triggers", [])
|
||||||
|
except Exception as exc:
|
||||||
|
unreal.log_warning(f"Could not clear stance triggers; keeping template defaults: {exc}")
|
||||||
|
unreal.EditorAssetLibrary.save_loaded_asset(action)
|
||||||
|
|
||||||
|
|
||||||
|
def mapping_exists(context, action, key_name):
|
||||||
|
mapping_data = context.get_editor_property("default_key_mappings")
|
||||||
|
for mapping in list(mapping_data.get_editor_property("mappings")):
|
||||||
|
mapping_key = mapping.get_editor_property("key")
|
||||||
|
if (
|
||||||
|
mapping.get_editor_property("action") == action
|
||||||
|
and str(mapping_key.get_editor_property("key_name")) == key_name
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def map_key(context, action, key_name):
|
||||||
|
if mapping_exists(context, action, key_name):
|
||||||
|
unreal.log(f"Mapping already exists: {action.get_name()} -> {key_name}")
|
||||||
|
return
|
||||||
|
|
||||||
|
key = unreal.Key()
|
||||||
|
key.set_editor_property("key_name", key_name)
|
||||||
|
|
||||||
|
mapping_data = context.get_editor_property("default_key_mappings")
|
||||||
|
mappings = list(mapping_data.get_editor_property("mappings"))
|
||||||
|
new_mapping = unreal.EnhancedActionKeyMapping()
|
||||||
|
new_mapping.set_editor_property("action", action)
|
||||||
|
new_mapping.set_editor_property("key", key)
|
||||||
|
mappings.append(new_mapping)
|
||||||
|
mapping_data.set_editor_property("mappings", mappings)
|
||||||
|
context.set_editor_property("default_key_mappings", mapping_data)
|
||||||
|
|
||||||
|
unreal.log(f"Added mapping: {action.get_name()} -> {key_name}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
crouch_action = create_input_action("/Game/Input/Actions/IA_Crouch")
|
||||||
|
prone_action = create_input_action("/Game/Input/Actions/IA_Prone")
|
||||||
|
set_boolean_value_type(crouch_action)
|
||||||
|
set_boolean_value_type(prone_action)
|
||||||
|
|
||||||
|
context = load("/Game/Input/IMC_Default")
|
||||||
|
map_key(context, crouch_action, "C")
|
||||||
|
map_key(context, crouch_action, "Gamepad_RightShoulder")
|
||||||
|
map_key(context, prone_action, "Z")
|
||||||
|
map_key(context, prone_action, "Gamepad_LeftShoulder")
|
||||||
|
unreal.EditorAssetLibrary.save_loaded_asset(context)
|
||||||
|
|
||||||
|
character_bp = load("/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter")
|
||||||
|
character_cdo = unreal.get_default_object(character_bp.generated_class())
|
||||||
|
character_cdo.set_editor_property("CrouchAction", crouch_action)
|
||||||
|
character_cdo.set_editor_property("ProneAction", prone_action)
|
||||||
|
for property_name, value in STANCE_DEFAULTS.items():
|
||||||
|
character_cdo.set_editor_property(property_name, value)
|
||||||
|
unreal.EditorAssetLibrary.save_loaded_asset(character_bp)
|
||||||
|
|
||||||
|
unreal.log("Agrarian stance input setup complete.")
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import math
|
||||||
|
import unreal
|
||||||
|
|
||||||
|
|
||||||
|
STANCE_DEFAULTS = {
|
||||||
|
"CrouchSpeedMultiplier": 0.55,
|
||||||
|
"ProneSpeedMultiplier": 0.25,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def load(path):
|
||||||
|
asset = unreal.EditorAssetLibrary.load_asset(path)
|
||||||
|
if not asset:
|
||||||
|
raise RuntimeError(f"Could not load {path}")
|
||||||
|
return asset
|
||||||
|
|
||||||
|
|
||||||
|
def mapping_found(context, action, key_name):
|
||||||
|
mapping_data = context.get_editor_property("default_key_mappings")
|
||||||
|
for mapping in list(mapping_data.get_editor_property("mappings")):
|
||||||
|
mapping_key = mapping.get_editor_property("key")
|
||||||
|
if (
|
||||||
|
mapping.get_editor_property("action") == action
|
||||||
|
and str(mapping_key.get_editor_property("key_name")) == key_name
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
crouch_action = load("/Game/Input/Actions/IA_Crouch")
|
||||||
|
prone_action = load("/Game/Input/Actions/IA_Prone")
|
||||||
|
context = load("/Game/Input/IMC_Default")
|
||||||
|
character_bp = load("/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter")
|
||||||
|
character_cdo = unreal.get_default_object(character_bp.generated_class())
|
||||||
|
|
||||||
|
missing = []
|
||||||
|
for action, key_name in [
|
||||||
|
(crouch_action, "C"),
|
||||||
|
(crouch_action, "Gamepad_RightShoulder"),
|
||||||
|
(prone_action, "Z"),
|
||||||
|
(prone_action, "Gamepad_LeftShoulder"),
|
||||||
|
]:
|
||||||
|
if not mapping_found(context, action, key_name):
|
||||||
|
missing.append(f"missing mapping {action.get_name()} -> {key_name}")
|
||||||
|
|
||||||
|
if character_cdo.get_editor_property("CrouchAction") != crouch_action:
|
||||||
|
missing.append("BP_ThirdPersonCharacter CrouchAction is not IA_Crouch")
|
||||||
|
if character_cdo.get_editor_property("ProneAction") != prone_action:
|
||||||
|
missing.append("BP_ThirdPersonCharacter ProneAction is not IA_Prone")
|
||||||
|
|
||||||
|
for property_name, expected in STANCE_DEFAULTS.items():
|
||||||
|
actual = float(character_cdo.get_editor_property(property_name))
|
||||||
|
if not math.isclose(actual, expected, rel_tol=0.0, abs_tol=0.01):
|
||||||
|
missing.append(f"{property_name}: expected {expected}, got {actual}")
|
||||||
|
|
||||||
|
if missing:
|
||||||
|
raise RuntimeError("Stance input verification failed: " + "; ".join(missing))
|
||||||
|
|
||||||
|
unreal.log("Agrarian stance input verification complete.")
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -31,6 +31,7 @@ AAgrarianGameCharacter::AAgrarianGameCharacter()
|
|||||||
bUseControllerRotationRoll = false;
|
bUseControllerRotationRoll = false;
|
||||||
|
|
||||||
// Configure character movement
|
// Configure character movement
|
||||||
|
GetCharacterMovement()->NavAgentProps.bCanCrouch = true;
|
||||||
GetCharacterMovement()->bOrientRotationToMovement = true;
|
GetCharacterMovement()->bOrientRotationToMovement = true;
|
||||||
GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f);
|
GetCharacterMovement()->RotationRate = FRotator(0.0f, 500.0f, 0.0f);
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@ AAgrarianGameCharacter::AAgrarianGameCharacter()
|
|||||||
GetCharacterMovement()->JumpZVelocity = 500.f;
|
GetCharacterMovement()->JumpZVelocity = 500.f;
|
||||||
GetCharacterMovement()->AirControl = 0.35f;
|
GetCharacterMovement()->AirControl = 0.35f;
|
||||||
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
|
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
|
||||||
|
GetCharacterMovement()->MaxWalkSpeedCrouched = WalkSpeed * CrouchSpeedMultiplier;
|
||||||
GetCharacterMovement()->MinAnalogWalkSpeed = 20.f;
|
GetCharacterMovement()->MinAnalogWalkSpeed = 20.f;
|
||||||
GetCharacterMovement()->BrakingDecelerationWalking = 2000.f;
|
GetCharacterMovement()->BrakingDecelerationWalking = 2000.f;
|
||||||
GetCharacterMovement()->BrakingDecelerationFalling = 1500.0f;
|
GetCharacterMovement()->BrakingDecelerationFalling = 1500.0f;
|
||||||
@@ -95,6 +97,7 @@ void AAgrarianGameCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty
|
|||||||
{
|
{
|
||||||
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||||
DOREPLIFETIME(AAgrarianGameCharacter, bWantsToSprint);
|
DOREPLIFETIME(AAgrarianGameCharacter, bWantsToSprint);
|
||||||
|
DOREPLIFETIME(AAgrarianGameCharacter, bIsProne);
|
||||||
DOREPLIFETIME(AAgrarianGameCharacter, AgeYears);
|
DOREPLIFETIME(AAgrarianGameCharacter, AgeYears);
|
||||||
DOREPLIFETIME(AAgrarianGameCharacter, PhysicalConditionMultiplier);
|
DOREPLIFETIME(AAgrarianGameCharacter, PhysicalConditionMultiplier);
|
||||||
DOREPLIFETIME(AAgrarianGameCharacter, StrengthMultiplier);
|
DOREPLIFETIME(AAgrarianGameCharacter, StrengthMultiplier);
|
||||||
@@ -130,6 +133,16 @@ void AAgrarianGameCharacter::SetupPlayerInputComponent(UInputComponent* PlayerIn
|
|||||||
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Canceled, this, &AAgrarianGameCharacter::StopSprint);
|
EnhancedInputComponent->BindAction(SprintAction, ETriggerEvent::Canceled, this, &AAgrarianGameCharacter::StopSprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CrouchAction)
|
||||||
|
{
|
||||||
|
EnhancedInputComponent->BindAction(CrouchAction, ETriggerEvent::Started, this, &AAgrarianGameCharacter::ToggleCrouchStance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ProneAction)
|
||||||
|
{
|
||||||
|
EnhancedInputComponent->BindAction(ProneAction, ETriggerEvent::Started, this, &AAgrarianGameCharacter::ToggleProneStance);
|
||||||
|
}
|
||||||
|
|
||||||
if (ToggleCameraAction)
|
if (ToggleCameraAction)
|
||||||
{
|
{
|
||||||
EnhancedInputComponent->BindAction(ToggleCameraAction, ETriggerEvent::Started, this, &AAgrarianGameCharacter::ToggleCameraPerspective);
|
EnhancedInputComponent->BindAction(ToggleCameraAction, ETriggerEvent::Started, this, &AAgrarianGameCharacter::ToggleCameraPerspective);
|
||||||
@@ -166,6 +179,11 @@ void AAgrarianGameCharacter::Interact()
|
|||||||
|
|
||||||
void AAgrarianGameCharacter::StartSprint()
|
void AAgrarianGameCharacter::StartSprint()
|
||||||
{
|
{
|
||||||
|
if (bIsProne || bIsCrouched)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SetWantsToSprint(true);
|
SetWantsToSprint(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +192,32 @@ void AAgrarianGameCharacter::StopSprint()
|
|||||||
SetWantsToSprint(false);
|
SetWantsToSprint(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AAgrarianGameCharacter::ToggleCrouchStance()
|
||||||
|
{
|
||||||
|
if (bIsProne)
|
||||||
|
{
|
||||||
|
SetProne(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWantsToSprint(false);
|
||||||
|
if (bIsCrouched)
|
||||||
|
{
|
||||||
|
UnCrouch();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Crouch();
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyMovementSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AAgrarianGameCharacter::ToggleProneStance()
|
||||||
|
{
|
||||||
|
SetProne(!bIsProne);
|
||||||
|
}
|
||||||
|
|
||||||
void AAgrarianGameCharacter::ToggleCameraPerspective()
|
void AAgrarianGameCharacter::ToggleCameraPerspective()
|
||||||
{
|
{
|
||||||
SetFirstPersonCamera(!bFirstPersonCamera);
|
SetFirstPersonCamera(!bFirstPersonCamera);
|
||||||
@@ -235,6 +279,8 @@ bool AAgrarianGameCharacter::CanSprint() const
|
|||||||
{
|
{
|
||||||
return SurvivalComponent
|
return SurvivalComponent
|
||||||
&& SurvivalComponent->IsAlive()
|
&& SurvivalComponent->IsAlive()
|
||||||
|
&& !bIsProne
|
||||||
|
&& !bIsCrouched
|
||||||
&& SurvivalComponent->Survival.Stamina > MinSprintStamina;
|
&& SurvivalComponent->Survival.Stamina > MinSprintStamina;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,6 +299,29 @@ float AAgrarianGameCharacter::GetCurrentMovementSpeedMultiplier() const
|
|||||||
return CalculateMovementSpeedMultiplier();
|
return CalculateMovementSpeedMultiplier();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AAgrarianGameCharacter::SetProne(bool bNewProne)
|
||||||
|
{
|
||||||
|
if (bIsProne == bNewProne)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bIsProne = bNewProne;
|
||||||
|
|
||||||
|
if (bIsProne)
|
||||||
|
{
|
||||||
|
SetWantsToSprint(false);
|
||||||
|
UnCrouch();
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyMovementSpeed();
|
||||||
|
|
||||||
|
if (!HasAuthority())
|
||||||
|
{
|
||||||
|
ServerSetProne(bIsProne);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AAgrarianGameCharacter::SetTerrainMovementMultiplier(float NewTerrainMovementMultiplier)
|
void AAgrarianGameCharacter::SetTerrainMovementMultiplier(float NewTerrainMovementMultiplier)
|
||||||
{
|
{
|
||||||
TerrainMovementMultiplier = FMath::Clamp(NewTerrainMovementMultiplier, 0.25f, 1.25f);
|
TerrainMovementMultiplier = FMath::Clamp(NewTerrainMovementMultiplier, 0.25f, 1.25f);
|
||||||
@@ -264,7 +333,9 @@ void AAgrarianGameCharacter::ApplyMovementSpeed()
|
|||||||
if (UCharacterMovementComponent* MovementComponent = GetCharacterMovement())
|
if (UCharacterMovementComponent* MovementComponent = GetCharacterMovement())
|
||||||
{
|
{
|
||||||
const float BaseSpeed = IsSprinting() ? SprintSpeed : WalkSpeed;
|
const float BaseSpeed = IsSprinting() ? SprintSpeed : WalkSpeed;
|
||||||
MovementComponent->MaxWalkSpeed = FMath::Max(0.0f, BaseSpeed * CalculateMovementSpeedMultiplier());
|
const float FinalSpeed = FMath::Max(0.0f, BaseSpeed * CalculateMovementSpeedMultiplier());
|
||||||
|
MovementComponent->MaxWalkSpeed = FinalSpeed;
|
||||||
|
MovementComponent->MaxWalkSpeedCrouched = FinalSpeed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,6 +349,7 @@ float AAgrarianGameCharacter::CalculateMovementSpeedMultiplier() const
|
|||||||
* TraitMultiplier
|
* TraitMultiplier
|
||||||
* CalculateSurvivalMovementMultiplier()
|
* CalculateSurvivalMovementMultiplier()
|
||||||
* CalculateCarryWeightMovementMultiplier()
|
* CalculateCarryWeightMovementMultiplier()
|
||||||
|
* CalculateStanceMovementMultiplier()
|
||||||
* FMath::Clamp(TerrainMovementMultiplier, 0.25f, 1.25f),
|
* FMath::Clamp(TerrainMovementMultiplier, 0.25f, 1.25f),
|
||||||
0.15f,
|
0.15f,
|
||||||
1.35f);
|
1.35f);
|
||||||
@@ -353,11 +425,36 @@ float AAgrarianGameCharacter::CalculateCarryWeightMovementMultiplier() const
|
|||||||
CurrentCarryWeight);
|
CurrentCarryWeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float AAgrarianGameCharacter::CalculateStanceMovementMultiplier() const
|
||||||
|
{
|
||||||
|
if (bIsProne)
|
||||||
|
{
|
||||||
|
return FMath::Clamp(ProneSpeedMultiplier, 0.05f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bIsCrouched)
|
||||||
|
{
|
||||||
|
return FMath::Clamp(CrouchSpeedMultiplier, 0.1f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
void AAgrarianGameCharacter::OnRep_SprintState()
|
void AAgrarianGameCharacter::OnRep_SprintState()
|
||||||
{
|
{
|
||||||
ApplyMovementSpeed();
|
ApplyMovementSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AAgrarianGameCharacter::OnRep_ProneState()
|
||||||
|
{
|
||||||
|
if (bIsProne)
|
||||||
|
{
|
||||||
|
UnCrouch();
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyMovementSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
void AAgrarianGameCharacter::DoMove(float Right, float Forward)
|
void AAgrarianGameCharacter::DoMove(float Right, float Forward)
|
||||||
{
|
{
|
||||||
if (GetController() != nullptr)
|
if (GetController() != nullptr)
|
||||||
@@ -448,6 +545,11 @@ void AAgrarianGameCharacter::ServerSetWantsToSprint_Implementation(bool bNewWant
|
|||||||
SetWantsToSprint(bNewWantsToSprint);
|
SetWantsToSprint(bNewWantsToSprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AAgrarianGameCharacter::ServerSetProne_Implementation(bool bNewProne)
|
||||||
|
{
|
||||||
|
SetProne(bNewProne);
|
||||||
|
}
|
||||||
|
|
||||||
void AAgrarianGameCharacter::ServerInteract_Implementation(AActor* TargetActor)
|
void AAgrarianGameCharacter::ServerInteract_Implementation(AActor* TargetActor)
|
||||||
{
|
{
|
||||||
if (!TargetActor || !TargetActor->GetClass()->ImplementsInterface(UAgrarianInteractable::StaticClass()))
|
if (!TargetActor || !TargetActor->GetClass()->ImplementsInterface(UAgrarianInteractable::StaticClass()))
|
||||||
|
|||||||
@@ -77,6 +77,14 @@ protected:
|
|||||||
UPROPERTY(EditAnywhere, Category="Input")
|
UPROPERTY(EditAnywhere, Category="Input")
|
||||||
UInputAction* SprintAction;
|
UInputAction* SprintAction;
|
||||||
|
|
||||||
|
/** Toggle crouch movement stance. */
|
||||||
|
UPROPERTY(EditAnywhere, Category="Input")
|
||||||
|
UInputAction* CrouchAction;
|
||||||
|
|
||||||
|
/** Toggle prone movement stance. */
|
||||||
|
UPROPERTY(EditAnywhere, Category="Input")
|
||||||
|
UInputAction* ProneAction;
|
||||||
|
|
||||||
/** Toggle between third-person and first-person camera views. */
|
/** Toggle between third-person and first-person camera views. */
|
||||||
UPROPERTY(EditAnywhere, Category="Input")
|
UPROPERTY(EditAnywhere, Category="Input")
|
||||||
UInputAction* ToggleCameraAction;
|
UInputAction* ToggleCameraAction;
|
||||||
@@ -101,6 +109,14 @@ protected:
|
|||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement", meta = (ClampMin = "0", ClampMax = "100"))
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement", meta = (ClampMin = "0", ClampMax = "100"))
|
||||||
float MinSprintStamina = 5.0f;
|
float MinSprintStamina = 5.0f;
|
||||||
|
|
||||||
|
/** Movement multiplier while crouched. */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement|Stance", meta = (ClampMin = "0.1", ClampMax = "1"))
|
||||||
|
float CrouchSpeedMultiplier = 0.55f;
|
||||||
|
|
||||||
|
/** Movement multiplier while prone. */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Agrarian|Movement|Stance", meta = (ClampMin = "0.05", ClampMax = "1"))
|
||||||
|
float ProneSpeedMultiplier = 0.25f;
|
||||||
|
|
||||||
/** Age hook used by movement until full lifecycle/aging systems own it. */
|
/** Age hook used by movement until full lifecycle/aging systems own it. */
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0"))
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category="Agrarian|Movement|Modifiers", meta = (ClampMin = "0"))
|
||||||
float AgeYears = 25.0f;
|
float AgeYears = 25.0f;
|
||||||
@@ -145,6 +161,10 @@ protected:
|
|||||||
UPROPERTY(ReplicatedUsing = OnRep_SprintState, VisibleAnywhere, BlueprintReadOnly, Category="Agrarian|Movement", meta = (AllowPrivateAccess = "true"))
|
UPROPERTY(ReplicatedUsing = OnRep_SprintState, VisibleAnywhere, BlueprintReadOnly, Category="Agrarian|Movement", meta = (AllowPrivateAccess = "true"))
|
||||||
bool bWantsToSprint = false;
|
bool bWantsToSprint = false;
|
||||||
|
|
||||||
|
/** Replicated prone stance for low crawl movement. */
|
||||||
|
UPROPERTY(ReplicatedUsing = OnRep_ProneState, VisibleAnywhere, BlueprintReadOnly, Category="Agrarian|Movement|Stance", meta = (AllowPrivateAccess = "true"))
|
||||||
|
bool bIsProne = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Constructor */
|
/** Constructor */
|
||||||
@@ -175,6 +195,12 @@ protected:
|
|||||||
/** Called when sprint input is released. */
|
/** Called when sprint input is released. */
|
||||||
void StopSprint();
|
void StopSprint();
|
||||||
|
|
||||||
|
/** Called when crouch input is pressed. */
|
||||||
|
void ToggleCrouchStance();
|
||||||
|
|
||||||
|
/** Called when prone input is pressed. */
|
||||||
|
void ToggleProneStance();
|
||||||
|
|
||||||
/** Called for camera perspective toggle input */
|
/** Called for camera perspective toggle input */
|
||||||
void ToggleCameraPerspective();
|
void ToggleCameraPerspective();
|
||||||
|
|
||||||
@@ -196,10 +222,14 @@ protected:
|
|||||||
float CalculateAgeMovementMultiplier() const;
|
float CalculateAgeMovementMultiplier() const;
|
||||||
float CalculateSurvivalMovementMultiplier() const;
|
float CalculateSurvivalMovementMultiplier() const;
|
||||||
float CalculateCarryWeightMovementMultiplier() const;
|
float CalculateCarryWeightMovementMultiplier() const;
|
||||||
|
float CalculateStanceMovementMultiplier() const;
|
||||||
|
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void OnRep_SprintState();
|
void OnRep_SprintState();
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void OnRep_ProneState();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Handles move inputs from either controls or UI interfaces */
|
/** Handles move inputs from either controls or UI interfaces */
|
||||||
@@ -230,6 +260,12 @@ public:
|
|||||||
UFUNCTION(BlueprintPure, Category="Agrarian|Movement")
|
UFUNCTION(BlueprintPure, Category="Agrarian|Movement")
|
||||||
bool IsSprinting() const;
|
bool IsSprinting() const;
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintPure, Category="Agrarian|Movement|Stance")
|
||||||
|
bool IsProne() const { return bIsProne; }
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, Category="Agrarian|Movement|Stance")
|
||||||
|
void SetProne(bool bNewProne);
|
||||||
|
|
||||||
UFUNCTION(BlueprintPure, Category="Agrarian|Movement")
|
UFUNCTION(BlueprintPure, Category="Agrarian|Movement")
|
||||||
float GetCurrentCarryWeight() const;
|
float GetCurrentCarryWeight() const;
|
||||||
|
|
||||||
@@ -247,6 +283,10 @@ public:
|
|||||||
UFUNCTION(Server, Reliable)
|
UFUNCTION(Server, Reliable)
|
||||||
void ServerSetWantsToSprint(bool bNewWantsToSprint);
|
void ServerSetWantsToSprint(bool bNewWantsToSprint);
|
||||||
|
|
||||||
|
/** Server-authoritative prone stance update. */
|
||||||
|
UFUNCTION(Server, Reliable)
|
||||||
|
void ServerSetProne(bool bNewProne);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Returns CameraBoom subobject **/
|
/** Returns CameraBoom subobject **/
|
||||||
|
|||||||
Reference in New Issue
Block a user