Volver al blog
Guide11 min de lectura

Sistema de mascotas y compañeros para FiveM: crea compañeros leales con scripts

Añade mascotas y compañeros a tu servidor de FiveM. IA que te sigue, alimentación, tiendas, modelos personalizados y scripts para QBCore y ESX.

Agency Scripts

Fundador y desarrollador principal en Agency Scripts

Las mascotas como compañeras de roleplay

Las mascotas aportan una dimensión emocional única a los servidores de roleplay que ningún otro sistema puede ofrecer. Un jugador que recorre la ciudad con su perro caminando a su lado aporta una personalidad visual que enriquece cada interacción. Las mascotas convierten actividades cotidianas, como ir a la tienda, en momentos inmersivos. También generan temas de conversación espontáneos cuando otros jugadores ven a tu pastor alemán o preguntan por tu gato. Más allá del aspecto social, las mascotas pueden tener funciones prácticas, como perros guardianes que alertan a sus dueños de intrusos, unidades K-9 de policía que ayudan en las búsquedas, animales de apoyo emocional en el roleplay hospitalario o compañeros de caza que ayudan a rastrear presas. Para crear un sistema de mascotas, hay que gestionar la creación y eliminación de peds, el comportamiento de seguimiento de la IA, la integración de animaciones, la simulación de necesidades como el hambre y la felicidad, la persistencia entre sesiones y los comandos de interacción que permiten al dueño controlar a su compañero con gestos naturales y comandos de voz.

Modelos de animales y configuración disponibles

GTA V incluye varios modelos de peds de animales que funcionan bien como compañeros. Los perros son los más versátiles, con modelos como a_c_shepherd para los pastores alemanes, a_c_husky para los huskies, a_c_poodle para los caniches, a_c_rottweiler para los rottweilers, a_c_retriever para los retrievers y a_c_chop para el icónico modelo Chop. Para los gatos, usa a_c_cat_01. Si quieres opciones exóticas, hay conejos con a_c_rabbit_01 e incluso aves con a_c_crow. Cada tipo de mascota debería tener distintos parámetros de comportamiento configurados en un archivo compartido. Los perros siguen de cerca a sus dueños y pueden correr junto a vehículos a velocidades moderadas. Los gatos son más independientes y, de vez en cuando, se alejan un poco antes de regresar. Las aves pueden posarse en el hombro del jugador mediante la vinculación de entidades. Define para cada tipo de mascota la distancia de seguimiento, el multiplicador de velocidad de movimiento, las animaciones de inactividad y de interacción, y las habilidades especiales para crear personalidades distintas para cada especie.

-- shared/config.lua
Config = {}

Config.PetTypes = {
    shepherd = {
        model       = 'a_c_shepherd',
        label       = 'German Shepherd',
        price       = 5000,
        followDist  = 2.5,
        runDist     = 8.0,
        maxSpeed    = 7.0,
        category    = 'dog',
        abilities   = {'guard', 'fetch', 'search'},
        idleAnims   = {'sit', 'lie_down', 'sniff'},
    },
    husky = {
        model       = 'a_c_husky',
        label       = 'Husky',
        price       = 6000,
        followDist  = 3.0,
        runDist     = 10.0,
        maxSpeed    = 8.0,
        category    = 'dog',
        abilities   = {'fetch', 'howl'},
        idleAnims   = {'sit', 'lie_down', 'play'},
    },
    cat = {
        model       = 'a_c_cat_01',
        label       = 'Cat',
        price       = 2000,
        followDist  = 4.0,
        runDist     = 6.0,
        maxSpeed    = 5.0,
        category    = 'cat',
        abilities   = {'purr', 'hunt_rodent'},
        idleAnims   = {'sit', 'groom', 'sleep'},
    },
    poodle = {
        model       = 'a_c_poodle',
        label       = 'Poodle',
        price       = 4000,
        followDist  = 2.0,
        runDist     = 6.0,
        maxSpeed    = 5.5,
        category    = 'dog',
        abilities   = {'fetch', 'trick'},
        idleAnims   = {'sit', 'beg', 'spin'},
    },
    rottweiler = {
        model       = 'a_c_rottweiler',
        label       = 'Rottweiler',
        price       = 7000,
        followDist  = 2.0,
        runDist     = 8.0,
        maxSpeed    = 7.5,
        category    = 'dog',
        abilities   = {'guard', 'attack', 'intimidate'},
        idleAnims   = {'sit', 'lie_down', 'bark'},
    },
}

