BiteFight
簡單外掛開發之IE篇
最近在玩BiteFight(黑暗傳說),這是一個簡單的休閑性質的網頁遊戲,模式就是練功、做任務、升級,類似於文字MUD。因為手動練功做任務太麻煩了,而且不能7*24小時進行,於是想做一個外掛。
做的思路有很多,我選擇了其中比較簡單的兩種:
一、基於IE的HtmlView用VC做一個程式,每次重新整理頁面的時候執行JavaScript任務指令碼;
二、做一個FireFox擴充(extension),監聽“DOMContentLoaded”事件,執行JavaScript任務指令碼。
兩種思路我都做了實現,而且運行良好,但是FireFox
extension具有一些優勢,我將在文章的末尾進行比較。(遊戲明確反外掛,所以只提供源碼片段和示範程式(適用S1伺服器):下載(請用瀏覽器右鍵菜單/目標另存新檔,需更改尾碼名)
)
本篇著重介紹基於IE的HtmlView的關鍵開發步驟和部分代碼:
1.
建立一個基於HtmlView的單文檔應用;
2. 增加功能表項目,例如:“Robbery Human”,並增加處理函數
void CWebMudView::OnStartRobberyHuman()
{
m_iCurrentWorkType = ERobberyHuman; // 設定當前的任務類型
CString url;
url.LoadString(IDS_STRING_ATTACK_URL); // 從Resource 中讀取Robbery
Human的頁面url
// 把任務指令碼內容讀取到m_strCurrentScript變數中
GetFileContent(GetCurrWorkingDir() + "//RobberyHuman.js", m_strCurrentScript);
Navigate2(url, NULL, NULL);
}
3.
重載HtmlView的OnDocumentComplete()虛函數
void
CWebMudView::OnDocumentComplete(LPCTSTR lpszURL)
{
CString
title;
title.Format("[%s] %s", WorkTypeArray[m_iTargetWorkType],
lpszURL);
gGetMainFrame()->UpdateTitle(title);
switch(m_iCurrentWorkType)
{
....
case
ERobberyHuman:
m_iCurrentWorkType = EIdle; //
把當前的任務類型置空,防止重入
RunScript(m_strCurrentScript);
break;
....
}
CHtmlView::OnDocumentComplete(lpszURL);
}
4.
增加執行JavaScript指令碼函數
void CWebMudView::RunScript(CString
strCode)
{
CString strLang("javascript");
//
LPDISPATCH
pDisp = NULL;
IHTMLDocument2 *pHTMLDoc = NULL;
IHTMLWindow2
*pHTMLWnd = NULL;
try{
if
(!(::IsWindow(this->m_hWnd)))//!! must do this, for
m_hWnd=0xcccc
return;
pDisp =
this->GetHtmlDocument();
if( pDisp )
{
if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLDocument2,
(void**)&pHTMLDoc)))
{
if(SUCCEEDED(pHTMLDoc->get_parentWindow( &pHTMLWnd )))
{
BSTR bstrCode =
strCode.AllocSysString();
BSTR bstrLang =
strLang.AllocSysString();
VARIANT
vRet;
vRet.vt = VT_BOOL;
BOOL bRet
= SUCCEEDED(pHTMLWnd->execScript(bstrCode,bstrLang,&vRet)); //
執行指令碼
if (bRet==FALSE &&
m_bShowScriptResult)
{
TRACE("/n!!!!!!!!!!!!!!!!Run Script
error!!!!!!!!!!!!!!!!!/n");
AfxMessageBox("Run Script
error!!");
}
SysFreeString(bstrCode);
SysFreeString(bstrLang);
}
}
}
}catch(...){}
try{
if(pHTMLWnd != NULL)
pHTMLWnd->Release();
if(pHTMLDoc != NULL)
pHTMLDoc->Release();
if(pDisp != NULL)
pDisp->Release();
}catch(...){}
}
5. 編譯產生可執行檔
6.
編寫RobberyHuman.js,並儲存到可執行檔所在的目錄
function
robbery()
{
// 如果當前頁面不是robbery頁面,則延遲並跳轉到robbery頁面
if
(document.URL.indexOf("robbery.php") == -1) {
// alert("Wrong
page!!!");
window.setTimeout("window.location.href='http://s2.bitefight.cn/bite/robbery.php';",
5*1000);
return;
}
if (document.forms.length >
0) {
// 分析form,提交post請求
if
(document.getElementById('mjz')==null) {
alert("Robbery human
times to max!!");
} else {
window.setTimeout("document.forms[0].submit();", 5*1000);
}
}
}
robbery();
7.
運行測試
註:外掛的核心其實是JavaScript指令碼,可以做的很複雜,自動完成許多任務。
在我的機器上我實現的功能主要包括:
1. Work
: robbery
human->work->robbery->...
1) robbery human every 10 minutes to max
times, or failed, goto 2);
2) work in tomb for one hour, then goto
1)
2. Protect
your Hero
: robbery human->robbery hero->work->robbery
human->.....
1) robbery human every 10 minutes to max times, or failed,
goto 2);
2) robbery Hero, or failed, goto 3)
3) work in tomb for one
hour, then goto 1)
3. Training Upgrade
: work->robbery
human->training->work->....
1) work in tomb for one hour, then
goto 2)
2) robbery human every 10 minutes to max times, or failed, goto
3)
3) try to upgrade you skill's level, or failed, goto
1)
由於BiteFight使用cookie儲存session,
每次提交form的時候都會提交儲存的session,而IE只有一個profile,共用cookie,因此只能儲存一個session,所以基於IE的HtmlView實現外掛在同一台PC上只能運行一個,無法同時練多個Hero。而在同一台PC上可以運行多個FireFox,其中每個FireFox使用自己的profile/cookie,所以基於FireFox
Extension的外掛可以同時運行多個。