Skip to main content

Migration from v2

v3 keeps the commonly used exports identical. Some internals changed because the architecture moved to server-authoritative logic, MySQL and statebags.

✅ Unchanged (drop-in)

Client exports: getIsHandcuffed, getIsHardcuffed, getHasAnkletracker, getHasHeadbag, getHasTape, cuffPlayer(item, player), hardcuffPlayer(item, player), uncuffPlayer(item, player), ankleTrackerPlayer(player), headbagPlayer(player), tapePlayer(player), dragPlayer(player), escortPlayer(player), putPlayerInCar(player), putPlayerOutOfCar(player)

Server exports: getIsPlayerHandcuffed, getIsPlayerHardcuffed, gethasPlayerAnkleTracker, gethasPlayerHeadbag, gethasPlayerTape

Event handler: msk_handcuffs:handler (same signature)

♻️ Renamed events

v2v3Notes
TriggerClientEvent('msk_handcuffs:cuff', src, item, player)TriggerClientEvent('msk_handcuffs:useItem', src, 'cuff', item)server → client trigger
…:hardcuff / :uncuff:useItem with 'hardcuff' / 'uncuff'
…:setAnkletracker / :setHeadbag / :setTape:useItem with 'ankletracker' / 'headbag' / 'tape'
TriggerServerEvent('msk_handcuffs:setDrag', targetId)TriggerServerEvent('msk_handcuffs:requestDrag', targetId)now distance-validated
…:putInCar…:requestPutInCar
…:outOfCar…:requestOutOfCar
msk_handcuffs:setCuffStatus (relog restore)msk_handcuffs:requestRestore (client → server)see Multichar guide
tip

The cleanest integration is via the exports (dragPlayer, putPlayerInCar, …). Prefer them over the raw events.

❌ Removed

RemovedReason / replacement
Server exports cuffAdmin, hardcuffAdmin, uncuffAdmin, ankleTrackAdmin, headbagAdmin, tapeAdminAdmin actions are server-authoritative; use the admin commands
Client exports cuffPlayerAdmin, hardcuffPlayerAdmin, uncuffPlayerAdmin, ankleTrackerAdminsame as above
Client exports/events Cuff, Hardcuff, Uncuff (self)These were the unvalidated self-uncuff exploit path
Server exports getDatabase, getPlayerFromDatabaseNo flat file anymore — read statebags or the status exports
Client export getObjectStateProps are managed internally
Aliases gethasAnkletracker, gethasHeadbagUse getHasAnkletracker / getHasHeadbag
Server callbacks MSK.Register('msk_handcuffs:getIsHandcuffed' / … / 'canUncuff')Status is now readable directly via statebags

Status reads — old vs new

-- v2 (callback)
local isCuffed = MSK.Trigger('msk_handcuffs:getIsHandcuffed', {source = targetId})

-- v3 (statebag — no callback needed)
local isCuffed = Player(targetId).state.isHandcuffed
-- or the export
local isCuffed = exports.msk_handcuffs:getIsPlayerHandcuffed({source = targetId})
Need the old names back?

If other resources depend on a removed export/event, a thin compatibility layer can map the old names onto the new logic. Open an issue / ask in the MSK Scripts Discord.