I am working on a game where a player is randomly selected to be the beast and has to kill the entire investigator team.
But I am having issues with the game recognizing that the entire investigator team is dead.
I've inserted my code below;
function playerAlive()
local activePlayers = game.Workspace.ImportantBlock:GetAttribute("numPlayers")
local inGame = game.Workspace.ImportantBlock:GetAttribute("inGame")
local playerTeam = game.Players.LocalPlayer.Team:GetAttribute()
if playerTeam(Investigator)==0 then
game.Workspace.ImportantBlock:SetAttribute("inGame", false)
end
wait(1)
playerAlive()
end
(I connected important values to costume attributes within a block I named "ImportantBlock" because I am having issues with global variables, so far it caused no problems.)
There are two lines which are problematic:
local playerTeam = game.Players.LocalPlayer.Team:GetAttribute()
if playerTeam(Investigator)==0 then
What you seem to want to do is to check how many players are in the "Investigator" team. However, you're trying to call the playerTeam variable (as a function) with an argument, called Investigator, and comparing that.
playerTeam will never be a function (attributes can't be functions). Besides, a GetAttribute call without arguments will error.
The way to count the players in a team is the following:
-- this should probably be at the top of your file, but it works anywhere
local Teams = game:GetService("Teams")
local Players = game:GetService("Players")
local InvestigatorTeam = Teams["Investigator"]
-- in your function:
local count = 0
for _, player in ipairs(Players:GetPlayers()) do
if player.Team == InvestigatorTeam then
count += 1
end
end
if count == 0 then
--no players left
end
P.S. You're setting yourself up with a nice stack overflow error here. You keep calling the playerAlive function in itself until there are no players. If you keep doing this long enough, the stack will get filled up and your script will crash.
Your can avoid this like so:
function countPlayers()
local count = 0
for _, player in ipairs(Players:GetPlayers()) do
if player.Team == InvestigatorTeam then
count += 1
end
end
return count
end
function checkGameEnded()
while true do
if countPlayers() == 0 then
game.Workspace.ImportantBlock:SetAttribute("inGame", false)
end
task.wait(1)
end
end
One final note: don't use wait(), use task.wait(). The former is old, poorly implemented, inconsistent and most importantly, deprecated. The newer version uses heartbeats to count time.
One more final note: use workspace instead of game.Workspace.
Related
I'm trying to implement a system in Roblox Studio that allows a player to cause damage to all players nearby when they jump. I'm trying to develop code that is triggered when the player jumps, and as they land, 10 damage is caused to all players (and dummies for testing purposes) nearby. I've tried three or four different approaches, but none of them seem to work. Here's the latest version of my code:
function onJump(player)
-- Get the player's position
local playerPosition = player.Character.HumanoidRootPart.Position
-- Find all players and dummys within a 5 block radius of the player
local objectsInRange = game:GetService("Workspace"):GetDescendants()
local objectsToDamage = {}
for _, object in pairs(objectsInRange) do
if object:IsA("Player") or (object:IsA("Model") and object.Name == "RespawnDummy") then
local objectPosition = object.PrimaryPart.Position
local distance = (playerPosition - objectPosition).Magnitude
if distance <= 5 then
table.insert(objectsToDamage, object)
end
end
end
-- Damage all players and dummys within range
for _, objectToDamage in pairs(objectsToDamage) do
if objectToDamage:IsA("Player") then
objectToDamage.Character.Humanoid:TakeDamage(10)
elseif objectToDamage:IsA("Model") then
objectToDamage:BreakJoints()
end
end
end
-- Connect the function to the player's Jump event
game.Players.Player.Character.Humanoid.Jump:Connect(onJump)
The biggest challenge seems to be simply having the script identify when a player jumps. I'm not getting any error messages - but I'm also not getting any output if I add a 'print' command inside this function, so it doesn't look as though the jump is being picked up at all.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Like in the title, i am looking for a script that can do that. If someone can repair this script I'll be happy :D
function onTouched(part)
local h = part.Parent:findFirstChild("Humanoid")
if h ~= nil then
if player.parent.torso.roblox.Texture == "https://web.roblox.com/Bloxxer-item?id=1028595" then
script.Parent.Check.Transparency = 0
wait (2)
script.Parent.Check.Transparency = 1
end
end
end
script.Parent.Touched:connect(onTouched)
If you cannot find any free-model that either does what you want, or are editable; here we go:
Because we are referencing script.Parent often, lets make a variable:
local Block = script.Parent
Also lets avoid putting constants like urls in the code body by making variable for that too:
local TShirtTexture = "http://www.roblox.com/asset/?version=1&id=1028594"
Note that the t-shirt texture link differs from the item link. I think the Bloxxer texture is http://www.roblox.com/asset/?version=1&id=1028594. To find the link, join the game in studio with the t-shirt on and inspect the t-shirt
We also need a debouncer
Then i like anonymous functions better if you do not really need to reference it outside:
Block.Touched:connect(function(Part)
-- code goes here
end)
The line part.Parent:findFirstChild might be unsafe as part.Parent might be nil if the part was removed after touching but before the code runs, so it is best to check it first (some VIP doors used to break if you shoot at them because of this). Same with the other stuff, check that it exists, else the code might break at some point.
Next, the character Torso is capitalized. Also, the t-shirt is in the character, not the player. And throw in some variables
And finally everything together:
-- Put some variables
local Block = script.Parent
local TShirtTexture = "http://www.roblox.com/asset/?version=1&id=1028594"
-- Debounce variable
local Debounce = false
-- Use anonymous function
Block.Touched:connect(function(Part)
-- Assume that the Part is a BodyPart, thus the parent should be the character
local Character = Part.Parent
-- Ensure that our assumption is correct
if Character == nil or Character:findFirstChild("Humanoid") == nil then return end
-- Reference to the assumed Torso
local Torso = Character:findFirstChild("Torso")
-- Ensure that it exists
if Torso == nil then return end
-- Reference to the assumed T-Shirt
local TShirt = Torso:findFirstChild("roblox")
-- Ensure that it exists, and that it is a Decal (T-Shirts are decals)
if TShirt == nil or not TShirt:IsA("Decal") then return end
-- Ensure the texture is correct
if TShirt.Texture ~= TShirtTexture then return end
-- Check debounce
if Debounce then return end
Debounce = true
-- Do stuff
Block.Check.Transparency = 0
wait (2)
Block.Check.Transparency = 1
Debounce = false
end)
And if you want to check if the player owns the item, but not have to wear it, check this out
Also, if scripts does not work, remember to post relevant errors
function onTouch(part)
local human = part.Parent:findFirstChild("Humanoid")
if (human == nil) then
return
end
human.Health = human.Health - 10
end
script.Parent.Touched:connect(onTouch)
I'm new to coding in lua, and it is my first time using functions. I want to know what the "part" is equal to so that I can find out how to set up the human variable
local human = part.Parent:findFirstChild("Humanoid")
without using the "part," like what can I plug in so that works without even setting up part, because I want to do something with it in a loop:
local burnaffect = false
--local a = 0
function onTouch(part)
local human = part.Parent:findFirstChild("Humanoid")
if (human == nil and burnaffect == false) then
return
end
a = 0
burnaffect = true
end
script.Parent.Touched:connect(onTouch)
while burnaffect == true do
local part = --????
local human = part.Parent:findFirstChild("Humanoid")
human.Health = human.Health - 10
end
The code may seem confusing but I'm fairly new so I don't know what is best yet.
It looks like what you're trying to do is have a player "set on fire" when they touch a certain brick. The code below does exactly this, and I'll explain it line by line afterwards.
function onTouch(part)
local human = part.Parent:findFirstChild("Humanoid")
if (human == nil) then
return
end
local fire = Instance.new("Fire", part)
while (human.Health > 0) do
human.Health = human.Health - 10
wait(0.1)
end
end
script.Parent.Touched:connect(onTouch)
So, I'll start going through this.
function onTouch(part)
We need to define the function first and give it a name so that we can reference it in the Touched event later. The part parameter is the Part object that touched the script.Parent object and caused the Touched event to fire. So, ROBLOX will automatically call this function whenever something touches your script.Parent and automatically input the Part that touched it as that first parameter, part.
local human = part.Parent:findFirstChild("Humanoid")
This will get the Parent of the Part that touched the block (because if a player is touching the block, it isn't going to give us the Character, it's going to give us an Arm or a Leg in the part variable, because that's the actual Part that touched it, so we need to get that part's Parent. Then, once we have the Parent, we want to get the Humanoid object inside of the Character. Then, we put that Humanoid object inside of the human variable (if we could find one, otherwise we put nil into that human variable).
if (human == nil) then
We want to check if human is nil (which would mean we couldn't find a Humanoid object in the line before this one, which means whatever touched this isn't a real Character, so we'll want to return (which means stop running the function immediately).
local fire = Instance.new("Fire", part)
This line isn't necessary, I added it because I thought if you wanted to simulate burning, this would help. You can leave it out if you'd like. It will create a new Instance of type Fire, and places it inside of the part. That is to say, if a player's Leg touches this part, a Fire will be put inside of that leg, which will make it appear to ignite in flames.
while (human.Health > 0) do
We want to keep looping until the player dies (has a human.Health value of 0 or less) so we tell the loop to keep going while human.Health is greater than 0.
human.Health = human.Health - 10
We'll deincrement the human.Health value by 10, and then wait(0.1), which will cause the script to wait for 1/10 of a second (you can change this to a different number, but it is important to keep it as if you remove it, the loop will run extremely fast and kill the player immediately. If you want this to happen, you can remove the wait, but if you wanted to kill the player immediately, you could just set human.Health = 0 in the first place.
If you have any questions, feel free to ask! Hope this answered your question.
I remember when I used to use Lua for Roblox. The part is the part in the game that gets touched. You need to reference it so you can find the humanoid object it belongs to or lack of so your code can tell if it is a humanoid that touched it or not. Let me know if you have any further questions.
I was writing a script to move items in and out of storage in a game. I'd planned to allow for item queues in the event that there was not sufficient free space when I ran the script. I'd also planned to allow for more than one queue to exist at a time (ex: a queue to move items into the inventory, and a second queue to move items into the storage).
I originally thought that I should use coroutines to achieve this. The first queue would run until the destination for items (storage or inventory) was full, then would pause using coroutine.yield and allow the next queue to run. The queues would be restarted when a free space opened up.
threads = {}
local co = coroutine.create(function(list, target)
--list: a list of items to be moved
--target: inventory or storage (where the item is to be moved)
while list.n > 0 do
if target.count < target.max then
move(list:last(), target)
else
coroutine.yield()
end
end
end)
threads:append(co)
-- this code would run when free spaces were detected
for i = 1, #threads do
local status = coroutine.resume(threads[i])
if not status then
threads:remove[i]
end
end
However, I realized that I didn't necessarily need to use coroutines.
inventory_lists = {}
-- lists of items to be moved to the inventory
storage_lists = {}
-- lists of items to be moved to the storage
run_threads = function(list, target)
while list.n > 0 and target.count < target.max do
move(list:last(), target)
end
end
-- this code would run when free spaces were detected
for i = 1, #inventory_lists do
run_threads(inventory_lists[i], inventory)
end
for i = 1, #storage_lists do
run_threads(storage_lists[i], storage)
end
These pieces of code accomplish the same thing, and I don't see any reason to use one over the other. Should I avoid using coroutines in this case, since there doesn't seem to be an advantage?
It seems this is an inappropriate use for coroutines as there simply isn't any need to use them: the tables are all available globally, there's no need to store the state of any variables, and all of the information is immediately available (nothing needs to block).
I suppose it's not incorrect in the sense that it still runs, but it's similar to doing
co = coroutine.wrap(function()
print('Hello') coroutine.yield() print('World')
end)
co() co()
When you could simply print 'Hello\nWorld'.
just starting to play around with the awesome corona sdk.
I started building a simple shooter game.
I have the following code :
-- Global Variables
local shot = audio.loadSound('shot.mp3')
local bg = display.newImage('bg.png')
local shoot = {}
local Main = {}
local Init = {}
local bullets = display.newGroup()
function update()
if(bullets.numChildren ~= 0) then
for i = 1, bullets.numChildren do
bullets[i].y = bullets[i].y - 8
-- Destroy Offstage Bullets
if(bullets[i].y < (-bullets[i].height-5)) then
-- bullets[i]:removeSelf()
bullets:remove(bullets[i])
display.remove(bullets[i])
return
end
end
end
end
-- Initialisation functions
function Init ()
display.setStatusBar(display.HiddenStatusBar)
local movieclip = require('movieclip')
local physics = require('physics')
physics.start()
physics.setGravity(0, 0)
end
function shoot:tap(e)
for i = 1, 15 do
local bullet = display.newImage('bullet.png')
bullet.x = 150
bullet.y = 470
bullet.name = 'bullet'
physics.addBody(bullet)
bullets.insert(bullets, bullet)
end
audio.play(shot)
end
-- Main routine
function Main ()
Init()
bg:addEventListener('tap', shoot)
Runtime:addEventListener('enterFrame', update)
end
Main()
For now it 'works'; but when the bullet comes of the screen the whole 'game' slows down and I can clearly see that each bullet is removed which slows down the game.
Maybe i'm not doing it right; also tried the :removeSelf() function; same results.
I was facing the same problem...And got the soln for this:
you are removing objects using for loop:
if you remove objects in for loop say: you deleted object at index 1, then object 2 moves to object 1...so when it loops to object to it wont check object 2(bcoz its moved to object 1's place and you are checking object 3)
for j = 1, buttonGroup.numChildren do
buttonGroup[1]:removeSelf(); --this removes all childrens
end
for j = 1, buttonGroup.numChildren do
buttonGroup[j]:removeSelf(); --this removes alternative childrens
end
I hope its useful
I fought for a long long time with object removal for my game which uses a lot of tabbed views. The solution I found was to use "= nil", ":removeSelf()" and ".alpha = 0" on all objects which need removing. If they are all added to the same group, and nothing else is in it, that could be used too, but doesn't always work for various reasons as to how groups are set up behind the scenes.
It would seem what you've done there is remove the contents of "bullets" but that's just a reference, so where you say each bullet is being removed, it's actually only being dropped from the array - the object itself still exists and needs to be nil'd in order to prevent a memory leak and a slowing of the app (you will probably have found that each bullet slows the app more, right?)
Add this condition after your removes and you should be set:
if(not(bullet == nil)) then
bullet.alpha = 0;
bullet:removeSelf();
bullet = nil;
end
its easier to simply create a table like this
local bulletCache = {}
Then in your bullet creation code add
table.insert(bulletCache, myBulletObject)
then in your exit code and/or your destroy code say
for i = 1, #bulletCache do
--[[
--Below is not needed but just to keep your code consitant
pcall(function()
bullet.alpha = 0
end)
--]]
pcall(function()
bullet:removeSelf()
end)
pcall(function()
bullet = nil
end)
end
First of all, never try to execute any kind of loop in GameLoop. It does drop fps of game, because it takes usually more memory.
Now, it seems that you just want to destroy bullets after disappearing from the screen and you are using physics too, so why you are not taking advantage of that?
Here are the steps you should follow. (If you find any query or difficulty about it then ask me)
1.Draw a Static Physical Line little bit above the screen. Let say y is -20.
local _yLimit = -20
local _limitLine = display.newLine(0,_yLimit,display.contentWidth,_yLimit)
_limitLine.anchorX = 0
_limitLine.anchorY = 0
2.Add all bullets as a physical object.
3.Apply force at the Bottom Center of bullet, rather then transforming it. [Assuming that bullet have rectangular physical shape, otherwise decide the equilibrium point of the shape].
4.Check for collisions with "collision" event listener.
5.Destroy bullets on collision
Thats so simple :)
Let me know if you still have problems regarding this.