How to configure the VIP and benefits system in MU Online
Build a complete VIP system on your MU Online server — a control table, tiers, EXP and drop bonuses, exclusive benefits and website integration.
A well-built VIP system is the backbone of most private MU Online servers. It rewards the players who support the project with recurring bonuses — more experience, more drop, exclusive access — and, at the same time, gives you the predictability to cover the VPS, anti-DDoS protection and development
A well-built VIP system is the backbone of most private MU Online servers. It rewards the players who support the project with recurring bonuses — more experience, more drop, exclusive access — and, at the same time, gives you the predictability to cover the VPS, anti-DDoS protection and development. But a poorly configured VIP has two serious side effects: if the bonuses are excessive, it breaks the balance and drives away non-paying players; if expiration does not work, you hand out eternal benefits by mistake. This guide shows how to build the system from scratch, covering the database, the configuration file, the types of benefit and the website integration.
The examples use the classic MuServer schema (SQL Server, MuOnline database, MEMB_INFO table) and the [VIP] section of the GameServer configuration file. Table, column and parameter names vary by season/emulator — treat every snippet as an example to adapt to your server.
How the VIP system works
A VIP's life cycle goes through four moments:
1. Activation (website, donation or GM command)
│
2. Writes/updates the row in the VIP table
with start and expiration dates
│
3. On login, the GameServer reads the VIP status
and applies the EXP/Drop/Zen multipliers
│
4. Periodic check: if the date has expired,
the status returns to normal and the bonuses vanish
Note that the server does not "push" VIP in real time: it queries the table on login and at a defined interval. This means that almost all the logic lives in two places — the control table and the configuration file — and that is where we begin.
Prerequisites
Before configuring, make sure you have:
- A working MU server (GameServer, ConnectServer and database up). If you have not reached that point yet, follow the guide on how to create a MU Online server first.
- Access to SQL Server with permission to create tables and procedures in the game database.
- Access to the GameServer configuration files (usually in
GameServer/Data/or similar). - A database backup before creating new tables.
- The server website (if you are going to automate the sale/donation of VIP), with a PHP/PDO connection to the database.
- A defined tier plan: how many tiers, which bonuses and for how long.
Step 1 — Create the VIP control table
Some distributions already ship this table. If yours does not, create a dedicated one — it is cleaner than scattering columns across MEMB_INFO:
USE MuOnline;
GO
CREATE TABLE MEMB_VIP (
AccountID VARCHAR(10) NOT NULL, -- login (logical FK to MEMB_INFO)
VipLevel TINYINT NOT NULL DEFAULT 1, -- 1=Bronze, 2=Silver, 3=Gold
StartDate DATETIME NOT NULL DEFAULT GETDATE(),
ExpireDate DATETIME NOT NULL, -- expiration date
Active TINYINT NOT NULL DEFAULT 1, -- 1=active, 0=expired
CONSTRAINT PK_MEMB_VIP PRIMARY KEY (AccountID)
);
GO
-- Index so the GameServer can scan expirations quickly
CREATE INDEX IX_VIP_Expire ON MEMB_VIP (ExpireDate, Active);
GO
Alternative: columns in MEMB_INFO
Distributions that expect VIP to be built in sometimes read straight from the account:
ALTER TABLE MEMB_INFO ADD VipLevel TINYINT DEFAULT 0;
ALTER TABLE MEMB_INFO ADD VipExpire DATETIME NULL;
GO
Check which model your distribution uses before choosing — the GameServer only applies VIP if it reads from the structure it expects.
Step 2 — Activate VIP for an account
To grant or extend VIP, the standard is: if it already exists, extend from the greater of "now" and the current expiration (so no one loses days when renewing); if it does not exist, create it.
-- Grant/extend VIP tier 1 for 30 days to account 'jogador01'
IF EXISTS (SELECT 1 FROM MEMB_VIP WHERE AccountID = 'jogador01')
UPDATE MEMB_VIP
SET ExpireDate = DATEADD(DAY, 30,
CASE WHEN ExpireDate > GETDATE() THEN ExpireDate ELSE GETDATE() END),
VipLevel = 1,
Active = 1
WHERE AccountID = 'jogador01';
ELSE
INSERT INTO MEMB_VIP (AccountID, VipLevel, StartDate, ExpireDate)
VALUES ('jogador01', 1, GETDATE(), DATEADD(DAY, 30, GETDATE()));
GO
Wrapping this in a procedure avoids repetition and makes it easier to call from the website:
CREATE PROCEDURE sp_AtivarVIP
@conta VARCHAR(10),
@nivel TINYINT = 1,
@dias INT = 30
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM MEMB_INFO WHERE memb___id = @conta)
BEGIN RAISERROR('Account does not exist', 16, 1); RETURN; END;
IF EXISTS (SELECT 1 FROM MEMB_VIP WHERE AccountID = @conta)
UPDATE MEMB_VIP
SET ExpireDate = DATEADD(DAY, @dias,
CASE WHEN ExpireDate > GETDATE() THEN ExpireDate ELSE GETDATE() END),
VipLevel = @nivel, Active = 1
WHERE AccountID = @conta;
ELSE
INSERT INTO MEMB_VIP (AccountID, VipLevel, StartDate, ExpireDate)
VALUES (@conta, @nivel, GETDATE(), DATEADD(DAY, @dias, GETDATE()));
END;
GO
-- Usage:
EXEC sp_AtivarVIP 'jogador01', 2, 30; -- Silver VIP for 30 days
Step 3 — Configure the bonuses in the GameServer file
This is where VIP "takes effect". The exact section varies by season/emulator, but the format usually looks like this:
; ===== VIP SYSTEM =====
[VIP]
Enable = 1 ; turns the VIP system on
; --- Tier 1 (Bronze) ---
VIP1_ExpRate = 150 ; +50% EXP (150% of base value) — format varies
VIP1_DropRate = 130 ; +30% drop
VIP1_ZenRate = 120 ; +20% zen
; --- Tier 2 (Silver) ---
VIP2_ExpRate = 200 ; +100% EXP
VIP2_DropRate = 150
VIP2_ZenRate = 140
; --- Tier 3 (Gold) ---
VIP3_ExpRate = 300 ; +200% EXP
VIP3_DropRate = 200
VIP3_ZenRate = 180
CheckInterval = 60 ; seconds between expiration checks
ExpireNotify = 1 ; notifies the player when VIP expires
> Watch the multiplier format: some distributions use a percentage (150 = +50%), others use an absolute factor (2 = 2x), and others add to the base rate. Read your distribution's file and test with a character before announcing the numbers to players.
After editing, restart the GameServer to load the configuration.
Step 4 — Choose the benefits of each tier
EXP and drop bonuses are the beginning, not the end. The table below lists common benefits and how each is usually implemented. Not all exist in every season — confirm the support in your distribution.
| Benefit | Where it is configured | Note |
|---|---|---|
| Increased EXP | VIPx_ExpRate in the GS config | Most valued bonus; do not overdo it |
| Increased drop | VIPx_DropRate in the GS config | Affects the economy — adjust carefully |
| Extra Zen | VIPx_ZenRate in the GS config | Inflationary effect if too high |
| Access to an exclusive map | VIP check on the map (config/GS) | Move gate + better spot |
| Extra character slots | Slots column in MEMB_INFO | Depends on the distribution |
| Exclusive command (e.g. /offlevel) | VIP tier check in the handler | Not every season has it |
| Expanded vault/warehouse | Warehouse config per VIP | Requires distribution support |
| Colored name/VIP tag | Prefix on the name | Cosmetic, high perceived value |
A balanced tier structure, as an example only (the values vary by season/emulator and by your audience):
| Tier | Duration | EXP | Drop | Extra |
|---|---|---|---|---|
| Bronze | 30 days | +50% | +30% | VIP tag |
| Silver | 30 days | +100% | +50% | Tag + VIP map access |
| Gold | 30 days | +200% | +100% | Everything + extra slot + command |
> The prices and the decision to monetize are yours. Private MU servers have copyright restrictions; keep the project as a non-profit hobby and treat values only as a structuring reference.
Step 5 — Query and manage VIPs
Having maintenance SQL commands on hand avoids day-to-day headaches.
-- Active VIPs and days remaining
SELECT AccountID, VipLevel,
DATEDIFF(DAY, GETDATE(), ExpireDate) AS DiasRestantes
FROM MEMB_VIP
WHERE ExpireDate > GETDATE() AND Active = 1
ORDER BY ExpireDate ASC;
GO
-- Mark expired ones (run as a scheduled job)
UPDATE MEMB_VIP
SET Active = 0
WHERE ExpireDate < GETDATE() AND Active = 1;
GO
-- Remove VIP from an account manually
UPDATE MEMB_VIP
SET Active = 0, ExpireDate = GETDATE()
WHERE AccountID = 'jogador01';
GO
Schedule the expiration UPDATE as a SQL Server Agent Job (every hour, for example) to keep the table consistent even if the GameServer does not do the cleanup.
Step 6 — Integrate with the website
The ultimate goal is to grant VIP with no manual intervention after a confirmed donation. On the website side (PHP/PDO), the call is simple because the logic lives in the procedure:
<?php
// dar-vip.php — called after confirming the payment
function ativarVip(PDO $db, string $conta, int $nivel, int $dias): bool {
$stmt = $db->prepare("EXEC sp_AtivarVIP :conta, :nivel, :dias");
$stmt->bindValue(':conta', $conta);
$stmt->bindValue(':nivel', $nivel, PDO::PARAM_INT);
$stmt->bindValue(':dias', $dias, PDO::PARAM_INT);
return $stmt->execute();
}
// Usage, after validating the provider's payment confirmation:
// ativarVip($db, $contaDoUsuario, 2, 30);
Integration best practices:
- Validate the confirmation on the server, never trust only the return from the user's browser.
- Record a log of each activation (account, tier, days, date, payment reference) for auditing and support.
- Be idempotent: if the same payment is notified twice, do not grant the benefit twice (store the ID of the already-processed transaction).
- Show on the website the player's remaining VIP days, reading from
MEMB_VIP— it reduces support tickets.
Common errors and fixes
| Symptom | Likely cause | Fix |
|---|---|---|
| VIP bonuses do not apply | Wrong config section or Enable=0 | Confirm the exact section name and restart the GS |
| VIP never expires | Missing expiration job and GS does not check | Create the SQL job to UPDATE Active=0 every hour |
| Player complains about losing days on renewal | Renewal overwrote the date instead of extending | Use the CASE WHEN ExpireDate > GETDATE() to extend |
| VIP granted twice | Payment webhook processed twice | Make the activation idempotent by transaction ID |
| Absurdly high EXP | Multiplier format misinterpreted | Test with a character; confirm whether it is % or a factor |
| Website says "account does not exist" | Case/space difference in the login | Normalize the login before calling the procedure |
Launch checklist
- Database backup taken before creating tables/procedures
MEMB_VIPtable (or equivalent columns) created and indexedsp_AtivarVIPprocedure created and tested with a real account[VIP]config section filled in and GameServer restarted- Multipliers tested with a character (% vs factor format confirmed)
- Tiers and benefits documented for the team and the players
- Expiration SQL job scheduled and validated
- Website integration tested with a test payment
- Idempotent activation confirmed (a duplicate notification does not duplicate VIP)
- Player panel showing remaining VIP days
- Activation log working for auditing and support
Frequently asked questions
Do I need to modify the GameServer executable to have VIP?
In most distributions, no. VIP support already comes built in and is enabled through the configuration file and a database table. Only very old distributions require code editing to handle tiers.
How many VIP tiers should I create?
Three is usually the ideal balance — something like Bronze, Silver and Gold. Fewer than that limits the value progression; more than that confuses the player and makes balancing each tier's bonuses harder.
How does the server know when VIP has expired?
The GameServer checks the expiration date in the VIP table at a configurable interval and on login. When the date passes, the status is reverted and the bonuses stop being applied in the next session.
Can I grant VIP automatically after a donation on the website?
Yes. The standard flow is: the website receives the payment confirmation, calls a procedure or runs an UPDATE on the VIP table with the new expiration date, and the GameServer applies the bonuses in the player's next session.
Are VIP and Cash Shop the same thing?
No. VIP grants recurring time-based bonuses (EXP, drop, access) while the subscription is active. The Cash Shop sells individual items for virtual currency. Many servers use both systems together.