Jump to content

Recommended Posts

  • Bot

Thank you for the updates.
the BindPose error is gone as far as i can see
the functionality of the gui is really nice
but the bones position error is still there

and a small thing would be that when i try to add the model for animation it doubles the directory items:

https://metin2.download/picture/nMo0r55xnF1mZ932Vkkm1Qk5AS0ZA9wc/.gif

Edited by Metin2 Dev
Core X - External 2 Internal
  • Love 1

english_banner.gif

15 hours ago, GeoGeo123 said:

Thank you for the updates.
the BindPose error is gone as far as i can see
the functionality of the gui is really nice
but the bones position error is still there

and a small thing would be that when i try to add the model for animation it doubles the directory items:

https://metin2.download/picture/nMo0r55xnF1mZ932Vkkm1Qk5AS0ZA9wc/.gif

Double inserting file in Gui is fixed, pls send me the file where you get bone errors, I will find a way  for fixing.

Edited by Metin2 Dev
Core X - External 2 Internal

giphy.gif

Best regards, Arlinamid

On 3/21/2022 at 8:04 AM, arlinamid said:

Double inserting file in Gui is fixed, pls send me the file where you get bone errors, I will find a way  for fixing.

Regarding the bone errors.. my granny converter library already addresses this kind of issue. However it was not exposed as an extra option until now.. **Update** Now, it only requires to enable an option which can be set straightforwardly.

You could implement a checkbox for the option in your GUI.

I just updated my library to provide the option for this which can be set straightforwardly. I also updated the example.

Just review my recent commit:

This is the hidden content, please

Edited by Anohros
  • Metin2 Dev 72
  • Eyes 1
  • Not Good 2
  • Sad 1
  • Good 18
  • Love 4
  • Love 32

@AnohrosYesterday, goes around this anim issue, and I arrive to UE4 source, i think it has  some fixes. I found this check it pls. 

This is the hidden content, please

In this file has void CorrectAnimTrackInterpolation  could be these fixing ?

  • Metin2 Dev 48
  • kekw 1
  • Eyes 1
  • Not Good 1
  • Think 2
  • Good 11
  • muscle 1
  • Love 5
  • Love 20

giphy.gif

Best regards, Arlinamid

On 3/20/2022 at 4:24 PM, GeoGeo123 said:

Thank you for the updates.
the BindPose error is gone as far as i can see
the functionality of the gui is really nice
but the bones position error is still there

and a small thing would be that when i try to add the model for animation it doubles the directory items:

https://metin2.download/picture/nMo0r55xnF1mZ932Vkkm1Qk5AS0ZA9wc/.gif

@GeoGeo123 Could you provide the file path "d:/ymir work/.." to the affected animation or send me the file? I think the armor is not required to check the issue.

@ arlinamid The correction script from Unreal Engine could be useful ? I know, my option mentioned above just enables a work around - it is a old way I handled the conversion.

Another issue I'am aware of but not addressed yet: The file "d:/ymir work/pc2/warrior/intro/selected.gr2" is currently not supported with the default animation importer, but works with the old animation importer.

At least it's only a few not supported animations. You can count it on one hand. For my purpose it is just fine to use the old animation importer.

Edited by Metin2 Dev
Core X - External 2 Internal
  • Management
On 3/22/2022 at 7:59 PM, Anohros said:

Regarding the bone errors.. my granny converter library already addresses this kind of issue. However it was not exposed as an extra option until now.. **Update** Now, it only requires to enable an option which can be set straightforwardly.

You could implement a checkbox for the option in your GUI.

I just updated my library to provide the option for this which can be set straightforwardly. I also updated the example.

Just review my recent commit:

This is the hidden content, please

Without those changes: https://metin2.download/picture/KEsNS2jtTUTXw32WZKAw6YfAegY24ig8/.gif

With those changes: https://metin2.download/picture/fofDIklu9ykjoR2cBqPu1i3a3n8W9765/.gif

