AFlareSpacecraft* UFlareSpacecraftNavigationSystem::GetDockStation() { if (IsDocked()) { for (int32 SpacecraftIndex = 0; SpacecraftIndex < Spacecraft->GetGame()->GetActiveSector()->GetSpacecrafts().Num(); SpacecraftIndex++) { AFlareSpacecraft* Station = Spacecraft->GetGame()->GetActiveSector()->GetSpacecrafts()[SpacecraftIndex]; if (Station && Station->GetParent()->GetImmatriculation() == Data->DockedTo) { return Station; } } } return NULL; }
void UFlareSpacecraftDamageSystem::OnCollision(class AActor* Other, FVector HitLocation, FVector NormalImpulse) { // If receive hit from over actor, like a ship we must apply collision damages. // The applied damage energy is 0.2% of the kinetic energy of the other actor. The kinetic // energy is calculated from the relative speed between the 2 actors, and only with the relative // speed projected in the axis of the collision normal: if 2 very fast ship only slightly touch, // only few energy will be decipated by the impact. // // The damages are applied only to the current actor, the ReceiveHit method of the other actor // will also call an it will apply its collision damages itself. // If the other actor is a projectile, specific weapon damage code is done in the projectile hit // handler: in this case we ignore the collision AFlareShell* OtherProjectile = Cast<AFlareShell>(Other); if (OtherProjectile) { return; } // No primitive component, ignore UPrimitiveComponent* OtherRoot = Cast<UPrimitiveComponent>(Other->GetRootComponent()); if (!OtherRoot) { return; } // Ignore debris AStaticMeshActor* OtherActor = Cast<AStaticMeshActor>(Other); if (OtherActor) { if (OtherActor->GetName().StartsWith("Debris")) { return; } } // Relative velocity FVector DeltaVelocity = ((OtherRoot->GetPhysicsLinearVelocity() - Spacecraft->Airframe->GetPhysicsLinearVelocity()) / 100); // Compute the relative velocity in the impact axis then compute kinetic energy /*float ImpactSpeed = DeltaVelocity.Size(); float ImpactMass = FMath::Min(Spacecraft->GetSpacecraftMass(), OtherRoot->GetMass()); */ //200 m /s -> 6301.873047 * 20000 -> 300 / 2 damage float ImpactSpeed = 0; float ImpactEnergy = 0; float ImpactMass = Spacecraft->GetSpacecraftMass(); // Check if the mass was set and is valid if (ImpactMass > KINDA_SMALL_NUMBER) { ImpactSpeed = NormalImpulse.Size() / (ImpactMass * 100.f); ImpactEnergy = ImpactMass * ImpactSpeed / 8402.f; } float Radius = 0.2 + FMath::Sqrt(ImpactEnergy) * 0.11; //FLOGV("OnCollision %s", *Spacecraft->GetImmatriculation().ToString()); //FLOGV(" OtherRoot->GetPhysicsLinearVelocity()=%s", *OtherRoot->GetPhysicsLinearVelocity().ToString()); //FLOGV(" OtherRoot->GetPhysicsLinearVelocity().Size()=%f", OtherRoot->GetPhysicsLinearVelocity().Size()); //FLOGV(" Spacecraft->Airframe->GetPhysicsLinearVelocity()=%s", *Spacecraft->Airframe->GetPhysicsLinearVelocity().ToString()); //FLOGV(" Spacecraft->Airframe->GetPhysicsLinearVelocity().Size()=%f", Spacecraft->Airframe->GetPhysicsLinearVelocity().Size()); //FLOGV(" dot=%f", FVector::DotProduct(DeltaVelocity.GetUnsafeNormal(), HitNormal.GetUnsafeNormal())); /*FLOGV(" DeltaVelocity=%s", *DeltaVelocity.ToString()); FLOGV(" ImpactSpeed=%f", ImpactSpeed); FLOGV(" ImpactMass=%f", ImpactMass); FLOGV(" ImpactEnergy=%f", ImpactEnergy); FLOGV(" Radius=%f", Radius);*/ bool HasHit = false; FHitResult BestHitResult; float BestHitDistance = 0; for (int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++) { UFlareSpacecraftComponent* Component = Cast<UFlareSpacecraftComponent>(Components[ComponentIndex]); if (Component) { FHitResult HitResult(ForceInit); FCollisionQueryParams TraceParams(FName(TEXT("Fragment Trace")), true); TraceParams.bTraceComplex = true; TraceParams.bReturnPhysicalMaterial = false; Component->LineTraceComponent(HitResult, HitLocation, HitLocation + Spacecraft->GetLinearVelocity().GetUnsafeNormal() * 10000, TraceParams); if (HitResult.Actor.IsValid()){ float HitDistance = (HitResult.Location - HitLocation).Size(); if (!HasHit || HitDistance < BestHitDistance) { BestHitDistance = HitDistance; BestHitResult = HitResult; } //FLOGV("Collide hit %s at a distance=%f", *Component->GetReadableName(), HitDistance); HasHit = true; } } } if (HasHit) { //DrawDebugLine(Spacecraft->GetWorld(), HitLocation, BestHitResult.Location, FColor::Magenta, true); } else { int32 BestComponentIndex = -1; BestHitDistance = 0; for (int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++) { UFlareSpacecraftComponent* Component = Cast<UFlareSpacecraftComponent>(Components[ComponentIndex]); if (Component) { float ComponentDistance = (Component->GetComponentLocation() - HitLocation).Size(); if (BestComponentIndex == -1 || BestHitDistance > ComponentDistance) { BestComponentIndex = ComponentIndex; BestHitDistance = ComponentDistance; } } } UFlareSpacecraftComponent* Component = Cast<UFlareSpacecraftComponent>(Components[BestComponentIndex]); FCollisionQueryParams TraceParams(FName(TEXT("Fragment Trace")), true); TraceParams.bTraceComplex = true; TraceParams.bReturnPhysicalMaterial = false; Component->LineTraceComponent(BestHitResult, HitLocation, Component->GetComponentLocation(), TraceParams); //DrawDebugLine(Spacecraft->GetWorld(), HitLocation, BestHitResult.Location, FColor::Yellow, true); } AFlareSpacecraft* OtherSpacecraft = Cast<AFlareSpacecraft>(Other); UFlareCompany* DamageSource = NULL; if (OtherSpacecraft) { DamageSource = OtherSpacecraft->GetParent()->GetCompany(); LastDamageCauser = OtherSpacecraft; } else { LastDamageCauser = NULL; } ApplyDamage(ImpactEnergy, Radius, BestHitResult.Location, EFlareDamage::DAM_Collision, DamageSource); }