Jak powinienem sprawdzić, czy gracz osiągnął osiągnięcie?

13

Tworzę grę MMO i właśnie doszedłem do momentu, w którym muszę wdrożyć osiągnięcia ... Jak to zrobić? Najprostszą rzeczą do zrobienia byłoby uruchomienie tego raz na 100 ms:

for a in achievements
    for p in players
        if a.meetsRequirements(p) then p.completeAchievement(a)

Ale to tylko powoduje jeszcze więcej komplikacji. Na przykład, jak sprawdzić, czy osiągnięcie zostało rzeczywiście ukończone? Czy gracze mają na sobie niestandardowe właściwości tylko dla konkretnego osiągnięcia? Robiłem coś takiego z zadaniami, ponieważ są one głównie „zbierz 100 drewna”, więc aktywne zadania u gracza to sprawdzają. Ponadto musi być lepszy moment, aby to sprawdzić, co moim zdaniem spowalnia okresowo mój serwer.

jcora
źródło
7
Dlaczego po prostu nie wykonasz odpowiednich kontroli, gdy działania zostaną wykonane? To znaczy, jeśli użytkownik zbiera drewno, sprawdź, czy odpowiada specyfikacji „zbierz 100 drewna”.
Mike Cluck
1
Ten rodzaj wydaje się zbyt bałaganiarski ... Wszędzie byłoby mnóstwo czeków. Myślę, że będę trzymać się powyższego algorytmu ze względu na jego prostotę ...
jcora,
10
Istnieją sposoby na zmniejszenie bałaganu: na przykład obsługa zdarzeń „OnChange”, a następnie dołączanie do nich „obiektów” osiągnięć i obsługiwanie logiki. Zrozum także, że przy obecnym ustawieniu masz poziom złożoności O (n ^ 2), co oznacza, że ​​gra staje się wolniejsza z większą liczbą postaci. Rodzaj problemu dla MMO
Mike Cluck,

Odpowiedzi:

23

To, co robisz, zależy od charakteru osiągnięcia. O ile wszystkie twoje osiągnięcia nie pasują do prostego wzorca (zbierz X liczby Y), będziesz musiał je do pewnego stopnia w specjalnym przypadku.

Korzystając z systemu komunikacji opartego na komunikatach, można zapewnić haczyki, które umiejscawiają kodowanie specjalnych przypadków. Możesz mieć określone działania wysyłające wiadomości do słuchaczy, którzy się zarejestrują. Następnie Twój kod / skrypt osiągnięć może po prostu zarejestrować się u odpowiednich słuchaczy i wykonać wszystko, co jest konieczne do odpalenia osiągnięcia.

Będziesz mieć wiadomości o typowych wydarzeniach, których oczekujesz od osiągnięć. Rzeczy takie jak „gracz zdobył przedmiot X” lub „jednostka Y zabiła jednostkę Z”. W ten sposób możesz śledzić np. Liczbę Z, które zabił gracz.

To chyba najlepsze, co możesz zrobić dla systemu osiągnięć. Centralizuje kod tak bardzo, jak to możliwe, i nakłada na słuchaczy ciężar rzeczywistego wykrywania osiągnięć.

Należy również zauważyć, że w przypadku scentralizowanych systemów osiągnięć (X-Box Live, osiągnięcia Steam) postęp w kierunku osiągnięć jest zwykle zapisywany na serwerze. Tak więc w przypadku osiągnięć akumulacji („wykonaj zadanie XY wiele razy”) skrypt osiągnięć wykrywa tylko, kiedy X zostało wykonane, i zlicza liczbę serwerów. W przypadku innych osiągnięć („wykonaj zadanie X”) osiągnięcie serwera jest binarne: albo to zrobiłeś, albo nie.

Nicol Bolas
źródło
+1 To jest świetna informacja. Przydatne nawet bez potrzeby wdrażania osiągnięć w tym czasie.
Joshua Hedges
Dzięki! Nie mogę się doczekać, aby to wdrożyć, chciałbym mieć ten pomysł wcześniej ...
jcora,
3

W zależności od charakteru twoich osiągnięć możesz również wprowadzić pewnego rodzaju „osiągnięcia znaczników”.

Jeśli masz na przykład 3 kolejne osiągnięcia:
Drewno 1 - Zbierz 100 drewna
Drewno 2 - Zbierz 500 drewna
Drewno 3 - Zbierz 1 tys. Drewna

W takim przypadku warto zarejestrować zdarzenie OnChange dla pierwszego osiągnięcia, dopóki gracz go nie ukończy. Po zakończeniu możesz zarejestrować kolejny obiekt osiągnięcia.

To oczywiście wymaga zaprojektowania (lub obliczenia) drzewa zależności osiągnięć.

Książe Charles
źródło