· 7 years ago · Feb 08, 2019, 10:56 PM
1local class = require(game.ReplicatedStorage.BehaviorTree.middleclass)
2local Registry = require(game.ReplicatedStorage.BehaviorTree.registry)
3local Node = require(game.ReplicatedStorage.BehaviorTree.node_types.node)
4local BehaviorTree = class('BehaviorTree', Node)
5
6BehaviorTree.Node = Node
7BehaviorTree.Registry = Registry
8BehaviorTree.Task = Node
9BehaviorTree.BranchNode = require(game.ReplicatedStorage.BehaviorTree.node_types.branch_node)
10BehaviorTree.Priority = require(game.ReplicatedStorage.BehaviorTree.node_types.priority)
11BehaviorTree.ActivePriority = require(game.ReplicatedStorage.BehaviorTree.node_types.active_priority)
12BehaviorTree.Random = require(game.ReplicatedStorage.BehaviorTree.node_types.random)
13BehaviorTree.Sequence = require(game.ReplicatedStorage.BehaviorTree.node_types.sequence)
14BehaviorTree.Decorator = require(game.ReplicatedStorage.BehaviorTree.node_types.decorator)
15BehaviorTree.InvertDecorator = require(game.ReplicatedStorage.BehaviorTree.node_types.invert_decorator)
16BehaviorTree.AlwaysFailDecorator = require(game.ReplicatedStorage.BehaviorTree.node_types.always_fail_decorator)
17BehaviorTree.AlwaysSucceedDecorator = require(game.ReplicatedStorage.BehaviorTree.node_types.always_succeed_decorator)
18
19BehaviorTree.register = Registry.register
20BehaviorTree.getNode = Registry.getNode
21
22function BehaviorTree:run(object)
23 if self.started then
24 Node.running(self) --call running if we have control
25 else
26 self.started = true
27 self.object = object or self.object
28 self.rootNode = Registry.getNode(self.tree)
29 self.rootNode:setControl(self)
30 self.rootNode:start(self.object)
31 self.rootNode:call_run(self.object)
32 end
33end
34
35function BehaviorTree:running()
36 Node.running(self)
37 self.started = false
38end
39
40function BehaviorTree:success()
41 self.rootNode:finish(self.object);
42 self.started = false
43 Node.success(self)
44end
45
46function BehaviorTree:fail()
47 self.rootNode:finish(self.object);
48 self.started = false
49 Node.fail(self)
50end
51
52return BehaviorTree
53
54
55local class = require(game.ReplicatedStorage.BehaviorTree.middleclass)
56local Registry = require(game.ReplicatedStorage.BehaviorTree.registry)
57local Priority = require(game.ReplicatedStorage.BehaviorTree.node_types.priority)
58local ActivePriority = class('ActivePriority', Priority)
59
60function ActivePriority:success()
61 self:_finishRunningNode()
62 self.runningTask = nil
63 Priority.success(self)
64end
65
66function ActivePriority:fail()
67 if self.runningTask == self.actualTask then
68 -- The previously-running task just failed
69 self.runningTask = nil
70 end
71 Priority.fail(self)
72end
73
74function ActivePriority:running()
75 self:_finishRunningNode()
76 self.runningTask = self.actualTask
77 self.control:running()
78 self.actualTask = 1
79end
80
81function ActivePriority:_finishRunningNode()
82 if self.runningTask and self.runningTask > self.actualTask then
83 local runningNode = Registry.getNode(self.nodes[self.runningTask])
84 runningNode:finish()
85 end
86end
87
88return ActivePriority
89
90
91local class = require(game.ReplicatedStorage.BehaviorTree.middleclass)
92local Decorator = require(game.ReplicatedStorage.BehaviorTree.node_types.decorator)
93local AlwaysFailDecorator = class('AlwaysFailDecorator', Decorator)
94
95function AlwaysFailDecorator:success()
96 self.control:fail()
97end
98
99function AlwaysFailDecorator:fail()
100 self.control:fail()
101end
102
103return AlwaysFailDecorator
104
105
106
107local class = require(game.ReplicatedStorage.BehaviorTree.middleclass)
108local Decorator = require(game.ReplicatedStorage.BehaviorTree.node_types.decorator)
109local AlwaysSucceedDecorator = class('AlwaysSucceedDecorator', Decorator)
110
111function AlwaysSucceedDecorator:success()
112 self.control:success()
113end
114
115function AlwaysSucceedDecorator:fail()
116 self.control:success()
117end
118
119return AlwaysSucceedDecorator
120
121
122local class = require(game.ReplicatedStorage.BehaviorTree.middleclass)
123local Registry = require(game.ReplicatedStorage.BehaviorTree.registry)
124local Node = require(game.ReplicatedStorage.BehaviorTree.node_types.node)
125local BranchNode = class('BranchNode', Node)
126
127function BranchNode:start(object)
128 if not self.nodeRunning then
129 self:setObject(object)
130 self.actualTask = 1
131 end
132end
133
134function BranchNode:run(object)
135 if self.actualTask <= #self.nodes then
136 self:_run(object)
137 end
138end
139
140function BranchNode:_run(object)
141 if not self.nodeRunning then
142 self.node = Registry.getNode(self.nodes[self.actualTask])
143 self.node:start(object)
144 self.node:setControl(self)
145 end
146 self.node:run(object)
147end
148
149function BranchNode:running()
150 self.nodeRunning = true
151 self.control:running()
152end
153
154function BranchNode:success()
155 self.nodeRunning = false
156 self.node:finish(self.object)
157 self.node = nil
158end
159
160function BranchNode:fail()
161 self.nodeRunning = false
162 self.node:finish(self.object);
163 self.node = nil
164end
165
166return BranchNode
167
168
169local class = require(game.ReplicatedStorage.BehaviorTree.middleclass)
170local Registry = require(game.ReplicatedStorage.BehaviorTree.registry)
171local Node = require(game.ReplicatedStorage.BehaviorTree.node_types.node)
172local Decorator = class('Decorator', Node)
173
174function Decorator:initialize(config)
175 Node.initialize(self, config)
176 self.node = Registry.getNode(self.node)
177end
178
179function Decorator:setNode(node)
180 self.node = Registry.getNode(node)
181end
182
183function Decorator:start(object)
184 self.node:start(object)
185end
186
187function Decorator:finish(object)
188 self.node:finish(object)
189end
190
191function Decorator:run(object)
192 self.node:setControl(self)
193 self.node:call_run(object)
194end
195
196return Decorator
197
198
199local class = require(game.ReplicatedStorage.BehaviorTree.middleclass)
200local Registry = require(game.ReplicatedStorage.BehaviorTree.registry)
201local Decorator = require(game.ReplicatedStorage.BehaviorTree.node_types.decorator)
202local InvertDecorator = class('InvertDecorator', Decorator)
203
204function InvertDecorator:success()
205 self.control:fail()
206end
207
208function InvertDecorator:fail()
209 self.control:success()
210end
211
212return InvertDecorator
213
214
215local class = require(game.ReplicatedStorage.BehaviorTree.middleclass)
216local Registry = require(game.ReplicatedStorage.BehaviorTree.registry)
217local Node = class('Node')
218
219function Node:initialize(config)
220 config = config or {}
221 for k, v in pairs(config) do
222 self[k] = v
223 end
224
225 if self.name ~= nil then
226 Registry.register(self.name, self)
227 end
228end
229
230function Node:start() end
231function Node:finish() end
232function Node:run() end
233
234function Node:call_run(object)
235-- success = function() self:success() end
236-- fail = function() self:fail() end
237-- running = function() self:running() end
238 self:run(object)
239-- success, fail, running = nil,nil,nil
240end
241
242function Node:setObject(object)
243 self.object = object
244end
245
246function Node:setControl(control)
247 self.control = control
248end
249
250function Node:running()
251 if self.control then
252 self.control:running(self)
253 end
254end
255
256function Node:success()
257 if self.control then
258 self.control:success()
259 end
260end
261
262function Node:fail()
263 if self.control then
264 self.control:fail()
265 end
266end
267
268return Node
269
270
271local class = require(game.ReplicatedStorage.BehaviorTree.middleclass)
272local Registry = require(game.ReplicatedStorage.BehaviorTree.registry)
273local BranchNode = require(game.ReplicatedStorage.BehaviorTree.node_types.branch_node)
274local Priority = class('Priority', BranchNode)
275
276function Priority:success()
277 BranchNode.success(self)
278 self.control:success()
279end
280
281function Priority:fail()
282 BranchNode.fail(self)
283 self.actualTask = self.actualTask + 1
284 if self.actualTask <= #self.nodes then
285 self:_run(self.object)
286 else
287 self.control:fail()
288 end
289end
290
291return Priority
292
293
294local class = require(game.ReplicatedStorage.BehaviorTree.middleclass)
295local BranchNode = require(game.ReplicatedStorage.BehaviorTree.node_types.branch_node)
296local Random = class('Random', BranchNode)
297
298function Random:start(object)
299 BranchNode.start(self, object)
300 self.actualTask = math.floor(math.random() * #self.nodes+1)
301end
302
303function Random:success()
304 BranchNode.success(self)
305 self.control:success()
306end
307
308function Random:fail()
309 BranchNode.fail(self)
310 self.control:fail()
311end
312
313return Random
314
315
316local class = require(game.ReplicatedStorage.BehaviorTree.middleclass)
317local BranchNode = require(game.ReplicatedStorage.BehaviorTree.node_types.branch_node)
318local Sequence = class('Sequence', BranchNode)
319
320function Sequence:success()
321 BranchNode.success(self)
322 self.actualTask = self.actualTask + 1
323 if self.actualTask <= #self.nodes then
324 self:_run(self.object)
325 else
326 self.control:success()
327 end
328end
329
330function Sequence:fail()
331 BranchNode.fail(self)
332 self.control:fail()
333end
334
335return Sequence
336
337
338local middleclass = {
339 _VERSION = 'middleclass v3.0.1',
340 _DESCRIPTION = 'Object Orientation for Lua',
341 _URL = 'https://github.com/kikito/middleclass',
342 _LICENSE = [[
343 MIT LICENSE
344
345 Copyright (c) 2011 Enrique GarcÃa Cota
346
347 Permission is hereby granted, free of charge, to any person obtaining a
348 copy of this software and associated documentation files (the
349 "Software"), to deal in the Software without restriction, including
350 without limitation the rights to use, copy, modify, merge, publish,
351 distribute, sublicense, and/or sell copies of the Software, and to
352 permit persons to whom the Software is furnished to do so, subject to
353 the following conditions:
354
355 The above copyright notice and this permission notice shall be included
356 in all copies or substantial portions of the Software.
357
358 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
359 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
360 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
361 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
362 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
363 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
364 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
365 ]]
366}
367
368local function _setClassDictionariesMetatables(aClass)
369 local dict = aClass.__instanceDict
370 dict.__index = dict
371
372 local super = aClass.super
373 if super then
374 local superStatic = super.static
375 setmetatable(dict, super.__instanceDict)
376 setmetatable(aClass.static, { __index = function(_,k) return dict[k] or superStatic[k] end })
377 else
378 setmetatable(aClass.static, { __index = function(_,k) return dict[k] end })
379 end
380end
381
382local function _setClassMetatable(aClass)
383 setmetatable(aClass, {
384 __tostring = function() return "class " .. aClass.name end,
385 __index = aClass.static,
386 __newindex = aClass.__instanceDict,
387 __call = function(self, ...) return self:new(...) end
388 })
389end
390
391local function _createClass(name, super)
392 local aClass = { name = name, super = super, static = {}, __mixins = {}, __instanceDict={} }
393 aClass.subclasses = setmetatable({}, {__mode = "k"})
394
395 _setClassDictionariesMetatables(aClass)
396 _setClassMetatable(aClass)
397
398 return aClass
399end
400
401local function _createLookupMetamethod(aClass, name)
402 return function(...)
403 local method = aClass.super[name]
404 assert( type(method)=='function', tostring(aClass) .. " doesn't implement metamethod '" .. name .. "'" )
405 return method(...)
406 end
407end
408
409local function _setClassMetamethods(aClass)
410 for _,m in ipairs(aClass.__metamethods) do
411 aClass[m]= _createLookupMetamethod(aClass, m)
412 end
413end
414
415local function _setDefaultInitializeMethod(aClass, super)
416 aClass.initialize = function(instance, ...)
417 return super.initialize(instance, ...)
418 end
419end
420
421local function _includeMixin(aClass, mixin)
422 assert(type(mixin)=='table', "mixin must be a table")
423 for name,method in pairs(mixin) do
424 if name ~= "included" and name ~= "static" then aClass[name] = method end
425 end
426 if mixin.static then
427 for name,method in pairs(mixin.static) do
428 aClass.static[name] = method
429 end
430 end
431 if type(mixin.included)=="function" then mixin:included(aClass) end
432 aClass.__mixins[mixin] = true
433end
434
435local Object = _createClass("Object", nil)
436
437Object.static.__metamethods = { '__add', '__call', '__concat', '__div', '__ipairs', '__le',
438 '__len', '__lt', '__mod', '__mul', '__pairs', '__pow', '__sub',
439 '__tostring', '__unm'}
440
441function Object.static:allocate()
442 assert(type(self) == 'table', "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'")
443 return setmetatable({ class = self }, self.__instanceDict)
444end
445
446function Object.static:new(...)
447 local instance = self:allocate()
448 instance:initialize(...)
449 return instance
450end
451
452function Object.static:subclass(name)
453 assert(type(self) == 'table', "Make sure that you are using 'Class:subclass' instead of 'Class.subclass'")
454 assert(type(name) == "string", "You must provide a name(string) for your class")
455
456 local subclass = _createClass(name, self)
457 _setClassMetamethods(subclass)
458 _setDefaultInitializeMethod(subclass, self)
459 self.subclasses[subclass] = true
460 self:subclassed(subclass)
461
462 return subclass
463end
464
465function Object.static:subclassed(other) end
466
467function Object.static:isSubclassOf(other)
468 return type(other) == 'table' and
469 type(self) == 'table' and
470 type(self.super) == 'table' and
471 ( self.super == other or
472 type(self.super.isSubclassOf) == 'function' and
473 self.super:isSubclassOf(other)
474 )
475end
476
477function Object.static:include( ... )
478 assert(type(self) == 'table', "Make sure you that you are using 'Class:include' instead of 'Class.include'")
479 for _,mixin in ipairs({...}) do _includeMixin(self, mixin) end
480 return self
481end
482
483function Object.static:includes(mixin)
484 return type(mixin) == 'table' and
485 type(self) == 'table' and
486 type(self.__mixins) == 'table' and
487 ( self.__mixins[mixin] or
488 type(self.super) == 'table' and
489 type(self.super.includes) == 'function' and
490 self.super:includes(mixin)
491 )
492end
493
494function Object:initialize() end
495
496function Object:__tostring() return "instance of " .. tostring(self.class) end
497
498function Object:isInstanceOf(aClass)
499 return type(self) == 'table' and
500 type(self.class) == 'table' and
501 type(aClass) == 'table' and
502 ( aClass == self.class or
503 type(aClass.isSubclassOf) == 'function' and
504 self.class:isSubclassOf(aClass)
505 )
506end
507
508
509
510function middleclass.class(name, super, ...)
511 super = super or Object
512 return super:subclass(name, ...)
513end
514
515middleclass.Object = Object
516
517setmetatable(middleclass, { __call = function(_, ...) return middleclass.class(...) end })
518
519return middleclass
520
521
522local registeredNodes = {}
523
524local Registry = {}
525
526function Registry.register(name, node)
527 registeredNodes[name] = node;
528end
529
530function Registry.getNode(name)
531 if type(name) == 'string' then
532 return registeredNodes[name]
533 else
534 return name
535 end
536end
537
538return Registry
539
540
541--[[
542 to use: place the BehaviorTree folder in ReplicatedStorage
543
544
545 documentation on how to use this library:
546 https://github.com/oniich-n/behaviortree.rbxlua
547
548 check out the included examples as well
549
550 <3, oniich_n
551--]]
552
553local BT = require(game.ReplicatedStorage.BehaviorTree.behavior_tree)
554local count
555
556local looking = BT.Task:new()
557function looking:run()
558 print("looking")
559 self:success()
560end
561local runningTask = BT.Task:new()
562function runningTask:run()
563 print("running")
564 if count == 10 then
565 self:success()
566 else
567 self:running()
568 end
569end
570
571BT.register('looking', looking)
572BT.register('running', runningTask)
573
574local Frank = BT:new({
575 tree = BT.Sequence:new({
576 nodes = {
577 'looking', 'running'
578 }
579 })
580})
581
582for i = 1, 20 do
583 count = i
584 Frank:run()
585end
586
587
588
589local BT = require(game.ReplicatedStorage.BehaviorTree.behavior_tree)
590
591local Frank = BT:new({
592 object = {name = 'test'},
593 tree = BT.Sequence:new({
594 nodes = {
595 BT.Task:new({
596 run = function(task, object)
597 print(object.name .. " looking")
598 task:success()
599 end
600 }),
601 BT.Random:new({
602 nodes = {
603 BT.Task:new({
604 run = function(task, object)
605 print(object.name .. " walk left")
606 task:success()
607 end
608 }),
609 BT.Task:new({
610 run = function(task, object)
611 print(object.name .. " walk up")
612 task:success()
613 end
614 }),
615 BT.Task:new({
616 run = function(task, object)
617 print(object.name .. " walk right")
618 task:success()
619 end
620 }),
621 BT.Task:new({
622 run = function(task, object)
623 print(object.name .. " walk down")
624 task:success()
625 end
626 }),
627 }
628 }),
629 }
630 })
631})
632
633for _ = 1, 20 do
634 Frank:run()
635end
636
637
638local Loaded = {}
639
640return function(name, async)
641 local module = script:FindFirstChild(name, true)
642 local loadState = Loaded[name]
643
644 if not loadState then
645 local bind = Instance.new("BindableEvent")
646
647 loadState = {
648 loaded = false,
649 event = bind.Event,
650 name = name,
651 path = module:GetFullName():gsub("^.*%.([^.]+)%.Load%.", "%1.")
652 }
653
654 Loaded[name] = loadState
655
656 coroutine.wrap(function()
657-- local timer = tick()
658 require(module)
659-- local elapsed = tick() - timer
660-- warn(("%s: %dms"):format(loadState.path, elapsed * 1e3))
661
662 loadState.loaded = true
663 loadState.event = nil
664
665 bind:Fire()
666 bind:Destroy()
667 bind = nil
668 end)()
669 end
670
671 if async then
672 if not loadState.async then
673 local result = {}
674
675 if loadState.loaded then
676 setmetatable(result, { __index = require(module), __newindex = require(module) })
677 else
678 setmetatable(result, {
679 __index = function(t, i)
680 warn(("Tried to access %s.%s before it was loaded\n%s"):format(name, tostring(i), debug.traceback()))
681 end
682 })
683
684 loadState.event:Connect(function()
685 setmetatable(result, { __index = require(module), __newindex = require(module) })
686 end)
687 end
688
689 loadState.async = result
690 end
691
692 return loadState.async
693 end
694
695 if not loadState.loaded then
696 local calleeState = Loaded[tostring(getfenv(2).script)]
697 if calleeState then
698 calleeState.requiring = loadState
699 end
700
701 if loadState.requiring then
702 local list = {}
703
704 local target = loadState
705 while not target.loaded and target.requiring and not list[target] do
706 list[target] = true
707 list[#list + 1] = target.path
708 target = target.requiring
709 end
710
711 if not target.loaded and list[target] then
712 list[#list + 1] = target.path
713 warn(("Found a recursive dependency: %s"):format(table.concat(list, " > ")))
714 end
715 end
716
717 loadState.event:Wait()
718
719 if calleeState and calleeState.requiring == loadState then
720 calleeState.requiring = nil
721 end
722 end
723
724 return require(module)
725end
726
727local module = {}
728
729
730local players = game:GetService("Players");
731local player = players.LocalPlayer;
732local mouse = player:GetMouse();
733
734local CollectionService = game:GetService("CollectionService");
735
736local CAS = game:GetService("ContextActionService");
737
738local UserInputService = game:GetService("UserInputService");
739
740
741local ReplicatedStorage = game:GetService("ReplicatedStorage");
742local LoadModule = require(ReplicatedStorage.Modules.Load);
743local WildLife = LoadModule("WildLife",true);
744
745local ValidCharacterParts = {
746 "LeftFoot", "LeftHand", "LeftLowerArm", "LeftLowerLeg", "LeftUpperArm", "LeftUpperLeg",
747 "RightFoot", "RightHand", "RightLowerArm", "RightLowerLeg", "RightUpperArm", "RightUpperLeg",
748 "UpperTorso", "LowerTorso", "Head"
749}
750local temp = {};
751for _,v in pairs(ValidCharacterParts) do
752 temp[v]=true;
753end
754module.ValidCharacterParts=temp;
755
756
757local FootstepMaterials =
758{
759 "Sand",
760 "Wood",
761 "WoodBox",
762 "Fabric",
763 "Sandstone",
764 "Limestone",
765 "Mud",
766 "Ground",
767 "Grass",
768 "LeafyGrass",
769 "Rock",
770 "Metal",
771 "Mud"
772}
773
774for _,v in pairs(FootstepMaterials) do
775 FootstepMaterials[v]=true;
776end
777module.FootstepMaterials=FootstepMaterials;
778
779local terrain = workspace.Terrain;
780
781
782
783function GetCloneOf(item, real, clone)
784 if item then
785 return item == real and clone or GetCloneOf(item.Parent, real, clone)[item.Name]
786 end
787end
788
789local threadBind = Instance.new("BindableEvent")
790
791
792
793
794
795
796
797
798
799
800module.AreKeysPressed = function(keys)
801
802 if typeof(keys) ~= "table" then
803 keys={keys};
804 end
805
806 local passed = false;
807
808 --[=[
809 Either going to be a keycode or a userinputtype(in this case we can use IsMouseButtonPressed
810 --]=]
811
812
813 for _,enum in pairs(keys) do
814 if typeof(enum) == "EnumItem" then
815 if tostring(enum.EnumType) == "KeyCode" then
816 if UserInputService:IsKeyDown(enum) then
817 passed=true;
818 end
819 else
820
821 if UserInputService:IsMouseButtonPressed(enum) then
822 passed=true;
823 end
824 end
825 end
826 end
827
828
829 if passed then
830 return true;
831 end
832end
833
834
835
836module.Thread = function(fn)
837 local bind = threadBind
838 threadBind = nil
839
840 local con = bind.Event:Connect(fn)
841 bind:Fire()
842 con:Disconnect()
843
844 if threadBind == nil then
845 threadBind = bind
846 else
847 bind:Destroy()
848 end
849end
850
851module.GetCloneOf = GetCloneOf;
852
853module.DrawRay = function(ray)
854 local origin = ray.Origin;
855 local direction = ray.Direction;
856
857
858 local att0 = Instance.new("Attachment",terrain);
859 att0.CFrame=CFrame.new(origin);
860
861 local att1 = Instance.new("Attachment",terrain);
862 att1.CFrame=CFrame.new(origin+direction);
863
864 local beam = Instance.new("Beam",terrain);
865 beam.Color=ColorSequence.new(Color3.new(1,0,0));
866 beam.Transparency=NumberSequence.new(0.8);
867 beam.FaceCamera=true;
868 beam.Attachment0=att0;
869 beam.Attachment1=att1;
870
871 game.Debris:AddItem(beam,.25);
872 game.Debris:AddItem(att0,.25);
873 game.Debris:AddItem(att1,.25);
874
875end
876
877
878
879local NewRay = Ray.new;
880
881local Ignore = workspace:WaitForChild("Ignore");
882
883
884local function CreateInvisiblePart(cframe)
885 local part = Instance.new("Part",Ignore);
886 part.Anchored=true;
887 part.CFrame=cframe;
888 part.Transparency=1;
889 part.CanCollide=false;
890 return part;
891end
892module.CreateInvisiblePart=CreateInvisiblePart;
893
894local cam = workspace.CurrentCamera;
895
896module.GetMouseHit = function(dist)
897
898 dist=dist or 200;
899 local ignoreList = { player.Character, Ignore,cam}
900
901 local ControllingAnimals = WildLife.ControllingAnimals;
902 for animal,_ in pairs(ControllingAnimals) do
903 ignoreList[#ignoreList + 1] = animal.character;
904 end
905 if WildLife.RidingAnimal then
906 ignoreList[#ignoreList + 1] = WildLife.RidingAnimal.character;
907 end
908
909 local ray = NewRay(mouse.UnitRay.Origin,mouse.UnitRay.Direction*dist);
910 local hit,pos = workspace:FindPartOnRayWithIgnoreList(ray, ignoreList)
911
912 return pos, hit;
913end
914
915
916local function CantMoveHandler()
917 return Enum.ContextActionResult.Sink
918end
919
920module.ToggleCantMove = function(cantmove)
921 if cantmove then
922 CAS:BindActionAtPriority("CantMove",CantMoveHandler,false,Enum.ContextActionPriority.High.Value,unpack(Enum.PlayerActions:GetEnumItems()));
923 else
924 CAS:UnbindAction("CantMove");
925 end
926end
927
928
929module.ConnectRoot = function(char)
930 local human = char:FindFirstChildOfClass("Humanoid")
931 local lowerTorso = char:FindFirstChild("LowerTorso")
932 if not human or not lowerTorso then return end
933
934 local rootJoint = lowerTorso:FindFirstChild("Root")
935 if not rootJoint then return end
936
937 rootJoint.Part0 = human.RootPart
938end
939
940module.DisconnectRoot = function(char)
941 local lowerTorso = char:FindFirstChild("LowerTorso")
942 if not lowerTorso then return end
943
944 local rootJoint = lowerTorso:FindFirstChild("Root")
945 if not rootJoint then return end
946
947 rootJoint.Part0 = nil
948end
949
950
951return module
952
953
954local Mathf = {}
955function Mathf.Clamp(Num,Min,Max)
956 return Num < Min and Min or Num > Max and Max or Num
957end
958function Mathf.Lerp(n,g,t)
959 return n+(g-n)*t
960end
961function Mathf.Wrap(Number,Min,Max)
962 return (Number-Min)%(Max-Min)+Min
963end
964function Mathf.Cubic_Interpolate(v0, v1, v2, v3,x)
965 local P = (v3 - v2) - (v0 - v1)
966 local Q = (v0 - v1) - P
967 local R = v2 - v0
968 local S = v1
969
970 return P*x^3 + Q*x^2 + R*x + S
971 end
972function Mathf.Round(n,m,b)
973 return math.floor(n/m+b)*m
974end
975function Mathf.InPart(part,pos)
976 local rel=part.CFrame:pointToObjectSpace(pos)
977 if math.abs(rel.x) <= part.Size.x/2 and math.abs(rel.y) <= part.Size.y/2 and math.abs(rel.z) <= part.Size.z/2 then
978 return true
979 end
980 return false
981end
982function Mathf.IK(a,b,l1,l2) --joint pivot, end point, length 1, length 2
983 if (a-b).magnitude >= l1+l2 then
984 return CFrame.new(a,b),0,0
985 end
986 if (a-b).magnitude < (math.max(l1,l2)-math.min(l1,l2)) then
987 return CFrame.new(a,b),0,math.pi
988 end
989 local cf=CFrame.new(a,b)
990 local b=cf:pointToObjectSpace(b)
991 local x=(b.z^2-l2^2+l1^2)/(2*b.z)
992 local y=math.sqrt(1-(x/l1)^2)*l1
993 local a1=-math.asin(y/((x^2+y^2)^0.5))
994 local a2=(x < b.z) and -math.pi+math.asin(-y/(((b.z-x)^2+y^2)^0.5)) or -math.asin(-y/(((b.z-x)^2+y^2)^0.5))
995
996 return cf,a1,a2-a1
997end
998function Mathf.DirectionToPlane(relPos,v)
999 local plane=relPos.x <= -v.Size.x/2 and "-x" or relPos.x >= v.Size.x/2 and "x" or relPos.z <= -v.Size.z/2 and "-z" or relPos.z >= v.Size.z/2 and "z"
1000 local lv = relPos.lookVector
1001 local forw, dist, dist2
1002 if plane =="-x" then
1003 forw=lv.x
1004 dist=math.abs(math.abs(relPos.x)-v.Size.x/2)
1005 dist2=math.abs(math.abs(relPos.x)+v.Size.x/2)
1006 elseif plane=="x" then
1007 forw=lv.x
1008 dist=-math.abs(math.abs(relPos.x)-v.Size.x/2)
1009 dist2=-math.abs(math.abs(relPos.x)+v.Size.x/2)
1010 elseif plane=="z" then
1011 forw=lv.z
1012 dist=math.abs(math.abs(relPos.z)-v.Size.z/2)
1013 dist2=math.abs(math.abs(relPos.z)+v.Size.z/2)
1014 elseif plane=="-z" then
1015 forw=lv.z
1016 dist=-math.abs(math.abs(relPos.z)-v.Size.z/2)
1017 dist2=-math.abs(math.abs(relPos.z)+v.Size.z/2)
1018 end
1019 local amt=dist/forw
1020 local amt2=dist2/forw
1021 local pos=relPos.p+lv*amt
1022 pos=CFrame.new(Mathf.Clamp(pos.x,-v.Size.x/2,v.Size.x/2),Mathf.Clamp(pos.y,-v.Size.y/2,v.Size.y/2),Mathf.Clamp(pos.z,-v.Size.z/2,v.Size.z/2))
1023 return pos
1024end
1025function Mathf.Noise(input,inc,Seed)
1026 input=input+Seed
1027 local point1=Mathf.Round(input,inc,0)
1028 local npoint1=Mathf.Round(input,inc,-1)
1029 local epoint1=Mathf.Round(input,inc,0.99)
1030 local nepoint1=Mathf.Round(input,inc,1.99)
1031 if point1== 0 then point1 = 1 end
1032 if npoint1==0 then npoint1=1 end
1033 if epoint1==0 then epoint1=1 end
1034 if nepoint1==0 then nepoint1=1 end
1035 local ntepoint1=(math.sin(nepoint1+nepoint1/nepoint1*math.tan(nepoint1))+1)/2
1036 local ntpoint1=(math.sin(npoint1+npoint1/npoint1*math.tan(npoint1))+1)/2
1037 local tpoint1=(math.sin(point1+point1/point1*math.tan(point1))+1)/2
1038 local tepoint1=(math.sin(epoint1+epoint1/epoint1*math.tan(epoint1))+1)/2
1039 local dist=math.abs(point1-epoint1)
1040 local perc
1041 if dist~=0 then
1042 perc=math.abs(input-point1)/dist
1043 else
1044 perc=1
1045 end
1046 local avg=(tepoint1)
1047 local av=(tpoint1)
1048 local preva=(ntpoint1)
1049 local nexta=(ntepoint1)
1050 local avperc=(perc)
1051 local forx = Mathf.Cubic_Interpolate(preva,av,avg,nexta,avperc)
1052 return forx
1053end
1054function Mathf.Round(Num,Mult,Bias)
1055 return math.floor(Num/Mult+Bias)*Mult
1056end
1057function Mathf.LerpColor3(c1,c2,p)
1058 return Color3.new(c1.r+(c2.r-c1.r)*p,c1.g+(c2.g-c1.g)*p,c1.b+(c2.b-c1.b)*p)
1059end
1060function Mathf.SmoothLerp(n,g,t)
1061 return t < 0.001 and n or t > 0.999 and g or Mathf.Lerp(n,g,(math.cos(t*math.rad(180)-math.rad(180))+1)/2)
1062end
1063function Mathf.PercentBetween(i,n1,n2)
1064 return math.clamp((i-n1)/(n2-n1),0,1)
1065end
1066function Mathf.LerpTowards(n,g,t)
1067 if n < g then
1068 return Mathf.Clamp(n+t,n,g)
1069 else
1070 return Mathf.Clamp(n-t,g,n)
1071 end
1072end
1073function Mathf.CFrameModel(m,c,g)
1074 for _,v in ipairs(m:GetChildren()) do
1075 if v:IsA("BasePart") then
1076 v.CFrame=g*(c:toObjectSpace(v.CFrame))
1077 end
1078 Mathf.CFrameModel(v,c,g)
1079 end
1080end
1081function Mathf.Vector3ToPixel(Position,Camera,Reference)
1082 local screen_width=Reference.AbsoluteSize.X
1083 local screen_height=Reference.AbsoluteSize.Y
1084 local point = (Camera.CoordinateFrame*CFrame.Angles(0,0,-Camera:GetRoll())):inverse() * (Position)
1085 local fovMult = 1 / math.tan(math.rad(Camera.FieldOfView)/2)
1086 local x = screen_width / 2 * (1 + point.x / -point.z * fovMult * screen_height / screen_width)
1087 local y = screen_height / 2 * (1 + point.y / -point.z * fovMult)
1088 if point.z > 0 then
1089 x=20000
1090 y=20000
1091 end
1092
1093 return x,screen_height-y-36
1094end
1095
1096function Mathf.LerpAngle(a1,a2,t)
1097 local dist=math.abs(a2-a1)
1098 if dist > 180 then
1099 if a2 > a1 then
1100 a1=a1+360
1101 else
1102 a2=a2+360
1103 end
1104 end
1105 return Mathf.Wrap(Mathf.Lerp(a1,a2,t),0,360)
1106end
1107
1108
1109function Mathf.LerpAngleOld(a1,a2,p)
1110 a1=math.deg(a1)
1111 a2=math.deg(a2)
1112 local shortest_angle=((((a2 - a1) % 360) + 540) % 360) - 180;
1113 return math.rad(a1+shortest_angle * p);
1114end
1115
1116function Mathf.LerpTowardsAngle(a1,a2,t)
1117 local dist=math.abs(a2-a1)
1118 if dist > 180 then
1119 if a1 > a2 then
1120 a1=a1+360
1121 else
1122 a2=a2+360
1123 end
1124 end
1125 return Mathf.LerpTowards(a1,a2,t)
1126end
1127function Mathf.LerpAngle2(A1,A2,Percent)
1128 A1=(A1+180)
1129 A2=(A2+180)
1130 difference = math.abs(A2 - A1);
1131 if (difference > 180) then
1132 -- We need to add on to one of the values.
1133 if (A2 > A1) then
1134 -- We'll add it on to start...
1135 A2 = A2-360
1136 else
1137 -- Add it on to end.
1138 A1 = A1-360
1139 end
1140 end
1141 A1=(A1-180)
1142 A2=(A2-180)
1143 --print(math.floor(A1).."vs"..math.floor(A2))
1144 return Mathf.Wrap(Mathf.Lerp(A1,A2,Percent),-180,180)
1145end
1146function Mathf.AngleDistance(A1,A2)
1147 A1=math.deg(A1)
1148 A2=math.deg(A2)
1149 difference = math.abs(A2 - A1);
1150 if (difference > 180) then
1151 -- We need to add on to one of the values.
1152 if (A1 > A2) then
1153 -- We'll add it on to start...
1154 A2 = A2+360
1155 else
1156 -- Add it on to end.
1157 A1 = A1+360
1158 end
1159 end
1160 return math.rad(A1-A2)
1161end
1162function Mathf.LerpAngle(A1,A2,Percent)
1163 difference = math.abs(A2 - A1);
1164 if (difference > 180) then
1165 -- We need to add on to one of the values.
1166 if (A2 > A1) then
1167 -- We'll add it on to start...
1168 A1 =A1+360
1169 else
1170 -- Add it on to end.
1171 A2 =A2+360
1172 end
1173 end
1174 return Mathf.Wrap(Mathf.Lerp(A1,A2,Percent),0,360)
1175end
1176function Mathf.InterpolateCFrame(CF1,CF2,Percent)
1177 --[[x1,y1,z1=CF1:toEulerAnglesXYZ()
1178 x2,y2,z2=CF2:toEulerAnglesXYZ()
1179 Angle=Vector3.new(math.rad(Mathf.LerpAngle(math.deg(x1),math.deg(x2),Percent)),math.rad(Mathf.LerpAngle2(math.deg(y1),math.deg(y2),Percent)),math.rad(Mathf.LerpAngle2(math.deg(z1),math.deg(z2),Percent)))
1180 return CFrame.new(CF1.p:Lerp(CF2.p,Percent))*CFrame.Angles(Angle.x,Angle.y,Angle.z)]]
1181 return Percent < 0.001 and CF1 or Percent > 0.999 and CF2 or CF1:lerp(CF2,Percent)
1182end
1183return Mathf
1184
1185local module = {}
1186
1187
1188-- Services
1189
1190local Lighting = game:GetService("Lighting");
1191local UserInputService = game:GetService("UserInputService");
1192local TweenService = game:GetService("TweenService");
1193local RunService = game:GetService("RunService")
1194local Players = game:GetService("Players");
1195local CollectionService = game:GetService("CollectionService");
1196local ReplicatedStorage = game:GetService("ReplicatedStorage");
1197
1198
1199--
1200
1201
1202local LoadModule = require(ReplicatedStorage.Modules.Load);
1203local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
1204
1205local SharedData = LoadSharedModule("SharedData");
1206
1207local PlayerCharacter = LoadModule("PlayerCharacter", true)
1208local InputHandler = LoadModule("InputHandler")
1209local Camera = LoadModule("Camera")
1210local Utils = LoadModule("Utils")
1211local Mathf = LoadModule("Mathf")
1212local FX = LoadModule("FX");
1213local VFX = LoadModule("VFX");
1214local WildLife = LoadModule("WildLife",true);
1215local Network = LoadSharedModule("Network");
1216local UIObjects = LoadModule("UIObjects");
1217
1218
1219--
1220
1221local Player = Players.LocalPlayer;
1222
1223local Ignore = workspace.Ignore;
1224local Communication = ReplicatedStorage.Communication;
1225
1226
1227
1228local LastEquippedItemAmmoText, LastDrawingBow, lastlassoed, LastTaming, LastMouseFree
1229
1230local ClientSounds = UIObjects.ClientSounds;
1231local SelectSlotSound = ClientSounds.SelectSlot;
1232
1233
1234local ui = UIObjects.Client;
1235
1236local BowUI = UIObjects.Bow;
1237local BowCursor = BowUI.ArrowCursor;
1238local ArrowBar1 = BowCursor.Bar1;
1239local ArrowBar2 = BowCursor.Bar2;
1240local BowCursorBase = BowCursor.Base;
1241
1242
1243local TamingUI = UIObjects.AnimalTaming;
1244local TamingCircle = TamingUI.Circle;
1245local TamingBar = TamingUI.ProgressBar;
1246local TamingBarFill = TamingBar.Fill;
1247local TamingBarPercent = TamingBar.Percent;
1248local TamingTime = TamingUI.Hourglass.TextLabel;
1249local TamingTimeScale = TamingTime.UIScale;
1250
1251local TamingTweenInfo = TweenInfo.new(0.2,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,true,0);
1252local TamingTimeScaleTween = TweenService:Create(TamingTimeScale,TamingTweenInfo,{Scale=1.2});
1253local TamingColorTween = TweenService:Create(TamingTime,TamingTweenInfo,{TextColor3=Color3.new(1,0,0)});
1254
1255
1256
1257
1258
1259game:GetService("StarterGui"):SetCore("ChatWindowPosition",UDim2.new(0.01,0,0.7,0));
1260
1261
1262local EquippedItem = ui.EquippedItem;
1263local EquippedItemImage = EquippedItem.ImageLabel;
1264local EquippedItemLabel = EquippedItem.TextLabel;
1265local EquippedItemAmmo = EquippedItem.Ammo;
1266local EquippedItemAmmoTweenInfo = TweenInfo.new(.2,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,true,0);
1267
1268
1269local BreakFree = ui.BreakFree;
1270local BreakFreeBar = BreakFree.Bar;
1271local BreakFreeFill = BreakFreeBar.Fill;
1272
1273local PoisonedVision = ui.PoisonedVision;
1274local DamageOverlay = ui.DamageOverlay;
1275
1276local DeathLabel = ui.DeathLabel;
1277local DeathLabels =
1278{
1279 "You got rekt",
1280 "Ouch",
1281 "You should see the doctor",
1282 "ripperoni",
1283 "You're super dead",
1284 "You could be healthier",
1285 "To be continued..."
1286}
1287
1288local KeyAction = ui.KeyAction;
1289local GetUp = ui.GetUp;
1290
1291local DamageOverlay = ui.DamageOverlay;
1292shared.DamageOverlay=DamageOverlay;
1293
1294
1295
1296local RespawnButton = ui.RespawnButton;
1297local RespawnButtonLabel = RespawnButton.TextLabel;
1298
1299local Cursor = ui.Cursor;
1300
1301
1302
1303local LeftBar = Cursor.LeftBar;
1304local RightBar = Cursor.RightBar;
1305local BottomBar = Cursor.BottomBar;
1306
1307BarPerc=0;
1308
1309LeftBarX=0.3; -- .2
1310RightBarX=.7; -- .8
1311BottomBarY=0.55; -- .65
1312
1313BarOutMax=0.5;
1314LeftBarXMax=LeftBarX-BarOutMax;
1315RightBarXMax=RightBarX+BarOutMax;
1316BottomBarYMax=BottomBarY+BarOutMax;
1317
1318
1319
1320
1321
1322
1323
1324shared.HitMarker = ClientSounds.HitMarker;
1325
1326
1327
1328
1329
1330
1331local MenuSaturationValue = FX.NewSaturationValue(0,0.2);
1332local MenuBrightnessValue = FX.NewBrightnessValue(0,0.2);
1333
1334local MenuMuffleValue = FX.NewMuffleValue(0,0.2);
1335
1336local MenuBlurValue = FX.NewBlurValue(0,0.2);
1337
1338local mouse = Player:GetMouse();
1339
1340
1341
1342local function MouseInBounds(UIObject)
1343
1344 local mousex = mouse.x;
1345 local mousey = mouse.y;
1346
1347 local object_size = UIObject.AbsoluteSize;
1348 local halfsizex = object_size.x/2;
1349 local halfsizey = object_size.y/2;
1350
1351 local object_pos = UIObject.AbsolutePosition;
1352
1353 local anchor = UIObject.AnchorPoint;
1354
1355 local objectx = object_pos.x + (object_size.x*anchor.x);
1356 local objecty = object_pos.y + (object_size.y*anchor.y);
1357
1358 return mousex < objectx + halfsizex and mousex > objectx - halfsizex and
1359 mousey < objecty + halfsizey and mousey > objecty - halfsizey;
1360end
1361
1362
1363local function GetNumSlotChildren(slot)
1364 local n = 0;
1365 for _,v in pairs(slot:GetChildren()) do
1366 if v:isA("ImageLabel") then
1367 n=n+1;
1368 end
1369 end
1370 return n;
1371end
1372
1373
1374
1375
1376local Slots = {};
1377
1378local lastclosestslot;
1379
1380
1381local function ShowAppropriateSlotIndex()
1382 for name,foundslot in pairs(Slots) do
1383
1384 local numindices = GetNumSlotChildren(foundslot);
1385
1386 for _,icon in pairs(foundslot:GetChildren()) do
1387 if icon:isA("ImageLabel") then
1388
1389
1390 local slotindex = foundslot:FindFirstChild("Index");
1391 if slotindex then
1392
1393 local thisindex = tonumber(icon.Name:match("%d+"));
1394 if slotindex.Value ~= thisindex then
1395 icon.Visible=false;
1396 else
1397 icon.Visible=true
1398 end
1399 end
1400
1401 end
1402 end
1403 end
1404
1405 lastclosestslot=nil;
1406end
1407
1408
1409
1410
1411
1412
1413
1414-- BOW UI
1415
1416
1417
1418
1419
1420function module.SetArrowBarGoals(rot1, rot2, smooth)
1421 if not smooth then
1422 ArrowBar1.Rotation = rot1
1423 ArrowBar2.Rotation = rot2
1424 else
1425 ArrowBar1.Rotation = Mathf.Lerp(ArrowBar1.Rotation, rot1, 0.2)
1426 ArrowBar2.Rotation = Mathf.Lerp(ArrowBar2.Rotation, rot2, 0.2)
1427 end
1428end
1429
1430
1431
1432
1433--
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448local LastSelectedItem;
1449
1450
1451
1452
1453
1454
1455
1456module.UpdateEquippedItem = function()
1457-- local item = PlayerCharacter:GetEquippedItem()
1458-- local image = ItemIcons:FindFirstChild(item.Name)
1459--
1460-- if image then
1461-- local aspectratio = 1
1462-- local imageratio = image:FindFirstChildOfClass("UIAspectRatioConstraint")
1463-- if imageratio then
1464-- aspectratio=imageratio.AspectRatio
1465-- end
1466--
1467-- EquippedItemImage.UIAspectRatioConstraint.AspectRatio = aspectratio
1468-- EquippedItemImage.Image = image.Image
1469-- EquippedItemLabel.Text = item.Name
1470--
1471-- if item.Ammo then
1472-- EquippedItemAmmo.Text = item.Ammo .. "/" .. item.MaxAmmo
1473-- EquippedItemAmmo.Visible = true
1474-- else
1475-- EquippedItemAmmo.Visible = false
1476-- end
1477--
1478-- if EquippedItemAmmo.Text ~= LastEquippedItemAmmoText then
1479-- local tween = TweenService:Create(EquippedItemAmmo.UIScale,EquippedItemAmmoTweenInfo,{Scale=1.5})
1480-- tween:Play()
1481-- end
1482--
1483-- LastEquippedItemAmmoText = EquippedItemAmmo.Text
1484-- end
1485end
1486shared.UpdateEquippedItem=module.UpdateEquippedItem;
1487
1488
1489
1490
1491local DeathWaitTime = 5;
1492
1493
1494RespawnButton.MouseButton1Down:connect(function()
1495 if not respawning then
1496 if deathtime and tick()-deathtime >= DeathWaitTime then
1497 respawning=true;
1498 Network:FireServer("Respawn");
1499 end
1500 end
1501end)
1502
1503
1504
1505GetUp.MouseButton1Down:connect(function()
1506 if PlayerCharacter:CanGetUp() then
1507 GetUp.Visible = false
1508 PlayerCharacter:GetUp()
1509 end
1510end)
1511
1512
1513Network:BindEvents({
1514 Respawn = function(char)
1515 if char == Player.Character then
1516 respawning=nil;
1517 deathtime=nil;
1518 lastdead=nil;
1519
1520 RespawnButton.Visible = false;
1521 DeathLabel.Visible = false;
1522 end
1523 end
1524})
1525
1526
1527module.Fire = function()
1528 BarPerc=1;
1529end
1530
1531local updateTime = 0
1532local lastUpdate = 0;
1533
1534shared.BreakFreePerc = 0;
1535shared.BreakFreePercSpeed=0.45;
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552-- Side bar handling
1553
1554
1555
1556local cam = workspace.CurrentCamera;
1557
1558
1559-- Role picking
1560
1561
1562 local RoleDescriptions=
1563 {
1564 ["Law"]="Lawmen bring outlaws in to justice, protecting the citizens of the wild west",
1565 ["Outlaw"] = "Outlaws are the bandits of the wild west. They have no boundaries, and make a living off of robbing",
1566 ["Citizen"] = "Citizens try to stay away from the fight, but can protect themselves from outlaws if necessary. Citizens complete jobs for money"
1567 }
1568
1569
1570 local RolePickingBlur = FX.NewBlurValue(0,0.5);
1571 local RolePickingDarkness = FX.NewBrightnessValue(0,0.5);
1572
1573 local RolePickerGui = UIObjects.RolePicker;
1574 local RolePickerFrame = RolePickerGui.Frame;
1575 local RolePickerDescription = RolePickerGui.Description;
1576
1577 local PickingRole;
1578
1579
1580
1581
1582 local PlayerInfo = UIObjects.PlayerInfo;
1583
1584 local PlayerDataFrame = PlayerInfo.PlayerDataFrame;
1585 local BucksLabel = PlayerDataFrame.Bucks;
1586
1587 local HealthAndStam = PlayerInfo.HealthAndStamina;
1588
1589 local StaminaBar = HealthAndStam.Stamina.Bar;
1590 local HealthBar = HealthAndStam.Health.Bar;
1591 local HealthBarLabel = HealthBar.ValueText;
1592 local StaminaBarLabel = StaminaBar.ValueText;
1593 local HealthFill = HealthBar.ValueFrame
1594 local StaminaFill = StaminaBar.ValueFrame;
1595
1596 local RoleInfo = PlayerInfo.Role;
1597 local RoleInfoLabel = RoleInfo.TextLabel;
1598 RoleInfoImage=RoleInfo.ImageLabel;
1599
1600
1601 local RoleIcons = SharedData.RoleIcons;
1602
1603
1604 local function PickedRole()
1605 if PickingRole then
1606 -- Update Role UI
1607
1608 RoleInfoLabel.Text=PickingRole;
1609 RoleInfoImage.Image=RoleIcons[PickingRole];
1610
1611-- RolePickerGui.Enabled=false;
1612 RolePickerGui.Parent = nil
1613
1614 shared.GameLoading=true;
1615
1616 Network:InvokeServer("SetRole", PickingRole);
1617
1618 shared.Role = PickingRole;
1619
1620 shared.GameLoading=false;
1621
1622 FX.SetTintColorGoal(Color3.new(1,1,1));
1623 RolePickingBlur:SetGoal(0);
1624 RolePickingDarkness:SetGoal(0);
1625
1626 local hrp = PlayerCharacter.RootPart
1627 if hrp then
1628 shared.RolePickingTransition = true
1629
1630 local begin = tick()
1631 local startCFrame = hrp.CFrame * CFrame.new(0, 100, 100)
1632 cam.CFrame = startCFrame
1633
1634 repeat
1635 RunService.RenderStepped:Wait()
1636 local t = (tick() - begin) / 1
1637
1638 cam.CFrame = startCFrame:Lerp(hrp.CFrame * CFrame.new(0, 5, 15), t)
1639 until t >= 1
1640 end
1641
1642 module.ToggleGameGUI(true);
1643
1644 shared.RolePickingTransition=nil;
1645 shared.RolePicking=nil;
1646
1647 Utils.ToggleCantMove(false);
1648 InputHandler:Enable()
1649 Camera:Enable()
1650 end
1651 end
1652
1653 for _,v in pairs(RolePickerFrame:GetDescendants()) do
1654 if v:isA("ImageButton") then
1655 local glow = v.Parent.Glow;
1656 local scale = v.UIScale;
1657
1658
1659 local tweeninfo = TweenInfo.new(0.25);
1660
1661 local glow_selected = TweenService:Create(glow,tweeninfo,{ImageTransparency=0});
1662 local glow_deselected = TweenService:Create(glow,tweeninfo,{ImageTransparency=1});
1663
1664 local scale_selected = TweenService:Create(scale,tweeninfo,{Scale=1.1});
1665 local scale_deselected = TweenService:Create(scale,tweeninfo,{Scale=1});
1666
1667 local color_selected = TweenService:Create(v,tweeninfo,{ImageColor3=Color3.new(1,1,1)});
1668 local color_deselected = TweenService:Create(v,tweeninfo,{ImageColor3=Color3.fromRGB(109, 109, 109)});
1669
1670
1671 v.MouseEnter:connect(function()
1672
1673 SelectSlotSound:Play();
1674
1675 glow_selected:Play();
1676 scale_selected:Play();
1677 color_selected:Play();
1678
1679 PickingRole=v.Name;
1680
1681 RolePickerDescription.Text=RoleDescriptions[PickingRole];
1682
1683 end)
1684 v.MouseLeave:connect(function()
1685
1686
1687
1688 glow_deselected:Play();
1689 scale_deselected:Play();
1690 color_deselected:Play();
1691
1692
1693 end)
1694
1695 v.MouseButton1Down:connect(function()
1696 PickedRole();
1697 end)
1698 end
1699 end
1700
1701
1702
1703 module.PickRole = function()
1704 shared.RolePicking = true
1705 Camera:Disable()
1706 cam.CFrame = CFrame.new(0, 1000, 0)
1707 Utils.ToggleCantMove(true);
1708 FX.SetTintColorGoal(Color3.fromRGB(195, 163, 126));
1709 RolePickingBlur:SetGoal(36);
1710 RolePickingDarkness:SetGoal(0.3);
1711
1712 local PlayerGui = Player:FindFirstChild("PlayerGui")
1713 local LoadingBackground = PlayerGui and PlayerGui:FindFirstChild("Background");
1714
1715 if LoadingBackground then
1716 LoadingBackground:Destroy()
1717 end
1718
1719 local RolePickerDesc = RolePickerGui.Description;
1720 local RolePickerTitle = RolePickerGui.Title;
1721
1722 local desctween = TweenService:Create(RolePickerDesc,TweenInfo.new(0.5),{TextTransparency=0});
1723 local roletitletween = TweenService:Create(RolePickerTitle,TweenInfo.new(0.5),{TextTransparency=0});
1724
1725
1726 RolePickerGui.Enabled = true;
1727
1728 desctween:Play();
1729 roletitletween:Play();
1730
1731 RolePickerFrame.Position=UDim2.new(0.5,0,0.75,0);
1732 local frametween = TweenService:Create(RolePickerFrame,TweenInfo.new(0.5),{Position=UDim2.new(0.5,0,0.571,0)});
1733 frametween:Play();
1734
1735 for _,v in pairs(RolePickerFrame:GetDescendants()) do
1736 if v:isA("ImageButton") then
1737 local tween = TweenService:Create(v,TweenInfo.new(0.5),{ImageTransparency=0});
1738 tween:Play();
1739 end
1740 end
1741
1742 end
1743
1744
1745--
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756-- I gained moneyz
1757
1758 BucksLabel:GetPropertyChangedSignal("Text"):connect(function()
1759 --ChangedVisual(BucksLabel:FindFirstChild("UIScale"))
1760 end)
1761
1762--
1763
1764
1765
1766
1767-- Loading
1768
1769local Loading = UIObjects.Loading;
1770local LoadingTumble = Loading.Tumble;
1771local LoadingLabel = Loading.TextLabel;
1772
1773--
1774
1775
1776local GameGUIs = CollectionService:GetTagged("GameGUI");
1777
1778module.ToggleGameGUI = function(bool)
1779 for _,v in pairs(GameGUIs) do
1780 v.Enabled=bool;
1781 end
1782end
1783
1784module.ToggleGameGUI(false);
1785
1786
1787local function LoadingAnimate(updateTime)
1788 LoadingTumble.Position=UDim2.new(0.915,0,0.896+math.sin(tick()*Loading.freq.Value)*Loading.amp.Value,0);
1789 LoadingTumble.Rotation=(LoadingTumble.Rotation+(updateTime*Loading.rotspeed.Value))%360;
1790end
1791
1792startTick = tick()
1793
1794function shortTick()
1795 return tick()-startTick
1796end
1797
1798
1799
1800
1801
1802local LastPlayerData = shared.PlayerData;
1803local LastRagdolled
1804module.UpdatePlayerData = function()
1805 local playerdata = shared.PlayerData;
1806 local bucks = playerdata.Bucks;
1807
1808 if LastPlayerData then
1809 if bucks > LastPlayerData.Bucks then
1810 local gainsound = UIObjects.ClientSounds.GainCurrency;
1811 gainsound:Play();
1812 elseif bucks < LastPlayerData.Bucks then
1813 local losesound = UIObjects.ClientSounds.LoseCurrency;
1814 losesound:Play();
1815 end
1816 end
1817
1818 LastPlayerData = playerdata;
1819
1820 BucksLabel.Text = bucks;
1821end
1822
1823local WasRagdolled, WasTiedUp
1824
1825module.Update = function()
1826 updateTime = tick() - lastUpdate;
1827 lastUpdate = tick()
1828
1829 local isRagdolled = PlayerCharacter:IsRagdolled()
1830 if WasRagdolled ~= isRagdolled then
1831 WasRagdolled = isRagdolled
1832 end
1833
1834
1835 -- Health & Stam
1836
1837 local healthval = PlayerCharacter.HealthValue
1838 if healthval then
1839 healthval = healthval.Value
1840
1841 local percent_to_max = math.clamp(healthval / 100, 0, 1)
1842 local alpha = math.clamp(updateTime / 0.25, 0, 1)
1843
1844 HealthFill.Size = HealthFill.Size:Lerp(UDim2.new(percent_to_max*0.95, 0, 0.8, 0), alpha)
1845 HealthBarLabel.Text = math.floor(percent_to_max * 100) .. "%"
1846 end
1847
1848
1849 -- Poisoned
1850
1851 local poisonval = PlayerCharacter.PoisonValue
1852 if poisonval then
1853 if poisonval.Value > 0 then
1854 PoisonedVision.Visible = true
1855
1856 local alpha = math.clamp(updateTime / 0.25, 0, 1)
1857 PoisonedVision.ImageTransparency = Mathf.Lerp(PoisonedVision.ImageTransparency, 1 - poisonval.Value, alpha)
1858 else
1859 PoisonedVision.Visible = false
1860 end
1861 end
1862
1863
1864 -- Loading
1865
1866 local GameLoading = shared.GameLoading;
1867 local LoadingAlpha = math.clamp(updateTime/0.25, 0, 1)
1868
1869 if GameLoading then -- Fade in
1870 LoadingTumble.ImageTransparency = Mathf.Lerp(LoadingTumble.ImageTransparency, 0, LoadingAlpha)
1871 LoadingLabel.TextTransparency = Mathf.Lerp(LoadingLabel.TextTransparency, 0, LoadingAlpha)
1872
1873 LoadingAnimate(updateTime)
1874 elseif LoadingTumble.ImageTransparency < 1 then -- Fade out
1875 LoadingAnimate(updateTime)
1876
1877 LoadingTumble.ImageTransparency = Mathf.Lerp(LoadingTumble.ImageTransparency, 1, LoadingAlpha)
1878 LoadingLabel.TextTransparency = Mathf.Lerp(LoadingLabel.TextTransparency, 1, LoadingAlpha)
1879 end
1880
1881
1882 local hrp = PlayerCharacter.RootPart;
1883 if not hrp then return end
1884
1885
1886 if PlayerCharacter:CanBreakFree() then
1887 if not WasTiedUp then
1888 WasTiedUp = true
1889 BreakFree.Visible = true
1890 end
1891
1892 BreakFreeFill.Size = UDim2.new(math.clamp(PlayerCharacter.BreakFreePerc, 0, 1), 0, 1, 0)
1893 elseif WasTiedUp then
1894 WasTiedUp = false
1895 BreakFree.Visible = false
1896 end
1897
1898
1899 GetUp.Visible = PlayerCharacter:IsRagdolled() and PlayerCharacter:CanGetUp() and hrp.Velocity.magnitude < 2
1900
1901 if PlayerCharacter:GetLassoTarget() then
1902 KeyAction.TextLabel.Text = "F: Release"
1903 KeyAction.Visible = true
1904 elseif PlayerCharacter.IsCarrying then
1905 KeyAction.TextLabel.Text = "F: Put Down"
1906 KeyAction.Visible = true
1907 else
1908 KeyAction.Visible = false
1909 end
1910
1911
1912 local dead = PlayerCharacter.IsDead
1913 if dead then
1914 if not lastdead then
1915 deathtime = tick()
1916 DeathLabel.Text = DeathLabels[math.random(1, #DeathLabels)]
1917 DeathLabel.Visible = true
1918 RespawnButton.Visible = true
1919 end
1920
1921
1922 local timeleft = math.clamp(DeathWaitTime - math.floor(tick()-deathtime),0,DeathWaitTime);
1923 local RespawnLabelText;
1924
1925 if timeleft <= 0 then
1926 RespawnLabelText = "Respawn!";
1927 RespawnButtonLabel.TextColor3=Color3.new(1,1,1);
1928 else
1929 RespawnLabelText = "Respawn("..timeleft.."s)";
1930 RespawnButtonLabel.TextColor3=Color3.fromRGB(140, 140, 140);
1931 end
1932
1933 RespawnButtonLabel.Text=RespawnLabelText;
1934 end
1935
1936 lastdead = dead
1937
1938
1939
1940 local mousepos = UserInputService:GetMouseLocation();
1941
1942
1943
1944
1945
1946 -- Taming
1947
1948 local Taming = shared.Taming
1949
1950 if LastTaming ~= Taming then
1951 LastTaming = Taming
1952 TamingUI.Enabled = Taming and true or false
1953 end
1954
1955 if Taming then
1956 local animal = Taming.animal;
1957 local lastmovement = Taming.lastmovement;
1958 local movementtime = Taming.movementtime;
1959 local circlesize = Taming.circlesize;
1960
1961 if tick()-lastmovement >= movementtime then
1962 Taming.lastmovement=tick();
1963 Taming.movementtime=math.random()*2;
1964
1965 local viewportsize = cam.ViewportSize;
1966 local width = viewportsize.x;
1967 local height = viewportsize.y;
1968
1969
1970 local halfwidth = width*0.5;
1971 local halfheight = height*0.5;
1972
1973 local xregion = halfwidth*0.25;
1974 local yregion = halfheight*0.25;
1975
1976 local randomx = halfwidth+math.random(-xregion,xregion);
1977 local randomy = halfheight+math.random(-yregion,yregion);
1978 local randomv2 = Vector2.new(randomx,randomy);
1979
1980 local randomscreenpos = UDim2.new(0,randomx,0,randomy);
1981
1982 TamingCircle:TweenPosition(randomscreenpos,"Out","Linear",((randomv2-TamingCircle.AbsolutePosition).magnitude)/Taming.velocity,true,nil);
1983 end
1984
1985 local speed = updateTime*0.01*0.75 * Taming.sizespeed;
1986
1987 if MouseInBounds(TamingCircle) then
1988 local prevsize = TamingCircle.Size;
1989 local increase = speed;
1990 Taming.circlesize=math.clamp(circlesize+increase,Taming.minsize,Taming.maxsize);
1991 else
1992 local prevsize = TamingCircle.Size;
1993 local decrease = speed--*0.875;
1994
1995 Taming.circlesize=math.clamp(circlesize-decrease,Taming.minsize,Taming.maxsize);
1996 end
1997
1998 local percent = Mathf.PercentBetween(Taming.circlesize,Taming.minsize,Taming.maxsize);
1999
2000 TamingBarFill.Size=UDim2.new(percent,0,1,0);
2001 TamingBarPercent.Text=math.floor(percent*100).."%";
2002
2003 TamingCircle.Size=UDim2.new(circlesize,0,circlesize,0);
2004
2005 if percent <= 0 then
2006 -- Minimum
2007 if not Taming.AtMinimum then
2008 Taming.AtMinimum=tick();
2009 end
2010 else
2011 Taming.AtMinimum=nil;
2012
2013 if percent >= 1 or percent >= 0.1 and Player.Name == "AntiBoomz0r" then
2014 -- Completed!
2015 shared.StopTamingAnimal(true)
2016 end
2017 end
2018
2019 local Elapsed = math.floor(tick() - Taming.StartTime)
2020
2021 TamingTime.Text = tostring(60 - Elapsed) .. "s"
2022
2023 if Elapsed ~= Taming.LastElapsed and Elapsed >= 60*0.75 then
2024 TamingTimeScaleTween:Play();
2025 TamingColorTween:Play();
2026 end
2027
2028 Taming.LastElapsed = Elapsed
2029
2030 local TimeOut = Elapsed >= 60
2031 if Taming.AtMinimum or TimeOut then
2032 if TimeOut or tick()-Taming.AtMinimum >= 5 then
2033 print("Stopped taming animal because timeout")
2034 shared.StopTamingAnimal()
2035 shared.Taming = nil
2036
2037 PlayerCharacter:Ragdoll(hrp, hrp.Position, Vector3.new(0,1,0), 2500)
2038 end
2039 end
2040 end
2041
2042
2043
2044 -- Cursor
2045
2046 local forward_velocity = (hrp.Velocity * Vector3.new(1,0,1)).magnitude;
2047 local BarVelocity=forward_velocity/50;
2048
2049 BarPerc=Mathf.Lerp(BarPerc,0+BarVelocity,math.clamp(updateTime/0.1,0,1));
2050
2051
2052 local newLeftBarX = Mathf.Lerp(LeftBarX,LeftBarXMax,BarPerc);
2053 local newRightBarX = Mathf.Lerp(RightBarX,RightBarXMax,BarPerc);
2054 local newBottomBarY = Mathf.Lerp(BottomBarY,BottomBarYMax,BarPerc);
2055
2056 LeftBar.Position=LeftBar.Position:lerp(UDim2.new(newLeftBarX,0,0.4,0),math.clamp(updateTime/0.025,0,1));
2057 RightBar.Position=RightBar.Position:lerp(UDim2.new(newRightBarX,0,0.4,0),math.clamp(updateTime/0.025,0,1));
2058 BottomBar.Position=BottomBar.Position:lerp(UDim2.new(0.5,0,newBottomBarY,0),math.clamp(updateTime/0.025,0,1));
2059
2060
2061 local MouseFree = not Camera:IsCustom() or shared.Taming
2062 local item = PlayerCharacter:GetEquippedItem()
2063
2064 if not MouseFree and item.Name == "Bow" then
2065 Cursor.Visible = false
2066 BowCursor.Visible = true
2067
2068 local drawing = item.IsDrawing
2069 ArrowBar1.Visible = drawing
2070 ArrowBar2.Visible = drawing
2071 BowCursorBase.Visible = drawing
2072 else
2073 BowCursor.Visible = false
2074 Cursor.Visible = not MouseFree and not Camera:IsFirstPerson()
2075 end
2076
2077
2078
2079 if MouseFree then
2080 if LastMouseFree ~= MouseFree then
2081 UserInputService.MouseBehavior = Enum.MouseBehavior.Default
2082 UserInputService.MouseIconEnabled = true
2083 end
2084 else
2085 UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
2086 if LastMouseFree ~= MouseFree then
2087 UserInputService.MouseIconEnabled = false
2088 end
2089 end
2090
2091 LastMouseFree = MouseFree
2092
2093
2094 Cursor.Position = UDim2.new(0.5, 0, 0.5, -18)
2095 BowCursor.Position = UDim2.new(0.5, 0, 0.5, -18)
2096end
2097
2098
2099return module
2100
2101
2102--[[
2103 PlayerCharacter
2104 Handles Player Characters
2105--]]
2106
2107-- Services
2108
2109local ReplicatedStorage = game:GetService("ReplicatedStorage")
2110local CollectionService = game:GetService("CollectionService")
2111local UserInputService = game:GetService("UserInputService")
2112local RunService = game:GetService("RunService")
2113local TweenService = game:GetService("TweenService")
2114local Players = game:GetService("Players")
2115
2116-- Modules
2117
2118local LoadModule = require(ReplicatedStorage.Modules.Load)
2119local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
2120
2121local FaceMouse = LoadModule("FaceMouse")
2122local AnimationHandler = LoadModule("AnimationHandler")
2123local PlayerRobbing = LoadModule("PlayerRobbing")
2124local InputHandler = LoadModule("InputHandler")
2125local Projectiles = LoadModule("Projectiles")
2126local Ragdolls = LoadModule("Ragdolls")
2127local BodyTilt = LoadModule("BodyTilt")
2128local Camera = LoadModule("Camera")
2129local Mathf = LoadModule("Mathf")
2130local Utils = LoadModule("Utils")
2131local FX = LoadModule("FX",true)
2132local AFX = LoadModule("AFX",true);
2133local IK = LoadModule("IK")
2134local VFX = LoadModule("VFX",true);
2135local Holsters = LoadModule("Holsters",true);
2136local RobbingItems = LoadModule("RobbingItems",true);
2137
2138local UI = LoadModule("UI",true)
2139local UIHandler = LoadModule("UIHandler",true);
2140local WildLife = LoadModule("WildLife",true);
2141
2142local Network = LoadSharedModule("Network")
2143local SharedUtils = LoadSharedModule("SharedUtils")
2144
2145-- Variables
2146
2147local LocalPlayer = Players.LocalPlayer
2148local Resources = ReplicatedStorage.Resources
2149local Communication = ReplicatedStorage.Communication
2150local Ignore = workspace.Ignore
2151
2152local IsSprintButtonDown = false
2153local IsSprinting = false
2154local WasUpdatingWaist = false
2155local HasControl = true
2156local IsRagdolled = false
2157local IsGettingUp = false
2158
2159local CharacterKinematics = {}
2160local PlayerItems = {}
2161local DefaultFistItem = { itemname = "Fist" }
2162local EquippedItemData = DefaultFistItem
2163local Character, Human, RootPart
2164
2165local Health_Saturation = FX.NewSaturationValue(0, 0.5)
2166local Health_Brightness = FX.NewBrightnessValue(0, 0.5)
2167local Health_Muffle = FX.NewMuffleValue(0, 0.5)
2168
2169local WalkspeedFadeTime = 0.5
2170local WalkspeedGoal = 12
2171
2172local BreakFreePercSpeed = 0.45
2173
2174local LastMoveTrack
2175local LastMoveTrackSpeedGoal = 0
2176local LastFalling, FallStart
2177local LastHumanState
2178local LastBreakFreeAttempt
2179
2180local module = {}
2181
2182module.BreakFreePerc = 0
2183
2184
2185local NewRay = Ray.new;
2186local Terrain = workspace.Terrain;
2187
2188function module:FaceMouse(bool)
2189 self.FacingMouse=bool;
2190end
2191
2192function module:HasControl()
2193 return HasControl;
2194end
2195
2196
2197
2198
2199function WaitFor(par, list, timeout)
2200 local items = {}
2201 local start = tick()
2202
2203 local function doList(par, list)
2204 for i,name in pairs(list) do
2205 if type(name) == "table" then
2206 local item = par:WaitForChild(i, timeout - (tick() - start))
2207 if not item then return nil end
2208 items[i] = item
2209
2210 doList(item, name)
2211 else
2212 local item = par:WaitForChild(name, timeout - (tick() - start))
2213 if not item then return nil end
2214 items[name] = item
2215 end
2216 end
2217 end
2218
2219 doList(par, list)
2220 return items
2221end
2222
2223function AddCharacterKinematics(char)
2224 if CharacterKinematics[char] or not char:IsDescendantOf(workspace) then return end
2225 CharacterKinematics[char] = true
2226
2227 local items = WaitFor(char, {
2228 RightUpperLeg = { "RightHip" },
2229 RightLowerLeg = { "RightKnee" },
2230 RightFoot = { "RightAnkle" },
2231
2232 LeftUpperLeg = { "LeftHip" },
2233 LeftLowerLeg = { "LeftKnee" },
2234 LeftFoot = { "LeftAnkle" },
2235
2236 LowerTorso = { "Root" }
2237 }, 60)
2238
2239 if not items or not char:IsDescendantOf(workspace) then
2240 CharacterKinematics[char] = nil
2241 return
2242 end
2243
2244 local removed;
2245 removed = char.AncestryChanged:Connect(function()
2246 if not char:IsDescendantOf(workspace) then
2247 CharacterKinematics[char] = nil
2248 removed:disconnect()
2249 end
2250 end)
2251
2252 IK.AddIKJoint(items.RightHip, items.RightKnee, items.RightAnkle, 0.3, 1, 0.7, { char, Ignore })
2253 IK.AddIKJoint(items.LeftHip, items.LeftKnee, items.LeftAnkle, 0.3, 1, 0.7, { char, Ignore })
2254
2255 BodyTilt:AddRoot(items.Root,{ root = items.Root, transition = 0.3, goalTransition = 0.1, mult = 0.1, angle = 20, sprintvelocity = 13 })
2256end
2257
2258
2259function module:GetItem(name)
2260 return PlayerItems[name]
2261end
2262
2263function module:GetEquippedItem()
2264 return self:GetItem(EquippedItemData and EquippedItemData.itemname or "Fist")
2265end
2266
2267function module:GetEquippedItemData()
2268 return EquippedItemData
2269end
2270
2271function module:SetCharacter(char)
2272 local children = WaitFor(char, {
2273 "Humanoid", "Head", "Health", "PoisonPerc",
2274 UpperTorso = { "Waist" },
2275 LowerTorso = { "Root" },
2276 Head = {"Neck"},
2277 "HumanoidRootPart"
2278 }, 30)
2279
2280 if not children then return end
2281 children.Humanoid.WalkSpeed = 30
2282
2283 Character = char
2284 Human = children.Humanoid
2285 RootPart = children.HumanoidRootPart
2286 Waist = children.Waist
2287 RootJoint = children.Root
2288 Neck = children.Neck;
2289
2290
2291
2292
2293 -- For Face Mouse Module
2294 local springPart = Instance.new("Part");
2295 springPart.Name="SpringPart";
2296 springPart.Size = Vector3.new(1, 1, 1);
2297 springPart.CFrame = CFrame.new();
2298 springPart.CanCollide = false;
2299 springPart.Transparency = 1;
2300 springPart.Parent = char;
2301
2302 local bpos = Instance.new("BodyPosition");
2303 bpos.Position = Vector3.new();
2304 bpos.Parent = springPart;
2305 bpos.D=800;
2306
2307 self.SpringPart = springPart;
2308 self.SpringBody = bpos;
2309 self.Waist=Waist;
2310 self.Neck=Neck
2311 self.Neckc0=Neck.C0;
2312 self.Waistc0=Waist.C0;
2313 --
2314
2315
2316 self.Character = Character
2317 self.StateInfo = Character:WaitForChild("StateInfo");
2318 self.Seated = self.StateInfo:WaitForChild("Seated");
2319
2320 self.Human = children.Humanoid
2321 self.RootPart = children.HumanoidRootPart
2322 self.Head = children.Head
2323 self.HealthValue = children.Health
2324 self.PoisonValue = children.PoisonPerc
2325
2326 self.AnimationHandler = AnimationHandler.new(char)
2327
2328 self.Idling=true;
2329 LastMoveTrack = nil
2330
2331 Utils.Thread(function() AddCharacterKinematics(char) end)
2332
2333
2334 Holsters:EquipHolster("Holster2");
2335
2336 print'set char';
2337 SharedUtils.SetPhysicalProperties(Character,"Default");
2338
2339 self:FaceMouse(true);
2340
2341end
2342
2343
2344local IsEquippingItem = false
2345local QueuedEquip
2346
2347function module:EquipHolster(name)
2348 if not Character then return end
2349
2350 Holsters:EquipHolster(name);
2351end
2352
2353function module:PlayCharacterSound(name)
2354 local sound = RootPart:FindFirstChild(name);
2355 if sound then
2356 sound:Play();
2357 end
2358end
2359
2360function module:Sit()
2361 local humanoid = self.Human;
2362 if humanoid then
2363
2364 self.Idling=nil;
2365 if not self:IsRagdolled() then
2366 self.AnimationHandler:PlayTrack("Seated", 0.1, 1, 1)
2367 humanoid:ChangeState("Physics");
2368 end
2369 end
2370end
2371
2372function module:GetSeated()
2373 return module.Seated and module.Seated.Value;
2374end
2375
2376function module:Unseated()
2377 local humanoid = self.Human;
2378 if humanoid then
2379
2380 self.AnimationHandler:StopTrack("Seated",0.1);
2381 if not self:IsRagdolled() then
2382 self.Idling=true;
2383 humanoid:ChangeState("Jumping");
2384 end
2385 end
2386end
2387function module:Unseat()
2388 if (module.Seated and module.Seated.Value) or self.OnWagon then
2389 Network:FireServer("Unseat");
2390 end
2391end
2392
2393
2394function module:EquipItem(itemData)
2395 if (not Character) then return end
2396 itemData = itemData or DefaultFistItem
2397
2398 if typeof(itemData) ~= "table" or typeof(itemData.itemname) ~= "string" then
2399 warn("Tried to PlayerCharacter:EquipItem() with an invalid item")
2400 return
2401 end
2402
2403 local item = self:GetItem(itemData.itemname)
2404
2405 if not item then
2406 warn(debug.traceback(("Tried to equip item '%s', which doesn't exist"):format(itemData.itemname)))
2407 return
2408 end
2409
2410 if itemData.itemname ~= "Fist" and (IsRagdolled or not HasControl or self.IsDead) then
2411 warn(debug.traceback(("Tried to equip item '%s' while ragdolled or dead"):format(itemData.itemname)))
2412 return
2413 end
2414
2415 if IsEquippingItem then
2416 QueuedEquip = itemData
2417 return
2418 end
2419
2420 if itemData == EquippedItemData then return end
2421
2422 IsEquippingItem = true
2423
2424 -- Unequip old item
2425 local oldItem = self:GetEquippedItem()
2426 if oldItem then oldItem:Unequip() end
2427
2428 EquippedItemData = itemData
2429 item:Equip()
2430
2431 IsEquippingItem = false
2432
2433 Network:FireServer("EquipItem", item.Name)
2434
2435 UI.UpdateEquippedItem()
2436 UIHandler:UpdateEquippedItem()
2437
2438 if QueuedEquip then
2439 local newItem = QueuedEquip
2440 QueuedEquip = nil
2441 return self:EquipItem(newItem)
2442 end
2443end
2444
2445function module:StopAllTracks()
2446 self.AnimationHandler:StopAllTracks();
2447end
2448
2449function module:OnControlLost() -- On death / respawn
2450 RobbingItems:DropRobbingItem();
2451
2452 module:EquipItem(nil)
2453 module:Unseat();
2454
2455 UIHandler:OnControlLost()
2456
2457 self:FaceMouse(false)
2458
2459 IsGettingUp = false
2460
2461 self:StopAllTracks();
2462
2463 if shared.Taming then
2464 print("Stopped taming animal because control lost")
2465 shared.StopTamingAnimal()
2466 end
2467
2468 Camera:SetMode("Free")
2469
2470 Human.WalkSpeed = 0
2471 WalkspeedGoal = 0
2472
2473 LastMoveTrack = nil
2474 LastFalling = nil
2475 LastHumanState = nil
2476
2477
2478end
2479
2480function module:IsLassoing()
2481 local item = module:GetEquippedItem()
2482 return item.Name == "Lasso" and (item.IsLassoing or item.IsThrowingLasso or item.IsReelingIn)
2483end
2484
2485function module:GetLassoTarget()
2486 local item = module:GetEquippedItem()
2487 return item.Name == "Lasso" and item.IsLassoing and item.LassoTarget or nil
2488end
2489
2490function module:IsRagdolled()
2491 return not HasControl and not module.IsTiedUp or IsRagdolled
2492end
2493
2494function module:CanBreakFree()
2495 return module.IsTiedUp or not HasControl
2496end
2497
2498function module:CanGetUp()
2499 return HasControl and IsRagdolled and not module.IsDead and not module.IsTiedUp and not IsGettingUp
2500end
2501
2502local MoveCon, JumpCon
2503local MovementBlockers = {}
2504
2505function module:ToggleMovementBlocker(name, enabled)
2506 if enabled then
2507 if MovementBlockers[name] then return end
2508 MovementBlockers[name] = true
2509
2510 if not MoveCon then
2511 print("Movement Blocker enabled")
2512 MoveCon = Human:GetPropertyChangedSignal("MoveDirection"):Connect(function()
2513 Human:Move(Vector3.new())
2514 end)
2515
2516 JumpCon = Human:GetPropertyChangedSignal("Jump"):Connect(function()
2517 Human.Jump = false
2518 end)
2519
2520 Human:Move(Vector3.new())
2521 Human.Jump = false
2522 end
2523 else
2524 if MovementBlockers[name] then
2525 MovementBlockers[name] = nil
2526
2527 if not next(MovementBlockers) and MoveCon then
2528 MoveCon:Disconnect()
2529 JumpCon:Disconnect()
2530 MoveCon = nil
2531 JumpCon = nil
2532 print("Movement Blocker Disabled")
2533 end
2534 end
2535 end
2536end
2537
2538function module:Ragdoll(hit,fell,...)
2539 if not HasControl or IsRagdolled or module.IsDead or module.IsTiedUp then return end
2540 IsRagdolled = true
2541 self:OnControlLost()
2542
2543 Ragdolls:EnterRagdoll(Character)
2544 Ragdolls:ControlRagdoll(Character)
2545
2546 if hit then
2547 Ragdolls:CreateRagdollForce(hit, ...)
2548 end
2549
2550
2551 Network:FireServer("EnterRagdoll",fell,self.Character)
2552end
2553
2554function module:GetUp()
2555 if not module:CanGetUp() or IsGettingUp then return end
2556 IsGettingUp = true
2557
2558 local groundray = NewRay(RootPart.Position+Vector3.new(0,5,0),Vector3.new(0,-10,0));
2559 local groundhit,groundpos,groundnorm,groundmat = workspace:FindPartOnRayWithIgnoreList(groundray,{Character,Ignore});
2560 local hitwater = groundhit and groundmat and groundmat == Enum.Material.Water;
2561
2562 local onBack = RootPart.CFrame.lookVector.Y > 0
2563 local animName = onBack and "GetUpFromBack" or "GetUpFromStomach"
2564 if hitwater then
2565 animName=animName.."Water";
2566 end
2567
2568 local dir = RootPart.CFrame.upVector * (onBack and -1 or 1) * Vector3.new(1, 0, 1)
2569 local target = CFrame.new(RootPart.Position, RootPart.Position + dir) + Vector3.new(0, 1, 0)
2570
2571 local transform = SharedUtils.JointCFSToTransform(self.Character)
2572 local rootTransform = (RootJoint.C0:Inverse() * target:ToObjectSpace(RootJoint.Part1.CFrame * RootJoint.C1))
2573 transform[RootJoint] = rootTransform
2574
2575 self.Idling=true;
2576
2577 local animTrack = self.AnimationHandler:PlayTrack(animName, 0, 1, 1.5)
2578
2579 local didExit = false
2580 local stepCon
2581 local function stepUpdate()
2582 local t = animTrack.TimePosition
2583 if t < 0.5 then
2584 local fadeIn = t / 0.5
2585 local diff = RootPart.Position - target.p
2586
2587 transform[RootJoint] = rootTransform + Vector3.new(0, math.clamp(-diff.Y, -2, 2), 0)
2588
2589 for joint,transform in pairs(transform) do
2590 joint.Transform = transform:Lerp(joint.Transform, fadeIn)
2591 end
2592 elseif t >= 1 then
2593 stepCon:Disconnect()
2594 animTrack:AdjustWeight(0, 0.5 / animTrack.Speed)
2595 end
2596 end
2597
2598 module.LastIsSwimming=nil;
2599
2600 coroutine.wrap(function()
2601 RunService.Stepped:Wait()
2602 Ragdolls:ExitRagdoll(self.Character);
2603
2604 local hitwater;
2605
2606 if RootPart then
2607 hitwater = SharedUtils.IsPositionInWater(RootPart.Position,{self.Character,Ignore});
2608 end
2609
2610 if hitwater then
2611 SharedUtils.SetPhysicalProperties(self.Character,"Swimming");
2612 end
2613
2614
2615
2616 RootPart.CFrame = target
2617
2618 stepCon = RunService.Stepped:Connect(stepUpdate)
2619 stepUpdate()
2620 end)()
2621
2622 animTrack.Stopped:Wait()
2623 if stepCon then stepCon:Disconnect() end
2624
2625 Ragdolls:ExitRagdoll(self.Character)
2626 Ragdolls:UncontrolRagdoll(self.Character)
2627
2628 if not IsGettingUp then return end
2629
2630 IsRagdolled = false
2631 IsGettingUp = false
2632
2633 Network:FireServer("ExitRagdoll")
2634
2635
2636 module:FaceMouse(true);
2637end
2638
2639function module:StartCarrying(char)
2640 if module.IsCarrying then return end
2641 module.IsCarrying = true
2642 module.IsCarryingLocal = true
2643 module.CarryTarget = char
2644
2645 Ragdolls:ExitRagdoll(char)
2646
2647 InputHandler:ToggleAction("StopCarry", true)
2648
2649 self.AnimationHandler:PlayTrack("PickUp", .25, 1, 1)
2650
2651 coroutine.wrap(function()
2652 self.AnimationHandler:GetTrack("PickUp").Stopped:Wait()
2653 if not module.IsCarrying or module.CarryCanceled then return end
2654 Ragdolls:StartCarrying(Character, char)
2655
2656 -- Play carryperson over everything else
2657 self.AnimationHandler:GetTrack("CarryPerson").Priority = Enum.AnimationPriority.Action
2658
2659 self.AnimationHandler:PlayTrack("CarryPerson", .25, 1, 1)
2660 end)()
2661
2662 coroutine.wrap(function()
2663 local success = Network:InvokeServer("AttemptCarry", char)
2664 module.IsCarryingLocal = false
2665
2666 if module.CarryCanceled then
2667 module.IsCarrying = false
2668 module.CarryTarget = nil
2669 module.CarryCanceled = nil
2670 elseif not success then
2671 module:StopCarrying(true)
2672 end
2673 end)()
2674end
2675
2676function module:StopCarrying(instant)
2677 if not module.IsCarrying or module.CarryCanceled then return end
2678 local carryTarget = module.CarryTarget
2679
2680 if module.IsCarryingLocal then
2681 module.CarryCanceled = true
2682 else
2683 module.IsCarrying = false
2684 module.CarryTarget = nil
2685 end
2686
2687 InputHandler:ToggleAction("StopCarry", false)
2688
2689 self.AnimationHandler:StopTrack("PickUp", .1)
2690 self.AnimationHandler:StopTrack("CarryPerson", .1)
2691
2692 local targetHuman = carryTarget:FindFirstChildOfClass("Humanoid")
2693 if targetHuman then
2694 targetHuman:ChangeState("Physics")
2695 end
2696
2697 if instant then
2698 Ragdolls:StopCarrying(Character)
2699 Network:FireServer("StopCarrying")
2700 else
2701 self.AnimationHandler:PlayTrack("PickUp", .1, 1, 1)
2702
2703 local cframe = RootPart.CFrame * CFrame.new(0, -2, -3)
2704 * CFrame.Angles(-math.pi / 2, 0, math.pi / 2)
2705
2706 module:ToggleMovementBlocker("PickUp", true)
2707
2708 coroutine.wrap(function()
2709 self.AnimationHandler:GetTrack("PickUp").Stopped:Wait()
2710 Ragdolls:StopCarrying(Character)
2711 module:ToggleMovementBlocker("PickUp", false)
2712
2713 local rootPart = carryTarget:FindFirstChild("HumanoidRootPart")
2714 if rootPart then
2715 rootPart.Anchored = true
2716 rootPart.CFrame = cframe
2717 rootPart.Anchored = false
2718 end
2719
2720 Network:FireServer("StopCarrying", cframe)
2721 end)()
2722 end
2723end
2724
2725
2726
2727do
2728 local typeFolder = script.PlayerItems.Types
2729 for _,mod in pairs(script.PlayerItems:GetDescendants()) do
2730 if mod:IsA("ModuleScript") and not mod:IsDescendantOf(typeFolder) then
2731 local item = require(mod)
2732 PlayerItems[item.Name] = item
2733 end
2734 end
2735
2736 local function newChar(plr, char)
2737 if not char:IsDescendantOf(workspace) then
2738 while not char:IsDescendantOf(workspace) and plr.Parent and plr.Character == char do
2739 wait()
2740 end
2741 if not plr.Parent or plr.Character ~= char then return end
2742 end
2743
2744 AddCharacterKinematics(char)
2745 AnimationHandler.new(char)
2746 end
2747
2748 local function newPlayer(plr)
2749 if plr == LocalPlayer then return end
2750 plr.CharacterAdded:Connect(function(char) newChar(plr, char) end)
2751 if plr.Character then
2752 Utils.Thread(function() newChar(plr, plr.Character) end)
2753 end
2754 end
2755
2756 Players.PlayerAdded:Connect(newPlayer)
2757 for i,v in pairs(Players:GetPlayers()) do newPlayer(v) end
2758end
2759
2760
2761
2762
2763
2764
2765
2766function module:Whistle()
2767 if self.AnimationHandler then
2768 self.AnimationHandler:PlayTrack("Whistle",.1,1,1);
2769 end
2770end
2771
2772AnimationHandler:BindToKeyframe({
2773 Whistle=function(self)
2774 local Rig = self.Rig;
2775 if Rig then
2776 local Head = Rig:FindFirstChild("Head");
2777 if Head then
2778 local whistle = Head:FindFirstChild("Whistle");
2779
2780 if whistle then
2781 whistle=whistle:clone();
2782 whistle.Parent=Head;
2783 whistle.Pitch=math.random(90,110)/100;
2784 whistle:Play();
2785 whistle.Ended:connect(function()
2786 whistle:Destroy();
2787 end)
2788 end
2789 end
2790 end
2791 end,
2792 SpurKick=function(self)
2793 local Rig = self.Rig;
2794 if Rig then
2795 local hrp = Rig:FindFirstChild("HumanoidRootPart");
2796 if hrp then
2797 local kick = hrp:FindFirstChild("SpurKick");
2798
2799 if self.Owner then
2800 local ridinganimal = WildLife:GetRidingAnimal();
2801 if ridinganimal then
2802 ridinganimal:Boost();
2803 Camera:Vibrate(math.rad(.1),.2,0.05);
2804 ridinganimal.self.AnimationHandler:PlayTrack("Spur");
2805
2806 end
2807 end
2808
2809 if kick then
2810 kick=kick:clone();
2811 kick.Parent=hrp;
2812 kick.Pitch=math.random(90,110)/100;
2813 kick:Play();
2814 kick.Ended:connect(function()
2815 kick:Destroy();
2816 end)
2817
2818 end
2819
2820
2821 end
2822 end
2823 end,
2824
2825})
2826
2827InputHandler:RegisterActions({
2828 Sprint = {"Sprint", function(state)
2829 IsSprintButtonDown = state == Enum.UserInputState.Begin
2830 return true
2831 end},
2832
2833 Jump = {"Jump", function(state)
2834 if state.Name ~= "Begin" then
2835 return;
2836 end
2837
2838 module:Unseat();
2839 return true
2840 end},
2841
2842 PullFromHolster={"ActivateItemSec",function(state)
2843 if state == Enum.UserInputState.Begin then
2844 module.AnimationHandler:PlayTrack("HolsterPull",.1,1,1);
2845 else
2846 module.AnimationHandler:StopTrack("HolsterPull",.1);
2847 end
2848 end,false},
2849
2850 StartCarry = {"Interact", function(state)
2851 if state.Name ~= "Begin" then return end
2852 if shared.Taming or module:IsRagdolled() or module.IsCarrying then return end
2853
2854 if module.CanCarry then
2855 local carryTarget = module.CanCarryTarget
2856
2857 module.CanCarry = false
2858 module.CanCarryTarget = nil
2859
2860 if module.CanCarryNotif then
2861 module.CanCarryNotif.Enabled = false
2862 module.CanCarryNotif = nil
2863 end
2864
2865 InputHandler:ToggleAction("StartCarry", false)
2866
2867 local item = module:GetEquippedItem()
2868 if item.Name == "Lasso" and item.LassoTarget then
2869 item.StartedCarrying = true
2870 end
2871
2872 module:EquipItem(nil)
2873 module:StartCarrying(carryTarget)
2874 end
2875 end, false},
2876
2877 StopCarry = {"InteractCancel", function(state)
2878 if state.Name ~= "Begin" then return end
2879 if not module.IsCarrying or module.CarryCanceled then return end
2880 module:StopCarrying()
2881 end, false},
2882
2883 BreakFree = {"InteractCancel", function(state)
2884 if state.Name ~= "Begin" then return end
2885 if not module:CanBreakFree() then return end
2886
2887 if tick() - (LastBreakFreeAttempt or 0) < 0.1 then return end
2888 IsWiggling = true
2889 LastBreakFreeAttempt = tick()
2890
2891 module.AnimationHandler:PlayTrack("TiedUpWiggle", 0.25, 1, 3)
2892
2893 BreakFreePercSpeed = math.max(0.1, BreakFreePercSpeed - 0.005)
2894 module.BreakFreePerc = module.BreakFreePerc + 0.05
2895 end, false},
2896})
2897
2898
2899local ReplicatedItems = {}
2900
2901Network:BindEvents({
2902 Respawn = function(char)
2903 if char == Character then
2904 module.IsDead = false
2905 module:OnControlLost()
2906
2907 if IsRagdolled then
2908 IsRagdolled = false
2909 Ragdolls:ExitRagdoll(Character)
2910 Ragdolls:UncontrolRagdoll(Character)
2911 end
2912
2913 module.IsTiedUp = false
2914 InputHandler:ToggleAction("BreakFree", false)
2915
2916 Human:ChangeState("GettingUp")
2917
2918 module.Idling=true;
2919 InputHandler:Enable()
2920
2921 module:FaceMouse(true);
2922
2923 end
2924
2925 for _,part in pairs(char:GetChildren()) do
2926 if part:IsA("BasePart") then
2927 for _,child in pairs(part:GetChildren()) do
2928 if child.Name == "EffectArrow" then
2929 child:Destroy()
2930 end
2931 end
2932 end
2933 end
2934 end,
2935 Die = function(client, hit, relPos, dir, force)
2936 if client == LocalPlayer then
2937 module.IsDead = true
2938 module:OnControlLost()
2939
2940 module.IsTiedUp = false
2941 InputHandler:ToggleAction("BreakFree", false)
2942 InputHandler:Disable()
2943
2944 if not IsRagdolled then
2945 IsRagdolled = true
2946 Ragdolls:EnterRagdoll(Character)
2947 Ragdolls:ControlRagdoll(Character)
2948 end
2949
2950 if hit then
2951 wait()
2952 Ragdolls:CreateRagdollForce(hit, hit.CFrame * relPos, dir, force)
2953 end
2954 else
2955 -- clone character, local ragdoll?
2956 end
2957 end,
2958 EquipItem = function(player, itemName)
2959 if player == LocalPlayer then
2960-- module:EquipItem(itemName)
2961 warn("Server called EquipItem on LocalPlayer, this shouldn't happen unless something went wrong!")
2962 return
2963 end
2964
2965 local item = PlayerItems[itemName]
2966 local char = player.Character
2967
2968 if char and char:IsDescendantOf(workspace) and item then
2969 local state = ReplicatedItems[char]
2970
2971 if not state then
2972 state = { char = char }
2973 ReplicatedItems[char] = state
2974
2975 local remCon
2976 remCon = char.AncestryChanged:Connect(function()
2977 if char:IsDescendantOf(workspace) then return end
2978 remCon:Disconnect()
2979 ReplicatedItems[char] = nil
2980 end)
2981 end
2982
2983 if state.lastItem then
2984 state.lastItem:ReplicatedUnequip(char, state.itemState)
2985 end
2986
2987 state.lastItem = item
2988 state.itemState = {}
2989
2990 item:ReplicatedEquip(char, state.itemState)
2991 end
2992 end,
2993
2994
2995 -- Ragdoll
2996
2997 RequestKnockback = function(hit, relPos, hitDir, force)
2998 if module:IsRagdolled() or module.IsDead or module.IsTiedUp then return end
2999 module:Ragdoll(hit,nil,hit.CFrame * relPos, hitDir, force)
3000 end,
3001 RequestRagdoll=function()
3002 if module:IsRagdolled() or module.IsDead or module.IsTiedUp then return end
3003 module:Ragdoll()
3004 end,
3005
3006 EnterRagdoll = function()
3007 module:OnControlLost()
3008
3009 if not IsRagdolled then
3010 IsRagdolled = true
3011 Ragdolls:EnterRagdoll(module.Character)
3012 Ragdolls:ControlRagdoll(module.Character)
3013 end
3014 end,
3015
3016 -- Lassoing, ignore the names
3017
3018 GainControl = function()
3019 HasControl = true
3020
3021 InputHandler:ToggleAction("BreakFree", false)
3022 end,
3023 LoseControl = function()
3024 HasControl = false
3025 module:OnControlLost()
3026
3027 InputHandler:ToggleAction("BreakFree", true)
3028 module.BreakFreePerc = 0
3029 BreakFreePercSpeed = 0.45
3030
3031 if IsRagdolled then
3032 IsRagdolled = false
3033 Ragdolls:ExitRagdoll(module.Character)
3034 Ragdolls:UncontrolRagdoll(module.Character)
3035 end
3036 end,
3037
3038 -- Carrying
3039
3040 TieUp = function()
3041 module:OnControlLost()
3042
3043 module.IsTiedUp = true
3044 module.BreakFreePerc = 0
3045 BreakFreePercSpeed = 0.45
3046
3047 Human:ChangeState("Physics")
3048
3049 InputHandler:ToggleAction("BreakFree", true)
3050 module.AnimationHandler:PlayTrack("TiedUpGround", .25, 1, 1)
3051
3052 if IsRagdolled then
3053 IsRagdolled = false
3054 Ragdolls:ExitRagdoll(module.Character)
3055 Ragdolls:UncontrolRagdoll(module.Character)
3056 end
3057 end,
3058 CreateCarryEffect = function(carrier, target)
3059 Ragdolls:StartCarrying(carrier, target)
3060
3061 if target == Character then
3062 Human:ChangeState("Physics")
3063
3064 module.AnimationHandler:StopTrack("TiedUpGround", .25)
3065 module.AnimationHandler:PlayTrack("TiedUp", .25, 1, 1)
3066 end
3067 end,
3068 RemoveCarryEffect = function(carrier, target, cframe)
3069 Ragdolls:StopCarrying(carrier)
3070
3071 local rootPart = target:FindFirstChild("HumanoidRootPart")
3072 if rootPart and cframe then
3073 rootPart.Anchored = true
3074 rootPart.CFrame = cframe
3075 rootPart.Anchored = false
3076 end
3077
3078 if target == Character and module.IsTiedUp then
3079 Human:ChangeState("Physics")
3080 module.AnimationHandler:StopTrack("TiedUp", .25)
3081 module.AnimationHandler:PlayTrack("TiedUpGround", .25, 1, 1)
3082 end
3083 end,
3084 StopCarrying = function(instant)
3085 if module.IsCarrying and not module.IsCarryingLocal then
3086 module:StopCarrying(instant)
3087 end
3088 end,
3089
3090 -- Tied Up
3091
3092 CreateTiedUpEffect = function(char)
3093 if char:FindFirstChild("TiedUpEffect") then return end
3094 local twine = Resources.LassoTwine:Clone()
3095 twine.Name = "TiedUpEffect"
3096 twine.TwineWeld.Part0 = char:FindFirstChild("UpperTorso")
3097 twine.TwineWeld.C0 = CFrame.new(0, 0, 0.5)
3098 twine.Parent = char
3099 end,
3100 RemoveTiedUpEffect = function(char)
3101 if char:FindFirstChild("TiedUpEffect") then
3102 char.TiedUpEffect:Destroy()
3103 end
3104
3105 print("REMOVE TIED UP: ",char,module:GetLassoTarget());
3106 if char == module:GetLassoTarget() then -- If the player is my lasso target, unequip lasso
3107 module:EquipItem(nil);
3108 end
3109
3110 end,
3111
3112 -- For when someone you were lassoing dies
3113 DisconnectLasso=function()
3114 if module:GetLassoTarget() then
3115 module:EquipItem();
3116 end
3117 end,
3118 --
3119
3120
3121
3122 -- Waist
3123
3124 UpdateWaist = function(char, cframe)
3125 local upperTorso = char:FindFirstChild("UpperTorso")
3126 local waist = upperTorso and upperTorso:FindFirstChild("Waist")
3127 if waist then
3128 local rigAtt = waist.Part0.WaistRigAttachment
3129-- waist.C0 = (cframe or CFrame.new()) * rigAtt.CFrame
3130 end
3131 end
3132})
3133
3134
3135function module.Update(updateTime)
3136 if not Character then return end
3137
3138 RobbingItems.Update(updateTime);
3139
3140 -- Face Mouse
3141
3142
3143 FaceMouse.Update(updateTime);
3144
3145
3146 --
3147
3148
3149 IsSprinting = IsSprintButtonDown
3150 module.IsSprinting = IsSprinting
3151
3152 -- Update equipped item
3153
3154 local item = module:GetEquippedItem()
3155 item:Update()
3156
3157 -- Stop wiggling (also please move this out of the main loop at some point)
3158
3159 if IsWiggling and tick() - LastBreakFreeAttempt > 1 then
3160 IsWiggling = false
3161 module.AnimationHandler:StopTrack("TiedUpWiggle")
3162 end
3163
3164 -- Health effects
3165
3166 local health = module.HealthValue.Value
3167 if health < 40 then
3168 local perc_to_dead = Mathf.PercentBetween(health, 40, 0)
3169 module.PercToDead = perc_to_dead
3170
3171 Health_Saturation:SetGoal(Mathf.Lerp(0.5, 1.3, perc_to_dead))
3172 Health_Muffle:SetGoal(Mathf.Lerp(0.5, 1, perc_to_dead))
3173 Health_Brightness:SetGoal(Mathf.Lerp(0, -0.3, perc_to_dead))
3174 else
3175 module.PercToDead = nil
3176
3177 Health_Muffle:SetGoal(0)
3178 Health_Saturation:SetGoal(0)
3179 Health_Brightness:SetGoal(0)
3180 end
3181
3182 -- Update Waist
3183
3184 local waistGoal = CFrame.new()
3185 local waistupdatetime = .1
3186
3187 if item.IsAiming then
3188 WasUpdatingWaist = true
3189
3190 local mousePos = Utils.GetMouseHit()
3191
3192 local relative = RootPart.CFrame:pointToObjectSpace(mousePos)
3193 local angleY = math.asin(relative.unit.Y) - math.asin(2 / math.max(relative.magnitude,2))
3194 local angleXZ = math.atan2(-relative.X, -relative.Z)
3195
3196 local _,ay,_ = (RootJoint.Part0.CFrame:toObjectSpace(RootJoint.Part1.CFrame)):toEulerAnglesYXZ();
3197
3198 local OnVehicle = WildLife:GetOnVehicle();
3199 local SeatPart = module:GetSeated();
3200
3201 if Camera:IsFirstPerson() then
3202 if not OnVehicle and not SeatPart then
3203 angleXZ = 0
3204 end
3205
3206 waistupdatetime = 0.05;
3207 end
3208
3209 waistGoal = CFrame.Angles(0, -ay + angleXZ, 0) * CFrame.Angles(angleY, ay, 0)
3210 Network:FireServer("UpdateWaist", waistGoal)
3211 elseif WasUpdatingWaist then
3212 WasUpdatingWaist = false
3213 Network:FireServer("UpdateWaist")
3214 end
3215
3216 Waist.C0 = Waist.C0:Lerp(waistGoal * Waist.Part0.WaistRigAttachment.CFrame, math.clamp(updateTime/waistupdatetime,0,1))
3217
3218 -- Carrying
3219
3220 local canCarry = false
3221 local carryTarget
3222
3223
3224 local ControllingAnimals = WildLife:GetControllingAnimals();
3225
3226 if not module:IsRagdolled() and not module.IsCarrying and not module.IsDead and not (#ControllingAnimals>0) then
3227 if item.Name == "Lasso" and item.IsLassoing and item.LassoTarget then
3228 local dist = (item.LassoTarget.HumanoidRootPart.Position - RootPart.Position).Magnitude
3229 if dist <= 5 then
3230 canCarry = true
3231 carryTarget = item.LassoTarget
3232 end
3233 else
3234 local closest
3235 local dist
3236
3237 for _,player in pairs(Players:GetPlayers()) do
3238 if player ~= LocalPlayer then
3239 local char = player.Character
3240 local stateInfo = char and char:FindFirstChild("StateInfo")
3241 if stateInfo and stateInfo.TiedUp.Value and not stateInfo.Carried.Value then
3242 local charDist = (char.HumanoidRootPart.Position - RootPart.Position).Magnitude
3243 if charDist <= 5 and (not dist or charDist < dist) then
3244 closest = char
3245 dist = charDist
3246 end
3247 end
3248 end
3249 end
3250
3251 canCarry = closest ~= nil
3252 carryTarget = closest
3253 end
3254 end
3255
3256 local lastCarryTarget = module.CanCarryTarget
3257 if canCarry ~= module.CanCarry or carryTarget ~= lastCarryTarget then
3258 module.CanCarry = canCarry
3259 module.CanCarryTarget = carryTarget
3260
3261 InputHandler:ToggleAction("StartCarry", canCarry)
3262
3263 if module.CanCarryNotif then
3264 module.CanCarryNotif.Enabled = false
3265 module.CanCarryNotif = nil
3266 end
3267
3268 local carryNotif = carryTarget and carryTarget:FindFirstChild("CarryNotification", true)
3269 if carryNotif then
3270 module.CanCarryNotif = carryNotif
3271 carryNotif.Enabled = true
3272 end
3273 end
3274
3275 -- Tied Up
3276
3277 if module:CanBreakFree() then
3278 if module.BreakFreePerc >= 1 then
3279 if not IsBreakingFree then
3280 IsBreakingFree = true
3281 coroutine.wrap(function()
3282 local success = Network:InvokeServer("AttemptBreakFree")
3283 if success then
3284 if module.IsTiedUp then
3285 module.IsTiedUp = false
3286 InputHandler:ToggleAction("BreakFree", false)
3287 module:Ragdoll()
3288 end
3289 end
3290
3291 IsBreakingFree = false
3292 end)()
3293 end
3294 else
3295 module.BreakFreePerc = math.max(0, module.BreakFreePerc - updateTime * BreakFreePercSpeed)
3296 end
3297 end
3298
3299 -- Check
3300
3301 if module:IsRagdolled() then return end
3302
3303
3304
3305 -- Swimming
3306
3307 local humanState = Human:GetState().Name;
3308
3309 local IsSwimming = humanState == "Swimming" and true or false;
3310
3311 if IsSwimming then
3312 if not module.LastIsSwimming then
3313 SharedUtils.SetPhysicalProperties(Character,"Swimming");
3314 local splashcf = CFrame.new(RootPart.Position);
3315 VFX.CreateWaterSplash(splashcf);
3316 Network:FireServer("CreateWaterSplash",splashcf);
3317 end
3318 else
3319 if module.LastIsSwimming then
3320 SharedUtils.SetPhysicalProperties(Character,"Default");
3321 end
3322 end
3323 module.LastIsSwimming=IsSwimming;
3324
3325 --
3326
3327
3328
3329 -- Falling
3330
3331
3332
3333 if RootPart.Velocity.Y < -20 then
3334 if not LastFalling then
3335 LastFalling = true
3336 FallStart = RootPart.Position.Y
3337 end
3338
3339 local fallDist = FallStart - RootPart.Position.Y
3340
3341 local RidingAnimal = WildLife:GetRidingAnimal();
3342
3343 if fallDist > 20 then
3344
3345 module:Ragdoll(nil,true);
3346
3347
3348 if RidingAnimal then
3349 RidingAnimal:Ragdoll();
3350 end
3351
3352
3353
3354
3355 return
3356 end
3357 else
3358 if LastFalling then
3359 LastFalling = nil
3360 FallStart = nil
3361 end
3362 end
3363
3364 -- Character Animations
3365
3366 local animTrack = LastMoveTrack
3367 local animTrackSpeedGoal = LastMoveTrackSpeedGoal
3368
3369
3370
3371 local Seated = module.Seated and module.Seated.Value;
3372
3373
3374 local RootVelocity = RootPart.Velocity;
3375 local horVel = RootVelocity * Vector3.new(1, 0, 1)
3376 if horVel.magnitude == 0 then
3377 horVel = Human.MoveDirection
3378 end
3379
3380 if (Human.MoveDirection.Magnitude > 0 or (IsSwimming == true and RootVelocity.magnitude > 4)) and not Seated then
3381
3382
3383 local moveAngleZ = math.asin(math.clamp(RootPart.CFrame.lookVector:Dot(horVel.Unit), -1, 1)) / (math.pi / 2)
3384 local moveAngleX = math.asin(math.clamp(RootPart.CFrame.rightVector:Dot(horVel.Unit), -1, 1)) / (math.pi / 2)
3385
3386 local dir = moveAngleZ > 0.45 and "Forward" or moveAngleZ < -0.45 and "Backward"
3387 or moveAngleX > 0 and "Right" or "Left"
3388
3389
3390 if IsSwimming then
3391 animTrack="Swim";
3392 WalkspeedGoal=14;
3393 animTrackSpeedGoal = 1
3394 elseif IsSprinting then
3395 WalkspeedGoal = 26
3396
3397 animTrack = "Run"
3398 animTrackSpeedGoal = 3
3399 else
3400 WalkspeedGoal = 7
3401
3402 if dir == "Forward" or dir == "Backward" then -- Forwards or Backwards
3403 animTrack = "Walk"
3404 animTrackSpeedGoal = 1
3405 elseif dir == "Right" then -- Right
3406 animTrack = "LeftStrafe"
3407 animTrackSpeedGoal = -1
3408 else -- Left
3409 animTrack = "LeftStrafe"
3410 animTrackSpeedGoal = 1
3411 end
3412 end
3413
3414 if dir == "Backward" then animTrackSpeedGoal = -animTrackSpeedGoal end
3415 else
3416
3417 animTrack = nil
3418 animTrackSpeedGoal = 0;
3419 WalkspeedGoal = 0;
3420 end
3421
3422 if not humanState:match("Run") and IsSwimming == false then
3423 animTrack = nil
3424 end
3425
3426 WalkspeedFadeTime = math.clamp(WalkspeedFadeTime + (updateTime/2), 0, 0.25)
3427
3428 Human.WalkSpeed = Mathf.Lerp(
3429 Human.WalkSpeed,
3430 WalkspeedGoal,
3431 math.clamp(updateTime / WalkspeedFadeTime,0,1)
3432 )
3433
3434 -- Play anims
3435
3436 if LastHumanState ~= humanState then
3437 if humanState == "Jumping" then
3438 module.AnimationHandler:PlayTrack("Jump", 0.2, 1, 1)
3439 module:Unseat();
3440
3441
3442 elseif humanState == "Freefall" then
3443 local jumpTrack = module.AnimationHandler:GetTrack("Jump")
3444
3445 if jumpTrack.IsPlaying then
3446 coroutine.wrap(function()
3447 jumpTrack.Stopped:Wait()
3448 if Human:GetState().Name == "Freefall" then
3449 module.AnimationHandler:PlayTrack("Fall", 0.25, 1, 1)
3450 end
3451 end)()
3452 else
3453 module.AnimationHandler:PlayTrack("Fall", 0.25, 1, 1)
3454 end
3455 elseif LastHumanState == "Jumping" or LastHumanState == "Freefall" then
3456 module.AnimationHandler:StopTrack("Jump", 0.1)
3457 module.AnimationHandler:StopTrack("Fall", 0.1)
3458 WalkspeedFadeTime = 0.1
3459 end
3460
3461 LastHumanState = humanState
3462 end
3463
3464
3465
3466 if Seated then
3467 module.AnimationHandler:StopTrack("Fall", 0.1)
3468 else
3469 if module.LastSeated then
3470 module:Unseated();
3471 end
3472 end
3473
3474 module.LastSeated=Seated;
3475
3476
3477
3478 local IdleTrack = IsSwimming and "SwimIdle" or "Idle";
3479 local Idling = module.Idling;
3480
3481 if Idling then
3482
3483 if module.LastIdleTrack and module.LastIdleTrack ~= IdleTrack then
3484 module.AnimationHandler:StopTrack(module.LastIdleTrack,0.1);
3485 end
3486 module.AnimationHandler:PlayTrack(IdleTrack, 0.1, 1, 1);
3487
3488 else
3489 module.AnimationHandler:StopTrack(IdleTrack,0.1);
3490 end
3491 module.LastIdleTrack=IdleTrack;
3492
3493
3494 if LastMoveTrack ~= animTrack or LastMoveTrackSpeedGoal ~= animTrackSpeedGoal then
3495 local lastTrack = LastMoveTrack
3496 LastMoveTrack = animTrack
3497 LastMoveTrackSpeedGoal = animTrackSpeedGoal
3498
3499 local timePos = 0
3500
3501 if lastTrack then
3502 module.AnimationHandler:StopTrack(lastTrack, WalkspeedFadeTime)
3503 local lastTrackInst = module.AnimationHandler:GetTrack(lastTrack)
3504 timePos = lastTrackInst.TimePosition / lastTrackInst.Length
3505
3506 if lastTrack == "Run" and animTrack == "Walk" then
3507 timePos = (timePos + .05) % 1
3508 end
3509 end
3510
3511 if animTrack then
3512 module.AnimationHandler:PlayTrack(animTrack, WalkspeedFadeTime, 1, animTrackSpeedGoal)
3513 local animTrackInst = module.AnimationHandler:GetTrack(animTrack)
3514 animTrackInst.TimePosition = timePos * animTrackInst.Length
3515
3516 if lastTrack then
3517 local track = module.AnimationHandler:GetTrack(lastTrack)
3518 track:AdjustSpeed(track.Length / animTrackInst.Length * animTrackSpeedGoal)
3519 end
3520 end
3521 end
3522end
3523
3524
3525return module
3526
3527--[[
3528 MuleItem
3529 Handles all logic for the Mule gun
3530
3531 class MuleItem extends GunItem {}
3532--]]
3533
3534-- Services
3535
3536local ReplicatedStorage = game:GetService("ReplicatedStorage")
3537
3538-- Modules
3539
3540local LoadModule = require(ReplicatedStorage.Modules.Load)
3541local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
3542
3543local GunItem = LoadModule("GunItem")
3544
3545-- Variables
3546
3547local module = GunItem.new("Mule")
3548
3549return module
3550
3551--[[
3552 YellowBoyRifleItem
3553 Handles all logic for the YellowBoyRifle gun
3554
3555 class YellowBoyRifle extends GunItem {}
3556--]]
3557
3558-- Services
3559
3560local ReplicatedStorage = game:GetService("ReplicatedStorage")
3561
3562-- Modules
3563
3564local LoadModule = require(ReplicatedStorage.Modules.Load)
3565local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
3566
3567local GunItem = LoadModule("GunItem")
3568
3569-- Variables
3570
3571local self = GunItem.new("YellowBoyRifle")
3572
3573self.BaseRecoil = 25;
3574self.RagdollPower = 2;
3575self.ProjectileAccuracy = 1;
3576self.ProjectilePower = 1200;
3577self.ProjectileDamage = 30;
3578
3579
3580
3581return self;
3582
3583--[[
3584 PeacekeeperItem
3585 Handles all logic for the Peacekeeper gun
3586
3587 class PeacekeeperItem extends GunItem {}
3588--]]
3589
3590-- Services
3591
3592local ReplicatedStorage = game:GetService("ReplicatedStorage")
3593
3594-- Modules
3595
3596local LoadModule = require(ReplicatedStorage.Modules.Load)
3597local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
3598
3599local GunItem = LoadModule("GunItem")
3600
3601-- Variables
3602
3603local self = GunItem.new("Peacekeeper")
3604self.Sidearm=true;
3605
3606self.BaseRecoil = 15;
3607self.RagdollPower = 1;
3608self.ProjectileAccuracy = 1;
3609self.ProjectilePower = 750;
3610self.ProjectileDamage = 20;
3611
3612
3613
3614return self;
3615
3616--[[
3617 PeacekeeperItem
3618 Handles all logic for the Peacekeeper gun
3619
3620 class PeacekeeperItem extends GunItem {}
3621--]]
3622
3623-- Services
3624
3625local ReplicatedStorage = game:GetService("ReplicatedStorage")
3626
3627-- Modules
3628
3629local LoadModule = require(ReplicatedStorage.Modules.Load)
3630local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
3631
3632local GunItem = LoadModule("GunItem")
3633
3634-- Variables
3635
3636local self = GunItem.new("Lemat")
3637self.Sidearm=true;
3638
3639self.BaseRecoil = 15;
3640self.RagdollPower = 1;
3641self.ProjectileAccuracy = 1;
3642self.ProjectilePower = 750;
3643self.ProjectileDamage = 20;
3644
3645
3646
3647return self;
3648
3649--[[
3650 PeacekeeperItem
3651 Handles all logic for the Peacekeeper gun
3652
3653 class PeacekeeperItem extends GunItem {}
3654--]]
3655
3656-- Services
3657
3658local ReplicatedStorage = game:GetService("ReplicatedStorage")
3659
3660-- Modules
3661
3662local LoadModule = require(ReplicatedStorage.Modules.Load)
3663local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
3664
3665local GunItem = LoadModule("GunItem")
3666
3667-- Variables
3668
3669local self = GunItem.new("Model3")
3670self.Sidearm=true;
3671
3672self.BaseRecoil = 15;
3673self.RagdollPower = 1;
3674self.ProjectileAccuracy = 1;
3675self.ProjectilePower = 750;
3676self.ProjectileDamage = 20;
3677
3678
3679
3680return self;
3681
3682--[[
3683 BowItem
3684 Handles all logic for bows
3685
3686 class BowItem extends BaseItem {
3687 boolean BowItem.IsDrawing
3688 boolean BowItem.IsAiming
3689 }
3690--]]
3691
3692-- Services
3693
3694local ReplicatedStorage = game:GetService("ReplicatedStorage")
3695
3696-- Modules
3697
3698local LoadModule = require(ReplicatedStorage.Modules.Load)
3699local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
3700
3701local AnimationHandler = LoadModule("AnimationHandler")
3702local PlayerCharacter = LoadModule("PlayerCharacter", true)
3703local Projectiles = LoadModule("Projectiles", true)
3704local Camera = LoadModule("Camera", true)
3705local Mathf = LoadModule("Mathf")
3706local UI = LoadModule("UI", true)
3707local BaseItem = LoadModule("BaseItem")
3708
3709-- Variables
3710
3711local Resources = ReplicatedStorage.Resources
3712
3713local module = BaseItem.new("Bow")
3714
3715module.IsDrawing = false
3716module.IsAiming = false
3717
3718AnimationHandler:BindToKeyframe({
3719 BowRelease = function(self)
3720 local bow = self.Rig:FindFirstChild("Bow")
3721 local arrow = self.Rig:FindFirstChild("Arrow")
3722
3723 if arrow and not self.Owner then
3724 arrow:Destroy()
3725 end
3726
3727 if bow then
3728 local handle = bow:FindFirstChild("BowHandle")
3729 if handle then
3730 local shootsound = handle:FindFirstChild("BowFire"..math.random(1,5))
3731 shootsound:Play()
3732 end
3733 end
3734 end,
3735 BowKnock = function(self)
3736 local bow = self.Rig:FindFirstChild("Bow")
3737 if bow then
3738 local handle = bow:FindFirstChild("BowHandle")
3739 if handle then
3740 local knocksound = handle:FindFirstChild("ArrowKnock"..math.random(1,3))
3741 knocksound:Play()
3742 end
3743 end
3744 end,
3745 BowDraw = function(self)
3746 local bow = self.Rig:FindFirstChild("Bow")
3747 if bow then
3748 local handle = bow:FindFirstChild("BowHandle")
3749 if handle then
3750 local drawsound = handle:FindFirstChild("BowDrawPull"..math.random(1,3))
3751 drawsound:Play()
3752 end
3753 end
3754 end,
3755 GrabArrow = function(self)
3756 local bow = self.Rig:FindFirstChild("Bow")
3757 if bow then
3758 local handle = bow:FindFirstChild("BowHandle")
3759 if handle then
3760 local grabsound = handle:FindFirstChild("ArrowGrab"..math.random(1,2))
3761 grabsound:Play()
3762 end
3763 end
3764
3765 local arrow = self.Rig:FindFirstChild("Arrow")
3766 local righthand = self.Rig:FindFirstChild("RightHand")
3767 if not arrow and righthand then
3768 arrow = Resources.Arrow:Clone()
3769
3770 local weld = Instance.new("Motor6D")
3771 weld.Name = "WeldToArrow"
3772 weld.Part0 = righthand
3773 weld.Part1 = arrow.ArrowHandle
3774 weld.C0 = arrow.C0.Value
3775 weld.C1 = arrow.C1.Value
3776 weld.Parent = arrow
3777
3778 arrow.Parent = self.Rig
3779 end
3780 end
3781})
3782
3783
3784function module:Activate()
3785 if self.IsDrawing then return end
3786 self.IsDrawing = true
3787
3788 if not PlayerCharacter.Character:FindFirstChild("Arrow") then
3789 self:StopTrack("Idle", .25, 1, 1)
3790 self:PlayTrack("Knock", .25, 1, 2)
3791
3792 self:GetTrack("Knock").Stopped:Wait()
3793 if not self.IsEquipped or not self.IsDrawing then return end
3794
3795 self:StopTrack("Knock", 0.25)
3796 else
3797 self:StopTrack("Idle", 0.1)
3798 end
3799
3800 self.StartedPulling = tick()
3801
3802 self:PlayTrack("Aim", 0.25, 1, 2)
3803 self:GetTrack("Aim").Stopped:Wait()
3804 if not self.IsEquipped or not self.IsDrawing then return end
3805
3806 self.Vibration = 0
3807 self.IsAiming = true
3808 self.StartedDrawing = tick()
3809
3810 self:PlayTrack("Draw", 0, 1, 1.5)
3811 self:GetTrack("Draw").Stopped:Wait()
3812 if not self.IsEquipped or not self.IsDrawing then return end
3813
3814 self:PlayTrack("Drawn", 0, 1, 1)
3815end
3816
3817function module:Deactivate()
3818 if not self.IsDrawing then return end
3819 self.IsDrawing = false
3820
3821 local arrow = PlayerCharacter.Character:FindFirstChild("Arrow")
3822 if self.IsAiming and arrow then
3823 local origin = arrow.ArrowHandle.Position
3824 local power = math.min(1, (tick() - self.StartedDrawing) / self.DrawTime)
3825 local accuracy = Mathf.Lerp(1, 0.5, self.Vibration)
3826
3827 arrow:Destroy()
3828
3829 Projectiles.Fire({
3830 char = PlayerCharacter.Character,
3831 origin = origin,
3832 power = Mathf.Lerp(30, 350, power),
3833 damage = Mathf.Lerp(20, 50, power),
3834 accuracy = accuracy,
3835 isArrow = true
3836 })
3837
3838 self.IsShooting = true
3839 self:PlayTrack("Release", 0, 1, 1)
3840
3841 coroutine.wrap(function()
3842 self:GetTrack("Release").Stopped:Wait()
3843 self.IsShooting = false
3844 end)()
3845
3846 local recoil = Mathf.Lerp(5, 20, power)
3847 Camera:AddRecoil(Mathf.Lerp(recoil, recoil * 1.5, self.Vibration))
3848 elseif arrow then
3849 arrow.ArrowHandle.ArrowVibrate:Stop()
3850 end
3851
3852 self.IsAiming = false
3853 self.StartedPulling = nil
3854 self.StartedDrawing = nil
3855
3856 self:StopTrack("Knock", 0.25)
3857 self:StopTrack("Aim", 0.25)
3858 self:StopTrack("Draw", 0.25)
3859 self:StopTrack("Drawn", 0.25)
3860 self:PlayTrack("Idle", 0.25, 1, 1)
3861end
3862
3863function module:ReplicatedUnequip(char, state)
3864 self.super.ReplicatedUnequip(self, char, state)
3865
3866 if char == PlayerCharacter.Character then
3867 PlayerCharacter:FaceMouse(true);
3868 end
3869
3870 local arrow = char:FindFirstChild("Arrow")
3871 if arrow then
3872 arrow:Destroy()
3873 end
3874end
3875
3876function module:Equip()
3877 self.super.Equip(self)
3878
3879 PlayerCharacter:FaceMouse(false);
3880
3881 if not self.PullTime then
3882 self.PullTime = module:GetTrack("Aim").Length * 0.5
3883 self.DrawTime = module:GetTrack("Draw").Length * 0.75
3884 end
3885
3886 self:PlayTrack("Idle")
3887 Camera:SetMode("Custom")
3888end
3889
3890function module:Update()
3891 if self.IsDrawing then
3892 if self.IsAiming then
3893 local elapsed = tick() - self.StartedDrawing
3894
3895 if elapsed < 1.5 then
3896 local stress = (elapsed / 1.5) * 0.02
3897
3898 local perc = math.min(1, elapsed / (self.DrawTime - 0.5))
3899 local Bar1Goal = Mathf.Lerp(0 ,50, perc)
3900 local Bar2Goal = Mathf.Lerp(0, -50, perc)
3901
3902 UI.SetArrowBarGoals(Bar1Goal, Bar2Goal)
3903 Camera:Vibrate(math.rad(stress), .05, 0)
3904 else
3905 local arrow = PlayerCharacter.Character:FindFirstChild("Arrow")
3906 if arrow then
3907 local sound = arrow.ArrowHandle.ArrowVibrate
3908
3909 if not sound.IsPlaying then
3910 sound:Play()
3911 end
3912
3913 local vibAmt = Mathf.PercentBetween(elapsed, 1.25, 4.5) ^ 2
3914 self.Vibration = vibAmt
3915
3916 sound.Volume = vibAmt / 2
3917
3918 Camera:Vibrate(math.rad(vibAmt * .1), .05, 0)
3919
3920 local now = tick() % 1024
3921
3922 local arrowShakeAmt = vibAmt * .02
3923 local arrowShake = CFrame.fromOrientation(
3924 math.noise(now * 12 + 18.45) * arrowShakeAmt,
3925 math.noise(now * 12 + 4.300) * arrowShakeAmt,
3926 math.noise(now * 12 + 12.75) * arrowShakeAmt
3927 )
3928
3929 local baseC0 = arrow.ArrowHandle.Fake:FindFirstChild("C0").Value
3930 arrow.ArrowHandle.Fake.C0 = baseC0 * arrowShake
3931
3932 local dist = math.clamp(1 - math.acos(-arrowShake.lookVector.Z) * 100, 0, 1)
3933 UI.SetArrowBarGoals(50 * dist, -50 * dist, true)
3934
3935 local weld = self.Model:FindFirstChild("WeldToBow")
3936 if weld then
3937 local bowShakeAmt = vibAmt * .01
3938 weld.C0 = self.Model.WeldC0.Value * CFrame.new(
3939 math.noise(now * 9 + 18.45) * bowShakeAmt,
3940 math.noise(now * 9 + 4.300) * bowShakeAmt,
3941 math.noise(now * 9 + 12.75) * bowShakeAmt
3942 )
3943 end
3944 end
3945 end
3946 elseif self.StartedPulling then
3947 local perc = math.min(1, (tick() - self.StartedPulling) / self.PullTime)
3948 local Bar1Goal = Mathf.Lerp(-120, 0, perc)
3949 local Bar2Goal = Mathf.Lerp(120, 0, perc)
3950
3951 UI.SetArrowBarGoals(Bar1Goal, Bar2Goal)
3952 end
3953 end
3954end
3955
3956
3957return module
3958
3959--[[
3960 LassoItem
3961 Handles all logic for the lasso item
3962 Do note that the actual lassoing logic is in Ragdolls
3963
3964 class LassoItem extends BaseItem {
3965 bool LassoItem.IsThrowingLasso
3966 bool LassoItem.IsReelingIn
3967 bool LassoItem.IsLassoing : is true even when taming
3968 bool LassoItem.IsTaming : only true when lassoing an animal (before mounting it)
3969
3970 Instance? LassoItem.LassoTarget : only defined when lassoing a person
3971 }
3972--]]
3973
3974-- Services
3975
3976local ReplicatedStorage = game:GetService("ReplicatedStorage")
3977local TweenService = game:GetService("TweenService")
3978
3979-- Modules
3980
3981local LoadModule = require(ReplicatedStorage.Modules.Load)
3982local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
3983
3984local PlayerCharacter = LoadModule("PlayerCharacter", true)
3985local InputHandler = LoadModule("InputHandler")
3986local Ragdolls = LoadModule("Ragdolls", true)
3987local BaseItem = LoadModule("BaseItem")
3988local Camera = LoadModule("Camera")
3989local FX = LoadModule("FX", true)
3990local VFX = LoadModule("VFX");
3991
3992local Network = LoadSharedModule("Network")
3993
3994-- Variables
3995
3996local Resources = ReplicatedStorage.Resources
3997local Ignore = workspace.Ignore
3998
3999local module = BaseItem.new("Lasso")
4000
4001
4002InputHandler:RegisterActions({
4003 DisconnectLasso = {"InteractCancel", function(state)
4004 if state.Name ~= "Begin" then return end
4005
4006 local item = PlayerCharacter:GetEquippedItem()
4007 if item.Name == "Lasso" then
4008 PlayerCharacter:EquipItem(nil)
4009 end
4010 end, false},
4011 TightenLasso = {"TightenLasso", function()
4012 local item = PlayerCharacter:GetEquippedItem()
4013 if item.Name == "Lasso" and item.LassoTarget then
4014 item.LassoLength = math.clamp(item.LassoLength - 1, 5, 50)
4015
4016 local tween = TweenService:Create(item.LassoPuller, TweenInfo.new(.5), {
4017 Length = item.LassoLength
4018 })
4019 tween:Play()
4020
4021 local att = Instance.new("Attachment", workspace.Terrain)
4022 local att1 = Instance.new("Attachment", PlayerCharacter.RootPart)
4023 att1.CFrame = CFrame.Angles(0, 0, math.pi / 2)
4024 att.CFrame = att1.WorldCFrame
4025
4026 local const = Instance.new("PrismaticConstraint")
4027 const.Attachment0 = att
4028 const.Attachment1 = att1
4029 const.Parent = att
4030
4031 tween.Completed:Connect(function()
4032 const:Destroy()
4033 att:Destroy()
4034 att1:Destroy()
4035 end)
4036
4037 if tick() - (item.LastTightenYank or 0) > 1 then
4038 item.LastTightenYank = tick()
4039 item:PlayTrack("YankInPlace", .1, 1, 1)
4040 end
4041 end
4042 end, false},
4043 LoosenLasso = {"LoosenLasso", function()
4044 local item = PlayerCharacter:GetEquippedItem()
4045 if item.Name == "Lasso" and item.LassoTarget then
4046 item.LassoLength = math.clamp(item.LassoLength + 1, 5, 50)
4047
4048 TweenService:Create(item.LassoPuller, TweenInfo.new(.5), {
4049 Length = item.LassoLength
4050 }):Play()
4051 end
4052 end, false}
4053})
4054
4055
4056function module:ReplicatedEquip(char, state)
4057 local item = Instance.new("Model")
4058 item.Name = "LassoItems"
4059
4060 local circle = Resources.LassoCircle:Clone()
4061 circle.Weld.Part0 = char.RightHand
4062 circle.Parent = item
4063
4064 local ropeToCircle = Resources.RopeToCircle:Clone()
4065 ropeToCircle.Attachment0 = char.RightHand.RightGripAttachment
4066 ropeToCircle.Attachment1 = circle.Attachment
4067 ropeToCircle.Parent = item
4068
4069 VFX.CreateFakeAttachment(ropeToCircle, "Attachment0", ropeToCircle.Attachment0, true)
4070 VFX.CreateFakeAttachment(ropeToCircle, "Attachment1", ropeToCircle.Attachment1, true)
4071
4072 local ropeToHand = Resources.RopeToHand:Clone()
4073 ropeToHand.Attachment0 = char.LeftHand.LeftGripAttachment
4074 ropeToHand.Attachment1 = char.RightHand.RightGripAttachment
4075 ropeToHand.Parent = item
4076
4077 local twine = Resources.LassoTwine:Clone()
4078 twine.TwineWeld.Part0 = char.LeftHand
4079 twine.Parent = item
4080
4081 item.Parent = char
4082
4083 state.LassoCircle = circle
4084 state.CircleWeld = circle.Weld
4085 state.RopeToCircle = ropeToCircle
4086 state.Model = item
4087end
4088
4089function module:ReplicatedUnequip(char, state)
4090 if state.Model then
4091 state.Model:Destroy()
4092 state.Model = nil
4093 end
4094end
4095
4096function module:LassoCharacter(char)
4097 local stateInfo = char:FindFirstChild("StateInfo")
4098 if not stateInfo or stateInfo.Ragdolled.Value then
4099 PlayerCharacter:EquipItem(nil)
4100 return
4101 end
4102
4103 local rootPart = char:FindFirstChild("HumanoidRootPart")
4104 local leftLeg = char:FindFirstChild("LeftLowerLeg")
4105 local rightLeg = char:FindFirstChild("RightLowerLeg")
4106
4107 if not rootPart or not leftLeg or not rightLeg then return end
4108
4109 self.IsLassoingLocal = true
4110 self.LassoTarget = char
4111
4112 local animalWeld = rootPart:FindFirstChild("Animal_To_Player")
4113 if animalWeld then
4114 animalWeld.Part1 = nil
4115 end
4116
4117 local folder = Instance.new("Folder")
4118 folder.Name = "LassoItems"
4119 folder.Parent = char
4120
4121 self.LassoEffect = folder
4122
4123 local ankleconstraint = Instance.new("RopeConstraint")
4124 ankleconstraint.Name = "AnkleConstraint"
4125 ankleconstraint.Attachment0 = leftLeg.LassoConstraint
4126 ankleconstraint.Attachment1 = rightLeg.LassoConstraint
4127 ankleconstraint.Length = .9
4128 ankleconstraint.Parent = folder
4129
4130 local waistAtt = PlayerCharacter.Character.LowerTorso.WaistRigAttachment
4131 local draggingAtt = leftLeg.LeftAnkleRigAttachment
4132
4133 local puller = Instance.new("RopeConstraint")
4134 puller.Name = "Puller"
4135 puller.Length = (waistAtt.WorldPosition - draggingAtt.WorldPosition).Magnitude
4136 puller.Visible = false
4137 puller.Restitution = 0.5
4138 puller.Attachment0 = waistAtt
4139 puller.Attachment1 = draggingAtt
4140 puller.Parent = folder
4141
4142 self.LassoPuller = puller
4143 self.LassoLength = puller.Length
4144
4145 FX:CreateLassoEffect(PlayerCharacter.Character, char, folder)
4146 Ragdolls:EnterRagdoll(char)
4147 Ragdolls:ControlRagdoll(char)
4148
4149 InputHandler:ToggleAction("DisconnectLasso", true)
4150 InputHandler:ToggleAction("LoosenLasso", true)
4151 InputHandler:ToggleAction("TightenLasso", true)
4152
4153 coroutine.wrap(function()
4154 local success
4155 self:Async(function() success = Network:InvokeServer("AttemptLasso", char) end)
4156 if not self.IsEquipped then return end
4157
4158 if not success then
4159 PlayerCharacter:EquipItem(nil)
4160 return
4161 end
4162
4163 self.IsLassoingLocal = false
4164 end)()
4165end
4166
4167function module:LassoAnimal(animal)
4168 local lassoCircle = animal:FindFirstChild("LassoCircle")
4169 if not lassoCircle then
4170 PlayerCharacter:EquipItem(nil)
4171 return
4172 end
4173
4174 self.IsTaming = true
4175 self.IsTamingLocal = true
4176 self.TamingTarget = animal
4177 self.TamingCircle = lassoCircle
4178 self.TamingDistance = (PlayerCharacter.RootPart.Position - lassoCircle.Position).Magnitude
4179
4180 FX:CreateTamingEffect(animal, PlayerCharacter.Character)
4181
4182 coroutine.wrap(function()
4183 local success
4184 self:Async(function()
4185 success = Network:InvokeServer("AttemptTame", animal)
4186 end)
4187 if not self.IsEquipped then return end
4188
4189 if not success then
4190 PlayerCharacter:EquipItem(nil)
4191 return
4192 end
4193
4194 self.IsTamingLocal = false
4195 end)()
4196end
4197
4198
4199function module:OnHit(hit, instant)
4200 self.LassoTouched:Disconnect()
4201 self.LassoTouched = nil
4202
4203 self.IsThrowingLasso = false
4204
4205 self:StopTrack("Hold", .1)
4206
4207 if instant then
4208 PlayerCharacter:ToggleMovementBlocker("Lassoing", false)
4209 return
4210 end
4211
4212 local foundChar, foundAnimal
4213
4214 if hit then
4215 local par = hit.Parent
4216 while par and par ~= workspace do
4217 foundChar = par:FindFirstChild("Humanoid") and par
4218 if foundChar then break end
4219
4220 foundAnimal = par:FindFirstChild("AnimationController") and par
4221 if foundAnimal then break end
4222
4223 par = par.Parent
4224 end
4225 end
4226
4227 local animLength = 1
4228 local sound = PlayerCharacter.RootPart:FindFirstChild("LassoReelFinish" .. math.random(1, 2))
4229 if sound then
4230 sound.Pitch = math.random(140, 150) / 100
4231 sound:Play()
4232 animLength = sound.TimeLength * (1 / sound.Pitch)
4233 end
4234
4235 if foundChar then
4236 local stateInfo = foundChar:FindFirstChild("StateInfo")
4237 if shared.Role ~= "Law" or not stateInfo or stateInfo.Ragdolled.Value or stateInfo.Dead.Value then
4238 foundChar = nil
4239 end
4240 elseif foundAnimal then
4241 local owner = foundAnimal:FindFirstChild("Owner")
4242 local taming = foundAnimal:FindFirstChild("Taming")
4243 if not owner or owner.Value or not taming or taming.Value then
4244 foundAnimal = nil
4245 end
4246 end
4247
4248 if foundChar or foundAnimal then
4249 if shared.HitMarker then
4250 shared.HitMarker:Play()
4251 end
4252
4253 self.Model:Destroy()
4254 self.Model = nil
4255
4256 self.IsLassoing = true
4257
4258 if foundChar then
4259 self:LassoCharacter(foundChar)
4260 elseif foundAnimal then
4261 self:LassoAnimal(foundAnimal)
4262 end
4263
4264 local Wagon = PlayerCharacter.OnWagon;
4265
4266 local YankTrack = Wagon and "YankWagon" or "Yank";
4267
4268 local track = self:GetTrack(YankTrack)
4269 self:PlayTrack(YankTrack, 0.1)
4270
4271 coroutine.wrap(function()
4272 track.Stopped:Wait()
4273 PlayerCharacter:ToggleMovementBlocker("Lassoing", false)
4274
4275 if not self.IsLassoing then return end
4276 self:PlayTrack("Attached", .25)
4277 end)()
4278 else
4279 self.IsReelingIn = true
4280
4281 local lassoCircle = self.LassoCircle
4282 lassoCircle.Anchored = true
4283
4284 local goal = CFrame.new(PlayerCharacter.Character.RightHand.Position, lassoCircle.Position)
4285 * CFrame.Angles(0, math.pi / 2, 0)
4286
4287 local tweenInfo = TweenInfo.new(animLength)
4288
4289 local ropeTween = TweenService:Create(
4290 self.RopeToCircle,
4291 tweenInfo,
4292 { Length = 0 }
4293 )
4294 local moveTween = TweenService:Create(
4295 lassoCircle,
4296 tweenInfo,
4297 { CFrame = goal }
4298 )
4299 local scaleTween = TweenService:Create(
4300 lassoCircle.Mesh,
4301 tweenInfo,
4302 { Scale = Vector3.new(0.1, 0.1, 0.1) }
4303 )
4304
4305 lassoCircle.BodyForce.Force = Vector3.new()
4306 self.ReelTween = moveTween
4307
4308 ropeTween:Play()
4309 moveTween:Play()
4310 scaleTween:Play()
4311
4312
4313 local Wagon = PlayerCharacter.OnWagon;
4314
4315 local YankTrack = Wagon and "YankWagon" or "Yank";
4316
4317 local track = self:GetTrack(YankTrack)
4318 self:PlayTrack(YankTrack, 0.1)
4319
4320 coroutine.wrap(function()
4321 track.Stopped:Wait()
4322 PlayerCharacter:ToggleMovementBlocker("Lassoing", false)
4323 if not self.IsReelingIn then return end
4324
4325 local WrapUpTrack = Wagon and "WrapUpWagon" or "WrapUp";
4326
4327
4328 self:PlayTrack(WrapUpTrack, 0.1, 1, 1)
4329 moveTween.Completed:Wait()
4330 if not self.IsReelingIn then return end
4331
4332 lassoCircle.BodyGyro.MaxTorque = Vector3.new()
4333 lassoCircle.Anchored = false
4334 lassoCircle.Weld.Part1 = lassoCircle
4335
4336 self:StopTrack(WrapUpTrack,0.5)
4337 self:PlayTrack("Swing", 0.1, 1, 1)
4338
4339 self.ReelTween = nil
4340 self.IsReelingIn = false
4341 end)()
4342 end
4343end
4344
4345function module:CanThrow()
4346 return not (self.IsThrowingLasso or self.IsReelingIn or self.IsLassoing)
4347end
4348
4349function module:Activate()
4350 if not self:CanThrow() then return end
4351 self.IsThrowingLasso = true
4352
4353 local Wagon = PlayerCharacter.OnWagon;
4354
4355 local ThrowTrack = Wagon and "ThrowWagon" or "Throw";
4356
4357 self:StopTrack("Swing")
4358 self:PlayTrack(ThrowTrack, 0.1, 1, 1.5)
4359
4360 PlayerCharacter:ToggleMovementBlocker("Lassoing", true)
4361
4362 local releaseCon
4363 releaseCon = self:GetTrack(ThrowTrack).KeyframeReached:Connect(function(key)
4364 if key ~= "LassoRelease" or not self.IsEquipped then return end
4365 releaseCon:Disconnect()
4366
4367 local clothMove = PlayerCharacter.RootPart.ClothMove
4368 local throwSound = PlayerCharacter.RootPart.LassoThrow
4369
4370 throwSound.Pitch = math.random(98, 102) / 100
4371 throwSound:Play()
4372 clothMove:Play()
4373
4374 self.CircleWeld.Part1 = nil
4375
4376 local lassoCircle = self.LassoCircle
4377 local circleGyro = lassoCircle.BodyGyro
4378 local camCFrame = workspace.CurrentCamera.CFrame
4379
4380 local facePos = Vector3.new(camCFrame.X, lassoCircle.Position.Y, camCFrame.Z)
4381
4382 circleGyro.MaxTorque = Vector3.new(1, 1, 1) * 4e6
4383 circleGyro.CFrame = CFrame.new(lassoCircle.Position, facePos) * CFrame.Angles(0, -math.pi / 2, 0)
4384 lassoCircle.BodyForce.Force = Vector3.new(0, lassoCircle:GetMass() * workspace.Gravity * 0.5, 0)
4385
4386 self:StopTrack(ThrowTrack)
4387 self:PlayTrack("Hold", 0.1, 1, 1)
4388
4389 local throwTarget = camCFrame.p + camCFrame.lookVector * 40
4390 local throwDir = (throwTarget - lassoCircle.Position)
4391 local ropelength = throwDir.Magnitude
4392
4393 lassoCircle.Mesh.Scale = Vector3.new(.1, .1, .1)
4394 lassoCircle.Velocity = throwDir.Unit * 80
4395
4396 self.RopeToCircle.Length = ropelength * 0.1
4397 self.RopeToCircle.Enabled = true
4398
4399 local touched;
4400 touched = lassoCircle.Touched:Connect(function(hit)
4401 if hit:isDescendantOf(PlayerCharacter.Character) or hit:isDescendantOf(Ignore) then return end
4402
4403 if not hit.CanCollide and not hit.Parent:FindFirstChild("Humanoid") and not hit.Parent:FindFirstChild("AnimationController") then
4404 return
4405 end
4406
4407 self:OnHit(hit)
4408 end)
4409
4410 self.LassoTouched = touched
4411 end)
4412end
4413
4414function module:Equip()
4415 self.super.Equip(self)
4416
4417 PlayerCharacter:FaceMouse(false);
4418
4419 self:PlayTrack("Swing", .1, 1, 1.25)
4420 Camera:SetMode("Custom")
4421end
4422
4423function module:Unequip()
4424 self.super.Unequip(self)
4425
4426 local LassoRopePullSound = PlayerCharacter.RootPart:FindFirstChild("LassoRopePull")
4427 if LassoRopePullSound and LassoRopePullSound.IsPlaying then
4428 LassoRopePullSound:Stop()
4429 end
4430
4431 if self.IsThrowingLasso then
4432 self:OnHit(nil, true)
4433 end
4434
4435 if self.IsReelingIn then
4436 self.IsReelingIn = false
4437 self.ReelTween:Cancel()
4438 end
4439
4440 if self.IsLassoing then
4441 self.IsLassoing = false
4442
4443 if self.IsTaming then
4444 self.IsTaming = false
4445
4446 FX:RemoveTamingEffect(PlayerCharacter.Character)
4447
4448 local LassoRopePullSound = PlayerCharacter.RootPart:FindFirstChild("LassoRopePull")
4449 if LassoRopePullSound and LassoRopePullSound.IsPlaying then
4450 LassoRopePullSound:Stop()
4451 end
4452
4453 if not self.DidMount then
4454 Network:FireServer("StopTaming")
4455 end
4456 elseif self.LassoTarget then
4457 local target = self.LassoTarget
4458
4459 self.LassoEffect:Destroy()
4460 self.LassoEffect = nil
4461
4462 self.LassoTarget = nil
4463
4464 Ragdolls:UncontrolRagdoll(target)
4465 Ragdolls:ExitRagdoll(target)
4466
4467 local didTieUp = self.StartedCarrying == true
4468 Network:FireServer("DisconnectLasso", didTieUp)
4469 end
4470 end
4471
4472 InputHandler:ToggleAction("DisconnectLasso", false)
4473 InputHandler:ToggleAction("LoosenLasso", false)
4474 InputHandler:ToggleAction("TightenLasso", false)
4475
4476 self.StartedCarrying = false
4477 self.IsTamingLocal = false
4478 self.TryingToMount = false
4479 self.DidMount = false
4480end
4481
4482
4483function module:Update()
4484 local isUpdatingLasso = self.IsThrowingLasso or self.IsReelingIn
4485
4486 if isUpdatingLasso then
4487 self.IsUpdatingLasso = true
4488 Network:FireServer("UpdateThrownLasso", self.LassoCircle.CFrame)
4489 elseif self.IsUpdatingLasso then
4490 self.IsUpdatingLasso = false
4491 Network:FireServer("UpdateThrownLasso", nil)
4492 end
4493
4494 if self.IsLassoing and self.LassoTarget then
4495 local dist = (PlayerCharacter.RootPart.Position - self.LassoTarget.HumanoidRootPart.Position).Magnitude
4496
4497 local lastDist = self.LastLassoDistance or 0
4498 self.LastLassoDistance = dist
4499
4500 local pullSound = PlayerCharacter.RootPart:FindFirstChild("LassoRopePull")
4501
4502 if tick() - (self.LastLassoPullThang or 0) > 0.5 then
4503 self.LastLassoPullThang = tick()
4504
4505 if dist - lastDist <= -.05 then
4506 if not pullSound.IsPlaying then
4507 pullSound:Play()
4508 end
4509
4510 self:PlayTrack("CloseIn", .25, 1, .75)
4511 elseif dist - lastDist > .05 then
4512 if not pullSound.IsPlaying then
4513 pullSound:Play()
4514 end
4515
4516 self:PlayTrack("CloseIn", .25, 1, -.75)
4517 else
4518 if pullSound.IsPlaying then
4519 pullSound:Stop()
4520 end
4521
4522 self:StopTrack("CloseIn", .25)
4523 end
4524 end
4525 end
4526
4527 if self.IsTaming then
4528 local dist = (PlayerCharacter.RootPart.Position - self.TamingCircle.Position).Magnitude
4529
4530 if not self.IsTamingLocal and not self.TryingToMount then
4531 if dist > self.TamingDistance + 5 then
4532 local lassobreak = PlayerCharacter.RootPart:FindFirstChild("LassoBreak")
4533 if lassobreak and not lassobreak.IsPlaying then
4534 lassobreak:Play()
4535 end
4536
4537 PlayerCharacter:EquipItem(nil)
4538 return
4539 end
4540
4541 if dist < 8 then
4542 self.TryingToMount = true
4543 coroutine.wrap(function()
4544 self:Async(function() Network:InvokeServer("TamingMount") end)
4545 if not self.IsEquipped then return end
4546 self.DidMount = true
4547 PlayerCharacter:EquipItem(nil)
4548 end)()
4549 end
4550 end
4551
4552 local lastDist = self.LastTamingRopeDistance or 0
4553 self.LastTamingRopeDistance = dist
4554
4555 local pullSound = PlayerCharacter.RootPart:FindFirstChild("LassoRopePull")
4556
4557 if dist - lastDist <= -.05 then
4558 if not pullSound.IsPlaying then
4559 pullSound:Play()
4560 end
4561
4562 self:PlayTrack("CloseIn", .25, 1, .75)
4563 elseif dist - lastDist > -.025 then
4564 if pullSound.IsPlaying then
4565 pullSound:Stop()
4566 end
4567
4568 self:StopTrack("CloseIn", .25)
4569 end
4570 end
4571end
4572
4573
4574Network:BindEvents({
4575 UpdateThrownLasso = function(char, cframe)
4576 local lassoItems = char and char:FindFirstChild("LassoItems")
4577 if lassoItems then
4578 local lassoCircle = lassoItems:FindFirstChild("LassoCircle")
4579
4580 if cframe then
4581 lassoCircle.Weld.Part1 = nil
4582 lassoCircle.Anchored = true
4583 lassoCircle.CFrame = cframe
4584 else
4585 lassoCircle.Anchored = false
4586 lassoCircle.Weld.Part1 = lassoCircle
4587 end
4588 end
4589 end
4590})
4591
4592
4593return module
4594
4595--[[
4596 DynamiteItem
4597 Handles all logic for Dynamite
4598
4599--]]
4600
4601-- Services
4602
4603local ReplicatedStorage = game:GetService("ReplicatedStorage")
4604
4605-- Modules
4606
4607local LoadModule = require(ReplicatedStorage.Modules.Load)
4608local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
4609
4610local AnimationHandler = LoadModule("AnimationHandler")
4611local PlayerCharacter = LoadModule("PlayerCharacter", true)
4612local Projectiles = LoadModule("Projectiles", true)
4613local Camera = LoadModule("Camera", true)
4614local Mathf = LoadModule("Mathf")
4615local UI = LoadModule("UI", true)
4616local BaseItem = LoadModule("BaseItem")
4617
4618local FuseFX = LoadModule("FuseFX");
4619
4620local DrawProjectile = LoadModule("DrawProjectile");
4621
4622
4623-- Variables
4624
4625local Resources = ReplicatedStorage.Resources
4626
4627local module = BaseItem.new("Dynamite")
4628
4629
4630module.IsAiming = false
4631
4632
4633
4634
4635function module:Activate()
4636 if self.IsAiming then return end
4637 self.IsAiming = true
4638
4639 print("ACTIVATE");
4640
4641 if not self.Lit then
4642 self:PlayTrack("Light",.1,1,1);
4643 end
4644end
4645
4646function module:Deactivate()
4647 if not self.IsAiming then return end
4648 self.IsAiming = false
4649
4650 print("DEACTIVATE");
4651
4652 if not self.Lit then
4653 self:StopTrack("Light",.1);
4654 else
4655 self:StopTrack("LightLoop",0);
4656 self:PlayTrack("Throw",0,1,1);
4657
4658 self.Lit=nil;
4659
4660 DrawProjectile.DrawingProjectilePosition=nil;
4661
4662
4663 local primary = self.Model.PrimaryPart;
4664 if primary then
4665 local projectile = {
4666 char = PlayerCharacter.Character,
4667 origin = primary.Position,
4668 accuracy = 1,
4669 power = 25,
4670 ragdollpower_mult = 1,
4671 damage = 10,
4672 isDynamite=true,
4673 lightTime=self.LightTime;
4674 }
4675 Projectiles.Fire(projectile);
4676 end
4677
4678 end
4679
4680end
4681
4682function module:OnDynamiteLit()
4683 self.Lit=true;
4684 self.LightTime=tick();
4685 self:StopTrack("Light",.5);
4686 self:PlayTrack("LightLoop",.5,1,1);
4687end
4688
4689function module:ReplicatedUnequip(char, state)
4690 self.super.ReplicatedUnequip(self, char, state)
4691
4692 DrawProjectile.DrawingProjectilePosition=nil;
4693
4694 if char == PlayerCharacter.Character then
4695 self.Lit=nil;
4696 PlayerCharacter:FaceMouse(true);
4697 end
4698
4699end
4700
4701function module:Equip()
4702 self.super.Equip(self)
4703
4704 PlayerCharacter:FaceMouse(false);
4705
4706 self:PlayTrack("Idle")
4707 Camera:SetMode("Custom")
4708end
4709
4710function module:Update()
4711 if self.Lit then
4712 if self.Model then
4713 local primarypart = self.Model.PrimaryPart;
4714 if primarypart then
4715 DrawProjectile.DrawingProjectilePosition=primarypart.Position;
4716 end
4717 end
4718 else
4719 DrawProjectile.DrawingProjectilePosition=nil;
4720 end
4721end
4722
4723
4724
4725AnimationHandler:BindToKeyframe({
4726 LightDynamite=function(self)
4727 if self.Owner then
4728 local item = PlayerCharacter:GetEquippedItem();
4729 if item.OnDynamiteLit then
4730 item:OnDynamiteLit();
4731 end
4732 end
4733
4734 local rig = self.Rig;
4735 if rig then
4736 local dynamite = rig:FindFirstChild("Dynamite");
4737 if dynamite then
4738 local primary = dynamite.PrimaryPart;
4739 if primary then
4740 local matchlight = primary:FindFirstChild("MatchLight");
4741 if matchlight then
4742 matchlight:Play();
4743 FuseFX:StartLightingFuse(rig,dynamite,tick(),8);
4744 end
4745 end
4746 end
4747 end
4748 end
4749})
4750
4751return module
4752
4753--[[
4754 KnifeItem
4755 Handles all logic for knives
4756
4757 class KnifeItem extends BaseItem {}
4758--]]
4759
4760-- Services
4761
4762local ReplicatedStorage = game:GetService("ReplicatedStorage")
4763
4764-- Modules
4765
4766local LoadModule = require(ReplicatedStorage.Modules.Load)
4767local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
4768
4769local BaseItem = LoadModule("BaseItem")
4770local Camera = LoadModule("Camera")
4771
4772-- Variables
4773
4774local module = BaseItem.new("Knife")
4775
4776function module:Activate()
4777 self:PlayTrack("Stab", 0, 1, 1)
4778end
4779
4780function module:Equip()
4781 self.super.Equip(self)
4782
4783 self:PlayTrack("Idle")
4784 Camera:SetMode("Custom")
4785end
4786
4787return module
4788
4789--[[
4790 FistItem
4791 Handles all logic for fists
4792
4793 class FistItem extends BaseItem {}
4794--]]
4795
4796-- Services
4797
4798local ReplicatedStorage = game:GetService("ReplicatedStorage")
4799
4800-- Modules
4801
4802local LoadModule = require(ReplicatedStorage.Modules.Load)
4803local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
4804local PlayerCharacter = LoadModule("PlayerCharacter",true);
4805local InputHandler = LoadModule("InputHandler")
4806local BaseItem = LoadModule("BaseItem")
4807local Camera = LoadModule("Camera")
4808
4809-- Variables
4810
4811local module = BaseItem.new("Fist")
4812
4813function module:Equip()
4814 self.super.Equip(self)
4815
4816 PlayerCharacter:FaceMouse(true);
4817
4818 InputHandler:ToggleAction("ActivateItem", false)
4819 InputHandler:ToggleAction("ActivateItemSec", false)
4820
4821 Camera:SetMode("Free")
4822end
4823
4824function module:Unequip()
4825 self.super.Unequip(self)
4826
4827 InputHandler:ToggleAction("ActivateItem", true)
4828 InputHandler:ToggleAction("ActivateItemSec", true)
4829end
4830
4831return module
4832
4833--[[
4834 BaseItem
4835 Base class for all items
4836
4837 class BaseItem {
4838 string BaseItem.Name
4839 bool BaseItem.IsEquipped
4840
4841 bool BaseItem:HasTrack(string trackName)
4842 AnimationTrack? BaseItem:GetTrack(string trackName)
4843 AnimationTrack? BaseItem:PlayTrack(string trackName[, number fadeTime, number weight, number speed])
4844 AnimationTrack? BaseItem:StopTrack(string trackName[, number fadeTime])
4845 void BaseItem:StopAllTracks([number fadeTime])
4846 All track names are prefixed by the item name, as in PlayTrack("Idle") in Lasso
4847 would play an animation called "LassoIdle". StopAllTracks only stops animations
4848 played with these methods, so it can be used to stop animations after unequipping,
4849 which is what the default implementation of BaseItem:Unequip does.
4850
4851 void BaseItem:Async(function func, ...)
4852 Yields until inner function finishes or BaseItem:CancelAsyncs() is called
4853
4854 void BaseItem:CancelAsyncs()
4855 Cancels all current asyncs, causing them to resume
4856 Called whenever the item is unequipped
4857
4858 void BaseItem:ReplicatedEquip(Model playerCharacter, table state)
4859 Called when another player equips this item
4860 Default implementation of BaseItem:Equip calls this with state set to self
4861 Otherwise state is an empty table
4862
4863 void BaseItem:ReplicatedUnequip(Model playerCharacter, table state)
4864 Called when another player unequips this item
4865 Default implementation of BaseItem:Unequip calls this with state set to self
4866 Otherwise state is the table that was used in ReplicatedEquip for this character
4867
4868 void BaseItem:Equip()
4869 Called when local player equips this item
4870 Default implementation of this calls self:ReplicatedEquip with state set to self
4871
4872 void BaseItem:Unequip()
4873 Called when local player unequips this item
4874 Default implementation of this calls self:ReplicatedUnequip with state set to self
4875
4876 void BaseItem:Activate()
4877 Called when primary action button (Left mouse button) is pressed down
4878
4879 void BaseItem:Deactivate()
4880 Called when primary action button (Left mouse button) is released
4881
4882 void BaseItem:ActivateSeconadry()
4883 Called when secondary action button (Right mouse button) is pressed down
4884
4885 void BaseItem:DeactivateSecondary()
4886 Called when secondary action button (Right mouse button) is released
4887
4888 void BaseItem:Update(number updateTime)
4889 Called every frame while the item is equipped
4890 }
4891--]]
4892
4893-- Services
4894
4895local ReplicatedStorage = game:GetService("ReplicatedStorage")
4896local UserInputService = game:GetService("UserInputService")
4897
4898-- Modules
4899
4900local LoadModule = require(ReplicatedStorage.Modules.Load)
4901local GunItem = LoadModule("GunItem",true);
4902
4903local KeyBindings = LoadModule("KeyBindings");
4904
4905local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
4906
4907local PlayerCharacter = LoadModule("PlayerCharacter", true)
4908local InputHandler = LoadModule("InputHandler")
4909local Utils = LoadModule("Utils")
4910
4911-- Variables
4912
4913local Resources = ReplicatedStorage.Resources
4914
4915local SuperMeta SuperMeta = {
4916 __index = function(this, i)
4917 local self = this.__self
4918 local depth = this.__depth
4919
4920 if i == "super" then
4921 local value = setmetatable({ __depth = depth + 1, __self = self }, SuperMeta)
4922 rawset(this, i, value)
4923 return value
4924 end
4925
4926 local orig = self[i]
4927 if orig == nil then return nil end
4928
4929 local target = self
4930 local value = orig
4931
4932 for _ = 1, depth do
4933 local newValue
4934
4935 repeat
4936 local meta = getmetatable(target)
4937 target = meta and meta.__index
4938 if type(target) ~= "table" then return nil end
4939 newValue = rawget(target, i)
4940 until newValue ~= nil and newValue ~= value
4941
4942 value = newValue
4943 end
4944
4945 rawget(this, i, value)
4946 return value
4947 end,
4948 __newindex = function() error("Attempt to modify a readonly table") end
4949}
4950
4951local module = {}
4952
4953InputHandler:RegisterActions({
4954 ActivateItem = {"ActivateItem", function(state)
4955 local item = PlayerCharacter:GetEquippedItem()
4956
4957 if state.Name == "Begin" then
4958 if PlayerCharacter:IsRagdolled() then return true end
4959
4960 if not item.IsActivated then
4961 item.IsActivated = true
4962 Utils.Thread(function() item:Activate() end)
4963 end
4964 else
4965 if item.IsActivated then
4966 item.IsActivated = false
4967 Utils.Thread(function() item:Deactivate() end)
4968 end
4969 end
4970
4971 return true
4972 end},
4973 ActivateItemSec = {"ActivateItemSec", function(state)
4974 local item = PlayerCharacter:GetEquippedItem()
4975
4976 if state.Name == "Begin" then
4977 if PlayerCharacter:IsRagdolled() then return true end
4978
4979 if not item.IsActivatedSecondary then
4980 item.IsActivatedSecondary = true
4981 Utils.Thread(function() item:ActivateSecondary() end)
4982 end
4983 else
4984 if item.IsActivatedSecondary then
4985 item.IsActivatedSecondary = false
4986 Utils.Thread(function() item:DeactivateSecondary() end)
4987 end
4988 end
4989
4990 return true
4991 end}
4992})
4993
4994function module.new(name)
4995 local self = {}
4996 setmetatable(self, { __index = module })
4997 self.super = setmetatable({ __depth = 1, __self = self }, SuperMeta)
4998
4999 self.Name = name
5000 self.Asyncs = {}
5001 self.RegisteredActions = {}
5002 self.Anims = {}
5003
5004 self.IsEquipped = false
5005 self.IsActivated = false
5006 self.IsActivatedSecondary = false
5007
5008 self.BaseModel = Resources.Items:FindFirstChild(self.Name)
5009
5010 if self.BaseModel then
5011 local cameraAim = self.BaseModel:FindFirstChild("CameraAimPoint")
5012 self.CameraAimPoint = cameraAim and cameraAim.Value
5013 end
5014
5015 return self
5016end
5017
5018function module:ResolveTrack(name)
5019 local animName = self.Anims[name]
5020 if animName ~= nil then
5021 return animName or nil
5022 end
5023
5024 if PlayerCharacter.AnimationHandler:GetTrack(self.Name .. name) then
5025 self.Anims[name] = self.Name .. name
5026 return self.Name .. name
5027 end
5028
5029 self.Anims[name] = false
5030 return nil
5031end
5032
5033function module:HasTrack(name)
5034 return self:ResolveTrack(name) ~= nil
5035end
5036
5037function module:GetTrack(name)
5038 local animName = self:ResolveTrack(name)
5039 return animName and PlayerCharacter.AnimationHandler:GetTrack(animName) or nil
5040end
5041
5042function module:PlayTrack(name, ...)
5043 local animName = self:ResolveTrack(name)
5044
5045 if not animName then
5046 --warn(debug.traceback(("Animation '%s%s' does not exist")):format(self.Name, name))
5047 return nil
5048 end
5049
5050 PlayerCharacter.AnimationHandler:PlayTrack(animName, ...)
5051 return self:GetTrack(animName)
5052end
5053
5054function module:StopTrack(name, ...)
5055 local animName = self:ResolveTrack(name)
5056
5057 if not animName then
5058 warn(debug.traceback(("Animation '%s%s' does not exist")):format(self.Name, name))
5059 return nil
5060 end
5061
5062 PlayerCharacter.AnimationHandler:StopTrack(animName, ...)
5063 return self:GetTrack(animName)
5064end
5065
5066function module:StopAllTracks(fadeTime)
5067 for _,animName in pairs(self.Anims) do
5068 if animName then -- List also contains invalid items
5069 PlayerCharacter.AnimationHandler:StopTrack(animName, fadeTime)
5070 end
5071 end
5072end
5073
5074function module:Async(fn, ...)
5075 local bind = Instance.new("BindableEvent")
5076 self.Asyncs[bind] = true
5077
5078 coroutine.wrap(function(...)
5079 fn(...)
5080 if bind then
5081 bind:Fire()
5082 end
5083 end)(...)
5084
5085 bind.Event:Wait()
5086 self.Asyncs[bind] = nil
5087 bind:Destroy()
5088 bind = nil
5089end
5090
5091function module:CancelAsyncs()
5092 for bind,_ in pairs(self.Asyncs) do
5093 bind:Fire()
5094 end
5095end
5096
5097function module:ReplicatedEquip(char, state)
5098 if not self.BaseModel then return end
5099
5100 local part0 = char:FindFirstChild(self.BaseModel.WeldTo.Value)
5101 if not part0 then return end
5102
5103 local item = self.BaseModel:Clone()
5104
5105 local weld = item:FindFirstChildWhichIsA("Motor6D");
5106
5107 weld.Part0 = part0
5108 weld.Part1 = item.HandleReference.Value
5109 weld.Parent = item
5110
5111 item.Parent = char
5112 state.Model = item
5113
5114 GunItem:RefillChamber(item);
5115end
5116
5117function module:ReplicatedUnequip(char, state)
5118 if state.Model then
5119 state.Model:Destroy()
5120 state.Model = nil
5121 end
5122end
5123
5124function module:Activate()
5125end
5126
5127function module:Deactivate()
5128end
5129
5130function module:ActivateSecondary()
5131end
5132
5133function module:DeactivateSecondary()
5134end
5135
5136function module:Equip()
5137 self.IsEquipped = true
5138 self:ReplicatedEquip(PlayerCharacter.Character, self)
5139
5140 print("Equip: ",self.Name);
5141
5142 if self.FaceMouse then
5143 if PlayerCharacter:HasControl() then
5144 PlayerCharacter:FaceMouse(true);
5145 end
5146 elseif not self.Name == "Fist" then
5147 PlayerCharacter:FaceMouse(false);
5148 end
5149end
5150
5151function module:Unequip()
5152 self.IsEquipped = false
5153
5154 self:CancelAsyncs()
5155 self:StopAllTracks()
5156
5157 self:ReplicatedUnequip(PlayerCharacter.Character, self)
5158
5159 self.IsActivatedSecondary = false
5160 Utils.Thread(function() self:DeactivateSecondary() end)
5161 self.LastTrack=nil;
5162
5163 if PlayerCharacter:HasControl() and self.Name ~= "Fist" then
5164 PlayerCharacter:FaceMouse(true);
5165 end
5166
5167end
5168
5169function module:Update()
5170end
5171
5172return module
5173
5174--[[
5175 GunItem
5176 Base class for all gun based items
5177
5178 GunItem extends BaseItem {
5179 bool GunItem.IsAiming
5180 bool GunItem.IsLoading
5181 bool GunItem.IsReloading
5182 Because logic, IsLoading means the gun is being reloaded and IsReloading means it's playing
5183 the little after-shooting animation
5184
5185 bool GunItem.CanBeFanned
5186 bool GunItem.IsFanning
5187 A gun can be fanned if it has a "Fan" animation
5188
5189 number GunItem.Ammo
5190 number GunItem.MaxAmmo
5191
5192 number GunItem.BaseRecoil
5193 number GunItem.RagdollPower
5194 number GunItem.ProjectileAccuracy
5195 number GunItem.ProjectilePower
5196 number GunItem.ProjectileDamage
5197
5198 void GunItem:Load()
5199 Starts the gun reloading process if possible
5200 }
5201--]]
5202
5203-- Services
5204
5205local ReplicatedStorage = game:GetService("ReplicatedStorage")
5206local TweenService = game:GetService("TweenService");
5207
5208-- Modules
5209
5210local LoadModule = require(ReplicatedStorage.Modules.Load)
5211local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
5212
5213local Utils = LoadModule("Utils");
5214local KeyBindings = LoadModule("KeyBindings");
5215local Holsters = LoadModule("Holsters");
5216
5217local AnimationHandler = LoadModule("AnimationHandler")
5218local PlayerCharacter = LoadModule("PlayerCharacter", true)
5219local InputHandler = LoadModule("InputHandler", true)
5220local Projectiles = LoadModule("Projectiles", true)
5221local Ragdolls = LoadModule("Ragdolls", true)
5222local Camera = LoadModule("Camera", true)
5223local FX = LoadModule("FX", true)
5224local VFX = LoadModule("VFX",true);
5225local UI = LoadModule("UI", true)
5226local Mathf = LoadModule("Mathf");
5227local BaseItem = LoadModule("BaseItem",true)
5228
5229local WildLife = LoadModule("WildLife",true);
5230
5231local SharedData = LoadSharedModule("SharedData")
5232local Network = LoadSharedModule("Network")
5233
5234-- Variables
5235
5236local Resources = ReplicatedStorage.Resources
5237local Ignore = workspace.Ignore
5238
5239local module = {}
5240setmetatable(module, { __index = BaseItem })
5241module.IsGunItem = true
5242
5243
5244
5245
5246
5247
5248
5249--[[
5250
5251 Some misc gun functions
5252
5253--]]
5254
5255
5256function module:GetBulletAtIndex(gun,index)
5257 return gun:FindFirstChild("ChamberBullet"..index);
5258end
5259function module:InsertBulletToChamber(gun,index)
5260 if not self:GetBulletAtIndex(gun,index) then
5261 local chamber = gun:FindFirstChild("ChamberReal");
5262
5263 local reference = Resources.Weapons.Chambers.Load:FindFirstChild(gun.Name);
5264 if reference then
5265 local indexbullet = reference:FindFirstChild(index);
5266 if indexbullet then
5267 local base = indexbullet.Base;
5268 local rel = reference.Chamber.CFrame:toObjectSpace(base.CFrame);
5269
5270 local bulletclone = Resources.Weapons.Bullets:FindFirstChild(gun.Name):clone();
5271 bulletclone.Name="ChamberBullet"..index;
5272 bulletclone.Parent=gun;
5273
5274 local weld = Instance.new("Weld");
5275 weld.C0=rel;
5276 weld.Part0=chamber;
5277 weld.Part1=bulletclone.Base;
5278 weld.Parent=bulletclone;
5279 return bulletclone;
5280 end
5281 end
5282 end
5283end
5284function module:RefillChamber(gun)
5285 local chamber = gun:FindFirstChild("ChamberReal");
5286 if chamber then
5287 for i = 1,6 do
5288 self:InsertBulletToChamber(gun,i);
5289 end
5290 end
5291end
5292function module:DropShell(gun,index,fly)
5293 local bullet = self:GetBulletAtIndex(gun,index);
5294 if bullet then
5295 local reference = Resources.Weapons.Chambers.Eject:FindFirstChild(gun.Name);
5296 local referencebullet = reference:FindFirstChild(index);
5297 if referencebullet then
5298 local c0 = reference.Chamber.CFrame:toObjectSpace(referencebullet.Base.CFrame);
5299
5300 local weld = bullet:FindFirstChild("Weld");
5301 if weld then
5302 bullet.Name="Shell";
5303 bullet.Parent=Ignore;
5304
5305 local base = bullet:FindFirstChild("Base");
5306
5307 local length = math.random(15,20)/100;
5308
5309 if fly then
5310 length=.1;
5311 end
5312
5313 delay(10,function()
5314 bullet:Destroy();
5315 end)
5316
5317 local tween = TweenService:Create(weld,TweenInfo.new(length),{C0=c0});
5318 tween:Play();
5319 tween.Completed:connect(function()
5320 weld:Destroy();
5321 bullet.Base.CanCollide=true;
5322
5323 local chamber = gun:FindFirstChild("Chamber");
5324 if chamber and fly then
5325 local velocity = (base.Position-chamber.Position).unit*(math.random(200,300)/100);
5326 local bodyvelocity = Instance.new("BodyVelocity",bullet.Base);
5327 bodyvelocity.Velocity=velocity;
5328 bodyvelocity.MaxForce=Vector3.new(400000,400000,400000);
5329 delay(.1,function()
5330 bodyvelocity:Destroy();
5331 end)
5332 bullet.Base.RotVelocity=Vector3.new(math.random(-360,360),math.random(-360,360),math.random(-360,360));
5333
5334 end
5335 end)
5336 end
5337 end
5338 end
5339end
5340
5341function module:CutBulletByIndex(gun,index)
5342 local bullet = module:GetBulletAtIndex(gun,index);
5343
5344 print("Cutting: ",index);
5345 if bullet then
5346
5347 local endpiece = bullet:FindFirstChild("End");
5348 if endpiece then
5349 endpiece:Destroy();
5350 end
5351 end
5352end
5353
5354
5355--
5356
5357
5358
5359
5360
5361InputHandler:RegisterActions({
5362 ReloadGun = {"Reload", function(state)
5363 if state.Name ~= "Begin" then return end
5364 local item = PlayerCharacter:GetEquippedItem()
5365 if item.IsGunItem then
5366 item:Load()
5367 end
5368 end, false},
5369 FanGun = {"InteractCancel", 2000, function(state)
5370 local item = PlayerCharacter:GetEquippedItem()
5371 if item.IsGunItem and item.CanBeFanned then
5372 item.IsFanButtonDown = state == Enum.UserInputState.Begin
5373 end
5374 end, false},
5375})
5376
5377function module.new(name)
5378 local self = BaseItem.new(name)
5379 setmetatable(self, { __index = module })
5380
5381 local baseModel = self.BaseModel
5382
5383
5384 local itemData = SharedData.PlayerItems[self.Name]
5385 self.MaxAmmo = itemData.MaxAmmo
5386 self.Ammo = self.MaxAmmo
5387
5388 self.IsAimButtonDown = false
5389 self.IsAiming = false
5390 self.IsFanButtonDown = false
5391 self.IsFanning = false
5392 self.IsLoading = false
5393 self.IsReloading = false
5394
5395
5396
5397 local referencefolder = Resources.Weapons.Chambers.Load:FindFirstChild(name);
5398
5399 if referencefolder then
5400 self.ChamberIndex=1;
5401 end
5402
5403
5404 return self
5405end
5406
5407function module:Load()
5408 if self.IsLoading or self.IsReloading or self.Ammo >= self.MaxAmmo then return end
5409 self.IsLoading = true
5410
5411 if not self:HasTrack("IdleLoad") then
5412 warn("Cannot load weapon - no idleload anim")
5413 return
5414 end
5415
5416 local gun = self.Model;
5417 local chamber = gun:FindFirstChild("Chamber");
5418 if chamber then
5419
5420 chamber.WeldToReal.C0=chamber.WeldToReal.OriginalC0.Value;
5421
5422 -- Cancel existing tweens
5423 TweenService:Create(chamber.WeldToReal,TweenInfo.new(0),{C0=chamber.WeldToReal.C0}):Play();
5424 end
5425
5426 self.ChamberIndex = 1
5427
5428 self:PlayTrack("IdleLoad", .1, 1, .75)
5429
5430 coroutine.wrap(function()
5431 self:GetTrack("IdleLoad").Stopped:Wait()
5432 if not self.IsEquipped then return end
5433
5434 if self:HasTrack("LoadEnd") then
5435 self:PlayTrack("LoadEnd", .1, 1, .75)
5436 self:GetTrack("LoadEnd").Stopped:Wait()
5437 if not self.IsEquipped then return end
5438 end
5439
5440 self.IsLoading = false
5441 end)()
5442end
5443
5444function module:ActivateSecondary()
5445 self.IsAimButtonDown = true
5446end
5447
5448function module:DeactivateSecondary()
5449
5450 self.IsAimButtonDown = false
5451end
5452
5453
5454
5455
5456
5457
5458
5459local ChamberTweens = {};
5460local ChamberReloadIndex={};
5461local SpinningChamberEffect={}
5462local SpinningChamberEffects={};
5463
5464local RNG = Random.new();
5465
5466function SpinningChamberEffect.new(gun,item)
5467 local self = setmetatable({},{__index=SpinningChamberEffect});
5468 self.Goal = RNG:NextInteger(75,85)
5469 self.InitialAcceleration=RNG:NextInteger(14500,15500);
5470
5471 self.Goal=self.Goal*60;
5472 self.Value=0;
5473 self.TimeStart=tick();
5474 self.gun=gun;
5475
5476 self.item=item;
5477
5478 self.chamber = gun.Chamber;
5479
5480 local weld = gun.Chamber.WeldToReal;
5481 self.StartC0=weld.C0;
5482
5483 self.weld=weld;
5484
5485 SpinningChamberEffects[gun]=self;
5486end
5487
5488local function ApproachValueSmoothly(value, initialAcceleration, t) --decelerates overtime to smoothly approach value
5489 local m, a = value, initialAcceleration
5490
5491 local output = m*(1 - math.exp(-a*t/m))
5492 if value - output < 0.101 then
5493 output = value
5494 end
5495 return output
5496end
5497
5498function SpinningChamberEffect:Update()
5499 local elapsed = (tick()-self.TimeStart);
5500 local value = ApproachValueSmoothly(self.Goal,self.InitialAcceleration,elapsed);
5501
5502 if self.Goal-value <= 60 then
5503 local tween = TweenService:Create(self.weld,TweenInfo.new(0.5),{C0=self.StartC0*CFrame.Angles(0,0,-math.rad(self.Goal))});
5504 tween:Play();
5505 self:Dispose();
5506 else
5507 self.weld.C0=self.StartC0*CFrame.Angles(0,0,-math.rad(value));
5508 end
5509end
5510
5511function SpinningChamberEffect:Dispose()
5512 local item = self.item;
5513 SpinningChamberEffects[self.gun]=nil;
5514
5515 item.ChamberIndex=(item.ChamberIndex-self.Goal/60)%6;
5516 if item.ChamberIndex == 0 then
5517 item.ChamberIndex=6;
5518 end
5519
5520 print("Dispose", item.ChamberIndex)
5521end
5522
5523local function LocalChamberSpinEffect(gun,item)
5524 local chamber = gun:FindFirstChild("Chamber")
5525 if chamber then
5526 chamber.Spin:Play();
5527 SpinningChamberEffect.new(gun,item);
5528 end
5529end
5530local function ChamberSpinEffect(gun)
5531
5532 local Equipped = PlayerCharacter:GetEquippedItem();
5533 if Equipped then
5534 if Equipped.Model == gun then
5535 LocalChamberSpinEffect(gun,Equipped);
5536 end
5537 end
5538
5539end
5540
5541
5542
5543function module:Activate()
5544 if self.IsLoading then
5545 if self.Ammo > 0 then
5546 self:StopTrack("IdleLoad", 0.25)
5547 end
5548 return
5549 elseif self.Ammo <= 0 then
5550 self:Load()
5551 return
5552 end
5553
5554 if not self.IsAiming or self.Ammo <= 0 then return end
5555 if self.IsLoading or self.IsReloading then return end
5556
5557 if not self:HasTrack("Fire") then
5558 warn("Unable to shoot weapon - missing animation track")
5559 return
5560 end
5561
5562
5563
5564
5565
5566 local animTrack = self.IsFanning and "Fan" or "Fire"
5567
5568 -- 1.75 fan speed: lowest
5569 -- highest: 4
5570 local FanSpeed = 4;
5571
5572 --FanSpeed=(1.75+4)/2;
5573
5574 if self.IsFanning then
5575 local fanlen = self:GetTrack(animTrack).Length/FanSpeed;
5576 if self.LastFired and tick()-self.LastFired < fanlen then
5577 return;
5578 end
5579 end
5580
5581
5582 local Firing = true;
5583
5584 local gun = self.Model;
5585
5586
5587 --[=[
5588
5589 Spin Chamber One Rotation
5590
5591
5592 --]=]
5593
5594 local Chamber = gun:FindFirstChild("Chamber");
5595 if Chamber then
5596 local Weld = Chamber:FindFirstChild("WeldToReal");
5597 if Weld then
5598
5599 local reverses = Weld:FindFirstChild("Reverses");
5600
5601 if ChamberTweens[gun] then
5602 ChamberTweens[gun].Tween:Cancel();
5603 Weld.C0=ChamberTweens[gun].C0;
5604 end
5605 local C0Goal = Weld.OriginalC0.Value * CFrame.Angles(0,0,math.rad(self.ChamberIndex*60 * (reverses and -1 or 1)));
5606 local SpinTween = TweenService:Create(Weld,TweenInfo.new(.5),{C0=C0Goal});
5607 SpinTween:Play();
5608 ChamberTweens[gun]={Tween=SpinTween,C0=C0Goal};
5609 end
5610
5611 local bullet = module:GetBulletAtIndex(gun,self.ChamberIndex);
5612
5613 if bullet then
5614 module:CutBulletByIndex(gun,self.ChamberIndex);
5615 else
5616 Firing=nil;
5617 end
5618
5619
5620 self.ChamberIndex=self.ChamberIndex+1;
5621 if self.ChamberIndex == 7 then
5622 self.ChamberIndex=1;
5623 end
5624
5625 end
5626
5627 --
5628
5629 if not Firing then
5630 animTrack="Dry"..animTrack;
5631 end
5632
5633 if Firing then
5634 self.LastFired=tick();
5635
5636 self.IsReloading = true
5637 self.Ammo = self.Ammo - 1
5638
5639 local origin = self.Model.Tip.Position
5640
5641
5642
5643 local projectile = {
5644 char = PlayerCharacter.Character,
5645 origin = origin,
5646 accuracy = self.ProjectileAccuracy * (self.IsFanning and 0.75 or 1),
5647 power = self.ProjectilePower,
5648 ragdollpower_mult = self.RagdollPower,
5649 damage = self.ProjectileDamage
5650 }
5651
5652 local projCount = self.Name == "Mule" and 4 or 1
5653 for i = 1, projCount do
5654 Projectiles.Fire(projectile)
5655 end
5656 end
5657
5658
5659 local recoil = self.BaseRecoil
5660
5661 if self.IsFanning then
5662 recoil = recoil / 2
5663 self:PlayTrack(animTrack, 0, 1, FanSpeed)
5664 else
5665 self:PlayTrack(animTrack, .1, 1, 1)
5666 end
5667
5668 coroutine.wrap(function()
5669 self:Async(wait, .1)
5670 if not self.IsEquipped then return end
5671
5672 if not self.IsFanning then
5673 self:GetTrack(animTrack).Stopped:Wait()
5674 if not self.IsEquipped then return end
5675
5676 local relTrack = "IdleReload"
5677 if self.IsAiming and self:HasTrack("Reload") then
5678 relTrack = "Reload"
5679 end
5680
5681 if self:HasTrack(relTrack) then
5682 self:PlayTrack(relTrack, .1, 1, 1)
5683 self:GetTrack(relTrack).Stopped:Wait()
5684 if not self.IsEquipped then return end
5685 end
5686 end
5687 self.IsReloading = false
5688 end)()
5689
5690 if Firing then
5691 if recoil > 40 then
5692 Camera:Vibrate(math.rad(2), .05, .05)
5693 end
5694
5695 Camera:AddRecoil(recoil)
5696
5697 UI.Fire()
5698 UI.UpdateEquippedItem()
5699 end
5700end
5701
5702function module:Equip()
5703 if self.Sidearm then
5704 if not self.ReadyingSidearm then
5705 self.ReadyingSidearm = true
5706
5707 PlayerCharacter.AnimationHandler:PlayTrack("HolsterReady",.1,1,1);
5708
5709 InputHandler:ToggleAction("PullFromHolster", true)
5710 Holsters:EquipGun(self.Name);
5711
5712 Camera:SetMode("Custom")
5713 return
5714 else
5715 self.ReadyingSidearm = false
5716
5717 PlayerCharacter.AnimationHandler:StopTrack("HolsterReady", .1);
5718 InputHandler:ToggleAction("PullFromHolster", false)
5719 end
5720 end
5721
5722 self.super.Equip(self)
5723
5724 self.CanBeFanned = self:HasTrack("Fan")
5725
5726 InputHandler:ToggleAction("FanGun", self.CanBeFanned)
5727 InputHandler:ToggleAction("ReloadGun", true)
5728
5729 if self:HasTrack("Idle") then
5730 self:PlayTrack("Idle")
5731 self.LastTrack = "Idle"
5732 end
5733
5734 if Utils.AreKeysPressed(KeyBindings.InteractCancel) and self.CanBeFanned then
5735 self.IsFanButtonDown=true;
5736 end
5737
5738 if Utils.AreKeysPressed(KeyBindings.ActivateItemSec) then
5739 self.IsActivatedSecondary = true
5740 self:ActivateSecondary();
5741 end
5742
5743 if Utils.AreKeysPressed(KeyBindings.ActivateItem) then
5744 self.IsActivated = true
5745 self:Activate();
5746 end
5747
5748 if self.Sidearm then
5749 Holsters:SetGunVisible(false);
5750 end
5751
5752 Camera:SetMode("Custom")
5753
5754 PlayerCharacter:FaceMouse(false);
5755end
5756
5757function module:Unequip()
5758 if self.Sidearm then
5759 if self.ReadyingSidearm then
5760 self.ReadyingSidearm = false
5761
5762 PlayerCharacter.AnimationHandler:StopTrack("HolsterReady", .1);
5763 InputHandler:ToggleAction("PullFromHolster", false)
5764 return
5765 end
5766
5767 local Holster = Holsters:GetHolster();
5768
5769 if Holster and Holster.Gun and not Holster.GunVisible then
5770 print("Returning");
5771 PlayerCharacter.AnimationHandler:PlayTrack("HolsterReturn",.1,1,2);
5772 end
5773 end
5774
5775 self.super.Unequip(self)
5776
5777 PlayerCharacter:FaceMouse(true);
5778
5779 InputHandler:ToggleAction("FanGun", false)
5780 InputHandler:ToggleAction("ReloadGun", false)
5781
5782 self.IsLoading = false
5783 self.IsReloading = false
5784 self.IsFanButtonDown = false
5785end
5786
5787function module:Update()
5788
5789 local ControllingAnimals = WildLife:GetControllingAnimals();
5790 self.IsAiming = self.IsAimButtonDown
5791 and not self.IsLoading
5792 and (not PlayerCharacter.IsSprinting or (#ControllingAnimals>0))
5793 and not shared.RadialMenuOpen
5794
5795
5796
5797 if self.CanBeFanned then
5798 self.IsFanning = self.IsFanButtonDown
5799 and not self.IsLoading
5800 and not shared.RadialMenuOpen
5801 end
5802
5803 local animTrack = self:HasTrack("Idle") and "Idle" or nil
5804
5805 if self.IsAiming then
5806 if self.IsFanning and self:HasTrack("FanHold") then
5807 animTrack = "FanHold"
5808 elseif self:HasTrack("Aim") then
5809 animTrack = "Aim"
5810 end
5811 animTrack = self.IsFanning and "FanHold" or "Aim"
5812 end
5813
5814 local lastTrack = self.LastTrack
5815 if animTrack ~= lastTrack and not self.IsLoading and not self.IsReloading then
5816 self.LastTrack = animTrack
5817
5818 if lastTrack then
5819 self:StopTrack(lastTrack, 0.15)
5820 end
5821
5822 if animTrack then
5823 self:PlayTrack(animTrack, 0.15)
5824 end
5825 end
5826end
5827
5828
5829function GetGun(rig)
5830 local equippedItem
5831
5832 if rig == PlayerCharacter.Character then
5833 equippedItem = PlayerCharacter:GetEquippedItem().Name
5834 else
5835 local stateInfo = rig:FindFirstChild("StateInfo")
5836 equippedItem = stateInfo and stateInfo:FindFirstChild("EquippedItem") and stateInfo.EquippedItem.Value
5837 end
5838
5839 return equippedItem and rig:FindFirstChild(equippedItem) or nil
5840end
5841
5842
5843local function GunFireDry(handler,track)
5844 local gun = GetGun(handler.Rig)
5845 if not gun then return warn("[GunItem.AnimHandler.GunFire] No Gun") end
5846
5847 local tip = gun:FindFirstChild("Tip")
5848 if not tip then return warn("[GunItem.AnimHandler.GunFire] No Tip in", gun:GetFullName()) end
5849
5850
5851
5852 local fireSound = tip:FindFirstChild("DryFire");
5853
5854 if fireSound then
5855 fireSound = fireSound:clone()
5856 fireSound.Parent = tip
5857 fireSound.Pitch = fireSound.Pitch + math.random(97,103) / 1000
5858
5859 fireSound.Stopped:Connect(function()
5860 fireSound:Destroy()
5861 end)
5862
5863 print("Fire sound");
5864
5865 fireSound:Play()
5866 else
5867 warn("[GunItem.AnimHandler.GunFire] No Fire in", gun:GetFullName())
5868 end
5869end
5870
5871
5872
5873local function GunFire(handler,track)
5874
5875 local gun = GetGun(handler.Rig)
5876 if not gun then return warn("[GunItem.AnimHandler.GunFire] No Gun") end
5877
5878 local tip = gun:FindFirstChild("Tip")
5879 if not tip then return warn("[GunItem.AnimHandler.GunFire] No Tip in", gun:GetFullName()) end
5880
5881
5882
5883 local fireSound = tip:FindFirstChild("Fire");
5884
5885 if fireSound then
5886 fireSound = fireSound:clone()
5887 fireSound.Parent = tip
5888 fireSound.Pitch = fireSound.Pitch + math.random(97,103) / 1000
5889
5890 fireSound.Stopped:Connect(function()
5891 fireSound:Destroy()
5892 end)
5893
5894 print("Fire sound");
5895
5896 fireSound:Play()
5897 else
5898 warn("[GunItem.AnimHandler.GunFire] No Fire in", gun:GetFullName())
5899 end
5900
5901 local smoke = tip:FindFirstChild("Smoke")
5902 if smoke then
5903 smoke:Emit(25)
5904 else
5905 warn("[GunItem.AnimHandler.GunFire] No Smoke in", gun:GetFullName())
5906 end
5907
5908 VFX.WeaponEffect(gun)
5909end
5910
5911
5912
5913
5914for _,v in pairs(ReplicatedStorage.Resources.Animations.Player:GetDescendants()) do
5915 if (v:isA("Animation")) and v.Name:match("Fire") or (v.Name:match("Fan") and not v.Name:match("Hold")) then
5916 if v.Name:match("Dry") then
5917 AnimationHandler:BindToStart(v.Name,GunFireDry);
5918 else
5919 AnimationHandler:BindToStart(v.Name,GunFire);
5920 end
5921 end
5922end
5923
5924
5925function module.UpdateEffects()
5926 for _,v in pairs(SpinningChamberEffects) do
5927 v:Update();
5928 end
5929end
5930
5931
5932
5933AnimationHandler:BindToKeyframe({
5934 PullFromHolster = function(self)
5935 print("Pull from holster")
5936
5937 if self.Owner then
5938 local item = PlayerCharacter:GetEquippedItem()
5939
5940 if item.Sidearm and item.ReadyingSidearm then
5941 self:StopTrack("HolsterPull",0.1);
5942 item:Equip()
5943
5944 PlayerCharacter:PlayCharacterSound("HolsterDraw"..math.random(1,4));
5945 end
5946 end
5947 end,
5948
5949 HolsterReturn=function(self)
5950
5951 print("Return from holster")
5952
5953 if self.Owner then
5954 Holsters:SetGunVisible(true);
5955 PlayerCharacter:PlayCharacterSound("HolsterReturn"..math.random(1,3));
5956 end
5957 end,
5958 GrabRifleBullet = function(self)
5959 local gun = GetGun(self.Rig)
5960 if not gun then return end
5961
5962 local bullet = Resources.RifleBullet:Clone()
5963 bullet.Name = "Bullet"
5964 bullet.Parent = gun
5965
5966 local bottom = bullet:FindFirstChild("RifleBulletBottom")
5967 local righthand = self.Rig:FindFirstChild("RightHand")
5968
5969 if bottom and righthand then
5970 local weld = Instance.new("Motor6D")
5971 weld.Parent = righthand
5972 weld.Part0 = righthand
5973 weld.Part1 = bottom
5974 weld.Name = "WeldToBullet"
5975
5976 local weldvalue = Instance.new("ObjectValue")
5977 weldvalue.Name = "WeldValue"
5978 weldvalue.Value = weld
5979 weldvalue.Parent = gun
5980 end
5981 end,
5982
5983 RevolverCock = function(self)
5984 local gun = GetGun(self.Rig)
5985 if not gun then return end
5986
5987 local hammer = gun:FindFirstChild("Hammer")
5988 if hammer then
5989 hammer.Reload:Play()
5990 end
5991 end,
5992 RevolverBarrelOpen = function(self)
5993 local gun = GetGun(self.Rig);
5994 if not gun then return end
5995
5996 local barrel = gun:FindFirstChild("Barrel");
5997 if barrel then
5998 barrel.Open:Play();
5999 end
6000
6001 if self.Owner then
6002 Camera:Lurch(Vector3.new(-0.25,0,0),0.25,0.15);
6003 end
6004
6005 end,
6006 RevolverBarrelEjectShells = function(self)
6007 local gun = GetGun(self.Rig);
6008 if not gun then return end
6009
6010 for i = 1,6 do
6011 local foundbullet = module:GetBulletAtIndex(gun,i);
6012 if foundbullet then
6013 if not foundbullet:FindFirstChild("End") then
6014 module:DropShell(gun,i,true);
6015 end
6016 end
6017 end
6018 self.ChamberIndex=1;
6019 end,
6020
6021 RevolverBarrelClose = function(self)
6022 local gun = GetGun(self.Rig);
6023 if not gun then return end
6024
6025 local barrel = gun:FindFirstChild("Barrel");
6026 if barrel then
6027 barrel.Close:Play();
6028 end
6029
6030 if self.Owner then
6031 Camera:Lurch(Vector3.new(0.25,0,0),0.25,0.15);
6032 end
6033
6034 end,
6035 RevolverSpin = function(self)
6036 local gun = GetGun(self.Rig)
6037 if not gun then return end
6038
6039 local Owner = self.Owner;
6040
6041 if Owner then
6042 ChamberSpinEffect(gun);
6043
6044 ChamberReloadIndex[gun]=nil;
6045
6046 ChamberTweens[gun]=nil;
6047 end
6048
6049 end,
6050 RevolverDropShells = function(self)
6051 local gun = GetGun(self.Rig);
6052 if gun then
6053 local chamber = gun:FindFirstChild("Chamber");
6054 if chamber then
6055 chamber.ShellSlide:Play();
6056 end
6057 for i = 1,6 do
6058 local foundbullet = module:GetBulletAtIndex(gun,i);
6059 if foundbullet then
6060 if not foundbullet:FindFirstChild("End") then
6061 module:DropShell(gun,i);
6062 end
6063 end
6064 end
6065 end
6066 end,
6067 RevolverChamber = function(self)
6068 local gun = GetGun(self.Rig)
6069 if not gun then return end
6070
6071 local chamber = gun:FindFirstChild("Chamber")
6072 if chamber then
6073 chamber.Open:Play()
6074 end
6075 end,
6076 RevolverChamberClose = function(self)
6077 local gun = GetGun(self.Rig)
6078 if not gun then return end
6079
6080 if self.Owner then
6081 local chamber = gun:FindFirstChild("Chamber")
6082 if chamber then
6083 chamber.Close:Play()
6084 Camera:Lurch(Vector3.new(0,0,-0.25),0.25,0.15);
6085
6086 end
6087 end
6088 end,
6089 RevolverInsert = function(self, _, track)
6090 local gun = GetGun(self.Rig)
6091 if not gun then return end
6092
6093
6094 local chamber = gun:FindFirstChild("Chamber")
6095 if chamber then
6096
6097 local ReloadIndex = ChamberReloadIndex[gun];
6098 local i = 0;
6099 if ReloadIndex then
6100 while true do
6101 ReloadIndex = ReloadIndex+1;
6102 i=i+1;
6103 if ReloadIndex == 7 then
6104 ReloadIndex=1;
6105 end
6106
6107 if not module:GetBulletAtIndex(gun,ReloadIndex) or i == 6 then
6108 break;
6109 end
6110 end
6111 else
6112 for i = 1,6 do
6113 local bullet = module:GetBulletAtIndex(gun,i);
6114 if not bullet or i == 6 then
6115 print("Insert start: ",i);
6116 ReloadIndex=i;
6117 break;
6118 end
6119 end
6120 end
6121
6122
6123
6124 ChamberReloadIndex[gun]=ReloadIndex;
6125
6126
6127 local bullet = module:InsertBulletToChamber(gun,ReloadIndex);
6128
6129
6130
6131 local insert = chamber:FindFirstChild("Insert"):Clone()
6132 insert.Parent = chamber
6133 insert.Pitch = math.random(98, 102) / 100
6134 insert:Play()
6135 insert.Stopped:Connect(function()
6136 insert:Destroy()
6137 end)
6138
6139 if self.Owner then
6140 local item = PlayerCharacter:GetEquippedItem()
6141 if item and item.Ammo then
6142 if item.Ammo < item.MaxAmmo then
6143 item.Ammo = item.Ammo + 1
6144
6145 if UI.UpdateEquippedItem then
6146 UI.UpdateEquippedItem()
6147 end
6148 end
6149
6150 if item.Ammo >= item.MaxAmmo then
6151 self:StopTrack(track, 0.1)
6152 end
6153 end
6154 end
6155 end
6156 end,
6157 Load = function(self, _, track)
6158 local gun = GetGun(self.Rig)
6159 if not gun then return end
6160
6161 local bullet = gun:FindFirstChild("Bullet")
6162
6163 if bullet then
6164 local val = bullet:FindFirstChild("WeldValue")
6165 if val then
6166 val.Value:Destroy()
6167 end
6168 bullet:Destroy()
6169 end
6170
6171 local handle = gun:FindFirstChild("HandleReference")
6172 if handle then
6173 handle = handle.Value
6174
6175 local insert = handle:FindFirstChild("Insert"):Clone()
6176 insert.Parent = handle
6177 insert.Pitch = math.random(98, 102) / 100
6178 insert:Play()
6179 insert.Stopped:Connect(function()
6180 insert:Destroy()
6181 end)
6182
6183 if self.Owner then
6184 local item = PlayerCharacter:GetEquippedItem()
6185 if item and item.Ammo then
6186 if item.Ammo < item.MaxAmmo then
6187 item.Ammo = item.Ammo + 1
6188
6189 if UI.UpdateEquippedItem then
6190 UI.UpdateEquippedItem()
6191 end
6192 end
6193
6194 if item.Ammo >= item.MaxAmmo then
6195 self:StopTrack(track, 0.1)
6196 end
6197 end
6198 end
6199 end
6200 end,
6201
6202 [{"ChamberOpen", "OpenChamber"}] = function(self)
6203 local gun = GetGun(self.Rig)
6204 if not gun then return end
6205
6206 local ChamberOpen = gun:FindFirstChild("ChamberOpen", true)
6207 if ChamberOpen then
6208 ChamberOpen:Play()
6209 end
6210
6211 local hole = gun:FindFirstChild("EjectHole")
6212 if hole then
6213 local casing = Resources.ShellCasing:Clone()
6214 casing.Parent = Ignore
6215 casing.CFrame = hole.CFrame * hole.ShellAttachment.CFrame
6216 casing.Velocity = (hole.CFrame.rightVector + Vector3.new(-.5, 3, 0)) * 8
6217 casing.RotVelocity = Vector3.new(0, math.random(-360, 360), 0)
6218
6219 delay(5, function() casing:Destroy() end)
6220 end
6221 end,
6222
6223 [{"ChamberClose", "CloseChamber"}] = function(self)
6224 local gun = GetGun(self.Rig)
6225 if not gun then return end
6226
6227 local ChamberClose = gun:FindFirstChild("ChamberClose", true)
6228 if ChamberClose then
6229 ChamberClose:Play()
6230 end
6231 end
6232})
6233
6234
6235return module
6236
6237--[[
6238 Pickaxe
6239 Base class for all pickaxe items
6240
6241 Pickaxe extends BaseItem {
6242 }
6243--]]
6244
6245
6246
6247-- Services
6248
6249local ReplicatedStorage = game:GetService("ReplicatedStorage")
6250local CollectionService = game:GetService("CollectionService");
6251
6252
6253-- Modules
6254
6255local LoadModule = require(ReplicatedStorage.Modules.Load)
6256local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
6257
6258local SharedUtils = LoadSharedModule("SharedUtils");
6259
6260local Utils = LoadModule("Utils");
6261local KeyBindings = LoadModule("KeyBindings");
6262local Holsters = LoadModule("Holsters");
6263
6264local AnimationHandler = LoadModule("AnimationHandler")
6265local PlayerCharacter = LoadModule("PlayerCharacter", true)
6266local InputHandler = LoadModule("InputHandler", true)
6267local Projectiles = LoadModule("Projectiles", true)
6268local Ragdolls = LoadModule("Ragdolls", true)
6269local Camera = LoadModule("Camera", true)
6270local FX = LoadModule("FX", true)
6271local UI = LoadModule("UI", true)
6272local Cursor = LoadModule("Cursor");
6273local BaseItem = LoadModule("BaseItem")
6274
6275local Mining = LoadModule("Mining");
6276
6277
6278local SharedData = LoadSharedModule("SharedData")
6279local Network = LoadSharedModule("Network")
6280
6281
6282-- Variables
6283
6284local Resources = ReplicatedStorage.Resources
6285local Ignore = workspace.Ignore
6286
6287local module = {}
6288setmetatable(module, { __index = BaseItem })
6289
6290
6291
6292
6293function module.new(name)
6294 local self = BaseItem.new(name)
6295 setmetatable(self, { __index = module })
6296
6297 local baseModel = self.BaseModel
6298
6299 local itemData = SharedData.PlayerItems[self.Name]
6300
6301 return self
6302end
6303
6304
6305
6306function module:ActivateSecondary()
6307 self.IsAimButtonDown = true
6308end
6309
6310function module:DeactivateSecondary()
6311
6312 self.IsAimButtonDown = false
6313end
6314
6315function module:Activate()
6316end
6317
6318
6319function module:Hit(hit,pos,norm)
6320 if self.Swinging and not self.HitDebounce then
6321 local parent = hit.Parent;
6322 if parent then
6323 local deposit = SharedUtils.GetDeposit(parent);
6324 if deposit then
6325 self.HitDebounce=true;
6326
6327 print("Hit: ",deposit);
6328
6329 Mining:HitDeposit(parent,pos,norm);
6330 end
6331 end
6332 end
6333end
6334
6335function module:Equip()
6336 self.super.Equip(self)
6337
6338 if self:HasTrack("Idle") then
6339 self:PlayTrack("Idle")
6340 self.LastTrack = "Idle"
6341 end
6342
6343 local top = self.Model:WaitForChild("Top");
6344 self.Top=top;
6345 self.LastPosition=top.Attachment.WorldPosition;
6346
6347end
6348
6349function module:Unequip()
6350 self.super.Unequip(self)
6351 self.HitDebounce=nil;
6352 Cursor:SetCursorType("Free");
6353end
6354
6355local NewRay = Ray.new;
6356
6357function module:Update()
6358
6359
6360
6361 --[=[
6362
6363 Swing
6364
6365 --]=]
6366
6367 if self.IsActivated then
6368 if self:HasTrack("Swing") then
6369 if not self.Swinging then
6370 self.Swinging=true;
6371
6372 self.HitDebounce=nil;
6373
6374 self:PlayTrack("Swing",.1,1,1.5);
6375
6376 local track = self:GetTrack("Swing");
6377
6378 local stopped;
6379 stopped = track.Stopped:connect(function()
6380 stopped:disconnect();
6381 self.Swinging=nil;
6382 end)
6383 end
6384 end
6385 end
6386
6387
6388 local hitpos,mousehit = Utils.GetMouseHit();
6389
6390 Cursor:SetCursorType();
6391
6392 if mousehit then
6393 local parent = mousehit.Parent;
6394 if parent then
6395 if SharedUtils.GetDeposit(parent) then
6396 Cursor:SetCursorType("Image");
6397 Cursor:SetCursorImage("Pickaxe");
6398 end
6399 end
6400 end
6401
6402 local Top = self.Top;
6403 if Top then
6404
6405 local topp = Top.Attachment.WorldPosition;
6406 if self.Swinging then
6407 if self.LastPosition and not self.HitDebounce then
6408
6409 local dir = topp-self.LastPosition;
6410 local ray = NewRay(self.LastPosition,dir*1.5);
6411 local hit,pos,norm = workspace:FindPartOnRayWithIgnoreList(ray,{Ignore,self.Model,PlayerCharacter.Character});
6412 if hit then
6413 self:Hit(hit,pos,norm);
6414 end
6415 end
6416 end
6417 self.LastPosition=topp;
6418 end
6419
6420 self.LastSwinging=self.Swinging;
6421end
6422
6423local function GetAxe(rig)
6424 for _,v in pairs(rig:GetChildren()) do
6425 if v:isA("Model") and v.Name:match("Pickaxe") then
6426 return v;
6427 end
6428 end
6429end
6430
6431
6432AnimationHandler:BindToKeyframe({
6433 PickaxeSwing=function(self)
6434 print(self);
6435 local axe = GetAxe(self.Rig);
6436 if axe then
6437 local handle = axe.PrimaryPart;
6438 if handle then
6439 local sound = handle:FindFirstChild("Woosh"..math.random(1,4));
6440 if sound then
6441 sound:Play();
6442 end
6443 end
6444 end
6445 end
6446})
6447
6448
6449return module
6450
6451--[[
6452 Tier1Pickaxe
6453 Handles all logic for the Tier1Pickaxe
6454
6455 class Tier1Pickaxe extends Pickaxe {}
6456--]]
6457
6458-- Services
6459
6460local ReplicatedStorage = game:GetService("ReplicatedStorage")
6461
6462-- Modules
6463
6464local LoadModule = require(ReplicatedStorage.Modules.Load)
6465local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
6466
6467local Pickaxe = LoadModule("Pickaxe")
6468
6469-- Variables
6470
6471local module = Pickaxe.new("Tier1Pickaxe")
6472
6473return module
6474
6475--[[
6476 Tier2Pickaxe
6477 Handles all logic for the Tier2Pickaxe
6478
6479 class Tier2Pickaxe extends Pickaxe {}
6480--]]
6481
6482-- Services
6483
6484local ReplicatedStorage = game:GetService("ReplicatedStorage")
6485
6486-- Modules
6487
6488local LoadModule = require(ReplicatedStorage.Modules.Load)
6489local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
6490
6491local Pickaxe = LoadModule("Pickaxe")
6492
6493-- Variables
6494
6495local module = Pickaxe.new("Tier2Pickaxe")
6496
6497return module
6498
6499--[[
6500 Tier3Pickaxe
6501 Handles all logic for the Tier3Pickaxe
6502
6503 class Tier3Pickaxe extends Pickaxe {}
6504--]]
6505
6506-- Services
6507
6508local ReplicatedStorage = game:GetService("ReplicatedStorage")
6509
6510-- Modules
6511
6512local LoadModule = require(ReplicatedStorage.Modules.Load)
6513local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
6514
6515local Pickaxe = LoadModule("Pickaxe")
6516
6517-- Variables
6518
6519local module = Pickaxe.new("Tier3Pickaxe")
6520
6521return module
6522
6523--[[
6524 Tier4Pickaxe
6525 Handles all logic for the Tier4Pickaxe
6526
6527 class Tier4Pickaxe extends Pickaxe {}
6528--]]
6529
6530-- Services
6531
6532local ReplicatedStorage = game:GetService("ReplicatedStorage")
6533
6534-- Modules
6535
6536local LoadModule = require(ReplicatedStorage.Modules.Load)
6537local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
6538
6539local Pickaxe = LoadModule("Pickaxe")
6540
6541-- Variables
6542
6543local module = Pickaxe.new("Tier4Pickaxe")
6544
6545return module
6546
6547--[[
6548 Tier1Pickaxe
6549 Handles all logic for the Tier5Pickaxe
6550
6551 class Tier5Pickaxe extends Pickaxe {}
6552--]]
6553
6554-- Services
6555
6556local ReplicatedStorage = game:GetService("ReplicatedStorage")
6557
6558-- Modules
6559
6560local LoadModule = require(ReplicatedStorage.Modules.Load)
6561local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
6562
6563local Pickaxe = LoadModule("Pickaxe")
6564
6565-- Variables
6566
6567local module = Pickaxe.new("Tier5Pickaxe")
6568
6569return module
6570
6571--[[
6572 Tier6Pickaxe
6573 Handles all logic for the Tier6Pickaxe
6574
6575 class Tier6Pickaxe extends Pickaxe {}
6576--]]
6577
6578-- Services
6579
6580local ReplicatedStorage = game:GetService("ReplicatedStorage")
6581
6582-- Modules
6583
6584local LoadModule = require(ReplicatedStorage.Modules.Load)
6585local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
6586
6587local Pickaxe = LoadModule("Pickaxe")
6588
6589-- Variables
6590
6591local module = Pickaxe.new("Tier6Pickaxe")
6592
6593return module
6594
6595local module = {}
6596
6597-- Module that handles IK(Matt's)
6598
6599local ReplicatedStorage = game:GetService("ReplicatedStorage");
6600
6601
6602local LoadModule = require(ReplicatedStorage.Modules.Load)
6603
6604local AnimationHandler = LoadModule("AnimationHandler", true)
6605local PlayerCharacter = LoadModule("PlayerCharacter", true)
6606local Camera = LoadModule("Camera")
6607local Mathf = LoadModule("Mathf")
6608
6609
6610
6611
6612
6613local Joints = {}
6614local Rigs = {}
6615
6616
6617function AddIKJoint(hipJoint,kneeJoint,footJoint,footHeight,directionMult,width,ignore)
6618 table.insert(Joints ,{
6619 framerate = 60,
6620 lastUpdate = tick(),
6621 hipjoint = hipJoint,
6622 hip = {hipJoint, hipJoint.C0, hipJoint.C1},
6623 knee = {kneeJoint, kneeJoint.C0, kneeJoint.C1},
6624 foot = {footJoint, footJoint.C0, footJoint.C1},
6625 curHeight = 1,
6626 width = width,
6627 lastFootPos = Vector3.new(),
6628 footHeight = footHeight,
6629 directionMult = directionMult,
6630 ignore = ignore
6631 })
6632end
6633
6634module.AddIKJoint=AddIKJoint;
6635
6636local newray = Ray.new;
6637
6638local Ignore = workspace.Ignore
6639local weldinfo = ReplicatedStorage.Resources.WeldInfo
6640
6641local function Transparent(x)
6642 return x and x:isA("BasePart") and x.Transparency > 0;
6643end
6644
6645function LimbIK(JointList)
6646 local hip = JointList.hip
6647 local knee = JointList.knee
6648 local foot = JointList.foot
6649
6650 local root = hip[1].Part0
6651
6652 if root then
6653 local char = root.Parent;
6654 if char then
6655 local stateinfo = char:FindFirstChild("StateInfo")
6656
6657 if stateinfo or char:FindFirstChild("Rider") then
6658 local ut = tick()-JointList.lastUpdate
6659 JointList.lastUpdate = tick()
6660
6661 local hipCF = root.CFrame*hip[2]
6662 local kneeCF = hipCF*hip[1].Transform*(hip[3]:inverse())*knee[2]
6663 local footCF = kneeCF*knee[1].Transform*(knee[3]:inverse())*foot[2]
6664 local stepCF = footCF*CFrame.new(0,-JointList.footHeight,0)
6665
6666 local topLength = (hipCF.p - kneeCF.p).magnitude
6667 local bottomLength = (kneeCF.p - footCF.p).magnitude
6668 local direction = CFrame.new(hipCF.p,stepCF.p)
6669
6670 local totalLength = topLength + bottomLength
6671
6672 local dirPos = direction + direction.lookVector*(topLength+bottomLength)*2
6673
6674 local hPos1 = direction*Vector3.new(0,JointList.width/2,0)
6675 local rPos = dirPos*Vector3.new(0,JointList.width/2,0)
6676 local r1 = newray(hPos1,(rPos-hPos1))
6677 local h1,p1 = workspace:FindPartOnRayWithIgnoreList(r1,JointList.ignore,false,true)
6678
6679
6680 local hPos2 = direction*Vector3.new(0,-JointList.width/2,0)
6681 rPos = dirPos*Vector3.new(0,-JointList.width/2,0)
6682 local r2 = Ray.new(hPos2,(rPos-hPos2))
6683 local h2,p2 = workspace:FindPartOnRayWithIgnoreList(r2,JointList.ignore,false,true)
6684
6685 local hPos3 = direction*Vector3.new(JointList.width/2,0,0)
6686 rPos = dirPos*Vector3.new(JointList.width/2,0,0)
6687 local r3 = Ray.new(hPos3,(rPos-hPos3))
6688 local h3,p3 = workspace:FindPartOnRayWithIgnoreList(r3,JointList.ignore,false,true)
6689
6690 local hPos4 = direction*Vector3.new(-JointList.width/2,0,0)
6691 rPos = dirPos*Vector3.new(-JointList.width/2,0,0)
6692 local r4 = Ray.new(hPos4,(rPos-hPos4))
6693 local h4,p4 = workspace:FindPartOnRayWithIgnoreList(r4,JointList.ignore,false,true)
6694
6695 if Transparent(h1) then
6696 p1=Vector3.new();
6697 end
6698 if Transparent(h2) then
6699 p2=Vector3.new();
6700 end
6701 if Transparent(h3) then
6702 p3=Vector3.new();
6703 end
6704 if Transparent(h4) then
6705 p4=Vector3.new();
6706 end
6707
6708 local dist1 = (hPos1 - p1).magnitude
6709 local dist2 = (hPos2 - p2).magnitude
6710 local dist3 = (hPos3 - p3).magnitude
6711 local dist4 = (hPos4 - p4).magnitude
6712
6713 local dist = math.min(dist1,dist2,dist3,dist4)
6714
6715 JointList.curHeight = Mathf.LerpTowards(Mathf.Lerp(JointList.curHeight,dist,ut/0.2),dist,ut)
6716 local cf, topAngle, bottomAngle = Mathf.IK(Vector3.new(), Vector3.new(0,0,-JointList.curHeight), topLength,bottomLength)
6717
6718
6719 local ItemModify = CFrame.new()
6720
6721 if stateinfo then
6722 local animHandler = AnimationHandler:GetHandler(char)
6723
6724 if animHandler and animHandler.ItemRotate then -- Modify welds if aiming
6725 local itemfolder = weldinfo:FindFirstChild(stateinfo.EquippedItem.Value)
6726
6727 if itemfolder then
6728 local subfolder = itemfolder:FindFirstChild("Default")
6729
6730 if stateinfo.OnAnimal.Value then
6731 subfolder = itemfolder:FindFirstChild("OnAnimal");
6732 elseif stateinfo.Seated.Value then
6733 subfolder = itemfolder:FindFirstChild("Seated");
6734 end
6735
6736 if subfolder then
6737 local jointFolder = subfolder:FindFirstChild(hip[1].Name)
6738 if jointFolder then
6739 local angle = jointFolder.Angle.Value
6740 local pos = jointFolder.Pos.Value
6741
6742 ItemModify = CFrame.Angles(math.rad(angle.X), math.rad(angle.Y), math.rad(angle.Z)) * CFrame.new(pos)
6743 end
6744 end
6745 end
6746 end
6747 end
6748
6749 if stateinfo and (stateinfo.OnAnimal.Value or stateinfo.Dead.Value or stateinfo.Seated.Value or stateinfo.Ragdolled.Value or stateinfo.TiedUp.Value) then
6750 hip[1].C0 = hip[2] * ItemModify
6751 knee[1].C0 = knee[2] * ItemModify
6752 else
6753 local modhip = -topAngle * JointList.directionMult
6754 local modknee = -bottomAngle * JointList.directionMult
6755
6756 local axis = "x" --Workspace.axis.Value;
6757
6758 if axis == "x" then
6759 hip[1].C0 = hip[2] * CFrame.Angles(modhip, 0, 0) * ItemModify
6760 knee[1].C0 = knee[2] * CFrame.Angles(modknee, 0, 0)
6761 elseif axis == "y" then
6762 hip[1].C0 = hip[2] * CFrame.Angles(0, modhip, 0) * ItemModify
6763 knee[1].C0 = knee[2] * CFrame.Angles(0, modknee, 0)
6764 elseif axis == "z" then
6765 hip[1].C0 = hip[2] * CFrame.Angles(0, 0, modhip) * ItemModify
6766 knee[1].C0 = knee[2] * CFrame.Angles(0, 0, modknee)
6767 end
6768
6769 end
6770
6771 if char == PlayerCharacter.Character and (Camera:IsFirstPerson() and not PlayerCharacter:GetSeated()) then
6772 hip[1].C0 = hip[1].C0 * CFrame.new(0, 0, 1.5)
6773 end
6774
6775 local fpos = workspace.CurrentCamera.CFrame:pointToObjectSpace(footCF.p)
6776 local camDist = fpos.magnitude
6777 JointList.framerate = fpos.z > 5 and 1 or camDist > 200 and 5 or camDist > 100 and 10 or camDist > 50 and 20 or camDist > 25 and 30 or 60
6778 end
6779 end
6780 end
6781end
6782
6783
6784module.Update = function()
6785 for i,v in ipairs(Joints) do
6786 if (tick()-v.lastUpdate >= 1/v.framerate) then
6787 if not v.hipjoint or (v.hipjoint and not v.hipjoint.Parent) then
6788 Joints[i]=nil;
6789 else
6790 LimbIK(v)
6791 end
6792 end
6793 end
6794end
6795
6796
6797
6798return module
6799
6800
6801
6802local module = {};
6803
6804local ReplicatedStorage = game:GetService("ReplicatedStorage");
6805
6806local LoadModule = require(ReplicatedStorage:WaitForChild("Modules").Load);
6807local Mathf = LoadModule("Mathf");
6808local Camera = workspace.CurrentCamera
6809
6810
6811local BodyTiltObject = {};
6812local BodyTiltObjects = {};
6813
6814
6815function BodyTiltObject.new(rootjoint,info)
6816 local self = setmetatable({},{__index=BodyTiltObject});
6817
6818 rootjoint.AncestryChanged:connect(function(_,parent)
6819 if not parent then
6820 BodyTiltObjects[rootjoint]=nil;
6821 end
6822 end)
6823
6824 self.root=rootjoint;
6825 self.curAngle=0;
6826 self.goalAngle=0;
6827 self.part=rootjoint.Part0;
6828 self.c0=rootjoint.C0;
6829 self.c1=rootjoint.C1;
6830
6831 self:UpdateParameters(info);
6832
6833 self.framerate=60;
6834 self.lastUpdate=tick();
6835
6836 BodyTiltObjects[rootjoint]=self;
6837end
6838function BodyTiltObject:UpdateParameters(info)
6839 self.BodyTiltAxis = info.BodyTiltAxis or "Z";
6840 self.transRate=info.transition;
6841 self.goalTransRate=info.goalTransition;
6842 self.mult=info.mult;
6843 self.angle=math.rad(info.angle);
6844 self.sprint_velocity=info.sprintvelocity;
6845end
6846function BodyTiltObject:Update()
6847 local ut = tick()-self.lastUpdate
6848 self.lastUpdate = tick()
6849
6850 local av = self.part.RotVelocity.y
6851
6852 local rootjoint = self.root;
6853 if rootjoint then
6854
6855 local rootpart = rootjoint.Part0;
6856 if rootpart then
6857
6858 local rig = rootpart.Parent;
6859
6860 if rig then
6861 local maxAngle = self.angle;
6862
6863 local mult = self.mult;
6864
6865 local forwardvelocity = (rootpart.Velocity*Vector3.new(1,0,1)).magnitude;
6866
6867 if forwardvelocity < 5 then
6868 mult=0;
6869 else
6870 mult=Mathf.Lerp(mult/4,mult,Mathf.PercentBetween(forwardvelocity,5,self.sprint_velocity));
6871 end
6872
6873
6874 --mult -0.5
6875
6876
6877 local tilt = Mathf.Clamp(av*mult,-maxAngle,maxAngle);
6878
6879
6880 local char_states = rig:FindFirstChild("StateInfo");
6881
6882 local goalTransRate = self.goalTransRate;
6883 local transRate = self.transRate;
6884
6885 self.goalAngle = Mathf.Lerp(self.goalAngle,tilt,Mathf.Clamp(ut/goalTransRate,0,1))
6886 self.curAngle = Mathf.Lerp(self.curAngle,self.goalAngle,Mathf.Clamp(ut/transRate,0,1))
6887
6888 local rootcf;
6889 local axis = self.BodyTiltAxis;
6890 if axis == "X" then
6891 rootcf = CFrame.Angles(self.curAngle,0,0);
6892 elseif axis == "Y" then
6893 rootcf = CFrame.Angles(0,self.curAngle,0);
6894 elseif axis == "Z" then
6895 rootcf = CFrame.Angles(0,0,self.curAngle);
6896 end
6897
6898 local rootangle = self.c0*rootcf;
6899
6900 if char_states then -- If the rig is a player
6901 if char_states.OnAnimal.Value or char_states.Dead.Value or char_states.Seated.Value or char_states.Ragdolled.Value then -- If the player is on a horse, don't tilt
6902 rootangle=self.c0;
6903 end
6904 end
6905
6906
6907 self.root.C0=rootangle;
6908
6909
6910 local fpos = Camera.CFrame:pointToObjectSpace(self.part.Position)
6911 local camDist = fpos.magnitude
6912 self.framerate = fpos.z > 5 and 1 or camDist > 200 and 5 or camDist > 100 and 10 or camDist > 50 and 20 or camDist > 25 and 30 or 60
6913 end
6914 end
6915 end
6916end
6917
6918
6919
6920function module:AddRoot(root,info)
6921 BodyTiltObject.new(root,info);
6922end
6923function module:ChangeParameters(root,info)
6924 local obj = BodyTiltObjects[root];
6925 if obj then
6926 obj:UpdateParameters(info);
6927 end
6928end
6929
6930
6931
6932
6933
6934function module.Update()
6935 for root,obj in pairs(BodyTiltObjects) do
6936 if (tick()-obj.lastUpdate >= 1/obj.framerate) then
6937 obj:Update();
6938 end
6939 end
6940end
6941
6942
6943return module;
6944
6945
6946--[[
6947 AnimationHandler
6948 Handles... Animations?
6949
6950 class Module {
6951 AnimationHandler Module.new(Model rig)
6952 Creates a new animationhandler for rig if one has not already been created
6953
6954 AnimationHandler Module:GetHandler(Model rig)
6955 Returns the animationhandler for this rig if one exists
6956
6957 void Module:BindToKeyframe(string name, function handler)
6958 void Module:BindToKeyframe(string[] names, function handler)
6959 void Module:BindToKeyframe({ (string name) = (function handler), (string[] names) = (function handler), ...})
6960 Binds a function to a keyframe. If an animationhandler reaches a keyframe with given
6961 name. function<AnimationHandler self, string keyframe, AnimationTrack track> handler
6962 }
6963
6964 class AnimationHandler {
6965 Model AnimationHandler.Rig
6966 string AnimationHandler.RigType
6967 Instance<AnimationController,Humanoid> AnimationHandler.AnimationController
6968 bool AnimationHandler.Owner
6969
6970 AnimationTrack AnimationHandler:GetTrack(string track)
6971 AnimationTrack AnimationHandler:PlayTrack(string track[, number fadetime, number weight, number speed])
6972 AnimationTrack AnimationHandler:StopTrack(string track[, number fadetime])
6973 void AnimationHandler:AdjustSpeed(string track, number speed)
6974 First argument can also be an AnimationTrack received from GetTrack.
6975
6976 void AnimationHandler:StopAllTracks()
6977 }
6978--]]
6979
6980
6981-- Services
6982
6983local ReplicatedStorage = game:GetService("ReplicatedStorage")
6984local CollectionService = game:GetService("CollectionService")
6985local Players = game:GetService("Players")
6986
6987-- Modules
6988
6989local LoadModule = require(ReplicatedStorage.Modules.Load)
6990local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
6991
6992
6993local PlayerCharacter = LoadModule("PlayerCharacter",true);
6994local Mathf = LoadModule("Mathf")
6995
6996local FX = LoadModule("FX",true);
6997local AFX = LoadModule("AFX",true);
6998local Camera = LoadModule("Camera");
6999
7000
7001
7002local SharedUtils = LoadSharedModule("SharedUtils")
7003
7004
7005local Network = LoadSharedModule("Network")
7006
7007
7008
7009-- Variables
7010
7011local Resources = ReplicatedStorage.Resources
7012local Ignore = workspace.Ignore
7013
7014local AnimationHandlers = {}
7015local KeyframeListeners = {}
7016local BoundToStart = {};
7017local AnimationHandler = {}
7018local Animations = {}
7019local Keyframes = {}
7020
7021local FootstepKeyframes = { -- Please give footstep keyframes a better name
7022 LeftFoot = true, RightFoot = true,
7023 LeftFrontHoof = true, RightFrontHoof = true,
7024 LeftFrontPaw = true, RightFrontPaw = true,
7025 LeftBackPaw = true, RightBackPaw = true
7026}
7027
7028local ItemRotateAnims = {}
7029
7030local module = {}
7031
7032
7033-- Map of animation IDs to their corresponding Name
7034
7035ID_To_AnimationName = {};
7036
7037for _,v in pairs(Resources.Animations:GetDescendants()) do
7038 if v:isA("Animation") then
7039 ID_To_AnimationName[v.AnimationId]=v.Name;
7040 end
7041end
7042
7043
7044for _,folder in pairs(Resources.Animations:GetChildren()) do
7045 local map = {}
7046 Animations[folder.Name] = map
7047
7048 for _,anim in pairs(folder:GetDescendants()) do
7049 map[anim.Name] = anim
7050
7051 local itemRotate = anim:FindFirstChild("ItemRotate")
7052 if itemRotate and itemRotate.Value then
7053 ItemRotateAnims[anim.Name] = true
7054 end
7055 end
7056end
7057
7058
7059function module.new(rig)
7060
7061 local begin = tick()
7062
7063 local rigTypeValue = rig:FindFirstChild("RigType") and rig.RigType.Value or "Player";
7064 if not rigTypeValue then return end
7065
7066 if not Animations[rigTypeValue] then
7067 warn(debug.traceback(("Invalid RigType.Value %s"):format(tostring(rigTypeValue))))
7068 return
7069 end
7070
7071 local animController = rigTypeValue == "Player"
7072 and rig:WaitForChild("Humanoid", 30 - (tick() - begin))
7073 or rig:WaitForChild("AnimationController", 30 - (tick() - begin))
7074
7075 if not animController then return end
7076
7077 local self = setmetatable({}, { __index = AnimationHandler })
7078
7079 self.Rig = rig
7080 self.RigType = rigTypeValue;
7081 self.AnimationController = animController
7082
7083 if self.RigType == "Player" then
7084 self.Owner = self.Rig == PlayerCharacter.Character
7085 else
7086 self.Owner = false
7087
7088 coroutine.wrap(function()
7089 local owner= self.Rig:WaitForChild("Owner", 30)
7090
7091 if not owner then return end
7092
7093 self.Owner = owner.Value == Players.LocalPlayer
7094 owner.Changed:Connect(function(value)
7095 self.Owner = value == Players.LocalPlayer
7096 end)
7097 end)()
7098 end
7099
7100 self.Listeners = {}
7101 self.PlayingAnimationTracks = {}
7102 self.LoadedAnimationTracks = {}
7103
7104 animController.AnimationPlayed:Connect(function(track) self:_Attach(track) end)
7105 for _,track in pairs(animController:GetPlayingAnimationTracks()) do
7106 self:_Attach(track)
7107 end
7108
7109 local remCon
7110 remCon = rig.AncestryChanged:Connect(function()
7111 if rig:IsDescendantOf(workspace) then return end
7112 remCon:Disconnect()
7113
7114 local handlers = AnimationHandlers[rig]
7115 for i,v in ipairs(handlers) do
7116 if v == self then
7117 handlers[i] = handlers[#handlers]
7118 handlers[#handlers] = nil
7119 end
7120 end
7121
7122 if handlers.active == self then
7123 handlers.active = nil
7124 self.Active = false
7125
7126 local nextActive = handlers[#handlers]
7127 if nextActive then
7128 nextActive:SetActive()
7129 else
7130 AnimationHandlers[rig] = nil
7131 end
7132 end
7133 end)
7134
7135 local handlers = AnimationHandlers[rig]
7136 if not handlers then
7137 handlers = {}
7138 AnimationHandlers[rig] = handlers
7139 end
7140
7141 handlers[#handlers + 1] = self
7142
7143 if not handlers.active then
7144 self:SetActive()
7145 end
7146
7147 return self
7148end
7149
7150-- Call to get handler of a rig
7151function module:GetHandler(rig)
7152 local handlers = AnimationHandlers[rig]
7153 return handlers and handlers.active or nil
7154end
7155
7156
7157-- Call to bind a function to the start of a specific animation track
7158
7159function module:BindToStart(name,fn)
7160 if type(name) == "table" then
7161 if fn == nil then
7162 for name,fn in pairs(name) do
7163 self:BindToStart(name, fn)
7164 end
7165 else
7166 for _,name in pairs(name) do
7167 self:BindToStart(name, fn)
7168 end
7169 end
7170 return
7171 end
7172
7173 local Bound = BoundToStart[name];
7174 BoundToStart[name]=fn;
7175
7176end
7177
7178
7179-- Call to bind a function to a keyframe
7180function module:BindToKeyframe(name, fn)
7181 if type(name) == "table" then
7182 if fn == nil then
7183 for name,fn in pairs(name) do
7184 self:BindToKeyframe(name, fn)
7185 end
7186 else
7187 for _,name in pairs(name) do
7188 self:BindToKeyframe(name, fn)
7189 end
7190 end
7191 return
7192 end
7193
7194 local list = KeyframeListeners[name]
7195
7196 if not list then
7197 list = {}
7198 KeyframeListeners[name] = list
7199 end
7200
7201 list[fn] = true
7202end
7203
7204
7205
7206function AnimationHandler:SetActive()
7207 local handlers = AnimationHandlers[self.Rig]
7208 if handlers.active == self then
7209 return
7210 end
7211
7212 if handlers.active then
7213 handlers.active.Active = false
7214 end
7215
7216 handlers.active = self
7217
7218 self.Active = true
7219end
7220
7221-- Called internally when a track is played
7222function AnimationHandler:_Attach(track)
7223
7224 if self.PlayingAnimationTracks[track] then return end
7225 self.PlayingAnimationTracks[track] = true
7226
7227 if not self.Listeners[track] then
7228 self:_AddListener(track)
7229 end
7230
7231 local trackname = ID_To_AnimationName[track.Animation.AnimationId];
7232 if trackname then
7233 local bound_function = BoundToStart[trackname];
7234
7235
7236 if bound_function then
7237 bound_function(self,track);
7238 end
7239 end
7240
7241
7242 local itemRotate = ItemRotateAnims[track.Animation.Name]
7243
7244 if itemRotate then
7245 self.ItemRotate = true
7246
7247 if not self.ItemRotateList then
7248 self.ItemRotateList = {}
7249 end
7250
7251 self.ItemRotateList[track] = true
7252 end
7253
7254 local stopCon
7255 stopCon = track.Stopped:Connect(function()
7256 stopCon:Disconnect()
7257 self.PlayingAnimationTracks[track] = nil
7258
7259 if itemRotate then
7260 self.ItemRotateList[track] = nil
7261
7262 if next(self.ItemRotateList) == nil then
7263 self.ItemRotate = false
7264 end
7265 end
7266 end)
7267end
7268
7269-- Called internally when a new track is played, unless it was recently
7270function AnimationHandler:_AddListener(track)
7271
7272
7273 if self.Listeners[track] then return end
7274 self.Listeners[track] = true
7275
7276 track.KeyframeReached:Connect(function(name)
7277
7278 if not self.Active then return end
7279
7280 if Keyframes[name] then
7281 Keyframes[name](self, name, track)
7282 end
7283
7284 local list = KeyframeListeners[name]
7285 if list then
7286 for fn,_ in pairs(list) do
7287 fn(self, name, track)
7288 end
7289 end
7290
7291 if FootstepKeyframes[name] then
7292 Keyframes.Footstep(self, name, track)
7293 end
7294
7295 end)
7296end
7297
7298-- Called to get an animation track
7299function AnimationHandler:GetTrack(track)
7300 local gotTrack = self.LoadedAnimationTracks[track]
7301 if gotTrack == nil then
7302 if typeof(track) == "Instance" and track:IsA("AnimationTrack") then
7303 warn(debug.traceback("Tried to get a track from another handler"))
7304 return
7305 elseif typeof(track) ~= "string" then
7306 warn(debug.traceback(("bad argument #2 to AnimationHandler:GetTrack (AnimationTrack or string expected, got %s)"):format(typeof(track))))
7307 return
7308 end
7309
7310 local anim = Animations[self.RigType][track]
7311 gotTrack = anim and self.AnimationController:LoadAnimation(anim) or false
7312
7313 if gotTrack then
7314 self.LoadedAnimationTracks[gotTrack] = gotTrack;
7315
7316 end
7317 self.LoadedAnimationTracks[track] = gotTrack
7318 end
7319
7320 return gotTrack or nil
7321end
7322
7323-- Called to play an animation track
7324function AnimationHandler:PlayTrack(trackName, fadetime, weight, speed)
7325 local track = self:GetTrack(trackName)
7326
7327 if not track then
7328 warn(debug.traceback("Tried to play a non-existing track"))
7329 return
7330 end
7331
7332 if not self.Owner then
7333 warn(debug.traceback("Tried to play a track on a rig you don't own"))
7334 return
7335 end
7336
7337 if not self.Active then
7338 --warn(debug.traceback("Tried to play a track on an inactive handler"))
7339 return
7340 end
7341
7342 if not track.IsPlaying then
7343 track:Play(fadetime, weight, speed)
7344
7345 if self.RigType ~= "Player" and not self.DontReplicateAnimal then
7346 Network:FireServer("PlayAnimalAnimation", self.Rig, trackName, fadetime, weight, speed)
7347 end
7348 end
7349
7350 return track
7351end
7352
7353-- Called to stop an animation track
7354function AnimationHandler:StopTrack(trackName, fadetime)
7355 local track = self:GetTrack(trackName)
7356
7357 if not track then
7358 warn(debug.traceback("Tried to stop a non-existing track"))
7359 return
7360 end
7361
7362 if not self.Owner then
7363 warn(debug.traceback("Tried to stop a track on a rig you don't own"))
7364 return
7365 end
7366
7367 if not self.Active then
7368 --warn(debug.traceback("Tried to stop a track on an inactive handler"))
7369 return
7370 end
7371
7372 if track.IsPlaying then
7373 track:Stop(fadetime)
7374
7375 if self.RigType ~= "Player" and not self.DontReplicateAnimal then
7376 Network:FireServer("StopAnimalAnimation", self.Rig, trackName, fadetime)
7377 end
7378 end
7379
7380 return track
7381end
7382
7383-- Called to stop all playing tracks
7384function AnimationHandler:StopAllTracks(fadetime)
7385 for track,_ in pairs(self.PlayingAnimationTracks) do
7386 self:StopTrack(track, fadetime)
7387 end
7388 if self.Owner then
7389 Network:FireServer("StopAllAnimalAnimations", self.Rig)
7390 end
7391end
7392
7393-- Called to adjust speed of an animation track
7394function AnimationHandler:AdjustSpeed(trackName, speed)
7395 local track = self:GetTrack(trackName)
7396
7397 if not track then
7398 warn(debug.traceback("Tried to adjust speed of a non-existing track"))
7399 return
7400 end
7401
7402 if not self.Owner then
7403 warn(debug.traceback("Tried to adjust speed on a rig you don't own"))
7404 return
7405 end
7406
7407 if not self.Active then
7408 --warn(debug.traceback("Tried to play a track on an inactive handler"))
7409 return
7410 end
7411
7412 if self.RigType ~= "Player" then
7413 Network:FireServer("AdjustAnimalAnimationSpeed",self.Rig,trackName,speed);
7414 end
7415
7416 track:AdjustSpeed(speed)
7417end
7418
7419
7420-- Generic keyframe handlers
7421
7422function Keyframes:Footstep(name)
7423 local part = self.Rig:FindFirstChild(name)
7424 if not part then return end
7425
7426
7427 local rigtype = self.RigType;
7428
7429 if rigtype ~= "Bear" then
7430 AFX.Footstep(part, self.Rig)
7431 end
7432
7433
7434 if self.RigType == "Bison" or self.RigType == "Bear" and PlayerCharacter.RootPart then
7435 local playerRootPart = PlayerCharacter.RootPart
7436 local rootPart = self.Rig:FindFirstChild("HumanoidRootPart")
7437
7438 if rootPart and (rootPart.Velocity * Vector3.new(1, 0, 1)).Magnitude > 15 then
7439 local distPerc = (playerRootPart.Position - rootPart.Position).Magnitude / 130
7440 if distPerc < 1 then
7441 local angle = math.rad((1 - distPerc) * 2)
7442 Camera:Vibrate(angle, .1, .1)
7443
7444 if rigtype == "Bear" then
7445 AFX.Footstep(part, self.Rig,{material="Heavy"});
7446 end
7447
7448 end
7449 end
7450 end
7451end
7452
7453
7454function Keyframes:Loop()
7455 if not self.Owner then return end
7456
7457 local rootPart = self.Rig:FindFirstChild("HumanoidRootPart")
7458 if rootPart then
7459 local woosh = rootPart:FindFirstChild("Woosh")
7460 if woosh then
7461 woosh.Pitch = math.random(98,102)/100
7462 woosh:Play()
7463 end
7464 end
7465end
7466
7467
7468
7469return module
7470
7471--[[
7472 Ragdolls
7473 This module will be responsible for handling all things related to ragdoll mechanics
7474--]]
7475
7476-- Services
7477
7478local ReplicatedStorage = game:GetService("ReplicatedStorage")
7479local CollectionService = game:GetService("CollectionService")
7480local PhysicsService = game:GetService("PhysicsService")
7481local TweenService = game:GetService("TweenService")
7482local RunService = game:GetService("RunService")
7483local Players = game:GetService("Players")
7484
7485-- Modules
7486
7487local LoadModule = require(ReplicatedStorage.Modules.Load)
7488local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
7489
7490local RagdollImpactListeners = LoadModule("RagdollImpactListeners");
7491local WildLife = LoadModule("WildLife",true);
7492local PlayerCharacter = LoadModule("PlayerCharacter", true)
7493local Utils = LoadModule("Utils")
7494local FX = LoadModule("FX")
7495
7496local SharedUtils = LoadSharedModule("SharedUtils")
7497local Network = LoadSharedModule("Network")
7498
7499-- Variables
7500
7501local CarriedPlayersGroup = PhysicsService:GetCollisionGroupId("CarriedPlayers")
7502
7503local Resources = ReplicatedStorage.Resources
7504local WoundPoint = Resources.WoundPointPart.WoundPoint
7505
7506local LocalPlayer = Players.LocalPlayer
7507local Ignore = workspace.Ignore
7508
7509local ReplicatedRagdolls = {}
7510local CarriedCharacters = {}
7511local ControlledRagdolls = {}
7512
7513local Heartbeat = RunService.Heartbeat;
7514
7515local module = {}
7516
7517function module:EnterRagdoll(char)
7518
7519 RagdollImpactListeners:connect(char,true);
7520
7521 SharedUtils.SetPhysicalProperties(char,"Ragdolled");
7522
7523 SharedUtils.ToggleCollisionModel(char,false);
7524 SharedUtils.ToggleWeldsActive(char, false)
7525
7526 local hrp = char:FindFirstChild("HumanoidRootPart")
7527 if hrp then
7528 hrp.CanCollide = false
7529 end
7530
7531 local human = char:FindFirstChild("Humanoid")
7532 if human then
7533 human:ChangeState("Physics")
7534 end
7535
7536
7537
7538
7539 local wildlifeobjects = WildLife:GetWildLife();
7540 local animal = wildlifeobjects[char];
7541 if animal and animal.OnRagdolled then
7542 animal:OnRagdolled();
7543 end
7544
7545end
7546
7547function module:ExitRagdoll(char)
7548
7549 RagdollImpactListeners:disconnect(char);
7550
7551 SharedUtils.SetPhysicalProperties(char,"Default");
7552
7553
7554 SharedUtils.ToggleWeldsActive(char, true)
7555 SharedUtils.ToggleCollisionModel(char,true);
7556
7557 local hrp = char:FindFirstChild("HumanoidRootPart")
7558 if hrp then
7559 hrp.CanCollide = true
7560 end
7561
7562 local human = char:FindFirstChild("Humanoid")
7563
7564 if human and human:GetState().Name == "Physics" then
7565 human:ChangeState("GettingUp")
7566 end
7567end
7568
7569function module:CreateRagdollForce(hit, pos, dir, force)
7570 if not hit then
7571 return;
7572 end
7573 coroutine.wrap(function()
7574 local mass = 0
7575
7576 Heartbeat:wait();
7577
7578 for _,part in pairs(hit:GetConnectedParts(true)) do
7579 mass = mass + part:GetMass()
7580 end
7581
7582
7583 local att = Instance.new("Attachment")
7584 att.Position = hit.CFrame:PointToObjectSpace(pos)
7585 att.Parent = hit
7586
7587
7588 local vectorforce = Instance.new("VectorForce")
7589 vectorforce.Visible = true
7590 vectorforce.ApplyAtCenterOfMass = false
7591 vectorforce.RelativeTo = "World"
7592 vectorforce.Force = dir.Unit * (mass * force)
7593 vectorforce.Attachment0 = att
7594 vectorforce.Parent = att
7595
7596 delay(.3, function() att:Destroy() print'force destroyed' end)
7597 end)()
7598end
7599
7600
7601function module:ControlRagdoll(char)
7602 if ControlledRagdolls[char] then
7603 return;
7604 end
7605
7606 local joints = {}
7607 local hrp = char.HumanoidRootPart
7608
7609 local rigtype = char:FindFirstChild("RigType") and char.RigType.Value or "Player";
7610
7611 local root;
7612 if rigtype == "Player" then
7613 root = char.LowerTorso.Root
7614 else
7615 root = hrp:FindFirstChildWhichIsA("Motor6D");
7616 end
7617
7618 local characterjoints = SharedUtils.GetCharacterJoints(char);
7619
7620 if rigtype ~= "Player" then
7621 characterjoints[#characterjoints+1]=root;
7622 end
7623
7624 for _,joint in pairs(characterjoints) do
7625 if joint.Part0 then
7626 joints[#joints + 1] = {
7627 joint = joint,
7628 part0 = joint.Part0,
7629 part1 = rigtype == "Player" and joint.Parent or joint.Part1Reference.Value; -- Welds are disabled by setting part1 to nil
7630 }
7631
7632 end
7633 end
7634
7635 local human = char:FindFirstChild("Humanoid");
7636
7637 local data = {
7638 human = human,
7639 hrp = hrp,
7640 root = root,
7641 joints = joints
7642 }
7643
7644 if char ~= LocalPlayer.Character and rigtype == "Player" then
7645 root.Part0 = nil
7646 hrp.Anchored = true
7647 data.rootDisabled = true
7648 end
7649
7650 ControlledRagdolls[char] = data
7651end
7652
7653function module:UncontrolRagdoll(char)
7654 local data = ControlledRagdolls[char]
7655 if not data then return end
7656
7657 if data.rootDisabled then
7658 data.root.Part0 = data.hrp
7659 data.hrp.Anchored = false
7660 end
7661
7662 ControlledRagdolls[char] = nil
7663end
7664
7665function module:StartCarrying(carrier, target)
7666 local targetPart = target:FindFirstChild("UpperTorso")
7667 local att = carrier:FindFirstChild("CarryAttachment", true)
7668
7669 if target and att then
7670 local isSelf = target == PlayerCharacter.Character
7671
7672 if not isSelf then
7673 targetPart.Anchored = true
7674 end
7675
7676 local collisionGroups = {}
7677
7678 for _,part in pairs(target:GetChildren()) do
7679 if part:IsA("BasePart") then
7680 collisionGroups[part] = part.CollisionGroupId
7681 part.CollisionGroupId = CarriedPlayersGroup
7682 end
7683 end
7684
7685 CarriedCharacters[carrier] = {
7686 isSelf = isSelf,
7687 target = targetPart,
7688 targetChar = target,
7689 attachment = att,
7690 collisionGroups = collisionGroups
7691 }
7692 end
7693end
7694
7695function module:StopCarrying(carrier)
7696 local data = CarriedCharacters[carrier]
7697 if data then
7698 data.target.Anchored = false
7699
7700 for part,origGroup in pairs(data.collisionGroups) do
7701 if part.CollisionGroupId == CarriedPlayersGroup then
7702 part.CollisionGroupId = origGroup
7703 end
7704 end
7705
7706 CarriedCharacters[carrier] = nil
7707 end
7708end
7709function module:StopReplicatingRagdoll(char)
7710 RagdollImpactListeners:disconnect(char);
7711 local data = ReplicatedRagdolls[char]
7712 if data then
7713 ReplicatedRagdolls[char] = nil
7714 data.hrp.Anchored = false
7715 end
7716end
7717
7718
7719Network:BindEvents({
7720 UpdateControlledRagdolls = function(char, hrpPos,hrpAngle,jointGoals)
7721
7722 local data = ReplicatedRagdolls[char]
7723
7724 local hrp = char:FindFirstChild("HumanoidRootPart");
7725
7726 if not data then
7727
7728 RagdollImpactListeners:connect(char);
7729
7730 local wildlifeobjects = WildLife:GetWildLife();
7731 local animal = wildlifeobjects[char];
7732 if animal and animal.OnRagdolled then
7733 animal:OnRagdolled();
7734 end
7735
7736
7737 data = { hrp = hrp }
7738 ReplicatedRagdolls[char] = data
7739 end
7740
7741 hrp.Anchored = true
7742
7743 -- Reconstruct HRP CF
7744 local x,y,z = SharedUtils.decompress(hrpAngle);
7745 local hrpGoal = CFrame.fromEulerAnglesYXZ(x,y,z) + hrpPos;
7746 --
7747
7748 data.hrp_goal = hrpGoal
7749 data.jointGoals = jointGoals
7750 end,
7751 StopControlledRagdoll = function(char)
7752 module:StopReplicatingRagdoll(char);
7753 end
7754})
7755
7756
7757
7758
7759function UpdateReplicatedRagdolls(_, updateTime)
7760 local alpha = math.clamp(updateTime / 0.05, 0, 1)
7761
7762 for char,data in pairs(ReplicatedRagdolls) do
7763 data.hrp.CFrame = data.hrp.CFrame:Lerp(data.hrp_goal, alpha)
7764
7765 for _,tab in pairs(data.jointGoals) do
7766 local joint, goal,ypos = unpack(tab);
7767 if joint then
7768 local dx,dy,dz = SharedUtils.decompress(goal);
7769
7770 goal = CFrame.new(0,ypos,0)*CFrame.fromEulerAnglesYXZ(dx,dy,dz);
7771
7772 joint.Transform = joint.Transform:Lerp(goal, alpha)
7773 end
7774 end
7775 end
7776end
7777
7778function UpdateControlledRagdolls(_, updateTime)
7779 if next(ControlledRagdolls) == nil then return end
7780 local updateData = {}
7781
7782 for char,data in pairs(ControlledRagdolls) do
7783 local hrp = data.hrp
7784
7785 local hrp_goal = hrp.CFrame;
7786 local hrp_angle_x,hrp_angle_y,hrp_angle_z = hrp_goal:toEulerAnglesYXZ();
7787 local hrp_angle = SharedUtils.compress(hrp_angle_x,hrp_angle_y,hrp_angle_z);
7788 local hrp_pos = hrp_goal.p;
7789
7790 if data.rootDisabled then
7791 hrp_goal = data.root.Part1.CFrame * data.root.C1 * data.root.C0:Inverse()
7792 hrp.CFrame = hrp_goal
7793 hrp.Anchored=true;
7794 end
7795
7796
7797 local joints = {}
7798 for _,tab in pairs(data.joints) do
7799 local joint = tab.joint
7800 local cf = (tab.part0.CFrame * joint.C0):ToObjectSpace(tab.part1.CFrame * joint.C1)
7801
7802
7803 local x,y,z = cf:toEulerAnglesYXZ();
7804
7805
7806 local goal = SharedUtils.compress(x,y,z);
7807
7808 local ypos = cf.p.y;
7809
7810 joints[#joints + 1] = {
7811 joint,
7812 goal,
7813 ypos
7814 }
7815 end
7816
7817 Network:FireServer("UpdateControlledRagdolls", char, hrp_pos,hrp_angle,joints)
7818 end
7819end
7820
7821function UpdateCarriedCharacters()
7822 for carrier,data in pairs(CarriedCharacters) do
7823 if data.isSelf then
7824 data.target.Velocity = Vector3.new()
7825 data.target.RotVelocity = Vector3.new()
7826 end
7827
7828 data.target.CFrame = data.attachment.WorldCFrame
7829 end
7830end
7831
7832RunService.Stepped:Connect(UpdateReplicatedRagdolls)
7833RunService.Stepped:Connect(UpdateControlledRagdolls)
7834Heartbeat:Connect(UpdateCarriedCharacters)
7835
7836
7837return module
7838
7839
7840--[=[
7841 Module responsible for handling holsters for sidearms
7842--]=]
7843
7844
7845local module = {}
7846
7847local Players = game:GetService("Players");
7848local LocalPlayer = Players.LocalPlayer;
7849
7850
7851local ReplicatedStorage = game:GetService("ReplicatedStorage");
7852local Resources = ReplicatedStorage.Resources;
7853
7854local LoadModule = require(ReplicatedStorage.Modules.Load);
7855local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
7856
7857local Network = LoadSharedModule("Network");
7858
7859local PlayerCharacter = LoadModule("PlayerCharacter",true);
7860
7861local CollectionService = game:GetService("CollectionService");
7862
7863
7864local Holster = {};
7865local Holsters = {};
7866
7867function Holster.new(char,name)
7868
7869
7870 if Holsters[char] then
7871 Holsters[char]:Dispose();
7872 end
7873
7874 local LowerTorso = char:FindFirstChild("LowerTorso");
7875 if LowerTorso then
7876
7877 local self = {};
7878 setmetatable(self,{__index=Holster});
7879
7880
7881 local model = Resources.Holsters:FindFirstChild(name):clone();
7882 model.PrimaryPart.CFrame=LowerTorso.CFrame;
7883
7884 wait();
7885
7886 model.Parent=char;
7887
7888 local primary = model.PrimaryPart;
7889 local HolsterAttachmentCF = primary.HolsterAttachment.CFrame;
7890
7891 local at0 = Instance.new("Attachment",LowerTorso);
7892 at0.CFrame=HolsterAttachmentCF;
7893 at0.Name="At0";
7894 local at1 = Instance.new("Attachment",primary);
7895 at1.Name="At1";
7896
7897 local weld = Instance.new("Motor6D",primary);
7898 weld.Part0=LowerTorso;
7899 weld.Part1=primary;
7900 weld.C0=HolsterAttachmentCF;
7901--
7902-- local hinge = Instance.new("HingeConstraint",model);
7903-- hinge.Attachment0=at0;
7904-- hinge.Attachment1=at1;
7905-- hinge.LimitsEnabled=true;
7906-- hinge.Restitution=0.25;
7907-- hinge.LowerAngle=-15;
7908-- hinge.UpperAngle=15;
7909
7910
7911 self.Holster=model;
7912 self.at0=at0;
7913 self.at1=at1;
7914 self.char=char;
7915 self.GunVisible=false;
7916
7917
7918 Holsters[char]=self;
7919
7920
7921
7922 char:GetPropertyChangedSignal("Parent"):connect(function()
7923 if char.Parent == nil then
7924 self:Dispose();
7925 end
7926 end)
7927
7928 return self;
7929 end
7930end
7931
7932function Holster:EquipGun(name)
7933 if self.Gun then
7934
7935 if self.Gun.Name == name then
7936 return;
7937 else
7938 self.Gun:Destroy();
7939 end
7940 end
7941
7942 local holster = self.Holster;
7943 local primary = holster.PrimaryPart;
7944 local gunattachment = primary:FindFirstChild(name);
7945 local newgun = Resources.Holsters.Items:FindFirstChild(name):clone();
7946
7947 local gunweld = Instance.new("Weld");
7948 gunweld.Part0=primary;
7949 gunweld.Part1=newgun.PrimaryPart;
7950 gunweld.C0=gunattachment.CFrame;
7951
7952 gunweld.Parent=newgun;
7953 newgun.Parent=holster;
7954
7955 self:SetGunVisible(self.GunVisible);
7956
7957 self.Gun=newgun;
7958end
7959function Holster:SetGunVisible(b)
7960 self.GunVisible=b;
7961
7962 if self.Gun then
7963 for _,v in pairs(self.Gun:GetChildren()) do
7964 if v:isA("BasePart") then
7965 v.Transparency = b == true and 0 or 1;
7966 end
7967 end
7968 end
7969end
7970
7971
7972function Holster:Dispose()
7973 if self.Holster then
7974 self.Holster:Destroy();
7975 end
7976 if self.at0 then
7977 self.at0:Destroy();
7978 end
7979
7980 if self.at1 then
7981 self.at1:Destroy();
7982 end
7983 if self.char then
7984 Holsters[self.char]=nil;
7985 end
7986end
7987
7988function module:EquipHolster(name)
7989
7990 if PlayerCharacter.Character then
7991
7992 if module.Holster then
7993 module.Holster:Dispose();
7994 end
7995
7996 -- To do: Replicate
7997
7998 local NewHolster = Holster.new(PlayerCharacter.Character,name);
7999 module.Holster=NewHolster;
8000
8001 Network:FireServer("EquipHolster",name);
8002 end
8003end
8004function module:GetHolster()
8005 return module.Holster;
8006end
8007
8008function module:EquipGun(name)
8009 local Holster = module:GetHolster();
8010 if Holster then
8011 Holster:EquipGun(name);
8012
8013 module:SetGunVisible(true);
8014 Network:FireServer("EquipGunInHolster",name);
8015 end
8016end
8017function module:SetGunVisible(b)
8018 local Holster = module:GetHolster();
8019 if Holster then
8020 Holster:SetGunVisible(b);
8021
8022 Network:FireServer("SetGunVisibleHolster",b);
8023 end
8024end
8025
8026
8027
8028Network:BindEvents({
8029 EquipHolster = function(player,holsterdata)
8030
8031 if player == LocalPlayer then
8032
8033 module:EquipHolster(holsterdata.HolsterName);
8034 return
8035 end
8036
8037 local char = player.Character
8038
8039 if char and char:IsDescendantOf(workspace) then
8040
8041 local name = holsterdata.HolsterName;
8042 local equippedgun = holsterdata.EquippedGun;
8043 local gunvisible = holsterdata.GunVisible;
8044
8045 local newholster = Holster.new(char,name);
8046 newholster:SetGunVisible(gunvisible);
8047 if equippedgun then
8048 newholster:EquipGun(equippedgun);
8049 end
8050 end
8051 end,
8052 EquipGunInHolster = function(player,name)
8053 local char = player.Character
8054
8055 if char and char:IsDescendantOf(workspace) then
8056 local holster = Holsters[char];
8057 if holster then
8058 holster:EquipGun(name);
8059 end
8060 end
8061 end,
8062 SetGunVisibleHolster = function(player,visible)
8063 local char = player.Character
8064
8065 if char and char:IsDescendantOf(workspace) then
8066 local holster = Holsters[char];
8067 if holster then
8068 holster:SetGunVisible(visible);
8069 end
8070 end
8071 end
8072})
8073
8074return module
8075
8076
8077local module = {}
8078
8079--
8080
8081local ReplicatedStorage = game:GetService("ReplicatedStorage");
8082local LoadModule = require(ReplicatedStorage.Modules.Load);
8083local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
8084
8085local PlayerCharacter = LoadModule("PlayerCharacter",true);
8086local WildLife = LoadModule("WildLife", true);
8087
8088local FaceMouseUtils = LoadSharedModule("FaceMouseUtils");
8089local Network = LoadSharedModule("Network");
8090
8091--
8092
8093local player = game:GetService("Players").LocalPlayer;
8094local mouse = player:GetMouse();
8095
8096local Ignore = workspace.Ignore;
8097
8098local CharacterSpring = {};
8099local CharacterSprings = {};
8100
8101
8102-- Create spring object
8103function CharacterSpring.new(char)
8104 local self = setmetatable({},{__index=CharacterSpring});
8105
8106 local springPart = Instance.new("Part");
8107 springPart.Name="SpringPart";
8108 springPart.Size = Vector3.new(1, 1, 1);
8109 springPart.CFrame = CFrame.new();
8110 springPart.CanCollide = false;
8111 springPart.Transparency = 1;
8112 springPart.Parent = char;
8113
8114 self.springPart=springPart;
8115
8116 local hrp = char:WaitForChild("HumanoidRootPart");
8117
8118 local bpos = Instance.new("BodyPosition");
8119 bpos.Position = Vector3.new();
8120 bpos.Parent = springPart;
8121 bpos.D=800;
8122
8123 local human = char:WaitForChild("Humanoid");
8124
8125 local head = char:WaitForChild("Head");
8126
8127
8128 local waist = char:WaitForChild("UpperTorso"):WaitForChild("Waist");
8129 local waistc0 = ReplicatedStorage.Resources.PlayerCharacter.UpperTorso.Waist.C0;
8130
8131 local neck = head:WaitForChild("Neck");
8132 local neckc0 = ReplicatedStorage.Resources.PlayerCharacter.Head.Neck.C0;
8133
8134 self.goal=Vector3.new();
8135 self.char=char;
8136 self.human=human;
8137 self.waist=waist;
8138 self.waistc0=waistc0;
8139 self.neck=neck;
8140 self.neckc0=neckc0;
8141 self.hrp=hrp;
8142 self.lastupdate=tick();
8143 self.bpos=bpos;
8144 self.springPart=springPart;
8145
8146 char:GetPropertyChangedSignal("Parent"):connect(function()
8147 if char.Parent == nil then
8148 self:Dispose();
8149 end
8150 end)
8151
8152 CharacterSprings[char]=self;
8153
8154 return self;
8155end
8156--
8157
8158-- Set Spring Goal
8159function CharacterSpring:SetGoal(pos)
8160 self.goal=pos;
8161end
8162
8163--
8164
8165-- Dispose spring
8166function CharacterSpring:Dispose()
8167 if self.char then
8168 CharacterSprings[self.char]=nil;
8169 end
8170
8171 self.springPart:Destroy();
8172end
8173--
8174
8175
8176
8177
8178
8179local lastUpdate = 0;
8180
8181local update_time = 0.2 -- time interal in which local client updates joint info to server
8182
8183
8184
8185module.Update = function(dt)
8186
8187 if true then
8188 return;
8189 end
8190
8191 local alpha = math.clamp(dt/0.2,0,1);
8192
8193 -- Update other springs
8194
8195
8196 for i,springobj in pairs(CharacterSprings) do
8197
8198 local springPart = springobj.springPart;
8199 local bpos = springobj.bpos;
8200 local hrp = springobj.hrp;
8201 local waist = springobj.waist;
8202 local waistc0 = springobj.waistc0;
8203 local neck = springobj.neck;
8204 local neckc0 = springobj.neckc0;
8205 local char = springobj.char;
8206 local human = springobj.human;
8207 local goal = springobj.goal;
8208 local hrp = springobj.hrp;
8209 local updated_last = springobj.lastupdate;
8210 if goal == nil or tick()-updated_last >= 4 then -- If no goal or it's been 4 seconds since last update
8211 neck.C0=neckc0;
8212 waist.C0=waistc0;
8213 else
8214
8215 local hTheta, hTheta2, vTheta = FaceMouseUtils.calcAngles(springPart.Position);
8216
8217
8218
8219 local necklook = 1;
8220
8221 if human.MoveDirection == Vector3.new() then
8222 necklook=0.5;
8223 end
8224
8225 local waistgoal = CFrame.fromEulerAnglesYXZ(vTheta, hTheta - hTheta2, 0) + waistc0.p
8226 local neckgoal = CFrame.fromEulerAnglesYXZ(vTheta*0.5,(hTheta - hTheta2) * necklook , 0) + neckc0.p
8227
8228 waist.C0=waist.C0:lerp(waistgoal,alpha);
8229 neck.C0=neck.C0:lerp(neckgoal,alpha);
8230
8231 springPart.Position=goal;
8232
8233
8234 end
8235
8236
8237 end
8238 --
8239
8240
8241
8242
8243
8244 -- Update my springs
8245
8246
8247
8248 local springPart = PlayerCharacter.SpringPart;
8249 local bpos = PlayerCharacter.SpringBody;
8250 local hrp = PlayerCharacter.RootPart;
8251 local waist = PlayerCharacter.Waist;
8252 local waistc0 = PlayerCharacter.Waistc0;
8253 local neck = PlayerCharacter.Neck;
8254 local neckc0 = PlayerCharacter.Neckc0;
8255 local char = PlayerCharacter.Character;
8256
8257 local waistgoal = waistc0;
8258 local neckgoal = neckc0;
8259
8260 local alpha = math.clamp(dt/0.2,0,1);
8261
8262
8263-- print(PlayerCharacter.FacingMouse);
8264
8265
8266 if PlayerCharacter.FacingMouse == true then
8267 local hTheta, hTheta2, vTheta = FaceMouseUtils.calcAngles(springPart.Position);
8268
8269
8270 local hrp_pos = hrp.Position;
8271
8272 local necklook = 1;
8273
8274 if hrp.Parent.Humanoid.MoveDirection == Vector3.new() and not WildLife:GetRidingAnimal() and not PlayerCharacter.OnWagon and not PlayerCharacter:GetSeated() then
8275 hrp.CFrame=hrp.CFrame:lerp(hrp.CFrame*CFrame.fromEulerAnglesYXZ(0, hTheta2, 0),alpha); -- Auto replicates
8276 necklook=0.5;
8277 end
8278
8279 waistgoal = CFrame.fromEulerAnglesYXZ(vTheta, hTheta - hTheta2, 0) + waistc0.p
8280 neckgoal = CFrame.fromEulerAnglesYXZ(vTheta*0.5,(hTheta - hTheta2) * necklook , 0) + neckc0.p
8281
8282 local hit,pos = workspace:FindPartOnRayWithIgnoreList(Ray.new(mouse.UnitRay.Origin,mouse.UnitRay.Direction*200),{char,Ignore});
8283
8284 bpos.Position = hrp.CFrame:pointToObjectSpace(pos);
8285
8286 waist.C0=waist.C0:lerp(waistgoal,alpha);
8287 neck.C0=neck.C0:lerp(neckgoal,alpha);
8288
8289 if tick()-lastUpdate >= update_time then
8290 lastUpdate=tick();
8291 Network:FireServer("UpdateCharacterSpring",char,bpos.Position);
8292 end
8293
8294 else -- if PlayerCharacter.FacingMouse == false then
8295 if LastFaceMouse then
8296 waist.C0=waistgoal;
8297 neck.C0=neckgoal;
8298
8299 Network:FireServer("UpdateCharacterSpring",char,nil)
8300 end
8301 end
8302
8303 lastwaistgoal=waistgoal;
8304 lastneckgoal=neckgoal;
8305
8306 LastFaceMouse=PlayerCharacter.FaceMouse == true or nil;
8307
8308
8309
8310
8311 --
8312
8313
8314end
8315
8316Network:BindEvents(
8317 {
8318 UpdateCharacterSpring=function(char,pos)
8319 if not char then
8320 return;
8321 end
8322
8323 local object = CharacterSprings[char] or CharacterSpring.new(char);
8324 object:SetGoal(pos);
8325 object.lastupdate=tick();
8326
8327 end
8328 }
8329)
8330
8331return module
8332
8333
8334--[=[
8335 Handles CFraming characters to seats
8336--]=]
8337
8338local module = {}
8339
8340local Players = game:GetService("Players");
8341local Player = Players.LocalPlayer;
8342
8343local ReplicatedStorage = game:GetService("ReplicatedStorage");
8344local RunService = game:GetService("RunService");
8345local Heartbeat = RunService.Heartbeat;
8346
8347local LoadModule = require(ReplicatedStorage.Modules.Load);
8348local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
8349
8350local SharedUtils = LoadSharedModule("SharedUtils");
8351local PlayerCharacter = LoadModule("PlayerCharacter");
8352local Network = LoadSharedModule("Network");
8353
8354
8355local SeatObject = {};
8356local SeatObjects = {};
8357function SeatObject.new(char,seat,owner)
8358
8359 if not char or not seat then
8360 return;
8361 end
8362
8363
8364 local root = char:FindFirstChild("HumanoidRootPart");
8365 if not root then
8366 return;
8367 end
8368
8369
8370 local self = setmetatable({},{__index=SeatObject});
8371
8372 self.alignat_0 = Instance.new("Attachment",root);
8373 self.alignat_1 = Instance.new("Attachment",seat);
8374
8375 local alignpos = Instance.new("AlignPosition",self.alignat_0);
8376 alignpos.Attachment0=self.alignat_0;
8377 alignpos.Attachment1=self.alignat_1;
8378 alignpos.RigidityEnabled=true;
8379 self.alignpos=alignpos;
8380
8381 local alignori = Instance.new("AlignOrientation",self.alignat_0);
8382 alignori.Attachment0=self.alignat_0;
8383 alignori.Attachment1=self.alignat_1;
8384 alignori.RigidityEnabled=true;
8385
8386 self.alignori=alignori;
8387
8388 self.seat=seat;
8389 self.hrp = root;
8390 self.char=char;
8391
8392 self.owner=owner;
8393
8394 SharedUtils.SetCollisionGroup(char,"Seated");
8395
8396 if owner then
8397
8398 PlayerCharacter:StopAllTracks();
8399
8400 PlayerCharacter:Sit();
8401
8402 end
8403
8404 char.AncestryChanged:connect(function(_,parent)
8405 if not parent then
8406 self:Dispose();
8407 end
8408 end)
8409 SeatObjects[char]=self;
8410end
8411function SeatObject:Update()
8412 if self.hrp and self.seat then
8413 self.hrp.CFrame=self.seat.CFrame;
8414 end
8415end
8416function SeatObject:Dispose()
8417 print("SEAT OBJECT DISPOSED ON CHAR: ",self.char);
8418 if self.char then
8419 SharedUtils.SetCollisionGroup(self.char,"Default");
8420 SeatObjects[self.char]=nil;
8421 end
8422 if self.alignat_0 then
8423 self.alignat_0:Destroy();
8424 end
8425 if self.alignat_1 then
8426 self.alignat_1:Destroy();
8427 end
8428end
8429
8430
8431Network:BindEvents({
8432 SeatPlayer=function(char,seat)
8433 if char then
8434 local owner = char.Name == Player.Name or PlayerCharacter.Character == char;
8435 SeatObject.new(char,seat,owner);
8436 end
8437 end,
8438 UnseatPlayer=function(char)
8439 local obj = SeatObjects[char];
8440 if obj then
8441 obj:Dispose();
8442 end
8443 end
8444})
8445
8446local function Update()
8447 for char,obj in pairs(SeatObjects) do
8448 obj:Update();
8449 end
8450end
8451
8452Heartbeat:connect(Update);
8453
8454return module
8455
8456
8457--[=[
8458 Handles client side RobbingItem equips
8459 Examples include money bags, boxes, and gold bars
8460--]=]
8461
8462
8463local module = {}
8464
8465local Players = game:GetService("Players");
8466local LocalPlayer = Players.LocalPlayer;
8467
8468
8469local ReplicatedStorage = game:GetService("ReplicatedStorage");
8470local Resources = ReplicatedStorage.Resources;
8471
8472local LoadModule = require(ReplicatedStorage.Modules.Load);
8473local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
8474local SharedUtils = LoadSharedModule("SharedUtils");
8475local Mathf = LoadSharedModule("Mathf");
8476
8477local Network = LoadSharedModule("Network");
8478
8479local PlayerCharacter = LoadModule("PlayerCharacter",true);
8480
8481local CollectionService = game:GetService("CollectionService");
8482
8483local RobbingItems={};
8484local RobbingItem={};
8485
8486local Terrain = workspace:WaitForChild("Terrain");
8487local Ignore = workspace:WaitForChild("Ignore");
8488
8489local MyRobbingItem;
8490
8491function RobbingItem.new(itemtype,character)
8492 local self = setmetatable({},{__index=RobbingItem});
8493
8494 self.owns = PlayerCharacter.Character == character;
8495 if self.owns == true then
8496 MyRobbingItem=self;
8497 end
8498
8499 local item = Resources.RobbingItems:FindFirstChild(itemtype);
8500
8501 if not item then
8502 return;
8503 end
8504 if not character then
8505 return;
8506 end
8507
8508
8509 item=item:clone();
8510
8511 item.Parent=character;
8512
8513 if itemtype == "MoneyBag" then
8514 local bag = item:WaitForChild("Bag");
8515 local pickup = bag:WaitForChild("Pickup");
8516 pickup.Pitch=math.random(98,102)/100;
8517 pickup:Play();
8518
8519 local leftgrip = character:WaitForChild("LeftHand"):WaitForChild("LeftGripAttachment");
8520
8521 self.leftgrip=leftgrip;
8522
8523 local attachmentpart = Instance.new("Part");
8524 attachmentpart.Anchored=true;
8525 attachmentpart.CanCollide=false;
8526 attachmentpart.Transparency=1;
8527 attachmentpart.Parent=Ignore;
8528 attachmentpart.CFrame=leftgrip.WorldCFrame;
8529
8530 local attachment1=Instance.new("Attachment",attachmentpart);
8531
8532 self.attachmentpart=attachmentpart;
8533
8534 local ballsocket = item:WaitForChild("BallSocketConstraint");
8535 ballsocket.Attachment1=attachment1;
8536
8537 bag.CFrame=attachmentpart.CFrame;
8538 ballsocket.Enabled=true;
8539 end
8540
8541 self.char=character;
8542 self.itemtype=itemtype;
8543 self.item=item;
8544 self.defaultsize=item.PrimaryPart.Size;
8545
8546 RobbingItems[character]=self;
8547
8548 character.AncestryChanged:connect(function(_,par)
8549 if not par then
8550 self:Dispose();
8551 end
8552 end)
8553
8554 return self;
8555end
8556
8557function RobbingItem:Dispose()
8558
8559 if MyRobbingItem == self then
8560 MyRobbingItem=nil;
8561 end
8562
8563 if self.item and self.item.Parent then
8564 self.item:Destroy();
8565 end
8566 if self.char then
8567 RobbingItems[self.char]=nil;
8568 end
8569end
8570
8571function RobbingItem:UpdateBagSize(size)
8572 if self.item then
8573 local perc = size/4;
8574 SharedUtils.ScaleModel(self.item,Mathf.Lerp(1,2,perc),self.defaultsize);
8575
8576
8577 if self.owns == true then
8578 if shared.ClientSounds then
8579 shared.ClientSounds.GainCurrency:Play();
8580 end
8581 end
8582
8583 end
8584end
8585
8586
8587function module.Update(updateTime)
8588 for char,obj in pairs(RobbingItems) do
8589 if obj.itemtype == "MoneyBag" then
8590 local leftgrip = obj.leftgrip;
8591 local attachmentpart = obj.attachmentpart;
8592
8593 if attachmentpart then
8594 attachmentpart.CFrame=leftgrip.WorldCFrame;
8595 end
8596 end
8597 end
8598end
8599
8600function module:DropRobbingItem()
8601 if MyRobbingItem then
8602 Network:FireServer("DropRobbingItem",MyRobbingItem.item.PrimaryPart.CFrame);
8603 MyRobbingItem:Dispose();
8604 end
8605end
8606
8607Network:BindEvents({
8608 EquipRobbingItem=function(itemtype,player,size)
8609 size=size or 1;
8610 if not player then
8611 return;
8612 end
8613 local character = player.Character;
8614 if not character then
8615 return;
8616 end
8617
8618
8619 if RobbingItems[character] then
8620 RobbingItems[character]:Dispose();
8621 end
8622
8623 if itemtype ~= nil then
8624 local item = RobbingItem.new(itemtype,character);
8625 if itemtype == "MoneyBag" then
8626 item:UpdateBagSize(size);
8627 end
8628 end
8629 end,
8630 DropRobbingItem=function(itemtype,player)
8631 if not player then
8632 return;
8633 end
8634 local character = player.Character;
8635 if not character then
8636 return;
8637 end
8638
8639 local item = RobbingItems[character];
8640 if item then
8641 item:Dispose();
8642 end
8643 end,
8644 AddBankMoneySize=function(cashsize,player)
8645 if not player then
8646 return;
8647 end
8648 local character = player.Character;
8649 if not character then
8650 return;
8651 end
8652 local item = RobbingItems[character];
8653 if item then
8654 item:UpdateBagSize(cashsize);
8655 end
8656 end
8657})
8658return module
8659
8660
8661local module = {}
8662
8663
8664-- Modules
8665local ReplicatedStorage = game:GetService("ReplicatedStorage");
8666local LoadModule = require(ReplicatedStorage:WaitForChild("Modules"):WaitForChild("Load"));
8667local PlayerCharacter = LoadModule("PlayerCharacter", true)
8668local UIObjects = LoadModule("UIObjects");
8669--
8670
8671-- Network
8672local LoadSharedModule = require(ReplicatedStorage:WaitForChild("SharedModules"):WaitForChild("Load"));
8673local Network = LoadSharedModule("Network");
8674local Time = LoadSharedModule("Time");
8675--
8676
8677-- Variables
8678local players = game:GetService("Players");
8679local player = players.LocalPlayer;
8680
8681local PlayerRobbingGui = UIObjects.PlayerRobbing;
8682local PlayerRobbingDescriptionLabel = PlayerRobbingGui:WaitForChild("Description");
8683local PlayerRobbingFrame = PlayerRobbingGui:WaitForChild("Frame");
8684local PlayerRobbingFrame_Plr = PlayerRobbingFrame:WaitForChild("Player");
8685local PlayerRobbingFrame_Robbing = PlayerRobbingFrame:WaitForChild("Robbing");
8686local PlayerRobbingFrame_BeingRobbed = PlayerRobbingFrame:WaitForChild("BeingRobbed");
8687
8688local PlayerRobbingProgress = PlayerRobbingGui:WaitForChild("ProgressBar");
8689local PlayerRobbingProgressFill = PlayerRobbingProgress:WaitForChild("Fill");
8690local PlayerRobbingProgressPercent = PlayerRobbingProgress:WaitForChild("Percent");
8691
8692local PlayerRobbingHourGlass = PlayerRobbingGui:WaitForChild("Hourglass");
8693local HourGlassTxt = PlayerRobbingHourGlass:WaitForChild("TextLabel");
8694
8695
8696local time_till_rob = 30;
8697
8698
8699--
8700
8701
8702
8703
8704local cam = workspace.CurrentCamera;
8705
8706
8707
8708local AttemptingToRob; -- Player we're attempting to rob
8709
8710 -- Gets cleaned when the server sends us back a message which says we're robbing a player
8711
8712--]=]
8713
8714local RobbingPlayer;
8715
8716local BeingRobbed;
8717
8718
8719local function StopRobbing() -- Stop robbing prematurely
8720 if RobbingPlayer then
8721
8722 local plr = RobbingPlayer.plr;
8723
8724
8725 RobbingPlayer=nil;
8726
8727 Network:FireServer("StopRobbingPlayer");
8728
8729 end
8730end
8731
8732local function AttemptToRob(char)
8733
8734
8735 local plr = players:GetPlayerFromCharacter(char);
8736 local states = char:FindFirstChild("StateInfo");
8737 if not states then
8738 return;
8739 end
8740
8741 local aiming = states:FindFirstChild("Aiming");
8742 local beingrobbed = states:FindFirstChild("BeingRobbed");
8743
8744 if not aiming then
8745 return;
8746 end
8747
8748 if not beingrobbed then
8749 return;
8750 end
8751
8752 if not plr then
8753 return;
8754 end
8755
8756
8757 if AttemptingToRob then
8758 return;
8759 end
8760
8761 if aiming.Value == true then -- If they're aiming their gun at me, I can't rob them!
8762 return;
8763 end
8764
8765 if beingrobbed.Value == true then -- If they're already being robbed, I can't rob them
8766 return;
8767 end
8768
8769
8770 AttemptingToRob=plr;
8771
8772 local rob_success = Network:InvokeServer("AttemptToRob",plr);
8773
8774 AttemptingToRob=nil;
8775
8776 if rob_success then
8777
8778 local char = plr.Character;
8779 if char then
8780
8781 local charhrp = char:FindFirstChild("HumanoidRootPart");
8782 if charhrp then
8783 PlayerRobbingFrame_BeingRobbed.Visible=false;
8784 PlayerRobbingFrame_Plr.Visible=true;
8785 PlayerRobbingFrame_Robbing.Visible=true;
8786
8787 PlayerRobbingFrame_Plr.Text=plr.Name;
8788
8789 PlayerRobbingDescriptionLabel.Text="Keep your gun on'em, and don't let them get too far!";
8790 PlayerRobbingGui.Enabled=true;
8791 RobbingPlayer={plr=plr,timestamp=rob_success.timestamp,charhrp=charhrp};
8792 end
8793 end
8794 end
8795end
8796
8797
8798
8799
8800
8801function AngleBetweenVectors(v1, v2)
8802 return math.acos(v1.Unit:Dot(v2.Unit))
8803end
8804
8805local function AimingAt(charhrp)
8806
8807
8808 local a = cam.CFrame - cam.CFrame.p + PlayerCharacter.RootPart.CFrame.p
8809
8810 local b = charhrp.CFrame; -- their root part
8811
8812 local dist = (a.p-b.p).magnitude;
8813
8814 local angle = AngleBetweenVectors(b.lookVector,(a.p-b.p).unit)
8815 local angle2 = AngleBetweenVectors(a.lookVector,(b.p-a.p).unit)
8816
8817
8818 local isAiming = PlayerCharacter:GetEquippedItem().IsAiming
8819 return isAiming and angle2 < math.rad(50) and angle < math.rad(50) and dist < 20;
8820end
8821
8822
8823
8824
8825module.Update = function()
8826 if RobbingPlayer then
8827
8828
8829
8830 local CurrentlyAimingAt = AimingAt(RobbingPlayer.charhrp);
8831
8832 if not CurrentlyAimingAt then
8833 StopRobbing();
8834 else
8835 local current_timestamp = Time.GetTime();
8836
8837 local started = RobbingPlayer.timestamp;
8838
8839 local elapsed = current_timestamp - started;
8840
8841
8842 local percent = math.clamp(elapsed/time_till_rob,0,1);
8843
8844 PlayerRobbingProgressFill.Size=UDim2.new(percent,0,1,0);
8845 PlayerRobbingProgressPercent.Text=math.floor(percent*100).."%";
8846 HourGlassTxt.Text = math.floor(time_till_rob-elapsed).."s";
8847 end
8848
8849 end
8850
8851
8852 if BeingRobbed then
8853
8854 local current_timestamp = Time.GetTime();
8855
8856 local started = BeingRobbed.timestamp;
8857
8858 local elapsed = current_timestamp - started;
8859
8860 local percent = math.clamp(elapsed/time_till_rob,0,1);
8861
8862 PlayerRobbingProgressFill.Size=UDim2.new(percent,0,1,0);
8863 PlayerRobbingProgressPercent.Text=math.floor(percent*100).."%";
8864 HourGlassTxt.Text = math.floor(time_till_rob-elapsed).."s";
8865
8866 end
8867end
8868
8869
8870
8871module.UpdateOtherCharacters = function(thischar)
8872 -- Player Character passes in thischar per player
8873
8874
8875 -- Look for player to rob
8876
8877 if not AttemptingToRob and not RobbingPlayer then
8878 local hrp = PlayerCharacter.RootPart;
8879 if hrp then
8880
8881 local charhrp = thischar:FindFirstChild("HumanoidRootPart");
8882 if charhrp then
8883
8884 if AimingAt(charhrp) then
8885 --AttemptToRob(thischar);
8886 end
8887 end
8888 end
8889 end
8890 --
8891end
8892
8893
8894
8895-- Network
8896
8897
8898
8899Network:BindEvents({
8900 BeingRobbed=function(tab)
8901 local timestamp = tab.timestamp;
8902
8903
8904 PlayerRobbingFrame_BeingRobbed.Visible=true;
8905 PlayerRobbingFrame_Plr.Visible=false;
8906 PlayerRobbingFrame_Robbing.Visible=false;
8907
8908
8909 PlayerRobbingDescriptionLabel.Text="You can run away or fight back, but it could cost your life!";
8910 PlayerRobbingGui.Enabled=true;
8911
8912
8913 BeingRobbed={timestamp=timestamp,perp=tab.perp};
8914 end,
8915 StopRobbingPlayer=function(victim)
8916
8917 if victim == player then
8918 -- If I'm the victim
8919
8920 BeingRobbed=nil;
8921 else
8922 RobbingPlayer=nil;
8923 end
8924
8925 PlayerRobbingGui.Enabled=false;
8926
8927 end
8928})
8929
8930
8931
8932--
8933
8934
8935
8936
8937return module
8938
8939
8940--[[
8941 InputHandler
8942 A wrapper on top of ContextActionService.
8943 Handles creation and usage of actions that are bound to KeyBindings present in the KeyBindings module
8944
8945
8946 class InputHandler {
8947 boolean InputHandler.Enabled
8948 Tells whether InputHandler will handle any input at the moment
8949
8950 void InputHandler:ReloadKeyBindings()
8951 Reloads keybindings from KeyBindings module, applying all changes
8952
8953 void InputHandler:RegisterActions({ (string actionName) = (table actionData), ... })
8954 Registers new actions. Names must be unique.
8955
8956 struct actionData = {
8957 string keyBinding, // See KeyBindings module for available keyBindings
8958 [number priority = 1000,]
8959 function<UserInputState inputState, Input input, string actionName> handler,
8960 [boolean enableByDefault]
8961 }
8962
8963 If handler function returns true, it will act as if Enum.ContextActionResult.Pass was returned
8964
8965 void InputHandler:ToggleAction(string actionName[, boolean forceState])
8966 Toggle an Action by name. Works identically to Action:Toggle()
8967
8968 void InputHandler:EnableAction(string actionName)
8969 Enable an Action by name. Works identically to Action:Enable()
8970
8971 void InputHandler:DisableAction(string actionName)
8972 Disable an Action by name. Works identically to Action:Disable()
8973
8974 void InputHandler:Enable()
8975 Enables the InputHandler
8976
8977 void InputHandler:Disable()
8978 Disables the InputHandler
8979
8980 void InputHandler:ReloadActions()
8981 Reloads all enabled Actions
8982
8983 Action InputHandler:GetAction(string actionName)
8984 Returns a registered action by name
8985 }
8986
8987 class Action {
8988 boolean Action.Enabled
8989 string Action.Name
8990 number Action.Priority
8991 function Action.Handler
8992 KeyBinding Action.KeyBinding
8993
8994 void Action:Enable()
8995 Enables the Action
8996
8997 void Action:Disable()
8998 Disables the Action
8999
9000 void Action:Toggle([boolean forceEnabled])
9001 Toggles the Action
9002 }
9003
9004 class KeyBinding {
9005 Action[] KeyBinding.Bound
9006 Instance<UserInputType,KeyCode>[] KeyBinding.InputTypes
9007 }
9008
9009
9010--]]
9011
9012-- Services
9013
9014local ReplicatedStorage = game:GetService("ReplicatedStorage")
9015local ContextAction = game:GetService("ContextActionService")
9016local UserInputService = game:GetService("UserInputService");
9017local CollectionService = game:GetService("CollectionService");
9018
9019-- Modules
9020
9021local LoadModule = require(ReplicatedStorage.Modules.Load)
9022
9023local KeyBindingsModule = LoadModule("KeyBindings")
9024
9025-- Variables
9026
9027local Action = {}
9028local ActionMeta = { __index = Action }
9029local KeyBindings = {}
9030local RegisteredActions = {}
9031
9032local module = {
9033 Enabled = false
9034}
9035
9036
9037
9038
9039
9040
9041--[=[
9042 Detect User Input changed
9043 (Keyboard vs Gamepad)
9044
9045 Tells UI to update accordingly
9046
9047--]=]
9048
9049local LastInputType;
9050
9051
9052local function ChangeInput(inputtype)
9053 local tagged = CollectionService:GetTagged("XboxUI");
9054
9055 local enabled = inputtype == "Xbox";
9056
9057 for _,v in pairs(tagged) do
9058 if v:isA("ScreenGui") then
9059 v.Enabled=enabled;
9060 else
9061 v.Visible=enabled;
9062 end
9063 end
9064end
9065
9066local function InputChanged(inputObject)
9067 local InputType = "PC";
9068
9069
9070 if inputObject.UserInputType.Name:match("Gamepad") or inputObject.KeyCode.Name:match("Thumbstick") then
9071 InputType = "Xbox";
9072 elseif inputObject.UserInputType.Name:match("Mouse") or inputObject.UserInputType == Enum.UserInputType.Keyboard then
9073 InputType = "PC";
9074 end
9075
9076 if InputType then
9077 if InputType ~= module.LastInputType then
9078 ChangeInput(InputType);
9079 end
9080 end
9081
9082 module.LastInputType=InputType;
9083end
9084
9085
9086UserInputService.InputBegan:connect(InputChanged);
9087UserInputService.InputChanged:connect(InputChanged);
9088
9089
9090
9091
9092
9093--
9094
9095
9096
9097function module:ReloadKeyBindings()
9098 for name,bindings in pairs(KeyBindingsModule) do
9099 local data = KeyBindings[name]
9100
9101 if not data then
9102 data = {
9103 Bound = {}
9104 }
9105
9106 KeyBindings[name] = data
9107 end
9108
9109
9110 local inputTypes = {}
9111 local filters = {}
9112
9113 for _,v in pairs(type(bindings) == "table" and bindings or {bindings}) do
9114 if typeof(v) == "table" then
9115 local inputType, filter = v[1], v[2]
9116
9117 inputTypes[#inputTypes + 1] = inputType
9118
9119 local list = filters[inputType]
9120 if not list then
9121 list = {filter}
9122 filters[inputType] = list
9123 elseif type(list) == "table" then
9124 list[#list + 1] = filter
9125 end
9126 else
9127 filters[v] = true
9128 inputTypes[#inputTypes + 1] = v
9129 end
9130 end
9131
9132 data.InputFilters = filters
9133 data.InputTypes = inputTypes
9134 end
9135
9136 self:ReloadActions()
9137end
9138
9139function module:ReloadActions()
9140 for name,action in pairs(RegisteredActions) do
9141 if action.Enabled then
9142 action:Disable()
9143 action:Enable()
9144 end
9145 end
9146end
9147
9148function module:RegisterActions(map)
9149 for name,args in pairs(map) do
9150 if RegisteredActions[name] then error(("Action %s already exists"):format(name)) end
9151
9152 local kbName, priority, fn, enabled = unpack(args)
9153 if type(priority) == "function" then
9154 priority, fn, enabled = nil, priority, fn
9155 end
9156
9157 local keyBinding = KeyBindings[kbName]
9158 if not keyBinding then error(("KeyBinding %s does not exist"):format(kbName)) end
9159
9160 local action = {
9161 KeyBinding = keyBinding,
9162 Name = name,
9163 Priority = priority or 1000,
9164 Function = fn,
9165 Enabled = false
9166 }
9167
9168 action.Handler = function(...) return action:HandleInput(...) end
9169
9170 setmetatable(action, ActionMeta)
9171
9172 keyBinding.Bound[#keyBinding.Bound + 1] = action
9173 RegisteredActions[name] = action
9174
9175 if not (enabled == false) then action:Enable() end
9176 end
9177end
9178
9179function module:GetAction(name)
9180 return RegisteredActions[name]
9181end
9182
9183function module:ToggleAction(name, enabled)
9184 local action = RegisteredActions[name]
9185
9186 if not action then
9187 error(("Action '%s' doesn't exist"):format(name))
9188 end
9189
9190 action:Toggle(enabled)
9191end
9192
9193function module:EnableAction(...)
9194 for _,name in pairs({...}) do
9195 local action = RegisteredActions[name]
9196
9197 if not action then
9198 error(("Action '%s' doesn't exist"):format(name))
9199 end
9200
9201 action:Enable()
9202 end
9203end
9204
9205function module:DisableAction(...)
9206 for _,name in pairs({...}) do
9207 local action = RegisteredActions[name]
9208
9209 if not action then
9210 error(("Action '%s' doesn't exist"):format(name))
9211 end
9212
9213 action:Disable()
9214 end
9215end
9216
9217function module:Enable()
9218 self.Enabled = true
9219 self:ReloadActions()
9220end
9221
9222function module:Disable()
9223 self.Enabled = false
9224 self:ReloadActions()
9225end
9226
9227
9228
9229function Action:HandleInput(actionName, inputState, input)
9230 local filters = self.KeyBinding.InputFilters
9231 local typeFilters = filters[input.UserInputType]
9232 local keyFilters = filters[input.KeyCode]
9233 local valid = typeFilters == true or keyFilters == true
9234
9235 if not valid and typeFilters then
9236 for _,filter in pairs(typeFilters) do
9237 if filter(input) then
9238 valid = true
9239 break
9240 end
9241 end
9242 end
9243
9244 if not valid and keyFilters then
9245 for _,filter in pairs(keyFilters) do
9246 if filter(input) then
9247 valid = true
9248 break
9249 end
9250 end
9251 end
9252
9253 if not valid then
9254 return Enum.ContextActionResult.Pass
9255 end
9256
9257 local result = self.Function(inputState, input, actionName)
9258
9259 if result == true then
9260 result = Enum.ContextActionResult.Pass
9261 end
9262
9263 return result
9264end
9265
9266function Action:Enable()
9267 if not self.Enabled then
9268 self.Enabled = true
9269 if module.Enabled then
9270 ContextAction:BindActionAtPriority(self.Name, self.Handler, false, self.Priority, unpack(self.KeyBinding.InputTypes))
9271 end
9272 end
9273end
9274
9275function Action:Disable()
9276 if self.Enabled then
9277 self.Enabled = false
9278 ContextAction:UnbindAction(self.Name)
9279 end
9280end
9281
9282function Action:Toggle(forceState)
9283 local enabled = not self.Enabled
9284 if forceState ~= nil then enabled = not not forceState end
9285
9286 if self.Enabled ~= enabled then
9287 if enabled then
9288 self:Enable()
9289 else
9290 self:Disable()
9291 end
9292 end
9293end
9294
9295
9296module:ReloadKeyBindings()
9297
9298return module
9299
9300 --[[
9301 KeyBindings
9302 A list of UserInputTypes and KeyCodes associated with every keybinding
9303 This table is used by InputHandler when InputHandler:ReloadKeyBindings() is called
9304--]]
9305
9306return {
9307 ActivateItem = { Enum.UserInputType.MouseButton1 },
9308
9309 ActivateItemSec = { Enum.UserInputType.MouseButton2 },
9310
9311 Jump = {Enum.KeyCode.Space,Enum.KeyCode.ButtonA},
9312
9313 Interact = { Enum.KeyCode.E },
9314
9315 InteractCancel = { Enum.KeyCode.F },
9316
9317 Sprint = { Enum.KeyCode.LeftShift,Enum.KeyCode.ButtonL3},
9318
9319 ToggleInventory={Enum.KeyCode.B,Enum.KeyCode.ButtonB},
9320 ToggleHorses={Enum.KeyCode.H},
9321
9322 L1={Enum.KeyCode.ButtonL1},
9323
9324 R1={Enum.KeyCode.ButtonR1},
9325
9326 LoosenLasso = { { Enum.UserInputType.MouseWheel, function(input) return input.Position.Z > 0 end } },
9327
9328 TightenLasso = { { Enum.UserInputType.MouseWheel, function(input) return input.Position.Z < 0 end } },
9329
9330 Reload = { Enum.KeyCode.R },
9331 FanGun = { Enum.KeyCode.F },
9332 ChangeShoulder = { Enum.KeyCode.X },
9333 ChangeCamera = { Enum.KeyCode.V },
9334
9335 DebugTeleport = { Enum.KeyCode.T },
9336 DebugPoop = { Enum.KeyCode.M }
9337}
9338
9339local module = {}
9340
9341local UserInputService = game:GetService("UserInputService");
9342local ReplicatedStorage = game:GetService("ReplicatedStorage");
9343
9344-- Modules
9345
9346local LoadModule = require(ReplicatedStorage.Modules.Load)
9347local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
9348
9349local InputHandler = LoadModule("InputHandler");
9350local PlayerCharacter = LoadModule("PlayerCharacter");
9351local UI_Utils = LoadModule("UI_Utils");
9352local UIObjects = LoadModule("UIObjects");
9353local ToolTips = LoadModule("ToolTips");
9354local Inventory = LoadModule("Inventory",true);
9355
9356local SharedData = LoadSharedModule("SharedData");
9357--
9358
9359local Players = game:GetService("Players");
9360local Player = Players.LocalPlayer;
9361
9362local Hotbar = UIObjects.Hotbar.Hotbar.Frame;
9363
9364local HotbarSlot = {};
9365local HotbarSlots = {};
9366
9367
9368local IndexSelected = 1;
9369
9370
9371function HotbarSlot.new(slot)
9372 local self = setmetatable({},{__index=HotbarSlot});
9373 self.slot=slot;
9374 for _,v in pairs(slot:GetDescendants()) do
9375 self[v.Name]=v;
9376 end
9377
9378 self.nCTrimColOrg = slot.Number.CircleTrim_6px.ImageColor3
9379 self.nCColOrg = slot.Number.Circle_64px.ImageColor3
9380 self.nTxtColOrg = slot.Number.ValueText.TextColor3;
9381
9382 HotbarSlots[#HotbarSlots+1]=self;
9383 return self;
9384end
9385
9386
9387
9388function HotbarSlot:MouseDown()
9389 self.Frame.CornerFlat_24px.ImageColor3 = Color3.new(1,1,1);
9390end
9391
9392function HotbarSlot:MouseUp()
9393 self.Frame.CornerFlat_24px.ImageColor3 = Color3.fromRGB(70, 61, 56);
9394end
9395
9396
9397
9398
9399function HotbarSlot:Mouse2Down()
9400
9401
9402 if module.ActionTip then
9403 module:RemoveActionTip();
9404 end
9405
9406
9407 if not self:GetAssignedItem() then
9408 return;
9409 end
9410
9411
9412
9413 self:Hover();
9414
9415
9416 local tooltip = ToolTips.ActionTip.new(
9417 {
9418 Option1={text="Unequip Item",
9419 callback=function()
9420
9421 self:AssignItem(nil);
9422
9423 module:RemoveActionTip();
9424
9425 Inventory:Update();
9426
9427 end
9428 },
9429 Option2={text="Cancel",
9430 callback=function()
9431
9432 module:RemoveActionTip();
9433
9434 end
9435 }
9436 }
9437 );
9438
9439 local slot = self.slot;
9440
9441
9442 local framepos = slot.AbsolutePosition;
9443 local abssize = slot.AbsoluteSize;
9444
9445 framepos=UDim2.new(0,framepos.X+abssize.x/2,0,framepos.y+abssize.y*0.5);
9446
9447 tooltip:SetPosition(framepos);
9448 tooltip:SetTitle("");
9449 tooltip:SetDescription("");
9450
9451 module.ActionTip = {slot=self,tip=tooltip};
9452
9453end
9454
9455
9456function HotbarSlot:HoverLeave()
9457 self.Hovered=nil;
9458 self.Frame.CornerFlat_24px:TweenSize(UDim2.new(1,4,1,4),"Out","Quint",.2,true)
9459 self.Frame.CornerFlat_24px.Rotation = 0
9460 self.Number:TweenPosition(UDim2.new(.5,0,1,0),"In","Back",.1,true)
9461end
9462
9463function HotbarSlot:Hover()
9464 if module.ActionTip then
9465 return;
9466 end
9467
9468 self.Hovered=true;
9469 self.Frame.CornerFlat_24px:TweenSize(UDim2.new(.8,4,0.8,4),"In","Back",.1,true)
9470 self.Number:TweenPosition(UDim2.new(.5,0,1.3,0),"Out","Back",.1,true)
9471end
9472
9473function HotbarSlot:OnSelect() -- NOTE(AntiBoomz0r): Separated effects from :Select(), this is only called when the item is actually selected
9474 if module.Selected then
9475 module.Selected:OnDeselect()
9476 end
9477
9478 print(self, "Selected");
9479 local slot = self.slot;
9480
9481 self.Frame.CornerFlat_24px.ImageColor3 = Color3.new(1,1,1);
9482
9483 slot:TweenSize(UDim2.new(0,64+12,0,64+12),"Out","Quint",.1,true)
9484 slot.Number.CircleTrim_6px.ImageColor3 = Color3.fromRGB(49,49,49)
9485 slot.Number.Circle_64px.ImageColor3 = Color3.fromRGB(255,255,255)
9486 slot.Number.ValueText.TextColor3 = Color3.fromRGB(49,49,49)
9487
9488 module.Selected=self;
9489
9490 IndexSelected=slot.LayoutOrder;
9491end
9492
9493function HotbarSlot:Select()
9494 if module.Selected then
9495 module.Selected:Deselect()
9496 end
9497
9498 self:OnSelect()
9499
9500 if self.AssignedItem then
9501 PlayerCharacter:EquipItem(self.AssignedItem)
9502 end
9503end
9504
9505function HotbarSlot:OnDeselect() -- NOTE(AntiBoomz0r): Separated effects from :Deselect(), only called when actually deselected
9506 local slot = self.slot;
9507
9508 self.Frame.CornerFlat_24px.ImageColor3 = Color3.fromRGB(70, 61, 56);
9509
9510 slot:TweenSize(UDim2.new(0,64,0,64),"Out","Back",.1,true)
9511 slot.Number.CircleTrim_6px.ImageColor3 = self.nCTrimColOrg
9512 slot.Number.Circle_64px.ImageColor3 = self.nCColOrg
9513 slot.Number.ValueText.TextColor3 = self.nTxtColOrg;
9514
9515 module.Selected = nil;
9516end
9517
9518function HotbarSlot:Deselect()
9519 self:OnDeselect()
9520 PlayerCharacter:EquipItem(nil)
9521end
9522
9523
9524
9525function HotbarSlot:OnHovered()
9526 self.Frame.CornerFlat_24px.Rotation = self.Frame.CornerFlat_24px.Rotation + 1;
9527end
9528
9529function HotbarSlot:Activated()
9530
9531 module:RemoveActionTip();
9532
9533 if module.Selected == self then
9534 self:Deselect();
9535 else
9536 self:Select();
9537 end
9538end
9539
9540
9541
9542function HotbarSlot:ClearViewportFrame()
9543
9544 self.ViewportItem=nil;
9545
9546 for _,v in pairs(self.ViewportFrame:GetChildren()) do
9547 if not v:isA("UIScale") and not v:isA("ImageLabel") then
9548 v:Destroy();
9549 end
9550 end
9551end
9552
9553
9554function HotbarSlot:AssignItem(item)
9555 self:ClearViewportFrame();
9556
9557
9558 self.ViewportCamera=nil;
9559
9560 if item then
9561 local itemname = item.itemname;
9562
9563 if itemname then
9564 local data = UI_Utils.GetViewportFrameItem(itemname);
9565
9566 if data then
9567 local clone = data.model;
9568 local cam = data.cam;
9569
9570
9571 cam.Parent=self.ViewportFrame;
9572 clone.Parent=self.ViewportFrame;
9573
9574 self.ViewportFrame.BackgroundColor3 = Color3.new();
9575 self.ViewportItemCF = clone:GetPrimaryPartCFrame();
9576 self.ViewportItem = clone;
9577 self.ViewportFrame.CurrentCamera=cam;
9578 self.ViewportCamera=cam;
9579
9580 end
9581 end
9582 end
9583
9584 self.AssignedItem=item;
9585
9586end
9587
9588function HotbarSlot:GetAssignedItem()
9589 return self.AssignedItem;
9590end
9591
9592
9593local HotbarChildren = Hotbar:GetChildren();
9594for _,v in pairs(HotbarChildren) do
9595 if not v:isA("ImageButton") then
9596 table.remove(HotbarChildren,_);
9597 end
9598end
9599
9600table.sort(HotbarChildren,function(a,b)
9601 return a.LayoutOrder < b.LayoutOrder;
9602end)
9603
9604for i = 1,#HotbarChildren do
9605 local slot = HotbarChildren[i];
9606 if slot.Name == "HotbarSlot" then
9607 local item = HotbarSlot.new(slot);
9608 local mouseUpCon
9609
9610 slot.MouseButton2Down:connect(function()
9611 item:Mouse2Down();
9612 end)
9613 slot.MouseButton1Down:connect(function()
9614
9615 if module.ActionTip then
9616 return;
9617 end
9618
9619 item:MouseDown();
9620
9621 mouseUpCon = UserInputService.InputEnded:Connect(function(input)
9622 if input.UserInputType == Enum.UserInputType.MouseButton1 then
9623 mouseUpCon:Disconnect()
9624 mouseUpCon = nil
9625 item:MouseUp()
9626 end
9627 end)
9628 end)
9629 slot.MouseEnter:connect(function()
9630
9631 if module.ActionTip then
9632 return;
9633 end
9634
9635 item:Hover();
9636 end)
9637 slot.MouseLeave:connect(function()
9638
9639 if module.ActionTip then
9640 return;
9641 end
9642
9643 item:HoverLeave();
9644 end)
9645 slot.MouseButton1Up:connect(function()
9646 if mouseUpCon then
9647 mouseUpCon:Disconnect()
9648 mouseUpCon = nil
9649 end
9650
9651 if module.ActionTip then
9652 return;
9653 end
9654
9655 if not module:RecentlyRemovedTip() then
9656 item:Activated();
9657 end
9658 end)
9659 end
9660end
9661
9662
9663
9664local keycodes_to_num =
9665{
9666 {"One", "KeypadOne"},
9667 {"Two", "KeypadTwo"},
9668 {"Three", "KeypadThree"},
9669 {"Four", "KeypadFour"},
9670 {"Five", "KeypadFive"},
9671 {"Six", "KeypadSix"},
9672 {"Seven", "KeypadSeven"}
9673}
9674
9675
9676local function SelectSlotAtIndex(index)
9677 for _,slot in pairs(HotbarSlots) do
9678 if slot.slot.LayoutOrder == index then
9679 slot:Activated();
9680 break;
9681 end
9682 end
9683end
9684
9685UserInputService.InputBegan:connect(function(input, processed)
9686 if processed then
9687 return;
9688 end
9689 local keycode = input.KeyCode;
9690 local inputtype = input.UserInputType;
9691 for index = 1,#keycodes_to_num do
9692 local tab = keycodes_to_num[index];
9693 if keycode.Name == tab[1] or keycode.Name == tab[2] then
9694
9695 -- Ugly hack to make european chat hotkey not trigger
9696
9697 game:GetService("RunService").RenderStepped:Wait()
9698 if UserInputService:GetFocusedTextBox() then break end
9699
9700
9701 -- Activate slot
9702
9703 SelectSlotAtIndex(index)
9704 break
9705 end
9706 end
9707end)
9708
9709function module:DeselectAll()
9710 for _,v in pairs(HotbarSlots) do
9711 v:Deselect();
9712 v:HoverLeave();
9713 end
9714end
9715
9716
9717function module:RemoveActionTip()
9718 if module.ActionTip then
9719
9720 local tip = module.ActionTip.tip;
9721 local slot = module.ActionTip.slot;
9722 tip:Dispose();
9723 slot:HoverLeave();
9724 module.ActionTip=nil;
9725 module.LastRemovedTip=tick();
9726 end
9727end
9728
9729function module:RecentlyRemovedTip()
9730 return module.LastRemovedTip and tick() - module.LastRemovedTip < 0.15;
9731end
9732
9733
9734function module:AttemptToEquipInventoryItem(item)
9735
9736 local Full=true;
9737
9738 if self:ContainsItem(item) then
9739 return false;
9740 end
9741
9742 for i = 1,7 do
9743 local slot = HotbarSlots[i];
9744 local assigned = slot:GetAssignedItem();
9745 if not assigned then
9746
9747 slot:AssignItem(item);
9748
9749 Full=false;
9750 break;
9751 end
9752 end
9753
9754 if Full then
9755 return false;
9756 else
9757 return true;
9758 end
9759end
9760
9761function module:AttemptToUnequipInventoryItem(item)
9762
9763 local Found = false;
9764
9765
9766 for i = 1,7 do
9767 local slot = HotbarSlots[i];
9768 local assigned = slot:GetAssignedItem();
9769 if assigned and assigned == item then
9770
9771 slot:AssignItem(nil);
9772
9773 Found=true;
9774 break;
9775 end
9776 end
9777
9778 if Found then
9779 return true;
9780 else
9781 return false;
9782 end
9783
9784end
9785
9786function module:ContainsItem(item)
9787
9788 local contains = false;
9789
9790 for i = 1,7 do
9791 local slot = HotbarSlots[i];
9792 local assigned = slot:GetAssignedItem();
9793 if assigned then
9794
9795 if assigned == item then
9796 contains=true;
9797 break;
9798 end
9799 end
9800 end
9801 return contains;
9802end
9803
9804function module:UpdateSelectedItem()
9805-- local equippedItem = PlayerCharacter:GetEquippedItem()
9806-- local selectedItem = module.Selected and module.Selected:GetAssignedItem()
9807--
9808-- if selectedItem and selectedItem ~= equippedItem then
9809-- module.Selected:OnDeselect()
9810-- end
9811--
9812-- for i = 1,7 do
9813-- local slot = HotbarSlots[i]
9814-- local assigned = slot:GetAssignedItem()
9815--
9816-- print(assigned,equippedItem,equippedItem.itemname);
9817--
9818-- if assigned and assigned ~= equippedItem then
9819-- slot:OnSelect()
9820-- break
9821-- end
9822-- end
9823end
9824
9825
9826-- Register Input
9827
9828InputHandler:RegisterActions({
9829 HotbarRight = {"R1", function(state)
9830
9831 if state.Name ~= "Begin" then return end
9832
9833 IndexSelected=IndexSelected+1;
9834 if IndexSelected == 8 then
9835 IndexSelected=1;
9836 end
9837
9838 SelectSlotAtIndex(IndexSelected);
9839
9840 end, true},
9841
9842 HotbarLeft = {"L1", function(state)
9843
9844 if state.Name ~= "Begin" then return end
9845
9846 IndexSelected=IndexSelected-1;
9847 if IndexSelected == 0 then
9848 IndexSelected=7;
9849 end
9850
9851 SelectSlotAtIndex(IndexSelected);
9852
9853 end, true}
9854})
9855
9856
9857
9858function module:Update()
9859 for _,slot in pairs(HotbarSlots) do
9860
9861 local Hovered = slot.Hovered;
9862
9863 if slot.Hovered then
9864 slot:OnHovered();
9865
9866 local item = slot.ViewportItem;
9867 if item then
9868 item:SetPrimaryPartCFrame(item:GetPrimaryPartCFrame()*CFrame.Angles(0,math.rad(1),0));
9869 end
9870
9871
9872 elseif slot.LastHovered then
9873
9874 slot.Frame.CornerFlat_24px.Rotation = 0;
9875
9876 local item = slot.ViewportItem;
9877 local original = slot.ViewportItemCF;
9878 if item then
9879 item:SetPrimaryPartCFrame(original);
9880 end
9881
9882 end
9883
9884 slot.LastHovered=Hovered;
9885 end
9886end
9887
9888
9889
9890
9891return module
9892
9893
9894--[=[
9895 Used to handle core UI stuff
9896--]=]
9897
9898local module = {}
9899
9900local Players = game:GetService("Players");
9901local Player = Players.LocalPlayer;
9902
9903local CollectionService = game:GetService("CollectionService");
9904local UserInputService = game:GetService("UserInputService");
9905local ReplicatedStorage = game:GetService("ReplicatedStorage");
9906local CollectionService = game:GetService("CollectionService");
9907
9908local LoadModule = require(ReplicatedStorage.Modules.Load)
9909local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
9910
9911local InputHandler = LoadModule("InputHandler");
9912local KeyBindings = LoadModule("KeyBindings");
9913
9914local SharedData = LoadSharedModule("SharedData");
9915local Network = LoadSharedModule("Network");
9916
9917local Mathf = LoadModule("Mathf");
9918local UI = LoadModule("UI",true);
9919local UIObjects = LoadModule("UIObjects");
9920local Hotbar = LoadModule("Hotbar",true);
9921local Inventory = LoadModule("Inventory",true);
9922local Horses = LoadModule("Horses",true);
9923local PlayerCharacter = LoadModule("PlayerCharacter");
9924
9925local Cursor = LoadModule("Cursor",true);
9926local WildLife = LoadModule("WildLife",true);
9927local AnimalRiding = LoadModule("AnimalRiding",true);
9928local RobbingItems = LoadModule("RobbingItems",true);
9929
9930local SideBar = UIObjects.SideBar;
9931local SideBarFrame = SideBar.Frame;
9932local PlayerInfo = UIObjects.PlayerInfo;
9933local Bucks = PlayerInfo.PlayerDataFrame.Bucks;
9934
9935
9936--[=[
9937 ActionBillboards are objects that, if nearby, fire the nearest action on Keybinds.ActionKeyPressed
9938--]=]
9939
9940
9941local ActionBillboard={};
9942local ActionBillboards={};
9943
9944
9945local function ActionOrePickup(obj)
9946 local object = obj.obj;
9947
9948 local pickedup = object:FindFirstChild("PickedUp");
9949 if pickedup then
9950 if pickedup.Value == false then
9951 pickedup.Value=true;
9952 ActionBillboards[obj]=nil;
9953 Network:FireServer("PickupItem",object);
9954 end
9955 end
9956end
9957local function ActionRobBank(obj)
9958 local gui = obj.obj;
9959 Network:FireServer("RobBank",gui);
9960end
9961
9962local function ActionEnterSeat(obj)
9963 local part = obj.part;
9964 print("enter seat: ",part);
9965 if part then
9966 Network:FireServer("Sit",part);
9967 end
9968end
9969
9970
9971local function GetWagon(obj)
9972 for _,v in pairs(workspace.WagonSpawns:GetChildren()) do
9973 if obj.part:isDescendantOf(v) then
9974 return v;
9975 end
9976 end
9977 for _,v in pairs(workspace.Wagons:GetChildren()) do
9978 if obj.part:isDescendantOf(v) then
9979 return v;
9980 end
9981 end
9982end
9983
9984local function EnterWagonAction(obj)
9985 local wagon = GetWagon(obj);
9986 if wagon then
9987 Network:FireServer("EnterWagon",wagon);
9988 end
9989end
9990
9991local function ActionPickupRobbingItem(obj)
9992 local part = obj.part;
9993 RobbingItems:DropRobbingItem();
9994 PlayerCharacter.AnimationHandler:PlayTrack("PickupItem");
9995 Network:FireServer("PickupRobbingItem",part);
9996end
9997
9998local BillboardActions=
9999{
10000 EnterDriver={action=EnterWagonAction,duration=0},
10001 EnterSeat={action=ActionEnterSeat,duration=0},
10002 RobBankMoney={action=ActionRobBank,duration=2},
10003 PickupMoneybag={action=ActionPickupRobbingItem,duration=0};
10004}
10005
10006
10007local function GetActionCallback(action)
10008 local tab = BillboardActions[action];
10009 if tab then
10010 return tab.action,tab.duration;
10011 end
10012end
10013
10014local backColor = Color3.fromRGB(186, 169, 109)
10015local barColor = Color3.fromRGB(62, 62, 62)
10016
10017
10018
10019function ActionBillboard:ResetActionGui()
10020 if self.rightCircle then
10021 self.rightCircle.ImageColor3=barColor;
10022 self.leftCircle.ImageColor3=barColor;
10023 self.leftCircle.Rotation=180;
10024 self.rightCircle.Rotation=0;
10025 self.backCircle.ImageColor3=backColor;
10026 self.framescale.Scale=1;
10027 end
10028 if ActivatingBillboard == self then
10029 ActivatingBillboard=nil;
10030 end
10031end
10032
10033function ActionBillboard.new(obj,callback)
10034
10035 local self = setmetatable({},{__index=ActionBillboard});
10036
10037 coroutine.wrap(function()
10038
10039
10040 local owner = obj:WaitForChild("Owner").Value;
10041
10042 if owner and owner ~= Player then -- I don't own this billboard
10043 return;
10044 end
10045
10046 self.obj=obj;
10047 self.part = obj.Parent;
10048
10049
10050
10051
10052 self.Billboards={};
10053 self.ObjectDistance=obj:WaitForChild("DisplayDistance").Value;
10054
10055 self.disabledval=obj:WaitForChild("Disabled");
10056 self.disabledval.Changed:connect(function(newval)
10057 self.disabled=newval;
10058 end)
10059 self.disabled=self.disabledval.Value;
10060
10061 obj.ZIndexBehavior=Enum.ZIndexBehavior.Sibling;
10062
10063 if BillboardActions[obj.Name] then
10064 local frame = obj:WaitForChild("Frame");
10065 self.framescale = Instance.new("UIScale",frame);
10066 local rightFrame = frame:WaitForChild("RightFrame");
10067 local leftFrame = frame:WaitForChild("LeftFrame");
10068 local rightCircle = rightFrame:WaitForChild("RightCircle");
10069 local leftCircle = leftFrame:WaitForChild("LeftCircle");
10070 local frontCircle = frame:WaitForChild("FrontCircle");
10071 local backCircle = frame:WaitForChild("BackCircle");
10072 local iconkey = frontCircle:WaitForChild("Icon"):WaitForChild("ValueText");
10073 local holdframe = frontCircle:WaitForChild("Hold");
10074
10075 self.iconkey=iconkey;
10076 self.frontCircle=frontCircle;
10077 self.leftCircle=leftCircle;
10078 self.rightCircle=rightCircle;
10079 self.leftFrame=leftFrame;
10080 self.rightFrame=rightFrame;
10081 self.holdframe=holdframe;
10082 self.backCircle=backCircle;
10083
10084 self:ResetActionGui();
10085 end
10086
10087
10088 self.callback,self.actiontime = GetActionCallback(obj.Name);
10089
10090
10091 if self.holdframe then
10092 self.holdframe.Visible = self.actiontime ~= 0;
10093 end
10094
10095 ActionBillboards[obj]=self;
10096
10097 return self;
10098 end)()
10099end
10100function ActionBillboard:Dispose()
10101 if ActivatingBillboard == self then
10102 ActivatingBillboard=nil;
10103 end
10104 if self.obj then
10105 ActionBillboards[self.obj]=nil;
10106 end
10107end
10108
10109function ActionBillboard:ActivateStart()
10110
10111 local OnVehicle = WildLife:GetOnVehicle();
10112
10113 local can_do_action = not OnVehicle and not PlayerCharacter.IsCarrying and not PlayerCharacter:IsRagdolled();
10114 if can_do_action and self.actiontime then
10115 self.TimeActivated=tick();
10116 ActivatingBillboard=self;
10117 self.framescale.Scale=1.1;
10118 end
10119end
10120function ActionBillboard:ActivateEnd()
10121 if self.leftCircle then
10122 self:ResetActionGui();
10123 end
10124end
10125
10126function ActionBillboard:GetDistance()
10127 if PlayerCharacter.RootPart then
10128 local pos = self.part.Position+self.obj.StudsOffsetWorldSpace;
10129 return (PlayerCharacter.RootPart.Position-pos).magnitude;
10130 end
10131end
10132
10133local function GetClosestActionBillboard()
10134 local lastdist = 999;
10135 local closest;
10136 for _,obj in pairs(ActionBillboards) do
10137 local dist = obj:GetDistance();
10138 if dist and dist <= obj.ObjectDistance and obj.callback then
10139 if dist < lastdist then
10140 closest=obj;
10141 lastdist=dist;
10142 end
10143 end
10144 end
10145
10146
10147 return closest;
10148end
10149
10150
10151local function OnBillboardBlockAdded(obj)
10152 if obj:isA("BillboardGui") and obj:isDescendantOf(workspace) then
10153 ActionBillboard.new(obj);
10154 end
10155end
10156
10157local function OnBillboardBlockRemoved(obj)
10158 if ActionBillboards[obj] then
10159 ActionBillboards[obj]:Dispose();
10160 end
10161end
10162
10163coroutine.wrap(function()
10164 CollectionService:GetInstanceAddedSignal("BillboardBlock"):connect(OnBillboardBlockAdded);
10165 for _,v in pairs(CollectionService:GetTagged("BillboardBlock")) do
10166 OnBillboardBlockAdded(v);
10167 end
10168
10169 CollectionService:GetInstanceRemovedSignal("BillboardBlock"):connect(OnBillboardBlockRemoved);
10170end)()
10171
10172InputHandler:RegisterActions({
10173 InteractBillboards = {"Interact", function(state)
10174
10175 if state.Name == "Begin" then
10176 if PlayerCharacter:IsRagdolled() then return true end
10177
10178 local closest = GetClosestActionBillboard();
10179
10180 if closest then
10181 closest:ActivateStart();
10182 end
10183 else
10184 if ActivatingBillboard then
10185 ActivatingBillboard:ActivateEnd();
10186 end
10187 end
10188
10189 return true
10190 end,true},
10191})
10192
10193--
10194
10195
10196
10197for _,v in pairs(SideBarFrame:GetChildren()) do
10198 if v:isA("ImageButton") then
10199 v.MouseEnter:connect(function()
10200 v.UIScale.Scale=1.1;
10201 end)
10202 v.MouseLeave:connect(function()
10203 v.UIScale.Scale=1
10204 end)
10205 v.MouseButton1Click:connect(function()
10206 if v.Name == "Inventory" then
10207 Inventory:Toggle();
10208 elseif v.Name == "Horses" then
10209 Horses:Toggle();
10210 end
10211 end)
10212 end
10213end
10214
10215
10216local function UpdateCursor(updateTime)
10217 local mouseposition = UserInputService:GetMouseLocation();
10218 local mousex,mousey = mouseposition.x,mouseposition.y;
10219
10220 Cursor:SetPosition(mousex,mousey);
10221end
10222
10223
10224function module:OnControlLost()
10225 Hotbar:DeselectAll();
10226 if Inventory.Opened == true then
10227 Inventory:Close();
10228 end
10229end
10230
10231function module:UpdateEquippedItem(itemName)
10232 Hotbar:UpdateSelectedItem()
10233end
10234
10235
10236local LastBillboardDisplayUpdate=0;
10237
10238module.Update = function(updateTime)
10239 UI.Update(updateTime);
10240 Hotbar.Update(updateTime);
10241 Inventory.UpdateInventory(updateTime);
10242 Horses.UpdateHorses(updateTime);
10243 AnimalRiding.Update(updateTime);
10244 UpdateCursor(updateTime);
10245
10246 --[=[
10247 Update ActionBillboards
10248 --]=]
10249
10250 local rootpart = PlayerCharacter.RootPart;
10251 if not rootpart then
10252 return;
10253 end
10254 local rootpos = rootpart.Position;
10255
10256 local candisplay = not PlayerCharacter:IsRagdolled() and not WildLife:GetOnVehicle() and not PlayerCharacter:GetSeated();
10257
10258 if tick()-LastBillboardDisplayUpdate >= 0.15 then
10259 LastBillboardDisplayUpdate=tick();
10260
10261
10262 for _,obj in pairs(ActionBillboards) do
10263
10264 local displaying = (obj:GetDistance() <= obj.ObjectDistance and obj.disabled == false) and true or false;
10265
10266 if not candisplay then
10267 displaying=false;
10268 end
10269
10270 if displaying == false then
10271
10272 obj.obj.Enabled=false;
10273 if ActivatingBillboard == obj then
10274 obj:ResetActionGui();
10275 end
10276 elseif displaying == true then
10277
10278 obj.obj.Enabled=true;
10279
10280 end
10281
10282 end
10283 end
10284
10285 if ActivatingBillboard then
10286
10287 if ActivatingBillboard.disabled == true then
10288 ActivatingBillboard:ResetActionGui();
10289 else
10290 if ActivatingBillboard.actiontime then
10291 if ActivatingBillboard.TimeActivated then
10292 local elapsed = tick()-ActivatingBillboard.TimeActivated;
10293 local alpha = math.clamp(elapsed/ActivatingBillboard.actiontime,0,1);
10294
10295
10296 if alpha < 0.5 then
10297 ActivatingBillboard.rightCircle.ImageColor3 = barColor
10298 ActivatingBillboard.leftCircle.Rotation, ActivatingBillboard.rightCircle.Rotation = 180, alpha*360
10299 else
10300 ActivatingBillboard.rightCircle.ImageColor3 = backColor;
10301 ActivatingBillboard.leftCircle.Rotation, ActivatingBillboard.rightCircle.Rotation = alpha*360, 0;
10302
10303 if alpha >= 1 then
10304 if ActivatingBillboard.callback then
10305 ActivatingBillboard:callback();
10306 end
10307 ActivatingBillboard:ResetActionGui();
10308 end
10309 end
10310
10311 end
10312 end
10313 end
10314 end
10315
10316
10317end
10318
10319module.UpdatePlayerData = function(data)
10320 Inventory:Update();
10321 Horses:Update();
10322
10323 if LastPlayerData then
10324 if LastPlayerData.Bucks < data.Bucks then
10325 local clientsounds = shared.ClientSounds;
10326 if clientsounds then
10327 clientsounds.GainCurrency:Play();
10328 end
10329 elseif LastPlayerData.Bucks > data.Bucks then
10330 local clientsounds = shared.ClientSounds;
10331 if clientsounds then
10332 clientsounds.LoseCurrency:Play();
10333 end
10334 end
10335 end
10336
10337 Bucks.Text=data.Bucks;
10338
10339 LastPlayerData=data;
10340end
10341module.PickRole = function()
10342 UI.PickRole();
10343end
10344
10345
10346
10347
10348return module
10349
10350
10351--[=[
10352 Handles the inventory
10353--]=]
10354
10355local Inventory = {};
10356
10357
10358-- Services
10359
10360local Players = game:GetService("Players");
10361local ReplicatedStorage = game:GetService("ReplicatedStorage");
10362local GuiService = game:GetService("GuiService");
10363local UserInputService = game:GetService("UserInputService");
10364local TweenService = game:GetService("TweenService");
10365
10366--
10367
10368
10369-- Modules
10370
10371local LoadModule = require(ReplicatedStorage.Modules.Load)
10372local UI_Utils = LoadModule("UI_Utils");
10373local UIObjects = LoadModule("UIObjects");
10374local ToolTips = LoadModule("ToolTips");
10375local InputHandler = LoadModule("InputHandler",true);
10376local Hotbar = LoadModule("Hotbar");
10377
10378local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
10379local SharedData = LoadSharedModule("SharedData");
10380local Network = LoadSharedModule("Network");
10381--
10382
10383
10384
10385local Player = Players.LocalPlayer;
10386
10387local InventoryUI = UIObjects.Menus.Backpack;
10388local OpenSound = InventoryUI.Open;
10389local CloseSound = InventoryUI.Close;
10390local SideBar = UIObjects.SideBar;
10391local SideBarFrame = SideBar.Frame;
10392local InventoryNew = SideBarFrame.Inventory.New;
10393local InventoryNewTxt = InventoryNew.ValueText;
10394local InventoryNewScale = InventoryNew.UIScale;
10395
10396
10397for _,v in pairs(InventoryUI:GetDescendants()) do
10398 Inventory[v.Name]=v;
10399end
10400
10401
10402local ScrollingFrame = Inventory.ScrollingFrame;
10403
10404local GridSlot = ScrollingFrame.GridSlot:clone();
10405ScrollingFrame.GridSlot:Destroy();
10406
10407local PurchaseGridFrames =
10408{
10409 ScrollingFrame.GridSlot_Purchase1,
10410 ScrollingFrame.GridSlot_Purchase2,
10411 ScrollingFrame.GridSlot_Purchase3,
10412 ScrollingFrame.GridSlot_PurchaseButton
10413}
10414
10415
10416
10417--[=[
10418 InventorySlot
10419--]=]
10420
10421
10422
10423local InventorySlot = {};
10424local InventorySlots = {};
10425function InventorySlot.new()
10426 local self = setmetatable({},{__index=InventorySlot});
10427
10428 local newslot = GridSlot:clone();
10429 newslot.Parent=ScrollingFrame;
10430
10431
10432 self.slot = newslot;
10433
10434 InventorySlots[#InventorySlots+1]=self;
10435
10436 self.ViewportFrame=newslot.ViewportFrame;
10437
10438 self.EquippedImage=newslot.EquippedImage;
10439
10440
10441
10442 newslot.MouseEnter:connect(function()
10443
10444 if Inventory.ActionTip then
10445 return;
10446 end
10447
10448 self:Hover();
10449 end)
10450 newslot.MouseLeave:connect(function()
10451
10452 if Inventory.ActionTip then
10453 return;
10454 end
10455
10456 self:HoverEnd();
10457 end)
10458 newslot.MouseButton1Down:connect(function()
10459 self:Activated();
10460 end)
10461 newslot.MouseButton2Down:connect(function()
10462 self:Activated();
10463 end)
10464
10465
10466 return self;
10467end
10468
10469local ActionTipCancel =
10470{
10471 text="Cancel",
10472 callback=function()
10473 Inventory:RemoveActionTip();
10474 end
10475}
10476
10477
10478function InventorySlot:DropItem()
10479 if shared.PlayerData then
10480 table.remove(shared.PlayerData.Inventory,self.slot.LayoutOrder);
10481 end
10482 self:AssignItem();
10483 Inventory:Update();
10484
10485 Network:FireServer("DropItem",self.slot.LayoutOrder);
10486end
10487
10488function InventorySlot:ActionTipEquippable(AssignedItem,Equipped)
10489
10490 local tooltip;
10491
10492 if not Equipped then
10493 tooltip = ToolTips.ActionTip.new(
10494 {
10495
10496
10497 Option1={text="Equip Item",
10498 callback=function()
10499 Inventory:RemoveActionTip();
10500
10501 local success = Hotbar:AttemptToEquipInventoryItem(AssignedItem);
10502
10503 if success then
10504 self.EquippedImage.Visible=true;
10505 end
10506
10507 end},
10508 Option2=ActionTipCancel
10509 }
10510 );
10511
10512 else
10513
10514 tooltip = ToolTips.ActionTip.new(
10515 {
10516
10517
10518 Option1={text="Unequip Item",
10519 callback=function()
10520 Inventory:RemoveActionTip();
10521
10522 local success = Hotbar:AttemptToUnequipInventoryItem(AssignedItem);
10523
10524 self.EquippedImage.Visible=false;
10525
10526 end},
10527
10528 Option2=ActionTipCancel
10529 }
10530 );
10531 end
10532
10533 return tooltip;
10534end
10535
10536function InventorySlot:ActionTipOre(AssignedItem)
10537
10538 local tooltip;
10539
10540 tooltip = ToolTips.ActionTip.new(
10541 {
10542
10543
10544 Option1={text="Drop Item",
10545 callback=function()
10546 Inventory:RemoveActionTip();
10547
10548 self:DropItem();
10549
10550 end},
10551
10552 Option2=ActionTipCancel
10553 }
10554 );
10555
10556 return tooltip;
10557end
10558
10559
10560
10561function InventorySlot:Activated()
10562
10563
10564
10565 local slot = self.slot;
10566
10567 local AssignedItem = self:GetAssignedItem();
10568
10569 self:RemoveHoverTip();
10570
10571 if Inventory.ActionTip then
10572 Inventory:RemoveActionTip();
10573 end
10574
10575
10576
10577
10578
10579 if AssignedItem and not Inventory.ActionTip then
10580
10581 local itemname = AssignedItem.itemname;
10582
10583 local PlayerItem = SharedData.PlayerItems[itemname];
10584
10585
10586 if PlayerItem then
10587
10588 local Equipped = Hotbar:ContainsItem(AssignedItem);
10589
10590 local tooltip;
10591
10592
10593
10594
10595 if self.LastActivated and tick() - self.LastActivated < .25 then
10596
10597 if Equipped then
10598 local success = Hotbar:AttemptToUnequipInventoryItem(AssignedItem);
10599
10600 self.EquippedImage.Visible=false;
10601 else
10602 local success = Hotbar:AttemptToEquipInventoryItem(AssignedItem);
10603
10604 if success then
10605 self.EquippedImage.Visible=true;
10606 end
10607 end
10608
10609 return;
10610
10611 end
10612
10613 local tooltip;
10614
10615 if PlayerItem.Type == "Ore" then
10616 tooltip = self:ActionTipOre();
10617 else
10618 tooltip = self:ActionTipEquippable(AssignedItem,Equipped);
10619 end
10620
10621
10622
10623
10624
10625 local framepos = slot.AbsolutePosition;
10626 local abssize = slot.AbsoluteSize;
10627 framepos=UDim2.new(0,framepos.X+abssize.x/2,0,framepos.y+abssize.y);
10628 tooltip:SetPosition(framepos);
10629 tooltip:SetTitle(itemname);
10630 tooltip:SetDescription(PlayerItem.Description);
10631
10632 Inventory.ActionTip = {slot=self,tip=tooltip};
10633
10634
10635 self:Hover();
10636 end
10637 end
10638
10639
10640 self.LastActivated=tick();
10641
10642end
10643
10644function InventorySlot:RemoveHoverTip()
10645 if self.HoverTip then
10646 self.HoverTip:Dispose();
10647 end
10648end
10649
10650function InventorySlot:Hover()
10651 self.Hovered=true;
10652
10653 self.slot.BackgroundColor3 = Color3.fromRGB(199, 166, 125);
10654 self.ViewportFrame.UIScale.Scale=1.4;
10655
10656
10657 Inventory.ItemText.Text = self:GetAssignedItem() and self:GetAssignedItem().itemname or "";
10658
10659 local newslot = self.slot;
10660
10661 local AssignedItem = self:GetAssignedItem();
10662
10663
10664 if AssignedItem and not Inventory.ActionTip then
10665
10666 local itemname = AssignedItem.itemname;
10667
10668 local PlayerItem = SharedData.PlayerItems[itemname];
10669
10670 if PlayerItem then
10671 self.HoverTip = ToolTips.TitleTip.new();
10672
10673 local framepos = newslot.AbsolutePosition;
10674 local abssize = newslot.AbsoluteSize;
10675 framepos=UDim2.new(0,framepos.X+abssize.X/2,0,framepos.y+abssize.Y);
10676
10677 self.HoverTip:SetPosition(framepos);
10678 self.HoverTip:SetTitle(itemname);
10679 self.HoverTip:SetDescription(PlayerItem.Description);
10680 end
10681 end
10682
10683
10684end
10685function InventorySlot:HoverEnd()
10686 self.Hovered=nil;
10687
10688 self.slot.BackgroundColor3 = Color3.fromRGB(63, 52, 39);
10689 self.ViewportFrame.UIScale.Scale=1;
10690
10691 self:RemoveHoverTip();
10692end
10693
10694function InventorySlot:ClearViewportFrame()
10695
10696 self.ViewportItem=nil;
10697
10698 for _,v in pairs(self.ViewportFrame:GetChildren()) do
10699 if not v:isA("UIScale") and not v:isA("ImageLabel") then
10700 v:Destroy();
10701 end
10702 end
10703end
10704
10705function InventorySlot:AssignToIndex(n)
10706 self.slot.LayoutOrder=n;
10707end
10708function InventorySlot:AssignItem(item)
10709
10710
10711 self:ClearViewportFrame();
10712
10713 self.AssignedItem=item;
10714
10715 local itemname = item.itemname;
10716
10717 self.ViewportCamera=nil;
10718
10719
10720 local data = UI_Utils.GetViewportFrameItem(itemname);
10721
10722 if data then
10723 local clone = data.model;
10724 local cam = data.cam;
10725
10726 cam.Parent=self.ViewportFrame;
10727 clone.Parent=self.ViewportFrame;
10728
10729 self.ViewportFrame.BackgroundColor3 = data.viewportcolor or Color3.new();
10730 self.ViewportItemCF = clone:GetPrimaryPartCFrame();
10731 self.ViewportItem = clone;
10732 self.ViewportFrame.CurrentCamera=cam;
10733 self.ViewportCamera=cam;
10734 end
10735
10736 if Hotbar:ContainsItem(item) then
10737 self.EquippedImage.Visible=true;
10738 end
10739
10740end
10741function InventorySlot:GetAssignedItem()
10742 return self.AssignedItem;
10743end
10744function InventorySlot:Dispose()
10745 if self.HoverTip then
10746 self.HoverTip:Dispose();
10747 end
10748end
10749
10750
10751
10752
10753
10754--
10755
10756
10757function Inventory:RemoveActionTip()
10758 if Inventory.ActionTip then
10759
10760 local tip = Inventory.ActionTip.tip;
10761 local slot = Inventory.ActionTip.slot;
10762 tip:Dispose();
10763 slot:HoverEnd();
10764 Inventory.ActionTip=nil;
10765 end
10766end
10767
10768function Inventory:Clear()
10769
10770 Inventory:RemoveActionTip();
10771
10772 for _,slot in pairs(InventorySlots) do
10773 slot:ClearViewportFrame();
10774 slot:Dispose();
10775 end
10776 InventorySlots={};
10777 for _,v in pairs(ScrollingFrame:GetChildren()) do
10778 if v.Name == "GridSlot" then
10779 v:Destroy();
10780 end
10781 end
10782end
10783
10784
10785function Inventory:Update()
10786
10787
10788 self:Clear();
10789
10790 local playerdata = shared.PlayerData;
10791 print("Slots: ",playerdata.InventorySlots);
10792
10793 self.SlotsPopulated=0;
10794 self.TotalSlots=playerdata.InventorySlots;
10795
10796 for index = 1,playerdata.InventorySlots do
10797
10798 local playerdataitem = playerdata.Inventory[index];
10799
10800 local slot = InventorySlot.new();
10801 slot:AssignToIndex(index);
10802
10803 local inventoryitem = playerdataitem
10804 if inventoryitem then
10805 self.SlotsPopulated=self.SlotsPopulated+1;
10806 slot:AssignItem(playerdataitem);
10807 end
10808 end
10809
10810 self.NumSlots.Text=self.SlotsPopulated.."/"..self.TotalSlots;
10811
10812
10813 for i = 1,4 do
10814 PurchaseGridFrames[i].LayoutOrder=self.TotalSlots+i;
10815 end
10816
10817 if self.LastSlotsPopulated then
10818 if self.SlotsPopulated>self.LastSlotsPopulated and self.Opened == false then
10819
10820 if not self.NewItems then
10821 self.NewItems=0;
10822 end
10823
10824 self.NewItems = self.NewItems + self.SlotsPopulated-self.LastSlotsPopulated;
10825 end
10826 end
10827
10828 self.LastSlotsPopulated=self.SlotsPopulated;
10829end
10830
10831
10832local InventoryUIScale=InventoryUI:WaitForChild("UIScale");
10833
10834function Inventory:Open()
10835
10836 self:Clear();
10837
10838 self:Update();
10839
10840 self.Opened=true;
10841
10842 self.NewItems=nil;
10843
10844 InventoryUIScale.Scale=0.5;
10845 InventoryUI.Visible=true;
10846
10847 if InputHandler.LastInputType == "Xbox" then
10848 GuiService.SelectedObject=InventorySlots[1].slot;
10849 end
10850
10851 local scaletween = TweenService:Create(InventoryUIScale,TweenInfo.new(.1),{Scale=1});
10852 InventoryUI:TweenPosition(UDim2.new(0.5,0,0.5,0),"Out","Linear",.1,true,nil);
10853 scaletween:Play();
10854
10855 OpenSound:Play();
10856end
10857function Inventory:Close()
10858
10859 self:Clear();
10860
10861 self.Opened=false;
10862
10863 InventoryUI.Visible=false;
10864
10865
10866 if InputHandler.LastInputType == "Xbox" then
10867 GuiService.SelectedObject=nil;
10868 end
10869
10870 InventoryUI.Position=UDim2.new(.5,0,.6,0);
10871
10872 CloseSound:Play();
10873end
10874function Inventory:Toggle()
10875 if self.Opened then
10876 Inventory:Close()
10877 else
10878 Inventory:Open()
10879 end
10880end
10881
10882
10883
10884
10885Inventory.UpdateInventory = function(updateTime)
10886 for _,slot in pairs(InventorySlots) do
10887 if slot.Hovered then
10888 local item = slot.ViewportItem;
10889 if item then
10890 item:SetPrimaryPartCFrame(item:GetPrimaryPartCFrame()*CFrame.Angles(0,math.rad(1),0));
10891 end
10892 else
10893 if slot.LastHovered then
10894 local item = slot.ViewportItem;
10895 local original = slot.ViewportItemCF;
10896 if item then
10897 item:SetPrimaryPartCFrame(original);
10898 end
10899 end
10900 end
10901
10902 slot.LastHovered=slot.Hovered;
10903 end
10904
10905
10906 local NewItems = Inventory.NewItems;
10907
10908 if NewItems then
10909 InventoryNewTxt.Text=NewItems;
10910 if not Inventory.LastNewItems then
10911 InventoryNew.Visible=true;
10912 Inventory.NewItemsTween=TweenService:Create(InventoryNewScale,TweenInfo.new(.1,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,true,0),{Scale=1.5});
10913 Inventory.NewItemsTween:Play();
10914 end
10915 if Inventory.NewItemsTween and Inventory.NewItemsTween.PlaybackState == Enum.PlaybackState.Completed then
10916 InventoryNewScale.Scale=math.sin(tick()*2.5)*0.15+1.15;
10917 end
10918 else
10919 if Inventory.LastNewItems then
10920 if Inventory.NewItemsTween then
10921 Inventory.NewItemsTween:Cancel();
10922 end
10923 InventoryNewScale.Scale=1;
10924 InventoryNew.Visible=false;
10925 end
10926 end
10927 Inventory.LastNewItems=NewItems;
10928end
10929
10930
10931-- Register Input
10932
10933InputHandler:RegisterActions({
10934 ToggleInventory = {"ToggleInventory", function(state)
10935
10936 if state.Name ~= "Begin" then return end
10937
10938 Inventory:Toggle();
10939
10940 end, true}
10941})
10942
10943
10944
10945
10946return Inventory;
10947
10948
10949--[=[
10950 Module responsible for controlling and adding tooltips, either prompts or actions for items
10951--]=]
10952
10953local Players = game:GetService("Players");
10954local Player = Players.LocalPlayer;
10955
10956local ReplicatedStorage = game:GetService("ReplicatedStorage");
10957local LoadModule = require(ReplicatedStorage.Modules.Load);
10958local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
10959local UIObjects = LoadModule("UIObjects");
10960
10961local module = {ActionTip={},TitleTip={}}
10962
10963
10964local BaseTitle = {};
10965
10966setmetatable(module.TitleTip,{__index=BaseTitle});
10967setmetatable(module.ActionTip,{__index=BaseTitle});
10968
10969
10970
10971
10972
10973local ToolTips = UIObjects.ToolTips;
10974local ProgressTip = ToolTips.ToolTip_Progress;
10975local ProgressTitle = ProgressTip.ToolTipName;
10976local ProgressFill = ProgressTip.Bar.ValueFrame;
10977local ProgressTxt = ProgressTip.Bar.ValueText;
10978
10979
10980local Progress = {};
10981module.Progress=Progress;
10982
10983--[=[
10984 Progress tip
10985--]=]
10986
10987
10988function Progress:SetVisible(b)
10989 ProgressTip.Visible=b;
10990end
10991function Progress:SetTitle(txt)
10992 ProgressTitle.Text=txt;
10993end
10994function Progress:SetPercent(perc)
10995 ProgressFill:TweenSize(UDim2.new(perc,0,1,0),"Out","Linear",.2,true,nil);
10996 ProgressTxt.Text=math.floor(perc*100).."%";
10997end
10998
10999
11000--
11001
11002
11003function module.ActionTip.new(tab)
11004 local self = setmetatable({},{__index=module.ActionTip});
11005 local frame = ToolTips.ToolTip_Action:clone();
11006 frame.Parent=ToolTips;
11007 frame.Visible=true;
11008
11009 self.frame=frame;
11010 for _,v in pairs(frame:GetDescendants()) do
11011 self[v.Name]=v;
11012 end
11013
11014 local OptionList = self.OptionList;
11015 for option,data in pairs(tab) do
11016 local button = OptionList:FindFirstChild(option);
11017 if button then
11018 button.Visible=true;
11019 button.ValueText.Text=data.text;
11020
11021 button.MouseEnter:connect(function()
11022 button.BackgroundTransparency=.5;
11023 end)
11024 button.MouseLeave:connect(function()
11025 button.BackgroundTransparency=1;
11026 end)
11027 button.MouseButton1Down:connect(function()
11028 data.callback();
11029 self:Dispose();
11030 end)
11031 end
11032 end
11033 return self;
11034end
11035
11036
11037
11038function module.TitleTip.new(tab)
11039 local self = setmetatable({},{__index=module.TitleTip});
11040 local frame = ToolTips.ToolTip_Title:clone();
11041 frame.Parent=ToolTips;
11042 frame.Visible=true;
11043
11044 self.frame=frame;
11045 for _,v in pairs(frame:GetDescendants()) do
11046 self[v.Name]=v;
11047 end
11048
11049 return self;
11050end
11051
11052
11053function BaseTitle:SetTitle(txt)
11054 self.ToolTipName.Text=txt;
11055end
11056function BaseTitle:SetDescription(txt)
11057 self.ToolTipDescription.Text=txt;
11058end
11059function BaseTitle:SetPosition(pos)
11060 self.frame.Position=pos;
11061end
11062function BaseTitle:Dispose()
11063 self.frame:Destroy();
11064end
11065
11066
11067
11068
11069return module
11070
11071
11072local module = {}
11073
11074local Player = game:GetService("Players").LocalPlayer;
11075local mouse = Player:GetMouse();
11076
11077
11078local ReplicatedStorage = game:GetService("ReplicatedStorage");
11079local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
11080local SharedData = LoadSharedModule("SharedData");
11081
11082function module.GetMouseLocationInParent(parent)
11083 return UDim2.new(0,mouse.X-parent.AbsolutePosition.X,0,mouse.Y-parent.AbsolutePosition.Y);
11084end
11085
11086
11087
11088function module.GetViewportFrameItem(itemname)
11089
11090 itemname = itemname or "";
11091 local Resources = ReplicatedStorage.Resources;
11092 local ViewportScenes = Resources.ViewportScenes;
11093 local ViewportItem = ViewportScenes:FindFirstChild(itemname);
11094 if ViewportItem then
11095
11096 local PlayerItem = SharedData.PlayerItems[itemname];
11097
11098 if PlayerItem then
11099 local camcf = ViewportItem.CameraCFrame.Value;
11100 local fov = ViewportItem.FOV.Value;
11101
11102 local cam = Instance.new("Camera");
11103 cam.CFrame=camcf;
11104 cam.FieldOfView=fov;
11105
11106 local clone = ViewportItem:clone();
11107
11108 local centerp = Instance.new("Part");
11109 centerp.Anchored=true;
11110 centerp.Transparency=1;
11111 centerp.Name="ViewportCenter";
11112
11113 centerp.CFrame=CFrame.new(clone:GetModelCFrame().p);
11114 centerp.Parent=clone;
11115
11116 clone.PrimaryPart=centerp;
11117
11118 return {model=clone,cam=cam,viewportcolor=PlayerItem.ViewportColor};
11119 end
11120 end
11121
11122end
11123
11124return module
11125
11126
11127--[=[
11128 Module for image cursors
11129--]=]
11130
11131local cursor = {};
11132
11133local ReplicatedStorage = game:GetService("ReplicatedStorage");
11134local LoadModule = require(ReplicatedStorage.Modules.Load);
11135local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
11136
11137local UIObjects = LoadModule("UIObjects");
11138
11139local CursorImages = LoadModule("CursorImages");
11140
11141local player = game:GetService("Players").LocalPlayer;
11142
11143
11144local cursorgui = UIObjects.Cursor;
11145local frame = cursorgui:WaitForChild("Frame");
11146
11147
11148
11149local imageframe = frame:WaitForChild("Image");
11150
11151local UserInputService = game:GetService("UserInputService");
11152
11153
11154
11155
11156function cursor:SetCursorType(Type)
11157
11158 if Type == "Image" then
11159 imageframe.Visible=true;
11160 UserInputService.MouseIconEnabled=false;
11161 else
11162 UserInputService.MouseIconEnabled=true;
11163 imageframe.Visible=false;
11164 end
11165end
11166
11167
11168function cursor:SetCursorImage(name)
11169
11170 local tab = CursorImages[name];
11171 imageframe.Image=tab.image;
11172 imageframe.Size=UDim2.new(0,tab.size,0,tab.size);
11173
11174end
11175
11176
11177cursor:SetCursorType("Free");
11178
11179
11180--[=[
11181 Used internally by UIHandler
11182--]=]
11183
11184function cursor:SetPosition(x,y)
11185 frame.Position=UDim2.new(0,x,0,y-36);
11186end
11187
11188
11189
11190
11191return cursor;
11192
11193return
11194{
11195 Dot={image="rbxassetid://2583764938",size=8},
11196 Pickaxe={image="rbxassetid://2674109067",size=32}
11197}
11198
11199--[=[
11200 Handles the Horse Menu
11201--]=]
11202
11203local Horses = {};
11204
11205
11206-- Services
11207
11208local Players = game:GetService("Players");
11209local ReplicatedStorage = game:GetService("ReplicatedStorage");
11210local UserInputService = game:GetService("UserInputService");
11211local TweenService = game:GetService("TweenService");
11212
11213
11214
11215-- Modules
11216
11217local LoadModule = require(ReplicatedStorage.Modules.Load)
11218local InputHandler = LoadModule("InputHandler",true);
11219local PlayerCharacter = LoadModule("PlayerCharacter");
11220local UIObjects = LoadModule("UIObjects");
11221
11222local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load)
11223local SharedData = LoadSharedModule("SharedData");
11224local Network = LoadSharedModule("Network");
11225--
11226
11227local cam = workspace.CurrentCamera;
11228local Player = Players.LocalPlayer;
11229
11230local HorsesUI = UIObjects.Menus.Horses;
11231local OpenSound = HorsesUI.Open;
11232local CloseSound = HorsesUI.Close;
11233local HorsesUIScale = HorsesUI.UIScale;
11234
11235local SideBar = UIObjects.SideBar;
11236local SideBarFrame = SideBar.Frame;
11237local HorsesNew = SideBarFrame.Horses.New;
11238local HorsesNewTxt = HorsesNew.ValueText;
11239local HorsesNewScale = HorsesNew.UIScale;
11240
11241
11242for _,v in pairs(HorsesUI:GetDescendants()) do
11243 Horses[v.Name]=v;
11244end
11245
11246local SlotTemplate = Horses.SlotTemplate:clone();
11247Horses.SlotTemplate:Destroy();
11248
11249
11250local HorseSlot = {};
11251local HorseSlots = {};
11252
11253
11254function HorseSlot.new(horse,index)
11255 local self = setmetatable({},{__index=HorseSlot});
11256
11257 local slot = SlotTemplate:clone();
11258 slot.Parent=Horses.ScrollingFrame;
11259
11260 slot.LayoutOrder=index;
11261
11262 self.slot=slot;
11263
11264 for _,v in pairs(slot:GetDescendants()) do
11265 self[v.Name]=v;
11266 end
11267
11268
11269 local BreedInfo = SharedData.HorseBreedInfo[horse.Breed];
11270 local breedname = BreedInfo.BreedDisplay or horse.Breed;
11271
11272 local Stars = BreedInfo.Stars;
11273
11274
11275
11276 local StarsFrame = self.Stars;
11277 local staricon = StarsFrame.Star:clone();
11278 for i = 1,Stars-1 do
11279 staricon:clone().Parent=StarsFrame;
11280 end
11281
11282
11283 local CoatData = horse.CoatData or SharedData.HorseBreedColors[horse.Breed];
11284
11285 local BridleColor = Color3.new();
11286 local EyeColor = CoatData.Eye1;
11287 local FurColor = CoatData.Mane;
11288 local SkinColor = CoatData.Head;
11289
11290 local StatPopulateColor = Color3.fromRGB(171, 34, 34);
11291 local StatsFrame = self.StatsFrame;
11292 for i,v in pairs(StatsFrame:GetChildren()) do
11293 if v:isA("Frame") then
11294 local frame = v.Frame;
11295 local value = BreedInfo[v.Name];
11296 for i = 1,value do
11297 frame[i].BackgroundColor3=StatPopulateColor;
11298 end
11299 end
11300 end
11301
11302 self.Bridle.ImageColor3=BridleColor;
11303 self.Eye.ImageColor3=EyeColor;
11304 self.Fur.ImageColor3=FurColor;
11305 self.Skin.ImageColor3=SkinColor;
11306
11307 self.AssignedHorse=horse;
11308
11309 self.Nickname.Text=horse.Nickname;
11310 self.BreedName.Text="("..breedname..")";
11311
11312 local called = horse.Called == true;
11313 if called then
11314 self.ActionType="Uncall";
11315 else
11316 self.ActionType="Call";
11317 end
11318
11319 self.ActionText.Text = self.ActionType;
11320
11321 --ToDo
11322
11323 -- Color to horse colors(Bridle,Eye,Fur,Skin)
11324 -- Add Stars from Rating
11325
11326
11327 --
11328
11329
11330 local ActionButton = self.Action;
11331
11332 local ActionButtonFrame = ActionButton.ButtonFrame;
11333 local ActionColorReleased_Green = Color3.fromRGB(81, 208, 62);
11334 local ActionColorPressed_Green = Color3.fromRGB(60, 154, 46);
11335
11336 local ActionColorReleased_Red = Color3.fromRGB(208, 57, 57);
11337 local ActionColorPressed_Red = Color3.fromRGB(153, 42, 42);
11338
11339 self.ActionButtonFrame=ActionButtonFrame;
11340
11341 if self.ActionType == "Call" then
11342 self.ActionColorReleased=ActionColorReleased_Green;
11343 self.ActionColorPressed=ActionColorPressed_Green;
11344 else
11345 self.ActionColorReleased=ActionColorReleased_Red;
11346 self.ActionColorPressed=ActionColorPressed_Red;
11347 end
11348
11349 ActionButtonFrame.BackgroundColor3=self.ActionColorReleased;
11350
11351 ActionButton.MouseEnter:connect(function()
11352 self:OnActionHover();
11353 end)
11354 ActionButton.MouseLeave:connect(function()
11355 self:OnActionLeft();
11356 end)
11357 ActionButton.MouseButton1Down:connect(function()
11358 self:OnActionPressed();
11359 end)
11360 ActionButton.MouseButton1Up:connect(function()
11361 self:OnActionReleased();
11362 end)
11363
11364 HorseSlots[#HorseSlots+1]=self;
11365 return self;
11366end
11367function HorseSlot:OnActionPressed()
11368 self.ActionScale.Scale=.9;
11369 self.ActionButtonFrame.BackgroundColor3=self.ActionColorPressed;
11370end
11371function HorseSlot:OnActionReleased()
11372 self.ActionScale.Scale=1;
11373 self.ActionButtonFrame.BackgroundColor3=self.ActionColorReleased;
11374
11375 if self.ActionType then
11376 if self.ActionType == "Call" then
11377 PlayerCharacter:Whistle();
11378 Network:FireServer("CallAnimal",self.slot.LayoutOrder,cam.CFrame);
11379 else
11380 Network:FireServer("UncallAnimal");
11381 end
11382 end
11383end
11384function HorseSlot:OnActionHover()
11385 self.ActionScale.Scale=1.1;
11386end
11387function HorseSlot:OnActionLeft()
11388 self.ActionScale.Scale=1;
11389end
11390
11391
11392
11393function Horses:Clear()
11394
11395 HorseSlots={};
11396 for _,v in pairs(Horses.ScrollingFrame:GetChildren()) do
11397 if v:isA("Frame") then
11398 v:Destroy();
11399 end
11400 end
11401end
11402
11403
11404function Horses:Update()
11405
11406
11407 self:Clear();
11408
11409 local playerdata = shared.PlayerData;
11410
11411 local numhorses = #playerdata.Horses;
11412 print("Owned Horses: ",numhorses);
11413
11414 self.NumOwned.Text=numhorses.." Owned";
11415
11416 self.SlotsPopulated=0;
11417 self.TotalSlots=numhorses;
11418
11419 for index = 1,numhorses do
11420 local horse = playerdata.Horses[index];
11421 if horse then
11422 local slot = HorseSlot.new(horse,index);
11423 self.SlotsPopulated=self.SlotsPopulated+1;
11424 end
11425 end
11426
11427 if self.LastSlotsPopulated then
11428 if self.SlotsPopulated>self.LastSlotsPopulated and self.Opened == false then
11429
11430 if not self.NewItems then
11431 self.NewItems=0;
11432 end
11433
11434 self.NewItems = self.NewItems + self.SlotsPopulated-self.LastSlotsPopulated;
11435 end
11436 end
11437
11438 self.LastSlotsPopulated=self.SlotsPopulated;
11439end
11440
11441
11442function Horses:Open()
11443
11444 self:Update();
11445
11446 self.Opened=true;
11447
11448 self.NewItems=nil;
11449
11450 HorsesUIScale.Scale=0.5;
11451 HorsesUI.Visible=true;
11452
11453 local scaletween = TweenService:Create(HorsesUIScale,TweenInfo.new(.1),{Scale=1});
11454 HorsesUI:TweenPosition(UDim2.new(0.2,0,0.5,0),"Out","Linear",.1,true,nil);
11455 scaletween:Play();
11456
11457 OpenSound:Play();
11458end
11459function Horses:Close()
11460
11461 self:Clear();
11462
11463 self.Opened=false;
11464
11465 HorsesUI.Visible=false;
11466
11467
11468 HorsesUI.Position=UDim2.new(.2,0,.6,0);
11469
11470 CloseSound:Play();
11471end
11472
11473function Horses:Toggle()
11474 if self.Opened then
11475 Horses:Close()
11476 else
11477 Horses:Open()
11478 end
11479end
11480
11481function Horses:UpdateHorses()
11482 local NewItems = Horses.NewItems;
11483
11484 if NewItems then
11485 HorsesNewTxt.Text=NewItems;
11486 if not Horses.LastNewItems then
11487 HorsesNew.Visible=true;
11488 Horses.NewItemsTween=TweenService:Create(HorsesNewScale,TweenInfo.new(.1,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,true,0),{Scale=1.5});
11489 Horses.NewItemsTween:Play();
11490 end
11491 if Horses.NewItemsTween and Horses.NewItemsTween.PlaybackState == Enum.PlaybackState.Completed then
11492 HorsesNewScale.Scale=math.sin(tick()*2.5)*0.15+1.15;
11493 end
11494 else
11495 if Horses.LastNewItems then
11496 if Horses.NewItemsTween then
11497 Horses.NewItemsTween:Cancel();
11498 end
11499 HorsesNewScale.Scale=1;
11500 HorsesNew.Visible=false;
11501 end
11502 end
11503 Horses.LastNewItems=NewItems;
11504end
11505
11506
11507
11508-- Register Input
11509
11510InputHandler:RegisterActions({
11511 ToggleHorses = {"ToggleHorses", function(state)
11512
11513 if state.Name ~= "Begin" then return end
11514
11515 Horses:Toggle();
11516
11517 end, true}
11518})
11519
11520
11521
11522
11523return Horses;
11524
11525
11526local module = {}
11527
11528--[=[
11529 Services
11530--]=]
11531
11532local Players = game:GetService("Players");
11533local ReplicatedStorage = game:GetService("ReplicatedStorage");
11534local TweenService = game:GetService("TweenService");
11535--
11536
11537local LoadModule = require(ReplicatedStorage.Modules.Load);
11538local WildLife = LoadModule("WildLife",true);
11539local UIObjects = LoadModule("UIObjects");
11540local Mathf = LoadModule("Mathf");
11541
11542local Player = Players.LocalPlayer;
11543
11544local AnimalRidingGui = UIObjects.AnimalRiding
11545
11546
11547local SpurKick = AnimalRidingGui.SpurKick;
11548local BoostAdded = AnimalRidingGui.BoostAdded;
11549
11550local AnimalRidingFrame = AnimalRidingGui.Frame;
11551
11552local BoostIcon = {};
11553local BoostIcons={};
11554function BoostIcon.new(obj)
11555 local self = setmetatable({},{__index=BoostIcon});
11556 self.frame=obj;
11557 self.icon=obj.ImageLabel;
11558 self.enabled=false;
11559 self.lastenabled=false;
11560
11561 BoostIcons[#BoostIcons+1]=self;
11562 return self;
11563end
11564function BoostIcon:Exit()
11565 if self.tween then
11566 self.tween:Cancel();
11567 end
11568 if self.icontween then
11569 self.icontween:Cancel();
11570 end
11571
11572 local objtweeninfo = TweenInfo.new(.25,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,false,0);
11573
11574 local icontweeninfo = TweenInfo.new(.15,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,true,0);
11575 self.icon.Rotation=0;
11576 self.frame.Size=UDim2.new(0.25,0,1,0);
11577 self.tween = TweenService:Create(self.frame,objtweeninfo,{Size=UDim2.new(0.2,0,0.2,0)});
11578
11579 self.icontween = TweenService:Create(self.icon,icontweeninfo,{Rotation=25});
11580
11581 self.tween:Play();
11582 self.icontween:Play();
11583 self.tween.Completed:connect(function(state)
11584 if state == Enum.PlaybackState.Completed then
11585 self.frame.Visible=false;
11586 end
11587 end)
11588end
11589function BoostIcon:Enter(maxboosts)
11590
11591 BoostAdded.Pitch = Mathf.Lerp(1.1,1.4,Mathf.PercentBetween(self.frame.LayoutOrder,1,maxboosts));
11592 BoostAdded:Play();
11593
11594 if self.tween then
11595 self.tween:Cancel();
11596 end
11597 if self.icontween then
11598 self.icontween:Cancel();
11599 end
11600
11601 self.icon.Rotation=0;
11602 self.frame.Visible=true;
11603
11604 local objtweeninfo = TweenInfo.new(.15,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,false,0);
11605
11606 local icontweeninfo = TweenInfo.new(.25,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,true,0);
11607
11608 self.tween = TweenService:Create(self.frame,objtweeninfo,{Size=UDim2.new(0.2,0,1,0)});
11609
11610 self.icontween = TweenService:Create(self.icon,icontweeninfo,{Rotation=-25});
11611
11612 self.tween:Play();
11613 self.icontween:Play();
11614
11615end
11616
11617
11618for i = 1,5 do
11619 local icon = AnimalRidingFrame:FindFirstChild(i);
11620 BoostIcon.new(icon);
11621end
11622
11623
11624function module:SpurKickSound()
11625 SpurKick:Play();
11626end
11627
11628function module:GetRidingAnimal()
11629 local RidingAnimal = WildLife:GetRidingAnimal();
11630
11631 if not RidingAnimal then
11632 local getcontrolling = WildLife:GetControllingAnimals();
11633 if #getcontrolling>0 then
11634 _,RidingAnimal=next(getcontrolling);
11635 end
11636 end
11637 return RidingAnimal;
11638end
11639
11640
11641function module:UpdateAnimalBoosts()
11642
11643
11644 local RidingAnimal = self:GetRidingAnimal();
11645
11646 if RidingAnimal then
11647
11648
11649
11650 for i = 1,5 do
11651 local icon = BoostIcons[i];
11652 if icon then
11653
11654 if i <= RidingAnimal.MaxBoosts then
11655 icon.enabled = RidingAnimal.Boosts >= i;
11656 else
11657 icon.enabled = false;
11658 end
11659
11660 if not icon.enabled then
11661 if icon.lastenabled then
11662 icon:Exit();
11663 end
11664 else
11665 if not icon.lastenabled then
11666 icon:Enter(RidingAnimal.MaxBoosts);
11667 end
11668 end
11669
11670 icon.lastenabled=icon.enabled;
11671 end
11672 end
11673 end
11674end
11675
11676function module.Update(updateTime)
11677
11678 module:UpdateAnimalBoosts();
11679
11680
11681 local RidingAnimal = module:GetRidingAnimal();
11682
11683 AnimalRidingGui.Enabled = RidingAnimal and not RidingAnimal.Taming
11684end
11685
11686
11687return module
11688
11689
11690--[=[
11691 Handles references to all instances in PlayerGui, without needing to wait for PlayerGui to load
11692 Also makes it not necessary to use WaitForChild for ui stuff
11693--]=]
11694
11695local module = {}
11696
11697local ReplicatedStorage = game:GetService("ReplicatedStorage")
11698local Players = game:GetService("Players")
11699
11700local Player = Players.LocalPlayer
11701local Objects = {}
11702
11703
11704for _,gui in pairs(ReplicatedStorage.Resources.StarterGui:GetChildren()) do
11705 local clone = gui:Clone()
11706
11707 module[gui.Name] = clone
11708 Objects[gui.Name] = clone
11709end
11710
11711
11712coroutine.wrap(function()
11713 local playerGui = Player:WaitForChild("PlayerGui")
11714
11715 for _,gui in pairs(Objects) do
11716 gui.Parent = playerGui
11717 end
11718end)()
11719
11720
11721return module
11722
11723--[=[
11724 Module used to register and fire bindable events
11725--]=]
11726
11727local module = {}
11728
11729local Events = {};
11730function module:RegisterEvent(name,fn)
11731 if Events[name] then
11732 warn("Event already registered!");
11733 return;
11734 else
11735
11736 local bindable = Instance.new("BindableEvent");
11737 bindable.Event:connect(fn);
11738 Events[name]=bindable;
11739 end
11740end
11741function module:FireEvent(name,args)
11742 local bindable = Events[name];
11743 if bindable then
11744 bindable:Fire(args);
11745 end
11746end
11747
11748return module
11749
11750
11751--[=[
11752 Client module for all things Mining
11753--]=]
11754
11755
11756local module = {}
11757
11758local ReplicatedStorage = game:GetService("ReplicatedStorage");
11759local CollectionService = game:GetService("CollectionService");
11760
11761local LoadModule = require(ReplicatedStorage.Modules.Load);
11762local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
11763local Network = LoadSharedModule("Network");
11764
11765local PlayerCharacter = LoadModule("PlayerCharacter",true);
11766
11767local SharedUtils = LoadSharedModule("SharedUtils");
11768local SharedData = LoadSharedModule("SharedData");
11769
11770local Camera = LoadModule("Camera");
11771local ToolTips = LoadModule("ToolTips");
11772local FX = LoadModule("FX");
11773
11774
11775
11776local OreDeposit = {};
11777local OreDeposits = {};
11778
11779function OreDeposit.new(obj,deposit)
11780 local self = setmetatable({},{__index=OreDeposit});
11781
11782 local DepositInfo = obj:WaitForChild("DepositInfo");
11783 local OreRemaining = DepositInfo.OreRemaining;
11784 local Progress = DepositInfo.Progress;
11785 local MaxHealth = DepositInfo.MaxHealth;
11786
11787 self.OreRemaining=OreRemaining;
11788 self.Progress=Progress;
11789 self.MaxHealth=MaxHealth;
11790
11791 self.Progress:GetPropertyChangedSignal("Value"):connect(function()
11792 self:UpdateProgress();
11793 end)
11794
11795 self.obj=obj;
11796 self.depositname=deposit;
11797 self.primarypart = obj.PrimaryPart;
11798
11799 OreDeposits[obj]=self;
11800 return self;
11801end
11802function OreDeposit:UpdateProgress()
11803 if module.MiningDeposit == self then
11804 local progress = math.clamp(self.Progress.Value/self.MaxHealth.Value,0,1);
11805
11806 local deposit = self.depositname;
11807 ToolTips.Progress:SetTitle(deposit.." Deposit");
11808 ToolTips.Progress:SetPercent(progress);
11809 ToolTips.Progress:SetVisible(true);
11810
11811 end
11812end
11813function OreDeposit:GetDistance()
11814 if PlayerCharacter.RootPart then
11815 local dist = (PlayerCharacter.RootPart.Position - self.primarypart.Position).magnitude;
11816 return dist;
11817 end
11818end
11819
11820
11821for _,v in pairs(SharedData.OreDeposits) do
11822
11823 for i,k in pairs(CollectionService:GetTagged(v)) do
11824 OreDeposit.new(k,v);
11825 end
11826
11827 CollectionService:GetInstanceAddedSignal(v):connect(function(obj)
11828 OreDeposit.new(obj,v);
11829 end)
11830end
11831
11832
11833function module:HitDeposit(parent,pos,norm)
11834 FX:OreHit(parent,pos,norm);
11835 Camera:Vibrate(math.rad(.3),.2,0.05)
11836
11837
11838 local depositobj = OreDeposits[parent];
11839
11840 if depositobj then
11841 self.MiningDeposit=depositobj;
11842 depositobj:UpdateProgress();
11843
11844 Network:FireServer("MineDeposit",parent,pos,norm);
11845 end
11846
11847end
11848
11849function module:Update(updateTime)
11850 local MiningDeposit = self.MiningDeposit;
11851 if MiningDeposit then
11852 local dist = MiningDeposit:GetDistance();
11853 if not dist or (dist and dist > 15) then
11854 self.MiningDeposit=nil;
11855 ToolTips.Progress:SetVisible(false);
11856 end
11857 end
11858end
11859
11860
11861return module
11862
11863
11864--[[
11865 Camera
11866 Handles camera stuff
11867--]]
11868
11869-- Services
11870
11871local ReplicatedStorage = game:GetService("ReplicatedStorage")
11872local UserInputService = game:GetService("UserInputService")
11873local Players = game:GetService("Players")
11874local UserGameSettings = UserSettings():GetService("UserGameSettings")
11875
11876-- Modules
11877
11878local LoadModule = require(ReplicatedStorage.Modules.Load)
11879
11880local PlayerCharacter = LoadModule("PlayerCharacter", true)
11881local InputHandler = LoadModule("InputHandler")
11882local Mathf = LoadModule("Mathf")
11883local Utils = LoadModule("Utils")
11884local WildLife = LoadModule("WildLife",true);
11885
11886-- Variables
11887
11888local Camera = workspace.CurrentCamera
11889local Ignore = workspace.Ignore
11890
11891local ThirdPersonOffset = Vector3.new(2,3,10)
11892local FirstPersonOffset = Vector3.new(0,0.5,0)
11893local MinAngleX = math.rad(-80)
11894local MaxAngleX = math.rad(80)
11895local GamepadDeadZone = 0.22
11896
11897local CurrentCameraType = "Free"
11898local Shoulder = "Right"
11899local IsFirstPerson = false
11900
11901local gAngleX, gAngleY = 0, 0
11902local Recoil = 0
11903local MouseDelta
11904
11905local gVibration = 0
11906local vibration = 0
11907local vibTime = 1
11908local vibSmooth = 0.1
11909local vibStart = tick()
11910
11911local gKnock = Vector3.new()
11912local cKnock = Vector3.new()
11913local knockSpeed = 0.1
11914local knockRecover = 0.1
11915
11916local module = {}
11917
11918module.FOVGoal=70;
11919
11920
11921function module:IsCustom()
11922 return CurrentCameraType == "Custom" or CurrentCameraType == "Free" and IsFirstPerson
11923end
11924
11925
11926UserInputService.InputChanged:Connect(function(input)
11927 if not module:IsCustom() then return end
11928
11929 if input.UserInputType == Enum.UserInputType.MouseMovement then
11930 local sensitivity = UserGameSettings.MouseSensitivity
11931
11932 MouseDelta = Vector2.new(
11933 -input.Delta.X * sensitivity * 0.3,
11934 -input.Delta.Y * sensitivity * 0.3
11935 )
11936
11937
11938 elseif input.KeyCode == Enum.KeyCode.Thumbstick2 then
11939 local sensitivity = UserGameSettings.GamepadCameraSensitivity
11940 local pos = input.Position
11941
11942 if pos.Magnitude < GamepadDeadZone then
11943 MouseDelta = nil
11944 else
11945 local norPos = pos.Unit * ((pos.Magnitude - GamepadDeadZone) / (1 - GamepadDeadZone))
11946
11947 MouseDelta = Vector2.new(
11948 -norPos.X * sensitivity * 2.5,
11949 norPos.Y * sensitivity * 2.5
11950 )
11951 end
11952 end
11953end)
11954
11955InputHandler:RegisterActions({
11956 ChangleShoulder = {"ChangeShoulder", function(state)
11957 if state.Name ~= "Begin" then return end
11958 Shoulder = Shoulder == "Right" and "Left" or "Right"
11959 end},
11960
11961 ChangeCameraMode = {"ChangeCamera", function(state)
11962 if state.Name ~= "Begin" then return end
11963 module:SetFirstPerson(not IsFirstPerson)
11964 end},
11965})
11966
11967function module:AddRecoil(amt)
11968 Recoil = Recoil + amt
11969end
11970
11971function module:Enable()
11972 self.Disabled = false
11973end
11974
11975function module:Disable()
11976 self.Disabled = true
11977end
11978
11979function module:SetMode(mode)
11980 CurrentCameraType = mode
11981end
11982
11983function module:GetMode()
11984 return CurrentCameraType
11985end
11986
11987function module:SetCameraCFrame(cframe)
11988 local oldLV = Camera.CFrame.LookVector
11989 local newLV = cframe.LookVector
11990
11991 local diffY = math.atan2(-newLV.X, -newLV.Z) - math.atan2(-oldLV.X, -oldLV.Z)
11992 local diffX = math.asin(newLV.Y) - math.asin(oldLV.Y)
11993
11994 gAngleY = gAngleY + diffY
11995 gAngleX = gAngleX - diffX
11996
11997 Camera.CFrame = cframe
11998
11999end
12000
12001function module:SetFirstPerson(enabled)
12002 IsFirstPerson = not not enabled
12003
12004 local trans = IsFirstPerson and 1 or 0
12005
12006 PlayerCharacter.Head.Transparency = trans
12007
12008 for _,v in pairs(PlayerCharacter.Character:GetChildren()) do
12009 if v:IsA("Accessory") then
12010 for _,v in pairs(v:GetChildren()) do
12011 if v:IsA("BasePart") then
12012 v.Transparency = trans
12013 end
12014 end
12015 end
12016 end
12017end
12018
12019function module:IsFirstPerson()
12020 return IsFirstPerson
12021end
12022
12023function module:Vibrate(maxAngle, duration, transition)
12024 gVibration = maxAngle
12025 vibTime = duration
12026 vibSmooth = transition
12027 vibStart = tick()
12028end
12029
12030function module:Lurch(lurchAngle, snapTime, recover)
12031 gKnock = lurchAngle
12032 knockSpeed = snapTime
12033 knockRecover = recover
12034end
12035
12036function module:UpdateVibrate(updateTime)
12037 local elapsed = tick() - vibStart
12038
12039 if elapsed < vibSmooth then
12040 vibration = Mathf.SmoothLerp(0, gVibration, elapsed / vibSmooth)
12041 else
12042 vibration = Mathf.SmoothLerp(gVibration, 0, (elapsed - vibSmooth) / (vibTime - vibSmooth))
12043 end
12044
12045 cKnock = cKnock:Lerp(gKnock, Mathf.Clamp(updateTime / knockSpeed, 0, 1))
12046 gKnock = gKnock:Lerp(Vector3.new(), Mathf.Clamp(updateTime / knockRecover, 0, 1))
12047
12048 return CFrame.fromOrientation(
12049 (math.random() * 2 - 1) * vibration + cKnock.x,
12050 (math.random() * 2 - 1) * vibration + cKnock.y,
12051 (math.random() * 2 - 1) * vibration + cKnock.z
12052 )
12053end
12054
12055local LastCameraType
12056function module.Update(updateTime)
12057 if module.Disabled then return end
12058 local cameraType = CurrentCameraType
12059
12060 if IsFirstPerson then
12061 cameraType = "Custom"
12062 end
12063
12064 if cameraType ~= LastCameraType then
12065 LastCameraType = cameraType
12066
12067 MouseDelta = nil
12068
12069 if cameraType == "Free" then
12070 PlayerCharacter.Human.AutoRotate = true
12071 Camera.CameraSubject = PlayerCharacter.Human
12072 Camera.CameraType = "Custom"
12073 else
12074 PlayerCharacter.Human.AutoRotate = false
12075 Camera.CameraType = "Scriptable"
12076
12077 if cameraType == "Custom" then
12078 local lookVector = Camera.CFrame.lookVector
12079 gAngleY = math.atan2(-lookVector.X, -lookVector.Z)
12080 gAngleX = math.asin(lookVector.Y)
12081 end
12082 end
12083 end
12084
12085
12086 local vibrate = module:UpdateVibrate(updateTime)
12087
12088 local fovGoal = module.FOVGoal;
12089
12090 if cameraType == "Custom" then
12091 local subject = IsFirstPerson and PlayerCharacter.Head or PlayerCharacter.RootPart
12092 local equippedItem = PlayerCharacter:GetEquippedItem()
12093
12094 fovGoal = equippedItem.IsAiming and 60 or fovGoal;
12095
12096 local cameraOffsetGoal
12097
12098 if not IsFirstPerson then
12099 cameraOffsetGoal = equippedItem.IsAiming and equippedItem.CameraAimPoint or ThirdPersonOffset
12100 else
12101 cameraOffsetGoal = FirstPersonOffset
12102
12103 local aimpoint = equippedItem.IsAiming and equippedItem.Model and equippedItem.Model:FindFirstChild("FirstPersonAimPoint")
12104 if aimpoint and not equippedItem.IsLoading then
12105 local offsetValue = equippedItem.IsFanning and aimpoint:FindFirstChild("FanOffset") or aimpoint:FindFirstChild("Offset")
12106
12107 subject = aimpoint
12108 cameraOffsetGoal = offsetValue.Value
12109 end
12110 end
12111
12112 if Shoulder == "Left" and not IsFirstPerson then
12113 cameraOffsetGoal = cameraOffsetGoal * Vector3.new(-1, 1, 1)
12114 end
12115
12116 local cameraOffset = cameraOffsetGoal
12117
12118 --
12119
12120 -- Apply mouse / gamepad movement
12121
12122 if MouseDelta then
12123 if Recoil > 0 and MouseDelta.Y < 0 then
12124 local comp = math.min(Recoil, -MouseDelta.Y)
12125 Recoil = Recoil - comp
12126 MouseDelta = MouseDelta + Vector2.new(0, comp)
12127 end
12128
12129 gAngleX = gAngleX + math.rad(MouseDelta.Y)
12130 gAngleY = gAngleY + math.rad(MouseDelta.X)
12131
12132 MouseDelta = nil
12133 end
12134
12135 Recoil = math.clamp(Recoil - (updateTime * 40), 0, 100)
12136
12137 -- Normalize angles to right ranges
12138
12139 gAngleY = (gAngleY + math.pi) % (math.pi * 2) - math.pi
12140 gAngleX = math.clamp(gAngleX, MinAngleX, MaxAngleX)
12141
12142 -- Apply angle limits
12143
12144 local limitVector, limitMax
12145
12146 local ControllingAnimals = WildLife.ControllingAnimals;
12147
12148 local AnimalLook;
12149 local NumAnimals = 1;
12150
12151 for animal,obj in pairs(ControllingAnimals) do
12152 if animal and animal.hrp then
12153 NumAnimals=NumAnimals+1;
12154 AnimalLook=(AnimalLook or Vector3.new())+animal.hrp.CFrame.lookVector;
12155 end
12156 end
12157
12158 local RidingAnimal = WildLife:GetRidingAnimal();
12159 if RidingAnimal then
12160 AnimalLook=(AnimalLook or Vector3.new())+RidingAnimal.hrp.CFrame.lookVector;
12161 end
12162
12163
12164
12165 local SeatPart = PlayerCharacter:GetSeated();
12166
12167
12168
12169 if AnimalLook then
12170 AnimalLook=AnimalLook/NumAnimals;
12171
12172 limitVector = -AnimalLook;
12173 limitMax = math.rad(65)
12174 elseif PlayerCharacter:GetLassoTarget() and PlayerCharacter:GetLassoTarget():FindFirstChild("HumanoidRootPart") then
12175 limitVector = (PlayerCharacter:GetLassoTarget().HumanoidRootPart.Position - PlayerCharacter.RootPart.Position).Unit
12176 limitMax = math.rad(90)
12177 elseif SeatPart then
12178 limitVector=SeatPart.CFrame.lookVector;
12179 limitMax = math.rad(65);
12180 end
12181
12182
12183 if limitVector then
12184 local limitAngle = math.atan2(-limitVector.X, -limitVector.Z)
12185
12186 local diffAngle = gAngleY - limitAngle
12187 if diffAngle > math.pi then
12188 diffAngle = diffAngle - math.pi * 2
12189 elseif diffAngle < -math.pi then
12190 diffAngle = diffAngle + math.pi * 2
12191 end
12192
12193 if diffAngle > limitMax then
12194 gAngleY = gAngleY - (diffAngle - limitMax)
12195 elseif diffAngle < -limitMax then
12196 gAngleY = gAngleY - (diffAngle + limitMax)
12197 end
12198 end
12199
12200 -- Calculate CFrame and Focus
12201
12202 local angleY = gAngleY
12203 local angleX = math.clamp(gAngleX + math.rad(Recoil), MinAngleX, MaxAngleX)
12204
12205 local baseAngle = CFrame.fromOrientation(angleX, angleY, 0)
12206
12207 local camCFrame = CFrame.new(subject.Position) * (baseAngle * vibrate) * CFrame.new(cameraOffset)
12208
12209 Camera.Focus = camCFrame * CFrame.new(0, 0, -0.5)
12210
12211 Camera.CFrame = camCFrame
12212
12213 -- AutoRotate
12214
12215 local rootPart = PlayerCharacter.RootPart
12216 local cantRotate = AnimalLook or (equippedItem.Name == "Lasso" and (equippedItem.IsThrowingLasso or equippedItem.IsReelingIn)) or SeatPart;
12217
12218 if not cantRotate then
12219 local rootLook = rootPart.CFrame.LookVector
12220 local rootAngle = math.atan2(-rootLook.X, -rootLook.Z)
12221
12222 local diffAngle = angleY - rootAngle
12223 if diffAngle > math.pi then
12224 diffAngle = diffAngle - math.pi * 2
12225 elseif diffAngle < -math.pi then
12226 diffAngle = diffAngle + math.pi * 2
12227 end
12228
12229-- rootPart.RotVelocity = Vector3.new(0, diffAngle * 30, 0)
12230
12231 rootPart.CFrame = rootPart.CFrame * CFrame.Angles(0, diffAngle * (0.15 ^ (1 / (updateTime * 60))), 0)
12232 end
12233 elseif cameraType == "Taming" then
12234 local animal = shared.Taming.animal
12235
12236 if animal then
12237 local focus = PlayerCharacter.Head.Position
12238 local camCFrame = CFrame.new(animal:GetTamingCameraPoint(), focus)
12239
12240 Camera.CFrame = camCFrame * vibrate
12241 Camera.Focus = CFrame.new(focus, focus + camCFrame.lookVector)
12242 end
12243 elseif cameraType == "Customizing" then
12244 return
12245 elseif cameraType == "Free" then
12246 Camera.CFrame = Camera.CFrame * vibrate
12247 Camera.FieldOfView = Mathf.Lerp(Camera.FieldOfView, fovGoal, math.clamp(updateTime/0.1,0,1));
12248
12249 return
12250 end
12251
12252
12253 local ignoreList = { Camera, PlayerCharacter.Character, Ignore }
12254 local cutoff = Camera:GetLargestCutoffDistance(ignoreList)
12255
12256 if cutoff > 0 then
12257 Camera.CFrame = Camera.CFrame * CFrame.new(0,0, -cutoff)
12258 end
12259end
12260
12261
12262return module
12263
12264--[=[
12265 Module responsible for handling most visual effects
12266--]=]
12267
12268
12269
12270
12271-- Services
12272
12273local Lighting = game:GetService("Lighting");
12274local CollectionService = game:GetService("CollectionService");
12275local TweenService = game:GetService("TweenService");
12276local SoundService = game:WaitForChild("SoundService")
12277local ReplicatedStorage = game:GetService("ReplicatedStorage");
12278
12279
12280-- Modules
12281
12282local LoadModule = require(ReplicatedStorage.Modules.Load);
12283
12284local AFX = LoadModule("AFX",true);
12285local VFX = LoadModule("VFX",true);
12286local RagdollImpactListeners = LoadModule("RagdollImpactListeners",true);
12287
12288local LoadSharedModule = require(ReplicatedStorage:WaitForChild("SharedModules"):WaitForChild("Load"));
12289
12290local Network = LoadSharedModule("Network");
12291
12292
12293local AnimationHandler = LoadModule("AnimationHandler", true)
12294local PlayerCharacter = LoadModule("PlayerCharacter", true)
12295local Mathf = LoadModule("Mathf")
12296local Utils = LoadModule("Utils")
12297local UIObjects = LoadModule("UIObjects");
12298
12299-- Variables
12300
12301local Resources = ReplicatedStorage.Resources;
12302local Ignore = workspace.Ignore;
12303
12304local module = {}
12305
12306
12307local player = game:GetService("Players").LocalPlayer;
12308local Terrain = workspace:WaitForChild("Terrain");
12309local Resources = ReplicatedStorage.Resources;
12310
12311local client = UIObjects.Client;
12312local ClientSounds = UIObjects.ClientSounds;
12313
12314local heartbeat = ClientSounds.Heartbeat;
12315local damageoverlay = client.DamageOverlay;
12316
12317local DamageOverlayBeatInfo = TweenInfo.new(heartbeat.TimeLength,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,true,0);
12318local DamageOverlayBeat = TweenService:Create(damageoverlay,DamageOverlayBeatInfo,{Size=UDim2.new(1.1,0,1.1,36)});
12319
12320
12321local SaturationValues = {};
12322
12323local GlobalMuffle = SoundService:WaitForChild("GlobalSoundModifier"):WaitForChild("GlobalMuffle");
12324
12325
12326local ColorCorrection = Lighting:WaitForChild("ColorCorrection");
12327local Blur = Lighting:WaitForChild("Blur");
12328
12329local PoisonCC = Lighting:WaitForChild("PoisonCC");
12330local PoisonColor = Color3.fromRGB(225,255,126);
12331local PoisonBrightness=-0.3;
12332
12333local FootstepMaterials = Utils.FootstepMaterials;
12334
12335
12336
12337local SaturationValue = {};
12338local SaturationValues = {};
12339
12340local BrightnessValue = {};
12341local BrightnessValues = {};
12342
12343local BlurValue = {};
12344local BlurValues = {};
12345
12346
12347local MuffleValue = {};
12348local MuffleValues = {};
12349
12350
12351
12352
12353
12354
12355function MuffleValue.new(goal,transition_time)
12356 local self = setmetatable({},{__index=MuffleValue});
12357 self.value=0;
12358 self.goal=goal;
12359 self.transition_time=transition_time;
12360
12361 MuffleValues[#MuffleValues+1]=self;
12362
12363 return self;
12364end
12365
12366function MuffleValue:SetGoal(goal)
12367 self.goal=goal;
12368end
12369function MuffleValue:SetTransitionTime(transitiontime)
12370 self.transition_time=transitiontime;
12371end
12372function module.NewMuffleValue(goal,transition_time)
12373 return MuffleValue.new(goal,transition_time);
12374end
12375
12376
12377function BlurValue.new(goal,transition_time)
12378 local self = setmetatable({},{__index=BlurValue});
12379
12380 self.value=0;
12381 self.goal=goal;
12382 self.transition_time=transition_time;
12383
12384 BlurValues[#BlurValues+1]=self;
12385
12386 return self;
12387end
12388
12389function BlurValue:SetGoal(goal)
12390 self.goal=goal;
12391end
12392function BlurValue:SetTransitionTime(transitiontime)
12393 self.transition_time=transitiontime;
12394end
12395
12396function module.NewBlurValue(goal,transition_time)
12397 return BlurValue.new(goal,transition_time);
12398end
12399
12400
12401function SaturationValue.new(goal,transition_time)
12402 local self = setmetatable({},{__index=SaturationValue});
12403
12404 self.value=0;
12405 self.goal=goal;
12406 self.transition_time=transition_time;
12407
12408 SaturationValues[#SaturationValues+1]=self;
12409
12410 return self;
12411end
12412
12413function SaturationValue:SetGoal(goal)
12414 self.goal=goal;
12415end
12416function SaturationValue:SetTransitionTime(transitiontime)
12417 self.transition_time=transitiontime;
12418end
12419
12420function module.NewSaturationValue(goal,transition_time)
12421 return SaturationValue.new(goal,transition_time);
12422end
12423
12424
12425function BrightnessValue.new(goal,transition_time)
12426 local self = setmetatable({},{__index=BrightnessValue});
12427
12428 self.value=0;
12429 self.goal=goal;
12430 self.transition_time=transition_time;
12431
12432 BrightnessValues[#BrightnessValues+1]=self;
12433
12434 return self;
12435end
12436
12437function BrightnessValue:SetGoal(goal)
12438 self.goal=goal;
12439end
12440function BrightnessValue:SetTransitionTime(transitiontime)
12441 self.transition_time=transitiontime;
12442end
12443
12444function module.NewBrightnessValue(goal,transition_time)
12445 return BrightnessValue.new(goal,transition_time);
12446end
12447
12448local TintColor = Color3.new(1,1,1)
12449local TintColorGoal = Color3.new(1,1,1);
12450
12451
12452module.SetTintColorGoal = function(goal)
12453 TintColorGoal=goal;
12454end
12455
12456
12457local DamageOverlayTransparency=1;
12458
12459
12460local lastdamagebeat = tick();
12461
12462
12463
12464
12465
12466
12467
12468
12469-- Taming
12470
12471local TamingEffect = {};
12472local TamingEffects = {};
12473
12474function TamingEffect.new(animal, char)
12475 local oldEffect = TamingEffects[animal]
12476 if oldEffect then
12477 oldEffect:Disconnect()
12478 end
12479
12480 local circle = animal:FindFirstChild("LassoCircle")
12481 local pullingchar_righthand = char:FindFirstChild("RightHand")
12482 local pullingchar_lefthand = char:FindFirstChild("LeftHand")
12483
12484 if not circle or not char then return end
12485
12486 local att1 = circle:FindFirstChild("Attachment")
12487 if not att1 then return end
12488
12489 if pullingchar_righthand and pullingchar_lefthand then
12490 local self = setmetatable({},{__index=TamingEffect});
12491
12492 local fakepuller = Instance.new("RopeConstraint",char);
12493 fakepuller.Color=BrickColor.new("Fawn brown");
12494 fakepuller.Visible = true;
12495 fakepuller.Name = "PullerVisual";
12496 fakepuller.Length = 0;
12497 fakepuller.Attachment0 = pullingchar_righthand.RightGripAttachment;
12498 fakepuller.Attachment1 = att1;
12499 VFX.CreateFakeAttachment(fakepuller, "Attachment0", fakepuller.Attachment0, true);
12500 VFX.CreateFakeAttachment(fakepuller, "Attachment1", fakepuller.Attachment1, true);
12501
12502 local leftgrip = pullingchar_lefthand.LeftGripAttachment;
12503 local rightgrip = pullingchar_righthand.RightGripAttachment;
12504
12505 local twine = Resources:WaitForChild("LassoTwine"):clone();
12506 twine.Parent = char;
12507
12508 local twineweld = twine:WaitForChild("TwineWeld");
12509 twineweld.Part0 = pullingchar_lefthand;
12510
12511 local ropetohand = Resources:WaitForChild("RopeToHand"):clone();
12512 ropetohand.Attachment0 = leftgrip;
12513 ropetohand.Attachment1 = rightgrip;
12514 ropetohand.Parent = twine;
12515
12516 circle.Transparency = 0
12517
12518 self.twine = twine;
12519 self.puller = fakepuller;
12520 self.circle = circle;
12521 self.char = char;
12522 self.animal = animal;
12523 self.lastdistance = (twine.Position-circle.Position).magnitude;
12524 self.originalposition = circle.Position;
12525 self.originaldistance=self.lastdistance;
12526
12527 TamingEffects[animal] = self
12528 TamingEffects[char] = self
12529
12530 return self
12531 end
12532end
12533
12534function TamingEffect:Disconnect()
12535 self.twine:Destroy()
12536 self.puller:Destroy()
12537 self.circle.Transparency = 1
12538
12539 TamingEffects[self.animal] = nil
12540 TamingEffects[self.char] = nil
12541end
12542
12543function module:CreateTamingEffect(animal, char)
12544 TamingEffect.new(animal, char)
12545end
12546
12547function module:RemoveTamingEffect(char) -- also works with animal
12548 local effect = TamingEffects[char]
12549 if effect then
12550 effect:Disconnect()
12551 end
12552end
12553
12554function module:CreateLassoEffect(myChar, char, parent)
12555 local myLeftHand = myChar.LeftHand
12556 local myRightHand = myChar.RightHand
12557 local leftLeg = char.LeftLowerLeg
12558
12559 local draggingCircle = Resources.DraggingCircle:Clone()
12560 draggingCircle.CFrame = leftLeg.CFrame
12561 draggingCircle.Anchored = false
12562 draggingCircle.Parent = parent
12563
12564 local weld = Instance.new("Weld")
12565 weld.Part0 = draggingCircle
12566 weld.Part1 = leftLeg
12567 weld.C0 = CFrame.new(-.4, 0, 0)
12568 weld.Parent = draggingCircle
12569
12570 -- Fake puller
12571 local fakepuller = Instance.new("RopeConstraint")
12572 fakepuller.Color = BrickColor.new("Fawn brown")
12573 fakepuller.Visible = true
12574 fakepuller.Name = "PullerVisual"
12575 fakepuller.Length = 0
12576 fakepuller.Attachment0 = myChar.RightHand.RightGripAttachment
12577 fakepuller.Attachment1 = draggingCircle.Attachment
12578 fakepuller.Parent = parent
12579
12580 VFX.CreateFakeAttachment(fakepuller, "Attachment0", fakepuller.Attachment0, true)
12581 VFX.CreateFakeAttachment(fakepuller, "Attachment1", fakepuller.Attachment1, true)
12582
12583 local twine = Resources.LassoTwine:Clone()
12584 twine.TwineWeld.Part0 = myLeftHand
12585 twine.Parent = parent
12586
12587 local ropetohand = Resources.RopeToHand:Clone()
12588 ropetohand.Attachment0 = myLeftHand.LeftGripAttachment
12589 ropetohand.Attachment1 = myRightHand.RightGripAttachment
12590 ropetohand.Parent = twine
12591end
12592
12593local LassoEffects = {}
12594
12595Network:BindEvents({
12596 CreateLassoEffect = function(lassoer, lassoed)
12597 local items = lassoer:FindFirstChild("LassoItems")
12598 if items then
12599 items:Destroy()
12600 end
12601
12602 local folder = Instance.new("Folder")
12603 folder.Name = "LassoEffect"
12604 module:CreateLassoEffect(lassoer, lassoed, folder)
12605 folder.Parent = lassoer
12606
12607 LassoEffects[lassoer] = folder
12608 end,
12609 RemoveLassoEffect = function(lassoer)
12610 local effect = LassoEffects[lassoer]
12611 if effect then
12612 effect:Destroy()
12613 LassoEffects[lassoer] = nil
12614 end
12615 end,
12616 TameEffect = function(animal, char)
12617 module:CreateTamingEffect(animal, char)
12618 end,
12619 StopTamingEffect = function(animal)
12620 module:RemoveTamingEffect(animal)
12621 end
12622})
12623
12624
12625
12626local lasthealth
12627module.Update = function(updateTime)
12628
12629 RagdollImpactListeners.Update(updateTime);
12630 AFX.Update(updateTime);
12631 VFX.Update(updateTime);
12632
12633 local saturation_decrease = 0;
12634 local brightness_increase = 0;
12635 local blur_increase = 0;
12636
12637
12638 local perc_to_muffled = 0;
12639
12640 local perc_to_dead = PlayerCharacter.PercToDead;
12641
12642 local bloodborder = shared.BloodBorder;
12643
12644
12645 -- Poisoned
12646 local poisonperc = PlayerCharacter.PoisonValue;
12647 if poisonperc then
12648 if poisonperc.Value > 0 then
12649 PoisonCC.Enabled=true;
12650 poisonperc=math.clamp(poisonperc.Value/1,0,1);
12651
12652 local alpha = math.clamp(updateTime/0.25,0,1);
12653
12654 PoisonCC.Brightness=Mathf.Lerp(PoisonCC.Brightness,Mathf.Lerp(0,-0.3,poisonperc),alpha);
12655 PoisonCC.TintColor=PoisonCC.TintColor:lerp(Color3.new(1,1,1):lerp(PoisonColor,poisonperc),alpha);
12656 else
12657 PoisonCC.Enabled=false;
12658 end
12659 end
12660 --
12661
12662 if damageoverlay then
12663 DamageOverlayTransparency=math.clamp(DamageOverlayTransparency+updateTime/2,0,1);
12664
12665 local health = PlayerCharacter.HealthValue;
12666 if health then
12667 health=health.Value;
12668
12669 if (lasthealth and health-lasthealth <= -10) or perc_to_dead then
12670 DamageOverlayTransparency=0;
12671 end
12672
12673 lasthealth=health;
12674 end
12675
12676 damageoverlay.ImageTransparency=DamageOverlayTransparency;
12677
12678 if perc_to_dead then
12679
12680 if perc_to_dead >= 1 then
12681 heartbeat.Volume=Mathf.Lerp(heartbeat.Volume,0,math.clamp(updateTime/1,0,1));
12682 else
12683 if not heartbeat.IsPlaying then
12684 heartbeat:Play();
12685 end
12686 heartbeat.Pitch=Mathf.Lerp(1,0.8,perc_to_dead);
12687 heartbeat.Volume=Mathf.Lerp(0.1,0.3,perc_to_dead);
12688
12689
12690 local out = Mathf.Lerp(1,1.2,math.clamp(heartbeat.PlaybackLoudness/100,0,1));
12691 damageoverlay:TweenSize(UDim2.new(out,0,out,36),"Out","Linear",.1,true,nil);
12692 end
12693 else
12694 if heartbeat.IsPlaying then
12695 heartbeat:Stop();
12696 end
12697 end
12698 end
12699
12700
12701 for _,tab in pairs(MuffleValues) do
12702 local increase = tab.value;
12703 tab.value=Mathf.Lerp(increase,tab.goal,math.clamp(updateTime/tab.transition_time,0,1));
12704 perc_to_muffled=perc_to_muffled+increase;
12705 end
12706
12707
12708 perc_to_muffled=math.clamp(perc_to_muffled,0,1);
12709
12710 GlobalMuffle.HighGain=Mathf.Lerp(0,-80,perc_to_muffled);
12711 GlobalMuffle.LowGain=Mathf.Lerp(0,10,perc_to_muffled);
12712 GlobalMuffle.MidGain=Mathf.Lerp(0,-80,perc_to_muffled);
12713
12714
12715 for _,tab in pairs(BlurValues) do
12716 local increase = tab.value;
12717 tab.value=Mathf.Lerp(increase,tab.goal,math.clamp(updateTime/tab.transition_time,0,1));
12718 blur_increase=blur_increase+increase;
12719 end
12720 for _,tab in pairs(SaturationValues) do
12721 local satdecrease = tab.value;
12722 tab.value=Mathf.Lerp(satdecrease,tab.goal,math.clamp(updateTime/tab.transition_time,0,1));
12723 saturation_decrease = saturation_decrease + satdecrease;
12724 end
12725 for _,tab in pairs(BrightnessValues) do
12726 local brightdecrease = tab.value;
12727 tab.value=Mathf.Lerp(brightdecrease,tab.goal,math.clamp(updateTime/tab.transition_time,0,1));
12728 brightness_increase = brightness_increase + brightdecrease;
12729 end
12730
12731
12732
12733 Blur.Size = math.clamp(0+blur_increase,0,100);
12734
12735 ColorCorrection.Brightness = math.clamp(0+brightness_increase,-1,1);
12736
12737 ColorCorrection.Saturation = math.clamp(0.3-saturation_decrease,-1,1);
12738
12739 TintColor=TintColor:lerp(TintColorGoal,math.clamp(updateTime/0.2,0,1));
12740
12741 ColorCorrection.TintColor=TintColor;
12742end
12743
12744
12745return module
12746
12747
12748local Listeners = {};
12749local Listener = {};
12750local PartListener = {};
12751
12752local module = {};
12753
12754--[=[
12755 Services
12756--]=]
12757
12758local ReplicatedStorage = game:GetService("ReplicatedStorage");
12759local CollectionService = game:GetService("CollectionService");
12760--
12761
12762local LoadModule = require(ReplicatedStorage.Modules.Load);
12763local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
12764local FX = LoadModule("FX",true);
12765local AFX = LoadModule("AFX",true);
12766local VFX = LoadModule("VFX",true);
12767local SharedUtils = LoadSharedModule("SharedUtils");
12768
12769local SFXFolderImpacts = ReplicatedStorage.Resources.SFX.RagdollImpacts;
12770
12771local Ignore = workspace:WaitForChild("Ignore");
12772
12773function Listener.new(char,owns)
12774 if not Listeners[char] then
12775 local self = setmetatable({},{__index=Listener});
12776 self.char=char;
12777 self.hrp=self.char.PrimaryPart;
12778 self.owns=owns;
12779
12780 local parts = SharedUtils.GetCharacterParts(char);
12781
12782 local partlisteners = {};
12783 self.LastTagImpacts={};
12784 self.partlisteners=partlisteners;
12785 for _,v in pairs(parts) do
12786 partlisteners[#partlisteners+1]=PartListener.new(self,v);
12787 end
12788
12789 Listeners[char]=self;
12790 end
12791end
12792
12793
12794local Terrain = workspace:WaitForChild("Terrain");
12795
12796
12797local NewRay = Ray.new;
12798
12799function PartListener.new(Listener,part)
12800
12801 local self = setmetatable({},{__index=PartListener});
12802
12803 self.Listener=Listener;
12804 self.part=part;
12805 self.lastimpacttime=0;
12806 self.lastUpdate=0;
12807 self.char=Listener.char;
12808 self.lastposition=part.Position;
12809
12810 return self;
12811end
12812function PartListener:Event(obj,pos,norm,mat)
12813 local time = tick();
12814 if not obj:isDescendantOf(self.char) then
12815
12816 if obj == Terrain then
12817
12818 self:CheckTag(mat.Name,pos,norm);
12819
12820 else
12821 local tags = CollectionService:GetTags(obj);
12822
12823 for _,tag in pairs(tags) do
12824 if self:CheckTag(tag) then
12825 break;
12826 end
12827 end
12828 end
12829 end
12830end
12831function PartListener:Update(updateTime)
12832 local time = tick();
12833 if time - self.lastUpdate >= updateTime*2 then
12834 self.lastUpdate = time;
12835
12836 local part = self.part;
12837 local currentpos = part.Position;
12838 local lastpos = self.lastposition;
12839
12840 local ray = NewRay(lastpos,(currentpos-lastpos)*2);
12841 local hit,pos,norm,mat = workspace:FindPartOnRayWithIgnoreList(ray,{Ignore,self.Listener.char},false);
12842 if hit then
12843 self:Event(hit,pos,norm,mat);
12844 end
12845 self.lastposition=currentpos;
12846 end
12847end
12848
12849function PartListener:CheckTag(tag,raypos,raynorm)
12850 if tag then
12851 local part = self.part;
12852
12853 local time = tick();
12854
12855 local foundfolder = SFXFolderImpacts:FindFirstChild(tag);
12856 if foundfolder then
12857 local magnitude = (part.Velocity*Vector3.new(0,1,0)).magnitude;
12858
12859 local volume,pitchshift = SharedUtils.GetVolumeAndPitchFromVelocity(magnitude);
12860
12861 if magnitude > 6.5 then
12862
12863 if time - self.lastimpacttime >= .5 then
12864 self.lastimpacttime=time;
12865
12866 local cancontinue=true;
12867 local lasttagimpact = self.Listener.LastTagImpacts[tag];
12868 if lasttagimpact then
12869 if time - lasttagimpact < .25 then
12870 cancontinue=false;
12871 end
12872 end
12873
12874
12875 if cancontinue == true then
12876 self.Listener.LastTagImpacts[tag]=time;
12877 local playssound = true;
12878
12879 if tag == "Sand" or tag == "Limestone" then
12880 VFX.LocalCreateDust(part.Position,part.Velocity,Color3.fromRGB(255, 203, 139));
12881 elseif tag == "Ground" then
12882 VFX.LocalCreateDust(part.Position,part.Velocity,Color3.fromRGB(155, 105, 47));
12883 elseif tag == "Mud" then
12884 playssound=false;
12885 if raypos and raynorm then
12886 local cf = CFrame.new(raypos,raypos+raynorm);
12887 VFX.CreateMudSplash(cf);
12888 end
12889 elseif tag == "Water" then
12890 playssound=false;
12891 if raypos and raynorm then
12892 local cf = CFrame.new(raypos,raypos+raynorm);
12893 VFX.CreateWaterSplash(cf);
12894 end
12895 end
12896
12897 if playssound == true then
12898 AFX.PlayRandomSound(foundfolder,part,{DontReplicate=true,Volume=volume,PitchShift=pitchshift});
12899 end
12900 end
12901
12902 end
12903 end
12904 return true;
12905 end
12906 end
12907end
12908
12909
12910function Listener:Dispose()
12911 if self.char then
12912 local Listener = Listeners[self.char];
12913 if Listener then
12914 Listener.partlisteners=nil;
12915 Listeners[self.char]=nil;
12916 end
12917 end
12918end
12919
12920function module:connect(char,owns)
12921 if char then
12922 Listener.new(char,owns);
12923 end
12924end
12925function module:disconnect(char)
12926 if char and Listeners[char] then
12927 Listeners[char]:Dispose();
12928 end
12929end
12930
12931function module.Update(updateTime)
12932 for char,obj in pairs(Listeners) do
12933 local partlisteners = obj.partlisteners;
12934 for _,v in pairs(partlisteners) do
12935 v:Update(updateTime);
12936 end
12937
12938 if obj.owns then
12939 local hrp = obj.hrp;
12940 local hrppos = hrp.Position;
12941
12942 local hitwater = SharedUtils.IsPositionInWater(hrppos,{obj.char,Ignore});
12943
12944 if hitwater then
12945 if not obj.lasthitwater then
12946 SharedUtils.SetPhysicalProperties(obj.char,"RagdolledWater");
12947 end
12948 else
12949 if obj.lasthitwater then
12950 SharedUtils.SetPhysicalProperties(obj.char,"Ragdolled");
12951 end
12952 end
12953 obj.lasthitwater = hitwater;
12954
12955 end
12956 end
12957end
12958
12959return module;
12960
12961
12962-- Visual Effects Handler
12963
12964local module = {}
12965
12966--[=[
12967 Services
12968--]=]
12969
12970local ReplicatedStorage = game:GetService("ReplicatedStorage");
12971local CollectionService = game:GetService("CollectionService");
12972local Debris = game:GetService("Debris");
12973local Lighting = game:GetService("Lighting");
12974local TweenService = game:GetService("TweenService");
12975local Resources = ReplicatedStorage.Resources;
12976--
12977
12978local Terrain = workspace:WaitForChild("Terrain");
12979local Ignore = workspace:WaitForChild("Ignore");
12980local LoadModule = require(ReplicatedStorage.Modules.Load);
12981local LoadSharedModule = require(ReplicatedStorage.SharedModules.Load);
12982
12983local Network = LoadSharedModule("Network");
12984local FX = LoadModule("FX",true);
12985local Utils = LoadModule("Utils");
12986local AnimationHandler = LoadModule("AnimationHandler");
12987local AFX = LoadModule("AFX",true);
12988local Mathf = LoadModule("Mathf");
12989
12990local FuseFX = LoadModule("FuseFX");
12991local DrawProjectile = LoadModule("DrawProjectile");
12992
12993local NewRay = Ray.new;
12994
12995local SpurBlur = Lighting:WaitForChild("SpurBlur");
12996local SpurBlurTweenInfo = TweenInfo.new(.2,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,true,0);
12997
12998local SpurCC = Lighting:WaitForChild("SpurCC");
12999local SpurCCTweenInfo = TweenInfo.new(.4,Enum.EasingStyle.Linear,Enum.EasingDirection.Out,0,true,0);
13000
13001
13002local newray = Ray.new;
13003
13004local BillboardBlocks = {};
13005
13006local function AddBillboardBlock(obj)
13007 --local gui = obj:WaitForChild("BillboardGui");
13008
13009 --BillboardBlocks[obj]={gui=gui,offsety=gui.StudsOffset.Y,sineoffset=math.random()};
13010end
13011
13012coroutine.wrap(function()
13013 for _,v in pairs(CollectionService:GetTagged("BillboardBlock")) do
13014 AddBillboardBlock(v);
13015 end
13016end)()
13017
13018CollectionService:GetInstanceAddedSignal("BillboardBlock"):connect(function(obj)
13019 AddBillboardBlock(obj);
13020end)
13021CollectionService:GetInstanceRemovedSignal("BillboardBlock"):connect(function(obj)
13022 BillboardBlocks[obj]=nil;
13023end)
13024
13025
13026
13027
13028
13029
13030
13031--[=[
13032 Object vibration
13033--]=]
13034
13035local ObjectVibration={};
13036local ObjectVibrations={};
13037
13038function ObjectVibration.new(obj,angle,duration)
13039 local self = setmetatable({},{__index=ObjectVibration});
13040 self.angle=angle;
13041 self.duration=duration;
13042
13043 local primarypart = obj.PrimaryPart;
13044 self.primarypart=primarypart;
13045 self.primarypartcf = primarypart.CFrame;
13046 self.timestart=tick();
13047 self.obj=obj;
13048 ObjectVibrations[obj]=self;
13049end
13050function ObjectVibration:Dispose()
13051 ObjectVibrations[self.obj]=nil;
13052end
13053function ObjectVibration:Update(updateTime)
13054 local primarypart = self.primaryp