public void Start(Vector3 direction, int?trailEffectId) { this.Physics.LinearVelocity = direction; this.Physics.AngularVelocity = new Vector3(MyMwcUtils.GetRandomFloat(0.2f, 1.5f), MyMwcUtils.GetRandomFloat(0.2f, 1.5f), 0); if (m_size == 0) { m_size = this.WorldVolume.Radius; } if (trailEffectId != null) { m_trailEffect = MyParticlesManager.CreateParticleEffect(trailEffectId.Value); m_trailEffect.AutoDelete = true; m_trailEffect.UserScale = this.WorldVolume.Radius / 10; m_trailEffect.UserBirthMultiplier /= 2; m_trailEffect.WorldMatrix = this.WorldMatrix;// worldMatrix; } m_burningCue = MyAudio.AddCue3D(MySoundCuesEnum.SfxMeteorFly, this.GetPosition(), this.GetForward(), Vector3.Up, direction); m_startTime = MyMinerGame.TotalGamePlayTimeInMilliseconds; if (MyMultiplayerGameplay.IsHosting) { MyMultiplayerGameplay.Static.NewEntity(GetObjectBuilder(true), WorldMatrix); } }
public static void Start() { Clear(); IsActive = true; startTime = MyMinerGame.TotalGamePlayTimeInMilliseconds; ambientSound = MyAudio.AddCue3D(MySoundCuesEnum.SfxSolarWind, MyCamera.Position + MyCamera.ForwardVector * MaxSoundDistance, Vector3.Forward, Vector3.Up, Vector3.Zero, 0); sphereCenter = MyCamera.Position + MyCamera.ForwardVector * 400; for (int i = 0; i < SmokeCount; i++) { Vector3 pos = sphereCenter + MyMwcUtils.GetRandomVector3Normalized() * MyMwcUtils.GetRandomFloat(0, SmokeSphereRadius); var smokePart = new SmokeParticle { Angle = MyMwcUtils.GetRandomRadian(), Color = Vector4.Zero, AngularVelocity = MyMwcUtils.GetRandomFloat(-0.15f, 0.15f), Pos = pos, Velocity = MyMwcUtils.GetRandomVector3Normalized() * MyMwcUtils.GetRandomFloat(0, 30f) }; smokeParticles.Add(smokePart); } }
private void PlaySound() { if (m_cue == null || !m_cue.Value.IsPlaying) { m_cue = MyAudio.AddCue3D(m_cueEnum, Vector3.Transform(m_pointLocalMatrix.Translation, base.WorldMatrix), WorldMatrix.Forward, WorldMatrix.Up, Physics.LinearVelocity); } }
public static void MakeExplosion(Vector3 explosionCenter) { m_explosionCenter = explosionCenter; if (m_State == NuclearState.INACTIVE || m_State == NuclearState.FLASH_IN) { m_StartMilliseconds = MyMinerGame.TotalGamePlayTimeInMilliseconds; m_State = NuclearState.FADE_IN; m_burningCue = MyAudio.AddCue3D(MySoundCuesEnum.SfxSolarWind, m_explosionCenter, -MyCamera.ForwardVector, Vector3.Up, Vector3.Zero); MyAudio.AddCue3D(MySoundCuesEnum.SfxNuclearExplosion, m_explosionCenter, -MyCamera.ForwardVector, Vector3.Up, Vector3.Zero); m_radius = 100; MinerWars.AppCode.Game.TransparentGeometry.Particles.MyParticleEffect explosion = MinerWars.AppCode.Game.TransparentGeometry.Particles.MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Explosion_Huge); explosion.WorldMatrix = Matrix.CreateWorld(m_explosionCenter, MyCamera.ForwardVector, MyCamera.UpVector); explosion.UserScale = 3; explosion.AutoDelete = true; MyPostProcessGodRays godRays = (MyPostProcessGodRays)MyRender.GetPostProcess(MyPostProcessEnum.GodRays); m_godRaysState = godRays.Enabled; godRays.Enabled = true; MySector.GodRaysProperties.Enabled = true; } else if (m_State == NuclearState.FLASH) { m_StartMilliseconds = MyMinerGame.TotalGamePlayTimeInMilliseconds; } }
void StartTubeMovingCue() { if ((m_tubeMovingCue == null) || (m_tubeMovingCue.Value.IsPlaying == false)) { m_tubeMovingCue = MyAudio.AddCue3D(MySoundCuesEnum.VehHarvesterTubeMovingLoop2d, WorldMatrix.Translation, WorldMatrix.Forward, WorldMatrix.Up, Parent.Physics.LinearVelocity); } }
void StartMovingCue() { if ((m_movingCue == null) || (m_movingCue.Value.IsPlaying == false)) { m_movingCue = MyAudio.AddCue3D(MySoundCuesEnum.WepMineMoveALoop, GetPosition(), WorldMatrix.Forward, WorldMatrix.Up, this.Physics.LinearVelocity); } }
protected void PlayKinematicEndSound() { if (m_endSound == null || !m_endSound.Value.IsPlaying) { if (m_endSoundCue.HasValue) { m_endSound = MyAudio.AddCue3D(m_endSoundCue.Value, m_kinematicPartOwner.WorldMatrix.Translation, m_kinematicPartOwner.WorldMatrix.Forward, m_kinematicPartOwner.WorldMatrix.Up, new Vector3(0, 0, 0)); } } StopKinematicSounds(m_endSound); }
// This method will start sun wind. Or if there is one coming, this will reset it so it will start again. public static void Start() { // Activate sun wind IsActive = true; m_smallBillboardsStarted = false; m_timeLastUpdate = MyMinerGame.TotalGamePlayTimeInMilliseconds; // Place sun wind at farest possible negative Z position //Vector3 directionToSunNormalized = MyMwcUtils.Normalize(MyGuiScreenGameBase.Static.SunPosition - MyCamera.Position); MyMwcSectorGroups.Get(MyGuiScreenGameBase.Static.Sector.SectorGroup).GetDirectionToSunNormalized(); Vector3 directionToSunNormalized = MyGuiScreenGamePlay.Static.GetDirectionToSunNormalized(); m_initialSunWindPosition = MyCamera.Position + directionToSunNormalized * MySunWindConstants.SUN_WIND_LENGTH_HALF; m_directionFromSunNormalized = -directionToSunNormalized; // Start the sound of burning (looping) StopCue(); m_burningCue = MyAudio.AddCue3D(MySoundCuesEnum.SfxSolarWind, m_initialSunWindPosition, m_directionFromSunNormalized, Vector3.Up, Vector3.Zero); //MySounds.UpdateCuePitch(m_burningCue, MyMwcUtils.GetRandomFloat(-1, +1)); m_speed = MyMwcUtils.GetRandomFloat(MySunWindConstants.SPEED_MIN, MySunWindConstants.SPEED_MAX); m_strength = MyMwcUtils.GetRandomFloat(0, 1); MyUtils.GetPerpendicularVector(ref m_directionFromSunNormalized, out m_rightVector); m_downVector = MyMwcUtils.Normalize(Vector3.Cross(m_directionFromSunNormalized, m_rightVector)); StartBillboards(); // Reinit computed max distances, they'll be computed in update m_computedMaxDistances = 0; m_deltaTime = 0; // Collect entities m_sunwindEntities.Clear(); foreach (var entity in MyEntities.GetEntities()) { if (!(entity is MySmallShip)) { continue; } // Do not move with indestructibles (NPCs etc) if (!entity.IsDestructible) { continue; } m_sunwindEntities.Add(entity); } }
void StartParticleSound() { var effectShouldEmitSound = Enabled && m_effectHelper != null && m_effectHelper.SoundCueEnum.HasValue; var effectCurrentlyEmittingSound = m_cue.HasValue && m_cue.Value.IsPlaying; if (effectShouldEmitSound && !effectCurrentlyEmittingSound) { m_cue = MyAudio.AddCue3D( m_effectHelper.SoundCueEnum.Value, WorldMatrix.Translation, WorldMatrix.Forward, WorldMatrix.Up, Vector3.Zero); } }
private void PlayEndSound(bool killOther) { if (m_loopSound != null && m_loopSound.Value.IsPlaying && killOther) { m_loopSound.Value.Stop(SharpDX.XACT3.StopFlags.Immediate); m_loopSound = null; } if (m_startSound != null && m_startSound.Value.IsPlaying && killOther) { m_startSound.Value.Stop(SharpDX.XACT3.StopFlags.Immediate); m_startSound = null; } if (m_endSound == null || !m_endSound.Value.IsPlaying) { m_endSound = MyAudio.AddCue3D(m_endSoundCue.Value, m_ownerKinematic.WorldMatrix.Translation, m_ownerKinematic.WorldMatrix.Forward, m_ownerKinematic.WorldMatrix.Up, new Vector3(0, 0, 0)); } }
void UpdateSound() { var distanceSquared = Vector3.DistanceSquared(MyCamera.Position, this.GetPosition()); bool closeEnough = distanceSquared < MAX_CHATTER_DISTANCE_SQUARED; if (IsWorking() && closeEnough) { if (!chatterCue.HasValue || !chatterCue.Value.IsPlaying) { var soundCueEnum = GetRandomChatterCueForMyFaction(); chatterCue = MyAudio.AddCue3D( soundCueEnum, this.GetPosition(), this.GetForward(), this.GetUp(), Vector3.Zero); } } else { StopChatterCue(); } }
void PlayLoopSound(ref MySoundCue?sound, MySoundCuesEnum?soundCue) { if (soundCue != null) { if (m_starting && sound.HasValue && sound.Value.IsPlaying) { m_starting = false; m_playing = true; } if (sound == null || (m_playing && !sound.Value.IsPlaying)) { m_playing = false; sound = MyAudio.AddCue3D( soundCue.Value, m_kinematicPartOwner.WorldMatrix.Translation, Vector3.Forward, Vector3.Forward, Vector3.Zero); m_starting = sound != null; } } }
// Update position, check collisions, etc. // Return false if projectile dies/timeouts in this tick. public bool Update() { // Projectile was killed , but still not last time drawn, so we don't need to do update (we are waiting for last draw) if (m_state == MyProjectileStateEnum.KILLED) { return(true); } // Projectile was killed and last time drawn, so we can finally remove it from buffer if (m_state == MyProjectileStateEnum.KILLED_AND_DRAWN) { if (m_trailEffect != null) { // stop the trail effect m_trailEffect.Stop(); m_trailEffect = null; } return(false); } Vector3 position = m_position; m_position += m_velocity * MyConstants.PHYSICS_STEP_SIZE_IN_SECONDS; m_velocity = m_externalVelocity * m_externalAddition + m_directionNormalized * m_speed; if (m_externalAddition < 1.0f) { m_externalAddition *= 0.5f; } // Distance timeout float trajectoryLength = Vector3.Distance(m_position, m_origin); if (trajectoryLength >= m_maxTrajectory) { if (m_trailEffect != null) { // stop the trail effect m_trailEffect.Stop(); m_trailEffect = null; } m_state = MyProjectileStateEnum.KILLED; return(true); } if (m_trailEffect != null) { m_trailEffect.WorldMatrix = Matrix.CreateTranslation(m_position); } m_checkIntersectionIndex++; m_checkIntersectionIndex = m_checkIntersectionIndex % CHECK_INTERSECTION_INTERVAL; //check only each n-th intersection if (m_checkIntersectionIndex != 0) { return(true); } // Calculate hit point, create decal and throw debris particles Vector3 lineEndPosition = position + CHECK_INTERSECTION_INTERVAL * (m_velocity * MyConstants.PHYSICS_STEP_SIZE_IN_SECONDS); MyLine line = new MyLine(m_positionChecked ? position : m_origin, lineEndPosition, true); m_positionChecked = true; MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("MyEntities.GetIntersectionWithLine()"); MyIntersectionResultLineTriangleEx?intersection = MyEntities.GetIntersectionWithLine(ref line, m_ignorePhysObject, null, false); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); MyEntity physObject = intersection != null ? intersection.Value.Entity : null; if (physObject != null) { while (physObject.Physics == null && physObject.Parent != null) { physObject = physObject.Parent; } } if ((intersection != null) && (physObject != null) && (physObject.Physics.CollisionLayer != MyConstants.COLLISION_LAYER_UNCOLLIDABLE) && m_ignorePhysObject != physObject) { MyIntersectionResultLineTriangleEx intersectionValue = intersection.Value; bool isPlayerShip = MySession.PlayerShip == physObject; MyMaterialType materialType = isPlayerShip ? MyMaterialType.PLAYERSHIP : physObject.Physics.MaterialType; //material properties MyMaterialTypeProperties materialProperties = MyMaterialsConstants.GetMaterialProperties(materialType); bool isProjectileGroupKilled = false; if (m_sharedGroup != null) { isProjectileGroupKilled = m_sharedGroup.Killed; m_sharedGroup.Killed = true; } if (!isProjectileGroupKilled) { // Play bullet hit cue MyAudio.AddCue3D(m_ammoProperties.IsExplosive ? materialProperties.ExpBulletHitCue : materialProperties.BulletHitCue, intersectionValue.IntersectionPointInWorldSpace, Vector3.Zero, Vector3.Zero, Vector3.Zero); } float decalAngle = MyMwcUtils.GetRandomRadian(); // If we hit the glass of a miner ship, we need to create special bullet hole decals // drawn from inside the cockpit and change phys object so rest of the code will think we hit the parent // IMPORTANT: Intersection between projectile and glass is calculated only for mining ship in which player sits. So for enemies this will be never calculated. if (intersection.Value.Entity is MyCockpitGlassEntity) { if (!isProjectileGroupKilled) { MyCockpitGlassDecalTexturesEnum bulletHoleDecalTexture; float bulletHoleDecalSize; if (MyMwcUtils.GetRandomBool(3)) { bulletHoleDecalTexture = MyCockpitGlassDecalTexturesEnum.BulletHoleOnGlass; bulletHoleDecalSize = 0.25f; } else { bulletHoleDecalTexture = MyCockpitGlassDecalTexturesEnum.BulletHoleSmallOnGlass; bulletHoleDecalSize = 0.1f; } // Place bullet hole decal on player's cockpit glass (seen from inside the ship) MyCockpitGlassDecals.Add(bulletHoleDecalTexture, bulletHoleDecalSize, decalAngle, 1.0f, ref intersectionValue, false); // Create hit particles throwed into the cockpit (it's simulation of broken glass particles) // IMPORTANT: This particles will be relative to miner ship, so we create them in object space coordinates and update them by object WorldMatrix every time we draw them //MyParticleEffects.CreateHitParticlesGlass(ref intersectionValue.IntersectionPointInObjectSpace, ref intersectionValue.NormalInWorldSpace, ref line.Direction, physObject.Parent); } } // If this was "mine", it must explode else if (physObject is MyMineBase) { m_state = MyProjectileStateEnum.KILLED; if (!IsDummy) { (physObject as MyAmmoBase).Explode(); } return(true); } // If this was missile, cannon shot, it must explode if it is not mine missile else if (physObject is MyAmmoBase) { if (((MyAmmoBase)physObject).OwnerEntity == m_ignorePhysObject) { m_state = MyProjectileStateEnum.KILLED; if (!IsDummy) { (physObject as MyAmmoBase).Explode(); } return(true); } } else if (this.OwnerEntity is MySmallShip && (MySmallShip)this.OwnerEntity == MySession.PlayerShip && physObject is MyStaticAsteroid && !physObject.IsDestructible) { if (this.m_ammoProperties.IsExplosive || (this.m_ammoProperties.AmmoType == MyAmmoType.Explosive && this.m_weapon is Weapons.MyShotGun)) { HUD.MyHud.ShowIndestructableAsteroidNotification(); } } else if (!isProjectileGroupKilled && !isPlayerShip) { // Create smoke and debris particle at the place of voxel/model hit m_ammoProperties.OnHitParticles(ref intersectionValue.IntersectionPointInWorldSpace, ref intersectionValue.Triangle.InputTriangleNormal, ref line.Direction, physObject, m_weapon, OwnerEntity); MySurfaceImpactEnum surfaceImpact; if (intersectionValue.Entity is MyVoxelMap) { var voxelMap = intersectionValue.Entity as MyVoxelMap; var voxelCoord = voxelMap.GetVoxelCenterCoordinateFromMeters(ref intersectionValue.IntersectionPointInWorldSpace); var material = voxelMap.GetVoxelMaterial(ref voxelCoord); if (material == MyMwcVoxelMaterialsEnum.Indestructible_01 || material == MyMwcVoxelMaterialsEnum.Indestructible_02 || material == MyMwcVoxelMaterialsEnum.Indestructible_03 || material == MyMwcVoxelMaterialsEnum.Indestructible_04 || material == MyMwcVoxelMaterialsEnum.Indestructible_05_Craters_01) { surfaceImpact = MySurfaceImpactEnum.INDESTRUCTIBLE; } else { surfaceImpact = MySurfaceImpactEnum.DESTRUCTIBLE; } } else if (intersectionValue.Entity is MyStaticAsteroid) { surfaceImpact = MySurfaceImpactEnum.INDESTRUCTIBLE; } else { surfaceImpact = MySurfaceImpactEnum.METAL; } m_ammoProperties.OnHitMaterialSpecificParticles(ref intersectionValue.IntersectionPointInWorldSpace, ref intersectionValue.Triangle.InputTriangleNormal, ref line.Direction, physObject, surfaceImpact, m_weapon); } if (!(physObject is MyExplosionDebrisBase) && physObject != MySession.PlayerShip) { // Decal size depends on material. But for mining ship create smaller decal as original size looks to large on the ship. float decalSize = MyMwcUtils.GetRandomFloat(materialProperties.BulletHoleSizeMin, materialProperties.BulletHoleSizeMax); // Place bullet hole decal float randomColor = MyMwcUtils.GetRandomFloat(0.5f, 1.0f); MyDecals.Add( materialProperties.BulletHoleDecal, decalSize, decalAngle, new Vector4(randomColor, randomColor, randomColor, 1), false, ref intersectionValue, 0.0f, m_ammoProperties.DecalEmissivity, MyDecalsConstants.DECAL_OFFSET_BY_NORMAL); } if (!(physObject is MyVoxelMap) && !IsDummy) { ApplyProjectileForce(physObject, intersectionValue.IntersectionPointInWorldSpace, m_directionNormalized, isPlayerShip); } // If this object is miner ship, then shake his head little bit if (physObject is MySmallShip && !IsDummy) { MySmallShip minerShip = (MySmallShip)physObject; minerShip.IncreaseHeadShake(MyHeadShakeConstants.HEAD_SHAKE_AMOUNT_AFTER_PROJECTILE_HIT); } //Handle damage MyEntity damagedObject = intersectionValue.Entity; // not a very nice way to damage actual prefab associated with the large ship weapon (if MyPrefabLargeWeapon is reworked, it might change) if (damagedObject is MyLargeShipBarrelBase) { damagedObject = damagedObject.Parent; } if (damagedObject is MyLargeShipGunBase) { MyLargeShipGunBase physObj = damagedObject as MyLargeShipGunBase; if (physObj.PrefabParent != null) { damagedObject = physObj.PrefabParent; } } // Decrease health of stricken object if (!IsDummy) { damagedObject.DoDamage(m_ammoProperties.HealthDamage, m_ammoProperties.ShipDamage, m_ammoProperties.EMPDamage, m_ammoProperties.DamageType, m_ammoProperties.AmmoType, m_ignorePhysObject); if (MyMultiplayerGameplay.IsRunning) { var ammo = MyAmmoConstants.FindAmmo(m_ammoProperties); MyMultiplayerGameplay.Static.ProjectileHit(damagedObject, intersectionValue.IntersectionPointInWorldSpace, this.m_directionNormalized, ammo, this.OwnerEntity); } } if (m_trailEffect != null) { // stop the trail effect m_trailEffect.Stop(); m_trailEffect = null; } // Kill this projectile (set the position to intersection point, so we draw trail polyline only up to this point) m_position = intersectionValue.IntersectionPointInWorldSpace; m_state = MyProjectileStateEnum.KILLED; return(true); } return(true); }
public static void Update() { // Update only if sun wind is active if (IsActive == false) { return; } float darkeningPhase; float dt; int relTime = GetDarkeningPhase(out darkeningPhase, out dt); if (relTime > MaxTimeMs) { Clear(); return; } MyAudio.UpdateCuePosition(ambientSound, MyCamera.Position + MyCamera.ForwardVector * -MaxSoundDistance * (1 - darkeningPhase), MyCamera.ForwardVector, MyCamera.UpVector, Vector3.Zero); MyAudio.UpdateCueVolume(ambientSound, darkeningPhase * MaxAmbientVolume); // update smoke foreach (SmokeParticle part in smokeParticles) { Vector3 toCamera = (MyCamera.Position - part.Pos); toCamera.Normalize(); float alpha = darkeningPhase * MaxSmokeAlpha; part.Color = new Vector4(alpha, alpha, alpha, alpha); //part.Color.W = darkeningPhase; part.Pos += part.Velocity * dt + toCamera * CenterBias * dt; part.Angle += part.AngularVelocity * dt; } // remove old ice and sparks m_iceList.Clear(); foreach (IceParticle particle in iceParticles) { if (particle.StartTime + 4000 < relTime) { m_iceList.Add(particle); } } foreach (IceParticle ice in m_iceList) { ice.AsteroidEntity.MarkForClose(); Debug.Assert(ice.TrailEffect != null, "ice.TrailEffect != null"); ice.TrailEffect.Stop(); ice.TrailEffect = null; StopCue(ice.Sound); iceParticles.Remove(ice); } int c = 0; while (c < storms.Count) { ElectricStorm storm = storms[c]; if (storm.StartTime + 1500 < relTime) { storms.RemoveAt(c); continue; } c++; } // if its dark add new sparks and ice balls if (darkeningPhase >= 1) { if (storms.Count < MaxSparkCount && MyMwcUtils.GetRandomInt(SparkEveryMs) < dt * 1000.0f) { var storm = new ElectricStorm { Position = MyCamera.Position + MyCamera.ForwardVector * 250 + MyMwcUtils.GetRandomVector3HemisphereNormalized(MyCamera.ForwardVector) * MyMwcUtils.GetRandomFloat(0, 300), StartTime = relTime, Effect = MyParticlesManager.CreateParticleEffect( (int)MyParticleEffectsIDEnum.Damage_Sparks), }; storm.Effect.WorldMatrix = Matrix.CreateTranslation(storm.Position); storm.Effect.AutoDelete = true; storm.Effect.UserScale = 2; storm.Sound = MyAudio.AddCue2D(MySoundCuesEnum.SfxSpark); storms.Add(storm); } if (iceParticles.Count < MaxIceCount && MyMwcUtils.GetRandomInt(IceEveryMs) < dt * 1000.0f) { Vector3 dir = MyMwcUtils.GetRandomVector3HemisphereNormalized(MyCamera.ForwardVector); Vector3 pos = MyCamera.Position + MyCamera.ForwardVector * 250 + MyMwcUtils.GetRandomVector3Normalized() * MyMwcUtils.GetRandomFloat(0, 200) + dir * MyMwcUtils.GetRandomFloat(0, 500); MyMwcObjectBuilder_StaticAsteroid rockModel = MySectorGenerator.GenerateStaticAsteroid(MyMwcUtils.GetRandomFloat(0.1f, 2f), MyStaticAsteroidTypeSetEnum.A, MyMwcVoxelMaterialsEnum.Ice_01, pos, random, asteroidTypes); Matrix matrix = Matrix.CreateFromAxisAngle(MyMwcUtils.GetRandomVector3Normalized(), MyMwcUtils.GetRandomFloat(0, MathHelper.Pi)); matrix.Translation = pos; MyEntity asteroid = MyEntities.CreateFromObjectBuilderAndAdd(null, rockModel, matrix); asteroid.Physics.Enabled = false; asteroid.CastShadows = false; MyParticleEffect effect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_CannonShot); Vector3 velocity = -dir *MyMwcUtils.GetRandomInt(150, 400); iceParticles.Add(new IceParticle { StartTime = relTime, Position = pos, Direction = -dir, AsteroidEntity = asteroid, TrailEffect = effect, RotAxis = MyMwcUtils.GetRandomVector3Normalized(), RotAngle = MyMwcUtils.GetRandomRadian(), AngularVelocity = MyMwcUtils.GetRandomFloat(0.2f, 10f), Velocity = velocity, Sound = MyAudio.AddCue3D(MySoundCuesEnum.WepSniperHighFire2d, pos, dir, dir * -dir, velocity) }); } } // update ice parts foreach (IceParticle particle in iceParticles) { particle.RotAngle += particle.AngularVelocity * dt; particle.Position += particle.Velocity * dt; Matrix matrix = Matrix.CreateFromAxisAngle(particle.RotAxis, particle.RotAngle); matrix.Translation = particle.Position; particle.AsteroidEntity.SetWorldMatrix(matrix); Matrix trans = Matrix.CreateTranslation(-particle.Direction * 10); particle.TrailEffect.WorldMatrix = matrix * trans; MyAudio.UpdateCuePosition(particle.Sound, particle.Position, particle.Direction, particle.Direction * -particle.Direction, particle.Velocity); } lastUpdateMs = MyMinerGame.TotalGamePlayTimeInMilliseconds; }
// This method realy initiates/starts the missile // IMPORTANT: Direction vector must be normalized! public virtual void Start(MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum type, Vector3 position, Vector3 initialVelocity, Vector3 direction, Vector3 relativePos, MyEntity minerShip, MyEntity target, float customMaxDistance, bool isDummy, bool isLightWeight) { m_ammoProperties = MyAmmoConstants.GetAmmoProperties(type); m_missileType = type; m_isExploded = false; m_collidedEntity = null; m_collisionPoint = null; m_maxTrajectory = customMaxDistance > 0 ? customMaxDistance : m_ammoProperties.MaxTrajectory; IsDummy = isDummy; Faction = minerShip.Faction; Vector3?correctedDirection = null; if (MyGameplayConstants.GameplayDifficultyProfile.EnableAimCorrection) { if (minerShip == MinerWars.AppCode.Game.Managers.Session.MySession.PlayerShip) { correctedDirection = MyEntities.GetDirectionFromStartPointToHitPointOfNearestObject(minerShip, position, m_ammoProperties.MaxTrajectory); } } if (correctedDirection != null) { direction = correctedDirection.Value; } base.Start(position, initialVelocity, direction, 0, minerShip); if (correctedDirection != null) //override the base class behaviour, update the missile direction { Matrix ammoWorld = minerShip.WorldMatrix; ammoWorld.Translation = position; ammoWorld.Forward = correctedDirection.Value; SetWorldMatrix(ammoWorld); } switch (m_missileType) { //just going forward (deprecated) case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Missile_Basic: m_initTime = MyMissileConstants.MISSILE_INIT_TIME; m_initDir = MyMissileConstants.MISSILE_INIT_DIR; m_blendVelocities = MyMissileConstants.MISSILE_BLEND_VELOCITIES_IN_MILISECONDS; m_missileTimeout = MyMissileConstants.MISSILE_TIMEOUT; m_explosionType = MyExplosionTypeEnum.MISSILE_EXPLOSION; break; case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Missile_BioChem: m_initTime = MyMissileConstants.MISSILE_INIT_TIME; m_initDir = MyMissileConstants.MISSILE_INIT_DIR; m_blendVelocities = MyMissileConstants.MISSILE_BLEND_VELOCITIES_IN_MILISECONDS; m_missileTimeout = MyMissileConstants.MISSILE_TIMEOUT; m_explosionType = MyExplosionTypeEnum.BIOCHEM_EXPLOSION; break; case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Missile_EMP: m_initTime = MyMissileConstants.MISSILE_INIT_TIME; m_initDir = MyMissileConstants.MISSILE_INIT_DIR; m_blendVelocities = MyMissileConstants.MISSILE_BLEND_VELOCITIES_IN_MILISECONDS; m_missileTimeout = MyMissileConstants.MISSILE_TIMEOUT; m_explosionType = MyExplosionTypeEnum.EMP_EXPLOSION; break; //Missile is guided to the nearest enemy in the radius case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Guided_Missile_Engine_Detection: //Missile is guided to the closest enemy in the visible spot case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Guided_Missile_Visual_Detection: //Missile is guided to actual selected target by smallship radar case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Guided_Missile_Radar_Detection: m_initDir.X = 5.0f * MathHelper.Clamp(relativePos.X, -1, 1); m_blendVelocities = MyGuidedMissileConstants.MISSILE_BLEND_VELOCITIES_IN_MILISECONDS; m_missileTimeout = MyGuidedMissileConstants.MISSILE_TIMEOUT; m_turnSpeed = MyGuidedMissileConstants.MISSILE_TURN_SPEED; m_explosionType = MyExplosionTypeEnum.MISSILE_EXPLOSION; GuidedInMultiplayer = true; break; default: throw new NotImplementedException(); } UpdateTarget(target); if (!isLightWeight) { // Play missile thrust cue (looping) m_thrusterCue = MyAudio.AddCue3D(m_ammoProperties.ShotSound, GetPosition(), WorldMatrix.Forward, WorldMatrix.Up, m_initialVelocity); m_light = MyLights.AddLight(); if (m_light != null) { m_light.Start(MyLight.LightTypeEnum.PointLight, GetPosition(), MyMissileHelperUtil.GetMissileLightColor(), 1, MyMissileConstants.MISSILE_LIGHT_RANGE); } } #if DEBUG_MISSILE m_trailDebug.Clear(); #endif if (m_missileType == MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Missile_Basic) { /* * MyParticleEffect startEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_MissileStart); * startEffect.WorldMatrix = WorldMatrix; */ m_smokeEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_Missile); m_smokeEffect.WorldMatrix = WorldMatrix; m_smokeEffect.AutoDelete = false; } }
/// <summary> /// Starts the explosion. /// </summary> /// <param name="damage"></param> /// <param name="type"></param> /// <param name="explosionSphere"></param> /// <param name="lifespanInMiliseconds"></param> /// <param name="explosionForceDirection"></param> /// <param name="groupMask"></param> /// <param name="createExplosionDebris"></param> /// <param name="cascadeLevel"></param> /// <param name="hitEntity"></param> /// <param name="particleScale"></param> /// <param name="ownerEntity"></param> /// <param name="affectVoxels"></param> /// <param name="applyForceAndDamage"></param> /// <param name="createDecals"></param> /// <param name="direction">If applicable, gives the direction of the explosion, e.g. when it was caused by a missile (with its moving direction).</param> public void Start(ref MyExplosionInfo explosionInfo) { //MyCommonDebugUtils.AssertDebug(explosionInfo.ExplosionSphere.Radius <= MyExplosionsConstants.EXPLOSION_RADIUS_MAX); MyCommonDebugUtils.AssertDebug(explosionInfo.ExplosionSphere.Radius > 0); MyRender.GetRenderProfiler().StartProfilingBlock("MyExplosion.Start"); m_explosionSphere = explosionInfo.ExplosionSphere; m_elapsedMiliseconds = 0; m_lifespanInMiliseconds = explosionInfo.LifespanMiliseconds; if (explosionInfo.PlaySound) { MyRender.GetRenderProfiler().StartProfilingBlock("Sound"); // Play explosion sound if (m_explosionCue != null && m_explosionCue.Value.IsPlaying) { m_explosionCue.Value.Stop(SharpDX.XACT3.StopFlags.Immediate); } m_explosionCue = MyAudio.AddCue3D(GetCueEnumByExplosionType(explosionInfo.ExplosionType), m_explosionSphere.Center, Vector3.Zero, Vector3.Zero, Vector3.Zero); MyRender.GetRenderProfiler().EndProfilingBlock(); } MyRender.GetRenderProfiler().StartProfilingBlock("Light"); // Light of explosion /* * m_light = MyLights.AddLight(); * if (m_light != null) * { * m_light.Start(MyLight.LightTypeEnum.PointLight, m_explosionSphere.Center, MyExplosionsConstants.EXPLOSION_LIGHT_COLOR, 1, Math.Min(m_explosionSphere.Radius * 8.0f, MyLightsConstants.MAX_POINTLIGHT_RADIUS)); * m_light.Intensity = 2.0f; * } */ MyRender.GetRenderProfiler().EndProfilingBlock(); // close explosion check bool close = IsExplosionClose(explosionInfo.ExplosionSphere); MyParticleEffectsIDEnum newParticlesType; switch (explosionInfo.ExplosionType) { case MyExplosionTypeEnum.SMALL_SHIP_EXPLOSION: // Create metal debris objects thrown from the explosion // This must be called before ApplyExplosionForceAndDamage (because there we apply impulses to the debris) // Throw a lot of debrises, more than only if some metalic object is hit (because this is destruction of a ship) //MyPhysObjectExplosionDebrises.CreateExplosionDebris(m_explosionSphere.Center, 1); newParticlesType = MyParticleEffectsIDEnum.Explosion_Smallship; break; case MyExplosionTypeEnum.MISSILE_EXPLOSION: newParticlesType = // ? MyParticleEffectsIDEnum.Explosion_Missile_Close MyParticleEffectsIDEnum.Explosion_Missile; break; case MyExplosionTypeEnum.BOMB_EXPLOSION: case MyExplosionTypeEnum.GRAVITY_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Bomb; break; case MyExplosionTypeEnum.AMMO_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Ammo; break; case MyExplosionTypeEnum.BLASTER_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Blaster; break; case MyExplosionTypeEnum.BIOCHEM_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_BioChem; break; case MyExplosionTypeEnum.EMP_EXPLOSION: case MyExplosionTypeEnum.FLASH_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_EMP; break; case MyExplosionTypeEnum.METEOR_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Meteor; break; case MyExplosionTypeEnum.NUCLEAR_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Nuclear; break; case MyExplosionTypeEnum.PLASMA_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Plasma; break; case MyExplosionTypeEnum.SMALL_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_SmallPrefab; break; case MyExplosionTypeEnum.LARGE_SHIP_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Huge; break; case MyExplosionTypeEnum.LARGE_PREFAB_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Large; break; case MyExplosionTypeEnum.MEDIUM_PREFAB_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Medium; break; case MyExplosionTypeEnum.ASTEROID_EXPLOSION: newParticlesType = MyParticleEffectsIDEnum.Explosion_Asteroid; break; default: throw new System.NotImplementedException(); break; } if (explosionInfo.Damage > 0) { MyRender.GetRenderProfiler().StartProfilingBlock("Voxel or collision"); // If explosion sphere intersects a voxel map, we need to cut out a sphere, spawn debrises, etc MyVoxelMap voxelMap = explosionInfo.AffectVoxels && explosionInfo.EmpDamage == 0 ? MyVoxelMaps.GetOverlappingWithSphere(ref m_explosionSphere) : null; if (voxelMap != null) { // Dirty explosion with a lot of dust MyMwcVoxelMaterialsEnum?voxelMaterial = null; float voxelContentRemovedInPercent = 0; bool createDebris = true; // We want to create debris if (explosionInfo.HitEntity != null) // but not when we hit prefab { createDebris &= explosionInfo.HitEntity is MyVoxelMap; } //cut off BoundingSphere voxelExpSphere = new BoundingSphere(explosionInfo.VoxelExplosionCenter, m_explosionSphere.Radius * explosionInfo.VoxelCutoutScale); if (MyVoxelGenerator.CutOutSphereFast(voxelMap, voxelExpSphere, out voxelContentRemovedInPercent, out voxelMaterial, (explosionInfo.OwnerEntity is MySmallShip && explosionInfo.OwnerEntity == Managers.Session.MySession.PlayerShip), MyFakes.VOXELS_REMOVE_RATIO)) { if (explosionInfo.HitEntity is MyVoxelMap) { HUD.MyHud.ShowIndestructableAsteroidNotification(); } createDebris = false; // and no debris when voxel is indestructible } // Only if at least something was removed from voxel map // If voxelContentRemovedInPercent is more than zero than also voxelMaterial shouldn't be null, but I rather check both of them. if ((voxelContentRemovedInPercent > 0) && (voxelMaterial != null)) { //remove decals MyDecals.HideTrianglesAfterExplosion(voxelMap, ref voxelExpSphere); MyRender.GetRenderProfiler().StartProfilingBlock("CreateDebris"); if (explosionInfo.CreateDebris && (createDebris || explosionInfo.ForceDebris) && MyRenderConstants.RenderQualityProfile.ExplosionDebrisCountMultiplier > 0) { // Create debris rocks thrown from the explosion // This must be called before ApplyExplosionForceAndDamage (because there we apply impulses to the debris) MyExplosionDebrisVoxel.CreateExplosionDebris(ref voxelExpSphere, voxelContentRemovedInPercent, voxelMaterial.Value, explosionInfo.GroupMask, voxelMap); } MyRender.GetRenderProfiler().EndProfilingBlock(); MyRender.GetRenderProfiler().StartProfilingBlock("CreateParticleEffect"); MyParticleEffect explosionEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.MaterialExplosion_Destructible); explosionEffect.WorldMatrix = Matrix.CreateTranslation(voxelExpSphere.Center); explosionEffect.UserRadiusMultiplier = voxelExpSphere.Radius; MyRender.GetRenderProfiler().EndProfilingBlock(); } } MyRender.GetRenderProfiler().EndProfilingBlock(); } if (explosionInfo.Damage > 0) { // Create dirt decals in player's cockpit glass MyRender.GetRenderProfiler().StartProfilingBlock("Cockpit Decals"); CreateDirtDecalOnCockpitGlass(ref m_explosionSphere); MyRender.GetRenderProfiler().EndProfilingBlock(); } if (DEBUG_EXPLOSIONS) { MyRender.GetRenderProfiler().EndProfilingBlock(); return; } if (explosionInfo.Damage > 0) { BoundingSphere influenceExplosionSphere = m_explosionSphere; influenceExplosionSphere.Radius *= MyExplosionsConstants.EXPLOSION_RADIUS_MULTPLIER_FOR_IMPULSE; for (int i = 0; i < explosionInfo.CascadeLevel; i++) { influenceExplosionSphere.Radius *= MyExplosionsConstants.EXPLOSION_CASCADE_FALLOFF; } // Throws surrounding objects away from centre of the explosion. if (explosionInfo.ApplyForceAndDamage) { if (explosionInfo.ExplosionType == MyExplosionTypeEnum.LARGE_PREFAB_EXPLOSION || explosionInfo.ExplosionType == MyExplosionTypeEnum.LARGE_SHIP_EXPLOSION || explosionInfo.ExplosionType == MyExplosionTypeEnum.MEDIUM_PREFAB_EXPLOSION) { DisableContainedDummyParticles(ref explosionInfo); } explosionInfo.StrengthImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_IMPULSE * m_explosionSphere.Radius / 20; explosionInfo.StrengthAngularImpulse = MyExplosionsConstants.EXPLOSION_STRENGTH_ANGULAR_IMPULSE; explosionInfo.HitEntity = explosionInfo.HitEntity != null?explosionInfo.HitEntity.GetBaseEntity() : null; MyRender.GetRenderProfiler().StartProfilingBlock("ApplyExplosionForceAndDamage"); MyEntities.ApplyExplosionForceAndDamage(ref explosionInfo); MyRender.GetRenderProfiler().EndProfilingBlock(); } // Look for objects in explosion radius BoundingBox boundingBox; BoundingBox.CreateFromSphere(ref influenceExplosionSphere, out boundingBox); //if (explosionInfo.CreateDecals && explosionInfo.Direction.HasValue && explosionInfo.EmpDamage == 0) //{ // CreateDecals(explosionInfo.Direction.Value); //} } if (explosionInfo.CreateParticleEffect) { MyRender.GetRenderProfiler().StartProfilingBlock("Particles"); if (explosionInfo.CustomEffect != null) { if (explosionInfo.CustomEffect.ParticleID == 0) { explosionInfo.CustomEffect.ParticleID = (int)newParticlesType; } //Reload effect explosionInfo.CustomEffect.Enabled = false; explosionInfo.CustomEffect.Enabled = true; } else { // Explosion particles GenerateExplosionParticles(newParticlesType, m_explosionSphere, explosionInfo.ParticleScale); } MyRender.GetRenderProfiler().EndProfilingBlock(); } MyRender.GetRenderProfiler().EndProfilingBlock(); /* * // When MyAmmoBase entity is closed to explosion it will explode * if (entity is MyAmmoBase) * { * (entity as MyAmmoBase).ExplodeCascade(cascadeLevel + 1); * } */ // Smut decals - must be called after the explosion, after voxels are cutted out /*if ((intersection.PhysObject is MyVoxelMap) == false) * { * if (intersection.PhysObject is MyCockpitGlass) * { * // Change phys object so rest of the code will think we hit the parent * // Same fix is in projectile too - because cockpit glass is only helper object, we don't use it for real rendering and stuff * // And if not changed, it can make problem in "phys object decals" * intersection.PhysObject = intersection.PhysObject.Parent; * } * * // Create explosion smut decal on model we hit by this missile * MyDecals.Add( * MyDecalTexturesEnum.ExplosionSmut, * MyMwcUtils.GetRandomFloat(m_explosionSphere.Radius * 0.7f, m_explosionSphere.Radius * 1.3f), * MyMwcUtils.GetRandomRadian(), * GetSmutDecalRandomColor(), * true, * ref intersection); * } * else * { * // Creating explosion smut decal on voxel is more complicated than on voxel. We will project few lines * // from explosion epicentrum to the surounding world (random directions) and place decal where intersection detected. * //if (knownMissileDirection != null) * //{ * // MyLine linePrologned = new MyLine(knownIntersection.Value.IntersectionPointInObjectSpace, * // knownIntersection.Value.IntersectionPointInObjectSpace + knownMissileDirection.Value * MyExplosionsConstants.EXPLOSION_RANDOM_RADIUS_MAX * 2, * // true); * // MyLineTriangleIntersectionResult intersectionForSmut = knownIntersection.Value.VoxelMap.GetIntersectionWithLine(ref linePrologned); * // if (intersectionForSmut.Found == true) * // { * // MyDecals.Add( * // MyDecalTexturesEnum.ExplosionSmut, * // MyMwcUtils.GetRandomFloat(m_explosionSphere.Radius * 0.5f, m_explosionSphere.Radius * 1.0f), * // MyMwcUtils.GetRandomRadian(), * // GetSmutDecalRandomColor(), * // false, * // ref intersectionForSmut); * // } * //} * }*/ // Generate dust particles that will stay in place of the explosion //doesnt look good in final //GenerateStatisDustParticles(m_explosionSphere); }
// This method realy initiates/starts the missile // IMPORTANT: Direction vector must be normalized! public void Start(Vector3 position, Vector3 initialVelocity, Vector3 directionNormalized, MyMwcObjectBuilder_SmallShip_Ammo usedAmmo, MySmallShip minerShip) { m_usedAmmo = usedAmmo; m_ammoProperties = MyAmmoConstants.GetAmmoProperties(usedAmmo.AmmoType); m_gameplayProperties = MyGameplayConstants.GetGameplayProperties(m_usedAmmo, Faction); m_penetratedVoxelMap = null; m_wasPenetration = false; m_hasExplosion = false; m_isExploded = false; m_collidedEntity = null; m_collisionPoint = null; Matrix orientation = GetWorldRotation(); Vector3 pos = position; // Play missile thrust cue (looping) m_thrusterCue = MyAudio.AddCue3D(MySoundCuesEnum.WepMissileFly, pos, orientation.Forward, orientation.Up, this.Physics.LinearVelocity); m_light = MyLights.AddLight(); if (m_light != null) { m_light.Start(MyLight.LightTypeEnum.PointLight, GetPosition(), MyMissileHelperUtil.GetCannonShotLightColor(), 1, MyMissileConstants.MISSILE_LIGHT_RANGE); } m_diffuseColor = m_ammoProperties.TrailColor; switch (usedAmmo.AmmoType) { case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Basic: case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_High_Speed: case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Armor_Piercing_Incendiary: case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_SAPHEI: case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Proximity_Explosive: m_explosionType = MyExplosionTypeEnum.MISSILE_EXPLOSION; break; case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_BioChem: m_explosionType = MyExplosionTypeEnum.BIOCHEM_EXPLOSION; break; case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_EMP: m_explosionType = MyExplosionTypeEnum.EMP_EXPLOSION; break; case MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Tunnel_Buster: m_explosionType = MyExplosionTypeEnum.BLASTER_EXPLOSION; break; default: throw new MyMwcExceptionApplicationShouldNotGetHere(); break; } this.Physics.Mass = m_gameplayProperties.WeightPerUnit; Vector3?correctedDirection = null; if (MyGameplayConstants.GameplayDifficultyProfile.EnableAimCorrection) { if (minerShip == MinerWars.AppCode.Game.Managers.Session.MySession.PlayerShip) { correctedDirection = MyEntities.GetDirectionFromStartPointToHitPointOfNearestObject(minerShip, position, m_ammoProperties.MaxTrajectory); } } if (correctedDirection != null) { directionNormalized = correctedDirection.Value; } base.Start(position, initialVelocity, directionNormalized, m_ammoProperties.DesiredSpeed, minerShip); if (correctedDirection != null) //override the base class behaviour, update the missile direction { Matrix ammoWorld = minerShip.WorldMatrix; ammoWorld.Translation = position; ammoWorld.Forward = correctedDirection.Value; SetWorldMatrix(ammoWorld); } m_smokeEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_CannonShot); m_smokeEffect.AutoDelete = false; m_smokeEffect.WorldMatrix = WorldMatrix; }