diff --git a/2001/ze_pretender/banana_trigger.js b/2001/ze_pretender/banana_trigger.js new file mode 100644 index 0000000..4c97213 --- /dev/null +++ b/2001/ze_pretender/banana_trigger.js @@ -0,0 +1,226 @@ +import { Instance } from "cs_script/point_script"; + + +const BANANA_TEMPLATE_NAME = "@banana_temp"; + +const bananaState = { + lastTriggerTime: 0, + cooldown: 1.0, + cachedTemplate: null, + lastCacheTime: 0 +}; + +const SLIDE_SPEED = 150; +const MIN_ANGULAR_SPEED = 270; +const MAX_ANGULAR_SPEED = 720; +const THINK_INTERVAL = 0.1; +const MAX_ACTIVE_PLAYERS = 8; + +const spinState = { + lastThinkTime: 0, + activePlayers: {}, +}; + +const _tempVelocity = { x: 0, y: 0, z: 0 }; +const _tempAngles = { pitch: 0, yaw: 0, roll: 0 }; + +const state = { + banana: bananaState, + spin: spinState, +}; + +function SpawnBananaNearActivator(activator) { + try { + if (!activator || !activator.IsValid() || !activator.IsAlive()) return false; + const currentTime = Instance.GetGameTime(); + if (currentTime - state.banana.lastCacheTime > 30 || !state.banana.cachedTemplate || !state.banana.cachedTemplate.IsValid()) { + state.banana.cachedTemplate = Instance.FindEntityByName(BANANA_TEMPLATE_NAME); + state.banana.lastCacheTime = currentTime; + } + const template = state.banana.cachedTemplate; + if (!template || !template.IsValid()) return false; + const origin = activator.GetAbsOrigin(); + const t = Math.random() * Math.PI * 2; + const r = Math.random() * 10; + const ents = template.ForceSpawn({ + x: origin.x + Math.cos(t) * r, + y: origin.y + Math.sin(t) * r, + z: origin.z + 15 + }, { pitch: 0, yaw: 0, roll: 0 }); + return !!(ents && ents.length > 0); + } catch (error) { + return false; + } +} + +function HandleBananaTrigger(inputData) { + try { + const currentTime = Instance.GetGameTime(); + if (currentTime - state.banana.lastTriggerTime < state.banana.cooldown) return; + state.banana.lastTriggerTime = currentTime; + SpawnBananaNearActivator(inputData && inputData.activator ? inputData.activator : null); + } catch (error) { + } +} + +function IsValidPawn(entity) { + try { + return entity && entity.IsValid && entity.IsValid() && entity.GetPlayerController; + } catch (e) { + return false; + } +} + +function GetPlayerSlotFromEntity(entity) { + try { + const controller = entity.GetPlayerController && entity.GetPlayerController(); + return controller ? controller.GetPlayerSlot() : undefined; + } catch (e) { + return undefined; + } +} + +function YawToHorizontalUnit(yawDeg) { + const yawRad = yawDeg / 180 * Math.PI; + return { x: Math.cos(yawRad), y: Math.sin(yawRad), z: 0 }; +} + +function RandomAngularSpeed() { + return MIN_ANGULAR_SPEED + Math.random() * (MAX_ANGULAR_SPEED - MIN_ANGULAR_SPEED); +} + +function ClampAngle360(a) { + let x = a % 360; + if (x < 0) x += 360; + return x; +} + +function StartSpinSlide(activator) { + try { + if (!IsValidPawn(activator) || !activator.IsAlive()) { + return; + } + const playerSlot = GetPlayerSlotFromEntity(activator); + if (playerSlot === undefined) { + return; + } + + if (!state.spin.activePlayers[playerSlot]) { + const ang = (typeof activator.GetEyeAngles === "function" ? activator.GetEyeAngles() : activator.GetAbsAngles()) || {}; + state.spin.activePlayers[playerSlot] = { + dir: YawToHorizontalUnit(ang.yaw !== undefined ? ang.yaw : 0), + angularSpeed: RandomAngularSpeed(), + yaw: ang.yaw !== undefined ? ang.yaw : 0, + basePitch: ang.pitch !== undefined ? ang.pitch : 0, + }; + } + } catch (e) { + } +} + +function StopSpinSlide(activator) { + try { + if (!IsValidPawn(activator)) { + return; + } + const playerSlot = GetPlayerSlotFromEntity(activator); + if (playerSlot === undefined) { + return; + } + delete state.spin.activePlayers[playerSlot]; + + const pawn = activator; + if (pawn && pawn.IsValid()) { + const currentVel = pawn.GetAbsVelocity(); + pawn.Teleport({ velocity: { x: 0, y: 0, z: currentVel.z } }); + } + } catch (e) { + } +} + +function StopAllSpinSlide() { + for (const key in state.spin.activePlayers) { + const playerSlot = Number(key); + const controller = Instance.GetPlayerController(playerSlot); + if (controller) { + const pawn = controller.GetPlayerPawn(); + if (pawn && pawn.IsValid()) { + const currentVel = pawn.GetAbsVelocity(); + pawn.Teleport({ velocity: { x: 0, y: 0, z: currentVel.z } }); + } + } + } + state.spin.activePlayers = {}; +} + +function UpdatePlayerMotion(dt) { + let processed = 0; + for (const key in state.spin.activePlayers) { + if (processed++ >= MAX_ACTIVE_PLAYERS) break; + const playerSlot = Number(key); + const motion = state.spin.activePlayers[playerSlot]; + const controller = Instance.GetPlayerController(playerSlot); + if (!controller) { + delete state.spin.activePlayers[playerSlot]; + continue; + } + const pawn = controller.GetPlayerPawn(); + if (!pawn || !pawn.IsValid() || !pawn.IsAlive()) { + delete state.spin.activePlayers[playerSlot]; + continue; + } + + motion.yaw = ClampAngle360(motion.yaw + motion.angularSpeed * dt); + + _tempAngles.pitch = motion.basePitch; + _tempAngles.yaw = motion.yaw; + _tempAngles.roll = 0; + + const currentVel = pawn.GetAbsVelocity(); + _tempVelocity.x = motion.dir.x * SLIDE_SPEED; + _tempVelocity.y = motion.dir.y * SLIDE_SPEED; + _tempVelocity.z = currentVel.z; + + pawn.Teleport({ angles: _tempAngles, velocity: _tempVelocity }); + } +} + +function ScriptThink() { + const now = Instance.GetGameTime(); + const dt = state.spin.lastThinkTime > 0 ? Math.max(0, now - state.spin.lastThinkTime) : THINK_INTERVAL; + state.spin.lastThinkTime = now; + + try { + UpdatePlayerMotion(dt); + } catch (e) { + } + + Instance.SetNextThink(now + THINK_INTERVAL); +} + +function Init() { + state.spin.lastThinkTime = Instance.GetGameTime(); +} + +Instance.OnScriptInput("banana", HandleBananaTrigger); + +Instance.OnScriptInput("spin_start", (inputData) => { + StartSpinSlide(inputData.activator); +}); + +Instance.OnScriptInput("spin_stop", (inputData) => { + StopSpinSlide(inputData.activator); +}); + +Instance.OnActivate(() => { + Init(); +}); + +Instance.OnScriptReload({ + after: () => { + Init(); + } +}); + +Instance.SetThink(ScriptThink); +Instance.SetNextThink(THINK_INTERVAL); diff --git a/2001/ze_pretender/boss_move.js b/2001/ze_pretender/boss_move.js new file mode 100644 index 0000000..6fc90e9 --- /dev/null +++ b/2001/ze_pretender/boss_move.js @@ -0,0 +1,850 @@ +// @ts-nocheck +import { Instance } from "cs_script/point_script"; +const CT_TEAM = 3; +const T_TEAM = 2; +const RAD_TO_DEG = 180 / Math.PI; +const NPC_MOVE_CONFIG = { + TICKRATE_IDLE: 0.5, + TICKRATE_ACTIVE: 0.1, + TARGET_DISTANCE: 3000, + TARGET_TIME: 5, + FORWARD_TIMEOUT: 0.02, + FRONT_ANGLE: 3, + + CHASE_DISTANCE: 2500, + + FORWARD_SPEED: 1200, + CHASE_SPEED: 1000, + STOP_SPEED_THRESHOLD: 50, + + ACCELERATION: 1500, + DECELERATION: 1200, + + TURN_SPEED: 360, + + MIN_SPEED: 250 +}; +const DASH_CONFIG = { + WINDUP_TIME: 0.8, + DASH_DURATION: 0.5, + COOLDOWN_TIME: 2.5, + DASH_SPEED: 1800, + STOP_DISTANCE: 150, + MIN_DASH_DISTANCE: 400, + MAX_DASH_DISTANCE: 1500 +}; +const DashState = { +IDLE: 0, +WINDUP: 1, +DASHING: 2, +COOLDOWN: 3 +}; +function AddVector(a, b) { +return { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z }; +} +function Distance3D(a, b) { +const dx = a.x - b.x; +const dy = a.y - b.y; +const dz = a.z - b.z; +return Math.sqrt(dx * dx + dy * dy + dz * dz); +} +function ForwardFromAngles(angles) { +const pitch = (angles.pitch / 180) * Math.PI; +const yaw = (angles.yaw / 180) * Math.PI; +const cosPitch = Math.cos(pitch); +return { + x: cosPitch * Math.cos(yaw), + y: cosPitch * Math.sin(yaw), + z: -Math.sin(pitch) +}; +} +function WrapDegrees(degrees) { +return ((degrees + 180) % 360 + 360) % 360 - 180; +} +function TraceObstacleAhead(self, origin, forward, distance) { +const result = Instance.TraceSphere({ + radius: 16, + start: origin, + end: AddVector(origin, { x: forward.x * distance, y: forward.y * distance, z: forward.z * distance }), + ignoreEntity: self, + ignorePlayers: true +}); +return result.didHit; +} +function CanSee(start, end, self, target) { +const line = Instance.TraceLine({ + start, + end, + ignoreEntity: self +}); +if (!line.didHit || line.hitEntity === target) { + return true; +} +const hitDistToTarget = Distance3D(line.end, end); +if (hitDistToTarget > 16) { + return false; +} +const sphere = Instance.TraceSphere({ + radius: 4, + start, + end, + ignoreEntity: self +}); +return !sphere.didHit || sphere.hitEntity === target; +} +function CanSeeAnyPoint(start, points, self, target) { +for (const end of points) { + if (CanSee(start, end, self, target)) { + return true; + } +} +return false; +} +class BossMover { +constructor(entity) { + this.entity = entity; + this.target = undefined; + this.targetTime = 0; + this.nextTickAt = 0; + this.dashState = DashState.IDLE; + this.dashTarget = undefined; + this.dashEndTime = 0; + this.dashCooldownEndTime = 0; + this.dashWindupStartTime = 0; + this.speedMultiplier = 1.0; +} +SetSpeedMultiplier(multiplier) { + this.speedMultiplier = multiplier; +} +IsValid() { + return this.entity && this.entity.IsValid(); +} +FindTarget() { + const selfOrigin = this.entity.GetAbsOrigin(); + const eyeFrom = AddVector(selfOrigin, { x: 0, y: 0, z: 80 }); + const players = Instance.FindEntitiesByClass("player"); + const candidates = []; + for (const p of players) { + if (!p || !p.IsValid()) { + continue; + } + if (p.GetTeamNumber() !== CT_TEAM || p.GetHealth() <= 0) { + continue; + } + const pOrigin = p.GetAbsOrigin(); + if (Distance3D(selfOrigin, pOrigin) > NPC_MOVE_CONFIG.TARGET_DISTANCE) { + continue; + } + const samplePoints = [ + AddVector(pOrigin, { x: 0, y: 0, z: 64 }), + AddVector(pOrigin, { x: 0, y: 0, z: 38 }), + AddVector(pOrigin, { x: 0, y: 0, z: 10 }) + ]; + if (CanSeeAnyPoint(eyeFrom, samplePoints, this.entity, p)) { + candidates.push(p); + } + } + if (candidates.length === 0) { + return undefined; + } + return candidates[Math.floor(Math.random() * candidates.length)]; +} +Tick(now) { + if (!this.IsValid()) { + return false; + } +if (this.dashState === DashState.WINDUP) { + const elapsed = now - this.dashWindupStartTime; + if (elapsed >= DASH_CONFIG.WINDUP_TIME) { + this.StartDash(); + } + this.nextTickAt = now + 0.1; + return true; + } + if (this.dashState === DashState.DASHING) { + if (now >= this.dashEndTime) { + this.EndDash(); + } else { + this.UpdateDashMovement(); + } + this.nextTickAt = now + 0.1; + return true; + } +if (this.dashState === DashState.COOLDOWN) { + if (now >= this.dashCooldownEndTime) { + this.dashState = DashState.IDLE; + Instance.EntFireAtName({ + name: "chief_hurt_tr", + input: "Enable", + delay: 0 + }); + } + this.nextTickAt = now + 0.1; + return true; +} + const self = this.entity; + const angle = self.GetAbsAngles(); + if (angle.pitch > 75 || angle.pitch < -75) { + self.Teleport({ angles: { pitch: 0, yaw: angle.yaw, roll: angle.roll } }); + } + if (!this.target || !this.target.IsValid() || this.target.GetTeamNumber() !== CT_TEAM || this.target.GetHealth() <= 0) { + this.target = this.FindTarget(); + this.targetTime = 0; + } + if (!this.target) { + this.nextTickAt = now + NPC_MOVE_CONFIG.TICKRATE_IDLE; + return true; + } + const selfOrigin = self.GetAbsOrigin(); + const selfVelocity = self.GetAbsVelocity(); + const selfAngles = self.GetAbsAngles(); + const targetOrigin = this.target.GetAbsOrigin(); + const dx = targetOrigin.x - selfOrigin.x; + const dy = targetOrigin.y - selfOrigin.y; + const dz = targetOrigin.z - selfOrigin.z; + const distToTarget = Math.sqrt(dx * dx + dy * dy + dz * dz); + const absYaw = Math.atan2(dy, dx) * RAD_TO_DEG; + const targetYaw = absYaw; + const currentForward = ForwardFromAngles(selfAngles); + const dirX = dx / distToTarget; + const dirY = dy / distToTarget; + const forward = { x: dirX, y: dirY, z: currentForward.z }; + + let targetSpeed = 0; + + if (distToTarget <= NPC_MOVE_CONFIG.CHASE_DISTANCE) { + const t = Math.min(1, distToTarget / NPC_MOVE_CONFIG.CHASE_DISTANCE); + const smoothT = t * t * (3 - 2 * t); + targetSpeed = NPC_MOVE_CONFIG.FORWARD_SPEED * (0.5 + 0.5 * smoothT) * this.speedMultiplier; + } else { + targetSpeed = NPC_MOVE_CONFIG.CHASE_SPEED * this.speedMultiplier; + } + + if (TraceObstacleAhead(self, selfOrigin, forward, 100) && distToTarget < 300) { + targetSpeed *= 0.3; + } + + let moveSpeed = 0; + const currentSpeed = Math.sqrt(selfVelocity.x * selfVelocity.x + selfVelocity.y * selfVelocity.y); + + if (targetSpeed > currentSpeed) { + const accelRate = Math.min(1, NPC_MOVE_CONFIG.ACCELERATION * NPC_MOVE_CONFIG.TICKRATE_ACTIVE / Math.max(1, targetSpeed - currentSpeed)); + moveSpeed = currentSpeed + (targetSpeed - currentSpeed) * accelRate; + } else { + const decelRate = Math.min(1, NPC_MOVE_CONFIG.DECELERATION * NPC_MOVE_CONFIG.TICKRATE_ACTIVE / Math.max(1, currentSpeed - targetSpeed)); + moveSpeed = currentSpeed - (currentSpeed - targetSpeed) * decelRate; + } + + if (targetSpeed > 0 && moveSpeed < NPC_MOVE_CONFIG.MIN_SPEED) { + moveSpeed = NPC_MOVE_CONFIG.MIN_SPEED; + } + + const newVelocityZ = selfVelocity.z; + + self.Teleport({ + position: null, + velocity: { x: forward.x * moveSpeed, y: forward.y * moveSpeed, z: newVelocityZ }, + angles: { pitch: 0, yaw: targetYaw, roll: selfAngles.roll }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + this.targetTime += NPC_MOVE_CONFIG.TICKRATE_ACTIVE; + if (this.targetTime >= NPC_MOVE_CONFIG.TARGET_TIME) { + this.target = undefined; + this.targetTime = 0; + } + this.nextTickAt = now + NPC_MOVE_CONFIG.TICKRATE_ACTIVE; + return true; +} +StartDash() { + this.dashState = DashState.DASHING; + const now = Instance.GetGameTime(); + this.dashEndTime = now + DASH_CONFIG.DASH_DURATION; + Instance.EntFireAtName({ + name: "chief_model", + input: "SetAnimationNotLooping", + value: "Chief_dash", + delay: 0 + }); + Instance.EntFireAtName({ + name: "chief_push", + input: "Enable", + delay: 0 + }); + Instance.EntFireAtName({ + name: "chief_hurt", + input: "Enable", + delay: 0 + }); +} +EndDash() { + this.dashState = DashState.COOLDOWN; + const now = Instance.GetGameTime(); + this.dashCooldownEndTime = now + DASH_CONFIG.COOLDOWN_TIME; + this.entity.Teleport({ + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + Instance.EntFireAtName({ + name: "chief_push", + input: "Disable", + delay: 0 + }); + Instance.EntFireAtName({ + name: "chief_hurt", + input: "Disable", + delay: 0 + }); +} +UpdateDashMovement() { + if (!this.dashTarget || !this.dashTarget.IsValid()) { + this.EndDash(); + return; + } + const selfOrigin = this.entity.GetAbsOrigin(); + const targetOrigin = this.dashTarget.GetAbsOrigin(); + const dx = targetOrigin.x - selfOrigin.x; + const dy = targetOrigin.y - selfOrigin.y; + const dz = targetOrigin.z - selfOrigin.z; + const distance = Math.sqrt(dx * dx + dy * dy + dz * dz); + if (distance < DASH_CONFIG.STOP_DISTANCE) { + this.EndDash(); + return; + } + const dirX = dx / distance; + const dirY = dy / distance; + const targetYaw = Math.atan2(dy, dx) * RAD_TO_DEG; + this.entity.Teleport({ + position: null, + velocity: { x: dirX * DASH_CONFIG.DASH_SPEED * this.speedMultiplier, y: dirY * DASH_CONFIG.DASH_SPEED * this.speedMultiplier, z: 0 }, + angles: { pitch: 0, yaw: targetYaw, roll: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); +} +CanStartDash() { + if (this.dashState !== DashState.IDLE) { + return false; + } + if (!this.target || !this.target.IsValid()) { + return false; + } + const selfOrigin = this.entity.GetAbsOrigin(); + const targetOrigin = this.target.GetAbsOrigin(); + const dx = targetOrigin.x - selfOrigin.x; + const dy = targetOrigin.y - selfOrigin.y; + const dz = targetOrigin.z - selfOrigin.z; + const distance = Math.sqrt(dx * dx + dy * dy + dz * dz); + + if (distance < DASH_CONFIG.MIN_DASH_DISTANCE || distance > DASH_CONFIG.MAX_DASH_DISTANCE) { + return false; + } + return true; +} +TriggerDash() { + if (!this.CanStartDash()) { + return false; + } + this.dashTarget = this.target; + if (!this.dashTarget) { + return false; + } + this.dashState = DashState.WINDUP; + this.dashWindupStartTime = Instance.GetGameTime(); + Instance.EntFireAtName({ + name: "chief_hurt_tr", + input: "Disable", + delay: 0 + }); + Instance.EntFireAtName({ + name: "chief_model", + input: "SetAnimationNotLooping", + value: "Chief_dash_start", + delay: 0 + }); + this.entity.Teleport({ + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + return true; +} +} +const state = { + bossMovement: new Map(), + bossMovementEnabled: true, + chief: { + maxHp: 0, + hp: 0, + hitbox: null, + lastHurtAt: 0, + didBreak: false + }, + void: { + maxHp: 0, + hp: 0, + hitbox: null, + lastHurtAt: 0, + didBreak: false + }, + milkheilter: { + maxHp: 0, + hp: 0, + hitbox: null, + lastHurtAt: 0, + didBreak: false + }, + voidtp: { + active: false, + spawnTime: null, + killTime: null, + victim: null, + hasSecondVictim: false, + secondVictim: null + } +}; +function clamp(v, lo, hi) { + return Math.max(lo, Math.min(hi, v)); +} + +function countAliveCT() { + try { + let count = 0; + const players = Instance.FindEntitiesByClass("player"); + for (const p of players) { + if (!p || !p.IsValid()) continue; + if (p.GetTeamNumber() === CT_TEAM && p.IsAlive()) { + count++; + } + } + return count; + } catch (error) { + return 0; + } +} + +function breakHitbox(hitboxName) { + try { + if (hitboxName) { + Instance.EntFireAtName({ name: hitboxName, input: "Break", delay: 0 }); + } + } catch (error) { + } +} + +function updateBossBar(bossBarName, hp, maxHp, barSteps = 40) { + try { + if (maxHp <= 0 || hp <= 0) { + Instance.EntFireAtName({ name: bossBarName, input: "SetAlphaScale", value: 0 }); + return; + } + const stepsVisible = Math.max(1, barSteps - 1); + const step = clamp(Math.floor((hp / maxHp) * stepsVisible), 0, stepsVisible); + Instance.EntFireAtName({ name: bossBarName, input: "SetAlphaScale", value: step }); + } catch (error) { + } +} + +const CHIEF_CONFIG = { + HITBOX_NAME: "chief_hitbox_1", + BOSS_BAR_NAME: "stage2_chief_hp_bar", + BASE_HP: 5000, + CT_BONUS: 200, + HURT_DELTA: 20, + BAR_STEPS: 40 +}; + +function initChiefHp() { + try { + const aliveCT = countAliveCT(); + state.chief.maxHp = CHIEF_CONFIG.BASE_HP + aliveCT * CHIEF_CONFIG.CT_BONUS; + state.chief.hp = state.chief.maxHp; + state.chief.hitbox = Instance.FindEntityByName(CHIEF_CONFIG.HITBOX_NAME); + state.chief.didBreak = false; + updateBossBar(CHIEF_CONFIG.BOSS_BAR_NAME, state.chief.hp, state.chief.maxHp, CHIEF_CONFIG.BAR_STEPS); + } catch (error) { + } +} + +function applyChiefHurt() { + try { + if (state.chief.maxHp <= 0) { + initChiefHp(); + } + const now = Instance.GetGameTime(); + if (now - state.chief.lastHurtAt < 0.05) { + return; + } + state.chief.lastHurtAt = now; + state.chief.hp = clamp(state.chief.hp - CHIEF_CONFIG.HURT_DELTA, 0, state.chief.maxHp); + updateBossBar(CHIEF_CONFIG.BOSS_BAR_NAME, state.chief.hp, state.chief.maxHp, CHIEF_CONFIG.BAR_STEPS); + if (state.chief.hp <= 0 && !state.chief.didBreak) { + breakHitbox(CHIEF_CONFIG.HITBOX_NAME); + state.chief.didBreak = true; + } + } catch (error) { + } +} + +const VOID_CONFIG = { + HITBOX_NAME: "void_hitbox_1", + BOSS_BAR_NAME: "stage2_void_hp_bar", + BASE_HP: 5000, + CT_BONUS: 400, + HURT_DELTA: 20, + BAR_STEPS: 40 +}; + +const MILKHEILTER_CONFIG = { + HITBOX_NAME: "milkheilter_hitbox_1", + BOSS_BAR_NAME: "stage3_milkheilter_hp_bar", + BASE_HP: 6000, + CT_BONUS: 600, + HURT_DELTA: 20, + BAR_STEPS: 40 +}; + +function initVoidHp() { + try { + const aliveCT = countAliveCT(); + state.void.maxHp = VOID_CONFIG.BASE_HP + aliveCT * VOID_CONFIG.CT_BONUS; + state.void.hp = state.void.maxHp; + state.void.hitbox = Instance.FindEntityByName(VOID_CONFIG.HITBOX_NAME); + state.void.didBreak = false; + updateBossBar(VOID_CONFIG.BOSS_BAR_NAME, state.void.hp, state.void.maxHp, VOID_CONFIG.BAR_STEPS); + } catch (error) { + } +} + +function applyVoidHurt() { + try { + if (state.void.maxHp <= 0) { + initVoidHp(); + } + const now = Instance.GetGameTime(); + if (now - state.void.lastHurtAt < 0.05) { + return; + } + state.void.lastHurtAt = now; + state.void.hp = clamp(state.void.hp - VOID_CONFIG.HURT_DELTA, 0, state.void.maxHp); + updateBossBar(VOID_CONFIG.BOSS_BAR_NAME, state.void.hp, state.void.maxHp, VOID_CONFIG.BAR_STEPS); + if (state.void.hp <= 0 && !state.void.didBreak) { + breakHitbox(VOID_CONFIG.HITBOX_NAME); + state.void.didBreak = true; + } + } catch (error) { + } +} + +function initMilkheilterHp() { + try { + const aliveCT = countAliveCT(); + state.milkheilter.maxHp = MILKHEILTER_CONFIG.BASE_HP + aliveCT * MILKHEILTER_CONFIG.CT_BONUS; + state.milkheilter.hp = state.milkheilter.maxHp; + state.milkheilter.hitbox = Instance.FindEntityByName(MILKHEILTER_CONFIG.HITBOX_NAME); + state.milkheilter.didBreak = false; + updateBossBar(MILKHEILTER_CONFIG.BOSS_BAR_NAME, state.milkheilter.hp, state.milkheilter.maxHp, MILKHEILTER_CONFIG.BAR_STEPS); + } catch (error) { + } +} + +function applyMilkheilterHurt() { + try { + if (state.milkheilter.maxHp <= 0) { + initMilkheilterHp(); + } + const now = Instance.GetGameTime(); + if (now - state.milkheilter.lastHurtAt < 0.05) { + return; + } + state.milkheilter.lastHurtAt = now; + state.milkheilter.hp = clamp(state.milkheilter.hp - MILKHEILTER_CONFIG.HURT_DELTA, 0, state.milkheilter.maxHp); + updateBossBar(MILKHEILTER_CONFIG.BOSS_BAR_NAME, state.milkheilter.hp, state.milkheilter.maxHp, MILKHEILTER_CONFIG.BAR_STEPS); + if (state.milkheilter.hp <= 0 && !state.milkheilter.didBreak) { + breakHitbox(MILKHEILTER_CONFIG.HITBOX_NAME); + state.milkheilter.didBreak = true; + } + } catch (error) { + } +} + +function StartBossMovement(inputData) { +const caller = inputData?.caller; +if (!caller || !caller.IsValid()) { + return; +} +state.bossMovementEnabled = true; +state.bossMovement.set(caller, new BossMover(caller)); +Instance.SetNextThink(0.1); +} +function StopBossMovement(inputData) { +const caller = inputData?.caller; +if (!caller) { + return; +} +state.bossMovement.delete(caller); +if (caller && caller.IsValid()) { + caller.Teleport({ + position: caller.GetAbsOrigin(), + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); +} +if (state.bossMovement.size === 0) { + state.bossMovementEnabled = false; +} +} +function TriggerDash(inputData) { +const caller = inputData?.caller; +if (!caller || !caller.IsValid()) { + return; +} +const mover = state.bossMovement.get(caller); +if (mover && mover.TriggerDash()) { + Instance.SetNextThink(0.1); +} +} +function ProcessBossMovement() { +if (state.bossMovement.size === 0) { + return false; +} +const now = Instance.GetGameTime(); +let hasActive = false; +for (const [entity, mover] of state.bossMovement) { + if (!entity || !entity.IsValid() || !mover || !mover.IsValid()) { + state.bossMovement.delete(entity); + continue; + } + if (mover.nextTickAt !== undefined && now < mover.nextTickAt) { + hasActive = true; + continue; + } + const stillValid = mover.Tick(now); + if (!stillValid) { + state.bossMovement.delete(entity); + continue; + } + hasActive = true; +} +return hasActive; +} +Instance.SetThink(() => { + if (state.bossMovementEnabled && ProcessBossMovement()) { + Instance.SetNextThink(0.1); + return; + } else if (state.bossMovementEnabled) { + Instance.SetNextThink(0.1); + return; + } + + if (state.voidtp && state.voidtp.active) { + ProcessVoidtpTimers(); + Instance.SetNextThink(0.1); + return; + } +}); +Instance.OnScriptInput("npc_move_start", StartBossMovement); +Instance.OnScriptInput("npc_move_stop", (inputData) => { + StopBossMovement(inputData); +}); +Instance.OnScriptInput("dash", TriggerDash); +Instance.OnScriptInput("voidtp", (inputData) => { + let firstVictimSlot = -1; + let secondVictimSlot = -1; + let totalTCount = 0; + + for (let slot = 0; slot < 64; slot++) { + const controller = Instance.GetPlayerController(slot); + if (!controller || !controller.IsValid()) continue; + if (controller.GetTeamNumber() !== T_TEAM) continue; + + const player = controller.GetPlayerPawn(); + if (!player || !player.IsValid()) continue; + if (!player.IsAlive()) continue; + + totalTCount++; + const rand = Math.random(); + + if (firstVictimSlot < 0) { + firstVictimSlot = slot; + } else if (rand < 0.5) { + secondVictimSlot = firstVictimSlot; + firstVictimSlot = slot; + } else if (secondVictimSlot < 0 || rand < 0.75) { + secondVictimSlot = slot; + } + } + + if (firstVictimSlot < 0) { + return; + } + + const template = Instance.FindEntityByName("@temp_hammermodel"); + + const firstController = Instance.GetPlayerController(firstVictimSlot); + if (firstController && firstController.IsValid()) { + const firstPlayer = firstController.GetPlayerPawn(); + if (firstPlayer && firstPlayer.IsValid()) { + const p1Origin = { x: -9578.05, y: -3536.55, z: 6211 }; + firstPlayer.Teleport({ position: p1Origin, angles: { pitch: 0, yaw: 0, roll: 0 }, velocity: { x: 0, y: 0, z: 0 }, angularVelocity: { x: 0, y: 0, z: 0 } }); + firstPlayer.SetMaxHealth(1500); + firstPlayer.SetHealth(1500); + if (template) { + template.ForceSpawn(p1Origin); + } + } + } + + let secondController = null; + if (secondVictimSlot >= 0) { + secondController = Instance.GetPlayerController(secondVictimSlot); + if (secondController && secondController.IsValid()) { + const secondPlayer = secondController.GetPlayerPawn(); + if (secondPlayer && secondPlayer.IsValid()) { + const p2Origin = { x: -10334.7, y: -3534, z: 6208.95 }; + secondPlayer.Teleport({ position: p2Origin, angles: { pitch: 0, yaw: 0, roll: 0 }, velocity: { x: 0, y: 0, z: 0 }, angularVelocity: { x: 0, y: 0, z: 0 } }); + secondPlayer.SetMaxHealth(1500); + secondPlayer.SetHealth(1500); + if (template) { + template.ForceSpawn(p2Origin); + } + } + } + } + + state.voidtp = { + active: true, + spawnTime: Instance.GetGameTime(), + killTime: Instance.GetGameTime() + 35, + victim: firstController, + hasSecondVictim: secondVictimSlot >= 0, + secondVictim: secondController + }; + + Instance.SetNextThink(0.1); +}); + +function ProcessVoidtpTimers() { + if (!state.voidtp || !state.voidtp.active) { + return false; + } + + const now = Instance.GetGameTime(); + + if (state.voidtp.killTime !== null && now >= state.voidtp.killTime) { + if (state.voidtp.victim && state.voidtp.victim.IsValid()) { + const pawn = state.voidtp.victim.GetPlayerPawn(); + if (pawn && pawn.IsValid() && pawn.IsAlive()) { + pawn.Kill(); + } + } + if (state.voidtp.hasSecondVictim && state.voidtp.secondVictim && state.voidtp.secondVictim.IsValid()) { + const pawn2 = state.voidtp.secondVictim.GetPlayerPawn(); + if (pawn2 && pawn2.IsValid() && pawn2.IsAlive()) { + pawn2.Kill(); + } + } + state.voidtp.active = false; + state.voidtp.killTime = null; + state.voidtp.victim = null; + state.voidtp.secondVictim = null; + state.voidtp.hasSecondVictim = false; + return false; + } + + return true; +} +Instance.OnScriptInput("speed", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const players = Instance.FindEntitiesByClass("player"); + const ctPlayers = []; + for (const p of players) { + if (!p || !p.IsValid()) continue; + if (p.GetTeamNumber() !== CT_TEAM || !p.IsAlive()) continue; + ctPlayers.push(p); + } + if (ctPlayers.length === 0) { + return; + } + const targetPlayer = ctPlayers[Math.floor(Math.random() * ctPlayers.length)]; + const targetOrigin = targetPlayer.GetAbsOrigin(); + caller.Teleport({ + position: { x: targetOrigin.x, y: targetOrigin.y, z: targetOrigin.z + 20 }, + angles: { pitch: 0, yaw: 0, roll: 0 }, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); +}); + +Instance.OnScriptInput("chiefstart", (inputData) => { + try { + initChiefHp(); + } catch (error) { + } +}); + +Instance.OnScriptInput("chiefhurt", (inputData) => { + try { + applyChiefHurt(); + } catch (error) { + } +}); + +Instance.OnScriptInput("breakchief_hitbox_1", (inputData) => { + try { + breakHitbox(CHIEF_CONFIG.HITBOX_NAME); + state.chief.didBreak = true; + } catch (error) { + } +}); + +Instance.OnScriptInput("voidstart", (inputData) => { + try { + initVoidHp(); + } catch (error) { + } +}); + +Instance.OnScriptInput("voidhurt", (inputData) => { + try { + applyVoidHurt(); + } catch (error) { + } +}); + +Instance.OnScriptInput("breakvoid_hitbox_1", (inputData) => { + try { + breakHitbox(VOID_CONFIG.HITBOX_NAME); + state.void.didBreak = true; + } catch (error) { + } +}); + +Instance.OnScriptInput("milkheilterstart", (inputData) => { + try { + initMilkheilterHp(); + } catch (error) { + } +}); + +Instance.OnScriptInput("milkheilterhurt", (inputData) => { + try { + applyMilkheilterHurt(); + } catch (error) { + } +}); + +Instance.OnScriptInput("breakmilkheilter_hitbox_1", (inputData) => { + try { + breakHitbox(MILKHEILTER_CONFIG.HITBOX_NAME); + state.milkheilter.didBreak = true; + } catch (error) { + } +}); + +Instance.OnActivate(() => { +}); +Instance.OnScriptReload({ +after: () => { +} +}); diff --git a/2001/ze_pretender/ct_death_tex.js b/2001/ze_pretender/ct_death_tex.js new file mode 100644 index 0000000..328330a --- /dev/null +++ b/2001/ze_pretender/ct_death_tex.js @@ -0,0 +1,63 @@ +import { Instance } from "cs_script/point_script"; + +// by wolfkk +let deathTemplates = []; +const CT_TEAM_ID = 3; +const deathTemplateConfig = { + templateName: "@death_tex", + spawnOffset: { x: 0, y: 0, z: 0 } +}; + +let cachedDeathTemplate = null; +let lastTemplateCacheTime = 0; + +Instance.OnPlayerKill((event) => { + try { + const victim = event.player; + if (victim && victim.GetTeamNumber() === CT_TEAM_ID) { + SpawnDeathTemplate(victim); + } + } catch (error) { + } +}); + +function SpawnDeathTemplate(victimPawn) { + try { + if (!victimPawn || !victimPawn.IsValid()) return; + const currentTime = Instance.GetGameTime(); + if (currentTime - lastTemplateCacheTime > 30 || !cachedDeathTemplate || !cachedDeathTemplate.IsValid()) { + cachedDeathTemplate = Instance.FindEntityByName(deathTemplateConfig.templateName); + lastTemplateCacheTime = currentTime; + } + const deathTemplate = cachedDeathTemplate; + if (!deathTemplate || !deathTemplate.IsValid() || !deathTemplate.ForceSpawn) return; + const deathPosition = victimPawn.GetAbsOrigin(); + const spawnPosition = { + x: deathPosition.x + deathTemplateConfig.spawnOffset.x, + y: deathPosition.y + deathTemplateConfig.spawnOffset.y, + z: deathPosition.z + deathTemplateConfig.spawnOffset.z + }; + const spawnedEntities = deathTemplate.ForceSpawn(spawnPosition, victimPawn.GetAbsAngles()); + if (spawnedEntities && spawnedEntities.length > 0) { + const validEntities = spawnedEntities.filter(ent => ent && ent.IsValid()); + if (validEntities.length > 0) { + deathTemplates.push({ + entities: validEntities, + spawnTime: Instance.GetGameTime(), + position: spawnPosition + }); + } + } + } catch (error) { + } +} + +Instance.OnScriptInput("GetCount", () => {}); + +Instance.OnRoundStart(() => { + deathTemplates = []; +}); + +Instance.OnRoundEnd(() => { + deathTemplates = []; +}); \ No newline at end of file diff --git a/2001/ze_pretender/ze_pretender.js b/2001/ze_pretender/ze_pretender.js new file mode 100644 index 0000000..3d4b492 --- /dev/null +++ b/2001/ze_pretender/ze_pretender.js @@ -0,0 +1,4978 @@ +// @ts-nocheck +import { Instance } from "cs_script/point_script"; +import { CSDamageTypes } from "cs_script/point_script"; + +const CT_TEAM = 3; +const T_TEAM = 2; +const RAD_TO_DEG = 180 / Math.PI; + +const SHOP_CONFIG = { + HP_COST: 20, + HP_BONUS: 10, + ARMOR_COST: 30, + ARMOR_BONUS: 0.02, + CD_COST: 20, + CD_BONUS: 0.01, + LUCK_COST: 20, + LUCK_BONUS: 0.01 +}; + +const MAX_PURCHASE_LIMITS = { + hp: 10, + cd: 20, + al: 20, + luck: 20 +}; + +const MAX_LIMITS = { + MAX_HP: 250, + MAX_HP_BONUS: 150, + MAX_ARMOR_REDUCTION: 0.30, + MAX_CD_REDUCTION: 0.50, + MAX_LUCK_VALUE: 0.40 +}; + +const BASE_LUCK_PROBABILITIES = { + nothing: 0.70, + coin50: 0.03, + coin10: 0.18, + coin20: 0.09 +}; + +const COIN_TEMPLATES = { + coin10: "@temp_10", + coin20: "@temp_20", + coin50: "@temp_50" +}; + +const RESERVED_ARTIFACTS = [ + { key: "sword", input: "buysword", template: "@temp_sword", cost: 200 }, + { key: "heal", input: "buyheal", template: "@temp_heal", cost: 50 }, + { key: "speed", input: "buyspeed", template: "@temp_speed", cost: 50 }, + { key: "shield", input: "buyshield", template: "@temp_shield", cost: 50 }, + { key: "pepsicola", input: "buypepsicola", template: "@temp_pepsicola", cost: 50 }, + { key: "cocacola", input: "buycocacola", template: "@temp_cocacola", cost: 50 } +]; + +const state = { + ctPurchaseCounts: {}, + + ctTeamStats: { + money: 0, + hpBonus: 0, + armorReduction: 0, + cdReduction: 0, + luckValue: 0 + }, + roundStartSnapshot: null, + healthUpdateTime: 0, + + vote: { + active: true, + yesSlots: new Set() + }, + npcMovement: new Map(), + npcMovementEnabled: true, + handTimerStartTime: null, + lolTeleportQueue: [], + lolTeleportCooldown: new Map(), + tpteamCooldown: new Map(), + shopinQueue: [], + + playerRecords: new Map(), + + tPurchases: { + magicHand: false, + hammer: false, + doakesDoom: false, + axe: false, + push: false, + box: false, + godshield: false, + jump: false, + ammo: false, + wd40: false, + pepsicola: false, + cocacola: false, + pill: false + }, + + totalWins: 0, + pendingExRelay: false, + + knownTPlayers: new Set(), + playerTeamState: new Map(), + + zmrandom: { + enabled: false, + selectedEvents: [], + selectedEventKeys: [], + tPlayerUsedEvent: false, + currentRoundEvents: [], + noPurchaseLimit: false, + currentSelectedIndex: -1, + exSelectActive: false, + started: false, + usedEventKeysHistory: [], + + limitammo: false, + rain: false, + banana: false, + hammer: false, + hammerTimerStartTime: null, + doakescome: false, + doakescomeTimerStartTime: null, + deadman: false, + deadmanTimerStartTime: null, + deadhand: false, + deadhandTimerStartTime: null, + vip: false, + vipPlayerSlot: null, + vipTemplateSpawned: false + }, + + moneyMaxLimit: 500, + buyrandomLocked: true +}; + +const SHOP_RANDOM_LIST = [ + { key: "axe", input: "buyrandom1", template: "@temp_axemodel", cost: 200, modelName: "axemodelshop" }, + { key: "push", input: "buyrandom2", template: "@temp_pushmodel", cost: 250, modelName: "pushmodelshop" }, + { key: "box", input: "buyrandom3", template: "@temp_boxmodel", cost: 999, modelName: "boxmodelshop" }, + { key: "godshield", input: "buyrandom4", template: "@temp_godshieldmodel", cost: 200, modelName: "godshieldmodelshop" }, + { key: "ammo", input: "buyrandom5", template: "@temp_ammomodel", cost: 150, modelName: "ammodmodelshop" }, + { key: "wd40", input: "buyrandom6", template: "@temp_wd40model", cost: 250, modelName: "wd40modelshop" }, + { key: "pepsicola", input: "buypepsicola", template: "@temp_pepsicola", cost: 50, modelName: "pepsicolamodelshop" }, + { key: "cocacola", input: "buycocacola", template: "@temp_cocacola", cost: 50, modelName: "cocacolamodelshop" }, + { key: "pill", input: "buypill", template: "@temp_pill", cost: 100, modelName: "pillmodelshop" }, + { key: "randomuse", input: "buyrandom", template: "@temp_random", cost: 300, modelName: "randomusemodelshop" }, + { key: "nukemini", input: "buyrandom7", template: "@temp_nukemini", cost: 400, modelName: "nukeminimodelshop" }, + { key: "teleport", input: "buyrandom8", template: "@temp_teleport", cost: 300, modelName: "teleportmodelshop" } +]; + +const RANDOM_SHOP_POSITIONS = [ + { x: -11422.1, y: 11684.6, z: -1197.64, priceEntity: "buyrandom1_c", buyInput: "buyrandom1" }, + { x: -11422.1, y: 11606.5, z: -1197.64, priceEntity: "buyrandom2_c", buyInput: "buyrandom2" } +]; + +const ZMRANDOM_EVENTS = [ + { key: "limitammo", input: "zmrandom1", setmessageKey: "random_1", name: "Limit Ammo", description: "All players bullet limit to 20" }, + { key: "rain", input: "zmrandom2", setmessageKey: "random_2", name: "Rain Event", description: "Every 30s spawn @temp_flash at random player" }, + { key: "banana", input: "zmrandom3", setmessageKey: "random_3", name: "Banana Event", description: "Change drop to @temp_banana" }, + { key: "hammer", input: "zmrandom4", setmessageKey: "random_4", name: "Hammer Event", description: "Spawn @temp_hammermodel at all T players once" }, + { key: "doakescome", input: "zmrandom5", setmessageKey: "random_5", name: "Doakes Come", description: "Every 60s 15% chance spawn @temp_doakes at CT (luck reduces chance)" }, + { key: "deadman", input: "deadman", setmessageKey: "random_6", name: "Deadman", description: "Every 30s spawn @temp_deathman at random player" }, + { key: "deadhand", input: "deadhand", setmessageKey: "random_7", name: "Deadhand", description: "Every 30s 30% chance spawn @temp_hand at CT (luck reduces chance)" }, + { key: "vip", input: "zmrandom8", setmessageKey: "random_8", name: "VIP Event", description: "Random CT becomes VIP, all CTs die when VIP dies" } +]; + +const ZMRANDOM_POSITIONS = [ + { x: -10855.6, y: 13315.1, z: 467 }, + { x: -10742.6, y: 13305.1, z: 467 }, + { x: -10629.6, y: 13295.1, z: 467 }, + { x: -10516.6, y: 13285.1, z: 467 } +]; + +function GetRandomInt(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +function GetDistance2D(a, b) { + const dx = a.x - b.x; + const dy = a.y - b.y; + return Math.sqrt(dx * dx + dy * dy); +} + +function WeightedRandomSelect(items, weights) { + const totalWeight = weights.reduce((sum, w) => sum + w, 0); + let random = Math.random() * totalWeight; + for (let i = 0; i < items.length; i++) { + random -= weights[i]; + if (random <= 0) return items[i]; + } + return items[items.length - 1]; +} + +function IsInsideRect(pos, rectOrigin, sizeX, sizeY) { + const halfX = sizeX / 2; + const halfY = sizeY / 2; + return pos.x >= rectOrigin.x - halfX && pos.x <= rectOrigin.x + halfX && + pos.y >= rectOrigin.y - halfY && pos.y <= rectOrigin.y + halfY; +} + +class SpawnData { + constructor(templateName, origin, angle, originOffset = { x: 0, y: 0, z: 0 }, angleOffset = { pitch: 0, yaw: 0, roll: 0 }, weights = null, excludedZones = null) { + this.templateName = templateName; + this.origin = origin; + this.angle = angle; + this.originOffset = originOffset; + this.angleOffset = angleOffset; + this.weights = weights; + this.excludedZones = excludedZones; + } + + Spawn(usedPositions) { + let templateName = this.templateName; + let isTelevision = false; + if (Array.isArray(templateName)) { + if (this.weights) { + templateName = WeightedRandomSelect(templateName, this.weights); + } else { + templateName = templateName[Math.floor(Math.random() * templateName.length)]; + } + isTelevision = templateName === "@temp_television"; + } + + const template = Instance.FindEntityByName(templateName) + || (templateName === "temp" ? Instance.FindEntityByName("@temp") : undefined); + if (!template || !template.IsValid()) { + return; + } + + let spawnPos; + let attempts = 0; + const maxAttempts = 100; + let inExcludedZone = false; + do { + spawnPos = { + x: this.origin.x + GetRandomInt(-this.originOffset.x, this.originOffset.x), + y: this.origin.y + GetRandomInt(-this.originOffset.y, this.originOffset.y), + z: this.origin.z + GetRandomInt(-this.originOffset.z, this.originOffset.z) + }; + attempts++; + + inExcludedZone = false; + if (this.excludedZones) { + for (const zone of this.excludedZones) { + if (IsInsideRect(spawnPos, zone.origin, zone.sizeX, zone.sizeY)) { + inExcludedZone = true; + break; + } + } + } + } while ( + attempts < maxAttempts && + (inExcludedZone || usedPositions.some(pos => GetDistance2D(spawnPos, pos) < 70)) + ); + + usedPositions.push(spawnPos); + + let spawnAng; + if (isTelevision) { + const randomYaw = Math.floor(Math.random() * 360); + spawnAng = { + pitch: 0, + yaw: randomYaw, + roll: 0 + }; + } else { + const effectiveAngleOffset = this.angleOffset || { pitch: 0, yaw: 0, roll: 0 }; + spawnAng = { + pitch: this.angle.pitch + GetRandomInt(-effectiveAngleOffset.pitch, effectiveAngleOffset.pitch), + yaw: this.angle.yaw + GetRandomInt(-effectiveAngleOffset.yaw, effectiveAngleOffset.yaw), + roll: this.angle.roll + GetRandomInt(-effectiveAngleOffset.roll, effectiveAngleOffset.roll) + }; + } + + template.ForceSpawn(spawnPos, spawnAng); + } +} + +function SpawnGroup(group) { + const usedPositions = []; + for (const spawnData of group) { + spawnData.Spawn(usedPositions); + } +} + +const SpawnDataGroup1 = [ + new SpawnData("boggart_temp", { x: 5543.51, y: 5110.8, z: 1150.12 }, { pitch: 0, yaw: 180, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("boggart_temp", { x: 8065.84, y: 265.224, z: 569.189 }, { pitch: 0, yaw: 180, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("boggart_temp", { x: 6928, y: -449.5, z: 569.189 }, { pitch: 0, yaw: 180, roll: 0 }, { x: 60, y: 60, z: 0}), + new SpawnData("boggart_temp", { x: 6829.7, y: -4188.63, z: 527 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("boggart_temp", { x: 7981.81, y: -4203.27, z: 527 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 0, y: 0, z: 0}), + new SpawnData("boggart_temp", { x: 7983.99, y: -7049.49, z: 527 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("boggart_temp", { x: 10481.8, y: -8572.73, z: 588.403 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("boggart_temp", { x: 11651.4, y: -8980, z: 743.666 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 60, y: 0, z: 0 }), + new SpawnData("boggart_temp", { x: 13499, y: -12252, z: 532.302 }, { pitch: 0, yaw: 180, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("boggart_temp", { x: 12215.7, y: -13264.8, z: 413.606 }, { pitch: 0, yaw: 90, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("boggart_temp", { x: 8990.43, y: -14475.6, z: 57.8123 }, { pitch: 0, yaw: 180, roll: 0 }, { x: 0, y: 0, z: 0 }), + new SpawnData("boggart_temp", { x: 8340.32, y: -12676.1, z: 50.4286 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 0, y: 0, z: 0 }), + new SpawnData("boggart_temp", { x: 7388.61, y: -13307.1, z: 43.7529 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 0, y: 0, z: 0 }), + new SpawnData("boggart_temp", { x: 6172.1, y: -13925.1, z: 44.6729 }, { pitch: 0, yaw: 90, roll: 0 }, { x: 0, y: 0, z: 0 }) +]; + +const SpawnDataGroup2 = [ + new SpawnData("skeleton_temp", { x: 13276.1, y: 9272.39, z: -2404.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 13983.6, y: 5102.5, z: -2059.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 11462.3, y: 2723.27, z: -1889 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 12431.9, y: -225.085, z: -1377.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 12962.9, y: -5240.24, z: -969.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 12459.4, y: -7484.74, z: -882.603 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 13523.4, y: -7563.75, z: -884.21 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 9289.67, y: -7152.9, z: -369.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 7559.97, y: -8680.49, z: -302.75 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 7559.97, y: -8232.5, z: -302.75 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 6325.81, y: -7703.85, z: -62.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 2900.26, y: -7840.09, z: 1113.71 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -881.709, y: -3853.39, z: 1124.25 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -200.021, y: -4423.22, z: 1124.25 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -1297.14, y: -1659.49, z: 1042.45 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -3799.62, y: -1697.44, z: 1042.45 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -5424.84, y: -1681.04, z: 1344.31 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -6733.07, y: -1206.02, z: 1966.55 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -6749.58, y: -2017.3, z: 1787.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -7872.62, y: -1256.14, z: 2095.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -9139.98, y: 1366.5, z: 3437.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -10043.3, y: 229.969, z: 3974.57 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -6629.96, y: -3909.64, z: 1935.75 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -6746.18, y: -4831.27, z: 2167.25 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -9175.99, y: -4261.94, z: 3332.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -10082.8, y: -3303.75, z: 3154.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -9951.04, y: -2066.33, z: 2761.38 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -10766, y: -824.974, z: 2878.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 11247.6, y: 7157.4, z: -2342.75 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -10206.6, y: -1595.73, z: 4825.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -9535.86, y: -1886.57, z: 4942.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -9707.89, y: -1502.99, z: 5489.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -9862.41, y: -1528.72, z: 3971 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -9315.2, y: -2296.97, z: 3874 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -9398.02, y: -750.177, z: 4050 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -10011.5, y: -1865.5, z: 6087 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -9925.25, y: -2582.5, z: 6218.01 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("livingarmor_temp", { x: 10500.3, y: -7515.64, z: -890.464 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("livingarmor_temp", { x: 9019.5, y: -7840.5, z: -359.114 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("livingarmor_temp", { x: 4995.61, y: -7927.5, z: 147.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("livingarmor_temp", { x: -6393.19, y: -3913.56, z: 1935.75 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("livingarmor_temp", { x: -9279.72, y: -1668.67, z: 3874 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("@temp_doakes", { x: -10180, y: -2254.68, z: 5068 }, { pitch: 0, yaw: 270, roll: 0 }), + new SpawnData("@temp_doakes", { x: -9931.39, y: -2944.43, z: 3152.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("@temp_doakes", { x: -1841.7, y: -3238.71, z: 1123 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("@temp_doakes", { x: 9207.61, y: -7333, z: -373.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("@temp_doakes", { x: 12662, y: -6910.5, z: -861 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("@temp_crossmodel", { x: 9015.5, y: 1402.26, z: -4001.5 }, { pitch: 0, yaw: 0, roll: 0 }) +]; + +const SpawnDataGroup3 = [ + new SpawnData("skeleton_temp", { x: -12466.7, y: -10032.8, z: 2071.61 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -13233.2, y: -10738.4, z: 2071.61 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -11687.9, y: -12197, z: 1361.11 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -7449.17, y: -9950.26, z: 1350.24 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -5105.89, y: -10032.4, z: 1341.96 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -2618.16, y: -13001.9, z: 1073.72 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -2064.36, y: -12399.9, z: 1059.85 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -3413.88, y: -12061.7, z: 1065.96 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -3984.08, y: -9978.58, z: 1392.26 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 78.7583, y: -10490.7, z: 3324.11 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 4787.59, y: -10416, z: 3356.96 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 8258.98, y: -7862.51, z: 3294.46 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: 7462.63, y: -5762.75, z: 3347.25 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("skeleton_temp", { x: -1291.7, y: -10260.4, z: 2127.7 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -9380.97, y: -11421.5, z: 1338.75 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -9955, y: -11491.5, z: 1338.75 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -7982.33, y: -10682.5, z: 1338.75 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -6973.48, y: -10131.9, z: 1363.59 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -5108.41, y: -9700.74, z: 1341.96 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -1123.15, y: -12751.1, z: 1076.09 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -2689, y: -11782.5, z: 1064.43 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -2639.66, y: -11680.5, z: 1064.43 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -2387.07, y: -11931.2, z: 1064.43 }, { pitch: 0, yaw: 179, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -2315.45, y: -11814.3, z: 1064.43 }, { pitch: 0, yaw: 179, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -2429.78, y: -11708.7, z: 1064.43 }, { pitch: 0, yaw: 179, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -2495.04, y: -11818.2, z: 1064.43 }, { pitch: 0, yaw: 179, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -2026.72, y: -8818.61, z: 1790.3 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -779.846, y: -9634.99, z: 2136.34 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -2916.39, y: -8979.48, z: 2095.8 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -3564.82, y: -11285.6, z: 2105 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -356.244, y: -9266.3, z: 3309.81 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 6617.08, y: -10552.8, z: 3249.26 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 8528.98, y: -10389.2, z: 3249.25 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 7575.63, y: -7854.57, z: 3300.76 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 8023.69, y: -5086.62, z: 3249.25 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -104.563, y: -12995.2, z: 1283 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -2809.5, y: -12348.9, z: 1060.88 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -4579.54, y: -11054.5, z: 1080.36 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -3924.75, y: -12249.4, z: 1071.27 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("@temp_doakes", { x: -8848.51, y: -11452.8, z: 1333.75 }, { pitch: 0, yaw: 270, roll: 0 }), + new SpawnData("@temp_doakes", { x: 5598.7, y: -10567.2, z: 3289 }, { pitch: 2, yaw: 270, roll: 0 }), + new SpawnData("@temp_doakes", { x: 7261.38, y: -10006.5, z: 3242.25 }, { pitch: 0, yaw: 270, roll: 0 }), + new SpawnData("@temp_doakes", { x: 8124.5, y: -7475.91, z: 3241.75 }, { pitch: 0, yaw: 270, roll: 0 }), + new SpawnData("@temp_doakes", { x: -1416, y: -10571.7, z: 2123.59 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1416, y: -9729.69, z: 2132.64 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -599, y: -9729.69, z: 2118.33 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2075, y: -9729.69, z: 2118.33 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1946.5, y: -9169.19, z: 2110.72 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2664, y: -9669.19, z: 2113.14 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2664, y: -9186.19, z: 2102.33 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -3337.5, y: -9669.19, z: 2106.84 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -3337.5, y: -9188.69, z: 2097.86 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -3337.5, y: -10766.2, z: 2118.33 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2393, y: -10766.2, z: 2107.83 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2393, y: -11285.7, z: 2118.33 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2913, y: -11285.7, z: 2106.74 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2913, y: -12219.7, z: 2105.6 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1928, y: -12219.7, z: 2112.86 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1375.5, y: -12219.7, z: 2103.22 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1375.5, y: -11459.2, z: 2108.33 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -803, y: -11459.2, z: 2121.25 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -803, y: -10847.2, z: 2124.39 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -655, y: -10008.7, z: 2118.33 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2552.5, y: -10230.7, z: 2113.33 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1123.74, y: -9868.64, z: 2138.48 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -3496.98, y: -10314.7, z: 2111.2 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1921.5, y: -9243.5, z: 2110.72 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1468, y: -9567, z: 2125.73 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1055.5, y: -9770.5, z: 2135.29 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1257, y: -10549, z: 2123.09 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1257, y: -10549, z: 2118.33 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -1440, y: -10336.5, z: 2127.39 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -803, y: -10600.5, z: 2126.6 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -3010, y: -11607, z: 2105.6 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -3312.5, y: -11285.7, z: 2106.82 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2483, y: -9339.5, z: 2102.33 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2315.5, y: -9586.5, z: 2112.93 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2212, y: -9263.5, z: 2107.53 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2076, y: -9263.5, z: 2108.74 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }), + new SpawnData("@temp_doakes", { x: -2027.5, y: -9486, z: 2118.59 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 120, y: 120, z: 0 }) +]; + +const SpawnDataGroup4 = [ + new SpawnData("sigiladdict_temp", { x: 3736.17, y: 10723.8, z: 1683.09 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 7461.73, y: -6089.14, z: 553.405 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 9921.08, y: -7739.67, z: 562.438 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 10364.1, y: -13237.9, z: 82.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 7519.64, y: -2036.84, z: 609.033 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("sigiladdict_temp", { x: 8481.52, y: -3123.37, z: 527 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("sigiladdict_temp", { x: 6405.28, y: -3123.12, z: 527 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("sigiladdict_temp", { x: 13453.3, y: -12536.9, z: 530.5 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("sigiladdict_temp", { x: 8280.9, y: -13791.1, z: 28 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 60, y: 60, z: 0 }), + new SpawnData("sigiladdict_temp", { x: 6046.78, y: -13131.7, z: 10 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 60, y: 60, z: 0 }) +]; + +const SpawnDataGroup5 = [ + new SpawnData("sigiladdict_temp", { x: 11908.4, y: 8172.25, z: -2444.25 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 11561.7, y: 4557.86, z: -2024.52 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 8558.34, y: -8383.62, z: -300.918 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 5667.5, y: -7656.62, z: 60.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 4674.53, y: -7510.49, z: 545.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -2200.8, y: -1474.97, z: 1049.73 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -6271.54, y: -4421.68, z: 2164.42 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -9302.81, y: -772.644, z: 3035 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -8257.91, y: -5260.65, z: 2391.88 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -10026, y: -774.588, z: 3033.59 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -9257.95, y: -963, z: 4043.69 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -9928.93, y: -1455.9, z: 3971 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -10381.4, y: -925.828, z: 3971 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -10133.5, y: 1287.69, z: 3974.57 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -10052.4, y: 1853.11, z: 3974.57 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -10536.4, y: -1364.69, z: 5380 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -9646.5, y: -1362.37, z: 4717.48 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -9921.72, y: -2863.5, z: 6218.05 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -10258.5, y: -3533.58, z: 6216.95 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -9655.5, y: -3493.14, z: 6219 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 4943.96, y: -7661.28, z: 1238.5 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -10175.5, y: -4769, z: 6216.95 }, { pitch: 0, yaw: 0, roll: 0 }) +]; + +const SpawnDataGroup6 = [ + new SpawnData("@temp_sandstorm", { x: 69.6525, y: 912.009, z: 2236.61 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 500, z: 0 }), + new SpawnData("@temp_sandstorm", { x: -13.8275, y: 1638.83, z: 2213.89 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 500, z: 0 }), + new SpawnData("@temp_sandstorm", { x: 212.493, y: 2073.79, z: 2243.52 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 500, z: 0 }), + + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -967.68, y: 7229.87, z: 1759.11 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 180, y: 120, z: 0 }, { pitch: 0, yaw: 0, roll: 0 }, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -967.68, y: 7229.87, z: 1759.11 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 180, y: 120, z: 0 }, { pitch: 0, yaw: 0, roll: 0 }, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -967.68, y: 7229.87, z: 1759.11 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 180, y: 120, z: 0 }, { pitch: 0, yaw: 0, roll: 0 }, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -967.68, y: 7229.87, z: 1759.11 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 180, y: 120, z: 0 }, { pitch: 0, yaw: 0, roll: 0 }, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -967.68, y: 7229.87, z: 1759.11 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 180, y: 120, z: 0 }, { pitch: 0, yaw: 0, roll: 0 }, [1, 0.3, 1, 1, 0.6]), + + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, { pitch: 0, yaw: 0, roll: 0 }, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -341.662, y: 6109.71, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 800, y: 130, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: 405.867, y: 5137.24, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 250, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -1151.89, y: 5046.98, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 200, y: 300, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6], [{ origin: { x: -356.34, y: 3436.11, z: 1407.91 }, sizeX: 200, sizeY: 143 }]), + new SpawnData(["@temp_breakbox", "@temp_nuclearbox", "@temp_nukebox", "@temp_candle", "@temp_greenshit"], { x: -325.783, y: 3481.75, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 500, y: 200, z: 0 }, null, [1, 0.3, 1, 1, 0.6]), + + new SpawnData("sigiladdict_temp", { x: -6140.27, y: -70.5998, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -6105.72, y: -1015.95, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -938.286, y: 7262.79, z: 1761.62 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -891.887, y: 4650.11, z: 1723.95 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 193.256, y: 5357.64, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: 628.19, y: 5357.64, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -1308.82, y: 5342.99, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("sigiladdict_temp", { x: -997.685, y: 5342.99, z: 1391.09 }, { pitch: 0, yaw: 0, roll: 0 }) +]; + +const SpawnDataGroup7 = [ + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2930.21, y: -1471.1, z: 2978.06 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 200, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2930.21, y: -1471.1, z: 2978.06 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 200, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2930.21, y: -1471.1, z: 2978.06 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 200, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2930.21, y: -1471.1, z: 2978.06 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 200, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2930.21, y: -1471.1, z: 2978.06 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 200, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2930.21, y: -1471.1, z: 2978.06 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 250, y: 200, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -3768.95, y: -2302.71, z: 3142.42 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 170, y: 120, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -3768.95, y: -2302.71, z: 3142.42 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 170, y: 120, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -3768.95, y: -2302.71, z: 3142.42 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 170, y: 120, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2406.02, y: -2302.01, z: 3476.68 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 300, y: 300, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2406.02, y: -2302.01, z: 3476.68 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 300, y: 300, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2406.02, y: -2302.01, z: 3476.68 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 300, y: 300, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2406.02, y: -2302.01, z: 3476.68 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 300, y: 300, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2406.02, y: -2302.01, z: 3476.68 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 300, y: 300, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2544.22, y: -3183.43, z: 3423.96 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 80, y: 300, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2544.22, y: -3183.43, z: 3423.96 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 80, y: 300, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + new SpawnData(["@temp_breakbox", "@temp_milkdragonfat", "@temp_blueshit", "@temp_television"], { x: -2514.39, y: -4585.35, z: 3415.33 }, { pitch: 0, yaw: 0, roll: 0 }, { x: 600, y: 500, z: 0 }, { pitch: 0, yaw: 180, roll: 0 }, [1, 0.8, 1, 1]), + + new SpawnData("milkdragon_temp", { x: -2906.21, y: -798.787, z: 2973.6 }, { pitch: 0, yaw: 180, roll: 0 }, { x: 160, y: 160, z: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -2821.2, y: -416.025, z: 2973.6 }, { pitch: 0, yaw: 180, roll: 0 }, { x: 160, y: 160, z: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -3118.13, y: -205.378, z: 2973.6 }, { pitch: 0, yaw: 90, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -3395.43, y: -1484.37, z: 2969.21 }, { pitch: 0, yaw: 90, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -2718.83, y: -1218.63, z: 2973.6 }, { pitch: 0, yaw: 270, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -3657.26, y: -2181.78, z: 3138.2 }, { pitch: 0, yaw: 270, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -2307.91, y: -2134.01, z: 3476.47 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 200, y: 300, z: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -2218.04, y: -2414.95, z: 3476.47 }, { pitch: 0, yaw: 270, roll: 0 }, { x: 200, y: 200, z: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -1909.71, y: -5089.22, z: 3420 }, { pitch: 0, yaw: 180, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -2042.58, y: -5089.22, z: 3420 }, { pitch: 0, yaw: 180, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -2227.01, y: -5089.22, z: 3420 }, { pitch: 0, yaw: 180, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -2410.75, y: -5089.22, z: 3420 }, { pitch: 0, yaw: 180, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -2596.01, y: -5089.22, z: 3420 }, { pitch: 0, yaw: 180, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -2776.14, y: -5089.22, z: 3420 }, { pitch: 0, yaw: 180, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -2946.35, y: -5089.22, z: 3420 }, { pitch: 0, yaw: 180, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }), + new SpawnData("milkdragon_temp", { x: -3093.63, y: -5089.22, z: 3420 }, { pitch: 0, yaw: 180, roll: 0 }, { pitch: 0, yaw: 0, roll: 0 }) +]; + +const MilkDragonFixedPositions = [ + { origin: { x: -1909.71, y: -5089.22, z: 3420 }, angle: { pitch: 0, yaw: 180, roll: 0 } }, + { origin: { x: -2042.58, y: -5089.22, z: 3420 }, angle: { pitch: 0, yaw: 180, roll: 0 } }, + { origin: { x: -2227.01, y: -5089.22, z: 3420 }, angle: { pitch: 0, yaw: 180, roll: 0 } }, + { origin: { x: -2410.75, y: -5089.22, z: 3420 }, angle: { pitch: 0, yaw: 180, roll: 0 } }, + { origin: { x: -2596.01, y: -5089.22, z: 3420 }, angle: { pitch: 0, yaw: 180, roll: 0 } }, + { origin: { x: -2776.14, y: -5089.22, z: 3420 }, angle: { pitch: 0, yaw: 180, roll: 0 } }, + { origin: { x: -2946.35, y: -5089.22, z: 3420 }, angle: { pitch: 0, yaw: 180, roll: 0 } }, + { origin: { x: -3093.63, y: -5089.22, z: 3420 }, angle: { pitch: 0, yaw: 180, roll: 0 } } +]; + +function SpawnMilkDragonAtFixedPositions() { + const template = Instance.FindEntityByName("milkdragon_temp"); + if (!template || !template.IsValid()) { + return; + } + + const numToSpawn = Math.floor(Math.random() * 4) + 3; + + const shuffled = [...MilkDragonFixedPositions]; + for (let i = shuffled.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; + } + + const positionsToSpawn = shuffled.slice(0, numToSpawn); + + for (const posData of positionsToSpawn) { + template.ForceSpawn(posData.origin, posData.angle); + } +} + +function TeleportExSelectToPosition(positionIndex) { + const exSelect = Instance.FindEntityByName("ex_select"); + if (!exSelect || !exSelect.IsValid()) return; + + const pos = ZMRANDOM_POSITIONS[positionIndex]; + if (pos) { + exSelect.Teleport({ + position: { x: pos.x, y: pos.y, z: pos.z }, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } +} + +function StartExSelectMovement() { + if (!state.zmrandom.enabled) return; + + TeleportExSelectToPosition(0); +} + +function TeleportExSelectForCurrentRound() { + if (!state.zmrandom.enabled || !state.zmrandom.exSelectActive) return; + + if (state.zmrandom.currentSelectedIndex >= 0) { + TeleportExSelectToPosition(state.zmrandom.currentSelectedIndex); + } +} + +function FisherYatesShuffle(array) { + const shuffled = [...array]; + for (let i = shuffled.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; + } + return shuffled; +} + +function ShuffleZMSEvents() { + const history = state.zmrandom.usedEventKeysHistory || []; + const availableEvents = ZMRANDOM_EVENTS.filter(e => !history.includes(e.key)); + + if (availableEvents.length < 4) { + state.zmrandom.usedEventKeysHistory = []; + const shuffled = FisherYatesShuffle(ZMRANDOM_EVENTS); + state.zmrandom.selectedEvents = shuffled.slice(0, 4); + } else { + const shuffled = FisherYatesShuffle(availableEvents); + state.zmrandom.selectedEvents = shuffled.slice(0, 4); + } + + state.zmrandom.selectedEventKeys = state.zmrandom.selectedEvents.map(e => e.key); + state.zmrandom.currentRoundEvents = []; + + UpdateZMMessageDisplay(); +} + +function UpdateZMMessageDisplay() { + const displayKeys = ["random_1", "random_2", "random_3", "random_4"]; + + for (let i = 0; i < displayKeys.length; i++) { + const setmessageKey = displayKeys[i]; + let eventName = "---"; + + if (state.zmrandom.tPlayerUsedEvent) { + Instance.EntFireAtName({ + name: setmessageKey, + input: "SetMessage", + value: eventName, + delay: 0 + }); + continue; + } + + if (i < state.zmrandom.selectedEvents.length) { + const event = state.zmrandom.selectedEvents[i]; + if (event) { + eventName = event.name; + } + } + + Instance.EntFireAtName({ + name: setmessageKey, + input: "SetMessage", + value: eventName, + delay: 0 + }); + } +} + +function StartZMRandomTimer(eventKey, timerKey, intervalSeconds) { + state.zmrandom[eventKey] = true; + state.zmrandom[timerKey] = Instance.GetGameTime(); + Instance.SetNextThink(0.1); +} + +function ProcessZMRandomTimers() { + if (!state.zmrandom.enabled) return false; + + const now = Instance.GetGameTime(); + let hasActive = false; + let nextThink = 1.0; + + if (state.zmrandom.rain && state.zmrandom.rainTimerStartTime !== null) { + hasActive = true; + const elapsed = now - state.zmrandom.rainTimerStartTime; + if (elapsed >= 30) { + SpawnFlashAtRandomPlayer(); + state.zmrandom.rainTimerStartTime = now; + } + nextThink = Math.min(nextThink, 0.5); + } + + if (state.zmrandom.doakescome && state.zmrandom.doakescomeTimerStartTime !== null) { + hasActive = true; + const elapsed = now - state.zmrandom.doakescomeTimerStartTime; + if (elapsed >= 60) { + TrySpawnDoakesAtRandomCT(); + state.zmrandom.doakescomeTimerStartTime = now; + } + nextThink = Math.min(nextThink, 1.0); + } + + if (state.zmrandom.deadman && state.zmrandom.deadmanTimerStartTime !== null) { + hasActive = true; + const elapsed = now - state.zmrandom.deadmanTimerStartTime; + if (elapsed >= 30) { + SpawnDeathmanAtRandomPlayer(); + state.zmrandom.deadmanTimerStartTime = now; + } + nextThink = Math.min(nextThink, 0.5); + } + + if (state.zmrandom.deadhand && state.zmrandom.deadhandTimerStartTime !== null) { + hasActive = true; + const elapsed = now - state.zmrandom.deadhandTimerStartTime; + if (elapsed >= 30) { + TrySpawnHandAtRandomCTWithLuck(); + state.zmrandom.deadhandTimerStartTime = now; + } + nextThink = Math.min(nextThink, 0.5); + } + + if (hasActive) { + Instance.SetNextThink(nextThink); + } + return hasActive; +} + +function LimitAllPlayerAmmo(maxAmmo) { + try { + const players = GetCachedPlayers(); + for (const player of players) { + if (!player || !player.IsValid()) continue; + + const weapon = player.GetActiveWeapon(); + if (!weapon || !weapon.IsValid()) continue; + + if (weapon.GetClassName() !== "weapon_knife") { + const clipAmmo = weapon.GetClipAmmo(); + if (clipAmmo > maxAmmo) { + weapon.SetClipAmmo(maxAmmo); + } + + const reserveAmmo = weapon.GetReserveAmmo(); + if (reserveAmmo > maxAmmo) { + weapon.SetReserveAmmo(maxAmmo); + } + } + } + } catch (error) { + } +} + +function LimitPlayerAmmoOnWeaponSwitch(player) { + if (!state.zmrandom.limitammo) return; + if (!player || !player.IsValid()) return; + + try { + const weapon = player.GetActiveWeapon(); + if (!weapon || !weapon.IsValid()) return; + + if (weapon.GetClassName() === "weapon_knife") return; + + const weaponData = weapon.GetData(); + if (!weaponData) return; + + const maxClip = weaponData.GetMaxClipAmmo(); + const maxReserve = weaponData.GetMaxReserveAmmo(); + + const limitedClip = Math.min(maxClip, 20); + const limitedReserve = Math.min(maxReserve, 20); + + const currentClip = weapon.GetClipAmmo(); + if (currentClip > limitedClip) { + weapon.SetClipAmmo(limitedClip); + } + + const currentReserve = weapon.GetReserveAmmo(); + if (currentReserve > limitedReserve) { + weapon.SetReserveAmmo(limitedReserve); + } + } catch (error) { + } +} + +function LimitAllPlayersAmmoOnSwitch() { + if (!state.zmrandom.limitammo) return; + + const players = GetCachedPlayers(); + for (const player of players) { + LimitPlayerAmmoOnWeaponSwitch(player); + } +} + +function GetAliveCTPawns() { + const ctPlayers = []; + for (let slot = 0; slot < 64; slot++) { + const ctrl = Instance.GetPlayerController(slot); + if (ctrl && ctrl.IsValid() && ctrl.GetTeamNumber() === CT_TEAM) { + const pawn = ctrl.GetPlayerPawn(); + if (pawn && pawn.IsValid() && pawn.IsAlive()) { + ctPlayers.push(pawn); + } + } + } + return ctPlayers; +} + +function SpawnTemplateAtRandomCT(templateName) { + try { + const template = Instance.FindEntityByName(templateName); + if (!template || !template.IsValid()) { + return; + } + + const ctPlayers = GetAliveCTPawns(); + if (ctPlayers.length === 0) { + return; + } + + const randomCT = ctPlayers[Math.floor(Math.random() * ctPlayers.length)]; + template.ForceSpawn(randomCT.GetAbsOrigin(), { pitch: 0, yaw: 0, roll: 0 }); + } catch (error) { + } +} + +function SpawnTemplateAtRandomCTWithLuck(templateName, baseChance) { + try { + const template = Instance.FindEntityByName(templateName); + if (!template || !template.IsValid()) { + return; + } + + const ctPlayers = GetAliveCTPawns(); + if (ctPlayers.length === 0) { + return; + } + + const teamStats = GetCTTeamStats(); + const luckValue = teamStats.luckValue || 0; + const spawnChance = Math.max(0, baseChance - luckValue * 0.3); + + if (Math.random() < spawnChance) { + const randomCT = ctPlayers[Math.floor(Math.random() * ctPlayers.length)]; + template.ForceSpawn(randomCT.GetAbsOrigin(), { pitch: 0, yaw: 0, roll: 0 }); + } + } catch (error) { + } +} + +function SpawnTemplateAtRandomAlivePlayer(templateName) { + try { + const template = Instance.FindEntityByName(templateName); + if (!template || !template.IsValid()) { + return; + } + + const players = GetCachedPlayers(); + const alivePlayers = []; + for (const p of players) { + if (!p || !p.IsValid()) continue; + if (!p.IsAlive()) continue; + alivePlayers.push(p); + } + + if (alivePlayers.length === 0) { + return; + } + + const randomPlayer = alivePlayers[Math.floor(Math.random() * alivePlayers.length)]; + template.ForceSpawn(randomPlayer.GetAbsOrigin(), { pitch: 0, yaw: 0, roll: 0 }); + } catch (error) { + } +} + +function SpawnFlashAtRandomPlayer() { + SpawnTemplateAtRandomAlivePlayer("@temp_flash"); +} + +function TrySpawnDoakesAtRandomCT() { + SpawnTemplateAtRandomCTWithLuck("@temp_doakes", 0.15); +} + +function SpawnDeathmanAtRandomPlayer() { + SpawnTemplateAtRandomAlivePlayer("@temp_deathman"); +} + +function TrySpawnHandAtRandomCTWithLuck() { + SpawnTemplateAtRandomCTWithLuck("@temp_hand", 0.30); +} + +function SpawnHammerAtAllTPlayers() { + try { + const hammerTemplate = Instance.FindEntityByName("@temp_hammermodel"); + if (!hammerTemplate || !hammerTemplate.IsValid()) { + return; + } + + const players = GetCachedPlayers(); + for (const p of players) { + if (!p || !p.IsValid()) continue; + if (p.GetTeamNumber() !== T_TEAM) continue; + if (!p.IsAlive()) continue; + + const position = p.GetAbsOrigin(); + const angles = p.GetAbsAngles(); + hammerTemplate.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); + } + } catch (error) { + } +} + +function SelectRandomVipAndSpawnTemplate() { + try { + const vipTemplate = Instance.FindEntityByName("@temp_vip"); + if (!vipTemplate || !vipTemplate.IsValid()) { + return; + } + + const ctPlayers = []; + for (let slot = 0; slot < 64; slot++) { + const ctrl = Instance.GetPlayerController(slot); + if (ctrl && ctrl.IsValid() && ctrl.GetTeamNumber() === CT_TEAM) { + const pawn = ctrl.GetPlayerPawn(); + if (pawn && pawn.IsValid() && pawn.IsAlive()) { + ctPlayers.push({ ctrl, pawn, slot }); + } + } + } + + if (ctPlayers.length === 0) { + return; + } + + const randomCT = ctPlayers[Math.floor(Math.random() * ctPlayers.length)]; + state.zmrandom.vipPlayerSlot = randomCT.slot; + state.zmrandom.vipTemplateSpawned = true; + + const position = randomCT.pawn.GetAbsOrigin(); + const angles = randomCT.pawn.GetAbsAngles(); + vipTemplate.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); + + const playerName = randomCT.ctrl.GetPlayerName(); + Instance.ServerCommand(`say ${playerName} has been selected as VIP! If VIP dies, all humans will die!`); + } catch (error) { + } +} + +function KillAllCTs() { + try { + const players = GetCachedPlayers(); + for (const p of players) { + if (!p || !p.IsValid()) continue; + if (p.GetTeamNumber() !== CT_TEAM) continue; + if (!p.IsAlive()) continue; + + p.Kill(); + } + Instance.ServerCommand('say VIP has fallen! All humans have been eliminated!'); + } catch (error) { + } +} + +function HandleZMRandomSelection(inputData, eventIndex) { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetClassName() !== "player") { + return; + } + + if (activator.GetTeamNumber() !== T_TEAM) { + return; + } + + if (!state.zmrandom.enabled) { + return; + } + + if (state.zmrandom.tPlayerUsedEvent) { + return; + } + + if (eventIndex >= state.zmrandom.selectedEvents.length) { + return; + } + + const event = state.zmrandom.selectedEvents[eventIndex]; + if (!event) { + return; + } + + state.zmrandom.tPlayerUsedEvent = true; + state.zmrandom.currentSelectedIndex = eventIndex; + state.zmrandom.currentRoundEvents.push(event); + + if (!state.zmrandom.usedEventKeysHistory.includes(event.key)) { + state.zmrandom.usedEventKeysHistory.push(event.key); + } + + UpdateZMMessageDisplay(); + ApplyZMEvent(event); + } catch (error) { + } +} + +function ApplyZMEvent(event) { + switch (event.key) { + case "limitammo": + state.zmrandom.limitammo = true; + break; + + case "rain": + state.zmrandom.rain = true; + Instance.EntFireAtName({ + name: "rain", + input: "start", + delay: 0 + }); + Instance.EntFireAtName({ + name: "rain_relay", + input: "Enable", + delay: 0 + }); + StartZMRandomTimer("rain", "rainTimerStartTime", 30); + break; + + case "banana": + state.zmrandom.banana = true; + break; + + case "hammer": + SpawnHammerAtAllTPlayers(); + break; + + case "doakescome": + StartZMRandomTimer("doakescome", "doakescomeTimerStartTime", 60); + break; + + case "deadman": + StartZMRandomTimer("deadman", "deadmanTimerStartTime", 30); + break; + + case "deadhand": + StartZMRandomTimer("deadhand", "deadhandTimerStartTime", 30); + break; + + case "vip": + state.zmrandom.vip = true; + state.zmrandom.vipPlayerSlot = null; + state.zmrandom.vipTemplateSpawned = false; + SelectRandomVipAndSpawnTemplate(); + break; + } +} + +function ResetZMState() { + state.zmrandom.limitammo = false; + state.zmrandom.rain = false; + state.zmrandom.rainTimerStartTime = null; + state.zmrandom.banana = false; + state.zmrandom.hammer = false; + state.zmrandom.hammerTimerStartTime = null; + state.zmrandom.doakescome = false; + state.zmrandom.doakescomeTimerStartTime = null; + state.zmrandom.deadman = false; + state.zmrandom.deadmanTimerStartTime = null; + state.zmrandom.deadhand = false; + state.zmrandom.deadhandTimerStartTime = null; + state.zmrandom.tPlayerUsedEvent = false; + state.zmrandom.currentRoundEvents = []; + state.zmrandom.currentSelectedIndex = -1; + state.zmrandom.vip = false; + state.zmrandom.vipPlayerSlot = null; + state.zmrandom.vipTemplateSpawned = false; +} + +function ResetZMStateForNewRound() { + state.zmrandom.limitammo = false; + state.zmrandom.rain = false; + state.zmrandom.rainTimerStartTime = null; + state.zmrandom.banana = false; + state.zmrandom.hammer = false; + state.zmrandom.hammerTimerStartTime = null; + state.zmrandom.doakescome = false; + state.zmrandom.doakescomeTimerStartTime = null; + state.zmrandom.deadman = false; + state.zmrandom.deadmanTimerStartTime = null; + state.zmrandom.deadhand = false; + state.zmrandom.deadhandTimerStartTime = null; + state.zmrandom.tPlayerUsedEvent = false; + state.zmrandom.vip = false; + state.zmrandom.vipPlayerSlot = null; + state.zmrandom.vipTemplateSpawned = false; + + Instance.EntFireAtName({ + name: "rain", + input: "stop", + delay: 0 + }); +} + +function EndZMEvent() { + ResetZMState(); + state.zmrandom.enabled = false; + + const displayKeys = ["random_1", "random_2", "random_3", "random_4"]; + for (const key of displayKeys) { + Instance.EntFireAtName({ + name: key, + input: "SetMessage", + value: "---", + delay: 0 + }); + } + + Instance.EntFireAtName({ + name: "rain", + input: "stop", + delay: 0 + }); +} + +let currentRoundRandomItems = []; + +const NPC_MOVE_CONFIG = { + TICKRATE_IDLE: 1.8, + TICKRATE_ACTIVE: 0.1, + TARGET_DISTANCE: 2000, + TARGET_TIME: 5, + FORWARD_TIMEOUT: 0.2, + FRONT_ANGLE: 5, + FORWARD_SPEED: 600, + ANGULAR_SPEED: 500 +}; + +class NpcMover { + constructor(entity) { + this.entity = entity; + this.target = undefined; + this.targetTime = 0; + this.forwardTimeout = NPC_MOVE_CONFIG.FORWARD_TIMEOUT; + this.nextTickAt = 0; + } + + IsValid() { + return this.entity && this.entity.IsValid(); + } + + Tick(now) { + if (!this.IsValid()) { + return false; + } + + const self = this.entity; + const angle = self.GetAbsAngles(); + if (angle.pitch > 75 || angle.pitch < -75) { + self.Teleport({ angles: { pitch: 0, yaw: angle.yaw, roll: angle.roll } }); + } + + if (!this.target || !this.target.IsValid() || this.target.GetTeamNumber() !== CT_TEAM || this.target.GetHealth() <= 0) { + this.target = this.FindTarget(); + this.targetTime = 0; + } + + if (!this.target) { + this.nextTickAt = now + NPC_MOVE_CONFIG.TICKRATE_IDLE; + return true; + } + + const selfOrigin = self.GetAbsOrigin(); + const selfVelocity = self.GetAbsVelocity(); + const selfAngles = self.GetAbsAngles(); + const targetOrigin = this.target.GetAbsOrigin(); + + const absYaw = Math.atan2(targetOrigin.y - selfOrigin.y, targetOrigin.x - selfOrigin.x) * RAD_TO_DEG; + const localYaw = WrapDegrees(absYaw - selfAngles.yaw); + const forward = ForwardFromAngles(selfAngles); + + if (Math.abs(localYaw) > NPC_MOVE_CONFIG.FRONT_ANGLE) { + if (TraceObstacleAhead(self, selfOrigin, forward, 30)) { + this.forwardTimeout = 0; + } + self.Teleport({ angularVelocity: { x: 0, y: 0, z: NPC_MOVE_CONFIG.ANGULAR_SPEED * (localYaw > 0 ? 1 : -1) } }); + } + + this.forwardTimeout += NPC_MOVE_CONFIG.TICKRATE_ACTIVE; + if (this.forwardTimeout > NPC_MOVE_CONFIG.FORWARD_TIMEOUT) { + self.Teleport({ velocity: { x: forward.x * NPC_MOVE_CONFIG.FORWARD_SPEED, y: forward.y * NPC_MOVE_CONFIG.FORWARD_SPEED, z: selfVelocity.z } }); + } + + this.targetTime += NPC_MOVE_CONFIG.TICKRATE_ACTIVE; + if (this.targetTime >= NPC_MOVE_CONFIG.TARGET_TIME) { + this.target = undefined; + this.targetTime = 0; + } + + this.nextTickAt = now + NPC_MOVE_CONFIG.TICKRATE_ACTIVE; + return true; + } + + FindTarget() { + const selfOrigin = this.entity.GetAbsOrigin(); + const eyeFrom = AddVector(selfOrigin, { x: 0, y: 0, z: 80 }); + const players = GetCachedPlayers(); + const candidates = []; + + for (const p of players) { + if (!p || !p.IsValid()) { + continue; + } + if (p.GetTeamNumber() !== CT_TEAM || p.GetHealth() <= 0) { + continue; + } + const pOrigin = p.GetAbsOrigin(); + if (Distance3D(selfOrigin, pOrigin) > NPC_MOVE_CONFIG.TARGET_DISTANCE) { + continue; + } + + const targetEye = AddVector(pOrigin, { x: 0, y: 0, z: 18 }); + if (CanSee(eyeFrom, targetEye, this.entity, p)) { + candidates.push(p); + } + } + + if (candidates.length === 0) { + return undefined; + } + + return candidates[Math.floor(Math.random() * candidates.length)]; + } + +} + +function AddVector(a, b) { + return { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z }; +} + +function Distance3D(a, b) { + const dx = a.x - b.x; + const dy = a.y - b.y; + const dz = a.z - b.z; + return Math.sqrt(dx * dx + dy * dy + dz * dz); +} + +function ForwardFromAngles(angles) { + const pitch = (angles.pitch / 180) * Math.PI; + const yaw = (angles.yaw / 180) * Math.PI; + const cosPitch = Math.cos(pitch); + return { + x: cosPitch * Math.cos(yaw), + y: cosPitch * Math.sin(yaw), + z: -Math.sin(pitch) + }; +} + +function WrapDegrees(degrees) { + return ((degrees + 180) % 360 + 360) % 360 - 180; +} + +function TraceObstacleAhead(self, origin, forward, distance) { + const result = Instance.TraceSphere({ + radius: 16, + start: origin, + end: AddVector(origin, { x: forward.x * distance, y: forward.y * distance, z: forward.z * distance }), + ignoreEntity: self, + ignorePlayers: true + }); + return result.didHit; +} + +function CanSee(start, end, self, target) { + const line = Instance.TraceLine({ + start, + end, + ignoreEntity: self + }); + if (!line.didHit || line.hitEntity === target) { + return true; + } + + const hitDistToTarget = Distance3D(line.end, end); + if (hitDistToTarget > 16) { + return false; + } + + const sphere = Instance.TraceSphere({ + radius: 4, + start, + end, + ignoreEntity: self + }); + return !sphere.didHit || sphere.hitEntity === target; +} + +function CanSeeAnyPoint(start, points, self, target) { + for (const end of points) { + if (CanSee(start, end, self, target)) { + return true; + } + } + return false; +} + +function StartNpcMovement(inputData) { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + state.npcMovementEnabled = true; + state.npcMovement.set(caller, new NpcMover(caller)); + Instance.SetNextThink(0.1); +} + +function StopNpcMovement(inputData) { + const caller = inputData?.caller; + if (!caller) { + return; + } + state.npcMovement.delete(caller); + if (caller && caller.IsValid()) { + caller.Teleport({ + position: caller.GetAbsOrigin(), + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } + if (state.npcMovement.size === 0) { + state.npcMovementEnabled = false; + } +} + +function ProcessNpcMovement() { + if (state.npcMovement.size === 0) { + return false; + } + + const now = Instance.GetGameTime(); + let hasActive = false; + + for (const [entity, mover] of state.npcMovement) { + if (!entity || !entity.IsValid() || !mover || !mover.IsValid()) { + state.npcMovement.delete(entity); + continue; + } + + if (mover.nextTickAt !== undefined && now < mover.nextTickAt) { + hasActive = true; + continue; + } + + const stillValid = mover.Tick(now); + if (!stillValid) { + state.npcMovement.delete(entity); + continue; + } + hasActive = true; + } + + return hasActive; +} +function GetCTTeamStats() { + return state.ctTeamStats; +} + +function IsCTPlayer(player) { + return player && player.GetTeamNumber() === CT_TEAM; +} + +function GetCurrentHumanCount() { + const players = Instance.FindEntitiesByClass("player"); + let count = 0; + for (const p of players) { + if (p?.IsValid() && p.GetTeamNumber() === CT_TEAM) { + count++; + } + } + return count; +} + +function GetVoteYesCount() { + return state.vote.yesSlots.size; +} + +function GetVoteRequiredYesCount() { + const total = GetCurrentHumanCount(); + if (total < 3) { + return 1; + } + return Math.ceil(total * 0.7); +} + +function UpdateVoteDisplay() { + const total = GetCurrentHumanCount(); + const yes = GetVoteYesCount(); + const required = GetVoteRequiredYesCount(); + + const percent = total > 0 ? Math.floor((yes / total) * 100) : 0; + const text = `VOTE: ${yes}/${required} (${percent}%)`; + + Instance.EntFireAtName({ + name: "start_text", + input: "SetMessage", + value: text, + delay: 0 + }); +} + +function EvaluateVote() { + if (!state.vote.active) { + return; + } + + UpdateVoteDisplay(); + + const yes = GetVoteYesCount(); + const required = GetVoteRequiredYesCount(); + + if (yes >= required) { + TriggerVoteSuccess(); + } +} + +function TriggerVoteSuccess() { + state.vote.active = false; + UpdateVoteDisplay(); + Instance.EntFireAtName({ + name: "start_relay", + input: "Trigger", + delay: 0 + }); +} + +function UpdateMoneyDisplay() { + const teamStats = GetCTTeamStats(); + const totalMoney = teamStats.money || 0; + + + const moneyDisplayNames = ["money_c", "money_c1", "money_c2"]; + for (const name of moneyDisplayNames) { + const moneyDisplay = Instance.FindEntityByName(name); + if (!moneyDisplay) { + continue; + } + Instance.EntFireAtTarget({ + target: moneyDisplay, + input: "SetMessage", + value: `G: ${totalMoney}`, + delay: 0 + }); + } +} + +function SaveGameData() { +} + +function UpdateWinDisplay() { + const winDisplayNames = ["server_win_c", "server_win_c1", "server_win_c2"]; + for (const name of winDisplayNames) { + const winDisplay = Instance.FindEntityByName(name); + if (!winDisplay) { + continue; + } + Instance.EntFireAtTarget({ + target: winDisplay, + input: "SetMessage", + value: `WINS: ${state.totalWins}`, + delay: 0 + }); + } +} + +function UpdateDisplayEntity(entityName, value, isPercentage = false) { + const display = Instance.FindEntityByName(entityName); + if (display) { + const displayValue = isPercentage + ? Math.round(value * 100).toString() + "%" + : Math.round(value).toString(); + Instance.EntFireAtTarget({ + target: display, + input: "SetMessage", + value: displayValue, + delay: 0 + }); + } +} + +function UpdateAllDisplays() { + const teamStats = GetCTTeamStats(); + + UpdateDisplayEntity("hp_c", 100 + (teamStats.hpBonus || 0)); + UpdateDisplayEntity("cd_c", teamStats.cdReduction || 0, true); + UpdateDisplayEntity("al_c", teamStats.armorReduction || 0, true); + UpdateDisplayEntity("luck_c", teamStats.luckValue || 0, true); + + UpdateDisplayEntity("hp_c2", 100 + (teamStats.hpBonus || 0)); + UpdateDisplayEntity("cd_c2", teamStats.cdReduction || 0, true); + UpdateDisplayEntity("al_c2", teamStats.armorReduction || 0, true); + UpdateDisplayEntity("luck_c2", teamStats.luckValue || 0, true); +} + +function AddMoney(amount) { + const teamStats = GetCTTeamStats(); + teamStats.money = Math.min((teamStats.money || 0) + amount, state.moneyMaxLimit); + UpdateMoneyDisplay(); +} + +function SpendMoney(amount) { + const teamStats = GetCTTeamStats(); + if ((teamStats.money || 0) < amount) { + return false; + } + teamStats.money -= amount; + UpdateMoneyDisplay(); + return true; +} + +function BuyAttribute(config) { + const { statName, currentValue, maxLimit, cost, bonus, bonusName, updateHealth = false } = config; + const teamStats = GetCTTeamStats(); + + if (currentValue >= maxLimit) { + return false; + } + + if (!SpendMoney(cost)) { + return false; + } + + const newValue = Math.min(currentValue + bonus, maxLimit); + teamStats[statName] = newValue; + + if (updateHealth) { + UpdateAllCTHealth(); + } + + UpdateAllDisplays(); + + if (statName === 'hpBonus') { + Instance.ServerCommand(`say All humans gained ${newValue} bonus HP (Total HP: ${100 + newValue})`); + } else { + Instance.ServerCommand(`say All humans gained ${(newValue * 100).toFixed(1)}% ${bonusName}`); + } + + return true; +} + +function BuyHP() { + const teamStats = GetCTTeamStats(); + return BuyAttribute({ + statName: 'hpBonus', + currentValue: teamStats.hpBonus || 0, + maxLimit: MAX_LIMITS.MAX_HP_BONUS, + cost: SHOP_CONFIG.HP_COST, + bonus: SHOP_CONFIG.HP_BONUS, + bonusName: 'HP', + updateHealth: true + }); +} + +function BuyArmor() { + const teamStats = GetCTTeamStats(); + return BuyAttribute({ + statName: 'armorReduction', + currentValue: teamStats.armorReduction || 0, + maxLimit: MAX_LIMITS.MAX_ARMOR_REDUCTION, + cost: SHOP_CONFIG.ARMOR_COST, + bonus: SHOP_CONFIG.ARMOR_BONUS, + bonusName: 'damage reduction' + }); +} + +function BuyCD() { + const teamStats = GetCTTeamStats(); + return BuyAttribute({ + statName: 'cdReduction', + currentValue: teamStats.cdReduction || 0, + maxLimit: MAX_LIMITS.MAX_CD_REDUCTION, + cost: SHOP_CONFIG.CD_COST, + bonus: SHOP_CONFIG.CD_BONUS, + bonusName: 'CD reduction' + }); +} + +function BuyLuck() { + const teamStats = GetCTTeamStats(); + return BuyAttribute({ + statName: 'luckValue', + currentValue: teamStats.luckValue || 0, + maxLimit: MAX_LIMITS.MAX_LUCK_VALUE, + cost: SHOP_CONFIG.LUCK_COST, + bonus: SHOP_CONFIG.LUCK_BONUS, + bonusName: 'luck' + }); +} + +function BuyAttributeFreeTimes(config, times) { + const { statName, currentValue, maxLimit, bonus, bonusName } = config; + let val = currentValue; + let gained = 0; + for (let i = 0; i < times; i++) { + if (val >= maxLimit) break; + val = Math.min(val + bonus, maxLimit); + gained += bonus; + } + if (gained <= 0) { + return null; + } + return { statName, newValue: val, bonusName }; +} + +function ApplyPillBonus() { + const teamStats = GetCTTeamStats(); + const attrs = [ + { + statName: 'armorReduction', + currentValue: teamStats.armorReduction || 0, + maxLimit: MAX_LIMITS.MAX_ARMOR_REDUCTION, + bonus: SHOP_CONFIG.ARMOR_BONUS, + bonusName: 'damage reduction' + }, + { + statName: 'cdReduction', + currentValue: teamStats.cdReduction || 0, + maxLimit: MAX_LIMITS.MAX_CD_REDUCTION, + bonus: SHOP_CONFIG.CD_BONUS, + bonusName: 'CD reduction' + }, + { + statName: 'luckValue', + currentValue: teamStats.luckValue || 0, + maxLimit: MAX_LIMITS.MAX_LUCK_VALUE, + bonus: SHOP_CONFIG.LUCK_BONUS, + bonusName: 'luck' + } + ]; + + const chosen = attrs[Math.floor(Math.random() * attrs.length)]; + const result = BuyAttributeFreeTimes(chosen, 5); + if (result) { + teamStats[result.statName] = result.newValue; + UpdateAllDisplays(); + Instance.ServerCommand(`say All humans gained ${result.bonusName} x5 (random pill bonus)!`); + } else { + UpdateAllDisplays(); + } +} + +function UpdateAllCTHealth() { + const teamStats = GetCTTeamStats(); + cachedPlayerList = Instance.FindEntitiesByClass("player"); + playerListCacheTime = Instance.GetGameTime(); + for (const player of cachedPlayerList) { + if (!player || !player.IsValid() || !IsCTPlayer(player)) { + continue; + } + + const ctrl = player.GetPlayerController(); + if (!ctrl) { + continue; + } + + const baseHP = 100; + const hpBonus = Math.min(teamStats.hpBonus || 0, MAX_LIMITS.MAX_HP_BONUS); + const newMaxHP = Math.min(baseHP + hpBonus, MAX_LIMITS.MAX_HP); + + player.SetMaxHealth(newMaxHP); + + if (player.IsAlive()) { + player.SetHealth(newMaxHP); + } + } +} + +function ValidateCTPlayer(playerSlot) { + const ctrl = Instance.GetPlayerController(playerSlot); + if (!ctrl) { + return null; + } + + const player = ctrl.GetPlayerPawn(); + if (!player || !player.IsValid() || !IsCTPlayer(player)) { + return null; + } + + return { ctrl, player }; +} + +function ApplyArmorReduction(playerSlot, damage) { + if (!ValidateCTPlayer(playerSlot)) { + return damage; + } + + const teamStats = GetCTTeamStats(); + const reduction = teamStats.armorReduction || 0; + return damage * (1 - reduction); +} + +function CalculateLuckAdjustedProbabilities() { + const teamStats = GetCTTeamStats(); + const luckBonus = teamStats.luckValue || 0; + + const prob = { + nothing: Math.max(0, BASE_LUCK_PROBABILITIES.nothing - luckBonus * 0.5), + coin50: BASE_LUCK_PROBABILITIES.coin50 + luckBonus * 0.1, + coin10: BASE_LUCK_PROBABILITIES.coin10 + luckBonus * 0.2, + coin20: BASE_LUCK_PROBABILITIES.coin20 + luckBonus * 0.2 + }; + + const total = prob.nothing + prob.coin50 + prob.coin10 + prob.coin20; + if (total > 0) { + Object.keys(prob).forEach(key => prob[key] /= total); + } + + return prob; +} + +function DropCoins(position) { + const prob = CalculateLuckAdjustedProbabilities(); + + const rand = Math.random(); + let coinType = null; + + if (rand < prob.nothing) { + return; + } else if (rand < prob.nothing + prob.coin50) { + coinType = "coin50"; + } else if (rand < prob.nothing + prob.coin50 + prob.coin10) { + coinType = "coin10"; + } else { + coinType = "coin20"; + } + + const templateName = COIN_TEMPLATES[coinType]; + const template = Instance.FindEntityByName(templateName); + + if (!template) { + return; + } + + const entities = template.ForceSpawn(position, { pitch: 0, yaw: 0, roll: 0 }); + void entities; +} + +function GetAdjustedCooldownSeconds(baseSeconds) { + const teamStats = GetCTTeamStats(); + const reduction = Math.min(Math.max(teamStats.cdReduction || 0, 0), MAX_LIMITS.MAX_CD_REDUCTION); + return Math.max(0, baseSeconds * (1 - reduction)); +} + +const activatorStunState = new Map(); +let magicLastSpawnTime = 0; + +const milkmanState = new Map(); +const sandstormState = new Map(); + +const cooldowns = new Map(); + +function ClearPlayerFromAllQueues(player) { + const ctrl = player.GetPlayerController(); + if (!ctrl) { + return; + } + const slot = ctrl.GetPlayerSlot(); + + activatorStunState.delete(slot); +} + +function GetPlayerSlotKey(inputData) { + const entity = inputData.activator || inputData.caller; + if (!entity || !entity.IsValid()) { + return null; + } + + if (entity.GetClassName() === "player") { + const ctrl = entity.GetPlayerController(); + return ctrl ? ctrl.GetPlayerSlot() : null; + } + + if (entity.GetClassName() === "player_ctrl") { + return entity.GetPlayerSlot(); + } + + return null; +} + +function TeleportActivatorToRandomCTOffset(activator, distance, checkCooldown = false, pendingActivators = null) { + if (!activator || !activator.IsValid()) { + return false; + } + + const ctrl = activator.GetPlayerController(); + if (!ctrl) { + return false; + } + const slot = ctrl.GetPlayerSlot(); + + const now = Instance.GetGameTime(); + const LOL_TP_COOLDOWN = 1.0; + + if (checkCooldown) { + const cooldownEnd = state.lolTeleportCooldown.get(slot); + if (cooldownEnd !== undefined && now < cooldownEnd) { + return false; + } + } + + const ctCandidates = []; + const tCandidates = []; + const players = GetCachedPlayers(); + for (const p of players) { + if (!p || !p.IsValid()) continue; + if (p === activator) continue; + + if (pendingActivators && pendingActivators.has(p)) continue; + + const pController = p.GetPlayerController(); + const pSlot = pController ? pController.GetPlayerSlot() : -1; + const pCooldownEnd = state.lolTeleportCooldown.get(pSlot); + + if (pCooldownEnd !== undefined && now < pCooldownEnd) continue; + + if (!p.IsAlive()) continue; + + if (p.GetTeamNumber() === CT_TEAM) { + ctCandidates.push(p); + } else if (p.GetTeamNumber() === T_TEAM) { + tCandidates.push(p); + } + } + + let candidates = ctCandidates; + if (ctCandidates.length < 1) { + candidates = tCandidates; + } + + if (candidates.length === 0) { + return false; + } + + const target = candidates[Math.floor(Math.random() * candidates.length)]; + + if (checkCooldown) { + const targetController = target.GetPlayerController(); + if (targetController) { + state.lolTeleportCooldown.set(targetController.GetPlayerSlot(), now + LOL_TP_COOLDOWN); + } + } + + const origin = target.GetAbsOrigin(); + const a = Math.random() * Math.PI * 2; + + const newPos = { + x: origin.x + Math.cos(a) * distance, + y: origin.y + Math.sin(a) * distance, + z: origin.z + }; + + activator.Teleport({ + position: newPos, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + + return true; +} + +let cachedPlayerList = []; +let playerListCacheTime = 0; +const PLAYER_CACHE_INTERVAL = 1.0; + +function GetCachedPlayers() { + const now = Instance.GetGameTime(); + if (now - playerListCacheTime > PLAYER_CACHE_INTERVAL) { + cachedPlayerList = Instance.FindEntitiesByClass("player"); + playerListCacheTime = now; + } + return cachedPlayerList; +} + +function GetAliveCTCount() { + let count = 0; + const players = GetCachedPlayers(); + for (const p of players) { + if (!p || !p.IsValid()) continue; + if (p.GetTeamNumber() !== CT_TEAM) continue; + if (!p.IsAlive()) continue; + count++; + } + return count; +} + +function GetAliveTCount() { + let count = 0; + const players = GetCachedPlayers(); + for (const p of players) { + if (!p || !p.IsValid()) continue; + if (p.GetTeamNumber() !== T_TEAM) continue; + if (!p.IsAlive()) continue; + count++; + } + return count; +} + +function ScheduleLolTeleport(activator, delaySeconds, checkCooldown = false) { + if (!activator || !activator.IsValid()) { + return; + } + + const wasEmpty = !state.lolTeleportQueue || state.lolTeleportQueue.length === 0; + const now = Instance.GetGameTime(); + state.lolTeleportQueue = state.lolTeleportQueue.filter(t => t && t.activator !== activator); + state.lolTeleportQueue.push({ + activator, + executeAt: now + delaySeconds, + checkCooldown + }); + + if (wasEmpty) { + Instance.SetNextThink(0.1); + } +} + +function ProcessLolTeleports() { + if (!state.lolTeleportQueue || state.lolTeleportQueue.length === 0) { + return; + } + + const now = Instance.GetGameTime(); + const remaining = []; + + const pendingActivators = new Set(); + for (const task of state.lolTeleportQueue) { + if (task && task.activator && task.activator.IsValid()) { + pendingActivators.add(task.activator); + } + } + + for (const task of state.lolTeleportQueue) { + if (!task || !task.activator) { + continue; + } + if (!task.activator.IsValid()) { + continue; + } + + if (now < task.executeAt) { + remaining.push(task); + continue; + } + + const success = TeleportActivatorToRandomCTOffset(task.activator, 15, task.checkCooldown, pendingActivators); + if (!success && task.checkCooldown) { + remaining.push(task); + } + } + + state.lolTeleportQueue = remaining; +} + +function ProcessShopinQueue() { + if (!state.shopinQueue || state.shopinQueue.length === 0) { + return false; + } + + const targetOrigin = { x: -11003.2, y: 11451.9, z: -1298.51 }; + + let selectedActivator = null; + + for (const entry of state.shopinQueue) { + if (!entry.activator || !entry.activator.IsValid()) { + continue; + } + if (entry.activator.GetClassName() !== "player") { + continue; + } + if (!entry.activator.IsAlive()) { + continue; + } + if (selectedActivator === null) { + selectedActivator = entry.activator; + } + } + + state.shopinQueue = []; + + if (selectedActivator) { + const currentAngles = selectedActivator.GetEyeAngles(); + selectedActivator.Teleport({ + position: targetOrigin, + angles: currentAngles, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + + const shopRelay = Instance.FindEntityByName("shop_relay"); + if (shopRelay && shopRelay.IsValid()) { + Instance.EntFireAtTarget({ + target: shopRelay, + input: "Trigger", + caller: selectedActivator, + activator: selectedActivator + }); + } + } + + return true; +} + +function ProcessCooldowns() { + const now = Instance.GetGameTime(); + + let hasActive = false; + + if (state.healthUpdateTime > 0 && now >= state.healthUpdateTime) { + state.healthUpdateTime = 0; + UpdateAllCTHealth(); + UpdateAllDisplays(); + } + + if (activatorStunState.size > 0) { + hasActive = true; + const toDelete = []; + for (const [slot, data] of activatorStunState) { + if (data.__invalidated) { + toDelete.push(slot); + continue; + } + const activator = data.__activatorRef; + if (!activator || !activator.IsValid()) { + toDelete.push(slot); + continue; + } + if (now >= data.stunEndTime) { + toDelete.push(slot); + activator.Teleport({ + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } else { + activator.Teleport({ + position: activator.GetAbsOrigin(), + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } + } + for (const slot of toDelete) { + activatorStunState.delete(slot); + } + } + + const hasNpcMovement = state.npcMovementEnabled ? ProcessNpcMovement() : false; + ProcessLolTeleports(); + ProcessShopinQueue(); + + const hasLolTasks = state.lolTeleportQueue && state.lolTeleportQueue.length > 0; + const hasShopinTasks = state.shopinQueue && state.shopinQueue.length > 0; + + const hasZM = ProcessZMRandomTimers(); + + const hasMilkman = ProcessMilkmanState(); + const hasSandstorm = ProcessSandstormState(); + + const hasGreenshit = ProcessGreenshit(); + + if (hasNpcMovement || hasLolTasks || hasZM || hasMilkman || hasSandstorm || hasShopinTasks || hasGreenshit) { + Instance.SetNextThink(hasNpcMovement ? 0.02 : 0.1); + } else if (state.handTimerStartTime !== null) { + hasActive = true; + const elapsed = now - state.handTimerStartTime; + if (elapsed >= 30) { + if (Math.random() < 0.10) { + TrySpawnHandAtRandomCT(); + } + state.handTimerStartTime = now; + } + Instance.SetNextThink(0.5); + } else if (hasActive) { + Instance.SetNextThink(0.1); + } +} + +Instance.SetThink(ProcessCooldowns); + +function SaveRoundStartSnapshot() { + state.roundStartSnapshot = { + ctTeamStats: JSON.parse(JSON.stringify(state.ctTeamStats)) + }; +} + +function RollbackToRoundStart() { + if (!state.roundStartSnapshot) { + return; + } + + state.ctTeamStats = JSON.parse(JSON.stringify(state.roundStartSnapshot.ctTeamStats)); + + UpdateAllCTHealth(); + UpdateMoneyDisplay(); + UpdateAllDisplays(); +} + +Instance.OnModifyPlayerDamage((event) => { + try { + const player = event.player; + if (!player || !player.IsValid() || !IsCTPlayer(player)) { + return; + } + + const ctrl = player.GetPlayerController(); + if (!ctrl) { + return; + } + + const slot = ctrl.GetPlayerSlot(); + const teamStats = GetCTTeamStats(); + + const now = Instance.GetGameTime(); + const protectUntil = player.__shieldProtectUntil || 0; + if (protectUntil > now) { + if (!player.__shieldProtectTempSpawned) { + player.__shieldProtectTempSpawned = true; + const protectTemplate = Instance.FindEntityByName("@temp_protect"); + if (protectTemplate) { + protectTemplate.ForceSpawn(player.GetAbsOrigin(), { pitch: 0, yaw: 0, roll: 0 }); + } + } + return { abort: true }; + } + + const godProtectUntil = player.__godshieldProtectUntil || 0; + if (godProtectUntil > now) { + if (!player.__godshieldProtectTempSpawned) { + player.__godshieldProtectTempSpawned = true; + const godProtectTemplate = Instance.FindEntityByName("@temp_godprotect"); + if (godProtectTemplate) { + godProtectTemplate.ForceSpawn(player.GetAbsOrigin(), { pitch: 0, yaw: 0, roll: 0 }); + } + } + return { abort: true }; + } + + const dodgeChance = teamStats.luckValue || 0; + if (dodgeChance > 0 && Math.random() < dodgeChance) { + const missTemplate = Instance.FindEntityByName("@temp_miss"); + if (missTemplate) { + missTemplate.ForceSpawn(player.GetAbsOrigin(), { pitch: 0, yaw: 0, roll: 0 }); + } + + return { abort: true }; + } + + return { damage: ApplyArmorReduction(slot, event.damage) }; + } catch (error) { + } +}); + +Instance.OnPlayerActivate((event) => { + try { + const player = event.player; + if (!player || !player.IsValid()) { + return; + } + + const ctrl = player.GetPlayerController(); + if (!ctrl) { + return; + } + + const slot = ctrl.GetPlayerSlot(); + const team = player.GetTeamNumber(); + + if (!state.playerTeamState.has(slot)) { + state.playerTeamState.set(slot, team); + } + + if (team === T_TEAM) { + const oldTeam = state.playerTeamState.get(slot); + if (oldTeam !== T_TEAM) { + state.knownTPlayers.add(slot); + state.playerTeamState.set(slot, T_TEAM); + Instance.EntFireAtName({ + name: "removecontext", + input: "Trigger" + }); + } + } + + if (team === CT_TEAM) { + const teamStats = GetCTTeamStats(); + const baseHP = 100; + const hpBonus = Math.min(teamStats.hpBonus || 0, MAX_LIMITS.MAX_HP_BONUS); + const newMaxHP = Math.min(baseHP + hpBonus, MAX_LIMITS.MAX_HP); + player.SetMaxHealth(newMaxHP); + player.SetHealth(newMaxHP); + } + } catch (error) { + } +}); + +Instance.OnPlayerReset((event) => { + try { + const player = event.player; + if (!player || !player.IsValid()) { + return; + } + + greenshitState.players.delete(player); + + const ctrl = player.GetPlayerController(); + if (!ctrl) { + return; + } + + const slot = ctrl.GetPlayerSlot(); + const newTeam = player.GetTeamNumber(); + const oldTeam = state.playerTeamState.get(slot); + state.playerTeamState.set(slot, newTeam); + + if (oldTeam !== undefined && oldTeam !== T_TEAM && newTeam === T_TEAM) { + state.knownTPlayers.add(slot); + Instance.EntFireAtName({ + name: "removecontext", + input: "Trigger" + }); + } + + state.vote.yesSlots.delete(slot); + + ClearPlayerFromAllQueues(player); + + if (!IsCTPlayer(player)) { + return; + } + + const teamStats = GetCTTeamStats(); + const baseHP = 100; + const hpBonus = Math.min(teamStats.hpBonus || 0, MAX_LIMITS.MAX_HP_BONUS); + const newMaxHP = Math.min(baseHP + hpBonus, MAX_LIMITS.MAX_HP); + + player.SetMaxHealth(newMaxHP); + player.SetHealth(newMaxHP); + + UpdateAllDisplays(); + } catch (error) { + } +}); + +function TrySpawnHandAtRandomCT() { + try { + const handTemplate = Instance.FindEntityByName("@temp_hand"); + if (!handTemplate || !handTemplate.IsValid()) { + return; + } + + const ctPlayers = GetAliveCTPawns(); + if (ctPlayers.length === 0) { + return; + } + + const randomCT = ctPlayers[Math.floor(Math.random() * ctPlayers.length)]; + handTemplate.ForceSpawn(randomCT.GetAbsOrigin(), { pitch: 0, yaw: 0, roll: 0 }); + } catch (error) { + } +} + +Instance.OnPlayerKill((event) => { + try { + if (!state.zmrandom.vip || !state.zmrandom.vipTemplateSpawned) { + return; + } + + const player = event.player; + if (!player || !player.IsValid()) { + return; + } + + if (!IsCTPlayer(player)) { + return; + } + + const ctrl = player.GetPlayerController(); + if (!ctrl) { + return; + } + + const slot = ctrl.GetPlayerSlot(); + + if (slot === state.zmrandom.vipPlayerSlot) { + KillAllCTs(); + } + } catch (error) { + } +}); + +Instance.OnRoundStart(() => { + activatorStunState.clear(); + cooldowns.clear(); + state.tpteamCooldown.clear(); + state.lolTeleportCooldown.clear(); + milkmanState.clear(); + sandstormState.clear(); + + SaveRoundStartSnapshot(); + state.healthUpdateTime = Instance.GetGameTime() + 2.0; + + state.vote.active = true; + state.vote.yesSlots = new Set(); + UpdateVoteDisplay(); + + state.ctPurchaseCounts = {}; + state.tPurchases.magicHand = false; + state.tPurchases.hammer = false; + state.tPurchases.doakesDoom = false; + state.tPurchases.axe = false; + state.tPurchases.push = false; + state.tPurchases.box = false; + state.tPurchases.godshield = false; + state.tPurchases.jump = false; + state.tPurchases.ammo = false; + state.tPurchases.wd40 = false; + state.handTimerStartTime = null; + + state.knownTPlayers.clear(); + state.playerTeamState.clear(); + + ResetZMStateForNewRound(); + + if (state.zmrandom.started) { + ShuffleZMSEvents(); + } + UpdateZMMessageDisplay(); + + if (state.zmrandom.exSelectActive) { + StartExSelectMovement(); + TeleportExSelectForCurrentRound(); + } + + SetupRandomShop(); + + UpdateAllCTHealth(); + + UpdateMoneyDisplay(); + UpdateAllDisplays(); + UpdateWinDisplay(); + + if (state.pendingExRelay) { + state.pendingExRelay = false; + Instance.EntFireAtName({ + name: "ex_relay", + input: "Trigger", + delay: 0.1 + }); + } +}); + +Instance.OnRoundEnd((event) => { + const isCTWin = event.winningTeam === CT_TEAM; + const isDraw = event.winningTeam === 4; + + if (isCTWin) { + state.roundStartSnapshot = null; + } else { + RollbackToRoundStart(); + } + + if (state.zmrandom.exSelectActive && !state.zmrandom.started) { + ResetZMStateForNewRound(); + } + + if (isCTWin) { + Instance.EntFireAtName({ + name: "you_win", + input: "StartSound" + }); + } else { + Instance.EntFireAtName({ + name: "you_lose", + input: "StartSound" + }); + } +}); + +Instance.OnPlayerDisconnect((event) => { + try { + const playerSlot = event.playerSlot; + if (playerSlot === undefined || playerSlot === null) { + return; + } + + state.playerTeamState.delete(playerSlot); + state.knownTPlayers.delete(playerSlot); + state.playerRecords.delete(playerSlot); + } catch (error) { + } +}); + +function GetPlayerSlotFromInput(inputData) { + const entity = inputData.activator || inputData.caller; + if (!entity || !entity.IsValid()) { + return null; + } + + if (entity.GetClassName() === "player") { + const ctrl = entity.GetPlayerController(); + return ctrl ? ctrl.GetPlayerSlot() : null; + } + + if (entity.GetClassName() === "player_ctrl") { + return entity.GetPlayerSlot(); + } + + return null; +} + +function ValidateCTPlayerForShop(inputData) { + const slot = GetPlayerSlotFromInput(inputData); + if (slot === null) { + return null; + } + + const validated = ValidateCTPlayer(slot); + if (!validated) { + return null; + } + + return slot; +} + +function ValidateTPlayerForShop(inputData) { + const slot = GetPlayerSlotFromInput(inputData); + if (slot === null) { + return null; + } + + const ctrl = Instance.GetPlayerController(slot); + if (!ctrl) { + return null; + } + + const player = ctrl.GetPlayerPawn(); + if (!player || !player.IsValid()) { + return null; + } + + if (player.GetTeamNumber() !== T_TEAM) { + return null; + } + + return slot; +} + +function HandleTBuyInput(inputData, buyFunction) { + try { + if (ValidateTPlayerForShop(inputData) !== null) { + buyFunction(inputData); + } + } catch (error) { + } +} + +function BuyMagicHand(inputData) { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (state.tPurchases.magicHand) { + return; + } + + const template = Instance.FindEntityByName("@temp_magichandmodel"); + if (!template) { + return; + } + + state.tPurchases.magicHand = true; + + const position = activator.GetAbsOrigin(); + const angles = activator.GetAbsAngles(); + template.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); + } catch (error) { + } +} + +function BuyHammer(inputData) { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (state.tPurchases.hammer) { + return; + } + + const template = Instance.FindEntityByName("@temp_hammermodel"); + if (!template) { + return; + } + + state.tPurchases.hammer = true; + + const position = activator.GetAbsOrigin(); + const angles = activator.GetAbsAngles(); + template.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); + } catch (error) { + } +} + +function BuyDoakesDoom(inputData) { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (state.tPurchases.doakesDoom) { + return; + } + + const template = Instance.FindEntityByName("@temp_doakes_doom"); + if (!template) { + return; + } + + state.tPurchases.doakesDoom = true; + + const position = activator.GetAbsOrigin(); + const angles = activator.GetAbsAngles(); + template.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); + } catch (error) { + } +} + +function BuyJump(inputData) { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (state.tPurchases.jump) { + return; + } + + const template = Instance.FindEntityByName("@temp_jump"); + if (!template) { + return; + } + + state.tPurchases.jump = true; + + const position = activator.GetAbsOrigin(); + const angles = activator.GetAbsAngles(); + template.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); + } catch (error) { + } +} + +function HandleBuyInput(inputData, buyFunction, itemKey) { + try { + const slot = ValidateCTPlayerForShop(inputData); + if (slot === null) { + return; + } + + if (!state.ctPurchaseCounts[slot]) { + state.ctPurchaseCounts[slot] = {}; + } + + if (!state.ctPurchaseCounts[slot][itemKey]) { + state.ctPurchaseCounts[slot][itemKey] = 0; + } + + const purchaseLimit = MAX_PURCHASE_LIMITS[itemKey] || 10; + if (!state.zmrandom.noPurchaseLimit && state.ctPurchaseCounts[slot][itemKey] >= purchaseLimit) { + return; + } + + buyFunction(); + state.ctPurchaseCounts[slot][itemKey]++; + } catch (error) { + } +} + +Instance.OnScriptInput("buyhp", (inputData) => HandleBuyInput(inputData, BuyHP, "hp")); +Instance.OnScriptInput("buyal", (inputData) => HandleBuyInput(inputData, BuyArmor, "al")); +Instance.OnScriptInput("buycd", (inputData) => HandleBuyInput(inputData, BuyCD, "cd")); +Instance.OnScriptInput("buyluck", (inputData) => HandleBuyInput(inputData, BuyLuck, "luck")); + +Instance.OnScriptInput("shopin", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetClassName() !== "player") { + return; + } + + if (!activator.IsAlive()) { + return; + } + + const now = Instance.GetGameTime(); + state.shopinQueue = state.shopinQueue || []; + state.shopinQueue.push({ activator, time: now }); + + if (state.shopinQueue.length === 1) { + Instance.SetNextThink(0.1); + } + } catch (error) { + } +}); + +Instance.OnScriptInput("buymagichand", (inputData) => HandleTBuyInput(inputData, BuyMagicHand)); +Instance.OnScriptInput("buyhammer", (inputData) => HandleTBuyInput(inputData, BuyHammer)); +Instance.OnScriptInput("buydoakesdoom", (inputData) => HandleTBuyInput(inputData, BuyDoakesDoom)); +Instance.OnScriptInput("buyjump", (inputData) => HandleTBuyInput(inputData, BuyJump)); + +Instance.OnScriptInput("startvote", (inputData) => { + try { + if (!state.vote.active) { + return; + } + + const slot = GetPlayerSlotFromInput(inputData || {}); + if (slot === null) { + return; + } + + const validated = ValidateCTPlayer(slot); + if (!validated) { + return; + } + + if (state.vote.yesSlots.has(slot)) { + return; + } + + state.vote.yesSlots.add(slot); + UpdateVoteDisplay(); + EvaluateVote(); + } catch (error) { + } +}); + +Instance.OnScriptInput("starthand", () => { + if (!state.tPurchases.magicHand) { + return; + } + if (state.handTimerStartTime !== null) { + return; + } + state.handTimerStartTime = Instance.GetGameTime(); +}); + +Instance.OnScriptInput("endvote", (inputData) => { + try { + if (!state.vote.active) { + return; + } + + const slot = GetPlayerSlotFromInput(inputData || {}); + if (slot === null) { + return; + } + + const validated = ValidateCTPlayer(slot); + if (!validated) { + return; + } + + if (!state.vote.yesSlots.has(slot)) { + return; + } + + state.vote.yesSlots.delete(slot); + UpdateVoteDisplay(); + } catch (error) { + } +}); + +Instance.OnScriptInput("votestart", (inputData) => { + try { + if (!state.vote.active) { + return; + } + + const slot = GetPlayerSlotFromInput(inputData || {}); + if (slot === null) { + return; + } + + const validated = ValidateCTPlayer(slot); + if (!validated) { + return; + } + + TriggerVoteSuccess(); + } catch (error) { + } +}); + +Instance.OnScriptInput("swordcd", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const callerName = caller.GetEntityName(); + if (!callerName) { + return; + } + + const now = Instance.GetGameTime(); + const cdEndTime = cooldowns.get(callerName); + if (cdEndTime !== undefined && now < cdEndTime) { + return; + } + + const baseCd = 10; + const cd = GetAdjustedCooldownSeconds(baseCd); + cooldowns.set(callerName, now + cd); + + Instance.EntFireAtName({ + name: callerName, + input: "unlock", + delay: cd + }); +}); + +Instance.OnScriptInput("shieldcd", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const callerName = caller.GetEntityName(); + if (!callerName) { + return; + } + + const now = Instance.GetGameTime(); + const cdEndTime = cooldowns.get(callerName); + if (cdEndTime !== undefined && now < cdEndTime) { + return; + } + + const baseCd = 15; + const cd = GetAdjustedCooldownSeconds(baseCd); + cooldowns.set(callerName, now + cd); + + Instance.EntFireAtName({ + name: callerName, + input: "unlock", + delay: cd + }); +}); + +Instance.OnScriptInput("speedcd", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const callerName = caller.GetEntityName(); + if (!callerName) { + return; + } + + const now = Instance.GetGameTime(); + const cdEndTime = cooldowns.get(callerName); + if (cdEndTime !== undefined && now < cdEndTime) { + return; + } + + const baseCd = 20; + const cd = GetAdjustedCooldownSeconds(baseCd); + cooldowns.set(callerName, now + cd); + + Instance.EntFireAtName({ + name: callerName, + input: "unlock", + delay: cd + }); +}); + +Instance.OnScriptInput("axecd", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const callerName = caller.GetEntityName(); + if (!callerName) { + return; + } + + const now = Instance.GetGameTime(); + const cdEndTime = cooldowns.get(callerName); + if (cdEndTime !== undefined && now < cdEndTime) { + return; + } + + const baseCd = 5; + const cd = GetAdjustedCooldownSeconds(baseCd); + cooldowns.set(callerName, now + cd); + + Instance.EntFireAtName({ + name: callerName, + input: "unlock", + delay: cd + }); +}); + +Instance.OnScriptInput("pushcd", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const callerName = caller.GetEntityName(); + if (!callerName) { + return; + } + + const now = Instance.GetGameTime(); + const cdEndTime = cooldowns.get(callerName); + if (cdEndTime !== undefined && now < cdEndTime) { + return; + } + + const baseCd = 80; + const cd = GetAdjustedCooldownSeconds(baseCd); + cooldowns.set(callerName, now + cd); + + Instance.EntFireAtName({ + name: callerName, + input: "unlock", + delay: cd + }); +}); + +Instance.OnScriptInput("wd40cd", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const callerName = caller.GetEntityName(); + if (!callerName) { + return; + } + + const now = Instance.GetGameTime(); + const cdEndTime = cooldowns.get(callerName); + if (cdEndTime !== undefined && now < cdEndTime) { + return; + } + + const baseCd = 40; + const cd = GetAdjustedCooldownSeconds(baseCd); + cooldowns.set(callerName, now + cd); + + Instance.EntFireAtName({ + name: callerName, + input: "unlock", + delay: cd + }); +}); + +Instance.OnScriptInput("teleportcd", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const callerName = caller.GetEntityName(); + if (!callerName) { + return; + } + + const now = Instance.GetGameTime(); + const cdEndTime = cooldowns.get(callerName); + if (cdEndTime !== undefined && now < cdEndTime) { + return; + } + + const baseCd = 30; + const cd = GetAdjustedCooldownSeconds(baseCd); + cooldowns.set(callerName, now + cd); + + Instance.EntFireAtName({ + name: callerName, + input: "unlock", + delay: cd + }); +}); + +Instance.OnScriptInput("godshieldcd", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const callerName = caller.GetEntityName(); + if (!callerName) { + return; + } + + const now = Instance.GetGameTime(); + const cdEndTime = cooldowns.get(callerName); + if (cdEndTime !== undefined && now < cdEndTime) { + return; + } + + const baseCd = 15; + const cd = GetAdjustedCooldownSeconds(baseCd); + cooldowns.set(callerName, now + cd); + + Instance.EntFireAtName({ + name: callerName, + input: "unlock", + delay: cd + }); +}); + +Instance.OnScriptInput("crosscd", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const callerName = caller.GetEntityName(); + if (!callerName) { + return; + } + + const now = Instance.GetGameTime(); + const cdEndTime = cooldowns.get(callerName); + if (cdEndTime !== undefined && now < cdEndTime) { + return; + } + + const baseCd = 40; + const cd = GetAdjustedCooldownSeconds(baseCd); + cooldowns.set(callerName, now + cd); + + Instance.EntFireAtName({ + name: callerName, + input: "unlock", + delay: cd + }); +}); + +Instance.OnScriptInput("ammocd", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const callerName = caller.GetEntityName(); + if (!callerName) { + return; + } + + const now = Instance.GetGameTime(); + const cdEndTime = cooldowns.get(callerName); + if (cdEndTime !== undefined && now < cdEndTime) { + return; + } + + const baseCd = 40; + const cd = GetAdjustedCooldownSeconds(baseCd); + cooldowns.set(callerName, now + cd); + + Instance.EntFireAtName({ + name: callerName, + input: "unlock", + delay: cd + }); +}); + +Instance.OnScriptInput("randomusecd", (inputData) => { + const caller = inputData?.caller; + if (!caller || !caller.IsValid()) { + return; + } + const callerName = caller.GetEntityName(); + if (!callerName) { + return; + } + + const now = Instance.GetGameTime(); + const cdEndTime = cooldowns.get(callerName); + if (cdEndTime !== undefined && now < cdEndTime) { + return; + } + + const baseCd = 600; + const cd = GetAdjustedCooldownSeconds(baseCd); + cooldowns.set(callerName, now + cd); + + Instance.EntFireAtName({ + name: callerName, + input: "unlock", + delay: cd + }); +}); + +function SetupRandomShop() { + const shuffled = [...SHOP_RANDOM_LIST].sort(() => Math.random() - 0.5); + const newRandomItems = shuffled.slice(0, 2); + + for (const newItem of newRandomItems) { + if (newItem) { + state.tPurchases[newItem.key] = false; + } + } + + currentRoundRandomItems = newRandomItems; + + const priceDisplayNames1 = ["buyrandom1_c", "buyrandom1_c1", "buyrandom1_c2"]; + const priceDisplayNames2 = ["buyrandom2_c", "buyrandom2_c1", "buyrandom2_c2"]; + + const priceDisplayMap = [priceDisplayNames1, priceDisplayNames2]; + + for (let i = 0; i < RANDOM_SHOP_POSITIONS.length; i++) { + const pos = RANDOM_SHOP_POSITIONS[i]; + const item = currentRoundRandomItems[i]; + + const priceDisplayNames = priceDisplayMap[i]; + for (const priceName of priceDisplayNames) { + const priceEntity = Instance.FindEntityByName(priceName); + if (priceEntity && item) { + if (state.buyrandomLocked) { + Instance.EntFireAtTarget({ + target: priceEntity, + input: "SetMessage", + value: "LOCK", + delay: 0 + }); + } else { + Instance.EntFireAtTarget({ + target: priceEntity, + input: "SetMessage", + value: `${item.cost}G`, + delay: 0 + }); + } + } else if (priceEntity) { + Instance.EntFireAtTarget({ + target: priceEntity, + input: "SetMessage", + value: "---", + delay: 0 + }); + } + } + + if (item) { + const modelEntity = Instance.FindEntityByName(item.modelName); + if (modelEntity) { + if (state.buyrandomLocked) { + modelEntity.Teleport({ + position: { x: 0, y: 0, z: -10000 }, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } else { + modelEntity.Teleport({ + position: { x: pos.x, y: pos.y, z: pos.z }, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } + } + } + } + + for (const item of SHOP_RANDOM_LIST) { + const modelEntity = Instance.FindEntityByName(item.modelName); + if (modelEntity) { + let isInShop = false; + for (const roundItem of currentRoundRandomItems) { + if (roundItem && roundItem.key === item.key) { + isInShop = true; + break; + } + } + if (!isInShop || state.buyrandomLocked) { + modelEntity.Teleport({ + position: { x: 0, y: 0, z: -10000 }, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } + } + } +} + +function GetCurrentRoundItemByPosition(positionIndex) { + if (positionIndex >= 0 && positionIndex < currentRoundRandomItems.length) { + return currentRoundRandomItems[positionIndex]; + } + return null; +} + +function HandleBuyRandomItem(inputData, positionIndex) { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetClassName() !== "player") { + return; + } + + if (!IsCTPlayer(activator)) { + return; + } + + if (state.buyrandomLocked) { + return; + } + + const item = GetCurrentRoundItemByPosition(positionIndex); + if (!item) { + return; + } + + if (state.tPurchases[item.key]) { + return; + } + + const ctrl = activator.GetPlayerController(); + if (!ctrl) { + return; + } + const slot = ctrl.GetPlayerSlot(); + + if (!state.ctPurchaseCounts[slot]) { + state.ctPurchaseCounts[slot] = {}; + } + if (!state.ctPurchaseCounts[slot][item.key]) { + state.ctPurchaseCounts[slot][item.key] = 0; + } + const MAX_RANDOM_PURCHASES_PER_CT = 1; + if (!state.zmrandom.noPurchaseLimit && state.ctPurchaseCounts[slot][item.key] >= MAX_RANDOM_PURCHASES_PER_CT) { + return; + } + + if (!SpendMoney(item.cost)) { + return; + } + + state.tPurchases[item.key] = true; + state.ctPurchaseCounts[slot][item.key]++; + + const template = Instance.FindEntityByName(item.template); + if (template) { + const position = activator.GetAbsOrigin(); + const angles = activator.GetAbsAngles(); + template.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); + } + + const modelEntity = Instance.FindEntityByName(item.modelName); + if (modelEntity) { + const currentPos = modelEntity.GetAbsOrigin(); + modelEntity.Teleport({ + position: { x: currentPos.x, y: currentPos.y, z: currentPos.z - 300 }, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } + + const priceDisplayNamesMap = [ + ["buyrandom1_c", "buyrandom1_c1", "buyrandom1_c2"], + ["buyrandom2_c", "buyrandom2_c1", "buyrandom2_c2"] + ]; + + const priceDisplayNames = priceDisplayNamesMap[positionIndex] || priceDisplayNamesMap[0]; + + for (const priceName of priceDisplayNames) { + const priceEntity = Instance.FindEntityByName(priceName); + if (priceEntity) { + Instance.EntFireAtTarget({ + target: priceEntity, + input: "SetMessage", + value: "SELL OUT", + delay: 0 + }); + } + } + } catch (error) { + } +} + +Instance.OnScriptInput("buyrandom1", (inputData) => HandleBuyRandomItem(inputData, 0)); +Instance.OnScriptInput("buyrandom2", (inputData) => HandleBuyRandomItem(inputData, 1)); +Instance.OnScriptInput("spawngroup1", () => SpawnGroup(SpawnDataGroup1)); + +Instance.OnScriptInput("pill", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (!IsCTPlayer(activator)) { + return; + } + + let pawn = activator; + if (activator.GetClassName() !== "player") { + const owner = activator.GetOwner(); + if (owner && owner.IsValid()) { + pawn = owner; + } + } + + const ctrl = pawn.GetPlayerController(); + if (!ctrl) { + return; + } + + ApplyPillBonus(); + + const now = Instance.GetGameTime(); + pawn.__shieldProtectUntil = now + 5; + + const protectTemplate = Instance.FindEntityByName("@temp_protect"); + if (protectTemplate) { + protectTemplate.ForceSpawn(pawn.GetAbsOrigin(), { pitch: 0, yaw: 0, roll: 0 }); + } + + Instance.ServerCommand("say ** " + ctrl.GetPlayerName() + " used pill! 5s invulnerable + random stat x5 **"); + + } catch (error) { + } +}); +Instance.OnScriptInput("spawngroup2", () => SpawnGroup(SpawnDataGroup2)); +Instance.OnScriptInput("spawngroup3", () => SpawnGroup(SpawnDataGroup3)); +Instance.OnScriptInput("spawngroup4", () => SpawnGroup(SpawnDataGroup4)); +Instance.OnScriptInput("spawngroup5", () => SpawnGroup(SpawnDataGroup5)); +Instance.OnScriptInput("spawngroup6", () => SpawnGroup(SpawnDataGroup6)); +Instance.OnScriptInput("spawngroup7", () => { SpawnGroup(SpawnDataGroup7); SpawnMilkDragonAtFixedPositions(); }); +Instance.OnScriptInput("milkdragonspawn", () => SpawnMilkDragonAtFixedPositions()); + +Instance.OnScriptInput("refresh", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (!IsCTPlayer(activator)) { + return; + } + + if (state.buyrandomLocked) { + return; + } + + if (!SpendMoney(30)) { + return; + } + + SetupRandomShop(); + Instance.ServerCommand("say ** refresh **"); + + } catch (error) { + } +}); + +Instance.OnScriptInput("godshieldprotect", (inputData) => { + try { + const activator = inputData.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetClassName() !== "player") { + return; + } + + if (!IsCTPlayer(activator)) { + return; + } + + const now = Instance.GetGameTime(); + activator.__godshieldProtectUntil = now + 1.5; + activator.__godshieldProtectTempSpawned = false; + } catch (error) { + + } +}); + +Instance.OnScriptInput("shieldprotect", (inputData) => { + try { + const activator = inputData.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetClassName() !== "player") { + return; + } + + if (!IsCTPlayer(activator)) { + return; + } + + const now = Instance.GetGameTime(); + activator.__shieldProtectUntil = now + 1.5; + activator.__shieldProtectTempSpawned = false; + } catch (error) { + + } +}); + +Instance.OnScriptInput("drop", (inputData) => { + try { + const caller = inputData.caller; + if (!caller || !caller.IsValid()) { + return; + } + + const position = caller.GetAbsOrigin(); + + if (state.zmrandom.banana) { + const bananaTemplate = Instance.FindEntityByName("@temp_banana"); + if (bananaTemplate) { + const angles = caller.GetAbsAngles(); + bananaTemplate.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); + return; + } + } + + DropCoins(position); + } catch (error) { + } +}); + +function DropMoreAtCaller(position, angles) { + if (state.zmrandom.banana) { + const bananaTemplate = Instance.FindEntityByName("@temp_banana"); + if (bananaTemplate) { + bananaTemplate.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); + return; + } + } + + const r = Math.random(); + let templateName; + if (r < 0.05) { + templateName = Math.random() < 0.5 ? "@temp_heal" : "@temp_shield"; + } else if (r < 0.25) { + templateName = "@temp_10"; + } else if (r < 0.30) { + templateName = "@temp_20"; + } else { + return; + } + + const template = Instance.FindEntityByName(templateName); + if (!template) { + return; + } + + template.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); +} + +Instance.OnScriptInput("drop_more", (inputData) => { + try { + const caller = inputData.caller; + if (!caller || !caller.IsValid()) { + return; + } + const position = caller.GetAbsOrigin(); + const angles = caller.GetAbsAngles(); + DropMoreAtCaller(position, angles); + } catch (error) { + } +}); + +function DropShopItemAtCaller(position, angles) { + const shopItems = [ + { template: "@temp_axemodel", name: "axe" }, + { template: "@temp_pushmodel", name: "push" }, + { template: "@temp_godshieldmodel", name: "godshield" }, + { template: "@temp_ammomodel", name: "ammo" }, + { template: "@temp_pill", name: "pill" }, + { template: "@temp_nukemini", name: "nukemini" }, + { template: "@temp_random", name: "random" } + ]; + + const item = shopItems[Math.floor(Math.random() * shopItems.length)]; + const template = Instance.FindEntityByName(item.template); + + if (!template) { + return; + } + + template.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); +} + +Instance.OnScriptInput("drop_shop_item", (inputData) => { + try { + const caller = inputData.caller; + if (!caller || !caller.IsValid()) { + return; + } + const position = caller.GetAbsOrigin(); + const angles = caller.GetAbsAngles(); + DropShopItemAtCaller(position, angles); + } catch (error) { + } +}); + +function HandleCoinCollection(inputData, amount) { + try { + const slot = GetPlayerSlotFromInput(inputData || {}); + if (slot === null) { + return; + } + const validated = ValidateCTPlayer(slot); + if (!validated) { + return; + } + + AddMoney(amount); + } catch (error) { + } +} + +Instance.OnScriptInput("collectcoin_10", (inputData) => HandleCoinCollection(inputData, 10)); +Instance.OnScriptInput("collectcoin_20", (inputData) => HandleCoinCollection(inputData, 20)); +Instance.OnScriptInput("collectcoin_50", (inputData) => HandleCoinCollection(inputData, 50)); + +Instance.OnScriptInput("add", (inputData) => HandleCoinCollection(inputData, 100)); + +Instance.OnScriptInput("npc_move_start", StartNpcMovement); +Instance.OnScriptInput("npc_move_stop", (inputData) => { + StopNpcMovement(inputData); +}); + +Instance.OnScriptInput("magic", (inputData) => { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + const now = Instance.GetGameTime(); + + const baseStunDuration = 4; + const teamStats = GetCTTeamStats(); + const cdReduction = teamStats.cdReduction || 0; + const stunDuration = baseStunDuration * (1 - cdReduction); + const stunEndTime = now + stunDuration; + + const ctrl = activator.GetPlayerController(); + if (!ctrl) { + return; + } + const slot = ctrl.GetPlayerSlot(); + + activatorStunState.set(slot, { + stunEndTime, + stunDuration, + __invalidated: false, + __activatorRef: activator + }); + + Instance.SetNextThink(0.1); + + const globalCd = 3; + if (now - magicLastSpawnTime < globalCd) { + return; + } + + const template = Instance.FindEntityByName("@temp_magic"); + if (!template) { + return; + } + + const position = activator.GetAbsOrigin(); + const angles = activator.GetAbsAngles(); + template.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); + + magicLastSpawnTime = now; +}); + +function playSecretSoundForActivator(activator) { + if (!activator) { + return; + } + + const pawn = activator; + const ctrl = typeof pawn.GetPlayerController === "function" + ? pawn.GetPlayerController() + : undefined; + + if (!ctrl || typeof ctrl.GetPlayerSlot !== "function") { + return; + } + + const slot = ctrl.GetPlayerSlot(); + + Instance.ClientCommand(slot, 'play "sounds/lol.vsnd"'); +} + +function playSteamSoundForActivator(activator) { + if (!activator) { + return; + } + + const pawn = activator; + const ctrl = typeof pawn.GetPlayerController === "function" + ? pawn.GetPlayerController() + : undefined; + + if (!ctrl || typeof ctrl.GetPlayerSlot !== "function") { + return; + } + + const slot = ctrl.GetPlayerSlot(); + + Instance.ClientCommand(slot, 'play "sounds/steam.vsnd"'); +} + +function HandleBuyArtifact(inputData, artifact) { + try { + const slot = ValidateCTPlayerForShop(inputData); + if (slot === null) { + return; + } + + if (!SpendMoney(artifact.cost)) { + return; + } + + const activator = inputData.activator; + if (!activator || !activator.IsValid()) { + return; + } + + const template = Instance.FindEntityByName(artifact.template); + if (!template) { + return; + } + + const position = activator.GetAbsOrigin(); + const angles = activator.GetAbsAngles(); + template.ForceSpawn(position, { pitch: angles.pitch, yaw: angles.yaw, roll: angles.roll }); + + const priceEntity = Instance.FindEntityByName(artifact.input + "_c"); + if (priceEntity) { + Instance.EntFireAtTarget({ + target: priceEntity, + input: "SetMessage", + value: "SELL OUT", + delay: 0 + }); + } + } catch (error) { + } +} + +for (const artifact of RESERVED_ARTIFACTS) { + Instance.OnScriptInput(artifact.input, (inputData) => HandleBuyArtifact(inputData, artifact)); +} + +Instance.OnScriptInput("secretsound", ({ activator }) => { + playSecretSoundForActivator(activator); +}); + +Instance.OnScriptInput("secretsound2", ({ activator }) => { + playSteamSoundForActivator(activator); +}); + +Instance.OnScriptInput("gay", ({ activator }) => { + try { + if (!activator || !activator.IsValid()) { + return; + } + + const template = Instance.FindEntityByName("@temp_gay"); + if (!template || !template.IsValid()) { + return; + } + + template.ForceSpawn(activator.GetAbsOrigin(), { pitch: 0, yaw: 0, roll: 0 }); + } catch (error) { + } +}); + +Instance.OnScriptInput("lol", ({ activator }) => { + try { + if (!activator || !activator.IsValid()) { + return; + } + + const ctrl = activator.GetPlayerController(); + if (!ctrl) { + return; + } + const slot = ctrl.GetPlayerSlot(); + + const now = Instance.GetGameTime(); + const LOL_TP_COOLDOWN = 1.0; + state.lolTeleportCooldown.set(slot, now + LOL_TP_COOLDOWN); + + playSecretSoundForActivator(activator); + activator.Teleport({ + position: { x: -12218, y: 11210.6, z: -1445.99 }, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + ScheduleLolTeleport(activator, 14, true); + } catch (e) { + } +}); + +Instance.OnScriptInput("tpteam", (inputData) => { + try { + const activator = inputData?.activator || inputData?.caller; + + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetClassName() !== "player") { + return; + } + + if (activator.GetTeamNumber() !== CT_TEAM) { + return; + } + + const currentHealth = activator.GetHealth(); + if (currentHealth <= 0) { + return; + } + + const now = Instance.GetGameTime(); + const TPTEAM_COOLDOWN = 1.0; + + const ctCandidates = []; + const tCandidates = []; + const players = Instance.FindEntitiesByClass("player"); + for (const p of players) { + if (!p || !p.IsValid()) continue; + if (!p.IsAlive()) continue; + if (p === activator) continue; + + const ctrl = p.GetPlayerController(); + const slot = ctrl ? ctrl.GetPlayerSlot() : -1; + const cooldownEnd = state.tpteamCooldown.get(slot); + if (cooldownEnd !== undefined && now < cooldownEnd) continue; + + if (p.GetTeamNumber() === CT_TEAM) { + ctCandidates.push(p); + } else if (p.GetTeamNumber() === T_TEAM) { + tCandidates.push(p); + } + } + + if (ctCandidates.length >= 1) { + const healthCost = Math.floor(currentHealth * 0.4); + activator.SetHealth(currentHealth - healthCost); + + const target = ctCandidates[Math.floor(Math.random() * ctCandidates.length)]; + activator.Teleport({ + position: target.GetAbsOrigin(), + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + + const activatorController = activator.GetPlayerController(); + if (activatorController) { + state.tpteamCooldown.set(activatorController.GetPlayerSlot(), now + TPTEAM_COOLDOWN); + } + const targetController = target.GetPlayerController(); + if (targetController) { + state.tpteamCooldown.set(targetController.GetPlayerSlot(), now + TPTEAM_COOLDOWN); + } + return; + } + + if (tCandidates.length === 0) { + return; + } + + const healthCostT = Math.floor(currentHealth * 0.4); + activator.SetHealth(currentHealth - healthCostT); + + const targetT = tCandidates[Math.floor(Math.random() * tCandidates.length)]; + activator.Teleport({ + position: targetT.GetAbsOrigin(), + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + + const activatorControllerT = activator.GetPlayerController(); + if (activatorControllerT) { + state.tpteamCooldown.set(activatorControllerT.GetPlayerSlot(), now + TPTEAM_COOLDOWN); + } + const targetControllerT = targetT.GetPlayerController(); + if (targetControllerT) { + state.tpteamCooldown.set(targetControllerT.GetPlayerSlot(), now + TPTEAM_COOLDOWN); + } + } catch (e) { + } +}); + +function ResetShopAndStats() { + state.ctPurchaseCounts = {}; + state.ctTeamStats.money = 0; + state.ctTeamStats.hpBonus = 0; + state.ctTeamStats.armorReduction = 0; + state.ctTeamStats.cdReduction = 0; + state.ctTeamStats.luckValue = 0; + + state.tPurchases.magicHand = false; + state.tPurchases.hammer = false; + state.tPurchases.doakesDoom = false; + state.tPurchases.axe = false; + state.tPurchases.push = false; + state.tPurchases.box = false; + state.tPurchases.godshield = false; + state.tPurchases.jump = false; + state.tPurchases.ammo = false; + state.tPurchases.wd40 = false; + state.handTimerStartTime = null; + + UpdateAllCTHealth(); + UpdateMoneyDisplay(); + UpdateAllDisplays(); +} + +Instance.OnScriptInput("clear", (inputData) => { + try { + ResetShopAndStats(); + } catch (error) { + } +}); + +Instance.OnScriptInput("loadhp", (inputData) => { + try { + UpdateAllCTHealth(); + Instance.ServerCommand("say HP properties refreshed for all CT players!"); + } catch (error) { + } +}); + +Instance.OnActivate(() => { + UpdateMoneyDisplay(); + UpdateAllDisplays(); + UpdateWinDisplay(); + SetupRandomShop(); +}); + +Instance.OnScriptInput("win", () => { + try { + state.totalWins += 1; + SaveGameData(); + + if (state.totalWins >= 10) { + state.pendingExRelay = true; + } + + UpdateWinDisplay(); + Instance.ServerCommand(`say server wins: ${state.totalWins}`); + } catch (error) { + } +}); + +Instance.OnScriptInput("zmrandom_start", () => { + try { + state.zmrandom.enabled = true; + state.zmrandom.exSelectActive = true; + state.zmrandom.started = true; + state.zmrandom.noPurchaseLimit = true; + state.buyrandomLocked = false; + state.moneyMaxLimit = 999; + ShuffleZMSEvents(); + StartExSelectMovement(); + SetupRandomShop(); + Instance.ServerCommand('say EX ZMRandom events enabled! zombies can select one event per round.'); + } catch (error) { + } +}); + +Instance.OnScriptInput("zmrandom_end", () => { + try { + state.zmrandom.enabled = false; + state.zmrandom.noPurchaseLimit = false; + state.zmrandom.exSelectActive = false; + state.zmrandom.started = false; + state.buyrandomLocked = true; + state.moneyMaxLimit = 500; + EndZMEvent(); + SetupRandomShop(); + Instance.ServerCommand('say EX ZMRandom events disabled.'); + } catch (error) { + } +}); + +Instance.OnScriptInput("zmrandom1", (inputData) => HandleZMRandomSelection(inputData, 0)); +Instance.OnScriptInput("zmrandom2", (inputData) => HandleZMRandomSelection(inputData, 1)); +Instance.OnScriptInput("zmrandom3", (inputData) => HandleZMRandomSelection(inputData, 2)); +Instance.OnScriptInput("zmrandom4", (inputData) => HandleZMRandomSelection(inputData, 3)); +Instance.OnScriptInput("zmrandom5", (inputData) => HandleZMRandomSelection(inputData, 4)); +Instance.OnScriptInput("zmrandom6", (inputData) => HandleZMRandomSelection(inputData, 5)); +Instance.OnScriptInput("zmrandom7", (inputData) => HandleZMRandomSelection(inputData, 6)); +Instance.OnScriptInput("zmrandom8", (inputData) => HandleZMRandomSelection(inputData, 7)); + +Instance.OnScriptInput("zmhome", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetClassName() !== "player") { + return; + } + + activator.Teleport({ + position: { x: -13212.8, y: 11068.4, z: -1415.69 }, + angles: { pitch: 0, yaw: 90, roll: 0 }, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } catch (error) { + } +}); + +Instance.OnScriptInput("humanhome", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetClassName() !== "player") { + return; + } + + activator.Teleport({ + position: { x: -11042.2, y: 10727.7, z: -1356.91 }, + angles: { pitch: 0, yaw: 90, roll: 0 }, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } catch (error) { + } +}); + +Instance.OnScriptInput("limitammo", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetTeamNumber() !== T_TEAM) { + return; + } + + if (!state.zmrandom.enabled) { + return; + } + + if (state.zmrandom.tPlayerUsedEvent) { + return; + } + + const eventIndex = state.zmrandom.selectedEventKeys.indexOf("limitammo"); + if (eventIndex === -1) { + return; + } + + state.zmrandom.tPlayerUsedEvent = true; + state.zmrandom.currentSelectedIndex = eventIndex; + state.zmrandom.limitammo = true; + + if (!state.zmrandom.usedEventKeysHistory.includes("limitammo")) { + state.zmrandom.usedEventKeysHistory.push("limitammo"); + } + } catch (error) { + } +}); + +Instance.OnScriptInput("rain", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetTeamNumber() !== T_TEAM) { + return; + } + + if (!state.zmrandom.enabled) { + return; + } + + if (state.zmrandom.tPlayerUsedEvent) { + return; + } + + const eventIndex = state.zmrandom.selectedEventKeys.indexOf("rain"); + if (eventIndex === -1) { + return; + } + + state.zmrandom.tPlayerUsedEvent = true; + state.zmrandom.currentSelectedIndex = eventIndex; + state.zmrandom.rain = true; + state.zmrandom.rainTimerStartTime = Instance.GetGameTime(); + Instance.SetNextThink(0.1); + + if (!state.zmrandom.usedEventKeysHistory.includes("rain")) { + state.zmrandom.usedEventKeysHistory.push("rain"); + } + + Instance.EntFireAtName({ + name: "rain_relay", + input: "Trigger", + delay: 0 + }); + } catch (error) { + } +}); + +Instance.OnScriptInput("banana", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetTeamNumber() !== T_TEAM) { + return; + } + + if (!state.zmrandom.enabled) { + return; + } + + if (state.zmrandom.tPlayerUsedEvent) { + return; + } + + const eventIndex = state.zmrandom.selectedEventKeys.indexOf("banana"); + if (eventIndex === -1) { + return; + } + + state.zmrandom.tPlayerUsedEvent = true; + state.zmrandom.currentSelectedIndex = eventIndex; + state.zmrandom.banana = true; + + if (!state.zmrandom.usedEventKeysHistory.includes("banana")) { + state.zmrandom.usedEventKeysHistory.push("banana"); + } + } catch (error) { + } +}); + +Instance.OnScriptInput("doakescome", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetTeamNumber() !== T_TEAM) { + return; + } + + if (!state.zmrandom.enabled) { + return; + } + + if (state.zmrandom.tPlayerUsedEvent) { + return; + } + + const eventIndex = state.zmrandom.selectedEventKeys.indexOf("doakescome"); + if (eventIndex === -1) { + return; + } + + state.zmrandom.tPlayerUsedEvent = true; + state.zmrandom.currentSelectedIndex = eventIndex; + state.zmrandom.doakescome = true; + state.zmrandom.doakescomeTimerStartTime = Instance.GetGameTime(); + Instance.SetNextThink(0.1); + + if (!state.zmrandom.usedEventKeysHistory.includes("doakescome")) { + state.zmrandom.usedEventKeysHistory.push("doakescome"); + } + } catch (error) { + } +}); + +Instance.OnScriptInput("deadman", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetTeamNumber() !== T_TEAM) { + return; + } + + if (!state.zmrandom.enabled) { + return; + } + + if (state.zmrandom.tPlayerUsedEvent) { + return; + } + + const eventIndex = state.zmrandom.selectedEventKeys.indexOf("deadman"); + if (eventIndex === -1) { + return; + } + + state.zmrandom.tPlayerUsedEvent = true; + state.zmrandom.currentSelectedIndex = eventIndex; + state.zmrandom.deadman = true; + state.zmrandom.deadmanTimerStartTime = Instance.GetGameTime(); + Instance.SetNextThink(0.1); + + if (!state.zmrandom.usedEventKeysHistory.includes("deadman")) { + state.zmrandom.usedEventKeysHistory.push("deadman"); + } + } catch (error) { + } +}); + +Instance.OnScriptInput("deadhand", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetTeamNumber() !== T_TEAM) { + return; + } + + if (!state.zmrandom.enabled) { + return; + } + + if (state.zmrandom.tPlayerUsedEvent) { + return; + } + + const eventIndex = state.zmrandom.selectedEventKeys.indexOf("deadhand"); + if (eventIndex === -1) { + return; + } + + state.zmrandom.tPlayerUsedEvent = true; + state.zmrandom.currentSelectedIndex = eventIndex; + state.zmrandom.deadhand = true; + state.zmrandom.deadhandTimerStartTime = Instance.GetGameTime(); + Instance.SetNextThink(0.1); + + if (!state.zmrandom.usedEventKeysHistory.includes("deadhand")) { + state.zmrandom.usedEventKeysHistory.push("deadhand"); + } + } catch (error) { + } +}); + +Instance.OnScriptInput("vip", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetTeamNumber() !== T_TEAM) { + return; + } + + if (!state.zmrandom.enabled) { + return; + } + + if (state.zmrandom.tPlayerUsedEvent) { + return; + } + + const eventIndex = state.zmrandom.selectedEventKeys.indexOf("vip"); + if (eventIndex === -1) { + return; + } + + state.zmrandom.tPlayerUsedEvent = true; + state.zmrandom.currentSelectedIndex = eventIndex; + state.zmrandom.vip = true; + state.zmrandom.vipPlayerSlot = null; + state.zmrandom.vipTemplateSpawned = false; + SelectRandomVipAndSpawnTemplate(); + + if (!state.zmrandom.usedEventKeysHistory.includes("vip")) { + state.zmrandom.usedEventKeysHistory.push("vip"); + } + } catch (error) { + } +}); + +Instance.OnScriptInput("hammer", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetTeamNumber() !== T_TEAM) { + return; + } + + if (!state.zmrandom.enabled) { + return; + } + + if (state.zmrandom.tPlayerUsedEvent) { + return; + } + + const eventIndex = state.zmrandom.selectedEventKeys.indexOf("hammer"); + if (eventIndex === -1) { + return; + } + + state.zmrandom.tPlayerUsedEvent = true; + state.zmrandom.currentSelectedIndex = eventIndex; + SpawnHammerAtAllTPlayers(); + + if (!state.zmrandom.usedEventKeysHistory.includes("hammer")) { + state.zmrandom.usedEventKeysHistory.push("hammer"); + } + } catch (error) { + } +}); + +Instance.OnScriptReload({ + after: () => { + UpdateMoneyDisplay(); + UpdateAllDisplays(); + UpdateWinDisplay(); + } +}); + +Instance.OnScriptInput("sandstorm", (inputData) => { + try { + const activator = inputData?.activator; + const caller = inputData?.caller; + + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetClassName() !== "player") { + return; + } + + if (!activator.IsAlive()) { + return; + } + + const ctrl = activator.GetPlayerController(); + if (!ctrl) { + return; + } + + const slot = ctrl.GetPlayerSlot(); + + if (sandstormState.has(slot)) { + return; + } + + StartSandstormEffect(activator, caller); + } catch (error) { + } +}); + +Instance.OnGunReload((event) => { + if (!state.zmrandom.limitammo) return; + LimitPlayerAmmoOnWeaponSwitch(event.weapon?.GetOwner()); +}); + +Instance.OnGunFire((event) => { + if (!state.zmrandom.limitammo) return; + LimitPlayerAmmoOnWeaponSwitch(event.weapon?.GetOwner()); +}); + +Instance.OnPlayerReset((event) => { + if (state.zmrandom.limitammo) { + LimitPlayerAmmoOnWeaponSwitch(event.player); + } +}); + +const MILKMAN_PHASES = { + LIFT_UP: 0, + MOVE_FORWARD: 1, + EXECUTE: 2 +}; + +const MILKMAN_CONFIG = { + LIFT_DURATION: 3.0, + MOVE_DURATION: 2.0, + LIFT_HEIGHT: 30, + MOVE_DISTANCE: 30, + LIFT_SPEED: 10, + MOVE_SPEED: 10 +}; + +function StartMilkmanEffect(activator) { + if (!activator || !activator.IsValid()) { + return; + } + + const ctrl = activator.GetPlayerController(); + if (!ctrl) { + return; + } + + const slot = ctrl.GetPlayerSlot(); + const now = Instance.GetGameTime(); + + milkmanState.set(slot, { + activator: activator, + phase: MILKMAN_PHASES.LIFT_UP, + phaseStartTime: now, + startPosition: activator.GetAbsOrigin(), + targetPosition: null + }); + + Instance.SetNextThink(0.1); +} + +function ProcessMilkmanState() { + if (milkmanState.size === 0) { + return false; + } + + const now = Instance.GetGameTime(); + let hasActive = false; + const toDelete = []; + + for (const [slot, data] of milkmanState) { + if (!data.activator || !data.activator.IsValid()) { + toDelete.push(slot); + continue; + } + + const activator = data.activator; + const elapsed = now - data.phaseStartTime; + hasActive = true; + + let frozenPosition = null; + + if (data.phase === MILKMAN_PHASES.LIFT_UP) { + if (elapsed >= MILKMAN_CONFIG.LIFT_DURATION) { + data.phase = MILKMAN_PHASES.MOVE_FORWARD; + data.phaseStartTime = now; + data.startPosition = activator.GetAbsOrigin(); + + const angles = activator.GetAbsAngles(); + const forward = ForwardFromAngles(angles); + const currentPos = data.startPosition; + data.targetPosition = { + x: currentPos.x + forward.x * MILKMAN_CONFIG.MOVE_DISTANCE, + y: currentPos.y + forward.y * MILKMAN_CONFIG.MOVE_DISTANCE, + z: currentPos.z + MILKMAN_CONFIG.LIFT_HEIGHT + }; + } else { + const progress = elapsed / MILKMAN_CONFIG.LIFT_DURATION; + const currentPos = data.startPosition; + const newZ = currentPos.z + (MILKMAN_CONFIG.LIFT_HEIGHT * progress); + + frozenPosition = { x: currentPos.x, y: currentPos.y, z: newZ }; + } + } else if (data.phase === MILKMAN_PHASES.MOVE_FORWARD) { + if (elapsed >= MILKMAN_CONFIG.MOVE_DURATION) { + data.phase = MILKMAN_PHASES.EXECUTE; + data.phaseStartTime = now; + } else { + const progress = elapsed / MILKMAN_CONFIG.MOVE_DURATION; + const currentPos = data.startPosition; + const targetPos = data.targetPosition; + + if (targetPos) { + const newPos = { + x: currentPos.x + (targetPos.x - currentPos.x) * progress, + y: currentPos.y + (targetPos.y - currentPos.y) * progress, + z: targetPos.z + }; + + frozenPosition = newPos; + } + } + } else if (data.phase === MILKMAN_PHASES.EXECUTE) { + if (elapsed >= 0.1) { + const deathPosition = activator.GetAbsOrigin(); + + activator.Kill(); + + SpawnCoinsAtPosition(deathPosition); + + toDelete.push(slot); + hasActive = false; + } + } + + if (frozenPosition !== null) { + activator.Teleport({ + position: frozenPosition, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } + } + + for (const slot of toDelete) { + milkmanState.delete(slot); + } + + if (hasActive) { + Instance.SetNextThink(0.1); + } + + return hasActive; +} + +function SpawnCoinsAtPosition(position) { + if (Math.random() < 0.30) { + return; + } + + const templates = ["@temp_10", "@temp_20", "@temp_50"]; + + for (let i = 0; i < 3; i++) { + const offsetX = (Math.random() - 0.5) * 100; + const offsetY = (Math.random() - 0.5) * 100; + const coinPosition = { + x: position.x + offsetX, + y: position.y + offsetY, + z: position.z + }; + + const templateName = templates[Math.floor(Math.random() * templates.length)]; + const template = Instance.FindEntityByName(templateName); + if (template && template.IsValid()) { + template.ForceSpawn(coinPosition, { pitch: 0, yaw: Math.random() * 360, roll: 0 }); + } + } +} + +function StartSandstormEffect(activator, caller) { + if (!activator || !activator.IsValid()) { + return; + } + + const ctrl = activator.GetPlayerController(); + if (!ctrl) { + return; + } + + const slot = ctrl.GetPlayerSlot(); + + sandstormState.set(slot, { + activator: activator, + caller: caller, + radius: 100, + startAngle: 0, + startZ: activator.GetAbsOrigin().z, + rotationSpeed: Math.PI * 2, + startTime: Instance.GetGameTime(), + lookAngles: activator.GetAbsAngles() + }); + + Instance.SetNextThink(0.1); +} + +function ProcessSandstormState() { + if (sandstormState.size === 0) { + return false; + } + + const now = Instance.GetGameTime(); + let hasActive = false; + const toDelete = []; + + for (const [slot, data] of sandstormState) { + if (!data.activator || !data.activator.IsValid() || !data.caller || !data.caller.IsValid()) { + toDelete.push(slot); + continue; + } + + hasActive = true; + const elapsed = now - data.startTime; + const duration = 3.0; + + if (elapsed >= duration) { + if (data.activator.IsAlive()) { + data.activator.Kill(); + } + toDelete.push(slot); + } else { + const progress = elapsed / duration; + const callerOrigin = data.caller.GetAbsOrigin(); + const angle = data.startAngle + elapsed * data.rotationSpeed; + + const newX = callerOrigin.x + Math.cos(angle) * data.radius; + const newY = callerOrigin.y + Math.sin(angle) * data.radius; + const targetZ = data.startZ + 700; + const newZ = data.startZ + (targetZ - data.startZ) * progress; + + data.activator.Teleport({ + position: { x: newX, y: newY, z: newZ }, + angles: data.lookAngles, + velocity: { x: 0, y: 0, z: 0 }, + angularVelocity: { x: 0, y: 0, z: 0 } + }); + } + } + + for (const slot of toDelete) { + sandstormState.delete(slot); + } + + if (hasActive) { + Instance.SetNextThink(0.1); + } + + return hasActive; +} + +Instance.OnScriptInput("milkman", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + if (activator.GetClassName() !== "player") { + return; + } + + if (!activator.IsAlive()) { + return; + } + + const ctrl = activator.GetPlayerController(); + if (!ctrl) { + return; + } + + const slot = ctrl.GetPlayerSlot(); + + if (milkmanState.has(slot)) { + return; + } + + StartMilkmanEffect(activator); + + Instance.ServerCommand("say ** Someone sacrificed themselves to the Milkman. **"); + } catch (error) { + } +}); + +Instance.OnScriptInput("killzm", () => { + try { + const players = GetCachedPlayers(); + for (const p of players) { + if (!p || !p.IsValid()) continue; + if (p.GetTeamNumber() !== T_TEAM) continue; + if (!p.IsAlive()) continue; + + p.Kill(); + } + } catch (error) { + } +}); + +const filterState = { + activatorBindings: new Map(), + callerToActivator: new Map() +}; + +function bindfilter(activator, target) { + if (!activator || !activator.IsValid()) return; + if (!target || !target.IsValid()) return; + + let binding = filterState.activatorBindings.get(activator); + if (!binding) { + binding = { target: null, callers: new Map() }; + } + binding.target = target; + filterState.activatorBindings.set(activator, binding); +} + +function bindbutton(caller, activator) { + if (!caller || !caller.IsValid()) return; + if (!activator || !activator.IsValid()) return; + + const existingActivator = filterState.callerToActivator.get(caller); + if (existingActivator && existingActivator !== activator) { + const existingBinding = filterState.activatorBindings.get(existingActivator); + if (existingBinding) { + existingBinding.callers.delete(caller); + if (existingBinding.callers.size === 0) { + filterState.activatorBindings.delete(existingActivator); + } else { + filterState.activatorBindings.set(existingActivator, existingBinding); + } + } + filterState.callerToActivator.delete(caller); + } + + let binding = filterState.activatorBindings.get(activator); + if (!binding) { + binding = { target: null, callers: new Map() }; + } + + binding.callers.set(caller, caller); + filterState.activatorBindings.set(activator, binding); + + filterState.callerToActivator.set(caller, activator); +} + +function clean(caller, activator) { + if (!caller || !caller.IsValid()) return; + + if (!activator) { + activator = filterState.callerToActivator.get(caller); + if (!activator || !activator.IsValid()) return; + } + + filterState.activatorBindings.delete(activator); + + filterState.callerToActivator.forEach((value, key) => { + if (value === activator) { + filterState.callerToActivator.delete(key); + } + }); +} + +function press(inputData) { + const activator = inputData?.activator; + const caller = inputData?.caller; + + if (!activator || !caller) { + return false; + } + + const boundActivator = filterState.callerToActivator.get(caller); + if (!boundActivator || !boundActivator.IsValid()) { + return false; + } + if (boundActivator !== activator) { + return false; + } + + const binding = filterState.activatorBindings.get(activator); + if (!binding || !binding.target) { + return false; + } + + if (!binding.callers.has(caller)) { + return false; + } + + Instance.EntFireAtName({ + name: binding.target.GetEntityName(), + input: "TestActivator", + caller: caller, + activator: activator + }); + + return true; +} + +Instance.OnScriptInput("bindfilter", (inputData) => { + try { + const activator = inputData?.activator; + const caller = inputData?.caller; + if (!activator || !activator.IsValid() || !caller || !caller.IsValid()) return; + bindfilter(activator, caller); + } catch (error) { + } +}); + +Instance.OnScriptInput("bindbutton", (inputData) => { + try { + const caller = inputData?.caller; + const activator = inputData?.activator; + if (!caller || !caller.IsValid() || !activator || !activator.IsValid()) return; + bindbutton(caller, activator); + } catch (error) { + } +}); + +Instance.OnScriptInput("clean", (inputData) => { + try { + const caller = inputData?.caller; + const activator = inputData?.activator; + if (!caller || !caller.IsValid()) return; + clean(caller, activator); + } catch (error) { + } +}); + +Instance.OnScriptInput("press", (inputData) => { + try { + press(inputData); + } catch (error) { + } +}); + + +const GREENSHIT_CONFIG = { + TOTAL_DURATION: 36, + RAINBOW_STEPS: 36 +}; + +const greenshitState = { + players: new Map() +}; + +function HSVtoRGB(h, s, v) { + let r, g, b; + const i = Math.floor(h * 6); + const f = h * 6 - i; + const p = v * (1 - s); + const q = v * (1 - f * s); + const t = v * (1 - (1 - f) * s); + switch (i % 6) { + case 0: r = v; g = t; b = p; break; + case 1: r = q; g = v; b = p; break; + case 2: r = p; g = v; b = t; break; + case 3: r = p; g = q; b = v; break; + case 4: r = t; g = p; b = v; break; + case 5: r = v; g = p; b = q; break; + } + return { + r: Math.round(r * 255), + g: Math.round(g * 255), + b: Math.round(b * 255) + }; +} + +function ProcessGreenshit() { + const now = Instance.GetGameTime(); + const toDelete = []; + + greenshitState.players.forEach((data, pawn) => { + if (!pawn || !pawn.IsValid()) { + toDelete.push(pawn); + return; + } + + if (!pawn.IsAlive()) { + toDelete.push(pawn); + return; + } + + const elapsed = now - data.startTime; + + if (elapsed >= GREENSHIT_CONFIG.TOTAL_DURATION) { + if (!data.killPhaseStarted) { + data.killPhaseStarted = true; + } + + if (Math.random() < 0.5) { + pawn.Kill(); + } + + toDelete.push(pawn); + return; + } + }); + + for (const pawn of toDelete) { + greenshitState.players.delete(pawn); + } + + return greenshitState.players.size > 0; +} + +function ApplyGreenshitToPawn(pawn) { + if (!pawn || !pawn.IsValid() || !pawn.IsAlive()) { + return false; + } + if (greenshitState.players.has(pawn)) { + return false; + } + + const now = Instance.GetGameTime(); + greenshitState.players.set(pawn, { + startTime: now, + killPhaseStarted: false + }); + + const initialRgb = HSVtoRGB(0, 1.0, 1.0); + pawn.SetColor({ r: initialRgb.r, g: initialRgb.g, b: initialRgb.b }); + Instance.ServerCommand('say ** Someone is infected with Greenshit. **'); + + const totalColorChanges = GREENSHIT_CONFIG.TOTAL_DURATION; + const colorInterval = GREENSHIT_CONFIG.TOTAL_DURATION / GREENSHIT_CONFIG.RAINBOW_STEPS; + for (let i = 1; i <= totalColorChanges; i++) { + const hue = (i / GREENSHIT_CONFIG.RAINBOW_STEPS) % 1.0; + const rgb = HSVtoRGB(hue, 1.0, 1.0); + + Instance.EntFireAtTarget({ + target: pawn, + input: "Color", + value: { r: rgb.r, g: rgb.g, b: rgb.b }, + delay: i * colorInterval + }); + } + + return true; +} + +Instance.OnScriptInput("greenshit", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + let pawn = activator; + if (typeof activator.GetPlayerPawn === 'function') { + pawn = activator.GetPlayerPawn(); + } + + ApplyGreenshitToPawn(pawn); + } catch (error) { + } +}); + +function GetPlayerSlotFromEntity(entity) { + if (!entity || !entity.IsValid()) { + return null; + } + if (entity.GetClassName() === "player") { + const ctrl = entity.GetPlayerController(); + return ctrl ? ctrl.GetPlayerSlot() : null; + } + if (entity.GetClassName() === "player_ctrl") { + return entity.GetPlayerSlot(); + } + return null; +} + +Instance.OnScriptInput("pepsi", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + let pawn = activator; + if (typeof activator.GetPlayerPawn === 'function') { + pawn = activator.GetPlayerPawn(); + } + + const slot = GetPlayerSlotFromEntity(pawn); + if (slot === null) { + return; + } + + if (!state.playerRecords.has(slot)) { + state.playerRecords.set(slot, new Set()); + } + const records = state.playerRecords.get(slot); + + if (!records.has("coca")) { + records.add("pepsi"); + return; + } + + records.delete("coca"); + records.delete("pepsi"); + + const playerController = pawn.GetPlayerController(); + if (playerController && playerController.IsValid()) { + const playerName = playerController.GetPlayerName(); + Instance.ServerCommand(`say ** ${playerName} betrayed Coca-Cola for Pepsi-Cola and was struck down by divine retribution. **`); + } + + ApplyGreenshitToPawn(pawn); + } catch (error) { + } +}); + +Instance.OnScriptInput("coca", (inputData) => { + try { + const activator = inputData?.activator; + if (!activator || !activator.IsValid()) { + return; + } + + let pawn = activator; + if (typeof activator.GetPlayerPawn === 'function') { + pawn = activator.GetPlayerPawn(); + } + + const slot = GetPlayerSlotFromEntity(pawn); + if (slot === null) { + return; + } + + if (!state.playerRecords.has(slot)) { + state.playerRecords.set(slot, new Set()); + } + const records = state.playerRecords.get(slot); + + if (!records.has("pepsi")) { + records.add("coca"); + return; + } + + records.delete("pepsi"); + records.delete("coca"); + + const playerController = pawn.GetPlayerController(); + if (playerController && playerController.IsValid()) { + const playerName = playerController.GetPlayerName(); + Instance.ServerCommand(`say ** ${playerName} betrayed Pepsi-Cola for coca-Cola and was struck down by divine retribution. **`); + } + + ApplyGreenshitToPawn(pawn); + } catch (error) { + } +}); + +Instance.OnScriptInput("randomuse", () => { + try { + const choice = Math.random(); + if (choice < 0.5) { + const existingProps = []; + const propMap = []; + if (state.ctTeamStats.armorReduction > 0) { + existingProps.push(state.ctTeamStats.armorReduction); + propMap.push('armorReduction'); + } + if (state.ctTeamStats.cdReduction > 0) { + existingProps.push(state.ctTeamStats.cdReduction); + propMap.push('cdReduction'); + } + if (state.ctTeamStats.luckValue > 0) { + existingProps.push(state.ctTeamStats.luckValue); + propMap.push('luckValue'); + } + for (let i = existingProps.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + const temp = existingProps[i]; + existingProps[i] = existingProps[j]; + existingProps[j] = temp; + } + for (let i = 0; i < propMap.length; i++) { + state.ctTeamStats[propMap[i]] = existingProps[i]; + } + UpdateAllDisplays(); + Instance.ServerCommand("say ** All properties are scrambled. **"); + } else { + if (!state.zmrandom.enabled || state.zmrandom.selectedEvents.length === 0) { + return; + } + const randomIndex = Math.floor(Math.random() * state.zmrandom.selectedEvents.length); + const event = state.zmrandom.selectedEvents[randomIndex]; + if (event) { + state.zmrandom.currentSelectedIndex = randomIndex; + state.zmrandom.currentRoundEvents.push(event); + if (!state.zmrandom.usedEventKeysHistory.includes(event.key)) { + state.zmrandom.usedEventKeysHistory.push(event.key); + } + UpdateZMMessageDisplay(); + ApplyZMEvent(event); + Instance.ServerCommand("say ** A random zmrandom has been triggered. **"); + } + } + Instance.EntFireAtName({ + name: "shop", + input: "RunScriptInput", + value: "buyluck" + }); + } catch (error) { + } +}); + +Instance.OnScriptInput("SetModel", (ctx) => { + const pawn = ctx.activator; + if (pawn && pawn.GetTeamNumber() === CT_TEAM) { + pawn.SetModel("models/player/wolfkk/models/mastermilk/mastermilk.vmdl"); + } +});