Register for your free account! | Forgot your password?

Go Back   elitepvpers > MMORPGs > Nostale
You last visited: Today at 00:57

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



How to manage Nostale map

Discussion on How to manage Nostale map within the Nostale forum part of the MMORPGs category.

Reply
 
Old   #1
 
elite*gold: 0
Join Date: Oct 2018
Posts: 257
Received Thanks: 207
How to manage Nostale map

Hello

One thing I was doing in early 2021 was a Map Editor.
I never finished it for two reasons. One being described later.

First, here is the link to the git repo:
and here is what it currently look like:

The explaination of what it is is in the README. This topic will be useful for those who are really motivated to create a map viewer/creator - copy pasting won't be enough : there are still a lot to do.

After reading the README, you know the limitations of the blender script. So here we go :

First, how NStuData.NOS works :
It is, as a lot of other .NOS files, just an archive, you can read it "humanly" once you know how it is written, let's take a look.


I am using HxD in order to have the hexadecimal (left part) representation.
Red part: file header (it will always be the same for NStpuData, it will be another for NStgData, etc)
Orange part: no clue, sorry
Green part: Number of files in this archive - note that it is in little endian, it means you have to read it from right to left, instead of reading 0xBA020000 (3120693248 files), you read it 0x000002BA (698 files)
Blue part: no clue, sorry


Red part: ID - starts from 0 to... number of files - 1 (0 to 697 in my case) - for this file, it is also the map ID
Green part: Offset. If you don't know what an offset is, it is just a position relative to something.
(Note, there are number of files * 4 * 2 pairs, if you have any programming knowledges, just think of a loop)

Example :
My offset is 0x000015E5 (remember, little endian) - it means that if I go to 0x15E5 (we can ommit the left 0), we will have our data :


Obviously, we are not expecting to have only 0x10 as data.
This is what we are left with:

