x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Animations replicate for Clients but not for Server

I am not sure if anyone has had a similar issue. I don't know if this is a bug or what. I Implemented a 'Melee' attack. everything works great except when in multiplayer. The animation replicates and plays for everyone when one of the clients performs the attack. However when the server performs the melee attack it works properly but the animation doesn't play. Here is my code:

MyCharacter.cpp

 void AArenaCharacter::OnMelee()
 {
     AArenaPlayerController* MyPC = Cast<AArenaPlayerController>(Controller);
     if (MyPC && MyPC->IsGameInputAllowed())
     {
         IdleTime = 0.0f;
         bDoingMelee = true;
         CurrentWeapon->StartMelee();
     }
 }
 
 void AArenaCharacter::OnStopMelee()
 {
     bDoingMelee = false;
     HitActors.Empty();
 }
 
 bool AArenaCharacter::CanMelee() const
 {
     return true;
 }
 
 void AArenaCharacter::AttackTrace()
 {
     //Overlapping actors for each box spawned will be stored here
     TArray<struct FOverlapResult> OutOverlaps;
     //The initial rotation of our box is the same as our character rotation
     FQuat Rotation = Instigator->GetTransform().GetRotation();
     FVector Start = Instigator->GetTransform().GetLocation() + Rotation.Rotator().Vector() * 100.0f;
 
     FCollisionShape CollisionHitShape;
     FCollisionQueryParams CollisionParams;
     //We do not want to store the instigator character in the array, so ignore it's collision
     CollisionParams.AddIgnoredActor(Instigator);
 
     //Set the channels that will respond to the collision
     FCollisionObjectQueryParams CollisionObjectTypes;
     CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_PhysicsBody);
     CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_Pawn);
     CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldStatic);
 
     //Create the box and get the overlapping actors
     CollisionHitShape = FCollisionShape::MakeBox(FVector(60.0f, 60.0f, 0.5f));
     GetWorld()->OverlapMulti(OutOverlaps, Start, Rotation, CollisionHitShape, CollisionParams, CollisionObjectTypes);
 
     //Process all hit actors
     for (int i = 0; i < OutOverlaps.Num(); ++i)
     {
         //We process each actor only once per Attack execution
         if (OutOverlaps[i].GetActor() && !HitActors.Contains(OutOverlaps[i].GetActor()))
         {
             //Process the actor to deal damage
             CurrentWeapon->Melee(OutOverlaps[i].GetActor(), HitActors);
             ServerMeleeAttack(CurrentWeapon, OutOverlaps[i].GetActor(), HitActors);
         }
     }
 }
 
 void AArenaCharacter::OnRep_Melee()
 {
     if (bDoingMelee)
     {
         CurrentWeapon->StartMelee(true);
     }
     else
     {
         CurrentWeapon->StopMelee();
     }
 }
 
 bool AArenaCharacter::ServerMeleeAttack_Validate(class AArenaRangedWeapon* Weapon, AActor* target, const TArray<AActor*>& HActors)
 {
     return true;
 }
 
 void AArenaCharacter::ServerMeleeAttack_Implementation(class AArenaRangedWeapon* Weapon, AActor* target, const TArray<AActor*>& HActors)
 {
     Weapon->Melee(target, HActors);
 }

MyWeapon.cpp

 void AArenaRangedWeapon::StartMelee(bool bFromReplication)
 {
     if (!bFromReplication && Role < ROLE_Authority)
     {
         ServerStartMelee();
     }
 
     if (bFromReplication || CanMelee())
     {
         bWantsToMelee = true;
         DetermineWeaponState();
 
         float AnimDuration = PlayWeaponAnimation(MeleeAnim);
         if (AnimDuration <= 0.0f)
         {
             AnimDuration = 0.3f;
         }
 
         GetWorldTimerManager().SetTimer(this, &AArenaRangedWeapon::StopMelee, AnimDuration, false);
         if (Role == ROLE_Authority)
         {
             //GetWorldTimerManager().SetTimer(this, &AArenaRangedWeapon::StartMelee, FMath::Max(0.1f, AnimDuration - 0.1f), false);
         }
 
         if (MyPawn && MyPawn->IsLocallyControlled())
         {
             PlayWeaponSound(MeleeSound);
         }
         ServerStartMelee();
     }
 }
 
 void AArenaRangedWeapon::StopMelee()
 {
     if (CurrentState == EWeaponState::Meleeing)
     {
         bWantsToMelee = false;
         DetermineWeaponState();
         StopWeaponAnimation(MeleeAnim);
     }
 }
 bool AArenaRangedWeapon::ServerStartMelee_Validate()
 {
     return true;
 }
 
 void AArenaRangedWeapon::ServerStartMelee_Implementation()
 {
     StartMelee();
 }
 
 bool AArenaRangedWeapon::ServerStopMelee_Validate()
 {
     return true;
 }
 
 void AArenaRangedWeapon::ServerStopMelee_Implementation()
 {
     StopMelee();
 }
 
 bool AArenaRangedWeapon::CanMelee() const
 {
     bool bCanMelee = (!MyPawn || MyPawn->CanMelee());
     bool bStateOKToMelee = ((CurrentState == EWeaponState::Idle) || (CurrentState == EWeaponState::Firing));
     return ((bCanMelee == true) && (bStateOKToMelee == true));
 }
 
 void AArenaRangedWeapon::Melee(AActor* ActorToProcess, TArray<AActor*> HitActors)
 {
     if (!ActorToProcess || HitActors.Contains(ActorToProcess))
     {
         return;
     }
     //Add this actor to the array because we are spawning one box per tick and we don't want to hit the same actor twice during the same attack animation
     HitActors.AddUnique(ActorToProcess);
     FHitResult AttackHitResult;
     FDamageEvent AttackDamageEvent;
     AArenaCharacter* GameCharacter = Cast<AArenaCharacter>(ActorToProcess);
 
     if (GameCharacter)
     {
         ActorToProcess->TakeDamage(WeaponConfig.MeleeDamage, AttackDamageEvent, Instigator->GetController(), MyPawn->Controller);
     }
 }
 
 void AArenaRangedWeapon::DetermineWeaponState()
 {
     EWeaponState::Type NewState = EWeaponState::Idle;
 
     if (bIsEquipped)
     {
         if (bPendingReload)
         {
             if (CanReload() == false)
             {
                 NewState = CurrentState;
             }
             else
             {
                 NewState = EWeaponState::Reloading;
             }
         }
         else if ((bPendingReload == false) && (bWantsToFire == true) && (CanFire() == true))
         {
             NewState = EWeaponState::Firing;
         }
         else if ((bWantsToMelee == true) && (CanMelee() == true))
         {
             NewState = EWeaponState::Meleeing;
         }
     }
     else if (bPendingEquip)
     {
         NewState = EWeaponState::Equipping;
     }
 
     SetWeaponState(NewState);
 }
Product Version: Not Selected
Tags:
more ▼

asked Nov 25 '14 at 06:13 AM in C++ Programming

avatar image

Janyx
492 66 65 211

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

0 answers: sort voted first
Be the first one to answer this question
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question