mirror of
https://github.com/gooba42/adventureland.git
synced 2026-10-14 18:39:27 -05:00
Update runner_functions.js
This commit is contained in:
+202
-49
@@ -8,10 +8,12 @@ var character={
|
||||
// Added this wrapper so instead of using .real_x and .real_y on all entities, .x and .y's can be used uniformly
|
||||
"note":"This is a proxy object, the real character is in parent.character",
|
||||
"properties":["x","y"],
|
||||
"read_only":["x","y","real_x","real_y","from_x","from_y","going_x","going_y","moving","target","vx","vy","move_num","attack","speed","hp","mp","xp","max_hp","max_mp","range","level","rip","s","c","in","map","stand","items","slots"],
|
||||
"proxy_character":true,
|
||||
}
|
||||
|
||||
Object.defineProperty(character,'x',{get:function(){return parent.character.real_x;},set:function(){game_log("You can't set coordinates manually, use the move(x,y) function!");}});
|
||||
Object.defineProperty(character,'y',{get:function(){return parent.character.real_y;},set:function(){game_log("You can't set coordinates manually, use the move(x,y) function!");}});
|
||||
Object.defineProperty(character,'x',{get:function(){return parent.character.real_x;},set:function(){game_log("You can't set coordinates manually, use the move(x,y) function!");},enumerable:true});
|
||||
Object.defineProperty(character,'y',{get:function(){return parent.character.real_y;},set:function(){game_log("You can't set coordinates manually, use the move(x,y) function!");},enumerable:true});
|
||||
for(var p in parent.character) proxy(p); // Not all properties are sadly available right away, new properties are captured imperfectly
|
||||
// var character=parent.character; // Old [25/06/2018]
|
||||
|
||||
@@ -124,6 +126,18 @@ function use_skill(name,target)
|
||||
parent.use_skill(name,target);
|
||||
}
|
||||
|
||||
function reduce_cooldown(name,ms)
|
||||
{
|
||||
// parent.next_skill contains Date objects of when the skills will be available next
|
||||
// show_json(parent.next_skill) to get a better idea
|
||||
// reduce_cooldown("attack",100) would cause the attack cooldown to reduce by 100 ms
|
||||
// If your ping is 100+ms - this would ~correct/improve/adjust the cooldown
|
||||
// attack(target).then(function(data){ reduce_cooldown("attack",character.ping*0.95); });
|
||||
// Above call is likely the ideal usage
|
||||
if(parent.next_skill[name])
|
||||
parent.skill_timeout(name,-mssince(parent.next_skill[name])-ms);
|
||||
}
|
||||
|
||||
function bank_deposit(gold)
|
||||
{
|
||||
if(!character.bank) return game_log("Not inside the bank");
|
||||
@@ -260,7 +274,14 @@ function set_message(text,color)
|
||||
function game_log(message,color)
|
||||
{
|
||||
if(!color) color="#51D2E1";
|
||||
parent.add_log(message,color);
|
||||
if(character.bot) parent.parent.add_log(character.name+": "+message,color);
|
||||
else parent.add_log(message,color);
|
||||
}
|
||||
|
||||
function log(message,color)
|
||||
{
|
||||
if(is_object(message)) message=JSON.stringify(message);
|
||||
game_log(message,color);
|
||||
}
|
||||
|
||||
function get_target_of(entity) // .target is a Name for Monsters and `id` for Players - this function return whatever the entity in question is targeting
|
||||
@@ -322,7 +343,7 @@ function can_attack(target) // also works for priests/heal
|
||||
{
|
||||
// is_disabled function checks .rip and .stunned
|
||||
if(!target) return false;
|
||||
if(!parent.is_disabled(character) && in_attack_range(target) && new Date()>=parent.next_attack) return true;
|
||||
if(!parent.is_disabled(character) && in_attack_range(target) && new Date()>=parent.next_skill.attack) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -348,19 +369,27 @@ function is_transporting(entity)
|
||||
|
||||
function attack(target)
|
||||
{
|
||||
if(safeties && mssince(last_attack)<400) return;
|
||||
if(!target) { game_log("Nothing to attack()","gray"); return; }
|
||||
if(target.type=="character") parent.player_attack.call(target);
|
||||
else parent.monster_attack.call(target);
|
||||
last_attack=new Date();
|
||||
if(target==character) target=parent.character;
|
||||
if(!target)
|
||||
{
|
||||
game_log("Nothing to attack()","gray");
|
||||
return rejecting_promise({reason:"not_found"});
|
||||
}
|
||||
if(target.type=="character")
|
||||
return parent.player_attack.call(target,null,true);
|
||||
else
|
||||
return parent.monster_attack.call(target,null,true);
|
||||
}
|
||||
|
||||
function heal(target)
|
||||
{
|
||||
if(safeties && mssince(last_attack)<400) return;
|
||||
if(!target) { game_log("No one to heal()","gray"); return; }
|
||||
parent.player_heal.call(target);
|
||||
last_attack=new Date();
|
||||
if(target==character) target=parent.character; // Don't send the proxy object to parent [10/06/19]
|
||||
if(!target)
|
||||
{
|
||||
game_log("No one to heal()","gray");
|
||||
return rejecting_promise({reason:"not_found"});
|
||||
}
|
||||
return parent.player_heal.call(target,null,true);
|
||||
}
|
||||
|
||||
function buy(name,quantity) //item names can be spotted from show_json(character.items) - they can be bought only if an NPC sells them
|
||||
@@ -406,19 +435,12 @@ function trade_buy(target,trade_slot) // target needs to be an actual player
|
||||
|
||||
function upgrade(item_num,scroll_num,offering_num) // number of the item and scroll on the show_json(character.items) array - 0 to N-1
|
||||
{
|
||||
parent.u_item=item_num;
|
||||
parent.u_scroll=scroll_num;
|
||||
parent.u_offering=offering_num;
|
||||
return parent.upgrade("code"); // returns a Promise
|
||||
return parent.upgrade(item_num,scroll_num,offering_num,"code"); // returns a Promise
|
||||
}
|
||||
|
||||
function compound(item0,item1,item2,scroll_num,offering_num) // for example -> compound(0,1,2,6) -> 3 items in the first 3 slots, scroll at the 6th spot
|
||||
{
|
||||
parent.c_items=[item0,item1,item2];
|
||||
parent.c_last=3;
|
||||
parent.c_scroll=scroll_num;
|
||||
parent.c_offering=offering_num;
|
||||
parent.compound();
|
||||
parent.compound(item0,item1,item2,scroll_num,offering_num,"code");
|
||||
}
|
||||
|
||||
function craft(i0,i1,i2,i3,i4,i5,i6,i7,i8)
|
||||
@@ -429,6 +451,12 @@ function craft(i0,i1,i2,i3,i4,i5,i6,i7,i8)
|
||||
parent.craft();
|
||||
}
|
||||
|
||||
function auto_craft(name)
|
||||
{
|
||||
// Picks the inventory positions automatically. Example: auto_craft("computer")
|
||||
return parent.auto_craft(name,true);
|
||||
}
|
||||
|
||||
function dismantle(item_num)
|
||||
{
|
||||
parent.ds_item=item_num;
|
||||
@@ -468,14 +496,48 @@ function show_json(e) // renders the object as json inside the game
|
||||
else parent.show_json(parent.game_stringify(e,'\t'));
|
||||
}
|
||||
|
||||
function get_player(name) // returns the player by name, if the player is within the vision area
|
||||
function get_monster(id)
|
||||
{
|
||||
// returns the monster by id, an integer, if the monster is within the vision area
|
||||
var target=parent.entities[id];
|
||||
if(target && target.type!="monster") target=null;
|
||||
return target;
|
||||
}
|
||||
|
||||
function get_player(name)
|
||||
{
|
||||
// returns the player by name, if the player is within the vision area
|
||||
var target=null,entities=parent.entities;
|
||||
if(name==character.name) target=character;
|
||||
for(i in entities) if(entities[i].type=="character" && entities[i].name==name) target=entities[i];
|
||||
return target;
|
||||
}
|
||||
|
||||
function get_entity(id)
|
||||
{
|
||||
// entities are currently players, monsters and citizen npcs, this function returns players and monsters
|
||||
var target=parent.entities[id];
|
||||
if(id==character.name) target=character;
|
||||
return target;
|
||||
}
|
||||
|
||||
function find_npc(npc_id)
|
||||
{
|
||||
// returns smart_move'able coordinates for an NPC key from G.npcs
|
||||
for(var name in parent.G.maps)
|
||||
{
|
||||
var map=parent.G.maps[name];
|
||||
if(map.ignore || !map.npcs) continue;
|
||||
for(var i=0;i<map.npcs.length;i++)
|
||||
{
|
||||
var npc=map.npcs[i];
|
||||
if(npc.id==npc_id)
|
||||
return {map:name,"in":name,x:npc.position[0],y:npc.position[1]};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function get_nearest_monster(args)
|
||||
{
|
||||
//args:
|
||||
@@ -519,8 +581,9 @@ function get_nearest_hostile(args) // mainly as an example [08/02/17]
|
||||
{
|
||||
var current=parent.entities[id];
|
||||
if(current.type!="character" || !current.visible || current.rip || current.invincible || current.npc) continue;
|
||||
if(current.party && character.party==current.party) continue;
|
||||
if(current.guild && character.guild==current.guild) continue;
|
||||
if(character.team && current.team==character.team) continue;
|
||||
if(!character.team && current.party && character.party==current.party) continue;
|
||||
if(!character.team && current.guild && character.guild==current.guild) continue;
|
||||
if(args.friendship && in_arr(current.owner,parent.friends)) continue;
|
||||
if(args.exclude && in_arr(current.name,args.exclude)) continue; // get_nearest_hostile({exclude:["Wizard"]}); Thanks
|
||||
var c_dist=parent.distance(character,current);
|
||||
@@ -531,9 +594,9 @@ function get_nearest_hostile(args) // mainly as an example [08/02/17]
|
||||
|
||||
function use_hp_or_mp()
|
||||
{
|
||||
if(safeties && mssince(last_potion)<600) return;
|
||||
if(safeties && mssince(last_potion)<min(200,character.ping*3)) return;
|
||||
var used=false;
|
||||
if(new Date()<parent.next_potion) return;
|
||||
if(new Date()<parent.next_skill.use_hp) return;
|
||||
if(character.mp/character.max_mp<0.2) use('use_mp'),used=true;
|
||||
else if(character.hp/character.max_hp<0.7) use('use_hp'),used=true;
|
||||
else if(character.mp/character.max_mp<0.8) use('use_mp'),used=true;
|
||||
@@ -546,9 +609,9 @@ function loot(commander)
|
||||
{
|
||||
// loot(true) allows code characters to make their commanders' loot instead, extremely useful [14/01/18]
|
||||
var looted=0;
|
||||
if(safeties && mssince(last_loot)<200) return;
|
||||
if(safeties && mssince(last_loot)<min(300,character.ping*3)) return;
|
||||
last_loot=new Date();
|
||||
for(id in parent.chests)
|
||||
for(var id in parent.chests)
|
||||
{
|
||||
var chest=parent.chests[id];
|
||||
if(safeties && (chest.items>character.esize || chest.last_loot && mssince(chest.last_loot)<1600)) continue;
|
||||
@@ -635,7 +698,13 @@ function send_cm(to,data)
|
||||
{
|
||||
// to: Name or Array of Name's
|
||||
// data: JSON object
|
||||
parent.send_code_message(to,data);
|
||||
var to_server=[];
|
||||
if(!is_array(to)) to=[to];
|
||||
to.forEach(function(name){
|
||||
if(is_character_local(name)) send_local_cm(name,data);
|
||||
else to_server.push(name);
|
||||
})
|
||||
if(to_server.length) parent.send_code_message(to_server,data); // message over the server - has a high call cost / character.cc
|
||||
}
|
||||
|
||||
function on_disappear(entity,data)
|
||||
@@ -643,11 +712,6 @@ function on_disappear(entity,data)
|
||||
// game_log("disappear: "+entity.id+" "+JSON.stringify(data));
|
||||
}
|
||||
|
||||
function on_combined_damage() // When multiple characters stay in the same spot, they receive combined damage, this function gets called whenever a monster deals combined damage
|
||||
{
|
||||
// move(character.real_x+5,character.real_y);
|
||||
}
|
||||
|
||||
function on_party_invite(name) // called by the inviter's name
|
||||
{
|
||||
// accept_party_invite(name)
|
||||
@@ -786,11 +850,19 @@ character.all=function(f){
|
||||
character.listeners.push(def);
|
||||
return def.id;
|
||||
};
|
||||
character.on=function(event,f){
|
||||
var def={f:f,id:randomStr(30),event:event};
|
||||
character.one=function(event,f){ // gets overwritten if another handler comes along
|
||||
var def={f:f,id:randomStr(30),event:event,one:true};
|
||||
character.listeners.push(def);
|
||||
return def.id;
|
||||
};
|
||||
character.on=function(event,f){
|
||||
var def={f:f,id:randomStr(30),event:event},handled=false;
|
||||
for(var i=0;i<character.listeners.length;i++)
|
||||
if(character.listeners[i].one && character.listeners[i].event==event)
|
||||
character.listeners[i]=def,handled=true;
|
||||
if(!handled) character.listeners.push(def);
|
||||
return def.id;
|
||||
};
|
||||
character.trigger=function(event,args){
|
||||
var to_delete=[];
|
||||
for(var i=0;i<character.listeners.length;i++)
|
||||
@@ -943,6 +1015,64 @@ function reset_mappings()
|
||||
set_skillbar(parent.skillbar);
|
||||
}
|
||||
|
||||
|
||||
// delete previous/stale messages
|
||||
var activity=localStorage.getItem("activity");
|
||||
activity=activity&&JSON.parse(activity)||{};
|
||||
if(!activity.cm) activity.cm={};
|
||||
delete activity.cm[character.name];
|
||||
localStorage.setItem("activity",JSON.stringify(activity));
|
||||
|
||||
|
||||
var processed_activity=false,processed_activity_change=false;
|
||||
setInterval(function(){
|
||||
var activity=localStorage.getItem("activity");
|
||||
processed_activity_change=false;
|
||||
processed_activity=activity=activity&&JSON.parse(activity)||{};beat={};
|
||||
if(!activity.heartbeat) activity.heartbeat={};
|
||||
if(!activity.heartbeat[character.name] || mssince(new Date(activity.heartbeat[character.name]))>200)
|
||||
activity.heartbeat[character.name]=(new Date()).toString(),processed_activity_change=true;
|
||||
if(!activity.cm) activity.cm={};
|
||||
if(activity.cm[character.name] && activity.cm[character.name].length)
|
||||
{
|
||||
activity.cm[character.name].forEach(function(cm){
|
||||
character.trigger("cm",{name:cm[0],message:cm[1],local:true});
|
||||
});
|
||||
delete activity.cm[character.name];
|
||||
processed_activity_change=true;
|
||||
}
|
||||
if(processed_activity_change)
|
||||
localStorage.setItem("activity",JSON.stringify(activity));
|
||||
processed_activity=false;
|
||||
},10);
|
||||
|
||||
function send_local_cm(name,data)
|
||||
{
|
||||
var activity=processed_activity;
|
||||
if(!processed_activity)
|
||||
{
|
||||
activity=localStorage.getItem("activity");
|
||||
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]);
|
||||
if(!processed_activity)
|
||||
localStorage.setItem("activity",JSON.stringify(activity));
|
||||
else
|
||||
processed_activity_change=true;
|
||||
}
|
||||
|
||||
function is_character_local(name)
|
||||
{
|
||||
var activity=localStorage.getItem("activity");
|
||||
activity=activity&&JSON.parse(activity)||{};
|
||||
if(activity.heartbeat && activity.heartbeat[name] && mssince(new Date(activity.heartbeat[name]))<2400)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function pset(name,value)
|
||||
{
|
||||
// on Web, window.localStorage is used, on Steam/Mac, the electron-store package is used for persistent storage
|
||||
@@ -1000,6 +1130,7 @@ function smart_move(destination,on_done) // despite the name, smart_move isn't v
|
||||
if(destination.to=="town") destination.to="main";
|
||||
if(G.monsters[destination.to])
|
||||
{
|
||||
var locations=[],theone;
|
||||
for(var name in G.maps)
|
||||
(G.maps[name].monsters||[]).forEach(function(pack){
|
||||
if(pack.type!=destination.to || G.maps[name].ignore || G.maps[name].instance) return;
|
||||
@@ -1008,18 +1139,19 @@ function smart_move(destination,on_done) // despite the name, smart_move isn't v
|
||||
pack.last=pack.last||0;
|
||||
var boundary=pack.boundaries[pack.last%pack.boundaries.length];
|
||||
pack.last++;
|
||||
smart.map=boundary[0];
|
||||
smart.x=(boundary[1]+boundary[3])/2;
|
||||
smart.y=(boundary[2]+boundary[4])/2;
|
||||
locations.push([boundary[0],(boundary[1]+boundary[3])/2,(boundary[2]+boundary[4])/2]);
|
||||
}
|
||||
else if(pack.boundary)
|
||||
{
|
||||
var boundary=pack.boundary;
|
||||
smart.map=name;
|
||||
smart.x=(boundary[0]+boundary[2])/2;
|
||||
smart.y=(boundary[1]+boundary[3])/2;
|
||||
locations.push([name,(boundary[0]+boundary[2])/2,(boundary[1]+boundary[3])/2]);
|
||||
}
|
||||
});
|
||||
if(locations.length) // This way, when you smart_move("snake") repeatedly - you can keep visiting different maps with snakes
|
||||
{
|
||||
theone=random_one(locations);
|
||||
smart.map=theone[0]; smart.x=theone[1]; smart.y=theone[2];
|
||||
}
|
||||
}
|
||||
else if(G.maps[destination.to||destination.map])
|
||||
{
|
||||
@@ -1033,6 +1165,11 @@ function smart_move(destination,on_done) // despite the name, smart_move isn't v
|
||||
else if(destination.to=="potions" && in_arr(character.map,["winterland","winter_inn","winter_cave"])) smart.map="winter_inn",smart.x=-84,smart.y=-173;
|
||||
else if(destination.to=="potions") smart.map="main",smart.x=56,smart.y=-122;
|
||||
else if(destination.to=="scrolls") smart.map="main",smart.x=-465,smart.y=-71;
|
||||
else if(find_npc(destination.to))
|
||||
{
|
||||
var l=find_npc(destination.to);
|
||||
smart.map=l.map,smart.x=l.x,smart.y=l.y+15;
|
||||
}
|
||||
}
|
||||
if(!smart.map)
|
||||
{
|
||||
@@ -1122,7 +1259,7 @@ function bfs()
|
||||
var current=queue[start];
|
||||
// game_log(current.x+" "+current.y);
|
||||
var map=G.maps[current.map];
|
||||
var c_moves=moves;
|
||||
var c_moves=moves,qlist=[];
|
||||
if(current.map==smart.map)
|
||||
{
|
||||
var c_dist=abs(current.x-smart.x)+abs(current.y-smart.y);
|
||||
@@ -1144,15 +1281,16 @@ function bfs()
|
||||
if(smart.prune.map && smart.flags.map) {start++; continue;}
|
||||
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(smart.map!="bank" && door[4]=="bank") 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))
|
||||
qpush({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});
|
||||
});
|
||||
map.npcs.forEach(function(npc){
|
||||
if(npc.id=="transporter" && simple_distance({x:npc.position[0],y:npc.position[1]},{x:current.x,y:current.y})<75)
|
||||
{
|
||||
for(var place in G.npcs.transporter.places)
|
||||
{
|
||||
qpush({map:place,x:G.maps[place].spawns[G.npcs.transporter.places[place]][0],y:G.maps[place].spawns[G.npcs.transporter.places[place]][1],transport:true,s:G.npcs.transporter.places[place]});
|
||||
qlist.push({map:place,x:G.maps[place].spawns[G.npcs.transporter.places[place]][0],y:G.maps[place].spawns[G.npcs.transporter.places[place]][1],transport:true,s:G.npcs.transporter.places[place]});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1168,6 +1306,7 @@ function bfs()
|
||||
if(can_move({map:current.map,x:current.x,y:current.y,going_x:new_x,going_y:new_y,base:character.base}))
|
||||
qpush({map:current.map,x:new_x,y:new_y});
|
||||
});
|
||||
qlist.forEach(function(q){qpush(q);}); // So regular move's are priotised
|
||||
|
||||
start++;
|
||||
if(mssince(timer)>(!parent.is_hidden()&&40||500)) return;
|
||||
@@ -1273,9 +1412,24 @@ function proxy(name)
|
||||
{
|
||||
if(in_arr(name,character.properties)) return;
|
||||
character.properties.push(name);
|
||||
Object.defineProperty(character,name,{get:function(){return parent.character[name];},set:function(value){delete this[name]; parent.character[name]=value;}});
|
||||
Object.defineProperty(character,name,{
|
||||
get:function(){return parent.character[name];},
|
||||
set:function(value){
|
||||
delete this[name];
|
||||
if(character.read_only.includes(name))
|
||||
{
|
||||
game_log("You attempted to change the character."+name+" value manually. You have to use the provided functions to control your character!",colors.code_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.character[name]=value;
|
||||
}
|
||||
},
|
||||
enumerable:true,
|
||||
});
|
||||
}
|
||||
|
||||
character.read_only.push(...["on","once"]);
|
||||
["bank","user","code","angle","direction","target","from_x","from_y","going_x","going_y","moving","vx","vy","move_num"].forEach(function(p){proxy(p)});
|
||||
setInterval(function(){ for(var p in parent.character) proxy(p); },50); // bottom of the barrel
|
||||
|
||||
@@ -1296,11 +1450,10 @@ function performance_trick()
|
||||
|
||||
//safety flags
|
||||
var last_loot=new Date(0);
|
||||
var last_attack=new Date(0);
|
||||
var last_potion=new Date(0);
|
||||
var last_transport=new Date(0);
|
||||
|
||||
var last_message="",current_message="";
|
||||
if(!window.requestAnimationFrame) window.requestAnimationFrame=function(a){ setTimeout(a,16); }; // jsdom patch [18/04/19]
|
||||
function code_draw()
|
||||
{
|
||||
if(last_message!=current_message) $("#gg").html(current_message),last_message=current_message;
|
||||
|
||||
Reference in New Issue
Block a user