SHOW:
|
|
- or go back to the newest paste.
1 | -- StarterGUI: | |
2 | -- LocalScript: | |
3 | -- Name The LocalScript: mirrors | |
4 | ||
5 | local player = game:GetService("Players").LocalPlayer | |
6 | local character; repeat wait() character = player.Character until character | |
7 | local camera = game:GetService("Workspace").CurrentCamera | |
8 | ||
9 | local rs = game:GetService("RunService").RenderStepped | |
10 | local reflections = require(script:WaitForChild("reflections")) | |
11 | ||
12 | local mirrors = game:GetService("Workspace"):WaitForChild("Mirror model") | |
13 | ||
14 | rs:connect(function() | |
15 | reflections:clearCharacters() | |
16 | local characters = {} | |
17 | for _, player in pairs(game:GetService("Players"):GetPlayers()) do | |
18 | table.insert(characters, player.Character) | |
19 | end | |
20 | for _, mirror in pairs(mirrors:GetChildren()) do | |
21 | if mirror:IsA("BasePart") then | |
22 | reflections:drawWorld(mirror, game:GetService("Workspace"), {mirrors, unpack(characters)}) | |
23 | reflections:drawCharacters(characters, mirror) | |
24 | end | |
25 | end | |
26 | end) | |
27 | ||
28 | -- ModuleScript: | |
29 | -- Name The ModuleScript: reflections | |
30 | ||
31 | local class = {} | |
32 | local camera = game:GetService("Workspace").CurrentCamera | |
33 | ||
34 | local renderPacket = {} | |
35 | ||
36 | local reflections = Instance.new("Model", camera) | |
37 | local users = Instance.new("Model", reflections) | |
38 | local environment = Instance.new("Model", reflections) | |
39 | reflections.Name = "reflections" | |
40 | users.Name = "users" | |
41 | environment.Name = "environment" | |
42 | ||
43 | --// Functions | |
44 | ||
45 | function gather(children, class, tab) | |
46 | local tab = tab and tab or {} | |
47 | for _, child in pairs(children) do | |
48 | if child:IsA(class) then | |
49 | table.insert(tab, child) | |
50 | end | |
51 | tab = gather(type(child) == "table" and child or child:GetChildren(), class, tab) | |
52 | end | |
53 | return tab | |
54 | end | |
55 | ||
56 | function gather_Ignores(children, class, ignores) | |
57 | local tab = {} | |
58 | for _, part in pairs(gather(children, class)) do | |
59 | local pass = true | |
60 | for _, thing in pairs(ignores) do | |
61 | if part == thing or part:IsDescendantOf(thing) then | |
62 | pass = false | |
63 | end | |
64 | end | |
65 | if pass then | |
66 | table.insert(tab, part) | |
67 | end | |
68 | end | |
69 | return tab | |
70 | end | |
71 | ||
72 | --// Methods | |
73 | ||
74 | function class:reflect(item, against) | |
75 | local cf = item:IsA("BasePart") and item.CFrame or item.PrimaryPart.CFrame | |
76 | local x, y, z, r00, r01, r02, r10, r11, r12, r20, r21,r22 = against.CFrame:toObjectSpace(cf):components() | |
77 | local newCf = against.CFrame:toWorldSpace(CFrame.new(-x ,y ,z , r00, -r01, -r02, -r10, r11, r12, -r20, r21, r22)) | |
78 | if item:IsA("BasePart") then | |
79 | item.CFrame = newCf | |
80 | if item:IsA("CornerWedgePart") then | |
81 | item.Size = Vector3.new(item.Size.z, item.Size.y, item.Size.x) | |
82 | item.CFrame = item.CFrame * CFrame.Angles(0,math.rad(90),0) | |
83 | end | |
84 | elseif item:IsA("Model") then | |
85 | item:SetPrimaryPartCFrame(newCf) | |
86 | end | |
87 | end | |
88 | ||
89 | function class:drawWorld(against, parent, ignores) | |
90 | table.insert(ignores, camera) | |
91 | local renders = gather_Ignores({parent}, "BasePart", ignores) | |
92 | renderPacket[against] = renderPacket[against] or {} | |
93 | for _, part in pairs(renders) do | |
94 | if (not part.Locked or part.Parent:IsA("Hat")) and part.Transparency < 1 then | |
95 | if not renderPacket[against][part] or renderPacket[against][part].cf ~= part.CFrame then | |
96 | if renderPacket[against][part] then | |
97 | renderPacket[against][part].focus:Destroy() | |
98 | end | |
99 | local focus = part:Clone() | |
100 | local joints = gather(focus:GetChildren(), "JointInstance") | |
101 | for _, joint in pairs(joints) do joint:Destroy() end | |
102 | focus.Anchored = true | |
103 | self:reflect(focus, against) | |
104 | focus.Parent = environment | |
105 | renderPacket[against][part] = { | |
106 | cf = part.CFrame; | |
107 | origin = part; | |
108 | focus = focus; | |
109 | event = part.AncestryChanged:connect(function() focus:Destroy() end); | |
110 | } | |
111 | end | |
112 | end | |
113 | end | |
114 | end | |
115 | ||
116 | function class:drawCharacters(characters, against) | |
117 | for _, character in pairs(characters) do | |
118 | character.Archivable = true | |
119 | local character = character:Clone() | |
120 | local hum = character:FindFirstChild("Humanoid") | |
121 | local scripts = gather(character:GetChildren(), "BaseScript") | |
122 | local parts = gather(character:GetChildren(), "BasePart") | |
123 | local joints = gather(character:GetChildren(), "JointInstance") | |
124 | if hum then | |
125 | hum.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None | |
126 | end | |
127 | for _, src in pairs(scripts) do src:Destroy() end | |
128 | for _, joint in pairs(joints) do joint:Destroy() end | |
129 | for _, part in pairs(parts) do | |
130 | part.Anchored = true | |
131 | part.CanCollide = false | |
132 | self:reflect(part, against) | |
133 | end | |
134 | character.Parent = users | |
135 | end | |
136 | end | |
137 | ||
138 | function class:clearCharacters() | |
139 | users:ClearAllChildren() | |
140 | end | |
141 | ||
142 | function class:cleanup() | |
143 | environment:ClearAllChildren() | |
144 | users:ClearAllChildren() | |
145 | renderPacket = {} | |
146 | end | |
147 | ||
148 | return class | |
149 | ||
150 | -- Made by Youtube.com/c/StillwaterYT |