Jump to content

[0.23] Im a Cupcake Wannabe (Advanced Hover System)


mpink

Recommended Posts

What is the difference between Active Hover and Fixed?

Fixed hover Sets the thrust output = to the force of gravity So if you tilt the craft and point the thrust in a direction not exactly opposite to gravity then you start to fall out of the sky.

Active Hover increases the thrust as you tilt in an attempt to maintain your hover So will use 100% thrust if you are pointing at the horizon.

The active thrust seams to be far superior to fixed thrust but i was not convinced it would work so well at the time of programming so kept the fixed version in too.

Both systems will use variable gravity if an active grav sensor is found.

Im still fixing some nasty silly bugs. There was a problem with RCS Left tracking the up key in one part :huh: and up and down may be the wrong way around. Ill fix up the last small problems and do some more testing. With luck V0.41 will be released in a few hours and ill start on a tutorial video or 2.

Link to comment
Share on other sites

All links have been updated to V0.41

And iv been working on some basic tutorial videos.

Basic Hover Setup

That all might be a lot more convincing if i were a better pilot ;)

Was stuck on a train for a few hours yesterday so i managed to sketch out and do some basic math for my kethane colony and look forward to giving this a true test.

It will probably take me a week or 2 to get the videos made but they should be a lot more interesting from a showcase point of view.

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.

//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.magnitu de && 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.magni tude && 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

Link to comment
Share on other sites

Good stuff mpink but maybe I have missed something:

- does Kerbals get back to mainframe era ? 1.5 and 6 t for these devices ? Far too much for just a flight assistant IMHO

heat production 50 & 100/s resp, what does they do ??? Is there any KSP game included inside ? Or Have they been designed and made by Acer ?

- the "small" one works strange, activated by default on launch, suppose to have nothing to do (all engines off), it overheat and crash, and it has done nothing at all

- a gravity sensor may be included inside as it is needed,

- the idea of creating a subassembly of parts is nice (also because it's the 1st time I see something like this)

EDIT: no cooling device included, how are we suppose to cool it ? Going a bit underwater ? Or it has been made to work in cold deep space (where it is useless) ?

I suggest kindda "same player shoot again" if you know what I mean ;)

It's not today I'll be able to fly like cupcake... :huh:

Edited by Justin Kerbice
Link to comment
Share on other sites

Good stuff mpink but maybe I have missed something:

- does Kerbals get back to mainframe era ? 1.5 and 6 t for these devices ? Far too much for just a flight assistant IMHO

heat production 50 & 100/s resp, what does they do ??? Is there any KSP game included inside ? Or Have they been designed and made by Acer ?

Yeah its my attempt at balancing and so dosnt have much of a place in real life.

The mass of the small AHS is based on the Advanced Stabilizer (0.5T with a 9MS crash tolerance).

As the Small AHS has a 30MS tolerance it seams fair to be 1.5T ?

Im not claiming that the computer system is heavy just the container.

Following this though the Large AHS should probably only be around 1.4T as the larger default control system is only 0.2T but this seams a bit unfair as it has a 60/MS tolerance with 6 node attachments and crossfead ability.

- the "small" one works strange, activated by default on launch, suppose to have nothing to do (all engines off), it overheat and crash, and it has done nothing at all

Not so true but i see your point. It only appears in the stack icons so you can see its state and get a warning of its heat. Use the tweakables to turn it on/off.

Even if the engines are off it still dose all the math and adjusts the engines thrust trying to control them. This is a bug and it should ignore engines that are off. Even worse than making heat is that it uses engine slots for engines that are off :(. This is a pain in the bum when your transporting 1 or 2 small VTOL construction craft using a larger VTOL Transport.

Im not sure if there is any point in using heat yet. To reduce heat you must place parts onto the Part producing heat and these connected parts absorb heat and convert it into light dissipating it.

Its so easy to remove heat i dont see much point in having it at all + theres probably no reason for such a large amount of heat production (I must look into this).

In my defense of heavy/hot computer systems though have a look at the Apollo onboard computer.

250px-AGC_user_interface.jpg

LOLs at the 70 lb (32 kg) large calculator using 55W. Im not sure exactly what it could do or how fast it was but doing flyby wire with that generation of computing would have been messy.

The SAS system could well be analog as autopilot's were around long before computers and are not very complicated.

- a gravity sensor may be included inside as it is needed,

Yeah true i was just trying to link systems to provide a reason for adding sensors to your craft.

I think in real life i would want at least 3 or more gravity and accelerometer sensors but yeah to make things easier to use i should include them in the AHS.

- the idea of creating a subassembly of parts is nice (also because it's the 1st time I see something like this)

Thanks :) it also has the advantage of not loading any extra models or textures so shouldn't waste any memory (Theres often talk of a memory limit when using lots and lots of plugins)

EDIT: no cooling device included, how are we suppose to cool it ? Going a bit underwater ? Or it has been made to work in cold deep space (where it is useless) ?

To reduce heat you must place parts onto the Part producing heat and these connected parts absorb heat and convert it into light dissipating it.

Iv been using it to build my space stations without using RCS thrusters/tanks and iv been building a small 70T kethane mine on minmus.

I suggest kindda "same player shoot again" if you know what I mean ;)

