Skip to content

Instantly share code, notes, and snippets.

@kungfooman
Created March 23, 2017 18:10
Show Gist options
  • Save kungfooman/ba75d5bac0261f6ba78e468df40e1650 to your computer and use it in GitHub Desktop.
Save kungfooman/ba75d5bac0261f6ba78e468df40e1650 to your computer and use it in GitHub Desktop.
ET JavaScript Dynamic Brushes and Safe/Load position mod
// MIT License, have fun
function sprintf() {
var ret = "";
var param = 1; // maps to first %
var msg = arguments[0];
for (var i=0; i<msg.length; i++) {
if (msg[i] == "%") {
// %% will be printed as normal %
if (msg[i+1] == "%") {
ret += "%";
i++;
} else
ret += arguments[param++];
} else {
ret += msg[i];
}
}
return ret;
}
function printf() {
var ret = "";
var param = 1; // maps to first %
var msg = arguments[0];
for (var i=0; i<msg.length; i++) {
if (msg[i] == "%") {
// %% will be printed as normal %
if (msg[i+1] == "%") {
ret += "%";
i++;
} else
ret += arguments[param++];
} else {
ret += msg[i];
}
}
log(ret);
return ret.length;
}
function require(filename) {
var content = file_get_contents( filename );
try {
eval.bind( get_global() )(content);
} catch (e) {
printf("require(%): error %\n", filename, e.stack);
}
}
if (typeof date_start == "undefined")
date_start = Date.now();
// time since loading this file for first time
function now() {
return Date.now() - date_start;
}
print = function() {
for (var i=0; i<arguments.length; i++) {
log(arguments[i]);
}
}
function var_dump(ret) {
switch (typeof ret) {
case "number": {
print("ret = ", ret, ";");
break;
}
case "string": {
print("ret = \"", ret, "\";");
break;
}
case "function": {
// print infos like byte codes or length of byte codes
print("Function: ", ret);
break;
}
case "boolean": {
print("ret = ", ret, ";");
break;
}
case "object": {
if (ret.constructor.name == "Array") {
print("ret = [\n");
for (var i=0; i<ret.length; i++) {
if (typeof ret[i] == "object")
printf("\t%: % {...},\n", i, ret[i].constructor.name);
else
printf("\t%: %,\n", i, ret[i]);
}
print("];\n");
}
// An array still can have properties, so print them aswell:
{
printf("% {\n", ret.constructor.name);
for (var i in ret) {
if (typeof ret[i] == "object")
printf("\t%: % {...},\n", i, ret[i].constructor.name);
else
printf("\t%: %,\n", i, ret[i]);
}
print("};\n");
}
break;
}
case "undefined": {
// print infos like byte codes or length of byte codes
print("undefined;");
break;
}
default:
print("Unhandled type: ", typeof ret);
}
}
handle_input = function(code, global) {
try {
var ret = eval.bind(global)(code);
log("> ");
var_dump(ret);
log("\n");
} catch (e) {
print("handle_input> error: ", e.stack, "\n");
}
//repl_settext("asdddd");
}
//global = get_global();
//printf("Global: %", global);
//var_dump(global);
consolecommand = function() {
var args = getargs();
var cmdline = "";
for (var i=1; i<args.length; i++)
cmdline += args[i] + " ";
//printf("cmdline: %\n", cmdline);
handle_input(cmdline, get_global());
}
//function ThreadState()
function wait(time) { Duktape.Thread.yield( ["wait", time * 1000] ); }
function waittillframeend() { Duktape.Thread.yield( ["waittillframeend" ] ); }
function waittill(what) { Duktape.Thread.yield( ["waittill", what ] ); }
if (typeof level == "undefined") {
level = {};
level.time = 0;
}
function Entity(id) {
this.id = id;
this.threads = [];
this.thread = function(func) {
var self = this;
return function() {
var t = new Duktape.Thread(function(args) {
func.bind(self)(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
//func.apply(self, arguments) // waiting for: https://github.com/svaarala/duktape/issues/1420
});
t.nextrun = level.time;
t.parameters = arguments;
self.threads.push(t)
}
}
this.runframe = function() {
// iterate backwards over it, so we can delete finished threads instantly via ID
for (var i=this.threads.length-1; i>=0; i--) {
var thread = this.threads[i];
var state = Duktape.info(thread);
//printf("entid=% threadid=% state=%,%\n", this.id, i, state[0], state[1]);
if (thread.nextrun > level.time) {
//printf("entid=% threadid=%> No run yet: nextrun in %\n", this.id, i, thread.nextrun - level.time)
continue;
}
try {
var whatnow = Duktape.Thread.resume(thread, thread.parameters);
var state = Duktape.info(thread);
//printf("AFTER RESUME: entid=% threadid=% state=%,%\n", this.id, i, state[0], state[1]);
switch (whatnow[0]) {
case "wait": thread.nextrun += whatnow[1]; break;
}
//printf("whatnow: %\n", whatnow);
} catch (e) {
this.threads.splice(i, 1); // delete thread from array
//printf("Entity::runframe> Finished Thread id=% entityid=% level.time=%\n", i, this.id, level.time);
}
}
}
this.useButtonPressed = function() { return entity_usebuttonpressed (this.id); }
this.sprintButtonPressed = function() { return entity_sprintbuttonpressed(this.id); }
this.attackButtonPressed = function() { return entity_attackbuttonpressed(this.id); }
this.getEye = function() { return entity_get_eye (this.id); }
this.getOrigin = function() { return entity_get_origin (this.id); }
this.setOrigin = function(origin) { return entity_set_origin (this.id, origin[0], origin[1], origin[2]); }
this.getAngles = function() { return entity_get_angles (this.id); }
this.setAngles = function(angles) { return entity_set_angles (this.id, angles[0], angles[1], angles[2]); }
this.getForward = function() { return entity_get_forward (this.id); }
this.getClassname = function() { return entity_get_classname (this.id); }
this.moveTo = function(pos, durationSeconds) { return entity_moveto (this.id, pos[0], pos[1], pos[2], durationSeconds); }
this.solid = function() { return entity_solid (this.id); }
this.notSolid = function() { return entity_notsolid (this.id); }
this.printf = function() {
var msg = sprintf.apply(undefined, arguments);
sendservercommand(this.id, "print \"" + msg + "\"");
}
}
function vec3_new() {
return new Float32Array(3);
}
function vec3_scale(vec, scalar, output) {
output[0] = vec[0] * scalar;
output[1] = vec[1] * scalar;
output[2] = vec[2] * scalar;
}
function vec3_copy(from_, to) {
to[0] = from_[0];
to[1] = from_[1];
to[2] = from_[2];
}
function vec3_add(a, b, c) {
c[0] = a[0] + b[0];
c[1] = a[1] + b[1];
c[2] = a[2] + b[2];
}
function vec3_sub(a, b, ret) {
ret[0] = a[0] - b[0];
ret[1] = a[1] - b[1];
ret[2] = a[2] - b[2];
}
function vec3_length(a) {
return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
}
function vec3_distance(a, b) {
var delta = vec3_new();
vec3_sub(b, a, delta);
return vec3_length(delta);
}
function bullettrace(from, to, hit_players, entity_to_ignore) {
var tmp = trace(from[0], from[1], from[2], to[0], to[1], to[2], entity_to_ignore.id);
return {
position: tmp.endpos,
fraction: tmp.fraction,
entity: new Entity(tmp.entityNum)
}
}
doshit = function(a, b, c) {
try {
var nadeid = spawngrenade();
var nade = new Entity(nadeid);
nade.notSolid();
var brush_distance = 1024;
var brush_selected = 0;
var grenade_oldpos = vec3_new();
var brush_oldpos = vec3_new();
var brush_moving = undefined;
while (1) {
//printf("this.id====%\n", this.id);
if ( ! this.attackButtonPressed()) {
brush_selected = 0;
}
if (brush_selected) {
var change = 15;
if (brush_distance > 150) change = 20;
if (brush_distance > 300) change = 40;
if (brush_distance > 600) change = 60;
if (this.sprintButtonPressed()) brush_distance += change;
if (this.useButtonPressed() ) brush_distance -= change;
var pos = this.getEye();
var forward = this.getForward();
var newnadepos = vec3_new();
vec3_copy(pos, newnadepos);
vec3_scale(forward, brush_distance, forward);
vec3_add(newnadepos, forward, newnadepos);
nade.setOrigin(newnadepos);
var delta_grenade = vec3_new();
// a - b = c
vec3_sub(newnadepos, grenade_oldpos, delta_grenade);
var finalpos = vec3_new();
vec3_add(brush_oldpos, delta_grenade, finalpos);
if (1) {
brush_moving.moveTo(finalpos, 0.15); // 0.15 feels somewhat smooth, but 0.05 isn't too bad as well
} else {
brush_moving.setOrigin(finalpos);
}
} else if (this.attackButtonPressed()) {
var pos = this.getEye();
var forward = this.getForward();
var newpos = vec3_new();
vec3_copy(pos, newpos);
vec3_scale(forward, 1024*10, forward);
vec3_add(newpos, forward, newpos);
var tmp = bullettrace(pos, newpos, "useless", nade);
if (tmp["fraction"] != 0) {
//printf("classname: %\n", tmp["entity"].getClassname());
//nade.setOrigin(tmp["position"]);
if (tmp["entity"].getClassname() == "func_plat") {
brush_selected = 1;
brush_distance = vec3_distance(pos, tmp["position"]);
vec3_copy(tmp["position"], grenade_oldpos);
vec3_copy(tmp["entity"].getOrigin(), brush_oldpos);
brush_moving = tmp["entity"];
this.printf("Selected Brush ID: %\n", brush_moving.id);
}
//printf("asd: % asd[0]=%\n", asd, asd[0]);
}
}
wait(0.05);
}
} catch (e) {
printf("Error: % %\n", e, e.stack);
}
}
function callback_runframe(levelTime) {
runframe();
}
function runframe() {
for (var i=0; i</*entities.length*/1024; i++) {
if (entities[i] != undefined)
entities[i].runframe()
}
level.time += 50;
}
lastpos = undefined;
lastangles = undefined;
thread_loadpos = function() {
var lastpress = 0;
while (1) {
while ( ! this.useButtonPressed()) { wait(0.05); }
while ( this.useButtonPressed()) { wait(0.05); }
var time = level.time - lastpress;
if (time <= 400)
{
if (typeof lastpos != "undefined") {
this.setOrigin(lastpos);
this.setAngles(lastangles);
} else {
this.printf("You have no last position saved");
}
this.printf("thread_loadpos> Last press: %, save pos: %", time, lastpos);
}
lastpress = level.time;
wait(0.05);
}
}
thread_savepos = function() {
var lastpress = 0;
while (1) {
while ( ! this.sprintButtonPressed()) { wait(0.05); }
while ( this.sprintButtonPressed()) { wait(0.05); }
var time = level.time - lastpress;
if (time <= 400)
{
lastpos = this.getOrigin();
lastangles = this.getAngles();
this.printf("thread_savepos> Last press: time=%", time);
}
lastpress = level.time;
wait(0.05);
}
}
if (typeof entities == "undefined")
entities = Array(1024);
function callback_clientconnected(clientNum) {
entities[clientNum] = new Entity(clientNum);
var ent = entities[clientNum];
ent.thread(doshit)(1,22,333);
ent.thread(thread_loadpos)();
ent.thread(thread_savepos)();
//ent thread doshit (1,22,333);
printf("Client connected: %\n", clientNum);
}
print("lib.js loaded\n");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment