Update runner_functions.js

This commit is contained in:
Kaan Soral
2020-06-09 15:27:04 +03:00
committed by GitHub
parent 407db262af
commit b274346b84
+185 -85
View File
@@ -33,6 +33,7 @@ game={
html:!parent.no_html, // if game.html is false, this character is loaded in [CODE] mode html:!parent.no_html, // if game.html is false, this character is loaded in [CODE] mode
}; };
character.bot=parent.is_bot; character.bot=parent.is_bot;
character.cli=parent.is_cli;
//#NOTE: Most new features are experimental - for #feedback + suggestions: https://discord.gg/X4MpntA [05/01/18] //#NOTE: Most new features are experimental - for #feedback + suggestions: https://discord.gg/X4MpntA [05/01/18]
@@ -99,26 +100,6 @@ function shift(num,name) // shifts an item, likely a booster, in the num-th inve
parent.shift(num,name); parent.shift(num,name);
} }
function can_use(name)
{
if(G.skills[name] && G.skills[name].class && !in_arr(character.ctype,G.skills[name].class)) return false; // checks the class
return parent.can_use(name); // checks the cooldown
}
function use(name,target) // a multi-purpose use function, works for skills too
{
if(isNaN(name)) // if name is not an integer, use the skill
{
if(!target) target=get_target();
parent.use_skill(name,target);
}
else
{
// for example, if there is a potion at the first inventory slot, use(0) would use it
equip(name);
}
}
function use_skill(name,target,extra_arg) function use_skill(name,target,extra_arg)
{ {
// target: object or string (character name or monster ID) // target: object or string (character name or monster ID)
@@ -169,21 +150,17 @@ function bank_store(num,pack,pack_slot)
if(!pack) if(!pack)
{ {
var cp=undefined,cs=undefined; var cp=undefined,cs=undefined;
bank_packs.forEach(function(cpack){ for(var cpack in bank_packs)
if(!character.bank[cpack]) return; {
if(pack || bank_packs[cpack][0]!=character.map || !character.bank[cpack]) continue;
for(var i=0;i<42;i++) for(var i=0;i<42;i++)
{ {
if(pack) return;
if(can_stack(character.bank[cpack][i],character.items[num])) // the item we want to store and this bank item can stack - best case scenario if(can_stack(character.bank[cpack][i],character.items[num])) // the item we want to store and this bank item can stack - best case scenario
{
pack=cpack; pack=cpack;
}
if(!character.bank[cpack][i] && !cp) if(!character.bank[cpack][i] && !cp)
{
cp=cpack; cp=cpack;
}
} }
}); }
if(!pack && !cp) return game_log("Bank is full!"); if(!pack && !cp) return game_log("Bank is full!");
if(!pack) pack=cp; if(!pack) pack=cp;
} }
@@ -332,15 +309,17 @@ function get_targeted_monster()
return null; return null;
} }
function change_target(target,public) function change_target(target)
{ {
parent.ctarget=target; parent.ctarget=target;
if(!public) //no need to send the target on default for CODE, some people are using change_target 5-6 times in an interval parent.send_target_logic();
{ }
// user change_target(target,true) from now on to send the target to the server explicitly [23/10/16]
if(target) parent.last_id_sent=target.id; function change_target_privately(target)
else parent.last_id_sent=''; {
} parent.ctarget=target;
if(target) parent.last_id_sent=target.id; // Marks the id as sent, so it doesn't actually get sent
else parent.last_id_sent='';
parent.send_target_logic(); parent.send_target_logic();
} }
@@ -352,8 +331,8 @@ function can_move_to(x,y)
function xmove(x,y) function xmove(x,y)
{ {
if(can_move_to(x,y)) move(x,y); if(can_move_to(x,y)) return move(x,y);
else smart_move({x:x,y:y}); else return smart_move({x:x,y:y});
} }
function is_in_range(target,skill) function is_in_range(target,skill)
@@ -449,6 +428,11 @@ function sell(num,quantity) //sell an item from character.items by it's order -
parent.sell(num,quantity); parent.sell(num,quantity);
} }
function consume(num) // consumes or uses an inventory item
{
parent.socket.emit("equip",{num:num,consume:true});
}
function equip(num,slot) // slot is optional function equip(num,slot) // slot is optional
{ {
parent.socket.emit("equip",{num:num,slot:slot}); parent.socket.emit("equip",{num:num,slot:slot});
@@ -518,8 +502,8 @@ function pm(name,message) // please use responsibly, thank you! :)
function move(x,y) function move(x,y)
{ {
if(!can_walk(character)) return; if(!can_walk(character)) return rejecting_promise({reason:"unable"});
parent.move(x,y); return parent.move(x,y,true);
} }
function cruise(speed) function cruise(speed)
@@ -533,6 +517,27 @@ function show_json(e) // renders the object as json inside the game
else parent.show_json(parent.game_stringify(e,'\t')); else parent.show_json(parent.game_stringify(e,'\t'));
} }
function get_servers()
{
// returns an array of server data
// best to inspect the format with show_json(get_servers())
return parent.X.servers;
}
function get_characters()
{
// returns an infrequently updated array of your characters
// best to inspect the format with show_json(get_characters())
return parent.X.characters;
}
function get_party()
{
// returns an infrequently updated object
// best to inspect the format with show_json(get_party())
return parent.party;
}
function get_monster(id) function get_monster(id)
{ {
// returns the monster by id, an integer, if the monster is within the vision area // returns the monster by id, an integer, if the monster is within the vision area
@@ -685,6 +690,14 @@ function send_item(receiver,num,quantity)
parent.socket.emit("send",{name:receiver,num:num,q:quantity||1}); parent.socket.emit("send",{name:receiver,num:num,q:quantity||1});
} }
function send_cx(receiver,cx)
{
// Sends cosmetics to one of your own characters
if(!receiver) return game_log("No receiver sent to send_cx");
if(receiver.name) receiver=receiver.name;
parent.socket.emit("send",{name:receiver,cx:cx});
}
function destroy(num) // num: 0 to 41 function destroy(num) // num: 0 to 41
{ {
parent.socket.emit("destroy",{num:num}); parent.socket.emit("destroy",{num:num});
@@ -718,6 +731,11 @@ function leave_party()
parent.socket.emit("party",{event:"leave"}); parent.socket.emit("party",{event:"leave"});
} }
function kick_party_member(name)
{
parent.socket.emit('party',{event:'kick',name:name});
}
function accept_magiport(name) function accept_magiport(name)
{ {
parent.remove_chat("mp"+name); parent.remove_chat("mp"+name);
@@ -1052,41 +1070,57 @@ function reset_mappings()
// delete previous/stale messages // delete previous/stale messages
var activity=localStorage.getItem("activity"); for (var key in localStorage)
activity=activity&&JSON.parse(activity)||{}; {
if(!activity.cm) activity.cm={}; if(key.startsWith("cm_"+character.name+"_"))
delete activity.cm[character.name]; {
localStorage.setItem("activity",JSON.stringify(activity)); var data=localStorage.getItem(key);
localStorage.removeItem(key);
game_log("Removed a stale code message from: "+JSON.parse(data)[0],"gray");
}
}
setInterval(function(){ setInterval(function(){
var activity=localStorage.getItem("activity"),activities=[],beat={},change=false; var activity=localStorage.getItem("activity"),messages=[];
activity=activity&&JSON.parse(activity)||{}; activity=activity&&JSON.parse(activity)||{};
if(!activity.heartbeat) activity.heartbeat={}; if(!activity.heartbeat) activity.heartbeat={};
if(activity.cm) delete activity.cm;
if(!activity.heartbeat[character.name] || mssince(new Date(activity.heartbeat[character.name]))>200) if(!activity.heartbeat[character.name] || mssince(new Date(activity.heartbeat[character.name]))>200)
activity.heartbeat[character.name]=(new Date()).toString(),change=true;
if(!activity.cm) activity.cm={};
if(activity.cm[character.name] && activity.cm[character.name].length)
{ {
activities=activity.cm[character.name]; activity.heartbeat[character.name]=(new Date()).toString();
delete activity.cm[character.name];
change=true;
}
if(change)
localStorage.setItem("activity",JSON.stringify(activity)); localStorage.setItem("activity",JSON.stringify(activity));
activities.forEach(function(cm){ }
character.trigger("cm",{name:cm[0],message:cm[1],local:true});
for (var key in localStorage)
{
if(key.startsWith("cm_"+character.name+"_"))
{
var data=localStorage.getItem(key);
localStorage.removeItem(key);
data=JSON.parse(data);
data[2]=new Date(data[2]);
messages.push(data);
}
}
messages.sort(function(a,b){
if(!(a[2]-b[2]))
return a[3]-b[3];
else
return a[2]-b[2];
});
if(messages.length) console.log(messages);
messages.forEach(function(cm){
character.trigger("cm",{name:cm[0],message:cm[1],date:cm[2],local:true});
}); });
},10); },10);
var local_m_num=0;
function send_local_cm(name,data) function send_local_cm(name,data)
{ {
var activity=localStorage.getItem("activity"); localStorage.setItem("cm_"+name+"_"+randomStr(20),JSON.stringify([character.name,data,new Date(),++local_m_num]));
activity=activity&&JSON.parse(activity)||{};
if(!activity.heartbeat) activity.heartbeat={};
if(!activity.cm) activity.cm={};
if(!activity.cm[name]) activity.cm[name]=[];
activity.cm[name].push([character.name,data]);
localStorage.setItem("activity",JSON.stringify(activity));
} }
function is_character_local(name) function is_character_local(name)
@@ -1134,19 +1168,52 @@ function get(name)
} }
} }
function load_code(name,onerror) // onerror can be a function that will be executed if load_code fails function load_code(name,onerror)
{ {
if(!onerror) onerror=function(){ game_log("load_code: Failed to load",colors.code_error); } // load_code executes the code at top-level in a synchronized manner
var xhrObj = new XMLHttpRequest(); // each function/variable becomes directly available
xhrObj.open('GET',"/code.js?name="+encodeURIComponent(name)+"&timestamp="+(new Date().getTime()), false); // onerror can be a function that will be executed if load_code fails
xhrObj.send('');
var code=parent.get_code_file(name); // works on Electron, returns the local file
if(code===null)
{
var xhrObj = new XMLHttpRequest();
xhrObj.open('GET',"/code.js?name="+encodeURIComponent(name)+"&timestamp="+(new Date().getTime()), false);
xhrObj.send('');
code=xhrObj.responseText;
}
var library=document.createElement("script"); var library=document.createElement("script");
library.type="text/javascript"; library.type="text/javascript";
library.text=xhrObj.responseText; library.text=code;
library.onerror=onerror; library.onerror=onerror||function(){ game_log("load_code: Failed to load",colors.code_error); };
document.getElementsByTagName("head")[0].appendChild(library); document.getElementsByTagName("head")[0].appendChild(library);
} }
function require_code(name)
{
// require_code executes code inside it's own scope in a synchronized manner
// functions returns the exports dictionary, emulating a require
var code=parent.get_code_file(name);
if(code===null)
{
var xhrObj = new XMLHttpRequest();
xhrObj.open('GET',"/code.js?name="+encodeURIComponent(name)+"&xrequire=1&timestamp="+(new Date().getTime()), false);
xhrObj.send('');
code=xhrObj.responseText;
}
var module={exports:{}};
var exports=module.exports;
eval(code);
return module.exports;
}
var smart={ var smart={
moving:false, moving:false,
map:"main",x:0,y:0, map:"main",x:0,y:0,
@@ -1163,8 +1230,11 @@ var smart={
flags:{} flags:{}
}; };
function smart_move(destination,on_done) // despite the name, smart_move isn't very smart or efficient, it's up to the players to implement a better movement method [05/02/17] function smart_move(destination,on_done)
{ {
// despite the name, smart_move isn't very smart or efficient, it's up to the players to implement a better movement method [05/02/17]
// on_done function is an old callback function for compatibility, smart_move also returns a Promise [25/03/20]
if(smart.moving) smart.on_done(false,"interrupted");
smart.map=""; smart.map="";
if(is_string(destination)) destination={to:destination}; if(is_string(destination)) destination={to:destination};
if(is_number(destination)) destination={x:destination,y:on_done},on_done=null; if(is_number(destination)) destination={x:destination,y:on_done},on_done=null;
@@ -1223,29 +1293,36 @@ function smart_move(destination,on_done) // despite the name, smart_move isn't v
if(!smart.map) if(!smart.map)
{ {
game_log("Unrecognized location","#CF5B5B"); game_log("Unrecognized location","#CF5B5B");
return; return rejecting_promise({reason:"invalid"});
} }
smart.moving=true; smart.moving=true;
smart.plot=[]; smart.flags={}; smart.searching=smart.found=false; smart.plot=[]; smart.flags={}; smart.searching=smart.found=false;
if(destination.return) if(destination.return)
{ {
var cx=character.real_x,cy=character.real_y,cmap=character.map; var cx=character.real_x,cy=character.real_y,cmap=character.map;
smart.on_done=function(){ smart.on_done=function(done,reason){
if(on_done) on_done(); if(on_done) on_done(done);
smart_move({map:cmap,x:cx,y:cy}); smart_move({map:cmap,x:cx,y:cy});
if(done) resolve_deferreds("smart_move",{success:true});
else reject_deferreds("smart_move",{reason:reason});
} }
} }
else smart.on_done=on_done||function(){}; else smart.on_done=function(done,reason){
console.log(smart.map+" "+smart.x+" "+smart.y); if(on_done) on_done(done);
if(done) resolve_deferreds("smart_move",{success:true});
else reject_deferreds("smart_move",{reason:reason});
};
console.log("smart_move: "+smart.map+" "+smart.x+" "+smart.y);
return push_deferred("smart_move");
} }
function stop(action) function stop(action,second)
{ {
if(!action || action=="move") if(!action || action=="move" || action=="smart")
{ {
if(smart.moving) smart.on_done(false); if(smart.moving) smart.on_done(second||false,"interrupted");
smart.moving=false; smart.moving=false;
move(character.real_x,character.real_y); if(action!="smart") move(character.real_x,character.real_y);
} }
else if(action=="invis") else if(action=="invis")
{ {
@@ -1330,7 +1407,7 @@ function bfs()
if(smart.prune.map && smart.flags.map) {start++; continue;} if(smart.prune.map && smart.flags.map) {start++; continue;}
map.doors.forEach(function(door){ map.doors.forEach(function(door){
// if(simple_distance({x:map.spawns[door[6]][0],y:map.spawns[door[6]][1]},{x:current.x,y:current.y})<30) // if(simple_distance({x:map.spawns[door[6]][0],y:map.spawns[door[6]][1]},{x:current.x,y:current.y})<30)
if(smart.map!="bank" && door[4]=="bank") return; // manually patch the bank shortcut if(smart.map!="bank" && door[4]=="bank" && !G.maps[current.map].mount || door[8]=="complicated") return; // manually patch the bank shortcut
if(is_door_close(current.map,door,current.x,current.y) && can_use_door(current.map,door,current.x,current.y)) if(is_door_close(current.map,door,current.x,current.y) && can_use_door(current.map,door,current.x,current.y))
qlist.push({map:door[4],x:G.maps[door[4]].spawns[door[5]||0][0],y:G.maps[door[4]].spawns[door[5]||0][1],transport:true,s:door[5]||0}); qlist.push({map:door[4],x:G.maps[door[4]].spawns[door[5]||0][0],y:G.maps[door[4]].spawns[door[5]||0][1],transport:true,s:door[5]||0});
}); });
@@ -1361,12 +1438,12 @@ function bfs()
if(mssince(timer)>(!parent.is_hidden()&&40||500)) return; if(mssince(timer)>(!parent.is_hidden()&&40||500)) return;
} }
if(result===null) result=best,optimal=false;
if(result===null) if(result===null)
{ {
result=best,optimal=false;
game_log("Path not found!","#CF575F"); game_log("Path not found!","#CF575F");
smart.moving=false; smart.moving=false;
smart.on_done(false); smart.on_done(false,"failed");
} }
else else
{ {
@@ -1396,9 +1473,31 @@ function start_pathfinding()
smart.start_x=character.real_x; smart.start_x=character.real_x;
smart.start_y=character.real_y; smart.start_y=character.real_y;
queue=[],visited={},start=0,best=null; queue=[],visited={},start=0,best=null;
qpush({x:character.real_x,y:character.real_y,map:character.map,i:-1}); if(character.cli)
game_log("Searching for a path...","#89D4A2"); {
bfs(); parent.CLI_OUT.push({"type":"smart_move",G:G,start_x:smart.start_x,start_y:smart.start_y,start_map:character.map,x:smart.x,y:smart.y,map:smart.map});
}
else
{
qpush({x:character.real_x,y:character.real_y,map:character.map,i:-1});
game_log("Searching for a path...","#89D4A2");
bfs();
}
}
function cli_smart_move_result(data)
{
if(data.found)
{
smart.found=true;
smart.plot=data.plot;
}
else
{
game_log("CLI: Path not found!","#CF575F");
smart.moving=false;
smart.on_done(false,"failed");
}
} }
function continue_pathfinding() function continue_pathfinding()
@@ -1413,6 +1512,7 @@ function smart_move_logic()
{ {
start_pathfinding(); start_pathfinding();
} }
else if(!smart.found && character.cli) { /* Just wait */ }
else if(!smart.found) else if(!smart.found)
{ {
if(Math.random()<0.1) if(Math.random()<0.1)