Red part: I don't know
Green part: data size (how many bytes the map data is coded on)
Blue part: packed data size (you can think of a .rar size (blue part) vs the un-archived size (green part)
Purple part: Wether data is packed or not.
The rest : data.

If purple part is 0, it means it is not packed (so green part = blue part, by definition), if purple part is 1, it means it is packed.

If you know some archiving algorithm or whatever it's called, you can maybe recogniez what is used by looking at the following bytes (0x78) - it is Zlib.
So you can just use Zlib algorithm in order to unpack the map, from 0x78 to where 0x78 is + blue part
Example : 0x78 is at 0x15F2 and blue part is 0x4F4A if we sum them up, the result is 0x653C, so we should un-zlib from 0x15F2 (included) to 0x653C (excluded).

Then, just repeat it.



In Golang, you can parse it that way:
Code:
func Unzlib(data []byte) ([]byte, error) {
	var out bytes.Buffer
	bb := bytes.NewBuffer(data)
	r, err := zlib.NewReader(bb)
	if err != nil {
		return []byte{}, err
	}
	defer r.Close()
	_, err = io.Copy(&out, r)
	return out.Bytes(), err
}

func unmarshal(data []byte) (FileNtData, error) {
	var fnt FileNtData

	if len(data) < 0x15 { // Be sure the file is larger than header
		return fnt, errors.New("file is too short to be NT Data")
	}

	fnt.header.header = data[0:0x0C]
	fnt.header.unknown1 = data[0x0C:0x10]
	fnt.header.nbFiles = binary.LittleEndian.Uint32(data[0x10:0x14])
	fnt.header.unknown2 = data[0x14]

	if uint32(len(data)) < 0x15+0x8*fnt.header.nbFiles { // Be sure the file is larger than header + entities info
		return fnt, errors.New("file is too short to be NT Data")
	}

	for i := 0; i < int(fnt.header.nbFiles); i++ {
		var d ntData

		d.id = binary.LittleEndian.Uint32(data[0x15+(i*8) : 0x19+(i*8)])
		d.offset = binary.LittleEndian.Uint32(data[0x19+(i*8) : 0x1D+(i*8)])

		fmt.Println(d.id, d.offset)

		if len(data) <= int(d.offset)+0x0D { // Be sure the file is larger than where data is + data info
			return fnt, errors.New("file is too short to be NT Data")
		}

		d.unknown = data[d.offset : d.offset+0x04]
		d.dataSize = binary.LittleEndian.Uint32(data[d.offset+0x04 : d.offset+0x08])
		d.packedDataSize = binary.LittleEndian.Uint32(data[d.offset+0x08 : d.offset+0x0C])
		d.isPacked = data[d.offset+0x0C] != 0

		if len(data) < int(d.offset)+0x0D+int(d.packedDataSize) { // Be sure the file is larger than where data is + data info + data
			return fnt, errors.New("file is too short to be NT Data")
		}

		d.data = data[d.offset+0x0D : d.offset+0x0D+d.packedDataSize]

		if d.isPacked {
			var err error
			if d.data, err = cryptoutils.Unzlib(d.data); err != nil {
				return fnt, err
			}
		}

		fnt.data = append(fnt.data, d)
	}
	fnt.sort()

	return fnt, nil
}
By repeating those steps (or by using this code), we are left with the map structure files.
Here is what it looks like :

It is the same principle: there are some bytes and we need their meaning - there are at least two ways of doing it, I will explain both later, let's first about known values.


Any part that is before the square is not important (it is metadata for the map, that you can see there: )
The black part is the number of UNIQUE models which are imported.

Then comes a list of ids (4 bytes each)

Red part: model id - it is basically the name of the .obj. For example, here it is 0xA22 (2594), it means:

(Note that I am working on the map id 63)
Blue part: Another model id
Red : same, etc

Then we go to 0x89 + nb of models * 4, in my case, 0xC5 :

(one at the right, in reality - it starts at the 0x01)
This is the start of an object. In this block, everything related to it is described: its color, its position, its rotation axis, its size, etc.

The first selected byte (0x01) is what I called "interaction type". It defines two things :
1) the space the object takes in memory, 0x01 means it will take 0x45 bytes - see for more informations
2) Not 100% sure - it also defines what kind of object it is.
0x00 seems to be useless
0x01 means it is "ground"
0x02 means it is an object, like a rock, etc
0x03 means a light or something like that (or I confused with 0x00)


Red part: model index - in this case it is 0x0000, meaning the first one, so we go at 0x87 + this value. 0x87+0x0000 = 0x87, so we take a look at the value, it is 0x00000A22 (2594) it means it is the object I showed you earlier.
Orange part: X position
Green part: Z position
Black part: Y position

I lost some data, so you will have to continue by yourself, I will explain two ways of doing it.

First: bad but easy method (I recommand starting by this one)
- Open the map file with an hex editor (HxD for example)
- Go to a data block that codes for an object (the blue selection on the screen above for example)
- Change some data (I recommand 1 by 1)
- Save, import it on OnexExplorer, save the NStuData file, place it in Nostale/NostaleData directory
- Connect to Nostale, go on the map and see the changes (and note it, obviously)
- Revert your changes and start again with another offset

Second:
- Connect to Nostale, go on the map
- Start Cheat Engine as admin, attach it to Nostale
- Open the map file with HxD
- Pick up an object you would like to observ
- Copy some data on it (ex :

)
- Save the address value (0xEB7EFDC in my case)
- Open Reclass as admin:
- Attach Reclass to NosTale
- Enter the address in the """textbox"""

- Change the address that way : remove the last digit/letter and change it by 0 : 0xEB7EFDC -> 0xEB7EFD0
- Change the address that way : remove the before last digit/letter by 1 : 0xEB7EFD0 -> 0xEB7EFC0
- Repeat until you see something like :

