Attempting to recreate an effect from a Blockland addon

Hello, first time posting a topic here.
Apologies if this is in the wrong section,

What I’ve been trying to achieve is two little things from Blockland, well, an addon for blockland.
I’ve been trying for a few days to achieve these two little features that are in it, one being hard to do, and the other one also being hard to do. (well for me at least)

Here’s two snippets;
Effect 1

Effect 2:

(I’ve seen these effects done in a roblox game before, forgot the name and the link, I just remember seeing it and playing it, and it had to do with this addon)

Those effects are two i’ve currently been struggling with. The first one locks the player and the npc in place, making the player stuck there while the npc sits behind them still, waiting for the player to turn around and if the player does not turn around, the nc goes away letting the player move again.

The second effect does the exact same thing as the top one, except this time it forces the player to turn around, not in a smooth motion either, but in a rather choppy way, I’ve tried lerps and tweens and cframe changes for this, but however it’s been rendered useless as whatever I try has not come close as to rendering the same effect. (haha get it renderman)

I’ve currently tried changing the currentcameras cframe by a few seconds to look at it to recreate the choppiness, but that has been not working efficiently. Lerps and tweens make the turns smooth instead of choppy, so that is not what has worked.

I do not want an entire script wrote out for me on how to do both of them, I’d rather have an idea of what to do and explain what stuff does so I can at least learn from it, any help is appreciated, thank you so much.

1 Like

An idea for the choppy part:
Tween a NumberValue instead. Have a .Changed event bound to the NumberValue wherein you set the player’s camera’s CFrame angles to some radial calculation using math.floor(NumberValue.Value) instead. The tween will be smooth, but the floored value of the tween will be jaunty.

The loss of control part:
If you anchor the players’ characters’ HumanoidRootPart, they will be frozen. Alternatively, you could disable their controls client-sided but that could be undone by an exploiter. Run a timer on the server and unanchor them when it’s over to return control.

3 Likes

Thank you! I will try this out very soon, i appreciate the feedback heavily

1 Like

Hey, I’m having a little bit of trouble getting the CFRAME angles to radial degrees, or just degrees in general to do this, I have tried going offo f the characters’ primarypart’s orientation to make a radial going on the Y axis, to make it display it as if it was the cameras Y, but it was the characters instead, but that failed ultimately, ((even though it’s pretty much the simplest thing ever)) and tried to tween that, but it ended up shaking a lot.

Edit:**meant to say LERP not tween, I tried to lerp the value. realized that mistake.

1 Like

You’re on the right track, I can explain the rotating axis but you would need to adapt this idea to have the other two axes, as well as the flooring since I haven’t played with this in studio to see how it would look. I would personally use the players’ Head since that’s where the camera is supposed to be anyways and makes reading the logic a little easier. Try this:
Tween the NumberValue from 0 to 180, that’ll represent degrees. On the .Changed event, set the players’ Head to something like char.Head.CFrame = CFrame.new(CFrame.Angles(0, math.rad(NumberValue.Value), 0) + char.Head.CFrame.Position)
Then, you can just set the camera’s CFrame to the head’s CFrame in the same go.

That should keep the head where it’s supposed to be but spin it 180 degrees on the y-axis. Again I’ve not seen it in studio, Humanoids are very frustrating to work with so there might be problems with the neck, would have to test to see. Remember to anchor anything being lerped/tweened as unanchored parts don’t enjoy being CFrame manipulated

2 Likes

I’m having trouble understanding, sorry, you’re saying to tween the char’s head’s cframe, to the number value’s y? and then lock the camera’s cframe to the heads?

Right, you’re using the NumberValue’s .Value to represent degrees of rotation. math.rad(NumberValue.Value) turns degrees into radians, which CFrame angles are based on. This will make it 0 to 1*pi instead. This will make the players’ head spin around. In the same assignment you can set the players’ camera CFrame to the same (assuming they are locked in first-person, I should have mentioned that). You may also need to set the camera to Scriptable at least for this portion of the effect to be able to dislodge it from the standard camera script.

I have done it, but instead of tweens i did it to where it adds a 30 degree angle to a player until it equals or is above 180, to where the player is facing the NPC, but it’s quite buggy doing that, as i’ve tried the tween idea and i failed toe xecute it

			num = 30
				while plr.Character.Locked.Value == true and num <=180 do 
					wait(1)
					plr.Character:SetPrimaryPartCFrame(plr.Character.PrimaryPart.CFrame * CFrame.Angles(0, math.rad(num), 0))

					num = num + 45
					print(num)
					if num >=180 then
						print("reached 180 and over")
					end
				end

