Witaj
Gość

Wątek: [Poradnik] Python  (Przeczytany 7107 razy)

  • *******
  • Wiadomości: 1092

  • Pochwał: 22

[Poradnik] Python
« dnia: Marzec 14, 2009, 09:20:45 pm »
W temacie o eventach zdeklarowałem się , że zrobię coś w tym stylu , a więc robię  :P

Python

Ok , ale każdy początkujący może zadać pytanie , ale co to jest ? Lub po co komu to , więc :

Interaktywny język programowania , Standardowa implementacja to tzw. CPython (pisany w C), ale istnieją też inne, takie jak Jython (w Javie)  , który właśnie nas interesuję . Pewnie wiele osób , które miały styczność z serverem L2J widziała pliki pythona (.py) Są wykorzystywane do questów , eventów , automatycznych zadać , npc - jego zastosowanie można znaleźć praktycznie do każdego zadania .

Ta instrukcja jest bardziej dla początkujących osób . Jeśli znasz trochę pythona to także e Tobie te informacje mogą się przydać . Jeśli widzisz jakieś błędy , lub masz pomysły to proszę popraw mnie niezwłocznie - nikt nie jest nieomylny .

1. Początek . Na wstępnie , musimy zastanowić się co chcemy zrobić . Czy ma to być skrypt na automatyczne announce ? Buffer ? Quest ? A może event ?

2. Skrypty znajdziemy w folderze :

Cytuj
data/scripts

I kolejno foldery odnoszą się do poszczególnych zadań :

/data/scripts/quests/ - Do tego folderu umieszczamy skrypty i htmle z questami
/data/scripts/custom/ - Tutaj dajemy NPC typu buffer , eventy itp.
/data/script/cron/ - Tutaj dajemy skrypty automatyczne ( nie wymagają akcji od graczy itp ) Np auto Event
/data/script/ai/ - Inteligencja/zachowanie Mobów/Raid Bossów/NPC itp
/data/script/teleports/ - Czyli złożone teleporty ( np teleport tylko gdy jesteś noblesse , teleport za item )

Reszta na razie nas interesuje .

3. Wytłumaczenie kilku znaków w plikach pythona .

--------------------------------------

Cytuj
# Script by Matim
# @author Matim

- Znak # służy do umieszczania komentarza jedno wersowego , wszystko co się w nim znajduje jest ignorowane przez skrypt

- @author służy do podania autora ( nik/mail itp ) Poda nam autora podczas eksportowania dokumentacji

--------------------------------------

Cytuj
/*
 * Komentarz , który
 * rozciąga się
 * na wiele wersów
*/

Tak jak wyżej , służy do komentarza na wiele wersów .

--------------------------------------

Cytuj
import sys
from com.l2jfree import Config
from com.l2jfree.gameserver.model.quest import State
from com.l2jfree.gameserver.model.quest import QuestState
from com.l2jfree.gameserver.model.quest.jython import QuestJython as JQuest

Importujemy z core już zdefiniowane class'y . Te trzy podane wyżej są wymagane do każdego skryptu . Reszte klas ładujemy wedle własnego uznania lub zapotrzebowania ( lub piszemy własne )

Proszę zwrócić uwage na importy gdzie :

Cytuj
from com.l2jfree.gameserver.model.quest import State

Z folderu com.l2jfree.gameserver.model.quest zaimportuje klase State

Co tu takiego dziwnego ? Otóż to jest ścieżka pod klase zawartą na plikach L2JFree , a więc na L2J czy L2Emu będzie to wyglądało inaczej , cała ścieżka może diametralnie się różnić , a więc uważaj by uniknąć późniejszych
błędów . Jeśli nie jesteś pewien ścieżki do klasy , proponuje pobrać Source Core danego L2J'tu i sprawdzić osobiście .

--------------------------------------

4. Ok mamy pomysł , zaimportowaliśmy poprawnie klasy , ale jak wygląda to całe dalsze pisanie . Otóż dostępne są już nam gotowe klasy , które importujemy z core oraz zdefiniowane funkcje , a więc nam przypada tylko ładnie to poukładać w kupę  :P Dostępne Funkcje :

