卡歐悉

V113JS腳本教學(小白向)精華

發表於 2021-8-21 07:10:03
卡歐悉 發表於 2021-8-21 07:10:03 | 顯示全部樓層 |閱讀模式
先打個預防針 老手 高手 勿噴
這邊專門寫給跟我一樣沒有程式語言基礎
自學或者剛學剛踏入這塊的小白

剩下的廢話就不說太多了
如果稍微資質聰穎的可以去看看這篇教學
https://www.namepluto.com/4548/

以下這邊會假是你是純小白



分割線******************************************

首先在你的伺服器資料夾中
點開src中的scripting資料夾
先不要管編譯軟體還是什麼的
你會看到大致上長這樣
螢幕擷取畫面 2021-08-21 060635.png
使用任何可以編輯文字的軟體去打開
"NPCConversationManager.java"
上面看不懂的亂七八糟先不要理他
你會看到很多

    public XXXX OOOOO() {
        XXXXXXXXXXXXXX
    }

類似這樣內容的東西
NPCConversationManager中所提到OOOOO()就是你之後NPC的JS可以動用到的內容
我們再看一下NPC Conversation Manager
簡單翻譯就是NPC對話管理
Conversation Manager簡稱就是CM
在伺服器資料夾handling\channel\handler\NPCHandler.java中
你可以看到
final NPCConversationManager cm = NPCScriptManager.getInstance().getCM(c);
基本上就是你在JS中打cm.後面接任意的OOOOO()
只要你的OOOOO()符合NPCConversationManager這個裡面定義的內容 就可以使用
沒有的話就會以很多形式報錯
這部分先理解到這邊
接下來舉例



今天以一個任意NPC的代碼
比如隆都魯這個NPC
螢幕擷取畫面 2021-08-21 071629.png
你可以上網查 可以用你的端口自帶的功能查 以任意的方式去找到這個NPC的代碼
他的代碼是9209003基本上是一個七位數

以這個NPC為例子我們來重新寫他的內容
所以你要先到你伺服器負責管理NPC的JS的資料夾去創建一個9209003.js
資料夾路徑通常會是Libs\scripts\npc


然後接下來有幾點要注意 113的端口有些中文只支援BIG5編碼
然而很多人會把含有中文的內容寫在UTF8的編碼的JS檔案裡面
這會導致當你寫完一個正確的NPC 點了NPC卻發現類似這篇的問題
http://www.xinbiao-aicl.com/foru ... amp;page=1#pid15459
如果你不知道甚麼是BIG5編碼也無所謂
總之你就想成我們表面上看到的東西 在電腦眼裡可能是完全不一樣

所以到此為止建議是使用專業的編碼軟體或者是使用Notepad++來進行NPC的編輯
https://notepad-plus-plus.org/downloads/



打開notepad並且在上方
螢幕擷取畫面 2021-08-21 062246.png
找到字元改成BIG5
螢幕擷取畫面 2021-08-21 062247.png
並在存檔時確認右下方是顯示BIG5
螢幕擷取畫面 2021-08-21 062533.png


接下來NPC編寫的部分 因為本人也是小白+自學
會有蠻多不專業解釋跟名詞的部分 在此先消毒一下



分割線******************************************
總之我們在打開了9209003.js
並在其中先KEY下以下內容


function start() {
}

function action(mode, type, selection) {
}



總之NPC的JS主體架構大概就分為這兩個部分
有更簡單的可能只有

function start() {
}

這個部分
而JS中常常使用//一串文字
來表示註記 這些註記不會被執行 單純給編寫的人方便後面查看使用 可以放在任何地方
註記的方式分為兩種 一種是// 一種是/* */

以下舉例

ABC//DEFG

ABC/*DEFG*/

以上兩行 會被程式所執行的部分只有ABC
DEFG則是註記
所以我們暫時將程式碼寫成下面

//一開始點NPC執行
function start() {
}

//後續執行
function action(mode, type, selection) {
}

以上面兩行為例 雖然之後都不會動到他們 但是還是可以稍微說明一下

紅色的部分想像成名稱
綠色的部分就是條件 沒有的話就是空 意味著沒有條件
藍色的部分就是內容

這個部分大概記一下就好 對於思考會有點幫助
我們主要將要寫的內容寫入藍色的部分{}之中

這邊先舉例一個的方式

cm.sendSimple("");

sendSimple在113裡面
就是顯是一個對話框
而兩個"中間可以夾你任何想要輸入的文字
這邊附帶一提
有些文字可能會導致NPC無法打開 比如"裏"這個字 這個可能是遊戲中的一些缺字問題 在這邊不多做解釋
不過如果你很確定你NPC寫了沒有問題 卻打不開 可以想想是否有這個可能
然後記得每一段寫完的內容後面要加上;
所以我們先在start後面的{}中寫下
cm.sendSimple("你好");

