Jump to content

Share GF TO C4 AI COMPILER :D


Recommended Posts

Here is a modified GF compiler, which compiles AIs to run on C4-based servers.

 

https://l2servers.com.ar/Compilador_GFIL_TO_C6.rar


PD: The 2020 AI Leak can also be downgraded to C4. 🤣

Edited by ViTTus
Link to comment
Share on other sites

28 minutes ago, zconll said:

This is nice share, if compare with olds Sauron's compiler (full bugs and wrong offsets), but you have missing one function used in c4.

 

"GetClosestPositionList"

ok, later I will publish a new version with the GetClosestPositionList function.

thanks for the heads up.

anything else that is missing or failed let me know.

Link to comment
Share on other sites

1 hour ago, zconll said:

This is nice share, if compare with olds Sauron's compiler (full bugs and wrong offsets), but you have missing one function used in c4.

 

"GetClosestPositionList"

I just checked, and the GetCloestPositionList function is found.

gf= 235209100

c4 =184877443
    functions.insert(std::make_pair(235209100, 184877443)); // GetCloestPositionList


or is there a difference of gg vs. myself?

Edited by ViTTus
Link to comment
Share on other sites

 

 

I found one critical bug when use "PSTATE_XXX" constants with next variable "myself.p_state".

Here one example:

"myself.p_state != PSTATE_ATTACK"

when compile, i have next result:

 

	push_event	//  myself
	push_const 704
	add
	fetch_i
	push_const 280
	add
	fetch_i4
	push_const 547427735455137795
	not_equal

 

instead

 

	push_event	//  myself
	push_const 704
	add
	fetch_i
	push_const 280
	add
	fetch_i4
	push_const 3
	not_equal

 

"PSTATE_ATTACK" constant value is 3 in this case, for more information abouts values for different "PSTATE_XXX", check "compiler.cpp", there is defined all constants with his values.

 

These constant is defined inside compiler, so they aren't taken from "manual.pch".

Edited by zconll
Link to comment
Share on other sites

On 8/4/2022 at 5:05 PM, zconll said:

 

 

I found one critical bug when use "PSTATE_XXX" constants with next variable "myself.p_state".

Here one example:

"myself.p_state != PSTATE_ATTACK"

when compile, i have next result:

 

	push_event	//  myself
	push_const 704
	add
	fetch_i
	push_const 280
	add
	fetch_i4
	push_const 547427735455137795
	not_equal

 

instead

 

	push_event	//  myself
	push_const 704
	add
	fetch_i
	push_const 280
	add
	fetch_i4
	push_const 3
	not_equal

 

"PSTATE_ATTACK" constant value is 3 in this case, for more information abouts values for different "PSTATE_XXX", check "compiler.cpp", there is defined all constants with his values.

 

These constant is defined inside compiler, so they aren't taken from "manual.pch".


they are declared well, how strange that this problem is occurring... I will continue investigating what could it be.


#include <NPCd/Compiler.h>
#include <Common/Utils.h>
#include <Common/CLog.h>
#include <vector>
#include <fstream>
#include <iostream>
#include <sstream>
#include "tchar.h"

std::wstring Compiler::exeFilename;
std::string Compiler::filename;
bool Compiler::close = false;
bool Compiler::closeOnError = false;


TCHAR   wScriptPath[260];

TCHAR   aScriptFstringT[260];

TCHAR   aScriptCategory[260];
TCHAR   aScriptCategory2[260];




