آموزش برنامه نویسی و ساخت مود GTA V – بخش دوم
در بخش قبل، به مقدمات برنامهنویسی و ساخت مود GTA V اشاره کردیم، اما اکنون در این بخش که بخش دوم است، میخواهیم مودی بنویسیم که بتواند روی تعداد ستارههای پلیس تاثیر بگذارد. و البته به همراه آن موارد مهم دیگری را نیز یاد خواهیم گرفت. بنابراین در ادامه با فول کده همراه باشید.
پروژهی Wanted Level
یک پروژه به روشی که در بخش قبلی گفته شد ایجاد کرده و قسمتهای مهم آن را پیاده سازی کنید.
میخواهیم با فشردن کلید «O» از روی کیبورد، یک واحد به تعداد ستارهها اضافه شده و با فشردن کلید «I»، یک واحد از آنها کم شود! همچنین قصد داریم در ادامه کاری کنیم تا اگر مقدار به انتها رسید و پنج ستاره شد، با فشردن دوبارهی «O»، مقدار ستارهها صفر شده و از ابتدا ادامه پیدا کند و همین مورد را برای «I» و بهصورت برعکس خواهیم نوشت. بنابراین ابتدا هردو کلید را درون رویداد «KeyDown» پیادهسازی میکنیم:
private void OnKeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.O) { } else (e.KeyCode == Keys.I) { } }
طبق دانش سیشارپ و داتنت خود، همانند بخشی قبلی شرطی برای کلیدهای «O» و «I» مینویسیم. سپس کد خود را به صورت زیر تکمیل میکنیم:
private void OnKeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.O) { Game.Player.WantedLevel = Game.Player.WantedLevel >= 5 ? 0 : Game.Player.WantedLevel + 1; } else (e.KeyCode == Keys.I) { Game.Player.WantedLevel = Game.Player.WantedLevel <= 0 ? 5 : Game.Player.WantedLevel - 1; } }
ویژگی «WantedLevel» بازیکن، به تعداد ستارههای تحت تعقیب بازیکن مربوط میشود و از نوع عدد صحیح است. در واقع این ویژگی تنها میتواند مقدار 0 تا 5 را به خود بگیرد! چرا که تنها 5 تا ستاره داریم و مقدار 0 یعنی ستارهای نداریم. حالا با یک شرطِ اپراتوریِ ساده در زمان فشردن کلید «O»، بررسی میکنیم که اگر مقدار بزرگتر یا مساوی 5 بود، تعداد ستارهها 0 شود و اگر مقدار کوچکتر از 5 بود، یکی به مقدار قبلی اضافه شود (یعنی ستارهها یک واحد زیاد شود).با این حساب، در زمان فشردن کلید «I» نیز شرط کوچکتر مساویِ 0 را بررسی میکنیم.
حالا شاید بخواهید وقتی تعداد ستارهها را با کلید «I» به انتها میرسانید، دیگر از ابتدا شروع نشده و بهجای آن یک پیام چاپ شود که مقدار به انتها رسیده است! بنابراین بهصورت زیر عمل کنید:
private void OnKeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.O) { if (Game.Player.WantedLevel < 5) Game.Player.WantedLevel++; else UI.ShowSubtitle("Wanted Level in Maximum"); } else if (e.KeyCode == Keys.I) { if (Game.Player.WantedLevel > 0) Game.Player.WantedLevel--; else UI.ShowSubtitle("Wanted Level in Minimum"); } }
در اینجا اولا مجبور شدیم تا از شرط if به جای شرط سادهی اپراتوری استفاده کنیم که البته این قواعد خود زبان سیشارپ است. ثانیا در زمانی که مقدار ستارهها به انتها یا ابتدا رسیده است و دیگر قابل کم و زیاد شدن نیست، از کلاس «UI» استفاده کرده و متد «ShowSubtitle» آن را صدا زدیم. این متد یک زیرنویس در بازی نمایش میدهد (همانند زیرنویسهای خود بازی). و ورودی دوم آن نیز زمان نمایش زیرنویس را تعیین میکند که ما در اینجا زمان پیشفرض آن را در نظر گرفته و ورودی دوم آن را به متد ارسال نکردیم. همچنین لازم بهذکر است که ورودی زمان نیز برحسب میلیثانیه بوده و هر 1000 میلی ثانیه برابر یک ثانیه است.
معزلی به نام کلید
شاید بخواهیم کاری کنیم که کار کردن کلیدهای «O» و «I»، به نگهداشتن کلید «Ctrl» نیز نیاز داشته باشد و به عبارتی مودی که نوشتیم، با گرفتن کلیدهای ترکیبی «Ctrl + O» و «Ctrl +I» کار کند. البته این بیشتر درس سیشارپ است؛ اما هدف من از گفتن آن چیز دیگریست که توضیح خواهم داد. بنابراین میتوانیم به صورت زیر عمل کنیم:
private void OnKeyDown(object sender, KeyEventArgs e) { if (e.Control) { if (e.KeyCode == Keys.O) { if (Game.Player.WantedLevel < 5) Game.Player.WantedLevel++; else UI.ShowSubtitle("Wanted Level in Maximum"); } else if (e.KeyCode == Keys.I) { if (Game.Player.WantedLevel > 0) Game.Player.WantedLevel--; else UI.ShowSubtitle("Wanted Level in Minimum"); } } }
همانطور که میبینید، ابتدا باید بررسی کنیم که کلید «Ctrl» گرفته شده است یا نه و برای انحام آن، از ویژگی «Control» آبجکت «e» استفاده میکنیم. این ویژگی یک مقداری از نوع کلاس «bool» است که اگر «Ctrl» گرفته شده باشد، مقدار آن برابر «true» خواهد بود. ادامهی کد نیز همان چیزهای قبلی میباشد.
اما اگر شما سری مودهای «JulioNib» که اکثر آنها پولی میباشند و چندمورد از آنها را بهصورت رایگان در سایت منتشر کردهایم را تست کرده باشید، متوجه این میشوید که سازندهی این مودها، یک منوی کلی برای مودهای خود تعریف کرده است که با کلیدهای ترکیبی «Ctrl+N» باز میشود و سپس مودها نیز در آن لیست قرار دارند. یا یک اسکریپت دیگری که توسط شخصی توسعه داده شده بود و با کمک آن میتوان مودی را توسط گرفتن یک شمارهی خاصی از تلفن همراه در داخل بازی فعال و غیرفعال کرد. بدین روش تداخلها به وجود نمیآیند و بهتر است ما نیز برای مودهای خود یک کلید ترکیبی تعریف کنیم و یک منوی کلی بسازیم.
در آینده با ساخت این موارد آشنا خواهیم شد و حتی به روش استفاده از اسکریپت فعال کردن مود با شمارهتلفن نیز خواهیم پرداخت. که فعلا در حد کلیشیهای این موضوع را بدانید بهتر است و در آینده آن را عملی خواهیم کرد.
فریز کردن ستارهها
اجازه دهید تا با در نظر گرفتن یک قابلیت دیگر، از رویداد «Tick» هم استفاده کنیم. این قابلیتی که در نظر داریم، این اجازه را میدهد تا تعداد سطح تعقیب یا ستارههای پلیس را روی یک مقدار خاصی تنظیم و قفل کنیم. بنابراین دیگر تعداد ستارهها از آن مقدار کمتر یا بیشتر نخواهد شد مگر به خواست ما! اما حالا به نظرتان چطور چنین چیزی را بنویسیم؟!
میدانیم که رویداد Tick، قبل از نمایش هر فریم از بازی اجرا میشود! بنابراین بایستی در این رویداد کاری کنیم تا مقدار «WantedLevel» بازیکن، روی همان چیزی که تنظیم شده است باقی بماند! اما منطق خود را چگونه باید پیاده کنیم؟!
ما برای نوشتن چنین چیزی، ابتدا دو متغیر سراسری در نظر میگیریم:
private bool isFreezedWantedLevel; private int lastWantedLevel;
متغیر «isFreezedWantedLevel» برای این است که بفهمیم در حال حاظر قابلیت فریز (قفل تعداد ستارهها) فعال است یا خیر! و متغیر «lastWantedLevel» نیز آخرین مقدار تنظیم شده را در خود نگه خواهد داشت. حالا به رویداد «Tick» میرویم:
private void OnTick(object sender, EventArgs e) { if (isFreezedWantedLevel) Game.Player.WantedLevel = lastWantedLevel; lastWantedLevel = Game.Player.WantedLevel; }
در اینجا، ابتدا بررسی میکنیم که اگر فریز ستارهها فعال بود، مقدار تحت تعقیب بازیکن را به آخرین «lastWantedLevel» ای که تنظیم شده است تغییر دهد. اما علاوه بر این، در خارج از شرط و در انتهای هرفریم، مقدار «lastWantedLevel» را به مقدار فعلی تحت تعقیب بازیکن تغییر میدهیم! شاید بگویید چرا؟! سوال خوبی است! چون ممکن است تعداد ستارهها توسط مود دیگری تنظیم شده باشد؛ ولی «lastWantedLevel» ما روی مقدار قدیمی باشد. و بدین دلیل مقدار را در اینجا به روز میکنیم. البته در رویداد «KeyDown» نیز باید مقدار آن را به روز کنیم.
حالا فرض کنید که میخواهیم قابلیت فریز با کلید ترکیبی «Ctrl + U» فعال و غیرفعال شود. بنابراین به صورت زیر کد «KeyDown» را تکمیل میکنیم:
private void OnKeyDown(object sender, KeyEventArgs e) { if (e.Control) { if (e.KeyCode == Keys.O) { if (Game.Player.WantedLevel < 5) { Game.Player.WantedLevel++; lastWantedLevel = Game.Player.WantedLevel; } else UI.ShowSubtitle("Wanted Level in Maximum"); } else if (e.KeyCode == Keys.I) { if (Game.Player.WantedLevel > 0) { Game.Player.WantedLevel--; lastWantedLevel = Game.Player.WantedLevel; } else UI.ShowSubtitle("Wanted Level in Minimum"); } else if (e.KeyCode == Keys.U) { if (isFreezedWantedLevel) UI.ShowSubtitle("Wanted Level UnFreezed"); else UI.ShowSubtitle("Wanted Level Freezed"); isFreezedWantedLevel = !isFreezedWantedLevel; } } }
داخل شرط «Ctrl + U»، بررسی میکنیم که اگر قابلیت فریز در حال حاظر فعال بود، زیرنویس غیرفعال شدن را نمایش دهد و اگر غیرفعال بود، زیرنویس فعال شدن را نمایش دهد. همچنین در انتهای شرط نیز مقدار فعلی آن را برابر با مقدار برعکس یا مخالف خود میکنیم. (Toggle کردن)
نکتهی مهم این است که در داخل کلیدهای «O» و «I» نیز مقدار «lastWantedLevel» را به روز میکنیم. چرا که اگر این کار را انجام ندهیم، در زمان فریز بودن نمیتوانیم به صورت دستی مقدار را تغییر دهیم! چون رویداد «Tick» بعد از «KeyDown» اجرا میشود. (البته این را فراموش نکنید که با «KeyUp» نیز میتوانیم این کلیدها را تنظیم کنیم و تنها فرق این است که اگر انگشت مبارک خود را روی کلیدی نگه داریم و رها نکنیم، رویداد «KeyDown» مدام اجرا میشود! اما «KeyUp» تنها یک بار اجرا خواهد شد و سپس باید دوباره فشار دهیم و رها کنیم. پس اگر میخواهید با نگه داشتن کلید «Ctrl + O» و «Ctrl + I»، مقدار به تدریج کم و زیاد شود، از «KeyDown» استفاده کنید و درغیر اینصورت نیازی نیست.)
کدنهایی ما بهصورت زیر خواهد بود:
using System; using System.Windows.Forms; using GTA; namespace FuLLKade { public class WantedLevel : Script { private bool isFreezedWantedLevel; private int lastWantedLevel; public WantedLevel() { Tick += OnTick; KeyDown += OnKeyDown; } private void OnTick(object sender, EventArgs e) { if (isFreezedWantedLevel) Game.Player.WantedLevel = lastWantedLevel; lastWantedLevel = Game.Player.WantedLevel; } private void OnKeyDown(object sender, KeyEventArgs e) { if (e.Control) { if (e.KeyCode == Keys.O) { if (Game.Player.WantedLevel < 5) { Game.Player.WantedLevel++; lastWantedLevel = Game.Player.WantedLevel; } else UI.ShowSubtitle("Wanted Level in Maximum"); } else if (e.KeyCode == Keys.I) { if (Game.Player.WantedLevel > 0) { Game.Player.WantedLevel--; lastWantedLevel = Game.Player.WantedLevel; } else UI.ShowSubtitle("Wanted Level in Minimum"); } else if (e.KeyCode == Keys.U) { if (isFreezedWantedLevel) UI.ShowSubtitle("Wanted Level UnFreezed"); else UI.ShowSubtitle("Wanted Level Freezed"); isFreezedWantedLevel = !isFreezedWantedLevel; } } } } }
به زودی با درس بعدی … منتظر باشید.
سلام. خیلی ممنونم از این مطلب.
واقعا خوشم اومد. من از بچگی به برنامه نویسی علاقه مند بودم و دوست داشتم کار های خودم رو داشته باشم. خب سری gta هم یک بازی کامل و جامع و آماده تغییرات هست ولی تا الان نمیدونستم چطور باید این تغییرات رو اعمال کرد.
لطفا هر چه زود تر ادامه آموزش رو تو سایت قرار بدین.
سلام. سپاس از نظر لطف شما بزرگوارید
متاسفانه فعلا مشغله زیادی دارم و فرصت نیست. ان شالله در آینده
موفق باشید
منم
کی بخش سوم میاد هنوز نیومده ؟
تابستون ادامه میدیم.
خیلی ممنون مثلا من میخوام یه مود بسازم که مثلا در همه ی خونه ها باز بشه و اون بتونه بره توش ؟
هرچیزی که به ذهن میرسه رو نمیشه ساخت یا حداقل ساختنش خیلی پیچیدس. اینکه داخل هر خونه بره نمیشه چون هر خونهای فضای داخلی نداره مگه اینکه تله پورت شه یه جای دیگه. البته چنین مودیم که میگید قبلا ساختن منتها تو همه خونهها نمیره و فقط به مواردی میره که امکانش وجود داره 🙂
ببخشید می خواستم بگم لطفا آموزشی که بشه با این مود ها آنلاین بازی کردن بدون بن شدن از سرور رو بگذارید