MapCamera 스크립트(맵 진입 OnBeginPlay)가 카메라에 더해 플레이어도 셋업: - PlayerControllerComponent.LookDirectionX=1 (오른쪽 — 기본은 -1 왼쪽) - FixedLookAt=true (방향 고정) - Enable=false (키보드 입력 차단: 이동/점프/공격) - map01: 몬스터 3마리 배치(사용자 의도 변경 포함) - 메이커 Play 검증: LookDirectionX=1·Enable=false 확인, 오른쪽키 입력→플레이어 미이동(입력 차단), 아바타 정상, 카메라 zoom90·offset(1.5,-1) 유지 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
111 lines
3.5 KiB
JavaScript
111 lines
3.5 KiB
JavaScript
import { readFileSync, writeFileSync } from 'node:fs';
|
|
|
|
// 맵별 고정 카메라: 맵 로드 시 플레이어 CameraComponent를 data/camera.json 값으로 설정.
|
|
// 새 CameraComponent를 만들지 않고(엔진 소유) 기존 카메라 속성만 런타임 설정한다.
|
|
const CAM = JSON.parse(readFileSync('data/camera.json', 'utf8'));
|
|
const MAP_NUMBERS = Array.from({ length: 11 }, (_, i) => i + 1); // map01~11
|
|
|
|
function prop(Type, Name, DefaultValue = 'nil') {
|
|
return { Type, DefaultValue, SyncDirection: 0, Attributes: [], Name };
|
|
}
|
|
function method(Name, Code, Arguments = [], ExecSpace = 6) {
|
|
return {
|
|
Return: { Type: 'void', DefaultValue: null, SyncDirection: 0, Attributes: [], Name: null },
|
|
Arguments,
|
|
Code,
|
|
Scope: 2,
|
|
ExecSpace,
|
|
Attributes: [],
|
|
Name,
|
|
};
|
|
}
|
|
|
|
function writeCodeblock() {
|
|
const cb = {
|
|
Id: '',
|
|
GameId: '',
|
|
EntryKey: 'codeblock://mapcamera',
|
|
ContentType: 'x-mod/codeblock',
|
|
Content: '',
|
|
Usage: 0,
|
|
UsePublish: 1,
|
|
UseService: 0,
|
|
CoreVersion: '26.5.0.0',
|
|
StudioVersion: '',
|
|
DynamicLoading: 0,
|
|
ContentProto: {
|
|
Use: 'Json',
|
|
Json: {
|
|
CoreVersion: { Major: 0, Minor: 2 },
|
|
ScriptVersion: { Major: 1, Minor: 0 },
|
|
Description: '',
|
|
Id: 'MapCamera',
|
|
Language: 1,
|
|
Name: 'MapCamera',
|
|
Type: 1,
|
|
Source: 0,
|
|
Target: null,
|
|
Properties: [prop('number', 'CamTries', '0')],
|
|
Methods: [
|
|
method('OnBeginPlay', `self.CamTries = 0
|
|
local eventId = 0
|
|
local function apply()
|
|
self.CamTries = self.CamTries + 1
|
|
local cam = nil
|
|
local lp = _UserService.LocalPlayer
|
|
if lp ~= nil then
|
|
cam = lp.CameraComponent
|
|
end
|
|
if cam == nil then
|
|
cam = _CameraService:GetCurrentCameraComponent()
|
|
end
|
|
if cam ~= nil then
|
|
cam.ZoomRatio = ${CAM.zoomRatio}
|
|
cam.ScreenOffset = Vector2(${CAM.screenOffsetX}, ${CAM.screenOffsetY})
|
|
cam.ConfineCameraArea = ${CAM.confineCameraArea}
|
|
cam.CameraOffset = Vector2(${CAM.cameraOffsetX}, ${CAM.cameraOffsetY})
|
|
end
|
|
local pc = nil
|
|
if lp ~= nil then
|
|
pc = lp.PlayerControllerComponent
|
|
if pc ~= nil then
|
|
pc.LookDirectionX = 1
|
|
pc.FixedLookAt = true
|
|
pc.Enable = false
|
|
end
|
|
end
|
|
if cam ~= nil and pc ~= nil then
|
|
_TimerService:ClearTimer(eventId)
|
|
elseif self.CamTries > 30 then
|
|
_TimerService:ClearTimer(eventId)
|
|
end
|
|
end
|
|
eventId = _TimerService:SetTimerRepeat(apply, 0.1)`),
|
|
],
|
|
EntityEventHandlers: [],
|
|
},
|
|
},
|
|
};
|
|
writeFileSync('RootDesk/MyDesk/MapCamera.codeblock', JSON.stringify(cb, null, 2), 'utf8');
|
|
}
|
|
|
|
function patchMap(nn) {
|
|
const tag = String(nn).padStart(2, '0');
|
|
const file = `map/map${tag}.map`;
|
|
const map = JSON.parse(readFileSync(file, 'utf8'));
|
|
const root = map.ContentProto.Entities.find((e) => e.path === `/maps/map${tag}`);
|
|
if (!root) throw new Error(`[gen-camera] 맵 루트 없음: ${file}`);
|
|
// idempotent: 기존 script.MapCamera 제거 후 재추가
|
|
root.jsonString['@components'] = root.jsonString['@components'].filter((c) => c['@type'] !== 'script.MapCamera');
|
|
root.jsonString['@components'].push({ '@type': 'script.MapCamera', Enable: true });
|
|
const names = (root.componentNames || '').split(',').filter((s) => s && s !== 'script.MapCamera');
|
|
names.push('script.MapCamera');
|
|
root.componentNames = names.join(',');
|
|
writeFileSync(file, JSON.stringify(map, null, 2), 'utf8');
|
|
return `map${tag}`;
|
|
}
|
|
|
|
writeCodeblock();
|
|
const patched = MAP_NUMBERS.map(patchMap);
|
|
console.log('MapCamera codeblock written; patched maps:', patched.join(', '));
|