Patrząc na poczynania innych użytkowników, dążacych do wprowadzenia was w tajniki programowania pluginów do CS 1.6 w AMXX, poczułem się lekko zniesmaczony.
Dlatego przybywam z pomocą 🙂 Dziś dowiesz się wystarczająco wielu rzeczy, które mogą przydać Ci się w zabawie pluginami, gdzie jedynym ograniczeniem będą Twoje umiejętności ( no i wyobraźnia 😛 )
AMXX - Czym właściwie jest?
A więc, przejdźmy do rzeczy. Czym jest AMXX? Wielu ludzi czasami zadaje sobie to pytanie. Odpowiedź czeka tuż za rogiem, czytaj dalej drogi kolego.
Czego potrzebuję?
Zakładając, że podejmiesz się tego wyzwania, potrzebna Ci będzie wiedza z zakresu jednego z dwóch języków programowania:
Pawn (prosty 32- oraz 64-bitowy język skryptowy) - w składni podobny do C, stąd też niewiele od niego się różniący
C (ta opcja jest już dla bardziej wymagających od siebie programistów) - fakt faktem, C jest niekiedy lepszy, ale nie oznacza to zawsze.
A także:
Gry opartej na silniku Half-Life ( Counter-Strike 1.6 jest chyba najwygodniejszą opcją, nieprawdaż? )
Silnika AMX Mod X zainstalowanego na silniku gry
Cierpliwości i chęci do nauki
Zdolności czytania dokumentacji AMXX
AMXX Studio ( IDE domyślnie instalowanym wraz z silnikiem AMXX )
Okej, mam to. Co dalej?
No cóż, to chyba pora na pierwszy skrypt, czyż nie?
Po uruchomieniu AMXX Studio ( zwykle jego ikona powinna pojawić się na pulpicie, po zainstalowaniu silnika ) przywita Cię prosty snippet code:
OH! No tak, wybacz, zapomniałem wspomnieć że AMXX Studio to bardzo proste, ale jednak IDE (Zintegrowane środowisko programistyczne (od ang. integrated development environment) – program lub zespół programów (środowisko) służących do tworzenia, modyfikowania, testowania i konserwacji oprogramowania.). Zero podpowiadania składni ( nie, to nie Visual Studio Code xD ), tylko Ty i Twój pomysł, no i edytor.
Wracając, oto snippet:
Po kolei:
#include <amxmodx> // Tutaj widzisz import
#include <amxmisc> // potrzebnych bibliotek
// Deklaracje zmiennych przyjmujących niezmienne wartości
#define PLUGIN "New Plug-In" // Nazwa pluginu
#define VERSION "1.0" // Wersja wtyczki
#define AUTHOR "author" // Autor wykonujący wtyczkę
public plugin_init() { // Publiczna funkcja ( forward plugin_init() ). Więcej wyjaśnień później
register_plugin(PLUGIN, VERSION, AUTHOR) // Rejestracja pluginu w silniku ( tak, aby potem mógł on zostać załadowany i zinterpretowany )
// Tutaj dodajesz swój własny kod
}
Okej, wracając do forwardu plugin_init()... Jest to forward który zawsze, ale to zawsze ma wykonywać się PIERWSZY. Dobrym nawykiem byłoby tutaj zawarcie wszelkich najpotrzebniejszych cvarów, eventów, wiadomości oraz komend. Od tego forwardu bowiem zaczyna się interpretowanie wtyczki.
Too... Jaki plugin napiszemy? Hmm, może tabelę wyników na HUD, tak jak w CS:GO, tylko nieco inaczej?
Fine.
Zaczynajmy. Ostrzegam, to gotowy kod, więc uważnie się z nim zapoznaj, nie przepisuj, choć nie bronię nawet skopiować, tylko się czegoś naucz. Robię to wyłącznie dlatego, że i tak wprowadzenie się lekko przedłuża 😛
#include <amxmodx>
#include <amxmisc>
#include <dhudmessage> // Include przydatny do wyświetlania napisów na HUDzie z perspektywy gracza
#define PLUGIN "Score Board" // Nazwa pluginu
#define VERSION "1.0" // Wersja wtyczki
#define AUTHOR "InFiNiTy" // Autor wykonujący wtyczkę
/*
Wygrane zespołów
*/
new TTWins;
new CTWins;
/*
Zespoły
*/
new TT;
new CT;
/*
Zmienne pomocnicze
*/
new Float:round_start = -1.0; // Czas rozpoczęcia rundy
new Float:round_time; // Czas trwania rundy
new mp_roundtime; // Zmienna przechowująca wartość z predefiniowanego serwerowo cvaru mp_roundtime
new round = 0 // Ilość rund
public plugin_init() {
register_plugin(PLUGIN, VERSION, AUTHOR)
/* Taski */
set_task(1.0, "scoreboard", 0, "", 0, "b")
// Task będzie wywoływany co sekundę, odwołując się do funkcji scoreboard, z id = 0, bez parametrów, bez parametrów dodatkowych, z flagą b ( powtarzanie w nieskończoność ).
// Po dokładniejsze informacje odsyłam do dokumentacji ( link wyżej )
/* Cvary */
register_cvar("t_pref", "TT")
register_cvar("ct_pref", "CT")
/* Eventy */
register_event("SendAudio", "tt_win", "a", "2&%!MRAD_terwin") // Wygrana TT
register_event("SendAudio", "ct_win", "a", "2&%!MRAD_ctwin") // Wygrana CT
/* Zdarzenia serwerowe */
register_logevent("EventRoundStart", 2, "1=Round_Start"); // Start rundy
register_logevent("EventRoundEnd", 2, "1=Round_End"); // Koniec rundy
register_logevent("GameCommencing", 2, "1=Game_Commencing"); // Rozpoczęcie rozgrywki
register_event("HLTV", "event_new_round", "a", "1=0", "2=0"); // Kompatybilność z HLTV ( pod względem działania )
register_event("TextMsg", "EventRoundRestart", "a", "2&#Game_C", "2&#Game_w"); // Restart rundy
mp_roundtime = get_cvar_pointer("mp_roundtime"); // Pobranie wartości predefiniowanego cvara mp_roundtime (czas rundy w sekundach)
}
public GameCommencing(){ // Rozpoczęcie rozgrywki
round=0;
}
public event_new_round(){ // Nowa runda
round++;
}
// Główna funkcja - HUD Scoreboard
public scoreboard() {
new TPrefix[512],CTPrefix[512];
get_cvar_string("t_pref",TPrefix,charsmax(TPrefix));
get_cvar_string("ct_pref",CTPrefix,charsmax(CTPrefix));
new iPlayers[32];
get_players(iPlayers, TT, "ae", "TERRORIST");
get_players(iPlayers, CT, "ae", "CT");
new Float:RoundTime = get_roundtime_left();
new RTF = floatround(RoundTime,floatround_round);
switch(get_pcvar_num(hud_d)) { // Switch między wyglądem HUDu
case(1): {
set_dhudmessage(0, 255, 0, 0.37, 0.05, 0, 6.0, 1.0, 0.0, 0.1, false)
show_dhudmessage(0, "%s [ %i ] --< %i >-- [ %i ] %s", TPrefix, TTWins, RTF, CTWins, CTPrefix)
}
case(2): {
set_dhudmessage(0, 255 ,0, -1.0, 0.05, 0, 6.0, 1.0, 0.0, 0.1, false)
show_dhudmessage(0, "%s: [ %i ] < $i > [ %i ] %s", TPrefix, TTWins, RTF, CTWins, CTPrefix)
}
}
}
// Wygrana TT
public tt_win() {
if(get_playersnum() < 2) return
TTWins++
}
// Wygrana CT
public ct_win() {
if(get_playersnum() < 2) return
CTWins++
}
public EventRoundStart() {
round_start = get_gametime();
round_time = get_pcvar_float(mp_roundtime) * 60.0
}
public EventRoundEnd() {
round_start = -1.0
}
public EventRoundRestart() {
round_start = -1.0
CTWins = 0
TTWins = 0
}
stock Float:get_roundtime_left() // Określenie "stock" oznacza, że interpreter ma ominąć tą funkcję podczas kompilacji ( pozostawić ją nienaruszoną )
return (round_start == -1.0) ? 0.0 : ((round_start + round_time) - get_gametime());
No i tyle! Efektów niestety pokazać nie mogę, ale sami przekonacie się na własne oczy, że działa, i to jak 🙂