Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Converted using Mokiros's Model to Script plugin
- -- Converted string size: 8773
- local genv={}
- local ModuleScripts = {
- function() local utility = {}
- function utility:WideRayCast(start, target, offset, ignoreList)
- local parts = {}
- local ray = Ray.new(start, target - start)
- local part, point = game.Workspace:FindPartOnRayWithIgnoreList(ray, ignoreList)
- if part then table.insert(parts, part) end
- local offsetVector = offset * (target - start):Cross(Vector3.FromNormalId(Enum.NormalId.Top)).unit
- local ray = Ray.new(start + offsetVector, target - start + offsetVector)
- local part, point = game.Workspace:FindPartOnRayWithIgnoreList(ray, ignoreList)
- if part then table.insert(parts, part) end
- local ray = Ray.new(start - offsetVector, target - start - offsetVector)
- local part, point = game.Workspace:FindPartOnRayWithIgnoreList(ray, ignoreList)
- if part then table.insert(parts, part) end
- return parts
- end
- function utility:FindNearestPathPoint(path, point, start, target, ignoreList)
- local occludePoint = path:CheckOcclusionAsync(point)
- if occludePoint > 0 then
- utility:WideRayCast(start)
- end
- end
- local maxForce = 75
- function utility:GetRepulsionVector(unitPosition, otherUnitsPositions)
- local repulsionVector = Vector3.new(0,0,0)
- local count = 0
- for _, other in pairs(otherUnitsPositions) do
- local fromOther = unitPosition - other
- --fromOther = fromOther.unit * ((-maxForce / 5) * math.pow(fromOther.magnitude,2) + maxForce)
- fromOther = fromOther.unit * 1000 / math.pow((fromOther.magnitude + 1), 2)
- repulsionVector = repulsionVector + fromOther
- end
- return repulsionVector * maxForce
- end
- function utility:GetIdleState(StateMachine)
- local IdleState = StateMachine.NewState()
- IdleState.Name = "Idle"
- IdleState.Action = function() end
- IdleState.Init = function() end
- return IdleState
- end
- function utility:GetClosestVisibleTarget(npcModel, characters, ignoreList, fieldOfView)
- local closestTarget = nil
- local closestDistance = math.huge
- for _, character in pairs(characters) do
- local toTarget = character.Torso.Position - npcModel.Torso.Position
- local toTargetWedge = toTarget * Vector3.new(1,0,1)
- local angle = math.acos(toTargetWedge:Dot(npcModel.Torso.CFrame.lookVector)/toTargetWedge.magnitude)
- if math.deg(angle) < fieldOfView then
- local targetRay = Ray.new(npcModel.Torso.Position, toTarget)
- local part, position = game.Workspace:FindPartOnRayWithIgnoreList(targetRay, ignoreList)
- if part and part.Parent == character then
- if toTarget.magnitude < closestDistance then
- closestTarget = character
- closestDistance = toTarget.magnitude
- end
- end
- end
- end
- return closestTarget
- end
- local function isSpaceEmpty(position)
- local region = Region3.new(position - Vector3.new(2,2,2), position + Vector3.new(2,2,2))
- return game.Workspace:IsRegion3Empty(region)
- end
- function utility:FindCloseEmptySpace(model)
- local targetPos = Vector3.new(0,0,0)
- local count = 0
- math.randomseed(os.time())
- repeat
- local xoff = math.random(5,10)
- if math.random() > .5 then
- xoff = xoff * -1
- end
- local zoff = math.random(5, 10)
- if math.random() > .5 then
- zoff = zoff * -1
- end
- targetPos = Vector3.new(model.Torso.Position.X + xoff,model.Torso.Position.Y,model.Torso.Position.Z + zoff)
- if isSpaceEmpty(targetPos) then
- return targetPos
- else
- targetPos = targetPos + Vector3.new(0,4,0)
- end
- if isSpaceEmpty(targetPos) then
- return targetPos
- end
- count = count + 1
- until count > 10
- return nil
- end
- return utility end;
- function() local destroyService = {}
- local destroyQueue = {}
- function destroyService:AddItem(theobject, delay)
- local now = os.time()
- local destroyObject = {object = theobject, destroyTime = delay + now}
- for i, storedObject in pairs(destroyQueue) do
- if destroyQueue[i].destroyTime > destroyObject.destroyTime then
- table.insert(destroyQueue, i, destroyObject)
- return true
- end
- end
- table.insert(destroyQueue, destroyObject)
- return true
- end
- local updateThread = coroutine.create(function()
- while true do
- local now = os.time()
- for _, storedObject in pairs(destroyQueue) do
- if now >= storedObject.destroyTime then
- table.remove(destroyQueue, 1)
- if storedObject.object then
- storedObject.object:Destroy()
- end
- elseif now >= storedObject.destroyTime - 1 then
- if storedObject.object and storedObject.object:IsA("Part") then
- local trans = storedObject.object.Transparency + 1/30
- storedObject.object.Transparency = trans
- end
- else
- break
- end
- end
- wait()
- end
- end)
- coroutine.resume(updateThread)
- return destroyService end;
- function() local humanoidList = {}
- local storage = {}
- function humanoidList:GetCurrent()
- return storage
- end
- local function findHumanoids(object, list)
- if object then
- if object:IsA("Humanoid") then
- table.insert(list, object)
- end
- for _, child in pairs(object:GetChildren()) do
- local childList = findHumanoids(child, list)
- end
- end
- end
- local updateThread = coroutine.create(function()
- while true do
- storage = {}
- findHumanoids(game.Workspace, storage)
- wait(3)
- end
- end)
- coroutine.resume(updateThread)
- return humanoidList end;
- function() local machine = {}
- machine.new = function()
- local StateMachine = {}
- StateMachine.WaitTime = .2
- StateMachine.CurrentState = nil
- StateMachine.SwitchState = function(newState)
- if StateMachine.CurrentState then
- StateMachine.CurrentState.Stop()
- end
- StateMachine.CurrentState = newState
- if newState then
- newState.Start()
- end
- end
- StateMachine.NewState = function()
- local state = {}
- state.Name = ""
- state.Conditions = {}
- state.isRunning = false
- state.Action = function() end
- state.Run = function()
- state.isRunning = true
- while state.isRunning do
- --check conditions
- --print("checking conditions")
- for _, condition in pairs(state.Conditions) do
- --print("Checking " .. condition.Name)
- if condition.Evaluate() then
- --print(condition.Name .. " is true. Switching states")
- StateMachine.SwitchState(condition.TransitionState)
- return
- end
- end
- --if no conditions satisfied, perform action
- state.Action()
- wait(StateMachine.WaitTime)
- end
- end
- state.Init = function()
- end
- state.Start = function()
- --print("Starting " .. state.Name)
- state.Init()
- local thread = coroutine.create(state.Run)
- coroutine.resume(thread)
- end
- state.Stop = function()
- --print("Stopping " .. state.Name)
- state.isRunning = false
- end
- return state
- end
- StateMachine.NewCondition = function()
- local condition = {}
- condition.Name = ""
- condition.Evaluate = function() print("replace me") return false end
- condition.TransitionState = {}
- return condition
- end
- return StateMachine
- end
- return machine end;
- function() --local PathLib = require(game.ServerStorage.PathfindingLibrary).new()
- local HumanoidList = require(game.ServerStorage.ROBLOX_HumanoidList)
- local AIUtilities = require(game.ServerStorage.ROBLOX_AIUtilities)
- local ZombieAI = {}
- function updateDisplay(display, state)
- local thread = coroutine.create(function()
- while true do
- wait()
- if state then
- display.Text = state.Name
- end
- end
- end)
- coroutine.resume(thread)
- end
- ZombieAI.new = function(model)
- local zombie = {}
- -- CONFIGURATION VARIABLES
- -- local AttackRange, FieldOfView, AggroRange, ChanceOfBoredom, BoredomDuration,
- -- Damage, DamageCooldown
- local configTable = model.Configurations
- local configs = {}
- local function loadConfig(configName, defaultValue)
- if configTable:FindFirstChild(configName) then
- configs[configName] = configTable:FindFirstChild(configName).Value
- else
- configs[configName] = defaultValue
- end
- end
- loadConfig("AttackRange", 3)
- loadConfig("FieldOfView", 180)
- loadConfig("AggroRange", 200)
- loadConfig("ChanceOfBoredom", .5)
- loadConfig("BoredomDuration", 10)
- loadConfig("Damage", 10)
- loadConfig("DamageCooldown", 1)
- local StateMachine = require(game.ServerStorage.ROBLOX_StateMachine).new()
- local PathLib = require(game.ServerStorage.ROBLOX_PathfindingLibrary).new()
- local ZombieTarget = nil
- local ZombieTargetLastLocation = nil
- local lastBored = os.time()
- -- STATE DEFINITIONS
- -- IdleState: NPC stays still. Refreshes bored timer when started to
- -- allow for random state change
- local IdleState = StateMachine.NewState()
- IdleState.Name = "Idle"
- IdleState.Action = function()
- end
- IdleState.Init = function()
- lastBored = os.time()
- end
- -- SearchState: NPC wanders randomly increasing chance of spotting
- -- enemy. Refreshed bored timer when started to allow for random state
- -- change
- local SearchState = StateMachine.NewState()
- SearchState.Name = "Search"
- local lastmoved = os.time()
- local searchTarget = nil
- SearchState.Action = function()
- -- move to random spot nearby
- if model then
- local now = os.time()
- if now - lastmoved > 2 then
- lastmoved = now
- local xoff = math.random(5, 10)
- if math.random() > .5 then
- xoff = xoff * -1
- end
- local zoff = math.random(5, 10)
- if math.random() > .5 then
- zoff = zoff * -1
- end
- local testtarg = AIUtilities:FindCloseEmptySpace(model)
- --if testtarg then print(testtarg) else print("could not find") end
- searchTarget = Vector3.new(model.Torso.Position.X + xoff,model.Torso.Position.Y,model.Torso.Position.Z + zoff)
- --local target = Vector3.new(model.Torso.Position.X + xoff,model.Torso.Position.Y,model.Torso.Position.Z + zoff)
- --model.Humanoid:MoveTo(target)
- searchTarget = testtarg
- end
- if searchTarget then
- PathLib:MoveToTarget(model, searchTarget)
- end
- end
- end
- SearchState.Init = function()
- lastBored = os.time()
- end
- -- PursueState: Enemy has been spotted, need to give chase.
- local PursueState = StateMachine.NewState()
- PursueState.Name = "Pursue"
- PursueState.Action = function()
- -- Double check we still have target
- if ZombieTarget then
- -- Get distance to target
- local distance = (model.Torso.Position - ZombieTarget.Torso.Position).magnitude
- -- If we're far from target use pathfinding to move. Otherwise just MoveTo
- if distance > configs["AttackRange"] + 5 then
- PathLib:MoveToTarget(model, ZombieTarget.Torso.Position)
- else
- model.Humanoid:MoveTo(ZombieTarget.Torso.Position)
- -- if ZombieTarget.Torso.Position.Y > model.Torso.Position.Y + 2 then
- -- model.Humanoid.Jump = true
- -- end
- end
- end
- end
- PursueState.Init = function()
- end
- -- AttackState: Keep moving towards target and play attack animation.
- local AttackState = StateMachine.NewState()
- AttackState.Name = "Attack"
- local lastAttack = os.time()
- local attackTrack = model.Humanoid:LoadAnimation(model.Animations.Attack)
- AttackState.Action = function()
- model.Humanoid:MoveTo(ZombieTarget.Torso.Position)
- local now = os.time()
- if now - lastAttack > 3 then
- lastAttack = now
- attackTrack:Play()
- end
- end
- -- HuntState: Can't see target but NPC will move to target's last known location.
- -- Will eventually get bored and switch state.
- local HuntState = StateMachine.NewState()
- HuntState.Name = "Hunt"
- HuntState.Action = function()
- if ZombieTargetLastLocation then
- PathLib:MoveToTarget(model, ZombieTargetLastLocation)
- end
- end
- HuntState.Init = function()
- lastBored = os.time() + configs["BoredomDuration"] / 2
- end
- -- CONDITION DEFINITIONS
- -- CanSeeTarget: Determines if a target is visible. Returns true if target is visible and
- -- sets current target. A target is valid if it is nearby, visible, has a Torso and WalkSpeed
- -- greater than 0 (this is to ignore inanimate objects that happen to use humanoids)
- local CanSeeTarget = StateMachine.NewCondition()
- CanSeeTarget.Name = "CanSeeTarget"
- CanSeeTarget.Evaluate = function()
- if model then
- -- Get list of all nearby Zombies and non-Zombie humanoids
- -- Zombie list is used to ignore zombies during later raycast
- local humanoids = HumanoidList:GetCurrent()
- local zombies = {}
- local characters = {}
- for _, object in pairs(humanoids) do
- if object and object.Parent and object.Parent:FindFirstChild("Torso") and object.Health > 0 and object.WalkSpeed > 0 then
- local torso = object.Parent:FindFirstChild("Torso")
- if torso then
- local distance = (model.Torso.Position - torso.Position).magnitude
- if distance <= configs["AggroRange"] then
- if object.Parent.Name == "Drooling Zombie" then
- table.insert(zombies, object.Parent)
- else
- table.insert(characters, object.Parent)
- end
- end
- end
- end
- end
- local target = AIUtilities:GetClosestVisibleTarget(model, characters, zombies, configs["FieldOfView"])
- if target then
- ZombieTarget = target
- return true
- end
- -- -- Go through each valid target to see if within field of view and if there is
- -- -- clear line of sight. Field of view treated as wedge in front of character.
- -- for _, character in pairs(characters) do
- -- local toTarget = (character.Torso.Position - model.Torso.Position)
- -- toTarget = Vector3.new(toTarget.X, 0, toTarget.Z)
- -- local angle = math.acos(toTarget:Dot(model.Torso.CFrame.lookVector)/toTarget.magnitude)
- -- if math.deg(angle) < configs["FieldOfView"]/2 then
- -- ZombieTarget = character
- -- -- raycast to see if target is actually visible
- -- local toTarget = Ray.new(model.Torso.Position, (ZombieTarget.Torso.Position - model.Torso.Position))
- -- local part, position = game.Workspace:FindPartOnRayWithIgnoreList(toTarget, zombies)
- -- if part and part.Parent == ZombieTarget then
- -- return true
- -- end
- -- ZombieTarget = nil
- -- end
- -- end
- end
- return false
- end
- CanSeeTarget.TransitionState = PursueState
- -- TargetDead: Check if target is dead.
- local TargetDead = StateMachine.NewCondition()
- TargetDead.Name = "TargetDead"
- TargetDead.Evaluate = function()
- if ZombieTarget and ZombieTarget.Humanoid then
- return ZombieTarget.Humanoid.Health <= 0
- end
- return true
- end
- TargetDead.TransitionState = IdleState
- -- GotDamaged: Check if NPC has taken damage
- local lastHealth = model.Humanoid.Health
- local GotDamaged = StateMachine.NewCondition()
- GotDamaged.Name = "GotDamaged"
- GotDamaged.Evaluate = function()
- if model then
- if lastHealth > model.Humanoid.Health then
- return true
- end
- end
- return false
- end
- GotDamaged.TransitionState = SearchState
- -- GotBored: Used to provide random state change.
- local GotBored = StateMachine.NewCondition()
- GotBored.Name = "GotBored"
- GotBored.Evaluate = function()
- local now = os.time()
- if now - lastBored > configs["BoredomDuration"] then
- local roll = math.random()
- if roll < configs["ChanceOfBoredom"] then
- lastBored = now
- if GotBored.TransitionState == SearchState then
- GotBored.TransitionState = IdleState
- else
- GotBored.TransitionState = SearchState
- end
- return true
- end
- end
- return false
- end
- GotBored.TransitionState = IdleState
- -- LostTarget: Checks clear line of sight
- local LostTarget = StateMachine.NewCondition()
- LostTarget.Name = "LostTarget"
- LostTarget.Evaluate = function()
- if true then return false end
- if ZombieTarget then
- if (ZombieTarget.Torso.Position - model.Torso.Position).magnitude > 10 then
- local toTarget = Ray.new(model.Torso.Position, (ZombieTarget.Torso.Position - model.Torso.Position))
- local part, position = game.Workspace:FindPartOnRay(toTarget, model)
- if not part or part.Parent ~= ZombieTarget then
- --print("Lost target!")
- ZombieTargetLastLocation = ZombieTarget.Torso.Position
- ZombieTarget = nil
- return true
- end
- end
- end
- return false
- end
- LostTarget.TransitionState = HuntState
- local WithinRange = StateMachine.NewCondition()
- WithinRange.Name = "WithinRange"
- WithinRange.Evaluate = function()
- if ZombieTarget then
- local distance = (model.Torso.Position - ZombieTarget.Torso.Position).magnitude
- if distance < configs["AttackRange"] then
- --print("Within attack range!")
- return true
- end
- end
- return false
- end
- WithinRange.TransitionState = AttackState
- local OutsideRange = StateMachine.NewCondition()
- OutsideRange.Name = "OutsideRange"
- OutsideRange.Evaluate = function()
- if ZombieTarget then
- local distance = (model.Torso.Position - ZombieTarget.Torso.Position).magnitude
- if distance > configs["AttackRange"] then
- --print("Outside attack range!")
- return true
- end
- end
- return false
- end
- OutsideRange.TransitionState = PursueState
- table.insert(IdleState.Conditions, CanSeeTarget)
- table.insert(IdleState.Conditions, GotDamaged)
- table.insert(IdleState.Conditions, GotBored)
- table.insert(SearchState.Conditions, GotBored)
- table.insert(SearchState.Conditions, CanSeeTarget)
- table.insert(PursueState.Conditions, LostTarget)
- table.insert(PursueState.Conditions, WithinRange)
- table.insert(PursueState.Conditions, TargetDead)
- table.insert(AttackState.Conditions, OutsideRange)
- table.insert(AttackState.Conditions, TargetDead)
- table.insert(HuntState.Conditions, GotBored)
- table.insert(HuntState.Conditions, CanSeeTarget)
- -- Setup arms damage
- local canHit = true
- local lastHit = os.time()
- local function handleHit(other)
- if canHit then
- if other and other.Parent and other.Parent.Name ~= "Drooling Zombie" and other.Parent:FindFirstChild("Humanoid") then
- local enemy = other.Parent
- if enemy.Humanoid.WalkSpeed > 0 then
- enemy.Humanoid.Health = enemy.Humanoid.Health - configs["Damage"]
- canHit = false
- end
- end
- else
- local now = os.time()
- if now - lastHit > configs["DamageCooldown"] then
- lastHit = now
- canHit = true
- end
- end
- end
- local leftHitConnect, rightHitConnect
- leftHitConnect = model:FindFirstChild("Left Arm").Touched:connect(handleHit)
- rightHitConnect = model:FindFirstChild("Right Arm").Touched:connect(handleHit)
- --ZombieAI.Animate(model)
- --updateDisplay()
- --updateDisplay(model.BillboardGui.TextLabel, StateMachine.CurrentState)
- local thread = coroutine.create(function()
- while true do
- wait()
- -- calculate repulsion force
- local humanoids = HumanoidList:GetCurrent()
- local localZombies = {}
- for _, humanoid in pairs(humanoids) do
- if humanoid and humanoid ~= model.Humanoid and humanoid.Parent and humanoid.Parent:FindFirstChild("Torso") then
- local torso = humanoid.Parent:FindFirstChild("Torso")
- local distance = (model.Torso.Position - torso.Position).magnitude
- if distance <= 2.5 then
- table.insert(localZombies, torso.Position)
- end
- end
- end
- local repulsionDirection = AIUtilities:GetRepulsionVector(model.Torso.Position, localZombies)
- if repulsionDirection.magnitude > 0 then
- --print("replusion direction: " .. tostring(repulsionDirection))
- end
- model.Torso.RepulsionForce.force = repulsionDirection
- if StateMachine.CurrentState and model.Configurations.Debug.Value then
- model.BillboardGui.TextLabel.Visible = true
- model.BillboardGui.TextLabel.Text = StateMachine.CurrentState.Name
- end
- if not model.Configurations.Debug.Value then
- model.BillboardGui.TextLabel.Visible = false
- end
- end
- end)
- coroutine.resume(thread)
- StateMachine.SwitchState(IdleState)
- zombie.Stop = function()
- StateMachine.SwitchState(nil)
- end
- return zombie
- end
- return ZombieAI end;
- function() local PathfindingUtility = {}
- local TargetOffsetMax = 10--5
- local JumpThreshold = 1.5 --2.5
- local NextPointThreshold = 4
- local PathfindingService = game:GetService("PathfindingService")
- PathfindingService.EmptyCutoff = .3
- function PathfindingUtility.new()
- local this = {}
- local currentTargetPos = nil
- local lastTargetPos = Vector3.new(math.huge, math.huge, math.huge)
- local path = nil
- local currentPointIndex = 1
- function this:MoveToTarget(character, target)
- local targetOffset = (lastTargetPos - target).magnitude
- --
- -- local targetOffsetVector = (lastTargetPos - target)
- -- if targetOffsetVector.magnitude < math.huge then
- -- targetOffsetVector = (lastTargetPos - target) * Vector3.new(1,0,1)
- -- end
- if targetOffset > TargetOffsetMax then
- --if targetOffsetVector.magnitude > TargetOffsetMax then
- --print("moveto")
- local startPoint = character.Torso.Position
- local humanoidState = character.Humanoid:GetState()
- if humanoidState == Enum.HumanoidStateType.Jumping or humanoidState == Enum.HumanoidStateType.Freefall then
- --print("this")
- local ray = Ray.new(character.Torso.Position, Vector3.new(0, -100, 0))
- local hitPart, hitPoint = game.Workspace:FindPartOnRay(ray, character)
- if hitPart then
- startPoint = hitPoint
- end
- end
- --print("making new path")
- local newTarget = target
- local ray = Ray.new(target + Vector3.new(0,-3,0), Vector3.new(0, -100, 0))
- local hitPart, hitPoint = game.Workspace:FindPartOnRay(ray, character)
- if hitPoint then
- if (hitPoint - target).magnitude > 4 then
- newTarget = newTarget * Vector3.new(1,0,1) + Vector3.new(0,3,0)
- end
- end
- --local newTarget = Vector3.new(1,0,1) * target + Vector3.new(0, 2, 0)
- path = PathfindingService:ComputeSmoothPathAsync(startPoint, newTarget, 500)
- if path.Status ~= Enum.PathStatus.Success then
- --print(tostring(path.Status))
- end
- --path = PathfindingService:ComputeRawPathAsync(startPoint, target, 500)
- -- game.Workspace.Points:ClearAllChildren()
- -- local ps = path:GetPointCoordinates()
- -- for _, point in pairs(ps) do
- -- local part = Instance.new("Part", game.Workspace.Points)
- -- part.CanCollide = false
- -- part.Anchored = true
- -- part.FormFactor = Enum.FormFactor.Custom
- -- part.Size = Vector3.new(1,1,1)
- -- part.Position = point
- -- end
- currentPointIndex = 1
- lastTargetPos = target
- end
- if path then
- local points = path:GetPointCoordinates()
- if currentPointIndex < #points then
- local currentPoint = points[currentPointIndex]
- local distance = (character.Torso.Position - currentPoint).magnitude
- if distance < NextPointThreshold then
- currentPointIndex = currentPointIndex + 1
- end
- character.Humanoid:MoveTo(points[currentPointIndex])
- if points[currentPointIndex].Y - character.Torso.Position.Y > JumpThreshold then
- character.Humanoid.Jump = true
- end
- else
- character.Humanoid:MoveTo(target)
- end
- end
- end
- return this
- end
- return PathfindingUtility end;}local ActualModules = {}
- local _og_require = require
- local ModuleCache = {}
- function fake_require(a)
- local am,mc = ActualModules[a],ModuleCache[a]
- if typeof(a)=='Instance' and a:IsA("ModuleScript") and (am or mc) then
- if mc then
- return mc
- end
- local func = am
- local res = func()
- ModuleCache[a] = res
- ActualModules[a] = nil
- return res
- else
- local a,b = pcall(_og_require,a)
- if not a then
- error(b,2)
- else
- return b
- end
- end
- end
- function ms(var)
- local func = table.remove(ModuleScripts,1)
- setfenv(func,setmetatable({script=var,require=fake_require,global=genv},{
- __index = getfenv(func),
- }))
- ActualModules[var] = func
- end
- local Scripts = {
- function() -- Created by Quenty (@Quenty, follow me on twitter).
- -- Should work with only ONE copy, seamlessly with weapons, trains, et cetera.
- -- Parts should be ANCHORED before use. It will, however, store relatives values and so when tools are reparented, it'll fix them.
- --[[ INSTRUCTIONS
- - Place in the model
- - Make sure model is anchored
- - That's it. It will weld the model and all children.
- THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED.
- THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED.
- THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED.
- THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED.
- THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED.
- THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED.
- THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED.
- THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED.
- This script is designed to be used is a regular script. In a local script it will weld, but it will not attempt to handle ancestory changes.
- ]]
- --[[ DOCUMENTATION
- - Will work in tools. If ran more than once it will not create more than one weld. This is especially useful for tools that are dropped and then picked up again.
- - Will work in PBS servers
- - Will work as long as it starts out with the part anchored
- - Stores the relative CFrame as a CFrame value
- - Takes careful measure to reduce lag by not having a joint set off or affected by the parts offset from origin
- - Utilizes a recursive algorith to find all parts in the model
- - Will reweld on script reparent if the script is initially parented to a tool.
- - Welds as fast as possible
- ]]
- -- qPerfectionWeld.lua
- -- Created 10/6/2014
- -- Author: Quenty
- -- Version 1.0.3
- -- Updated 10/14/2014 - Updated to 1.0.1
- --- Bug fix with existing ROBLOX welds ? Repro by asimo3089
- -- Updated 10/14/2014 - Updated to 1.0.2
- --- Fixed bug fix.
- -- Updated 10/14/2014 - Updated to 1.0.3
- --- Now handles joints semi-acceptably. May be rather hacky with some joints. :/
- local NEVER_BREAK_JOINTS = false -- If you set this to true it will never break joints (this can create some welding issues, but can save stuff like hinges).
- local function CallOnChildren(Instance, FunctionToCall)
- -- Calls a function on each of the children of a certain object, using recursion.
- FunctionToCall(Instance)
- for _, Child in next, Instance:GetChildren() do
- CallOnChildren(Child, FunctionToCall)
- end
- end
- local function GetNearestParent(Instance, ClassName)
- -- Returns the nearest parent of a certain class, or returns nil
- local Ancestor = Instance
- repeat
- Ancestor = Ancestor.Parent
- if Ancestor == nil then
- return nil
- end
- until Ancestor:IsA(ClassName)
- return Ancestor
- end
- local function GetBricks(StartInstance)
- local List = {}
- -- if StartInstance:IsA("BasePart") then
- -- List[#List+1] = StartInstance
- -- end
- CallOnChildren(StartInstance, function(Item)
- if Item:IsA("BasePart") then
- List[#List+1] = Item;
- end
- end)
- return List
- end
- local function Modify(Instance, Values)
- -- Modifies an Instance by using a table.
- assert(type(Values) == "table", "Values is not a table");
- for Index, Value in next, Values do
- if type(Index) == "number" then
- Value.Parent = Instance
- else
- Instance[Index] = Value
- end
- end
- return Instance
- end
- local function Make(ClassType, Properties)
- -- Using a syntax hack to create a nice way to Make new items.
- return Modify(Instance.new(ClassType), Properties)
- end
- local Surfaces = {"TopSurface", "BottomSurface", "LeftSurface", "RightSurface", "FrontSurface", "BackSurface"}
- local HingSurfaces = {"Hinge", "Motor", "SteppingMotor"}
- local function HasWheelJoint(Part)
- for _, SurfaceName in pairs(Surfaces) do
- for _, HingSurfaceName in pairs(HingSurfaces) do
- if Part[SurfaceName].Name == HingSurfaceName then
- return true
- end
- end
- end
- return false
- end
- local function ShouldBreakJoints(Part)
- --- We do not want to break joints of wheels/hinges. This takes the utmost care to not do this. There are
- -- definitely some edge cases.
- if NEVER_BREAK_JOINTS then
- return false
- end
- if HasWheelJoint(Part) then
- return false
- end
- local Connected = Part:GetConnectedParts()
- if #Connected == 1 then
- return false
- end
- for _, Item in pairs(Connected) do
- if HasWheelJoint(Item) then
- return false
- elseif not Item:IsDescendantOf(script.Parent) then
- return false
- end
- end
- return true
- end
- local function WeldTogether(Part0, Part1, JointType, WeldParent)
- --- Weld's 2 parts together
- -- @param Part0 The first part
- -- @param Part1 The second part (Dependent part most of the time).
- -- @param [JointType] The type of joint. Defaults to weld.
- -- @param [WeldParent] Parent of the weld, Defaults to Part0 (so GC is better).
- -- @return The weld created.
- JointType = JointType or "Weld"
- local RelativeValue = Part1:FindFirstChild("qRelativeCFrameWeldValue")
- local NewWeld = Part1:FindFirstChild("qCFrameWeldThingy") or Instance.new(JointType)
- Modify(NewWeld, {
- Name = "qCFrameWeldThingy";
- Part0 = Part0;
- Part1 = Part1;
- C0 = CFrame.new();--Part0.CFrame:inverse();
- C1 = RelativeValue and RelativeValue.Value or Part1.CFrame:toObjectSpace(Part0.CFrame); --Part1.CFrame:inverse() * Part0.CFrame;-- Part1.CFrame:inverse();
- Parent = Part1;
- })
- if not RelativeValue then
- RelativeValue = Make("CFrameValue", {
- Parent = Part1;
- Name = "qRelativeCFrameWeldValue";
- Archivable = true;
- Value = NewWeld.C1;
- })
- end
- return NewWeld
- end
- local function WeldParts(Parts, MainPart, JointType, DoNotUnanchor)
- -- @param Parts The Parts to weld. Should be anchored to prevent really horrible results.
- -- @param MainPart The part to weld the model to (can be in the model).
- -- @param [JointType] The type of joint. Defaults to weld.
- -- @parm DoNotUnanchor Boolean, if true, will not unachor the model after cmopletion.
- for _, Part in pairs(Parts) do
- if ShouldBreakJoints(Part) then
- Part:BreakJoints()
- end
- end
- for _, Part in pairs(Parts) do
- if Part ~= MainPart then
- WeldTogether(MainPart, Part, JointType, MainPart)
- end
- end
- if not DoNotUnanchor then
- for _, Part in pairs(Parts) do
- Part.Anchored = false
- end
- MainPart.Anchored = false
- end
- end
- local function PerfectionWeld()
- local Tool = GetNearestParent(script, "Tool")
- local Parts = GetBricks(script.Parent)
- local PrimaryPart = Tool and Tool:FindFirstChild("Handle") and Tool.Handle:IsA("BasePart") and Tool.Handle or script.Parent:IsA("Model") and script.Parent.PrimaryPart or Parts[1]
- if PrimaryPart then
- WeldParts(Parts, PrimaryPart, "Weld", false)
- else
- warn("qWeld - Unable to weld part")
- end
- return Tool
- end
- local Tool = PerfectionWeld()
- if Tool and script.ClassName == "Script" then
- --- Don't bother with local scripts
- script.Parent.AncestryChanged:connect(function()
- PerfectionWeld()
- end)
- end
- -- Created by Quenty (@Quenty, follow me on twitter).
- end;
- function() function waitForChild(parent, childName)
- local child = parent:findFirstChild(childName)
- if child then return child end
- while true do
- child = parent.ChildAdded:wait()
- if child.Name==childName then return child end
- end
- end
- local Figure = script.Parent
- local Torso = waitForChild(Figure, "Torso")
- local RightShoulder = waitForChild(Torso, "Right Shoulder")
- local LeftShoulder = waitForChild(Torso, "Left Shoulder")
- local RightHip = waitForChild(Torso, "Right Hip")
- local LeftHip = waitForChild(Torso, "Left Hip")
- local Neck = waitForChild(Torso, "Neck")
- local Humanoid = waitForChild(Figure, "Humanoid")
- local pose = "Standing"
- local currentAnim = ""
- local currentAnimTrack = nil
- local currentAnimKeyframeHandler = nil
- local currentAnimSpeed = 1.0
- local animTable = {}
- local animNames = {
- idle = {
- { id = "http://www.roblox.com/asset/?id=125750544", weight = 9 },
- { id = "http://www.roblox.com/asset/?id=125750618", weight = 1 }
- },
- walk = {
- { id = "http://www.roblox.com/asset/?id=125749145", weight = 10 }
- },
- run = {
- { id = "run.xml", weight = 10 }
- },
- jump = {
- { id = "http://www.roblox.com/asset/?id=125750702", weight = 10 }
- },
- fall = {
- { id = "http://www.roblox.com/asset/?id=125750759", weight = 10 }
- },
- climb = {
- { id = "http://www.roblox.com/asset/?id=125750800", weight = 10 }
- },
- toolnone = {
- { id = "http://www.roblox.com/asset/?id=125750867", weight = 10 }
- },
- toolslash = {
- { id = "http://www.roblox.com/asset/?id=129967390", weight = 10 }
- -- { id = "slash.xml", weight = 10 }
- },
- toollunge = {
- { id = "http://www.roblox.com/asset/?id=129967478", weight = 10 }
- },
- wave = {
- { id = "http://www.roblox.com/asset/?id=128777973", weight = 10 }
- },
- point = {
- { id = "http://www.roblox.com/asset/?id=128853357", weight = 10 }
- },
- dance = {
- { id = "http://www.roblox.com/asset/?id=130018893", weight = 10 },
- { id = "http://www.roblox.com/asset/?id=132546839", weight = 10 },
- { id = "http://www.roblox.com/asset/?id=132546884", weight = 10 }
- },
- dance2 = {
- { id = "http://www.roblox.com/asset/?id=160934142", weight = 10 },
- { id = "http://www.roblox.com/asset/?id=160934298", weight = 10 },
- { id = "http://www.roblox.com/asset/?id=160934376", weight = 10 }
- },
- dance3 = {
- { id = "http://www.roblox.com/asset/?id=160934458", weight = 10 },
- { id = "http://www.roblox.com/asset/?id=160934530", weight = 10 },
- { id = "http://www.roblox.com/asset/?id=160934593", weight = 10 }
- },
- laugh = {
- { id = "http://www.roblox.com/asset/?id=129423131", weight = 10 }
- },
- cheer = {
- { id = "http://www.roblox.com/asset/?id=129423030", weight = 10 }
- },
- }
- -- Existance in this list signifies that it is an emote, the value indicates if it is a looping emote
- local emoteNames = { wave = false, point = false, dance = true, dance2 = true, dance3 = true, laugh = false, cheer = false}
- math.randomseed(tick())
- function configureAnimationSet(name, fileList)
- if (animTable[name] ~= nil) then
- for _, connection in pairs(animTable[name].connections) do
- connection:disconnect()
- end
- end
- animTable[name] = {}
- animTable[name].count = 0
- animTable[name].totalWeight = 0
- animTable[name].connections = {}
- -- check for config values
- local config = script:FindFirstChild(name)
- if (config ~= nil) then
- -- print("Loading anims " .. name)
- table.insert(animTable[name].connections, config.ChildAdded:connect(function(child) configureAnimationSet(name, fileList) end))
- table.insert(animTable[name].connections, config.ChildRemoved:connect(function(child) configureAnimationSet(name, fileList) end))
- local idx = 1
- for _, childPart in pairs(config:GetChildren()) do
- if (childPart:IsA("Animation")) then
- table.insert(animTable[name].connections, childPart.Changed:connect(function(property) configureAnimationSet(name, fileList) end))
- animTable[name][idx] = {}
- animTable[name][idx].anim = childPart
- local weightObject = childPart:FindFirstChild("Weight")
- if (weightObject == nil) then
- animTable[name][idx].weight = 1
- else
- animTable[name][idx].weight = weightObject.Value
- end
- animTable[name].count = animTable[name].count + 1
- animTable[name].totalWeight = animTable[name].totalWeight + animTable[name][idx].weight
- -- print(name .. " [" .. idx .. "] " .. animTable[name][idx].anim.AnimationId .. " (" .. animTable[name][idx].weight .. ")")
- idx = idx + 1
- end
- end
- end
- -- fallback to defaults
- if (animTable[name].count <= 0) then
- for idx, anim in pairs(fileList) do
- animTable[name][idx] = {}
- animTable[name][idx].anim = Instance.new("Animation")
- animTable[name][idx].anim.Name = name
- animTable[name][idx].anim.AnimationId = anim.id
- animTable[name][idx].weight = anim.weight
- animTable[name].count = animTable[name].count + 1
- animTable[name].totalWeight = animTable[name].totalWeight + anim.weight
- -- print(name .. " [" .. idx .. "] " .. anim.id .. " (" .. anim.weight .. ")")
- end
- end
- end
- -- Setup animation objects
- function scriptChildModified(child)
- local fileList = animNames[child.Name]
- if (fileList ~= nil) then
- configureAnimationSet(child.Name, fileList)
- end
- end
- script.ChildAdded:connect(scriptChildModified)
- script.ChildRemoved:connect(scriptChildModified)
- for name, fileList in pairs(animNames) do
- configureAnimationSet(name, fileList)
- end
- -- ANIMATION
- -- declarations
- local toolAnim = "None"
- local toolAnimTime = 0
- local jumpAnimTime = 0
- local jumpAnimDuration = 0.3
- local toolTransitionTime = 0.1
- local fallTransitionTime = 0.3
- local jumpMaxLimbVelocity = 0.75
- -- functions
- function stopAllAnimations()
- local oldAnim = currentAnim
- -- return to idle if finishing an emote
- if (emoteNames[oldAnim] ~= nil and emoteNames[oldAnim] == false) then
- oldAnim = "idle"
- end
- currentAnim = ""
- if (currentAnimKeyframeHandler ~= nil) then
- currentAnimKeyframeHandler:disconnect()
- end
- if (currentAnimTrack ~= nil) then
- currentAnimTrack:Stop()
- currentAnimTrack:Destroy()
- currentAnimTrack = nil
- end
- return oldAnim
- end
- function setAnimationSpeed(speed)
- if speed ~= currentAnimSpeed then
- currentAnimSpeed = speed
- currentAnimTrack:AdjustSpeed(currentAnimSpeed)
- end
- end
- function keyFrameReachedFunc(frameName)
- if (frameName == "End") then
- -- print("Keyframe : ".. frameName)
- local repeatAnim = stopAllAnimations()
- local animSpeed = currentAnimSpeed
- playAnimation(repeatAnim, 0.0, Humanoid)
- setAnimationSpeed(animSpeed)
- end
- end
- -- Preload animations
- function playAnimation(animName, transitionTime, humanoid)
- local idleFromEmote = (animName == "idle" and emoteNames[currentAnim] ~= nil)
- if (animName ~= currentAnim and not idleFromEmote) then
- if (currentAnimTrack ~= nil) then
- currentAnimTrack:Stop(transitionTime)
- currentAnimTrack:Destroy()
- end
- currentAnimSpeed = 1.0
- local roll = math.random(1, animTable[animName].totalWeight)
- local origRoll = roll
- local idx = 1
- while (roll > animTable[animName][idx].weight) do
- roll = roll - animTable[animName][idx].weight
- idx = idx + 1
- end
- -- print(animName .. " " .. idx .. " [" .. origRoll .. "]")
- local anim = animTable[animName][idx].anim
- -- load it to the humanoid; get AnimationTrack
- currentAnimTrack = humanoid:LoadAnimation(anim)
- -- play the animation
- currentAnimTrack:Play(transitionTime)
- currentAnim = animName
- -- set up keyframe name triggers
- if (currentAnimKeyframeHandler ~= nil) then
- currentAnimKeyframeHandler:disconnect()
- end
- currentAnimKeyframeHandler = currentAnimTrack.KeyframeReached:connect(keyFrameReachedFunc)
- end
- end
- -------------------------------------------------------------------------------------------
- -------------------------------------------------------------------------------------------
- local toolAnimName = ""
- local toolAnimTrack = nil
- local currentToolAnimKeyframeHandler = nil
- function toolKeyFrameReachedFunc(frameName)
- if (frameName == "End") then
- -- print("Keyframe : ".. frameName)
- local repeatAnim = stopToolAnimations()
- playToolAnimation(repeatAnim, 0.0, Humanoid)
- end
- end
- function playToolAnimation(animName, transitionTime, humanoid)
- if (animName ~= toolAnimName) then
- if (toolAnimTrack ~= nil) then
- toolAnimTrack:Stop()
- toolAnimTrack:Destroy()
- transitionTime = 0
- end
- local roll = math.random(1, animTable[animName].totalWeight)
- local origRoll = roll
- local idx = 1
- while (roll > animTable[animName][idx].weight) do
- roll = roll - animTable[animName][idx].weight
- idx = idx + 1
- end
- -- print(animName .. " * " .. idx .. " [" .. origRoll .. "]")
- local anim = animTable[animName][idx].anim
- -- load it to the humanoid; get AnimationTrack
- toolAnimTrack = humanoid:LoadAnimation(anim)
- -- play the animation
- toolAnimTrack:Play(transitionTime)
- toolAnimName = animName
- currentToolAnimKeyframeHandler = toolAnimTrack.KeyframeReached:connect(toolKeyFrameReachedFunc)
- end
- end
- function stopToolAnimations()
- local oldAnim = toolAnimName
- if (currentToolAnimKeyframeHandler ~= nil) then
- currentToolAnimKeyframeHandler:disconnect()
- end
- toolAnimName = ""
- if (toolAnimTrack ~= nil) then
- toolAnimTrack:Stop()
- toolAnimTrack:Destroy()
- toolAnimTrack = nil
- end
- return oldAnim
- end
- -------------------------------------------------------------------------------------------
- -------------------------------------------------------------------------------------------
- function onRunning(speed)
- if speed>0.01 then
- playAnimation("walk", 0.1, Humanoid)
- pose = "Running"
- else
- playAnimation("idle", 0.1, Humanoid)
- pose = "Standing"
- end
- end
- function onDied()
- pose = "Dead"
- end
- function onJumping()
- playAnimation("jump", 0.1, Humanoid)
- jumpAnimTime = jumpAnimDuration
- pose = "Jumping"
- end
- function onClimbing(speed)
- playAnimation("climb", 0.1, Humanoid)
- setAnimationSpeed(speed / 12.0)
- pose = "Climbing"
- end
- function onGettingUp()
- pose = "GettingUp"
- end
- function onFreeFall()
- if (jumpAnimTime <= 0) then
- playAnimation("fall", fallTransitionTime, Humanoid)
- end
- pose = "FreeFall"
- end
- function onFallingDown()
- pose = "FallingDown"
- end
- function onSeated()
- pose = "Seated"
- end
- function onPlatformStanding()
- pose = "PlatformStanding"
- end
- function onSwimming(speed)
- if speed>0 then
- pose = "Running"
- else
- pose = "Standing"
- end
- end
- function getTool()
- for _, kid in ipairs(Figure:GetChildren()) do
- if kid.className == "Tool" then return kid end
- end
- return nil
- end
- function getToolAnim(tool)
- for _, c in ipairs(tool:GetChildren()) do
- if c.Name == "toolanim" and c.className == "StringValue" then
- return c
- end
- end
- return nil
- end
- function animateTool()
- if (toolAnim == "None") then
- playToolAnimation("toolnone", toolTransitionTime, Humanoid)
- return
- end
- if (toolAnim == "Slash") then
- playToolAnimation("toolslash", 0, Humanoid)
- return
- end
- if (toolAnim == "Lunge") then
- playToolAnimation("toollunge", 0, Humanoid)
- return
- end
- end
- function moveSit()
- RightShoulder.MaxVelocity = 0.15
- LeftShoulder.MaxVelocity = 0.15
- RightShoulder:SetDesiredAngle(3.14 /2)
- LeftShoulder:SetDesiredAngle(-3.14 /2)
- RightHip:SetDesiredAngle(3.14 /2)
- LeftHip:SetDesiredAngle(-3.14 /2)
- end
- local lastTick = 0
- function move(time)
- local amplitude = 1
- local frequency = 1
- local deltaTime = time - lastTick
- lastTick = time
- local climbFudge = 0
- local setAngles = false
- if (jumpAnimTime > 0) then
- jumpAnimTime = jumpAnimTime - deltaTime
- end
- if (pose == "FreeFall" and jumpAnimTime <= 0) then
- playAnimation("fall", fallTransitionTime, Humanoid)
- elseif (pose == "Seated") then
- stopAllAnimations()
- moveSit()
- return
- elseif (pose == "Running") then
- playAnimation("walk", 0.1, Humanoid)
- elseif (pose == "Dead" or pose == "GettingUp" or pose == "FallingDown" or pose == "Seated" or pose == "PlatformStanding") then
- -- print("Wha " .. pose)
- amplitude = 0.1
- frequency = 1
- setAngles = true
- end
- if (setAngles) then
- desiredAngle = amplitude * math.sin(time * frequency)
- RightShoulder:SetDesiredAngle(desiredAngle + climbFudge)
- LeftShoulder:SetDesiredAngle(desiredAngle - climbFudge)
- RightHip:SetDesiredAngle(-desiredAngle)
- LeftHip:SetDesiredAngle(-desiredAngle)
- end
- -- Tool Animation handling
- local tool = getTool()
- if tool then
- animStringValueObject = getToolAnim(tool)
- if animStringValueObject then
- toolAnim = animStringValueObject.Value
- -- message recieved, delete StringValue
- animStringValueObject.Parent = nil
- toolAnimTime = time + .3
- end
- if time > toolAnimTime then
- toolAnimTime = 0
- toolAnim = "None"
- end
- animateTool()
- else
- stopToolAnimations()
- toolAnim = "None"
- toolAnimTime = 0
- end
- end
- -- connect events
- Humanoid.Died:connect(onDied)
- Humanoid.Running:connect(onRunning)
- Humanoid.Jumping:connect(onJumping)
- Humanoid.Climbing:connect(onClimbing)
- Humanoid.GettingUp:connect(onGettingUp)
- Humanoid.FreeFalling:connect(onFreeFall)
- Humanoid.FallingDown:connect(onFallingDown)
- Humanoid.Seated:connect(onSeated)
- Humanoid.PlatformStanding:connect(onPlatformStanding)
- Humanoid.Swimming:connect(onSwimming)
- -- main program
- local runService = game:service("RunService");
- -- initialize to idle
- playAnimation("idle", 0.1, Humanoid)
- pose = "Standing"
- while Figure.Parent~=nil do
- local _, time = wait(0.1)
- move(time)
- end
- end;
- function() local zombie = script.Parent
- for _, script in pairs(zombie.ModuleScripts:GetChildren()) do
- if not game.ServerStorage:FindFirstChild(script.Name) then
- script:Clone().Parent = game.ServerStorage
- end
- end
- local AI = require(game.ServerStorage.ROBLOX_ZombieAI).new(zombie)
- local DestroyService = require(game.ServerStorage.ROBLOX_DestroyService)
- local function clearParts(parent)
- for _, part in pairs(parent:GetChildren()) do
- clearParts(part)
- end
- local delay
- if parent:IsA("Part") then
- delay = math.random(5,10)
- else
- delay = 11
- end
- DestroyService:AddItem(parent, delay)
- end
- zombie.Humanoid.Died:connect(function()
- AI.Stop()
- math.randomseed(tick())
- clearParts(zombie)
- script.Disabled = true
- end)
- local lastMoan = os.time()
- math.randomseed(os.time())
- while true do
- local animationTrack = zombie.Humanoid:LoadAnimation(zombie.Animations.Arms)
- animationTrack:Play()
- -- local now = os.time()
- -- if now - lastMoan > 5 then
- -- if math.random() > .3 then
- -- zombie.Moan:Play()
- ---- print("playing moan")
- -- lastMoan = now
- -- end
- -- end
- wait(2)
- end
- end;}local ActualScripts = {}
- function s(var)
- local func = table.remove(Scripts,1)
- setfenv(func,setmetatable({script=var,require=fake_require or require,global=genv},{
- __index = getfenv(func),
- }))
- table.insert(ActualScripts,coroutine.wrap(func))
- end
- local Part_Classes = {"Part","WedgePart","CornerWedgePart"}
- local Part_Shapes = {"Brick","Cylinder","Sphere","Torso","Wedge"}
- function DecodeUnion(t)
- local r = function()return table.remove(t,1) end
- local split = function(str,sep)
- local fields = {}
- str:gsub(("([^%s]+)"):format(sep or ','),function(c)fields[#fields+1]=c end)
- return fields
- end
- local m = Instance.new("Folder")
- m.Name = "UnionCache ["..tostring(math.random(1,9999)).."]"
- m.Archivable = false
- m.Parent = game:GetService("ServerStorage")
- local Union,Subtract = {},{}
- repeat
- local isNegate = false
- local class = r()
- if class=='-' then
- isNegate = true
- class = r()
- end
- if class=='n' then
- local d = {}
- local a = r()
- repeat
- table.insert(d,a)
- a = r()
- until a=='p'
- local u = DecodeUnion(d)
- if u then
- table.insert(isNegate and Subtract or Union,u)
- end
- else
- local size,pos,rot = Vector3.new(unpack(split(r()))),Vector3.new(unpack(split(r()))),Vector3.new(unpack(split(r())))
- local part = Instance.new(Part_Classes[tonumber(class)])
- part.Size = size
- part.Position = pos
- part.Orientation = rot
- if r()=="+" then
- local m,ms,of = r(),Vector3.new(unpack(split(r()))),Vector3.new(unpack(split(r())))
- if tonumber(m)==6 then
- part.Shape = Enum.PartType.Cylinder
- elseif tonumber(m)==7 then
- part.Shape = Enum.PartType.Ball
- else
- local mesh = Instance.new(tonumber(m)==8 and "CylinderMesh" or "SpecialMesh")
- if tonumber(m)~=8 then
- mesh.MeshType = Enum.MeshType[Part_Shapes[tonumber(m)]]
- end
- mesh.Scale = ms
- mesh.Offset = of
- mesh.Parent = part
- end
- end
- table.insert(isNegate and Subtract or Union,part)
- end
- until #t<=0
- local first = Union[1]
- first.Parent = m
- if #Union>1 then
- first = first:UnionAsync(Union)
- first.Parent = m
- end
- if #Subtract>0 then
- first = first:SubtractAsync(Subtract)
- first.Parent = m
- end
- first.Parent = nil
- m:Destroy()
- return first
- end
- Decode = function(str,t,props,classes,values,ICList,Model,CurPar,LastIns,split,RemoveAndSplit,InstanceList)
- local tonum,table_remove,inst,parnt,comma,table_foreach = tonumber,table.remove,Instance.new,"Parent",",",
- function(t,f)
- for a,b in pairs(t) do
- f(a,b)
- end
- end
- local Types = {
- Color3 = Color3.new,
- Vector3 = Vector3.new,
- Vector2 = Vector2.new,
- UDim = UDim.new,
- UDim2 = UDim2.new,
- CFrame = CFrame.new,
- Rect = Rect.new,
- NumberRange = NumberRange.new,
- BrickColor = BrickColor.new,
- PhysicalProperties = PhysicalProperties.new,
- NumberSequence = function(...)
- local a = {...}
- local t = {}
- repeat
- t[#t+1] = NumberSequenceKeypoint.new(table_remove(a,1),table_remove(a,1),table_remove(a,1))
- until #a==0
- return NumberSequence.new(t)
- end,
- ColorSequence = function(...)
- local a = {...}
- local t = {}
- repeat
- t[#t+1] = ColorSequenceKeypoint.new(table_remove(a,1),Color3.new(table_remove(a,1),table_remove(a,1),table_remove(a,1)))
- until #a==0
- return ColorSequence.new(t)
- end,
- number = tonumber,
- boolean = function(a)
- return a=="1"
- end
- }
- split = function(str,sep)
- if not str then return end
- local fields = {}
- local ConcatNext = false
- str:gsub(("([^%s]+)"):format(sep),function(c)
- if ConcatNext == true then
- fields[#fields] = fields[#fields]..sep..c
- ConcatNext = false
- else
- fields[#fields+1] = c
- end
- if c:sub(#c)=="\\" then
- c = fields[#fields]
- fields[#fields] = c:sub(1,#c-1)
- ConcatNext = true
- end
- end)
- return fields
- end
- RemoveAndSplit = function(t)
- return split(table_remove(t,1),comma)
- end
- t = split(str,";")
- props = RemoveAndSplit(t)
- classes = RemoveAndSplit(t)
- values = split(table_remove(t,1),'|')
- ICList = RemoveAndSplit(t)
- InstanceList = {}
- Model = inst"Model"
- CurPar = Model
- table_foreach(t,function(ct,c)
- if c=="n" or c=="p" then
- CurPar = c=="n" and LastIns or CurPar[parnt]
- else
- ct = split(c,"|")
- local class = classes[tonum(table_remove(ct,1))]
- if class=="UnionOperation" then
- LastIns = {UsePartColor="1"}
- else
- LastIns = inst(class)
- if LastIns:IsA"Script" then
- s(LastIns)
- elseif LastIns:IsA("ModuleScript") then
- ms(LastIns)
- end
- end
- local function SetProperty(LastIns,p,str,s)
- s = Types[typeof(LastIns[p])]
- if p=="CustomPhysicalProperties" then
- s = PhysicalProperties.new
- end
- if s then
- LastIns[p] = s(unpack(split(str,comma)))
- else
- LastIns[p] = str
- end
- end
- local UnionData
- table_foreach(ct,function(s,p,a,str)
- a = p:find":"
- p,str = props[tonum(p:sub(1,a-1))],values[tonum(p:sub(a+1))]
- if p=="UnionData" then
- UnionData = split(str," ")
- return
- end
- if class=="UnionOperation" then
- LastIns[p] = str
- return
- end
- SetProperty(LastIns,p,str)
- end)
- if UnionData then
- local LI_Data = LastIns
- LastIns = DecodeUnion(UnionData)
- table_foreach(LI_Data,function(p,str)
- SetProperty(LastIns,p,str)
- end)
- end
- table.insert(InstanceList,LastIns)
- LastIns[parnt] = CurPar
- end
- end)
- table_remove(ICList,1)
- table_foreach(ICList,function(a,b)
- b = split(b,">")
- InstanceList[tonum(b[1])][props[tonum(b[2])]] = InstanceList[tonum(b[3])]
- end)
- return Model:GetChildren()
- end
- local Objects = Decode('Name,Color,Material,Transparency,Position,Orientation,Size,BottomSurface,TopSurface,MaxVelocity,C0,C1,Part0,Part1,Force,CanCollide,UnionData,SecondaryColor,MeshType,Scale,WalkSpeed,AnimationId,Value,S'
- ..'tudsOffset,BackgroundColor3,Visible,Font,Text,TextSize,MeshId,OverlayTextureId,BodyPart,PlaybackSpeed,SoundId,Volume,HeadColor3,LeftArmColor3,RightArmColor3,LeftLegColor3,RightLegColor3,TorsoColor3;Pa'
- ..'rt,Model,Motor6D,BodyForce,MeshPart,UnionOperation,SpecialMesh,Fire,WedgePart,Script,Humanoid,StringValue,Animation,NumberValue,BillboardGui,TextLabel,Configuration,ModuleScript,IntValue,BoolValue,Cha'
- ..'racterMesh,Sound,BodyColors;Part|Alien|HumanoidRootPart|0.1529,0.2745,0.1764|528|1|10.8326,3,-4.9814|0,-180,0|2,2,1|0|Root Hip|0.1|0,0,0,-1,0,0,0,0,1,0,1,-0|Torso|Left Hip|-1,-1,0,-0.0001,0,-1,0,0.999'
- ..'9,0,1,0,-0.0001|-0.5,1,0,-0.0001,0,-1,0,0.9999,0,1,0,-0.0001|Right Hip|1,-1,0,-0.0001,0,1,-0,0.9999,0,-1,0,-0.0001|0.5,1,0,-0.0001,0,1,0,0.9999,0,-1,0,-0.0001|Left Shoulder|-1,0.5,0,-0.0001,0,-1,0,0.9'
- ..'999,0,1,0,-0.0001|0.5,0.5,0,-0.0001,0,-1,0,0.9999,0,1,0,-0.0001|Right Shoulder|1,0.5,0,-0.0001,0,1,-0,0.9999,0,-1,0,-0.0001|-0.5,0.5,0,-0.0001,0,1,0,0.9999,0,-1,0,-0.0001|Neck|0,1,0,-1,0,0,0,0,1,0,1,-'
- ..'0|0,-0.5,0,-1,0,0,0,0,1,0,1,-0|RepulsionForce|0,0,0|EnhancedCone|0.0666,0.0666,0.0666|8.5537,3.2582,0.1622|0.1099,102.1299,-115.7201|0.65,3.43,0.6899|0|6.9107,3.4991,0.7543|4.01,110.25,-115.4301|12.00'
- ..'42,3.4991,-0.4154|4.01,97.25,-115.4301|11.741,4.2006,-7.0315|0,-180,179|1,8.3,1|13.7383,3.2583,-0.6227|0.1099,89.1299,-115.7201|12.8813,3.2653,-0.6246|1.85,92.7399,-115.6601|9.4665,4.2006,-7.0314|0,-1'
- ..'80,-179|7.7182,3.2653,0.3532|1.85,105.7399,-115.6601|1 1.4,0.1,2.0999 11.5368,22.368,-7.0307 11,-180,20 = 1 1.4,0.1,2.0999 11.4939,21.9654,-6.9524 11,-180,20 = 1 1.4,0.1,2.0999 11.563,24.4479,-7.435 1'
- ..'1,-180,20 = 1 1.4,0.1,2.0999 11.6059,24.8504,-7.5132 11,-180,20 = 1 1.3,0.1,2.0999 11.6183,23.5924,-7.2687 11,-180,20 = 1 1.3,0.1,2.0999 11.5755,23.1899,-7.1904 11,-180,20 = 1 1.3,0.1,2.0999 11.6359,2'
- ..'5.362,-7.6127 11,-180,20 = 1 1.2,0.1,2.0999 11.6142,24.0117,-7.3502 11,-180,20 = 1 1.3,0.1,2.0999 11.5326,22.7873,-7.1122 11,-180,20 = 1 1.4,0.1,2.0999 9.6829,21.96,-6.942 -10,0,20 = - 1 3,4,1.8999 10'
- ..'.6226,23.7248,-7.3232 -10,0,0 = 1 1.4,0.1,2.0999 9.6138,24.4504,-7.3811 -10,0,20 = 1 1.4,0.1,2.0999 9.571,24.8543,-7.4523 -10,0,20 = 1 1.4,0.1,2.0999 9.6401,22.3638,-7.0132 -10,0,20 = 1 1.3,0.1,2.0999'
- ..' 9.5585,23.5922,-7.2298 -10,0,20 = 1 1.3,0.1,2.0999 9.6014,23.1884,-7.1586 -10,0,20 = 1 1.2,0.1,2.0999 9.5627,24.0129,-7.304 -10,0,20 = 1 1.3,0.1,2.0999 9.5409,25.3675,-7.5428 -10,0,20 = 1 1.3,0.1,2.0'
- ..'999 9.6442,22.7845,-7.0874 -10,0,20 =|272|1 1.6799,1.7999,3.5 10.6226,28.6988,-7.274 -89,-179.9901,89.9899 + 3 1,1,1 0,0,0 - 1 2.2,0.7999,1.4999 11.6427,27.9628,-7.1194 7.0799,-13.79,-104.17 = - 1 2.2'
- ..',0.7999,1.4999 9.6427,27.9127,-7.1194 -5.77,-172.34,-106.0801 =|12.5844,5.3627,1.2817|14.9899,91.08,-172.4701|1,2.9,0.7199|8.7141,7.3797,1.2228|6.7699,111.5299,138.9499|9.6026,11.9995,-7.0315|0,0,-1|1'
- ..',8,1|13.2543,21.2706,-8.0611|-2.01,-0.02,5.9899|1,9,1|8.4037,5.2146,2.1408|7.0599,103.0199,-172.67|8.2175,7.4678,1.3948|14.9899,104.08,137.5299|8.9405,5.1787,1.8418|0.1099,102.1299,-172.7201|13.1335,7'
- ..'.4679,0.5026|14.9899,91.08,137.5299|11.6049,11.9995,-7.0315|0,0,1|13.5903,12.5909,-4.1252|-40.75,-4.99,1.9099|1,12,1|13.4512,7.4043,0.4775|11.2799,94.5199,138.32|13.7374,5.1787,1.1008|0.1099,89.1299,-'
- ..'172.7201|13.656,7.3797,0.4468|6.7699,98.5299,138.9499|10.6226,16.1002,-7.0315|2.6,1,0.9999|13.147,5.2147,1.2714|7.0599,90.0199,-172.67|7.7874,21.1478,-7.6363|-1.9701,22.3999,-6.02|10.6226,20.7467,-7.5'
- ..'143|-5,0,0|1,9.9,1|7.9246,12.5911,-3.4176|-40.7001,27.3999,-13.95|0.9294,0.9176,0.9176|100|10.6226,23.3742,-6.7404|1,1,1|8.5214,7.4043,1.2989|11.2799,107.5199,138.32|7.8577,5.3627,2.2774|14.9899,104.0'
- ..'8,-172.4701|10.6226,29.1661,-6.3885|1,-180,0|0.2,1,0.2999|Sphere|288|11.1726,29.2996,-6.7343|-84,-23,-90|0.4799,0.2999,0.2|3|10.0726,29.2996,-6.7342|-84,37,-90|10.6226,29.3818,-7.5542|-84,0,-90|2.1799'
- ..',2,2.6|10.6226,23.0424,-8.2423|-79,-180,90|1.3799,2,6|9.9726,16.8002,-7.0315|0,-90,0|1,0.3999,1.2999|11.2726,16.7502,-7.0315|0,90,0|1,0.2999,1.2999|qPerfectionWeld|Left Leg|11.3327,1,-4.9814|1,2,1|Rig'
- ..'ht Leg|10.3327,1,-4.9814|Left Arm|12.3326,3,-4.9814|Right Arm|9.3326,3,-4.9814|Head|0.2274,0.4901,0.0823|10.8326,4.5,-4.9814|2,1,1|1.25,1.25,1.25|21|Animate|climb|ClimbAnim|http://www.roblox.com/asset'
- ..'/?id=125750800|fall|FallAnim|http://www.roblox.com/asset/?id=125750759|idle|Animation1|http://www.roblox.com/asset/?id=125750544|Weight|9|Animation2|http://www.roblox.com/asset/?id=125750618|jump|Jump'
- ..'Anim|http://www.roblox.com/asset/?id=125750702|run|RunAnim|http://www.roblox.com/asset/?id=125749145|toolnone|ToolNoneAnim|http://www.roblox.com/asset/?id=125750867|walk|WalkAnim|0,100,0,30|0,5,0|1,0,'
- ..'1,0|4|Idle|24|ModuleScripts|ROBLOX_AIUtilities|ROBLOX_DestroyService|ROBLOX_HumanoidList|ROBLOX_StateMachine|ROBLOX_ZombieAI|ROBLOX_PathfindingLibrary|Configurations|Damage|30|Debug|FieldOfView|180|Ag'
- ..'groRange|200|Animations|Attack|http://www.roblox.com/asset/?id=180416148|Arms|http://www.roblox.com/asset/?id=183294396|Zombie Left Arm|37683097|37686282|2|Zombie Left Leg|37683150|37687646|Zombie Rig'
- ..'ht Arm|37683174|Zombie Right Leg|37683227|5|Zombie torso|37683263|1|Moan|0.15|http://www.roblox.com/asset/?id=12222242|0.05;0,3>13>2,3>14>4,5>13>4,5>14>75,6>13>4,6>14>76,7>13>4,7>14>77,8>13>4,8>14>78,'
- ..'9>13>4,9>14>79;2|1:2;n;1|1:3|2:4|3:5|4:6|5:7|6:8|7:9|8:10|9:10|2:4|2:4;n;3|1:11|10:12|11:13|12:13;p;1|1:14|2:4|3:5|4:6|5:7|6:8|7:9|8:10|9:10|2:4|2:4;n;3|1:15|10:12|11:16|12:17;3|1:18|10:12|11:19|12:20'
- ..';3|1:21|10:12|11:22|12:23;3|1:24|10:12|11:25|12:26;3|1:27|10:12|11:28|12:29;4|1:30|15:31;2|1:2;n;5|1:32|2:33|5:34|6:35|7:36|16:37|2:33|2:33;5|1:32|2:33|5:38|6:39|7:36|16:37|2:33|2:33;5|1:32|2:33|5:40|'
- ..'6:41|7:36|16:37|2:33|2:33;5|1:32|2:33|5:42|6:43|7:44|16:37|2:33|2:33;5|1:32|2:33|5:45|6:46|7:36|16:37|2:33|2:33;5|1:32|2:33|5:47|6:48|7:36|16:37|2:33|2:33;5|1:32|2:33|5:49|6:50|7:44|16:37|2:33|2:33;5|'
- ..'1:32|2:33|5:51|6:52|7:36|16:37|2:33|2:33;6|2:33|16:37|2:33|2:33|17:53;6|2:33|3:54|16:37|2:33|2:33|17:55;1|2:33|5:56|6:57|7:58|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:59|6:60|7:58|16:37|8:10|9:10|2:33'
- ..'|2:33;n;7;p;1|2:33|5:61|6:62|7:63|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:64|6:65|7:66|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:67|6:68|7:58|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:69|6:70|7:58|16:3'
- ..'7|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:71|6:72|7:58|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:73|6:74|7:58|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:75|6:76|7:63|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:7'
- ..'7|6:78|7:79|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:80|6:81|7:58|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:82|6:83|7:58|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:84|6:85|7:58|16:37|8:10|9:10|2:33|2:33;'
- ..'n;7;p;1|2:33|5:86|7:87|16:37|8:10|9:10|2:33|2:33;1|2:33|5:88|6:89|7:58|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:90|6:91|7:66|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:33|5:92|6:93|7:94|16:37|8:10|9:10|2:33|'
- ..'2:33;n;7;p;1|2:33|5:95|6:96|7:79|16:37|8:10|9:10|2:33|2:33;n;7;p;1|2:97|4:98|5:99|6:93|7:100|16:37|8:10|9:10|2:97|2:97;n;8|2:100|18:100|2:100|2:100;p;1|2:33|5:101|6:102|7:58|16:37|8:10|9:10|2:33|2:33;'
- ..'n;7;p;1|2:33|5:103|6:104|7:58|16:37|8:10|9:10|2:33|2:33;n;7;p;9|2:33|3:54|5:105|6:106|7:107|16:37|2:33|2:33;1|1:108|2:97|3:109|5:110|6:111|7:112|16:37|8:10|9:10|2:97|2:97;n;7|19:113;p;1|1:108|2:97|3:1'
- ..'09|5:114|6:115|7:112|16:37|8:10|9:10|2:97|2:97;n;7|19:113;p;1|1:108|2:33|3:54|5:116|6:117|7:118|16:37|8:10|9:10|2:33|2:33;n;7|19:113;p;1|1:108|2:33|3:54|5:119|6:120|7:121|16:37|8:10|9:10|2:33|2:33;n;7'
- ..'|19:113;p;9|2:33|5:122|6:123|7:124|16:37|8:10|2:33|2:33;9|2:33|5:125|6:126|7:127|16:37|8:10|2:33|2:33;p;10|1:128;p;1|1:129|2:4|3:5|4:6|5:130|6:8|7:131|16:37|8:10|9:10|2:4|2:4;1|1:132|2:4|3:5|4:6|5:133'
- ..'|6:8|7:131|16:37|8:10|9:10|2:4|2:4;1|1:134|2:4|3:5|4:6|5:135|6:8|7:131|16:37|8:10|9:10|2:4|2:4;1|1:136|2:4|3:5|4:6|5:137|6:8|7:131|16:37|8:10|9:10|2:4|2:4;1|1:138|2:139|3:5|4:6|5:140|6:8|7:141|8:10|9:'
- ..'10|2:139|2:139;n;7|20:142;p;11|21:143;10|1:144;n;12|1:145;n;13|1:146|22:147;p;12|1:148;n;13|1:149|22:150;p;12|1:151;n;13|1:152|22:153;n;14|1:154|23:155;p;13|1:156|22:157;n;14|1:154|23:6;p;p;12|1:158;n'
- ..';13|1:159|22:160;p;12|1:161;n;13|1:162|22:163;p;12|1:164;n;13|1:165|22:166;p;12|1:167;n;13|1:168|22:163;p;p;10;15|7:169|24:170;n;16|7:171|25:100|26:37|27:172|28:173|29:174;p;17|1:175;n;18|1:176;18|1:1'
- ..'77;18|1:178;18|1:179;18|1:180;18|1:181;p;17|1:182;n;19|1:183|23:184;20|1:185;19|1:186|23:187;19|1:188|23:189;p;17|1:190;n;13|1:191|22:192;13|1:193|22:194;p;21|1:195|30:196|31:197|32:198;21|1:199|30:20'
- ..'0|31:201|32:172;21|1:202|30:203|31:197|32:113;21|1:204|30:205|31:201|32:206;21|1:207|30:208|31:197|32:209;22|1:210|33:211|34:212|35:213;23|36:139|37:4|38:4|39:4|40:4|41:4;p;')
- for _,Object in pairs(Objects) do
- Object.Parent = script and script.Parent==workspace and script or workspace
- end
- for _,f in pairs(ActualScripts) do f() end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement