Exemplo n.º 1
0
void OnAmxxAttach()
{
	initialze_offsets();
	initialize_glb_offsets();
	MF_AddNatives(engfunc_natives);
	MF_AddNatives(dllfunc_natives);
	MF_AddNatives(pev_natives);
	MF_AddNatives(forward_natives);
	MF_AddNatives(pdata_natives);
	MF_AddNatives(tr_Natives);
	MF_AddNatives(glb_natives);
	MF_AddNatives(ext2_natives);
	MF_AddNatives(misc_natives);
	g_kvd_glb.kvd.szClassName = const_cast<char *>(g_kvd_glb.cls.chars());
	g_kvd_glb.kvd.szKeyName = const_cast<char *>(g_kvd_glb.key.chars());
	g_kvd_glb.kvd.szValue = const_cast<char *>(g_kvd_glb.val.chars());
	g_kvd_glb.kvd.fHandled = 0;

	ConfigManager = MF_GetConfigManager();

	char error[256];
	error[0] = '\0';

	if (!ConfigManager->LoadGameConfigFile("common.games", &CommonConfig, error, sizeof(error)) && error[0] != '\0')
	{
		MF_Log("Could not read common.games gamedata: %s", error);
		MF_Log("get/set/find_ent_data* natives have been disabled");
		return;
	}

	MF_AddNatives(pdata_gc_natives);
}
Exemplo n.º 2
0
void InitGlobalVars()
{
	void *address = nullptr;

#if defined(WIN32)

	int offset = 0;

	if (CommonConfig->GetOffset("svs", &offset))
	{
		uintptr_t base = *reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(g_engfuncs.pfnGetCurrentPlayer) + offset);
		ServerStatic = reinterpret_cast<server_static_t*>(base - 4);
	}
#else
	if (CommonConfig->GetMemSig("svs", &address))
	{
		ServerStatic = reinterpret_cast<server_static_t*>(address);
	}
