XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Барахолка
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
ScorpioT1000
Работаем
offline
Опыт: отключен
Но парсить код на предмет обращения к полям это уже слишком, как мне кажется
prog, это делается в пять строк
Тем более что моя утилита рассчитана на работу перед cJass
давай придумаем уникальный кейворд и я напишу ту, которая парсит перед cJass
Старый 21.02.2012, 18:59
prog

offline
Опыт: 32,865
Активность:
распарсить код карты регуляркой не проблема - просто на мой взгляд это избыточно.
prog:
если хоть один равкод не похож на равкод (значит там заюзали цикл или переменную), то ставим галку добавлять в базу все нестандартные (и "тронутые") объекты, т.е. уже для частных случаев фикс. хотя редко кто равкоды вставляет в чистом виде, НО cjass и оптимизатор векса какраз ДЕЛАЕТ ЭТО! =)
  1. мы работаем с .j файлом до всех оптимизаторов - в чистом виде.
  2. если бы мы работали с равкодами, то могли бы работать и с дефайнами - равкоды в БД вносить придется все-же через пометки в РО (например в поле описание редактора вбить в конце saved)
  3. тип поля это уже другой вопрос - для начала сделаю через конфиг (правда не внешний, а в комментариях) а потом добавлю автосбор явно указанных типов.
  4. можно и явно загруженные равкоды, конечно, добавлять в БД, но лучше вызовы всех явных значений по равкоду тогда заменять дефайном - данные то статические.
Старый 21.02.2012, 19:05
ScorpioT1000
Работаем
offline
Опыт: отключен
мда, регуляркой по файлу - это сильно =) ну успехов вобщем ...
Старый 21.02.2012, 20:19
prog

offline
Опыт: 32,865
Активность:
ScorpioT1000, да, если скрипт большой - будет долго) вот домой с работы вернусь - что-нибудь запилю.
Старый 21.02.2012, 20:43
Alex_Hell
Mapmaker 'N' Programmer
offline
Опыт: 6,885
Активность:
На счет списка полей - я считаю что можно подгрузить все возможные поля. Хотя тут нужно смотреть производительность. Предложили вариант - смотреть какие поля используются, и только их загонять в структуру - тоже способ, определить это не сложно - найти все обращения к конкретным свойствам структуры типа UnitInfo.Name, UnitInfo.Description, и только для используемых сгенерить БД.
Количество сохраненных юнитов, предметов - опять таки можно все сохранить. Нужно кнечно тестить производительность. Но я уверен что хоть 100 хоть 1000 юнитов будут почти одинаково влиять на производительность - это же шех таблица, она для этого и предназначена, в крайнем случае можно разбить на несколько хеш-таблиц, в каждой допустим храняться данные по 100 юнитам, тогда на начальном этапе нужно будет выбрать одну из таблиц, а уже потом внутри нее нужного юнита. Распределение по таблицам пусть делает прога, она например заводит
Hashtable UnitTable[count] и внутри метода
UnitInfo UnitInfo.create(int id)
{
integer tableIndex
UnitInfo info = info.allocate()
if (id <= 'B000')
{
tableIndex = 0
}
elseif if (id <= 'C000')
{
tableIndex = 1
}
или арифметически: tableIndex = (id - 'A000') / 100

UnitTableKey_Description - константа
info.Name = LoadString(UnitTable[tableIndex], id, UnitTableKey_Name)
info.Description = LoadString(UnitTable[tableIndex], id, UnitTableKey_Description)
return info
}
либо можно массив структур UnitInfo сгенерить заранее, а в хеш-таблице хранить только позицию внутри этого массива - не нужны каждый раз аллокации
ScorpioT1000:
1000 полей у структур
это у какого объекта 1000 полей?
У юнита вроде всех больше, так там вроде сотня от силы
Кстати регулярка там будет довольно простая. Я сам писал прогу, модифицирующую j-скрипт, которая назодила там блоки функций, переменные, обращения к определенным переменным. Тут нужно всего-то найти внутри блока функции создание переменной типа UnitInfo.create(), запомнить в какую локалку это помещается, а дальше, в рамках этой функции найти все обращения к этой переменной, а именно info.Name, info.Description, и т.д. список которых ограничен, и для всех которые найдены - добавить в результирующий set<string>. Если запись идет в глобалку - искать дополнительно по всему файлу придется. Тогда в set<string> будет набор имен полей, которые надо парсить из файла карты. Ну уж парсинг сделать - dictionary<string, X> где ключ - имя поля для парсинга (Name, Description), X - структура информации достаточной для парсинга, это может быть offset внутри файла и т.д. я не разбирался как там внутри war3map.w3u храняться данные.

