Volver al blog
Guide10 min de lectura

Sistema de territorios de bandas para FiveM: crea guerras por el control del territorio

Crea un sistema de territorios para bandas en FiveM, con zonas, conquistas, recompensas, control de drogas y scripts para guerras de rol.

Agency Scripts

Fundador y desarrollador principal en Agency Scripts

Diseño de un sistema de territorios

Los sistemas de territorios para bandas son unas de las mecánicas más atractivas que puedes añadir a un servidor de roleplay de FiveM, porque dan a las organizaciones criminales un motivo tangible para competir, cooperar e invertir en el crecimiento de su facción. En esencia, un sistema de territorios divide el mapa en zonas que las bandas pueden reclamar y controlar, lo que otorga beneficios específicos a la banda que las posee dentro de esos límites. Las decisiones de diseño que tomes aquí definirán toda la experiencia de roleplay criminal de tu servidor. Debes tener en cuenta cuántas zonas crear, qué tamaño debe tener cada una, qué beneficios ofrece controlarla, con qué frecuencia se puede disputar y qué ocurre cuando una banda pierde todo su territorio. Si hay muy pocas zonas, solo podrán participar las bandas más grandes; si hay demasiadas, el conflicto se dispersará y los territorios individuales perderán importancia. Un enfoque equilibrado consiste en crear 15-25 zonas en áreas que ya tengan importancia para el roleplay criminal, como puntos de venta de drogas, distritos de almacenes y zonas residenciales de bajos ingresos.

Estructura de datos de los territorios

La capa de datos debe registrar quién posee cada zona, su estado de captura y las ventajas asociadas a cada territorio. Guarda las definiciones de los territorios en un archivo de configuración y los datos de propiedad en la base de datos, para que puedas ajustar la distribución de las zonas sin modificar los datos persistentes. Cada zona necesita un identificador único, coordenadas que definan sus límites, el propietario actual y una marca de tiempo de la última captura. Los límites basados en polígonos te dan un control preciso de las formas de las zonas para que se ajusten de manera natural a las calles y los puntos de referencia, aunque las zonas circulares basadas en un radio son más fáciles de implementar y ofrecen un mejor rendimiento:

Config.Territories = {
    ['grove_street'] = {
        label = 'Grove Street',
        center = vector3(105.5, -1942.5, 20.8),
        radius = 150.0,  -- Simple radius approach
        blip = { sprite = 543, scale = 1.2 },
        perks = { 'drug_selling_boost', 'reduced_police_alert' },
        captureTime = 300,  -- Seconds to capture
        cooldown = 3600,    -- Seconds before re-capture
    },
    ['ballas_territory'] = {
        label = 'Forum Drive',
        center = vector3(78.0, -1812.0, 29.0),
        radius = 120.0,
        blip = { sprite = 543, scale = 1.0 },
        perks = { 'weapon_discount', 'safe_stash' },
        captureTime = 300,
        cooldown = 3600,
    },
}

-- Database table for ownership
--[[
CREATE TABLE IF NOT EXISTS gang_territories (
    zone_id VARCHAR(50) PRIMARY KEY,
    owner_gang VARCHAR(50) DEFAULT NULL,
    captured_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    capture_count INT DEFAULT 0,
    last_war_at TIMESTAMP DEFAULT NULL
);
]]

Plantéate añadir una capture_count columna que registre cuántas veces ha cambiado de manos una zona. Puedes usar este dato para hacer análisis e identificar las zonas demasiado disputadas, lo que indicaría que quizá debas ajustar el tiempo de espera o la dificultad de captura de esas áreas específicas.

Mecánicas de captura

La mecánica de captura es el ciclo de juego que impulsa todo el sistema de territorios. Cuando una banda rival entra en un territorio e inicia un intento de captura, comienza un temporizador que los atacantes deben aguantar hasta que termine, mientras la banda defensora recibe alertas y puede responder. Los sistemas de captura más atractivos exigen que la banda atacante mantenga dentro de la zona a un número mínimo de miembros durante toda la captura, creando puntos de enfrentamiento naturales. Si el número de atacantes cae por debajo del mínimo, el progreso de captura se pausa o empieza a retroceder. Aquí tienes una implementación del servidor de la lógica central de captura:

local activeCaptures = {}

