Skocz do zawartości
  • 0

Skrypt na wyrzucanie itemów do skrzynki nie działa.


Pytanie

Jeżeli gracz zginie bezpośrednio z ręki innego gracza (np. przez miecz), pojawia się w miejscu jego śmierci skrzynia, w której jest 50% itemów. Niestety przy śmierci od voida, ta skrzynka nie pojawia się. Czy mógłbym prosić o pomoc? Zamieszczam cały skrypt:

 

on join:
    set {combat.%player%} to false

on damage:
    if {combat.%victim%} is false:
        attacker is player
        if victim isn't wearing armor:
            cancel event
            stop
    if {combat.%victim%} is false:
        attacker is player
        if attacker isn't wearing armor:
            cancel event
            stop
            
    
    attacker is player
    victim is player
    set {combat.attacker.%{_p}%} to "%attacker%"
    set {combat.victim.%{_p}%} to "%victim%"
    combat(victim)
    combat(attacker)

function combat(p: player):
    
    if {combat.%{_p}%} is false:

        set {combat.%{_p}%} to true
        set {combat.cooldown.%{_p}%} to 16

        while {combat.cooldown.%{_p}%} is not 0:

            remove 1 from {combat.cooldown.%{_p}%}
            send actionbar "&4&lIn combat &6for &4&l%{combat.cooldown.%{_p}%}% &6seconds. Don't log out." to {_p}
        

            if {combat.cooldown.%{_p}%} is 0:
                set {combat.%{_p}%} to false
                send actionbar "&6You are no longer in &4&lcombat&6. You can &4&llog out &6now." to {_p}
                delete {combat.attacker.%{_p}%}
                delete {combat.victim.%{_p}%}


            wait 1 second
    else:
        set {combat.cooldown.%{_p}%} to 16


command /ct:
    permission: sc.clearCombatLog
    trigger:
        set {combat.cooldown.%player%} to 0
        set {combat.%player%} to false

on quit:
    if {combat.%player%} is true:
        kill player
        set {combat.%player%} to false
        set {combat.cooldown.%player%} to 0

on death:
    if victim's world is "World1":

        set {_loc} to victim's location
        set block at location at {_loc} to chest

        loop all items in victim's inventory:
            chance of 50%:
                add loop-item to {_items::*}
           
        loop all blocks in radius 2 around victim:
            if loop-block is chest:
                loop {_items::*}:            
                    add loop-value-2 to loop-block's inventory
                    remove loop-value-2 from {_items::*}
                    remove loop-value-2 from victim's inventory


        

        wait 30 seconds
        set block at location at {_loc} to air
        
on death:    
    if {combat.%victim%} is true:
        send actionbar "&6You are no longer in &4&lcombat&6. You can &4&llog out &6now." to attacker and victim
        set death message to "%victim% got &4&lkilled &fby %attacker%"
        set {combat.%victim%} to false
        set {combat.cooldown.%victim%} to 0

on command:
    if {combat.%player%} is true:
        if command isn't "ct":
            send actionbar "&4&lYou are not allowed to use commands during combat!"
            cancel event


on step on lime carpet:

    if {combat.%player%} is false:
        push player north at speed 3
        push player up at speed 2

on damage:
    if damage was caused by void:
        if {combat.%victim%} is true:
            if {combat.attacker.%{_p}%} isn't victim:
                teleport victim to location of ({combat.attacker.%{_p}%} parsed as a player)
                wait 1 ticks
                kill victim
            else:
                teleport victim to location of ({combat.victim.%{_p}%} parsed as a player)
                wait 1 ticks
                kill victim
                

        else if {combat.%victim%} is false:
            set {_p} to victim's world
            teleport victim to location(-37.5, 28, -91.5, {_p}, 0, 0)
            cancel event
 

Odnośnik do komentarza
https://skript.pl/temat/57393-skrypt-na-wyrzucanie-item%C3%B3w-do-skrzynki-nie-dzia%C5%82a/
Udostępnij na innych stronach

3 odpowiedzi na to pytanie

Rekomendowane odpowiedzi

  • 0
4 godziny temu, zygiszu napisał:

Jeżeli gracz zginie bezpośrednio z ręki innego gracza (np. przez miecz), pojawia się w miejscu jego śmierci skrzynia, w której jest 50% itemów. Niestety przy śmierci od voida, ta skrzynka nie pojawia się. Czy mógłbym prosić o pomoc?

Jak Pan chce sprawić, aby skrzynka pojawiła się w próżni/otchłani? Współrzędna Y bloków musi należeć do przedziału [-64;319], tak więc niemożliwym jest stawianie bloków poniżej dolnej granicy tego przedziału bez użycia odpowiednich modyfikacji na serwerze.