Отредактировано Alex_Hell, 21.02.2012 в 22:59.
Старый 21.02.2012, 22:43
prog

offline
Опыт: 32,865
Активность:
Alex_Hell, господи, а время нужное чтобы это все в память во время старта карты подгрузить ты учитываешь? А способности многоуровневые ты учитываешь?
Старый 21.02.2012, 22:56
Alex_Hell
Mapmaker 'N' Programmer
offline
Опыт: 6,885
Активность:
prog, заполнить хеш-таблицу? Очень быстро)) Ты сделай тест и провериш, нам скажеш)) Я же сказал - нужно мерять производительность, если медленно - грузить только используемые поля (см выше) и используемые объеты (юниты, предметы) - помечать отдельно saved как ты указал или как-то так
Alex_Hell добавил:
Ребят, а вы не вкурсе, в SC2 есть что-то подобное? Вроде возможности во время игры обращаться к любым полям юнитов и еще круче возможность их изменять прямо во время игры? Было бы интересно не плодить кучу предметов с разным описанием (например бонусов в зависимости от сокетов), а сделать 1 предмет, а потом во время игры сделать что-то вроде myItem.Description = myGlobalDescription + "бонус: 100 ХП". Сейчас это предполагается обходить постпроцессором, генерящим предметы на основе базового, а я пишу о возможности динамически во время игры менять все характеристики и описания
Старый 21.02.2012, 23:17
prog

offline
Опыт: 32,865
Активность:
Alex_Hell, в ск2 точно есть возможность обращаться к этим данным - оттуда и почерпнул вдохновение, насчет изменения не уверен, кажется тоже можно, но не все.
В варе ты динамически во время игры ты ничего не поменяешь. Вернее характеристики можно изменить если изначально сделать систему кастомных характеристик предметов, а вот описания предметов никак не поменять, не вмешиваясь в память игры извне.
П.С. Свою утилиту в процесс сохранения карты JNGP вклинил, файлы с данными утилите скормил, теперь надо научить ее разбирать этот формат.
Старый 21.02.2012, 23:44
ScorpioT1000
Работаем
offline
Опыт: отключен
Alex_Hell, регексп медленный, я готов написать приложение / либу на C++, которая проходит по файлу - по каждому символу - 1 раз, одна проверка (кроме совпадений), это дело 5 минут
динамически во время игры менять все характеристики и описания
нельзя нормально... ну точнее есть одна штука, контейнер - GetAbilityEffectById а в абилку можно запихать сколько угодно любых строк, через запятую O_O я это юзал, но опятьже нельзя менять
ScorpioT1000 добавил:
это у какого объекта 1000 полей?
способности многоуровневые
=)
Старый 21.02.2012, 23:48
prog

offline
Опыт: 32,865
Активность:
ScorpioT1000, я то на Java пишу и либа на C++ мне не очень поможет) но это я разленился просто - никто мне не помешает сделать все что надо и без регулярок.
Старый 22.02.2012, 00:03
prog

offline
Опыт: 32,865
Активность:
Научил утилиту читать из файла данные по объектам. Пока только отклонения от стандартных значений. Еще немного и первая дубовая версия будет готова.
Старый 23.02.2012, 00:39
J64_