Code used (with it false that weird flying bug doesn't happen):

    GCL::Importer::GrannyImportOptions options;
    options.importAnimationDeboor = true;
    GrannyImporter* importer = new GrannyImporter(options);

I attempted to apply that update to see if it would solve the left shoulder issue, but apparently it didn't.

To fix it manually just need to mirror Bone_shoulder_03 on XY axis and adjust the position manually.

Edited by Metin2 Dev
Core X - External 2 Internal
  • Love 1

raw

raw

Hello,  I'm still working on this project, and today I found a strange things.

I'm imported saved fbx file to 3ds max and Unity. With Unity I get these:

.gif

Everything fine animation look pretty.

With 3ds Max I get these

.gif

It has animation mistake, so we need some error correction,  I try to find  way to get error correction

  • Love 2

giphy.gif

Best regards, Arlinamid

  • 3 months later...

@ arlinamid

https://metin2.download/picture/moGnFyWel6r2s4Qf0BzvgfDA1a6ik6HI/.png

It extracts the dds files but does not create the .fbx file. Visual studio is not installed, is it doing it?

Edited by Metin2 Dev
Core X - External 2 Internal
  • 5 months later...
  • Active+ Member

Not sure if it's a error or not (since i've found the same problem with other similar tools) but while exporting sura model, the bones of 2 of the fingers in the left hand always export bigger than the other fingers

15b420741b0bed64a15466e8deaece4d.png

The only way i found to kinda fix this was using grnreader or noesis and exporting to smd (if it was exported to fbx the problem also occurs)

Edited by Metin2 Dev
Core X - External 2 Internal
  • Former Staff
On 1/26/2023 at 1:55 PM, idok2 said:

My question is, how did u import the map? I want it too sooo soo badly ?

using System;
using System.IO;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;

public class MapLoaderView : MonoBehaviour
{
    public Terrain Terrain;

    private const int TerrainTileSize = 131;
    private const int TerrainTileSquare = TerrainTileSize * TerrainTileSize;
    private const int SplatSize = TerrainTileSize - 2;
    private const int SplatSquare = SplatSize * SplatSize;
    // Start is called before the first frame update
    void Start()
    {
        var mapWidth = 4;
        var mapHeight = 5;
        
        float[,] data = new float[Terrain.terrainData.heightmapResolution, Terrain.terrainData.heightmapResolution];
        Terrain.terrainData.SetHeights(0, 0, data);
        
        NativeArray<int> xOffset = new NativeArray<int>(mapWidth * mapHeight, Allocator.TempJob);
        NativeArray<int> yOffset = new NativeArray<int>(mapWidth * mapHeight, Allocator.TempJob);
        NativeArray<float> jobData = new NativeArray<float>(SplatSquare * mapHeight * mapWidth, Allocator.TempJob);
        NativeArray<UInt16> mapData = new NativeArray<UInt16>(TerrainTileSquare * mapHeight * mapWidth, Allocator.TempJob);
        
        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            var file = File.ReadAllBytes($"Assets/_M2/Features/Maps/Original/metin2_map_c1/00{tileX}00{tileY}/height.raw");
            var tileOffset = ((tileX * TerrainTileSquare * mapHeight) + (tileY * TerrainTileSquare));
            for (var offset = 0; offset < file.Length / 2; offset++)
            {
                var mapDataOffset = tileOffset + offset;
                mapData[mapDataOffset] = BitConverter.ToUInt16(file, offset * 2);
            }
            
            xOffset[tileX * mapHeight + tileY] = tileX;
            yOffset[tileX * mapHeight + tileY] = tileY;
        }
        
