Register for your free account! | Forgot your password?

Go Back   elitepvpers > MMORPGs > Nostale
You last visited: Today at 13:55

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

Advertisement



[Release] NSeffData VFX structure

Discussion on [Release] NSeffData VFX structure within the Nostale forum part of the MMORPGs category.

Reply
 
Old   #1
 
Bejine's Avatar
 
elite*gold: 0
Join Date: Jul 2014
Posts: 283
Received Thanks: 317
Lightbulb [Release] NSeffData VFX structure

structures.h
Code:
#pragma once
#include <vector>

//C++ doesnt have those data types, so I'll just store them in floats, but this is how you read them
using half = float;	//2 bytes, short(value)/32767.0f
using single = float; //1 byte, byte(value)/127.0f
using half_mid = float; //2 bytes, (short(value) < 0) ? ((-(val + 32768))/32767.0f) : (val/32767.0f);
using single_mid = float; //1 byte, (byte(value) < 0) ? ((-(val + 128))/127.0f) : (val/127.0f);

struct Coordinates
{
	float x;
	float y;
	float z;
};

struct CoordinatesHalfMid
{
	half_mid x;
	half_mid y;
	half_mid z;
};

struct CoordinatesUByte
{
	uint8_t x;
	uint8_t z;
	uint8_t y;
};

using Vertex = Coordinates;

using Normal = Coordinates;

struct UVCoord
{
	float u;
	float v;
};

struct Face
{
	uint32_t f1;
	uint32_t f2;
	uint32_t f3;
};

struct Group
{
	std::vector<Face> faces;
};

struct Quaternion
{
	float x;
	float y;
	float z;
	float w;
};

struct QuaternionHalfMid
{
	half_mid x;
	half_mid y;
	half_mid z;
	half_mid w;
};

using Rotation = Quaternion;

using Scale = Coordinates;

struct TranslateAnimationFrameInfo
{
	int16_t timestamp;
	Coordinates translate;
};

struct RotateAnimationFrameInfo
{
	int16_t timestamp;
	Rotation rotation;
};

struct ScaleAnimationFrameInfo
{
	int16_t timestamp;
	Scale scale;
};

struct BoundingBox
{
	Coordinates min;
	Coordinates mid;
	Coordinates max;
	float radius;
};

struct TextureInfo
{
	int32_t texture_id;
	bool is_both_sides; //backface culling
	uint16_t group_id;	//id of faces group
};

struct AnimationHeader
{
	uint16_t unk;	//???
	uint16_t length;	//these 3 names might be misleading, don't assume they are correct
	uint16_t ticks;
	uint16_t speed;
};

struct NodeAnimationFrameValues
{
	Rotation rotation;
	Scale scale;
	Coordinates translation;
};

struct NodeInfo
{
	Coordinates translate;
	Rotation rotate;
	Scale scale;
	std::vector<TranslateAnimationFrameInfo> translate_animation_frames;
	std::vector<RotateAnimationFrameInfo> rotate_animation_frames;
	std::vector<ScaleAnimationFrameInfo> scale_animation_frames;
	std::vector<TextureInfo> texture_infos;
};

struct TransformNode
{
	std::vector<TransformNode> children;
	NodeInfo node_info;
};

struct TextureData
{
	int16_t width;
	int16_t height;
	bool smooth_scaling;
	uint8_t mipmap_depth;
	uint32_t internal_format;
	uint32_t format;
	uint32_t type;
	uint32_t texId;
	uint8_t bytesize;
	std::vector<char> data;
};

struct Color
{
	uint8_t blue;
	uint8_t green;
	uint8_t red;
	uint8_t alpha;
};

struct VfxConfigurationFromAtoB
{
	float origin_height;
	uint8_t follow_entity_height;
	uint8_t padding_bytes[42];
};

struct VfxConfigurationNormal
{
	float origin_height;
	Coordinates origin_offset;
	float target_height;
	Coordinates target_offset;
	float distance_offset;	//offset in origin<->target axis
	float travel_speed;
	float height_parabola;
	uint16_t unk1;
	half_mid plane_parabola;
};

