void ICmpUpdatable.OnUpdate() { ParticleEffect effect = this.GameObj.GetComponent <ParticleEffect>(); bool isActive = this.teamColor != ColorRgba.White; ColorHsva teamColorHsva = this.teamColor.ToHsva(); foreach (ParticleEmitter emitter in effect.Emitters) { float spawnAlpha = 1.0f - MathF.Clamp(this.spawnTimer / 5.0f, 0.0f, 1.0f); float alpha = 0.25f + 0.75f * (isActive ? spawnAlpha : 0.0f); emitter.MinColor = this.teamColor.WithAlpha(alpha).ToHsva(); emitter.MaxColor = this.teamColor.WithAlpha(alpha).ToHsva(); } this.spawnTimer -= Time.SPFMult * Time.TimeMult; if (this.spawnTimer <= 0.0f) { if (isActive) { this.Spawn(); } this.spawnTimer += this.spawnDelay; } }
void ICmpCollisionListener.OnCollisionBegin(Component sender, CollisionEventArgs args) { Ship otherShip = args.CollideWith.GetComponent <Ship>(); if (otherShip == null) { return; } if (args.CollideWith == this.owner) { return; } if (otherShip.TeamColor == this.TeamColor) { return; } ColorHsva teamColorHsva = otherShip.TeamColor.ToHsva(); GameObject obj = this.hitEffect.Res.Instantiate(); obj.Transform.Pos = this.GameObj.Transform.Pos; obj.Transform.Angle = this.GameObj.Transform.Angle; foreach (ParticleEmitter emitter in obj.GetComponent <ParticleEffect>().Emitters) { emitter.BaseVel += this.GameObj.Transform.Vel; emitter.MinColor = emitter.MinColor.WithHue(MathF.Lerp(emitter.MinColor.H, teamColorHsva.H, teamColorHsva.S)); emitter.MaxColor = emitter.MaxColor.WithHue(MathF.Lerp(emitter.MaxColor.H, teamColorHsva.H, teamColorHsva.S)); } this.GameObj.ParentScene.AddObject(obj); CameraController.ApplyScreenShake(this.GameObj.Transform.Pos, 0.05f); otherShip.Hit(this); this.GameObj.DisposeLater(); }
/// <summary> /// Returns a component-wise random <see cref="ColorHsva"/>. /// </summary> /// <param name="r"></param> /// <param name="min"></param> /// <param name="max"></param> /// <returns></returns> public static ColorHsva NextColorHsva(this Random r, ColorHsva min, ColorHsva max) { return(new ColorHsva( r.NextFloat(min.H, max.H), r.NextFloat(min.S, max.S), r.NextFloat(min.V, max.V), r.NextFloat(min.A, max.A))); }
protected override void OnEditedTypeChanged() { base.OnEditedTypeChanged(); System.Drawing.Bitmap iconBitmap = this.EditedType.GetEditorImage() as System.Drawing.Bitmap; ColorHsva avgClr = iconBitmap != null? iconBitmap.GetAverageColor().ToHsva() : Duality.Drawing.ColorHsva.TransparentWhite; if (avgClr.S <= 0.05f) { avgClr = new ColorHsva( 0.001f * (float)(this.EditedType.Name.GetHashCode() % 1000), 1.0f, 0.5f); } this.PropertyName = this.EditedType.GetTypeCSCodeName(true); this.HeaderIcon = iconBitmap; this.HeaderColor = ExtMethodsColor.ColorFromHSV(avgClr.H, 0.2f, 0.8f); }
public void Explode() { if (this.Disposed) { return; } ColorHsva teamColorHsva = this.teamColor.ToHsva(); GameObject explosionObj = this.explosionPrefab.Res.Instantiate(this.GameObj.Transform.Pos); foreach (ParticleEffect effect in explosionObj.GetComponentsDeep <ParticleEffect>()) { foreach (ParticleEmitter emitter in effect.Emitters) { emitter.MinColor = emitter.MinColor.WithHue(MathF.Lerp(emitter.MinColor.H, teamColorHsva.H, teamColorHsva.S)); emitter.MaxColor = emitter.MaxColor.WithHue(MathF.Lerp(emitter.MaxColor.H, teamColorHsva.H, teamColorHsva.S)); } } this.GameObj.ParentScene.AddObject(explosionObj); this.GameObj.DisposeLater(); CameraController.ApplyScreenShake(this.GameObj.Transform.Pos, 1.0f); if (this == this.GameObj.ParentScene.FindComponent <Player>().ControlTarget) { SoundInstance sound = DualityApp.Sound.PlaySound(this.explosionSound); } else { SoundInstance sound = DualityApp.Sound.PlaySound3D(this.explosionSound, this.GameObj.Transform.Pos); sound.Volume = 0.75f; sound.Lowpass = 0.75f; } if (this.thrusterSoundInstance != null) { this.thrusterSoundInstance.FadeOut(0.5f); this.thrusterSoundInstance = null; } }
protected override void OnEditedTypeChanged() { base.OnEditedTypeChanged(); System.Drawing.Bitmap iconBitmap = this.EditedType.GetEditorImage() as System.Drawing.Bitmap; ColorHsva avgClr = iconBitmap != null ? iconBitmap.GetAverageColor().ToHsva() : Duality.Drawing.ColorHsva.TransparentWhite; if (avgClr.S <= 0.05f) { avgClr = new ColorHsva( 0.001f * (float)(this.EditedType.Name.GetHashCode() % 1000), 1.0f, 0.5f); } this.PropertyName = this.EditedType.GetTypeCSCodeName(true); this.HeaderIcon = iconBitmap; this.HeaderColor = ExtMethodsSystemDrawingColor.ColorFromHSV(avgClr.H, 0.2f, 0.8f); this.Hints &= ~HintFlags.HasButton; this.Hints &= ~HintFlags.ButtonEnabled; }
protected override void OnEditedTypeChanged() { base.OnEditedTypeChanged(); System.Drawing.Bitmap iconBitmap = CorePluginRegistry.GetTypeImage(this.EditedType) as System.Drawing.Bitmap; ColorHsva avgClr = iconBitmap != null? iconBitmap.GetAverageColor().ToHsva() : Duality.ColorFormat.ColorHsva.TransparentWhite; if (avgClr.S <= 0.05f) { avgClr = new ColorHsva( 0.001f * (float)(this.EditedType.Name.GetHashCode() % 1000), 1.0f, 0.5f); } this.PropertyName = this.EditedType.GetTypeCSCodeName(true); this.HeaderIcon = iconBitmap; this.HeaderColor = ExtMethodsSystemDrawingColor.ColorFromHSV(avgClr.H, 0.2f, 0.8f); this.Hints &= ~HintFlags.HasButton; this.Hints &= ~HintFlags.ButtonEnabled; }
protected override void OnEditedTypeChanged() { base.OnEditedTypeChanged(); System.Drawing.Bitmap iconBitmap = CorePluginRegistry.RequestTypeImage(this.EditedType) as System.Drawing.Bitmap; ColorHsva avgClr = iconBitmap != null ? iconBitmap.GetAverageColor().ToHsva() : Duality.ColorFormat.ColorHsva.TransparentWhite; if (avgClr.S <= 0.05f) { avgClr = new ColorHsva( 0.001f * (float)(this.EditedType.Name.GetHashCode() % 1000), 1.0f, 0.5f); } this.PropertyName = this.EditedType.GetTypeCSCodeName(true); this.HeaderIcon = iconBitmap; this.HeaderColor = ExtMethodsSystemDrawingColor.ColorFromHSV(avgClr.H, 0.2f, 0.8f); }
void ICmpUpdatable.OnUpdate() { Transform transform = this.GameObj.Transform; RigidBody body = this.GameObj.GetComponent <RigidBody>(); ShipBlueprint blueprint = this.blueprint.Res; // Heal when damaged if (this.hitpoints < 1.0f) { this.hitpoints = MathF.Clamp(this.hitpoints + blueprint.HealRate * Time.SPFMult * Time.TimeMult / blueprint.MaxHitpoints, 0.0f, 1.0f); } // Apply force according to the desired thrust Vector2 actualVelocity = body.LinearVelocity; Vector2 targetVelocity = this.targetThrust * blueprint.MaxSpeed; Vector2 velocityDiff = (targetVelocity - actualVelocity); float sameDirectionFactor = Vector2.Dot( velocityDiff / MathF.Max(0.001f, velocityDiff.Length), this.targetThrust / MathF.Max(0.001f, this.targetThrust.Length)); Vector2 thrusterActivity = this.targetThrust.Length * MathF.Max(sameDirectionFactor, 0.0f) * velocityDiff / MathF.Max(velocityDiff.Length, 1.0f); if (thrusterActivity.Length > 0.00001f) // Don't wake physics without actually doing work { body.ApplyWorldForce(thrusterActivity * blueprint.ThrusterPower); } // Turn to the desired fire angle if (this.targetAngleRatio > 0.0f) { float shortestTurnDirection = MathF.TurnDir(transform.Angle, this.targetAngle); float shortestTurnLength = MathF.CircularDist(transform.Angle, this.targetAngle); float turnDirection; float turnLength; if (MathF.Abs(body.AngularVelocity) > blueprint.MaxTurnSpeed * 0.25f) { turnDirection = MathF.Sign(body.AngularVelocity); turnLength = (turnDirection == shortestTurnDirection) ? shortestTurnLength : (MathF.RadAngle360 - shortestTurnLength); } else { turnDirection = shortestTurnDirection; turnLength = shortestTurnLength; } float turnSpeedRatio = MathF.Min(turnLength * 0.25f, MathF.RadAngle30) / MathF.RadAngle30; float turnVelocity = turnSpeedRatio * turnDirection * blueprint.MaxTurnSpeed * this.targetAngleRatio; float angularVelocityChange = (turnVelocity - body.AngularVelocity) * blueprint.TurnPower; if (MathF.Abs(angularVelocityChange) > 0.0000001f) // Don't wake physics without actually doing work { body.AngularVelocity += angularVelocityChange * Time.TimeMult; } } // Weapon cooldown this.weaponTimer = MathF.Max(0.0f, this.weaponTimer - Time.MsPFMult * Time.TimeMult); // Play the owners special flight sound, when available if (this.owner != null && this.owner.FlightLoop != null) { SoundListener listener = Scene.Current.FindComponent <SoundListener>(); Vector3 listenerPos = listener.GameObj.Transform.Pos; // Determine the target panning manually, because we don't want a true 3D sound here (doppler, falloff, ...) float targetPanning; if (listenerPos.Xy == transform.Pos.Xy || Player.AlivePlayers.Count() <= 1) { targetPanning = 0.0f; } else { targetPanning = -Vector2.Dot(Vector2.UnitX, (listenerPos - transform.Pos).Xy.Normalized); } // Determine the target volume float targetVolume = MathF.Clamp(this.targetThrust.Length, 0.0f, 1.0f); // Clean up disposed flight loop if (this.flightLoop != null && this.flightLoop.Disposed) { this.flightLoop = null; } // Start the flight loop when requested if (targetVolume > 0.0f && this.flightLoop == null) { if ((int)Time.MainTimer.TotalMilliseconds % 2976 <= (int)Time.MsPFMult) { this.flightLoop = DualityApp.Sound.PlaySound(this.owner.FlightLoop); this.flightLoop.Looped = true; } } // Configure existing flight loop if (this.flightLoop != null) { this.flightLoop.Volume += (targetVolume - this.flightLoop.Volume) * 0.05f * Time.TimeMult; this.flightLoop.Panning += (targetPanning - this.flightLoop.Panning) * 0.05f * Time.TimeMult; } } // Display the damage effect when damaged if (this.hitpoints < 0.85f && blueprint.DamageEffect != null) { // Create a new damage effect instance, if not present yet if (this.damageEffect == null) { GameObject damageObj = blueprint.DamageEffect.Res.Instantiate(transform.Pos); damageObj.Parent = this.GameObj; this.damageEffect = damageObj.GetComponent <ParticleEffect>(); if (this.damageEffect == null) { throw new NullReferenceException(); } } // Configure the damage effect foreach (ParticleEmitter emitter in this.damageEffect.Emitters) { if (emitter == null) { continue; } emitter.BurstDelay = new Range(50.0f + this.hitpoints * 50.0f, 100.0f + this.hitpoints * 300.0f); if (this.owner != null) { ColorHsva targetColor = this.owner.Color.ToHsva(); emitter.MinColor = new ColorHsva(targetColor.H, targetColor.S, emitter.MinColor.V, emitter.MinColor.A); emitter.MaxColor = new ColorHsva(targetColor.H, targetColor.S, emitter.MaxColor.V, emitter.MaxColor.A); } } } // Get rid of existing damage effects, if no longer needed else if (this.damageEffect != null) { // Stop emitting and dispose when empty foreach (ParticleEmitter emitter in this.damageEffect.Emitters) { if (emitter == null) { continue; } emitter.BurstDelay = float.MaxValue; } this.damageEffect.DisposeWhenEmpty = true; this.damageEffect = null; } }
void ICmpCollisionListener.OnCollisionBegin(Component sender, CollisionEventArgs args) { RigidBodyCollisionEventArgs bodyArgs = args as RigidBodyCollisionEventArgs; if (bodyArgs == null) { return; } if (bodyArgs.OtherShape.IsSensor) { return; } // Did we collide with a ship? If it's the same that fired the bullet, ignore this Ship otherShip = args.CollideWith.GetComponent <Ship>(); if (otherShip != null && otherShip.Owner == this.owner) { return; } // Get all the objet references we'll need RigidBody otherBody = args.CollideWith.RigidBody; Transform transform = this.GameObj.Transform; RigidBody body = this.GameObj.RigidBody; BulletBlueprint blueprint = this.blueprint.Res; // Okay, let's determine where *exactly* our bullet hit RayCastData firstHit; bool hitAnything = RigidBody.RayCast(transform.Pos.Xy - body.LinearVelocity * 2, transform.Pos.Xy + body.LinearVelocity * 2, data => { if (data.Shape.IsSensor) { return(-1.0f); } return(data.Fraction); }, out firstHit); Vector3 hitPos; float hitAngle; if (hitAnything) { hitPos = new Vector3(firstHit.Pos, 0.0f); hitAngle = (-firstHit.Normal).Angle; } else { // Note that it is possible for the raycast to not hit anything, // because it is essentially a line, while our bullet is wider than zero. hitPos = transform.Pos; hitAngle = transform.Angle; } // Push around whatever we've just hit and do damage, if it was a ship otherBody.ApplyWorldImpulse(body.LinearVelocity * MathF.Min(otherBody.Mass, blueprint.ImpactMass), transform.Pos.Xy); if (otherShip != null) { otherShip.DoDamage(blueprint.Damage); } // If we hit a part of the world, spawn the world hit effect if (otherShip == null && blueprint.HitWorldEffect != null) { GameObject effectObj = blueprint.HitWorldEffect.Res.Instantiate(hitPos, hitAngle); Scene.Current.AddObject(effectObj); } // Also spawn a generic hit effect in the color of the bullet if (blueprint.HitEffect != null) { GameObject effectObj = blueprint.HitEffect.Res.Instantiate(hitPos, hitAngle); ParticleEffect effect = effectObj.GetComponent <ParticleEffect>(); if (effect != null && this.owner != null) { ColorHsva color = this.owner.Color.ToHsva(); foreach (ParticleEmitter emitter in effect.Emitters) { emitter.MaxColor = emitter.MaxColor.WithSaturation(color.S).WithHue(color.H); emitter.MinColor = emitter.MinColor.WithSaturation(color.S).WithHue(color.H); } } Scene.Current.AddObject(effectObj); } // Play hit sounds if (blueprint.HitSound != null) { SoundInstance inst = DualityApp.Sound.PlaySound3D(blueprint.HitSound, hitPos); inst.Pitch = MathF.Rnd.NextFloat(0.95f, 1.05f); } HitSoundController otherHitSound = otherBody.GameObj.GetComponent <HitSoundController>(); if (otherHitSound != null) { otherHitSound.NotifyHit(MathF.Rnd.NextFloat(0.75f, 1.0f)); } // Delete the bullet this.GameObj.DisposeLater(); }