Modding Help I need help with lua coding.

Discussion in 'Starbound Modding' started by TheHero2805, Jun 6, 2017.

  1. TheHero2805

    TheHero2805 Scruffy Nerf-Herder

    A few weeks ago I started a personal project of updating an outdated mod which adds 8 new techs to Starbound. The techs add "Stands" from the anime JoJo's Bizarre Adventure into the game, or at least they're supposed to. After asking for help in another thread I made, I have already gotten some help with most of the outdated files.
    Now I have the problem of not knowing how to code in lua and am therefore unable to update it.

    This is the lua code that overall sets the standard of how all the other Stands work and what they can do.
    I know it is outdated because I looked through the "Official Starbound Wiki" and saw that this code here contains functions that are not in the list of functions that work in the latest version.
    Code:
    function init()
      data.active = false
      data.fireTimer = 0
      tech.setVisible(false)
      data.punched = false
      data.started = false
      data.ended = false
    end
    
    function uninit()
      if data.active then
        data.active = false
        tech.setVisible(false)
        tech.setToolUsageSuppressed(false)
        tech.setParentFacingDirection(nil)
      end
    end
    
    function input(args)
      if args.moves["special"] == 1 then
        if data.active then
          return "standDeactivate"
        else
          return "standActivate"
        end
      elseif args.moves["primaryFire"] then
        return "standFire"
      end
    
      return nil
    end
    
    function update(args)
      local energyCostPerSecond = tech.parameter("energyCostPerSecond")
      local standFireCycle = tech.parameter("standFireCycle")
      local standStartCycle = tech.parameter("standStartInterval")
      local standAttackCycle = tech.parameter("standAttackInterval")
      local standProjectile = tech.parameter("standProjectile")
      local attackSound = tech.parameter("attackSound")
      local summonSound = tech.parameter("summonSound")
      local standProjectileConfig = tech.parameter("standProjectileConfig")
      local standAimLimit = tech.parameter("standAimLimit") * math.pi / 180
    
      if not data.active and args.actions["standActivate"] then
        tech.setVisible(true)
        tech.playImmediateSound(summonSound)
        tech.setParentAppearance("normal")
        tech.setAnimationState("moving","summon")
        tech.setToolUsageSuppressed(true)
        data.active = true
    
      elseif data.active and (args.actions["standDeactivate"] or energyCostPerSecond * args.dt > args.availableEnergy) then
        tech.setVisible(false)
        tech.setParentAppearance("normal")
        tech.setToolUsageSuppressed(false)
        tech.setParentOffset({0, 0})
        data.active = false
    end
    tech.setParentFacingDirection(nil)
     
      if data.active then
        local diff = world.distance(args.aimPosition, tech.position())
        local aimAngle = math.atan2(diff[2], diff[1])
        local flip = aimAngle > math.pi / 2 or aimAngle < -math.pi / 2
    
        if flip then
          tech.setFlipped(true)
          tech.setParentFacingDirection(-1)
          if aimAngle > 0 then
            aimAngle = math.max(aimAngle, math.pi - standAimLimit)
          else
            aimAngle = math.min(aimAngle, -math.pi + standAimLimit)
          end
    
        else
          tech.setFlipped(false)
          tech.setParentFacingDirection(1)
          if aimAngle > 0 then
            aimAngle = math.min(aimAngle, standAimLimit)
          else
            aimAngle = math.max(aimAngle, -standAimLimit)
          end
        end
    
        if data.started==false then
            if not tech.onGround() then
              if tech.velocity()[2] > 0 then
                tech.setAnimationState("moving", "moving")
              else
                tech.setAnimationState("moving", "moving")
              end
            elseif tech.walking() or tech.running() then
              if flip and tech.direction() == 1 or not flip and tech.direction() == -1 then
                tech.setAnimationState("moving", "moving")
                else
                tech.setAnimationState("moving", "moving")
              end
            else
                tech.setAnimationState("moving", "idle")
            end
        end
       
        if args.actions["standFire"] or data.started==true then
            if data.fireTimer <=standStartCycle and data.fireTimer>=0 then
                if data.started == false then   
                    tech.setAnimationState("moving","start")
                    tech.playImmediateSound(attackSound)
                end
                data.started=true
            elseif data.fireTimer>standStartCycle and data.fireTimer<=standAttackCycle and data.started==true then
                if data.punched==false then
                    tech.setAnimationState("moving","attack")
                    world.spawnProjectile(standProjectile, tech.position(), tech.parentEntityId(), {math.cos(aimAngle), math.sin(aimAngle)}, false, standProjectileConfig)
                end   
                data.punched=true
            elseif data.fireTimer>standAttackCycle and data.fireTimer<=standFireCycle and data.punched==true then
                if data.ended==false then
                    tech.setAnimationState("moving","end")
                end   
                data.ended=true
            elseif data.fireTimer>standFireCycle and data.ended==true then
                data.started=false
                data.punched=false
                data.ended=false
                data.fireTimer=0
            end   
            data.fireTimer = data.fireTimer + args.dt
        end
        return energyCostPerSecond * args.dt
      end
    
      return 0
    end
    
    

    I don't know much about many coding/programming languages but I can mostly tell what a program can do when I look at it.
    Now I don't want people to recode the whole thing for me because that way I don't learn anything. I just want to know the basics of how programming techs in Starbound works so I can do it myself.
     
  2. Cyel

    Cyel Scruffy Nerf-Herder

    Basically, scripted things in Starbound are either "client-side" or "server-side" (for example, techs are clientside, objects are serverside), and scripts get access to tables depending on their context (for example, "tech.setVisible()" is a function in the tech table; the tech table is only available in tech scripts).
    You can find documentation about (mostly) all the available tables and their functions in your game's folder, /Starbound/doc/lua.

    From a quick read of that code, it seems most of the "outdated" functions have just been moved to another table; for example "tech.running()" is now "mcontroller.running()"; "tech.position()" would be "mcontroller.position()", and "tech.parentEntityId()" would be "entity.id()".
    If you look around in the docs, you should more or less easily find the functions you want. I'd recommend loading the whole folder (referenced as a "project" i think?) in your text editor, and fuzzy-search in it (ctrl+shift+F generally) for things.
    (If you want some examples of good text editors for coding, there's a list there: http://starbounder.org/Modding:Text_Editors

    You'll probably also need to change "special" to "special1" soon since that will change in 1.3

    If you snoop into other up-to-date tech scripts, you should probably find working examples doing similar things!
     
  3. TheHero2805

    TheHero2805 Scruffy Nerf-Herder

    Thank you for your reply. This will help me a lot and I will hopefully make this mod work again. Though I technically still need to wait to get a reply from the original uploader who made this mod because otherwise I can't upload my rework here.
     
    Cyel likes this.
  4. TheHero2805

    TheHero2805 Scruffy Nerf-Herder

    I have looked online for a lot of the changes made to the lua in starbound and have already changed most of the lua files. But there is still one file that needs updating but I couldn't figure out what to change in it. The lua code is supposed to act like a blink dash tech. Now the problem I have with that is that I can't seem to find any version of a blink dash lua code for me to use as reference.
    Code:
    
    function checkCollision(position)
      local collisionBounds = tech.collisionBounds()
      collisionBounds[1] = collisionBounds[1] - mcontroller.position()[1] + position[1]
      collisionBounds[2] = collisionBounds[2] - mcontroller.position()[2] + position[2]
      collisionBounds[3] = collisionBounds[3] - mcontroller.position()[1] + position[1]
      collisionBounds[4] = collisionBounds[4] - mcontroller.position()[2] + position[2]
    
      return not world.rectCollision(collisionBounds)
    end
    
    function blinkAdjust(position, doPathCheck, doCollisionCheck, doLiquidCheck, doStandCheck)
      local blinkCollisionCheckDiameter = tech.parameter("blinkCollisionCheckDiameter")
      local blinkVerticalGroundCheck = tech.parameter("blinkVerticalGroundCheck")
      local blinkFootOffset = tech.parameter("blinkFootOffset")
    
      if doPathCheck then
        local collisionBlocks = world.collisionBlocksAlongLine(mcontroller.position(), position, true, 1)
        if #collisionBlocks ~= 0 then
          local diff = world.distance(position, mcontroller.position())
          diff[1] = diff[1] / math.abs(diff[1])
          diff[2] = diff[2] / math.abs(diff[2])
    
          position = {collisionBlocks[1][1] - diff[1], collisionBlocks[1][2] - diff[2]}
        end
      end
    
      if doCollisionCheck and not checkCollision(position) then
        local spaceFound = false
        for i = 1, blinkCollisionCheckDiameter * 2 do
          if checkCollision({position[1] + i / 2, position[2] + i / 2}) then
            position = {position[1] + i / 2, position[2] + i / 2}
            spaceFound = true
            break
          end
    
          if checkCollision({position[1] - i / 2, position[2] + i / 2}) then
            position = {position[1] - i / 2, position[2] + i / 2}
            spaceFound = true
            break
          end
    
          if checkCollision({position[1] + i / 2, position[2] - i / 2}) then
            position = {position[1] + i / 2, position[2] - i / 2}
            spaceFound = true
            break
          end
    
          if checkCollision({position[1] - i / 2, position[2] - i / 2}) then
            position = {position[1] - i / 2, position[2] - i / 2}
            spaceFound = true
            break
          end
        end
    
        if not spaceFound then
          return nil
        end
      end
    
      if doStandCheck then
        local groundFound = false
        for i = 1, blinkVerticalGroundCheck * 2 do
          local checkPosition = {position[1], position[2] - i / 2}
    
          if world.pointCollision(checkPosition, false) then
            groundFound = true
            position = {checkPosition[1], checkPosition[2] + 0.5 - blinkFootOffset}
            break
          end
        end
    
        if not groundFound then
          return nil
        end
      end
    
      if doLiquidCheck and (world.liquidAt(position) or world.liquidAt({position[1], position[2] + blinkFootOffset})) then
        return nil
      end
    
      if doCollisionCheck and not checkCollision(position) then
        return nil
      end
    
      return position
    end
    
    function findRandomBlinkLocation(doCollisionCheck, doLiquidCheck, doStandCheck)
      local randomBlinkTries = tech.parameter("randomBlinkTries")
      local randomBlinkDiameter = tech.parameter("randomBlinkDiameter")
    
      for i=1,randomBlinkTries do
        local position = mcontroller.position()
        position[1] = position[1] + (math.random() * 2 - 1) * randomBlinkDiameter
        position[2] = position[2] + (math.random() * 2 - 1) * randomBlinkDiameter
    
        local position = blinkAdjust(position, false, doCollisionCheck, doLiquidCheck, doStandCheck)
        if position then
          return position
        end
      end
    
      return nil
    end
    
    function init()
      data.mode = "none"
      data.timer = 0
      data.targetPosition = nil
      data.active = false
      data.fireTimer = 0
      data.started = false
      data.warped = false
      data.ended = false
      tech.setVisible(false)
      tech.setToolUsageSuppressed(true)
    end
    
    function uninit()
      tech.setParentState()
        if data.active then
        data.active = false
        tech.setVisible(false)
        tech.setToolUsageSuppressed(false)
        mcontroller.controlFace(nil)
      end
    end
    
    function input(args)
      if args.moves["special1"] == 1 then
        if data.active then
         return "standDeactivate"
        else
          return "standActivate"
        end
      elseif args.moves["primaryFire"] then
        return "blink"
      end
    
      return nil
    end
    
    function update(args)
      local energyUsage = tech.parameter("energyUsage")
      local energyCostPerSecond = tech.parameter("energyCostPerSecond")
      local blinkMode = tech.parameter("blinkMode")
      local blinkOutTime = tech.parameter("blinkOutTime")
      local blinkInTime = tech.parameter("blinkInTime")
      local startSound = tech.parameter("startSound")
      local endSound = tech.parameter("endSound") 
      local summonSound = tech.parameter("summonSound")   
      local standAimLimit = tech.parameter("standAimLimit") * math.pi / 180
      local standFireCycle = tech.parameter("standFireCycle")
      local standStartCycle = tech.parameter("standStartInterval")
      local standAttackCycle = tech.parameter("standAttackInterval")
    
      if not data.active and args.actions["standActivate"] then
        tech.setVisible(true)
        tech.playSound(summonSound)
        tech.setParentState()
        tech.setToolUsageSuppressed(true)
        data.active = true
      
      elseif data.active and (args.actions["standDeactivate"] or energyCostPerSecond * args.dt > status.resource("energy")) then
        tech.setVisible(false)
        tech.setParentState()
        tech.setToolUsageSuppressed(false)
        tech.setParentOffset({0, 0})
        data.active = false  
      end
    mcontroller.controlFace(nil)
      if data.active then
        local diff = world.distance(tech.aimPosition, mcontroller.position())
        local aimAngle = math.atan2(diff[2], diff[1])
        local flip = aimAngle > math.pi / 2 or aimAngle < -math.pi / 2
    
        if flip then
          animator.setFlipped(true)
         mcontroller.controlFace(-1)
          if aimAngle > 0 then
            aimAngle = math.max(aimAngle, math.pi - standAimLimit)
          else
            aimAngle = math.min(aimAngle, -math.pi + standAimLimit)
          end
    
        else
          animator.setFlipped(false)
         mcontroller.controlFace(1)
          if aimAngle > 0 then
            aimAngle = math.min(aimAngle, standAimLimit)
          else
            aimAngle = math.max(aimAngle, -standAimLimit)
          end
        end
    
        if data.started==false then
            if not mcontroller.onGround() then
             if mcontroller.velocity()[2] > 0 then
                animator.setAnimationState("moving", "moving")
             else
                animator.setAnimationState("moving", "moving")
             end
            elseif mcontroller.walking() or mcontroller.running() then
             if flip and mcontroller.movingDirection() == 1 or not flip and mcontroller.movingDirection() == -1 then
                animator.setAnimationState("moving", "moving")
                else
                animator.setAnimationState("moving", "moving")
             end
            else
                animator.setAnimationState("moving", "idle")
            end
        end
      if (args.actions["blink"] and data.mode == "none" and status.resource("energy") > energyUsage and data.active==true) or data.started==true then
        local blinkPosition = nil
        if blinkMode == "random" then
          local randomBlinkAvoidCollision = tech.parameter("randomBlinkAvoidCollision")
          local randomBlinkAvoidMidair = tech.parameter("randomBlinkAvoidMidair")
          local randomBlinkAvoidLiquid = tech.parameter("randomBlinkAvoidLiquid")
    
          blinkPosition =
            findRandomBlinkLocation(randomBlinkAvoidCollision, randomBlinkAvoidMidair, randomBlinkAvoidLiquid) or
            findRandomBlinkLocation(randomBlinkAvoidCollision, randomBlinkAvoidMidair, false) or
            findRandomBlinkLocation(randomBlinkAvoidCollision, false, false)
        elseif blinkMode == "cursor" then
            if data.fireTimer <=standStartCycle and data.fireTimer>=0 then
                if data.started==false then  
                    tech.setParentState()
                    animator.setAnimationState("blinking", "out")
                    animator.setAnimationState("moving","start")
                    tech.playSound(startSound)
                end
                data.started=true
            elseif data.started==true and data.warped==false and data.fireTimer>standStartCycle and data.fireTimer<standAttackCycle then
                blinkPosition = blinkAdjust(tech.aimPosition, true, true, false, false)
                data.warped = true
            elseif data.warped ==true and data.started==true and data.fireTimer >=standAttackCycle and data.fireTimer<standFireCycle then
                if data.ended==false then  
                    tech.setParentState()
                    animator.setAnimationState("blinking", "in")
                    animator.setAnimationState("moving","end")
                    tech.playSound(endSound)
                end  
                data.ended=true
            elseif data.ended==true and data.warped==true and data.fireTimer >=standFireCycle then
                data.started=false
                data.warped=false
                data.ended=false
                data.fireTimer=0
            end
            data.fireTimer = data.fireTimer + args.dt
        elseif blinkMode == "cursorPenetrate" then
          blinkPosition = blinkAdjust(tech.aimPosition, false, true, false, false)
        end
    
        if blinkPosition then
          data.targetPosition = blinkPosition
          data.mode = "start"
        else
          -- Make some kind of error noise
        end
      end
    
      if data.mode == "start" then
        tech.setVelocity({0, 0})
        data.mode = "out"
        data.timer = 0
    
        return energyUsage
      elseif data.mode == "out" then
        tech.setVelocity({0, 0})
        data.timer = data.timer + args.dt
    
        if data.timer > blinkOutTime then
          tech.setPosition(data.targetPosition)
          data.mode = "in"
          data.timer = 0
        end
    
        return 0
      elseif data.mode == "in" then
        tech.setVelocity({0, 0})
        data.timer = data.timer + args.dt
    
        if data.timer > blinkInTime then
          data.mode = "none"
        end
    
        return 0
      end
    end
    end
    
    I have already changed most of the things I found by replacing them in notepad++ so this isn't really the original code.
     
  5. louberte50

    louberte50 Void-Bound Voyager

    I hope that you are going to keep working on it because Im not good at modding but I really want to use this old Jojo mod!
     

Share This Page