FiveM 帮派领地系统:地盘战争脚本编写
构建一个功能完善的 FiveM 帮派领地系统。区域、占领、奖励、毒品控制关联以及用于深度角色扮演战争的最佳帮派脚本。
Agency Scripts
Agency Scripts 创始人兼首席开发者
设计领地系统
帮派领地系统是您可以添加到FiveM角色扮演服务器中最吸引人的机制之一,因为它们为犯罪组织提供了切实的竞争、合作和投资帮派发展的理由。领地系统的核心是将地图划分为帮派可以宣称和控制的区域,赋予拥有帮派在这些边界内特定的利益。您在这里做出的设计决策将塑造服务器上的整个犯罪角色扮演体验。您需要考虑创建多少个区域,每个区域多大,控制区域提供哪些利益,区域多久可以被争夺一次,以及当帮派失去所有领地时会发生什么。区域太少意味着只有最大的帮派能参与,而区域过多则会分散冲突,使单个领地显得无意义。平衡的做法是在已有犯罪角色扮演意义的区域创建15-25个区域,如毒品销售点、仓库区和低收入住宅区。
领地数据结构
数据层需要跟踪区域所有权、占领状态及每个领地的特权。将领地定义存储在配置文件中,所有权数据存储在数据库中,以便调整区域布局而不影响持久数据。每个区域需有唯一标识符、定义其范围的边界坐标、当前所有者及最后占领时间戳。使用多边形边界可精确控制区域形状,自然跟随街道和地标,尽管简单的半径区域更易实现且性能更佳:
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
);
]]
考虑添加 capture_count 列跟踪一个区域被更换所有者的次数,您可以用它进行分析并识别竞争过于激烈的区域,这表明您可能需要调整这些特定区域的冷却时间或占领难度。
捕获机制
占领机制是驱动整个领地系统的游戏循环。当敌对帮派进入领地并发起占领尝试时,计时器开始,攻击方必须坚持到计时完成,而防守帮派会收到警报并可作出响应。最吸引人的占领系统要求攻击帮派在整个占领期间保持一定数量的成员在区域内,形成自然的对抗点。如果攻击方人数低于阈值,占领进度将暂停或开始衰减。以下是核心占领逻辑的服务器端实现:
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)
运行一个服务器端线程,每隔几秒更新占领进度,检查是否维持了最低攻击者数量且未发生冷却违规。当占领完成时,更新数据库,通知所有相关玩家,并在服务器范围内应用新的所有权。向所有连接客户端广播领地变更,以便他们实时更新地图标记。
地图标记和视觉反馈
小地图和暂停菜单地图上的领地标记对于显示玩家哪些区域由哪个帮派控制至关重要。每个领地应显示与所属帮派颜色匹配的彩色标记,未被占领的领地显示为中性灰色或白色。占领进行时,标记应闪烁或变为争夺色,以吸引服务器内玩家注意。使用 AddBlipForRadius 用于领地区域,因为它在地图上创建一个圆形区域覆盖,清晰地传达区域边界:
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
除了地图标记,考虑添加世界内视觉指示器,如彩色烟雾、涂鸦道具或帮派旗帜,当领地被占领时在关键点生成。这些环境提示让玩家沉浸于帮派战争叙事中,即使小地图不可见,也能感受到领地边界的存在。您可以使用 CreateObject native 在每个区域的预定义位置生成帮派专用道具。
帮派特权和奖励
领地特权是激励帮派争夺和防守地盘的关键。没有有意义的奖励,领地控制会变成玩家只参与一次后忽视的形式。最佳特权提供经济和战略优势,帮派控制更多领地时优势叠加。经济特权可能包括该区域内毒品销售利润的百分比提升、访问专属黑市商贩、帮派关联商店的折扣,或定期向帮派共享银行账户存入被动收入。战略特权可能包括领地内更快的重生时间、该区域犯罪减少警察警报、访问隐藏的武器和毒品藏匿点,或放置帮派专属陷阱和防御。将特权实现为服务器端检查,当具有正确帮派身份的玩家在其帮派拥有的领地内执行动作时激活。保持特权系统模块化,便于根据玩家反馈轻松添加新特权或调整现有特权,无需重构整个代码库。
地盘争夺事件与排程
结构化的地盘争夺战事件为领土系统增加了计划的竞争元素,防止玩家疲惫的持续低级别小规模冲突。您可以限制领土战斗在特定时间窗口内进行,如周五和周六晚上,创造玩家期待的事件,玩家会计划并带上完整阵容。或者,实现一个宣战系统,帮派必须通过游戏内机制正式向另一帮派宣战,触发30分钟准备期后领土才可争夺。这给防守帮派时间召集成员并准备防御,导致更大规模和更戏剧性的战斗。跟踪战争统计数据,如击杀、死亡、获得和失去的领土及造成的伤害,并在战争期结束时全服宣布结果。玩家可查看的排行榜或战争历史系统增加了竞争排名元素,使帮派在活跃战争期之间保持参与,并创造成为服务器历史一部分的故事。
反利用措施
领地系统是利用的主要目标,因为它们直接影响游戏内经济和权力动态。最常见的利用是僵尸占领,即帮派成员在低人口时段登录,悄无声息地占领领地。通过要求最低服务器人口才能发起占领,并在占领开始时发送 Discord webhook 通知,确保防守者即使不在线也能响应,防止此类行为。另一个利用是快速切换帮派身份,为多个帮派占领领地。执行至少 24 小时的帮派更换冷却时间,离开帮派时立即剥夺所有领地相关权限。限制每个帮派的占领尝试频率,防止通过频繁发起占领进行破坏。技术方面,所有领地交互均在服务器端验证,绝不信任客户端报告玩家是否在区域边界内,使用服务器端位置检查与 GetEntityCoords(GetPlayerPed(src)) 在占领周期中验证玩家位置。记录每次占领尝试、成功和失败,附带时间戳和玩家标识符,以便调查可疑行为并凭借明确证据对利用者采取行动。
与其他系统集成
领地系统在与服务器其他玩法系统连接时发挥最大潜力。将领地与毒品销售系统关联,控制毒品区可提高售价或降低NPC干扰风险。与住房系统连接,帮派领地提供减免物业税或专属安全屋。与警察系统集成,领地影响调度优先级,帮派控制区的犯罪可能导致警察警报延迟或减少,模拟现实中帮派区的执法难度。将领地数据传入手机或通知系统,帮派领导可随时查看领地状态、占领历史并协调防御。若服务器有进阶或声望系统,将领地控制与帮派声望挂钩,解锁更高级活动和装备。引用领地所有权的系统越多,该机制越具影响力和吸引力,从独立小游戏转变为服务器犯罪RP生态的核心支柱。