This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Corky_McDuff's profile picture

Star Trek Turbo Lift (Teleport)

Started by Corky_McDuff, 26 September 2014 - 09:46 AM
Corky_McDuff #1
Posted 26 September 2014 - 11:46 AM
Hi All
First post and completely new to CC, so apologies in advance!

We are building a full scale model of the Star Trek Enterprise (NCC-1701a for you fellow ST geeks)

I am looking to fill the hull with Tech now and first port of call are the Turbo lifts which I would like to use command blocks for teleporting between each floor rather than actual moving blocks.

The idea and code that I have, came from a Star Trek forum, that I cannot seem to add the link to here. On the forum, someone had built an Enterprise and used the following code;

print()
write(" Enter Deck Number ")
return read()
end

cb = peripheral.wrap("bottom")
if getdeck() == "break" then return
elseif getdeck () == "1" then
cb.setcommand("/tp @p -499 140 334")
cb.runcommand()
elseif getdeck() == "2" then
cb.setcommand("/tp @p -499 132 334")
cb.runcommand()
else
term.clear()
term.setCursorPos(2,2)
print ("Invalid Destination Entered")
end

Unfortunately the screen shot he posted does not show all of the code.
There are a couple of lines missing at the beginning. Can one of you gurus please assist in adding what need to make this work, that would be appreciated…Thank you.
Lyqyd #2
Posted 26 September 2014 - 05:40 PM
Probably something like this:


local function getdeck()

You might also want a `while true do` after the "cb =" line, with an additional `end` at the end.
H4X0RZ #3
Posted 26 September 2014 - 09:04 PM
The Problem with the code is, that every time you enter a "deck" which doesn't match the current if-thigy (forgot the name *facepalm*) it will ask you another time. For Example:

#Entered if part
#If part runs getdeck() which asks you the deck you want to go
# you enter "2"
#the if part isn't ran
#Entered second If part
#If part runs getdeck() which asks another time which deck you want to go
#this time you enter "1"
#the if part isn't ran too
Corky_McDuff #4
Posted 28 September 2014 - 09:45 AM
Thanks for the replies and advice.
I'm really struggling with this.

What I am trying to do is have a computer and monitor in each "Turbo Lift", with a command block hidden under the computer.
I would like to have "Enter Deck Number" showing on the monitor with the available "Decks" and ideally what each deck is call i.e. "deck 12 medical bay" or something to that effect.
Then by entering the deck number the command block teleports you.

But really at a loss where to start with this.
KingofGamesYami #5
Posted 28 September 2014 - 01:58 PM
Well, you want to look at the command block api, and perhaps the monitor touch event.
Corky_McDuff #6
Posted 30 September 2014 - 01:19 PM
Thanks KingofGamesYami for the links, I will certainly have a go at the monitor touch event!

I will provide the pastebin details when back at my PC for those interested, but in the mean time;

So I have got it working… sort of. But a work in progress.
It finally decides to teleport me after inputting the deck number in about three times, when the command block comes back from its cigarette break and sends me.
Anyone else experience this delay when integrating CC & Command Blocks?

Also, what would I need to add to make the program show on the monitor permanently please?
I have watched all sorts of training videos and read several tutorials but just not getting how I do this. Probably very basic stuff for you guys, but I spent about 3hrs yesterday trying different things too avail.
Presumably I need to do this prior to making it touch screen?

Thanks again all.
KingofGamesYami #7
Posted 30 September 2014 - 04:09 PM
Also, what would I need to add to make the program show on the monitor permanently please?

I assume you want term.redirect.
Corky_McDuff #8
Posted 01 October 2014 - 09:18 AM
Thanks again KingofGamesYami . As simple as that lol. I'll give it ago.

Its only just dawned on me what Freack100 meant, every time I enter the deck number, it asks again instead of running the command immediately on the commandblock. The command only runs after entering the deck number a few times….hardly Turbo :D/>

