所有地图上的功能性区域通过Y3编辑器中的Area+标签实现。代码使用 Area.get_*_areas_by_tag() 获取。
| 标签 | 形状 | 说明 | 参数(KV) |
|---|---|---|---|
player_spawn |
圆形 | 玩家出生点 | — |
npc_spawn |
圆形 | NPC出生区域 | — |
hide_spot |
圆形(R=2) | 藏尸点 | capacity:int |
item_spawn |
圆形(R=1) | 物品刷新点 | — |
interact_bench |
圆形(R=1.5) | 长椅互动点 | — |
interact_board |
圆形(R=1.5) | 告示栏互动点 | — |
interact_well |
圆形(R=1.5) | 水井互动点 | — |
interact_vendor |
圆形(R=2) | 摊位互动点 | — |
smoke_zone |
圆形 | 烟雾弹动态创建 | — |
checkpoint |
圆形(R=3) | VIP模式检查点 | order:int |
exit_point |
圆形(R=3) | VIP撤离点 | — |
fake_vip_spawn |
圆形 | 假VIP出生点 | — |
play_zone |
圆形 | 当前可游玩区域(缩圈) | — |
local CONST = require 'config.const'
local Balance = require 'config.balance'
local M = {}
local current_area = nil
local current_radius = nil
local shrink_timer = nil
local damage_timer = nil
-----------------------------------------------------------
-- 启动
-----------------------------------------------------------
function M.start()
-- 初始为全地图
current_area = y3.area.get_map_area()
current_radius = Balance.CIRCLE_INIT_RADIUS
-- 创建圈区域
local center = current_area:get_center_point()
current_area = y3.area.create_circle_area(center, current_radius)
current_area:add_tag('play_zone')
-- 第一次缩圈在3分钟后
y3.timer.wait(Balance.CIRCLE_FIRST_SHRINK, function()
M.shrink()
end)
end
-----------------------------------------------------------
-- 缩圈
-----------------------------------------------------------
function M.shrink()
if not current_area then return end
local new_radius = current_radius * Balance.CIRCLE_SHRINK_RATIO
if new_radius < Balance.CIRCLE_MIN_RADIUS then
new_radius = Balance.CIRCLE_MIN_RADIUS
end
-- 动画式缩小(每秒减一点)
local delta = current_radius - new_radius
local steps = math.ceil(delta / 0.5)
shrink_timer = y3.timer.count_loop(1.0, steps, function(timer, count)
current_radius = current_radius - 0.5
if current_radius < new_radius then
current_radius = new_radius
end
current_area:set_radius(current_radius)
end)
-- 启动区域外伤害
M.start_damage()
-- 下次缩圈
y3.timer.wait(Balance.CIRCLE_INTERVAL, function()
M.shrink()
end)
end
-----------------------------------------------------------
-- 区域外持续伤害
-----------------------------------------------------------
function M.start_damage()
if damage_timer then return end
damage_timer = y3.timer.loop(2.0, function()
local PlayerMgr = require 'core.player_manager'
for _, pd in ipairs(PlayerMgr.get_all_player_units()) do
if pd.alive then
local pos = pd.unit:get_point()
if not current_area:is_point_in_area(pos) then
pd.unit:add_hp(-Balance.CIRCLE_DAMAGE_PER_TICK)
end
end
end
end, '圈外伤害')
end
-----------------------------------------------------------
-- 停止
-----------------------------------------------------------
function M.stop()
if shrink_timer then shrink_timer:remove() end
if damage_timer then damage_timer:remove() end
if current_area then current_area:remove() end
end
return M
某些地图区域(如建筑内部、墙壁后方)可通过编辑器设置视野阻挡:
-- 在编辑器中可配置,也可通过代码动态控制
local wall_area = y3.area.get_rectangle_by_res_id(WALL_AREA_ID)
wall_area:edit_area_fov_block(1, true) -- 添加视野阻挡
不同区域可以有不同光照,影响"看清"其他玩家的距离:
| 区域类型 | 光照 | 识别距离 |
|---|---|---|
| 亮区(灯下、广场) | 明亮 | 正常 |
| 暗区(小巷、角落) | 昏暗 | 减半 |
| 室内 | 中等 | -20% |
实现方式:通过区域标签 light_dark / light_indoor 标记,怀疑值系统中检测玩家是否在暗区时给予减怀疑值加成。
-- 在suspicion.lua的update中增加
local dark_areas = y3.area.get_circle_areas_by_tag('light_dark')
local in_dark = false
for _, da in ipairs(dark_areas) do
if da:is_point_in_area(unit:get_point()) then
in_dark = true
break
end
end
if in_dark then
delta = delta - 1 -- 在暗区额外减少怀疑值
end
NPC行走路径在编辑器中通过Road工具绘制。
| 路径类型 | 标签约定 | 分配给 |
|---|---|---|
| 主街道环线 | road_main_loop |
civilian, patrol |
| 支线小巷 | road_alley_* |
civilian |
| 巡逻路线 | road_patrol_* |
patrol |
| 广场路线 | road_square |
civilian, wanderer |
| VIP撤离路线 | road_vip_escape_* |
fake_vip |