-
Posts
248 -
Joined
-
Last visited
-
Days Won
19
Content Type
Profiles
Forums
Downloads
Jobs Available
Server Database
Third-Party Services
Top Guides
Store
Posts posted by Winterfox
-
-
You need to end the script after each label, so it doesn't fall through and executes the code of the next.
OnBarDead1: setcell "grandarena",45,53,45,46,cell_walkable,1; end; OnBarDead2: setcell "grandarena",53,54,46,54,cell_walkable,1; end; ...
-
Poring Slot
In this game, you can place bets on one of 5 slots. Each slot has a different chance to be picked, but also gives a higher reward, the lesser the chance.
After enough bets are placed, a player can pay a fee to spin the wheel. After a certain amount of time, one slot is picked and the winners can get their prize.
This script is resistant to server restarts and script reloads. It always keeps track of all currently placed bets and prizes a player has.
If the player is offline during a spin but wins, he gets a notification on the next login that he has pending prizes.
The following things are customizable via config variables:- Price per spin.
- Amount of bets before a spin can be started.
- The item used as currency for the game.
- The minimum amount for a bet.
- The sprite, name, color, bonus on win and position of each slot selection.
- The position and type of each slot.
Updates and bug fixes are free and will be available here for all customers.
Costumers can contact me via discord for support. My username there is hope2812.
-
Submitter
-
Submitted09/09/23
-
Category
-
Video
-
Content AuthorWinterfox
-
You can use the time labels:
OnClock<hour><minute>: OnMinute<minute>: OnHour<hour>: On<weekday><hour><minute>: OnDay<month><day>: This will execute when the server clock hits the specified date or time. Hours and minutes are given in military time. ('0105' will mean 01:05 AM). Weekdays are Sun,Mon,Tue,Wed,Thu,Fri,Sat. Months are 01 to 12, days are 01 to 31. Remember the zero.
This would run the event every 24 hours at 14 o'clock:
OnHour14: goto l_start; end;
-
The script constant Eff_Freeze refers to SC_FREEZE in the source code.
Looking this up, it seems that resistance to freeze (or any other status) isn't handled in pc.cpp but in status.cpp -
I think your problem is the falltrough after the call of an OnBarDead label. This leads to one OnBarDead label calling all succeeding setcell calls that make the cells walkable.
If for example OnBarDead1 gets called, it falls through all labels until it hits the end command at the end of the file, effectivly making all non-walkable cells walkable instead of only the ones you targeted with your label. -
1 hour ago, kundalini313 said:
how to make barricades unpassable until all destroyed?
It would be a good idea to include your script in the post.
Otherwise, it is pretty hard to help you. -
If you have logging enabled, you can check the picklog table for rows where type is S.
// 0x00000010 - (S) Log NPC transactions (buy/sell)
For details, check log_athena.conf. The logging part is directly at the beginning of the file.
-
Autoplay
This is a command that basically turns a character into a bot.
Once a player with the proper permissions uses this command, the character will start to walk around the map and attack all mobs it sees automatically.
Warps are ignored and most functions like chatting etc. are disabled while in autoplay mode.
Autoplay is disabled automatically when the character dies while it is active.The following things are configurable:
- The radius the character searches for mobs around itself.
- The minimum path length the character walks per move.
- The maximum path length the character walks per move.
- The timeout when a character fails to attack a mob.
- The timeout when a character fails to move.
- The minimal group level to use the command.
Updates and bug fixes are free and will be available here for all customers.
Costumers can contact me via discord for support. My username there is hope2812.
-
Submitter
-
Submitted09/10/23
-
Category
-
Video
-
Content AuthorWinterfox
-
4 hours ago, jamesandrew said:
Thanks for the explanation. Very helpful!
So... If I want to use unlimited quantity for 1010 and 1011 can I use marketshop and change the quantity to -1 ?
//=Ore Exchanger //============================================================ - marketshop market_refine_prt_in -1,1010:-1:-1,1011:-1:-1 - marketshop market_refine_payon -1,1010:-1:-1,1011:-1:-1 - marketshop market_refine_morocc_in -1,1010:-1:-1,1011:-1:-1 - marketshop market_refine_alberta_in -1,1010:-1:-1,1011:-1:-1 - marketshop market_refine_yuno_in01 -1,1010:-1:-1,1011:-1:-1 - marketshop market_refine_ein_in01 -1,1010:-1:-1,1011:-1:-1 - marketshop market_refine_lhz_in02 -1,1010:-1:-1,1011:-1:-1 prt_in,63,69,3 script Dietrich#ns_prt 4_M_02,{ mes "[" + strnpcinfo(1) + "]"; mes "We sell and exchange various ores used in smelting."; next; switch( select( "View basic smelting ores", "View advanced smelting ores", "Cancel" ) ) { case 1: mes "[" + strnpcinfo(1) + "]"; mes "Phracon and Emveretarcon are available for use in smelting low-level weapons."; close2; callshop "market_refine_" + strnpcinfo(4); end; case 2: mes "[" + strnpcinfo(1) + "]"; mes "We are purifying Elunium Stone and Oridecon Stone, or exchanging Coins."; close2; callshop "barter_refine_1"; end; case 3: mes "[" + strnpcinfo(1) + "]"; mes "If you lack the materials used for smelting, come anytime."; close; } end; OnInit: setunittitle getnpcid(0), "<Ore Refiner>"; end; }
Exactly. npcshopupdate uses the same arguments for stocks as the marketshop itemlist, as it is also explained in the script documentation:
"marketshop" can have limited quantity of an item in stock. Use -1 in the stock field to have unlimited stock in a marketshop.
-
1
-
-
If you want to update the stock programmatically, for example on a certain event, you can use npcshopupdate.
*npcshopupdate "<name>",<item_id>,<price>{,<stock>} Update an entry from a shop. If the price is 0 it won't be changed. May also be used for marketshop to update the stock quantity. For unlimited stock, use -1. For other shop types, the stock value has no effect.
Which means to reset the stock of item 1010 in the market_refine_prt_in shop, you would do it like this:
npcshopupdate("market_refine_prt_in", 1010, 0, 999999);
If you want to simply change the stock for testing purposes, you could edit the shop in the market table in the database.
In your NPCs case, if you check line 588 in the file npc/merchants/refine.txt, you will see the NPC refine_barter_init.
Which uses above-mentioned npcshopupdate to update the stocks of the NPCs in your post when the script gets loaded.
So if you only care about resetting the stock of those, reloading only the script where the shops are defined should suffice.
You can use this command to do this:@reloadnpcfile npc/merchants/refine.txt
-
1
-
-
-
You can generate the navigation information of the npcs for the client by running navigenerator in the server root directory.
Afterward, you can find the clientside files in the folder generated/clientside and copy that into your client root directory. -
- script FREEZE FAKE_NPC,{ OnInit: .@group = 99; bindatcmd("freeze", strnpcinfo(3) + "::OnFreeze", .@group); bindatcmd("unfreeze", strnpcinfo(3) + "::OnUnfreeze", .@group); end; OnFreeze: .@mode = 1; OnUnfreeze: getmapunits(BL_PC, .@atcmd_parameters$[0], .@players); freeloop(1); for(.@i = 0; .@i < getarraysize(.@players); .@i++) pcblockmove(.@players[.@i], .@mode); freeloop(0); }
-
1
-
-
-
That is possible via Script, but I am not sure how well it scales for many players at the same time.
-
- script FREEZE FAKE_NPC,{ OnInit: bindatcmd("freeze", strnpcinfo(3) + "::OnFreeze"); bindatcmd("unfreeze", strnpcinfo(3) + "::OnUnfreeze"); end; OnFreeze: .@mode = 1; OnUnfreeze: getmapunits(BL_PC, .@atcmd_parameters$[0], .@players); freeloop(1); for(.@i = 0; .@i < getarraysize(.@players); .@i++) pcblockmove(.@players[.@i], .@mode); freeloop(0); }
-
I didn't test it, but this should do what you want.
- script FREEZE FAKE_NPC,{ OnInit: bindatcmd("freeze", strnpcinfo(3) + "::OnFreeze"); bindatcmd("unfreeze", strnpcinfo(3) + "::OnUnfreeze"); end; OnFreeze: .@mode = 1; OnUnfreeze: getmapunits(BL_PC, getarg(0), .@players); freeloop(1); for(.@i = 0; .@i < getarraysize(.@players); .@i++) pcblockmove(.@players[.@i], .@mode); freeloop(0); }
-
On 9/6/2023 at 8:12 PM, jamesandrew said:
I'm making a simple fishing script.
The rules are:
- Must equip a fishing rod (2764)
- 5 seconds cast time
- Get one reward per cast
- Rewards rate are: Red Herb 40%; Yellow Herb 30%; White Herb 20%, Blue Herb 10%, Yggdrasil Berry 0.01%
prt_fild00,278,237,0 script Fishing School 10065,{ set .@Rod,2764; //Fishing rod if (isequipped(.@Rod)){ specialeffect EF_BUBBLE,"Fishing School"; soundeffect "_attack_axe.wav",0; dispbottom "[Fishing] Casting..."; set .@fcast,5; progressbar "ffffff",.@fcast; if (rand(1,10) <= 4) ||(rand(1,10) <= 3) || (rand(1,10) <= 2) || (rand(1,10) <= 1){ setarray .@Catch[0],507,508,509,510;// Red 40%, Yellow 30%, White 20%, Blue Herb 10% set .@CatchRand,.@Catch[rand(getarraysize(.@Catch))]; getitem .@CatchRand,1; specialeffect2 610; soundeffectall "see_otter_damage.wav",0,strcharinfo(3); dispbottom("[Fishing] You got "+ getitemname(.@CatchRand) +"."); } else { dispbottom "[Fishing] Nothing was caught..."; specialeffect2 611; end;} if (rand(1,100) == 1){ setarray .@Rare[0],607; //Yggdrasil Berry 0.01% set .@RareCatch, .@Rare[rand(getarraysize(.@Rare))]; getitem .@RareCatch,1; dispbottom("[Fishing] Congratulations you got "+ getitemname(.@RareCatch) +"."); specialeffect2 68; end;} else { end;} } else { dispbottom "[Fishing] You need a Fishing Rod."; end; } }
are these rands correct?
Your pick code throws 4 dice with 10 eyes and checks if at least one fits, and then picks an item randomly.
Which means your script decides if it should give loot or not (Which contradicts your 4. Rule) but in case it drops an item, it gives every item an equal chance to be dropped.
Except Yggrasil Berry, which gets a 1% chance to be dropped regardless of if there was already a drop, which also contradicts your 4. Rule.
Here is what I would do to change your script to make it fit your given rules:
prt_fild00,278,237,0 script Fishing School 10065,{ if (!isequipped(.rod)) { dispbottom("[Fishing] You need a Fishing Rod."); end; } specialeffect(EF_BUBBLE, "Fishing School"); soundeffect("_attack_axe.wav", 0); dispbottom("[Fishing] Casting..."); progressbar("ffffff", .cast_delay); .@pick = rand(1, .catch_weight_sum); for(.@i = 0; .@i < getarraysize(.catches); .@i += 2) { .@pick -= .catches[.@i + 1]; if(.@pick <= 0) { .@catch = .catches[.@i]; break; } } getitem(.@catch, 1); specialeffect2(610); soundeffectall("see_otter_damage.wav", 0, strcharinfo(3)); dispbottom("[Fishing] You got "+ getitemname(.@catch) + "."); end; OnInit: .rod = 2764; .cast_delay = 5; // Red Herb 40%; Yellow Herb 30%; White Herb 20%, Blue Herb 10%, Yggdrasil Berry 0.01% setarray(.catches, 507, 4000, 508, 3000, 509, 2000, 510, 1000, 607, 1); for(.@i = 0; .@i < getarraysize(.catches); .@i += 2) .catch_weight_sum = .catches[.@i + 1]; }
-
1
-
-
1 hour ago, namerpus18 said:
I am sorry, I also tried that method but the thing is inside the quote should be a <condition> can be any expression similar to the <condition> in the 'if' command. I am not quite sure if doing for inside it is really possible. Thank you
OnInit: questinfo(QTYPE_QUEST),QMARK_YELLOW, "checkquest (11114,HUNTING) == 2 || checkquest (11115,HUNTING) == 2 || checkquest (11116,HUNTING) == 2 || checkquest (11117,HUNTING) == 2 || checkquest (11118,HUNTING) == 2 || checkquest (11119,HUNTING) == 2 || checkquest (11120,HUNTING) == 2 || checkquest (11121,HUNTING) == 2 || checkquest (11122,HUNTING) == 2 || checkquest (11123,HUNTING) == 2";
You are right, it doesn't seem like you can put anything inside the condition argument of the questinfo function that doesn't return a value directly.
It simply evaluates if the result of the script in the conditions string results in true or false, when certain events like the completion of a quest trigger a reevaluation.
That means you can only use functions that the script engine knows and that return a value.
So what you can do alternatively is to build the condition string dynamically.prontera,150,193,4 script DEMO 124,{ OnInit: setarray(.@quests, 11114, 11115, 11116, 11117, 11118, 11119, 11120, 11121, 11122, 11123); for(.@i = 0; .@i < getarraysize(.@quests); .@i++) .@condition$[.@i] = "checkquest(" + .@quests[.@i] + ", HUNTING) == 2"; questinfo(QTYPE_QUEST, QMARK_YELLOW, implode(.@condition$, "||")); }
-
1
-
-
- script SKILL_DEMO FAKE_NPC,{ OnInit: monster("prontera", 150, 170, "Helper A", 1002, 1); .@mob_a = $@mobid[0]; unitblockmove(.@mob_a, 1); getunitdata(.@mob_a, .@mob_a_data); .@pos_x = .@mob_a_data[UMOB_X]; .@pos_y = .@mob_a_data[UMOB_Y]; monster("prontera", 140, 160, "Helper B", 1002, 1); .@mob_b = $@mobid[0]; while(.@pos_x != .@target_x || .@pos_y != .@target_y) { getunitdata(.@mob_b, .@mob_b_data); .@target_x = .@mob_b_data[UMOB_X]; .@target_y = .@mob_b_data[UMOB_Y]; if(.@pos_x != .@target_x) .@pos_x += (.@pos_x < .@target_x) ? 1 : -1; if(.@pos_y != .@target_y) .@pos_y += (.@pos_y < .@target_y) ? 1 : -1; unitskillusepos(.@mob_a, "MG_THUNDERSTORM", 10, .@pos_x, .@pos_y, -5, false, 0, true); sleep(1000); } }
-
25 minutes ago, namerpus18 said:
Good Day everyone,
I just need some help, if someone can help me shorten this script. My methods are too limited and i cant find a way to shorten it.
Does it improve if i manage to optimize this script? I feel that this script alone takes a lot of checking.
Thank you so much,
if(getmonsterinfo(killedrid, MOB_MVPEXP) > 1 && isbegin_quest(19000) > 0 || isbegin_quest(19001) > 0 || isbegin_quest(19002) > 0 || isbegin_quest(19003) > 0 || isbegin_quest(19004) > 0 || isbegin_quest(19005) > 0 || isbegin_quest(19006) > 0 || isbegin_quest(19007) > 0 || isbegin_quest(19008) > 0 || isbegin_quest(19009) > 0 || isbegin_quest(19010) > 0 || isbegin_quest(19011) > 0 || isbegin_quest(19012) > 0 || isbegin_quest(19013) > 0 || isbegin_quest(19014) > 0 || isbegin_quest(19015) > 0 || isbegin_quest(19016) > 0 || isbegin_quest(19017) > 0 || isbegin_quest(19018) > 0 || isbegin_quest(19019) > 0 ) { .... }
It is hard to really optimize the script without knowing the whole code. But to make the snippet you have more manageable, you could organize your code like this:
for(.@i = 0; .@i < 20; .@i++) { if(isbegin_quest(19000 + .@i) > 0) { .@has_quest = 1; break; } } if(getmonsterinfo(killedrid, MOB_MVPEXP) > 1 && .@has_quest) { }
-
4 hours ago, jamesandrew said:
I've just tested it. It does work but it's very easy to abuse by swapping weapons
Thanks though----edit
Is it possible to use specialeffect2 from this list rathena/doc/effect_list.txt at master · rathena/rathena (github.com) to make your character act like auto attacking mobs?I am not sure if there is an effect that makes it look like a character attacks.
Another idea I had would be to spawn an invisible mob below the ore NPC when the player meets the requirements, and then to set him up to attack that mob and lock him in this state until he killed the ore mob.
When the ore mob is dead, you can hide the npc for the player for a certain amount of time.
For the part of making a player attack a mob and blocking movement, you could check the commands: unitattack and, setpcblock that could help you with that. In general, the unit commands could be of help to you.
For the part about visibility of ores, you could use the on touch area of the npc and combine that with cloakonnpc or cloakonnpcself to control which players can see the npc right now. -
You could attach the checks on a label that gets triggered when the mob that represents an ore gets killed.
Here is a small example:- script MINING FAKE_NPC,{ OnInit: // Config setarray(.mining_utils, 28116); setarray(.minerals, 3742, 3743, 1083); .mineral_0_name$ = "Bronze"; setarray(.mineral_0_maps$, "prontera"); setarray(.mineral_0_amounts, 10); setarray(.mineral_0_areas_x_1, 150); setarray(.mineral_0_areas_x_2, 163); setarray(.mineral_0_areas_y_1, 175); setarray(.mineral_0_areas_y_2, 137); setarray(.mineral_0_items, 502, 10, 1, 5, 503, 40, 1, 5, 504, 50, 1, 5); .mineral_1_name$ = "Silver"; setarray(.mineral_1_maps$, "prontera"); setarray(.mineral_1_amounts, 10); setarray(.mineral_1_areas_x_1, 150); setarray(.mineral_1_areas_x_2, 163); setarray(.mineral_1_areas_y_1, 150); setarray(.mineral_1_areas_y_2, 200); setarray(.mineral_1_items, 505, 10, 1, 5, 506, 40, 1, 5, 507, 50, 1, 5); .mineral_2_name$ = "Gold"; setarray(.mineral_2_maps$, "prontera"); setarray(.mineral_2_amounts, 10); setarray(.mineral_2_areas_x_1, 150); setarray(.mineral_2_areas_x_2, 163); setarray(.mineral_2_areas_y_1, 175); setarray(.mineral_2_areas_y_2, 137); setarray(.mineral_2_items, 508, 10, 1, 5, 509, 40, 1, 5, 510, 50, 1, 5); // Config End for(.@i = 0; .@i < getarraysize(.minerals); .@i++) { .@name$ = getd(".mineral_" + .@i + "_name$"); .@items = getd(".mineral_" + .@i + "_items"); .@items_size = getarraysize(getd(".mineral_" + .@i + "_items")); .@item_sum = 0; for(.@x = 0; .@x < .@items_size; .@x += 4) .@item_sum += getd(".mineral_" + .@i + "_items[" + (.@x + 1) + "]"); setd(".mineral_" + .@i + "_item_sum", .@item_sum); .@maps_size = getarraysize(getd(".mineral_" + .@i + "_maps$")); for(.@y = 0; .@y < .@maps_size; .@y++) { .@maps$ = getd(".mineral_" + .@i + "_maps$[" + .@y + "]"); .@amounts = getd(".mineral_" + .@i + "_amounts[" + .@y + "]"); .@areas_x_1 = getd(".mineral_" + .@i + "_areas_x_1[" + .@y + "]"); .@areas_x_2 = getd(".mineral_" + .@i + "_areas_x_2[" + .@y + "]"); .@areas_y_1 = getd(".mineral_" + .@i + "_areas_y_1[" + .@y + "]"); .@areas_y_2 = getd(".mineral_" + .@i + "_areas_y_2[" + .@y + "]"); areamonster(.@maps$, .@areas_x_1, .@areas_x_2, .@areas_y_1, .@areas_y_2, .@name$, .minerals[.@i], .@amounts, "MINING::OnMined"); } } end; OnMined: .@mineral = inarray(.minerals, killedrid); .@mineral_name$ = getd(".mineral_" + .@mineral + "_name$"); .@util = getequipid(EQI_HAND_R); if(inarray(.mining_utils, .@util) == -1) { dispbottom("Using your " + getitemname(.@util) + " destroyed any useful resource from " + .@mineral_name$ + "."); end; } .@mineral_item_sum = getd(".mineral_" + .@mineral + "_item_sum"); .@mineral_items_size = getarraysize(getd(".mineral_" + .@i + "_items")); .@pick = rand(1, .@mineral_item_sum); for(.@i = 0; .@i < .@mineral_items_size; .@i += 4) { .@pick -= getd(".mineral_" + .@mineral + "_items[" + (.@i + 1) + "]"); if(.@pick <= 0) break; } .@item = getd(".mineral_" + .@mineral + "_items[" + .@i + "]"); .@item_min_amount = getd(".mineral_" + .@mineral + "_items[" + (.@i + 2) + "]"); .@item_max_amount = getd(".mineral_" + .@mineral + "_items[" + (.@i + 3) + "]"); getitem(.@item, rand(.@item_min_amount, .@item_max_amount)); }
This will spawn different minerals (in this example represented by purple ore and plants), which give different items on kill etc. once a mineral gets killed, it checks if an item from the .mining_utils array is equipped and if not gives the player the message, that using the wrong item destroyed any useful resources otherwise it will roll which and how many of an item the player gets.
-
1
-
-
The easiest way would be to create a custom mob that looks like a mineral. You could for example copy Purple Ore (id: 3742) and add the items you want the player to get by mining as drop.
You just need to remember to add your custom mob to mob_avail,yml to tell rathena to make the client use the sprite of the original mob for your custom one.-
1
-
consume item for each hit
in Database Requests
Posted · Edited by Winterfox
You could try to achieve this effect using autobonus by setting a short amount for the duration the script will last.