Cytuj
onAdvEvent(self, event, npc, player)
- Funkcja definiowana zawsze gdy coś się ma stać ( event - wydarzenie ) Gdy np Gracz kliknie na link / czy npc zginie . Itp. Za chwile będą podane do tego inne definicje .

Cytuj
onAttack(self, npc, player, damage, isPet)
- Tą funkcje używamy zawsze gdy gracz atakuje Npc , którego rejestrowaliśmy do questa

Cytuj
onKill(self, npc, player, isPet)
- Funkcja używana gdy gracz zabije NPC , którego rejestrowaliśmy do questa

Cytuj
onFirstTalk(self,npc, player)
- Funkcja używana gdy gracz rozmawia poraz pierwszy z kimś/czymś zarejestrowanym do questa

Cytuj
onDeath (self, npc, character, st)
- Funkcja używana gdy ktoś/coś zarejestrowany do questa umiera

Cytuj
onSpawn (self, npc)
- Jedyna funkcja , która nie odnosi się do gracza , funkcja używana gdy coś się spanuje . Lub ''re" spawnuje

Cytuj
st.getState() == State.COMPLETED
- Stan , quest zakończony

--------------------------------------

Wszystkich funkcji jest o wiele więcej , wszystkie znajdziecie w pliku documentations.txt w data/script/quests

--------------------------------------

5. Ok a teraz podam i opisze kilka przykładowych skryptów :

- Auto Announce Script :

Czyli .. pomyśl jak by to trzeba było zacząć , a więc najpierw wypada zaimportować odpowiednią klase . W tym wypadku jest to klasa announce oraz :

Cytuj
import sys
from com.l2jfree.gameserver import Announcements
from com.l2jfree.l2j.gameserver.model.quest.jython import QuestJython as JQuest
from com.l2jfree.util import Rnd
from java.lang import System

Dalej piszemy :

Cytuj
class Quest (JQuest) :

 def __init__(self,id,name,descr):
     JQuest.__init__(self,id,name,descr)
     self.startQuestTimer("timer105",900000,None,None,True)

 def onAdvEvent(self,event,npc,player) :
    if event == "timer105" :
        annc = Rnd.get(8 )
        if annc == 1 :
            Announcements.getInstance().announceToAll("Tu wpisz announce 1")
        elif annc == 2 :
            Announcements.getInstance().announceToAll("Tu wpisz announce 2")


QUEST     = Quest(4007,"4007_announce","announce")

print "Autoannounce loaded!"

No i mamy prosty , zrozumiały skrypt , które będzie robił ogloszenia w tym przypadku co 15 min - ponieważ :

Cytuj
self.startQuestTimer("timer105",900000,None,None,True)

900000 - 15 min - Tam zmieniamy wg własnego uznania

W folderze data/script/custom robimy folder auto_announcements , w którym robimy plik __.init.py , do którego dodajemy w/w skrypt . W pliku script.cfg dopisujemy :

Cytuj
custom/announce/__init__.py

--------------------------------------

Funkcja , która wyświetli plik html ( Najpierw definiujemy oczywiście [if] - czyli funkcje , jeśli ktoś zrobi coś , pokaże się HTML)

Cytuj
            else:
                return "<html><body>Kochamy to forum , lol</body></html>"


--------------------------------------

Funkcja , coś za coś

Cytuj
def onEvent (self,event,st) :
    htmltext = event
    if event == "2_1" :
          st.takeItems(ADENA_ID,1)
          st.giveItems(SWORD_ID,1)
          htmltext = "7223-08.htm"

Czyli zabierze nam 1 sztuke Adeny i da 1 miecz , ale oczywiście na początku definiujemy nazwy/id tych przedmiotów o tak :

Cytuj
ADENA_ID = 57
SWORD_ID = 1093

I teraz już chyba każdy rozumie co i dlaczego nam daje . Dodatkowo wyświetli nam html ( htmltext = "7223-08.htm" )

--------------------------------------

Zagranie muzyczki akceptacji questa :

Cytuj
st.playSound("ItemSound.quest_accept")

Tu nie ma nic do tłumaczenia .

---------------------------------------

Po zabiciu czegoś dostajemy coś  i pokazuje się nam html .

Cytuj
def onKill(self,npc,player,isPet):
    if event == "1" :
          st.giveItems(SWORD_ID,1)
          htmltext = "7223-08.htm"