        TerrainJob terrainJob = new TerrainJob
        {
            xOffsetData = xOffset,
            yOffsetData = yOffset,
            data = jobData,
            mapWidth = mapWidth,
            mapHeight = mapHeight,
            mapData = mapData,
        };
        JobHandle handle = terrainJob.Schedule(mapWidth * mapHeight, 1);
        handle.Complete();

        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            for (var pixelX = 0; pixelX < SplatSize; pixelX++)
            for (var pixelY = 0; pixelY < SplatSize; pixelY++)
            {
                var dataOffset = ((tileX * SplatSquare * mapHeight) + (((mapHeight - 1) - tileY) * SplatSquare));
                data[tileY * SplatSize + pixelY, tileX * SplatSize + pixelX] = terrainJob.data[dataOffset + pixelX * SplatSize + pixelY];
            }
        }

        Terrain.terrainData.SetHeights(0, 0, data);

        xOffset.Dispose();
        yOffset.Dispose();
        jobData.Dispose();
        mapData.Dispose();

        int size = 258;
        int[,] texData = new int[size * mapWidth, size * mapHeight];
        
        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            LoadTextures($"Assets/_M2/Features/Maps/Original/metin2_map_c1/00{tileX}00{tileY}/tile.raw", tileX, (mapHeight - 1) - tileY, ref texData);
        }
        
        LoadFullTextures(texData, Terrain.terrainData, size * mapWidth, size * mapHeight);
        bool[,] holes = new bool[Terrain.terrainData.holesResolution, Terrain.terrainData.holesResolution];
        for (var pixelX = 0; pixelX < Terrain.terrainData.holesResolution; pixelX++)
        for (var pixelY = 0; pixelY < Terrain.terrainData.holesResolution; pixelY++)
        {
            var solid = pixelX + 1 < mapHeight * SplatSize && pixelY + 1 < mapWidth * SplatSize;
            holes[pixelX, pixelY] = solid;
        }
        Terrain.terrainData.SetHoles(0, 0, holes);
    }

    public struct TerrainJob : IJobParallelFor
    {
        [NativeDisableParallelForRestriction]
        public NativeArray<float> data;
        [ReadOnly]
        public NativeArray<int> xOffsetData;
        [ReadOnly]
        public NativeArray<int> yOffsetData;
        [ReadOnly] 
        public NativeArray<UInt16> mapData;
        [ReadOnly]
        public int mapWidth;
        [ReadOnly]
        public int mapHeight;
        
        public void Execute(int i)
        {
            var xShift = xOffsetData[i];
            var yShift = yOffsetData[i];

            var dataOffset = ((xShift * TerrainTileSquare * mapHeight) + (yShift * TerrainTileSquare));

            var targetDataOffset = ((xShift * SplatSquare * mapHeight) + (yShift * SplatSquare));
            
            for (int pixelY = 0; pixelY < TerrainTileSize; pixelY++)
            {
                for (int pixelX = 0; pixelX < TerrainTileSize; pixelX++)
                {
                    float v = (float)mapData[dataOffset + (pixelX * TerrainTileSize) + pixelY] / 0xFFFF;
                    if (pixelX >= 1 && pixelY >= 1 && pixelX <= SplatSize && pixelY <= SplatSize)
                    {
                        var realY = pixelY - 1;
                        var realX = pixelX - 1;
                        data[targetDataOffset + realY * SplatSize + ((SplatSize - 1) - realX)] = v;
                    }
                }
            }
        }
    }
    
    public struct Native2DArray<T> : System.IDisposable where T: struct
    {
        private int sizeX;
        private int sizeY;
        private NativeArray<T> flatArray;
        
        public Native2DArray(int sizeX, int sizeY, Allocator allocator)
        {
            this.sizeX = sizeX;
            this.sizeY = sizeY;
            flatArray = new NativeArray<T>(sizeX * sizeY, allocator);
        }
 
        public T this[int x, int y]
        {
            get { return flatArray[x + y * sizeX]; }
            set { flatArray[x + y * sizeX] = value; }
        }
 
        public void Dispose()
        {
            flatArray.Dispose();
        }

        public int Length => this.sizeX * this.sizeY;
    }

    void LoadTerrain(string aFileName, TerrainData aTerrain, int shiftX, int shiftY)
    {
        int size = 131;
        
        float[,] data = new float[size - 2, size - 2];
        using (var file = System.IO.File.OpenRead(aFileName))
        using (var reader = new System.IO.BinaryReader(file))
        {
            for (int y = size - 1; y >= 0; y--)
            {
                for (int x = 0; x < size; x++)
                {
                    float v = (float)reader.ReadUInt16() / 0xFFFF;
                    if (x >= 1 && y >= 1 && x <= size - 2 && y <= size - 2)
                    {
                        data[y - 1, x - 1] = v;
                    }
                }
            }
        }
    }

    void LoadTextures(string tileFileName, int shiftX, int shiftY, ref int[,] fullTexData)
    {
        int size = 258;

        using (var texFile = System.IO.File.OpenRead(tileFileName))
        using (var texReader = new System.IO.BinaryReader(texFile))
        {
            for (int y = size - 1; y >= 0; y--)
            {
                for (int x = 0; x < size; x++)
                {
                    int tex = texReader.ReadByte();
                    fullTexData[size * shiftX + x, size * shiftY + y] = tex - 1;
                }
            }
        }
    }
    
    void LoadFullTextures(int[,] fullTexData, TerrainData aTerrain, int width, int height)
    {
        float[,,] texData = aTerrain.GetAlphamaps(0, 0, width, height);
        {
            for (int y = height - 1; y >= 0; y--)
            {
                for (int x = 0; x < width; x++)
                {
                    {
                        var count = 0;
                        float[] texWeights = new float[aTerrain.terrainLayers.Length];
                        // BOTTOM
                        if (x - 1 >= 0 && y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y - 1]] += 1 / 9f;
                        }

                        if (y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x, y - 1]] += 1;
                        }

                        if (x + 1 < width && y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y - 1]] += 1;
                        }
                        
                        // CENTER
                        if (x - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y]] += 1;
                        }

                        if (true)
                        {
                            count++;
                            texWeights[fullTexData[x, y]] += 1;
                        }

                        if (x + 1 < width)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y]] += 1;
                        }
                        
                        // TOP
                        if (x - 1 >= 0 && y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y]] += 1;
                        }

                        if (y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x, y]] += 1;
                        }

                        if (x + 1 < width && y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y]] += 1;
                        }

                        for (var iTex = 0; iTex < aTerrain.terrainLayers.Length; iTex++)
                        {
                            texData[y, x, iTex] = texWeights[iTex] / (float)count;
                        }
                    }
                }
            }
        }

        aTerrain.SetAlphamaps(0, 0, texData);
    }

    bool IsBitSet(byte b, int pos)
    {
        return (b & (1 << pos)) != 0;
    }

    // Update is called once per frame
    void Update()
    {
    }
}
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;

