ROBLOX - If statement won't run inside of while loop? - lua

I've run into something really strange. I was originally trying to make a music script (more like system, tbh) and it had the same problem. Now I have boiled it down to a simple test:
while true do
if script.Parent.musicstate.Value == true then
print("Play")
elseif script.Parent.musicstate.Value == false then
print("Stop")
end
wait()
end
When I run it, it will either only print "Stop" or only print "Play." The string it will print will depend on the value of the bool value when the game starts, as in it does not change what it prints depending on the current value. All help will be appreciated, thanks!
The structure, SongScript is what is running:

Never ever make such an infinite loop crashing your whole system! There is a lot more efficient way to do. You have the problem due to the fact that the script would auto break so it won't crash your whole system.
script.Parent.musicstate.Changed:Connect(function()
if script.Parent.musicstate.Value == true then
print("Play")
elseif script.Parent.musicstate.Value == false then
print("Stop")
end
end)

Related

Making a frame visible is possible but making invisible is not

script.Parent.MouseButton1Click:Connect(function()
if script.Parent.Parent.Frame.Visible == true then
script.Parent.Parent.Frame.Visible = false
end
if script.Parent.Parent.Frame.Visible == false then
script.Parent.Parent.Frame.Visible = true
end
end)
I am very new to coding (have started practically yesterday ) and ive decided to start with lua in roblox studio. The program here is working i can assure you (some things in code may not be in proper place since im having a bit trouble writing code on this site) but the code works. I have tried to make it seperatly for 2 buttons then I tried this and nothing seems to work. I am starting to think it is caused by the program itself and not the code since I can make other things invisible with that code. I've placed those 2 codes for visibility and invisibility in 1 thing since I've been told that events caused by the code happen at same time so some of them may not work.
Assume Visible is true. The first condition will be true and Visible will be set to false. Then, in the next condition Visible is false and the condition is therefore true, again. And it sets Visible back to true.
Now, in order to fix it you want to execute the second condition only if the first failed. Take a look at elseif https://www.lua.org/pil/4.3.1.html.
script.Parent.MouseButton1Click:Connect(function()
if script.Parent.Parent.Frame.Visible == true then
script.Parent.Parent.Frame.Visible = false
elseif script.Parent.Parent.Frame.Visible == false then
script.Parent.Parent.Frame.Visible = true
end
end)
This code is still quite bulky and can be improved:
script.Parent.MouseButton1Click:Connect(function()
script.Parent.Parent.Frame.Visible = not script.Parent.Parent.Frame.Visible
end)
Now you assign true to Visible if Visible does not evaluate to true. It basically toggles the boolean.

What am I doing wrong with my AI?