It's not today I'll be able to fly like cupcake... :huh:

The plugin has become stupidly complex and should probably be broken into 2 different systems.

After linking vertical speed control into the RCS forward/backward keys i just had to add a full RCS style control and they are most defiantly 2 different systems/plugins and should be split.

So what im thinking is ill try to integrate engines into the default RCS systems and remove the complicated direction setup for the engines.

Then i will add a simple on/off tweak for setting if an engine should be used to Hover.

My biggest concern now though is not breaking my test colony :) but then i could just hack my save file and fix any compatibility problems.

Javascript is disabled. View full album

So far the colony consist of 7 parts. One of them is my low grav constructor better seen on the 2nd image attached to the stations core.

It has been painful to get this far but the more it hurts me the faster ill get around to fixing it.

Link to comment
Share on other sites

Yeah its my attempt at balancing and so dosnt have much of a place in real life.

The mass of the small AHS is based on the Advanced Stabilizer (0.5T with a 9MS crash tolerance).

As the Small AHS has a 30MS tolerance it seams fair to be 1.5T ?

Im not claiming that the computer system is heavy just the container.

Following this though the Large AHS should probably only be around 1.4T as the larger default control system is only 0.2T but this seams a bit unfair as it has a 60/MS tolerance with 6 node attachments and crossfead ability.

Not so true but i see your point. It only appears in the stack icons so you can see its state and get a warning of its heat. Use the tweakables to turn it on/off.

Even if the engines are off it still dose all the math and adjusts the engines thrust trying to control them. This is a bug and it should ignore engines that are off. Even worse than making heat is that it uses engine slots for engines that are off :(. This is a pain in the bum when your transporting 1 or 2 small VTOL construction craft using a larger VTOL Transport.

Im not sure if there is any point in using heat yet. To reduce heat you must place parts onto the Part producing heat and these connected parts absorb heat and convert it into light dissipating it.

Its so easy to remove heat i dont see much point in having it at all + theres probably no reason for such a large amount of heat production (I must look into this).

In my defense of heavy/hot computer systems though have a look at the Apollo onboard computer.

http://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/AGC_user_interface.jpg/250px-AGC_user_interface.jpg

LOLs at the 70 lb (32 kg) large calculator using 55W. Im not sure exactly what it could do or how fast it was but doing flyby wire with that generation of computing would have been messy.

The SAS system could well be analog as autopilot's were around long before computers and are not very complicated.

Yeah true i was just trying to link systems to provide a reason for adding sensors to your craft.

I think in real life i would want at least 3 or more gravity and accelerometer sensors but yeah to make things easier to use i should include them in the AHS.

Thanks :) it also has the advantage of not loading any extra models or textures so shouldn't waste any memory (Theres often talk of a memory limit when using lots and lots of plugins)

To reduce heat you must place parts onto the Part producing heat and these connected parts absorb heat and convert it into light dissipating it.

Iv been using it to build my space stations without using RCS thrusters/tanks and iv been building a small 70T kethane mine on minmus.

The plugin has become stupidly complex and should probably be broken into 2 different systems.

After linking vertical speed control into the RCS forward/backward keys i just had to add a full RCS style control and they are most defiantly 2 different systems/plugins and should be split.

So what im thinking is ill try to integrate engines into the default RCS systems and remove the complicated direction setup for the engines.

Then i will add a simple on/off tweak for setting if an engine should be used to Hover.

My biggest concern now though is not breaking my test colony :) but then i could just hack my save file and fix any compatibility problems.

http://imgur.com/a//Yjfpb

So far the colony consist of 7 parts. One of them is my low grav constructor better seen on the 2nd image attached to the stations core.

It has been painful to get this far but the more it hurts me the faster ill get around to fixing it.

geez how many mods are you running? i'm running 25 mods but i lag if i have a rocket with over 250 parts

Link to comment
Share on other sites

geez how many mods are you running? i'm running 25 mods but i lag if i have a rocket with over 250 parts

Lol yeah only Kethane, Engineer and AHS myself. Iv tried to stay away from mods to keep my lag under control.

Iv bumped into the mem limit in other threads before http://forum.kerbalspaceprogram.com/threads/43600-Allowing-KSP-to-use-more-than-4gb-of-memory

