Jump to content

Tokei

Members
  • Posts

    591
  • Joined

  • Last visited

  • Days Won

    74

Everything posted by Tokei

  1. Well, the file air_evt is probably encrypted, so you can't make it into a flat map. As for the cities, well, the files may be in another GRF which takes priority over your data.grf. I would presume they are in whateverRO.grf. Either way, it'd be easier to make yourself a new grf, like maps.grf and then put it as the highest priority possible in your data.ini.
  2. Well, same way you're patching your iteminfo. If you're using GRF Editor to make your thor files, then drop the files in "root":
  3. Heya, Did you check if the char-server has loaded properly first? The map-server will not connect to the char-server unless the char-server is loaded, so you might want to check that. It should be saying "Awaiting maps from map-server." For inter-server connections, you should also use the localhost IP (127.0.0.1). This goes for map-server to char-server and char-server to login-server. Regardless of your server being public or not, inter-server connections should remain in a "closed" system. But ultimately, since you're using your private IP to connect right now, it would seem to indicate there is also a problem with your port configuration. So make sure port 6121 is forwarded to 192.168.1.14 in your router configuration. Note that this step is only required if you plan to make your server public. You should make sure that the server can run locally first using the localhost IP.
  4. Heya, These script commands are an alternative for those who do not want to use yaml for making barter shops. The shops can be reloaded by reloading the script, using the barter_clear command. The NPC location is defined just like a regular NPC and then using callshop <npc barter name>, just like regular shop types (which is already possible without this diff, but I thought I'd mention it anyway). Removes all items from a barter shop barter_clear <npc name>; Add item, not extended barter_add <npc name>,<item id>,<amount>,<req item id>,<req amount>; Add item, extended barter_add_ex <npc name>,<item id>,<amount>,<zeny>{,<req item id>,<req amount>,<req refine>}*; Here's a script example: prontera,150,188,0 script Barter NPC 77,{ mes "[Barter NPC]"; next; switch(select("Normal barter shop.:Extended barter shop.:")) { case 1: mes "[Barter NPC]"; mes "..."; close2; callshop "barter_test_npc"; end; case 2: mes "[Barter NPC]"; mes "..."; close2; callshop "barter_test_npc_ex"; end; } end; OnInit: barter_clear "barter_test_npc"; barter_add "barter_test_npc", 504, 10, 501, 20; barter_add "barter_test_npc", 504, 10, 502, 10; barter_add "barter_test_npc", "White_Potion", 10, "Yellow_Potion", 3; barter_clear "barter_test_npc_ex"; barter_add_ex "barter_test_npc_ex", "Zeny_Knife", 5, 5000, "Knife", 1, 9; barter_add_ex "barter_test_npc_ex", "Zeny_Knife", 5, 5000, "Knife", 1, 9, "White_Potion", 10, 0; barter_add_ex "barter_test_npc_ex", "Zeny_Knife", 5, 5000, "Knife", 1, 9, "White_Potion", 10, 0, "White_Potion", 10, 0; end; } prontera,152,188,0 script Barter NPC2 77,{ callshop "barter_test_npc"; end; } And here's the diff file: diff --git a/src/map/npc.cpp b/src/map/npc.cpp index d227467ed..37f50d94d 100644 --- a/src/map/npc.cpp +++ b/src/map/npc.cpp @@ -842,6 +842,26 @@ void BarterDatabase::loadingFinished(){ BarterDatabase barter_db; +struct npc_data* npc_create_dummy_barter_npc(const char *npcname) { + struct npc_data* nd = npc_create_npc(-1, 0, 0); + + npc_parsename(nd, npcname, nullptr, nullptr, __FILE__ ":" QUOTE(__LINE__)); + + nd->class_ = -1; + nd->speed = 200; + + nd->bl.type = BL_NPC; + nd->subtype = NPCTYPE_BARTER; + + nd->u.barter.extended = false; + + map_addiddb(&nd->bl); + + strdb_put(npcname_db, npcname, nd); + + return nd; +} + /** * Returns the viewdata for normal NPC classes. * @param class_: NPC class ID diff --git a/src/map/npc.hpp b/src/map/npc.hpp index 0a0c104e6..82ad2cf3d 100644 --- a/src/map/npc.hpp +++ b/src/map/npc.hpp @@ -1479,6 +1479,8 @@ enum e_npcv_status : uint8 { NPCVIEW_INVISIBLE = 0x29, NPCVIEW_CLOAK = 0x30, }; + +struct npc_data* npc_create_dummy_barter_npc(const char* npcname); struct view_data* npc_get_viewdata(int class_); int npc_chat_sub(struct block_list* bl, va_list ap); int npc_event_dequeue(map_session_data* sd,bool free_script_stack=true); diff --git a/src/map/script.cpp b/src/map/script.cpp index 5aeebe228..6742ab8c4 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -26916,6 +26916,154 @@ BUILDIN_FUNC(preg_match) { #endif } +/*========================================== + * Removes all items from a barter shop + * barter_clear <npc name>; + *------------------------------------------*/ +BUILDIN_FUNC(barter_clear) +{ + const char* npcname = script_getstr(st, 2); + std::shared_ptr<s_npc_barter> barter = barter_db.find(npcname); + + if (barter != nullptr) { + barter->items.clear(); + } + + return SCRIPT_CMD_SUCCESS; +} + +/*========================================== + * Add an item to the barter shop + * Not extended: + * barter_add <npc name>,<item id>,<amount>,<req item id>,<req amount>; + * + * Extended: + * barter_add_ex <npc name>,<item id>,<amount>,<zeny>{,<req item id>,<req amount>,<req refine>}*; + *------------------------------------------*/ +BUILDIN_FUNC(barter_add) +{ + const char* npcname = script_getstr(st, 2); + std::shared_ptr<s_npc_barter> barter = barter_db.find(npcname); + struct npc_data* nd = npc_name2id(npcname); + const char* command = script_getfuncname(st); + + if (barter == nullptr) { + barter = std::make_shared<s_npc_barter>(); + barter->name = npcname; + barter_db.put(npcname, barter); + } + + if (nd == nullptr) { + nd = npc_create_dummy_barter_npc(npcname); + } + + int index = barter->items.size(); + + std::shared_ptr<s_npc_barter_item> item = std::make_shared<s_npc_barter_item>(); + item->index = index; + barter->items[index] = item; + + if (strcmpi(command, "barter_add_ex") == 0) { + nd->u.barter.extended = true; + + if (script_isstring(st, 3)) { + const char* name = script_getstr(st, 3); + + std::shared_ptr<item_data> id = item_db.searchname(name); + + if (id == nullptr) { + ShowError("buildin_barter_add: Nonexistant item %s\n", name); + return SCRIPT_CMD_FAILURE; + } + + item->nameid = id->nameid; + } + else { + item->nameid = script_getnum(st, 3); + } + + item->stock = script_getnum(st, 4); + item->stockLimited = false; + item->price = script_getnum(st, 5); + + int offset = 6; + + while (script_hasdata(st, offset) && script_hasdata(st, offset + 1) && script_hasdata(st, offset + 2)) { + std::shared_ptr<s_npc_barter_requirement> requirement = std::make_shared<s_npc_barter_requirement>(); + + requirement->index = (uint16)item->requirements.size(); + + if (script_isstring(st, offset)) { + const char* name = script_getstr(st, offset); + + std::shared_ptr<item_data> id = item_db.searchname(name); + + if (id == nullptr) { + ShowError("buildin_barter_add: Nonexistant item %s\n", name); + return SCRIPT_CMD_FAILURE; + } + + requirement->nameid = id->nameid; + } + else { + requirement->nameid = script_getnum(st, offset); + } + + requirement->amount = script_getnum(st, offset + 1); + requirement->refine = script_getnum(st, offset + 2); + item->requirements[requirement->index] = requirement; + offset += 3; + } + } + else { + nd->u.barter.extended = false; + + if (script_isstring(st, 3)) { + const char* name = script_getstr(st, 3); + + std::shared_ptr<item_data> id = item_db.searchname(name); + + if (id == nullptr) { + ShowError("buildin_barter_add: Nonexistant item %s\n", name); + return SCRIPT_CMD_FAILURE; + } + + item->nameid = id->nameid; + } + else { + item->nameid = script_getnum(st, 3); + } + + item->stock = script_getnum(st, 4); + item->stockLimited = false; + + std::shared_ptr<s_npc_barter_requirement> requirement = std::make_shared<s_npc_barter_requirement>(); + + requirement->index = 0; + + if (script_isstring(st, 5)) { + const char* name = script_getstr(st, 5); + + std::shared_ptr<item_data> id = item_db.searchname(name); + + if (id == nullptr) { + ShowError("buildin_barter_add: Nonexistant item %s\n", name); + return SCRIPT_CMD_FAILURE; + } + + requirement->nameid = id->nameid; + } + else { + requirement->nameid = script_getnum(st, 5); + } + + requirement->amount = script_getnum(st, 6); + item->requirements[0] = requirement; + } + + return SCRIPT_CMD_SUCCESS; +} + /// script command definitions /// for an explanation on args, see add_buildin_func struct script_function buildin_func[] = { @@ -27623,6 +27771,10 @@ struct script_function buildin_func[] = { BUILDIN_DEF(isdead, "?"), BUILDIN_DEF(macro_detector, "?"), + BUILDIN_DEF(barter_clear, "s"), + BUILDIN_DEF(barter_add, "svi*"), + BUILDIN_DEF2(barter_add, "barter_add_ex", "svii*"), + #include "../custom/script_def.inc" {NULL,NULL,NULL}, Quick notes: There isn't a whole lot of error handling. Do... not use an existing NPC name for the barter name if you don't want to crash, but otherwise, should be fine! There is no handling for stocks. You can add parameters to it in the script command if you feel like it, but I've personally never used this option so I just didn't add it. barter.diff
  5. Take a look at System\OngoingQuestInfoList_True.lub (or Sakray.lub, depending of your client version), for example: [7858] = { Title = "불온한 소리의 정체 조사", IconName = "ico_ep.bmp", Description = { "리벨리온 대원 일부는 격벽 너머에서 들려오는 소리의 정체를 밝히기 위해 이미 움직였다. 루키는 소리의 근원이 괴물이라면 멋지게 해치워 달라고 했다." }, Summary = "괴물 사냥", RewardEXP = "800000", RewardJEXP = "800000", RewardItemList = { { ItemID = 25723, ItemNum = 15 } } },
  6. Make sure you are at the latest version: 1.8.4.6 (link in the download description page). Well, that means it found no *.gat files in your currently opened GRF. You're not showing what's in there, so I don't know.
  7. This script is... way more complicated than it has to be. The rand function is misused in two different places, which I'm guessing is the main problem you're having. First thing first: [email protected] > rand( 1, 1000 ) ^ that's a big no-no. Randomized numbers for chances are always from [0-999], not [1-1000]. You then use rand(1000); or rand(0, 999), but the former is preferred for various reasons. Also, normally you put the rand first for clarity's sake, but that one is preference: if (rand(1000) < [email protected]) Declaring functions at the beginning is fine, but it's also unecessary and not used that much anymore. Use callsub instead, though... using local scope functions for this script is overkill. rAthena scripts prefer the no-space syntax for function arguments, but that one is up to you. As for the main problem you're having, that is because [email protected] is returning negative values because of rand( 1, getd( ".size_tot_"+ getarg(0) ) ) has invalid bounds and... well, because this is overly complicated so it's not really worth spending time deciphering what it does. I suggest a simpler approach: prontera,155,177,5 script random 615,{ if (countitem(.rare_ticket)) { mes "Rare Ticket"; [email protected] = .rate_chance_rare; // chance [email protected] = .rare_ticket; } else if (countitem(.normal_ticket)) { mes "Normal Ticket"; [email protected] = .rate_chance_normal; // chance [email protected] = .normal_ticket; } else { mes "random"; close; } switch(select("Go.:No.:")) { case 2: close; } delitem [email protected], 1; if (rand(1000) < [email protected]) { mes "random"; getitem .rare[rand(.rare_size)], 1; close; } else { mes "random"; getitem .normal[rand(.normal_size)], 1; close; } end; OnInit: .normal_ticket = 501; .rare_ticket = 502; .rate_chance_rare = 500; // chance to get a rare costume with rare ticket (500 = 50%) .rate_chance_normal = 100; // chance to get a rare costume with normal ticket (100 = 10%) // rare items setarray .rare,5909,5912,5914,5915,5977,5979,5980,15280,15841,15843,15858; .rare_size = getarraysize(.rare); // normal items setarray .normal,50001; .normal_size = getarraysize(.normal); end; }
  8. The lub files are irrelevant, just don't remove/modify/replace them.
  9. The separator used for menus is the colon, ":". So just change "%" to "%:". Though, this line: [email protected] = [email protected][select([email protected]$)]; doesn't make a whole lot of sense. Keep in mind that select returns the first value as 1 instead of 0, so you have to remove 1. What you probably wanted to write was the following. [email protected] = select([email protected]$) - 1; [email protected] = [email protected][[email protected]]; Also, not... an issue, but you'd probably want to change your variable names a bit by adding an 's' to your arrays otherwise it becomes very messy (and addding [0] is redundant). copyarray [email protected], [email protected]_item, [email protected]; Also, might as well use sprintf for your drop rates, it makes your life easier. So something like this: mes "Monster ID: "+getmonsterinfo([email protected]_id,MOB_NAME)+"'"; if (getmobdrops([email protected]_id)) { // 'getmobdrops' returns 1 on success // immediately copy global temporary variables into scope variables, // since we don't know when 'getmobdrops' will get called again for // another mob, overwriting your global temporary variables [email protected] = [email protected]_count; copyarray [email protected], [email protected]_item, [email protected]; copyarray [email protected], [email protected]_rate, [email protected]; mes getmonsterinfo([email protected]_id,MOB_NAME) + " - " + [email protected] + " drops found:"; for ([email protected] = 0; [email protected] < [email protected]; [email protected]++) { [email protected]$ = [email protected]$ + sprintf("%d (%s) %d.%02d%%", [email protected][[email protected]], getitemname([email protected][[email protected]]), [email protected][[email protected]] / 100, [email protected][[email protected]] % 100) + ":"; } [email protected]$ = [email protected]$ + ":"; } else { mes "Unknown monster ID."; } [email protected] = select([email protected]$) - 1; [email protected] = [email protected][[email protected]]; [email protected] = [email protected][[email protected]];
  10. Hmm, well I was able to make it into a flat map without any issues? Make sure you are using the latest version in the description.
  11. That usually means you're missing a VC++ library, though I don't remember which one it was compiled on. I'm guessing it's most likely VC++ 2010 (maybe 2008 as well). I'm guessing you picked x64 instead of x86 though.
  12. Heya, Unfortunately, that is not really possible. The gif format doesn't support semi-transparency. One pixel color can be transparent (which is commonly the pink color in RO, or 0xff00ff). While... this is possible to support, it would also make any other semi-transparent pixel look horrible with shades of pink for any of your other semi-transparent layers (I'd show you an example, but I'm on phone right now). It's a limitation of the gif format, there's not much I can do there. That's why I didn't really bother with transparency support while saving gif images and instead opted of rendering the str as they are directly shown in the preview window. I would suggest simply changing the background to black to make these gifs as this is when you'll have the best output. Alternatively, you could change the background color to wherever you plan on displaying these gifs, but you'll quickly see white background isn't a great choice for most str. Saving those animations is just really troublesome. The only real "solution" I could come up with is saving the output as a series of PNG images (which I'm not sure is actually possible, but worth looking into). Though, that wouldn't really solve what you're trying to do, at least I don't think...?
  13. Heya, You can create a new script command: static int buildin_killmonsterarea_sub(struct block_list *bl,va_list ap) { int x1 = va_arg(ap, int); int y1 = va_arg(ap, int); int x2 = va_arg(ap, int); int y2 = va_arg(ap, int); if (x1 <= bl->x && bl->x <= x2 && y2 <= bl->y && bl->y <= y1) status_kill(bl); return 0; } BUILDIN_FUNC(killmonsterarea) { const char *mapname; int16 m; int x1, x2, y1, y2; mapname=script_getstr(st,2); if( (m = map_mapname2mapid(mapname))<0 ) return 0; x1=script_getnum(st,3); y1=script_getnum(st,4); x2=script_getnum(st,5); y2=script_getnum(st,6); map_foreachinmap(buildin_killmonsterarea_sub,m,BL_MOB, x1, y1, x2, y2); return SCRIPT_CMD_SUCCESS; } // def BUILDIN_DEF(killmonsterarea,"siiii"),
  14. GRF encryption isn't restricted by client version. It works on any.
  15. I am not able to reproduce this issue. Str files do not have a bias value to begin with though, that's emulated. If the bias value isn't showing up, it could be that it simply failed to guess the value properly. Either way, I would need an example (with a file if possible) on how to reproduce. As for the second part, at 0x10c, the value should indeed be 0x00000000. That is the delay for texture animation. That value, "0x7f800000", means "Infinifty" which is usually the result of a division by 0. That's... a bug with the original str file. I saw it in your EZV file and I fixed the output to say "0" instead as it didn't make any sense to save the value as "Infinity" in a EZV file. As for the str file itself, it has no impact since the animation type is set to normal, and therefore the value isn't read at all. I will make a small change however and make sure this value (infinity) can't propagate anywhere either and fix it when loading the str file instead. I'll wait for more information on the bias issue above though.
  16. Heya, I see what you mean now; it should be fixed in 1.0.7.
  17. Well, as the error says: the file is empty (0 byte).
  18. Hmm, I'm not able to reproduce your issue. Saving as ezv works fine on my end. I have uploaded a newer version (1.0.6) to save ezv as 0.95 instead of 0.94 to support tga images. But that doesn't appear to be related to your issue at all, so you'd have to give me a way to reproduce the problem.
  19. Updated to 1.8.4.5: Fixed a bunch of issues with the dark theme. Fixed focussing in the tree view. Added Str preview support. Added support for RSW version 0x206. Fixed another packed DLL issue regarding GRF encryption. Extracting resources will now export all files. Added more checks when saving GRFs beyond 4 GB. I've added a "fix" for this issue, but like I said last time, it isn't an issue. GRF Editor will now prevent you from saving files past 4 GB of size. If your GRFs are reaching that size, you will need to use another GRF alongside for your client. There are no other solutions. Should be fixed now.
  20. Heya, Sorry about this! I have re-uploaded with the same link as above. It appears one of the library didn't compress properly when packing the executable.
  21. Updated to 1.8.4.3 : Added support for json and bson file formats (you can save as a bson file after editing). Only common types are supported. Fixed a bug with the lub decompiler regarding non-latin strings not being enclosed properly.
  22. It's failing to save the file because you have the file opened in GRF Editor already. You can't write/modify a file that's being used by another program. So as the error says, the file is locked.
  23. The client can read up to uint32, so ~4GB. But you are indeed correct, GRF Editor shouldn't allow more than that either for obvious reasons. Though the check put in place for size limit is obviously not working, so I'd have to fix that.
×
×
  • Create New...