664 zákazníckych serverů
80 TV kanálů
78002 registrovaných užívatelů
podporujeme youtubery a streamery

Skladba vlastního pluginu #1 – CS:GO VIP Plugin

Jistě každý někdy přemýšlel nad tím jak udělat svůj server originální a chtěl si složit svůj vlastní plugin. V tomto článku se vám pokusíme vysvětlit některé základní informace jak na to.
Nížší skladba pluginu je pouze výuční a nedoporučujeme ji používat na serverech.
Dejme tomu zadáme si cíle, které chceme aby měli VIP hráči. V našem případě tedy:

1. Větší HP na Spawnu
2. +5 HP za každý kill
3. VIP TAG v tabulce
4. Možnost Resetovat si Skore
5. VIP bude mít 100 Armoru na Spawnu a normální hráč 0
6. VIP bude mít Nižší Gravity
7. VIP bude mít o 0.2 větší damage

To by Zatím v Základu stačilo. Sami sobě jsme si dali cíle a teď už je jen stačí naprogramovat. Musíme však brát v úvahu, že když už programujeme vlastní pluginy tak si udržet nějakou tu originalito a né jen něco stáhnout z internetu a nebo kopírovat jiné servery. Jelikož na vás půjdeme ze začátku z lehka, stačí nám tedy obyčejný textový dokument, do kterého budeme psát kódy a pak webový compiler na adrese: http://www.sourcemod.net/compiler.php ... Celé programování spočívá v tom že my si nejdříve musíme napsat vlastní scripty a ty poté pomocí webového compileru převést na plugin. Plugin je totiž finální verze všeho našeho úsilí o změnu na serveru. Taky je důležité udržet si vlastní scripty přehlepdé a tak se v článku budu později vracet s vysvětlením co jednotlivé části znamenají.

Tak abych začal popisovat jak nejjednodušeji budeme postupovat při tvorbě našeho vlsatního prvního pluginu. Nejdůležitější částí pluginu jsou tzv. "include", to jsou soubory které mají v sobě uložené všechny částice, které různé příkazy potřebují ke správné funkčnosti. My tedy začneme s těmi základními. Do vytvořeného souboru začneme psát od začátku.
#include 
#include
#include
Další důležité jsou #define řádky, v našem případě si jimi ušetříme spoustu přepisování v pluginu při pozdějších úpravách a slouží něco jako odkazy. Například nastavíme si VIP na Rezervační Slot FLAG, pomůže nám to v tom, že když se později rozhodneme změnit FLAG, na kterým to bude nastavené > stačí nám změnit jeden řádek a né v několika desítkách pokud jsou naše výhody rozsáhlejší. Taky si nastavípe Prefix, což v našem případě bude něco jako odkaz na naše stránky, které se budou ukazovat jako začátek každé serverové zprávy v chatu. Písmenka vypadají takto: \x1-10 jsou barvy kterými se zprávy v chatu ukazují. Pak také hlavní argumenty které budeme v celém scriptu používat. A jedna z důležitýh věcí pluginu "Plugin:myinfo" , to slouží jako interní označení pluginu na serveru.
#define VIP ADMFLAG_RESERVATION
#define Prefix "\x4 \x6[GameHosting.cz] \x7"

new freevip[MAXPLAYERS+1] = 0;

public Plugin:myinfo =
{
name = "VIP Plugin",
author = "Miluska xD",
description = "VIP Plugin",
version = "1.0",
url = "www.GameHosting.cz"
}

Tak jsme si zapsali základní a potřebné Includy a Definice scripty můžeme pokročit k jednotlivým prvkům VIP Výhod. Nastavíme si tedy už na začátku, v rámci přehlednosti scriptu, nějaké ty výhody ať to máme vše pohromadě.
public SetClientSpeed(client)
{
if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", 1.2);
}
else
{
SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", 1.0);
}
}
public PerformGravity(client)
{
if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
SetEntityGravity(client, 0.7);
}
else
{
SetEntityGravity(client, 1.0);
}
}
public HandleTag(client)
{
if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
CS_SetClientClanTag(client, "[VIP]");
}
}
public Action:resetscore(client, args)
{
if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
EditScore(client);
}
}
void EditScore(int client)
{
SetEntProp(client, Prop_Data, "m_iFrags", 0);
SetEntProp(client, Prop_Data, "m_iDeaths", 0);
}

