SC CODE: // Copyright 2024. Civilware. All rights reserved.
// TELA Decentralized Web Document (TELA-DOC-1)
Function InitializePrivate() Uint64
10 IF init() == 0 THEN GOTO 30
20 RETURN 1
30 STORE("nameHdr", "update.js")
31 STORE("descrHdr", "Update JS file")
32 STORE("iconURLHdr", "")
33 STORE("dURL", "update.js")
34 STORE("docType", "TELA-JS-1")
35 STORE("subDir", "")
36 STORE("fileCheckC", "1f583b450e11b0f23248b6206b6162e94c0395b503e4269ec6dc60b9599fc92f")
37 STORE("fileCheckS", "210205474653fe7aaf62b3da588bde91eaa2541ec6e914d395d44d1b4a671de5")
100 RETURN 0
End Function
Function init() Uint64
10 IF EXISTS("owner") == 0 THEN GOTO 30
20 RETURN 1
30 STORE("owner", address())
50 STORE("docVersion", "1.0.0")
60 STORE("hash", HEX(TXID()))
70 STORE("likes", 0)
80 STORE("dislikes", 0)
100 RETURN 0
End Function
Function address() String
10 DIM s as String
20 LET s = SIGNER()
30 IF IS_ADDRESS_VALID(s) THEN GOTO 50
40 RETURN "anon"
50 RETURN ADDRESS_STRING(s)
End Function
Function Rate(r Uint64) Uint64
10 DIM addr as String
15 LET addr = address()
16 IF r < 100 && EXISTS(addr) == 0 && addr != "anon" THEN GOTO 30
20 RETURN 1
30 STORE(addr, ""+r+"_"+BLOCK_HEIGHT())
40 IF r < 50 THEN GOTO 70
50 STORE("likes", LOAD("likes")+1)
60 RETURN 0
70 STORE("dislikes", LOAD("dislikes")+1)
100 RETURN 0
End Function
/*//----------------
// Update Entities
function update(dt) {
updateCamera();
updateViewBox();
updateSpawnTimer(dt);
updateEnemies(dt);
updateProjectiles(dt);
}
function resizeSVG() {
sw = window.innerWidth;
sh = window.innerHeight;
updateViewBox();
}
function updateViewBox() {
if (keys["="]) zoom *= 0.98;
if (keys["-"]) zoom *= 1.02;
const viewW = sw * zoom;
const viewH = sh * zoom;
const camX = camCenter.x - viewW / 2;
const camY = camCenter.y - viewH / 2;
camLeft = camCenter.x - (sw * zoom) / 2;
camTop = camCenter.y - (sh * zoom) / 2;
camRight = camCenter.x + (sw * zoom) / 2;
camBottom = camCenter.y + (sh * zoom) / 2;
svg.setAttribute("viewBox", `${camX} ${camY} ${viewW} ${viewH}`);
}
// Timer
let enemySpawnTimer = 1000;//1 second
function updateSpawnTimer(dt) {
enemySpawnTimer -= dt;
if (enemySpawnTimer <= 0) {
for (const base of game.bases) {
if (base.cooldown > 0) {
base.cooldown -= dt;
continue;
}
const count = game.enemies.filter(e => e.base === base).length;
if (count < base.maxEnemies) {
spawnEnemyFromBase(base);
base.cooldown = base.spawnInterval;
}
}
enemySpawnTimer = 2000;
}
}
function updateCamera(dt) {
// camera follows player
camCenter.x = game.player.x;
camCenter.y = game.player.y;
}
function updateProjectiles(dt) {
// handle projectiles
for (let p of game.projectiles) {
p.x += Math.cos(p.angle) * p.speed * dt;
p.y += Math.sin(p.angle) * p.speed * dt;
p.life -= dt;
}
}
function updateParticles(dt) {
for (let p of game.particles) {
p.x += p.vx * dt;
p.y += p.vy * dt;
p.life -= dt;
}
}
function enemyCanShoot(e) {
const dx = game.player.x - e.x;
const dy = game.player.y - e.y;
const dist = Math.hypot(dx, dy);
if (dist > 800) return false; // max range
if (e.fireCooldown > 0) return false;
// optional: check if enemy is roughly facing the player
const angleToPlayer = Math.atan2(dy, dx);
const diff = Math.abs(Math.atan2(Math.sin(angleToPlayer - e.angle), Math.cos(angleToPlayer - e.angle)));
if (diff > 0.6) return false; // not facing player enough
return true;
}
function getPredictedAim(e) {
const px = game.player.x;
const py = game.player.y;
const pvx = Math.cos(game.player.angle) * game.player.speed;
const pvy = Math.sin(game.player.angle) * game.player.speed;
const ex = e.x;
const ey = e.y;
const bulletSpeed = 900;
const dx = px - ex;
const dy = py - ey;
const dist = Math.hypot(dx, dy);
const t = dist / bulletSpeed;
const predictedX = px + pvx * t;
const predictedY = py + pvy * t;
return Math.atan2(predictedY - ey, predictedX - ex);
}
function getAvoidanceAngle(e) {
const lookDist = 30;
const rays = [
e.angle, // center
e.angle + 0.4, // left
e.angle - 0.4 // right
];
let dangerLeft = false;
let dangerCenter = false;
let dangerRight = false;
for (let i = 0; i < rays.length; i++) {
const ang = rays[i];
const lx = e.x + Math.cos(ang) * lookDist;
const ly = e.y + Math.sin(ang) * lookDist;
for (const obj of worldObjects) {
if (pointInPoly(lx, ly, obj.poly, obj.x, obj.y)) {
if (i === 0) dangerCenter = true;
if (i === 1) dangerLeft = true;
if (i === 2) dangerRight = true;
}
}
}
// Return an angle offset to apply to desiredAngle
if (dangerCenter) {
const side = e.avoidDir ?? (Math.random() < 0.5 ? 1 : -1);
e.avoidDir = side;
return side * 0.8;
}
if (dangerLeft) return -0.4;
if (dangerRight) return +0.4;
return 0; // no avoidance needed
}
function updateEnemies(dt) {
for (let e of game.enemies) {
switch (e.type) {
case "chaser": updateChaser(e, dt); break;
case "strafer": updateStrafer(e, dt); break;
case "tank": updateTank(e, dt); break;
}
}
}
function updateChaser(e, dt) {
// 1. CHASE LOGIC
const dx = game.player.x - e.x;
const dy = game.player.y - e.y;
let desiredAngle = Math.atan2(dy, dx);
// 2. AVOIDANCE LOGIC
desiredAngle += getAvoidanceAngle(e);
// Smooth steering toward desiredAngle
let diff = desiredAngle - e.angle;
diff = Math.atan2(Math.sin(diff), Math.cos(diff));
e.angle += diff * 0.15;
// 4. MOVE
e.x += Math.cos(e.angle) * e.speed * dt;
e.y += Math.sin(e.angle) * e.speed * dt;
// Firing
e.fireCooldown -= dt;
// after movement
if (enemyCanShoot(e)) {
const aimAngle = getPredictedAim(e);
spawnEnemyBullet(e.x, e.y, aimAngle);
e.fireCooldown = e.fireRate;
}
}
function updateStrafer(e, dt) {
const dx = game.player.x - e.x;
const dy = game.player.y - e.y;
const dist = Math.hypot(dx, dy);
const angleToPlayer = Math.atan2(dy, dx);
let desiredAngle = angleToPlayer;
// Maintain distance
const ideal = 260;
if (dist < ideal - 20) desiredAngle += Math.PI; // back up
else if (dist > ideal + 20) desiredAngle = angleToPlayer; // move in
// Add strafing
const strafe = e.clockwise ? Math.PI/2 : -Math.PI/2;
desiredAngle += strafe;
// Add avoidance
desiredAngle += getAvoidanceAngle(e);
// Smooth steering
let diff = desiredAngle - e.angle;
diff = Math.atan2(Math.sin(diff), Math.cos(diff));
e.angle += diff * 0.15;
// Move
e.x += Math.cos(e.angle) * e.speed * dt;
e.y += Math.sin(e.angle) * e.speed * dt;
// Shooting
e.fireCooldown -= dt;
if (enemyCanShoot(e)) {
const aimAngle = getPredictedAim(e);
spawnEnemyBullet(e.x, e.y, aimAngle);
e.fireCooldown = e.fireRate;
}
}
function updateTank(e, dt) {
// --- 1. HULL MOVEMENT
const dx = game.player.x - e.x;
const dy = game.player.y - e.y;
const angleToPlayer = Math.atan2(dy, dx);
// Add avoidance
let desiredHullAngle = angleToPlayer + getAvoidanceAngle(e);
// Smooth hull steering
let diffHull = desiredHullAngle - e.angle;
diffHull = Math.atan2(Math.sin(diffHull), Math.cos(diffHull));
e.angle += diffHull * e.hullTurnSpeed;
// Maintain ideal range
const dist = Math.hypot(dx, dy);
if (dist > e.idealRange + 40 || e.repositioning) {
// move closer
e.x += Math.cos(e.angle) * e.speed * dt;
e.y += Math.sin(e.angle) * e.speed * dt;
} else if (dist < e.idealRange - 40) {
// back up
e.x -= Math.cos(e.angle) * e.speed * dt;
e.y -= Math.sin(e.angle) * e.speed * dt;
}
// --- 2. TURRET ROTATION
if (!e.turret.angle) e.turret.angle = e.angle; // init
let desiredTurretAngle = angleToPlayer;
let diffTurret = desiredTurretAngle - e.turret.angle;
diffTurret = Math.atan2(Math.sin(diffTurret), Math.cos(diffTurret));
e.turret.angle += diffTurret * e.turret.turnSpeed;
// --- 3. FIRE CONTROL
e.fireCooldown -= dt;
const turretAligned = Math.abs(diffTurret) < 0.1;
const clearShot = !rayHitsObject(e.x, e.y, e.turret.angle);
const inRange = dist < e.idealRange + 100;
if (clearShot && inRange){
e.repositioning = false;
if (turretAligned && e.fireCooldown <= 0 ) {
spawnBigEnemyBullet(e.x, e.y, e.turret.angle);
e.fireCooldown = e.fireRate;
}
} else if (!clearShot){
e.repositioning = true;
}
}
function rayHitsObject(x, y, angle, maxDist = 2000) {
const endX = x + Math.cos(angle) * maxDist;
const endY = y + Math.sin(angle) * maxDist;
for (const obj of worldObjects) {
const poly = getWorldPoly(obj);
for (let i = 0; i < poly.length; i++) {
const a = poly[i];
const b = poly[(i + 1) % poly.length];
if (segmentsIntersect(x, y, endX, endY, a.x, a.y, b.x, b.y)) {
return true; // blocked
}
}
}
return false; // clear shot
}
function segmentsIntersect(x1,y1, x2,y2, x3,y3, x4,y4) {
function ccw(ax,ay, bx,by, cx,cy) {
return (cy - ay) * (bx - ax) > (by - ay) * (cx - ax);
}
return (
ccw(x1,y1, x3,y3, x4,y4) !== ccw(x2,y2, x3,y3, x4,y4) &&
ccw(x1,y1, x2,y2, x3,y3) !== ccw(x1,y1, x2,y2, x4,y4)
);
}
*/ |
| SC Arguments: [Name:SC_ACTION Type:uint64 Value:'1' Name:SC_CODE Type:string Value:'// Copyright 2024. Civilware. All rights reserved.
// TELA Decentralized Web Document (TELA-DOC-1)
Function InitializePrivate() Uint64
10 IF init() == 0 THEN GOTO 30
20 RETURN 1
30 STORE("nameHdr", "update.js")
31 STORE("descrHdr", "Update JS file")
32 STORE("iconURLHdr", "")
33 STORE("dURL", "update.js")
34 STORE("docType", "TELA-JS-1")
35 STORE("subDir", "")
36 STORE("fileCheckC", "1f583b450e11b0f23248b6206b6162e94c0395b503e4269ec6dc60b9599fc92f")
37 STORE("fileCheckS", "210205474653fe7aaf62b3da588bde91eaa2541ec6e914d395d44d1b4a671de5")
100 RETURN 0
End Function
Function init() Uint64
10 IF EXISTS("owner") == 0 THEN GOTO 30
20 RETURN 1
30 STORE("owner", address())
50 STORE("docVersion", "1.0.0")
60 STORE("hash", HEX(TXID()))
70 STORE("likes", 0)
80 STORE("dislikes", 0)
100 RETURN 0
End Function
Function address() String
10 DIM s as String
20 LET s = SIGNER()
30 IF IS_ADDRESS_VALID(s) THEN GOTO 50
40 RETURN "anon"
50 RETURN ADDRESS_STRING(s)
End Function
Function Rate(r Uint64) Uint64
10 DIM addr as String
15 LET addr = address()
16 IF r < 100 && EXISTS(addr) == 0 && addr != "anon" THEN GOTO 30
20 RETURN 1
30 STORE(addr, ""+r+"_"+BLOCK_HEIGHT())
40 IF r < 50 THEN GOTO 70
50 STORE("likes", LOAD("likes")+1)
60 RETURN 0
70 STORE("dislikes", LOAD("dislikes")+1)
100 RETURN 0
End Function
/*//----------------
// Update Entities
function update(dt) {
updateCamera();
updateViewBox();
updateSpawnTimer(dt);
updateEnemies(dt);
updateProjectiles(dt);
}
function resizeSVG() {
sw = window.innerWidth;
sh = window.innerHeight;
updateViewBox();
}
function updateViewBox() {
if (keys["="]) zoom *= 0.98;
if (keys["-"]) zoom *= 1.02;
const viewW = sw * zoom;
const viewH = sh * zoom;
const camX = camCenter.x - viewW / 2;
const camY = camCenter.y - viewH / 2;
camLeft = camCenter.x - (sw * zoom) / 2;
camTop = camCenter.y - (sh * zoom) / 2;
camRight = camCenter.x + (sw * zoom) / 2;
camBottom = camCenter.y + (sh * zoom) / 2;
svg.setAttribute("viewBox", `${camX} ${camY} ${viewW} ${viewH}`);
}
// Timer
let enemySpawnTimer = 1000;//1 second
function updateSpawnTimer(dt) {
enemySpawnTimer -= dt;
if (enemySpawnTimer <= 0) {
for (const base of game.bases) {
if (base.cooldown > 0) {
base.cooldown -= dt;
continue;
}
const count = game.enemies.filter(e => e.base === base).length;
if (count < base.maxEnemies) {
spawnEnemyFromBase(base);
base.cooldown = base.spawnInterval;
}
}
enemySpawnTimer = 2000;
}
}
function updateCamera(dt) {
// camera follows player
camCenter.x = game.player.x;
camCenter.y = game.player.y;
}
function updateProjectiles(dt) {
// handle projectiles
for (let p of game.projectiles) {
p.x += Math.cos(p.angle) * p.speed * dt;
p.y += Math.sin(p.angle) * p.speed * dt;
p.life -= dt;
}
}
function updateParticles(dt) {
for (let p of game.particles) {
p.x += p.vx * dt;
p.y += p.vy * dt;
p.life -= dt;
}
}
function enemyCanShoot(e) {
const dx = game.player.x - e.x;
const dy = game.player.y - e.y;
const dist = Math.hypot(dx, dy);
if (dist > 800) return false; // max range
if (e.fireCooldown > 0) return false;
// optional: check if enemy is roughly facing the player
const angleToPlayer = Math.atan2(dy, dx);
const diff = Math.abs(Math.atan2(Math.sin(angleToPlayer - e.angle), Math.cos(angleToPlayer - e.angle)));
if (diff > 0.6) return false; // not facing player enough
return true;
}
function getPredictedAim(e) {
const px = game.player.x;
const py = game.player.y;
const pvx = Math.cos(game.player.angle) * game.player.speed;
const pvy = Math.sin(game.player.angle) * game.player.speed;
const ex = e.x;
const ey = e.y;
const bulletSpeed = 900;
const dx = px - ex;
const dy = py - ey;
const dist = Math.hypot(dx, dy);
const t = dist / bulletSpeed;
const predictedX = px + pvx * t;
const predictedY = py + pvy * t;
return Math.atan2(predictedY - ey, predictedX - ex);
}
function getAvoidanceAngle(e) {
const lookDist = 30;
const rays = [
e.angle, // center
e.angle + 0.4, // left
e.angle - 0.4 // right
];
let dangerLeft = false;
let dangerCenter = false;
let dangerRight = false;
for (let i = 0; i < rays.length; i++) {
const ang = rays[i];
const lx = e.x + Math.cos(ang) * lookDist;
const ly = e.y + Math.sin(ang) * lookDist;
for (const obj of worldObjects) {
if (pointInPoly(lx, ly, obj.poly, obj.x, obj.y)) {
if (i === 0) dangerCenter = true;
if (i === 1) dangerLeft = true;
if (i === 2) dangerRight = true;
}
}
}
// Return an angle offset to apply to desiredAngle
if (dangerCenter) {
const side = e.avoidDir ?? (Math.random() < 0.5 ? 1 : -1);
e.avoidDir = side;
return side * 0.8;
}
if (dangerLeft) return -0.4;
if (dangerRight) return +0.4;
return 0; // no avoidance needed
}
function updateEnemies(dt) {
for (let e of game.enemies) {
switch (e.type) {
case "chaser": updateChaser(e, dt); break;
case "strafer": updateStrafer(e, dt); break;
case "tank": updateTank(e, dt); break;
}
}
}
function updateChaser(e, dt) {
// 1. CHASE LOGIC
const dx = game.player.x - e.x;
const dy = game.player.y - e.y;
let desiredAngle = Math.atan2(dy, dx);
// 2. AVOIDANCE LOGIC
desiredAngle += getAvoidanceAngle(e);
// Smooth steering toward desiredAngle
let diff = desiredAngle - e.angle;
diff = Math.atan2(Math.sin(diff), Math.cos(diff));
e.angle += diff * 0.15;
// 4. MOVE
e.x += Math.cos(e.angle) * e.speed * dt;
e.y += Math.sin(e.angle) * e.speed * dt;
// Firing
e.fireCooldown -= dt;
// after movement
if (enemyCanShoot(e)) {
const aimAngle = getPredictedAim(e);
spawnEnemyBullet(e.x, e.y, aimAngle);
e.fireCooldown = e.fireRate;
}
}
function updateStrafer(e, dt) {
const dx = game.player.x - e.x;
const dy = game.player.y - e.y;
const dist = Math.hypot(dx, dy);
const angleToPlayer = Math.atan2(dy, dx);
let desiredAngle = angleToPlayer;
// Maintain distance
const ideal = 260;
if (dist < ideal - 20) desiredAngle += Math.PI; // back up
else if (dist > ideal + 20) desiredAngle = angleToPlayer; // move in
// Add strafing
const strafe = e.clockwise ? Math.PI/2 : -Math.PI/2;
desiredAngle += strafe;
// Add avoidance
desiredAngle += getAvoidanceAngle(e);
// Smooth steering
let diff = desiredAngle - e.angle;
diff = Math.atan2(Math.sin(diff), Math.cos(diff));
e.angle += diff * 0.15;
// Move
e.x += Math.cos(e.angle) * e.speed * dt;
e.y += Math.sin(e.angle) * e.speed * dt;
// Shooting
e.fireCooldown -= dt;
if (enemyCanShoot(e)) {
const aimAngle = getPredictedAim(e);
spawnEnemyBullet(e.x, e.y, aimAngle);
e.fireCooldown = e.fireRate;
}
}
function updateTank(e, dt) {
// --- 1. HULL MOVEMENT
const dx = game.player.x - e.x;
const dy = game.player.y - e.y;
const angleToPlayer = Math.atan2(dy, dx);
// Add avoidance
let desiredHullAngle = angleToPlayer + getAvoidanceAngle(e);
// Smooth hull steering
let diffHull = desiredHullAngle - e.angle;
diffHull = Math.atan2(Math.sin(diffHull), Math.cos(diffHull));
e.angle += diffHull * e.hullTurnSpeed;
// Maintain ideal range
const dist = Math.hypot(dx, dy);
if (dist > e.idealRange + 40 || e.repositioning) {
// move closer
e.x += Math.cos(e.angle) * e.speed * dt;
e.y += Math.sin(e.angle) * e.speed * dt;
} else if (dist < e.idealRange - 40) {
// back up
e.x -= Math.cos(e.angle) * e.speed * dt;
e.y -= Math.sin(e.angle) * e.speed * dt;
}
// --- 2. TURRET ROTATION
if (!e.turret.angle) e.turret.angle = e.angle; // init
let desiredTurretAngle = angleToPlayer;
let diffTurret = desiredTurretAngle - e.turret.angle;
diffTurret = Math.atan2(Math.sin(diffTurret), Math.cos(diffTurret));
e.turret.angle += diffTurret * e.turret.turnSpeed;
// --- 3. FIRE CONTROL
e.fireCooldown -= dt;
const turretAligned = Math.abs(diffTurret) < 0.1;
const clearShot = !rayHitsObject(e.x, e.y, e.turret.angle);
const inRange = dist < e.idealRange + 100;
if (clearShot && inRange){
e.repositioning = false;
if (turretAligned && e.fireCooldown <= 0 ) {
spawnBigEnemyBullet(e.x, e.y, e.turret.angle);
e.fireCooldown = e.fireRate;
}
} else if (!clearShot){
e.repositioning = true;
}
}
function rayHitsObject(x, y, angle, maxDist = 2000) {
const endX = x + Math.cos(angle) * maxDist;
const endY = y + Math.sin(angle) * maxDist;
for (const obj of worldObjects) {
const poly = getWorldPoly(obj);
for (let i = 0; i < poly.length; i++) {
const a = poly[i];
const b = poly[(i + 1) % poly.length];
if (segmentsIntersect(x, y, endX, endY, a.x, a.y, b.x, b.y)) {
return true; // blocked
}
}
}
return false; // clear shot
}
function segmentsIntersect(x1,y1, x2,y2, x3,y3, x4,y4) {
function ccw(ax,ay, bx,by, cx,cy) {
return (cy - ay) * (bx - ax) > (by - ay) * (cx - ax);
}
return (
ccw(x1,y1, x3,y3, x4,y4) !== ccw(x2,y2, x3,y3, x4,y4) &&
ccw(x1,y1, x2,y2, x3,y3) !== ccw(x1,y1, x2,y2, x4,y4)
);
}
*/'] |