struct VfxConfigurationRandomness
{
	CoordinatesHalfMid emitters_offset;	//the whole cube of emitters moves
	QuaternionHalfMid emitters_rotation;	//the whole cube of emitters rotates
	CoordinatesHalfMid emitters_distance;	//distance between themselves in their grid
	CoordinatesHalfMid emitters_vector;
	CoordinatesUByte emitters_count;		//amount of emitters and amount of axis it emits on given coord
	CoordinatesUByte particles_rotation;	//along given axis, intensity
	CoordinatesUByte particles_scale;	//along given axis, intensity
	uint8_t gravity;
	uint8_t first_tick_intensity;
	uint8_t intensity;
	uint8_t rate;
	uint16_t tick_delay_min;
	uint16_t tick_delay_max;
	uint16_t particle_lifespan_min;
	uint16_t particle_lifespan_max;
};

union VfxConfiguration
{
	VfxConfigurationNormal normal;
	VfxConfigurationFromAtoB from_a_to_b;
	VfxConfigurationRandomness randomness;
};

struct VfxPatchCount
{
	uint32_t count;
	uint32_t timestamps_address;	//only in-memory for faster reading (?)
	uint32_t values_address;	//only in-memory for faster reading (?)
};

enum VfxObjectType : uint8_t
{
	NORMAL = 0,
	TARGETED = 1,
	RANDOMNESS = 2
};

enum VfxObjectInterpolationType : uint8_t
{
	RUN_ONCE = 0,
	RUN_ONCE_AND_TO_FIRST = 1,
	REPEAT = 2,
	ONLY_LAST = 3
};

struct VfxObjectHeader
{
	uint32_t ft;
	VfxObjectType type;	//0 - normal, 1 - from A to B, 2 - randomness
	uint8_t camera_lock;	//maybe bit flags?
	uint8_t only_on_hit;
	uint8_t split_damage;
	uint32_t source_blending;
	uint32_t destination_blending;
	int32_t model_1_id;
	int32_t model_2_id;	//apparently always -1 and not actually model2? wtf
	uint8_t on_target;
	VfxConfiguration configuration;	//VfxConfigurationNormal, VfxConfigurationFromAtoB, or VfxConfigurationRandomness
	AnimationHeader animation_ticks_info;
	int32_t anim_offset;	//appear after this time
	uint32_t anim_duration;	//absolute, so if anim_offset > anim_duration, nothing will show
	uint8_t flag_0;
	VfxObjectInterpolationType interpolation;
	uint8_t follow_previous_object;	//if true, object will be relative to the previous (?) one
	uint8_t has_depth_test;
	uint8_t has_transform;	//scale, rotate and translate patches
	uint8_t flag_2;
	uint8_t flag_3;	//unused???
	uint8_t has_texture_transform;	//texture_scale, texture_rotation and texture_translate patches
	VfxPatchCount patch_rotation_count;
	VfxPatchCount patch_scale_count;
	VfxPatchCount patch_translation_count;
	VfxPatchCount patch_color_count;
	VfxPatchCount patch_texture_count;
	VfxPatchCount patch_texture_rotation_count;
	VfxPatchCount patch_texture_scale_count;
	VfxPatchCount patch_texture_translate_count;
};

struct VfxHeader
{
	int32_t vfx_id;
	uint32_t unk1;
	uint32_t unk2;
	uint16_t object_count;
	uint32_t unk3;
	int32_t unk_id2;
	uint32_t unk4;
};

struct VfxPatchRotation
{
	std::vector<uint16_t> timestamps;
	std::vector<Rotation> rotations;
};

struct VfxPatchScale
{
	std::vector<uint16_t> timestamps;
	std::vector<Scale> scales;
};

struct VfxPatchTranslation
{
	std::vector<uint16_t> timestamps;
	std::vector<Coordinates> translations;
};

struct VfxPatchColor
{
	std::vector<uint16_t> timestamps;
	std::vector<Color> colors;
};

struct VfxPatchTexture
{
	std::vector<uint16_t> timestamps;
	std::vector<int32_t> textures;
};

struct VfxPatchTextureRotation
{
	std::vector<uint16_t> timestamps;
	std::vector<Rotation> texture_rotations;
};

struct VfxPatchTextureScale
{
	std::vector<uint16_t> timestamps;
	std::vector<Scale> texture_scales;
};

struct VfxPatchTextureTranslation
{
	std::vector<uint16_t> timestamps;
	std::vector<Coordinates> texture_translations;
};

