caanmasu 319 Posted October 5, 2023 Share Posted October 5, 2023 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. 3 1 1 Link to comment Share on other sites More sharing options...
Erexo 0 Posted October 10, 2023 Share Posted October 10, 2023 Is it possible to make command for gm? Like /create_arena name1 name2? And it will teleport players and gm to arena? Link to comment Share on other sites More sharing options...
caanmasu 319 Posted October 10, 2023 Author Share Posted October 10, 2023 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; } } 1 Link to comment Share on other sites More sharing options...
Active+ Member HFWhite 528 Posted October 12, 2023 Active+ Member Share Posted October 12, 2023 not working. When i press the Arena button, nothing happens. Link to comment Share on other sites More sharing options...
caanmasu 319 Posted October 13, 2023 Author Share Posted October 13, 2023 16 hours ago, SCOOB said: not working. When i press the Arena button, nothing happens. Write to my Discord: caanmasu If something is wrong, I will fix it Link to comment Share on other sites More sharing options...
hero2 0 Posted April 4 Share Posted April 4 Very nice system. How many duels are played? Does it depend on the players? Does it teleport directly after signing up? How many hands etc. do they throw? Link to comment Share on other sites More sharing options...
Recommended Posts