RegisterNetEvent('territory:server:startCapture', function(zoneId)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player then return end

    local gang = Player.PlayerData.gang.name
    if gang == 'none' then return end

    local zone = Config.Territories[zoneId]
    if not zone then return end

    -- Check cooldown
    local territory = MySQL.query.await(
        'SELECT * FROM gang_territories WHERE zone_id = ?', {zoneId}
    )
    if territory and territory[1] then
        local lastWar = territory[1].last_war_at
        if lastWar and (os.time() - lastWar) < zone.cooldown then
            TriggerClientEvent('QBCore:Notify', src, 'Territory on cooldown', 'error')
            return
        end
        if territory[1].owner_gang == gang then
            TriggerClientEvent('QBCore:Notify', src, 'You already own this', 'error')
            return
        end
    end

    -- Check minimum gang members in zone
    local membersInZone = GetGangMembersInZone(gang, zoneId)
    if #membersInZone < Config.MinCaptureMembers then
        TriggerClientEvent('QBCore:Notify', src,
            'Need ' .. Config.MinCaptureMembers .. ' members in zone', 'error')
        return
    end

    activeCaptures[zoneId] = {
        attackingGang = gang,
        startTime = os.time(),
        progress = 0,
    }

    -- Alert defending gang
    local defender = territory and territory[1] and territory[1].owner_gang
    if defender then
        AlertGangMembers(defender, 'Your territory is under attack: ' .. zone.label)
    end

    TriggerClientEvent('territory:client:captureStarted', -1, zoneId, gang)
end)

Ejecuta un hilo del servidor que se active cada pocos segundos para actualizar el progreso de captura y comprobar que se mantiene el número mínimo de atacantes y que no se ha incumplido ningún tiempo de espera. Cuando termine la captura, actualiza la base de datos, notifica a todos los jugadores pertinentes y aplica la nueva propiedad en todo el servidor. Transmite el cambio de territorio a todos los clientes conectados para que actualicen sus blips del mapa en tiempo real.

Blips del mapa e indicadores visuales

Los blips de territorio en el minimapa y en el mapa del menú de pausa son esenciales para mostrar a los jugadores qué bandas controlan cada zona. Cada territorio debe mostrar un blip del color de la banda propietaria; los territorios sin propietario deben aparecer en gris neutro o blanco. Cuando una captura esté en curso, el blip debe parpadear o cambiar a un color de disputa para llamar la atención de los jugadores de todo el servidor. Usa AddBlipForRadius para las zonas de territorio, ya que crea una superposición circular en el mapa que muestra claramente los límites de la zona:

function CreateTerritoryBlip(zoneId, data, ownerGang)
    local zone = Config.Territories[zoneId]
    if not zone then return end

    -- Remove existing blip if any
    if territoryBlips[zoneId] then
        RemoveBlip(territoryBlips[zoneId].radius)
        RemoveBlip(territoryBlips[zoneId].icon)
    end

    -- Radius blip for territory area
    local radiusBlip = AddBlipForRadius(
        zone.center.x, zone.center.y, zone.center.z, zone.radius
    )
    local gangColor = GetGangBlipColor(ownerGang)  -- Returns blip color ID
    SetBlipColour(radiusBlip, gangColor)
    SetBlipAlpha(radiusBlip, 80)

    -- Center icon blip
    local iconBlip = AddBlipForCoord(zone.center.x, zone.center.y, zone.center.z)
    SetBlipSprite(iconBlip, zone.blip.sprite)
    SetBlipScale(iconBlip, zone.blip.scale)
    SetBlipColour(iconBlip, gangColor)
    SetBlipAsShortRange(iconBlip, true)
    BeginTextCommandSetBlipName('STRING')
    AddTextComponentSubstringPlayerName(zone.label .. ' [' .. (ownerGang or 'Unclaimed') .. ']')
    EndTextCommandSetBlipName(iconBlip)

    territoryBlips[zoneId] = { radius = radiusBlip, icon = iconBlip }
end

Además de los blips del mapa, plantéate añadir indicadores visuales dentro del mundo, como humo de colores, objetos de grafiti o banderas de la banda que aparezcan en puntos clave de un territorio cuando se capture. Estas señales ambientales sumergen a los jugadores en la narrativa de la guerra entre bandas y hacen que los límites de los territorios se perciban como algo tangible, incluso cuando el minimapa no está visible. Puedes usar el CreateObject nativo para generar objetos específicos de cada banda en ubicaciones predefinidas de cada zona.

Ventajas y recompensas para las bandas

Las ventajas territoriales motivan a las bandas a luchar por su territorio y defenderlo. Sin recompensas significativas, controlar un territorio se convierte en una novedad que los jugadores prueban una vez y luego ignoran. Las mejores ventajas ofrecen beneficios económicos y estratégicos que aumentan a medida que una banda controla más territorio. Entre las ventajas económicas podrían estar un aumento porcentual de las ganancias por vender drogas dentro de la zona, acceso a vendedores exclusivos del mercado negro, precios reducidos en tiendas vinculadas a la banda o ingresos pasivos que se depositan periódicamente en la cuenta bancaria compartida de la banda. Las ventajas estratégicas podrían incluir tiempos de reaparición más rápidos dentro del territorio, menos alertas policiales por los delitos cometidos en la zona, acceso a escondites secretos para guardar armas y drogas, o la posibilidad de colocar trampas y defensas específicas de la banda. Implementa las ventajas mediante comprobaciones en el servidor que se activen cuando un jugador con la afiliación adecuada realice una acción dentro de un territorio que pertenezca a su banda. Mantén el sistema de ventajas modular para que puedas añadir fácilmente nuevas ventajas o ajustar las existentes según los comentarios de los jugadores, sin tener que reestructurar toda la base de código.