struct VfxObjectPatch
{
	VfxPatchRotation rotation;
	VfxPatchScale scale;
	VfxPatchTranslation translation;
	VfxPatchColor color;
	VfxPatchTexture texture;
	VfxPatchTextureRotation texture_rotation;
	VfxPatchTextureScale texture_scale;
	VfxPatchTextureTranslation texture_translation;
};

struct VfxObjectPatchValues
{
	Rotation rotation;
	Scale scale;
	Coordinates translation;
	Color color;
	int32_t texture;
	Rotation texture_rotation;
	Scale texture_scale;
	Coordinates texture_translation;
};
loadVfx function body (pseudo .cpp)
NSeffElement is irrelevant, this is just so you can know how the NSeffData item structure is, because it's not in the code above.
Code:
    NSeffElement vfx;

    VfxHeader vfx_header{};
    vfx_header.vfx_id = LittleEndianFileReader::readInt(h);
    vfx_header.unk1 = LittleEndianFileReader::readInt(h);
    vfx_header.unk2 = LittleEndianFileReader::readInt(h);
    vfx_header.object_count = LittleEndianFileReader::readShort(h);
    vfx_header.unk3 = LittleEndianFileReader::readInt(h);
    vfx_header.unk_id2 = LittleEndianFileReader::readShort(h);
    vfx_header.unk4 = LittleEndianFileReader::readInt(h);
    vfx.setHeader(vfx_header);

    for (int i = 0; i < vfx_header.object_count; i++)
    {
        VfxObjectHeader obj_info{};
        obj_info.ft = LittleEndianFileReader::readUInt(h);
        obj_info.type = (VfxObjectType)LittleEndianFileReader::readUByte(h);
        obj_info.camera_lock = LittleEndianFileReader::readUByte(h);
        obj_info.only_on_hit = LittleEndianFileReader::readUByte(h);
        obj_info.split_damage = LittleEndianFileReader::readUByte(h);
        obj_info.source_blending = LittleEndianFileReader::readUInt(h);
        obj_info.destination_blending = LittleEndianFileReader::readUInt(h);
        obj_info.model_1_id = LittleEndianFileReader::readInt(h);
        obj_info.model_2_id = LittleEndianFileReader::readInt(h);
        obj_info.on_target = LittleEndianFileReader::readUByte(h);
        if (obj_info.type == VfxObjectType::RANDOMNESS)
        {
            VfxConfigurationRandomness conf{};
            conf.emitters_offset.x = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_offset.y= LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_offset.z = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_rotation.x = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_rotation.y = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_rotation.z = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_rotation.w = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_distance.x = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_distance.y = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_distance.z = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_vector.x = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_vector.y = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_vector.z = LittleEndianFileReader::readPackedMidFloat(h);
            conf.emitters_count.x = LittleEndianFileReader::readUByte(h);
            conf.emitters_count.y = LittleEndianFileReader::readUByte(h);
            conf.emitters_count.z = LittleEndianFileReader::readUByte(h);
            conf.particles_rotation.x = LittleEndianFileReader::readUByte(h);
            conf.particles_rotation.y = LittleEndianFileReader::readUByte(h);
            conf.particles_rotation.z = LittleEndianFileReader::readUByte(h);
            conf.particles_scale.x = LittleEndianFileReader::readUByte(h);
            conf.particles_scale.y = LittleEndianFileReader::readUByte(h);
            conf.particles_scale.z = LittleEndianFileReader::readUByte(h);
            conf.gravity = LittleEndianFileReader::readUByte(h);
            conf.first_tick_intensity = LittleEndianFileReader::readUByte(h);
            conf.intensity = LittleEndianFileReader::readUByte(h);
            conf.rate = LittleEndianFileReader::readUByte(h);
            conf.tick_delay_min = LittleEndianFileReader::readUShort(h);
            conf.tick_delay_max = LittleEndianFileReader::readUShort(h);
            conf.particle_lifespan_min = LittleEndianFileReader::readUShort(h);
            conf.particle_lifespan_max = LittleEndianFileReader::readUShort(h);
            obj_info.configuration.randomness = conf;
        }
        else if (obj_info.type == VfxObjectType::NORMAL)
        {
            VfxConfigurationNormal conf{};
            conf.origin_height = LittleEndianFileReader::readFloat(h);
            conf.origin_offset.x = LittleEndianFileReader::readFloat(h);
            conf.origin_offset.y = LittleEndianFileReader::readFloat(h);
            conf.origin_offset.z = LittleEndianFileReader::readFloat(h);
            conf.target_height = LittleEndianFileReader::readFloat(h);
            conf.target_offset.x = LittleEndianFileReader::readFloat(h);
            conf.target_offset.y = LittleEndianFileReader::readFloat(h);
            conf.target_offset.z = LittleEndianFileReader::readFloat(h);
            conf.distance_offset = LittleEndianFileReader::readFloat(h);
            conf.travel_speed = LittleEndianFileReader::readFloat(h);
            conf.height_parabola = LittleEndianFileReader::readFloat(h);
            conf.unk1 = LittleEndianFileReader::readUShort(h);
            conf.plane_parabola = LittleEndianFileReader::readBytePackedMidFloat(h);
            obj_info.configuration.normal = conf;
        }
        else
        {
            VfxConfigurationFromAtoB conf{};
            conf.origin_height = LittleEndianFileReader::readFloat(h);
            conf.follow_entity_height = LittleEndianFileReader::readUByte(h);
            conf.padding_bytes;
            h.read(reinterpret_cast<char*>(conf.padding_bytes), 42);
            obj_info.configuration.from_a_to_b = conf;
        }

        obj_info.animation_ticks_info.unk = LittleEndianFileReader::readUShort(h);
        obj_info.animation_ticks_info.length = LittleEndianFileReader::readUShort(h);
        obj_info.animation_ticks_info.ticks = LittleEndianFileReader::readUShort(h);
        obj_info.animation_ticks_info.speed = LittleEndianFileReader::readUShort(h);
        obj_info.anim_offset = LittleEndianFileReader::readInt(h);
        obj_info.anim_duration = LittleEndianFileReader::readUInt(h);
        obj_info.flag_0 = LittleEndianFileReader::readUByte(h);
        obj_info.interpolation = (VfxObjectInterpolationType)LittleEndianFileReader::readUByte(h);
        obj_info.follow_previous_object = LittleEndianFileReader::readUByte(h);
        obj_info.has_depth_test = LittleEndianFileReader::readUByte(h);
        obj_info.has_transform = LittleEndianFileReader::readUByte(h);
        obj_info.flag_2 = LittleEndianFileReader::readUByte(h);
        obj_info.flag_3 = LittleEndianFileReader::readUByte(h);
        obj_info.has_texture_transform = LittleEndianFileReader::readUByte(h);
        obj_info.patch_rotation_count.count = LittleEndianFileReader::readUInt(h);
        obj_info.patch_rotation_count.timestamps_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_rotation_count.values_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_scale_count.count = LittleEndianFileReader::readUInt(h);
        obj_info.patch_scale_count.timestamps_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_scale_count.values_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_translation_count.count = LittleEndianFileReader::readUInt(h);
        obj_info.patch_translation_count.timestamps_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_translation_count.values_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_color_count.count = LittleEndianFileReader::readUInt(h);
        obj_info.patch_color_count.timestamps_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_color_count.values_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_count.count = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_count.timestamps_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_count.values_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_rotation_count.count = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_rotation_count.timestamps_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_rotation_count.values_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_scale_count.count = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_scale_count.timestamps_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_scale_count.values_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_translate_count.count = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_translate_count.timestamps_address = LittleEndianFileReader::readUInt(h);
        obj_info.patch_texture_translate_count.values_address = LittleEndianFileReader::readUInt(h);

        vfx.addObjectInfo(obj_info);
    }

    for (int i = 0; i < vfx_header.object_count; i++)
    {
        VfxObjectPatch obj_patch;

        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_rotation_count.count; j++)
        {
            obj_patch.rotation.timestamps.push_back(LittleEndianFileReader::readUShort(h));
        }
        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_rotation_count.count; j++)
        {
            Rotation rotation{};
            rotation.x = LittleEndianFileReader::readFloat(h);
            rotation.y = LittleEndianFileReader::readFloat(h);
            rotation.z = LittleEndianFileReader::readFloat(h);
            rotation.w = LittleEndianFileReader::readFloat(h);
            obj_patch.rotation.rotations.push_back(rotation);
        }

        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_scale_count.count; j++)
        {
            obj_patch.scale.timestamps.push_back(LittleEndianFileReader::readUShort(h));
        }
        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_scale_count.count; j++)
        {
            Scale scale{};
            scale.x = LittleEndianFileReader::readFloat(h);
            scale.y = LittleEndianFileReader::readFloat(h);
            scale.z = LittleEndianFileReader::readFloat(h);
            obj_patch.scale.scales.push_back(scale);
        }

        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_translation_count.count; j++)
        {
            obj_patch.translation.timestamps.push_back(LittleEndianFileReader::readUShort(h));
        }
        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_translation_count.count; j++)
        {
            Coordinates translation{};
            translation.x = LittleEndianFileReader::readFloat(h);
            translation.y = LittleEndianFileReader::readFloat(h);
            translation.z = LittleEndianFileReader::readFloat(h);
            obj_patch.translation.translations.push_back(translation);
        }

        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_color_count.count; j++)
        {
            obj_patch.color.timestamps.push_back(LittleEndianFileReader::readUShort(h));
        }
        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_color_count.count; j++)
        {
            Color color{};
            color.blue = LittleEndianFileReader::readUByte(h);
            color.green = LittleEndianFileReader::readUByte(h);
            color.red = LittleEndianFileReader::readUByte(h);
            color.alpha = LittleEndianFileReader::readUByte(h);
            obj_patch.color.colors.push_back(color);
        }

        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_texture_count.count; j++)
        {
            obj_patch.texture.timestamps.push_back(LittleEndianFileReader::readUShort(h));
        }
        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_texture_count.count; j++)
        {
            int32_t texture = LittleEndianFileReader::readInt(h);
            obj_patch.texture.textures.push_back(texture);
        }

        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_texture_rotation_count.count; j++)
        {
            obj_patch.texture_rotation.timestamps.push_back(LittleEndianFileReader::readUShort(h));
        }
        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_texture_rotation_count.count; j++)
        {
            Rotation texture_rotation{};
            texture_rotation.x = LittleEndianFileReader::readFloat(h);
            texture_rotation.y = LittleEndianFileReader::readFloat(h);
            texture_rotation.z = LittleEndianFileReader::readFloat(h);
            texture_rotation.w = LittleEndianFileReader::readFloat(h);
            obj_patch.texture_rotation.texture_rotations.push_back(texture_rotation);
        }

        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_texture_scale_count.count; j++)
        {
            obj_patch.texture_scale.timestamps.push_back(LittleEndianFileReader::readUShort(h));
        }
        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_texture_scale_count.count; j++)
        {
            Scale texture_scale{};
            texture_scale.x = LittleEndianFileReader::readFloat(h);
            texture_scale.y = LittleEndianFileReader::readFloat(h);
            texture_scale.z = LittleEndianFileReader::readFloat(h);
            obj_patch.texture_scale.texture_scales.push_back(texture_scale);
        }

        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_texture_translate_count.count; j++)
        {
            obj_patch.texture_translation.timestamps.push_back(LittleEndianFileReader::readUShort(h));
        }
        for (uint32_t j = 0; j < vfx.getObjectInfos(i).patch_texture_translate_count.count; j++)
        {
            Coordinates texture_translation{};
            texture_translation.x = LittleEndianFileReader::readFloat(h);
            texture_translation.y = LittleEndianFileReader::readFloat(h);
            texture_translation.z = LittleEndianFileReader::readFloat(h);
            obj_patch.texture_translation.texture_translations.push_back(texture_translation);
        }

        vfx.addObjectPatch(obj_patch);
    }
