Alexustas / Props-requests

6 stars 1 forks source link

the first newbie steps in Lua #41

Open Alexustas opened 8 years ago

Alexustas commented 8 years ago

I'll post here some of my learning scripts, which may be useful in the future

the very first script

function aset_getNumber(value,number) 
    if type(value) == "number" and number ~= 0 then 
--      print ("value and number - ok!") 
        local AbsValue = math.abs(value)
        local aInt,aFact = math.modf(AbsValue)
        local aIntLen = string.len(aInt)
        local aFactLen = string.len(aFact)
--      print (aInt,"-",aIntLen," | ", aFact,"-", aFactLen)
            if number>0 then
                RetNumber = tonumber((string.sub(aInt,aIntLen-number+1,aIntLen-number+1)))
            else 
                RetNumber = tonumber(string.sub(aFact,2+math.abs(number),2+math.abs(number)))
            end
    else 
        RetNumber = 0
--      print ("NOT OK ((") 
    end
        if RetNumber==nil then 
            RetNumber = 0 
--          print ("Not good, but OK")
        end
--  print (RetNumber)
    return RetNumber
end

--
-- tests
--
myVariable = 9871234.56 
print (aset_getNumber(myVariable,5))

->7

print (aset_getNumber(myVariable,1))

->4

print (aset_getNumber(myVariable,-1))

->5

this script returns a specified digit of a given number

you need to move from right to left from ".", if you want to get digit ofthe left (integer) part of the variable and use a positive number. for the fractional part, you have to use negative numbers and move from left to right from "." So if you need to get the third digit of the "13867" then you need to use 'aset_getNumber(myVariable,3)' and function returns "8". For second digit in the fractional part of the "149.247" you need to use 'aset_getNumber(myVariable,-2)' and function returns "4". I plan to use this function for the "mechanical odometer-style indicators" using 'ROTATION' module with "speed" option

Alexustas commented 8 years ago

second script

This script truncates given string to the specified length

function aset_StringLimiter(String,Len)
    if String ~= nil and math.floor(Len) == math.ceil(Len) then 
        return string.sub(String,1,Len)
        else return "err"
    end
end

--
-- tests
--

print (aset_StringLimiter("asdfqwer",5))
->asdfq

print (aset_StringLimiter("asdfqwer",2))
->as

print (aset_StringLimiter("asdfqwer",22))
->asdfqwer

This script can be useful if on a small indicator displayed a some messages, and the message may suddenly be too long, like "Untitled Space Craft"...

Alexustas commented 8 years ago

third script

very basic variable formatter, mainly for training

function aset_BasicVarFormat(Var,Len,DecVal,Mult,Pref)
    local formatStr = tostring("%".. Len.."." ..DecVal.."f")
    return tostring((string.format(formatStr, Var*Mult))..Pref)
end

--
-- tests
--

Variable = -52523.236
print (aset_BasicVarFormat(Variable,15,1,1," km"))

->       -52523.2 km

Variable = -52523.236
print (aset_BasicVarFormat(Variable,-15,2,10,"kg"))

->-525232.36     kg

