void m_transporter_OnContactEvent(MyEntity obj) { //Damage all bot which touched our mothership (we have to prevent sticking bots to ms because of physics) if (obj is MySmallShipBot) { obj.DoDamage(0, 5, 0, MyDamageType.Unknown, MyAmmoType.Unknown, m_transporter); } }
private void ScannerOnOnEntityScanned(MyPrefabScanner sender, MyEntity scannedEntity) { if (scannedEntity == MySession.PlayerShip && m_scanners.Contains(sender)) { scannedEntity.DoDamage(0, 1000000, 0, MyDamageType.Unknown, MyAmmoType.Unknown, null); ((MyPrefabContainer)sender.Parent).AlarmOn = true; } }
// 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); }
protected override void Drill() { // Sphere which is used to make tunnel to voxel and sphere for testing collision with voxel m_fakeCollisionSphere = new BoundingSphere(m_fakeSpherePositionTransformed, m_radius); // Check for collision with drill and world //MyEntity collisionResult = MyEntities.GetIntersectionWithSphere(ref m_fakeCollisionSphere, this, Parent, false, true); // bSphere collision doesn't work - the sphere is tested against LOD0 model, but it is hidden inside the COL model and the bSphere is too small to reach it - so I use line instead MyEntity collisionResult = null; MyLine line; if (MySession.Is25DSector) { line = new MyLine(m_positionMuzzleInWorldSpace - 10 * WorldMatrix.Forward, m_positionMuzzleInWorldSpace + 20 * WorldMatrix.Forward, true); } else { line = new MyLine(m_positionMuzzleInWorldSpace - 10 * WorldMatrix.Forward, m_positionMuzzleInWorldSpace + 5 * WorldMatrix.Forward, true); } MyIntersectionResultLineTriangleEx?intersection = MyEntities.GetIntersectionWithLine(ref line, Parent, this, true, true); if (intersection != null && intersection.Value.Entity.Physics != null) { collisionResult = intersection.Value.Entity; } if (!(collisionResult is MyVoxelMap)) { m_lastTimeDrillNotCollidedWithVoxelMapInMiliseconds = MyMinerGame.TotalGamePlayTimeInMilliseconds; if (!MySession.Is25DSector) { ((MySmallShip)Parent).IncreaseHeadShake(MyDrillDeviceConstants.SHAKE_DURING_ROTATION); } StopDustEffect(); if (collisionResult != null) { var effect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.MaterialHit_Autocannon_Metal); effect.WorldMatrix = Matrix.CreateTranslation(m_fakeCollisionSphere.Center); collisionResult.DoDamage(0, m_damage * MyConstants.PHYSICS_STEP_SIZE_IN_SECONDS, 0, MyDamageType.Drill, MyAmmoType.Basic, Parent); } } // Display particles when we are in contact with voxel else { if (m_dustEffect == null) { m_dustEffect = MyParticlesManager.CreateParticleEffect((int)MyParticleEffectsIDEnum.Smoke_DrillDust); } m_dustEffect.WorldMatrix = Matrix.CreateTranslation(m_fakeSpherePositionTransformed); m_dustEffect.UserScale = MySession.Is25DSector ? 3 : 1; ((MySmallShip)Parent).IncreaseHeadShake(MyDrillDeviceConstants.SHAKE_DURING_IN_VOXELS); } // Play sound if there is collision with voxel if (collisionResult != null) { if (collisionResult is MyStaticAsteroid) { if (!collisionResult.IsDestructible) { MinerWars.AppCode.Game.HUD.MyHud.ShowIndestructableAsteroidNotification(); } } StartDrillingCue(collisionResult is MyVoxelMap); StopMovingCue(); } else { StartMovingCue(); StopDrillingCue(); } // We found voxel so lets make tunel into it using (var voxelMapsFound = PoolList <MyVoxelMap> .Get()) { bool drilled = false; bool drilledSomeDestructibleContent = false; MyVoxelMaps.GetListOfVoxelMapsWhoseBoundingSphereIntersectsSphere(ref m_fakeCollisionSphere, voxelMapsFound, null); int drillInterval = MySession.Is25DSector ? 100 : (int)MyDrillDeviceConstants.DRILL_INTERVAL_IN_MILISECONDS; int timerToDrillInterval = MySession.Is25DSector ? 100 : (int)MyDrillDeviceConstants.TIME_TO_DRILL_VOXEL_IN_MILISECONDS; foreach (MyVoxelMap voxelMap in voxelMapsFound) { if ((collisionResult is MyVoxelMap) && ((MyMinerGame.TotalGamePlayTimeInMilliseconds - m_lastTimeDrilled) > drillInterval) && (MyMinerGame.TotalGamePlayTimeInMilliseconds - m_lastTimeDrillNotCollidedWithVoxelMapInMiliseconds) > timerToDrillInterval) { drilled = true; float rangeStep = 0; float radius = GetRadiusNeededForTunel(); BoundingSphere bigSphereForTunnel = new BoundingSphere(m_fakeCollisionSphere.Center, radius); while (rangeStep < m_range) { MyMwcVector3Int exactCenterOfDrilling = voxelMap.GetVoxelCoordinateFromMeters(bigSphereForTunnel.Center); // we don't want to drill indestructible voxels or empty space if (voxelMap.IsVoxelInVoxelMap(ref exactCenterOfDrilling) && voxelMap.GetVoxelMaterialIndestructibleContent(ref exactCenterOfDrilling) == MyVoxelConstants.VOXEL_CONTENT_FULL) { break; } else { drilledSomeDestructibleContent = true; } CutOutFromVoxel(voxelMap, ref bigSphereForTunnel); bigSphereForTunnel.Center += 2 * WorldMatrix.Forward; rangeStep += 1; } } } if (drilled) { m_lastTimeDrilled = MyMinerGame.TotalGamePlayTimeInMilliseconds; if (!drilledSomeDestructibleContent) { HUD.MyHud.ShowIndestructableAsteroidNotification(); } } } }