MAGNET 2 1 2 1 Napisano 7 Maja 2020 Przedstawiam drugą odsłonę pluginu, który pozwala w prosty sposób tworzyć własne osiągnięcia/misje na serwerze. Poprzednia wersja zawierała dużo niedociągnięć i była napisana po prostu brzydko. Liczę, że modyfikacja przypadnie do gustu osobom, które mają w planach stworzenie własnego systemu misji i szuka wygodnego rozwiązania 🙂. Jak to działa? Plugin daje dostęp do funkcji natywnych i forwardów, które pozwalają na tworzenie achievementów/misji i zarządzanie nimi z poziomu dowolnego pluginu. Dzięki temu możliwa jest rozbudowa istniejących już pluginów (np. modyfikacje CodMod, Jailbreak, czy jakikolwiek plugin sobie nie wymyślicie) i tworzenie bardzo ciekawych, nietuzinkowych wyzwań. Komendy: sm_ac sm_achievements sm_mission sm_missions Konfiguracja 1. Zawartość paczki wrzuć na serwer 2. Zdecyduj w jakiej bazie danych chcesz zapisywać informacje - MySQL czy SQLite? Zależnie od odpowiedzi, wklej do addons/sourcemod/configs/databases.cfg następującą konfigurację: Dla SQLite: "AchievementsGO" { "driver" "sqlite" "database" "AchievementsGO" } Dla MySQL: "AchievementsGO" { "driver" "mysql" "host" "HOST" // edytuj "database" "AchievementsGO" // edytuj (opcjonalnie) "user" "USER" // edytuj "pass" "HASLO" // edytuj //"timeout" "0" "port" "PORT" // edytuj, domyslnie 3306 } 3. Twórz 🙂 Jak stworzyć swój achievement/misję? Oto przykładowy plugin: Spoiler #include <AchievementsGO> int missionOne; int missionTwo; int missionThree; int missionFour; int missionFive; public void OnPluginStart() { RegConsoleCmd("sm_pkt", FreePoint); } public Action FreePoint(int client, int args) { AGO_AddPoint(client, missionOne); } public void AGO_OnRegisterAchievements() { AGO_AddAchievement("Mistrz pisania", "Type !pkt 5 times", "", 5, 1, OnIdGranted); AGO_AddAchievement("Misja pierwsza", "Opis misji pierwszej\nNagroda: XXX", "", 60, 2, OnIdGranted); AGO_AddAchievement("Misja druga", "Opis misji pierwszej\nNagroda: XXX", "Katalog 1", 50, 3, OnIdGranted); AGO_AddAchievement("Misja trzecia", "Opis misji pierwszej\nNagroda: XXX", "Katalog 1", 11, 8, OnIdGranted); AGO_AddAchievement("Misja czwarta", "Opis misji pierwszej\nNagroda: +10HP", "Katalog 2", 48, 1027, OnIdGranted); } public void AGO_OnPlayerAchievementsLoaded(int client) { if (AGO_IsAchievementCompleted(client, missionFive)) { // tutaj jakiś kod, dający graczowi 10HP po odrodzeniu (np. jakaś flaga etc.) } } public void OnIdGranted(int achievementID, int temporaryID) { switch(temporaryID) { case 1: { missionOne = achievementID; } case 2: { missionTwo = achievementID; } case 3: { missionThree = achievementID; } case 8: { missionFour = achievementID; } case 1027: { missionFive = achievementID; } } } Miejscem, gdzie rejestrujemy achievementy musi być być funkcja AGO_OnRegisterAchievements(). W niej korzystamy z AGO_AddAchievement, który posiada kilka argumentów: native bool AGO_AddAchievement(char[] Name, char[] Description, char[] Category, int Value, int temporaryID, Function functionCallback); Name - nazwa, Description - opis, Category - folder, od którego zostanie przypisane osiągnięcie. Pozwala to na organizowanie/grupowanie misji według własnych upodobań. Zotawiając to pole puste (""), osiągnięcie będzie po prostu bez żadnej kategorii, Value - jest to ilość punktów, która musi zostać osiągnięta, aby zadanie mogło zostać zaliczone. Może to reprezentować dowolną rzecz, np. liczbę wymaganych killi, liczbę kroków, które gracz musi wykonać itd., temporaryID - pomocniczy identyfikator, który pozwala na zidentyfikowanie osiągnięcia, kiedy zostanie ono zarejestrowane przez silnik i jego identyfikator trafi do callbacka. Musi on być unikalny jedynie w obrębie pojedyńczego pluginu, w którym implementujemy osiągnięcia, functionCallback - każdej misji przypisany jest niezależny identyfikator. Ten parametr to po prostu funkcja, do której ta informacja ma trafić. W poprzedniej wersji ID misji były po prostu przekazywane przez returna (np. int misjaX = AGO_AddAchievement....), jednak wymagało to mieszania zapytań synchronicznych i asynchronicznych - obecne rozwiązanie eliminuje ten problem. Mając już ID, przypisane do jakiejś zmiennej, możemy zająć się procesem dodawania punktów. Najczęściej stosowane będzie AGO_AddPoints (jak pokazano w przykładzie, w którym osiągnięcie "Mistrz pisania" można zdobyć, wpisując pięciokrotnie komendę !pkt), ale dostępnych jest parę funkcji, które podam poniżej: Plik AchievementsGO.inc (spolszczony): Spoiler #if defined _AchievementsGO_included_ #endinput #endif #define _AchievementsGO_included_ /** * Dodaje nowe osiągnięcie. Operacja musi zostać wykonana w funkcji AGO_OnRegisterAchievements() * aby mieć pewność, że wszystko zostanie poprawnie załadowane * * @param Name Nazwa osiągnięcia (max 64 znaki) * @param Description Krótki opis (max 128 znaków) * @param Category Kategoria(folder) osiągnięcia. Jeśli chcesz, aby misja znajdowała się w sekcji głównej, zostaw ten argument pusty ("") * @param Value Ustawia cel (liczbę punktów), które trzeba zdobyć, aby uznać achievement za zakończony * @param temporaryID Pomocnicza wartość, która trafia do handlera. Pomaga zidentyfikować osiągnięcie. Zajrzyj do przykładu, aby lepiej zrozumieć działanie * @param functionCallback Funkcja, która zostanie wywołana po tym, jak osiągnięcie zostanie załadowane. Zajrzyj do przykładu * @return true if achievement will be inserted. false otherwise */ native bool AGO_AddAchievement(char[] Name, char[] Description, char[] Category, int Value, int temporaryID, Function functionCallback); /** * Dodaje jeden punkt do osiągnięcia gracza. Nie działa, jeśli achievement został już ukończony * * @param client ID gracza * @param IdOfAchievement ID osiągnięcia (uzyskane z funkcji AGO_AddAchievement()) * @return Aktualny postęp osiągnięcia, lub -1 w razie niepowodzenia */ native int AGO_AddPoint(int client, int IdOfAchievement); /** * Dodaje punkty do osiągnięcia gracza. Nie działa, jeśli achievement został już ukończony * * @param client ID gracza * @param IdOfAchievement ID osiągnięcia (uzyskane z funkcji AGO_AddAchievement()) * @param amount Ilość punktów, która ma zostać przydzielona * @return Aktualny postęp osiągnięcia, lub -1 w razie niepowodzenia */ native int AGO_AddPoints(int client, int IdOfAchievement, int amount); /** * Usuwa jeden punkt z osiągnięcia gracza. Nie działa, jeśli achievement został już ukończony * * @param client ID gracza * @param IdOfAchievement ID osiągnięcia (uzyskane z funkcji AGO_AddAchievement()) * @return Aktualny postęp osiągnięcia, lub -1 w razie niepowodzenia */ native int AGO_RemovePoint(int client, int IdOfAchievement); /** * Usuwa punkty z osiągnięcia gracza. Nie działa, jeśli achievement został już ukończony * * @param client ID gracza * @param IdOfAchievement ID osiągnięcia (uzyskane z funkcji AGO_AddAchievement()) * @param amount Ilosć punktów, która ma zostać zabrana * @return Aktualny postęp osiągnięcia, lub -1 w razie niepowodzenia */ native int AGO_RemovePoints(int client, int IdOfAchievement, int amount); /** * Resetuje postęp achievementu. Oznacza go również jako nieskończony * * @param client ID gracza * @param IdOfAchievement ID osiągnięcia (uzyskane z funkcji AGO_AddAchievement()) * @return true, jeśli reset się powiódł. W innym przypadku - false */ native bool AGO_ResetAchievement(int client, int IdOfAchievement); /** * Ustawia konkretną liczbę punktów danemu achievementowi. Nie działa, jeśli achievement został już ukończony * * @param client ID gracza * @param IdOfAchievement ID osiągnięcia (uzyskane z funkcji AGO_AddAchievement()) * @param amount Liczba punktów, która ma zostać ustawiona * @return Aktualny postęp osiągnięcia, lub -1 w razie niepowodzenia */ native bool AGO_SetPoints(int client, int IdOfAchievement, int amount); /** * Pobiera nazwę osiągnięcia na podstawie ID * * @param IdOfAchievement ID osiągnięcia (uzyskane z funkcji AGO_AddAchievement()) * @param tab buffer na nazwę * @param size rozmiar buffera * @return 0 w razie powodzenia. W razie porażki: -1, a buffer zawiera frazę "NOT_FOUND" */ native void AGO_GetNameByIndex(int IdOfAchievement, char[] tab, int size); /** * Zwraca index osiągnięcia w oparciu o jego nazwę * * @param name Nazwa osiągnięcia * @return ID achievementa w razie powodzenia. Jeśli porażka: zwraca -1 */ native int AGO_GetIndexByName(char[] name); /** * Pobiera opis osiągnięcia na podstawie ID * * @param IdOfAchievement ID osiągnięcia (uzyskane z funkcji AGO_AddAchievement()) * @param tab buffer na opis * @param size rozmiar buffera * @return 0 w razie powodzenia. W razie porażki: -1, a buffer zawiera frazę "NOT_FOUND" */ native void AGO_GetDescriptionByIndex(int IdOfAchievement, char[] tab, int size); /** * Zwraca aktualny postęp achievementu * * @param client ID gracza * @param IdOfAchievement ID osiągnięcia (uzyskane z funkcji AGO_AddAchievement()) * @return Aktualny postęp osiągnięcia w razie sukcesu. W razie porażki: zwraca -1 */ native int AGO_GetAchievementProgress(int client, int IdOfAchievement); /** * Sprawdza, czy dany achievement został ukończony * * @param client ID gracza * @param IdOfAchievement ID osiągnięcia (uzyskane z funkcji AGO_AddAchievement()) * @return true - zakończony. false - nie ukończony, lub niepoprawne ID */ native int AGO_IsAchievementCompleted(int client, int IdOfAchievement); /** * Zwraca liczbę aktywnych achievementów * * @return Liczba aktywnych achievementów */ native int AGO_GetAmountOfAchievements(); /** * Sprawdza, czy tablice w SQL zostały prawidłowo utworzone * * @return 1 - tablice utworzenie. 0 - nieutworzone */ native int AGO_AreTablesCreated(); /** * Aktualizuje dane gracza w SQL (program robi to samoczynnie. Używaj, gdy uważasz za konieczne). * * @param client ID gracza * @return 1: sukces. 0: porażka */ native void AGO_UpdatePlayer(int client); /** * Wywoływany, gdy wszystkie osiągnięcia zostaną załadowane */ forward void AGO_OnAllAchievementsLoaded(); /** * Wywoływane, gdy gracz ukończy osiągnięcie * * @param client ID gracza * @param IdOfAchievement ID osiągnięcia (uzyskane z funkcji AGO_AddAchievement()) */ forward void AGO_OnAchievementAccomplished(int client, int IdOfAchievement); /** * Wywoływany, gdy silnik jest gotowy to rejestrowania osiągnięć. Proces ten musi odbywać się w tej funkcji */ forward void AGO_OnRegisterAchievements(); /** * Wywoływany, gdy status wszystkich osiągnięć zostanie załadowany po połączeniu się gracza z serwerem * * @param client ID gracza */ forward void AGO_OnPlayerAchievementsLoaded(int client); AchievementsGO.cfg: Spoiler // Pokazywać powiadomienie na czacie wszystkim graczom, gdy ktoś ukończy achievement? // - // Default: "1" ago_achievement_notification_all "1" // Pokazywać powiadomienie graczowi o ukończonym osiągnięciu na czacie? // - // Default: "1" ago_achievement_notification_chat "1" // Pokazywać powiadomienie graczowi o ukończonym osiągnięciu w HintText? // - // Default: "1" ago_achievement_notification_hint "1" //Po ilu dniach nieaktywności gracza jego rekordy będą usuwane z bazy? (0 - wyłączone, niezalecane) // - // Default: "30" ago_database_time_kick "30" // Minimalna liczba graczy, od której osiągnięcia będą naliczane? // - // Default: "3" ago_players_amount "3" Na koniec screeny z mojego serwera, gdzie zacząłem tworzenie misji (serwer CodMod): Spoiler Download: Repozytorium GitHubHej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami! Bezpośredni downloadHej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami! Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach
KatowADRE Napisano 9 Maja 2020 Czy jesteś w stanie zrobić gotową paczkę z misjami na zamówienie? Jeżeli tak, to prosiłbym o kontakt w tej sprawie. Jestem w stanie nawet zapłacić za robotę. 🙂 pozdrawiam, Cytuj Przez MAGNET, 9 Maja 2020 To napisz do mnie na PW jakie to mają być misje, jaki zakres i ile jesteś w stanie zapłacić Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach
Gość Napisano 9 Maja 2020 Również jestem dyspozycyjny w zakresie pisania misji na zlecenie. 🙂 Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach
KatowADRE Napisano 10 Maja 2020 Prosiłbym was o kontakt ze mną na STEAM priv. Ponieważ jestem w delegacji, a ciężko mi wchodzić na forum.. Na STEAM się dogadamy. https://steamcommunity.com/id/twitchkatow Cytuj Udostępnij tę odpowiedź Odnośnik do odpowiedzi Udostępnij na innych stronach