offline
Опыт: 4,724
Активность:
Alex_Hell:
UnitInfo UnitInfo.create(int id)
{
integer tableIndex
UnitInfo info = info.allocate()
if (id <= 'B000')
{
tableIndex = 0
}
elseif if (id <= 'C000')
{
tableIndex = 1
}
или арифметически: tableIndex = (id - 'A000') / 100

UnitTableKey_Description - константа
info.Name = LoadString(UnitTable[tableIndex], id, UnitTableKey_Name)
info.Description = LoadString(UnitTable[tableIndex], id, UnitTableKey_Description)
return info
}
без аллокации структур:
define{
  ConvertASCII2(x) = IntegerTertiaryOp(47 < x and x < 58, x - 48, x - 55)
  Convert2ASCII(x) = IntegerTertiaryOp(0 <= x and x < 10, x + 48, x + 55)
}
struct RawcodeData_Unit{
  string aa, bb, cc;
}

int array Rawcode
int RC2HX_S

void ReadRawcode(int x){
  Rawcode[1] =      x / 0x1000000
  Rawcode[2] = ModI(x / 0x10000  , 0x100, x / 0x1000000)
  Rawcode[3] = ModI(x / 0x100    , 0x100, x / 0x10000)
  Rawcode[4] = ModI(x          , 0x100, x / 0x100)
}
// последние три числа равкода читаем как 16 СС
int RawcodeAsHex2Decx(int id){
  ReadRawcode(id)
  RC2HX_S = ConvertASCII2(Rawcode[2])
  RC2HX_S = ConvertASCII2(Rawcode[3]) + RC2HX_S * 0x10
  RC2HX_S = ConvertASCII2(Rawcode[4]) + RC2HX_S * 0x10
  return RC2HX_S
}
int array ObjectIdOffset
int ObjectIdC = 0
int GetObjectId(int raw){
  RawcodeAsHex2Decx(raw)
  
  if(ObjectIdOffset[Rawcode[1]] == null){
    ObjectIdC += 0xff // число 0xff - максимальное значение числа из последних трех цифр равкода
    ObjectIdOffset[Rawcode[1]] = ObjectIdC
  }
  // Первая буква числа может быть любым
  RC2HX_S += ObjectIdOffset[Rawcode[1]]
  
  return RC2HX_S
}
// Обращение:
"'HOFF' aa field is " + RawcodeData_Unit(GetObjectId('H0FF')).aa
...
РО:
I000
I001
...
Q009
Q00A
Q00B

