-- ============================================================================= -- Creado y Desarrollado por SPTEAM -- CLIENTE: KILLFEED V_GOLD (BLINDADO ANTI-CRASH UP43 / UP44) -- ============================================================================= local MAP_NAMES = require("Scripts\\KillFeed\\KillFeed_MapList") or {} local KF_SYS = { WindowID = 215, PacketName = "KillFeed_Data" } local LocalKeys = { LButton = 1, Shift = 16, Escape = 27, G = 71, F4 = 115 } -- [1] CONFIGURACION CALIBRADA local KF_SETTINGS = { ENABLE_DEBUG = false, -- false para jugadores | true para calibrar con F4 HistoryMaxSave = 200, BgImageID = 50109, Folder = "Custom\\ScriptImages\\KillFeed\\", MaxItems = 5, DisplayTime = 150, FadeStart = 60, AnimTime = 15, SlideDist = 150, Sep_Y = 22, Padding = 4, IconSize = 14, TextOffsetY = 5, BarOffsetY = 10, WinW = 290, WinH = 380, WinOffsetX = 99, WinOffsetY = -77, Header_Y = 73, Header_TextX = 85, Header_SepX = 135, Header_VictX = 155, List_StartY = 119, List_TextX = 57, List_SepX = 105, List_VictX = 120, List_RowHeight = 25, List_InfoOffset = 122, Button = { imgClosed = 50110, imgOpen = 50111 }, Arrows = { imgIzq = 50112, imgDer = 50113, Size = 24, Dist = 55 } } -- [MÉTRICAS POR RESOLUCIÓN] local KF_RDB = { [1360] = { X=850, Y=399, Size=22, BarH=30, WinX=586, WinY=70, WinW=270, WinH=380, IconOffsetY=-5, IconOffsetX=0, CharW_Min=4, CharW_May=6, FineDiscount=2, InfoOffset=130, Gap1=5, Gap2=5, BtnX=193, BtnY=0, BtnW=30, BtnH=18 }, [1024] = { X=636, Y=399, Size=22, BarH=30, WinX=352, WinY=48, WinW=276, WinH=380, IconOffsetY=-5, IconOffsetX=0, CharW_Min=4, CharW_May=5, FineDiscount=2, InfoOffset=132, Gap1=4, Gap2=4, BtnX=209, BtnY=0, BtnW=30, BtnH=18 }, [800] = { X=636, Y=399, Size=24, BarH=36, WinX=370, WinY=60, WinW=270, WinH=380, IconOffsetY=-7, IconOffsetX=-2, CharW_Min=4, CharW_May=6, FineDiscount=2, InfoOffset=122, Gap1=4, Gap2=4, BtnX=226, BtnY=0, BtnW=26, BtnH=20 } } function KF_GetConfigObj() local W = WindowGetWidth() if W >= 1300 then return KF_RDB[1360] elseif W >= 1000 then return KF_RDB[1024] else return KF_RDB[800] end end local KF_MAP_CLASES = { [0]=50101, [16]=50101, [32]=50101, [1]=50102, [17]=50102, [33]=50102, [2]=50103, [18]=50103, [34]=50103, [3]=50104, [19]=50104, [4]=50105, [20]=50105, [5]=50106, [21]=50106, [37]=50106, [6]=50107, [22]=50107 } local KillList = {} local PendingList = {} local QueueTimer = 0 if _G.KillFeed_History == nil then _G.KillFeed_History = {} end local WinState = { Open = false, ScrollIndex = 2, X = 0, Y = 0, Dragging = false, OffX = 0, OffY = 0, ScrollDelay = 0, MouseDown = false, LastRes = 0 } local DBG = { Active = false, Mode = 1, ModesName = { "POSICION VENTANA (X,Y)", "HEADER (X,Y)", "LISTA (X,Y)", "ESPACIO FILAS (H)", "TAMAÑO VENTANA (W,H)", "INFO LISTA (MARGEN DER)", "POSICION BOTON (X,Y)" }, DummyData = {} } function DBG_GenerateDummy() DBG.DummyData = {} DBG.DummyData[1] = { killer = "Destructor", victim = "Vic_Suprem", kImg = 50102, vImg = 50101, mapName = "Swamp of Darkness", time = os.time() } for i = 1, 15 do DBG.DummyData[#DBG.DummyData + 1] = { killer = "SERGIOLIN", victim = "EDITHLINDA", kImg = 50107, vImg = 50106, mapName = "Lorencia", time = os.time() - (i * 50) } end end -- ============================================================================= -- HELPERS SEGUROS Y UTILIDADES -- ============================================================================= local function SafeDisableClick() if DisableClickClient then DisableClickClient() elseif DisableCLick then DisableCLick() end end local function SafeRenderText5(x, y, txt, w, sort) if RenderText5 then RenderText5(x, y, txt or "", w or 0, sort or 1) elseif RenderText3 then RenderText3(x, y, txt or "", w or 0, sort or 1) elseif RenderText then RenderText(x, y, txt or "", w or 0, sort or 1) end end local function SafeRenderText3(x, y, txt, w, sort) if RenderText3 then RenderText3(x, y, txt or "", w or 0, sort or 1) elseif RenderText then RenderText(x, y, txt or "", w or 0, sort or 1) end end local function IsNativeBlockingWindowOpen() if CheckWindowOpen(UIInventory) == 1 or CheckWindowOpen(UICharacter) == 1 or CheckWindowOpen(UIWarehouse) == 1 or CheckWindowOpen(UITrade) == 1 or CheckWindowOpen(UIShop) == 1 or CheckWindowOpen(UIChaosBox) == 1 or CheckWindowOpen(UIStore) == 1 or CheckWindowOpen(UIOtherStore) == 1 or CheckWindowOpen(UISkillTree) == 1 or CheckWindowOpen(UIFullMap) == 1 or CheckWindowOpen(UINPC_Dialog) == 1 or CheckWindowOpen(UIParty) == 1 or CheckWindowOpen(UIQuest) == 1 or CheckWindowOpen(UIGuild) == 1 or CheckWindowOpen(UICashShop) == 1 or CheckWindowOpen(UIOptions) == 1 or CheckWindowOpen(UIMuHelper) == 1 or CheckWindowOpen(UICommandWindow) == 1 or CheckWindowOpen(UIGensInfo) == 1 then return true end return false end function KF_GetScale() local H = WindowGetHeight() if H <= 600 then return 0.85 end if H <= 768 then return 0.82 end return 1.0 end function RecuperarTexto(PacketName, Inicio, Largo) local Txt = "" for i = 0, Largo - 1 do local C = GetBytePacket(PacketName, Inicio + i) if C and C > 0 then Txt = Txt .. string.char(C) end end return Txt end function GetMapName(ID) if MAP_NAMES[ID] then if type(MAP_NAMES[ID]) == "table" then return MAP_NAMES[ID][1] end return MAP_NAMES[ID] end return "Map " .. tostring(ID) end function CheckMapEnabled(ID) if MAP_NAMES[ID] then if type(MAP_NAMES[ID]) == "table" then return MAP_NAMES[ID][2] end return true end return true end function GetTimeAgo(Timestamp) local diff = os.time() - (Timestamp or os.time()) if diff < 5 then return "Ahora" end if diff < 60 then return diff .. "s" end if diff < 3600 then return math.floor(diff / 60) .. "m" end return "+1h" end function IsMouseIn(x, y, w, h) local mx, my = MousePosX(), MousePosY() return (mx >= x and mx <= x + w and my >= y and my <= y + h) end function KF_GetImage(ClassID) return KF_MAP_CLASES[ClassID] or 50101 end function KF_EstimarAnchoTexto(Texto, Cfg, esHeader) Texto = tostring(Texto or "") local L = string.len(Texto) local _, M = string.gsub(Texto, "[A-Z]", "") local _, F = string.gsub(Texto, "[iltfj1I]", "") local m = L - M local B = (m * Cfg.CharW_Min) + (M * Cfg.CharW_May) local D = F * Cfg.FineDiscount local A = B - D if A < 2 then A = 2 end local Final = A if esHeader then Final = Final * 1.25 end return Final end function KF_CalcularCoords(AnchorX, FaceSize, Data, Cfg) local CX = AnchorX local FRX = CX - FaceSize CX = FRX - KF_SETTINGS.Padding local WNV = KF_EstimarAnchoTexto(Data.victim, Cfg) local TVX = CX - WNV CX = TVX - Cfg.Gap2 local IX = CX - KF_SETTINGS.IconSize CX = IX - Cfg.Gap1 local WNK = KF_EstimarAnchoTexto(Data.killer, Cfg) local TKX = CX - WNK CX = TKX - KF_SETTINGS.Padding local FLX = CX - FaceSize return FLX, TKX, IX, TVX, FRX end -- ============================================================================= -- GESTIÓN DE ESTADO DE VENTANA (SIN PISAR OTRAS INTERFACES) -- ============================================================================= function SetKillFeedState(isOpen) WinState.Open = isOpen if isOpen then UICustomInterface = KF_SYS.WindowID WinState.ScrollIndex = 2 local Config = KF_GetConfigObj() local CurrentW = WindowGetWidth() if WinState.LastRes ~= CurrentW or WinState.X == 0 then WinState.X = Config.WinX WinState.Y = Config.WinY WinState.LastRes = CurrentW KF_SETTINGS.WinW = Config.WinW or 270 KF_SETTINGS.WinH = Config.WinH or 380 end if WinState.Y < 10 then WinState.Y = 10 end else WinState.Dragging = false WinState.MouseDown = false if UICustomInterface == KF_SYS.WindowID then UICustomInterface = 0 end end end function KillFeed_Load() LoadBitmap(KF_SETTINGS.Folder .. "BarKill.tga", 50100) LoadBitmap(KF_SETTINGS.Folder .. "Mago.tga", 50101) LoadBitmap(KF_SETTINGS.Folder .. "Bk.tga", 50102) LoadBitmap(KF_SETTINGS.Folder .. "Elf.tga", 50103) LoadBitmap(KF_SETTINGS.Folder .. "Magic.tga", 50104) LoadBitmap(KF_SETTINGS.Folder .. "Dlord.tga", 50105) LoadBitmap(KF_SETTINGS.Folder .. "Summo.tga", 50106) LoadBitmap(KF_SETTINGS.Folder .. "RageFigh.tga", 50107) LoadBitmap(KF_SETTINGS.Folder .. "IconKill.tga", 50108) LoadBitmap(KF_SETTINGS.Folder .. "KillFeedBG.jpg", KF_SETTINGS.BgImageID) LoadBitmap(KF_SETTINGS.Folder .. "BotonKillFeed.tga", KF_SETTINGS.Button.imgClosed) LoadBitmap(KF_SETTINGS.Folder .. "BotonKillFeedB.tga",KF_SETTINGS.Button.imgOpen) LoadBitmap(KF_SETTINGS.Folder .. "IzqScr.tga", KF_SETTINGS.Arrows.imgIzq) LoadBitmap(KF_SETTINGS.Folder .. "DerScr.tga", KF_SETTINGS.Arrows.imgDer) end -- ============================================================================= -- RECEPCIÓN DE PROTOCOLO (LEY #6: CERO CLEARPACKET AQUÍ) -- ============================================================================= local DeduplicationBuffer = {} function KillFeed_Protocol(Packet, PacketName) if Packet == KF_SYS.WindowID and PacketName == KF_SYS.PacketName then local shift = 0 local NumEvents = GetBytePacket(PacketName, 0) if NumEvents == Packet then NumEvents = GetBytePacket(PacketName, 1) shift = 1 end if not NumEvents or NumEvents <= 0 or NumEvents > 20 then return true end local Offset = 1 + shift local now = os.time() -- Limpieza de firmas expiradas una sola vez por paquete for sig, t in pairs(DeduplicationBuffer) do if (now - t) > 10 then DeduplicationBuffer[sig] = nil end end for e = 1, NumEvents do local kClass = GetBytePacket(PacketName, Offset); Offset = Offset + 1 local vClass = GetBytePacket(PacketName, Offset); Offset = Offset + 1 local mapID = GetBytePacket(PacketName, Offset); Offset = Offset + 1 local kName = RecuperarTexto(PacketName, Offset, 10); Offset = Offset + 10 local vName = RecuperarTexto(PacketName, Offset, 10); Offset = Offset + 10 if CheckMapEnabled(mapID) ~= false then local Signature = kName .. ":" .. vName if DeduplicationBuffer[Signature] == nil or (now - DeduplicationBuffer[Signature]) > 3 then DeduplicationBuffer[Signature] = now local DataObj = { killer = kName, victim = vName, kImg = KF_GetImage(kClass), vImg = KF_GetImage(vClass), mapName = GetMapName(mapID), time = now, timer = KF_SETTINGS.DisplayTime, animTimer = KF_SETTINGS.AnimTime } PendingList[#PendingList + 1] = DataObj table.insert(_G.KillFeed_History, 1, DataObj) if #_G.KillFeed_History > KF_SETTINGS.HistoryMaxSave then table.remove(_G.KillFeed_History) end end end end return true end return false end -- ============================================================================= -- RENDERIZADO -- ============================================================================= function KillFeed_DrawHistoryWindow() if not WinState.Open then return end if UICustomInterface ~= KF_SYS.WindowID then UICustomInterface = KF_SYS.WindowID end local s = KF_GetScale() local ConfigObj = KF_GetConfigObj() local W = math.floor(KF_SETTINGS.WinW * s) local H = math.floor(KF_SETTINGS.WinH * s) local X, Y = WinState.X, WinState.Y SetBlend(1); glColor4f(1.0, 1.0, 1.0, 1.0) RenderImage2(KF_SETTINGS.BgImageID, X, Y, W, H, 0.0, 0.0, 1.0, 1.0, 1, 1, 1.0) SetBlend(0); DisableAlphaBlend() local ListToDraw = DBG.Active and DBG.DummyData or _G.KillFeed_History if #ListToDraw == 0 then return end -- HEADER local LastKill = ListToDraw[1] local HX = math.floor(X + (KF_SETTINGS.Header_TextX * s)) local HSepX = math.floor(X + (KF_SETTINGS.Header_SepX * s)) local HVictX= math.floor(X + (KF_SETTINGS.Header_VictX * s)) local HY = math.floor(Y + ((KF_SETTINGS.Header_Y + 3) * s)) SetFontType(1) SetTextBg(0, 0, 0, 0) SetTextColor(100, 180, 100, 255); SafeRenderText5(HX, HY, LastKill.killer, 80, 1) SetTextColor(180, 180, 180, 255); SafeRenderText5(HSepX, HY, ">", 20, 1) SetTextColor(180, 80, 80, 255); SafeRenderText5(HVictX, HY, LastKill.victim, 80, 1) local TimeStr = GetTimeAgo(LastKill.time) SetTextColor(160, 155, 140, 255) SafeRenderText5(HX, math.floor(HY + (16 * s)), LastKill.mapName .. " · " .. TimeStr, 180, 1) -- LISTA local SlotsVisible = 10 if WinState.ScrollIndex < 2 then WinState.ScrollIndex = 2 end local EndIndex = math.min(WinState.ScrollIndex + SlotsVisible - 1, #ListToDraw) local ListY = math.floor(Y + (KF_SETTINGS.List_StartY * s)) local RowH = math.floor(KF_SETTINGS.List_RowHeight * s) local LX = math.floor(X + (KF_SETTINGS.List_TextX * s)) local LSepX = math.floor(X + (KF_SETTINGS.List_SepX * s)) local LVictX = math.floor(X + (KF_SETTINGS.List_VictX * s)) local FinalInfoOffset = ConfigObj.InfoOffset or KF_SETTINGS.List_InfoOffset local RightX = math.floor(X + W - (FinalInfoOffset * s)) SetFontType(0) if #ListToDraw >= 2 then for i = WinState.ScrollIndex, EndIndex do local Data = ListToDraw[i] if Data then SetTextColor(100, 160, 100, 220); SafeRenderText5(LX, ListY, Data.killer, 65, 1) SetTextColor(140, 140, 140, 255); SafeRenderText5(LSepX, ListY, ">", 10, 1) SetTextColor(160, 70, 70, 220); SafeRenderText5(LVictX, ListY, Data.victim, 65, 1) local InfoStr = Data.mapName .. " · " .. GetTimeAgo(Data.time) SetTextColor(130, 130, 130, 180) SafeRenderText5(RightX, ListY, InfoStr, 90, 4) ListY = ListY + RowH end end end -- FLECHAS DE NAVEGACIÓN local ListSize = #ListToDraw local MaxIndex = math.max(2, ListSize - 8) local ArrS = math.floor(KF_SETTINGS.Arrows.Size * s) local ArrY = math.floor(Y + H - (28 * s)) local ArrDist = math.floor(KF_SETTINGS.Arrows.Dist * s) local CenterX = math.floor(X + (W / 2)) SetBlend(1); glColor4f(1.0, 1.0, 1.0, 1.0) if WinState.ScrollIndex > 2 then RenderImage2(KF_SETTINGS.Arrows.imgIzq, CenterX - ArrDist, ArrY, ArrS, ArrS, 0, 0, 1.0, 1.0, 1, 1, 1.0) end if WinState.ScrollIndex < MaxIndex then RenderImage2(KF_SETTINGS.Arrows.imgDer, CenterX + ArrDist - ArrS, ArrY, ArrS, ArrS, 0, 0, 1.0, 1.0, 1, 1, 1.0) end SetBlend(0); DisableAlphaBlend() -- DEBUG PANEL if DBG.Active then SetFontType(0) SetTextBg(0, 0, 0, 200) SetTextColor(0, 255, 255, 255) SafeRenderText5(X, Y - 30, "=== MODO DEBUG ACTIVO (" .. DBG.ModesName[DBG.Mode] .. ") ===", W, 4) local valStr = "" if DBG.Mode == 1 then valStr = "WinX: " .. WinState.X .. " | WinY: " .. WinState.Y elseif DBG.Mode == 2 then valStr = "HeadX: " .. KF_SETTINGS.Header_TextX .. " | HeadY: " .. KF_SETTINGS.Header_Y elseif DBG.Mode == 3 then valStr = "ListX: " .. KF_SETTINGS.List_TextX .. " | ListY: " .. KF_SETTINGS.List_StartY elseif DBG.Mode == 4 then valStr = "RowH: " .. KF_SETTINGS.List_RowHeight elseif DBG.Mode == 5 then valStr = "WinW: " .. KF_SETTINGS.WinW .. " | WinH: " .. KF_SETTINGS.WinH elseif DBG.Mode == 6 then valStr = "Margen: " .. KF_SETTINGS.List_InfoOffset end SetTextColor(255, 255, 0, 255) SafeRenderText5(X, Y + H + 5, valStr, W, 4) SetTextBg(0, 0, 0, 0) end SetTextColor(255, 255, 255, 255) end local function KillFeed_MainRender_Internal() if GetMainScene() ~= 5 then if WinState.Open then SetKillFeedState(false) end return end -- 1. ACTUALIZACIÓN DE TIMERS DE LA COLA (Corre siempre en segundo plano) if #PendingList > 0 then if QueueTimer > 0 then QueueTimer = QueueTimer - 1 else local NextKill = table.remove(PendingList, 1) KillList[#KillList + 1] = NextKill if #KillList > KF_SETTINGS.MaxItems then table.remove(KillList, 1) end QueueTimer = 2 end end if #KillList > 0 then for i = #KillList, 1, -1 do local Data = KillList[i] if Data.animTimer > 0 then Data.animTimer = Data.animTimer - 1 end Data.timer = Data.timer - 1 if Data.timer <= 0 then table.remove(KillList, i) end end end -- 2. SI SE ABRE UNA VENTANA NATIVA O CUSTOM AJENA, CERRAMOS Y NO DIBUJAMOS ENCIMA if IsNativeBlockingWindowOpen() or (UICustomInterface > 0 and UICustomInterface ~= KF_SYS.WindowID) then if WinState.Open then SetKillFeedState(false) end return end local Cfg = KF_GetConfigObj() -- 3. BOTÓN TOGGLE local BtnW, BtnH, BtnX, BtnY = Cfg.BtnW, Cfg.BtnH, Cfg.BtnX, Cfg.BtnY local BtnImg = WinState.Open and KF_SETTINGS.Button.imgOpen or KF_SETTINGS.Button.imgClosed SetBlend(1); glColor4f(1.0, 1.0, 1.0, 1.0) RenderImage2(BtnImg, BtnX, BtnY, BtnW, BtnH, 0, 0, 1.0, 1.0, 1, 1, 1.0) SetBlend(0); DisableAlphaBlend() if DBG.Active and DBG.Mode == 7 then SetFontType(0); SetTextBg(0, 0, 0, 200); SetTextColor(0, 255, 0, 255) SafeRenderText5(BtnX, BtnY + BtnH + 5, "BTN (" .. WindowGetWidth() .. "): " .. BtnX .. "," .. BtnY .. " [" .. BtnW .. "x" .. BtnH .. "]", 100, 1) SetTextBg(0, 0, 0, 0); SetTextColor(255, 255, 255, 255) end -- 4. VENTANA DE HISTORIAL (SI ESTÁ ABIERTA) if WinState.Open then KillFeed_DrawHistoryWindow() if WinState.MouseDown then local s = KF_GetScale() local RealW = math.floor(KF_SETTINGS.WinW * s) local RealH = math.floor(KF_SETTINGS.WinH * s) local ArrS = math.floor(KF_SETTINGS.Arrows.Size * s) local ArrY = math.floor(WinState.Y + RealH - (28 * s)) local ArrDist = math.floor(KF_SETTINGS.Arrows.Dist * s) local CenterX = math.floor(WinState.X + (RealW / 2)) if WinState.ScrollDelay > 0 then WinState.ScrollDelay = WinState.ScrollDelay - 1 else if IsMouseIn(CenterX - ArrDist, ArrY, ArrS, ArrS) then if WinState.ScrollIndex > 2 then WinState.ScrollIndex = WinState.ScrollIndex - 1 end WinState.ScrollDelay = 4 elseif IsMouseIn(CenterX + ArrDist - ArrS, ArrY, ArrS, ArrS) then local ListSize = DBG.Active and #DBG.DummyData or #_G.KillFeed_History local MaxIndex = math.max(2, ListSize - 8) if WinState.ScrollIndex < MaxIndex then WinState.ScrollIndex = WinState.ScrollIndex + 1 end WinState.ScrollDelay = 4 end end else WinState.ScrollDelay = 0 end return -- Si el historial está abierto no dibujamos el HUD flotante end -- 5. HUD FLOTANTE DE MUERTES EN VIVO if #KillList > 0 then local BaseAnchorX, FaceSize, CurrentBarH = Cfg.X, Cfg.Size, Cfg.BarH for i = 1, #KillList do local Data = KillList[i] if Data then local AlphaVal = (Data.timer < KF_SETTINGS.FadeStart) and (Data.timer / KF_SETTINGS.FadeStart) or 1.0 local AnimOffsetX = (Data.animTimer > 0) and (KF_SETTINGS.SlideDist * (Data.animTimer / KF_SETTINGS.AnimTime)) or 0 local AnimatedAnchorX = BaseAnchorX + AnimOffsetX local StackOffset = #KillList - i local DrawY = Cfg.Y - (StackOffset * KF_SETTINGS.Sep_Y) local FaceL_X, _, _, _, FaceR_X = KF_CalcularCoords(AnimatedAnchorX, FaceSize, Data, Cfg) local BarStartX = FaceL_X + (FaceSize / 2) local BarWidth = (FaceR_X + (FaceSize / 2)) - BarStartX local BarY = DrawY + (FaceSize / 2) - (CurrentBarH / 2) + KF_SETTINGS.BarOffsetY SetBlend(1) RenderImage2(50100, BarStartX, BarY, BarWidth, CurrentBarH, 0, 0, 1.0, 1.0, 1, 1, AlphaVal) end end for i = 1, #KillList do local Data = KillList[i] if Data then local AlphaVal = (Data.timer < KF_SETTINGS.FadeStart) and (Data.timer / KF_SETTINGS.FadeStart) or 1.0 local IntAlpha = math.floor(255 * AlphaVal) local AnimOffsetX = (Data.animTimer > 0) and (KF_SETTINGS.SlideDist * (Data.animTimer / KF_SETTINGS.AnimTime)) or 0 local AnimatedAnchorX = BaseAnchorX + AnimOffsetX local StackOffset = #KillList - i local DrawY = Cfg.Y - (StackOffset * KF_SETTINGS.Sep_Y) local FaceL_X, TextK_X, Icon_X, TextV_X, FaceR_X = KF_CalcularCoords(AnimatedAnchorX, FaceSize, Data, Cfg) local BarY = DrawY + (FaceSize / 2) - (CurrentBarH / 2) + KF_SETTINGS.BarOffsetY SetBlend(1) RenderImage2(Data.kImg, FaceL_X, DrawY, FaceSize, FaceSize, 0, 0, 1.0, 1.0, 1, 1, AlphaVal) RenderImage2(Data.vImg, FaceR_X, DrawY, FaceSize, FaceSize, 0, 0, 1.0, 1.0, 1, 1, AlphaVal) local IconDrawX = Icon_X + Cfg.IconOffsetX local IconDrawY = BarY + (CurrentBarH - KF_SETTINGS.IconSize) / 2 + Cfg.IconOffsetY RenderImage2(50108, IconDrawX, IconDrawY, KF_SETTINGS.IconSize, KF_SETTINGS.IconSize, 0, 0, 1.0, 1.0, 1, 1, AlphaVal) SetBlend(0); DisableAlphaBlend() local TextY = BarY + KF_SETTINGS.TextOffsetY SetFontType(1); SetTextBg(0, 0, 0, 0) SetTextColor(255, 180, 0, IntAlpha) SafeRenderText3(math.floor(TextK_X), math.floor(TextY), Data.killer, 100, 1) SetTextColor(255, 50, 50, IntAlpha) SafeRenderText3(math.floor(TextV_X), math.floor(TextY), Data.victim, 100, 1) end end SetTextColor(255, 255, 255, 255) end end function KillFeed_MainRender() local ok = pcall(KillFeed_MainRender_Internal) if not ok then SetTextBg(0, 0, 0, 0) SetTextColor(255, 255, 255, 255) SetBlend(0) DisableAlphaBlend() glColor4f(1.0, 1.0, 1.0, 1.0) end end -- ============================================================================= -- INPUTS -- ============================================================================= function KillFeed_UpdateMouse() if GetMainScene() ~= 5 then if WinState.Open then SetKillFeedState(false) end return end if IsNativeBlockingWindowOpen() or (UICustomInterface > 0 and UICustomInterface ~= KF_SYS.WindowID) then return end if not DBG.Active then local Cfg = KF_GetConfigObj() if IsMouseIn(Cfg.BtnX, Cfg.BtnY, Cfg.BtnW, Cfg.BtnH) then SafeDisableClick() if CheckPressedKey(LocalKeys.LButton) == 1 then SetKillFeedState(not WinState.Open) return end end end if not WinState.Open then return end local s = KF_GetScale() local RealW = math.floor(KF_SETTINGS.WinW * s) local RealH = math.floor(KF_SETTINGS.WinH * s) if IsMouseIn(WinState.X, WinState.Y, RealW, RealH) then SafeDisableClick() end if not DBG.Active then if CheckPressedKey(LocalKeys.LButton) == 1 then WinState.MouseDown = true if IsMouseIn(WinState.X, WinState.Y, RealW, math.floor(50 * s)) then WinState.Dragging = true WinState.OffX = MousePosX() - WinState.X WinState.OffY = MousePosY() - WinState.Y end end if CheckReleasedKey(LocalKeys.LButton) == 1 then WinState.Dragging = false WinState.MouseDown = false end if WinState.Dragging then WinState.X = MousePosX() - WinState.OffX WinState.Y = MousePosY() - WinState.OffY end end end function KillFeed_UpdateKey() if GetMainScene() ~= 5 then if WinState.Open then SetKillFeedState(false) end return end if WinState.Open and CheckPressedKey(LocalKeys.Escape) == 1 then SetKillFeedState(false) SafeDisableClick() end end function KillFeed_Key(Key) if GetMainScene() ~= 5 then return false end if UIChatWindow and CheckWindowOpen(UIChatWindow) == 1 then return false end if Key == LocalKeys.Escape and WinState.Open then SetKillFeedState(false) return true end -- Blindaje: Solo entrar en modo Debug si ENABLE_DEBUG = true if not KF_SETTINGS.ENABLE_DEBUG then return false end if Key == LocalKeys.F4 and WinState.Open then DBG.Active = not DBG.Active if DBG.Active and #DBG.DummyData == 0 then DBG_GenerateDummy() end return true end if DBG.Active then if Key == LocalKeys.G then DBG.Mode = (DBG.Mode % 7) + 1 end local step = (CheckPressedKey(LocalKeys.Shift) == 1) and 5 or 1 local CfgObj = KF_GetConfigObj() if Key == 37 then if DBG.Mode == 1 then WinState.X = WinState.X - step elseif DBG.Mode == 2 then KF_SETTINGS.Header_TextX = KF_SETTINGS.Header_TextX - step elseif DBG.Mode == 3 then KF_SETTINGS.List_TextX = KF_SETTINGS.List_TextX - step elseif DBG.Mode == 5 then KF_SETTINGS.WinW = KF_SETTINGS.WinW - step elseif DBG.Mode == 6 then if CfgObj.InfoOffset then CfgObj.InfoOffset = CfgObj.InfoOffset - step else KF_SETTINGS.List_InfoOffset = KF_SETTINGS.List_InfoOffset - step end elseif DBG.Mode == 7 then CfgObj.BtnX = CfgObj.BtnX - step end elseif Key == 39 then if DBG.Mode == 1 then WinState.X = WinState.X + step elseif DBG.Mode == 2 then KF_SETTINGS.Header_TextX = KF_SETTINGS.Header_TextX + step elseif DBG.Mode == 3 then KF_SETTINGS.List_TextX = KF_SETTINGS.List_TextX + step elseif DBG.Mode == 5 then KF_SETTINGS.WinW = KF_SETTINGS.WinW + step elseif DBG.Mode == 6 then if CfgObj.InfoOffset then CfgObj.InfoOffset = CfgObj.InfoOffset + step else KF_SETTINGS.List_InfoOffset = KF_SETTINGS.List_InfoOffset + step end elseif DBG.Mode == 7 then CfgObj.BtnX = CfgObj.BtnX + step end elseif Key == 38 then if DBG.Mode == 1 then WinState.Y = WinState.Y - step elseif DBG.Mode == 2 then KF_SETTINGS.Header_Y = KF_SETTINGS.Header_Y - step elseif DBG.Mode == 3 then KF_SETTINGS.List_StartY = KF_SETTINGS.List_StartY - step elseif DBG.Mode == 4 then KF_SETTINGS.List_RowHeight = KF_SETTINGS.List_RowHeight - step elseif DBG.Mode == 5 then KF_SETTINGS.WinH = KF_SETTINGS.WinH - step elseif DBG.Mode == 6 then if CfgObj.InfoOffset then CfgObj.InfoOffset = CfgObj.InfoOffset - step else KF_SETTINGS.List_InfoOffset = KF_SETTINGS.List_InfoOffset - step end elseif DBG.Mode == 7 then CfgObj.BtnY = CfgObj.BtnY - step end elseif Key == 40 then if DBG.Mode == 1 then WinState.Y = WinState.Y + step elseif DBG.Mode == 2 then KF_SETTINGS.Header_Y = KF_SETTINGS.Header_Y + step elseif DBG.Mode == 3 then KF_SETTINGS.List_StartY = KF_SETTINGS.List_StartY + step elseif DBG.Mode == 4 then KF_SETTINGS.List_RowHeight = KF_SETTINGS.List_RowHeight + step elseif DBG.Mode == 5 then KF_SETTINGS.WinH = KF_SETTINGS.WinH + step elseif DBG.Mode == 6 then if CfgObj.InfoOffset then CfgObj.InfoOffset = CfgObj.InfoOffset + step else KF_SETTINGS.List_InfoOffset = KF_SETTINGS.List_InfoOffset + step end elseif DBG.Mode == 7 then CfgObj.BtnY = CfgObj.BtnY + step end elseif Key == 104 and DBG.Mode == 7 then CfgObj.BtnH = CfgObj.BtnH + step elseif Key == 98 and DBG.Mode == 7 then CfgObj.BtnH = CfgObj.BtnH - step elseif Key == 102 and DBG.Mode == 7 then CfgObj.BtnW = CfgObj.BtnW + step elseif Key == 100 and DBG.Mode == 7 then CfgObj.BtnW = CfgObj.BtnW - step end return true end return false end function KillFeed_Scroll(Value) if GetMainScene() ~= 5 then if WinState.Open then SetKillFeedState(false) end return end if not WinState.Open then return end local s = KF_GetScale() local RealW = math.floor(KF_SETTINGS.WinW * s) local RealH = math.floor(KF_SETTINGS.WinH * s) if IsMouseIn(WinState.X, WinState.Y, RealW, RealH) then if Value > 0 then if WinState.ScrollIndex > 2 then WinState.ScrollIndex = WinState.ScrollIndex - 1 end else local ListSize = DBG.Active and #DBG.DummyData or #_G.KillFeed_History local MaxIndex = math.max(2, ListSize - 8) if WinState.ScrollIndex < MaxIndex then WinState.ScrollIndex = WinState.ScrollIndex + 1 end end end end if _G.KillFeed_Init == nil then BridgeFunctionAttach('MainLoader', 'KillFeed_Load') BridgeFunctionAttach('MainProcThread', 'KillFeed_MainRender') BridgeFunctionAttach('UpdateMouseEvent', 'KillFeed_UpdateMouse') BridgeFunctionAttach('UpdateKeyEvent', 'KillFeed_UpdateKey') BridgeFunctionAttach('KeyboardEvent', 'KillFeed_Key') BridgeFunctionAttach('ScrollMouseEvent', 'KillFeed_Scroll') if ProtocolFunctions and ProtocolFunctions.ClientProtocol then ProtocolFunctions.ClientProtocol(KillFeed_Protocol) else BridgeFunctionAttach('ClientProtocol', 'KillFeed_Protocol') end _G.KillFeed_Init = true end