feat(currency_wars): complete systems, settlement Rank SS, damage report, camera and recovery fixes
This commit is contained in:
1 parent
c008243f11
commit
0995055296
78 files changed
+33840
-9525
No files matched your search
+268
-55
@@ -65,6 +65,62 @@ local function get_active_cam()
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Resolve the controlled member or current battle actor through the Client's
|
||||
-- entity state, and anchor to that model's observed head bone. If the current
|
||||
-- phase does not expose either, do not guess a world position.
|
||||
local function model_for(candidate)
|
||||
local ok, result = pcall(function()
|
||||
local component = candidate and candidate:GetComponent(typeof(CS.RPG.GameCore.CharacterModelComponent))
|
||||
return component and component:GetModelGO()
|
||||
end)
|
||||
if ok then return result end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function is_player_avatar(entity, model)
|
||||
if not entity or not model then return false end
|
||||
local name = tostring(model.name or '')
|
||||
if name:find('Monster', 1, true) then return false end
|
||||
if name:find('Avatar_00', 1, true) then return false end
|
||||
if name:find('Avatar_', 1, true) or name:find('Player_', 1, true) then
|
||||
return true
|
||||
end
|
||||
local ok, isHuman = pcall(function()
|
||||
local anim = model:GetComponentInChildren(typeof(CS.UnityEngine.Animator))
|
||||
return anim and anim.isHuman
|
||||
end)
|
||||
return ok and (isHuman == true)
|
||||
end
|
||||
|
||||
local function find_head_bone(model)
|
||||
if not model then return nil end
|
||||
local ok, bone = pcall(function()
|
||||
local animator = model:GetComponentInChildren(typeof(CS.UnityEngine.Animator))
|
||||
if animator and animator.isHuman then
|
||||
return animator:GetBoneTransform(CS.UnityEngine.HumanBodyBones.Head)
|
||||
end
|
||||
return nil
|
||||
end)
|
||||
if ok and bone and bone.gameObject.activeInHierarchy then
|
||||
return bone
|
||||
end
|
||||
local nodes = model:GetComponentsInChildren(typeof(CS.UnityEngine.Transform), true)
|
||||
for i = 0, nodes.Length - 1 do
|
||||
local node = nodes[i]
|
||||
if node.name == 'Head_M' and node.gameObject.activeInHierarchy then
|
||||
return node
|
||||
end
|
||||
end
|
||||
for i = 0, nodes.Length - 1 do
|
||||
local node = nodes[i]
|
||||
local lname = node.name:lower()
|
||||
if (lname == 'head' or lname == 'bip001 head' or lname:find('head_m', 1, true)) and node.gameObject.activeInHierarchy then
|
||||
return node
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Resolve the controlled member or current battle actor through the Client's
|
||||
-- entity state, and anchor to that model's observed head bone. If the current
|
||||
-- phase does not expose either, do not guess a world position.
|
||||
@@ -74,40 +130,83 @@ local function current_facecam_target()
|
||||
local field = typeof(CS.RPG.Client.GamePhaseManager):GetField('_CurrentPhase', flags)
|
||||
local phase = manager and field and field:GetValue(manager)
|
||||
if not phase then return nil, nil, nil, false end
|
||||
|
||||
local now = Time.unscaledTime or 0
|
||||
local entity, mode
|
||||
|
||||
if typeof(CS.RPG.Client.BattleGamePhase):IsInstanceOfType(phase) then
|
||||
local instance = phase.BattleInstanceRef
|
||||
mode = instance and instance.TurnBasedGameModeRef
|
||||
entity = mode and mode.CurrentTurnOwnerEntity
|
||||
-- Inserted attacks can act outside the turn owner's turn. Prefer the
|
||||
-- most recently attacking entity while the Client reports one.
|
||||
if mode then
|
||||
-- 1. Attacking Avatar (skill, ultimate, basic attack)
|
||||
local attackers = mode:GetAttackingEntityList()
|
||||
if attackers and attackers.Count > 0 then entity = attackers[attackers.Count - 1] end
|
||||
if attackers and attackers.Count > 0 then
|
||||
for i = attackers.Count - 1, 0, -1 do
|
||||
local cand = attackers[i]
|
||||
local candModel = model_for(cand)
|
||||
if is_player_avatar(cand, candModel) then
|
||||
entity = cand
|
||||
_G.__FC_BATTLE_LAST_ATTACKER = cand
|
||||
_G.__FC_BATTLE_ATTACK_TIME = now
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 2. Keep tracking recent ultimate / attacking avatar during cutscenes (up to 4.5s)
|
||||
if not entity and _G.__FC_BATTLE_LAST_ATTACKER then
|
||||
local lastModel = model_for(_G.__FC_BATTLE_LAST_ATTACKER)
|
||||
if lastModel and (now - (_G.__FC_BATTLE_ATTACK_TIME or 0)) < 4.5 then
|
||||
entity = _G.__FC_BATTLE_LAST_ATTACKER
|
||||
end
|
||||
end
|
||||
|
||||
-- 3. Turn owner (only if player avatar)
|
||||
if not entity then
|
||||
local turnOwner = mode.CurrentTurnOwnerEntity
|
||||
local turnModel = model_for(turnOwner)
|
||||
if is_player_avatar(turnOwner, turnModel) then
|
||||
entity = turnOwner
|
||||
_G.__FC_BATTLE_LAST_AVATAR = turnOwner
|
||||
end
|
||||
end
|
||||
|
||||
-- 4. Stick to last active player avatar if turn owner is an enemy monster
|
||||
if not entity and _G.__FC_BATTLE_LAST_AVATAR then
|
||||
local lastModel = model_for(_G.__FC_BATTLE_LAST_AVATAR)
|
||||
if lastModel then
|
||||
entity = _G.__FC_BATTLE_LAST_AVATAR
|
||||
end
|
||||
end
|
||||
|
||||
-- 5. Fallback: MVP entity if it's an avatar
|
||||
if not entity and mode.CurrentMVPEntity then
|
||||
local mvp = mode.CurrentMVPEntity
|
||||
local mvpModel = model_for(mvp)
|
||||
if is_player_avatar(mvp, mvpModel) then
|
||||
entity = mvp
|
||||
_G.__FC_BATTLE_LAST_AVATAR = mvp
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif phase:GetType().Name == 'AdventurePhase' then
|
||||
entity = phase.CurrentPlayingTeamMember
|
||||
else
|
||||
return nil, nil, nil, false
|
||||
end
|
||||
|
||||
if not entity then return nil, nil, nil, true end
|
||||
local function model_for(candidate)
|
||||
local ok, result = pcall(function()
|
||||
local component = candidate and candidate:GetComponent(typeof(CS.RPG.GameCore.CharacterModelComponent))
|
||||
return component and component:GetModelGO()
|
||||
end)
|
||||
if ok then return result end
|
||||
return nil
|
||||
end
|
||||
|
||||
local model = model_for(entity)
|
||||
-- In a transformed turn the Client can report a model-less turn owner;
|
||||
-- the live battle's MVP entity points to the visible transformed actor.
|
||||
if not model and mode then
|
||||
local fallback = mode.CurrentMVPEntity
|
||||
local fallbackModel = model_for(fallback)
|
||||
if fallbackModel then entity, model = fallback, fallbackModel end
|
||||
if fallbackModel and is_player_avatar(fallback, fallbackModel) then
|
||||
entity, model = fallback, fallbackModel
|
||||
end
|
||||
end
|
||||
if not model then return nil, nil, nil, true end
|
||||
|
||||
local cachedAlive, cachedActive = pcall(function()
|
||||
return _G.__FC_FACE_HEAD and _G.__FC_FACE_ROOT
|
||||
and _G.__FC_FACE_HEAD.gameObject.activeInHierarchy and _G.__FC_FACE_ROOT.gameObject.activeInHierarchy
|
||||
@@ -115,13 +214,13 @@ local function current_facecam_target()
|
||||
if _G.__FC_FACE_ENTITY == entity.RuntimeID and cachedAlive and cachedActive then
|
||||
return _G.__FC_FACE_HEAD, _G.__FC_FACE_ROOT, entity.RuntimeID, true
|
||||
end
|
||||
local nodes = model:GetComponentsInChildren(typeof(CS.UnityEngine.Transform), true)
|
||||
for i = 0, nodes.Length - 1 do
|
||||
if nodes[i].name == 'Head_M' and nodes[i].gameObject.activeInHierarchy then
|
||||
return nodes[i], model.transform, entity.RuntimeID, true
|
||||
end
|
||||
|
||||
local head = find_head_bone(model)
|
||||
if head then
|
||||
return head, model.transform, entity.RuntimeID, true
|
||||
end
|
||||
return nil, nil, nil, true
|
||||
|
||||
return nil, model.transform, entity.RuntimeID, true
|
||||
end
|
||||
|
||||
-- Log only changes, so diagnostics stay useful during long battles.
|
||||
@@ -158,7 +257,9 @@ local function facecam_target(cam)
|
||||
local battleHead, battleRoot, id, tracked = current_facecam_target()
|
||||
if tracked then
|
||||
_G.__FC_FACE_ENTITY = id
|
||||
return battleHead, battleRoot
|
||||
if battleHead and battleRoot then
|
||||
return battleHead, battleRoot
|
||||
end
|
||||
end
|
||||
local brain = cam:GetComponent(typeof(CS.Cinemachine.CinemachineBrain))
|
||||
local virtual = brain and brain.ActiveVirtualCamera
|
||||
@@ -179,22 +280,37 @@ end
|
||||
local function update_facecam(cam, settings)
|
||||
local now = Time.unscaledTime or 0
|
||||
if now >= (_G.__FC_FACE_NEXT or 0) then
|
||||
_G.__FC_FACE_NEXT = now + 0.15
|
||||
_G.__FC_FACE_NEXT = now + 0.08
|
||||
local ok, head, root, id, tracked = pcall(current_facecam_target)
|
||||
log_facecam_target(ok, head, root, id, tracked)
|
||||
if ok and tracked and head and root then
|
||||
_G.__FC_FACE_HEAD, _G.__FC_FACE_ROOT, _G.__FC_FACE_ENTITY = head, root, id
|
||||
if ok and tracked then
|
||||
if head and root then
|
||||
_G.__FC_FACE_HEAD, _G.__FC_FACE_ROOT, _G.__FC_FACE_ENTITY = head, root, id
|
||||
_G.__FC_FACE_MISSING_SINCE = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local head, root = _G.__FC_FACE_HEAD, _G.__FC_FACE_ROOT
|
||||
local alive, active = pcall(function() return head and root and head.gameObject.activeInHierarchy end)
|
||||
if not alive or not active then
|
||||
-- Character transformations can briefly unload a model while keeping
|
||||
-- the same entity ID. Give the replacement time to become available.
|
||||
-- Character transformations or ultimate cutscenes can briefly unload/hide a model.
|
||||
-- Hold last valid camera transform only within a short grace period (3s).
|
||||
-- If character remains unavailable (e.g. battle finished or scene changed),
|
||||
-- return false so FaceCam automatically deactivates and restores Cinemachine.
|
||||
_G.__FC_FACE_MISSING_SINCE = _G.__FC_FACE_MISSING_SINCE or now
|
||||
return now - _G.__FC_FACE_MISSING_SINCE < 2
|
||||
if now - _G.__FC_FACE_MISSING_SINCE > 3.0 then
|
||||
return false
|
||||
end
|
||||
if _G.__FC_POS and _G.__FC_EULER then
|
||||
cam.transform.position = _G.__FC_POS
|
||||
cam.transform.eulerAngles = _G.__FC_EULER
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
_G.__FC_FACE_MISSING_SINCE = nil
|
||||
|
||||
local distance = _G.__FC_FACE_DISTANCE or tonumber(settings.distance) or 2
|
||||
local scroll = Input.mouseScrollDelta.y
|
||||
if scroll ~= 0 then distance = distance - scroll * 0.2 end
|
||||
@@ -203,21 +319,53 @@ local function update_facecam(cam, settings)
|
||||
if scroll ~= 0 then
|
||||
show_ui('<color=#00FF88><b>[FaceCam: ON]</b> Distance: ' .. string.format('%.1f', distance) .. '</color>')
|
||||
end
|
||||
local target = head.position
|
||||
local anchor = _G.__FC_FACE_ANCHOR
|
||||
if not anchor or anchor.transform.parent ~= head then
|
||||
if anchor then CS.UnityEngine.Object.Destroy(anchor) end
|
||||
anchor = GameObject('GaC_FaceCamAnchor')
|
||||
anchor.transform:SetParent(head, false)
|
||||
_G.__FC_FACE_ANCHOR = anchor
|
||||
|
||||
-- Target: Center of the face/eyes (~0.08m above neck pivot Head_M)
|
||||
local eyeOffset = 0.08
|
||||
local faceCenter = head.position + Vector3(0, eyeOffset, 0)
|
||||
|
||||
-- In HSR rigs, head.up is aligned with the facial forward axis.
|
||||
-- Project onto horizontal plane (Y=0) so camera remains level and doesn't tilt/pitch with nodding.
|
||||
local fwdX = head.up.x
|
||||
local fwdZ = head.up.z
|
||||
local fwdMagSq = fwdX * fwdX + fwdZ * fwdZ
|
||||
local fwd
|
||||
if fwdMagSq > 0.001 then
|
||||
local invMag = 1.0 / math.sqrt(fwdMagSq)
|
||||
fwd = Vector3(fwdX * invMag, 0, fwdZ * invMag)
|
||||
elseif root then
|
||||
local rX = root.forward.x
|
||||
local rZ = root.forward.z
|
||||
local rMagSq = rX * rX + rZ * rZ
|
||||
if rMagSq > 0.001 then
|
||||
local invR = 1.0 / math.sqrt(rMagSq)
|
||||
fwd = Vector3(rX * invR, 0, rZ * invR)
|
||||
else
|
||||
fwd = Vector3(0, 0, 1)
|
||||
end
|
||||
else
|
||||
fwd = Vector3(0, 0, 1)
|
||||
end
|
||||
-- The observed game rig uses Head_M's local up axis as its facial
|
||||
-- direction; model-root forward does not follow the animated pose.
|
||||
local direction = head.up
|
||||
anchor.transform.position = target + direction * distance
|
||||
anchor.transform.rotation = CS.UnityEngine.Quaternion.LookRotation(target - anchor.transform.position, Vector3.up)
|
||||
cam.transform.position = anchor.transform.position
|
||||
cam.transform.rotation = anchor.transform.rotation
|
||||
|
||||
local desiredPos = faceCenter + fwd * distance
|
||||
local lookDir = faceCenter - desiredPos
|
||||
local desiredRot = CS.UnityEngine.Quaternion.LookRotation(lookDir, Vector3.up)
|
||||
|
||||
-- Smooth interpolation to remove micro-jitter while tracking
|
||||
local dt = Time.unscaledDeltaTime or 0.016
|
||||
if dt <= 0 or dt > 0.1 then dt = 0.016 end
|
||||
local smoothSpeed = 16.0
|
||||
local factor = math.min(1.0, dt * smoothSpeed)
|
||||
|
||||
if _G.__FC_LAST_TRACKED_ENTITY ~= _G.__FC_FACE_ENTITY or not _G.__FC_POS then
|
||||
_G.__FC_LAST_TRACKED_ENTITY = _G.__FC_FACE_ENTITY
|
||||
cam.transform.position = desiredPos
|
||||
cam.transform.rotation = desiredRot
|
||||
else
|
||||
cam.transform.position = Vector3.Lerp(cam.transform.position, desiredPos, factor)
|
||||
cam.transform.rotation = CS.UnityEngine.Quaternion.Slerp(cam.transform.rotation, desiredRot, factor)
|
||||
end
|
||||
|
||||
_G.__FC_POS = cam.transform.position
|
||||
_G.__FC_EULER = cam.transform.eulerAngles
|
||||
return true
|
||||
@@ -233,6 +381,19 @@ local function set_cinemachine_enabled(cam, enabled)
|
||||
pcall(function() if state.brain then state.brain.enabled = state.enabled end end)
|
||||
_G.__FC_BRAINS[id] = nil
|
||||
end
|
||||
pcall(function()
|
||||
if cam then
|
||||
local brain = cam:GetComponent(typeof(CS.Cinemachine.CinemachineBrain))
|
||||
if brain then brain.enabled = true end
|
||||
cam.enabled = true
|
||||
end
|
||||
local mainCam = CS.UnityEngine.Camera.main
|
||||
if mainCam and mainCam ~= cam then
|
||||
local brain = mainCam:GetComponent(typeof(CS.Cinemachine.CinemachineBrain))
|
||||
if brain then brain.enabled = true end
|
||||
mainCam.enabled = true
|
||||
end
|
||||
end)
|
||||
return
|
||||
end
|
||||
pcall(function()
|
||||
@@ -255,7 +416,7 @@ _G.__FC_MOUSE_GATE = _G.__FC_MOUSE_GATE or {modules={}, bindings={}}
|
||||
local function restore_mouse_gate()
|
||||
local gate = _G.__FC_MOUSE_GATE
|
||||
for _, state in ipairs(gate.modules) do
|
||||
pcall(function() state.module.allowMouseInput = state.allowed end)
|
||||
pcall(function() state.module.allowMouseInput = true end)
|
||||
end
|
||||
for _, state in ipairs(gate.bindings) do
|
||||
pcall(function()
|
||||
@@ -265,6 +426,13 @@ local function restore_mouse_gate()
|
||||
end
|
||||
end)
|
||||
end
|
||||
pcall(function()
|
||||
local eventSystem = CS.UnityEngine.EventSystems.EventSystem.current
|
||||
if eventSystem then
|
||||
local module = eventSystem:GetComponent(typeof(CS.InControl.InControlInputModule))
|
||||
if module then module.allowMouseInput = true end
|
||||
end
|
||||
end)
|
||||
gate.modules, gate.bindings, gate.sets = {}, {}, {}
|
||||
gate.active = false
|
||||
end
|
||||
@@ -305,7 +473,11 @@ local function update_mouse_gate()
|
||||
if not recorded then
|
||||
gate.modules[#gate.modules + 1] = {module=module, allowed=module.allowMouseInput}
|
||||
end
|
||||
module.allowMouseInput = false
|
||||
if Input.GetMouseButton(1) then
|
||||
module.allowMouseInput = false
|
||||
else
|
||||
module.allowMouseInput = true
|
||||
end
|
||||
end
|
||||
end
|
||||
gate.sets = gate.sets or {}
|
||||
@@ -352,7 +524,7 @@ function _G.__FREECAM_TICK()
|
||||
return
|
||||
end
|
||||
_G.__FC_INPUT_FRAME = frame
|
||||
if Input.GetKeyDown(KeyCode.Tab) then
|
||||
if Input.GetKeyDown(KeyCode.F8) or Input.GetKeyDown(KeyCode.Insert) then
|
||||
_G.__FREECAM_ENABLED = not _G.__FREECAM_ENABLED
|
||||
_G.__FC_LAST_TIME = nil
|
||||
local cam = get_active_cam()
|
||||
@@ -362,13 +534,11 @@ function _G.__FREECAM_TICK()
|
||||
_G.__FC_FACE_DISTANCE = tonumber(settings.distance) or 2
|
||||
local head, root
|
||||
if cam then head, root = facecam_target(cam) end
|
||||
if not head or not root then
|
||||
_G.__FREECAM_ENABLED = false
|
||||
show_ui("<color=#FFAA44>FaceCam: character head unavailable</color>")
|
||||
CS.UnityEngine.Debug.Log("[FaceCam] active camera follow target has no humanoid head")
|
||||
return
|
||||
if head and root then
|
||||
_G.__FC_FACE_HEAD, _G.__FC_FACE_ROOT = head, root
|
||||
else
|
||||
_G.__FC_FACE_HEAD, _G.__FC_FACE_ROOT = nil, nil
|
||||
end
|
||||
_G.__FC_FACE_HEAD, _G.__FC_FACE_ROOT = head, root
|
||||
end
|
||||
if cam then
|
||||
_G.__FC_POS = cam.transform.position
|
||||
@@ -376,9 +546,9 @@ function _G.__FREECAM_TICK()
|
||||
set_cinemachine_enabled(cam, false)
|
||||
end
|
||||
if settings.mode == "facecam" then
|
||||
show_ui("<color=#00FF88><b>[FaceCam: ON]</b> | Tab: Close</color>")
|
||||
show_ui("<color=#00FF88><b>[FaceCam: ON]</b> | F8/Insert: Close</color>")
|
||||
else
|
||||
show_ui("<color=#00FF88><b>[FreeCam: ON]</b> Speed: " .. string.format("%.1f", _G.__FREECAM_SPEED) .. " | Arrows: Fly | PgUp/PgDn: Up/Down | RMB: Look</color>")
|
||||
show_ui("<color=#00FF88><b>[FreeCam: ON]</b> Speed: " .. string.format("%.1f", _G.__FREECAM_SPEED) .. " | Arrows: Fly | PgUp/PgDn: Up/Down | RMB: Look | F8/Insert: Close</color>")
|
||||
end
|
||||
else
|
||||
local settings = _G.__GAC_CAMERA_SETTINGS or {mode="freecam"}
|
||||
@@ -387,6 +557,9 @@ function _G.__FREECAM_TICK()
|
||||
end
|
||||
_G.__FC_FACE_HEAD, _G.__FC_FACE_ROOT = nil, nil
|
||||
_G.__FC_FACE_ENTITY = nil
|
||||
_G.__FC_LAST_TRACKED_ENTITY = nil
|
||||
_G.__FC_BATTLE_LAST_ATTACKER = nil
|
||||
_G.__FC_BATTLE_LAST_AVATAR = nil
|
||||
_G.__FC_FACE_DISTANCE, _G.__FC_FACE_LOCAL_FORWARD = nil, nil
|
||||
_G.__FC_FACE_MISSING_SINCE = nil
|
||||
if _G.__FC_FACE_ANCHOR then CS.UnityEngine.Object.Destroy(_G.__FC_FACE_ANCHOR); _G.__FC_FACE_ANCHOR = nil end
|
||||
@@ -409,6 +582,43 @@ function _G.__FREECAM_TICK()
|
||||
CS.UnityEngine.Debug.Log("[FreeCam] Mouse gate error: " .. tostring(gateError))
|
||||
end
|
||||
|
||||
-- Detect game phase changes (e.g. Battle <-> Adventure or Scene loading transitions)
|
||||
-- Immediately restore Cinemachine and deactivate FreeCam/FaceCam so the camera does not
|
||||
-- get pinned in the void (black screen) when returning to overworld scenes like Dewlight Pavilion.
|
||||
pcall(function()
|
||||
local manager = CS.RPG.Client.GlobalVars.s_GamePhaseManager
|
||||
local phaseField = _G.__FC_PHASE_FIELD
|
||||
if not phaseField then
|
||||
local flags = CS.System.Enum.ToObject(typeof(CS.System.Reflection.BindingFlags), 60)
|
||||
phaseField = typeof(CS.RPG.Client.GamePhaseManager):GetField("_CurrentPhase", flags)
|
||||
_G.__FC_PHASE_FIELD = phaseField
|
||||
end
|
||||
local currentPhase = manager and phaseField and phaseField:GetValue(manager)
|
||||
local currentPhaseName = currentPhase and currentPhase:GetType().Name or ""
|
||||
if _G.__FC_LAST_PHASE_NAME and _G.__FC_LAST_PHASE_NAME ~= currentPhaseName and currentPhaseName ~= "" then
|
||||
local cam = get_active_cam()
|
||||
set_cinemachine_enabled(cam, true)
|
||||
restore_mouse_gate()
|
||||
_G.__FREECAM_ENABLED = false
|
||||
_G.__FC_POS = nil
|
||||
_G.__FC_EULER = nil
|
||||
_G.__FC_FACE_HEAD, _G.__FC_FACE_ROOT = nil, nil
|
||||
_G.__FC_FACE_ENTITY = nil
|
||||
_G.__FC_LAST_TRACKED_ENTITY = nil
|
||||
_G.__FC_BATTLE_LAST_ATTACKER = nil
|
||||
_G.__FC_BATTLE_LAST_AVATAR = nil
|
||||
_G.__FC_FACE_DISTANCE, _G.__FC_FACE_LOCAL_FORWARD = nil, nil
|
||||
_G.__FC_FACE_MISSING_SINCE = nil
|
||||
if _G.__FC_FACE_ANCHOR then
|
||||
CS.UnityEngine.Object.Destroy(_G.__FC_FACE_ANCHOR)
|
||||
_G.__FC_FACE_ANCHOR = nil
|
||||
end
|
||||
end
|
||||
if currentPhaseName ~= "" then
|
||||
_G.__FC_LAST_PHASE_NAME = currentPhaseName
|
||||
end
|
||||
end)
|
||||
|
||||
if _G.__FREECAM_ENABLED then
|
||||
local cam = get_active_cam()
|
||||
if cam then
|
||||
@@ -419,6 +629,9 @@ function _G.__FREECAM_TICK()
|
||||
_G.__FREECAM_ENABLED = false
|
||||
_G.__FC_FACE_HEAD, _G.__FC_FACE_ROOT = nil, nil
|
||||
_G.__FC_FACE_ENTITY = nil
|
||||
_G.__FC_LAST_TRACKED_ENTITY = nil
|
||||
_G.__FC_BATTLE_LAST_ATTACKER = nil
|
||||
_G.__FC_BATTLE_LAST_AVATAR = nil
|
||||
_G.__FC_FACE_DISTANCE, _G.__FC_FACE_LOCAL_FORWARD = nil, nil
|
||||
_G.__FC_FACE_MISSING_SINCE = nil
|
||||
if _G.__FC_FACE_ANCHOR then CS.UnityEngine.Object.Destroy(_G.__FC_FACE_ANCHOR); _G.__FC_FACE_ANCHOR = nil end
|
||||
@@ -441,11 +654,11 @@ function _G.__FREECAM_TICK()
|
||||
-- Speed adjustment (+ / -)
|
||||
if Input.GetKeyDown(KeyCode.Equals) or Input.GetKeyDown(KeyCode.KeypadPlus) then
|
||||
_G.__FREECAM_SPEED = math.min(300.0, _G.__FREECAM_SPEED * 1.5)
|
||||
show_ui("<color=#00FF88><b>[FreeCam: ON]</b> Speed: " .. string.format("%.1f", _G.__FREECAM_SPEED) .. " | Arrows: Fly | PgUp/PgDn: Up/Down | RMB: Look</color>")
|
||||
show_ui("<color=#00FF88><b>[FreeCam: ON]</b> Speed: " .. string.format("%.1f", _G.__FREECAM_SPEED) .. " | Arrows: Fly | PgUp/PgDn: Up/Down | RMB: Look | F8/Insert: Close</color>")
|
||||
end
|
||||
if Input.GetKeyDown(KeyCode.Minus) or Input.GetKeyDown(KeyCode.KeypadMinus) then
|
||||
_G.__FREECAM_SPEED = math.max(0.5, _G.__FREECAM_SPEED / 1.5)
|
||||
show_ui("<color=#00FF88><b>[FreeCam: ON]</b> Speed: " .. string.format("%.1f", _G.__FREECAM_SPEED) .. " | Arrows: Fly | PgUp/PgDn: Up/Down | RMB: Look</color>")
|
||||
show_ui("<color=#00FF88><b>[FreeCam: ON]</b> Speed: " .. string.format("%.1f", _G.__FREECAM_SPEED) .. " | Arrows: Fly | PgUp/PgDn: Up/Down | RMB: Look | F8/Insert: Close</color>")
|
||||
end
|
||||
|
||||
-- Raw Unity mouse input remains available to the camera while
|
||||
|
||||
Reference in new issue
Block a user