...
QQ00 - тут уже не правильно выведет
алсо, как я знаю, максимальное количество хеш-таблиц 255
Старый 23.02.2012, 15:51
Alex_Hell
Mapmaker 'N' Programmer
offline
Опыт: 6,885
Активность:
Judycaster64, мне не очень ясно что этот код делает, даже комментов нет. И как это конструируется структура RawcodeData_Unit у которой aa, bb, cc из результата возврата GetObjectId('H0FF') который int?
К тому же мой вариант вполне подходящий.
На примере как может быть...
Юниты в карте такие:
A000
...
A010
...
A020
Разделение по хеш-таблицам:
первые 256 юнитов в первой таблице (от A000 до A010)
вторые 256 юнитов во второй таблице (от A011 до A020)
и т.д.
Хеш-таблицы уже заполнены значениями:
В первой таблице:
Key1 * Key2 * Value
'A000' * Hash("Name") * "Unit1"
'A000' * Hash("Description") * "UnitDesc1"
'A000' * Hash("AddInfo") * "AddInfo1"
'A001' * Hash("Name") * "Unit2"
'A001' * Hash("Description") * "UnitDesc2"
'A001' * Hash("AddInfo") * "AddInfo2"
...
и во 2й:
Key1 * Key2 * Value
'A011' * Hash("Name") * "Unit257"
'A011' * Hash("Description") * "UnitDesc257"
'A011' * Hash("AddInfo") * "AddInfo257"
'A012' * Hash("Name") * "Unit258"
'A012' * Hash("Description") * "UnitDesc258"
'A012' * Hash("AddInfo") * "AddInfo258"
...
Либо если сделать через массив структур (аллокации заранее):
Массив структур:
UnitInfo {Name = "Unit1", Description = "UnitDesc1", AddInfo = "AddInfo1"}
UnitInfo {Name = "Unit2", Description = "UnitDesc2", AddInfo = "AddInfo2"}
...
UnitInfo {Name = "Unit257", Description = "UnitDesc257", AddInfo = "AddInfo257"}
UnitInfo {Name = "Unit258", Description = "UnitDesc258", AddInfo = "AddInfo258"}
...
А в хеш-таблицах тогда:
в 1й:
Key1 * Key2 * Value (Key2 = не играет роли, Value = индекс к массиву структур)
'A000' * 0 * 0
'A001' * 0 * 1
во 2й:
Key1 * Key2 * Value
'A011' * 0 * 257
'A012' * 0 * 258
Вроде бы Value = Key1 - 'A000'?
Но в случае когда не по всем юнитам нужно сохранять данные, а только отмеченных признаком, их ID например:
A000
A005
A009
A011
A021
A031
Массив структур будет последовательно заполнен данными именно этих юнитов:
UnitInfo {Name = "Unit0", Description = "UnitDesc0", AddInfo = "AddInfo0"}
UnitInfo {Name = "Unit5", Description = "UnitDesc5", AddInfo = "AddInfo5"}
...
Если предположить что в таблице 3 юнита (для примера)...
в 1й хеш-таблице будет:
Key1 * Key2 * Value
'A000' * 0 * 0
'A005' * 0 * 1
'A009' * 0 * 2
во 2й хеш-таблице будет:
'A011' * 0 * 3
'A021' * 0 * 4
'A031' * 0 * 5
Получение данных юнита по его ID:
Hashtable[] UnitHashTable

struct UnitInfo
{
  private static UnitInfo[8190] s_UnitUnfo // заполняет прога

  // >>
  public string Name
  public string Description
  public string AddInfo
  // <<

  public static UnitInfo GetById(int id)
  {
    int tableIndex

    // в данном случае в каждой таблице по 3 юнита; эти ограничивающие ID ставит прога по
    // самому последнему ID по списку (3, 6, 9... или если 256 юнитов в таблице: 256, 512, 768)
    if (id <= 'A009')
    {
      tableIndex = 0
    }
    elseif if (id <= 'A031')
    {
      tableIndex = 1
    }
    // ...

    // если по юниту не задали инфу, а пользователь его запросил в коде
    if (not HaveStoredInteger(UnitHashTable[table_index], id, 0)) return 0

    return s_UnitUnfo[LoadInteger(UnitHashTable[table_index], id, 0)]
  }
}
Писал по памяти, возможно синтаксис или имена функций не корректны))

Отредактировано Alex_Hell, 23.02.2012 в 22:11.
Старый 23.02.2012, 21:53
ScorpioT1000
Работаем
offline
Опыт: отключен
Alex_Hell, не надо структуры, надо функции. это было бы круто если бы были плюсы или ява, но тут лучше функции, плюс в том что сижасс может их выпилить потом =) если не юзаются, а вжасс - инлайнить
хештаблицы не нужны, лучше сделать на примере XAT - 8 массивов строк по 8190 элементов, которые абстрагированы функциями доступа как 1 большой массив, а обращаться к ним через индексы
потом заполняем его подряд данными, создаем набор констант - типов полей, например
#define UNIT_NAME = 12
и функции типа
OE_LOAD('A001', UNIT_NAME) - функция обращается к определенной ячейке юнита со смещением == UNIT_NAME
Старый 23.02.2012, 22:21
Doc

offline
Опыт: 63,163
Активность:
Hashtable[] UnitHashTable
это просто омфг, зачем?
Старый 23.02.2012, 23:07
prog

