How to hold a value for a period of time - lua

New to Lua scripting, so hopefully I'm using the right terminology to describe this, please forgive if I'm not, I'll get better over time....
I'm writing code for a game using Lua. And I have a function that sets a value. Now I need to "hold" this value for a set period of time after which it gets set to another value.
I'm trying to replicate this behavior:
Imagine a car-start key.
0 = off
1 = ignition on
2 = ignition on + starter -- this fires to get the engine to ignite. In real-life, this "start" position 2 is HELD while the starter does its thing, then once the engine ignites, you'd let go and it springs back to = 1 to keep the ignition on while the engine keeps running.
Now imagine instead, a start button and it can not NOT be pushed in and held in position=2 (like the key) for the time required for the starter to ignite the engine. Instead, once touched, that should cause the starter to runs for a set period of time in position 2 and when it senses a certain =>RPM, the starter stops and goes back to position 1, and leaves the engine running.
Similarly, I have a button that when "touched" fires the starter, but that starter event as expected goes from 0 to 2 and back to 1 in a blink. If I set it to be 2 then it fires forever.
I need to hold its phase 2 position in place for 15 seconds, then it can get back to 1
What I have:
A button that has an animated state. (0 off, 1, 2).
If 0 then 1, if 1 then 2 using phase==2 as the spring step from 2 back to 1
At position == 2, StarterKey = 2
No syntax issues.
The StarterKey variable is triggered to be =2 at position 2 -- BUT not long enough for the engine to ignite. I need StarterKey=2 to stay as a 2 for 15 seconds. Or, do I need to time the entire if phase==2 stage to be held for longer? Not sure.
What should I be looking at please? Here's a relevant snip..
function EngineStart()
if phase == 0 then
if ButtonState == 0 then
ButtonState = 1
StarterKey = 2 -- I tried adding *duration = 15* this event but that does not work
end
end
end
I also have the subsequent elseif phase == 2 part for when the button is in position == 2 so it springs back to 1 -- that all works fine.
How do I, or what do I need to use, to introduce time for my events and functions? I don't want to measure time, but set event time.
Thanks!

Solved this by watching a Lua tutorial video online (taught me how) + discovered that the sim has a timer function that I then used to set the number of seconds ("time") that the starter key-press stayed in its 2 position, which then fired it long enough for the igniters to do their work. (what to use)
QED :)) HA!

Related

(Lua) How do I increment a variable every time one of three if statements runs?

I'm building a moving and sensing bot in CoppelliaSim for school. CopelliaSim uses Lua for scripting. Basically every time the bot's forward sensors hit something, one of three if statements will run. I want it to count how many times any of these if statements runs, and once that count gets to a certain amount (like 20), I'll run something else, which will do the same thing (find collisions, add to the count, reach an amount, and switch back to the first).
i=0
result=sim.readProximitySensor(noseSensor) -- Read the proximity sensor
-- If we detected something, we set the backward mode:
if (result>0) then backUntilTime=sim.getSimulationTime()+3
print("Collision Detected")
i=i+1
print(i)
end
result=sim.readProximitySensor(noseSensor0) -- Read the proximity sensor
-- If we detected something, we set the backward mode:
if (result>0) then backUntilTime=sim.getSimulationTime()+3
print("Collision Detected")
i=i+1
print(i)
end
result=sim.readProximitySensor(noseSensor1) -- Read the proximity sensor
-- If we detected something, we set the backward mode:
if (result>0) then backUntilTime=sim.getSimulationTime()+3
print("Collision Detected")
i=i+1
print(i)
end
Above is the start of a function and one of the three If statements. I'm printing just to see if it actually increments. It is printing, but it is not incrementing (just 1 over and over). This bot has 3 sensors on it (an if statement for each sensor) and it adds 1 to i for the first collision and ignores the rest, even if it's from the same sensor. I feel like my problem is just some simple syntax issue with Lua that I don't know and can't find how to properly fix.
I'm happy to provide more code if this little snippet was not sufficient to answer this question.
Assuming that you have a looping function such as sysCall_actuation which is being executed per simulation step. As Joseph Sible-Reinstate Monica has already stated, you are setting your variable i back to zero every time a simulation step is executed. To achieve your goal, you would have to set your variable to 0 outside your function. There are two appropriate approaches to achieve that:
Define the variable outside any function, in the beginning of your file (or before you define any function that uses your variable e.g right before the definition of sysCall_actuation).
-- Beginning of the file.
local i = 0
..
function sysCall_actuation()
..
i = i + 1
..
end
Define your variable in sysCall_init function, which is the appropriate approach in CoppeliaSim.
function sysCall_init()
i = 0
..
end
Finally, you can use your variable in your sysCall_actuation function with basic comparison operations:
function sysCall_actuation()
..
if i > 20 then
i = 0 -- Reset 'i' so this function will not be running every step again and again.
-- Do something here.
..
end
As a side note, practice using local variables whenever you can, to keep the memory clean and avoid having ambiguous variables.

