SHOW:
|
|
- or go back to the newest paste.
1 | - | --Converted with ttyyuu12345's model to script plugin v4 |
1 | + | --https://github.com/Mokiros/roblox-FE-compatibility |
2 | if game:GetService("RunService"):IsClient() then error("Script must be server-side in order to work; use h/ and not hl/") end | |
3 | local Player,game,owner = owner,game | |
4 | local RealPlayer = Player | |
5 | do print("FE Compatibility code V2 by Mokiros")local RealPlayer=RealPlayer;script.Parent=RealPlayer.Character;local a=function(b)b[1].f[b[2]]=nil end;local c={__index={disconnect=a,Disconnect=a}}local d={__index={Connect=function(b,e)local f=tostring(math.random(0,10000))while b.f[f]do f=tostring(math.random(0,10000))end;b.f[f]=e;return setmetatable({b,f},c)end}}d.__index.connect=d.__index.Connect;local function g()return setmetatable({f={}},d)end;local h={Hit=CFrame.new(),KeyUp=g(),KeyDown=g(),Button1Up=g(),Button1Down=g(),Button2Up=g(),Button2Down=g()}h.keyUp=h.KeyUp;h.keyDown=h.KeyDown;local i={InputBegan=g(),InputEnded=g()}local CAS={Actions={},BindAction=function(self,j,k,l,...)CAS.Actions[j]=k and{Name=j,Function=k,Keys={...}}or nil end}CAS.UnbindAction=CAS.BindAction;local function m(self,n,...)for o,e in pairs(self[n].f)do e(...)end end;h.T=m;i.T=m;local p=Instance.new("RemoteEvent")p.Name="UserInput_Event"p.OnServerEvent:Connect(function(q,r)if q~=RealPlayer then return end;h.Target=r.e;h.Hit=r.d;if not r.f then local s=r.c==Enum.UserInputState.Begin;if r.b==Enum.UserInputType.MouseButton1 then return h:T(s and"Button1Down"or"Button1Up")end;if r.b==Enum.UserInputType.MouseButton2 then return h:T(s and"Button2Down"or"Button2Up")end;for o,t in pairs(CAS.Actions)do for o,u in pairs(t.Keys)do if u==r.a then t.Function(t.Name,r.c,r)end end end;h:T(s and"KeyDown"or"KeyUp",r.a.Name:lower())i:T(s and"InputBegan"or"InputEnded",r,false)end end)p.Parent=NLS([==[local a=script:WaitForChild("UserInput_Event")local b=owner:GetMouse()local c=game:GetService("UserInputService")local d=function(e,f)if f then return end;a:FireServer({a=e.KeyCode,b=e.UserInputType,c=e.UserInputState,d=b.Hit,e=b.Target})end;c.InputBegan:Connect(d)c.InputEnded:Connect(d)local g,h;local i=game:GetService("RunService").Heartbeat;while true do if g~=b.Hit or h~=b.Target then g,h=b.Hit,b.Target;a:FireServer({f=1,Target=h,d=g})end;for j=1,2 do i:Wait()end end]==],script)local v=game;local w={__index=function(self,u)local x=rawget(self,"_RealService")if x then return typeof(x[u])=="function"and function(o,...)return x[u](x,...)end or x[u]end end,__newindex=function(self,u,y)local x=rawget(self,"_RealService")if x then x[u]=y end end}local function z(t,A)t._RealService=typeof(A)=="string"and v:GetService(A)or A;return setmetatable(t,w)end;local B={GetService=function(self,x)return rawget(self,x)or v:GetService(x)end,Players=z({LocalPlayer=z({GetMouse=function(self)return h end},Player)},"Players"),UserInputService=z(i,"UserInputService"),ContextActionService=z(CAS,"ContextActionService"),RunService=z({_btrs={},RenderStepped=v:GetService("RunService").Heartbeat,BindToRenderStep=function(self,j,o,k)self._btrs[j]=self.Heartbeat:Connect(k)end,UnbindFromRenderStep=function(self,j)self._btrs[j]:Disconnect()end},"RunService")}rawset(B.Players,"localPlayer",B.Players.LocalPlayer)B.service=B.GetService;z(B,game)game,owner=B,B.Players.LocalPlayer end --Converted with ttyyuu12345's model to script plugin v4 | |
6 | function sandbox(var,func) | |
7 | local env = getfenv(func) | |
8 | local newenv = setmetatable({},{ | |
9 | __index = function(self,k) | |
10 | if k=="script" then | |
11 | return var | |
12 | else | |
13 | return env[k] | |
14 | end | |
15 | end, | |
16 | }) | |
17 | setfenv(func,newenv) | |
18 | return func | |
19 | end | |
20 | cors = {} | |
21 | mas = Instance.new("Model",game:GetService("Lighting")) | |
22 | Tool0 = Instance.new("Tool") | |
23 | LocalScript1 = Instance.new("LocalScript") | |
24 | Script2 = Instance.new("Script") | |
25 | Part3 = Instance.new("Part") | |
26 | SpecialMesh4 = Instance.new("SpecialMesh") | |
27 | Script5 = Instance.new("Script") | |
28 | ObjectValue6 = Instance.new("ObjectValue") | |
29 | ObjectValue7 = Instance.new("ObjectValue") | |
30 | Tool0.Name = "LaserSpecs" | |
31 | Tool0.Parent = mas | |
32 | Tool0.TextureId = "http://www.roblox.com/asset/?id=100449698" | |
33 | Tool0.GripForward = Vector3.new(-0, 1.31134158e-07, -1) | |
34 | Tool0.GripPos = Vector3.new(1.53999996, -1.27000034, -1.31999993) | |
35 | Tool0.GripUp = Vector3.new(0, 1, 1.31134158e-07) | |
36 | LocalScript1.Name = "SpotWeld_Main" | |
37 | LocalScript1.Parent = Tool0 | |
38 | table.insert(cors,sandbox(LocalScript1,function() | |
39 | --local mDebugId = game.Workspace.DebugId.Value | |
40 | --game.Workspace.DebugId.Value = game.Workspace.DebugId.Value+1 | |
41 | --print("Running swordscript <"..mDebugId..">") | |
42 | ||
43 | ------------------------------------- | |
44 | -- Makes an RBX::Lua Instance using | |
45 | -- a table of key-value pairs to | |
46 | -- initialize it. Values with numeric | |
47 | -- keys will be parented to the object | |
48 | -- and other values will be set | |
49 | -- as members of the object. | |
50 | function Create(ty) | |
51 | return function(data) | |
52 | local obj = Instance.new(ty) | |
53 | for k, v in pairs(data) do | |
54 | if type(k) == 'number' then | |
55 | v.Parent = obj | |
56 | else | |
57 | obj[k] = v | |
58 | end | |
59 | end | |
60 | return obj | |
61 | end | |
62 | end | |
63 | ||
64 | --------------------------------------- | |
65 | -- Same as Make, but modifies an existing | |
66 | -- object rather than creating ones. | |
67 | function Modify(obj, data) | |
68 | for k, v in pairs(data) do | |
69 | if type(data) == 'number' then | |
70 | data.Parent = obj | |
71 | else | |
72 | data[k] = v | |
73 | end | |
74 | end | |
75 | return obj | |
76 | end | |
77 | ||
78 | ----------------------------------------- | |
79 | -- Creates a class which can be instantiated | |
80 | -- using `CreateCLASSNAME( ... )`. | |
81 | ---usage: | |
82 | --class'MyClass'(function(this, arg1) | |
83 | -- this.ClassMember = value | |
84 | -- function this.ClassMethod(...) ... end | |
85 | --end, function(def) | |
86 | -- def.StaticMember = value | |
87 | -- function def.StaticMethod(...) ... end | |
88 | --end) | |
89 | --local obj = CreateMyClass(arg1) | |
90 | ------------------------------------------ | |
91 | local function class(name) | |
92 | local def = {} | |
93 | getfenv(0)[name] = def | |
94 | return function(ctor, static) | |
95 | local nctor = function(...) | |
96 | local this = {} | |
97 | if ctor then | |
98 | ctor(this, ...) | |
99 | end | |
100 | return this | |
101 | end | |
102 | getfenv(0)['Create'..name] = nctor | |
103 | if static then static(def) end | |
104 | end | |
105 | end | |
106 | ||
107 | ||
108 | --------------------------------------------- | |
109 | -- Signal class for custom-made events | |
110 | --API: | |
111 | -- Signal:connect(callback) | |
112 | -- Signal:fire(...) | |
113 | -- Signal:wait() | |
114 | --------------------------------------------- | |
115 | class'Signal'(function(this) | |
116 | local mListeners = {} | |
117 | local mWaitObject = Create'BoolValue'{} | |
118 | ||
119 | function this:connect(func) | |
120 | local connection = {} | |
121 | function connection:disconnect() | |
122 | mListeners[func] = nil | |
123 | end | |
124 | mListeners[func] = connection | |
125 | return connection | |
126 | end | |
127 | ||
128 | function this:fire(...) | |
129 | --print("Fire evt<"..tostring(this).."> from script<"..mDebugId..">") | |
130 | for func, conn in pairs(mListeners) do | |
131 | --print("-> "..tostring(func).."( ... )") | |
132 | func(...) | |
133 | end | |
134 | mWaitObject.Value = not mWaitObject.Value | |
135 | end | |
136 | ||
137 | function this:wait() | |
138 | mWaitObject.Changed:wait() | |
139 | end | |
140 | end) | |
141 | ||
142 | ||
143 | -------------------------------------------------- | |
144 | -- Bin class for cleaning up assets | |
145 | --API: | |
146 | -- Bin:add(func: Function, ident: String) | |
147 | -- Bin:clean(ident: String) | |
148 | -- Bin:cleanAll() | |
149 | -------------------------------------------------- | |
150 | class'Bin'(function(this) | |
151 | local mGarbage = {} | |
152 | ||
153 | function this:add(func, ident) | |
154 | ident = ident or '__unnamed' | |
155 | if not mGarbage[ident] then | |
156 | mGarbage[ident] = {} | |
157 | end | |
158 | mGarbage[ident][#mGarbage[ident]+1] = func | |
159 | end | |
160 | ||
161 | function this:clean(ident) | |
162 | local listToCall = mGarbage[ident] | |
163 | if listToCall then | |
164 | for _, func in pairs(listToCall) do | |
165 | func() | |
166 | end | |
167 | mGarbage[ident] = nil | |
168 | end | |
169 | end | |
170 | ||
171 | function this:cleanAll() | |
172 | for ident, list in pairs(mGarbage) do | |
173 | for _, func in pairs(list) do | |
174 | func() | |
175 | end | |
176 | mGarbage[ident] = nil | |
177 | end | |
178 | end | |
179 | end) | |
180 | ||
181 | ||
182 | ----------------------------------------------------- | |
183 | -- AnimationProvider class for easy loading of | |
184 | -- animation assets into animationtracks once | |
185 | -- a humanoid is available. | |
186 | --API: | |
187 | -- AnimationProvider:registerAnimation(ident, assetid) | |
188 | -- AnimationProvider:setHumanoid(humanoid) | |
189 | -- AnimationProvider:setTool(tool) | |
190 | -- AnimationProvider:getAnimation(ident) | |
191 | ----------------------------------------------------- | |
192 | class'AnimationProvider'(function(this) | |
193 | local mAnimations = {--[[ident => {AnimationId, CurrentTrack, CurrentAnim} ]]} | |
194 | local mCurrentHumanoid = nil | |
195 | ||
196 | function this:registerAnimation(ident, assetid) | |
197 | --check for an existing copy of the anim | |
198 | local existingAnim = Tool.Tool:FindFirstChild('ANIM_'..ident) | |
199 | ||
200 | --make the data for this anim | |
201 | local animdat = { | |
202 | AnimationId = assetid, | |
203 | CurrentAnim = existingAnim or Create'Animation'{ | |
204 | Name = "ANIM_"..ident, | |
205 | AnimationId = assetid, | |
206 | }, | |
207 | } | |
208 | mAnimations[ident] = animdat | |
209 | ||
210 | --if there's a current tool, put it in there | |
211 | if Tool.Tool then | |
212 | Tool.HUGE_EQUIP_HACK = true | |
213 | animdat.CurrentAnim.Parent = Tool.Tool | |
214 | Tool.HUGE_EQUIP_HACK = false | |
215 | end | |
216 | ||
217 | --if there's a humanoid load the animation track | |
218 | if mCurrentHumanoid then | |
219 | animdat.CurrentTrack = mCurrentHumanoid:LoadAnimation(animdat.CurrentAnim) | |
220 | end | |
221 | end | |
222 | ||
223 | function this:setHumanoid(humanoid) | |
224 | mCurrentHumanoid = humanoid | |
225 | for _, anim in pairs(mAnimations) do | |
226 | anim.CurrentTrack = humanoid:LoadAnimation(anim.CurrentAnim) | |
227 | end | |
228 | end | |
229 | ||
230 | function this:getAnimation(ident) | |
231 | local dat = mAnimations[ident] | |
232 | if not dat then error("Gear Fatal Error: Animation `"..ident.."` not found") end | |
233 | if not dat.CurrentTrack then | |
234 | error("Gear Fatal Error: No Humanoid for animation `"..ident.."` to run in") | |
235 | end | |
236 | return dat.CurrentTrack | |
237 | end | |
238 | end) | |
239 | ||
240 | ||
241 | ---------------------------------------------- | |
242 | -- SoundProvider class | |
243 | -- functions similarily to the animationprovider | |
244 | ---------------------------------------------- | |
245 | class'SoundProvider'(function(this) | |
246 | local mSounds = {} | |
247 | ||
248 | function this:registerSound(ident, assetid, inpart) | |
249 | inpart = inpart or Tool.Tool:FindFirstChild('Handle') | |
250 | if not inpart then | |
251 | repeat | |
252 | inpart = Tool.Tool.ChildAdded:wait() | |
253 | until inpart.Name == 'Handle' | |
254 | end | |
255 | local existingSound = inpart:FindFirstChild('SOUND_'..ident) | |
256 | local sounddat = { | |
257 | SoundId = assetid, | |
258 | CurrentSound = existingSound or Create'Sound'{ | |
259 | Name = 'SOUND_'..ident, | |
260 | SoundId = assetid, | |
261 | Parent = inpart, | |
262 | }, | |
263 | } | |
264 | mSounds[ident] = sounddat | |
265 | end | |
266 | ||
267 | function this:getSound(ident) | |
268 | local dat = mSounds[ident] | |
269 | if dat then | |
270 | return dat.CurrentSound | |
271 | end | |
272 | end | |
273 | end) | |
274 | ||
275 | ||
276 | ---------------------------------------------- | |
277 | -- DebounceProvider class -- Prevent events | |
278 | -- from happening in too rapid succession | |
279 | ---------------------------------------------- | |
280 | class'DebounceProvider'(function(this) | |
281 | local mFlagNameToLastTime = {} | |
282 | ||
283 | function this:test(ident, delta) | |
284 | local t = tick() | |
285 | local lastTime = mFlagNameToLastTime[ident] or 0 | |
286 | if delta then | |
287 | return (t-lastTime) > delta | |
288 | else | |
289 | return mFlagNameToLastTime[ident] | |
290 | end | |
291 | end | |
292 | function this:set(ident, state) | |
293 | if state then | |
294 | mFlagNameToLastTime[ident] = state | |
295 | elseif state == false then | |
296 | mFlagNameToLastTime[ident] = false | |
297 | else | |
298 | mFlagNameToLastTime[ident] = tick() | |
299 | end | |
300 | end | |
301 | end) | |
302 | ||
303 | ||
304 | function TagHumanoid(humanoid) | |
305 | if Tool.Player then | |
306 | local tag = Create'ObjectValue'{ | |
307 | Name = "creator", | |
308 | Value = Tool.Player, | |
309 | Parent = humanoid, | |
310 | } | |
311 | game.Debris:AddItem(tag, 1) | |
312 | end | |
313 | end | |
314 | ||
315 | ||
316 | ------- wait for any event in a set of events to fire ------ | |
317 | function WaitForAny(tb) | |
318 | local evt = tb | |
319 | local conn = {} | |
320 | local eventargs = nil | |
321 | local waitProxy = Create'BoolValue'{} | |
322 | for _, e in pairs(evt) do | |
323 | local c = e:connect(function(...) | |
324 | for _, c in pairs(conn) do | |
325 | c:disconnect() | |
326 | end | |
327 | eventargs = {...} | |
328 | waitProxy.Value = not waitProxy.Value | |
329 | end) | |
330 | conn[#conn+1] = c | |
331 | end | |
332 | -- | |
333 | waitProxy.Changed:wait() | |
334 | -- | |
335 | return unpack(eventargs) | |
336 | end | |
337 | ||
338 | ||
339 | ---------------------------------------------- | |
340 | ||
341 | local EmitterPart = nil | |
342 | ||
343 | -- Tool singleton class | |
344 | --API: | |
345 | -- ... | |
346 | class'Tool'(nil, function(this) | |
347 | --need this here for the animationprovider to use | |
348 | this.HUGE_EQUIP_HACK = false | |
349 | ||
350 | this.Bin = CreateBin() | |
351 | this.AnimationProvider = CreateAnimationProvider() | |
352 | this.DebounceProvider = CreateDebounceProvider() | |
353 | this.SoundProvider = CreateSoundProvider() | |
354 | ||
355 | --general values | |
356 | this.Tool = script.Parent | |
357 | this.Player = nil | |
358 | this.Humanoid = nil | |
359 | this.Character = nil | |
360 | ||
361 | --============ several flags for the gear | |
362 | --nothing | |
363 | ||
364 | --some events | |
365 | this.Equipped = CreateSignal() | |
366 | this.Unequipped = CreateSignal() | |
367 | this.OwnerChange = CreateSignal() | |
368 | ||
369 | --mouse utility events | |
370 | this.MouseClick = CreateSignal() | |
371 | this.MouseRelease = CreateSignal() | |
372 | this.MouseDoubleClick = CreateSignal() | |
373 | this.DoubleClickThreshold = 0.2 | |
374 | this.MouseDown = false | |
375 | this.KeyDown = CreateSignal() | |
376 | ||
377 | local mLastClickTime = 0 | |
378 | ||
379 | script.Parent.Equipped:connect(function(mouse) | |
380 | --print("Internal Equipped: Time b: "..time()) | |
381 | --set up general values in the tool | |
382 | this.Mouse = mouse | |
383 | local curOwner = game.Players:GetPlayerFromCharacter(script.Parent.Parent) | |
384 | if curOwner ~= this.Player then | |
385 | this.Player = curOwner | |
386 | this.OwnerChange:fire(this.Player) | |
387 | end | |
388 | this.Character = this.Player.Character | |
389 | this.Humanoid = this.Character.Humanoid | |
390 | this.AnimationProvider:setHumanoid(this.Humanoid) | |
391 | ||
392 | --set up the mouse events | |
393 | mouse.Button1Down:connect(function() | |
394 | this.MouseDown = true | |
395 | local t = tick() | |
396 | if (t-mLastClickTime) < this.DoubleClickThreshold then | |
397 | --prvent multiple double-clicks in a row | |
398 | mLastClickTime = 0 | |
399 | this.MouseDoubleClick:fire(mouse) | |
400 | else | |
401 | mLastClickTime = t | |
402 | this.MouseClick:fire(mouse) | |
403 | end | |
404 | end) | |
405 | mouse.Button1Up:connect(function() | |
406 | this.MouseDown = false | |
407 | if EmitterPart then | |
408 | EmitterPart:Destroy() | |
409 | EmitterPart=nil | |
410 | end | |
411 | end) | |
412 | mouse.KeyDown:connect(function(key) | |
413 | this.KeyDown:fire(key) | |
414 | end) | |
415 | ||
416 | --done setup, call the equipped function | |
417 | if this.HUGE_EQUIP_HACK then | |
418 | --the HUGE_EQUIP_HACK flags tells the tool that the equip is a synchronous | |
419 | --call as a result of parenting an animation to the character, which happens | |
420 | --when the tool is picked up from the workspace, but not during normal equips | |
421 | --(Why does this happen???), if this is the case, the call should be rederrred | |
422 | --one tick to ensure that all of the gear's loading can complete before it's | |
423 | --equipped event is called. | |
424 | --TODO: Blame John for this. | |
425 | Delay(0, function() | |
426 | this.Equipped:fire(mouse) | |
427 | end) | |
428 | else | |
429 | --otherwise, proceed as normal | |
430 | this.Equipped:fire(mouse) | |
431 | end | |
432 | end) | |
433 | ||
434 | script.Parent.Unequipped:connect(function() | |
435 | --before my teardown, fire the event | |
436 | this.Unequipped:fire() | |
437 | ||
438 | --delete all my garbage | |
439 | this.Bin:cleanAll() | |
440 | end) | |
441 | end) | |
442 | ||
443 | ||
444 | ||
445 | ||
446 | ||
447 | ||
448 | ||
449 | ||
450 | ||
451 | ||
452 | ||
453 | ||
454 | ||
455 | ||
456 | ||
457 | ||
458 | ||
459 | ||
460 | ||
461 | ||
462 | ||
463 | ||
464 | ||
465 | ||
466 | local BeamColor = BrickColor.new(Color3.new(255, 0, 0)) | |
467 | local PartModel = Create'Model'{ | |
468 | Name = 'SpotWeld_Parts', | |
469 | } | |
470 | local Failsafe = nil | |
471 | ||
472 | Tool.AnimationProvider:registerAnimation('equip', 'http://www.roblox.com/asset/?id=69427262') | |
473 | Tool.AnimationProvider:registerAnimation('fire', 'http://www.roblox.com/asset/?id=69427271') | |
474 | Tool.AnimationProvider:registerAnimation('hold', 'http://www.roblox.com/asset/?id=69427277') | |
475 | ||
476 | class'RaycastIgnore'(nil, function(def) | |
477 | local mIgnoreMap = setmetatable({}, {__mode='k'}) | |
478 | function def:addIgnore(obj) | |
479 | mIgnoreMap[obj] = true | |
480 | end | |
481 | function def:genIgnoreList() | |
482 | local ignoreList = {} | |
483 | for p, _ in pairs(mIgnoreMap) do | |
484 | ignoreList[#ignoreList+1] = p | |
485 | for _,t in pairs(p:GetChildren()) do | |
486 | if t.Name == 'Effect' then | |
487 | ignoreList[#ignoreList+1] = t | |
488 | end | |
489 | end | |
490 | end | |
491 | for _, ch in pairs(Tool.Character:GetChildren()) do | |
492 | if ch:IsA('BasePart') then | |
493 | ignoreList[#ignoreList+1] = ch | |
494 | end | |
495 | for _, handle in pairs(ch:GetChildren()) do | |
496 | if handle:IsA('BasePart') then | |
497 | ignoreList[#ignoreList+1] = ch | |
498 | end | |
499 | end | |
500 | end | |
501 | return ignoreList | |
502 | end | |
503 | end) | |
504 | ||
505 | class'SpotWeld_Charge'(function(this) | |
506 | this.Completed = CreateSignal() | |
507 | -- | |
508 | local mReady = false | |
509 | local mSpokeList = {} --[i] = {Direction, Part, Len, Dist} | |
510 | local mChargeSphere = nil | |
511 | local mFracComplete = 0 | |
512 | -- | |
513 | local mLocation; | |
514 | -- | |
515 | local mCurrentRun = 0 | |
516 | -- | |
517 | local function genSpokes() | |
518 | if mReady then return end | |
519 | mReady = true | |
520 | ||
521 | --make charge sphere | |
522 | mChargeSphere = Create'Part'{ | |
523 | Name = 'SpotWeld_ChrageSphere', | |
524 | FormFactor = 'Custom', | |
525 | Anchored = true, | |
526 | CanCollide = false, | |
527 | Transparency = 0.3, | |
528 | BrickColor = BeamColor, | |
529 | Create'SpecialMesh'{MeshType='Sphere',}, | |
530 | } | |
531 | RaycastIgnore:addIgnore(mChargeSphere) | |
532 | ||
533 | --make new spokes | |
534 | for i = 1, 20 do | |
535 | local spoke = {} | |
536 | spoke.Part = Create'Part'{ | |
537 | Name = 'SpotWeld_Spoke', | |
538 | FormFactor = 'Custom', | |
539 | Anchored = true, | |
540 | CanCollide = false, | |
541 | Transparency = 0.3, | |
542 | BrickColor = BeamColor, | |
543 | } | |
544 | RaycastIgnore:addIgnore(spoke.Part) | |
545 | mSpokeList[i] = spoke | |
546 | end | |
547 | end | |
548 | local function randomizeSpokes() | |
549 | for _, spoke in pairs(mSpokeList) do | |
550 | spoke.Direction = CFrame.new(mLocation)*CFrame.Angles(math.random(-1.14, 1.14), | |
551 | math.random(-1.14, 1.14), | |
552 | math.random(-1.14, 1.14)) | |
553 | spoke.Len = math.random()*1+1 | |
554 | spoke.Dist = math.random()*1+1 | |
555 | spoke.Part.Size = Vector3.new(0.1, 0.1, spoke.Len) | |
556 | end | |
557 | end | |
558 | local function showSpokes(state) | |
559 | if mReady then | |
560 | local par = ((state) and PartModel or nil) | |
561 | mChargeSphere.Parent = par | |
562 | for _, spoke in pairs(mSpokeList) do | |
563 | spoke.Part.Parent = par | |
564 | end | |
565 | end | |
566 | end | |
567 | local function setSpokes() | |
568 | local sphereSz = mFracComplete | |
569 | mChargeSphere.Size = Vector3.new(sphereSz, sphereSz, sphereSz) | |
570 | mChargeSphere.CFrame = CFrame.new(mLocation) | |
571 | -- | |
572 | for _, spoke in pairs(mSpokeList) do | |
573 | local endDistOut = (1-mFracComplete)*spoke.Dist | |
574 | local innerDistOut = endDistOut-spoke.Len-sphereSz | |
575 | local gotLen; | |
576 | if innerDistOut < 0 then | |
577 | gotLen = spoke.Len+innerDistOut | |
578 | else | |
579 | gotLen = spoke.Len | |
580 | end | |
581 | spoke.Part.Size = Vector3.new(0.1, 0.1, spoke.Len+innerDistOut) | |
582 | spoke.Part.CFrame = spoke.Direction*CFrame.new(0, 0, -(endDistOut-gotLen/2)) | |
583 | end | |
584 | end | |
585 | -- | |
586 | function this:run(location) | |
587 | mLocation = location | |
588 | mCurrentRun = mCurrentRun+1 | |
589 | local thisRun = mCurrentRun | |
590 | mFracComplete = 0 | |
591 | -- | |
592 | genSpokes() | |
593 | randomizeSpokes() | |
594 | showSpokes(true) | |
595 | -- | |
596 | Spawn(function() | |
597 | local lastTime = tick() | |
598 | while mCurrentRun == thisRun and mFracComplete < 1 do | |
599 | local now = tick() | |
600 | local dt = now-lastTime | |
601 | lastTime = now | |
602 | -- | |
603 | mFracComplete = math.min(1, mFracComplete+dt*2) | |
604 | setSpokes() | |
605 | -- | |
606 | wait() | |
607 | end | |
608 | if mCurrentRun == thisRun then | |
609 | showSpokes(false) | |
610 | this.Completed:fire() | |
611 | end | |
612 | end) | |
613 | end | |
614 | function this:stop() | |
615 | showSpokes(false) | |
616 | mCurrentRun = mCurrentRun+1 | |
617 | end | |
618 | -- | |
619 | function this:destroy() | |
620 | mReady = false | |
621 | mChargeSphere:Destroy() | |
622 | for i, spoke in pairs(mSpokeList) do | |
623 | mSpokeList[i] = nil | |
624 | spoke.Part:Destroy() | |
625 | end | |
626 | end | |
627 | end) | |
628 | ||
629 | ||
630 | ||
631 | --[[ | |
632 | locations: | |
633 | ||
634 | C | |
635 | /\ | |
636 | / \ | |
637 | A B | |
638 | locationGetFunc => A, B, C | |
639 | ]] | |
640 | local function frand(a, b) | |
641 | return a+math.random()*(b-a) | |
642 | end | |
643 | class'WavyBeam'(function(this, numSegs) | |
644 | local mSegList = {} | |
645 | for i = 1, numSegs do | |
646 | mSegList[i] = Create'Part'{ | |
647 | Name = 'SpotWeld_BeamBit', | |
648 | Anchored = true, | |
649 | CanCollide = false, | |
650 | FormFactor = 'Custom', | |
651 | BrickColor = BeamColor, | |
652 | Transparency = 0.3, | |
653 | } | |
654 | RaycastIgnore:addIgnore(mSegList[i]) | |
655 | end | |
656 | function this:show(from, to) | |
657 | local totalLen = (from-to).magnitude | |
658 | local wave = math.min(totalLen/5, 1)/2 | |
659 | local dirCF = CFrame.new(from, to) | |
660 | local lastPos = dirCF.p --(dirCF*CFrame.new(frand(-wave, wave), frand(-wave, wave), 0)).p | |
661 | for i = 1, numSegs do | |
662 | local p = mSegList[i] | |
663 | p.Parent = PartModel | |
664 | local distToThisEnd = i*(totalLen/numSegs) | |
665 | local newPos; | |
666 | if i == numSegs then | |
667 | newPos = (dirCF*CFrame.new(0,0,-distToThisEnd)).p | |
668 | else | |
669 | newPos = (dirCF*CFrame.new(frand(-wave, wave), | |
670 | frand(-wave, wave), | |
671 | -distToThisEnd)).p | |
672 | end | |
673 | p.Size = Vector3.new(0.1, 0.1, totalLen/numSegs) | |
674 | p.CFrame = CFrame.new(lastPos, newPos)*CFrame.new(0, 0, -(lastPos-newPos).magnitude/2) | |
675 | lastPos = newPos | |
676 | end | |
677 | end | |
678 | function this:hide() | |
679 | for i = 1, numSegs do | |
680 | mSegList[i].Parent = nil | |
681 | end | |
682 | end | |
683 | end) | |
684 | class'SpotWeld_Beam'(function(this) | |
685 | ||
686 | ||
687 | local mParticleEmitter = Create'Part'{ | |
688 | Name = 'SpotWeld_ParticleEmitter', | |
689 | Anchored = true, | |
690 | CanCollide = false, | |
691 | Transparency = 1, | |
692 | Create'Sound'{ | |
693 | Name = 'HoldSound1', | |
694 | Looped = true, | |
695 | SoundId = 'http://www.roblox.com/asset/?id=100429993', | |
696 | Volume=1 | |
697 | }, | |
698 | Create'Sound'{ | |
699 | Name = 'HoldSound2', | |
700 | Looped = true, | |
701 | SoundId = 'http://www.roblox.com/asset/?id=100429993', | |
702 | Volume=1 | |
703 | }, | |
704 | } | |
705 | RaycastIgnore:addIgnore(mParticleEmitter) | |
706 | local mBeam_AC = CreateWavyBeam(2) | |
707 | local mBeam_BC = CreateWavyBeam(2) | |
708 | -- | |
709 | local mIsShown = false | |
710 | function this:show(a, b, c, showBeam) | |
711 | if not a then | |
712 | this:hide() | |
713 | return | |
714 | end | |
715 | ||
716 | -- | |
717 | mBeam_AC:show(a, c) | |
718 | mBeam_BC:show(b, c) | |
719 | -- | |
720 | ||
721 | -- | |
722 | if showBeam then | |
723 | -- | |
724 | mParticleEmitter.Parent = PartModel | |
725 | mParticleEmitter.CFrame = CFrame.new(c) | |
726 | -- | |
727 | if not mIsShown then | |
728 | mParticleEmitter.HoldSound1:Play() | |
729 | Delay(0.5, function() mParticleEmitter.HoldSound2:Play() end) | |
730 | end | |
731 | mIsShown = true | |
732 | else | |
733 | if EmitterPart then | |
734 | EmitterPart:Destroy() | |
735 | EmitterPart=nil | |
736 | end | |
737 | mParticleEmitter.Parent = nil | |
738 | mIsShown = false | |
739 | end | |
740 | -- | |
741 | end | |
742 | function this:hide() | |
743 | mIsShown = false | |
744 | -- | |
745 | mBeam_AC:hide() | |
746 | mBeam_BC:hide() | |
747 | -- | |
748 | mParticleEmitter.Parent = nil | |
749 | end | |
750 | end) | |
751 | ||
752 | --effects | |
753 | local ChargeEffect = CreateSpotWeld_Charge() | |
754 | local BeamEffect = CreateSpotWeld_Beam() | |
755 | ||
756 | --helper to show the beam | |
757 | function showBeamEffect(target, showBeam) | |
758 | local ch = Tool.Character | |
759 | local head = ch:FindFirstChild("Head") | |
760 | if not (head) then | |
761 | BeamEffect:hide() | |
762 | end | |
763 | -- | |
764 | local ray = CFrame.new(head.Position, target)*CFrame.new(0, 2, -1) | |
765 | local a = (head.CFrame*CFrame.new(-.25, 0, 0)).p | |
766 | local b = (head.CFrame*CFrame.new(.25, 0, 0)).p | |
767 | local c = target | |
768 | -- | |
769 | --local b = (head.CFrame*CFrame.new(-0.3, 0.15, -0.6)).p | |
770 | BeamEffect:show(a, b, c, showBeam) | |
771 | end | |
772 | ||
773 | ||
774 | function findFaceFromCoord(size, loc) | |
775 | local pa, pb = -size/2, size/2 | |
776 | local dx = math.min(math.abs(loc.x-pa.x), math.abs(loc.x-pb.x)) | |
777 | local dy = math.min(math.abs(loc.y-pa.y), math.abs(loc.y-pb.y)) | |
778 | local dz = math.min(math.abs(loc.z-pa.z), math.abs(loc.z-pb.z)) | |
779 | -- | |
780 | if dx < dy and dx < dz then | |
781 | if math.abs(loc.x-pa.x) < math.abs(loc.x-pb.x) then | |
782 | return Enum.NormalId.Left --'Left' | |
783 | else | |
784 | return Enum.NormalId.Right --'Right' | |
785 | end | |
786 | elseif dy < dx and dy < dz then | |
787 | if math.abs(loc.y-pa.y) < math.abs(loc.y-pb.y) then | |
788 | return Enum.NormalId.Bottom --'Bottom' | |
789 | else | |
790 | return Enum.NormalId.Top --'Top' | |
791 | end | |
792 | elseif dz < dx and dz < dy then | |
793 | if math.abs(loc.z-pa.z) < math.abs(loc.z-pb.z) then | |
794 | return Enum.NormalId.Front --'Front' | |
795 | else | |
796 | return Enum.NormalId.Back --'Back' | |
797 | end | |
798 | end | |
799 | end | |
800 | ||
801 | ||
802 | ||
803 | function createFire(part, hit) | |
804 | if (part.Parent or game):FindFirstChild("Humanoid") or | |
805 | ((part.Parent or game).Parent or game):FindFirstChild("Humanoid") then | |
806 | return | |
807 | end | |
808 | if not EmitterPart then | |
809 | EmitterPart = Create'Part'{ | |
810 | Name = 'EmitPart', | |
811 | FormFactor = 'Custom', | |
812 | CanCollide = false, | |
813 | Anchored = true, | |
814 | Size = Vector3.new(.2, .2, .2), | |
815 | Transparency = 1, | |
816 | Parent = script.Parent, | |
817 | } | |
818 | RaycastIgnore:addIgnore(EmitterPart) | |
819 | local emitScript = script:FindFirstChild('Emitter'):Clone() | |
820 | emitScript.Parent=EmitterPart | |
821 | emitScript.Disabled = false | |
822 | end | |
823 | ||
824 | ||
825 | local hitFace = findFaceFromCoord(part.Size, part.CFrame:toObjectSpace(CFrame.new(hit))) | |
826 | local dir = (part.CFrame-part.Position)*Vector3.FromNormalId(hitFace) | |
827 | if part:IsA('Terrain') then | |
828 | EmitterPart.CFrame = CFrame.new(hit) | |
829 | else | |
830 | EmitterPart.CFrame = CFrame.new(hit, hit+dir)*CFrame.Angles(-math.pi/2, 0, 0) | |
831 | end | |
832 | game.Debris:AddItem(scorch, 5) | |
833 | end | |
834 | ||
835 | ||
836 | local mClickNum = 0 | |
837 | local mSelected = false | |
838 | Tool.MouseClick:connect(function() | |
839 | mClickNum = mClickNum+1 | |
840 | local thisClick = mClickNum | |
841 | if not Tool.Mouse.Target or not Tool.Character:FindFirstChild("Head") then | |
842 | return | |
843 | end | |
844 | -- | |
845 | Tool.AnimationProvider:getAnimation('fire'):Play(0, 1, 4) | |
846 | Spawn(function() | |
847 | repeat until Tool.AnimationProvider:getAnimation('fire').KeyframeReached:wait() == 'complete' | |
848 | Tool.AnimationProvider:getAnimation('hold'):Play(0, 1, 1) | |
849 | end) | |
850 | -- | |
851 | Tool.Humanoid.WalkSpeed = 0 | |
852 | -- | |
853 | local headPos = Tool.Character.Head.Position | |
854 | local hit = Tool.Mouse.Hit.p | |
855 | ChargeEffect:run((CFrame.new(headPos, hit)*CFrame.new(0, 2, -3)).p) | |
856 | ChargeEffect.Completed:wait() | |
857 | ChargeEffect:stop() | |
858 | -- | |
859 | local isDamageTick = false | |
860 | local timeOfLastScorch = tick() | |
861 | local partsToIgnore = RaycastIgnore:genIgnoreList() | |
862 | local headPart = Tool.Character:FindFirstChild("Head") | |
863 | while mSelected and Tool.MouseDown and mClickNum == thisClick and headPart do | |
864 | --first, find the true mouse hit, ignoring my ray parts | |
865 | local mouseRay = Tool.Mouse.UnitRay | |
866 | local newRay = Ray.new(mouseRay.Origin, mouseRay.Direction.unit*999.9) | |
867 | local _, hit = game.Workspace:FindPartOnRayWithIgnoreList(newRay, partsToIgnore) | |
868 | ||
869 | --found true hit, now go on to raycast to there from firefrom point | |
870 | local headPos = Tool.Character.Head.Position | |
871 | local fireFrom = (CFrame.new(headPos, hit)*CFrame.new(0, 2, -1)).p | |
872 | local castRay = Ray.new(fireFrom, (hit-fireFrom).unit*999.9) | |
873 | local part, target = game.Workspace:FindPartOnRayWithIgnoreList(castRay, partsToIgnore) | |
874 | ||
875 | local charHeading = Tool.Character.Torso.CFrame.lookVector | |
876 | local outOfFOV = (math.acos((target-fireFrom).unit:Dot(charHeading)) > 1.5) | |
877 | if not target or outOfFOV then | |
878 | --just shoot arbitrarily ahead | |
879 | showBeamEffect((Tool.Character.Head.CFrame*CFrame.new(0, 0, -10)).p, false) | |
880 | ||
881 | elseif (target-fireFrom).magnitude > 50 then | |
882 | --too far away | |
883 | target = fireFrom+(target-fireFrom).unit*50 | |
884 | showBeamEffect(target, false) | |
885 | ||
886 | else | |
887 | --mechanism to do more damage every other tick | |
888 | isDamageTick = not isDamageTick | |
889 | if isDamageTick then | |
890 | --see if the target exists and is a humanoid | |
891 | local hum = (part.Parent or game):FindFirstChild("Humanoid") | |
892 | hum = hum or ((part.Parent or game).Parent or game):FindFirstChild("Humanoid") | |
893 | if hum then | |
894 | --found a humanoid, do damage | |
895 | TagHumanoid(hum) | |
896 | hum:TakeDamage(4) | |
897 | end | |
898 | end | |
899 | ||
900 | --make scorch effects | |
901 | if (tick()-timeOfLastScorch) > 0.1 then | |
902 | timeOfLastScorch = tick() | |
903 | createFire(part, target) | |
904 | end | |
905 | ||
906 | --show the beam | |
907 | showBeamEffect(target, true) | |
908 | end | |
909 | wait() | |
910 | end | |
911 | if mClickNum == thisClick then | |
912 | BeamEffect:hide() | |
913 | Tool.Humanoid.WalkSpeed = 16 | |
914 | Tool.AnimationProvider:getAnimation('hold'):Stop() | |
915 | end | |
916 | end) | |
917 | ||
918 | local mHatPart = nil | |
919 | Tool.Equipped:connect(function() | |
920 | mSelected = true | |
921 | PartModel.Parent = game.Workspace | |
922 | Failsafe = Tool.Tool.Failsafe:Clone() | |
923 | Failsafe.Disabled = false | |
924 | Failsafe.Model.Value = PartModel | |
925 | Failsafe.Humanoid.Value = Tool.Humanoid | |
926 | Failsafe.Parent = PartModel | |
927 | -- | |
928 | Tool.AnimationProvider:getAnimation('equip'):Play(0.1, 1, 4) | |
929 | --Tool.Tool.Grip = CFrame.new() | |
930 | Tool.Tool.Handle.Transparency = 1 | |
931 | -- | |
932 | Spawn(function() | |
933 | --this code causes re-firing of the equipped event fpor some reason? | |
934 | --putting it in a new thread fixes this behavior | |
935 | mHatPart = Tool.Tool.Handle:Clone() | |
936 | mHatPart.Transparency = 0 | |
937 | mHatPart.Parent = Tool.Character | |
938 | local w = Create'Weld'{ | |
939 | Parent = mHatPart, | |
940 | Part0 = mHatPart, | |
941 | Part1 = Tool.Character:FindFirstChild('Head'), | |
942 | C0 = CFrame.new(0.040000014, 0, 0.0199999996, 1, 0, 0, 0, 1.31134158e-007, 1, 0, -1, 1.31134158e-007), | |
943 | C1 = CFrame.new(0, 0.200000003, -0.100000001, 1, 0, 0, 0, -4.37113883e-008, 1, 0, -1, -4.37113883e-008) | |
944 | } | |
945 | end) | |
946 | end) | |
947 | ||
948 | Tool.Unequipped:connect(function() | |
949 | mSelected = false | |
950 | PartModel.Parent = nil | |
951 | Failsafe:Destroy() | |
952 | Failsafe = nil | |
953 | ||
954 | if EmitterPart then | |
955 | EmitterPart:Destroy() | |
956 | EmitterPart=nil | |
957 | end | |
958 | -- | |
959 | Tool.AnimationProvider:getAnimation('equip'):Stop() | |
960 | Tool.AnimationProvider:getAnimation('fire'):Stop() | |
961 | Tool.AnimationProvider:getAnimation('hold'):Stop() | |
962 | --kill any running effects | |
963 | ChargeEffect:stop() | |
964 | BeamEffect:hide() | |
965 | -- | |
966 | Tool.Humanoid.WalkSpeed = 16 | |
967 | --Tool.Handle.Transparency = 0 | |
968 | -- | |
969 | if mHatPart then | |
970 | mHatPart:Destroy() | |
971 | mHatPart = nil | |
972 | end | |
973 | end) | |
974 | ||
975 | end)) | |
976 | Script2.Name = "Emitter" | |
977 | Script2.Parent = LocalScript1 | |
978 | Script2.Disabled = true | |
979 | table.insert(cors,sandbox(Script2,function() | |
980 | local Particle = Instance.new('Part') | |
981 | Particle.Name = 'Effect' | |
982 | Particle.Size = Vector3.new(.2,.2,.2) | |
983 | Particle.CanCollide = false | |
984 | Particle.Transparency = 1 | |
985 | local PartMesh = Instance.new('SpecialMesh') | |
986 | PartMesh.Name = 'PartMesh' | |
987 | PartMesh.MeshId = 'http://www.roblox.com/asset/?id=87112830'--'http://www.roblox.com/asset/?id=96501868'-- | |
988 | PartMesh.TextureId = 'http://www.roblox.com/asset/?id=99871304' | |
989 | PartMesh.Parent=Particle | |
990 | local PartVelocity = Instance.new('BodyVelocity') | |
991 | PartVelocity.maxForce = Vector3.new(99999999,99999999,999999) | |
992 | PartVelocity.velocity= Vector3.new(0,1,0) | |
993 | PartVelocity.Parent=Particle | |
994 | local PartSpin = Instance.new('BodyAngularVelocity') | |
995 | PartSpin.maxTorque = Vector3.new(999999999,99999999,999999) | |
996 | PartSpin.angularvelocity =Vector3.new(1,1,1) | |
997 | PartSpin.Parent=Particle | |
998 | ||
999 | local Lifetime = 2 | |
1000 | local Rate =.1 | |
1001 | ||
1002 | function TweenTransparency(element,starta,enda,length) | |
1003 | local startTime = time() | |
1004 | while time() - startTime < length do | |
1005 | element.Transparency = ((enda - starta) * ((time() - startTime)/length)) + starta | |
1006 | wait(.01) | |
1007 | end | |
1008 | element.Transparency = enda | |
1009 | end | |
1010 | ||
1011 | function TweenScale(element,starts,ends,length) | |
1012 | local startTime = time() | |
1013 | while time() - startTime < length do | |
1014 | element.Scale = ((ends - starts) * ((time() - startTime)/length)) + starts | |
1015 | wait(.01) | |
1016 | end | |
1017 | element.Scale = ends | |
1018 | end | |
1019 | ||
1020 | function TweenColor(element,startc,endc,length) | |
1021 | local startTime = time() | |
1022 | while time() - startTime < length do | |
1023 | element.VertexColor = ((endc - startc) * ((time() - startTime)/length)) + startc | |
1024 | wait(.01) | |
1025 | end | |
1026 | element.VertexColor = endc | |
1027 | end | |
1028 | ||
1029 | while true do | |
1030 | PartVelocity.velocity= Vector3.new((math.random()-.5)/2,math.random()+3,(math.random()-.5)/2) | |
1031 | PartMesh.Scale= Vector3.new((math.random()/2)+.2,math.random()/2+.2,math.random()/2+.2) | |
1032 | PartSpin.angularvelocity =Vector3.new(math.random()*3,math.random()*3,math.random()*3) | |
1033 | Particle.CFrame= script.Parent.CFrame | |
1034 | local npart= Particle:Clone() | |
1035 | local nmesh = npart:FindFirstChild('PartMesh') | |
1036 | npart.Transparency = 1 | |
1037 | npart.Parent=script.Parent | |
1038 | ||
1039 | Spawn(function() | |
1040 | TweenTransparency(npart, 1,.5,.1) | |
1041 | TweenTransparency(npart, .5,1,1.5) | |
1042 | end) | |
1043 | --Spawn(function() | |
1044 | --TweenColor(nmesh, Vector3.new(.8+(math.random()*.4),1,1),Vector3.new(.5,.5,.5),1.5) | |
1045 | --end) | |
1046 | Spawn(function() TweenScale(nmesh,nmesh.Scale,nmesh.Scale*math.random()*.5,1.5) end) | |
1047 | game.Debris:AddItem(npart,Lifetime) | |
1048 | wait(Rate) | |
1049 | ||
1050 | end | |
1051 | end)) | |
1052 | Part3.Name = "Handle" | |
1053 | Part3.Parent = Tool0 | |
1054 | Part3.FormFactor = Enum.FormFactor.Symmetric | |
1055 | Part3.Shape = Enum.PartType.Ball | |
1056 | Part3.Size = Vector3.new(1, 1, 1) | |
1057 | Part3.CFrame = CFrame.new(80.6800003, 19.2970848, 174.050003, 1, -2.21533113e-17, 9.25474816e-17, 2.21533113e-17, 1, -3.76204621e-17, -9.25474816e-17, 3.76204621e-17, 1) | |
1058 | Part3.BottomSurface = Enum.SurfaceType.Smooth | |
1059 | Part3.TopSurface = Enum.SurfaceType.Smooth | |
1060 | Part3.Position = Vector3.new(80.6800003, 19.2970848, 174.050003) | |
1061 | SpecialMesh4.Parent = Part3 | |
1062 | SpecialMesh4.MeshId = "http://www.roblox.com/asset/?id=1185246" | |
1063 | SpecialMesh4.Scale = Vector3.new(4, 4, 4) | |
1064 | SpecialMesh4.TextureId = "http://www.roblox.com/asset/?id=5013397" | |
1065 | SpecialMesh4.MeshType = Enum.MeshType.FileMesh | |
1066 | SpecialMesh4.Scale = Vector3.new(4, 4, 4) | |
1067 | Script5.Name = "Failsafe" | |
1068 | Script5.Parent = Tool0 | |
1069 | Script5.Disabled = true | |
1070 | table.insert(cors,sandbox(Script5,function() | |
1071 | while not script:FindFirstChild("Humanoid") do | |
1072 | script.ChildAdded:wait() | |
1073 | end | |
1074 | script.Humanoid.Value.Died:connect(function() | |
1075 | script.Model.Value:Destroy() | |
1076 | end) | |
1077 | end)) | |
1078 | ObjectValue6.Name = "Model" | |
1079 | ObjectValue6.Parent = Script5 | |
1080 | ObjectValue7.Name = "Humanoid" | |
1081 | ObjectValue7.Parent = Script5 | |
1082 | for i,v in pairs(mas:GetChildren()) do | |
1083 | v.Parent = game:GetService("Players").LocalPlayer.Backpack | |
1084 | pcall(function() v:MakeJoints() end) | |
1085 | end | |
1086 | mas:Destroy() | |
1087 | for i,v in pairs(cors) do | |
1088 | spawn(function() | |
1089 | pcall(v) | |
1090 | end) | |
1091 | end |