Модификация игры ASM/C++ Часть 5. - Форум администраторов игровых серверов
Форум администраторов игровых серверов StormWall - Защита от DDos атак
Регистрация Мнения Справка Пользователи Календарь Все разделы прочитаны
Вернуться   Форум администраторов игровых серверов > Полезное / Common > Программирование / Programming

Программирование / Programming
Ищете помощи в написании программы, есть сложность в выполнении задания (в институте и т.д.), пожалуйста, спросите у нас в данном форуме и мы обязательно вам поможем. При поддержке: Рейтинг серверов самых популярных online-игр

Ответ
Опции темы
Непрочитано 28.07.2016, 20:28   #1
Аватар для VOLKyiv
Пользователь

Автор темы (Топик Стартер) Модификация игры ASM/C++ Часть 5.

Всем, привет!
В предыдущих частях мы подготовили нашу DLL и она уже может создавать солнце
Но нам нужно сделать конструктор и деструктор нашего объекта который создает солнце.

Для этого найдем конструктор, и перенесем инициализацию из функции sub_40D840 в настоящий конструктор.
На самом деле это функция другого класса, в которой инициализируеться наш объект.
К примеру это выглядит вот так

 
int __thiscall sub_4528B0(_DWORD *this)
{
  v1 = this;
  sub_452640((int)this);
  v2 = operator new(0x57D8u);
  if ( v2 )
    v3 = sub_40A3C0(v1, (int)v2);
  else
    v3 = 0;
  v4 = v1[49];
  v5 = v1[48];
  v1[538] = v3;
  (*(void (__thiscall **)(int, _DWORD, _DWORD, int, int))(*(_DWORD *)v3 + 160))(v3, 0, 0, v5, v4);
  (*(void (__stdcall **)(_DWORD))(*(_DWORD *)v1[200] + 12))(v1[538]);
  (*(void (__stdcall **)(_DWORD))(*(_DWORD *)v1[200] + 48))(v1[538]);
 
  return (*(int (__stdcall **)(_DWORD))(*(_DWORD *)v1[200] + 32))(v1[538]);
}
 
class FirstClass
{
	/* .... */
	/* 0A82 */ Creator* obj;
	/* 0A86 */
public:
	void func2(Creator*){};
	void func3(Creator*){};
	void func4(Creator*){};
 
	void InitObj()
	{
		obj = new Creator;
		obj->func1(0, 0, v5, v4);
 
		func2(obj);
		func3(obj);
		func4(obj);
	}
};
 
Code: C++
И нам нужно перехватить конструктор вот этот

sub_40A3C0(v1, (int)v2);

Реализуем это в DLL.

 
LPVOID __fastcall Creator::Constructor(LPVOID lpPtr, LPVOID /* edx */, Creator* pCreator)
{
	typedef Creator*(__thiscall *t)(LPVOID, Creator*);
	t f = (t)0x0040A3C0;
 
	g_Creator = pCreator;
 
	Creator* pReturn = f(lpPtr, pCreator);
	new (&pCreator->objCreatorEx) CreatorEx;
 
	return pReturn;
}
 
Code: C++
Несмотря на то что используется соглашение о вызове __thiscall, я использую __fastcall по одной довольно тупой причине
Когда статической функции указать соглашение о вызове __thiscall, она подсвечивается как ошибка, что мне не нравится но при этом код компилируется
Но я люблю когда в коде нет красных полос

При __thiscall первый аргумент передается функции с помощью регистра ECX, все остальное через стек.
А __fastcall два первых аргумента передаются через регистры это тот же ECX, и еще EDX, все остальное через стек.
Если посмотреть у меня в коде EDX просто не используется.

Теперь реализуем деструктор.
 
void *__thiscall sub_40AF10(void *this, char a2)
{
  void *v2; // esi@1
 
  v2 = this;
  sub_40AF40((int)this);
  if ( a2 & 1 )
    operator delete(v2);
  return v2;
}
 
Code: C++
Тоже самое как и с конструктором.
 
Creator* __fastcall Creator::Destructor(Creator* pCreator, LPVOID /* edx */, bool bIsMemoryFreeUsed)
{
	if (g_Creator == pCreator)
		g_Creator = NULL;
 
	pCreator->objCreatorEx.~CreatorEx();
 
	typedef Creator*(__thiscall *t)(Creator*, bool);
	t f = (t)0x0040AF10;
	return f(pCreator, bIsMemoryFreeUsed);
}
Code: C++
Так же я еще добавил функцию рандома.
 
int __cdecl Creator::GameRandom(int nRange)
{
	typedef unsigned int(__cdecl *t)(int);
	t f = (t)0x005FF2A0;
	return f(nRange);
}
Code: C++
А функция void CreateSun(int a2, int a3, int a4, int a5);
Изменилась на
 