void Compiler::Init()
{
	bool path_custom =false;
	int argc;
	wchar_t **argv;
	argv = CommandLineToArgvW(GetCommandLineW(), &argc);
	if (!argv) {
		MessageBox(0, L"Couldn't parse command line arguments (CommandLineToArgvW failed)", L"Error", 0);
		exit(0);
	}
	std::vector<std::wstring> args;
	for (size_t i = 0; i < argc; ++i) {
		args.push_back(std::wstring(argv[i]));
	}
	LocalFree(argv);

	exeFilename = args[0];
	if (args.size() > 1) {
		for (size_t i = 1; i < args.size(); ++i) {
			if (args[i] == L"-c" || args[i] == L"--close") {
				close = true;
			} else if (args[i] == L"-e" || args[i] == L"--close-on-error") {
				closeOnError = true;
			} else if (filename.empty()) {
				filename = Narrow(args[i]);
			} else if (args[i] == L"-p") {
				path_custom = true;
			} else if (path_custom) {
				std::string patch  = Narrow(args[i]);
				std::wstring value(patch.begin(), patch.end());

				const WCHAR * value2 = value.c_str();

				lstrcat(wScriptPath, value2);

				lstrcat(aScriptFstringT, wScriptPath);
				lstrcat(aScriptFstringT, L"fstring.txt");

				lstrcat(aScriptCategory, wScriptPath);
				lstrcat(aScriptCategory, L"category_pch.txt");

				lstrcat(aScriptCategory2, wScriptPath);
				lstrcat(aScriptCategory2, L"categorydata.txt");

			}
			else {
				wchar_t buffer[4096];
				if (args[0].size() < 2048) {
					wsprintf(buffer, L"Usage:\r\n%s [-c|--close] [-e|--close-on-error] [FILENAME]", exeFilename.c_str());
				} else {
					wsprintf(buffer, L"Usage:\r\n%s... [-c|--close] [-e|--close-on-error] [FILENAME]", exeFilename.substr(0, 2048).c_str());
				}
				MessageBox(0, buffer, L"Invalid arguments", 0);
				exit(0);
			}

			if (path_custom)
			{
				WriteRelativeAddress(0x418CC2, 3, &wScriptPath,0);					//		..\\1cript
				WriteRelativeAddress(0x475993, 3, &aScriptFstringT,0);				//		../1cript/fstring.txt
				WriteRelativeAddress(0x419511, 3, &aScriptCategory,0);				//		..\Script\category_pch.txt
				WriteRelativeAddress(0x418CD8, 3, &aScriptCategory2,0);				//		..\Script\category_pch.txt

//				lstrcat(wScriptPath, L"..\\\\1cript\\\\");
//				lstrcat(aScriptFstringT, L"../1cript/fstring.txt");
//				lstrcat(aScriptCategory, L"../1cript/category_pch.txt");
//				lstrcat(aScriptCategory2, L"..\\1cript\\categorydata.txt");
			}




//Sleep(30000);







		}
	}
	if (filename.empty()) {
		return;
	}
	WriteInstructionCall(0x55A890 + 0x185, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x55A890 + 0x6A2, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5BB4D0 + 0x495, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5BB4D0 + 0x505, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5BB4D0 + 0x685, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5BC0C0 + 0x1C, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5BE07C + 0x162, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5BE07C + 0x18C, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5BE234 + 0x6D, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x818, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x92F, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0xBD2, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x1552, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x1AF5, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x1BA5, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x1C2D, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x1CB8, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x1EA3, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x20E0, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x2306, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x2408, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x260A, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x283A, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x28B6, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x29A5, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x2A2A, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x2B7F, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x2C6A, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x2D22, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x2FF6, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x30A5, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x3276, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x335E, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x3446, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x3520, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x38E1, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x39CB, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x3C9F, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x3DF3, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x3EF5, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x403D, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x40E2, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x4340, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x43E5, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x4542, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x4627, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x46D2, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x497C, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x49DB, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x4A69, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x4BA2, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x4EA1, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x4F37, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x5017, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x50CA, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x5366, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x53C4, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x5531, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x5C3AC8 + 0x558F, reinterpret_cast<UINT32>(LogError));
	WriteInstructionCall(0x54817C, reinterpret_cast<UINT32>(Compile));
	WriteInstructionJmp(0x42B140, reinterpret_cast<UINT32>(exit));
	WriteMemoryBYTES(0x665D40, L"Global\\CONSOLE_LOG_NASC", 50);
	WriteInstructionJmp(0x475826, 0x475846);
	WriteAddress(0x5BE2EC + 3, 0x665030);
	WriteMemoryBYTES(0x448108, "\x48\x31\xC0\xC3", 4);
	WriteMemoryBYTES(0x44838C, "\x48\x31\xC0\xC3", 4);
	WriteMemoryBYTES(0x482A60, "\x48\x31\xC0\xC3", 4);
	WriteMemoryBYTES(0x55C82C, "\x48\x31\xC0\xC3", 4);
	WriteMemoryBYTES(0x596998, "\x48\x31\xC0\xC3", 4);
	WriteMemoryBYTES(0x596A28, "\x48\x31\xC0\xC3", 4);
	WriteMemoryBYTES(0x596AB8, "\x48\x31\xC0\xC3", 4);
	WriteMemoryBYTES(0x596B58, "\x48\x31\xC0\xC3", 4);
	WriteMemoryBYTES(0x596BE8, "\x48\x31\xC0\xC3", 4);
	WriteMemoryBYTES(0x596C88, "\x48\x31\xC0\xC3", 4);
	NOPMemory(0x5BE2F3, 5);
	NOPMemory(0x5B9EF7, 5);
	NOPMemory(0x5B9F39, 5);
	NOPMemory(0x474D73, 5);
	NOPMemory(0x474D8B, 5);
	NOPMemory(0x4759DF, 5);
	NOPMemory(0x41C7AA, 5);
	WriteInstructionCall(0x449435, 0x5E9210);




}

