Heres a decent attempt at recreating the map.
How it works
Firstly, there is a control NPC which gets the locations of each player no more than once a second. The map NPC on the client then requests this info from the control NPC.
Why have I done it like this? To minimize the amount of info needing to be sent backwards and forwards continously. As it stands, information is only collected when one or more people are viewing the map.*
*
though this solution would be slightly less efficient if there was always going to be one or more people viewing the map, e.g. if it were to be used as a minimap. However, this is not the case so the way it's done is like that for a reason. If it were to be used as a minimap i'd have the control npc collect the info continously rather than waiting for requests from the client
Features:- Uses M key to open like the normal map
- When opened will focus in on your position (though always show as much of the map as possible, it will never show past the edges of the map.)
- Keypad + and Keypad - zoom in and out, arrow keys scroll
- Your head is shown slightly larger on the map than other peoples
- Retains ctrl+click functionality for Staff (Buggy while zommed in or out at the moment.)
The scripts:
MapDB (control NPC)
PHP Code:
//////////////////////////////////////
// Script by Knight Who Says Ni //
//////////////////////////////////////
public function onCreated() {
this.gmapname = "overworld.gmap";
}
public function pollInfo() {
if(this.lastupdate+1 < timevar2) {
this.locations.clear();
this.playernames.clear();
for (p: allplayers) {
if (p.level ==this.gmapname) {
this.locations.add({p.account,p.level,p.x,p.y});
}
}
this.lastupdate = int(timevar2);
}
}
public function getLocations() {
return this.locations;
}
//#CLIENTSIDE
-Map weapon NPC
PHP Code:
//////////////////////////////////////
// Script by Knight Who Says Ni //
//////////////////////////////////////
function onCreated() {
this.staffGuilds = {"Manager","LAT","NAT","etc"};
this.allowedAccounts = {"JkWhoSaysNi","..."};
}
function isStaff() {
return (player.account in this.allowedAccounts || player.guild in this.staffGuilds);
}
function onActionServerside() {
//retrieve data from the mapdb npc
if (params[0] == "info") {
mapdb = findnpc("MapDB");
mapdb.pollInfo();
locations = mapdb.getLocations();
//send data back to the client
triggeraction(0,0,"clientside","-Map",locations);
}
elseif (params[0] == "warp" && isStaff()) {
setlevel2(params[1],params[2],params[3]);
}
}
//#CLIENTSIDE
function putimg(id,imx,imy,image,vis) {
showimg(id,image,imx,imy);
changeimgvis(id,vis);
}
function onCreated() {
disablemap();
this.active = 0;
this.mapimg = "mapimg.png";
this.mapimgwidth = 1624;
this.mapimgheight = 1344;
this.levelswide = 29;
this.levelshigh = 24;
this.gmapname = "overworld.gmap";
}
function showmap() {
disabledefmovement();
setani("maps1","");
this.zoom = 1;
putimg(201,this.xoffset,this.yoffset,this.mapimg,6);
changeimgzoom(201,1);
showpoly(200,{0,0,screenwidth,0,screenwidth,screenheight,0,screenwidth,0,0});
changeimgvis(200,5);
changeimgcolors(200,0,0,0,1);
showtext(202, 20, 20, "Arial", "b", "Press 'M' exit." ).zoom = 0.6;
changeimgvis(202,7);
showtext(203, 20, 30, "Arial", "b", "Keypad + Zoom in" ).zoom = 0.6;
changeimgvis(203,7);
showtext(204, 20, 40, "Arial", "b", "Keypad - Zoom out" ).zoom = 0.6;
changeimgvis(204,7);
showtext(205, 20, 50, "Arial", "b", "Press the 'Arrow Keys' to move around" ).zoom = 0.6;
changeimgvis(205,7);
this.active = 1;
showPlayers();
}
function showPlayers() {
triggeraction(0,0,"serverside","-Map","info");
}
function onActionClientside() {
for(i=0;i<=params[0].size();i++) {
if (params[0][i][1] == this.gmapname) {
putimg(i+250,(((params[0][i][2]/64)*((this.mapimgwidth/this.levelswide)*(this.zoom)))-10)+this.xoffset, (((params[0][i][3]/64)*((this.mapimgheight/this.levelshigh)*(this.zoom)))-10)+this.yoffset,findplayer(params[0][i][0]).headimg,8);
changeimgpart(i+250,0,64,32,32);
changeimgzoom(i+250,(params[0][i][0] == player.account) ? 0.7 : 0.5);
}
}
}
function onTimeout() {
if (this.active == 1) {
if(this.lastupdate+1 < timevar2) {
showPlayers();
this.lastupdate = timevar2;
}
if(keydown2(38,false)) {
this.yoffset += 20;
findimg(201).y += 20;
for (i=250; i<=(250+this.numplayers);i++) {
findimg(i).y += 20;
}
}
if(keydown2(40,false)) {
this.yoffset -= 20;
findimg(201).y -= 20;
for (i=250; i<=(250+this.numplayers);i++) {
findimg(i).y -= 20;
}
}
if(keydown2(39,false)) {
this.xoffset -=20;
findimg(201).x -= 20;
for (i=250; i<=(250+this.numplayers);i++) {
findimg(i).x -= 20;
}
}
if(keydown2(37,false)) {
this.xoffset += 20;
findimg(201).x += 20;
for (i=250; i<=(250+this.numplayers);i++) {
findimg(i).x += 20;
}
}
setTimer(0.05);
}
else exit();
}
function onMouseDown() {
if (this.active == 1 && this.ctrlpressed) {
enabledefmovement();
this.active = 0;
exit();
triggeraction(0,0,"serverside","-Map","warp",this.gmapname,((mousescreenx-this.xoffset)/this.mapimgwidth)*(this.levelswide*64),((mousescreeny-this.yoffset)/this.mapimgheight)*(this.levelshigh*64));
sleep(0.1);
exit();
}
}
function onKeyPressed() {
if (params[1] == "m") {
if (this.active == 0) {
this.ctrlpressed = false;
player.ani = "maps1";
disabledefmovement();
setTimer(0.1);
this.xoffset = 0;
this.yoffset = 0;
if (player.level == this.gmapname) {
poffsetx = ((player.x/64)*(this.mapimgwidth/this.levelswide));
poffsety = ((player.y/64)*(this.mapimgheight/this.levelshigh));
if (poffsetx > screenwidth) {
this.xoffset = (0-poffsetx)+screenwidth/2;
}
if (poffsety > screenheight) {
this.yoffset = (0-poffsety)+screenheight/2;
}
if ((this.xoffset + this.mapimgwidth) < screenwidth) {
this.xoffset = 0-(this.mapimgwidth - screenwidth);
}
if ((this.yoffset + this.mapimgheight) < screenheight) {
this.yoffset = 0-(this.mapimgheight - screenheight);
}
}
showmap();
}
elseif (this.active == 1) {
exit();
enabledefmovement();
this.active = 0;
sleep(0.5);
exit();
}
}
if (this.active == 1) {
if (params[1] == "+") {
this.zoom += 0.1;
changeimgzoom(201,this.zoom);
this.xoffset = (this.mapimgwidth*(1-this.zoom))/2;
this.yoffset = (this.mapimgheight*(1-this.zoom))/2;
this.xoffset += findimg(201).x;
this.yoffset += findimg(201).y;
triggeraction(0,0,"serverside","-Map","info");
}
if (params[1] == "-") {
this.zoom -= 0.1;
changeimgzoom(201,this.zoom);
this.xoffset = (this.mapimgwidth*(1-this.zoom))/2;
this.yoffset = (this.mapimgheight*(1-this.zoom))/2;
this.xoffset += findimg(201).x;
this.yoffset += findimg(201).y;
triggeraction(0,0,"serverside","-Map","info");
}
}
if (params[2] == 29){
this.ctrlpressed = true;
}
}
function exit() {
hideimg(201);
hideimg(200);
hideimg(202);
hideimg(203);
hideimg(204);
hideimg(205);
this.ctrlpressed = false;
for (i=250; i<=(250+this.numplayers);i++) {
hideimg(i);
}
}
Usage
In the MapDB npc you must set this.gmapname to the name of the gmap being used.
In -Map (serverside) you should set this.staffGuilds and this.allowedAccounts to allow staff to use ctrl+click warping
In -Map (clientside) you need to set the following:
this.mapimg The name of the image of the map.
this.mapimgwidth The width, in pixels, of the map image
this.mapimgheight The height, in pixels, of the map image
this.levelswide The width, in levels of the gmap
this.levelshigh The height, in levels of the gmap.
this.gmapname The name of the .gmap corresponding to the map image.
Hope some people find this useful and please give credit where it's due!
