//Finds Currently Detected Enemy Location #region Enemy Scan #RFC# /*================================================= * Function: RFC Function bar #RFC# * --------------------------------------- */ Vector3D EnemyScan(MISSILE This_Missile) { //Targeting Module //----------------------------------------------- //Retrieves Target Position var This_Missile_Director = This_Missile.TURRET as IMyLargeTurretBase; var ENEMY_POS = new Vector3D(); //LOS as first call if (TOWCamera != null) { Vector3D Scanpos = RC.WorldMatrix.Forward * TOW_Distance; if (TOWCamera.CanScan(Scanpos)) { TemporaryTarget = new MyDetectedEntityInfo(); var ThisEntity = TOWCamera.Raycast(Scanpos); if (ThisEntity.Relationship == MyRelationsBetweenPlayerAndBlock.Enemies) { TemporaryTarget = ThisEntity; ENEMY_POS = (Vector3D)TemporaryTarget.HitPosition; } } } //Turret Detection As Secondary else if (This_Missile_Director.GetTargetedEntity().IsEmpty() == false && !(OverrideToLongTargets && TemporaryTarget.IsEmpty())) { ENEMY_POS = This_Missile_Director.GetTargetedEntity().Position; //Also based on position for critical hits } //Finally If nothing Detected on turrets default to LOS with some basic prediction else { if (!TemporaryTarget.IsEmpty()) { double TimeSinceFired = (TemporaryTarget.TimeStamp - DateTime.Now.Millisecond) / 1000.00; Vector3D Velocity = (Vector3D)TemporaryTarget.Velocity; ENEMY_POS = (Vector3D)TemporaryTarget.HitPosition + Velocity * TimeSinceFired; } //OtherWise Straigh Up TOW else { ENEMY_POS = RC.GetPosition() + RC.WorldMatrix.Forward * ((This_Missile.GYRO.GetPosition() - Me.GetPosition()).Length() + 300); } } return(ENEMY_POS); }
//SubMethod State Machine For Launching Missiles #region MissileLaunchHandler public IEnumerable <bool> MissileLaunchHandler() { //Gathers Missile Information yield return(INIT_NEXT_MISSILE()); //Disables Merge Block MISSILE ThisMissile = MISSILES[MISSILES.Count - 1]; var MERGE_A = ThisMissile.MERGE; (MERGE_A as IMyShipMergeBlock).Enabled = false; yield return(true); yield return(true); //Safety Tick //Launches Missile & Gathers Next Scanner PREP_FOR_LAUNCH(MISSILES.Count - 1); }
public void Update() { // スペースキーで一括回収 if (Input.GetKeyDown(KeyCode.Space)) { this.pool.Clear(); } // アクティブなオブジェクト数の更新 // 呼び出されたフレームで経過時間0 秒で処理されていたものを通常稼動扱いにする this.pool.FrameTop(); float elapsedTime = Time.deltaTime; this.calcTime += elapsedTime; // とりあえず0.1 秒毎に発射 float span = 0.1f; if (this.calcTime >= span) { // プールから取り出して点火 Missile2D missile; Vector3 point = trans_.localPosition; if (this.pool.AwakeObject((int)this.nextType, point, out missile)) { missile.Ignition(); } if (this.nextType == MISSILE.LEFT) { this.nextType = MISSILE.UP; } else { ++this.nextType; } this.calcTime -= span; } // アクティブなオブジェクトの更新 this.pool.Proc(elapsedTime); }
//Preps For Launch & Launches #region RFC Prep-For Launch Subroutine #RFC# /*================================================= * Function: RFC Function bar #RFC# * --------------------------------------- */ void PREP_FOR_LAUNCH(int INT) { Echo(INT + ""); MISSILE ThisMissile = MISSILES[INT]; ThisMissile.MissileMass = 0; ThisMissile.MissileThrust = 0; //Preps Battery For Launch var POWER_A = ThisMissile.POWER; if (ThisMissile.POWER != null && ThisMissile.POWER is IMyBatteryBlock) { POWER_A.ApplyAction("OnOff_On"); POWER_A.SetValue("Recharge", false); POWER_A.SetValue("Discharge", true); ThisMissile.MissileMass += POWER_A.Mass; } //Removes Thrusters That Are Still on the same Grid As launcher List <IMyThrust> TemporaryThrust = new List <IMyThrust>(); TemporaryThrust.AddRange(ThisMissile.THRUSTERS); for (int i = 0; i < TemporaryThrust.Count; i++) { var item = TemporaryThrust[i]; if (item.CubeGrid != ThisMissile.GYRO.CubeGrid) { ThisMissile.THRUSTERS.Remove(item); continue; } } //Retrieves Largest Thrust Direction Dictionary <Vector3D, double> ThrustDict = new Dictionary <Vector3D, double>(); foreach (IMyThrust item in ThisMissile.THRUSTERS) { Vector3D Fwd = item.WorldMatrix.Forward; double Thrval = item.MaxEffectiveThrust; if (ThrustDict.ContainsKey(Fwd) == false) { ThrustDict.Add(Fwd, Thrval); } else { ThrustDict[Fwd] = ThrustDict[Fwd] + Thrval; } } List <KeyValuePair <Vector3D, double> > ThrustList = ThrustDict.ToList(); ThrustList.Sort((x, y) => y.Value.CompareTo(x.Value)); Vector3D ThrForward = ThrustList[0].Key; //Preps Thrusters For Launch (removes any not on grid) TemporaryThrust = new List <IMyThrust>(); TemporaryThrust.AddRange(ThisMissile.THRUSTERS); for (int i = 0; i < TemporaryThrust.Count; i++) { var item = TemporaryThrust[i]; //Retrieves Thrusters Only Going In The Forward if (item.WorldMatrix.Forward != ThrForward) { item.ApplyAction("OnOff_On"); ThisMissile.THRUSTERS.Remove(item); continue; } //Runs Std Operations item.ApplyAction("OnOff_On"); double ThisThrusterThrust = (item as IMyThrust).MaxThrust; (item as IMyThrust).ThrustOverride = (float)ThisThrusterThrust; ThisMissile.MissileThrust += ThisThrusterThrust; ThisMissile.MissileMass += item.Mass; } //Removes Any Warheads Not On The Grid List <IMyTerminalBlock> TemporaryWarheads = new List <IMyTerminalBlock>(); TemporaryWarheads.AddRange(ThisMissile.WARHEADS); for (int i = 0; i < ThisMissile.WARHEADS.Count; i++) { var item = TemporaryWarheads[i]; if (item.CubeGrid != ThisMissile.GYRO.CubeGrid) { ThisMissile.WARHEADS.Remove(item); continue; } ThisMissile.MissileMass += item.Mass; } //----------------------------------------------------- //Adds Additional Mass & Sets Accel (ovverrides If Possible) ThisMissile.MissileMass += ThisMissile.GYRO.Mass; ThisMissile.MissileMass += ThisMissile.MERGE.Mass; double number; if (double.TryParse(ThisMissile.GYRO.CustomData, out number)) { double.TryParse(ThisMissile.GYRO.CustomData, out ThisMissile.MissileMass); } ThisMissile.MissileAccel = ThisMissile.MissileThrust / ThisMissile.MissileMass; //Sets Grid Type ThisMissile.IsLargeGrid = ThisMissile.GYRO.CubeGrid.GridSizeEnum == MyCubeSize.Large; ThisMissile.FuseDistance = ThisMissile.IsLargeGrid ? 16 : 7; }
//Finds First Missile Available #region RFC Initialise Missile Blocks #RFC# /*================================================= * Function: RFC Function bar #RFC# * --------------------------------------- */ bool INIT_NEXT_MISSILE() { //Finds Missile Blocks (performs 1 gts) List <IMyTerminalBlock> GYROS = new List <IMyTerminalBlock>(); GridTerminalSystem.GetBlocksOfType <IMyGyro>(GYROS, b => b.CustomName == "#A#"); List <IMyTerminalBlock> TURRETS = new List <IMyTerminalBlock>(); GridTerminalSystem.GetBlocksOfType <IMyLargeTurretBase>(TURRETS, b => b.CustomName == "#A#"); List <IMyThrust> THRUSTERS = new List <IMyThrust>(); GridTerminalSystem.GetBlocksOfType <IMyThrust>(THRUSTERS, b => b.CustomName == "#A#"); List <IMyTerminalBlock> MERGES = new List <IMyTerminalBlock>(); GridTerminalSystem.GetBlocksOfType <IMyShipMergeBlock>(MERGES, b => b.CustomName == "#A#"); List <IMyTerminalBlock> BATTERIES = new List <IMyTerminalBlock>(); GridTerminalSystem.GetBlocksOfType <IMyTerminalBlock>(BATTERIES, b => b.CustomName == "#A#" && (b is IMyBatteryBlock || b is IMyReactor)); List <IMyTerminalBlock> WARHEADS = new List <IMyTerminalBlock>(); GridTerminalSystem.GetBlocksOfType <IMyWarhead>(WARHEADS, b => b.CustomName == "#A#"); //Diagnostics For No Gyro Lstrundata = "No More Missile (Gyros) Detected"; //Iterates Through List To Find Complete Missile Based On Gyro foreach (var Key_Gyro in GYROS) { MISSILE NEW_MISSILE = new MISSILE(); NEW_MISSILE.GYRO = Key_Gyro; Vector3D GyroPos = Key_Gyro.GetPosition(); double Distance = 40; //Sorts And Selects Turrets List <IMyTerminalBlock> TempTurrets = TURRETS.FindAll(b => (b.GetPosition() - GyroPos).LengthSquared() < Distance * Distance); TempTurrets.Sort((x, y) => (x.GetPosition() - Key_Gyro.GetPosition()).LengthSquared().CompareTo((y.GetPosition() - Key_Gyro.GetPosition()).LengthSquared())); //Sorts And Selects Batteries List <IMyTerminalBlock> TempPower = BATTERIES.FindAll(b => (b.GetPosition() - GyroPos).LengthSquared() < Distance * Distance); TempPower.Sort((x, y) => (x.GetPosition() - Key_Gyro.GetPosition()).LengthSquared().CompareTo((y.GetPosition() - Key_Gyro.GetPosition()).LengthSquared())); //Sorts And Selects Merges List <IMyTerminalBlock> TempMerges = MERGES.FindAll(b => (b.GetPosition() - GyroPos).LengthSquared() < Distance * Distance); TempMerges.Sort((x, y) => (x.GetPosition() - Key_Gyro.GetPosition()).LengthSquared().CompareTo((y.GetPosition() - Key_Gyro.GetPosition()).LengthSquared())); //Sorts And Selects Thrusters NEW_MISSILE.THRUSTERS = THRUSTERS.FindAll(b => (b.GetPosition() - GyroPos).LengthSquared() < Distance * Distance); //Sorts And Selects Warheads NEW_MISSILE.WARHEADS = WARHEADS.FindAll(b => (b.GetPosition() - GyroPos).LengthSquared() < Distance * Distance); //Checks All Key Blocks Are Present bool HasTurret = TempTurrets.Count > 0; bool HasPower = TempPower.Count > 0; bool HasMerge = TempMerges.Count > 0; bool HasThruster = NEW_MISSILE.THRUSTERS.Count > 0; //Echos Some Useful Diagnostics Lstrundata = "Last Missile Failed To Fire\nReason:" + "\nHas Gyro: True" + "\nHas Turret: " + HasTurret + "\nHas Power: " + HasPower + "\nHasMerge: " + HasMerge + "\nHasThruster: " + HasThruster; //Assigns and Exits Loop if (HasTurret && HasPower && HasMerge && HasThruster) { NEW_MISSILE.TURRET = TempTurrets[0]; NEW_MISSILE.POWER = TempPower[0]; NEW_MISSILE.MERGE = TempMerges[0]; MISSILES.Add(NEW_MISSILE); Lstrundata = "Launched Missile:" + MISSILES.Count; return(true); } } return(false); }
//Standard Guidance Routine #region RdavNav Missile Guidance #RFC# /*================================================= * RdavNav * --------------------------------------- */ void STD_GUIDANCE(MISSILE This_Missile) { //Targeting Module //----------------------------------------------- //Retrieves Target Position var This_Missile_Director = This_Missile.TURRET as IMyLargeTurretBase; var ENEMY_POS = new Vector3D(); //Logical Determination Of Enemy Position if (This_Missile_Director.GetTargetedEntity().IsEmpty() == false) { ENEMY_POS = This_Missile_Director.GetTargetedEntity().Position; //Also based on position for critical hits } //else if (!(This_Missile.TARGET_PREV_POS == null)) //new Vector3D() //{ENEMY_POS = This_Missile.TARGET_PREV_POS;} else { ENEMY_POS = RC.GetPosition() + RC.WorldMatrix.Forward * ((This_Missile.GYRO.GetPosition() - Me.GetPosition()).Length() + 300); } //Sorts CurrentVelocities Vector3D MissilePosition = This_Missile.GYRO.CubeGrid.WorldVolume.Center; Vector3D MissilePositionPrev = This_Missile.MIS_PREV_POS; Vector3D MissileVelocity = (MissilePosition - MissilePositionPrev) / Global_Timestep; Vector3D TargetPosition = ENEMY_POS; Vector3D TargetPositionPrev = This_Missile.TARGET_PREV_POS; Vector3D TargetVelocity = (TargetPosition - This_Missile.TARGET_PREV_POS) / Global_Timestep; //Uses RdavNav Navigation APN Guidance System //----------------------------------------------- //Setup LOS rates and PN system Vector3D LOS_Old = Vector3D.Normalize(TargetPositionPrev - MissilePositionPrev); Vector3D LOS_New = Vector3D.Normalize(TargetPosition - MissilePosition); Vector3D Rel_Vel = Vector3D.Normalize(TargetVelocity - MissileVelocity); //And Assigners Vector3D am = new Vector3D(1, 0, 0); double LOS_Rate; Vector3D LOS_Delta; Vector3D MissileForwards = This_Missile.THRUSTERS[0].WorldMatrix.Backward; //Vector/Rotation Rates if (LOS_Old.Length() == 0) { LOS_Delta = new Vector3D(0, 0, 0); LOS_Rate = 0.0; } else { LOS_Delta = LOS_New - LOS_Old; LOS_Rate = LOS_Delta.Length() / Global_Timestep; } //----------------------------------------------- //Closing Velocity double Vclosing = (TargetVelocity - MissileVelocity).Length(); //If Under Gravity Use Gravitational Accel Vector3D GravityComp = -RC.GetNaturalGravity(); //Calculate the final lateral acceleration Vector3D LateralDirection = Vector3D.Normalize(Vector3D.Cross(Vector3D.Cross(Rel_Vel, LOS_New), Rel_Vel)); Vector3D LateralAccelerationComponent = LateralDirection * PNGain * LOS_Rate * Vclosing + LOS_Delta * 9.8 * (0.5 * PNGain); //Eases Onto Target Collision LOS_Delta * 9.8 * (0.5 * Gain) //If Impossible Solution (ie maxes turn rate) Use Drift Cancelling For Minimum T double OversteerReqt = (LateralAccelerationComponent).Length() / This_Missile.MissileAccel; if (OversteerReqt > 0.98) { LateralAccelerationComponent = This_Missile.MissileAccel * Vector3D.Normalize(LateralAccelerationComponent + (OversteerReqt * Vector3D.Normalize(-MissileVelocity)) * 40); } //Calculates And Applies Thrust In Correct Direction (Performs own inequality check) double ThrustPower = RdavUtils.Vector_Projection_Scalar(MissileForwards, Vector3D.Normalize(LateralAccelerationComponent)); //TESTTESTTEST ThrustPower = This_Missile.IsLargeGrid ? MathHelper.Clamp(ThrustPower, 0.9, 1) : ThrustPower; //MathHelper.Clamp(ThrustPower, 0.6, 1); //for improved thrust performance foreach (IMyThrust thruster in This_Missile.THRUSTERS) { if (thruster.ThrustOverride != (thruster.MaxThrust * ThrustPower)) //12 increment inequality to help conserve on performance { thruster.ThrustOverride = (float)(thruster.MaxThrust * ThrustPower); } } //Calculates Remaining Force Component And Adds Along LOS double RejectedAccel = Math.Sqrt(This_Missile.MissileAccel * This_Missile.MissileAccel - LateralAccelerationComponent.LengthSquared()); //Accel has to be determined whichever way you slice it if (double.IsNaN(RejectedAccel)) { RejectedAccel = 0; } LateralAccelerationComponent = LateralAccelerationComponent + LOS_New * RejectedAccel; //----------------------------------------------- //Guides To Target Using Gyros am = Vector3D.Normalize(LateralAccelerationComponent + GravityComp); double Yaw; double Pitch; GyroTurn6(am, 18, 0.3, This_Missile.THRUSTERS[0], This_Missile.GYRO as IMyGyro, This_Missile.PREV_Yaw, This_Missile.PREV_Pitch, out Pitch, out Yaw); //Updates For Next Tick Round This_Missile.TARGET_PREV_POS = TargetPosition; This_Missile.MIS_PREV_POS = MissilePosition; This_Missile.PREV_Yaw = Yaw; This_Missile.PREV_Pitch = Pitch; //Detonates warheads in close proximity if ((TargetPosition - MissilePosition).LengthSquared() < 20 * 20 && This_Missile.WARHEADS.Count > 0) //Arms { foreach (var item in This_Missile.WARHEADS) { (item as IMyWarhead).IsArmed = true; } } if ((TargetPosition - MissilePosition).LengthSquared() < This_Missile.FuseDistance * This_Missile.FuseDistance && This_Missile.WARHEADS.Count > 0) //A mighty earth shattering kaboom { (This_Missile.WARHEADS[0] as IMyWarhead).Detonate(); } }