Тема: [Уголок багодела] Расширение структур OBJECTTYPE и Страниц: 1 | Прочитано 4473 раз |
bugmonster [Баги! Баги везде!]
Source
ПРОГРАММИРЫ НЕ УЧИТЫВАЛИ ЭТУ СИТУАЦИЮ
Пол: Репутация: +1337
|
|
[Уголок багодела] Расширение структур OBJECTTYPE и « от 20.09.2006 в 11:22:57 » |
|
Здравствуйте, почтенные гробокопатели и прочие интересующиеся. Представляю на суд моё начинание под кодовым названием "Уголок багодела". Уголок багодела планируется как цикл статей, посвящённых доработке исходников JA2. Этот цикл статей будет интересен тем, кто занимается правкой исходников и созданием собственных модификаций JA2. Первую статью старался писать так, что бы было понятно начинающему, однако указанное усовершенствование должно быть полезно даже для опытных модостроителей. Для чтения очень желательно знание языка С. Каждая статья построена как мануал, поэтому выполнив все описанные шаги вы получите требуемый результат, но для понимания сути изменений нужно читать и пояснения Расширение структур OBJECTTYPE и SOLDIERTYPE. 1. Что такое OBJECTTYPE и SOLDIERTYPE и зачем их "расширять"? 2. Ковыряем. 3. Что это было. 1. Что такое OBJECTTYPE и SOLDIERTYPE и зачем их "расширять"? Это две из множества структур, используемых в Джа2 для хранения информации об объектах игры. В структурах типа OBJECTTYPE хранится информация о каждом предмете, существующем в игре. Важно понимать, что если в игре есть конкретная аптечка, которую можно взять, использовать, продать, то информация о ней будет храниться в OBJECTTYPE. Там хранится, например, статус аптечки, т.е. сколько процентов "бинтов" в ней осталось. А каждый солдат, наёмник (и даже корова с вороной ) хранится в своём SOLDIERTYPE. В каждом SOLDIERTYPE есть место для информации об инвентаре солдата. Инвентарь - это массив из предметов OBJECTTYPE. Если увеличить размер структуры OBJECTTYPE, то изменится и размер структуры SOLDIERTYPE - именно поэтому в статье две этих структуры рассматриваются вместе. А зачем вообще увеличивать их размеры? Дело в том, что множество нововведений ("фич"), требуют место для хранения новых данных в этих структурах, а свободного места - нет. Например увеличение количества слотов под аттачи к оружию потребует в структуре OBJECTTYPE увеличить длину массивов UINT16 usAttachItem[MAX_ATTACHMENTS]; INT8 bAttachStatus[MAX_ATTACHMENTS]; , но разработчики не оставили в структуре OBJECTTYPE свободного места Увеличение количества "карманов" в инвентаре солдата потребует в структуре SOLDIERTYPE увеличить длину массива OBJECTTYPE inv[ NUM_INV_SLOTS ];. Здесь разработчики предусмотрели в конце структуры свободное место в виде UINT8 bFiller[ 39 ];, и его можно использовать для добавления небольших новых полей, но расширить или перенести на его место инвентарь не получится. 2. Ковыряем. А что нам мешает просто изменить OBJECTTYPE и SOLDIERTYPE, добавив в них новые поля по своему вкусу? Ничего. Все сохраняемые файлы игры, в т.ч. карты будут иметь новую структуру. Однако, загрузить существующие карты игра не сможет. Дело в том, что в файлах карт хранятся структуры OBJECTTYPE и SOLDIERTYPE (на самом деле информация о солдатах хранится в файле карты в виде структуры SOLDIERCREATE_STRUCT, но это дела не меняет). Хранятся они в "старом" виде, а игра теперь думает, что в "новом". Но мы - модостроители, зачем нам старые карты? Но ведь не все моды используют только новые карты, да и для сохранения переделанной карты в редакторе нужно сначала загрузить исходную в старом формате. Есть простое решение - при загрузке карты читать OBJECTTYPE и SOLDIERTYPE старого типа и тут же в памяти преобразовывать их в новый вид. Для начала откроем файл Tactical\Item types.h и скопипастим объявление структуры OBJECTTYPE. Старое объявление не трогая переименуем в OBJECTTYPE_OLD, а скопированное изменим по вкусу - это и будет наш новый OBJECTTYPE. В результате получится код вроде такого (избыточное цитирование не изменённого кода опущено под знаками " ...", изменённый код выделен жирным): typedef struct { UINT16 usItem; UINT8 ubNumberOfObjects; ... // attached objects UINT16 usAttachItem[MAX_ATTACHMENTS]; INT8 bAttachStatus[MAX_ATTACHMENTS]; ... } OBJECTTYPE_OLD; typedef struct { UINT16 usItem; UINT8 ubNumberOfObjects; ... // attached objects // MAX_ATTACHMENTS*4 - это неправильный способ увеличить количество аттачей, зато наглядный UINT16 usAttachItem[MAX_ATTACHMENTS*4]; INT8 bAttachStatus[MAX_ATTACHMENTS*4]; // а тут я зарезервировал 256 байт прозапас union { UINT8 bChunk[256]; }; INT8 fFlags; UINT8 ubMission; INT8 bTrap; // 1-10 exp_lvl to detect UINT8 ubImprintID; // ID of merc that item is imprinted on UINT8 ubWeight; UINT8 fUsed; // flags for whether the item is used or not } OBJECTTYPE; OBJECTTYPE на картах используется как часть двух структур - WORLDITEM и SOLDIERCREATE_STRUCT, значит нужно создать для этих структур прототипы старого размера и функции превращения (или переноса данных) из старого формата структуры в новый. Открываем файл Tactical\World Items.h и копипастим объявление структуры WORLDITEM. В неё мы не планируем ничего добавлять, но так как членом этой структуры является OBJECTTYPE, нужно создать "старую версию" WORLDITEM для загрузки карт. Ещё нужно объявить функции переноса данных для OBJECTTYPE и WORLDITEM: typedef struct { ... OBJECTTYPE o; ... } WORLDITEM; typedef struct { ... OBJECTTYPE_OLD o; ... } WORLDITEM_OLD; void RenovateObjectype(OBJECTTYPE * pNew, OBJECTTYPE_OLD * pOld); void RenovateWorldItem(WORLDITEM * pNew, WORLDITEM_OLD * pOld); Открываем файл Tactical\World Items.c и добавляем в него реализацию функций: void RenovateObjectype(OBJECTTYPE * pNew, OBJECTTYPE_OLD * pOld) { pNew->usItem = pOld->usItem; pNew->ubNumberOfObjects = pOld->ubNumberOfObjects; memcpy( &(pNew->bStatus), &(pOld->bStatus), MAX_OBJECTS_PER_SLOT); // заполняем нулями массив memset( &(pNew->usAttachItem), 0, sizeof(pNew->usAttachItem)); // копируем старый массив в начало большого нового memcpy( &(pNew->usAttachItem), &(pOld->usAttachItem), MAX_ATTACHMENTS*2 ); memset( &(pNew->bAttachStatus), 0, sizeof(pNew->bAttachStatus)); memcpy( &(pNew->bAttachStatus), &(pOld->bAttachStatus), MAX_ATTACHMENTS ); pNew->fFlags = pOld->fFlags; pNew->ubMission = pOld->ubMission; pNew->bTrap = pOld->bTrap; pNew->ubImprintID = pOld->ubImprintID; pNew->ubWeight = pOld->ubWeight; pNew->fUsed = pOld->fUsed; } void RenovateWorldItem(WORLDITEM * pNew, WORLDITEM_OLD * pOld) { pNew->fExists = pOld->fExists; pNew->sGridNo = pOld->sGridNo; pNew->ubLevel = pOld->ubLevel; RenovateObjectype( &(pNew->o), &(pOld->o) ); pNew->usFlags = pOld->usFlags; pNew->bRenderZHeightAboveLevel = pOld->bRenderZHeightAboveLevel; pNew->bVisible = pOld->bVisible; pNew->ubNonExistChance = pOld->ubNonExistChance; } Открываем файл Tactical\Soldier Create.h и делаем с SOLDIERCREATE_STRUCT то же самое. typedef struct { ... //Inventory OBJECTTYPE_OLD Inv[ NUM_INV_SLOTS ]; ... } SOLDIERCREATE_STRUCT_OLD; typedef struct { ... //Inventory OBJECTTYPE Inv[ NUM_INV_SLOTS ]; ... } SOLDIERCREATE_STRUCT; void RenovateSoldierCreateStruct(SOLDIERCREATE_STRUCT * pNew, SOLDIERCREATE_STRUCT_OLD * pOld); Открываем файл Tactical\Soldier Create.c и добавляем в него реализацию RenovateSoldierCreateStruct void RenovateSoldierCreateStruct(SOLDIERCREATE_STRUCT * pNew, SOLDIERCREATE_STRUCT_OLD * pOld) { int i; // просто копирую часть структуры до инвентаря memcpy( pNew, pOld, (char*)&(pNew->Inv)-(char*)pNew ); // конвертирую инвентарь по предметам один за одним for( i=0; i<NUM_INV_SLOTS; i++ ) RenovateObjectype( pNew->Inv+i, pOld->Inv+i ); // копирую оставшуюся после инвентаря часть структуры memcpy( &(pNew->HeadPal),&(pOld->HeadPal), sizeof(SOLDIERCREATE_STRUCT)-((char*)&(pNew->HeadPal)-(char*)pNew) ); } Теперь сама загрузка. Загрузка карты происходит в TileEngine\worlddef.c в функции BOOLEAN LoadWorld( UINT8 *puiFilename ) добавим к переменным (строка ~2630) флажок, означающий загрузку старой карты. BOOLEAN fLegacyMap; после загрузки записанного в файл размера структуры SOLDIERTYPE (строка ~2714) сравним его с используемым, и в случае несовпадения установим флажок загрузки старой карты. // Load soldier size LOADDATA( &uiSoldierSize, pBuffer, sizeof( INT32 ) ); fLegacyMap = uiSoldierSize!=sizeof(SOLDIERTYPE); добавляем данный флажок как параметр к функциям загрузки предметов (строка ~3009) LoadWorldItemsFromMap( &pBuffer, fLegacyMap ); и солдат (строка ~3062) LoadSoldiersFromMap( &pBuffer, fLegacyMap ); Теперь модифицируем сами функции. Tactical\Soldier Init List.h (строка ~25): BOOLEAN LoadSoldiersFromMap( INT8 **hBuffer, BOOLEAN fLegacyMap ); Tactical\Soldier Init List.c (строка ~279): BOOLEAN LoadSoldiersFromMap( INT8 **hBuffer, BOOLEAN fLegacyMap ) { ... if( tempBasicPlacement.fDetailedPlacement ) { //Add the static detailed placement information in the same newly created node as the basic placement. //read static detailed placement from file if( fLegacyMap ) { // загружаем старую структуру LOADDATA( &tempDetailedPlacementOld, *hBuffer, sizeof( SOLDIERCREATE_STRUCT_OLD ) ); // переконвертируем её в новую RenovateSoldierCreateStruct(&tempDetailedPlacement, &tempDetailedPlacementOld); } else { // хотя на первый взгляд скобки здесь не нужны, LOADDATA - это макрос, развертывающийся в несколько комманд LOADDATA( &tempDetailedPlacement, *hBuffer, sizeof( SOLDIERCREATE_STRUCT ) ); } //allocate memory for new static detailed placement pNode->pDetailedPlacement = (SOLDIERCREATE_STRUCT*)MemAlloc( sizeof( SOLDIERCREATE_STRUCT ) ); if( !pNode->pDetailedPlacement ) { AssertMsg( 0, "Failed to allocate memory for new detailed placement in LoadSoldiersFromMap." ); return FALSE; } ... return TRUE; } Tactical\World Items.h (строка ~43): void LoadWorldItemsFromMap( INT8 **hBuffer, BOOLEAN fLegacyMap ); Tactical\World Items.c (строка ~446): void LoadWorldItemsFromMap( INT8 **hBuffer, BOOLEAN fLegacyMap ) { ... if( gTacticalStatus.uiFlags & LOADING_SAVED_GAME && !gfEditMode ) { //The sector has already been visited. The items are saved in a different format that will be //loaded later on. So, all we need to do is skip the data entirely. if( fLegacyMap ) *hBuffer += sizeof( WORLDITEM_OLD ) * uiNumWorldItems; else *hBuffer += sizeof( WORLDITEM ) * uiNumWorldItems; return; } else for ( i = 0; i < uiNumWorldItems; i++ ) { //Add all of the items to the world indirectly through AddItemToPool, but only if the chance //associated with them succeed. if( fLegacyMap ) { LOADDATA( &dummyItemOld, *hBuffer, sizeof( WORLDITEM_OLD ) ); RenovateWorldItem(&dummyItem, &dummyItemOld ); } else { LOADDATA( &dummyItem, *hBuffer, sizeof( WORLDITEM ) ); } ... } Вот и всё. 3. Что это было. Исходников готовых не прилагаю, так как эта инструкция больше руководство к действию, чем готовое решение, т.к. сама по себе такая модификация не добавляет в игру новых возможностей. Для тех, кто не понимает как распорядиться полученным добром - в следующих статьях я (а может и кто другой) расскажу как расширить инвентарь наёмника или как сделать оружие с двумя калибрами и двумя магазинами. Хотя в структуру SOLDIERTYPE не добавлялись новые поля, это можно сделать на основе полученных данных.
|
« Изменён в : 20.09.2006 в 11:28:06 пользователем: bugmonster » |
Зарегистрирован |
Восславим же радость и мужество, Труда и науки содружество Восславим мудрую партию, Помолимся за неё.
А Пентагон в свои руки поганые, Пусть возьмёт свои доллары сраные И в ж... себе затолкает
|
|
|
Farah_Aydid [Блэк Хок Даун]
Полный псих
Доктор Джекил и мистер Хайд - кем я буду сегодня?
Пол: Репутация: +128
|
|
Re: [Уголок багодела] Расширение структур OBJECTTY « Ответ #1 от 14.11.2009 в 08:39:02 » |
|
(2009 год) Наткнулся на эту тему в поисках информации об особых функциях предметов. Конкретно, меня интересуют эффекты наркотиков, алкоголя и прочих медикаментов. В каких файлах хранится инфа для этих особых предметов? И насколько они функциональны для редактирования и создания новых предметов такого класса? Возможно ли, например, ввести зависимость от наркотиков? Возможно ли добавить абсолютно новые медикаменты с другими эффектами? Как и где вообще можно управлять настройкой этих эффектов? Ковыряюсь в обычных ХМЛ-файлах для мода 113, но простыми средствами редактора новых предметов с необходимыми эффектами создать не получается. Видимо, инфа о наркоте хранится в каком-то особом файле, потому что даже обычным дупликатом старого предмета эффекты не переносятся на новый. Наверное, должен совпадать индекс предмета, с индексом, указанным в том самом загадочном файле, который я ищу.)) ОООо! Эта инфа наверное в JSD хранится. И как же ее ковырять. О, ужас!
|
« Изменён в : 14.11.2009 в 08:46:53 пользователем: Farah_Aydid » |
Зарегистрирован |
Всех джайцев сослать в страну Африканского Рога!!! =) http://www.ja2.su/mods/Ja2v113/Farah_Aydid/JA2_113_HoA_in_progress.rar Устарело. Обнова скоро будет.
http://kunt.mybrute.com Воруй@Убивай
|
|
|
<<GEM>> [Добрый волшебник]
Прирожденный Джаец
Иногда мне дико не хватает мозгов.
Пол: Репутация: +675
|
|
Re: [Уголок багодела] Расширение структур OBJECTTY « Ответ #2 от 14.11.2009 в 18:06:11 » |
|
14.11.2009 в 08:39:02, Farah_Aydid писал(a):Эта инфа наверное в JSD хранится. |
| - не думаю. Инфа эта строго в исходниках записана. В оригинальном Джа так.
|
|
Зарегистрирован |
Модельки от меня.
|
|
|
bugmonster [Баги! Баги везде!]
Source
ПРОГРАММИРЫ НЕ УЧИТЫВАЛИ ЭТУ СИТУАЦИЮ
Пол: Репутация: +1337
|
|
Re: [Уголок багодела] Расширение структур OBJECTTY « Ответ #3 от 15.11.2009 в 06:47:26 » |
|
2Farah_Aydid: JSDшки это совсем из другой оперы, в Джа2 (в том числе и 1.13) свойства алкоголя и наркотиков жестко закодированы на номер предмета. А вообще это оффтоп, ты ошибся темой.
|
|
Зарегистрирован |
Восславим же радость и мужество, Труда и науки содружество Восславим мудрую партию, Помолимся за неё.
А Пентагон в свои руки поганые, Пусть возьмёт свои доллары сраные И в ж... себе затолкает
|
|
|
Lion [Lion. King Lion.]
Welcome to Metavira!
Пол: Репутация: +362
|
|
Re: [Уголок багодела] Расширение структур OBJECTTY « Ответ #4 от 25.03.2013 в 04:02:47 » |
|
2bugmonster: В статье подробно описана возня с переделыванием карт из старого формата в новый с клонированием структур и прочими радостями жизни. Меня больше интересует вопрос (можно, конечно, и в исходниках глянуть, но думаю, Вы знаете ответ), всегда ли в файле с картой хранятся эти структуры? Можно ли вольно править OBJECTTYPE и SOLDIERTYPE, а карты просто переносить, если на них нет ни одного персонажа и ни одного предмета? Опять же можно ли приводить карты к новым структурам методом: 1) Удалить с карты в старом формате всех людей и все предметы. 2) Открыть карту как карту в новом формате, вернуть людей и предметы?
|
|
Зарегистрирован |
|
|
|
bugmonster [Баги! Баги везде!]
Source
ПРОГРАММИРЫ НЕ УЧИТЫВАЛИ ЭТУ СИТУАЦИЮ
Пол: Репутация: +1337
|
|
Re: [Уголок багодела] Расширение структур OBJECTTY « Ответ #5 от 26.03.2013 в 01:22:27 » |
|
2Lion: Quote:Можно ли вольно править OBJECTTYPE и SOLDIERTYPE, а карты просто переносить, если на них нет ни одного персонажа и ни одного предмета? |
| Да, ЕМНИП. Quote:Опять же можно ли приводить карты к новым структурам методом: 1) Удалить с карты в старом формате всех людей и все предметы. 2) Открыть карту как карту в новом формате, вернуть людей и предметы? |
| Исходя из вышесказанного - можно. Но лучше дописать конвертацию в исходниках.
|
|
Зарегистрирован |
Восславим же радость и мужество, Труда и науки содружество Восславим мудрую партию, Помолимся за неё.
А Пентагон в свои руки поганые, Пусть возьмёт свои доллары сраные И в ж... себе затолкает
|
|
|
Lion [Lion. King Lion.]
Welcome to Metavira!
Пол: Репутация: +362
|
|
Re: [Уголок багодела] Расширение структур OBJECTTY « Ответ #6 от 26.03.2013 в 01:46:39 » |
|
26.03.2013 в 01:22:27, bugmonster писал(a):Но лучше дописать конвертацию в исходниках. |
| В каком отношении лучше? При учёте того, что на картах, о которых идёт речь, предметов и людей просто нет. Т.е. удалять никого не надо. Хотя можно и конвертацию написать.
|
|
Зарегистрирован |
|
|
|
bugmonster [Баги! Баги везде!]
Source
ПРОГРАММИРЫ НЕ УЧИТЫВАЛИ ЭТУ СИТУАЦИЮ
Пол: Репутация: +1337
|
|
Re: [Уголок багодела] Расширение структур OBJECTTY « Ответ #7 от 26.03.2013 в 02:11:14 » |
|
26.03.2013 в 01:46:39, Lion писал(a):В каком отношении лучше? При учёте того, что на картах, о которых идёт речь, предметов и людей просто нет. Т.е. удалять никого не надо. |
| Лучше в общем случае. Карты без предметов и людей это очень специфический случай.
|
|
Зарегистрирован |
Восславим же радость и мужество, Труда и науки содружество Восславим мудрую партию, Помолимся за неё.
А Пентагон в свои руки поганые, Пусть возьмёт свои доллары сраные И в ж... себе затолкает
|
|
|
Lion [Lion. King Lion.]
Welcome to Metavira!
Пол: Репутация: +362
|
|
Re: [Уголок багодела] Расширение структур OBJECTTY « Ответ #8 от 26.03.2013 в 02:46:36 » |
|
26.03.2013 в 02:11:14, bugmonster писал(a):Карты без предметов и людей это очень специфический случай. |
| Не согласен. Для определённого этапа создания проекта - вполне нормально. Какие карты - известно, а что конкретно на них будет - известно плохо, рисуется ландшафт, а положить предметы и людей - дело быстрое и нехитрое, к тому же лучше это делать на всех картах сразу. Спасибо.
|
« Изменён в : 26.03.2013 в 02:46:50 пользователем: Lion » |
Зарегистрирован |
|
|
|
MAn [Человечище!!!]
Пол: Репутация: +403
|
|
Re: [Уголок багодела] Расширение структур OBJECTTY « Ответ #9 от 26.03.2013 в 02:54:37 » |
|
Offtop:26.03.2013 в 02:46:36, Lion писал(a):а положить предметы и людей - дело быстрое и нехитрое, |
| Положить - может и нехитрое. Если положить с пробором. |
|
|
|
Зарегистрирован |
|
|
|
|