Jump to content

caanmasu

Banned
  • Posts

    90
  • Joined

  • Last visited

  • Feedback

    0%

Posts posted by caanmasu

  1. I did this quest a while ago

    item_proto.txt
    vnum 70038
    item_type ITEM_QUEST or 18

     

    auto_cape.quest
     

    define VNUM_CAPE 70038
    
    quest auto_cape begin
    	state start begin
    	
    		function capeAction()
    			pc.aggregate_monster()
    			pc.changegold(-1000)
    		end
    	
    		when VNUM_CAPE.use begin
    			if pc.getqf("wait_time") < get_time() then
    				if item.get_socket(0) == 0 then
    					item.set_socket(0, 1)
    					pc.setqf("wait_time", get_time()+3)
    					pc.setqf("cell_item", item.get_cell())
    					auto_cape.capeAction()
    					loop_timer("lt_autocape", 3)
    				else
    					item.set_socket(0, 0)
    					cleartimer("lt_autocape")
    				end
    			else
    				syschat("Espera un momento")
    			end
    		end
    		when lt_autocape.timer begin
    			auto_cape.capeAction()
    		end
    		when login begin
    			if item.select_cell(pc.getqf("cell_item")) then
    				if item.vnum == VNUM_CAPE and item.get_socket(0) == 1 then
    					auto_cape.capeAction()
    					loop_timer("lt_autocape", 3)
    				end
    			end
    		end
    		when die begin
    			if item.select_cell(pc.getqf("cell_item")) then
    				if item.vnum == VNUM_CAPE and item.get_socket(0) == 1 then
    					item.set_socket(0, 0)
    					cleartimer("lt_autocape")
    				end
    			end
    		end
    	end
    end

     

    Activate/Deactivate slot:
    root/constInfo.py
     

    def IS_AUTO_POTION_HP(itemVnum):
    	if 72723 <= itemVnum and 72726 >= itemVnum:
    		return 1
    	elif itemVnum >= 76021 and itemVnum <= 76022:
    		return 1
    	elif itemVnum == 79012:
    		return 1
    	#ADD THIS
    	elif itemVnum == 70038:
    		return 1
    	#
    
    	return 0



     

  2. 3 hours ago, UrsuPolar said:

    I thought you can skip the mission if you ignore it and after you would have leveled up to 41 it would have disappeard by itself.

    Solution:

    Find:

    state information begin

    Add below:

    when login or levelup with not (pc.level >=30 and pc.level <=40) begin
    	clear_letter()
    	restart_quest()
    end

     

    • Good 1
  3. Hi

     

    You must keep in mind that the fast loading is one thing and the backgroundless image is another, even if they come from the same system.
    This time I will tell you how to make the backgroundless image at login. I can't share you the playersettingmodule by binary because all the "systems" are premium.

    1. Remove the stuff related to the loading image and loading bar:
    2. Change the script path

    Let's begin.


    root/introloading.py

    1.

    class LoadingWindow(ui.ScriptWindow):
        def __init__(self, stream):
            print "NEW LOADING WINDOW -------------------------------------------------------------------------------"
            ui.Window.__init__(self)
            net.SetPhaseWindow(net.PHASE_WINDOW_LOAD, self)
    
            self.stream=stream
            #self.loadingImage=0 #comment this line
            #self.loadingGage=0 #comment this line
            self.errMsg=0
            self.update=0
            self.playerX=0
            self.playerY=0
            self.loadStepList=[]

    2.

        def Open(self):
            print "OPEN LOADING WINDOW -------------------------------------------------------------------------------"
    
            #app.HideCursor()
    
            try:
                pyScrLoader = ui.PythonScriptLoader()
    
                if localeInfo.IsYMIR() or localeInfo.IsWE_KOREA() or localeInfo.IsCANADA() or localeInfo.IsBRAZIL() or localeInfo.IsEUROPE() or localeInfo.IsJAPAN():
                    #pyScrLoader.LoadScriptFile(self, uiScriptLocale.LOCALE_UISCRIPT_PATH + "LoadingWindow.py") #comment this line. This path is locale/common/ui
                    pyScrLoader.LoadScriptFile(self, uiScriptLocale.LOCALE_UISCRIPT_PATH + "NewLoadingWindow.py") #add this line
                else:
                    pyScrLoader.LoadScriptFile(self, "UIScript/LoadingWindow.py")
            except:
                import exception
                exception.Abort("LodingWindow.Open - LoadScriptFile Error")
    
            try:
                #self.loadingImage=self.GetChild("BackGround") #comment this line
                self.errMsg=self.GetChild("ErrorMessage")
                #self.loadingGage=self.GetChild("FullGage") #comment this line
            except:
                import exception
                exception.Abort("LodingWindow.Open - LoadScriptFile Error")

    3.

        def Close(self):
            print "---------------------------------------------------------------------------- CLOSE LOADING WINDOW"
    
            app.SetFrameSkip(1)
    
            self.loadStepList=[]
            #self.loadingImage=0 #comment this line
            #self.loadingGage=0 #comment this line
            self.errMsg=0
            self.ClearDictionary()
            self.Hide()

    4.

        #comment this method
        #def __SetProgress(self, p):
        #    if self.loadingGage:
        #        self.loadingGage.SetPercentage(2+98*p/100, 100)


        
    5.

                (98, ui.__mem_func__(self.__LoadGuildBuilding)),
                # END_OF_GUILD_BUILDING
    
                (100, ui.__mem_func__(self.__StartGame)),
            ]
            if app.ENABLE_WOLFMAN_CHARACTER:
                self.loadStepList+=[(100, ui.__mem_func__(self.__LoadWolfman)),]
    
            #self.__SetProgress(0) #comment this line
            #self.__SetNext(self.__LoadMap)
    
        def OnUpdate(self):

    5.

                self.loadStepList.pop(0)
    
                #self.__SetProgress(progress) #comment this line
    
        def __InitData(self):
            playerSettingModule.LoadGameData("INIT")

    Finally, we are going to remove the transparency of the loading window.

    Every time the client changes phase, for example, from the character change phase to the login phase, the window will be completely black because the alpha value (transparency) is equal to 1. We must change the value to 0.

    root/uiphasecurtain.py

        def OnUpdate(self):
    
            if 0 != self.event:
    
                self.curAlpha += self.speed
                if self.curAlpha >= 1.0: #change value to 0.0
                    self.curAlpha = 1.0 #change value to 0.0
    
                    event=self.event
                    self.event = 0
    
    
                    if -1 != self.args:
                        event(self.args)
                    else:
                        event()


                        

    Put newloadingwindow.py in locale/common/ui, then put images in d:/ymir work/ui/game/new_loading/

    Files: 

    This is the hidden content, please


     

    • Metin2 Dev 6
    • Not Good 1
    • Good 1
    • Love 1
    • Love 4
  4. Hi

     

    Bug fix by me

     

    Before fix: https://metin2.download/video/FHN62NXpd74c1pLqPt5PJDX7IBs5r2vA/.mp4

    After fix: https://metin2.download/video/NguTHfen88bFnAuP6JZ5fIMiiLoeSgRm/.mp4

     

    Fix:

     

    char_state.cpp


    Comment this line:
     

    f.m_pkChrFind->AddAffect(AFFECT_WAR_FLAG, POINT_MOV_SPEED, 50 - f.m_pkChrFind->GetPoint(POINT_MOV_SPEED), 0, INFINITE_AFFECT_DURATION, 0, false);

    Add below:

    f.m_pkChrFind->UpdatePacket();

     

    Like this:

    	if (!pMap->GetTeamIndex(GetPoint(POINT_STAT), idx))
    		return;
    
    	f.m_pkChrFind->AddAffect(AFFECT_WAR_FLAG, POINT_NONE, GetPoint(POINT_STAT), idx == 0 ? AFF_WAR_FLAG1 : AFF_WAR_FLAG2, INFINITE_AFFECT_DURATION, 0, false);
    	//f.m_pkChrFind->AddAffect(AFFECT_WAR_FLAG, POINT_MOV_SPEED, 50 - f.m_pkChrFind->GetPoint(POINT_MOV_SPEED), 0, INFINITE_AFFECT_DURATION, 0, false); //fix
    	f.m_pkChrFind->UpdatePacket();  //fix
    
    	pMap->RemoveFlag(idx);

     

    char.cpp

    Find:

    		case POINT_MOV_SPEED:
    			min_limit = 0;
    
    			if (IsPC())
    				limit = 200;
    			else
    				limit = 250;

    Add below:

    			if (FindAffect(AFFECT_WAR_FLAG))
    				limit = 50;

     

    Like this:

    		case POINT_MOV_SPEED:
    			min_limit = 0;
    
    			if (IsPC())
    				limit = 200;
    			else
    				limit = 250;
    			if (FindAffect(AFFECT_WAR_FLAG))
    				limit = 50;
    			break;

     

     

    • Metin2 Dev 3
    • Good 1
    • Love 5
  5. 2 hours ago, Erexo said:

    Is it possible to make command for gm? Like /create_arena name1 name2? And it will teleport players and gm to arena? 

     

    I make this code (NO TESTED) as guide.

     

    This may be the beginning of what you want to do. Does not include the observer mode part.

     

    cmd_gm.cpp

    ACMD(do_start_arena)
    {
    	char arg1[256], arg2[256];
    	two_arguments(argument, arg1, sizeof(arg1), arg2, sizeof(arg2));
    
    	if (!*arg1 && !*arg2)
    	{
    		ch->ChatPacket(CHAT_TYPE_INFO, "Usage: start_arena <name1> <name2>");
    		return;
    	}
    
    	LPCHARACTER ch1 = CHARACTER_MANAGER::instance().FindPC(arg1);
    	LPCHARACTER ch2 = CHARACTER_MANAGER::instance().FindPC(arg2);
    	if (!ch1 || !ch2)
    	{
    		ch->ChatPacket(CHAT_TYPE_INFO, "At least one player is offline.");
    		return;
    	}
    	
    	if ( CArenaManager::instance().IsMember(ch1->GetMapIndex(), ch1->GetPlayerID()) != MEMBER_NO ||
    			CArenaManager::instance().IsMember(ch2->GetMapIndex(), ch2->GetPlayerID()) != MEMBER_NO	)
    	{
    		ch->ChatPacket(CHAT_TYPE_INFO, "At least one player is on arena.");
    		return;
    	}
    	
    	if (!(ch1->GetArena()) || ch1->GetArenaObserverMode())
    	{
    		if (CArenaManager::instance().IsMember(ch1->GetMapIndex(), ch1->GetPlayerID()) == MEMBER_DUELIST)
    		{
    			ch->ChatPacket(CHAT_TYPE_INFO, "At least one player is on arena.");
    			return;
    		}
    	}
    	
    	if (!(ch2->GetArena()) || ch2->GetArenaObserverMode())
    	{
    		if (CArenaManager::instance().IsMember(ch2->GetMapIndex(), ch2->GetPlayerID()) == MEMBER_DUELIST)
    		{
    			ch->ChatPacket(CHAT_TYPE_INFO, "At least one player is on arena.");
    			return;
    		}
    	}
    	
    	if (ch1->IsHorseRiding())
    	{
    		ch1->StopRiding();
    		ch1->HorseSummon(false);
    	}
    
    	if (ch2->IsHorseRiding())
    	{
    		ch2->StopRiding();
    		ch2->HorseSummon(false);
    	}
    	
    	if (!(CArenaManager::instance().StartDuel(ch1, ch2, 3)))
    	{
    		ch->ChatPacket(CHAT_TYPE_INFO, "An error has occurred");
    		return;
    	}
    }

     

    • Love 1
  6. Hi


    Demostration: https://metin2.download/video/3lPDNkFwv4KaL4T2u9ClI0xfmfD0oZ0U/.mp4

     

    Important: Do these tests without people in the game.


    Inputs:

    You must enter the average and the desired skill. The cycle ends when a greater or equal average or skill has been found.
    If you just want to find average, enter the value of your average, and an unlikely skill value.
    If you just want to find skill, enter the value of your skill, and an average improbable value.

    Example:

    I just want to find 60 on average:
    Average input: 60
    Skill input: 100

    I just want to find 28 skill:
    Average input: 100
    Skill input: 28

    I want to find 60 average or 28 skill:
    Average input: 60
    Skill input: 28




    Implementation:
     

    questlua_global.cpp

    1. 
    Add anywhere:
     

    	ALUA(_skill_mean) //return success, skill, mean, switches
    	{
    		if( !lua_isnumber(L, 1) || !lua_isnumber(L, 2) || !lua_isnumber(L, 3)) //skill, mean, switches
    			return 0;
    		
    		int skill_need = lua_tonumber(L, 1);
    		int mean_need = lua_tonumber(L, 2);
    		int count = lua_tonumber(L, 3);
    		
    		int switches = 0;
    		int new_skill = 0;
    		int new_mean = 0;
    		
    		for (int i = 0; i < count; i++)
    		{
    			int iSkillBonus = MINMAX(-30, (int) (gauss_random(0, 5) + 0.5f), 30);
    			int iNormalHitBonus = 0;
    			if (abs(iSkillBonus) <= 20)
    				iNormalHitBonus = -2 * iSkillBonus + abs(number(-8, 8) + number(-8, 8)) + number(1, 4);
    			else
    				iNormalHitBonus = -2 * iSkillBonus + number(1, 5);
    			switches = i+1;
    			new_skill = iSkillBonus;
    			new_mean = iNormalHitBonus;
    			if (iSkillBonus >= skill_need || iNormalHitBonus >= mean_need)
    			{
    				lua_pushboolean(L, true);
    				lua_pushnumber(L, new_skill);
    				lua_pushnumber(L, new_mean);
    				lua_pushnumber(L, switches);
    				return 4;
    			}
    		}
    		lua_pushboolean(L, false);
    		lua_pushnumber(L, new_skill);
    		lua_pushnumber(L, new_mean);
    		lua_pushnumber(L, switches);
    		return 4;
    	}

    2. Above of:

    			{	NULL,	NULL	}

    Add:

    			{	"get_skill_mean", 				_skill_mean					},


    meanskill_simulator.quest

    quest meanskill_simulator begin
    	state start begin
    		when letter with pc.is_gm() begin
    			send_letter("Mean Skill simulator")
    		end
    		
    		when button or info begin
    			meanskill_simulator.dialog()
    			while true do
    				if select("Again", "Close") == 2 then
    					return
    				end
    				meanskill_simulator.dialog()
    			end
    		end
    		
    		function dialog()
    			local max_switches = 1000000
    			say("Mean:")
    			local mean = tonumber(input())
    			say("Skill:")
    			local skill = tonumber(input())
    			local success, new_skill, new_mean, switches = get_skill_mean(skill, mean, max_switches)
    			if success then
    				say(" Success: ")
    			else
    				say("Fail: ")
    			end
    			say("Mean: "..new_mean)
    			say("Skill: "..new_skill)
    			say("Switches: "..numtomoney(switches))
    		end
    	end
    end

     

    • Metin2 Dev 1
  7. Hi

     

    This feature allows you to make an arena with a player from the target, not just from the NPC.
    The position of where they start the battle is also saved so that they return to the same place and not always next to Yu-Hwan.

    The code communicates quest/lua with client (python), and server (C++) with quest.

     

    GIF:

    https://metin2.download/video/XKptZ6CY5jnSnp6v1F5yr04Dq6XxHWnw/.mp4

     

    Feature created by Camilo (caanmasu)
    
    https://i.gyazo.com/d0859862714c81271a8cfeca3071d5d1.mp4
    
    This feature allows you to make an arena with a player from the target, not just from the NPC.
    The position of where they start the battle is also saved so that they return to the same place and not always next to Yu-Hwan.
    
    The code communicates quest/lua with Python, and server (C++) with quest.
    
    
    Clientside
    
    root:
    
    constinfo.py
    
    ENABLE_ARENA_MANAGER_TARGET = True
    if ENABLE_ARENA_MANAGER_TARGET:
    	QUEST_arena_manager_INDEX = 0
    	QUEST_arena_manager_TARGET = 0
    
    game.py
    
    1:
    Above:
    
    		self.serverCommander=stringCommander.Analyzer()
    		
    Add:
    
    		if constInfo.ENABLE_ARENA_MANAGER_TARGET:
    			serverCommandList.update({"StartArenaManager" : self.QUEST_arena_manager})
    			serverCommandList.update({"GetTargetArenaManager" : self.QUEST_get_target_arena_manager})
    			
    2:
    Add this functions:
    
    	if constInfo.ENABLE_ARENA_MANAGER_TARGET:
    		def QUEST_arena_manager(self, quest_index):
    			constInfo.QUEST_arena_manager_INDEX = quest_index
    
    		def QUEST_get_target_arena_manager(self):
    			net.SendQuestInputStringPacket(str(constInfo.QUEST_arena_manager_TARGET))
    
    uitarget.py
    
    1:
    
    import event
    
    2:
    
    Above:
    
    GRADE_NAME =	{
    
    Add:
    
    	if constInfo.ENABLE_ARENA_MANAGER_TARGET:
    		BUTTON_NAME_LIST.append(localeInfo.TARGET_BUTTON_ARENA_MANAGER)
    		
    3:
    
    Above:
    
    		self.buttonDict["VOTE_BLOCK_CHAT"].SetEvent(ui.__mem_func__(self.__OnVoteBlockChat))
    
    Add:
    
    		if constInfo.ENABLE_ARENA_MANAGER_TARGET:
    			self.buttonDict[localeInfo.TARGET_BUTTON_ARENA_MANAGER].SAFE_SetEvent(self.__OnArena)
    			
    4:
    
    Above:
    
    		if player.IsPartyMember(self.vid):
    		
    Add:
    
    		if constInfo.ENABLE_ARENA_MANAGER_TARGET:
    			if player.GetStatus(player.LEVEL) >= constInfo.PVPMODE_PROTECTED_LEVEL:
    				self.__ShowButton(localeInfo.TARGET_BUTTON_ARENA_MANAGER)
    
    5:
    
    Add this function:
    
    	if constInfo.ENABLE_ARENA_MANAGER_TARGET:
    		def __OnArena(self):
    			constInfo.QUEST_arena_manager_TARGET = chr.GetNameByVID(self.vid)
    			event.QuestButtonClick(int(constInfo.QUEST_arena_manager_INDEX))
    
    
    locale_game.txt
    
    TARGET_BUTTON_ARENA_MANAGER	Arena
    
    
    If you do not have input ignore, then do it:
    
    
    constinfo.py
    
    Add anywhere:
    
    INPUT_IGNORE = 0
    
    game.py
    
    1:
    
    Find this function:
    
    	def OpenQuestWindow(self, skin, idx):
    		self.interface.OpenQuestWindow(skin, idx)
    
    Replace for:
    
    	def OpenQuestWindow(self, skin, idx):
    		if constInfo.INPUT_IGNORE == 1:
    			return
    		else:
    			self.interface.OpenQuestWindow(skin, idx)
    			
    2:
    
    Below of:
    
    			# PRIVATE_SHOP_PRICE_LIST
    			"MyShopPriceList"		: self.__PrivateShop_PriceList,
    			# END_OF_PRIVATE_SHOP_PRICE_LIST
    			
    Add:
    
    			"quest_input_ignore"		: self.questInputIgnore,
    			
    Add this function:
    
    	def questInputIgnore(self, var):
    		constInfo.INPUT_IGNORE = int(var)
    		
    interfacemondule.py
    
    Find:
    
    	def OpenQuestWindow(self, skin, idx):
    		wnds = ()
    		
    Replace for:
    
    	def OpenQuestWindow(self, skin, idx):
    		if constInfo.INPUT_IGNORE == 1:
    			return
    		else:
    			wnds = ()
    			
    
    Quest:
    
    arena_manager.cpp
    
    1:
    Add those when:
    
    		when login begin
    			cmdchat(string.format("StartArenaManager %s", q.currentquestindex()))
    		end
    		
    		when logout begin --
    			if pc.get_map_index() == 112 then
    				pc.delqf("saved_x")
    				pc.delqf("saved_y")
    			end
    		end
    		
    		when button begin
    		
    			--clientside related
    			cmdchat("quest_input_ignore 1") --Note: If you set my input_ignore then this is correct. If you already had your own input_ignore, put the correct command.
    			local victim_name = input(cmdchat("GetTargetArenaManager"))
    			cmdchat("quest_input_ignore 0")
    			--
    			
    			if game.get_event_flag("arena_close") > 0 then
    				say(gameforge.arena_manager._30_say) --token 42
    				return
    			end
    			
    			local useMinLevel = game.get_event_flag("arena_use_min_level")
    
    			if useMinLevel == 0 then
    				useMinLevel = 25 ;
    			end
    
    			if pc.get_level() < useMinLevel then
    				say(string.format(gameforge.arena_manager._50_say, useMinLevel)) --token 44
    				return
    			else
    				local sname = victim_name
    				local opp_vid = find_pc_by_name(sname)
    				local old = pc.select(opp_vid , opp_vid)
    				local opp_level = pc.level
    				-- Save the position (opponent) from where the arena was started
    				pc.setf("arena_manager", "saved_x", pc.x) --BUG FIXED: si no se especifica el nombre de la quest, se tomará la quest del id anterior (la quest que se compiló antes de ésta en el quest_list)
    				pc.setf("arena_manager", "saved_y", pc.y) --
    				pc.select(old, old)
    				if opp_level < useMinLevel then
    					say(string.format(gameforge.arena_manager._110_say, useMinLevel)) --token 28
    					return
    				end
    
    				local a = arena.is_in_arena(opp_vid)
    				if a == 0 then
    					say_reward(string.format(gameforge.arena_manager._130_say, sname)) --token 30
    					return
    				end
    				chat(string.format(gameforge.arena_manager._85_say, pc.name, sname)) --token 48
    				local agree = confirm(opp_vid, string.format(gameforge.arena_manager._87_say, sname, pc.name), 30) --token 49 (text very long)
    				if agree!= CONFIRM_OK then
    					say(string.format(gameforge.arena_manager._150_say, sname)) --token 32
    					return
    				end
    				-- Save the position (current player) from where the arena was started
    				pc.setqf("saved_x", pc.x) --
    				pc.setqf("saved_y", pc.y) --
    				local s = arena.start_duel(sname, 3)
    				if s == 0 then
    					say(gameforge.arena_manager._160_say) --token 33
    				elseif s == 2 then
    					say(gameforge.arena_manager._170_say) --token 34
    				elseif s == 3 then
    					say(gameforge.arena_manager._180_say) --token 35
    				end
    			end
    		end
    		
    2:
    
    Find:
    
    				if table.getn(arena_observer) >= s then
    
    Add:
    
    				-- Save the position (observer player) from where the arena was started
    					pc.setqf("saved_x", pc.x) --
    					pc.setqf("saved_y", pc.y) --
    					
    					
    Serverside
    
    arena.cpp
    
    1. 
    
    Find:
    
    	LPCHARACTER playerB = GetPlayerB();
    	
    Add:
    
    	quest::PC* pPC_A = quest::CQuestManager::instance().GetPC(playerA->GetPlayerID());
    	quest::PC* pPC_B = quest::CQuestManager::instance().GetPC(playerB->GetPlayerID());
    
    	int saved_A_x = pPC_A->GetFlag("arena_manager.saved_x");
    	int saved_A_y = pPC_A->GetFlag("arena_manager.saved_y");
    
    	int saved_B_x = pPC_B->GetFlag("arena_manager.saved_x");
    	int saved_B_y = pPC_B->GetFlag("arena_manager.saved_y");
    
    2: 
    
    Find:
    
    		playerA->WarpSet(ARENA_RETURN_POINT_X(playerA->GetEmpire()), ARENA_RETURN_POINT_Y(playerA->GetEmpire()));
    
    Replace for:
    
    		if (saved_A_x != 0 && saved_A_y != 0)
    			playerA->WarpSet(saved_A_x*100, saved_A_y*100);
    		else
    			playerA->WarpSet(ARENA_RETURN_POINT_X(playerA->GetEmpire()), ARENA_RETURN_POINT_Y(playerA->GetEmpire()));
    			
    3:
    
    Find:
    
    	playerB->WarpSet(ARENA_RETURN_POINT_X(playerB->GetEmpire()), ARENA_RETURN_POINT_Y(playerB->GetEmpire()));
    
    Replace for:
    
    		if (saved_B_x != 0 && saved_B_y != 0)
    			playerB->WarpSet(saved_B_x*100, saved_B_y*100);
    		else
    			playerB->WarpSet(ARENA_RETURN_POINT_X(playerB->GetEmpire()), ARENA_RETURN_POINT_Y(playerB->GetEmpire()));
    			
    4:
    
    Find:
    
    		LPCHARACTER pChar = CHARACTER_MANAGER::instance().FindByPID(iter->first);
    		if (pChar != NULL)
    		{
    			pChar->WarpSet(ARENA_RETURN_POINT_X(pChar->GetEmpire()), ARENA_RETURN_POINT_Y(pChar->GetEmpire()));
    		}
    		
    Replace for:
    
    		LPCHARACTER pChar = CHARACTER_MANAGER::instance().FindByPID(iter->first);
    		if (pChar != NULL)
    		{
    			
    			quest::PC* pPC = quest::CQuestManager::instance().GetPC(pChar->GetPlayerID());
    			
    			int saved_x = pPC->GetFlag("arena_manager.saved_x");
    			int saved_y = pPC->GetFlag("arena_manager.saved_y");
    			if (saved_x != 0 && saved_y != 0)
    				pChar->WarpSet(saved_x*100, saved_y*100);
    			else
    				pChar->WarpSet(ARENA_RETURN_POINT_X(pChar->GetEmpire()), ARENA_RETURN_POINT_Y(pChar->GetEmpire()));
    		}


     

    Regards.

    • Metin2 Dev 2
    • Lmao 1
    • Good 1
  8. Check UniversalDung_LIB.data and configure it
    Make a file data/dungeon/universaldung/regen.txt, etc.

    It is the first time that I use this way of programming, I hope it is understood.

    UniversalDung_LIB.lua

    UniversalDung_LIB = {}
    
    UniversalDung_LIB.data = {
    	map_index_in = 43, --map dungeon index
    	map_index_out = {41, {9696, 2784}}, --index and cords (global) from where you enter the dung
    	base_cord = {8192, 2048}, --dung map base global coordinates (Setting.txt)
    	need_level = {100, 120}, --minimum and maximum level to enter
    	need_item = {27001, 1}, --object and count to enter. Comment: deactivate
    	wait_time_exit = 60, --time for me to get you out of the dung when I finish it
    	wait_duration = 60*10, --waiting time to re-enter
    	maxlife_dungeon = 60*30, --max duration dung
    	
    	floors = {
    		[1] = {
    			jump_cord = {872, 166},
    			regen_path = {
    				{"data/dungeon/universaldung/regen.txt", false}, --2° param is set_regen_file = true, regen_file = false
    			}
    		},
    		[2] = {
    			jump_cord = {370, 833},
    			regen_path = {
    				{"data/dungeon/universaldung/stone.txt", false},
    			}
    		},
    		[3] = {
    			jump_cord = {507, 859},
    			regen_path = {
    				{"data/dungeon/universaldung/boss.txt", false},
    				{"data/dungeon/universaldung/regen.txt", true},
    			},
    			boss_vnum = 591,
    		},
    	}
    }
    
    UniversalDung_LIB.checkEnter = function()
    	local data = UniversalDung_LIB.data
    	if party.is_party() then
    		local t_need_level, b_need_level = {}, true
    		local t_need_item, b_need_item = {}, true
    		
    		for _, pid in ipairs({party.get_member_pids()}) do
    			q.begin_other_pc_block(pid)
    				if pc.level < data.need_level[1] or pc.level > data.need_level[2] then
    					table.insert(t_need_level, pc.get_name())
    					b_need_level = false
    				end
    				if data.need_item then
    					if pc.count_item(data.need_item[1]) < data.need_item[2] then
    						table.insert(t_need_item, pc.get_name())
    						b_need_item = false
    					end
    				end
    			q.end_other_pc_block()
    		end
    
    		if not party.is_leader() then
    			say("You must be the leader of the group.")
    			return false
    		elseif party.is_in_dungeon() then
    			say("Your party has already entered the dungeon. ")
    			return false
    		elseif not party.is_map_member_flag_lt("last_exit_time", get_time()-data.wait_duration) then
    			say_reward("There are some members of the group[ENTER] who still have to wait.")
    			return false
    		elseif party.get_near_count() != table.getn({party.get_member_pids()}) then
    			say_reward("All group members must be meet.")
    			party.chat("All group members must be meet..")
    			return false
    		end
    		
    		if not b_need_level then
    			say(string.format("These players do not meet the[ENTER]level (%s-%s)", data.need_level[1], data.need_level[2]))
    			for _, name in next, t_need_level, nil do
    				say(string.format("-> %s", name))
    			end
    			return false
    		end
    		if data.need_item then
    			if not b_need_item then
    				say(string.format("These players haven't item[ENTER]x%s %s", item_name(data.need_item[1]), data.need_item[2]))
    				for _, name in next, t_need_item, nil do
    					say(string.format("-> %s", name))
    				end
    				return false
    			end
    		end
    	else
    		if pc.level > data.need_level[2] or pc.level < data.need_level[1] then
    			say(string.format("You do not meet the level (%s-%s)", data.need_level[1], data.need_level[2]))
    			return false
    		end
    		if data.need_item then
    			if pc.count_item(data.need_item[1]) < data.need_item[2] then
    				say(string.format("You don't have x%s %s", data.need_item[2], item_name(data.need_item[1])))
    				return false
    			end
    		end
    	end
    	return true
    end
    
    UniversalDung_LIB.isInDungeon = function()
    	local my_map_index, inside_index = pc.get_map_index(), UniversalDung_LIB.data.map_index_in
    	return pc.in_dungeon() and my_map_index >= inside_index*10000 and my_map_index < (inside_index+1)*10000
    end
    
    UniversalDung_LIB.isInMapOut = function()
    	return pc.get_map_index() == UniversalDung_LIB.data.map_index_out[1]
    end
    
    UniversalDung_LIB.createDungeon = function()
    	local data = UniversalDung_LIB.data
    
    	local dung_floor = 1
    
    	if party.is_party() then
    		if data.need_item then
    			local pids = {party.get_member_pids()}
    			for i, pid in next, pids, nil do
    				q.begin_other_pc_block(pid)
    				pc.remove_item(data.need_item[1], data.need_item[2])
    				q.end_other_pc_block()
    			end
    		end
    		d.new_jump_party(data.map_index_in, 
    			data.base_cord[1]+data.floors[dung_floor].jump_cord[1],
    			data.base_cord[2]+data.floors[dung_floor].jump_cord[2]
    		)
    	else
    		d.new_jump(data.map_index_in, 
    			(data.base_cord[1]+data.floors[dung_floor].jump_cord[1])*100,
    			(data.base_cord[2]+data.floors[dung_floor].jump_cord[2])*100
    		)
    		if data.need_item then
    			pc.remove_item(data.need_item[1], data.need_item[2])
    		end
    	end
    
    	server_timer("universaldung_exit_time", data.maxlife_dungeon, d.get_map_index())
    	server_loop_timer("universaldung_main_timer", 5, d.get_map_index())
    	d.set_warp_location(data.map_index_out[1], data.map_index_out[2][1], data.map_index_out[2][2])
    	d.setf("floor", dung_floor)
    	
    	UniversalDung_LIB.makeFloor(true) --1° param: first floor (no jump)
    	
    end
    
    UniversalDung_LIB.makeFloor = function(first_jump)
    	d.clear_regen()
    	local data = UniversalDung_LIB.data
    	local data_floor = data.floors[d.getf("floor")]
    	if data_floor then
    		if data_floor.regen_path then
    			for _, data_regen in ipairs(data_floor.regen_path) do
    				if data_regen[2] then
    					d.set_regen_file(data_regen[1])
    				else
    					d.regen_file(data_regen[1])
    				end
    			end
    		end
    	else
    		d.notice(string.format("You will be teleported in %s seconds.", data.wait_time_exit))
    		server_timer("universaldung_exit_time", data.wait_time_exit, d.get_map_index())
    	end
    	if not first_jump then
    		server_timer("universaldung_next_jump", 3, d.get_map_index())
    	end
    end
    
    UniversalDung_LIB.nextJump = function() --server_timer
    	local data = UniversalDung_LIB.data
    	local data_floor = data.floors[d.getf("floor")]
    	d.jump_all(data.base_cord[1]+data_floor.jump_cord[1], data.base_cord[2]+data_floor.jump_cord[2])
    end
    
    UniversalDung_LIB.killProcess = function() --server_timer
    	local data = UniversalDung_LIB.data
    	local _floor = d.getf("floor")
    	local data_floor = data.floors[_floor]
    	if _floor == 3 then
    		if data_floor.boss_vnum then
    			d.clear_regen()
    			d.setf("floor", _floor+1)
    			UniversalDung_LIB.makeFloor()
    		end
    	end
    end
    
    UniversalDung_LIB.mainProcess = function() --server_loop_timer
    	local data = UniversalDung_LIB.data
    	local _floor = d.getf("floor")
    	local data_floor = data.floors[_floor]
    	if d.count_monster() == 0 then
    		if _floor == 1 then
    			d.setf("floor", _floor+1)
    			UniversalDung_LIB.makeFloor()
    		elseif _floor == 2 then --same logic than above
    			d.setf("floor", _floor+1)
    			UniversalDung_LIB.makeFloor()
    		end
    	end
    end
    
    UniversalDung_LIB.checkWaitTime = function()
    	local data = UniversalDung_LIB.data
    	if get_time()-pc.getf("UniversalDung_zone", "last_exit_time") < data.wait_duration then
    		say("You still have to wait to enter.")
    		local left_time = pc.getf("UniversalDung_zone","last_exit_time")-get_time()+data.wait_duration
    		say_reward(string.format("Time remaining: %s", get_time_remaining(left_time)))
    		return false
    	end
    	return true
    end
    
    UniversalDung_LIB.exitDungeon = function()
    	local data = UniversalDung_LIB.data
    	d.set_warp_location(data.map_index_out[1], data.map_index_out[2][1], data.map_index_out[2][2])
    	d.exit_all()
    end
    
    UniversalDung_LIB.saveExitTime = function()
    	if not pc.is_gm() then
    		pc.setqf("last_exit_time", get_time())
    	end
    end
    
    UniversalDung_LIB.sayDuration = function()
    	local data = UniversalDung_LIB.data
    	say(string.format("Dungeon duration:[ENTER]%s.", get_time_remaining(data.maxlife_dungeon)))
    end
    
    


    UniversalDung_zone.quest
     

    define ENTRY_MAN 20354
    
    quest UniversalDung_zone begin
    	state start begin
    		when ENTRY_MAN.chat."Universal dung" with UniversalDung_LIB.isInMapOut() begin
    			say_title(mob_name(npc.get_race()))
    
    			if not UniversalDung_LIB.checkWaitTime() then
    				return
    			end
    			
    			UniversalDung_LIB.sayDuration()
    
    			say("Do you want to enter?")
    			if select("Yes", "No") == 2 then
    				return
    			end
    			
    			if UniversalDung_LIB.checkEnter() then
    				timer("universaldung_make_dungeon", 2)
    			end
    		end
    		
    		when universaldung_make_dungeon.timer begin
    			UniversalDung_LIB.createDungeon()
    		end
    		
    		when universaldung_exit_time.server_timer begin
    			if d.select(get_server_timer_arg()) then
    				UniversalDung_LIB.exitDungeon()
    			end
    		end
    		
    		when universaldung_main_timer.server_timer begin
    			if d.select(get_server_timer_arg()) then
    				UniversalDung_LIB.mainProcess()
    			end
    		end
    		
    		when universaldung_next_jump.server_timer begin
    			if d.select(get_server_timer_arg()) then
    				UniversalDung_LIB.nextJump()
    			end
    		end
    		
    		when logout with UniversalDung_LIB.isInDungeon() begin
    			UniversalDung_LIB.saveExitTime()
    		end
    
    		when kill with UniversalDung_LIB.isInDungeon() begin
    			UniversalDung_LIB.killProcess()
    		end
    	end
    end

     

  9.  

    3 hours ago, antrikos91 said:
      Reveal hidden contents

    [client]
    port                            = 3306
    socket                          = /tmp/mysql.sock

    [mysql]
    prompt                          = \u@\h [\d]>\_
    no_auto_rehash

    [mysqld]
    user                            = mysql
    port                            = 3306
    socket                          = /tmp/mysql.sock
    #bind-address                    = 127.0.0.1
    basedir                         = /usr/local
    datadir                         = /var/db/mysql
    tmpdir                          = /var/db/mysql_tmpdir
    replica-load-tmpdir             = /var/db/mysql_tmpdir
    secure-file-priv                = /var/db/mysql_secure
    log-bin                         = mysql-bin
    log-output                      = TABLE
    relay-log-recovery              = 1
    slow-query-log                  = 1
    server-id                       = 1
    sync_binlog                     = 1
    sync_relay_log                  = 1
    binlog_cache_size               = 16M
    binlog_expire_logs_seconds      = 2592000
    default_password_lifetime       = 0
    enforce-gtid-consistency        = 1
    gtid-mode                       = ON
    safe-user-create                = 1
    lower_case_table_names          = 1
    explicit-defaults-for-timestamp = 1
    myisam-recover-options          = BACKUP,FORCE
    open_files_limit                = 32768
    table_open_cache                = 16384
    table_definition_cache          = 8192
    net_retry_count                 = 16384
    key_buffer_size                 = 256M
    max_allowed_packet              = 64M
    long_query_time                 = 0.5
    innodb_buffer_pool_size         = 1G
    innodb_data_home_dir            = /var/db/mysql
    innodb_log_group_home_dir       = /var/db/mysql
    innodb_data_file_path           = ibdata1:128M:autoextend
    innodb_temp_data_file_path      = ibtmp1:128M:autoextend
    innodb_flush_method             = O_DIRECT
    innodb_redo_log_capacity        = 512M
    innodb_log_buffer_size          = 16M
    innodb_write_io_threads         = 8
    innodb_read_io_threads          = 8
    innodb_autoinc_lock_mode        = 2

    [mysqldump]
    max_allowed_packet              = 256M
    quote_names
    quick
     

    Thats it mine my.cnf. Its fine?

    all starts normaly and the and i have connection refused

    https://metin2.download/picture/ktWQMOG7GErz8NQE1g6M8yIfm7IHtwvB/.png

    check db/syserr

  10. Looking at your code I think that the dungeon is being adapted to the lobby dungeon system of the WoM2 serverfiles.
    If you go to questlua_dungeon.cpp, the dungeon_set_flag function receives three parameters:
     

    	ALUA(dungeon_set_flag)
    	{
    		//if (lua_gettop(L) < 3 || !lua_isnumber(L, 1) || !lua_isstring(L, 2) || !lua_isnumber(L, 3))
    		if (!lua_isnumber(L, 1) || !lua_isstring(L, 2) || !lua_isnumber(L, 3))
    		{
    			sys_err("not enough arguments.");
    			return 0;
    		}
    
    		int32_t mapidx = (int32_t)lua_tonumber(L, 1);
    
    		LPDUNGEON dungeon = CDungeonManager::instance().FindByMapIndex(mapidx);
    		if (!dungeon)
    		{
    			sys_err("dungeon %d doesn't exist.", mapidx);
    			return 0;
    		}
    
    		dungeon->SetFlag(lua_tostring(L, 2), (int32_t)lua_tonumber(L, 3));
    		return 0;
    	}

    1: map index
    2. flag name
    3. flag value

    Solution:
    In each d.setf, for example:

    d.setf("dungeon_expire_time", 0);

    Change for:

    d.setf(d.get_map_index(), "dungeon_expire_time", 0);

     

  11. Hello

     

    I have reworked the get function calls without parameters.

    I mean when you use pc.empire instead of pc.get_empire()

    This time I have extended to more features and added the quest features.

     

    Tested in Marty Sama.

     

    Explanation:

    To add more functions you must know which ones.
    Functions must return a value and must not receive any parameters.
    pc.get_empire() is very simple, it returns a number and no parameter is sent. Its "alias" would be pc.empire or whatever name best suits it.
    item.get_value() does not work. Its alias would be item.value but the server will not know which value it refers to, since it needs to specify the index of that value. This structure does not work if the function requires parameters.

    When you need to use q.getcurrentquestindex(), you just put q.index. Now it's simpler.

     

     

    Steps:

    questlib.lua. Remove this code:

    Remove:
    
    npc_index_table = {
        ['race'] = npc.getrace,
        ['empire'] = npc.get_empire,
    }
    
    pc_index_table = {
        ['weapon']		= pc.getweapon,
        ['level']		= pc.get_level,
        ['hp']		= pc.gethp,
        ['maxhp']		= pc.getmaxhp,
        ['sp']		= pc.getsp,
        ['maxsp']		= pc.getmaxsp,
        ['exp']		= pc.get_exp,
        ['nextexp']		= pc.get_next_exp,
        ['job']		= pc.get_job,
        ['money']		= pc.getmoney,
        ['gold'] 		= pc.getmoney,
        ['name'] 		= pc.getname,
        ['playtime'] 	= pc.getplaytime,
        ['leadership'] 	= pc.getleadership,
        ['empire'] 		= pc.getempire,
        ['skillgroup'] 	= pc.get_skill_group,
        ['x'] 		= pc.getx,
        ['y'] 		= pc.gety,
        ['local_x'] 	= pc.get_local_x,
        ['local_y'] 	= pc.get_local_y,
    }
    
    item_index_table = {
        ['vnum']		= item.get_vnum,
        ['name']		= item.get_name,
        ['size']		= item.get_size,
        ['count']		= item.get_count,
        ['type']		= item.get_type,
        ['sub_type']	= item.get_sub_type,
        ['refine_vnum']	= item.get_refine_vnum,
        ['level']		= item.get_level,
    }
    
    function npc_index(t,i)
        local npit = npc_index_table
        if npit[i] then
        return npit[i]()
        else
        return rawget(t,i)
        end
    end
    
    function pc_index(t,i)
        local pit = pc_index_table
        if pit[i] then
        return pit[i]()
        else
        return rawget(t,i)
        end
    end
    
    function item_index(t, i)
        local iit = item_index_table
        if iit[i] then
        return iit[i]()
        else
        return rawget(t, i)
        end
    end
    
    setmetatable(pc,{__index=pc_index})
    setmetatable(npc,{__index=npc_index})
    setmetatable(item,{__index=item_index})


    Add this code:
     

    index_tables = {
    	pc = {
    		['weapon']		= pc.getweapon,
    		['level']		= pc.get_level,
    		['hp']			= pc.gethp,
    		['maxhp']		= pc.getmaxhp,
    		['sp']			= pc.getsp,
    		['maxsp']		= pc.getmaxsp,
    		['exp']			= pc.get_exp,
    		['nextexp']		= pc.get_next_exp,
    		['job']			= pc.get_job,
    		['money']		= pc.getmoney,
    		['gold'] 		= pc.getmoney,
    		['name'] 		= pc.getname,
    		['playtime'] 	= pc.getplaytime,
    		['leadership'] 	= pc.getleadership,
    		['empire'] 		= pc.getempire,
    		['skillgroup'] 	= pc.get_skill_group,
    		['x'] 			= pc.getx,
    		['y'] 			= pc.gety,
    		['local_x'] 	= pc.get_local_x,
    		['local_y'] 	= pc.get_local_y,
    		['mapindex'] 	= pc.get_map_index,
    		['guild'] 		= pc.get_guild,
    		['sex'] 		= pc.get_sex,
    		['gmlevel'] 	= pc.get_gm_level,
    		['ip'] 			= pc.get_ip0,
    		['hwid'] 		= pc.get_hwid,
    	},
    	npc = {
    		['race']		= npc.getrace,
    		['empire']		= npc.get_empire,
    		['vid']			= npc.get_vid,
    		['level']		= npc.get_level0,
    		['name']		= npc.get_name0,
    		['pid']			= npc.get_pid0,
    		['type']		= npc.get_type0,
    		['hwid']		= npc.get_hwid,
    	},
    	item = {
    		['id']			= item.get_id,
    		['cell']		= item.get_cell,
    		['vnum']		= item.get_vnum,
    		['name']		= item.get_name,
    		['size']		= item.get_size,
    		['count']		= item.get_count,
    		['type']		= item.get_type,
    		['sub_type']	= item.get_sub_type,
    		['refine_vnum']	= item.get_refine_vnum,
    		['level']		= item.get_level,
    		['levellimit']	= item.get_level_limit,
    		['wearflag']	= item.get_wearflag0,
    		['antiflag']	= item.get_antiflag0,
    		['immuneflag']	= item.get_immuneflag0,
    	},
    	q = {
    		['index']		= q.getcurrentquestindex,
    		['name']		= q.getcurrentquestname,
    	}
    	--add your new space
    }
    
    function generic_index(t, i)
    	local it = index_tables[t]
    	return it[i] and it[i]() or rawget(t, i)
    end
    
    setmetatable(pc, { __index = function(t, i) return generic_index("pc", i) end })
    setmetatable(npc, { __index = function(t, i) return generic_index("npc", i) end })
    setmetatable(item, { __index = function(t, i) return generic_index("item", i) end })
    setmetatable(q, { __index = function(t, i) return generic_index("q", i) end }) --quest
    --add your new space

     

    • Metin2 Dev 1
  12. Hello

    Once I was bored and it occurred to me to create a feature to kiss your own shaman.

    This feature was tested in Aslan's shaman system.

     

    Now you can feel a little more... accompanied. 😏


    GIF: https://metin2.download/picture/xi0bvz0b58BySGFx2G19o462XJgd1l3g/.gif

    spacer.png

     

    CommonDefines.h / service.h

    #define ENABLE_ASLAN_BUFF_NPC_SYSTEM
    #ifdef ENABLE_ASLAN_BUFF_NPC_SYSTEM
    	[...]
    	#define ENABLE_ASLAN_BUFF_EMOTION //add new
    #endif

     

    char.cpp
     

    LPCHARACTER CHARACTER::FindCharacterInView(const char * c_pszName, bool bFindPCOnly)
    {
    	ENTITY_MAP::iterator it = m_map_view.begin();
    
    	for (; it != m_map_view.end(); ++it)
    	{
    		if (!it->first->IsType(ENTITY_CHARACTER))
    			continue;
    
    		LPCHARACTER tch = (LPCHARACTER) it->first;
    
    		if (bFindPCOnly && tch->IsNPC()
    #if defined(ENABLE_ASLAN_BUFF_NPC_SYSTEM) && defined(ENABLE_ASLAN_BUFF_EMOTION)
    			&& !tch->IsBuffNPC()
    #endif
    		)
    			continue;
    
    		if (!strcasecmp(tch->GetName(), c_pszName)
    #if defined(ENABLE_ASLAN_BUFF_NPC_SYSTEM) && defined(ENABLE_ASLAN_BUFF_EMOTION)
    			&& GetBuffNPCSystem()->GetOwner() == this
    #endif
    		)
    			return (tch);
    	}
    
    	return NULL;
    }

     

    cmd_emotion.cpp

    #if defined(ENABLE_ASLAN_BUFF_NPC_SYSTEM) && defined(ENABLE_ASLAN_BUFF_EMOTION)
    #include "buff_npc_system.h"
    #endif


    In ACMD(do_emotion):

    1. Find:

    		if (!victim->IsPC() || victim == ch)
    			return;

    Replace for:

    		if ((!victim->IsPC()
    #if defined(ENABLE_ASLAN_BUFF_NPC_SYSTEM) && defined(ENABLE_ASLAN_BUFF_EMOTION)
    			&& !victim->IsBuffNPC())
    #endif
    		|| victim == ch
    		)
    			return;

    2. Find: (if your serverfile are old, likely you have this: s_emotion_set.insert(std::make_pair(ch->GetVID(), victim->GetVID()));)

    				else
    				{
    					ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이 행동은 상호동의 하에 가능 합니다."));
    					return;
    				}
    			}
    
    			s_emotion_set.emplace(ch->GetVID(), victim->GetVID());

    Replace for:

    				else
    				{
    #if defined(ENABLE_ASLAN_BUFF_NPC_SYSTEM) && defined(ENABLE_ASLAN_BUFF_EMOTION)
    					if (!(victim->IsBuffNPC() && ch->GetBuffNPCSystem() && victim ==  ch->GetBuffNPCSystem()->GetCharacter()))
    					{
    						ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이 행동은 상호동의 하에 가능 합니다."));
    						return;
    					}
    					if (victim->IsBuffNPC() && ch->GetBuffNPCSystem() && victim ==  ch->GetBuffNPCSystem()->GetCharacter())
    					{
    						if (ch->GetBuffNPCSystem()->GetSex() == GET_SEX(ch))
    						{
    							ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이성간에만 할 수 있습니다."));
    							return;
    						}
    					}
    #else
    					ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("이 행동은 상호동의 하에 가능 합니다."));
    					return;
    #endif
    				}
    			}
    
    			s_emotion_set.emplace(ch->GetVID(), victim->GetVID());

     

    • kekw 7
    • Lmao 10
    • Love 2
×
×
  • 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.