Achievements system [SQL запазване]

Аватар
HuliganaKuncho
Respected
Respected
Мнения: 1385
Регистриран на: 14 Дек 2013, 15:10
Ник в играта: HuliganaKuncho
Скайп профил: petar.sub12
Вашият пол е: Мъж
Обратна връзка:

Achievements system [SQL запазване]

Мнение от HuliganaKuncho »

Това е система за постижения, която съдържа 12 постижения, които ще обясна подробно по-надолу. Плъгина е с отворен код, всеки има право да го модифицира, както му харесва, стига да не се присвояват авторски права. За проблеми или предложения, използвайте тази тема или ЛС.

Постижения:
1) 1HP kill - убийте враг докато сте на 1 кръв.
2) Nice aim - направете 750 убийства с headshot.
3) Blind kill - убийте враг докато сте флашнат.
4) 50 stabs - направете 50 убийства с нож.
5) Scratcher - изпръскайте 300 спрея.
6) Fly man - убийте враг докато сте във въздуха.
7) Bomber man - убийте двама врагове с една граната.
8) Defuser - обезвредете 200 бомби.
9) Planter - заложете 200 бомби.
10) Server Lover - влезте в сървъра 1000 пъти.
11) SPLAT - убийте двама врагове с един патрон.
12) Best Player - играйте един час в сървъра.

Как да го свържа с SQL:
- На линия #36,37,38 и 39 намирате:
new Host[] = ""; <- тук пишете вашият хост.
new User[]= ""; <- тук пишете вашият потребител към база данните.
new Pass[] = ""; <- тук пишете вашата парола към потребителя.
new Db[] = ""; <- тук пишете вашата база данни.


Changelog:

Код за потвърждение: Избери целия код

v1.0 - първи релийз на плъгина
Да направя:

Код за потвърждение: Избери целия код

- да добавя запазване с nvault
- да добавя cvar's, за по-лесна настройка на постиженията
- да добавя звуци към някое постижение
- да добавя накакви бонуси, при определен брой изпълнени постижения
- да добавя motd с помощна информация
Модули които изисква:
#include <amxmodx>
#include <cstrike>
#include <engine>
#include <fakemeta>
#include <colorchat>
#include <fun>
#include <sqlx>
#include <hamsandwich>

Код на плъгина:

Код за потвърждение: Избери целия код

#include <amxmodx>
#include <cstrike>
#include <engine>
#include <fakemeta>
#include <colorchat>
#include <fun>
#include <sqlx>
#include <hamsandwich>

#define XO_WEAPON	     4
#define XO_PLAYER            5
#define ALPHA_FULLBLINDED    255
#define m_flFlashedUntil     514
#define m_flFlashedAt        515
#define m_flFlashHoldTime    516
#define m_flFlashDuration    517
#define m_iFlashAlpha        518

#define GetBit(%1,%2) 		(%1 &  1 << (%2 & 31))
#define SetBit(%1,%2)	 	(%1 |=  (1 << (%2 & 31)))
#define DelBit(%1,%2)		(%1 &= ~(1 << (%2 & 31)))

const MAX_PLAYERS = 32
new g_Prefix[] = "^1[^4Achievments^1]"

new Handle:MySQL_Tuple, Handle:MySQL_Connection, g_Error[255], MySQL_Query[512]
new bool:playerLoaded[33]

new a_lowhp[32], a_hsk[32], a_blk[32], a_knk[32], a_pnt[32], a_flyman[32], a_he[32], a_plr[32], a_dsr[32], a_svlover[32], a_1a2k[32], a_timespend[32]
new p_hs[32], p_knife[32], p_spr[32], p_inair[32], p_he[32], p_bdef[32], p_pl[32], p_connections[32], p_minutes[32]

new iKillerShot, g_iShotKills[MAX_PLAYERS + 1], g_iGunEvent_IDsBitsum

new Host[] = 	"";
new User[]= 	"";
new Pass[] = 	"";
new Db[] = 	"";

