Динамическое создание ландшафта (Wurst)

Published
» Способ реализации: Wurst
» Тип: Наработка
» Версия Warcraft: 1.30 (должно работать и на 1.27)
Наработка содержит исполняющий файл и библиотеку wurst. Исполняющий файл берет 3 файла (.doo, .w3e, .w3d) и создает пакет wurst с заданным именем. Для работы пакета необходима вышеназванная библиотека. При генерации указывается регион для копирования. Информация будет получена только для этого региона.
Содержание конечного Name.wurst:
  • карта высот
  • текстуры ландшафта
  • используемые на данном участке типы декораций (doodads - точно, destructable - не проверял)
  • расположение декораций относительно центра региона (z (высота) - абсолютная величина, в дальнейшем планирую исправить)
В итоге будет создан экземпляр класса DecorationPreset c функцией create(real centr_x, real centr_y, int rotate_90), которая позволяет создать копию обработанного участка. rotate_90 - позволяет поворачивать пресет на 90 градусов относительно центра заданное число раз.
Так как триггерно можно создавать только destructable, то на декорации (doodad) в исходной карте распространяются те же ограничения что и на destructable, например нельзя делать ассиметричный масштаб.
» Библиотека
» MoreDestructableDefs.wurst
package MoreDestructableDefs

import public DestructableObjEditing
import public ObjEditingNatives

public function DestructableDefinition.setMaxRoll (real value)
    this.def.setUnreal ("bmar", value)
    
public function DestructableDefinition.setMaxPitch (real value)
    this.def.setUnreal ("bmap", value)

public function DestructableDefinition.setSelectable (bool value)
    this.def.setBoolean ("bgse", value)

public function DestructableDefinition.setShadow (string value)
    this.def.setString ("bshd", value)

public function DestructableDefinition.setColor (int red, int green, int blue)
    this.def.setInt ("bvcr", red)
    this.def.setInt ("bvcg", green)
    this.def.setInt ("bvcb", blue)

public function DestructableDefinition.setDeathPath (string value)
    this.def.setString ("bptd", value)

public function DestructableDefinition.setMinScale (real value)
    this.def.setUnreal ("bmis", value)

public function DestructableDefinition.setMaxScale (real value)
    this.def.setUnreal ("bmas", value)

public function DestructableDefinition.setTargetType (string value)
    this.def.setString ("btar", value)

public function DestructableDefinition.setNumVar (int value)
    this.def.setInt ("bvar", value)
» ClassDecorationData.wurst
package ClassDecorationData


public class DecorationData
    int old_id
    int new_id
    vec3 offset
    angle angle
    real scale
    int variation

    construct (int old_id, int new_id, real x, real y, real z, real angle_rad, real scale, int variation)
        this.old_id = old_id
        this.new_id = new_id
        this.offset = vec3 (x, y, z)
        this.angle = angle (angle_rad)
        this.scale = scale
        this.variation = variation

    function getId () returns int
        if (this.new_id == -1)
            print ("Get decoration type id error")
        return this.new_id
» ClassTerrainData.wurst
package ClassTerrainData


public class TerrainData
    int  id
    vec3 offset

    construct (int id, real x, real y, real z)
        this.id = id
        this.offset = vec3 (x, y, z)

    construct (int id, vec3 pos)
        this.id = id
        this.offset = pos
» ClassDecorationType.wurst
package ClassDecorationType

import MoreDestructableDefs
import ObjectIdGenerator

public decorationTuple array all_types
int types_count = 0

public tuple decorationTuple (int old_id, int new_id, string model, int red, int green, int blue)

public function compiletime (decorationTuple deco_tuple) returns decorationTuple
    return deco_tuple

public function addDecorationType (decorationTuple type_tuple)
    bool found = false
    for i = 0 to types_count
        if (all_types[i].new_id == type_tuple.new_id)
            found = true
    if (not found)
        all_types[types_count] = type_tuple
        types_count++

public function registerDecorationType (int old_id, string model, int red, int green, int blue) returns decorationTuple
    decorationTuple type_tuple = decorationTuple (old_id, 0, model, red, green, blue)
    bool found = false
    for i = 0 to types_count
        if (all_types[i].model == model and
            all_types[i].red == red and
            all_types[i].green == green and
            all_types[i].blue == blue)

            type_tuple.new_id = all_types[i].new_id
            found = true
            break

    if (not found)
        type_tuple.new_id = UPGD_ID_GEN.next()
        if compiletime
            DestructableDefinition _tmp_type = new DestructableDefinition(type_tuple.new_id, 'LTbr')
                ..setTargetType ("")
                ..setSelectable (false)
                ..setShadow ("")
                ..setModel (type_tuple.model)
                ..setNumVar (1)
                ..setColor (type_tuple.red, type_tuple.green, type_tuple.blue)
                ..setPath ("")
                ..setDeathPath ("")
                ..setMaxScale (9.9)
                ..setMinScale (0.1)
        all_types[types_count] = type_tuple
        types_count++

    return type_tuple
