Jump to content

Syreldar

Premium
  • Posts

    1297
  • Joined

  • Last visited

  • Days Won

    38
  • Feedback

    100%

Posts posted by Syreldar

  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:

     

    spacer.png

    That visual error is due to your quest's string probably missing the format for the number.

    • Good 1
  2. 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. 8hzfRRT.png

    • Love 1
    • Love 1
  3. 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.

    • Love 1
  4. On 4/27/2023 at 7:17 AM, TMP4 said:

    It is coming from the 4th floor:

      Hide contents
        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.

    • Love 3
  5. ..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

     

    • Metin2 Dev 1
    • Love 1
  6. 25/04/2023:

    1. Added SELECT_YES, SELECT_ENTER, SELECT_NO;
    2. Added EMPIRES;
    3. Added ARMED_HORSE_LEVEL, MILITARY_HORSE_LEVEL;
    4. Added STATUS_VIT, STATUS_INT, STATUS_STR, STATUS_DEX;
    5. Added ITEM_TYPES, ITEM_SUB_TYPES;
    6. Added AFFECT;
    7. Updated APPLY;
    8. Added JOB_TO_RACE, RACE_TO_JOB, RACE_TO_SEX;
    9. Changed RACE_NAME_LIST;
    10. Added PC_RACE_LIST, PC2_RACE_LIST, PC3_RACE_LIST;
    11. Added MALE_RACE_LIST, FEMALE_RACE_LIST;
    12. Added SEX_NAME_LIST
    13. Added STATUS_NAME_LIST;
    14. Added EMPIRE_NAME_LIST;
    • Metin2 Dev 1
  7. 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?

    • kekw 2
  8. 31 minutes ago, BYB said:

    Hey sorry to bother you again I applied this and after this happened :

    spacer.png

    Any idea what went wrong ? I tried replacing the locale_string and translate.lua incase of encoding error but didnt help plus its 3 sec in any case no matter what number I change it to

     

    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.

  9. 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

    UUEcBK3.png

     

    • kekw 1
    • Scream 1
    • Good 3
    • Love 4
  10. 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 🌞
     

    HgRkPDS.png

    qyzeWp6.png

     

    • Smile Tear 1
  11. 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.

  12. 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.

×
×
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.