V prví řadě jste si všimli slov PUBLIC a nějaký název. To slouží jako název vyvolávací části začínající a končící závorkami. Závorky jsou důležité, protože jedna chybějící nám může pěkně zavařit. Řekněme že dostatečná angličtina nám pomůže si vysvětlit, co který název znamená. Samozřejmě musíme znát i cvary které používáme a chystáme se je měnit. Například ""m_flLaggedMovementValue", jak jste pochopili slouží k změně rychlosti. Dále "SetEntityGravity" ke změně gravitace a "CS_SetClientClanTag" jak nám již napovídá ke změně TAGu v tabulce. A nyní dál do příkazů serveru do chatu a hlavní funkce scriptu. K Resetování Score se dostaneme hned níže.
public OnPluginStart()
{
RegConsoleCmd("sm_rs", resetscore);

HookEvent("round_start", round_start);
HookEvent("player_spawn", hrac_spawn);
HookEvent("player_death", hrac_zemrel);
}

Řádky s označením: RegConsoleCmd slouží jako registrace příkazu pro vyvolání nějakého odkazu. V tomto případě vidíte "sm_rs" a "sm_shop". Tyto odkazy můžeme buď použít v console přesně tak jak je vidíme nebo pomocí chatu ovšem začátek "sm_" nahradíme lomítkem nebo vykřičníkem např.: !rs. Po napsání tohoto slova do chatu si náš VIP hráč vynuluje skóre jak cidíme výše u té rychlosti, gravity a tagu. Vidíte tam "public Action:resetscore(client, args)" přičemž Action (akce) s psaným argumentem (args) vyvolá danému VIP hráči (client) další odkaz, kterým je: "EditScore(client)" a ten o řádek níže vynuluje smrti a fragy. Místo registračních argumentů vidíte také základní systémy serverů: Spawn, Death a start kola. Začneme tedy u Spawnu a smrti protivníka.
public Action hrac_spawn(Handle event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(GetEventInt(event, "userid"));

freevip[client] = 1;

PerformGravity(client);
SetClientSpeed(client);
HandleTag(client);

if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
new health = 125;
SetEntityHealth(client,health);
SetEntProp( client, Prop_Send, "m_ArmorValue", 100, 1 );
}
else
{
new health = 100;
SetEntityHealth(client,health);
SetEntProp( client, Prop_Send, "m_ArmorValue", 0, 1 );
}

}
public Action:hrac_zemrel(Handle:event, const String:name[], bool:dontBroadcast)
{
new victim = GetClientOfUserId(GetEventInt(event, "userid"));
new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));

if (attacker != victim)
{
if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
new health[MAXPLAYERS+1];

health[attacker] = GetEntProp(attacker, Prop_Send, "m_iHealth");
SetEntityHealth(attacker, health[attacker] + 5);

}
}
}

Ve Spawnu už konečně vidíte na začátku odkazy ke spuštění speedu, gravity a tagu. Tyto odkazy se aktualizují při každém respawnutí hráče, aby nám nedocházelo k bugům. Dále rovnou si nastavíme naší další výhodu VIP hráčům, a tím je HP (život) a Armor (brnění) na začátku kola a NEVIP hráčům pro jistotu nastavíme také vlastní hodnoty. Také jste si už po několikáté všimli řádku "freegold[client]" na který už konečně přichází řada. Tímto si právě pro nás ve Spawnu hráče nastavíme pro různé víkendové eventy dle našeho přání zda povolíme naším hráčům VIP zdarma. A když se zakoukáme do řádku "if (GetUserFlagBits(client) & VIP || freevip[client] == 1) " tak vidíme: if = začínající podmínka se závorkou s nějakým argumentem, opak je ELSE a dále & a || to znamená: & = Rovná se neboli související... || = NEBO (v našem případě buď VIP Flag NEBO freevip) ... a později se střetnete i s && = A, zároveň. VIP hráčům tedy nastavíme health ("new health" každé nové číselné či slovní gesto musíme zapsat jako new) na 125 a obyčejným hráčům na 100. Dále cvar pro Armor používáme "m_ArmorValue" a nastavíme pro VIP 100 a obyčejným hráčům 0.