enum ItemType : long {
	Sun25 = 4, Sun15, Sun50
};
enum ItemSpeed : long {
	NORMAL = 0, SLOW
};
void CreateItem(int posX, int posY, ItemType item, ItemSpeed speed);
Code: C++
Вот функция которая создает солнце, и она же сразу же помещает его в массив

Показать код:
Свернуть ↑Развернуть ↓


я очень долго пытался понять что это за функция, предполагал что это std::array<CSun, 0x400>. Но больше всего это std::map<const char*, void*>;

Вот так место в памяти выделяется
Показать код:
Свернуть ↑Развернуть ↓


Знаю точно что v1 = *(_DWORD *)(a1 + 0xC); номер места в памяти где будет расположен следующий элемент, ++*(_DWORD *)(a1 + 0x10); количество итемов на текущий момент, v2 = *(_DWORD *)(a1 + 4); максимальное количество итемов(которое было)
Предположительно массив вот такой
 
struct Item
{
	/* 0000 */ unsigned long __uUnkValue0000[54];
	/* 00D8 */
};
 
struct ArrayItems
{
	/* 0000 */ Item* arrSuns;
	/* 0004 */ unsigned long dwMaxCount;
	/* 0008 */ unsigned long dwCapacity;
	/* 000C */ unsigned long dwNextPosition;
	/* 0010 */ unsigned long dwCount;
	/* 0014 */ char* szName = "coins";
	/* 0018 */
 
	ArraySuns()
	{
		dwCapacity = 0x400;
		dwCount = 0xDF69; // Не понимаю почему
		dwMaxCount = 0;
		dwNextPosition = 0;
 
		arrSuns = new Item[0x400];
	}
 
	~ArraySuns()
	{
		delete[] arrSuns;
	}
};
Code: C++
Но нам интересен не сам массив, а то какой элемент создается, в нашем случае это Item
Мне удалось понять некоторые переменные внутри него.

Показать код:
Свернуть ↑Развернуть ↓


Теперь попробуем перехватить конструктор создания предмета. Можно перехватить вот здесь на моменте выделения памяти int __usercall sub_420D90@<eax>(int a1@<edi>)
Но это не конструктор, и мы не сможем поменять тогда значения на свои. А лишь получить адрес на объект.
Вот настоящий конструктор int __userpurge sub_432C60@<eax>(int a1@<eax>, int a2@<ecx>, Item* pItem, signed int X, signed int Y)
Обратите внимание на соглашение о вызове, это так же последствия оптимизации. Через EAX, передаётся тип предмета. А через ECX скорость движения нашего предмета.
Единственное что можно тут сделать так это написать функцию naked. Смотрим на код

Показать код:
Свернуть ↑Развернуть ↓


Записываем свой naked

WriteInstructionJmp(0x0040F443, (UINT)ItemNakedConstructor);

Теперь напишем функцию где будем отслеживать нажатие кнопки F5, после чего будем создавать солнце

 
DWORD WINAPI ThreadProc(LPVOID lpPtr)
{
	while (true)
	{
		if (::GetAsyncKeyState(VK_F5) != 0)
		{
			if (g_Creator)
			{
				::Sleep(50);
 
				g_Creator->objCreatorEx.PushSun();
			}
		}
	}
 
	return 0;
}
 
Code: C++
Попробуем скомпилировать и запустить

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

Видео

Но таким способом мы не можем сделать например следующее, если нам нужно подобрать когда солнце будет на земле.
Поэтому я буду в следующей части показывать как сделать это с помощью функции.

Так же у предмета есть функция которая возвращает время сколько предмет будет валяться на полу.

unsigned int Item::GetMaxWaitTime(void)
{
	typedef unsigned int(__thiscall *t)(Item*);
	t f = (t)0x00435DA0;
	return f(this);
}
Code: C++
Тем самым мы можем сделать так чтобы солнце пропадало сразу же после того как коснётся земли.
Сделать это можно вот так в конструкторе:

pItem->dwTimeWait = pItem->GetMaxWaitTime();

Жду ваши вопросы

Так же сделал репозиторий с исходным кодом проекта.
GitHub

Если нужен исходник:
PlantsVsZombies.rar

1 часть
2 часть
3 часть
4 часть

Пересмотрел все возможные предметы, начиная от 7, лень было переименовывать
Посмотреть код:
Свернуть ↑Развернуть ↓

Последний раз редактировалось VOLKyiv; 29.07.2016 в 02:16. Причина: Добавил полные перечисления
VOLKyiv вне форума Ответить с цитированием
Сказали спасибо:
Непрочитано 28.07.2016, 20:47   #2
Пользователь

По умолчанию Re: Модификация игры ASM/C++ Часть 5.

