-
Posts
1297 -
Joined
-
Last visited
-
Days Won
38 -
Feedback
100%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by Syreldar
-
-
11/05/2023:
- Added color_str(color, text).
- Updated some global calls for the latest globals.lua update.
- 1
-
11/05/2023:
- Improvements to the overall structure of the globals.
- Added POINTS
-
I would not post code that's not working.
-
5 minutes ago, NightCore.PL said:
1. So the first hunting quest is not selectable? I thought i remember from regular metin2 that it was.
I was talking about your questcategory not behaving properly, not having a selection is also a quest issue, not the system's.
- 1
-
3 hours ago, NightCore.PL said:
one more thing, i think you're supposed to pick between 10 dogs or 5 wolves but that option never appeared for me. maybe this is why it glitched?
No, you just had to use a letter.
3 hours ago, NightCore.PL said:That visual error is due to your quest's string probably missing the format for the number.
- 1
-
7 hours ago, Intel said:
Also, to add what Syreldar said, when using server timers you cannot use qestlua_pc functions (no pc is selected in a server timer).
Furthermore:
if map_index >= 217000 and map_index < 217000 then
I am pretty sure it should've been < 218000 (if it was meant for the exit from the dungeon when logging in):
when login begin if pc.get_map_index() == 217 then pc.warp(exit_x*100, exit_y*100, 217) end elseif pc.get_map_index() >= 217000 and pc.get_map_index() < 218000 then pc.set_warp_location(217, exit_x, exit_y) end end
217000 to 217999 are all valid dungeon instances of the map with index 217
*10000, not 1000!
These formalities can be avoided by using the InDungeon(MAP_INDEX) function from my function lib.Also care about the "elseif", you should remove the if's end for it to work.
- 1
- 1
-
I mean..
In the first quest you're using pc.warp, not even using its index arg, meaning you make a simple warp to a map. Everyone can access that map, obviously.
In the second quest you're warping into the same map always with pc.warp, starting a 3 seconds timer and then calling d.new_jump_all, meaning you send every person in your map, yourself included, inside an instanced version of the target map.
The solution is to either use d.new_jump or d.new_jump party, the former warping only you, the latter warping you and your whole party if present.
Also never use local timers within a dungeons, they're bound to pc instances, meaning if you crash the instance breaks even if you can rejoin to it.
Also always make dungeon checks on triggers, when 2095.kill begin is nowhere near enough. you gotta check the map index, too.
Also you are generating yet another dungeon instance when the baroness spawns via calling d.new_jump_all for absolutely no reason.
- 1
-
-
Just now, nicohare711 said:
That's none of his business. You simply set the item's size to 0. Your item_proto's fault.
- 1
-
On 4/27/2023 at 7:17 AM, TMP4 said:
It is coming from the 4th floor:
when devil_stone4_update.server_timer begin if d.select(get_server_timer_arg()) then if not d.is_unique_dead("real") then for i = 1, 6 do if d.getf("fakedead" .. i) == 0 then if d.unique_get_hp_perc("fake" .. i) < 50 then d.purge_unique("fake" .. i) d.setf("fakedead" .. i, 1) notice_multiline(gameforge.deviltower_zone._90_dNotice,d.notice) end end end else server_timer("devil_stone4_end", 5, get_server_timer_arg()) --d.kill_all() d.purge() notice_multiline(gameforge.deviltower_zone._100_dNotice,d.notice) clear_server_timer('devil_stone4_fail1', get_server_timer_arg()) clear_server_timer('devil_stone4_fail2', get_server_timer_arg()) clear_server_timer('devil_stone4_fail', get_server_timer_arg()) end else server_timer('devil_stone4_stop_timer', 1, get_server_timer_arg()) end end
So the important thing is that this is not a syserr-free server file. Every base file had and have this syserr. Despite that syserr, devil tower works fine.
I don't have a fix for that.if d.unique_get_hp_perc("fake" .. i) < 50 then d.purge_unique("fake" .. i)
change with:
if not d.is_unique_dead("fake" .. i) and d.unique_get_hp_perc("fake" .. i) < 50 then d.purge_unique("fake" .. i)
This way you check if the unique still exists before making operations and checks on it. Sadly the official quests are far from perfect. They work, but they lack safety checks like these.
Anyway, this is the right way to do stuff with uniques, but despite this fix you will still get an 'error' that looks like this:
IsUniqueDead: Unknown Key or Dead : fake3
Now this one actually makes no sense as an error, meaning it's not actually an error. I'll explain briefly:
This triggers, like I show in the snippet below, when an unique is not found in the unique map.
But that's exactly the point of the 'IsUniqueDead' function in the first place, to check if they're dead or not existing, so I suspect they just copypasted it from the other similiar methods and never doublechecked, but one thing for sure: this syserr definitely does not belong to this method and can safely be commented out, like this:
bool CDungeon::IsUniqueDead(const std::string& key) { TUniqueMobMap::iterator it = m_map_UniqueMob.find(key); if (it == m_map_UniqueMob.end()) { //sys_err("Unknown Key or Dead : %s", key.c_str()); return true; } return it->second->IsDead(); }
And now not only the quest's code will behave properly, but your syserr will also be clean from errors like this, assuming you haven't got any other quest that makes unique calls without checking for IsUniqueDead, in which case you'll have to add the check in each one of their occurrences, too.
- 3
-
8 minutes ago, backtop said:
Thank you for your help But I don't have the function item.set_attribute in questlib.lua can you share this function?
it's not a Lua func, hint: questlua_item.cpp
-
..You really don't need that amount of code and states to make such a basic thing.
define MAX_LEVEL 70 define PROG_LEVEL 10 define START_AVG_DMG 10 define PROG_AVG_DMG 3 define MAX_AVG_DMG 30 -- Needs: globals.lua, functions.lua, item.set_attribute(idx, type, value) quest young_heroes_weapons begin state start begin function IsYoungHeroLevel(pc_level) return pc_level >= PROG_LEVEL*pc.getqf("times") and pc_level <= MAX_LEVEL; end -- function function GetYoungHeroWeaponsPerJob(pc_job) local data = { [WARRIOR] = {21900, 21903}, [NINJA] = {21900, 21901, 21902}, [SURA] = {21900}, [SHAMAN] = {21904, 21905}, [WOLFMAN] = {21906} }; return data[pc_job]; end -- function when letter or levelup with young_heroes_weapons.IsYoungHeroLevel(pc.get_level()) begin send_letter("Young Heroes' Weapons"); end -- when when button or info with young_heroes_weapons.IsYoungHeroLevel(pc.get_level()) begin say_title("Young Heroes' Weapons:[ENTER]") say("Select your weapon:[ENTER]") local weapons_per_job = young_heroes_weapons.GetYoungHeroWeaponsPerJob(pc.get_job()); local choose_weapon_list_name = {}; for _, weapon_vnum in ipairs(weapons_per_job) do table.insert(choose_weapon_list_name, item_name(weapon_vnum + PROG_LEVEL*pc.getqf("times"))); end -- for table.insert(choose_weapon_list_name, "I'll choose later"); local selection = select_table(choose_weapon_list_name); if (selection == table.getn(choose_weapon_list_name)) then send_letter(letter_str); return; end -- if local weapon_to_receive = weapons_per_job[selection] + PROG_LEVEL*pc.getqf("times"); pc.give_item2_select(weapon_to_receive); -- Adds Average Damage like official. item.set_attribute(0, APPLY.NORMAL_HIT_DAMAGE_BONUS, math.min(MAX_AVG_DMG, START_AVG_DMG + PROG_AVG_DMG*pc.getqf("times"))); pc.setqf("times", pc.getqf("times")+1); q.done(); end -- when end -- state end -- quest
- 1
- 1
-
-
25/04/2023:
- Added SELECT_YES, SELECT_ENTER, SELECT_NO;
- Added EMPIRES;
- Added ARMED_HORSE_LEVEL, MILITARY_HORSE_LEVEL;
- Added STATUS_VIT, STATUS_INT, STATUS_STR, STATUS_DEX;
- Added ITEM_TYPES, ITEM_SUB_TYPES;
- Added AFFECT;
- Updated APPLY;
- Added JOB_TO_RACE, RACE_TO_JOB, RACE_TO_SEX;
- Changed RACE_NAME_LIST;
- Added PC_RACE_LIST, PC2_RACE_LIST, PC3_RACE_LIST;
- Added MALE_RACE_LIST, FEMALE_RACE_LIST;
- Added SEX_NAME_LIST
- Added STATUS_NAME_LIST;
- Added EMPIRE_NAME_LIST;
- 1
-
25/04/2023:
- Added table_get_count(table).
- Added is_valid_num_field(num).
- Added is_valid_table_field(table).
- Added is_valid_func_field(func).
- Added time_remaining_until(os.date("%H:%M")).
-
6 minutes ago, Radhan said:
Having said that, don't disparage other people's work, thank you.
Why are you acting like it's your work to begin with?
-
Ava2 serverfiles. Trash italian scam server with 30 players online. Don't even try it.
- 1
- 1
- 1
-
3 hours ago, ATAG said:
In our case this is not a problem, higher number means less drop
Yeah, let's make 2 kilos of salad with 5% lettuce, 10% tomatoes, 40% pine nuts, 30% olive oil, 15% balsamic vinegar, in the end it's a lot of food, so I'm sure it'll be good!.. right?
- 2
-
31 minutes ago, BYB said:
It means when you applied the change you saved the file in the wrong encoding. So now all the LC_TEXT calls are messed up.
You need to revert the change and remake it, and save the file with the proper encoding this time.
-
Nice job. If anybody wants the quest version of a mob_drop_item.txt that's easily customizeable:
define TYPE_LIMIT_STATIC 1 define TYPE_LIMIT_DYNAMIC 2 define TYPE_KILL 3 quest drops begin state start begin function GetDropData(vnum) return ({ [8002] = { ["type"] = {TYPE_LIMIT_STATIC, 50}, ["drops"] = { {["vnum"] = 101051, ["quantity"] = 1, ["perc"] = 100}, {["vnum"] = 101001, ["quantity"] = 1, ["perc"] = 100}, {["vnum"] = 71151, ["quantity"] = 5, ["perc"] = 100}, -- more drops here. } }, -- more monsters here. })[vnum] or nil; end -- function when kill with not npc.is_pc() begin local npc_race = npc.get_race(); local drop_data = drops.GetDropData(npc_race); if (drop_data == nil) then return; end -- if local drop_type, drop_type_arg = drop_data["type"][1], drop_data["type"][2]; -- LIMIT_STATIC = Within 15 of a fixed level (defined in the limit's 2nd arg) -- LIMIT_DYNAMIC = Within 15 of target's level. if (drop_type == TYPE_LIMIT_STATIC or drop_type == TYPE_LIMIT_DYNAMIC) then local level_reference = (drop_type == TYPE_LIMIT_STATIC and drop_type_arg or npc.get_level()); if (math.abs(pc.get_level() - level_reference) > 15) then return; end -- if -- KILL = Kill a certain amount of enemies to have a chance to drop. elseif (drop_type == TYPE_KILL) then local qf_name = string.format("drop_%d_count", npc_race); pc.setqf(qf_name, pc.getqf(qf_name)+1); if (math.mod(pc.getqf(qf_name), drop_type_arg) ~= 0) then return; end -- if end -- if/elseif for _, item_data in ipairs(drop_data["drops"]) do if (math.random(100) <= item_data["perc"]) then game.drop_item_with_ownership(item_data["vnum"], item_data["quant"]); --break; -- Uncomment if you want to limit to one drop per monster kill. end -- if end -- for end -- when end -- state end -- quest
Spoiler- 1
- 1
- 3
- 4
-
3 hours ago, Macromango said:
At this point I'm afraid to ask, but here I go.
PLAYER_INDEX DATABASE
ID stands for the id of the account and this is clear to me
EMPIRE stands for the kingdom of the account clearly with shinsoo = 1, jinno = 3 etc
What about those pids?
They are almost probably associated to each player character per account, but still I don't really get what the values refer to, all information I looked for seemed confusing and non exaustive;
If someone could point me to something I'll be glad to get deeper into the undestanding of this
Keep up the good work, cheers
Macro
- 1
-
20/03/2023:
- Added get_random_number_within_except(range_min, range_max, except_table)
-
26 minutes ago, caanmasu said:
I ask you the favor that you don't sabotage my posts, just as I don't sabotage yours. At no time have I commented on your answers.
Secondly, you talk about advantages of lua and you mentioned an advantage that does not have to do with performance, which is the topic we are talking about.
If you're so professional, why don't you explain how to do it and that's it?
The moment you stop spreading misinformation is the moment I stop commenting on your posts, simple as that.
I don't talk about performance because performance is irrelevant on Metin2. If you think otherwise you're simply delusional.
-
37 minutes ago, strangerino said:
So I actually have this:
quest dropquest begin state start begin when kill with not npc.is_pc() begin local randReceptura = math.random(0, 1000); local randPruty = math.random(0, 1500); local randOstatni_0 = math.random(0, 500); -- Smes local randOstatni_1 = math.random(0, 500); -- Byliny local randOstatni_2 = math.random(0, 500); -- Predmety local randZily = math.random(0, 850); sanceReceptura = 3; -- Receptury sancePruty = 1; -- Pruty sanceOstatni = 10; -- Bordel sanceZily = 3; -- Zily metiny local levelRange = 25; local receptura = {30121, 30122, 30122, 30123, 30124, 30125, 30126, 30127, 30128}; local pruty = {80007, 80006, 80005, 80004, 80003}; local ostatni = { 25040, 50012, 50013, 50006, 50007, 50008, 50009, 50014, 50015, 50005, 50301, 50302, 50303, 50304, 50305, 50306, 50307, 50308, 50309, 50310, 50314, 50315, 50316, 50600 }; local byliny = { 50701, 50702, 50703, 50704, 50705, 50706, 50707, 50708, 50709, 50710, 50711, 50712, 70251, 70252, 70253, 70254 }; local zily = { 71057, 71058, 71059, 71060, 71061, 71062, 71063, 71064, 71065, 71066, 71067, 71080, 71081, 71082 }; local drop_1_20 = { 11, 13, 21, 23, 31, 33, 41, 43, 3001, 3003, 3011, 3013, 3021, 3023, 3031, 3033, 5001, 5003, 5011, 5013, 5021, 5023, 5031, 5033, 7001, 7003, 7011, 7013, 7021, 7023, 7031, 7033, 1001, 1003, 1011, 1013, 1021, 1023, 1031, 1033, 2001, 2003, 2011, 2013, 2021, 2023, 2031, 2033, 11201, 11203, 11211, 11213, 11221, 11223, 11601, 11603, 11611, 11613, 11621, 11623, 11401, 11403, 11411, 11413, 11421, 11423, 11801, 11803, 11811, 11813, 11821, 11823, 12201, 12203, 12341, 12343, 12481, 12483, 12621, 12623, 15001, 15003, 15021, 15023, 15041, 15043, 13001, 13003, 16001, 16003, 16021, 16023, 16041, 16043, 16061, 16063, 14001, 14003, 14021, 14023, 14041, 14043, 14061, 14063, 17001, 17003, 17021, 17023, 17041, 17043, 17061, 17063 }; local drop_21_50 = { 51, 53, 61, 63, 71, 73, 81, 83, 91, 93, 101, 103, 111, 113, 121, 123, 3041, 3043, 3051, 3053, 3061, 3063, 3071, 3073, 3081, 3083, 3091, 3093, 3101, 3103, 3111, 3113, 5041, 5043, 5051, 5053, 5061, 5063, 5071, 5073, 7041, 7043, 7051, 7053, 7061, 7063, 7071, 7073, 7081, 7083, 7091, 7093, 7101, 7103, 7111, 7113, 1041, 1043, 1051, 1053, 1061, 1063, 1071, 1073, 1081, 1083, 2041, 2043, 2051, 2053, 2061, 2063, 2071, 2073, 2081, 2083, 2091, 2093, 2101, 2103, 2111, 2113, 11231, 11233, 11241, 11243, 11251, 11253, 11261, 11263, 11631, 11633, 11641, 11643, 11651, 11653, 11661, 11663, 11431, 11433, 11441, 11443, 11451, 11453, 11461, 11463, 11831, 11833, 11841, 11843, 11851, 11853, 11861, 11863, 12221, 12223, 12241, 12243, 12361, 12363, 12381, 12383, 12501, 12503, 12521, 12523, 12641, 12643, 12661, 12663, 15061, 15063, 15081, 15083, 15101, 15103, 15121, 15123, 15141, 15143, 15161, 15163, 15181, 15183, 13021, 13023, 13041, 13043, 16081, 16083, 16101, 16103, 16121, 16123, 16141, 16143, 16161, 16163, 16181, 16183, 14081, 14083, 14101, 14103, 14121, 14123, 14141, 14143, 14161, 14163, 14181, 14183, 17081, 17083, 17101, 17103, 17121, 17123, 17141, 17143, 17161, 17163, 17181, 17183 }; -- Check if using gloves if(pc.get_wear(7) == 70043 or pc.get_wear(8) == 70043) then sanceReceptura = sanceReceptura * 2; -- Receptury sancePruty = sancePruty * 2; -- Pruty sanceOstatni = sanceOstatni * 2; -- Bordel sanceZily = sanceZily * 2; -- Zily metiny else sanceReceptura = sanceReceptura; -- Receptury sancePruty = sancePruty; -- Pruty sanceOstatni = sanceOstatni; -- Bordel sanceZily = sanceZily; -- Zily metiny end if (pc.get_level() - npc.get_level() < levelRange) then -- Drop receptury start for index = 1, table.getn(receptura) do if (randReceptura <= sanceReceptura) then local itemSelection = math.random(1, table.getn(receptura)); game.drop_item_with_ownership(receptura[itemSelection], 1); break; end end -- Drop pruty start for index = 1, table.getn(pruty) do if (randPruty <= sancePruty) then local itemSelection = math.random(1, table.getn(pruty)); game.drop_item_with_ownership(pruty[itemSelection], 1); break; end end -- Drop bordel start (0) SMES for index = 1, table.getn(ostatni) do if (randOstatni_0 <= sanceOstatni) then local itemSelection = math.random(1, table.getn(ostatni)); game.drop_item_with_ownership(ostatni[itemSelection], 1); break; end end -- Drop byliny start (1) BYLINY for index = 1, table.getn(byliny) do if (randOstatni_1 <= sanceOstatni) then local itemSelection = math.random(1, table.getn(byliny)); game.drop_item_with_ownership(byliny[itemSelection], 1); break; end end -- Drop zily a metiny start for index = 1, table.getn(zily) do if (randZily <= sanceZily) then local itemSelection = math.random(1, table.getn(zily)); game.drop_item_with_ownership(zily[itemSelection], 1); break; end end -- Drop level 1 - 20 start (2) PREDMETY if(pc.get_level() > 0 and pc.get_level() < 21) then for index = 1, table.getn(drop_1_20) do if (randOstatni_2 <= sanceOstatni) then local itemSelection = math.random(1, table.getn(drop_1_20)); game.drop_item_with_ownership(drop_1_20[itemSelection], 1); break; end end end -- Drop level 21 50 start (2) PREDMETY if(pc.get_level() > 21 and pc.get_level() < 51) then for index = 1, table.getn(drop_21_50) do if (randOstatni_2 <= sanceOstatni) then local itemSelection = math.random(1, table.getn(drop_21_50)); game.drop_item_with_ownership(drop_21_50[itemSelection], 1); break; end end end end end end end
Just need to find out whether there is a function to count the drop chances (items, empire drop chance, etc...) Already done gloves. But will improve that later.
Is there a function to find those I listed above?
This is an example of a bad quest. You're running way more loops than necessary.
It won't still lag your server. But for readability and maintenance purposes, I suggest you to let a professional do it for you.
Fix: Sura weapon and Shaman
in Bug Fixes
Posted · Edited by Syreldar
The fix I posted 5 years ago has been thoroughly tested by many users, myself included.
There's no problem whatsoever, but feel free to use whatever suits you best.