Zabijamy coś , dostajemy item i pokazuje się html , tego też nie trzeba tłumaczyć

---------------------------------------

Teraz coś z buffera . Przykładowy buffek :

Cytuj
class Quest (JQuest) :

   def __init__(self,id,name,descr): JQuest.__init__(self,id,name,descr)


   def onEvent(self,event,st):
      htmltext = event
      count=st.getQuestItemsCount(ADENA_ID)
      if count < 150000 or st.getPlayer().getLevel() < 10 :
         htmltext = "<html><head><body>Nie stac cie lajzo<br></body></html>"
      else:
         st.takeItems(ADENA_ID,0)
         st.getPlayer().setTarget(st.getPlayer())
         
         if event == "1":
            st.takeItems(ADENA_ID,1000)
                                st.getPlayer().useMagic(SkillTable.getInstance().getInfo(9951,5),False,False)
                                st.getPlayer().restoreHPMP()
            return "1.htm"      
            st.setState(COMPLETED)
 
         

         #Wind Walk
         if event == "2":
            st.takeItems(ADENA_ID,10000)
            SkillTable.getInstance().getInfo(1204,2).getEffects(st.getPlayer(),st.getPlayer())                           
            st.getPlayer().restoreHPMP()
            return "2.htm"      
            st.setState(COMPLETED)

I kolejny oznacza to :

Cytuj
      count=st.getQuestItemsCount(ADENA_ID)
      if count < 150000 or st.getPlayer().getLevel() < 10 :
         htmltext = "<html><head><body>Nie stac cie lajzo<br></body></html>"

Najpierw u góry trzeba zdefiniowac ( ADENA_ID ) i IF mówi nam , że jeśli ilość tej adeny jest mniejsza niż 150000 lub level gracza jest mniejszy niż 10 to wyświetla wiadomość .

Cytuj
         #Wind Walk
         if event == "2":
            st.takeItems(ADENA_ID,10000)
            SkillTable.getInstance().getInfo(1204,2).getEffects(st.getPlayer(),st.getPlayer())                           
            st.getPlayer().restoreHPMP()
            return "2.htm"      
            st.setState(COMPLETED)

W htmlu robimy sobie button , który wysyła bypassa to skryptu z eventem ( wydarzeniem ) -2 i dostajemy buffa windwalk .

Cytuj
st.takeItems(ADENA_ID,10000)

W zamian za buffa bierze 10000 adena

Cytuj
SkillTable.getInstance().getInfo(1204,2).getEffects(st.getPlayer(),st.getPlayer())   

Za adena daje nam buffa ID 1204

Cytuj
            st.getPlayer().restoreHPMP()
            return "2.htm"   

Dodatkowo regeneruje HP i Mp oraz wraca do htmla ( xxx-2.html )

---------------------------------------

Auto Event - CTF

Cytuj
Cytuj
import sys
from com.l2jfree.gameserver.model.entity.events import CTF
CTF.loadData()
CTF.autoEvent()

Banalny skrypt , zaimportowaliśmy CTF z core , i każemy mu odpalić CTF ( trzeba jeszce zrobic tabele .sql , w której podamy co ile ma uruchamiać event ) Taki skrypt nazywamy ctf.py i dajemy do folderu data/script/cron - ponieważ ma to być skrypt , który działa nawet bez akcji osoby trzeciej . A tabela ma wyglądac tak :

Cytuj
INSERT INTO global_tasks(task,type,last_activation,param1,param2,param3) VALUES ('998', 'jython', 'TYPE_FIXED_SHEDULED', '1219484326015', '600000', '14400000', 'ctf.py');

param1 - czas w jakim event wystartuje po restarcie ( w milisekundach )
param2 - czas , po którym event znowu wystartuje

---------------------------------------

na razie tyle , wkrótce podam i opisze więcej skryptów oraz bardziej przybliżę pisanie ich samemu . Oraz podam i opisze kilka plików .java , które działają na zasadzie skryptu , nie wymagają kompilacji itp . Np robienie własnej komendy bez wchodzenia do core . No i napisze kilka eventów z kompletnymi komentarzami .

Thanx  :P


Nie chce mi sie szukać tego obrazka ale masz plusa xD

/edit

xD
« Ostatnia zmiana: Październik 03, 2010, 08:49:09 pm wysłana przez Matim »


  • *******
  • Wiadomości: 1866

  • Pochwał: 18

  • <3