public plugin_init() 
{
	register_plugin("Achievments system", "1.0", "<HK>")
	
	register_event("DeathMsg", "player_killed", "a")
	register_event( "23", "player_spray", "a", "1=112")
	
	register_forward(FM_CmdStart, "FwdCmdStart")
	
	register_logevent("round_start", 2, "0=World triggered", "1=Round_Start")
	
	register_clcmd("say /ach", "a_menu")
	register_clcmd("say_team /ach", "a_menu")
	register_clcmd("say /achievement", "a_menu")
	register_clcmd("say_team /achievement", "a_menu")
	
	set_task(60.0, "time_record", .flags="b")
}

public plugin_precache() 
{    
	MySQL_Tuple = SQL_MakeDbTuple(Host, User, Pass, Db)
		
	new ErrorCode
	MySQL_Connection = SQL_Connect(MySQL_Tuple, ErrorCode, g_Error, charsmax(g_Error))
	if(MySQL_Connection == Empty_Handle)
		set_fail_state(g_Error)
			
	formatex(MySQL_Query, charsmax(MySQL_Query),"CREATE TABLE IF NOT EXISTS `achievments` (`id` INT(1) NOT NULL AUTO_INCREMENT,`steamid` VARCHAR(32),`name` VARCHAR(32),`a_lowhp` INT(1),`a_hsk` INT(1),`p_hs` INT(1),`p_knife` INT(1),`a_blk` INT(1),`a_knk` INT(1),`a_pnt` INT(1),`a_flyman` INT (1),`p_spr` INT(1),`a_he` INT (1),`a_plr` INT (1),`a_dsr` INT (1),`p_pl` INT (1),`p_bdef` INT (1),`a1` INT (1),`p1` INT (1),`a_1a2k` INT (1), `a_spd` INT (1),  PRIMARY KEY(`id`))") 
	SQL_ThreadQuery(MySQL_Tuple, "SQL_TrashHandler", MySQL_Query)
}