What would be a more effective way of doing this do you think please?
Bomb Bloke #9
Posted 01 October 2014 - 10:04 AM
The idea is to assign what the user enters to a variable, then perform your checks against that.

Eg:

if getdeck() == "1" then  -- Run "getdeck"
  -- whatever
elseif getdeck() == "2" then  -- Run "getdeck" again...
  -- etc

… becomes:

local myVar = getdeck()  -- store the result of getdeck against myVar

if myVar == "1" then  -- Doesn't run getdeck again!
  -- whatever
elseif myVar == "2" then  -- Still doesn't run getdeck again!
  -- etc
Corky_McDuff #10
Posted 01 October 2014 - 10:08 AM
Cheers Bomb Bloke, that makes a lot of sense.
Corky_McDuff #11
Posted 01 October 2014 - 08:46 PM
http://pastebin.com/0rs3t7nR - This is where I have got to in my efforts so far.
Apologies, I am stuck implementing Bomb Bloke's suggestion. Where am I going wrong this time you lovely CC experts? :rolleyes:/>
Dragon53535 #12
Posted 01 October 2014 - 09:56 PM

local function getDeck() --# The function called getDeck()
--doStuff
  return read() -- Returns what the user inputs
end
local myVar = getDeck() -- Runs getDeck() and grabs the information returned
if myVar == "1" then --# if the information stored in myVar is "1" then
  --dostuff
elseif myVar == "2" then
  --doMoreStuff
end
Corky_McDuff #13
Posted 01 October 2014 - 10:38 PM
Ahh ok, so you need to leave the function in at the beginning. I foolishly assumed it was replaced.
Works perfectly. Thank you so much!!

Now on to adding the buttons on the monitor! :unsure:/>
Corky_McDuff #14
Posted 04 October 2014 - 06:28 PM
So the program works and does what I want it to, which is teleport the user to the selected deck on our Starship Enterprise project. Thank you all for your help. This is the code as of now - wvqKQ6Hw
However the next part is way beyond my abilities, which are small to start with on CC.

I would be really greatfull if anyone would be kind enough to help me out in writing the next bit.
I need buttons on the monitor that list the floor number and ideally the corresponding description i.e. Engineering 3
There are several floors in some areas (this is a big project), so need to be able to squeeze on one monitor if possible. However there is space to have a square of for monitors if needed.
So this will need to be touchscreen then when a number is clicked you are teleported to that floor.

Thank you once again.
Bomb Bloke #15
Posted 04 October 2014 - 10:54 PM
This is where you'd want something like the touchpoint API.
VSXGsonic #16
Posted 06 October 2014 - 08:55 PM
If he uses 1.6x couldn't he just use a pocket pc . Just open it scroll through the list click the floor and a computer under the teleport deck would receive it and use the coresonding command block ? Then size is not an issue if he uses a scroll check to move around the list.

Just a thought ^-^

Edit: and just have a 2x1 size monitor display the destination then puff ur on new floor
Edited on 06 October 2014 - 06:59 PM
Corky_McDuff #17
Posted 07 October 2014 - 09:53 AM
I appreciate your replies, thanks.
However…..just imagine that I know absolutely nothing about CC and you would still have over estimated my knowledge! :P/>

I need to learn how to use an API, as I don't understand how I integrate that with my program.The pocket pc is a nice idea, but for realism I would like to try and avoid it if possible.

The actual ship is coming on well though. There are three of working on it, but it is huge and takes hours of work just to put in one floor of the saucer section, which consists of around 70,000 blocks per main floor. Main engineering is complete and we use a huge reactor powering 4 large turbines to charge vast banks of capacitors that in turn provide power for lighting etc. I will try and post a pic if anyone is interested. But we are getting to a point where areas will be difficult to access without working lifts.
Bomb Bloke #18
Posted 07 October 2014 - 10:17 AM
Take a read through this first; it covers what an API is (at least, in the context of ComputerCraft), and how they're used.

