טוב, אז במדריך זה אני אנסה ללמד אתכם קצת על NPCים, איך לערוך אותם והראה כמה אפשרויות שניתן לעשות עם הNPC.
(מדריך זה הוא עריכת הסקריפט של הNPC, ולא איך לערוך את המראה שלו.)
מה זה בעצם NPC?
NPC - Non Player Character
אלו הם בעצם הדמויות שמשמשות כעזר למשחק כדי להעביר סיפור מסויים במשחק או לתת משימות (Quests) וכדומה.
תיכנות הNPC :
הNPC בעצם מתוכנת בשפת JavaScript (JS).
על מנת לדעת לתכנת NPC בסיסי כל מה שצריך זה קצת ידע באנגלית, ללמוד לפי המדריך כיצד לערוך את הNPC וקצת שכל.
כדי ללמוד לערוך NPC כל מה שצריך זה לקחת סקריפט בסיסי של NPC ולדעת מה הוא עושה ואיפה צריך לערוך.
אז קודם כל נקח סקריפט בסיסי שבעצם לא עושה כלום:
קוד PHP:
var status = 0;
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (status == 1 && mode == 0 ) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if (status == 0) {
cm.dispose();
}
}
}
אז מה אנחנו בעצם רואים בסקריפט?
קודם כל יש לנו את השורה הזאת :
המילה var בJS היא בעצם הצהרה על משתנה שבמקרה זה הוא status.
החלק ' = 0 ' זוהי בעצם פקודה השמה, שבמה מכניסים את הערך '0' לתוך המשתנה status.
ה' ; ' סוגר את הפקודה. יש להשתמש בו על מנת לסגור כל פקודה שאתם משתמשים בה (דוגמאות תראו בהמשך).
החלק הבא שיש לנו הוא
קוד PHP:
function start() {
status = -1;
action(1, 0, 0);
}
השורה function start() זו היא בעצם הצהרה על פתיחת פונקציה.
זו היא בעצם פונקצית הפתיחה של הNPC, כאשר לוחצים על הNPC זה הדבר שהוא יפתח ראשון.
בתוך הפונקציה אתם רואים שתי שורות:
שכמו שהזכרתי בתחילת המדריך זו היא פקודת השמה, בפקודה זו הכנסנו את הערך '1-' לתוך המשתנה status.
קוד PHP:
action(1, 0, 0);
שורה זו היא בעצם פקודה שמפעילה את הפונקציה action שנמצאת בהמשך התוכנית, ומכניסה לתוכנה את הערכים לפי מיקום המספר.
כלומר פקודה זו מכניסה את הערכים הבאים:
קוד PHP:
mode = 1
type = 0
selection =0
התווים { ו } תוחמים את תחילת הפונקציה וסיום הפונקציה, חובה להשתמש בתווים אלה על מנת שהמערכת תדע איכן מתחילה הפונקציה, אין היא מסתיימת ומה היא כוללת.
כעת יש לנו את הפונקציה השניה, שבסקריפט זה משמשת כגוף של הסקריפט
קוד PHP:
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (status == 1 && mode == 0 ) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if (status == 0) {
cm.dispose();
}
}
}
השורה
קוד PHP:
function action(mode, type, selection)
גם היא הצהרה על פתיחת פונקציה, להבדיל מהפונקציה הקודמת, הפונקציה הזאת משתמשת ב3 משתנים (משתנים אלה מוגדרים בתוך הסורס ולך אין צורך להצהיר עליהם), ולכן בתוך הסוגריים נראה את שלושת המשתנים.
עכשיו יש לנו את החלק הזה שהוא קצת מבלבל
קוד PHP:
if (mode == -1) {
cm.dispose();
} else {
if (status == 1 && mode == 0 ) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
אז מה בעצם אנחנו רואים כאן?
השורה
היא בעצם פקודת תנאי, והיא עושה את מה שיש בתוכה אך ורק אם התנאי מתקיים. במקרה שלנו התנאי הוא אם המשתנה mode שווה ל1-.
אם תנאי זה מתקיים אז הוא ניגש לתוכן שלה (גם פה התחום התוכן מסומן ע"י { ו } ) שהוא:
שורה זאת היא בעצם פקודת NPC שמוגדרת בתוך הסורס, פקודה זו מבטלת את מצב השיחה, כלומר אם משתמש מדבר עם NPC, מצב השיחה הוא '1'. כאשר נשתמש בפקודה מצב השיחה יהפוך להיות '0'.
(כאשר מצב השיחה הוא '1' המשתמש אינו יכול ללחוץ על NPC על מנת לדבר איתו, מה שגורם לשחקן להיות "תקוע", לכן למקרים כאלה יצרו את הפקודת שחקן @dispose.)
בשורה הבאה נראה
זו היא פקודה שמגדירה מה הוא יעשה אם התנאי לא מתקיים, פקודה זו תבוא אך ורק לאחר פקודת תנאי.
לאחר מכן נראה שוב פקודת תנאי
קוד PHP:
if (status == 1 && mode == 0 )
(יש לשים לב שפקודה זאת נמצאת בתוך הגוף של else.)
תנאי זה בודק האם status שווה ל1.
ואם mode שווה ל0.
הסימנים && כמו שהם מוכרים - הם ועוד, כלומר על מנת שהתנאי יתקיים ותוכנית תיגש לגוף של התנאי, גם status=1 וגם mode=0 חייבים להתקיים.
לאחר מכן נראה return; זו בעצם בקודה שמחזירה לתחילת התוכנית.
הגענו לשורות
קוד PHP:
status++;
status--;
אלה הם פקודות קידום משתנה (במקרה זה המשתנה הוא status).
status++ תקדם את המשתנה ב1, כלומר אם הוא היה 1 אז לאחר הפקודה הוא יהיה 2.
status-- תוריד את הערך של המשתנה ב1, ככלומר אם הוא היה 1 אז לאחר הפקודה הוא יהיה 0.
*על מנת להבין למה עושים את כל הבדיקות האלה של המוד יש להבין קודם על איך פועל NPC עם פקודות הטקסט שלו שעליהם נסביר בהמשך*
לאחר מכן, יש את החלק הזה
קוד PHP:
if (status == 0) {
cm.dispose();
}
פקודת תנאי פשוטה, אך בסקריפט זה משמשת כהתחלת הNPC, כלומר מה הוא יעשה בפעם הראשונה שמדברים איתו.
לאחר שלמדנו את הסקריפט הבסיסי ומה כל דבר אומר בו, נלמד להשתמש בפקודות NPC.
נתחיל באיפה אפשר למצוא איזה פקודות NPC יש.
כדי למצוא איזה פקודות יש, צריך ללכת לקובץ NPCConversationManager.java.
שם בעצם מוגדרות רוב הפונקציות שהם בעצם הפקודות האפשריות לNPC, חלק מהפקודות נמצאות גם בMapleCharacter.java ולכן יש להתשמש בקריאה cm.getChar() לפני.
נתחיל עם כמה מהבסיסיות ביותר, פקודות הטקסט.
קיימות כמה פקודות להצגת טקסט, וכל פקודה כמובן מציגה טקסט בחלון שיחה שונה.
לדוגמא
תציג חלון שיחה שבו יש אפשרות לחיצה של OK.
קוד PHP:
cm.sendNext("");
תציג חלון שיחה שבו יש אפשרות לחיצה של Next.
רשימה של סוגי החלונות, ומה כל כפתור אומר לגבי הNPC.
cm.sendOk("");
תציג חלון שיחה שבו יש אפשרות לחיצה של OK.
כאשר לוחצים על OK, mode שווה ל1.
cm.sendNext("");
תציג חלון שיחה שבו יש אפשרות לחיצה של Next.
כאשר לוחצים על Next , mode שווה ל1.
cm.sendNextPrev("");
תציג חלון שיחה שבו יש אפשריות לחיצה של Next וPrev.
כאשר לוחצים על Next מוד שווה ל1.
כאשר לוחצים על Prev מוד שווה ל0.
cm.sendSimple("");
תציג חלון שיחה שבו אין אפשרויות.
משתמשים לרוב על מנת לתת בחירה (שעליה נלמד בהמשך).
cm.sendAccept("");
תציג חלון שיחה שבו יש אפשרות של Accept.
כאשר לוחצים על Accept מוד שווה ל1.
cm.sendAcceptDecline("");
תציג חלון שיחה שבו יש אפשרויות של Accept וDecline.
כאשר לוחצים על Accept מד שווה ל1.
כאשר לוחצים על Decline מוד שווה ל0.
cm.sendYesNo("");
תציג חלון שיחה שבו יש אפשרויות של Yes וNo.
כאשר לוחצים על Yes מוד שווה ל1.
כאשר לוחצים על No מוד שווה ל0.
cm.sendGetText("");
תציג חלון שיחה ובתוכו אפשרות כתיבה, וכפתור Send על מנת לשלוח את הטקסט הכתוב.
כאשר ילחצו על Send מוד יהיה שווה ל1.
cm.sendGetNumber("");
תציג חלון שיחה ובתוכו אפשרות כתיבה, להבדיל מהקודם שבו אפשר לקבל טקסט, בפקודה זו אפשר לקבל רק מספרים.
יש גם אפשרויות לקבוע את המקסימום ואתה מינימום של המספר.
כאשר לוחצים Send מוד שווה ל1.
** בכל סוגי החלונות יש גם את הכפתור End Chat, כפתור זה מגדיר שמוד שווה ל1-. **
לאחר שראינו כיצד הNPC מגיב ללחיצות הכפתורים, נוכל כעת להבין מדוע עושים בסקריפט את החלק הזה
קוד PHP:
if (mode == -1) {
cm.dispose();
} else {
if (status == 1 && mode == 0 ) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
אם מוד שווה ל1-, כלומר אם לחצו על End Chat הוא יסגור את חלון השיחה.
אם מוד שווה ל1, כלומר לחצו על Next\Yes\Ok\Send\Accept או בחירה של אחת האפשרויות (שעליהם נסביר בהמשך), הוא יקדם את הסטאטוס ב1.
ואם מוד שווה ל0, כלומר לחצו על No\Prev\Decline הוא יוריד 1 בסטאטוס.
בקוד נראה גם את האפשרות
קוד PHP:
if (status == 1 && mode == 0 ) {
cm.dispose();
return;
אפשרות זו לרוב משומשת כאשר יש את האפשרויות YesNo\AcceptDeclie.
מאחר וכאשר לוחצים על No\Decline הוא מכניס למוד 0, ומוגדר לו שכאשר מוד שווה 0 הוא מוריד אחד בטאטוס,
אם נרצה שכשנלחץ No\Decline הוא פשוט יצא מהחלון שיחה נגדיר לו שכאשר מוד הוא 0 (לחצו על Prev\No\Decline) והסטאטוס הוא 1 החלון שיחה יסגר.
נעבור לשיחה קצת יותר מתקדמת , בעלת כמה שלבים:
קוד PHP:
/*
* By SapiRxD
*/
var status = 0;
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.dispose();
} else {
if (status == 0 && mode == 0 ) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if (status == 0) {
cm.sendYesNo("Do you want to see something cool?");
}
else if (status == 1){
cm.sendOk("So go to iAtraf.co.il!");
cm.dispose();
}
}
}
בסקריפט זה נראה שלבסיס הוספנו 2 פקודות ותנאי נוסף.
בתחילת הסקריפט כמו מקודם הגדרנו לו מה יקרה כאשר ילחצו על הכפתורים ויגע למוד 1, 0 או 1-.
נגיע ישירות לחלק
קוד PHP:
if (status == 0) {
cm.sendYesNo("Do you want to see something cool?");
בשורה הראשונה נראה את התנאי, אם סטאטוס שווה ל0, בגלל שברגע שהוא מגיע לשורה הזאת הסטאטוס אכן שווה ל0, תנאי זה מתקיים ולכן הוא יבצע את מה שבשורה השניה.
בשורה השניה אנחנו רואים שיש פקודה להצגה של חלון שיחה עם אפשרויות של Yes וNo, בתוך החלון שיחה יהיה רשום
Do you want to see something cool?
אם ילחצו על לא (No), בגלל שמוגדר לו שכאשר סטאטוס שווה ל0 ומוד שווה ל0 (לחצו לא) הוא יסגור את החלון שיחה, אז הוא פשוט יסגור את החלון שיחה.
אם ילחצו על כן, למוד יכנס 1 והסטאטוס יקודם באחד (מ0 ל1.)
נגיע לחלק הזה
קוד PHP:
else if (status == 1){
cm.sendOk("So go to iAtraf.co.il!");
בשורה הראשונה שוב אפשר לראות תנאי, אם הסטאטוס שווה ל1, ובגלל שהוא קודם ל1 אחרי שלחצנו כן, התנאי מתקיים והוא יבצע את מה שיש בשורה השניה.
בשורה השניה שוב אנחנו רואים פקודה להצגת חלון שיחה אך הפעם עם אפשרות של Ok.
בחלון השיחה יוצג הטקסט
So go to iAtraf.co.il!
ולאחר שנלחץ אוקיי החלון יסגר בגלל שיש אחריו את הפקודה cm.dispose(); .
על אותו עיקרון אפשר להוסיף עוד מקרים של סטאטוסים ועוד שיחות.
*בסקריפט זה ראינו גם את החלק
קוד PHP:
/* by spairxd */
.
התוים /* */ משמשים בשביל להעיר הערות, כל מה שנמצא ביניהם לא יחשב כטקסט בסקריפט, דבר זה יכול לשמש כהערות לסקריפט, לרשימת קרדיטים וכו'.
ניתן לעשות את זה גם על ידי // - במקרה זה, כל מה שרשום באותה שורה אחרי // לא יחשב.
לאחר שלמדנו על איך להציג טקסט בחלונות שיחה, נלמד כעת את האפשרויות כתיבה שיש.
צבעים בטקסט ואפשרויות תצוגה של הטקסט:
בהצגת הטקסט בNPC יש אפשרות להציג אותו ב5 צבעים שונים: שחור, ירוק, כחול, סגול ואדום (ברירת המחדל היא שחור).
על מנת לעשות את הכתב שחור, נוסיף את "#k" לפני הטקסט.
על מנת לעשות את הכתב ירוק, נוסיף את "#g" לפני הטקסט.
בשביל כחול נוסיף "#b" לפני.
בשביל סגול, "#p".
ובשביל אדום , "#r".
(כמובן שבלי המרכאות, והסולמית צריכה להיות לפני האות.)
על מנת לרדת שורה פשוט רושמים
\r\n
ניתן גם להציג את שם השחקן בדרך פשוטה ע"י הוספת #h #.
ניתן גם להבליט את הטקסט על ע"י הוספת "#e" לפני הטקסט, ועל מנת לשנות אותו חזרה לרגיל נוסיף "#n" לפני.
כמו כן, ניתן גם להציג תמונות או שמות של מפות, NPC או מפלצות, ולהציג כמה יש לשחקן בחפצים מאותו חפץ לפי ID ע"י מספר תוספות:
#c[itmeid]# - מראה כמה פעמים יש את החפץ לשחקן בתיקיית חפצים.
#i[itemid]# - מראה תמונה של אותו חפץ.
#m[mapid]# - מראה את השם של המפה.
#o[mobid]# - מראה את השם של המפלצת.
#p[npcod]# - מראה את השם של הNPC.
#q[skillid]# - מראה את השם של הסקיל.
#s[skillid]# - מקרה את התמונה של הסקיל.
#t[itemid]# - מראה את השם של החפץ.
#v[itemid]# - מראה תמונה של החפץ.
#z[itemid]# - מראה את השם של החפץ.
#B[%]# - מראה מד התקדמות.
ניתן גם להציג תמונות מתוך הקיבצי WZ כך:
#f[imagelocation]# או
#F[imagelocation]#
אפשרויות בחירה:
ניתן להציג גם אפשרויות בחירה אשר בהתאם לבחירה הNPC יפעל.
נסתכל על הסקריפט הבא:
קוד PHP:
if (status == 0) {
cm.sendSimple("Do you want to see something cool?\r\n #L0#Yes#l\r\n #L1#No#l");
}
else if (status == 1){
if (selection == 0){
cm.sendOk("So go to #riAtraf.co.il!");
cm.dispose();
} else if (selection == 1){
cm.dispose();
}
}
נוכל לראות שכאשר סטאטוס שווה ל0 הוא פותח חלון שיחה בלי אפשרויות של כפתורים.
אך אם נסתכל בפנים נראה את החלק הזה:
קוד PHP:
#L0#Yes#l\r\n #L1#No#l
#L0# מגדיר את התחלת אפשרות הבחירה 0.
Yes זו היא בעצם אפשרות הבחירה
#l סוגר את אפשרות הבחירה, כלומר האפשרות לחיצה תיהיה רק על המילה Yes.
\r\n מגדיר ירידת שורה.
#L1# מגדיר את התחלת אפשרות הבחירה 1.
No זו היא בעצם אפשרות הבחירה.
#l סוגר את אפשרות הבחירה, במקרה זה האפשרות תיהיה לחיצה רק על המילה No.
כאשר לוחצים על אחת האפשרויות גם פה המוד מקבל 1, ולכן הסטאטוס מתקדם ב1, לכן את הפעולות שהNPC עושה כתוצאה מהבחירה נרשום בתנאי של הסטאטוס הבא.
המספר שלאחר L הוא בעצם המספר של הבחירה, כלומר כאשר ילחצו על הבחירה למשתנה selection יכנס הערך של המספר שבו בחרו, כלומר אם בחרו בL0 אז selection יהיה שווה ל0, אם בחרו בL4 אז selection יהיה שווה ל4.
לאחר מכן נסתכל על החלק הזה
קוד PHP:
else if (status == 1){
if (selection == 0){
cm.sendOk("So go to #riAtraf.co.il!");
cm.dispose();
} else if (selection == 1){
cm.dispose();
נראה שבשורה הראשונה יש תנאי שבודק אם סטאטוס שווה ל1, בגלל שכשאר שבחרו באחד האפשרויות זה העלה את הסטאטוס ל1, תנאי זה מתקיים.
בשורה השניה יש עוד תנאי שבודק את מצב הבחירה (selection ), אם הוא שווה ל0 (אם הבחירה היית בL0 שהוא Yes).
במקרה שבחרו 0 (Yes) הוא יציג חלון שיחה שבו יהיה רשום
So go to iAtraf.co.il
הiAtraf יהיה באדום בגלל התוספת של ה#r.
במקרה שבחרו 1 (No ) הוא ידלג על החלק שבתוך התנאי הראשון בגלל שהתנאי אינו מתקיים כי הבחירה שווה ל1 ולא ל0.
ולכן הוא יכנס לתנאי השני שבודק האם הבחירה שווה ל1.
ובגלל שבתוך יש את הפקודה דיספוז הוא יסגור את חלון השיחה.
ניתן לעשות כמה בחירות שרוצים (בAll in one shop NPC יש יותר מ80 בחירות), וניתן להגיד איזה מספר בחירה שרוצים (לדוגמא 500 ,2000).
פקודות נוספות לNPC:
הפקודות שאני אסביר עליהן הן פקודות בסיסיות שבדרך כלל יש בכל ריפאק או סורס, אך גם הן הכי שימושיות.
cm.gainMeso(amount);
זו היא פקודה שנותנת (או לוקחת) למשתמש מזוס.
כדי שהיא תתן מזוס, נכניס בסוגריים את המספר הרצוי כמספר חיובי.
כדי שהיא תקח מזוס, נכניס בסוגריים את המספר הרצוי כמספר שלילי (עם מינוס לפני).
cm.gainExp(amount);
זו היא פקודה שנותנת (או לוקחת) למשתמש EXP.
כדי שהיא תתן מEXP, נכניס בסוגריים את המספר הרצוי כמספר חיובי.
כדי שהיא תקח מEXP, נכניס בסוגריים את המספר הרצוי כמספר שלילי (עם מינוס לפני).
cm.modifyNx(amount);
(בריפאקים ישנים כמו קופה הפקודה היא gainNX)
זו היא פקודה שנותנת (או לוקחת) למשתמש NX.
כדי שהיא תתן NX, נכניס בסוגריים את המספר הרצוי כמספר חיובי.
כדי שהיא תקח NX, נכניס בסוגריים את המספר הרצוי כמספר שלילי (עם מינוס לפני).
cm.gainItem(itemid, amount);
פקודה שנותנת (או לוקחת) חפצים.
את הID של החפץ יש לרשום במקום itemid.
את כמות החפצים שהוא יתן (או יקח) יש לרשום במקום amount.
גם פה, מספר שלילי כדי לקחת, חיובי כדי לתת.
cm.haveItem(itemid, amount);
פקודה זו בודקת אם יש לשחקן את החפץ ואם יש לו את הכמות המבוקשת (שימושי מאוד לקווסטים).
את הID של החפץ יש לרשום במקום itemid.
את כמות החפצים שהוא יבדוק אם יש יש לרשום במקום amount.
cm.itemQuantity(itemid);
פקודה זו בודקת את הכמות שיש מאותו חפץ.
את הID של החפץ יש להחניס בתוך הסוגריים.
פקודה זו דומה מאוד לhaveItem, ולפי דעתי פחות עדיפה.
cm.warp(mapid);
פקודה זו מעבירה את השחקן למפה אחרת.
את הID של המפה הרצויה יש להכניס בסוגריים.
cm.getLevel();
פקודה זו בודקת את הרמה של השחקן.
cm.getMeso();
פקודה זו בודקת כמה מזוס יש לשחקן.
cm.maxSkills();
פקודה זו ממקססת את הסקילים.
יש אותה ברוב הריפאקים החדשים אך בישנים אין.
cm.openShop(shopid);
פקודה זו פותחת חנות מסויימת.
את הID של החנות יש להכניס בתוך הסוגריים.
cm.openNpc(npcid);
פקודה זו פותחת NPC מסויים.
את הID של הNPC יש להכניס בתוך הסוגריים.
טוב אז לאחר שלמדנו את הבסיס, הגענו לסיום מדריך זה.
אז לסיום אראה לכם סקריפט ובו מיושמים רובם הגדול של הדברים שלמדנו במדריך.
רוצים לבדוק את עצמכם? תנסו להבין לבד מה הסקריפט עושה ומה כל דבר בתוכו מבצע.
קוד PHP:
/*
Created by SapiRxD
*/
var status = 0;
function start() {
status = -1;
action(1, 0, 0);
}
function action(mode, type, selection) {
if (mode == -1) {
cm.sendOk("Bye then...")
cm.dispose();
} else {
if (mode == 0 && status >= 0) {
cm.dispose();
return;
}
if (mode == 1)
status++;
else
status--;
if (status == 0) {
cm.sendSimple("What whould you like to do?\r\n\r\n#r#L0#Max skills#l\r\n#b#L1#Open shop#l\r\n#p#L2#Open npc#l\r\n#g#L3#I want to take the quest#l\r\n#k#L4#Trade item for meso#l");
}else if(status == 1){
if (selection == 0){ // Max skills
cm.maxSkills();
cm.dispose();
}else if (selection == 1){ // open shop
cm.openShop(1);
}else if (selection == 2){ // open npc
cm.openNpc(91920292);
}else if (selection == 3){ // give a quest
cm.sendNext("Give me 200 of item' and I'll give you mesos, exp, nx and more!");
if (cm.haveItem(2883721, 200)){
cm.gainItem(2883721, -200);
cm.gainMeso(3000);
cm.gainExp(39993);
cm.modifyNx(30020);
cm.gainItem(39384, 3);
cm.sendOk("Enjoy.");
cm.dispose();
}else {
cm.sendOk("You dont have enough .");
cm.dispose();
}
}else if (selection == 4){ // trading.
if (cm.getMeso() >= 504054){
cm.gainMeso(-504054);
cm.gainItem(3578473);
cm.dispose();
}
}
}
}
}
כל הקרדיט למדריך זה הולך אלי בלבד.
אין להעתיק מדריך זה בלי רשותי.
תודה, ובהצלחה עם הNPC ^.^