Skip to content

Instantly share code, notes, and snippets.

@FirstVertex
Last active August 11, 2023 00:48
Show Gist options
  • Save FirstVertex/8ac1450c8c3cdcdd82a2b68ca28ecd00 to your computer and use it in GitHub Desktop.
Save FirstVertex/8ac1450c8c3cdcdd82a2b68ca28ecd00 to your computer and use it in GitHub Desktop.
Roblox-ts Exploding Orbs
import { Players, ReplicatedStorage } from "@rbxts/services";
const player = Players.LocalPlayer;
const mouse = player.GetMouse();
const orbTemplate = ReplicatedStorage.FindFirstChild('Orb') as BasePart;
const inFrontOfPlayer = new CFrame(0, 0, -2);
const orbSpeed = new Vector3(0, 0, -120);
let hrp: BasePart | undefined = undefined;
function onCharacterAdded(char: Model) {
hrp = char.WaitForChild('HumanoidRootPart') as BasePart;
}
mouse.Button1Down.Connect(() => {
if (!hrp?.Parent) {
return;
}
const orb = orbTemplate.Clone();
orb.CFrame = hrp.CFrame.ToWorldSpace(inFrontOfPlayer);
orb.Parent = game.Workspace;
orb.AssemblyLinearVelocity = orb.CFrame.VectorToWorldSpace(orbSpeed);
});
// for the initial load
const char = player.Character || player.CharacterAdded.Wait()[0];
onCharacterAdded(char);
// for subsequent character loads
player.CharacterAdded.Connect((char: Model) => {
onCharacterAdded(char);
});
// insert at line 8
const launchAngle = CFrame.fromOrientation(math.rad(33), 0, 0);
// append to line 18
.ToWorldSpace(launchAngle)
// insert after "orb.AssemblyLinearVelocity ="
orb.Touched.Connect((op: BasePart) => {
if (!op.IsDescendantOf(char)) {
const orbPos = orb.Position;
orb.Destroy();
const explosion = new Instance('Explosion');
explosion.BlastRadius = 25;
explosion.BlastPressure = 75;
explosion.Position = orbPos;
explosion.Parent = game.Workspace; // BOOM!
}
});
// https://github.com/roblox-aurora/rbx-net
// npm i @rbxts/net --save
// replace the code in shared/module.ts with this
import Net, { Definitions } from "@rbxts/net";
export const Remotes = Net.Definitions.Create({
ShootReq: Definitions.ClientToServerEvent<[]>(),
});
import { Players } from "@rbxts/services";
import { Remotes } from "shared/module";
const player = Players.LocalPlayer;
const mouse = player.GetMouse();
const shootReqEvent = Remotes.Client.Get('ShootReq');
let buttonConnection: RBXScriptConnection | undefined;
function onCharacterAdded() {
if (buttonConnection) {
buttonConnection.Disconnect();
}
// send a request to shoot to the server
buttonConnection = mouse.Button1Down.Connect(shootReqEvent.SendToServer);
}
// for the initial load
if (!player.Character) {
player.CharacterAdded.Wait();
}
onCharacterAdded();
// for subsequent character loads
player.CharacterAdded.Connect(onCharacterAdded);
import { ReplicatedStorage } from "@rbxts/services";
import { Remotes } from "shared/module";
const shootReqEvent = Remotes.Server.Get('ShootReq');
const orbTemplate = ReplicatedStorage.FindFirstChild('Orb') as BasePart;
const inFrontOfPlayer = new CFrame(0, 0, -2);
const orbSpeed = new Vector3(0, 0, -120);
const launchAngle = CFrame.fromOrientation(math.rad(33), 0, 0);
shootReqEvent.Connect((player: Player) => {
const char = player.Character;
if (char?.Parent) {
const orb = orbTemplate.Clone();
const hrp = char.FindFirstChild('HumanoidRootPart') as BasePart;
if (!hrp) {
return;
}
orb.CFrame = hrp.CFrame.ToWorldSpace(inFrontOfPlayer).ToWorldSpace(launchAngle);
orb.Parent = game.Workspace;
orb.AssemblyLinearVelocity = orb.CFrame.VectorToWorldSpace(orbSpeed);
orb.Touched.Connect((op: BasePart) => {
if (!op.IsDescendantOf(char)) {
const orbPos = orb.Position;
orb.Destroy();
const explosion = new Instance('Explosion');
explosion.BlastRadius = 25;
explosion.BlastPressure = 80;
explosion.Position = orbPos;
explosion.Parent = game.Workspace; // BOOM!
}
});
}
});
// add to shared/module.ts and paste this content:
export const shotCooldownTime = 2;
// add this to main.server.ts:
const shootCooldowns = new Map<number, number>();
function canShoot(uid: number, stamp: number): boolean {
const nextShoot = shootCooldowns.get(uid);
if (nextShoot) {
return stamp > nextShoot;
}
return true;
}
// add after (if char?.Parent)
const stamp = os.clock();
if (!canShoot(uid, stamp)) {
warn('server: shot is in cooldown');
return;
}
// add after orb.Touched
shootCooldowns.set(uid, stamp + shotCooldownTime);
// add after shootReqEvent.connect
Players.PlayerRemoving.Connect(player => shootCooldowns.delete(player.UserId));
// test the above to insure server-side cooldown is working. also apply client-side cooldown
// add after let buttonConnection
let nextShotTime = 0;
// change handler for mouse.button1down.connect
const stamp = os.clock();
if (!nextShotTime || stamp > nextShotTime) {
shootReqEvent.SendToServer();
nextShotTime = stamp + shotCooldownTime;
} else {
warn('client: shot is in cooldown');
}
// add to the bottom of main.server.ts
function onCharacterAdded(_player: Player, char: Model): void {
const ff = new Instance("ForceField");
ff.Visible = false;
ff.Parent = char;
}
function onPlayerAdded(player: Player): void {
if (player.Character) {
onCharacterAdded(player, player.Character);
}
player.CharacterAdded.Connect(char => onCharacterAdded(player, char));
}
Players.PlayerAdded.Connect((player) => onPlayerAdded(player));
Players.GetPlayers().forEach(player => onPlayerAdded(player));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment