Jump to content
  • Chmurka
  • Boróweczka
  • Jabłuszko
  • Limonka
  • Czekoladka
  • Węgielek
Sign in to follow this  
Brum Brum

[CS:GO] Deathrun Sklep (ADEPT_Deathrun_Shop)

Recommended Posts

Opis: Dodaje sklep pod komendy !shop !sklep !drshop !drsklep

Co posiada sklep? To co na ss

20190114232948_1.jpg.daac4581698b30bcc79c8ff7d254dba2.jpg

Sklep jest pod MySQL, aby sklep działał należy dodać to do databases.cfg

"DRShopDB"
{
	"driver"			"default"
	"host"				"IP do bazy danych"
	"database"			"nazwa bazy danych"
	"user"				"użytkownik bazy danych"
	"pass"				"Hasło do waszej bazy"
	//"timeout"			"0"
	//"port"			"0"
}

Sklep jest przygotowany pod -> 

KOD:

Spoiler

#include <cstrike>
#include <sdktools>
#include <deathrun>
#include <dr_shop>
#pragma semicolon 1
#pragma newdecls required

#define MOD_TAG "\x01\x0B★ \x07[ADEPT -> DR Shop]\x04 "
#define CS_ALL_TEAM -1
#define MAX_SERVICE 64
#define MAX_NAME 32

Handle ServicePlugins[MAX_SERVICE];
char ServiceName[MAX_SERVICE][MAX_NAME];

int ServiceTeam[MAX_SERVICE];
int ServiceCost[MAX_SERVICE];

bool PlayerOwnSomething[MAXPLAYERS + 1];

int ServiceCount = 0;

ConVar AddCounterTerroristMoney, AddTerroristMoney; 

int Money[MAXPLAYERS + 1];

Database DB;

public Plugin myinfo = 
{
	name = "ADEPT -> Deathrun Shop", 
	author = "Brum Brum || Koraks || Magnet(MySQL)", 
	description = "Autorski plugin StudioADEPT.net", 
	version = "1.0"
}

public void OnPluginStart()
{
	AddCounterTerroristMoney = CreateConVar("sm_drshop_earn_ct", "100", "Ilość $ które dostanie CT");
	AddTerroristMoney = CreateConVar("sm_drshop_earn_t", "10", "Ilość $ które dostanie TT");
	HookEvent("player_death", Event_PlayerDeath);
	RegConsoleCmd("sm_shop", CMD_Shop);
	RegConsoleCmd("sm_sklep", CMD_Shop);
	RegConsoleCmd("sm_drshop", CMD_Shop);
	RegConsoleCmd("sm_drsklep", CMD_Shop);
	RegAdminCmd("sm_dodajhajs", CMD_DodajHajs, ADMFLAG_ROOT);
	AutoExecConfig(true, "ADEPT_DR_Shop");
	DB_Connect();
}
public Action DB_Connect()
{
	if (SQL_CheckConfig("DRShopDB"))
	{
		char error[512];
		DB = SQL_Connect("DRShopDB", true, error, sizeof(error));
		
		if (DB == null) {
			LogMessage("Could not connect to DR shop! Error: %s", error);
			return;
		} else {
			char query[512];
			Format(query, sizeof(query), "CREATE TABLE IF NOT EXISTS DRShop(AccountID INT NOT NULL, Money INT NOT NULL,PlayerName VARCHAR(64) NOT NULL,SteamID VARCHAR(64) NOT NULL) CHARACTER SET utf8");
			DB.Query(CreateTableHandler, query, _, DBPrio_Normal);
		}
	}
	else {
		SetFailState("Nie mozna odnalezc konfiguracji 'DRShopDB' w databases.cfg. ");
	}
}

public void CreateTableHandler(Database db, DBResultSet results, const char[] error, any data) {
	if (db == null) {
		LogMessage("Could not create tables! Error: %s", error);
	}
}

public void OnClientAuthorized(int client, const char[] auth) {
	SQL_LoadData(client);
}
public void OnClientDisconnect(int client) {
	SQL_SaveData(client);
}

void SQL_LoadData(int client) {
	int clientAccountID = GetSteamAccountID(client);
	
	char query[512];
	Format(query, sizeof(query), "SELECT Money FROM DRShop WHERE AccountID=%d", clientAccountID);
	DB.Query(LoadDataHandler, query, GetClientUserId(client), DBPrio_Normal);
}

public void LoadDataHandler(Database db, DBResultSet results, const char[] error, int clientUserId) {
	if (db == null) {
		LogMessage("Could not load user data! Error: %s", error);
		return;
	}
	
	int client = GetClientOfUserId(clientUserId);
	if (!client)return;
	char name[MAX_NAME_LENGTH], auth[64];
	GetClientName(client, name, sizeof(name));
	GetClientAuthId(client, AuthId_Steam2, auth, sizeof(auth));
	char sanitized_name[64 * 2 + 1];
	DB.Escape(name, sanitized_name, sizeof(name));
	// jesli nie ma gracza w bazie...
	if (results.RowCount == 0) {
		Money[client] = 0;
		char query[512];
		Format(query, sizeof(query), "INSERT INTO DRShop VALUES(%d, 0,'%s','%s')", GetSteamAccountID(client), sanitized_name, auth);
		DB.Query(InsertNewPlayer, query, _, DBPrio_Normal);
	} else {
		while (SQL_FetchRow(results)) {
			Money[client] = SQL_FetchInt(results, 0);
		}
	}
}

public void InsertNewPlayer(Database db, DBResultSet results, const char[] error, any data) {
	if (db == null) {
		LogMessage("Could not insert player! Error: %s", error);
	}
}

void SQL_SaveData(int client) {
	char query[512], name[MAX_NAME_LENGTH];
	GetClientName(client, name, sizeof(name));
	char sanitized_name[64 * 2 + 1];
	DB.Escape(name, sanitized_name, sizeof(name));
	Format(query, sizeof(query), "UPDATE DRShop SET Money= %d,PlayerName = '%s' WHERE AccountID=%d", Money[client], sanitized_name, GetSteamAccountID(client));
	DB.Query(UpdatePlayerData, query, _, DBPrio_Normal);
}

public void UpdatePlayerData(Database db, DBResultSet results, const char[] error, any data) {
	if (db == null) {
		LogMessage("Could not update player data! Error: %s", error);
	}
}

public void OnClientPutInServer(int client)
{
	CreateTimer(1.0, ShowMoney, GetClientUserId(client), TIMER_REPEAT);
}

public void OnConfigsExecuted()
{
	ServerCommand("mp_playercashawards 0");
	ServerCommand("mp_teamcashawards 0");
}

public Action ShowMoney(Handle timer, int userid)
{
	int client = GetClientOfUserId(userid);
	if (!IsValidClient(client))return Plugin_Stop;
	
	if (IsValidClient(client))
	{
		SetHudTextParams(0.020, 0.020, 1.0, 255, 69, 0, 255, 0, 0.25, 1.5, 0.5);
		if (IsValidClient(client))
		{
			ShowHudText(client, -1, "Aktualnie masz %d$", dr_GetMoneyAmount(client));
		}
	}
	return Plugin_Continue;
}

public Action Event_PlayerDeath(Event event, const char[] name, bool dontBroadcast)
{
	int victim = GetClientOfUserId(event.GetInt("userid"));
	int attacker = GetClientOfUserId(event.GetInt("attacker"));
	if (!IsValidClient(victim))return;
	if (!IsValidClient(attacker))return;
	if (victim == attacker)return;
	int tmoney = AddTerroristMoney.IntValue;
	int ctmoney = AddCounterTerroristMoney.IntValue;
	if (dr_IsPlayerTerrorist(attacker))
	{
		dr_AddMoney(attacker, tmoney);
		PrintToChat(attacker, "%s Zdobyłeś \x02%d$\x04 za zabicie", MOD_TAG, tmoney);
	}
	else {
		dr_AddMoney(attacker, ctmoney);
		PrintToChat(attacker, "%s Zdobyłeś \x02%d$\x04 za zabicie", MOD_TAG, ctmoney);
	}
	
}

public Action CMD_Shop(int client, int args)
{
	char money[128];
	Format(money, sizeof(money), "ADEPT -> DR Shop\nTwoja ilość gotówki %d$", dr_GetMoneyAmount(client));
	Menu menu = new Menu(Menu_Handler);
	menu.SetTitle(money);
	for (int i = 0; i < MAX_SERVICE; i++)
	{
		char name[64];
		if (ServiceTeam[i] == GetClientTeam(client) || ServiceTeam[i] == CS_ALL_TEAM)
		{
			bool active;
			
			char handle[32];
			Format(handle, sizeof(handle), "%d", ServicePlugins[i]);
			
			Function func = GetFunctionByName(ServicePlugins[i], "CanBuyService");
			if (func == INVALID_FUNCTION)continue;
			Call_StartFunction(ServicePlugins[i], func);
			Call_PushCell(client);
			Call_Finish(active);
			
			Format(name, sizeof(name), "-> %s [%d$]", ServiceName[i], ServiceCost[i]);
			
			menu.AddItem(handle, name, TransferBoolToMenu(active));
		}
	}
	menu.ExitBackButton = true;
	menu.ExitButton = true;
	menu.Display(client, 60);
}

public Action CMD_DodajHajs(int client, int args)
{
	if (args < 2)
	{
		ReplyToCommand(client, "%s Uzyj: sm_dodajhajs <#userid|nick> [wartosc]", MOD_TAG);
		return Plugin_Handled;
	}
	
	char arg2[10];
	
	GetCmdArg(2, arg2, sizeof(arg2));
	
	int amount = StringToInt(arg2);
	
	char strTarget[32]; GetCmdArg(1, strTarget, sizeof(strTarget));
	char strTargetName[MAX_TARGET_LENGTH];
	int TargetList[MAXPLAYERS], TargetCount;
	bool TargetTranslate;
	
	if ((TargetCount = ProcessTargetString(strTarget, client, TargetList, MAXPLAYERS, COMMAND_FILTER_NO_IMMUNITY, strTargetName, sizeof(strTargetName), TargetTranslate)) <= 0)
	{
		ReplyToTargetError(client, TargetCount);
		return Plugin_Handled;
	}
	for (int i = 0; i < TargetCount; i++)
	{
		int iClient = TargetList[i];
		if (IsClientInGame(iClient))
		{
			if (amount > 0)
			{
				dr_AddMoney(iClient, amount);
				PrintToChat(client, "%s Dodałeś \x07%d$\x04 Graczowi \x07%N\x04", MOD_TAG, amount, iClient);
			}
			else PrintToChat(client, "%sIlosc kwoty musi byc większa od zera !", MOD_TAG);
		}
	}
	return Plugin_Continue;
}

public int Menu_Handler(Menu menu, MenuAction action, int client, int item)
{
	if (!IsValidClient(client))return;
	switch (action)
	{
		case MenuAction_Select:
		{
			char itemName[32];
			menu.GetItem(item, itemName, sizeof(itemName));
			
			Handle handle = view_as<Handle>(StringToInt(itemName));
			Function func = GetFunctionByName(handle, "PlayerTryBuy");
			if (func == INVALID_FUNCTION)
			{
				PrintToChat(client, "%sTa usługa jest zepsuta :( Powiadom o tym najszybciej admin i wybierz inna usługe!", MOD_TAG);
				CloseHandle(menu);
				
			}
			else
			{
				bool block = false;
				
				Call_StartFunction(handle, func);
				Call_PushCell(client);
				Call_Finish(block);
				
				for (int i = 0; i < MAX_SERVICE; i++)
				{
					if (ServicePlugins[i] == handle)
					{
						dr_RemoveMoney(client, ServiceCost[i]);
						break;
					}
				}
				if (block)PlayerOwnSomething[client] = block;
			}
		}
	}
}


public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
	CreateNative("dr_RegisterService", Native_RegisterService);
	CreateNative("dr_GetPlayerBuySomething", Native_GetPlayerBuySomething);
	CreateNative("dr_GetMoneyAmount", Native_GetAmount);
	CreateNative("dr_RemoveMoney", Native_RemoveMoney);
	CreateNative("dr_AddMoney", Native_AddMoney);
	CreateNative("dr_SetMoney", Native_SetMoney);
	RegPluginLibrary("dr_shop");
	return APLRes_Success;
}

public int Native_RegisterService(Handle plugin, int numParams)
{
	if (++ServiceCount > MAX_SERVICE)
	{
		ThrowNativeError(1, "Native Error : Maksymalna ilosc modułów zostala juz osiagnieta ! [%d/%d]", ServiceCount, MAX_SERVICE);
		return -1;
	}
	ServicePlugins[ServiceCount] = plugin;
	
	GetNativeString(1, ServiceName[ServiceCount], MAX_NAME);
	ServiceCost[ServiceCount] = GetNativeCell(2);
	ServiceTeam[ServiceCount] = GetNativeCell(3);
	
	return 1;
}

public int Native_GetPlayerBuySomething(Handle plugin, int numParams)
{
	int client = GetNativeCell(1);
	
	if (IsValidClient(client))
	{
		return PlayerOwnSomething[client];
	}
	return false;
}
public int Native_GetAmount(Handle plugin, int numParams)
{
	int client = GetNativeCell(1);
	if (IsValidClient(client))
	{
		return Money[client];
	}
	return 0;
}

public int Native_RemoveMoney(Handle plugin, int numParams)
{
	int client = GetNativeCell(1);
	int i_credits = GetNativeCell(2);
	if (IsValidClient(client) && i_credits > 0)
	{
		Money[client] -= i_credits;
		return true;
	}
	return false;
}

public int Native_AddMoney(Handle plugin, int numParams)
{
	int client = GetNativeCell(1);
	int i_credits = GetNativeCell(2);
	if (IsValidClient(client) && i_credits > 0)
	{
		Money[client] += i_credits;
		return true;
	}
	return false;
}

public int Native_SetMoney(Handle plugin, int numParams)
{
	int client = GetNativeCell(1);
	int i_credits = GetNativeCell(2);
	if (IsValidClient(client) && i_credits >= 0)
	{
		Money[client] = i_credits;
		return true;
	}
	
	return false;
}

stock int TransferBoolToMenu(bool value)
{
	if (value)return ITEMDRAW_DEFAULT;
	else return ITEMDRAW_DISABLED;
}

public bool IsValidClient(int client)
{
	if (!(1 <= client <= MaxClients) || !IsClientInGame(client) || !IsClientConnected(client) || IsFakeClient(client) || IsClientSourceTV(client))
		return false;
	
	return true;
} 

 

Przykład modułu
 

Spoiler

#include <dr_shop>
#include <sdktools>
#include <cstrike>
#define MOD_TAG "\x01\x0B★ \x07[ADEPT-Shop: Example]\x06 "
#define ServiceName "Granat Dymny"
#define ServiceCost 350 // cena
#define ServiceTeam CS_ALL_TEAM //Wybieramy team kto może kupić

public Plugin myinfo = 
{
	name = "ADEPT -> Shop : Smoke", 
	description = "Autorski plugin StudioADEPT.net", 
	author = "Brum Brum", 
	version = "1.0", 
	url = "http://www.StudioADEPT.net"
};

public void OnLibraryAdded(const char[] name)
{
	if (!strcmp(name, "dr_shop"))
	{
		dr_RegisterService(ServiceName, ServiceCost, ServiceTeam);
	}
}

public bool PlayerTryBuy(int client) //Gracz kupił
{
	GivePlayerItem(client, "weapon_smokegrenade");
	return false; // GetPlayerBuySomethink <- true:false
}
public bool CanBuyService(int client)
{
	if (!dr_GetPlayerBuySomething(client)//jeżeli nic nie ma to może kupić && dr_GetMoneyAmount(client) >= ServiceCost && IsPlayerAlive(client)) //Czy Gracz może kupić
	{
		return true;
	}
	return false;
}

 


Dodatkowe info: Jak ktoś chce mieć 2 sklepy np. Ten i Zephrus wystarczy z tego usunąć RegConsoleCmd("sm_shop"); oraz RegConsoleCmd("sm_sklep);

 

Dziękuje Magnetowi za pomoc przy MySQL ?

 

 

dr_shop.inc
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

ADEPT_Deathrun_Shop_Module.sp
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

ADEPT_Flashbang.sp
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

ADEPT_Health.sp
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

ADEPT_Invisible.sp
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

ADEPT_LowGravity.sp
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

ADEPT_Respawn.sp
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

ADEPT_Smoke.sp
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

dr_shop.inc
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

Edited by Brum Brum
Aktualizacja inc
  • Lubię to! 5

Share this post


Link to post
Share on other sites

No fajnie, fajnie, ale... Plugin łączy się z bazą danych tylko przy starcie i jak nie wyjdzie, to kontynuuje działanie. Jeżeli się łączy tylko raz, to równie dobrze można go zatrzymać przez FailState, czy coś w ten deseń. Aczkolwiek nie wiem, czy o to tutaj chodzi. Rozwiązaniem w tym przypadku jest wielokrotne połączenie, czyli ponowna próba połączenia w przypadku nieudanej. ?

Share this post


Link to post
Share on other sites

Nie rozumiem czemu cały kod łączenia się z bazą wykonujesz w OnPluginStart. Przyjemniej dla oka by było zrobić to oddzielnie.

Lepiej moim zdaniem by było zrobić w OPS

 

DB_Connect();

 

Następnie wykonujemy połączenie do bazy w taki o sposób.

 

public Action DB_Connect()
{
	if(SQL_CheckConfig("DRShopDB"))
	{
		char DBBuffer[512];
		g_hSql = SQL_Connect("DRShopDB", true, DBBuffer, sizeof(DBBuffer));
		if (g_hSql == INVALID_HANDLE)
			LogError("[GO-CODE] Could not connect: %s", DBBuffer);
		else
		{
			SQL_LockDatabase(g_hSql);
			SQL_FastQuery(g_hSql, "CREATE TABLE IF NOT EXISTS `DRShop` (`auth_data` VARCHAR(64) NOT NULL, `name` VARCHAR(64) NOT NULL, `Money` INT NOT NULL, `AccountID` INT NOT NULL, UNIQUE KEY `auth_data` (`auth_data`)) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;");
			SQL_UnlockDatabase(g_hSql);
		}
	}
	else
		SetFailState("Nie mozna odnalezc konfiguracji 'DRShopDB' w databases.cfg.");
}

Oczywiście jest to kwestia gustu, jednak dla mnie jest wtedy kod bardziej przejrzysty no i łatwiej się w nim odnaleźć.

 

MOD_TAG mógłbyś zrobić w formie Cvaru i każdy mógłby sobie go zmodyfikować albo usunąć, dla osób które nie lubią za każdym razem kompilować pluginu gdy chcą coś w nim zmienić, ułatwia to użytkownikowi roboty i dodaje estetyki.

 

Nie miałem niestety czasu przejrzeć całości bo jestem w pośpiechu jednak moim zdaniem można tu wiele wiele poprawić, ale daje dużego + za wstawkę ;).

 

Również można by było zaopatrzyć się w wykorzystanie modułów do sklepu. 

Dodawanie dodatków do menu i opcji poprzez osobnego do tego pluginu, również poprawi to estetykę pluginu.

Share this post


Link to post
Share on other sites

O co Wam chodzi z tą bazą xD

 

@Mesharsky

 

To prawda, możesz wyrzucić łączenie z bazą danych do oddzielnej funkcji. Czy w tak małym pluginie to coś zmienia? Nie.

 

Jeśli chodzi o funkcję, to wykorzystujesz synchroniczną metodę do łączenia się z bazą, co jest jak najbardziej w porządku, bo najpierw zakładasz locka. Sprawdzenie konfiguracji też jest dobrym pomysłem. Czy jednak w ogólnym rozrachunku coś się zmienia? Nie, ponieważ 1. łączenie się z bazą i tak wykona się wcześniej od łączących się graczy 2. query graczy mają niższy priorytet od samego tworzenia tabeli (a będzie ono potrzebne tylko jeden raz - kiedy tabeli jeszcze nie ma)

By MAGNET,

SQL_CheckConfig można dodać, bo jest spoko

Share this post


Link to post
Share on other sites

@Mesharsky 
MOD_TAG Mogę zrobić pod ConVar
Co do modułowości to jeszcze tego nie umiem robić, jak się nauczę wtedy zrobię update sklepu z modułami, ale aktualnie nie ma co na to liczyć

 

  • Lubię to! 1

Share this post


Link to post
Share on other sites

@MAGNET Chodzi o to, że jak połączenie się nie uda, to działanie sklepu nie ma sensu, więc można zrobić ponowienie połączenia lub zatrzymać plugin, tak jak to zrobił @Mesharsky .

  • Lubię to! 2

Share this post


Link to post
Share on other sites
7 godzin temu, roki123h napisał:

Da rade do tego dodac modele do postaci, tagi, pety, traile?

@Brum Brum

Nie XD Możesz sobie dodać zephyrusa do tego tylko usuń z tego /shop /sklep i będzie dobrze zostanie Ci jeszcze /drshop

Edited by Brum Brum
  • Lubię to! 1
  • Haha! 1

Share this post


Link to post
Share on other sites

Mam pewien problem.

Sklep nie chce mi dzialac a po wpisaniu w konsoli sm plugins list wyskakuje cos takiego

 

Errors: ADEPT_Deathrun_Shop_Module.smx (ADEPT -> Deathrun Shop): Native "dr_IsPlayerTerrorist" was not found

Share this post


Link to post
Share on other sites
17 minut temu, kubix napisał:

Mam pewien problem.

Sklep nie chce mi dzialac a po wpisaniu w konsoli sm plugins list wyskakuje cos takiego

 

Errors: ADEPT_Deathrun_Shop_Module.smx (ADEPT -> Deathrun Shop): Native "dr_IsPlayerTerrorist" was not found

Jest napisane w poście, że ten sklep jest przygotowany pod mojego dr`a. Wyskakuje Ci błąd, bo nie może znaleźć rzeczy z tamtego deathruna 😉 

  • Kocham to! 1

Share this post


Link to post
Share on other sites
20 minut temu, laibach napisał:

Cześć Mam problem Nie mogę skompilować tych wtyczek tutaj jest błąd:

 

errory.jpg

nie pobrałeś pliku inc, bądź nie dodałeś go do folderu include

Share this post


Link to post
Share on other sites

Skoro kompilator wywala Ci taki błąd to nie wykrywa inc.
nSVGzix.png
Gdyby wykrywało inc nie pojawiłby się taki błąd.

Share this post


Link to post
Share on other sites

 inc wygląda następująco:

native int dr_GetMoneyAmount(int client);
native bool dr_RemoveMoney(int client, int count);
native bool dr_AddMoney(int client, int count);
native bool dr_SetMoney(int client, int count);

  • Lubię to! 1

Share this post


Link to post
Share on other sites
18 minut temu, laibach napisał:

 inc wygląda następująco:

native int dr_GetMoneyAmount(int client);
native bool dr_RemoveMoney(int client, int count);
native bool dr_AddMoney(int client, int count);
native bool dr_SetMoney(int client, int count);

hmm faktycznie. Już aktualizuje download.

  • Lubię to! 1

Share this post


Link to post
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.   Restore formatting

  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.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

Nasza historia

Na początku byliśmy małą grupą internetowych znajomych, którzy stwierdzili, że potrzebne jest solidne forum, na którym znajdą się ludzie z dużą wiedzą programistyczną ukierunkowaną na CS:GO. Pomysł powstał na początku 2018 roku, a parę miesięcy później, 19 kwietnia, powstała ta strona internetowa. Jako alternatywna odpowiedź na inne tego typu miejsca, poważnie podeszliśmy do tematu, najpierw tłumacząc angielską dokumentację SourceMod'a na język polski, a potem pisząc rozległe poradniki i wypełniając forum najpotrzebniejszymi rzeczami dla właścicieli serwerów i programistów. Cała nasza Ekipa jest dumna z pracy jaką w to włożyliśmy i cieszymy się że zbierają się wokół nas zarówno ludzie znający tematy sourcepawn'a i konfiguracji, jak i również nowe twarze w tym "biznesie", którym z chęcią niesiemy wiedzę oraz pomoc w rozwiązywaniu problemów.

Największe modyfikacje serwerowe

×
×
  • Create New...