Jump to content


  • Content Count

  • Avg. Content Per Day

  • Joined

  • Last visited

  • Days Won


Tokei last won the day on July 12

Tokei had the most liked content!

Community Reputation

476 Excellent

About Tokei

  • Rank

Profile Information

  • Gender
  • Location

Recent Profile Visitors

16,446 profile views
  1. It will affect your server load, yes. You would need to add a restriction in the source such as: if (src && src->type == BL_PC && bl->type == BL_MOB && damage > 0) { struct mob_data *md = (struct mob_data *)bl; if (md->id == 1002) { mapreg_setreg(reference_uid(add_str("[email protected]_mid"), 0), md->id); mapreg_setreg(reference_uid(add_str("[email protected]_gid"), 0), md->bl.id); npc_event_do_id("MyNPC::OnEvent", src->id); } } That on its own would be more reasonable, but if you have... I don't know, 10 people attacking the mob with 193 aspd, I'd be concerned. You'd probably want to do it all in the source instead, or at the very least put the chance of drop in the source. Something like... if (src && src->type == BL_PC && bl->type == BL_MOB && damage > 0) { struct mob_data *md = (struct mob_data *)bl; struct map_session_data *sd = (struct map_session_data *)src; if (md->id == 1002 && (rnd() % 100) < 5) { // 5% chance struct item it; t_itemid nameid = 501; int flag; memset(&it,0,sizeof(it)); it.nameid = nameid; it.identify = 1; it.bound = BOUND_NONE; // Assuming it is not a pet egg, you can skip some checks. Up to you at this point. if ((flag = pc_additem(sd, &it, 1, LOG_TYPE_SCRIPT))) { clif_additem(sd, 0, 0, flag); } } }
  2. Personally though, I'd say you should make a yaml conf file where you define drop groups with a chance, then assign a mob to a drop group in your mob_db.yml file instead. It's more work, but it's also much more effecient than running a script. Then again, that requires more source knowledge I suppose.
  3. You'd still need to modify your source to do that. You can be more restrictive as well and attach more "parameters". killerid won't work as it isn't added to the script yet. So something like... if (src && src->type == BL_PC && bl->type == BL_MOB && damage > 0) { struct mob_data *md = (struct mob_data *)bl; mapreg_setreg(reference_uid(add_str("[email protected]_mid"), 0), md->id); mapreg_setreg(reference_uid(add_str("[email protected]_gid"), 0), md->bl.id); npc_event_do_id("MyNPC::OnEvent", src->id); } OnEvent: switch([email protected]_mid) { case 1002: if (rand(100) < 5) { getitem 501, 1; } break; } end;
  4. It's possible, but it's also... very intensive for your server and I would highly recommend against it. In battle.cpp, in battle_calc_damage, add the NPC call: if (bl->type == BL_PC) { npc_event_do_id("MyNPC::OnEvent", bl->id); } And with the matching script: - script MyNPC -1,{ end; OnEvent: //callfunc("F_Function"); dispbottom "You have attacked."; end; } It would be much better to add code in the source for what you want to do instead.
  5. I loaded the maps you provided and there are no objects. So nothing to do with GRF Editor, but an issue with your local files or your client.
  6. Heya, You would have to share the map files you're trying to modify as there should be no issues with the settings you've picked.
  7. Well, the question is hard to answer because there is nothing wrong with the script. The announcements are clearly wrong, and it doesn't account for server reboots where the rates would be reset to Friday's rates, but besides that... it works as you'd expect. What issue do you have in particular?
  8. The job sprite does not get smaller. Neither in-game nor in Act Editor. The wing size has gotten smaller, though.
  9. Have you tried using Magnify (with anchor points)? If that's not what you're looking for, you'll have to use math to do what you want. Act files only use 1 anchor per frame.
  10. Well you can get the full command used with something like: OnNavigate: [email protected]$ = implode([email protected]_parameters$, " "); if (isloggedin(getcharid(3, [email protected]$)) != 1) { message strcharinfo(0), "Target player '" + [email protected]$ + "' is offline or do not exist."; } sleep2 1; unitwalkto getcharid(3), getcharid(3, [email protected]$); end; Though, unitwalkto is very limited and will most likely fail in most scenarios.
  11. Use 0.5 to reduce the size by half. It's a decimal value that has no range limit; you can use -0.5 if you wanted to reduce by half and inverse the image too.
  12. Well, they are misaligned in the RSW file because RSM models are centered using a bounding box, while RSM2 are not centered by their bounding box. So to align them within the RSW file, you need to calculate the difference between the two. Calculate the bounding box for the RSM2 file, calculate the offset between the center of it with the location in the RSW. Calculate the bounding box for the RSM file, add the previous offset to the RSW file to re-align the model­. But technically speaking, the converted RSM model is working as intended.
  13. Heya, Have you tried Scripts > Magnify?
  14. Heya, I just wanted to add there that this is actually incorrect (unless there was a major update on rAthena I'm not aware of). The script engine does not allocate memory for the 0 to 4000 values in your example. Technically speaking, arrays are emulated and not actually arrays in the source. When you use ".array[4001]", the engine does the following: ".array" is a string that gets indexed. The string is given a unique number, say 9048. From then on, everytime the string ".array" is used, it will be refered to as 9048. This is called the id. 4001 is the index. uid (id and index): Both of the values above combined as one (32bit for the id, 32bit for the index, making up 64bit for the uid). The uid with its value is then stored in a big collection for the whole NPC script. This big collection also contains the values of other non-array variables such as ".temp = 20;". They are all stored in the same place. If you had written the variable as ".array_4001", it would have created a new unique value for the string such as 9049 and the index would have been 0. As you need to index the string everytime you create a new variable, using setd with a big amount of variables is usually not a good practice. Using .array[4001] is handled better source wise. Quick note, but this is also why [email protected] = 5 is identical to [email protected][0] = 5 and both would return the same value. They have the same uid. What rAthena also does when you use an index greater than 0 is that it starts keeping track of the array keys (members). So say you used .array[4001], it will keep track that 4001 is a member of the array for the .array variable. As for getarraysize(), it should be used very carefully and never in the condition of the for loop. getarraysize() does the following: Checks if the .array value exists in the big collection. If not, adds 0 as a member of the array. (This is more of a hack, as it's impossible to know otherwise if [0] is part of the array or not.) Go through all the members of the array and find the highest key, then does + 1. So in your case, using getarraysize(.array) would indeed return 4002 as 4001 is the only member of the array. Using arrays instead of getd/setd would be much faster (and cleaner) in your script sample as a result: prontera,155,181,5 script Card Buyer 757,{ mes "["+strnpcinfo(1)+"]"; mes "You have any card to sell ? <3"; next; getinventorylist; for ([email protected] = 0; [email protected] < @inventorylist_count; [email protected]++) { [email protected] = .card[@inventorylist_id[[email protected]]]; if ([email protected]) [email protected]$ = [email protected]$ + getitemname(@inventorylist_id[[email protected]]) + " ^FF0000"+F_InsertComma([email protected])+" Zeny^000000"; [email protected]$ = [email protected]$ + ":"; } [email protected] = select([email protected]$) - 1; clear; [email protected] = .card[@inventorylist_id[[email protected]]]; mes "["+strnpcinfo(1)+"]"; mes "Sell "+getitemname(@inventorylist_id[[email protected]])+" for ^FF0000"+F_InsertComma([email protected])+" Zeny^000000?"; if (select("Confirm", "Cancel") == 1) { delitem @inventorylist_id[[email protected]], 1; Zeny += [email protected]; clear; mes "["+strnpcinfo(1)+"]"; mes "You have sold "+getitemname(@inventorylist_id[[email protected]])+" for ^FF0000"+F_InsertComma([email protected])+" Zeny^000000."; } close; function AddCard { [email protected] = getarg(0, 0); [email protected] = getargcount(); for ([email protected] = 1; [email protected] <= [email protected]; [email protected]++) .card[getarg([email protected], 0)] = [email protected]; return; } OnInit: // AddCard( <zeny>, <card_id>...); AddCard( 10000, 4001, 4002, 4003, 4004); AddCard(100000, 4011, 4012, 4013, 4014); AddCard(500000, 4021, 4022, 4023, 4024, 4025); AddCard(999999, 4031, 4032, 4033, 4034, 4035, 4036); end; } Edit: This of course doesn't hold true if you would start iterating through the whole array with for ([email protected] = 0; [email protected] < getarraysize(.array); [email protected]++). This would give horrendous performance. We use the array there as a dictionary rather than a list.
  15. You have a few ways of doing that. Your script doesn't cover all possible abusable ways even with logout. It is possible to cancel a script without logging out. One trick is to "abuse" the addtimer behavior. While a script is running, the timed event will not run until the current script is finished (it is queued). As for the logging out issue, you can simply use OnPCLogoutEvent. One drawback from this is that you need to delete the timer as otherwise it will revert whenever you exit the NPC. So I added another menu option to confirm your style, " ~ I want this style". I'd probably remove the " ~ Revert to original" if I were you as it's not needed at all. Cancelling will do that for you and that way you can keep 4 menu options and keep things clean. prontera,76,96,1 script Stylist#custom_stylist 122,{ setarray [email protected][1], getbattleflag("max_cloth_color"), getbattleflag("max_hair_style"), getbattleflag("max_hair_color"); setarray [email protected][1], LOOK_CLOTHES_COLOR, LOOK_HAIR, LOOK_HAIR_COLOR; set [email protected], select(" ~ Cloth color: ~ Hairstyle: ~ Hair color"); set [email protected], getlook([email protected][[email protected]]); set [email protected],1; @stylist_look_type = [email protected][[email protected]]; @stylist_look_value = getlook(@stylist_look_type); addtimer 1, strnpcinfo(0) + "::OnPCLogoutEvent"; while(1) { setlook [email protected][[email protected]], [email protected]; message strcharinfo(0),"This is style #"[email protected]+"."; set [email protected]$, " ~ Next (^0055FF"+(([email protected][email protected][[email protected]])[email protected]+1:1)+"^000000): ~ Previous (^0055FF"+(([email protected]!=1)[email protected]:[email protected][[email protected]])+"^000000): ~ Jump to...: ~ I want this style"; switch(prompt([email protected]$)) { case 1: set [email protected], (([email protected] != [email protected][[email protected]]) ? [email protected]+1 : 1); break; case 2: set [email protected], (([email protected] != 1) ? [email protected] : [email protected][[email protected]]); break; case 3: message strcharinfo(0),"Choose a style between 1 - "[email protected][[email protected]]+"."; input [email protected],0,[email protected][[email protected]]; if ([email protected]) set [email protected], rand(1,[email protected][[email protected]]); break; case 4: // You have to set the values to 0 and remove the timer event once the colors are chosen and confirmed // Your code currently doesn't have a way out of your loops, so I added this one. @stylist_look_type = @stylist_look_value = 0; deltimer strnpcinfo(0) + "::OnPCLogoutEvent"; end; default: set [email protected], [email protected]; setlook [email protected][[email protected]], [email protected]; end; } } end; OnPCLogoutEvent: if (@stylist_look_type != 0) { setlook @stylist_look_type, @stylist_look_value; } deltimer strnpcinfo(0) + "::OnPCLogoutEvent"; end; }
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.