Files
wnsrc/gamemodes/darkrp/plugins/waterloot/sv_plugin.lua
lifestorm df294d03aa Upload
2024-08-04 23:54:45 +03:00

439 lines
17 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLUGIN = PLUGIN
function PLUGIN:CanPlaceCookingPot(client)
if !client then return false end
if !client:Alive() then return false end
local targetEnt = client:GetEyeTraceNoCursor().Entity
for _, v in pairs(ents.FindInSphere(client:GetPos(), 50)) do
if v:GetClass() != "ix_campfire" then continue end
targetEnt = v
break
end
if !targetEnt then client:Notify("Pişirme kabının kamp ateşinde veya fırında olması gerekir!") return false end
if !IsValid(targetEnt) then client:Notify("Pişirme kabının kamp ateşinde veya fırında olması gerekir!") return false end
if targetEnt.HasPotPlaced then client:Notify("Bu kamp ateşinde veya fırında zaten bir tencere var!") return false end
local entClass = targetEnt:GetClass()
if entClass == "ix_campfire" then return targetEnt, "ix_campfire" end
if entClass != "ix_item" then client:Notify("Pişirme kabının kamp ateşinde veya fırında olması gerekir!") return false end
if entClass == "ix_item" and !targetEnt:GetItemTable() then client:Notify("Pişirme kabının kamp ateşinde veya fırında olması gerekir!") return false end
local itemTable = targetEnt:GetItemTable()
local allowedTools = {"tool_oven_rusty", "tool_oven"}
if entClass == "ix_item" and table.HasValue(allowedTools, itemTable.uniqueID) then return targetEnt, itemTable.uniqueID end
end
function PLUGIN:PlaceCookingPot(client, item)
local cookingSurfaceEnt, uniqueID = self:CanPlaceCookingPot(client)
if !cookingSurfaceEnt or (cookingSurfaceEnt and !IsValid(cookingSurfaceEnt)) then return false end
local bSuccess, error = item:Transfer(nil, nil, nil, item.player)
if (!bSuccess and isstring(error)) then
client:Notify("Could not drop the cooking pot and place it.")
return
end
local potEntity = bSuccess
local normPos = 45
local rustyPos = 25
local campPos = 32
local zPos = (uniqueID == "ix_campfire" and campPos or uniqueID =="tool_oven_rusty" and rustyPos or normPos)
potEntity:SetAngles(cookingSurfaceEnt:GetAngles())
potEntity:SetPos(cookingSurfaceEnt:GetPos() + cookingSurfaceEnt:GetUp() * zPos)
constraint.Weld( potEntity, cookingSurfaceEnt, 0, 0, 0, true, true )
local physObj = potEntity:GetPhysicsObject()
if !physObj then return end
physObj:EnableMotion(false)
cookingSurfaceEnt.HasPotPlaced = true
item.cookingPlatform = cookingSurfaceEnt
potEntity.isFiltrating = false
potEntity.cookingPlatform = cookingSurfaceEnt
client:EmitSound("physics/metal/metal_barrel_impact_soft1.wav")
end
function PLUGIN:TargetError(client, type)
client:Notify("You are not looking at a "..type.."!")
end
function PLUGIN:CanFiltrateWater(client, item)
if !client then return false end
if !client:Alive() then return false end
if item:GetData("filtrated", false) then client:Notify("Bu su zaten filtrelenmiş!") return false end
if !item:GetData("water") then client:Notify("Şişede su yok!") return false end
local currentWaterAmount = item:GetData("water", 0)
if currentWaterAmount <= 0 then client:Notify("Şişede filtrelenecek kadar su yok!") return false end
local targetEnt = client:GetEyeTraceNoCursor().Entity
if !targetEnt then self:TargetError(client, "cooking pot") return false end
if !IsValid(targetEnt) then self:TargetError(client, "cooking pot") return false end
local entClass = targetEnt:GetClass()
if entClass != "ix_item" then self:TargetError(client, "cooking pot") return false end
if entClass == "ix_item" and !targetEnt:GetItemTable() then self:TargetError(client, "cooking pot") return false end
local itemTable = targetEnt:GetItemTable()
if itemTable.uniqueID != "tool_cookingpot" then
client:Notify("Bu suyu süzmek için bir tencereye bakmanız gerekir.")
return false
end
local itemID = targetEnt.ixItemID
itemTable = ix.item.instances[itemID]
if targetEnt.isFiltrating then client:Notify("Bu pişirme kabı zaten su filtreliyor!") return false end
local parent = targetEnt.cookingPlatform
if !IsValid(parent) then client:Notify("Pişirme kabının kamp ateşinde veya fırında olması gerekir!") return false end
local parentClass = parent:GetClass()
if parentClass == "ix_campfire" then return targetEnt, currentWaterAmount, itemTable end
if parentClass == "ix_item" and !parent:GetItemTable() then client:Notify("Pişirme kabının kamp ateşinde veya fırında olması gerekir!") return false end
local allowedTools = {"tool_oven_rusty", "tool_oven"}
if table.HasValue(allowedTools, parent:GetItemTable().uniqueID) then return targetEnt, currentWaterAmount, itemTable end
client:Notify("Pişirme kabının kamp ateşinde veya fırında olması gerekir!")
return false
end
function PLUGIN:FiltrateWater(client, item)
local cookingPot, currentWaterAmount, potItem = self:CanFiltrateWater(client, item)
if !cookingPot or cookingPot and !IsValid(cookingPot) or !currentWaterAmount then return false end
potItem:SetData("durability", math.max(0, potItem:GetDurability() - 1))
if (potItem:GetDurability() == 0) then
if cookingPot.cookingPlatform then
cookingPot.cookingPlatform.HasPotPlaced = false
end
cookingPot:EmitSound("weapons/crowbar/crowbar_impact"..math.random(1, 2)..".wav", 65)
cookingPot:Remove()
return
end
cookingPot.currentWaterAmount = currentWaterAmount
item:SetData("water", 0)
local smoke = ents.Create( "env_smokestack" )
smoke:SetPos(cookingPot:GetPos())
smoke:SetAngles(cookingPot:GetAngles())
smoke:SetKeyValue("InitialState", "1")
smoke:SetKeyValue("WindAngle", "0 0 0")
smoke:SetKeyValue("WindSpeed", "0")
smoke:SetKeyValue("rendercolor", "255 255 255")
smoke:SetKeyValue("renderamt", "50") -- alpha
smoke:SetKeyValue("SmokeMaterial", "particle/smokesprites_0001.vmt")
smoke:SetKeyValue("BaseSpread", "1")
smoke:SetKeyValue("SpreadSpeed", "3")
smoke:SetKeyValue("Speed", "11")
smoke:SetKeyValue("StartSize", "8")
smoke:SetKeyValue("EndSize", "9")
smoke:SetKeyValue("roll", "8")
smoke:SetKeyValue("Rate", "24")
smoke:SetKeyValue("JetLength", "46")
smoke:SetKeyValue("twist", "6")
smoke:Spawn()
smoke:SetParent(cookingPot)
smoke:Activate()
if (!IsValid(cookingPot.spark)) then
cookingPot.spark = ents.Create("env_splash")
end
cookingPot.spark:SetPos(cookingPot:GetPos())
cookingPot.spark:SetKeyValue( "scale", 3 )
cookingPot.spark:Fire("Splash")
cookingPot:DeleteOnRemove(cookingPot.spark)
cookingPot.spark:SetParent(cookingPot)
if IsValid(cookingPot.cookingPlatform) then
cookingPot.cookingPlatform:EmitSound( "ambient/levels/canals/water_flow_loop1.wav", 75, 100, 1, CHAN_AUTO )
end
cookingPot:DeleteOnRemove(smoke)
cookingPot.finished = false
cookingPot.isFiltrating = true
netstream.Start(client, "ixWaterLootCreateProgressTextCookingPot", cookingPot:EntIndex())
local timerName = "ixWaterLootFiltrationTimer_"..cookingPot:EntIndex()
timer.Create(timerName, ix.config.Get("waterFiltrationTimeNeeded", 1) * 60, 1, function()
if !IsValid(cookingPot) then timer.Remove(timerName) return end
if !item or item and !item.GetID then return false end
if IsValid(cookingPot.cookingPlatform) then
cookingPot.cookingPlatform:StopSound( "ambient/levels/canals/water_flow_loop1.wav" )
end
netstream.Start(client, "ixWaterLootCreateProgressTextCookingPot", cookingPot:EntIndex(), true)
cookingPot.finished = true
cookingPot.isFiltrating = false
if !IsValid(smoke) then return end
smoke:Remove()
end)
end
function PLUGIN:IsWaterDeepEnough(client)
local pos = client:GetPos() + Vector(0, 0, 15)
local trace = {}
trace.start = pos
trace.endpos = pos + Vector(0, 0, 1)
trace.mask = bit.bor( MASK_WATER )
local tr = util.TraceLine(trace)
return tr.Hit
end
function PLUGIN:FillWaterError(client)
client:Notify("Bir su birikintisine ya da filtrelenmiş su içeren bir tencereye bakmıyorsunuz veya suda yeterince derin değilsiniz!")
end
function PLUGIN:CanFillWaterCannister(client)
if self:IsWaterDeepEnough(client) then return true end
local targetEnt = client:GetEyeTraceNoCursor().Entity
if !targetEnt then self:FillWaterError(client) return false end
if !IsValid(targetEnt) then self:FillWaterError(client) return false end
local entClass = targetEnt:GetClass()
if entClass == "ix_watercache" and !targetEnt.HasPotPlaced then client:Notify("Depoda su almaya yardımcı olacak bir vana yok!") return false end
if entClass == "ix_watercache" and targetEnt.HasPotPlaced then return targetEnt end
if entClass != "ix_item" then self:FillWaterError(client) return false end
if entClass == "ix_item" and !targetEnt:GetItemTable() then self:FillWaterError(client) return false end
local itemTable = targetEnt:GetItemTable()
if itemTable.uniqueID != "tool_cookingpot" then
self:FillWaterError(client)
return false
else
return targetEnt
end
end
function PLUGIN:FillEmptyWaterCannister(client, item)
if item:GetData("water", 0) >= 100 then client:Notify("Bu su şişesi zaten dolu.") return false end
local target = self:CanFillWaterCannister(client)
if !target then return false end
if isbool(target) or target:GetClass() == "ix_watercache" then
local newValue = math.Clamp(item:GetData("water", 0) + ix.config.Get("waterFillPerRefill", 100), 0, 100)
client:Notify("You've refilled the "..item:GetName().." to "..newValue.."%")
item:SetData("filtrated", false)
item:SetData("water", newValue)
client:EmitSound("ambient/water/water_spray1.wav")
local leechChance = ix.config.Get("chanceToGetLeech", 50)
if self:CalcLeechChance(leechChance) then
local itemTable = ix.item.list["ing_raw_leech"]
local character = client:GetCharacter()
local inventory = character:GetInventory()
if IsValid(client) and character and inventory then
if (!inventory:FindEmptySlot(itemTable.width, itemTable.height)) then
return false
end
inventory:Add("ing_raw_leech")
end
end
item:DamageDurability(1)
return
end
if IsEntity(target) then
if !target.currentWaterAmount then client:Notify("Bu tencerede su yok!") return false end
if !target.finished then client:Notify("Bu pişirme kabı henüz kaynamadı!") return false end
if item:GetData("water", 0) > 0 and !item:GetData("filtrated", false) then client:Notify("Bu şişede filtrelenmemiş su var!") return false end
item:SetData("water", target.currentWaterAmount)
item:SetData("filtrated", true)
netstream.Start(client, "ixWaterLootCreateProgressTextCookingPot", target:EntIndex(), false)
target.currentWaterAmount = nil
target.finished = false
client:EmitSound("ambient/water/water_spray1.wav")
if (!IsValid(target.spark)) then
target.spark = ents.Create("env_splash")
end
target.spark:SetPos(target:GetPos())
target.spark:SetKeyValue( "scale", 3 )
target.spark:Fire("Splash")
target:DeleteOnRemove(target.spark)
target.spark:SetParent(target)
end
end
function PLUGIN:CalcLeechChance(percentage)
return math.random() < percentage / 100
end
function PLUGIN:EmptyWaterCannister(client, item)
if !client then return false end
if !client:Alive() then return false end
if item:GetData("water", 0) > 0 then
item:SetData("water", 0)
client:EmitSound("ambient/water/water_spray1.wav")
else
client:Notify("Bu şişede boşaltacak su yok!")
end
end
function PLUGIN:CanDrinkWater(client, item)
if !client then return false end
if !client:Alive() then return false end
if !item:GetData("water") then client:Notify("Bu şişede su yok!") return false end
if item:GetData("water", 0) <= 0 then client:Notify("Bu şişede yeterli su yok!") return false end
if (ix.faction.Get(client:Team()).bDrinkUnfilteredWater) then return true end
if !item:GetData("filtrated", false) then client:Notify("Bu su filtrelenmemiş!") return false end
return item:GetData("filtrated", false)
end
function PLUGIN:DrinkWater(client, itemID, waterAmount)
if !ix.item.instances[itemID] then return false end
local item = ix.item.instances[itemID]
local character = client:GetCharacter()
if !character then return false end
local inventory = character:GetInventory()
if !inventory then return false end
if !inventory:GetItems()[itemID] then
local targetEnt = client:GetEyeTraceNoCursor().Entity
if !targetEnt then return false end
if !IsValid(targetEnt) then return false end
if targetEnt:GetClass() != "ix_item" then return false end
if targetEnt.ixItemID and targetEnt.ixItemID != itemID then return false end
end
if !self:CanDrinkWater(client, item) then return false end
if item:GetData("water", 0) < waterAmount then client:Notify("Şişede olduğundan daha fazla su içmeye çalışıyorsunuz!") return false end
item:SetData("water", item:GetData("water", 0) - waterAmount)
character:SetThirst(math.Clamp(character:GetThirst() - math.ceil(waterAmount), 0, 100))
client:EmitSound("npc/barnacle/barnacle_gulp2.wav")
end
function PLUGIN:RequestDrinkWater(client, item)
if !self:CanDrinkWater(client, item) then return false end
netstream.Start(client, "ixWaterLootDrinkWater", item:GetID(), item:GetData("water", 0))
end
function PLUGIN:CanPlaceValve(client, item)
if !client then return false end
if !client:Alive() then return false end
local targetEnt = client:GetEyeTraceNoCursor().Entity
if !targetEnt then client:Notify("Bir su deposuna bakmıyorsunuz!") return false end
if !IsValid(targetEnt) then client:Notify("Bir su deposuna bakmıyorsunuz!") return false end
local entClass = targetEnt:GetClass()
if entClass != "ix_watercache" then client:Notify("Bir su deposuna bakmıyorsunuz!") return false end
if targetEnt.HasPotPlaced then client:Notify("Bu su deposunda zaten bir vana var!") return false end
return targetEnt
end
function PLUGIN:PlaceValve(client, item)
local waterCacheEnt = self:CanPlaceValve(client, item)
if !waterCacheEnt or (waterCacheEnt and !IsValid(waterCacheEnt)) then return false end
local bSuccess, error = item:Transfer(nil, nil, nil, item.player)
if (!bSuccess and isstring(error)) then
client:Notify("Could not drop the water valve and place it.")
return
end
local waterValve = bSuccess
local rotation = Vector(90, 0, 0)
local angle = waterCacheEnt:GetAngles()
angle:RotateAroundAxis(angle:Up(), rotation.x)
waterValve:SetAngles(angle)
waterValve:SetPos(waterCacheEnt:GetPos() + waterCacheEnt:GetUp() * -12.5)
constraint.Weld( waterValve, waterCacheEnt, 0, 0, 0, true, true )
local physObj = waterValve:GetPhysicsObject()
if !physObj then return end
physObj:EnableMotion(false)
waterCacheEnt.HasPotPlaced = true
item.waterCache = waterCacheEnt
end
function PLUGIN:RegisterSaveEnts()
ix.saveEnts:RegisterEntity("ix_watercache", true, true, true, {
OnSave = function(entity, data) --OnSave
return {pos = data.pos, angles = data.angles + Angle(0, 180, 0), motion = false}
end,
})
end
function PLUGIN:LoadWaterCaches()
if (!ix.config.Get("SaveEntsOldLoadingEnabled")) then return end
local waterCaches = ix.data.Get("watercaches")
if waterCaches then
for _, v in pairs(waterCaches) do
local entity = ents.Create("ix_watercache")
entity:SetAngles(v.angles)
entity:SetPos(v.position)
entity:Spawn()
local physicsObject = entity:GetPhysicsObject()
if (IsValid(physicsObject)) then
physicsObject:EnableMotion(false)
end
end
MsgC(Color(0, 255, 0), "[WATER LOOT] Water Caches Loaded.\n")
else
MsgC(Color(0, 255, 0), "[WATER LOOT] No Water Caches Loaded.\n")
end
end
-- A function to save the static props.
function PLUGIN:SaveWaterCaches()
local waterCaches = {}
for _, v in pairs(ents.FindByClass("ix_watercache")) do
waterCaches[#waterCaches + 1] = {
angles = v:GetAngles(),
position = v:GetPos()
}
end
ix.data.Set("watercaches", waterCaches)
end
-- Called when Helix has loaded all of the entities.
function PLUGIN:InitPostEntity()
self:LoadWaterCaches()
end
-- Called just after data should be saved.
function PLUGIN:SaveData()
self:SaveWaterCaches()
end
netstream.Hook("ixWaterLootDrinkWater", function(client, itemID, waterAmount)
PLUGIN:DrinkWater(client, itemID, waterAmount)
end)