Eventos y programación de guerras territoriales

Los eventos estructurados de guerras territoriales añaden un componente competitivo programado al sistema y evitan las escaramuzas constantes de baja intensidad, que pueden llegar a agotar a los jugadores. En lugar de permitir capturas en cualquier momento, puedes limitar las batallas territoriales a franjas horarias específicas, como los viernes y sábados por la noche, para crear eventos que los jugadores esperen, planifiquen y a los que acudan con toda su plantilla. Otra opción es implementar un sistema de declaración de guerra en el que una banda deba declarar formalmente la guerra a otra mediante una mecánica del juego. Esto inicia un periodo de preparación de 30 minutos antes de que se puedan disputar los territorios. Así, la banda defensora tiene tiempo para reunir a sus miembros y preparar las defensas, lo que da lugar a batallas más grandes y espectaculares. Registra estadísticas de guerra, como asesinatos, muertes, territorios ganados y perdidos, y daño infligido, y luego anuncia los resultados a todo el servidor cuando termine el periodo de guerra. Una clasificación o un historial de guerras que los jugadores puedan consultar añade un componente competitivo que mantiene el interés de las bandas entre los periodos de guerra activa y crea historias que pasan a formar parte del historial del servidor.

Medidas contra exploits

Los sistemas de territorios son un blanco habitual de exploits porque afectan directamente a la economía y a las dinámicas de poder del juego. El exploit más común es la captura zombi: un miembro de una banda inicia sesión durante las horas de poca actividad y captura territorios sin oposición. Evítalo exigiendo una población mínima en el servidor antes de iniciar capturas y enviando notificaciones mediante webhooks de Discord cada vez que comience una captura, para que los defensores puedan responder aunque no estén conectados en ese momento. Otro exploit consiste en cambiar de banda rápidamente para capturar territorios para varios grupos. Aplica un tiempo de espera de al menos 24 horas reales para cambiar de banda y elimina inmediatamente todos los permisos relacionados con territorios al abandonar una banda. Limita la frecuencia de los intentos de captura de cada banda para evitar que inicien capturas repetidamente con el fin de molestar a otros jugadores. En el ámbito técnico, valida todas las interacciones con los territorios en el servidor, nunca confíes en que el cliente informe si un jugador está dentro de una zona y comprueba las posiciones en el servidor usando GetEntityCoords(GetPlayerPed(src)) para verificar la ubicación de los jugadores en cada actualización de la captura. Registra cada intento de captura, éxito y fracaso con marcas de tiempo e identificadores de jugador para que puedas investigar patrones sospechosos y tomar medidas contra quienes exploten el sistema con pruebas claras.

Integración con otros sistemas

Un sistema de territorios alcanza todo su potencial cuando se conecta con otros sistemas de juego de tu servidor. Vincula los territorios con el sistema de venta de drogas para que controlar una zona de venta aumente los precios de venta o reduzca el riesgo de interferencia de los NPC. Conéctalo con el sistema de viviendas para que los territorios de una banda ofrezcan impuestos sobre la propiedad reducidos o casas francas exclusivas. Intégralo con el sistema policial haciendo que los territorios afecten a la prioridad de los avisos: los delitos cometidos en zonas controladas por bandas podrían generar avisos policiales con retraso o menos urgentes, simulando los retos reales de vigilar barrios controlados por bandas. Envía los datos territoriales al teléfono o al sistema de notificaciones para que los líderes de las bandas puedan consultar el estado de los territorios, ver el historial de capturas y coordinar la defensa desde cualquier punto del mapa. Si tu servidor tiene un sistema de progresión o reputación, vincula el control territorial a las ganancias de reputación de las bandas para desbloquear actividades y equipamiento de nivel superior. Cuantos más sistemas tengan en cuenta quién posee cada territorio, más impactante y atractiva será esta mecánica, que pasará de ser un minijuego independiente a convertirse en un pilar central del ecosistema de roleplay criminal de tu servidor.

¿Listo para empezar?

Consigue los scripts en nuestra tienda, o únete al Discord para soporte, novedades y un adelanto de lo que viene.