little endian file reader .h that i used
Code:
#pragma once
#include <cstdint>
#include <fstream>

namespace LittleEndianFileReader
{
    inline int8_t readByte(std::fstream& f)
    {
        int8_t val = 0;
        char bytes[1] = { 0 };
        f.read(bytes, 1);

        val = bytes[0];

        return val;
    }

    inline uint8_t readUByte(std::fstream& f)
    {
        uint8_t val = 0;
        char bytes[1] = { 0 };
        f.read(bytes, 1);

        val = (unsigned)bytes[0];

        return val;
    }

    inline int32_t readInt(std::fstream& f)
    {
        int32_t val = 0;
        char bytes[4] = { 0 };
        f.read(bytes, 4);

        val = (bytes[0] & 0xFF) | ((bytes[1] & 0xFF) << 8) | ((bytes[2] & 0xFF) << 16) | ((bytes[3] & 0xFF) << 24);

        return val;
    }

    inline uint32_t readUInt(std::fstream& f)
    {
        uint32_t val = 0;
        char bytes[4] = { 0 };
        f.read(bytes, 4);

        val = (bytes[0] & 0xFF) | ((bytes[1] & 0xFF) << 8) | ((bytes[2] & 0xFF) << 16) | ((bytes[3] & 0xFF) << 24);

        return val;
    }

