W temacie o eventach zdeklarowałem się , że zrobię coś w tym stylu , a więc robię
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 :
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 .
--------------------------------------
# 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
--------------------------------------
/*
* Komentarz , który
* rozciąga się
* na wiele wersów
*/
Tak jak wyżej , służy do komentarza na wiele wersów .
--------------------------------------
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 :
from com.l2jfree.gameserver.model.quest import State
Z folderu
com.l2jfree.gameserver.model.quest zaimportuje klase
StateCo 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ę
Dostępne Funkcje :
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 .
onAttack(self, npc, player, damage, isPet)
- Tą funkcje używamy zawsze gdy gracz atakuje Npc , którego rejestrowaliśmy do questa
onKill(self, npc, player, isPet)
- Funkcja używana gdy gracz zabije NPC , którego rejestrowaliśmy do questa
onFirstTalk(self,npc, player)
- Funkcja używana gdy gracz rozmawia
poraz pierwszy z kimś/czymś zarejestrowanym do questa
onDeath (self, npc, character, st)
- Funkcja używana gdy ktoś/coś zarejestrowany do questa umiera
onSpawn (self, npc)
- Jedyna funkcja , która nie odnosi się do gracza , funkcja używana gdy coś się spanuje . Lub ''re" spawnuje
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 :
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 :
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ż :
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 :
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)
else:
return "<html><body>Kochamy to forum , lol</body></html>"
--------------------------------------
Funkcja , coś za coś
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 :
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 :
st.playSound("ItemSound.quest_accept")
Tu nie ma nic do tłumaczenia .
---------------------------------------
Po zabiciu czegoś dostajemy coś i pokazuje się nam html .
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 :
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 :
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ść .
#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 .
st.takeItems(ADENA_ID,10000)
W zamian za buffa bierze 10000 adena
SkillTable.getInstance().getInfo(1204,2).getEffects(st.getPlayer(),st.getPlayer())
Za adena daje nam buffa ID
1204 st.getPlayer().restoreHPMP()
return "2.htm"
Dodatkowo regeneruje HP i Mp oraz wraca do htmla ( xxx-2.html )
---------------------------------------
Auto Event - CTF
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 :
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
Nie chce mi sie szukać tego obrazka ale masz plusa xD/edit
xD