I've been programming an AI with Lua that you communicate with it in my own logical language. I stumbled across a problem and I can't seem to figure this out.
I'm trying to put y/n questions in. I pretty much said: mi=David la; (sets variable to David. la; is punctuation) la mi=David dor la; (Is 'mi' equal to 'David'?)
When I typed that into it, 'ROBO-DUDE' didn't say anything.
if v == "lol" then
local yes = true
for _,v in pairs(mode[2]) do
if v == false then
print(v)
yes = false
end
print(yes)
end
print(yes)
if yes == true then
things = things .. "jar; "
else
things = things .. "awa; "
end
end
This block of code is in a loop for the 'la' statement. 'dor' means to respond yes/no, the lexer changes it to 'lol'.
When I tested it, the code seemed to skip the dor/lol part of the loop. I went to check the lexer.
if v == "dor" then
sentence[#sentence+1] = "lol"
end
I have no clue what went wrong here. I would like somebody's help on this problem.
Nevermind. I found the problem. When I used a for loop, I used the variable 'v' for the main parser loop and the one that looped through another table/array. I believe changing the variable (any of them) will fix my issue.

vlc.playlist.loop automation

Basically I have this .lua code in my vlc extension, now I am having problems in setting the VLC repeat automatically to loop all in a playlist.
I have tried setting it into "all", 0, 1, 2, true, "TRUE" but it does just not set the playlist's loop value into "all".
I also cannot get the playlist loop value. I tried object.playlist().loop, vlc.playlist.loop.
I read the VLC's Lua Script and Extensions page but I still cannot get what is supposed to be that
<status>
value or any of its acceptable strings.
function trigger()
vlc.playlist.stop()
vlc.playlist.sort("random")
vlc.playlist.goto(0)
--vlc.playlist.repeat_(<status>)
--vlc.playlist.loop(<status>)
vlc.playlist.play()
end
Solved it, thanks to Vyacheslav and Piglet
this would now set the vlc playlist loop to loop all, but I cannot print or vlc.msg.info the value of playlist.loop though. But it works in the end.
function trigger()
vlc.playlist.stop()
vlc.playlist.sort("random")
vlc.playlist.goto(0)
playlist = vlc.object.playlist();
if vlc.var.get(playlist,"loop") == false then vlc.playlist.loop() end
vlc.playlist.play()
end
I have not tried it but following the documentations logic status should be either nil, true or false. If nil (or no argument) it will toggle the current state. true will enable, false disable loop or repeat.
Not sure why you expect loop to be "all".
Did you remove the -- in front of the respective line?
I assume setting both doesn't make sense. And they will toggle each other internally?
In common case, if you do not know how it properly works, it is possible to search such code in github.com.
In your case, you can use this:
https://github.com/search?utf8=%E2%9C%93&q=vlc.playlist.loop+language%3ALua&type=Code&ref=searchresults
As you can see,
you can use such code:
elseif command == "pl_loop" then
vlc.playlist.loop()
elseif command == "pl_repeat" then
vlc.playlist.repeat_()
or
elseif c == 'loop' then
if vlc.playlist.loop(v) then
vlc.playlist.repeat_('off')
end
elseif c == 'repeat' then
if vlc.playlist.repeat_(v) then
vlc.playlist.loop('off')
end

Why is this code not starting?

I am trying to simulate a Simon Says game. I am currently using Corona SDK, and using Lua as my language.
I have put the addEventListener(touch) on the function, "starting". I have tried debugging it and it seems that the code does not correctly run the part that says, if (started) then statement. I would be very grateful if you guys were to help lead me to the right direction!
Here's part of my code:
local function starting(event)
if (started == false) then
started = true
end
if (event.phase == "ended") then
start()
startText.isVisible = false
---------------------------------------------------
--THIS BELOW PART IS WRONG-- does not do "started"
if (started) then
count = count + 1
--if started--
if(math.mod(count,20) == 0) then
clicked = 0
if(light >= 0) then
light = light - 1
end
end
Make sure you have initialized started as false like rpattiso mentioned. Also in my past experience with Lua, sometimes just putting if (started) then
does not work for me, so you should try if (started == true) then.

game Lua scripting - using couroutine or polling?

I am starting to learn how to use Lua scripting for different game profile with logitech software.
First I tried to use onevent (I know it isn't very advanced) and created this attack combo script
function OnEvent(event, arg)
if event == "MOUSE_BUTTON_PRESSED" and arg == 1 then --set flag for mb1
mb1_pressed = true
elseif event == "MOUSE_BUTTON_RELEASED" and arg == 1 then --set flag for mb1=false
mb1_pressed = false
end
end
if mb1_pressed then --using flags to determine whether to start attack or not
repeat
presskey("A")
Sleep(50)
releasekey("A")
Sleep(100)
--if MB1 is release, it will also break script. if i only tap mb1, this will only execute the first line of attack without the rest below
if not (**argument**, can be MB1/ismouse1) then break end
presskey("S")
Sleep(50)
releasekey("")
Sleep(120)
presskey("A")
Sleep(50)
releasekey("A")
Sleep(200)
if not (**argument**, can be MB1/ismouse1) then break end --if MB1 is release, it will also break script. this point will prevent script from looping from start if mb1 release
until not (**argument**, i use ismouse1) --end the loop of script
end
So I am trying to bind this to G6 button of my logiech mouse (using mouse_button_press == 6)
Setting a flag with MB6 works, but ending a loop/breaking a loop cannot be triggered by MB6
After some research on SDK/Lua forum of logitech support, it seems that there is a problem with my script
Flags cannot be used/detect as an argument while a script is performing a loop sequence
IsMouseButtonPressed (reads windows keypress) can be used in place or arguments
Windows only detects MB1-5, so binding to G6 is not possible (registers as 6th button)
I read that using couroutine.yield() or polling can be used for stopping repeat scripts in loop. But I cannot find a tutorial for beginners online.
Sorry for the noobish question!
I don't know anything about Logitech mice so I will try to explain things using a simplified, pure Lua example. Lets model the autoattack script as a loop that prints "A" and "B" alternatively. The "A" corresponds to the first part of your loop (press and release A) and the "B" represents the second part (press and release S and A).
function autoattack()
while true do
print("A")
print("B")
end
end
autoattack()
So far we are OK but the loop will obviously run forever and we need to add a way to stop it. I think what you are trying to do is something along the lines of:
local autoattacking = false
function autoattack()
autoattacking = true
while true do
print("A")
if not autoattacking then break end
print("B")
if not autoattacking then break end
end
end
function stop_autoattack()
autoattacking = false
end
autoattack()
stop_autoattack()
However, since autoattack is an infinite loop, stop_autoattack never runs and the autoattacking flag never gets updated. How can we fix this?
Polling
Instead of calling a function and setting a flag to stop the loop, what if we could call some code to see if the loop should be stopped or not?
function continue_autoattack()
print("continue autoattacking? y/n")
return (io.read("*l") == "y")
end
function autoattack()
while true do
print("A")
if not continue_autoattack() then break end
print("B")
if not continue_autoattack() then break end
end
end
autoattack()
In your mouse this would probably mean using some sort of isKeyPressed function, if its available in the API. Its also important to note that the autoattack loop is still an infinite loop - its just that we changed it so it is in control of its stopping condition.
Coroutines
If we want to keep the code to stop the loop outside the loop we will need a way to run the autoattack loop one step at a time. Here is an example:
local state = 1
function autoattack_step()
if state == 1 then
print("A")
state = 2
elseif state == 2
print("B")
state = 1
elseif state == 3
print("STOPPED")
--state remains as 3
else
error("bad state") -- defensive programming; I hate if/elseif without an else
end
end
function stop_autoattack()
state = 3
end
autoattack_step()
autoattack_step()
autoattack_step()
stop_autoattack()
autoattack_step()
Since we broke up the autoattack loop, we now have a chance to call stop_autoattack between calls to autoattack_step. To do this in your mouse script, I think stop_autoattack can go in "release button" handlers but I dont know where I would put the autoattack_step calls. Maybe the API includes something similar to setTimeout or setInterval in Javascript.
As for coroutines, where do they come in? Did you notice how we needed to do some substantial code refactoring to break the loop into single step chunks for autoattack_step? Coroutines are a Lua feature that lets you write code using loops while still being able to run them "one step at a time". When a coroutine reaches a coroutine.yield, it returns back to its caller. The thing is that when you call coroutine.resume again the coroutine will continue executing from where it stopped instead of going back to the start like a normal function would.
local autoattacking = true
autoattack = coroutine.create(function()
while true do
print("A")
coroutine.yield()
if not autoattacking then break end
print("B")
coroutine.yield()
if not autoattacking then break end
end
end)
function stop_autoattack()
autoattacking = false
end
coroutine.resume(autoattack)
coroutine.resume(autoattack)
coroutine.resume(autoattack)
stop_autoattack()
coroutine.resume(autoattack)
coroutine.resume(autoattack)
Very often, coroutines let you keep code more readable, without turning inside out with lots of explicit "state" variables. We still need to have some "higher up" code calling coroutine.resume though, just like we needed to have some higher level code calling autoattack_step.
Ok, so specific to Logitech's implementation of lua in the Logitech Gaming Software suite, you need to use polling.
Once you press a G-key (mouse, pad or keyboard) the OnEvent() function is called. Once inside on event no new OnEvent() events can be called until you exit, your process will become 'stuck' in any loop (as it can't exit the loop, it can't exit the OnEvent() call.
What you need is an interrupt to poll for.
There are three:- IsMouseButtonPressed( button), IsMKeyPressed( key ), IsModifierPressed( modifier ).
If you want your routiene to run while you hold the (any specified) mouse button, you can use IsMouseButtonPressed(n) thus:-
while IsMouseButtonPressed(n) do
doStuff()
end
If you wish to to say, have a toggle switch to start firing (ie: to auto-press a mouse button), then you have to use one of the other two available interrupts, ie:-
PressMouseButton(n);
while not IsModifierPressed("ctrl") do
doStuff()
end
Here your loop will run until you hold down the ctrl key. So not a puristic toggle switch (a G-key to turn on and ctrl to turn off), but passable I believe.
Note:- after further playing, er, testing, I have found IsMouseButtonPressed(n) is independent of PressMouseButton(n), rather this is read from the i/o device, so you can use IsMouseButtonPressed as the interrupt for auto-mouse pressing.
Using a G-Key to kick the action off and a mouse click to interrupt (end) the action , (or you could use both mouse and/or modifier).

Resources