Getting the value of an "IntValue" always gets default value

I am a student and I am trying to get the value of an "IntValue" to use has level, what I mean by this is that I need to have a skill level for each individual player and use this skill level to multiply the amount of damage the skill does.
for example: Skill level is 5
the damage should be: baseDamage * SkillLevel
in my case. base damage is 2 so the end result should be 10 damage.
but when I try doing this whit code it doesn't work. (I'm not the best at LUA and I'm fairly new to stack so I apologize in advance)
Code (So far I got this):
local XP = 0 --Exp Amount
local LevelValue = player.Backpack.ScriptStorage.Player.SkillLevel.Value --Gets the value of the skill level from the "IntValue"
--Other code that I don't want to show (it just checks if a remote event has fired the server, and it adds .5 to the XP every time it fires)
--This is the line that should add 1 to the level
LevelValue = LevelValue + 1
--But everytime it gets to 2 it simply gets set back to 1 (the default level)
I just showed the relevant pieces of code. everything that was not relevant to this wasn't shown (except for: XP = XP + .5 which is in the code I'm not showing)
hope this helps figure out what the problem is. as said above: "I'm not the best at LUA and I'm fairly new to stack so I apologize in advance"
In your code, you store SkillLevel.Value into the LevelValue local variable. This takes a snapshot of that value and stores it in the variable. So when you modify the local variable, you are not updating the IntValue object that is storing SkillLevel.
When you want to update SkillLevel, you need to update the IntValue directly :
local SkillLevel = player.Backpack.ScriptStorage.Player.SkillLevel
local LevelValue = SkillLevel.Value
-- .. do some other stuff
-- add 1 to the level
SkillLevel.Value = SkillLevel.Value + 1

Is there a reason why this code is not outputting a worth

Problem
Hello, StackOverflow community! I am working on this Lua game, and I was testing to see if it would change the text on my TextLabel to the Bitcoins current worth, I was utterly disappointed when nothing showed up.
I have tried to do research on Google, and my code seems to be just right.
Code
Change = false
updated = false
while Change[true] do --While change = true do
worth = math.random(1,4500) --Pick random number
print('Working!') --Say its working
Updated = true --Change the updated local var.
end --Ending while loop
script.Parent.TextLabel.Text.Text = 'Bitcoin is currently worth: ' .. worth
--Going to the Text, and changing in to a New worth.
while Updated[false] do --While updated = false do
wait(180) --Wait
Change = true --After waits 3 minutes it makes an event trigger
end -- Ending while loop
wait(180) --Wait
Updated = false --Reseting Script.
I expect the output on the Label to be a random number.
I can't really speak to roblox, but there are a couple of obvious problems with your code:
Case
You have confusion between capitalized ("Updated", "Change") and lowercase ("updated", "change" [in commented while statement]), which will fail. See, for example:
bj#bj-lt:~$ lua
Lua 5.2.4 Copyright (C) 1994-2015 Lua.org, PUC-Rio
> Updated = true
> print(Updated)
true
> print(updated)
nil
So be super-careful about what identifiers you capitalize. In general, most programmers leave variables like that in all-lowercase (or sometimes things like camelCase). I suppose there might be some oddball lua runtime out there that is case-insensitive, but I don't know of one.
Type misuse.
Updated is a boolean (a true/false value), so the syntax:
while Change[true] do
...is invalid. See:
> if Updated[true] then
>> print("foo")
>> end
stdin:1: attempt to index global 'Updated' (a boolean value)
stack traceback:
stdin:1: in main chunk
[C]: in ?
Note also that the "While change == true do" is also wrong because of case ("While" is not valid lua, but "while" is).
Lastly:
Lack of threading.
You have basically two different things that you're trying to do at once, namely randomly change the "worth" variable as fast as possible (it's in a loop) and see a set a label to match it (it looks like you probably want it to change constantly). This requires two threads of operation (one to change worth and another to read it and stick it on the label). You've written this like you're assuming you have a spreadsheet or something and that. What your code is actually doing is:
Setting some variables
Updating worth indefinitely, printing 'Working!' a bunch, and...
Never stopping
The rest of the code never runs, because the rest of the code isn't in a background thread (basically the first bit monopolizes the runtime and never yields to everything else).
Lastly, even if the top code was running in the background, you only set the Text label one-time to exactly "Bitcoin is currently worth: 3456" (or some similar number) one time. The way this is written there won't be any updates thereafter (and, if it runs once before the other thread has warmed up, it might not be set to anything useful at all).
My guess is that your runtime is spitting out errors left and right due to the identifier problems and/or is running in a tight infinite loop and never actually getting to the label refresh logic.
BJ Black has given an excellent description of the issues with the syntax, so I'll try to cover the Roblox piece of this. In order for this kind of thing to work properly in a Roblox game, here are some assumptions to double check :
Since we are working with a TextLabel, is it inside a ScreenGui? Or a SurfaceGui?
If it's in a ScreenGui, make sure that ScreenGui is in StarterGui, and is this code in a LocalScript
If it's in a SurfaceGui, make sure that SurfaceGui is adorning a Part and this code
is in a Script
After you checked all those pieces, maybe this is closer to what you were thinking :
-- define the variables we're working with
local textLabel = script.Parent.TextLabel
local worth = 0
-- create an infinite loop
spawn(function()
while true do
--Pick random number
worth = math.random(1,4500)
-- update the text of the label with the new worth
textLabel.Text = string.format("Bitcoin is currently worth: %d", worth)
-- wait for 3 minutes, then loop
wait(180)
end
end)
I removed Updated and Changed because all they were doing was deciding whether or not to change the value. The flow of your loop was:
do nothing and display an undefined number. Wait 3 minutes
update the number, display it, wait 6 minutes
repeat 1 and 2.
So hopefully this is a little clearer and closer to what you were thinking.

