Club Command Line

Developer
Size
12,560 Kb
Views
34,408

How do I make an club command line?

A mini 2D virtual world with a command line made to be like the one in Minecraft. Manipulate JS-controlled chibis as well as your own (name in yellow) by using commands to change appearance and stats, teleport them somewhere else, or you can spawn more if you’d like! Since I wasn’t focused too much on AI for this demo, the JS-controlled chibis just move around randomly and send emojis. I have tab suggestions only working for required arguements.. What is a club command line? How do you make a club command line? This script and codes were developed by Jon Kantner on 17 August 2022, Wednesday.

Club Command Line Previews

Club Command Line - Script Codes HTML Codes

<!DOCTYPE html>
<html >
<head> <meta charset="UTF-8"> <title>Club Command Line</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="css/style.css">
</head>
<body> <canvas></canvas> <script src="js/index.js"></script>
</body>
</html>

Club Command Line - Script Codes CSS Codes

* {	box-sizing: border-box;	margin: 0;	padding: 0;
}
body { font-family: Arial, sans-serif; margin: 0;
}
canvas, form, div {	margin: auto;
}
canvas {	display: block;
}
form {	background-color: #048;
}
input, button {	border: 0;	vertical-align: middle;
}
input {	appearance: none;	-webkit-appearance: none;	width: 75%;
}
button {	color: #fff;
}
.send {	background-color: #5b5;	width: 15%;
}
.send:hover {	background-color: #6c6;
}
.send:active {	background-color: #4a4;
}
.send:disabled {	opacity: 0.7;
}
.send:disabled:hover {	background-color: #5b5;
}
.view-chat {	background-color: #48c;	width: 10%;
}
.view-chat:hover {	background-color: #59d;
}
.view-chat:active {	background-color: #37b;
}
.chat-log {	background-color: rgba(0,0,0,0.5);	color: #fff;	display: none;	flex-direction: column-reverse;	overflow-y: scroll;
}
.chat-log span {	line-height: 24px;
}
.help-text {	color: #4f4;
}
.info-text {	color: #ff4;
}
.error-text {	color: #f44;
}

Club Command Line - Script Codes JS Codes