Then take another look at the examples in the touchpoint thread and see how you go from there.
Dragon53535 #19
Posted 07 October 2014 - 10:20 AM
For api's lets pretend we have a simple API like this
PretendApi

function add(num1, num2) --#Just a simple adding function, using it as an example. Please note the lack of the word local infront of the function.
  return num1 + num2
end
Now lets say that the API's file is called Pretend. we would then use this

os.loadAPI("Pretend") --# This loads the file and allows it to be run.
print(Pretend.add(5,3)) --> 8
Notice the name of the file is put before the actual function's name.
Corky_McDuff #20
Posted 07 October 2014 - 11:12 AM
This is such a helpful forum, you guys are awesome.

Ok, so that makes sense.It's almost like a separate program that runs in the background when called in the main program.
I think where I will get confused is when I try and add the code into my existing program to make it work with the API.
But I'll give it a whirl.
Dragon53535 #21
Posted 07 October 2014 - 11:31 AM
Really when you load an API it's as if it's a function that you just haven't called yet. It's there, and the computer knows what it does, however it's not constantly running and won't run until you tell it to.
Corky_McDuff #22
Posted 07 October 2014 - 02:03 PM
Ahh ok. Cheers Dragon
Corky_McDuff #23
Posted 08 October 2014 - 10:25 PM
It's official, I don't have the foggiest clue what am doing! lol
Please feel free to fill in the blanks as its no spoiler for me, I just want working lifts :D/>
This is where I a currently and probably made a mess of it - JW6Pa7DH

…help please!!
Dragon53535 #24
Posted 09 October 2014 - 04:46 AM
You're not doing anything wrong, or at least not exactly :P/>. I would create a function that you send the deck number to, and then inside there it checks for your variable.

local function deckTP(deckNum)
  if deckNum == "1" then
	commandBlock.setCommand("tp @p[r=2] -211 106 405")
	commandBlock.runCommand()
  elseif deckNum == "2" then
	commandBlock.setCommand("tp @p[r=2] -211 113 405")
	commandBlock.runCommand()
  elseif deckNum == "3" then
	commandBlock.setCommand("tp @p[r=2] -211 120 405")
	commandBlock.runCommand()
  else
	term.clear()
	term.setCursorPos(1,1)
	print("Invalid Destination Entered")
  end
end

And then you could swap your getdeck function to be this

local function getdeck()
  term.clear()
  term.setCursorPos(1,1)
  term.write("Turbo Lift")
  print()
  write("Enter Deck Number: ")
  deckTP(read())
end

Now for your buttons with the touchpoint API, any button that you want to add (and i'm going to leave the names and such, however i'm giving 2 examples) You should try and format them like this

t:add("Floor 1",function() deckTP("1") end,  2, 2, 14, 11, colors.red, colors.lime)
t:add("Floor 2",function() deckTP("2") end,  16, 2, 28, 11, colors.red, colors.lime)
If you notice in that second part where it says function() you notice right after that it's got deckTP("1") and deckTP("2") this allows you to have it so when you click the button, you teleport like you should. If you're going to have multiple buttons, that's the only part you need to keep the same, except that number inside deckTP, change that for whatever floor the button should take you to.

Now for your button handling, i would put that all in a function and then whenever a button is pressed, flash it, and execute the function inside of it.

local function buttonPress()
while true do
  t:draw()

  --# handleEvents will convert monitor_touch events to button_click if it was on a button
	  local event, p1 = t:handleEvents(os.pullEvent())
	  if event == "button_click" then
		t:flash(p1) --# This will cause it to look green for a second and then back to red
		t.buttonList[p1].func() --# This will call the function in the button, That thing earlier where it says function() deckTP("1") end.
		break  
	  end
  end
end

And then at the bottom in your while loop you should use the parallel API so that it's reading input from the screen, and at the same time, looking for a button input.

while true do
  parallel.waitForAny(buttonPress,getdeck) --#it runs both of the functions, please note the lack of () next to the function names. and will continue on whenever one of them ends.
  --#However we're in a while true loop, which means that it will restart when one finishes :P/>/>/>/>/>/>
end

So all in all, to get your code working, you would need something like this
Spoiler

--# load the touchpoint API
os.loadAPI("touchpoint")

--# initialize a new button set on the top monitor
local t=touchpoint.new("top")
local monitor = peripheral.wrap("top")
monitor.setTextScale(1)
local commandBlock = peripheral.wrap("left")
t:add("Floor 1",function() deckTP("1") end,  2, 2, 14, 11, colors.red, colors.lime)
t:add("Floor 2",function() deckTP("2") end,  16, 2, 28, 11, colors.red, colors.lime)
local function deckTP(deckNum)
  if deckNum == "1" then
	commandBlock.setCommand("tp @p[r=2] -211 106 405")
	commandBlock.runCommand()
  elseif deckNum == "2" then
	commandBlock.setCommand("tp @p[r=2] -211 113 405")
	commandBlock.runCommand()
  elseif deckNum == "3" then
	commandBlock.setCommand("tp @p[r=2] -211 120 405")
	commandBlock.runCommand()
  else
	term.clear()
	term.setCursorPos(1,1)
	print("Invalid Destination Entered")
  end
end
local function getdeck()
  term.clear()
  term.setCursorPos(1,1)
  term.write("Turbo Lift")
  print()
  write("Enter Deck Number: ")
  deckTP(read())
end
local function buttonPress()
  while true do
    t:draw()
    --# handleEvents will convert monitor_touch events to button_click if it was on a button
	  local event, p1 = t:handleEvents(os.pullEvent())
	  if event == "button_click" then
		t:flash(p1) --# This will cause it to look green for a second and then back to red
		t.buttonList[p1].func() --# This will call the function in the button, That thing earlier where it says function() deckTP("1") end.
		break
	end
  end
end
while true do
  parallel.waitForAny(buttonPress,getdeck) --#it runs both of the functions, please note the lack of () next to the function names. and will continue on whenever one of them ends.
  --#However we're in a while true loop, which means that it will restart when one finishes :P/>/>/>/>/>/>
end

Make sure you of course have the touchpoint API installed in the file touchpoint
Edited on 09 October 2014 - 02:52 AM
Corky_McDuff #25
Posted 09 October 2014 - 09:51 AM
Dragon….what can I say, you are indeed a legend!
How much do I owe you? Just send me the invoice. :P/>

touchpoint API is installed. I managed that much hehe.
I was getting an error saying that the button was out of bounds. I am presuming that this means the button would not fit or something?

thanks again for all your help! I can't wait to try this out after work.
…If only I could run MC on my work laptop!!
Dragon53535 #26
Posted 09 October 2014 - 08:51 PM
Yes that is correct, if the button cannot fit on the screen then it errors.
Corky_McDuff #27
Posted 09 October 2014 - 10:32 PM
Cheers Dragon.
I am getting the following error when clicking a button - parallel:22: Turbo:9: attempt to call nil
Any ideas?
Dragon53535 #28
Posted 09 October 2014 - 10:43 PM
Can you post your code for me?
Corky_McDuff #29
Posted 09 October 2014 - 10:55 PM
I just tried the exact code you entered in the spoiler.
Dragon53535 #30
Posted 09 October 2014 - 11:03 PM
I know the problem, and i didn't test the code. (at the time, tested it earlier on a server, forgot this was like this :P/>) Just move line 9 and 10 below the deckTP function

Edit: Post #256 I AM BYTEMAN
Edited on 09 October 2014 - 09:05 PM
Corky_McDuff #31
Posted 09 October 2014 - 11:33 PM
Thanks, I moved them hopefully to the right place and I teleport once but then it stops ad get the following error.