offline
Опыт: 32,865
Активность:
ScorpioT1000, java читается как джава. Прочтение ява не признается как допустимое ни Sun ни Oracle.
По поводу хранения данных расскажи поподробнее, а лучше напиши код примера - я какраз дошел до генерации кода утилитой - пока пилю просто дефайны, но скоро и до базы доберусь. Учти только что данные не только строковые бывают, но и числовые и даже многострочные(хранятся то они как одна строка, но логика подсказывает что логично их распарсить для удобства обращения), не говоря уже о равкодах и списках равкодов.
Старый 23.02.2012, 23:14
ScorpioT1000
Работаем
offline
Опыт: отключен
давай тогда напишу базу, скину щас

код

Вот код, смотри всё что закомменчено "GENERATE":
» открыть код
#include "cj_types.j"

// ==================================================================
// ========================== Big Array Macro =======================
// ==================================================================

// ScorpioT1000 (C) 2012
library BigArray {

#define SIMPLE_ARRAY_LENGTH = 8191
#define BIGARRAY_ARRAY_LENGTH = 65528
#define BIGARRAY_TRAVERSAL_SEP = 200

#define BIGARRAY(VAR_TYPE, ARR_NAME, VAR_NULL_VALUE) = {

    VAR_TYPE array bigarray_##ARR_NAME##_0
    VAR_TYPE array bigarray_##ARR_NAME##_1
    VAR_TYPE array bigarray_##ARR_NAME##_2
    VAR_TYPE array bigarray_##ARR_NAME##_3
    VAR_TYPE array bigarray_##ARR_NAME##_4
    VAR_TYPE array bigarray_##ARR_NAME##_5
    VAR_TYPE array bigarray_##ARR_NAME##_6
    VAR_TYPE array bigarray_##ARR_NAME##_7
    int bigarray_##ARR_NAME##_count = 0

    void ARR_NAME##Set(int index, VAR_TYPE value) {
        int arr_num = index / SIMPLE_ARRAY_LENGTH
        int local_index = index - (arr_num * SIMPLE_ARRAY_LENGTH)
        if((index >= BIGARRAY_ARRAY_LENGTH) || (index < 0)) {
            return
        }
        
        if(arr_num < 4) { // 0-3
            if(arr_num < 2) { // 0-1
                if(arr_num == 0) { // 0
                    bigarray_##ARR_NAME##_0 [local_index] = value
                } else { // 1
                    bigarray_##ARR_NAME##_1 [local_index] = value
                }
            } else { // 2-3
                if(arr_num == 2) { // 2
                    bigarray_##ARR_NAME##_2 [local_index] = value
                } else { // 3
                    bigarray_##ARR_NAME##_3 [local_index] = value
                }
            }
        } else { // 4-7
            if(arr_num < 6) { // 4-5
                if(arr_num == 4) { // 4
                    bigarray_##ARR_NAME##_4 [local_index] = value
                } else { // 5
                    bigarray_##ARR_NAME##_5 [local_index] = value
                }
            } else { // 6-7
                if(arr_num == 6) { // 6
                    bigarray_##ARR_NAME##_6 [local_index] = value
                } else { // 7
                    bigarray_##ARR_NAME##_7 [local_index] = value
                }
            }
        }
        

        if(index >= bigarray_##ARR_NAME##_count) {
            bigarray_##ARR_NAME##_count = index+1
        }
    }
    
    
    VAR_TYPE ARR_NAME##Get(int index) {
        int arr_num = index / SIMPLE_ARRAY_LENGTH
        int local_index = index - (arr_num * SIMPLE_ARRAY_LENGTH)
        if((index >= bigarray_##ARR_NAME##_count) || (index < 0)) {
            return VAR_NULL_VALUE
        }
        
        if(arr_num < 4) { // 0-3
            if(arr_num < 2) { // 0-1
                if(arr_num == 0) { // 0
                    return bigarray_##ARR_NAME##_0 [local_index]
                } else { // 1
                    return bigarray_##ARR_NAME##_1 [local_index]
                }
            } else { // 2-3
                if(arr_num == 2) { // 2
                    return bigarray_##ARR_NAME##_2 [local_index]
                } else { // 3
                    return bigarray_##ARR_NAME##_3 [local_index]
                }
            }
        } else { // 4-7
            if(arr_num < 6) { // 4-5
                if(arr_num == 4) { // 4
                    return bigarray_##ARR_NAME##_4 [local_index]
                } else { // 5
                    return bigarray_##ARR_NAME##_5 [local_index]
                }
            } else { // 6-7
                if(arr_num == 6) { // 6
                    return bigarray_##ARR_NAME##_6 [local_index]
                } else { // 7
                    return bigarray_##ARR_NAME##_7 [local_index]
                }
            }
        }
        return VAR_NULL_VALUE
    }

} 

}