int Compiler::LogError(void*, const wchar_t* format, ...)
{
	va_list va;
    va_start(va, format);
	CLog::AddV(CLog::Red, format, va);
	vwprintf(format, va);
    va_end(va);
	return 1;
}

void Compiler::Compile()
{
	std::string outputFilename = filename + ".obj";

	size_t pos = filename.rfind(".");
	if (pos != std::string::npos) {
		outputFilename = filename.substr(0, pos) + ".obj";
	}

	std::wstring wfilename = Widen(filename);
	std::wstring woutputFilename = Widen(outputFilename);

	CLog::Add(CLog::Blue, L" ");
	CLog::Add(CLog::Blue, L"Going to compile %s to %s", wfilename.c_str(), woutputFilename.c_str());
	CLog::Add(CLog::Blue, L" ");

	if (!std::wifstream(filename.c_str())) {
		CLog::Add(CLog::Red, L"Can't open input file %s", wfilename.c_str());
		Done(false);
	}

	*reinterpret_cast<int*>(0x37886B8) = 1; // enable logging

	Parser parser;
	reinterpret_cast<void*(*)(void*)>(0x5C9980)(&parser); // construct parser

	reinterpret_cast<void(*)(UINT64, UINT64, FILE*)>(0x55A890)(0x36E58D0, (DWORD)&wScriptPath, 0); // load pch db

	// this is how we can add @variables
	// reinterpret_cast<void(*)(UINT64, const wchar_t*, int)>(0x55B18C)(0x36E58D0, L"variable", 123);

	InputFile inputFile;
	reinterpret_cast<void(*)(InputFile*, const char*, int, int)>(0x4086F8)(&inputFile, filename.c_str(), 1, 1); // open input file

	if (inputFile.something2[inputFile.something1] & 6) { // check input file OK
		CLog::Add(CLog::Red, L"Can't open input file!");
		Done(false);
	}

	CLog::Add(CLog::Blue, L"Creating parser...");

	if (!reinterpret_cast<bool(*)(Parser*, const wchar_t*)>(0x5BE2B4)(&parser, wfilename.c_str())) { // give file to parser
		CLog::Add(CLog::Red, L"Failed to create parser");
		Done(false);
	}

	CLog::Add(CLog::Blue, L"Registering constants...");

	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_IDLE", 0);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_MOVE_AROUND", 1);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_DO_NOTHING", 2);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_ATTACK", 3);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_CHASE", 4);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_FLEE", 5);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_GET_ITEM", 6);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_FOLLOW", 7);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_DECAYING", 8);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_MOVE_TO_WAY_POINT", 9);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_USE_SKILL", 10);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_MOVE_TO", 11);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_EFFECT_ACTION", 12);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_PET_DEFAULT", 13);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_MOVE_TO_TARGET", 14);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PSTATE_MOVE_SUPERPOINT", 15);



	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"MSTATE_NORMAL", 0);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"MSTATE_BERSERK", 1);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"MS_SILENCE", 2);

	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"FRIEND", 0);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"SAME_PARTY", 1);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"SAME_BLOODPLEDGE", 2);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"PC", 3);
	reinterpret_cast<void(*)(unsigned char*, const wchar_t*, int)>(0x55B18C)(&parser.padding[0x1C8], L"NPC", 4);

	CLog::Add(CLog::Blue, L"Creating output file...");

	reinterpret_cast<void(*)(const char*)>(0x419D84)(outputFilename.c_str()); // open output


	reinterpret_cast<void(*)(int, int, int, int, int, int)>(0x419E40)( // write header
		sizeof(void*), 427, 408, 235, 125, 0);

	*reinterpret_cast<UINT32*>(reinterpret_cast<char*>(&parser) + 0x110) = 4; // mode?

	CLog::Add(CLog::Blue, L"Compiling...");

	bool error = reinterpret_cast<UINT32(*)(Parser*)>(0x5D7F70)(&parser); // compile
	int errors = *reinterpret_cast<UINT32*>(0x37886C0); // get error count

	reinterpret_cast<void(*)()>(0x419F00)(); // close output file

	if (error || errors) {
		CLog::Add(CLog::Red, L"Compilation failed, error count = %d", errors);
		Done(false);
	} else {
		CLog::Add(CLog::Blue, L"Compilation done");
	}

	Done(true);
}

