-- Made by LazaroValkyrie
-- Crystal PvP
if game:GetService("RunService"):IsStudio() then
owner = nil
end
local block_size = 2.5
local y_offset = Vector3.new(0,-block_size/2,0)
local hitbox_allowance = Vector3.new(0.05,0.05,0.05)
local BlockVector3 = Vector3.new(block_size,block_size,block_size)
local config = {
range = 5,
place_crystal = true,
place_support_block = true,
attack_placed_crystals = false,
surround_speed = 1/10,
auto_surround = false,
check_speed = 1/20,
place_speed = 0,
crystal_speed = 1/20,
max_self_damage = 8*5,
minimum_target_damage = 9*5,
minimum_health = 0, -- 4*5
damage_balance = 1.4,
target_range = 10,
target_mode = 'damage', -- damage
fast_place = true, -- uses cached placements
smart_target = true, -- doesn't reset cache if player is the same
cache_limit = 20,
post_death_cache_limit = 20, -- attacks after death (better with smart target)
fast_calc = false, -- can miss better places
fast_calc_limit = 3,
auto_crystal = false,
check_immunity = false, -- player is immune for 0.5 seconds when getting hurt
check_immunity_self_damage = true,
--cev = false, -- place obsidian on head, place crystal, destroy obsidian, destroy crystal
attack_self = false,
no_particles = true,
instant_crystal_render = true, -- shows crystal when instant auto crystal
lfx = false,
debug = false,
classic_explosion = true,
}
local local_entities = {}
local core = {}
core.util = {}
core.blockutil = {}
core.crystalutil = {}
core.entityutil = {}
core.storageutil = {}
core.plr = owner
core.storageutil.get = function(name,no_set)
if not _G['cpvp server'] then
_G['cpvp server'] = {}
end
if not _G['cpvp server'][name] and not no_set then
_G['cpvp server'][name] = {}
end
return _G['cpvp server'][name]
end
core.storageutil.set = function(i,v)
if not _G['cpvp server'] then
_G['cpvp server'] = {}
end
_G['cpvp server'][i] = v
return _G['cpvp server'][i]
end
core.util.clean_up = function()
coroutine.wrap(function()
for pos,block in pairs(core.storageutil.get('block_reference')) do
if not block then
core.storageutil.get('block_reference')[pos] = nil
end
end
for model,box in pairs(core.storageutil.get('hitboxes')) do
if model and not box then
core.storageutil.get('hitboxes')[model] = nil
if model then
model:Destroy()
end
end
end
for entity,_type in pairs(core.storageutil.get('entities')) do
if entity and not core.entityutil.in_world(entity) then
core.entityutil.remove_entity(entity)
end
end
for main,data in pairs(core.storageutil.get('anims')) do
if main and not core.entityutil.in_world(main) then
core.storageutil.get('anims')[main] = nil
core.util.destroy(main)
end
end
end)()
end
local ls_anim = os.clock()
local function get_char()
local char = {}
if game:GetService("RunService"):IsStudio() then
char.model = workspace.TemplateR6
else
char.model = core.plr.Character
end
if char.model then
char.head = char.model:FindFirstChild("Head")
char.root = char.model:FindFirstChild("HumanoidRootPart") or char.model:FindFirstChild("Torso")
char.hum = char.model:FindFirstChildOfClass("Humanoid")
end
return char
end
assert(get_char().hum.RigType == Enum.HumanoidRigType.R6,'Character is not R6.')
core.fx = Instance.new("Folder")
core.fx.Parent = script
script.ChildRemoved:Connect(function(obj)
if obj == core.fx then
core.fx = Instance.new("Folder")
core.fx.Parent = script
end
end)
core.junk = Instance.new("Folder")
core.junk.Parent = script
script.ChildRemoved:Connect(function(obj)
if obj == core.junk then
core.junk = Instance.new("Folder")
core.junk.Parent = script
end
end)
core.entityutil.in_world = function(obj)
if obj and obj:IsDescendantOf(workspace) then
return true
end
end
core.entityutil.is_alive = function(model)
if model and model:IsA("Model") then else return end
local thum = model:FindFirstChildOfClass("Humanoid")
local troot = model:FindFirstChild("HumanoidRootPart") or model:FindFirstChild("Torso") or model.PrimaryPart
if thum and troot and thum.Health > 0 then
return true
end
end
core.util.destroy = function(obj)
pcall(function()
obj:Destroy()
end)
end
core.blockutil.create_selection = function(part)
local selection = Instance.new('SelectionBox')
selection.Color3 = Color3.new()
selection.Transparency = 0
selection.SurfaceColor3 = Color3.new(1,0,0)
selection.SurfaceTransparency = 0.5
selection.LineThickness = 0.05
selection.Adornee = part
selection.Parent = part
return selection
end
core.entityutil.get_hitbox = function(model,fake,size,offset,position,perm,parent,visible)
local troot = model:FindFirstChild("HumanoidRootPart") or model:FindFirstChild("Torso") or model.PrimaryPart
if troot then else return end
if fake then
local hb = core.storageutil.get('hitboxes')[model]
if hb then
size = hb.Size
position = hb.Position
offset = Vector3.new()
end
return {
box = {
Size = size or Vector3.new(1,4.5-block_size/2,1)-hitbox_allowance*1.5,
Position = (position or troot.Position) + (offset or Vector3.new(0,-0.75-block_size/4,0))
},
}
end
if core.storageutil.get('hitboxes')[model] then
return {
box = core.storageutil.get('hitboxes')[model],
destroy = function()
core.util.destroy(core.storageutil.get('hitboxes')[model])
core.storageutil.get('hitboxes')[model] = nil
end,
}
end
local box = Instance.new("Part")
box.CanCollide = false
box.Anchored = true
box.CanTouch = false
box.CanQuery = true
box.Massless = true
box.Color = Color3.new(1,0,0)
box.Transparency = 1
box.Size = size or Vector3.new(1,4.5-block_size/2,1)-hitbox_allowance*1.5
if perm then
core.storageutil.get('hitboxes')[model] = box
end
box.Position = (position or troot.Position) + (offset or Vector3.new(0,-0.75-block_size/4,0))
if parent then
box.Parent = parent
else
box.Parent = core.junk
end
if visible or config.debug then
local c = box:Clone()
core.blockutil.create_selection(c)
c.Parent = workspace
game:GetService("Debris"):AddItem(c,3)
end
return {
box = box,
destroy = function()
if not perm then
core.util.destroy(box)
end
end,
}
end
core.entityutil.create_points = function(hb)
local hb_pos = hb.Position
local size = hb.Size
local x,y,z = size.X,size.Y,size.z
x = 0
y = 2
z = 0
local points = {}
for _x = 0,x do
for _y = 0,y do
for _z = 0,z do
--local pos = hb.Position+Vector3.new(-size.X/2+_x*size.X/x,-size.Y/2+_y*size.Y/y,-size.Z/2+_z*size.Z/z)
local pos = hb.Position+Vector3.new(0,-size.Y/2.9+_y*size.Y/y,0)
--if config.debug then
-- local p = Instance.new("Part")
-- p.CanCollide = false
-- p.Anchored = true
-- p.CanTouch = false
-- p.CanQuery = true
-- p.Transparency = 0
-- p.Position = pos
-- p.Size = Vector3.new(0.1,0.1,0.1)
-- p.Parent = core.junk
-- game:GetService("Debris"):AddItem(p,30)
--end
table.insert(points,pos)
end
end
end
return points
end
core.util.raycast = function(origin,dir,cancollide,mode,ignore)
local param = RaycastParams.new()
param.FilterType = mode or Enum.RaycastFilterType.Exclude
param.FilterDescendantsInstances = ignore
param.RespectCanCollide = cancollide or false
param.IgnoreWater = true
local ray = workspace:Raycast(origin,dir,param)
return ray
end
core.entityutil.ray_entity = function(origin,model,ignore,is_test)
if origin and model then else return end
is_test = not is_test
local hb = core.entityutil.get_hitbox(model,true)
local points = core.entityutil.create_points(hb.box)
local param = RaycastParams.new()
--ray_param.RespectCanCollide = false -- default to false
param.IgnoreWater = true
param.FilterType = Enum.RaycastFilterType.Include
param.FilterDescendantsInstances = {
core.blockutil.get_blocks(),
core.temp_block
}
--[[
param.FilterDescendantsInstances = {
model,
core.storageutil.get('hitboxes'),
core.entityutil.get_entities(),
core.fx,
core.junk,
ignore
}
]]
local exposure = 0
for _,pos2 in points do
local dir = (pos2-origin)
local dist = dir.Magnitude
local ray = workspace:Raycast(origin,dir,param)
if not is_test and config.debug then
local p = Instance.new("Part")
p.CanCollide = false
p.Anchored = true
p.CanTouch = false
p.CanQuery = true
p.Color = Color3.new(1,0,0)
p.Transparency = 0.5
p.CFrame = CFrame.new(origin+dir/2,pos2)--*CFrame.fromEulerAnglesXYZ(0,90,0)
p.Size = Vector3.new(0.1,0.1,dist)
p.Parent = core.junk
game:GetService("Debris"):AddItem(p,3)
end
if not ray then
exposure += 1
end
end
exposure = exposure/#points
return exposure
end
core.entityutil.add_entity = function(model,_type,global)
core.storageutil.get('entities')[model] = _type
if not global then
local_entities[model] = true
end
end
core.entityutil.remove_entity = function(model)
core.storageutil.get('anims')[model] = nil
core.storageutil.get('entities')[model] = nil
local_entities[model] = nil
if core.storageutil.get('hitboxes')[model] then
core.storageutil.get('hitboxes')[model]:Destroy()
core.storageutil.get('hitboxes')[model] = nil
end
end
core.entityutil.get_entities = function()
local t = {}
for entity,_type in pairs(core.storageutil.get('entities')) do
table.insert(t,entity)
end
return t
end
core.util.scan = function(v)
if v.Name == 'end crystal' then
core.entityutil.add_entity(v,'end crystal',true)
return
end
if core.entityutil.is_alive(v) then
--[[
local thum = v:FindFirstChildOfClass("Humanoid")
thum.HealthChanged:Connect(function(new_health)
if 0 >= new_health then
core.entityutil.remove_entity(v)
end
end)
]]
core.entityutil.add_entity(v,'player',true)
end
end
for i,v in ipairs(workspace:GetDescendants()) do
core.util.scan(v)
end
workspace.DescendantAdded:Connect(function(v)
task.wait(0.2)
core.util.scan(v)
end)
workspace.DescendantRemoving:Connect(function(v)
if core.storageutil.get('entities')[v] then
core.entityutil.remove_entity(v)
end
end)
core.util.in_range = function(block_pos)
local root_pos = core.blockutil.to_grid(get_char().root.Position)
local dist = (root_pos-block_pos).Magnitude
if config.range >= dist then
return 1
end
end
core.blockutil.get_sphere = function(pos,range)
local t = {}
range = math.floor(range)
local y_range = 0
for i = 1,range do
local ray = core.util.raycast(core.blockutil.from_grid(pos),Vector3.new(0,-block_size*i,0),true,Enum.RaycastFilterType.Include,{
workspace:FindFirstChild('Base'),
workspace:FindFirstChild('Baseplate'),
workspace:FindFirstChild('SpawnLocation')
})
if ray then
break
end
y_range -= 1
end
for x = -range,range do
for y = y_range,range-1 do
if math.sqrt(x^2+y^2) > range then
continue
end
for z = -range,range do
if range >= (pos-pos+Vector3.new(x,y,z)).Magnitude then
table.insert(t,pos+Vector3.new(x,y,z))
end
end
end
end
return t
end
local normal_ids = {
[0] = Vector3.new(1,0,0), -- right
[1] = Vector3.new(0,1,0), -- top
[2] = Vector3.new(0,0,1), -- back
[3] = Vector3.new(-1,0,0), -- left
[4] = Vector3.new(0,-1,0), -- bottom
[5] = Vector3.new(0,0,-1), -- front
}
core.blockutil.to_normal = function(surface)
return normal_ids[surface]
end
core.blockutil.process_block = function(pos,mode)
if mode then
core.storageutil.get('place_process')[pos] = 1
else
core.storageutil.get('place_process')[pos] = nil
end
end
core.blockutil.get_block = function(pos)
if core.entityutil.in_world(core.storageutil.get('block_reference')[pos]) then
return core.storageutil.get('block_reference')[pos]
else
core.storageutil.get('block_reference')[pos] = nil
end
end
core.blockutil.get_blocks = function(pos)
local t = {}
for i,v in pairs(core.storageutil.get('block_reference')) do
table.insert(t,v)
end
return t
end
core.blockutil.is_block = function(target)
local pos = core.blockutil.to_grid(target.Position)
return core.blockutil.get_block(pos) == target
end
core.blockutil.set_block = function(pos,block)
core.storageutil.get('block_reference')[pos] = block
end
core.entityutil.get_type = function(model)
if model then else return end
return core.storageutil.get('entities')[model]
end
core.blockutil.destroy_block = function(block)
if core.blockutil.is_block(block) then
core.storageutil.get('block_reference')[core.blockutil.to_grid(block.Position)] = nil
core.util.destroy(block)
elseif core.entityutil.get_type(block.Parent) == 'end crystal' then
core.crystalutil.explode(block.Parent)
end
end
core.blockutil.mine_block = function(block)
if block then else return end
core.blockutil.destroy_block(block)
end
core.blockutil.reset_air = function(pos,temp)
core.storageutil.get('in_air_cache')[pos] = nil
if temp then
return
end
for _,surface in pairs(normal_ids) do
if core.blockutil.get_block(pos+surface) then
return
end
core.storageutil.get('in_air_cache')[pos+surface] = nil
end
end
core.blockutil.in_air = function(pos)
if core.storageutil.get('in_air_cache')[pos] then
return true
end
for _,surface in pairs(normal_ids) do
if core.blockutil.get_block(pos+surface) then
return
end
end
local ray = core.util.raycast(core.blockutil.from_grid(pos),Vector3.new(0,-block_size,0),true,Enum.RaycastFilterType.Exclude,{
core.entityutil.get_entities(),
core.storageutil.get('hitboxes'),
core.fx,
core.junk,
script
})
if ray then
return
end
--if config.debug then
-- --print('in air')
--end
core.storageutil.get('in_air_cache')[pos] = 1
return true
end
core.blockutil.entity_block_conflict = function(model,pos)
if core.entityutil.is_alive(model) then
local hb = core.entityutil.get_hitbox(model)
pos = core.blockutil.from_grid(pos)
local param = OverlapParams.new()
param.FilterType = Enum.RaycastFilterType.Include
param.FilterDescendantsInstances = {hb.box,core.storageutil.get('hitboxes')}
local parts = workspace:GetPartBoundsInBox(CFrame.new(pos),BlockVector3-hitbox_allowance,param)
local t = #parts
hb.destroy()
return t > 0
end
end
core.util.round = function(n)
if typeof(n) == 'Vector3' then
local function f(n)
return math.floor(n+0.5)
end
return Vector3.new(f(n.X),f(n.Y),f(n.Z))
end
return math.floor(n+0.5)
end
core.blockutil.to_grid = function(pos)
local newpos = core.util.round(Vector3.new(pos.X/block_size,pos.Y/block_size,pos.Z/block_size))
return newpos
end
core.blockutil.from_grid = function(pos)
local newpos = Vector3.new(pos.X*block_size,pos.Y*block_size,pos.Z*block_size) + y_offset
return newpos
end
core.blockutil.can_place = function(pos,no_walls,full_check)
if core.storageutil.get('place_process')[pos] then return end
if core.blockutil.get_block(pos) then return end
local param = OverlapParams.new()
param.FilterDescendantsInstances = {
--core.blockutil.get_blocks(),
core.junk
}
local parts = workspace:GetPartBoundsInBox(CFrame.new(core.blockutil.from_grid(pos)),BlockVector3-hitbox_allowance,param)
local list = {}
for i,v in ipairs(parts) do
local model = v.Parent
local thum = model:FindFirstChildOfClass("Humanoid")
if core.storageutil.get('hitboxes')[model] and v == core.storageutil.get('hitboxes')[model] then
return nil,model
end
if no_walls then
return
end
if (v.CanCollide or v.Name == 'HumanoidRootPart') and full_check then
return
end
if thum and not table.find(list,model) then
table.insert(list,model)
end
end
for i,v in ipairs(list) do
if core.blockutil.entity_block_conflict(v,pos) then
return
end
end
return true
end
core.crystalutil.can_place = function(pos)
if core.blockutil.can_place(pos) and core.blockutil.get_block(pos+Vector3.new(0,-1,0)) then
return true
end
end
core.util.create_texture = function(part,normal,id,zindex,brightness)
local sg = part:FindFirstChild('block_texture_' .. normal.Name)
local image = nil
if not sg then
sg = Instance.new("SurfaceGui")
sg.Name = 'block_texture_' .. normal.Name
sg.ResetOnSpawn = true
sg.Face = normal
sg.Parent = part
sg.ZIndexBehavior = Enum.ZIndexBehavior.Global
end
if brightness then
sg.Brightness = brightness
sg.LightInfluence = 0
else
sg.LightInfluence = 1
end
sg.ZOffset = zindex or 0
image = sg:FindFirstChildOfClass('ImageLabel')
if not image then
image = Instance.new("ImageLabel")
image.Size = UDim2.new(1,0,1,0)
image.BackgroundTransparency = 1
image.ResampleMode = Enum.ResamplerMode.Pixelated
end
image.ZIndex = zindex or 1
image.Parent = nil
image.Image = 'rbxassetid://' .. id
game:GetService("ContentProvider"):PreloadAsync({image})
image.Parent = sg
end
local wool = "rbxassetid://3843797566"
local metal = "rbxassetid://935281533"
local sand = "rbxassetid://3843792584"
local gravel = "rbxassetid://3843794655"
local wood1 = "rbxassetid://3843789432"
local wood2 = "rbxassetid://3843786781"
local grass = "rbxassetid://3843796214"
local snow = "rbxassetid://3843791122"
local obsidian_template = nil
do
local Part1 = Instance.new("Part")
Part1.Name = "Obsidian"
Part1.Transparency = 0
Part1.Size = BlockVector3
Part1.BottomSurface = Enum.SurfaceType.Smooth
Part1.CanCollide = true
Part1.Anchored = true
Part1.Massless = true
Part1.CastShadow = false
Part1.Material = Enum.Material.Fabric
Part1.TopSurface = Enum.SurfaceType.Smooth
for _,normal in pairs(Enum.NormalId:GetEnumItems()) do
core.util.create_texture(Part1,normal,286047170)
end
obsidian_template = Part1
end
core.util.play = function(s)
coroutine.wrap(function()
game:GetService("ContentProvider"):PreloadAsync({s})
if not s.Loaded then
repeat task.wait() until s.Loaded
end
s:Play()
end)()
end
core.blockutil.place = function(pos)
if core.entityutil.is_alive(get_char().model) then else return end
core.blockutil.reset_air(pos,true)
if core.blockutil.can_place(pos) and not core.blockutil.in_air(pos) then
core.blockutil.reset_air(pos)
core.blockutil.process_block(pos,true)
local obby = obsidian_template:Clone()
obby.Position = core.blockutil.from_grid(pos)
obby.Parent = script
local placesound = Instance.new("Sound")
placesound.SoundId = metal
placesound.Volume = 1.5
placesound.Parent = obby
core.util.play(placesound)
game:GetService("Debris"):AddItem(placesound,2)
core.blockutil.set_block(pos,obby)
core.blockutil.process_block(pos,false)
return true
end
end
core.crystalutil.update_entities = function()
local ds = os.clock()-ls_anim
for entity,_type in pairs(core.storageutil.get('entities')) do
if core.entityutil.in_world(entity) then else
core.entityutil.remove_entity(entity)
continue
end
if _type == 'end crystal' and local_entities[entity] then
local p1,p2,p3,main = entity.p1,entity.p2,entity.p3,entity.main
if core.storageutil.get('anims')[entity] then else continue end
local f = core.storageutil.get('anims')[entity].innerRotation
local f1 = math.sin(f * 0.2)/2+0.5
f1 = f1^2+f1
local _p3 = f*3/60
local _p4 = f1*0.4*block_size
-- major replication lag, move this to client later
main.CFrame = core.storageutil.get('anims')[entity].origin*CFrame.new(0,_p4,0)
local rot = CFrame.Angles(0.7071,0,0.7071)*CFrame.Angles(0,1*_p3,0)
p1.Weld.C1 = rot
rot = rot*CFrame.Angles(0,1*_p3,0)*CFrame.Angles(0.7071*60,0,0.7071*60)
p2.Weld.C1 = rot
rot = rot*CFrame.Angles(0,1*_p3,0)*CFrame.Angles(0.7071*60,0,0.7071*60)
p3.Weld.C1 = rot
core.storageutil.get('anims')[entity].innerRotation += ds/(1/20)
--[[
main.CFrame = core.storageutil.get('anims')[entity].origin*CFrame.new(0,block_size/2*math.cos(core.storageutil.get('anims')[entity].time*5),0)
core.storageutil.get('anims')[entity].time += ds
p1.Weld.C1 = p1.Weld.C1*CFrame.Angles(0,math.rad(60*ds),0)
p2.Weld.C1 = p2.Weld.C1*CFrame.Angles(math.rad(0*ds),0,math.rad(80*ds))
p3.Weld.C1 = p3.Weld.C1*CFrame.Angles(math.rad(100*ds),0,math.rad(0*ds))
]]
end
end
end
local crystal_template = nil
do
local Model0 = Instance.new("Model")
local Part1 = Instance.new("Part")
local Part4 = Instance.new("Part")
local Part6 = Instance.new("Part")
local Part69 = Instance.new("Part")
Model0.Name = "End Crystal"
Part1.Name = "p1"
Part1.Parent = Model0
Part1.Orientation = Vector3.new(0, 45, 0)
Part1.Rotation = Vector3.new(0, 45, 0)
Part1.Color = Color3.new(0.666667, 0, 0.666667)
Part1.Material = Enum.Material.Fabric
Part1.Transparency = 1
Part1.Size = BlockVector3*1
Part1.Anchored = true
Part1.BottomSurface = Enum.SurfaceType.Smooth
Part1.BrickColor = BrickColor.new("Magenta")
Part1.CanCollide = false
Part1.TopSurface = Enum.SurfaceType.Smooth
Part1.brickColor = BrickColor.new("Magenta")
Part69.Name = "main"
Part69.Parent = Model0
Part69.Orientation = Vector3.new(0, 45, 0)
Part69.Rotation = Vector3.new(0, 45, 0)
Part69.Material = Enum.Material.SmoothPlastic
Part69.Color = Color3.new(0, 0, 0)
Part69.Transparency = 1
Part69.Size = Vector3.new(0.05, 0.5, 0.05)
Part69.Anchored = true
Part69.CanCollide = false
Part4.Name = "p2"
Part4.Parent = Model0
Part4.Orientation = Vector3.new(45, 0, 0)
Part4.Rotation = Vector3.new(45, 0, 0)
Part4.Color = Color3.new(0.666667, 0, 0.666667)
Part4.Material = Enum.Material.Fabric
Part4.Transparency = 1
Part4.Size = BlockVector3*0.75
Part4.Anchored = true
Part4.BottomSurface = Enum.SurfaceType.Smooth
Part4.BrickColor = BrickColor.new("Magenta")
Part4.CanCollide = false
Part4.TopSurface = Enum.SurfaceType.Smooth
Part4.brickColor = BrickColor.new("Magenta")
Part6.Name = "p3"
Part6.Parent = Model0
Part6.Orientation = Vector3.new(45, 0, 0)
Part6.Rotation = Vector3.new(45, 0, 0)
Part6.Color = Color3.new(0.666667, 0, 0.666667)
Part6.Size = BlockVector3*0.75
Part6.Transparency = 1
Part6.Anchored = true
Part6.BottomSurface = Enum.SurfaceType.Smooth
Part6.BrickColor = BrickColor.new("Magenta")
Part6.CanCollide = false
Part6.Material = Enum.Material.Fabric
Part6.TopSurface = Enum.SurfaceType.Smooth
Part6.brickColor = BrickColor.new("Magenta")
if not config.lfx then
for _,normal in pairs(Enum.NormalId:GetEnumItems()) do
core.util.create_texture(Part6,normal,4671609130,1)
end
for _,normal in pairs(Enum.NormalId:GetEnumItems()) do
core.util.create_texture(Part4,normal,4671588152,2)
end
for _,normal in pairs(Enum.NormalId:GetEnumItems()) do
core.util.create_texture(Part1,normal,4671588152,3)
end
else
Part1.Transparency = 0.7
Part6.Transparency = 0
Part4.Transparency = 0.7
end
crystal_template = Model0
end
local last_crystal_instant = nil
core.crystalutil.place = function(pos)
if core.entityutil.is_alive(get_char().model) then else return end
core.blockutil.reset_air(pos,true)
if core.crystalutil.can_place(pos) then -- 1.13+ placement
if last_crystal_instant then
core.crystalutil.explode(last_crystal_instant)
end
core.blockutil.reset_air(pos)
core.blockutil.process_block(pos,true)
local model = crystal_template:Clone()
model.Name = 'end crystal'
local p1 = model.p1
local p2 = model.p2
local p3 = model.p3
local main = model.main
local chum = Instance.new("Humanoid")
chum.MaxHealth = 1 -- hard life..
chum.Health = 1
chum.HealthDisplayType = Enum.HumanoidHealthDisplayType.AlwaysOff
chum.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
chum.Parent = model
chum.HealthChanged:Connect(function()
if core.storageutil.get('entities')[model] then else return end
core.crystalutil.explode(model)
end)
do
for i,v in ipairs(model:GetChildren()) do
if v.Name ~= 'main' and v:IsA("BasePart") then
local w = Instance.new("Weld")
w.Part0 = main
w.Part1 = v
w.Parent = v
v.Anchored = false
v.Massless = true
v.CastShadow = false
end
end
main.Position = core.blockutil.from_grid(pos)+Vector3.new(0,block_size*0.1,0)
main.Anchored = true
core.storageutil.get('anims')[model] = {
origin = main.CFrame,
--time = os.clock(),
innerRotation = math.random(10000),
}
--[[
p1.Weld.C1 = CFrame.Angles(math.rad(45),0,math.rad(45))
p2.Weld.C1 = CFrame.Angles(math.rad(45),math.rad(45),math.rad(45))
p3.Weld.C1 = CFrame.Angles(0,math.rad(45),math.rad(45))
]]
end
model.PrimaryPart = main
main.Position = core.blockutil.from_grid(pos)
local hb = core.entityutil.get_hitbox(model,false,BlockVector3*2-hitbox_allowance,Vector3.new(0,block_size/2,0),main.Position,true,model) -- *1.95 for block conflict
local click = Instance.new("ClickDetector")
click.MaxActivationDistance = 6*block_size
click.Parent = hb.box
click.MouseClick:Connect(function()
if core.storageutil.get('entities')[model] then else return end
click:Destroy()
core.crystalutil.explode(model)
end)
core.entityutil.add_entity(model,'end crystal')
model.Parent = core.fx
core.crystalutil.update_entities()
core.blockutil.process_block(pos,false)
return model
end
end
core.entityutil.set_hurt_sound = function(model)
local root = model:FindFirstChild("HumanoidRootPart") or model:FindFirstChild("Torso") or model.PrimaryPart
if root then
if core.util.can_sound('hurt') then
core.util.sound_debounce('hurt',1/10)
local hs = Instance.new("Sound")
hs.SoundId = 'rbxassetid://14424561569'
hs.Volume = 0.5
--hs.PlaybackSpeed = math.random(95,105)/100
hs.Parent = root
core.util.play(hs)
end
end
end
core.entityutil.set_hurt_ind = function(model)
if model then else return end
model:SetAttribute('hurt_st',os.clock())
local hc = model:GetAttribute('hurt_st')
for i,v in ipairs(model:GetChildren()) do
if v:IsA("BasePart") and v.Name ~= 'HumanoidRootPart' then else
continue
end
local hurt = v:FindFirstChild('hurt_highlight')
if not hurt then
hurt = Instance.new('Highlight')
hurt.Name = 'hurt_highlight'
hurt.DepthMode = Enum.HighlightDepthMode.Occluded
hurt.FillTransparency = 0.5
hurt.FillColor = Color3.new(1,0,0)
hurt.OutlineTransparency = 1
hurt.Enabled = false
hurt.Adornee = v
hurt.Parent = v
end
hurt.Enabled = true
task.delay(0.5,function()
if hc == model:GetAttribute('hurt_st') then else
return
end
hurt.Enabled = false
end)
end
end
core.entityutil.set_immunity = function(thum,damage)
core.storageutil.get('immunities')[thum] = {
time = os.clock(),
damage = damage
}
end
core.entityutil.is_immune = function(thum)
local immunity = core.storageutil.get('immunities')[thum]
if immunity and 0.5 >= os.clock()-immunity.time then
return true
end
end
core.entityutil.immune_diff = function(thum,damage)
local immunity = core.storageutil.get('immunities')[thum]
if immunity then
--if damage >= thum.Health then
-- return damage
--end
local diff = damage-immunity.damage
if diff > 0 then
return diff
end
end
end
core.entityutil.take_damage = function(thum,damage)
if core.entityutil.is_immune(thum) then
local diff = core.entityutil.immune_diff(thum,damage)
if diff then
if (thum.Health - diff) > 0 then
core.entityutil.set_hurt_sound(thum.Parent)
end
thum:TakeDamage(diff)
if thum.Health >= 100000 and thum.Parent and thum.Parent.Name ~= 'Dummy' then
thum.Health = 0
end
end
else
core.entityutil.set_hurt_sound(thum.Parent)
core.entityutil.set_hurt_ind(thum.Parent)
core.entityutil.set_immunity(thum,damage)
thum:TakeDamage(damage)
if thum.Health >= 100000 and thum.Parent and thum.Parent.Name ~= 'Dummy' then
thum.Health = 0
end
end
end
core.crystalutil.calc_damage = function(entity,pos,do_damage)
if entity then else return end
if not do_damage then
pos = pos+Vector3.new(0,block_size/2,0)+Vector3.new(0,-block_size+0.01,0)
--[[
if config.debug then
local exp_part = Instance.new("Part")
exp_part.Anchored = true
exp_part.CanCollide = false
exp_part.CanQuery = false
exp_part.Transparency = 0
exp_part.Size = Vector3.new(.5,.5,.5)
exp_part.Position = pos
exp_part.Parent = core.junk
game:GetService("Debris"):AddItem(exp_part,0.5)
end
]]
end
local power = 6
local radius = power*2
local troot = entity:FindFirstChild("HumanoidRootPart") or entity:FindFirstChild("Torso") or entity.PrimaryPart
if not troot then return end
local tpos = troot.Position
local feet_pos = tpos+Vector3.new(0,-3+0.01,0)
local dist = (pos-feet_pos).Magnitude/block_size
dist = core.util.round(dist)
if radius >= dist then
local exposure = core.entityutil.ray_entity(pos,entity,{},do_damage)
if exposure then else return end
local impact = (1-(dist/radius))*exposure
local damage = 10.5*(impact*impact+impact)*power+1 -- easy = 3.5, normal = 7, hard = 10.5
damage = damage*5 -- mc to roblox hp conversion
--damage = core.util.round(damage)
-- 125 damage against a block in mc (this does 127)
if do_damage then
--print(entity,math.floor(damage),exposure,dist)
local thum = entity:FindFirstChildOfClass("Humanoid")
if thum then
core.entityutil.take_damage(thum,damage)
end
else
return damage
end
end
end
core.util.sound_debounce = function(id,t,s)
core.storageutil.get('sound_debounces')[id] = {
st = os.clock(),
t = t,
sound = s,
}
end
core.util.can_sound = function(id)
if core.storageutil.get('sound_debounces')[id] then
if core.storageutil.get('sound_debounces')[id].t >= os.clock()-core.storageutil.get('sound_debounces')[id].st then
return
end
end
return true
end
local explosions = {}
do
local ids = {17495858639,17495859492,17495861983,17495862769}
for i,v in pairs(ids) do
local s = Instance.new("Sound")
s.SoundId = "rbxassetid://" .. v
s.Volume = 1
--s.RollOffMaxDistance = 16*block_size*2
game:GetService("ContentProvider"):PreloadAsync({s})
table.insert(explosions,s)
end
end
core.crystalutil.explode = function(model,chain,instant)
if model and core.entityutil.get_type(model) == 'end crystal' then else
return
end
local hb = core.entityutil.get_hitbox(model)
local center_pos = hb.box.Position
local pos = center_pos+Vector3.new(0,-block_size+0.01,0)
core.entityutil.remove_entity(model)
if last_crystal_instant then
last_crystal_instant.Parent = nil
last_crystal_instant:ClearAllChildren()
last_crystal_instant:Destroy()
last_crystal_instant = nil
end
if instant and config.instant_crystal_render then
model.Parent = core.junk
last_crystal_instant = model
task.delay(1/10,function()
if last_crystal_instant then else
return
end
model.Parent = nil
model:ClearAllChildren()
model:Destroy()
end)
else
model.Parent = nil
model:ClearAllChildren()
model:Destroy()
end
if chain then return end -- end crystals get destroyed in chains
local exp_part
if not chain then
exp_part = Instance.new("Part")
exp_part.Anchored = true
exp_part.CanCollide = false
exp_part.CanQuery = false
exp_part.Massless = true
exp_part.CastShadow = false
exp_part.Transparency = 1
exp_part.Size = Vector3.new(1,1,1)
exp_part.Position = pos
exp_part.Parent = core.junk
if config.debug then
exp_part.Transparency = 0
end
if not config.no_particles then
local ParticleEmitter1 = Instance.new("ParticleEmitter")
ParticleEmitter1.Parent = exp_part
ParticleEmitter1.Speed = NumberRange.new(25,25)
ParticleEmitter1.Color = ColorSequence.new(Color3.new(1,1,1),Color3.new(1,1,1))
ParticleEmitter1.Enabled = false
ParticleEmitter1.LightEmission = 0.80000001192093
ParticleEmitter1.Texture = "rbxassetid://3607612871"
ParticleEmitter1.Size = NumberSequence.new(0.5,1)
ParticleEmitter1.Lifetime = NumberRange.new(0.5)
ParticleEmitter1.LockedToPart = true
ParticleEmitter1.Rate = 10000
ParticleEmitter1.RotSpeed = NumberRange.new(270, 270)
ParticleEmitter1.SpreadAngle = Vector2.new(-90, -90)
ParticleEmitter1.VelocitySpread = -90
ParticleEmitter1.Shape = Enum.ParticleEmitterShape.Sphere
ParticleEmitter1:Emit(100)
end
if core.util.can_sound('explosion') then
core.util.sound_debounce('explosion',1/20)
local s = explosions[math.random(#explosions)]:Clone()
s.Parent = exp_part
core.util.play(s)
end
game:GetService("Debris"):AddItem(exp_part,3.9)
end
for entity,_type in pairs(core.storageutil.get('entities')) do
if core.entityutil.in_world(entity) then else
core.entityutil.remove_entity(entity)
continue
end
local power = 6
local radius = power*2
if _type == 'player' and core.entityutil.is_alive(entity) and (not entity:FindFirstChild("ForceField") or entity == get_char().model and config.attack_self) and not chain then
core.crystalutil.calc_damage(entity,pos,true)
elseif _type == 'end crystal' then
local hb = core.entityutil.get_hitbox(entity,true)
local dist = (center_pos-hb.box.Position).Magnitude/block_size
--dist = core.util.round(dist)
if radius >= dist then
core.crystalutil.explode(entity,true)
end
end
end
if not chain then
return true
end
end
pcall(function()
game:GetService("PhysicsService"):CreateCollisionGroup('ray_entity')
game:GetService("PhysicsService"):CreateCollisionGroup('ray_block')
game:GetService("PhysicsService"):CollisionGroupSetCollidable('ray_entity','ray_block',false)
end)
local asd = {}
local cached_placement
core.crystalutil.auto_place = function(data,instant)
local cpos = data.crystal_pos
local best_place
if not core.blockutil.get_block(cpos-Vector3.new(0,1,0)) then
best_place = cpos-Vector3.new(0,1,0)
end
if config.auto_crystal then else return end
if data.entity_collision then
core.crystalutil.explode(data.entity_collision)
return true
end
if best_place and config.place_support_block then
--print(best_self_damage,best_damage)
core.blockutil.place(best_place)
local ps = math.clamp(config.place_speed,0,10)
if config.place_speed > 0 then
task.wait(ps)
end
--local target_dmg = core.crystalutil.calc_damage(target,core.blockutil.from_grid(best_crystal))
--local self_dmg = core.crystalutil.calc_damage(get_char().model,core.blockutil.from_grid(best_crystal))
--warn(self_dmg,target_dmg)
end
if config.auto_crystal then else return end
local crystal
if config.place_crystal then
crystal = core.crystalutil.place(cpos)
end
if crystal then else
return
end
if config.crystal_speed > 0 and not instant then
if config.fast_place then
task.wait(1/20)
else
task.wait(config.crystal_speed)
end
else
instant = true
end
core.crystalutil.explode(crystal,nil,instant)
if crystal then
return true
end
end
local cache_timeout = 0
local post_death_cache_timeout = 0
core.crystalutil.auto_crystal = function() -- scans for placeable blocks and crystals
if core.entityutil.is_alive(get_char().model) and get_char().hum.Health >= config.minimum_health then else return end
local st = os.clock()
local closest_dist = 1/0
local best_damage = 0
local best_self_damage = 1/0
local target,target_root
if config.check_immunity_self_damage and get_char().model:FindFirstChildOfClass("ForceField") then
best_self_damage = 0
end
local best_crystals = {}
local bypass = false
for entity,_type in pairs(core.storageutil.get('entities')) do
if core.entityutil.in_world(entity) then else
core.entityutil.remove_entity(entity)
continue
end
if _type == 'player' and (entity ~= get_char().model or config.attack_self) then
if core.entityutil.is_alive(entity) then
elseif (config.smart_target and cached_placement and cached_placement.target == entity) then
bypass = true
else
continue
end
if not entity:FindFirstChildOfClass("ForceField") or (config.attack_self and entity == get_char().model) then else
continue
end
local troot = entity:FindFirstChild("HumanoidRootPart") or entity:FindFirstChild("Torso") or entity.PrimaryPart
local thum = entity:FindFirstChildOfClass("Humanoid")
if troot and thum then
local dist = (troot.Position-get_char().root.Position).Magnitude
if closest_dist > dist and config.target_range >= dist/block_size then
if config.check_immunity and core.entityutil.is_immune(thum) and not core.entityutil.immune_diff(thum,config.minimum_target_damage) then
continue
end
closest_dist = dist
target = entity
target_root = target:FindFirstChild("HumanoidRootPart") or target:FindFirstChild("Torso") or target.PrimaryPart
end
end
end
end
if target and target_root then else
if cached_placement then
if config.smart_target then
cache_timeout += 1
if cache_timeout > config.cache_limit then
cache_timeout = 0
cached_placement = nil
return
else
bypass = true
target = cached_placement.target
end
else
cached_placement = nil
return
end
else
return
end
end
local function fast_place()
local cpos = cached_placement.crystal_pos
local block_pos = cpos-Vector3.new(0,1,0)
if core.util.in_range(block_pos) then else
cached_placement = nil
return
end
if core.entityutil.is_alive(target) then else
if not config.smart_target or 0 > config.post_death_cache_limit then
cached_placement = nil
return
else
post_death_cache_timeout += 1
if post_death_cache_timeout > config.post_death_cache_limit then
post_death_cache_timeout = 0
cached_placement = nil
return nil,true
else
bypass = true
end
end
end
if cached_placement.target == target then
elseif config.smart_target and cached_placement.target.Name == target.Name then
elseif config.smart_target and cached_placement.player and game:GetService("Players"):GetPlayerFromCharacter(target) == cached_placement.player then
else
cached_placement = nil
return
end
local dist = (core.blockutil.to_grid(cached_placement.self_pos)-core.blockutil.to_grid(get_char().root.Position)).Magnitude
if 2 >= dist then else
cached_placement = nil
return
end
if target_root then
local dist = (core.blockutil.to_grid(cached_placement.target_pos)-core.blockutil.to_grid(target_root.Position)).Magnitude
if 2 >= dist then else
cached_placement = nil
return
end
elseif post_death_cache_timeout > 0 then
else
cached_placement = nil
return
end
if not core.blockutil.get_block(block_pos) and not core.blockutil.can_place(block_pos) then
cached_placement = nil
return
end
local crystal_can_place,entity_collision = core.blockutil.can_place(cpos)
if not crystal_can_place and core.entityutil.get_type(entity_collision) ~= 'end crystal' then
cached_placement = nil
return
end
local box
if not core.blockutil.get_block(block_pos) then
box = Instance.new("Part")
box.CanCollide = false
box.Anchored = true
box.CanTouch = false
box.CastShadow = false
box.CanQuery = true
box.Massless = true
box.Transparency = 0
box.Size = BlockVector3
box.Position = core.blockutil.from_grid(block_pos)
box.Parent = workspace
core.temp_block = box
end
local self_dmg = 0
if best_self_damage > 0 then
self_dmg = core.crystalutil.calc_damage(get_char().model,core.blockutil.from_grid(cpos))
if config.attack_self then
self_dmg = 0
end
if self_dmg and config.max_self_damage >= self_dmg then else
if box then
box:Destroy()
end
cached_placement = nil
return
end
end
local target_dmg = 0
if target_root then
target_dmg = core.crystalutil.calc_damage(target,core.blockutil.from_grid(cpos))
elseif post_death_cache_timeout > 0 then
target_dmg = 1/0
end
if target_dmg and target_dmg >= config.minimum_target_damage and target_dmg/self_dmg >= config.damage_balance then
if box then
box:Destroy()
end
local data = cached_placement
data.entity_collision = entity_collision
local placed = core.crystalutil.auto_place(cached_placement, post_death_cache_timeout > 0)
return placed, cache_timeout > 0
else
if box then
box:Destroy()
end
cached_placement = nil
end
end
if config.fast_place and cached_placement then
local placed,cancel = fast_place()
if placed then
if core.entityutil.is_alive(target) then
cache_timeout = 0
post_death_cache_timeout = 0
end
return
end
if bypass or cancel then
return
end
end
if config.debug then
if #asd > 0 then
for i,v in ipairs(asd) do
v:Destroy()
end
end
end
local numba = 0
local pos = core.blockutil.to_grid(get_char().root.Position)
local blocks = core.blockutil.get_sphere(pos,config.range)
for _,block_pos: Vector3 in ipairs(blocks) do
local cpos = block_pos+Vector3.new(0,1,0)
if core.blockutil.in_air(block_pos) then
continue
end
if not core.blockutil.get_block(block_pos) and not core.blockutil.can_place(block_pos) then -- cant place in places without obsidian
continue
end
if core.blockutil.get_block(cpos) then
continue
end
local crystal_can_place,entity_collision = core.blockutil.can_place(cpos)
if not crystal_can_place and core.entityutil.get_type(entity_collision) ~= 'end crystal' then -- 1.13+ check
continue
end
if config.target_mode == 'damage' then
local box = Instance.new("Part")
box.CanCollide = false
box.Anchored = true
box.CanTouch = false
box.CastShadow = false
box.CanQuery = true
box.Massless = true
box.Transparency = 1
box.Size = BlockVector3
box.Position = core.blockutil.from_grid(block_pos)
box.Parent = workspace
core.temp_block = box
--game:GetService("PhysicsService"):SetPartCollisionGroup(box,'ray_block')
--for i,v in ipairs(target:GetDescendants()) do
-- if v:IsA("BasePart") then
-- game:GetService("PhysicsService"):SetPartCollisionGroup(v,'ray_entity')
-- end
--end
local self_dmg = 0
if best_self_damage > 0 then
self_dmg = core.crystalutil.calc_damage(get_char().model,core.blockutil.from_grid(cpos))
if config.attack_self then
self_dmg = 0
end
if self_dmg and config.max_self_damage >= self_dmg and best_self_damage >= self_dmg then else
box:Destroy()
continue
end
end
local target_dmg = core.crystalutil.calc_damage(target,core.blockutil.from_grid(cpos))
numba += 1
if target_dmg and target_dmg >= best_damage and target_dmg >= config.minimum_target_damage and target_dmg/self_dmg >= config.damage_balance then
best_damage = target_dmg
best_self_damage = self_dmg
table.insert(best_crystals,1,{
crystal_pos = cpos,
entity_collision = entity_collision,
})
end
box:Destroy()
if config.fast_calc and #best_crystals >= config.fast_calc_limit then
break
end
end
--if config.debug then
-- local box = Instance.new("Part")
-- box.CanCollide = false
-- box.Anchored = true
-- box.CanTouch = false
-- box.CanQuery = true
-- box.Massless = true
-- box.Color = Color3.new(1,0,0)
-- box.Transparency = 0.5
-- box.Size = BlockVector3*1.1
-- box.Position = core.blockutil.from_grid(block_pos)
-- --core.blockutil.create_selection(box)
-- box.Parent = core.junk
-- game:GetService("Debris"):AddItem(box,2)
-- --table.insert(asd,box)
--end
end
for _,data in ipairs(best_crystals) do
local placed = core.crystalutil.auto_place(data)
if placed then
if config.fast_place and target_root then
cache_timeout = 0
post_death_cache_timeout = 0
cached_placement = data
cached_placement.target = target
cached_placement.player = game:GetService("Players"):GetPlayerFromCharacter(target)
cached_placement.target_pos = target_root.Position
cached_placement.self_pos = get_char().root.Position
end
blocks = nil
--warn(os.clock()-st,numba,numba*3)
break
end
end
blocks = nil
--warn(os.clock()-st,numba,numba*3)
end
core.entityutil.is_entity = function(target)
if not target then return end
if not target:IsA("Model") then
target = target:FindFirstAncestorOfClass("Model")
end
if target and (target:FindFirstChildOfClass("Humanoid") or core.storageutil.get('hitboxes')[target]) then
return true
end
end
core.util.mouse_place = function(mode,pos,target,surface)
if core.entityutil.is_alive(get_char().model) then else return end
if target and pos then else return end
if core.entityutil.is_entity(target) then return end
local normal = nil --core.blockutil.to_normal(surface)
if surface then
if typeof(surface) == 'Vector3' then else
return
end
for i,v in pairs(normal_ids) do
if surface == v then
normal = surface
break
end
end
if normal then else
return
end
end
pos = core.util.round(core.blockutil.to_grid(pos+y_offset)+normal/2+Vector3.new(0,1,0)/2) -- adjusted to surface pos
if target and core.blockutil.is_block(target) then
local tpos = core.blockutil.to_grid(target.Position)
local spos = tpos+normal -- might grid fail lol
local cpos = tpos+Vector3.new(0,1,0)
if mode == 'end crystal' then
local crystal = core.crystalutil.place(cpos)
if crystal and config.attack_placed_crystals then
core.crystalutil.explode(crystal,nil,true)
end
elseif mode == 'block' then
core.blockutil.place(spos)
end
elseif mode == 'block' then
core.blockutil.place(pos)
end
end
core.blockutil.auto_surround = function()
if core.entityutil.is_alive(get_char().model) then else return end
if config.auto_surround then else return end
local death_con,root_con
local function center_char()
local raw_root_pos = get_char().root.Position
local root_pos = core.blockutil.to_grid(get_char().root.Position)
local root_pos2 = core.blockutil.from_grid(root_pos)
get_char().root.Position = Vector3.new(root_pos2.X,raw_root_pos.Y,root_pos2.Z)
end
local function stop()
if config.auto_surround then else return end
config.auto_surround = false
get_char().root.Anchored = false
print('auto_surround: ' .. tostring(config.auto_surround))
death_con:Disconnect()
root_con:Disconnect()
end
death_con = get_char().hum.Died:Connect(function()
death_con:Disconnect()
root_con:Disconnect()
repeat
task.wait()
until get_char().hum.Health and get_char().hum.Health > 0
core.blockutil.auto_surround()
end)
local y_level = get_char().root.Position.Y
root_con = get_char().root.Changed:Connect(function()
if get_char().hum.Jump then
stop()
return
end
if math.abs(y_level-get_char().root.Position.Y)*block_size >= block_size*0.9 then
stop()
return
end
end)
if get_char().hum.Jump then
stop()
return
end
center_char()
while core.entityutil.is_alive(get_char().model) do
if config.auto_surround then else return end
local root_pos = core.blockutil.to_grid(get_char().root.Position)
local spos = {
Vector3.new(1,0,0),
Vector3.new(-1,0,0),
Vector3.new(0,0,1),
Vector3.new(0,0,-1),
}
for i = 1,#spos do
local spos = spos[i]
if not core.blockutil.get_block(root_pos+spos) then
get_char().root.Anchored = true
if not core.blockutil.can_place(root_pos+spos,false,true) then
center_char()
root_pos = core.blockutil.to_grid(get_char().root.Position)
end
if get_char().hum.Jump then
stop()
return
end
if math.abs(y_level-get_char().root.Position.Y) >= 0.1 then
stop()
return
end
if config.auto_surround then else
stop()
return
end
local placed = core.blockutil.place(root_pos+spos)
if not placed then
center_char()
root_pos = core.blockutil.to_grid(get_char().root.Position)
end
end
end
get_char().root.Anchored = false
task.wait(config.surround_speed+0.5)
end
end
local packets = {
['place'] = function(data)
core.util.mouse_place('block',data.pos,data.target,data.surface)
end,
['place_crystal'] = function(data)
core.util.mouse_place('end crystal',data.pos,data.target,data.surface)
end,
['mine'] = function(data)
core.blockutil.mine_block(data.target)
end,
['auto_crystal'] = function()
config.auto_crystal = not config.auto_crystal
print('auto_crystal: ' .. tostring(config.auto_crystal))
while config.auto_crystal do
core.crystalutil.auto_crystal()
if config.fast_place and cached_placement then
task.wait()
else
task.wait(config.check_speed)
end
end
end,
['auto_surround'] = function()
config.auto_surround = not config.auto_surround
print('auto_surround: ' .. tostring(config.auto_surround))
core.blockutil.auto_surround()
end,
['attack_placed_crystals'] = function()
config.attack_placed_crystals = not config.attack_placed_crystals
print('attack_placed_crystals: ' .. tostring(config.attack_placed_crystals))
end
}
local function run_client()
local remote = Instance.new("RemoteEvent")
remote.Parent = core.plr:FindFirstChildOfClass("PlayerGui")
remote.OnServerEvent:Connect(function(lplr,packet,...)
if lplr == core.plr then else return end
local func = packets[packet]
if func then
func(...)
end
end)
NLS([[
local remote = script.Parent
local uis = game:GetService("UserInputService")
local mouse = game:GetService("Players").LocalPlayer:GetMouse()
local lplr = game.Players.LocalPlayer
local char = lplr.Character
local head = char:WaitForChild("Head")
local place_hold = false
local mine_hold = false
local crystal_hold = false
local function is_fps()
return head.LocalTransparencyModifier == 1
end
local function raycast()
local param = RaycastParams.new()
param.FilterDescendantsInstances = {char}
param.IgnoreWater = true
local origin = workspace.CurrentCamera.CFrame.Position
local dir = (mouse.Hit.Position-origin).Unit*1000
local dist = dir.Magnitude
local ray = workspace:Raycast(origin,dir,param)
local t = {
pos = ray and ray.Position or mouse.Hit.Position,
target = ray and ray.Instance,
surface = ray and ray.Normal
}
return t
end
uis.InputBegan:Connect(function(input,press)
if press then return end
if input.UserInputType == Enum.UserInputType.Keyboard then
local key = input.KeyCode
if key == Enum.KeyCode.E then
--mine_hold = false
place_hold = false
crystal_hold = true
repeat
remote:FireServer('place_crystal',raycast())
task.wait(1/20)
until not crystal_hold
elseif key == Enum.KeyCode.F then
--crystal_hold = false
place_hold = false
mine_hold = true
repeat
remote:FireServer('mine',raycast())
task.wait(1/5)
until not mine_hold
elseif key == Enum.KeyCode.C then
remote:FireServer('auto_crystal')
elseif key == Enum.KeyCode.R then
remote:FireServer('auto_surround')
elseif key == Enum.KeyCode.T then
remote:FireServer('attack_placed_crystals')
end
elseif input.UserInputType == Enum.UserInputType.MouseButton2 and is_fps() then
mine_hold = false
crystal_hold = false
place_hold = true
repeat
remote:FireServer('place',raycast())
task.wait(1/10)
until not place_hold
end
end)
uis.InputEnded:Connect(function(input,press)
if input.UserInputType == Enum.UserInputType.Keyboard then
local key = input.KeyCode
if key == Enum.KeyCode.E then
crystal_hold = false
elseif key == Enum.KeyCode.F then
mine_hold = false
end
elseif input.UserInputType == Enum.UserInputType.MouseButton2 then
place_hold = false
end
end)
]],remote)
end
run_client()
core.plr.CharacterAdded:Connect(function()
task.wait(0.2)
run_client()
end)
local last_place = os.clock()
game:GetService("RunService").Stepped:Connect(function()
core.crystalutil.update_entities()
ls_anim = os.clock()
end)
local pings = {}
local ping = core.storageutil.get('ping',true)
if not ping and game:GetService("RunService"):IsServer() then
ping = core.storageutil.set('ping',Instance.new("BindableEvent"))
end
ping.Event:Connect(function(id)
if id ~= core.plr.UserId then
pings[id] = os.clock()
end
end)
coroutine.wrap(function()
while true do
ping:Fire(core.plr.UserId)
for id,st in pairs(pings) do
if os.clock()-st >= 3 then
pings[id] = nil
core.util.clean_up()
break
end
end
wait(0.5+math.random()*0.5)
end
end)()
coroutine.wrap(function()
while true do
core.util.clean_up()
wait(60)
end
end)()
warn([[
-- Made by LazaroValkyrie
-- Crystal PvP v1.3
Must be in First Person
(Auto Runs on spawn)
RMB - Place
E - Place Crystal
F - Mine Block/Crystal
C - Auto Crystal
R - Auto Surround
T - Attack Placed Crystal Setting
]])