Creación y comportamiento de seguimiento

El núcleo de cualquier sistema de mascotas es la IA de seguimiento, que hace que el animal siga a su dueño de forma natural. Cuando un jugador saque a su mascota, crea el ped en su posición con CreatePed y el modelo correspondiente. Configura el ped como no persistente con SetEntityAsMissionEntity y haz que sea amistoso con el dueño mediante grupos de relaciones. El comportamiento de seguimiento usa un ciclo del lado del cliente que calcula constantemente la distancia entre la mascota y el dueño. Cuando la distancia supera el umbral de seguimiento, ordena a la mascota correr hacia una posición un poco detrás y a un lado del dueño con TaskFollowToOffsetOfEntity. Esta función nativa gestiona automáticamente la búsqueda de rutas, para que la mascota rodee obstáculos, camine por las aceras y evite el tráfico. Cuando el dueño se detiene y la mascota alcanza la distancia de seguimiento, reproduce una animación de inactividad, como sentarse o tumbarse. Si el dueño se sube a un vehículo y se aleja, teletransporta a la mascota dentro del vehículo si es de un tipo adecuado. De lo contrario, elimina a la mascota y vuelve a crearla cuando el dueño salga del vehículo, para evitar que se pierda al otro lado del mapa.

-- client/pet_behavior.lua
local activePet = nil
local petData   = nil

function SpawnPet(petType, name)
    if activePet then DespawnPet() end

    local config = Config.PetTypes[petType]
    if not config then return end

    local ped = PlayerPedId()
    local coords = GetOffsetFromEntityInWorldCoords(ped, 1.5, 1.5, 0.0)

    RequestModel(config.model)
    while not HasModelLoaded(config.model) do Wait(10) end

    activePet = CreatePed(28, config.model,
        coords.x, coords.y, coords.z, 0.0, true, false)

    SetEntityAsMissionEntity(activePet, true, true)
    SetBlockingOfNonTemporaryEvents(activePet, true)
    SetPedCanBeTargetted(activePet, false)
    SetPedCanRagdoll(activePet, false)

    -- Set relationship so pet doesn't attack owner
    local playerGroup = GetHashKey('PLAYER')
    local petGroup = GetHashKey('PET_COMPANION')
    AddRelationshipGroup('PET_COMPANION')
    SetPedRelationshipGroupHash(activePet, petGroup)
    SetRelationshipBetweenGroups(0, petGroup, playerGroup)
    SetRelationshipBetweenGroups(0, playerGroup, petGroup)

    petData = {type = petType, name = name, config = config}

    -- Start follow loop
    CreateThread(PetFollowLoop)
end

function PetFollowLoop()
    while activePet and DoesEntityExist(activePet) do
        local ped = PlayerPedId()
        local petCoords = GetEntityCoords(activePet)
        local ownerCoords = GetEntityCoords(ped)
        local dist = #(petCoords - ownerCoords)

        if dist > 50.0 then
            -- Teleport if too far
            SetEntityCoords(activePet,
                ownerCoords.x, ownerCoords.y, ownerCoords.z)
        elseif dist > petData.config.runDist then
            -- Run to owner
            TaskFollowToOffsetOfEntity(activePet, ped,
                0.0, -1.5, 0.0, petData.config.maxSpeed,
                -1, 1.0, true)
        elseif dist > petData.config.followDist then
            -- Walk to owner
            TaskFollowToOffsetOfEntity(activePet, ped,
                0.0, -1.5, 0.0, 2.0, -1, 1.0, true)
        else
            -- Idle nearby
            if not IsEntityPlayingAnim(activePet, 'creatures@dog@amb@', 'sit_enter', 3) then
                if math.random() > 0.95 then
                    PlayIdleAnimation()
                end
            end
        end

        Wait(500)
    end
end

Necesidades de la mascota y sistema de vínculo

