ASI類 腳本 編寫 修改 漢化 Native Trainer 開源計畫 - 原始碼已中文化
轉發請保留該字樣:「」 昔日的戰友OB又復活歸來。。說點題外話:說是開源,其實本身Native Trainer就是開源的,我只是整合、修改、漢化部分代碼,所以相當的慚愧,國內基本上找不到此類話題的網站,那不如從此帖開始,慢慢的整合一群志同道合的朋友,共同研究,為大家創造更多的插件,打個簡單的比方外掛,敢於開源的人少之又少,及時開源也是過期的東西。國情就是如此,也只能感慨一番。
我相信付出都會有收穫,也因為這種精神我認識了許多志同道合的朋友,從最初的pvpgn、bnetd project此類開源項目,讓我學習到這種精神,讓我印象最為深刻的就是SourceMod類插件,幾乎是共享的,有很多優秀的作品,L4D1代,我製作了LXD、Random event、viprank等插件,如當初我不開源,沒有那群志同道合的朋友,也不至於能霸佔全球rank第一如此之久,也不會在L4D2的時候還能看到我製作的hack能夠得到延續,也不會看到一批一批優秀的製作者。
所以我想說,共同進步的同時又能方便廣大玩家,何樂而不為。So 此帖不光開源,也會在空餘時間進行授課,對SDK進行慢慢的翻譯,逐漸更新,個人思想始終是有侷限的,期待大家的共同加入。
第一篇帖子權當基礎教程,我並非是c++高手,只是趨於愛好,逐漸學習,學學忘忘。【不足之處還望指正,學習就是摸索、研究、請教】
1、什麼是Asi
Asi是Script Hook V的腳本文件,與其說是腳本,我認為不如說是DLL文件更為恰當,用Editplus類軟件編輯Asi文件時,都能看到文件頭的標準win32結構,Script Hook從字面瞭解,就能明白,通過hook(例如我給你打電話,中間需要一個基站,hook你可以看作一個偽造的基站,攔截正規基站的信息,然後對其發出修改後的指令,然後得到結果,外掛常用的一種形式)創建我們需要功能,讓Script Hook來識別,並在遊戲內體現出來。而Asi的書寫結構是標準的c++結構,所以說大家還是學c++吧,哈哈。
2、如何編譯Asi
安裝VS2013,打開 SourcesamplesNativeTrainer.sln 工程文件,然後如圖所示,下方會有簡要提示,無論是否編譯成功。
3、關於中文編譯
採用中文需要注意事項,首先編碼必須是utf8,然後字符集必須採用"使用 Unicode 字符集", 因為編碼的問題(這是我的猜測,我在很早以前看到過GTA系列是單字節遊戲,漢化也是採取的外掛形式,在實際測試過程中,亂碼問題,建議全部採取繁體中文書寫,如果編譯出現錯誤C2001,偶數中文背後加上英文符,或gbk to utf8字符轉換)
4、代碼基礎講解
因為代碼都是標準的C++結構,所以這裡不對最基礎的指令進行說明,只對針對遊戲有作用的代碼進行說明。首先來看一段代碼,代碼內能備註的,我都進行備註
創建菜單函數,創建菜單的方式有許多種,這裡只以其中之一進行說明,該函數涵蓋本附件源碼內的基礎功能
首先看創建菜單的一個功能draw_menu_line(caption, 350.0, 15.0, 18.0, 0.0, 5.0, false, true);後面一堆參數怎麼知道表達的是什麼意思?你可以在vs中搜索draw_menu_line後會出現下方的代碼,相對應後你就知道都是什麼意思了,或者直接在vs中自己手動鍵入draw_menu_line他也會提示,那麼翻譯出現就是//draw_menu_line(文本,寬度,高度,頂位置,左邊位置,文本位置,是否可選中,是否為標題,自動調整文本(不指定則為true))那麼我們繼續看下面的一段代碼void update_status_text()
{
if (GetTickCount() < statusTextDrawTicksMax)
{
UI::SET_TEXT_FONT(0);
UI::SET_TEXT_SCALE(0.55, 0.55);
UI::SET_TEXT_COLOUR(243, 23, 84, 255);
UI::SET_TEXT_WRAP(0.0, 1.0);
UI::SET_TEXT_CENTRE(0);
UI::SET_TEXT_DROPSHADOW(0, 0, 0, 0, 0);
UI::SET_TEXT_EDGE(1, 0, 0, 0, 205);
if (statusTextGxtEntry)
{
UI::_SET_TEXT_ENTRY((char *)statusText.c_str());
} else
{
UI::_SET_TEXT_ENTRY("STRING");
UI::_ADD_TEXT_COMPONENT_STRING((char *)statusText.c_str());
}
UI::_DRAW_TEXT(0.5, 0.5);
}
}突然想起來一個嚴重的問題,那必須要說下,且到了上班的點了,也不夠時間了。void main() //初始入口,例如我在另外一篇帖子中發的online_bypass源碼,如果你需要用,那麼就需要加在這裡,我備註過(備註也等同於讓這段代碼失效)的部分就是了,
{
//#include "bypass.h"
//online_bypass.h();
reset_globals(); //這裡是對所有變量進行初始賦值,我遇到過一個BUG,直接複製粘貼進去的變量是失效的,如果遇到此類問題,建議手打,編譯的時候不會出現錯誤警告。
while (true) //正文中我提到過,可以把asi看成一個dll,在main.cpp中一看便知,插件只會加載一次,具體見main.cpp,和本文無關不做解釋了
{
if (trainer_switch_pressed()) //搜索trainer_switch_pressed 得知此段代碼意思 如果f4被按下
{
menu_beep(); //搜索得知,播放聲音
process_main_menu(); //執行process_main_menu參數
}
update_features(); 否則執行update_features()函數,有時候我們發現修改的功能失效,按下F4,再關閉後即可生效,update_features掌管了大部分的修改功能。
WAIT(0);
}
}process_main_menu() 解釋int activeLineIndexMain = 0; //定義一個初始值
void process_main_menu()
{
const float lineWidth = 300.0; //表格寬度
const int lineCount = 10; //行數
std::string caption = "NATIVE TRAINER (AB) PLus BY WInD"; //std string caption 記得這裡嗎?前文中創建菜單那裡提到過,標題的類型就是 std string,caption是自定義的參數名
static LPCSTR lineCaption = { //創建表格
"玩家選項",
"武器選項",
"載具選項",
"世界選項",
"時間選項",
"天氣選項",
"其他雜項",
"在線解鎖",
"等級修改",
"增強部分 BY WInD" //結尾是沒有,號的
};
DWORD waitTime = 150; /定義一個變量
while (true)
{
// timed menu draw, used for pause after active line switch
DWORD maxTickCount = GetTickCount() + waitTime; //該段代碼中的GetTickCount()在main菜單中,可以看到有個參數,創建了一個隨機數種子,而GetTickCount()在update_status_text()中有有一個判斷,主要用於解決同時創建菜單造成的字體顏色混淆作用
do
{
// draw menu
draw_menu_line(caption, lineWidth, 15.0, 18.0, 0.0, 5.0, false, true); //這裡不做解釋了,上面已經解釋過了,至說明一下創建過程經過
for (int i = 0; i < lineCount; i++) //循環,賦值i=0 如果 i<linecount 則跳出循環,否則i++後繼續執行,如果i<10,也就是執行10次後,i="10了,那麼則跳出循環。
if (i != activeLineIndexMain) //如果I 不等於activeLineIndexMain(該值初始值為0,也就是說0不等於0的情況下) 則執行 draw_menu_line(lineCaption, lineWidth, 9.0, 60.0 + i * 36.0, 0.0, 9.0, false, false);
draw_menu_line(lineCaption, lineWidth, 9.0, 60.0 + i * 36.0, 0.0, 9.0, false, false); //創建菜單 以此從第一項創建到10項,結尾的兩個false,則代表他們既不是標題也是可選中項目,可以這樣理解他這裡是為了防止BUG才這樣處理的, 在本段代碼開頭,如果第一次創建的話,因為按了F4以後,我們首選就是菜單的第一個項目上了,那麼接下來我們要創建的是2~9項目,用於防止重複創建,可以不用理解,直接調用即可,這裡只是做一個說明。
draw_menu_line(lineCaption, lineWidth + 1.0, 11.0, 56.0 + activeLineIndexMain * 36.0, 0.0, 7.0, true, false);
update_features(); //創建完畢後,立即執行參數,該段後面會大致講解。
WAIT(0); //延時
} while (GetTickCount() < maxTickCount);
waitTime = 0;
// process buttons
bool bSelect, bBack, bUp, bDown; //邏輯參數 選擇 返回 前 後
get_button_state(&bSelect, &bBack, &bUp, &bDown, NULL, NULL); //獲取key設置值,以後會講解,來不及了,要上班了
if (bSelect) //如果按下選擇按鈕
{
menu_beep(); //發聲
switch (activeLineIndexMain) //選擇
{
case 0:
process_player_menu(); //第一項進入 process_player_menu()
break;
case 1:
process_weapon_menu(); //第二項進入 process_weapon_menu() 後面以此類推
break;
case 2:
process_veh_menu();
break;
case 3:
process_world_menu();
break;
case 4:
process_time_menu();
break;
case 5:
process_weather_menu();
break;
case 6:
process_misc_menu();
break;
case 7:
set_status_text("[自用功能,不影響和諧]");
//process_rec_menu();
break;
case 8:
set_status_text("[自用功能,不影響和諧]");
//process_level_menu();
break;
case 9:
process_about_menu();
break;
}
waitTime = 200;
} else //如果沒有進行選擇操作
if (bBack || trainer_switch_pressed()) //如果是 返回 或按下f4
{
menu_beep();
break; //中段
} else
if (bUp) //如果按向上按鈕
{
menu_beep();
if (activeLineIndexMain == 0)
activeLineIndexMain = lineCount; //一些賦值,不說明了,可以自己對比兩個值在不同位置的作用,來做比較
activeLineIndexMain--;
waitTime = 150;
} else
if (bDown)
{
menu_beep();
activeLineIndexMain++;
if (activeLineIndexMain == lineCount)
activeLineIndexMain = 0;
waitTime = 150;
}
}
}前文中我們提到了get_button_state(&bSelect, &bBack, &bUp, &bDown, NULL, NULL); //獲取key設置值,以後會講解,來不及了,要上班了該段代碼中我們可以追蹤代碼段,得到void get_button_state(bool *a, bool *b, bool *up, bool *down, bool *l, bool *r) //
{
if (a) *a = IsKeyDown(VK_NUMPAD5); //整段的作用很明確,就是為了定義熱鍵按鈕,key代碼可以在http://blog.sina.com.cn/s/blog_7006ccc10101bnmr.html中查詢
if (b) *b = IsKeyDown(VK_NUMPAD0) || trainer_switch_pressed() || IsKeyDown(VK_BACK);
if (up) *up = IsKeyDown(VK_NUMPAD8);
if (down) *down = IsKeyDown(VK_NUMPAD2);
if (r) *r = IsKeyDown(VK_NUMPAD6);
if (l) *l = IsKeyDown(VK_NUMPAD4);
}前文中多次提到過update_features,那麼作為本次代碼講解的結束,我想再合適不過了void update_features() //從名稱就可以看出,這裡主要用做刷新、更新作用,當然這些你都可以自定義的
{
update_status_text(); //前面提到過,不再說嘛
update_vehicle_guns(); //本函數作用類似於我們正在講解的,也不做說明
// changing player model if died/arrested while being in another skin, since it can cause inf loading loop
if (skinchanger_used) //先追蹤變量,其實問中我多次用到參數變量等詞彙,有時候是一個意思,因為我不是專業寫教程的,難免有時候自己錯亂一下,可以得到 該值為true的情況下,必須是在更換過人物模型後,這2段都是為了檢查人物如果死亡後,狀態又在刷新,防止角色卡死
check_player_model();
// wait until player is ready, basicly to prevent using the trainer while player is dead or arrested
while (ENTITY::IS_ENTITY_DEAD(PLAYER::PLAYER_PED_ID()) || PLAYER::IS_PLAYER_BEING_ARRESTED(PLAYER::PLAYER_ID(), TRUE)) //本段內容同上,都是為了檢查角色狀態的, 死亡或正在創建過程中 那麼腳本就繼續等待 循環判斷指令
WAIT(0);
// read default feature values from the game
featureWorldRandomCops = PED::CAN_CREATE_RANDOM_COPS() == TRUE; //給featureWorldRandomCops變量賦予默認值true,並讓SDK中我們查詢得到的是否允許創建隨機的警察該值也為true.
// common variables
Player player = PLAYER::PLAYER_ID(); //變量定義,玩家ID,這3段主要是為了後面的書寫進行定義的,這裡的第一個Player,是SDK包含的自定義數據類型,可以看作是 DWORD數據類型
Ped playerPed = PLAYER::PLAYER_PED_ID(); //角色模型ID 同上
BOOL bPlayerExists = ENTITY::DOES_ENTITY_EXIST(playerPed); //邏輯數據類型玩家是否退出 傳遞
// player invincible
if (featurePlayerInvincibleUpdated) //追蹤該變量featurePlayerInvincibleUpdated可以知道,這段變量是用於判斷是否進行過玩家無敵的操作,作用在於,每次進行還原,再進行無敵操作,下面的代碼就能夠看的出來
{
if (bPlayerExists && !featurePlayerInvincible) // 玩家是否退出 並且檢查另外一個變量,上面的featurePlayerInvincibleUpdated同時還控制著 ON OFF開關的顯示
PLAYER::SET_PLAYER_INVINCIBLE(player, FALSE); //SDK部分 禁止玩家無敵
featurePlayerInvincibleUpdated = false;
}
if (featurePlayerInvincible) //同理上面那段
{
if (bPlayerExists) //檢查玩家是否退出遊戲
PLAYER::SET_PLAYER_INVINCIBLE(player, TRUE); //沒有,那就無敵吧
}
// player never wanted
if (featurePlayerNeverWanted) //同理上面,因為是SDK部分,所以不做說明,所以說如果能夠搞清楚遊戲的SDK,那麼你可以實現很多的功能,這是一個艱巨而漫長的過程。
{
if (bPlayerExists)
PLAYER::CLEAR_PLAYER_WANTED_LEVEL(player);
}
// police ignore player
if (featurePlayerIgnoredUpdated)
{
if (bPlayerExists)
PLAYER::SET_POLICE_IGNORE_PLAYER(player, featurePlayerIgnored);
featurePlayerIgnoredUpdated = false;
}
// player special ability
if (featurePlayerUnlimitedAbility)
{
if (bPlayerExists)
PLAYER::_RECHARGE_SPECIAL_ABILITY(player, 1);
}
// player no noise
if (featurePlayerNoNoiseUpdated)
{
if (bPlayerExists && !featurePlayerNoNoise)
PLAYER::SET_PLAYER_NOISE_MULTIPLIER(player, 1.0);
featurePlayerNoNoiseUpdated = false;
}
if (featurePlayerNoNoise)
PLAYER::SET_PLAYER_NOISE_MULTIPLIER(player, 0.0);
// player fast swim
if (featurePlayerFastSwimUpdated)
{
if (bPlayerExists && !featurePlayerFastSwim)
PLAYER::_SET_SWIM_SPEED_MULTIPLIER(player, 1.0);
featurePlayerFastSwimUpdated = false;
}
if (featurePlayerFastSwim)
PLAYER::_SET_SWIM_SPEED_MULTIPLIER(player, 1.49);
// player fast run
if (featurePlayerFastRunUpdated)
{
if (bPlayerExists && !featurePlayerFastRun)
PLAYER::_SET_MOVE_SPEED_MULTIPLIER(player, 1.0);
featurePlayerFastRunUpdated = false;
}
if (featurePlayerFastRun)
PLAYER::_SET_MOVE_SPEED_MULTIPLIER(player, 1.49);
// player super jump
if (featurePlayerSuperJump)
{
if (bPlayerExists)
GAMEPLAY::SET_SUPER_JUMP_THIS_FRAME(player);
}
// weapon
if (featureWeaponFireAmmo)
{
if (bPlayerExists)
GAMEPLAY::SET_FIRE_AMMO_THIS_FRAME(player);
}
if (featureWeaponExplosiveAmmo)
{
if (bPlayerExists)
GAMEPLAY::SET_EXPLOSIVE_AMMO_THIS_FRAME(player);
}
if (featureWeaponExplosiveMelee)
{
if (bPlayerExists)
GAMEPLAY::SET_EXPLOSIVE_MELEE_THIS_FRAME(player);
}
// weapon no reload
if (bPlayerExists && featureWeaponNoReload) //上面的都差不多,從這裡稍不一樣,那就從這裡開始
{
Hash cur; //hash數據類型我從來沒有接觸過,能網上百度來的,我絕對不會在這裡跟大家說
if (WEAPON::GET_CURRENT_PED_WEAPON(playerPed, &cur, 1)) //這裡不是很清楚,那就去查SDK Any GET_CURRENT_PED_WEAPON(Ped ped, Hash *weapHash, BOOL p2) // 0xB0237302 判斷 獲取模型手上的槍的hash值,這到底是什麼參數,我暈 如果為真反正就是判斷玩家手上是否有槍就對了,並且把這把槍的值賦到cur變量中
{
if (WEAPON::IS_WEAPON_VALID(cur)) //如果是一把有效的槍,或者說你把槍切換出來了
{
int maxAmmo; //定義一個最大的子彈數
if (WEAPON::GET_MAX_AMMO(playerPed, cur, &maxAmmo)) //獲取這把槍的最大彈藥數,這裡是獲取,而不是制定,也就說,你可以不要這段代碼,然後下面那段代碼,按照我的方法修改是同理
{
WEAPON::SET_PED_AMMO(playerPed, cur, maxAmmo); //這樣修改 WEAPON::SET_PED_AMMO(playerPed, cur, 10) 這樣也可以,以此類推。不過這樣改了就不能不用裝彈了,原理未知,光從代碼上看,還不足以實現無須裝彈
maxAmmo = WEAPON::GET_MAX_AMMO_IN_CLIP(playerPed, cur, 1); //最大彈夾數
if (maxAmmo > 0) //如果彈夾高於0
WEAPON::SET_AMMO_IN_CLIP(playerPed, cur, maxAmmo); //那麼設置一個最大彈夾
}
}
}
}
// player's vehicle invincible
if (featureVehInvincibleUpdated) //載具無敵,同理上面,先進行一次還原,再進行無敵操作
{
if (bPlayerExists && !featureVehInvincible && PED::IS_PED_IN_ANY_VEHICLE(playerPed, 0))
{
Vehicle veh = PED::GET_VEHICLE_PED_IS_USING(playerPed);
ENTITY::SET_ENTITY_INVINCIBLE(veh, FALSE);
ENTITY::SET_ENTITY_PROOFS(veh, 0, 0, 0, 0, 0, 0, 0, 0);
VEHICLE::SET_VEHICLE_TYRES_CAN_BURST(veh, 1);
VEHICLE::SET_VEHICLE_WHEELS_CAN_BREAK(veh, 1);
VEHICLE::SET_VEHICLE_CAN_BE_VISIBLY_DAMAGED(veh, 1);
}
featureVehInvincibleUpdated = false;
}
if (featureVehInvincible)
{
if (bPlayerExists && PED::IS_PED_IN_ANY_VEHICLE(playerPed, 0))
{
Vehicle veh = PED::GET_VEHICLE_PED_IS_USING(playerPed);
ENTITY::SET_ENTITY_INVINCIBLE(veh, TRUE);
ENTITY::SET_ENTITY_PROOFS(veh, 1, 1, 1, 1, 1, 1, 1, 1); //變動處 SDK:void SET_ENTITY_PROOFS(Entity Entity, BOOL bulletProof, BOOL fireProof, BOOL explosionProof, BOOL collisionProof, BOOL meleeProof, Any p6, Any p7, Any p8) // 0x7E9EAB66 對應SDK就一目瞭然
VEHICLE::SET_VEHICLE_TYRES_CAN_BURST(veh, 0);
VEHICLE::SET_VEHICLE_WHEELS_CAN_BREAK(veh, 0);
VEHICLE::SET_VEHICLE_CAN_BE_VISIBLY_DAMAGED(veh, 0);
}
}
// player's vehicle boost
if (featureVehSpeedBoost && bPlayerExists && PED::IS_PED_IN_ANY_VEHICLE(playerPed, 0))
{
Vehicle veh = PED::GET_VEHICLE_PED_IS_USING(playerPed);
DWORD model = ENTITY::GET_ENTITY_MODEL(veh);
bool bUp = IsKeyDown(VK_NUMPAD9);
bool bDown = IsKeyDown(VK_NUMPAD3);
if (bUp || bDown) //這裡為汽車加速,並定義了2個熱鍵,用於實現汽車加速的
{
float speed = ENTITY::GET_ENTITY_SPEED(veh);
if (bUp)
{
speed += speed * 0.05f; //speed=speed+speed*0.05f
VEHICLE::SET_VEHICLE_FORWARD_SPEED(veh, speed);
} else
if (ENTITY::IS_ENTITY_IN_AIR(veh) || speed > 5.0)
VEHICLE::SET_VEHICLE_FORWARD_SPEED(veh, 0.0);
}
}
// time pause
if (featureTimePausedUpdated)
{
TIME::PAUSE_CLOCK(featureTimePaused);
featureTimePausedUpdated = false;
}
// time sync
if (featureTimeSynced)
{
time_t now = time(0);
tm t;
localtime_s(&t, &now);
TIME::SET_CLOCK_TIME(t.tm_hour, t.tm_min, t.tm_sec);
}
if (featureVehAllMod) //載具自動改造,具體自己去查SDK
{
Vehicle veh = PED::GET_VEHICLE_PED_IS_USING(playerPed);
VEHICLE::SET_VEHICLE_MOD_KIT(veh, 0); // sdk 解釋 SET_VEHICLE_MOD_KIT(Vehicle vehicle, int unknown) // 0xB8132158 SDK部分都還暫時不明所以,沒人更新,如果你知道,你可以去管網更新,這樣大家以後下載最新的SDK,就有解釋
VEHICLE::SET_VEHICLE_COLOURS(veh, 120, 120);
VEHICLE::SET_VEHICLE_NUMBER_PLATE_TEXT(veh, (Any*)"KINKYHAX");
VEHICLE::SET_VEHICLE_NUMBER_PLATE_TEXT_INDEX(veh, 1);
VEHICLE::TOGGLE_VEHICLE_MOD(veh, 18, 1);
VEHICLE::TOGGLE_VEHICLE_MOD(veh, 22, 1);
VEHICLE::SET_VEHICLE_MOD(veh, 16, 5, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 12, 2, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 11, 3, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 14, 14, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 15, 3, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 13, 2, 0);
VEHICLE::SET_VEHICLE_WHEEL_TYPE(veh, 6);
VEHICLE::SET_VEHICLE_WINDOW_TINT(veh, 5);
VEHICLE::SET_VEHICLE_MOD(veh, 23, 19, 1);
VEHICLE::SET_VEHICLE_MOD(veh, 0, 1, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 1, 1, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 2, 1, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 3, 1, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 4, 1, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 5, 1, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 6, 1, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 7, 1, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 8, 1, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 9, 1, 0);
VEHICLE::SET_VEHICLE_MOD(veh, 10, 1, 0);
}
if (featureVehSlide)
{
VEHICLE::SET_VEHICLE_REDUCE_GRIP(PED::GET_VEHICLE_PED_IS_IN(PLAYER::PLAYER_PED_ID(), 0), 1);
}
else
{
VEHICLE::SET_VEHICLE_REDUCE_GRIP(PED::GET_VEHICLE_PED_IS_IN(PLAYER::PLAYER_PED_ID(), 0), 0);
}
if (featureVehRainbow) //這裡說下彩虹冊車,說實話我還不知道update_features()是如何自動刷新的,因為代碼我還沒有全部看完,慢慢講解,慢慢自己研究看看。
{
Vehicle veh = PED::GET_VEHICLE_PED_IS_USING(playerPed);
DWORD model = ENTITY::GET_ENTITY_MODEL(veh);
if (PED::IS_PED_IN_ANY_VEHICLE) //如果玩家在車輛內,其實這裡有個BUG的,應該還要加一段判斷 PLAYER::IS_PLAYER_CONTROL_ON(player) && PED::IS_PED_IN_ANY_VEHICLE(playerPed, 0)) 這樣才不會在還沒有上車的時候就出現問題.
{
VEHICLE::SET_VEHICLE_CUSTOM_PRIMARY_COLOUR(veh, rand() % 255, rand() % 255, rand() % 255); //設置隨機顏色
WAIT(150); //延時150
VEHICLE::SET_VEHICLE_CUSTOM_SECONDARY_COLOUR(veh, rand() % 255, rand() % 255, rand() % 255);
WAIT(150);
}
}
if (featureVehStickyCar)
{
if (PED::IS_PED_IN_ANY_VEHICLE(PLAYER::PLAYER_PED_ID(), 0))
{
int myVehicle = PED::GET_VEHICLE_PED_IS_USING(PLAYER::PLAYER_PED_ID());
VEHICLE::SET_VEHICLE_ON_GROUND_PROPERLY(myVehicle);
}
}
// hide hud
if (featureMiscHideHud)
UI::HIDE_HUD_AND_RADAR_THIS_FRAME();
}5、SDK整理翻譯
網站地址:http://www.dev-c.com/nativedb/ 該SDK由網友維護更新,可隨時去更新,這樣才會有一些新的備註,不會出現類似於unnkow情況發生.SDK部分需要很長時間研究
PLAYER 玩家部分
ENTITY 實體
PED 角色模型
VEHICLE 車輛相關
OBJECT 對象
AI AI
GAMEPLAY 操作類
AUDIO 音樂類
CUTSCENE 動畫類
INTERIOR 室內
CAM 攝像機
WEAPON 武器
ITEMSET
STREAMING
SCRIPT 腳本
UI 界面
GRAPHICS 圖形
STATS 統計
BRAIN
MOBILE 手機
APP
TIME 時間
PATHFIND
CONTROLS 控制
DATAFILE
FIRE 火
DECISIONEVENT
ZONE
ROPE 範圍
WATER 水
WORLDPROBE
NETWORK 網絡
NETWORKCASH 高級網絡 金錢?
DLC1
DLC2
SYSTEM 系統
DECORATOR
UNK_SC
UNK
6、文件結構
SDK部分:
sourceincenums.h
sourceincmain.h
sourceinc
ativeCaller.h
sourceincatives.h SDK主要文件,網上更新也是更新該文件
sourceinc ypes.h 自定義數據類型文件
Lib文件:
sourcelibScriptHookV.lib
可編寫腳本文件:
sourcelibsamplesNativeTrainerkeyboard.h
sourcelibsamplesNativeTrainerkeyboard.cpp
sourcelibsamplesNativeTrainermain.cpp 看結構就是一個DLL
sourcelibsamplesNativeTrainerscript.cpp 主要代碼存放文件
sourcelibsamplesNativeTrainerscript.h
原始碼:
**** Hidden Message *****
頁:
[1]