public bomb_defused(id)  
{
	p_bdef[id] += 1
	if(p_bdef[id] == 200 && !a_dsr[id]) {
		a_dsr[id] = 1
		ColorChat (id, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 Defuser^1.", g_Prefix)
	}
}

public bomb_planted(id)   
{
	p_pl[id] += 1
	if(p_pl[id] == 200 && !a_plr[id]) {
		a_plr[id] = 1
		ColorChat (id, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 Planter^1.", g_Prefix)
	}
}

public plugin_end()
{
	SQL_FreeHandle(MySQL_Connection)
}

public round_start(id)
{
	p_he[id] = 0
}

public player_spray() 
{ 
	new iPlayer = read_data(2)
	
	p_spr[iPlayer] += 1
	if(p_spr[iPlayer] == 300 && !a_pnt[iPlayer]) {
		a_pnt[iPlayer] = 1
		ColorChat (iPlayer, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 Scratcher^1.", g_Prefix)
	}
}

public a_menu(id)
{
	new szText[555 char]
	formatex(szText, charsmax(szText), "\wAchievments menu")
	new Menu = menu_create(szText, "a_menu_handler")

	if(a_lowhp[id] == 1) {
		formatex(szText, charsmax(szText), "\d1HP kill [Kill someone at 1 HP] - COMPLETED")
		menu_additem(Menu, szText, "1", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\w1HP kill [\yKill someone at 1 HP\w]")
		menu_additem(Menu, szText, "1", 0)
	}
	if(a_hsk[id] == 1) {
		formatex(szText, charsmax(szText), "\dNice aim [Make 750 HS] - COMPLETED")
		menu_additem(Menu, szText, "2", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\wNice aim [\yMake 750 HS/You: \w%d\y\w]", p_hs[id])
		menu_additem(Menu, szText, "2", 0)
	}
	if(a_blk[id] == 1) {
		formatex(szText, charsmax(szText), "\dBlind kill [Kill someone when you are flashed] - COMPLETED")
		menu_additem(Menu, szText, "3", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\wBlind kill [\yKill someone when you are flashed\w]")
		menu_additem(Menu, szText, "3", 0)
	}
	if(a_knk[id] == 1) {
		formatex(szText, charsmax(szText), "\d50 stabs [Make 50 Knife kills] - COMPLETED")
		menu_additem(Menu, szText, "4", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\w50 stabs [\yMake 50 Knife kills/You: \w%d\y\w]", p_knife[id])
		menu_additem(Menu, szText, "4", 0)
	}
	if(a_pnt[id] == 1) {
		formatex(szText, charsmax(szText), "\dScratcher [Make 300 sprays] - COMPLETED")
		menu_additem(Menu, szText, "5", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\wScratcher [\yMake 300 sprays/You: \w%d\y\w]", p_spr[id])
		menu_additem(Menu, szText, "5", 0)
	}
	if(a_flyman[id] == 1) {
		formatex(szText, charsmax(szText), "\dFly man [Kill someone when you are in air] - COMPLETED")
		menu_additem(Menu, szText, "6", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\wFly man [\yKill someone when you are in air\w]")		
		menu_additem(Menu, szText, "6", 0)
	}
	if(a_he[id] == 1) {
		formatex(szText, charsmax(szText), "\dBomber Man [Kill 2 peoples with HE] - COMPLETED")
		menu_additem(Menu, szText, "7", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\wBomber Man [\yKill 2 peoples with HE\w]")
		menu_additem(Menu, szText, "7", 0)
	}
	if(a_dsr[id] == 1) {
		formatex(szText, charsmax(szText), "\dDefuser [Defuse 200 bombs] - COMPLETED")
		menu_additem(Menu, szText, "8", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\wDefuser [\yDefuse 200 bombs/You: \w%d\y\w]", p_bdef[id])
		menu_additem(Menu, szText, "8", 0)
	}
	if(a_plr[id] == 1) {
		formatex(szText, charsmax(szText), "\dPlanter [Plant 200 bombs] - COMPLETED")
		menu_additem(Menu, szText, "9", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\wPlanter [\yPlant 200 bombs/You: \w%d\y\w]", p_pl[id])
		menu_additem(Menu, szText, "9", 0)
	}
	if(a_svlover[id] == 1) {
		formatex(szText, charsmax(szText), "\dServer Lover [Join 1000 times] - COMPLETED")
		menu_additem(Menu, szText, "10", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\wServer Lover [\yJoin 1000 times/You: \w%d\y\w]", p_connections[id])
		menu_additem(Menu, szText, "10", 0)
	}
	if(a_svlover[id] == 1) {
		formatex(szText, charsmax(szText), "\dSplat [Kill 2 enemys with one bullet] - COMPLETED")
		menu_additem(Menu, szText, "11", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\wSplat [\yKill 2 enemys with one bullet\w]", p_connections[id])
		menu_additem(Menu, szText, "11", 0)
	}
	if(a_timespend[id] == 1) {
		formatex(szText, charsmax(szText), "\dBest Player [Play hole map] - COMPLETED")
		menu_additem(Menu, szText, "12", 0)
	}
	else {
		formatex(szText, charsmax(szText), "\wBest Player [\yPlay hole map (60min.)\w]")
		menu_additem(Menu, szText, "12", 0)
	}
	
	menu_setprop(Menu, MPROP_EXIT, MEXIT_ALL)
	menu_display(id, Menu, 0)
}

public a_menu_handler(id, menu, item)
{    
	new data[6], iName[64], access, callback
	menu_item_getinfo(menu, item, access, data,5, iName, 63, callback) 
	new key = str_to_num(data)
	switch(key)
	{      
		case 1: 
			a_menu(id)
		case 2: 
			a_menu(id)
		case 3: 
			a_menu(id)
		case 4: 
			a_menu(id)
		case 5: 
			a_menu(id)
		case 6: 
			a_menu(id)
		case 7: 
			a_menu(id)
		case 8: 
			a_menu(id)
		case 9: 
			a_menu(id)
		case 10:
			a_menu(id)
		case 11:
			a_menu(id)
		case 12: 
			a_menu(id)
	}
	menu_destroy(menu)
	return PLUGIN_HANDLED
}



public client_disconnect(id) 
	Save(id)

public client_putinserver(id)
{
	p_minutes[id] = 0
	playerLoaded[id] = false
	Load(id)
	p_connections[id] += 1
	if(p_connections[id] == 1000 && !a_svlover[id]) {
		a_svlover[id] = 1
		ColorChat (id, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 Server Lover^1.", g_Prefix)
	}
}

public player_killed()
{
	new killer = read_data(1)
	new victim = read_data(2)
	new headshot = read_data(3)
	new iPercent
	if(killer == victim)
		return PLUGIN_HANDLED
		
	if(get_user_health(killer) == 1 && a_lowhp[killer] != 1) {
		a_lowhp[killer] = 1
		ColorChat (killer, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 1HP Kill^1.", g_Prefix)
	}
	
	if(p_hs[killer] < 749 && headshot && a_hsk[killer] != 1)
			p_hs[killer] += 1
			
	else if(p_hs[killer] >= 749 && headshot && a_hsk[killer] != 1) {
		ColorChat (killer, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 750 Headshot Kills^1.", g_Prefix)
		a_hsk[killer] = 1
	}
	
	if(get_user_flashed(killer, iPercent))
	{
		if(iPercent == 100 && !a_blk[killer]) {
			a_blk[killer] = 1
			ColorChat (killer, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 Blind Kill^1.", g_Prefix)
		}

	}
	
	if(get_user_weapon(killer) == CSW_KNIFE)
	{
		if(p_knife[killer] >= 49 && !a_knk[killer]) {
			a_knk[killer] = 1
			ColorChat (killer, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 50 Knife Kills^1.", g_Prefix)
		}
		if(!a_knk[killer])
			p_knife[killer] += 1
	}
	
	if(p_inair[killer]) {
		a_flyman[killer] = 1
		ColorChat (killer, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 Fly man^1.", g_Prefix)
	}
	
	if(get_user_weapon(killer) == CSW_HEGRENADE)
		p_he[killer] += 1
		
	if(p_he[killer] == 2 && a_he[killer] != 1) {
		a_he[killer] = 1
		ColorChat (killer, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 BomberMan^1.", g_Prefix)
	}
	
	if(GetBit(iKillerShot, killer))
	{
		g_iShotKills[killer]++
		if(g_iShotKills[killer] >= 2)
		{
			a_1a2k[killer] = 1
			ColorChat (killer, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 Splat^1.", g_Prefix)
		}
	}
	
	return PLUGIN_HANDLED
}

public time_record()
{
	new players[32], pnum, tempid
	get_players(players, pnum)
	
	for(new i; i<pnum; i++)
	{
		tempid = players[i]
		new CsTeams:team = cs_get_user_team(tempid)
		
		if(team != CS_TEAM_SPECTATOR && team != CS_TEAM_UNASSIGNED)
		{
			p_minutes[tempid] += 1
			if(p_minutes[tempid] == 59 && !a_timespend[tempid])
			{
				a_timespend[tempid] += 1
				ColorChat (tempid, NORMAL, "%s Pozdravleniq! Otkluchihte postijenieto^4 Best Player^1.", g_Prefix)
			}
		}
	}
}


public FwdPlaybackEvent( flags, id, eventid )
{
	if(!(g_iGunEvent_IDsBitsum & (1 << eventid)))
		return FMRES_IGNORED;
		
	DelBit(iKillerShot, id)
	g_iShotKills[id] = 0

	return FMRES_HANDLED
}

public Ham_CBasePlayer_TraceAttack(this, attacker, Float:damage, Float:direction[ 3 ], traceresult, damagebits)
{
	if(is_user_connected(attacker) && is_user_alive(attacker))
	{
		static g_iWeapon; g_iWeapon = get_user_weapon(attacker)
		if(g_iWeapon == CSW_KNIFE || g_iWeapon == CSW_HEGRENADE)
		{
			return HAM_HANDLED
		}
		
		SetBit(iKillerShot,attacker)
	
	}
	return HAM_HANDLED
	
}

public FwdCmdStart(id, handle)
{
	if (!is_user_alive(id)) 
		return FMRES_IGNORED
	
	if(entity_get_int(id, EV_INT_flags ) & FL_ONGROUND)
		p_inair[id] = false
	else
		p_inair[id] = true
		
	return FMRES_IGNORED
}

get_user_flashed(id, &iPercent=0)
{
	new Float:flFlashedAt = get_pdata_float( id, m_flFlashedAt, XO_PLAYER )
	if( !flFlashedAt )
		return 0

	new Float:flGameTime = get_gametime()
	new Float:flTimeLeft = flGameTime - flFlashedAt
	new Float:flFlashDuration = get_pdata_float( id, m_flFlashDuration, XO_PLAYER )
	new Float:flFlashHoldTime = get_pdata_float( id, m_flFlashHoldTime, XO_PLAYER )
	new Float:flTotalTime = flFlashHoldTime + flFlashDuration
	
	if( flTimeLeft > flTotalTime )
		return 0
	
	new iFlashAlpha = get_pdata_int( id, m_iFlashAlpha, XO_PLAYER )
	
	if( iFlashAlpha == ALPHA_FULLBLINDED )
	{
		if( get_pdata_float( id, m_flFlashedUntil, XO_PLAYER) - flGameTime > 0.0 )
			iPercent = 100
		else
			iPercent = 100-floatround( ( ( flGameTime - ( flFlashedAt + flFlashHoldTime ) ) * 100.0 )/flFlashDuration )
	}
	else
		iPercent = 100-floatround( ( ( flGameTime - flFlashedAt ) * 100.0 ) / flTotalTime )
	
	return iFlashAlpha
}

public Save(id) 
{
	if(!playerLoaded[id])
		return PLUGIN_CONTINUE
	
	new szAuthid[32]
	get_user_name(id, szAuthid, charsmax(szAuthid))
		
	formatex(MySQL_Query, charsmax(MySQL_Query), "UPDATE `achievments` SET `a_lowhp` = '%i', `a_hsk` = '%i', `p_hs` = '%i', `p_knife` = '%i', `a_blk` = '%i', `a_knk` = '%i', `a_pnt` = '%i', `a_flyman` = '%i', `p_spr` = '%i',`a_he` = '%i',`a_plr` = '%i',`a_dsr` = '%i',`p_pl` = '%i',`p_bdef` = '%i', `a1` = '%i', `p1` = '%i', `a_1a2k` = '%i', `a_spd` = '%i' WHERE `steamid` = '%s'",
	a_lowhp[id], a_hsk[id], p_hs[id], p_knife[id], a_blk[id], a_knk[id], a_pnt[id], a_flyman[id], p_spr[id],a_he[id], a_plr[id], a_dsr[id], p_pl[id], p_bdef[id],  a_svlover[id], p_connections[id], a_1a2k[id], a_timespend[id], szAuthid)
	SQL_ThreadQuery(MySQL_Tuple, "SQL_TrashHandler", MySQL_Query)
	
	return PLUGIN_CONTINUE
}
public Load(id) 
{
	new szAuthid[32]
	get_user_name(id, szAuthid, charsmax(szAuthid))
	
	// Update item in mysql
	new Handle:sqlQuery, strQuery[512]
	sqlQuery = SQL_PrepareQuery(MySQL_Connection, "SELECT * FROM `achievments` WHERE `steamid` = '%s'", szAuthid)
	
	if(SQL_Execute(sqlQuery))
	{
		if(SQL_NumResults(sqlQuery))
		{
			a_lowhp[id] = SQL_ReadResult(sqlQuery, 3)
			a_hsk[id] = SQL_ReadResult(sqlQuery, 4)
			p_hs[id] = SQL_ReadResult(sqlQuery, 5)
			p_knife[id] = SQL_ReadResult(sqlQuery, 6)
			a_blk[id] = SQL_ReadResult(sqlQuery, 7)
			a_knk[id] = SQL_ReadResult(sqlQuery, 8)
			a_pnt[id] = SQL_ReadResult(sqlQuery, 9)
			a_flyman[id] = SQL_ReadResult(sqlQuery, 10)
			p_spr[id] = SQL_ReadResult(sqlQuery, 11)
			a_he[id] = SQL_ReadResult(sqlQuery, 12)
			a_plr[id] = SQL_ReadResult(sqlQuery, 13)
			a_dsr[id] = SQL_ReadResult(sqlQuery, 14)
			p_pl[id] = SQL_ReadResult(sqlQuery, 15)
			p_bdef[id] = SQL_ReadResult(sqlQuery, 16)
			a_svlover[id] = SQL_ReadResult(sqlQuery, 17)
			p_connections[id] = SQL_ReadResult(sqlQuery, 18)
			a_1a2k[id] = SQL_ReadResult(sqlQuery, 19)
			a_timespend[id] = SQL_ReadResult(sqlQuery, 20)
		}
		else
		{		
			new strName[32], strSafename[32]
			get_user_name(id, strName, 31)
			
			MakeStringSQLSafe(strName, strSafename, 31)

			formatex(strQuery, 511, "INSERT INTO `achievments` (`steamid`, `name`)VALUES ('%s', '%s')", szAuthid, strSafename)
			SQL_ThreadQuery(MySQL_Tuple, "SQL_TrashHandler", strQuery)
		}
	}
	playerLoaded[id] = true
}

MakeStringSQLSafe(const input[], output[], len)
{
	copy(output, len, input);
	replace_all(output, len, "'", "*");
	replace_all(output, len, "^"", "*");
	replace_all(output, len, "`", "*");
}

public SQL_TrashHandler(FailState,Handle:Query,Error[],Errcode,Data[],DataSize) { 
	if(FailState == TQUERY_CONNECT_FAILED)
		log_amx("[Achievments] Can't connect to SQL!  [%d] %s", Errcode, Error)
	else if(FailState == TQUERY_QUERY_FAILED)
		log_amx("[Achievments] Quary failed! [%d] %s", Errcode, Error)
	
	SQL_FreeHandle(Query)
}
Плъгина е писан от мен, кода е напълно отворен, моля не присвоявайте авторски права и не го продавайте. Забранявам темата да се пуска в друг форум/сайт, освен този. :bulgaria:
Средни пръсти от морето до небето, #хаштаг Кънчата хлг, искренно ваш враг.
Аватар
Dragonspower
Напреднал
Напреднал
Мнения: 178
Регистриран на: 02 Мар 2014, 13:51
Ник в играта: Dragonspower
Скайп профил: Ersoy_98
Вашият пол е: Мъж
Местоположение: България
Обратна връзка:

Re: Achievements system [SQL запазване]

Мнение от Dragonspower »

Тази система я има в една българска Counter-Strike Верига и е доста интересна.
Браво!
Si vous voyez une personne en détresse aide. Tous les retours :)
Аватар
mario01_2001
Баннат
Баннат
Мнения: 13
Регистриран на: 17 Апр 2016, 12:45
Ник в играта: MDMNFDKFDNKDNFN
Скайп профил: Нямам
Вашият пол е: Мъж
Местоположение: Перник
Обратна връзка:

Re: Achievements system [SQL запазване]

Мнение от mario01_2001 »

Хубав урок! Браво! :)
Последно промяна от iv00 на 31 Май 2016, 11:33, променено общо 1 път.
Причина: Спам
Трудно е да продължиш, лесно е да кажеш не мога!
Аватар
HuliganaKuncho
Respected
Respected
Мнения: 1385
Регистриран на: 14 Дек 2013, 15:10
Ник в играта: HuliganaKuncho
Скайп профил: petar.sub12
Вашият пол е: Мъж
Обратна връзка:

Re: Achievements system [SQL запазване]

Мнение от HuliganaKuncho »

Какъв урок те гони, това е плъгин.
Средни пръсти от морето до небето, #хаштаг Кънчата хлг, искренно ваш враг.
Публикувай отговор

Обратно към “Плъгини”

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 1 гост