Odp: [PORADNIK]Python
« Odpowiedź #1 dnia: Marzec 14, 2009, 09:37:25 pm »
Dzieki Matim, taki poradnik na pewno pomoże. Bardzo fajnie napisany, już go przeczytałem i polecam każdemu.

Gz
Sebal- Life ...

▬▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬▬▬▬

SHUT UP AND ENJOY THE MUSIC

▬▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬▬▬▬


  • *******
  • Wiadomości: 1092

  • Pochwał: 22

Odp: [PORADNIK]Python
« Odpowiedź #2 dnia: Marzec 14, 2009, 09:40:09 pm »
Np , jutro napisze więcej , Btw Seebal fajny avatar  :D


  • *******
  • Wiadomości: 1866

  • Pochwał: 18

  • <3
Odp: [PORADNIK]Python
« Odpowiedź #3 dnia: Marzec 14, 2009, 09:44:20 pm »
Np , jutro napisze więcej , Btw Seebal fajny avatar  :D

Już się nie mogę doczekać, dzięki chcesz podobny ^^?  Btw. Mati ja to nie wiem co mam z tym Twoim gg znowu mi zniknąłeś (:o), jak możesz to się odezwij :oops:
Sebal- Life ...

▬▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬▬▬▬

SHUT UP AND ENJOY THE MUSIC

▬▬▬▬▬▬▬▬▬▬▬ஜ۩۞۩ஜ▬▬▬▬▬▬▬▬▬▬▬▬▬


  • Wiadomości: 391

  • Pochwał: 10

Odp: [PORADNIK]Python
« Odpowiedź #4 dnia: Marzec 20, 2009, 05:18:01 pm »
Świetnie nareszcie ktoś się wybija co potrafi zdecydowanie więcej jak edycję configów. Miło, że omówiłeś kilka metod/funkcji. Rzeczywiście można wiele rzeczy spokojnie stworzyć nie ingerując i modyfikując kodu.
Polaczkowo:
Impos - Aeore Healer lvl 93 / Wynn Summoner 85 / TH 58
klan - Kowale
CP Sairea


  • *******
  • Wiadomości: 1092

  • Pochwał: 22

Odp: [PORADNIK]Python
« Odpowiedź #5 dnia: Marzec 20, 2009, 06:43:04 pm »
Świetnie nareszcie ktoś się wybija co potrafi zdecydowanie więcej jak edycję configów. Miło, że omówiłeś kilka metod/funkcji. Rzeczywiście można wiele rzeczy spokojnie stworzyć nie ingerując i modyfikując kodu.

Dlatego właśnie bardzo lubie pyhona  :) Miło , że Ci się podoba , dzięki . Wiadomo , że python nie daje nam tyle możliwości co modyfikacja core/java , ale i tak jest duże pole do popisu  :P


  • Wiadomości: 82

  • Pochwał: 0

Odp: [PORADNIK]Python
« Odpowiedź #6 dnia: Marzec 25, 2009, 07:19:53 pm »

--------------------------------------

Cytuj
import sys
from com.l2jfree import Config
from com.l2jfree.gameserver.model.quest import State
from com.l2jfree.gameserver.model.quest import QuestState
from com.l2jfree.gameserver.model.quest.jython import QuestJython as JQuest

Importujemy z core już zdefiniowane class'y . Te trzy podane wyżej są wymagane do każdego skryptu . Reszte klas ładujemy wedle własnego uznania lub zapotrzebowania ( lub piszemy własne )

Proszę zwrócić uwage na importy gdzie :

Cytuj
from com.l2jfree.gameserver.model.quest import State

Z folderu com.l2jfree.gameserver.model.quest zaimportuje klase State

Co tu takiego dziwnego ? Otóż to jest ścieżka pod klase zawartą na plikach L2JFree , a więc na L2J czy L2Emu będzie to wyglądało inaczej , cała ścieżka może diametralnie się różnić , a więc uważaj by uniknąć późniejszych
błędów . Jeśli nie jesteś pewien ścieżki do klasy , proponuje pobrać Source Core danego L2J'tu i sprawdzić osobiście .