    inline int16_t readShort(std::fstream& f)
    {
        int16_t val = 0;
        char bytes[2] = { 0 };
        f.read(bytes, 2);

        val = (bytes[0] & 0xFF) | ((bytes[1] & 0xFF) << 8);

        return val;
    }

    inline uint16_t readUShort(std::fstream& f)
    {
        uint16_t val = 0;
        char bytes[2] = { 0 };
        f.read(bytes, 2);

        val = (bytes[0] & 0xFF) | ((bytes[1] & 0xFF) << 8);

        return val;
    }

    inline float readFloat(std::fstream& f)
    {
        uint32_t val = 0;
        char bytes[4] = { 0 };
        f.read(bytes, 4);

        val = (bytes[0] & 0xFF) | ((bytes[1] & 0xFF) << 8) | ((bytes[2] & 0xFF) << 16) | ((bytes[3] & 0xFF) << 24);
        
        return reinterpret_cast<float&>(val);
    }

    inline float readPackedFloat(std::fstream& f)
    {
        int16_t val = 0;
        char bytes[2] = { 0 };
        f.read(bytes, 2);

        val = (bytes[0] & 0xFF) | ((bytes[1] & 0xFF) << 8);

        return val / 32767.0f;
    }

    inline float readPackedMidFloat(std::fstream& f)
    //0x0000~0x7FFF positive, 0x8000~0xFFFF negative, where 0x8000 is equal to -0x0001
    {
        int16_t val = 0;
        char bytes[2] = { 0 };
        f.read(bytes, 2);

        val = (bytes[0] & 0xFF) | ((bytes[1] & 0xFF) << 8);
        if (val < 0)
            val = -(val + 32768);

        return val / 32767.0f;
    }