Молодец, стараешься, давненько тут ничего толкового не было.
__________________
https://sites.google.com/site/l2clientdev/ - мой небольшой сборник.
Emperor вне форума Ответить с цитированием
Непрочитано 28.07.2016, 20:56   #3
Изгнанные

По умолчанию Re: Модификация игры ASM/C++ Часть 5.

Было бы веселее если бы ты смог это повторить на движке L2, Там есть похожие фичи - регулируемые только движком игры, было бы больше интересующих голов !

Я как то пытался в C3, найти обработчик тулбар-шортактов , но меня хватило лишь на инвентарь
Было
Стало

и
Текстуру шортактов сломал, вместе с кнопками.



И чето как то бросил я
luslighter вне форума Ответить с цитированием
Непрочитано 28.07.2016, 21:01   #4
Аватар для VOLKyiv
Пользователь

Автор темы (Топик Стартер) Re: Модификация игры ASM/C++ Часть 5.

Цитата:
Сообщение от luslighter Посмотреть сообщение
тулбар-шортактов
Это внизу панель?
VOLKyiv вне форума Ответить с цитированием
Непрочитано 28.07.2016, 21:02   #5
Изгнанные

По умолчанию Re: Модификация игры ASM/C++ Часть 5.

Цитата:
Сообщение от VOLKyiv Посмотреть сообщение
Это внизу панель?
Она самая !
P.S.
Описание менющек кнопок и прочего, построено на каких то стандартных решениях от майков ,с использованием XML !
luslighter вне форума Ответить с цитированием
Непрочитано 28.07.2016, 21:12   #6
Аватар для VOLKyiv
Пользователь

Автор темы (Топик Стартер) Re: Модификация игры ASM/C++ Часть 5.

Цитата:
Сообщение от luslighter Посмотреть сообщение
Она самая !
P.S.
Описание менющек кнопок и прочего, построено на каких то стандартных решениях от майков ,с использованием XML !
ну мне код смотреть надо, но больше всего там что-то вроде таблицы указателей на функцию.

 
typedef void(__cdecl *fPtr)(void);
 
struct Table
{
       fPtr arr_fnc[10];
};
 
Code: C++
VOLKyiv вне форума Ответить с цитированием
Непрочитано 28.07.2016, 21:32   #7
Изгнанные

По умолчанию Re: Модификация игры ASM/C++ Часть 5.

Цитата:
Сообщение от VOLKyiv Посмотреть сообщение
ну мне код смотреть надо, но больше всего там что-то вроде таблицы указателей на функцию.

 
typedef void(__cdecl *fPtr)(void);
 
struct Table
{
       fPtr arr_fnc[10];
};
 
Code: C++
Так то не просто XML, А уже скомпиленный XML с CPP, не помню точно как это называется, но раньше это юзали для построения GUI в 2000-ых.
luslighter вне форума Ответить с цитированием
Непрочитано 28.07.2016, 21:57   #8
Аватар для VOLKyiv
Пользователь

Автор темы (Топик Стартер) Re: Модификация игры ASM/C++ Часть 5.

Цитата:
Сообщение от luslighter Посмотреть сообщение
Так то не просто XML, А уже скомпиленный XML с CPP, не помню точно как это называется, но раньше это юзали для построения GUI в 2000-ых.
Без кода бессилен

Добавлено через 20 минут
Для правильного подбора предмета добавил функцию, чтобы не писать вот так:

pItem->nIsPickUp = TRUE;
Code: C++
что есть не правильно, вот собственно функция:

void Item::PickUp(void)
{
	typedef void(__thiscall *t)(Item*);
	t f = (t)0x00434DC0;
	f(this);
}
Code: C++

Последний раз редактировалось VOLKyiv; 28.07.2016 в 22:19. Причина: Добавлено сообщение
VOLKyiv вне форума Ответить с цитированием
Ответ

Метки
модификация игры, создание чита


Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 
Опции темы

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

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Модификация игры ASM/C++ Часть 4. VOLKyiv Программирование / Programming 7 28.07.2016 01:50
Модификация игры ASM/C++ Часть 3. VOLKyiv Программирование / Programming 0 27.07.2016 14:22
Модификация игры ASM/C++ Часть 2. VOLKyiv Программирование / Programming 0 27.07.2016 14:04
Модификация игры ASM/C++ Часть 1. VOLKyiv Программирование / Programming 0 27.07.2016 13:59
Визуальная часть игры Ajax52 Документация 5 04.01.2012 21:10


© 2007–2020 «Форум администраторов игровых серверов»
Защита сайта от DDoS атак — StormWall
Работает на Булке неизвестной версии с переводом от zCarot
Текущее время: 08:29. Часовой пояс GMT +3.

Вверх