Jump to content

Syreldar

Premium
  • Posts

    1295
  • Joined

  • Last visited

  • Days Won

    38
  • Feedback

    100%

Posts posted by Syreldar

  1. Insert a .quest file anywhere within the /quest folder.

    From there you may compile it singularly via terminal (./qc PATH/QUESTNAME.EXT), or you may batch-compile all of them by inserting them into the quest_list and using the make file.

    In order for a quest to work you may want to restart the server, however if it's not a new quest and you just made changes to it, you may also use the in-game command "/reload q" without running into issues.

  2. special_item_group.txt

    Group	스폐셜
    {
    	Vnum	10050 --
    	type	special --
    	1	71148	100000	1 --Ring of Will Power
    	2	71149	100001	1 --Ring of Deadly Power
    	3	71158	100002	1 --Hero's Medal
    	4	71135	100003	1 --Crescent Moon Ring
    	5	71136	100004	1 --Mighty Lolly
    	6	71143	100005	1 --Ring of Joy
    	7	71145	100006	1 --Amulet of Eternal Love
    	8	71188	100007	1 --Magic Lolly
    	9	71199	100008	1 --Chocolate Amulet
    	10	71202	100009	1 --Nazar Amulet
    	11	72054	100010	1 --Amulet of the Guardians
    	12	76030	100011	1 --Power Lolly
    	13	76047	100011	1 --Power Lolly (3D)
    	14	72062	100012	1 --Experience Ring +200
    	15	72062	100012	1 --Experience Ring +200
    	16	72703	100015	1 --Tiger Bone Earring
    	17	72709	100015	1 --Tiger Bone Earring
    	18	72704	100016	1 --Dragon Bone Earring
    	19	72710	100016	1 --Dragon Bone Earring
    	20	72705	100017	1 --Tiger Bone Bracelet
    	21	72711	100017	1 --Tiger Bone Bracelet
    	22	72706	100018	1 --Dragon Bone Bracelet
    	23	72712	100018	1 --Dragon Bone Bracelet
    }

    ->    3    71158    100002    1 --Hero's Medal

    Group    속성3
    {
        Vnum    100002 --
        type    ATTR --
        1    66    50 --
        2    64    30 --
        3    7    20 --
        4    9    20 --
        5    69    10 --
        6    70    10 --
        effect    d:\ymirwork\effect\etc\buff\buff_symbol1.mse --
    }

     

    • Love 1
  3. I stumbled upon a customer that had this issue today. I was not aware that you posted a solution for it almost a year ago.

    This is the full Lua workaround I used for the guy, posting it here just for the sake of doing it.

    From my functions.lua:

    Spoiler
    --[[
        Description:
            Returns an array of ASCII values representing each character in the 'str' string.
    
        Arguments:
            str (string): The string to be converted into an array of ASCII values.
    
        Example:
            string_to_ascii_array("hello") -- Returns {104, 101, 108, 108, 111}
    
        Returns:
            table: An array of ASCII values.
    
        Time complexity: O(n), where n is the length of the string.
        Space complexity: O(n), where n is the length of the string.
    ]]
    string_to_ascii_array = function(str)
        local array = {};
        local str_len = string.len(str);
        for i = 1, str_len do
            array[i] = string.byte(str, i);
        end -- for
    
        return array;
    end -- function
    
    --[[
        Description:
            Returns a string converted from an array of ASCII values.
    
        Arguments:
            array (table): The array of ASCII values to be converted into a string.
    
        Example:
            ascii_array_to_string({104, 101, 108, 108, 111}) -- Returns "hello"
    
        Returns:
            string: The string representation of the ASCII values.
    
        Time complexity: O(n), where n is the length of the array.
        Space complexity: O(n), where n is the length of the array.
    ]]
    ascii_array_to_string = function(array)
        local str = "";
        local array_len = table_get_count(array);
        for i = 1, array_len do
            str = str .. string.char(array[i]);
        end -- for
    
        return str;
    end -- function

     

    New functions:
     

    Spoiler
    set_dungeon_leader_name = function(name)
        local array = string_to_ascii_array(name);
        for index, value in ipairs(array) do
            d.setf(string.format("leader_name%d", index), value);
        end -- for
    end -- function
    
    get_dungeon_leader_name = function()
        local table_ex, i = {}, 1;
        local flag = d.getf(string.format("leader_name%d", i));
    
        while (flag and flag ~= 0) do
            table_ex[table.getn(table_ex) + 1] = flag;
            i = i + 1;
            flag = d.getf(string.format("leader_name%d", i));
        end -- while
    
        return ascii_array_to_string(table_ex);
    end -- function

     

    Usage example:

    Spoiler
    when login with Dungeon.InDungeon() begin
        pc.set_warp_location(--[[outside]]);
    
        -- Initialize the dungeon
        if (d.getf("initialized") == 0) then
            d.setf("initialized", 1);
            d.setf("start_time", get_time());
    
            d.regen_file(string.format("%s/dungeon_regen.txt", --[[regen_path]]));
            server_loop_timer("dungeon_monster_count", 2, d.get_map_index());
        end -- if
    
        -- Here we set the name of the leader.
        if (party.is_leader() or not party.is_party()) then
            d.setf("is_party_dungeon", party.is_leader() and 1 or 0);
            set_dungeon_leader_name(pc.get_name());
        end -- if
    
        notice("<Dungeon> Kill all the monsters to complete the dungeon.")
    end -- when
    
    when dungeon_monster_count.server_timer begin
        local instance_index = get_server_timer_arg();
        if (not d.select(instance_index)) then
            return;
        end -- if
    
        local data = Dungeon.GetData();
        local count_monster = d.count_monster();
        if (count_monster > 0) then
            --d.notice(string.format("Remaining monsters: %d.", count_monster));
            return;
        end -- if
    
        clear_server_timer("dungeon_monster_count", instance_index);
    
        -- Here we get the name we previously memorized for the instance.
        local leader_name = get_dungeon_leader_name();
        notice_all(string.format("[Dungeon] %s has completed `Dungeon Name`.", d.getf("is_party_dungeon") == 1 and string.format("%s's party", leader_name) or leader_name))
    end -- when

     

    You could also do this upon d.new_jump* call instead of onLogin.

    • Love 4
  4. 58 minutes ago, Juki said:
    quest collect_quest_lv30  begin
    	state start begin
    		when login or levelup with pc.level >= 30 begin
    			set_state(information)
    		end
    	end
    
    	state information begin
    		when letter begin
    			local v = find_npc_by_vnum(20084)
    			if v != 0 then
    				target.vid("__TARGET__", v, gameforge.collect_herb_lv10._150_sayTitle)
    			end
    			send_letter(gameforge.collect_quest_lv30._10_sendLetter)
    		end
    
    		when button or info begin
    			say_title(gameforge.collect_quest_lv30._10_sendLetter)
    			say(gameforge.collect_quest_lv30._20_say)
    		end
    
    		when __TARGET__.target.click or	20084.chat.gameforge.collect_quest_lv30._30_npcChat begin
    			target.delete("__TARGET__")
    			say_title(gameforge.collect_herb_lv10._50_sayTitle)
    			say(gameforge.collect_quest_lv30._40_say)
    			wait()
    			say_title(gameforge.collect_herb_lv10._50_sayTitle)
    			say(gameforge.collect_quest_lv30._50_say)
    			wait()
    			say_title(gameforge.collect_herb_lv10._150_sayTitle)
    			say(gameforge.collect_quest_lv30._60_say)
    			set_state(go_to_disciple) 
    			pc.setqf("collect_count",0)
    			pc.setqf("drink_drug",0)
    		end
    	end
    
    
    	state go_to_disciple begin
    		when letter begin
    			send_letter(gameforge.collect_quest_lv30._70_sendLetter)
    
    		end
    		when button or info begin
    			say_title(gameforge.collect_quest_lv30._80_sayTitle)
    			say(gameforge.collect_quest_lv30._90_say)
    			say_item_vnum(30006)
    			say_reward(string.format(gameforge.collect_quest_lv30._100_sayReward, pc.getqf("collect_count")))
    					end
    
    		when 71035.use begin
    			if pc.getqf("drink_drug")==1 then
    				say(gameforge.collect_quest_lv30._120_say)
    
    				return
    			end
    			if pc.count_item(30006)==0 then
    				say_title(gameforge.collect_herb_lv10._50_sayTitle)
    				say(gameforge.collect_quest_lv30._130_say)
    				return
    			end
    			pc.remove_item(71035, 1)
    			pc.setqf("drink_drug",1)
    		end
    
    		when 601.kill begin
    			local s = number(1, 100)
    			if s <= 5 then
    				pc.give_item2(30006, 1)
    			end 
    		end
    
    
        	when 20084.chat.gameforge.collect_quest_lv30._140_npcChat with pc.count_item(30006) >0   begin
    				if pc.count_item(30006) >0 then 
    				say_title(gameforge.collect_herb_lv10._150_sayTitle)
    				say(gameforge.collect_quest_lv30._150_say)
    				pc.remove_item("30006", 1)
    				wait()
    
    				local pass_percent
    				if pc.getqf("drink_drug")==0 then
    					pass_percent=60
    				else
    					if true == pet.is_summon(34003) or true == pet.is_summon(34001) then
    						pass_percent=92
    					else
    						pass_percent=90
    					end
    				end
    
    				notice(pass_percent)
    
    				local s= number(1,100)
    				if s <= pass_percent  then
    				   if pc.getqf("collect_count")< 9 then    
    						local index =pc.getqf("collect_count")+1
    						pc.setqf("collect_count",index)
    						say_title(gameforge.collect_herb_lv10._150_sayTitle)
    						say(string.format(gameforge.collect_quest_lv30._160_say, 10-pc.getqf("collect_count")))
    						pc.setqf("drink_drug",0)	
    						return
    					end
    					say_title(gameforge.collect_herb_lv10._50_sayTitle)
    					say(gameforge.collect_quest_lv30._170_say)
    					pc.setqf("collect_count",0)
    					pc.setqf("drink_drug",0)
    					set_state(key_item)
    					return
    				else
    				say_title(gameforge.collect_herb_lv10._50_sayTitle)
    				say(gameforge.collect_quest_lv30._180_say)
    				pc.setqf("drink_drug",0)	
    				return
    				end
    			else
    				say_title(gameforge.collect_herb_lv10._50_sayTitle)
    				--say(string.format(gameforge.collect_quest_lv30._190_say, item_name(30006)))
    				say(gameforge.collect_quest_lv30._190_say)
    				return
    			end
    	    else
    		  say_title(gameforge.collect_herb_lv10._50_sayTitle)
    		  say(gameforge.collect_quest_lv30._200_say)
    		  return
    		end
    
    	end
    end
    
    
    	state key_item begin
    		when letter begin
    			send_letter(gameforge.collect_quest_lv30._210_sendLetter)
    
    			if pc.count_item(30220)>0 then
    				local v = find_npc_by_vnum(20084)
    				if v != 0 then
    					target.vid("__TARGET__", v, gameforge.collect_herb_lv10._150_sayTitle)
    				end
    			end
    
    		end
    		when button or info begin
    			if pc.count_item(30220) >0 then
    				say_title(gameforge.collect_quest_lv30._220_sayTitle)
    								say_reward(gameforge.collect_quest_lv30._230_sayReward)
    								return
    			end
    			say_title(gameforge.collect_quest_lv30._220_sayTitle)
    			say(gameforge.collect_quest_lv30._240_say)
    			say_item_vnum(30220)
    			say(gameforge.collect_quest_lv30._250_say)
    		end
    
    
    
    		when 631.kill or 632.kill or 633.kill or 634.kill or 635.kill or 636.kill or 637.kill  begin
    			local s = number(1, 500)
    			if s == 1 and pc.count_item(30220)==0 then
    				pc.give_item2(30220, 1)
    				send_letter(gameforge.collect_quest_lv30._260_sendLetter)
    			end
    		end
    
    		when __TARGET__.target.click  or	20084.chat.gameforge.collect_quest_lv30._270_npcChat with pc.count_item(30220) > 0  begin
    			target.delete("__TARGET__")
    			if pc.count_item(30220) > 0 then 
    				say_title(gameforge.collect_herb_lv10._150_sayTitle)
    				say(gameforge.collect_quest_lv30._280_say)
    				pc.remove_item(30220,1)
    				set_state(__reward)
    			else
    				say_title(gameforge.collect_herb_lv10._150_sayTitle)
    				--say(string.format(gameforge.collect_quest_lv30._290_say, item_name(30220)))
    				say(gameforge.collect_quest_lv30._290_say)
    				return
    			end
    		end
    
    	end
    
    	state __reward begin
    		when letter begin
    			send_letter(gameforge.collect_quest_lv30._300_sendLetter)
    
    			local v = find_npc_by_vnum(20018)
    			if v != 0 then
    				target.vid("__TARGET__", v, gameforge.collect_quest_lv30._310_targetVid)
    			end
    
    		end
    		when button or info begin
    			say_title(gameforge.collect_quest_lv30._300_sendLetter)
    			say(gameforge.collect_quest_lv30._320_say)
    		end
    
    		when __TARGET__.target.click  or	20018.chat.gameforge.collect_quest_lv30._330_npcChat  begin
    			target.delete("__TARGET__")
    			say_title(gameforge.collect_quest_lv30._340_sayTitle)
    			say(gameforge.collect_quest_lv30._350_say)
    			say_reward(gameforge.collect_quest_lv30._360_sayReward)
    
    			affect.add_collect(apply.MOV_SPEED, 10, 60*60*24*365*60) --60Jahre
    			pc.give_item2(50109)
    			clear_letter()
    			set_quest_state("collect_quest_lv40", "run")
    			set_state(__complete)
    		end
    
    	end
    
    
    	state __giveup__ begin
    		when 20084.chat.gameforge.collect_quest_lv30._370_npcChat begin
    			say_title(gameforge.collect_herb_lv10._50_sayTitle)
    			say(gameforge.collect_quest_lv30._380_say)
    			set_state(start)
    	     end
    	 end
    	state __complete begin
    	end
    end

    so this is what i did but it doesn't seem to work...

    You either aren't compiling your stuff properly or forgot to reset the flag on your character.

    • Love 1
  5. On 2/23/2024 at 7:34 PM, Rakancito said:

    WTF??? YOU ARE WRONG!!

    • All languages has advantages and disadvantages.
    • C++ is faster than Lua.
    • Lua is easier than C++.
    • C++ has more good communication with the machine than Lua.
    • C++ has debug tools.
    • Lua is nice and good, but if you have bugs, you will need go to C++ if you want resolve the problem.
    • Memory problems are programming errors, not programming language errors, and are due to poor programming practice or lack of code review.
    • The order of the code does not equal the difficulty of understanding code (C++ is harder than Lua).
    • You can cause important errors in Lua and memory problems just like in C++

    And I can continue with disadvantages or advantages.

    If you have more Lua developers it's because Lua is more easier than C++, Lua has one syntax more easy. But if you have good practices and concepts of programming, you will have a good code and secure code.

    In my personal think, C++ has advantages because it's more fast and has one more communication with the machine than Lua, but the project will be more expensive and complicated.It is simply to the client's liking. But C++ will always be better than Lua in many ways. Only Lua is easier to learn and anyone can be a Lua developer.

    Lua has nice helps for inexpert developers and good practices for codes with small size however C++ has advantages with big codes.

    • If you have a big new bug in Lua you go to C++.
    • C++ has great tools with debug for codes. If you use a good testing techniques you will have a super-tool.

    In summary: Lua and C++ are good, but C++ is harder to learn. For this reason, although C++ is better for big code, because it's more faster and more advantages, it is avoided due to the cost it represents. Not everyone is a C++ developer.

     

    "Lua is nice and good, but if you have bugs, you might need C++ to resolve the problem"

    It's true that certain complex bugs might require C++ work (They're so rare that the only example that comes to my mind over 10 years of development is this:)

    But you just cannot use that as a matter of fact when such an occurrence is that rare. I literally cannot think of any other issue that can't be solved directly without C++ work.

     

    "You can cause important errors in Lua and memory problems just like in C++"

    No. Unless you override entire classes like pc.* by assigning them to global variables and giving them arbitrary values, that's simply not possible. And such a gigantic mistake that can STILL be fixed in the blink of an eye, you can't say the same about C++ core crashes/memory issues. We both know that solving a generic Lua error (which still lets the game run with no issues) is much simpler than solving a core crash caused by shit C++ code made by people like you who force themselves to use it when they can't just cause "C++ is cooler / harder to use".

     

    "C++ is faster than Lua"

    Yes, but that doesn't matter on Metin2, due to the game's limitations, speed is not a factor: Two dungeons written in these two languages with identical code functionality will run exactly the same way and at exactly the same pace. Thus, you're wrong, you can't apply generic logic in this case.

    Also, while C++ is known for its speed, which again, is not a factor to take into account on Metin2, Lua offers remarkable flexibility, and C++ should be used to that end: To help assemble functions useable in Lua in order to write more complex stuff while maintaining Lua's ease to update/use; that's the whole point of scripting languages and it's the reason why YMIR adopted this design, why do you think they don't make dungeon in C++? The entire quest system has been made exactly to handle such things, and it's very much stable and safe to use, not to mention easy to use, as you said, but apparently for you "easy to use = bad" (?).

    Lua's straightforward syntax and semantics allow developers to implement features quickly and with fewer lines of code -> faster development cycles -> more productivity.

    Writing something in a harder way doesn't make it better at all. I don't know you but given the message I quoted, this doesn't seem a design choice/preference on your end to me, not as much as it seems a sorry attempt to flex and feel superior.. which you failed at miserably from what I see.

    I've coded much more complex stuff than this in Lua for Metin2 during my lifetime, stuff that I'm sure you can't even fathom, (For example, do you even know what a coroutine is and how to apply it on a Metin2 quest?)

    While this.. stuff that you made, once I remove the python UIs I get one of the most basic, boring and plain dungeons ever conceived.

    Be humble, and try to learn rather than trying to put other people down when you can't even defend your own competences properly.

     

    "Only Lua is easier to learn and anyone can be a Lua developer."

    True, it's easier to learn. You might want to start learning it, given your show of C++ knowledge today.

    • Good 2
    • muscle 2
    • Love 2
  6. define WEAPON_SHOP_DEALER 9001
    define ARMOUR_SHOP_DEALER 9002
    define TINCTURE_VNUM 71047
    define SOCKETS_MAX_NUM 3
    
    quest tincture_stone_add begin
        state start begin
            function GetItemSlotsNum()
                --
            end -- function
    
            function BuildStoneListForItemType(item_type)
                --
            end -- function
    
            function GetStoneFamily(stone_vnum)
                --
            end -- function
    
            function IsStoneFamilySocketed(stone_vnum)
                --
            end -- function
    
            function BuildAvailableStoneListForItemType(item_type)
                 --
            end -- function
    
            when WEAPON_SHOP_DEALER.take or ARMOUR_SHOP_DEALER.take begin
                local npc_vnum = npc.get_race();
                say_title(string.format("%s:[ENTER]", mob_name(npc_vnum)))
    
                local item_type = item.get_type(); 
                if (npc_vnum == WEAPON_SHOP_DEALER and item_type ~= ITEM_TYPES.WEAPON) then
                    say_reward("I only accept weapons.[ENTER]")
                    return;
    
                elseif (npc_vnum == ARMOUR_SHOP_DEALER and item_type ~= ITEM_TYPES.ARMOR) then
                    say_reward("I only accept armors.[ENTER]")
                    return;
                end -- if/elseif
    
                local item_sub_type = item.get_sub_type();
                local invalid_weapon_subtypes = {
                    ITEM_SUB_TYPES.WEAPONS.ARROW,
                    ITEM_SUB_TYPES.WEAPONS.MOUNT_SPEAR,
                    ITEM_SUB_TYPES.WEAPONS.QUIVER
                };
                if (npc_vnum == WEAPON_SHOP_DEALER and table_is_in(invalid_weapon_subtypes, item_sub_type)) then
                    say_reward("I only accept valid weapons.[ENTER]")
                    return;
    
                elseif (npc_vnum == ARMOUR_SHOP_DEALER and item_sub_type ~= ITEM_SUB_TYPES.ARMORS.BODY) then
                    say_reward("I only accept valid armors.[ENTER]")
                    return;
                end -- if/elseif
    
                if (pc.count_item(TINCTURE_VNUM) == 0) then
                    say_reward("You require:")
                    say_item_vnum(TINCTURE_VNUM);
                    return;
                end -- if
    
                local slots_num = tincture_stone_add.GetItemSlotsNum();
                if (slots_num == 0) then
                    say_reward("This item can't be socketed.[ENTER]")
                    return;
                end -- if
    
                say(string.format("This item has %d possible slot%s.[ENTER]", slots_num, (slots_num > 1 and "s" or "")))
                local available_socket_ids, socket_vnum = {}, -1;
                for socket_id = 0, slots_num-1 do
                    socket_vnum = item.get_socket(socket_id);
                    if (socket_vnum > 1) then
                        color_say("lightgreen", string.format("Slot n.%d: %s;", socket_id + 1, item_name(socket_vnum)))
                    else
                        say_reward(string.format("Slot n.%d: No stone;", socket_id + 1))
                        table.insert(available_socket_ids, socket_id);
                    end -- if/else
                end -- for
    
                if (table.getn(available_socket_ids) == 0) then
                    say_reward("[ENTER]There's already a stone in every available socket.[ENTER]")
                    return;
                end -- if
    
                local available_stones_vnums = tincture_stone_add.BuildAvailableStoneListForItemType(item_type);
                if (table.getn(available_stones_vnums) == 0) then
                    say_reward("[ENTER]You don't have any stone I can socket in.[ENTER]")
                    return;
                end -- if
    
                say("[ENTER]Which stone do you want to add?")
                local available_stones_names = {};
                table.foreach(available_stones_vnums,
                    function(_, stone_vnum)
                        table.insert(available_stones_names, item_name(stone_vnum));
                    end -- function
                );
                table.insert(available_stones_names, "Abort");
    
                -- Window length management
                local available_stones_num = table.getn(available_stones_names);
                if (available_stones_num > 3) then
                    say_size(350, 300 + 27 * math.min(5, available_stones_num - SOCKETS_MAX_NUM))
                else
                    say("")
                end -- if/else
    
                local selected_stone = select_table(available_stones_names);
                if (selected_stone == table.getn(available_stones_names)) then
                    return;
                end -- if
    
                pc.remove_item(TINCTURE_VNUM, 1);
    
                local selected_stone_vnum = available_stones_vnums[selected_stone];
                pc.remove_item(selected_stone_vnum, 1);
                item.set_socket(available_socket_ids[1], selected_stone_vnum);
            end -- when
        end -- state
    end -- quest

    This is an old quest I wrote. In order for the logic to work, the socket of index 0 must work.. and it does even on traditional kraizy files.

    Are you sure this error is a thing? I'm pretty sure (although I didn't check) that some official quests also use that very same instruction.

    • Metin2 Dev 1
    • Think 1
  7. 24/01/2024 (last update):

    1. The func 'is_valid_number' now has an "allow_zero" arg. and default values.
    2. Added 'count_digits(num)'.
    3. Added 'get_nth_digit(num, index)'.
    4. Added 'generate_num_array(limit)'.
    5. Added 'get_time_after_seconds(sec)'.
    6. Added 'mirror_shuffle(original_table, shuffled_table, target_table)'
    7. Renamed BuildSkillList to BuildSkillList2 in order to avoid conflicts with the default func from ymir.

    it's been fun.

    • Metin2 Dev 1
    • Sad 1
    • Good 1
  8.  

    13 hours ago, shenhui1986 said:


    questlua_pc.cpp: In function 'int quest::pc_in_dungeon(lua_State*)':
    questlua_pc.cpp:277:31: error: invalid use of incomplete type 'class CDungeon'
      277 |     ret = (mapIndex == dungeon->GetOriginalMapIndex());
          |                               ^~
    In file included from stdafx.h:57,
                     from questlua_pc.cpp:1:
    typedef.h:78:7: note: forward declaration of 'class CDungeon'
       78 | class CDungeon;
          |       ^~~~~~~~
    gmake: *** [Makefile:171: .obj/questlua_pc.o] Error 1

     

     

     

    This is the solution

    #include "dungeon.h" 

     

    in questlua_pc.cpp

    Bro.

    You don't need a C++ function for such a thing.

    InDungeon = function(map_index)
        local pc_index = pc.get_map_index();
        return
            pc.in_dungeon() and
            pc_index >= ToDungeonIndex(map_index) and
            pc_index < ToDungeonIndex(map_index+1);
    end -- function
    when MOB_VNUM.kill with InDungeon(DUNGEON_MAP_INDEX) begin

     

    • Love 1
  9. Mh, doable but unpractical, and also bad from a technical point of view.

    The way dungeon instances work is by creating an instanced version of the target map and then warping to it. 

    Now, you're doing it wrong obviously, but even if you were doing it the right way.. this process requires the target's map to be in the same core of the map from which you try and enter the dungeon.

    Meaning either you place ALL the maps in your server in a single core, so you can enter any dungeon from any map, or this is just a bad idea; and I don't think I need to explain why placing all the server's maps in a single core is not good practice.

    Given how easy this is to do, the fact that no server decided to apply this approach even with all the QoLs implemented over the years speaks volumes.

    • Good 1
  10. 17 minutes ago, Lycawn said:

    Actually tested , works for me 

    Regens in Metin2 works with a constant global timer, meaning they use a single timer to check the state of every mob/group, and respawn it if it's dead, starting from the time when the server has been last restarted. They don't initialize a respawn timer for each dead mob/group.

    Let's say your last restart was at 12:00, and you have a boss that respawns once every 4 hours, and it has gets killed at 15:00

    You would think it respawns at 19:00, but it actually will respawn at 16:00, because it checks for it once every 4 hours starting from server start time, not mob death time. If you were to kill it at 15:59, it will respawn exactly one minute later.

    You can't really say "it works for me", you just didn't test it enough and have no idea how it works, which is fine.

    • Not Good 1
    • Good 1
  11. 26/09/2023:

    1. Added num_to_char(num).
    2. Added char_to_num(string).
    3. Added string_to_ascii_array(string).
    4. Added ascii_array_to_string(table).
    5. Added skill_level_to_id(num).
    6. Added skill_id_to_level(string).
    7. Added time_to_sec(num, string). (Kept the old functions as wrapper funcs for backwards compatibility)
    • Metin2 Dev 1
    • Love 1
  12. 13 hours ago, AndreiS said:

    Is any good this solution ?

    No. You're effectively changing how the skill works instead of fixing the issue (which I still don't get what it even is)

×
×
  • 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.