    inline float readBytePackedFloat(std::fstream& f)
    {
        int8_t val = 0;
        char bytes[1] = { 0 };
        f.read(bytes, 1);

        val = bytes[0] & 0xFF;

        return val / 127.0f;
    }

    inline float readBytePackedMidFloat(std::fstream& f)
        //0x00~0x7F positive, 0x80~0xFF negative, where 0x80 is equal to -0x01
    {
        int8_t val = 0;
        char bytes[1] = { 0 };
        f.read(bytes, 1);

        val = bytes[0] & 0xFF;
        if (val < 0)
            val = -(val + 128);

        return val / 127.0f;
    }

    inline void skip(std::fstream& f, uint32_t amount)
    {
        f.seekg(amount, std::ios::cur);
    }
}
Bejine is offline  
Thanks
22 Users
Old 12/13/2024, 23:27   #2
 
elite*gold: 0
Join Date: Mar 2023
Posts: 19
Received Thanks: 0
Does anyone know how to find the 3D model ID in the NSeffData structure? For example, for the Fire Wings, which have the VFX ID 1230 (+1 upgrade):

VfxHeader:
Vfx ID: 1230
Unk1: 33484
Unk2: 13255984
Object Count: 2
Unk3: 68726752
Unk ID2: 1
Unk4: 285474816

VfxObjectHeader 1:
FT: 67117061
Type: 0
Camera Lock: 0
Only On Hit: 2
Split Damage: 3
Source Blending: 50528256
Destination Blending: 4718592
Model 1 ID: -45136
Model 2 ID: 1711341567
On Target: 102
Configuration:
Normal Configuration:
Origin Height: 1.14399e-40
Origin Offset: (0, 0, -1.59232e-23)
Target Height: 2.26352e-41
Target Offset: (0, 0, 0)
Distance Offset: 0
Travel Speed: -1.07611e+08
Height Parabola: 2.21685e-41
Unk1: 0
Plane Parabola: 0.468764
Animation Ticks Info:
Unk: 7680
Length: 40960
Ticks: 0
Speed: 0
Animation Offset: -256
Animation Duration: 131327
Flag 0: 0
Interpolation: 1
Follow Previous Object: 0
Has Depth Test: 0
Has Transform: 1
Flag 2: 0
Flag 3: 0
Has Texture Transform: 0
Patch Rotation Count: 0
Timestamps Address: 0
Values Address: 256
Patch Scale Count: 3600986112
Timestamps Address: 3601002496
Values Address: 256
Patch Translation Count: 3600998400
Timestamps Address: 3601006592
Values Address: 0
Patch Color Count: 0
Timestamps Address: 0
Values Address: 0
Patch Texture Count: 0
Timestamps Address: 0
Values Address: 512
Patch Texture Rotation Count: 3602583552
Timestamps Address: 3974508544
Values Address: 2
Patch Texture Scale Count: 0
Timestamps Address: 0
Values Address: 0
Patch Texture Translation Count: 0
Timestamps Address: 0
Values Address: 85001216

