--[[ | 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 locks = {"ix_combinelock", "ix_combinelock_cwu", "ix_combinelock_cmru", "ix_combinelock_dob", "ix_combinelock_moe"} function Schema:RegisterSaveEnts() ix.saveEnts:RegisterEntity("ix_rationdispenser", true, true, true, { OnSave = function(entity, data) --OnSave data.enabled = entity:GetEnabled() data.motion = false end, OnRestore = function(entity, data) --OnRestore entity:SetEnabled(data.enabled) end, }) for k, v in ipairs(locks) do ix.saveEnts:RegisterEntity(v, true, true, true, { OnSave = function(entity, data) --OnSave data.id = entity.door:MapCreationID() data.localpos = entity.door:WorldToLocal(entity:GetPos()) data.localangs = entity.door:WorldToLocalAngles(entity:GetAngles()) data.locked = entity:GetLocked() data.accessLvl = entity.accessLevel end, OnRestore = function(entity, data) --OnRestore local door = ents.GetMapCreatedEntity(data.id) entity:SetDoor(door, door:LocalToWorld(data.localpos), door:LocalToWorldAngles(data.localangs)) entity:SetLocked(data.locked) entity.accessLevel = data.accessLvl end, ShouldSave = function(entity) --ShouldSave return IsValid(entity.door) end, ShouldRestore = function(data) --ShouldRestore local door = ents.GetMapCreatedEntity(data.id) return IsValid(door) and door:IsDoor() end }) end ix.saveEnts:RegisterEntity("ix_forcefield", true, true, true, { OnSave = function(entity, data) --OnSave data.mode = entity:GetMode() end, OnRestore = function(entity, data) --OnRestore entity:SetMode(data.mode) if (data.mode == 1) then entity:SetSkin(3) entity.dummy:SetSkin(3) else local entTable = scripted_ents.Get("ix_forcefield") local skin = entTable.MODES entity:SetSkin(skin[data.mode][4]) entity.dummy:SetSkin(skin[data.mode][4]) end end, }) ix.saveEnts:RegisterEntity("ix_rebelfield", true, true, true, { OnSave = function(entity, data) --OnSave data.mode = entity:GetMode() end, OnRestore = function(entity, data) --OnRestore entity:SetMode(data.mode) if (data.mode == 1) then entity:SetSkin(3) entity.dummy:SetSkin(3) else local entTable = scripted_ents.Get("ix_rebelfield") local skin = entTable.MODES entity:SetSkin(skin[data.mode][4]) entity.dummy:SetSkin(skin[data.mode][4]) end end, }) end function Schema:LoadData() Schema.CombineObjectives = ix.data.Get("combineObjectives", {}, false, true) if (!ix.config.Get("SaveEntsOldLoadingEnabled")) then return end self:LoadRationDispensers() self:LoadCombineLocks() self:LoadForceFields() end function Schema:SaveData() self:SaveRationDispensers() self:SaveCombineLocks() self:SaveForceFields() self:SaveRebelForceFields() end function Schema:PlayerSwitchFlashlight(client, enabled) return true end function Schema:CanPlayerOpenCombineLock(client, entity) if (client:HasActiveCombineSuit() or ix.faction.Get(client:Team()).allowCombineLock) then return true end if (client:GetCharacter():GetInventory():HasItem("combine_card")) then return true end return false end function Schema:PlayerUse(client, entity) local weapon = client:GetActiveWeapon() if (weapon and IsValid(weapon) and weapon:GetClass() == "weapon_physgun") then return false end if (!client:IsRestricted() and entity:IsDoor() and IsValid(entity.ixLock) and client:KeyDown(IN_SPEED)) then if (self:CanPlayerOpenCombineLock(client, entity)) then entity.ixLock:Toggle(client) return false else local class = entity.ixLock:GetClass() if (class == "ix_grouplock" or class == "ix_combinelock_cwu" or class == "ix_combinelock_dob" or class == "ix_combinelock_cmru" or class == "ix_combinelock_moe") then entity.ixLock:Toggle(client) return false end end end local ragdoll = nil if (entity:IsRagdoll() and entity.ixPlayer) then ragdoll = entity entity = entity.ixPlayer end end function Schema:PlayerUseDoor(client, door) if (!door:HasSpawnFlags(256) and !door:HasSpawnFlags(1024)) then if (client:HasActiveCombineSuit() or ix.faction.Get(client:Team()).allowCombineDoors) then door:Fire("open") end end end function Schema:PostPlayerLoadout(client) local factionTable = ix.faction.Get(client:Team()) if (factionTable.OnNameChanged) then factionTable:OnNameChanged(client, "", client:GetCharacter():GetName()) end if (factionTable.maxHealth) then client:SetMaxHealth(factionTable.maxHealth) client:SetHealth(factionTable.maxHealth) end local character = client:GetCharacter() if (character) then client:SetRestricted(character:GetData("tied", false)) end end function Schema:PrePlayerLoadedCharacter(client, character, oldCharacter) if (oldCharacter) then oldCharacter:SetData("tied", client:IsRestricted()) end end function Schema:PlayerLoadedCharacter(client, character, oldCharacter) if (client:IsDispatch()) then ix.combineNotify:AddNotification("LOG:// Décryptage de la connexion du noeud entrant de 144.76.222.66") timer.Simple(1, function() ix.combineNotify:AddNotification("NTC:// Envoi en ligne du noeud d'intelligence artificielle", Color(255, 255, 0, 255)) end) elseif (oldCharacter and oldCharacter:GetFaction() == FACTION_OVERWATCH) then ix.combineNotify:AddNotification("NTC:// Envoi du noeud d'intelligence artificielle hors ligne", Color(255, 255, 0, 255)) elseif (client:IsCombine() or (oldCharacter and oldCharacter:IsCombine())) then ix.combineNotify:AddNotification("LOG:// Reconstruction du manifeste Overwatch", Color(50, 100, 175)) end end function Schema:PlayerDisconnected(client) if (client:GetCharacter()) then client:GetCharacter():SetData("tied", client:IsRestricted()) end if (client:IsDispatch()) then ix.combineNotify:AddNotification("NTC:// Envoi du noeud d'intelligence artificielle hors ligne", Color(255, 255, 0, 255)) elseif (client:IsCombine()) then ix.combineNotify:AddNotification("LOG:// Reconstruction du manifeste Overwatch", Color(50, 100, 175)) end end function Schema:CharacterVarChanged(character, key, oldValue, value) local client = character:GetPlayer() if (key == "name") then local factionTable = ix.faction.Get(client:Team()) if (factionTable.OnNameChanged) then factionTable:OnNameChanged(client, oldValue, value) end end end function Schema:PlayerFootstep(client, position, foot, soundName, volume) local factionTable = ix.faction.Get(client:Team()) if (factionTable and factionTable.runSounds and client:IsRunning()) then client:EmitSound(factionTable.runSounds[foot]) return true end client:EmitSound(soundName) return true end local digitToSound = { "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" } function Schema:PlayerDeath(client, inflicter, attacker) if (client:HasActiveTracker() or client:IsCombineScanner()) then if (ix.config.Get("suitsNoConnection")) then return end local suit = ix.item.instances[client:GetCharacter():GetCombineSuit()] ix.combineNotify:AddNotification("NTC:// Téléchargement du biosignal perdu") ix.combineNotify:AddImportantNotification("WRN:// Perte du biosignal de l'unité " .. client:GetCombineTag(), nil, client, client:GetPos()) local start = "npc/overwatch/radiovoice/die"..math.random(1, 3)..".wav" if (suit.isOTA) then start = "npc/combine_soldier/die"..math.random(1, 3)..".wav" end local on = "npc/overwatch/radiovoice/on1.wav" local onRand = math.random(1, 2) if (onRand == 2) then on = "npc/overwatch/radiovoice/on3.wav" end local sounds = {start, on} local tag = client:GetCombineTag() local name = {} if (string.find(tag,"^%w+%-%d$")) then local parts = string.Explode("-", tag, false) if (Schema.voices.stored["dispatch radio"][string.lower(parts[1])]) then name[1] = Schema.voices.stored["dispatch radio"][string.lower(parts[1])].sound end if (Schema.voices.stored["dispatch radio"][digitToSound[tonumber(parts[2])]]) then name[2] = Schema.voices.stored["dispatch radio"][digitToSound[tonumber(parts[2])]].sound end end local areaSounds = {} if (client:IsInArea()) then local area = client:GetArea() if (area and ix.area.stored[area].properties.dispatchsound) then for _, v in pairs(string.Explode(";", ix.area.stored[area].properties.dispatchsound)) do areaSounds[#areaSounds + 1] = Schema.voices.stored["dispatch radio"][string.lower(v)].sound end end end local rand = math.random(1, table.Count(areaSounds) > 0 and 3 or 2) if (rand == 1) then sounds[#sounds + 1] = "npc/overwatch/radiovoice/lostbiosignalforunit.wav" if (table.Count(name) == 2) then table.Add(sounds, name) end elseif (rand == 2) then if (table.Count(name) == 2) then table.Add(sounds, name) end sounds[#sounds + 1] = "npc/overwatch/radiovoice/unitdeserviced.wav" elseif (rand == 3) then if (table.Count(name) == 2) then table.Add(sounds, name) end sounds[#sounds + 1] = "npc/overwatch/radiovoice/unitdownat.wav" end if (table.Count(areaSounds) > 0) then table.Add(sounds, areaSounds) end local chance = math.random(1, 7) if (chance == 2) then sounds[#sounds + 1] = "npc/overwatch/radiovoice/remainingunitscontain.wav" elseif (chance == 3) then sounds[#sounds + 1] = "npc/overwatch/radiovoice/reinforcementteamscode3.wav" end if (onRand != 2) then sounds[#sounds + 1] = "npc/overwatch/radiovoice/off4.wav" else sounds[#sounds + 1] = "npc/overwatch/radiovoice/off2.wav" end for _, v in ipairs(player.GetAll()) do if (v:HasActiveCombineSuit()) then ix.util.EmitQueuedSounds(v, sounds, 2, nil, v == client and 100 or 80) end end end end function Schema:PlayerHurt(client, attacker, health, damage) if (health <= 0) then return end if (client:HasActiveTracker() and (client.ixTraumaCooldown or 0) < CurTime()) then if (health < 25) then ix.combineNotify:AddNotification("WRN:// Signes vitaux en baisse - consulter une unité Helix.", Color(255, 0, 0, 255), nil, nil, client) else local text = damage > 50 and "Severe" or "External" ix.combineNotify:AddNotification("WRN:// " .. text .. " : Traumatisme Détecté", Color(255, 0, 0, 255), nil, nil, client) end client.ixTraumaCooldown = CurTime() + 15 end end local chatTypes = { ["ic"] = true, ["w"] = true, ["wd"] = true, ["y"] = true, ["radio"] = true, ["radio_eavesdrop"] = true, ["radio_eavesdrop_yell"] = true, ["dispatch"] = true, ["dispatch_radio"] = true, ["overwatch_radio"] = true, ["dispatchota_radio"] = true, ["dispatchcp_radio"] = true, ["scanner_radio"] = true, ["request"] = true, ["broadcast"] = true, ["localbroadcast"] = true } local globalBlacklist = { ["radio_eavesdrop"] = true, ["radio_eavesdrop_yell"] = true, } local validEnds = { ["."] = true, ["?"] = true, ["!"] = true } local function fixMarkup(a, b) return a.." "..string.utf8upper(b) end function Schema:PlayerMessageSend(speaker, chatType, text, anonymous, receivers, rawText, data) if (chatTypes[chatType] and speaker) then local class = self.voices.GetClass(speaker) local textTable = string.Explode("; ?", rawText, true) local voiceList = {} for k, v in ipairs(textTable) do local bFound = false local vUpper = string.utf8upper(v) local info for _, c in ipairs(class) do info = self.voices.Get(c, vUpper) if (info) then break end end if (info) then bFound = true if (info.sound) then voiceList[#voiceList + 1] = { global = info.global, sound = info.sound } end if (k == 1) then textTable[k] = info.text else textTable[k] = string.utf8lower(info.text) end if (k != #textTable) then local endText = string.utf8sub(info.text, -1) if (endText == "!" or endText == "?") then textTable[k] = string.gsub(textTable[k], "[!?]$", ",") end end end if (bFound == false and k != #textTable) then textTable[k] = v .. "; " end end local str str = table.concat(textTable, " ") str = string.gsub(str, " ?([.?!]) (%l?)", fixMarkup) if (voiceList[1]) then local volume = 80 if (chatType == "w" or (data.radioType and data.radioType == ix.radio.types.whisper)) then volume = 60 elseif (chatType == "y" or (data.radioType and data.radioType == ix.radio.types.yell)) then volume = 150 end local delay = 0 for _, v in ipairs(voiceList) do local sound = v.sound if (istable(sound)) then local gender = speaker:GetCharacter():GetGender() if gender and gender != "" then if gender == "male" then sound = v.sound[1] else sound = v.sound[2] end else sound = v.sound[1] end end if sound then if (delay == 0) then speaker:EmitSound(sound, volume) else timer.Simple(delay, function() speaker:EmitSound(sound, volume) end) end if (v.global and !globalBlacklist[chatType]) then if (delay == 0) then for _, v1 in ipairs(receivers) do if (v1 != speaker) then netstream.Start(v1, "PlaySound", sound) end end else timer.Simple(delay, function() for _, v1 in ipairs(receivers) do if (v1 != speaker) then netstream.Start(v1, "PlaySound", sound) end end end) end end delay = delay + SoundDuration(sound) + 0.1 end end end str = string.Trim(str) str = str:utf8sub(1, 1):utf8upper() .. str:utf8sub(2) if (!validEnds[str:utf8sub(-1)]) then str = str .. "." end if (speaker:HasActiveCombineMask() and !speaker:IsDispatch()) then return string.format("<:: %s ::>", str) else return str end end end function Schema:CanPlayerJoinClass(client, class, info) if (client:IsRestricted()) then client:Notify("Vous ne pouvez pas changer de classe quand vous êtes attachés !") return false end end function Schema:PlayerSpawnObject(client) if (client:IsRestricted()) then return false end end function Schema:PlayerSpray(client) return true end function Schema:ShouldCalculatePlayerNeeds(client, character) local factionTable = ix.faction.Get(client:Team()) if (factionTable.noNeeds) then return false end end netstream.Hook("ViewObjectivesUpdate", function(client, text) if (client:GetCharacter() and hook.Run("CanPlayerEditObjectives", client)) then local date = ix.date.Get() local data = { text = text:utf8sub(1, 1000), lastEditPlayer = client:GetCharacter():GetName(), lastEditDate = date } ix.data.Set("combineObjectives", data, false, true) Schema.CombineObjectives = data ix.combineNotify:AddNotification("LOG:// Récupération de la mise à jour du manifeste des objectifs d'Overwatch (RÉVISION " .. date:spanseconds() .. ")") ix.combineNotify:AddObjectiveNotification("OBJECTIF:// " .. data.text) end end) netstream.Hook("SearchDecline", function(client) if (!IsValid(client.ixSearchRequest)) then return end client.ixSearchRequest:NotifyLocalized(hook.Run("GetCharacterName", client, "ic") or client:GetName().." refuse la fouille.") client.ixSearchRequest = nil end) netstream.Hook("SearchTimeout", function(client) if (!IsValid(client.ixSearchRequest)) then return end client.ixSearchRequest:NotifyLocalized(hook.Run("GetCharacterName", client, "ic") or client:GetName().." n'a pas répondu à la demande.") client.ixSearchRequest = nil end) netstream.Hook("SearchAllow", function(client) if (!IsValid(client.ixSearchRequest)) then return end Schema:SearchPlayer(client.ixSearchRequest, client) client.ixSearchRequest.ixLastSearchRequest = nil client.ixSearchRequest = nil end) netstream.Hook("ixSetToolMaxDurability", function(client, itemID, amount) amount = math.max(amount, 1) local item = ix.item.instances[itemID] item:SetData("maxDurability", amount) if (item:GetDurability() > amount) then item:SetData("durability", amount) end end) netstream.Hook("ixSetToolDurability", function(client, itemID, amount) local item = ix.item.instances[itemID] amount = math.Clamp(amount, 1, item:GetMaxDurability()) item:SetData("durability", amount) end) -- This is a TERRIBLE way of doing this, but it works without editing helix. -- Adds an option to make certain configs silent. net.Receive("ixConfigSet", function(length, client) local key = net.ReadString() local value = net.ReadType() if (CAMI.PlayerHasAccess(client, "Helix - Manage Config", nil) and type(ix.config.stored[key].default) == type(value)) then ix.config.Set(key, value) if (ix.util.IsColor(value)) then value = string.format("[%d, %d, %d]", value.r, value.g, value.b) elseif (istable(value)) then local value2 = "[" local count = table.Count(value) local i = 1 for _, v in SortedPairs(value) do value2 = value2 .. v .. (i == count and "]" or ", ") i = i + 1 end value = value2 elseif (isstring(value)) then value = string.format("\"%s\"", tostring(value)) elseif (isbool(value)) then value = string.format("[%s]", tostring(value)) end if (!ix.config.stored[key].data.silent and !ix.config.Get("silentConfigs")) then -- Don't notify everyone. ix.util.NotifyLocalized("cfgSet", nil, client:Name(), key, tostring(value)) else for _, v in ipairs(player.GetAll()) do if (v:IsAdmin()) then v:NotifyLocalized("cfgSet", client:Name(), key, tostring(value)) end end end ix.log.Add(client, "cfgSet", key, value) end end) hook.Remove( "InitPostEntity", "CreateVoiceVGUI")