syntax: aset_BasicVarFormat(Variable,[_full_lengthof variable_],[number of fractional digits],[multiplier],["suffix"]

If the length is positive, then the alignment of the text produced by the right side, otherwise by left side

MOARdV commented 8 years ago

Very cool!

BTW - once you're using Lua in MAS / KSP, there is fc.LogMessage(message) that will let you write strings to the KSP.log. It does not support C# formatting (not yet, anyway), but you can use Lua's string library.

Alexustas commented 8 years ago

fourth script

This script converts the latitude and longitude entered by the user in a user-friendly format, in to degrees, for further processing in the game. I believe that sooner or later we will be able to freely enter any text, using props. even now it is possible to enter numbers. So this script can be useful for the implementation of a control terminal, such as CDU

fds-b737ng-pro-mx-cdu-2

script

-- string to number

function aset_CoordStringToDecNumber(CoordInput)
    local dir = 1
    local ValLen = string.len(CoordInput)
        if ValLen >= 6 and ValLen <= 8 then
            local DirSym = (string.sub(CoordInput, ValLen, ValLen)) -- extract the last symbol of given string
            if DirSym == "N" or DirSym == "S" or DirSym == "W" or DirSym == "E" then 
                local Result = tonumber((string.sub(CoordInput, 1, ValLen-5))) + (tonumber((string.sub(CoordInput, ValLen-4, ValLen-3))))/60 + (tonumber((string.sub(CoordInput, ValLen-2, ValLen-1))))/3600    
                if DirSym == "N" and Result <= 90 or DirSym == "S" and Result <= 90 or (DirSym == "W" and Result <= 180) or (DirSym == "E" and Result <= 180) then
                    if DirSym == "S" or DirSym == "W" then dir = -1 end 
                    return Result*dir
                else 
                    print ("Invalid input.\nLatitude should be less than 90°\nLongitude should be less than 180°") 
                    return 0
                end
            else 
                print ("Invalid Direction! expected 'N','S','W' or 'E'") 
                return 0  
            end
        else 
            print ("Invalid input. expected at lest 6 chars") 
            return 0  
        end
end

-- coordinates to number

function aset_UserInputCoord(InputString)
    local slashPos = string.find(InputString,"/")
    if slashPos ~= nil then         
    --  print ("found slash at "..slashPos.." pos")
        local InputStringLen = string.len(InputString)
        local InputLat = string.sub(InputString, 1, slashPos-1)
        local InputLon = string.sub(InputString, slashPos+1,InputStringLen)
    --  print ("Lat:"..InputLat,"Lon:"..InputLon)
    --  print (aset_CoordStringToDecNumber(InputLat), aset_CoordStringToDecNumber(InputLon))
        return aset_CoordStringToDecNumber(InputLat), aset_CoordStringToDecNumber(InputLon)
    else print ("Invalid input.Use format lat/lon")
    end 
end
--
-- tests
--
print (aset_UserInputCoord("51921N/1233545W"))
-> 5.3225   -123.59583333333

print (aset_UserInputCoord("11945S/32200W"))
->-1.3291666666667  -3.3666666666667

user (pilot) enters the desired position eg 52345N/761520E and script converts this string to the two numbers 5.3958333333333 and 76.255555555556

DeputyLOL commented 8 years ago

COOOOOOOOLLLLLLL!!!!!!!!!

MOARdV commented 8 years ago

I believe that sooner or later we will be able to freely enter any text,

MAS supports free text entry. Look at the number buttons I used for the MechJeb control panel - AvionicsSystems/ASET_Props/swButton/MAS_swButton_MJ0.cfg and the rest. The buttons are adding text to a text value, which is then converted to a number for feeding to MJ.

Actually, I guess I hide what's happening because I also wanted the 'on' LED to toggle when I press the button. Here's the actual function:

fc.AppendPersistent(persistent, newstring, maximumLength)

persistent = name of the persistent newstring = the string to add (could be "0", or "1", or "Kerbin", or whatever) maximumLength = the maximum length of the persistent, so you can limit how long the string will grow.

For the MJ number keys, I used fc.AppendPersistent("MAS_MechJebBuffer", "0", 6)

Alexustas commented 8 years ago

The fifth script

2D rotation of geo-point with given coordinates rendered on a MFD screen

script:

function aset_RotatedPoint(OriginX,OriginY,TGTposX,TGTposY,RetAxis,RotVariable,scale)
    if TGTposX == nil then TGTposX = OriginX end
    if TGTposY == nil then TGTposY = OriginY end    
    local DeltaX = (tonumber(TGTposX) - tonumber(OriginX)) * scale
    local DeltaY = (tonumber(TGTposY) - tonumber(OriginY)) * scale
    local InvHeading = math.rad(RotVariable) 
    local RotatedX = DeltaX * math.cos(InvHeading) - DeltaY * math.sin(InvHeading)
    local RotatedY = DeltaY * math.cos(InvHeading) + DeltaX * math.sin(InvHeading)
    if RetAxis == "X" then return RotatedX end
    if RetAxis == "Y" then return RotatedY end
end

script in action (video)

https://youtu.be/Lb4l_wMlosY

syntax: aset_RotatedPoint(OriginX,OriginY,TGTposX,TGTposY,RetAxis,RotVariable,scale)

OriginX,OriginY - coordinates of the point around which the rotation takes place. generall, longitude and latitude of vessel, but could be used any pair of coordinate TGTposX,TGTposY - coordinates of the point which must be rotated RetAxis - the value of which axis should return function. can be "X" or "Y" RotVariable - rotation angle. in generall - fc.Heading(), but could be used any variable or value scale - multiplier

application in practice

$&$aset_RotatedPoint(fc.Longitude(),fc.Latitude(),fc.TargetLongitude(),fc.TargetLatitude(),"X",fc.Heading(),fc.GetPersistentAsNumber("zoom%PROPID%"));

MOARdV commented 8 years ago

Very cool.

DeputyLOL commented 8 years ago

I'd love to use this but I don't have any text on screen. :(

Alexustas commented 8 years ago

full page definition:

Zoom:{0}$&$fc.GetPersistentAsNumber("zoom%PROPID%")

                           OUT-

               ^            IN-
               |
               |
---------------[#FF8800FF][@x{0}][@y{1}]+[@x0][@y0][#FFFFFFFF]----------------  $&$aset_RotatedPoint(fc.Longitude(),fc.Latitude(),fc.TargetLongitude(),fc.TargetLatitude(),"X",fc.Heading(),fc.GetPersistentAsNumber("zoom%PROPID%")); aset_RotatedPoint(fc.Longitude(),fc.Latitude(),fc.TargetLongitude(),fc.TargetLatitude(),"Y",fc.Heading(),fc.GetPersistentAsNumber("zoom%PROPID%"))*-1
               |[#FF8800FF][@x{0}][@y{1}]{2:##0.0}  $&$aset_RotatedPoint(fc.Longitude(),fc.Latitude(),fc.TargetLongitude(),fc.TargetLatitude(),"X",fc.Heading(),fc.GetPersistentAsNumber("zoom%PROPID%")); aset_RotatedPoint(fc.Longitude(),fc.Latitude(),fc.TargetLongitude(),fc.TargetLatitude(),"Y",fc.Heading(),fc.GetPersistentAsNumber("zoom%PROPID%"))*-1-16;fc.TargetDistance()
               |