--------------------------------------
Tak z ciekawości. Dając w ten sposób:
import sys
from com.l2jfree import Config
from com.l2jfree.gameserver.model.quest import *
from com.l2jfree.gameserver.model.quest.jython import QuestJython as JQuest

Będzie na 1oo% poprawnie funkcjonować?

"Dopóki nie skorzystałem z internetu, nie wiedziałem, że na świecie jest tylu idiotów."
Stanisław Lem


  • ******
  • Wiadomości: 1390

  • Pochwał: 15

  • Urażona dzidzia, urażona dzidzia!
Odp: [PORADNIK]Python
« Odpowiedź #7 dnia: Marzec 25, 2009, 07:43:37 pm »
Nie będzie ...


  • Wiadomości: 82

  • Pochwał: 0

Odp: [PORADNIK]Python
« Odpowiedź #8 dnia: Marzec 25, 2009, 07:49:55 pm »
Skoro jest tam wiele tych klas, a przez symbol * możemy stosować kilka klas bez dokładnego określenie to dlaczego nie zadziała  :? ?

"Dopóki nie skorzystałem z internetu, nie wiedziałem, że na świecie jest tylu idiotów."
Stanisław Lem


  • ******
  • Wiadomości: 1390

  • Pochwał: 15

  • Urażona dzidzia, urażona dzidzia!
Odp: [PORADNIK]Python
« Odpowiedź #9 dnia: Marzec 25, 2009, 08:22:35 pm »
Skoro jest tam wiele tych klas, a przez symbol * możemy stosować kilka klas bez dokładnego określenie to dlaczego nie zadziała  :? ?

Python ?

Tam każdą klase jaką chcesz wykorzystac musisz  zdefiniowac w import


  • *******
  • Wiadomości: 1092

  • Pochwał: 22

Odp: [PORADNIK]Python
« Odpowiedź #10 dnia: Marzec 25, 2009, 09:27:56 pm »
Wiem , że w Javie np Pakie util zawiera wiele klas , a w związku z tym można stosować kilka z nich bez wyraźnego określenia . Można to łatwo uzyskać poprzesz wpisanie symbolu wieloznacznego :

Cytuj
*

np :

Cytuj
import java.util.*;

Jest to sposób bardziej powszechny niż wskazywanie każdej klasy z osobna , kiedy włączyć kolekcje klas.

Ale przyznam , że nie wiem jak to będzie dokładnie w pythonie . Radze jednak posłuchać Maślana i importować z osobna .


  • Wiadomości: 82

  • Pochwał: 0

Odp: [PORADNIK]Python
« Odpowiedź #11 dnia: Marzec 25, 2009, 10:03:22 pm »
Chyba też posiadasz książkę Bruce'a Eckel'a ^^.

"Dopóki nie skorzystałem z internetu, nie wiedziałem, że na świecie jest tylu idiotów."
Stanisław Lem


  • *******
  • Wiadomości: 1092

  • Pochwał: 22

Odp: [PORADNIK]Python
« Odpowiedź #12 dnia: Marzec 25, 2009, 10:17:50 pm »
Owszem .


  • ******
  • Wiadomości: 1390

  • Pochwał: 15

  • Urażona dzidzia, urażona dzidzia!
Odp: [PORADNIK]Python
« Odpowiedź #13 dnia: Marzec 26, 2009, 03:08:35 pm »
Chyba też posiadasz książkę Bruce'a Eckel'a ^^.

Python nie jest na tyle wydajnym jezykiem zeby oczekiwac od niego takich rozwiązan
« Ostatnia zmiana: Kwiecień 26, 2009, 05:47:06 pm wysłana przez Maślan »


  • Wiadomości: 56

  • Pochwał: 1

Odp: [Poradnik]Python
« Odpowiedź #14 dnia: Maj 07, 2009, 02:51:34 pm »
a jak np. zrobic zeby przy dzwiach stal np. ktory za jakis itemik lub kilka otworzy nam te drzwi?


  • *******
  • Wiadomości: 1092

  • Pochwał: 22

Odp: [Poradnik]Python
« Odpowiedź #15 dnia: Maj 07, 2009, 04:06:59 pm »
Popatrz się na Teleporterów , którzy teleportują za jakiś quest item , popatrz potem na doormanów i napisz to sam jak powinno być odpowiednio , nie będzie dużo pracy .