// ==================================================================
// ====================== Object Editor Loader ======================
// ==================================================================

// ScorpioT1000 (C) 2012
library OE requires BigArray {


#define OE_RETURN_ERROR_VALUE = ""


// ========================== UNIT ==========================

BIGARRAY(string,OEUnitData,null)

define {
    OEU_missileart = 0
    OEU_backSw1 = 1
    OEU_dmgpt1 = 2
    // ! GENERATE MORE data types
    OEU_COUNT = 3// the last number
}

#define OE_UNIT_START_RAWCODE = 'h000'

string OELoadUnitData(int rawcode, int data_type) {
    if(data_type >= OEU_COUNT) {
        return OE_RETURN_ERROR_VALUE
    }
    
    return OEUnitDataGet((rawcode - OE_UNIT_START_RAWCODE) * OEU_COUNT + data_type)
}

void OESaveUnitData(int rawcode, int data_type, string value) {
    OEUnitDataSet((rawcode - OE_UNIT_START_RAWCODE) * OEU_COUNT + data_type, value)
}

/*
OEUnitData structure:
[0*OEU_COUNT + 0]: h000 - OEU_missileart
[0*OEU_COUNT + 1]: h000 - OEU_backSw1
...
[1*OEU_COUNT + 0]: h001 - OEU_missileart
[1*OEU_COUNT + 1]: h001 - OEU_backSw1
...

Formula: (rawcode - OE_UNIT_START_RAWCODE) * OEU_COUNT + data_type
*/


// GENERATE DATABASE, a new function for each unit:
void OEUDatabase0() { // unit: h000
    OESaveUnitData('h000', OEU_missileart, "")
    OESaveUnitData('h000', OEU_backSw1, "0.567")
    OESaveUnitData('h000', OEU_dmgpt1, "0.433")
    // ...

}
void OEUDatabase1() { // unit: h001
    OESaveUnitData('h001', OEU_missileart, "")
    OESaveUnitData('h001', OEU_backSw1, "0.654")
    OESaveUnitData('h001', OEU_dmgpt1, "0.321")
    // ...

}

// ...


// ========================== ITEM ==========================

BIGARRAY(string,OEItemData,null)

define {
    OEI_armor = 0
    OEI_file = 1
    OEI_scale = 2
    // ! GENERATE MORE data types
    OEI_COUNT = 3 // the last number
}

#define OE_ITEM_START_RAWCODE = 'I000'

string OELoadItemData(int rawcode, int data_type) {
    if(data_type >= OEI_COUNT) {
        return OE_RETURN_ERROR_VALUE
    }
    
    return OEItemDataGet((rawcode - OE_ITEM_START_RAWCODE) * OEI_COUNT + data_type)
}

void OESaveItemData(int rawcode, int data_type, string value) {
    OEItemDataSet((rawcode - OE_ITEM_START_RAWCODE) * OEI_COUNT + data_type, value)
}


// GENERATE DATABASE, a new function for each item:
void OEDatabase0() { // unit: h000
    OESaveItemData('I000', OEI_armor, "Wood")
    OESaveItemData('I000', OEI_file, "Objects\\InventoryItems\\TreasureChest\\treasurechest.mdl")
    OESaveItemData('I000', OEI_scale, "1.00")
    // ...

}
void OEIDatabase1() { // unit: h001
    OESaveItemData('I001', OEI_armor, "Stone")
    OESaveItemData('I001', OEI_file, "Objects\\InventoryItems\\TreasureChest\\blabla.mdl")
    OESaveItemData('I001', OEI_scale, "2.00")
    // ...

}
// ...

// ========================== ABILITY ==========================

BIGARRAY(string,OEAbilityData,null)

define {
    OEA_animnames = 0
    OEA_Missileart = 1
    OEA_MissileHoming = 2 
    // ! GENERATE MORE data types
    OEA_COUNT = 3 // the last number
}

#define OE_ABILITY_START_RAWCODE = 'A000'

string OELoadAbilityData(int rawcode, int data_type) {
    if(data_type >= OEA_COUNT) {
        return OE_RETURN_ERROR_VALUE
    }
    
    return OEAbilityDataGet((rawcode - OE_ABILITY_START_RAWCODE) * OEA_COUNT + data_type)
}

void OESaveAbilityData(int rawcode, int data_type, string value) {
    OEAbilityDataSet((rawcode - OE_ABILITY_START_RAWCODE) * OEA_COUNT + data_type, value)
}


// GENERATE DATABASE, a new function for each item:
void OEADatabase0() { // unit: h000
    OESaveAbilityData('A000', OEA_animnames, "stand,fuck")
    OESaveAbilityData('A000', OEA_Missileart, "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl")
    OESaveAbilityData('A000', OEA_MissileHoming, "1")
    // ...

}
void OEADatabase1() { // unit: h001
    OESaveAbilityData('A001', OEA_animnames, "stand,fuck")
    OESaveAbilityData('A001', OEA_Missileart, "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl")
    OESaveAbilityData('A001', OEA_MissileHoming, "1")
    // ...

}
// ...

}