你現在的程式碼應該看起來像下面這樣:




//一開始點NPC執行
function start() {
cm.sendSimple("你好");
}
//後續執行
function action(mode, type, selection) {
}





這時候別急著按儲存
還有一個很重要的是cm.dispose();
這個代表執行到這邊 遊戲中會結束與這個NPC的對話階段
如果沒有這個東西
你就算把對話框關掉 遊戲還會判斷你還在跟NPC對話
當你要重複跟其他NPC講話或做其他動作
就會看到這個

螢幕擷取畫面 2021-08-21 064708.png


現在你知道為什麼跟某些NPC對話完會需要EA了
代表他NPC中沒有在該有的段落加入cm.dispose();


加入後並且為了方便你了解 我加入了一點註記
你的程式碼應該長這樣

//一開始點NPC執行
function start() {
cm.sendSimple("你好");//顯示一個帶"你好"的對話框
cm.dispose();//結束對話階段
}
//後續執行
function action(mode, type, selection) {
}

儲存後你遊戲中NPC點開後應該會顯示如下

螢幕擷取畫面 2021-08-21 064915.png

你問我為什麼是"你好"不是"HelloWolrd"
拜託不要那麼老套了





分割線******************************************

以上介紹了cm.sendSimple();的用法
換言之在NPCConversationManager中找得到的內容
你只要明白正確的用法 都可以在JS中做使用
這些用法有包含 且不限於
判斷一些玩家的狀態 或者抓取一些遊戲中的內容
而且內容間可以互相搭配與限制條件

接下來就來講一下一些條件的判斷
但在介紹之前我們先來介紹另外一樣東西
cm.haveItem()
這是用來判斷玩家背包中是否含有某樣物品
紅寶殼的物品代碼為4000016

今天假設玩家如果包包裏有紅寶殼 NPC就會說有
沒有紅寶殼 NPC就會說沒有


在這我們要學習的就是條件判斷的如果怎麼寫

如果(條件){
內容
}
又如果(條件){
內容
}
剩下{
}

寫成程式碼就是

if(cm.haveItem(4000016)){
cm.sendSimple("有");
}
else{
cm.sendSimple("沒有");
}


整段就會看起來像



//一開始點NPC執行
function start() {

if(cm.haveItem(4000016)){//如果玩家背包中有紅寶殼
cm.sendSimple("有");//顯示一個帶"有"的對話框
}
else{//例外的狀況
cm.sendSimple("沒有");//顯示一個帶"沒有"的對話框
}
cm.dispose();//結束對話階段 這段不寫在if跟else的{}之中是無論執行哪一個最後執行完都會執行這段
}
//後續執行
function action(mode, type, selection) {
}




這邊介紹一個蠻好用的網站
https://www.10bestdesign.com/dirtymarkup/js/

只要將以上的內容丟進去之後
點clean
網頁就會自動幫你的內容作排版
將我們的程式碼丟入之後 整體就會變成像下面這樣乾淨的樣子


螢幕擷取畫面 2021-08-21 072332.png







儲存到9209003.js後NPC就會顯示如下

螢幕擷取畫面 2021-08-21 070853.png

螢幕擷取畫面 2021-08-21 070914.png





分割線******************************************

到目前為止 你應該已經可以讓NPC說出一些簡單的話語跟玩家交互
再來就是怎麼讓NPC做出更複雜的內容

首先任務目標

我們要讓隆都魯說出你好 並且讓他在下一句說想要把紅寶殼換成楓幣 每個紅寶殼可以換100楓幣

在這邊要介紹一個東西 var
var是變數variable的意思
總之寫程式有點像是在讀一個充滿簡化的英文內容

var的用法有很多種 總之我們先舉個栗子

var status=-1;

請理解成"把-1這個東西給status"

再來我們看到function action(mode, type, selection)
這邊大概表示action會受到mode type 跟 selection的影響


舉個例子 打開某些對話比較複雜的NPC
你會看到去除裡面的內容 他們的JS通常會長這樣



var status = -1;
function start() {
        action(1, 0, 0);
}

function action(mode, type, selection) {
if (mode == 1) { status++;}
else {status--;}
}



總之我們先介紹mode
與NPC的交互中

以cm.sendSimple為例
我們會看到NPC的介面長這樣
螢幕擷取畫面 2021-08-21 160213.png

而以cm.sendYesNo為例
我們會看到NPC的介面長這樣
螢幕擷取畫面 2021-08-21 160240.png

這邊如果點了
是 mode就是1
否 mode就是0
停止對話mode也是0

理解到這邊 上面的程式碼就不難看懂了

var status = -1;//設定一個status變數 值是 -1
function start() {
        action(1, 0, 0);//執行start時 mode為1 type為0 selection為0
}

