-
Posts
264 -
Joined
-
Last visited
-
Days Won
29 -
Feedback
91%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by Owsap
-
-
I recently came across this issue when updating some things on the party (group) system and I realized that this problem was present on all the branches of the source. Although I've seen certain topics with some solutions, they don't provide much information and, in my opinion, a good solution. So, I'll share mine with you and you can use it if you're happy with the results.
The Bug
When you set a role to a member as a leader, it will give the member a certain bonus according to the role, this bonus is given if the leadership skill is high. Now, if you decide to remove the members role, in theory the bonus should be removed. However, when this happens, it will only compute the battle points of the player which will make some bonuses of certain roles the same until the character computes all his points again. For example, if you set a member with the tanker role, which grants a bonus of additional health points and then remove the role from the member, the bonus will not be removed until the character computes his points again. It doesn't remove the bonus because the function by default only computes the battle points, this relates to roles like, attacker and defender.
Realization
So far, we realized a possible solution, which is replacing the ComputeBattlePoints with ComputePoints, well sure, and I've seen this solution on this forum in some help request topics but this comes to a major cost in performance since the role computation function CParty::ComputeRolePoint is frequently called.
The Solution
What we really want to do is check if the member has any bonus assigned to a role, remove the bonus and finally compute the character's points appropriately, avoiding constant updates to the ComputePoints function. If the member doesn't have any bonus given from a role, there will be no need to calculate the points.
Spoiler/// @ server/game/src/party.cpp // Search @ void CParty::ComputeRolePoint if (!bAdd) { ch->PointChange(POINT_PARTY_ATTACKER_BONUS, -ch->GetPoint(POINT_PARTY_ATTACKER_BONUS)); ch->PointChange(POINT_PARTY_TANKER_BONUS, -ch->GetPoint(POINT_PARTY_TANKER_BONUS)); ch->PointChange(POINT_PARTY_BUFFER_BONUS, -ch->GetPoint(POINT_PARTY_BUFFER_BONUS)); ch->PointChange(POINT_PARTY_SKILL_MASTER_BONUS, -ch->GetPoint(POINT_PARTY_SKILL_MASTER_BONUS)); ch->PointChange(POINT_PARTY_DEFENDER_BONUS, -ch->GetPoint(POINT_PARTY_DEFENDER_BONUS)); ch->PointChange(POINT_PARTY_HASTE_BONUS, -ch->GetPoint(POINT_PARTY_HASTE_BONUS)); ch->ComputeBattlePoints(); return; } // Replace with (you might need to include <array> in your file) if (!bAdd) { const BYTE bMaxRoleNum = PARTY_ROLE_MAX_NUM - PARTY_ROLE_ATTACKER; std::array<long, bMaxRoleNum> alPartyPoints = { ch->GetPoint(POINT_PARTY_ATTACKER_BONUS), ch->GetPoint(POINT_PARTY_TANKER_BONUS), ch->GetPoint(POINT_PARTY_BUFFER_BONUS), ch->GetPoint(POINT_PARTY_SKILL_MASTER_BONUS), ch->GetPoint(POINT_PARTY_HASTE_BONUS), ch->GetPoint(POINT_PARTY_DEFENDER_BONUS) }; bool bComputePoints = false; for (BYTE bIndex = 0; bIndex < bMaxRoleNum; ++bIndex) { if (alPartyPoints[bIndex] != 0) { BYTE bRole = PARTY_ROLE_ATTACKER + bIndex; WORD wPointType = POINT_NONE; switch (bRole) { case PARTY_ROLE_ATTACKER: wPointType = POINT_PARTY_ATTACKER_BONUS; break; case PARTY_ROLE_TANKER: wPointType = POINT_PARTY_TANKER_BONUS; break; case PARTY_ROLE_BUFFER: wPointType = POINT_PARTY_BUFFER_BONUS; break; case PARTY_ROLE_SKILL_MASTER: wPointType = POINT_PARTY_SKILL_MASTER_BONUS; break; case PARTY_ROLE_HASTE: wPointType = POINT_PARTY_HASTE_BONUS; break; case PARTY_ROLE_DEFENDER: wPointType = POINT_PARTY_DEFENDER_BONUS; break; default: continue; } ch->PointChange(wPointType, -alPartyPoints[bIndex]); bComputePoints = true; } } if (bComputePoints) ch->ComputePoints(); return; } // If flexibility and readability are more important for you, than you can use a map. // However, it may have a slight performance overhead compared to array access. if (!bAdd) { std::map<WORD, long> mPartyPoints; mPartyPoints[POINT_PARTY_ATTACKER_BONUS] = ch->GetPoint(POINT_PARTY_ATTACKER_BONUS); mPartyPoints[POINT_PARTY_TANKER_BONUS] = ch->GetPoint(POINT_PARTY_TANKER_BONUS); mPartyPoints[POINT_PARTY_BUFFER_BONUS] = ch->GetPoint(POINT_PARTY_BUFFER_BONUS); mPartyPoints[POINT_PARTY_SKILL_MASTER_BONUS] = ch->GetPoint(POINT_PARTY_SKILL_MASTER_BONUS); mPartyPoints[POINT_PARTY_HASTE_BONUS] = ch->GetPoint(POINT_PARTY_HASTE_BONUS); mPartyPoints[POINT_PARTY_DEFENDER_BONUS] = ch->GetPoint(POINT_PARTY_DEFENDER_BONUS); bool bComputePoints = false; for (const auto& it : mPartyPoints) { if (it.second != 0) { ch->PointChange(it.first, -it.second); bComputePoints = true; } } if (bComputePoints) ch->ComputePoints(); return; }
- 5
- 1
- 7
-
Maybe this is what you're looking for.
- 1
-
-
Repository Updated
Changed QuestionDialog to QuestionDialog2.
This change is due to the multi-line token which is not supported by all clients.
To improve compatibility, the dialog message has been split into two tokens.
The issue with the player's distance while the dialogue is open has also been fixed.
Thanks for testing and reporting back.
I recommend taking a look at all the code in the repository as I amended some issues on the first commit.- 9
- 6
-
18 minutes ago, nazox said:
Thanks @ Owsap i'm fixing button, but work, nice released thanks!
I just updated the repository, there was one thing missing for the button to work, everything should be fine now.
- 1
-
Synchronizes the character's position with the server and can be used to free them if they get stuck.
If there is no available position within the available distance, the character will be warped to the village..
- 85
- 1
- 1
- 14
- 5
- 34
-
Like everything you learn, you study and practice.
A lot of trial and error is involved.
- 2
-
I like the idea and small details, good work.
- 1
-
Added random title color feature and a check for alignment grade to apply the particle effect and / or the random title color.
- 2
-
- 137
- 3
- 27
- 1
- 6
- 55
-
-
-
As the title indicates, the following changes will extend the affect flags limit from 64 to 96.
Server
common/service.h
Spoiler/// 1. // Add #define __EXTENDED_AFFECT_FLAG__
game/src/affect_flag.h
Spoiler/// 1. // Search DWORD bits[2]; inline TAffectFlag() { bits[0] = 0; bits[1] = 0; } inline TAffectFlag(DWORD v1, DWORD v2 = 0) { bits[0] = v1; bits[1] = v2; } // Replace with #if defined(__EXTENDED_AFFECT_FLAG__) DWORD bits[3]; inline TAffectFlag() { bits[0] = 0; bits[1] = 0; bits[2] = 0; } inline TAffectFlag(DWORD v1, DWORD v2 = 0, DWORD v3 = 0) { bits[0] = v1; bits[1] = v2; bits[2] = v3; } #else DWORD bits[2]; inline TAffectFlag() { bits[0] = 0; bits[1] = 0; } inline TAffectFlag(DWORD v1, DWORD v2 = 0) { bits[0] = v1; bits[1] = v2; } #endif /// 2. // Search bits[0] = rhs.bits[0]; bits[1] = rhs.bits[1]; // Add below #if defined(__EXTENDED_AFFECT_FLAG__) bits[2] = rhs.bits[2]; #endif /// 3. // Search return lhs.bits[0] == rhs.bits[0] && lhs.bits[1] == rhs.bits[1]; // Replace with #if defined(__EXTENDED_AFFECT_FLAG__) return lhs.bits[0] == rhs.bits[0] && lhs.bits[1] == rhs.bits[1] && lhs.bits[2] == rhs.bits[2]; #else return lhs.bits[0] == rhs.bits[0] && lhs.bits[1] == rhs.bits[1]; #endif
game/src/building.cpp
Spoiler/// 1. // Search @ CObject::EncodeInsertPacket pack.dwAffectFlag[0] = unsigned(m_data.xRot); pack.dwAffectFlag[1] = unsigned(m_data.yRot); // Add below #if defined(__EXTENDED_AFFECT_FLAG__) pack.dwAffectFlag[2] = unsigned(m_data.zRot); #endif
game/src/char.cpp
Spoiler/// 1. // Search @ CHARACTER::EncodeInsertPacket pack.dwAffectFlag[0] = m_afAffectFlag.bits[0]; pack.dwAffectFlag[1] = m_afAffectFlag.bits[1]; // Add below #if defined(__EXTENDED_AFFECT_FLAG__) pack.dwAffectFlag[2] = m_afAffectFlag.bits[2]; #endif /// 2. // Search @ CHARACTER::UpdatePacket pack.dwAffectFlag[0] = m_afAffectFlag.bits[0]; pack.dwAffectFlag[1] = m_afAffectFlag.bits[1]; // Add below #if defined(__EXTENDED_AFFECT_FLAG__) pack.dwAffectFlag[2] = m_afAffectFlag.bits[2]; #endif
game/src/packet.h
Spoiler/// 1. // Search @ struct packet_add_char DWORD dwAffectFlag[2]; // Replace with #if defined(__EXTENDED_AFFECT_FLAG__) DWORD dwAffectFlag[3]; #else DWORD dwAffectFlag[2]; #endif /// 2. // Search @ struct packet_update_char DWORD dwAffectFlag[2]; // Replace with #if defined(__EXTENDED_AFFECT_FLAG__) DWORD dwAffectFlag[3]; #else DWORD dwAffectFlag[2]; #endif
•
Client
UserInterface/Locale_inc.h
Spoiler/// 1. // Add #define ENABLE_EXTENDED_AFFECT_FLAG
UserInterface/AffectFlagContainer.h
Spoiler/// 1. // Search BIT_SIZE = 64, // Replace with #if defined(ENABLE_EXTENDED_AFFECT_FLAG) BIT_SIZE = 96, #else BIT_SIZE = 64, #endif
UserInterface/Packet.h
Spoiler/// 1. // Search @ struct packet_add_char DWORD dwAffectFlag[2]; // Replace with #if defined(ENABLE_EXTENDED_AFFECT_FLAG) DWORD dwAffectFlag[3]; #else DWORD dwAffectFlag[2]; #endif /// 2. // Search @ struct packet_add_char2 DWORD dwAffectFlag[2]; // Replace with #if defined(ENABLE_EXTENDED_AFFECT_FLAG) DWORD dwAffectFlag[3]; #else DWORD dwAffectFlag[2]; #endif /// 3. // Search @ struct packet_update_char DWORD dwAffectFlag[2]; // Replace with #if defined(ENABLE_EXTENDED_AFFECT_FLAG) DWORD dwAffectFlag[3]; #else DWORD dwAffectFlag[2]; #endif /// 4. // Search @ struct packet_update_char2 DWORD dwAffectFlag[2]; // Replace with #if defined(ENABLE_EXTENDED_AFFECT_FLAG) DWORD dwAffectFlag[3]; #else DWORD dwAffectFlag[2]; #endif
UserInterface/PythonNetworkStreamPhaseGameActor.cpp
Spoiler/// 1. // Search @ CPythonNetworkStream::RecvCharacterAppendPacket kNetActorData.m_kAffectFlags.CopyData(32, sizeof(chrAddPacket.dwAffectFlag[1]), &chrAddPacket.dwAffectFlag[1]); // Add below #if defined(ENABLE_EXTENDED_AFFECT_FLAG) kNetActorData.m_kAffectFlags.CopyData(64, sizeof(chrAddPacket.dwAffectFlag[2]), &chrAddPacket.dwAffectFlag[2]); #endif /// 2. // Search @ CPythonNetworkStream::RecvCharacterAppendPacketNew kNetActorData.m_kAffectFlags.CopyData(32, sizeof(chrAddPacket.dwAffectFlag[1]), &chrAddPacket.dwAffectFlag[1]); // Add below #if defined(ENABLE_EXTENDED_AFFECT_FLAG) kNetActorData.m_kAffectFlags.CopyData(64, sizeof(chrAddPacket.dwAffectFlag[2]), &chrAddPacket.dwAffectFlag[2]); #endif /// 3. // Search @ CPythonNetworkStream::RecvCharacterUpdatePacket kNetUpdateActorData.m_kAffectFlags.CopyData(32, sizeof(chrUpdatePacket.dwAffectFlag[1]), &chrUpdatePacket.dwAffectFlag[1]); // Add below #if defined(ENABLE_EXTENDED_AFFECT_FLAG) kNetUpdateActorData.m_kAffectFlags.CopyData(64, sizeof(chrUpdatePacket.dwAffectFlag[2]), &chrUpdatePacket.dwAffectFlag[2]); #endif /// 4. // Search @ CPythonNetworkStream::RecvCharacterUpdatePacketNew kNetUpdateActorData.m_kAffectFlags.CopyData(32, sizeof(chrUpdatePacket.dwAffectFlag[1]), &chrUpdatePacket.dwAffectFlag[1]); // Add below #if defined(ENABLE_EXTENDED_AFFECT_FLAG) kNetUpdateActorData.m_kAffectFlags.CopyData(64, sizeof(chrUpdatePacket.dwAffectFlag[2]), &chrUpdatePacket.dwAffectFlag[2]); #endif
•
Curiosity
Spoilerenum EAffectBits { AFFECT_YMIR, AFFECT_INVISIBILITY, AFFECT_SPAWN, AFFECT_POISON, AFFECT_SLOW, AFFECT_STUN, AFFECT_DUNGEON_READY, // ´øÀü¿¡¼ Áغñ »óÅ AFFECT_SHOW_ALWAYS, // AFFECT_DUNGEON_UNIQUE ¿¡¼ º¯°æ(Ŭ¶óÀ̾ðÆ®¿¡¼ ÄøµµÇÁö¾ÊÀ½) AFFECT_BUILDING_CONSTRUCTION_SMALL, AFFECT_BUILDING_CONSTRUCTION_LARGE, AFFECT_BUILDING_UPGRADE, AFFECT_MOV_SPEED_POTION, AFFECT_ATT_SPEED_POTION, AFFECT_FISH_MIND, AFFECT_JEONGWI, // Àü±ÍÈ¥ AFFECT_GEOMGYEONG, // °Ë°æ AFFECT_CHEONGEUN, // õ±ÙÃß AFFECT_GYEONGGONG, // °æ°ø¼ú AFFECT_EUNHYEONG, // ÀºÇü¹ý AFFECT_GWIGEOM, // ±Í°Ë AFFECT_GONGPO, // °øÆ÷ AFFECT_JUMAGAP, // ÁÖ¸¶°© AFFECT_HOSIN, // È£½Å AFFECT_BOHO, // º¸È£ AFFECT_KWAESOK, // Äè¼Ó AFFECT_HEUKSIN, // Èæ½Å¼öÈ£ AFFECT_MUYEONG, // ¹«¿µÁø AFFECT_REVIVE_INVISIBILITY, // ºÎÈ° ¹«Àû AFFECT_FIRE, // Áö¼Ó ºÒ AFFECT_GICHEON, // ±âõ ´ë°ø AFFECT_JEUNGRYEOK, // Áõ·Â¼ú AFFECT_DASH, // ´ë½¬ AFFECT_PABEOP, // ÆĹý¼ú AFFECT_FALLEN_CHEONGEUN, // ´Ù¿î ±×·¹À̵å õ±ÙÃß AFFECT_POLYMORPH, // Æú¸®¸ðÇÁ AFFECT_WAR_FLAG1, AFFECT_WAR_FLAG2, AFFECT_WAR_FLAG3, AFFECT_CHINA_FIREWORK, AFFECT_CANNOT_ATTACK, AFFECT_CANNOT_USE_SKILL, AFFECT_DS, AFFECT_BLEEDING, AFFECT_RED_POSSESSION, AFFECT_BLUE_POSSESSION, AFFECT_UNK45, // ? AFFECT_UNK46, // ? AFFECT_UNBEATABLE, AFFECT_BATTLE_FIELD_RANK1, AFFECT_BATTLE_FIELD_RANK2, AFFECT_BATTLE_FIELD_RANK3, AFFECT_TARGET_VICTIM, AFFECT_UNK52, // ? AFFECT_ELECTRIC_SHOCK, AFFECT_CONFUSION, AFFECT_SOUL_RED, AFFECT_SOUL_BLUE, AFFECT_SOUL_MIX, AFFECT_UNK58, // ? AFFECT_BATTLE_ROYALE_SLOW_1, AFFECT_BATTLE_ROYALE_SLOW_2, AFFECT_BATTLE_ROYALE_SLOW_3, AFFECT_UNK62, // ? AFFECT_PASWAE, AFFECT_UNK64, // ? AFFECT_FLAG_ELEMENT_BUFF_CRACK_NONE, AFFECT_FLAG_ELEMENT_BUFF_CRACK_FIRE, AFFECT_FLAG_ELEMENT_BUFF_CRACK_ICE, AFFECT_FLAG_ELEMENT_BUFF_CRACK_ELECT, AFFECT_FLAG_ELEMENT_BUFF_CRACK_WIND, AFFECT_FLAG_ELEMENT_BUFF_CRACK_EARTH, AFFECT_FLAG_ELEMENT_BUFF_CRACK_DARK, AFFECT_FLAG_UNK72, // guild_battle (blue) AFFECT_FLAG_UNK73, // guild_battle (yellow) AFFECT_FLAG_UNK74, // guild_battle (green) AFFECT_FLAG_UNK75, // guild_battle (red) AFFECT_FLAG_UNK76, // ? AFFECT_FLAG_UNK77, // ? AFFECT_FLAG_UNK78, // ? AFFECT_FLAG_UNK79, // ? AFFECT_CHEONUN_INVINCIBILITY, AFFECT_CHEONUN_NORMAL, AFFECT_CHEONUN_MASTER, AFFECT_CHEONUN_GRAND_MASTER, AFFECT_CHEONUN_PERFECT_MASTER, AFFECT_NUM, AFFECT_HWAYEOM = AFFECT_GEOMGYEONG, };
.
- 21
- 5
- 1
- 16
-
6 hours ago, WeedHex said:
It's different from official
I know they updated the quest part and removed the quest items because they are no longer in the proto. However, they rarely enable this event on the server so testing it fully is limited and that's why I made based on the old version but if you are sure about something please describe what is missing.
- 1
-
1 hour ago, xGalardo said:
0614 21:23:26078 :: NameError
0614 21:23:26078 :: :
0614 21:23:26078 :: global name 'questbutton_max' is not defined
0614 21:23:26078 ::
If dont have questbutton_max, just change to self.QUEST_BUTTON_MAX_NUMBoth 2015 & 2018 root files have the mentioned lines from the guide but if that works for you, sure...
On 6/13/2023 at 2:43 PM, Gurgarath said:Thank you for your release! It is really cool! Also, this is one of the new addition that I feel the most weird about, it looks like a bug more than a feature somehow
I agree, when I first saw it on the live server it looked weird because the text didn't match the window length but at least for the buttons it's not that bad since it has space for bigger texts. I wonder how long it will take them until they adjust all the "[ENTER]" tokens in the locale_quest.txt or completely remove them to make the text match the width of the window and break line correctly.
- 1
-
Because why not...
Only a few changes are necessary, and the input width has remained unchanged.Preview of the Quest Width Expansion
Guide
Client
SpoilerClient
root/uiQuest.pySpoiler''' 1. ''' # Search @ def MakeNextButton b.SetSize(100, 26) b.SetPosition(self.sx + self.board.GetWidth() / 2 - 50, self.sy + yPos) # Replace with if app.ENABLE_QUEST_WIDTH_EXPANSION: b.SetSize(280, 26) b.SetPosition(self.sx + self.board.GetWidth() / 2 - 140, self.sy + yPos) else: b.SetSize(100, 26) b.SetPosition(self.sx + self.board.GetWidth() / 2 - 50, self.sy + yPos) ''' 2. ''' # Search @ def MakeQuestion self.prevbutton.SetPosition(self.sx + self.board.GetWidth() / 2 - 164, self.sy + (event.GetLineCount(self.descIndex) + questbutton_max - 1) * 16 + 20 + 5) # Replace with if app.ENABLE_QUEST_WIDTH_EXPANSION: self.prevbutton.SetPosition(self.sx + self.board.GetWidth() / 2 - 340, self.sy + (event.GetLineCount(self.descIndex) + questbutton_max - 1) * 16 + 20 + 5) else: self.prevbutton.SetPosition(self.sx + self.board.GetWidth() / 2 - 164, self.sy + (event.GetLineCount(self.descIndex) + questbutton_max - 1) * 16 + 20 + 5) ''' 3. ''' # Search @ def MakeQuestion self.nextbutton.SetPosition(self.sx + self.board.GetWidth() / 2 + 112, self.sy + (event.GetLineCount(self.descIndex) + questbutton_max - 1) * 16 + 20 + 5) # Replace with if app.ENABLE_QUEST_WIDTH_EXPANSION: self.nextbutton.SetPosition(self.sx + self.board.GetWidth() / 2 + 288, self.sy + (event.GetLineCount(self.descIndex) + questbutton_max - 1) * 16 + 20 + 5) else: self.nextbutton.SetPosition(self.sx + self.board.GetWidth() / 2 + 112, self.sy + (event.GetLineCount(self.descIndex) + questbutton_max - 1) * 16 + 20 + 5) ''' 4. ''' # Search @ def MakeEachButton button.SetSize(200, 26) button.SetPosition(self.sx + self.board.GetWidth() / 2 - 100, self.sy + (event.GetLineCount(self.descIndex) + i * 2) * 16 + 20 + 5) # Replace with if app.ENABLE_QUEST_WIDTH_EXPANSION: button.SetSize(560, 26) button.SetPosition(self.sx + self.board.GetWidth() / 2 - 280, self.sy + (event.GetLineCount(self.descIndex) + i * 2) * 16 + 20 + 5) else: button.SetSize(200, 26) button.SetPosition(self.sx + self.board.GetWidth() / 2 - 100, self.sy + (event.GetLineCount(self.descIndex) + i * 2) * 16 + 20 + 5)
Client
UIScript/QuestDialog.pySpoilerimport app ROOT = "d:/ymir work/ui/public/" if app.ENABLE_QUEST_WIDTH_EXPANSION: QUEST_BOARD_WIDTH_ADJUSTMENT_VALUE = 2 ## 퀘스트 보드 폭 조정 값 window = { "name" : "QuestDialog", "style" : ("float",), "x" : 0, "y" : 0, "width" : 800, "height" : 450, "children" : ( { "name" : "board", "type" : "thinboard", "style" : ("attach", "ignore_size",), "x" : 0, "y" : 0, "horizontal_align" : "center", "vertical_align" : "center", "width" : 350, "height" : 300, }, ), } if app.ENABLE_QUEST_WIDTH_EXPANSION: window["children"][0]["width"] = window["children"][0]["width"] * QUEST_BOARD_WIDTH_ADJUSTMENT_VALUE
•
Srcs
SpoilerClient
UserInterface/Locale_inc.h/// 1. // Add anywhere #define ENABLE_QUEST_WIDTH_EXPANSION
Client
UserInterface/PythonApplicationModule.cpp/// Search PyModule_AddIntConstant(poModule, "CAMERA_STOP", CPythonApplication::CAMERA_STOP); // Add below #if defined(ENABLE_QUEST_WIDTH_EXPANSION) PyModule_AddIntConstant(poModule, "ENABLE_QUEST_WIDTH_EXPANSION", 1); #else PyModule_AddIntConstant(poModule, "ENABLE_QUEST_WIDTH_EXPANSION", 0); #endif
•
- 43
- 1
- 9
- 1
- 1
- 15
-
I put together an AIO (all in one) package for those who might need.
- Packs 23.1.4
- Protos 23.1.2
- Root Metadata & Dumped Binary 23.1.2
I also took the liberty to add the `data` folder for monsters and pc motions for the server.
And, if you are interested in finding guild marks, I dumped them in the `mark/` folder.Folder Structure
Spoiler├─── Client/ │ ├─── bgm/ │ │ └─── (Background Music) │ ├─── lib/ │ │ └─── (Python Library) │ ├─── mark/ │ │ └─── (Cropped Guild Marks) │ ├─── pack/ │ │ ├─── (Packs 23.1.4) │ │ ├─── ... │ │ └─── root/ │ │ └─── (Metadata 23.1.2) │ ├─── upload/ │ │ └─── (Default Guild Marks) │ ├─── logo1.avi │ ├─── logo2.avi │ ├─── metin2.ico │ ├─── metin2client.dat │ └─── metin2client_v23.1.2_x86.exe └─── Server/ └─── share/ ├─── data/ │ └─── (Motions) └─── package/ └─── (Hybridcrypt Keys 23.1.4)
External Link
MEGA:
M2DL:
Special thanks to those people who helped in making this archive.- 187
- 2
- 1
- 52
- 6
- 93
-
5 hours ago, nicohare711 said:
@ Owsap
I think you made a mistake in the part of the client source with the subject of subtypesCare to share what you're referring to exactly?
-
Spoiler4 minutes ago, nicohare711 said:
¿Cómo puedo arreglar esto? @ Owsap
char_item.cpp: en la función miembro 'bool CHARACTER::UseItemEx(LPITEM, TItemPos)':
char_item.cpp:6409:74: error: el uso de 'auto' en la declaración de parámetros lambda solo está disponible con -std=c++14 o -std=gnu++14
auto it = std::find_if(soul_map.begin(), soul_map.end(), [&](const auto& kv_pair) { ^~~~
char_item.cpp
: En la función lambda:
char_item. cpp:6410:23: error: solicitud de miembro 'segundo' en 'kv_pair', que no es de tipo de clase 'const int'
return kv_pair.segundo.punto_tipo == afecto.bApplyOn;
^~~~~~
En archivo incluido desde /usr/local/lib/gcc8/include/c++/bits/stl_algobase.h:71,
de /usr/local/lib/gcc8/include/c++/bits/char_traits.h:39,
de /usr/local/lib/gcc8/include/c++/string:40,
de ../../../ Externo/incluir/msl/utils.h:18,
desde ../../common/utils.h:1,
desde stdafx.h:15,
desde char_item.cpp:1:
/usr/local/lib/gcc8/ include/c++/bits/predefined_ops.h: En instanciación de 'bool __gnu_cxx::__ops::_Iter_pred<_Predicate>::operator()(_Iterator) [with _Iterator = std::__detail::_Node_iterator<std::pair< const carácter sin firmar, CARÁCTER::UseItemEx(LPITEM, TItemPos)::SoulData>, false, false>; _Predicado = CARÁCTER::UseItemEx(LPITEM, TItemPos)::<lambda(const int&)>]':
/usr/local/lib/gcc8/include/c++/bits/stl_algo.h:104:42: requerido de '_InputIterator std::__find_if(_InputIterator, _InputIterator, _Predicate, std::input_iterator_tag) [con _InputIterator = std:: __detail::_Node_iterator<std::pair<const unsigned char, CHARACTER::UseItemEx(LPITEM, TItemPos)::SoulData>, false, false>; _Predicado = __gnu_cxx::__ops::_Iter_pred<CHARACTER::UseItemEx(LPITEM, TItemPos)::<lambda(const int&)> >]'
/usr/local/lib/gcc8/include/c++/bits/stl_algo.h: 161:23: requerido de '_Iterator std::__find_if(_Iterator, _Iterator, _Predicate) [with _Iterator = std::__detail::_Node_iterator<std::pair<const unsigned char, CHARACTER::UseItemEx(LPITEM, TItemPos): :SoulData>, falso, falso>; _Predicado = __gnu_cxx::__ops::_Iter_pred<CHARACTER::UseItemEx(LPITEM, TItemPos)::
/usr/local/lib/gcc8/include/c++/bits/stl_algo.h:3930:28: requerido de '_IIter std::find_if(_IIter, _IIter, _Predicate) [with _IIter = std::__detail::_Node_iterator< std::pair<const unsigned char, CHARACTER::UseItemEx(LPITEM, TItemPos)::SoulData>, false, false>; _Predicate = CHARACTER::UseItemEx(LPITEM, TItemPos)::<lambda(const int&)>]'
char_item.cpp:6411:9: requerido desde aquí
/usr/local/lib/gcc8/include/c++/bits/predefined_ops. h:283:11: error: no hay coincidencia para llamar a '(CHARACTER::UseItemEx(LPITEM, TItemPos)::<lambda(const int&)>) (std::pair<const unsigned char, CHARACTER::UseItemEx(LPITEM , TItemPos)::SoulData>&)'
{ return bool(_M_pred(*__it)); }
^~~~~~~~~~~~~~~~~~~~
char_item.cpp:6409:87: nota: candidato: 'CHARACTER::UseItemEx(LPITEM, TItemPos)::<lambda(const int&)>' auto it =
std::find_if(soul_map.begin(), soul_map.end( ), [&](const auto& kv_pair) {
^
char_item.cpp:6409:87: nota: ninguna conversión conocida para el argumento 1 de 'std::pair<const unsigned char, CHARACTER::UseItemEx(LPITEM, TItemPos):: SoulData>' a 'const int&'
gmake: *** [Makefile:185: .obj/char_item.o] Error 1
root@jailsrc:/usr/src/Server/game/src #To fix this, you can either update the compiler flag to use C++14 or later by adding std=c++14 in your Makefile, or you can specify the data type of the lambda parameter explicitly instead of using auto.
For example, instead of:
auto it = std::find_if(soul_map.begin(), soul_map.end(), [&](const auto& kv_pair) { return kv_pair.second.point_type == affect.bApplyOn; });
You can try:
auto it = std::find_if(soul_map.begin(), soul_map.end(), [&](const std::pair<const BYTE, SoulData>& kv_pair) { return kv_pair.second.point_type == affect.bApplyOn; });
I will not reply to every single error you could encounter due to C++ version warnings. Please consider upgrading your version to at least C++14.
-
3 hours ago, WeedHex said:
What about those who have recently bought on your site?
Thanks anyway!
I could answer that, but to be honest, it's none of your business.
- 1
- 1
- 1
-
Temporarily boosts the character's physical attack and / or skill damage.
You can learn more about the system from the official wiki page.Thanks to @blackdragonx61 for the reversed effect position.
- 183
- 1
- 3
- 1
- 37
- 7
- 89
-
As the title indicates, I'm sharing with everyone my test script for creating UI's, systems, etc...
The advantage of this tool is that you don't need to restart your client every time you make a change which time is crucial.This tool will certainly help you tremendously if you know how to use it correctly.
I will not go in much detail on how to use it because it's very basic and understandable.As long as you respect the primary class name and contain the default methods in the class, you're good.
Otherwise, if you know what you're doing then you can modify the script to your liking.
uiTestScript.py
# # File : uiTestScript.py # Author : Owsap # Copyright (C) 2023 Owsap Development # import app import ui import wndMgr import uiToolTip import localeInfo """ # Example: # uiTest.py class TestWindow(ui.ScriptWindow): def __init__(self): ui.ScriptWindow.__init__(self) def __del__(self): ui.ScriptWindow.__del__(self) def Show(self): ui.ScriptWindow.Show(self) def Hide(self): ui.ScriptWindow.Hide(self) """ def LoadModule(name): import sys, imp if name in sys.modules: del sys.modules[name] if name in locals(): del locals()[name] if name in globals(): del globals()[name] module_info = imp.find_module(name) module = imp.load_module(name, *module_info) if not module in locals(): locals()[name] = module if not module in globals(): globals()[name] = module return module class TestScript(ui.BoardWithTitleBar): BOARD_WIDTH = 230 BOARD_HEIGHT = 80 SLOT_WIDTH = 150 def __init__(self): ui.BoardWithTitleBar.__init__(self) self.wndScript = None ## Item ToolTip self.tooltipItem = uiToolTip.ItemToolTip() self.tooltipItem.Hide() ## Board self.SetSize(self.BOARD_WIDTH, self.BOARD_HEIGHT) self.SetPosition(0, wndMgr.GetScreenHeight() - self.BOARD_HEIGHT) self.AddFlag("movable") self.SetTitleName("Test Script") self.SetCloseEvent(self.Hide) self.Show() ## Board > Slot Bar slotBar = ui.SlotBar() slotBar.SetParent(self) slotBar.SetSize(self.SLOT_WIDTH, 18) slotBar.SetPosition(13, 32) slotBar.Show() self.slotBar = slotBar ## Board > Slot Bar > EditLine editLine = ui.EditLine() editLine.SetParent(self.slotBar) editLine.SetSize(self.SLOT_WIDTH, 18) editLine.SetPosition(4, 3) editLine.SetMax(30) editLine.SetText("uiTest") editLine.Show() self.editLine = editLine ## Board > Load Button loadButton = ui.Button() loadButton.SetParent(self) loadButton.SetPosition(self.SLOT_WIDTH + 23, 32) loadButton.SetUpVisual("d:/ymir work/ui/public/small_button_01.sub") loadButton.SetOverVisual("d:/ymir work/ui/public/small_button_02.sub") loadButton.SetDownVisual("d:/ymir work/ui/public/small_button_03.sub") loadButton.SetEvent(self.__OnClickLoadButton) loadButton.SetText("Load") loadButton.Show() self.loadButton = loadButton ## Board > TextLine (Print Mouse Position) self.textLine = ui.TextLine() self.textLine.SetParent(self) self.textLine.SetFontName(localeInfo.UI_DEF_FONT) self.textLine.SetWindowHorizontalAlignCenter() self.textLine.SetHorizontalAlignCenter() self.textLine.SetWindowVerticalAlignBottom() self.textLine.SetVerticalAlignBottom() self.textLine.SetPosition(0, 13) self.textLine.SetText("Tip: Press F10 to load / reload.") self.textLine.Show() def __del__(self): ui.BoardWithTitleBar.__del__(self) del self.tooltipItem del self.tooltipSkill self.slotBar = None self.editLine = None self.loadButton = None self.textLine = None def Show(self): ui.BoardWithTitleBar.Show(self) def Hide(self): ui.BoardWithTitleBar.Hide(self) def OnKeyDown(self, key): if key == app.DIK_F10: self.__OnClickLoadButton() def __OnClickLoadButton(self): module_name = self.editLine.GetText() if not module_name: print("Empty module name") return if self.wndScript: self.wndScript.Hide() del self.wndScript self.wndScript = None try: module = LoadModule(module_name) except Exception as error: print("Error loading module: %s" % str(error)) return self.wndScript = module.TestWindow() #self.wndScript.SetItemToolTip(self.tooltipItem) self.wndScript.Show() wndTestScript = TestScript() wndTestScript.Show()
Requirements
In order to use this tool, you must make sure it executes the module when the client is started, if you're familiar with loginInfo.py, it's practically the same thing.
Make sure you only enable this feature on a debug build for testing purposes.
Simply add the script above on your main client directory and you're ready.""" 1. @ introLogin.py """ # Search if musicInfo.loginMusic != "": snd.SetMusicVolume(systemSetting.GetMusicVolume()) snd.FadeInMusic("BGM/"+musicInfo.loginMusic) # Add above self.__LoadTestFile("uiTestScript.py") """ 2. @ introLogin.py """ # Search def PopupDisplayMessage(self, msg): # Add above def __LoadTestFile(self, fileName): try: testScriptDict = {} execfile(fileName, testScriptDict) except: pass
Here is an example of the uiTest.py file that will be loaded but you can load any other module that you add in your client main directory.
Spoiler# # File : uiTest.py # import ui class TestWindow(ui.ScriptWindow): def __init__(self): ui.ScriptWindow.__init__(self) self.__LoadWindow() def __del__(self): ui.ScriptWindow.__del__(self) def __LoadWindow(self): try: self.__LoadScript("UIScript/SelectItemWindow.py") except: import exception exception.Abort("TestWindow.LoadWindow.LoadObject") def __LoadScript(self, fileName): pyScrLoader = ui.PythonScriptLoader() pyScrLoader.LoadScriptFile(self, fileName) def Show(self): ui.ScriptWindow.Show(self) def Hide(self): ui.ScriptWindow.Hide(self)
Enjoy.
- 14
- 3
- 1
- 10
-
11 hours ago, Nuzzo said:
Add this in your PythonPlayerModule.cpp, you should add it at the end of the file above "}".
PyModule_AddIntConstant(poModule, "ITEM_SLOT_COUNT", c_ItemSlot_Count);
-
Nice job, now they're really getting pissed.
- 4
bug party
in Community Support - Questions & Answers
Posted