#endif
	if (CommonConfig->GetAddress("sv", &address))
	{
		Server = *reinterpret_cast<server_t**>(address);
	}

	if (!ServerStatic)
	{
		MF_Log("svs global variable is not available\n");
	}
	
	if (!Server)
	{
		MF_Log("sv global variable is not available\n");
	}
}
Exemplo n.º 3
0
void OnAmxxAttach()
{
	initialze_offsets();
	initialize_glb_offsets();

	MF_AddNatives(engfunc_natives);
	MF_AddNatives(dllfunc_natives);
	MF_AddNatives(pev_natives);
	MF_AddNatives(forward_natives);
	MF_AddNatives(pdata_natives);
	MF_AddNatives(tr_Natives);
	MF_AddNatives(glb_natives);
	MF_AddNatives(ext2_natives);
	MF_AddNatives(misc_natives);
	MF_AddNatives(pdata_entities_natives);
	MF_AddNatives(pdata_gamerules_natives);

	g_kvd_glb.kvd.szClassName = const_cast<char *>(g_kvd_glb.cls.chars());
	g_kvd_glb.kvd.szKeyName = const_cast<char *>(g_kvd_glb.key.chars());
	g_kvd_glb.kvd.szValue = const_cast<char *>(g_kvd_glb.val.chars());
	g_kvd_glb.kvd.fHandled = 0;

	ConfigManager = MF_GetConfigManager();

	char error[256] = "";

	if (!ConfigManager->LoadGameConfigFile("common.games", &CommonConfig, error, sizeof(error)) && error[0] != '\0')
	{
		MF_Log("get/set_ent_data* natives have been disabled because common.games gamedata could not be read: %s", error);
		return;
	}

	*error = '\0';

	if (!ConfigManager->LoadGameConfigFile("common.games/gamerules.games", &GamerulesConfig, error, sizeof(error)) && error[0] != '\0')
	{
		MF_Log("get/set_gamerules_* natives have been disabled because common.games/gamerules.games gamedata could not be read: %s", error);
		return;
	}

	void *address = nullptr;

	if (!CommonConfig->GetAddress("g_pGameRules", &address) || !address)
	{
		MF_Log("get/set_gamerules_* natives have been disabled because g_pGameRules address could not be found. ");
		return;
	}

#if defined(KE_WINDOWS)
	GameRulesAddress = *reinterpret_cast<void***>(address);
#else
	GameRulesAddress = reinterpret_cast<void**>(address);
#endif
}
void OnAmxxAttach(void)
{
	// Assert that the enum is aligned properly with the table

	assert(strcmp(hooklist[Ham_FVecVisible].name, "fvecvisible")==0);
	assert(strcmp(hooklist[Ham_Player_UpdateClientData].name, "player_updateclientdata")==0);
	assert(strcmp(hooklist[Ham_Item_AddToPlayer].name, "item_addtoplayer")==0);
	assert(strcmp(hooklist[Ham_Weapon_ExtractAmmo].name, "weapon_extractammo")==0);
	assert(strcmp(hooklist[Ham_TS_BreakableRespawn].name, "ts_breakablerespawn")==0);
	assert(strcmp(hooklist[Ham_NS_UpdateOnRemove].name, "ns_updateonremove")==0);
	assert(strcmp(hooklist[Ham_TS_ShouldCollide].name, "ts_shouldcollide")==0);

	assert(strcmp(hooklist[Ham_GetDeathActivity].name, "getdeathactivity")==0);
	assert(strcmp(hooklist[Ham_StopFollowing].name, "stopfollowing")==0);
	assert(strcmp(hooklist[Ham_CS_Player_OnTouchingWeapon].name, "cstrike_player_ontouchingweapon")==0);
	assert(strcmp(hooklist[Ham_DOD_Weapon_Special].name, "dod_weapon_special")==0);
	assert(strcmp(hooklist[Ham_TFC_RadiusDamage2].name, "tfc_radiusdamage2")==0);
	assert(strcmp(hooklist[Ham_ESF_Weapon_HolsterMeleed].name, "esf_weapon_holsterwhenmeleed")==0);
	assert(strcmp(hooklist[Ham_NS_Weapon_GetDeployTime].name, "ns_weapon_getdeploytime")==0);
	assert(strcmp(hooklist[Ham_SC_MedicCallSound].name, "sc_mediccallsound")==0);
	assert(strcmp(hooklist[Ham_SC_Player_CanTouchPlayer].name, "sc_player_cantouchplayer")==0);
	assert(strcmp(hooklist[Ham_SC_Weapon_ChangeWeaponSkin].name, "sc_weapon_changeweaponskin")==0);
	assert(strcmp(hooklist[Ham_SC_Player_IsConnected].name, "sc_player_isconnected")==0);

	MF_AddNatives(pdata_natives_safe);
	if (ReadConfig() > 0)
	{
		if (Offsets.IsValid())
		{
			MF_AddNatives(RegisterNatives);
			MF_AddNatives(ReturnNatives);
			MF_AddNatives(pdata_natives);
		}
		else
		{
#ifdef _WIN32
			MF_Log("Error: pev and base not set for section \"%s windows\", cannot register natives.", MF_GetModname());
#elif defined(__linux__)
			MF_Log("Error: pev and base not set for section \"%s linux\", cannot register natives.", MF_GetModname());
#elif defined(__APPLE__)
			MF_Log("Error: pev and base not set for section \"%s mac\", cannot register natives.", MF_GetModname());
#endif
		}
	}
	else
	{
		MF_Log("Error: Cannot read config file, natives not registered!");
	}
}
Exemplo n.º 5
0
static cell AMX_NATIVE_CALL csdm_reload_cfg(AMX *amx, cell *params)
{
	char file[255];

	file[0] = '\0';

	if  (params[0] / sizeof(cell) != 0)
	{
		int len;
		char *str = MF_GetAmxString(amx, params[1], 0, &len);
		if (str[0] != '\0')
		{
			MF_BuildPathnameR(file, sizeof(file)-1, "%s/%s", LOCALINFO("amxx_configsdir"), str);
		}
	}

	if (file[0] == '\0')
	{
		MF_BuildPathnameR(file, sizeof(file)-1, "%s/csdm.cfg", LOCALINFO("amxx_configsdir"));
	}

	if (g_Config.ReadConfig(file) != Config_Ok)
	{
		MF_Log("Could not read config file: %s", file);
		return 0;
	}

	return 1;
}
Exemplo n.º 6
0
void CtrlDetours_Natives(bool set)
{
	if (set)
	{
		void *address = nullptr;

		if (MainConfig->GetMemSig("CreateNamedEntity", &address)) // cs_create_entity()
		{
			CS_CreateNamedEntity = reinterpret_cast<CreateNamedEntityFunc>(address);
		}

		if (MainConfig->GetMemSig("FindEntityByString", &address)) // cs_find_ent_by_class()
		{
			CS_UTIL_FindEntityByString = reinterpret_cast<UTIL_FindEntityByStringFunc>(address);
		}

		if (!CS_CreateNamedEntity)
		{
			MF_Log("CREATE_NAMED_ENITTY is not available - native cs_create_entity() has been disabled");
		}

		if (!CS_UTIL_FindEntityByString)
		{
			MF_Log("UTIL_FindEntByString is not available - native cs_find_ent_by_class() has been disabled");
		}

		if (MainConfig->GetMemSig("GiveDefaultItems", &address))
		{
			GiveDefaultItemsDetour = DETOUR_CREATE_MEMBER_FIXED(GiveDefaultItems, address);
		}

		if (!GiveDefaultItemsDetour)
		{
			MF_Log("GiveDefaultItems is not available - native cs_set_no_knives has been disabled");
		}
	}
	else
	{
		if (GiveDefaultItemsDetour)
		{
			GiveDefaultItemsDetour->Destroy();
		}
	}
}
Exemplo n.º 7
0
void CtrlDetours_ClientCommand(bool set)
{
	if (set)
	{
		void *base = reinterpret_cast<void *>(MDLL_ClientCommand);

#if defined(WIN32)

		int offset = 0;

		if (MainConfig->GetOffset("UseBotArgs", &offset))
		{
			UseBotArgs = get_pdata<int*>(base, offset);
		}

		if (MainConfig->GetOffset("BotArgs", &offset))
		{
			BotArgs = get_pdata<const char**>(base, offset);
		}

#elif defined(__linux__) || defined(__APPLE__)

		void *address = nullptr;

		if (MainConfig->GetMemSig("UseBotArgs", &address))
		{
			UseBotArgs = reinterpret_cast<int *>(address);
		}

		if (MainConfig->GetMemSig("BotArgs", &address))
		{
			BotArgs = reinterpret_cast<const char **>(address);
		}
#endif
		ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, base);

		CommonConfig->GetOffsetByClass("CBasePlayer", "m_iTeam", &TeamOffset);
		CommonConfig->GetOffsetByClass("CBasePlayer", "m_iMenu", &MenuOffset);

		if (!ClientCommandDetour || !UseBotArgs || !BotArgs || !TeamOffset || !MenuOffset)
		{
			MF_Log("ClientCommand is not available - forward client_command has been disabled");
		}
	}
	else
	{
		if (ClientCommandDetour)
		{
			ClientCommandDetour->Destroy();
		}

		ItemAliasList.clear();
	}
}
Exemplo n.º 8
0
void OnAmxxAttach()
{
	MF_AddNatives(CstrikeNatives);

	InitializeHacks();

	// cs_create_entity()
	CS_CreateNamedEntity = reinterpret_cast<CreateNamedEntityFunc>(UTIL_FindAddressFromEntry(CS_IDENT_CREATENAMEDENTITY, CS_IDENT_HIDDEN_STATE));

	if (CS_CreateNamedEntity <= 0)
	{
		MF_Log("CREATE_NAMED_ENITTY is not available - native cs_create_entity() has been disabled");
	}

	// cs_find_ent_by_class()
	CS_UTIL_FindEntityByString = reinterpret_cast<UTIL_FindEntityByStringFunc>(UTIL_FindAddressFromEntry(CS_IDENT_UTIL_FINDENTITYBYSTRING, CS_IDENT_HIDDEN_STATE));
	
	if (CS_UTIL_FindEntityByString <= 0)
	{
		MF_Log("UTIL_FindEntByString is not available - native cs_find_ent_by_class() has been disabled");
	}
}
Exemplo n.º 9
0
void RankSystem::loadRank(const char* filename)
{
	FILE *bfp = fopen(filename , "rb");
	
	if (!bfp)
	{
		MF_Log("Could not load stats file: %s", filename);
		return;
	}
	
	short int i = 0;
	if (fread(&i, sizeof(short int), 1, bfp) != 1)
	{
		fclose(bfp);
		return;
	}

	
	if (i == RANK_VERSION)
	{
		Stats d;
		char unique[64], name[64];
		if (fread(&i, sizeof(short int), 1, bfp) != 1)
		{
			fclose(bfp);
			return;
		}

		while(i && !feof(bfp))
		{
			TRYREAD(name, i, sizeof(char), bfp);
			TRYREAD(&i, 1, sizeof(short int), bfp);
			TRYREAD(unique, i, sizeof(char) , bfp);
			TRYREAD(&d.tks, 1, sizeof(int), bfp);
			TRYREAD(&d.damage, 1, sizeof(int), bfp);
			TRYREAD(&d.deaths, 1, sizeof(int), bfp);
			TRYREAD(&d.kills, 1, sizeof(int), bfp);
			TRYREAD(&d.shots, 1, sizeof(int), bfp);
			TRYREAD(&d.hits, 1, sizeof(int), bfp);
			TRYREAD(&d.hs, 1, sizeof(int), bfp);
			TRYREAD(&d.points, 1, sizeof(int), bfp);
			TRYREAD(d.bodyHits, 1, sizeof(d.bodyHits), bfp);
			TRYREAD(&i, 1, sizeof(short int), bfp);

			RankSystem::RankStats* a = findEntryInRank( unique , name );
			if ( a ) a->updatePosition( &d );
		}
	}
	
	fclose(bfp);
}
Exemplo n.º 10
0
void OnAmxxAttach()
{
	MF_AddNatives(sockets_natives);
    // And, if win32, we have to specially start up the winsock environment
    #ifdef _WIN32  
        short wVersionRequested;
        WSADATA wsaData;
        wVersionRequested = MAKEWORD (1, 1);
        if (WSAStartup (wVersionRequested, &wsaData) != 0) {
            MF_Log("Sockets Module: Error while starting up winsock environment.!");
        }
    #endif
    return;
}
Exemplo n.º 11
0
bmodObject::bmodObject(const char * model, float mass) {
	if(!getModelShape(model, &shape)) {
		MF_Log("BAD model! (%s)", model);
		shape = new btEmptyShape();
	}

	btVector3 inertia(0, 0, 0);
	shape->calculateLocalInertia(mass, inertia);
	bmodMotionState* objectMotionState = new bmodMotionState(this);
	btRigidBody::btRigidBodyConstructionInfo objectRigidBodyCI(mass, objectMotionState, shape, inertia);
	rigidBody = new btRigidBody(objectRigidBodyCI);

	g_bt_dynamicsWorld->addRigidBody(rigidBody);
}
Exemplo n.º 12
0
void OnPluginsLoaded()
{
	CvarFadeToblack   = CVAR_GET_POINTER("mp_fadetoblack");
	CvarForceCamera   = CVAR_GET_POINTER("mp_forcecamera");
	CvarForceChaseCam = CVAR_GET_POINTER("mp_forcechasecam");

	TypeConversion.init();

	if (!ErrorLogs.empty())
	{
		for (size_t line = 0; line < ErrorLogs.length(); ++line)
		{
			MF_Log(ErrorLogs[line].chars());
		}

		ErrorLogs.clear();
	}
}
Exemplo n.º 13
0
// ns_find_weapon_offset(idPlayer,"primweapon","lastinvweapon")
static cell AMX_NATIVE_CALL ns_find_weapon_offset(AMX *amx, cell *params)
{
	char *SPrimWeapon=MF_GetAmxString(amx,params[2],0,NULL);
	char *SLastInv=MF_GetAmxString(amx,params[3],1,NULL);
	edict_t *ePlayer=INDEXENT_NEW(params[1]);

	// Locate entities by name
	edict_t *PrimWeapon=NULL;
	edict_t *LastInv=NULL;

	edict_t *Temp=NULL;

	while ((Temp=UTIL_FindEntityByString(Temp,"classname",SPrimWeapon))!=NULL)
	{
		if (Temp->v.owner==ePlayer)
		{
			PrimWeapon=Temp;
			break;
		}
	}
	Temp=NULL;
	while ((Temp=UTIL_FindEntityByString(Temp,"classname",SLastInv))!=NULL)
	{
		if (Temp->v.owner==ePlayer)
		{
			LastInv=Temp;
			break;
		}
	}

	if (LastInv == NULL || PrimWeapon == NULL)
	{
		if (LastInv==NULL)
		{
			MF_Log("LastInv==NULL");
		}
		if (PrimWeapon==NULL)
		{
			MF_Log("PrimWeapon=NULL");
		}
		return 0;
	}

	// now iterate through the client's private data until we find the pointer to PrimWeapon/LastInv's offset
	unsigned int *Ptr=(unsigned int*)ePlayer->pvPrivateData;

	int FoundLastInv=0;
	int FoundPrim=0;
	size_t count=0;
	unsigned int iPrim;
	unsigned int iLast;

	// so nasty D: this is basically horrible_cast
	union bleh
	{
		void *ptr;
		unsigned int ival;
	}blah;
	
	blah.ptr=PrimWeapon->pvPrivateData;
	iPrim=blah.ival;

	blah.ptr=LastInv->pvPrivateData;
	iLast=blah.ival;

	while (count<4000)
	{
		if (*Ptr==iLast)
		{
			MF_Log("Found LastInv: %d",count);
			FoundLastInv=1;
		}
		if (*Ptr==iPrim)
		{
			MF_Log("Found Primary: %d",count);
			FoundPrim=1;
		}

		if (FoundLastInv && FoundPrim)
		{
			//break;
		}
		count+=4;
		Ptr++;
	}
	return 1;
}
Exemplo n.º 14
0
void CtrlDetours_BuyCommands(bool set)
{
	if (set)
	{
		void *address = nullptr;

		if (MainConfig->GetMemSig("GiveShield", &address))
		{
			GiveShieldDetour = DETOUR_CREATE_MEMBER_FIXED(GiveShield, address);
		}

		if (MainConfig->GetMemSig("GiveNamedItem", &address))
		{
			GiveNamedItemDetour = DETOUR_CREATE_MEMBER_FIXED(GiveNamedItem, address);
		}

		if (MainConfig->GetMemSig("AddAccount", &address))
		{
			AddAccountDetour = DETOUR_CREATE_MEMBER_FIXED(AddAccount, address);
		}
		
		if (!GiveShieldDetour || !GiveNamedItemDetour || !AddAccountDetour)
		{
			if (!GiveShieldDetour)
			{
				MF_Log("GiveShield is not available");
			}

			if (!GiveNamedItemDetour)
			{
				MF_Log("GiveNamedItem is not available");
			}

			if (!AddAccountDetour)
			{
				MF_Log("AddAccount is not available");
			}

			MF_Log("Some functions are not available - forward CS_OnBuyAttempt and CS_OnBuy have been disabled");
		}
	}
	else
	{
		if (GiveShieldDetour)
		{
			GiveShieldDetour->Destroy();
		}

		if (GiveNamedItemDetour)
		{
			GiveNamedItemDetour->Destroy();
		}

		if (AddAccountDetour)
		{
			AddAccountDetour->Destroy();
		}

		ItemAliasList.clear();
	}
}
Exemplo n.º 15
0
bool loadDatabase()
{
	const auto isDatabaseLoaded = HandleDB.filename != nullptr;

	if (isDatabaseLoaded)
	{
		return true;
	}

	const char *databases[] =
	{
		"City",
		"Country" // Is the default shipped database with AMXX.
	};

	const auto modName = MF_GetModname();
	const auto dataDir = MF_GetLocalInfo("amxx_datadir", "addons/amxmodx/data");

	char file[260];
	auto status = -1;

	for (auto& database : databases)
	{
		// MF_BuildPathname not used because backslash
		// makes CreateFileMapping failing under windows.

		ke::SafeSprintf(file, sizeof file, "%s/%s/GeoLite2-%s.mmdb", modName, dataDir, database);

		status = MMDB_open(file, MMDB_MODE_MMAP, &HandleDB);

		if (status == MMDB_SUCCESS)
		{
			break;
		}

		if (status != MMDB_FILE_OPEN_ERROR)
		{
			MF_Log("Could not open %s - %s", file, MMDB_strerror(status));

			if (status == MMDB_IO_ERROR)
			{
				MF_Log("    IO error: %s", strerror(errno));
			}
		}
	}

	if (status != MMDB_SUCCESS)
	{
		MF_Log("Could not find GeoIP2 databases. Disabled natives.");
		return false;
	}

	MF_Log("Database info: %s %i.%i",
		   HandleDB.metadata.description.descriptions[0]->description,
		   HandleDB.metadata.binary_format_major_version,
		   HandleDB.metadata.binary_format_minor_version);

	// Retrieve supported languages.
	for (size_t i = 0; i < HandleDB.metadata.languages.count; i++)
	{
		LangList.append(ke::AString(HandleDB.metadata.languages.names[i]));
	}

	return true;
}
Exemplo n.º 16
0
int ReadConfig(void)
{
	char FileName[512];

	MF_BuildPathnameR(FileName,sizeof(FileName),"%s",get_localinfo("amxx_configsdir","addons/amxmodx/configs"));

	strncat(FileName,"/hamdata.ini",sizeof(FileName)-1);

	FILE *fp=fopen(FileName,"r");


	ke::SafeSprintf(CurrentModName, sizeof(CurrentModName), "%s", MF_GetModname());

	if (!fp)
	{
		MF_Log("Unable to open \"%s\" for reading.", FileName);

		return -1;
	}

	char data[2048];

	int insec=0;

	while (!feof(fp))
	{
		data[0]='\0';

		fgets(data, sizeof(data)-1, fp);

		char *b=&data[0];

		switch(lex(b))
		{
		case LEX_PEV:
			{
				if (insec)
				{
					process_pev(b);
				}
				break;
			};
		case LEX_BASE:
			{
				if (insec)
				{
					process_base(b);
				}
				break;
			};
		case LEX_MIRROR:
			{
				read_mirror(b);
				break;
			};
		case LEX_START_SEC:
			{
				insec=read_start_section(b);

				if (!insec)
				{
					skip_to_end_of_section(fp);
				}
				break;
			};
		case LEX_END_SEC:
			{
				insec=0;
				break;
			};
		case LEX_UNKNOWN:
			{
				if (insec)
				{
					process_key(b);
				}
			};
		}


	}

	fclose(fp);

	return 1;
}
Exemplo n.º 17
0
void ParticleManager::ReadFile(void)
{
	this->Prune();
	if (m_iFileLoaded!=0)
	{
		return;
	}
	m_iFileLoaded=1;

	char FileName[256];

	UTIL_Format(FileName, sizeof(FileName)-1, "%s/ns.ps", MF_GetModname());
	FILE *fp=fopen(FileName,"r");

	if (!fp)
	{
		MF_Log("ParticleManager: Cannot open \"%s\" for reading!",FileName);
		return;
	}

	// Since I don't care about the actual parameters of each
	// particle system, just their order and name
	// I only have to scan for "start pSystemName NAME"

	char Buffer[1024];

	char *Start;
	char *End;

	int Count=0;

	memset(&Buffer[0],0x0,sizeof(Buffer));

	while (!feof(fp))
	{
		Buffer[0]='\0';

		fgets(Buffer,1023,fp);

		Start=&Buffer[0];

		// strip whitespace from the front
		while (*Start==' ' ||
			*Start=='\t')
		{
			++Start;
		}

		// if the first character is ' ignore it
		if (*Start=='\'')
		{
			continue;
		}

		// if the first word is "start" then this is a line we want

		if (strncmp("start ",Start,6)!=0)
		{
			continue;
		}

		// Move up past 2 space blocks

		while (*Start!='\0' &&
			*Start!=' ' &&
			*Start!='\t')
		{
			++Start;
		}
		while (*Start==' ' ||
			*Start=='\t')
		{
			++Start;
		}

		while (*Start!='\0' &&
			*Start!=' ' &&
			*Start!='\t')
		{
			++Start;
		}
		while (*Start==' ' ||
			*Start=='\t')
		{
			++Start;
		}

		// now strip whitespace from the end

		End=Start+strlen(Start)-1;

		while (*End=='\n' ||
			*End=='\r' ||
			*End==' ' ||
			*End=='\t')
		{
			*End--='\0';
		}

		// "Start" should now point to the name of this particle system

		//printf("Particle system %d = \"%s\"\n",Count,Start);


		this->Add(Start,1);


		++Count;
	}

	fclose(fp);
};
Exemplo n.º 18
0
void TitleManager::LoadTitles(void)
{
	if (m_Loaded!=0) // already loaded?
	{
		return;
	}

	m_Loaded=1;

	char FileName[128];

	UTIL_Format(FileName, sizeof(FileName)-1, "%s/titles.txt", MF_GetModname());

	FILE *fp=fopen(FileName,"r");

	if (!fp)
	{
		MF_Log("Unable to load \"%s\": TitleManager will not work!",FileName);
		return;
	};

	//MF_Log("TitleManager Loading titles from \"%s\"",FileName);
	char KeyName[512];			// last known good keyname
	char Data[2048];			// data for the key
								// does not support multi line data, but for 
								// location namesthat is acceptable.
	char  TempBuffer[2048];		// currently read data
	char *TempPointer;
	char *TempPointerEnd;

	unsigned int Line=0;
scan_for_key:
	KeyName[0]='\0';

	while (!feof(fp))
	{
		Line++;
		fgets(TempBuffer,2047,fp);
		TempPointer=&TempBuffer[0];

		// get rid of white space at the front
		while (*TempPointer=='\0' ||	// terminator
			*TempPointer==' ' ||		// space
			*TempPointer=='\t')			// tab
		{
			++TempPointer;
		}
		if (*TempPointer=='\0' ||		// terminator
			*TempPointer=='/')			// comment
		{
			continue;
		}

		// get rid of \r\n at the end
		TempPointerEnd=TempPointer+strlen(TempPointer)-1;
		while (*TempPointerEnd=='\r' || 
			*TempPointerEnd=='\n' ||
			*TempPointerEnd=='\t' ||
			*TempPointerEnd==' ')
		{
			*TempPointerEnd--='\0';
		}

		if (*TempPointer=='{')			// start of data
		{
			if (KeyName[0]!='\0')		// do we have a keyname
			{
				goto scan_for_data;
			}
			else
			{
				MF_Log("TitleManager: titles.txt line %u: began a data section with no key name in use!",Line);
				goto scan_for_key;
			}
		}

		// have a valid key name here
		strncpy(KeyName,TempBuffer,sizeof(KeyName)-1);
		
		// keep looping (until we hit a '{')
	};

	// if we're out here then !feof() failed
	goto end_of_file;
scan_for_data:
	Data[0]='\0';

	while (!feof(fp))
	{
		Line++;
		fgets(TempBuffer,2047,fp);
		TempPointer=&TempBuffer[0];

		// get rid of white space at the front
		while (*TempPointer=='\0' ||	// terminator
			*TempPointer==' ' ||		// space
			*TempPointer=='\t')			// tab
		{
			++TempPointer;
		}
		if (*TempPointer=='\0' ||		// terminator
			*TempPointer=='/')			// comment
		{
			continue;
		}

		// get rid of trailing whitespace
		TempPointerEnd=TempPointer+strlen(TempPointer)-1;
		while (*TempPointerEnd=='\r' || 
			*TempPointerEnd=='\n' ||
			*TempPointerEnd=='\t' ||
			*TempPointerEnd==' ')
		{
			*TempPointerEnd--='\0';
		}

		if (*TempPointer=='}')			// end of data
		{
			// insert KeyName & Data into the hash
			ke::AString key(UTIL_ToLowerCase(KeyName));

			this->m_Hash.insert(key, new ke::AString(Data));

			goto scan_for_key;
		}

		// have valid data here
		strncpy(Data,TempBuffer,sizeof(Data)-1);
	};
end_of_file:

	fclose(fp);

	//MF_Log("TitleManager loaded %u entries from titles.txt (%u lines parsed)",m_List.size(),Line);
};