// ========================== INIT ==========================

void OE_Init() {
    // GENERATE executes
    ExecuteFunc("OEUDatabase0")
    ExecuteFunc("OEUDatabase1")
    // ...
    ExecuteFunc("OEIDatabase0")
    ExecuteFunc("OEIDatabase1")
    
    ExecuteFunc("OEADatabase0")
    ExecuteFunc("OEADatabase1")
    // ..........

}

// ==================================================================
// ==================================================================
// ==================================================================




// ==================================================================

// JUST TEST, REMOVE ME
function Trig_code_Actions takes nothing returns nothing
    OE_Init()
    BJDebugMsg(OELoadItemData('I001',OEI_file))

endfunction

задача программы

тоесть твоя утила должна в этом коде добавить следующее:
  1. дописать типы у юнита, также у итемов и абилок.
не забудь, что у итемов OEI, абилок - OEA
задать OEU_COUNT как число этих полей
define {
    OEU_missileart = 0
    OEU_backSw1 = 1
    OEU_dmgpt1 = 2
    // ! GENERATE MORE data types
    OEU_COUNT = 3// the last number
}
  1. Сгенерировать функции такого типа для каждого юнита, которые вызывают заполнение ячеек всех типов (зачем их несколько - спросишь ты? ответ - чтобы избежать падения поток от лимита операций)
для итемов и абил аналогично, не забудь про OEU и OEA и про суффиксы OESaveItemData
// GENERATE DATABASE, a new function for each unit:
void OEUDatabase0() { // unit: h000
    OESaveUnitData('h000', OEU_missileart, "")
    OESaveUnitData('h000', OEU_backSw1, "0.567")
    OESaveUnitData('h000', OEU_dmgpt1, "0.433")
    // ...

}
void OEUDatabase1() { // unit: h001
    OESaveUnitData('h001', OEU_missileart, "")
    OESaveUnitData('h001', OEU_backSw1, "0.654")
    OESaveUnitData('h001', OEU_dmgpt1, "0.321")
    // ...

}

// ...
  1. Наконец, создать функцию инициализации, которая вызовет все функции в новых потоках:
void OE_Init() {
    // GENERATE executes
    ExecuteFunc("OEUDatabase0")
    ExecuteFunc("OEUDatabase1")
    // ...
    ExecuteFunc("OEIDatabase0")
    ExecuteFunc("OEIDatabase1")
    
    ExecuteFunc("OEADatabase0")
    ExecuteFunc("OEADatabase1")
    // ..........

}
баффы и декорации пока не сделал, реализуй сначала это
строки предлагаю положить на пользователя, ему ведь нетрудно будет конвертить из строки в число, а вот нам рассчитвать все комбинации будет нелегко
есть еще проблема - здесь только для кастомных полей. для стандартных надо еще сделать дополнение, но сделай хотябы так, а то я потратил полтора часа уже на это =)
ScorpioT1000 добавил:
кароче я уже придумал как сделать для любого равкода, тока там надо изначально знать равкод с самым маленьким индексом, вобщем, позже добавлю одну функцию, в которую надо будет передать все стандартные равкоды перед заполнением бд, сделай это покачто

Отредактировано ScorpioT1000, 24.02.2012 в 01:29.
Старый 24.02.2012, 01:43
prog

offline
Опыт: 32,865
Активность:
ScorpioT1000, пользователю то не трудно, конечно, превратить строку в число, но как быть со случаем когда в строке записаны, например, равкоды через запятую? Парсить это на jass повеситься можно, если с проверкой валидности исходных данных. С Массивами строк в поле еще хуже.
ИМХО надо немного усложнить структуру хранения данных, но обеспечить возможность доступа к таким составным полям без геморроя.
Также у тебя не учтены многоуровневые способности, на сколько я вижу.
Т.Е. твой способ годится только для юнитов, предметов, разрушаемых объектов и бафов. Для способностей и декораций надо делать подругому.
Со стандартными равкодами я вообще не уверен стоит ли возиться на данном этапе.
Старый 24.02.2012, 02:03
ScorpioT1000
Работаем
offline
Опыт: отключен
prog, поля сделай покачто через запятую, на жассе парсить это затратно, но лучше парсить на жассе, т.к. это будет ввод лишнего измерения =) я могу предоставить просто отдельные функции типа "считать это массивом" ну как
OELoadUnitDataList(rawcode, data_type) вернет допустим какуюто сижасс структуру с функциями доступа, вобщем это щас не так важно, уверен еще будут проблемы поважнее, сделай пока это
Что касается уровней - ок, введу для абилок уровни, не проблема =)

Отредактировано ScorpioT1000, 24.02.2012 в 02:33.
Старый 24.02.2012, 02:27
prog

offline
Опыт: 32,865
Активность:
Кстати, можно же заставить WE подгрузить slk таблицы не из архива игры, правильно? значит можно в РО добавить свои поля и использовать их так как нам надо. А карте, предназначенной для запуска, этих полей и близко не будет чтобы вар на них случайно не ругнулся - все равно же делать два набора данных - для редактирования и для запуска.
Есть кандидат на использование в качестве препроцессора для описаний
FreeMarker
ссыль на документацию
Думаю, эта библиотека более чем подойдет.
Примерно так может выглядеть описание способности:
((код
Это способность ${A000.name} и она выносит мозг цели на n секунд.|n
<#list A000.levels as level>
Уровень ${level}: выносит на ${level.dur} сек.|n
</#list>
А если цель под воздействием заклинания "${A002.name}" то эффект длится в 2 раза дольше.
))
В игре это может выглядеть так:
((код
Это способность Взрыв Мозга и она выносит мозг цели на n секунд.
Уровень 1: выносит на 1 сек.
Уровень 2: выносит на 1 сек.
Уровень 3: выносит на 2 сек.
Уровень 4: выносит на 3 сек.
А если цель под воздействием заклинания "Отупение" то эффект длится в 2 раза дольше.
))
Единственная проблема - ограничение на количество символов в описании. В игре увеличить не удастся, скорее всего, а вот в РО можно попробовать - чтобы влезали шаблоны для более сложных описаний.
В базу, конечно, пойдет уже готовое описание - чтобы не нагружать jass ненужной работой.

Отредактировано prog, 24.02.2012 в 06:53.
Старый 24.02.2012, 03:37
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 09:43.