/*
public function findType (DecorationData data) returns int
    for i = 0 to types_count
        if (all_types[i].old_id == old_id)
            if (all_types[i].model == model and
                all_types[i].red == red and
                all_types[i].green == green and
                all_types[i].blue == blue)
    
                type_tuple.new_id = all_types[i].new_id
                found = true
                break
    return -1*/
» DecorationPreset.wurst
package ClassDecorationPreset

import public LinkedList

import public ClassDecorationType
import public ClassDecorationData
import public ClassTerrainData
import public ObjectIds

LinkedList<DecorationPreset> all_presets = new LinkedList<DecorationPreset>

function findPreset (string name) returns DecorationPreset
    DecorationPreset found = null
    for data in all_presets
        if (data.getName() == name)
            found = data
            break
    return found

public class DecorationPreset
    private string name
    private LinkedList<DecorationData> decorations
    private LinkedList<TerrainData> terrain

    construct (string name, LinkedList<DecorationData> decorations, LinkedList<TerrainData> terrain)
        this.name = name
        this.decorations = decorations
        this.terrain = terrain
        all_presets.add(this)

    function getName () returns string
        return this.name

    function create (real centr_x, real centr_y, int rotate_90)
        vec3 cur_pos
        angle cur_angle
        real cx = centr_x % 128
        real cy = centr_y % 128
        int rot_90 = rotate_90 mod 4
        /* Terrain */
        for cur_point in terrain
            cur_pos = cur_point.offset
            for i = 0 to rot_90
                real tmp
                tmp = cur_pos.x
                cur_pos.x = -cur_pos.y
                cur_pos.y = tmp
            TerrainDeformCrater (cur_pos.x, cur_pos.y, 128, cur_pos.z, 0, true)
            SetTerrainType (cur_pos.x, cur_pos.y, cur_point.id, -1, 1, 1)
        /* Decorations */
        for cur_decor in decorations
            cur_pos = cur_decor.offset
            cur_angle = cur_decor.angle
            for i = 0 to rot_90
                real tmp
                tmp = cur_pos.x
                cur_pos.x = -cur_pos.y
                cur_pos.y = tmp
                cur_angle = (cur_angle.degrees() + 90).fromDeg()
            CreateDestructableZ (cur_decor.getId(), cx + cur_pos.x, cy + cur_pos.y, cur_pos.z, cur_angle.degrees(), cur_decor.scale, cur_decor.variation)
        FogMaskEnable(false)
        FogEnable(false)
        FogMaskEnable(true)
        FogEnable(true)
» Пример файла результата
package Test2

import public ClassDecorationPreset

/* Don't change constants manually. */
constant string name = "Test2"
constant real size_x = 512.00
constant real size_y = 512.00
constant int destr_count = 6
constant int points_count = 25
constant int types_count = 2

decorationTuple array used_types
LinkedList<DecorationData> decorations = new LinkedList<DecorationData>
LinkedList<TerrainData> terrain = new LinkedList<TerrainData>
public DecorationPreset dp_Test2


init
    addTypesData()
    for i = 0 to types_count
        addDecorationType(used_types[i])
    addDecorationData()
    addTerrainData()
    dp_Test2 = new DecorationPreset (name, decorations, terrain)

    dp_Test2.create (0, 0 , 0)


function getNewId(int old_id) returns int
    for i = 0 to types_count
        if used_types[i].old_id == old_id
            return used_types[i].new_id
    return -1


function addTypesData ()
    used_types[0] = compiletime(registerDecorationType('D000', "Doodads\\Cityscape\\Props\\City_Statue\\City_Statue.mdl", 255, 255, 255))
    used_types[1] = compiletime(registerDecorationType('D001', "Doodads\\Cityscape\\Structures\\City_ColumnSingle2_Ruined\\City_ColumnSingle2_Ruined.mdl"​, 255, 255, 255))


