-
Posts
1361 -
Joined
-
Days Won
77 -
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by Shogun
-
-
So after 5 years I finally decided to make a map from scratch, which became the new map 1 for romanian players in WoM2: the Deunsang Citadel.
Spoiler
I am also releasing most of the trees and shrubs I used, these are from Oblivion and I did already release them before (and many people used them in their maps) but I reworked both the lighting and the textures, especially of the trees, and fixed a couple that were not working before.
- 27
- 1
- 2
- 1
- 1
- 10
- 3
- 38
-
Removed the download as my account was downgraded and I am over the attachment limit.
- 2
-
hace 6 horas, ReFresh dijo:
@Cunoo I can do much better things around graphic details but I don't need it and I don't have a time for it. I'm glad too when someone help me or post a free stuff.
Well nobody cares? This is how they were supposed to look, that's why the field in the database is called specular, because it´s supposed to change the reflection not just the brightness as it was. It's explained in this post from 4 years ago, in the second part:
Now go whine somewhere else.
- 2
- 5
-
We use a mix of MyISAM and InnoDB, depending on the table.
- 1
-
With the 2018 you are implying that this is some official update which its not. We already know what year it is thank you. They're pretty ugly anyhow.
- 4
-
Show your mob_proto line
-
Amazing, always wanted to have this.
Merci beaucoup
- 1
-
SERVER_IP = ""
How did you expect this to work exactly?
-
can you show the skybox here?
-
Today I'm going to explain how to add and modify the different sounds that exist in the game.
First of all we have the soundtrack; the music that is played in each map or when we choose it from the music menu. This is pretty straightforward as we just have to copy mp3 files to the bgm folder and they will be read automatically.
In order to add the mp3 file as default sound on a map, you would edit locale/whatever/settings.lua and find lines looking like this
add_bgm_info(125, "chasing_dragon.mp3", 0.5)
Where the first value is the map index, second the filename and third the volume. Pretty straightforward.
The next option the game offers us in the accoustic department is adding a sound to a motion, such as a skill or an emotion. In order to do this, we just need to find the msa file which we want to add a sound to. We will go to the folder of the mob, npc or character in question, find the motion we want through the motlist (if it's not a character), and then; create the respective folder under sound if it doesn't exist. For example, for adding a sound to the motion npc/bakchon/01.msa we would make the folder sound/npc/backchon/ and in it a text file name 01.mss with this format:
ScriptType CharacterSoundInformation SoundDataCount 2 SoundData00 0.396000 "sound/monster/ice_snow_golem/drop_1.wav" SoundData01 0.000000 "sound/monster/ice_snow_golem/fall_1.wav"
SoundDataCount: number of sounds
SoundData00 etc is just used to list the sounds in order and finally the number represents the time, in seconds, that the sound will wait to be played once the motion starts. Of course if the time is higher than the motion duration, the sound is never going to work.
The third option for adding sounds is doing it in the msa files themselves through MOTION_EVENT_TYPE_SOUND. I'm not going to comment this because it's never used by YMir and the mss methos is just easier.
Finally, we can add sounds to an specific place in a map, such as water running under a bridge. To do this, we have to create a .pra file in the property folder/pack with the following information:
YPRT 778119171 ambiencesoundvector "sound/ambience/water_underbridge.wav" propertyname "water_underbridge" propertytype "Ambience" maxvolumeareapercentage "0.300000" playinterval "0.000000" playintervalvariation "0.000000" playtype "LOOP"
YPRT: just an identifier so the game knows its a property file (Ymir PRoperTy)
The number is supposed to be the CRC of the file, but you can use whatever you want as long as it's unique. If you change this number later, the asset will disappear from the maps where you used it so be careful.
- ambiencesoundvector: filename of a WAV or MP3 file
- propertyname: just a name to identify it, can be anything.
- propertytype: in this case Ambience and be careful with case, it's an uppercase A at the start!
- maxvolumeareapercentage: which percentage (0 to 1) of the radius around the placement of the sound is played at 100% volume. I would set this to 1 for non-looping sounds as they only play once when you enter the defined area and won't play again till you leave and re-enter it.
- playinterval: how frequently a sound of type STEP plays
- playintervalvariation: random variation on the previous interval.
- playtype: ONCE, STEP or LOOP
Once in World Editor, we can add our sounds as any other object; except we will set their Size, or the radius around the placement where it will be played, with the AreaAmbienceSize control in WE. If maxvolumeareasize is less than 1, the sound will get quieter from that % of the radius and end up being totally silent at the edge of the total radius.
As I mentioned, all the sounds in the game can be either MP3 or WAV. A comment about WAV files. Most WAV files we can find on the internet will not work with Metin2 straight away. We can use MP3 instead, but we are adding unnecessary overhead to the game, so if you want to use WAV files in Metin here's how.
- Download and install the free Audacity Sample Editor. https://www.audacityteam.org/download/windows/
- Open the original WAV file with it. You may need to press CTRL+A to select the whole sample.
- Metin2 doesn't play stereo WAVs so if your WAV is stereo head to the Track menu and choose > Mix > Mix stereo down to mono.
- Choose Resample... in the same menu and then 22050
- In the top left select "Project Rate" and change it to 22050
- Finally go to the File menu and click on Export and then WAV. Choose 16 bit PCM as format and done.
- 4
- 1
- 1
- 21
-
It's cached, if you want to change it on the database, you will have to log off the character first, and possibly wait some minutes as well. Or restart the server.
-
Who cares about the debug binary? Its for debugging, not for providing a smooth playing experience. A release binary will fail silently as its supposed to.
Whatever the official servers did about the lag I really doubt it has anything to do with mss files.
-
How is a file not found causing lags but finding and loading it isn't?
The only way to solve this is to disable the automatic seek of mss files entirely and implement a system to describe in your msa files whether there's a mss to load or not. But if this wasn't an issue in 2004 I don't see how it would be in 2018.
-
¿A tool to edit the mss files? They are 3 lines of text lol. The only tool you need is notepad.
The client will search for a mss file with the same folder and filename for every msa found. It's not an actual error and you should disable the message to avoid spam.
- 1
-
"I think it is much better instead of going one by one folder to check."
You know you can do this right?
tail -f */*/syserr
-
I'm asking what is the point of updating the file's version.
For starters it breaks texture path changer tools.
-
I feel like it's 2002 all over again
-
As we work with maps we accumulate a large number of unused textures which end up making the client / pack downloads for our server bigger. For this reason I made this little python 2.7 script.
It will read all the textureset files and the texture paths on it and copy to textureset_release/ only the textures that are actually being used by your maps, as listed in Settings.txt
The folder where the script looks for Settings.txt files recursively is "maps/", change it at the start of the code if yours is different. Likewise, it will look for "textureset/" and "terrainmaps/", and create "textureset_release/". No files will be deleted.
Disclaimer: The code is very ugly, I actually have no idea of python, I made this script looking at docs and based on my knowledge of other languages. If you actually know python I suggest you don't look at it to avoid hurting your eyes.
import os import re import string import shutil import sys ct = 0 usedimg = [] usedsets = [] list = [] mapfolder = 'maps/' class cd: """Context manager for changing the current working directory""" def __init__(self, newPath): self.newPath = os.path.expanduser(newPath) def __enter__(self): self.savedPath = os.getcwd() os.chdir(self.newPath) def __exit__(self, etype, value, traceback): os.chdir(self.savedPath) def cleanValue(val): val = val.replace('\\', '/') val = val.strip(' \t\n"') val = val.lower() return val def copyFile(src, dest): try: shutil.copy(src, dest) # eg. src and dest are the same file except shutil.Error as e: print('Error: %s' % e) # eg. source or destination doesn't exist except IOError as e: print('Error: %s' % e.strerror) # Read the tab-separated value of a parameter "param" in all files named "fname" (can be an extension) in folder "folder" def SaveParams(param,fname,folder,list): for path, subdirs, files in os.walk(folder): for filename in files: if filename.lower() == fname.lower() or (fname.startswith('.') and filename.endswith (fname)): f = os.path.join(path, filename) with open(f, "rt") as current: for line in current: lcline = line.lower() lcparam = param.lower() if lcparam in lcline: # strip tabs and split values value = line.rstrip('\t\n') # get parameter value list.append(value) # Read a value with the order number "order" within a parameter block "block" in all files named "fname" (can be an extension) in folder "folder" which are also in list "compare" def SaveParamsFromBlock(block,order,fname,folder,list,compare): for path, subdirs, files in os.walk(folder): for filename in files: if filename in compare and (filename.lower() == fname.lower() or (fname.startswith('.') and filename.endswith (fname))): countblock = -1 f = os.path.join(path, filename) with open(f, "rt") as current: for line in current: lcline = line.lower() lcblock = block.lower() if countblock == order: list.append(line) countblock = -1 elif lcline.startswith(lcblock): countblock = 0 elif countblock >= 0: countblock = countblock + 1 # move to the client data folder with cd('..\client\data'): try: os.makedirs('terrainmaps_release') except: shutil.rmtree('terrainmaps_release') os.makedirs('terrainmaps_release') print "This script copies to terrainmaps_release only the textures which are actually listed in textureset files." print "The folder is emptied on each run. make_archive.py uses this folder as source for making the terrainmaps pack." print "This script is written to be run from the tools repo copy and assumes the client repo copy to be in the same base directory as tools" print "" select = raw_input("Press any key to start, e to exit") if str(select) == "e": sys.exit() # Get all the texturesets used in our maps SaveParams('TextureSet','Setting.txt','maps',usedsets) # Extract the filename part of the used TextureSet paths and write it back to the list for idx,val in enumerate(usedsets): val = cleanValue(val) parts = re.split('/', val.lower()) # check its actually a terrainmaps path usedsets[idx] = parts[-1] # Fetch a list of the textures used in the sets used SaveParamsFromBlock('Start Texture',0,'.txt','textureset',usedimg,usedsets) # Copy the textures used in textureset_release for idx,val in enumerate(usedimg): # check its actually a terrainmaps path if "terrainmaps" in val: val = cleanValue(val) val = val[len('d:/ymir work/terrainmaps/'):] usedimg[idx] = val.lower() srcPath = 'terrainmaps/' + usedimg[idx] destPath = 'terrainmaps_release/' + usedimg[idx] print "Copy " + srcPath + " to " + destPath if not os.path.isdir(os.path.dirname(destPath)): os.makedirs(os.path.dirname(destPath)) copyFile(srcPath, destPath) ct = ct + 1 print "Total " + str(ct) + " textures copied in terrainmaps_release" raw_input("Press any key to exit")
As a bonus another python 2.7 script used to create the property/list file with all your prb, pre. Assumes a property/ folder at the location where you run it.
import os import math count = 0 extensions = ('prb','prt','prd','pre','pra') with open("property/list", "w") as a: for path, subdirs, files in os.walk(r'property'): for filename in files: f = os.path.join(path, filename) if filename != "list" and filename !="reserve": extension = filename.split ('.')[-1] if (extension in extensions): a.write(str(f) + '\n') else: Print ("Strange file: " + f) count = count + 1 print 'Total: ' + str(count) + ' files listed on property/list!' raw_input("Press any key to exit")
And finally another script to copy all your msa and motlist.txt files to a server/data folder that you can upload later to your server. It will only copy when files are different or not existing at the destination. It assumes a ../client/data/npc (and so on) and ../server/data/monster etc. structure, feel free to edit the paths in the scripts to your needs.
import os import shutil from itertools import chain import filecmp pathList = [] count = 0 def copyFile(src, dest): try: shutil.copy(src, dest) return True # eg. src and dest are the same file except shutil.Error as e: print('Error: %s' % e) # eg. source or destination doesn't exist except IOError as e: print('Error: %s' % e.strerror) print "This script moves all the .msa and motlist.txt files from pc monster and npc client folders to the appropiate server folders, creating them if necessary." paths = ('../client/data/monster/', '../client/data/monster2/', '../client/data/npc/', '../client/data/npc2/', '../client/data/pc/', '../client/data/pc2/') for path, dirs, files in chain.from_iterable(os.walk(path) for path in paths): for filename in files: if filename.endswith('.msa') or filename.endswith('.txt'): realpath = path.replace('\\', '/') cfolder = os.path.split(realpath)[1] gfolder = 'monster' if ('/pc/' in realpath): gfolder = 'pc/' + realpath.split('/')[4] elif ('/pc2/' in realpath): gfolder = 'pc2/' + realpath.split('/')[4] else: # Check for duplicated non-pc folders existingpath = next((s for s in pathList if ('/' + cfolder) in s), None) if existingpath and existingpath.endswith(cfolder): if realpath != existingpath: print("Warning: duplicate folders " + realpath + " and " + existingpath + "!") pathList.remove(existingpath) break elif path not in pathList: pathList.append(realpath) else: pathList.append(realpath) spath = realpath + '/' + filename dpath = '../server/data/' + gfolder + '/' + cfolder # Create destination folder if not existing if not os.path.isdir(dpath): os.makedirs(dpath) dpath = dpath + '/' + filename # Copy file if destination is not existing or different if not os.path.exists(dpath) or not filecmp.cmp(spath,dpath): if copyFile(spath, dpath): print "Copied " + spath + " to " + dpath count = count + 1 print "Finished copying " + str(count) + " files!" raw_input("Press any key to exit")
How to use: install python 2.7 anywhere on your hd (C:\Python27 for example), add this path to the system path, and save this code in a file named something.py, then run it by doubleclick
Remember to change directory to wherever you have your client files.
- 7
-
Just search for the string "emotion" in root and source you should find everything you need by copy pasting how the other emotions are implemented. I did it myself and I don't know C++ or Python.
- 2
-
-
Why are you using packs? Unpack all that stuff
- 1
- 1
-
Does this have any practical use?
- 2
-
Cool, I use mysqltuner.pl for optimization but never heard about this
- 1
-
Cos im back doing maps and other stuff now
- 1
Data truncated for column 'size' at row 1
in Community Support - Questions & Answers
Posted
thats not an error