public static class NativeArrayExtension
{
    public static byte[] ToRawBytes<T>(this NativeArray<T> arr) where T : struct
    {
        var slice = new NativeSlice<T>(arr).SliceConvert<byte>();
        var bytes = new byte[slice.Length];
        slice.CopyTo(bytes);
        return bytes;
    }

    public static void CopyFromRawBytes<T>(this NativeArray<T> arr, byte[] bytes) where T : struct
    {
        var byteArr = new NativeArray<byte>(bytes, Allocator.Temp);
        var slice = new NativeSlice<byte>(byteArr).SliceConvert<T>();

        UnityEngine.Debug.Assert(arr.Length == slice.Length);
        slice.CopyTo(arr);
    }

    public static NativeArray<T> FromRawBytes<T>(byte[] bytes, Allocator allocator) where T : struct
    {
        int structSize = UnsafeUtility.SizeOf<T>();

        UnityEngine.Debug.Assert(bytes.Length % structSize == 0);

        int length = bytes.Length / UnsafeUtility.SizeOf<T>();
        var arr = new NativeArray<T>(length, allocator);
        arr.CopyFromRawBytes(bytes);
        return arr;
    }
}

This would be the map loader I have used

  • Good 1
  • Love 1
On 2/4/2023 at 11:03 PM, .InyaProduction said:
using System;
using System.IO;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;