Další akce je: "Action:hrac_zemrel" co se tedy vlastně stane když hráč Zemře? Chtěli jsme výhodu pro VIP +5 HP za kill použijeme tedy stejný příkaz "SetEntityHealth" a útočníkovi (attacker) zapíšeme argument + 5 (+5 HP) při každém zabití. Určitě ste si také všimli že nyní je u "new health" použité: MAXPLAYERS+1 ... To proto že S "MAXPLAYERS+1" (new health[MAXPLAYERS+1]) je pouze pro jednoho clienta zatímco BEZ "MAXPLAYERS+1" (new health) určujeme celoserverově pro všechny.

A nakonec v poslední řadě základní registrací máme start kola. Do něj nepoužijeme momentálně nic než náš první ServerCommand. Ten se odesílá přímo do konzole serveru a my použijeme zrovna Reload Admins, to znamená že každé kolo se načtou nově přidané VIP a admini pokud je během kola (mapy) přidáme, nemusí tak čekat do konce mapy.

public Action round_start(Handle event, const char[] name, bool dontBroadcast)
{
ServerCommand("sm_reloadadmins");
}

A jedny z posledních výhod máme při napojení na server napsat zprávu do chatu, že se napojuje VIP hráč + aktivace většího damage.

public OnClientPutInServer(client)
{
if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
PrintToChatAll("%s VIP Hrac %N Se Pripojuje na Server",Prefix, client);
}
SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
}

public Action:OnTakeDamage(victim, &attacker, &inflictor, &Float:damage, &damagetype)
{
if (GetUserFlagBits(attacker) & VIP || freevip[attacker] == 1)
{
damage *= 1.2;
return Plugin_Changed;
}
return Plugin_Continue;
}

Tak a pro vysvětlení "OnClientPutInServer" je automatická základní předvolba inslude SOURCEMOD což znamená že jí dále nemusíme nikam zapisovat a znamená to tedy odkaz vyvolaný připojením hráče na server. Jako první tedy server zjistí zdali je připojující hráč VIP, pokud ano odešle všem na serveru do chatu Zpravu. Vysvětlivka argumentů: %s je odkaz na náš Prefix a tedy místo toho se ukáže náš DEFINE [GameHosting.cz] VIP Hrac %N je odkaz na jméno připojujícího se clienta a zbytek zprávy v uvozovkách. Za¨uvozovkami vidíme právě ty odkazy a POZOR ZÁLEŽÍ na jejich pořadí!!! Záměna odkazů nemusí třeba vůbec fungovat protože každé %s %i %N má svůj účel. %s = slovo , %i = číslo, %N = jméno.

Další a poslední naše chtěná výhoda je tedy odkazující na Action zvětšení damage. I tady tedy server zhodnotí zda je útočník VIP a pomocí našeho vzorce zvětšuje damage protivníka.

Náš finální plugin by tedy mohl vypadat po kupě nějak takto:

#include 
#include
#include

#define VIP ADMFLAG_RESERVATION
#define Prefix "\x4 \x6[GameHosting.eu] \x7";

new freevip[MAXPLAYERS+1] = 0;

public SetClientSpeed(client)
{
if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", 1.2);
}
else
{
SetEntPropFloat(client, Prop_Send, "m_flLaggedMovementValue", 1.0);
}
}
PerformGravity(client)
{
if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
SetEntityGravity(client, 0.7);
}
else
{
SetEntityGravity(client, 1.0);
}
}
HandleTag(client)
{
if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
CS_SetClientClanTag(client, "[VIP]");
}
}

