public static void Create( Vector2D sourcePosition, Vector2D targetPosition, double traceStartWorldOffset, ITextureResource texture, double beamWidth, Vector2D originOffset, double duration, bool endsWithHit, double fadeInDistance, double fadeOutDistanceHit, double fadeOutDistanceNoHit, BlendMode blendMode) { var deltaPos = targetPosition - sourcePosition; var length = deltaPos.Length; var fadeInFraction = fadeInDistance / length; var fadeOutFraction = endsWithHit ? fadeOutDistanceHit / length : fadeOutDistanceNoHit / length; if (fadeInFraction > 0.333 || fadeOutFraction > 0.333) { // no sense in displaying such a short beam return; } var sceneObject = Client.Scene.CreateSceneObject(nameof(ComponentWeaponEnergyBeam)); var component = sceneObject.AddComponent <ComponentWeaponEnergyBeam>(); ComponentWeaponTrace.CalculateAngleAndDirection(deltaPos, out var angleRad, out var normalizedRay); // offset start position of the ray sourcePosition += normalizedRay * traceStartWorldOffset; sceneObject.Position = sourcePosition; component.beamOriginOffset = originOffset; component.beamWidth = beamWidth; component.primaryRendererDefaultPositionOffset = Vector2D.Zero; component.spriteRendererLine.TextureResource = texture; component.targetPosition = targetPosition; component.duration = duration; component.renderingMaterial .EffectParameters .Set("Length", (float)length) .Set("FadeInFraction", (float)fadeInFraction) .Set("FadeOutFraction", (float)fadeOutFraction); component.spriteRendererLine.BlendMode = blendMode; component.Update(0); }
public static void ClientOnWeaponHitOrTrace( ICharacter firingCharacter, IProtoItemWeapon protoWeapon, IProtoItemAmmo protoAmmo, IProtoCharacter protoCharacter, Vector2Ushort fallbackCharacterPosition, IReadOnlyList <WeaponHitData> hitObjects, Vector2D endPosition, bool endsWithHit) { if (firingCharacter is not null && !firingCharacter.IsInitialized) { firingCharacter = null; } var weaponTracePreset = protoWeapon.FireTracePreset ?? protoAmmo?.FireTracePreset; var worldPositionSource = SharedCalculateWeaponShotWorldPositon( firingCharacter, protoWeapon, protoCharacter, fallbackCharacterPosition.ToVector2D(), hasTrace: weaponTracePreset?.HasTrace ?? false); protoWeapon.ClientOnWeaponHitOrTrace(firingCharacter, worldPositionSource, protoWeapon, protoAmmo, protoCharacter, fallbackCharacterPosition, hitObjects, endPosition, endsWithHit); if (weaponTracePreset?.HasTrace ?? false) { ComponentWeaponTrace.Create(weaponTracePreset, worldPositionSource, endPosition, hasHit: endsWithHit, lastHitData: hitObjects.LastOrDefault(t => t.WorldObject is not null)); } foreach (var hitData in hitObjects) { var hitWorldObject = hitData.WorldObject; if (hitWorldObject is not null && !hitWorldObject.IsInitialized) { hitWorldObject = null; } var protoWorldObject = hitData.FallbackProtoWorldObject; double delay; { var worldObjectPosition = CalculateWorldObjectPosition(hitWorldObject, hitData); delay = weaponTracePreset?.HasTrace ?? false ? SharedCalculateTimeToHit(weaponTracePreset, worldPositionSource : worldPositionSource, endPosition : worldObjectPosition + hitData.HitPoint.ToVector2D()) : 0; } ClientTimersSystem.AddAction( delay, () => { // re-calculate the world object position var worldObjectPosition = CalculateWorldObjectPosition(hitWorldObject, hitData); var fireScatterPreset = protoAmmo?.OverrideFireScatterPreset ?? protoWeapon.FireScatterPreset; var projectilesCount = fireScatterPreset.ProjectileAngleOffets.Length; var objectMaterial = hitData.FallbackObjectMaterial; if (hitWorldObject is ICharacter hitCharacter && hitCharacter.IsInitialized) { objectMaterial = ((IProtoCharacterCore)hitCharacter.ProtoCharacter) .SharedGetObjectMaterialForCharacter(hitCharacter); } protoWeapon.ClientPlayWeaponHitSound(hitWorldObject, protoWorldObject, fireScatterPreset, objectMaterial, worldObjectPosition); if (weaponTracePreset is not null) { ClientAddHitSparks(weaponTracePreset.HitSparksPreset, hitData, hitWorldObject, protoWorldObject, worldObjectPosition, projectilesCount, objectMaterial, randomizeHitPointOffset: !weaponTracePreset.HasTrace, randomRotation: !weaponTracePreset.HasTrace, drawOrder: weaponTracePreset.DrawHitSparksAsLight ? DrawOrder.Light : DrawOrder.Default); } });