mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 05:43:46 +03:00
891 lines
28 KiB
Lua
891 lines
28 KiB
Lua
--[[
|
|
| 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
|
|
|
|
-- Util Functions:
|
|
-- A function to sync apartment name and type with the client (for ESP)
|
|
function PLUGIN:SyncApartments(client)
|
|
if !CAMI.PlayerHasAccess(client, "Helix - Observer Extra ESP", nil) then return end
|
|
|
|
local nameAndType = self:AppGetNameAndType()
|
|
|
|
for _, v in pairs(player.GetAll()) do
|
|
if !CAMI.PlayerHasAccess(v, "Helix - Observer Extra ESP", nil) then continue end
|
|
netstream.Start(v, "SyncApartments", nameAndType)
|
|
end
|
|
end
|
|
|
|
-- A function to sync the apartment doors, name and type with the client (for ESP) on initial spawn
|
|
function PLUGIN:SyncToOneApartments(client, appID, foundApartment, genericData, bDatafile)
|
|
if (appID) then
|
|
local nameTable = {}
|
|
appID = tonumber(appID)
|
|
if !self.apartments[appID] then return end
|
|
|
|
nameTable[appID] = {
|
|
name = self.apartments[appID].name
|
|
}
|
|
|
|
netstream.Start(client, "SyncApartments", nameTable, true, bDatafile)
|
|
return
|
|
end
|
|
|
|
if foundApartment and genericData then
|
|
local names = self:GetAppNames()
|
|
netstream.Start(client, "TerminalUpdateHousing", foundApartment, names, genericData)
|
|
end
|
|
|
|
if !CAMI.PlayerHasAccess(client, "Helix - Observer Extra ESP", nil) then return end
|
|
|
|
local nameAndType = self:AppGetNameAndType()
|
|
netstream.Start(client, "SyncApartments", nameAndType)
|
|
end
|
|
|
|
function PLUGIN:SyncApartmentsToDatapad(client, curCollect)
|
|
if !self:HasAccessToDatafile(client) then return end
|
|
|
|
local toSend = {}
|
|
local curApartments = {}
|
|
local curShops = {}
|
|
|
|
for appID, v in pairs(self.apartments) do
|
|
v.appID = appID
|
|
|
|
if v.type == "normal" then
|
|
curApartments[#curApartments + 1] = v
|
|
continue
|
|
end
|
|
|
|
curShops[#curShops + 1] = v
|
|
end
|
|
|
|
for i = curCollect - 4, curCollect do
|
|
if curApartments[i] then
|
|
toSend[#toSend + 1] = curApartments[i]
|
|
end
|
|
|
|
if curShops[i] then
|
|
toSend[#toSend + 1] = curShops[i]
|
|
end
|
|
end
|
|
|
|
netstream.Start(client, "SyncApartmentsToDatapad", toSend)
|
|
end
|
|
|
|
-- A function to get doors, type and names from the apartments table
|
|
function PLUGIN:AppGetNameAndType()
|
|
local namesAndType = {}
|
|
for appID, tApartment in pairs(self.apartments) do
|
|
namesAndType[appID] = {
|
|
name = tApartment.name,
|
|
doors = tApartment.doors,
|
|
type = tApartment.type
|
|
}
|
|
end
|
|
|
|
return namesAndType
|
|
end
|
|
|
|
-- A function to get names from the apartments table
|
|
function PLUGIN:GetAppNames()
|
|
local names = {}
|
|
for appID, tApartment in pairs(self.apartments) do
|
|
names[appID] = {
|
|
name = tApartment.name
|
|
}
|
|
end
|
|
|
|
return names
|
|
end
|
|
|
|
-- A function to update an apartment in the database
|
|
function PLUGIN:UpdateApartment(appID)
|
|
local queryUpdate = mysql:Update("ix_apartments_"..game.GetMap())
|
|
queryUpdate:Where("app_id", appID)
|
|
queryUpdate:Update("app_name", self.apartments[appID].name)
|
|
local doors = {}
|
|
for _, v in pairs(self.apartments[appID].doors) do
|
|
if (IsValid(Entity(v))) then
|
|
local id = Entity(v):MapCreationID()
|
|
if (id == -1) then continue end
|
|
doors[#doors + 1] = id
|
|
end
|
|
end
|
|
queryUpdate:Update("app_doors", util.TableToJSON(doors))
|
|
queryUpdate:Update("app_employees", util.TableToJSON(self.apartments[appID].employees))
|
|
queryUpdate:Update("app_permits", util.TableToJSON(self.apartments[appID].permits))
|
|
queryUpdate:Update("app_tenants", util.TableToJSON(self.apartments[appID].tenants))
|
|
queryUpdate:Update("app_lastactions", util.TableToJSON(self.apartments[appID].lastActions))
|
|
queryUpdate:Update("app_rent", self.apartments[appID].rent)
|
|
queryUpdate:Update("app_payments", util.TableToJSON(self.apartments[appID].payments))
|
|
queryUpdate:Update("app_type", self.apartments[appID].type)
|
|
queryUpdate:Update("app_noassign", self.apartments[appID].noAssign)
|
|
queryUpdate:Update("app_rentdue", self.apartments[appID].rentDue)
|
|
queryUpdate:Execute()
|
|
end
|
|
|
|
local function HandlePermitUpdateForEachChar(newPermit, permits, char, charID, isEmployee)
|
|
if char then
|
|
local genericData = char:GetGenericdata()
|
|
local charPermits = ix.permits.get()
|
|
if isEmployee then
|
|
for k, _ in pairs(charPermits) do
|
|
charPermits[k] = false
|
|
end
|
|
for k, v in pairs(genericData.permits) do
|
|
charPermits[k] = v
|
|
end
|
|
for k, v in pairs(permits) do
|
|
if charPermits[k] != v then return end
|
|
end
|
|
end
|
|
|
|
char:SetPermit(newPermit, !permits[newPermit])
|
|
else
|
|
local query = mysql:Select("ix_characters_data")
|
|
query:Where("key", "genericdata")
|
|
query:Where("id", tostring(charID))
|
|
query:Select("data")
|
|
query:Callback(function(result)
|
|
if (!istable(result) or #result == 0) then
|
|
return
|
|
end
|
|
local genericData = util.JSONToTable(result[1]["data"])
|
|
|
|
local charPermits = ix.permits.get()
|
|
if isEmployee then
|
|
for k, _ in pairs(charPermits) do
|
|
charPermits[k] = false
|
|
end
|
|
for k, v in pairs(genericData.permits) do
|
|
charPermits[k] = v
|
|
end
|
|
for k, v in pairs(permits) do
|
|
if charPermits[k] != v then return end
|
|
end
|
|
end
|
|
if !permits[newPermit] then
|
|
genericData.permits[newPermit] = !permits[newPermit]
|
|
else
|
|
genericData.permits[newPermit] = nil
|
|
end
|
|
local addPermit = mysql:Update("ix_characters_data")
|
|
addPermit:Where("id", tostring(charID))
|
|
addPermit:Where("key", "genericdata")
|
|
addPermit:Update("data", util.TableToJSON(genericData))
|
|
addPermit:Execute()
|
|
end)
|
|
query:Execute()
|
|
end
|
|
end
|
|
|
|
function PLUGIN:HandleShopPermitUpdate(appID, newPermit)
|
|
local apartment = self.apartments[appID]
|
|
if apartment.type != "shop" then return end
|
|
local permits = {}
|
|
for permit, bValue in pairs(apartment.permits) do
|
|
permits[permit] = bValue
|
|
end
|
|
permits[newPermit] = !permits[newPermit]
|
|
for cid, employee in pairs(apartment.employees) do
|
|
local char
|
|
local charID
|
|
self:LookUpCardItemIDByCID(tostring(cid), function(result)
|
|
local idCardID = result[1].idcard or false
|
|
if !result then return end
|
|
if !ix.item.instances[idCardID] then
|
|
ix.item.LoadItemByID(idCardID, false, function(item)
|
|
if !item then return end
|
|
char = ix.char.loaded[item:GetData("owner")]
|
|
charID = item:GetData("owner")
|
|
|
|
HandlePermitUpdateForEachChar(newPermit, permits, char, charID, true)
|
|
end)
|
|
else
|
|
char = ix.char.loaded[ix.item.instances[idCardID]:GetData("owner")]
|
|
charID = ix.item.instances[idCardID]:GetData("owner")
|
|
|
|
HandlePermitUpdateForEachChar(newPermit, permits, char, charID, true)
|
|
end
|
|
end)
|
|
end
|
|
|
|
for cid, tenant in pairs(apartment.tenants) do
|
|
local char
|
|
local charID
|
|
self:LookUpCardItemIDByCID(tostring(cid), function(result)
|
|
local idCardID = result[1].idcard or false
|
|
if !result then return end
|
|
if !ix.item.instances[idCardID] then
|
|
ix.item.LoadItemByID(idCardID, false, function(item)
|
|
if !item then return end
|
|
char = ix.char.loaded[item:GetData("owner")]
|
|
charID = item:GetData("owner")
|
|
|
|
HandlePermitUpdateForEachChar(newPermit, permits, char, charID, false)
|
|
end)
|
|
else
|
|
char = ix.char.loaded[ix.item.instances[idCardID]:GetData("owner")]
|
|
charID = ix.item.instances[idCardID]:GetData("owner")
|
|
|
|
HandlePermitUpdateForEachChar(newPermit, permits, char, charID, false)
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
-- A function to check if a door is already added to an apartment
|
|
function PLUGIN:CheckIfDoorAlreadyAdded(client, entDoor, bNoNotify)
|
|
for key, tInfo in pairs(self.apartments) do
|
|
for _, doorIndex in pairs(tInfo.doors) do
|
|
if doorIndex == entDoor:EntIndex() then
|
|
if !bNoNotify then
|
|
client:NotifyLocalized("Cette porte est déjà ajoutée à un appartement ! - "..tInfo.name)
|
|
end
|
|
|
|
return key, tInfo.name
|
|
end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
-- A function to check if an apartment exists before adding a door to it
|
|
function PLUGIN:CheckIfApartmentExists(client, appName)
|
|
for key, tInfo in pairs(self.apartments) do
|
|
if string.lower(tInfo.name) == string.lower(appName) then
|
|
return key
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
-- A function check what apartment a CID belongs to
|
|
function PLUGIN:GetApartmentByCID(cid, type)
|
|
for key, tInfo in pairs(self.apartments) do
|
|
if (type and type:find("shop")) then
|
|
if tInfo.type != "shop" then continue end
|
|
end
|
|
|
|
if (type and type:find("apartment")) then
|
|
if tInfo.type == "shop" then continue end
|
|
end
|
|
|
|
if tInfo.tenants[cid] or tInfo.employees[cid] then
|
|
return key
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
-- A function to find the apartment to assign
|
|
function PLUGIN:GetWhichApartmentToAssign(appType)
|
|
local appTenants = {}
|
|
local maxTenants = ix.config.Get("housingMaxTenants")
|
|
for appID, tApartment in pairs(self.apartments) do
|
|
if tApartment.noAssign == true then continue end
|
|
if table.IsEmpty(tApartment.doors) then continue end
|
|
if table.Count(tApartment.tenants) >= maxTenants then continue end
|
|
if tApartment.type != appType then continue end
|
|
|
|
appTenants[appID] = table.Count(tApartment.tenants)
|
|
end
|
|
|
|
local fillOrder = {}
|
|
for i = 0, maxTenants - 1 do
|
|
fillOrder[#fillOrder + 1] = i
|
|
end
|
|
if (maxTenants >= 2) then
|
|
if (ix.config.Get("housingFirstFull")) then
|
|
fillOrder = table.Reverse(fillOrder)
|
|
elseif (ix.config.Get("housingFirstDouble")) then
|
|
fillOrder[1] = 1
|
|
fillOrder[2] = 0
|
|
end
|
|
end
|
|
|
|
for _, i in ipairs(fillOrder) do
|
|
for appID2, tenantCount in pairs(appTenants) do
|
|
if tenantCount == i then
|
|
return appID2
|
|
end
|
|
end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function PLUGIN:InventoryItemAdded(oldInv, inventory, item)
|
|
if (oldInv != nil) then return end
|
|
|
|
if (item.uniqueID == "apartmentkey" or item.uniqueID == "shopkey") then
|
|
PLUGIN:UpdateItemIDTenant(item:GetData("cid"), item:GetID(), item.uniqueID)
|
|
PLUGIN:UpdateItemIDEmployee(item:GetData("cid"), item:GetID(), item.uniqueID)
|
|
end
|
|
end
|
|
|
|
-- A function to get what apartment the door is assigned to
|
|
function PLUGIN:GetDoorApartment(client, entDoor)
|
|
if !self:CheckIfDoorAlreadyAdded(client, entDoor) then
|
|
client:NotifyLocalized("Impossible de trouver un appartement auquel cette porte est attribuée...")
|
|
end
|
|
end
|
|
|
|
-- A function to check if a key has access
|
|
function PLUGIN:GetKeyHasAccess(item, entDoor, bNoNotify)
|
|
local client = item:GetOwner()
|
|
local _, appName = self:CheckIfDoorAlreadyAdded(client, entDoor, true)
|
|
local itemCID = item:GetData("cid") or false
|
|
local itemID = item:GetID()
|
|
|
|
for appID, tApartment in pairs(self.apartments) do
|
|
if !tApartment.tenants[itemCID] and !tApartment.employees[itemCID] then continue end
|
|
for _, doorIndex in pairs(tApartment.doors) do
|
|
if doorIndex != entDoor:EntIndex() then continue end
|
|
|
|
if tApartment.tenants[itemCID] and tApartment.tenants[itemCID].key == itemID then return appID, itemCID
|
|
elseif tApartment.employees[itemCID] and tApartment.employees[itemCID].key == itemID then return appID, itemCID end
|
|
end
|
|
end
|
|
|
|
if !bNoNotify then
|
|
client:NotifyLocalized("You don't have access to this housing!")
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
-- A function get if a key already has access to another apartment
|
|
function PLUGIN:GetKeyAlreadyHasOtherAccess(item)
|
|
local itemCID = item:GetData("cid") or false
|
|
|
|
for key, tApartment in pairs(self.apartments) do
|
|
local tenant = tApartment.tenants[itemCID]
|
|
if (tenant and tenant != false) then return key end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function PLUGIN:HasCIDInInventory(client, cid)
|
|
local bFound = false
|
|
for _, v in pairs(client:GetCharacter():GetInventory():GetItems()) do
|
|
if v.uniqueID != "id_card" then continue end
|
|
if v:GetData("cid", false) and tonumber(v:GetData("cid", false)) == tonumber(cid) then
|
|
bFound = v
|
|
break
|
|
end
|
|
end
|
|
|
|
return bFound
|
|
end
|
|
|
|
function PLUGIN:RequestAssignedApartmentInfo(client, cid, bShop)
|
|
if !self:HasCIDInInventory(client, cid) then return end
|
|
|
|
local assignedApp
|
|
if !bShop then assignedApp = self:GetApartmentByCID(cid, "apartment") end
|
|
if bShop then assignedApp = self:GetApartmentByCID(cid, "shop") end
|
|
if !assignedApp then
|
|
netstream.Start(client, "ReplyApartmentInfo", false, false)
|
|
return
|
|
end
|
|
|
|
netstream.Start(client, "ReplyApartmentInfo", self.apartments[assignedApp], assignedApp, bShop)
|
|
end
|
|
|
|
function PLUGIN:ToggleApartmentNoAssign(client, appID)
|
|
if !appID then client:NotifyLocalized("Invalid apartment") return end
|
|
|
|
if self.apartments[appID].noAssign then
|
|
self.apartments[appID].noAssign = false
|
|
client:NotifyLocalized("Faire basculer l'affectation de cet appartement sur faux.")
|
|
else
|
|
self.apartments[appID].noAssign = true
|
|
client:NotifyLocalized("Faire basculer l'affectation de cet appartement sur vrai.")
|
|
end
|
|
|
|
self:UpdateApartment(appID)
|
|
end
|
|
|
|
function PLUGIN:AddDoorInteraction(client, appID, cid)
|
|
self.apartments[appID].lastActions[cid] = os.time()
|
|
self:UpdateApartment(appID)
|
|
end
|
|
|
|
function PLUGIN:PayRent(client, amount, appID, cid)
|
|
local cidItem = self:HasCIDInInventory(client, cid)
|
|
if !cidItem then return false end
|
|
|
|
local cidData = cidItem:GetData("cid")
|
|
if !cidData then return false end
|
|
|
|
if cidItem:GetCredits() < amount then
|
|
netstream.Start(client, "SendHousingErrorMessage", "PAS ASSEZ DE CRÉDITS")
|
|
return
|
|
end
|
|
|
|
cidData = Schema:ZeroNumber(cidData, 5)
|
|
|
|
if self.apartments[appID].payments[cidData] then
|
|
self.apartments[appID].payments[cidData] = {amount = amount + self.apartments[appID].payments[cidData].amount, date = os.time()}
|
|
else
|
|
self.apartments[appID].payments[cidData] = {amount = amount, date = os.time()}
|
|
end
|
|
|
|
cidItem:TakeCredits(amount, "Housing", "Rent")
|
|
ix.city.main:AddCredits(amount)
|
|
|
|
self:UpdateApartment(appID)
|
|
|
|
netstream.Start(client, "UpdateHousingPaymentPanel", self.apartments[appID], appID, amount)
|
|
end
|
|
|
|
function PLUGIN:SetTenantAutoPayment(client, appID, cid, bEnabled)
|
|
local cidItem = self:HasCIDInInventory(client, cid)
|
|
if !cidItem then return false end
|
|
|
|
local cidData = cidItem:GetData("cid")
|
|
if !cidData then return false end
|
|
|
|
cidData = Schema:ZeroNumber(cidData, 5)
|
|
|
|
self.apartments[appID].tenants[cidData].autoPay = bEnabled
|
|
self:UpdateApartment(appID)
|
|
end
|
|
|
|
function PLUGIN:HasAccessToDatafile(client)
|
|
local combineutilities = ix.plugin.list["combineutilities"]
|
|
if !combineutilities then return end
|
|
if (!combineutilities:HasAccessToDatafile(client)) then return false end
|
|
|
|
return true
|
|
end
|
|
|
|
-- Hooks
|
|
|
|
netstream.Hook("SetTenantAutoPayment", function(client, appID, cid, bEnabled)
|
|
PLUGIN:SetTenantAutoPayment(client, appID, cid, bEnabled)
|
|
end)
|
|
|
|
hook.Add("CanPlayerAccessDoor", "CheckForKeyItem", function(client, entDoor)
|
|
for _, item in ipairs(client:GetCharacter():GetInventory():GetItemsByUniqueID("apartmentkey")) do
|
|
local appID, cid = PLUGIN:GetKeyHasAccess(item, entDoor, true)
|
|
if (appID and cid) then
|
|
PLUGIN:AddDoorInteraction(client, appID, cid)
|
|
return true
|
|
end
|
|
end
|
|
|
|
for _, item in ipairs(client:GetCharacter():GetInventory():GetItemsByUniqueID("shopkey")) do
|
|
local appID, cid = PLUGIN:GetKeyHasAccess(item, entDoor, true)
|
|
if (appID and cid) then
|
|
PLUGIN:AddDoorInteraction(client, appID, cid)
|
|
return true
|
|
end
|
|
end
|
|
|
|
return false
|
|
end)
|
|
|
|
hook.Add("CAMI.PlayerUsergroupChanged", "SyncApartmentsToOne", function(client)
|
|
PLUGIN:SyncToOneApartments(client)
|
|
end)
|
|
|
|
netstream.Hook("RequestApartmentNames", function(client, appID)
|
|
PLUGIN:SyncToOneApartments(client, appID)
|
|
end)
|
|
|
|
function PLUGIN:RefreshApartmentsPanel(client)
|
|
if !CAMI.PlayerHasAccess(client, "Helix - Manage Apartments", nil) then return end
|
|
|
|
local nameAndType = PLUGIN:AppGetNameAndType()
|
|
|
|
for appID, tApartment in pairs(PLUGIN.apartments) do
|
|
nameAndType[appID].rent = tApartment.rent
|
|
end
|
|
|
|
netstream.Start(client, "SyncApartmentsApartmentsPanel", nameAndType)
|
|
end
|
|
|
|
netstream.Hook("RequestApartmentNamesApartmentsPanel", function(client)
|
|
PLUGIN:RefreshApartmentsPanel(client)
|
|
end)
|
|
|
|
netstream.Hook("CreateApartmentApartmentsUI", function(client, type, name)
|
|
PLUGIN:CreateApartment(client, name, false, type)
|
|
PLUGIN:RefreshApartmentsPanel(client)
|
|
end)
|
|
|
|
netstream.Hook("RequestApartmentNamesDatafile", function(client, appID)
|
|
PLUGIN:SyncToOneApartments(client, appID, false, false, true)
|
|
end)
|
|
|
|
netstream.Hook("ixApartmentsRequest", function(client, cid, type)
|
|
PLUGIN:HandleAssignment(client, cid, type)
|
|
end)
|
|
|
|
netstream.Hook("RequestAssignedApartmentInfo", function(client, cid, bShop)
|
|
PLUGIN:RequestAssignedApartmentInfo(client, cid, bShop)
|
|
end)
|
|
|
|
netstream.Hook("ixApartmentsAssignKeyToApartment", function(client, keyItemID, appID, bRemove)
|
|
if !CAMI.PlayerHasAccess(client, "Helix - Manage Apartments Key", nil) then return end
|
|
if !ix.item.instances[keyItemID] then return end
|
|
|
|
if !bRemove then
|
|
ix.item.instances[keyItemID]:AssignToApartment(appID)
|
|
else
|
|
ix.item.instances[keyItemID]:RemoveApartment()
|
|
end
|
|
end)
|
|
|
|
netstream.Hook("ixApartmentsAssignCIDToKey", function(client, keyItemID, cid)
|
|
if !CAMI.PlayerHasAccess(client, "Helix - Manage Apartments Key", nil) then return end
|
|
if !ix.item.instances[keyItemID] then return end
|
|
|
|
ix.item.instances[keyItemID]:SetCID(cid)
|
|
end)
|
|
|
|
netstream.Hook("PayRent", function(client, amount, appID, cid)
|
|
PLUGIN:PayRent(client, amount, appID, cid)
|
|
end)
|
|
|
|
netstream.Hook("RequestApartmentNamesDatapad", function(client, curCollect)
|
|
PLUGIN:SyncApartmentsToDatapad(client, curCollect)
|
|
end)
|
|
|
|
netstream.Hook("ChangeApartmentName", function(client, appID, newName)
|
|
if !CAMI.PlayerHasAccess(client, "Helix - Manage Apartments", nil) then return end
|
|
if !PLUGIN.apartments[appID] then return end
|
|
PLUGIN.apartments[appID].name = newName
|
|
PLUGIN:UpdateApartment(appID)
|
|
|
|
for _, doorEntID in pairs(PLUGIN.apartments[appID].doors) do
|
|
local entDoor = Entity(doorEntID)
|
|
if (IsValid(entDoor) and entDoor:IsDoor()) then
|
|
entDoor:SetNetVar("visible", true)
|
|
entDoor:SetNetVar("name", newName)
|
|
|
|
local doorPlugin = ix.plugin.list["doors"]
|
|
if doorPlugin then
|
|
doorPlugin:SaveDoorData()
|
|
end
|
|
end
|
|
end
|
|
|
|
netstream.Start(client, "UpdateApartmentList")
|
|
end)
|
|
|
|
netstream.Hook("RemoveApartmentHousing", function(client, name)
|
|
PLUGIN:RemoveApartment(client, name)
|
|
netstream.Start(client, "UpdateApartmentList")
|
|
end)
|
|
|
|
netstream.Hook("RemoveTenant", function(client, tenantCID, appID)
|
|
if !PLUGIN:HasAccessToDatafile(client) then return end
|
|
if !PLUGIN.apartments[appID] then return end
|
|
if !PLUGIN.apartments[appID].tenants[tenantCID] then
|
|
for newAppID, tApartment in pairs(PLUGIN.apartments) do
|
|
if !tApartment.tenants[tenantCID] then continue end
|
|
|
|
PLUGIN:RemoveTenant(client, tenantCID, newAppID, true)
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
PLUGIN:RemoveTenant(client, tenantCID, appID, true)
|
|
end)
|
|
|
|
netstream.Hook("RemoveEmployee", function(client, employeeCID, appID)
|
|
if !PLUGIN:HasAccessToDatafile(client) and !PLUGIN.apartments[appID].tenants[client:GetCharacter():GetGenericdata().cid] then return end
|
|
if !PLUGIN.apartments[appID] then return end
|
|
if !PLUGIN.apartments[appID].employees[employeeCID] then
|
|
for newAppID, tApartment in pairs(PLUGIN.apartments) do
|
|
if !tApartment.employees[employeeCID] then continue end
|
|
|
|
PLUGIN:RemoveEmployee(client, employeeCID, newAppID, true)
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
PLUGIN:RemoveEmployee(client, employeeCID, appID, true)
|
|
end)
|
|
|
|
function PLUGIN.RenewKey(idCard, genericData, client, appID, bEmployee)
|
|
if !PLUGIN:HasAccessToDatafile(client) then return end
|
|
|
|
if !idCard then return end
|
|
local cid = idCard:GetData("cid")
|
|
if !cid or istable(cid) then client:NotifyLocalized("CID IS TABLE") return end
|
|
|
|
if !PLUGIN.apartments[appID] then return end
|
|
if !bEmployee then
|
|
if !PLUGIN.apartments[appID].tenants[cid] then return end
|
|
else
|
|
if !PLUGIN.apartments[appID].employees[cid] then return end
|
|
end
|
|
local character = ix.char.loaded[genericData.id]
|
|
if character then
|
|
local appType = PLUGIN.apartments[appID].type
|
|
if !character:GetPurchasedItems()[appType == "shop" and "shopkey" or "apartmentkey"] then
|
|
character:SetPurchasedItems(appType == "shop" and "shopkey" or "apartmentkey", 1)
|
|
else
|
|
client:NotifyLocalized("Il y a déjà une clé qui attend au terminal de collecte pour ce CID.")
|
|
end
|
|
if !bEmployee then
|
|
PLUGIN.apartments[appID].tenants[cid].key = true
|
|
else
|
|
PLUGIN.apartments[appID].employees[cid].key = true
|
|
end
|
|
PLUGIN:UpdateApartment(appID)
|
|
client:NotifyLocalized("Succès. Leur clé actuelle est désactivée et ils peuvent maintenant prendre une nouvelle clé dans le terminal de collecte.")
|
|
netstream.Start(client, "UpdateIndividualApartment", appID, PLUGIN.apartments[appID])
|
|
return
|
|
end
|
|
|
|
client:NotifyLocalized("Echec. La personne n'est pas en ligne, donc aucune clé peut lui être réassignée.")
|
|
end
|
|
|
|
netstream.Hook("RenewKey", function(client, tenantCID, appID, bEmployee)
|
|
if !PLUGIN:HasAccessToDatafile(client) then return end
|
|
if !PLUGIN.apartments[appID] then return end
|
|
tenantCID = Schema:ZeroNumber(tenantCID, 5)
|
|
|
|
if !PLUGIN.apartments[appID].tenants[tenantCID] and !PLUGIN.apartments[appID].employees[tenantCID] then return end
|
|
|
|
PLUGIN:LookUpCardItemIDByCID(tostring(tenantCID), function(result)
|
|
local idCardID = result[1].idcard or false
|
|
if !result then client:NotifyLocalized("This CID doesn't exist!") return end
|
|
|
|
if !ix.item.instances[idCardID] then
|
|
ix.item.LoadItemByID(idCardID, false, function(item)
|
|
if !item then return end
|
|
item:LoadOwnerGenericData(PLUGIN.RenewKey, false, client, appID, bEmployee)
|
|
end)
|
|
else
|
|
ix.item.instances[idCardID]:LoadOwnerGenericData(PLUGIN.RenewKey, false, client, appID, bEmployee)
|
|
end
|
|
end)
|
|
end)
|
|
|
|
function PLUGIN.AddEmployeeManually(idCard, genericData, client, appID)
|
|
local cid = idCard:GetData("cid")
|
|
if !cid or istable(cid) then client:NotifyLocalized("CID IS TABLE") return end
|
|
if PLUGIN.apartments[appID].type != "shop" then return client:NotifyLocalized("This is not a shop!") end
|
|
cid = Schema:ZeroNumber(idCard:GetData("cid"), 5)
|
|
for newAppID, tApartment in pairs(PLUGIN.apartments) do
|
|
if tApartment.type != "shop" then continue end
|
|
if tApartment.employees[cid] then return client:NotifyLocalized(tostring(cid) .. " is already being an employee in " .. PLUGIN.apartments[newAppID].name) end
|
|
if tApartment.tenants[cid] then return client:NotifyLocalized(tostring(cid) .. " is already being a tenant in " .. PLUGIN.apartments[newAppID].name) end
|
|
end
|
|
local character = ix.char.loaded[genericData.id]
|
|
if character then
|
|
for k, v in pairs(PLUGIN.apartments[appID].permits) do
|
|
character:SetPermit(k, v)
|
|
end
|
|
if PLUGIN:AddKeyToApartment(client, cid, appID, nil, nil, true) then
|
|
local appType = PLUGIN.apartments[appID].type
|
|
local item = (appType != "shop" and "apartmentkey" or "shopkey")
|
|
if !character:GetPurchasedItems()[item] then
|
|
character:SetPurchasedItems(item, 1)
|
|
else
|
|
client:NotifyLocalized("There is already a"..(appType != "shop" and "n apartment" or " shop").." key waiting at the pickup dispenser for this cid. It has been updated.")
|
|
end
|
|
netstream.Start(client, "UpdateIndividualApartment", appID, PLUGIN.apartments[appID])
|
|
end
|
|
netstream.Start(client, "AddEmployeeToList", PLUGIN.apartments[appID], cid, appID)
|
|
else
|
|
client:NotifyLocalized("Fail. The character was not online, so no employee was assigned.")
|
|
end
|
|
end
|
|
|
|
function PLUGIN.AddTenantManually(idCard, genericData, client, appID)
|
|
local cid = idCard:GetData("cid")
|
|
if !cid or istable(cid) then client:NotifyLocalized("CID IS TABLE") return end
|
|
cid = Schema:ZeroNumber(idCard:GetData("cid"), 5)
|
|
|
|
if PLUGIN.apartments[appID].employees[cid] then return client:NotifyLocalized("You can't assign person who's already is an employee as a tenant.") end
|
|
|
|
if PLUGIN.apartments[appID].type == "shop" then
|
|
if table.IsEmpty(genericData.permits) then
|
|
client:NotifyLocalized("Ce CID n'a pas de permis, mais a quand même été ajouté.")
|
|
end
|
|
end
|
|
|
|
if PLUGIN.apartments[appID].type == "shop" then
|
|
genericData.shop = appID
|
|
else
|
|
genericData.housing = appID
|
|
end
|
|
|
|
local combineutilities = ix.plugin.list["combineutilities"]
|
|
if combineutilities and combineutilities.UpdateGenericData then
|
|
combineutilities:UpdateGenericData(genericData)
|
|
end
|
|
|
|
|
|
local character = ix.char.loaded[genericData.id]
|
|
if character then
|
|
if PLUGIN.apartments[appID].type == "shop" then
|
|
for k, v in pairs(PLUGIN.apartments[appID].permits) do
|
|
character:SetPermit(k, v)
|
|
end
|
|
end
|
|
if PLUGIN:AddKeyToApartment(client, cid, appID) then
|
|
local appType = PLUGIN.apartments[appID].type
|
|
local item = (appType != "shop" and "apartmentkey" or "shopkey")
|
|
|
|
if !character:GetPurchasedItems()[item] then
|
|
character:SetPurchasedItems(item, 1)
|
|
else
|
|
client:NotifyLocalized("Il existe déjà un"..(appType != "shop" and "apartement" or " commerce").." avec une clé dans un terminal de collecte.")
|
|
end
|
|
|
|
netstream.Start(client, "UpdateIndividualApartment", appID, PLUGIN.apartments[appID])
|
|
end
|
|
|
|
if PLUGIN.apartments[appID].type == "shop" then
|
|
for _, shopTerminal in pairs(ents.FindByClass("ix_shopterminal")) do
|
|
shopTerminal:UpdateScreen()
|
|
end
|
|
end
|
|
else
|
|
client:NotifyLocalized("Échec. Le personnage n'était pas en ligne, donc aucun locataire n'a été assigné.")
|
|
end
|
|
end
|
|
|
|
netstream.Hook("AddTenant", function(client, appID, cid)
|
|
if !PLUGIN:HasAccessToDatafile(client) then return end
|
|
if !appID or !cid then return end
|
|
|
|
cid = Schema:ZeroNumber(cid, 5)
|
|
|
|
if !PLUGIN:CheckIfCIDExistsLoaded(cid) then
|
|
if !PLUGIN:CheckIfCIDExistsDatabase(cid) then
|
|
client:NotifyLocalized("Ce CID n'existe pas !")
|
|
return
|
|
end
|
|
|
|
client:NotifyLocalized("Ce CID n'existe pas !")
|
|
return
|
|
end
|
|
|
|
PLUGIN:LookUpCardItemIDByCID(tostring(cid), function(result)
|
|
local idCardID = result[1].idcard or false
|
|
if !result then client:NotifyLocalized("Ce CID n'existe pas !") return end
|
|
|
|
if !ix.item.instances[idCardID] then
|
|
ix.item.LoadItemByID(idCardID, false, function(item)
|
|
if !item then return end
|
|
item:LoadOwnerGenericData(PLUGIN.AddTenantManually, false, client, appID)
|
|
end)
|
|
else
|
|
ix.item.instances[idCardID]:LoadOwnerGenericData(PLUGIN.AddTenantManually, false, client, appID)
|
|
end
|
|
end)
|
|
end)
|
|
|
|
netstream.Hook("AddEmployee", function(client, appID, cid)
|
|
if !PLUGIN:HasAccessToDatafile(client) and !PLUGIN.apartments[appID].tenants[client:GetCharacter():GetGenericdata().cid] then return end
|
|
if !appID or !cid then return end
|
|
if PLUGIN.apartments[appID].type != "shop" then return client:NotifyLocalized("This is not a shop!") end
|
|
|
|
|
|
cid = Schema:ZeroNumber(cid, 5)
|
|
|
|
if !PLUGIN:CheckIfCIDExistsLoaded(cid) then
|
|
if !PLUGIN:CheckIfCIDExistsDatabase(cid) then
|
|
client:NotifyLocalized("This CID doesn't exist!")
|
|
return
|
|
end
|
|
|
|
client:NotifyLocalized("This CID doesn't exist!")
|
|
return
|
|
end
|
|
|
|
PLUGIN:LookUpCardItemIDByCID(tostring(cid), function(result)
|
|
local idCardID = result[1].idcard or false
|
|
if !result then client:NotifyLocalized("This CID doesn't exist!") return end
|
|
|
|
if !ix.item.instances[idCardID] then
|
|
ix.item.LoadItemByID(idCardID, false, function(item)
|
|
if !item then return end
|
|
item:LoadOwnerGenericData(PLUGIN.AddEmployeeManually, false, client, appID)
|
|
end)
|
|
else
|
|
ix.item.instances[idCardID]:LoadOwnerGenericData(PLUGIN.AddEmployeeManually, false, client, appID)
|
|
end
|
|
end)
|
|
end)
|
|
|
|
netstream.Hook("ApartmentUpdateRent", function(client, appID, newRent)
|
|
if !PLUGIN:HasAccessToDatafile(client) then return end
|
|
|
|
PLUGIN:SetApartmentRent(client, appID, false, newRent)
|
|
netstream.Start(client, "UpdateIndividualApartment", appID, PLUGIN.apartments[appID])
|
|
end)
|
|
|
|
netstream.Hook("ApartmentExtendRentDueDateByDays", function(client, appID, days)
|
|
if !PLUGIN:HasAccessToDatafile(client) then return end
|
|
PLUGIN.apartments[appID].rentDue = PLUGIN.apartments[appID].rentDue + 3600 * 24 * tonumber(days)
|
|
PLUGIN:UpdateApartment(appID)
|
|
|
|
netstream.Start(client, "UpdateIndividualApartment", appID, PLUGIN.apartments[appID])
|
|
end)
|
|
|
|
netstream.Hook("BuyShopViaTerminal", function(client, ent, permits)
|
|
if !IsValid(ent) then return end
|
|
|
|
if ent:IsPurchasable() then
|
|
local shopID = ent:GetShopID()
|
|
local character = client:GetCharacter()
|
|
local idCard = character:GetInventory():HasItem("id_card")
|
|
|
|
if (client:EyePos():DistToSqr(ent:GetPos()) > 62500) then return end
|
|
if !shopID then return client:NotifyLocalized("Can't find any shop with this ID.") end
|
|
if !idCard then return client:NotifyLocalized("You don't have CID in your inventory!") end
|
|
if !permits or #table.GetKeys(permits) > 3 then return end
|
|
if character:GetGenericdata().socialCredits < ent:GetShopSocialCreditReq() then
|
|
return client:NotifyLocalized("You don't have enough social credits!")
|
|
end
|
|
|
|
if !idCard:HasCredits(ent:GetShopCost()) then
|
|
return client:NotifyLocalized("You don't have enough credits!")
|
|
end
|
|
|
|
idCard:TakeCredits(ent:GetShopCost(), "Shop Terminal", "Shop bought.")
|
|
local idCardNumber = idCard:GetData("cid", "00000")
|
|
|
|
for i = 1, #PLUGIN.apartments do
|
|
local apartment = PLUGIN.apartments[i]
|
|
if apartment.type == "shop" and apartment.tenants[idCardNumber] then
|
|
return client:NotifyLocalized("You already own a shop!")
|
|
end
|
|
end
|
|
|
|
for k, _ in pairs(PLUGIN.apartments[shopID].permits) do
|
|
if permits[k] then
|
|
PLUGIN.apartments[shopID].permits[k] = true
|
|
else
|
|
PLUGIN.apartments[shopID].permits[k] = false
|
|
end
|
|
end
|
|
|
|
idCard:LoadOwnerGenericData(PLUGIN.AddTenantManually, false, client, shopID)
|
|
end
|
|
end) |