Script stops after a few seconds

I have this exploit for Murder Mystery 2.
It is a tpcoins and esp exploit. When I enable the tpcoins it will turn off after a few seconds. Is there any way of making it so it stays on?
Here's the code:
function enableTpCoin()
if nameMap ~= "" and wp[nameMap] ~= nil then
if lplr.PlayerGui.MainGUI.Game.CashBag:FindFirstChild("Elite") then
tpCoin(10)
elseif lplr.PlayerGui.MainGUI.Game.CashBag:FindFirstChild("Coins") then
tpCoin(15)
end
end
Trigger to start the script is q.
Short answer, you can't. Since this is script related I'll answer your question.
So each round, the player can only earn 10 coins, and 15 if they have purchased the "Elite" gamepass.
This meaning that the game physically doesn't allow you to add anymore per round. You'll have to execute the code at the launch of every round.
The game has FE, so it's most likely that the original developer of the game has specified the remote events to only accept 10 or 15 coins depending on the boolean value whether the user is "Elite" or not.
Even if Universal Link says the truth, here's the solution.
Create a new function. In that function, do a while loop with a interval (use wait(.1)), and in that while loop, call enableTpCoin().
Now, call spawn() and pass the function you created as an argument.
The code should look like this:
function _loop()
while wait(.1) do
enableTpCoin()
end
end
spawn(_loop)

Problems interpreting a square wave

I'm trying to use an ESP8266 SoC to read a water flow sensor that is said to produce a square wave as output. I thought it would be a simple matter of using a GPIO port in interrupt mode, to count rising edge transitions -- and in fact that initially seemed to work. Then I upgraded the firmware from 0.96 to 1.5 and it has since ceased to work, I see no transitions when the wheel spins anymore.
However, if I run a wire to the pin [for the GPIO I'm using] and touch it to VCC momentarily, the interrupt routine is called as expected, so I know the sensor is wired to the right pin, and the interrupt routine is registered correctly. My code:
function intCb(level)
SpinCount = SpinCount + 1
local levelString = "up"
if level == gpio.HIGH then
levelString = "down"
end
gpio.trig(pin, levelString, intCb)
end
gpio.write(pin, 0)
gpio.trig(pin, "up", intCb)
gpio.mode(pin, gpio.INT, gpio.FLOAT)
So what am I missing? Do I need more support circuitry to read a square wave as input? If so then how did it work initially?
For anything that involves hardware it's really hard to give a definite answer here on SO. In most cases one bases it on hints (and hunches sometimes). A few ideas:
gpio.FLOAT should probably be gpio.PULLUP instead (unless you have an external pull-up resistor).
Your setup doesn't seem to be fundamentally different from e.g. using a push button or a switch to trigger some event. Hence, you probably want to use some kind of debounce or throttle function.
Since you seem to be interested in both rising and falling edges (as you switch between up and down) you might just as well listen for both, no?
So, assuming I drew the right conclusions something like the following generic skeleton may prove to be useful:
-- inspired by https://github.com/hackhitchin/esp8266-co-uk/blob/master/tutorials/introduction-to-gpio-api.md
-- and http://www.esp8266.com/viewtopic.php?f=24&t=4833&start=5#p29127
local pin = 4 --> GPIO2
function debounce (func)
local last = 0
local delay = 5000
return function (...)
local now = tmr.now()
local delta = now - last
-- if delta < 0 then delta = delta + 2147483647 end; proposed because of delta rolling over
if delta < delay then return end;
last = now
return func(...)
end
end
function onChange ()
print('The pin value has changed to '..gpio.read(pin))
end
gpio.mode(pin, gpio.INT, gpio.PULLUP) -- see https://github.com/hackhitchin/esp8266-co-uk/pull/1
gpio.trig(pin, 'both', debounce(onChange))
I solved this using a 555 timer chip as a schmitt trigger:

Resources