Другое С/С++ Вопрос - Ответ

kin4stat

mq-team · kin4@naebalovo.team
Всефорумный модератор
2,733
4,730
Добрый вечер, вот что из этого всего реально отвечает за смену навыков владения оружием?

1. CPed +0x72C = [byte] Навык владения оружием (0-4)

2. 0xC8AAB8 - Начало блока, куда считывается информация об оружии с меткой J (оружие ближнего боя) и $ (остальное оружие). В этом блоке 0x50 элементов по 0x70 байт в каждом. Индекс элемента высчитывается по формуле: <номер оружия> + <смещение>. Смещение определяется навыком оружия skilllevel: STD - 0, POOR - 25, PRO - 36, особое (характеристики пистолета копов) - 47. Все имена взяты из заголовка оригинального weapon.dat.

3.
  • +0x30 = [dword] Владение оружием
    • 0 - POOR //Наихудшее
    • 1 - STD //Среднее
    • 2 - PRO //Наилучшее
    • 3 - особое
  • +0x34 = [dword] statrequired. Уровень статистики, необходимый для получения текущего навыка владения оружи
В спойлере скилл локального игрока в процентах. Может быть можно обратным способом записать туда значение. https://www.blast.hk/threads/10970/post-98968
 

manukhov

Известный
125
128

loganhackerdff

Известный
868
518
Ну так там считывают, а изменять то как? Что записать? ID оружия + 0x36?
в dwAddr просто перед адресом добавь (DWORD*)
C++:
template <typename T>
void WriteMem(DWORD* dwAddr, size_t size, T value)
{
    DWORD NewProtection;
    VirtualProtect(dwAddr, size, PAGE_EXECUTE_READWRITE, &NewProtection);
    *reinterpret_cast<T*>(dwAddr) = value;
    VirtualProtect(dwAddr, size, NewProtection, &NewProtection);
}
 

kin4stat

mq-team · kin4@naebalovo.team
Всефорумный модератор
2,733
4,730
в dwAddr просто перед адресом добавь (DWORD*)
C++:
template <typename T>
void WriteMem(DWORD* dwAddr, size_t size, T value)
{
    DWORD NewProtection;
    VirtualProtect(dwAddr, size, PAGE_EXECUTE_READWRITE, &NewProtection);
    *reinterpret_cast<T*>(dwAddr) = value;
    VirtualProtect(dwAddr, size, NewProtection, &NewProtection);
}
Он экстреналы делает
 

manukhov

Известный
125
128
в dwAddr просто перед адресом добавь (DWORD*)
C++:
template <typename T>
void WriteMem(DWORD* dwAddr, size_t size, T value)
{
    DWORD NewProtection;
    VirtualProtect(dwAddr, size, PAGE_EXECUTE_READWRITE, &NewProtection);
    *reinterpret_cast<T*>(dwAddr) = value;
    VirtualProtect(dwAddr, size, NewProtection, &NewProtection);
}
ты точно этот код прикрепить хотел? Wpm для примера вполне хватит
 

Musaigen

abobusnik
Проверенный
1,585
1,309
Добрый вечер, вот что из этого всего реально отвечает за смену навыков владения оружием?

1. CPed +0x72C = [byte] Навык владения оружием (0-4)

2. 0xC8AAB8 - Начало блока, куда считывается информация об оружии с меткой J (оружие ближнего боя) и $ (остальное оружие). В этом блоке 0x50 элементов по 0x70 байт в каждом. Индекс элемента высчитывается по формуле: <номер оружия> + <смещение>. Смещение определяется навыком оружия skilllevel: STD - 0, POOR - 25, PRO - 36, особое (характеристики пистолета копов) - 47. Все имена взяты из заголовка оригинального weapon.dat.

3.
  • +0x30 = [dword] Владение оружием
    • 0 - POOR //Наихудшее
    • 1 - STD //Среднее
    • 2 - PRO //Наилучшее
    • 3 - особое
  • +0x34 = [dword] statrequired. Уровень статистики, необходимый для получения текущего навыка владения оружи
C++:
// Для internal'a
// weaponType - ID оружия.
// cSkill - сам скилл.
void CPed::SetWeaponSkill(eWeaponType weaponType, char cSkill)
{
    // Вместо eWeaponType можно и int
    reinterpret_cast<void(__thiscall*)(CPed*, eWeaponType, char)>(0x5E3C10)(this, weaponType, cSkill);
}
this можно заменить *reinterpret_cast<void**>(0xB6F5F0)
Ну и понятное дело вместо CPed* поставить void*
 
Последнее редактирование:

loganhackerdff

Известный
868
518
C++:
// Для internal'a
// weaponType - ID оружия.
// cSkill - сам скилл.
void CPed::SetWeaponSkill(eWeaponType weaponType, char cSkill)
{
    // Вместо eWeaponType можно и int
    reinterpret_cast<void(__thiscall*)(CPed*, eWeaponType, char)>(0x5E3C10, this, weaponType, cSkill);
}
this можно заменить reinterpret_cast<void*>(0xB6F5F0)
Ну и понятное дело вместо CPed* поставить void*
а почему инменно reinterept_cast а не static_cast и не простое разименование указателя?
 

kin4stat

mq-team · kin4@naebalovo.team
Всефорумный модератор
2,733
4,730
а почему инменно reinterept_cast а не static_cast и не простое разименование указателя?
Потому что reinterpret_cast буквально говорит: Видишь тут хранится float? Вот, считай что теперь это int
А static_cast пытается сохранить значение. Т.е. float 4.0f превратится в int 4, а не в миллион

И получается тебе надо взять тот же указатель, но чтобы процессор расценивал его как void*, Поэтому реинтерпрет каст

Тут более подробно распишу для тех кому интересно:
4 типа int хранится в памяти как 0x00000004, а 4 типа float хранится как 0x00008040
Если сделать reinterpret_cast 4 типа float к int, то получим 1082130432, а не как мы ожидали 4.
Static cast же сделает из 0x00008040 0x00000004
Да, я знаю что нельзя кастовать float к int, просто мне было удобно это для примера :D(Ограничение можно обойти через memcpy)
 
Последнее редактирование:

Const

Потрачен
28
54
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.

Musaigen

abobusnik
Проверенный
1,585
1,309
Нет. *reinterpret_cast<class CPed **>(0xB6F5F0). В данном случае ты сделал абсолютно бессмысленное кастование, одно и то же, что reinterpret_cast<uint32_t>(0xB6F5F0)
Я знаю что нужно именно так кастовать, только у @T4yz1e может не быть класса CPed, я и показал как нужно кастовать в этом случае.
Конечно можно ещё сделать класс пустышку, но зачем?
 

Const

Потрачен
28
54
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Я знаю что нужно именно так кастовать, только у @T4yz1e может не быть класса CPed, я и показал как нужно кастовать в этом случае.
Конечно можно ещё сделать класс пустышку, но зачем?
Ты даже в том случае написал неправильно, если использовать с void, правильно будет *reinterpret_cast<void **>(), а если написать class CPed не нужно объявлять класс-пустышку.
 
  • Нравится
Реакции: Musaigen

bab0n

Известный
95
10
3 вопроса:
1] Есть ли функция на то, имеет ли игрок у себя оружие под определённым id? lua:
hasCharGotWeapon(Ped ped, int weapon)
2] Можно ли как то делать изменение активации считывая нажатия с клавиатуры? Тип не так что id клавишы вводиться или её имя, а ты начал кнопку X, программа зарегала её id
3] Есть альтернатива на взятие ствола в руку? lua:
setCurrentCharWeapon(playerPed, id)