A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
CharacterMovementCompTypes.cpp
Go to the documentation of this file.
1// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
2
3/*=============================================================================
4 Movement.cpp: Character movement implementation
5
6=============================================================================*/
7
10#include "VRBPDatatypes.h"
12#include "VRBaseCharacter.h"
13#include "VRRootComponent.h"
14#include "VRPlayerController.h"
15
23
25{
26 // Fills in 01 and 02 for Jump / Crouch
27 uint8 Result = FSavedMove_Character::GetCompressedFlags();
28
29 // Not supporting custom movement mode directly at this time by replicating custom index
30 // We use 4 bits for this so a maximum of 16 elements
31 //Result |= (uint8)VRReplicatedMovementMode << 2;
32
33 // This takes up custom_2
34 /*if (bWantsToSnapTurn)
35 {
36 Result |= FLAG_SnapTurn;
37 }*/
38
39 // Reserved_1, and Reserved_2, Flag_Custom_0 and Flag_Custom_1 are used up
40 // By the VRReplicatedMovementMode packing
41
42
43 // only custom_2 and custom_3 are left currently
44 return Result;
45}
46
47bool FSavedMove_VRBaseCharacter::CanCombineWith(const FSavedMovePtr& NewMove, ACharacter* Character, float MaxDelta) const
48{
50
51
52 if (!nMove || (VRReplicatedMovementMode != nMove->VRReplicatedMovementMode))
53 return false;
54
56 return false;
57
59 return false;
60
62 return false;
63
64 // Hate this but we really can't combine if I am sending a new capsule height
65 if (!FMath::IsNearlyEqual(LFDiff.Z, nMove->LFDiff.Z))
66 return false;
67
68 if (!FVector2D(LFDiff.X, LFDiff.Y).IsZero() && !FVector2D(nMove->LFDiff.X, nMove->LFDiff.Y).IsZero() && !FVector::Coincident(LFDiff.GetSafeNormal2D(), nMove->LFDiff.GetSafeNormal2D(), AccelDotThresholdCombine))
69 return false;
70
71 return FSavedMove_Character::CanCombineWith(NewMove, Character, MaxDelta);
72}
73
74
75bool FSavedMove_VRBaseCharacter::IsImportantMove(const FSavedMovePtr& LastAckedMove) const
76{
77 // Auto important if toggled climbing
79 return true;
80
82 return true;
83
85 return true;
86
88 return true;
89
90 // #TODO: What to do here?
91 // This is debatable, however it will ALWAYS be non zero realistically and only really effects step ups for the most part
92 //if (!LFDiff.IsNearlyZero())
93 //return true;
94
95 // Else check parent class
96 return FSavedMove_Character::IsImportantMove(LastAckedMove);
97}
98
100{
101 // See if we can get the VR capsule location
102 //if (AVRBaseCharacter * VRC = Cast<AVRBaseCharacter>(C))
103 //{
104 if (UVRBaseCharacterMovementComponent* moveComp = Cast<UVRBaseCharacterMovementComponent>(C->GetMovementComponent()))
105 {
106
107 // Saving this out early because it will be wiped before the PostUpdate gets the values
108 //ConditionalValues.MoveAction.MoveAction = moveComp->MoveAction.MoveAction;
109
110 VRReplicatedMovementMode = moveComp->VRReplicatedMovementMode;
111
112 if (moveComp->HasRequestedVelocity())
113 ConditionalValues.RequestedVelocity = moveComp->RequestedVelocity;
114 else
115 ConditionalValues.RequestedVelocity = FVector::ZeroVector;
116
117 // Throw out the Z value of the headset, its not used anyway for movement
118 // Instead, re-purpose it to be the capsule half height
119 if (AVRBaseCharacter* BaseChar = Cast<AVRBaseCharacter>(C))
120 {
121 if (BaseChar->VRReplicateCapsuleHeight)
122 LFDiff.Z = BaseChar->GetCapsuleComponent()->GetUnscaledCapsuleHalfHeight();
123 else
124 LFDiff.Z = 0.0f;
125 }
126 else
127 LFDiff.Z = 0.0f;
128 }
129 else
130 {
132 ConditionalValues.CustomVRInputVector = FVector::ZeroVector;
133 ConditionalValues.RequestedVelocity = FVector::ZeroVector;
134 }
135 //}
136 //else
137 //{
138 // VRReplicatedMovementMode = EVRConjoinedMovementModes::C_MOVE_MAX;//None;
139 // ConditionalValues.CustomVRInputVector = FVector::ZeroVector;
140 //}
141
142 FSavedMove_Character::SetInitialPosition(C);
143}
144
145void FSavedMove_VRBaseCharacter::CombineWith(const FSavedMove_Character* OldMove, ACharacter* InCharacter, APlayerController* PC, const FVector& OldStartLocation)
146{
147 UCharacterMovementComponent* CharMovement = InCharacter->GetCharacterMovement();
148
149 // to combine move, first revert pawn position to PendingMove start position, before playing combined move on client
150 CharMovement->UpdatedComponent->SetWorldLocationAndRotation(OldStartLocation, OldMove->StartRotation, false, nullptr, CharMovement->GetTeleportType());
151 CharMovement->Velocity = OldMove->StartVelocity;
152
153 CharMovement->SetBase(OldMove->StartBase.Get(), OldMove->StartBoneName);
154 CharMovement->CurrentFloor = OldMove->StartFloor;
155
156 // Now that we have reverted to the old position, prepare a new move from that position,
157 // using our current velocity, acceleration, and rotation, but applied over the combined time from the old and new move.
158
159 // Combine times for both moves
160 DeltaTime += OldMove->DeltaTime;
161
162 //FSavedMove_VRBaseCharacter * BaseSavedMove = (FSavedMove_VRBaseCharacter *)NewMove.Get();
163 FSavedMove_VRBaseCharacter* BaseSavedMovePending = (FSavedMove_VRBaseCharacter*)OldMove;
164
165 if (/*BaseSavedMove && */BaseSavedMovePending)
166 {
167 LFDiff.X += BaseSavedMovePending->LFDiff.X;
168 LFDiff.Y += BaseSavedMovePending->LFDiff.Y;
169 }
170
171 // Roll back jump force counters. SetInitialPosition() below will copy them to the saved move.
172 // Changes in certain counters like JumpCurrentCount don't allow move combining, so no need to roll those back (they are the same).
173 InCharacter->JumpForceTimeRemaining = OldMove->JumpForceTimeRemaining;
174 InCharacter->JumpKeyHoldTime = OldMove->JumpKeyHoldTime;
175}
176
177void FSavedMove_VRBaseCharacter::PostUpdate(ACharacter* C, EPostUpdateMode PostUpdateMode)
178{
179 FSavedMove_Character::PostUpdate(C, PostUpdateMode);
180
181 // See if we can get the VR capsule location
182 //if (AVRBaseCharacter * VRC = Cast<AVRBaseCharacter>(C))
183 //{
184 if (UVRBaseCharacterMovementComponent* moveComp = Cast<UVRBaseCharacterMovementComponent>(C->GetMovementComponent()))
185 {
186 ConditionalValues.CustomVRInputVector = moveComp->CustomVRInputVector;
187 ConditionalValues.MoveActionArray = moveComp->MoveActionArray;
188 moveComp->MoveActionArray.Clear();
189 }
190 //}
191 /*if (ConditionalValues.MoveAction.MoveAction != EVRMoveAction::VRMOVEACTION_None)
192 {
193 // See if we can get the VR capsule location
194 if (AVRBaseCharacter * VRC = Cast<AVRBaseCharacter>(C))
195 {
196 if (UVRBaseCharacterMovementComponent * moveComp = Cast<UVRBaseCharacterMovementComponent>(VRC->GetMovementComponent()))
197 {
198 // This is cleared out in perform movement so I need to save it before applying below
199 EVRMoveAction tempAction = ConditionalValues.MoveAction.MoveAction;
200 ConditionalValues.MoveAction = moveComp->MoveAction;
201 ConditionalValues.MoveAction.MoveAction = tempAction;
202 }
203 else
204 {
205 ConditionalValues.MoveAction.Clear();
206 }
207 }
208 else
209 {
210 ConditionalValues.MoveAction.Clear();
211 }
212 }*/
213}
214
216{
218
219 VRCapsuleLocation = FVector::ZeroVector;
220 VRCapsuleRotation = FRotator::ZeroRotator;
221 LFDiff = FVector::ZeroVector;
222
223 ConditionalValues.CustomVRInputVector = FVector::ZeroVector;
224 ConditionalValues.RequestedVelocity = FVector::ZeroVector;
226 //ConditionalValues.MoveAction.Clear();
227
228 FSavedMove_Character::Clear();
229}
230
232{
233 UVRBaseCharacterMovementComponent* BaseCharMove = Cast<UVRBaseCharacterMovementComponent>(Character->GetCharacterMovement());
234
235 if (BaseCharMove)
236 {
238 //BaseCharMove->MoveAction = ConditionalValues.MoveAction;
239 BaseCharMove->CustomVRInputVector = ConditionalValues.CustomVRInputVector;//this->CustomVRInputVector;
241 }
242
244 {
245 BaseCharMove->RequestedVelocity = ConditionalValues.RequestedVelocity;
246 BaseCharMove->SetHasRequestedVelocity(true);
247 }
248 else
249 {
250 BaseCharMove->SetHasRequestedVelocity(false);
251 }
252
253 FSavedMove_Character::PrepMoveFor(Character);
254}
255
256FVRCharacterScopedMovementUpdate::FVRCharacterScopedMovementUpdate(USceneComponent* Component, EScopedUpdate::Type ScopeBehavior, bool bRequireOverlapsEventFlagToQueueOverlaps)
257 : FScopedMovementUpdate(Component, ScopeBehavior, bRequireOverlapsEventFlagToQueueOverlaps)
258{
259 UVRRootComponent* RootComponent = Cast<UVRRootComponent>(Owner);
260 if (RootComponent)
261 {
263 }
264}
265
267{
268 bool bTransformIsDirty = IsTransformDirty();
269
270 FScopedMovementUpdate::RevertMove();
271
272 UVRRootComponent* RootComponent = Cast<UVRRootComponent>(Owner);
273 if (RootComponent)
274 {
275 // If the base class was going to miss bad overlaps, ie: the offsetcomponent to world is different but the transform isn't
276 if (!bTransformIsDirty && !IsDeferringUpdates() && !InitialVRTransform.Equals(RootComponent->OffsetComponentToWorld))
277 {
278 RootComponent->UpdateOverlaps();
279 }
280
281 // Fix offset
282 RootComponent->GenerateOffsetToWorld();
283 }
284}
285
286
294
298
299void FVRCharacterNetworkMoveData::ClientFillNetworkMoveData(const FSavedMove_Character& ClientMove, ENetworkMoveType MoveType)
300{
301 // Handles the movement base itself now
302 FCharacterNetworkMoveData::ClientFillNetworkMoveData(ClientMove, MoveType);
303
304 // I know that we overloaded this, so it should be our base type
305 if (const FSavedMove_VRBaseCharacter* SavedMove = (const FSavedMove_VRBaseCharacter*)(&ClientMove))
306 {
307 ReplicatedMovementMode = SavedMove->VRReplicatedMovementMode;
308 ConditionalMoveReps = SavedMove->ConditionalValues;
309
310 // #TODO: Roll these into the conditionals
311 VRCapsuleLocation = SavedMove->VRCapsuleLocation;
312 LFDiff = SavedMove->LFDiff;
313 VRCapsuleRotation = FRotator::CompressAxisToShort(SavedMove->VRCapsuleRotation.Yaw);
314 }
315}
316
317bool FVRCharacterNetworkMoveData::Serialize(UCharacterMovementComponent& CharacterMovement, FArchive& Ar, UPackageMap* PackageMap, ENetworkMoveType MoveType)
318{
319 NetworkMoveType = MoveType;
320
321 bool bLocalSuccess = true;
322 const bool bIsSaving = Ar.IsSaving();
323
324 Ar << TimeStamp;
325
326 // Handle switching the acceleration rep
327 // Can't use SerializeOptionalValue here as I don't want to bitwise compare floats
328 bool bRepAccel = bIsSaving ? !Acceleration.IsNearlyZero() : false;
329 Ar.SerializeBits(&bRepAccel, 1);
330
331 if (bRepAccel)
332 {
333 Acceleration.NetSerialize(Ar, PackageMap, bLocalSuccess);
334 }
335 else
336 {
337 if (!bIsSaving)
338 {
339 Acceleration = FVector::ZeroVector;
340 }
341 }
342
343 //Location.NetSerialize(Ar, PackageMap, bLocalSuccess);
344
345 uint16 Yaw = bIsSaving ? FRotator::CompressAxisToShort(ControlRotation.Yaw) : 0;
346 uint16 Pitch = bIsSaving ? FRotator::CompressAxisToShort(ControlRotation.Pitch) : 0;
347 uint16 Roll = bIsSaving ? FRotator::CompressAxisToShort(ControlRotation.Roll) : 0;
348 bool bRepYaw = Yaw != 0;
349
350 ACharacter* CharacterOwner = CharacterMovement.GetCharacterOwner();
351
352 bool bCanRepRollAndPitch = (CharacterOwner && (CharacterOwner->bUseControllerRotationRoll || CharacterOwner->bUseControllerRotationPitch));
353 bool bRepRollAndPitch = bCanRepRollAndPitch && (Roll != 0 || Pitch != 0);
354 Ar.SerializeBits(&bRepRollAndPitch, 1);
355
356 if (bRepRollAndPitch)
357 {
358 // Reversed the order of these
359 uint32 Rotation32 = 0;
360 uint32 Yaw32 = bIsSaving ? Yaw : 0;
361
362 if (bIsSaving)
363 {
364 Rotation32 = (((uint32)Roll) << 16) | ((uint32)Pitch);
365 Ar.SerializeIntPacked(Rotation32);
366 }
367 else
368 {
369 Ar.SerializeIntPacked(Rotation32);
370
371 // Reversed the order of these so it costs less to replicate
372 Pitch = (Rotation32 & 65535);
373 Roll = (Rotation32 >> 16);
374 }
375 }
376
377 uint32 Yaw32 = bIsSaving ? Yaw : 0;
378
379 Ar.SerializeBits(&bRepYaw, 1);
380 if (bRepYaw)
381 {
382 Ar.SerializeIntPacked(Yaw32);
383 Yaw = (uint16)Yaw32;
384 }
385
386 if (!bIsSaving)
387 {
388 ControlRotation.Yaw = bRepYaw ? FRotator::DecompressAxisFromShort(Yaw) : 0;
389 ControlRotation.Pitch = bRepRollAndPitch ? FRotator::DecompressAxisFromShort(Pitch) : 0;
390 ControlRotation.Roll = bRepRollAndPitch ? FRotator::DecompressAxisFromShort(Roll) : 0;
391 }
392
393 // ControlRotation : FRotator handles each component zero/non-zero test; it uses a single signal bit for zero/non-zero, and uses 16 bits per component if non-zero.
394 //ControlRotation.NetSerialize(Ar, PackageMap, bLocalSuccess);
395
396 SerializeOptionalValue<uint8>(bIsSaving, Ar, CompressedMoveFlags, 0);
397 SerializeOptionalValue<uint8>(bIsSaving, Ar, MovementMode, MOVE_Walking);
398 VRCapsuleLocation.NetSerialize(Ar, PackageMap, bLocalSuccess);
399 Ar << VRCapsuleRotation;
400
401 if (MoveType == ENetworkMoveType::NewMove)
402 {
403 Location.NetSerialize(Ar, PackageMap, bLocalSuccess);
404
405 // Location, relative movement base, and ending movement mode is only used for error checking, so only save for the final move.
406 SerializeOptionalValue<UPrimitiveComponent*>(bIsSaving, Ar, MovementBase, nullptr);
407 SerializeOptionalValue<FName>(bIsSaving, Ar, MovementBaseBoneName, NAME_None);
408 //SerializeOptionalValue<uint8>(bIsSaving, Ar, MovementMode, MOVE_Walking); // Epic has this like this too, but it is bugged and killing movements
409 }
410
411 bool bHasReplicatedMovementMode = ReplicatedMovementMode != EVRConjoinedMovementModes::C_MOVE_MAX;
412 Ar.SerializeBits(&bHasReplicatedMovementMode, 1);
413
414 if (bHasReplicatedMovementMode)
415 {
416 // Increased to 6 bits for 64 total elements instead of 16
417 Ar.SerializeBits(&ReplicatedMovementMode, 6);
418 }
419 else if (!bIsSaving)
420 {
422 }
423
424 // Rep out our custom move settings
425 ConditionalMoveReps.NetSerialize(Ar, PackageMap, bLocalSuccess);
426
427 //VRCapsuleLocation.NetSerialize(Ar, PackageMap, bLocalSuccess);
428 LFDiff.NetSerialize(Ar, PackageMap, bLocalSuccess);
429 //Ar << VRCapsuleRotation;
430
431 return !Ar.IsError();
432}
433
434
435void FVRCharacterMoveResponseDataContainer::ServerFillResponseData(const UCharacterMovementComponent& CharacterMovement, const FClientAdjustment& PendingAdjustment)
436{
437 FCharacterMoveResponseDataContainer::ServerFillResponseData(CharacterMovement, PendingAdjustment);
438
439 if (const UVRBaseCharacterMovementComponent* BaseMovecomp = Cast<const UVRBaseCharacterMovementComponent>(&CharacterMovement))
440 {
441 bHasRotation = !BaseMovecomp->bUseClientControlRotation;
442 }
443}
virtual bool IsImportantMove(const FSavedMovePtr &LastAckedMove) const override
virtual bool CanCombineWith(const FSavedMovePtr &NewMove, ACharacter *Character, float MaxDelta) const override
virtual void PostUpdate(ACharacter *C, EPostUpdateMode PostUpdateMode) override
virtual void CombineWith(const FSavedMove_Character *OldMove, ACharacter *InCharacter, APlayerController *PC, const FVector &OldStartLocation) override
virtual void PrepMoveFor(ACharacter *Character) override
EVRConjoinedMovementModes VRReplicatedMovementMode
virtual uint8 GetCompressedFlags() const override
virtual void SetInitialPosition(ACharacter *C)
FVRCharacterScopedMovementUpdate(USceneComponent *Component, EScopedUpdate::Type ScopeBehavior=EScopedUpdate::DeferredUpdates, bool bRequireOverlapsEventFlagToQueueOverlaps=true)
void SetHasRequestedVelocity(bool bNewHasRequestedVelocity)
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent), ClassGroup = VRExpansionLibrary)
FORCEINLINE void GenerateOffsetToWorld(bool bUpdateBounds=true, bool bGetPureYaw=true)
FTransform OffsetComponentToWorld
virtual void ServerFillResponseData(const UCharacterMovementComponent &CharacterMovement, const FClientAdjustment &PendingAdjustment) override
virtual void ClientFillNetworkMoveData(const FSavedMove_Character &ClientMove, ENetworkMoveType MoveType) override
EVRConjoinedMovementModes ReplicatedMovementMode
virtual bool Serialize(UCharacterMovementComponent &CharacterMovement, FArchive &Ar, UPackageMap *PackageMap, ENetworkMoveType MoveType) override
bool NetSerialize(FArchive &Ar, class UPackageMap *Map, bool &bOutSuccess)
FVector RequestedVelocity
UPROPERTY(Transient)
FVector CustomVRInputVector
UPROPERTY(Transient)
FVRMoveActionArray MoveActionArray
UPROPERTY(Transient)
TArray< FVRMoveActionContainer > MoveActions
UPROPERTY()