mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
Upload
This commit is contained in:
439
gamemodes/darkrp/plugins/waterloot/sv_plugin.lua
Normal file
439
gamemodes/darkrp/plugins/waterloot/sv_plugin.lua
Normal file
@@ -0,0 +1,439 @@
|
||||
--[[
|
||||
| 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("La marmite doit être sur un feu de camp ou un four !") return false end
|
||||
if !IsValid(targetEnt) then client:Notify("La marmite doit être sur un feu de camp ou un four !") return false end
|
||||
if targetEnt.HasPotPlaced then client:Notify("Il y a déjà une marmite sur ce feu de camp ou un four !") return false end
|
||||
local entClass = targetEnt:GetClass()
|
||||
|
||||
if entClass == "ix_campfire" then return targetEnt, "ix_campfire" end
|
||||
if entClass != "ix_item" then client:Notify("La marmite doit être sur un feu de camp ou un four !") return false end
|
||||
if entClass == "ix_item" and !targetEnt:GetItemTable() then client:Notify("La marmite doit être sur un feu de camp ou un four !") 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("Impossible de laisser tomber la marmite ou de placer.")
|
||||
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("Vous ne regardez pas un "..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("Cette eau est déjà filtrée !") return false end
|
||||
if !item:GetData("water") then client:Notify("Il n’y a pas d’eau dans la bouteille !") return false end
|
||||
local currentWaterAmount = item:GetData("water", 0)
|
||||
if currentWaterAmount <= 0 then client:Notify("Il n’y a pas assez d’eau pour filtrer dans la bouteille !") 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("Vous devez regarder un pot de cuisson pour filtrer cette eau.")
|
||||
return false
|
||||
end
|
||||
|
||||
local itemID = targetEnt.ixItemID
|
||||
itemTable = ix.item.instances[itemID]
|
||||
|
||||
if targetEnt.isFiltrating then client:Notify("Cette marmite filtre déjà l’eau !") return false end
|
||||
|
||||
local parent = targetEnt.cookingPlatform
|
||||
if !IsValid(parent) then client:Notify("La marmite doit être sur un feu de camp ou un four !") 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("La marmite doit être sur un feu de camp ou un four !") 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("La marmite doit être sur un feu de camp ou un four!")
|
||||
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("Vous ne regardez pas une valve d’eau, une marmite avec de l’eau filtrée ou vous n’êtes pas assez profond dans l’eau !")
|
||||
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("Il n'y a pas de valve sur le cache pour aider à prélever de l'eau !") 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("Cette bouteille d’eau est déjà pleine.") 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("Vous avez rempli "..item:GetName().." à "..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("Il n’y a pas d’eau dans cette marmite !") return false end
|
||||
if !target.finished then client:Notify("Cette marmite n’a pas encore bouillie!") return false end
|
||||
if item:GetData("water", 0) > 0 and !item:GetData("filtrated", false) then client:Notify("Cette bouteille contient de l'eau non filtrée !") 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("Il n’y a pas d’eau à vider dans cette bouteille !")
|
||||
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("Il n’y a pas d’eau dans cette bouteille !") return false end
|
||||
if item:GetData("water", 0) <= 0 then client:Notify("Il n’y a pas assez d’eau dans cette bouteille !") return false end
|
||||
|
||||
if (ix.faction.Get(client:Team()).bDrinkUnfilteredWater) then return true end
|
||||
|
||||
if !item:GetData("filtrated", false) then client:Notify("Cette eau n’est pas filtrée !") 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("Vous essayez de boire plus d’eau qu’il n’y en a dans la bouteille!") 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("Vous ne regardez pas une cache d’eau !") return false end
|
||||
if !IsValid(targetEnt) then client:Notify("Vous ne regardez pas une cache d’eau !") return false end
|
||||
local entClass = targetEnt:GetClass()
|
||||
if entClass != "ix_watercache" then client:Notify("Vous ne regardez pas une cache d’eau !") return false end
|
||||
if targetEnt.HasPotPlaced then client:Notify("Il y a déjà une valve sur cette cache d’eau !") 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("Impossible de faire tomber la vanne d’eau et de la placer.")
|
||||
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] Valve d’eau chargées.\n")
|
||||
else
|
||||
MsgC(Color(0, 255, 0), "[WATER LOOT] Aucune valve d’eau chargée.\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)
|
||||
Reference in New Issue
Block a user