Cómo Configurar Rate Limits y Ajustes de Tasa por Horario en MU
Aprende a configurar rate limits dinámicos y ajustes automáticos de EXP, drop y tasas por horario en tu servidor MU Online.
Los rate limits y ajustes de tasa por horario son técnicas avanzadas que permiten al administrador del servidor MU Online crear picos de actividad planificados, recompensar a los jugadores en horarios pico y equilibrar automáticamente la economía del servidor. Esta guía cubre la implementación completa usando SQL Server (2008–2019) y el sistema de configuración de GameServer Season 6.
Concepto: Cómo Procesa MU Online las Tasas
MuServer lee las tasas base de dos fuentes principales:
- GameServer/GameServer.ini — define los multiplicadores globales fijos de EXP, Drop y Jewel al iniciar el servidor.
- Base de datos (MuOnline) — algunas tablas como
T_EventConfig,T_RateControl(en builds personalizados) oT_ServerInfopueden sobrescribir esos valores en tiempo de ejecución sin reiniciar el servidor.
La estrategia de este tutorial es mantener el .ini con valores base conservadores y usar SQL Server Agent Jobs (o el Programador de Tareas de Windows) para inyectar multiplicadores dinámicos en la tabla de configuración de la base de datos, que el GameServer lee periódicamente.
Paso 1: Configuración Base en GameServer.ini
Localiza el archivo de configuración principal:
GameServer/GameServer.ini
Define los valores base que se usarán como referencia mínima (fuera del horario de bonus):
[GameServerInfo]
ExpRate=30
DropRate=30
MoneyDropRate=30
JewelDropRate=30
MasterExpRate=15
Paso 2: Crear la Tabla de Control de Tasas en la Base de Datos
Conéctate a SQL Server Management Studio (SSMS) y ejecuta en la base de datos MuOnline:
USE MuOnline;
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'T_RateSchedule' AND type = 'U')
BEGIN
CREATE TABLE T_RateSchedule (
ScheduleID INT IDENTITY(1,1) PRIMARY KEY,
HoraInicio TINYINT NOT NULL, -- 0-23
HoraFin TINYINT NOT NULL, -- 0-23 (inclusivo)
DiaSemana TINYINT NOT NULL, -- 0=Todos, 1=Dom, 2=Lun... 7=Sab
MultExpRate DECIMAL(5,2) NOT NULL DEFAULT 1.00,
MultDropRate DECIMAL(5,2) NOT NULL DEFAULT 1.00,
MultJewelRate DECIMAL(5,2) NOT NULL DEFAULT 1.00,
MultMasterExp DECIMAL(5,2) NOT NULL DEFAULT 1.00,
Descripcion VARCHAR(100) NULL,
Activo BIT NOT NULL DEFAULT 1
);
END
GO
Inserta las ventanas de horario de bonus deseadas:
-- Bonus de fin de semana (Sáb y Dom, todo el día) - EXP y Drop duplicados
INSERT INTO T_RateSchedule (HoraInicio, HoraFin, DiaSemana, MultExpRate, MultDropRate, MultJewelRate, MultMasterExp, Descripcion)
VALUES (0, 23, 1, 2.00, 1.50, 1.50, 2.00, 'Bonus Domingo Completo');
INSERT INTO T_RateSchedule (HoraInicio, HoraFin, DiaSemana, MultExpRate, MultDropRate, MultJewelRate, MultMasterExp, Descripcion)
VALUES (0, 23, 7, 2.00, 1.50, 1.50, 2.00, 'Bonus Sábado Completo');
-- Horario pico (todos los días, 20h-23h) - +50% EXP
INSERT INTO T_RateSchedule (HoraInicio, HoraFin, DiaSemana, MultExpRate, MultDropRate, MultJewelRate, MultMasterExp, Descripcion)
VALUES (20, 23, 0, 1.50, 1.00, 1.00, 1.50, 'Happy Hour Nocturno');
-- Madrugada (todos los días, 00h-08h) - tasas reducidas
INSERT INTO T_RateSchedule (HoraInicio, HoraFin, DiaSemana, MultExpRate, MultDropRate, MultJewelRate, MultMasterExp, Descripcion)
VALUES (0, 8, 0, 0.80, 0.80, 0.80, 0.80, 'Tasa Reducida Madrugada');
GO
Paso 3: Crear la Tabla de Estado Actual de Tasas
Esta tabla es leída por el GameServer (o un panel web) para mostrar las tasas vigentes:
USE MuOnline;
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE name = 'T_RateActual' AND type = 'U')
BEGIN
CREATE TABLE T_RateActual (
ID INT PRIMARY KEY DEFAULT 1,
ExpRateActual INT NOT NULL DEFAULT 30,
DropRateActual INT NOT NULL DEFAULT 30,
JewelRateActual INT NOT NULL DEFAULT 30,
MasterExpActual INT NOT NULL DEFAULT 15,
UltimaActualizacion DATETIME NOT NULL DEFAULT GETDATE(),
FuenteAplicada VARCHAR(100) NULL
);
-- Registro único (fila de estado global)
INSERT INTO T_RateActual (ID, ExpRateActual, DropRateActual, JewelRateActual, MasterExpActual)
VALUES (1, 30, 30, 30, 15);
END
GO
Paso 4: Stored Procedure de Aplicación de Tasa
USE MuOnline;
GO
CREATE OR ALTER PROCEDURE sp_AplicarTasaHoraria
AS
BEGIN
SET NOCOUNT ON;
DECLARE @HoraActual TINYINT = DATEPART(HOUR, GETDATE());
DECLARE @DiaActual TINYINT = DATEPART(WEEKDAY, GETDATE()); -- 1=Dom, 7=Sab
-- Tasas base (coinciden con las constantes del GameServer.ini)
DECLARE @BaseExp INT = 30;
DECLARE @BaseDrop INT = 30;
DECLARE @BaseJewel INT = 30;
DECLARE @BaseMaster INT = 15;
-- Multiplicadores calculados (mayor especificidad = mayor prioridad)
DECLARE @MultExp DECIMAL(5,2) = 1.00;
DECLARE @MultDrop DECIMAL(5,2) = 1.00;
DECLARE @MultJewel DECIMAL(5,2) = 1.00;
DECLARE @MultMaster DECIMAL(5,2) = 1.00;
DECLARE @Fuente VARCHAR(100) = 'Predeterminado';
-- Selecciona la regla activa más específica para el momento actual
-- DiaSemana=0 es comodín; las reglas específicas por día tienen prioridad
SELECT TOP 1
@MultExp = MultExpRate,
@MultDrop = MultDropRate,
@MultJewel = MultJewelRate,
@MultMaster = MultMasterExp,
@Fuente = Descripcion
FROM T_RateSchedule
WHERE Activo = 1
AND @HoraActual >= HoraInicio
AND @HoraActual <= HoraFin
AND (DiaSemana = @DiaActual OR DiaSemana = 0)
ORDER BY
CASE WHEN DiaSemana = @DiaActual THEN 0 ELSE 1 END ASC, -- Día específico primero
HoraFin - HoraInicio ASC; -- Ventana más pequeña = más específico
-- Actualiza T_RateActual con los valores calculados
UPDATE T_RateActual
SET
ExpRateActual = CAST(@BaseExp * @MultExp AS INT),
DropRateActual = CAST(@BaseDrop * @MultDrop AS INT),
JewelRateActual = CAST(@BaseJewel * @MultJewel AS INT),
MasterExpActual = CAST(@BaseMaster * @MultMaster AS INT),
UltimaActualizacion = GETDATE(),
FuenteAplicada = @Fuente
WHERE ID = 1;
END;
GO
Prueba el procedimiento manualmente:
EXEC sp_AplicarTasaHoraria;
SELECT * FROM T_RateActual;
Paso 5: Programar Ejecución Automática vía SQL Server Agent
En SSMS, navega a: SQL Server Agent → Jobs → New Job
O ejecuta vía T-SQL:
USE msdb;
GO
EXEC sp_add_job
@job_name = N'MU_ActualizarTasasHorarias';
EXEC sp_add_jobstep
@job_name = N'MU_ActualizarTasasHorarias',
@step_name = N'Ejecutar sp_AplicarTasaHoraria',
@command = N'EXEC MuOnline.dbo.sp_AplicarTasaHoraria',
@database_name = N'MuOnline';
-- Ejecuta cada 15 minutos
EXEC sp_add_schedule
@schedule_name = N'Cada_15min',
@freq_type = 4, -- Diario
@freq_interval = 1,
@freq_subday_type = 4, -- Minutos
@freq_subday_interval = 15;
EXEC sp_attach_schedule
@job_name = N'MU_ActualizarTasasHorarias',
@schedule_name = N'Cada_15min';
EXEC sp_add_jobserver
@job_name = N'MU_ActualizarTasasHorarias';
GO
actualizar_tasas.bat en C:\MuServer\Scripts\ con el contenido: sqlcmd -S .\SQLEXPRESS -d MuOnline -E -Q "EXEC dbo.sp_AplicarTasaHoraria" y prográmalo en el Programador de Tareas de Windows para ejecutarse cada 15 minutos.Paso 6: Integrar con el GameServer (Rate Limit en Tiempo Real)
Para que el GameServer aplique las tasas de la base de datos sin reiniciar, algunos builds de S6 soportan comandos GM vía socket. Usa el comando de consola del GameServer:
/setexp [valor]
/setdrop [valor]
Automatiza mediante un script batch que lee T_RateActual y envía los comandos:
@echo off
REM C:\MuServer\Scripts\sync_rates.bat
FOR /F "tokens=1" %%A IN ('sqlcmd -S .\MSSQLSERVER -d MuOnline -E -h-1 -Q "SET NOCOUNT ON; SELECT ExpRateActual FROM T_RateActual WHERE ID=1"') DO SET EXP=%%A
FOR /F "tokens=1" %%A IN ('sqlcmd -S .\MSSQLSERVER -d MuOnline -E -h-1 -Q "SET NOCOUNT ON; SELECT DropRateActual FROM T_RateActual WHERE ID=1"') DO SET DROP=%%A
echo Tasa EXP actual: %EXP%
echo Tasa DROP actual: %DROP%
REM Enviar a la consola del GameServer via named pipe o herramienta admin
REM (la implementación varía por build - consulta la documentación de tu MuServer)
Paso 7: Rate Limiting de Conexiones (ConnectServer)
Además de las tasas de EXP/Drop, limita el número de conexiones simultáneas en:
ConnectServer/ConnectServer.ini
[ServerInfo]
MaxConnections=500
MaxConnectionsPerIP=3
ConnectionTimeout=30
LoginRateLimit=5
; LoginRateLimit = máximo de intentos de login por IP en 60 segundos
Para el rate limiting de paquetes sospechosos, edita:
GameServer/GameServer.ini
[AntiHack]
PacketFloodLimit=100
; Máximo de paquetes por segundo por conexión antes de desconectar
PacketFloodAction=1
; 0=Solo log, 1=Kick, 2=Ban temporal
BanDuration=30
; Duración del ban temporal en minutos
Verificación y Solución de Problemas
Verificar la tasa actualmente aplicada:
SELECT
ExpRateActual,
DropRateActual,
JewelRateActual,
MasterExpActual,
UltimaActualizacion,
FuenteAplicada
FROM MuOnline.dbo.T_RateActual
WHERE ID = 1;
Verificar el historial de ejecuciones del Job:
SELECT
j.name AS JobName,
h.run_date,
h.run_time,
h.run_status, -- 1=Éxito, 0=Error
h.message
FROM msdb.dbo.sysjobhistory h
JOIN msdb.dbo.sysjobs j ON h.job_id = j.job_id
WHERE j.name = 'MU_ActualizarTasasHorarias'
ORDER BY h.run_date DESC, h.run_time DESC;
T_RateSchedule antes de modificar las reglas de horario. Una configuración incorrecta puede aplicar tasas cero (MultExpRate=0), impidiendo la progresión de todos los jugadores del servidor.Resetear a tasas predeterminadas en emergencia:
UPDATE MuOnline.dbo.T_RateActual
SET ExpRateActual=30, DropRateActual=30, JewelRateActual=30, MasterExpActual=15,
FuenteAplicada='Reset Manual de Emergencia', UltimaActualizacion=GETDATE()
WHERE ID=1;
Perguntas frequentes
¿Puedo aplicar tasas diferentes para VIP y no-VIP en el mismo horario?
Sí. Utiliza la tabla T_UserProperty o T_AccountCharacter para filtrar por cuenta VIP. Crea un stored procedure que verifique el campo VipLevel antes de aplicar el multiplicador, ej: IF @VipLevel >= 1 SET @ExpMult = @ExpMult * 1.5.
El SQL Agent está deshabilitado en SQL Server Express, ¿cómo programarlo?
SQL Server Express no incluye SQL Agent. Usa el Programador de Tareas de Windows para ejecutar un script .bat que llame a SQLCMD, ej: sqlcmd -S localhost -d MuOnline -Q \"EXEC sp_AplicarTasaHoraria\" -E cada 15-30 minutos.
¿Cómo evitar conflictos entre el rate limit del GameServer.ini y las tasas de la base de datos?
Los valores de GameServer.ini son multiplicadores base. Los stored procedures del banco aplican un segundo multiplicador encima. Mantén el .ini con ExpRate=1 y gestiona todo desde la base de datos para evitar una doble multiplicación accidental.
¿Es posible configurar tasas por mapa específico además del horario?
Sí. La tabla T_MapConfig (en algunos builds de S6) o la lógica personalizada en el stored procedure puede verificar el MapNumber y aplicar tasas diferentes. Combina con DATEPART(HOUR, GETDATE()) para tasas por mapa Y horario simultáneamente.