function addDecorationData ()
    decorations.add (new DecorationData ('D000', getNewId('D000'), -3.02, 25.50, 222.90, 4.712389, 1.00, 1))
    decorations.add (new DecorationData ('D001', getNewId('D001'), -68.40, -36.50, 171.70, 2.356194, 1.20, 1))
    decorations.add (new DecorationData ('D001', getNewId('D001'), -100.25, 28.36, 171.70, 3.573724, 1.19, 1))
    decorations.add (new DecorationData ('D001', getNewId('D001'), 98.03, 26.87, 171.70, 1.110093, 1.19, 1))
    decorations.add (new DecorationData ('D001', getNewId('D001'), -7.50, 104.71, 171.70, -0.807842, 1.20, 1))
    decorations.add (new DecorationData ('D001', getNewId('D001'), 72.89, -31.06, 171.70, 2.356194, 1.20, 1))


function addTerrainData ()
    terrain.add (new TerrainData ('Jblm', -256.00, -256.00, 0))
    terrain.add (new TerrainData ('Jblm', -128.00, -256.00, 0))
    terrain.add (new TerrainData ('Jblm', 0.00, -256.00, 0))
    terrain.add (new TerrainData ('Jblm', 128.00, -256.00, 0))
    terrain.add (new TerrainData ('Jblm', 256.00, -256.00, 0))
    terrain.add (new TerrainData ('Jblm', -256.00, -128.00, 0))
    terrain.add (new TerrainData ('Jbtl', -128.00, -128.00, -152))
    terrain.add (new TerrainData ('Jbtl', 0.00, -128.00, -152))
    terrain.add (new TerrainData ('Jbtl', 128.00, -128.00, -152))
    terrain.add (new TerrainData ('Jblm', 256.00, -128.00, 0))
    terrain.add (new TerrainData ('Jblm', -256.00, 0.00, 0))
    terrain.add (new TerrainData ('Jblm', -128.00, 0.00, -152))
    terrain.add (new TerrainData ('Jblm', 0.00, 0.00, -152))
    terrain.add (new TerrainData ('Jblm', 128.00, 0.00, -152))
    terrain.add (new TerrainData ('Jblm', 256.00, 0.00, 0))
    terrain.add (new TerrainData ('Jblm', -256.00, 128.00, 0))
    terrain.add (new TerrainData ('Jblm', -128.00, 128.00, -152))
    terrain.add (new TerrainData ('Jblm', 0.00, 128.00, -152))
    terrain.add (new TerrainData ('Jblm', 128.00, 128.00, -152))
    terrain.add (new TerrainData ('Jblm', 256.00, 128.00, 0))
    terrain.add (new TerrainData ('Jblm', -256.00, 256.00, 0))
    terrain.add (new TerrainData ('Jblm', -128.00, 256.00, 0))
    terrain.add (new TerrainData ('Jblm', 0.00, 256.00, 0))
    terrain.add (new TerrainData ('Jblm', 128.00, 256.00, 0))
    terrain.add (new TerrainData ('Jblm', 256.00, 256.00, 0))


Views: 1 075

» Лучшие комментарии


ApEJI #2 - 2 years ago (изм. ) -4
Голосов: +2 / -6
Очень легко сделать рандомный ландшафт с помощью триггеров, ловите мою наработку)
1 - резет
123 - 1й тайл
1234 - 2й тайл
12345 -3й тайл
а еще на сайте часы убегают, новость опубликована в 17:09 хотя сейчас 16:56
Прикрепленные файлы
Nelloy #3 - 2 years ago -6
Голосов: +2 / -8
ApEJI, ресет хранит только последнее изменение.
Рандомный ландшафт сделать играбельным в большем масштабе намного сложнее, а еще сложнее сделать его интересным, многообразным и логичным. Честно говоря, не увидел чего-то необычного в наработке. Тем более на гуи... Фу-фу-фу, простите...
ApEJI #4 - 2 years ago 5
Голосов: +5 / -0
Фу-фу-фу, простите...
я НЕ создавал на эту тему пост, просто показал возможность реализации даже на гуи в ЗАБРОШЕННОМ проекте, это будет полезно тем, кто спрашивает каждый день вопросы, и даже сегодня был такой про рандомные квесты
Nelloy #7 - 2 years ago 0
Голосов: +0 / -0
Clamp, сделано, но не нашел как прятать под спойлер
МрачныйВорон #9 - 1 year ago (изм. ) 0
Голосов: +0 / -0
Можете объяснить как эта работает? Утверждаю yes (y), вожу название name, координаты (сам не знаю какие надо, у меня карта 64х64, значит ли что везде надо 64?). Далее создается файлик с name и это все

И да, какое назначение этой программы?