VfxObjectHeader 2:
FT: 262176
Type: 0
Camera Lock: 2
Only On Hit: 3
Split Damage: 0
Source Blending: 256
Destination Blending: 2952808448
Model 1 ID: -177
Model 2 ID: 1717960959
On Target: 230
Configuration:
Normal Configuration:
Origin Height: 4.45613e-43
Origin Offset: (0, 0, 1.5882e-23)
Target Height: 8.82818e-44
Target Offset: (0, 0, 0)
Distance Offset: -1.0842e-19
Travel Speed: -1.07375e+08
Height Parabola: 8.54792e-44
Unk1: 0
Plane Parabola: 0.00183111
Animation Ticks Info:
Unk: 30
Length: 160
Ticks: 0
Speed: 0
Animation Offset: -1
Animation Duration: 512
Flag 0: 1
Interpolation: 0
Follow Previous Object: 0
Has Depth Test: 1
Has Transform: 0
Flag 2: 0
Flag 3: 0
Has Texture Transform: 0
Patch Rotation Count: 0
Timestamps Address: 0
Values Address: 1
Patch Scale Count: 14072656
Timestamps Address: 14066384
Values Address: 1
Patch Translation Count: 14072608
Timestamps Address: 14072624
Values Address: 2
Patch Color Count: 14066448
Timestamps Address: 14066464
Values Address: 0
Patch Texture Count: 0
Timestamps Address: 0
Values Address: 2
Patch Texture Rotation Count: 14066592
Timestamps Address: 49079136
Values Address: 0
Patch Texture Scale Count: 0
Timestamps Address: 0
Values Address: 0
Patch Texture Translation Count: 0
Timestamps Address: 0
Values Address: 0

So, what is supposed to be the 3D model ID in the NStgeData file?

I’ve tried searching one by one, but none match. Is there any calculation or formula involving any parameters to determine the 3D model ID?
3rJoselu is offline  
Reply

Tags
nostale, nseffdata, structure, vfx


Similar Threads Similar Threads
unpack / pack files NStuData, NSeffData
01/03/2021 - Nostale - 1 Replies
I am looking for a person who will make unpack / pack files NStuData, NSeffData we will agree individually Discord Maza#4746
[Release] Arena Info Packet Structure
02/21/2011 - CO2 PServer Guides & Releases - 12 Replies
Heya! I hope this become an usefull release for who use an source with arena... and i would really apreciate any help to end the other 4 packets .... (2208,2205,2206,2207); so... this is the structure... only... if u get it working you will see something like this in game: http://b.imagehost.org/0760/19240804.jpg
[Release] Packet encryption / structure
10/26/2010 - General Gaming Discussion - 13 Replies
============================================= ========= FANTASY TENNIS PACKET SYSTEM ======== ============== by AnotherCoder ============== ============================================= 1. ENCRYPTION 2. PACKET STRUCTURE
[Release] Basic Structure for Cloud Saint's Jar
08/19/2009 - CO2 PServer Guides & Releases - 1 Replies
I don't use LOTF or CoEmu but I know the quest has been release. This structure of the item packet is for the Jar. You have to find the method for adding a soul in the jar. I'm on the older client, I don't want to take the time to search... Length -> UInt16 //I think it's 36 like the other Type -> UInt16 //0x3F0 or 1008 UniqId -> UInt32 //Random Number ItemId -> UInt32 //750000 for the Jar ToKill -> UInt16 //0 to 65535 Type -> UInt16 //1 to 20 (Monster) SubType -> UInt16 //0x01 ->...



All times are GMT +1. The time now is 13:55.


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.