metin2-factory
-
Posts
174 -
Joined
-
Last visited
-
Days Won
13 -
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by metin2-factory
-
-
Small update:
Added tool tip to make it more clear for players, follow the steps below to have it.
Like this post if you find it useful
Screens:
in _init_ and in Destroy methods look for:
if app.ENABLE_VIEW_ELEMENT: self.elementImage = None
replace with:
if app.ENABLE_VIEW_ELEMENT: self.elementImage = None self.elementId = None self.elementImageToolTip = None
search for:
def Close(self):
add inside the method:
if app.ENABLE_VIEW_ELEMENT and self.elementImage: self.elementImage.Hide()
Search for:
ELEMENT_IMAGE_DIC = {1: "elect", 2: "fire", 3: "ice", 4: "wind", 5: "earth", 6: "dark"}
add above:
import uiToolTip
inside ResetTargetBoard method look for:
if app.ENABLE_VIEW_ELEMENT and self.elementImage: self.elementImage = None
replace with:
if app.ENABLE_VIEW_ELEMENT and self.elementImage: self.elementImage = None self.elementId = None if self.elementImageToolTip: self.elementImageToolTip.Hide()
Look for:
def SetElementImage(self, elementId):
replace the whole method with:
def SetElementImage(self, elementId): try: if elementId > 0 and elementId in ELEMENT_IMAGE_DIC.keys(): self.elementId = elementId self.elementImage = ui.ImageBox() self.elementImage.SAFE_SetStringEvent("MOUSE_OVER_IN", self.OnElementImageOverIn) self.elementImage.SAFE_SetStringEvent("MOUSE_OVER_OUT", self.OnElementImageOverOut) self.elementImage.SetPosition(self.GetLeft() - 40, self.GetTop()) self.elementImage.LoadImage( "d:/ymir work/ui/game/12zi/element/%s.sub" % (ELEMENT_IMAGE_DIC[elementId])) self.elementImage.Show() except: pass def OnElementImageOverIn(self): if not self.elementImageToolTip: self.elementImageToolTip = uiToolTip.ToolTip() self.elementImageToolTip.ClearToolTip() self.elementImageToolTip.AppendTextLine(ELEMENT_IMAGE_DIC[self.elementId] + " element") self.elementImageToolTip.SetToolTipPosition(self.GetLeft() - 40, self.GetTop() + 70) self.elementImageToolTip.Show() def OnElementImageOverOut(self): if self.elementImageToolTip: self.elementImageToolTip.Hide()
That's it.
Enjoy!
- 2
- 6
-
19 minutes ago, Sonitex said:
That's the worst part, there is no errors...
use sys_err function server side(char.cpp) and print in python(game.py) to find bElement value.
it should be between 1 and 6 for elemental mobs. if it's not in this range then you did something wrong.
Also, make sure in mob_proto server side the mobs race is with ATT_
for example: ATT_ICE, ATT_FIRE, ATT_WIND etc etc- 3
-
8 minutes ago, Sonitex said:
Check your tabs at line 142 in uiTarget.py
@metin2-factory I seem to have the same problem as others, element icons are not showing up for some reason.
Do you get any error? check syserr.txt client side
-
2 hours ago, Horinna said:
PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "SetHPTargetBoard", Py_BuildValue("(iiiii)", TargetPacket.dwVID, TargetPacket.bHPPercent, TargetPacket.bElement));
to
PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "SetHPTargetBoard", Py_BuildValue("(iii)", TargetPacket.dwVID, TargetPacket.bHPPercent, TargetPacket.bElement));
Thanks, i'v updated my post.
If you have the error below:
1028 16:37:29247 :: TypeError
1028 16:37:29247 :: :
1028 16:37:29247 :: SetHPTargetBoard() takes exactly 4 arguments (6 given)
1028 16:37:29247 ::
open PythonNetworkPhaseGame and modify as above -
Hey there,
I have an Halloween gift for you all. i have been working for a few hours on official like element image on target window(See screenshots below).
When you click on a mob if it is defined as elemental, it will open an element image in addition to the target window.
Don't forget to hit the like button!
(C) Metin2 guild wars - coded by [GA]Ruin - 27/10/2017 (I create custom metin2 systems in c++/python. if you want a custom system send me a pm and we can talk over skype).
Let's begin!
Server Side:Open service.h, add in the end:
#define ELEMENT_TARGET
Open char.cpp, search for
else { p.dwVID = 0; p.bHPPercent = 0; }
add below:
#ifdef ELEMENT_TARGET const int ELEMENT_BASE = 11; DWORD curElementBase = ELEMENT_BASE; DWORD raceFlag; if (m_pkChrTarget && m_pkChrTarget->IsMonster() && (raceFlag = m_pkChrTarget->GetMobTable().dwRaceFlag) >= RACE_FLAG_ATT_ELEC) { for (int i = RACE_FLAG_ATT_ELEC; i <= RACE_FLAG_ATT_DARK; i *= 2) { curElementBase++; int diff = raceFlag - i; if (abs(diff) <= 1024) break; } p.bElement = curElementBase - ELEMENT_BASE; } else { p.bElement = 0; } #endif
open packet.h, search for:
} TPacketGCTarget;
add above:
#ifdef ELEMENT_TARGET BYTE bElement; #endif
Client side:
open locale_inc.h, add in the end:
#define ELEMENT_TARGET
open packet.h, search for
} TPacketGCTarget;
add above:
#ifdef ELEMENT_TARGET BYTE bElement; #endif
open PythonNetworkPhaseGame.cpp, look for:
else if (pInstPlayer->CanViewTargetHP(*pInstTarget))
replace below with the following:
#ifdef ELEMENT_TARGET PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "SetHPTargetBoard", Py_BuildValue("(iii)", TargetPacket.dwVID, TargetPacket.bHPPercent, TargetPacket.bElement)); #else PyCallClassMemberFunc(m_apoPhaseWnd[PHASE_WINDOW_GAME], "SetHPTargetBoard", Py_BuildValue("(ii)", TargetPacket.dwVID, TargetPacket.bHPPercent)); #endif
open PythonApplicationModule.cpp, look for
#ifdef ENABLE_ENERGY_SYSTEM
add above:
#ifdef ELEMENT_TARGET PyModule_AddIntConstant(poModule, "ENABLE_VIEW_ELEMENT", 1); #else PyModule_AddIntConstant(poModule, "ENABLE_VIEW_ELEMENT", 0); #endif
open game.py, look for
def SetHPTargetBoard(self, vid, hpPercentage): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.Show()
replace with:
if app.ENABLE_VIEW_ELEMENT: def SetHPTargetBoard(self, vid, hpPercentage,bElement): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.SetElementImage(bElement) self.targetBoard.Show() else: def SetHPTargetBoard(self, vid, hpPercentage): if vid != self.targetBoard.GetTargetVID(): self.targetBoard.ResetTargetBoard() self.targetBoard.SetEnemyVID(vid) self.targetBoard.SetHP(hpPercentage) self.targetBoard.Show()
open uitarget.py, look for
import background
add below:
if app.ENABLE_VIEW_ELEMENT: ELEMENT_IMAGE_DIC = {1: "elect", 2: "fire", 3: "ice", 4: "wind", 5: "earth", 6 : "dark"}
look for:
self.isShowButton = False
add below:
if app.ENABLE_VIEW_ELEMENT: self.elementImage = None
inside Destroy method, look for:
self.__Initialize()
add below:
if app.ENABLE_VIEW_ELEMENT: self.elementImage = None
inside ResetTargetBoard method, look for:
self.hpGauge.Hide()
add below:
if app.ENABLE_VIEW_ELEMENT and self.elementImage: self.elementImage = None
look for :
def SetElementImage(self,elementId):
add above:
if app.ENABLE_VIEW_ELEMENT: def SetElementImage(self,elementId): try: if elementId > 0 and elementId in ELEMENT_IMAGE_DIC.keys(): self.elementImage = ui.ImageBox() self.elementImage.SetParent(self.name) self.elementImage.SetPosition(-60,-12) self.elementImage.LoadImage("d:/ymir work/ui/game/12zi/element/%s.sub" % (ELEMENT_IMAGE_DIC[elementId])) self.elementImage.Show() except: pass
Compile server, client source and root pack and that's it!
Enjoy!
Happy halloween!
- 112
- 1
- 3
- 1
- 2
- 6
- 2
- 27
- 6
- 180
-
8 hours ago, Tasho said:
Maybe he was want to do something with the sum.
Should look like that:
//PythonChat.h BOOL GetChatMode(DWORD dwID); //PythonChat.cpp BOOL CPythonChat::GetChatMode(DWORD dwID) { TChatSet * pChatSet = GetChatSetPtr(dwID); if (!pChatSet) return FALSE; BYTE byChatHistoryLogModes[] = { CHAT_TYPE_TALKING, CHAT_TYPE_INFO, CHAT_TYPE_NOTICE, CHAT_TYPE_PARTY, CHAT_TYPE_GUILD, CHAT_TYPE_SHOUT, #ifdef ENABLE_DICE_SYSTEM CHAT_TYPE_DICE_INFO #endif }; int iRet = 0; for (BYTE i = 0; i < _countof(byChatHistoryLogModes); i++) { if (pChatSet->CheckMode(byChatHistoryLogModes[i])) iRet += 1 << byChatHistoryLogModes[i]; } return iRet > 0; } //PythonChatModule.cpp PyObject * chatGetChatMode(PyObject* poSelf, PyObject* poArgs) { int iID; if (!PyTuple_GetInteger(poArgs, 0, &iID)) return Py_BuildException(); return Py_BuildValue("b", CPythonChat::Instance().GetChatMode(iID)); } //Python def ToggleChatMode(self, mode): if self.allChatMode: self.allChatMode = False for i in self.CHAT_MODE_INDEX: chat.DisableChatMode(self.chatID, i) chat.EnableChatMode(self.chatID, mode) self.btnAll.SetUp() else: chat.ToggleChatMode(self.chatID, mode) if not chat.GetChatMode(self.chatID): self.btnAll.Down() self.ToggleAllChatMode()
well, since iRet is just for debug, this will be better.
BOOL CPythonChat::IsChatModeEnabled(DWORD dwID) { TChatSet * pChatSet = GetChatSetPtr(dwID); if (!pChatSet) return FALSE; for (BYTE i = 0; i < CHAT_TYPE_MAX_NUM; i++) { if (pChatSet->CheckMode(i)) return TRUE; } return FALSE; }
isModeEnabled = chat.IsChatModeEnabled(self.chatID) if not isModeEnabled: self.btnAll.Down() self.ToggleAllChatMode()
But anyway, it's not a big deal. everyone has its own style
-
ison, modeflag = chat.GetChatMode(self.chatID)
what is the modeflag variable used for?
is it needed anywhere or you added it just for debugging your code?
because i can't see it being used anywhere
-
A nice update has been released, look above
-
Looks good!
- 1
-
Every time you're using direct query it allocates new object of SQLMSg and it returns the pointer to this object.
it'd be preffered to be handled by an auto_ptr so it would deallocate all of the containing dynamic objects inside of SQLMsg automatically when SQLMsg destructor is called.
The reason they used a delete in this call is because they probably knew for certian they wouldn't use this pointer to the object anymore and it can potentially cause a memory leak.
My advice is to always use an auto_ptr as it saves you the trouble to remember where and when to delete this pointer.
*Incase you know for sure that you won't use the SQLMsg pointer object anymore(mostly for actions such as UPDATE / DELETE / INSERT) then you should add delete before the directquery as you mentioned above(Although, you are still in risk that the dynamically allocated objects inside SQLMsg will not be free'd).
Hope i made it clear.
- 2
-
19 minutes ago, StormHunter said:
Im a leecher dumbass for saying the truth?
If it makes you have to claim stuff you didnt made, poor you.
Mate, So far i'm the one with 100+ rank/likes. i have contributed to this forum much more than you that's for sure.
Surf around the C++ code release section and find for yourself how many useful guides i made. all of my stuff worked and working today 100%.
I have never posted any leeched code/tool and i have no intention to do so.
So take your lame ass some where else/keep your thoughts to yourself.
Thanks.
P.S Here's a proof for the efficient difference between my tool and the old italian tool.
If you have a little bit of programming knowledge you'll easily realize which one is better.
My code:
Italian tool code:
-
12 hours ago, StormHunter said:
You worked on it during the past week? Did you?
Or did you just change some buttons placement and branded it as your own?
WPF? Could swear its winforms.
P.S: Obfuscating it doesnt change the fact you used an already available free code, changed partially its visual appearance and branded it your own. At least show respect and credit the first releaser.
What a load of crap. there is a similar tool made long time ago(in Italian language) but i took nothing out of this tool code except a few layout design ideas. the italian tool is poorly coded with unefficient & un-maintainable code, without seperation of UI and Logic,No containers, and the list goes on and on.
Here, i have made it fully english + coded the tool from scratch(in an efficient,maintainable way) + coded new features that no tool existing today has. and i have obfuscated it so leecher dumbass like yourself can't steal the code.
You don't have to trust me but it's a fact that this tool has features that no other tool has today.
And yes, the tool was built with wpf.
P.S
Quote- mob/group file viewer.
- Importing regen file.
- Remember information - Remember the last data entered such as direction, respawn time,count etc.
- Color Character by color(Mob-Red, Stone-Blue, Boss-turquoise, NPC-Belge, Group-Black).
- Add a character - Left click.
- Remove a character - right click on a character dot.
- Load MOB/Group information - select mob_names.txt/group.txt to view information on a data grid(shown on screen shots below). When choosing a group.txt make sure you have type field set on group.
- Ctrl Z Feature - Reverse action, that means that if you added a character it will be deleted and if you removed a character it will be added back.
- Separation of exported files - Files will be exported upon the type of the map character, if you had stone,boss and npc character then stone.txt,boss.txt and npc.txt will be generated.
About 90% of these features do not exist in the old italian tool.
- 1
-
Spoiler
Advanced Regen Editor
I have worked in the past week on a new regen tool(made in C#-WPF) to make the life easier for the mappers/server owner between us.
It is an advanced regen tool that includes all the basic functions + new ones such as:
- mob/group file viewer.
- Importing regen file.
- Remember information - Remember the last data entered such as direction, respawn time,count etc.
- Color Character by color(Mob-Red, Stone-Blue, Boss-turquoise, NPC-Belge, Group-Black).
- Add a character - Left click.
- Remove a character - right click on a character dot.
- Load MOB/Group information - select mob_names.txt/group.txt to view information on a data grid(shown on screen shots below). When choosing a group.txt make sure you have type field set on group.
- Ctrl Z Feature - Reverse action, that means that if you added a character it will be deleted and if you removed a character it will be added back.
- Separation of exported files - Files will be exported upon the type of the map character, if you had stone,boss and npc character then stone.txt,boss.txt and npc.txt will be generated.
If you find any bugs, please reply here with the bug information in specific details.
Please Like this thread if you find my tool useful!
Ⓒ Metin2 Guild Wars.
Version 1.0 Download Link:
Update 06/10/2017:
- Zoom in/out feature has been added.
- View entities seperately feature has been added.
- Import regen bug has been fixed.
- Enjoy!
Version 1.1 Download Link:
Virustotal:
Enjoy!!
- 220
- 4
- 2
- 1
- 5
- 1
- 1
- 59
- 15
- 141
-
8 hours ago, Rachx3 said:
Well, i didn't see someone published it before until now.
and if you look at the implementations of his and mine, you could easily notice the difference.
Anyway, it doesn't hurt
-
4 hours ago, Galet said:
Thanks ! I remember this feature was a part of samouraï core, but I'm unsure, by the way, thanks !
This feature was created custom made by me. but a similar version may be included in other servers.
and np
QuoteDo you have a feature to reload the item\mob proto?
With "/reload p" nothing happensIt should work, you have an issue with your server files/src.
I can help you and fix it(not for free), send me a pm.
-
Author: (c) Metin2 Factory/Guild Wars
This implementation includes a new ingame GM command:
/reload_regen which reloads ingame current map regen(regen.txt,boss.txt,stones.txt,etc) including server_attr
Please follow the following steps:
Open cmd.cpp
look for:
ACMD(do_purge);
Add below:
ACMD(reload_regen);
Look for:
{ "nowar", do_nowar, 0, POS_DEAD, GM_PLAYER },
Add below:
{ "reload_regen", reload_regen , 0, POS_DEAD, GM_GOD },
Open cmd_gm.cpp
look for the end of ACMD(do_purge) function
and add below:
ACMD(reload_regen) { std::vector<LPEVENT> regenEvent = SECTREE_MANAGER::instance().GetRegenEvent(ch->GetMapIndex()); for (std::vector<LPEVENT>::iterator it = regenEvent.begin(); it != regenEvent.end(); ++it) { event_cancel(&(*it)); } FuncPurge func(ch); func.m_bAll = true; LPSECTREE_MAP lm = SECTREE_MANAGER::instance().GetMap(ch->GetMapIndex()); lm->for_each(func); char * mapIndex; mapIndex = number_to_str(ch->GetMapIndex(), 10); SECTREE_MANAGER::instance().BuildMap(mapIndex, LocaleService_GetMapPath().c_str()); }
Open sectree_manager.cpp
Look for the end of int SECTREE_MANAGER::Build(const char * c_pszListFileName, const char* c_pszMapBasePath) function
Add below:
int SECTREE_MANAGER::BuildMap(const char * c_pszMapID, const char* c_pszMapBasePath) { std::string mapIndexPath = c_pszMapBasePath; mapIndexPath += "/index"; int test; FILE* fp = fopen(mapIndexPath.c_str(), "rb"); if (fp == NULL) { return 0; } std::string line; char buf[256 + 1]; while (fgets(buf, 256, fp)) { std::string tmp = buf; if (tmp.find(c_pszMapID) != std::string::npos) { printf("found!!"); break; } } char szFilename[256]; char szMapName[256]; int iIndex; *strrchr(buf, '\n') = '\0'; if (!strncmp(buf, "//", 2) || *buf == '#') return 0; sscanf(buf, " %d %s ", &iIndex, szMapName); snprintf(szFilename, sizeof(szFilename), "%s/%s/Setting.txt", c_pszMapBasePath, szMapName); TMapSetting setting; setting.iIndex = iIndex; if (!LoadSettingFile(iIndex, szFilename, setting)) { sys_err("can't load file %s in LoadSettingFile", szFilename); return 0; } snprintf(szFilename, sizeof(szFilename), "%s/%s/Town.txt", c_pszMapBasePath, szMapName); if (!LoadMapRegion(szFilename, setting, szMapName)) { sys_err("can't load file %s in LoadMapRegion", szFilename); return 0; } if (true == test_server) sys_log(0, "[BUILD] Build %s %s %d ", c_pszMapBasePath, szMapName, iIndex); // ¸ÕÀú ÀÌ ¼¹ö¿¡¼ ÀÌ ¸ÊÀÇ ¸ó½ºÅ͸¦ ½ºÆùÇØ¾ß Çϴ°¡ È®ÀÎ ÇÑ´Ù. if (map_allow_find(iIndex)) { LPSECTREE_MAP pkMapSectree = BuildSectreeFromSetting(setting); m_map_pkSectree.insert(std::map<DWORD, LPSECTREE_MAP>::value_type(iIndex, pkMapSectree)); snprintf(szFilename, sizeof(szFilename), "%s/%s/server_attr", c_pszMapBasePath, szMapName); LoadAttribute(pkMapSectree, szFilename, setting); snprintf(szFilename, sizeof(szFilename), "%s/%s/regen.txt", c_pszMapBasePath, szMapName); regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY); snprintf(szFilename, sizeof(szFilename), "%s/%s/npc.txt", c_pszMapBasePath, szMapName); regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY); snprintf(szFilename, sizeof(szFilename), "%s/%s/boss.txt", c_pszMapBasePath, szMapName); regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY); snprintf(szFilename, sizeof(szFilename), "%s/%s/stone.txt", c_pszMapBasePath, szMapName); regen_load(szFilename, setting.iIndex, setting.iBaseX, setting.iBaseY); snprintf(szFilename, sizeof(szFilename), "%s/%s/dungeon.txt", c_pszMapBasePath, szMapName); LoadDungeon(iIndex, szFilename); pkMapSectree->Build(); } return 1; }
Open regen.cpp
Look for:
regen->event = event_create(regen_event, info, PASSES_PER_SEC(number(0, 16)) + PASSES_PER_SEC(regen->time));add below:
SECTREE_MANAGER::instance().AddRegenEventToMap(lMapIndex, regen->event);
Open sectree_manager.h
Look for:
std::map<DWORD, std::vector<npc_info> > m_mapNPCPosition;
Add below:
std::map<long, std::vector<LPEVENT>> m_mapRegen;
Look for:
bool GetRandomLocation(long lMapIndex, PIXEL_POSITION & r_pos, DWORD dwCurrentX = 0, DWORD dwCurrentY = 0, int iMaxDistance = 0);Add below:
void AddRegenEventToMap(long lMapIndex, LPEVENT event) { m_mapRegen[lMapIndex].push_back(event); } std::vector<LPEVENT> GetRegenEvent(long lMapIndex) { return m_mapRegen[lMapIndex]; }
Open utils.h from common folder
Look for:
/*----atoi function-----*/Add below:
/*----itoa function-----*/ inline char* number_to_str(int val, int base) { static char buf[32] = { 0 }; int i = 30; for (; val && i; --i, val /= base) buf[i] = "0123456789abcdef"[val % base]; return &buf[i + 1]; } /*----itoa function-----*/
Recompile the source and enjoy.
- 8
- 4
- 10
-
If you want a seperate dungeon for each different player you should use d.join instead of pc.warp
d.joim(mapindex)
Or, recode d.new_jump_party to work also for single players.
- 1
-
I'm working on a big project, looking for proffesional animator that has previous knowledge with 3dmax.
Paying well.
Send me a forum PM for more info.
-
Hi, i'm searching Professional web developer.
Paying well, for more info send me a forum PM and we will talk on skype.
-
Look at the client/server source code. learn the classes/functions hierarchy. Add/Modify slowly the source and experience the changes in game.
Learn the Client/Server packet structure and try adding your own packets to transmit data from client to server and vice versa.
Take a look at some released systems from known people and study what they did.
GL.
- 1
-
Topic has been updated.
-
Hey,
Today i will make a small guide how to enable refinement scroll to be stackable.
This will enable you to stack any refinement scroll such as blessing scroll, magic metal etc.
Before we start diving into the source code, make sure to look into item_proto and check that there isn't any ANTI_STACK flag and the item is defined as ITEM_STACKABLE.
Client side:
Open uiinventory.py
Search for:
def __DropSrcItemToDestItemInInventory(self, srcItemVID, srcItemSlotPos, dstItemSlotPos): if srcItemSlotPos == dstItemSlotPos: return if item.IsRefineScroll(srcItemVID):
Replace with:
def __DropSrcItemToDestItemInInventory(self, srcItemVID, srcItemSlotPos, dstItemSlotPos): if srcItemSlotPos == dstItemSlotPos: return if item.IsRefineScroll(srcItemVID): if player.GetItemIndex(srcItemSlotPos) == player.GetItemIndex(dstItemSlotPos): self.__SendMoveItemPacket(srcItemSlotPos, dstItemSlotPos,0) else: self.RefineItem(srcItemSlotPos, dstItemSlotPos) self.wndItem.SetUseMode(FALSE)
Search for:
if item.IsRefineScroll(srcItemVNum): if player.REFINE_OK == player.CanRefine(srcItemVNum, dstSlotPos)
Replace with:
if item.IsRefineScroll(srcItemVNum): if player.REFINE_OK == player.CanRefine(srcItemVNum, dstSlotPos) or player.GetItemIndex(dstSlotPos) == srcItemVNum:
That's all, Enjoy!
- 1
- 1
- 6
-
Hey,
I have made a small function that will enable you to use an unlimited amount of arguments in server source code.
For example look at the function do_item in cmd_gm.cpp, it gets 2 arguments : arg1 and arg2.
Using my function you will be able to have as many arguments easier and in more convenient way.
That means you can have 5,7 or even 20 arguments.
Let's begin:
Open utils.cpp and look for #include "stdafx.h" add below the following:
#include <boost/algorithm/string/classification.hpp> // Include boost::for is_any_of #include <boost/algorithm/string/split.hpp>
look for const char *first_cmd
add above:
void split_argument(const char *argument, std::vector<std::string> & vecArgs) { std::string arg = argument; boost::split(vecArgs, arg, boost::is_any_of(" "), boost::token_compress_on); }
open utils.h and look for const char * first_cmd
add above:
extern void split_argument(const char *argument, std::vector<std::string> & vecArgs);
That's all.
How to use?
Let's look for example in ACMD(do_item) method:
Instead of
char arg1[256], arg2[256]; two_arguments(argument, arg1, sizeof(arg1), arg2, sizeof(arg2));
you can replace with:
std::vector<std::string> vecArgs; split_argument(argument,vecArgs);
And now you can access any of the arguments starting from index of 1.
so for example if you type ingame the command /item 6001 10
vecArgs[1] is 6001
vecArgs[2] is 10
if you need to convert it to number, you can use as example:
int iCount = 0; str_to_number(iCount, vecArgs[2].c_str());
If you need any assistance, write here a reply and ill do my best in helping you.
Enjoy
- 10
-
Looking for working server/client side protection against hacks such m2 bob or similar hacks.
Paying via paypal/pay safe card.
Send me a pm with your skype info.
v17.5 Element Image on Target
in Features & Metin2 Systems
Posted
At first i tried only client side but there were 2 down sides. first, the flags are declared only in server side that means you'd have to add a new enum in
client side which is pointless. and second, for some reason a few raceflag do not show properly on client side. also, i prefer the logic to remain in server side.
It doesn't matter much and i rather keep the code clean and easier to work with. also, server side check is required for the element icon over player target which ill add later on.