diff --git a/2001/ze_maontain_escape/bicycle.js b/2001/ze_maontain_escape/bicycle.js new file mode 100644 index 0000000..fae4a0a --- /dev/null +++ b/2001/ze_maontain_escape/bicycle.js @@ -0,0 +1,208 @@ +import { Instance, CSInputs } from "cs_script/point_script"; + +// 配置参数 +const UPDATE_INTERVAL = 0.2; // 更新间隔(秒) +const MAX_SPEED_FWD = 250; // 前进最大速度 +const MAX_SPEED_REV = MAX_SPEED_FWD / 4; // 倒车最大速度(前进的1/4) +const TURN_RATE = 100; // 最大转向角速度(度/秒) +const ACCELERATION = 1500; // 水平加速度(单位/秒²) + +// 爬坡辅助参数 +const HILL_ASSIST_ANGLE_MIN = -75; // 触发爬坡辅助的最小 pitch 角度 +const HILL_ASSIST_ANGLE_MAX = 30; // 触发爬坡辅助的最大 pitch 角度 +const HILL_ASSIST_MAX_SPEED = 35; // 爬坡辅助最大附加速度 + +// 侧翻修正参数 +const ROLL_THRESHOLD = 90; // 触发侧翻修正的 roll 绝对值阈值 +const ROLL_CORRECTION_RATE = 300; // 最大侧翻修正角速度 + +// 脚本状态 +let bicycleBox = null; // 当前自行车实体 +let riderPawn = null; // 当前骑手玩家 +let isRiding = false; // 是否正在骑行 +let thinkRegistered = false; // think 是否已注册 + +// 按键按下时间记录(用于优先级处理) +let keyTimers = {}; + +// 辅助函数:提取 namefix 后缀 +function getSuffixFromName(name) { return name.match(/_(\d+)$/)?.[1] || null; } + +// 辅助函数:检查实体是否有效 +function isValidEntity(ent) { return ent && ent.IsValid(); } + +// 辅助函数:计算前向向量(基于 QAngle) +function getForwardVector(angles) { + const pitch = angles.pitch * Math.PI / 180; + const yaw = angles.yaw * Math.PI / 180; + const cosPitch = Math.cos(pitch); + return { + x: Math.cos(yaw) * cosPitch, + y: Math.sin(yaw) * cosPitch, + z: -Math.sin(pitch) + }; +} + +// 辅助函数:限制水平速度变化量(平滑加速/减速) +function applyAcceleration(current, target, maxDelta) { + const diff = { x: target.x - current.x, y: target.y - current.y }; + const len = Math.sqrt(diff.x * diff.x + diff.y * diff.y); + if (len <= maxDelta) return target; + const scale = maxDelta / len; + return { x: current.x + diff.x * scale, y: current.y + diff.y * scale }; +} + +// 主更新循环 +function think() { + if (!isRiding) { Instance.SetNextThink(Instance.GetGameTime() + UPDATE_INTERVAL); return; } + + // 检查实体有效性,失效时自动停止骑行 + if (!isValidEntity(bicycleBox) || !isValidEntity(riderPawn) || !riderPawn.IsAlive()) { + isRiding = false; + return; + } + + // 1. 将骑手位置锁定到自行车位置 + riderPawn.Teleport({ position: bicycleBox.GetAbsOrigin() }); + + // 2. 获取当前时间 + const currentTime = Instance.GetGameTime(); + + // 3. 检查按键状态 + const pressedForward = riderPawn.IsInputPressed(CSInputs.FORWARD); + const pressedBack = riderPawn.IsInputPressed(CSInputs.BACK); + const pressedLeft = riderPawn.IsInputPressed(CSInputs.LEFT); + const pressedRight = riderPawn.IsInputPressed(CSInputs.RIGHT); + + // 更新按键按下时间(仅刚按下时记录) + if (riderPawn.WasInputJustPressed(CSInputs.FORWARD)) keyTimers[CSInputs.FORWARD] = currentTime; + if (riderPawn.WasInputJustPressed(CSInputs.BACK)) keyTimers[CSInputs.BACK] = currentTime; + if (riderPawn.WasInputJustPressed(CSInputs.LEFT)) keyTimers[CSInputs.LEFT] = currentTime; + if (riderPawn.WasInputJustPressed(CSInputs.RIGHT)) keyTimers[CSInputs.RIGHT] = currentTime; + + // 键释放时清除时间戳 + if (!pressedForward) keyTimers[CSInputs.FORWARD] = null; + if (!pressedBack) keyTimers[CSInputs.BACK] = null; + if (!pressedLeft) keyTimers[CSInputs.LEFT] = null; + if (!pressedRight) keyTimers[CSInputs.RIGHT] = null; + + // 移动方向:1前进 -1后退 0无 + let moveDir = 0; + const forwardTime = keyTimers[CSInputs.FORWARD]; + const backTime = keyTimers[CSInputs.BACK]; + if (forwardTime !== null && backTime !== null) moveDir = forwardTime < backTime ? 1 : -1; + else if (forwardTime !== null) moveDir = 1; + else if (backTime !== null) moveDir = -1; + + // 转向方向:1左转 -1右转 0无 + let turnDir = 0; + const leftTime = keyTimers[CSInputs.LEFT]; + const rightTime = keyTimers[CSInputs.RIGHT]; + if (leftTime !== null && rightTime !== null) turnDir = leftTime < rightTime ? 1 : -1; + else if (leftTime !== null) turnDir = 1; + else if (rightTime !== null) turnDir = -1; + + // 4. 获取自行车当前朝向 + const boxAngles = bicycleBox.GetAbsAngles(); + const pitch = boxAngles.pitch; + const roll = boxAngles.roll; + + // 5. 获取当前速度和角速度 + const currentVel = bicycleBox.GetAbsVelocity(); + const currentAngVel = bicycleBox.GetAbsAngularVelocity(); + + // 6. 计算基础目标水平速度(基于玩家输入) + let baseTargetHor = { x: 0, y: 0 }; + if (moveDir !== 0) { + const forward = getForwardVector(boxAngles); + const maxSpeed = moveDir > 0 ? MAX_SPEED_FWD : MAX_SPEED_REV; + baseTargetHor = { x: forward.x * maxSpeed * moveDir, y: forward.y * maxSpeed * moveDir }; + } + + // 7. 爬坡辅助(仅前进时且在角度范围内) + let hillAssistSpeed = 0; + if (moveDir > 0 && pitch >= HILL_ASSIST_ANGLE_MIN && pitch <= HILL_ASSIST_ANGLE_MAX) { + const factor = (pitch - HILL_ASSIST_ANGLE_MIN) / (HILL_ASSIST_ANGLE_MAX - HILL_ASSIST_ANGLE_MIN); + hillAssistSpeed = factor * HILL_ASSIST_MAX_SPEED; + const forward = getForwardVector(boxAngles); + baseTargetHor.x += forward.x * hillAssistSpeed; + baseTargetHor.y += forward.y * hillAssistSpeed; + } + + // 8. 平滑加速/减速(水平方向) + const maxDelta = ACCELERATION * UPDATE_INTERVAL; + const newHor = applyAcceleration({ x: currentVel.x, y: currentVel.y }, baseTargetHor, maxDelta); + + // 9. 合成新速度:保留垂直速度,加上爬坡辅助垂直分量 + let newVelocity = { x: newHor.x, y: newHor.y, z: currentVel.z }; + if (hillAssistSpeed > 0) { + const forward = getForwardVector(boxAngles); + newVelocity.z += forward.z * hillAssistSpeed; + } + + // 10. 侧翻修正(基于滚转角) + let correctionAngVelY = 0; + if (Math.abs(roll) > ROLL_THRESHOLD) { + const error = -roll; + const k = 2.0; + correctionAngVelY = Math.max(-ROLL_CORRECTION_RATE, Math.min(ROLL_CORRECTION_RATE, error * k)); + } + + // 11. 新角速度:保留俯仰,修正滚转,设置偏航 + const newAngularVelocity = { + x: currentAngVel.x, + y: correctionAngVelY, + z: turnDir * TURN_RATE + }; + + // 12. 应用 Teleport(只设置速度和角速度) + bicycleBox.Teleport({ velocity: newVelocity, angularVelocity: newAngularVelocity }); + + // 13. 安排下一次更新 + Instance.SetNextThink(Instance.GetGameTime() + UPDATE_INTERVAL); +} + +// 处理 Start 输入(上车) +Instance.OnScriptInput("start", (inputData) => { + const caller = inputData.caller; + const activator = inputData.activator; + if (!caller || !activator) return; + + const suffix = getSuffixFromName(caller.GetEntityName()); + if (!suffix) return; + + const box = Instance.FindEntityByName(`bicycle_box_${suffix}`); + if (!box || !box.IsValid()) return; + + if (!activator.IsAlive || !activator.IsAlive()) return; + + if (isRiding) isRiding = false; // 替换旧骑手 + + bicycleBox = box; + riderPawn = activator; + isRiding = true; + + if (!thinkRegistered) { + Instance.SetThink(think); + thinkRegistered = true; + } + Instance.SetNextThink(Instance.GetGameTime() + UPDATE_INTERVAL); +}); + +// 处理 Stop 输入(下车) +Instance.OnScriptInput("stop", () => { + isRiding = false; + bicycleBox = null; + riderPawn = null; + keyTimers = {}; +}); + +// 处理脚本重载(Tools 模式) +Instance.OnScriptReload({ + before: () => { + isRiding = false; + bicycleBox = null; + riderPawn = null; + thinkRegistered = false; + } +}); \ No newline at end of file diff --git a/2001/ze_maontain_escape/countdown.js b/2001/ze_maontain_escape/countdown.js index 0c38b27..9d52813 100644 --- a/2001/ze_maontain_escape/countdown.js +++ b/2001/ze_maontain_escape/countdown.js @@ -1,4 +1,4 @@ -//纯预设模版的倒计时脚本,游戏内对point_script实体输入RunScriptInput,值为endin_30,则触发30秒内结束战斗的倒计时 +//纯预设模版的倒计时脚本,游戏内对point_script实体输入RunScriptInput,值为pushin_30,则触发30秒内结束战斗的倒计时 //回合重启或者输入值为stop时倒计时会直接停止 //局内需存在以下实体 //①、一个game_zone_player固实体,命名为countdown_game_zone_player_hide,实体内io:OnPlayerOutZone>countdown_hudhint>HideHudHint>>0>-1 @@ -15,13 +15,13 @@ const CONFIG = { ZONE_SHOW: "countdown_game_zone_player_show", ZONE_HIDE: "countdown_game_zone_player_hide", }, - THINK_INTERVAL: 0.1, + THINK_INTERVAL: 0.1, // 更新间隔(秒) ZERO_DISPLAY_TIME: 0.5 // 0 显示多久后消失(秒) }; // 文本模板 const TEMPLATES = { - endin: "{time}秒内结束战斗", + pushin: "随机推力{time}", flykill: "{time}秒后禁飞", knifefight: "{time}秒后用刀决战!!!", nukeboom: "{time}秒后核弹降临", @@ -172,7 +172,7 @@ Instance.OnScriptInput("stop", CountdownManager.stop); // 预设倒计时 [ - "endin_30", + "pushin_5", "flykill_30", "knifefight_30", "nukeboom_120", diff --git a/2001/ze_maontain_escape/gt.js b/2001/ze_maontain_escape/gt.js new file mode 100644 index 0000000..606dba7 --- /dev/null +++ b/2001/ze_maontain_escape/gt.js @@ -0,0 +1,132 @@ +import { Instance, CSInputs } from "cs_script/point_script"; + +function vec(x, y, z) { return { x, y, z }; } +function add(v1, v2) { return { x: v1.x + v2.x, y: v1.y + v2.y, z: v1.z + v2.z }; } +function scale(v, s) { return { x: v.x * s, y: v.y * s, z: v.z * s }; } +function len3(v) { return Math.hypot(v.x, v.y, v.z); } +function fwd(a) { + const p = (a.pitch * Math.PI) / 180; + const y = (a.yaw * Math.PI) / 180; + const h = Math.cos(p); + return { x: Math.cos(y) * h, y: Math.sin(y) * h, z: -Math.sin(p) }; +} +function right(a) { + const y = (a.yaw * Math.PI) / 180; + return { x: Math.cos(y + Math.PI/2), y: Math.sin(y + Math.PI/2), z: 0 }; +} +function print(text) { Instance.Msg(text); } +function fireT(target, input, val, delay, caller, activator) { + Instance.EntFireAtTarget({ target, input, value: val, caller, activator, delay }); +} + +const CONFIG = { + MOVE: { + MAX_SPEED: 300, + ACCEL_TIME: 0.3, + DAMPING: 0.8, + DURATION: 10.0 + }, + THINK_DELAY: 0.1 +}; + +const skillData = new Map(); // key: pawn, value: { endTime, velFwd, velRight } + +function isSkillActive(pawn) { + const data = skillData.get(pawn); + return data && Instance.GetGameTime() < data.endTime; +} + +function activateSkill(pawn) { + if (!pawn || !pawn.IsValid()) return false; + if (isSkillActive(pawn)) return false; + + fireT(pawn, "keyvalues", "gravity 0", 0); + let vel = pawn.GetAbsVelocity(); + vel.z = 200; + pawn.Teleport(undefined, undefined, vel); + fireT(pawn, "keyvalues", "gravity 1", CONFIG.MOVE.DURATION); + + skillData.set(pawn, { + endTime: Instance.GetGameTime() + CONFIG.MOVE.DURATION, + velFwd: vec(0, 0, 0), + velRight: vec(0, 0, 0) + }); + return true; +} + +function deactivateSkill(pawn) { + if (skillData.has(pawn)) { + skillData.delete(pawn); + } +} + +function updateMovement(pawn) { + const data = skillData.get(pawn); + if (!data) return; + const now = Instance.GetGameTime(); + if (now >= data.endTime) { + deactivateSkill(pawn); + return; + } + if (!pawn.IsValid() || !pawn.IsAlive()) { + deactivateSkill(pawn); + return; + } + + const angles = pawn.GetEyeAngles(); + const forward = fwd(angles); + const rightVec = right(angles); + const delta = CONFIG.THINK_DELAY; + const maxSpeed = CONFIG.MOVE.MAX_SPEED; + const accel = maxSpeed / CONFIG.MOVE.ACCEL_TIME; + + let fwdInput = 0; + if (pawn.IsInputPressed(CSInputs.FORWARD)) fwdInput = 1; + else if (pawn.IsInputPressed(CSInputs.BACK)) fwdInput = -1; + + let rightInput = 0; + if (pawn.IsInputPressed(CSInputs.LEFT)) rightInput = 1; + else if (pawn.IsInputPressed(CSInputs.RIGHT)) rightInput = -1; + + if (fwdInput !== 0) { + const accelVec = scale(forward, accel * delta * fwdInput); + data.velFwd = add(data.velFwd, accelVec); + const speed = len3(data.velFwd); + if (speed > maxSpeed) data.velFwd = scale(data.velFwd, maxSpeed / speed); + } else { + data.velFwd = scale(data.velFwd, CONFIG.MOVE.DAMPING); + if (len3(data.velFwd) < 0.01) data.velFwd = vec(0, 0, 0); + } + + if (rightInput !== 0) { + const accelVec = scale(rightVec, accel * delta * rightInput); + data.velRight = add(data.velRight, accelVec); + const speed = len3(data.velRight); + if (speed > maxSpeed) data.velRight = scale(data.velRight, maxSpeed / speed); + } else { + data.velRight = scale(data.velRight, CONFIG.MOVE.DAMPING); + if (len3(data.velRight) < 0.01) data.velRight = vec(0, 0, 0); + } + + const finalVel = add(data.velFwd, data.velRight); + pawn.Teleport(undefined, undefined, finalVel); +} + +let lastThinkTime = 0; +function think() { + const now = Instance.GetGameTime(); + lastThinkTime = now; + for (let [pawn] of skillData) updateMovement(pawn); + Instance.SetNextThink(now + CONFIG.THINK_DELAY); +} + +Instance.SetThink(think); +Instance.SetNextThink(Instance.GetGameTime() + CONFIG.THINK_DELAY); + +Instance.OnScriptInput("gt_shift", ({ activator }) => { + if (!activator || !activator.IsValid()) return; + let pawn = activator; + if (pawn.GetPlayerPawn) pawn = pawn.GetPlayerPawn(); + if (!pawn || !pawn.IsValid()) return; + activateSkill(pawn); +}); \ No newline at end of file diff --git a/2001/ze_maontain_escape/jk.js b/2001/ze_maontain_escape/jk.js new file mode 100644 index 0000000..1936211 --- /dev/null +++ b/2001/ze_maontain_escape/jk.js @@ -0,0 +1,338 @@ +import { Instance, CSInputs } from "cs_script/point_script"; + +var jk_maxhp = 25; // 剑客血量 +const MARK_RADIUS = 384; // 范围 +const MARK_HEALTH_THRESHOLD = 10000; // 斩杀血量 +const MARK_DELAY = 1; // 标记时间 +const DASH_TIME = 0.5; // 冲刺时间 +const COOLDOWN_DURATION = 2; // 斩杀冷却时间(秒) +var jk_dmg = [4000,12000] // 伤害,[左键,右键] + +function vec(x, y, z) { return { x, y, z }; } +function ang(p, y, r) { return { pitch: p, yaw: y, roll: r }; } +function len3(v) { return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } +function len2(v) { return Math.sqrt(v.x * v.x + v.y * v.y); } +function sub(v1, v2) { return { x: v1.x - v2.x, y: v1.y - v2.y, z: v1.z - v2.z }; } +function add(v1, v2) { return { x: v1.x + v2.x, y: v1.y + v2.y, z: v1.z + v2.z }; } +function scale(v, s) { return { x: v.x * s, y: v.y * s, z: v.z * s }; } +function fwd(a) { + const p = (a.pitch * Math.PI) / 180; + const y = (a.yaw * Math.PI) / 180; + const h = Math.cos(p); + return { x: Math.cos(y) * h, y: Math.sin(y) * h, z: -Math.sin(p) }; +} +function dot(a, b) { return a.x * b.x + a.y * b.y + a.z * b.z; } + +function print(text) { Instance.Msg(text); } +function fire(name, input = "", val = "", delay = 0, caller, activator) { + Instance.EntFireAtName({ name, input, value: val, caller, activator, delay }); +} +function fireT(target, input = "", val = "", delay = 0, caller, activator) { + Instance.EntFireAtTarget({ target, input, value: val, caller, activator, delay }); +} +function find(name) { return Instance.FindEntityByName(name); } +function findAll(name) { return Instance.FindEntitiesByName(name); } +function findByClass(cls) { return Instance.FindEntitiesByClass(cls); } + +function setPlayerColor(player, r, g, b, a = 255) { + if (player && player.IsValid()) { + player.SetColor({ r, g, b, a }); + } +} + +var jk_hp = jk_maxhp; +var jk = undefined; +var mmfix = undefined; + +const ARRIVE_DIST = 100; +const FOV_DEG = 12; +const FOV_COS = Math.cos(FOV_DEG * Math.PI / 180); + +let targetStates = new Map(); + +let dashing = false; +let dashTarget = undefined; +let dashVelocity = undefined; + +let charging = false; +let chargeTarget = undefined; +let chargeStartTime = 0; + +let thinkStarted = false; +let lastExecutionTime = 0; + +Instance.OnScriptInput("jk_reset", ({}) => { + let allplayer = findByClass("player"); + for (const p of allplayer) { + setPlayerColor(p, 255, 255, 255, 255); + } + targetStates.clear(); + jk = undefined; + jk_hp = jk_maxhp; + dashing = false; + dashTarget = undefined; + dashVelocity = undefined; + charging = false; + chargeTarget = undefined; + lastExecutionTime = 0; +}); + +Instance.OnScriptInput("jk_getitem", ({ caller,activator }) => { + jk = activator; + let ml = findByClass("func_movelinear") + for(const m of ml){ + if(len2(sub(m.GetAbsOrigin(),caller.GetAbsOrigin())) <= 32){ + mmfix = m + } + } + if(!mmfix){print("error")} + if (!thinkStarted) { + thinkStarted = true; + Instance.SetThink(think); + Instance.SetNextThink(Instance.GetGameTime() + 0.1); + } +}); + +Instance.OnScriptInput("jk_atk1", ({activator}) => { + if ( activator && activator.IsValid() && activator.IsAlive()){ + activator.TakeDamage({ damage: jk_dmg[0], attacker: jk, inflictor: jk }); + } +}); + +Instance.OnScriptInput("jk_atk2", ({activator}) => { + if ( activator && activator.IsValid() && activator.IsAlive()){ + activator.TakeDamage({ damage: jk_dmg[1], attacker: jk, inflictor: jk }); + } +}); + +Instance.OnScriptInput("jk_gethit", ({}) => { + jk_hp--; + if (jk_hp <= 0) { + jk_hp = 0; + fireT(jk, "keyvalues", "targetname ", 0); + fireT(jk, "alpha", "255"); + fireT(jk, "sethealth", "-1", 0); + fireT(mmfix, "fireuser1"); + jk = undefined; + } else { + jk.SetHealth(jk_hp * 1000); + } +}); + +Instance.OnScriptInput("jk_gethit_gt1", ({ activator }) => { + if (activator !== jk) return; + + jk_hp -= 3; + if (jk_hp <= 0) { + jk_hp = 0; + fireT(jk, "keyvalues", "targetname ", 0); + fireT(jk, "alpha", "255"); + fireT(jk, "sethealth", "-1", 0); + fireT(mmfix, "fireuser1"); + jk = undefined; + } else { + jk.SetHealth(jk_hp * 1000); + } +}); + +Instance.OnScriptInput("jk_gethit_gt2", ({ activator }) => { + if (activator !== jk) return; + + jk_hp -= 8; + if (jk_hp <= 0) { + jk_hp = 0; + fireT(jk, "keyvalues", "targetname ", 0); + fireT(jk, "alpha", "255"); + fireT(jk, "sethealth", "-1", 0); + fireT(mmfix, "fireuser1"); + jk = undefined; + } else { + jk.SetHealth(jk_hp * 1000); + } +}); + + +Instance.OnScriptInput("jk_dash", ({}) => { + if (!jk) return; + const angles = jk.GetEyeAngles(); + const dir = fwd(angles); + let vel = scale(dir, 500); + if (Math.abs(angles.pitch) < 15) { + vel.z += 150; + } + jk.Teleport({ velocity: vel }); +}); + +function think() { + const now = Instance.GetGameTime(); + + if (!jk || !jk.IsValid() || jk.GetTeamNumber() === 2) { + for (let [target, state] of targetStates) { + if (target.IsValid()) setPlayerColor(target, 255, 255, 255); + } + targetStates.clear(); + dashing = false; + dashTarget = undefined; + dashVelocity = undefined; + charging = false; + chargeTarget = undefined; + jk = undefined; + Instance.SetNextThink(now + 0.1); + return; + } + + if (dashing && dashTarget && dashTarget.IsValid() && dashTarget.IsAlive()) { + const jkPos = jk.GetAbsOrigin(); + const targetPos = dashTarget.GetAbsOrigin(); + const dirToTarget = sub(targetPos, jkPos); + const dist = len3(dirToTarget); + + if (dist < ARRIVE_DIST) { + fireT(mmfix, "fireuser2", "", 0, undefined, jk); + dashTarget.TakeDamage({ damage: 1000000, attacker: jk, inflictor: jk }); + dashing = false; + dashTarget = undefined; + dashVelocity = undefined; + } else { + dashTarget.Teleport({ velocity: vec(0, 0, 0) }); + if (dashVelocity) jk.Teleport({ velocity: dashVelocity }); + } + } else if (dashing) { + fireT(mmfix, "fireuser2", "", 0, undefined, jk); + dashing = false; + dashTarget = undefined; + dashVelocity = undefined; + } + + if (charging) { + if (!chargeTarget || !chargeTarget.IsValid() || !chargeTarget.IsAlive()) { + targetStates.delete(chargeTarget); + fireT(mmfix, "fireuser2", "", 0, undefined, jk); + charging = false; + chargeTarget = undefined; + } else { + jk.Teleport({ velocity: vec(0, 0, 0) }); + chargeTarget.Teleport({ velocity: vec(0, 0, 0) }); + + const elapsed = now - chargeStartTime; + if (elapsed >= 0.5) { + const jkPos = jk.GetAbsOrigin(); + const targetPos = chargeTarget.GetAbsOrigin(); + const dir = sub(targetPos, jkPos); + const dist = len3(dir); + if (dist >= 1) { + const normDir = scale(dir, 1 / dist); + const speed = dist / DASH_TIME; + dashVelocity = scale(normDir, speed); + } else { + dashVelocity = vec(0, 0, 0); + } + + dashing = true; + dashTarget = chargeTarget; + dashTarget.Teleport({ velocity: vec(0, 0, 0) }); + jk.Teleport({ velocity: dashVelocity }); + + fireT(mmfix, "fireuser3", "", 0, undefined, jk); + + setPlayerColor(chargeTarget, 255, 255, 255); + targetStates.delete(chargeTarget); + + charging = false; + chargeTarget = undefined; + } + } + } + + if (!dashing && !charging && jk && jk.IsValid()) { + const jkPos = jk.GetAbsOrigin(); + + const players = findByClass("player"); + const currentTargets = new Set(); + + for (const p of players) { + if (p.GetTeamNumber() === 2 && p.IsAlive()) { + const dist = len3(sub(p.GetAbsOrigin(), jkPos)); + if (dist <= MARK_RADIUS && p.GetHealth() < MARK_HEALTH_THRESHOLD) { + currentTargets.add(p); + if (!targetStates.has(p)) { + targetStates.set(p, { startTime: now, marked: false }); + } + } + } + } + + for (let [target, state] of targetStates) { + if (!currentTargets.has(target) || !target.IsValid() || !target.IsAlive()) { + setPlayerColor(target, 255, 255, 255); + targetStates.delete(target); + } + } + + for (let [target, state] of targetStates) { + if (!state.marked) { + const elapsed = now - state.startTime; + if (elapsed >= MARK_DELAY) { + state.marked = true; + setPlayerColor(target, 255, 0, 0); + } else { + const progress = elapsed / MARK_DELAY; + const gb = Math.floor(255 * (1 - progress)); + setPlayerColor(target, 255, gb, gb); + } + } + } + if (jk.WasInputJustPressed(CSInputs.LOOK_AT_WEAPON)) { + if (now - lastExecutionTime < COOLDOWN_DURATION) { + } else { + const eyeAng = jk.GetEyeAngles(); + const forward = fwd(eyeAng); + let bestTarget = null; + let bestDot = -1; + + const allButtons = Instance.FindEntitiesByClass("func_button"); + + for (let [target, state] of targetStates) { + if (!state.marked) continue; + if (!target.IsValid() || !target.IsAlive()) continue; + + // 视线检测 + const start = jk.GetEyePosition(); + const end = target.GetEyePosition(); + const ignoreList = [jk, target, ...allButtons]; + const traceResult = Instance.TraceLine({ + start, + end, + ignoreEntity: ignoreList, + ignorePlayers: false, + traceHitboxes: true + }); + if (traceResult.didHit && traceResult.hitEntity !== undefined) { + continue; // 被遮挡 + } + + const dir = sub(target.GetAbsOrigin(), jkPos); + const dist = len3(dir); + if (dist < 1) continue; + const normDir = scale(dir, 1 / dist); + const d = dot(forward, normDir); + if (d >= FOV_COS && d > bestDot) { + bestDot = d; + bestTarget = target; + } + } + + if (bestTarget) { + charging = true; + chargeTarget = bestTarget; + chargeStartTime = now; + jk.Teleport({ velocity: vec(0, 0, 0) }); + fireT(mmfix, "fireuser4", "", 0, undefined, jk); + lastExecutionTime = now; + } + } + } + } + + Instance.SetNextThink(now + 0.1); +} \ No newline at end of file diff --git a/2001/ze_maontain_escape/llt.js b/2001/ze_maontain_escape/llt.js new file mode 100644 index 0000000..e8d88ee --- /dev/null +++ b/2001/ze_maontain_escape/llt.js @@ -0,0 +1,132 @@ +import { Instance, CSInputs } from "cs_script/point_script"; + +var llt_maxhp = 30; // 血量 +var llt_dmg = [4000,15000,10000] // 伤害,[左键,右键和大招,剑气] + +function vec(x, y, z) { return { x, y, z }; } +function ang(p, y, r) { return { pitch: p, yaw: y, roll: r }; } +function len3(v) { return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } +function len2(v) { return Math.sqrt(v.x * v.x + v.y * v.y); } +function sub(v1, v2) { return { x: v1.x - v2.x, y: v1.y - v2.y, z: v1.z - v2.z }; } +function add(v1, v2) { return { x: v1.x + v2.x, y: v1.y + v2.y, z: v1.z + v2.z }; } +function scale(v, s) { return { x: v.x * s, y: v.y * s, z: v.z * s }; } +function fwd(a) { + const p = (a.pitch * Math.PI) / 180; + const y = (a.yaw * Math.PI) / 180; + const h = Math.cos(p); + return { x: Math.cos(y) * h, y: Math.sin(y) * h, z: -Math.sin(p) }; +} +function dot(a, b) { return a.x * b.x + a.y * b.y + a.z * b.z; } + +function print(text) { Instance.Msg(text); } +function fire(name, input = "", val = "", delay = 0, caller, activator) { + Instance.EntFireAtName({ name, input, value: val, caller, activator, delay }); +} +function fireT(target, input = "", val = "", delay = 0, caller, activator) { + Instance.EntFireAtTarget({ target, input, value: val, caller, activator, delay }); +} +function find(name) { return Instance.FindEntityByName(name); } +function findAll(name) { return Instance.FindEntitiesByName(name); } +function findByClass(cls) { return Instance.FindEntitiesByClass(cls); } + +function setPlayerColor(player, r, g, b, a = 255) { + if (player && player.IsValid()) { + player.SetColor({ r, g, b, a }); + } +} + +var llt_hp = llt_maxhp; +var llt = undefined; +var mmfix = undefined; + +Instance.OnScriptInput("llt_getitem", ({ caller,activator }) => { + llt = activator; + let ml = findByClass("func_movelinear") + for(const m of ml){ + if(len2(sub(m.GetAbsOrigin(),caller.GetAbsOrigin())) <= 32){ + mmfix = m + } + } + if(!mmfix){print("error")} +}); + +Instance.OnScriptInput("llt_atk1", ({activator}) => { + if ( activator && activator.IsValid() && activator.IsAlive()){ + activator.TakeDamage({ damage: llt_dmg[0], attacker: llt, inflictor: llt }); + } +}); + +Instance.OnScriptInput("llt_atk2", ({activator}) => { + if ( activator && activator.IsValid() && activator.IsAlive()){ + activator.TakeDamage({ damage: llt_dmg[1], attacker: llt, inflictor: llt }); + } +}); + +var ult = undefined + +Instance.OnScriptInput("llt_ult_spawn", ({caller}) => { + let player = findByClass("player") + for(const p of player){if(len3(sub(p.GetEyePosition(),caller.GetAbsOrigin()))<4){ult = p}} +}); + +Instance.OnScriptInput("llt_ult_atk", ({activator}) => { + if ( activator && activator.IsValid() && activator.IsAlive()){ + activator.TakeDamage({ damage: llt_dmg[2], attacker: ult, inflictor: ult }); + fireT(activator,"keyvalues","speed 0.5",0) + fireT(activator,"keyvalues","speed 1",3) + } +}); + +Instance.OnScriptInput("llt_gethit", ({}) => { + llt_hp--; + if (llt_hp <= 0) { + llt_hp = 0; + fireT(llt, "keyvalues", "targetname ", 0); + fireT(llt, "alpha", "255"); + fireT(llt, "sethealth", "-1", 0); + fireT(mmfix, "fireuser1"); + llt = undefined; + } else { + llt.SetHealth(llt_hp * 1000); + } +}); + +Instance.OnScriptInput("llt_gethit_gt1", ({ activator }) => { + if (activator !== llt) return; + + llt_hp -= 3; + if (llt_hp <= 0) { + llt_hp = 0; + fireT(llt, "keyvalues", "targetname ", 0); + fireT(llt, "alpha", "255"); + fireT(llt, "sethealth", "-1", 0); + fireT(mmfix, "fireuser1"); + llt = undefined; + } else { + llt.SetHealth(llt_hp * 1000); + } +}); + +Instance.OnScriptInput("llt_gethit_gt2", ({ activator }) => { + if (activator !== llt) return; + + llt_hp -= 8; + if (llt_hp <= 0) { + llt_hp = 0; + fireT(llt, "keyvalues", "targetname ", 0); + fireT(llt, "alpha", "255"); + fireT(llt, "sethealth", "-1", 0); + fireT(mmfix, "fireuser1"); + llt = undefined; + } else { + llt.SetHealth(llt_hp * 1000); + } +}); + +Instance.OnScriptInput("llt_s1", ({ activator }) => { + find("llt_ult_temp0").ForceSpawn(activator.GetEyePosition(),activator.GetEyeAngles()) +}); + +Instance.OnScriptInput("llt_s2", ({ activator }) => { + find("llt_ult_temp1").ForceSpawn(activator.GetEyePosition(),activator.GetEyeAngles()) +}); \ No newline at end of file diff --git a/2001/ze_maontain_escape/move.js b/2001/ze_maontain_escape/move.js new file mode 100644 index 0000000..3628495 --- /dev/null +++ b/2001/ze_maontain_escape/move.js @@ -0,0 +1,106 @@ +import { Instance } from "cs_script/point_script"; + +/* ===================== 配置 ===================== */ +const CONFIG = { + moveDamagePerSecond: 1, + idleHealPerSecond: 2, + checkInterval: 0.3, + disabledInterval: 2.0, // 关闭状态下降频 + maxHealth: 125, + minMoveSpeed: 100.0 +}; + +const MOVE_THRESHOLD_SQ = + (CONFIG.minMoveSpeed * CONFIG.checkInterval) * + (CONFIG.minMoveSpeed * CONFIG.checkInterval); + +/* ===================== 状态 ===================== */ +let ENABLED = false; +const lastPositions = new Map(); + +/* ===================== Script Input ===================== */ +Instance.OnScriptInput("enable", () => { + ENABLED = true; +}); + +Instance.OnScriptInput("disable", () => { + ENABLED = false; + lastPositions.clear(); +}); + +/* ===================== 主循环 ===================== */ +function think() { + const now = Instance.GetGameTime(); + + if (!ENABLED) { + Instance.SetNextThink(now + CONFIG.disabledInterval); + return; + } + + for (let slot = 0; slot < 32; slot++) { + const controller = Instance.GetPlayerController(slot); + if (!controller || !controller.IsValid() || !controller.IsConnected()) { + continue; + } + + const pawn = controller.GetPlayerPawn(); + if (!pawn || !pawn.IsValid() || !pawn.IsAlive()) { + continue; + } + + const currentPos = pawn.GetAbsOrigin(); + const lastPos = lastPositions.get(slot); + + if (!lastPos) { + lastPositions.set(slot, currentPos); + continue; + } + + const dx = currentPos.x - lastPos.x; + const dy = currentPos.y - lastPos.y; + const dz = currentPos.z - lastPos.z; + + const distSq = dx * dx + dy * dy + dz * dz; + const isMoving = distSq > MOVE_THRESHOLD_SQ; + + if (isMoving) { + damageWithIOKill(pawn); + } else { + heal(pawn); + } + + lastPositions.set(slot, currentPos); + } + + Instance.SetNextThink(now + CONFIG.checkInterval); +} + +/* ===================== 行为函数 ===================== */ +function damageWithIOKill(pawn) { + const hp = pawn.GetHealth(); + if (hp <= 0) return; + + const nextHp = hp - CONFIG.moveDamagePerSecond; + + if (nextHp <= 0) { + Instance.EntFireAtTarget({ + target: pawn, + input: "SetHealth", + value: "-1" + }); + return; + } + + pawn.SetHealth(nextHp); +} + +function heal(pawn) { + const hp = pawn.GetHealth(); + if (hp <= 0 || hp >= CONFIG.maxHealth) return; + + pawn.SetHealth(hp + CONFIG.idleHealPerSecond); +} + +/* ===================== 启动 ===================== */ +Instance.SetThink(think); +Instance.SetNextThink(Instance.GetGameTime() + 0.1);