001 | --[[ |
002 | Author: WelpNathan |
003 | Date: 31/05/2018 |
004 |
005 | Script: This script will control how the SCP reacts to touching |
006 | and other interactions. |
007 | --]] |
008 |
009 | --------------------------- |
010 | -- V A R I A B L E S -- |
011 | --------------------------- |
012 |
013 | -- ROBLOX Services |
014 | local players = game:GetService( 'Players' ) |
015 | local physicsService = game:GetService( "PhysicsService" ) |
016 | local pathfindingService = game:GetService( "PathfindingService" ) |
017 |
018 | -- Locate the physical SCP |
019 | local this = script.Parent.Parent:WaitForChild( 'PhysicalSCP' ) |
020 |
021 | -- Store the settings of the SCP |
022 | local settingsSCP = { |
023 | magnitudeMax = 500 , |
024 | sound = { |
025 | damageSound = 1542642349 , |
026 | standbySound = { } |
027 | } |
028 | } |
029 |
030 | -- Store the previous weld in memory |
031 | local previousWeld = nil |
032 |
033 | local scpBreached = false |
034 |
035 | --------------------------- |
036 | -- M A I N S C R I P T -- |
037 | --------------------------- |
038 |
039 | script.Parent.BreachSCP.Changed:Connect( function (value) |
040 | scpBreached = value |
041 | end ) |
042 |
043 | --[[ |
044 | Function: |
045 | Usage: |
046 | - When called, it will loop through the parts in the model |
047 | and will generate a weld to weld them all together. |
048 | Arguments: |
049 | - model: |
050 | - This is the model which will be welded together. Only |
051 | supports singular for loop. Won't go into other models. |
052 |
053 | --]] |
054 | local weldModel = function (model) |
055 | local parts = model:GetChildren() |
056 | for _, part in pairs (parts) do |
057 | if part:IsA( "Part" ) then |
058 | if previousWeld ~ = nil then |
059 | local weld = Instance.new( "Weld" ) |
060 | weld.Part 0 = previousWeld |
061 | weld.Part 1 = part |
062 | weld.C 0 = previousWeld.CFrame:inverse() |
063 | weld.C 1 = part.CFrame:inverse() |
064 | weld.Parent = previousWeld |
065 | part.Anchored = false |
066 | end |
067 | previousWeld = part |
068 | end |
069 | end |
070 | end |
071 | -- Weld the humanoid parts |
072 | weldModel(script.Parent.Parent.PhysicalSCP) |
073 |
074 | --[[ |
075 | Make sure that the SCP cannot collide with doors. |
076 | --]] |
077 | local scpGroup = "GroupSCP" |
078 | local doorGroup = "GroupDoor" |
079 |
080 | physicsService:CreateCollisionGroup(scpGroup) |
081 | physicsService:CreateCollisionGroup(doorGroup) |
082 |
083 | function addPartToCollisionGroup(root, colissionGroup) |
084 | for _, child in pairs (root:GetChildren()) do |
085 | addPartToCollisionGroup(child, colissionGroup) |
086 | end |
087 |
088 | if root:IsA( 'Part' ) or root:IsA( 'UnionOperation' ) then |
089 | physicsService:SetPartCollisionGroup(root, colissionGroup) |
090 | end |
091 | end |
092 | addPartToCollisionGroup(workspace.SiteDoors, doorGroup) |
093 | addPartToCollisionGroup(this, scpGroup) |
094 | physicsService:CollisionGroupSetCollidable(doorGroup, scpGroup, false ) |
095 |
096 | --[[ |
097 | Function: |
098 | Usage: |
099 | - When called, it will attempt to locate the nearest player |
100 | model to attack. It will only attack players. SCPs are |
101 | allies. |
102 | Arguments: |
103 | - positionSCP: |
104 | - This is the current position of the SCP. This is usually |
105 | the Torso found in PhysicalSCP. |
106 | --]] |
107 | local findNearestAttack = function (positionSCP) |
108 | local currentPlayers = players:GetPlayers() |
109 | local pos = settingsSCP.magnitudeMax |
110 | local attackPart = nil |
111 | for _, player in pairs (currentPlayers) do |
112 | -- Check to see if there is a valid model of the player |
113 | if player.Character and player.Character:FindFirstChild( 'Humanoid' ) and player.Character:FindFirstChild( 'HumanoidRootPart' ) and player.Character.Humanoid.Health > 0 then |
114 | local distance = player:DistanceFromCharacter(positionSCP) |
115 | if distance < settingsSCP.magnitudeMax and distance ~ = 0 and distance < pos then |
116 | pos = distance |
117 | attackPart = player.Character.HumanoidRootPart |
118 | end |
119 | end |
120 | end |
121 |
122 | return attackPart |
123 | end |
124 |
125 | --[[ |
126 | Function: |
127 | Usage: |
128 | - When called, it will scroll through a table and see |
129 | if there is a matching value. |
130 | Arguments: |
131 | - tablePhysical: The table. |
132 | - tableValue: The table value we're trying to find. |
133 | --]] |
134 | local searchTable = function (tablePhysical, tableValue) |
135 | for i, v in pairs (tablePhysical) do |
136 | if v = = tableValue then |
137 | return i |
138 | end |
139 | end |
140 | return nil |
141 | end |
142 |
143 | --[[ |
144 | Touch Event: |
145 | - When this is fired, it will proceed to check if a |
146 | player has touched the SCP. If a player has, they will |
147 | take damage. |
148 | --]] |
149 | local damageDebounce = { } |
150 | this.BoundarySCP.Touched:Connect( function (hit) |
151 | if scpBreached = = false then return end |
152 | local player = players:GetPlayerFromCharacter(hit.Parent) |
153 | if player and player.Character and player.Character:FindFirstChild( 'Humanoid' ) and player.Character.Humanoid.Health > 0 then |
154 | if searchTable(damageDebounce, player.UserId) = = nil then |
155 | -- Take damage from the player |
156 | -- Add a debounce so they don't constantly take damage |
157 | -- Remove the debounce |
158 | player.Character.Humanoid:TakeDamage( 20 ) |
159 | table.insert(damageDebounce, player.UserId) |
160 |
161 | -- If there is a damage sound, play it |
162 | if settingsSCP.sound.damageSound ~ = nil then |
163 | local sound = Instance.new( 'Sound' , this.Torso) |
164 | sound.SoundId = 'rbxassetid://' .. settingsSCP.sound.damageSound |
165 | sound.Volume = 1 |
166 | sound:Play() |
167 | spawn( function () |
168 | repeat wait( 3 ) until sound.Playing = = false |
169 | sound:Destroy() |
170 | end ) |
171 | end |
172 |
173 | wait( 0.5 ) |
174 | local index = searchTable(damageDebounce, player.UserId) |
175 | table.remove(damageDebounce, index) |
176 | end |
177 | end |
178 | end ) |
179 |
180 | -- Make the SCP into a production environment (remove red) |
181 | for _, part in pairs (this:GetChildren()) do |
182 | if part:IsA( 'Part' ) then |
183 | part.Transparency = 1 |
184 | end |
185 | end |
186 | this.Torso.Transparency = 0 |
187 |
188 | local destroyed = function (x) |
189 | if x.Parent then return false end |
190 | local _, result = pcall ( function () x.Parent = x end ) |
191 | return result:match( "locked" ) and true or false |
192 | end |
193 |
194 | --[[ |
195 | While Loop: |
196 | Every 3 seconds, it will compare all distances of players and |
197 | if the player is within the SCP's reach, it will attempt to move to it. |
198 | --]] |
199 | while true do |
200 | while scpBreached do |
201 | local targetPlayer = findNearestAttack(this:WaitForChild( 'Torso' ).Position) |
202 | if targetPlayer ~ = nil then |
203 | -- Calculate the path and get the waypoints |
204 | local start = this:WaitForChild( 'Torso' ) |
205 | local path = pathfindingService:FindPathAsync(start.Position, targetPlayer.Character.HumanoidRootPart.Position) |
206 | local waypoints = path:GetWaypoints() |
207 |
208 | -- Loop through all of the waypoints in the path |
209 | for waypointIndex, waypoint in pairs (waypoints) do |
210 | if waypoint.Action = = Enum.PathWaypointAction.Jump then |
211 | this.Humanoid.Jump = true |
212 | else |
213 | local waypointPosition = waypoint.Position |
214 | -- Make the humanoid move to the current waypoint |
215 | this.Humanoid:MoveTo(waypointPosition) |
216 | -- Wait until the humanoid has reached it's target |
217 | this.Humanoid.MoveToFinished:Wait() |
218 |
219 | if scpBreached = = false then break end |
220 |
221 | if targetPlayer and targetPlayer.Character:FindFirstChild( 'HumanoidRootPart' ) and targetPlayer.Character:FindFirstChild( 'Humanoid' ) and targetPlayer.Character.Humanoid.Health > 0 and (targetPlayer.Character.HumanoidRootPart.Position - this.Torso.Position).magnitude < 20 then |
222 | break |
223 | end |
224 | end |
225 | end |
226 |
227 | if targetPlayer and targetPlayer.Character and targetPlayer.Character:FindFirstChild( 'Humanoid' ) and targetPlayer.Character.Humanoid.Health > 0 and targetPlayer.Character:FindFirstChild( 'HumanoidRootPart' ) then |
228 | if (targetPlayer.Character.HumanoidRootPart.Position - this.Torso.Position).magnitude < 20 then |
229 | while scpBreached = = true and targetPlayer and targetPlayer.Character:FindFirstChild( 'HumanoidRootPart' ) and targetPlayer.Character:FindFirstChild( 'Humanoid' ) and targetPlayer.Character.Humanoid.Health > 0 and (targetPlayer.Character.HumanoidRootPart.Position - this.Torso.Position).magnitude < 20 do |
230 | this.Humanoid:MoveTo(targetPlayer.Character.HumanoidRootPart.Position, targetPlayer.Character.HumanoidRootPart) |
231 | wait( 0.5 ) |
232 | end |
233 | end |
234 | end |
235 | end |
236 | wait( 0.25 ) |
237 | end |
238 | wait( 0.25 ) |
239 | end |
Read the error it says sitedoors is not in workspace check if it exist or is correctly named