protected override void OnContactStart(MyContactEventInfo contactInfo) { base.OnContactStart(contactInfo); m_collidedEntity = contactInfo.GetOtherEntity(this); if (this.OwnerEntity is MySmallShip && (MySmallShip)this.OwnerEntity == MySession.PlayerShip && m_collidedEntity is MyStaticAsteroid && !m_collidedEntity.IsDestructible) { HUD.MyHud.ShowIndestructableAsteroidNotification(); } Explode(); }
protected override void OnContactStart(MyContactEventInfo contactInfo) { base.OnContactStart(contactInfo); if (m_state == MyCurrentState.ACTIVATED) { m_collidedEntity = contactInfo.GetOtherEntity(this); if (m_collidedEntity is MySmallShip && MyFactions.GetFactionsRelation(this, m_collidedEntity) == MyFactionRelationEnum.Enemy) { if (this.OwnerEntity is MySmallShip && (MySmallShip)this.OwnerEntity == MySession.PlayerShip && m_collidedEntity is MyStaticAsteroid && !m_collidedEntity.IsDestructible) { HUD.MyHud.ShowIndestructableAsteroidNotification(); } // Create explosion and close; Explode(); } } }
/// <summary> /// Called when [contact touches] with this entity. /// </summary> /// <param name="contactInfo">The contact info.</param> protected override void OnContactTouch(MyContactEventInfo contactInfo) { /*var physicObject0 = (MyRigidBody) contactInfo.m_RigidBody1.m_UserData; var physicObject1 = (MyRigidBody) contactInfo.m_RigidBody2.m_UserData; float minSpeedForScrapeSound = 5; if (physicObject0.Speed > 5 || physicObject1.Speed > minSpeedForScrapeSound) { base.OnContactTouch(contactInfo); }*/ }
protected override void OnContactEnd(MyContactEventInfo contactInfo) { base.OnContactEnd(contactInfo); this.Physics.AngularDamping = m_angularDampingDefault; }
protected override void OnContactStart(MyContactEventInfo contactInfo) { if (!m_directionAfterContact.HasValue) { base.OnContactStart(contactInfo); var entityA = ((MyPhysicsBody) contactInfo.m_RigidBody1.m_UserData).Entity; var entityB = ((MyPhysicsBody) contactInfo.m_RigidBody2.m_UserData).Entity; var otherEntity = entityA == this ? entityB : entityA; var voxelMap = otherEntity as MyVoxelMap; Vector3 position; Vector3 normal; if (voxelMap != null) { var line = new MyLine(this.GetPosition(), this.GetPosition() + DISTANCE_TO_TEST_VOXEL_INTERSECTION * this.GetForward()); MyIntersectionResultLineTriangleEx? intersectionResult; var intersected = voxelMap.GetIntersectionWithLine(ref line, out intersectionResult); //Debug.Assert(intersected); //Debug.Assert(intersectionResult != null); if (intersectionResult != null) { normal = intersectionResult.Value.NormalInWorldSpace; position = intersectionResult.Value.IntersectionPointInWorldSpace - this.WorldVolume.Radius * 0.5f * normal; } else { normal = -contactInfo.m_ContactNormal; position = GetPosition() + this.WorldVolume.Radius * 0.5f * normal; } } else { normal = -contactInfo.m_ContactNormal; position = GetPosition() + this.WorldVolume.Radius * 0.5f * normal; } Physics.LinearVelocity = Vector3.Zero; Vector3 upVector; MyUtils.GetPerpendicularVector(ref normal, out upVector); m_directionAfterContact = normal; this.MoveAndRotate(position, Matrix.CreateWorld(position, m_directionAfterContact.Value, upVector)); Physics.Static = true; m_matrixAfterContact = WorldMatrix; m_elevation = 0; m_azimuth = 0; } }
/// <summary> /// deletes all contact info and checks it with last one in order to generate contact notifications /// A.B. this is using list - will be slow in case of lots of objects /// </summary> public void Flush() { m_StartContactEvents.Clear(); m_TouchContactEvents.Clear(); m_EndContactEvents.Clear(); for (int i = 0; i < m_ActiveContactConstrains.Count; i++) { if (m_ActiveContactConstrains[i].GetRBElementInteraction().RBElement1 == null || m_ActiveContactConstrains[i].GetRBElementInteraction().RBElement2 == null) { continue; } if (m_ActiveContactConstrains[i].GetRBElementInteraction().GetRigidBody1().NotifyContactHandler == null && m_ActiveContactConstrains[i].GetRBElementInteraction().GetRigidBody2().NotifyContactHandler == null) { continue; } uint guid = m_ActiveContactConstrains[i].GUID; MyContactEventInfo cei = null; if (m_ContactEventCache.TryGetValue(guid, out cei)) { // contact found should we make touch? if ((uint)MyPhysics.physicsSystem.GetRigidBodyModule().GetRigidBodyContactEventTypeMask(cei.m_RigidBody1.Type, cei.m_RigidBody2.Type) > ((uint)MyContactEventType.CET_START_AND_END)) { m_TouchContactEvents.Add(cei); } else { m_FreeCei.Push(cei); } m_ContactEventCache.Remove(guid); } else { // contact not found new contact if (m_FreeCei.Count == 0) { m_FreeCei.Push(new MyContactEventInfo()); } cei = m_FreeCei.Pop(); cei.Fill(m_ActiveContactConstrains[i]); m_StartContactEvents.Add(cei); } } foreach (KeyValuePair <uint, MyContactEventInfo> kvp in m_ContactEventCache) { m_EndContactEvents.Add(kvp.Value); } m_ContactEventCache.Clear(); FireContactCallbacks(); for (int i = 0; i < m_ActiveContactConstrains.Count; i++) { FreeRBContactConstraint(m_ActiveContactConstrains[i]); if (m_ActiveContactConstrains[i].GetRBElementInteraction().RBElement1 == null || m_ActiveContactConstrains[i].GetRBElementInteraction().RBElement2 == null) { continue; } if (m_ActiveContactConstrains[i].GetRBElementInteraction().GetRigidBody1().NotifyContactHandler == null && m_ActiveContactConstrains[i].GetRBElementInteraction().GetRigidBody2().NotifyContactHandler == null) { continue; } // else fill new contact event cache if (m_FreeCei.Count == 0) { m_FreeCei.Push(new MyContactEventInfo()); } MyContactEventInfo cei = m_FreeCei.Pop(); cei.Fill(m_ActiveContactConstrains[i]); if (!m_ContactEventCache.ContainsKey(m_ActiveContactConstrains[i].GUID)) { m_ContactEventCache.Add(m_ActiveContactConstrains[i].GUID, cei); } } m_ActiveContactConstrains.Clear(); }
/// <summary> /// calls the user contact callbacks /// </summary> private void FireContactCallbacks() { MyRigidBodyModule module = MyPhysics.physicsSystem.GetRigidBodyModule(); for (int i = 0; i < m_StartContactEvents.Count; i++) { MyContactEventInfo coi = m_StartContactEvents[i]; MyContactEventType cet = module.GetRigidBodyContactEventTypeMask(coi.m_RigidBody1.Type, coi.m_RigidBody2.Type); if (cet == MyContactEventType.CET_START || cet == MyContactEventType.CET_START_AND_END || cet == MyContactEventType.CET_START_AND_TOUCH || cet == MyContactEventType.CET_START_AND_TOUCH_AND_END) { if (coi.m_RigidBody1.NotifyContactHandler != null) { coi.m_RigidBody1.NotifyContactHandler.OnContactStart(coi); } if (coi.m_RigidBody2.NotifyContactHandler != null) { coi.m_RigidBody2.NotifyContactHandler.OnContactStart(coi); } } } for (int i = 0; i < m_TouchContactEvents.Count; i++) { MyContactEventInfo coi = m_TouchContactEvents[i]; MyContactEventType cet = module.GetRigidBodyContactEventTypeMask(coi.m_RigidBody1.Type, coi.m_RigidBody2.Type); if (cet == MyContactEventType.CET_TOUCH || cet == MyContactEventType.CET_START_AND_TOUCH || cet == MyContactEventType.CET_END_AND_TOUCH || cet == MyContactEventType.CET_START_AND_TOUCH_AND_END) { if (coi.m_RigidBody1.NotifyContactHandler != null) { coi.m_RigidBody1.NotifyContactHandler.OnContactTouch(coi); } if (coi.m_RigidBody2.NotifyContactHandler != null) { coi.m_RigidBody2.NotifyContactHandler.OnContactTouch(coi); } } m_FreeCei.Push(coi); } for (int i = 0; i < m_EndContactEvents.Count; i++) { MyContactEventInfo coi = m_EndContactEvents[i]; MyContactEventType cet = module.GetRigidBodyContactEventTypeMask(coi.m_RigidBody1.Type, coi.m_RigidBody2.Type); if (cet == MyContactEventType.CET_END || cet == MyContactEventType.CET_START_AND_END || cet == MyContactEventType.CET_END_AND_TOUCH || cet == MyContactEventType.CET_START_AND_TOUCH_AND_END) { if (coi.m_RigidBody1.NotifyContactHandler != null) { coi.m_RigidBody1.NotifyContactHandler.OnContactEnd(coi); } if (coi.m_RigidBody2.NotifyContactHandler != null) { coi.m_RigidBody2.NotifyContactHandler.OnContactEnd(coi); } } m_FreeCei.Push(coi); } }
/// <summary> /// Called when [contact touch]. /// </summary> /// <param name="contactInfo">The contact info.</param> public virtual void OnContactTouch(MyContactEventInfo contactInfo) { this.Entity.NotifyContactTouch(contactInfo); }
/// <summary> /// Rise the OnContactStart event. /// </summary> /// <param name="contactInfo">The contact info.</param> internal void NotifyContactStart(MyContactEventInfo contactInfo) { OnContactStart(contactInfo); }
/// <summary> /// Called when [contact touches] with this entity. /// </summary> /// <param name="contactInfo">The contact info.</param> protected virtual void OnContactTouch(MyContactEventInfo contactInfo) { if (this.Physics.PlayCollisionCueEnabled) { MyAudio.PlayCollisionCue(contactInfo, MyMaterialsConstants.MyMaterialCollisionType.Touch); } }
/// <summary> /// Called on some contact start with this entity. /// </summary> /// <param name="contactInfo">The contact info.</param> protected virtual void OnContactStart(MyContactEventInfo contactInfo) { MyRender.GetRenderProfiler().StartProfilingBlock("MyEntity::OnContactStart"); if (this.Physics.PlayCollisionCueEnabled) { MyAudio.PlayCollisionCue(contactInfo, MyMaterialsConstants.MyMaterialCollisionType.Start); } if (MyMwcFinalBuildConstants.DrawCollisionSpotsInHud) { MyHud.DebugClearAndAddText(contactInfo.m_ContactPoint, new StringBuilder("COLLISION POINT")); } MyRender.GetRenderProfiler().EndProfilingBlock(); }
protected override void OnContactStart(MyContactEventInfo contactInfo) { var collidedEntity = contactInfo.GetOtherEntity(this); if (!(collidedEntity is MyMeteor)) { MyParticleEffect pe = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Explosion_Meteor); pe.WorldMatrix = this.WorldMatrix; pe.UserScale = this.m_size * 0.01f; MyExplosion newExplosion = MyExplosions.AddExplosion(); MyExplosionInfo info = new MyExplosionInfo() { PlayerDamage = 100, Damage = 100, EmpDamage = 0, ExplosionType = MyExplosionTypeEnum.METEOR_EXPLOSION, ExplosionSphere = new BoundingSphere(GetPosition(), m_size), LifespanMiliseconds = MyExplosionsConstants.EXPLOSION_LIFESPAN, ParticleScale = 1, OwnerEntity = this, HitEntity = collidedEntity, ExplosionFlags = MyExplosionFlags.APPLY_FORCE_AND_DAMAGE | MyExplosionFlags.AFFECT_VOXELS | MyExplosionFlags.CREATE_DEBRIS /*| MyExplosionFlags.FORCE_DEBRIS*/, PlaySound = true, VoxelCutoutScale = 1, VoxelExplosionCenter = GetPosition() }; if (newExplosion != null) { newExplosion.Start(ref info); } this.MarkForClose(); } }
// Plays one-time cue of impact/collision/hit between two objects. Logic behind will preserve that only one sound is played, even if coldet routine gives us this collision two times. // We also check deceleration needed for playing the sound and if we aren't currently playing sound of collision for this two objects. internal static void PlayCollisionCue(MyContactEventInfo contactEventInfo, MyMaterialsConstants.MyMaterialCollisionType type) { var physicsObject0 = (MyPhysicsBody)contactEventInfo.m_RigidBody1.m_UserData; var physicsObject1 = (MyPhysicsBody)contactEventInfo.m_RigidBody2.m_UserData; // We won't add more collision sounds if dictionary is full (we need to wait until some cues are removed) if (m_collisionDictionary.Count > MyAudioConstants.MAX_COLLISION_SOUNDS) { if ((physicsObject0.Entity != MySession.PlayerShip) && (physicsObject1.Entity != MySession.PlayerShip)) { return; } } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("PlayCollisionCue"); Vector3 ZERO_CUE_VALUES = Vector3.Zero; MySoundCue? cue0 = null; float volume = 1;// MathHelper.Lerp(MySoundsConstants.DECELERATION_MIN_VOLUME, MySoundsConstants.DECELERATION_MAX_VOLUME, deceleration / MySoundsConstants.MAX_DECELERATION); MyMaterialType materialType1 = physicsObject0.MaterialType; MyMaterialType materialType2 = physicsObject1.MaterialType; if (physicsObject0.Entity == MySession.PlayerShip) materialType1 = MyMaterialType.PLAYERSHIP; if (physicsObject1.Entity == MySession.PlayerShip) materialType2 = MyMaterialType.PLAYERSHIP; if (type == MyMaterialsConstants.MyMaterialCollisionType.End && m_collisionDictionary.ContainsKey(contactEventInfo.m_Guid)) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("cue.Stop"); //We are already playing this collision and we need to end it with specific sound MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartNextBlock("AddCue3D"); MySoundCuesEnum? collisionSound = MyMaterialsConstants.GetCollisionCue(MyMaterialsConstants.MyMaterialCollisionType.End, materialType1, materialType2); if (collisionSound.HasValue) { MySoundCue cue = m_collisionDictionary[contactEventInfo.m_Guid]; cue.Stop(StopFlags.Release); cue0 = AddCue3D(collisionSound.Value, contactEventInfo.m_ContactPoint, ZERO_CUE_VALUES, ZERO_CUE_VALUES, ZERO_CUE_VALUES, volume); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); } else { if (type == MyMaterialsConstants.MyMaterialCollisionType.Start) { // If we aren't already playing collision cue for this particular combination of physical objects, now is the time if (!m_collisionDictionary.ContainsKey(contactEventInfo.m_Guid)) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Start audio"); MySoundCuesEnum? collisionSound = MyMaterialsConstants.GetCollisionCue(MyMaterialsConstants.MyMaterialCollisionType.Start, materialType1, materialType2); if (collisionSound.HasValue) { List<int> soundInstances; if (!m_collisionSoundsDictionary.TryGetValue((int)collisionSound.Value, out soundInstances)) { m_collisionSoundsDictionary.Add((int)collisionSound, soundInstances = new List<int>()); } if (soundInstances.Count < MyAudioConstants.MAX_COLLISION_SOUNDS_PER_SECOND) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("AddCue3D"); cue0 = AddCue3D(collisionSound.Value, contactEventInfo.m_ContactPoint, ZERO_CUE_VALUES, ZERO_CUE_VALUES, ZERO_CUE_VALUES, volume); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); if (cue0.HasValue) { soundInstances.Add(MyMinerGame.TotalTimeInMilliseconds); } } } MyMaterialTypeProperties materialProps1 = MyMaterialsConstants.GetMaterialProperties(materialType1); MyMaterialTypeProperties materialProps2 = MyMaterialsConstants.GetMaterialProperties(materialType2); MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); Vector3 particleDir = contactEventInfo.m_Velocity1.LengthSquared() > contactEventInfo.m_Velocity2.LengthSquared() ? contactEventInfo.m_Velocity1 - contactEventInfo.m_Velocity2 : contactEventInfo.m_Velocity2 - contactEventInfo.m_Velocity1; if (MyMwcUtils.IsZero(particleDir.LengthSquared())) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); return; //it is valid because of collision in rotation } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Collision particles"); particleDir = -MyMwcUtils.Normalize(particleDir); if (Vector3.DistanceSquared(MyCamera.Position, contactEventInfo.m_ContactPoint) < 100 * 100) { // Create smoke particles at the place of collision bool doSparks = materialProps1.DoSparksOnCollision || materialProps2.DoSparksOnCollision; bool doSmoke = materialProps1.DoSmokeOnCollision || materialProps2.DoSmokeOnCollision; MyParticleEffects.CreateCollisionParticles(contactEventInfo.m_ContactPoint, particleDir, false, doSparks); MyParticleEffects.CreateCollisionParticles(contactEventInfo.m_ContactPoint, contactEventInfo.m_ContactNormal, doSmoke, false); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); #if DEBUG_AUDIO Matrix colMatrix = Matrix.CreateWorld(contactEventInfo.m_ContactPoint, particleDir, Vector3.Up); m_soundCollisions.Add(colMatrix); #endif } else if (type == MyMaterialsConstants.MyMaterialCollisionType.Touch) { MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().StartProfilingBlock("Touch"); MySoundCuesEnum? scrapeSound = MyMaterialsConstants.GetCollisionCue(MyMaterialsConstants.MyMaterialCollisionType.Touch, materialType1, materialType2); if (scrapeSound.HasValue) { cue0 = AddCue3D(scrapeSound.Value, contactEventInfo.m_ContactPoint, ZERO_CUE_VALUES, ZERO_CUE_VALUES, ZERO_CUE_VALUES, volume); } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); // Create smoke particles at the place of collision //MyParticleEffects.CreateCollisionParticles(contactEventInfo.m_ContactPoint, physicsObject1.GetVelocity() - physicsObject0.GetVelocity()); } if (cue0.HasValue) { if (!m_collisionDictionary.ContainsKey(contactEventInfo.m_Guid)) { m_collisionDictionary.Add(contactEventInfo.m_Guid, cue0.Value); } } } } MinerWars.AppCode.Game.Render.MyRender.GetRenderProfiler().EndProfilingBlock(); }
/// <summary> /// Called on some contact with this entity. /// </summary> /// <param name="contactInfo">The contact info.</param> protected override void OnContactStart(MyContactEventInfo contactInfo) { base.OnContactStart(contactInfo); var collidedEntity = contactInfo.GetOtherEntity(this); /* if (IsExploded || contactInfo.GetOtherEntity(this) != m_collidedEntity || m_wasPenetration) { return; } */ /* if (Vector3.Dot(WorldMatrix.Forward, contactInfo.m_ContactNormal) < MyMissileConstants.MISSILE_MINIMAL_HIT_DOT) { //Hit wasnt facing the target, just slide or something return; } */ if (collidedEntity is MySmallShip && OwnerEntity == MySession.PlayerShip && MySession.PlayerFriends.Contains(collidedEntity as MySmallShip)) { //missiles wont hit out friends return; } m_collidedEntity = collidedEntity; m_collidedEntity.OnClose += m_collidedEntityClosedHandler; m_collisionPoint = contactInfo.m_ContactPoint; if (this.OwnerEntity is MySmallShip && (MySmallShip)this.OwnerEntity == MySession.PlayerShip && m_collidedEntity is MyStaticAsteroid && !m_collidedEntity.IsDestructible) { HUD.MyHud.ShowIndestructableAsteroidNotification(); } /* if (m_usedAmmo.AmmoType == MyMwcObjectBuilder_SmallShip_Ammo_TypesEnum.Cannon_Tunnel_Buster) { if (m_collidedEntity is MyVoxelMap) { return; } } */ Explode(m_collidedEntity); }
/// <summary> /// Rise the OnContactsEnd event. /// </summary> /// <param name="contactInfo">The contact info.</param> internal void NotifyContactEnd(MyContactEventInfo contactInfo) { OnContactEnd(contactInfo); }
protected override void OnContactStart(MyContactEventInfo contactInfo) { MyPhysicsBody ps1 = (MyPhysicsBody)contactInfo.m_RigidBody1.m_UserData; MyPhysicsBody ps2 = (MyPhysicsBody)contactInfo.m_RigidBody2.m_UserData; if (ps1.Entity is MyExplosionDebrisBase && ps2.Entity is MyExplosionDebrisBase) { MyCommonDebugUtils.AssertDebug(false); } base.OnContactStart(contactInfo); }
/// <summary> /// Rise the OnContactTouche event. /// </summary> /// <param name="contactInfo">The contact info.</param> internal void NotifyContactTouch(MyContactEventInfo contactInfo) { OnContactTouch(contactInfo); }
/// <summary> /// Called on some contact start with this entity. /// </summary> /// <param name="contactInfo">The contact info.</param> protected override void OnContactStart(MyContactEventInfo contactInfo) { MyEntity collidedEntity = contactInfo.GetOtherEntity(this); Debug.Assert(!collidedEntity.Closed); MyMissile missile = collidedEntity as MyMissile; if ((missile != null) && (OwnerEntity == missile.OwnerEntity)) { //We have hit another missile of ours return; } base.OnContactStart(contactInfo); m_collidedEntity = collidedEntity; m_collidedEntity.OnClose += m_collidedEntity_OnClose; m_collisionPoint = contactInfo.m_ContactPoint; if (this.OwnerEntity is MySmallShip && (MySmallShip)this.OwnerEntity == MySession.PlayerShip && m_collidedEntity is MyStaticAsteroid && !m_collidedEntity.IsDestructible) { HUD.MyHud.ShowIndestructableAsteroidNotification(); } Explode(); }
/// <summary> /// Called when [contact start]. /// </summary> /// <param name="contactInfo">The contact info.</param> public virtual void OnContactStart(MyContactEventInfo contactInfo) { // Notify entity(script) about contact. this.Entity.NotifyContactStart(contactInfo); }