Need help on ROBLOX script (Lua) - lua

I`m making a script for my UFO in ROBLOX where whenever the UFO passes overhead it plays an audio. I made a script that goes as follows
while true do
if script.Parent.Parent.Velocity.Magnitude>10 then
if local h = hit.Parent:FindFirstChild("Humanoid")
then script.parent:play()
wait(5)
else
wait()
end
wait()
end
Any corrections would be a real help!
Thanks!

Everything aside, at the root there are a lot of syntax errors as well as the error of implementation, all in all the code block you've given us won't do what you wanted it to.
However, here's a basic idea of what the solution is:
local newThread = coroutine.create(function()
while true do
for i, v in game.Players:GetPlayers()
local playerListener = workspace[v.Name]["Head"]
local ufoListener = workspace.Ufo:FindFirstChild('Listener')
local magnitude = (playerListener.Position - ufoListener.Position).magnitude
if (magnitude > 10) then
script.Parent:play()
else
wait(0.5)
end
end
end
end)
coroutine.resume(newThread)
Essentially, here's the rundown: We're using coroutines so this while loop doesn't yield this thread for all eternity. There are some more complex avenues using bindable events and maybe some server-client handshake where, when fired from the LocalPlayer, it calls an event in the server- but I digress. This should be perfect for your needs without confusing you too much.

Related

Why isn't this Roblox function/script working?

I started with Roblox a few months ago and my only semi-related prior experience is in web development, so you're dealing with a noob here.
I'm having trouble awarding my game's currency to the players of the winning team of a round. Every other aspect of my currency seems to work fine - it displays, can update, saves with datastores etc.
This in-game currency is set up in the same manner as leaderstats (but not as a leaderstats) - it's created under the player at runtime (if that's the proper way of saying it) via a script in SSS.
The function I'm having issues with doesn't seem to do anything, and I've tried about 20 different variations, some of which were radically different from this. The one below is the last one I tried before giving up to seek help here.
function goldToWinningTeam()
local winningTeam = TeamManager:GetWinningTeam()
for i, Player in pairs(Players:GetPlayers()) do
if player.TeamColor == winningTeam.TeamColor then
player.currency.Gold.Value += 100
else
player.currency.Gold.Value += 50
end
end
end
This doesn't produce any output errors or interfere with other game logic as far as I can tell.
At the moment, for testing, the function above is in my main game script (a regular script). Its proper/ideal location, upon getting it to work, is also something I'd appreciate some feedback on. I was thinking either in my TeamManager or PlayerManager module scripts, or possibly my GameCurrecy script, which is a regular script in SSS.
Below are the TeamManager function(s) called from above. I've tried using either. Both work as expected for their intended purpose of displaying a victor at round end. I figured they would also work in this use case.
function TeamManager:GetWinningTeam()
local highestScore = 0
local winningTeam = nil
for _, team in ipairs(Teams:GetTeams()) do
if TeamScores[team] > highestScore then
highestScore = TeamScores[team]
winningTeam = team
end
end
return winningTeam
end
-- Below works identically for displaying victor
function TeamManager:HasTeamWon()
for _, team in ipairs(Teams:GetTeams()) do
if TeamScores[team] >= Configurations.DESTROYS_TO_WIN then
return team
end
end
return false
end
Again, I'm very new to this and it's only a hobby, please forgive any obvious ignorances.

attempt to index nil with 'leaderstats' in roblox studio

local garbage = game.Teams["Glizzy Garbage"]
local player = game.Players.LocalPlayer
if player.leaderstats.Pounds.Value <= 1000 then --this is the line that the output is detecting the error
player.Team = garbage
end
I am trying to make it where when the player reaches a certain amount of 'pounds' then they will automatically receive a roll. I've searched through many youtube videos and haven't found a fix or an alternative way to do this, and I'm not sure why this isn't working. This script is located in the workspace. All help is appreciated.
The LocalPlayer object is only exposed in LocalScripts. Because you're using a Script in the Workspace, you'll have to access the player object another way. It's also a good idea to handle this kind of logic inside a function that is fired any time the Pounds value changes.
Try using the game.Players.PlayerAdded signal :
local garbage = game.Teams["Glizzy Garbage"]
game.Players.PlayerAdded:Connect(function(player)
local Pounds = player.leaderstats.Pounds
Pounds.Changed:Connect(function(value)
if value <= 1000 then
player.Team = garbage
end
end)
end)
Mine is just
local plrStage = plr.leaderstats.Stage.Value
try instead of putting team name put team colour
also use
player.Team.Service = garbage
end)

How to fix an end expected error near eof

I made a cash for kill script in Roblox, but wanted to go further than that and implement a script where when a player has a gamepass, then that player would recieve more cash than another normal player would.
This is for a battle royale styled game in Roblox, and when I playtested it, there were no errors, but the script didn't work.
game.Players.PlayerAdded:connect(function(player)
local folder = Instance.new("Folder",player)
folder.Name = "leaderstats"
local currency1 = Instance.new("IntValue",folder)
currency1.Name = "Cash"
local increment = 50
if game:GetService("MarketplaceService"):PlayerOwnsAsset(player,7382818)then
increment = increment + 50
end
player:WaitForChild("Humanoid").Died:connect(function()
local tag = player.Humanoid:FindFirstChild("creator")
if tag ~= nil then
local killer = tag.Value
if killer ~= nil then
-- Find the killer's leaderstats folder
local killerStats = killer:FindFirstChild("leaderstats")
if killerStats ~= nil then
-- Find the killer's Cash IntValue
local killerCash = killerStats:FindFirstChild("Cash")
-- Increase cash as before
killerCash.Value = killerCash.Value + increment
end
end
end
end)
I expected a VIP player, who has the gamepass, to receive more cash, but when I tested it, no player received any cash for killing another player at all.
How to fix an end expected error near eof
If the Lua interpreter complains about a missing end you`re missing it somewhere.
Read through your code and make sure everything that is supposed to be closed with an end has one. Read through the Lua Reference Manual to find out which keywords need an end.
In your code it's if statements and function definitions. Checking each pair from inside out you'll end up one end) short to close this game.Players.PlayerAdded:connect(function(player) as mentioned in the comments.

Remote event problems

I'm making a game using ROBLOX about the tank battle system of Dragon Quest Heroes Rocket Slime (although not using 100% GUI's)
Since I didn't know how to make ammo become locked onto a path in normal ROBLOX, I decided to use a gui to show the ammo "firing"
To do this, I have a remote event that fires a function inside the main script of the GUI system when ammo is loaded
cannon.Touched:connect(function(v)
if fireable[v.Name] and v.Parent == workspace then
event:FireAllClients("Left",v.Name)
v:Destroy()
end
end)
Then, the GUI gets the correct sprite for the ammo loaded and fires it out of the right tank (the first argument in the FireAllClients part)
This is one of the two if statements for firing ammo (the other one is literally the same except that it's for the right side tank)
local tank = tankFiring == "Left" and tank1 or tankFiring == "Right" and tank2
if tank == tank1 then
print("yo!")
script.Fire:Play()
local ammoFrame = sp.Ammo:Clone()
ammoFrame.Parent = tank
ammoFrame.Visible = true
ammoFrame.Position = UDim2.new(0,120,0,68)
playAnimation("Cannon Fire",UDim2.new(0,120,0,68-25),tank.Frame)
ammoFrame.Image = ammoTypes[type]["img"]
ammoFrame.Size = ammoTypes[type]["Size"]
repeat
wait(.1)
ammoFrame.Rotation = ammoTypes[type]["Rotatable"] == true and ammoFrame.Rotation + 15 or 0
ammoFrame.Position = ammoFrame.Position + UDim2.new(0,1,0,0)
until
tank2:FindFirstChild("Ammo") and isTouching(ammoFrame,tank2:GetChildren()[3]) or isTouching(ammoFrame,tank2) or ammoFrame == nil
if tank2:FindFirstChild("Ammo") and isTouching(ammoFrame,tank2:GetChildren()[3]) then
script.Collision:Play()
local lastAmmoPos = ammoFrame.Position
playAnimation("Explosion",lastAmmoPos-UDim2.new(0,15,0,25),tank.Frame)
ammoFrame:Destroy()
tank2:GetChildren()[3]:Destroy()
end
if isTouching(ammoFrame,tank2) then
script.Collision:Play()
ammoFrame:Destroy()
workspace["Tank2"].Health.Value = workspace["Tank2"].Health.Value - ammoTypes[type]["dmg"]
end
end
The problem with this, is that if a player joins AFTER the ammo has been shot, they will not see the ammo on the GUI
Is there anyway to fix this? I can't just FireAllClients again, since that'll just fire another piece of ammo for all the players.
Have a service that keeps track of what ammo is in what state. Then all clients first asks the servers of current ammo states when joining, and then subscribes to further changes.

Easiest way to make lua script wait/pause/sleep/block for a few seconds?

I cant figure out how to get lua to do any common timing tricks, such as
sleep - stop all action on thread
pause/wait - don't go on to the next
command, but allow other code in the
application to continue
block - don't go on to next command until the
current one returns
And I've read that a
while os.clock()<time_point do
--nothing
end
eats up CPU time.
Any suggestions? Is there an API call I'm missing?
UPDATE: I wrote this question a long time ago trying to get WOW Lua to replay actions on a schedule (i.e. stand, wait 1 sec, dance, wait 2 sec, sit. Without pauses, these happen almost all in the same quarter second.) As it turned out WOW had purposely disabled pretty much everything that allows doing action on a clock because it could break the game or enable bots. I figured to re-create a clock once it had been taken away, I'd have to do something crazy like create a work array (with an action and execution time) and then register an event handler on a bunch of common events, like mouse move, then in the even handler, process any action whose time had come. The event handler wouldn't actually happen every X milliseconds, but if it was happening every 2-100 ms, it would be close enough. Sadly I never tried it.
[I was going to post this as a comment on John Cromartie's post, but didn't realize you couldn't use formatting in a comment.]
I agree. Dropping it to a shell with os.execute() will definitely work but in general making shell calls is expensive. Wrapping some C code will be much quicker at run-time. In C/C++ on a Linux system, you could use:
static int lua_sleep(lua_State *L)
{
int m = static_cast<int> (luaL_checknumber(L,1));
usleep(m * 1000);
// usleep takes microseconds. This converts the parameter to milliseconds.
// Change this as necessary.
// Alternatively, use 'sleep()' to treat the parameter as whole seconds.
return 0;
}
Then, in main, do:
lua_pushcfunction(L, lua_sleep);
lua_setglobal(L, "sleep");
where "L" is your lua_State. Then, in your Lua script called from C/C++, you can use your function by calling:
sleep(1000) -- Sleeps for one second
If you happen to use LuaSocket in your project, or just have it installed and don't mind to use it, you can use the socket.sleep(time) function which sleeps for a given amount of time (in seconds).
This works both on Windows and Unix, and you do not have to compile additional modules.
I should add that the function supports fractional seconds as a parameter, i.e. socket.sleep(0.5) will sleep half a second. It uses Sleep() on Windows and nanosleep() elsewhere, so you may have issues with Windows accuracy when time gets too low.
You can't do it in pure Lua without eating CPU, but there's a simple, non-portable way:
os.execute("sleep 1")
(it will block)
Obviously, this only works on operating systems for which "sleep 1" is a valid command, for instance Unix, but not Windows.
Sleep Function - Usage : sleep(1) -- sleeps for 1 second
local clock = os.clock
function sleep(n) -- seconds
local t0 = clock()
while clock() - t0 <= n do
end
end
Pause Function - Usage : pause() -- pause and waits for the Return key
function pause()
io.stdin:read'*l'
end
hope, this is what you needed! :D - Joe DF
for windows you can do this:
os.execute("CHOICE /n /d:y /c:yn /t:5")
It doesn't get easier than this. Sleep might be implemented in your FLTK or whatever, but this covers all the best ways to do standard sort of system sleeps without special event interrupts. Behold:
-- we "pcall" (try/catch) the "ex", which had better include os.sleep
-- it may be a part of the standard library in future Lua versions (past 5.2)
local ok,ex = pcall(require,"ex")
if ok then
-- print("Ex")
-- we need a hack now too? ex.install(), you say? okay
pcall(ex.install)
-- let's try something else. why not?
if ex.sleep and not os.sleep then os.sleep = ex.sleep end
end
if not os.sleep then
-- we make os.sleep
-- first by trying ffi, which is part of LuaJIT, which lets us write C code
local ok,ffi = pcall(require,"ffi")
if ok then
-- print("FFI")
-- we can use FFI
-- let's just check one more time to make sure we still don't have os.sleep
if not os.sleep then
-- okay, here is our custom C sleep code:
ffi.cdef[[
void Sleep(int ms);
int poll(struct pollfd *fds,unsigned long nfds,int timeout);
]]
if ffi.os == "Windows" then
os.sleep = function(sec)
ffi.C.Sleep(sec*1000)
end
else
os.sleep = function(sec)
ffi.C.poll(nil,0,sec*1000)
end
end
end
else
-- if we can't use FFI, we try LuaSocket, which is just called "socket"
-- I'm 99.99999999% sure of that
local ok,socket = pcall(require,"socket")
-- ...but I'm not 100% sure of that
if not ok then local ok,socket = pcall(require,"luasocket") end
-- so if we're really using socket...
if ok then
-- print("Socket")
-- we might as well confirm there still is no os.sleep
if not os.sleep then
-- our custom socket.select to os.sleep code:
os.sleep = function(sec)
socket.select(nil,nil,sec)
end
end
else
-- now we're going to test "alien"
local ok,alien = pcall(require,"alien")
if ok then
-- print("Alien")
-- beam me up...
if not os.sleep then
-- if we still don't have os.sleep, that is
-- now, I don't know what the hell the following code does
if alien.platform == "windows" then
kernel32 = alien.load("kernel32.dll")
local slep = kernel32.Sleep
slep:types{ret="void",abi="stdcall","uint"}
os.sleep = function(sec)
slep(sec*1000)
end
else
local pol = alien.default.poll
pol:types('struct', 'unsigned long', 'int')
os.sleep = function(sec)
pol(nil,0,sec*1000)
end
end
end
elseif package.config:match("^\\") then
-- print("busywait")
-- if the computer is politically opposed to NIXon, we do the busywait
-- and shake it all about
os.sleep = function(sec)
local timr = os.time()
repeat until os.time() > timr + sec
end
else
-- print("NIX")
-- or we get NIXed
os.sleep = function(sec)
os.execute("sleep " .. sec)
end
end
end
end
end
For the second request, pause/wait, where you stop processing in Lua and continue to run your application, you need coroutines. You end up with some C code like this following:
Lthread=lua_newthread(L);
luaL_loadfile(Lthread, file);
while ((status=lua_resume(Lthread, 0) == LUA_YIELD) {
/* do some C code here */
}
and in Lua, you have the following:
function try_pause (func, param)
local rc=func(param)
while rc == false do
coroutine.yield()
rc=func(param)
end
end
function is_data_ready (data)
local rc=true
-- check if data is ready, update rc to false if not ready
return rc
end
try_pause(is_data_ready, data)
I would implement a simple function to wrap the host system's sleep function in C.
Pure Lua uses only what is in ANSI standard C. Luiz Figuereido's lposix module contains much of what you need to do more systemsy things.
require 'alien'
if alien.platform == "windows" then
kernel32 = alien.load("kernel32.dll")
sleep = kernel32.Sleep
sleep:types{ret="void",abi="stdcall","uint"}
else
-- untested !!!
libc = alien.default
local usleep = libc.usleep
usleep:types('int', 'uint')
sleep = function(ms)
while ms > 1000 do
usleep(1000)
ms = ms - 1000
end
usleep(1000 * ms)
end
end
print('hello')
sleep(500) -- sleep 500 ms
print('world')
I agree with John on wrapping the sleep function.
You could also use this wrapped sleep function to implement a pause function in lua (which would simply sleep then check to see if a certain condition has changed every so often). An alternative is to use hooks.
I'm not exactly sure what you mean with your third bulletpoint (don't commands usually complete before the next is executed?) but hooks may be able to help with this also.
See:
Question: How can I end a Lua thread cleanly?
for an example of using hooks.
You can use:
os.execute("sleep 1") -- I think you can do every command of CMD using os.execute("command")
or you can use:
function wait(waitTime)
timer = os.time()
repeat until os.time() > timer + waitTime
end
wait(YourNumberHere)
You want win.Sleep(milliseconds), methinks.
Yeah, you definitely don't want to do a busy-wait like you describe.
It's also easy to use Alien as a libc/msvcrt wrapper:
> luarocks install alien
Then from lua:
require 'alien'
if alien.platform == "windows" then
-- untested!!
libc = alien.load("msvcrt.dll")
else
libc = alien.default
end
usleep = libc.usleep
usleep:types('int', 'uint')
function sleep(ms)
while ms > 1000 do
usleep(1000)
ms = ms - 1000
end
usleep(1000 * ms)
end
print('hello')
sleep(500) -- sleep 500 ms
print('world')
Caveat lector: I haven't tried this on MSWindows; I don't even know if msvcrt has a usleep()
I started with Lua but, then I found that I wanted to see the results instead of just the good old command line flash. So i just added the following line to my file and hey presto, the standard:
please press any key to continue...
os.execute("PAUSE")
My example file is only a print and then a pause statment so I am sure you don't need that posted here.
I am not sure of the CPU implications of a running a process for a full script. However stopping the code mid flow in debugging could be useful.
I believe for windows you may use: os.execute("ping 1.1.1.1 /n 1 /w <time in milliseconds> >nul as a simple timer.
(remove the "<>" when inserting the time in milliseconds) (there is a space between the rest of the code and >nul)
cy = function()
local T = os.time()
coroutine.yield(coroutine.resume(coroutine.create(function()
end)))
return os.time()-T
end
sleep = function(time)
if not time or time == 0 then
time = cy()
end
local t = 0
repeat
local T = os.time()
coroutine.yield(coroutine.resume(coroutine.create(function() end)))
t = t + (os.time()-T)
until t >= time
end
You can do this:
function Sleep(seconds)
local endTime = os.time() + seconds
while os.time() < endTime do
end
end
print("This is printed first!")
Sleep(5)
print("This is printed 5 seconds later!")
You could try this:
function wait(seconds)
local start = os.time()
repeat until os.time() > start + seconds
end
wait(5) print("cargo. Cargo what? Cargo, storage.") -- waits 5 seconds and then prints
It worked for me in Lua CLI.
This should work:
os.execute("PAUSE")

Resources