public class MapLoaderView : MonoBehaviour
{
    public Terrain Terrain;

    private const int TerrainTileSize = 131;
    private const int TerrainTileSquare = TerrainTileSize * TerrainTileSize;
    private const int SplatSize = TerrainTileSize - 2;
    private const int SplatSquare = SplatSize * SplatSize;
    // Start is called before the first frame update
    void Start()
    {
        var mapWidth = 4;
        var mapHeight = 5;
        
        float[,] data = new float[Terrain.terrainData.heightmapResolution, Terrain.terrainData.heightmapResolution];
        Terrain.terrainData.SetHeights(0, 0, data);
        
        NativeArray<int> xOffset = new NativeArray<int>(mapWidth * mapHeight, Allocator.TempJob);
        NativeArray<int> yOffset = new NativeArray<int>(mapWidth * mapHeight, Allocator.TempJob);
        NativeArray<float> jobData = new NativeArray<float>(SplatSquare * mapHeight * mapWidth, Allocator.TempJob);
        NativeArray<UInt16> mapData = new NativeArray<UInt16>(TerrainTileSquare * mapHeight * mapWidth, Allocator.TempJob);
        
        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            var file = File.ReadAllBytes($"Assets/_M2/Features/Maps/Original/metin2_map_c1/00{tileX}00{tileY}/height.raw");
            var tileOffset = ((tileX * TerrainTileSquare * mapHeight) + (tileY * TerrainTileSquare));
            for (var offset = 0; offset < file.Length / 2; offset++)
            {
                var mapDataOffset = tileOffset + offset;
                mapData[mapDataOffset] = BitConverter.ToUInt16(file, offset * 2);
            }
            
            xOffset[tileX * mapHeight + tileY] = tileX;
            yOffset[tileX * mapHeight + tileY] = tileY;
        }
        
