diff --git a/app/src/main/kotlin/com/github/iamrezamousavi/mafia/MainActivity.kt b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/MainActivity.kt index 0610210..32d350e 100644 --- a/app/src/main/kotlin/com/github/iamrezamousavi/mafia/MainActivity.kt +++ b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/MainActivity.kt @@ -1,20 +1,28 @@ package com.github.iamrezamousavi.mafia +import android.content.Context +import android.content.SharedPreferences import android.os.Bundle -import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment +import com.github.iamrezamousavi.mafia.data.local.PREF_APP_LANGUAGE +import com.github.iamrezamousavi.mafia.data.local.preferences import com.github.iamrezamousavi.mafia.databinding.ActivityMainBinding +import com.github.iamrezamousavi.mafia.utils.getContextWrapper -class MainActivity : AppCompatActivity() { +class MainActivity : + AppCompatActivity(), + SharedPreferences.OnSharedPreferenceChangeListener { private lateinit var binding: ActivityMainBinding - private val mainViewModel: MainViewModel by viewModels() - private lateinit var navHostFragment: NavHostFragment private lateinit var navController: NavController + override fun attachBaseContext(newBase: Context) { + super.attachBaseContext(getContextWrapper(newBase)) + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) @@ -23,5 +31,18 @@ class MainActivity : AppCompatActivity() { navHostFragment = supportFragmentManager.findFragmentById(R.id.fragmentContainerView) as NavHostFragment navController = navHostFragment.navController + + preferences.registerOnSharedPreferenceChangeListener(this) + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + if (key == PREF_APP_LANGUAGE) { + recreate() + } + } + + override fun onDestroy() { + super.onDestroy() + preferences.unregisterOnSharedPreferenceChangeListener(this) } } diff --git a/app/src/main/kotlin/com/github/iamrezamousavi/mafia/data/local/SharedPreferences.kt b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/data/local/SharedPreferences.kt new file mode 100644 index 0000000..e76737f --- /dev/null +++ b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/data/local/SharedPreferences.kt @@ -0,0 +1,18 @@ +package com.github.iamrezamousavi.mafia.data.local + +import android.content.Context +import android.content.SharedPreferences +import androidx.core.content.edit +import com.github.iamrezamousavi.mafia.data.model.Language +import com.github.iamrezamousavi.mafia.data.model.toLanguage + +const val PREF_APP_LANGUAGE = "AppLanguage" + +val Context.preferences: SharedPreferences + get() = getSharedPreferences("${packageName}_preferences", Context.MODE_PRIVATE) + +fun SharedPreferences.saveLanguage(language: Language) = edit { + putString(PREF_APP_LANGUAGE, language.code) +} + +fun SharedPreferences.getLanguage() = getString(PREF_APP_LANGUAGE, Language.FA.code).toLanguage()!! diff --git a/app/src/main/kotlin/com/github/iamrezamousavi/mafia/data/model/Language.kt b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/data/model/Language.kt new file mode 100644 index 0000000..719eab3 --- /dev/null +++ b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/data/model/Language.kt @@ -0,0 +1,17 @@ +package com.github.iamrezamousavi.mafia.data.model + +import java.util.Locale + +enum class Language( + val code: String, + val nativeName: String +) { + FA("fa", "فارسی"), + EN("en", "English"); + + fun asSystemLocale() = Locale(code) +} + +fun String?.toLanguage() = Language.entries.find { it.code == this } + +fun String?.toNativeLanguage() = Language.entries.find { it.nativeName == this } diff --git a/app/src/main/kotlin/com/github/iamrezamousavi/mafia/utils/Configuration.kt b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/utils/Configuration.kt new file mode 100644 index 0000000..d6f5af2 --- /dev/null +++ b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/utils/Configuration.kt @@ -0,0 +1,12 @@ +package com.github.iamrezamousavi.mafia.utils + +import android.os.Build +import androidx.annotation.ChecksSdkIntAtLeast + +@get:ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU) +inline val isAtLeastAndroid13 + get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU + +@get:ChecksSdkIntAtLeast(api = Build.VERSION_CODES.N) +inline val isAtLeastAndroid7 + get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N diff --git a/app/src/main/kotlin/com/github/iamrezamousavi/mafia/utils/Locale.kt b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/utils/Locale.kt new file mode 100644 index 0000000..96f0a1b --- /dev/null +++ b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/utils/Locale.kt @@ -0,0 +1,37 @@ +package com.github.iamrezamousavi.mafia.utils + +import android.content.Context +import android.content.ContextWrapper +import com.github.iamrezamousavi.mafia.data.local.getLanguage +import com.github.iamrezamousavi.mafia.data.local.preferences +import java.util.Locale + +@Suppress("DEPRECATION") +fun getContextWrapper(context: Context): ContextWrapper { + val resources = context.resources + val configuration = resources.configuration + + val language = context.preferences.getLanguage() + val locale = Locale(language.code) + Locale.setDefault(locale) + + val currentLocale = + if (isAtLeastAndroid7) { + configuration.locales.get(0) + } else { + configuration.locale + } + + if (currentLocale.language == language.code) { + return ContextWrapper(context) + } + + configuration.setLocale(locale) + + if (isAtLeastAndroid7) { + context.createConfigurationContext(configuration) + } + resources.updateConfiguration(configuration, resources.displayMetrics) + + return ContextWrapper(context) +} diff --git a/app/src/main/kotlin/com/github/iamrezamousavi/mafia/view/MainFragment.kt b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/view/MainFragment.kt index a5f60d1..e3cf108 100644 --- a/app/src/main/kotlin/com/github/iamrezamousavi/mafia/view/MainFragment.kt +++ b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/view/MainFragment.kt @@ -73,6 +73,10 @@ class MainFragment : Fragment() { } } + binding.mainToolBar.setNavigationOnClickListener { + findNavController().navigate(R.id.action_mainFragment_to_settingsFragment) + } + binding.mainToolBar.setOnMenuItemClickListener { menuItem -> when (menuItem.itemId) { R.id.menuItemSelectAll -> { diff --git a/app/src/main/kotlin/com/github/iamrezamousavi/mafia/view/SettingsFragment.kt b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/view/SettingsFragment.kt new file mode 100644 index 0000000..cf02209 --- /dev/null +++ b/app/src/main/kotlin/com/github/iamrezamousavi/mafia/view/SettingsFragment.kt @@ -0,0 +1,79 @@ +package com.github.iamrezamousavi.mafia.view + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.AdapterView +import android.widget.ArrayAdapter +import androidx.fragment.app.Fragment +import com.github.iamrezamousavi.mafia.data.local.getLanguage +import com.github.iamrezamousavi.mafia.data.local.preferences +import com.github.iamrezamousavi.mafia.data.local.saveLanguage +import com.github.iamrezamousavi.mafia.data.model.Language +import com.github.iamrezamousavi.mafia.data.model.toNativeLanguage +import com.github.iamrezamousavi.mafia.databinding.FragmentSettingsBinding + +class SettingsFragment : Fragment() { + + private lateinit var binding: FragmentSettingsBinding + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentSettingsBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setupLanguageSpinner() + } + + private fun setupLanguageSpinner() { + val currentLanguage = requireContext().preferences.getLanguage() + val items = Language + .entries + .map { it.nativeName } + .sorted() + .let { languages -> + listOf(currentLanguage.nativeName) + + languages.filter { it != currentLanguage.nativeName } + } + val arrayAdapter = ArrayAdapter( + requireContext(), + android.R.layout.simple_spinner_item, + items + ).also { adapter -> + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + } + + binding.langSpinner.apply { + adapter = arrayAdapter + onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected( + parent: AdapterView<*>, + view: View?, + position: Int, + id: Long + ) { + val selectedItem = parent.getItemAtPosition(position).toString() + val newLanguage = selectedItem.toNativeLanguage() + val currentLang = requireContext().preferences.getLanguage() + if (newLanguage != currentLang) { + if (newLanguage != null) { + requireContext().preferences.saveLanguage(newLanguage) + setSelection(0) + } + } + } + + @Suppress("EmptyFunctionBlock") + override fun onNothingSelected(parent: AdapterView<*>?) { + } + } + } + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 48a314f..9ac55b8 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -4,7 +4,6 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:layoutDirection="rtl" tools:context=".MainActivity"> + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml index d9ddf6b..b6d7b5d 100644 --- a/app/src/main/res/navigation/nav_graph.xml +++ b/app/src/main/res/navigation/nav_graph.xml @@ -17,6 +17,9 @@ app:exitAnim="@anim/slide_to_previous" app:popEnterAnim="@anim/slide_from_previous" app:popExitAnim="@anim/slide_to_next" /> + - \ No newline at end of file + + diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml new file mode 100644 index 0000000..eb92540 --- /dev/null +++ b/app/src/main/res/values-fa/strings.xml @@ -0,0 +1,110 @@ + + + Mafia + نام بازیکن + انتخاب نقش‌ها (%1$d) + لیست بازیکن‌ها + تقسیم نقش‌ها (%1$d) + تقسیم نقش‌ها + راوی + + تعداد بازیکنان: %1$d + تعداد نقش‌های مستقل: %1$d + تعداد شهروندان: %1$d + تعداد مافیا + + حداقل ۳ نفر باید انتخاب کنید + تعداد نقش‌های انتخابی با تعداد بازیکن‌ها مطابقت ندارد + تعداد نقش‌های مافیا زیاد است + همه بازیکن‌ها نقش‌های خود را دیدند.\nآیا میخواهید وارد صفحه راوی شوید؟ + انتخاب همه + حذف بازیکن + بازپخش نقش‌ها + ورود به صفحه راوی + متوجه شدم + تایید + ، + + تنظیمات + زبان + + نقش‌های شهروندان + نقش‌های مافیا + نقش‌های مستقل + + شهروند + شهروند ساده + دکتر + کاراگاه + تک‌تیرانداز + شهردار + محافظ + روانشناس + حرفه‌ای + تفنگ‌دار + قاضی + قهرمان + کشیش + هکر + فرشته + نگهبان + ساقی + + مافیا + مافیا ساده + گادفادر + دکتر لکتر + سایلنسر + تروریست + مذاکره کننده + ناتو + خرابکار + شعبده‌باز + گروگان‌گیر + بادیگارد + بمب‌گذار + + مستقل + مجهول + گرگ‌نما + قاتل + هزار چهره + سندیکا + + + شهروند ساده می‌بایست سعی کند در روز مافیاها را با دقت شناسایی کند و به آن‌ها رای دهد و در شب عمل خاصی را انجام نمی‌دهد. + می‌تواند در شب یک نفر را که احتمال می‌دهد مافیا آن را کشته باشد، نجات می‌دهد + می‌تواند هر شب استعلام نقش یک نفر را از گرداننده بگیرد + تک‌تیرانداز شهروندی است که تفنگ دارد و می‌تواند به کسانی که فکر می‌کند مافیا هستند، شلیک کند. + زمانی که شخصی با رای گیری حذف شود و شهردار حس کند که او شهروند است، می‌تواند تصویب حذف کردن بازیکن را وتو کند. + محافظ می‌تواند جان خود را برای شهروندی که بمب جلوی آن است، فدا کند. قاتل در صورتی از بازی حذف می‌شود که محافظ را بزند. + می‌تواند هر کسی که دارد به روند بازی لطمه می‌زند را ساکت کند. + در شب به هیچ عنوان حذف نمی شود مگر اینکه توسط ساقی گیج شود. + تفنگدار تیر دارد و می‌تواند آن تیرها را به کسانی که فکر می‌کند به آنها نیاز دارند، اهدا کند. + می‌تواند یکبار نتیجه رای‌گیری روز را تغییر دهد یعنی باطل یا ملغی کند + هر دو شب می‌تواند 24 ساعت یکی را بیمه کند که از هر اتفاقی در امان باشد. + کشیش باید تشخیص بدهد که چه کسی توسط ناتاشا سایلنت شده و او را از سایلنت بودن خارج کند. اگر کسی که کشیش انتخاب کند سایلنت نبوده باشد، نطق اضافه دریافت می‌کند. + هکر در شب دوم بازی، یک لیست سه نفره به گرداننده می‌دهد و گرداننده تعداد مافیاهای موجود در لیست را به او می‌گوید + فرشته می‌تواند یک بار کسی را که کشته شده است را به بازی برگرداند. + نگهبان از شهروندان در برابر گروگان‌گیر محافظت می‌کند. + ساقی شب یکی از افراد را انتخاب می‌کند و اون شخص را گیج و منگ می‌کند + + مثل همه حق صحبت دارد، رای می‌دهد و شب‌ها در تصمیم‌گیری‌های تیم مافیا شرکت می‌کند. + رئیس گروه مافیا است. تصمیم نهایی را می‌گیرد و توسط گرداننده به کارآگاه لو داده نمی‌شود. + هر شب یکی از مافیاها را انتخاب و از خطر تیر خوردن در شب نجات می‌دهد. + می‌تواند هر شب یک نفر را برای روز بعد سایلنت کند. + اگر در روز توسط بازیکنان از بازی خارج شود، می‌تواند یکی دیگر از بازیکنان را به همراه خود حذف یا ترور کند. + مذاکره کننده در شب می‌تواند یک نفر را عضوی از دسته‌ی مافیا کند. + در صورتی که ناتو بتواند نقش یکی از شهروندان را درست حدس بزند، آن شهروند از بازی خارج می‌شود. + اگر شخصی را انخاب کند و آن شخص حق تیر داشته باشد و در روز از تیرش استفاده کند، آن تیر به خودش برمی‌گردد. + هر شب می‌تواند قابلیت یک نفر را 24 ساعت از او بگیرد + هر شب یکی از شهروندها را گروگان می‌گیرد و آن شخص نمیتواند آن شب از توانایی‌اش استفاده کند + تا زمانی که در بازی باشد حملات شب به پدرخوانده و معشوقه به او می‌رسند. + جلوی یک شهروند بمب می‌گذارد + + اولین بار که توسط شخصی در شب انتخاب شود به اون جناح می پیوندد + هر سه شب در میان یک نفر را به گرگ‌نما تبدیل می‌کند. + هر شب یک نفر را می‌کشد. + هر شخصی که در روز از بازی خارج شود قابلیت آن شخص را به مدت یک روز می‌گیرد و همچنین در شب هر شخصی روی آن کاری بکند به خود آن شخص بر می گردد. + او تمام نقش‌های مهم بازی را می‌شناسد. در شب کسی نمی‌تواند او را بکشد اما در روز بسیار اسیب‌پذیر است. شرط پیروزی ماندن بین سه نفر آخر است. + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eb92540..62b26a3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,110 +1,110 @@ Mafia - نام بازیکن - انتخاب نقش‌ها (%1$d) - لیست بازیکن‌ها - تقسیم نقش‌ها (%1$d) - تقسیم نقش‌ها - راوی + Player Name + Roles Selection (%1$d) + Players List + Roles Division (%1$d) + Roles Division + Narrator - تعداد بازیکنان: %1$d - تعداد نقش‌های مستقل: %1$d - تعداد شهروندان: %1$d - تعداد مافیا + Number of Players: %1$d + Number of Independent Roles: %1$d + Number of Citizen Roles: %1$d + Number of Mafia Roles - حداقل ۳ نفر باید انتخاب کنید - تعداد نقش‌های انتخابی با تعداد بازیکن‌ها مطابقت ندارد - تعداد نقش‌های مافیا زیاد است - همه بازیکن‌ها نقش‌های خود را دیدند.\nآیا میخواهید وارد صفحه راوی شوید؟ - انتخاب همه - حذف بازیکن - بازپخش نقش‌ها - ورود به صفحه راوی - متوجه شدم - تایید - ، + At least 3 players must be selected + The number of selected roles does not match the number of players + Too many Mafia roles + All players have viewed their roles.\nWould you like to enter the Narrator page? + Select All + Delete Player + Refresh Roles + Go to Narrator page + Understand + OK + , - تنظیمات - زبان + Settings + Language - نقش‌های شهروندان - نقش‌های مافیا - نقش‌های مستقل + Citizen Roles + Mafia Roles + Independent Roles - شهروند - شهروند ساده - دکتر - کاراگاه - تک‌تیرانداز - شهردار - محافظ - روانشناس - حرفه‌ای - تفنگ‌دار - قاضی - قهرمان - کشیش - هکر - فرشته - نگهبان - ساقی + Citizen + Simple Citizen + Doctor + Detective + Sniper + Mayor + Guardian + Psychologist + Professional + Gunman + Judge + Champion + Priest + Hacker + Angel + Vigilante + Bartender - مافیا - مافیا ساده - گادفادر - دکتر لکتر - سایلنسر - تروریست - مذاکره کننده - ناتو - خرابکار - شعبده‌باز - گروگان‌گیر - بادیگارد - بمب‌گذار + Mafia + Simple Mafia + Godfather + Dr.Lecter + Silencer + Terrorist + Negotiator + NATO + Vandal + Magician + Hostage Taker + Bodyguard + Bomber - مستقل - مجهول - گرگ‌نما - قاتل - هزار چهره - سندیکا + Independent + Unknown + Werewolf + Killer + Thousand Faces + Syndicate - شهروند ساده می‌بایست سعی کند در روز مافیاها را با دقت شناسایی کند و به آن‌ها رای دهد و در شب عمل خاصی را انجام نمی‌دهد. - می‌تواند در شب یک نفر را که احتمال می‌دهد مافیا آن را کشته باشد، نجات می‌دهد - می‌تواند هر شب استعلام نقش یک نفر را از گرداننده بگیرد - تک‌تیرانداز شهروندی است که تفنگ دارد و می‌تواند به کسانی که فکر می‌کند مافیا هستند، شلیک کند. - زمانی که شخصی با رای گیری حذف شود و شهردار حس کند که او شهروند است، می‌تواند تصویب حذف کردن بازیکن را وتو کند. - محافظ می‌تواند جان خود را برای شهروندی که بمب جلوی آن است، فدا کند. قاتل در صورتی از بازی حذف می‌شود که محافظ را بزند. - می‌تواند هر کسی که دارد به روند بازی لطمه می‌زند را ساکت کند. - در شب به هیچ عنوان حذف نمی شود مگر اینکه توسط ساقی گیج شود. - تفنگدار تیر دارد و می‌تواند آن تیرها را به کسانی که فکر می‌کند به آنها نیاز دارند، اهدا کند. - می‌تواند یکبار نتیجه رای‌گیری روز را تغییر دهد یعنی باطل یا ملغی کند - هر دو شب می‌تواند 24 ساعت یکی را بیمه کند که از هر اتفاقی در امان باشد. - کشیش باید تشخیص بدهد که چه کسی توسط ناتاشا سایلنت شده و او را از سایلنت بودن خارج کند. اگر کسی که کشیش انتخاب کند سایلنت نبوده باشد، نطق اضافه دریافت می‌کند. - هکر در شب دوم بازی، یک لیست سه نفره به گرداننده می‌دهد و گرداننده تعداد مافیاهای موجود در لیست را به او می‌گوید - فرشته می‌تواند یک بار کسی را که کشته شده است را به بازی برگرداند. - نگهبان از شهروندان در برابر گروگان‌گیر محافظت می‌کند. - ساقی شب یکی از افراد را انتخاب می‌کند و اون شخص را گیج و منگ می‌کند + Citizens are ought to detect mafia correctly during the day, but may not do anything during the night. + May save a person whom he believes would be killed during the night. + Detective can query the side of a player during the night. + Sniper is a citizen who can shoot those who he thinks are in side of the mafia. + Can veto the elimination of a player they believe to be a Citizen during the voting process. + Guardian can scarifies themselves against the bomb in the front a player, Killer shall be killed if they attack the Guardian. + Psychologist can silent someone in the day, as their night act. + Professional may not be killed during the night, unless they get drunk by the bartender. + Gunman have got guns, and may give it to those who are in need. + They can change the result of elimination vote, that is, making it invalid. + They can protect someone from any harm, for a day, each two days. + Priest may allow a silented person to speak, if they are already allowed, they may speak for a extended time. + hacker in the second night, picks three players and the narrator say count of Mafias in those. + Angel can return someone who has killed, once at the game. + Vigilante can protect citizen from the hostage. + bartender select one person to drunk. - مثل همه حق صحبت دارد، رای می‌دهد و شب‌ها در تصمیم‌گیری‌های تیم مافیا شرکت می‌کند. - رئیس گروه مافیا است. تصمیم نهایی را می‌گیرد و توسط گرداننده به کارآگاه لو داده نمی‌شود. - هر شب یکی از مافیاها را انتخاب و از خطر تیر خوردن در شب نجات می‌دهد. - می‌تواند هر شب یک نفر را برای روز بعد سایلنت کند. - اگر در روز توسط بازیکنان از بازی خارج شود، می‌تواند یکی دیگر از بازیکنان را به همراه خود حذف یا ترور کند. - مذاکره کننده در شب می‌تواند یک نفر را عضوی از دسته‌ی مافیا کند. - در صورتی که ناتو بتواند نقش یکی از شهروندان را درست حدس بزند، آن شهروند از بازی خارج می‌شود. - اگر شخصی را انخاب کند و آن شخص حق تیر داشته باشد و در روز از تیرش استفاده کند، آن تیر به خودش برمی‌گردد. - هر شب می‌تواند قابلیت یک نفر را 24 ساعت از او بگیرد - هر شب یکی از شهروندها را گروگان می‌گیرد و آن شخص نمیتواند آن شب از توانایی‌اش استفاده کند - تا زمانی که در بازی باشد حملات شب به پدرخوانده و معشوقه به او می‌رسند. - جلوی یک شهروند بمب می‌گذارد + The mafia member who can speak, vote and share comments. + The mafia leader. Got the final decision and don\'t tell they side to detective. + Can save the mafia members every night from shoots. + Can silent a player next day during the night. + If Terrorist get dismissal during the day, can take someone else with they. + Negotiator can buy some simple citizen to add in mafia team. + If Nato can guess someone role, that player will be dismissal from the city. + If select someone who has a gun, and the player use they gun during the day, the player will be dismissal from the city. + Can take some one role, for a day, every night. + Can take someone and the player can\'t use they ability. + Until bodyguard in the game, attack to Godfather will be collect to his. + Can bomb front a player. - اولین بار که توسط شخصی در شب انتخاب شود به اون جناح می پیوندد - هر سه شب در میان یک نفر را به گرگ‌نما تبدیل می‌کند. - هر شب یک نفر را می‌کشد. - هر شخصی که در روز از بازی خارج شود قابلیت آن شخص را به مدت یک روز می‌گیرد و همچنین در شب هر شخصی روی آن کاری بکند به خود آن شخص بر می گردد. - او تمام نقش‌های مهم بازی را می‌شناسد. در شب کسی نمی‌تواند او را بکشد اما در روز بسیار اسیب‌پذیر است. شرط پیروزی ماندن بین سه نفر آخر است. + Join the side of a player who select him first. + It turns a person into a werewolf every third night. + Killed someone every night. + Got role of a player who dismissal from the city, for a day. + He knows every important roles. No one can kill him during the night. The condition of victory is to stay among the last three. \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bd6979b..77e1bd9 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] agp = "8.7.1" kotlin = "2.0.21" -jdk = "17" +jdk = "21" core-ktx = "1.13.1" appcompat = "1.6.1"