Turn GUI on and off depending on if player is in region - roblox

I have a script working for a rounds based game. It starts with a lobby and an intermission timer of 30 seconds. Then teleports players into a chosen map within a region I defined. During the round it counts down and either ends the round after 180 seconds or if 1 player is left. Players who are killed (or remain at the end of the 180 seconds) are teleported back to the lobby and the cycle continues. I used the script below and it works well. I would like to leverage the table / array from this script to identify players who are in the region and turn off / make invisible a Spectate GUI that I would like to make visible only to players in the lobby (ie. NOT in the region I defined that encompasses the various round maps). But I'm having trouble figuring out how to amend this script. Any help would be greatly appreciated! thanks. CODE below:
'''
while true do -- repeats forever and calls the functions
wait(2)
intermissionTimer()
chooseMap()
loadMap()
wait(2)
teleportPlayers()
wait(2)
local time = roundLength
while wait(1) do
partsInRegion = workspace:FindPartsInRegion3(region, game.ServerStorage.Maps,3000) -- this returns a table
playersFound = {} -- table players found
for i, part in pairs (partsInRegion) do
if part.Parent:FindFirstChild("Humanoid") ~= nil then
playersFound[part.Parent.Name] = part.Parent -- add players character to table
winner = playersFound[part.Parent.Name].Name
print (winner)
print (i, part) -- 0
end
end
function Length(playersFound)
local counter = 0
for _, v in pairs(playersFound) do
counter =counter + 1
end
return counter
end
if time == 0 then
Status.Value = "Round over!"
workspace.SoundLibrary.Nowinner:Play()
break
elseif Length(playersFound)== 1 then
workspace.SoundLibrary.Winner:Play()
Status.Value = winner.. " wins!"
wait(5)
break
else
Status.Value = time .." seconds left"
time = time - 1
end
end
wait (2)
teleportBack()
deleteMap()
end
'''

At the end of your for-loop, you have a table full of players who are still in the game. You can get a list of all of the players in the game by using the Players service. Each player object is stored as a child there, and you can compare the names of your surviving players against the names of all the players to find who is dead.
local partsInRegion = workspace:FindPartsInRegion3(region, game.ServerStorage.Maps,3000)
local playersFound = {}
-- find all the players still alive
for k, part in pairs(partsInRegion) do
if part.Parent:FindFirstChild("Humanoid") ~= nil then
playersFound[part.Parent.Name] = part.Parent
end
end
-- figure out who is dead
local allPlayers = game.Players:GetChildren()
for i, player in ipairs(allPlayers) do
-- if they are not still in the game, they must be dead
if playersFound[player.Name] == nil then
-- get the Spectate gui, replace this line with your actual gui
local gui = ReplicatedStorage.SpectateGui:Clone()
-- give the dead player the spectate gui, if they don't already have it
if player.PlayerGui[gui.Name] == nil then
gui.Parent = player.PlayerGui
end
end
end

Related

start 2 timers simultaneously in a matlab function