public Plugin:myinfo =
{
name = "VIP Plugin",
author = "Miluska xD",
description = "VIP Plugin",
version = "1.0",
url = "www.GameHosting.cz"
}

public OnPluginStart()
{
RegConsoleCmd("sm_rs", resetscore);
HookEvent("round_start", round_start);
HookEvent("player_spawn", hrac_spawn);
HookEvent("player_death", hrac_zemrel);
}

public Action:resetscore(client, args)
{
if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
EditScore(client);
}
}

void EditScore(int client)
{
SetEntProp(client, Prop_Data, "m_iFrags", 0);
SetEntProp(client, Prop_Data, "m_iDeaths", 0);
}

public Action hrac_spawn(Handle event, const char[] name, bool dontBroadcast)
{
int client = GetClientOfUserId(GetEventInt(event, "userid"));

freevip[client] = 1;

PerformGravity(client);
SetClientSpeed(client);
HandleTag(client);

if (GetUserFlagBits(client) & VIP || freevip[client] == 1)
{
new health = 125;
SetEntityHealth(client,health);
SetEntProp( client, Prop_Send, "m_ArmorValue", 100, 1 );
}
else
{
new health = 100;
SetEntityHealth(client,health);
SetEntProp( client, Prop_Send, "m_ArmorValue", 0, 1 );
}

}
public Action:hrac_zemrel(Handle:event, const String:name[], bool:dontBroadcast)
{
new victim = GetClientOfUserId(GetEventInt(event, "userid"));
new attacker = GetClientOfUserId(GetEventInt(event, "attacker"));

if (attacker != victim)
{
if (GetUserFlagBits(attacker) & VIP || freevip[attacker] == 1)
{
new health[MAXPLAYERS+1];

health[attacker] = GetEntProp(attacker, Prop_Send, "m_iHealth");
SetEntityHealth(attacker, health[attacker] + 5);
}
}
}

public Action round_start(Handle event, const char[] name, bool dontBroadcast)
{
ServerCommand("sm_reloadadmins");
}

public Action:OnTakeDamage(victim, &attacker, &inflictor, &Float:damage, &damagetype)
{
if (GetUserFlagBits(attacker) & VIP || freevip[attacker] == 1)
{
damage *= 1.2;
return Plugin_Changed;
}
return Plugin_Continue;
}

public OnClientPutInServer(client)
{
SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage);
}

Tak jsme si ukázali velice jednoduchý příklad jak by mohlo vypadat pár VIP výhod, samozřejmě jich jde vymyslet i naprogramovat několik desítek a to skiny, oznámení na server, reklamy, bez reklam atd atd atd ale to kdybychom to tu měli vše udělat tak máme plugin o několika tisících řádkách. My však pouze v návodu uvádíme příklad jak by toto mohlo vymapat a pomoci něco přiučit. A v příštím článku se už můžeme podívat na trochu náročnější plugin nebo jak si vlastně zřídit svůj vlastní herní portál nebo pomoci s instalací programu přímo do vašeho PC abychom nemuseli stále používat náročně Web Compiler.

10.03.2016

Komentáře

[09.03.2026 13:41] Jeromeherman
HOW TO RECOVER FUNDS LOST IN FOREX TRADING, CRYPTO INVESTMENT OR CRYPTO TRADING If you have fallen victim to a Bitcoin or crypto investment scam and have lost funds, it can be a devastating experience. However, there are steps you can take to try and recover your lost funds. One option is to contact GEO COORDINATES RECOVERY HACKER, a company that specializes in recovering funds lost to scams. Their services proved invaluable in my case, and their success in recovering my funds has been a tremendous relief. They have the skills and knowledge required to tackle such complex issues and provide effective solutions. I hope my story helps others who might be struggling with similar issues and encourages them to take action to recover their losses. Reach out to GEO COORDINATES RECOVERY HACKER via contact details Email: [email protected] Telegram @Geocoordinateshacker Website; https://geovcoordinateshac.wixsite.com/geo-coordinates-hack