As for lag well..... iv only just grabbed myself a gfx card (was using an inbuilt) so im used to it and even with the card my comp cant seam to get the physics over 0.3X-0.4X

My main lunch system is running around 700 parts and drops down to 0.25X at the moment but compered to what it was before the 0.23 physics update it feels very smooth to me.

In the older versions i had to reduce the physics frames and could not build over 200 parts without explosions.

Iv got to try videoing a launch of the 5 orange tank Fuel Transport System. Its a true monster :).

Link to comment
Share on other sites

Yeah its my attempt at balancing and so dosnt have much of a place in real life.

The mass of the small AHS is based on the Advanced Stabilizer (0.5T with a 9MS crash tolerance).

As the Small AHS has a 30MS tolerance it seams fair to be 1.5T ?

Im not claiming that the computer system is heavy just the container.

Following this though the Large AHS should probably only be around 1.4T as the larger default control system is only 0.2T but this seams a bit unfair as it has a 60/MS tolerance with 6 node attachments and crossfead ability.

ok

But IMHO, such mass for an allegedly VTOL assistant... it's a one way ticket to trashcan. Kerbals are smart and have strong and lightweight material, as well as "super nano technology" :).

Not so true but i see your point. It only appears in the stack icons so you can see its state and get a warning of its heat. Use the tweakables to turn it on/off.

Even if the engines are off it still dose all the math and adjusts the engines thrust trying to control them. This is a bug and it should ignore engines that are off. Even worse than making heat is that it uses engine slots for engines that are off :(. This is a pain in the bum when your transporting 1 or 2 small VTOL construction craft using a larger VTOL Transport.

Im not sure if there is any point in using heat yet. To reduce heat you must place parts onto the Part producing heat and these connected parts absorb heat and convert it into light dissipating it.

Its so easy to remove heat i dont see much point in having it at all + theres probably no reason for such a large amount of heat production (I must look into this).

Yes for the icon but it's confusing, I saw "crashed" so I think: "it's done for good, go back to VAB and try again." I didn't notice first a right kick do the trick.

For the heat dissipation, I didn't understand at all, you wrote this twice but twice is something I can't decypher. heat -> light ? An engine ? A light ? If you produce something and there is no consumer, there is a balance issue (kindda khetane without kethane powered engine).

In my defense of heavy/hot computer systems though have a look at the Apollo onboard computer.

LOLs at the 70 lb (32 kg) large calculator using 55W. Im not sure exactly what it could do or how fast it was but doing flyby wire with that generation of computing would have been messy.

The SAS system could well be analog as autopilot's were around long before computers and are not very complicated.

mmm... a 60s computer is not a good reference. All military planes are full of calculators which don't weight tons AFAIK?

Yeah true

i was just trying to link systems to provide a reason for adding sensors to your craft.

I think in real life i would want at least 3 or more gravity and accelerometer sensors but yeah to make things easier to use i should include them in the AHS.

Thanks :) it also has the advantage of not loading any extra models or textures so shouldn't waste any memory (Theres often talk of a memory limit when using lots and lots of plugins)

ok.

I think we don't know at all how memory is used here, I guess texture can be fully shared, but using parts means create new instance of them in mem and I'm pretty sure there is some memory leaks here or there (in the chain: KSP-Unity-libraries-OSlib-OSkernel-drivers)

I know I have quite a lot of criticisms so I can offer you to create new models like the subassemblies or other look.

To reduce heat you must place parts onto the Part producing heat and these connected parts absorb heat and convert it into light dissipating it.

Iv been using it to build my space stations without using RCS thrusters/tanks and iv been building a small 70T kethane mine on minmus.

see above.

The plugin has become stupidly complex and should probably be broken into 2 different systems.

After linking vertical speed control into the RCS forward/backward keys i just had to add a full RCS style control and they are most defiantly 2 different systems/plugins and should be split.

So what im thinking is ill try to integrate engines into the default RCS systems and remove the complicated direction setup for the engines.

Then i will add a simple on/off tweak for setting if an engine should be used to Hover.

mmm... ok

From my point of view, as I think of such VTOL control system, we have to:

- identify/measure speeds (vertical, lateral, horizontal) as Mechjeb dock autopilot do

- know a way to "nullify" a given speed

- do it on command (hovering at current altitude, be steady where we are now, stop moving forward, ...)

My biggest concern now though is not breaking my test colony :) but then i could just hack my save file and fix any compatibility problems.

So far the colony consist of 7 parts. One of them is my low grav constructor better seen on the 2nd image attached to the stations core.

It has been painful to get this far but the more it hurts me the faster ill get around to fixing it.