I have a program with 2 timer functions like this (p_maj_input and p_maj_output_motion are equal so the period of both timer is the same):
maj_input = timer('ExecutionMode','fixedRate','Period',p_maj_input,'TasksToExecute', ...
floor(Tmeasurement/p_maj_input)-1,'TimerFcn',{#time_append,p_maj_input,HR_all,freq_HR, ...
BVP_all,freq_BVP,TEMP_all,freq_TEMP,ACC_x_all,ACC_y_all,ACC_z_all,freq_ACC,EDA_all,freq_EDA, ...
folder_all,all_dir,num_dir}); start(maj_input);
maj_output_motion=timer('ExecutionMode','fixedRate','Period',p_maj_output_motion,'TasksToExecute', ...
floor(Tmeasurement/p_maj_output_motion)-1,'TimerFcn',{#output_motion_append, ...
freq_MOTION,freq_mvt_score,freq_walk,p_maj_output_motion,p_maj_output_walk,folder_all,all_dir,num_dir});%,'StartDelay',min(5,p_maj_output_motion)); %startDelay must be min 5 for walk detection start(maj_output_motion);
In each timer callback function there is a loop over subfolders contained in a folder that is selected at the beginning of the program.
output_motion_append(obj,event,freq_MOTION,freq_mvt_score,freq_walk,p_maj_output_motion,p_maj_output_walk,folder_all,all_dir,num_dir)
fprintf('motion %d\n',obj.TasksExecuted)
toc
for folder_index=1:num_dir
[folder_original,folder_fictive] = subfolderFunction(all_dir, folder_all, folder_index);
fileName=strcat(folder_fictive,'\ACC.csv');
[ACC_time, ACC_x, ACC_y, ACC_z] = loadValuesE4_acc(fileName);
% Motion Amount
[agitation,agitation_ts] = identifyAgitation(ACC_x,ACC_y,ACC_z,ACC_time);
agitation=agitation';
len1=length(agitation);
if len1<=freq_MOTION*p_maj_output_motion
i_init1=1;
elseif len1>freq_MOTION*p_maj_output_motion
i_init1=len1-freq_MOTION*p_maj_output_motion+1;
end
writematrix([agitation(i_init1:len1)],strcat(folder_fictive,'\MOTION_output.csv'),'WriteMode','Append');
writematrix([mvt_score(i_init2:len2)],strcat(folder_fictive,'\neurologicScore_output.csv'),'WriteMode','Append');
end
end
Everything works fine if the number of subfolders is lower than 4 : the good values appear in the files on which is carried out the writematrix function. And the timer callback function are are called one after the other, so both timer work simultaneously.
However if there are 5 subfolders or more, it is not the good values and using the debugging I noticed that the first callback function is triggered the number of 'TasksToExecute', and then only the second callback function seems to be called. That is to say the 2 timers don't work simultaneously.
I have tried to increase p_maj_input and p_maj_output_motion to see if the problem is that matlab can't finish to run before another timer callback function is called but still for 5 subfolders I get the same problem.
Does anyone know where my problem is coming from?
This behavior occurs because one timer hasn't finished executing by the time it triggers again, so the second timer never has a chance to execute until the first timer is finished. If you change the ExecutionMode from 'fixedRate' to 'fixedSpacing', then you'll guarantee that there's time for the second timer to execute.
function duelingTimers()
disp('With ExecutionMode = fixedRate')
t1 = timer('ExecutionMode','fixedRate','Period',0.1,'TasksToExecute',5,'TimerFcn',#timerFcn1);
t2 = timer('ExecutionMode','fixedRate','Period',0.1,'TasksToExecute',5,'TimerFcn',#timerFcn2);
cleanup = onCleanup(#()delete([t1,t2]));
function timerFcn1(~,~)
pause(0.2)
disp('Timer 1');
end
function timerFcn2(~,~)
pause(0.2)
disp('Timer 2');
end
start(t1),start(t2)
wait(t1)
wait(t2)
disp(newline)
disp('With ExecutionMode = fixedSpacing')
t1.ExecutionMode = 'fixedSpacing';
t2.ExecutionMode = 'fixedSpacing';
start(t1),start(t2)
wait(t1)
wait(t2)
end

Why isn't the code running. It isn't doing anything inside my loop. | Roblox Studio

None of it's working. Can you please help. This is in Roblox Studio.
local Time = math.floor (game.Lighting:GetMinutesAfterMidnight(480/60))
local intakeAlert = game.StarterGui.Main.IntakeAlert
local prisonerCount = game.ReplicatedStorage.NumPrisoners
local intake = game.ReplicatedStorage.PrisonerIntake -- This is the prisoner intake status
while wait() do
if Time == 8 then -- Checks if it is 8 hours after midnight.
print("Prison Bus Arriving.")
intakeAlert.Visible = true
wait(2)
intakeAlert.Visible = false
end
end
After reading your code, the reason I can say that the reason it is not running is because of this line of code:
if Time == 8 then -- Checks if it is 8 hours after midnight.
The main reason is probably your time variable.
local Time = math.floor (game.Lighting:GetMinutesAfterMidnight(480/60))
First things first, GetMinutesAfterMidnight() doesn't take any parameters. I'm not sure why there is one
Second, you setup your variable at runtime, meaning its value is static. If the ingame time at runtime was 2, then the time variable would remain 2 until the script is stopped.
Here is my fix to this:
local intakeAlert = game.StarterGui.Main.IntakeAlert
local prisonerCount = game.ReplicatedStorage.NumPrisoners
local intake = game.ReplicatedStorage.PrisonerIntake -- This is the prisoner intake status
local debounce -- Make sure this event doesn't fire several times
while true do
local currentTime = math.floor(game.Lighting.ClockTime) -- You can change this to GetMinutesBeforeMidnight if you want. Might have to do some math.
if currentTime == 8 then -- Checks if it is 8 hours after midnight.
if debounce then return end -- Return if the event has already been fired.
debounce = true
print("Prison Bus Arriving.")
intakeAlert.Visible = true
wait(2)
intakeAlert.Visible = false
else
debounce = false -- If its 9 after midnight, debounce will be set to false for the next day.
end
wait() -- You should avoid using this, I suggest changing it to something like RunService.Heartbeat:Wait() but that's your choice.
end

Classes and modules and Lua, oh my

I'm working on a game in Lua, and so far I have everything working with everything in one document. However, to better organize everything, I've decided to expand it into modules, and while I figure I could probably get it working more or less the same, I figure now might be an opportunity to make things a little more clear and elegant.
One example is enemies and enemy movement. I have an array called enemyTable, and here is the code in Update that moves each enemy:
for i, bat in ipairs(enemyTable) do
if bat.velocity < 1.1 * player.maxSpeed * pxPerMeter then
bat.velocity = bat.velocity + 1.1 * player.maxSpeed * pxPerMeter * globalDelta / 10
end
tempX,tempY = math.normalize(player.x - bat.x,player.y - bat.y)
bat.vectorX = (1 - .2) * bat.vectorX + (.2) * tempX
bat.vectorY = (1 - .2) * bat.vectorY + (.2) * tempY
bat.x = bat.x + (bat.velocity*bat.vectorX - player.velocity.x) * globalDelta
bat.y = bat.y + bat.velocity * bat.vectorY * globalDelta
if bat.x < 0 then
table.remove(enemyTable,i)
elseif bat.x > windowWidth then
table.remove(enemyTable,i)
end
end
This code does everything I want it to, but now I want to move it into a module called enemy.lua. My original plan was to create a function enemy.Move() inside enemy.lua that would do this exact thing, then return the updated enemyTable. Then the code inside main.lua would be something like:
enemyTable = enemy.Move(enemyTable)
What I'd prefer is something like:
enemyTable.Move()
...but I'm not sure if there's any way to do that in Lua? Does anyone have any suggestions for how to accomplish this?
Sounds like you just want the metatable of enemyTable to be the enemy module table. Lua 5.1 reference manual entry for metatables
Something like this.
enemy.lua
local enemy = {}
function enemy:move()
for _, bat in ipairs(self) do
....
end
end
return enemy
main.lua
local enemy = require("enemy")
enemyTable = setmetatable({}, {__index = enemy})
table.insert(enemyTable, enemy.new())
table.insert(enemyTable, enemy.new())
table.insert(enemyTable, enemy.new())
enemyTable:move()
Of course you can do it. For what I can see, your Move function processes the table you pass it as an argument and returns another table, in a functional programming fashion, leaving the first table immutate. You just have to set your Move function so that it knows it has to operate on your enemy table instead of creating a new table. So in your module write:
local enemy = {}
-- insert whatever enemy you want in the enemy table
function enemy.Move()
for _, bat in ipairs(enemy) do
--operate on each value of the enemy table
end
--note that this function doesn't have to return anything: not a new enemy table, at least
end
return enemy
And in your love.load function you can call
enemyTable = require "enemymodule"
Then you just have to call enemyTable.Move()

Using fixedRate timer in MATLAB with different data for each interval (trying to replace for loop with timer)

Is there a way to have a MATLAB timer pass different data on each subsequent call to the timer function? My goal is to cycle through intervals at a fixed rate, and the pause function inside a loop is not precise enough.
I have workng MATLAB code that uses a for loop to send data via serial ports, then wait a specified time before the next iteration of the loop. The serial communication varies in speed, so if I specify 300 seconds as the period, the loop actually executes every 340-360 seconds. Here is the existing code:
clear all;
testFile = input('What is the name of the test data file (with extension): ', 's');
measurementData = csvread(testFile);
intervalDuration = input('What is the measurement change period (seconds): ');
intervalNumber = size(measurementData,2);
% Set up the COM PORT communication
sensorComPort = [101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120];
controllerComPort = [121,122,123,124];
for j=1:intervalNumber
tic
fprintf('\nInterval # %2d\n',rem(j,24));
sensorMeasurementPS = [measurementData(1,j),measurementData(2,j),measurementData(3,j),measurementData(4,j),measurementData(5,j), measurementData(6,j),measurementData(7,j),measurementData(8,j),measurementData(9,j),measurementData(10,j), measurementData(11,j),measurementData(12,j),measurementData(13,j),measurementData(14,j),measurementData(15,j), measurementData(16,j),measurementData(17,j),measurementData(18,j),measurementData(19,j),measurementData(20,j)];
serialSensorObj = startsensorPSWithoutReset(sensorComPort, sensorMeasurementPS);
serialSensorObj = changeMeasurement(serialSensorObj, sensorMeasurementPS);
rc = stopsensorPS(serialSensorObj);
controllerMeasurementPS = [measurementData(21,j),measurementData(22,j),measurementData(23,j),measurementData(24,j)];
serialControllerObj = startControllerPSWithoutReset(controllerComPort, controllerMeasurementPS);
serialControllerObj = changeMeasurement(serialControllerObj, controllerMeasurementPS);
rc2 = stopControllerPS(serialControllerObj);
pause(intervalDuration);
t = toc;
fprintf('Elapsed time = %3.4f\n',t);
end
clear serialSensorObj;
clear serialControllerObj;
The serial functions are specified in other files and they are working as intended.
What I need to do is have the serial communication execute on a more precise 5-minute interval. (The actual timing of the commands inside the interval will still vary slightly, but the commands will kick off every 5 minutes over the course of 24 hours. The current version loses time and gets out of sync with another system that is reading the measurements I'm setting by serial port.)
My first thought is to use a MATLAB timer with the fixedRate execution mode, which queues the function at fixed intervals. However, it doesn't appear that I can send the timer function different data for each interval. I thought about having the timer function change a counter in the workspace, similar to j in my existing for loop, but I know that having functions interact with the workspace is not recommended.
Here's what I've come up with so far for the timer method:
function [nextJ] = changeMeasurement_fcn(obj,event,j,sensorComPort,controllerComPort)
tic
fprintf('\nInterval # %2d\n',rem(j,24));
sensorMeasurementPS = [measurementData(1,j),measurementData(2,j),measurementData(3,j),measurementData(4,j),measurementData(5,j), measurementData(6,j),measurementData(7,j),measurementData(8,j),measurementData(9,j),measurementData(10,j), measurementData(11,j),measurementData(12,j),measurementData(13,j),measurementData(14,j),measurementData(15,j), measurementData(16,j),measurementData(17,j),measurementData(18,j),measurementData(19,j),measurementData(20,j)];
serialSensorObj = startSensorPSWithoutReset(sensorComPort, sensorMeasurementPS);
serialSensorObj = changeMeasurement(serialSensorObj, sensorMeasurementPS);
rc = stopSensorPS(serialSensorObj);
controllerMeasurementPS = [measurementData(21,j),measurementData(22,j),measurementData(23,j),measurementData(24,j)];
serialControllerObj = startControllerPSWithoutReset(controllerComPort, controllerMeasurementPS);
serialControllerObj = changeMeasurement(serialControllerObj, controllerMeasurementPS);
rc2 = stopControllerPS(serialControllerObj);
t2 = toc;
fprintf('Elapsed time = %3.4f\n',t2);
and this is how I would call it from the main m file:
t = timer('TimerFcn',#changeMeasurement,'ExecutionMode','fixedRate','period',intervalDuration);
% then I need some code to accept the returned nextJ from the timer function
This feels a bit sloppy so I'm hoping there's a built-in way to have a timer cycle through a data set.
Another idea I had was to keep the for loop but change the pause function to use a value calculated based on how much time would add up to 5 minutes for the iteration.
To summarize my question:
a) Can I have a timer pass different data to the timer function on each iteration?
b) Is that a good way to go about cycling through the intervals in my data on a precise 5-minute interval?
Thanks!
I stumbled on this page: http://www.mathworks.com/company/newsletters/articles/tips-and-tricks-simplifying-measurement-and-timer-callbacks-with-nested-functions-new-online-support-features.html
and learned that timer callback functions can be nested inside other functions (but not regular scripts).
Using that information, I cut my scenario to the basics and came up with this code:
function timerTestMain_fcn
testFile = input('What is the name of the test data file (with extension): ', 's');
testData = csvread(testFile);
intervalDuration = input('What is the voltage change period (seconds): ');
intervalNumber = size(testData,2);
t = timer('ExecutionMode','fixedRate','period',intervalDuration,'TasksToExecute',intervalNumber);
t.TimerFcn = {#timerTest_fcn};
start(t);
wait(t);
delete(t);
function timerTest_fcn(obj,event)
tic
event_time = datestr(event.Data.time);
interval_id = t.TasksExecuted;
data_value = testData(1,interval_id);
txt1 = 'Interval ';
txt2 = num2str(interval_id);
txt3 = ' occurred at ';
txt4 = ' with data value of ';
txt5 = num2str(data_value);
msg = [txt1 txt2 txt3 event_time txt4 txt5];
disp(msg)
t2 = toc;
fprintf('Elapsed time = %3.4f\n',t2);
end
end
The test data file it requests must be a csv containing a row vector. For example, you could put the values 11,12,13,14,15 across the first row of the csv. The output message would then say 'Interval 1 occurred at [time] with data value of 11', 'Interval 2 occurred at [time] with data value of 12', etc.
The key is that by nesting the functions, the timer callback can reference both the test data and the timer attributes contained in the outer function. The TasksExecuted property of the timer serves as the counter.
Thanks to anyone who thought about my question. Comments welcome.

VHDL Timer Synchronous/Asynchronous load speed issue

I am trying to code a i2c like bus on a spartan 6. I have a bunch of states that i time using the folowing counter.
-- Timer --
TimesUp <= true when TmrCnt = 0 else
false when TmrCnt /= 0 else
false;
tmrProc: process(ClkxC, SetTmr, TmrInit)
begin
if (rising_edge(ClkxC)) then
if (SetTmr = '1') then
TmrCnt <= TmrInit;
elsif (TmrCnt > 0) then
TmrCnt <= TmrCnt - 1;
end if;
end if;
end process;
The problem is that my state machine is clocked on the same clock and for some short duration states it just blasts through as if the timer is not set in time.
So I tried this:
-- Timer --
TimesUp <= true when TmrCnt = 0 else
false when TmrCnt /= 0 else
false;
tmrProc: process(ClkxC, SetTmr, TmrInit)
begin
if (SetTmr = '1') then
TmrCnt <= TmrInit;
elsif (rising_edge(ClkxC)) then
if (TmrCnt > 0) then
TmrCnt <= TmrCnt - 1;
end if;
end if;
end process;
Now it simulates just fine, but when I try to implement i get an error message saying that:
This design contains one or more registers/latches that are directly
incompatible with the Spartan6 architecture. The two primary causes of this is
either a register or latch described with both an asynchronous set and
asynchronous reset, or a register or latch described with an asynchronous
set or reset which however has an initialization value of the opposite
polarity (i.e. asynchronous reset with an initialization value of 1).
I really don't know how to make the timer load fast enough without braking the rules of the spartan 6.
The warning has been explicitly described in Xilinx WP309 Targeting and Retargeting Guide for Spartan-6 FPGAs [P9-11].
To reduce cost of the overall architecture, slices in Spartan-6 FPGAs do not have a REV
pin. As a result, flip-flops no longer implement both a set signal and a reset signal. In
addition, a register with a set or reset signal can only have an initialization value of
the same polarity. For example, a flip-flop with an asynchronous reset can only have an
initialization value of 0.
That is to say, the following kinds of registers/latches are NOT RECOMMENDED when using Xilinx Spartan-6 FPGAs:
______|______
| Set |
| |
---| D Q |--- -- 1. a register/latch with both ASYNCHRONOUS
| _ | set and reset signals
---|>Clk Q |o-- -- NOT RECOMMENDED
| |
| Reset |
|___________|
|
-- 2. a register/latch described with an ASYNCHRONOUS set/reset which
however has an initialization value of the opposite polarity
-- The default value of reg is 0 which is the left
-- bound value of the integer type definition.
signal reg: integer range 0 to 7; <-----
|
process (clk, reset) |___ opposite
begin | NOT RECOMMENDED
if (reset = '0') then |
reg <= 7; <-----
elsif ( rising_edge(clk) ) then
reg <= val;
end if;
end process;
Solutions recommended by Xilinx:
1. Remove either the set or reset from all registers and latches
if not needed for required functionality
2. Modify the code in order to produce a synchronous set and/or
reset (both is preferred)
3. Ensure all registers have the same initialization value as the
described asynchronous set or reset polarity
4. Use the -async_to_sync option to transform the asynchronous
set/reset to synchronous operation
(timing simulation highly recommended when using this option)
In your design, you can either initialize TmrCnt to TmrInit or count TmrCnt in an upward direction.
Moving from the first (synchronous) approach to the second (asynchronous set) is rarely the right way to solve the problem; regardless of the Spartan-6 economies on reset logic. Indeed I would justify them on grounds of ... "don't do that".
Instead, look at the statement "The problem is that my state machine is clocked on the same clock and for some short duration states it just blasts through as if the timer is not set in time."
Firstly, there is nothing short duration about I2C signals, unless perhaps this is a multi-hundred MHz derivative of it...
Secondly, one thing VHDL does really well is synchronous design, so "blasting through" without resetting the counter points at something else : possibly the signal assignment rules referred to here.
I suspect this is causing issues where the state machine is setting SetTmr to communicate with the counter in a separate process; so the counter sees SetTmr one cycle later, and that cycle delay is causing the observed mis-behaviour because TimesUp has the wrong value during that cycle.
One answer - a pattern I use a lot - is simply to roll the timer into the SM process itself; then you set it directly and save the handshaking logic and a separate process...
StateMch : process(Clock)
begin
if rising_edge(Clock) then
-- default actions
if Timer > 0 then
Timer <= Timer - 1;
end if;
-- state machine
case State is
when Start_Wait =>
Timer <= My_Delay;
State <= Waiting;
when Waiting =>
if Timer = 0 then
State <= Done;
end if;
when others =>
State <= Start_Wait;
end case;
end if;
end process;
Apart from being simpler and (I find) easier to understand than a huge collection of tiny processes, this allows several states to use the same timer to generate different delays.