caanmasu
-
Posts
90 -
Joined
-
Last visited
-
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by caanmasu
-
-
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
- 1
-
Search "PointChange(POINT_STAT" in source
-
Hey, calm down. Take things easy.
Look, I did the Tower of Sung Ma dungeon with Lua.
Specifically, I did it on April 4 and 5 of last year.If you want to continue with that project we could do something together. Write me.
My language is Spanish but I can translate in English.
- 1
- 3
-
Check match between locale/xx and db
Navicat
Database common, table locale, mKey LOCALE
In my case: mValue is "germany", then my path is locale/germany
Ok?
-
@Denizeri24 o.O share it please
-
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 pathLet's begin.
root/introloading.py1.
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:
- 6
- 1
- 1
- 1
- 4
-
Range min: att_speed
Range max: mov_speed
att_speed < mov_speed
If you put range [110-109] get error
Solution: set range 109-110
Remember: if you put 109 - 120, for example, it'll respawn groups random from 109 to 120 idx -
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;
- 3
- 1
- 5
-
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
-
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
-
-
Hi
Demostration: https://metin2.download/video/3lPDNkFwv4KaL4T2u9ClI0xfmfD0oZ0U/.mp4Important: 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: 100I just want to find 28 skill:
Average input: 100
Skill input: 28I 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.questquest 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
- 1
-
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.
- 2
- 1
- 1
-
1. In db/conf.txt, which value has PROTO_FROM_DB? (WinSCP)
2. Send db/ClientManagerBoot.cpp from server
3. Send mob_proto dumped from db
-
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.luaUniversalDung_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
-
Do everything you can to leave the syserr db clean
-
3 hours ago, antrikos91 said:
[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
-
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);
-
Send quest
- 1
-
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
- 1
-
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/.gifCommonDefines.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());
- 7
- 10
- 2
-
-
Send both files
-
getLimit is not declared in the method, it didn't even arrive as a parameter. Just delete it.
Auto Bravery Cape
in Community Support - Questions & Answers
Posted
I did this quest a while ago
item_proto.txt
vnum 70038
item_type ITEM_QUEST or 18
auto_cape.quest
Activate/Deactivate slot:
root/constInfo.py