I believe this is extremely inefficient and there could be another way to do this. @imminium has achieved this effect in one of their games similar to the topic, if they see this maybe they could assist?

The first effect is approachable with one of Vector3s function.
I did my research in the past, and I think the best way you can determine if a player is looking at the NPC is using the :Dot() function on a Vector3.

I’ll try my best to explain it:


I get the direction that the player is facing with LookVector, in this case, by getting their direction from their Heads

local CharacterHead = Character:FindFirstChild("Head") -- Get the player's head (Part)
local DirectionOfHead = CharacterHead.CFrame.LookVector -- Returns the forward direction of the CFrame. It is a Vector3.

Then, I get the direction from the position of the player to the NPC (assuming you have both of their positions, we’ll use the head again for convenience). These are both Vector3s.

local PositionOfCharacter = CharacterHead.Position -- or CharacterHead.CFrame.Position
local DirectionToNPC = NPC_Position - PositionOfCharacter -- (B - A)

Now that we have both directions (DirectionOfHead and DirectionToNPC), we can use the :Dot() function on one of them, like this:

local Result = DirectionOfHead:Dot(DirectionToNPC)

…which returns a number (between -1 and 1) based on the “agreement” / “alignment percentage” between the two directional vectors, which is based on how similar they are. The more similar they become, the higher the value and vice versa.


With Result, we can now determine if the player is actually looking at the NPC. For example, if Result is greater than 0.5, then we assume the NPC is in sight of the player and we can do harm to them.

Hopefully this helps for the first effect you’re trying to achieve!

Some resources that may cover what I didn’t here:

Vector3 (for using the :Dot() function)
CFrame (for obtaining the LookVector)

2 Likes

Thank you lots! I’m mainly looking for the answer to how to make the player forcefully turn around in a choppy way, toward the “Renderman”, etc etc. as in effect two.

For the second effect:

In theory, I think you can achieve that by constantly rotating the character’s CFrame property every 0.5 to 1 second without needing to use wait(x), but using timestamps paired with one of RunService’s events (Stepped, Heartbeat, etc.).

Here’s a stepping stone example on how I usually set up something with timestamps in mind.

local Timestamp = os.time() -- returns the elapsed time after (1 January 1970, 00:00:00 UTC)
local AmountOfTimeToWait = 1

RunService.Stepped:Connect(function()
    local Now = os.time()
    if Now >= Timestamp then -- Is the time now greater than the timestamp?
        Timestamp = Now + AmountOfTimeToWait -- Reset the timestamp and add one more second to it

        -- Insert Code
    end
end)

In relation to making the player rotate while creating the choppy effect, you could try something like this, assuming you have the HumanoidRootPart of the player’s character (this is just another stepping stone example):

--...
local PlayerRotateTimestamp = os.time() -- Create a timestamp that we'll use to measure how much time has passed
--...

--... in a function connected to RunService's events
local function onStepped()
    local Now = os.time()
    if Now >= PlayerRotateTimestamp then
        PlayerRotateTimestamp = Now + 1
         if HumanoidRootPart ~= nil then
                HumanoidRootPart.CFrame = HumanoidRootPart.CFrame * CFrame.Angles(0, math.rad(30), 0)
                -- Essentially rotates the player 30° every one second
         end
    end

    -- Code for checking if player is actually viewing the NPC and then killing them mercilessly
end

There are then a couple issues that I can spot using this code snippet in practice.

• This would only rotate the player in one direction only, which can then be done by checking if the player is closer to the NPC in one direction or the other (but I have yet to try that).

• There is a very, very never-zero chance that the incremental angle is enough for the player to completely avoid seeing the NPC, which can be resolved in several ways. Probably one of the best ways is taking advantage of the result of the :Dot() function as a percentage value for how much you should rotate the player.


Some other things to take note of if you’re planning to adapt this:

• This can be done on the client-side as well but at a couple security risks that could give the player an unfair advantage if not executed with care

• If you want to be more precise and use decimals to fine-tune your interval time between rotating the player, use os.clock(). Supposed to be intended for benchmarking (as told by the wiki), but this can present a few other use cases.

• As mentioned, there are a variety of events that RunService presents, with Stepped, Heartbeat, RenderStepped (client-sided only) being the more “legacy versions,” and PreSimulation, PostSimulation, PreRender and PreAnimation being the more recent versions. I believe we’re being recommended to use this in future work, but until then!

Hopefully this helps!

Additional resources in context:
os (for use in the timestamp method)
RunService (in tandem with timestamps, along with the variety of events)

This was exactly what i was looking for! Thank you so much for your time, you and @MP3Face , both of you have been extremely helpful

1 Like