-
Posts
265 -
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
-
-
-
Replace auto_ptr with unique_ptr.
QuoteThe C++11 standard made auto_ptr deprecated, replacing it with the unique_ptr class template. auto_ptr was fully removed in C++17. For shared ownership, the shared_ptr template class can be used. shared_ptr was defined in C++11 and is also available in the Boost library for use with previous C++ versions.
Reference: https://en.wikipedia.org/wiki/Auto_ptr
- 2
-
This is due to the dump_proto only reading one value although you have more values separated with a delimiter so you have to make sure you have the right delimiter.
If your mob_proto.txt has for example:ANIMAL,ZODIAC
You have to make sure your dump_proto is reading the symboly ,
And if your dump_proto for example has:ANIMAL|ZODIAC
Then the delimiter you should be using is |
Here is an example./// 1. @ dump_proto/ItemCSVReader.cpp // Search @ int get_Mob_RaceFlag_Value string* arInputString = StringSplit(inputString, "|"); // 프로토 정보 내용을 단어별로 쪼갠 배열. // Replace with string* arInputString = StringSplit(inputString, ","); // 프로토 정보 내용을 단어별로 쪼갠 배열.
- 1
-
Here is a rather "complete" tutorial and I hope you understand.
First, let's start with the Server Source.
Server Source
Spoiler/// 1. @ game/char.cpp // Search @ void CHARACTER::PointChange default: sys_err("CHARACTER::PointChange: %s: unknown point change type %d", GetName(), type); return; // Add above case POINT_MY_NEW_BONUS: SetPoint(type, GetPoint(type) + amount); val = GetPoint(type); break; /// 2. @ common/length.h // Search MAX_APPLY_NUM, // Add above APPLY_MY_NEW_BONUS, /// 3. @ game/char.cpp // Search default: sys_err("Unknown apply type %d name %s", bApplyType, GetName()); break; // Add above case APPLY_MY_NEW_BONUS: PointChange(aApplyInfo[bApplyType].bPointType, iVal); break; /// 4. @ game/char.h // Search @ enum EPointTypes //POINT_MAX_NUM = 255 common/length.h // Add above POINT_MY_NEW_BONUS, /// 5. @ game/constants.cpp // Extend aApplyInfo[MAX_APPLY_NUM] with { POINT_MY_NEW_BONUS, }, // APPLY_MY_NEW_BONUS // Example { POINT_RESIST_PENETRATE, }, // APPLY_ANTI_PENETRATE_PCT, 91 { POINT_MY_NEW_BONUS, }, // APPLY_MY_NEW_BONUS }; /// 6. @ game/constants.cpp // Search @ TValueName c_aApplyTypeNames[] = { NULL, 0 } // Add above { "MY_NEW_BONUS", APPLY_MY_NEW_BONUS }, /// 7. Example /* * Now it all depends on what you want to do with this bonus. * I will give you an example of how this bonus could be applied for Metin Stones. */ /// @ game/battle.cpp // Search @ int CalcAttBonus iAtk += (iAtk * pkAttacker->GetPoint(POINT_ATTBONUS_MONSTER)) / 100; // Add below if (pkVictim->IsStone()) iAtk += (iAtk * pkAttacker->GetPoint(POINT_MY_NEW_BONUS)) / 100; /// 8. @ db/ProtoReader.cpp // Search @ get_Item_ApplyType_Value and extend arApplyType[] with "APPLY_MY_NEW_BONUS", // Example "APPLY_ANTI_PENETRATE_PCT", "APPLY_MY_NEW_BONUS", };
We can do the MySQL part now since we have finished with the server part.
MySQLSpoiler/* * Search @ Database (Use Navicat, it's a great piece of software.) * player.item_attr * * 1. Edit / Design table. * * 2. Extended the "apply" row "Values" with "MY_NEW_BONUS". * * 3. Save table. * * 4. Open player.item_attr table and add the new bonus type. * * apply prob lv1 lv2 lv3 lv4 lv5 weapon body ... * MY_NEW_BONUS 1 2 4 6 10 15 0 0 ... * * 5. You can also do the same procedure above for the item_attr_rare (this table is for the 6/7 bonus) * */
Now let's move on to the Client Source.
Client SourceSpoiler/// 1. @ GameLib/ItemData.h // Search @ enum EApplyTypes MAX_APPLY_NUM = 255, // Add above APPLY_MY_NEW_BONUS, /// 2. @ UserInterface/Packet.h // Search @ enum EPointTypes // 클라이언트 포인트 POINT_MIN_WEP = 200, // Add above POINT_MY_NEW_BONUS, /// 3. @ UserInterface/PythonItemModule.cpp // Search PyModule_AddIntConstant(poModule, "APPLY_PENETRATE_PCT", CItemData::APPLY_PENETRATE_PCT); // Add below PyModule_AddIntConstant(poModule, "APPLY_MY_NEW_BONUS", CItemData::APPLY_MY_NEW_BONUS); /// 4. @ UserInterface/PythonPlayerModule.cpp // Search PyModule_AddIntConstant(poModule, "POINT_PENETRATE_PCT", POINT_PENETRATE_PCT); // Add below PyModule_AddIntConstant(poModule, "POINT_MY_NEW_BONUS", POINT_MY_NEW_BONUS);
Let's not forget our special tool, DumpProto.
DumpProtoSpoiler/// 1. @ dump_proto/ItemCSVReader.cpp // Search @ int get_Item_ApplyType_Value and extend arApplyType[] with "APPLY_MY_NEW_BONUS", // Example "APPLY_ANTI_PENETRATE_PCT", "APPLY_MY_NEW_BONUS", };
Last but not least your client needs to read the new bonus type.
Client Root
Spoiler''' 1. @ root/uiToolTip.py ''' # Search @ class ItemToolTip AFFECT_DICT = { # Extend with item.APPLY_MY_NEW_BONUS : localeInfo.TOOLTIP_APPLY_MY_NEW_BONUS,
And finally, your bonus needs a name.
Client Locale
Spoiler-- 1. @ locale/x/locale_game.txt -- Add inside TOOLTIP_APPLY_MY_NEW_BONUS TOOLTIP_APPLY_ATTBONUS_WARRIOR My New Bonus +%d%% SA
⚠ Following the order of the points and apply types are very important, make sure every modification is in order since an incorent order may read another bonus.
Sincerely, Owasp.
- 2
- 3
- 3
-
You can try to add a pulse for that.
/// 1. @ common/service.h // Add #define __CHANGE_STAT_PULSE__ /// 2. @ game/char.h // Search }; ESex GET_SEX(LPCHARACTER ch); // Add above #if defined(__CHANGE_STAT_PULSE__) public: int GetChangeStatPulse() { return m_iChangeStatPulse; } void SetChangeStatPulse(int iPulse) { m_iChangeStatPulse = iPulse; } protected: int m_iChangeStatPulse; #endif /// 3. @ char.cpp // Search @ void CHARACTER::Initialize m_dwNextStatePulse = 0; // Add below #if defined(__CHANGE_STAT_PULSE__) m_iChangeStatPulse = 0; #endif /// 4. @ cmd_general.cpp // Search @ ACMD(do_stat) if (ch->GetRealPoint(idx) >= MAX_STAT) return; // Add below #if defined(__CHANGE_STAT_PULSE__) if (ch->GetChangeStatPulse() > thecore_pulse()) { if (test_server) ch->ChatPacket(CHAT_TYPE_INFO, "Slow down, you're changing stats to fast!"); return; } ch->SetChangeStatPulse(thecore_pulse() + PASSES_PER_SEC(10 * 1)); #endif
- 1
- 1
-
3 hours ago, memett4545 said:
I did not understand how to solve the problem
Just add it above the class in the char_manager.h file.
class CHARACTER_MANAGER : public singleton<CHARACTER_MANAGER>
Result
#if defined(__EVENT_BANNER_FLAG__) typedef std::map<DWORD, std::string> BannerMapType; #endif class CHARACTER_MANAGER : public singleton<CHARACTER_MANAGER>
-
15 minutes ago, Kafa said:
This worked. Thank you
The issue was that the banner list wasn't being initialized with the command if the game event flag wasn't enabled before.
So here is what you must change;/// 1. // Search @ CHARACTER_MANAGER::SpawnBanners if (!m_bIsLoadedBanners) return false; // Replace with if (!m_bIsLoadedBanners) InitializeBanners();
Topic: Updated MEGA (Link) & committed an updated to the repository. -
Just now, Kafa said:
They're all implemented bro.
Type /e banner 20143, wait 5 - 10 seconds and restart the server and then check if they have appeared.
-
2 minutes ago, Kafa said:
Do you have the NPC's implemented?
20127 Anniversary Banner 1 20128 Anniversary Banner 2 20129 Anniversary Banner 3 20130 Anniversary Banner 4 20131 Anniversary Banner 5 20132 Anniversary Banner 6 20133 Anniversary Banner 7 20134 Solar Banner 20135 Christmas Banner 20138 Ramadan Banner 20142 Halloween Banner 20143 Easter Banner
-
4 minutes ago, Kafa said:
And regarding to this topic. If i type /banner 1 easter nothing really happens, everything is correct..
Did you add the data files to your server files?
And please show your char_manager.cpp and char_manager.h
You can use https://metin2.dev/bin/ to paste your files.
- 2
-
13 minutes ago, Kafa said:
This doesnt work for me, the first release (Slot Machine) doesnt work too.
In Slot Machine i get a core crash..
You must show us the problem, what errors are you having? You cannot expect help just by saying that it doesn't work or it crashes.
Can you run the debugger (gdb)?First of all, if you don’t have the gdb package run the command: pkg install -y gdb
Learn how-to here:In short these are the commands that you need:
[root@localhost ~]# cd < Directory were .core is generated > [root@localhost ~]# gdb [root@localhost ~]# set gnutarget i386-marcel-freebsd [root@localhost ~]# file < Name of the core file > [root@localhost ~]# core < Name of the .core file > [root@localhost ~]# bt full [root@localhost ~]# backtrace
Here is an example of how it should look like:
[root@localhost ~]# cd /m2server/game/channel1/core1 [root@localhost ~]# gdb [root@localhost ~]# set gnutarget i386-marcel-freebsd [root@localhost ~]# file game [root@localhost ~]# core game.core [root@localhost ~]# bt full [root@localhost ~]# backtrace
Do you also have errors while compiling? If yes, show us the complete output of the compiler errors.Please make sure before posting, you are submitting the issues regarding the post / system to avoid off-topic.
Sincerely,
Owasp.- 2
- 2
-
M2 Download Center
( Internal )
( MEGA )
( GitHub )Hello, this release is nothing special but I hope someone finds it useful for their server.
Introduced in the 10th anniversary of Metin2, your city will look more appealing with banner flags describing the on-going event your server is currently running.
SpoilerHow to add more banners?
@ data/banner/list.txt
___________________ | VNUM | NAME | |------ | ----------| | 20142 | halloween | | 20143 | easter | | 20135 | xmas | ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
You can simply add more banner flags following the example above.
VNUM is the VNUM / ID of the NPC.
NAME is the name of the command and file of the banner.Note: If you want to add for example the Ramadan Banner which VNUM is 20138, this is how you should do it step by step.
-
Edit @ data/banner/list.txt and extended the file with:
___________________ | VNUM | NAME | |------ | ----------| | 20138 | ramadan | ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
-
Make duplicates of the existing banners.
-
Copy data/banner/a/xmas.txt and rename the duplicated file to data/banner/a/ramadan.txt
Edit data/banner/a/ramadan.txt and replace the VNUM / ID with the Ramadan Banner 20138.
-
Copy data/banner/b/xmas.txt and rename the duplicated file to data/banner/b/ramadan.txt
Edit data/banner/b/ramadan.txt and replace the VNUM / ID with the Ramadan Banner 20138.
-
Copy data/banner/c/xmas.txt and rename the duplicated file to data/banner/c/ramadan.txt
Edit data/banner/c/ramadan.txt and replace the VNUM / ID with the Ramadan Banner 20138.
-
Copy data/banner/a/xmas.txt and rename the duplicated file to data/banner/a/ramadan.txt
-
@ Source/Client/UserInterface/InstanceBase.cpp
Search#if defined(ENABLE_EVENT_BANNER_FLAG) BOOL CInstanceBase::IsBannerFlag() { if (GetRace() >= 20127 && GetRace() <= 20143) return TRUE; return FALSE; } #endif
Replace with (If you want it to be more manageable)
#if defined(ENABLE_EVENT_BANNER_FLAG) BOOL CInstanceBase::IsBannerFlag() { switch(GetRace()) { case 20127: // Anniversary Banner 1 case 20128: // Anniversary Banner 2 case 20129: // Anniversary Banner 3 case 20130: // Anniversary Banner 4 case 20131: // Anniversary Banner 5 case 20132: // Anniversary Banner 6 case 20133: // Anniversary Banner 7 case 20134: // Solar Banner case 20135: // Christmas Banner case 20138: // Ramadan Banner case 20142: // Halloween Banner case 20143: // Easter Banner return TRUE; } return FALSE; } #endif
Don't forget each folder (a / b / c) have different positions so be careful when copying files.
How to activiate?
In-game, you can use the command:
/banner < x > < banner_name > where < x > is the status ( 1 : ON / 0 : OFF ) and < banner_name > is the name of the banner @ data/banner/list.txt- 76
- 1
- 1
- 3
- 2
- 1
- 15
- 1
- 5
- 47
-
Edit @ data/banner/list.txt and extended the file with:
-
Here, use int for the loop and you can also use the default number function to randomize the numbers.
for (int bSlot = 0; bSlot < ESlotMachine::MAX_SLOT_MACHINE_SLOTS; ++bSlot) { m_bSlotMachineReel[bSlot] = number(1, (iSlotMachineReels > 0 ? iSlotMachineReels : ESlotMachine::MAX_SLOT_MACHINE_REELS)); }
-
On 3/26/2021 at 1:07 PM, memett4545 said:
I have forgot to change that to GOLD_MAX.
On 3/26/2021 at 1:57 PM, filipw1 said:First of all, I bet you will have more problems that this one, so you should create a topic in Q&A section, but for now, change "g_MaxGold" to "GOLD_MAX"
In fact there were some mistakes that I forgot to remove and to included.
I have reviewed the system on a clean server revision 40250.
Topic updated,
Additional information, reviewed code & updated files.
If any one encounters any problem regarding the system please let me know.- 1
-
M2 Download Center
( Internal )
( MEGA )
( GitHub )Hello again M2Dev,
It’s been quite I wile since I haven’t released anything for the community so today I decided to release one of my systems I created some days ago, it’s very simple and it consists on gambling to say the least…
Spoiler
The point is to bet your money (yang/gold) on a higher amount of gold and the higher you bet the higher the payout is, similar as how a casino slot machine works without being too complex.
The rules are simple, you have three (3) possible jackpots in which each one has a payout amount.
Hit the same icon three (3) times and you will win the jackpot.If you get any other combination that contain jackpot reel icons, you will win half your bet back with a short bet multiplier.
So, the jackpot reels work as so,
A, A, A = Jackpot 1
B, B, B = Jackpot 2
C, C, C = Jackpot 3All other possible combinations to have a winning: A, A, B; A, A, C; B, B, A; B, B, C; C, C, A; C, C, B; A, B, C; C, A, B; B, A, C; C, B, A; A, C, B;
If you happen to win a jackpot while having close to maximum gold, you will receive an item in your inventory if you have space for it otherwise you will receive it in your storage room. The item will contain the jackpot value.
How to configure?
@ game/constants.cpp you can edit all the betting values you want.
@ game/contants.cpp you can edit as well the jackpot values.
@ root/uiSlotMachineSystem.py you can edit the reel icons and bet values.In-game, you can also use the commands,
/e slot_machine_reels < x > where < x > is the number of reels you want to randomize.
The more reel icons you have, the harder it is to win a jackpot!/e slot_machine_multiplier < x > where < x > is the value of the multiplied you want.
The higher this value, the higher the payout is.Additional information
For those who are using older versions of C++ some data type identifiers need to be changed as shown below.
- uint64_t = unsigned long long
- uint32_t = UINT
- int32_t = INT
- uint16_t = WORD
- uint8_t = BYTE
Sincerly,
Owsap
- 66
- 1
- 1
- 2
- 2
- 1
- 1
- 3
- 14
- 8
- 55
-
3 minutes ago, CaNNab1S said:
It works now. Thank you very much. Can you tell me if the function is ok now ?
OLD: https://metin2.download/picture/P9ONfzv2Dm8BZNWwTnsJIv426cV6T5ZG/.png
NEW: https://metin2.download/picture/SWjAEo4FP2MJAN6sYKvDe33c8GSspIFG/.png
Yes, that's correct.
- 2
-
Here is your problem.
Change
int iRet; if(iRet != BATTLE_NONE) { pkVictim->SetSyncOwner(this); if (pkVictim->CanBeginFight()) pkVictim->BeginFight(this); }
With
pkVictim->SetSyncOwner(this); if (pkVictim->CanBeginFight()) pkVictim->BeginFight(this); int iRet;
- 2
-
Show us your CHARACTER::Attack function from char_battle.cpp
-
GitHub Repository:
Preview: https://metin2.download/picture/3m27cf351hv67tz592fY1akdHlKKN5Zs/.gif
- 58
- 1
- 1
- 8
- 41
-
6 hours ago, kaJaMrSimple said:
yes that's exactly what I want. but how can we add map and duration? (by the way I haven't tried yet if it works)
/// 1. @ game/src/char_manager.cpp // Search LPCHARACTER CHARACTER_MANAGER::SpawnMob(DWORD dwVnum, long lMapIndex, long x, long y, long z, bool bSpawnMotion, int iRot, bool bShow) { const CMob* pkMob = CMobManager::instance().Get(dwVnum); if (!pkMob) { sys_err("SpawnMob: no mob data for vnum %u", dwVnum); return NULL; } // Add below unsigned long ulRestricedMapIndex[] = { 3, 23, 43 }; if (g_bChannel > 1 /* Check channel */ && std::find(std::begin(ulRestricedMapIndex), std::end(ulRestricedMapIndex), mapindex) != std::end(ulRestricedMapIndex) /* Search the map index for this mob spawn */) { switch (dwVnum /* Mob VNUM */ ) { case 591: // Bestial Captain (Normally spawns @ metin2_map_a3, metin2_map_b3, metin2_map_c3) return NULL; } }
I'm not sure what you want with "duration" but the block of code above will block the spawn of the monster VNUM inside the switch which spawns in the map index inside the ulRestricedMapIndex array.
-
If I read your question correctly, you want to spawn a monster (boss) only in channel 1.
You can try this, I have not tested it.
Let me know if it works.
/// 1. @ game/src/char_manager.cpp // Search LPCHARACTER CHARACTER_MANAGER::SpawnMob(DWORD dwVnum, long lMapIndex, long x, long y, long z, bool bSpawnMotion, int iRot, bool bShow) { const CMob* pkMob = CMobManager::instance().Get(dwVnum); if (!pkMob) { sys_err("SpawnMob: no mob data for vnum %u", dwVnum); return NULL; } // Add below if (g_bChannel > 1) { switch (dwVnum) { case 591: // Bestial Captain (metin2_map_a3, metin2_map_b3, metin2_map_c3) return NULL; } }
- 1
-
Search for static void GrannyError in UserInterface.cpp.
- 1
-
1 minute ago, Arkane2 said:
0526 23:53:25663 :: Traceback (most recent call last): 0526 23:53:25663 :: File "game.py", line 1802, in OnMouseLeftButtonUp 0526 23:53:25663 :: File "interfaceModule.py", line 462, in MakeHyperlinkTooltip 0526 23:53:25663 :: File "uiToolTip.py", line 2549, in SetHyperlinkItem 0526 23:53:25663 :: NameError 0526 23:53:25663 :: : 0526 23:53:25663 :: global name 'transmutation' is not defined
0526 23:53:25663 :: Traceback (most recent call last): 0526 23:53:25663 :: File "game.py", line 1802, in OnMouseLeftButtonUp 0526 23:53:25663 :: File "interfaceModule.py", line 462, in MakeHyperlinkTooltip 0526 23:53:25663 :: File "uiToolTip.py", line 2549, in SetHyperlinkItem 0526 23:53:25663 :: NameError 0526 23:53:25663 :: : 0526 23:53:25663 :: global name 'transmutation' is not defined
When i try to click in chat https://metin2.download/picture/m6iaJxZwBitV23oXZEBzO32A7n8Y9KWu/.png
Check again, I have updated it.
- 1
-
Give this a try,
root/uiToolTip.py
Spoilerclass HyperlinkItemToolTip(ItemToolTip): def __init__(self): ItemToolTip.__init__(self, isPickable=TRUE) def SetHyperlinkItem(self, tokens): minTokenCount = 3 + player.METIN_SOCKET_MAX_NUM if app.ENABLE_CHANGELOOK_SYSTEM: minTokenCount += 1 maxTokenCount = minTokenCount + 2 * player.ATTRIBUTE_SLOT_MAX_NUM if tokens and len(tokens) >= (minTokenCount - 1 if app.ENABLE_CHANGELOOK_SYSTEM else minTokenCount) and len(tokens) <= maxTokenCount: head, vnum, flag = tokens[:3] itemVnum = int(vnum, 16) metinSlot = [int(metin, 16) for metin in tokens[3:6]] if app.ENABLE_CHANGELOOK_SYSTEM: changelookvnum = int(tokens[6], 16) rests = tokens[7:] else: rests = tokens[6:] if rests: attrSlot = [] rests.reverse() while rests: key = int(rests.pop(), 16) if rests: val = int(rests.pop()) attrSlot.append((key, val)) attrSlot += [(0, 0)] * (player.ATTRIBUTE_SLOT_MAX_NUM - len(attrSlot)) else: attrSlot = [(0, 0)] * player.ATTRIBUTE_SLOT_MAX_NUM self.ClearToolTip() if app.ENABLE_CHANGELOOK_SYSTEM: if not changelookvnum: self.AddItemData(itemVnum, metinSlot, attrSlot, 1) else: self.AddItemData(itemVnum, metinSlot, attrSlot, 1, 0, 0, player.INVENTORY, -1, changelookvnum) else: self.AddItemData(itemVnum, metinSlot, attrSlot, 1) ItemToolTip.OnUpdate(self) def OnUpdate(self): pass def OnMouseLeftButtonDown(self): self.Hide()
Owsap Alignment Affect
in Community Support - Questions & Answers
Posted