Un sistema de necesidades hace que tener una mascota implique una responsabilidad continua y aporta profundidad. Lleva un registro del hambre, la felicidad y la salud con valores entre 0 y 100 que disminuyan con el paso del tiempo real. El hambre disminuye 1 punto cada 5 minutos de tiempo real mientras la mascota esté creada. La felicidad disminuye más despacio, 1 punto cada 10 minutos, pero aumenta significativamente cuando el dueño interactúa con la mascota acariciándola, jugando a buscar la pelota o dándole premios. La salud se mantiene en 100, a menos que el hambre baje de 20, momento en que empieza a disminuir. Cuando el hambre llega a cero, la mascota se vuelve apática, se mueve más despacio y muestra animaciones tristes. Cuando la salud baja demasiado, la mascota necesita atención veterinaria para recuperarse. Los jugadores alimentan a sus mascotas usando objetos de comida de su inventario sobre la entidad de la mascota. Cada tipo de comida restaura una cantidad distinta de hambre: la comida básica para mascotas restaura 30 puntos, la comida prémium restaura 60 y los premios restauran 10, pero aumentan la felicidad en 15. El nivel de vínculo registra la relación acumulada entre el dueño y su mascota: aumenta con las interacciones positivas y disminuye cuando se descuida a la mascota. Los niveles de vínculo más altos desbloquean interacciones especiales y mejoran la respuesta de la mascota a los comandos.

-- server/pet_needs.lua
local petStates = {}

function InitPetState(ownerId, petId)
    petStates[ownerId] = {
        petId     = petId,
        hunger    = 100,
        happiness = 80,
        health    = 100,
        bond      = 0,
        lastFed   = os.time(),
        lastPet   = os.time(),
    }
end

-- Decay loop runs every 60 seconds
CreateThread(function()
    while true do
        Wait(60000)
        local now = os.time()
        for ownerId, state in pairs(petStates) do
            -- Hunger decay: 1 point per 5 minutes
            local minutesSinceFed = (now - state.lastFed) / 60
            state.hunger = math.max(0,
                100 - math.floor(minutesSinceFed / 5))

            -- Happiness decay
            local minutesSincePet = (now - state.lastPet) / 60
            state.happiness = math.max(0,
                math.min(100, state.happiness -
                    math.floor(minutesSincePet / 10)))

            -- Health decays when starving
            if state.hunger < 20 then
                state.health = math.max(0,
                    state.health - 1)
            end

            -- Sync to client
            local player = GetPlayerFromIdentifier(ownerId)
            if player then
                TriggerClientEvent('pet:syncState', player, state)
            end
        end
    end
end)

RegisterNetEvent('pet:feed', function(foodItem)
    local src = source
    local id = GetPlayerIdentifier(src, 0)
    local state = petStates[id]
    if not state then return end

    local foodValues = {
        petfood        = {hunger = 30, happiness = 5},
        premium_food   = {hunger = 60, happiness = 10},
        pet_treat      = {hunger = 10, happiness = 15},
    }

    local food = foodValues[foodItem]
    if not food then return end

    -- Remove item from inventory
    local removed = exports['ox_inventory']:RemoveItem(src, foodItem, 1)
    if not removed then return end

    state.hunger = math.min(100, state.hunger + food.hunger)
    state.happiness = math.min(100, state.happiness + food.happiness)
    state.lastFed = os.time()
    state.bond = state.bond + 1

    TriggerClientEvent('pet:syncState', src, state)
    TriggerClientEvent('pet:feedAnimation', src)
end)

Comandos de interacción y animaciones

Ofrece a los jugadores una amplia variedad de comandos para interactuar con sus mascotas. Un menú radial o un sistema de comandos debería incluir opciones como sentarse, quedarse quieta, seguir, venir, tumbarse, dar la pata, buscar y ladrar. Cada comando activa una animación correspondiente en el ped de la mascota mediante los diccionarios de animaciones de criaturas incluidos en GTA V. El comando para sentarse usa animaciones de creatures@dog@amb@ con los clips sit_enter y sit_loop. Para tumbarse se usan animaciones ambientales similares. Para jugar a buscar, crea un objeto de pelota pequeño, lánzalo siguiendo una trayectoria parabólica y ordena a la mascota correr hasta el lugar donde caerá la pelota, recogerla mediante una vinculación y volver con el dueño. El comando para ladrar activa un sonido de ladrido mediante PlayPedAmbientSpeechNative. Para acariciarla, reproduce una animación de arrodillarse en el ped del jugador y, al mismo tiempo, una animación de la mascota moviendo la cola con alegría. Estas interacciones no son solo cosméticas: cada una aumenta las estadísticas de felicidad y vínculo, y recompensa a los jugadores que interactúan activamente con su compañera en lugar de tratarla como una simple seguidora.