EDIT:
Pragnę dodać, że Pana skrypt jest napisany w sposób ignorujący dobre praktyki. Podam dwa moim zdaniem najważniejsze problemy z tym kodem.

  1. Zmienne gracza są zapisywane jako pojedyncze, niezależne zmienne, a nie listy, co jest złym rozwiązaniem. Jeśli Pan będzie miał potrzebę wyczyszczenia, bądź, co gorsza, zapętlenia listy, nie będzie to taka prosta w wykonaniu operacja.
    # Zła praktyka:
    
    set {combat.%player%} to true
    set {combat.attacker.%{_p}%} to victim
    
    # Dobra praktyka:
    
    set {combat::%player%} to true
    set {combat::attacker::%{_p}%} to victim
    
    # Dzięki takiemu zabiegowi jesteśmy w stanie łatwo manipulować tymi listami. Przykłady poniżej.
    
    clear {combat::*}
    clear {combat::attacker::*}
    loop {combat::*}:
    	# ...
  2. Dodawanie dużych w opóźnień może być przyczyną późniejszych problemów w skrypcie. Moja uwaga się koncentruje na linijce "wait 30 seconds".
    Dlaczego może to generować problemy? Dlatego, że jeśli chociażby serwer przestanie działać w ciągu tych 30 sekund, dalsze instrukcje po tym opóźnieniu nigdy nie zostaną wykonane. Konsekwencją tego może być później znajdywanie na serwerze nieusuniętych skrzyń, które zostały postawione przez działanie ów skryptu.

Na koniec dopowiem, że zauważyłem dziwną rzecz w Pana kodzie i zapewne jest to przyczyna braku działania kodu w przypadku wpadnięcia do otchłani. Mowa o linijce "if {combat.attacker.%{_p}%} isn't victim:" - nigdzie Pan nie zdefiniował wyżej w tym listenerze zdarzenia "on damage:" czym jest zmienna lokalna {_p}.

EDIT:
Dopatrzyłem się tego samego problemu na samym początku skryptu - w pierwszym listenerze zdarzenia "on damage:" odwołuje się Pan do zmiennej {_p}, która nie została jakkolwiek zdefiniowana.

Edytowane przez Kormic
Odnośnik do komentarza
https://skript.pl/temat/57393-skrypt-na-wyrzucanie-item%C3%B3w-do-skrzynki-nie-dzia%C5%82a/#findComment-341801
Udostępnij na innych stronach

  • 0

Gracz po otrzymaniu obrażeń od voida jest teleportowany do attackera. To działa. Niestety właśnie tu ta skrzynka się nie pojawia.

1. Na pewno to zmienię

2. Gracz tuż przed śmiercią od voida jest teleportowany do gracza, z którym się bił. Tutaj wszystko chyba działa.

Edytowane przez zygiszu
Odnośnik do komentarza
https://skript.pl/temat/57393-skrypt-na-wyrzucanie-item%C3%B3w-do-skrzynki-nie-dzia%C5%82a/#findComment-341802
Udostępnij na innych stronach

  • 0
17 minut temu, zygiszu napisał:

Gracz po otrzymaniu obrażeń od voida jest teleportowany do attackera. To działa. Niestety właśnie tu ta skrzynka się nie pojawia.

1. Na pewno to zmienię

2. Gracz tuż przed śmiercią od voida jest teleportowany do gracza, z którym się bił. Tutaj wszystko chyba działa.

Z początku rozum podpowiada, że Pana rozwiązanie z teleportacją gracza do innego gracza, który go zaatakował przed spadkiem w otchłań, nie powinno działać. Po chwili jednak doszedłem do wniosku, że jest możliwy dość specyficzny scenariusz, w którym Pana skrypt paradoksalnie działa.

Otóż nie jest to jedyne miejsce (mowa o listenerze zdarzenia, w którym pojawiają się linijki takie jak na przykład "teleport victim to location of ({combat.attacker.%{_p}%} parsed as a player"), w którym Pan używa niezdefiniowanej wcześniej zmiennej {_p}.
Użycie niezdefiniowanej zmiennej zawsze skutkuje zwróceniem wartości <none>, co niekoniecznie musi zwracać błąd. Tak więc istnieje szansa, że Pan ma zapisane zmienne o nazwach {combat.<none>}, {combat.attacker.<none>}, itd.

Nie ma problemu z odwołaniem się do takiej zmiennej, co łatwo pokazać za pomocą przykładowego kodu poniżej.

command /test:
	trigger:
		set {_zmienna::%{_p}%} to 1 # zmienna {_p} nie została nigdzie wcześniej zdefiniowana, a więc zwraca ona <none>
		broadcast "%{_zmienna::<none>}%"

Z początku by się mogło wydawać, że powyższy kod nie zadziała, ale nic bardziej mylnego. Na czacie zostanie wyświetlona wartość "1".

Co prawda ja odwołałem się bezpośrednio do <none> w zmiennej i Skript mnie ostrzegł o możliwym konflikcie nazewnictwa, ale w Pana przypadku niekoniecznie musi się tak dziać, gdyż Pan ponownie używa zmiennej {_p}. Tak więc Pan nie wprost pobiera wartość chociażby zmiennej {combat.<none>}, której wartość wcześniej została zapisana również przez użycie niezdefiniowanej zmiennej {_p}.

Mam nadzieję, że wytłumaczyłem to jasno i klarownie. Pana skrypt może działać, ale działa on w sposób nieprzewidywalny i w wyniku tego, że dla wszystkich graczy mamy zmienną {combat.<none>}, w przypadku większej ilości walk między graczami działanie skryptu stanie się nieprzewidywalne, co może doprowadzić do dziwnych sytuacji (na przykład będą teleportowani inni gracze, którzy walczą w tym samym momencie).

Odnośnik do komentarza
https://skript.pl/temat/57393-skrypt-na-wyrzucanie-item%C3%B3w-do-skrzynki-nie-dzia%C5%82a/#findComment-341804
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Nieaktywny
Odpowiedz na pytanie...

×   Wklejono zawartość z formatowaniem.   Usuń formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...