Pity you :).

I strongly advise you to have:

- one KSP install you play with, with fully tested mods

- one KSP install to play with your dev mod and also test unknow mods (dev testbed)

- one KSP clean/stock install to test your incoming release (to be sure mostly to don't forget to include the tiny little useful part of mod XYZ)

Link to comment
Share on other sites

You might look at KSPI or talk to the developer Fractal_UK about heat production and dissipation. His mod does a lot of that.

Ye gods, NO! I tried adding KSPI to an existing game and all my stuff died because it suddenly had to deal with heat it had never been designed for :)

Link to comment
Share on other sites

Im not sure exactly what it could do or how fast it was but doing flyby wire with that generation of computing would have been messy.

Funny that you should say that, as the LEM is pretty much the world's first fly-by-wire craft. Or technically the LLRV was, but that boils down to the same thing. Do not mistake old computers for computers that are useless. It is amazing how much you can achieve with even the smallest amount of calculative power - if you are creative and efficient.

Today, with incredible amounts of cheap and efficient calculations, programs are generally written lazily. This sometimes leads to people believing that you actually need that much power to achieve those tasks.

Link to comment
Share on other sites

KSPI heat is easy to deal with..all you have to do is slap some raditors to your ship as part of the design. The mod even gives you a nice UI in assembly now so you can see if your ship is going to overheat...or not.

All of which does absolutely zero good for anything you might already have built and flying in space, which was my point. When you install KSPI into an existing game, its heat applies to all existing ships, which of course have no defense against it because you launched them before you installed KSPI. So everything you have that relies on solar panels will surely die and most other ships will have major problems. It's not at all pretty.

The only way around this is to create a totally separate game installation for KSPI, keeping it entirely out of any ongoing games you have. While this is OK for something as major and complex as KSPI, it would really suck for AHS, which is just a simple nice-to-have part you'd like to incorporate into your existing save. Hence, I strongly recommend against putting KSPI-type heat on AHS.

Link to comment
Share on other sites

hmmm I don't really understand what this mod does.im tying to make a craft that will hover but it doesn't really feel like hovering.tried different designs and didn't seem to work like in some of the vids here.a tutorial for dummies on how to make hover crafts would be appreciated.

EDIT: ok I just built something that manages to hover....this mod needs a lot of experimention until someone can manage to understand how it works.anyway it fun now that I figured it out!thanks

Edited by techstepman
Link to comment
Share on other sites

  • 3 weeks later...

This mod would be a great help in dragging the larger asteroids around. The ability to use big rocket engines as RCS thrusters might make it possible to reorient a Size E without having to undock and fly the ship to a different side of it. I hope this gets updated someday ;)

Link to comment
Share on other sites

  • 3 weeks later...

Hey mate,

RCS module seems to be not working for me in 0.23.5, none of the engines is showing the options for linking them up with the master. I tried the small and big versions of your part, with jet engines / stock rocket motors and others like the sabre engines form B9. Will there be an update eventually or am I the only one having problems with the current game version?

best regards

Edit: Ok, I found some engines that somehow work with your mod, but none of the stock engines will, neither do B9 or Nova Punch... Strangely its some of the Interstellar Mod that actually work :confused:... Any idea what I could do to get the rest of the engines working? Even if its just the stock engines, any help appreciated!

Edited by Haifi
Link to comment
Share on other sites

  • 3 weeks later...

Is this abandoned? I loaded it and tried to use it but no luck. Looked into the files and there were gross misspellings present, no offense author but I am assuming that English isn't your native tongue. I went through and corrcted the misspellings in the files and dll but this still did not help the bug issues.

I am dying for a freaking auto hover such as this and don't like star wars lasors shooting everywhere just to hover. I would prefer engine power.

Link to comment
Share on other sites

Hi Albert, as you see i tried to ask something myself but to no avail. After fiddling with the code for a while i found what the problem for me was. Im using the hotrockets fx mod and it changes the Module ModuleEngines into ModuleEnginesFX, thats why the call the hover mod uses did not work. After modifying the .cs and building the .dll i got a lot of the engines running with AHS. So if youre using some FX mods check if they use modulemanager to replace the ModuleEngines in your engineparts. Besides that the mod works for now, but I think it would be good if a programmer had a look at it, to make it call not only for one or the other module but for both. Im sadly not good enough yet in C# to modify it.

Best regards, hope this helps

Link to comment
Share on other sites

Well, its code has a "do what you want with it" license, so ill be sure to keep the source stowed away safely. If anyone is interested to get the source after Spaceport went down, pm and ill send you a copy. Maybe there is someone able and interested enough to revive it at a later date.

Link to comment
Share on other sites

  • 2 months later...
This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...