Persistencia e integración con la tienda de mascotas

Las mascotas deben persistir entre sesiones del servidor para que los jugadores no pierdan a sus compañeras cada vez que se reinicie el servidor. Guarda en la base de datos los datos de la mascota, incluidos el identificador del dueño, el tipo de mascota, el nombre personalizado, los valores actuales de necesidades, el nivel de vínculo y los trucos o habilidades desbloqueados. Cuando el dueño inicie sesión, consulta los datos de su mascota y ofrece la opción de sacarla mediante un comando, o hazlo automáticamente si la tenía activa al desconectarse. Integra la adquisición de mascotas mediante una tienda dentro del juego ubicada en un lugar lógico del mapa. La NUI de la tienda muestra los tipos de mascotas disponibles, con sus modelos en una zona de vista previa, precios y descripciones. Tras la compra, el jugador le pone nombre a su nueva mascota y esta aparece a su lado. Considera añadir un centro de adopción como alternativa, con precios más bajos y tipos de mascotas aleatorios, para aportar un enfoque benéfico al roleplay. En las economías del servidor, las mascotas también pueden tener gastos periódicos, como visitas al veterinario para recuperar la salud, sesiones de peluquería para obtener bonificaciones de apariencia y sesiones de adiestramiento para desbloquear nuevas animaciones de comandos, lo que crea un coste realista por tener mascotas que se integra con tu sistema económico general.

-- SQL schema
CREATE TABLE IF NOT EXISTS pets (
    id          INT AUTO_INCREMENT PRIMARY KEY,
    owner_id    VARCHAR(64) NOT NULL,
    char_slot   INT DEFAULT 1,
    pet_type    VARCHAR(32) NOT NULL,
    pet_name    VARCHAR(64) NOT NULL,
    hunger      INT DEFAULT 100,
    happiness   INT DEFAULT 80,
    health      INT DEFAULT 100,
    bond        INT DEFAULT 0,
    tricks      JSON DEFAULT '[]',
    is_active   TINYINT DEFAULT 0,
    created_at  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at  TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_owner (owner_id, char_slot)
);

-- server/persistence.lua
function SavePet(ownerId, charSlot, state)
    MySQL.update([[
        UPDATE pets SET
            hunger = ?, happiness = ?, health = ?,
            bond = ?, is_active = 1, updated_at = NOW()
        WHERE owner_id = ? AND char_slot = ?
    ]], {
        state.hunger, state.happiness, state.health,
        state.bond, ownerId, charSlot
    })
end

function LoadPet(ownerId, charSlot)
    return MySQL.single.await([[
        SELECT * FROM pets
        WHERE owner_id = ? AND char_slot = ?
        AND is_active = 1
    ]], {ownerId, charSlot})
end

Integración policial K-9 y funciones especiales

Para el roleplay de las fuerzas del orden, amplía el sistema de mascotas con una integración completa de unidades K-9. Los perros policía tienen habilidades especiales que no están disponibles para las mascotas civiles. El comando de búsqueda hace que el perro K-9 olfatee vehículos o edificios cercanos y alerte sobre objetos de contrabando configurables ladrando y sentándose junto a la fuente. Puedes implementarlo comprobando los inventarios de los jugadores cercanos o los maleteros de los vehículos en busca de objetos marcados cuando se use el comando de búsqueda. El comando de rastreo hace que el perro K-9 siga un rastro de olor. Puedes implementarlo creando un rastro de posiciones de un sospechoso que huye y ordenando al perro que lo siga. El comando de ataque hace que el perro K-9 corra hacia un objetivo y reproduzca una animación de ataque, lo que ofrece a los agentes una opción no letal para detener sospechosos. Limita estas habilidades a los jugadores con el trabajo de policía y la certificación de adiestrador K-9. El perro K-9 debería llevar un chaleco policial mediante variaciones de componentes del ped o accesorios vinculados para distinguirlo visualmente de las mascotas civiles. Esta especialización crea un puesto único y muy codiciado dentro de la jerarquía del departamento de policía.

¿Listo para empezar?

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