        TerrainJob terrainJob = new TerrainJob
        {
            xOffsetData = xOffset,
            yOffsetData = yOffset,
            data = jobData,
            mapWidth = mapWidth,
            mapHeight = mapHeight,
            mapData = mapData,
        };
        JobHandle handle = terrainJob.Schedule(mapWidth * mapHeight, 1);
        handle.Complete();

        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            for (var pixelX = 0; pixelX < SplatSize; pixelX++)
            for (var pixelY = 0; pixelY < SplatSize; pixelY++)
            {
                var dataOffset = ((tileX * SplatSquare * mapHeight) + (((mapHeight - 1) - tileY) * SplatSquare));
                data[tileY * SplatSize + pixelY, tileX * SplatSize + pixelX] = terrainJob.data[dataOffset + pixelX * SplatSize + pixelY];
            }
        }

        Terrain.terrainData.SetHeights(0, 0, data);

        xOffset.Dispose();
        yOffset.Dispose();
        jobData.Dispose();
        mapData.Dispose();

        int size = 258;
        int[,] texData = new int[size * mapWidth, size * mapHeight];
        
        for (int tileX = 0; tileX < mapWidth; tileX++)
        for (int tileY = 0; tileY < mapHeight; tileY++)
        {
            LoadTextures($"Assets/_M2/Features/Maps/Original/metin2_map_c1/00{tileX}00{tileY}/tile.raw", tileX, (mapHeight - 1) - tileY, ref texData);
        }
        
        LoadFullTextures(texData, Terrain.terrainData, size * mapWidth, size * mapHeight);
        bool[,] holes = new bool[Terrain.terrainData.holesResolution, Terrain.terrainData.holesResolution];
        for (var pixelX = 0; pixelX < Terrain.terrainData.holesResolution; pixelX++)
        for (var pixelY = 0; pixelY < Terrain.terrainData.holesResolution; pixelY++)
        {
            var solid = pixelX + 1 < mapHeight * SplatSize && pixelY + 1 < mapWidth * SplatSize;
            holes[pixelX, pixelY] = solid;
        }
        Terrain.terrainData.SetHoles(0, 0, holes);
    }

    public struct TerrainJob : IJobParallelFor
    {
        [NativeDisableParallelForRestriction]
        public NativeArray<float> data;
        [ReadOnly]
        public NativeArray<int> xOffsetData;
        [ReadOnly]
        public NativeArray<int> yOffsetData;
        [ReadOnly] 
        public NativeArray<UInt16> mapData;
        [ReadOnly]
        public int mapWidth;
        [ReadOnly]
        public int mapHeight;
        
        public void Execute(int i)
        {
            var xShift = xOffsetData[i];
            var yShift = yOffsetData[i];

            var dataOffset = ((xShift * TerrainTileSquare * mapHeight) + (yShift * TerrainTileSquare));

            var targetDataOffset = ((xShift * SplatSquare * mapHeight) + (yShift * SplatSquare));
            
            for (int pixelY = 0; pixelY < TerrainTileSize; pixelY++)
            {
                for (int pixelX = 0; pixelX < TerrainTileSize; pixelX++)
                {
                    float v = (float)mapData[dataOffset + (pixelX * TerrainTileSize) + pixelY] / 0xFFFF;
                    if (pixelX >= 1 && pixelY >= 1 && pixelX <= SplatSize && pixelY <= SplatSize)
                    {
                        var realY = pixelY - 1;
                        var realX = pixelX - 1;
                        data[targetDataOffset + realY * SplatSize + ((SplatSize - 1) - realX)] = v;
                    }
                }
            }
        }
    }
    
    public struct Native2DArray<T> : System.IDisposable where T: struct
    {
        private int sizeX;
        private int sizeY;
        private NativeArray<T> flatArray;
        
        public Native2DArray(int sizeX, int sizeY, Allocator allocator)
        {
            this.sizeX = sizeX;
            this.sizeY = sizeY;
            flatArray = new NativeArray<T>(sizeX * sizeY, allocator);
        }
 
        public T this[int x, int y]
        {
            get { return flatArray[x + y * sizeX]; }
            set { flatArray[x + y * sizeX] = value; }
        }
 
        public void Dispose()
        {
            flatArray.Dispose();
        }

        public int Length => this.sizeX * this.sizeY;
    }

    void LoadTerrain(string aFileName, TerrainData aTerrain, int shiftX, int shiftY)
    {
        int size = 131;
        
        float[,] data = new float[size - 2, size - 2];
        using (var file = System.IO.File.OpenRead(aFileName))
        using (var reader = new System.IO.BinaryReader(file))
        {
            for (int y = size - 1; y >= 0; y--)
            {
                for (int x = 0; x < size; x++)
                {
                    float v = (float)reader.ReadUInt16() / 0xFFFF;
                    if (x >= 1 && y >= 1 && x <= size - 2 && y <= size - 2)
                    {
                        data[y - 1, x - 1] = v;
                    }
                }
            }
        }
    }

    void LoadTextures(string tileFileName, int shiftX, int shiftY, ref int[,] fullTexData)
    {
        int size = 258;

        using (var texFile = System.IO.File.OpenRead(tileFileName))
        using (var texReader = new System.IO.BinaryReader(texFile))
        {
            for (int y = size - 1; y >= 0; y--)
            {
                for (int x = 0; x < size; x++)
                {
                    int tex = texReader.ReadByte();
                    fullTexData[size * shiftX + x, size * shiftY + y] = tex - 1;
                }
            }
        }
    }
    
    void LoadFullTextures(int[,] fullTexData, TerrainData aTerrain, int width, int height)
    {
        float[,,] texData = aTerrain.GetAlphamaps(0, 0, width, height);
        {
            for (int y = height - 1; y >= 0; y--)
            {
                for (int x = 0; x < width; x++)
                {
                    {
                        var count = 0;
                        float[] texWeights = new float[aTerrain.terrainLayers.Length];
                        // BOTTOM
                        if (x - 1 >= 0 && y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y - 1]] += 1 / 9f;
                        }

                        if (y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x, y - 1]] += 1;
                        }

                        if (x + 1 < width && y - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y - 1]] += 1;
                        }
                        
                        // CENTER
                        if (x - 1 >= 0)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y]] += 1;
                        }

                        if (true)
                        {
                            count++;
                            texWeights[fullTexData[x, y]] += 1;
                        }

                        if (x + 1 < width)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y]] += 1;
                        }
                        
                        // TOP
                        if (x - 1 >= 0 && y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x - 1, y]] += 1;
                        }

                        if (y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x, y]] += 1;
                        }

                        if (x + 1 < width && y + 1 < height)
                        {
                            count++;
                            texWeights[fullTexData[x + 1, y]] += 1;
                        }

                        for (var iTex = 0; iTex < aTerrain.terrainLayers.Length; iTex++)
                        {
                            texData[y, x, iTex] = texWeights[iTex] / (float)count;
                        }
                    }
                }
            }
        }

        aTerrain.SetAlphamaps(0, 0, texData);
    }

    bool IsBitSet(byte b, int pos)
    {
        return (b & (1 << pos)) != 0;
    }

    // Update is called once per frame
    void Update()
    {
    }
}
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;

