You are not logged in.
Огромное всем тут спасибо, для SA много чего теперь можно сделать.
Но мб кто-нибудь добудет аналогичные адреса для Vice City?=)
Мне всего лишь нужен угол поворота крышки багажника - я делаю выдвижной спойлер, всё что нужно уже есть, а вот повернуть крышку багажника не удается.
Суть в том что в скрипте я должен при нажатии кнопки заставить крышку багажника исчезнуть, и на месте её прицепить к машине "выдвижную" крышку - которая играет роль заднего спойлера. Это я уже по сути сделал: в модели изменил, чтобы багажник поворачивался во внутрь, и поворачивал его опкодом
04E1: open_and_freeze_car_trunk 0@
Таким образом крашка багажника моментально поворачивается вовнутрь, исчезая из виду, и на ее месте выдвигается спойлер.
Но никаким опкодом(напомню, речь идет о Vice City) невозможно вернуть багажник в "закрытое" состояние, поэтому единственный выход - открывать и закрывать багажник через адрес памяти.
на gtamodding.com есть оффсет для башни танка и двигателя пляжного джипа:
+0x5B0 - [DWORD] - Rhino & Fire truck Cannon angle
+0x5BB - [DWORD] - BF-Inject Rotation angle
Я пробовал на основе этого найти оффсет крышки багажника, но не смог. Подореваю, что не там ищу.
Пжс, помогите, уже около месяца бьюсь(в сумме дни)
Offline
Shag, там искать ничего не нужно. И в 3, и в ВС, и в СА по одному принципу сделано.
Из конструктора должен вызываться SetModelIndex, который заполняет место в структуре транспорта, отведённое для хранения нужных компонентов. Там и смотришь, где начинается это место в структуре.
Для того, чтобы найти Ид компонентов в этой структуре, можно просто вбить в поиск "door_lf" и найти нужный список (списков будет несколько, для каждого класса транспорта он свой).
RwFrame *__thiscall CAutomobile::SetModelIndex(CAutomobile *this, int modelId) { int i; CVehicle::SetModelIndex(this, modelId); for(i=0; i<20; i++) this->m_pCarNode[i] = 0; return CClumpModelInfo::FillFrameArray(this->m_pRwObject, this->m_pCarNode); }
Если надо добавить свой компонент. В структуру авто он записан не будет, так что надо его искать через RwObject (CEntity +0x18). Дальше надо использовать функцию, которая найдёт нужный компонент по его имени. В SA была такая функция, не знаю, есть ли в 3/ВС, но и самому её написать не очень сложно.
RwFrame * FindComponent(CVehicle *vehicle, char *name) { int data[2]; data[0] = (int)name; data[1] = 0; RwFrame *parent = vehicle->m_pRWObject->object.parent; RwFrameForAllChildren(parent, &FindComponentCB, data); return (RwFrame *)data[1]; }
int FindComponentCB(RwFrame *frame, int *data) { if ( !strcmp(data[0], RwFrameGetNodeName(frame)) ) data[1] = (int)frame; else { RwFrameForAllChildren(frame, &FindComponentCB, data); if( !data[1] ) return 1; } return 0; }
Last edited by DK22Pac (21-10-2012 12:10)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
спс, но мне не нужно добавлять компоненты, а только поворачивать имеющиеся.
Я это делаю через клео, и там к сожалению, не получится применить то, что вы написали. Как я понял, сложность только в том, чтобы найти нужный оффсет, но я наугад перетрусил практически всё(кстати при этом пару интересных адресов нашел), но нужного не нашел.
Мне просто нужно управлять углом поворота багажника, т.е. всего 1 адрес, а спойлер я сделаю скриптами
Offline
и на месте её прицепить к машине "выдвижную" крышку - которая играет роль заднего спойлера. Это я уже по сути сделал: в модели изменил, чтобы багажник поворачивался во внутрь
Так если ты редактируешь модель, почему просто не добавить в ней новый компонент - спойлер, и крутить его?
Двери и багжники в III/VC/SA контроллируются классом CDoor, он должен быть где-то в начале CAutomobile.
Вот так в гта3
struct CAutomobile : public CVehicle { CDamageManager m_sCarDamage; CDoor m_sCarDoor[6]; struct RwFrame *m_pCarNode[20]; struct CColPoint m_sWheelColPoint[4];
struct CDoor { float m_fOpenAngle; float m_fClosedAngle; BYTE m_bDirn; BYTE m_bAxis; BYTE m_bState; BYTE __padding0; float m_fAngle; float m_fPrevAngle; float m_fAngVel; struct CVector m_vPos; };
Last edited by DK22Pac (29-10-2012 22:34)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
нет, это не подойдет. Я делаю не ламбо, а Bugatti Veyron. Там спойлер состоит из 5 подвижных деталей. Поэтому работу с делалями я провожу, цепляя новый спойлер в качестве новых объектов, и передвигая/поворачивая их. Вначале(в закрытом состоянии) багажник - это и есть спойлер, но потом я опкодом
04E1: open_and_freeze_car_trunk 0@ моментально поворачиваю багажник вовнутрь, таким образом "крышка багажника" исчезает из виду и машина оказывается без спойлера. А скриптами я создаю и цепляю тот спойлер, который выдвигается и поворачивается. Для глаза это почти незаметно. А при опускании спойлера происходит поворот и перемещение объектов обратно, потом этот спойлер, состоящий из объектов исчезает(скрипт удаляет объекты), а т.к. настоящий спойлер (крышка багажника) повернута во внутрь и её не видно, мне нужно "закрыть багажник", а такого опкода нет. Возможно это трудно представить с моих слов, но поворотами компонентов нужный результат не получится, т.к. нужно еще их двигать относительно друг друга, но это уже моя проблема.
Мне нужно лишь получить возможность закрыть стандартный багажник, или найти адрес его угла поворота. Потому что разработчики забыли придумать анти-пару к опкоду 04E1: open_and_freeze_car_trunk 0@
Заранее спс
Last edited by Shag (30-10-2012 18:57)
Offline
Когда-то kenking писал о проверки стандартных компонентов категории b и a. Про двери капот и багажник уже было объяснено, а вот про лобовое стекло фары итд нет. Еще раз вспоминаю первый случай и объясняю второй.
0A97: 31@ = car 1@ struct 31@ += 0x5A0 // вот здесь начинается структура CDamageManager. 31@ += 0x9 // 0xA 0xB 0xC 0xD 0xE по этим смещениям находятся результаты состояний компонентов дверей и капота с багажником. 0A8D: 31@ = read_memory 31@ size 1 virtual_protect 0 // размер соответственно 1 байт { в переменной 31@ будет: 0 - означает, что компонент закрыт и целый 1 - ... открыт и целый 2 - ... закрыт и поврежденный 3 - ... открыт и поврежденный 4 - означает, что компонент отсутствует }
другая ситуация обстоит с другими компонентами
31@ += 0x5A0 // вот здесь начинается структура CDamageManager. 31@ += 0x14 // по этому смещению и находится результат состояний другой категории компонентов. 0A8D: 31@ = read_memory 31@ size 4 virtual_protect 0 // размер соответственно 4 байта { тут 8 разных компонент, состояния которых находятся в нижних битах каждого байта если представить 4 байта в двоичном виде, то будет выглядеть так: 00xx 00xx 00xx 00xx 00xx 00xx 00xx 00xx , где xx состояние компонента оно может принимать следующие двоичные значения 0 - означает что компонент целый 1 - ... сломан 10 - ... сломан 11 - ... отсутствует/отключена читать компоненты надо в таком порядке справо-налево: левая передняя фара (крыло) правая передняя фара (крыло) левая задняя фара (крыло) правая задняя фара (крыло) лобовое стекло передний бампер задний бампер неизвестно }
I know everything and nothing...
Offline
в переменной 31@ будет:
0 - означает, что компонент закрыт и целый
1 - ... открыт и целый
2 - ... закрыт и поврежденный
3 - ... открыт и поврежденный
4 - означает, что компонент отсутствует
Это я уже находил, но это подойдет больше для чтения, т.е. проверок, а мне нужно просто закрыть багажник, причем в Вайс Сити(для него нет никакой документации по этому поводу).
Касаемо работы с CAutomobile и CVehicle - я этого пока не умею, да и программ нужных сейчас нет, типа IDA.
Если всё так просто, может кто помочь найти нужное смещение? Нужно либо возможность поворачивать багажник, либо просто закрыть его. А всё остальное - мои проблемы
Offline
Там спойлер состоит из 5 подвижных деталей
Создать 5 таких компонентов в иерархии - проблема?
Функция из опкода 04E1 (В базе Alien'a есть основные структуры)
void __thiscall _PopBoot(CAutomobile *this) { CAutomobile *car; int status; CMatrix m; CVector vPrevPos; float rotation[3]; car = this; status = CDamageManager::GetComponnetStatus(&this->damageManager, 1); // COMPONENT_BOOT switch ( status ) { case 0: // STATE_OK case 1: // STATE_OPENED car->m_sCarDoor[1].m_fAngle = car->m_sCarDoor[1].m_fOpenAngle; CMatrix::constructor_1(&m, &car->m_pCarNode[18]->frame.modelling, 0); vPrevPos.x = m.rw.pos.x; vPrevPos.y = m.rw.pos.y; vPrevPos.z = m.rw.pos.z; rotation[0] = g_vPopBootRotation.x; rotation[1] = g_vPopBootRotation.y; rotation[2] = g_vPopBootRotation.z; rotation[car->m_sCarDoor[1].m_bAxis] = car->m_sCarDoor[1].m_fAngle; CMatrix::SetRotation(&m, rotation[0], rotation[1], rotation[2]); m.rw.pos.x = m.rw.pos.x + vPrevPos.x; m.rw.pos.y = m.rw.pos.y + vPrevPos.y; m.rw.pos.z = m.rw.pos.z + vPrevPos.z; CMatrix::UpdateRW(&m); result = CMatrix::destructor(&m); break; default: return; } return; }
Т.е. надо установить угол в классе CDoor и развернуть сам компонент (RwFrame).
Вот адреса
CDamageManager::GetComponnetStatus (метод) 0x5A9810 CMatrix::SetRotation (метод) 0x4DF240 Смещение к компоненту #18 CAutomobile +0x3DC СМещение к m_sCarDoor[1].m_fClosedAngle CAutomobile +0x2E0 СМещение к m_sCarDoor[1].m_fOpenAngle CAutomobile +0x2E4 СМещение к m_sCarDoor[1].m_bAxis CAutomobile +0x2E9 СМещение к m_sCarDoor[1].m_fAngle CAutomobile +0x2EC
Last edited by DK22Pac (31-10-2012 19:33)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
DK22Pac
спс огромное, в кредиты запишу))
А по поводу создания 5 компонентов: я стандартный то багажник не нашел, как я найду 5 новых? А ведь их не просто поворачивать надо, а еще и двигать относительно друг друга! А это еще дополнительные адреса
Offline
Дмитрий, товарищ же сказал, что не разбирается, а ты ему код exe выкладываешь
Компонент #18 в VC это, как я понял, багажник? Если да, то в скрипте его адрес будет вычисляться так (номеров опкодов не знаю, КЛЕО для VC у меня нет):
1@ = car 0@ struct 1@ += 0x3DC read memory 1@ size 4 result_to 1@ virtual_protect 0 if 1@ <> 0 // если компонент существует then // тут пишем действия
Как через один компонент иерархии получить адреса всех остальных компонентов, а также как узнать/изменить позицию/поворот компонента в мире и позицию/поворот компонента относительно компонента-родителя подробно расписано в данной теме. Правда эта информация приведена для SA, но если структура компонента (так называемая структура RwFrame) в SA и в VC одинаковая (вопрос тем, кто в курсе - одинаковые ли они?), то эту информацию можно использовать и для VC.
Offline
Shag, вот поиск компонента по имени. В игре не проверялось.
05E7: 1@ = car 0@ struct 1@ += 0x4C 05E0: 1@ = read_memory 1@ size 4 virtual_protect 0 1@ += 4 05E0: 1@ = read_memory 1@ size 4 virtual_protect 0 05F8: 4@ = var 2@ offset 05F7: 2@ = label @dummy_name offset 3@ = 0 05E1: call 0x645060 num_params 3 pop 3 4@ 0x5411E0 1@ if 3@ > 0 then // Получили результат в переменную 3@ end // -- name -- :dummy_name hex "mydummy" 00 end
Last edited by DK22Pac (05-11-2012 23:21)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Напиши пожалуйста для SA такой же код (поиск компонента по имени)
Offline
{$CLEO} wait 0 while true wait 0 if player.Defined($player_char) then if actor.Driving($player_actor) then 03C0: 0@ = actor $PLAYER_ACTOR car 0A97: 0@ = car 0@ struct 0@ += 0x18 0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0 0AC6: 1@ = label @Name offset 0AA7: call_function 0x4C5400 num_params 2 pop 2 1@ 0@ 2@ // поиск компонента if 2@ > 0 // если компонент существует, то производим действия над ним then 2@ += 0x50 0A8E: 3@ = 2@ + 0x30 // int 0A8E: 4@ = 2@ + 0x34 // int 0A8E: 5@ = 2@ + 0x38 // int 0A8D: 3@ = read_memory 3@ size 4 virtual_protect 0 0A8D: 4@ = read_memory 4@ size 4 virtual_protect 0 0A8D: 5@ = read_memory 5@ size 4 virtual_protect 0 04D5: create_corona_at 3@ 4@ 5@ radius 1.0 type 2 flare 2 RGB 0 255 0 end end end end :Name hex "boot_dummy" 00 end
Last edited by Den_spb (12-11-2012 20:10)
Offline
0AA7: call_function 0x4C5400 num_params 2 pop 2 _nodename "myname" _rwObject 0@ _store_to 1@
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Den_spb и DK22Pac, большое спасибо.
Offline
Уважаемые сриптеры, у меня несколько вопросов.
0A97: 1@ = car 0@ struct 1@ += 0x650 // правое переднее колесо 0A8D: 1@ = read_memory 1@ size 4 virtual_protect 0 if 1@ <> 0 then 1@ += 0x10 // указатель на матрицу 1@ += 48 // X-position. Суммирование в 2 этапа применено для наглядности
.
1)в данном коде матрица по смещению 0x10, это какая матрица? матрица перехода от родителя к дочернему элементу? Если так, то она должна быть 3*3, т.е. 36 байт. а у нас как минимум 60 байт. 2)X-positon - это X в какой системе координат?
в этом коде:
0A97: 1@ = car 0@ struct 1@ += 0x650 //Указатель на адрес правого переднего колеса 0A8D: 9@ = read_memory 1@ size 4 virtual_protect 0 //Адрес колеса if 9@ <> 0 then 0AA7: call_function 0x7F0990 num_params 1 pop 1 9@ 10@ end
3)10@ содержит матрицу, опять же что это за матрица? ну и аналогичный вопрос: 4)что за X координата по смещению 48 от начала матрицы, в смысле в какой системе координат?
Offline
ComponentStruct + 0x10 - матрица позиции компонента в системе координат его родителя. ComponentStruct + 0x50 - матрица позиции компонента в мировой системе координат.
Матрицы состоят из 16 чисел, по 4 байта каждое, т.е. общий размер матрицы - 64 байта.
Устройство матриц следующее:
+0 RightX +4 RightY +8 RightZ +0xC не используется +0x10 TopX +0x14 TopY +0x18 TopZ +0x1C не используется +0x20 AtX +0x24 AtY +0x28 AtZ +0x2C не используется +0x30 PosX +0x34 PosY +0x38 PosZ +0x3C не используется
Right, Top, At - единичные вектора, которые определяют углы поворота объекта (относительно родителя - в матрице +0x10, и относительно мировой системы координат - в матрице +0x50).
Если все 3 угла поворота равны нулю, то:
координаты Right - (1.0; 0.0; 0.0) координаты Top - (0.0; 1.0; 0.0) координаты At - (0.0; 0.0; 1.0)
Вектор Pos - радиус вектор, определяющий позицию объекта (в системе координат родителя - для матрицы +0x10, и в мировой системе координат - для матрицы +0x50).
Функция 0x7F0990 получает адрес матрицы позиции компонента в мире (+0x50). Можно не вызывать эту функцию, а просто прибавить 0x50 к адресу начала структуры компонента.
Offline
Большое спасибо, Den_spb, что помог расставить все на свои места, еще одно не больше уточнение: я могу задавать позицию компонента в +0x30 PosX +0x34 PosY +0x38 PosZ от матрицы позиции компонента в мире (+0x50) или надо все таки просчитывать в локальных координатах т.е. от родителя, и соответственно записывать в матрицу (+0x10). или надо и туда и туда записывать (есс-но в одну глобальные координаты, а в другую локальные посчитанные относительно родителя с нужными сдвигами/ поворотами) чтобы компонент изменил свое положение. а то по идее если меняется глобальная координата то и меняется координата расположения компонента относительно родителя. Еще раз большое спасибо) p.s. проверил запись в матрицу глобального расположения, компонент не изменил свое положение.
Last edited by tonyfull (12-02-2013 14:47)
Offline
Движок каждый раз производит перезапись значений в мировых матрицах компонентов, двигаясь от корневого компонента иерархии к компонентам самого низкого ранга.
При этом для нахождения мировой матрицы компонента-ребёнка перемножаются мировая матрица компонента-родителя и локальная матрица компонента-ребёнка. Локальную матрицу движок перезаписывает только в том случае, если нужно изменить позицию/поворот данного компонента относительно родителя.
Отсутствие эффекта при перезаписи мировых матриц компонентов в скрипте связано с очерёдностью выполнения процессов:
выполнение скриптов -> пересчёт координат -> отрисовка
То есть игровой движок пересчитывает значения в мировых матрицах компонентов после выполнения клео-скриптов, поэтому значения, записанные скриптом будут вновь переписаны. По этой же причине будет отсутствовать эффект и при перезаписи локальных матриц некоторых компонентов (например, нельзя повернуть передние колёса, а также изменить их позицию по оси z. В то же время, например, двери автомобиля можно вращать и перемещать как угодно, т.к. локальные матрицы дверей обновляются не всё время, а только во время их открытия и закрытия).
Если необходимо задать компоненту определённые глобальные координаты, то можно пересчитать глобальные координаты в локальные и записать их в локальную матрицу.
Offline
Движок каждый раз производит перезапись значений в мировых матрицах компонентов, двигаясь от корневого компонента иерархии к компонентам самого низкого ранга.
При этом для нахождения мировой матрицы компонента-ребёнка перемножаются мировая матрица компонента-родителя и локальная матрица компонента-ребёнка. Локальную матрицу движок перезаписывает только в том случае, если нужно изменить позицию/поворот данного компонента относительно родителя.
Отсутствие эффекта при перезаписи мировых матриц компонентов в скрипте связано с очерёдностью выполнения процессов:
выполнение скриптов -> пересчёт координат -> отрисовка
То есть игровой движок пересчитывает значения в мировых матрицах компонентов после выполнения клео-скриптов, поэтому значения, записанные скриптом будут вновь переписаны. По этой же причине будет отсутствовать эффект и при перезаписи локальных матриц некоторых компонентов (например, нельзя повернуть передние колёса, а также изменить их позицию по оси z. В то же время, например, двери автомобиля можно вращать и перемещать как угодно, т.к. локальные матрицы дверей обновляются не всё время, а только во время их открытия и закрытия).
Если необходимо задать компоненту определённые глобальные координаты, то можно пересчитать глобальные координаты в локальные и записать их в локальную матрицу.
Благодарствую, теперь все понятно)))
Offline
Возникли следующие вопросы:
1) Можно ли на отдельном взятом компоненте (стандартном или дополнительно добавленном) менять текстуру скриптом?
2) Если да, то возможно ли текстуру загружать из любого txd файла?
Если, кто знает, то напишите пожалуйста небольшой пример в клео.
Ещё: при установке на модель транспорта покрасочной работы (винила, скина) есть ограничение в количестве винилов. В стандартных моделях используются только 4. Можно сделать и устанавливать пятый винил - это срабатывает. Но дальнейшее увеличение количества винилов не получается. Модель при этом теряет все текстуры и становится прозрачно-чёрной. На моделях добавленных на дополнительные ID - винилы не работают. Можно ли обойти это ограничение по количеству винилов и их не работу на моделях установленных на дополнительные ID?
Заранее спасибо за ответы.
Offline
1)
{$CLEO} 0A8D: 4@ = read_memory 0xC228AC size 4 virtual_protect 0 while true wait 0 if 0AB0: key_pressed 9 then while 0AB0: key_pressed 9 wait 0 end if player.Defined(0) then if actor.Driving($3) then 0811: 0@ = actor $3 car_nosave 0A97: 0@ = car 0@ struct 0@ += 0x18 0A8D: 0@ = read_memory 0@ size 4 virtual_protect 0 // frame = GetFrameByNodeName(car->clump, "windscreen_dummy"); 0AA7: call_function 0x4C5400 num_params 2 pop 2 _nodename "windscreen_dummy" _clump 0@ _frame 1@ if 1@ <> 0 then 2@ = 0 3@ = 0 // RwFrameForAllObjects(frame, CVehicleModelInfo::GetOkAndDamagedAtomicCB, &data); 0AA5: call 0x7F1200 num_params 3 pop 3 _data 2@v _callback 0x4C7BD0 _frame 1@ if 2@ <> 0 then 2@ += 0x18 0A8D: 2@ = read_memory 2@ size 4 virtual_protect 0 // RpGeometryForAllMaterials(atomic->geometry, SetTextureCB, gTexWaterClear); 0AA5: call 0x74C790 num_params 3 pop 3 _data 4@ _callback 0x732850 _geometry 2@ // RpGeometryForAllMaterials(atomic->geometry, SetAlphaCB, 255); 0AA5: call 0x74C790 num_params 3 pop 3 _data 255 _callback 0x7323B0 _geometry 2@ end end end end end end
Сразу скажу, что такой код применит текстуру для всех созданных в игре автомобилей с такой же моделью. Сделать по-другому в CLEO, без асм-вставок практически нереально (см. старую версию ImVehFt (ImVehLM) в CLEO).
2) Да, в NewOpcodes есть такое:
0D44: 0@ = find_texture "radio_wctr" in_dictionary "rlogos" // IF and SET 0D46: 0@ = find_texture "radio_wctr" in_dictionary 1@ // IF and SET
3) 4 Id txd хранятся в CVehicleModelInfo. Их там только 4.
/*+0x2FA*/ WORD m_wRemapTxdId[4]; /*+0x302*/ WORD _padding;
Last edited by DK22Pac (30-05-2013 17:12)
Plugin-SDK https://github.com/DK22Pac/plugin-sdk
Discord-сервер по plugin-sdk и программированию в GTA
RU https://discord.gg/QEesDGb
ENG https://discord.gg/zaVqFQv
Offline
Спасибо большое.
Выше было сказано, что по смещению +172 от компонента записано название этого компонента.
Вопрос: можно ли переписать это значение произвольным названием так, чтобы это изменение касалось только конкретного транспорта (например, только авто игрока), а не для всего транспорта этой модели?
Offline