void Compiler::Done(bool status)
{
	if (close && status) {
		exit(0);
	}
	if (closeOnError && !status) {
		exit(1);
	}
	for (;;) {
		Sleep(100);
	}
}

 

Link to comment
Share on other sites

the majority in mcx voted for me to leave the forum. That's why I won't make any more posts. and this project. I will do it privately... you should thank all those people who voted for me to leave here... greetings.

 

Celestine. You can close the topic if you want.

Link to comment
Share on other sites

Sad hearr project will be closed, I did some tests and I found some critical bugs, so compiler can not be used to compile complete AI since it needs manual repair of the compiled code.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share



  • Posts

    • Ты вообще понимаешь свою ущербность с того что ты несешь? Ты же был дауном и крысой которая шарит чужой продукт так и остался. А все потому что как раз знания ПТУ не позволяют создать что-то свое. По этому ты юзер по жизни, ты будешь использовать только чужое, а создать что-то свое не хватает знаний. Я закончил магистратуру, по защите сетей. И знаний куда больше чем у такого орка как ты. Понимаешь в чем суть, человеку в оркостане бессмысленно объяснять что он подвергся пропаганде и стал орком. Почему? Да потому что человек который умеет мыслить не даст себе подвергнутся пропаганде не когда, не будет слушать бред а будет искать факты не с открытых источников а непосредственно со свидетелей в живую. И когда сопоставит все факты где говорят правду а где пропаганда, будет уже доверять проверенным источникам. Так вот итог: у вас все говорят что не было рф на донбасе 2014-го года и там была гражданская война. Но почему то когда тебя тыкают носом в отчеты ОБСЕ ты как-то закрываешь глаза и увиливаешь от ответа. Так кто тут трус? По этому сначала ответь на все вопросы которые я привел постами выше, чтоб иметь возможность о чем-то конструктивно общаться и отстаивать свою точку зрения, либо слейся и будь обсосанным по жизни орком, не забудь своего бойфренда хотаку за собой прихватить. Как говорится два дибила это сила а два долбоеба это руЦкая империя.
    • Sad hearr project will be closed, I did some tests and I found some critical bugs, so compiler can not be used to compile complete AI since it needs manual repair of the compiled code.
    • What's the point to keep lineage 2 alone in a whole forum? you could have more imagination of evolving the MxC Community instead of keep it alive for one game only.... If you do so do you think that will have more activity like in the past? The traffic you've got right now it will be the same and worst even after the changes you're gonna make(I mean for the l2 section only idea).... Add more game boards and categories with discussions and stuff into them to have more traffic if you want to make MxC Great again....
    • the majority in mcx voted for me to leave the forum. That's why I won't make any more posts. and this project. I will do it privately... you should thank all those people who voted for me to leave here... greetings.   Celestine. You can close the topic if you want.
    • 10 votes for stay, 4 for leave, you really have some issues to solve dude. Used to like you but you act weird
  • Topics

×
×
  • Create New...