Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 01/07/19 in all areas

  1. This feature allows you to clone maps ingame without having to reboot your server or do any changes client-side. The cloned maps will behave just like any other regular map, except players will not be able to save in them. If they log out, they will return to their spawn point. The commands: @clonemap source_map new_map @delmap new_map @clonemaplist This is useful if want to make an event on a map but there's an annoying NPC in the way (and you don't want to reboot your server just for that!). Another big upside being you don't need to send a patch for that either, the new map will be added 'live'. You can load scripts on these maps as well (they will be removed upon deleting the map). Usage example: @clonemap prontera newmap @addwarp newmap 150 150 test_portal (@unloadnpc test_portal) Have fun! These maps will be lost when rebooting the server. diff --git a/src/map/atcommand.c b/src/map/atcommand.c index d4b329c..25e4c8b 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -799,6 +799,11 @@ ACMD_FUNC(save) { nullpo_retr(-1, sd); + if( map[sd->bl.m].clone_id ) { + clif_displaymessage(fd, "You cannot create a savepoint in this map."); + return 1; + } + if( map[sd->bl.m].instance_id ) { clif_displaymessage(fd, msg_txt(sd,383)); // You cannot create a savepoint in an instance. return 1; @@ -5945,6 +5950,11 @@ ACMD_FUNC(autotrade) { return -1; } + if (map[sd->bl.m].clone_id) { + clif_displaymessage(fd, "You cannot use autotrade on cloned maps."); + return -1; + } + sd->state.autotrade = 1; if (battle_config.autotrade_monsterignore) sd->state.monster_ignore = 1; @@ -9937,6 +9947,111 @@ ACMD_FUNC(adopt) return -1; } +/** + * Clones an existing map without having to reboot your server. + * Usage: @clonemap <source_map_name> <new_map_name> + * @author Tokeiburu + */ +ACMD_FUNC(clonemap) +{ + int res; + char map_name_cur[MAP_NAME_LENGTH_EXT]; + char map_name_new[MAP_NAME_LENGTH_EXT]; + + memset(map_name_cur, '\0', sizeof(map_name_cur)); + memset(map_name_new, '\0', sizeof(map_name_new)); + + if (!message || !*message || sscanf(message, "%15s %15s", map_name_cur, map_name_new) < 2) { + clif_displaymessage(fd, "Usage: @clonemap <source_map_name> <new_map_name>"); + return -1; + } + + if (map_mapname2mapid(map_name_cur) < 0) { + sprintf(atcmd_output, "Source map not found: %s", map_name_cur); + clif_displaymessage(fd, atcmd_output); + return -1; + } + + if (map_mapname2mapid(map_name_new) >= 0) { // This will always show a warning in the console, but removing it is not worth the trouble. + sprintf(atcmd_output, "Destination map already exists: %s", map_name_new); + clif_displaymessage(fd, atcmd_output); + return -1; + } + + if ((res = map_addclonemap(map_name_cur, map_name_new)) < 0) { + sprintf(atcmd_output, "Failed to create a new map, error: %d", res); + clif_displaymessage(fd, atcmd_output); + return -1; + } + + sprintf(atcmd_output, "New map cloned (%s).", map_name_new); + clif_displaymessage(fd, atcmd_output); + return 0; +} + +/** + * Removes a cloned map. + * Usage: @delmap <map_name> + * @author Tokeiburu + */ +ACMD_FUNC(delmap) +{ + int res; + int m; + char map_name[MAP_NAME_LENGTH_EXT]; + + memset(map_name, '\0', sizeof(map_name)); + + if (!message || !*message || sscanf(message, "%15s", map_name) < 1) { + clif_displaymessage(fd, "Usage: @delmap <map_name>"); + return -1; + } + + if ((m = map_mapname2mapid(map_name)) < 0) { + sprintf(atcmd_output, "Map not found: %s", map_name); + clif_displaymessage(fd, atcmd_output); + return -1; + } + + if (map[m].clone_id == 0) { + clif_displaymessage(fd, "Only cloned maps can be removed."); + return -1; + } + + if ((res = map_delclonemap(map_name)) != 1) { + sprintf(atcmd_output, "Failed to remove map: %s", map_name); + clif_displaymessage(fd, atcmd_output); + return -1; + } + + sprintf(atcmd_output, "Cloned map removed (%s).", map_name); + clif_displaymessage(fd, atcmd_output); + return 0; +} + +/** + * Lists all cloned maps. + * Usage: @clonemaplist + * @author Tokeiburu + */ +ACMD_FUNC(clonemaplist) +{ + int i; + int count = 0; + + for (i = instance_start; i < MAX_MAP_PER_SERVER; i++) { + if (map[i].clone_id > 0) { + sprintf(atcmd_output, "%s (source: %s)", map[i].name, map[map[i].clone_id].name); + clif_displaymessage(fd, atcmd_output); + count++; + } + } + + sprintf(atcmd_output, "Found %d cloned map(s).", count); + clif_displaymessage(fd, atcmd_output); + return 0; +} + #include "../custom/atcommand.inc" /** @@ -10234,6 +10349,10 @@ void atcommand_basecommands(void) { ACMD_DEF(adopt), ACMD_DEF(agitstart3), ACMD_DEF(agitend3), + + ACMD_DEF(clonemap), + ACMD_DEF(delmap), + ACMD_DEF(clonemaplist), }; AtCommandInfo* atcommand; int i; diff --git a/src/map/chrif.c b/src/map/chrif.c index 4276434..cea689f 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -336,7 +336,7 @@ int chrif_save(struct map_session_data *sd, enum e_chrif_save_opt flag) { WFIFOB(char_fd,12) = (flag&CSAVE_QUIT) ? 1 : 0; //Flag to tell char-server this character is quitting. // If the user is on a instance map, we have to fake his current position - if( map[sd->bl.m].instance_id ){ + if( map[sd->bl.m].instance_id || map[sd->bl.m].clone_id ){ struct mmo_charstatus status; // Copy the whole status diff --git a/src/map/clif.c b/src/map/clif.c index 6c77044..97d8864 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -10352,7 +10352,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) #endif // Instances do not need their own channels - if( channel_config.map_enable && channel_config.map_autojoin && !map[sd->bl.m].flag.chmautojoin && !map[sd->bl.m].instance_id ) + if( channel_config.map_enable && channel_config.map_autojoin && !map[sd->bl.m].flag.chmautojoin && !map[sd->bl.m].instance_id && !map[sd->bl.m].clone_id ) channel_mjoin(sd); //join new map } else if (sd->guild && (battle_config.guild_notice_changemap == 2 || guild_notice)) clif_guild_notice(sd); // Displays at end diff --git a/src/map/map.c b/src/map/map.c index c7e326b..37d65f1 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -2095,7 +2095,7 @@ int map_quit(struct map_session_data *sd) { unit_remove_map_pc(sd,CLR_RESPAWN); - if( map[sd->bl.m].instance_id ) { // Avoid map conflicts and warnings on next login + if( map[sd->bl.m].instance_id || map[sd->bl.m].clone_id ) { // Avoid map conflicts and warnings on next login int16 m; struct point *pt; if( map[sd->bl.m].save.map ) @@ -2728,6 +2728,133 @@ int map_delinstancemap(int m) return 1; } +/*========================================== + * Add a cloned map + *------------------------------------------*/ +int map_addclonemap(const char *name, const char *newname) +{ + int src_m = map_mapname2mapid(name); + int dst_m = -1, i; + size_t num_cell, size; + + if(src_m < 0) + return -1; + + if(strlen(name) >= MAP_NAME_LENGTH) { + // against buffer overflow + ShowError("map_addclonemap: can't add long map name \"%s\"\n", name); + return -2; + } + + if(strlen(newname) >= MAP_NAME_LENGTH) { + // against buffer overflow + ShowError("map_addclonemap: can't add long map name \"%s\"\n", newname); + return -2; + } + + for(i = instance_start; i < MAX_MAP_PER_SERVER; i++) { + if(!map[i].name[0]) + break; + } + if(i < map_num) // Destination map value overwrites another + dst_m = i; + else if(i < MAX_MAP_PER_SERVER) // Destination map value increments to new map + dst_m = map_num++; + else { + // Out of bounds + ShowError("map_addclonemap failed. map_num(%d) > map_max(%d)\n",map_num, MAX_MAP_PER_SERVER); + return -3; + } + + if (map[src_m].clone_id) { + ShowError("map_addclonemap failed. Cannot clone a cloned map.\n",map_num, MAX_MAP_PER_SERVER); + return -4; + } + + // Copy the map + memcpy(&map[dst_m], &map[src_m], sizeof(struct map_data)); + + // Alter the name + // Due to this being custom we only worry about preserving as many characters as necessary for accurate map distinguishing + // This also allows us to maintain complete independence with main map functions + strncpy(map[dst_m].name,newname,MAP_NAME_LENGTH); + + map[dst_m].m = dst_m; + map[dst_m].clone_id = src_m; + map[dst_m].users = 0; + + memset(map[dst_m].npc, 0, sizeof(map[dst_m].npc)); + map[dst_m].npc_num = 0; + + // Reallocate cells + num_cell = map[dst_m].xs * map[dst_m].ys; + CREATE( map[dst_m].cell, struct mapcell, num_cell ); + memcpy( map[dst_m].cell, map[src_m].cell, num_cell * sizeof(struct mapcell) ); + + // Remove ontouch NPC cells + for (i = 0; i < num_cell; i++) { + map[dst_m].cell[i].npc = 0; + } + + // Remove all mob spawners (these should not be copied over) + for (i = 0; i < MAX_MOB_LIST_PER_MAP; i++) { + map[dst_m].moblist[i] = NULL; + } + + // Do not copy PVP nightmare drops + memset(map[dst_m].drop_list, 0, sizeof(map[dst_m].drop_list)); + + // Remove quest information from the map + map[dst_m].qi_data = NULL; + + size = map[dst_m].bxs * map[dst_m].bys * sizeof(struct block_list*); + map[dst_m].block = (struct block_list **)aCalloc(1,size); + map[dst_m].block_mob = (struct block_list **)aCalloc(1,size); + + map[dst_m].index = mapindex_addmap(-1, map[dst_m].name); + map[dst_m].channel = NULL; + map[dst_m].mob_delete_timer = INVALID_TIMER; + + map_addmap2db(&map[dst_m]); + + return dst_m; +} + +/*========================================== + * Deleting a cloned map + *------------------------------------------*/ +int map_delclonemap(const char* mapname) +{ + int m = map_mapname2mapid(mapname); + + if(m < 0 || map[m].instance_id || map[m].clone_id <= 0) + return 0; + + // Kick everyone out + map_foreachinmap(map_instancemap_leave, m, BL_PC); + + // Do the unit cleanup + map_foreachinmap(map_instancemap_clean, m, BL_ALL); + + if( map[m].mob_delete_timer != INVALID_TIMER ) + delete_timer(map[m].mob_delete_timer, map_removemobs_timer); + + // Free memory + aFree(map[m].cell); + map[m].cell = NULL; + aFree(map[m].block); + map[m].block = NULL; + aFree(map[m].block_mob); + map[m].block_mob = NULL; + map_free_questinfo(m); + + mapindex_removemap( map[m].index ); + map_removemapdb(&map[m]); + memset(&map[m], 0x00, sizeof(map[0])); + map[m].mob_delete_timer = INVALID_TIMER; + return 1; +} + /*========================================= * Dynamic Mobs [Wizputer] *-----------------------------------------*/ @@ -2838,6 +2965,10 @@ void map_removemobs(int16 m) *------------------------------------------*/ const char* map_mapid2mapname(int m) { + if (map[m].clone_id) { // Clone map check + return map[map[m].clone_id].name; + } + if (map[m].instance_id) { // Instance map check struct instance_data *im = &instance_data[map[m].instance_id]; diff --git a/src/map/map.h b/src/map/map.h index ec0b2b0..762ab2d 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -705,6 +705,9 @@ struct map_data { unsigned short instance_id; int instance_src_map; + // Clone map system + unsigned short clone_id; + /* rAthena Local Chat */ struct Channel *channel; @@ -820,6 +823,10 @@ int map_addflooritem(struct item *item, int amount, int16 m, int16 x, int16 y, i int map_addinstancemap(const char *name, unsigned short instance_id); int map_delinstancemap(int m); +// Clone map system +int map_delclonemap(const char* mapname); +int map_addclonemap(const char *name, const char *newname); + // player to map session void map_addnickdb(int charid, const char* nick); void map_delnickdb(int charid, const char* nick); diff --git a/src/map/pc.c b/src/map/pc.c index 66a42f4..07d395b 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -5599,6 +5599,11 @@ bool pc_memo(struct map_session_data* sd, int pos) pos = 0; } + if( map[sd->bl.m].clone_id ) { + clif_displaymessage( sd->fd, "You cannot create a memo in this map." ); + return false; + } + if( map[sd->bl.m].instance_id ) { clif_displaymessage( sd->fd, msg_txt(sd,384) ); // You cannot create a memo in an instance. return false; diff --git a/src/map/script.c b/src/map/script.c index f53b799..9f59068 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -9607,6 +9607,11 @@ BUILDIN_FUNC(savepoint) y = script_getnum(st,4); m = map_mapindex2mapid(map_idx); + if( map[m].clone_id ) { + ShowError("buildin_savepoint: You cannot create a savepoint on this map %s.\n", str); + return SCRIPT_CMD_FAILURE; + } + if (cid_pos == 7) { int dx = script_getnum(st,5), dy = script_getnum(st,6), x1 = x + dx, y1 = y + dy, clonemap.diff
    1 point
  2. View File TreeOfSavior Tombstone With Numbers MiniGame script header //===== rAthena Script ======================================= //= Tree Of Savior 'Tombstone With Numbers' //===== By: ================================================== //= Sader1992 //https://rathena.org/board/profile/30766-sader1992/ //https://github.com/sader1992/sader_scripts //= Email [email protected] //===== Compatible With: ===================================== //= rAthena Project //============================================================ //= Variables Info: //= 'COOLDOWN_TOMBSTONE_WITH_NUMBERS' the cool-down timer //============================================================ //= Description: //= This NPC is in a lot of tree of savior maps //= with deferent attempt number and deferent rage //= the rewards normally buff/items //= the NPC cool-down on winning is 20min and on losing is none //= if you want more than 1 copy from this NPC you need to use deferent variable for each NPC , or else they will share the same cool-down. //============================================================ Submitter sader1992 Submitted 01/06/2019 Category Games, Events, Quests Video Content Author sader1992  
    1 point
  3. Try use this https://github.com/zackdreaver/ROenglishRE/blob/master/Ragnarok/data/luafiles514/lua files/effecttool/prt_cas.lub
    1 point
  4. for what?? Just See this Post bro, follow step by step i told u to use search engine
    1 point
  5. Here... 31479,bloody_aura,bloody aura,4,5,0,10,,0,,0,0xFFFFFFFF,7,2,8192,,1,0,47,{},{},{} 31470,vwngeance_aura,vengeance aura,4,5,0,10,,0,,0,0xFFFFFFFF,7,2,8192,,1,0,48,{},{},{}
    1 point
  6. Maybe now? I read something about rids in unitattack. function script F_botex { set .@i,0; set .@rid,getcharid(3); while (.@i < 1) { set .@b,0; dispbottom .@i+""; .@rid = getcharid(3); getmapxy(.@m$,.@x0,.@y0,0); sleep2 100; .@x = rand(-13,13)+.@x0; .@y = rand(-13,13)+.@y0; sleep2 100; if(!checkcell( .@m$,.@x,.@y,cell_chkpass )){ dispbottom "Coordinate not exists!"; continue; } else if(checkcell( .@m$,.@x,.@y,cell_chkpass )){ dispbottom "Coordinate exists!"; } sleep2 100; while(.@x0 != .@x && .@y0 != .@y) { set .@b,.@b+1; viewpoint 1,.@x,.@y,1,0xFF0000; dispbottom "auto walking to x = "+.@x+" y = "+.@y; unitwalk getcharid(3),.@x,.@y,strnpcinfo(3)+"::OnReach"; sleep2 2000; if(.@b > 5) break; getmapxy(.@m$,.@x0,.@y0,0); sleep2 100; } .@n = getareaunits(BL_MOB,.@m$,.@x0 + 5,.@y0 + 5,.@x0 - 5,.@y0 - 5,.@mob); detachrid; unitattack .@rid,.@mob[rand(.@n)],true; attachrid .@rid; percentheal 100,100; sleep2 100; dispbottom "JackJack"; } end; }
    1 point
  7. function script random_walk { @walking = !@walking; if(@walking) { while(@walking) { getmapxy .@m$,.@x,.@y,UNITTYPE_PC; getfreecell .@m$,.@to_x,.@to_y,.@x,.@y,10,10; unitwalk getcharid(3),.@to_x,.@to_y; while(.@x != .@to_x || .@y != .@to_y) { sleep2 500; getmapxy .@m$,.@x,.@y,UNITTYPE_PC; } } } return; } function script F_botex { set .@i,0; while (.@i < 1) { set .@b,0; dispbottom .@i+""; .@rid = getcharid(3); getmapxy(.@m$,.@x0,.@y0,0); sleep2 100; .@x = rand(-13,13)+.@x0; .@y = rand(-13,13)+.@y0; sleep2 100; if(!checkcell( .@m$,.@x,.@y,cell_chkpass )){ dispbottom "Coordinate not exists!"; continue; } else if(checkcell( .@m$,.@x,.@y,cell_chkpass )){ dispbottom "Coordinate exists!"; } sleep2 100; while(.@x0 != .@x && .@y0 != .@y) { set .@b,.@b+1; viewpoint 1,.@x,.@y,1,0xFF0000; dispbottom "auto walking to x = "+.@x+" y = "+.@y; unitwalk getcharid(3),.@x,.@y,strnpcinfo(3)+"::OnReach"; sleep2 2000; if(.@b > 5) break; getmapxy(.@m$,.@x0,.@y0,0); sleep2 100; } .@n = getareaunits(BL_MOB,.@m$,.@x0 + 5,.@y0 + 5,.@x0 - 5,.@y0 - 5,.@mob); unitattack 0,.@mob[rand(.@n)],true; percentheal 100,100; sleep2 100; dispbottom "JackJack"; } end; }
    1 point
  8. Version 1.0.0

    1113 downloads

    This is a sky city made by me long time ago. You can contact me in Skype by adding me at keough_99 Feel free to use my maps!!
    Free
    1 point
  9. Version 1.0.0

    1522 downloads

    I'm releasing this mall map for free! Feel free to message for support add me in skype: keough_99
    Free
    1 point
  10. Version 1.0.0

    1324 downloads

    I'm releasing this map for free! Enjoy! Spread love! Contact me in Skype: keough_99
    Free
    1 point
  11. Version 1.0.0

    614 downloads

    This map is my first one of a new concept I tried by an Idea I had with a RO map long ago. I call this a Panoramic Map and I think you will notice it right away. I added space on this map, but by some camera angles edit and there, and doing some work with textures... I could add the effect of a far distance space area, that I hope you will enjoy. I recommend this map to be used only for small same matches of 1 vs 1, or 5 vs 5. Use it on your server for pvp tournaments, as a final stage. Or use it for a small GvG team tournament 2 teams of 5 or 7 users per each. Don't waste this map for a common pvp arena, be smart with your server and add it as a plus as a final stage of a tournament for example.
    Free
    1 point
  12. Version 1.0.0

    620 downloads

    You may need new Prontera & Lasagna staff to use this map Includes mini-map & soundtrack from video
    Free
    1 point
  13. Version 1.0.0

    1618 downloads

    Hey there everyone, long time no see! So it's been a very long time since I have been on these boards and I do miss it all. Feeling a little nostalgia looking through these all, I decided to release them all to the public, completely free. Going in no particular order after the first few, they are just my favorites. I hope you guys love them as I have. Sanctum Main town oriented map. My absolute favorite and latest work (When I was mapping). The idea I had for this was a chuck of a mountain broke off and landed here, subsequently creating a waterfall from atop and surrounding the town. Giving it protection and a perfect center for life. I never got around to finishing the outside of the map, I don't even know what I thought for the surroundings, perhaps just trees. Sanctum In And here is the inside map for Sanctum. The first picture is the general area where various NPC's can be placed. The second picture is where I planned to use an script to automatically place anyone who wished to vend in the one walkable/edited Gat. It would cycle through and remove those vending for a prolonged period of time and also anyone not vending at all. Guild Base This map was designed for the top guilds or just those who hold castles to have a domain of their own. The first picture is just a hangout spot for anyone in the guild. The second picture is for any combat/training/monster summoning to be done. The third picture is for the guild master where special NPC's can be placed as the server owners desire.  Novice Starter Grounds PvP Valkyrie A little small for a PvP map but I enjoyed making it and like how it turned out. Trinity The first main town I made some time back around 2010. Don't judge me on some of the rookie mistakes I made with lighting and such haha. The following Trinity ___ maps are connected via a warp on the edges of the map. Trinity In Trinity Courtyard Before the Sanctum maps, this was my favorite creation. I just liked the feel of this one. Trinity Vending Similar to the Sanctum In vending idea, I wanted to limit vending to only those tiles with the colored objects on it. Trinity Port Anexus A simple instance based map with a boss at the end. Another one of my earlier works. Works The beginnings of my templates map. I would urge any current mapper to use this technique to create unique model compilations and copy it over to the map in progress. I have used this to create a forest that looks completely customized in a matter of minutes. Well there they are, open to any and all. I hope to hear your feedback on these! Thanks, Truly ~
    Free
    1 point
  14. Version 1.0

    736 downloads

    This mapping project was created by myself and Olrox. For complete background information of this project please see this thread here. Once you download and use this package you agree to the following terms: YOU cannot claim our work as yours YOU are NOT permitted to use this work for commercial purposes YOU can edit the maps as you wish but credit must always be due to the original creators (myself and Olrox) Enjoy the maps, and I hope this expansion adds a little more fun to Lutie~ Don't forget to give Olrox a +1 for his hard work! More rep to him
    Free
    1 point
  15. Version 1.0

    1112 downloads

    The city of Atlantis. This town consists of the following areas and features: 1. Baron Square For all of you LoL (League of Legends) players out there, I've imported the Christmas Version of Baron as the central piece of attraction in the square of Atlantis City. Baron is worshiped and governs the city. 2. Atlantis Palace Atlantis comes equipped with a royal palace which houses the elite that controls the city such as the queen, king, and other royal members. It is located directly North of Atlantis positioned in the middle-top of the map. 3. Court Yard Flower Meadow Directly South of Atlantis is a small courtyard containing several underwater plants and flowers to serve as a great place to socialize or house NPCs. 4. Houses There are several buildings West of Atlantis. They are there to serve as a local inn, tool shop, weapon/armor shop, magic shop, etc. 5. Exit Points Atlantis has several exit areas. The exit West of the City was originally designed to connect to an underwater field. You can use this for w/e you want. The exit located at the very bottom right of the map (South-East) shows a cave entrance. You can use this to connect to an underground pathway to some destination or w/e you want. Finally, there is an exit at the middle-right of the city. You will notice there is a nice flowery pathway leading towards it complete with statues and pillars. This can be used to connect to a sacred area or anything else you can come up with. 6. Waterfall Enclosure The entire city is surrounded by waterfalls producing the idea that the water is being controlled, preventing it from drowning the city. Whats controlling the water are specific pillars at different corners around the map which have magic powers of some sort.. The package provided is already packed as a GRF and ready to be added to your server. You will notice that I attached the .EXTRA file to the GRF. With this file you will be able to have a mapper edit the map without losing the currently assigned lightmaps. Therefore, feel free to edit the map but credits are still owed to me.
    Free
    1 point
  16. Version 1.1

    3069 downloads

    The Haunted House! Includes both an entrance map and interior map. Whether it be a Halloween themed event dungeon or just a fun house to play in, feel free to use these maps for all of your scary adventures!
    Free
    1 point
  17. Version 1.0

    664 downloads

    This is a map created by Kenedos. Information regarding his map is explained below. All of the descriptions are written by him.
    Free
    1 point
×
×
  • Create New...