Now getting parallel:22: Turbo:25: button already exists?

Pastebin - ATmJE8Qb

Thanks again!!
Dragon53535 #32
Posted 09 October 2014 - 11:38 PM
You've put it inside the deckTP function, move it below the end under it, around line 29
Corky_McDuff #33
Posted 10 October 2014 - 12:43 PM
ok, nice one. I will amend my error.

Is it fairly simple to have these buttons look more like a list than these big buttons?
I reduced the text size to .5 but need to make the buttons only as deep as one line so I can fit several on one monitor.
Like this;

Deck 1
Deck 2
Deck 3
Deck 4
Deck 5

I am loving it so far, it's going to work very well for what I want, and you guys have been amazing, thank you so much.

The next projects for CC will be a) display some sort of tech looking image ideally like the typical startrek images you see on computers in the film (just for effect if possible).
B)/> Have computers just cycling some random code or similar (again, just for effect)
c) Central control of the lighting systems, alarms and tech from the bridge.
Corky_McDuff #34
Posted 10 October 2014 - 07:37 PM
Ignore the last one, figured it out in the end. Looks pretty good, but doesn't seem to work all the time when you click.
I do get the following error - touchpoint:68: attempt to index ? (a nil value) - when I first start the program, then it sort of works if I try again.

I have not altered touchpoint at all and my latest version of Turbo is Gxzw55q
Bomb Bloke #35
Posted 11 October 2014 - 03:17 AM
Usually that means you're attempting to reference something - like a function - before you've defined it. Make sure for eg that you define your functions before you attempt to assign them to your buttons.
Dragon53535 #36
Posted 11 October 2014 - 03:32 AM
The line in the touchpoint api refers to the clickmap. Since it's saying "attempt to index a nil value" Your x positions for the buttons are messing up. For whatever reason, your x position for the buttons is not on the screen.

t:add("Deck 2",function() deckTP("2") end, 16, 2, 28, 11, colors.red, colors.lime)
I'm assuming it's this one as i think 28 would be out of your monitors range.


t:add("Deck 2",function() deckTP("2") end, left, up, right, down, colors.red, colors.lime)
Those show you what direction they control, first is how far left you start, second is what line up top, third is how far right, fourth is how far down.


self.clickMap[i][j]
Is the line it's referencing, and unless self is nil, which would mean that you didn't do touchpoint.new earlier (however since it went into the correct function i'm going to say you did)
And since it went, we know that clickMap isn't nil, and so the only other part that you could be attempting to index would be the x variable, in this case i, and if clickMap is nil, then clickMap[j] would be attempting to index a nil value
Edited on 11 October 2014 - 01:37 AM
Lyqyd #37
Posted 11 October 2014 - 04:04 AM
Looks like the latest posted pastebin code is invalid? I'd like to help, but I can't do so without seeing the latest copy of the code.
Corky_McDuff #38
Posted 11 October 2014 - 06:22 PM
Thank you all, my latest pastebin code is 1mvrUQ6N
Lyqyd #39
Posted 11 October 2014 - 07:57 PM
Okay, doesn't look too bad. Are you having any issues or errors with that version of the code?
Corky_McDuff #40
Posted 11 October 2014 - 08:20 PM
Cheers, yes. I am getting touchpoint:68: attempt to index ? (a nil value) when I try and run the program first time.
But it works on the second attempt.

Which means that I cannot run the program from the startup, so when the server is rebooted, none of the lifts work.
Dragon53535 #41
Posted 11 October 2014 - 09:40 PM
Your monitor.setTextScale is the problem. setup the top of your program like this

local monitor = peripheral.wrap("top")
monitor.setTextScale(.5)
local t=touchpoint.new("top")
Corky_McDuff #42
Posted 11 October 2014 - 10:00 PM
blimey, your a genius. How do you guys know all this stuff?

Thank you once again for coming to my rescue!
It works brilliantly…..love it! :D/>