/// <summary> /// Creates a missile with homing and target finding capabilities. /// </summary> public GuidedMissile(IMyEntity missile, GuidedMissileLauncher launcher, Target initialTarget) : base(missile, launcher.CubeBlock) { m_launcher = launcher; myAmmo = launcher.loadedAmmo; m_entity = missile; m_owner = launcher.CubeBlock.OwnerId; if (myAmmo.Description.HasAntenna) { myAntenna = new RelayNode(missile, () => m_owner, ComponentRadio.CreateRadio(missile, 0f)); } TryHard = true; SEAD = myAmmo.Description.SEAD; Static.AllGuidedMissiles.Add(this); Registrar.Add(MyEntity, this); MyEntity.OnClose += MyEntity_OnClose; acceleration = myDescr.Acceleration + myAmmo.MissileDefinition.MissileAcceleration; addSpeedPerUpdate = myDescr.Acceleration * Globals.UpdateDuration; if (!(launcher.CubeBlock is Sandbox.ModAPI.Ingame.IMyLargeTurretBase)) { m_rail = new RailData(Vector3D.Transform(MyEntity.GetPosition(), CubeBlock.WorldMatrixNormalizedInv)); } Options = m_launcher.m_weaponTarget.Options.Clone(); Options.TargetingRange = myAmmo.Description.TargetRange; SetTarget(initialTarget); if (myAmmo.RadarDefinition != null) { Log.DebugLog("Has a radar definiton"); m_radar = new RadarEquipment(missile, myAmmo.RadarDefinition, launcher.CubeBlock); if (myAntenna == null) { Log.DebugLog("Creating node for radar"); myAntenna = new RelayNode(missile, () => m_owner, null); } } Log.DebugLog("Options: " + Options + ", initial target: " + (CurrentTarget == null ? "null" : CurrentTarget.Entity.getBestName()) + ", entityId: " + missile.EntityId); //Log.DebugLog("AmmoDescription: \n" + MyAPIGateway.Utilities.SerializeToXML<Ammo.AmmoDescription>(myDescr), "GuidedMissile()"); }
/// <summary> /// Creates a missile with homing and target finding capabilities. /// </summary> public GuidedMissile(IMyEntity missile, GuidedMissileLauncher launcher, out Target initialTarget) : base(missile, launcher.CubeBlock) { myLogger = new Logger("GuidedMissile", () => missile.getBestName(), () => m_stage.ToString()); m_launcher = launcher; myAmmo = launcher.loadedAmmo; m_owner = launcher.CubeBlock.OwnerId; if (myAmmo.Description.HasAntenna) myAntenna = new RelayNode(missile, () => m_owner, ComponentRadio.CreateRadio(missile, 0f)); TryHard = true; SEAD = myAmmo.Description.SEAD; AllGuidedMissiles.Add(this); MyEntity.OnClose += MyEntity_OnClose; acceleration = myDescr.Acceleration + myAmmo.MissileDefinition.MissileAcceleration; addSpeedPerUpdate = myDescr.Acceleration * Globals.UpdateDuration; if (!(launcher.CubeBlock is Sandbox.ModAPI.Ingame.IMyLargeTurretBase)) m_rail = new RailData(Vector3D.Transform(MyEntity.GetPosition(), CubeBlock.WorldMatrixNormalizedInv)); Options = m_launcher.m_weaponTarget.Options.Clone(); Options.TargetingRange = myAmmo.Description.TargetRange; RelayStorage storage = launcher.m_relayPart.GetStorage(); if (storage == null) { myLogger.debugLog("failed to get storage for launcher", Logger.severity.WARNING); } else { myLogger.debugLog("getting initial target from launcher", Logger.severity.DEBUG); GetLastSeenTarget(storage, myAmmo.MissileDefinition.MaxTrajectory); } initialTarget = CurrentTarget; if (myAmmo.RadarDefinition != null) { myLogger.debugLog("Has a radar definiton"); m_radar = new RadarEquipment(missile, myAmmo.RadarDefinition, launcher.CubeBlock); if (myAntenna == null) { myLogger.debugLog("Creating node for radar"); myAntenna = new RelayNode(missile, () => m_owner, null); } } Registrar.Add(missile, this); myLogger.debugLog("Options: " + Options + ", initial target: " + (myTarget == null ? "null" : myTarget.Entity.getBestName())); //myLogger.debugLog("AmmoDescription: \n" + MyAPIGateway.Utilities.SerializeToXML<Ammo.AmmoDescription>(myDescr), "GuidedMissile()"); }
// 初始化铁轨 public void InitRails() { int world_x = (int)transform.position.x, world_z = (int)transform.position.z; RailsArray = new GameObject[30, 40]; int i = 0; foreach (Transform rail in transform) { rail.position = new Vector3(world_x, 1, world_z + i); rail.name = "Rail_" + world_x + "_" + (world_z + i); RailsArray[world_x, world_z + i] = rail.gameObject; ++i; } Transform StationRails = GameObject.Find("Terminal").transform.Find("Rails"); EndRail = new RailData[2]; i = 0; foreach (Transform rail in StationRails) { EndRail[i] = new RailData(); EndRail[i].pos = rail.position; EndRail[i].faceDirect = FaceDirect.East; EndRail[i].turnDirect = TurnDirect.Straight; int sx = (int)rail.position.x, sz = (int)rail.position.z; RailsArray[sx, sz] = rail.gameObject; ++i; } LastRail = new RailData(); LastRail.pos = new Vector3(world_x, 1, world_z + 9); LastRail.faceDirect = FaceDirect.East; LastRail.turnDirect = TurnDirect.Straight; Finish = false; }
/// <summary> /// Updates m_stage if guidance starts or stops. /// </summary> private void CheckGuidance() { switch (m_stage) { case Stage.Rail: double minDist = (MyEntity.WorldAABB.Max - MyEntity.WorldAABB.Min).AbsMax(); minDist *= 2; if (CubeBlock.WorldAABB.DistanceSquared(MyEntity.GetPosition()) >= minDist * minDist) { myGuidanceEnds = Globals.ElapsedTime.Add(TimeSpan.FromSeconds(myDescr.GuidanceSeconds)); m_rail = null; if (myDescr.SemiActiveLaser) { Log.DebugLog("past arming range, semi-active.", Logger.severity.INFO); m_stage = Stage.SemiActive; return; } if (CurrentTarget is GolisTarget) { Log.DebugLog("past arming range, golis active", Logger.severity.INFO); m_stage = Stage.Golis; return; } if (myAmmo.Description.BoostDistance > 1f) { Log.DebugLog("past arming range, starting boost stage", Logger.severity.INFO); StartGravity(); m_stage = Stage.Boost; if (m_gravData == null) { Log.DebugLog("no gravity, terminating", Logger.severity.WARNING); m_stage = Stage.Terminated; } } else { Log.DebugLog("past arming range, starting guidance.", Logger.severity.INFO); m_stage = Stage.Guided; } } return; case Stage.Boost: if (Vector3D.DistanceSquared(CubeBlock.GetPosition(), MyEntity.GetPosition()) >= myAmmo.Description.BoostDistance * myAmmo.Description.BoostDistance) { Log.DebugLog("completed boost stage, starting mid course stage", Logger.severity.INFO); m_stage = Stage.MidCourse; } return; case Stage.MidCourse: Target t = CurrentTarget; if (t.Entity == null) { return; } double toTarget = Vector3D.Distance(MyEntity.GetPosition(), t.GetPosition()); double toLaunch = Vector3D.Distance(MyEntity.GetPosition(), CubeBlock.GetPosition()); if (toTarget < toLaunch) { Log.DebugLog("closer to target(" + toTarget + ") than to launch(" + toLaunch + "), starting guidance", Logger.severity.INFO); m_stage = Stage.Guided; myGuidanceEnds = Globals.ElapsedTime.Add(TimeSpan.FromSeconds(myDescr.GuidanceSeconds)); m_gravData = null; } return; case Stage.SemiActive: case Stage.Golis: case Stage.Guided: if (Globals.ElapsedTime >= myGuidanceEnds) { Log.DebugLog("finished guidance", Logger.severity.INFO); m_stage = Stage.Ballistic; } return; } }
public void Grind() { float sphereRad = 2f; // Perform a spherecast. If anything the cast touches has a rail, add it to a list of possible rails. Collider[] hitColliders = Physics.OverlapSphere(transform.position, sphereRad); if (hitColliders.Length > 0) { // Look through the list of rails and find the spline that is closest to the player. List <RailData> rails = new List <RailData>(); foreach (var c in hitColliders) { Transform parent = c.transform; while (parent != null) { RailData railData = parent.GetComponent <RailData>(); if (railData) { bool sameRail = false; foreach (var rail in rails) { if (rail == railData) { sameRail = true; break; } } if (!sameRail) { rails.Add(railData); } break; } else { parent = parent.parent; } } } if (rails.Count > 0) { // Default to the first rail BGCcMath closestRail = rails[0].m_railData[0]; float closestDist = Vector3.Distance(transform.position, rails[0].m_railData[0].CalcPositionByClosestPoint(transform.position)); foreach (var rail in rails) { foreach (var r in rail.m_railData) { // Find the coping that is nearest to the player float newClosestDist = Vector3.Distance(transform.position, r.CalcPositionByClosestPoint(transform.position)); if (newClosestDist < closestDist) { closestRail = r; closestDist = newClosestDist; } } } if (closestDist <= sphereRad) { // If the player is facing away from its movement vector, change to switch. Otherwise, they are in the regular stance float fwdVelDot = Vector3.Dot(transform.forward, m_rb.velocity); if (m_switch && fwdVelDot > 0) { m_switch = false; TrickManager.GetInstance().WriteToStanceTextBox("Regular"); } else if (!m_switch && fwdVelDot < 0) { m_switch = true; TrickManager.GetInstance().WriteToStanceTextBox("Switch"); } // Find the vector in front of the player or under the player that best suits m_moveDir = (m_switch) ? -transform.forward : transform.forward; m_currentRail = closestRail; m_grinding = true; } } } }
/// <summary> /// Updates m_stage if guidance starts or stops. /// </summary> private void CheckGuidance() { switch (m_stage) { case Stage.Rail: double minDist = (MyEntity.WorldAABB.Max - MyEntity.WorldAABB.Min).AbsMax(); minDist *= 2; if (CubeBlock.WorldAABB.DistanceSquared(MyEntity.GetPosition()) >= minDist * minDist) { m_rail = null; if (myDescr.SemiActiveLaser) { myGuidanceEnds = Globals.ElapsedTime.Add(TimeSpan.FromSeconds(myDescr.GuidanceSeconds)); myLogger.debugLog("past arming range, semi-active.", Logger.severity.INFO); m_stage = Stage.SemiActive; return; } if (myAmmo.Description.BoostDistance > 1f) { myLogger.debugLog("past arming range, starting boost stage", Logger.severity.INFO); StartGravity(); m_stage = Stage.Boost; if (m_gravData == null) { myLogger.debugLog("no gravity, terminating", Logger.severity.WARNING); m_stage = Stage.Terminated; } } else { myGuidanceEnds = Globals.ElapsedTime.Add(TimeSpan.FromSeconds(myDescr.GuidanceSeconds)); myLogger.debugLog("past arming range, starting guidance.", Logger.severity.INFO); m_stage = Stage.Guided; } } return; case Stage.Boost: if (Vector3D.DistanceSquared(CubeBlock.GetPosition(), MyEntity.GetPosition()) >= myAmmo.Description.BoostDistance * myAmmo.Description.BoostDistance) { myLogger.debugLog("completed boost stage, starting mid course stage", Logger.severity.INFO); m_stage = Stage.MidCourse; } return; case Stage.MidCourse: Target t = CurrentTarget; if (t.Entity == null) return; double toTarget = Vector3D.Distance(MyEntity.GetPosition(), t.GetPosition()); double toLaunch = Vector3D.Distance(MyEntity.GetPosition(), CubeBlock.GetPosition()); if (toTarget < toLaunch) { myLogger.debugLog("closer to target(" + toTarget + ") than to launch(" + toLaunch + "), starting guidance", Logger.severity.INFO); m_stage = Stage.Guided; myGuidanceEnds = Globals.ElapsedTime.Add(TimeSpan.FromSeconds(myDescr.GuidanceSeconds)); m_gravData = null; } return; case Stage.SemiActive: case Stage.Guided: if (Globals.ElapsedTime >= myGuidanceEnds) { myLogger.debugLog("finished guidance", Logger.severity.INFO); m_stage = Stage.Ballistic; } return; } }