Jump to content


Popular Content

Showing content with the highest reputation since 03/28/2020 in all areas

  1. 13 points
    Well, i dont understand to the new patch system, it starts to be a real mess. Many files are duplicated, but im not surprised, gf logic So i have collected all unpacked files into one client, so everything is clear and easy to find. All files up to 20.1.3 should be there, if something is missing, im sorry, it was just a lot of files and i have missed something. Thank you xP3NG3Rx !! https://mega.nz/#!v84kQKLa!I6Vx20dRZZ-AV-Bz0fETAZd_xlVwQ-XExtLf6_0Dsss
  2. 12 points
  3. 7 points
    Hi everyone, Since I have just set up a new server using the latest versions of both FreeBSD, I took the chance to come back and make a little contribution to my old forum. NOTE: MySQL 5.7 and newer deprecate the PASSWORD() function and thus requires changes on the source and on your website code. Install MySQL 5.6 instead if you are not ready for this - these instructions should work just fine with it, except for the my.cnf path 1. Physical server setup I divided this guide into three parts; hardware setup, OS and MySQL. Previous to the configuration of the OS we will have, of course, rented our server and set up some partitions. In my case, it's a server with 64 GB RAM and 2 NVMe disks. NVMe disks are the fastest in the market, performing even better than SSD. As for the OS, my provider, a very popular french company, offers only one BSD option - a premade template using Freebsd 11.3 ZFS, which I chose. Next I opted for ENglish and "set custom partitions". In the partition setup screen, I decide to assign MySQL its own partition on /var/db/mysql, with roughly three quarters of the space available (400 GB) and leave the rest for everything else. Finally I set a 2GB swap partition. Note that since we are using a RAID setup, the space taken by our partitions show as double. [A RAID, to explain it in layman terms, is a number of hard drives, all containing the same data, working simultaneously - so if one of them fails, the server can continue to work until the faulty disk is replaced and no data or uptime is lost. The downside is that the extra hard drives don't give us any extra space, a price that is worth paying for mission critical applications like this] Having MySQL in its own partition is not strictly needed so if you don't know how much space your MySQL partition will need, just make one big partition for everything (Mountpoint "/") and delete the default "/home" partition which is of little use for us. Remember to use the arrow icon when you set up your last partition to make sure you're using all the available space left! Once done here, enter a hostname for your server and let it get installed. Once completed, you will receive an e-mail with the root password, which you can use to connect to your server through putty on port 22. I won't explain here the usage of putty. 2. Upgrading to latest FreeBSD 2.1 Standard upgrade procedure I have highlighted the word upgrade so you notice we are talking about updating the whole kernel here to a new version - thus, an upgrade. Once we logged in, it's time to update our server to the latest FreeBSD release which at the time of writing this post is 12.1, but do check here first: freebsd.org freebsd-update upgrade -r 12.1-RELEASE Follow the on screen instructions. We have a clean system, so when asked "Does this look reasonable?" feel free to answer y as we are not going to break anything at this point. However, if you upgrade an existing server you should check each file that is being changed, assuming you know what those changes mean of course. You will be eventually shown, as in every OS update, a list of files to be updated - just type :q and enter to keep going. Finally you will be prompted to type "freebsd-update install" and, after the installation is done, to reboot. Now we are supposed to rebuild our ports, since we did not install anything yet and there is nothing to rebuild we will ignore this step; otherwise, rebuild your ports or upgrade your packages using either "portmaster -GaD" or "pkg update". Finally we will type freebsd-update install and we will have our new version of FreeBSD ready to use. 2.2 Standard update procedure If you are using OVH, it's time now to change your repositories since OVH does not provide updates for FreeBSD 12 in their custom repos yet, so we will be pulling our updates from the standard FreeBSD repositories instead. The downside is that we won't be able to use OVH's Real Time Monitoring system, but in my experience it is not of much use anyway. So let's do this: ee /usr/local/etc/pkg/repos/FreeBSD.conf If the file is empty, paste the following text: FreeBSD: { url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest", mirror_type: "srv", signature_type: "fingerprints", fingerprints: "/usr/share/keys/pkg", enabled: yes } Now let's disable OVH repos: ee /usr/local/etc/pkg/repos/OVH.conf And change both instances of "enabled: yes" to "enabled: no". If OVH adds FreeBSD 12 repositories to their repos at some point, you can always revert this change in the future. And now it's time to test updating our system works: portsnap fetch extract pkg update pkg upgrade If you just installed version 12.1 of FreeBSD like me it's possible that pkg is not working for you either. The solution is the following: pkg-static install -f pkg Then you should be able to run pkg normally. 2.3 Rebuilding databases Some system databases need to be rebuilt after a change, such as the changes resulting in a release upgrade like the one we just made. Also, we want to add our e-mail to receive root e-mail messages which may be important. ee /etc/aliases under: # root: me@my.domain add: root: [your email] Save and exit, and then let's sync the users database: newaliases /usr/sbin/pwd_mkdb -p /etc/master.passwd 2.4 Set up sendmail By default, FreeBSD generates audits periodically which can alert us to issues in our system (see crontab). So we will have them forwarded to our email. ee /etc/crontab We add at the top: MAILTO=[our email address] This forwards the cron output to our chosen mail address. Now to basic sendmail setup: cd /etc/mail/certs openssl dhparam -out dh.param 4096 NOTE: if you run your own mail server, you should add it as a smart host for sendmail; take a look here: https://lists.freebsd.org/pipermail/freebsd-questions/2004-February/035329.html Check /var/maillog to make sure everything works. (Be aware that your mail server might not like some random unknown server sending e-mail to it, so receiving them may require some work.) 2.4 Weeding out issues Version 12 being quite new, we will find some things are a bit buggy. These actions are not (should be not) part of the installation process, but are particular issues encountered with version 12. I got some error message with Perl 5.30 while building ports so I installed it from ports and the problem is gone: cd /usr/ports/lang/perl530 && make install clean Another error was caused by SSL missing, so I installed OpenSSL to solve it: pkg install openssl And added this lime in /etc/make.conf so the ports stop complaining when building. /etc/make.conf does not exist in the base install, so just create it. DEFAULT_VERSIONS+=ssl=openssl 2.5 System tuning There are hundreds of guides in the internet about tuning this or other sysctl setting on FreeBSD. Take them with a pinch of salt as they may not be appropiate to your FreeBSD version, and the default settings change in every version, potentially leaving former tuning settings obsolete. Here are a few ones that are proven to apply to this specific case: in /boot/loader.conf # prevent swapping by mysql - set this to a quarter or half of your RAM - ZFS only! vfs.zfs.arc_max="16G" In /etc/sysctl.conf kern.ipc.soacceptqueue=512 # max incoming TCP connections (default is 128, not very good in case of DDoS) compat.ia32.maxdsiz=2147483648 # compatibility for 32 bit apps Finally, if you want to have a firewall, you may want to install pf. I think I made a guide at some point, in any case it's beyond the scope of this tutorial. On a production server, you should also set up ssh key authentication and log in through an user specially created for running your Metin server. Remember to add this user to the wheel group so you can su into root from it as necessary; thereafter you can disable password authentication altogether in /etc/ssh/sshd_config. There are plenty of guides as well on how to do this, as it's a very standard procedure in the Unix world. 3. Installing MySQL 8 3.1 The installation itself Allright so far so good. Now it's time for MySQL 8. I have no idea why they decided to jump from 5.7 to 8 straight away, but it seems MySQL 8 does better on benchmarks than the previous versions. So I will attempt to run Metin on it. pkg install mysql80-server pkg install mysql80-client Add in rc.conf mysql_enable="YES" Now let's disable binary logging to save space, by commenting this line in /usr/local/etc/mysql/my.cnf #log-bin = mysql-bin And disable strict SQL - Metin does not like it: sql-mode = "" At this point you should start MySQL and check everything is fine: service mysql-server start Note you do not need to run mysql_upgrade in this version. Now you should import whichever data you want to import into MySQL. Do not just copy the files, use mysqldump. You should not import the mysql database if you're upgrading from older MySQL or MariaDB versions - add your users manually there. 3.2 Important changes in MySQL 8.0 Of course this version is faster and more efficient and so on, but it's not up to me to explain those changes. What I am going to go over is changes in configuration and behavior that you need to know about. Note that MySQL 8.0 does not create passwords with the old algorithm by default. We have to enable it. Also - very important- the MySQL PASSWORD() function has been deprecated - replace it in your code if you use it (the source does use it). Creating an user with the old password method: CREATE USER 'nativeuser'@'localhost'IDENTIFIED WITH mysql_native_password BY 'password'; Or you can set this as default in my.cnf. Note the FreeBSD port of MySQL 8 saves my.cnf in /usr/local/etc/mysql/my.cnf - instead of /usr/local/etc/my.cnf as older versions used to do. [mysqld] default-authentication-plugin=mysql_native_password 3.3 Getting my.cnf ready If you are using the default config file supplied, make sure you set max_conections to a reasonable number, let's say 200. Optionally, we can set do some tuning as well. # tuning for large RAM (>16GB) innodb-flush-log-at-trx-commit = 2 # safe on ZFS - may corrupt data on non journaling filesystems skip-innodb_doublewrite # tuning for fast disks. Set to 500 for SSD. Remove both lines if your disk is an old SATA drive. innodb_io_capacity = 1000 innodb_flush_neighbors = 0 Here is how our my.cnf looks like with these changes. I have also commented out bind-address since I do want to connect to my database from the outside, but that may not be your case. I have also set innodb_buffer_pool to 16G and innodb_log_file_size to 4G, since I have converted the game tables to InnoDB. If you are not using innodb, you can just leave the default of 1G. # $FreeBSD: branches/2020Q1/databases/mysql80-server/files/my.cnf.sample.in 469734 2018-05-12 15:35:25Z mmokhi $ [client] port = 3306 socket = /tmp/mysql.sock [mysql] prompt = \u@\h [\d]>\_ no_auto_rehash [mysqld] user = mysql port = 3306 socket = /tmp/mysql.sock #bind-address = basedir = /usr/local datadir = /var/db/mysql/ tmpdir = /var/db/mysql_tmpdir slave-load-tmpdir = /var/db/mysql_tmpdir secure-file-priv = /var/db/mysql_secure #log-bin = mysql-bin log-output = TABLE master-info-repository = TABLE relay-log-info-repository = TABLE relay-log-recovery = 1 slow-query-log = 1 server-id = 1 sync_binlog = 1 sync_relay_log = 1 binlog_cache_size = 16M default_password_lifetime = 0 enforce-gtid-consistency = 1 gtid-mode = ON safe-user-create = 1 lower_case_table_names = 1 explicit-defaults-for-timestamp = 1 myisam-recover-options = BACKUP,FORCE open_files_limit = 32768 table_open_cache = 16384 table_definition_cache = 8192 net_retry_count = 16384 key_buffer_size = 256M max_allowed_packet = 64M long_query_time = 5 innodb_buffer_pool_size = 16G innodb_data_home_dir = /var/db/mysql innodb_log_group_home_dir = /var/db/mysql innodb_data_file_path = ibdata1:128M:autoextend innodb_temp_data_file_path = ibtmp1:128M:autoextend innodb_flush_method = O_DIRECT innodb_log_file_size = 4G innodb_log_buffer_size = 128M innodb_write_io_threads = 8 innodb_read_io_threads = 8 innodb_autoinc_lock_mode = 2 skip-symbolic-links # Our stuff here default-authentication-plugin = mysql_native_password max_connections = 200 # disable strict mode (doesnt play well with our queries) sql-mode = "" # tuning for large RAM innodb-flush-log-at-trx-commit = 2 # safe on zfs - may corrupt data on non journaling filesystems skip-innodb_doublewrite # tuning for ssd and nvme innodb_io_capacity = 1000 innodb_flush_neighbors = 0 [mysqldump] max_allowed_packet = 512M quote_names quick For further tuning I recommend running mysql-tuner once in a while. It will provide us with valuable insights on our server; note that you should first let it run live so data can be gathered. cd /root fetch http://mysqltuner.pl perl mysqltuner.pl For instructions visit https://github.com/major/MySQLTuner-perl Feel free to comment on any issues you may have with my tutorial, I may try to help.
  4. 7 points
    1. Foreword If you are like me and enjoy spending time fiddling with FreeBSD, or you want to make it a bit harder to avoid making mistakes because you edited the wrong file or something, it pays off to set up some coloring in your FreeBSD shell. Not for the aesthetics, but to identify easier: who we are (user), where we are (path), and what are we looking at (file coloring) First let's start with the subject of shells. Zsh is pretty popular among programmers, and it also provides an easy way to do exactly what we want through the Oh My Zsh addon. Oh My Zsh is a package designed to make zsh easier to use; you can head here for more details if you want to know more: https://github.com/ohmyzsh/ohmyzsh Note that you can use zsh as a root shell, but any Unix admin worth his salt will tell you that root should be using one of the default shells available with FreeBSD, since, if you run into any issue with the shell, you won't be able to su to root, which is pretty bad. So I will also explain how to do exactly the same coloring with FreeBSD's default shell, csh. Now for the sake of example, let's say we have two users to deal with: root, and the user for our metin2 server which is aptly called metin2 [Note: a sensible approach in such setup is to forbid root from logging in through ssh and do that through the unprivileged metin2 user instead, using su whenever we need root access. I won't talk about this topic here though, just do not forget to add this metin2 user to the wheel group so he can su to root, if you follow this strategy.] 2. Installing Zsh So let's login as root and install the zsh shell first. We can do it from packages or ports, just stick to one method or you will break dependencies and other nasty stuff. pkg update pkg install zsh Or for ports: portsnap auto cd /usr/ports/shells/zsh make install cleam Now let's create our unprivileged user if we don't have one yet: adduser metin2 We wil get a bunch of questions, just leave the defaults - ecept for the shell which will be zsh, and in "Invite to other groups?" you should type wheel here, so we can superuser (su) into root. And of course you would want to type a password, though I prefer using ssh keys for login myself. That was easy wasn't it? 3. Installing oh-my-zsh Now let's switch to our new user with: su metin2 Note: Something that annoys me is how the keypad doesn't work in zsh, specifically the / * - symbols which I use all the time. To amend this, you can add the keybindings in this post in .zshrc. Note they may differ depending on your keyboard - press ctrl+v and then the desired key to find out that key's code: https://superuser.com/questions/742171/zsh-z-shell-numpad-numlock-doesnt-work Make sure we are at the home directory (/home/metin2) and then proceed to install Oh My Zsh: fetch https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh sh install.sh Yes we can install oh-my-zsh even though we are not the root user; of course it will work only for this user. Now try logging in a second Putty window to make sure everything works as intended - it's a good practice when we are changing stuff like shells, ssh or firewall parameters, to make sure we don't get locked out of our own system. 4. Setting up an oh-my-zsh theme Once installed, by editing the .zshrc file found in our home directory you can change the color scheme or theme to any of the ones available - be aware though that the FreeBSD terminal only supports 16 colors by default, so all those fancy Linux ones won't work properly without heavy modification of the environment. https://github.com/ohmyzsh/ohmyzsh/wiki/Themes Luckily for you I will provide here my own color scheme perfectly adapted for this amazing operating system, in case you want to use it - just create a new file called .oh-my-zsh/themes/wom.zsh-theme -mind the dot before oh-; paste this on it, save and then set the theme as "wom" in the beginning of the .zshrc file -again mind the dot-. # WoM2 oh my zsh theme by Shogun if [ $UID -eq 0 ]; then NCOLOR="red"; else NCOLOR="white"; fi PROMPT='%{$fg[$NCOLOR]%}%B%n@%m%b%{$reset_color%}:%{$fg[green]%}%B%0d%b%{$reset_color%} $(git_prompt_info)%(!.#.$) ' RPROMPT='[%*]' # git theming ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[blue]%}(%{$fg_no_bold[yellow]%}%B" ZSH_THEME_GIT_PROMPT_SUFFIX="%b%{$fg_bold[blue]%})%{$reset_color%} " ZSH_THEME_GIT_PROMPT_CLEAN="" ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg_bold[red]%}▒~\~W" # LS colors, made with https://geoff.greer.fm/lscolors/ export LSCOLORS="ExGxfxcxbxegehbhbgacad" zstyle ':completion:*' list-colors "di=1;34:ln=35:so=32:pi=33:ex=1;31:bd=34;46:cd=34;43:su=30;41:sg=30;46:tw=30;42:ow=30;43" Now once you are done you can open a new session (either login on a second Putty window if you're unsure about whether your changes could break something, or else just su to the same user again su metin2) and play around with the ls and cd commands to check directory listing and autocompletion are properly colorized. If you want to make your own theme, you can replace the parameters of the PROMPT (self explanatory), LSCOLORS (directory listing) and list-colors (autocomplete) - for the later two you can get the appropiate strings here: https://geoff.greer.fm/lscolors/ Note that the brownish color in this tool is actually yellow in FreeBSD, and that to access the second set of 8 colors you should mark "bold" which is not really bold but a different shade of the same color. 5. Shell coloring in csh Okay time to move to the root user and its default system shell which is a bit less user friendly. I prefer to get rid of the user specific settings file /root/.cshrc by deleting all the lines on it except for the comments at the start (hint - Ctrl+K in the ee editor deletes the line you're in) and then edit the system wide /etc/csh.cshrc file instead, so the changes apply to all users which use csh. # $FreeBSD: releng/11.3/etc/csh.cshrc 50472 1999-08-27 23:37:10Z peter $ # # System-wide .cshrc file for csh(1). # # WoM2 theme by Shogun on 31st April 2020 umask 22 set path = (/sbin /bin /usr/sbin /usr/bin /usr/local/sbin /usr/local/bin $HOME/bin) set color setenv EDITOR ee setenv PAGER less setenv BLOCKSIZE K setenv LSCOLORS ExGxfxcxBxegehbhbgacad setenv LS_COLORS "di=1;34:ln=1;36:so=35:pi=32:ex=1;31:bd=34;46:cd=34;47:su=31;47:sg=31;46:tw=30;42:ow=30;43" alias h history 25 alias j jobs -l alias la ls -aFG alias lf ls -FAG alias ll ls -lAFG alias ls ls -G set red="%{\033[1;31m%}" set green="%{\033[1;32m%}" set yellow="%{\033[1;33m%}" set blue="%{\033[1;34m%}" set magenta="%{\033[1;35m%}" set cyan="%{\033[1;36m%}" set white="%{\033[1;37m%}" set end="%{\033[0m%}" # This is needed at the end of the prompt if ($?prompt) then # An interactive shell -- set some stuff up set prompt = "${red}%N@%m:${green}%~${white} %# {end}" set promptchars = "%#" set filec set history = 1000 set savehist = (1000 merge) set autolist = ambiguous # Use history to aid expansion set autoexpand set autorehash set mail = (/var/mail/$USER) if ( $?tcsh ) then bindkey "^W" backward-delete-word bindkey -k up history-search-backward bindkey -k down history-search-forward endif endif # Clean up after ourselves... unset red green yellow blue magenta cyan yellow white end These settings will result in exactly the same coloring as in my wom theme for oh-myzsh; besides I set ee as the default editor and less as the default pager. Feel free to change these to your liking. For those curious about the topic I will explain the parts of this file related to coloring, since documentation on the net is pretty sparse about this: set color enables coloring for autocomplete. Without this, the LS_COLORS line below won't have any effect. setenv LSCOLORS will define the colors for directory listing (ls) - note that for this to work ls needs to be invoked with either the -G or the -l parameter, that's why we add the alias ls ls -G line. The parameters defining colors here are the same as in oh-my-zsh. setenv LS_COLORS defines the color scheme for the autocomplete, just like list-colors did in oh-my-zsh. Once again, it works the same way parameter wise. Interestingly, this parameter is used for ls in Linux, hence the confusing naming of the variables. The set red, green, etc lines are just a helper for coloring the prompt later on the script here: set prompt = "${red}%N@%m:${green}%~${white} %# {end}" 6. Notes What if we want to use zsh and oh-my-zsh for root as well? In that case you should not install it from the unprivileged user but from root. And what if we want to install oh-my-zsh for several unprivileged users, leaving root with csh (that's my own setup) - You will notice that if you try to install oh-my-zsh a second time, you will get an error. The way around this is, assuming we are logged in as this other user (let's call it "www") and in its home directory - let's call it /home/www: unset ZSH rm .zshrc rm .zsrhz-local (if exists) Now you can follow the same steps listed earlier to install it as this user. 7. TL; DR If you want some prettier colors but can't bother reading this or don't feel confident changing stuff, just copy and paste this on your putty window while you are logged in: echo 'set color' >> ~/.cshrc echo 'alias ls ls -G' >> ~/.cshrc Happy BSDing!
  5. 7 points
    Some models look like a simple duplicate at first glance, but after a closer look, they are the improved (corrected) models.
  6. 6 points
    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). Client files: element_image_client_files.rar 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! element_image_client_files.rar
  7. 6 points
    File Name: WorldEditor ReMIX File Submitter: martysama0134 File Submitted: 27 Aug 2014 File Category: Tools Intro: This WE is a version compiled directly by me which includes infinite fixes and features. It's certain that you won't longer use the worldeditor_en! To make it simple, I wrote all the details about this feature and the common WE inside the relative config file: (called WorldEditor.txt) // I recently built a new worldeditor version with new features, so: Be a guinea pig of mine and test it all! // Info: (v24) // -) 100% translated // -) granny2.9 // -) F6 as Insert alternative // -) many default features not present inside the worldeditor_en (probably, that binary was taken out from an SVN long time ago and resource hacked) such as Ins for all regions and skyboxes // -) WASD UPLEFTDOWNRIGHT to move around (+asynchronous diagonally movements) // -) UP-LEFT-DOWN-RIGHT to move around*10 (+asynchronous diagonally movements) // -) config file for few things // Output options by default // few others such as default WASD movement // whether or not Insert should let you go where you were before the press // no MAI dump when saving atlas // whether or not DevIL should compress and remove alpha from minimap.dds // whether or not loading .mdatr building heights // default textureset when creating maps // overlapped tabs // other stuff // -) few bugfixes // default title app name // attempting to write to an empty textureset name when creating new maps // ViewRadius doubled every load&save // shadowmap.dds creation // assert when saving atlas // crash when adjusting height // many buffer under/overflows // *.mdc collision data saving (for game_test) // not checking output options when loading maps // water brush waterid bug (the id was increased until 256 each time the function was called; now it's based on the water height just like it should be) // init texture map reload map crash and last 2px always blank // if pack/property exists, it'll be read! (note: if found, the local property/ directory will not be considered!) // square shape even for up/down height brushes // add textureset texture button (+multiselection) // remove textureset texture feature (just selecting a texture from the list and pressing DELETE) // creation of empty textureset with index -1 (changed to 0) // change baseposition button // misspelled stuff // skybox bottom image (nb: you also need a fixed launcher for this) // removed the boring CTRL requirement (to move the camera) when editing daylight/attr // fixed refresh texture imagebox when onKey-pressing the down/up keys (like when onClicking them) // fixed TextureSet file creation if not existing // fixed new wolfman motion event handling // -) created new TextureSet field when creating new maps // -) created new Change/Delete Texture buttons when double-clicking a texture // -) created Background Music playback and Shadow Recalculate buttons // -) created water height "set 0z", "+1z", "-1z" buttons // -) server_attr generator // Note: // 0) there are no regressions in this version! a bug here means it'd also be present in older WE versions too! // 1) the shadow output option is tricky: when UpdateUI is called, shadows are hidden although the check is pressed (i implemented the shadow recalculate function for that) #fixed since v11 // 2) the bgm player requires /miles and the fadein/out doesn't work until you load the map // 3) the adjusting height button works only if mdatr height is detected // 4) the Debug version is laggy when working on maps such as n_flame_dungeon and n_ice_dungeon (by default, because SphereRadius are intensively checked in SphereLib\spherepack.h) // 5) if you load a map, the script panels (where you load .msa et similia) will have the camera perspective a little fucked up (0z instead of -32767z or 0x 0y -163,94z) // 6) few tree objects are not movable and/or highlightable after placed on the ground and their selection is invisible (you can still delete 'em) // trick: draw a square selecting a normal building and 'em, then move the building and you'll see all of 'em will be moved! // 7) the server_attr generator will clean all the unused flags! attr[idx]&=~0xFFFFFFF8; // 8) you can read files from pack/Index 'n stuff but be aware that Property will not be considered! #fixed since v15 // 9) the MonsterAreaInfo features are laggy and buggy as fuck // 10) even though you can select many textures at once (using ctrl+click on textureset list; for brushing or initializing a base texture), you can't delete more than one at the same time // 11) the .mdatr height is tricky; if you move a building, the height will not be refreshed until you put a new building or whatever you want to trigger the update event // 12) by default, the worldeditor tries to render only the first 8 terrain textures of a 32x32px region (nb: a 1x1 map is a 256x256 px region) // 13) the minimap rendering cannot catch the buildings/trees inside the first 2x2 regions due a ymir cache fault and you need to set the camera to "see" them // 14) when the textureset, environment, etc load fails, the old filename still remains loaded // 15) the attr flag "3" (three) has no implementation, so don't use it! // TODO: // A) look at more than 8 textures for region -> DONE // B) create a shortcut to fix the #5 note -> DONE // C) disable the radius <= GetRadius()+0.0001f check to fix the #4 note -> REJECTED // the worldeditor_en calls this assert and, if ignored, the lag ceases to exist (this will not occur in source version) // at least, if the release version is not a problem for you, use that in those few cases when .mse are abused and try to kill the debug one // D) translation in more languages other than english -> REJECTED // english should be enough! // E) alternative path for d: -> REJECTED // you can mount d as a subpath of c like this: // subst d: "c:\mt2stuff" // ### WE CONFIG FILE VIEW_CHAR_OUTPUT_BY_DEFAULT = 1 VIEW_SHADOW_OUTPUT_BY_DEFAULT = 1 VIEW_WATER_OUTPUT_BY_DEFAULT = 1 // WINDOW_HEIGHT_SIZE = 1080 // WINDOW_WIDTH_SIZE = 1920 WINDOW_FOV_SIZE = 45 // #100 = 1px (minimal px movement when pressing WASD) WASD_MINIMAL_MOVE = 100 // came back from where you were before pressing Insert/F6 NO_GOTO_AFTER_INSERT = 1 // disable MAI dumps when saving atlas and/or pressing Insert/F6 NOMAI_ATLAS_DUMP = 1 // disable minimap.dds alpha saving and enable compression NOMINIMAP_RAWALPHA = 1 // enable .mdatr height collision loading when moving on buildings or adjusting terrain DETECT_MDATR_HEIGHT = 1 // disable fog when loading maps NOFOG_ONMAPLOAD = 1 // refresh all checkbox configurations when loading maps 'n stuff REFRESHALL_ONUPDATEUI = 0 // set a default mapname prefix when creating new maps ("" to disable) NEW_MAP_MAPNAME_PREFIX = "metin2_map_" // display a default textureset when creating new maps ("" to disable) // note: it loads the filepath if exists, otherwise it will create an empty textureset file NEWMAP_TEXTURESETLOADPATH = "textureset\metin2_a1.txt" // create a default textureset as "textureset/{mapname}.txt" // note: this option is not considered if NEWMAP_TEXTURESETLOADPATH is not empty. [before v24] // note: this option is not considered if the TextureSet path input is not empty when creating a new map [since v24] NEWMAP_TEXTURESETSAVEASMAPNAME = 1 // ## SHORT-CUTs // # ESC(ape) Clean cursor // # Canc(el|Delete) Delete stuff such as selected buildings // # Ctrl+S Save map // # Ins(ert) or F6 Save shadowmap|minimap.dds // # F3 BoundGrid Show/Hide // # F4 Render UI Show/Hide // # F11 WireFrame Show/Hide // # R Reload Texture // # Z and X Decrease/Increase Texture Splat by 0.1 // # CapsLock Show GaussianCubic effect if shadows are displayed // # L-Shift+1-6 Show TextureCountThreshold flags (&2-7) as colors on the ground // # L-Shift+8 Set Max Showable texture to 8 (de-fix note 12) // # L-Shift+0 Set Max Showable texture to 255 (fix note 12) // # H Refresh MDATR Heights (useful when you move an object) (fix note 11) // # Y Set Perspective as default (fix note 5) // # T Set the Camera to catch all the object on the screen (w/a note 13) then you'll be ready to press Insert/F6 // # DO NOT HAVE AN OBJECT SELECTED WHEN USING THOSE SHORTCUTS (MW1-7) // # MouseWheel+1 move cursor x rotation // # MouseWheel+2 move cursor y rotation // # MouseWheel+3 move cursor z rotation // # MouseWheel+4 move cursor height base (1x) // # MouseWheel+5 move cursor height base (0.5x) // # MouseWheel+6 move cursor height base (0.05x) // # MouseWheel+7 move cursor ambience scale (1x) // # MouseWheel+Q move selected object height base (1x) // # MouseWheel+9 move selected object x position (1x) (+asyncronous) // # MouseWheel+0 move selected object y position (1x) (+asyncronous) // # MW+RSHIFT+9|0 as above but *10x (+asyncronous) // # MW+RCONTROL+9|0 as above but *100x (+asyncronous) // # MouseLeft Insert Objects // # MouseRight Move camera (it could require CTRL too) // # SPACE Start move/selected animation in Object/Effect/Fly CB // # ESC Stop animation in Effect/Fly CB NB: A space is required for such things: //*space*stuff KEY*space*=*space*VALUE Download: https://www.mediafire.com/folder/g0r2rlnfewwv4/WE How To Map: This release will not cover this part. Look at CryPrime`s tutorials to understand how to do it. About the ServerAttr Generator: (since v14) This is a beta function but it should work fine. I tested it on gm_guild_build (1x1), metin2_map_a1 (4x5), metin2_map_trent (2x2), metin2_n_snowm_01 (6x6) and the result was the same as the blackyuko map editor. (I use a different lzo version and I clean deprecated and useless flags, so the size is different from this last one but the "final image" will be the same; using game_test to fix his server_attr will let mine and his perfectly equal byte per byte) I also give you the source code of my server_attr generator function. CLICK A server_attr file is based on all the attr.atr files merged into a one raw RGBA image and each one scaled from 256x256 to 512x512. After that, the image will be splitted into sectors of 128x128 px and each one compressed using lzo compression. The server_attr header is composed by the size of the map*4. (e.g. a 4x4 will have a 16x16 size with 256 sectors inside) (gj ymir CLICK) An uncompressed server_attr sector is just like this: CLICK (the sub 4 byte header is the size returned by the LzoCompress which indicates how much the compressed sector data are large) Each attr.atr is just like this: CLICK (the header is composed of 6 byte in total: 3 WORDs respectively for version, width and height; they are always 2634, 1, 1 so don't bother about it) A single attr.atr scaled from 256x256 to 512x512 will be just like this: CLICK You can use the game_test (from source) to perform few tasks like: Create a server_attr from a .mcd file (I won't suggest it) a <collision data filename> <map directory> Regenerate an old server_attr to server_attr.new using the current lzo compression and cleaning useless flag CLICK c <filename> Other stuff such as b to create a character instance or q to quit About the SkyBox Bottom pic fix: (since v21) Both metin2launch.exe and worldeditor.exe should be edited to see the bottom pic of the skybox. Ymir messed up the code wrongly flipping the bottom image. Open ./Srcs/Client/EterLib/SkyBox.cpp and replace: ////// Face 5: BOTTOM v3QuadPoints[0] = D3DXVECTOR3(1.0f, -1.0f, -1.0f); v3QuadPoints[1] = D3DXVECTOR3(1.0f, 1.0f, -1.0f); v3QuadPoints[2] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f); v3QuadPoints[3] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f); with: ////// Face 5: BOTTOM v3QuadPoints[0] = D3DXVECTOR3(1.0f, 1.0f, -1.0f); v3QuadPoints[1] = D3DXVECTOR3(1.0f, -1.0f, -1.0f); v3QuadPoints[2] = D3DXVECTOR3(-1.0f, 1.0f, -1.0f); v3QuadPoints[3] = D3DXVECTOR3(-1.0f, -1.0f, -1.0f); then recompile. Credits: old_map_tools__20140718-0420.rar we_remix_v24__20150621-0154.rar
  8. 6 points
    Hi everyone! So, after serveral days of searching a tool that could change the texture path of a .gr2 file, I found the tool(probably all of you know it, the texture changer by marv). After that I tried to change the texture paths of some gr2 models of a weapon, and guess what, it didn't work. I'm gonna reupload the file, because I didn't seen it on metin2dev, and I'm gonna teach you how to use it. First of all, I don't know about others, but for me it didn't work to change anything with this (I'm running windows 7 x64 bit). Some of guys told me that this "texture changer" works only on windows 7 x86 bit, so I reinstalled my windows(I really needed that tool), of course, it didn't work either way. So, go in Start and search cmd, and run it. After the cmd started you'll see a path right there C:\Users\Name (Instead of Name you'll have your username of computer administrator, or the account you're logged in), now that's the path where we can work with the tool. PAY ATTENTION!!! IF YOU START THE TOOL IN OTHER FOLDER INSTEAD OF C:\Users\Name THE TOOL WILL NOT WORK, AND YOU WILL NOT BE ABLE TO SAVE THE NEW MODEL. Exctract all the files from the archive(I'll post it below), and start Metin2TextureChanger.exe. Now click "Load" to choose a gr2 file you want to change texture path, BUT, the model name can't have spaces in name(devil sword.gr2 for example, it's wrong, the tool won't read it, and you'll not be able to save your new gr2 model), so if you want to change for example devil sword.gr2 you need to rename it into devil_sword.gr2 or devilsword.gr2 or any other name without spaces betwen. Where is "Neuer Texturpfad" we will chose the new path for texture, for example d:\ymir work\test\devil_sword_blue.dds , there you can choose any other path, but you can't modify "d:\ymir work" or you won't be able to see the weapon/armour in-game. Now we save the file wherever we want, it doesn't matter, this way must work for everybody. AGAIN, THIS TOOL WASN'T MADE BY ME. And I made this post because I've searched many days a tool that would work, but neither didn't work, and this tool didn't work for me either just when I used this method. So, this post is for guys who had the same problem like me (they had the tool, but couldn't save the new model) that's why I wanted to help them, and any other people who weren't been able to use it. And about the other tool I've found on this forum, the tool "made" by thunder-core, I didn't find that tool satisfying, it worked, but after the new model was made, I wasn't been able to import it in 3d max, or to convert the model from file format revision 7 to 6. So you were basicaly forced to upgrade your client to granny 2.9, and I found that inconvenient, because, I don't know about others, but I don't use source for binary, and because of that it's imposible to see the model in-game. And of course, the new model you've created, with the tool in attachement, is revision 7, so you need the new granny if you want to see it in-game, but you can use the converter from archive to convert from revision 7, to revision 6 (old), and you'll be able to see it in-game. If you already see it in-game, you don't need to use the converter. If you found this post helpful I'm glad I could help you. Metin2TextureChanger.rar Metin2TextureChanger.rar
  9. 5 points
    https://github.com/blackdragonx61/Metin2-Level-Info It gives info messages when character level up. From 2018 locale/xx/settings.lua: -- level, msg, type (you can add multiple msg) add_level_info(2, "MSGGGG1", 8); --8 big notice add_level_info(2, "MSGGGG122", 2); --2 notice add_level_info(3, "MSGGGG122333", 1); --1 info
  10. 5 points
    Hi there. While cleaning out "my closet", I found this thing I developed between 2014-2015 - maybe(?) - for my, at that moment, server. Since it's now closed, and I won't use it, I'm sharing it with you guys. Note: Didn't do the scrollbar, wasn't needed for me, so yeah. Now, let's start with opening your locale_game.txt and adding these lines: QUESTCATEGORY_0 Main Quests QUESTCATEGORY_1 Sub Quests QUESTCATEGORY_2 Collect Quests QUESTCATEGORY_3 Levelup Quests QUESTCATEGORY_4 Scroll Quests QUESTCATEGORY_5 System Quests Alright, now find your characterwindow.py (uiscript?) and you can either comment Quest_Page children or simply remove them all. Moving on to your interfaceModule.py find this line self.BINARY_RecvQuest(index, name, "file", localeInfo.GetLetterImageName()) and replace it with self.wndCharacter.questCategory.RecvQuest(self.BINARY_RecvQuest, index, name) Ok, then we are at the most, let's say, difficult part of this. Open your uiCharacter.py and just as you did in your characterwindow.py, remove or simply comment any single line related to quests. You can just search for these vars: self.questShowingStartIndex self.questScrollBar self.questSlot self.questNameList self.questLastTimeList self.questLastCountList Once you did that, you just: # Find these lines self.soloEmotionSlot = self.GetChild("SoloEmotionSlot") self.dualEmotionSlot = self.GetChild("DualEmotionSlot") self.__SetEmotionSlot() # And add the following import uiQuestCategory self.questCategory = uiQuestCategory.QuestCategoryWindow(self.pageDict["QUEST"]) # Find this def OnUpdate(self): self.__UpdateQuestClock() # Replace it with def OnUpdate(self): self.questCategory.OnUpdate() And we're done with the client-side. I attached some extra elements needed (such as the main python file (uiQuestCategory.py) and some image resources). Remember to edit the path linked to these images in that file. For the server-side... Well, screw it, uploaded it too. Too lazy to write. It has only a new quest function (q.getcurrentquestname()) and a few things to add in your questlib.lua. Btw, not sure if you have it, but if not, just add this extra function in ui.Button() (ui.py - class Button). def SetTextAlignLeft(self, text, height = 4): if not self.ButtonText: textLine = TextLine() textLine.SetParent(self) textLine.SetPosition(27, self.GetHeight()/2) textLine.SetVerticalAlignCenter() textLine.SetHorizontalAlignLeft() textLine.Show() self.ButtonText = textLine #Äù½ºÆ® ¸®½ºÆ® UI¿¡ ¸ÂÃç À§Ä¡ ÀâÀ½ self.ButtonText.SetText(text) self.ButtonText.SetPosition(27, self.GetHeight()/2) self.ButtonText.SetVerticalAlignCenter() self.ButtonText.SetHorizontalAlignLeft() Forgot the source part, fml, here it is. Add it to your questlua_quest.cpp. int quest_get_current_quest_name(lua_State* L) { CQuestManager& q = CQuestManager::instance(); PC* pPC = q.GetCurrentPC(); lua_pushstring(L, pPC->GetCurrentQuestName().c_str()); return 1; } void RegisterQuestFunctionTable() { luaL_reg quest_functions[] = { { "getcurrentquestname", quest_get_current_quest_name}, { NULL, NULL } }; CQuestManager::instance().AddLuaFunctionTable("q", quest_functions); } Now, finally, have fun and bye! questcategory.7z server-side.7z
  11. 4 points
  12. 4 points
    Today I bring you another exclusive release from Tim. This time is the granny.dll compatible with Granny 2.8 models and new binaries. Included for completeness is the already public granny DLL for the old binaries, and the bulkconverter.exe tool. What can I do with this? You can use granny models from any Granny version up to 2.8 in your client. How do I use this? Just replace the original dll in your client. Please note, it only works on original, packed client binaries. A tool (bulkconverter.exe) is provided so you can easily convert your current models to 2.8 for best performance. Usage: bulkconverter foldername Will convert all the gr2 files found inside foldername to v2.8 Granny format. Regards granny28.zip
  13. 4 points
    Hello! Here I post the download of Black Samurai and Straw Hat Rework.
  14. 4 points
    Hello everyone! Here i post a map 1x1 that I made
  15. 4 points
    27 March 2020 - Dungeon Info: Details: ◉ All the data is cached so the usage in server is very small. ◉ Very easy to add a new dungeon. ◉ Easy to adapt the quest to register the data ( I adapt one for you as an example ) ◉ Every dungeon has 3 types of ranking: completed count, fastest time and biggest damage on final boss. Video: PRICE: 300€
  16. 4 points
    Hi ! Today ThunderCore Society will offer you a special tool for 3d MAX Software. Note: That tool isn't for begginers and we don't offer suport for that. We hereby inform you that we take the copyrights file and his contents because ThunderCore Society has paid to perform this work. There exists an "readme" file that contains some informations about how to install the script. Attention: These files are under copyright and licensed by ThunderCore Society. Any violation of the license may result in suing. Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. NonCommercial — You may not use the material for commercial purposes. NoDerivatives — If you transform, or build upon the material, you may not distribute the modified material. No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. THC_MDE_TOOL.zip Link Update.
  17. 4 points
    Hi, Here i publish my edit of the public Render Target System. I hate it, when people earn money with public systems. https://mega.nz/#!3NkQSaiR!01DxELG-KvjL6fMQRHN_jf4PM_kRFeuiO8CVQke7Z-Y Original Thread https://metin2.dev/board/index.php?/topic/20550-rlsrendertarget/&tab=comments#comment-111384 https://gyazo.com/f1529844682e872a6c580c27b2daa289 have a look at my comments at UiToolTip.py Bug Fix: UiToolTip-Fix.txt
  18. 4 points
    Screenshot Serverside - C++ [*]packet.h: search for HEADER_CG_ITEM_DROP2 = 20, & paste HEADER_CG_ITEM_DESTROY = 21, under it. [*]packet.h: search for typedef struct command_item_drop2 { [...] } TPacketCGItemDrop2; & paste typedef struct command_item_destroy { BYTE header; TItemPos Cell; } TPacketCGItemDestroy; under it. [*]packet_info.cpp: search for Set(HEADER_CG_ITEM_DROP2, sizeof(TPacketCGItemDrop2), "ItemDrop2", true); & paste Set(HEADER_CG_ITEM_DESTROY, sizeof(TPacketCGItemDestroy), "ItemDestroy", true); under it. [*]input_main.cpp: search for void CInputMain::ItemDrop2(LPCHARACTER ch, const char * data) { [...] } & paste void CInputMain::ItemDestroy(LPCHARACTER ch, const char * data) { struct command_item_destroy * pinfo = (struct command_item_destroy *) data; if (ch) ch->DestroyItem(pinfo->Cell); } under it. [*]input_main.cpp: search for case HEADER_CG_ITEM_DROP2: [...] break; & paste case HEADER_CG_ITEM_DESTROY: if (!ch->IsObserverMode()) ItemDestroy(ch, c_pData); break; under it. [*]char_item.cpp: search for bool CHARACTER::DropItem(TItemPos Cell, BYTE bCount) & paste bool CHARACTER::DestroyItem(TItemPos Cell) { LPITEM item = NULL; if (!CanHandleItem()) { if (NULL != DragonSoul_RefineWindow_GetOpener()) ChatPacket(CHAT_TYPE_INFO, LC_TEXT("°*È*âÀ» ¿¬ »óÅ¿¡¼*´Â ¾ÆÀÌÅÛÀ» ¿Å±æ ¼ö ¾ø½À´Ï´Ù.")); return false; } if (IsDead()) return false; if (!IsValidItemPosition(Cell) || !(item = GetItem(Cell))) return false; if (item->IsExchanging()) return false; if (true == item->isLocked()) return false; if (quest::CQuestManager::instance().GetPCForce(GetPlayerID())->IsRunning() == true) return false; if (item->GetCount() <= 0) return false; SyncQuickslot(QUICKSLOT_TYPE_ITEM, Cell.cell, 255); ITEM_MANAGER::instance().RemoveItem(item); ChatPacket(CHAT_TYPE_INFO, LC_TEXT("Du hast %s zerstoert."), item->GetName()); return true; } above it. [*]char.h: search for bool DropItem(TItemPos Cell, BYTE bCount=0); & paste bool DestroyItem(TItemPos Cell); above it. [*]input.h: search for void ItemDrop2(LPCHARACTER ch, const char * data); & paste void ItemDestroy(LPCHARACTER ch, const char * data); under it. Clientside - C++ [*]packet.h: search for HEADER_CG_ITEM_DROP2 = 20, & paste HEADER_CG_ITEM_DESTROY = 21, ein. [*]packet.h: search for typedef struct command_item_drop2 { [...] } TPacketCGItemDrop2; & paste typedef struct command_item_destroy { BYTE header; TItemPos pos; } TPacketCGItemDestroy; under it. [*]PythonNetworkStreamPhaseGameItem.cpp: search for bool CPythonNetworkStream::SendItemDropPacketNew(TItemPos pos, DWORD elk, DWORD count) { [...] } & paste bool CPythonNetworkStream::SendItemDestroyPacket(TItemPos pos) { if (!__CanActMainInstance()) return true; TPacketCGItemDestroy itemDestroyPacket; itemDestroyPacket.header = HEADER_CG_ITEM_DESTROY; itemDestroyPacket.pos = pos; if (!Send(sizeof(itemDestroyPacket), &itemDestroyPacket)) { Tracen("SendItemDestroyPacket Error"); return false; } return SendSequence(); } under it. [*]PythonNetworkStreamModule.cpp: search for PyObject* netSendItemDropPacket(PyObject* poSelf, PyObject* poArgs) { [...] } & paste PyObject* netSendItemDestroyPacket(PyObject* poSelf, PyObject* poArgs) { TItemPos Cell; if (!PyTuple_GetInteger(poArgs, 0, &Cell.cell)) return Py_BuildException(); CPythonNetworkStream& rkNetStream = CPythonNetworkStream::Instance(); rkNetStream.SendItemDestroyPacket(Cell); return Py_BuildNone(); } under it. [*]PythonNetworkStreamModule.cpp: search for { "SendItemDropPacketNew", netSendItemDropPacketNew, METH_VARARGS }, & paste { "SendItemDestroyPacket", netSendItemDestroyPacket, METH_VARARGS }, under it. [*]PythonNetworkStream.h: search for bool SendItemDropPacketNew(TItemPos pos, DWORD elk, DWORD count); & paste bool SendItemDestroyPacket(TItemPos pos); under it. Clientside - Python [*]uiCommon.py: search for class QuestionDialog(ui.ScriptWindow): [...] & paste class QuestionDialogItem(ui.ScriptWindow): def __init__(self): ui.ScriptWindow.__init__(self) self.__CreateDialog() def __del__(self): ui.ScriptWindow.__del__(self) def __CreateDialog(self): pyScrLoader = ui.PythonScriptLoader() pyScrLoader.LoadScriptFile(self, "uiscript/questiondialogitem.py") self.board = self.GetChild("board") self.textLine = self.GetChild("message") self.acceptButton = self.GetChild("accept") self.destroyButton = self.GetChild("destroy") self.cancelButton = self.GetChild("cancel") def Open(self): self.SetCenterPosition() self.SetTop() self.Show() def Close(self): self.Hide() def SetWidth(self, width): height = self.GetHeight() self.SetSize(width, height) self.board.SetSize(width, height) self.SetCenterPosition() self.UpdateRect() def SAFE_SetAcceptEvent(self, event): self.acceptButton.SAFE_SetEvent(event) def SAFE_SetCancelEvent(self, event): self.cancelButton.SAFE_SetEvent(event) def SetAcceptEvent(self, event): self.acceptButton.SetEvent(event) def SetDestroyEvent(self, event): self.destroyButton.SetEvent(event) def SetCancelEvent(self, event): self.cancelButton.SetEvent(event) def SetText(self, text): self.textLine.SetText(text) def SetAcceptText(self, text): self.acceptButton.SetText(text) def SetCancelText(self, text): self.cancelButton.SetText(text) def OnPressEscapeKey(self): self.Close() return TRUE under it. [*]uiScript/questiondialogitem.py: download it & pack it in your pack/uiscript. [*]game.py: search in definition __DropItem for the first itemDropQuestionDialog = uiCommon.QuestionDialog() & replace it with itemDropQuestionDialog = uiCommon.QuestionDialogItem() [*]game.py: a few lines under it you can find itemDropQuestionDialog.SetAcceptEvent(lambda arg=TRUE: self.RequestDropItem(arg)) & paste itemDropQuestionDialog.SetDestroyEvent(lambda arg=TRUE: self.RequestDestroyItem(arg)) under it. [*]game.py: search for def RequestDropItem(self, answer): [...] & paste def RequestDestroyItem(self, answer): if not self.itemDropQuestionDialog: return if answer: dropType = self.itemDropQuestionDialog.dropType dropNumber = self.itemDropQuestionDialog.dropNumber if player.SLOT_TYPE_INVENTORY == dropType: if dropNumber == player.ITEM_MONEY: return else: self.__SendDestroyItemPacket(dropNumber) self.itemDropQuestionDialog.Close() self.itemDropQuestionDialog = None constInfo.SET_ITEM_DROP_QUESTION_DIALOG_STATUS(0) under it. [*]game.py: search for def __SendDropItemPacket(self, itemVNum, itemCount, itemInvenType = player.INVENTORY): [...] & paste def __SendDestroyItemPacket(self, itemVNum, itemInvenType = player.INVENTORY): if uiPrivateShopBuilder.IsBuildingPrivateShop(): chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.DROP_ITEM_FAILURE_PRIVATE_SHOP) return net.SendItemDestroyPacket(itemVNum) under it. [*]locale/xx/locale_interface.txt: add there somewhere DESTROY Destroy release_avenue.rar
  19. 4 points
    Hello There. I publish here this system i hope that this help you a bit with this you can hide your costume if you dont like it here is a gif: (if I forgot something just say it ) (this system is not complete yet you can hide only your costume no hairstyle,sash,weapon) costumewindow.rar (This system is not mine! i just found the source function and made the python codes and quest)
  20. 4 points
    There you go, uiCharacter.py and characterwindow.py for you to compare with yours. characterwindow.py uicharacter.py
  21. 3 points
    class okno(ui.BoardWithTitleBar): def __init__(self): You forgot to initialize the BoardWithTitleBar class: ui.BoardWithTitleBar.__init__(self) For adding a button you can use: ui.MakeButton(parent, x, y, tooltipText, path, up, over, down) Also for importing excepting modules you could do something better: for (moduleName, shortModuleName) in (('playerm2g2', 'player'), ('chatm2g', 'chat'), ('chrmgrm2g', 'chrmgr')): try: module = __import__(moduleName) except: module = __import__(shortModuleName) globals()[shortModuleName] = module So, this is the whole script: import ui, app, time, chr, math, playerSettingModule for (moduleName, shortModuleName) in (('playerm2g2', 'player'), ('chatm2g', 'chat'), ('chrmgrm2g', 'chrmgr')): try: module = __import__(moduleName) except: module = __import__(shortModuleName) globals()[shortModuleName] = module class MyBoard(ui.BoardWithTitleBar): def __init__(self): ui.BoardWithTitleBar.__init__(self) self.SetTitleName('First Window') self.SetSize(150, 150) self.SetCenterPosition() self.AddFlag("movable") self.children = [] for i in range(2): button = ui.MakeButton(self, 10 + (i * 70), self.GetHeight()-30, "ToolTip {}".format(i), "d:/ymir work/ui/public/", "middle_button_01.sub", "middle_button_02.sub", "middle_button_03.sub") button.SetText("Button{}".format(i)) button.SAFE_SetEvent(self.__OnClickButton, i) self.children.append(button) self.Show() def __del__(self): ui.BoardWithTitleBar.__del__(self) def __OnClickButton(self, button): chat.AppendChat(7, str(button)) instance = MyBoard() instance.Show()
  22. 3 points
    Forever Metin2 View File Information Tool: Forever Metin2 v1.3 Size: 137 MB Hi: Forever Metin2 Tutorials & Useful FAQ Feedback: https://discord.gg/YGQpsG YouTube: https://bit.ly/34U9xy2 Credits kind regards iace Submitter Ace Submitted 12/25/2019 Category Tools
  23. 3 points
    Hi community, metin2.dev is now one of the most used Metin2 forums and there are many topics, interactions, etc ... Although the current staff is working hard to maintain the forum, it is often complicated to manage everything. That's why we are looking for a new moderator. His/her role will be : Moderate the discord Forum Moderation Participation in the cleanliness of the forum Participation in team discussions and the evolution of metin2.dev If you have always been motivated by our beautiful community and want to get more involved, then don't hesitate to apply by sending me an MP forum. No model is imposed, but don't hesitate to tell me a little bit about yourself, your investment in the community, your motivations, expectations, etc ... We will close the recruitment once we find a moderator. Join us! The staff
  24. 3 points
  25. 3 points
    ù [ Access Denied ] We are: Phoenix MA | Ro@?T / Kira XuniliX | ArSenal OmeGa Dev | Senpai CreepyJah | The Monster Tronic | Nitroz Kartz
  26. 3 points
    #Updated The shoutbox is now available for all Metin2Dev members
  27. 3 points
    Introduction Hey, since I'm often asked if I can make an example for this or that in Python, I just post some of these examples in this thread from time to time. Usually they just end up in my trash (that's why the collection is small for now) but maybe it will help some of you to learn something. You are also welcome to post examples here and I will add them to the startpost. You have a wish for a certain example? Then write it in here. PS: These examples are designed very simple, so that they can be understood. Examples ui.ComoBox() ui.ScrollBar() with text ui.AniImageBox() as loading bar ui.ListBox() ui.ToggleButton() ui.RadioButtonGroup() ui.DragButton() ui.Bar(), ui.Box(), ui.Line() ui.Gauge(), ui.SliderBar() ui.TextLine(), ui.EditLine() Pagination Tabs DropDown Tree Category Navigation ListBox Search TextLineScrollable Class Collapsible window
  28. 3 points
    v20.1.3 Locales + Protos root(msm+txt files) + dumped metadata w/ builtins New mounts, new costumes Some new gui elements for the upcoming new skills
  29. 3 points
    EterNexus File Archiver View File File archiver for Metin2 with GUI made by Crysus Technologies. Please note, you will need Microsoft Visual C++ 2010 Redistributable Package installed to use this software. 32-bit download: http://www.microsoft.com/en-us/download/details.aspx?id=5555 64-bit download: http://www.microsoft.com/en-us/download/details.aspx?id=14632 Screenshots: EterNexus_1.0.3.1a.rar Submitter Rumor Submitted 02/03/14 Category Tools
  30. 2 points
    If you like it, share your opinion here. Model have collision and lights. Download: https://mega.nz/#!OhEQ3JpC!NrH3eV2xexBKvl72JO4at0kpBXIKxdMWIphmIeW1MzM
  31. 2 points
    Reupload: This is the content of the .exe:
  32. 2 points
    Guys because the Virus Pandemic is a big crisis, we reduce all work prices by -50%!
  33. 2 points
  34. 2 points
  35. 2 points
    Original Archive (with password from start post): https://mega.nz/#!VCp3RLBb!iu_ZLasFkk8uDVcfEdAHfBx_vqDy9g7WMlMGIM39HCg
  36. 2 points
    Check that all the folders within metin2_map_devilsCatacomb have an attr.atr file. Or just get this: https://mega.nz/#!AglRFIZQ!L7oFVWoYg29R0IcIFkjpcDzE6WJJqs5yhcSmzAXUFcE
  37. 2 points
  38. 2 points
  39. 2 points
    A fix has been made. Can you tell me if it's good for you ? (navbar only)
  40. 2 points
    Resend me the message. Yesterday I replied something like 60+ conversations, but I'm not sure if I saw yours at all. I'm still trying to catching up. Since many people contacted me asking me information related to the covid, I added some information about it in my Status page: https://martysama0134.com/Status
  41. 2 points
    Jotun-Thrym armor set:
  42. 2 points
    Note: This tutorial was originally written on 26-01-2017 for a pserver. Note: I don't have the SDK, I'll notify the admins if I manage to find one (it's missing on the temp forum) Note: AhnLab HackShield is deprecated, it has not received any update since 2013 or similar 1. Extern Go to Extern/include and create a new folder called hackshield (If you already have some files inside that remove all of them) Put the files from (Your HackShield SDK Zip)/Include to Extern/include/hackshield This step must be done on both Client and Server Extern Copy from (Your HackShield SDK Zip)/Lib/Win/x86/MultiThreaded to Extern/lib the following files: (Client only) HShield/HShield.lib AntiCrack/AntiCpXSvr.lib Copy (Your HackShield SDK Zip)/Developer/Lib/Win/x86/Multithreaded/HShield.lib to Extern/lib/HShield_d.lib (Yes you have to rename this) Copy from (Your HackShield SDK Zip)/Lib/FreeBSD/x86/AntiCrack/LibAntiCpXSvr_st.a to Extern/lib (Server only) Create a new file called hshieldLibLink.h in Extern/include/hackshield (Both Client and Server) and put this: #ifndef _HACKSHIELD_INCLUDE_LIBLINK_H_ #define _HACKSHIELD_INCLUDE_LIBLINK_H_ #ifdef _MSC_VER #ifdef _DEBUG #pragma comment(lib,"hshield_d.lib") #else #pragma comment(lib,"hshield.lib") #endif #pragma comment(lib,"HsUserUtil.lib") #endif #endif 2- Client source: Adding /CLR -- Speaicl note: you need to rebuild libjpeg, lzo, cryptopp with /MD and /MDd (defaults are /MT for CryptoPP, /MD for libjpeg and lzo if cmake is being used) You have to edit the VCXProjects Go to C/C++ -> All Options and find /M In Distribute/Release you have to set the "Runtime Library" value to /MD In Debug you have to set that to /MDd Now you have to go on General (In the project settings) and add "Support with Common Language Runtime" to 1 (/clr) Now go on C/C++ -> All Options and find /RTC and change that to "Default" Now go to All Options and write in command line: "/RTC:NO" --- Special note: this step was intended for an old CryptoPP version (I think v5.x?) follow this step only if you receive issues Now rebuild everything and you don't have "mutex is not supported in CLR" error 3. Client source: Adding hackshield Open UserInterface/HackShield.cpp You will find the following lines: (Or something similar at the beginning of the file) #if defined(LOCALE_SERVICE_EUROPE) #define METIN2HS_MONITORING_SERVER_ADDR "" #elif #define METIN2HS_MONITORING_SERVER_ADDR "" // GF #endif //#define METIN2HS_MONITORING_SERVER_ADDR "" //±è¿ë¿í pc Replace all with this: #define METIN2HS_MONITORING_SERVER_ADDR "YOUR IP OF THE MONITOR SERVER" -- Extra note: the monitoring server should be a server used to monitor running instances of HackShield, I never went deeply into this, perhaps you can find some extra information on the HackShield SDK docs Ok now open UserInterface/Locale_inc.h and add this: #define USE_AHNLAB_HACKSHIELD // HackShield #define METIN2HS_INCLUDE hackshield Open HackShield.h and replace: #include "HackshieldLicense.h" with: #include "HackshieldLicense_metin2client.h" Open UserInterface/HackshieldLicense_metin2client.h and replace: #define METIN2HS_EXE_FILE_NAME "metin2client.bin" With: #define METIN2HS_EXE_FILE_NAME "NAME OF THE METIN2 CLIENT.EXTENSION" Example: #define METIN2HS_EXE_FILE_NAME "testclient_arves100.exe" Now you need to setup your project for compile and use without error Open UserInterface Properties page: When you see Common Language Runtime Support (CLR) set it to /clr (If you use anyother it wont compile\link properly) Now go on C/C++ -> Enable C++ exception (sorry for bad translate <.<) Change "Yes (/EHsc)" to "Yes with SEH exceptions (/EHa)" Extra: If you get error on "DEFAULT_HSMS_TIME_OUT not defined" you have to do this: Open Extern/include/hackshield/hshield.h and delete: DEFAULT_HSMS_TIME_OUT Add after: #ifndef _HSHIELD_H_INC #define _HSHIELD_H_INC this: // Fix for compilation error #ifndef DEFAULT_HSMS_TIME_OUT #define DEFAULT_HSMS_TIME_OUT (5 * 1000) // 5ÃÊ #endif - 3. Server Open game/src/Makefile and change this: # HackShield INCDIR += -I../../libhackshield/include LIBDIR += -L../../libhackshield/lib LIBS += -lanticpxsvr to: # HackShield *New* INCDIR += -I../../../Extern/include/hackshield LIBS += -lanticpxsvr_st Open game/src/HackShield_Impl.cpp and edit this line: handle_ = _AhnHS_CreateServerObject("metin2client.bin.hsb"); with this: handle_ = _AhnHS_CreateServerObject("data/<client file name.extension>.hsb"); Open your Auth and Game CONFIGs and add this: hackshield_enable: 1 Extra: "hackshield_first_check_time" and "hackshield_check_cycle_time" are 2 CONFIG variables First check time: it tells after what second the server should ask the first heartbeat of the hackshield Cycle time: it tells after what second the server should ask a heartbeat of the hackshield 4. Client binary You have to copy from (HackShield SDK Zip)/Bin/Win/x86/HShield to Client Binary Folder If you want to use development hackshield (raccomended for Debug or QA) you have all content from (HackShield SDK Zip)/Developer/Bin to (Client Binary Folder)/HShield Remember: Do not distribute the development file (/Developer/Bin/), always use the release (/Bin/) If you want to periodically release updates for your HackShield you have to copy all content from (HackShield SDK Zip)/Bin/Win/x86/Update to your HShield folder on Client Binary Folder 5. Configuring Hackshield We will work on (HackShield SDK Zip)/Bin/Win/x86: We must setup the AntiCrack that will check if the Client integrity is ok AntiCrack/HSBGen.exe will generate our HSB file AntiCrack/HSBHelper.exe will check if the files are ok Explanation: The Output file will be the same name as we setted in HackShield_Impl.cpp before If you had to sign your exe make sure you do that after you used HSBGenerator If you use any other packer than UPX you must have to select "Execute Packet Exe File" Now it will generate a hsb file, put this file on (Server Binary Folder)/data/ You can now check the hsb file with the client to see if everything match We need to tell hackshield witch server he uses to update our HShield files (Only if you want HSUpdate.exe) Open Util/HSUpSetEnv.exe -- Extra note: this is used for updating HackShield content from a remote server, you might want to ship it and do not use HSUpdate.exe Let me explain this application: After you save it will create a HSUpdate.env file witch you have to put on (Client Binary Folder)/HShield Extra: Configuring HSUpdate server If you want to use FTP trasfer method you have to configure a ftp server with username and password you want to use (i won't explain this) You have to copy the folder PatchSet to your webserver Normally when you update your HackShield SDK you will get the update PatchSet for updating your client's HackShield to lateset version Everytime you get an HackShield SDK Update (mine is from 2012) you have to put the new PatchSet and distribute the new client (.exe) Extra: Disabling HS Monitor HackShield.cpp, change the _AhnHS_StartMonitor function to this: #ifdef ENABLE_HACKSHIELD_MONITOR DWORD dwRet = _AhnHS_StartMonitor (HsExtError, szInterfaceFilePath); if( dwRet != ERROR_SUCCESS ) { MessageBox(NULL, MA_T("START_MONITORING_SERVICE_ERROR"), "HACK_SHIELD", MB_OK); } #endif Extra: Customizing names We see before how to customize .hsb file name for Server, Check out Server part if you miss out HSMonitor Client Name and Version can be setted in UserInterface/HackShield.cpp by editing this: strcpy(HsExtError.szGameVersion, ""); //Game ë²„ì „ strcpy(HsExtError.szUserId, "Metin2User_test"); //ìœ ì € ID If you changed the locale/ folder you also have to edit this: #define PREFIX_LOCALE "locale/" If you want to edit the EhSvc.dll Name and Folder you have to edit this: #ifdef _DEBUG MA_PathMerge(szInterfaceFilePath, MA_ARRAYCOUNT(szInterfaceFilePath), szModuleDirPath, "hshield\\EHsvc.dll"); #else MA_PathMerge(szInterfaceFilePath, MA_ARRAYCOUNT(szInterfaceFilePath), szModuleDirPath, "hshield\\EHsvc.dll"); #endif If you want to change the HShield folder you have to edit this: MA_PathMerge(szFullFilePath, MA_ARRAYCOUNT(szFullFilePath), szModuleDirPath, "hshield"); I don't have any working image or anything to show, I think I can confirm that it should work fine.
  43. 2 points
  44. 2 points
    Not bad I have searched this last days but now I have without extra image
  45. 2 points
    This is a revised version of an old thread. Following this How-To, you will have a better customizable solution for the aspect of your quests. You will be able to choice amongst: quest icon, text color, blink effect (like whisper buttons) How To You just need to replace 2 little things: I) In interfaceModule.py, replace BINARY_RecvQuest with: http://pastebin.com/TAk9bx92 II) In questlib.lua, replace send_letter_ex with: http://pastebin.com/wDYjJdnp Explanation: -the 2° argument of send_letter_ex will support multiple parameters: -green|blue|purple|golden|fucsia|aqua and so on (you can add them in BINARY_RecvQuest by adding new colors 0xFF+#HEX; Color Picker Online) -blink (the quest will flash like the whisper messages) -ex (a dummy tag to separate it from "info" and "item") -the 3° argument is the name of the icon to choose, which the current availables are: -scroll_open.tga -scroll_open_green.tga -scroll_open_blue.tga -scroll_open_purple.tga -scroll_open_golden.tga Examples: send_letter_ex(localeInfo.LanguageOptionTitle, "green,blink,ex", "scroll_open_green.tga") send_letter_ex(localeInfo.LanguageOptionTitle, "blue,blink,ex", "scroll_open_blue.tga") send_letter_ex(localeInfo.LanguageOptionTitle, "purple,blink,ex", "scroll_open_purple.tga") send_letter_ex(localeInfo.LanguageOptionTitle, "golden,blink,ex", "scroll_open_golden.tga") send_letter_ex(localeInfo.LanguageOptionTitle, "golden,blink,ex", "scroll_open.tga") send_letter_ex(localeInfo.LanguageOptionTitle, "golden,blink,ex", "scroll_open_green.tga") Note: As you can imagine, the only limitation is that the color in N won't appear. (it will require additional code and work, so just forget it) Download: Check the attachment (colored-quest-scrolls-v2-res.7z) and add metin2_patch_new_questicon in your client. colored-quest-scrolls-v2-res.7z
  46. 2 points
    Hey guyz, I just made a regen creator. Here's a how to use GIF: Download (EN and HU version too): metin2_regen_creator_by_distraught_EN.exe metin2_regen_creator_by_distraught_HU.exe
  47. 2 points
    I want share you critical effect UserInterface/InstanceBaseEffect.cpp open and search; else if (flag & DAMAGE_CRITICAL) { //rkEftMgr.CreateEffect(ms_adwCRCAffectEffect[EFFECT_DAMAGE_CRITICAL],v3Pos,v3Rot); //return; 숫자도 표시. } thus replaced; else if (flag & DAMAGE_CRITICAL) { rkEftMgr.CreateEffect(ms_adwCRCAffectEffect[EFFECT_DAMAGE_CRITICAL],v3Pos,v3Rot); //return; 숫자도 표시. } root/playersettingmodule.py open and search; #chrmgr.RegisterCacheEffect(chrmgr.EFFECT_DAMAGE_CRITICAL, "", "d:/ymir work/effect/affect/damagevalue/critical.mse") thus replaced; chrmgr.RegisterCacheEffect(chrmgr.EFFECT_DAMAGE_CRITICAL, "", "d:/ymir work/effect/affect/damagevalue/critical.mse") effect; http://www.dosyaupload.com/9ii critical.7z
  48. 1 point
    Hello, Working on some new stuff I found out that current implementation of event looks a bit tricky. Due to this fact I basically deciced to re-implement it in C++11 providing up to date tech. Don`t forget to take a look at this topic before you start: https://metin2dev.org/board/index.php?/topic/305-src-compile-with-gcc48-c11-and-optimized-flags/ So lets begin. Add include into the main.cpp: #ifdef __NEW_EVENT_HANDLER__ #include "EventFunctionHandler.h" #endif And add this into main function before: while (idle()); #ifdef __NEW_EVENT_HANDLER__ CEventFunctionHandler EventFunctionHandler; #endif Now add this at the end of idle: #ifdef __NEW_EVENT_HANDLER__ CEventFunctionHandler::instance().Process(); #endif Now search for: sys_log(0, "<shutdown> Destroying CArenaManager..."); And add before: #ifdef __NEW_EVENT_HANDLER__ sys_log(0, "<shutdown> Destroying CEventFunctionHandler..."); CEventFunctionHandler::instance().Destroy(); #endif Now open service.h and add this define: #define __NEW_EVENT_HANDLER__ That`s all. Now just download attachment and add included files to your source. Enjoy. EventFunctionHandler.zip http://www71.zippyshare.com/v/XQNjXSKn/file.html
  49. 1 point
    Lambda expressions (since C++11), you need CFLAG += -std=c++11, if you want to do it without, then you've to do something like this: [hide] shop_manager.cpp 1.1 Search for: 1.2 Add after: 2.1 Search for: 2.2 Replace with: [/hide]
  50. 1 point
    Hello guy's, i dont wane writte an roman or something, becuse my english is very very bad. so what you have to do is look my video: That's all, have very fun with the new Tree's maybe anyone can convert the finished Tree's for metin2dev, and tell me for Release. Look pls the complet video, when not >>> so you dont know the passwort of the Winrar file. Ace PS: I have convert much of them, and all work's without wrong's or bug's. PPS: Sorry forget that: An very big thank's go to Shogun for the SpeedTree Program
  • Create New...

Important Information

Terms of Use / Privacy Policy / Guidelines / We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.