public static class NativeArrayExtension
{
    public static byte[] ToRawBytes<T>(this NativeArray<T> arr) where T : struct
    {
        var slice = new NativeSlice<T>(arr).SliceConvert<byte>();
        var bytes = new byte[slice.Length];
        slice.CopyTo(bytes);
        return bytes;
    }

    public static void CopyFromRawBytes<T>(this NativeArray<T> arr, byte[] bytes) where T : struct
    {
        var byteArr = new NativeArray<byte>(bytes, Allocator.Temp);
        var slice = new NativeSlice<byte>(byteArr).SliceConvert<T>();

        UnityEngine.Debug.Assert(arr.Length == slice.Length);
        slice.CopyTo(arr);
    }

    public static NativeArray<T> FromRawBytes<T>(byte[] bytes, Allocator allocator) where T : struct
    {
        int structSize = UnsafeUtility.SizeOf<T>();

        UnityEngine.Debug.Assert(bytes.Length % structSize == 0);

        int length = bytes.Length / UnsafeUtility.SizeOf<T>();
        var arr = new NativeArray<T>(length, allocator);
        arr.CopyFromRawBytes(bytes);
        return arr;
    }
}

This would be the map loader I have used

OMG! Thank you a lot. I am just getting started so i sorry, but i have 2 errors. 

https://metin2.download/picture/RgYGUN28Xh9l3QoY12ysqxyRlG6uVigA/.png

Before you asking, no i don't want to develop a game like metin 2 without knowledge. I just want to learn Unity this way. I just want to play around with things ? . And i like messing around with Metin2 things.

Edited by Metin2 Dev
Core X - External 2 Internal
On 2/6/2023 at 11:28 AM, idok2 said:

OMG! Thank you a lot. I am just getting started so i sorry, but i have 2 errors. 

https://metin2.download/picture/RgYGUN28Xh9l3QoY12ysqxyRlG6uVigA/.png

Before you asking, no i don't want to develop a game like metin 2 without knowledge. I just want to learn Unity this way. I just want to play around with things ? . And i like messing around with Metin2 things.

A wild guess..

does the map width and height match with your map?

I refer to this part from the source:

var mapWidth = 4;
var mapHeight = 5;

Width is the number of tiles in the x axis and height in y axis.