function action(mode, type, selection) {
if (mode == 1) { status++;}//如果mode剛好等於1意味著按下了下一頁 那麼我們把status無論是多少都增加1
else {status--;}//如果mode剛好等於0意味著按下了否或停止對話 那麼我們把status無論是多少都減少1
}


所以我們曉得當沒有點NPC的時候status 為-1
當點了NPC之後執行了function start() 他默認了我們點了一次下一頁
所以我們現在的status 來到了-1+1=0
到這邊我們就繼續寫下面的部份

目前我們擁有的就是 點開NPC後status值是0

步驟1:當status剛好為0時顯示你好

程式碼:
if (status == 0) {
        cm.sendYesNo("你好");
}



注意這時候我們用的是sendYesNo而不是sendSimple
而且因為對話階段沒有要結束 所以我們不用加上cm.dispose();




步驟2:當status剛好為1時顯示要用紅寶殼換100楓幣嗎?

程式碼:
else if (status == 1) {
        cm.sendYesNo("用紅寶殼換100楓幣嗎?");
}





步驟3:當status剛好為2時判斷玩家有沒有紅寶殼 沒有的話顯示沒有紅寶殼 有的話玩家扣除一個紅寶殼 獲得100楓幣

程式碼:
else if (status == 2) {
        if (cm.haveItem(4000016)) {
                cm.gainItem(4000016, -1);
                cm.gainMeso(100);
                cm.dispose();
        } else {
                cm.sendSimple("你沒有紅寶殼");
                cm.dispose();
        }
}


注意最後防止玩家點擊繼續而出現status=3的情況 我們使用了sendSimple來傳送"你沒有紅寶殼"


整段JS的程式碼會如下





var status = -1;
function start() {
        action(1, 0, 0);
}

function action(mode, type, selection) {
        if (mode == 1) {
                status++;
        }
        else {
                status--;
        }
        if (status == 0) {
                cm.sendYesNo("你好");
        } else if (status == 1) {
                cm.sendYesNo("用紅寶殼換100楓幣嗎?");
        } else if (status == 2) {
                if (cm.haveItem(4000016)) {
                        cm.gainItem(4000016, -1);
                        cm.gainMeso(100);
                        cm.dispose();
                } else {
                        cm.sendSimple("你沒有紅寶殼");
                        cm.dispose();
                }
        }else{
                cm.dispose();
        }
}












加上註釋後









var status = -1;//設定一個status變數 值是 -1
function start() {//點擊NPC後會執行START
        action(1, 0, 0);//執行START時 mode設定為1 type為0 selection為0
}

function action(mode, type, selection) {//start後執行的動作
        if (mode == 1) {//當玩家在對話中選擇同意 下一步 或者選擇對話中的選項
                status++;//使status多1
        }
        else {//反之{當玩家並非在對話中選擇同意 下一步 或者選擇對話中的選項)
                status--;//使status少1
        }
        if (status == 0) {//當status正好為0
                cm.sendYesNo("你好");//傳送一個帶YesNo按鈕 內容為 你好 的對話框
        } else if (status == 1) {//當status正好為1
                cm.sendYesNo("用紅寶殼換100楓幣嗎?");//傳送一個帶YesNo按鈕 內容為 用紅寶殼換100楓幣嗎 的對話框
        } else if (status == 2) {//當status正好為2
                if (cm.haveItem(4000016)) {//判斷如果玩家擁有4000016即紅寶殼
                        cm.gainItem(4000016, -1);//獲得-1個紅寶殼
                        cm.gainMeso(100);//獲得100楓幣
                        cm.dispose();//結束對話
                } else {//判斷除了"如果玩家擁有4000016即紅寶殼"的例外狀況 在這邊即為沒有紅寶殼
                        cm.sendSimple("你沒有紅寶殼");//傳送一個不帶YesNo按鈕 內容為 沒有 的對話框
                        cm.dispose();//結束對話
                }
        }else{//當status 不是0 1 2 等以上狀況 在這邊剩下的可能即為status為-1
            cm.dispose();//結束對話
     }
}



將以上的情況都設想到之後
你就完成了一個可以用紅寶殼兌換楓幣
且可以點擊是否與停止對話
或者使用ESC直接關閉對話階段
都不會報錯或需要EA的NPC


實際執行結果

對話階段1  status為0
螢幕擷取畫面 2021-08-21 164733.png
對話階段2  status為1
螢幕擷取畫面 2021-08-21 164745.png
對話階段3  status為2
有紅寶殼的狀況
螢幕擷取畫面 2021-08-21 164827.png
對話階段3  status為2
沒有紅寶殼的狀況
螢幕擷取畫面 2021-08-21 164807.png


將對話當中的判定物品替換掉
就可以完成簡單的蒐集兌換


20210821更新
瀏覽 11427 回復 3

您需要登錄後才可以回帖 登錄 | 註冊會員

返回頂部