

mpink
Members-
Posts
58 -
Joined
-
Last visited
Content Type
Profiles
Forums
Developer Articles
KSP2 Release Notes
Everything posted by mpink
-
LOL why not. I think it would probably be harder to script than to fly. Id still give you a run for you money. Now that would be cool and id love to see it. You have me thinking now..... You would need to be a very good shot with that seat but maybe just maybe it could be done predictably. Its defiantly a jeb style of getting to the VAB. Not sure about making tight turns though but brakes would help a lot. The current course is very flexible and dose not force you to do anything in an order just to achieve the 2 tasks before landing/crashing into the pad. The circle should be done below VAB roof height but is very flexible. My Thoughts on a mod are to make a gate command pod. You could then move a constructed gate into a position and set it in place with a lock button. Adding multiple gates would make the course and the lock could fix the gate in place off the ground. Passing through a gate could trigger a screen shot or 3 and a change of target to the next gate. Hummmmm a Restart system is a good call. I was planning on using the game clock and just spawning your craft in the center of the 1st gate. That way you would just revert to spawn and start again but i see that could be problematic if im not very very careful with the spawn position. Its just thoughts at the mo but it sounds like it should be easy. Iv got sketchy memories of a 2d rocket game in my youth. There were a few versions of it going around and 1 had multiplayer gate racing system. I suspect it would be a shed load harder in 3d but probably just a matter of practice. Im trying to think of places / features that would make good tracks. Id bet there are some good mountain canyons on kerbal and theres some cool spots on the moon too. LoL canyon moon racing might look a bit like a deathstart trench run. Any thoughts about places to checkout for making tracks would be great too. The most frightening thought is what Orbital Racing would look like. Trying to thread the needle doing like 2000M/S.
-
Thanks Im hoping that my kethane Mining colony plans will benefit a lot from this. I have visions of Mainsail powered transport ships . So i shall need a huge fuel transport network and bases that look like small towns. I updated that short video with a 5X playback rate so its only 10mins now As for being assured the top spot, im not so sure. I cant put this challenge down just yet and have a theoretical build that launches with 3 stages Using 25 sections delivering 30T into orbit for around 400 points. Its all stock and the build should be somewhat easy and a lot faster compared to the VTOL test. I still have a small Chuck Norris difficulty build i haven't showed yet too. My idea is that hard just isnt hard enough and Chuck Norris should mean stock only and no fuel pipes, struts or orange tanks. But with the number of other entry's to the challenge maybe making it harder wont help.
-
Ok im a day late but i think it was worth it. Hard Score 35.27T into LKO = 176.35 11 Sections so 8 Sections over the min + 80 = 256.35 Munar landing +50 = 306.35 Using Im A Cupcake Wannabe V0.3 Plugin. Now we have somewhat of a problem. Most of the video is at 3X speed already just to try and make the game clock run in real time but the full video is a shocking hour and a half long. I tryed a cut down version but its still 30 mins more than anyone will be willing to watch. I might try to get this one playing at 4X speed and then it will only take 17Mins LOL. Your best bet is to use the as you can skip to the parts you want much easier.Problem for me is that playlists dont seam to work if your watching in fullscreen mode. Ether way you will probably need some rock radio and snacks. Managed to put all the fuel tanks down with no crashes or retakes but the nose cones were a different matter. Think i placed all the parts when i was drunk a few weeks back and forgot to remove the side wheals from the Gear Action. After about 7 crashes i had to hack the save file to change the Action and fix my mistake. The only other bad problem i had was with that huge ladder. It looked like a bug caught on video to me. It seamed like the kerbal was following a ladder he was not in contact with and i had to retract it to get around the problem. I did try hacking gravity with the hope of jetpacking into the capsule before i found the fix but that resulted in the collapse of the rocket. So the bar has been truly set but is anyone crazy enough to try beating that ?
-
Telemachus can record and display most of the things your craft can do. Personally though i like to use a notepad and a pencil in more of a check list type style. Including things like activate SAS, Reduce throttle to 1.1G when going 110M/s (preferable under 1KM), Set nose up to 75 degrees at 200M/s (around 7KM) and Increase throttle to 2G at 10K (260M/s) Once i have a flight plan and check list draw out its very easy to spot where and when things are going wrong. If you do it this way you could save your crew by aborting before something gos very badly wrong. Using Telemachus can show you all of this but unless you have a co pilot to monitor it all then it probably wont help very much. The Wiki has a section about kerbins atmosphere and optimal speeds that is probably more important than understanding delta-v.
-
Rules You must start on the runway and become airborne as soon as you can to trigger the flight timer (dropping from a tower at the start should do this). You must pass under the walkway in the R&D department. You must do 1 circle of the VAB. Your time is taken when you safely land a kerbal on the Helipad on top of the VAB and stop moving (Just the kerbal i dont care about the craft). You must list any plugins that you use. Leader-board 2:27 - MPink Im sure iv seen one or two race type challenges before but im considering making a little racing mod and thought this would be a good tester as to peoples interest. My Entry I was using the Im a Cupcake Wannabe plugin. Landed and stopped at 2:27 on the flight clock. Im not superhuman the video is played back at 3X speed and still isnt in true game time. My poor old abused computer I look forward to seeing your attempts. Dont be afraid to post failures as almost making it can be very inspiring too. I know this time can be smashed with not to much effort but doing it on film is a different matter Good luck, have fun, and please put an ejection system on your craft !
-
[0.23] Im a Cupcake Wannabe (Advanced Hover System)
mpink replied to mpink's topic in KSP1 Mod Releases
v0.3 Update Crank the Rock Radio up to 11 and enjoy a 3 minute tour of the KSC demonstrating the power of V0.3 Change log Added reading of active gravity sensors for off world hovering. Added engine types to tweakable options for control over what engine types to use for a hover. Engine Types restricted to first 5 engine types found and should work for any engines (not just stock). Added a restriction so the ASS may only control 20 engines at one time. Code is still in the zip as ASS.cs //M Pink provides ASS (v0.3) freely for anyone to use for anyreason they see fit. //M Pink is not responsable for any damage caused by ASS. //Ass Should Be Used At Your Own Risk ! using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; namespace ASS { public class ASS : PartModule { [KSPField (guiName = "throtel", isPersistant=true, guiActive=false)] float throtel = 100f; [KSPField (guiName = "Version", isPersistant=true, guiActive=true, guiActiveEditor=true)] public string version = "0.3"; [UI_FloatRange (stepIncrement=0.01f, maxValue=2f, minValue=0f), KSPField (guiName="Translation G", isPersistant=true, guiActive=true, guiActiveEditor=true)] public float max_g_change = 0.25f; [KSPField (guiName="Gravity", isPersistant=false, guiActive=true, guiActiveEditor=false)] public string gravity_state = "No Sensor Found"; public int grav_sensor_index = -1; public bool grav_sensor_active = false; public string grav_readout = "....."; public float gravity = 9.82f; [UI_Toggle (enabledText="Deactivate", disabledText="Activate"), KSPField(guiName="ASS", isPersistant=true, guiActive=true, guiActiveEditor=true)] public bool ass_on = true; public bool ass_was_on = true; [KSPAction ("Action Activate ASS")] public void ActionActivateASS (KSPActionParam param) { this.ass_on=true; } [KSPAction ("Action Deactivate ASS")] public void ActionDeactivateASS (KSPActionParam param) { this.ass_on=false; } [KSPAction ("Action Toggle ASS")] public void ActionToggleASS (KSPActionParam param) { this.ass_on=!this.ass_on; } // //engine list int max_engine_types = 5; [KSPField (guiName="no_engine_types", isPersistant=true, guiActive=false)] int no_engine_types = 1; [UI_Toggle (enabledText="Release", disabledText="Control"), KSPField(guiName="Basic Jet Engine", isPersistant=true, guiActive=true, guiActiveEditor=true)] public bool engine_1 = true; [UI_Toggle (enabledText="Release", disabledText="Control"), KSPField(guiName="Engine 2", isPersistant=true, guiActive=true, guiActiveEditor=true)] public bool engine_2 = false; [UI_Toggle (enabledText="Release", disabledText="Control"), KSPField(guiName="Engine 3", isPersistant=true, guiActive=true, guiActiveEditor=true)] public bool engine_3 = false; [UI_Toggle (enabledText="Release", disabledText="Control"), KSPField(guiName="Engine 4", isPersistant=true, guiActive=true, guiActiveEditor=true)] public bool engine_4 = false; [UI_Toggle (enabledText="Release", disabledText="Control"), KSPField(guiName="Engine 5", isPersistant=true, guiActive=true, guiActiveEditor=true)] public bool engine_5 = false; [KSPField (guiName="engine_name_1", isPersistant=true, guiActive=false)] public string engine_name_1; [KSPField (guiName="engine_name_2", isPersistant=true, guiActive=false)] public string engine_name_2; [KSPField (guiName="engine_name_3", isPersistant=true, guiActive=false)] public string engine_name_3; [KSPField (guiName="engine_name_4", isPersistant=true, guiActive=false)] public string engine_name_4; [KSPField (guiName="engine_name_5", isPersistant=true, guiActive=false)] public string engine_name_5; public void SetEngineTypeName (int index_, string name_) { base.Fields[index_+6].guiName=name_; switch(index_) { case 0: this.engine_name_1=name_; break; case 1: this.engine_name_2=name_; break; case 2: this.engine_name_3=name_; break; case 3: this.engine_name_4=name_; break; case 4: this.engine_name_5=name_; break; } } public string GetEngineTypeName (int index_) { switch(index_) { case 0: return this.engine_name_1; case 1: return this.engine_name_2; case 2: return this.engine_name_3; case 3: return this.engine_name_4; case 4: return this.engine_name_5; } throw new SystemException("ASS.GetEngineTypeName() was passed invalid index_ of "+index_); } public void SetEngineControl (int index_, bool control_) { switch(index_) { case 0: this.engine_1=control_; break; case 1: this.engine_2=control_; break; case 2: this.engine_3=control_; break; case 3: this.engine_4=control_; break; case 4: this.engine_5=control_; break; } } public bool GetEngineControl (int index_) { switch(index_) { case 0: return this.engine_1; case 1: return this.engine_2; case 2: return this.engine_3; case 3: return this.engine_4; case 4: return this.engine_5; } throw new SystemException("ASS.GetEngineControl() was passed invalid index_ of "+index_); } public void SetNoEngineTypes ( int count_ ) { int a; this.no_engine_types=count_; for (a=0; a<this.max_engine_types; a++) { if (count_>a) { base.Fields[a+6].guiActive = base.Fields[a+6].guiActiveEditor = true; } else { base.Fields[a+6].guiActive = base.Fields[a+6].guiActiveEditor = false; } } } public void UpdateEngineState () { int a; this.engine_state=0; int state=1; for (a=0; a<this.no_engine_types; a++) { if (this.GetEngineControl(a)) this.engine_state += state; state*=2; } } [KSPEvent (guiName="Search For Engines", guiActive=true, guiActiveEditor=true)] void EventSearchForEngines () { Debug.Log("(ASS) EventSearchForEngines() Engine State = "+this.engine_state); this.GenEngineTypeList(); } bool sas_on=false; bool rcs_on=true; int no_parts_in_last_check = -1;//used to check if parts have changed from last update //list of part indices that are engines the system is will control int no_engines=0; int max_engines=20; int [] engine_indices = new int[20]; int engine_state = -1; int last_engine_state = -1; public ASS () { // Debug.Log("(ASS) Constructor()"); }//endof public ASS () public override void OnStart (PartModule.StartState state) { base.OnStart (state); // Debug.Log("(ASS) OnStart()"); /* Debug.Log(base.Events.Count+" Events"); int a; for (a=0; a<base.Events.Count; a++) { Debug.Log(a+") "+base.Events.GetByIndex(a).guiName); } Debug.Log(base.Fields.Count+" Fields"); for (a=0; a<base.Fields.Count; a++) { Debug.Log(a+") "+base.Fields[a].guiName); }*/ if (this.vessel!=null) {//vessel = null in editor //disable the find engines button if we are not in the editor base.Events.GetByIndex(0).active=false; } } public override void OnUpdate () { base.OnUpdate(); this.CheckGravSensor(); this.UpdateEngineState(); this.GenEngineList(); this.no_parts_in_last_check = this.vessel.parts.Count;//all changes in craft must now have been detected and delt with if (this.ass_was_on && !this.ass_on) { this.throtel=100f; this.SetThrust(); } this.ass_was_on = this.ass_on; if (!this.ass_on) return; //check for change in control states bool sas_state = this.vessel.ActionGroups[KSPActionGroup.SAS]; bool sas_changed = false; // bool rcs_changed = false; if (this.sas_on != sas_state) { this.sas_on = sas_state; sas_changed = true; } if (this.rcs_on != this.vessel.ActionGroups[KSPActionGroup.RCS] ) { this.rcs_on = this.vessel.ActionGroups[KSPActionGroup.RCS]; // rcs_changed = true; } //deal with changes in control state if (!this.sas_on && sas_changed) { //set throttel to max on SAS deactivation this.throtel=100f; this.SetThrust(); } //apply sas stablisation if (this.sas_on) { CenterOfThrustQuery cot = new CenterOfThrustQuery(); Vector3 thrust_vec = Vector3.zero; float t; int i; float combined_thust_center = 0; float target_thrust = this.gravity*this.vessel.GetTotalMass(); float thrust_range; //check engine list for (i=0; i<this.no_engines; i++) { this.vessel.parts[this.engine_indices[i]].FindModulesImplementing<ModuleEngines>()[0].OnCenterOfThrustQuery(cot); t = this.vessel.parts[this.engine_indices[i]].FindModulesImplementing<ModuleEngines>()[0].finalThrust; cot.dir.x *= t; cot.dir.y *= t; cot.dir.z *= t; thrust_vec += cot.dir; thrust_range = this.vessel.parts[this.engine_indices[i]].FindModulesImplementing<ModuleEngines>()[0].maxThrust - this.vessel.parts[this.engine_indices[i]].FindModulesImplementing<ModuleEngines>()[0].minThrust; combined_thust_center += ((t-this.vessel.parts[this.engine_indices[i]].FindModulesImplementing<ModuleEngines>()[0].minThrust)/thrust_range); } combined_thust_center /= ((float)this.no_engines); if (this.rcs_on) {//Change target thrust and thus vertical speed float max_thrust_change = (this.max_g_change*9.82f)*this.vessel.GetTotalMass (); target_thrust -= (max_thrust_change*this.vessel.ctrlState.Z); } //Check if we should set thrust to full or none. //It would be nice to calculate the exact thust needed but that would be very trouble some. //if ((target_thrust-thrust_vec.magnitude)<0f) this.throtel=0f; else this.throtel=100f; //Change of plans. Adjust throtle slowly and hope we find a sweatspot ! if (Mathf.Abs(target_thrust-thrust_vec.magnitude) > ((9.82f*this.vessel.GetTotalMass())*0.01) ) { const float max_change = 4f; if ((target_thrust-thrust_vec.magnitude)<0f) this.throtel-=max_change; else this.throtel+=max_change; } this.SetThrust(); } }//endof public override void OnUpdate () public void SetThrust () { //SetThrust can be caled from strange places like Actions so must have n engine list generator in it to prevent the use of invalid indices if (this.no_parts_in_last_check!=this.vessel.parts.Co unt) { this.GenEngineList(); } //clamp throtel as setting it out of range is cheating ! if (this.throtel>100f) this.throtel=100f; if (this.throtel<0f) this.throtel=0f; int i; //find engines for (i=0; i<this.no_engines; i++) { this.vessel.parts[this.engine_indices[i]].FindModulesImplementing<ModuleEngines>()[0].thrustPercentage = this.throtel; } }//endof void SetThrust () //Find active gravity sensor and then set gravity to a useable value public void CheckGravSensor () { this.FindActiveSensor(); if (this.grav_sensor_index==-1) { this.gravity_state = "No Sonsor Found"; } else { if (this.grav_sensor_active) { this.gravity_state = "No Active Sensor"; } else { try { // Debug.Log("(ASS) grav string = "+this.grav_readout); if (this.grav_readout.Length>5) { string s = this.grav_readout.Substring(0,this.grav_readout.Le ngth-5); // Debug.Log("(ASS) shrotend grav string = "+s); this.gravity = float.Parse(s); } else this.gravity = 9.82f; } catch { this.gravity = 9.82f; } this.gravity_state = this.grav_readout; } } }//endof void CheckGravSensor () public void FindActiveSensor () { if (no_parts_in_last_check!=this.vessel.parts.Count) {//if parts have change then the index is no longer valid this.grav_sensor_index = -1; this.grav_sensor_active = false; } if ( this.grav_sensor_index != -1 ) {//if grav sensor is valid check it is active and update readout this.grav_readout = this.vessel.parts[this.grav_sensor_index].FindModulesImplementing<ModuleEnviroSensor>()[0].readoutInfo; this.grav_sensor_active = this.grav_readout=="off"; } //We dont need to search again if we have an active sensor and parts have not changed if ( no_parts_in_last_check==this.vessel.parts.Count && this.grav_sensor_active==true ) return; this.grav_sensor_index = -1; this.grav_sensor_active = false; int i; for (i=0; i<this.vessel.parts.Count; i++) { if (this.vessel.parts[i].name=="sensorGravimeter") { if (this.vessel.parts[i].FindModulesImplementing<ModuleEnviroSensor>().Count>0) { // Debug.Log("(ASS) found sensor at "+i+") name="+this.vessel.parts[i].name); if (this.grav_sensor_index == -1) { // Debug.Log("(ASS) grav sensor index set to "+i+" as it was invalid"); this.grav_sensor_index=i; } this.grav_readout = this.vessel.parts[i].FindModulesImplementing<ModuleEnviroSensor>()[0].readoutInfo; this.grav_sensor_active = this.grav_readout=="off"; if (this.grav_sensor_active) { // Debug.Log("(ASS) found active sensor at "+i+" name="+this.vessel.parts[i].name); this.grav_sensor_index = i; break; } } } } }//endof void FindActiveSensor () public void AddPartToList ( Part p_, List<Part> list_ ) { list_.Add(p_); int i; for (i=0; i<p_.children.Count; i++) { this.AddPartToList(p_.children[i],list_); } } public void GenEngineTypeList () { // Debug.Log("(ASS) GenEngineTypeList() begining"); int c = 0; string[] new_names = {"","","","",""}; bool[] new_states = {false,false,false,false,false}; //all engines should be off by default unless there is no predefined engine states and then the 1st engine type should be enabled if (this.no_engine_types==0) new_states[0]=true; int i; //vessel will = null in editor so we must cycle through parts list another way Part start_part = this.part; while (start_part.parent!=null) start_part=start_part.parent; List<Part> part_list = new List<Part>(); AddPartToList(start_part,part_list); // Debug.Log("(ASS) GenEngineTypeList() searching "+part_list.Count+" parts"); for (i=0; i<part_list.Count; i++) { if (part_list[i].FindModulesImplementing<ModuleEngines>().Count>0) { string s = part_list[i].partInfo.title; int a; bool add_type=true; for (a=0; a<c; a++) { if (new_names[a]==s) add_type=false; } if (add_type) { new_names[c]=s; //search all engine types for match for(a=0; a<this.max_engine_types; a++) { if (this.GetEngineTypeName(a)==s) { new_states[c]=this.GetEngineControl(a); // Debug.Log("(ASS) GenEngineTypeList() "+s+" was found in old list and set as "+new_states[c]); } } c++; if (c>=this.max_engine_types) break; } } } for(i=0; i<c; i++) { // Debug.Log("(ASS) GenEngineTypeList() "+i+" = "+new_names[i]+" "+new_states[i]); this.SetEngineTypeName(i,new_names[i]); this.SetEngineControl(i,new_states[i]); } this.SetNoEngineTypes(c); // Debug.Log("(ASS) GenEngineTypeList() end"); } public void GenEngineList () { if (this.no_parts_in_last_check!=this.vessel.parts.Co unt || this.last_engine_state!=this.engine_state) { // Debug.Log("(ASS) GenEngineList() Engine State = "+this.engine_state); this.last_engine_state=this.engine_state; this.GenEngineTypeList(); this.no_engines=0; int p,t; for (p=0; p<this.vessel.parts.Count; p++) { if (this.vessel.parts[p].FindModulesImplementing<ModuleEngines>().Count>0) { // Debug.Log("(ASS) found engine "+p+" "+this.vessel.parts[p].partInfo.title); for (t=0; t<this.no_engine_types; t++) { if (this.GetEngineControl(t)) { if ( this.vessel.parts[p].partInfo.title == this.GetEngineTypeName(t) ) { // Debug.Log("(ASS) Adding engine "+p+" "+this.GetEngineTypeName(t)); this.engine_indices[this.no_engines] = p; this.no_engines++; if ( this.no_engines >= this.max_engines ) { // Debug.Log("(ASS) Found max number of engines "+this.max_engines); return; } } } } } } // Debug.Log("(ASS) "+this.no_engines+" Engines in control list"); } } public override void OnLoad (ConfigNode node) { // Debug.Log("(ASS) OnLoad node = "+node.ToString()); base.OnLoad(node); //This should eneble and disable the correct GUI engine components this.SetNoEngineTypes(this.no_engine_types); //This should set the GUI names from the stored data int i; for (i=0; i<this.no_engine_types; i++) this.SetEngineTypeName(i,this.GetEngineTypeName(i) ); } }//endof public class ASS : PartModule }//endof namespace ASS -
Hears a sneak preview of my current build and latest constructor. The final craft will be an 11 part monster But itl probably take 5 days to get the video made, edited and uploaded. I think I could build a Supper Heavy Lifter with this system now. It would need a mobile tower if it gets any higher but that would be the smallest of problems compered to solving the use of Mainsails at full throttle with dockingport joints like my new contender dose.
-
The 0.2V of the PNK A.S.S has been released in the plugins section. Iv thrown together a quick demonstration video. Im still working on my vertical construction methods but its taking me a long time to get it perfect. I have a new rocket and constructor undergoing testing now and hope to have a new hard entry for viewing soon.
-
[0.23] Im a Cupcake Wannabe (Advanced Hover System)
mpink replied to mpink's topic in KSP1 Mod Releases
Yes and no. It dose not change the engines acceleration time so that part is not cheating and adds a lot of problems to the flight. The craft in the video has rockets clipped into the jets in order to counter the problems with engine spool up time. The idea of the plugin is that once the engines are up to speed to cancel out gravity you don't need to change there speed very much but you do need upwards rockets for rapid speed changes. Cupcake is the player who made the video (using just a joystick and not this plugin). Source code is in the zip file named ASS.CS V0.2 = //M Pink provides ASS freely for anyone to use for anyreason they see fit. //M Pink is not responsable for any damage caused by ASS. //Ass Should Be Used At Your Own Risk ! using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; namespace ASS { public class ASS : PartModule { float throtel; [KSPField (guiName = "Active", isPersistant = true, guiActive = true)] public bool ass_on = true; [KSPAction ("Activate")] public void Activate (KSPActionParam param) { this.ass_on=true; } [KSPAction ("Deactivate")] public void Deactivate (KSPActionParam param) { this.ass_on=false; } [KSPAction ("Toggle")] public void Toggle (KSPActionParam param) { this.OnToggle (); } [KSPEvent (guiName = "Toggle ASS", guiActive = true)] public void OnToggle () { this.ass_on = !this.ass_on; } [UI_FloatRange (stepIncrement = 0.01f, maxValue = 1f, minValue = 0f), KSPField (guiName = "Translation G", isPersistant = true, guiActive = true, guiActiveEditor = true)] public float max_g_change = 0.25f; bool sas_on; bool rcs_on; public ASS () { Debug.Log("(ASS) Constructor()"); throtel = 100f; this.sas_on=false; this.rcs_on=true; } public override void OnUpdate () { base.OnUpdate(); if (!this.ass_on) return; //check for change in control states bool sas_state = this.vessel.ActionGroups[KSPActionGroup.SAS]; bool sas_changed = false; // bool rcs_changed = false; if (this.sas_on != sas_state) { this.sas_on = sas_state; sas_changed = true; } if (this.rcs_on != this.vessel.ActionGroups[KSPActionGroup.RCS] ) { this.rcs_on = this.vessel.ActionGroups[KSPActionGroup.RCS]; // rcs_changed = true; } //deal with changes in control state if (!this.sas_on && sas_changed) { //set throttel to max on SAS deactivation this.throtel=100f; this.SetThrust(); } //apply sas stablisation if (this.sas_on) { CenterOfThrustQuery cot = new CenterOfThrustQuery(); Vector3 thrust_vec = Vector3.zero; float t; int i; float target_thrust = 9.82f*this.vessel.GetTotalMass(); //find engines to check for (i=0; i<this.vessel.parts.Count; i++) { if (this.vessel.parts[i].name=="JetEngine") {//make a combined thrust vector for all engines this.vessel.parts[i].FindModulesImplementing<ModuleEngines>()[0].OnCenterOfThrustQuery(cot); t = this.vessel.parts[i].FindModulesImplementing<ModuleEngines>()[0].finalThrust; cot.dir.x *= t; cot.dir.y *= t; cot.dir.z *= t; thrust_vec += cot.dir; } } if (this.rcs_on) {//Change target thrust and thus vertical speed float max_thrust_change = (this.max_g_change*9.82f)*this.vessel.GetTotalMass(); target_thrust -= (max_thrust_change*this.vessel.ctrlState.Z); } //Check if we should set thrust to max or none. //It would be nice to calculate the exact thust needed but would be slow and hard. if ((target_thrust-thrust_vec.magnitude)<0f) this.throtel=0f; else this.throtel=100f; this.SetThrust(); } } public void SetThrust () { //clamp throtel as setting it out of range is cheating ! if (this.throtel>100f) this.throtel=100f; if (this.throtel<0f) this.throtel=0f; int i; //find engines for (i=0; i<this.vessel.parts.Count; i++) { if (this.vessel.parts[i].name=="JetEngine") {//apply thrtel to engine this.vessel.parts[i].FindModulesImplementing<ModuleEngines>()[0].thrustPercentage = this.throtel; } } } } } -
Im A Cupcake Wannabe (Advanced Hover System V0.41) V0.4 in action. The Intention of this plugin is to enable people to achieve the levels of flight control that Cupcake manages using just a joystick but using only a keyboard. http://www.youtube.com/watch?feature=player_embedded&v=SyUpLwbWbvU] Your probably better off just watching some example builds than reading my ramblings on how to use and setup the AHS. Examples Of v0.41 Builds (Tutorials) The plugin currently adds the parts Small Advanced Hover System and Large Advanced Hover System to the control section and the RCS Translation Module to all thrust tweakable engines on start-up. You may place multiple AHS on a craft at the same time and doing so will put the later found parts into a Slave mode where they just increase the number of engines that the Master AHS can control at any one time. The AHS Has 3 hover modes 1)Off = No hover control attempted 2)Active = Trys to output enough thrust to hover your craft no matte what direction it is facing. 3)Fixed = Uses a const thrust level that is just enough to hover but only if you point the craft in the correct direction. None of the hover modes attempt to change your speed but just cause a zero G effect. The hover direction can also be changed using tweakables and Actiongroups to let you change you orientation to the ground in mid flight. There is an RCS Translation Toggle in the tweakables/Action Groups that lets you enable/disable an RCS style 3D Translation using the RCS keys. To link engines into the AHS system you must right click on them and use the Next RCS Dimension and Toggle RCS Direction buttons to set the RCS Direction to your preferred state. Engines default to RCS Direction=None and in this state do not take up any of the AHS control slots. Action groups can also be used to set engine RCS Directions of all engines with one button press. The AHS produces a lot of heat and the small version is prone to Crashing or exploding if you do not use enough heat-sinks. All AHS use a SAS stack icon as to provide overheat warnings and show the active state using colour. White = Off Light Blue = Hover mode on and RCS Translation Active Green = Hover mode on Dark Blue = RCS Translation Active Red = Crashed The AHS can find and connect to an Active Gravity Sensor. Hovers are set by default at 9.82/MS but even Kerbins sea level gravity dose not match this so placing a gravity sensor and activating it on launch will greatly increase your chance of a stable hover (Especially off world) v0.3 Mun Lander Construction and Mission acelerated to 5X game time. Things Iv Tried But Dont Want To Continue With An Altitude lock. This was an attempt to maintain a set altitude but i found that with my lazy programming skills and the slow thrust change rate of the engines the craft would just yo yo + i think its better to need a little skill to fly still. Horizontal translation. This was an attempt to increase thrust to an engine on one side as to cause rotation and thus translation in response to the translation keys. The hope was that S.A.S would then correct the rotation but in reality the engines were too powerful and caused a lot of S.A.S drift completely defeating the point. Things To Do 1) Setup a heavy energy usage. The PNK A.S.S has a mass of 1 and should use lots of power to do all the computing. I think kerbal Comps probably get bigger as they get faster. 2) Enable Master Slave system for PNK A.S.S so that you can have more than one unit on a craft. Adding More units will increase the number of engines you can control at anyone time. 3) Look into adding tweakables to all engine modules as to add an RCS translation control for certain directions (RCS Mode: left/Right/none). This is just a way to better connect engine translation into the keyboard and not an attempt to replace the RCS system. These engines are not smart and will only do translation control not rotation. As the engines are manual setup this will need a lot of skill in the construction phase that should replace lake of skill one may have in the piloting phase. 4) Providing 3 works then it should be easy to set a hover direction using Action Groups. This would let you set what translation direction to use for controlling a hover. The main reason for this would be to enable some crazy acrobatics when constructing bases. You could remove a base component horizontally from its transport craft, rotate it 90 degrease and then hit an Action button to set the new hover direction and then place the component vertically. Attempt thrust to COM Alignment. Center of mass changes with strange payloads and so an auto balance system would be cool. while balancing trust to mass centres sounds good its a lot of work for not much of a result. Using multiple tugs at 1 time should be an easy way to balance any uneven load and force some need for skill to remain. 5) Monitor changes to the selected engine types and set the thrust on any released engines back to 100%. (probably irelevent but depends on how the RCS engine module works) Test 0.3 making a video for the Today I Build A Rocket challenge. (Currently the leader link) Build a Kethane Colony or 2 to test final version. Work With Variable Gravity (Find and use an active Gravity Sensor) Selectable Engine Type Tweakable Show the PNK A.S.S in action Full Change Log 0.41 Fixed stupid bugs so that the RCS Translation directions are the same as the RCS system (still dose not change perspective when using control from hear). Fixed silly bug where slaves were controlling as well as masters. Added 95% heat auto shutdown / crash state (wont always save you on a warp though) Running out of power now causes a crash state (When crashed the AHS needs to be shut down and started up again). Changed some of the max settings on sliders to try and give more precise control ( low end still seams to have a dead spot though ) Changed the gravity sensor reading so that the AHS gets its own supper precise gravity reading but only if a gravity sensor is in a working readable state. Added RCS Translation event and actions (No longer uses the RCS toggle). Removed the check for SAS toggle as hover mode replaced the need for this. Added Icon colours for the SAS stack icon (Cant use custom icons yet) so you can tell what state it is in at a glance without needing to right click the part. v0.4 Redesigned the ASS into an AHS so it now has hover direction, hover mode and some-other tweakables. Added RCSEngineTranslation Module and added it to all engine parts on start-up. Made 2 new models so that the AHS have there very own look (stock style). Added resource usage so it now eats up the energy and leaks out heat. Added Master/Slave system along with a more limiting number of controllable engines so multiple AHS should be needed for large craft. Added the Active hover mode as suggested by Virindi (good call there ) v0.3 Added reading of active gravity sensors for off world hovering. Added engine types to tweakable options for control over what engine types to use for a hover. Engine Types restricted to first 5 engine types found and should work for any engines (not just stock). Added a restriction so the ASS may only control 20 engines at one time. v0.2 Added thrust vector analysis so hovering can be maintained if engines move or dont all point in the same direction. Added Z translation controls and tweakable for changing your vertical speed. v0.1 Added the PNK ASS basic hover system. V0.41 Code with do what you want licence at the top //M Pink provides AHS (v0.41) freely for anyone to use for anyreason they see fit. //M Pink is not responsable for any damage caused by AHS. //AHS Should Be Used At Your Own Risk ! using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; namespace AHS { public class Direction {//Put an end to the problems of compearing strings (miss spelling a direction) by using the AHS.Direction public const string None = "None"; public const string Left = "Left"; public const string Right = "Right"; public const string Up = "Up"; public const string Down = "Down"; public const string Forward = "Forward"; public const string Backward = "Backward"; } [KSPAddon(KSPAddon.Startup.MainMenu,true)] public class RCSAddonSetup :MonoBehaviour { void Awake () { Debug.Log("(AHS.RCSAddonSetup) Awake()"); PartLoader pl = PartLoader.Instance; if (pl==null) { Debug.Log("(AHS.RCSAddonSetup) Partloader was null"); } else { Debug.Log("(AHS.RCSAddonSetup) Partloader Found"); Debug.Log("(AHS.RCSAddonSetup) Number of parts to scan = "+pl.parts.Count); int a=0; for (a=0; a<pl.parts.Count; a++) { bool has_engine = false; bool has_rcs = false; bool throtle_locked = true;//fail safe. Only use if throtleLocked is found and false int b=0; for (b=0; b<pl.parts[a].moduleInfos.Count; b++) { if ("Engine" == pl.parts[a].moduleInfos[b].moduleName) has_engine=true; if ("RCSEngineTranslation" == pl.parts[a].moduleInfos[b].moduleName) has_rcs=true; } if (has_engine) {//parts that dont have a ModuleEngines will return null for FindModulesImplementing if (pl.parts[a].partPrefab.FindModulesImplementing<ModuleEngines>().Count!=0) { throtle_locked = pl.parts[a].partPrefab.FindModulesImplementing<ModuleEngines>()[0].throttleLocked; } } if (has_engine && !has_rcs && !throtle_locked) { Debug.Log("(AHS.RCSAddonSetup) Engine module found for "+pl.parts[a].title+" adding RCSEngineTranslation module"); pl.parts[a].partPrefab.AddModule("RCSEngineTranslation"); AvailablePart.ModuleInfo info = new AvailablePart.ModuleInfo(); info.moduleName = "RCSEngineTranslation"; pl.parts[a].moduleInfos.Add(info); }//endof if (has_engine && !has_rcs) }//endof for (a=0; a<pl.parts.Count; a++) }//end of else if (pl==null) } } public class RCSEngineTranslation : PartModule { [KSPField (guiName = "dimention", isPersistant=true, guiActive=false)] int dimention = 0; [KSPField (guiName = "direction", isPersistant=true, guiActive=false)] bool invert_direction = false; [KSPField (guiName = "RCS Direction", isPersistant=false, guiActive=true, guiActiveEditor=true)] public string state_string = "Not Set Yet"; [KSPEvent ( guiName="Next RCS Dimention", guiActive=true, guiActiveEditor=true )] public void EventNextDirection() { this.dimention++; if (this.dimention>3) this.dimention=0; this.DisplayMode(); } [KSPEvent ( guiName="Togle RCS Direction", guiActive=true, guiActiveEditor=true )] public void EventTogleDirection() { this.invert_direction = !this.invert_direction; this.DisplayMode(); } [KSPAction ("Set RCS None")] void ActionSetRCSNone () { this.dimention=0; this.DisplayMode(); } [KSPAction ("Set RCS Left")] void ActionSetRCSLeft () { this.dimention=1; this.invert_direction=false; this.DisplayMode(); } [KSPAction ("Set RCS Right")] void ActionSetRCSRight () { this.dimention=1; this.invert_direction=true; this.DisplayMode(); } [KSPAction ("Set RCS Up")] void ActionSetRCSUp () { this.dimention=2; this.invert_direction=false; this.DisplayMode(); } [KSPAction ("Set RCS Down")] void ActionSetRCSDown () { this.dimention=2; this.invert_direction=true; this.DisplayMode(); } [KSPAction ("Set RCS Forward")] void ActionSetRCSForward () { this.dimention=3; this.invert_direction=false; this.DisplayMode(); } [KSPAction ("Set RCS Backward")] void ActionSetRCSBackward () { this.dimention=3; this.invert_direction=true; this.DisplayMode(); } public void DisplayMode () { switch (this.dimention) { case 1: if (!this.invert_direction) this.state_string=Direction.Left; else this.state_string=Direction.Right; break; case 2: if (!this.invert_direction) this.state_string=Direction.Up; else this.state_string=Direction.Down; break; case 3: if (!this.invert_direction) this.state_string=Direction.Forward; else this.state_string=Direction.Backward; break; default: this.state_string = Direction.None; break; } } public RCSEngineTranslation () { }//end of public RCSEngineTranslation () public override void OnLoad (ConfigNode node) { this.DisplayMode(); } public override void OnStart (PartModule.StartState state) { this.DisplayMode(); } }//end of public class RCSEngineTranslation : PartModule public class AHS : PartModule { //energy used per seconde [KSPField (isPersistant=true)] public float power_consumption = 0.5f; //heat produced per seconde [KSPField (isPersistant=true)] public float heat_production = 50f; //thrust settings for all dimentions //isPersistant is probably not needed as saves cant be done throtled up in an atmoshpher [KSPField (guiName = "throtel left", isPersistant=true, guiActive=false)] public float thrust_left = 100f; [KSPField (guiName = "throtel right", isPersistant=true, guiActive=false)] public float thrust_right = 100f; [KSPField (guiName = "throtel up", isPersistant=true, guiActive=false)] public float thrust_up = 100f; [KSPField (guiName = "throtel down", isPersistant=true, guiActive=false)] public float thrust_down = 100f; [KSPField (guiName = "throtel forward", isPersistant=true, guiActive=false)] public float thrust_forward = 100f; [KSPField (guiName = "throtel backward", isPersistant=true, guiActive=false)] public float thrust_backward = 100f; //start of display fields [KSPField (guiName = "Version", guiActive=true, guiActiveEditor=true)] public string version = "0.41"; [KSPField (guiName = "Comand State", guiActive=true, guiActiveEditor=true)] public string comand_state = "Not Set Yet";//Master,Slave,Off or Crashed. The state should be set to Off on deactivation and ony be set to Mast/Slave if its not Crashed [KSPField (guiName = "Engine Usage", guiActive=true, guiActiveEditor=true)] public string engine_usage = "Not Set Yet";//no / max [KSPField (guiName="Gravity", isPersistant=false, guiActive=true, guiActiveEditor=false)] public string gravity_state = "Not Set Yet"; public int grav_sensor_index = -1; public bool grav_sensor_active = false; public string grav_readout = "....."; public float gravity = 9.82f; [UI_Toggle (enabledText="Deactivate", disabledText="Activate"), KSPField(guiName="AHS", isPersistant=true, guiActive=true, guiActiveEditor=true)] public bool ahs_on = true; public bool ahs_was_on = true; [KSPAction ("Activate AHS")] public void ActionActivateAHS (KSPActionParam param) { this.ahs_on=true; } [KSPAction ("Deactivate AHS")] public void ActionDeactivateAHS (KSPActionParam param) { this.ahs_on=false; } [KSPAction ("Toggle AHS")] public void ActionToggleAHS (KSPActionParam param) { this.ahs_on=!this.ahs_on; } //halfway range seporators [UI_FloatRange (stepIncrement=0.01f, maxValue=3f, minValue=0.01f), KSPField (guiName="Translation G", isPersistant=true, guiActive=true, guiActiveEditor=true)] public float max_g_change = 0.25f; [UI_FloatRange (stepIncrement=0.5f, maxValue=25f, minValue=0.5f), KSPField (guiName="Thrust Change Rate", isPersistant=true, guiActive=true, guiActiveEditor=true)] public float max_thrust_change = 4f; [UI_Toggle (enabledText="Deactivate", disabledText="Activate"), KSPField(guiName="RCS Translation", isPersistant=true, guiActive=true, guiActiveEditor=true)] public bool rcs_on = true; [KSPAction ("Activate RCS Translation")] public void ActionActivateRCSTranslation (KSPActionParam param) { this.rcs_on=true; } [KSPAction ("Deactivate RCS Translation")] public void ActionDeactivateRCSTranslation (KSPActionParam param) { this.rcs_on=false; } [KSPAction ("Toggle RCS Translation")] public void ActionToggleRCSTranslation (KSPActionParam param) { this.rcs_on=!this.rcs_on; } [KSPField (guiName = "dimention", isPersistant=true, guiActive=false)] int hover_dimention = 3; [KSPField (guiName = "direction", isPersistant=true, guiActive=false)] bool hover_invert_direction = false; [KSPField (guiName = "Hover Direction", guiActive=true, guiActiveEditor=true)] public string hover_state_string = "Not Set Yet"; //index 0 [KSPEvent ( guiName="Next Hover Dimention", guiActive=true, guiActiveEditor=true )] public void EventNextDirection() { this.hover_dimention++; if (this.hover_dimention>3) this.hover_dimention=1; this.HoverDisplayMode(); } //index 1 [KSPEvent ( guiName="Togle Hover Direction", guiActive=true, guiActiveEditor=true )] public void EventTogleDirection() { this.hover_invert_direction = !this.hover_invert_direction; this.HoverDisplayMode(); } [KSPAction ("Hover Left")] public void ActionHoverLeft (KSPActionParam param) { this.hover_dimention=1; this.hover_invert_direction=false; this.HoverDisplayMode(); } [KSPAction ("Hover Right")] public void ActionHoveRight (KSPActionParam param) { this.hover_dimention=1; this.hover_invert_direction=true; this.HoverDisplayMode(); } [KSPAction ("Hover Up")] public void ActionHoverUP (KSPActionParam param) { this.hover_dimention=2; this.hover_invert_direction=false; this.HoverDisplayMode(); } [KSPAction ("Hover Down")] public void ActionHoverDown (KSPActionParam param) { this.hover_dimention=2; this.hover_invert_direction=true; this.HoverDisplayMode(); } [KSPAction ("Hover Forward")] public void ActionHoverForward (KSPActionParam param) { this.hover_dimention=3; this.hover_invert_direction=false; this.HoverDisplayMode(); } [KSPAction ("Hover Backward")] public void ActionHoverBackward (KSPActionParam param) { this.hover_dimention=3; this.hover_invert_direction=true; this.HoverDisplayMode(); } public void HoverDisplayMode () { switch (this.hover_dimention) { case 1: if (!this.hover_invert_direction) this.hover_state_string="Left"; else this.hover_state_string="Right"; break; case 2: if (!this.hover_invert_direction) this.hover_state_string="Up"; else this.hover_state_string="Down"; break; case 3: if (!this.hover_invert_direction) this.hover_state_string="Forward"; else this.hover_state_string="Backward"; break; default: this.hover_state_string = "None"; break; } } [KSPField (guiName="Hover Mode: Active", guiActive=false, isPersistant=true)] public int hover_mode = 1; //index 2 [KSPEvent (guiName="Hover Mode: Active", guiActive=true, guiActiveEditor=true)] public void EventNextHoverMode() { this.hover_mode++; if (this.hover_mode>2) this.hover_mode=0; this.SetHoverGUI(); } [KSPAction ("Set Active Hover Mode")] public void ActionSetActiveHover (KSPActionParam param) { this.hover_mode=1; this.SetHoverGUI(); } [KSPAction ("Set Fixed Hover Mode")] public void ActionSetFixedHover (KSPActionParam param) { this.hover_mode=2; this.SetHoverGUI(); } [KSPAction ("Set Hover Mode Off")] public void ActionSetHoverModeOff (KSPActionParam param) { this.hover_mode=0; this.SetHoverGUI(); } public void SetHoverGUI () { switch(this.hover_mode) { case 0: base.Events.GetByIndex(2).guiName="Hover Mode: Off"; break; case 1: base.Events.GetByIndex(2).guiName="Hover Mode: Active"; break; case 2: base.Events.GetByIndex(2).guiName="Hover Mode: Fixed"; break; } } //index 3 [KSPEvent (guiName="Force Editor Update", guiActive=true, guiActiveEditor=true)] void EventForceEditorUpdate () { this.CheckSlaveState(); this.CountEngines(); } int no_parts_in_last_check = -1;//used to check if parts have changed from last update [KSPField (isPersistant=true)] public int max_engines=10; public int controlable_engines=0; public List<int> slave_indices = new List<int>(); public AHS () { Debug.Log("(AHS) Constructor()"); }//endof public AHS () public override void OnStart (PartModule.StartState state) { base.OnStart (state); if (this.vessel!=null) {//vessel = null in editor //disable editor only events Debug.Log ("(AHS) Number of events = "+base.Events.Count); base.Events.GetByIndex(3).active=false; } this.HoverDisplayMode(); this.SetHoverGUI(); this.part.stagingIcon = "SAS";//DefaultIcons.CUSTOM } public override void OnUpdate () { base.OnUpdate(); this.CheckSlaveState();//master slave states could change every frame so needs checking //set icon color if (!this.ahs_on) this.part.stackIcon.SetIconColor(Color.white); else if (this.comand_state=="Crashed") this.part.stackIcon.SetIconColor(Color.red); else if (this.hover_mode!=0 && this.rcs_on) { this.part.stackIcon.SetIconColor(Color.cyan); } else if (this.hover_mode==0 && !this.rcs_on) { this.part.stackIcon.SetIconColor(Color.white); } else { if (this.hover_mode!=0) this.part.stackIcon.SetIconColor(Color.green); if (this.rcs_on) this.part.stackIcon.SetIconColor(Color.blue); } if (this.comand_state!="Master" && this.comand_state!="Slave") return; this.CheckGravSensor(); //all changes in craft must now have been detected and delt with this.no_parts_in_last_check = this.vessel.parts.Count; //energy useage check double amount_needed = (double)(this.power_consumption * TimeWarp.deltaTime); double amount_got = this.part.RequestResource("ElectricCharge" ,amount_needed); if ((amount_needed*0.95) > amount_got ) { this.comand_state = "Crashed"; return; } //temperature check if (this.part.temperature >= (this.part.maxTemp*0.95)) { this.comand_state = "Crashed"; return; } this.part.temperature += (this.heat_production * TimeWarp.deltaTime); //check for change in control states this.ahs_was_on = this.ahs_on; if (!this.ahs_on) return; this.CountEngines();//engines may be changed anytime so need rechecking //only the master control system should do any actual work if (this.comand_state!="Master") return; //apply AHS stablisation CenterOfThrustQuery cot = new CenterOfThrustQuery(); Vector3 thrust_up_vec = Vector3.zero; Vector3 thrust_down_vec = Vector3.zero; Vector3 thrust_left_vec = Vector3.zero; Vector3 thrust_right_vec = Vector3.zero; Vector3 thrust_forward_vec = Vector3.zero; Vector3 thrust_backward_vec = Vector3.zero; float t; int i; int c=0; List<ModuleEngines> engine_modules = new List<ModuleEngines>(); List<string> engine_rcs_state = new List<string>(); //make thrust vectors for (i=0; i<this.vessel.parts.Count; i++) { if (this.vessel.parts[i].FindModulesImplementing<RCSEngineTranslation>().Count>0) { if (this.vessel.parts[i].FindModulesImplementing<RCSEngineTranslation>()[0].state_string!="None" && c<this.controlable_engines) { c++; if (c==this.controlable_engines) Debug.Log("(AHS) Max controlable engines reached"); engine_modules.Add(this.vessel.parts[i].FindModulesImplementing<ModuleEngines>()[0]); engine_rcs_state.Add (this.vessel.parts[i].FindModulesImplementing<RCSEngineTranslation>()[0].state_string); this.vessel.parts[i].FindModulesImplementing<ModuleEngines>()[0].OnCenterOfThrustQuery(cot); t = this.vessel.parts[i].FindModulesImplementing<ModuleEngines>()[0].finalThrust; cot.dir.x *= t; cot.dir.y *= t; cot.dir.z *= t; switch (this.vessel.parts[i].FindModulesImplementing<RCSEngineTranslation>()[0].state_string) { case Direction.Up: thrust_up_vec += cot.dir; break; case Direction.Down: thrust_down_vec += cot.dir; break; case Direction.Left: thrust_left_vec += cot.dir; break; case Direction.Right: thrust_right_vec += cot.dir; break; case Direction.Forward: thrust_forward_vec += cot.dir; break; case Direction.Backward: thrust_backward_vec += cot.dir; break; } } } } float target_up_thrust = 0f; float target_down_thrust = 0f; float target_left_thrust = 0f; float target_right_thrust = 0f; float target_forward_thrust = 0f; float target_backward_thrust = 0f; if (this.rcs_on) {//Change target thrust and thus vertical speed float g_change_in_thrust = (this.max_g_change*9.82f)*this.vessel.GetTotalMass(); target_down_thrust -= (g_change_in_thrust*this.vessel.ctrlState.Y); target_up_thrust += (g_change_in_thrust*this.vessel.ctrlState.Y); target_left_thrust += (g_change_in_thrust*this.vessel.ctrlState.X); target_right_thrust -= (g_change_in_thrust*this.vessel.ctrlState.X); target_forward_thrust -= (g_change_in_thrust*this.vessel.ctrlState.Z); target_backward_thrust += (g_change_in_thrust*this.vessel.ctrlState.Z); } //adjust target thrust for hover correction if (this.hover_mode>0) { switch (this.hover_state_string) { case Direction.Up: target_up_thrust += (this.gravity*this.vessel.GetTotalMass()); break; case Direction.Down: target_down_thrust += (this.gravity*this.vessel.GetTotalMass()); break; case Direction.Left: target_left_thrust += (this.gravity*this.vessel.GetTotalMass()); break; case Direction.Right: target_right_thrust += (this.gravity*this.vessel.GetTotalMass()); break; case Direction.Forward: target_forward_thrust += (this.gravity*this.vessel.GetTotalMass()); break; case Direction.Backward: target_backward_thrust += (this.gravity*this.vessel.GetTotalMass()); break; } if (this.hover_mode==1) { Vector3 sky_vector = this.vessel.mainBody.transform.position-this.vessel.transform.position; Vector3 sky_n = sky_vector.normalized; Vector3 thr_n = Vector3.zero; //rotating one normal into the other should return 0 if they are on the same plan and 1 if at 90 degrease to each other switch (this.hover_state_string) { case Direction.Up: thr_n = thrust_up_vec.normalized; break; case Direction.Down: thr_n = thrust_down_vec.normalized; break; case Direction.Left: thr_n = thrust_left_vec.normalized; break; case Direction.Right: thr_n = thrust_right_vec.normalized; break; case Direction.Forward: thr_n = thrust_forward_vec.normalized; break; case Direction.Backward: thr_n = thrust_backward_vec.normalized; break; } float m = Mathf.Abs( (sky_n.x* thr_n.x) + (sky_n.y*thr_n.y) + (sky_n.z* thr_n.z)); if (m==0f) m=0.00000001f;//avoid divide by 0 switch (this.hover_state_string) { case Direction.Up: target_up_thrust /= m; break; case Direction.Down: target_down_thrust /= m; break; case Direction.Left: target_left_thrust /= m; break; case Direction.Right: target_right_thrust /= m; break; case Direction.Forward: target_forward_thrust /= m; break; case Direction.Backward: target_backward_thrust /= m; break; } } } //Adjust throtles slowly and hope we find a sweatspot ! float irevavent_thrust = ((9.82f*this.vessel.GetTotalMass())*0.01f); if (target_up_thrust==thrust_up_vec.magnitude && thrust_up_vec.magnitude==0f) this.thrust_up=0f; else { if ((target_up_thrust-thrust_up_vec.magnitude)<0f) this.thrust_up-=this.max_thrust_change; else this.thrust_up+=this.max_thrust_change; this.thrust_up = Mathf.Clamp(this.thrust_up,0f,100f); } if (target_down_thrust==thrust_down_vec.magnitude && thrust_down_vec.magnitude==0f) this.thrust_down=0f; else { if ((target_down_thrust-thrust_down_vec.magnitude)<0f) this.thrust_down-=this.max_thrust_change; else this.thrust_down+=this.max_thrust_change; this.thrust_down = Mathf.Clamp(this.thrust_down,0f,100f); } if (target_left_thrust==thrust_left_vec.magnitude && thrust_left_vec.magnitude==0f) this.thrust_left=0f; else { if ((target_left_thrust-thrust_left_vec.magnitude)<0f) this.thrust_left-=this.max_thrust_change; else this.thrust_left+=this.max_thrust_change; this.thrust_left = Mathf.Clamp(this.thrust_left,0f,100f); } if (target_right_thrust==thrust_right_vec.magnitude && thrust_right_vec.magnitude==0f) this.thrust_right=0f; else { if ((target_right_thrust-thrust_right_vec.magnitude)<0f) this.thrust_right-=this.max_thrust_change; else this.thrust_right+=this.max_thrust_change; this.thrust_right = Mathf.Clamp(this.thrust_right,0f,100f); } if (target_forward_thrust==thrust_forward_vec.magnitude && thrust_forward_vec.magnitude==0f) this.thrust_forward=0f; else { if ((target_forward_thrust-thrust_forward_vec.magnitude)<0f) this.thrust_forward-=this.max_thrust_change; else this.thrust_forward+=this.max_thrust_change; this.thrust_forward = Mathf.Clamp(this.thrust_forward,0f,100f); } if (target_backward_thrust==thrust_backward_vec.magnitude && thrust_backward_vec.magnitude==0f) this.thrust_backward=0f; else { if ((target_backward_thrust-thrust_backward_vec.magnitude)<0f) this.thrust_backward-=this.max_thrust_change; else this.thrust_backward+=this.max_thrust_change; this.thrust_backward = Mathf.Clamp(this.thrust_backward,0f,100f); } //set engine thrusts for (i=0; i<engine_modules.Count; i++) { switch (engine_rcs_state[i]) { case Direction.Up: engine_modules[i].thrustPercentage = this.thrust_up; break; case Direction.Down: engine_modules[i].thrustPercentage = this.thrust_down; break; case Direction.Left: engine_modules[i].thrustPercentage = this.thrust_left; break; case Direction.Right: engine_modules[i].thrustPercentage = this.thrust_right; break; case Direction.Forward: engine_modules[i].thrustPercentage = this.thrust_forward; break; case Direction.Backward: engine_modules[i].thrustPercentage = this.thrust_backward; break; } } }//endof public override void OnUpdate () //Used in editor to update gui info. Should be done in update as a full engine scan will be done every time as to check for states public void CountEngines () { int i; int master_index=-1; //vessel will = null in the editor so we must cycle through parts list another way if it is not set List <Part> part_list; if (this.vessel!=null) { part_list = this.vessel.Parts; } else { part_list = new List<Part>(); Part start_part = this.part; while (start_part.parent!=null) start_part=start_part.parent; AddPartToList(start_part,part_list); } int controlable_no = 0; int found_engines = 0; for (i=0; i<part_list.Count; i++) { if (part_list[i].FindModulesImplementing<AHS>().Count>0) { //functional states are only Master or Slave if (part_list[i].FindModulesImplementing<AHS>()[0].comand_state=="Master") { master_index=i; } if ( part_list[i].FindModulesImplementing<AHS>()[0].comand_state=="Master" || part_list[i].FindModulesImplementing<AHS>()[0].comand_state=="Slave" ) { controlable_no += part_list[i].FindModulesImplementing<AHS>()[0].max_engines; } } if (part_list[i].FindModulesImplementing<RCSEngineTranslation>().Count>0) { if (part_list[i].FindModulesImplementing<RCSEngineTranslation>()[0].state_string!="None") found_engines++; } } if (master_index!=-1) { part_list[master_index].FindModulesImplementing<AHS>()[0].controlable_engines = controlable_no; part_list[master_index].FindModulesImplementing<AHS>()[0].engine_usage = found_engines+"/"+controlable_no; List<int> slaves = part_list[master_index].FindModulesImplementing<AHS>()[0].slave_indices; for (i=0; i<slaves.Count; i++) { part_list[slaves[i]].FindModulesImplementing<AHS>()[0].engine_usage = found_engines+"/"+controlable_no; } } } //Search for working slaves and update the master's slave list public void CheckSlaveState () { int master_index = -1; int i; //vessel will = null in the editor so we must cycle through parts list another way if it is not set List <Part> part_list; if (this.vessel!=null) { part_list = this.vessel.Parts; } else { part_list = new List<Part>(); Part start_part = this.part; while (start_part.parent!=null) start_part=start_part.parent; AddPartToList(start_part,part_list); } for (i=0; i<part_list.Count; i++) { if (part_list[i].FindModulesImplementing<AHS>().Count>0) { //All inactive states must be checked before asigning master slave states if (!part_list[i].FindModulesImplementing<AHS>()[0].ahs_on) { part_list[i].FindModulesImplementing<AHS>()[0].comand_state = "Off"; } else if ( part_list[i].FindModulesImplementing<AHS>()[0].comand_state!="Crashed" ) { if (master_index==-1) { master_index=i; part_list[master_index].FindModulesImplementing<AHS>()[0].comand_state = "Master"; part_list[master_index].FindModulesImplementing<AHS>()[0].slave_indices.Clear(); } else { part_list[i].FindModulesImplementing<AHS>()[0].comand_state = "Slave"; part_list[master_index].FindModulesImplementing<AHS>()[0].slave_indices.Add(i); } } } } } //Find active gravity sensor and then set gravity to a useable value public void CheckGravSensor () { this.FindActiveSensor(); }//endof void CheckGravSensor () //Updates grav readout and sets active state + finds an active sensor //You can force sensor finding by setting grav_sensor_index to -1 public void FindActiveSensor () { if (no_parts_in_last_check!=this.vessel.parts.Count) {//if parts have change then the index is no longer valid this.grav_sensor_index = -1; this.grav_sensor_active = false; } if ( this.grav_sensor_index != -1 ) {//if grav sensor is valid check it is active and update readout this.ReadGravSensor(); } //We dont need to search again if we have an active sensor and parts have not changed if ( no_parts_in_last_check==this.vessel.parts.Count && this.grav_sensor_active==true ) return; this.grav_sensor_index = -1; this.grav_sensor_active = false; int i; for (i=0; i<this.vessel.parts.Count; i++) { if (this.vessel.parts[i].name=="sensorGravimeter") { if (this.vessel.parts[i].FindModulesImplementing<ModuleEnviroSensor>().Count>0) { if (this.grav_sensor_index == -1) { this.grav_sensor_index=i; } this.ReadGravSensor(); if (this.grav_sensor_active) { this.grav_sensor_index = i; break; } } } } }//endof void FindActiveSensor () public void ReadGravSensor () { if (this.grav_sensor_index==-1) { this.grav_readout = this.gravity_state = "No Sonsor Found"; this.gravity = 9.82f; this.grav_sensor_active = false; return; } float grav = float.NaN; try { ModuleEnviroSensor sensor = this.vessel.parts[this.grav_sensor_index].FindModulesImplementing<ModuleEnviroSensor>()[0]; if (sensor.readoutInfo.Length>6) { grav = float.Parse(sensor.readoutInfo.Substring(0,sensor.readoutInfo.Length-6)); if (grav != float.NaN) { //duplicate of the grav sensors methode of getting gravity but with out the lose of precision from string convertion grav = (float)FlightGlobals.getGeeForceAtPosition( base.transform.position ).magnitude; } } } catch { } if (grav==float.NaN || float.IsInfinity(grav) || grav.ToString()=="NaN") { this.gravity_state = this.grav_readout = "Senneor Read Error"; this.gravity = 9.82f; this.grav_sensor_active = false; } else { this.gravity_state = this.grav_readout = grav.ToString(); this.gravity = grav; this.grav_sensor_active = true; } } //part list builder. much better to use vessle.parts but its not avalible in the editor public void AddPartToList ( Part p_, List<Part> list_ ) { list_.Add(p_); int i; for (i=0; i<p_.children.Count; i++) { this.AddPartToList(p_.children[i],list_); } } public override void OnLoad (ConfigNode node) { base.OnLoad(node); this.HoverDisplayMode(); this.SetHoverGUI(); } //place for adding right click info to parts in the editor ? public override string GetInfo () { string result = ""; result += "Energy Usage: "+this.power_consumption.ToString()+"/sec\n"; result += "Heat Production: "+this.heat_production.ToString()+"/sec\n"; result += "Controlable Engines: "+this.max_engines.ToString()+"/sec\n"; return base.GetInfo ()+result; } }//endof public class AHS : PartModule }//endof namespace AHS
-
Yeah i use ascent and descent rockets with hot key toggles. The Im_A_Cupcake_Wanabe plugin dose a fair job of stabilizing my craft and then i have a few different methods for exact control. All involve the SAS being locked pointing straight up. Then i ether use RCS or side ways rockets hotkeyed into the keypad for positioning. I use both systems to adjust your crafts angle without changing its SAS lock so that normal SAS dose most of the hard work. I can happily dock a full half orange tank now but I dont have much vertical build experience yet and have a nasty habit of designing rockets that cant be built when you have the constructor attached to a part or even worse suffer from unexpected results due to primary / secondary docking. So i revert back to ground vehicles for the moment with the Small But Hard. 3.35T to orbit = a Hard score of 16.75 That should be easy to beat but taking the top spot isnt too hard just yet Ill develop the Pinks Ascent Stabilizing System (PNK ASS for short) a fair bit more over the next few weeks and probably start a thread to release it properly. My plan is to enable some more tweakables so that it can work with different engine types and handle variable gravity. It could be very handy for off world Colony construction. Loads of problems to fix and things to understand before itl be truly ready though but thought it might help get some more entry's. Sure theres also crane plugin that would make this a lot easier.
-
Awesome i look forward to you video. May your flight go off with no unexpected fire. Im still trying to build a supper hard no strut version of my 1st rocket. Iv been having a play with flying constructors some more too. No problem with landing on the VAB but without a joystick docking is still a but too tricky. Its making me think i should dust off my copy of MonoDev and build a quick addon. With tweakables it shouldn't be too hard to make a zero climb jet stabilization autopilot. As in you get to keep your throttle at full and the AP just adjusts the tweakable thrust level to balance the force of gravity and then you use hot keys with 2 other sets of rockets for adjusting your vertical speed. After removing the complexity of watching vertical speed and adjusting throttle using keys whilst watching thrust levels from the jets i might just have enough skill left to complete a dock.
-
My Epic Fail (bump) Close but no cigar. This should have put 50-60 T to orbit (250-300 points) as a Hard Entry LOL at not checking the spacing sooner. This is a complete rebuild as the central beam of the roller is too low to support legs on the beams of the rockets mobile tower hence the reason why i ended up using wheals under the rocket parts. This dose bring up a valid scoring concern though. It would seam to me that there's not much point in doing anything other than launching the largest payload. Returning from the moon should be worth a lot more than a large payload launch. The only thing i can think of though would be multiples of the payload points as achievements. Hummm or even easier would be to remove the 5 points per tone multiplier. I do have one more thought for the night. A Supper Hard version where your not aloud to use struts.
-
Humm yeah LoL the whole problem is due to a stupid diagram a wood work teacher drew about 20 years ago when he was trying to get the class to build some planes. The silly diagram showed how the lift from each wing was canceled out by gravity but when it was in a roll the flatter wing was meant to have a stronger effect against gravity and thus level the plane out. Oh how i laugh now. KSP is very clear in the VAB about where the center of mass is and the center of lift/thrust so i should have been able to forget this stupid lesson by now and move on. The plane thing is very simple. Triangles like to point at the direction the wind comes from. Enough said. On the construction side. I can now shift 4 large orange tanks from the end of the runway on to the pad in under 2 mins. So i should be ready to present my hard entry by the end of the weekend.
-
Is anyone else prepared to share some testing experience ? Iv been testing a cupcake style lifter too. I think im suffering from some bad physics. Im sure tilting the engines out like that should result in a stable hover that dose not need SAS to keep it pointed at the sky but it dose not seem to work. Its very odd and confusing as tilted wings on a plane dose result in a self stabilizing craft. It might just have been that i had the gimbals enabled on the 1st few flights. There seams to be a problem with gimballed engines above the center of balance (they gimbal the wrong way). Anyways iv yet to manage to safely land an orange tank anywhere let alone dock it so im not sure i have enough skill to do it this way. My Supper Roller seams to be showing a lot more promise. A warning to anyone trying to follow this line. The craft is aligned to the top of the pad so it fell 5M when physics kicked in ! Im taking its ability to withstand this as a very good sign It can just clear the pad and drive away (avoiding the silly bumps) safely carrying an orange tank (including the drop at the start). This as yet unusable transporter already ways 27T. Iv still got a long way to go before i have a working version for Hard but im sure il get there soon.
-
Thanks I thought it was cool too curious as to what ? Yes there are two sets of decouplers with jr docking ports and 2X fuel pipes per booster. The images are a bit low resolution even for the originals + i have the textures so low you can never spot what way a fuel pipe is connected. A pipe goes from the booster into the port that is a part of it and another pipe gose from the port on the main rocket over a decoupler and into the upper tank. There is some funny transfer hear as the skipper finds the bottom tank of the boosters to be the most distant while the booster engines use the top tank of the booster (funny but expected). The bigger problem is if you connect with the lower of the docking ports 1st. I had this happen on testing and it results in failure to cross feed. This seams a bit odd to me and could well be considered a bug if i could repeat it but im well aware of the strange results of primary and secondary docking ports. As for alignment, well this is where the T800's come in handy. Both the main tank and the boosters have lot of good markings to do alignment with and both the ports are aligned with a horizontal mark. The other thing about this rocket is it was easy to build in one part and test before trying to do any ground docking. Im not sure if its just me and my low terrain detail levels but .23 seams to have some very nasty invisible bumps on the pad now, so docking there isnt easy. Saying that it still seams easier than any of my attempts to recreate Cupcake's awesomeness.
-
To Day I Build A Small Rocket Lets Get the ball Rolling hear with my originally named Small Rocket. Hummmm so how do we score this. The rocket was built using stock only and constructed fully fulled but used 3 transporters 4 if you consider that the main section has 2 separate transporters after decoupling. Payload Skipper 4 Dry t800 0.5 X 4 = 2 MK1 Pod 0.84 Rockomax Adapter 0.1 MK16 Chute 0.1 Stack Decoupler 0.05 Gives a Total of 7.09 or 35.45 points 25 pts for Minmus flyby = 60.45 20 pts for Munar flyby = 80.45
-
PNK Enginering presents the 0.96 Shuttle Buss (Beta) [usable failure]. Note: the engineers don't suggest flying this with passengers as they don't have an ejection system ! The MK9 was tested with an 18T 1/2 orange fuel tank payload. It made a decaying 150K - 65K orbit. The MK9 shuttle is around 280 parts and the full launch system is about 540 parts. most certainly enjoying that .23 physics update. The following imgur images come with the most basic of flight instructions that should get you into orbit if your a very good pilot.
-
This is my 0.86 EJ style stock only shuttle. For a number of reasons it was scrapped before jeb snuck in and strapped some boosters to it. My 0.9 Version is still under construction but i have high hopes. The 1st step in my Shuttle designs is always a Zero Zero Ejection System test. Sure ill be back soon with some high quality successful payload delivery images
-
Start EVA with grabbed hands?
mpink replied to Zwer.ch's topic in KSP1 Gameplay Questions and Tutorials
Iv seen 2 things that cause the problem you mention. 1) Blocking the hatch with another part. This can cause your kerbal to be shot off into space as it trys its hardest not to share the same space as another object. 2) If your ship is under acceleration/deceleration from lets say atmospheric drag then the kerbal can get ripped from the ladder. The best thing to do is a launch pad EVA to test that your hatch isnt blocked and is working. Do you have the same problem with all capsules ? -
Right Clicking does not open object.
mpink replied to Darkeldar's topic in KSP1 Gameplay Questions and Tutorials
Hummm yeah i had the same problem. I think its mostly due to my supper laggy comp. I found with the new update that i now have to tap the right mouse button. As in not push it down and wait a moment and then release but just use a very rapid single tap. I think its due to the new camera rotation. You see if you can get the popup open it will now remain open when you use the right button to rotate the camera. I doubt it has anything to do with the speed of the click but more to do with moving the mouse after you have pressed it down and before you have let it go. This is why i blame it on my laggy comp as i think my mouse must remain completely still for one full game frame and at times on my computer that can take a while. It would be good to have a controllable deadzone in the settings so you could change the number of pixels the mouse needs to move to trigger rotation mode but iv no clue where we would have to write that to get someones attention. Id think its probably just a getting the hang of it thing and after a while you will be fine with it. I know im more than happy to be able to rotate now without loosing my selected part. LOL it is very very frightening though on your 1st mission trying to get EVE science before you hit the atmosphere and get dragged of your craft. -
BSC: Kerbal X - We have a winner!
mpink replied to Xeldrak's topic in KSP1 Challenges & Mission ideas
Blaze Fallow's craft is not Stock -
BSC: Kerbal X - We have a winner!
mpink replied to Xeldrak's topic in KSP1 Challenges & Mission ideas
Lol thats a lot of craft to test fly. The worst thing is that i just cant stop building. I finally managed to get my fuel load down to 6120 from the Kerbal X's 8286 but i dont think its a very good training craft (Very unforgiving) and its very definitely to late to change my entry. It has six asparagus boosters + six asparagus droptanks and only uses LV 30's in the main drive section I think the main thing about the Kerbal X is the payload was intended to be a joke and should be replaced easily by a new player and so im struggling to decide how to judge all the craft. The launcher though is still outstanding and beats most of the entry's iv seen on both style and performance. Thanks very much Xeldrak you have done a great job and kept my very entertained. -
BSC: Kerbal X - We have a winner!
mpink replied to Xeldrak's topic in KSP1 Challenges & Mission ideas
Yeah its an odd craft. It starts with a very low TWR (1.1 ish). I am under the impression that we should be trying to maintain terminal velocity for most the most efficient launch so dose this not mean we should be pushing for max G force at around 15K M ? Looking at my images it only makes 4.5 G so its not too crazy and at 32K M when it dumps its main drive section it was going 2K M/s so there is no insane drag of aerodynamic effects. Its designed for direct ascent so i dont think it dose a very good job as an orbital drive section where you would want lower G over a longer time at a higher altitude. I think my main concerns come from useless mass. Adding 0.4 mass to each LV 30 just bugs me. I should have used t-400's with fuel lines and jettison the center LV 45 when it gets lighter (runs out of fuel). Doing so results in dropping all the tanks before doing any turning witch is a bonus but i wanted to use the structural fuselage as it demonstrates a different cross fuel feeding method. Dose anyone know if the craft suffers from more drag as the drive sections are not node connected to the drop tanks ? Im guessing that it dose not and that KSP isnt that complex with its drag yet. Doing further testing iv decided to change my craft to update the description adding. I found these changes resulted the drive section reaching around 3K M/s at 45K M. Although landing 3 kerbals using just an LV-909 is somewhat tricky due to low TWR it had more than enough fuel to get me there and back. With the original craft using 3.25 orange tanks its coming in at one of the lightest 3 kerbal craft so far Im very much looking forward to test flying all the craft before voting. Theres some very interesting designs out there. Iv not tried any of them yet as entry's often get changed and i dont want to vote on an old version of a craft. Im most looking forward to reading all the descriptions though. -
BSC: Kerbal X - We have a winner!
mpink replied to Xeldrak's topic in KSP1 Challenges & Mission ideas
The Mun Xplorer is a direct ascent Mun orbiter designed to be used with a new game. The craft description should get a new player into a near mun orbit and give them enough fuel to explore a little and get home. Im sure the rocket could support a more complex landing craft but we are only going for a look right + kerbal spirit would be to strap some legs to this and we all know how that works out ! There are some more images in the Dir. Can anyone tell me what sort of staging this is ? Im happy to call it asparagus but im not sure thats right.