On 2/7/2023 at 9:09 PM, Anohros said:

A wild guess..

does the map width and height match with your map?

I refer to this part from the source:

var mapWidth = 4;
var mapHeight = 5;

Width is the number of tiles in the x axis and height in y axis.

Yes, its correct. Jinno map1 so C1, it is 4, 5.

  • 2 months later...

Can someone compile an old fbx version build?
I'm using 3ds max 2010 because I have a potato laptop, and the latest fbx import plugin available to that version is 2012.2 which only supports fbx version up to 7.2 (I think) while fbx produces by gr2 to fbx exporter is 7.7

Or can someone recommend me a software that can downgrade fbx version? No noesis please because it always messes up something to model.

Thanks in advance.

  • 2 weeks later...
On 5/3/2023 at 6:06 AM, ocarinas said:

Can someone compile an old fbx version build?
I'm using 3ds max 2010 because I have a potato laptop, and the latest fbx import plugin available to that version is 2012.2 which only supports fbx version up to 7.2 (I think) while fbx produces by gr2 to fbx exporter is 7.7

Or can someone recommend me a software that can downgrade fbx version? No noesis please because it always messes up something to model.

Thanks in advance.

It is right now not possible to set the fbx format version on the builds available here.

Though the current version of the fbx sdk supports to export to older versions of the fbx format. Basically, we do not need to downgrade the version of the fbx sdk and only have to pass the specific older version of the fbx format itself on export.

Edited by Anohros
  • 2 months later...
  • 3 months later...
On 2/6/2023 at 1:28 PM, idok2 said:

OMG! Thank you a lot. I am just getting started so i sorry, but i have 2 errors. 

https://metin2.download/picture/RgYGUN28Xh9l3QoY12ysqxyRlG6uVigA/.png

Before you asking, no i don't want to develop a game like metin 2 without knowledge. I just want to learn Unity this way. I just want to play around with things ? . And i like messing around with Metin2 things.

i'm getting this error too

@ .InyaProduction

  • 11 months later...
  • Former Staff
On 2/6/2023 at 11:28 AM, idok2 said:

OMG! Thank you a lot. I am just getting started so i sorry, but i have 2 errors. 

https://metin2.download/picture/RgYGUN28Xh9l3QoY12ysqxyRlG6uVigA/.png

Before you asking, no i don't want to develop a game like metin 2 without knowledge. I just want to learn Unity this way. I just want to play around with things ? . And i like messing around with Metin2 things.

This happens when the resolution of the terrains Heightmap / base texture is not high enough, you can just up that on the terrain settings.

 

Currently bored again and working on a bit of Unity in-editor tooling to convert m2 stuff, not sure if anything will be in a releaseable state for now though .png

  • 3 months later...
  • 2 months later...

I have some problems... Maybe I'm doing something wrong but I don't think so.

The generated fbx does not contain all the converted animations
And then it would be useful if the name of the actions were the same otherwise it would be a mess.

 

https://player.vimeo.com/video/1076436963?h=8c61d724b0

  • 6 months later...
  • 7 months later...
  • Former Staff

I might have been a bit bored again, server is now running on ubuntu 22 inside a docker environment and I built a Unity client that can connect to the fliege files without any serverside modifications (very much a prototype still)

- Dont mind the abyssmal UI, I tried letting claude convert the UI from the python scripts to UGUI, it looks horrible but atleast it was usable - so good enough for debugging

- The green aura on the right is from debugging how .mse files work exactly

 

here some in-editor views

.png

Hit tracing

.png

Full map (minus water) 

.png

  • Love 1

Don't use any images from : imgur, turkmmop, freakgamers, inforge, hizliresim... Or your content will be deleted without notice...
Use : https://metin2.download/media/add/

Please use https://metin2.download/ when uploading files smaller than 100MB, otherwise the approval will take longer due to manual upload.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
×
×
  • 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.