tierrilopes
-
Posts
666 -
Joined
-
Days Won
31 -
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by tierrilopes
-
-
Password:
metin2dev
My previous link is offline due to a dns change.
Edit:
Dns propagation finished:
Please guys, read previous posts.
With avua re-up, now you got 3 links.
Always search the topic before posting, thank you.
Edit: This wasnt directed to you .Avua, but for the ppl asking for re-up.
- 1
-
It works perfect! Thanks but
Do you know how to add administrator privilege by starting the patcher.
And how to add a design
Hello.
Design you can do it yourself, by adding images, a web browser component to show a website and so on.
Administrator, didnt made it yet, but i think you have to add it to a manifest file.
-
Password:
metin2dev
My previous link is offline due to a dns change.
Edit:
Dns propagation finished:
Who are you to repost this , whitout accord of the autor.
Why are you so arogant ?
Maybe he deleted this whit a scope.
Just say.
Im a metin2dev member.
Where im i being arrogant?
Re-uploading is being arrogant?
Losing free time so you can have the source is arrogant? Really?
I can re-upload without author consent. Why?
He didnt't informed that didnt want reuploads
He deleted it to redirect people to his own forum.
d3s4st3r
There was no library builder in the release also.
I can't see buildings or character, how to fix that?
Are you using a 40k client?
Or did you change anything on the source?
Just compiling it and using for example on the 40k test client, gave me no issues.
-
Password:
metin2dev
My previous link is offline due to a dns change.
Edit:
Dns propagation finished:
- 1
-
Please, read the previous posts.
Shisui had already answered that.
- 1
-
There isnt a crack, it got a official key.
Let me upload and i will repost here with the link.
Edit: Seems that i shared it without any kind of crack but the file was still deleted.
-
Yes they are.
After you compile the binary will be on the binary folder.
Open the client.sln with visual studio professional 2013
Set mode to distribute
And then press ctrl+shift+b and wait.
Can i open it with Visual Studio Premium 2013?
I guess you will have to test it, didnt tried other then the professional.
If you (or anyone else) needs the professional one i can send you.
I got it Dreamspark.
-
Yes they are.
After you compile the binary will be on the binary folder.
Open the client.sln with visual studio professional 2013
Set mode to distribute
And then press ctrl+shift+b and wait.
- 1
-
Non-sense having users to go another forum.
For that i dont know what was the effort on posting here in the first place.
Mirror link:
(recompressed with lzma2 ultra)
http://i.tlthings.net/client_source_clean.7z
Password:
metin2dev
-
Please, before posting questions, read the previous posts or this will be filled with spam.
Thank you.
-
Hello.
Some advices:
Change all users and passwords on your serverfiles.
Give only the required permissions to your database users. (for example only read, select, write and delete for website user)
Set a strong password for the adminpage (for example mine got 512 chars lenght).
Give othr members of your team restricted access to the database and serverfiles.
If you going to work on the source, there are some fixes and security methods available on the VIP area, so i would recommend you to adquire a vip package.
-
This starts to be a bit annoying guys.
Please read te previous posts.
First: If someone is wrong, then you fucked up compiling the bin, and edited and you shouldnt.
If working perfectly without any issues.
Second; Those letters, its because of the Debug Mode.
Change it to Release and then click on the green arrow or use shift+ctrl+b.
If you got any issue, please look in the topic first, or even look in another topics in the forum.
The spam gets annoying.
Thank you.
- 1
-
A sugestion, add a option to use bing translate instead of google translate.
Because bing has a better rate translating whole sentences without losing the meaning of the phrase.
- 2
-
db
SYSERR: Feb 17 18:56:13 :: __GetHostInfo: __GetHostInfo() ==> DirectQuery failed(SELECT mIP FROM gmhost) SYSERR: Feb 17 18:56:13 :: __GetAdminInfo: __GetAdminInfo() ==> DirectQuery failed(SELECT mID,mAccount,mName,mContactIP,mServerIP,mAuthority FROM gmlist WHERE mServerIP='ALL' or mServerIP='192.168.5.100') SYSERR: Feb 17 18:56:16 :: Process: FDWATCH: peer null in event: ident 22 SYSERR: Feb 17 18:56:17 :: Process: FDWATCH: peer null in event: ident 21 SYSERR: Feb 17 18:56:17 :: Process: FDWATCH: peer null in event: ident 20
ch1
SYSERR: Feb 17 18:57:28 :: ChildLoop: AsyncSQL: query failed: Table 'account.string' doesn't exist (query: SELECT name, text FROM string errno: 1146) SYSERR: Feb 17 18:57:28 :: DirectQuery: AsyncSQL::DirectQuery : mysql_query error: Table 'account.guild' doesn't exist query: SELECT id FROM guild SYSERR: Feb 17 18:57:32 :: ReadSpecialDropItemFile: ReadSpecialDropItemFile : there is no item 71164 : node µ¿¹°_»óÀÚ_ij½Ã SYSERR: Feb 17 18:57:32 :: Boot: cannot load SpecialItemGroup: locale/singapore/special_item_group.txt SYSERR: Feb 17 18:57:33 :: pid_deinit: End of pid
Remove item 71164 from special_item_group.txt
Add those missing tables to your database.
___
http://eterhost.net/knowledgebase.php?action=displayarticle&id=12
and:
portsnap fetch update
cd /usr/ports/misc/compat7x
make install clean
Those should be all the libs you need, and you should get them from authorized sources as shown here, not some random zip which might not work on your OS version at all and in thre worst case, leave your server unbootable.
Thanks so much. But i have a little problem. When i write the command "fetch ftp://ftp.freebsd.org/pub/FreeBSD/releases/amd64/9.3-RELEASE/lib32.txz"it says this - No route to host. Where can be the problem?
You dont need compat7x.
You must have access to the internet in the machine.
You can check if you have acess by using the following command:
ping www.google.com
____________
A dumb question... how can i change to metin2 user? i mean, when i try to open install.sh it says that i can`t run it as root.
Use the adduser command to add metin2 user, wheres some reference:Then open putty, and write metin2 (or whatever user you choose) instead of root.- 2
-
Download link is redirecting to another forum.
Could you fix it please Reboot?
Thank you.
-
Solved:
"get_input_value" : self.GetInputValue,
was in the wrong place.
-
This How To Compile Reboot ?
What ?
It's easy, open .sln and click build solution
What's This ?
thank you Metin2 dev
What you say ? I don't understand.What do we do with this file?
thank you
Open it with Visual Studio 2013, set mode to release, and then:
ctrl+shit+b
The file will be on the folder binary with the name Metin2Release.exe
found a bug, do not show defenses, show them UNKNOWN_VALUE
SCREEN:
It's something you edited, i just compiled it too check and its working fine:
- 1
-
Can't see any photo, can you upload it please?
-
It already got tabs, like this:
-
Could someone help me notice the mistake please?
Syserr:
networkModule.py(line:200) SetSelectCharacterPhasesystem.py(line:130) __pack_importsystem.py(line:110) _process_resultintroSelect.py(line:26) ? - import consoleModulesystem.py(line:130) __pack_importnetworkModule.SetSelectCharacterPhase - exceptions.SyntaxError:invalid syntax (line 488)Line 488 is the last line of the spoiler below.uitarget.pyimport app import ui import player import net import wndMgr import messenger import guild import char import nonplayer import localeInfo import constInfo import uiHealth import constInfo class TargetBoard(ui.ThinBoard): BUTTON_NAME_LIST = ( localeInfo.TARGET_BUTTON_WHISPER, localeInfo.TARGET_BUTTON_EXCHANGE, localeInfo.TARGET_BUTTON_FIGHT, localeInfo.TARGET_BUTTON_ACCEPT_FIGHT, localeInfo.TARGET_BUTTON_AVENGE, localeInfo.TARGET_BUTTON_FRIEND, localeInfo.TARGET_BUTTON_INVITE_PARTY, localeInfo.TARGET_BUTTON_LEAVE_PARTY, localeInfo.TARGET_BUTTON_EXCLUDE, localeInfo.TARGET_BUTTON_INVITE_GUILD, localeInfo.TARGET_BUTTON_DISMOUNT, localeInfo.TARGET_BUTTON_EXIT_OBSERVER, localeInfo.TARGET_BUTTON_VIEW_EQUIPMENT, localeInfo.TARGET_BUTTON_REQUEST_ENTER_PARTY, localeInfo.TARGET_BUTTON_BUILDING_DESTROY, localeInfo.TARGET_BUTTON_EMOTION_ALLOW, "VOTE_BLOCK_CHAT", ) GRADE_NAME = { nonplayer.PAWN : localeInfo.TARGET_LEVEL_PAWN, nonplayer.S_PAWN : localeInfo.TARGET_LEVEL_S_PAWN, nonplayer.KNIGHT : localeInfo.TARGET_LEVEL_KNIGHT, nonplayer.S_KNIGHT : localeInfo.TARGET_LEVEL_S_KNIGHT, nonplayer.BOSS : localeInfo.TARGET_LEVEL_BOSS, nonplayer.KING : localeInfo.TARGET_LEVEL_KING, } EXCHANGE_LIMIT_RANGE = 3000 def __init__(self): ui.ThinBoard.__init__(self) name = ui.TextLine() name.SetParent(self) name.SetDefaultFontName() name.SetOutline() name.Show() hpGauge = ui.Gauge() hpGauge.SetParent(self) hpGauge.MakeGauge(130, "red") hpGauge.Hide() closeButton = ui.Button() closeButton.SetParent(self) closeButton.SetUpVisual("d:/ymir work/ui/public/close_button_01.sub") closeButton.SetOverVisual("d:/ymir work/ui/public/close_button_02.sub") closeButton.SetDownVisual("d:/ymir work/ui/public/close_button_03.sub") closeButton.SetPosition(30, 13) if localeInfo.IsARABIC(): hpGauge.SetPosition(55, 17) hpGauge.SetWindowHorizontalAlignLeft() closeButton.SetWindowHorizontalAlignLeft() else: hpGauge.SetPosition(175, 17) hpGauge.SetWindowHorizontalAlignRight() closeButton.SetWindowHorizontalAlignRight() closeButton.SetEvent(ui.__mem_func__(self.OnPressedCloseButton)) closeButton.Show() self.buttonDict = {} self.showingButtonList = [] for buttonName in self.BUTTON_NAME_LIST: button = ui.Button() button.SetParent(self) if localeInfo.IsARABIC(): button.SetUpVisual("d:/ymir work/ui/public/Small_Button_01.sub") button.SetOverVisual("d:/ymir work/ui/public/Small_Button_02.sub") button.SetDownVisual("d:/ymir work/ui/public/Small_Button_03.sub") else: button.SetUpVisual("d:/ymir work/ui/public/small_thin_button_01.sub") button.SetOverVisual("d:/ymir work/ui/public/small_thin_button_02.sub") button.SetDownVisual("d:/ymir work/ui/public/small_thin_button_03.sub") button.SetWindowHorizontalAlignCenter() button.SetText(buttonName) button.Hide() self.buttonDict[buttonName] = button self.showingButtonList.append(button) self.buttonDict[localeInfo.TARGET_BUTTON_WHISPER].SetEvent(ui.__mem_func__(self.OnWhisper)) self.buttonDict[localeInfo.TARGET_BUTTON_EXCHANGE].SetEvent(ui.__mem_func__(self.OnExchange)) self.buttonDict[localeInfo.TARGET_BUTTON_FIGHT].SetEvent(ui.__mem_func__(self.OnPVP)) self.buttonDict[localeInfo.TARGET_BUTTON_ACCEPT_FIGHT].SetEvent(ui.__mem_func__(self.OnPVP)) self.buttonDict[localeInfo.TARGET_BUTTON_AVENGE].SetEvent(ui.__mem_func__(self.OnPVP)) self.buttonDict[localeInfo.TARGET_BUTTON_FRIEND].SetEvent(ui.__mem_func__(self.OnAppendToMessenger)) self.buttonDict[localeInfo.TARGET_BUTTON_FRIEND].SetEvent(ui.__mem_func__(self.OnAppendToMessenger)) self.buttonDict[localeInfo.TARGET_BUTTON_INVITE_PARTY].SetEvent(ui.__mem_func__(self.OnPartyInvite)) self.buttonDict[localeInfo.TARGET_BUTTON_LEAVE_PARTY].SetEvent(ui.__mem_func__(self.OnPartyExit)) self.buttonDict[localeInfo.TARGET_BUTTON_EXCLUDE].SetEvent(ui.__mem_func__(self.OnPartyRemove)) self.buttonDict[localeInfo.TARGET_BUTTON_INVITE_GUILD].SAFE_SetEvent(self.__OnGuildAddMember) self.buttonDict[localeInfo.TARGET_BUTTON_DISMOUNT].SAFE_SetEvent(self.__OnDismount) self.buttonDict[localeInfo.TARGET_BUTTON_EXIT_OBSERVER].SAFE_SetEvent(self.__OnExitObserver) self.buttonDict[localeInfo.TARGET_BUTTON_VIEW_EQUIPMENT].SAFE_SetEvent(self.__OnViewEquipment) self.buttonDict[localeInfo.TARGET_BUTTON_REQUEST_ENTER_PARTY].SAFE_SetEvent(self.__OnRequestParty) self.buttonDict[localeInfo.TARGET_BUTTON_BUILDING_DESTROY].SAFE_SetEvent(self.__OnDestroyBuilding) self.buttonDict[localeInfo.TARGET_BUTTON_EMOTION_ALLOW].SAFE_SetEvent(self.__OnEmotionAllow) self.buttonDict["VOTE_BLOCK_CHAT"].SetEvent(ui.__mem_func__(self.__OnVoteBlockChat)) self.healthBoard = uiHealth.HealthBoard() self.name = name self.hpGauge = hpGauge self.closeButton = closeButton self.nameString = 0 self.nameLength = 0 self.vid = 0 self.eventWhisper = None self.isShowButton = FALSE self.__Initialize() self.ResetTargetBoard() def __del__(self): ui.ThinBoard.__del__(self) print "===================================================== DESTROYED TARGET BOARD" def __Initialize(self): self.nameString = "" self.nameLength = 0 self.vid = 0 self.isShowButton = FALSE def Destroy(self): self.eventWhisper = None self.closeButton = None self.showingButtonList = None self.buttonDict = None self.name = None self.hpGauge = None self.__Initialize() def OnPressedCloseButton(self): self.healthBoard.Hide() player.ClearTarget() self.Close() def Close(self): self.__Initialize() self.healthBoard.Hide() self.Hide() def Open(self, vid, name): if vid: if not constInfo.GET_VIEW_OTHER_EMPIRE_PLAYER_TARGET_BOARD(): if not player.IsSameEmpire(vid): self.Hide() return if vid != self.GetTargetVID(): self.ResetTargetBoard() self.SetTargetVID(vid) self.SetTargetName(name) if player.IsMainCharacterIndex(vid): self.__ShowMainCharacterMenu() elif chr.INSTANCE_TYPE_BUILDING == chr.GetInstanceType(self.vid): self.Hide() else: self.RefreshButton() self.Show() else: self.HideAllButton() self.__ShowButton(localeInfo.TARGET_BUTTON_WHISPER) self.__ShowButton("VOTE_BLOCK_CHAT") self.__ArrangeButtonPosition() self.SetTargetName(name) self.Show() def Refresh(self): if self.IsShow(): if self.IsShowButton(): self.RefreshButton() def RefreshByVID(self, vid): if vid == self.GetTargetVID(): self.Refresh() def RefreshByName(self, name): if name == self.GetTargetName(): self.Refresh() def __ShowMainCharacterMenu(self): canShow= 0 self.HideAllButton() if player.IsMountingHorse(): self.__ShowButton(localeInfo.TARGET_BUTTON_DISMOUNT) canShow=1 if player.IsObserverMode(): self.__ShowButton(localeInfo.TARGET_BUTTON_EXIT_OBSERVER) canShow=1 if canShow: self.__ArrangeButtonPosition() self.Show() else: self.Hide() def __ShowNameOnlyMenu(self): self.HideAllButton() def SetWhisperEvent(self, event): self.eventWhisper = event def UpdatePosition(self): self.SetPosition(wndMgr.GetScreenWidth()/2 - self.GetWidth()/2, 10) def ResetTargetBoard(self): for btn in self.buttonDict.values(): btn.Hide() self.__Initialize() self.name.SetPosition(0, 13) self.name.SetHorizontalAlignCenter() self.name.SetWindowHorizontalAlignCenter() self.hpGauge.Hide() self.SetSize(250, 40) def SetTargetVID(self, vid): self.vid = vid def SetEnemyVID(self, vid): self.SetTargetVID(vid) name = chr.GetNameByVID(vid) level = nonplayer.GetLevelByVID(vid) grade = nonplayer.GetGradeByVID(vid) nameFront = "" if -1 != level: nameFront += "Lv." + str(level) + " " if self.GRADE_NAME.has_key(grade): nameFront += "(" + self.GRADE_NAME[grade] + ") " self.SetTargetName(nameFront + name) def GetTargetVID(self): return self.vid def GetTargetName(self): return self.nameString def SetTargetName(self, name): self.nameString = name self.nameLength = len(name) self.name.SetText(name) def SetHP(self, hpPercentage): if not self.hpGauge.IsShow(): self.SetSize(200 + 7*self.nameLength, self.GetHeight()) if localeInfo.IsARABIC(): self.name.SetPosition( self.GetWidth()-23, 13) else: self.name.SetPosition(23, 13) self.name.SetWindowHorizontalAlignLeft() self.name.SetHorizontalAlignLeft() self.hpGauge.Show() self.UpdatePosition() self.hpGauge.SetPercentage(hpPercentage, 100) def ShowDefaultButton(self): self.isShowButton = TRUE self.showingButtonList.append(self.buttonDict[localeInfo.TARGET_BUTTON_WHISPER]) self.showingButtonList.append(self.buttonDict[localeInfo.TARGET_BUTTON_EXCHANGE]) self.showingButtonList.append(self.buttonDict[localeInfo.TARGET_BUTTON_FIGHT]) self.showingButtonList.append(self.buttonDict[localeInfo.TARGET_BUTTON_EMOTION_ALLOW]) for button in self.showingButtonList: button.Show() def HideAllButton(self): self.isShowButton = FALSE for button in self.showingButtonList: button.Hide() self.showingButtonList = [] def __ShowButton(self, name): if not self.buttonDict.has_key(name): return self.buttonDict[name].Show() self.showingButtonList.append(self.buttonDict[name]) def __HideButton(self, name): if not self.buttonDict.has_key(name): return button = self.buttonDict[name] button.Hide() for btnInList in self.showingButtonList: if btnInList == button: self.showingButtonList.remove(button) break def OnWhisper(self): if None != self.eventWhisper: self.eventWhisper(self.nameString) def OnExchange(self): net.SendExchangeStartPacket(self.vid) def OnPVP(self): net.SendChatPacket("/pvp %d" % (self.vid)) def OnAppendToMessenger(self): net.SendMessengerAddByVIDPacket(self.vid) def OnPartyInvite(self): net.SendPartyInvitePacket(self.vid) def OnPartyExit(self): net.SendPartyExitPacket() def OnPartyRemove(self): net.SendPartyRemovePacket(self.vid) def __OnGuildAddMember(self): net.SendGuildAddMemberPacket(self.vid) def __OnDismount(self): net.SendChatPacket("/unmount") def __OnExitObserver(self): net.SendChatPacket("/observer_exit") def __OnViewEquipment(self): net.SendChatPacket("/view_equip " + str(self.vid)) def __OnRequestParty(self): net.SendChatPacket("/party_request " + str(self.vid)) def __OnDestroyBuilding(self): net.SendChatPacket("/build d %d" % (self.vid)) def __OnEmotionAllow(self): net.SendChatPacket("/emotion_allow %d" % (self.vid)) def __OnVoteBlockChat(self): cmd = "/vote_block_chat %s" % (self.nameString) net.SendChatPacket(cmd) def OnPressEscapeKey(self): self.OnPressedCloseButton() return TRUE def IsShowButton(self): return self.isShowButton def RefreshButton(self): self.HideAllButton() if chr.INSTANCE_TYPE_BUILDING == chr.GetInstanceType(self.vid): #self.__ShowButton(localeInfo.TARGET_BUTTON_BUILDING_DESTROY) #self.__ArrangeButtonPosition() return if player.IsPVPInstance(self.vid) or player.IsObserverMode(): # PVP_INFO_SIZE_BUG_FIX self.SetSize(200 + 7*self.nameLength, 40) self.UpdatePosition() # END_OF_PVP_INFO_SIZE_BUG_FIX return self.ShowDefaultButton() if guild.MainPlayerHasAuthority(guild.AUTH_ADD_MEMBER): if not guild.IsMemberByName(self.nameString): if 0 == chr.GetGuildID(self.vid): self.__ShowButton(localeInfo.TARGET_BUTTON_INVITE_GUILD) if not messenger.IsFriendByName(self.nameString): self.__ShowButton(localeInfo.TARGET_BUTTON_FRIEND) if player.IsPartyMember(self.vid): self.__HideButton(localeInfo.TARGET_BUTTON_FIGHT) if player.IsPartyLeader(self.vid): self.__ShowButton(localeInfo.TARGET_BUTTON_LEAVE_PARTY) elif player.IsPartyLeader(player.GetMainCharacterIndex()): self.__ShowButton(localeInfo.TARGET_BUTTON_EXCLUDE) else: if player.IsPartyMember(player.GetMainCharacterIndex()): if player.IsPartyLeader(player.GetMainCharacterIndex()): self.__ShowButton(localeInfo.TARGET_BUTTON_INVITE_PARTY) else: if chr.IsPartyMember(self.vid): self.__ShowButton(localeInfo.TARGET_BUTTON_REQUEST_ENTER_PARTY) else: self.__ShowButton(localeInfo.TARGET_BUTTON_INVITE_PARTY) if player.IsRevengeInstance(self.vid): self.__HideButton(localeInfo.TARGET_BUTTON_FIGHT) self.__ShowButton(localeInfo.TARGET_BUTTON_AVENGE) elif player.IsChallengeInstance(self.vid): self.__HideButton(localeInfo.TARGET_BUTTON_FIGHT) self.__ShowButton(localeInfo.TARGET_BUTTON_ACCEPT_FIGHT) elif player.IsCantFightInstance(self.vid): self.__HideButton(localeInfo.TARGET_BUTTON_FIGHT) if not player.IsSameEmpire(self.vid): self.__HideButton(localeInfo.TARGET_BUTTON_INVITE_PARTY) self.__HideButton(localeInfo.TARGET_BUTTON_FRIEND) self.__HideButton(localeInfo.TARGET_BUTTON_FIGHT) distance = player.GetCharacterDistance(self.vid) if distance > self.EXCHANGE_LIMIT_RANGE: self.__HideButton(localeInfo.TARGET_BUTTON_EXCHANGE) self.__ArrangeButtonPosition() self.__ArrangeButtonPosition() def __ArrangeButtonPosition(self): showingButtonCount = len(self.showingButtonList) pos = -(showingButtonCount / 2) * 68 if 0 == showingButtonCount % 2: pos += 34 for button in self.showingButtonList: button.SetPosition(pos, 33) pos += 68 self.SetSize(max(150, showingButtonCount * 75), 65) self.UpdatePosition() def OnUpdate(self): if player.IsPVPInstance(self.vid): constInfo.VID = self.vid event.QuestButtonClick(constInfo.STHX) if not self.healthBoard.IsShow() and self.vid != 0: self.healthBoard.Show() else: self.healthBoard.Hide() if self.isShowButton: exchangeButton = self.buttonDict[locale.TARGET_BUTTON_EXCHANGE] distance = player.GetCharacterDistance(self.vid) if distance < 0: return if exchangeButton.IsShow(): if distance > self.EXCHANGE_LIMIT_RANGE: self.RefreshButton() else: if distance < self.EXCHANGE_LIMIT_RANGE: self.RefreshButton()
- 1
-
It -> perfectly, so why so much crap?!
Read what Think said...
-
If you could manage to contact vanilla and, there could be a way to track the hacker.
I got no reason to complain about vanilla, she did a amazing job.
Sadly good things get ruined by retards (that hacker).
I wish vanilla the best in life, and i thank for all she has done.
- 2
-
Wonder where a mirror link (because your was offline) is a off-topic.
You never stated you did not wanted re-uploads.
So explain me, wheres the off-topic?
-
Problem solved.
Issue: wrong symbolic links.
Solution: Re-arranged symbolic links to match the corresponding log folder.
[ Dead Download Link ] MEGA Link Downloader [ We Need You ]
in Temporary
Posted
You've been doing something wrong probably.
If you need assistance on that we can discusse this in private.
In-topic:
Didnt knew that one, have been using this for a time now (since 2013):
http://megadownloaderapp.blogspot.pt/
I will test the one you showed to give my opinion on each one is better and has more functions.