Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
226 changes: 226 additions & 0 deletions 2001/ze_pretender/banana_trigger.js
Original file line number Diff line number Diff line change
@@ -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);
Loading