Compare commits

..
897 Commits
Author SHA1 Message Date
Atony 2a7570f022 Adjust code that gets roles and modifiers list 2026-10-22 02:01:05 -05:00
Atony 71138c7bbe Display current role and modifiers at top 2026-10-22 01:17:21 -05:00
Atony 2993ee2bbc Resync options upon clicking start
This is necessary to prevent some pretty common option desync that tends to happen. If anyone else can optimize it further or move it somewhere else, go for it.
2026-10-21 23:37:46 -05:00
Atony 79bbebd12a Allow modifiers and roles to override chance text 2026-10-21 17:48:33 -05:00
Az 5021afeee7 improve reflection search 2026-10-18 03:04:04 -04:00
Az 6bfc49af00 rename file 2026-10-18 02:25:04 -04:00
Atony 7a4e891367 Merge branch 'dev' into xml-translations 2026-10-18 00:23:35 -05:00
Az 1667fa4541 add missing documentation 2026-10-18 00:41:39 -04:00
AS fc7a1dc831 Merge pull request #112 from All-Of-Us-Mods/options-improvements
More additions to the options system
2026-10-18 00:37:36 -04:00
Atony d90d3c0a28 Merge pull request #107 from All-Of-Us-Mods/controller-support
Controller Support
2026-10-17 23:10:47 -05:00
Atony 6e48446894 Merge branch 'dev' into controller-support 2026-10-17 21:43:49 -05:00
Atony 0224ac95bc Merge branch 'dev' into options-improvements 2026-10-17 21:43:45 -05:00
Atony 48ee06990d Add background for tab buttons 2026-10-17 21:23:17 -05:00
Atony 0ddbabadd6 Add full grid options 2026-10-17 19:39:08 -05:00
Atony 12dee96200 Add auto-alignment to the left of the guide 2026-10-17 19:10:45 -05:00
Az d8162dcb32 avoid patching indexers instead 2026-10-17 18:23:15 -04:00
Az 5106efe2ac optimisations and utilities 2026-10-17 15:52:53 -04:00
Atony dc87c0fc7f Fix conflicting Local Settings Tabs
Neil made this change fyi
2026-10-17 11:26:29 -05:00
Az 6364f8eae6 constructor parity + scrap toggle display delegate 2026-10-17 04:27:24 -04:00
Az 3e421909de Merge branch 'dev' into options-improvements 2026-10-17 04:03:19 -04:00
Az e4cb4a28df warnings begone 2026-10-17 04:02:58 -04:00
AS 0f51eee1be Merge branch 'dev' into options-improvements 2026-10-16 20:52:49 -04:00
Atony 0b85c9fe96 Add new modifiers, settings, and page buttons 2026-10-16 14:57:56 -05:00
Atony 8fa6903a8d Merge pull request #111 from idkimneil/wiki-improv
Wiki improv
2026-10-16 14:19:20 -05:00
Az ca587ebb18 optimise code + add new example option 2026-10-15 23:21:09 -04:00
Az e0db03b576 Merge branch 'dev' into controller-support 2026-10-15 21:30:54 -04:00
Az aa69fafcf1 minor changes 2026-10-15 21:16:58 -04:00
Az 5e12d1f0d6 oops, copy paste 2026-10-15 21:07:17 -04:00
Az 04b7701b79 more stuff 2026-10-15 20:46:41 -04:00
neilmjain 5c51037503 track options better 2026-10-15 18:09:27 -04:00
neilmjain da7162d60d resize option content with more than 2 columns 2026-10-15 18:03:48 -04:00
neilmjain 602665079c wire up headers to pages with more than 2 columns 2026-10-15 18:03:09 -04:00
neilmjain 39d77a301b add properties to merge groups of options on one page 2026-10-15 18:01:27 -04:00
neilmjain 5e9967606d enlarge setting content by base 2026-10-15 16:37:11 -04:00
neilmjain a7585ee2fe add setting searching by mod name 2026-10-15 16:37:00 -04:00
Az b074fdc330 order code 2026-10-15 03:37:23 -04:00
Az fb74a688c3 remove useless translation calls + order players 2026-10-15 03:28:40 -04:00
Az 7ed3944ad1 target non public getters and setters 2026-10-15 03:10:38 -04:00
Az f08a00ded7 field support 2026-10-15 02:58:01 -04:00
Az f433454fe6 add missing documentation line 2026-10-15 02:01:14 -04:00
Az a31b9e29b9 improve options system 2026-10-15 01:41:56 -04:00
Atony bcacbad0e6 Merge branch 'dev' into wiki-improv 2026-10-14 23:13:28 -05:00
Atony c1978bbb88 Add sprites for settings in wiki 2026-10-14 23:09:08 -05:00
neilmjain cac15bf07f adjust positons of tab labels 2026-10-14 22:25:20 -04:00
neilmjain 1db6a80768 add the no results found text again 2026-10-14 22:18:55 -04:00
neilmjain 06ca48c088 Fix No Results Found text overlaying other UI elements. and add No Results found message to Settings tab 2026-10-14 22:08:59 -04:00
neilmjain 7b77d0d102 use Option Headers as Dividers to Search Options Results 2026-10-14 22:08:28 -04:00
neilmjain 901503f762 fix double dummy roles being spawned on the panel 2026-10-14 22:00:23 -04:00
Az 56cc7661c7 Merge branch 'master' into dev 2026-10-14 21:04:02 -04:00
AS bceed03ac7 Merge pull request #109 from All-Of-Us-Mods/more-colors
Add variable colors
2026-10-14 21:01:35 -04:00
neilmjain 144c762ae3 Merge branch 'wiki-improv' of https://github.com/idkimneil/MiraAPI into wiki-improv 2026-10-14 20:57:13 -04:00
neilmjain 5197b90360 layer sorting by extra mods 2026-10-14 20:57:12 -04:00
neilmjain 542bf72ece Sort Pages by Priority of menus and groups 2026-10-14 20:45:01 -04:00
neilmjain 754161d439 Implement ShowInMatchInfoGuide 2026-10-14 20:44:45 -04:00
Atony 63c411754c Merge branch 'wiki-improv' of https://github.com/idkimneil/MiraAPI into pr/111 2026-10-14 19:13:54 -05:00
Atony 5e863747f7 Merge branch 'dev' into pr/111 2026-10-14 19:13:42 -05:00
neilmjain a01ff6168c Override Vanilla View to match others 2026-10-14 20:08:44 -04:00
neilmjain 75142dbcb8 rename sm properties for easier reading 2026-10-14 19:01:36 -04:00
neilmjain 6d40113ea0 fix scroller and option content clipping 2026-10-14 18:36:57 -04:00
neilmjain e3358507bf Update UI to clone Options Num Rows to display settings 2026-10-14 18:20:21 -04:00
neilmjain 5ec02eec9c add CreateAdvancedSettingsPage to print the settings 2026-10-14 17:50:45 -04:00
neilmjain 1e453cf6af add very scuffed pagination of game settings 2026-10-14 17:26:00 -04:00
CallOfCreator 2748c64db2 Fix custom controller bindings blocking unused vanilla actions 2026-10-14 16:51:37 +00:00
Az 1027e90447 minor improvements 2026-10-14 03:49:21 -04:00
Az 60537fe1a3 Merge branch 'dev' into more-colors 2026-10-14 00:49:38 -04:00
Az 50312e31c2 resolve and suppress warnings 2026-10-14 00:48:08 -04:00
Az 19dd1bb497 fix mentioned issues + add more functionality 2026-10-14 00:18:56 -04:00
Atony 51efa74811 Merge branch 'dev' into controller-support 2026-10-13 22:50:50 -05:00
neilmjain 1c8f7318d3 add no results found text to modifiers page 2026-10-13 23:04:02 -04:00
neilmjain 8e4ff7c179 add filtering/hiding to modifiers page 2026-10-13 23:00:54 -04:00
neilmjain afcb4dc180 change No Roles Enabled to No Results Found for more general meaning across search settings 2026-10-13 23:00:40 -04:00
neilmjain 98aa9dc9a8 Merge branch 'wiki-improv' of https://github.com/idkimneil/MiraAPI into wiki-improv 2026-10-13 22:56:11 -04:00
neilmjain b6414fe5a0 Filter/hide roles by search in cleaner way 2026-10-13 22:52:16 -04:00
neilmjain 6f36aa91a5 also add filtering/hiding of entries not pertaining to search 2026-10-13 22:44:20 -04:00
neilmjain 57471289e1 Scale advanced wiki page content 2026-10-13 22:43:48 -04:00
neilmjain cc4daf5d8b change maximum to 1.00 instead of 1.50 2026-10-13 22:40:58 -04:00
AS 3b336fb27c Merge branch 'dev' into more-colors 2026-10-13 22:30:16 -04:00
AS 9da879fd61 Merge pull request #108 from All-Of-Us-Mods/overlooked-behaviour
Fixes to codebase
2026-10-13 22:23:04 -04:00
Atony 503b7cec51 Merge branch 'dev' into controller-support 2026-10-13 21:06:27 -05:00
Atony 348c7c615b Merge branch 'dev' into more-colors 2026-10-13 21:06:23 -05:00
Atony a07efcd268 Merge branch 'dev' into overlooked-behaviour 2026-10-13 21:06:12 -05:00
neilmjain 613ebafa8a Add match info guide scale setting 2026-10-13 21:24:18 -04:00
Atony 7349a259a1 Add icons to all menus 2026-10-12 03:07:57 -05:00
Atony a9dabe9ff4 Merge branch 'dev' into xml-translations 2026-10-11 22:39:05 -05:00
Atony 5d354eff5e Save wiki preferences in config file 2026-10-11 18:52:29 -05:00
Atony a6dab42df3 Hide searchbox in advanced menu pane 2026-10-11 18:31:10 -05:00
Atony 67e3a6a7bc Add labels to filter, grouping, and order buttons 2026-10-11 17:33:15 -05:00
Az 3982867943 cache il2cpp type 2026-10-11 12:29:32 -04:00
Az d5b08a7145 better audio loading 2026-10-11 12:25:13 -04:00
Az 01b172d73e remove more code, actually
and also fix build error
2026-10-11 12:05:25 -04:00
Az bdf9f4c9e8 deprecate addressables loader
- decprecates the addressables loader utility
- increments the required version
2026-10-11 12:01:26 -04:00
Sameer Umar 362cfc02ff Merge pull request #110 from rewalo/wiki-preset-fixes
Wiki preset fixes
2026-10-11 00:42:13 -04:00
ReAdmin d3bce25ef6 Guard EnsurePanel and expose TriggerPreload 2026-10-08 20:49:11 -07:00
ReAdmin 317fd243b1 Show role/modifier icons on wiki pages, fix wiki softlock after rejoining, even out sort buttons 2026-10-08 20:15:16 -07:00
ReAdmin b6bddbd0df Fix duplicate entries by building entries once on first open 2026-10-08 19:16:37 -07:00
ReAdmin edadd4f350 Defer UI init to first open, add search debounce, fix advanced wiki scale 2026-10-08 19:15:04 -07:00
ReAdmin c5431f0666 Keep advanced wiki pages at local scale when parenting 2026-10-08 18:46:44 -07:00
ReAdmin ec4a5f2bae Keep the wiki open animation smooth by deferring panel work 2026-10-08 18:27:14 -07:00
ReAdmin abfbd8ee73 Reveal wiki panels progressively and preload them before first open 2026-10-08 18:16:13 -07:00
ReAdmin f0650a9841 Look up role parent mods by type instead of scanning IL2CPP objects 2026-10-08 18:16:13 -07:00
Az 43f1209c1c minor code changes 2026-10-08 01:27:24 -04:00
Az a90a0c4905 cache audio clips 2026-10-08 01:20:05 -04:00
Az 6410a0dd42 consolidate copy pasted addressables code 2026-10-08 01:02:09 -04:00
Az f5a994abc3 avoid over-allocating objects
when reading sprite sheets
2026-10-08 00:30:57 -04:00
rewalo c4a5c638f7 Merge branch 'dev' into wiki-preset-fixes 2026-10-07 03:30:16 -07:00
ReAdmin 5379f22364 Remove wiki open timing diagnostics 2026-10-07 03:28:30 -07:00
ReAdmin cb292308c4 Add temporary wiki open frame timing diagnostics 2026-10-07 03:04:16 -07:00
ReAdmin ff17c946a4 Spread wiki panel reveal over frames and show the ring immediately 2026-10-07 03:03:51 -07:00
ReAdmin 5c0e5473a5 Reveal wiki panels across frames on every open 2026-10-07 02:59:10 -07:00
ReAdmin b84c5b064c Avoid redundant panel refreshes when reopening the wiki 2026-10-07 02:53:04 -07:00
ReAdmin ffd42a4a91 Copy the original label layout onto the cloned wiki search field 2026-10-07 02:44:04 -07:00
ReAdmin b94f0aa63b Build the wiki search box from the chat text field instead of a bare TextBoxTMP 2026-10-07 02:37:48 -07:00
ReAdmin 5d9c38a503 Wire a placeholder into the wiki search box so clearing an empty box works 2026-10-07 02:32:42 -07:00
ReAdmin 9cefeebe2b Keep the loading ring sprite alive across scene loads 2026-10-07 02:24:27 -07:00
ReAdmin a88f9b6611 Give the wiki search box a caret so clearing it does not corrupt input 2026-10-07 02:24:27 -07:00
ReAdmin 034521b7b6 Create resource sprites as full rect to stop tiling warnings 2026-10-07 02:16:11 -07:00
ReAdmin 77366593f1 Fix wiki open aborting before the player list is created 2026-10-07 02:16:11 -07:00
ReAdmin 0903503782 Show a loading spinner while wiki panels are built 2026-10-07 02:08:25 -07:00
ReAdmin a297898e6e Fix wiki failing to open after clearing the search box 2026-10-07 02:03:03 -07:00
ReAdmin c5c55745fd Build wiki panels across frames and stop re-initialising them on refresh 2026-10-07 01:56:58 -07:00
ReAdmin 9e5b470ae6 Fix CoLoopWithBudget default budget being zero 2026-10-07 01:53:09 -07:00
ReAdmin d827e5d1f9 Tidy role guide sorting, refresh and layout code 2026-10-07 01:40:35 -07:00
ReAdmin b00775e868 Clean up wiki options text generation 2026-10-07 01:31:44 -07:00
ReAdmin 83722a81c8 Share advanced wiki page creation 2026-10-07 01:31:06 -07:00
ReAdmin a1d22b2fac Fix preset lookup racing mod switches during option creation 2026-10-07 01:29:13 -07:00
Atony eac86ca4eb Remove clear garbage collector functionality
Crashes instantly on x64
2026-10-05 21:02:05 -05:00
Atony e5c41913cb Merge pull request #106 from TheDavSmasher/generic-option-list
Adds a generic IModdedOptionList definition for easier typed iteration
2026-10-05 01:04:55 -05:00
Atony 3b4b6e1800 Merge branch 'dev' into generic-option-list 2026-10-05 01:04:14 -05:00
Atony 7ee4d7da96 Bump appended number for option lists 2026-10-05 01:00:01 -05:00
Atony 206b00c11f De-duplicate some code 2026-10-04 23:18:39 -05:00
Atony aec2cfcad3 Fix presets failing to save 2026-10-04 22:09:03 -05:00
Atony 0dfb65e9b6 clear redundant code 2026-10-04 18:29:34 -05:00
Atony 3cf1963414 Optimize search and filter to be "per-menu" 2026-10-04 18:29:18 -05:00
Atony 6d1557a48d Add modifier support for wiki 2026-10-04 17:17:42 -05:00
Atony 5e6645ff3b Add wiki components to modifiers 2026-10-04 11:49:19 -05:00
AS a36f010207 Merge branch 'dev' into overlooked-behaviour 2026-10-04 02:52:02 -04:00
AS 7deaf5e963 Merge branch 'dev' into more-colors 2026-10-04 02:51:44 -04:00
Atony d0138936be Clear helper warnings 2026-10-04 00:16:04 -05:00
Atony 7cb8246953 Add more locale 2026-10-03 22:47:49 -05:00
Atony 9fd5b488b8 Add wiki abilities as a list for ICustomRole 2026-10-03 22:25:37 -05:00
Atony 24407580d5 Add summarized options helper for wiki 2026-10-03 22:25:01 -05:00
Atony 15c0002395 Open Roles Wiki tab immediately 2026-10-03 19:21:50 -05:00
Atony 91c7ea8dda Toggle roles enabled message properly 2026-10-03 19:16:39 -05:00
Atony 3bcc5139f3 Fix code spacing 2026-10-03 19:10:02 -05:00
Atony b912f6ffa3 Add search box reset safeguard 2026-10-03 19:09:28 -05:00
Atony f0503a6d68 Finish search functionality 2026-10-03 18:47:31 -05:00
Atony c2e251e9c6 Change text color 2026-10-03 15:59:20 -05:00
Atony 43fa7a0a2a Add functional search box and change UI 2026-10-03 15:44:26 -05:00
Atony a27a45944c Add WIP search box 2026-10-03 03:06:33 -05:00
XtraCube 79dc3280e8 dont use il2cpp lists unless absolutely necessary! 2026-10-02 11:52:15 -04:00
Sameer Umar 5303f09627 Add language links and badges to README 2026-10-01 23:07:47 -04:00
Sameer Umar 85f8da54dd Update README with new badge and language links 2026-10-01 23:07:12 -04:00
Az 2e212dee47 bounds checks 2026-10-01 01:50:39 -04:00
Az c2c7c63b9b correct documentation 2026-09-30 19:02:40 -04:00
Atony f52c5de4cd Add wip sorting toggling
az i know there's warnings PLEASE don't slime me out i'll fix it later i promise 🙏
2026-09-30 10:31:27 -05:00
Az cd753d554b fix naming
it originally was called "VariantColor" before i switched it to "VariableColor"
2026-09-30 10:28:26 -04:00
Az f3ddf8d2ab squash final bugs 2026-09-30 10:00:26 -04:00
Atony ab7d43f18b Add vanilla button checks for Influencer 2026-09-29 20:56:03 -05:00
Atony 9f4e519b9e Update game version 2026-09-29 20:55:42 -05:00
Az 27ac201f88 fix oversights + errors 2026-09-29 16:06:49 -04:00
Az a73d1df67e optimisations + example color 2026-09-29 13:54:06 -04:00
CallOfCreator 24f71de1dd Fixed the keybind menu not appearing when using controller input 2026-09-29 15:56:34 +00:00
Az 3bf066f38c add variable color system + color spaces 2026-09-29 09:53:18 -04:00
HayashiUme 44d476dd3a Translated using Weblate (Literary Chinese (lzh_CN))
Currently translated at 52.6% (20 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/lzh_CN/
2026-09-28 13:08:53 +00:00
Az c1cd4a7d67 fix small overlooked behaviours
- fixes issue #45 where the player leave event was in a postfix, when the player character was already destroyed
- fixes #46 where modded role options did not have the same change zero behaviour as vanilla ones
2026-09-27 23:24:57 -04:00
Az 5fb60a7082 fix warnings
scav you have committed a war crime. C# =/= python
2026-09-27 16:59:17 -04:00
CallOfCreator 041c39d7ff Controller Support 2026-09-27 16:14:56 +00:00
David Higueros 2d4619f2cf Used generic interface for ModdedOptionList 2026-09-25 12:44:44 -06:00
David Higueros 1b587547f7 Added ConfigName property to IModdedOptionList to optionally rename the individual options 2026-09-25 12:43:14 -06:00
David Higueros ffe9194d54 Resolved warnings 2026-09-25 11:47:12 -06:00
Atony 3575f308e4 Merge branch 'dev' into pr/106 2026-09-24 20:47:16 -05:00
Atony bfee7d44a2 Merge pull request #101 from All-Of-Us-Mods/cleanup
Clean project
2026-09-24 20:43:12 -05:00
Az 832d9fe7eb cleaning code is a sisyphean task 2026-09-24 20:27:19 -04:00
Az 458ca6e13d Merge remote-tracking branch 'origin/dev' into cleanup 2026-09-24 20:18:43 -04:00
Atony f89ffb0d86 Find the latest role options collection at start
This should help avoid the api breaking from additional roles and additional settings.
2026-09-24 17:08:56 -05:00
David Higueros 0f8d5bc8ca Merge branch 'dev' into generic-option-list 2026-09-23 21:23:07 -06:00
Atony 2cfdbea51f Reduce duped code 2026-09-23 21:53:46 -05:00
AS 1c35e93121 Merge branch 'dev' into generic-option-list 2026-09-23 19:08:01 -04:00
Az 7107f66bec fix additional warning 2026-09-23 19:05:58 -04:00
AS 7589057bd9 Fix reference to advancedWikiTab in RoleGuidePatches 2026-09-23 19:00:56 -04:00
Az ca5a43a121 Merge remote-tracking branch 'origin/dev' into cleanup 2026-09-23 18:56:29 -04:00
Atony fc7eaef7c4 Add proper scroller implementation for tab 2026-09-23 17:53:50 -05:00
Az 8b897a17f4 add documentation 2026-09-23 18:17:15 -04:00
Atony a693cef676 Fix instant SubAssetHolder error 2026-09-23 16:37:03 -05:00
Atony e4a24d4164 Keep MiraHudHelper public 2026-09-23 16:32:51 -05:00
Az c7901baa34 Merge remote-tracking branch 'origin/dev' into cleanup 2026-09-23 14:58:17 -04:00
Az 8dee2d0bd0 Merge remote-tracking branch 'origin/xml-translations' into cleanup 2026-09-23 14:49:27 -04:00
Bohnked 0c3869ccf8 Translated using Weblate (Hebrew)
Currently translated at 100.0% (38 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/he/
2026-09-23 18:08:55 +00:00
walter 0ddfb9da63 Translated using Weblate (Hebrew)
Currently translated at 100.0% (38 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/he/
2026-09-23 18:08:55 +00:00
Turret 9cae38481c Translated using Weblate (Polish)
Currently translated at 100.0% (38 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/pl/
2026-09-23 18:08:55 +00:00
Atony ef8b4af231 Fix masking and text positions 2026-09-23 01:57:10 -05:00
Atony a8cc2bc357 why did the languages get removed 2026-09-23 01:43:15 -05:00
Atony 173b0c37b3 Merge branch 'xml-translations' into dev 2026-09-23 01:41:29 -05:00
Atony b6881e4d77 Add WIP advanced role guide tab 2026-09-23 01:34:06 -05:00
Bohnked 76b8e8c1ee Translated using Weblate (Hebrew)
Currently translated at 36.8% (14 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/he/
2026-09-22 17:08:53 +00:00
David Higueros 1ab662bcf1 Adds a generic IModdedOptionList definition for easier typed iteration 2026-09-21 18:48:09 -06:00
Az 1f6558e7c3 Merge remote-tracking branch 'origin/dev' into cleanup 2026-09-21 18:35:15 -04:00
Sameer Umar 8fa87c0b7d Merge pull request #105 from TheDavSmasher/paginable-menu-locale
Custom Phone Menu fixes
2026-09-21 18:22:54 -04:00
David Higueros f2a4cf2b37 Added implicit operator to return Minigame component from Phone Menu 2026-09-21 15:18:48 -06:00
David Higueros 6dd36a80ab Changed paginable menu to use locale text for search and no results text 2026-09-21 15:11:29 -06:00
Bohnked c01d1ef7e9 Translated using Weblate (Hebrew)
Currently translated at 7.8% (3 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/he/
2026-09-21 15:08:53 +00:00
Az 208a388fc0 consistency 2026-09-21 00:26:00 -04:00
Az 957d6067a0 Update MiraLanguage.cs 2026-09-20 16:07:30 -04:00
Az e88eddfe56 Merge remote-tracking branch 'origin/dev' into cleanup 2026-09-20 15:58:10 -04:00
Atony fd354285bf Merge branch 'xml-translations' into dev 2026-09-20 09:51:42 -05:00
Atony 81da4a65b6 Merge branch 'xml-translations' of https://github.com/All-Of-Us-Mods/MiraAPI into xml-translations 2026-09-20 09:50:03 -05:00
Atony f10431f5b1 Add Arabic, Greek, Hebrew, and Lit-Chinese 2026-09-20 09:49:51 -05:00
Anthony a5de208f2e Deleted translation using Weblate (Hebrew) 2026-09-20 14:46:47 +00:00
walter 3edbe57aff Added translation using Weblate (Hebrew) 2026-09-20 13:30:27 +00:00
Az 2f56b46035 undo accidental deletion 2026-09-19 23:13:45 -04:00
Az 7c76219b17 Merge remote-tracking branch 'origin/dev' into cleanup 2026-09-19 23:12:52 -04:00
Atony 003d577a09 Create masked variants of tmp icons 2026-09-19 16:26:35 -05:00
Atony d41ab95fa4 Allow older mods to fallback med text to tab text 2026-09-19 15:16:09 -05:00
Atony 0cb0527ddf Fix null component errors for custom multi menu 2026-09-19 13:18:36 -05:00
Az 18452c0890 resolve new warnings 2026-09-18 12:51:30 -04:00
Az 0857ac5cf5 Merge remote-tracking branch 'origin/dev' into cleanup 2026-09-18 12:43:27 -04:00
Amber 9f0cf11ba1 Merge pull request #95 from TheDavSmasher/phone-menu-extension 2026-09-18 11:43:55 -04:00
Amber 82284c6540 Merge pull request #104 from soyFault/dev 2026-09-18 11:41:27 -04:00
Az d090a7c216 small corrections 2026-09-18 11:00:42 -04:00
Az 554a77fb64 merge ruleset into editorconfig 2026-09-13 18:40:37 -04:00
Az cd94666ed9 use aliases and add documentation for new method 2026-09-13 17:10:33 -04:00
Az 8b83dcbf1f re-add obsolete begin 2026-09-13 16:44:33 -04:00
Az 2c08e89e30 Revert "forgot shapeshifter's menu is a minigame itself"
This reverts commit f62513a3b4.
2026-09-13 16:41:19 -04:00
Fault 95d905c62b Merge branch 'localefault' into dev 2026-09-13 12:49:17 -06:00
Fault df4b32b462 Added localization changes for menus and Modifiers mini button in-game
Reused the Modifiers string
2026-09-13 12:42:52 -06:00
Leafly de349bfdea Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (38 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/zh_Hant/
2026-09-13 17:08:53 +00:00
FangkuaiYa e5bb36fd50 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (38 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/zh_Hans/
2026-09-12 14:08:55 +00:00
Az f62513a3b4 forgot shapeshifter's menu is a minigame itself 2026-09-12 01:27:16 -04:00
Az 34a4fcf69f change custom menu behaviour to wrap a script instead 2026-09-12 01:23:01 -04:00
Az 983b7be37a Merge branch 'dev' into pr/95 2026-09-12 00:20:02 -04:00
Az 1fbd93d6f7 Merge branch 'dev' into cleanup 2026-09-12 00:18:31 -04:00
Atony 16e3249b20 Expose ParseXmlFile 2026-09-10 00:02:10 -05:00
David Higueros 426cb22281 Merge branch 'dev' into phone-menu-extension 2026-09-09 19:52:43 -06:00
Atony 254de6e686 Fix language version 2026-09-09 10:55:06 -05:00
Draxen 5c7ebdac69 Translated using Weblate (Turkish)
Currently translated at 100.0% (38 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/tr/
2026-09-08 21:08:53 +00:00
AS db0a22866e Merge branch 'dev' into phone-menu-extension 2026-09-08 12:43:28 -04:00
Az 2ce04690a9 git is confusing 2026-09-07 15:33:11 -04:00
Az 875107e337 Merge branch 'dev' into cleanup 2026-09-07 15:32:46 -04:00
AS 8003afd9fb Merge pull request #92 from TheDavSmasher/util-extension-dev
Util Extension
2026-09-07 15:10:50 -04:00
Atony 85ed3b5d71 Merge branch 'dev' into util-extension-dev 2026-09-07 14:02:40 -05:00
Atony 7f79685696 fix other gamemode roles appearing in view pane 2026-09-06 21:06:28 -05:00
David Higueros 51044b1e89 Merge branch 'dev' into phone-menu-extension 2026-09-06 17:02:21 -06:00
David Higueros 6540f8b7bb Made EventHandler InvokeEvent extension methods 2026-09-06 16:40:21 -06:00
David Higueros caca3d92ad Merge branch 'dev' into util-extension-dev 2026-09-06 16:36:43 -06:00
Az 329cc85f96 make resharper happy 2026-09-06 09:54:01 -04:00
Az 8418b479d8 cleared all warnings
except for the todo ones, since they are supposed to be annoying
2026-09-06 07:03:31 -04:00
Az 7099e377ac Merge branch 'master' into cleanup 2026-09-04 15:06:03 -04:00
Leafly 9f39c10394 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 89.4% (34 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/zh_Hant/
2026-09-04 03:29:46 +00:00
Leafly 27b5c49eb5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 89.4% (34 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/zh_Hans/
2026-09-04 03:29:46 +00:00
Atony ef19f5f7de Merge pull request #103 from All-Of-Us-Mods/dev
0.5.0
2026-09-03 20:34:33 -05:00
Atony e619acbc2a Merge branch 'master' into dev 2026-09-03 20:30:53 -05:00
Atony 9e21726ced Fix MultiTargetButton being renamed? 2026-09-03 20:29:05 -05:00
Atony 7d7d6469ce Bump version 2026-09-03 02:29:00 -05:00
Atony 087ea2a4bd Clear up il2cpp warnings 2026-09-03 02:28:27 -05:00
Atony 81c6bac979 Add UiButtonResetEvent for better ui button grid 2026-09-02 15:16:32 -05:00
Leafly dcb6b14f5f Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 76.3% (29 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/zh_Hant/
2026-09-02 19:29:46 +00:00
Leafly b48950909e Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 78.9% (30 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/zh_Hans/
2026-09-02 19:29:46 +00:00
Faulo Fault 78066fae1c Translated using Weblate (Spanish)
Currently translated at 34.2% (13 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/es/
2026-09-02 19:29:46 +00:00
Atony 85fb507a43 Adjust gamemode role checks for info guide 2026-09-02 02:34:01 -05:00
Leafly 82e8764f54 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 44.7% (17 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/zh_Hant/
2026-09-01 16:29:46 +00:00
CraftR 9452b64887 Translated using Weblate (Polish)
Currently translated at 73.6% (28 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/pl/
2026-09-01 16:29:46 +00:00
Olli 1a52c4f342 Translated using Weblate (German)
Currently translated at 100.0% (38 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/de/
2026-09-01 16:29:46 +00:00
Shade the Minior Fan fbc29dfb61 Translated using Weblate (Portuguese (Portugal))
Currently translated at 100.0% (38 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/pt_PT/
2026-08-31 10:29:45 +00:00
Atony 3e2c6df829 Fix skip button vote area order 2026-08-30 19:00:57 -05:00
Atony 6c7b362f95 Add toggles to disable abilities upon use / vote 2026-08-30 18:24:35 -05:00
Atony 027d4763f3 Expose vote methods for other mods 2026-08-30 17:49:20 -05:00
Atony d2f6ba9718 Fix god-awful spacing in the roles guide 2026-08-29 22:55:44 -05:00
Atony 28871d0a01 Refresh role info on the info guide immediately 2026-08-29 22:35:47 -05:00
Atony b62b8ae216 Add more helpers for getting role strings 2026-08-29 22:35:10 -05:00
Atony 4bdddc6f8a Fix IdPart shenanigans 2026-08-29 19:39:21 -05:00
Atony fa47d1dec4 Merge branch 'xml-translations' of https://github.com/All-Of-Us-Mods/MiraAPI into xml-translations 2026-08-29 18:15:43 -05:00
Atony 004f62eb77 Tweak system for registering changes 2026-08-29 18:15:30 -05:00
Turret 3f7e30a5c3 Translated using Weblate (Polish)
Currently translated at 71.0% (27 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/pl/
2026-08-29 21:20:07 +00:00
Faulo Fault 1d18a2ac7b Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (38 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/es_419/
2026-08-29 21:20:07 +00:00
Shade the Minior Fan 663480c77f Translated using Weblate (Portuguese (Portugal))
Currently translated at 97.3% (37 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/pt_PT/
2026-08-29 18:38:23 +00:00
Turret e95b52dbe8 Translated using Weblate (Polish)
Currently translated at 68.4% (26 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/pl/
2026-08-29 18:38:23 +00:00
Faulo Fault 76105b3116 Translated using Weblate (Spanish (Latin America))
Currently translated at 76.3% (29 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/es_419/
2026-08-29 18:38:23 +00:00
Anthony c82cc0e173 Translated using Weblate (Spanish)
Currently translated at 31.5% (12 of 38 strings)

Translation: Mira API/Mira API
Translate-URL: https://weblate.duikbo.at/projects/mira-api/mira-api/es/
2026-08-29 17:11:26 +00:00
Az ceab86cc19 Merge branch 'dev' into cleanup 2026-08-28 03:14:56 -04:00
Atony 2a432dd928 Add more localized strings 2026-08-28 00:37:14 -05:00
Atony 648e9ec185 Wrap up locale system 2026-08-27 23:51:25 -05:00
Atony 709b59300b Revert "Set role amount to 0 if chance is 0"
This reverts commit 794c762949.
2026-08-27 22:37:01 -05:00
Atony f064952aa6 Merge pull request #91 from HayashiUme/dev
Add XML Translation Api
2026-08-27 19:50:48 -05:00
Atony e532e558b6 Fix local tabs not being localized without hovering 2026-08-27 19:49:10 -05:00
Atony a3ed901a18 Translate local setting buttons 2026-08-27 19:36:33 -05:00
Atony 48aff163f9 Fix issues with local settings tab localization 2026-08-27 19:29:12 -05:00
Atony 28a77f96cb Fix capitalization of all xml strings 2026-08-27 18:21:14 -05:00
Atony 4206b74d12 Fix localization being applied 2026-08-26 00:24:02 -05:00
Atony 276ab0ac79 Fix overall localization 2026-08-25 19:02:55 -05:00
Atony 34148499b7 Fix up system registration for the most part 2026-08-25 18:26:54 -05:00
Atony 5b006ab7d3 Fix xml loading 2026-08-25 01:04:11 -05:00
Atony 47582897a8 Fix loading errors 2026-08-25 00:47:54 -05:00
Atony 80e1e6e454 Clear some warnings 2026-08-25 00:20:52 -05:00
Atony c449669cf2 Fix example plugin error 2026-08-25 00:15:39 -05:00
Atony 6da1048d09 Adjust system for Crowdin / Weblate support 2026-08-25 00:04:09 -05:00
Atony 6a7f58effa Add localization for gamemodes 2026-08-24 22:23:57 -05:00
Atony 39da0e7d08 Merge branch 'dev' into pr/91 2026-08-24 22:16:53 -05:00
Atony 5a23c38fba Merge pull request #102 from WanderingPix/meeting-abilities
Meeting abilities
2026-08-24 21:56:01 -05:00
Atony 0b1b223a6e Merge branch 'dev' into meeting-abilities 2026-08-24 21:48:54 -05:00
Atony a4a363b015 Merge branch 'dev-update' into meeting-abilities 2026-08-24 21:46:00 -05:00
Atony 794c762949 Set role amount to 0 if chance is 0 2026-08-24 16:18:39 -05:00
Atony e901abfc60 Merge branch 'dev' into dev-update 2026-08-24 15:49:12 -05:00
Atony 853a94681a Merge pull request #17 from All-Of-Us-Mods/game-modes
Game modes
2026-08-24 15:41:24 -05:00
wanderingpix d37222010d Document CenteredGridArrange 2026-08-22 13:37:02 +01:00
wanderingpix 1254de742a Fix text labels visible for disabled meeting abilties 2026-08-22 13:33:55 +01:00
wanderingpix 7bbbd7597d Refactor + untargeted meeting abilities 2026-08-22 13:32:14 +01:00
wanderingpix 4b7f17fa30 Fix skip button being broken 2026-08-21 19:30:24 +01:00
wanderingpix 06d62da24d Multi target meeting abilities 2026-08-21 17:00:24 +01:00
wanderingpix 0050c34225 Add singleton for accessing meeting buttons 2026-08-21 14:00:24 +01:00
wanderingpix 605c792e8f More documentation + Button outline color 2026-08-21 12:32:43 +01:00
wanderingpix 54d7c84e91 Edit example meeting ability 2026-08-21 11:52:48 +01:00
wanderingpix eb4bff1834 Document meeting abilities 2026-08-21 11:44:30 +01:00
wanderingpix e381de033e WIP Targeted meeting abilities API 2026-08-20 22:41:26 +01:00
Atony f230cff5e5 Add RoleMedDescription for the role guide 2026-08-19 23:28:00 -05:00
Atony 7c7d184d1f Wip faction display for roles
These need to be their own text object later.
2026-08-19 17:24:54 -05:00
Atony 6b923cfe01 Show nameplate on player list menu 2026-08-19 17:10:41 -05:00
Atony 247c765176 Fix bad ui because sloth sucx 2026-08-19 15:56:13 -05:00
Atony a3668b3150 Add proper support for modded roles in wiki 2026-08-19 13:52:33 -05:00
Atony aa4dd24ac3 Change options to V11 2026-08-19 13:31:36 -05:00
Atony cb0afe3095 Add ui resizing + wiki in the lobby 2026-08-19 13:29:03 -05:00
Atony 883222be82 Merge branch 'dev-update' into game-modes 2026-08-19 00:18:25 -05:00
Atony 6b774500dd Fix reimplemented Judge for good 2026-08-18 23:07:39 -05:00
Atony f96f75cea1 Fix issues with Judge and new meeting changes 2026-08-18 15:10:11 -05:00
linmeideli acfe345133 enhanced 2026-08-18 21:25:22 +08:00
David Higueros 503665ce2b Merge branch 'dev' into phone-menu-extension 2026-08-17 21:37:44 -06:00
David Higueros 8795aab37c Merge branch 'dev' into util-extension-dev 2026-08-17 21:24:29 -06:00
Atony 75662a6c25 Improve vent checks 2026-08-17 17:47:33 -05:00
Atony 73e4506016 Fix role tab issue 2026-08-17 17:41:24 -05:00
Atony a491592669 Allow gamemodes to be hidden when registered 2026-08-16 23:01:58 -05:00
Atony 01fef0f747 Fix vanilla advanced role settings tab breaking 2026-08-16 22:36:57 -05:00
Atony e22f4daf3e Fix the first role option being duped in the menu 2026-08-16 22:00:24 -05:00
Atony b83cb5cc29 Force role menu to be refreshed on gamemode change 2026-08-16 21:56:48 -05:00
Atony fb164a54e3 Fix broken game options tab for mods 2026-08-16 20:05:30 -05:00
Atony b6475161f1 Merge branch 'dev' into game-modes 2026-08-16 17:03:11 -05:00
XtraCube c7f3f9d5da Merge remote-tracking branch 'origin/game-modes' into game-modes 2026-08-16 11:16:52 -04:00
XtraCube 5d54a0c2d3 cleanup this file 2026-08-16 11:16:37 -04:00
ang-xd cf1a75f5ea Fix gamemode options visibility 2026-08-16 11:16:37 -04:00
XtraCube 721bd20d2b improve lobby view pane gamemode handling 2026-08-16 11:08:08 -04:00
XtraCube 0e3b6be5be show different plugin gamemodes in lobby view pane 2026-08-16 10:46:19 -04:00
Az 058a88e1d2 fix new warnings (thanks tony) 2026-08-16 04:29:17 -04:00
Az 907e4d4c34 Merge branch 'dev' into cleanup 2026-08-16 03:33:09 -04:00
Atony 411340d9e9 Fix role screenshots for combined spritesheets 2026-08-15 16:27:49 -05:00
Atony 57d2a6a9b5 Expose button event types 2026-08-15 16:00:05 -05:00
Atony 6f61a75bb7 Add BundleSubAssetHolder for packed spritesheets 2026-08-15 13:18:05 -05:00
Atony 06c746c632 Add most music logic 2026-08-14 23:24:07 -05:00
Atony 95819cf83a Add (unsynced) in-game timebar + adjust ui pos 2026-08-14 22:29:40 -05:00
Atony d1d11e2bec Show gamemode change notification 2026-08-14 20:22:45 -05:00
Atony b4ed14f7f2 Remove Hide n Seek port on release builds for now 2026-08-14 19:52:51 -05:00
ang-xd 951af42358 Move icons to gamemode and add icons for vanilla modes 2026-08-14 16:39:16 -04:00
AS 27e14488af Merge branch 'dev' into game-modes 2026-08-14 07:11:38 -04:00
AzandHayashiUmi 182a53442e Update README_zh.md
Co-Authored-By: HayashiUmi <2558527373@qq.com>
2026-08-14 06:57:19 -04:00
ang-xd 9ab87955bb i forgor to mask mod icon 2026-08-14 03:19:06 -04:00
ang-xd 0141dfdea4 Update gamemodes info panel to show mod icon 2026-08-14 03:12:04 -04:00
Az 35e4c7cc9d move chinese readme to translated folder 2026-08-14 02:18:15 -04:00
AS b2a5b236c0 Merge pull request #79 from TAIKgroup/master
Translate the README.md of MiraAPI into Simplified Chinese
2026-08-14 02:14:46 -04:00
linmeideli 525f987926 this check does not work for Unity's fake null 2026-08-14 13:38:28 +08:00
linmeideli 0b81a8808a Add Translation API 2026-08-14 13:05:30 +08:00
Atony cd97fab3a2 Show gamemode description in options 2026-08-13 23:59:51 -05:00
Atony 3cd8db1f04 Show gamemode settings properly again 2026-08-13 23:00:09 -05:00
Az 33cafd1963 Merge branch 'dev' into cleanup 2026-08-13 23:56:53 -04:00
AS 535967475d Merge pull request #100 from All-Of-Us-Mods/shader-improvement
Pass shader caching through helper method
2026-08-13 23:43:50 -04:00
Az 6fd5993959 pass shader caching through helper method 2026-08-13 23:27:07 -04:00
Az df07369376 clean up warnings and typos 2026-08-13 23:20:22 -04:00
Atony b713599c13 Fix option toggling for vanilla options 2026-08-13 20:51:29 -05:00
ang-xd f44ec15804 Patch console use 2026-08-13 16:19:23 -04:00
ang-xd 847a4dd287 Move initialize to begin 2026-08-13 14:37:52 -04:00
Atony 83d55d409b Change indirect and defense flags to get sets 2026-08-13 10:07:40 -05:00
Atony 7a00ea9174 Merge branch 'dev' into game-modes 2026-08-13 09:24:10 -05:00
Atony 22716b29ab Add Framed and Advanced Murder RPCs 2026-08-13 09:20:26 -05:00
ang-xd 43291bda50 Merge branch 'game-modes' of https://github.com/All-Of-Us-Mods/MiraAPI into game-modes 2026-08-13 00:43:23 -04:00
ang-xd d4a675f2a9 Hide roles tab if no roles in mod 2026-08-13 00:43:15 -04:00
Atony 00c5c5c4ff Merge branch 'dev' into game-modes 2026-08-12 23:23:14 -05:00
Atony abb6f3d161 Add better murder event data 2026-08-12 23:22:55 -05:00
Atony eef098317e Add hide and seek end logic and cooldown checks 2026-08-12 23:20:19 -05:00
Atony 1c097b47df Add end game patches for all gamemodes 2026-08-12 23:18:17 -05:00
Atony 6fe2750545 Make kill timer use whatever the gamemode sets 2026-08-12 23:18:00 -05:00
Atony a57f40fa79 Apply role menu toggle 2026-08-12 23:17:29 -05:00
Atony 54bfd3002b Add role settings toggle and imp cooldown for mode 2026-08-12 22:53:30 -05:00
Atony 4c38189444 Fix initialize patch for gamemodes 2026-08-12 22:25:56 -05:00
Atony 14ce020208 Hide modifier spawning on non-dev builds 2026-08-12 21:14:50 -05:00
Atony 877fc15aec Merge branch 'dev' into game-modes 2026-08-09 22:26:50 -05:00
Atony 2160d1d823 Allow HandleVoteEvent's PreventVote to be set 2026-08-09 22:26:31 -05:00
amber 4d187f3f79 more null checks, yay! 2026-08-09 09:49:25 -04:00
amber 4e37f8b3d4 fix scrollbar 2026-08-09 09:31:59 -04:00
amber 015d175aa0 check if header is not null 2026-08-09 09:11:05 -04:00
Amber ca7da0c343 update gamelibs 2026-08-09 08:43:56 -04:00
Atony 72fa908cb0 Move patches to account for gamemodes 2026-08-08 20:34:10 -05:00
Atony 58067d9f21 Merge branch 'dev' into game-modes 2026-08-08 20:26:39 -05:00
Atony b8b85e2bc3 Merge pull request #99 from yanpla/fix/role-assignment
Fix role assignment
2026-08-08 20:13:02 -05:00
Atony 043845ee11 Fix crashing on Epic and MS Store 2026-08-08 19:57:47 -05:00
yanpla df7c182abb use .select() in loop 2026-08-09 01:52:33 +02:00
yanpla 2a4d16e65e simplify and fix role assignment patch 2026-08-09 01:50:29 +02:00
Nix-main 9606871cbe sync gamemode on join 2026-08-07 23:22:49 -04:00
Atony ae45c506cb Temporary fix for scroller being too small 2026-08-07 18:32:55 -05:00
Atony fd01273635 Merge branch 'dev' into game-modes 2026-08-07 15:08:23 -05:00
Atony 840761787f Merge pull request #97 from All-Of-Us-Mods/dev
MiraAPI 0.4.3
2026-08-06 18:29:35 -05:00
Atony 615d527c86 Merge branch 'master' into dev 2026-08-06 18:25:58 -05:00
Atony 7628a41d86 Adjust tab count + text 2026-08-06 17:50:25 -05:00
amber 121baeb178 Remove IsHideAndSeek 2026-08-06 17:37:55 -04:00
Atony 0cf4954eaf Add in Hide and Seek role logic 2026-08-05 22:36:34 -05:00
Atony 8f403f5408 Add modifier classic check 2026-08-05 22:05:27 -05:00
Atony 2f5c382ece Remove hns IsNormal patch 2026-08-05 22:00:20 -05:00
Nix-main 1ab0c3f4a7 Fix IsInstance for associated mode 2026-08-05 22:55:01 -04:00
Nix-main 0230d98642 make IsClassic and IsHideNSeek use assignable 2026-08-05 22:53:17 -04:00
Nix-main 04b7a9905d make gamemode use assignable from / instance 2026-08-05 22:00:09 -04:00
Nix-main 317e0b6ea9 Fix gamemodes not being properly added to the option 2026-08-05 21:26:09 -04:00
Nix-main cbe44a40d0 Fix button issue and emove options reload logic for now 2026-08-06 01:10:21 -04:00
Nix-main d5c3905684 fix reloading not occuring until next opening of the menu 2026-08-06 00:34:30 -04:00
Nix-main 49d16b707c use ValueChanged patch for logic 2026-08-06 00:31:04 -04:00
Nix-main 3eb5bfae01 Merge remote-tracking branch 'origin/game-modes' into game-modes
# Conflicts:
#	MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
2026-08-06 00:23:51 -04:00
Nix-main b1293081fc Merge remote-tracking branch 'origin/dev' into game-modes
# Conflicts:
#	MiraAPI/Patches/Options/GameSettingMenuPatches.cs
#	MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
2026-08-05 22:04:06 -04:00
Atony 83751a25a9 add back some fixes 2026-08-05 18:58:25 -05:00
Atony bd58fca7bd Merge branch 'dev' into game-modes 2026-08-05 18:50:22 -05:00
XtraCube 63d1003b2b fix role scroll issues 2026-08-05 15:08:58 -04:00
Atony 0645c32cca Add tmp sprite todo comment 2026-08-05 13:39:43 -05:00
Atony 8beabb20a2 Bump version 2026-08-05 12:19:10 -05:00
Atony 3f28d70308 Fix errors every time role options are opened 2026-08-05 12:18:36 -05:00
Atony b919c55ef1 Fix advanced role settings being unscrollable 2026-08-05 11:55:30 -05:00
XtraCube 55a2161876 get rid of field warning 2026-08-04 00:04:13 -04:00
XtraCube 4ca2249fbd options patches overhaul 2026-08-04 00:01:21 -04:00
Atony fc94c8e67e Bump version 2026-08-02 20:13:16 -05:00
Atony 83e550c1f2 Merge pull request #96 from All-Of-Us-Mods/dev
MiraAPI 0.4.2
2026-08-02 20:11:59 -05:00
Atony edee889ffe Fix hidden local tabs breaking the menu 2026-07-30 23:15:24 -05:00
amber 119d4c5152 use methodrpc 2026-07-30 01:58:04 -04:00
Nix-main c99f468abf sync gamemode option 2026-07-30 00:39:02 -04:00
Nix-main adde6db1d0 Merge remote-tracking branch 'origin/dev' into game-modes
# Conflicts:
#	MiraAPI/GameModes/AbstractGameMode.cs
#	MiraAPI/GameModes/CustomGameModeManager.cs
#	MiraAPI/GameOptions/AbstractOptionGroup.cs
#	MiraAPI/GameOptions/ModdedOptionsManager.cs
#	MiraAPI/Modifiers/Types/TimedModifier.cs
#	MiraAPI/Patches/Menu/NameplatesTabPatches.cs
#	MiraAPI/Patches/Menu/SkinsTabPatches.cs
#	MiraAPI/Patches/Menu/VisorsTabPatches.cs
#	MiraAPI/Patches/Options/GameOptionsMenuPatch.cs
#	MiraAPI/Patches/Options/GameSettingMenuPatches.cs
#	MiraAPI/Patches/Options/LobbyViewPanePatches.cs
#	MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
#	MiraAPI/PluginLoading/IMiraPlugin.cs
#	MiraAPI/PluginLoading/MiraPluginInfo.cs
#	MiraAPI/PluginLoading/MiraPluginManager.cs
#	MiraAPI/Utilities/Extensions.cs
2026-07-29 19:50:41 -04:00
Nix-main 0012fe8cd6 Make ActiveMode setter private 2026-07-29 18:14:27 -04:00
Nix-main 9148a1e8da Sync gamemode option surely 2026-07-29 18:13:14 -04:00
Atony 8c5aee4beb Fix vanilla roles tab being broken 2026-07-26 11:56:21 -05:00
Atony 30a39fa223 Add DisplayOnOptionsMenu for mira api mods 2026-07-26 11:12:28 -05:00
Atony 228ed9711a Add mod name abbreviation 2026-07-26 11:05:13 -05:00
Atony 7c085b1072 Add modifier post assignment-check 2026-07-25 18:03:29 -05:00
Atony 8750e5c894 Reorder modifier validity checks 2026-07-25 17:20:14 -05:00
David Higueros 695bbf8ea7 Registered menu types in Il2Cpp 2026-07-23 23:18:01 -06:00
Atony ca27188229 Merge branch 'dev' into pr/95 2026-07-23 19:27:45 -05:00
XtraCube 1b40b1c5e4 attempt to improve gc behavior 2026-07-20 20:23:38 -04:00
XtraCube 0a0ad74419 improve GC collection 2026-07-20 20:02:29 -04:00
XtraCube 992bdbcbf8 cleanup usings 2026-07-20 19:10:06 -04:00
XtraCube f9721a8d69 improve stability and FPS on 17.4+ 2026-07-20 19:06:52 -04:00
XtraCube e541840da9 improve lag issues in settings menu on 17.4 2026-07-20 16:35:52 -04:00
David Higueros 6ca0b25674 Fixed documentation typo lol 2026-07-18 18:02:17 -06:00
David Higueros 638db81335 Renamed parameters to match/improve documentation 2026-07-18 17:59:23 -06:00
David Higueros d603f5c953 Called SetNameplateAppearance on total selections equal case as well to account for confirming 2026-07-18 17:52:13 -06:00
David Higueros a776edc1f6 Added case for selecting a panel past the max selections 2026-07-18 17:51:13 -06:00
Atony 6b3ce1971d Merge branch 'dev' into phone-menu-extension 2026-07-18 08:50:34 -05:00
David Higueros 65e7770fc5 Merge branch 'dev' into util-extension-dev 2026-07-17 22:43:29 -06:00
David Higueros 8db3e10ce7 Added example for Visibility attribute 2026-07-17 22:41:23 -06:00
David Higueros e205a68330 Created examples of utilizing option lists 2026-07-17 22:37:41 -06:00
David Higueros ff6c6114cf Changed option list attributes to only accept strings with zero or one format parameters 2026-07-17 22:28:13 -06:00
Atony eb18d82d8e Allow overriding configuration on modded option 2026-07-17 21:34:10 -05:00
David Higueros ff3478be54 Merge branch 'dev' into util-extension-dev 2026-07-17 19:24:35 -06:00
Atony 7afd899e56 Improve example options 2026-07-17 15:47:53 -05:00
Atony 5cccc192b1 Add support for better option notfs 2026-07-17 15:07:40 -05:00
David Higueros 8246e58f00 Added base Begin for Paginable menu 2026-07-12 23:44:51 -06:00
David Higueros bae3ff8cea Added documentation to new classes and methods 2026-07-12 23:35:14 -06:00
David Higueros 24443c94ca Renamed parameter to match overload 2026-07-12 23:13:19 -06:00
David Higueros 7f023eb2c9 Created UiElement for confirm button 2026-07-12 22:55:03 -06:00
David Higueros 8700a2bf92 Added onSelection field to use earlier 2026-07-12 22:39:04 -06:00
David Higueros dc909037e8 Added shouldConfirm to single selection Begins with default false 2026-07-12 22:35:54 -06:00
David Higueros b3501b47c4 Added TODO comments for confirming multi-selection 2026-07-12 22:33:34 -06:00
David Higueros 9cfd8d6857 Clear selections on clicking back 2026-07-12 22:32:03 -06:00
David Higueros 54f594f947 Added 2 selections overload 2026-07-12 22:28:11 -06:00
David Higueros 4fb9897cc6 Made CustomPlayerMenu extend MultiSelectMenu 2026-07-12 22:19:59 -06:00
David Higueros 810facf50e Added canRepeat parameter 2026-07-12 22:12:56 -06:00
David Higueros e6621bd036 Added overload for single selections 2026-07-12 22:11:12 -06:00
David Higueros a5ec81b51f Created basic MultiSelect Custom Menu 2026-07-12 22:06:14 -06:00
David Higueros 88e17c4f58 Marked method as Obsolete to prevent it from being used. 2026-07-12 20:15:00 -06:00
David Higueros 49e5061d88 Created interfaces to define entries stored within the menu 2026-07-12 20:03:15 -06:00
David Higueros 6175628fdf Moved interface out of class 2026-07-12 19:54:58 -06:00
David Higueros d65203692b Created Paginable Menu subclass based on TOU GuesserMenu 2026-07-12 16:47:22 -06:00
David Higueros 04329e1c87 Added generic to only have certain types of entries 2026-07-12 16:22:55 -06:00
David Higueros 86912d75e4 Made menuEntries protected with initial value and BasicEntry sealed 2026-07-12 15:57:36 -06:00
David Higueros 1719bbf1b7 Added local variable, properties, and delegate type 2026-07-12 15:33:48 -06:00
David Higueros 59db03f39d Made Entry Selection check default to false 2026-07-12 15:10:13 -06:00
David Higueros 17db947003 Added base nameplate appearance method 2026-07-12 15:07:19 -06:00
David Higueros 48112c6a42 Added on mouse actions 2026-07-12 15:06:44 -06:00
David Higueros 1660dd72dc Renamed variables and removed variable 2026-07-12 14:48:43 -06:00
David Higueros 3f2a3286ed Added MenuDepth property 2026-07-12 13:38:23 -06:00
David Higueros cf374487be Merge branch 'dev' into phone-menu-extension 2026-07-12 12:44:42 -06:00
David Higueros 3f952da5b2 Added documentation and reverse implicit operator to BasicEntry 2026-07-12 12:42:42 -06:00
David Higueros f34697a5bf Moved option list attributes to subfolder 2026-07-10 19:02:06 -06:00
David Higueros 2ebb9f183c Allowed properties to be of type ModdedOption<bool> 2026-07-10 16:55:33 -06:00
David Higueros a2f363c8da Added instanceGet out parameter to provide the group instance when needed, null when static, or the Singleton Instance if another OptionGroup 2026-07-10 16:48:50 -06:00
David Higueros 121744e9ef Changed what flags are set for member finding 2026-07-10 16:13:14 -06:00
David Higueros bae3a245f1 Added case for properties, including list values and indexers 2026-07-10 15:34:38 -06:00
David Higueros 7b5e38b10e Added null member case 2026-07-10 14:10:33 -06:00
David Higueros 0895c58524 Added logic to determine method member validity and obtain visibility function 2026-07-10 14:01:17 -06:00
David Higueros 22d45c7c64 Applied attribute function in options manager 2026-07-10 13:28:50 -06:00
David Higueros 908ff4fa67 Created modded option visibility attribute 2026-07-10 13:26:52 -06:00
David Higueros e7184c9592 Added RoleID further util methods 2026-07-09 23:44:46 -06:00
Atony 9d7e41a3c9 Fix duplicated Populate Results Event 2026-07-09 23:03:02 -05:00
Atony 662b52f78d Allow populated votes to be modified 2026-07-09 22:57:59 -05:00
Atony dac1d82d5c Reduce heavy garbage collection temporarily 2026-07-09 22:57:31 -05:00
David Higueros 98a0d3e2a6 Changed to use Register Panels 2026-07-09 16:27:33 -06:00
David Higueros 71234128d0 Added protected methods to add panels to custom Phone Menu 2026-07-09 16:27:31 -06:00
David Higueros 5d34f78fe0 Created parent class for phone menus 2026-07-09 16:27:27 -06:00
Atony 1b718092ee Move GC clearing out of coroutines 2026-07-08 18:13:34 -05:00
Atony 3eb0a4fdb3 Fix some instant crashing
Happens very quickly on practice mode when spam switching tasks
2026-07-08 17:31:20 -05:00
Atony 850e82155c Improve tmp offsets 2026-07-01 23:39:57 -05:00
Atony ff30d5fdd6 Add tmp sprite scaling support 2026-07-01 20:30:44 -05:00
Atony 2eecba2e51 Add TMP icon support for roles 2026-07-01 19:57:29 -05:00
Atony 84321f290e Fix game option checks 2026-06-30 16:25:53 -05:00
David Higueros 6598cb6933 Undid chaging property to init setter 2026-06-30 14:21:28 -06:00
David Higueros 706a836e4a Invert order of operation for ResetTarget so SetOutline(false) still has previous target 2026-06-30 14:17:29 -06:00
David Higueros 418889087a Merge branch 'dev' into util-extension-dev 2026-06-29 17:03:47 -06:00
David Higueros a4daa87bfc Added implicit operator to loadable asset which will call LoadAsset 2026-06-29 16:41:44 -06:00
Atony d8d3cc202a Merge pull request #94 from All-Of-Us-Mods/dev
MiraAPI v0.4.1
2026-06-29 09:22:38 -05:00
Atony e08e7e5f4b Merge branch 'master' into dev 2026-06-29 09:22:03 -05:00
Atony a5f0ed5975 Bump version 2026-06-29 09:13:24 -05:00
Atony d1f5e56cb9 Merge pull request #93 from TheDavSmasher/documentation-improvement
Documentation improvement
2026-06-29 09:12:15 -05:00
Atony 127e3f600e Fix misc warnings 2026-06-29 09:05:35 -05:00
Atony 47e02d3dcf Add documentation for menu categories 2026-06-29 08:47:21 -05:00
Atony f53e4fdc38 Add more option documentation 2026-06-29 08:44:56 -05:00
Atony b1f0ec6da3 Fix settings button breaking 2026-06-28 21:15:30 -05:00
Atony d0d5056e39 Fix hat tab being severely broken on v17.4 2026-06-28 20:30:28 -05:00
Atony 57e3f20cba Improve role option garbage collection further 2026-06-27 21:00:57 -05:00
David Higueros 7fdfd506e0 Added missing method cref 2026-06-23 21:18:05 -06:00
David Higueros edf61e722f Updated added method 2026-06-23 21:17:43 -06:00
David Higueros 791daa08ad Merge branch 'dev' into documentation-improvement 2026-06-23 21:08:22 -06:00
David Higueros e4d2509895 Added href tags for links 2026-06-23 21:01:45 -06:00
David Higueros 62c8e27535 Fixed annotations with double > annotations 2026-06-23 20:55:47 -06:00
David Higueros 8852c014ab Replaced true, false, and null with langword annotations 2026-06-23 20:54:23 -06:00
David Higueros adb9a2823d Updated docstrings to reference classes, fields, and methods directly 2026-06-23 20:43:32 -06:00
David Higueros a8861f03ac Merge branch 'dev' into util-extension-dev 2026-06-23 15:19:17 -06:00
David Higueros 25794b149b Created attribute versions for option list 2026-06-21 22:05:14 -06:00
David Higueros c3384ef850 Changed parent attribute method signatures 2026-06-21 21:43:26 -06:00
David Higueros 3fd3c68aaf Removed propertyinfo field 2026-06-21 21:06:14 -06:00
David Higueros edeec4ca4d Implemented list value patches 2026-06-21 21:01:48 -06:00
David Higueros 67727945da Changed to store a reference to the property's value instance 2026-06-21 20:42:10 -06:00
David Higueros 68fb1d2b58 Added patches to the list's getter and setter 2026-06-21 20:27:46 -06:00
David Higueros 80b8af85cb Added IList cast and null check 2026-06-21 19:59:49 -06:00
David Higueros e5658df8c5 Created parent attribute class to share methods 2026-06-21 19:35:14 -06:00
David Higueros 887be871f0 Changed abstract methods to handle casting and calling abstract overload 2026-06-21 19:28:17 -06:00
David Higueros 11fa9581fa Added abstract option list attribute 2026-06-21 18:54:57 -06:00
David Higueros 604d2f375d Added interface to error logger check 2026-06-21 13:54:08 -06:00
David Higueros 39a43f5395 Removed unnecessary private get 2026-06-21 12:57:16 -06:00
David Higueros b5e35e2533 Added constructor overload 2026-06-21 12:38:38 -06:00
Atony ff658db6f1 Remove destroyable singletons 2026-06-20 15:08:22 -05:00
Atony 750e00d06d Run GC when destroying multiple objects 2026-06-20 14:53:45 -05:00
Atony 3a5a397846 Only run gc when using v17.4 2026-06-20 14:28:08 -05:00
David Higueros bea37d815a Applied Modded option list into options manager 2026-06-20 02:06:25 -06:00
David Higueros e115317ad4 Removed generic from interface for easier manager registering alongside property 2026-06-20 01:56:14 -06:00
David Higueros 6a899ba27d Removed properties that aren't required 2026-06-20 01:29:56 -06:00
David Higueros ad6ca6fa3e Simplified property setters and getter 2026-06-20 01:27:01 -06:00
David Higueros 93d5ebf15a Removed Preset fields from interface that won't be used 2026-06-20 01:20:08 -06:00
David Higueros 007c202058 Changed properties to init instead of set to allow using object initializer but not changing the values later 2026-06-20 00:52:07 -06:00
David Higueros f9f7b7e667 Expanded setters to set the inner options values as well 2026-06-19 23:30:58 -06:00
David Higueros beb7443c9a Extended from IReadOnlyList for potential easier iteration 2026-06-19 23:30:18 -06:00
David Higueros be1d77bc6c Removed readonly properties that can be more easily replicated with the indexer 2026-06-19 23:13:10 -06:00
David Higueros b0be07192e Removed middleman classes and fields that can be handled much easier 2026-06-19 23:12:08 -06:00
David Higueros f9a33ce109 Created concrete class for nested IModdedOptions that aren't the concrete class 2026-06-19 22:32:16 -06:00
David Higueros 71a3461432 Created subclass with generic values 2026-06-19 22:23:35 -06:00
David Higueros 612597566b Created abstract class for Option list 2026-06-19 21:35:03 -06:00
David Higueros 42eba6280d Created interface for sets of equal/comparable modded options 2026-06-19 21:05:23 -06:00
David Higueros c846109d07 Changed to use obsolete annotation 2026-06-19 17:07:31 -06:00
David Higueros 690b1b2dae Added generic Enum Option attribute 2026-06-19 14:23:27 -06:00
David Higueros 01fe88ede9 Added equivalent extensions of Modifier OfType methods 2026-06-19 13:47:07 -06:00
David Higueros 34c172b6f1 Added methods to get modifiers from an interface type 2026-06-19 13:40:15 -06:00
David Higueros 29779f3711 Added similar extensions with new try remove methods 2026-06-19 13:24:28 -06:00
David Higueros 388b6ec676 Added TryRemoveModifier methods to simplify get and remove modifiers 2026-06-19 13:17:31 -06:00
David Higueros d64eaddb0e Added remove self method for modifiers 2026-06-19 12:43:28 -06:00
Atony e3b0eb68c0 Temporary measures for clearing up memory leaks 2026-06-12 18:03:13 -05:00
amber 90921ff786 Remove UseVanillaVentButton as it's unnecessary 2026-06-11 22:37:10 -04:00
amber c1d0bb5d26 Seperate vanilla vent data receiving from the actual button 2026-06-11 22:34:27 -04:00
amber 25a55b1b60 ColoredName property rather than a method 2026-05-31 11:33:14 -04:00
amber af2cc9a3c1 Renames DefaultMode to ClassicMode among other util changes. 2026-05-31 11:27:46 -04:00
Atony e9730f018d Check valid gamemode roles to spawn 2026-05-31 10:08:41 -05:00
Atony 1d316bb02f Merge branch 'dev' into game-modes 2026-05-31 09:17:43 -05:00
Atony c59ed8eaa6 Fix screenshake within options menu 2026-05-31 09:17:26 -05:00
Atony 2eac3d04f1 Add more configuration for hns tasks 2026-05-31 09:16:48 -05:00
Atony 154b50fd76 Mods can now choose to appear in the settings menu 2026-05-31 08:54:27 -05:00
Atony 390e4c1157 Fix toggle title 2026-05-13 12:26:24 -05:00
Atony 35b444854a Fix showing/hiding groups 2026-05-13 12:23:51 -05:00
Atony 8e5028c236 Fix scroller issues 2026-05-13 12:07:15 -05:00
Atony ad113a47ab Hide and add gamemode options 2026-05-13 10:15:03 -05:00
Atony 59b8e92c48 WIP option toggling 2026-05-13 08:32:26 -05:00
Atony d313089521 Register MiraAPI within itself 2026-05-13 08:32:11 -05:00
Atony 0852f769ae Fix game mode option appearing in mod tabs 2026-05-12 22:18:48 -05:00
Atony ae4b4d872b Add crewmate kill tracker 2026-05-12 22:09:38 -05:00
Atony b33a66cbd9 Fix OnPlayerDeath for HnS 2026-05-12 21:48:14 -05:00
Atony ac87003d0a Fix color not applying on game mode name 2026-05-12 21:46:01 -05:00
Atony f7de7f127d Merge branch 'dev' into game-modes 2026-05-12 21:24:52 -05:00
Atony d2fafc3650 Fix errors in How to Play menu 2026-05-04 09:55:37 -05:00
Atony 0c0157fed2 Add soft-support for Corsac Cosmetics 2026-05-04 07:43:53 -05:00
Atony e095e2da6a Merge branch 'dev' into game-modes 2026-05-03 22:32:51 -05:00
Atony 90bf402cbc Fix UI resizing with the top right buttons 2026-05-03 11:57:04 -05:00
Atony 50cb8ffc3d Add body type patch for Hide n Seek 2026-05-01 20:52:54 -05:00
Atony 4f4b880ad4 Reimplement Hide n Seek intro (no music) 2026-05-01 20:34:45 -05:00
amber b627006ba1 Move gamemode option to the top, fix registration. 2026-05-01 12:44:54 -04:00
Atony b0ceb129a4 Re-add Hns options as modded options
The options don't appear yet though, this needs to be fixed!
2026-04-30 12:37:54 -05:00
Atony bf7c800613 Add basic Hide n Seek gamemode 2026-04-30 11:58:02 -05:00
Atony 990bac4c06 Merge branch 'dev' into game-modes 2026-04-30 10:09:46 -05:00
amber 08c6883a0d Remove more StringNames duplication 2026-04-26 23:19:01 -04:00
Nix-main 3066720e6e Rename Default -> Classic 2026-04-26 23:09:00 -04:00
Nix-main af363000c7 Fix bugs and add HuD 2026-04-26 23:06:38 -04:00
Atony 245f2e6919 Merge pull request #83 from All-Of-Us-Mods/dev
## What's Changed
- Guardian Angel protection is checked properly.
- The Options Menu no longer throws errors on Android
- Framerate slider applies properly on PC again
- StateMachineWrapper now allows overriding existing states and returns for Coroutines.
2026-04-18 08:41:18 -05:00
Atony fed3abafb2 Bump version 2026-04-18 08:31:59 -05:00
Atony 925d47a275 Fix framerate slider 2026-04-18 08:29:11 -05:00
Atony 45a3597ab2 Update dependencies 2026-04-04 20:50:27 -05:00
Chipseq faeb39d3de use AccessTools to allow any method to be an event handler 2026-04-04 22:05:41 +02:00
Atony 6b46cffe5e Add isKilling check for basic kills 2026-04-03 20:31:27 -05:00
Atony 00a60bb7ad Add methods for StateMachineWrapper 2026-04-03 09:46:44 -05:00
Atony d89bce6956 Merge branch 'master' into dev 2026-04-01 21:33:21 -05:00
Atony 7f92e94293 Fix options menu error on mobile 2026-04-01 21:30:28 -05:00
Atony 6199e55110 Add Guardian Angel protection checks 2026-04-01 21:30:19 -05:00
Pietro420 eac442443b Random Snapshot for kill anim 2026-03-29 22:34:43 -03:00
Pietro420 6321753ec0 Don't use nullable for kill anim 2026-03-29 22:26:07 -03:00
XtraCube e66d45bd21 revert ID change for now 2026-03-23 19:33:16 -04:00
XtraCube 1e00181220 Change plugin identifier for Mira API 2026-03-23 12:07:08 -04:00
Amber 77c13bebdc fix goofy 'works on my machine' 2026-03-22 03:30:33 -04:00
Atony fcd7856571 Merge pull request #82 from All-Of-Us-Mods/dev
MiraAPI 0.3.9
2026-03-21 16:25:04 -05:00
Atony 5680d27db1 Merge branch 'master' into dev 2026-03-21 16:22:27 -05:00
amber 00eaa2601c Make Gamemode text bigger 2026-03-11 21:55:40 -04:00
Atony 49d77fcf40 Fix issues with PlayerControl.Die race condition 2026-03-11 15:40:50 -05:00
Atony dcb4a3876f Fix neutral color in view pane 2026-03-11 00:23:32 -05:00
amber ba2deb66f1 Remove from HNS, fix spacing. 2026-03-10 20:24:39 -04:00
amber bb5c212e97 Summary tag for the only public part of the option 2026-03-10 19:57:11 -04:00
amber f59e0af7e8 make patch methods private 2026-03-10 19:54:10 -04:00
amber 8f3a137877 Merge remote-tracking branch 'origin/game-modes' into game-modes 2026-03-10 19:49:56 -04:00
amber 44415019cc Full gamemode option in vanilla Game Options menu. 2026-03-10 19:49:44 -04:00
Atony 7125374cda Merge branch 'runtime-options' into game-modes 2026-03-10 18:47:48 -05:00
Atony cff46ebd19 Merge branch 'dev' into runtime-options 2026-03-10 18:47:28 -05:00
Atony 9270de408d Verify that target isn't already dead or dc'd 2026-03-10 18:04:22 -05:00
Atony 8940de76bb Add one last murder check 2026-03-10 00:18:55 -05:00
Atony 1813fe5a84 Adjust functions 2026-03-09 09:43:00 -05:00
Atony 272b14f0e0 Change murders to check with the host beforehand 2026-03-09 09:35:36 -05:00
amber 8b19271e34 Merge branch 'runtime-options' into game-modes 2026-03-08 17:57:00 -04:00
amber c29e882d7e Fix error from float data in ModdedStringOption.cs 2026-03-08 13:24:24 -04:00
Atony fdfb876b44 Fix plugin loading 2026-03-07 22:36:39 -06:00
Atony 205eee96b2 Merge branch 'dev' into game-modes 2026-03-07 22:21:08 -06:00
amber 8774c9da70 Fix tony's -1 index 2026-03-07 21:48:28 -05:00
Atony 51c7e248f9 Update Directory.Build.props 2026-03-07 15:24:28 -06:00
Atony 02f9c20804 Add wip string option 2026-03-07 15:23:26 -06:00
XtraCube 6cc1d4b762 updated readme 2026-02-27 12:11:41 -05:00
Atony 9dfad78df6 Merge pull request #81 from All-Of-Us-Mods/dev
MiraAPI 0.3.8
2026-02-11 11:50:15 -06:00
Atony 7f506000a4 Check for vanilla kills 2026-02-11 11:40:55 -06:00
Atony 795b6a81d7 Merge branch 'dev' of https://github.com/All-Of-Us-Mods/MiraAPI into dev 2026-02-10 14:00:51 -06:00
Atony bd8d7a3208 Add lobby checks for kills 2026-02-10 14:00:47 -06:00
Atony e8536e5d4b Merge pull request #80 from All-Of-Us-Mods/dev
## What's New
- Individual game options can be reset if they are a part of a preset.
- A new meeting-specific murder rpc is now available for use, checking for kills happening within and outside of a meeting.
- ## What's Changed
- Framerate Slider has been renamed to be more accurate
- Memory usage per frame has been improved
2026-02-08 16:30:05 -06:00
Atony 090db766b2 Bump version from 0.3.6 to 0.3.7 2026-02-08 16:25:37 -06:00
Atony 1f0027108e Automatically change reactor dev build indicator 2026-02-01 13:22:57 -06:00
Atony 665724010d Fix how to play errors without custom roles 2026-01-26 13:02:39 -06:00
wangzeyu b100f92525 Update README_zh.md 2026-01-24 06:34:59 +08:00
wangzeyu 202b098857 Create README_zh.md 2026-01-24 06:33:49 +08:00
wangzeyu fedba71889 Update README.md 2026-01-23 05:22:50 +08:00
Atony 2d58c91289 Replace alt murder rpc 2026-01-21 04:47:27 -06:00
XtraCube b3ed6d67f9 Reduce memory allocations in HudManagerPatches.cs 2026-01-20 16:35:44 -05:00
Atony 64ef78e3a2 Fix wordwrap on local setting 2026-01-20 10:21:37 -06:00
Atony 5e9e4012ef Update CustomMurderRpc.cs 2026-01-19 21:38:45 -06:00
Atony fe04a7033a Change kill button to use alt murder rpc 2026-01-19 21:15:52 -06:00
Atony ba0ee49255 Add reset button for game options 2026-01-19 20:10:21 -06:00
Atony 97528b4380 Add alternative Murder RPC for meeting checks 2026-01-19 19:31:31 -06:00
Atony 50030c113b Merge pull request #78 from All-Of-Us-Mods/dev
## What's New
- Screen shake no longer interferes with scrolling in the host options menu
## What's Changed
- Sabotage flashes no longer break on Starlight
- Using the button scale setting no longer breaks the UI.
- If a role fails to register to a marshalling error (nullables) the game will no longer crash.
2026-01-04 12:41:46 -06:00
Atony 20e51cc993 Bump version 2026-01-04 12:38:43 -06:00
Atony 64b5e01ba1 Improve scrolling in roles menu itself 2026-01-03 19:06:51 -06:00
Atony d4469153ab Improve scrolling in roles menu 2026-01-03 19:00:46 -06:00
Atony ab67c233d8 Add FPS slider (default to 120 fps) 2026-01-03 18:55:12 -06:00
Atony c72eacc7a2 Fix options scroll with screen shake 2026-01-03 18:54:57 -06:00
Atony 13072d6834 Fix dualshock light errors on Starlight 2026-01-02 22:57:58 -06:00
Atony c6342750ef Add checks to prevent errors on Starlight 2026-01-02 15:17:31 -06:00
XtraCube 5c2e95376d add exception handling around role registration 2025-12-31 22:38:01 -05:00
Atony 067859b9fd Fix scale factor not setting properly when changed 2025-12-31 18:36:19 -06:00
Atony fe3bfcdbc4 Merge pull request #77 from All-Of-Us-Mods/dev
- Added Vanilla Button Click Event (and respective Cancel Event)
- Added accessibility settings for sabotage flashes and blares
- Added an in-game slider for resizing ability buttons
2025-12-28 18:00:57 -06:00
Atony 5d01462a32 Adjust local setting groups 2025-12-28 17:55:33 -06:00
Atony a9b6f40ed0 Add Button Scale Slider 2025-12-28 17:51:39 -06:00
Atony eae0024ec3 Add Accessibility settings for sabotages 2025-12-22 21:41:36 -06:00
Atony 2907564d6a Add Vanilla Button Click Event (& Cancel Event) 2025-12-16 22:14:50 -06:00
Atony 7ad003ed1e Merge pull request #75 from All-Of-Us-Mods/dev
- Adds custom game tabs, with their own names and description blurbs.
- All keybinds have been moved to the right for consistency and to prevent hide and seek vent uses being obscured.
- Holding shift will change most options to be split in half, like 2.5s -> 1.25s
- Vanilla roles can be blacklisted from spawning or appearing in menus via other mira mods.
- Roles can check if they can spawn on the current gamemode or under specific conditions, such as the current map.
- Adds options that can have customizable text for -1 and 0 values respectively.
- Adds support for modded roles in Hide and Seek
- Fixes vanilla roles bypassing murder attempts
- Fixes keybinds not being hidden on buttons
- Fixes buttons used via keybinds bypassing ButtonClickEvents
- Fixes crashing for Epic Games users when opening the keybinds menu.
2025-12-14 07:58:01 -06:00
Atony 93eea6ea2f Bump version 2025-12-14 07:50:55 -06:00
Atony 8e09b7fee0 Merge pull request #74 from All-Of-Us-Mods/new-features
- Adds custom game tabs, with their own names and description blurbs.
- All keybinds have been moved to the right for consistency and to prevent hide and seek vent uses being obscured.
- Holding shift will split options in half
- Vanilla roles can be blacklisted from spawning or appearing in menus via other mira mods.
- Roles can check if they can spawn on the current gamemode or under specific conditions, such as the current map.
- Add options that can have customizable text for -1 and 0 values respectively.
- Fix buttons used via keybinds bypassing ButtonClickEvents
2025-12-14 07:47:27 -06:00
Atony 1e4894538c Merge branch 'dev' into new-features 2025-12-14 07:40:15 -06:00
Atony 303aedafc7 Fix keybinds bypassing button click events 2025-12-13 15:29:12 -06:00
Atony 8ed4355504 Clear up I2lCpp warning 2025-12-08 12:28:02 -06:00
Atony 76b02835a7 Update HudManagerPatches.cs 2025-11-30 15:30:17 -06:00
Atony 8d5bc710e7 Move all binds to the top right of buttons 2025-11-30 15:22:37 -06:00
Atony 798ce451d5 Add text for setting descriptions 2025-11-29 14:21:25 -06:00
Atony 136bbde516 Fix MaxUses check 2025-11-29 13:40:21 -06:00
Atony 5252620108 Update CustomActionButton.cs 2025-11-27 23:00:24 -06:00
Atony c9b1c57774 Add toggle for buttons to change uses check 2025-11-27 22:54:03 -06:00
Atony d97df1a891 Add options for negatives as infinity 2025-11-27 22:30:04 -06:00
Atony e93ef6fd1d Add special modded number type 2025-11-27 21:34:20 -06:00
Atony 3afe437101 Fix Hns Task Event not registering properly 2025-11-23 12:50:52 -06:00
Atony 62c01b2f72 Add Hns Manager into the task event 2025-11-23 12:05:31 -06:00
Atony 089d2c1ea5 Add Hide and seek task event 2025-11-23 12:01:41 -06:00
Atony c65511d03e Add checks to hide roles from menus 2025-11-22 15:26:07 -06:00
Atony aee304fb96 Fix nullable roletype errors 2025-11-22 08:19:58 -06:00
Atony 11ba564eed Fix seeker role assignment 2025-11-21 23:18:41 -06:00
Atony 259b9b7097 Add logic for modifiers & roles in hide and seek 2025-11-21 18:23:08 -06:00
Atony 7e3a279b56 Fix imps and crew being shown twice in view pane 2025-11-20 21:51:39 -06:00
Atony 1fd2dd3539 Allow mods to blacklist vanilla roles 2025-11-20 21:39:45 -06:00
XtraCube 3f60bcae2c default constructor not supported for custom role config 2025-11-20 10:18:39 -05:00
Atony fe1580bb7e Fix double round events on Airship & Submerged 2025-11-17 18:45:32 -06:00
Atony 8b23021b2a Fix null error for player without assigned role 2025-11-16 08:41:29 -06:00
Atony fdc715dac2 Expose data for option names 2025-11-07 17:26:06 -06:00
Atony e1ca50be3e Vanilla roles no longer bypass murder cancels 2025-11-01 10:00:42 -05:00
Atony bf9b34e728 Fix modded keybinds not being hidden on buttons 2025-10-26 13:36:35 -05:00
Atony baf80618bb Rename keybinds option 2025-10-26 13:19:22 -05:00
Atony 7d1976f772 Relocale keybinds toggle to local options for epic 2025-10-26 13:15:20 -05:00
Atony 4ce24c2a00 Fix warning on epic games 2025-10-26 12:20:02 -05:00
Atony 7fa75946fd Make ResetCooldowns callable 2025-10-25 18:51:14 -05:00
Atony 43f92d4dc2 Standadize button position 2025-10-25 12:17:44 -05:00
Atony ee22b776eb Fix Vanilla view pane 2025-10-20 18:23:13 -05:00
Atony f31349f6e8 Add shift-intervals for options 2025-10-20 11:17:51 -05:00
Atony 448e2f9152 Adjust size and scale 2025-10-18 13:27:33 -05:00
Atony dde7e70406 Fix category names 2025-10-18 12:32:34 -05:00
Atony 713a7a2bcc Work on adding custom game tabs 2025-10-18 12:19:15 -05:00
Atony 056a9b6102 Merge pull request #72 from All-Of-Us-Mods/dev
Fix Logger error for v0.3.3
2025-10-14 13:53:21 -05:00
Atony 4b144a782d Fix Logger error 2025-10-14 13:53:02 -05:00
Atony ae917a9c77 Merge pull request #71 from All-Of-Us-Mods/dev
MiraAPI v0.3.3
2025-10-14 13:46:58 -05:00
Atony 7a8d608b17 Bump Version (again) 2025-10-14 13:46:08 -05:00
XtraCube 6503bbecb7 use reactor static logging pattern 2025-10-14 14:37:20 -04:00
XtraCube cb794c3fc2 make kill anim patch update resilient 2025-10-14 14:35:20 -04:00
XtraCube 88329bef79 update freeplay patch to be version resistant 2025-10-14 14:14:25 -04:00
XtraCube eb7abecd75 update to latest among us 2025-10-14 14:06:43 -04:00
Atony fc9e9740be Merge pull request #70 from All-Of-Us-Mods/dev
MiraAPI v0.3.2
2025-10-14 09:08:53 -05:00
Atony 3c51c88963 Bump version 2025-10-14 09:05:25 -05:00
Atony e42f5e6029 Log exception 2025-10-12 19:44:30 -05:00
Atony 61be7dda82 Maybe fix the issues with kill animations? 2025-10-12 18:33:45 -05:00
xChipseq 3220a4a820 change texture wrap mode to clamp 2025-10-11 00:46:35 +02:00
XtraCube 8fd142a92e fix custom murder dead body 2025-10-04 14:07:00 -04:00
XtraCube fcec6ad6e5 fix new role fields 2025-10-01 22:17:40 -04:00
XtraCube 10a7ffe886 add new role information to try and fix broken gamemanager 2025-10-01 20:59:44 -04:00
Atony 7e541733b7 More fixes for role names 2025-09-30 18:15:29 -05:00
Atony 99a275a97c Adjust edit pane for self-adjusting role names 2025-09-30 18:08:56 -05:00
XtraCube 67a5f0dd67 fixing inner scuff problems 2025-09-30 11:22:43 -04:00
XtraCube f13d46ec18 android support 2025-09-30 11:13:23 -04:00
Atony f9096b6160 Merge pull request #69 from All-Of-Us-Mods/dev
MiraAPI v0.3.1
2025-09-28 13:17:06 -05:00
Atony 8bf101534f Bump version 2025-09-28 13:13:21 -05:00
Atony 479323acdd Merge pull request #68 from yanpla/dev
Fix DetectiveNotesMinigame
2025-09-28 13:06:21 -05:00
Atony 50c5899f4d Merge branch 'dev' into dev 2025-09-28 13:06:12 -05:00
XtraCube fd719ae42f Merge remote-tracking branch 'origin/dev' into dev 2025-09-26 12:18:18 -04:00
XtraCube e050b043cb use reflection for intro cutscene patches 2025-09-26 12:18:13 -04:00
XtraCube e78c456636 match android 2025-09-25 13:47:54 -04:00
XtraCube 7e8d07672c fix mira asset 2025-09-25 12:27:26 -04:00
XtraCube 77ae01c66a improve player customization tabs 2025-09-25 12:25:12 -04:00
XtraCube ce824f05fa fix selection problem on android 2025-09-25 11:36:34 -04:00
yanpla b5fe3c7afd Remove custom roles from DetectiveNotesMinigame 2025-09-24 19:53:24 +02:00
XtraCube 1750cd3db9 Merge pull request #67 from All-Of-Us-Mods/dev
0.3.0
2025-09-24 08:54:52 -04:00
XtraCube 4dd2554b38 bump version 2025-09-24 08:53:09 -04:00
XtraCube e5cfd8a2fc fix game never ending 2025-09-24 08:24:14 -04:00
XtraCube 6d387cae96 fix round start events for airship 2025-09-24 07:35:50 -04:00
XtraCube 59f3058685 update comment 2025-09-24 07:21:31 -04:00
XtraCube 9dfb40d7bf add new role stubs 2025-09-24 07:12:34 -04:00
XtraCube ffca13e6e6 Merge remote-tracking branch 'origin/dev' into dev 2025-09-21 16:57:06 -04:00
XtraCube c1d2868e77 fix server dropdown 2025-09-21 16:57:00 -04:00
Atony 18c52e0138 Expose certain local option overrides and tabs 2025-09-20 22:17:51 -05:00
XtraCube b64bf7c9de bump version 2025-09-20 22:14:07 -04:00
XtraCube e98c16b9f5 fix role settings tab 2025-09-20 22:12:51 -04:00
xChipseq e166efa666 ignore custom roles in vanilla role options 2025-09-20 23:47:36 +02:00
xChipseq 8da80be027 add HideIconOnHover for local settings 2025-09-20 21:58:30 +02:00
XtraCube af75cc3606 revert un-inline 2025-09-20 11:16:56 -04:00
XtraCube 0f1962394a un-inline rpcendgame 2025-09-19 21:07:22 -04:00
XtraCube 36991f34ee fix index of task adder patch 2025-09-19 20:52:01 -04:00
Atony ae5f3783b4 Add locale to task adder 2025-09-18 05:07:05 -05:00
Atony 12a1908c3e Merge branch 'dev' of https://github.com/All-Of-Us-Mods/MiraAPI into dev 2025-09-18 04:47:11 -05:00
xChipseq 8246e05da6 Merge remote-tracking branch 'origin/dev' into dev 2025-09-17 21:04:24 +02:00
xChipseq c75e039141 fixes 2025-09-17 21:04:05 +02:00
Atony ac66e0d62b Clear up warnings 2025-09-17 12:23:40 -05:00
xChipseq c4cbf0b18d use the old system instead of role children 2025-09-17 19:19:47 +02:00
Pietro420 f3175990d3 ACTUALLY fix Viper 2025-09-14 20:07:17 -03:00
XtraCube 790d868759 fix viper 2025-09-14 15:26:58 -04:00
XtraCube 9f11874189 fix role settings 2025-09-14 15:15:06 -04:00
xChipseq 1b6a2c4eb3 part 1 of trying to fix the task adder 2025-09-12 23:49:24 +02:00
xChipseq 81887c34d9 fix misaligned settings (again) 2025-09-12 23:23:10 +02:00
xChipseq 810fd54e10 i love useless using thingies 2025-09-12 22:33:05 +02:00
xChipseq 5492c2b3cc fix how to play role tutorial 2025-09-12 22:02:21 +02:00
XtraCube f7a515882a Merge pull request #65 from All-Of-Us-Mods/2025.9.9
2025.9.9 Support
2025-09-11 21:00:00 -04:00
Atony 89eb774501 Merge pull request #66 from WanderingPix/fix-roleicons
Fix role icons now appearing if there are no settings for the role.
2025-09-11 05:26:17 -05:00
WanderingPixel 5fd57633ff Update RoleSettingMenuPatches.cs 2025-09-11 11:01:35 +01:00
xChipseq 834d1d878e fix 2025-09-10 22:45:48 +02:00
xChipseq 790b37e8d3 cool role file icons 2025-09-10 22:40:09 +02:00
xChipseq dfa8b29710 update task adder (and improvements) 2025-09-10 22:07:47 +02:00
Atony da7aab9aa2 Merge pull request #64 from All-Of-Us-Mods/vanilla-keybind-bindings
Vanilla keybindings
2025-09-09 18:44:18 -05:00
xChipseq 2c0042e6a8 bump to 2025.9.9 2025-09-09 22:58:18 +02:00
xChipseq 70f63f8b16 custom role fixes 2025-09-09 22:58:02 +02:00
xChipseq 03a3733966 fix body prefab 2025-09-09 22:57:19 +02:00
Atony 3d274c2f61 KEYBINDS WORK NOW 2025-09-09 05:05:56 -05:00
Atony b94e20c6f7 Add Ability Button bind 2025-09-08 20:29:33 -05:00
Chipseq 5a0428c7c0 Merge branch 'dev' into vanilla-keybind-bindings 2025-09-08 21:08:53 +02:00
xChipseq c41dd27f88 init vanilla keybinds after input manager init 2025-09-08 19:38:07 +02:00
xChipseq 6872ca6866 basekeybind class, vanilla keybindings 2025-09-08 18:37:09 +02:00
xChipseq 4b7fa906b9 fix misaligned options after labels 2025-09-07 22:49:23 +02:00
xChipseq b7173d18ab change mira config 2025-09-07 22:45:06 +02:00
xChipseq ffc7a1a4fd fix keybind icon clipping 2025-09-07 22:43:08 +02:00
XtraCube a1611f5f7a fix merge errors 2025-09-07 16:34:57 -04:00
XtraCube 1664aa1003 Merge branch 'fork/xChipseq/local-settings-rework' into dev
# Conflicts:
#	MiraAPI/MiraApiConfig.cs
#	MiraAPI/PluginLoading/MiraPluginManager.cs
#	MiraAPI/Utilities/Helpers.cs
2025-09-07 16:29:33 -04:00
xChipseq af3d99eafe wip 2025-09-07 21:25:15 +02:00
xChipseq 94197e38dd cleanup 2025-09-07 20:47:59 +02:00
angxl wtf 97a0b2084a Merge pull request #61 from WanderingPix/timed-modifiers-taskadder-icon
Timed modifier QOL changes in Task Adder
2025-09-07 13:50:48 -04:00
Atony 1d87790212 Merge pull request #62 from All-Of-Us-Mods/vote-event-tweaks
Add Before and After Vote Events
2025-09-06 22:54:04 -05:00
xChipseq 9d130a53de fix typo 2025-09-07 00:54:44 +02:00
Atony d8afc6887d Merge branch 'dev' into vote-event-tweaks 2025-09-06 14:36:22 -05:00
Atony c0a406610d Merge pull request #60 from WanderingPix/Roleicons-in-options-menu
Role icons in options menu
2025-09-06 14:32:14 -05:00
Atony d73c21936c Add Before and After vote events
Useful for local checks before a vote is placed (like with TOU Mira Prosecutor)
2025-09-06 14:19:17 -05:00
xChipseq 449192f0ef remove this annoying log 2025-09-06 19:02:40 +02:00
xChipseq f3614b9a5c fix null errors 2025-09-05 23:33:01 +02:00
angxl wtf a62c6d496c Merge pull request #57 from xChipseq/button-improvements
Custom Button Improvements + Major Keybind API rewrite
2025-09-04 19:02:07 -04:00
xChipseq bebd648691 remove null check, it's always none when null 2025-09-04 21:51:45 +02:00
xChipseq ecadfa86dd remove invoke log 2025-09-04 21:51:26 +02:00
WanderingPixel 5ad53f695f Update TaskAdderPatches.cs 2025-09-04 14:29:39 +01:00
WanderingPixel 31a9c0c98d Update TaskAdderPatches.cs 2025-09-04 13:23:31 +01:00
WanderingPixel ea389b986f Update TaskAdderPatches.cs 2025-09-04 12:58:09 +01:00
WanderingPixel ef85fab6a6 Update TaskAdderPatches.cs 2025-09-04 12:35:40 +01:00
WanderingPixel b2fdaaf89f Timed Modifier Enhancements in TaskAdderGame 2025-09-04 12:29:19 +01:00
WanderingPixel e6043b6f5f Fix Masking issue 2025-09-03 21:27:38 +01:00
WanderingPixel ffe0db0e9e Add role icons in role settings menu 2025-09-03 21:14:07 +01:00
xChipseq 705ef64b4d fix helper method returning null if no keybind 2025-09-02 22:27:04 +02:00
xChipseq ebdb4a09ca make number options accept floats 2025-09-02 19:24:34 +02:00
xChipseq ac113b6a7f add tab open method and fixes 2025-09-02 18:55:27 +02:00
xChipseq 1f6962efe9 add local setting buttons 2025-09-01 23:34:17 +02:00
xChipseq 6b37b9c09c add an error 2025-09-01 22:28:30 +02:00
xChipseq f515516937 remove the two million test tabs 2025-09-01 22:24:58 +02:00
xChipseq 8b2d24ccc1 more stuff 2025-09-01 22:22:32 +02:00
xChipseq 57bab258e5 enum and int options and lots of other stuff i forgot 2025-09-01 21:54:13 +02:00
ang-xd 04d5e72caa Add slider float value 2025-08-31 18:45:22 -04:00
ang-xd b4e6e448f2 Major work/rewrite on local settings 2025-08-31 18:04:52 -04:00
xChipseq b19a0178ad add a limit to multitarget buttons 2025-08-31 23:41:35 +02:00
xChipseq 8a71f13874 fix for keybind loading 2025-08-31 20:26:22 +02:00
xChipseq 809e7a07ab literally one dot 2025-08-31 20:21:50 +02:00
xChipseq 47394c6afe fix example mod 2025-08-31 18:06:53 +02:00
xChipseq a2a1e91439 replace EffectCancelable with a method 2025-08-31 18:03:17 +02:00
xChipseq 2f5ca32475 multitarget buttons 2025-08-31 17:59:38 +02:00
xChipseq 5fb59408fa wip 2025-08-31 17:51:02 +02:00
xChipseq 57c842ece6 Merge remote-tracking branch 'origin/local-settings-rework' into local-settings-rework 2025-08-30 23:08:55 +02:00
Chipseq 63e552245d Sync local settings branch with dev 2025-08-30 23:05:03 +02:00
xChipseq 43d7f80660 add show keybinds setting 2025-08-30 21:41:04 +02:00
xChipseq 45291b0e98 change default keybinds to make sense 2025-08-30 21:31:34 +02:00
xChipseq 45972f71a9 major rework of the keybinds api 2025-08-30 21:13:42 +02:00
xChipseq a6f7171b71 add PauseTimerInVent 2025-08-29 14:32:13 +02:00
xChipseq e6d3819517 add uses mode for buttons 2025-08-29 14:20:19 +02:00
xChipseq b97ada22bc allow the duration to be 0 2025-08-29 13:58:06 +02:00
xChipseq 5f67960b28 cancelable abilities 2025-08-29 13:38:35 +02:00
xChipseq b4e30b2b68 wip 2025-08-29 13:04:18 +02:00
ang-xd 2237d3a2df Additional changes to keybind icons 2025-08-28 12:33:19 -04:00
ang-xd e708c23f81 Fix checks and positions for keybinds 2025-08-28 11:26:45 -04:00
ang-xd 3ca33b1d86 Merge branch 'master' into dev 2025-08-28 11:08:57 -04:00
angxl wtf 8967348cd3 Merge pull request #55 from CallOfCreator/keybinds
Keybind Icons
2025-08-28 11:08:26 -04:00
angxl wtf 305d2c3714 Merge pull request #54 from AtonyGit/dev
Adjust Keybinds for Buttons + Add IntroRoleRevealEvent
2025-08-28 11:08:14 -04:00
Atony 85a0275eea Add IntroRoleRevealEvent
Also needs to be changed for the android branch
2025-08-24 19:48:43 -05:00
Atony f006deab3f Fix Send Immediately warning from Reactor 2025-08-24 18:33:52 -05:00
CallOfCreator a274f23e65 Merge pull request #1 from WanderingPix/keybinds
Add Keybind Icons
2025-08-21 11:36:08 -07:00
Atony f1a5aef581 Remove requirement but allow blank keybind 2025-08-17 20:52:46 -05:00
Atony ce15e93e59 Fix DefaultKeybind name + remove requirement
By default, buttons will use no keybind, and will not add a new keybind option in doing so.
2025-08-17 20:40:03 -05:00
XtraCube 08ca995eb1 Merge pull request #52 from All-Of-Us-Mods/dev
mira api 0.2.1
2025-08-17 16:39:35 -04:00
XtraCube 453259df98 Merge branch 'master' into dev 2025-08-17 16:36:16 -04:00
XtraCube 2ec3eec370 bump version 2025-08-17 16:34:56 -04:00
ang-xd 2ee8730ba4 WIP Left side Modifiers HUD option 2025-08-14 00:56:29 -04:00
XtraCube c89e5938cc Merge pull request #43 from CallOfCreator/keybinds
Implement Keybind API
2025-08-13 09:32:42 -04:00
WanderingPixel 513be01c02 Add Keybind icons for custom buttons 2025-08-09 22:12:15 +01:00
CallOfCreator 01fa1f0915 Update conflict system 2025-08-09 11:41:43 +00:00
CallOfCreator 355eef509b Add support for modifier keys 2025-08-06 18:03:48 +00:00
XtraCube 763a493283 Merge pull request #51 from xChipseq/dummy-improvements
Dummies Fix
2025-08-05 16:50:09 -04:00
xChipseq 68e421bf91 literally just a dot 2025-08-05 22:35:39 +02:00
xChipseq c343ab5e9f dummy fix 2025-08-05 22:34:00 +02:00
XtraCube 9c1ef70ea7 Merge pull request #50 from xChipseq/dummy-improvements
Dummy Voting Improvements
2025-08-04 21:19:18 -04:00
xChipseq c0c8fa08ff changed DidVote to check VotesRemaining instead of Votes 2025-08-04 20:58:24 +02:00
xChipseq e7fba386aa dummy changes 2025-08-04 20:53:50 +02:00
XtraCube 72e5e0c137 Merge pull request #49 from xChipseq/round-start-event
Invoke RoundStartEvent when starting freeplay
2025-08-04 12:30:09 -04:00
XtraCube 4422072060 Merge pull request #48 from AtonyGit/dev
Add BeforeRoundEvent for edge case scenarios
2025-08-04 12:29:51 -04:00
xChipseq 8145c8e599 patch 2025-08-04 15:33:04 +02:00
Atony afd6fbc3b6 Add BeforeRoundStartEvent 2025-08-02 14:24:53 -05:00
XtraCube 74741b41a7 Merge pull request #47 from WanderingPix/Ghosts-included-in-GetClosestPlayer
Add argument for PlayerControl.GetClosestPlayer() to include ghosts
2025-07-31 09:13:04 -04:00
WanderingPixel f98429b5f9 Update GetClosestPlayer method 2025-07-31 09:09:37 -04:00
XtraCube bf7edb30ab fix warnings 2025-07-20 07:30:38 -04:00
XtraCube b4527014b7 Merge pull request #44 from AtonyGit/dev
Allow modifiers to have freeplay colors
2025-07-16 14:41:01 -04:00
Atony 277391ef1c Add freeplay modifier colors 2025-07-11 22:30:09 -05:00
CallOfCreator dfe124d67a Add missing credit from previous commit 2025-07-11 18:06:06 +00:00
CallOfCreator 2b06633488 Cleanup 2025-07-11 18:00:58 +00:00
CallOfCreator 4784b1f0ad Rename CurrentKeybind to DefaultKeybind 2025-07-09 13:48:38 +00:00
CallOfCreator d9d0d6bc62 Implement Keybind API 2025-07-08 20:41:20 +00:00
XtraCube 6b3038f397 shuffle modifiers before assigning 2025-07-07 18:47:12 -04:00
XtraCube 4e1db039a0 Merge pull request #42 from AtonyGit/dev
Fix Regions Dropdown in "Find Game" & Add Tab Count for Cosmetics Menu
2025-07-05 15:36:08 -04:00
Atony 62bee24789 Fix Server Dropdown for Game Finder 2025-07-04 22:43:13 -05:00
Atony 2156c80467 Cosmetic Tab Count Improvements 2025-07-04 22:42:47 -05:00
XtraCube 0ff60071c2 fix canuse event 2025-06-30 20:47:17 -04:00
XtraCube de2f3f0d95 update assetbundle 2025-06-29 22:31:21 -04:00
XtraCube cd818a18cf Merge pull request #40 from All-Of-Us-Mods/dev
0.2.0 Update
2025-06-27 15:52:24 -04:00
XtraCube 7890ec9456 WIP update gamemodes 2025-03-04 19:21:57 -05:00
XtraCube 8bb191270f Merge branch 'dev' into game-modes
# Conflicts:
#	MiraAPI.Example/Modifiers/CaptainModifier.cs
#	MiraAPI/GameModes/CustomGameModeManager.cs
#	MiraAPI/GameOptions/AbstractOptionGroup.cs
#	MiraAPI/GameOptions/Attributes/ModdedEnumOptionAttribute.cs
#	MiraAPI/GameOptions/Attributes/ModdedNumberOptionAttribute.cs
#	MiraAPI/GameOptions/Attributes/ModdedToggleOptionAttribute.cs
#	MiraAPI/GameOptions/IModdedOption.cs
#	MiraAPI/GameOptions/ModdedOptionsManager.cs
#	MiraAPI/GameOptions/OptionTypes/ModdedEnumOption.cs
#	MiraAPI/GameOptions/OptionTypes/ModdedNumberOption.cs
#	MiraAPI/GameOptions/OptionTypes/ModdedOption.cs
#	MiraAPI/GameOptions/OptionTypes/ModdedToggleOption.cs
#	MiraAPI/Hud/CustomActionButton.cs
#	MiraAPI/MiraApiPlugin.cs
#	MiraAPI/Modifiers/BaseModifier.cs
#	MiraAPI/Patches/Options/GameOptionsMenuPatch.cs
#	MiraAPI/Patches/Options/LobbyViewPanePatches.cs
#	MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
#	MiraAPI/PluginLoading/MiraPluginManager.cs
#	MiraAPI/Roles/ICustomRole.cs
2025-03-04 19:02:38 -05:00
XtraCube 65cd177551 fix more scrolling issues 2025-02-18 11:15:00 -05:00
XtraCube 7801f81052 Merge branch 'dev' into game-modes
# Conflicts:
#	MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
2025-02-18 11:07:04 -05:00
XtraCube 2d59b29c15 cleanup 2025-02-18 10:19:55 -05:00
XtraCube a62c75a13b that was stupid 2025-02-18 10:19:22 -05:00
XtraCube c85cf7ef2f finish merge 2025-02-18 10:15:39 -05:00
XtraCube ead28339b0 Merge branch 'dev' into game-modes
# Conflicts:
#	MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
#	MiraAPI/Roles/CustomRoleConfiguration.cs
#	MiraAPI/Roles/ICustomRole.cs
2025-02-18 10:11:53 -05:00
XtraCube 9177d5b456 fix merge stuff 2025-02-17 10:14:38 -05:00
XtraCube 284a0f58b1 oops 2025-02-17 10:14:26 -05:00
XtraCube 47dfa63423 improve CustomRoleConfiguration.cs 2025-02-17 10:13:32 -05:00
XtraCube 1b261d7287 Merge remote-tracking branch 'origin/dev' into game-modes
# Conflicts:
#	MiraAPI/Hud/CustomActionButton.cs
#	MiraAPI/Patches/Options/RoleSettingMenuPatches.cs
#	MiraAPI/PluginLoading/MiraPluginManager.cs
#	MiraAPI/Roles/ICustomRole.cs
2025-02-17 09:59:42 -05:00
XtraCube fa8ea9dbab final fix to logic 2025-02-03 22:44:35 -05:00
XtraCube 9c15ca4d06 update to optimization 2025-02-03 22:43:25 -05:00
XtraCube a4b1868690 Merge branch 'optimization' into game-modes
# Conflicts:
#	MiraAPI/GameModes/DefaultMode.cs
#	MiraAPI/GameModes/RegisterGameModeAttribute.cs
#	MiraAPI/PluginLoading/MiraPluginManager.cs
2025-02-03 22:03:48 -05:00
AlchlcDvl 409503a261 read me change to reflect now mode filtering 2024-12-23 20:57:53 -05:00
AlchlcDvl edca42247d finish full implementation of game modes i hope 2024-12-23 20:52:18 -05:00
AlchlcDvl b6ba8f59bd better approach 2024-12-07 11:21:07 -05:00
AlchlcDvl f9f7898277 set option title 2024-12-07 11:18:58 -05:00
AlchlcDvl dbacd044eb game mode stuff, missing implementation of 4 methods coming soon™️ 2024-12-07 10:46:26 -05:00
455 changed files with 27556 additions and 5538 deletions

No files matched your search

+106 -1
View File
@@ -1 +1,106 @@
[*.{cs,vb}] [*.{cs,vb}]
# IDE0008: Use explicit type
dotnet_diagnostic.IDE0008.severity = none
# IDE0160: Convert to block scoped namespace
dotnet_diagnostic.IDE0160.severity = none
# IDE0011: Add braces
dotnet_diagnostic.IDE0011.severity = none
# CS8618: Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
dotnet_diagnostic.CS8618.severity = none
# CA1805: Do not initialize unnecessarily
dotnet_diagnostic.CA1805.severity = none
# S3358: Ternary operators should not be nested
dotnet_diagnostic.S3358.severity = none
# IDE1006: Naming Styles
dotnet_diagnostic.IDE1006.severity = none
# S3267: Use LINQ methods to simply foreach loops
dotnet_diagnostic.S3267.severity = none
# S125: Sections of code should not be commented out
dotnet_diagnostic.S125.severity = none
# SA1512: Single-line comments should not be followed by blank line
dotnet_diagnostic.SA1512.severity = none
# S2696: Instance members should not write to "static" fields
dotnet_diagnostic.S2696.severity = none
# S2245: Pseudorandom number generators (PRNGs) should not be used in security contexts
dotnet_diagnostic.S2245.severity = none
# IDE0130: Namespace does not match folder structure
dotnet_diagnostic.IDE0130.severity = none
# SA1633: File should have header
dotnet_diagnostic.SA1633.severity = none
# SA1101: Prefix local calls with this
dotnet_diagnostic.SA1101.severity = none
# SA1600: Elements should be documented
dotnet_diagnostic.SA1600.severity = none
# SA1516: Elements should be separated by blank line
dotnet_diagnostic.SA1516.severity = none
# SA1503: Braces should not be omitted
dotnet_diagnostic.SA1503.severity = none
# SA1201: Elements should appear in the correct order
dotnet_diagnostic.SA1201.severity = none
# SA1402: File may only contain a single type
dotnet_diagnostic.SA1402.severity = none
# SA1204: Static elements should appear before instance elements
dotnet_diagnostic.SA1204.severity = none
# SA1202: Elements should be ordered by access
dotnet_diagnostic.SA1202.severity = none
# SA1649: File name should match first type name
dotnet_diagnostic.SA1649.severity = none
# SA1313: Parameter names should begin with lower-case letter
dotnet_diagnostic.SA1313.severity = none
# SA1636: The file header copyright text should match the copyright text from the settings
dotnet_diagnostic.SA1636.severity = none
# SA1309: Field names should not begin with underscore
dotnet_diagnostic.SA1309.severity = none
# SA1407: Arithmetic expressions should declare precedence
dotnet_diagnostic.SA1407.severity = none
# SA1133: Each attribute should be placed in its own set of square brackets
dotnet_diagnostic.SA1133.severity = none
# IDE0001: Simplify Names
dotnet_diagnostic.IDE0001.severity = warning
# IDE0079: Remove unnecessary suppression
dotnet_diagnostic.IDE0079.severity = none
# S3903: Types should be defined in named namespaces
dotnet_diagnostic.S3903.severity = none
# IDE0045: Convert to conditional expression
dotnet_diagnostic.IDE0045.severity = none
# IDE0046: Convert to conditional expression
dotnet_diagnostic.IDE0046.severity = none
# S1244: Floating point numbers should not be tested for equality
dotnet_diagnostic.S1244.severity = none
# S2325: Methods and properties that don't access instance data should be static
dotnet_diagnostic.S2325.severity = none
+2 -2
View File
@@ -1,9 +1,9 @@
.git/ .git/
.idea/ .idea/
.vs/ .vs*/
obj/ obj/
bin/ bin/
.qodo/ .qodo/
*.user *.user
*.lock.json *.lock.json
+4 -4
View File
@@ -1,14 +1,14 @@
<Project> <Project>
<ItemGroup> <ItemGroup>
<PackageReference Include="Reactor" Version="2.3.1" /> <PackageReference Include="Reactor" Version="2.5.0-ci.371" />
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.735" Private="false" ExcludeAssets="runtime;native" /> <PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.735" Private="false" ExcludeAssets="runtime;native" />
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2025.4.15" PrivateAssets="all" /> <PackageReference Include="AmongUs.GameLibs.Steam" Version="2026.9.29" PrivateAssets="all" />
<PackageReference Include="BepInEx.AutoPlugin" Version="1.1.0" PrivateAssets="all" /> <PackageReference Include="BepInEx.AutoPlugin" Version="1.1.0" PrivateAssets="all" />
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.1.0-rc.1" PrivateAssets="all" ExcludeAssets="runtime" /> <PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.1.0-rc.1" PrivateAssets="all" ExcludeAssets="runtime" />
</ItemGroup> </ItemGroup>
<Target Name="Copy" AfterTargets="Build" Condition="'$(AmongUs)' != ''"> <Target Name="Copy" AfterTargets="Build" Condition="'$(AmongUs)' != ''">
<Copy SourceFiles="$(TargetPath)" DestinationFolder="$(AmongUs)/BepInEx/plugins/" UseSymboliclinksIfPossible="true" /> <Copy SourceFiles="$(TargetPath)" DestinationFolder="$(AmongUs)/BepInEx/plugins/" UseSymboliclinksIfPossible="true" />
</Target> </Target>
</Project> </Project>
+8 -11
View File
@@ -8,7 +8,7 @@
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile> <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<VersionPrefix>0.2.0</VersionPrefix> <VersionPrefix>0.5.0</VersionPrefix>
<VersionSuffix>dev</VersionSuffix> <VersionSuffix>dev</VersionSuffix>
<Authors>All Of Us, XtraCube, Angxl</Authors> <Authors>All Of Us, XtraCube, Angxl</Authors>
@@ -28,18 +28,15 @@
<AnalysisLevel>latest</AnalysisLevel> <AnalysisLevel>latest</AnalysisLevel>
<AnalysisMode>recommended</AnalysisMode> <AnalysisMode>recommended</AnalysisMode>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<NoWarn>$(NoWarn);SA0001</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Roslynator.Analyzers" Version="5.0.0" PrivateAssets="all" />
<PackageReference Include="Roslynator.Formatting.Analyzers" Version="5.0.0" PrivateAssets="all" />
<PackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="5.0.0" PrivateAssets="all" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.32.0.713" PrivateAssets="all" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" PrivateAssets="all" /> <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556" PrivateAssets="all" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\stylecop.json" Link="stylecop.json" Visible="false" /> <AdditionalFiles Include="$(MSBuildThisFileDirectory)/stylecop.json" Link="stylecop.json" Visible="false" />
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.7.0.110445">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup> </ItemGroup>
<PropertyGroup> </Project>
<CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)\stylecop.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
</Project>
+29
View File
@@ -0,0 +1,29 @@
<assembly name="0Harmony">
<member name="T:HarmonyLib.HarmonyPatch">
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor(JetBrains.Annotations.ImplicitUseTargetFlags)">
<argument>3</argument>
</attribute>
</member>
<member name="T:HarmonyLib.HarmonyPrefix">
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
</member>
<member name="T:HarmonyLib.HarmonyPostfix">
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
</member>
<member name="T:HarmonyLib.HarmonyTranspiler">
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
</member>
<member name="T:HarmonyLib.HarmonyFinalizer">
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
</member>
<member name="T:HarmonyLib.HarmonyPrepare">
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
</member>
<member name="T:HarmonyLib.HarmonyTargetMethod">
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
</member>
<member name="T:HarmonyLib.HarmonyTargetMethods">
<attribute ctor="M:JetBrains.Annotations.MeansImplicitUseAttribute.#ctor" />
</member>
</assembly>
@@ -1,31 +0,0 @@
using System;
using BepInEx;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using MiraAPI.PluginLoading;
using Reactor;
using Reactor.Networking;
using Reactor.Networking.Attributes;
namespace MiraAPI.Example.Extension;
[BepInAutoPlugin("mira.example.extension", "MiraExampleExtensionMod")]
[BepInProcess("Among Us.exe")]
[BepInDependency(ReactorPlugin.Id)]
[BepInDependency(MiraApiPlugin.Id)]
[BepInDependency(ExamplePlugin.Id)]
[ReactorModFlags(ModFlags.RequireOnAllClients)]
public partial class ExampleExtensionPlugin : BasePlugin, IMiraExtension
{
public Harmony Harmony { get; } = new(Id);
public override void Load()
{
Harmony.PatchAll();
}
public Type GetBasePluginType()
{
return typeof(ExamplePlugin);
}
}
@@ -1,14 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Version>1.0.0</Version>
<Description>Example extension for Mira API</Description>
<Authors>Angxl, XtraCube</Authors>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MiraAPI\MiraAPI.csproj" />
<ProjectReference Include="..\MiraAPI.Example\MiraAPI.Example.csproj" />
</ItemGroup>
<Import Project="..\AmongUs.props" />
</Project>
@@ -1,16 +0,0 @@
using MiraAPI.Example.Extension.Options;
using MiraAPI.GameOptions;
using MiraAPI.Modifiers.Types;
namespace MiraAPI.Example.Extension.Modifiers;
public class ExtensionModifier : GameModifier
{
public override string ModifierName => "Extension Modifier";
public override string GetDescription() => "This is from the extension mod!";
public override int GetAssignmentChance() => (int)OptionGroupSingleton<ExtensionModifierOptions>.Instance.ModifierChance;
public override int GetAmountPerGame() => (int)OptionGroupSingleton<ExtensionModifierOptions>.Instance.ModifierLimit;
}
@@ -1,13 +0,0 @@
using MiraAPI.Example.Roles;
using MiraAPI.GameOptions;
using MiraAPI.GameOptions.Attributes;
namespace MiraAPI.Example.Extension.Options;
public class ExtendedFreezerOptions : AbstractOptionGroup<FreezerRole>
{
public override string GroupName => "Extended Freezer Role Options";
[ModdedNumberOption("Freeze Uses", 1, 5)]
public float FreezeUses { get; set; } = 1;
}
@@ -1,17 +0,0 @@
using MiraAPI.Example.Extension.Modifiers;
using MiraAPI.GameOptions;
using MiraAPI.GameOptions.Attributes;
using MiraAPI.Utilities;
namespace MiraAPI.Example.Extension.Options;
public class ExtensionModifierOptions : AbstractOptionGroup<ExtensionModifier>
{
public override string GroupName => "Extension Modifier Options";
[ModdedNumberOption("Modifier Chance", 0, 100, 10, MiraNumberSuffixes.Percent)]
public float ModifierChance { get; set; } = 100f;
[ModdedNumberOption("Modifier Limit", 0, 10)]
public float ModifierLimit { get; set; } = 0;
}
@@ -1,15 +0,0 @@
using HarmonyLib;
using MiraAPI.Example.Buttons.Freezer;
using MiraAPI.Example.Extension.Options;
using MiraAPI.GameOptions;
namespace MiraAPI.Example.Extension.Patches;
[HarmonyPatch(typeof(FreezeButton), nameof(FreezeButton.MaxUses), MethodType.Getter)]
public static class FreezeButtonPatch
{
public static void Postfix(ref int __result)
{
__result = (int)OptionGroupSingleton<ExtendedFreezerOptions>.Instance.FreezeUses;
}
}
+7
View File
@@ -0,0 +1,7 @@
[*.{cs,vb}]
# SA1602: Enumeration items should be documented.
dotnet_diagnostic.SA1602.severity = none
# SA1601: Partial elements should be documented
dotnet_diagnostic.SA1601.severity = none
@@ -3,6 +3,7 @@ using MiraAPI.Example.Options.Roles;
using MiraAPI.Example.Roles; using MiraAPI.Example.Roles;
using MiraAPI.GameOptions; using MiraAPI.GameOptions;
using MiraAPI.Hud; using MiraAPI.Hud;
using MiraAPI.Keybinds;
using MiraAPI.Modifiers; using MiraAPI.Modifiers;
using MiraAPI.Utilities; using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets; using MiraAPI.Utilities.Assets;
@@ -12,13 +13,13 @@ namespace MiraAPI.Example.Buttons.Freezer;
public class FreezeButton : CustomActionButton<PlayerControl> public class FreezeButton : CustomActionButton<PlayerControl>
{ {
public override string Name => "Freeze"; public override string Name => "button.freeze";
public override float Cooldown => OptionGroupSingleton<FreezerRoleSettings>.Instance.FreezeDuration; public override float Cooldown => OptionGroupSingleton<FreezerRoleSettings>.Instance.FreezeDuration;
public override bool PauseTimerInVent => true;
public override int MaxUses => 1;
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton; public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
public override MiraKeybind? Keybind => MiraGlobalKeybinds.PrimaryAbility;
protected override void OnClick() protected override void OnClick()
{ {
+6 -6
View File
@@ -1,5 +1,6 @@
using MiraAPI.Example.Modifiers; using MiraAPI.Example.Modifiers;
using MiraAPI.Hud; using MiraAPI.Hud;
using MiraAPI.Keybinds;
using MiraAPI.Modifiers; using MiraAPI.Modifiers;
using MiraAPI.Utilities.Assets; using MiraAPI.Utilities.Assets;
using UnityEngine; using UnityEngine;
@@ -8,13 +9,12 @@ namespace MiraAPI.Example.Buttons;
public class MeetingButton : CustomActionButton public class MeetingButton : CustomActionButton
{ {
public override string Name => "Call Meeting"; public override string Name => "button.callMeeting";
public override float Cooldown => 15; public override float Cooldown => 15;
public override int MaxUses => 3; public override int MaxUses => 3;
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton; public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
public override MiraKeybind? Keybind => MiraGlobalKeybinds.ModifierPrimaryAbility;
public override bool Enabled(RoleBehaviour? role) public override bool Enabled(RoleBehaviour? role)
{ {
@@ -28,10 +28,10 @@ public class MeetingButton : CustomActionButton
PlayerControl.LocalPlayer.NetTransform.Halt(); PlayerControl.LocalPlayer.NetTransform.Halt();
var minigame = Object.Instantiate(bt.MinigamePrefab, Camera.main!.transform, false); var minigame = Object.Instantiate(bt.MinigamePrefab, Camera.main!.transform, false);
var taskAdderGame = minigame as TaskAdderGame; var taskAdderGame = minigame.TryCast<TaskAdderGame>();
if (taskAdderGame != null) if (taskAdderGame)
{ {
taskAdderGame.SafePositionWorld = bt.SafePositionLocal + (Vector2)bt.transform.position; taskAdderGame!.SafePositionWorld = bt.SafePositionLocal + (Vector2)bt.transform.position;
} }
minigame.transform.localPosition = new Vector3(0f, 0f, -50f); minigame.transform.localPosition = new Vector3(0f, 0f, -50f);
@@ -1,19 +1,19 @@
using MiraAPI.Example.Extension.GameOver; using MiraAPI.Example.GameOver;
using MiraAPI.Example.Extension.Roles; using MiraAPI.Example.Roles;
using MiraAPI.GameEnd; using MiraAPI.GameEnd;
using MiraAPI.Hud; using MiraAPI.Hud;
using MiraAPI.Keybinds;
using MiraAPI.Utilities.Assets; using MiraAPI.Utilities.Assets;
using UnityEngine; using UnityEngine;
namespace MiraAPI.Example.Extension.Buttons; namespace MiraAPI.Example.Buttons;
public class NeutralKillerButton : CustomActionButton public class NeutralKillerButton : CustomActionButton
{ {
public override string Name => "Win Game"; public override string Name => "button.winGame";
public override float Cooldown => 0f; public override float Cooldown => 0f;
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton; public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
public override MiraKeybind Keybind => ExampleKeybinds.NeutralWinKeybind;
protected override void OnClick() protected override void OnClick()
{ {
@@ -3,6 +3,7 @@ using MiraAPI.Example.Options.Roles;
using MiraAPI.Example.Roles; using MiraAPI.Example.Roles;
using MiraAPI.GameOptions; using MiraAPI.GameOptions;
using MiraAPI.Hud; using MiraAPI.Hud;
using MiraAPI.Keybinds;
using MiraAPI.Utilities.Assets; using MiraAPI.Utilities.Assets;
using Reactor.Utilities; using Reactor.Utilities;
using UnityEngine; using UnityEngine;
@@ -11,7 +12,7 @@ namespace MiraAPI.Example.Buttons.Teleporter;
public class TeleportButton : CustomActionButton public class TeleportButton : CustomActionButton
{ {
public override string Name => "Teleport"; public override string Name => "button.teleport";
public override float Cooldown => OptionGroupSingleton<TeleporterOptions>.Instance.TeleportCooldown.Value; public override float Cooldown => OptionGroupSingleton<TeleporterOptions>.Instance.TeleportCooldown.Value;
@@ -21,6 +22,7 @@ public class TeleportButton : CustomActionButton
public override LoadableAsset<Sprite> Sprite => ExampleAssets.TeleportButton; public override LoadableAsset<Sprite> Sprite => ExampleAssets.TeleportButton;
public override Color TextOutlineColor => new Color32(221, 176, 152, 255); public override Color TextOutlineColor => new Color32(221, 176, 152, 255);
public static bool IsZoom { get; private set; } public static bool IsZoom { get; private set; }
public override MiraKeybind? Keybind => MiraGlobalKeybinds.PrimaryAbility;
public override bool Enabled(RoleBehaviour? role) public override bool Enabled(RoleBehaviour? role)
{ {
@@ -59,11 +61,14 @@ public class TeleportButton : CustomActionButton
{ {
Camera.main.orthographicSize = MeetingHud.Instance ? 3f : ft; Camera.main.orthographicSize = MeetingHud.Instance ? 3f : ft;
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen); ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
foreach (var cam in Camera.allCameras) cam.orthographicSize = Camera.main.orthographicSize; foreach (var cam in Camera.allCameras)
cam.orthographicSize = Camera.main.orthographicSize;
yield return null; yield return null;
} }
foreach (var cam in Camera.allCameras) cam.orthographicSize = zoomDistance; foreach (var cam in Camera.allCameras)
cam.orthographicSize = zoomDistance;
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen); ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
} }
@@ -73,12 +78,14 @@ public class TeleportButton : CustomActionButton
{ {
Camera.main.orthographicSize = MeetingHud.Instance ? 3f : ft; Camera.main.orthographicSize = MeetingHud.Instance ? 3f : ft;
ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen); ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height, Screen.width, Screen.height, Screen.fullScreen);
foreach (var cam in Camera.allCameras) cam.orthographicSize = Camera.main.orthographicSize; foreach (var cam in Camera.allCameras)
cam.orthographicSize = Camera.main.orthographicSize;
yield return null; yield return null;
} }
foreach (var cam in Camera.allCameras) cam.orthographicSize = 3f; foreach (var cam in Camera.allCameras)
cam.orthographicSize = 3f;
HudManager.Instance.ShadowQuad.gameObject.SetActive(true); HudManager.Instance.ShadowQuad.gameObject.SetActive(true);
IsZoom = false; IsZoom = false;
+38
View File
@@ -0,0 +1,38 @@
using MiraAPI.Hud;
using MiraAPI.Keybinds;
using MiraAPI.Translation;
using MiraAPI.Utilities.Assets;
using UnityEngine;
namespace MiraAPI.Example.Buttons;
public class ThinkButton : CustomActionButton
{
public override string Name => "button.think";
public override float Cooldown => 15f;
public override float EffectDuration => 10f;
public override int MaxUses => 1;
public override ButtonUsesMode UsesMode => ButtonUsesMode.PerRound;
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
public override MiraKeybind Keybind => MiraGlobalKeybinds.SecondaryAbility;
protected override void OnClick()
{
Button!.OverrideText("button.think.thinking".Translate());
}
public override void OnEffectEnd()
{
Button!.OverrideText("button.think".Translate());
}
public override bool IsEffectCancellable()
{
return true;
}
public override bool Enabled(RoleBehaviour? role)
{
return role != null && role.IsImpostor;
}
}
+1
View File
@@ -9,5 +9,6 @@ public static class ExampleAssets
// Credit to EpicHorrors for the teleport button asset. // Credit to EpicHorrors for the teleport button asset.
public static LoadableResourceAsset TeleportButton { get; } = new("MiraAPI.Example.Resources.TeleportButton.png"); public static LoadableResourceAsset TeleportButton { get; } = new("MiraAPI.Example.Resources.TeleportButton.png");
public static LoadableResourceAsset SharpshootButton { get; } = new("MiraAPI.Example.Resources.SharpshootButton.png");
public static LoadableResourceAsset Banner { get; } = new("MiraAPI.Example.Resources.FortniteBanner.jpeg"); public static LoadableResourceAsset Banner { get; } = new("MiraAPI.Example.Resources.FortniteBanner.jpeg");
} }
+10 -3
View File
@@ -1,4 +1,6 @@
using MiraAPI.Colors; using MiraAPI.Colors;
using MiraAPI.Colors.ColorSpaces;
using MiraAPI.Utilities;
using UnityEngine; using UnityEngine;
namespace MiraAPI.Example; namespace MiraAPI.Example;
@@ -6,12 +8,17 @@ namespace MiraAPI.Example;
[RegisterCustomColors] [RegisterCustomColors]
public static class ExampleColors public static class ExampleColors
{ {
public static CustomColor Cerulean { get; } = new("Cerulean", new Color(0.0f, 0.48f, 0.65f)) public static CustomColor Cerulean { get; } = new("color.cerulean", new Color(0.0f, 0.48f, 0.65f))
{ {
ColorBrightness = CustomColorBrightness.Lighter, ColorBrightness = CustomColorBrightness.Lighter,
}; };
public static CustomColor Rose { get; } = new("Rose", new Color(0.98f, 0.26f, 0.62f)); public static CustomColor Rose { get; } = new("color.rose", new Color(0.98f, 0.26f, 0.62f));
public static CustomColor Gold { get; } = new("Gold", new Color(1.0f, 0.84f, 0.0f)); public static CustomColor Gold { get; } = new("color.gold", new Color(1.0f, 0.84f, 0.0f));
public static VariableColor Rainbow { get; } = new("color.rainbow", t => new HsbColor(MathUtilities.PingPong(t, 1f, 0.3f), 1f, 1f))
{
ColorBrightness = CustomColorBrightness.Lighter,
};
} }
+19 -3
View File
@@ -1,4 +1,5 @@
using System.Linq; using System.Globalization;
using System.Linq;
using MiraAPI.Events; using MiraAPI.Events;
using MiraAPI.Events.Mira; using MiraAPI.Events.Mira;
using MiraAPI.Events.Vanilla.Gameplay; using MiraAPI.Events.Vanilla.Gameplay;
@@ -17,7 +18,7 @@ public static class ExampleEventHandlers
{ {
public static void Initialize() public static void Initialize()
{ {
// You can register event handlers with the MiraEventManager class. // You can register event handlers with the MiraEventManager class
var handle = MiraEventManager.RegisterEventHandler<BeforeMurderEvent>(@event => var handle = MiraEventManager.RegisterEventHandler<BeforeMurderEvent>(@event =>
{ {
Logger<ExamplePlugin>.Info($"{@event.Source.Data.PlayerName} is about to kill {@event.Target.Data.PlayerName}"); Logger<ExamplePlugin>.Info($"{@event.Source.Data.PlayerName} is about to kill {@event.Target.Data.PlayerName}");
@@ -37,6 +38,21 @@ public static class ExampleEventHandlers
MiraEventManager.UnregisterEventHandler(handle); MiraEventManager.UnregisterEventHandler(handle);
} }
// If you want to check vanilla buttons, use something like this!
[RegisterEvent]
public static void VanillaButtonClickHandler(VanillaButtonClickEvent @event)
{
Logger<ExamplePlugin>.Info($"{@event.Button.buttonLabelText.text} is being used!");
if (@event.PlayerTarget != null)
{
Logger<ExamplePlugin>.Info($"{@event.PlayerTarget.Data.PlayerName} is being targeted!");
}
else if (@event.VentTarget != null)
{
Logger<ExamplePlugin>.Info($"Vent with id {@event.VentTarget.Id.ToString(CultureInfo.InvariantCulture)} is being targeted!");
}
}
// If you want to add extra votes to a player, do something like this. // If you want to add extra votes to a player, do something like this.
[RegisterEvent] [RegisterEvent]
public static void StartMeetingEvent(StartMeetingEvent _) public static void StartMeetingEvent(StartMeetingEvent _)
@@ -51,7 +67,7 @@ public static class ExampleEventHandlers
[RegisterEvent(15)] [RegisterEvent(15)]
public static void HandleVoteEvent(HandleVoteEvent @event) public static void HandleVoteEvent(HandleVoteEvent @event)
{ {
if (@event.VoteData.Owner.Data.Role is not FreezerRole) return; if (@event.VoteData.Owner.Data.Role is not NeutralKillerRole) return;
@event.VoteData.SetRemainingVotes(0); @event.VoteData.SetRemainingVotes(0);
+10
View File
@@ -0,0 +1,10 @@
using MiraAPI.Keybinds;
using Rewired;
namespace MiraAPI.Example;
[RegisterCustomKeybinds]
public static class ExampleKeybinds
{
public static MiraKeybind NeutralWinKeybind { get; } = new("Neutral Win", KeyboardKeyCode.C, ControllerButton.RightStick, [ModifierKey.Shift]);
}
+53
View File
@@ -0,0 +1,53 @@
using BepInEx.Configuration;
using MiraAPI.LocalSettings;
using MiraAPI.LocalSettings.Attributes;
using MiraAPI.Utilities;
using UnityEngine;
namespace MiraAPI.Example;
public class ExampleLocalSettings(ConfigFile config) : LocalSettingsTab(config)
{
public override string TabName => "settings.miraExample";
protected override bool ShouldCreateLabels => false;
public override LocalSettingTabAppearance TabAppearance => new()
{
ToggleActiveColor = Color.blue,
ToggleInactiveColor = Color.red,
};
[LocalSettingsButton]
public LocalSettingsButton ExampleButton { get; private set; } = new("settings.miraExample.button.exampleButton", OnExampleButtonClick);
[LocalToggleSetting]
public ConfigEntry<bool> ExampleToggle { get; private set; } = config.Bind("General", "Example Bool", true);
[LocalToggleSetting]
public ConfigEntry<bool> ExampleToggle2 { get; private set; } = config.Bind("General", "Example Bool 2", false);
[LocalSliderSetting(suffixType: MiraNumberSuffixes.Percent, formatString: "0", roundValue: true)]
public ConfigEntry<float> ExampleSlider { get; private set; } = config.Bind("General", "Slider", 50f);
[LocalNumberSetting]
public ConfigEntry<float> ExampleNumber { get; private set; } = config.Bind("General", "Example Number", 4f);
[LocalNumberSetting(min: 0.1f, max: 2.5f, increment: 0.1f, formatString: "0.0", suffixType: MiraNumberSuffixes.Multiplier)]
public ConfigEntry<float> ExampleFloatNumber { get; private set; } = config.Bind("General", "Example Multiplier", 1f);
[LocalEnumSetting]
public ConfigEntry<ExampleEnumSetting> ExampleEnum { get; private set; } = config.Bind("General", "Example Enum", ExampleEnumSetting.Fries);
private static void OnExampleButtonClick()
{
LocalSettingsTabSingleton<MiraApiSettings>.Instance.Open();
}
}
public enum ExampleEnumSetting
{
Cheeseburger,
Sandwich,
Fries,
ChickenNuggets,
}
+14 -2
View File
@@ -3,6 +3,7 @@ using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP; using BepInEx.Unity.IL2CPP;
using HarmonyLib; using HarmonyLib;
using MiraAPI.PluginLoading; using MiraAPI.PluginLoading;
using MiraAPI.Translation;
using Reactor; using Reactor;
using Reactor.Networking; using Reactor.Networking;
using Reactor.Networking.Attributes; using Reactor.Networking.Attributes;
@@ -16,9 +17,20 @@ namespace MiraAPI.Example;
[ReactorModFlags(ModFlags.RequireOnAllClients)] [ReactorModFlags(ModFlags.RequireOnAllClients)]
public partial class ExamplePlugin : BasePlugin, IMiraPlugin public partial class ExamplePlugin : BasePlugin, IMiraPlugin
{ {
public ExamplePlugin()
{
MiraLocaleManager.Register("mira.example");
}
public Harmony Harmony { get; } = new(Id); public Harmony Harmony { get; } = new(Id);
public string OptionsTitleText => "Mira API\nExample Mod"; public string OptionsTitleText { get; } = "Mira API\nExample Mod";
public ConfigFile GetConfigFile() => Config; public string CustomOptionMenuNameTwo { get; } = "Example Options";
public ConfigFile GetConfigFile()
{
return Config;
}
public override void Load() public override void Load()
{ {
ExampleEventHandlers.Initialize(); ExampleEventHandlers.Initialize();
+13
View File
@@ -0,0 +1,13 @@
using MiraAPI.GameModes;
using MiraAPI.Utilities.Assets;
using UnityEngine;
namespace MiraAPI.Example.GameModes;
public class ExampleMode : AbstractGameMode
{
public override string Name => "Example Mode";
public override string Description => "An example gamemode.";
public override LoadableAsset<Sprite>? Icon => ExampleAssets.ExampleButton;
public override Color Color => Color.red;
}
@@ -1,9 +1,10 @@
using MiraAPI.Example.Extension.Roles; using MiraAPI.Example.Roles;
using MiraAPI.GameEnd; using MiraAPI.GameEnd;
using MiraAPI.Translation;
using MiraAPI.Utilities; using MiraAPI.Utilities;
using UnityEngine; using UnityEngine;
namespace MiraAPI.Example.Extension.GameOver; namespace MiraAPI.Example.GameOver;
public class NeutralKillerGameOver : CustomGameOver public class NeutralKillerGameOver : CustomGameOver
{ {
@@ -14,7 +15,7 @@ public class NeutralKillerGameOver : CustomGameOver
public override void AfterEndGameSetup(EndGameManager endGameManager) public override void AfterEndGameSetup(EndGameManager endGameManager)
{ {
endGameManager.WinText.text = "Outcast Killer Wins!"; endGameManager.WinText.text = "gameover.outcastKiller.win".Translate();
endGameManager.WinText.color = Color.magenta; endGameManager.WinText.color = Color.magenta;
endGameManager.BackgroundBar.material.SetColor(ShaderID.Color, Color.magenta); endGameManager.BackgroundBar.material.SetColor(ShaderID.Color, Color.magenta);
} }
@@ -0,0 +1,29 @@
using MiraAPI.Example.Roles;
using MiraAPI.MeetingAbilities;
using MiraAPI.Utilities.Assets;
using UnityEngine;
namespace MiraAPI.Example.MeetingAbilities;
public class EndMeetingButton : MeetingActionButton
{
public override string Name => "End Meeting";
public override float Cooldown => 15;
public override float InitialCooldown => 30;
public override int MaxUses => 3;
public override LoadableAsset<Sprite> Sprite => ExampleAssets.ExampleButton;
public override bool Enabled(RoleBehaviour? role)
{
return PlayerControl.LocalPlayer != null && role is MayorRole;
}
protected override void OnClick()
{
MeetingHud.Instance.RpcClose();
}
}
@@ -0,0 +1,37 @@
using MiraAPI.MeetingAbilities;
using MiraAPI.Networking;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using UnityEngine;
namespace MiraAPI.Example.MeetingAbilities;
public class ShootButton : TargetedMeetingButton
{
public override string Name => "Shoot";
public override int MaxUses => 3;
public override float InitialCooldown => 5;
public override float Cooldown => 3;
public override LoadableAsset<Sprite> Sprite => ExampleAssets.SharpshootButton;
public override Color OutlineColor => Color.red;
public override bool Enabled(RoleBehaviour r)
{
return r.IsImpostor;
}
protected override void OnClick(PlayerVoteArea playerVoteArea)
{
playerVoteArea.SetDisabled();
var player = playerVoteArea.GetPlayer();
if (player != null)
{
PlayerControl.LocalPlayer.RpcCustomMurder(player);
}
}
}
@@ -0,0 +1,54 @@
using MiraAPI.MeetingAbilities;
using MiraAPI.Networking;
using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
using UnityEngine;
namespace MiraAPI.Example.MeetingAbilities;
public class ShotgunButton : MultiTargetMeetingButton
{
public override string Name => "Shotgun";
public override int MaxUses => 3;
public override float InitialCooldown => 5;
public override float Cooldown => 3;
public override LoadableAsset<Sprite> Sprite => ExampleAssets.SharpshootButton;
public override Color OutlineColor => Color.red;
public override bool Enabled(RoleBehaviour r)
{
return r.IsImpostor;
}
protected override void OnClick(PlayerVoteArea playerVoteArea)
{
// Emptu because it only triggers the actual kills once all meeting abilities have been used.
}
public override LoadableAsset<Sprite> SpriteActive => ExampleAssets.CallMeetingButton;
public override int TargetsCount => 4;
protected override void OnSelect(PlayerVoteArea playerVoteArea, bool toggle)
{
HudManager.Instance.PlayerCam.ShakeScreen(0.5f, 2);
}
public override void OnFinish()
{
foreach (var playerVoteArea in Targets.Keys)
{
playerVoteArea.SetDisabled();
var player = playerVoteArea.GetPlayer();
if (player != null)
{
PlayerControl.LocalPlayer.RpcCustomMurder(player);
}
}
}
}
+7 -6
View File
@@ -1,17 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<Version>1.0.0</Version> <Version>1.0.0</Version>
<Description>Example mod for Mira API</Description> <Description>Example mod for Mira API</Description>
<Authors>Angxl, XtraCube</Authors> <Authors>Author Name</Authors>
<NoWarn>$(NoWarn);EnableGenerateDocumentationFile</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\MiraAPI\MiraAPI.csproj" /> <ProjectReference Include="..\MiraAPI\MiraAPI.csproj" /> <!-- You typically would use the nuget package here: AllOfUs.MiraAPI -->
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Resources\**\*.*" /> <EmbeddedResource Include="Resources\**\*.*" />
</ItemGroup> </ItemGroup>
<Import Project="..\AmongUs.props" /> <Import Project="..\AmongUs.props" />
</Project> </Project>
+3 -2
View File
@@ -2,6 +2,7 @@
using MiraAPI.GameOptions; using MiraAPI.GameOptions;
using MiraAPI.Modifiers; using MiraAPI.Modifiers;
using MiraAPI.Modifiers.Types; using MiraAPI.Modifiers.Types;
using MiraAPI.Translation;
using MiraAPI.Utilities.Assets; using MiraAPI.Utilities.Assets;
using UnityEngine; using UnityEngine;
@@ -9,7 +10,7 @@ namespace MiraAPI.Example.Modifiers;
public class CaptainModifier : GameModifier public class CaptainModifier : GameModifier
{ {
public override string ModifierName => "Captain"; public override string ModifierName => MiraLocaleManager.Get("modifier.captain");
public override LoadableAsset<Sprite>? ModifierIcon => ExampleAssets.CallMeetingButton; public override LoadableAsset<Sprite>? ModifierIcon => ExampleAssets.CallMeetingButton;
public override void OnDeath(DeathReason reason) public override void OnDeath(DeathReason reason)
@@ -19,7 +20,7 @@ public class CaptainModifier : GameModifier
public override string GetDescription() public override string GetDescription()
{ {
return $"You can call a meeting from anywhere on the map."; return MiraLocaleManager.Get("modifier.captain.TabDescription");
} }
public override int GetAssignmentChance() public override int GetAssignmentChance()
@@ -1,13 +1,13 @@
using Il2CppSystem; using MiraAPI.Example.Roles;
using MiraAPI.Example.Roles;
using MiraAPI.Modifiers.Types; using MiraAPI.Modifiers.Types;
using MiraAPI.Translation;
using UnityEngine; using UnityEngine;
namespace MiraAPI.Example.Modifiers.Freezer; namespace MiraAPI.Example.Modifiers.Freezer;
public class FreezeModifier : TimedModifier public class FreezeModifier : TimedModifier
{ {
public override string ModifierName => "Freezed"; public override string ModifierName => MiraLocaleManager.Get("modifier.freezed");
public override bool HideOnUi => false; public override bool HideOnUi => false;
public override float Duration => 15f; public override float Duration => 15f;
public override bool AutoStart => true; public override bool AutoStart => true;
@@ -27,7 +27,7 @@ public class FreezeModifier : TimedModifier
if (Player.AmOwner || PlayerControl.LocalPlayer.Data.Role is FreezerRole) if (Player.AmOwner || PlayerControl.LocalPlayer.Data.Role is FreezerRole)
{ {
Player.cosmetics.SetOutline(true, new Nullable<Color>(Palette.LightBlue)); Player.cosmetics.SetOutline(true, new Il2CppSystem.Nullable<Color>(Palette.LightBlue));
} }
} }
@@ -1,14 +1,15 @@
using MiraAPI.Modifiers.Types; using MiraAPI.Modifiers.Types;
using MiraAPI.Translation;
namespace MiraAPI.Example.Modifiers; namespace MiraAPI.Example.Modifiers;
public class HighPriorityModifier : GameModifier public class HighPriorityModifier : GameModifier
{ {
public override string ModifierName => "High Priority"; public override string ModifierName => MiraLocaleManager.Get("modifier.highPriority");
public override string GetDescription() public override string GetDescription()
{ {
return "You are high priority! Idrk what this means either tbh..."; return MiraLocaleManager.Get("modifier.highPriority.TabDescription");
} }
public override int GetAssignmentChance() public override int GetAssignmentChance()
+66 -9
View File
@@ -1,31 +1,88 @@
using MiraAPI.GameOptions; using System.Diagnostics.CodeAnalysis;
using MiraAPI.GameOptions;
using MiraAPI.GameOptions.Attributes; using MiraAPI.GameOptions.Attributes;
using MiraAPI.Utilities; using MiraAPI.Utilities;
using UnityEngine; using UnityEngine;
namespace MiraAPI.Example.Options; namespace MiraAPI.Example.Options;
[SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Demo.")]
[SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Read above.")]
[SuppressMessage("Minor Code Smell", "S3400:Methods should not return constants", Justification = "Read above.")]
public class ExampleOptions : AbstractOptionGroup public class ExampleOptions : AbstractOptionGroup
{ {
public override string GroupName => "Example Options 1"; public override string GroupName => "options.exampleOptions1";
public override Color GroupColor => Color.green; public override Color GroupColor => Color.green;
public override bool ShowInMatchInfoGuide => true;
[ModdedToggleOption("Toggle Opt 1")] [ModdedToggleOption("options.exampleOptions1.toggleOpt1")]
public bool ToggleOpt { get; set; } = false; [ModdedOptionVisibility] // Automatically resolves to using ToggleOpt1Visibility, can also target toggle options
public bool ToggleOpt1 { get; set; } = false;
[ModdedToggleOption("Toggle Opt 2")] [ModdedToggleOption("options.exampleOptions1.toggleOpt2")]
[ModdedOptionVisibility(nameof(ToggleOpt1))] // ToggleOpt2 will be visible only when ToggleOpt1 is true
public bool ToggleOpt2 { get; set; } = true; public bool ToggleOpt2 { get; set; } = true;
[ModdedNumberOption("Number Opt", min: 0, max: 10, increment: .25f, formatString: "0.00", suffixType: MiraNumberSuffixes.Percent)] [ModdedNumberOption("options.exampleOptions1.numberOpt", min: 0, max: 10, increment: .25f, formatString: "0.00", suffixType: MiraNumberSuffixes.Percent)]
[ModdedOptionVisibility(nameof(NumberOptVisibility))] // Can also target static methods
public float NumberOpt { get; set; } = 4f; public float NumberOpt { get; set; } = 4f;
[ModdedEnumOption("Best API", typeof(BestApi), ["Mira API", "Mitochondria", "Reactor"])] [ModdedNumberOption("options.exampleOptions1.numberOpt", min: 0, max: 10, suffixType: MiraNumberSuffixes.Distance)]
public BestApi Opt { get; set; } = BestApi.MiraAPI; public int NumberOpt2 { get; set; } = 4; // Can also be int!
[ModdedEnumOption("options.exampleOptions1.bestApi", typeof(Api), ["Mira API", "Mitochondria", "Reactor"])]
public Api BestApi { get; set; } = Api.MiraAPI;
[ModdedEnumOption<Api>("options.exampleOptions1.worstApi", ["Mira API", "Mitochondria", "Reactor"])]
// These three can target both instance and static methods
[ModdedOptionGetter(nameof(GetApi))] // Can also automatically resolve to {Option Name}Getter
[ModdedOptionSetter(nameof(SetApi))] // Can also automatically resolve to {Option Name}Setter
[ModdedOptionChanged(nameof(ApiChanged))] // Can also automatically resolve to {Option Name}Changed
public Api WorstApi { get; set; } = Api.MiraAPI;
[ModdedEnumOptionList<ValueState>("Value State {0}", ["None", "Primary", "Secondary"])]
public ModdedArray<ValueState> ValueStates { get; set; } = [ValueState.Primary, ValueState.Secondary, ValueState.None, ValueState.None, ValueState.None];
[ModdedPlayerOption("options.exampleOptions1.players")]
public NetworkedPlayerInfo PlayerSelected { get; set; }
public bool ToggleOpt1Visibility()
{
return true;
}
public static bool NumberOptVisibility()
{
return true;
}
public static Api GetApi(Api currentValue)
{
return currentValue;
}
public static Api SetApi(Api newValue, Api oldValue)
{
return default;
}
public static void ApiChanged(Api currentValue)
{
// Something
}
} }
public enum BestApi public enum Api
{ {
MiraAPI, MiraAPI,
Mitochondria, Mitochondria,
Reactor, Reactor,
} }
public enum ValueState
{
None,
Primary,
Secondary,
}
+13 -7
View File
@@ -6,22 +6,28 @@ namespace MiraAPI.Example.Options;
public class ExampleOptions2 : AbstractOptionGroup public class ExampleOptions2 : AbstractOptionGroup
{ {
public override string GroupName => "Example Options 2"; public override string GroupName => "options.exampleOptions2";
public override uint GroupPriority => 0; // This group will be displayed first. The default value is uint.MaxValue. public override uint GroupPriority => 0; // This group will be displayed first. The default value is uint.MaxValue.
public override MenuCategory ParentMenu => MenuCategory.CustomTwo;
public override bool ShowInMatchInfoGuide => true;
public ModdedPlayerOption PlayerOption2 { get; } = new("YOU MUST CHOSE A PLAYER", false); public ModdedPlayerOption PlayerOption2 { get; } = new("options.exampleOptions2.youMustChoseAPlayer", false);
public ModdedPlayerOption PlayerOption { get; } = new("Eh whatever"); public ModdedPlayerOption PlayerOption { get; } = new("options.exampleOptions2.ehWhatever");
public ModdedToggleOption ToggleOpt1 { get; } = new("Toggle Option 1", false); public ModdedToggleOption ToggleOpt1 { get; } = new("options.exampleOptions2.toggleOption1", false);
public ModdedToggleOption ToggleOpt2 { get; } = new("Toggle Option 2", false) public ModdedOptionList<ModdedNumberOption> PlayerNums { get; } = new(5, i =>
new($"PlayerNum{i}", 2, 0, 5, 1, Utilities.MiraNumberSuffixes.None));
public ModdedToggleOption ToggleOpt2 { get; } = new("options.exampleOptions2.toggleOption2", false)
{ {
Visible = () => OptionGroupSingleton<ExampleOptions2>.Instance.ToggleOpt1, // implicit cast from ModdedToggleOption to bool Visible = () => OptionGroupSingleton<ExampleOptions2>.Instance.ToggleOpt1, // implicit cast from ModdedToggleOption to bool
}; };
public ModdedEnumOption<TestingData> EnumOpt { get; } = new("Enum Opt", 0) public ModdedEnumOption<TestingData> EnumOpt { get; } = new("options.exampleOptions2.enumOpt", 0)
{ {
ChangedEvent = x => Logger<ExamplePlugin>.Info($"changed Enum Opt to {x}"), ChangedEvent = x => Logger<ExamplePlugin>.Info($"changed Enum Opt to {x}"),
Getter = currentValue => currentValue,
Setter = (newValue, oldValue) => newValue,
}; };
} }
@@ -6,14 +6,14 @@ namespace MiraAPI.Example.Options.Modifiers;
public class CaptainModifierSettings : AbstractOptionGroup<CaptainModifier> public class CaptainModifierSettings : AbstractOptionGroup<CaptainModifier>
{ {
public override string GroupName => "Captain Settings"; public override string GroupName => "options.captainSettings";
[ModdedNumberOption("Amount", 0, 5)] [ModdedNumberOption("options.captainSettings.amount", 0, 5)]
public float Amount { get; set; } = 1; public float Amount { get; set; } = 1;
[ModdedNumberOption("Chance", 0, 100, 10)] [ModdedNumberOption("options.captainSettings.chance", 0, 100, 10)]
public float Chance { get; set; } = 50; public float Chance { get; set; } = 50;
[ModdedNumberOption("Uses", 1, 5)] [ModdedNumberOption("options.captainSettings.uses", 1, 5)]
public float NumUses { get; set; } = 3; public float NumUses { get; set; } = 3;
} }
@@ -6,8 +6,8 @@ namespace MiraAPI.Example.Options.Modifiers;
public class FreezeModifierSettings : AbstractOptionGroup<FreezeModifier> public class FreezeModifierSettings : AbstractOptionGroup<FreezeModifier>
{ {
public override string GroupName => "Freeze"; public override string GroupName => "options.freezeModifierSettings";
[ModdedToggleOption("Use Color")] [ModdedToggleOption("options.freezeModifierSettings.useColor")]
public bool UseColor { get; set; } = true; public bool UseColor { get; set; } = true;
} }
@@ -5,15 +5,13 @@ namespace MiraAPI.Example.Options.Modifiers;
public class GeneralModifierOptions : AbstractOptionGroup public class GeneralModifierOptions : AbstractOptionGroup
{ {
public override string GroupName => "General"; public override string GroupName => "options.generalModifier";
public override uint GroupPriority => 0; public override uint GroupPriority => 0;
public override MenuCategory ParentMenu => MenuCategory.Modifiers;
public override bool ShowInModifiersMenu => true; [ModdedToggleOption("options.generalModifier.someBooleanOption")]
[ModdedToggleOption("Some Boolean Option")]
public bool SomeBooleanOption { get; set; } = true; public bool SomeBooleanOption { get; set; } = true;
[ModdedNumberOption("Number Option", 0, 10, 1)] [ModdedNumberOption("options.generalModifier.numberOption", 0, 10)]
public float NumberOption { get; set; } = 5; public float NumberOption { get; set; } = 5;
} }
@@ -2,13 +2,22 @@
using MiraAPI.GameOptions; using MiraAPI.GameOptions;
using MiraAPI.GameOptions.Attributes; using MiraAPI.GameOptions.Attributes;
using MiraAPI.Utilities; using MiraAPI.Utilities;
using MiraAPI.Utilities.Assets;
namespace MiraAPI.Example.Options.Roles; namespace MiraAPI.Example.Options.Roles;
public class FreezerRoleSettings : AbstractOptionGroup<FreezerRole> public class FreezerRoleSettings : AbstractOptionGroup<FreezerRole>
{ {
public override string GroupName => "Custom Role"; public override OptionNotifConfiguration Configuration => new(
Palette.Blue,
TmpSpriteUtils.CreateSpriteAsset(
MiraAssets.ImpostorFile.LoadAsset(),
"ApiExample.Role.Impostor.FreezerRole"));
public override string GroupName => "ApiExample.Role.Freezer";
[ModdedNumberOption("Freeze Duration", 1, 15, 1, MiraNumberSuffixes.Seconds)] [ModdedNumberOption("ApiExample.Role.Freezer.Settings.FreezeDuration", 1, 15, 1, MiraNumberSuffixes.Seconds)]
public float FreezeDuration { get; set; } = 5; public float FreezeDuration { get; set; } = 5;
[ModdedNumberOption("ApiExample.Role.Freezer.Settings.FreezeUses", 1, 5)]
public float FreezeUses { get; set; } = 1;
} }
@@ -6,15 +6,15 @@ using MiraAPI.Utilities;
namespace MiraAPI.Example.Options.Roles; namespace MiraAPI.Example.Options.Roles;
public class TeleporterOptions : AbstractOptionGroup<TeleporterRole> public class TeleporterOptions : AbstractRoleOptionGroup<TeleporterRole>
{ {
public override string GroupName => "Teleporter"; public override string GroupName => "ApiExample.Role.Teleporter";
public ModdedNumberOption TeleportCooldown { get; set; } = new("Teleport Cooldown", 10, 5, 60, 2.5f, MiraNumberSuffixes.Seconds); public ModdedNumberOption TeleportCooldown { get; set; } = new("ApiExample.Role.Teleporter.Settings.TeleportCooldown", 10, 5, 60, 2.5f, MiraNumberSuffixes.Seconds);
[ModdedNumberOption("Teleport Duration", 5, 25, 1, MiraNumberSuffixes.Seconds)] [ModdedNumberOption("ApiExample.Role.Teleporter.Settings.TeleportDuration", 5, 25, 1, MiraNumberSuffixes.Seconds)]
public float TeleportDuration { get; set; } = 10; public float TeleportDuration { get; set; } = 10;
[ModdedNumberOption("Zoom Distance", 4, 15)] [ModdedNumberOption("ApiExample.Role.Teleporter.Settings.ZoomDistance", 4, 15)]
public float ZoomDistance { get; set; } = 6; public float ZoomDistance { get; set; } = 6;
} }
@@ -0,0 +1,86 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="ApiExample.Role.Crewmate.Teleporter">Teleporter</string>
<string name="ApiExample.Role.Crewmate.Teleporter.IntroBlurb">Zoom out and teleport across the map!</string>
<string name="ApiExample.Role.Crewmate.Teleporter.MedDescription">Zoom out and teleport across the map!</string>
<string name="ApiExample.Role.Crewmate.Teleporter.TabDescription">Zoom out and teleport across the map!</string>
<string name="ApiExample.Role.Crewmate.Teleporter.WikiDescription">The Teleporter is a Crewmate role that can move around the map using their dope-ass ability.</string>
<string name="ApiExample.Role.Impostor.Freezer">Freezer</string>
<string name="ApiExample.Role.Impostor.Freezer.IntroBlurb">Get iced, nerd.</string>
<string name="ApiExample.Role.Impostor.Freezer.MedDescription">Freeze others for a duration of time.</string>
<string name="ApiExample.Role.Impostor.Freezer.TabDescription">Freeze another player for a duration of time.</string>
<string name="ApiExample.Role.Impostor.Freezer.WikiDescription">The Freezer is an Impostor role that can freeze players. Or something along those lines.</string>
<string name="ApiExample.Role.Crewmate.Mayor">Mayor</string>
<string name="ApiExample.Role.Crewmate.Mayor.IntroBlurb">Democracy is the best policy.</string>
<string name="ApiExample.Role.Crewmate.Mayor.MedDescription">Vote out the Impostors with more votes.
Your votes have double the power.</string>
<string name="ApiExample.Role.Crewmate.Mayor.TabDescription">You get one extra vote in the meeting!</string>
<string name="ApiExample.Role.Crewmate.Mayor.WikiDescription">The Mayor is a Crewmate role that gets two votes in the meeting, instead of the singular vote other Crewmates get.</string>
<string name="ApiExample.Role.Crewmate.Chameleon">Chameleon</string>
<string name="ApiExample.Role.Crewmate.Chameleon.IntroBlurb">Become one with the environment.</string>
<string name="ApiExample.Role.Crewmate.Chameleon.MedDescription">Fade out of everyone's vision by not moving.</string>
<string name="ApiExample.Role.Crewmate.Chameleon.TabDescription">Stay invisible while not moving.</string>
<string name="ApiExample.Role.Crewmate.Chameleon.WikiDescription">The Chameleon is a Crewmate role that slowly becomes invisible while standing still.</string>
<string name="ApiExample.Role.Outcast.OutcastKiller">Outcast Killer</string>
<string name="ApiExample.Role.Outcast.OutcastKiller.IntroBlurb">Kill everyone else.</string>
<string name="ApiExample.Role.Outcast.OutcastKiller.MedDescription">Be the last outcast standing.
Eliminate every other faction.</string>
<string name="ApiExample.Role.Outcast.OutcastKiller.TabDescription">Outcast who can kill.</string>
<string name="ApiExample.Role.Outcast.OutcastKiller.WikiDescription">The Outcast Killer is an Outcast role that can kill, like some sort of neutral killer...</string>
<string name="outcast">Outcast</string>
<string name="outcast.group">Outcast Roles</string>
<string name="outcast.roleTitle">OUTCAST</string>
<string name="outcast.teamIntroDescription">You are an Outcast. You do not have a team.</string>
<string name="button.think">Think</string>
<string name="button.think.thinking">Thinking...</string>
<string name="button.freeze">Freeze</string>
<string name="button.teleport">Teleport</string>
<string name="button.callMeeting">Call Meeting</string>
<string name="button.winGame">Win Game</string>
<string name="modifier.captain">Captain</string>
<string name="modifier.captain.TabDescription">You can call a meeting from anywhere on the map.</string>
<string name="modifier.freezed">Freezed</string>
<string name="modifier.highPriority">High Priority</string>
<string name="modifier.highPriority.TabDescription">You are high priority! Idrk what this means either tbh...</string>
<string name="options.exampleOptions1">Example Options 1</string>
<string name="options.exampleOptions1.toggleOpt1">Toggle Opt 1</string>
<string name="options.exampleOptions1.toggleOpt2">Toggle Opt 2</string>
<string name="options.exampleOptions1.numberOpt">Number Opt</string>
<string name="options.exampleOptions1.bestApi">Best API</string>
<string name="options.exampleOptions1.worstApi">Worst API</string>
<string name="options.exampleOptions1.players">Choose A Player</string>
<string name="options.exampleOptions2">Example Options 2</string>
<string name="options.exampleOptions2.youMustChoseAPlayer">YOU MUST CHOSE A PLAYER</string>
<string name="options.exampleOptions2.ehWhatever">Eh whatever</string>
<string name="options.exampleOptions2.toggleOption1">Toggle Option 1</string>
<string name="options.exampleOptions2.toggleOption2">Toggle Option 2</string>
<string name="options.exampleOptions2.enumOpt">Enum Opt</string>
<string name="options.captainSettings">Captain Settings</string>
<string name="options.captainSettings.amount">Amount</string>
<string name="options.captainSettings.chance">Chance</string>
<string name="options.captainSettings.uses">Uses</string>
<string name="options.freezeModifierSettings">Freeze</string>
<string name="options.freezeModifierSettings.useColor">Use Color</string>
<string name="options.generalModifier">General</string>
<string name="options.generalModifier.someBooleanOption">Some Boolean Option</string>
<string name="options.generalModifier.numberOption">Number Option</string>
<string name="options.freezerRoleSettings">Custom Role</string>
<string name="ApiExample.Role.Freezer.Settings.FreezeDuration">Freeze Duration</string>
<string name="ApiExample.Role.Freezer.Settings.FreezeUses">Freeze Uses</string>
<string name="ApiExample.Role.Teleporter.Settings.TeleportCooldown">Teleport Cooldown</string>
<string name="ApiExample.Role.Teleporter.Settings.TeleportDuration">Teleport Duration</string>
<string name="ApiExample.Role.Teleporter.Settings.ZoomDistance">Zoom Distance</string>
<string name="settings.miraExample">Mira Example</string>
<string name="settings.miraExample.exampleBool">Example Bool</string>
<string name="settings.miraExample.exampleBool2">Example Bool 2</string>
<string name="settings.miraExample.slider">Slider</string>
<string name="settings.miraExample.exampleNumber">Example Number</string>
<string name="settings.miraExample.exampleMultiplier">Example Multiplier</string>
<string name="settings.miraExample.exampleEnum">Example Enum</string>
<string name="settings.miraExample.button.exampleButton">Example Button</string>
<string name="gameover.outcastKiller.win">Outcast Killer Wins!</string>
<string name="color.cerulean">Cerulean</string>
<string name="color.rose">Rose</string>
<string name="color.gold">Gold</string>
<string name="color.rainbow">Rainbow</string>
</resources>
@@ -0,0 +1,66 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="ApiExample.Role.Teleporter">传送者</string>
<string name="ApiExample.Role.Teleporter.IntroBlurb">缩小视野并在地图上传送!</string>
<string name="ApiExample.Role.Teleporter.MedDescription">缩小视野并在地图上传送!</string>
<string name="ApiExample.Role.Teleporter.TabDescription">缩小视野并在地图上传送!</string>
<string name="ApiExample.Role.Freezer">冰冻者</string>
<string name="ApiExample.Role.Freezer.TabDescription">将其他玩家冰冻一段时间。</string>
<string name="ApiExample.Role.Crewmate.Mayor">市长</string>
<string name="ApiExample.Role.Crewmate.Mayor.TabDescription">你拥有额外投票权!</string>
<string name="ApiExample.Role.Crewmate.Chamelon">变色龙</string>
<string name="ApiExample.Role.Crewmate.Chamelon.TabDescription">静止不动时保持隐身。</string>
<string name="ApiExample.Role.Outcast.OutcastKiller">流放杀手</string>
<string name="ApiExample.Role.Outcast.OutcastKiller.TabDescription">可以击杀的流放者。</string>
<string name="outcast">流放者</string>
<string name="outcast.roleTitle">流放者</string>
<string name="outcast.teamIntroDescription">你是流放者,你没有队伍。</string>
<string name="button.think">思考</string>
<string name="button.think.thinking">思考中...</string>
<string name="button.freeze">冰冻</string>
<string name="button.teleport">传送</string>
<string name="button.callMeeting">召集会议</string>
<string name="button.winGame">赢得游戏</string>
<string name="modifier.captain">队长</string>
<string name="modifier.captain.TabDescription">你可以在地图上任意位置召集会议。</string>
<string name="modifier.freezed">已被冰冻</string>
<string name="modifier.highPriority">高优先级</string>
<string name="modifier.highPriority.TabDescription">你是高优先级!老实说我也不太清楚这是什么意思……</string>
<string name="options.exampleOptions1">示例选项组 1</string>
<string name="options.exampleOptions1.toggleOpt1">开关选项 1</string>
<string name="options.exampleOptions1.toggleOpt2">开关选项 2</string>
<string name="options.exampleOptions1.numberOpt">数字选项</string>
<string name="options.exampleOptions1.bestApi">谁是最好的API</string>
<string name="options.exampleOptions2">示例选项组 2</string>
<string name="options.exampleOptions2.youMustChoseAPlayer">你必须选择一个玩家</string>
<string name="options.exampleOptions2.ehWhatever">咕咕嘎嘎</string>
<string name="options.exampleOptions2.toggleOption1">开关选项 1</string>
<string name="options.exampleOptions2.toggleOption2">开关选项 2</string>
<string name="options.exampleOptions2.enumOpt">枚举选项</string>
<string name="options.captainSettings">队长设置</string>
<string name="options.captainSettings.amount">数量</string>
<string name="options.captainSettings.chance">概率</string>
<string name="options.captainSettings.uses">使用次数</string>
<string name="options.freezeModifierSettings">冰冻</string>
<string name="options.freezeModifierSettings.useColor">使用颜色</string>
<string name="options.generalModifier">通用</string>
<string name="options.generalModifier.someBooleanOption">某个布尔选项</string>
<string name="options.generalModifier.numberOption">数字选项</string>
<string name="ApiExample.Role.Freezer.Settings.FreezeDuration">冰冻时长</string>
<string name="ApiExample.Role.Freezer.Settings.FreezeUses">冰冻次数</string>
<string name="ApiExample.Role.Teleporter.Settings.TeleportCooldown">传送冷却</string>
<string name="ApiExample.Role.Teleporter.Settings.TeleportDuration">传送持续时间</string>
<string name="ApiExample.Role.Teleporter.Settings.ZoomDistance">缩放距离</string>
<string name="settings.miraExample">Mira 示例插件</string>
<string name="settings.miraExample.exampleBool">示例布尔</string>
<string name="settings.miraExample.exampleBool2">示例布尔 2</string>
<string name="settings.miraExample.slider">滑块</string>
<string name="settings.miraExample.exampleNumber">示例数字</string>
<string name="settings.miraExample.exampleMultiplier">示例倍数</string>
<string name="settings.miraExample.exampleEnum">示例枚举</string>
<string name="settings.miraExample.button.exampleButton">示例按钮</string>
<string name="gameover.outcastKiller.win">流放杀手获胜!</string>
<string name="color.cerulean">天蓝</string>
<string name="color.rose">玫瑰红</string>
<string name="color.gold">金色</string>
</resources>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

+26 -16
View File
@@ -1,38 +1,41 @@
using AmongUs.GameOptions; using AmongUs.GameOptions;
using MiraAPI.Patches.Stubs; using MiraAPI.Patches.Stubs;
using MiraAPI.Roles; using MiraAPI.Roles;
using MiraAPI.Utilities.Assets;
using Reactor.Utilities; using Reactor.Utilities;
using TMPro;
using UnityEngine; using UnityEngine;
namespace MiraAPI.Example.Roles; namespace MiraAPI.Example.Roles;
public class ChameloenRole : CrewmateRole, ICustomRole public class ChameleonRole : CrewmateRole, ICustomRole
{ {
public string RoleName => "Chamelon"; private bool shouldHide;
public string RoleLongDescription => "Stay invisible while not moving.";
public string RoleDescription => RoleLongDescription; public string IdPart => "Chameleon";
public string IdPrefix => "ApiExample.Role.Crewmate";
public Color RoleColor => Palette.AcceptedGreen; public Color RoleColor => Palette.AcceptedGreen;
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate; public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
private bool _shouldHide;
public CustomRoleConfiguration Configuration => new(this) public CustomRoleConfiguration Configuration => new(this)
{ {
OptionsScreenshot = ExampleAssets.Banner, OptionsScreenshot = ExampleAssets.Banner,
Icon = MiraAssets.CrewmateFile,
IconTmp = TmpSpriteUtils.CreateSpriteAsset(
MiraAssets.CrewmateFile.LoadAsset(),
"ApiExample.Role.Impostor.ChameleonRole"),
IntroSound = CustomRoleUtils.GetIntroSound(RoleTypes.Shapeshifter), IntroSound = CustomRoleUtils.GetIntroSound(RoleTypes.Shapeshifter),
}; };
public override void Initialize(PlayerControl player) public override void Initialize(PlayerControl player)
{ {
Logger<ExamplePlugin>.Info("Initializing ChamelonRole for player: " + player.PlayerId); Logger<ExamplePlugin>.Info("Initializing ChameleonRole for player: " + player.PlayerId);
RoleBehaviourStubs.Initialize(this, player); RoleBehaviourStubs.Initialize(this, player);
_shouldHide = true; shouldHide = true;
} }
public void FixedUpdate() public void FixedUpdate()
{ {
if (!Player || !_shouldHide) if (!Player || !shouldHide)
{ {
return; return;
} }
@@ -51,27 +54,34 @@ public class ChameloenRole : CrewmateRole, ICustomRole
} }
else else
{ {
SpriteRenderer rend = Player.cosmetics.currentBodySprite.BodySprite; var rend = Player.cosmetics.currentBodySprite.BodySprite;
TextMeshPro tmp = Player.cosmetics.nameText; var tmp = Player.cosmetics.nameText;
tmp.color = Color.Lerp(tmp.color, new Color(tmp.color.r, tmp.color.g, tmp.color.b, Player.AmOwner ? 0.3f : 0), Time.deltaTime * 4f); tmp.color = Color.Lerp(
tmp.color,
new Color(tmp.color.r, tmp.color.g, tmp.color.b, Player.AmOwner ? 0.3f : 0),
Time.deltaTime * 4f);
rend.color = Color.Lerp(rend.color, new Color(1, 1, 1, Player.AmOwner ? 0.3f : 0), Time.deltaTime * 4f); rend.color = Color.Lerp(rend.color, new Color(1, 1, 1, Player.AmOwner ? 0.3f : 0), Time.deltaTime * 4f);
foreach (var cosmetic in Player.cosmetics.transform.GetComponentsInChildren<SpriteRenderer>()) foreach (var cosmetic in Player.cosmetics.transform.GetComponentsInChildren<SpriteRenderer>())
{ {
cosmetic.color = Color.Lerp(cosmetic.color, new Color(1, 1, 1, Player.AmOwner ? 0.3f : 0), Time.deltaTime * 4f); cosmetic.color = Color.Lerp(
cosmetic.color,
new Color(1, 1, 1, Player.AmOwner ? 0.3f : 0),
Time.deltaTime * 4f);
} }
} }
} }
public override void Deinitialize(PlayerControl targetPlayer) public override void Deinitialize(PlayerControl targetPlayer)
{ {
Logger<ExamplePlugin>.Info("Deinitializing ChamelonRole for player: " + targetPlayer.PlayerId); Logger<ExamplePlugin>.Info("Deinitializing ChameleonRole for player: " + targetPlayer.PlayerId);
RoleBehaviourStubs.Deinitialize(this, targetPlayer); RoleBehaviourStubs.Deinitialize(this, targetPlayer);
_shouldHide = false; shouldHide = false;
foreach (var cosmetic in Player.cosmetics.transform.GetComponentsInChildren<SpriteRenderer>(true)) foreach (var cosmetic in Player.cosmetics.transform.GetComponentsInChildren<SpriteRenderer>(true))
{ {
cosmetic.color = Color.white; cosmetic.color = Color.white;
} }
Player.cosmetics.currentBodySprite.BodySprite.color = Color.white; Player.cosmetics.currentBodySprite.BodySprite.color = Color.white;
Player.cosmetics.nameText.color = Color.white; Player.cosmetics.nameText.color = Color.white;
} }
+6 -4
View File
@@ -1,18 +1,20 @@
using MiraAPI.Roles; using MiraAPI.Roles;
using MiraAPI.Utilities.Assets;
using UnityEngine; using UnityEngine;
namespace MiraAPI.Example.Roles; namespace MiraAPI.Example.Roles;
public class FreezerRole : ImpostorRole, ICustomRole public class FreezerRole : ImpostorRole, ICustomRole
{ {
public string RoleName => "Freezer"; public string IdPart => "Freezer";
public string RoleLongDescription => "Freeze another player for a duration of time."; public string IdPrefix => "ApiExample.Role.Impostor";
public string RoleDescription => RoleLongDescription;
public Color RoleColor => Palette.Blue; public Color RoleColor => Palette.Blue;
public ModdedRoleTeams Team => ModdedRoleTeams.Impostor; public ModdedRoleTeams Team => ModdedRoleTeams.Impostor;
public CustomRoleConfiguration Configuration => new CustomRoleConfiguration(this) public CustomRoleConfiguration Configuration => new(this)
{ {
Icon = MiraAssets.ImpostorFile,
IconTmp = TmpSpriteUtils.CreateSpriteAsset(MiraAssets.ImpostorFile.LoadAsset(), "ApiExample.Role.Impostor.Freezer"),
OptionsScreenshot = ExampleAssets.Banner, OptionsScreenshot = ExampleAssets.Banner,
MaxRoleCount = 2, MaxRoleCount = 2,
}; };
+2 -3
View File
@@ -5,9 +5,8 @@ namespace MiraAPI.Example.Roles;
public class MayorRole : CrewmateRole, ICustomRole public class MayorRole : CrewmateRole, ICustomRole
{ {
public string RoleName => "Mayor"; public string IdPart => "Mayor";
public string RoleLongDescription => "You get extra votes!"; public string IdPrefix => "ApiExample.Role.Crewmate";
public string RoleDescription => RoleLongDescription;
public Color RoleColor => new Color32(221, 176, 152, 255); public Color RoleColor => new Color32(221, 176, 152, 255);
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate; public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
public CustomRoleConfiguration Configuration => new(this); public CustomRoleConfiguration Configuration => new(this);
@@ -1,20 +1,16 @@
using MiraAPI.Example.Extension.GameOver; using Il2CppInterop.Runtime.Attributes;
using MiraAPI.Example.GameOver;
using MiraAPI.GameEnd; using MiraAPI.GameEnd;
using MiraAPI.Roles; using MiraAPI.Roles;
using UnityEngine; using UnityEngine;
namespace MiraAPI.Example.Extension.Roles; namespace MiraAPI.Example.Roles;
public class NeutralKillerRole : ImpostorRole, ICustomRole public class NeutralKillerRole : ImpostorRole, ICustomRole
{ {
public string RoleName => "Outcast Killer"; public string IdPart => "OutcastKiller";
public string IdPrefix => "ApiExample.Role.Outcast";
public string RoleDescription => "Outcast who can kill.";
public string RoleLongDescription => this.RoleDescription;
public Color RoleColor => Color.magenta; public Color RoleColor => Color.magenta;
public ModdedRoleTeams Team => ModdedRoleTeams.Custom; public ModdedRoleTeams Team => ModdedRoleTeams.Custom;
public CustomRoleConfiguration Configuration => new(this) public CustomRoleConfiguration Configuration => new(this)
@@ -24,12 +20,13 @@ public class NeutralKillerRole : ImpostorRole, ICustomRole
CanUseVent = true, CanUseVent = true,
}; };
public RoleOptionsGroup RoleOptionsGroup { get; } = new("Outcast", Color.gray); public RoleOptionsGroup RoleOptionsGroup { get; } = new("outcast.group", Color.gray);
[HideFromIl2Cpp]
public TeamIntroConfiguration? IntroConfiguration { get; } = new( public TeamIntroConfiguration? IntroConfiguration { get; } = new(
Color.gray, Color.gray,
"OUTCAST", "outcast.roleTitle",
"You are an Outcast. You do not have a team."); "outcast.teamIntroDescription");
public override void SpawnTaskHeader(PlayerControl playerControl) public override void SpawnTaskHeader(PlayerControl playerControl)
{ {
+3 -4
View File
@@ -5,13 +5,12 @@ namespace MiraAPI.Example.Roles;
public class TeleporterRole : CrewmateRole, ICustomRole public class TeleporterRole : CrewmateRole, ICustomRole
{ {
public string RoleName => "Teleporter"; public string IdPart => "Teleporter";
public string RoleLongDescription => "Zoom out and teleport across the map!"; public string IdPrefix => "ApiExample.Role.Crewmate";
public string RoleDescription => RoleLongDescription;
public Color RoleColor => new Color32(221, 176, 152, 255); public Color RoleColor => new Color32(221, 176, 152, 255);
public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate; public ModdedRoleTeams Team => ModdedRoleTeams.Crewmate;
public CustomRoleConfiguration Configuration => new CustomRoleConfiguration(this) public CustomRoleConfiguration Configuration => new(this)
{ {
OptionsScreenshot = ExampleAssets.Banner, OptionsScreenshot = ExampleAssets.Banner,
CanModifyChance = false, CanModifyChance = false,
-6
View File
@@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiraAPI", "MiraAPI\MiraAPI.
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiraAPI.Example", "MiraAPI.Example\MiraAPI.Example.csproj", "{19B76855-16CC-43CC-A0A6-5A7FFB43F077}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiraAPI.Example", "MiraAPI.Example\MiraAPI.Example.csproj", "{19B76855-16CC-43CC-A0A6-5A7FFB43F077}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiraAPI.Example.Extension", "MiraAPI.Example.Extension\MiraAPI.Example.Extension.csproj", "{526FF017-80E1-4094-804D-741AF35AA226}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -23,10 +21,6 @@ Global
{19B76855-16CC-43CC-A0A6-5A7FFB43F077}.Debug|Any CPU.Build.0 = Debug|Any CPU {19B76855-16CC-43CC-A0A6-5A7FFB43F077}.Debug|Any CPU.Build.0 = Debug|Any CPU
{19B76855-16CC-43CC-A0A6-5A7FFB43F077}.Release|Any CPU.ActiveCfg = Release|Any CPU {19B76855-16CC-43CC-A0A6-5A7FFB43F077}.Release|Any CPU.ActiveCfg = Release|Any CPU
{19B76855-16CC-43CC-A0A6-5A7FFB43F077}.Release|Any CPU.Build.0 = Release|Any CPU {19B76855-16CC-43CC-A0A6-5A7FFB43F077}.Release|Any CPU.Build.0 = Release|Any CPU
{526FF017-80E1-4094-804D-741AF35AA226}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{526FF017-80E1-4094-804D-741AF35AA226}.Debug|Any CPU.Build.0 = Debug|Any CPU
{526FF017-80E1-4094-804D-741AF35AA226}.Release|Any CPU.ActiveCfg = Release|Any CPU
{526FF017-80E1-4094-804D-741AF35AA226}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
+107
View File
@@ -0,0 +1,107 @@
using System;
using System.Diagnostics.CodeAnalysis;
using MiraAPI.Utilities;
using UnityEngine;
namespace MiraAPI.Colors.ColorSpaces;
/// <summary>
/// A struct that denotes the CMYK (Cyan, Magenta, Yellow, Key) color space.
/// </summary>
/// <param name="c">The cyan component.</param>
/// <param name="m">The magenta component.</param>
/// <param name="y">The yellow component.</param>
/// <param name="k">The key component.</param>
/// <param name="a">The alpha component.</param>
[Serializable]
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Unity parity.")]
public record struct CmykColor(float c, float m, float y, float k, float a = 1f)
{
/// <summary>
/// Implicitly converts a <see cref="CmykColor"/> to a Unity <see cref="Color"/>.
/// </summary>
/// <param name="c">The color being converted.</param>
public static implicit operator Color(CmykColor c)
{
return ToColor(c);
}
/// <summary>
/// Implicitly converts a Unity <see cref="Color"/> to a <see cref="CmykColor"/>.
/// </summary>
/// <param name="c">The color being converted.</param>
public static implicit operator CmykColor(Color c)
{
return FromColor(c);
}
/// <summary>
/// Converts a <see cref="CmykColor"/> to a standard Unity RGB <see cref="Color"/>.
/// </summary>
/// <param name="cmyk">The CMYK color to convert.</param>
/// <returns>A Unity <see cref="Color"/> representing the same visual color.</returns>
public static Color ToColor(CmykColor cmyk)
{
var key = 1f - cmyk.k;
var r = (1f - cmyk.c) * key;
var g = (1f - cmyk.m) * key;
var b = (1f - cmyk.y) * key;
return new Color(MathUtilities.Clamp01(r), MathUtilities.Clamp01(g), MathUtilities.Clamp01(b), cmyk.a);
}
/// <summary>
/// Converts a standard Unity RGB <see cref="Color"/> to a <see cref="CmykColor"/>.
/// </summary>
/// <param name="color">The Unity Color to convert.</param>
/// <returns>A <see cref="CmykColor"/> representing the same visual color.</returns>
public static CmykColor FromColor(Color color)
{
var r = color.r;
var g = color.g;
var b = color.b;
var k = 1f - MathF.Max(r, MathF.Max(g, b));
if (k >= 1f)
return new CmykColor(0f, 0f, 0f, 1f, color.a);
var invK = 1f / (1f - k);
var c = (1f - r - k) * invK;
var m = (1f - g - k) * invK;
var y = (1f - b - k) * invK;
return new CmykColor(MathUtilities.Clamp01(c), MathUtilities.Clamp01(m), MathUtilities.Clamp01(y), MathUtilities.Clamp01(k), color.a);
}
/// <summary>
/// Linearly interpolates between two <see cref="CmykColor"/> values.
/// </summary>
/// <param name="a">The starting color.</param>
/// <param name="b">The ending color.</param>
/// <param name="t">The interpolation value between the two colors, clamped to a 0 to 1 range.</param>
/// <returns>The interpolated <see cref="CmykColor"/>.</returns>
public static CmykColor Lerp(CmykColor a, CmykColor b, float t)
{
return LerpUnclamped(a, b, MathUtilities.Clamp01(t));
}
/// <summary>
/// Linearly interpolates between two <see cref="CmykColor"/> values without clamping the interpolant.
/// </summary>
/// <param name="a">The starting color.</param>
/// <param name="b">The ending color.</param>
/// <param name="t">The interpolation value between the two colors.</param>
/// <returns>The interpolated <see cref="CmykColor"/>.</returns>
public static CmykColor LerpUnclamped(CmykColor a, CmykColor b, float t)
{
return new CmykColor(
MathUtilities.LerpUnclamped(a.c, b.c, t),
MathUtilities.LerpUnclamped(a.m, b.m, t),
MathUtilities.LerpUnclamped(a.y, b.y, t),
MathUtilities.LerpUnclamped(a.k, b.k, t),
MathUtilities.LerpUnclamped(a.a, b.a, t));
}
}
+136
View File
@@ -0,0 +1,136 @@
using System;
using System.Diagnostics.CodeAnalysis;
using MiraAPI.Utilities;
using UnityEngine;
namespace MiraAPI.Colors.ColorSpaces;
/// <summary>
/// A struct that denotes the HSB (Hue, Saturation, Brightness) color space.
/// </summary>
/// <param name="h">The hue component.</param>
/// <param name="s">The saturation component.</param>
/// <param name="b">The brightness component.</param>
/// <param name="a">The alpha component.</param>
[Serializable]
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Unity parity.")]
public record struct HsbColor(float h, float s, float b, float a = 1f)
{
/// <summary>
/// Implicitly converts an <see cref="HsbColor"/> to a Unity <see cref="Color"/>.
/// </summary>
/// <param name="c">The color being converted.</param>
public static implicit operator Color(HsbColor c)
{
return ToColor(c);
}
/// <summary>
/// Implicitly converts a Unity <see cref="Color"/> to an <see cref="HsbColor"/>.
/// </summary>
/// <param name="c">The color being converted.</param>
public static implicit operator HsbColor(Color c)
{
return FromColor(c);
}
/// <summary>
/// Converts an <see cref="HsbColor"/> to a standard Unity RGB <see cref="Color"/>.
/// </summary>
/// <param name="hsb">The HSB color to convert.</param>
/// <returns>A Unity <see cref="Color"/> representing the same visual color.</returns>
public static Color ToColor(HsbColor hsb)
{
if (hsb.s <= float.Epsilon)
return new Color(MathUtilities.Clamp01(hsb.b), MathUtilities.Clamp01(hsb.b), MathUtilities.Clamp01(hsb.b), hsb.a);
var c = hsb.b * hsb.s;
var hPrime = hsb.h * 6f;
var x = c * (1f - MathF.Abs((hPrime % 2f) - 1f));
var m = hsb.b - c;
var (r, g, b) = hPrime switch
{
< 1f => (c, x, 0f),
< 2f => (x, c, 0f),
< 3f => (0f, c, x),
< 4f => (0f, x, c),
< 5f => (x, 0f, c),
<= 6f => (c, 0f, x),
_ => (0f, 0f, 0f),
};
return new Color(
MathUtilities.Clamp01(r + m),
MathUtilities.Clamp01(g + m),
MathUtilities.Clamp01(b + m),
hsb.a);
}
/// <summary>
/// Converts a standard Unity RGB <see cref="Color"/> to an <see cref="HsbColor"/>.
/// </summary>
/// <param name="color">The Unity Color to convert.</param>
/// <returns>An <see cref="HsbColor"/> representing the same visual color.</returns>
public static HsbColor FromColor(Color color)
{
var max = MathF.Max(color.r, MathF.Max(color.g, color.b));
var min = MathF.Min(color.r, MathF.Min(color.g, color.b));
var delta = max - min;
var h = 0f;
if (delta > 0f)
{
if (max == color.r)
h = (color.g - color.b) / delta % 6f;
else if (max == color.g)
h = (color.b - color.r) / delta + 2f;
else
h = (color.r - color.g) / delta + 4f;
h /= 6f;
if (h < 0f)
h += 1f;
}
var s = max == 0f ? 0f : delta / max;
var b = max;
return new HsbColor(h, s, b, color.a);
}
/// <summary>
/// Linearly interpolates between two <see cref="HsbColor"/> values, using the shortest path for the hue.
/// </summary>
/// <param name="a">The starting color.</param>
/// <param name="b">The ending color.</param>
/// <param name="t">The interpolation value between the two colors, clamped to a 0 to 1 range.</param>
/// <returns>The interpolated <see cref="HsbColor"/>.</returns>
public static HsbColor Lerp(HsbColor a, HsbColor b, float t)
{
return LerpUnclamped(a, b, MathUtilities.Clamp01(t));
}
/// <summary>
/// Linearly interpolates between two <see cref="HsbColor"/> values without clamping the interpolant.
/// </summary>
/// <param name="a">The starting color.</param>
/// <param name="b">The ending color.</param>
/// <param name="t">The interpolation value between the two colors.</param>
/// <returns>The interpolated <see cref="HsbColor"/>.</returns>
public static HsbColor LerpUnclamped(HsbColor a, HsbColor b, float t)
{
var hueDifference = MathUtilities.Repeat(b.h - a.h, 1f);
if (hueDifference > 0.5f)
hueDifference -= 1f;
return new HsbColor(
MathUtilities.Repeat(a.h + (hueDifference * t), 1f),
MathUtilities.LerpUnclamped(a.s, b.s, t),
MathUtilities.LerpUnclamped(a.b, b.b, t),
MathUtilities.LerpUnclamped(a.a, b.a, t));
}
}
+132
View File
@@ -0,0 +1,132 @@
using System;
using System.Diagnostics.CodeAnalysis;
using MiraAPI.Utilities;
using UnityEngine;
namespace MiraAPI.Colors.ColorSpaces;
/// <summary>
/// A struct that denotes the HSL (Hue, Saturation, Lightness) color space.
/// </summary>
/// <param name="h">The hue component.</param>
/// <param name="s">The saturation component.</param>
/// <param name="l">The lightness component.</param>
/// <param name="a">The alpha component.</param>
[Serializable]
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Unity parity.")]
public record struct HslColor(float h, float s, float l, float a = 1f)
{
/// <summary>
/// Implicitly converts an <see cref="HslColor"/> to a Unity <see cref="Color"/>.
/// </summary>
/// <param name="c">The color being converted.</param>
public static implicit operator Color(HslColor c)
{
return ToColor(c);
}
/// <summary>
/// Implicitly converts a Unity <see cref="Color"/> to an <see cref="HslColor"/>.
/// </summary>
/// <param name="c">The color being converted.</param>
public static implicit operator HslColor(Color c)
{
return FromColor(c);
}
/// <summary>
/// Converts an <see cref="HslColor"/> to a standard Unity RGB <see cref="Color"/>.
/// </summary>
/// <param name="hsl">The HSL color to convert.</param>
/// <returns>A Unity <see cref="Color"/> representing the same visual color.</returns>
public static Color ToColor(HslColor hsl)
{
if (hsl.s <= float.Epsilon)
return new Color(MathUtilities.Clamp01(hsl.l), MathUtilities.Clamp01(hsl.l), MathUtilities.Clamp01(hsl.l), hsl.a);
var c = (1f - MathF.Abs(2f * hsl.l - 1f)) * hsl.s;
var hPrime = hsl.h * 6f;
var x = c * (1f - MathF.Abs((hPrime % 2f) - 1f));
var m = hsl.l - c / 2f;
var (r, g, b) = hPrime switch
{
< 1f => (c, x, 0f),
< 2f => (x, c, 0f),
< 3f => (0f, c, x),
< 4f => (0f, x, c),
< 5f => (x, 0f, c),
<= 6f => (c, 0f, x),
_ => (0f, 0f, 0f),
};
return new Color(MathUtilities.Clamp01(r + m), MathUtilities.Clamp01(g + m), MathUtilities.Clamp01(b + m), hsl.a);
}
/// <summary>
/// Converts a standard Unity RGB <see cref="Color"/> to an <see cref="HslColor"/>.
/// </summary>
/// <param name="color">The Unity Color to convert.</param>
/// <returns>An <see cref="HslColor"/> representing the same visual color.</returns>
public static HslColor FromColor(Color color)
{
var max = MathF.Max(color.r, MathF.Max(color.g, color.b));
var min = MathF.Min(color.r, MathF.Min(color.g, color.b));
var l = (max + min) / 2f;
var delta = max - min;
var s = delta == 0f ? 0f : delta / (1f - MathF.Abs((2f * l) - 1f));
var h = 0f;
if (delta > 0f)
{
if (max == color.r)
h = (color.g - color.b) / delta % 6f;
else if (max == color.g)
h = (color.b - color.r) / delta + 2f;
else
h = (color.r - color.g) / delta + 4f;
h /= 6f;
if (h < 0f)
h += 1f;
}
return new HslColor(h, s, l, color.a);
}
/// <summary>
/// Linearly interpolates between two <see cref="HslColor"/> values, using the shortest path for the hue.
/// </summary>
/// <param name="a">The starting color.</param>
/// <param name="b">The ending color.</param>
/// <param name="t">The interpolation value between the two colors, clamped to a 0 to 1 range.</param>
/// <returns>The interpolated <see cref="HslColor"/>.</returns>
public static HslColor Lerp(HslColor a, HslColor b, float t)
{
return LerpUnclamped(a, b, MathUtilities.Clamp01(t));
}
/// <summary>
/// Linearly interpolates between two <see cref="HslColor"/> values without clamping the interpolant.
/// </summary>
/// <param name="a">The starting color.</param>
/// <param name="b">The ending color.</param>
/// <param name="t">The interpolation value between the two colors.</param>
/// <returns>The interpolated <see cref="HslColor"/>.</returns>
public static HslColor LerpUnclamped(HslColor a, HslColor b, float t)
{
var hueDifference = MathUtilities.Repeat(b.h - a.h, 1f);
if (hueDifference > 0.5f)
hueDifference -= 1f;
return new HslColor(
MathUtilities.Repeat(a.h + (hueDifference * t), 1f),
MathUtilities.LerpUnclamped(a.s, b.s, t),
MathUtilities.LerpUnclamped(a.l, b.l, t),
MathUtilities.LerpUnclamped(a.a, b.a, t));
}
}
+43 -11
View File
@@ -1,5 +1,6 @@
using MiraAPI.Utilities; using System.Diagnostics.CodeAnalysis;
using Reactor.Localization.Utilities; using MiraAPI.Translation;
using MiraAPI.Utilities;
using UnityEngine; using UnityEngine;
namespace MiraAPI.Colors; namespace MiraAPI.Colors;
@@ -10,17 +11,37 @@ namespace MiraAPI.Colors;
/// <param name="name">The name of the option.</param> /// <param name="name">The name of the option.</param>
/// <param name="mainColor">The main color.</param> /// <param name="mainColor">The main color.</param>
/// <param name="shadowColor">The shadow color.</param> /// <param name="shadowColor">The shadow color.</param>
public sealed class CustomColor(StringNames name, Color32 mainColor, Color32 shadowColor) [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Internal code.")]
[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "Looks weird.")]
public class CustomColor(StringNames name, Color32 mainColor, Color32 shadowColor)
{ {
/// <summary> /// <summary>
/// Gets or sets the main color. /// Gets or sets the main color.
/// </summary> /// </summary>
public Color32 MainColor { get; set; } = mainColor; public Color32 MainColor
{
get;
set
{
field = value;
InternalMainColor = value;
}
}
= mainColor;
/// <summary> /// <summary>
/// Gets or sets the shadow color. /// Gets or sets the shadow color.
/// </summary> /// </summary>
public Color32 ShadowColor { get; set; } = shadowColor; public Color32 ShadowColor
{
get;
set
{
field = value;
InternalShadowColor = value;
}
}
= shadowColor;
/// <summary> /// <summary>
/// Gets or sets the name of the color. /// Gets or sets the name of the color.
@@ -32,18 +53,24 @@ public sealed class CustomColor(StringNames name, Color32 mainColor, Color32 sha
/// </summary> /// </summary>
public CustomColorBrightness ColorBrightness { get; set; } = CustomColorBrightness.Darker; public CustomColorBrightness ColorBrightness { get; set; } = CustomColorBrightness.Darker;
/// <inheritdoc /> internal Color InternalMainColor = mainColor;
public CustomColor(StringNames name, Color32 mainColor) : this(name, mainColor, mainColor.GetShadowColor(60)) internal Color InternalShadowColor = shadowColor;
/// <inheritdoc cref="CustomColor"/>
public CustomColor(StringNames name, Color32 mainColor)
: this(name, mainColor, mainColor.GetShadowColor(60))
{ {
} }
/// <inheritdoc /> /// <inheritdoc cref="CustomColor"/>
public CustomColor(string name, Color32 mainColor) : this(name, mainColor, mainColor.GetShadowColor(60)) public CustomColor(string name, Color32 mainColor)
: this(name, mainColor, mainColor.GetShadowColor(60))
{ {
} }
/// <inheritdoc /> /// <inheritdoc cref="CustomColor"/>
public CustomColor(string name, Color32 mainColor, Color32 shadowColor) : this(CustomStringName.CreateAndRegister(name), mainColor, shadowColor) public CustomColor(string name, Color32 mainColor, Color32 shadowColor)
: this(MiraLocaleManager.GetOrCreateLocaleString(name), mainColor, shadowColor)
{ {
} }
} }
@@ -53,6 +80,11 @@ public sealed class CustomColor(StringNames name, Color32 mainColor, Color32 sha
/// </summary> /// </summary>
public enum CustomColorBrightness public enum CustomColorBrightness
{ {
/// <summary>
/// An invalid color.
/// </summary>
Invalid = -1,
/// <summary> /// <summary>
/// A lighter color. /// A lighter color.
/// </summary> /// </summary>
+117 -2
View File
@@ -1,23 +1,52 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using HarmonyLib; using HarmonyLib;
using UnityEngine;
namespace MiraAPI.Colors; namespace MiraAPI.Colors;
/// <summary> /// <summary>
/// Used to register and track custom colors. /// Used to register and track <see cref="CustomColor"/>s.
/// </summary> /// </summary>
public static class PaletteManager public static class PaletteManager
{ {
/// <summary> /// <summary>
/// Gets all registered custom colors. /// Gets all registered <see cref="CustomColor"/>s.
/// </summary> /// </summary>
public static CustomColor[] RegisteredColors => [.. CustomColors]; public static CustomColor[] RegisteredColors => [.. CustomColors];
internal static readonly List<CustomColor> CustomColors = []; internal static readonly List<CustomColor> CustomColors = [];
internal static readonly HashSet<StringNames> VariableColorNames = [];
private static readonly CustomColorBrightness[] ColorBrightnessMap =
[
CustomColorBrightness.Darker, // Red
CustomColorBrightness.Darker, // Blue
CustomColorBrightness.Darker, // Green
CustomColorBrightness.Lighter, // Pink
CustomColorBrightness.Lighter, // Orange
CustomColorBrightness.Lighter, // Yellow
CustomColorBrightness.Darker, // Black
CustomColorBrightness.Lighter, // White
CustomColorBrightness.Darker, // Purple
CustomColorBrightness.Darker, // Brown
CustomColorBrightness.Lighter, // Cyan
CustomColorBrightness.Lighter, // Lime
CustomColorBrightness.Darker, // Maroon
CustomColorBrightness.Lighter, // Rose
CustomColorBrightness.Lighter, // Banana
CustomColorBrightness.Darker, // Gray
CustomColorBrightness.Darker, // Tan
CustomColorBrightness.Lighter, // Coral
];
private static int originalLength;
internal static void RegisterAllColors() internal static void RegisterAllColors()
{ {
originalLength = Palette.PlayerColors.Length;
var colors = CustomColors.Select(x => x.MainColor).ToArray(); var colors = CustomColors.Select(x => x.MainColor).ToArray();
var shadowColors = CustomColors.Select(x => x.ShadowColor).ToArray(); var shadowColors = CustomColors.Select(x => x.ShadowColor).ToArray();
var stringNames = CustomColors.Select(x => x.Name).ToArray(); var stringNames = CustomColors.Select(x => x.Name).ToArray();
@@ -29,4 +58,90 @@ public static class PaletteManager
Palette.TextColors = Palette.TextColors.ToArray().AddRangeToArray(colors); Palette.TextColors = Palette.TextColors.ToArray().AddRangeToArray(colors);
Palette.TextOutlineColors = Palette.TextOutlineColors.ToArray().AddRangeToArray(shadowColors); Palette.TextOutlineColors = Palette.TextOutlineColors.ToArray().AddRangeToArray(shadowColors);
} }
/// <summary>
/// Checks to see if the provided color ID belongs to a variable color.
/// </summary>
/// <param name="colorId">The id of the color.</param>
/// <returns><c>true</c> if the color is a variable color; <c>false</c> otherwise.</returns>
public static bool IsVariable(int colorId)
{
if ((uint)colorId >= (uint)Palette.ColorNames.Length)
return false;
return VariableColorNames.Contains(Palette.ColorNames[colorId]);
}
/// <summary>
/// Checks to see if the provided color ID belongs to a custom color.
/// </summary>
/// <param name="colorId">The ID of the color.</param>
/// <returns><c>true</c> if the color is a custom color; <c>false</c> otherwise.</returns>
public static bool IsCustomColor(int colorId)
{
return (uint)(colorId - originalLength) < (uint)CustomColors.Count;
}
/// <summary>
/// Gets the main color of the provided color ID.
/// </summary>
/// <param name="colorId">The id of the color.</param>
/// <returns>The main color associated with the provided ID.</returns>
public static Color GetMainColor(int colorId)
{
if ((uint)colorId >= (uint)Palette.ColorNames.Length)
return Color.white;
return !TryGetCustomColor(colorId, out var custom)
? Palette.PlayerColors[colorId]
: (custom is VariableColor variable
? variable.EvaluateMainColor(Time.time)
: custom.InternalMainColor);
}
/// <summary>
/// Gets the shadow color of the provided color ID.
/// </summary>
/// <param name="colorId">The ID of the color.</param>
/// <returns>The shadow color associated with the provided ID.</returns>
public static Color GetShadowColor(int colorId)
{
if ((uint)colorId >= (uint)Palette.ColorNames.Length)
return Color.white;
return !TryGetCustomColor(colorId, out var custom)
? Palette.ShadowColors[colorId]
: (custom is VariableColor variable
? variable.EvaluateShadowColor(Time.time)
: custom.InternalShadowColor);
}
/// <summary>
/// Gets the brightness type of the color associated with the provided ID.
/// </summary>
/// <param name="colorId">The ID of the color.</param>
/// <returns>The brightness type of the provided ID.</returns>
public static CustomColorBrightness GetBrightness(int colorId)
{
if ((uint)colorId >= (uint)Palette.ColorNames.Length)
return CustomColorBrightness.Invalid;
return TryGetCustomColor(colorId, out var custom)
? custom.ColorBrightness
: ColorBrightnessMap[colorId];
}
internal static bool TryGetCustomColor(int colorId, [NotNullWhen(true)] out CustomColor? custom)
{
var index = colorId - originalLength;
if ((uint)index >= (uint)CustomColors.Count)
{
custom = null;
return false;
}
custom = CustomColors[index];
return true;
}
} }
@@ -3,7 +3,7 @@
namespace MiraAPI.Colors; namespace MiraAPI.Colors;
/// <summary> /// <summary>
/// Used to mark a class for custom colors registration. /// Used to mark a class for <see cref="CustomColor"/> registration.
/// </summary> /// </summary>
[AttributeUsage(AttributeTargets.Class)] [AttributeUsage(AttributeTargets.Class)]
public class RegisterCustomColorsAttribute : Attribute; public class RegisterCustomColorsAttribute : Attribute;
+72
View File
@@ -0,0 +1,72 @@
using System;
using MiraAPI.LocalSettings;
using MiraAPI.Translation;
using MiraAPI.Utilities;
using UnityEngine;
namespace MiraAPI.Colors;
/// <summary>
/// Represents a dynamic custom color that changes over time.
/// </summary>
/// <param name="name">The name of the color.</param>
/// <param name="mainEvaluator">The function to evaluate the dynamic main color.</param>
/// <param name="shadowEvaluator">The function to evaluate the dynamic shadow color.</param>
/// <param name="mainColor">The static main color used when dynamic colors are disabled.</param>
/// <param name="shadowColor">The static shadow color used when dynamic colors are disabled.</param>
/// <param name="defaultTime">The default time that is used to automatically fill in the static colors when the latter is not provided.</param>
public sealed class VariableColor(StringNames name, Func<float, Color> mainEvaluator, Func<float, Color>? shadowEvaluator, Color32? mainColor = null, Color32? shadowColor = null, float defaultTime = 0f)
: CustomColor(name, mainColor ?? mainEvaluator(defaultTime), shadowColor ?? shadowEvaluator?.Invoke(defaultTime) ?? (mainColor ?? mainEvaluator(defaultTime)).GetShadowColor(60))
{
/// <summary>
/// Gets or sets a delegate that takes in a time value and returns the dynamic main color.
/// </summary>
public Func<float, Color> MainEvaluator { get; set; } = mainEvaluator;
/// <summary>
/// Gets or sets a delegate that takes in a time value and returns the dynamic shadow color.
/// </summary>
public Func<float, Color> ShadowEvaluator { get; set; } = shadowEvaluator ?? (t => mainEvaluator(t).GetShadowColor(0.24f));
/// <inheritdoc cref="VariableColor"/>
public VariableColor(StringNames name, Func<float, Color> mainEvaluator, Color32? mainColor = null, float defaultTime = 0f)
: this(name, mainEvaluator, null, mainColor, null, defaultTime)
{
}
/// <inheritdoc cref="VariableColor"/>
public VariableColor(string name, Func<float, Color> mainEvaluator, Color32? mainColor = null, float defaultTime = 0f)
: this(name, mainEvaluator, null, mainColor, null, defaultTime)
{
}
/// <inheritdoc cref="VariableColor"/>
public VariableColor(string name, Func<float, Color> mainEvaluator, Func<float, Color>? shadowEvaluator, Color32? mainColor = null, Color32? shadowColor = null, float defaultTime = 0f)
: this(MiraLocaleManager.GetOrCreateLocaleString(name), mainEvaluator, shadowEvaluator, mainColor, shadowColor, defaultTime)
{
}
/// <summary>
/// Evaluates the dynamic main color based on the provided time value.
/// </summary>
/// <param name="time">The time to evaluate the color against.</param>
/// <returns>The dynamically evaluated color, or the static <see cref="CustomColor.MainColor"/> if static variable colors are enabled in the user's settings.</returns>
public Color EvaluateMainColor(float time)
{
return LocalSettingsTabSingleton<MiraApiSettings>.Instance.EnableVariableColors.Value
? MainEvaluator(time)
: InternalMainColor;
}
/// <summary>
/// Evaluates the dynamic shadow color based on the provided time value.
/// </summary>
/// <param name="time">The time to evaluate the color against.</param>
/// <returns>The dynamically evaluated color, or the static <see cref="CustomColor.ShadowColor"/> if static variable colors are enabled in the user's settings.</returns>
public Color EvaluateShadowColor(float time)
{
return LocalSettingsTabSingleton<MiraApiSettings>.Instance.EnableVariableColors.Value
? ShadowEvaluator(time)
: InternalShadowColor;
}
}
+102
View File
@@ -0,0 +1,102 @@
using System.Diagnostics.CodeAnalysis;
using Il2CppInterop.Runtime.Attributes;
using MiraAPI.Colors;
using MiraAPI.Utilities;
using Reactor.Utilities.Attributes;
using UnityEngine;
namespace MiraAPI;
/// <summary>
/// The base class for variable color behaviour on <see cref="SpriteRenderer"/>s.
/// </summary>
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity methods.")]
[SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "Unity fields.")]
[SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "Read above.")]
public abstract class BaseVariableColorBehaviour : MonoBehaviour
{
/// <summary>
/// The <see cref="VariableColor"/> to apply.
/// </summary>
protected VariableColor? color;
/// <summary>
/// Sets the current variable color.
/// </summary>
/// <param name="newColor">The new <see cref="VariableColor"/>.</param>
[HideFromIl2Cpp]
public void SetColor(VariableColor? newColor)
{
color = newColor;
}
}
/// <summary>
/// A mono script that adjusts the material colors of a <see cref="Renderer"/> component that it's attached to based on the provided variable color.
/// </summary>
[RegisterInIl2Cpp]
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity methods.")]
public sealed class VariableColorBehaviour : BaseVariableColorBehaviour
{
private Renderer? rend;
private static readonly Color VisorColor = Palette.VisorColor;
/// <summary>
/// Sets the new <see cref="Renderer"/> target.
/// </summary>
/// <param name="newRend">The new <see cref="Renderer"/> that the script must target.</param>
public void SetRend(Renderer? newRend)
{
rend = newRend;
}
private void Awake()
{
rend = GetComponent<Renderer>();
}
private void Update()
{
if (color == null || rend == null)
return;
var time = Time.time;
var material = rend.material;
material.SetColor(ShaderID.VisorColor, VisorColor);
material.SetColor(ShaderID.BodyColor, color.EvaluateMainColor(time));
material.SetColor(ShaderID.BackColor, color.EvaluateShadowColor(time));
}
}
/// <summary>
/// A mono script that adjusts the graphic colors of a <see cref="SpriteRenderer"/> component that it's attached to based on the provided variable color.
/// </summary>
[RegisterInIl2Cpp]
[SuppressMessage("Style", "IDE0051:Remove unused private members", Justification = "Unity methods.")]
public sealed class BasicVariableColorBehaviour : BaseVariableColorBehaviour
{
private SpriteRenderer? rend;
/// <summary>
/// Sets the new <see cref="SpriteRenderer"/> target.
/// </summary>
/// <param name="newRend">The new <see cref="SpriteRenderer"/> that the script must target.</param>
public void SetRend(SpriteRenderer? newRend)
{
rend = newRend;
}
private void Awake()
{
rend = GetComponent<SpriteRenderer>();
}
private void Update()
{
if (color != null && rend != null)
rend.color = color.EvaluateMainColor(Time.time);
}
}
+12 -27
View File
@@ -3,42 +3,27 @@
namespace MiraAPI.Events.Mira; namespace MiraAPI.Events.Mira;
/// <summary> /// <summary>
/// Invoked when a Mira Button click is cancelled. Do not use for vanilla buttons. /// Invoked when a <see cref="CustomActionButton"/> click is cancelled. Do not use for vanilla <see cref="AbilityButton"/>s.
/// </summary> /// </summary>
/// <typeparam name="T">The Mira Button type.</typeparam> /// <typeparam name="T">The <see cref="CustomActionButton"/> type.</typeparam>
public sealed class MiraButtonCancelledEvent<T> : MiraEvent where T : CustomActionButton /// <param name="button">The <see cref="CustomActionButton"/> whose click was cancelled.</param>
public sealed class MiraButtonCancelledEvent<T>(T button) : MiraEvent
where T : CustomActionButton
{ {
/// <summary> /// <summary>
/// Gets Mira Button whose click was cancelled. /// Gets the <see cref="CustomActionButton"/> whose click was cancelled.
/// </summary> /// </summary>
public T Button { get; } public T Button { get; } = button;
/// <summary>
/// Initializes a new instance of the <see cref="MiraButtonCancelledEvent{T}"/> class.
/// </summary>
/// <param name="button">The Mira Button whose click was cancelled.</param>
public MiraButtonCancelledEvent(T button)
{
Button = button;
}
} }
/// <summary> /// <summary>
/// Invoked when a Mira Button click is cancelled. Do not use for vanilla buttons. /// Invoked when a <see cref="CustomActionButton"/> click is cancelled. Do not use for vanilla <see cref="AbilityButton"/>s.
/// </summary> /// </summary>
public sealed class MiraButtonCancelledEvent : MiraEvent /// <param name="button">The <see cref="CustomActionButton"/> whose click was cancelled.</param>
public sealed class MiraButtonCancelledEvent(CustomActionButton button) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets Mira Button whose click was cancelled. /// Gets the <see cref="CustomActionButton"/> whose click was cancelled.
/// </summary> /// </summary>
public CustomActionButton Button { get; } public CustomActionButton Button { get; } = button;
/// <summary>
/// Initializes a new instance of the <see cref="MiraButtonCancelledEvent"/> class.
/// </summary>
/// <param name="button">The Mira Button whose click was cancelled.</param>
public MiraButtonCancelledEvent(CustomActionButton button)
{
Button = button;
}
} }
+15 -31
View File
@@ -3,49 +3,33 @@
namespace MiraAPI.Events.Mira; namespace MiraAPI.Events.Mira;
/// <summary> /// <summary>
/// Button click event for Mira Buttons only. Do not use for vanilla buttons. /// Button click event for <see cref="CustomActionButton"/>s only. Do not use for vanilla <see cref="AbilityButton"/>s.
/// </summary> /// </summary>
/// <typeparam name="T">The Mira Button type.</typeparam> /// <typeparam name="T">The <see cref="CustomActionButton"/> type.</typeparam>
public sealed class MiraButtonClickEvent<T> : MiraCancelableEvent where T : CustomActionButton /// <param name="button">The <see cref="CustomActionButton"/> that was clicked.</param>
/// <param name="genericClickEvent">The generic <see cref="MiraButtonClickEvent"/> invoked before button-specific events.</param>
public class MiraButtonClickEvent<T>(T button, MiraButtonClickEvent genericClickEvent) : MiraCancelableEvent
where T : CustomActionButton
{ {
/// <summary> /// <summary>
/// Gets Mira Button that was clicked. /// Gets the <see cref="CustomActionButton"/> that was clicked.
/// </summary> /// </summary>
public T Button { get; } public T Button { get; } = button;
/// <summary> /// <summary>
/// Gets the generic click event that is invoked before this button-specific event. /// Gets the generic <see cref="MiraButtonClickEvent"/> that is invoked before this button-specific event.
/// </summary> /// </summary>
public MiraButtonClickEvent GenericClickEvent { get; } public MiraButtonClickEvent GenericClickEvent { get; } = genericClickEvent;
/// <summary>
/// Initializes a new instance of the <see cref="MiraButtonClickEvent{T}"/> class.
/// </summary>
/// <param name="button">The Mira Button that was clicked.</param>
/// <param name="genericClickEvent">The generic click event invoked before button-specific events.</param>
public MiraButtonClickEvent(T button, MiraButtonClickEvent genericClickEvent)
{
GenericClickEvent = genericClickEvent;
Button = button;
}
} }
/// <summary> /// <summary>
/// Button click event for Mira Buttons only. Do not use for vanilla buttons. /// Button click event for <see cref="CustomActionButton"/>s only. Do not use for vanilla <see cref="AbilityButton"/>s.
/// </summary> /// </summary>
public sealed class MiraButtonClickEvent : MiraCancelableEvent /// <param name="button">The <see cref="CustomActionButton"/> that was clicked.</param>
public class MiraButtonClickEvent(CustomActionButton button) : MiraCancelableEvent
{ {
/// <summary> /// <summary>
/// Gets Mira Button that was clicked. /// Gets the <see cref="CustomActionButton"/> that was clicked.
/// </summary> /// </summary>
public CustomActionButton Button { get; } public CustomActionButton Button { get; } = button;
/// <summary>
/// Initializes a new instance of the <see cref="MiraButtonClickEvent"/> class.
/// </summary>
/// <param name="button">The Mira Button that was clicked.</param>
public MiraButtonClickEvent(CustomActionButton button)
{
Button = button;
}
} }
@@ -0,0 +1,21 @@
using UnityEngine;
namespace MiraAPI.Events.Mira;
/// <summary>
/// Event fired by Mira API to adjust the UI buttons at the top right of the screen.
/// </summary>
/// <param name="topUiRow">The <see cref="GameObject"/> for the top UI row.</param>
/// <param name="secondUiRow">The <see cref="GameObject"/> for the second UI row.</param>
public class UiButtonPostResetEvent(GameObject topUiRow, GameObject secondUiRow) : MiraEvent
{
/// <summary>
/// Gets the <see cref="GameObject"/> parent for the very top UI row.
/// </summary>
public GameObject MainTopUiRow { get; } = topUiRow;
/// <summary>
/// Gets the <see cref="GameObject"/> parent for the second top UI row.
/// </summary>
public GameObject SecondTopUiRow { get; } = secondUiRow;
}
+15
View File
@@ -0,0 +1,15 @@
namespace MiraAPI.Events.Mira;
/// <summary>
/// Event fired by Mira API prior to adjusting the UI buttons at the top right of the screen.
/// </summary>
public class UiButtonResetEvent : MiraEvent
{
/// <summary>
/// Initializes a new instance of the <see cref="UiButtonResetEvent"/> class.
/// </summary>
public UiButtonResetEvent()
{
// nothing!
}
}
+4 -1
View File
@@ -1,8 +1,11 @@
namespace MiraAPI.Events; using MiraAPI.PluginLoading;
namespace MiraAPI.Events;
/// <summary> /// <summary>
/// Abstract class for Mira Events that can be cancelled. /// Abstract class for Mira Events that can be cancelled.
/// </summary> /// </summary>
[MiraIgnore]
public abstract class MiraCancelableEvent : MiraEvent public abstract class MiraCancelableEvent : MiraEvent
{ {
/// <summary> /// <summary>
+4 -1
View File
@@ -1,6 +1,9 @@
namespace MiraAPI.Events; using MiraAPI.PluginLoading;
namespace MiraAPI.Events;
/// <summary> /// <summary>
/// Abstract class for Mira Events. /// Abstract class for Mira Events.
/// </summary> /// </summary>
[MiraIgnore]
public abstract class MiraEvent; public abstract class MiraEvent;
+1 -1
View File
@@ -3,7 +3,7 @@
namespace MiraAPI.Events; namespace MiraAPI.Events;
/// <summary> /// <summary>
/// Event handle to use when unregistering an event. /// Event handle to use when unregistering a <see cref="MiraEvent"/>.
/// </summary> /// </summary>
public class MiraEventHandle public class MiraEventHandle
{ {
+25 -21
View File
@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using Reactor.Utilities;
namespace MiraAPI.Events; namespace MiraAPI.Events;
@@ -13,14 +12,16 @@ public static class MiraEventManager
private static readonly Dictionary<Type, List<MiraEventWrapper>> EventWrappers = []; private static readonly Dictionary<Type, List<MiraEventWrapper>> EventWrappers = [];
/// <summary> /// <summary>
/// Invoke an event. /// Invoke a <see cref="MiraEvent"/>.
/// </summary> /// </summary>
/// <param name="eventInstance">The event instance.</param> /// <param name="eventInstance">The <typeparamref name="T"/> instance.</param>
/// <typeparam name="T">Type of Event.</typeparam> /// <typeparam name="T">Type of Event.</typeparam>
/// <returns>If there was an event handler invoked for this event, return true. Otherwise, return false.</returns> /// <returns>If there was an event handler invoked for this event, return <see langword="true"/>. Otherwise, return <see langword="false"/>.</returns>
public static bool InvokeEvent<T>(T eventInstance) where T : MiraEvent public static bool InvokeEvent<T>(this T eventInstance)
where T : MiraEvent
{ {
EventWrappers.TryGetValue(typeof(T), out var handlers); EventWrappers.TryGetValue(typeof(T), out var handlers);
if (handlers == null || handlers.Count == 0) if (handlers == null || handlers.Count == 0)
{ {
return false; return false;
@@ -34,7 +35,7 @@ public static class MiraEventManager
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger<MiraApiPlugin>.Error($"Error invoking event handler for {typeof(T).Name}: {ex.ToString()}"); Error($"Error invoking event handler for {typeof(T).Name}: {ex.ToString()}");
} }
} }
@@ -42,14 +43,15 @@ public static class MiraEventManager
} }
/// <summary> /// <summary>
/// Invoke an event and use a specific type to find the handlers. /// Invoke a <see cref="MiraEvent"/> and use a specific type to find the handlers.
/// </summary> /// </summary>
/// <param name="eventInstance">The event instance.</param> /// <param name="eventInstance">The <see cref="MiraEvent"/> instance.</param>
/// <param name="type">The type to use for handler lookup.</param> /// <param name="type">The type to use for handler lookup.</param>
/// <returns>If there was an event handler invoked for this event, return true. Otherwise, return false.</returns> /// <returns>If there was an event handler invoked for this event, return <see langword="true"/>. Otherwise, return <see langword="false"/>.</returns>
public static bool InvokeEvent(MiraEvent eventInstance, Type type) public static bool InvokeEvent(this MiraEvent eventInstance, Type type)
{ {
EventWrappers.TryGetValue(type, out var handlers); EventWrappers.TryGetValue(type, out var handlers);
if (handlers == null || handlers.Count == 0) if (handlers == null || handlers.Count == 0)
{ {
return false; return false;
@@ -63,7 +65,7 @@ public static class MiraEventManager
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger<MiraApiPlugin>.Error($"Error invoking event handler for {type.Name}: {ex.ToString()}"); Error($"Error invoking event handler for {type.Name}: {ex.ToString()}");
} }
} }
@@ -71,12 +73,12 @@ public static class MiraEventManager
} }
/// <summary> /// <summary>
/// Register an event. /// Register a <see cref="MiraEvent"/> handler.
/// </summary> /// </summary>
/// <param name="type">The type of event.</param> /// <param name="type">The type of <see cref="MiraEvent"/> event.</param>
/// <param name="methodInfo">The MethodInfo of the event handler.</param> /// <param name="methodInfo">The <see cref="MethodInfo"/> of the event handler.</param>
/// <param name="priority">The priority of the event handler. Lower values are called first.</param> /// <param name="priority">The priority of the event handler. Lower values are called first.</param>
/// <returns>An event handle to use when unregistering the event.</returns> /// <returns>A <see cref="MiraEventHandle"/> to use when unregistering the event.</returns>
public static MiraEventHandle RegisterEventHandler(Type type, MethodInfo methodInfo, int priority = 0) public static MiraEventHandle RegisterEventHandler(Type type, MethodInfo methodInfo, int priority = 0)
{ {
if (!type.IsSubclassOf(typeof(MiraEvent))) if (!type.IsSubclassOf(typeof(MiraEvent)))
@@ -102,13 +104,14 @@ public static class MiraEventManager
} }
/// <summary> /// <summary>
/// Register an event. /// Register a <typeparamref name="T"/> handler.
/// </summary> /// </summary>
/// <param name="handler">The callback method/handler for the event.</param> /// <param name="handler">The callback method/handler for the event.</param>
/// <param name="priority">The priority of the event handler. Lower values are called first.</param> /// <param name="priority">The priority of the event handler. Lower values are called first.</param>
/// <typeparam name="T">Type of event.</typeparam> /// <typeparam name="T">Type of <see cref="MiraEvent"/> event.</typeparam>
/// <returns>An event handle to use when unregistering the event.</returns> /// <returns>A <see cref="MiraEventHandle"/> to use when unregistering the event.</returns>
public static MiraEventHandle RegisterEventHandler<T>(Action<T> handler, int priority = 0) where T : MiraEvent public static MiraEventHandle RegisterEventHandler<T>(Action<T> handler, int priority = 0)
where T : MiraEvent
{ {
EventWrappers.TryAdd(typeof(T), []); EventWrappers.TryAdd(typeof(T), []);
@@ -127,10 +130,10 @@ public static class MiraEventManager
} }
/// <summary> /// <summary>
/// Unregister an event using the event handle. /// Unregister a <see cref="MiraEvent"/> handler using the <see cref="MiraEventHandle"/>.
/// </summary> /// </summary>
/// <param name="eventHandle">A handle to the event.</param> /// <param name="eventHandle">A handle to the event.</param>
/// <returns>True if the event was unregistered successfully, false otherwise.</returns> /// <returns><see langword="true"/> if the event was unregistered successfully, <see langword="false"/> otherwise.</returns>
public static bool UnregisterEventHandler(MiraEventHandle eventHandle) public static bool UnregisterEventHandler(MiraEventHandle eventHandle)
{ {
if (!EventWrappers.TryGetValue(eventHandle.EventType, out var handlers)) if (!EventWrappers.TryGetValue(eventHandle.EventType, out var handlers))
@@ -147,6 +150,7 @@ public static class MiraEventManager
{ {
EventWrappers.Remove(eventHandle.EventType); EventWrappers.Remove(eventHandle.EventType);
} }
return true; return true;
} }
} }
+6 -15
View File
@@ -3,28 +3,19 @@
namespace MiraAPI.Events; namespace MiraAPI.Events;
/// <summary> /// <summary>
/// Wrapper for event handlers. /// Wrapper for <see cref="MiraEvent"/> handlers.
/// </summary> /// </summary>
public class MiraEventWrapper /// <param name="eventHandler">The action for the event handler.</param>
/// <param name="priority">The priority of the handler.</param>
public class MiraEventWrapper(Delegate eventHandler, int priority)
{ {
/// <summary> /// <summary>
/// Gets the event handler delegate. /// Gets the event handler delegate.
/// </summary> /// </summary>
public Delegate EventHandler { get; } public Delegate EventHandler { get; } = eventHandler;
/// <summary> /// <summary>
/// Gets the priority of the handler. Lower values are called first. /// Gets the priority of the handler. Lower values are called first.
/// </summary> /// </summary>
public int Priority { get; } public int Priority { get; } = priority;
/// <summary>
/// Initializes a new instance of the <see cref="MiraEventWrapper"/> class.
/// </summary>
/// <param name="eventHandler">The action for the event handler.</param>
/// <param name="priority">The priority of the handler.</param>
public MiraEventWrapper(Delegate eventHandler, int priority)
{
EventHandler = eventHandler;
Priority = priority;
}
} }
+4 -12
View File
@@ -3,22 +3,14 @@
namespace MiraAPI.Events; namespace MiraAPI.Events;
/// <summary> /// <summary>
/// Register an event. /// Register a <see cref="MiraEvent"/> handler.
/// </summary> /// </summary>
/// <param name="priority">The priority of the event. Lower values are called first.</param>
[AttributeUsage(AttributeTargets.Method)] [AttributeUsage(AttributeTargets.Method)]
public class RegisterEventAttribute : Attribute public class RegisterEventAttribute(int priority = 0) : Attribute
{ {
/// <summary> /// <summary>
/// Gets the priority of the event. Lower values are called first. /// Gets the priority of the event. Lower values are called first.
/// </summary> /// </summary>
public int Priority { get; } public int Priority { get; } = priority;
/// <summary>
/// Initializes a new instance of the <see cref="RegisterEventAttribute"/> class.
/// </summary>
/// <param name="priority">The priority of the event. Lower values are called first.</param>
public RegisterEventAttribute(int priority = 0)
{
Priority = priority;
}
} }
@@ -3,33 +3,66 @@
/// <summary> /// <summary>
/// Event that is invoked after a player is murdered. Only called after a successful murder. This event is not cancelable. /// Event that is invoked after a player is murdered. Only called after a successful murder. This event is not cancelable.
/// </summary> /// </summary>
public class AfterMurderEvent : MiraEvent /// <param name="source">The <see cref="PlayerControl"/> that killed the <paramref name="target"/>.</param>
/// <param name="target">The <see cref="PlayerControl"/> that was killed.</param>
/// <param name="framed">The <see cref="PlayerControl"/> that was framed.</param>
/// <param name="deadBody">The <paramref name="target"/>'s <see cref="global::DeadBody"/>, if it exists.</param>
/// <param name="isIndirect">Whether the murder was caused indirectly.</param>
/// <param name="ignoreDefense">Whether the murder ignored protection.</param>
public class AfterMurderEvent(PlayerControl source, PlayerControl target, PlayerControl? framed, DeadBody? deadBody, bool isIndirect = true, bool ignoreDefense = false) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the player that killed the target. /// Gets the <see cref="PlayerControl"/> that killed the <see cref="Target"/>.
/// </summary> /// </summary>
public PlayerControl Source { get; } public PlayerControl Source { get; } = source;
/// <summary> /// <summary>
/// Gets the player that was killed. /// Gets the <see cref="PlayerControl"/> that was killed.
/// </summary> /// </summary>
public PlayerControl Target { get; } public PlayerControl Target { get; } = target;
/// <summary> /// <summary>
/// Gets the player's body, if it exists. /// Gets the <see cref="PlayerControl"/> that was framed, if any.
/// </summary> /// </summary>
public DeadBody? DeadBody { get; } public PlayerControl? Framed { get; } = framed;
/// <summary>
/// Gets a value indicating whether the murder was done indirectly.
/// This is commonly used to prevent the <see cref="Source"/> <see cref="PlayerControl"/> from being killed.
/// </summary>
public bool IsIndirectAttack { get; } = isIndirect;
/// <summary>
/// Gets a value indicating whether the murder was able to bypass protective roles or general defense, such as <see cref="GuardianAngelRole"/>.
/// </summary>
public bool IgnoreDefense { get; } = ignoreDefense;
/// <summary>
/// Gets the <see cref="Target"/>'s <see cref="DeadBody"/>, if it exists.
/// </summary>
public DeadBody? DeadBody { get; } = deadBody;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="AfterMurderEvent"/> class. /// Initializes a new instance of the <see cref="AfterMurderEvent"/> class.
/// </summary> /// </summary>
/// <param name="source">The killer.</param> /// <param name="source">The <see cref="PlayerControl"/> that killed the <paramref name="target"/>.</param>
/// <param name="target">The killed player.</param> /// <param name="target">The <see cref="PlayerControl"/> that was killed.</param>
/// <param name="deadBody">The player's vody, if it exists.</param> /// <param name="deadBody">The <paramref name="target"/>'s <see cref="DeadBody"/>, if it exists.</param>
/// <param name="isIndirect">Whether the murder was caused indirectly.</param>
/// <param name="ignoreDefense">Whether the murder ignored protection.</param>
public AfterMurderEvent(PlayerControl source, PlayerControl target, DeadBody? deadBody, bool isIndirect, bool ignoreDefense = false)
: this(source, target, null, deadBody, isIndirect, ignoreDefense)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="AfterMurderEvent"/> class.
/// </summary>
/// <param name="source">The <see cref="PlayerControl"/> that killed the <paramref name="target"/>.</param>
/// <param name="target">The <see cref="PlayerControl"/> that was killed.</param>
/// <param name="deadBody">The <paramref name="target"/>'s <see cref="DeadBody"/>, if it exists.</param>
public AfterMurderEvent(PlayerControl source, PlayerControl target, DeadBody? deadBody) public AfterMurderEvent(PlayerControl source, PlayerControl target, DeadBody? deadBody)
: this(source, target, null, deadBody)
{ {
Source = source;
Target = target;
DeadBody = deadBody;
} }
} }
@@ -1,21 +1,13 @@
namespace MiraAPI.Events.Vanilla.Gameplay; namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary> /// <summary>
/// Invoked before RpcEndGame is called, allowing cancellation of the game end entirely. /// Invoked before <see cref="GameManager.RpcEndGame"/> is called, allowing cancellation of the game end entirely.
/// </summary> /// </summary>
public class BeforeGameEndEvent : MiraCancelableEvent /// <param name="reason">The reason for the game end.</param>
public class BeforeGameEndEvent(GameOverReason reason) : MiraCancelableEvent
{ {
/// <summary> /// <summary>
/// Gets the reason for the game end. /// Gets the reason for the game end.
/// </summary> /// </summary>
public GameOverReason Reason { get; } public GameOverReason Reason { get; } = reason;
/// <summary>
/// Initializes a new instance of the <see cref="BeforeGameEndEvent"/> class.
/// </summary>
/// <param name="reason">The reason for the game end.</param>
public BeforeGameEndEvent(GameOverReason reason)
{
Reason = reason;
}
} }
@@ -1,28 +1,71 @@
namespace MiraAPI.Events.Vanilla.Gameplay; using MiraAPI.Networking;
namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary> /// <summary>
/// Event that is invoked before a player is murdered. This event is cancelable. /// Event that is invoked before a player is murdered. This event is cancelable.
/// </summary> /// </summary>
public sealed class BeforeMurderEvent : MiraCancelableEvent /// <param name="source">The <see cref="PlayerControl"/> that is killing the <paramref name="target"/>.</param>
/// <param name="target">The <see cref="PlayerControl"/> that is being killed.</param>
/// <param name="framed">The <see cref="PlayerControl"/> that is being framed.</param>
/// <param name="isIndirect">Whether the murder is caused indirectly.</param>
/// <param name="ignoreDefense">Whether the murder should ignore protection.</param>
/// <param name="inMeeting">Whether the murder is intended to be triggered in a meeting.</param>
public sealed class BeforeMurderEvent(PlayerControl source, PlayerControl target, PlayerControl? framed, bool isIndirect = true, bool ignoreDefense = false, MeetingCheck inMeeting = MeetingCheck.Ignore)
: MiraCancelableEvent
{ {
/// <summary> /// <summary>
/// Gets the player that is killing the target. /// Gets the <see cref="PlayerControl"/> that is killing the <see cref="Target"/>.
/// </summary> /// </summary>
public PlayerControl Source { get; } public PlayerControl Source { get; } = source;
/// <summary> /// <summary>
/// Gets the player that is being killed. /// Gets the <see cref="PlayerControl"/> that is being killed.
/// </summary> /// </summary>
public PlayerControl Target { get; } public PlayerControl Target { get; } = target;
/// <summary>
/// Gets the <see cref="PlayerControl"/> that is being framed, if any.
/// </summary>
public PlayerControl? Framed { get; } = framed;
/// <summary>
/// Gets or sets a value indicating whether the murder is done indirectly.
/// This is commonly used to prevent the <see cref="Source"/> <see cref="PlayerControl"/> from being killed.
/// </summary>
public bool IsIndirectAttack { get; set; } = isIndirect;
/// <summary>
/// Gets or sets a value indicating whether the murder should bypass protective roles or general defense, such as <see cref="GuardianAngelRole"/>.
/// </summary>
public bool IgnoreDefense { get; set; } = ignoreDefense;
/// <summary>
/// Gets whether the murder was meant to be done in a meeting, via an enum.
/// </summary>
public MeetingCheck InMeeting { get; } = inMeeting;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BeforeMurderEvent"/> class. /// Initializes a new instance of the <see cref="BeforeMurderEvent"/> class.
/// </summary> /// </summary>
/// <param name="source">The player that is killing the target.</param> /// <param name="source">The <see cref="PlayerControl"/> that is killing the <paramref name="target"/>.</param>
/// <param name="target">The player that is being killed.</param> /// <param name="target">The <see cref="PlayerControl"/> that is being killed.</param>
public BeforeMurderEvent(PlayerControl source, PlayerControl target) /// <param name="inMeeting">Whether the murder is intended to be triggered in a meeting.</param>
public BeforeMurderEvent(PlayerControl source, PlayerControl target, MeetingCheck inMeeting = MeetingCheck.Ignore)
: this(source, target, false, false, inMeeting)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BeforeMurderEvent"/> class.
/// </summary>
/// <param name="source">The <see cref="PlayerControl"/> that is killing the <paramref name="target"/>.</param>
/// <param name="target">The <see cref="PlayerControl"/> that is being killed.</param>
/// <param name="isIndirect">Whether the murder is caused indirectly.</param>
/// <param name="ignoreDefense">Whether the murder should ignore protection.</param>
/// <param name="inMeeting">Whether the murder is intended to be triggered in a meeting.</param>
public BeforeMurderEvent(PlayerControl source, PlayerControl target, bool isIndirect, bool ignoreDefense = false, MeetingCheck inMeeting = MeetingCheck.Ignore)
: this(source, target, null, isIndirect, ignoreDefense, inMeeting)
{ {
Source = source;
Target = target;
} }
} }
@@ -0,0 +1,13 @@
namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary>
/// Event invoked on <see cref="IntroCutscene.OnDestroy"/> and <see cref="ExileController.WrapUp"/> to determine if it should run the <see cref="RoundStartEvent"/> event or not.
/// </summary>
/// <param name="triggeredByIntro">Whether the event was triggered by the intro or not.</param>
public class BeforeRoundStartEvent(bool triggeredByIntro) : MiraCancelableEvent
{
/// <summary>
/// Gets a value indicating whether the event was triggered by the <see cref="IntroCutscene"/> or <see cref="ExileController"/>.
/// </summary>
public bool TriggeredByIntro { get; } = triggeredByIntro;
}
@@ -1,21 +1,13 @@
namespace MiraAPI.Events.Vanilla.Gameplay; namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary> /// <summary>
/// The event that is invoked when the end game screen is shown. Non cancelable. /// The event that is invoked when the end game screen is shown. Non-cancelable.
/// </summary> /// </summary>
public class GameEndEvent : MiraEvent /// <param name="manager">The <see cref="global::EndGameManager"/> instance.</param>
public class GameEndEvent(EndGameManager manager) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the instance of the EndGameManager. /// Gets the <see cref="global::EndGameManager"/> instance.
/// </summary> /// </summary>
public EndGameManager EndGameManager { get; } public EndGameManager EndGameManager { get; } = manager;
/// <summary>
/// Initializes a new instance of the <see cref="GameEndEvent"/> class.
/// </summary>
/// <param name="manager">The instance of the EndGameManager.</param>
public GameEndEvent(EndGameManager manager)
{
EndGameManager = manager;
}
} }
@@ -1,21 +1,13 @@
namespace MiraAPI.Events.Vanilla.Gameplay; namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary> /// <summary>
/// The event that is invoked when the intro cutscene is shown. Non cancelable. /// The event that is invoked when the intro cutscene is shown. Non-cancelable.
/// </summary> /// </summary>
public class IntroBeginEvent : MiraEvent /// <param name="introCutscene">The intro cutscene.</param>
public class IntroBeginEvent(IntroCutscene introCutscene) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the instance of the IntroCutscene. /// Gets the <see cref="global::IntroCutscene"/> instance.
/// </summary> /// </summary>
public IntroCutscene IntroCutscene { get; } public IntroCutscene IntroCutscene { get; } = introCutscene;
/// <summary>
/// Initializes a new instance of the <see cref="IntroBeginEvent"/> class.
/// </summary>
/// <param name="introCutscene">The intro cutscene.</param>
public IntroBeginEvent(IntroCutscene introCutscene)
{
IntroCutscene = introCutscene;
}
} }
@@ -3,10 +3,11 @@
/// <summary> /// <summary>
/// The event that is invoked when the intro cutscene has finished playing. /// The event that is invoked when the intro cutscene has finished playing.
/// </summary> /// </summary>
/// <param name="introCutscene">The intro cutscene.</param>
public class IntroEndEvent(IntroCutscene introCutscene) : MiraEvent public class IntroEndEvent(IntroCutscene introCutscene) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the instance of the IntroCutscene. /// Gets the <see cref="global::IntroCutscene"/> instance.
/// </summary> /// </summary>
public IntroCutscene IntroCutscene { get; } = introCutscene; public IntroCutscene IntroCutscene { get; } = introCutscene;
} }
@@ -0,0 +1,13 @@
namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary>
/// The event that is invoked when the player's role is shown on the intro cutscene. Non-cancelable.
/// </summary>
/// <param name="introCutscene">The intro cutscene.</param>
public class IntroRoleRevealEvent(IntroCutscene introCutscene) : MiraEvent
{
/// <summary>
/// Gets the <see cref="global::IntroCutscene"/> instance.
/// </summary>
public IntroCutscene IntroCutscene { get; } = introCutscene;
}
@@ -1,21 +1,14 @@
namespace MiraAPI.Events.Vanilla.Gameplay; namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary> /// <summary>
/// Start Round event, invoked on IntroCutscene.OnDestroy and ExileController.WrapUp. /// Start Round event, invoked on <see cref="IntroCutscene.OnDestroy"/> and <see cref="ExileController.WrapUp"/>
/// if the <see cref="BeforeRoundStartEvent"/> isn't cancelled.
/// </summary> /// </summary>
public class RoundStartEvent : MiraEvent /// <param name="triggeredByIntro">Whether the event was triggered by the intro or not.</param>
public class RoundStartEvent(bool triggeredByIntro) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets a value indicating whether the event was triggered by the IntroCutscene or ExileController. /// Gets a value indicating whether the event was triggered by the <see cref="IntroCutscene"/> or <see cref="ExileController"/>.
/// </summary> /// </summary>
public bool TriggeredByIntro { get; } public bool TriggeredByIntro { get; } = triggeredByIntro;
/// <summary>
/// Initializes a new instance of the <see cref="RoundStartEvent"/> class.
/// </summary>
/// <param name="triggeredByIntro">Whether the event was triggered by the intro or not.</param>
public RoundStartEvent(bool triggeredByIntro)
{
TriggeredByIntro = triggeredByIntro;
}
} }
@@ -5,26 +5,17 @@ namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary> /// <summary>
/// Event that is invoked after a player's role is set. This event is not cancelable. /// Event that is invoked after a player's role is set. This event is not cancelable.
/// </summary> /// </summary>
public class SetRoleEvent : MiraEvent /// <param name="player">The player.</param>
/// <param name="role">The new role.</param>
public class SetRoleEvent(PlayerControl player, RoleTypes role) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the player whos role was changed. /// Gets the <see cref="PlayerControl"/> whose role was changed.
/// </summary> /// </summary>
public PlayerControl Player { get; } public PlayerControl Player { get; } = player;
/// <summary> /// <summary>
/// Gets the role that the player was set to. /// Gets the role that the player was set to.
/// </summary> /// </summary>
public RoleTypes Role { get; } public RoleTypes Role { get; } = role;
/// <summary>
/// Initializes a new instance of the <see cref="SetRoleEvent"/> class.
/// </summary>
/// <param name="player">The player.</param>
/// <param name="role">The new role.</param>
public SetRoleEvent(PlayerControl player, RoleTypes role)
{
Player = player;
Role = role;
}
} }
@@ -0,0 +1,29 @@
using MiraAPI.Hud;
namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary>
/// Invoked when a Vanilla <see cref="AbilityButton"/> click is cancelled. Do not use for <see cref="CustomActionButton"/>.
/// </summary>
/// <typeparam name="T">The vanilla <see cref="AbilityButton"/> type.</typeparam>
/// <param name="button">The vanilla <see cref="AbilityButton"/> whose click was cancelled.</param>
public sealed class VanillaButtonCancelledEvent<T>(T button) : MiraEvent
where T : AbilityButton
{
/// <summary>
/// Gets the Vanilla <see cref="AbilityButton"/> whose click was cancelled.
/// </summary>
public T Button { get; } = button;
}
/// <summary>
/// Invoked when a Vanilla <see cref="AbilityButton"/> click is cancelled. Do not use for <see cref="CustomActionButton"/>s.
/// </summary>
/// <param name="button">The vanilla <see cref="AbilityButton"/> whose click was cancelled.</param>
public sealed class VanillaButtonCancelledEvent(AbilityButton button) : MiraEvent
{
/// <summary>
/// Gets the Vanilla <see cref="AbilityButton"/> whose click was cancelled.
/// </summary>
public AbilityButton Button { get; } = button;
}
@@ -0,0 +1,47 @@
using MiraAPI.Hud;
namespace MiraAPI.Events.Vanilla.Gameplay;
/// <summary>
/// Button click event for Vanilla <see cref="AbilityButton"/>s only. Do not use for <see cref="CustomActionButton"/>s.
/// </summary>
/// <typeparam name="T">The vanilla <see cref="AbilityButton"/> type.</typeparam>
/// <param name="button">The vanilla <see cref="AbilityButton"/> that was clicked.</param>
/// <param name="genericClickEvent">The generic <see cref="VanillaButtonClickEvent"/> invoked before button-specific events.</param>
public sealed class VanillaButtonClickEvent<T>(T button, VanillaButtonClickEvent genericClickEvent) : MiraCancelableEvent
where T : AbilityButton
{
/// <summary>
/// Gets the vanilla <see cref="AbilityButton"/> that was clicked.
/// </summary>
public T Button { get; } = button;
/// <summary>
/// Gets the generic <see cref="VanillaButtonClickEvent"/> that is invoked before this button-specific event.
/// </summary>
public VanillaButtonClickEvent GenericClickEvent { get; } = genericClickEvent;
}
/// <summary>
/// Button click event for Vanilla <see cref="AbilityButton"/> only. Do not use for <see cref="CustomActionButton"/>s.
/// </summary>
/// <param name="button">The Vanilla <see cref="AbilityButton"/> that was clicked.</param>
/// <param name="playerTarget">The <see cref="PlayerControl"/> target, if any.</param>
/// <param name="ventTarget">The <see cref="Vent"/> target, if any.</param>
public sealed class VanillaButtonClickEvent(AbilityButton button, PlayerControl? playerTarget = null, Vent? ventTarget = null) : MiraCancelableEvent
{
/// <summary>
/// Gets the Vanilla <see cref="AbilityButton"/> that was clicked.
/// </summary>
public AbilityButton Button { get; } = button;
/// <summary>
/// Gets the target <see cref="PlayerControl"/>, if any, of the Vanilla <see cref="AbilityButton"/> that was clicked.
/// </summary>
public PlayerControl? PlayerTarget { get; } = playerTarget;
/// <summary>
/// Gets the target <see cref="Vent"/>, if any, of the Vanilla <see cref="AbilityButton"/> that was clicked.
/// </summary>
public Vent? VentTarget { get; } = ventTarget;
}
+3 -11
View File
@@ -3,19 +3,11 @@
/// <summary> /// <summary>
/// Event fired when a player closes the doors in a room. /// Event fired when a player closes the doors in a room.
/// </summary> /// </summary>
public class CloseDoorsEvent : MiraCancelableEvent /// <param name="room">The room that was closed.</param>
public class CloseDoorsEvent(SystemTypes room) : MiraCancelableEvent
{ {
/// <summary> /// <summary>
/// Gets the room that the doors were closed in. /// Gets the room that the doors were closed in.
/// </summary> /// </summary>
public SystemTypes Room { get; } public SystemTypes Room { get; } = room;
/// <summary>
/// Initializes a new instance of the <see cref="CloseDoorsEvent"/> class.
/// </summary>
/// <param name="room">The room that was closed.</param>
public CloseDoorsEvent(SystemTypes room)
{
Room = room;
}
} }
@@ -3,19 +3,11 @@
/// <summary> /// <summary>
/// Sabotage from Vanilla Among Us. /// Sabotage from Vanilla Among Us.
/// </summary> /// </summary>
public class PlayerOpenSabotageEvent : MiraCancelableEvent /// <param name="mapBehaviour">The <see cref="global::MapBehaviour"/>.</param>
public class PlayerOpenSabotageEvent(MapBehaviour mapBehaviour) : MiraCancelableEvent
{ {
/// <summary> /// <summary>
/// Gets the MapBehaviour. /// Gets the <see cref="global::MapBehaviour"/>.
/// </summary> /// </summary>
public MapBehaviour MapBehaviour { get; } public MapBehaviour MapBehaviour { get; } = mapBehaviour;
/// <summary>
/// Initializes a new instance of the <see cref="PlayerOpenSabotageEvent"/> class.
/// </summary>
/// <param name="mapBehaviour">The MapBehaviour.</param>
public PlayerOpenSabotageEvent(MapBehaviour mapBehaviour)
{
MapBehaviour = mapBehaviour;
}
} }
@@ -1,35 +1,25 @@
namespace MiraAPI.Events.Vanilla.Map; namespace MiraAPI.Events.Vanilla.Map;
/// <summary> /// <summary>
/// Cancelable event that is invoked before a system is updated. Usually used for sabotage events. /// <see cref="MiraCancelableEvent"/> that is invoked before a system is updated. Usually used for sabotage events.
/// </summary> /// </summary>
public class UpdateSystemEvent : MiraCancelableEvent /// <param name="systemType">The <see cref="SystemTypes"/> being updated.</param>
/// <param name="player">The <see cref="PlayerControl"/> that is updating the system.</param>
/// <param name="amount">Amount to update System to.</param>
public class UpdateSystemEvent(SystemTypes systemType, PlayerControl player, byte amount) : MiraCancelableEvent
{ {
/// <summary> /// <summary>
/// Gets the type of system that will be updated. /// Gets the type of system that will be updated.
/// </summary> /// </summary>
public SystemTypes SystemType { get; } public SystemTypes SystemType { get; } = systemType;
/// <summary> /// <summary>
/// Gets the player that is updating the system. /// Gets the <see cref="PlayerControl"/> that is updating the system.
/// </summary> /// </summary>
public PlayerControl Player { get; } public PlayerControl Player { get; } = player;
/// <summary> /// <summary>
/// Gets the byte amount the system is being updated by. /// Gets the byte amount the system is being updated by.
/// </summary> /// </summary>
public byte Amount { get; } public byte Amount { get; } = amount;
/// <summary>
/// Initializes a new instance of the <see cref="UpdateSystemEvent"/> class.
/// </summary>
/// <param name="systemType">The SystemType being updated.</param>
/// <param name="player">The player that is updating the system.</param>
/// <param name="amount">Amount to update System to.</param>
public UpdateSystemEvent(SystemTypes systemType, PlayerControl player, byte amount)
{
SystemType = systemType;
Player = player;
Amount = amount;
}
} }
@@ -3,19 +3,11 @@
/// <summary> /// <summary>
/// The event that is invoked when a player is ejected. Non-cancelable. /// The event that is invoked when a player is ejected. Non-cancelable.
/// </summary> /// </summary>
public class EjectionEvent : MiraEvent /// <param name="controller">The <see cref="global::ExileController"/> instance.</param>
public class EjectionEvent(ExileController controller) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the instance of the ExileController. /// Gets the <see cref="global::ExileController"/> instance.
/// </summary> /// </summary>
public ExileController ExileController { get; } public ExileController ExileController { get; } = controller;
/// <summary>
/// Initializes a new instance of the <see cref="EjectionEvent"/> class.
/// </summary>
/// <param name="controller">The exile controller.</param>
public EjectionEvent(ExileController controller)
{
ExileController = controller;
}
} }
@@ -6,7 +6,7 @@
public class EndMeetingEvent(MeetingHud meetingHud) : MiraEvent public class EndMeetingEvent(MeetingHud meetingHud) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the MeetingHud instance. /// Gets the <see cref="global::MeetingHud"/> instance.
/// </summary> /// </summary>
public MeetingHud MeetingHud { get; } = meetingHud; public MeetingHud MeetingHud { get; } = meetingHud;
} }
@@ -1,36 +1,26 @@
namespace MiraAPI.Events.Vanilla.Meeting; namespace MiraAPI.Events.Vanilla.Meeting;
/// <summary> /// <summary>
/// The event that is invoked when a body is reported. /// The event that is invoked when a body is reported.<br/>
/// This is invoked in CmdReportBody. /// This is invoked in <see cref="PlayerControl.CmdReportDeadBody(NetworkedPlayerInfo)"/>.
/// </summary> /// </summary>
public class ReportBodyEvent : MiraCancelableEvent /// <param name="reporter">The player who reported the body.</param>
/// <param name="target">The player being reported.</param>
/// <param name="body">The <see cref="DeadBody"/> being reported.</param>
public class ReportBodyEvent(PlayerControl reporter, NetworkedPlayerInfo? target, DeadBody? body) : MiraCancelableEvent
{ {
/// <summary> /// <summary>
/// Gets the player that is reporting the body. /// Gets the player that is reporting the body.
/// </summary> /// </summary>
public PlayerControl Reporter { get; } public PlayerControl Reporter { get; } = reporter;
/// <summary> /// <summary>
/// Gets the player that is being reported. Will be null for emergency meeting. /// Gets the player that is being reported. Will be <see langword="null"/> for emergency meeting.
/// </summary> /// </summary>
public NetworkedPlayerInfo? Target { get; } public NetworkedPlayerInfo? Target { get; } = target;
/// <summary> /// <summary>
/// Gets the body that is being reported. Will be null for emergency meeting. /// Gets the <see cref="DeadBody"/> that is being reported. Will be <see langword="null"/> for emergency meeting.
/// </summary> /// </summary>
public DeadBody? Body { get; } public DeadBody? Body { get; } = body;
/// <summary>
/// Initializes a new instance of the <see cref="ReportBodyEvent"/> class.
/// </summary>
/// <param name="reporter">The player who reported the body.</param>
/// <param name="target">The player being reported.</param>
/// <param name="body">The body being reported.</param>
public ReportBodyEvent(PlayerControl reporter, NetworkedPlayerInfo? target, DeadBody? body)
{
Reporter = reporter;
Target = target;
Body = body;
}
} }
@@ -4,19 +4,11 @@
/// The event that is invoked when a meeting is called. This event is not cancelable. /// The event that is invoked when a meeting is called. This event is not cancelable.
/// This event is called after Mira resets votes, so if you plan on adding votes to a specific player, do it with this event. /// This event is called after Mira resets votes, so if you plan on adding votes to a specific player, do it with this event.
/// </summary> /// </summary>
public class StartMeetingEvent : MiraEvent /// <param name="meetingHud">The <see cref="global::MeetingHud"/> instance.</param>
public class StartMeetingEvent(MeetingHud meetingHud) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the MeetingHud instance. /// Gets the <see cref="global::MeetingHud"/> instance.
/// </summary> /// </summary>
public MeetingHud MeetingHud { get; } public MeetingHud MeetingHud { get; } = meetingHud;
/// <summary>
/// Initializes a new instance of the <see cref="StartMeetingEvent"/> class.
/// </summary>
/// <param name="meetingHud">The MeetingHud instance.</param>
public StartMeetingEvent(MeetingHud meetingHud)
{
MeetingHud = meetingHud;
}
} }
@@ -0,0 +1,19 @@
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
/// <summary>
/// Event that is invoked after the local player successfully votes a player or skips. This event is not cancelable.
/// </summary>
/// <param name="playerVoteArea">The <see cref="PlayerVoteArea"/> that was voted on.</param>
/// <param name="voter">The player who voted.</param>
public class AfterVoteEvent(PlayerVoteArea playerVoteArea, PlayerControl voter) : MiraEvent
{
/// <summary>
/// Gets the instance of the voter's <see cref="PlayerVoteArea"/>.
/// </summary>
public PlayerVoteArea VoteArea { get; } = playerVoteArea;
/// <summary>
/// Gets the player who voted.
/// </summary>
public PlayerControl Player { get; } = voter;
}
@@ -0,0 +1,19 @@
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
/// <summary>
/// Event that is invoked before the local player confirms a vote on a player or when skipping. This event is cancelable.
/// </summary>
/// <param name="playerVoteArea">The <see cref="PlayerVoteArea"/> that was voted on.</param>
/// <param name="voter">The player who voted.</param>
public class BeforeVoteEvent(PlayerVoteArea playerVoteArea, PlayerControl voter) : MiraCancelableEvent
{
/// <summary>
/// Gets the instance of the voter's <see cref="PlayerVoteArea"/>.
/// </summary>
public PlayerVoteArea VoteArea { get; } = playerVoteArea;
/// <summary>
/// Gets the player who voted.
/// </summary>
public PlayerControl Player { get; } = voter;
}
@@ -3,24 +3,16 @@
/// <summary> /// <summary>
/// Checks if voting is complete. If canceled, the default end voting logic will be skipped. /// Checks if voting is complete. If canceled, the default end voting logic will be skipped.
/// </summary> /// </summary>
public class CheckForEndVotingEvent : MiraCancelableEvent /// <param name="isVotingComplete"><see langword="true"/> if voting is complete, <see langword="false"/> otherwise.</param>
public class CheckForEndVotingEvent(bool isVotingComplete) : MiraCancelableEvent
{ {
/// <summary> /// <summary>
/// Gets a value indicating whether default voting logic determines that voting is complete. /// Gets a value indicating whether default voting logic determines that voting is complete.
/// </summary> /// </summary>
public bool IsVotingComplete { get; } public bool IsVotingComplete { get; } = isVotingComplete;
/// <summary> /// <summary>
/// Gets or sets a value indicating whether the voting should be forced to end, regardless of the default logic. /// Gets or sets a value indicating whether the voting should be forced to end, regardless of the default logic.
/// </summary> /// </summary>
public bool ForceEndVoting { get; set; } public bool ForceEndVoting { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="CheckForEndVotingEvent"/> class.
/// </summary>
/// <param name="isVotingComplete">>True if voting is complete, false otherwise.</param>
public CheckForEndVotingEvent(bool isVotingComplete)
{
IsVotingComplete = isVotingComplete;
}
} }
@@ -0,0 +1,33 @@
using System;
using MiraAPI.Utilities;
using MiraAPI.Voting;
namespace MiraAPI.Events.Vanilla.Meeting.Voting;
/// <summary>
/// Invoked before the dummy selects their vote. If canceled, the dummy won't vote.
/// </summary>
/// <param name="dummy">The voting dummy.</param>
public class DummyVoteEvent(DummyBehaviour dummy) : MiraCancelableEvent
{
/// <summary>
/// Gets the dummy that needs to vote.
/// </summary>
public DummyBehaviour Dummy { get; } = dummy;
/// <summary>
/// Gets the instance of the dummy's <see cref="PlayerVoteData"/>.
/// </summary>
public PlayerVoteData VoteData { get; } = dummy.myPlayer.GetVoteData();
/// <summary>
/// Gets or sets a value indicating whether the dummy can vote to skip the meeting.
/// </summary>
public bool CanSkip { get; set; } = true;
/// <summary>
/// Gets or sets a predicate for validating whether the dummy can vote on a player.
/// By default, excludes dead and disconnected players.
/// </summary>
public Predicate<PlayerControl> PlayerIsValid { get; set; } = x => !x.Data.IsDead && !x.Data.Disconnected;
}
@@ -4,47 +4,43 @@ namespace MiraAPI.Events.Vanilla.Meeting.Voting;
/// <summary> /// <summary>
/// The event that is invoked when Mira handles a vote. This is invoked before Mira's behaviour, so be cautious. /// The event that is invoked when Mira handles a vote. This is invoked before Mira's behaviour, so be cautious.
/// If you intend on adding custom vote behaviour, cancel the event and do so.
/// If you are NOT canceling the event, keep in mind that Mira automatically removes a vote and adds the suspect to the VotedPlayers list after this event is invoked.
/// </summary> /// </summary>
public class HandleVoteEvent : MiraCancelableEvent /// <remarks>
/// If you intend on adding custom vote behaviour, cancel the event and do so.<br/>
/// If you are NOT canceling the event, keep in mind that Mira automatically removes a vote and adds the suspect to the <see cref="PlayerVoteData.Votes"/> list after this event is invoked.
/// </remarks>
/// <param name="playerVoteData">The voter's <see cref="PlayerVoteData"/>.</param>
/// <param name="targetId">The target's playerId.</param>
/// <param name="isOverruling">Whether the vote is actually for a Judge.</param>
public class HandleVoteEvent(PlayerVoteData playerVoteData, byte targetId, bool isOverruling = false) : MiraCancelableEvent
{ {
/// <summary> /// <summary>
/// Gets the instance of the voter's vote data. /// Gets the instance of the voter's <see cref="PlayerVoteData"/>.
/// </summary> /// </summary>
public PlayerVoteData VoteData { get; } public PlayerVoteData VoteData { get; } = playerVoteData;
/// <summary> /// <summary>
/// Gets the player who voted. /// Gets the player who voted.
/// </summary> /// </summary>
public PlayerControl Player { get; } public PlayerControl Player { get; } = playerVoteData.Owner;
/// <summary> /// <summary>
/// Gets the player id of the target. /// Gets the player id of the target.
/// </summary> /// </summary>
public byte TargetId { get; } public byte TargetId { get; } = targetId;
/// <summary> /// <summary>
/// Gets a value indicating whether to prevent the vote from commencing. /// Gets or sets a value indicating whether to prevent the vote from commencing.
/// </summary> /// </summary>
public bool PreventVote { get; } public bool PreventVote { get; set; } = false;
/// <summary> /// <summary>
/// Gets the player info of the target. /// Gets the <see cref="NetworkedPlayerInfo"/> of the target.
/// </summary> /// </summary>
public NetworkedPlayerInfo TargetPlayerInfo { get; } public NetworkedPlayerInfo TargetPlayerInfo { get; } = GameData.Instance.GetPlayerById(targetId);
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="HandleVoteEvent"/> class. /// Gets or sets a value indicating whether the vote event is an Overrule caused by a Judge.
/// </summary> /// </summary>
/// <param name="playerVoteData">The voter's data.</param> public bool IsOverruling { get; set; } = isOverruling;
/// <param name="targetId">The target's playerId.</param>
public HandleVoteEvent(PlayerVoteData playerVoteData, byte targetId)
{
VoteData = playerVoteData;
Player = playerVoteData.Owner;
TargetId = targetId;
PreventVote = false;
TargetPlayerInfo = GameData.Instance.GetPlayerById(targetId);
}
} }
@@ -5,39 +5,28 @@ namespace MiraAPI.Events.Vanilla.Meeting.Voting;
/// <summary> /// <summary>
/// The event that is invoked when the player tries to select another player to vote. /// The event that is invoked when the player tries to select another player to vote.
/// </summary> /// </summary>
public class MeetingSelectEvent : MiraEvent /// <param name="playerVoteData">The voter's <see cref="PlayerVoteData"/>.</param>
/// <param name="targetId">The target's playerId.</param>
/// <param name="allowSelect">Whether the player is allowed to select the target.</param>
public class MeetingSelectEvent(PlayerVoteData playerVoteData, int targetId, bool allowSelect) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the instance of the voter's vote data. /// Gets the instance of the voter's <see cref="PlayerVoteData"/>.
/// </summary> /// </summary>
public PlayerVoteData VoteData { get; } public PlayerVoteData VoteData { get; } = playerVoteData;
/// <summary> /// <summary>
/// Gets the player id of the target. /// Gets the player id of the target.
/// </summary> /// </summary>
public int TargetId { get; } public int TargetId { get; } = targetId;
/// <summary> /// <summary>
/// Gets the player info of the target. /// Gets the <see cref="NetworkedPlayerInfo"/> of the target.
/// </summary> /// </summary>
public NetworkedPlayerInfo TargetPlayerInfo { get; } public NetworkedPlayerInfo TargetPlayerInfo { get; } = GameData.Instance.GetPlayerById((byte)targetId);
/// <summary> /// <summary>
/// Gets or sets a value indicating whether the player is allowed to select the target. /// Gets or sets a value indicating whether the player is allowed to select the target.
/// </summary> /// </summary>
public bool AllowSelect { get; set; } public bool AllowSelect { get; set; } = allowSelect;
/// <summary>
/// Initializes a new instance of the <see cref="MeetingSelectEvent"/> class.
/// </summary>
/// <param name="playerVoteData">The voter's data.</param>
/// <param name="targetId">The target's playerId.</param>
/// <param name="allowSelect">>Whether the player is allowed to select the target.</param>
public MeetingSelectEvent(PlayerVoteData playerVoteData, int targetId, bool allowSelect)
{
VoteData = playerVoteData;
TargetId = targetId;
TargetPlayerInfo = GameData.Instance.GetPlayerById((byte)targetId);
AllowSelect = allowSelect;
}
} }
@@ -4,22 +4,16 @@ using MiraAPI.Voting;
namespace MiraAPI.Events.Vanilla.Meeting.Voting; namespace MiraAPI.Events.Vanilla.Meeting.Voting;
/// <summary> /// <summary>
/// Called in VotingUtils.HandlePopulateResults. /// Called in <see cref="VotingUtils.HandlePopulateResults"/>.
/// Cancelling is NOT advised but if you do plan on cancelling, please ensure you account for displaying ALL player's votes.
/// </summary> /// </summary>
public class PopulateResultsEvent : MiraCancelableEvent /// <remarks>
/// Cancelling is NOT advised but if you do plan on cancelling, please ensure you account for displaying ALL player's votes.
/// </remarks>
/// <param name="votes">The list of <see cref="CustomVote"/>s.</param>
public class PopulateResultsEvent(List<CustomVote> votes) : MiraCancelableEvent
{ {
/// <summary> /// <summary>
/// Gets a list of networked votes. /// Gets a list of networked <see cref="CustomVote"/>s.
/// </summary> /// </summary>
public List<CustomVote> Votes { get; } public List<CustomVote> Votes { get; } = votes;
/// <summary>
/// Initializes a new instance of the <see cref="PopulateResultsEvent"/> class.
/// </summary>
/// <param name="votes">The list of votes.</param>
public PopulateResultsEvent(List<CustomVote> votes)
{
Votes = votes;
}
} }
@@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using MiraAPI.Voting; using MiraAPI.Voting;
@@ -7,16 +8,11 @@ namespace MiraAPI.Events.Vanilla.Meeting.Voting;
/// <summary> /// <summary>
/// Ran after calculating votes and before displaying the results. Only ran on the host. /// Ran after calculating votes and before displaying the results. Only ran on the host.
/// </summary> /// </summary>
/// <remarks> /// <param name="votes">The list of <see cref="CustomVote"/>s that are being processed.</param>
/// Initializes a new instance of the <see cref="ProcessVotesEvent"/> class. /// <param name="exiledPlayer">The player to be exiled. Will be <see langword="null"/> if no player is to be exiled.</param>
/// </remarks>
/// <param name="votes">>The list of votes that are being processed.</param>
/// <param name="exiledPlayer">The player to be exiled. Will be null if no player is to be exiled.</param>
public class ProcessVotesEvent(List<CustomVote> votes, NetworkedPlayerInfo? exiledPlayer = null) : MiraEvent public class ProcessVotesEvent(List<CustomVote> votes, NetworkedPlayerInfo? exiledPlayer = null) : MiraEvent
{ {
private readonly List<CustomVote> _originalVotes = [.. votes]; private readonly List<CustomVote> originalVotes = [.. votes];
private NetworkedPlayerInfo? _exiledPlayer = exiledPlayer;
/// <summary> /// <summary>
/// Gets a value indicating whether the exiled player has been modified by the event. /// Gets a value indicating whether the exiled player has been modified by the event.
@@ -26,23 +22,35 @@ public class ProcessVotesEvent(List<CustomVote> votes, NetworkedPlayerInfo? exil
/// <summary> /// <summary>
/// Gets a value indicating whether the votes have been modified by the event. /// Gets a value indicating whether the votes have been modified by the event.
/// </summary> /// </summary>
public bool VotesModified => !Votes.SequenceEqual(_originalVotes); public bool VotesModified => !Votes.SequenceEqual(originalVotes);
/// <summary> /// <summary>
/// Gets the list of votes that are being processed. /// Gets the list of <see cref="CustomVote"/>s that are being processed.
/// </summary> /// </summary>
public List<CustomVote> Votes { get; } = votes; public List<CustomVote> Votes { get; } = votes;
/// <summary> /// <summary>
/// Gets or sets the player to be exiled. Will be null if no player is to be exiled. /// Gets or sets a value indicating whether an overruling was done. Normally set by judge but can be overwritten.
/// </summary> /// </summary>
public bool OverruledVote { get; set; }
/// <summary>
/// Gets or sets a value specifically to determine which Judge (if any) caused the overruling. Normally set by judge but can be overwritten.
/// </summary>
public ushort OverruledNonce { get; set; }
/// <summary>
/// Gets or sets the player to be exiled. Will be <see langword="null"/> if no player is to be exiled.
/// </summary>
[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "Looks weird.")]
public NetworkedPlayerInfo? ExiledPlayer public NetworkedPlayerInfo? ExiledPlayer
{ {
get => _exiledPlayer; get;
set set
{ {
_exiledPlayer = value; field = value;
ExiledPlayerModified = true; ExiledPlayerModified = true;
} }
} }
= exiledPlayer;
} }
@@ -3,11 +3,11 @@
/// <summary> /// <summary>
/// The event that is invoked when the voting phase of a meeting is complete. /// The event that is invoked when the voting phase of a meeting is complete.
/// </summary> /// </summary>
/// <param name="meetingHud">The MeetingHud instance.</param> /// <param name="meetingHud">The <see cref="global::MeetingHud"/> instance.</param>
public class VotingCompleteEvent(MeetingHud meetingHud) : MiraEvent public class VotingCompleteEvent(MeetingHud meetingHud) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the MeetingHud instance. /// Gets the <see cref="global::MeetingHud"/> instance.
/// </summary> /// </summary>
public MeetingHud MeetingHud { get; } = meetingHud; public MeetingHud MeetingHud { get; } = meetingHud;
} }
@@ -0,0 +1,25 @@
namespace MiraAPI.Events.Vanilla.Player;
/// <summary>
/// The event that is invoked when a player completes a task within Hide and Seek. Non-cancelable.
/// </summary>
/// <param name="hnsManager">The <see cref="HideAndSeekManager"/> currently active.</param>
/// <param name="player">The player who completed the task.</param>
/// <param name="task">The task that the player completed.</param>
public class CompleteHnsTaskEvent(HideAndSeekManager hnsManager, PlayerControl player, PlayerTask task) : MiraEvent
{
/// <summary>
/// Gets the instance of the <see cref="PlayerControl"/>.
/// </summary>
public PlayerControl Player { get; } = player;
/// <summary>
/// Gets the instance of the <see cref="PlayerTask"/> that the player completed.
/// </summary>
public PlayerTask Task { get; } = task;
/// <summary>
/// Gets the instance of the <see cref="HideAndSeekManager"/> attached to the game.
/// </summary>
public HideAndSeekManager HnsManager { get; } = hnsManager;
}
@@ -1,28 +1,19 @@
namespace MiraAPI.Events.Vanilla.Player; namespace MiraAPI.Events.Vanilla.Player;
/// <summary> /// <summary>
/// The event that is invoked when a player completes a task. Non cancelable. /// The event that is invoked when a player completes a task. Non-cancelable.
/// </summary> /// </summary>
public class CompleteTaskEvent : MiraEvent /// <param name="player">The player who completed the task.</param>
/// <param name="task">The task that the player completed.</param>
public class CompleteTaskEvent(PlayerControl player, PlayerTask task) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the instance of the <see cref="PlayerControl"/>. /// Gets the instance of the <see cref="PlayerControl"/>.
/// </summary> /// </summary>
public PlayerControl Player { get; } public PlayerControl Player { get; } = player;
/// <summary> /// <summary>
/// Gets the instance of the <see cref="PlayerTask"/> that the player completed. /// Gets the instance of the <see cref="PlayerTask"/> that the player completed.
/// </summary> /// </summary>
public PlayerTask Task { get; } public PlayerTask Task { get; } = task;
/// <summary>
/// Initializes a new instance of the <see cref="CompleteTaskEvent"/> class.
/// </summary>
/// <param name="player">The player who completed the task.</param>
/// <param name="task">The task that the player completed.</param>
public CompleteTaskEvent(PlayerControl player, PlayerTask task)
{
Player = player;
Task = task;
}
} }
@@ -1,35 +1,25 @@
namespace MiraAPI.Events.Vanilla.Player; namespace MiraAPI.Events.Vanilla.Player;
/// <summary> /// <summary>
/// Event that is invoked when a player dies. Non cancelable. /// Event that is invoked when a player dies. Non-cancelable.
/// </summary> /// </summary>
public class PlayerDeathEvent : MiraEvent /// <param name="player">The player who died.</param>
/// <param name="reason">The reason the player died.</param>
/// <param name="deadBody">The player's <see cref="global::DeadBody"/>, if it exists.</param>
public class PlayerDeathEvent(PlayerControl player, DeathReason reason, DeadBody? deadBody) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the player who died. /// Gets the player who died.
/// </summary> /// </summary>
public PlayerControl Player { get; } public PlayerControl Player { get; } = player;
/// <summary> /// <summary>
/// Gets the reason the player died. /// Gets the reason the player died.
/// </summary> /// </summary>
public DeathReason DeathReason { get; } public DeathReason DeathReason { get; } = reason;
/// <summary> /// <summary>
/// Gets the dead body associated with the player, if any. /// Gets the <see cref="global::DeadBody"/> associated with the player, if any.
/// </summary> /// </summary>
public DeadBody? DeadBody { get; } public DeadBody? DeadBody { get; } = deadBody;
/// <summary>
/// Initializes a new instance of the <see cref="PlayerDeathEvent"/> class.
/// </summary>
/// <param name="player">The player who died.</param>
/// <param name="reason">The reason the player died.</param>
/// <param name="deadBody">The player's body, if it exists.</param>
public PlayerDeathEvent(PlayerControl player, DeathReason reason, DeadBody? deadBody)
{
Player = player;
DeathReason = reason;
DeadBody = deadBody;
}
} }
@@ -3,21 +3,13 @@
namespace MiraAPI.Events.Vanilla.Player; namespace MiraAPI.Events.Vanilla.Player;
/// <summary> /// <summary>
/// Event that is invoked when a player joins the lobby. Non cancelable. /// Event that is invoked when a player joins the lobby. Non-cancelable.
/// </summary> /// </summary>
public class PlayerJoinEvent : MiraEvent /// <param name="data">The data of the player who joined.</param>
public class PlayerJoinEvent(ClientData data) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the player who joined. /// Gets the player who joined.
/// </summary> /// </summary>
public ClientData ClientData { get; } public ClientData ClientData { get; } = data;
/// <summary>
/// Initializes a new instance of the <see cref="PlayerJoinEvent"/> class.
/// </summary>
/// <param name="data">The data of the player who joined.</param>
public PlayerJoinEvent(ClientData data)
{
ClientData = data;
}
} }
@@ -3,28 +3,19 @@
namespace MiraAPI.Events.Vanilla.Player; namespace MiraAPI.Events.Vanilla.Player;
/// <summary> /// <summary>
/// Event that is invoked when a player leaves the game. Non cancelable. /// Event that is invoked when a player leaves the game. Non-cancelable.
/// </summary> /// </summary>
public class PlayerLeaveEvent : MiraEvent /// <param name="data">The data of the player who left.</param>
/// <param name="reason">The reason why the player left.</param>
public class PlayerLeaveEvent(ClientData data, DisconnectReasons reason) : MiraEvent
{ {
/// <summary> /// <summary>
/// Gets the player who left. /// Gets the player who left.
/// </summary> /// </summary>
public ClientData ClientData { get; } public ClientData ClientData { get; } = data;
/// <summary> /// <summary>
/// Gets the reason why the player left. /// Gets the reason why the player left.
/// </summary> /// </summary>
public DisconnectReasons Reason { get; } public DisconnectReasons Reason { get; } = reason;
/// <summary>
/// Initializes a new instance of the <see cref="PlayerLeaveEvent"/> class.
/// </summary>
/// <param name="data">The data of the player who left.</param>
/// <param name="reason">The reason why the player left.</param>
public PlayerLeaveEvent(ClientData data, DisconnectReasons reason)
{
ClientData = data;
Reason = reason;
}
} }
@@ -3,26 +3,17 @@
/// <summary> /// <summary>
/// Event that is invoked when a player enters a vent. This event is cancelable. /// Event that is invoked when a player enters a vent. This event is cancelable.
/// </summary> /// </summary>
public class EnterVentEvent : MiraCancelableEvent /// <param name="player">The <see cref="PlayerControl"/> that is entering the <paramref name="vent"/>.</param>
/// <param name="vent">The <see cref="global::Vent"/> being entered.</param>
public class EnterVentEvent(PlayerControl player, Vent? vent) : MiraCancelableEvent
{ {
/// <summary> /// <summary>
/// Gets the player that is entering the vent. /// Gets the <see cref="PlayerControl"/> that is entering the <see cref="Vent"/>.
/// </summary> /// </summary>
public PlayerControl Player { get; } public PlayerControl Player { get; } = player;
/// <summary> /// <summary>
/// Gets the vent that the player is entering. /// Gets the <see cref="global::Vent"/> that the <see cref="Player"/> is entering.
/// </summary> /// </summary>
public Vent? Vent { get; } public Vent? Vent { get; } = vent;
/// <summary>
/// Initializes a new instance of the <see cref="EnterVentEvent"/> class.
/// </summary>
/// <param name="player">The player that is entering the vent.</param>
/// <param name="vent">The vent being entered.</param>
public EnterVentEvent(PlayerControl player, Vent? vent)
{
Player = player;
Vent = vent;
}
} }
Loaded 100 of 455 files, more files were not shown because too many files have changed in this diff. Show more