window.addEventListener("load", app);
function app() {	var canvas = document.getElementsByTagName("canvas")[0],	ctx = canvas.getContext("2d"),	// canvas dimensions	w = 568,	h = 480,	// scale, keep at 2 for best retina results	s = 2;	// set canvas dimensions with scale	canvas.width = w * s;	canvas.height = h * s;	canvas.style.width = w + "px";	canvas.style.height = h + "px";	ctx.scale(s, s);	/* Main app code */	// all artwork done by me :)	var sprites = [	"http://jonkantner.com/experiments/vwc/grass.svg",	"http://jonkantner.com/experiments/vwc/fountain.svg",	"http://jonkantner.com/experiments/vwc/chibi_m.svg",	"http://jonkantner.com/experiments/vwc/chibi_f.svg" ], images = []; for (var sp in sprites) { images.push(new Image()); images[sp].src = sprites[sp]; }	var chatBar = {	barH: 54,	logH: 220,	margin: 5,	active: false,	showLog: false,	maxLines: 32,	history: [],	curHistoryItem: -1,	curAutoCmpltCmd: -1,	arg1pg: -1,	arg2pg: -1,	autoCmpltLvl: 0,	logShow: function() {	try {	let log = document.querySelector(".chat-log").style,	field = document.querySelector("input");	log.display = "flex";	this.active = true;	this.showLog = true;	field.focus();	}	catch(err) {	console.log("Chatbar must be created first in order to show the log");	}	},	logHide: function() {	try {	let log = document.querySelector(".chat-log").style,	field = document.querySelector("input");	log.display = "none";	this.active = false;	this.showLog = false;	field.blur();	}	catch(err) {	console.log("Chatbar must be created first in order to hide the log");	}	},	logToggle: function() {	if (this.showLog) {	this.logHide();	} else {	this.logShow();	}	},	create: function() {	let form = document.createElement("form"),	field = document.createElement("input"),	btn1 = document.createElement("button"),	btn2 = document.createElement("button"),	log = document.createElement("div");	// set up form elements and translate them to inside canvas	form.action = "";	form.style.padding = this.margin + "px";	form.style.width = (canvas.width / s) + "px";	form.style.height = (this.barH) + "px";	form.style.transform = "translateY(" + (-this.barH) + "px)";	// text input	field.type = "text";	field.style.fontSize = (this.barH*0.4) + "px";	field.style.height = (this.barH - this.margin*2) + "px";	field.style.padding = "0 " + this.margin + "px";	field.maxLength = 64;	// send button	btn1.className = "send";	btn1.style.fontSize = (this.barH*0.4) + "px";	btn1.style.height = (this.barH - this.margin*2) + "px";	btn1.disabled = "disabled";	// view chat button	btn2.className = "view-chat";	btn2.style.fontSize = (this.barH*0.25) + "px";	btn2.style.height = (this.barH - this.margin*2) + "px";	// chat log	log.className = "chat-log";	log.style.width = (canvas.width / s) + "px";	log.style.height = (this.logH) + "px";	log.style.transform = "translateY(" + (-this.barH*2 - this.logH) + "px)";	log.style.padding = this.margin + "px";	document.body.appendChild(form);	document.body.appendChild(log);	form.appendChild(field);	form.appendChild(btn1);	form.appendChild(btn2);	btn1.appendChild(document.createTextNode("Send"));	btn2.appendChild(document.createTextNode("View Chat"));	}	},	screenText = {	text: "",	color: "#fff",	fontS: 16,	timer: 3000,	maxTime: 3000,	fadeTime: 150,	y: 0,	h: 32,	updateText: function(txt, y, h, c) {	this.text = txt;	this.timer = this.maxTime;	this.y = y || 0;	this.h = h || 32;	this.color = c || "#fff";	}	},	bubbleObj = function(text,w,x,y) {	let minW = 35;	this.text = text;	this.w = w < minW ? minW : w;	this.x = x;	this.y = y;	},	cmdObj = function(name, args, desc) {	this.name = name;	this.args = args || "";	this.desc = desc || "";	},	cmd = [	new cmdObj("clear","","clear chat"),	new cmdObj("help","","get help menu"),	new cmdObj("entityinfo","<name>","get details of entity"),	new cmdObj("modentity","<name> <newname> [gender] [skin] [speed] [level]","modify entity"),	new cmdObj("npc","<add|del> <name> [gender] [skin] [speed] [level] [<x> <y>]","add/delete NPC"),	new cmdObj("tp","<name> <x> <y> or <name> <targetname>","teleport entity to new location"),	new cmdObj("who","","get list of all entities")	],	avatar = function(name, gender, skinTone, width, height, speed, frames, dir, x, y, lvl) {	let nameLenLimit = 16;	this.name = name.length > nameLenLimit ? name.substr(0,nameLenLimit) : name || "Anonymous";	this.gender = gender || 0;	this.skinTone = skinTone || 0;	this.w = width || 0;	this.h = height || 0;	this.speed = speed || 0;	this.curFrame = 1;	this.frames = frames || 1;	this.dir = dir || null;	this.isMoving = false;	this.canMove = true;	this.x = x || 0;	this.y = y || 0;	this.lvl = lvl || 0;	this.lastMsg = "";	this.msgTimer = 0;	this.msgMaxTime = 3000;	this.msgFadeTime = 150;	this.sendMsg = function(msg) {	if (msg.length > 0) {	let isCmd = false;	chatBar.curAutoCmpltCmd = -1;	chatBar.arg1pg = -1;	chatBar.arg2pg = -1;	// update last message if not a command	if (msg[0] != "/") {	this.lastMsg = msg;	} else {	isCmd = true;	}	let chatLog = document.querySelector(".chat-log"),	newEntry = document.createElement("span");	/* if command, execute if used by player (whose level is always 0,	and NPCs never send anything if they too are set at level 0) */	if (this.lvl === 0 && isCmd) {	switch (msg.substr(1,msg.length - 1).split(" ")[0]) {	// display help	case "help":	let helpHeading = "----- Help -----",	cmdInfo = [],	helpScrnTxt = "";	for (var c in cmd) {	cmdInfo[c] = "/" + cmd[c].name + " " + cmd[c].args + (cmd[c].args.length > 0 ? " " : "") + "- " + cmd[c].desc;	}	newEntry.className = "help-text";	newEntry.appendChild(document.createTextNode(helpHeading));	helpScrnTxt += helpHeading + "%";	// show available commands	for (var ci in cmdInfo) {	newEntry.appendChild(document.createElement("br"));	newEntry.appendChild(document.createTextNode(cmdInfo[ci]));	helpScrnTxt += cmdInfo[ci] + "%";	}	screenText.updateText(helpScrnTxt,h - chatBar.barH - (screenText.fontS*1.5*(cmdInfo.length)),screenText.fontS*2*(cmdInfo.length),"#4f4");	break;	// clear chat	case "clear":	let clearMsg = "Chat cleared";	chatLog.innerHTML = "";	newEntry.appendChild(document.createTextNode(clearMsg));	screenText.updateText(clearMsg,h - chatBar.barH,screenText.fontS*2);	break;	// get entity details	case "entityinfo":	let eiArgs = msg.split(" "),	eiTarget = eiArgs[1],	eiSearch = worldObjs.find(s => s.name === eiTarget) || 0,	eiFBLines = [],	eiFeedback = "";	if (eiSearch !== 0 && eiTarget) {	eiFBLines[0] = "----- " + eiSearch.name + " -----";	eiFBLines[1] = "Gender - " + (eiSearch.gender === 0 ? "male" : "female");	eiFBLines[2] = "Skin - " + eiSearch.skinTone;	eiFBLines[3] = "Speed - " + eiSearch.speed;	eiFBLines[4] = "Coordinates - " + Math.round(eiSearch.x) + "," + Math.round(eiSearch.y);	eiFBLines[5] = "AI activity level - " + eiSearch.lvl;	newEntry.className = "info-text";	for (var ei in eiFBLines) {	newEntry.appendChild(document.createTextNode(eiFBLines[ei]));	newEntry.appendChild(document.createElement("br"));	eiFeedback += eiFBLines[ei] + "%";	}	} else {	eiFeedback = !eiArgs[1] ? "Please specify an entity." : "Entity not found";	newEntry.className = "error-text";	newEntry.appendChild(document.createTextNode(eiFeedback));	}	let eiFBLen = eiFBLines.length > 0 ? eiFBLines.length : 1;	screenText.updateText(eiFeedback,h - chatBar.barH - (screenText.fontS*1.5*(eiFBLen - 1)),screenText.fontS*2*(eiFBLen - 1),eiSearch !== 0 && eiArgs[1] ? "#ff4" : "#f44");	break;	// modify entity	case "modentity":	let meArgs = msg.split(" "),	meTarget = meArgs[1],	meName = meArgs[2],	meGender = meArgs[3],	meSkin = meArgs[4],	meSpeed = meArgs[5],	meLevel = meArgs[6],	meSearch = worldObjs.find(s => s.name === meTarget) || 0,	meInvalid = false,	meValidArgCt = 0,	meFeedback = "Entity modified successfully";	if (meTarget) {	if (meSearch !== 0) {	if (meName) {	meValidArgCt = 2;	// check if new name isnt already used	let meNameUsed = worldObjs.find(ne => ne.name === meName) || 0;	if (meNameUsed === 0 || meTarget == meNameUsed.name) {	if (meGender) {	if ((meGender >= 0 && meGender <= 1) || meGender == "male" || meGender == "m" || meGender == "female" || meGender == "f") {	++meValidArgCt;	if (meSkin) {	if (meSkin >= 0 && meSkin <= 2) {	++meValidArgCt;	if (meSpeed) {	if (meSpeed >= 0 && meSpeed <= 9) {	++meValidArgCt;	if (meLevel) {	if (meLevel >= 0 && meLevel <= 20) {	++meValidArgCt;	if (meTarget == player.name) {	meInvalid = true;	meFeedback = "Entity must be an NPC to modify AI activity level.";	}	} else {	meInvalid = true;	meFeedback = "Level must be between 0 and 20.";	}	}	} else {	meInvalid = true;	meFeedback = "Speed must be between 0 and 9.";	}	}	} else {	meInvalid = true;	meFeedback = "Skin must be between 0 and 2.";	}	}	} else {	meInvalid = true;	meFeedback = "Gender must be 0 or 1. m(ale) and f(emale) are also valid.";	}	}	} else {	meInvalid = true;	meFeedback = "'" + meNameUsed.name + "' has already been used. Please choose another name.";	}	} else {	meInvalid = true;	meFeedback = "Please give at least a new name to use";	}	} else {	meInvalid = true;	meFeedback = "Entity does not exist.";	}	} else {	meInvalid = true;	meFeedback = "Usage: /modentity <name> <newname> [gender] [skin] [speed] [level]";	}	if (!meInvalid) {	let nameLenLimit = 16;	meSearch.name = meName.length > nameLenLimit ? meName.substr(0,nameLenLimit) : meName;	if (meValidArgCt >= 3)	meSearch.gender = meGender == "male" || meGender == "m" ? 0 : (meGender == "female" || meGender == "f" ? 1 : meGender);	if (meValidArgCt >= 4)	meSearch.skinTone = meSkin;	if (meValidArgCt >= 5)	meSearch.speed = +meSpeed;	if (meValidArgCt == 6)	meSearch.lvl = +meLevel;	}	newEntry.className = !meInvalid ? "" : "error-text";	newEntry.appendChild(document.createTextNode(meFeedback));	screenText.updateText(meFeedback,h - chatBar.barH,screenText.fontS*2,!meInvalid ? "#fff" : "#f44");	break;	// npc add/delete	case "npc":	let npcArgs = msg.split(" "),	npcAction = npcArgs[1],	npcName = npcArgs[2],	npcGender = npcArgs[3],	npcSkin = npcArgs[4],	npcSpeed = npcArgs[5],	npcLevel = npcArgs[6],	npcX = npcArgs[7],	npcY = npcArgs[8],	npcFeedback = "NPC successfully added",	npcInvalid = false,	npcUsage = "Usage: /npc <add|del> <name> [gender] [skin] [speed] [level] [<x> <y>]";	if (npcAction == "add") {	if (npcName) {	let npcNameUsed = worldObjs.find(np => np.name === npcName) || 0;	if (npcNameUsed === 0) {	if (npcGender) {	if ((npcGender >= 0 && npcGender <= 1) || npcGender == "male" || npcGender == "m" || npcGender == "female" || npcGender == "f") {	if (npcSkin) {	if (npcSkin >= 0 && npcSkin <= 2) {	if (npcSpeed) {	if (npcSpeed >= 0 && npcSpeed <= 9) {	if (npcLevel) {	if (npcLevel >= 0 || npcLevel <= 20) {	if (npcX) {	if (npcY) {	if (!isNaN(npcX) && !isNaN(npcY)) {	let xMax = canvas.offsetWidth;	if (npcX < 0 && npcX > xMax && npcY < 0 && npcY > h - chatBar.barH) {	npcInvalid = true;	npcFeedback = "Placement is out of bounds. X limit is 0-" + xMax + ". Y limit is 0-" + (h - chatBar.barH) + ".";	}	} else {	npcInvalid = true;	npcFeedback = "Placement coordinates are invalid.";	}	} else {	npcInvalid = true;	npcFeedback = "Placement coordinates need both X and Y.";	}	}	} else {	npcInvalid = true;	npcFeedback = "Level must be between 0 and 20.";	}	}	} else {	npcInvalid = true;	npcFeedback = "Speed must be between 0 and 9.";	}	}	} else {	npcInvalid = true;	npcFeedback = "Skin must be between 0 and 2.";	}	}	} else {	npcInvalid = true;	npcFeedback = "Gender must be 0 or 1. m(ale) and f(emale) are also valid.";	}	}	} else {	npcInvalid = true;	npcFeedback = "'" + npcNameUsed.name + "' has already been used. Please choose another name.";	}	} else {	npcInvalid = true;	npcFeedback = "Please choose at least a name for the NPC.";	}	if (!npcInvalid) {	let aGender = (npcGender == "male" || npcGender == "m" ? 0 : (npcGender == "female" || npcGender == "f" ? 1 : npcGender)) || 0,	aSkin = npcSkin || 0,	aSpeed = npcSpeed || 3,	aLevel = npcLevel || 8,	aX = npcX || player.x,	aY = npcY || player.y,	newNPC = new avatar(npcName,aGender,aSkin,30,60,+aSpeed,28,2,+aX,+aY,+aLevel);	npcs.push(newNPC);	worldObjs.push(npcs[npcs.length - 1]);	}	} else if (npcAction == "del") {	if (npcName) {	let npcSearch = npcs.find(s => s.name === npcName) || 0;	if (npcSearch !== 0) {	for (var n in npcs) {	if (npcs[n].name == npcSearch.name) {	npcs.splice(n,1);	}	}	for (var w in worldObjs) {	if (worldObjs[w].name == npcSearch.name) {	worldObjs.splice(w,1);	}	}	npcFeedback = "NPC successfully deleted";	} else {	npcInvalid = true;	npcFeedback = "Could not find that NPC to delete";	}	} else {	npcInvalid = true;	npcFeedback = "Please specify an NPC to delete.";	}	} else {	npcInvalid = true;	npcFeedback = npcUsage;	}	newEntry.className = !npcInvalid ? "" : "error-text";	newEntry.appendChild(document.createTextNode(npcFeedback));	screenText.updateText(npcFeedback,h - chatBar.barH,screenText.fontS*2,!npcInvalid ? "#fff" : "#f44");	break;	// teleport	case "tp":	let tpArgs = msg.split(" "),	tpEntity = tpArgs[1],	tpAfterEn = tpArgs[2],	enSearch = worldObjs.find(s => s.name === tpEntity) || 0,	rel = "~",	tpOK = false,	tpFeedback = "",	tpUsage = "Usage: /tp <name> <x> <y> or <name> <targetname>";	if (tpAfterEn) {	if (isNaN(tpAfterEn) && tpAfterEn[0] != rel) {	let tarEntity = tpAfterEn,	tEnSearch = worldObjs.find(ts => ts.name === tarEntity) || 0,	bothNames = tpEntity && tarEntity ? true : false;	tpOK = bothNames && enSearch !== 0 && tEnSearch !== 0 ? true : false;	tpFeedback = bothNames ? (enSearch !== 0 ? (tEnSearch !== 0 ? "Teleported " + tpEntity + " to " + tarEntity : "Target entity does not exist") : "Entity does not exist") : tpUsage;	if (tpOK) {	enSearch.x = tEnSearch.x;	enSearch.y = tEnSearch.y;	}	} else {	let tpX = tpAfterEn,	tpY = tpArgs[3];	if (tpX && tpY) {	// convert relative positions to regular	if (tpX[0] == rel) {	tpX = +tpX.substr(1,tpX.length - 1) + enSearch.x;	} else {	tpX = +tpX;	}	if (tpY[0] == rel) {	tpY = +tpY.substr(1,tpY.length - 1) + enSearch.y;	} else {	tpY = +tpY;	}	}	let cw = canvas.offsetWidth,	allValues = tpEntity && (tpX || tpX === 0) && (tpY || tpY === 0) ? true : false,	wthnScrn = tpX >= 0 && tpX <= cw && tpY >= 0 && tpY <= h - chatBar.barH ? true : false;	tpOK = enSearch !== 0 && allValues && wthnScrn ? true : false,	tpFeedback = allValues ? (enSearch !== 0 ? (wthnScrn ? "Teleported " + tpEntity + " to " + Math.round(tpX) + "," + Math.round(tpY) : "Coordinates are out of bounds. X limit is 0-" + cw + ". Y limit is 0-" + (h - chatBar.barH) + ".") : "Entity does not exist.") : tpUsage;	if (tpOK) {	enSearch.x = tpX;	enSearch.y = tpY;	}	}	} else {	tpFeedback = tpUsage;	}	newEntry.className = tpOK ? "" : "error-text";	newEntry.appendChild(document.createTextNode(tpFeedback));	screenText.updateText(tpFeedback,h - chatBar.barH,screenText.fontS*2,tpOK ? "#fff" : "#f44");	break;	// get list of all entities in alphabetical order	case "who":	let getEntities = [player.name],	displayEntNames = "Entity list: ";	for (var ge in npcs) {	ge = +ge + 1;	getEntities[ge] = npcs[ge - 1].name;	}	getEntities.sort(function(a, b){	if (a.toLowerCase() < b.toLowerCase())	return -1;	if (a.toLowerCase() > b.toLowerCase())	return 1;	return 0;	});	for (var de in getEntities) {	de = +de;	displayEntNames += (de > 0 ? ", " : "") + getEntities[de];	}	newEntry.appendChild(document.createTextNode(displayEntNames));	screenText.updateText(displayEntNames,h - chatBar.barH,screenText.fontS*2);	break;	// invalid command	default:	let cmdErr = "Invalid command. See /help for a list of available commands.";	newEntry.className = "error-text";	newEntry.appendChild(document.createTextNode(cmdErr));	screenText.updateText(cmdErr,h - chatBar.barH,screenText.fontS*2,"#f44");	break;	}	} else {	this.msgTimer = this.msgMaxTime;	newEntry.appendChild(document.createTextNode(this.name + ": " + this.lastMsg));	}	// add new line	chatLog.insertBefore(newEntry, chatLog.childNodes[0]);	// cut off oldest line if at max lines allowed	if (chatLog.childNodes.length > chatBar.maxLines) {	chatLog.removeChild(chatLog.getElementsByTagName("span")[chatBar.maxLines]);	}	}	};	},	structure = function(width, height, x, y, backArea, img, isAnim, frames) {	this.w = width;	this.h = height;	this.x = x;	this.y = y;	this.backArea = backArea || 0;	this.img = img || null;	this.isAnim = img && isAnim ? (typeof isAnim == "boolean" ? true : false) : false;	this.frames = frames || 1;	this.curFrame = 1;	},	randNum = function(min, max) { return Math.floor(Math.random() * (max - min)) + min; },	collision = function(a, b) { // top hits bottom, bottom hits top, left hits right, right hits left if ( ((a.y < b.y + b.h + 6 - b.backArea && a.y > b.y) || (a.y > b.y && a.y < b.y + b.h - b.backArea)) && ((a.x + a.w > b.x && a.x + a.w < b.x + b.w) || (a.x < b.x + b.w && a.x > b.x)) ) { return true; } else { return false; } },	findCllsn = function(a, b) {	for (var bi in b) {	if (collision(a, b[bi]) && Array.isArray(b)) {	return true;	}	}	},	player = new avatar("Player",0,0,30,60,3,28,2,w/2 - 15,h*0.8 - chatBar.barH),	npcs = [],	structures = [	new structure(w,50,0,-40),	new structure(10,h - chatBar.barH - 10,0,10),	new structure(10,h - chatBar.barH - 10,w - 10,10),	new structure(300,200,w/2 - 150,100,70,images[1],true,12)	],	worldObjs = [],	createNPCs = function() {	let nameObj = function(name,gender) {	this.name = name;	this.gender = gender;	},	npcNames = [	new nameObj("Alice", 1),	new nameObj("Jack", 0),	new nameObj("Jill", 1)	],	// to be same as players	avatarW = 30,	avatarH = 60;	for (var npcn in npcNames) {	let chooseSkin = randNum(0,3),	placeX = randNum(0,w - avatarW),	placeY = randNum(avatarH,h - chatBar.barH - avatarH);	npcs[npcn] = new avatar(npcNames[npcn].name,npcNames[npcn].gender,chooseSkin,avatarW,avatarH,3,28,2,placeX,placeY,8);	// relocate to player location if ended up inside structure	if (findCllsn(npcs[npcn],structures)) {	npcs[npcn].x = player.x;	npcs[npcn].y = player.y;	}	}	},	control = function(avatar, e) {	// avatar.dir values: 0 = up, 1 = right, 2 = down, 3 = left	if (e && !chatBar.active) {	avatar.isMoving = true;	avatar.canMove = true;	switch (e.keyCode) {	case 37:	avatar.dir = 3;	break;	case 38:	avatar.dir = 0;	break;	case 39:	avatar.dir = 1;	break;	case 40:	avatar.dir = 2;	break;	default:	avatar.canMove = false;	break;	}	}	},	stopControl = function(avatar) {	avatar.isMoving = false;	},	avatarSpriteLoop = function(avatar) {	if (avatar.curFrame == avatar.frames) {	avatar.curFrame = 1;	} else {	++avatar.curFrame;	}	},	moveAvatar = function(avatar) {	if (avatar.isMoving && avatar.canMove) {	switch (avatar.dir) {	case 3:	avatar.x -= avatar.speed;	// collision with right side of structure, collisions apply to walls as well	if (findCllsn(avatar,structures) || avatar.x < 0) {	avatar.x += avatar.speed;	avatar.curFrame = 1;	} else {	avatarSpriteLoop(avatar);	}	break;	case 0:	avatar.y -= avatar.speed;	// bottom side	if (findCllsn(avatar,structures) || avatar.y < 0) {	avatar.y += avatar.speed;	avatar.curFrame = 1;	} else {	avatarSpriteLoop(avatar);	}	break;	case 1:	avatar.x += avatar.speed;	// left side	if (findCllsn(avatar,structures) || avatar.x + avatar.w > w) {	avatar.x -= avatar.speed;	avatar.curFrame = 1;	} else {	avatarSpriteLoop(avatar);	}	break;	case 2:	avatar.y += avatar.speed;	// top side	if (findCllsn(avatar,structures) || avatar.y + avatar.h > h) {	avatar.y -= avatar.speed;	avatar.curFrame = 1;	} else {	avatarSpriteLoop(avatar);	}	break;	default:	break;	}	} else {	avatar.curFrame = 1;	}	},	npcAI = function(npc) {	if (npc.lvl > 0) {	npc.isMoving = randNum(0,npc.lvl + 1) === 0 ? false : true;	// just like player, NPCs can chat if not moving	if (npc.isMoving) {	npc.dir = randNum(0,4);	} else {	let msgs = ["
Club Command Line - Script Codes
Club Command Line - Script Codes
Home Page Home
Developer Jon Kantner
Username jkantner
Uploaded August 17, 2022
Rating 4
Size 12,560 Kb
Views 34,408
Do you need developer help for Club Command Line?

Find the perfect freelance services for your business! Fiverr's mission is to change how the world works together. Fiverr connects businesses with freelancers offering digital services in 500+ categories. Find Developer!

Jon Kantner (jkantner) Script Codes
Create amazing marketing copy with AI!

Jasper is the AI Content Generator that helps you and your team break through creative blocks to create amazing, original content 10X faster. Discover all the ways the Jasper AI Content Platform can help streamline your creative workflows. Start For Free!