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.
Related
I'm a newbie developer of roblox.
I'm trying to place a player in a specific position on first load in this way:
In StarterPlayer > StarterPlayerScripts I added a LocalScript with the following code:
local cf = CFrame.new(500, 5, 50)
local Char = game.Players.LocalPlayer
Char.HumanoidRootPart.CFrame = cf
When I click play, nothing happen onload.
What I'm doing wrong?
#ItsJustFunboy is half correct, you do need to use the Model:MoveTo function, but you might have some other issues as well : timing and LocalScripts.
Timing-wise, you have this code in StarterPlayerScripts. These LocalScripts execute when the Player joins the game, not when their character model appears. So it's possible that their character doesn't even exist at the time you're telling it to move. If you want to guarantee that the character model exists at the time you run this code, it needs to be in StarterCharacterScripts.
As for the problem with LocalScripts, they make changes to the world only on your client. Meaning that if you move your character in a LocalScript, then all the other players will still see your character model where it was, not where you moved it. So unless this is intentional, if you want everyone to see this change, you need to move the character model in a server-side Script.
So in a Script in the Workspace or in ServerScriptService, try this :
-- wait for a player to join the game
game.Players.PlayerAdded:Connect(function(player)
-- wait for their character to load into the game
player.CharacterAdded:Connect(function(character)
-- yield the thread for but a moment so that the character can finish loading
wait()
-- move their character
local targetPosition = Vector3.new(500, 5, 50)
character:MoveTo(targetPosition)
end)
end)
use the MoveTo() function:
local plr = game.Players.LocalPlayer
plr.Character:MoveTo(CFrame.new(500, 5, 50))
In Roblox I want to create.If the player has a Tool in backpack and touches brick.Give Player 2000
cash,and tool dispears.I already have made a leaderboard for the cash,and already have my tool in server storoge.
First off, you can start by using a .Touched event which fires every time an object is touched. A .Touched event can carry one parameter; the object that touched it. For example, if a player (R15) stepped on a block on the floor, the object that hit the part might be Left Foot. Here is what the skeleton of a .Touched function looks like:
<Part>.Touched:Connect(function(hit)
print(hit.Name) --As per the example above, this would print "Left Foot"
end)
Since any object can touch the part, but not every one has a Backpack, you'll want to first check if the object that hit your part is from an actual player. You can do this by looking for a Humanoid, which would be a sibling of the part that touched. You can do this by adding:
<Part>.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
print(hit.Name) --As per the example above, this would print "Left Foot"
end
end)
Now that we have verified that a player was what touched our part, we can use the function of game.Players called GetPlayerFromCharacter(). A Character is just your player in game.workspace, so by calling this function, it gets your player in game.Players from your character. This is similar to game.Players:FindFirstChild(<Player>.Name). Either one work, but I will be using the first one for this example. Added to your code, here is what it should now look like:
<Part>.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
end
end)
As you may know, Backpack is a direct child of the player in game.Players, so we can use player.Backpack to find our Backpack. Now we can do the same thing that we did to check for a humanoid, to check for our tool:
<Part>.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
local Backpack = player.Backpack
if Backpack:FindFirstChild("<Tool Name>") then
player.leaderstats.<Money>.Value += 2000 --Gives them 2000 cash
end
end
end)
If you cloned the tool into the player's Backpack previously, you can do Backpack.<Tool Name>:Destroy() to get rid of it/make it dissapear.
So I have a roblox puzzle game that I have been working on for a while now on based on the arcade classic Q bert where the goal is to change all the colours of the bricks while avoiding enemies and getting a high score but I will be adding some features of my own so it does not get as repetitive such as additional tasks like collecting keys on platforms to unlock the door to the next level and secrets like a diamond that rarely appears once every 10 rounds and collecting one gives the player an extra dude and 10 million points.
This is how the game looks so far https://streamable.com/na46cu
The issue I am having as you can see is that the colours do in fact change but when I jump on it again it changes back to the first colour it changes to which in this case is green but I want it to stay on the first colour and make it so that it does not change until the player jumps on the brick again and later on in the game I want it to become more complex and puzzle like as the game goes on like in this example [https://www.youtube.com/watch?v=9eXJWiNXpOo][2] .
I have tried a few things like adding timers ,debounces and even separate scripts alltogether none of which have worked out for me so far and I of course went out looking for a question from somebody else that had a similar problem but so far I have been struggling to find anybody else that has the same problem.
local module = {} --module for the modulescript and for loop is created
local CollectionService = game:GetService("CollectionService")
for _, part,brick in pairs (CollectionService:GetTagged("blocks"))
do
part.Touched:Connect(function(hit) --Part connects with the touched property to the function with the parameter hit
if (hit.Parent:FindFirstChild("Humanoid"))
then
part.BrickColor = BrickColor.new ("Bright green")
wait (2)
part.BrickColor = BrickColor.new ("Eggplant")
-- local sound = workspace.Sound -- use "local sound = workspace.Sound", if there is already a sound object in the workspace
--sound.SoundId = "rbxassetid://4797903038" --replace quoted text with whatever sound id you need to use
--sound:Play()
end
end)
end
-- end)
--end
return module
I am not the best programmer but I do know the basics of programming and I have tried out various programming languages like Python and c++ all of which are not all that hard to understand once you know the basics of it all but finding out the solution to the problem is the really tricky part and so is bug fixing and troubleshooting.
I do know I could try a simple debounce system but that still does not solve the problem and it only makes it so the code only runs once and slows it down.
I have been asking all over the place for a solution to this problem but I never got an answer to it so I am trying on good old Stackoverflow for once to see if this will be the place where I get the help I need.
this should work, try it
local module = {} --module for the modulescript and for loop is created
local CollectionService = game:GetService("CollectionService")
local DidParts = {} -- Initializing another table to check if the part is already in it
for _, part,brick in pairs(CollectionService:GetTagged("blocks")) do
part.Touched:Connect(function(hit) --Part connects with the touched property to the function with the parameter hit
if hit.Parent:FindFirstChild("Humanoid") then
if table.find(DidParts,part) then
return -- checking if the part isnt in the table if it is then return
end
part.BrickColor = BrickColor.new("Bright green")
wait(2)
part.BrickColor = BrickColor.new("Eggplant")
table.insert(DidParts,part) -- when all the code has finished insert it in the table
-- local sound = workspace.Sound -- use "local sound = workspace.Sound", if there is already a sound object in the workspace
--sound.SoundId = "rbxassetid://4797903038" --replace quoted text with whatever sound id you need to use
--sound:Play()
end
end)
end
-- end)
--end
return module
can someone help me on how show i move the NPCs through a path, like in the tds game?. I have tried this
local function move()
-- source is an array with all the positions it has to go to
for i=1,#source,1 do
-- This is in case the MoveTo takes more than 8 seconds
local itreached = false
while itreached == false do
npc.Humanoid:MoveTo(source[i].Position)
wait()
npc.Humanoid.MoveToFinished:Connect(function()
itreached = true
end)
end
end
end
and it works to an extend , that when i approach the npc it somehow falls and lags , otherwise if i just run it without a player it works just fine. Are there other techniques, like lerp or tween? I tried using lerp, but i couldn't move the whole model.
video showing the problem
You are running into an issue with network ownership. The Roblox engine decides who is responsible for calculating the positions of objects based on some calculation around who is closest to the object and who has a strong enough machine to do the calculation. For example, desktop computers and laptops tend to have a wider sphere of influence than mobile devices. Anyways, when you walk close it the NPCs, there is a handoff of ownership, and that is causing the NPCs to fall over. So to fix it, you need to call SetNetworkOwner(nil) on the NPC's PrimaryPart so that the part is owned by the server.
npc.PrimaryPart:SetNetworkOwner(nil)
Also, if you want to clean up your code, you can make it entirely driven by events. Once you tell it to start moving, it will select the next target once it arrives.
local targetPos = 1
local function move()
npc.Humanoid:MoveTo(source[targetPos].Position)
end
-- listen for when the NPC arrives at a position
npc.Humanoid.MoveToFinished:Connect(function(didArrive)
-- check that the NPC was able to arrive at their target location
if not didArrive then
local errMsg = string.format("%s could not arrive at the target location : (%s, %s, %s)", npc.Name, tostring(targetPos.X), tostring(targetPos.Y), tostring(targetPos.Z))
error(errMsg)
-- do something to handle this bad case! Delete the npc?
return
end
-- select the next target
targetPos = targetPos + 1
-- check if there are any more targets to move to
if targetPos <= #source then
move()
else
print("Done moving!")
end
end)
I am working on a 6 player rounds-based Roblox game with each round ending if either time runs out OR if every player except for one survivor remains. After each round players (and those killed during the round) are teleported back to a lobby, followed by a brief intermission, and then teleported bak into a map to start a new round (there are lots of different maps chosen randomly). My strategy for this game was to create a large region surrounding all the maps and during the rounds as the timer is counting down, continually detect the # players in the region. When that number gets to 1 the round would end and a winner would be declared. There are 2 problems with this approach:
I had to create a huge region to encompass all the different maps and as I add more maps the region will have to get bigger and bigger. Is detecting # players in such a large region when at most 6 players will be in only one map at a time?
My player detection script isn't working. It detects one player but when there are 2 players it still returns "1" as # of players. To trouble shoot this problem I created a simple game that detects when a player is in a region (gray baseplate) and when they leave the region (red baseplate). When I run the game - https://www.roblox.com/games/6060804433/Rounds - publicly with 2 players in the game it only returns 1 player in the game (which I display in an upper left GUI). My code is below - I think the problem is with how the table / dictionary playersFound works.
CODE:
regionPart = game.Workspace.RegionFromThisPart -- I created a transparent cube to define the region
pos1, pos2 = (regionPart.Position - (regionPart.Size/2)),(regionPart.Position + (regionPart.Size/2))
region = Region3.new(pos1,pos2)
Status = game.ReplicatedStorage.Status
wait(5)
while wait(1) do
partsInRegion = workspace:FindPartsInRegion3(region, game.Workspace.Baseplate,1000)
playersFound = {} -- table of players found
for i, part in pairs (partsInRegion) do
if part.Parent:FindFirstChild("Humanoid") ~= nil then
playersFound["playerinregion"] = part.Parent -- add players character to table
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
Status.Value = Length(playersFound) .." players in region"
end
Bonus question: The GUI I created to show the number of players in the region shows on my screen but not the other player's scree (it says "label" on their screen).
I have spent an incredible amount of time spinning my wheels and would GREATLY appreciate help solving this problem.
Thank you!
You're absolutely right that your issue stems from how you're putting players into your playersFound table. Because you are using the same key in the table every time, you are overwriting the old player with any new one you find.
Instead, try using a unique key to hold onto the players. This could be i or better yet, the player's name. And since you are just looping over the table again, why not just keep a counter of how many players there are.
local regionPart = game.Workspace.RegionFromThisPart -- I created a transparent cube to define the region
local pos1 = (regionPart.Position - (regionPart.Size/2))
local pos2 = (regionPart.Position + (regionPart.Size/2))
local region = Region3.new(pos1,pos2)
local Status = game.ReplicatedStorage.Status
local BasePlate = game.Workspace.Baseplate
local time = 30 -- seconds
wait(5)
while wait(1) do
-- count how many players are left
local playersFound = {}
local totalPlayersFound = 0
local partsInRegion = workspace:FindPartsInRegion3(region, baseplate, 1000)
for i, part in pairs(partsInRegion) do
if part.Parent:FindFirstChild("Humanoid") ~= nil then
-- keep track of all the players still alive
-- since a player's character is made of many parts, each player will show up multiple times,
-- so only hold onto each player once
local character = part.Parent
if (playersFound[character.Name] == nil) then
playersFound[character.Name] = character
print ("Found Player : ", character.Name)
totalPlayersFound = totalPlayersFound + 1
end
end
end
-- EDIT BASED ON COMMENTS --
-- update the UI based on the game state
if time == 0 then
Status.Value = "Round over!"
break
elseif totalPlayersFound == 1 then
-- since we know that there's only one entry in the playersFound table,
-- grab it using the next() function
local playerName, character = next(playersFound)
StatusValue = "Winner : " .. playerName
wait(5)
break
--elseif totalPlayersFound == 0 then
-- make sure to check in case no players are left
else
Status.Value = tostring(totalPlayersFound) .. " players in round"
time = time - 1
-- DEBUG :
-- print("There are " .. tostring(totalPlayersFound) .. " players in the round")
-- for playerName, character in pairs(playersFound) do
-- print(" - " .. playerName .. " is still in the game")
-- end
end
end
As for your bonus question, you should ask a follow up question and post the code that shows how you're creating the label and updating it.