You MUST see a class name when hoverring the address "NostaleClientX.exe+something"
In my case, I had to reduce from 0xEB7EFD0 to 0xEB7EFA0 in order to see this. It means every values below this line is a property of our variables (well, not if you go too far)
- Now, go back on HxD and on Reclass and compare the values:

(I recommand taking a screenshot of Reclass before any modifications in order to have a backup)
- Then go back on Reclass, and change some values - for some values you might change map or move camera in order to notice the difference, for some you won't need.
Here is an example:


Also, I created long time ago that can help :
- When you try to add an object, it won't work, you have to replace one, so there is something that tells the number of objects on the map or something like that



I hope this was useful, I think every important details have been discussed and you should be able to link data to what they do and then be able to continue this work!
Apourtartt is offline  
Thanks
7 Users
Old 05/17/2022, 18:42   #2
 
Bejine's Avatar
 
elite*gold: 0
Join Date: Jul 2014
Posts: 283
Received Thanks: 317
Quote:
Originally Posted by Apourtartt View Post
Red part: ID - starts from 0 to... number of files - 1 (0 to 697 in my case)
that's not true, ID can be anything (as long as its unique, and i think it also needs to be sorted), it doesn't have to be continuous from 0.
Bejine is offline  
Old 05/17/2022, 19:57   #3
 
elite*gold: 0
Join Date: Oct 2018
Posts: 257
Received Thanks: 207
Quote:
Originally Posted by Bejine View Post
that's not true, ID can be anything (as long as its unique, and i think it also needs to be sorted), it doesn't have to be continuous from 0.
You are right, but if I go into details of everything I would need more than 2 hours to write it
Apourtartt is offline  
Reply


Similar Threads Similar Threads
GM tool for manage your svr
09/12/2010 - EO PServer Hosting - 25 Replies
here you are a GM tool for manage your svr ealily! http://content.imagesocket.com/images/my0106d.jpg http://content.imagesocket.com/images/my0734d.jpg http://content.imagesocket.com/images/my02459.jpg http://content.imagesocket.com/images/my03c8e.jpg http://content.imagesocket.com/images/my04ef8.jpg http://content.imagesocket.com/images/my05fa4.jpg http://content.imagesocket.com/images/my06721.jpg
cant manage to update silkroad
09/15/2007 - Silkroad Online - 1 Replies
i cant manage to update silkroad i reinstalled the game like 100 times and nothing im getting a fucked up error usually i get this error at 20%/25% or 0 =\ does anybody know how can i finally update the game? X__X
Cant manage to make it work..
09/12/2007 - SRO Hacks, Bots, Cheats & Exploits - 12 Replies
Hello. I wanna try botting in SRO. I've downloaded lastest tbot (909),tcrack12_4, disabled adapter (microsoft), downloaded 1.18 client and replaced the exe in SRO folder. When i launch the bot, it says "Please load right client version".. What to do? P.S: Tried with 801 Too.. same error.. BTW: Why i got the app's window cut? (or it supposed to be like that..) -> http://img160.imageshack.us/img160/7607/wtfka2.jp g
manage an 8G Epic mount!
10/10/2006 - WoW Guides & Templates - 33 Replies
Thats right, I managed to aquire an Epic mount for mearly 8G and am now able to ride it w/o buying the 150 riding skill. How? Well, after the patch (12.1), quite a few people had actually bought their mounts but hadn't received their skill. This was mainly a select group of toons who were not of level to ride their mount yet, but had it banked for when they aquired that level. As it stood, these people would have to end up paying double if they now wanted to ride their epic mount. As for me,...
Any one manage to use walker after 30/7/05 patch?
08/30/2005 - Lineage 2 - 1 Replies
No walker for me after 30/7/05 patch :(. Protocol 555 can get to the char select area, but refuses to log, tried using koreas latest protocol 557 but cant even get past the link login server part. any one managed to get in? Using 10.5.1 walker, but also tried logging with 4.8 / 4.9



All times are GMT +1. The time now is 01:00.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.