aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format2
-rw-r--r--.gitignore7
-rw-r--r--.gitlab-ci.yml5
-rw-r--r--.travis.yml2
-rw-r--r--Attorney_Online.pro49
-rw-r--r--CONTRIBUTING.md44
-rw-r--r--README.md228
-rw-r--r--base/background/gs4/defensedesk.pngbin6880 -> 0 bytes
-rw-r--r--base/background/gs4/prosecutiondesk.pngbin6551 -> 0 bytes
-rw-r--r--base/background/gs4/stand.pngbin2657 -> 0 bytes
-rw-r--r--base/config.ini10
-rw-r--r--base/misc/default/chatbox.pngbin0 -> 505 bytes
-rw-r--r--base/misc/default/config.ini59
-rw-r--r--base/misc/default/holdit.opusbin0 -> 15238 bytes
-rw-r--r--base/misc/default/holdit_bubble.gifbin0 -> 39003 bytes
-rw-r--r--base/misc/default/objection.opusbin0 -> 15238 bytes
-rw-r--r--base/misc/default/objection_bubble.gifbin0 -> 43029 bytes
-rw-r--r--base/misc/default/takethat.opusbin0 -> 15238 bytes
-rw-r--r--base/misc/default/takethat_bubble.gifbin0 -> 40634 bytes
-rw-r--r--base/sounds/general/adminhelp.oggbin17220 -> 0 bytes
-rw-r--r--base/sounds/general/case_announced.oggbin15790 -> 0 bytes
-rw-r--r--base/sounds/music/failed_login.opusbin396160 -> 0 bytes
m---------base/themes0
-rw-r--r--include/aoapplication.h837
-rw-r--r--include/aoblipplayer.h7
-rw-r--r--include/aocaseannouncerdialog.h1
-rw-r--r--include/aocharmovie.h104
-rw-r--r--include/aoemotebutton.h11
-rw-r--r--include/aoevidencebutton.h11
-rw-r--r--include/aoevidencedisplay.h7
-rw-r--r--include/aoimage.h4
-rw-r--r--include/aolineedit.h9
-rw-r--r--include/aomovie.h3
-rw-r--r--include/aomusicplayer.h82
-rw-r--r--include/aooptionsdialog.h299
-rw-r--r--include/aoscene.h16
-rw-r--r--include/aosfxplayer.h23
-rw-r--r--include/aotextarea.h6
-rw-r--r--include/bass.h2444
-rw-r--r--include/bassopus.h64
-rw-r--r--include/chatlogpiece.h10
-rw-r--r--include/courtroom.h1549
-rw-r--r--include/datatypes.h6
-rw-r--r--include/discord_rich_presence.h1
-rw-r--r--include/lobby.h23
-rw-r--r--include/scrolltext.h47
-rw-r--r--resource/logo_ao2.icns (renamed from resource/logo.icns)bin1129414 -> 1129414 bytes
-rw-r--r--resource/logo_ao2.ico (renamed from resource/logo.ico)bin99678 -> 99678 bytes
-rw-r--r--resource/logo_ao2.png (renamed from resource/logo.png)bin29302 -> 29302 bytes
-rw-r--r--resource/logo_kfo.icobin0 -> 99678 bytes
-rw-r--r--resource/logo_kfo.pngbin0 -> 22609 bytes
-rw-r--r--resource/translations/ao_de.ts962
-rw-r--r--resource/translations/ao_en.ts944
-rw-r--r--resource/translations/ao_es.qmbin28457 -> 47385 bytes
-rw-r--r--resource/translations/ao_es.ts1000
-rw-r--r--resource/translations/ao_jp.ts964
-rw-r--r--resource/translations/ao_pl.qmbin27653 -> 48099 bytes
-rw-r--r--resource/translations/ao_pl.ts1044
-rw-r--r--resource/translations/ao_pt.qmbin28605 -> 47069 bytes
-rw-r--r--resource/translations/ao_pt.ts1003
-rw-r--r--resource/translations/ao_ru.ts960
-rw-r--r--resources.qrc6
-rwxr-xr-xscripts/macos_build.sh2
-rwxr-xr-xscripts/macos_post_build.sh3
-rwxr-xr-xscripts/release_macos.sh22
-rw-r--r--src/aoapplication.cpp7
-rw-r--r--src/aoblipplayer.cpp35
-rw-r--r--src/aobutton.cpp25
-rw-r--r--src/aocaseannouncerdialog.cpp6
-rw-r--r--src/aocharbutton.cpp20
-rw-r--r--src/aocharmovie.cpp431
-rw-r--r--src/aoemotebutton.cpp54
-rw-r--r--src/aoevidencebutton.cpp55
-rw-r--r--src/aoevidencedisplay.cpp64
-rw-r--r--src/aoimage.cpp33
-rw-r--r--src/aolineedit.cpp24
-rw-r--r--src/aomovie.cpp215
-rw-r--r--src/aomusicplayer.cpp240
-rw-r--r--src/aooptionsdialog.cpp499
-rw-r--r--src/aoscene.cpp88
-rw-r--r--src/aosfxplayer.cpp162
-rw-r--r--src/aotextarea.cpp22
-rw-r--r--src/charselect.cpp150
-rw-r--r--src/chatlogpiece.cpp23
-rw-r--r--src/courtroom.cpp9259
-rw-r--r--src/debug_functions.cpp1
-rw-r--r--src/emotes.cpp63
-rw-r--r--src/evidence.cpp566
-rw-r--r--src/hardware_functions.cpp17
-rw-r--r--src/lobby.cpp951
-rw-r--r--src/main.cpp11
-rw-r--r--src/packet_distribution.cpp1479
-rw-r--r--src/path_functions.cpp36
-rw-r--r--src/scrolltext.cpp135
-rw-r--r--src/text_file_functions.cpp1890
95 files changed, 17323 insertions, 12118 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 00000000..a0505826
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,2 @@
+BasedOnStyle: LLVM
+BreakBeforeBraces: Stroustrup
diff --git a/.gitignore b/.gitignore
index 3f8b3ae4..fedae9d9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,7 +9,7 @@ base_override.h
.DS_Store
base-full/
-base/
+logs/
bass.lib
bin/
@@ -17,6 +17,11 @@ bins/
build/
release/
debug/
+base/background
+base/characters
+base/sounds
+base/callwords.ini
+base/config.ini
.qmake.stash
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e9685de0..e0b0886f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -121,10 +121,7 @@ build windows i686:
# Base folder
.deploy_base: &deploy_base |
mkdir base
- mkdir base/themes
- cp -a ../base/themes/default base/themes/
- cp -a ../base/config.ini base/config.sample.ini
- cp -a ../base/serverlist.txt base/serverlist.sample.txt
+ cp -a ../base/ base/
# Miscellaneous files
.deploy_misc: &deploy_misc |
diff --git a/.travis.yml b/.travis.yml
index dbd19cdc..48bc2b56 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,7 +14,7 @@ deploy:
provider: releases
api_key:
secure: mZCNwnqKeqJP5CqgYOanYnr/KHydxueGPRhvGLpY0Pop7MiH3CIHMN5dhHbtgJvE5GGMR4xUIEhPpmkCEJw7YiPREMqT4mkV4DR531ZLB3t/FizyvIwXuP6jFwzTofZ51qHfBpcurVc9sMFeD9Pw+rLTTgIiXL2sZxUUXc8U+ZZug1lYndgcO6P00fUJd6V9lyFQUGmbSca97YbG6KuCym0fEpyRnMqzKLjYsUUo8UKRBADtmD822O6z2FSldNZDn45Mkx0MYfHWyT5hzTb7WGa+DrTB/0un1HqqsNPlb/ahjrFQQNR2qd7HNGZa+Mvwi6egTDug+k15x8lbkacUoi34U1eFq9LSTYm8dSO5g23I1OvGvjTCkDj1jOLPqB99XlbAJ0E/9Jzw7wtlLaAzvFzTj/B63TQnO3IsgHBWR14CZlf05WMOFf2irwl+kL6ktspIHnlGgaiWYYrKeAt7QJAXiQOdYDz6SaWVC6TyOE/SszXRU6xFotmCjkP2irM5yGE8SUw2uIzKjD9uG0ZXtbLcdQEFD316+qglqFTCjnKsRfbtQs2u5spZPsZSdsOZCbLfNIn0GSTFRymFsK6gsvji8AD8AZo0zcOZ/7NMVC6A8RnF3Ve+vU/xljhsIOxoLZDvZPia7WozdV99xmnepWBwkuoQs/K0xmWcnLZDcb0=
- file: "../bin/Attorney_Online_mac_x86_64.zip"
+ file: "../bin/Attorney_Online_macOS.zip"
draft: true
on:
tags: true
diff --git a/Attorney_Online.pro b/Attorney_Online.pro
index c773fb33..28a1e7ca 100644
--- a/Attorney_Online.pro
+++ b/Attorney_Online.pro
@@ -3,7 +3,7 @@ QT += core gui widgets network
TARGET = Attorney_Online
TEMPLATE = app
-VERSION = 2.7.2.0
+VERSION = 2.8.4.0
INCLUDEPATH += $$PWD/include
DESTDIR = $$PWD/bin
@@ -13,30 +13,39 @@ MOC_DIR = $$PWD/build
SOURCES += $$files($$PWD/src/*.cpp)
HEADERS += $$files($$PWD/include/*.h)
-
LIBS += -L$$PWD/lib
-
-#DEFINES += DISCORD
+# Uncomment to enable Discord Rich Presence
+# DEFINES += DISCORD
contains(DEFINES, DISCORD) {
-LIBS += -ldiscord-rpc
+ LIBS += -ldiscord-rpc
}
-#DEFINES += BASSAUDIO
+# Uncomment to enable the BASS audio engine
+# (Recommended for Windows)
+# DEFINES += BASSAUDIO
contains(DEFINES, BASSAUDIO) {
-LIBS += -lbass
+ LIBS += -lbass
+ LIBS += -lbassopus
}
-#DEFINES += QTAUDIO
+# Uncomment to enable the Qt audio engine
+# (Recommended for non-Windows platforms)
+# DEFINES += QTAUDIO
contains(DEFINES, QTAUDIO) {
-QT += multimedia
+ QT += multimedia
+}
+
+AUDIO_DEFINES = $$find(DEFINES, BASSAUDIO) $$find(DEFINES, QTAUDIO)
+count(AUDIO_DEFINES, 0) {
+ warning("No audio system selected. Your build will not have audio.")
}
-contains(CONFIG, qml_debug) {
-DEFINES += DEBUG_NETWORK
+count(AUDIO_DEFINES, 2) {
+ error("More than one audio system selected.")
}
macx:LIBS += -framework CoreFoundation -framework Foundation -framework CoreServices
@@ -46,16 +55,16 @@ CONFIG += c++14
RESOURCES += resources.qrc
-TRANSLATIONS = resource/translations/ao_en.ts \
- resource/translations/ao_jp.ts \
- resource/translations/ao_de.ts \
- resource/translations/ao_ru.ts \
- resource/translations/ao_es.ts \
- resource/translations/ao_pt.ts \
- resource/translations/ao_pl.ts
+TRANSLATIONS = resource/translations/ao_en.ts \
+ resource/translations/ao_jp.ts \
+ resource/translations/ao_de.ts \
+ resource/translations/ao_ru.ts \
+ resource/translations/ao_es.ts \
+ resource/translations/ao_pt.ts \
+ resource/translations/ao_pl.ts
-win32:RC_ICONS = resource/logo.ico
-macx:ICON = resource/logo.icns
+win32:RC_ICONS = resource/logo_ao2.ico
+macx:ICON = resource/logo_ao2.icns
android:DISTFILES += \
android/AndroidManifest.xml \
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..72cfa8fd
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,44 @@
+## Compiling
+
+The traditional route is by undergoing the [AO2 Rite of Passage](https://gist.github.com/oldmud0/6c645bd1667370c3e92686f7d0642c38).
+
+However, these days it is easy to get away with using the default Qt toolchain on any platform, which creates a dynamic executable. (Don't forget to invoke windeployqt when creating a release.)
+
+### Dependencies
+
+- [BASS](http://un4seen.com) (optional; may use Qt Multimedia instead)
+- [Discord Rich Presence](https://github.com/discordapp/discord-rpc) (optional)
+
+## Release instructions
+
+Follow these steps to make a new full release:
+
+- Set a new AO version in the `.pro` file and in `aoapplication.h`.
+- Compile the project.
+- Commit the version bump and and create a tag for the commit.
+- Rename the executable to `Attorney_Online`.
+- Create a temp directory.
+- Copy a fresh `base` folder to the temp dir. Ensure that the timestamps are consistent.
+ - Ignore this step if creating a client-only release.
+- Copy the repository's `base` folder to the temp dir.
+- Append `.sample` to the names of all `.ini` files, including `serverlist.txt`.
+- Copy the game executable to the temp dir.
+- Copy `bass.dll`, `discord-rpc.dll`, and `qapng.dll` if applicable.
+- Copy `README.md` as `README.md.txt` with CRLF line endings.
+- Copy `LICENSE` as `LICENSE.txt` with CRLF line endings.
+- Compress the contents of the temp dir to an archive with maximum compression, but
+ be sure that the contents are placed inside the root directory of the archive and not
+ within a subdirectory.
+- Compute the SHA-1 hash of the archive.
+- Upload the archive to the Wasabi bucket and an additional mirror (e.g. MEGA or OneDrive)
+ (if this is a full release).
+- Publish a GitHub release and upload the archive there (if this is a client-only release).
+- Add the new version to the `program.json` manifest for the respective platform
+ (if this is a client-only release).
+- Update the following on the website for the respective platform:
+ - Full download links (Wasabi and mirror)
+ - Client download link
+ - Full download hash
+ - Client download hash
+
+Repeat for each platform (currently 32-bit Windows and 64-bit Linux). Once you're done, don't forget to announce your release!
diff --git a/README.md b/README.md
index 1abd8dff..2f5341d3 100644
--- a/README.md
+++ b/README.md
@@ -2,231 +2,7 @@
[Attorney Online](https://aceattorneyonline.com) is an online version of the world-renowned courtroom drama simulator that allows you to create and play out cases in an off-the-cuff format.
-## Introduction for beginners
-
-You may already be familiar with roleplaying in forums, Roll20, and/or [AAO](http://aaonline.fr/) (the online casemaker). In this sense, Attorney Online is nothing more than a medium - an animated chatroom client - that allows cases to be played out as if it were an Ace Attorney game.
-
-Not unlike other roleplaying games, cases can last an absurd amount of time (between 4 to 6 hours) and generally follow a roleplaying format directed by a case sheet.
-
-An implied expectation for fast typing and real-time communication may seem daunting at first, but due to the number of people in the courtroom, things get hectic very quickly even with only a few people talking. Therefore, you should not feel pressured to talk constantly: only when you have the attention of the court (or when you have an objection to make) should you feel the need to speak.
-
-It is recommended, but not strictly necessary, to have played an Ace Attorney game before creating your own case. You should also try to spectate or take part in a community case in order to get a grasp of how cases are done in practice.
-
----
-
-## Basic features
-
-### In-character chat
-
-Type in a message in the gray box under the viewport, select an emote, and press Enter.
-
-### Emotes
-
-An emote represents a set of animations played while the character is speaking and idle. Some emotes also contain a preanimation, which is played before the text is said by the character.
-
-### Interjections (shouts)
-
-Select an interjection to toggle it. When you send a message, it will interrupt all other dialogue and interject with your message.
-
-### Out-of-character chat
-
-This is a general-purpose chat isolated within areas to discuss matters without interrupting cases. You must enter a name before chatting.
-
-### Music list
-
-Double-click a track to play it. Some servers automatically loop the track. Green tracks are available locally; red tracks are not.
-
-### Areas
-
-Servers have multiple areas to hold multiple cases simultaneously. Double-click an area in the music list to switch to it. (The reason that
-areas are in the music list is a historical one.)
-
-### Judge controls
-
-The judge can set health bars and play the Witness Testimony, Cross Examination, Guilty, and Not Guilty animations.
-
-### Mod calls
-
-Calling a mod notifies moderators currently in the server of an incident. (Mod call reasons require 2.6+ server-side support.) Logged-in moderators can toggle the Guard option to be notified of mod calls.
-
-### Muting
-
-Click on a character in the mute list to ignore any in-character chat from the specified character.
-
-### Positions
-
-All characters have a default position within the courtroom, but they can nonetheless be changed within the interface.
-
-Available positions:
-
-- `def` - Defense
-- `pro` - Prosecution
-- `hld` - Helper defense
-- `hlp` - Helper prosecution
-- `jud` - Judge
-- `wit` - Witness
-- `jur` - Juror (2.6+)
-- `sea` - Seance (2.6+)
-
-## Advanced features
-
-### Markup language
-
-2.6.0 introduces a markup language for in-character chat. It does not require server-side support.
-
-#### Color
-
-Wrapping text with these characters will set the text inside of them to the associated color.
-
-- `(` and `)` (parentheses) - blue
-- \` (backtick) - green
-- `|` (vertical bar) - orange
-- `[` and `]` (square brackets) - grey
-
-#### Speed
-
-Type `{` to slow down the text a bit, and `}` to speed it up. This takes effect after the character has been typed, so the text may take up different speeds at different points. Both of these can be stacked up to three times, and even against each other.
-
-Example:
-```
-Hello there! This text goes at normal speed.} Now, it's a bit faster!{ Now, it's back to normal.}}} Now it goes at maximum speed! {{Now it's only a little bit faster than normal.
-```
-
-#### Position
-
-If you begin a message with `~~` (two tildes), the two tildes are removed and the message is centered.
-
-### Pairing (2.6+)
-
-If two players are in the same position and select each other's characters using the in-game pair list (or with `/pair [id]`), they will appear alongside each other. You can set the offset of your character using the provided spinbox (or with `/offset [percentage]`).
-
-### Screenflash (2.6+)
-
-Placing a `$` (dollar symbol) at any point in the message will cause a white flash to appear at that point, and the symbol will disappear. You can do this multiple times in one message and stack it up with any other markup symbol. The flash will be silent, unlike the equivalent button.
-
-### Screenshake (2.6+)
-
-Placing an `@` (at symbol) at any point in the message will cause the screen to shake at that point, and the symbol will disappear. You can do this multiple times in one message and stack it up with any other markup symbol (including the screenflash).
-
-### Non-interrupting preanimations (2.6+)
-
-When checked, this will force text to immediately begin displaying without waiting for the preanimation to finish.
-
-### Custom IC names (shownames) (2.6+)
-
-You can set a custom in-character name using the provided text box. An option in the interface (or `/force_nonint_pres`) is also present to disable custom IC names for other players to prevent impersonation.
-
-### Extended area support (2.6+)
-
-Areas can be listed by clicking the A/M button (or `/switch_am`). The statuses of such areas are displayed (and updated automatically) if the server has 2.6+ support.
-
----
-
-## Upgrade guide for 2.6
-
-2.6 inherits features from the Case Café custom client and server. Old themes and servers will still work, but they will not expose the new additions to players.
-
-### Server
-
-2.6 support has only been developed for tsuserver3. serverD is currently not equipped at all for such support.
-
-- Apply the new code changes.
-- In `areas.yaml`:
- - You may add `shouts_allowed` to any of the areas to enable / disable shouts (and judge buttons, and realisation). By default, it's `shouts_allowed: true`.
- - You may add `jukebox` to any of the areas to enable the jukebox in there, but you can also use `/jukebox_toggle` in game as a mod to do the same thing. By default, it's `jukebox: false`.
- - You may add `showname_changes_allowed` to any of the areas to allow custom shownames used in there. If it's forbidden, players can't send messages or change music as long as they have a custom name set. By default, it's `showname_changes_allowed: false`.
- - You may add `abbreviation` to override the server-generated abbreviation of the area. Instead of area numbers, this server-pack uses area abbreviations in server messages for easier understanding (but still uses area IDs in commands, of course). No default here, but here is an example: `abbreviation: SIN` gives the area the abbreviation of 'SIN'.
- - You may add `noninterrupting_pres` to force users to use non-interrupting pres only. 2.6 users will see the pres play as the text goes; pre-2.6 users will not see pres at all. The default is `noninterrupting_pres: false`.
-
-### Client themes
-
-- You'll need the following, additional images:
- - `notguilty.gif` - Not Guilty verdict animation
- - `guilty.gif` - Guilty verdict animation
- - `notguilty.png` - Not Guilty button
- - `guilty.png` - Guilty button
- - `pair_button.png` - Pair button
- - `pair_button_pressed.png` - Pair button (selected)
-- In your `courtroom_sounds.ini`:
- - Add a sound effect for `not_guilty`, for example: `not_guilty = sfx-notguilty.wav`.
- - Add a sound effect for `guilty`, for example: `guilty = sfx-guilty.wav`.
- - Add a sound effect for the case alerts. They work similarly to modcall alerts, or callword alerts. For example: `case_call = sfx-triplegavel-soj.wav`.
-- In your `courtroom_design.ini`, place the following new UI elements as desired:
- - `log_limit_label`, which is a simple text that explains what the spinbox with the numbers is. Needs an X, Y, width, height number.
- - `log_limit_spinbox`, which is the spinbox for the log limit, allowing you to set the size of the log limit in-game. Needs the same stuff as above.
- - `ic_chat_name`, which is an input field for your custom showname. Needs the same stuff.
- - `ao2_ic_chat_name`, which is the same as above, but comes into play when the background has a desk.
- - Further comments on this: all `ao2_` UI elements come into play when the background has a desk. However, in AO2 nowadays, it's customary for every background to have a desk, even if it's just an empty gif. So you most likely have never seen the `ao2_`-less UI elements ever come into play, unless someone mis-named a desk or something.
- - `showname_enable` is a checkbox that toggles whether you should see shownames or not. This does not influence whether you can USE custom shownames or not, so you can have it off, while still showing a custom showname to everyone else. Needs X, Y, width, height as usual.
- - `settings` is a plain button that takes up the OS's looks, like the 'Call mod' button. Takes the same arguments as above.
- - You can also just type `/settings` in OOC.
- - `char_search` is a text input box on the character selection screen, which allows you to filter characters down to name. Needs the same arguments.
- - `char_passworded` is a checkbox, that when ticked, shows all passworded characters on the character selection screen. Needs the same as above.
- - `char_taken` is another checkbox, that does the same, but for characters that are taken.
- - `not_guilty` is a button similar to the CE / WT buttons, that if pressed, plays the Not Guilty verdict animation. Needs the same arguments.
- - `guilty` is similar to `not_guilty`, but for the Guilty verdict.
- - `pair_button` is a toggleable button, that shows and hides the pairing list and the offset spinbox. Works similarly to the mute button.
- - `pair_list` is a list of all characters in alphabetical order, shown when the user presses the Pair button. If a character is clicked on it, it is selected as the character the user wants to pair up with.
- - `pair_offset_spinbox` is a spinbox that allows the user to choose between offsets of -100% to 100%.
- - `switch_area_music` is a button with the text 'A/M', that toggles between the music list and the areas list. Though the two are different, they are programmed to take the same space.
- - `pre_no_interrupt` is a checkbox with the text 'No Intrpt', that toggles whether preanimations should delay the text or not.
- - `area_free_color` is a combination of red, green, and blue values ranging from 0 to 255. This determines the colour of the area in the Area list if it's free, and has a status of `IDLE`.
- - `area_lfp_color` determines the colour of the area if its status is `LOOKING-FOR-PLAYERS`.
- - `area_casing_color` determines the colour of the area if its status is `CASING`.
- - `area_recess_color` determines the colour of the area if its status is `RECESS`.
- - `area_rp_color` determines the colour of the area if its status is `RP`.
- - `area_gaming_color` determines the colour of the area if its status is `GAMING`.
- - `area_locked_color` determines the colour of the area if it is locked, regardless of status.
- - `ooc_default_color` determines the colour of the username in the OOC chat if the message doesn't come from the server.
- - `ooc_server_color` determines the colour of the username if the message arrived from the server.
- - `casing_button` is a button with the text 'Casing' that when clicked, brings up the Case Announcements dialog. You can give the case a name, and tick whom do you want to alert. You need to be a CM for it to go through. Only people who have at least one of the roles ticked will get the alert.
- - `casing` is a checkbox with the text 'Casing'. If ticked, you will get the case announcements alerts you should get, in accordance to the above. In the settings, you can change your defaults on the 'Casing' tab. (That's a buncha things titled 'Casing'!)
-
----
-
-## Compiling
-
-The traditional route is by undergoing the [AO2 Rite of Passage](https://gist.github.com/oldmud0/6c645bd1667370c3e92686f7d0642c38). Recently, however, it has become more feasible to get away with a dynamic compilation, which is much easier for beginners and requires less setup.
-
-### Dependencies
-
-- [QtApng](https://github.com/Skycoder42/QtApng)
-- [BASS](http://un4seen.com) (proprietary, but will become optional in the future; see #35)
-- [Discord Rich Presence](https://github.com/discordapp/discord-rpc)
-
-## Release instructions
-
-Follow these steps to make a new full release:
-
-- Set a new AO version in the `.pro` file and in `aoapplication.h`.
-- Compile the project.
-- Commit the version bump and and create a tag for the commit.
-- Rename the executable to `Attorney_Online`.
-- Create a temp directory.
-- Copy a fresh `base` folder to the temp dir. Ensure that the timestamps are consistent.
- - Ignore this step if creating a client-only release.
-- Copy the repository's `base` folder to the temp dir.
-- Append `.sample` to the names of all `.ini` files, including `serverlist.txt`.
-- Copy the game executable to the temp dir.
-- Copy `bass.dll`, `discord-rpc.dll`, and `qapng.dll` if applicable.
-- Copy `README.md` as `README.md.txt` with CRLF line endings.
-- Copy `LICENSE` as `LICENSE.txt` with CRLF line endings.
-- Compress the contents of the temp dir to an archive with maximum compression, but
- be sure that the contents are placed inside the root directory of the archive and not
- within a subdirectory.
-- Compute the SHA-1 hash of the archive.
-- Upload the archive to the Wasabi bucket and an additional mirror (e.g. MEGA or OneDrive)
- (if this is a full release).
-- Publish a GitHub release and upload the archive there (if this is a client-only release).
-- Add the new version to the `program.json` manifest for the respective platform
- (if this is a client-only release).
-- Update the following on the website for the respective platform:
- - Full download links (Wasabi and mirror)
- - Client download link
- - Full download hash
- - Client download hash
-
-Repeat for each platform (currently 32-bit Windows and 64-bit Linux). Once you're done, don't forget to announce your release!
+**[Refer to the docs](https://github.com/AttorneyOnline/docs/blob/master/docs/index.md) for more information.**
## Credits
@@ -244,6 +20,8 @@ Modifications copyright (c) 2017-2018 oldmud0
Case Café additions copyright (c) 2018 Cerapter
+Killing Fever Online additions copyright (c) 2019 Crystalwarrior
+
### Qt
This project uses Qt 5, which is licensed under the [GNU Lesser General Public License](https://www.gnu.org/licenses/lgpl-3.0.txt) with [certain licensing restrictions and exceptions](https://www.qt.io/qt-licensing-terms/). To comply with licensing requirements for static linking, object code is available if you would like to relink with an alternative version of Qt, and the source code for Qt may be found at https://github.com/qt/qtbase, http://code.qt.io/cgit/, or at https://qt.io.
diff --git a/base/background/gs4/defensedesk.png b/base/background/gs4/defensedesk.png
deleted file mode 100644
index 00a3ffb6..00000000
--- a/base/background/gs4/defensedesk.png
+++ /dev/null
Binary files differ
diff --git a/base/background/gs4/prosecutiondesk.png b/base/background/gs4/prosecutiondesk.png
deleted file mode 100644
index 9f626733..00000000
--- a/base/background/gs4/prosecutiondesk.png
+++ /dev/null
Binary files differ
diff --git a/base/background/gs4/stand.png b/base/background/gs4/stand.png
deleted file mode 100644
index 3719e36a..00000000
--- a/base/background/gs4/stand.png
+++ /dev/null
Binary files differ
diff --git a/base/config.ini b/base/config.ini
deleted file mode 100644
index 1e8705fa..00000000
--- a/base/config.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-theme = default
-blip_rate = 1
-blank_blip = false
-default_music = 50
-default_sfx = 50
-default_blip = 50
-discord = true
-ic_scroll_down = false
-; master = master.aceattorneyonline.com
-; ooc_name = Phoenix \ No newline at end of file
diff --git a/base/misc/default/chatbox.png b/base/misc/default/chatbox.png
new file mode 100644
index 00000000..0c3bae1e
--- /dev/null
+++ b/base/misc/default/chatbox.png
Binary files differ
diff --git a/base/misc/default/config.ini b/base/misc/default/config.ini
new file mode 100644
index 00000000..b3bf9a81
--- /dev/null
+++ b/base/misc/default/config.ini
@@ -0,0 +1,59 @@
+c0 = 255, 255, 255
+c0_name = White
+c0_talking = 1
+
+c1 = 0, 255, 0
+c1_name = Green
+c1_start = `
+c1_end = `
+c1_remove = 1
+c1_talking = 1
+
+c2 = 255, 0, 0
+c2_name = Red
+c2_start = ~
+c2_end = ~
+c2_remove = 1
+c2_talking = 1
+
+c3 = 255, 165, 0
+c3_name = Orange
+c3_start = |
+c3_end = |
+c3_remove = 1
+c3_talking = 0
+
+c4 = 45, 150, 255
+c4_name = Blue
+c4_start = (
+c4_end = )
+c4_remove = 0
+c4_talking = 0
+
+c5 = 255, 255, 0
+c5_name = Yellow
+c5_start = º
+c5_end = º
+c5_remove = 1
+c5_talking = 1
+
+c6 = 255, 192, 203
+c6_name = Pink
+c6_start = №
+c6_end = №
+c6_remove = 1
+c6_talking = 1
+
+c7 = 0, 255, 255
+c7_name = Cyan
+c7_start = √
+c7_end = √
+c7_remove = 1
+c7_talking = 1
+
+c8 = 187, 187, 187
+c8_name = Gray
+c8_start = [
+c8_end = ]
+c8_remove = 0
+c8_talking = 1 \ No newline at end of file
diff --git a/base/misc/default/holdit.opus b/base/misc/default/holdit.opus
new file mode 100644
index 00000000..a454be83
--- /dev/null
+++ b/base/misc/default/holdit.opus
Binary files differ
diff --git a/base/misc/default/holdit_bubble.gif b/base/misc/default/holdit_bubble.gif
new file mode 100644
index 00000000..536f8cd7
--- /dev/null
+++ b/base/misc/default/holdit_bubble.gif
Binary files differ
diff --git a/base/misc/default/objection.opus b/base/misc/default/objection.opus
new file mode 100644
index 00000000..7e15d05e
--- /dev/null
+++ b/base/misc/default/objection.opus
Binary files differ
diff --git a/base/misc/default/objection_bubble.gif b/base/misc/default/objection_bubble.gif
new file mode 100644
index 00000000..22c2169b
--- /dev/null
+++ b/base/misc/default/objection_bubble.gif
Binary files differ
diff --git a/base/misc/default/takethat.opus b/base/misc/default/takethat.opus
new file mode 100644
index 00000000..2f143e12
--- /dev/null
+++ b/base/misc/default/takethat.opus
Binary files differ
diff --git a/base/misc/default/takethat_bubble.gif b/base/misc/default/takethat_bubble.gif
new file mode 100644
index 00000000..795552a8
--- /dev/null
+++ b/base/misc/default/takethat_bubble.gif
Binary files differ
diff --git a/base/sounds/general/adminhelp.ogg b/base/sounds/general/adminhelp.ogg
deleted file mode 100644
index 704c0fd6..00000000
--- a/base/sounds/general/adminhelp.ogg
+++ /dev/null
Binary files differ
diff --git a/base/sounds/general/case_announced.ogg b/base/sounds/general/case_announced.ogg
deleted file mode 100644
index 1e9c3d4e..00000000
--- a/base/sounds/general/case_announced.ogg
+++ /dev/null
Binary files differ
diff --git a/base/sounds/music/failed_login.opus b/base/sounds/music/failed_login.opus
deleted file mode 100644
index 33532ee5..00000000
--- a/base/sounds/music/failed_login.opus
+++ /dev/null
Binary files differ
diff --git a/base/themes b/base/themes
-Subproject 6e1317ed93a9a4831047aa151c28742b1dd8afb
+Subproject 8de30fc0fa0e1492a29dad0e839764ca44168cb
diff --git a/include/aoapplication.h b/include/aoapplication.h
index 5646ddeb..f4685eca 100644
--- a/include/aoapplication.h
+++ b/include/aoapplication.h
@@ -1,383 +1,454 @@
-#ifndef AOAPPLICATION_H
-#define AOAPPLICATION_H
-
-#include "aopacket.h"
-#include "datatypes.h"
-#include "discord_rich_presence.h"
-
-#include <QApplication>
-#include <QFile>
-#include <QSettings>
-#include <QVector>
-
-#include <QDebug>
-#include <QDesktopWidget>
-#include <QRect>
-
-#include <QCryptographicHash>
-
-#include <QDir>
-#include <QStandardPaths>
-
-#include <QColor>
-#include <QScreen>
-#include <QStringList>
-#include <QTextStream>
-#ifdef QTAUDIO
-#include <QAudioDeviceInfo>
-#endif
-
-#include <QFuture>
-#include <QThread>
-#include <QThreadPool>
-#include <QtConcurrent/QtConcurrent>
-
-class NetworkManager;
-class Lobby;
-class Courtroom;
-class AOApplication : public QApplication {
- Q_OBJECT
-
-public:
- AOApplication(int &argc, char **argv);
- ~AOApplication();
-
- NetworkManager *net_manager;
- Lobby *w_lobby;
- Courtroom *w_courtroom;
- AttorneyOnline::Discord *discord;
-
- bool lobby_constructed = false;
- bool courtroom_constructed = false;
-
- void construct_lobby();
- void destruct_lobby();
-
- void construct_courtroom();
- void destruct_courtroom();
-
- bool is_music_track(QString trackname);
-
- void ms_packet_received(AOPacket *p_packet);
- void server_packet_received(AOPacket *p_packet);
-
- void send_ms_packet(AOPacket *p_packet);
- void send_server_packet(AOPacket *p_packet, bool encoded = true);
-
- void call_settings_menu();
- void call_announce_menu(Courtroom *court);
-
- /////////////////server metadata//////////////////
-
- unsigned int s_decryptor = 5;
- bool encryption_needed = true;
-
- bool yellow_text_enabled = false;
- bool prezoom_enabled = false;
- bool flipping_enabled = false;
- bool custom_objection_enabled = false;
- bool improved_loading_enabled = false;
- bool desk_mod_enabled = false;
- bool evidence_enabled = false;
- bool cccc_ic_support_enabled = false;
- bool arup_enabled = false;
- bool casing_alerts_enabled = false;
- bool modcall_reason_enabled = false;
- bool looping_sfx_support_enabled = false;
-
- ///////////////loading info///////////////////
-
- // player number, it's hardly used but might be needed for some old servers
- int s_pv = 0;
-
- QString server_software = "";
-
- int char_list_size = 0;
- int loaded_chars = 0;
- int generated_chars = 0;
- int evidence_list_size = 0;
- int loaded_evidence = 0;
- int music_list_size = 0;
- int loaded_music = 0;
- int area_count = 0;
- bool courtroom_loaded = false;
-
- //////////////////versioning///////////////
-
- int get_release() const { return RELEASE; }
- int get_major_version() const { return MAJOR_VERSION; }
- int get_minor_version() const { return MINOR_VERSION; }
- QString get_version_string();
-
- ///////////////////////////////////////////
-
- void set_favorite_list();
- QVector<server_type> &get_favorite_list() { return favorite_list; }
- void add_favorite_server(int p_server);
-
- void set_server_list();
- QVector<server_type> &get_server_list() { return server_list; }
-
- // reads the theme from config.ini and sets it accordingly
- void reload_theme();
-
- // Returns the character the player has currently selected
- QString get_current_char();
-
- // implementation in path_functions.cpp
- QString get_base_path();
- QString get_data_path();
- QString get_theme_path(QString p_file);
- QString get_default_theme_path(QString p_file);
- QString get_custom_theme_path(QString p_theme, QString p_file);
- QString get_character_path(QString p_char, QString p_file);
- QString get_sounds_path(QString p_file);
- QString get_music_path(QString p_song);
- QString get_background_path(QString p_file);
- QString get_default_background_path(QString p_file);
- QString get_evidence_path(QString p_file);
- QString get_case_sensitive_path(QString p_file);
-
- ////// Functions for reading and writing files //////
- // Implementations file_functions.cpp
-
- // Instead of reinventing the wheel, we'll use a QSettings class.
- QSettings *configini;
-
- // Reads the theme from config.ini and loads it into the current_theme
- // variable
- QString read_theme();
-
- // Returns the value of ooc_name in config.ini
- QString get_ooc_name();
-
- // Returns the blip rate from config.ini
- int read_blip_rate();
-
- // Returns true if blank blips is enabled in config.ini and false otherwise
- bool get_blank_blip();
-
- // Returns true if looping sound effects are enabled in the config.ini
- bool get_looping_sfx();
-
- // Returns true if kill music on object is enabled in the config.ini
- bool get_objectmusic();
-
- // Returns the value of default_music in config.ini
- int get_default_music();
-
- // Returns the value of default_sfx in config.ini
- int get_default_sfx();
-
- // Returns the value of default_blip in config.ini
- int get_default_blip();
-
- // Returns the value of whether Discord should be enabled on startup
- // from the config.ini.
- bool is_discord_enabled();
-
- // Returns the value of whether shaking and flashing should be enabled.
- // from the config.ini.
- bool is_shakeandflash_enabled();
-
- // Returns whether evidence should be maintained ic
- bool is_keepevi_enabled();
-
- // Returns the value of the maximum amount of lines the IC chatlog
- // may contain, from config.ini.
- int get_max_log_size();
-
- // Gets the punctuation delay modifier
- bool get_pundelay();
-
- //Gets whether slower text speed is enabled
- bool get_slower_blips();
- // Returns whether the log should go upwards (new behaviour)
- // or downwards (vanilla behaviour).
- bool get_log_goes_downwards();
-
- // Returns the username the user may have set in config.ini.
- QString get_default_username();
-
- // Returns the audio device used for the client.
- QString get_audio_output_device();
-#ifdef QTAUDIO
- QAudioDeviceInfo QtAudioDevice;
-#endif
-
- // Returns whether the user would like to have custom shownames on by default.
- bool get_showname_enabled_by_default();
-
- // Returns the list of words in callwords.ini
- QStringList get_call_words();
-
- // Appends the argument string to serverlist.txt
- void write_to_serverlist_txt(QString p_line);
-
- // Returns the contents of serverlist.txt
- QVector<server_type> read_serverlist_txt();
-
- // Returns the value of p_identifier in the design.ini file in p_design_path
- QString read_design_ini(QString p_identifier, QString p_design_path);
-
- // Returns the coordinates of widget with p_identifier from p_file
- QPoint get_button_spacing(QString p_identifier, QString p_file);
-
- // Returns the dimensions of widget with specified identifier from p_file
- pos_size_type get_element_dimensions(QString p_identifier, QString p_file);
-
- // Returns the name of the font with p_identifier from p_file
- QString get_font_name(QString p_identifier, QString p_file);
-
- // Returns the value of font_size with p_identifier from p_file
- int get_font_size(QString p_identifier, QString p_file);
-
- // Returns the color with p_identifier from p_file
- QColor get_color(QString p_identifier, QString p_file);
-
- // Returns the colour from the misc folder.
- QColor get_chat_color(QString p_identifier, QString p_chat);
-
- // Returns the sfx with p_identifier from sounds.ini in the current theme path
- QString get_sfx(QString p_identifier);
-
- // Figure out if we can opus this or if we should fall back to wav
- QString get_sfx_suffix(QString sound_to_check);
-
- // figure out if we can find what prefix this song uses
- QString get_music_prefix(QString song_to_check);
-
- // Can we use APNG for this? If not, WEBP? if not, GIF? If not, fall back to a
- // gif.
- QString get_image_suffix(QString path_to_check);
-
- // Returns the value of p_search_line within target_tag and terminator_tag
- QString read_char_ini(QString p_char, QString p_search_line,
- QString target_tag);
-
- // Returns the side of the p_char character from that characters ini file
- QString get_char_side(QString p_char);
-
- // Returns the showname from the ini of p_char
- QString get_showname(QString p_char);
-
- // Returns the value of chat from the specific p_char's ini file
- QString get_chat(QString p_char);
-
- // Returns the value of shouts from the specified p_char's ini file
- QString get_char_shouts(QString p_char);
-
- // Returns the preanim duration of p_char's p_emote
- int get_preanim_duration(QString p_char, QString p_emote);
-
- // Same as above, but only returns if it has a % in front(refer to Preanims
- // section in the manual)
- int get_ao2_preanim_duration(QString p_char, QString p_emote);
-
- // Not in use
- int get_text_delay(QString p_char, QString p_emote);
-
- // Returns the custom realisation used by the character.
- QString get_custom_realization(QString p_char);
-
- // Returns the name of p_char
- QString get_char_name(QString p_char);
-
- // Returns the total amount of emotes of p_char
- int get_emote_number(QString p_char);
-
- // Returns the emote comment of p_char's p_emote
- QString get_emote_comment(QString p_char, int p_emote);
-
- // Returns if an emote loops it's SFX
- QString get_sfx_looping(QString p_char, int p_emote);
-
- // Returns if an emote has a frame specific SFX for it
- QString get_frame_sfx_name(QString p_char, QString p_emote, int n_frame);
-
- // Returns if an emote has a frame specific SFX for it
- QString get_realization_frame(QString p_char, QString p_emote, int n_frame);
-
- // Returns if an emote has a frame specific SFX for it
- QString get_screenshake_frame(QString p_char, QString p_emote, int n_frame);
-
- // Returns the base name of p_char's p_emote
- QString get_emote(QString p_char, int p_emote);
-
- // Returns the preanimation name of p_char's p_emote
- QString get_pre_emote(QString p_char, int p_emote);
-
- // Returns the sfx of p_char's p_emote
- QString get_sfx_name(QString p_char, int p_emote);
-
- // Not in use
- int get_sfx_delay(QString p_char, int p_emote);
-
- // Returns the modifier for p_char's p_emote
- int get_emote_mod(QString p_char, int p_emote);
-
- // Returns the desk modifier for p_char's p_emote
- int get_desk_mod(QString p_char, int p_emote);
-
- // Returns p_char's gender
- QString get_gender(QString p_char);
-
- // ======
- // These are all casing-related settings.
- // ======
-
- // Returns if the user has casing alerts enabled.
- bool get_casing_enabled();
-
- // Returns if the user wants to get alerts for the defence role.
- bool get_casing_defence_enabled();
-
- // Same for prosecution.
- bool get_casing_prosecution_enabled();
-
- // Same for judge.
- bool get_casing_judge_enabled();
-
- // Same for witnesses.
- bool get_casing_wit_enabled();
-
- // Same for juror.
- bool get_casing_juror_enabled();
-
- // Same for steno.
- bool get_casing_steno_enabled();
-
- // Same for CM.
- bool get_casing_cm_enabled();
-
- // Get the message for the CM for casing alerts.
- QString get_casing_can_host_cases();
-
- // Get if html for ic log is enabled
- bool get_colored_iclog_enabled();
-
- // Get if ic log mirror is enabled
- bool get_iclmir_enabled();
-
- // Get if only inline coloring should be shown in log
- bool colorlog_restricted_enabled();
-
-private:
- const int RELEASE = 2;
- const int MAJOR_VERSION = 7;
- const int MINOR_VERSION = 0;
-
- QString current_theme = "default";
-
- QVector<server_type> server_list;
- QVector<server_type> favorite_list;
-
-private slots:
- void ms_connect_finished(bool connected, bool will_retry);
-
-public slots:
- void server_disconnected();
- void loading_cancelled();
-};
-
-#endif // AOAPPLICATION_H
+#ifndef AOAPPLICATION_H
+#define AOAPPLICATION_H
+
+#include "aopacket.h"
+#include "datatypes.h"
+#include "discord_rich_presence.h"
+
+#include <QApplication>
+#include <QFile>
+#include <QSettings>
+#include <QVector>
+
+#include <QDebug>
+#include <QDesktopWidget>
+#include <QRect>
+
+#include <QCryptographicHash>
+
+#include <QDir>
+#include <QStandardPaths>
+
+#include <QColor>
+#include <QScreen>
+#include <QStringList>
+#include <QTextStream>
+#ifdef QTAUDIO
+#include <QAudioDeviceInfo>
+#endif
+
+class NetworkManager;
+class Lobby;
+class Courtroom;
+
+class AOApplication : public QApplication {
+ Q_OBJECT
+
+public:
+ AOApplication(int &argc, char **argv);
+ ~AOApplication();
+
+ NetworkManager *net_manager;
+ Lobby *w_lobby;
+ Courtroom *w_courtroom;
+ AttorneyOnline::Discord *discord;
+
+ bool lobby_constructed = false;
+ bool courtroom_constructed = false;
+
+ void construct_lobby();
+ void destruct_lobby();
+
+ void construct_courtroom();
+ void destruct_courtroom();
+
+ void ms_packet_received(AOPacket *p_packet);
+ void server_packet_received(AOPacket *p_packet);
+
+ void send_ms_packet(AOPacket *p_packet);
+ void send_server_packet(AOPacket *p_packet, bool encoded = true);
+
+ void call_settings_menu();
+ void call_announce_menu(Courtroom *court);
+
+ /////////////////server metadata//////////////////
+
+ unsigned int s_decryptor = 5;
+ bool encryption_needed = true;
+
+ bool yellow_text_enabled = false;
+ bool prezoom_enabled = false;
+ bool flipping_enabled = false;
+ bool custom_objection_enabled = false;
+ bool improved_loading_enabled = false;
+ bool desk_mod_enabled = false;
+ bool evidence_enabled = false;
+ bool cccc_ic_support_enabled = false;
+ bool arup_enabled = false;
+ bool casing_alerts_enabled = false;
+ bool modcall_reason_enabled = false;
+ bool looping_sfx_support_enabled = false;
+ bool additive_enabled = false;
+ bool effects_enabled = false;
+
+ ///////////////loading info///////////////////
+
+ // player number, it's hardly used but might be needed for some old servers
+ int s_pv = 0;
+
+ QString server_software = "";
+
+ int char_list_size = 0;
+ int loaded_chars = 0;
+ int generated_chars = 0;
+ int evidence_list_size = 0;
+ int loaded_evidence = 0;
+ int music_list_size = 0;
+ int loaded_music = 0;
+
+ bool courtroom_loaded = false;
+
+ //////////////////versioning///////////////
+
+ int get_release() const { return RELEASE; }
+ int get_major_version() const { return MAJOR_VERSION; }
+ int get_minor_version() const { return MINOR_VERSION; }
+ QString get_version_string();
+
+ ///////////////////////////////////////////
+
+ void set_favorite_list();
+ QVector<server_type> &get_favorite_list() { return favorite_list; }
+ void add_favorite_server(int p_server);
+
+ void set_server_list();
+ QVector<server_type> &get_server_list() { return server_list; }
+
+ // reads the theme from config.ini and sets it accordingly
+ void reload_theme();
+
+ // Returns the character the player has currently selected
+ QString get_current_char();
+
+ // implementation in path_functions.cpp
+ QString get_base_path();
+ QString get_data_path();
+ QString get_theme_path(QString p_file);
+ QString get_default_theme_path(QString p_file);
+ QString get_custom_theme_path(QString p_theme, QString p_file);
+ QString get_character_path(QString p_char, QString p_file);
+ QString get_sounds_path(QString p_file);
+ QString get_music_path(QString p_song);
+ QString get_background_path(QString p_file);
+ QString get_default_background_path(QString p_file);
+ QString get_evidence_path(QString p_file);
+ QString get_case_sensitive_path(QString p_file);
+
+ ////// Functions for reading and writing files //////
+ // Implementations file_functions.cpp
+
+ // Instead of reinventing the wheel, we'll use a QSettings class.
+ QSettings *configini;
+
+ // Reads the theme from config.ini and loads it into the current_theme
+ // variable
+ QString read_theme();
+
+ // Returns the value of ooc_name in config.ini
+ QString get_ooc_name();
+
+ // Returns the blip rate from config.ini (once per X symbols)
+ int read_blip_rate();
+
+ // Returns true if blank blips is enabled in config.ini and false otherwise
+ bool get_blank_blip();
+
+ // Returns true if looping sound effects are enabled in the config.ini
+ bool get_looping_sfx();
+
+ // Returns true if stop music on objection is enabled in the config.ini
+ bool objection_stop_music();
+
+ // Returns the value of default_music in config.ini
+ int get_default_music();
+
+ // Returns the value of default_sfx in config.ini
+ int get_default_sfx();
+
+ // Returns the value of default_blip in config.ini
+ int get_default_blip();
+
+ // Returns the value of whether Discord should be enabled on startup
+ // from the config.ini.
+ bool is_discord_enabled();
+
+ // Returns the value of whether shaking should be enabled.
+ // from the config.ini.
+ bool is_shake_enabled();
+
+ // Returns the value of whether effects should be enabled.
+ // from the config.ini.
+ bool is_effects_enabled();
+
+ // Returns the value of whether frame-specific effects defined in char.ini
+ // should be sent/received over the network. from the config.ini.
+ bool is_frame_network_enabled();
+
+ // Returns the value of whether colored ic log should be a thing.
+ // from the config.ini.
+ bool is_colorlog_enabled();
+
+ // Returns the value of whether sticky sounds should be a thing.
+ // from the config.ini.
+ bool is_stickysounds_enabled();
+
+ // Returns the value of whether sticky effects should be a thing.
+ // from the config.ini.
+ bool is_stickyeffects_enabled();
+
+ // Returns the value of whether sticky preanims should be a thing.
+ // from the config.ini.
+ bool is_stickypres_enabled();
+
+ // Returns the value of whether custom chatboxes should be a thing.
+ // from the config.ini.
+ // I am increasingly maddened by the lack of dynamic auto-generation system for settings.
+ bool is_customchat_enabled();
+
+ // Returns the value of the maximum amount of lines the IC chatlog
+ // may contain, from config.ini.
+ int get_max_log_size();
+
+ // Returns whether the log should go upwards (new behaviour)
+ // or downwards (vanilla behaviour).
+ bool get_log_goes_downwards();
+
+ // Returns the username the user may have set in config.ini.
+ QString get_default_username();
+
+ // Returns the audio device used for the client.
+ QString get_audio_output_device();
+#ifdef QTAUDIO
+ QAudioDeviceInfo QtAudioDevice;
+#endif
+
+ // Returns whether the user would like to have custom shownames on by default.
+ bool get_showname_enabled_by_default();
+
+ // Returns the list of words in callwords.ini
+ QStringList get_call_words();
+
+ // returns all of the file's lines in a QStringList
+ QStringList get_list_file(QString p_file);
+
+ // Process a file and return its text as a QString
+ QString read_file(QString filename);
+
+ // Write text to file. make_dir would auto-create the directory if it doesn't
+ // exist.
+ bool write_to_file(QString p_text, QString p_file, bool make_dir = false);
+
+ // Append text to the end of the file. make_dir would auto-create the
+ // directory if it doesn't exist.
+ bool append_to_file(QString p_text, QString p_file, bool make_dir = false);
+
+ // Appends the argument string to serverlist.txt
+ void write_to_serverlist_txt(QString p_line);
+
+ // Returns the contents of serverlist.txt
+ QVector<server_type> read_serverlist_txt();
+
+ // Returns the value of p_identifier in the design.ini file in p_design_path
+ QString read_design_ini(QString p_identifier, QString p_design_path);
+
+ // Returns the coordinates of widget with p_identifier from p_file
+ QPoint get_button_spacing(QString p_identifier, QString p_file);
+
+ // Returns the dimensions of widget with specified identifier from p_file
+ pos_size_type get_element_dimensions(QString p_identifier, QString p_file,
+ QString p_char = "");
+
+ // Returns the value to you
+ QString get_design_element(QString p_identifier, QString p_file,
+ QString p_char = "");
+
+ // Returns the name of the font with p_identifier from p_file
+ QString get_font_name(QString p_identifier, QString p_file);
+
+ // Returns the value of font_size with p_identifier from p_file
+ int get_font_size(QString p_identifier, QString p_file);
+
+ // Returns the color with p_identifier from p_file
+ QColor get_color(QString p_identifier, QString p_file);
+
+ // Returns the markdown symbol used for specified p_identifier such as colors
+ QString get_chat_markdown(QString p_identifier, QString p_file);
+
+ // Returns the color from the misc folder.
+ QColor get_chat_color(QString p_identifier, QString p_chat);
+
+ // Returns the sfx with p_identifier from sounds.ini in the current theme path
+ QString get_sfx(QString p_identifier);
+
+ // Figure out if we can opus this or if we should fall back to wav
+ QString get_sfx_suffix(QString sound_to_check);
+
+ // Can we use APNG for this? If not, WEBP? If not, GIF? If not, fall back to
+ // PNG.
+ QString get_image_suffix(QString path_to_check);
+
+ // If this image is static and non-animated, return the supported static image
+ // formats. Currently only PNG.
+ QString get_static_image_suffix(QString path_to_check);
+
+ // Returns the value of p_search_line within target_tag and terminator_tag
+ QString read_char_ini(QString p_char, QString p_search_line,
+ QString target_tag);
+
+ // Returns a QStringList of all key=value definitions on a given tag.
+ QStringList read_ini_tags(QString p_file, QString target_tag = "");
+
+ // Sets the char.ini p_search_line key under tag target_tag to value.
+ void set_char_ini(QString p_char, QString value, QString p_search_line,
+ QString target_tag);
+
+ // Returns the text between target_tag and terminator_tag in p_file
+ QString get_stylesheet(QString p_file);
+
+ // Returns the text between target_tag and terminator_tag in p_file
+ QString get_tagged_stylesheet(QString target_tag, QString p_file);
+
+ // Returns the side of the p_char character from that characters ini file
+ QString get_char_side(QString p_char);
+
+ // Returns the showname from the ini of p_char
+ QString get_showname(QString p_char);
+
+ // Returns the value of chat image from the specific p_char's ini file
+ QString get_chat(QString p_char);
+
+ // Returns the value of chat font from the specific p_char's ini file
+ QString get_chat_font(QString p_char);
+
+ // Returns the value of chat font size from the specific p_char's ini file
+ int get_chat_size(QString p_char);
+
+ // Returns the value of shouts from the specified p_char's ini file
+ QString get_char_shouts(QString p_char);
+
+ // Returns the preanim duration of p_char's p_emote
+ int get_preanim_duration(QString p_char, QString p_emote);
+
+ // Same as above, but only returns if it has a % in front(refer to Preanims
+ // section in the manual)
+ int get_ao2_preanim_duration(QString p_char, QString p_emote);
+
+ // Not in use
+ int get_text_delay(QString p_char, QString p_emote);
+
+ // Get the effects folder referenced by the char.ini, read it and return the
+ // list of filenames in a string
+ QStringList get_theme_effects();
+
+ // Get the theme's effects folder, read it and return the list of filenames in
+ // a string
+ QStringList get_effects(QString p_char);
+
+ // t
+ QString get_effect(QString effect, QString p_char, QString p_folder);
+
+ // Return the effect sound associated with the fx_name in the
+ // misc/effects/<char-defined>/sounds.ini, or theme/effects/sounds.ini.
+ QString get_effect_sound(QString fx_name, QString p_char);
+
+ // Returns the custom realisation used by the character.
+ QString get_custom_realization(QString p_char);
+
+ // Returns the name of p_char
+ QString get_char_name(QString p_char);
+
+ // Returns the total amount of emotes of p_char
+ int get_emote_number(QString p_char);
+
+ // Returns the emote comment of p_char's p_emote
+ QString get_emote_comment(QString p_char, int p_emote);
+
+ // Returns the base name of p_char's p_emote
+ QString get_emote(QString p_char, int p_emote);
+
+ // Returns the preanimation name of p_char's p_emote
+ QString get_pre_emote(QString p_char, int p_emote);
+
+ // Returns the sfx of p_char's p_emote
+ QString get_sfx_name(QString p_char, int p_emote);
+
+ // Returns the blipsound of p_char's p_emote
+ QString get_emote_blip(QString p_char, int p_emote);
+
+ // Returns if the sfx is defined as looping in char.ini
+ QString get_sfx_looping(QString p_char, int p_emote);
+
+ // Returns if an emote has a frame specific SFX for it
+ QString get_sfx_frame(QString p_char, QString p_emote, int n_frame);
+
+ // Returns if an emote has a frame specific SFX for it
+ QString get_flash_frame(QString p_char, QString p_emote, int n_frame);
+
+ // Returns if an emote has a frame specific SFX for it
+ QString get_screenshake_frame(QString p_char, QString p_emote, int n_frame);
+
+ // Not in use
+ int get_sfx_delay(QString p_char, int p_emote);
+
+ // Returns the modifier for p_char's p_emote
+ int get_emote_mod(QString p_char, int p_emote);
+
+ // Returns the desk modifier for p_char's p_emote
+ int get_desk_mod(QString p_char, int p_emote);
+
+ // Returns p_char's gender
+ QString get_gender(QString p_char);
+
+ // ======
+ // These are all casing-related settings.
+ // ======
+
+ // Returns if the user has casing alerts enabled.
+ bool get_casing_enabled();
+
+ // Returns if the user wants to get alerts for the defence role.
+ bool get_casing_defence_enabled();
+
+ // Same for prosecution.
+ bool get_casing_prosecution_enabled();
+
+ // Same for judge.
+ bool get_casing_judge_enabled();
+
+ // Same for juror.
+ bool get_casing_juror_enabled();
+
+ // Same for steno.
+ bool get_casing_steno_enabled();
+
+ // Same for CM.
+ bool get_casing_cm_enabled();
+
+ // Get the message for the CM for casing alerts.
+ QString get_casing_can_host_cases();
+
+ // Get if automatic logging is enabled
+ bool get_auto_logging_enabled();
+
+ // The file name of the log file in base/logs.
+ QString log_filename;
+
+private:
+ const int RELEASE = 2;
+ const int MAJOR_VERSION = 8;
+ const int MINOR_VERSION = 4;
+
+ QString current_theme = "default";
+
+ QVector<server_type> server_list;
+ QVector<server_type> favorite_list;
+
+private slots:
+ void ms_connect_finished(bool connected, bool will_retry);
+
+public slots:
+ void server_disconnected();
+ void loading_cancelled();
+};
+
+#endif // AOAPPLICATION_H
diff --git a/include/aoblipplayer.h b/include/aoblipplayer.h
index 4520120e..5a104718 100644
--- a/include/aoblipplayer.h
+++ b/include/aoblipplayer.h
@@ -3,6 +3,7 @@
#if defined(BASSAUDIO)
#include "bass.h"
+#include "bassopus.h"
#elif defined(QTAUDIO)
#include <QSoundEffect>
#endif
@@ -10,6 +11,7 @@
#include "aoapplication.h"
#include <QDebug>
+#include <QElapsedTimer>
#include <QWidget>
#include <string.h>
@@ -19,14 +21,17 @@ public:
void set_blips(QString p_sfx);
void blip_tick();
- void set_volume(qreal p_volume);
+ void set_volume(int p_volume);
int m_cycle = 0;
private:
+ const int max_blip_ms = 60;
+
QWidget *m_parent;
AOApplication *ao_app;
qreal m_volume;
+ QElapsedTimer delay;
void set_volume_internal(qreal p_volume);
diff --git a/include/aocaseannouncerdialog.h b/include/aocaseannouncerdialog.h
index 89080def..0ac8f074 100644
--- a/include/aocaseannouncerdialog.h
+++ b/include/aocaseannouncerdialog.h
@@ -37,7 +37,6 @@ private:
QCheckBox *ui_judge_needed;
QCheckBox *ui_juror_needed;
QCheckBox *ui_steno_needed;
- QCheckBox *ui_witness_needed;
public slots:
void ok_pressed();
diff --git a/include/aocharmovie.h b/include/aocharmovie.h
index 6db490b9..2dda0ec2 100644
--- a/include/aocharmovie.h
+++ b/include/aocharmovie.h
@@ -1,77 +1,125 @@
#ifndef AOCHARMOVIE_H
#define AOCHARMOVIE_H
-#include "include/aosfxplayer.h"
-#include "include/courtroom.h"
#include <QDebug>
+#include <QElapsedTimer>
#include <QImageReader>
#include <QLabel>
-#include <QMovie>
-#include <QPainter>
#include <QTimer>
class AOApplication;
+
class AOCharMovie : public QLabel {
Q_OBJECT
public:
AOCharMovie(QWidget *p_parent, AOApplication *p_ao_app);
- void play(QString p_char, QString p_emote, QString emote_prefix);
+ // Play a hat.gif - style preanimation
void play_pre(QString p_char, QString p_emote, int duration);
+
+ // Play a (b)normal.gif - style animation (talking)
void play_talking(QString p_char, QString p_emote);
+
+ // Play an (a)normal.gif - style animation (not talking)
void play_idle(QString p_char, QString p_emote);
- void set_flipped(bool p_flipped) { m_flipped = p_flipped; }
- void LoadImageWithStupidMethodForFlipSupport(QImage image);
+ // Stop the movie, clearing the image
void stop();
- void play_frame_sfx();
-
- void sfx_two_network_boogaloo();
- void screenshake_two_network_boogaloo();
- void realization_two_network_boogaloo();
+ // Set the m_flipped variable to true/false
+ void set_flipped(bool p_flipped) { m_flipped = p_flipped; }
- AOSfxPlayer *frame_specific_sfx_player;
- Courtroom *mycourtroom;
- QString frame_sfx_hellstring = "";
- QString frame_screenshake_hellstring = "";
- QString frame_realization_hellstring = "";
- bool use_networked_framehell = false;
+ // Set the movie's playback speed (between 10% and 1000%)
+ void set_speed(int modifier) { speed = qMax(10, qMin(modifier, 1000)); }
+ // Move the label itself around
void move(int ax, int ay);
+
+ // This is somewhat pointless now as there's no "QMovie" object to resize, aka
+ // no "combo" to speak of
void combo_resize(int w, int h);
+ // Return the frame delay adjusted for speed
+ int get_frame_delay(int delay);
+
+ QStringList network_strings;
+
+ QString m_char;
+ QString m_emote;
+
private:
AOApplication *ao_app;
- QMovie *m_movie;
- QVector<QImage> movie_frames;
+ QVector<QPixmap> movie_frames;
+ QVector<int> movie_delays;
+
+ // Effects such as sfx, screenshakes and realization flashes are stored in
+ // here. QString entry format: "sfx^[sfx_name]", "shake", "flash". The program
+ // uses the QVector index as reference.
+ QVector<QVector<QString>> movie_effects;
+
QTimer *preanim_timer;
QTimer *ticker;
QString last_path;
- QString current_emote;
- QString current_char;
- int default_w;
- int default_h;
+ QImageReader *m_reader = new QImageReader();
- const int time_mod = 62;
+ QElapsedTimer actual_time;
+
+ // Usually used to turn seconds into milliseconds such as for [Time] tag in
+ // char.ini
+ const int time_mod = 60;
// These are the X and Y values before they are fixed based on the sprite's
// width.
int x = 0;
int y = 0;
+ // These are the width and height values before they are fixed based on the
+ // sprite's width.
+ int f_w = 0;
+ int f_h = 0;
- bool m_flipped = false;
+ int frame = 0;
+ int max_frames = 0;
+
+ int speed = 100;
+ bool m_flipped = false;
bool play_once = true;
- bool apng = false;
+
+ // Set the movie's image to provided paths, preparing for playback.
+ void load_image(QString p_char, QString p_emote, QString emote_prefix);
+
+ // Start playback of the movie (if animated).
+ void play();
+
+ // Play a frame-specific effect, if there's any defined for that specific
+ // frame.
+ void play_frame_effect(int frame);
+
+ // Retreive a pixmap adjused for mirroring/aspect ratio shenanigans from a
+ // provided QImage
+ QPixmap get_pixmap(QImage image);
+
+ // Set the movie's frame to provided pixmap
+ void set_frame(QPixmap f_pixmap);
+
+ // Initialize the frame-specific effects from the char.ini
+ void load_effects();
+
+ // Initialize the frame-specific effects from the provided network_strings,
+ // this is only initialized if network_strings has size more than 0.
+ void load_network_effects();
signals:
void done();
+ void shake();
+ void flash();
+ void play_sfx(QString sfx);
private slots:
- void timer_done();
+ void preanim_done();
void movie_ticker();
};
+
#endif // AOCHARMOVIE_H
diff --git a/include/aoemotebutton.h b/include/aoemotebutton.h
index acf0b484..58e7e747 100644
--- a/include/aoemotebutton.h
+++ b/include/aoemotebutton.h
@@ -2,7 +2,7 @@
#define AOEMOTEBUTTON_H
#include "aoapplication.h"
-
+#include <QPainter>
#include <QDebug>
#include <QPushButton>
@@ -10,11 +10,11 @@ class AOEmoteButton : public QPushButton {
Q_OBJECT
public:
- AOEmoteButton(QWidget *p_parent, AOApplication *p_ao_app, int p_x, int p_y);
+ AOEmoteButton(QWidget *p_parent, AOApplication *p_ao_app, int p_x, int p_y,
+ int p_w, int p_h);
- // void set_on(QString p_char, int p_emote);
- // void set_off(QString p_char, int p_emote);
- void set_image(QString p_char, int p_emote, QString suffix);
+ void set_image(QString p_image, QString p_emote_comment);
+ void set_char_image(QString p_char, int p_emote, QString suffix);
void set_id(int p_id) { m_id = p_id; }
int get_id() { return m_id; }
@@ -25,6 +25,7 @@ private:
int m_id = 0;
+
signals:
void emote_clicked(int p_id);
diff --git a/include/aoevidencebutton.h b/include/aoevidencebutton.h
index b56bfb1d..d7812fe9 100644
--- a/include/aoevidencebutton.h
+++ b/include/aoevidencebutton.h
@@ -12,10 +12,9 @@ class AOEvidenceButton : public QPushButton {
Q_OBJECT
public:
- AOEvidenceButton(QWidget *p_parent, AOApplication *p_ao_app, int p_x,
- int p_y);
+ AOEvidenceButton(QWidget *p_parent, AOApplication *p_ao_app, int p_x, int p_y,
+ int p_w, int p_h);
- void reset();
void set_image(QString p_image);
void set_theme_image(QString p_image);
void set_id(int p_id) { m_id = p_id; }
@@ -36,9 +35,9 @@ protected:
void leaveEvent(QEvent *e);
void mouseDoubleClickEvent(QMouseEvent *e);
/*
- void dragLeaveEvent(QMouseEvent *e);
- void dragEnterEvent(QMouseEvent *e);
- */
+void dragLeaveEvent(QMouseEvent *e);
+void dragEnterEvent(QMouseEvent *e);
+*/
signals:
void evidence_clicked(int p_id);
diff --git a/include/aoevidencedisplay.h b/include/aoevidencedisplay.h
index 1d6280da..979a754e 100644
--- a/include/aoevidencedisplay.h
+++ b/include/aoevidencedisplay.h
@@ -2,11 +2,11 @@
#define AOEVIDENCEDISPLAY_H
#include "aoapplication.h"
+#include "aomovie.h"
#include "aosfxplayer.h"
#include <QDebug>
#include <QLabel>
-#include <QMovie>
class AOEvidenceDisplay : public QLabel {
Q_OBJECT
@@ -17,15 +17,16 @@ public:
void show_evidence(QString p_evidence_image, bool is_left_side, int p_volume);
QLabel *get_evidence_icon();
void reset();
+ void combo_resize(int w, int h);
private:
AOApplication *ao_app;
- QMovie *evidence_movie;
+ AOMovie *evidence_movie;
QLabel *evidence_icon;
AOSfxPlayer *sfx_player;
private slots:
- void frame_change(int p_frame);
+ void show_done();
};
#endif // AOEVIDENCEDISPLAY_H
diff --git a/include/aoimage.h b/include/aoimage.h
index c4fdf2ee..01ef8540 100644
--- a/include/aoimage.h
+++ b/include/aoimage.h
@@ -16,8 +16,8 @@ public:
QWidget *m_parent;
AOApplication *ao_app;
- void set_image(QString p_image);
- void set_image_from_path(QString p_path);
+ bool set_image(QString p_image);
+ bool set_chatbox(QString p_path);
void set_size_and_pos(QString identifier);
};
diff --git a/include/aolineedit.h b/include/aolineedit.h
index 70f1f978..5dce3aaa 100644
--- a/include/aolineedit.h
+++ b/include/aolineedit.h
@@ -10,14 +10,17 @@ class AOLineEdit : public QLineEdit {
public:
AOLineEdit(QWidget *parent);
+ void preserve_selection(bool toggle) { p_selection = toggle; }
+
+private:
+ bool p_selection = false;
+
protected:
void mouseDoubleClickEvent(QMouseEvent *e);
+ void focusOutEvent(QFocusEvent *ev);
signals:
void double_clicked();
-
-private slots:
- void on_enter_pressed();
};
#endif // AOLINEEDIT_H
diff --git a/include/aomovie.h b/include/aomovie.h
index caa1baa4..eb7f7a53 100644
--- a/include/aomovie.h
+++ b/include/aomovie.h
@@ -14,8 +14,7 @@ public:
AOMovie(QWidget *p_parent, AOApplication *p_ao_app);
void set_play_once(bool p_play_once);
- void start_timer(int delay);
- void play(QString p_gif, QString p_char = "", QString p_custom_theme = "",
+ void play(QString p_image, QString p_char = "", QString p_custom_theme = "",
int default_duration = 0);
void combo_resize(int w, int h);
void stop();
diff --git a/include/aomusicplayer.h b/include/aomusicplayer.h
index 5181630c..82751b68 100644
--- a/include/aomusicplayer.h
+++ b/include/aomusicplayer.h
@@ -1,8 +1,10 @@
#ifndef AOMUSICPLAYER_H
#define AOMUSICPLAYER_H
+#include "file_functions.h"
#if defined(BASSAUDIO)
#include "bass.h"
+#include "bassopus.h"
#elif defined(QTAUDIO)
#include <QMediaPlayer>
#endif
@@ -10,76 +12,44 @@
#include "aoapplication.h"
#include <QDebug>
-#include <QObject>
-#include <QTimer>
#include <QWidget>
#include <string.h>
-#if defined(BASSAUDIO)
-class AOMusicPlayer : public QObject {
- Q_OBJECT
+class AOMusicPlayer {
public:
AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app);
virtual ~AOMusicPlayer();
+ void set_volume(int p_value, int channel = -1);
+ void set_looping(bool toggle, int channel = 0);
- void play(QString p_song);
- void set_volume(int p_value);
-
- void kill_loop();
- QString get_path();
- bool enable_looping = true;
-
-private:
- QWidget *m_parent;
- AOApplication *ao_app;
-
- int m_volume = 0;
- QString f_path;
-
- HSTREAM m_stream;
-};
-#elif defined(QTAUDIO)
-class AOMusicPlayer : public QObject {
-public:
- AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app);
- ~AOMusicPlayer();
-
- void play(QString p_song);
- void set_volume(int p_value);
-
- void kill_loop();
- QString get_path();
- bool enable_looping = true;
-
-private:
- QWidget *m_parent;
- AOApplication *ao_app;
-
- QMediaPlayer m_player;
-
- int m_volume = 0;
- QString f_path;
-};
-#else
-class AOMusicPlayer : public QObject {
-public:
- AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app);
- ~AOMusicPlayer();
+ const int m_channelmax = 4;
- void play(QString p_song);
- void set_volume(int p_value);
+ // These have to be public for the stupid sync thing
+ int loop_start[4] = {0, 0, 0, 0};
+ int loop_end[4] = {0, 0, 0, 0};
- void kill_loop();
- QString get_path();
- bool enable_looping = true;
+public slots:
+ void play(QString p_song, int channel = 0, bool loop = false,
+ int effect_flags = 0);
+ void stop(int channel = 0);
private:
QWidget *m_parent;
AOApplication *ao_app;
- int m_volume = 0;
- QString f_path;
+ bool m_looping = false;
+ int m_volume[4] = {0, 0, 0, 0};
+
+ // Channel 0 = music
+ // Channel 1 = ambience
+ // Channel 2 = extra
+ // Channel 3 = extra
+ #if defined(BASSAUDIO)
+ HSTREAM m_stream_list[4];
+ HSYNC loop_sync[4];
+ #elif defined(QTAUDIO)
+ QMediaPlayer m_stream_list[4];
+ #endif
};
-#endif
#endif // AOMUSICPLAYER_H
diff --git a/include/aooptionsdialog.h b/include/aooptionsdialog.h
index 9a1429a4..2b8c879b 100644
--- a/include/aooptionsdialog.h
+++ b/include/aooptionsdialog.h
@@ -1,153 +1,146 @@
-#ifndef AOOPTIONSDIALOG_H
-#define AOOPTIONSDIALOG_H
-
-#include "aoapplication.h"
-
-#ifdef BASSAUDIO
-#include "bass.h"
-#elif defined QTAUDIO
-#include <QAudio>
-#include <QAudioDeviceInfo>
-#endif
-
-#include <QtCore/QVariant>
-#include <QtWidgets/QApplication>
-#include <QtWidgets/QCheckBox>
-#include <QtWidgets/QComboBox>
-#include <QtWidgets/QDialog>
-#include <QtWidgets/QDialogButtonBox>
-#include <QtWidgets/QFormLayout>
-#include <QtWidgets/QFrame>
-#include <QtWidgets/QLabel>
-#include <QtWidgets/QLineEdit>
-#include <QtWidgets/QPlainTextEdit>
-#include <QtWidgets/QSpinBox>
-#include <QtWidgets/QTabWidget>
-#include <QtWidgets/QVBoxLayout>
-#include <QtWidgets/QWidget>
-
-#include <QDirIterator>
-#include <QTextStream>
-
-class AOOptionsDialog : public QDialog {
- Q_OBJECT
-public:
- explicit AOOptionsDialog(QWidget *parent = nullptr,
- AOApplication *p_ao_app = nullptr);
-
-private:
- AOApplication *ao_app;
-
- QVBoxLayout *ui_vertical_layout;
- QTabWidget *ui_settings_tabs;
-
- QWidget *ui_gameplay_tab;
- QWidget *ui_form_layout_widget;
- QFormLayout *ui_gameplay_form;
- QLabel *ui_theme_label;
- QComboBox *ui_theme_combobox;
- QFrame *ui_theme_log_divider;
- QLabel *ui_downwards_lbl;
- QCheckBox *ui_downwards_cb;
- QLabel *ui_length_lbl;
- QSpinBox *ui_length_spinbox;
- QLabel *ui_pun_delay;
- QCheckBox *ui_pun_delay_cb;
- QLabel *ui_slower_blips_lb;
- QCheckBox *ui_slower_blips_cb;
- QLineEdit *ui_username_textbox;
- QLabel *ui_username_lbl;
- QLabel *ui_showname_lbl;
- QCheckBox *ui_showname_cb;
- QFrame *ui_net_divider;
- QLabel *ui_ms_lbl;
- QLineEdit *ui_ms_textbox;
- QLabel *ui_discord_lbl;
- QLabel *ui_epilepsy_lbl;
- QCheckBox *ui_epilepsy_cb;
-
- QCheckBox *ui_discord_cb;
- QLabel *ui_language_label;
- QComboBox *ui_language_combobox;
-
- QLabel *ui_keepevi_lbl;
- QCheckBox *ui_keepevi_cb;
-
- QLabel *ui_keepcobj_lbl;
- QCheckBox *ui_keepcobj_cb;
-
- QWidget *ui_callwords_tab;
- QWidget *ui_callwords_widget;
- QVBoxLayout *ui_callwords_layout;
- QPlainTextEdit *ui_callwords_textbox;
- QLabel *ui_callwords_explain_lbl;
- QCheckBox *ui_callwords_char_textbox;
-
- QWidget *ui_audio_tab;
- QWidget *ui_audio_widget;
- QFormLayout *ui_audio_layout;
- QLabel *ui_audio_device_lbl;
- QComboBox *ui_audio_device_combobox;
- QFrame *ui_audio_volume_divider;
- QSpinBox *ui_music_volume_spinbox;
- QLabel *ui_music_volume_lbl;
- QSpinBox *ui_sfx_volume_spinbox;
- QLabel *ui_loopsfx_lbl;
- QCheckBox *ui_loopsfx_cb;
- QLabel *ui_objectmusic_lbl;
- QCheckBox *ui_objectmusic_cb;
-
- QSpinBox *ui_blips_volume_spinbox;
- QLabel *ui_sfx_volume_lbl;
- QLabel *ui_blips_volume_lbl;
- QFrame *ui_volume_blip_divider;
- QSpinBox *ui_bliprate_spinbox;
- QLabel *ui_bliprate_lbl;
- QCheckBox *ui_blank_blips_cb;
- QLabel *ui_blank_blips_lbl;
- QDialogButtonBox *ui_settings_buttons;
-
- QWidget *ui_casing_tab;
- QWidget *ui_casing_widget;
- QFormLayout *ui_casing_layout;
- QLabel *ui_casing_supported_lbl;
- QLabel *ui_casing_enabled_lbl;
- QCheckBox *ui_casing_enabled_cb;
- QLabel *ui_casing_def_lbl;
- QCheckBox *ui_casing_def_cb;
- QLabel *ui_casing_pro_lbl;
- QCheckBox *ui_casing_pro_cb;
- QLabel *ui_casing_jud_lbl;
- QCheckBox *ui_casing_jud_cb;
- QLabel *ui_casing_jur_lbl;
- QCheckBox *ui_casing_jur_cb;
- QLabel *ui_casing_steno_lbl;
- QCheckBox *ui_casing_steno_cb;
- QLabel *ui_casing_cm_lbl;
- QCheckBox *ui_casing_cm_cb;
- QLabel *ui_casing_wit_lbl;
- QCheckBox *ui_casing_wit_cb;
- QLabel *ui_casing_cm_cases_lbl;
- QLineEdit *ui_casing_cm_cases_textbox;
-
- QWidget *ui_other_tab;
- QWidget *ui_other_widget;
- QFormLayout *ui_other_layout;
- QLabel *ui_other_fancy_icl_enabled_lb;
- QCheckBox *ui_other_fancy_icl_enabled_cb;
- QLabel *ui_other_mirror_icl_enabled_lb;
- QCheckBox *ui_other_mirror_icl_enabled_cb;
-
- QLabel *ui_other_fancy_icl_limit_lb;
- QCheckBox *ui_other_fancy_icl_limit_cb;
-
- bool needs_default_audiodev();
-
-signals:
-
-public slots:
- void save_pressed();
- void discard_pressed();
-};
-
-#endif // AOOPTIONSDIALOG_H
+#ifndef AOOPTIONSDIALOG_H
+#define AOOPTIONSDIALOG_H
+
+#include "aoapplication.h"
+#include "bass.h"
+
+#include <QtCore/QVariant>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QCheckBox>
+#include <QtWidgets/QComboBox>
+#include <QtWidgets/QDialog>
+#include <QtWidgets/QDialogButtonBox>
+#include <QtWidgets/QFormLayout>
+#include <QtWidgets/QFrame>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QPlainTextEdit>
+#include <QtWidgets/QScrollArea>
+#include <QtWidgets/QSpinBox>
+#include <QtWidgets/QTabWidget>
+#include <QtWidgets/QVBoxLayout>
+#include <QtWidgets/QWidget>
+
+#include <QDirIterator>
+#include <QTextStream>
+
+class AOOptionsDialog : public QDialog {
+ Q_OBJECT
+public:
+ explicit AOOptionsDialog(QWidget *parent = nullptr,
+ AOApplication *p_ao_app = nullptr);
+
+private:
+ AOApplication *ao_app;
+
+ QVBoxLayout *ui_vertical_layout;
+ QTabWidget *ui_settings_tabs;
+
+ QWidget *ui_gameplay_tab;
+ QWidget *ui_form_layout_widget;
+ QFormLayout *ui_gameplay_form;
+ QLabel *ui_theme_label;
+ QComboBox *ui_theme_combobox;
+ QFrame *ui_theme_log_divider;
+ QLabel *ui_downwards_lbl;
+ QCheckBox *ui_downwards_cb;
+ QLabel *ui_length_lbl;
+ QSpinBox *ui_length_spinbox;
+ QFrame *ui_log_names_divider;
+ QLineEdit *ui_username_textbox;
+ QLabel *ui_username_lbl;
+ QLabel *ui_showname_lbl;
+ QCheckBox *ui_showname_cb;
+ QFrame *ui_net_divider;
+ QLabel *ui_ms_lbl;
+ QLineEdit *ui_ms_textbox;
+ QLabel *ui_discord_lbl;
+ QCheckBox *ui_discord_cb;
+ QLabel *ui_language_label;
+ QComboBox *ui_language_combobox;
+
+ QLabel *ui_shake_lbl;
+ QCheckBox *ui_shake_cb;
+ QLabel *ui_effects_lbl;
+ QCheckBox *ui_effects_cb;
+ QLabel *ui_framenetwork_lbl;
+ QCheckBox *ui_framenetwork_cb;
+
+ QLabel *ui_colorlog_lbl;
+ QCheckBox *ui_colorlog_cb;
+
+ QLabel *ui_stickysounds_lbl;
+ QCheckBox *ui_stickysounds_cb;
+
+ QLabel *ui_stickyeffects_lbl;
+ QCheckBox *ui_stickyeffects_cb;
+
+ QLabel *ui_stickypres_lbl;
+ QCheckBox *ui_stickypres_cb;
+
+ QLabel *ui_customchat_lbl;
+ QCheckBox *ui_customchat_cb;
+
+ QWidget *ui_callwords_tab;
+ QWidget *ui_callwords_widget;
+ QVBoxLayout *ui_callwords_layout;
+ QPlainTextEdit *ui_callwords_textbox;
+ QLabel *ui_callwords_explain_lbl;
+ QCheckBox *ui_callwords_char_textbox;
+
+ QWidget *ui_audio_tab;
+ QWidget *ui_audio_widget;
+ QFormLayout *ui_audio_layout;
+ QLabel *ui_audio_device_lbl;
+ QComboBox *ui_audio_device_combobox;
+ QFrame *ui_audio_volume_divider;
+ QSpinBox *ui_music_volume_spinbox;
+ QLabel *ui_music_volume_lbl;
+ QSpinBox *ui_sfx_volume_spinbox;
+ QSpinBox *ui_blips_volume_spinbox;
+ QLabel *ui_sfx_volume_lbl;
+ QLabel *ui_blips_volume_lbl;
+ QFrame *ui_volume_blip_divider;
+ QSpinBox *ui_bliprate_spinbox;
+ QLabel *ui_bliprate_lbl;
+ QCheckBox *ui_blank_blips_cb;
+ QLabel *ui_blank_blips_lbl;
+ QLabel *ui_loopsfx_lbl;
+ QCheckBox *ui_loopsfx_cb;
+ QLabel *ui_objectmusic_lbl;
+ QCheckBox *ui_objectmusic_cb;
+ QDialogButtonBox *ui_settings_buttons;
+
+ QWidget *ui_casing_tab;
+ QWidget *ui_casing_widget;
+ QFormLayout *ui_casing_layout;
+ QLabel *ui_casing_supported_lbl;
+ QLabel *ui_casing_enabled_lbl;
+ QCheckBox *ui_casing_enabled_cb;
+ QLabel *ui_casing_def_lbl;
+ QCheckBox *ui_casing_def_cb;
+ QLabel *ui_casing_pro_lbl;
+ QCheckBox *ui_casing_pro_cb;
+ QLabel *ui_casing_jud_lbl;
+ QCheckBox *ui_casing_jud_cb;
+ QLabel *ui_casing_jur_lbl;
+ QCheckBox *ui_casing_jur_cb;
+ QLabel *ui_casing_steno_lbl;
+ QCheckBox *ui_casing_steno_cb;
+ QLabel *ui_casing_cm_lbl;
+ QCheckBox *ui_casing_cm_cb;
+ QLabel *ui_casing_cm_cases_lbl;
+ QLineEdit *ui_casing_cm_cases_textbox;
+ QLabel *ui_log_lbl;
+ QCheckBox *ui_log_cb;
+
+ bool needs_default_audiodev();
+
+signals:
+
+public slots:
+ void save_pressed();
+ void discard_pressed();
+};
+
+#endif // AOOPTIONSDIALOG_H
diff --git a/include/aoscene.h b/include/aoscene.h
index 7c1ef6fd..726e2641 100644
--- a/include/aoscene.h
+++ b/include/aoscene.h
@@ -16,11 +16,27 @@ public:
void set_image(QString p_image);
void set_legacy_desk(QString p_image);
+ // Move the label itself around
+ void move(int ax, int ay);
+
+ // This is somewhat pointless now as there's no "QMovie" object to resize, aka
+ // no "combo" to speak of
+ void combo_resize(int w, int h);
+
private:
QWidget *m_parent;
QMovie *m_movie;
AOApplication *ao_app;
QString last_image;
+
+ // These are the X and Y values before they are fixed based on the sprite's
+ // width.
+ int x = 0;
+ int y = 0;
+ // These are the width and height values before they are fixed based on the
+ // sprite's width.
+ int f_w = 0;
+ int f_h = 0;
};
#endif // AOSCENE_H
diff --git a/include/aosfxplayer.h b/include/aosfxplayer.h
index af3aef6d..99188719 100644
--- a/include/aosfxplayer.h
+++ b/include/aosfxplayer.h
@@ -3,6 +3,7 @@
#if defined(BASSAUDIO)
#include "bass.h"
+#include "bassopus.h"
#elif defined(QTAUDIO)
#include <QSoundEffect>
#endif
@@ -10,32 +11,36 @@
#include "aoapplication.h"
#include <QDebug>
-#include <QTimer>
#include <QWidget>
#include <string.h>
-class AOSfxPlayer : public QObject {
- Q_OBJECT
+class AOSfxPlayer {
public:
AOSfxPlayer(QWidget *parent, AOApplication *p_ao_app);
- void play(QString p_sfx, QString p_char = "", QString shout = "");
- void stop();
+ void clear();
+ void loop_clear();
+ void play(QString p_sfx, QString p_char = "", QString shout = "",
+ int channel = -1);
+ void stop(int channel = -1);
void set_volume(qreal p_volume);
- void setLooping(bool is_looping);
+ void set_looping(bool toggle, int channel = -1);
+ int m_channel = 0;
private:
QWidget *m_parent;
AOApplication *ao_app;
qreal m_volume = 0;
- bool looping_sfx = false;
+ bool m_looping = true;
void set_volume_internal(qreal p_volume);
+ const int m_channelmax = 5;
+
#if defined(BASSAUDIO)
- HSTREAM m_stream;
+ HSTREAM m_stream_list[5];
#elif defined(QTAUDIO)
- QSoundEffect m_sfx;
+ QSoundEffect m_stream_list[5];
#endif
};
diff --git a/include/aotextarea.h b/include/aotextarea.h
index b8160890..453e9659 100644
--- a/include/aotextarea.h
+++ b/include/aotextarea.h
@@ -11,12 +11,12 @@ class AOTextArea : public QTextBrowser {
public:
AOTextArea(QWidget *p_parent = nullptr);
- void append_chatmessage(QString p_name, QString p_message, QString p_colour,
- bool song);
+ void append_linked(QString p_message);
+ void append_chatmessage(QString p_name, QString p_message, QString p_colur);
void append_error(QString p_message);
private:
- const QRegExp omnis_dank_url_regex = QRegExp("\\b(https?://\\S+\\.\\S+)\\b");
+ const QRegExp url_parser_regex = QRegExp("\\b(https?://\\S+\\.\\S+)\\b");
void auto_scroll(QTextCursor old_cursor, int scrollbar_value,
bool is_scrolled_down);
diff --git a/include/bass.h b/include/bass.h
index a3687b9f..ec2c7a29 100644
--- a/include/bass.h
+++ b/include/bass.h
@@ -1,1217 +1,1227 @@
-/*
- BASS 2.4 C/C++ header file
- Copyright (c) 1999-2018 Un4seen Developments Ltd.
-
- See the BASS.CHM file for more detailed documentation
-*/
-
-#ifndef BASS_H
-#define BASS_H
-
-#ifdef _WIN32
-#include <wtypes.h>
-typedef unsigned __int64 QWORD;
-#else
-#include <stdint.h>
-#define WINAPI
-#define CALLBACK
-typedef uint8_t BYTE;
-typedef uint16_t WORD;
-typedef uint32_t DWORD;
-typedef uint64_t QWORD;
-#ifndef __OBJC__
-typedef int BOOL;
-#endif
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-#define LOBYTE(a) (BYTE)(a)
-#define HIBYTE(a) (BYTE)((a) >> 8)
-#define LOWORD(a) (WORD)(a)
-#define HIWORD(a) (WORD)((a) >> 16)
-#define MAKEWORD(a, b) (WORD)(((a)&0xff) | ((b) << 8))
-#define MAKELONG(a, b) (DWORD)(((a)&0xffff) | ((b) << 16))
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define BASSVERSION 0x204 // API version
-#define BASSVERSIONTEXT "2.4"
-
-#ifndef BASSDEF
-#define BASSDEF(f) WINAPI f
-#else
-#define NOBASSOVERLOADS
-#endif
-
-typedef DWORD HMUSIC; // MOD music handle
-typedef DWORD HSAMPLE; // sample handle
-typedef DWORD HCHANNEL; // playing sample's channel handle
-typedef DWORD HSTREAM; // sample stream handle
-typedef DWORD HRECORD; // recording handle
-typedef DWORD HSYNC; // synchronizer handle
-typedef DWORD HDSP; // DSP handle
-typedef DWORD HFX; // DX8 effect handle
-typedef DWORD HPLUGIN; // Plugin handle
-
-// Error codes returned by BASS_ErrorGetCode
-#define BASS_OK 0 // all is OK
-#define BASS_ERROR_MEM 1 // memory error
-#define BASS_ERROR_FILEOPEN 2 // can't open the file
-#define BASS_ERROR_DRIVER 3 // can't find a free/valid driver
-#define BASS_ERROR_BUFLOST 4 // the sample buffer was lost
-#define BASS_ERROR_HANDLE 5 // invalid handle
-#define BASS_ERROR_FORMAT 6 // unsupported sample format
-#define BASS_ERROR_POSITION 7 // invalid position
-#define BASS_ERROR_INIT 8 // BASS_Init has not been successfully called
-#define BASS_ERROR_START 9 // BASS_Start has not been successfully called
-#define BASS_ERROR_SSL 10 // SSL/HTTPS support isn't available
-#define BASS_ERROR_ALREADY 14 // already initialized/paused/whatever
-#define BASS_ERROR_NOCHAN 18 // can't get a free channel
-#define BASS_ERROR_ILLTYPE 19 // an illegal type was specified
-#define BASS_ERROR_ILLPARAM 20 // an illegal parameter was specified
-#define BASS_ERROR_NO3D 21 // no 3D support
-#define BASS_ERROR_NOEAX 22 // no EAX support
-#define BASS_ERROR_DEVICE 23 // illegal device number
-#define BASS_ERROR_NOPLAY 24 // not playing
-#define BASS_ERROR_FREQ 25 // illegal sample rate
-#define BASS_ERROR_NOTFILE 27 // the stream is not a file stream
-#define BASS_ERROR_NOHW 29 // no hardware voices available
-#define BASS_ERROR_EMPTY 31 // the MOD music has no sequence data
-#define BASS_ERROR_NONET 32 // no internet connection could be opened
-#define BASS_ERROR_CREATE 33 // couldn't create the file
-#define BASS_ERROR_NOFX 34 // effects are not available
-#define BASS_ERROR_NOTAVAIL 37 // requested data/action is not available
-#define BASS_ERROR_DECODE 38 // the channel is/isn't a "decoding channel"
-#define BASS_ERROR_DX 39 // a sufficient DirectX version is not installed
-#define BASS_ERROR_TIMEOUT 40 // connection timedout
-#define BASS_ERROR_FILEFORM 41 // unsupported file format
-#define BASS_ERROR_SPEAKER 42 // unavailable speaker
-#define BASS_ERROR_VERSION 43 // invalid BASS version (used by add-ons)
-#define BASS_ERROR_CODEC 44 // codec is not available/supported
-#define BASS_ERROR_ENDED 45 // the channel/file has ended
-#define BASS_ERROR_BUSY 46 // the device is busy
-#define BASS_ERROR_UNKNOWN -1 // some other mystery problem
-
-// BASS_SetConfig options
-#define BASS_CONFIG_BUFFER 0
-#define BASS_CONFIG_UPDATEPERIOD 1
-#define BASS_CONFIG_GVOL_SAMPLE 4
-#define BASS_CONFIG_GVOL_STREAM 5
-#define BASS_CONFIG_GVOL_MUSIC 6
-#define BASS_CONFIG_CURVE_VOL 7
-#define BASS_CONFIG_CURVE_PAN 8
-#define BASS_CONFIG_FLOATDSP 9
-#define BASS_CONFIG_3DALGORITHM 10
-#define BASS_CONFIG_NET_TIMEOUT 11
-#define BASS_CONFIG_NET_BUFFER 12
-#define BASS_CONFIG_PAUSE_NOPLAY 13
-#define BASS_CONFIG_NET_PREBUF 15
-#define BASS_CONFIG_NET_PASSIVE 18
-#define BASS_CONFIG_REC_BUFFER 19
-#define BASS_CONFIG_NET_PLAYLIST 21
-#define BASS_CONFIG_MUSIC_VIRTUAL 22
-#define BASS_CONFIG_VERIFY 23
-#define BASS_CONFIG_UPDATETHREADS 24
-#define BASS_CONFIG_DEV_BUFFER 27
-#define BASS_CONFIG_VISTA_TRUEPOS 30
-#define BASS_CONFIG_IOS_MIXAUDIO 34
-#define BASS_CONFIG_DEV_DEFAULT 36
-#define BASS_CONFIG_NET_READTIMEOUT 37
-#define BASS_CONFIG_VISTA_SPEAKERS 38
-#define BASS_CONFIG_IOS_SPEAKER 39
-#define BASS_CONFIG_MF_DISABLE 40
-#define BASS_CONFIG_HANDLES 41
-#define BASS_CONFIG_UNICODE 42
-#define BASS_CONFIG_SRC 43
-#define BASS_CONFIG_SRC_SAMPLE 44
-#define BASS_CONFIG_ASYNCFILE_BUFFER 45
-#define BASS_CONFIG_OGG_PRESCAN 47
-#define BASS_CONFIG_MF_VIDEO 48
-#define BASS_CONFIG_AIRPLAY 49
-#define BASS_CONFIG_DEV_NONSTOP 50
-#define BASS_CONFIG_IOS_NOCATEGORY 51
-#define BASS_CONFIG_VERIFY_NET 52
-#define BASS_CONFIG_DEV_PERIOD 53
-#define BASS_CONFIG_FLOAT 54
-#define BASS_CONFIG_NET_SEEK 56
-#define BASS_CONFIG_AM_DISABLE 58
-#define BASS_CONFIG_NET_PLAYLIST_DEPTH 59
-#define BASS_CONFIG_NET_PREBUF_WAIT 60
-
-// BASS_SetConfigPtr options
-#define BASS_CONFIG_NET_AGENT 16
-#define BASS_CONFIG_NET_PROXY 17
-#define BASS_CONFIG_IOS_NOTIFY 46
-
-// BASS_Init flags
-#define BASS_DEVICE_8BITS 1 // 8 bit
-#define BASS_DEVICE_MONO 2 // mono
-#define BASS_DEVICE_3D 4 // enable 3D functionality
-#define BASS_DEVICE_16BITS 8 // limit output to 16 bit
-#define BASS_DEVICE_LATENCY 0x100 // calculate device latency (BASS_INFO struct)
-#define BASS_DEVICE_CPSPEAKERS \
- 0x400 // detect speakers via Windows control panel
-#define BASS_DEVICE_SPEAKERS 0x800 // force enabling of speaker assignment
-#define BASS_DEVICE_NOSPEAKER 0x1000 // ignore speaker arrangement
-#define BASS_DEVICE_DMIX 0x2000 // use ALSA "dmix" plugin
-#define BASS_DEVICE_FREQ 0x4000 // set device sample rate
-#define BASS_DEVICE_STEREO 0x8000 // limit output to stereo
-#define BASS_DEVICE_HOG 0x10000 // hog/exclusive mode
-#define BASS_DEVICE_AUDIOTRACK 0x20000 // use AudioTrack output
-#define BASS_DEVICE_DSOUND 0x40000 // use DirectSound output
-
-// DirectSound interfaces (for use with BASS_GetDSoundObject)
-#define BASS_OBJECT_DS 1 // IDirectSound
-#define BASS_OBJECT_DS3DL 2 // IDirectSound3DListener
-
-// Device info structure
-typedef struct {
-#if defined(_WIN32_WCE) || \
- (WINAPI_FAMILY && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
- const wchar_t *name; // description
- const wchar_t *driver; // driver
-#else
- const char *name; // description
- const char *driver; // driver
-#endif
- DWORD flags;
-} BASS_DEVICEINFO;
-
-// BASS_DEVICEINFO flags
-#define BASS_DEVICE_ENABLED 1
-#define BASS_DEVICE_DEFAULT 2
-#define BASS_DEVICE_INIT 4
-#define BASS_DEVICE_LOOPBACK 8
-
-#define BASS_DEVICE_TYPE_MASK 0xff000000
-#define BASS_DEVICE_TYPE_NETWORK 0x01000000
-#define BASS_DEVICE_TYPE_SPEAKERS 0x02000000
-#define BASS_DEVICE_TYPE_LINE 0x03000000
-#define BASS_DEVICE_TYPE_HEADPHONES 0x04000000
-#define BASS_DEVICE_TYPE_MICROPHONE 0x05000000
-#define BASS_DEVICE_TYPE_HEADSET 0x06000000
-#define BASS_DEVICE_TYPE_HANDSET 0x07000000
-#define BASS_DEVICE_TYPE_DIGITAL 0x08000000
-#define BASS_DEVICE_TYPE_SPDIF 0x09000000
-#define BASS_DEVICE_TYPE_HDMI 0x0a000000
-#define BASS_DEVICE_TYPE_DISPLAYPORT 0x40000000
-
-// BASS_GetDeviceInfo flags
-#define BASS_DEVICES_AIRPLAY 0x1000000
-
-typedef struct {
- DWORD flags; // device capabilities (DSCAPS_xxx flags)
- DWORD hwsize; // size of total device hardware memory
- DWORD hwfree; // size of free device hardware memory
- DWORD freesam; // number of free sample slots in the hardware
- DWORD free3d; // number of free 3D sample slots in the hardware
- DWORD minrate; // min sample rate supported by the hardware
- DWORD maxrate; // max sample rate supported by the hardware
- BOOL
- eax; // device supports EAX? (always FALSE if BASS_DEVICE_3D was not used)
- DWORD minbuf; // recommended minimum buffer length in ms (requires
- // BASS_DEVICE_LATENCY)
- DWORD dsver; // DirectSound version
- DWORD latency; // delay (in ms) before start of playback (requires
- // BASS_DEVICE_LATENCY)
- DWORD initflags; // BASS_Init "flags" parameter
- DWORD speakers; // number of speakers available
- DWORD freq; // current output rate
-} BASS_INFO;
-
-// BASS_INFO flags (from DSOUND.H)
-#define DSCAPS_CONTINUOUSRATE \
- 0x00000010 // supports all sample rates between min/maxrate
-#define DSCAPS_EMULDRIVER \
- 0x00000020 // device does NOT have hardware DirectSound support
-#define DSCAPS_CERTIFIED \
- 0x00000040 // device driver has been certified by Microsoft
-#define DSCAPS_SECONDARYMONO 0x00000100 // mono
-#define DSCAPS_SECONDARYSTEREO 0x00000200 // stereo
-#define DSCAPS_SECONDARY8BIT 0x00000400 // 8 bit
-#define DSCAPS_SECONDARY16BIT 0x00000800 // 16 bit
-
-// Recording device info structure
-typedef struct {
- DWORD flags; // device capabilities (DSCCAPS_xxx flags)
- DWORD formats; // supported standard formats (WAVE_FORMAT_xxx flags)
- DWORD inputs; // number of inputs
- BOOL singlein; // TRUE = only 1 input can be set at a time
- DWORD freq; // current input rate
-} BASS_RECORDINFO;
-
-// BASS_RECORDINFO flags (from DSOUND.H)
-#define DSCCAPS_EMULDRIVER \
- DSCAPS_EMULDRIVER // device does NOT have hardware DirectSound recording
- // support
-#define DSCCAPS_CERTIFIED \
- DSCAPS_CERTIFIED // device driver has been certified by Microsoft
-
-// defines for formats field of BASS_RECORDINFO (from MMSYSTEM.H)
-#ifndef WAVE_FORMAT_1M08
-#define WAVE_FORMAT_1M08 0x00000001 /* 11.025 kHz, Mono, 8-bit */
-#define WAVE_FORMAT_1S08 0x00000002 /* 11.025 kHz, Stereo, 8-bit */
-#define WAVE_FORMAT_1M16 0x00000004 /* 11.025 kHz, Mono, 16-bit */
-#define WAVE_FORMAT_1S16 0x00000008 /* 11.025 kHz, Stereo, 16-bit */
-#define WAVE_FORMAT_2M08 0x00000010 /* 22.05 kHz, Mono, 8-bit */
-#define WAVE_FORMAT_2S08 0x00000020 /* 22.05 kHz, Stereo, 8-bit */
-#define WAVE_FORMAT_2M16 0x00000040 /* 22.05 kHz, Mono, 16-bit */
-#define WAVE_FORMAT_2S16 0x00000080 /* 22.05 kHz, Stereo, 16-bit */
-#define WAVE_FORMAT_4M08 0x00000100 /* 44.1 kHz, Mono, 8-bit */
-#define WAVE_FORMAT_4S08 0x00000200 /* 44.1 kHz, Stereo, 8-bit */
-#define WAVE_FORMAT_4M16 0x00000400 /* 44.1 kHz, Mono, 16-bit */
-#define WAVE_FORMAT_4S16 0x00000800 /* 44.1 kHz, Stereo, 16-bit */
-#endif
-
-// Sample info structure
-typedef struct {
- DWORD freq; // default playback rate
- float volume; // default volume (0-1)
- float pan; // default pan (-1=left, 0=middle, 1=right)
- DWORD flags; // BASS_SAMPLE_xxx flags
- DWORD length; // length (in bytes)
- DWORD max; // maximum simultaneous playbacks
- DWORD origres; // original resolution
- DWORD chans; // number of channels
- DWORD mingap; // minimum gap (ms) between creating channels
- DWORD mode3d; // BASS_3DMODE_xxx mode
- float mindist; // minimum distance
- float maxdist; // maximum distance
- DWORD iangle; // angle of inside projection cone
- DWORD oangle; // angle of outside projection cone
- float outvol; // delta-volume outside the projection cone
- DWORD vam; // voice allocation/management flags (BASS_VAM_xxx)
- DWORD priority; // priority (0=lowest, 0xffffffff=highest)
-} BASS_SAMPLE;
-
-#define BASS_SAMPLE_8BITS 1 // 8 bit
-#define BASS_SAMPLE_FLOAT 256 // 32 bit floating-point
-#define BASS_SAMPLE_MONO 2 // mono
-#define BASS_SAMPLE_LOOP 4 // looped
-#define BASS_SAMPLE_3D 8 // 3D functionality
-#define BASS_SAMPLE_SOFTWARE 16 // not using hardware mixing
-#define BASS_SAMPLE_MUTEMAX 32 // mute at max distance (3D only)
-#define BASS_SAMPLE_VAM 64 // DX7 voice allocation & management
-#define BASS_SAMPLE_FX 128 // old implementation of DX8 effects
-#define BASS_SAMPLE_OVER_VOL 0x10000 // override lowest volume
-#define BASS_SAMPLE_OVER_POS 0x20000 // override longest playing
-#define BASS_SAMPLE_OVER_DIST \
- 0x30000 // override furthest from listener (3D only)
-
-#define BASS_STREAM_PRESCAN \
- 0x20000 // enable pin-point seeking/length (MP3/MP2/MP1)
-#define BASS_STREAM_AUTOFREE \
- 0x40000 // automatically free the stream when it stop/ends
-#define BASS_STREAM_RESTRATE \
- 0x80000 // restrict the download rate of internet file streams
-#define BASS_STREAM_BLOCK \
- 0x100000 // download/play internet file stream in small blocks
-#define BASS_STREAM_DECODE \
- 0x200000 // don't play the stream, only decode (BASS_ChannelGetData)
-#define BASS_STREAM_STATUS \
- 0x800000 // give server status info (HTTP/ICY tags) in DOWNLOADPROC
-
-#define BASS_MP3_IGNOREDELAY \
- 0x200 // ignore LAME/Xing/VBRI/iTunes delay & padding info
-#define BASS_MP3_SETPOS BASS_STREAM_PRESCAN
-
-#define BASS_MUSIC_FLOAT BASS_SAMPLE_FLOAT
-#define BASS_MUSIC_MONO BASS_SAMPLE_MONO
-#define BASS_MUSIC_LOOP BASS_SAMPLE_LOOP
-#define BASS_MUSIC_3D BASS_SAMPLE_3D
-#define BASS_MUSIC_FX BASS_SAMPLE_FX
-#define BASS_MUSIC_AUTOFREE BASS_STREAM_AUTOFREE
-#define BASS_MUSIC_DECODE BASS_STREAM_DECODE
-#define BASS_MUSIC_PRESCAN BASS_STREAM_PRESCAN // calculate playback length
-#define BASS_MUSIC_CALCLEN BASS_MUSIC_PRESCAN
-#define BASS_MUSIC_RAMP 0x200 // normal ramping
-#define BASS_MUSIC_RAMPS 0x400 // sensitive ramping
-#define BASS_MUSIC_SURROUND 0x800 // surround sound
-#define BASS_MUSIC_SURROUND2 0x1000 // surround sound (mode 2)
-#define BASS_MUSIC_FT2PAN 0x2000 // apply FastTracker 2 panning to XM files
-#define BASS_MUSIC_FT2MOD 0x2000 // play .MOD as FastTracker 2 does
-#define BASS_MUSIC_PT1MOD 0x4000 // play .MOD as ProTracker 1 does
-#define BASS_MUSIC_NONINTER 0x10000 // non-interpolated sample mixing
-#define BASS_MUSIC_SINCINTER 0x800000 // sinc interpolated sample mixing
-#define BASS_MUSIC_POSRESET 0x8000 // stop all notes when moving position
-#define BASS_MUSIC_POSRESETEX \
- 0x400000 // stop all notes and reset bmp/etc when moving position
-#define BASS_MUSIC_STOPBACK 0x80000 // stop the music on a backwards jump effect
-#define BASS_MUSIC_NOSAMPLE 0x100000 // don't load the samples
-
-// Speaker assignment flags
-#define BASS_SPEAKER_FRONT 0x1000000 // front speakers
-#define BASS_SPEAKER_REAR 0x2000000 // rear/side speakers
-#define BASS_SPEAKER_CENLFE 0x3000000 // center & LFE speakers (5.1)
-#define BASS_SPEAKER_REAR2 0x4000000 // rear center speakers (7.1)
-#define BASS_SPEAKER_N(n) ((n) << 24) // n'th pair of speakers (max 15)
-#define BASS_SPEAKER_LEFT 0x10000000 // modifier: left
-#define BASS_SPEAKER_RIGHT 0x20000000 // modifier: right
-#define BASS_SPEAKER_FRONTLEFT BASS_SPEAKER_FRONT | BASS_SPEAKER_LEFT
-#define BASS_SPEAKER_FRONTRIGHT BASS_SPEAKER_FRONT | BASS_SPEAKER_RIGHT
-#define BASS_SPEAKER_REARLEFT BASS_SPEAKER_REAR | BASS_SPEAKER_LEFT
-#define BASS_SPEAKER_REARRIGHT BASS_SPEAKER_REAR | BASS_SPEAKER_RIGHT
-#define BASS_SPEAKER_CENTER BASS_SPEAKER_CENLFE | BASS_SPEAKER_LEFT
-#define BASS_SPEAKER_LFE BASS_SPEAKER_CENLFE | BASS_SPEAKER_RIGHT
-#define BASS_SPEAKER_REAR2LEFT BASS_SPEAKER_REAR2 | BASS_SPEAKER_LEFT
-#define BASS_SPEAKER_REAR2RIGHT BASS_SPEAKER_REAR2 | BASS_SPEAKER_RIGHT
-
-#define BASS_ASYNCFILE 0x40000000
-#define BASS_UNICODE 0x80000000
-
-#define BASS_RECORD_PAUSE 0x8000 // start recording paused
-#define BASS_RECORD_ECHOCANCEL 0x2000
-#define BASS_RECORD_AGC 0x4000
-
-// DX7 voice allocation & management flags
-#define BASS_VAM_HARDWARE 1
-#define BASS_VAM_SOFTWARE 2
-#define BASS_VAM_TERM_TIME 4
-#define BASS_VAM_TERM_DIST 8
-#define BASS_VAM_TERM_PRIO 16
-
-// Channel info structure
-typedef struct {
- DWORD freq; // default playback rate
- DWORD chans; // channels
- DWORD flags; // BASS_SAMPLE/STREAM/MUSIC/SPEAKER flags
- DWORD ctype; // type of channel
- DWORD origres; // original resolution
- HPLUGIN plugin; // plugin
- HSAMPLE sample; // sample
- const char *filename; // filename
-} BASS_CHANNELINFO;
-
-#define BASS_ORIGRES_FLOAT 0x10000
-
-// BASS_CHANNELINFO types
-#define BASS_CTYPE_SAMPLE 1
-#define BASS_CTYPE_RECORD 2
-#define BASS_CTYPE_STREAM 0x10000
-#define BASS_CTYPE_STREAM_OGG 0x10002
-#define BASS_CTYPE_STREAM_MP1 0x10003
-#define BASS_CTYPE_STREAM_MP2 0x10004
-#define BASS_CTYPE_STREAM_MP3 0x10005
-#define BASS_CTYPE_STREAM_AIFF 0x10006
-#define BASS_CTYPE_STREAM_CA 0x10007
-#define BASS_CTYPE_STREAM_MF 0x10008
-#define BASS_CTYPE_STREAM_AM 0x10009
-#define BASS_CTYPE_STREAM_DUMMY 0x18000
-#define BASS_CTYPE_STREAM_DEVICE 0x18001
-#define BASS_CTYPE_STREAM_WAV 0x40000 // WAVE flag, LOWORD=codec
-#define BASS_CTYPE_STREAM_WAV_PCM 0x50001
-#define BASS_CTYPE_STREAM_WAV_FLOAT 0x50003
-#define BASS_CTYPE_MUSIC_MOD 0x20000
-#define BASS_CTYPE_MUSIC_MTM 0x20001
-#define BASS_CTYPE_MUSIC_S3M 0x20002
-#define BASS_CTYPE_MUSIC_XM 0x20003
-#define BASS_CTYPE_MUSIC_IT 0x20004
-#define BASS_CTYPE_MUSIC_MO3 0x00100 // MO3 flag
-
-typedef struct {
- DWORD ctype; // channel type
-#if defined(_WIN32_WCE) || \
- (WINAPI_FAMILY && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
- const wchar_t *name; // format description
- const wchar_t *exts; // file extension filter (*.ext1;*.ext2;etc...)
-#else
- const char *name; // format description
- const char *exts; // file extension filter (*.ext1;*.ext2;etc...)
-#endif
-} BASS_PLUGINFORM;
-
-typedef struct {
- DWORD version; // version (same form as BASS_GetVersion)
- DWORD formatc; // number of formats
- const BASS_PLUGINFORM *formats; // the array of formats
-} BASS_PLUGININFO;
-
-// 3D vector (for 3D positions/velocities/orientations)
-typedef struct BASS_3DVECTOR {
-#ifdef __cplusplus
- BASS_3DVECTOR(){};
- BASS_3DVECTOR(float _x, float _y, float _z) : x(_x), y(_y), z(_z){};
-#endif
- float x; // +=right, -=left
- float y; // +=up, -=down
- float z; // +=front, -=behind
-} BASS_3DVECTOR;
-
-// 3D channel modes
-#define BASS_3DMODE_NORMAL 0 // normal 3D processing
-#define BASS_3DMODE_RELATIVE 1 // position is relative to the listener
-#define BASS_3DMODE_OFF 2 // no 3D processing
-
-// software 3D mixing algorithms (used with BASS_CONFIG_3DALGORITHM)
-#define BASS_3DALG_DEFAULT 0
-#define BASS_3DALG_OFF 1
-#define BASS_3DALG_FULL 2
-#define BASS_3DALG_LIGHT 3
-
-// EAX environments, use with BASS_SetEAXParameters
-enum {
- EAX_ENVIRONMENT_GENERIC,
- EAX_ENVIRONMENT_PADDEDCELL,
- EAX_ENVIRONMENT_ROOM,
- EAX_ENVIRONMENT_BATHROOM,
- EAX_ENVIRONMENT_LIVINGROOM,
- EAX_ENVIRONMENT_STONEROOM,
- EAX_ENVIRONMENT_AUDITORIUM,
- EAX_ENVIRONMENT_CONCERTHALL,
- EAX_ENVIRONMENT_CAVE,
- EAX_ENVIRONMENT_ARENA,
- EAX_ENVIRONMENT_HANGAR,
- EAX_ENVIRONMENT_CARPETEDHALLWAY,
- EAX_ENVIRONMENT_HALLWAY,
- EAX_ENVIRONMENT_STONECORRIDOR,
- EAX_ENVIRONMENT_ALLEY,
- EAX_ENVIRONMENT_FOREST,
- EAX_ENVIRONMENT_CITY,
- EAX_ENVIRONMENT_MOUNTAINS,
- EAX_ENVIRONMENT_QUARRY,
- EAX_ENVIRONMENT_PLAIN,
- EAX_ENVIRONMENT_PARKINGLOT,
- EAX_ENVIRONMENT_SEWERPIPE,
- EAX_ENVIRONMENT_UNDERWATER,
- EAX_ENVIRONMENT_DRUGGED,
- EAX_ENVIRONMENT_DIZZY,
- EAX_ENVIRONMENT_PSYCHOTIC,
-
- EAX_ENVIRONMENT_COUNT // total number of environments
-};
-
-// EAX presets, usage: BASS_SetEAXParameters(EAX_PRESET_xxx)
-#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F
-#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F
-#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F
-#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F
-#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F
-#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F
-#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F
-#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F
-#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F
-#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F
-#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F
-#define EAX_PRESET_CARPETEDHALLWAY \
- EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F
-#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F
-#define EAX_PRESET_STONECORRIDOR \
- EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F
-#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F
-#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F
-#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F
-#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F
-#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F
-#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F
-#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F
-#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F
-#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F
-#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F
-#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F
-#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F
-
-typedef DWORD(CALLBACK STREAMPROC)(HSTREAM handle, void *buffer, DWORD length,
- void *user);
-/* User stream callback function. NOTE: A stream function should obviously be as
-quick as possible, other streams (and MOD musics) can't be mixed until it's
-finished. handle : The stream that needs writing buffer : Buffer to write the
-samples in length : Number of bytes to write user : The 'user' parameter value
-given when calling BASS_StreamCreate RETURN : Number of bytes written. Set the
-BASS_STREAMPROC_END flag to end the stream. */
-
-#define BASS_STREAMPROC_END 0x80000000 // end of user stream flag
-
-// special STREAMPROCs
-#define STREAMPROC_DUMMY (STREAMPROC *)0 // "dummy" stream
-#define STREAMPROC_PUSH (STREAMPROC *)-1 // push stream
-#define STREAMPROC_DEVICE (STREAMPROC *)-2 // device mix stream
-
-// BASS_StreamCreateFileUser file systems
-#define STREAMFILE_NOBUFFER 0
-#define STREAMFILE_BUFFER 1
-#define STREAMFILE_BUFFERPUSH 2
-
-// User file stream callback functions
-typedef void(CALLBACK FILECLOSEPROC)(void *user);
-typedef QWORD(CALLBACK FILELENPROC)(void *user);
-typedef DWORD(CALLBACK FILEREADPROC)(void *buffer, DWORD length, void *user);
-typedef BOOL(CALLBACK FILESEEKPROC)(QWORD offset, void *user);
-
-typedef struct {
- FILECLOSEPROC *close;
- FILELENPROC *length;
- FILEREADPROC *read;
- FILESEEKPROC *seek;
-} BASS_FILEPROCS;
-
-// BASS_StreamPutFileData options
-#define BASS_FILEDATA_END 0 // end & close the file
-
-// BASS_StreamGetFilePosition modes
-#define BASS_FILEPOS_CURRENT 0
-#define BASS_FILEPOS_DECODE BASS_FILEPOS_CURRENT
-#define BASS_FILEPOS_DOWNLOAD 1
-#define BASS_FILEPOS_END 2
-#define BASS_FILEPOS_START 3
-#define BASS_FILEPOS_CONNECTED 4
-#define BASS_FILEPOS_BUFFER 5
-#define BASS_FILEPOS_SOCKET 6
-#define BASS_FILEPOS_ASYNCBUF 7
-#define BASS_FILEPOS_SIZE 8
-#define BASS_FILEPOS_BUFFERING 9
-
-typedef void(CALLBACK DOWNLOADPROC)(const void *buffer, DWORD length,
- void *user);
-/* Internet stream download callback function.
-buffer : Buffer containing the downloaded data... NULL=end of download
-length : Number of bytes in the buffer
-user : The 'user' parameter value given when calling BASS_StreamCreateURL */
-
-// BASS_ChannelSetSync types
-#define BASS_SYNC_POS 0
-#define BASS_SYNC_END 2
-#define BASS_SYNC_META 4
-#define BASS_SYNC_SLIDE 5
-#define BASS_SYNC_STALL 6
-#define BASS_SYNC_DOWNLOAD 7
-#define BASS_SYNC_FREE 8
-#define BASS_SYNC_SETPOS 11
-#define BASS_SYNC_MUSICPOS 10
-#define BASS_SYNC_MUSICINST 1
-#define BASS_SYNC_MUSICFX 3
-#define BASS_SYNC_OGG_CHANGE 12
-#define BASS_SYNC_MIXTIME 0x40000000 // flag: sync at mixtime, else at playtime
-#define BASS_SYNC_ONETIME 0x80000000 // flag: sync only once, else continuously
-
-typedef void(CALLBACK SYNCPROC)(HSYNC handle, DWORD channel, DWORD data,
- void *user);
-/* Sync callback function. NOTE: a sync callback function should be very
-quick as other syncs can't be processed until it has finished. If the sync
-is a "mixtime" sync, then other streams and MOD musics can't be mixed until
-it's finished either.
-handle : The sync that has occured
-channel: Channel that the sync occured in
-data : Additional data associated with the sync's occurance
-user : The 'user' parameter given when calling BASS_ChannelSetSync */
-
-typedef void(CALLBACK DSPPROC)(HDSP handle, DWORD channel, void *buffer,
- DWORD length, void *user);
-/* DSP callback function. NOTE: A DSP function should obviously be as quick as
-possible... other DSP functions, streams and MOD musics can not be processed
-until it's finished.
-handle : The DSP handle
-channel: Channel that the DSP is being applied to
-buffer : Buffer to apply the DSP to
-length : Number of bytes in the buffer
-user : The 'user' parameter given when calling BASS_ChannelSetDSP */
-
-typedef BOOL(CALLBACK RECORDPROC)(HRECORD handle, const void *buffer,
- DWORD length, void *user);
-/* Recording callback function.
-handle : The recording handle
-buffer : Buffer containing the recorded sample data
-length : Number of bytes
-user : The 'user' parameter value given when calling BASS_RecordStart
-RETURN : TRUE = continue recording, FALSE = stop */
-
-// BASS_ChannelIsActive return values
-#define BASS_ACTIVE_STOPPED 0
-#define BASS_ACTIVE_PLAYING 1
-#define BASS_ACTIVE_STALLED 2
-#define BASS_ACTIVE_PAUSED 3
-
-// Channel attributes
-#define BASS_ATTRIB_FREQ 1
-#define BASS_ATTRIB_VOL 2
-#define BASS_ATTRIB_PAN 3
-#define BASS_ATTRIB_EAXMIX 4
-#define BASS_ATTRIB_NOBUFFER 5
-#define BASS_ATTRIB_VBR 6
-#define BASS_ATTRIB_CPU 7
-#define BASS_ATTRIB_SRC 8
-#define BASS_ATTRIB_NET_RESUME 9
-#define BASS_ATTRIB_SCANINFO 10
-#define BASS_ATTRIB_NORAMP 11
-#define BASS_ATTRIB_BITRATE 12
-#define BASS_ATTRIB_BUFFER 13
-#define BASS_ATTRIB_MUSIC_AMPLIFY 0x100
-#define BASS_ATTRIB_MUSIC_PANSEP 0x101
-#define BASS_ATTRIB_MUSIC_PSCALER 0x102
-#define BASS_ATTRIB_MUSIC_BPM 0x103
-#define BASS_ATTRIB_MUSIC_SPEED 0x104
-#define BASS_ATTRIB_MUSIC_VOL_GLOBAL 0x105
-#define BASS_ATTRIB_MUSIC_ACTIVE 0x106
-#define BASS_ATTRIB_MUSIC_VOL_CHAN 0x200 // + channel #
-#define BASS_ATTRIB_MUSIC_VOL_INST 0x300 // + instrument #
-
-// BASS_ChannelSlideAttribute flags
-#define BASS_SLIDE_LOG 0x1000000
-
-// BASS_ChannelGetData flags
-#define BASS_DATA_AVAILABLE 0 // query how much data is buffered
-#define BASS_DATA_FIXED 0x20000000 // flag: return 8.24 fixed-point data
-#define BASS_DATA_FLOAT 0x40000000 // flag: return floating-point sample data
-#define BASS_DATA_FFT256 0x80000000 // 256 sample FFT
-#define BASS_DATA_FFT512 0x80000001 // 512 FFT
-#define BASS_DATA_FFT1024 0x80000002 // 1024 FFT
-#define BASS_DATA_FFT2048 0x80000003 // 2048 FFT
-#define BASS_DATA_FFT4096 0x80000004 // 4096 FFT
-#define BASS_DATA_FFT8192 0x80000005 // 8192 FFT
-#define BASS_DATA_FFT16384 0x80000006 // 16384 FFT
-#define BASS_DATA_FFT32768 0x80000007 // 32768 FFT
-#define BASS_DATA_FFT_INDIVIDUAL \
- 0x10 // FFT flag: FFT for each channel, else all combined
-#define BASS_DATA_FFT_NOWINDOW 0x20 // FFT flag: no Hanning window
-#define BASS_DATA_FFT_REMOVEDC 0x40 // FFT flag: pre-remove DC bias
-#define BASS_DATA_FFT_COMPLEX 0x80 // FFT flag: return complex data
-
-// BASS_ChannelGetLevelEx flags
-#define BASS_LEVEL_MONO 1
-#define BASS_LEVEL_STEREO 2
-#define BASS_LEVEL_RMS 4
-#define BASS_LEVEL_VOLPAN 8
-
-// BASS_ChannelGetTags types : what's returned
-#define BASS_TAG_ID3 0 // ID3v1 tags : TAG_ID3 structure
-#define BASS_TAG_ID3V2 1 // ID3v2 tags : variable length block
-#define BASS_TAG_OGG 2 // OGG comments : series of null-terminated UTF-8 strings
-#define BASS_TAG_HTTP 3 // HTTP headers : series of null-terminated ANSI strings
-#define BASS_TAG_ICY 4 // ICY headers : series of null-terminated ANSI strings
-#define BASS_TAG_META 5 // ICY metadata : ANSI string
-#define BASS_TAG_APE 6 // APE tags : series of null-terminated UTF-8 strings
-#define BASS_TAG_MP4 \
- 7 // MP4/iTunes metadata : series of null-terminated UTF-8 strings
-#define BASS_TAG_WMA 8 // WMA tags : series of null-terminated UTF-8 strings
-#define BASS_TAG_VENDOR 9 // OGG encoder : UTF-8 string
-#define BASS_TAG_LYRICS3 10 // Lyric3v2 tag : ASCII string
-#define BASS_TAG_CA_CODEC 11 // CoreAudio codec info : TAG_CA_CODEC structure
-#define BASS_TAG_MF \
- 13 // Media Foundation tags : series of null-terminated UTF-8 strings
-#define BASS_TAG_WAVEFORMAT 14 // WAVE format : WAVEFORMATEEX structure
-#define BASS_TAG_AM_MIME 15 // Android Media MIME type : ASCII string
-#define BASS_TAG_AM_NAME 16 // Android Media codec name : ASCII string
-#define BASS_TAG_RIFF_INFO \
- 0x100 // RIFF "INFO" tags : series of null-terminated ANSI strings
-#define BASS_TAG_RIFF_BEXT 0x101 // RIFF/BWF "bext" tags : TAG_BEXT structure
-#define BASS_TAG_RIFF_CART 0x102 // RIFF/BWF "cart" tags : TAG_CART structure
-#define BASS_TAG_RIFF_DISP 0x103 // RIFF "DISP" text tag : ANSI string
-#define BASS_TAG_RIFF_CUE 0x104 // RIFF "cue " chunk : TAG_CUE structure
-#define BASS_TAG_RIFF_SMPL 0x105 // RIFF "smpl" chunk : TAG_SMPL structure
-#define BASS_TAG_APE_BINARY \
- 0x1000 // + index #, binary APE tag : TAG_APE_BINARY structure
-#define BASS_TAG_MUSIC_NAME 0x10000 // MOD music name : ANSI string
-#define BASS_TAG_MUSIC_MESSAGE 0x10001 // MOD message : ANSI string
-#define BASS_TAG_MUSIC_ORDERS \
- 0x10002 // MOD order list : BYTE array of pattern numbers
-#define BASS_TAG_MUSIC_AUTH 0x10003 // MOD author : UTF-8 string
-#define BASS_TAG_MUSIC_INST \
- 0x10100 // + instrument #, MOD instrument name : ANSI string
-#define BASS_TAG_MUSIC_SAMPLE \
- 0x10300 // + sample #, MOD sample name : ANSI string
-
-// ID3v1 tag structure
-typedef struct {
- char id[3];
- char title[30];
- char artist[30];
- char album[30];
- char year[4];
- char comment[30];
- BYTE genre;
-} TAG_ID3;
-
-// Binary APE tag structure
-typedef struct {
- const char *key;
- const void *data;
- DWORD length;
-} TAG_APE_BINARY;
-
-// BWF "bext" tag structure
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4200)
-#endif
-#pragma pack(push, 1)
-typedef struct {
- char Description[256]; // description
- char Originator[32]; // name of the originator
- char OriginatorReference[32]; // reference of the originator
- char OriginationDate[10]; // date of creation (yyyy-mm-dd)
- char OriginationTime[8]; // time of creation (hh-mm-ss)
- QWORD TimeReference; // first sample count since midnight (little-endian)
- WORD Version; // BWF version (little-endian)
- BYTE UMID[64]; // SMPTE UMID
- BYTE Reserved[190];
-#if defined(__GNUC__) && __GNUC__ < 3
- char CodingHistory[0]; // history
-#elif 1 // change to 0 if compiler fails the following line
- char CodingHistory[]; // history
-#else
- char CodingHistory[1]; // history
-#endif
-} TAG_BEXT;
-#pragma pack(pop)
-
-// BWF "cart" tag structures
-typedef struct {
- DWORD dwUsage; // FOURCC timer usage ID
- DWORD dwValue; // timer value in samples from head
-} TAG_CART_TIMER;
-
-typedef struct {
- char Version[4]; // version of the data structure
- char Title[64]; // title of cart audio sequence
- char Artist[64]; // artist or creator name
- char CutID[64]; // cut number identification
- char ClientID[64]; // client identification
- char Category[64]; // category ID, PSA, NEWS, etc
- char Classification[64]; // classification or auxiliary key
- char OutCue[64]; // out cue text
- char StartDate[10]; // yyyy-mm-dd
- char StartTime[8]; // hh:mm:ss
- char EndDate[10]; // yyyy-mm-dd
- char EndTime[8]; // hh:mm:ss
- char ProducerAppID[64]; // name of vendor or application
- char ProducerAppVersion[64]; // version of producer application
- char UserDef[64]; // user defined text
- DWORD dwLevelReference; // sample value for 0 dB reference
- TAG_CART_TIMER PostTimer[8]; // 8 time markers after head
- char Reserved[276];
- char URL[1024]; // uniform resource locator
-#if defined(__GNUC__) && __GNUC__ < 3
- char TagText[0]; // free form text for scripts or tags
-#elif 1 // change to 0 if compiler fails the following line
- char TagText[]; // free form text for scripts or tags
-#else
- char TagText[1]; // free form text for scripts or tags
-#endif
-} TAG_CART;
-
-// RIFF "cue " tag structures
-typedef struct {
- DWORD dwName;
- DWORD dwPosition;
- DWORD fccChunk;
- DWORD dwChunkStart;
- DWORD dwBlockStart;
- DWORD dwSampleOffset;
-} TAG_CUE_POINT;
-
-typedef struct {
- DWORD dwCuePoints;
-#if defined(__GNUC__) && __GNUC__ < 3
- TAG_CUE_POINT CuePoints[0];
-#elif 1 // change to 0 if compiler fails the following line
- TAG_CUE_POINT CuePoints[];
-#else
- TAG_CUE_POINT CuePoints[1];
-#endif
-} TAG_CUE;
-
-// RIFF "smpl" tag structures
-typedef struct {
- DWORD dwIdentifier;
- DWORD dwType;
- DWORD dwStart;
- DWORD dwEnd;
- DWORD dwFraction;
- DWORD dwPlayCount;
-} TAG_SMPL_LOOP;
-
-typedef struct {
- DWORD dwManufacturer;
- DWORD dwProduct;
- DWORD dwSamplePeriod;
- DWORD dwMIDIUnityNote;
- DWORD dwMIDIPitchFraction;
- DWORD dwSMPTEFormat;
- DWORD dwSMPTEOffset;
- DWORD cSampleLoops;
- DWORD cbSamplerData;
-#if defined(__GNUC__) && __GNUC__ < 3
- TAG_SMPL_LOOP SampleLoops[0];
-#elif 1 // change to 0 if compiler fails the following line
- TAG_SMPL_LOOP SampleLoops[];
-#else
- TAG_SMPL_LOOP SampleLoops[1];
-#endif
-} TAG_SMPL;
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-// CoreAudio codec info structure
-typedef struct {
- DWORD ftype; // file format
- DWORD atype; // audio format
- const char *name; // description
-} TAG_CA_CODEC;
-
-#ifndef _WAVEFORMATEX_
-#define _WAVEFORMATEX_
-#pragma pack(push, 1)
-typedef struct tWAVEFORMATEX {
- WORD wFormatTag;
- WORD nChannels;
- DWORD nSamplesPerSec;
- DWORD nAvgBytesPerSec;
- WORD nBlockAlign;
- WORD wBitsPerSample;
- WORD cbSize;
-} WAVEFORMATEX, *PWAVEFORMATEX, *LPWAVEFORMATEX;
-typedef const WAVEFORMATEX *LPCWAVEFORMATEX;
-#pragma pack(pop)
-#endif
-
-// BASS_ChannelGetLength/GetPosition/SetPosition modes
-#define BASS_POS_BYTE 0 // byte position
-#define BASS_POS_MUSIC_ORDER 1 // order.row position, MAKELONG(order,row)
-#define BASS_POS_OGG 3 // OGG bitstream number
-#define BASS_POS_RESET 0x2000000 // flag: reset user file buffers
-#define BASS_POS_RELATIVE \
- 0x4000000 // flag: seek relative to the current position
-#define BASS_POS_INEXACT 0x8000000 // flag: allow seeking to inexact position
-#define BASS_POS_DECODE \
- 0x10000000 // flag: get the decoding (not playing) position
-#define BASS_POS_DECODETO \
- 0x20000000 // flag: decode to the position instead of seeking
-#define BASS_POS_SCAN 0x40000000 // flag: scan to the position
-
-// BASS_ChannelSetDevice/GetDevice option
-#define BASS_NODEVICE 0x20000
-
-// BASS_RecordSetInput flags
-#define BASS_INPUT_OFF 0x10000
-#define BASS_INPUT_ON 0x20000
-
-#define BASS_INPUT_TYPE_MASK 0xff000000
-#define BASS_INPUT_TYPE_UNDEF 0x00000000
-#define BASS_INPUT_TYPE_DIGITAL 0x01000000
-#define BASS_INPUT_TYPE_LINE 0x02000000
-#define BASS_INPUT_TYPE_MIC 0x03000000
-#define BASS_INPUT_TYPE_SYNTH 0x04000000
-#define BASS_INPUT_TYPE_CD 0x05000000
-#define BASS_INPUT_TYPE_PHONE 0x06000000
-#define BASS_INPUT_TYPE_SPEAKER 0x07000000
-#define BASS_INPUT_TYPE_WAVE 0x08000000
-#define BASS_INPUT_TYPE_AUX 0x09000000
-#define BASS_INPUT_TYPE_ANALOG 0x0a000000
-
-// BASS_ChannelSetFX effect types
-#define BASS_FX_DX8_CHORUS 0
-#define BASS_FX_DX8_COMPRESSOR 1
-#define BASS_FX_DX8_DISTORTION 2
-#define BASS_FX_DX8_ECHO 3
-#define BASS_FX_DX8_FLANGER 4
-#define BASS_FX_DX8_GARGLE 5
-#define BASS_FX_DX8_I3DL2REVERB 6
-#define BASS_FX_DX8_PARAMEQ 7
-#define BASS_FX_DX8_REVERB 8
-#define BASS_FX_VOLUME 9
-
-typedef struct {
- float fWetDryMix;
- float fDepth;
- float fFeedback;
- float fFrequency;
- DWORD lWaveform; // 0=triangle, 1=sine
- float fDelay;
- DWORD lPhase; // BASS_DX8_PHASE_xxx
-} BASS_DX8_CHORUS;
-
-typedef struct {
- float fGain;
- float fAttack;
- float fRelease;
- float fThreshold;
- float fRatio;
- float fPredelay;
-} BASS_DX8_COMPRESSOR;
-
-typedef struct {
- float fGain;
- float fEdge;
- float fPostEQCenterFrequency;
- float fPostEQBandwidth;
- float fPreLowpassCutoff;
-} BASS_DX8_DISTORTION;
-
-typedef struct {
- float fWetDryMix;
- float fFeedback;
- float fLeftDelay;
- float fRightDelay;
- BOOL lPanDelay;
-} BASS_DX8_ECHO;
-
-typedef struct {
- float fWetDryMix;
- float fDepth;
- float fFeedback;
- float fFrequency;
- DWORD lWaveform; // 0=triangle, 1=sine
- float fDelay;
- DWORD lPhase; // BASS_DX8_PHASE_xxx
-} BASS_DX8_FLANGER;
-
-typedef struct {
- DWORD dwRateHz; // Rate of modulation in hz
- DWORD dwWaveShape; // 0=triangle, 1=square
-} BASS_DX8_GARGLE;
-
-typedef struct {
- int lRoom; // [-10000, 0] default: -1000 mB
- int lRoomHF; // [-10000, 0] default: 0 mB
- float flRoomRolloffFactor; // [0.0, 10.0] default: 0.0
- float flDecayTime; // [0.1, 20.0] default: 1.49s
- float flDecayHFRatio; // [0.1, 2.0] default: 0.83
- int lReflections; // [-10000, 1000] default: -2602 mB
- float flReflectionsDelay; // [0.0, 0.3] default: 0.007 s
- int lReverb; // [-10000, 2000] default: 200 mB
- float flReverbDelay; // [0.0, 0.1] default: 0.011 s
- float flDiffusion; // [0.0, 100.0] default: 100.0 %
- float flDensity; // [0.0, 100.0] default: 100.0 %
- float flHFReference; // [20.0, 20000.0] default: 5000.0 Hz
-} BASS_DX8_I3DL2REVERB;
-
-typedef struct {
- float fCenter;
- float fBandwidth;
- float fGain;
-} BASS_DX8_PARAMEQ;
-
-typedef struct {
- float fInGain; // [-96.0,0.0] default: 0.0 dB
- float fReverbMix; // [-96.0,0.0] default: 0.0 db
- float fReverbTime; // [0.001,3000.0] default: 1000.0 ms
- float fHighFreqRTRatio; // [0.001,0.999] default: 0.001
-} BASS_DX8_REVERB;
-
-#define BASS_DX8_PHASE_NEG_180 0
-#define BASS_DX8_PHASE_NEG_90 1
-#define BASS_DX8_PHASE_ZERO 2
-#define BASS_DX8_PHASE_90 3
-#define BASS_DX8_PHASE_180 4
-
-typedef struct {
- float fTarget;
- float fCurrent;
- float fTime;
- DWORD lCurve;
-} BASS_FX_VOLUME_PARAM;
-
-typedef void(CALLBACK IOSNOTIFYPROC)(DWORD status);
-/* iOS notification callback function.
-status : The notification (BASS_IOSNOTIFY_xxx) */
-
-#define BASS_IOSNOTIFY_INTERRUPT 1 // interruption started
-#define BASS_IOSNOTIFY_INTERRUPT_END 2 // interruption ended
-
-BOOL BASSDEF(BASS_SetConfig)(DWORD option, DWORD value);
-DWORD BASSDEF(BASS_GetConfig)(DWORD option);
-BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, const void *value);
-void *BASSDEF(BASS_GetConfigPtr)(DWORD option);
-DWORD BASSDEF(BASS_GetVersion)();
-int BASSDEF(BASS_ErrorGetCode)();
-BOOL BASSDEF(BASS_GetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info);
-#if defined(_WIN32) && !defined(_WIN32_WCE) && \
- !(WINAPI_FAMILY && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
-BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, HWND win,
- const GUID *dsguid);
-#else
-BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, void *win,
- void *dsguid);
-#endif
-BOOL BASSDEF(BASS_SetDevice)(DWORD device);
-DWORD BASSDEF(BASS_GetDevice)();
-BOOL BASSDEF(BASS_Free)();
-#if defined(_WIN32) && !defined(_WIN32_WCE) && \
- !(WINAPI_FAMILY && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
-void *BASSDEF(BASS_GetDSoundObject)(DWORD object);
-#endif
-BOOL BASSDEF(BASS_GetInfo)(BASS_INFO *info);
-BOOL BASSDEF(BASS_Update)(DWORD length);
-float BASSDEF(BASS_GetCPU)();
-BOOL BASSDEF(BASS_Start)();
-BOOL BASSDEF(BASS_Stop)();
-BOOL BASSDEF(BASS_Pause)();
-BOOL BASSDEF(BASS_SetVolume)(float volume);
-float BASSDEF(BASS_GetVolume)();
-
-HPLUGIN BASSDEF(BASS_PluginLoad)(const char *file, DWORD flags);
-BOOL BASSDEF(BASS_PluginFree)(HPLUGIN handle);
-const BASS_PLUGININFO *BASSDEF(BASS_PluginGetInfo)(HPLUGIN handle);
-
-BOOL BASSDEF(BASS_Set3DFactors)(float distf, float rollf, float doppf);
-BOOL BASSDEF(BASS_Get3DFactors)(float *distf, float *rollf, float *doppf);
-BOOL BASSDEF(BASS_Set3DPosition)(const BASS_3DVECTOR *pos,
- const BASS_3DVECTOR *vel,
- const BASS_3DVECTOR *front,
- const BASS_3DVECTOR *top);
-BOOL BASSDEF(BASS_Get3DPosition)(BASS_3DVECTOR *pos, BASS_3DVECTOR *vel,
- BASS_3DVECTOR *front, BASS_3DVECTOR *top);
-void BASSDEF(BASS_Apply3D)();
-#if defined(_WIN32) && !defined(_WIN32_WCE) && \
- !(WINAPI_FAMILY && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
-BOOL BASSDEF(BASS_SetEAXParameters)(int env, float vol, float decay,
- float damp);
-BOOL BASSDEF(BASS_GetEAXParameters)(DWORD *env, float *vol, float *decay,
- float *damp);
-#endif
-
-HMUSIC BASSDEF(BASS_MusicLoad)(BOOL mem, const void *file, QWORD offset,
- DWORD length, DWORD flags, DWORD freq);
-BOOL BASSDEF(BASS_MusicFree)(HMUSIC handle);
-
-HSAMPLE BASSDEF(BASS_SampleLoad)(BOOL mem, const void *file, QWORD offset,
- DWORD length, DWORD max, DWORD flags);
-HSAMPLE BASSDEF(BASS_SampleCreate)(DWORD length, DWORD freq, DWORD chans,
- DWORD max, DWORD flags);
-BOOL BASSDEF(BASS_SampleFree)(HSAMPLE handle);
-BOOL BASSDEF(BASS_SampleSetData)(HSAMPLE handle, const void *buffer);
-BOOL BASSDEF(BASS_SampleGetData)(HSAMPLE handle, void *buffer);
-BOOL BASSDEF(BASS_SampleGetInfo)(HSAMPLE handle, BASS_SAMPLE *info);
-BOOL BASSDEF(BASS_SampleSetInfo)(HSAMPLE handle, const BASS_SAMPLE *info);
-HCHANNEL BASSDEF(BASS_SampleGetChannel)(HSAMPLE handle, BOOL onlynew);
-DWORD BASSDEF(BASS_SampleGetChannels)(HSAMPLE handle, HCHANNEL *channels);
-BOOL BASSDEF(BASS_SampleStop)(HSAMPLE handle);
-
-HSTREAM BASSDEF(BASS_StreamCreate)(DWORD freq, DWORD chans, DWORD flags,
- STREAMPROC *proc, void *user);
-HSTREAM BASSDEF(BASS_StreamCreateFile)(BOOL mem, const void *file, QWORD offset,
- QWORD length, DWORD flags);
-HSTREAM BASSDEF(BASS_StreamCreateURL)(const char *url, DWORD offset,
- DWORD flags, DOWNLOADPROC *proc,
- void *user);
-HSTREAM BASSDEF(BASS_StreamCreateFileUser)(DWORD system, DWORD flags,
- const BASS_FILEPROCS *proc,
- void *user);
-BOOL BASSDEF(BASS_StreamFree)(HSTREAM handle);
-QWORD BASSDEF(BASS_StreamGetFilePosition)(HSTREAM handle, DWORD mode);
-DWORD BASSDEF(BASS_StreamPutData)(HSTREAM handle, const void *buffer,
- DWORD length);
-DWORD BASSDEF(BASS_StreamPutFileData)(HSTREAM handle, const void *buffer,
- DWORD length);
-
-BOOL BASSDEF(BASS_RecordGetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info);
-BOOL BASSDEF(BASS_RecordInit)(int device);
-BOOL BASSDEF(BASS_RecordSetDevice)(DWORD device);
-DWORD BASSDEF(BASS_RecordGetDevice)();
-BOOL BASSDEF(BASS_RecordFree)();
-BOOL BASSDEF(BASS_RecordGetInfo)(BASS_RECORDINFO *info);
-const char *BASSDEF(BASS_RecordGetInputName)(int input);
-BOOL BASSDEF(BASS_RecordSetInput)(int input, DWORD flags, float volume);
-DWORD BASSDEF(BASS_RecordGetInput)(int input, float *volume);
-HRECORD BASSDEF(BASS_RecordStart)(DWORD freq, DWORD chans, DWORD flags,
- RECORDPROC *proc, void *user);
-
-double BASSDEF(BASS_ChannelBytes2Seconds)(DWORD handle, QWORD pos);
-QWORD BASSDEF(BASS_ChannelSeconds2Bytes)(DWORD handle, double pos);
-DWORD BASSDEF(BASS_ChannelGetDevice)(DWORD handle);
-BOOL BASSDEF(BASS_ChannelSetDevice)(DWORD handle, DWORD device);
-DWORD BASSDEF(BASS_ChannelIsActive)(DWORD handle);
-BOOL BASSDEF(BASS_ChannelGetInfo)(DWORD handle, BASS_CHANNELINFO *info);
-const char *BASSDEF(BASS_ChannelGetTags)(DWORD handle, DWORD tags);
-DWORD BASSDEF(BASS_ChannelFlags)(DWORD handle, DWORD flags, DWORD mask);
-BOOL BASSDEF(BASS_ChannelUpdate)(DWORD handle, DWORD length);
-BOOL BASSDEF(BASS_ChannelLock)(DWORD handle, BOOL lock);
-BOOL BASSDEF(BASS_ChannelPlay)(DWORD handle, BOOL restart);
-BOOL BASSDEF(BASS_ChannelStop)(DWORD handle);
-BOOL BASSDEF(BASS_ChannelPause)(DWORD handle);
-BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value);
-BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib,
- float *value);
-BOOL BASSDEF(BASS_ChannelSlideAttribute)(DWORD handle, DWORD attrib,
- float value, DWORD time);
-BOOL BASSDEF(BASS_ChannelIsSliding)(DWORD handle, DWORD attrib);
-BOOL BASSDEF(BASS_ChannelSetAttributeEx)(DWORD handle, DWORD attrib,
- void *value, DWORD size);
-DWORD BASSDEF(BASS_ChannelGetAttributeEx)(DWORD handle, DWORD attrib,
- void *value, DWORD size);
-BOOL BASSDEF(BASS_ChannelSet3DAttributes)(DWORD handle, int mode, float min,
- float max, int iangle, int oangle,
- float outvol);
-BOOL BASSDEF(BASS_ChannelGet3DAttributes)(DWORD handle, DWORD *mode, float *min,
- float *max, DWORD *iangle,
- DWORD *oangle, float *outvol);
-BOOL BASSDEF(BASS_ChannelSet3DPosition)(DWORD handle, const BASS_3DVECTOR *pos,
- const BASS_3DVECTOR *orient,
- const BASS_3DVECTOR *vel);
-BOOL BASSDEF(BASS_ChannelGet3DPosition)(DWORD handle, BASS_3DVECTOR *pos,
- BASS_3DVECTOR *orient,
- BASS_3DVECTOR *vel);
-QWORD BASSDEF(BASS_ChannelGetLength)(DWORD handle, DWORD mode);
-BOOL BASSDEF(BASS_ChannelSetPosition)(DWORD handle, QWORD pos, DWORD mode);
-QWORD BASSDEF(BASS_ChannelGetPosition)(DWORD handle, DWORD mode);
-DWORD BASSDEF(BASS_ChannelGetLevel)(DWORD handle);
-BOOL BASSDEF(BASS_ChannelGetLevelEx)(DWORD handle, float *levels, float length,
- DWORD flags);
-DWORD BASSDEF(BASS_ChannelGetData)(DWORD handle, void *buffer, DWORD length);
-HSYNC BASSDEF(BASS_ChannelSetSync)(DWORD handle, DWORD type, QWORD param,
- SYNCPROC *proc, void *user);
-BOOL BASSDEF(BASS_ChannelRemoveSync)(DWORD handle, HSYNC sync);
-HDSP BASSDEF(BASS_ChannelSetDSP)(DWORD handle, DSPPROC *proc, void *user,
- int priority);
-BOOL BASSDEF(BASS_ChannelRemoveDSP)(DWORD handle, HDSP dsp);
-BOOL BASSDEF(BASS_ChannelSetLink)(DWORD handle, DWORD chan);
-BOOL BASSDEF(BASS_ChannelRemoveLink)(DWORD handle, DWORD chan);
-HFX BASSDEF(BASS_ChannelSetFX)(DWORD handle, DWORD type, int priority);
-BOOL BASSDEF(BASS_ChannelRemoveFX)(DWORD handle, HFX fx);
-
-BOOL BASSDEF(BASS_FXSetParameters)(HFX handle, const void *params);
-BOOL BASSDEF(BASS_FXGetParameters)(HFX handle, void *params);
-BOOL BASSDEF(BASS_FXReset)(HFX handle);
-BOOL BASSDEF(BASS_FXSetPriority)(HFX handle, int priority);
-
-#ifdef __cplusplus
-}
-
-#if defined(_WIN32) && !defined(NOBASSOVERLOADS)
-static inline HPLUGIN BASS_PluginLoad(const WCHAR *file, DWORD flags)
-{
- return BASS_PluginLoad((const char *)file, flags | BASS_UNICODE);
-}
-
-static inline HMUSIC BASS_MusicLoad(BOOL mem, const WCHAR *file, QWORD offset,
- DWORD length, DWORD flags, DWORD freq)
-{
- return BASS_MusicLoad(mem, (const void *)file, offset, length,
- flags | BASS_UNICODE, freq);
-}
-
-static inline HSAMPLE BASS_SampleLoad(BOOL mem, const WCHAR *file, QWORD offset,
- DWORD length, DWORD max, DWORD flags)
-{
- return BASS_SampleLoad(mem, (const void *)file, offset, length, max,
- flags | BASS_UNICODE);
-}
-
-static inline HSTREAM BASS_StreamCreateFile(BOOL mem, const WCHAR *file,
- QWORD offset, QWORD length,
- DWORD flags)
-{
- return BASS_StreamCreateFile(mem, (const void *)file, offset, length,
- flags | BASS_UNICODE);
-}
-
-static inline HSTREAM BASS_StreamCreateURL(const WCHAR *url, DWORD offset,
- DWORD flags, DOWNLOADPROC *proc,
- void *user)
-{
- return BASS_StreamCreateURL((const char *)url, offset, flags | BASS_UNICODE,
- proc, user);
-}
-
-static inline BOOL BASS_SetConfigPtr(DWORD option, const WCHAR *value)
-{
- return BASS_SetConfigPtr(option | BASS_UNICODE, (const void *)value);
-}
-#endif
-#endif
-
-#endif
+/*
+ BASS 2.4 C/C++ header file
+ Copyright (c) 1999-2019 Un4seen Developments Ltd.
+
+ See the BASS.CHM file for more detailed documentation
+*/
+
+#ifndef BASS_H
+#define BASS_H
+
+#ifdef _WIN32
+#include <wtypes.h>
+typedef unsigned __int64 QWORD;
+#else
+#include <stdint.h>
+#define WINAPI
+#define CALLBACK
+typedef uint8_t BYTE;
+typedef uint16_t WORD;
+typedef uint32_t DWORD;
+typedef uint64_t QWORD;
+#ifndef __OBJC__
+typedef int BOOL;
+#endif
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+#define LOBYTE(a) (BYTE)(a)
+#define HIBYTE(a) (BYTE)((a) >> 8)
+#define LOWORD(a) (WORD)(a)
+#define HIWORD(a) (WORD)((a) >> 16)
+#define MAKEWORD(a, b) (WORD)(((a)&0xff) | ((b) << 8))
+#define MAKELONG(a, b) (DWORD)(((a)&0xffff) | ((b) << 16))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BASSVERSION 0x204 // API version
+#define BASSVERSIONTEXT "2.4"
+
+#ifndef BASSDEF
+#define BASSDEF(f) WINAPI f
+#else
+#define NOBASSOVERLOADS
+#endif
+
+typedef DWORD HMUSIC; // MOD music handle
+typedef DWORD HSAMPLE; // sample handle
+typedef DWORD HCHANNEL; // playing sample's channel handle
+typedef DWORD HSTREAM; // sample stream handle
+typedef DWORD HRECORD; // recording handle
+typedef DWORD HSYNC; // synchronizer handle
+typedef DWORD HDSP; // DSP handle
+typedef DWORD HFX; // DX8 effect handle
+typedef DWORD HPLUGIN; // Plugin handle
+
+// Error codes returned by BASS_ErrorGetCode
+#define BASS_OK 0 // all is OK
+#define BASS_ERROR_MEM 1 // memory error
+#define BASS_ERROR_FILEOPEN 2 // can't open the file
+#define BASS_ERROR_DRIVER 3 // can't find a free/valid driver
+#define BASS_ERROR_BUFLOST 4 // the sample buffer was lost
+#define BASS_ERROR_HANDLE 5 // invalid handle
+#define BASS_ERROR_FORMAT 6 // unsupported sample format
+#define BASS_ERROR_POSITION 7 // invalid position
+#define BASS_ERROR_INIT 8 // BASS_Init has not been successfully called
+#define BASS_ERROR_START 9 // BASS_Start has not been successfully called
+#define BASS_ERROR_SSL 10 // SSL/HTTPS support isn't available
+#define BASS_ERROR_ALREADY 14 // already initialized/paused/whatever
+#define BASS_ERROR_NOCHAN 18 // can't get a free channel
+#define BASS_ERROR_ILLTYPE 19 // an illegal type was specified
+#define BASS_ERROR_ILLPARAM 20 // an illegal parameter was specified
+#define BASS_ERROR_NO3D 21 // no 3D support
+#define BASS_ERROR_NOEAX 22 // no EAX support
+#define BASS_ERROR_DEVICE 23 // illegal device number
+#define BASS_ERROR_NOPLAY 24 // not playing
+#define BASS_ERROR_FREQ 25 // illegal sample rate
+#define BASS_ERROR_NOTFILE 27 // the stream is not a file stream
+#define BASS_ERROR_NOHW 29 // no hardware voices available
+#define BASS_ERROR_EMPTY 31 // the MOD music has no sequence data
+#define BASS_ERROR_NONET 32 // no internet connection could be opened
+#define BASS_ERROR_CREATE 33 // couldn't create the file
+#define BASS_ERROR_NOFX 34 // effects are not available
+#define BASS_ERROR_NOTAVAIL 37 // requested data/action is not available
+#define BASS_ERROR_DECODE 38 // the channel is/isn't a "decoding channel"
+#define BASS_ERROR_DX 39 // a sufficient DirectX version is not installed
+#define BASS_ERROR_TIMEOUT 40 // connection timedout
+#define BASS_ERROR_FILEFORM 41 // unsupported file format
+#define BASS_ERROR_SPEAKER 42 // unavailable speaker
+#define BASS_ERROR_VERSION 43 // invalid BASS version (used by add-ons)
+#define BASS_ERROR_CODEC 44 // codec is not available/supported
+#define BASS_ERROR_ENDED 45 // the channel/file has ended
+#define BASS_ERROR_BUSY 46 // the device is busy
+#define BASS_ERROR_UNKNOWN -1 // some other mystery problem
+
+// BASS_SetConfig options
+#define BASS_CONFIG_BUFFER 0
+#define BASS_CONFIG_UPDATEPERIOD 1
+#define BASS_CONFIG_GVOL_SAMPLE 4
+#define BASS_CONFIG_GVOL_STREAM 5
+#define BASS_CONFIG_GVOL_MUSIC 6
+#define BASS_CONFIG_CURVE_VOL 7
+#define BASS_CONFIG_CURVE_PAN 8
+#define BASS_CONFIG_FLOATDSP 9
+#define BASS_CONFIG_3DALGORITHM 10
+#define BASS_CONFIG_NET_TIMEOUT 11
+#define BASS_CONFIG_NET_BUFFER 12
+#define BASS_CONFIG_PAUSE_NOPLAY 13
+#define BASS_CONFIG_NET_PREBUF 15
+#define BASS_CONFIG_NET_PASSIVE 18
+#define BASS_CONFIG_REC_BUFFER 19
+#define BASS_CONFIG_NET_PLAYLIST 21
+#define BASS_CONFIG_MUSIC_VIRTUAL 22
+#define BASS_CONFIG_VERIFY 23
+#define BASS_CONFIG_UPDATETHREADS 24
+#define BASS_CONFIG_DEV_BUFFER 27
+#define BASS_CONFIG_REC_LOOPBACK 28
+#define BASS_CONFIG_VISTA_TRUEPOS 30
+#define BASS_CONFIG_IOS_MIXAUDIO 34
+#define BASS_CONFIG_DEV_DEFAULT 36
+#define BASS_CONFIG_NET_READTIMEOUT 37
+#define BASS_CONFIG_VISTA_SPEAKERS 38
+#define BASS_CONFIG_IOS_SPEAKER 39
+#define BASS_CONFIG_MF_DISABLE 40
+#define BASS_CONFIG_HANDLES 41
+#define BASS_CONFIG_UNICODE 42
+#define BASS_CONFIG_SRC 43
+#define BASS_CONFIG_SRC_SAMPLE 44
+#define BASS_CONFIG_ASYNCFILE_BUFFER 45
+#define BASS_CONFIG_OGG_PRESCAN 47
+#define BASS_CONFIG_MF_VIDEO 48
+#define BASS_CONFIG_AIRPLAY 49
+#define BASS_CONFIG_DEV_NONSTOP 50
+#define BASS_CONFIG_IOS_NOCATEGORY 51
+#define BASS_CONFIG_VERIFY_NET 52
+#define BASS_CONFIG_DEV_PERIOD 53
+#define BASS_CONFIG_FLOAT 54
+#define BASS_CONFIG_NET_SEEK 56
+#define BASS_CONFIG_AM_DISABLE 58
+#define BASS_CONFIG_NET_PLAYLIST_DEPTH 59
+#define BASS_CONFIG_NET_PREBUF_WAIT 60
+#define BASS_CONFIG_WASAPI_PERSIST 65
+#define BASS_CONFIG_REC_WASAPI 66
+
+// BASS_SetConfigPtr options
+#define BASS_CONFIG_NET_AGENT 16
+#define BASS_CONFIG_NET_PROXY 17
+#define BASS_CONFIG_IOS_NOTIFY 46
+#define BASS_CONFIG_LIBSSL 64
+
+// BASS_Init flags
+#define BASS_DEVICE_8BITS 1 // 8 bit
+#define BASS_DEVICE_MONO 2 // mono
+#define BASS_DEVICE_3D 4 // enable 3D functionality
+#define BASS_DEVICE_16BITS 8 // limit output to 16 bit
+#define BASS_DEVICE_LATENCY 0x100 // calculate device latency (BASS_INFO struct)
+#define BASS_DEVICE_CPSPEAKERS \
+ 0x400 // detect speakers via Windows control panel
+#define BASS_DEVICE_SPEAKERS 0x800 // force enabling of speaker assignment
+#define BASS_DEVICE_NOSPEAKER 0x1000 // ignore speaker arrangement
+#define BASS_DEVICE_DMIX 0x2000 // use ALSA "dmix" plugin
+#define BASS_DEVICE_FREQ 0x4000 // set device sample rate
+#define BASS_DEVICE_STEREO 0x8000 // limit output to stereo
+#define BASS_DEVICE_HOG 0x10000 // hog/exclusive mode
+#define BASS_DEVICE_AUDIOTRACK 0x20000 // use AudioTrack output
+#define BASS_DEVICE_DSOUND 0x40000 // use DirectSound output
+
+// DirectSound interfaces (for use with BASS_GetDSoundObject)
+#define BASS_OBJECT_DS 1 // IDirectSound
+#define BASS_OBJECT_DS3DL 2 // IDirectSound3DListener
+
+// Device info structure
+typedef struct {
+#if defined(_WIN32_WCE) || \
+ (WINAPI_FAMILY && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+ const wchar_t *name; // description
+ const wchar_t *driver; // driver
+#else
+ const char *name; // description
+ const char *driver; // driver
+#endif
+ DWORD flags;
+} BASS_DEVICEINFO;
+
+// BASS_DEVICEINFO flags
+#define BASS_DEVICE_ENABLED 1
+#define BASS_DEVICE_DEFAULT 2
+#define BASS_DEVICE_INIT 4
+#define BASS_DEVICE_LOOPBACK 8
+
+#define BASS_DEVICE_TYPE_MASK 0xff000000
+#define BASS_DEVICE_TYPE_NETWORK 0x01000000
+#define BASS_DEVICE_TYPE_SPEAKERS 0x02000000
+#define BASS_DEVICE_TYPE_LINE 0x03000000
+#define BASS_DEVICE_TYPE_HEADPHONES 0x04000000
+#define BASS_DEVICE_TYPE_MICROPHONE 0x05000000
+#define BASS_DEVICE_TYPE_HEADSET 0x06000000
+#define BASS_DEVICE_TYPE_HANDSET 0x07000000
+#define BASS_DEVICE_TYPE_DIGITAL 0x08000000
+#define BASS_DEVICE_TYPE_SPDIF 0x09000000
+#define BASS_DEVICE_TYPE_HDMI 0x0a000000
+#define BASS_DEVICE_TYPE_DISPLAYPORT 0x40000000
+
+// BASS_GetDeviceInfo flags
+#define BASS_DEVICES_AIRPLAY 0x1000000
+
+typedef struct {
+ DWORD flags; // device capabilities (DSCAPS_xxx flags)
+ DWORD hwsize; // size of total device hardware memory
+ DWORD hwfree; // size of free device hardware memory
+ DWORD freesam; // number of free sample slots in the hardware
+ DWORD free3d; // number of free 3D sample slots in the hardware
+ DWORD minrate; // min sample rate supported by the hardware
+ DWORD maxrate; // max sample rate supported by the hardware
+ BOOL
+ eax; // device supports EAX? (always FALSE if BASS_DEVICE_3D was not used)
+ DWORD minbuf; // recommended minimum buffer length in ms (requires
+ // BASS_DEVICE_LATENCY)
+ DWORD dsver; // DirectSound version
+ DWORD latency; // delay (in ms) before start of playback (requires
+ // BASS_DEVICE_LATENCY)
+ DWORD initflags; // BASS_Init "flags" parameter
+ DWORD speakers; // number of speakers available
+ DWORD freq; // current output rate
+} BASS_INFO;
+
+// BASS_INFO flags (from DSOUND.H)
+#define DSCAPS_CONTINUOUSRATE \
+ 0x00000010 // supports all sample rates between min/maxrate
+#define DSCAPS_EMULDRIVER \
+ 0x00000020 // device does NOT have hardware DirectSound support
+#define DSCAPS_CERTIFIED \
+ 0x00000040 // device driver has been certified by Microsoft
+#define DSCAPS_SECONDARYMONO 0x00000100 // mono
+#define DSCAPS_SECONDARYSTEREO 0x00000200 // stereo
+#define DSCAPS_SECONDARY8BIT 0x00000400 // 8 bit
+#define DSCAPS_SECONDARY16BIT 0x00000800 // 16 bit
+
+// Recording device info structure
+typedef struct {
+ DWORD flags; // device capabilities (DSCCAPS_xxx flags)
+ DWORD formats; // supported standard formats (WAVE_FORMAT_xxx flags)
+ DWORD inputs; // number of inputs
+ BOOL singlein; // TRUE = only 1 input can be set at a time
+ DWORD freq; // current input rate
+} BASS_RECORDINFO;
+
+// BASS_RECORDINFO flags (from DSOUND.H)
+#define DSCCAPS_EMULDRIVER \
+ DSCAPS_EMULDRIVER // device does NOT have hardware DirectSound recording
+ // support
+#define DSCCAPS_CERTIFIED \
+ DSCAPS_CERTIFIED // device driver has been certified by Microsoft
+
+// defines for formats field of BASS_RECORDINFO (from MMSYSTEM.H)
+#ifndef WAVE_FORMAT_1M08
+#define WAVE_FORMAT_1M08 0x00000001 /* 11.025 kHz, Mono, 8-bit */
+#define WAVE_FORMAT_1S08 0x00000002 /* 11.025 kHz, Stereo, 8-bit */
+#define WAVE_FORMAT_1M16 0x00000004 /* 11.025 kHz, Mono, 16-bit */
+#define WAVE_FORMAT_1S16 0x00000008 /* 11.025 kHz, Stereo, 16-bit */
+#define WAVE_FORMAT_2M08 0x00000010 /* 22.05 kHz, Mono, 8-bit */
+#define WAVE_FORMAT_2S08 0x00000020 /* 22.05 kHz, Stereo, 8-bit */
+#define WAVE_FORMAT_2M16 0x00000040 /* 22.05 kHz, Mono, 16-bit */
+#define WAVE_FORMAT_2S16 0x00000080 /* 22.05 kHz, Stereo, 16-bit */
+#define WAVE_FORMAT_4M08 0x00000100 /* 44.1 kHz, Mono, 8-bit */
+#define WAVE_FORMAT_4S08 0x00000200 /* 44.1 kHz, Stereo, 8-bit */
+#define WAVE_FORMAT_4M16 0x00000400 /* 44.1 kHz, Mono, 16-bit */
+#define WAVE_FORMAT_4S16 0x00000800 /* 44.1 kHz, Stereo, 16-bit */
+#endif
+
+// Sample info structure
+typedef struct {
+ DWORD freq; // default playback rate
+ float volume; // default volume (0-1)
+ float pan; // default pan (-1=left, 0=middle, 1=right)
+ DWORD flags; // BASS_SAMPLE_xxx flags
+ DWORD length; // length (in bytes)
+ DWORD max; // maximum simultaneous playbacks
+ DWORD origres; // original resolution
+ DWORD chans; // number of channels
+ DWORD mingap; // minimum gap (ms) between creating channels
+ DWORD mode3d; // BASS_3DMODE_xxx mode
+ float mindist; // minimum distance
+ float maxdist; // maximum distance
+ DWORD iangle; // angle of inside projection cone
+ DWORD oangle; // angle of outside projection cone
+ float outvol; // delta-volume outside the projection cone
+ DWORD vam; // voice allocation/management flags (BASS_VAM_xxx)
+ DWORD priority; // priority (0=lowest, 0xffffffff=highest)
+} BASS_SAMPLE;
+
+#define BASS_SAMPLE_8BITS 1 // 8 bit
+#define BASS_SAMPLE_FLOAT 256 // 32 bit floating-point
+#define BASS_SAMPLE_MONO 2 // mono
+#define BASS_SAMPLE_LOOP 4 // looped
+#define BASS_SAMPLE_3D 8 // 3D functionality
+#define BASS_SAMPLE_SOFTWARE 16 // not using hardware mixing
+#define BASS_SAMPLE_MUTEMAX 32 // mute at max distance (3D only)
+#define BASS_SAMPLE_VAM 64 // DX7 voice allocation & management
+#define BASS_SAMPLE_FX 128 // old implementation of DX8 effects
+#define BASS_SAMPLE_OVER_VOL 0x10000 // override lowest volume
+#define BASS_SAMPLE_OVER_POS 0x20000 // override longest playing
+#define BASS_SAMPLE_OVER_DIST \
+ 0x30000 // override furthest from listener (3D only)
+
+#define BASS_STREAM_PRESCAN \
+ 0x20000 // enable pin-point seeking/length (MP3/MP2/MP1)
+#define BASS_STREAM_AUTOFREE \
+ 0x40000 // automatically free the stream when it stop/ends
+#define BASS_STREAM_RESTRATE \
+ 0x80000 // restrict the download rate of internet file streams
+#define BASS_STREAM_BLOCK \
+ 0x100000 // download/play internet file stream in small blocks
+#define BASS_STREAM_DECODE \
+ 0x200000 // don't play the stream, only decode (BASS_ChannelGetData)
+#define BASS_STREAM_STATUS \
+ 0x800000 // give server status info (HTTP/ICY tags) in DOWNLOADPROC
+
+#define BASS_MP3_IGNOREDELAY \
+ 0x200 // ignore LAME/Xing/VBRI/iTunes delay & padding info
+#define BASS_MP3_SETPOS BASS_STREAM_PRESCAN
+
+#define BASS_MUSIC_FLOAT BASS_SAMPLE_FLOAT
+#define BASS_MUSIC_MONO BASS_SAMPLE_MONO
+#define BASS_MUSIC_LOOP BASS_SAMPLE_LOOP
+#define BASS_MUSIC_3D BASS_SAMPLE_3D
+#define BASS_MUSIC_FX BASS_SAMPLE_FX
+#define BASS_MUSIC_AUTOFREE BASS_STREAM_AUTOFREE
+#define BASS_MUSIC_DECODE BASS_STREAM_DECODE
+#define BASS_MUSIC_PRESCAN BASS_STREAM_PRESCAN // calculate playback length
+#define BASS_MUSIC_CALCLEN BASS_MUSIC_PRESCAN
+#define BASS_MUSIC_RAMP 0x200 // normal ramping
+#define BASS_MUSIC_RAMPS 0x400 // sensitive ramping
+#define BASS_MUSIC_SURROUND 0x800 // surround sound
+#define BASS_MUSIC_SURROUND2 0x1000 // surround sound (mode 2)
+#define BASS_MUSIC_FT2PAN 0x2000 // apply FastTracker 2 panning to XM files
+#define BASS_MUSIC_FT2MOD 0x2000 // play .MOD as FastTracker 2 does
+#define BASS_MUSIC_PT1MOD 0x4000 // play .MOD as ProTracker 1 does
+#define BASS_MUSIC_NONINTER 0x10000 // non-interpolated sample mixing
+#define BASS_MUSIC_SINCINTER 0x800000 // sinc interpolated sample mixing
+#define BASS_MUSIC_POSRESET 0x8000 // stop all notes when moving position
+#define BASS_MUSIC_POSRESETEX \
+ 0x400000 // stop all notes and reset bmp/etc when moving position
+#define BASS_MUSIC_STOPBACK 0x80000 // stop the music on a backwards jump effect
+#define BASS_MUSIC_NOSAMPLE 0x100000 // don't load the samples
+
+// Speaker assignment flags
+#define BASS_SPEAKER_FRONT 0x1000000 // front speakers
+#define BASS_SPEAKER_REAR 0x2000000 // rear/side speakers
+#define BASS_SPEAKER_CENLFE 0x3000000 // center & LFE speakers (5.1)
+#define BASS_SPEAKER_REAR2 0x4000000 // rear center speakers (7.1)
+#define BASS_SPEAKER_N(n) ((n) << 24) // n'th pair of speakers (max 15)
+#define BASS_SPEAKER_LEFT 0x10000000 // modifier: left
+#define BASS_SPEAKER_RIGHT 0x20000000 // modifier: right
+#define BASS_SPEAKER_FRONTLEFT BASS_SPEAKER_FRONT | BASS_SPEAKER_LEFT
+#define BASS_SPEAKER_FRONTRIGHT BASS_SPEAKER_FRONT | BASS_SPEAKER_RIGHT
+#define BASS_SPEAKER_REARLEFT BASS_SPEAKER_REAR | BASS_SPEAKER_LEFT
+#define BASS_SPEAKER_REARRIGHT BASS_SPEAKER_REAR | BASS_SPEAKER_RIGHT
+#define BASS_SPEAKER_CENTER BASS_SPEAKER_CENLFE | BASS_SPEAKER_LEFT
+#define BASS_SPEAKER_LFE BASS_SPEAKER_CENLFE | BASS_SPEAKER_RIGHT
+#define BASS_SPEAKER_REAR2LEFT BASS_SPEAKER_REAR2 | BASS_SPEAKER_LEFT
+#define BASS_SPEAKER_REAR2RIGHT BASS_SPEAKER_REAR2 | BASS_SPEAKER_RIGHT
+
+#define BASS_ASYNCFILE 0x40000000
+#define BASS_UNICODE 0x80000000
+
+#define BASS_RECORD_PAUSE 0x8000 // start recording paused
+#define BASS_RECORD_ECHOCANCEL 0x2000
+#define BASS_RECORD_AGC 0x4000
+
+// DX7 voice allocation & management flags
+#define BASS_VAM_HARDWARE 1
+#define BASS_VAM_SOFTWARE 2
+#define BASS_VAM_TERM_TIME 4
+#define BASS_VAM_TERM_DIST 8
+#define BASS_VAM_TERM_PRIO 16
+
+// Channel info structure
+typedef struct {
+ DWORD freq; // default playback rate
+ DWORD chans; // channels
+ DWORD flags; // BASS_SAMPLE/STREAM/MUSIC/SPEAKER flags
+ DWORD ctype; // type of channel
+ DWORD origres; // original resolution
+ HPLUGIN plugin; // plugin
+ HSAMPLE sample; // sample
+ const char *filename; // filename
+} BASS_CHANNELINFO;
+
+#define BASS_ORIGRES_FLOAT 0x10000
+
+// BASS_CHANNELINFO types
+#define BASS_CTYPE_SAMPLE 1
+#define BASS_CTYPE_RECORD 2
+#define BASS_CTYPE_STREAM 0x10000
+#define BASS_CTYPE_STREAM_OGG 0x10002
+#define BASS_CTYPE_STREAM_MP1 0x10003
+#define BASS_CTYPE_STREAM_MP2 0x10004
+#define BASS_CTYPE_STREAM_MP3 0x10005
+#define BASS_CTYPE_STREAM_AIFF 0x10006
+#define BASS_CTYPE_STREAM_CA 0x10007
+#define BASS_CTYPE_STREAM_MF 0x10008
+#define BASS_CTYPE_STREAM_AM 0x10009
+#define BASS_CTYPE_STREAM_DUMMY 0x18000
+#define BASS_CTYPE_STREAM_DEVICE 0x18001
+#define BASS_CTYPE_STREAM_WAV 0x40000 // WAVE flag, LOWORD=codec
+#define BASS_CTYPE_STREAM_WAV_PCM 0x50001
+#define BASS_CTYPE_STREAM_WAV_FLOAT 0x50003
+#define BASS_CTYPE_MUSIC_MOD 0x20000
+#define BASS_CTYPE_MUSIC_MTM 0x20001
+#define BASS_CTYPE_MUSIC_S3M 0x20002
+#define BASS_CTYPE_MUSIC_XM 0x20003
+#define BASS_CTYPE_MUSIC_IT 0x20004
+#define BASS_CTYPE_MUSIC_MO3 0x00100 // MO3 flag
+
+typedef struct {
+ DWORD ctype; // channel type
+#if defined(_WIN32_WCE) || \
+ (WINAPI_FAMILY && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+ const wchar_t *name; // format description
+ const wchar_t *exts; // file extension filter (*.ext1;*.ext2;etc...)
+#else
+ const char *name; // format description
+ const char *exts; // file extension filter (*.ext1;*.ext2;etc...)
+#endif
+} BASS_PLUGINFORM;
+
+typedef struct {
+ DWORD version; // version (same form as BASS_GetVersion)
+ DWORD formatc; // number of formats
+ const BASS_PLUGINFORM *formats; // the array of formats
+} BASS_PLUGININFO;
+
+// 3D vector (for 3D positions/velocities/orientations)
+typedef struct BASS_3DVECTOR {
+#ifdef __cplusplus
+ BASS_3DVECTOR(){};
+ BASS_3DVECTOR(float _x, float _y, float _z) : x(_x), y(_y), z(_z){};
+#endif
+ float x; // +=right, -=left
+ float y; // +=up, -=down
+ float z; // +=front, -=behind
+} BASS_3DVECTOR;
+
+// 3D channel modes
+#define BASS_3DMODE_NORMAL 0 // normal 3D processing
+#define BASS_3DMODE_RELATIVE 1 // position is relative to the listener
+#define BASS_3DMODE_OFF 2 // no 3D processing
+
+// software 3D mixing algorithms (used with BASS_CONFIG_3DALGORITHM)
+#define BASS_3DALG_DEFAULT 0
+#define BASS_3DALG_OFF 1
+#define BASS_3DALG_FULL 2
+#define BASS_3DALG_LIGHT 3
+
+// EAX environments, use with BASS_SetEAXParameters
+enum {
+ EAX_ENVIRONMENT_GENERIC,
+ EAX_ENVIRONMENT_PADDEDCELL,
+ EAX_ENVIRONMENT_ROOM,
+ EAX_ENVIRONMENT_BATHROOM,
+ EAX_ENVIRONMENT_LIVINGROOM,
+ EAX_ENVIRONMENT_STONEROOM,
+ EAX_ENVIRONMENT_AUDITORIUM,
+ EAX_ENVIRONMENT_CONCERTHALL,
+ EAX_ENVIRONMENT_CAVE,
+ EAX_ENVIRONMENT_ARENA,
+ EAX_ENVIRONMENT_HANGAR,
+ EAX_ENVIRONMENT_CARPETEDHALLWAY,
+ EAX_ENVIRONMENT_HALLWAY,
+ EAX_ENVIRONMENT_STONECORRIDOR,
+ EAX_ENVIRONMENT_ALLEY,
+ EAX_ENVIRONMENT_FOREST,
+ EAX_ENVIRONMENT_CITY,
+ EAX_ENVIRONMENT_MOUNTAINS,
+ EAX_ENVIRONMENT_QUARRY,
+ EAX_ENVIRONMENT_PLAIN,
+ EAX_ENVIRONMENT_PARKINGLOT,
+ EAX_ENVIRONMENT_SEWERPIPE,
+ EAX_ENVIRONMENT_UNDERWATER,
+ EAX_ENVIRONMENT_DRUGGED,
+ EAX_ENVIRONMENT_DIZZY,
+ EAX_ENVIRONMENT_PSYCHOTIC,
+
+ EAX_ENVIRONMENT_COUNT // total number of environments
+};
+
+// EAX presets, usage: BASS_SetEAXParameters(EAX_PRESET_xxx)
+#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC, 0.5F, 1.493F, 0.5F
+#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL, 0.25F, 0.1F, 0.0F
+#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM, 0.417F, 0.4F, 0.666F
+#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM, 0.653F, 1.499F, 0.166F
+#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM, 0.208F, 0.478F, 0.0F
+#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM, 0.5F, 2.309F, 0.888F
+#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM, 0.403F, 4.279F, 0.5F
+#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL, 0.5F, 3.961F, 0.5F
+#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE, 0.5F, 2.886F, 1.304F
+#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA, 0.361F, 7.284F, 0.332F
+#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR, 0.5F, 10.0F, 0.3F
+#define EAX_PRESET_CARPETEDHALLWAY \
+ EAX_ENVIRONMENT_CARPETEDHALLWAY, 0.153F, 0.259F, 2.0F
+#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY, 0.361F, 1.493F, 0.0F
+#define EAX_PRESET_STONECORRIDOR \
+ EAX_ENVIRONMENT_STONECORRIDOR, 0.444F, 2.697F, 0.638F
+#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY, 0.25F, 1.752F, 0.776F
+#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST, 0.111F, 3.145F, 0.472F
+#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY, 0.111F, 2.767F, 0.224F
+#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS, 0.194F, 7.841F, 0.472F
+#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY, 1.0F, 1.499F, 0.5F
+#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN, 0.097F, 2.767F, 0.224F
+#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT, 0.208F, 1.652F, 1.5F
+#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE, 0.652F, 2.886F, 0.25F
+#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER, 1.0F, 1.499F, 0.0F
+#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED, 0.875F, 8.392F, 1.388F
+#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY, 0.139F, 17.234F, 0.666F
+#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC, 0.486F, 7.563F, 0.806F
+
+typedef DWORD(CALLBACK STREAMPROC)(HSTREAM handle, void *buffer, DWORD length,
+ void *user);
+/* User stream callback function. NOTE: A stream function should obviously be as
+quick as possible, other streams (and MOD musics) can't be mixed until it's
+finished. handle : The stream that needs writing buffer : Buffer to write the
+samples in length : Number of bytes to write user : The 'user' parameter value
+given when calling BASS_StreamCreate RETURN : Number of bytes written. Set the
+BASS_STREAMPROC_END flag to end the stream. */
+
+#define BASS_STREAMPROC_END 0x80000000 // end of user stream flag
+
+// special STREAMPROCs
+#define STREAMPROC_DUMMY (STREAMPROC *)0 // "dummy" stream
+#define STREAMPROC_PUSH (STREAMPROC *)-1 // push stream
+#define STREAMPROC_DEVICE (STREAMPROC *)-2 // device mix stream
+#define STREAMPROC_DEVICE_3D (STREAMPROC *)-3 // device 3D mix stream
+
+// BASS_StreamCreateFileUser file systems
+#define STREAMFILE_NOBUFFER 0
+#define STREAMFILE_BUFFER 1
+#define STREAMFILE_BUFFERPUSH 2
+
+// User file stream callback functions
+typedef void(CALLBACK FILECLOSEPROC)(void *user);
+typedef QWORD(CALLBACK FILELENPROC)(void *user);
+typedef DWORD(CALLBACK FILEREADPROC)(void *buffer, DWORD length, void *user);
+typedef BOOL(CALLBACK FILESEEKPROC)(QWORD offset, void *user);
+
+typedef struct {
+ FILECLOSEPROC *close;
+ FILELENPROC *length;
+ FILEREADPROC *read;
+ FILESEEKPROC *seek;
+} BASS_FILEPROCS;
+
+// BASS_StreamPutFileData options
+#define BASS_FILEDATA_END 0 // end & close the file
+
+// BASS_StreamGetFilePosition modes
+#define BASS_FILEPOS_CURRENT 0
+#define BASS_FILEPOS_DECODE BASS_FILEPOS_CURRENT
+#define BASS_FILEPOS_DOWNLOAD 1
+#define BASS_FILEPOS_END 2
+#define BASS_FILEPOS_START 3
+#define BASS_FILEPOS_CONNECTED 4
+#define BASS_FILEPOS_BUFFER 5
+#define BASS_FILEPOS_SOCKET 6
+#define BASS_FILEPOS_ASYNCBUF 7
+#define BASS_FILEPOS_SIZE 8
+#define BASS_FILEPOS_BUFFERING 9
+
+typedef void(CALLBACK DOWNLOADPROC)(const void *buffer, DWORD length,
+ void *user);
+/* Internet stream download callback function.
+buffer : Buffer containing the downloaded data... NULL=end of download
+length : Number of bytes in the buffer
+user : The 'user' parameter value given when calling BASS_StreamCreateURL */
+
+// BASS_ChannelSetSync types
+#define BASS_SYNC_POS 0
+#define BASS_SYNC_END 2
+#define BASS_SYNC_META 4
+#define BASS_SYNC_SLIDE 5
+#define BASS_SYNC_STALL 6
+#define BASS_SYNC_DOWNLOAD 7
+#define BASS_SYNC_FREE 8
+#define BASS_SYNC_SETPOS 11
+#define BASS_SYNC_MUSICPOS 10
+#define BASS_SYNC_MUSICINST 1
+#define BASS_SYNC_MUSICFX 3
+#define BASS_SYNC_OGG_CHANGE 12
+#define BASS_SYNC_DEV_FAIL 14
+#define BASS_SYNC_DEV_FORMAT 15
+#define BASS_SYNC_MIXTIME 0x40000000 // flag: sync at mixtime, else at playtime
+#define BASS_SYNC_ONETIME 0x80000000 // flag: sync only once, else continuously
+
+typedef void(CALLBACK SYNCPROC)(HSYNC handle, DWORD channel, DWORD data,
+ void *user);
+/* Sync callback function. NOTE: a sync callback function should be very
+quick as other syncs can't be processed until it has finished. If the sync
+is a "mixtime" sync, then other streams and MOD musics can't be mixed until
+it's finished either.
+handle : The sync that has occured
+channel: Channel that the sync occured in
+data : Additional data associated with the sync's occurance
+user : The 'user' parameter given when calling BASS_ChannelSetSync */
+
+typedef void(CALLBACK DSPPROC)(HDSP handle, DWORD channel, void *buffer,
+ DWORD length, void *user);
+/* DSP callback function. NOTE: A DSP function should obviously be as quick as
+possible... other DSP functions, streams and MOD musics can not be processed
+until it's finished.
+handle : The DSP handle
+channel: Channel that the DSP is being applied to
+buffer : Buffer to apply the DSP to
+length : Number of bytes in the buffer
+user : The 'user' parameter given when calling BASS_ChannelSetDSP */
+
+typedef BOOL(CALLBACK RECORDPROC)(HRECORD handle, const void *buffer,
+ DWORD length, void *user);
+/* Recording callback function.
+handle : The recording handle
+buffer : Buffer containing the recorded sample data
+length : Number of bytes
+user : The 'user' parameter value given when calling BASS_RecordStart
+RETURN : TRUE = continue recording, FALSE = stop */
+
+// BASS_ChannelIsActive return values
+#define BASS_ACTIVE_STOPPED 0
+#define BASS_ACTIVE_PLAYING 1
+#define BASS_ACTIVE_STALLED 2
+#define BASS_ACTIVE_PAUSED 3
+#define BASS_ACTIVE_PAUSED_DEVICE 4
+
+// Channel attributes
+#define BASS_ATTRIB_FREQ 1
+#define BASS_ATTRIB_VOL 2
+#define BASS_ATTRIB_PAN 3
+#define BASS_ATTRIB_EAXMIX 4
+#define BASS_ATTRIB_NOBUFFER 5
+#define BASS_ATTRIB_VBR 6
+#define BASS_ATTRIB_CPU 7
+#define BASS_ATTRIB_SRC 8
+#define BASS_ATTRIB_NET_RESUME 9
+#define BASS_ATTRIB_SCANINFO 10
+#define BASS_ATTRIB_NORAMP 11
+#define BASS_ATTRIB_BITRATE 12
+#define BASS_ATTRIB_BUFFER 13
+#define BASS_ATTRIB_MUSIC_AMPLIFY 0x100
+#define BASS_ATTRIB_MUSIC_PANSEP 0x101
+#define BASS_ATTRIB_MUSIC_PSCALER 0x102
+#define BASS_ATTRIB_MUSIC_BPM 0x103
+#define BASS_ATTRIB_MUSIC_SPEED 0x104
+#define BASS_ATTRIB_MUSIC_VOL_GLOBAL 0x105
+#define BASS_ATTRIB_MUSIC_ACTIVE 0x106
+#define BASS_ATTRIB_MUSIC_VOL_CHAN 0x200 // + channel #
+#define BASS_ATTRIB_MUSIC_VOL_INST 0x300 // + instrument #
+
+// BASS_ChannelSlideAttribute flags
+#define BASS_SLIDE_LOG 0x1000000
+
+// BASS_ChannelGetData flags
+#define BASS_DATA_AVAILABLE 0 // query how much data is buffered
+#define BASS_DATA_FIXED 0x20000000 // flag: return 8.24 fixed-point data
+#define BASS_DATA_FLOAT 0x40000000 // flag: return floating-point sample data
+#define BASS_DATA_FFT256 0x80000000 // 256 sample FFT
+#define BASS_DATA_FFT512 0x80000001 // 512 FFT
+#define BASS_DATA_FFT1024 0x80000002 // 1024 FFT
+#define BASS_DATA_FFT2048 0x80000003 // 2048 FFT
+#define BASS_DATA_FFT4096 0x80000004 // 4096 FFT
+#define BASS_DATA_FFT8192 0x80000005 // 8192 FFT
+#define BASS_DATA_FFT16384 0x80000006 // 16384 FFT
+#define BASS_DATA_FFT32768 0x80000007 // 32768 FFT
+#define BASS_DATA_FFT_INDIVIDUAL \
+ 0x10 // FFT flag: FFT for each channel, else all combined
+#define BASS_DATA_FFT_NOWINDOW 0x20 // FFT flag: no Hanning window
+#define BASS_DATA_FFT_REMOVEDC 0x40 // FFT flag: pre-remove DC bias
+#define BASS_DATA_FFT_COMPLEX 0x80 // FFT flag: return complex data
+#define BASS_DATA_FFT_NYQUIST 0x100 // FFT flag: return extra Nyquist value
+
+// BASS_ChannelGetLevelEx flags
+#define BASS_LEVEL_MONO 1
+#define BASS_LEVEL_STEREO 2
+#define BASS_LEVEL_RMS 4
+#define BASS_LEVEL_VOLPAN 8
+
+// BASS_ChannelGetTags types : what's returned
+#define BASS_TAG_ID3 0 // ID3v1 tags : TAG_ID3 structure
+#define BASS_TAG_ID3V2 1 // ID3v2 tags : variable length block
+#define BASS_TAG_OGG 2 // OGG comments : series of null-terminated UTF-8 strings
+#define BASS_TAG_HTTP 3 // HTTP headers : series of null-terminated ANSI strings
+#define BASS_TAG_ICY 4 // ICY headers : series of null-terminated ANSI strings
+#define BASS_TAG_META 5 // ICY metadata : ANSI string
+#define BASS_TAG_APE 6 // APE tags : series of null-terminated UTF-8 strings
+#define BASS_TAG_MP4 \
+ 7 // MP4/iTunes metadata : series of null-terminated UTF-8 strings
+#define BASS_TAG_WMA 8 // WMA tags : series of null-terminated UTF-8 strings
+#define BASS_TAG_VENDOR 9 // OGG encoder : UTF-8 string
+#define BASS_TAG_LYRICS3 10 // Lyric3v2 tag : ASCII string
+#define BASS_TAG_CA_CODEC 11 // CoreAudio codec info : TAG_CA_CODEC structure
+#define BASS_TAG_MF \
+ 13 // Media Foundation tags : series of null-terminated UTF-8 strings
+#define BASS_TAG_WAVEFORMAT 14 // WAVE format : WAVEFORMATEEX structure
+#define BASS_TAG_AM_MIME 15 // Android Media MIME type : ASCII string
+#define BASS_TAG_AM_NAME 16 // Android Media codec name : ASCII string
+#define BASS_TAG_RIFF_INFO \
+ 0x100 // RIFF "INFO" tags : series of null-terminated ANSI strings
+#define BASS_TAG_RIFF_BEXT 0x101 // RIFF/BWF "bext" tags : TAG_BEXT structure
+#define BASS_TAG_RIFF_CART 0x102 // RIFF/BWF "cart" tags : TAG_CART structure
+#define BASS_TAG_RIFF_DISP 0x103 // RIFF "DISP" text tag : ANSI string
+#define BASS_TAG_RIFF_CUE 0x104 // RIFF "cue " chunk : TAG_CUE structure
+#define BASS_TAG_RIFF_SMPL 0x105 // RIFF "smpl" chunk : TAG_SMPL structure
+#define BASS_TAG_APE_BINARY \
+ 0x1000 // + index #, binary APE tag : TAG_APE_BINARY structure
+#define BASS_TAG_MUSIC_NAME 0x10000 // MOD music name : ANSI string
+#define BASS_TAG_MUSIC_MESSAGE 0x10001 // MOD message : ANSI string
+#define BASS_TAG_MUSIC_ORDERS \
+ 0x10002 // MOD order list : BYTE array of pattern numbers
+#define BASS_TAG_MUSIC_AUTH 0x10003 // MOD author : UTF-8 string
+#define BASS_TAG_MUSIC_INST \
+ 0x10100 // + instrument #, MOD instrument name : ANSI string
+#define BASS_TAG_MUSIC_SAMPLE \
+ 0x10300 // + sample #, MOD sample name : ANSI string
+
+// ID3v1 tag structure
+typedef struct {
+ char id[3];
+ char title[30];
+ char artist[30];
+ char album[30];
+ char year[4];
+ char comment[30];
+ BYTE genre;
+} TAG_ID3;
+
+// Binary APE tag structure
+typedef struct {
+ const char *key;
+ const void *data;
+ DWORD length;
+} TAG_APE_BINARY;
+
+// BWF "bext" tag structure
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4200)
+#endif
+#pragma pack(push, 1)
+typedef struct {
+ char Description[256]; // description
+ char Originator[32]; // name of the originator
+ char OriginatorReference[32]; // reference of the originator
+ char OriginationDate[10]; // date of creation (yyyy-mm-dd)
+ char OriginationTime[8]; // time of creation (hh-mm-ss)
+ QWORD TimeReference; // first sample count since midnight (little-endian)
+ WORD Version; // BWF version (little-endian)
+ BYTE UMID[64]; // SMPTE UMID
+ BYTE Reserved[190];
+#if defined(__GNUC__) && __GNUC__ < 3
+ char CodingHistory[0]; // history
+#elif 1 // change to 0 if compiler fails the following line
+ char CodingHistory[]; // history
+#else
+ char CodingHistory[1]; // history
+#endif
+} TAG_BEXT;
+#pragma pack(pop)
+
+// BWF "cart" tag structures
+typedef struct {
+ DWORD dwUsage; // FOURCC timer usage ID
+ DWORD dwValue; // timer value in samples from head
+} TAG_CART_TIMER;
+
+typedef struct {
+ char Version[4]; // version of the data structure
+ char Title[64]; // title of cart audio sequence
+ char Artist[64]; // artist or creator name
+ char CutID[64]; // cut number identification
+ char ClientID[64]; // client identification
+ char Category[64]; // category ID, PSA, NEWS, etc
+ char Classification[64]; // classification or auxiliary key
+ char OutCue[64]; // out cue text
+ char StartDate[10]; // yyyy-mm-dd
+ char StartTime[8]; // hh:mm:ss
+ char EndDate[10]; // yyyy-mm-dd
+ char EndTime[8]; // hh:mm:ss
+ char ProducerAppID[64]; // name of vendor or application
+ char ProducerAppVersion[64]; // version of producer application
+ char UserDef[64]; // user defined text
+ DWORD dwLevelReference; // sample value for 0 dB reference
+ TAG_CART_TIMER PostTimer[8]; // 8 time markers after head
+ char Reserved[276];
+ char URL[1024]; // uniform resource locator
+#if defined(__GNUC__) && __GNUC__ < 3
+ char TagText[0]; // free form text for scripts or tags
+#elif 1 // change to 0 if compiler fails the following line
+ char TagText[]; // free form text for scripts or tags
+#else
+ char TagText[1]; // free form text for scripts or tags
+#endif
+} TAG_CART;
+
+// RIFF "cue " tag structures
+typedef struct {
+ DWORD dwName;
+ DWORD dwPosition;
+ DWORD fccChunk;
+ DWORD dwChunkStart;
+ DWORD dwBlockStart;
+ DWORD dwSampleOffset;
+} TAG_CUE_POINT;
+
+typedef struct {
+ DWORD dwCuePoints;
+#if defined(__GNUC__) && __GNUC__ < 3
+ TAG_CUE_POINT CuePoints[0];
+#elif 1 // change to 0 if compiler fails the following line
+ TAG_CUE_POINT CuePoints[];
+#else
+ TAG_CUE_POINT CuePoints[1];
+#endif
+} TAG_CUE;
+
+// RIFF "smpl" tag structures
+typedef struct {
+ DWORD dwIdentifier;
+ DWORD dwType;
+ DWORD dwStart;
+ DWORD dwEnd;
+ DWORD dwFraction;
+ DWORD dwPlayCount;
+} TAG_SMPL_LOOP;
+
+typedef struct {
+ DWORD dwManufacturer;
+ DWORD dwProduct;
+ DWORD dwSamplePeriod;
+ DWORD dwMIDIUnityNote;
+ DWORD dwMIDIPitchFraction;
+ DWORD dwSMPTEFormat;
+ DWORD dwSMPTEOffset;
+ DWORD cSampleLoops;
+ DWORD cbSamplerData;
+#if defined(__GNUC__) && __GNUC__ < 3
+ TAG_SMPL_LOOP SampleLoops[0];
+#elif 1 // change to 0 if compiler fails the following line
+ TAG_SMPL_LOOP SampleLoops[];
+#else
+ TAG_SMPL_LOOP SampleLoops[1];
+#endif
+} TAG_SMPL;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+// CoreAudio codec info structure
+typedef struct {
+ DWORD ftype; // file format
+ DWORD atype; // audio format
+ const char *name; // description
+} TAG_CA_CODEC;
+
+#ifndef _WAVEFORMATEX_
+#define _WAVEFORMATEX_
+#pragma pack(push, 1)
+typedef struct tWAVEFORMATEX {
+ WORD wFormatTag;
+ WORD nChannels;
+ DWORD nSamplesPerSec;
+ DWORD nAvgBytesPerSec;
+ WORD nBlockAlign;
+ WORD wBitsPerSample;
+ WORD cbSize;
+} WAVEFORMATEX, *PWAVEFORMATEX, *LPWAVEFORMATEX;
+typedef const WAVEFORMATEX *LPCWAVEFORMATEX;
+#pragma pack(pop)
+#endif
+
+// BASS_ChannelGetLength/GetPosition/SetPosition modes
+#define BASS_POS_BYTE 0 // byte position
+#define BASS_POS_MUSIC_ORDER 1 // order.row position, MAKELONG(order,row)
+#define BASS_POS_OGG 3 // OGG bitstream number
+#define BASS_POS_RESET 0x2000000 // flag: reset user file buffers
+#define BASS_POS_RELATIVE \
+ 0x4000000 // flag: seek relative to the current position
+#define BASS_POS_INEXACT 0x8000000 // flag: allow seeking to inexact position
+#define BASS_POS_DECODE \
+ 0x10000000 // flag: get the decoding (not playing) position
+#define BASS_POS_DECODETO \
+ 0x20000000 // flag: decode to the position instead of seeking
+#define BASS_POS_SCAN 0x40000000 // flag: scan to the position
+
+// BASS_ChannelSetDevice/GetDevice option
+#define BASS_NODEVICE 0x20000
+
+// BASS_RecordSetInput flags
+#define BASS_INPUT_OFF 0x10000
+#define BASS_INPUT_ON 0x20000
+
+#define BASS_INPUT_TYPE_MASK 0xff000000
+#define BASS_INPUT_TYPE_UNDEF 0x00000000
+#define BASS_INPUT_TYPE_DIGITAL 0x01000000
+#define BASS_INPUT_TYPE_LINE 0x02000000
+#define BASS_INPUT_TYPE_MIC 0x03000000
+#define BASS_INPUT_TYPE_SYNTH 0x04000000
+#define BASS_INPUT_TYPE_CD 0x05000000
+#define BASS_INPUT_TYPE_PHONE 0x06000000
+#define BASS_INPUT_TYPE_SPEAKER 0x07000000
+#define BASS_INPUT_TYPE_WAVE 0x08000000
+#define BASS_INPUT_TYPE_AUX 0x09000000
+#define BASS_INPUT_TYPE_ANALOG 0x0a000000
+
+// BASS_ChannelSetFX effect types
+#define BASS_FX_DX8_CHORUS 0
+#define BASS_FX_DX8_COMPRESSOR 1
+#define BASS_FX_DX8_DISTORTION 2
+#define BASS_FX_DX8_ECHO 3
+#define BASS_FX_DX8_FLANGER 4
+#define BASS_FX_DX8_GARGLE 5
+#define BASS_FX_DX8_I3DL2REVERB 6
+#define BASS_FX_DX8_PARAMEQ 7
+#define BASS_FX_DX8_REVERB 8
+#define BASS_FX_VOLUME 9
+
+typedef struct {
+ float fWetDryMix;
+ float fDepth;
+ float fFeedback;
+ float fFrequency;
+ DWORD lWaveform; // 0=triangle, 1=sine
+ float fDelay;
+ DWORD lPhase; // BASS_DX8_PHASE_xxx
+} BASS_DX8_CHORUS;
+
+typedef struct {
+ float fGain;
+ float fAttack;
+ float fRelease;
+ float fThreshold;
+ float fRatio;
+ float fPredelay;
+} BASS_DX8_COMPRESSOR;
+
+typedef struct {
+ float fGain;
+ float fEdge;
+ float fPostEQCenterFrequency;
+ float fPostEQBandwidth;
+ float fPreLowpassCutoff;
+} BASS_DX8_DISTORTION;
+
+typedef struct {
+ float fWetDryMix;
+ float fFeedback;
+ float fLeftDelay;
+ float fRightDelay;
+ BOOL lPanDelay;
+} BASS_DX8_ECHO;
+
+typedef struct {
+ float fWetDryMix;
+ float fDepth;
+ float fFeedback;
+ float fFrequency;
+ DWORD lWaveform; // 0=triangle, 1=sine
+ float fDelay;
+ DWORD lPhase; // BASS_DX8_PHASE_xxx
+} BASS_DX8_FLANGER;
+
+typedef struct {
+ DWORD dwRateHz; // Rate of modulation in hz
+ DWORD dwWaveShape; // 0=triangle, 1=square
+} BASS_DX8_GARGLE;
+
+typedef struct {
+ int lRoom; // [-10000, 0] default: -1000 mB
+ int lRoomHF; // [-10000, 0] default: 0 mB
+ float flRoomRolloffFactor; // [0.0, 10.0] default: 0.0
+ float flDecayTime; // [0.1, 20.0] default: 1.49s
+ float flDecayHFRatio; // [0.1, 2.0] default: 0.83
+ int lReflections; // [-10000, 1000] default: -2602 mB
+ float flReflectionsDelay; // [0.0, 0.3] default: 0.007 s
+ int lReverb; // [-10000, 2000] default: 200 mB
+ float flReverbDelay; // [0.0, 0.1] default: 0.011 s
+ float flDiffusion; // [0.0, 100.0] default: 100.0 %
+ float flDensity; // [0.0, 100.0] default: 100.0 %
+ float flHFReference; // [20.0, 20000.0] default: 5000.0 Hz
+} BASS_DX8_I3DL2REVERB;
+
+typedef struct {
+ float fCenter;
+ float fBandwidth;
+ float fGain;
+} BASS_DX8_PARAMEQ;
+
+typedef struct {
+ float fInGain; // [-96.0,0.0] default: 0.0 dB
+ float fReverbMix; // [-96.0,0.0] default: 0.0 db
+ float fReverbTime; // [0.001,3000.0] default: 1000.0 ms
+ float fHighFreqRTRatio; // [0.001,0.999] default: 0.001
+} BASS_DX8_REVERB;
+
+#define BASS_DX8_PHASE_NEG_180 0
+#define BASS_DX8_PHASE_NEG_90 1
+#define BASS_DX8_PHASE_ZERO 2
+#define BASS_DX8_PHASE_90 3
+#define BASS_DX8_PHASE_180 4
+
+typedef struct {
+ float fTarget;
+ float fCurrent;
+ float fTime;
+ DWORD lCurve;
+} BASS_FX_VOLUME_PARAM;
+
+typedef void(CALLBACK IOSNOTIFYPROC)(DWORD status);
+/* iOS notification callback function.
+status : The notification (BASS_IOSNOTIFY_xxx) */
+
+#define BASS_IOSNOTIFY_INTERRUPT 1 // interruption started
+#define BASS_IOSNOTIFY_INTERRUPT_END 2 // interruption ended
+
+BOOL BASSDEF(BASS_SetConfig)(DWORD option, DWORD value);
+DWORD BASSDEF(BASS_GetConfig)(DWORD option);
+BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, const void *value);
+void *BASSDEF(BASS_GetConfigPtr)(DWORD option);
+DWORD BASSDEF(BASS_GetVersion)();
+int BASSDEF(BASS_ErrorGetCode)();
+BOOL BASSDEF(BASS_GetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info);
+#if defined(_WIN32) && !defined(_WIN32_WCE) && \
+ !(WINAPI_FAMILY && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, HWND win,
+ const GUID *dsguid);
+#else
+BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, void *win,
+ void *dsguid);
+#endif
+BOOL BASSDEF(BASS_SetDevice)(DWORD device);
+DWORD BASSDEF(BASS_GetDevice)();
+BOOL BASSDEF(BASS_Free)();
+#if defined(_WIN32) && !defined(_WIN32_WCE) && \
+ !(WINAPI_FAMILY && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+void *BASSDEF(BASS_GetDSoundObject)(DWORD object);
+#endif
+BOOL BASSDEF(BASS_GetInfo)(BASS_INFO *info);
+BOOL BASSDEF(BASS_Update)(DWORD length);
+float BASSDEF(BASS_GetCPU)();
+BOOL BASSDEF(BASS_Start)();
+BOOL BASSDEF(BASS_Stop)();
+BOOL BASSDEF(BASS_Pause)();
+BOOL BASSDEF(BASS_IsStarted)();
+BOOL BASSDEF(BASS_SetVolume)(float volume);
+float BASSDEF(BASS_GetVolume)();
+
+HPLUGIN BASSDEF(BASS_PluginLoad)(const char *file, DWORD flags);
+BOOL BASSDEF(BASS_PluginFree)(HPLUGIN handle);
+const BASS_PLUGININFO *BASSDEF(BASS_PluginGetInfo)(HPLUGIN handle);
+
+BOOL BASSDEF(BASS_Set3DFactors)(float distf, float rollf, float doppf);
+BOOL BASSDEF(BASS_Get3DFactors)(float *distf, float *rollf, float *doppf);
+BOOL BASSDEF(BASS_Set3DPosition)(const BASS_3DVECTOR *pos,
+ const BASS_3DVECTOR *vel,
+ const BASS_3DVECTOR *front,
+ const BASS_3DVECTOR *top);
+BOOL BASSDEF(BASS_Get3DPosition)(BASS_3DVECTOR *pos, BASS_3DVECTOR *vel,
+ BASS_3DVECTOR *front, BASS_3DVECTOR *top);
+void BASSDEF(BASS_Apply3D)();
+#if defined(_WIN32) && !defined(_WIN32_WCE) && \
+ !(WINAPI_FAMILY && WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+BOOL BASSDEF(BASS_SetEAXParameters)(int env, float vol, float decay,
+ float damp);
+BOOL BASSDEF(BASS_GetEAXParameters)(DWORD *env, float *vol, float *decay,
+ float *damp);
+#endif
+
+HMUSIC BASSDEF(BASS_MusicLoad)(BOOL mem, const void *file, QWORD offset,
+ DWORD length, DWORD flags, DWORD freq);
+BOOL BASSDEF(BASS_MusicFree)(HMUSIC handle);
+
+HSAMPLE BASSDEF(BASS_SampleLoad)(BOOL mem, const void *file, QWORD offset,
+ DWORD length, DWORD max, DWORD flags);
+HSAMPLE BASSDEF(BASS_SampleCreate)(DWORD length, DWORD freq, DWORD chans,
+ DWORD max, DWORD flags);
+BOOL BASSDEF(BASS_SampleFree)(HSAMPLE handle);
+BOOL BASSDEF(BASS_SampleSetData)(HSAMPLE handle, const void *buffer);
+BOOL BASSDEF(BASS_SampleGetData)(HSAMPLE handle, void *buffer);
+BOOL BASSDEF(BASS_SampleGetInfo)(HSAMPLE handle, BASS_SAMPLE *info);
+BOOL BASSDEF(BASS_SampleSetInfo)(HSAMPLE handle, const BASS_SAMPLE *info);
+HCHANNEL BASSDEF(BASS_SampleGetChannel)(HSAMPLE handle, BOOL onlynew);
+DWORD BASSDEF(BASS_SampleGetChannels)(HSAMPLE handle, HCHANNEL *channels);
+BOOL BASSDEF(BASS_SampleStop)(HSAMPLE handle);
+
+HSTREAM BASSDEF(BASS_StreamCreate)(DWORD freq, DWORD chans, DWORD flags,
+ STREAMPROC *proc, void *user);
+HSTREAM BASSDEF(BASS_StreamCreateFile)(BOOL mem, const void *file, QWORD offset,
+ QWORD length, DWORD flags);
+HSTREAM BASSDEF(BASS_StreamCreateURL)(const char *url, DWORD offset,
+ DWORD flags, DOWNLOADPROC *proc,
+ void *user);
+HSTREAM BASSDEF(BASS_StreamCreateFileUser)(DWORD system, DWORD flags,
+ const BASS_FILEPROCS *proc,
+ void *user);
+BOOL BASSDEF(BASS_StreamFree)(HSTREAM handle);
+QWORD BASSDEF(BASS_StreamGetFilePosition)(HSTREAM handle, DWORD mode);
+DWORD BASSDEF(BASS_StreamPutData)(HSTREAM handle, const void *buffer,
+ DWORD length);
+DWORD BASSDEF(BASS_StreamPutFileData)(HSTREAM handle, const void *buffer,
+ DWORD length);
+
+BOOL BASSDEF(BASS_RecordGetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info);
+BOOL BASSDEF(BASS_RecordInit)(int device);
+BOOL BASSDEF(BASS_RecordSetDevice)(DWORD device);
+DWORD BASSDEF(BASS_RecordGetDevice)();
+BOOL BASSDEF(BASS_RecordFree)();
+BOOL BASSDEF(BASS_RecordGetInfo)(BASS_RECORDINFO *info);
+const char *BASSDEF(BASS_RecordGetInputName)(int input);
+BOOL BASSDEF(BASS_RecordSetInput)(int input, DWORD flags, float volume);
+DWORD BASSDEF(BASS_RecordGetInput)(int input, float *volume);
+HRECORD BASSDEF(BASS_RecordStart)(DWORD freq, DWORD chans, DWORD flags,
+ RECORDPROC *proc, void *user);
+
+double BASSDEF(BASS_ChannelBytes2Seconds)(DWORD handle, QWORD pos);
+QWORD BASSDEF(BASS_ChannelSeconds2Bytes)(DWORD handle, double pos);
+DWORD BASSDEF(BASS_ChannelGetDevice)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelSetDevice)(DWORD handle, DWORD device);
+DWORD BASSDEF(BASS_ChannelIsActive)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelGetInfo)(DWORD handle, BASS_CHANNELINFO *info);
+const char *BASSDEF(BASS_ChannelGetTags)(DWORD handle, DWORD tags);
+DWORD BASSDEF(BASS_ChannelFlags)(DWORD handle, DWORD flags, DWORD mask);
+BOOL BASSDEF(BASS_ChannelUpdate)(DWORD handle, DWORD length);
+BOOL BASSDEF(BASS_ChannelLock)(DWORD handle, BOOL lock);
+BOOL BASSDEF(BASS_ChannelPlay)(DWORD handle, BOOL restart);
+BOOL BASSDEF(BASS_ChannelStop)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelPause)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value);
+BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib,
+ float *value);
+BOOL BASSDEF(BASS_ChannelSlideAttribute)(DWORD handle, DWORD attrib,
+ float value, DWORD time);
+BOOL BASSDEF(BASS_ChannelIsSliding)(DWORD handle, DWORD attrib);
+BOOL BASSDEF(BASS_ChannelSetAttributeEx)(DWORD handle, DWORD attrib,
+ void *value, DWORD size);
+DWORD BASSDEF(BASS_ChannelGetAttributeEx)(DWORD handle, DWORD attrib,
+ void *value, DWORD size);
+BOOL BASSDEF(BASS_ChannelSet3DAttributes)(DWORD handle, int mode, float min,
+ float max, int iangle, int oangle,
+ float outvol);
+BOOL BASSDEF(BASS_ChannelGet3DAttributes)(DWORD handle, DWORD *mode, float *min,
+ float *max, DWORD *iangle,
+ DWORD *oangle, float *outvol);
+BOOL BASSDEF(BASS_ChannelSet3DPosition)(DWORD handle, const BASS_3DVECTOR *pos,
+ const BASS_3DVECTOR *orient,
+ const BASS_3DVECTOR *vel);
+BOOL BASSDEF(BASS_ChannelGet3DPosition)(DWORD handle, BASS_3DVECTOR *pos,
+ BASS_3DVECTOR *orient,
+ BASS_3DVECTOR *vel);
+QWORD BASSDEF(BASS_ChannelGetLength)(DWORD handle, DWORD mode);
+BOOL BASSDEF(BASS_ChannelSetPosition)(DWORD handle, QWORD pos, DWORD mode);
+QWORD BASSDEF(BASS_ChannelGetPosition)(DWORD handle, DWORD mode);
+DWORD BASSDEF(BASS_ChannelGetLevel)(DWORD handle);
+BOOL BASSDEF(BASS_ChannelGetLevelEx)(DWORD handle, float *levels, float length,
+ DWORD flags);
+DWORD BASSDEF(BASS_ChannelGetData)(DWORD handle, void *buffer, DWORD length);
+HSYNC BASSDEF(BASS_ChannelSetSync)(DWORD handle, DWORD type, QWORD param,
+ SYNCPROC *proc, void *user);
+BOOL BASSDEF(BASS_ChannelRemoveSync)(DWORD handle, HSYNC sync);
+HDSP BASSDEF(BASS_ChannelSetDSP)(DWORD handle, DSPPROC *proc, void *user,
+ int priority);
+BOOL BASSDEF(BASS_ChannelRemoveDSP)(DWORD handle, HDSP dsp);
+BOOL BASSDEF(BASS_ChannelSetLink)(DWORD handle, DWORD chan);
+BOOL BASSDEF(BASS_ChannelRemoveLink)(DWORD handle, DWORD chan);
+HFX BASSDEF(BASS_ChannelSetFX)(DWORD handle, DWORD type, int priority);
+BOOL BASSDEF(BASS_ChannelRemoveFX)(DWORD handle, HFX fx);
+
+BOOL BASSDEF(BASS_FXSetParameters)(HFX handle, const void *params);
+BOOL BASSDEF(BASS_FXGetParameters)(HFX handle, void *params);
+BOOL BASSDEF(BASS_FXReset)(HFX handle);
+BOOL BASSDEF(BASS_FXSetPriority)(HFX handle, int priority);
+
+#ifdef __cplusplus
+}
+
+#if defined(_WIN32) && !defined(NOBASSOVERLOADS)
+static inline HPLUGIN BASS_PluginLoad(const WCHAR *file, DWORD flags)
+{
+ return BASS_PluginLoad((const char *)file, flags | BASS_UNICODE);
+}
+
+static inline HMUSIC BASS_MusicLoad(BOOL mem, const WCHAR *file, QWORD offset,
+ DWORD length, DWORD flags, DWORD freq)
+{
+ return BASS_MusicLoad(mem, (const void *)file, offset, length,
+ flags | BASS_UNICODE, freq);
+}
+
+static inline HSAMPLE BASS_SampleLoad(BOOL mem, const WCHAR *file, QWORD offset,
+ DWORD length, DWORD max, DWORD flags)
+{
+ return BASS_SampleLoad(mem, (const void *)file, offset, length, max,
+ flags | BASS_UNICODE);
+}
+
+static inline HSTREAM BASS_StreamCreateFile(BOOL mem, const WCHAR *file,
+ QWORD offset, QWORD length,
+ DWORD flags)
+{
+ return BASS_StreamCreateFile(mem, (const void *)file, offset, length,
+ flags | BASS_UNICODE);
+}
+
+static inline HSTREAM BASS_StreamCreateURL(const WCHAR *url, DWORD offset,
+ DWORD flags, DOWNLOADPROC *proc,
+ void *user)
+{
+ return BASS_StreamCreateURL((const char *)url, offset, flags | BASS_UNICODE,
+ proc, user);
+}
+
+static inline BOOL BASS_SetConfigPtr(DWORD option, const WCHAR *value)
+{
+ return BASS_SetConfigPtr(option | BASS_UNICODE, (const void *)value);
+}
+#endif
+#endif
+
+#endif
diff --git a/include/bassopus.h b/include/bassopus.h
new file mode 100644
index 00000000..3d8b131d
--- /dev/null
+++ b/include/bassopus.h
@@ -0,0 +1,64 @@
+/*
+ BASSOPUS 2.4 C/C++ header file
+ Copyright (c) 2012-2015 Un4seen Developments Ltd.
+
+ See the BASSOPUS.CHM file for more detailed documentation
+*/
+
+#ifndef BASSOPUS_H
+#define BASSOPUS_H
+
+#include "bass.h"
+
+#if BASSVERSION != 0x204
+#error conflicting BASS and BASSOPUS versions
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef BASSOPUSDEF
+#define BASSOPUSDEF(f) WINAPI f
+#endif
+
+// BASS_CHANNELINFO type
+#define BASS_CTYPE_STREAM_OPUS 0x11200
+
+// Additional attributes
+#define BASS_ATTRIB_OPUS_ORIGFREQ 0x13000
+#define BASS_ATTRIB_OPUS_GAIN 0x13001
+
+HSTREAM BASSOPUSDEF(BASS_OPUS_StreamCreateFile)(BOOL mem, const void *file,
+ QWORD offset, QWORD length,
+ DWORD flags);
+HSTREAM BASSOPUSDEF(BASS_OPUS_StreamCreateURL)(const char *url, DWORD offset,
+ DWORD flags, DOWNLOADPROC *proc,
+ void *user);
+HSTREAM BASSOPUSDEF(BASS_OPUS_StreamCreateFileUser)(DWORD system, DWORD flags,
+ const BASS_FILEPROCS *procs,
+ void *user);
+
+#ifdef __cplusplus
+}
+
+#if defined(_WIN32) && !defined(NOBASSOVERLOADS)
+static inline HSTREAM BASS_OPUS_StreamCreateFile(BOOL mem, const WCHAR *file,
+ QWORD offset, QWORD length,
+ DWORD flags)
+{
+ return BASS_OPUS_StreamCreateFile(mem, (const void *)file, offset, length,
+ flags | BASS_UNICODE);
+}
+
+static inline HSTREAM BASS_OPUS_StreamCreateURL(const WCHAR *url, DWORD offset,
+ DWORD flags, DOWNLOADPROC *proc,
+ void *user)
+{
+ return BASS_OPUS_StreamCreateURL((const char *)url, offset,
+ flags | BASS_UNICODE, proc, user);
+}
+#endif
+#endif
+
+#endif
diff --git a/include/chatlogpiece.h b/include/chatlogpiece.h
index 0232666d..14d4b349 100644
--- a/include/chatlogpiece.h
+++ b/include/chatlogpiece.h
@@ -1,24 +1,26 @@
#ifndef CHATLOGPIECE_H
#define CHATLOGPIECE_H
+#include <QtWidgets/QApplication>
#include <QDateTime>
#include <QString>
class chatlogpiece {
+ Q_DECLARE_TR_FUNCTIONS(chatlogpiece)
public:
chatlogpiece();
chatlogpiece(QString p_name, QString p_showname, QString p_message,
- bool p_song, int color);
+ bool p_song,int color);
chatlogpiece(QString p_name, QString p_showname, QString p_message,
bool p_song, int color, QDateTime p_datetime);
+
QString get_name();
QString get_showname();
QString get_message();
- bool get_is_song();
+ bool is_song();
QDateTime get_datetime();
QString get_datetime_as_string();
int get_chat_color();
-
QString get_full();
private:
@@ -26,8 +28,8 @@ private:
QString showname;
QString message;
QDateTime datetime;
- bool is_song;
int color;
+ bool p_is_song;
};
#endif // CHATLOGPIECE_H
diff --git a/include/courtroom.h b/include/courtroom.h
index 396c4d70..182c2a68 100644
--- a/include/courtroom.h
+++ b/include/courtroom.h
@@ -1,739 +1,810 @@
-#ifndef COURTROOM_H
-#define COURTROOM_H
-
-#include "aoapplication.h"
-#include "aoblipplayer.h"
-#include "aobutton.h"
-#include "aocharbutton.h"
-#include "aocharmovie.h"
-#include "aoemotebutton.h"
-#include "aoevidencebutton.h"
-#include "aoevidencedisplay.h"
-#include "aoimage.h"
-#include "aolineedit.h"
-#include "aomovie.h"
-#include "aomusicplayer.h"
-#include "aooptionsdialog.h"
-#include "aopacket.h"
-#include "aoscene.h"
-#include "aosfxplayer.h"
-#include "aotextarea.h"
-#include "aotextedit.h"
-#include "chatlogpiece.h"
-#include "datatypes.h"
-#include "debug_functions.h"
-#include "file_functions.h"
-#include "hardware_functions.h"
-#include "lobby.h"
-#include <QBrush>
-#include <QCheckBox>
-#include <QCloseEvent>
-#include <QComboBox>
-#include <QDebug>
-#include <QFileDialog>
-#include <QFont>
-#include <QFuture>
-#include <QHeaderView>
-#include <QInputDialog>
-#include <QLayout>
-#include <QLineEdit>
-#include <QListWidget>
-#include <QMainWindow>
-#include <QMap>
-#include <QMenu>
-#include <QMetaObject>
-#include <QMovie>
-#include <QParallelAnimationGroup>
-#include <QPlainTextEdit>
-#include <QPropertyAnimation>
-#include <QRegExp>
-#include <QScrollBar>
-#include <QSignalMapper>
-#include <QSlider>
-#include <QSpinBox>
-#include <QTextBoundaryFinder>
-#include <QTextBrowser>
-#include <QTextCharFormat>
-#include <QThread>
-#include <QThreadPool>
-#include <QTransform>
-#include <QTreeWidget>
-#include <QVector>
-#include <QWidget>
-#include <QtConcurrent/QtConcurrent>
-#include <QtConcurrent/QtConcurrentRun>
-
-#include <stack>
-
-class AOApplication;
-class AOCharMovie;
-class Courtroom : public QMainWindow {
- Q_OBJECT
-public:
- explicit Courtroom(AOApplication *p_ao_app);
-
- void append_char(char_type p_char) { char_list.append(p_char); }
- void append_evidence(evi_type p_evi) { evidence_list.append(p_evi); }
- void append_music(QString f_music) { music_list.append(f_music); }
- void append_area(QString f_area) { area_list.append(f_area); }
- void clear_music() { music_list.clear(); }
- void clear_areas() { area_list.clear(); }
- void handle_failed_login();
- QString threading_sfx = "";
- QString threading_shake = "";
- QString threading_flash = "";
- QString threading_prefix = "";
- // cid and this may differ in cases of ini-editing
- QString current_char = "";
- int current_emote = 0;
- AOApplication *ao_app;
- // abstract widget to hold char buttons
- QWidget *ui_char_buttons;
- QVector<char_type> char_list;
- QVector<evi_type> evidence_list;
- QVector<QString> music_list;
- QVector<QString> area_list;
- QSignalMapper *char_button_mapper;
- QVector<AOCharButton *> ui_char_button_list;
- QVector<AOCharButton *> ui_char_button_list_filtered;
- QLineEdit *ui_char_search;
- QCheckBox *ui_char_passworded;
- QCheckBox *ui_char_taken;
- void mt_pre_framegetter(int frameNumber);
- void mt_framegetter(int frameNumber);
- void reset_music_list() { music_list.clear(); }
-
- void arup_append(int players, QString status, QString cm, QString locked)
- {
- arup_players.append(players);
- arup_statuses.append(status);
- arup_cms.append(cm);
- arup_locks.append(locked);
- }
-
- void arup_modify(int type, int place, QString value)
- {
- if (type == 0) {
- if (arup_players.size() > place)
- arup_players[place] = value.toInt();
- }
- else if (type == 1) {
- if (arup_statuses.size() > place)
- arup_statuses[place] = value;
- }
- else if (type == 2) {
- if (arup_cms.size() > place)
- arup_cms[place] = value;
- }
- else if (type == 3) {
- if (arup_locks.size() > place)
- arup_locks[place] = value;
- }
- list_areas();
- }
-
- void character_loading_finished();
-
- // sets position of widgets based on theme ini files
- void set_widgets();
- // sets font size based on theme ini files
- void set_font(QWidget *widget, QString p_identifier);
- // helper function that calls above function on the relevant widgets
- void set_fonts();
-
- void set_window_title(QString p_title);
- QPoint get_theme_pos(QString p_identifier);
-
- // reads theme inis and sets size and pos based on the identifier
- void set_size_and_pos(QWidget *p_widget, QString p_identifier);
- // sets status as taken on character with cid n_char and places proper shading
- // on charselect
- void set_taken(int n_char, bool p_taken);
-
- // sets the current background to argument. also does some checks to see if
- // it's a legacy bg
- void set_background(QString p_background);
-
- // sets the evidence list member variable to argument
- void set_evidence_list(QVector<evi_type> &p_evi_list);
-
- // called when a DONE#% from the server was received
- void done_received();
-
- // sets the local mute list based on characters available on the server
- void set_mute_list();
-
- // Sets the local pair list based on the characters available on the server.
- void set_pair_list();
-
- // sets desk and bg based on pos in chatmessage
- void set_scene();
-
- // sets text color based on text color in chatmessage
- void set_text_color();
-
- // And gets the colour, too!
- QColor get_text_color(QString color);
-
- // takes in serverD-formatted IP list as prints a converted version to server
- // OOC admittedly poorly named
- void set_ip_list(QString p_list);
-
- // disables chat if current cid matches second argument
- // enables if p_muted is false
- void set_mute(bool p_muted, int p_cid);
-
- // send a message that the player is banned and quits the server
- void set_ban(int p_cid);
-
- // cid = character id, returns the cid of the currently selected character
- int get_cid() { return m_cid; }
- QString get_current_char() { return current_char; }
- QString get_current_background() { return current_background; }
-
- // set the character using an ID
- void set_character(int char_id);
-
- // properly sets up some varibles: resets user state
- void enter_courtroom(int p_cid);
-
- // helper function that populates ui_music_list with the contents of
- // music_list
- void list_music();
- void list_areas();
-
- // these are for OOC chat
- void append_ms_chatmessage(QString f_name, QString f_message);
- void append_server_chatmessage(QString p_name, QString p_message,
- QString p_colour);
-
- // check whether or not current theme has images for buttons with fallback
- // text
- void detect_fallback_text();
-
- // these functions handle chatmessages sequentially.
- // The process itself is very convoluted and merits separate documentation
- // But the general idea is objection animation->pre animation->talking->idle
- void handle_chatmessage(QStringList *p_contents);
- void handle_chatmessage_2();
- void handle_chatmessage_3();
-
- // This function filters out the common CC inline text trickery, for appending
- // to the IC chatlog.
- QString filter_ic_text(QString p_text, bool skip_filter, int chat_color);
-
- // adds text to the IC chatlog. p_name first as bold then p_text then a newlin
- // this function keeps the chatlog scrolled to the top unless there's text
- // selected
- // or the user isn't already scrolled to the top
- void append_ic_text(QString p_text, QString p_name = "",
- bool is_songchange = false, bool force_filter = false,
- bool skip_filter = false, int chat_color = 0);
-
- // prints who played the song to IC chat and plays said song(if found on local
- // filesystem) takes in a list where the first element is the song name and
- // the second is the char id of who played it
- void handle_song(QStringList *p_contents);
-
- void play_preanim(bool noninterrupting);
-
- // plays the witness testimony or cross examination animation based on
- // argument
- void handle_wtce(QString p_wtce, int variant);
-
- // sets the hp bar of defense(p_bar 1) or pro(p_bar 2)
- // state is an number between 0 and 10 inclusive
- void set_hp_bar(int p_bar, int p_state);
-
- // Toggles the judge buttons, whether they should appear or not.
- void toggle_judge_buttons(bool is_on);
- void doScreenShake();
- void doRealization();
-
- void announce_case(QString title, bool def, bool pro, bool jud, bool jur,
- bool steno, bool wit);
-
- void check_connection_received();
-
- void refresh_iclog(bool skiplast);
-
- ~Courtroom();
-
-private:
- int m_courtroom_width = 714;
- int m_courtroom_height = 668;
-
- int m_viewport_x = 0;
- int m_viewport_y = 0;
-
- int m_viewport_width = 256;
- int m_viewport_height = 192;
-
- bool first_message_sent = false;
- int maximumMessages = 0;
- QPropertyAnimation *screenshake_animation;
- QPropertyAnimation *chatbox_screenshake_animation;
- QParallelAnimationGroup *screenshake_group;
- QMovie *frame_emote_checker;
- // This is for inline message-colouring.
-
- enum INLINE_COLOURS { INLINE_BLUE, INLINE_GREEN, INLINE_ORANGE, INLINE_GREY };
-
- // A stack of inline colours.
- std::stack<INLINE_COLOURS> inline_colour_stack;
-
- bool next_character_is_not_special = false; // If true, write the
- // next character as it is.
-
- bool message_is_centered = false;
-
- int current_display_speed = 3;
- int message_display_speed_slow[7] = {30, 40, 50, 60, 75, 100, 120};
- int message_display_speed[7] = {10, 20, 30, 40, 50, 60, 75};
-
- // This is for checking if the character should start talking again
- // when an inline blue text ends.
- bool entire_message_is_blue = false;
-
- // And this is the inline 'talking checker'. Counts how 'deep' we are
- // in inline blues.
- int inline_blue_depth = 0;
-
- // The character ID of the character this user wants to appear alongside with.
- int other_charid = -1;
-
- // The offset this user has given if they want to appear alongside someone.
- int offset_with_pair = 0;
-
- QVector<int> arup_players;
- QVector<QString> arup_statuses;
- QVector<QString> arup_cms;
- QVector<QString> arup_locks;
-
- QVector<chatlogpiece> ic_chatlog_history;
-
- // These map music row items and area row items to their actual IDs.
- QVector<int> music_row_to_number;
- QVector<int> area_row_to_number;
-
- // triggers ping_server() every 60 seconds
- QTimer *keepalive_timer;
-
- // determines how fast messages tick onto screen
- QTimer *chat_tick_timer;
- // int chat_tick_interval = 60;
- // which tick position(character in chat message) we are at
- int tick_pos = 0;
- // used to determine how often blips sound
- int blip_pos = 0;
- int blip_rate = 1;
- int rainbow_counter = 0;
- bool rainbow_appended = false;
- bool blank_blip = false;
-
- // The cursor to write with in mirror mode
- QTextCursor *mirror_cursor;
- // Used for getting the current maximum blocks allowed in the IC chatlog.
- int log_maximum_blocks = 0;
-
- // True, if the log should go downwards.
- bool log_goes_downwards = false;
-
- // delay before chat messages starts ticking
- QTimer *text_delay_timer;
-
- // delay before sfx plays
- QTimer *sfx_delay_timer;
-
- // keeps track of how long realization is visible(it's just a white square and
- // should be visible less than a second)
- QTimer *realization_timer;
-
- // every time point in char.inis times this equals the final time
- const int time_mod = 40;
-
- // the amount of time non-animated objection/hold it/takethat images stay
- // onscreen for in ms
- const int shout_stay_time = 724;
-
- // the amount of time non-animated guilty/not guilty images stay onscreen for
- // in ms
- const int verdict_stay_time = 3000;
-
- // the amount of time non-animated witness testimony/cross-examination images
- // stay onscreen for in ms
- const int wtce_stay_time = 1500;
-
- static const int chatmessage_size = 28;
- QString m_chatmessage[chatmessage_size];
- bool chatmessage_is_empty = false;
-
- QString previous_ic_message = "";
-
- // char id, muted or not
- QMap<int, bool> mute_map;
-
- // QVector<int> muted_cids;
-
- bool is_muted = false;
-
- // state of animation, 0 = objecting, 1 = preanim, 2 = talking, 3 = idle, 4 =
- // noniterrupting preanim
- int anim_state = 3;
-
- // state of text ticking, 0 = not yet ticking, 1 = ticking in progress, 2 =
- // ticking done
- int text_state = 2;
-
- // characters we consider punctuation
- const QString punctuation_chars = ".,?!:;";
-
- // amount by which we multiply the delay when we parse punctuation chars
- int punctuation_modifier = 0;
- bool slower_blips = false;
- // character id, which index of the char_list the player is
- int m_cid = -1;
- // cid and this may differ in cases of ini-editing
-
- QString char_name = "";
-
- int objection_state = 0;
- bool keep_custom_objection = false;
- QString objection_custom = "";
- int realization_state = 0;
- int screenshake_state = 0;
- int text_color = 0;
- bool is_presenting_evidence = false;
-
- int defense_bar_state = 0;
- int prosecution_bar_state = 0;
-
- int current_char_page = 0;
- int char_columns = 10;
- int char_rows = 9;
- int max_chars_on_page = 90;
-
- const int button_width = 60;
- const int button_height = 60;
-
- int current_emote_page = 0;
- int emote_columns = 5;
- int emote_rows = 2;
- int max_emotes_on_page = 10;
-
- QVector<evi_type> local_evidence_list;
-
- int current_evidence_page = 0;
- int current_evidence = 0;
- int evidence_columns = 6;
- int evidence_rows = 3;
- int max_evidence_on_page = 18;
-
- // is set to true if the bg folder contains defensedesk.png,
- // prosecutiondesk.png and stand.png
- bool is_ao2_bg = false;
-
- // whether or not to use text for buttons instead of images, true is text
- bool change_char_fallback = true;
- bool reload_theme_fallback = true;
- bool settings_fallback = true;
- bool call_mod_fallback = true;
- bool casing_fallback = true;
- bool amswap_fallback = true;
- bool ooc_toggle_fallback = true;
-
- // whether the ooc chat is server or master chat, true is server
- bool server_ooc = true;
-
- // Is AFK enabled
- bool isafk = false;
- QString current_background = "default";
-
- AOMusicPlayer *music_player;
- AOSfxPlayer *sfx_player;
- AOSfxPlayer *misc_sfx_player;
- AOSfxPlayer *frame_emote_sfx_player;
- AOSfxPlayer *pair_frame_emote_sfx_player;
- AOSfxPlayer *objection_player;
- AOBlipPlayer *blip_player;
-
- AOSfxPlayer *modcall_player;
-
- AOImage *ui_background;
-
- QWidget *ui_viewport;
- AOScene *ui_vp_background;
- AOMovie *ui_vp_speedlines;
- AOCharMovie *ui_vp_player_char;
- AOCharMovie *ui_vp_sideplayer_char;
- AOScene *ui_vp_desk;
- AOScene *ui_vp_legacy_desk;
- AOEvidenceDisplay *ui_vp_evidence_display;
- AOImage *ui_vp_chatbox;
- QLabel *ui_vp_showname;
- QTextEdit *ui_vp_message;
- AOMovie *ui_vp_realization;
- AOMovie *ui_vp_testimony;
- AOMovie *ui_vp_wtce;
- AOMovie *ui_vp_objection;
- void realization_done();
-
- bool colorf_iclog = false;
- bool mirror_iclog = false;
- bool colorf_limit = false;
-
- bool keep_evidence_display = false;
-
- QTextEdit *ui_ic_chatlog;
-
- AOTextArea *ui_ms_chatlog;
- AOTextArea *ui_server_chatlog;
-
- QListWidget *ui_mute_list;
- QListWidget *ui_area_list;
- QTreeWidget *ui_music_list;
-
- AOButton *ui_pair_button;
- QListWidget *ui_pair_list;
- QSpinBox *ui_pair_offset_spinbox;
-
- QLineEdit *ui_ic_chat_message;
- QLineEdit *ui_ic_chat_name;
-
- QLineEdit *ui_ooc_chat_message;
- QLineEdit *ui_ooc_chat_name;
-
- // QLineEdit *ui_area_password;
- QLineEdit *ui_music_search;
- QString music_search_par = "";
- QString area_search_par = "";
-
- QWidget *ui_emotes;
- QVector<AOEmoteButton *> ui_emote_list;
- AOButton *ui_emote_left;
- AOButton *ui_emote_right;
-
- QComboBox *ui_emote_dropdown;
- QComboBox *ui_pos_dropdown;
-
- AOImage *ui_defense_bar;
- AOImage *ui_prosecution_bar;
-
- QLabel *ui_music_label;
- QLabel *ui_sfx_label;
- QLabel *ui_blip_label;
-
- AOButton *ui_hold_it;
- AOButton *ui_objection;
- AOButton *ui_take_that;
-
- AOButton *ui_ooc_toggle;
-
- AOButton *ui_witness_testimony;
- AOButton *ui_cross_examination;
- AOButton *ui_guilty;
- AOButton *ui_not_guilty;
-
- AOButton *ui_change_character;
- AOButton *ui_reload_theme;
- AOButton *ui_call_mod;
- AOButton *ui_settings;
- AOButton *ui_announce_casing;
- AOButton *ui_switch_area_music;
-
- QCheckBox *ui_pre;
- QCheckBox *ui_flip;
- QCheckBox *ui_guard;
- QCheckBox *ui_casing;
-
- QCheckBox *ui_pre_non_interrupt;
- QCheckBox *ui_showname_enable;
-
- AOButton *ui_custom_objection;
- AOButton *ui_realization;
- AOButton *ui_screenshake;
- AOButton *ui_mute;
-
- QMenu *custom_obj_menu;
-
- AOButton *ui_defense_plus;
- AOButton *ui_defense_minus;
-
- AOButton *ui_prosecution_plus;
- AOButton *ui_prosecution_minus;
-
- QComboBox *ui_text_color;
-
- QSlider *ui_music_slider;
- QSlider *ui_sfx_slider;
- QSlider *ui_blip_slider;
-
- AOImage *ui_muted;
-
- QSpinBox *ui_log_limit_spinbox;
- QLabel *ui_log_limit_label;
-
- AOButton *ui_evidence_button;
- AOImage *ui_evidence;
- AOLineEdit *ui_evidence_name;
- QWidget *ui_evidence_buttons;
- QVector<AOEvidenceButton *> ui_evidence_list;
- AOButton *ui_evidence_left;
- AOButton *ui_evidence_right;
- AOButton *ui_evidence_present;
- AOImage *ui_evidence_overlay;
- AOButton *ui_evidence_delete;
- AOLineEdit *ui_evidence_image_name;
- AOButton *ui_evidence_image_button;
- AOButton *ui_evidence_x;
- AOTextEdit *ui_evidence_description;
-
- AOImage *ui_char_select_background;
-
- AOImage *ui_selector;
-
- AOButton *ui_back_to_lobby;
-
- QLineEdit *ui_char_password;
-
- AOButton *ui_char_select_left;
- AOButton *ui_char_select_right;
-
- AOButton *ui_spectator;
-
- void construct_char_select();
- void set_char_select();
- void set_char_select_page();
- void put_button_in_place(int starting, int chars_on_this_page);
- void filter_character_list();
-
- void construct_emotes();
- void set_emote_page();
- void set_emote_dropdown();
-
- void construct_evidence();
- void set_evidence_page();
-
-public slots:
- void objection_done();
- void preanim_done();
-
- void mod_called(QString p_ip);
-
- void case_called(QString msg, bool def, bool pro, bool jud, bool jur,
- bool steno, bool witness);
-
-private slots:
- void start_chat_ticking();
- void play_sfx();
-
- void chat_tick();
-
- void on_mute_list_clicked(QModelIndex p_index);
- void on_pair_list_clicked(QModelIndex p_index);
-
- void on_chat_return_pressed();
-
- void on_ooc_return_pressed();
-
- void on_music_search_keypr();
- void on_music_search_edited(QString p_text);
- void on_music_list_double_clicked(QTreeWidgetItem *p_item, int column);
- void on_area_list_double_clicked(QModelIndex p_model);
-
- void select_emote(int p_id);
-
- void on_emote_clicked(int p_id);
-
- void on_emote_left_clicked();
- void on_emote_right_clicked();
-
- void on_emote_dropdown_changed(int p_index);
- void on_pos_dropdown_changed(int p_index);
-
- void on_evidence_name_edited();
- void on_evidence_image_name_edited();
- void on_evidence_image_button_clicked();
- void on_evidence_clicked(int p_id);
- void on_evidence_double_clicked(int p_id);
-
- void on_evidence_hover(int p_id, bool p_state);
-
- void on_evidence_left_clicked();
- void on_evidence_right_clicked();
- void on_evidence_present_clicked();
-
- void on_hold_it_clicked();
- void on_objection_clicked();
- void on_take_that_clicked();
- void on_custom_objection_clicked();
- void ShowContextMenu(const QPoint &pos);
-
- void on_realization_clicked();
- void on_screenshake_clicked();
-
- void on_mute_clicked();
- void on_pair_clicked();
-
- void on_defense_minus_clicked();
- void on_defense_plus_clicked();
- void on_prosecution_minus_clicked();
- void on_prosecution_plus_clicked();
-
- void on_text_color_changed(int p_color);
-
- void on_music_slider_moved(int p_value);
- void on_sfx_slider_moved(int p_value);
- void on_blip_slider_moved(int p_value);
-
- void on_log_limit_changed(int value);
- void on_pair_offset_changed(int value);
-
- void on_ooc_toggle_clicked();
-
- void on_witness_testimony_clicked();
- void on_cross_examination_clicked();
- void on_not_guilty_clicked();
- void on_guilty_clicked();
-
- void on_change_character_clicked();
- void on_reload_theme_clicked();
- void on_call_mod_clicked();
- void on_settings_clicked();
- void on_announce_casing_clicked();
-
- void on_pre_clicked();
- void on_flip_clicked();
- void on_guard_clicked();
-
- void on_showname_enable_clicked();
-
- void on_evidence_button_clicked();
-
- void on_evidence_delete_clicked();
- void on_evidence_x_clicked();
-
- void on_back_to_lobby_clicked();
-
- void on_char_select_left_clicked();
- void on_char_select_right_clicked();
- void on_char_search_changed();
- void on_char_taken_clicked();
- void on_char_passworded_clicked();
-
- void on_spectator_clicked();
-
- void char_clicked(int n_char);
-
- void on_switch_area_music_clicked();
-
- void on_casing_clicked();
-
- void ping_server();
-
-#ifdef BASSAUDIO
- void load_bass_opus_plugin();
-#endif
-};
-
-#endif // COURTROOM_H
+#ifndef COURTROOM_H
+#define COURTROOM_H
+
+#include "aoapplication.h"
+#include "aoblipplayer.h"
+#include "aobutton.h"
+#include "aocharbutton.h"
+#include "aocharmovie.h"
+#include "aoemotebutton.h"
+#include "aoevidencebutton.h"
+#include "aoevidencedisplay.h"
+#include "aoimage.h"
+#include "aolineedit.h"
+#include "aomovie.h"
+#include "aomusicplayer.h"
+#include "aooptionsdialog.h"
+#include "aopacket.h"
+#include "aoscene.h"
+#include "aosfxplayer.h"
+#include "aotextarea.h"
+#include "aotextedit.h"
+#include "chatlogpiece.h"
+#include "datatypes.h"
+#include "debug_functions.h"
+#include "file_functions.h"
+#include "hardware_functions.h"
+#include "lobby.h"
+#include "scrolltext.h"
+
+#include <QCheckBox>
+#include <QCloseEvent>
+#include <QComboBox>
+#include <QHeaderView>
+#include <QLineEdit>
+#include <QListWidget>
+#include <QMainWindow>
+#include <QMap>
+#include <QPlainTextEdit>
+#include <QSlider>
+#include <QSpinBox>
+#include <QTextBrowser>
+#include <QTreeWidget>
+#include <QVector>
+
+#include <QBrush>
+#include <QDebug>
+#include <QDesktopServices>
+#include <QFileDialog>
+#include <QFont>
+#include <QInputDialog>
+#include <QMenu>
+#include <QMessageBox>
+#include <QParallelAnimationGroup>
+#include <QPropertyAnimation>
+#include <QRegExp>
+#include <QScrollBar>
+#include <QTextBoundaryFinder>
+#include <QTextCharFormat>
+//#include <QRandomGenerator>
+
+#include <stack>
+
+class AOApplication;
+
+class Courtroom : public QMainWindow {
+ Q_OBJECT
+public:
+ explicit Courtroom(AOApplication *p_ao_app);
+
+ void append_char(char_type p_char) { char_list.append(p_char); }
+ void append_evidence(evi_type p_evi) { evidence_list.append(p_evi); }
+ void append_music(QString f_music) { music_list.append(f_music); }
+ void append_area(QString f_area) { area_list.append(f_area); }
+ void clear_music() { music_list.clear(); }
+ void clear_areas() { area_list.clear(); }
+
+ void fix_last_area()
+ {
+ if (area_list.size() > 0) {
+ QString malplaced = area_list.last();
+ area_list.removeLast();
+ append_music(malplaced);
+ }
+ }
+
+ void arup_append(int players, QString status, QString cm, QString locked)
+ {
+ arup_players.append(players);
+ arup_statuses.append(status);
+ arup_cms.append(cm);
+ arup_locks.append(locked);
+ }
+
+ void arup_modify(int type, int place, QString value)
+ {
+ if (type == 0) {
+ if (arup_players.size() > place)
+ arup_players[place] = value.toInt();
+ }
+ else if (type == 1) {
+ if (arup_statuses.size() > place)
+ arup_statuses[place] = value;
+ }
+ else if (type == 2) {
+ if (arup_cms.size() > place)
+ arup_cms[place] = value;
+ }
+ else if (type == 3) {
+ if (arup_locks.size() > place)
+ arup_locks[place] = value;
+ }
+ list_areas();
+ }
+
+ void character_loading_finished();
+
+ // sets position of widgets based on theme ini files
+ void set_widgets();
+
+ // sets font size based on theme ini files
+ void set_font(QWidget *widget, QString class_name, QString p_identifier, QString p_char="", QString font_name="", int f_pointsize=0);
+
+ // Get the properly constructed font
+ QFont get_qfont(QString font_name, int f_pointsize, bool antialias = true);
+
+ // actual operation of setting the font on a widget
+ void set_qfont(QWidget *widget, QString class_name, QFont font,
+ QColor f_color = Qt::black, bool bold = false);
+
+ // helper function that calls above function on the relevant widgets
+ void set_fonts(QString p_char="");
+
+ // sets dropdown menu stylesheet
+ void set_dropdown(QWidget *widget);
+
+ // helper funciton that call above function on the relevant widgets
+ void set_dropdowns();
+
+ void set_window_title(QString p_title);
+
+ // reads theme inis and sets size and pos based on the identifier
+ void set_size_and_pos(QWidget *p_widget, QString p_identifier);
+
+ // reads theme inis and returns the size and pos as defined by it
+ QPoint get_theme_pos(QString p_identifier);
+
+ // sets status as taken on character with cid n_char and places proper shading
+ // on charselect
+ void set_taken(int n_char, bool p_taken);
+
+ // sets the current background to argument. also does some checks to see if
+ // it's a legacy bg
+ void set_background(QString p_background, bool display = false);
+
+ // sets the local character pos/side to use.
+ void set_side(QString p_side);
+
+ // sets the pos dropdown
+ void set_pos_dropdown(QStringList pos_dropdowns);
+
+ // sets the evidence list member variable to argument
+ void set_evidence_list(QVector<evi_type> &p_evi_list);
+
+ // called when a DONE#% from the server was received
+ void done_received();
+
+ // sets the local mute list based on characters available on the server
+ void set_mute_list();
+
+ // Sets the local pair list based on the characters available on the server.
+ void set_pair_list();
+
+ // sets desk and bg based on pos in chatmessage
+ void set_scene(QString f_desk_mod, QString f_side);
+
+ // takes in serverD-formatted IP list as prints a converted version to server
+ // OOC admittedly poorly named
+ void set_ip_list(QString p_list);
+
+ // disables chat if current cid matches second argument
+ // enables if p_muted is false
+ void set_mute(bool p_muted, int p_cid);
+
+ // send a message that the player is banned and quits the server
+ void set_ban(int p_cid);
+
+ // cid = character id, returns the cid of the currently selected character
+ int get_cid() { return m_cid; }
+ QString get_current_char() { return current_char; }
+ QString get_current_background() { return current_background; }
+
+ // updates character to p_cid and updates necessary ui elements
+ void update_character(int p_cid);
+
+ // properly sets up some varibles: resets user state
+ void enter_courtroom();
+
+ // helper function that populates ui_music_list with the contents of
+ // music_list
+ void list_music();
+ void list_areas();
+
+ // these are for OOC chat
+ void append_ms_chatmessage(QString f_name, QString f_message);
+ void append_server_chatmessage(QString p_name, QString p_message,
+ QString p_color);
+
+ // these functions handle chatmessages sequentially.
+ // The process itself is very convoluted and merits separate documentation
+ // But the general idea is objection animation->pre animation->talking->idle
+ void handle_chatmessage(QStringList *p_contents);
+ void handle_chatmessage_2();
+ void handle_chatmessage_3();
+
+ // This function filters out the common CC inline text trickery, for appending
+ // to the IC chatlog.
+ QString filter_ic_text(QString p_text, bool colorize = false, int pos = -1,
+ int default_color = 0);
+
+ // adds text to the IC chatlog. p_name first as bold then p_text then a newlin
+ // this function keeps the chatlog scrolled to the top unless there's text
+ // selected
+ // or the user isn't already scrolled to the top
+ void append_ic_text(QString p_text, QString p_name = "", QString action = "", int color = 0);
+
+ // prints who played the song to IC chat and plays said song(if found on local
+ // filesystem) takes in a list where the first element is the song name and
+ // the second is the char id of who played it
+ void handle_song(QStringList *p_contents);
+
+ void play_preanim(bool noninterrupting);
+
+ // plays the witness testimony or cross examination animation based on
+ // argument
+ void handle_wtce(QString p_wtce, int variant);
+
+ // sets the hp bar of defense(p_bar 1) or pro(p_bar 2)
+ // state is an number between 0 and 10 inclusive
+ void set_hp_bar(int p_bar, int p_state);
+
+ // Toggles the judge buttons, whether they should appear or not.
+ void toggle_judge_buttons(bool is_on);
+
+ void announce_case(QString title, bool def, bool pro, bool jud, bool jur,
+ bool steno);
+
+ void check_connection_received();
+
+ ~Courtroom();
+
+private:
+ AOApplication *ao_app;
+
+ int m_courtroom_width = 714;
+ int m_courtroom_height = 668;
+
+ int m_viewport_x = 0;
+ int m_viewport_y = 0;
+
+ int m_viewport_width = 256;
+ int m_viewport_height = 192;
+
+ bool first_message_sent = false;
+ int maximumMessages = 0;
+
+ QParallelAnimationGroup *screenshake_animation_group =
+ new QParallelAnimationGroup;
+
+ bool next_character_is_not_special = false; // If true, write the
+ // next character as it is.
+
+ bool message_is_centered = false;
+
+ int current_display_speed = 3;
+ int message_display_speed[7] = {0, 10, 25, 40, 50, 70, 90};
+
+ // The character ID of the character this user wants to appear alongside with.
+ int other_charid = -1;
+
+ // The offset this user has given if they want to appear alongside someone.
+ int char_offset = 0;
+
+ // 0 = in front, 1 = behind
+ int pair_order = 0;
+
+ QVector<char_type> char_list;
+ QVector<evi_type> evidence_list;
+ QVector<QString> music_list;
+ QVector<QString> area_list;
+
+ QVector<int> arup_players;
+ QVector<QString> arup_statuses;
+ QVector<QString> arup_cms;
+ QVector<QString> arup_locks;
+
+ QVector<chatlogpiece> ic_chatlog_history;
+
+ // triggers ping_server() every 60 seconds
+ QTimer *keepalive_timer;
+
+ // determines how fast messages tick onto screen
+ QTimer *chat_tick_timer;
+ // int chat_tick_interval = 60;
+ // which tick position(character in chat message) we are at
+ int tick_pos = 0;
+ // the actual document tick pos we gotta worry about for making the text
+ // scroll better
+ int real_tick_pos = 0;
+ // used to determine how often blips sound
+ int blip_ticker = 0;
+ int blip_rate = 1;
+ int rainbow_counter = 0;
+ bool rainbow_appended = false;
+ bool blank_blip = false;
+
+ // Whether or not is this message additive to the previous one
+ bool is_additive = false;
+
+ // Used for getting the current maximum blocks allowed in the IC chatlog.
+ int log_maximum_blocks = 0;
+
+ // True, if the log should go downwards.
+ bool log_goes_downwards = false;
+
+ // delay before chat messages starts ticking
+ QTimer *text_delay_timer;
+
+ // delay before sfx plays
+ QTimer *sfx_delay_timer;
+
+ // every time point in char.inis times this equals the final time
+ const int time_mod = 40;
+
+ // the amount of time non-animated objection/hold it/takethat images stay
+ // onscreen for in ms
+ const int shout_stay_time = 724;
+
+ // the amount of time non-animated guilty/not guilty images stay onscreen for
+ // in ms
+ const int verdict_stay_time = 3000;
+
+ // the amount of time non-animated witness testimony/cross-examination images
+ // stay onscreen for in ms
+ const int wtce_stay_time = 1500;
+
+ // characters we consider punctuation
+ const QString punctuation_chars = ".,?!:;";
+
+ // amount by which we multiply the delay when we parse punctuation chars
+ const int punctuation_modifier = 3;
+
+ static const int chatmessage_size = 30;
+ QString m_chatmessage[chatmessage_size];
+ bool chatmessage_is_empty = false;
+
+ QString previous_ic_message = "";
+ QString additive_previous = "";
+
+ // char id, muted or not
+ QMap<int, bool> mute_map;
+
+ // QVector<int> muted_cids;
+
+ bool is_muted = false;
+
+ // state of animation, 0 = objecting, 1 = preanim, 2 = talking, 3 = idle, 4 =
+ // noniterrupting preanim
+ int anim_state = 3;
+
+ // whether or not current color is a talking one
+ bool color_is_talking = true;
+
+ // state of text ticking, 0 = not yet ticking, 1 = ticking in progress, 2 =
+ // ticking done
+ int text_state = 2;
+
+ // character id, which index of the char_list the player is
+ int m_cid = -1;
+ // cid and this may differ in cases of ini-editing
+ QString current_char = "";
+
+ int objection_state = 0;
+ QString objection_custom = "";
+ int realization_state = 0;
+ int screenshake_state = 0;
+ int text_color = 0;
+
+ // How many unique user colors are possible
+ static const int max_colors = 12;
+
+ // Text Color-related optimization:
+ // Current color list indexes to real color references
+ QVector<int> color_row_to_number;
+
+ // List of associated RGB colors for this color index
+ QVector<QColor> color_rgb_list;
+
+ // List of markdown start characters, their index is tied to the color index
+ QStringList color_markdown_start_list;
+
+ // List of markdown end characters, their index is tied to the color index
+ QStringList color_markdown_end_list;
+
+ // Whether or not we're supposed to remove this char during parsing
+ QVector<bool> color_markdown_remove_list;
+
+ // Whether or not this color allows us to play the talking animation
+ QVector<bool> color_markdown_talking_list;
+ // Text Color-related optimization END
+
+ // List of all currently available pos
+ QStringList pos_dropdown_list;
+
+ bool is_presenting_evidence = false;
+
+ QString effect = "";
+
+ // Music effect flags we want to send to server when we play music
+ int music_flags = FADE_OUT;
+
+ int defense_bar_state = 0;
+ int prosecution_bar_state = 0;
+
+ int current_char_page = 0;
+ int char_columns = 10;
+ int char_rows = 9;
+ int max_chars_on_page = 90;
+
+ const int button_width = 60;
+ const int button_height = 60;
+
+ int current_emote_page = 0;
+ int current_emote = 0;
+ int emote_columns = 5;
+ int emote_rows = 2;
+ int max_emotes_on_page = 10;
+
+ QVector<evi_type> local_evidence_list;
+ QVector<evi_type> private_evidence_list;
+ QVector<evi_type> global_evidence_list;
+
+ // false = use private_evidence_list
+ bool current_evidence_global = true;
+
+ int current_evidence_page = 0;
+ int current_evidence = 0;
+ int evidence_columns = 6;
+ int evidence_rows = 3;
+ int max_evidence_on_page = 18;
+
+ // is set to true if the bg folder contains defensedesk.png,
+ // prosecutiondesk.png and stand.png
+ bool is_ao2_bg = false;
+
+ // whether the ooc chat is server or master chat, true is server
+ bool server_ooc = true;
+
+ QString current_background = "default";
+ QString current_side = "";
+
+ AOMusicPlayer *music_player;
+ AOSfxPlayer *sfx_player;
+ AOSfxPlayer *objection_player;
+ AOBlipPlayer *blip_player;
+
+ AOSfxPlayer *modcall_player;
+
+ AOImage *ui_background;
+
+ QWidget *ui_viewport;
+ AOScene *ui_vp_background;
+ AOMovie *ui_vp_speedlines;
+ AOCharMovie *ui_vp_player_char;
+ AOCharMovie *ui_vp_sideplayer_char;
+ AOScene *ui_vp_desk;
+ AOScene *ui_vp_legacy_desk;
+ AOEvidenceDisplay *ui_vp_evidence_display;
+ AOImage *ui_vp_chatbox;
+ QLabel *ui_vp_showname;
+ AOMovie *ui_vp_chat_arrow;
+ QTextEdit *ui_vp_message;
+ AOMovie *ui_vp_effect;
+ AOMovie *ui_vp_testimony;
+ AOMovie *ui_vp_wtce;
+ AOMovie *ui_vp_objection;
+
+ QTextEdit *ui_ic_chatlog;
+
+ AOTextArea *ui_ms_chatlog;
+ AOTextArea *ui_server_chatlog;
+
+ QListWidget *ui_mute_list;
+ QTreeWidget *ui_area_list;
+ QTreeWidget *ui_music_list;
+
+ ScrollText *ui_music_name;
+ AOMovie *ui_music_display;
+
+ AOButton *ui_pair_button;
+ QListWidget *ui_pair_list;
+ QSpinBox *ui_pair_offset_spinbox;
+
+ QComboBox *ui_pair_order_dropdown;
+
+ AOLineEdit *ui_ic_chat_message;
+ QLineEdit *ui_ic_chat_name;
+
+ QLineEdit *ui_ooc_chat_message;
+ QLineEdit *ui_ooc_chat_name;
+
+ // QLineEdit *ui_area_password;
+ QLineEdit *ui_music_search;
+
+ QWidget *ui_emotes;
+ QVector<AOEmoteButton *> ui_emote_list;
+ AOButton *ui_emote_left;
+ AOButton *ui_emote_right;
+
+ QComboBox *ui_emote_dropdown;
+ QComboBox *ui_pos_dropdown;
+
+ QComboBox *ui_iniswap_dropdown;
+ AOButton *ui_iniswap_remove;
+
+ QComboBox *ui_sfx_dropdown;
+ AOButton *ui_sfx_remove;
+
+ QComboBox *ui_effects_dropdown;
+
+ AOImage *ui_defense_bar;
+ AOImage *ui_prosecution_bar;
+
+ QLabel *ui_music_label;
+ QLabel *ui_sfx_label;
+ QLabel *ui_blip_label;
+
+ AOButton *ui_hold_it;
+ AOButton *ui_objection;
+ AOButton *ui_take_that;
+
+ AOButton *ui_ooc_toggle;
+
+ AOButton *ui_witness_testimony;
+ AOButton *ui_cross_examination;
+ AOButton *ui_guilty;
+ AOButton *ui_not_guilty;
+
+ AOButton *ui_change_character;
+ AOButton *ui_reload_theme;
+ AOButton *ui_call_mod;
+ AOButton *ui_settings;
+ AOButton *ui_announce_casing;
+ AOButton *ui_switch_area_music;
+
+ QCheckBox *ui_pre;
+ QCheckBox *ui_flip;
+ QCheckBox *ui_additive;
+ QCheckBox *ui_guard;
+ QCheckBox *ui_casing;
+
+ QCheckBox *ui_pre_non_interrupt;
+ QCheckBox *ui_showname_enable;
+
+ AOButton *ui_custom_objection;
+ QMenu *custom_obj_menu;
+ AOButton *ui_realization;
+ AOButton *ui_screenshake;
+ AOButton *ui_mute;
+
+ AOButton *ui_defense_plus;
+ AOButton *ui_defense_minus;
+
+ AOButton *ui_prosecution_plus;
+ AOButton *ui_prosecution_minus;
+
+ QComboBox *ui_text_color;
+
+ QSlider *ui_music_slider;
+ QSlider *ui_sfx_slider;
+ QSlider *ui_blip_slider;
+
+ AOImage *ui_muted;
+
+ AOButton *ui_evidence_button;
+ AOImage *ui_evidence;
+ AOLineEdit *ui_evidence_name;
+ QWidget *ui_evidence_buttons;
+ QVector<AOEvidenceButton *> ui_evidence_list;
+ AOButton *ui_evidence_left;
+ AOButton *ui_evidence_right;
+ AOButton *ui_evidence_present;
+ AOImage *ui_evidence_overlay;
+ AOButton *ui_evidence_delete;
+ AOLineEdit *ui_evidence_image_name;
+ AOButton *ui_evidence_image_button;
+ AOButton *ui_evidence_x;
+ AOButton *ui_evidence_ok;
+ AOButton *ui_evidence_switch;
+ AOButton *ui_evidence_transfer;
+ AOButton *ui_evidence_save;
+ AOButton *ui_evidence_load;
+ AOTextEdit *ui_evidence_description;
+
+ AOImage *ui_char_select_background;
+
+ // abstract widget to hold char buttons
+ QWidget *ui_char_buttons;
+
+ QVector<AOCharButton *> ui_char_button_list;
+ QVector<AOCharButton *> ui_char_button_list_filtered;
+ AOImage *ui_selector;
+
+ AOButton *ui_back_to_lobby;
+
+ QLineEdit *ui_char_password;
+
+ AOButton *ui_char_select_left;
+ AOButton *ui_char_select_right;
+
+ AOButton *ui_spectator;
+
+ QLineEdit *ui_char_search;
+ QCheckBox *ui_char_passworded;
+ QCheckBox *ui_char_taken;
+
+ void construct_char_select();
+ void set_char_select();
+ void set_char_select_page();
+ void char_clicked(int n_char);
+ void put_button_in_place(int starting, int chars_on_this_page);
+ void filter_character_list();
+
+ void initialize_emotes();
+ void refresh_emotes();
+ void set_emote_page();
+ void set_emote_dropdown();
+
+ void initialize_evidence();
+ void refresh_evidence();
+ void set_evidence_page();
+
+public slots:
+ void objection_done();
+ void preanim_done();
+ void do_screenshake();
+ void do_flash();
+ void do_effect(QString fx_path, QString fx_sound, QString p_char,
+ QString p_folder);
+ void play_char_sfx(QString sfx_name);
+
+ void mod_called(QString p_ip);
+
+ void case_called(QString msg, bool def, bool pro, bool jud, bool jur,
+ bool steno);
+
+private slots:
+ void start_chat_ticking();
+ void play_sfx();
+
+ void chat_tick();
+
+ void on_mute_list_clicked(QModelIndex p_index);
+ void on_pair_list_clicked(QModelIndex p_index);
+
+ void on_chat_return_pressed();
+
+ void on_ooc_return_pressed();
+
+ void on_music_search_return_pressed();
+ void on_music_search_edited(QString p_text);
+ void on_music_list_double_clicked(QTreeWidgetItem *p_item, int column);
+ void on_music_list_context_menu_requested(const QPoint &pos);
+ void music_fade_out(bool toggle);
+ void music_fade_in(bool toggle);
+ void music_synchronize(bool toggle);
+ void music_random();
+ void music_list_expand_all();
+ void music_list_collapse_all();
+ void on_area_list_double_clicked(QTreeWidgetItem *p_item, int column);
+
+ void select_emote(int p_id);
+
+ void on_emote_clicked(int p_id);
+
+ void on_emote_left_clicked();
+ void on_emote_right_clicked();
+
+ void on_emote_dropdown_changed(int p_index);
+ void on_pos_dropdown_changed(int p_index);
+
+ void on_iniswap_dropdown_changed(int p_index);
+ void set_iniswap_dropdown();
+ void on_iniswap_context_menu_requested(const QPoint &pos);
+ void on_iniswap_edit_requested();
+ void on_iniswap_remove_clicked();
+
+ void on_sfx_dropdown_changed(int p_index);
+ void set_sfx_dropdown();
+ void on_sfx_context_menu_requested(const QPoint &pos);
+ void on_sfx_edit_requested();
+ void on_sfx_remove_clicked();
+
+ void set_effects_dropdown();
+ void on_effects_context_menu_requested(const QPoint &pos);
+ void on_effects_edit_requested();
+ void on_character_effects_edit_requested();
+ void on_effects_dropdown_changed(int p_index);
+ bool effects_dropdown_find_and_set(QString effect);
+
+ QString get_char_sfx();
+ int get_char_sfx_delay();
+
+ void on_evidence_name_edited();
+ void on_evidence_image_name_edited();
+ void on_evidence_image_button_clicked();
+ void on_evidence_clicked(int p_id);
+ void on_evidence_double_clicked(int p_id);
+
+ void on_evidence_hover(int p_id, bool p_state);
+
+ void on_evidence_left_clicked();
+ void on_evidence_right_clicked();
+ void on_evidence_present_clicked();
+
+ void on_hold_it_clicked();
+ void on_objection_clicked();
+ void on_take_that_clicked();
+ void on_custom_objection_clicked();
+ void show_custom_objection_menu(const QPoint &pos);
+
+ void on_realization_clicked();
+ void on_screenshake_clicked();
+
+ void on_mute_clicked();
+ void on_pair_clicked();
+ void on_pair_order_dropdown_changed(int p_index);
+
+ void on_defense_minus_clicked();
+ void on_defense_plus_clicked();
+ void on_prosecution_minus_clicked();
+ void on_prosecution_plus_clicked();
+
+ void on_text_color_changed(int p_color);
+ void set_text_color_dropdown();
+
+ void on_music_slider_moved(int p_value);
+ void on_sfx_slider_moved(int p_value);
+ void on_blip_slider_moved(int p_value);
+
+ void on_log_limit_changed(int value);
+ void on_pair_offset_changed(int value);
+
+ void on_ooc_toggle_clicked();
+
+ void on_witness_testimony_clicked();
+ void on_cross_examination_clicked();
+ void on_not_guilty_clicked();
+ void on_guilty_clicked();
+
+ void on_change_character_clicked();
+ void on_reload_theme_clicked();
+ void on_call_mod_clicked();
+ void on_settings_clicked();
+ void on_announce_casing_clicked();
+
+ void on_pre_clicked();
+ void on_flip_clicked();
+ void on_additive_clicked();
+ void on_guard_clicked();
+
+ void on_showname_enable_clicked();
+
+ void on_evidence_name_double_clicked();
+ void on_evidence_image_name_double_clicked();
+ void on_evidence_button_clicked();
+
+ void on_evidence_delete_clicked();
+ void on_evidence_x_clicked();
+ void on_evidence_ok_clicked();
+ void on_evidence_switch_clicked();
+ void on_evidence_transfer_clicked();
+
+ void on_evidence_edited();
+
+ void evidence_close();
+ void evidence_switch(bool global);
+ void on_evidence_save_clicked();
+ void on_evidence_load_clicked();
+ bool compare_evidence_changed(evi_type evi_a, evi_type evi_b);
+
+ void on_back_to_lobby_clicked();
+
+ void on_char_select_left_clicked();
+ void on_char_select_right_clicked();
+ void on_char_search_changed();
+ void on_char_taken_clicked();
+ void on_char_passworded_clicked();
+
+ void on_spectator_clicked();
+
+ void on_switch_area_music_clicked();
+
+ void on_casing_clicked();
+
+ void ping_server();
+
+ void load_bass_opus_plugin();
+};
+
+#endif // COURTROOM_H
diff --git a/include/datatypes.h b/include/datatypes.h
index 89d4a40c..21ade040 100644
--- a/include/datatypes.h
+++ b/include/datatypes.h
@@ -96,9 +96,11 @@ enum CHAT_MESSAGE {
SCREENSHAKE,
FRAME_SCREENSHAKE,
FRAME_REALIZATION,
- FRAME_SFX
+ FRAME_SFX,
+ ADDITIVE,
+ EFFECTS
};
-enum COLOR { WHITE = 0, GREEN, RED, ORANGE, BLUE, YELLOW, RAINBOW, PINK, CYAN };
+enum MUSIC_EFFECT { FADE_IN = 1, FADE_OUT = 2, SYNC_POS = 4 };
#endif // DATATYPES_H
diff --git a/include/discord_rich_presence.h b/include/discord_rich_presence.h
index 71c85e25..42de59e2 100644
--- a/include/discord_rich_presence.h
+++ b/include/discord_rich_presence.h
@@ -8,6 +8,7 @@
#include <string>
#include <discord-rpc.h>
+#include <string>
#include <cstring>
#include <ctime>
diff --git a/include/lobby.h b/include/lobby.h
index a9b60571..42f52977 100644
--- a/include/lobby.h
+++ b/include/lobby.h
@@ -13,6 +13,7 @@
#include <QPlainTextEdit>
#include <QProgressBar>
#include <QTextBrowser>
+#include <QTreeWidget>
#include <QDebug>
#include <QScrollBar>
@@ -31,13 +32,17 @@ public:
void append_chatmessage(QString f_name, QString f_message);
void append_error(QString f_message);
void set_player_count(int players_online, int max_players);
+ void set_stylesheet(QWidget *widget, QString target_tag);
+ void set_stylesheets();
+ void set_fonts();
+ void set_font(QWidget *widget, QString p_identifier);
void set_loading_text(QString p_text);
void show_loading_overlay() { ui_loading_background->show(); }
void hide_loading_overlay() { ui_loading_background->hide(); }
QString get_chatlog();
int get_selected_server();
void enable_connect_button();
- void check_update();
+
void set_loading_value(int p_value);
bool public_servers_selected = true;
@@ -59,7 +64,10 @@ private:
QLabel *ui_version;
AOButton *ui_about;
- QListWidget *ui_server_list;
+ AOButton *ui_settings;
+
+ QTreeWidget *ui_server_list;
+ QLineEdit *ui_server_search;
QLabel *ui_player_count;
AOTextArea *ui_description;
@@ -74,11 +82,10 @@ private:
QProgressBar *ui_progress_bar;
AOButton *ui_cancel;
- QModelIndex last_model;
+ int last_index;
void set_size_and_pos(QWidget *p_widget, QString p_identifier);
-public slots:
- void lobbyThreadHandler(QString loadingText);
+
private slots:
void on_public_servers_clicked();
void on_favorites_clicked();
@@ -90,8 +97,10 @@ private slots:
void on_connect_pressed();
void on_connect_released();
void on_about_clicked();
- void on_server_list_clicked(QModelIndex p_model);
- void on_server_list_doubleclicked(QModelIndex p_model);
+ void on_settings_clicked();
+ void on_server_list_clicked(QTreeWidgetItem *p_item, int column);
+ void on_server_list_doubleclicked(QTreeWidgetItem *p_item, int column);
+ void on_server_search_edited(QString p_text);
void on_chatfield_return_pressed();
};
diff --git a/include/scrolltext.h b/include/scrolltext.h
new file mode 100644
index 00000000..9ed5ff77
--- /dev/null
+++ b/include/scrolltext.h
@@ -0,0 +1,47 @@
+#ifndef SCROLLTEXT_H
+#define SCROLLTEXT_H
+
+#include <QDebug>
+#include <QPainter>
+#include <QStaticText>
+#include <QTimer>
+#include <QWidget>
+
+class ScrollText : public QWidget {
+ Q_OBJECT
+ Q_PROPERTY(QString text READ text WRITE setText)
+ Q_PROPERTY(QString separator READ separator WRITE setSeparator)
+
+public:
+ explicit ScrollText(QWidget *parent = nullptr);
+
+public slots:
+ QString text() const;
+ void setText(QString text);
+
+ QString separator() const;
+ void setSeparator(QString separator);
+
+protected:
+ virtual void paintEvent(QPaintEvent *);
+ virtual void resizeEvent(QResizeEvent *);
+
+private:
+ void updateText();
+ QString _text;
+ QString _separator;
+ QStaticText staticText;
+ int singleTextWidth;
+ QSize wholeTextSize;
+ int leftMargin;
+ bool scrollEnabled;
+ int scrollPos;
+ QImage alphaChannel;
+ QImage buffer;
+ QTimer timer;
+
+private slots:
+ virtual void timer_timeout();
+};
+
+#endif // SCROLLTEXT_H
diff --git a/resource/logo.icns b/resource/logo_ao2.icns
index fb2456c8..fb2456c8 100644
--- a/resource/logo.icns
+++ b/resource/logo_ao2.icns
Binary files differ
diff --git a/resource/logo.ico b/resource/logo_ao2.ico
index b40e7866..b40e7866 100644
--- a/resource/logo.ico
+++ b/resource/logo_ao2.ico
Binary files differ
diff --git a/resource/logo.png b/resource/logo_ao2.png
index f53fe30c..f53fe30c 100644
--- a/resource/logo.png
+++ b/resource/logo_ao2.png
Binary files differ
diff --git a/resource/logo_kfo.ico b/resource/logo_kfo.ico
new file mode 100644
index 00000000..3c68adff
--- /dev/null
+++ b/resource/logo_kfo.ico
Binary files differ
diff --git a/resource/logo_kfo.png b/resource/logo_kfo.png
new file mode 100644
index 00000000..d8001233
--- /dev/null
+++ b/resource/logo_kfo.png
Binary files differ
diff --git a/resource/translations/ao_de.ts b/resource/translations/ao_de.ts
index c4e9f300..8b1aa844 100644
--- a/resource/translations/ao_de.ts
+++ b/resource/translations/ao_de.ts
@@ -9,7 +9,7 @@
<translation>Vom Server getrennt.</translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="151"/>
+ <location filename="../../src/aoapplication.cpp" line="152"/>
<source>Error connecting to master server. Will try again in %1 seconds.</source>
<translation>Fehler bei der Verbindung zum Master Server. Erneuter Versuch in %1 Sekunden.</translation>
</message>
@@ -18,7 +18,7 @@
<translation type="vanished">Fehler bei der Verbindung zum Master Server. Erneuter Versuch in %n Sekunden.</translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="156"/>
+ <location filename="../../src/aoapplication.cpp" line="157"/>
<source>There was an error connecting to the master server.
We deploy multiple master servers to mitigate any possible downtime, but the client appears to have exhausted all possible methods of finding and connecting to one.
Please check your Internet connection and firewall, and please try again.</source>
@@ -27,68 +27,67 @@ Wir verwenden mehrere Master Server um Ausfälle zu verhindern, jedoch hat der C
Bitte prüfe deine Internetverbindung und Firewall, und versuche es erneut.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="108"/>
+ <location filename="../../src/packet_distribution.cpp" line="94"/>
<source>Outdated version! Your version: %1
Please go to aceattorneyonline.com to update.</source>
<translation>Version zu alt! Deine Version: %1
Bitte besuche aceattorneyonline.com für ein Update.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="115"/>
<source>You have been exiled from AO.
Have a nice day.</source>
- <translation>Du wurdest von AO befreit.
+ <translation type="vanished">Du wurdest von AO befreit.
Schönen Urlaub.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="258"/>
+ <location filename="../../src/packet_distribution.cpp" line="235"/>
<source>Attorney Online 2</source>
<translation>Attorney Online 2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="282"/>
+ <location filename="../../src/packet_distribution.cpp" line="263"/>
<source>Loading</source>
<translation>Laden</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="373"/>
+ <location filename="../../src/packet_distribution.cpp" line="363"/>
<source>Loading evidence:
%1/%2</source>
<translation>Lade Beweisstücke:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="408"/>
- <location filename="../../src/packet_distribution.cpp" line="506"/>
+ <location filename="../../src/packet_distribution.cpp" line="398"/>
+ <location filename="../../src/packet_distribution.cpp" line="492"/>
<source>Loading music:
%1/%2</source>
<translation>Lade Musik:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="326"/>
- <location filename="../../src/packet_distribution.cpp" line="457"/>
+ <location filename="../../src/packet_distribution.cpp" line="316"/>
+ <location filename="../../src/packet_distribution.cpp" line="465"/>
<source>Loading chars:
%1/%2</source>
<translation>Lade Charaktere:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="635"/>
+ <location filename="../../src/packet_distribution.cpp" line="674"/>
<source>You have been kicked from the server.
Reason: %1</source>
<translation>Du wurdest von diesem Server geschmissen.
Grund: %1</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="643"/>
+ <location filename="../../src/packet_distribution.cpp" line="682"/>
<source>You have been banned from the server.
Reason: %1</source>
<translation>Du wurdest von diesem Server verbannt.
Grund: %1</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="651"/>
+ <location filename="../../src/packet_distribution.cpp" line="690"/>
<source>You are banned on this server.
Reason: %1</source>
<translation>Du bist von diesem Server verbannt.
@@ -153,382 +152,450 @@ Grund: </translation>
<translation>Stenograph benötigt</translation>
</message>
<message>
- <location filename="../../src/aocaseannouncerdialog.cpp" line="66"/>
<source>Witness needed</source>
- <translation>Zeuge benötigt</translation>
+ <translation type="vanished">Zeuge benötigt</translation>
</message>
</context>
<context>
<name>AOOptionsDialog</name>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="11"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="12"/>
<source>Settings</source>
<translation>Einstellungen</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="48"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="46"/>
<source>Gameplay</source>
<translation>Spiel</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="61"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="62"/>
<source>Theme:</source>
<translation>Theme:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="63"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="64"/>
<source>Sets the theme used in-game. If the new theme changes the lobby&apos;s look as well, you&apos;ll need to reload the lobby for the changes to take effect, such as by joining a server and leaving it.</source>
<translation>Setzt das Theme. Wenn das neue Theme auch das Aussehen der Lobby verändert, must du diese neu laden um die Änderungen zu sehen.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="109"/>
<source>Gives the default value for the in-game &apos;Custom shownames&apos; checkbox, which in turn determines whether the client should display custom in-character names.</source>
- <translation>Setzt den Standardwerd für den eigenen Anzeigenamen.</translation>
+ <translation type="vanished">Setzt den Standardwerd für den eigenen Anzeigenamen.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="305"/>
<source>Sets the default volume for music.</source>
- <translation>Standardlautstärke für die Musik.</translation>
+ <translation type="vanished">Standardlautstärke für die Musik.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="320"/>
<source>Sets the default volume for SFX sounds, like interjections or other character sound effects.</source>
- <translation>Standardlautstärke für Soundeffekte.</translation>
+ <translation type="vanished">Standardlautstärke für Soundeffekte.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="568"/>
<source>IC Log</source>
- <translation>Log</translation>
+ <translation type="vanished">Log</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="581"/>
<source>Colorful IC log:</source>
- <translation>Farbiges Log:</translation>
+ <translation type="vanished">Farbiges Log:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="583"/>
<source>Enables colored text in the log.</source>
- <translation>Aktiviert farbigen Text im Log.</translation>
+ <translation type="vanished">Aktiviert farbigen Text im Log.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="594"/>
<source>Only inline coloring:</source>
- <translation>Nur in-Zeilen Farben:</translation>
+ <translation type="vanished">Nur in-Zeilen Farben:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="596"/>
<source>Only inline coloring will be shown such as &lt;&gt;,|| etc.</source>
- <translation>Nur die in-Zeilen Farben wie &lt;&gt;,|| etc. werden gezeigt.</translation>
+ <translation type="vanished">Nur die in-Zeilen Farben wie &lt;&gt;,|| etc. werden gezeigt.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="606"/>
<source>Mirror IC log:</source>
- <translation>Log spiegeln:</translation>
+ <translation type="vanished">Log spiegeln:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="608"/>
<source>IC log will mirror the IC box. Meaning that if somebody gets interrupted nobody will know what they wanted to say. Enable for a more realistic experience.</source>
- <translation>Das Log spiegelt die Nachrichten. Bedeutet dass wenn jemand unterbrochen wird, kann man nicht sehen was derjenige sagen wollte. Für ein realistischeres Spielerlebnis.</translation>
+ <translation type="vanished">Das Log spiegelt die Nachrichten. Bedeutet dass wenn jemand unterbrochen wird, kann man nicht sehen was derjenige sagen wollte. Für ein realistischeres Spielerlebnis.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="620"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="95"/>
<source>Log goes downwards:</source>
<translation>Verlauf geht nach unten:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="622"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="97"/>
<source>If ticked, new messages will appear at the bottom (like the OOC chatlog). The traditional (AO1) behaviour is equivalent to this being unticked.</source>
<translation>Wenn angehakt werden neue Nachrichten unten erscheinen (wie beim OOC). Das traditionelle (AO1) Verhalten wäre nicht angehakt.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="634"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="110"/>
<source>Log length:</source>
<translation>Länge:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="635"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="111"/>
<source>The amount of messages the IC chatlog will keep before deleting older messages. A value of 0 or below counts as &apos;infinite&apos;.</source>
<translation>Die Menge an Nachrichten die aufgehoben werden bevor alte gelöscht werden. 0 bedeutet unendlich.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="93"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="133"/>
<source>Default username:</source>
<translation>Standard Benutzername:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="95"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="135"/>
<source>Your OOC name will be automatically set to this value when you join a server.</source>
<translation>Dein OOC Name wird automatisch auf dies gesetzt.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="107"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="148"/>
<source>Custom shownames:</source>
<translation>Eigener Anzeigename:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="150"/>
<source>Gives the default value for the in-game &apos;Custom shownames&apos; tickbox, which in turn determines whether the client should display custom in-character names.</source>
- <translation type="vanished">Standardwert für die Anzeigename Box, welche den In-Charakter Namen bestimmt.</translation>
+ <translation>Standardwert für die Anzeigename Box, welche den In-Charakter Namen bestimmt.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="127"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="170"/>
<source>Backup MS:</source>
<translation>Rückfall MS:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="129"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="172"/>
<source>If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address.</source>
<translation>Wenn dereingebaute Master Server fehlschlägt, wird das Spiel diesen hier verwenden.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="141"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="185"/>
<source>Discord:</source>
<translation>Discord:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="143"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="187"/>
<source>Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for.</source>
<translation>Erlaubt anderen auf Discord zu sehen auf welchem Server du spielst, welchen Charakter du spielst und wie lange.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="155"/>
<source>Allow Shake/Flash:</source>
- <translation>Schütteln/Geistesblitz erlauben:</translation>
+ <translation type="vanished">Schütteln/Geistesblitz erlauben:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="157"/>
<source>Allows screenshaking and flashing. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
- <translation>Erlaubt schütteln des Bildschirms und weiße Blitze. Deaktiviere dies falls du Bedenken wegen Photosensitivität hast.</translation>
+ <translation type="vanished">Erlaubt schütteln des Bildschirms und weiße Blitze. Deaktiviere dies falls du Bedenken wegen Photosensitivität hast.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="168"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="200"/>
<source>Language:</source>
<translation>Sprache:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="170"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="202"/>
<source>Sets the language if you don&apos;t want to use your system language.</source>
<translation>Setzte die Sprache falls du nicht die Systemsprache verwenden möchtest.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="193"/>
<source>Slower text speed:</source>
- <translation>Langsamerer Text:</translation>
+ <translation type="vanished">Langsamerer Text:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="194"/>
<source>Set the text speed to be the same as the AA games.</source>
- <translation>Setzt den Text auf die gleiche Geschwindigkeit wie in den AA Spielen.</translation>
+ <translation type="vanished">Setzt den Text auf die gleiche Geschwindigkeit wie in den AA Spielen.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="201"/>
<source>Blip delay on punctuations:</source>
- <translation>Blip Pausen bei Satzzeichen:</translation>
+ <translation type="vanished">Blip Pausen bei Satzzeichen:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="202"/>
<source>Punctuation delay modifier. Enable it for the blips to slow down on punctuations.</source>
- <translation>Aktivieren damit die Blips bei Satzzeichen langsamer werden.</translation>
+ <translation type="vanished">Aktivieren damit die Blips bei Satzzeichen langsamer werden.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="208"/>
+ <source> - Keep current setting</source>
+ <translation> - aktuelle Einstellung behalten</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="220"/>
+ <source>Allow Screenshake:</source>
+ <translation>Schütteln erlauben:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="222"/>
+ <source>Allows screenshaking. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
+ <translation>Erlaubt schütteln des Bildschirms. Deaktiviere dies falls du Bedenken wegen Photosensitivität hast.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="234"/>
+ <source>Allow Effects:</source>
+ <translation>Effekte erlauben:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="236"/>
+ <source>Allows screen effects. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
+ <translation>Erlaubt Bildeffekte. Deaktiviere dies falls du Bedenken wegen Photosensitivität hast.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="248"/>
+ <source>Network Frame Effects:</source>
+ <translation>Netzwerk Frame-Effekte:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="249"/>
+ <source>Send screen-shaking, flashes and sounds as defined in the char.ini over the network. Only works for servers that support this functionality.</source>
+ <translation>Sendet schüttel, Blitze und Geräusche aus der char.ini Datei über das Netzwerk. Funkioniert nur wenn der Server dies unterstützt.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="262"/>
+ <source>Colors in IC Log:</source>
+ <translation>Farben im IC Log:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="264"/>
+ <source>Use the markup colors in the server IC chatlog.</source>
+ <translation>Verwendet Farbe im IC Log so wie im Bild.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="275"/>
+ <source>Sticky Sounds:</source>
+ <translation>Klebende Geräuschauswahl:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="277"/>
+ <source>Turn this on to prevent the sound dropdown from clearing the sound after playing it.</source>
+ <translation>Aktiviere dies damit die Geräuschauswahl nicht zurückspringt nachdem es abgespielt wurde.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="212"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="289"/>
+ <source>Sticky Effects:</source>
+ <translation>Klebende Effekt:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="291"/>
+ <source>Turn this on to prevent the effects dropdown from clearing the effect after playing it.</source>
+ <translation>Aktiviere dies damit die Effektauswahl nicht zurückspringt nachdem er abgespielt wurde.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="304"/>
+ <source>Sticky Preanims:</source>
+ <translation>Klebende Voranimation:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="306"/>
+ <source>Turn this on to prevent preanimation checkbox from clearing after playing the emote.</source>
+ <translation>Aktiviere dies damit das Kontrollkästchen für die Voranimation nicht zurückspringt nachdem sie abgespielt wurde.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="324"/>
<source>Callwords</source>
<translation>Alarmwörter</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="239"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="351"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!&lt;br&gt;Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Gib so viele Alarmwörter ein wie du möchtest. Groß/Kleinschreibung ist egal. Für jede Wort nur eine Zeile!&lt;br&gt;Bitte keine leere Zeile am Ende -- du bekommst sonst bei jeder Nachricht einen Alarm.&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="249"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="361"/>
<source>Audio</source>
<translation>Audio</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="262"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="375"/>
<source>Audio device:</source>
<translation>Audiogerät:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="263"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="376"/>
<source>Sets the audio device for all sounds.</source>
<translation>Setzt das Audiogerät für all Geräusche.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="304"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="419"/>
<source>Music:</source>
<translation>Musik:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="420"/>
<source>Sets the music&apos;s default volume.</source>
- <translation type="vanished">Setzt die Musiklautstärke.</translation>
+ <translation>Setzt die Musiklautstärke.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="318"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="434"/>
<source>SFX:</source>
<translation>SFX:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="436"/>
<source>Sets the SFX&apos;s default volume. Interjections and actual sound effects count as &apos;SFX&apos;.</source>
- <translation type="vanished">Setzt die Lautstärke der Soundeffekte wie Einsprüche und die Geräusche der Charaktere.</translation>
+ <translation>Setzt die Lautstärke der Soundeffekte wie Einsprüche und die Geräusche der Charaktere.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="333"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="450"/>
<source>Blips:</source>
<translation>Blips:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="335"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="452"/>
<source>Sets the volume of the blips, the talking sound effects.</source>
<translation>Setzt die Lautstärke der Blips, das ist das Geräusch das die Charaktere beim Reden machen.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="354"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="474"/>
<source>Blip rate:</source>
<translation>Bliprate:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="356"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="476"/>
<source>Sets the delay between playing the blip sounds.</source>
<translation>Setzt die Pause zwischen einzelnen Blips.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="367"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="484"/>
+ <source>Play a blip sound &quot;once per every X symbols&quot;, where X is the blip rate.</source>
+ <translation>Spiele ein blip einmal für all X Buchstaben.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="491"/>
<source>Blank blips:</source>
<translation>Leere Blips:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="369"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="493"/>
<source>If true, the game will play a blip sound even when a space is &apos;being said&apos;.</source>
<translation>Wenn angehakt wird das Spiel auch bei einem Leerzeichen einen Blip machen.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="380"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="505"/>
<source>Enable Looping SFX:</source>
<translation>Wiederholende Soundeffekte:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="381"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="506"/>
<source>If true, the game will allow looping sound effects to play on preanimations.</source>
<translation>Wenn aktiviert, werden wiederholende Soundeffekte bei den Voranimationen erlaubt.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="392"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="518"/>
<source>Kill Music On Objection:</source>
<translation>Stoppe Musik bei Einspruch:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="394"/>
- <source>If true, the game will stop music when someone objects, like in the actual games.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="520"/>
+ <source>If true, AO2 will stop the music for you when you or someone else does &apos;Objection!&apos;.</source>
<translation>Hält die Musik an wenn jemand &quot;Einspruch&quot; ruft, wie im echten Spiel.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="408"/>
+ <source>If true, the game will stop music when someone objects, like in the actual games.</source>
+ <translation type="vanished">Hält die Musik an wenn jemand &quot;Einspruch&quot; ruft, wie im echten Spiel.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="532"/>
<source>Casing</source>
<translation>Fälle</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="424"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="549"/>
<source>This server supports case alerts.</source>
<translation>Dieser Server unterstützt Fallalarme.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="427"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="552"/>
<source>This server does not support case alerts.</source>
<translation>Dieser Server unterstützt Fallalarme nicht.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="428"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="553"/>
<source>Pretty self-explanatory.</source>
<translation>Eigentlich selbsterklärend.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="436"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="562"/>
<source>Casing:</source>
<translation>Fälle:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="438"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="564"/>
<source>If checked, you will get alerts about case announcements.</source>
<translation>Wenn angehakt wirst du benachrichtigt wenn ein Fall angekündigt wird.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="451"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="580"/>
<source>Defense:</source>
<translation>Verteidigung:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="452"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="581"/>
<source>If checked, you will get alerts about case announcements if a defense spot is open.</source>
<translation>Wenn angehakt wirst du benachrichtigt wenn ein Verteidiger benötigt wird.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="465"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="595"/>
<source>Prosecution:</source>
<translation>Kläger:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="467"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="597"/>
<source>If checked, you will get alerts about case announcements if a prosecutor spot is open.</source>
<translation>Wenn angehakt wirst du benachrichtigt wenn ein Kläger benötigt wird.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="480"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="611"/>
<source>Judge:</source>
<translation>Richter:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="481"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="612"/>
<source>If checked, you will get alerts about case announcements if the judge spot is open.</source>
<translation>Wenn angehakt wirst du benachrichtigt wenn ein Richter benötigt wird.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="494"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="626"/>
<source>Juror:</source>
<translation>Jury:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="495"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="627"/>
<source>If checked, you will get alerts about case announcements if a juror spot is open.</source>
<translation>Wenn angehakt wirst du benachrichtigt wenn eine Jury benötigt wird.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="508"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="641"/>
<source>Stenographer:</source>
<translation>Stenograph:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="510"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="643"/>
<source>If checked, you will get alerts about case announcements if a stenographer spot is open.</source>
<translation>Wenn angehakt wirst du benachrichtigt wenn ein Stenograph benötigt wird.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="523"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="657"/>
<source>CM:</source>
<translation>CM:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="525"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="659"/>
<source>If checked, you will appear amongst the potential CMs on the server.</source>
<translation>Wenn angehakt wirst du als potentielle CM angezeigt.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="536"/>
<source>Witness:</source>
- <translation>Zeuge:</translation>
+ <translation type="vanished">Zeuge:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="538"/>
<source>If checked, you will appear amongst the potential witnesses on the server.</source>
- <translation>Wenn angehakt wirst du als potentielle Zeuge angezeigt.</translation>
+ <translation type="vanished">Wenn angehakt wirst du als potentielle Zeuge angezeigt.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="551"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="673"/>
<source>Hosting cases:</source>
<translation>Fallleitung:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="553"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="675"/>
<source>If you&apos;re a CM, enter what cases you are willing to host.</source>
<translation>Wenn du CM bist, gib ein welche Fälle du spielen möchtest.</translation>
</message>
@@ -536,35 +603,36 @@ Grund: </translation>
<context>
<name>Courtroom</name>
<message>
- <location filename="../../src/charselect.cpp" line="69"/>
+ <location filename="../../src/charselect.cpp" line="21"/>
<source>Password</source>
<translation>Passwort</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="75"/>
+ <location filename="../../src/charselect.cpp" line="27"/>
<source>Spectator</source>
<translation>Zuschauer</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="78"/>
- <location filename="../../src/courtroom.cpp" line="179"/>
+ <location filename="../../src/charselect.cpp" line="30"/>
+ <location filename="../../src/courtroom.cpp" line="175"/>
<source>Search</source>
<translation>Suche</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="83"/>
+ <location filename="../../src/charselect.cpp" line="35"/>
<source>Passworded</source>
<translation>Gesperrt</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="87"/>
+ <location filename="../../src/charselect.cpp" line="39"/>
<source>Taken</source>
<translation>Benutzt</translation>
</message>
<message>
+ <location filename="../../src/charselect.cpp" line="231"/>
<source>Generating chars:
%1/%2</source>
- <translation type="vanished">Generiere Charaktere:
+ <translation>Generiere Charaktere:
%1/%2</translation>
</message>
<message>
@@ -574,193 +642,179 @@ Grund: </translation>
</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="182"/>
<source>Could not find %1</source>
- <translation>Konnte %1 nicht finden</translation>
+ <translation type="vanished">Konnte %1 nicht finden</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="149"/>
+ <location filename="../../src/courtroom.cpp" line="148"/>
<source>Showname</source>
<translation>Anzeigename</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="153"/>
+ <location filename="../../src/courtroom.cpp" line="152"/>
<source>Message</source>
<translation>Nachricht</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="160"/>
<source>OOC Message</source>
- <translation>OOC Nachricht</translation>
+ <translation type="vanished">OOC Nachricht</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="164"/>
+ <location filename="../../src/courtroom.cpp" line="167"/>
<source>Name</source>
<translation>Name</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="224"/>
+ <location filename="../../src/courtroom.cpp" line="217"/>
<source>Pre</source>
<translation>Vor</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="227"/>
+ <location filename="../../src/courtroom.cpp" line="220"/>
<source>Flip</source>
<translation>Spiegeln</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="224"/>
<source>Guard</source>
- <translation type="vanished">Wache</translation>
+ <translation>Wache</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="232"/>
<source>Disable Modcalls</source>
- <translation>Deaktiviere Moderatorenrufe</translation>
+ <translation type="vanished">Deaktiviere Moderatorenrufe</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="238"/>
- <location filename="../../src/courtroom.cpp" line="720"/>
+ <location filename="../../src/courtroom.cpp" line="233"/>
+ <location filename="../../src/courtroom.cpp" line="815"/>
<source>Casing</source>
<translation>Fall</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="243"/>
+ <location filename="../../src/courtroom.cpp" line="238"/>
<source>Shownames</source>
<translation>Anzeigenamen</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="246"/>
+ <location filename="../../src/courtroom.cpp" line="241"/>
<source>No Interrupt</source>
<translation>Keine Unterbrechung</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="264"/>
<source>White</source>
- <translation>Weiß</translation>
+ <translation type="vanished">Weiß</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="265"/>
<source>Green</source>
- <translation>Grün</translation>
+ <translation type="vanished">Grün</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="266"/>
<source>Red</source>
- <translation>Rot</translation>
+ <translation type="vanished">Rot</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="267"/>
<source>Orange</source>
- <translation>Orange</translation>
+ <translation type="vanished">Orange</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="268"/>
<source>Blue</source>
- <translation>Blau</translation>
+ <translation type="vanished">Blau</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="269"/>
<source>Yellow</source>
- <translation>Gelb</translation>
+ <translation type="vanished">Gelb</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="646"/>
+ <location filename="../../src/courtroom.cpp" line="742"/>
<source>Music</source>
<translation>Musik</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="648"/>
+ <location filename="../../src/courtroom.cpp" line="744"/>
<source>Sfx</source>
<translation>Sfx</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="650"/>
+ <location filename="../../src/courtroom.cpp" line="746"/>
<source>Blips</source>
<translation>Blips</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="653"/>
<source>Log limit</source>
- <translation>Verlaufsgrenze</translation>
+ <translation type="vanished">Verlaufsgrenze</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="664"/>
- <location filename="../../src/courtroom.cpp" line="3816"/>
+ <location filename="../../src/courtroom.cpp" line="767"/>
+ <location filename="../../src/courtroom.cpp" line="3475"/>
<source>Server</source>
<translation>Server</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="683"/>
+ <location filename="../../src/courtroom.cpp" line="791"/>
<source>Change character</source>
<translation>Charakter ändern</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="693"/>
+ <location filename="../../src/courtroom.cpp" line="797"/>
<source>Reload theme</source>
<translation>Aussehen neu laden</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="702"/>
+ <location filename="../../src/courtroom.cpp" line="803"/>
<source>Call mod</source>
<translation>Moderator rufen</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="711"/>
+ <location filename="../../src/courtroom.cpp" line="809"/>
<source>Settings</source>
<translation>Einstellungen</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="729"/>
+ <location filename="../../src/courtroom.cpp" line="822"/>
<source>A/M</source>
<translation>A/M</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="737"/>
+ <location filename="../../src/courtroom.cpp" line="827"/>
<source>Preanim</source>
<translation>Voranimation</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="818"/>
+ <location filename="../../src/courtroom.cpp" line="913"/>
<source>Back to Lobby</source>
<translation>Zurück zur Lobby</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="1265"/>
- <location filename="../../src/courtroom.cpp" line="3492"/>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
<source>You were granted the Disable Modcalls button.</source>
<translation>Du hast nun den &quot;Modcall deaktivieren&quot; Knopf.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3310"/>
+ <location filename="../../src/courtroom.cpp" line="2984"/>
<source>You have been banned.</source>
<translation>Du wurdest verbannt.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3739"/>
<source>Too many arguments to save a case! You only need a filename without extension and the courtroom status.</source>
- <translation>Zu viele Argumente zum Speichern! Bitte gib nur den Dateinamen ohne Erweiterung und den Saalstatus an.</translation>
+ <translation type="vanished">Zu viele Argumente zum Speichern! Bitte gib nur den Dateinamen ohne Erweiterung und den Saalstatus an.</translation>
</message>
<message>
<source>%1 has played a song: %2</source>
<translation type="vanished">%1 hat ein Lied gespielt: %2</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="270"/>
<source>Rainbow</source>
- <translation>Regenbogen</translation>
+ <translation type="vanished">Regenbogen</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="271"/>
<source>Pink</source>
- <translation>Pink</translation>
+ <translation type="vanished">Pink</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="272"/>
<source>Cyan</source>
- <translation>Cyan</translation>
+ <translation type="vanished">Cyan</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="295"/>
+ <location filename="../../src/courtroom.cpp" line="274"/>
<source>% offset</source>
<translation>% Abstand</translation>
</message>
@@ -773,104 +827,367 @@ Grund: </translation>
<translation type="vanished">Dies bewirkt nichts, aber egal.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3500"/>
<source>This does nothing, but there you go.</source>
- <translation>Dies bewirkt nichts, aber egal.</translation>
+ <translation type="vanished">Dies bewirkt nichts, aber egal.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3506"/>
+ <location filename="../../src/courtroom.cpp" line="3182"/>
<source>You opened the settings menu.</source>
<translation>Du hast die Einstellungen geöffnet.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3519"/>
<source>You will now pair up with </source>
- <translation>Du wirst nun mit </translation>
+ <translation type="vanished">Du wirst nun mit </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3521"/>
<source> if they also choose your character in return.</source>
- <translation> gepaart, wenn der andere dies auch tut.</translation>
+ <translation type="vanished"> gepaart, wenn der andere dies auch tut.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="143"/>
+ <source>None</source>
+ <translation>Keine</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="228"/>
+ <source>Additive</source>
+ <translation>Hinzufügend</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="277"/>
+ <source>To front</source>
+ <translation>Vorne</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="278"/>
+ <source>To behind</source>
+ <translation>Hinten</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="591"/>
+ <source>Select a character you wish to pair with.</source>
+ <translation>Wähle einen Charakter mit dem du gepaart sein möchtest.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="596"/>
+ <source>Change the percentage offset of your character&apos;s position from the center of the screen.</source>
+ <translation>Ändere den Abstand des Charakters zur Mitte.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="602"/>
+ <source>Change the order of appearance for your character.</source>
+ <translation>Ändere die Reihenfolge in der die Charaktere erscheinen.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="607"/>
+ <source>Display the list of characters to pair with.</source>
+ <translation>Zeigt die Liste der paarbaren Charaktere.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="665"/>
+ <source>Oops, you&apos;re muted!</source>
+ <translation>Ohje, du bist stumm!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="679"/>
+ <source>Set your character&apos;s emote to play on your next message.</source>
+ <translation>Setzt den Ausdruck für die nächste Nachricht.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="683"/>
+ <source>Set your character&apos;s supplementary background.</source>
+ <translation>Setzt die Position des Charakters.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="689"/>
+ <source>Set an &apos;iniswap&apos;, or an alternative character folder to refer to from your current character.
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/iniswaps.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="698"/>
+ <location filename="../../src/courtroom.cpp" line="715"/>
+ <source>Remove the currently selected iniswap from the list and return to the original character folder.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="706"/>
+ <source>Set a sound effect to play on your next &apos;Preanim&apos;. Leaving it on Default will use the emote-defined sound (if any).
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/soundlist.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="722"/>
+ <source>Choose an effect to play on your next spoken message.
+The effects are defined in your theme/effects/effects.ini. Your character can define custom effects by
+char.ini [Options] category, effects = &apos;miscname&apos; where it referes to misc/&lt;miscname&gt;/effects.ini to read the effects.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="749"/>
+ <source>Hold It!</source>
+ <translation>Moment mal!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="750"/>
+ <location filename="../../src/courtroom.cpp" line="756"/>
+ <location filename="../../src/courtroom.cpp" line="762"/>
+ <source>When this is turned on, your next in-character message will be a shout!</source>
+ <translation>Wenn dies an ist, wird die Nächste Nachricht ein Zuruf!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="755"/>
+ <source>Objection!</source>
+ <translation>Einspruch!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="761"/>
+ <source>Take That!</source>
+ <translation>Nimm das!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="769"/>
+ <source>Toggle between server chat and global AO2 chat.</source>
+ <translation>Wechselt zwischen Serverchat und AO2 Chat.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="773"/>
+ <location filename="../../src/courtroom.cpp" line="777"/>
+ <location filename="../../src/courtroom.cpp" line="783"/>
+ <location filename="../../src/courtroom.cpp" line="787"/>
+ <source>This will display the animation in the viewport as soon as it is pressed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="781"/>
+ <source>Guilty!</source>
+ <translation>Schuldig!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="794"/>
+ <source>Bring up the Character Select Screen and change your character.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="800"/>
+ <source>Refresh the theme and update all of the ui elements to match.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="806"/>
+ <source>Request the attention of the current server&apos;s moderator.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="812"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="818"/>
+ <source>An interface to help you announce a case (you have to be a CM first to be able to announce cases)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="824"/>
+ <source>Switch between Areas and Music lists</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3527"/>
+ <location filename="../../src/courtroom.cpp" line="829"/>
+ <source>Play a single-shot animation as defined by the emote when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="833"/>
+ <source>If preanim is checked, display the input text immediately as the animation plays concurrently.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="837"/>
+ <source>Mirror your character&apos;s emotes when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="841"/>
+ <source>Add text to your last spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="845"/>
+ <source>Do not listen to mod calls when checked, preventing them from playing sounds or focusing attention on the window.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="849"/>
+ <source>Lets you receive case alerts when enabled.
+(You can set your preferences in the Settings!)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="854"/>
+ <source>Display customized shownames for all users when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="857"/>
+ <source>Custom Shout!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="860"/>
+ <source>This will display the custom character-defined animation in the viewport as soon as it is pressed.
+To make one, your character&apos;s folder must contain custom.[webp/apng/gif/png] and custom.[wav/ogg/opus] sound effect</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="868"/>
+ <source>Play realization sound and animation in the viewport on the next spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="874"/>
+ <source>Shake the screen on next spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="880"/>
+ <source>Display the list of character folders you wish to mute.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="884"/>
+ <location filename="../../src/courtroom.cpp" line="892"/>
+ <source>Increase the health bar.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="888"/>
+ <location filename="../../src/courtroom.cpp" line="896"/>
+ <source>Decrease the health bar.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="900"/>
+ <source>Change the text color of the spoken message.
+You can also select a part of your currently typed message and use the dropdown to change its color!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="914"/>
+ <source>Return back to the server list.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="927"/>
+ <source>Become a spectator. You won&apos;t be able to interact with the in-character screen.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
+ <location filename="../../src/courtroom.cpp" line="3343"/>
+ <source>CLIENT</source>
+ <translation>CLIENT</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3061"/>
+ <location filename="../../src/courtroom.cpp" line="4479"/>
+ <location filename="../../src/courtroom.cpp" line="4486"/>
+ <source>has played a song</source>
+ <translation>spielte ein Lied</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3195"/>
+ <source>You will now pair up with %1 if they also choose your character in return.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3201"/>
<source>You are no longer paired with anyone.</source>
<translation>Du bist nicht mehr gepaart.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3532"/>
+ <location filename="../../src/courtroom.cpp" line="3206"/>
<source>Are you sure you typed that well? The char ID could not be recognised.</source>
<translation>Hast du dich vertippt? Die ID konnte nicht erkannt werden.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3547"/>
+ <location filename="../../src/courtroom.cpp" line="3221"/>
<source>You have set your offset to </source>
<translation>Dein Abstand ist auf </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3554"/>
+ <location filename="../../src/courtroom.cpp" line="3228"/>
<source>Your offset must be between -100% and 100%!</source>
<translation>Der Abstand muss zwischen -100% und 100% liegen!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3559"/>
+ <location filename="../../src/courtroom.cpp" line="3233"/>
<source>That offset does not look like one.</source>
<translation>Das sieht nicht wie ein Abstand aus.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3565"/>
+ <location filename="../../src/courtroom.cpp" line="3239"/>
<source>You switched your music and area list.</source>
<translation>Du hast zwischen Musik- und Gebitsliste umgeschaltet.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3572"/>
+ <location filename="../../src/courtroom.cpp" line="3246"/>
<source>You have forcefully enabled features that the server may not support. You may not be able to talk IC, or worse, because of this.</source>
<translation>Du hast Funktionen erzwungen die der Server eventuell nicht unterstützt. Möglicherweise wirst du nicht mehr sprechen können.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3586"/>
+ <location filename="../../src/courtroom.cpp" line="3260"/>
<source>Your pre-animations interrupt again.</source>
<translation>Deine Voranimation unterbrechen nun Text.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3589"/>
+ <location filename="../../src/courtroom.cpp" line="3263"/>
<source>Your pre-animations will not interrupt text.</source>
<translation>Deine Voranimation unterbrechen Text nicht.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3600"/>
+ <location filename="../../src/courtroom.cpp" line="3274"/>
<source>Couldn&apos;t open chatlog.txt to write into.</source>
<translation>Konnte chatlog.txt nicht öffnen.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3613"/>
+ <location filename="../../src/courtroom.cpp" line="3287"/>
<source>The IC chatlog has been saved.</source>
<translation>Der IC Verlauf wurde gespeichert.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3626"/>
+ <location filename="../../src/courtroom.cpp" line="3300"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely the case file you&apos;re looking for can&apos;t be found in there.</source>
<translation>Du hattest keinen &apos;base/cases&apos; Ordner! Ich hab ihn nun angelegt aber bedenke das er leer sein wird.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3641"/>
+ <location filename="../../src/courtroom.cpp" line="3315"/>
<source>You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini.
Cases you can load: %1</source>
<translation>Du musst einen Dateinamen angeben (ohne .ini). Stelle sicher das er im &apos;base/cases&apos; Ordner ist und das er korrekt formatiert ist.
Verfügbare Fälle: %1</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3669"/>
+ <location filename="../../src/courtroom.cpp" line="3343"/>
<source>Case made by %1.</source>
<translation>Fall von %1.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3679"/>
+ <location filename="../../src/courtroom.cpp" line="3353"/>
<source>Navigate to %1 for the CM doc.</source>
<translation>Gehe zu %1 für das CM Dokument.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3702"/>
+ <location filename="../../src/courtroom.cpp" line="3367"/>
+ <location filename="../../src/courtroom.cpp" line="3369"/>
+ <location filename="../../src/evidence.cpp" line="761"/>
+ <location filename="../../src/evidence.cpp" line="763"/>
+ <source>UNKNOWN</source>
+ <translation>UNBEKANNT</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3377"/>
<source>Your case &quot;%1&quot; was loaded!</source>
<translation>Dein Fall &quot;%1&quot; wurde geladen!</translation>
</message>
@@ -881,7 +1198,7 @@ Cases you can load: </source>
Verfügbare Fälle: </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3653"/>
+ <location filename="../../src/courtroom.cpp" line="3327"/>
<source>Too many arguments to load a case! You only need one filename, without extension.</source>
<translation>Zu viele Argumente! Du brauchst nur den Dateinamen, ohne Erweiterung.</translation>
</message>
@@ -906,74 +1223,234 @@ Verfügbare Fälle: </translation>
<translation type="vanished">&quot; wurde geladen!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3714"/>
+ <location filename="../../src/courtroom.cpp" line="3389"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely that you somehow deleted it.</source>
<translation>Du hattest keinen &apos;base/cases&apos; Ordner! Ich hab ihn nun angelegt aber bedenke das er leer sein wird.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3729"/>
+ <location filename="../../src/courtroom.cpp" line="3404"/>
<source>You need to give a filename to save (extension not needed) and the courtroom status!</source>
<translation>Du musst einen Dateinamen (ohne Erweiterung) angebenn, sowie den Gebietsstatus!</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="3414"/>
<source>Too many arguments to save a case! You only need a filename without extension and the courtroom status!</source>
- <translation type="vanished">Zu viele Argumente! Du brauchst nur den Dateinamen, ohne Erweiterung sowie den Gebietsstatus!</translation>
+ <translation>Zu viele Argumente! Du brauchst nur den Dateinamen, ohne Erweiterung sowie den Gebietsstatus!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3766"/>
+ <location filename="../../src/courtroom.cpp" line="3441"/>
<source>Succesfully saved, edit doc and cmdoc link on the ini!</source>
<translation>Erfolgreich gespeichert!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3806"/>
+ <location filename="../../src/courtroom.cpp" line="3468"/>
<source>Master</source>
<translation>Master</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4309"/>
+ <location filename="../../src/courtroom.cpp" line="3968"/>
+ <source>Expand All Categories</source>
+ <translation>Alle Kategorien erweitern</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3970"/>
+ <source>Collapse All Categories</source>
+ <translation>Alle Kategorien verstecken</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3974"/>
+ <source>Fade Out Previous</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3980"/>
+ <source>Fade In</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3986"/>
+ <source>Synchronize</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4256"/>
+ <source>Default</source>
+ <translation>Standard</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4417"/>
<source>Reason:</source>
<translation>Grund:</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4310"/>
+ <location filename="../../src/courtroom.cpp" line="4418"/>
<source>Call Moderator</source>
<translation>Moderator rufen</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4426"/>
+ <location filename="../../src/courtroom.cpp" line="4430"/>
<source>Error</source>
<translation>Fehler</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
+ <location filename="../../src/courtroom.cpp" line="4426"/>
<source>You must provide a reason.</source>
<translation>Du musst einen Grund angeben.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4430"/>
<source>The message is too long.</source>
<translation>Die Nachricht ist zu lang.</translation>
</message>
<message>
+ <location filename="../../src/evidence.cpp" line="34"/>
<source>Choose..</source>
- <translation type="vanished">Wähle..</translation>
+ <translation>Wähle..</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="25"/>
<source>Choose...</source>
- <translation>Wähle...</translation>
+ <translation type="vanished">Wähle...</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="17"/>
+ <source>Present this piece of evidence to everyone on your next spoken message</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="24"/>
+ <source>Save evidence to an .ini file.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="26"/>
+ <source>Load evidence from an .ini file.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="31"/>
+ <source>Destroy this piece of evidence</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="37"/>
+ <source>Close the evidence display/editing overlay.
+You will be prompted if there&apos;s any unsaved changes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="40"/>
+ <source>Save any changes made to this piece of evidence and send them to server.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="48"/>
+ <source>Double-click to edit. Press [X] to update your changes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="104"/>
+ <source>Bring up the Evidence screen.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="147"/>
+ <source>Switch evidence to private inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="151"/>
+ <source>Switch evidence to global inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="158"/>
+ <location filename="../../src/evidence.cpp" line="617"/>
+ <source>Transfer evidence to private inventory.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="208"/>
+ <location filename="../../src/evidence.cpp" line="163"/>
+ <location filename="../../src/evidence.cpp" line="627"/>
+ <source>Transfer evidence to global inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="263"/>
+ <source>The piece of evidence you&apos;ve been editing has changed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="264"/>
+ <source>Do you wish to keep your changes?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="265"/>
+ <source>Name: %1
+Image: %2
+Description:
+%3</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="387"/>
<source>Images (*.png)</source>
<translation>Bilder (*.png)</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="280"/>
+ <location filename="../../src/evidence.cpp" line="456"/>
+ <location filename="../../src/evidence.cpp" line="460"/>
+ <location filename="../../src/evidence.cpp" line="463"/>
+ <source>Double-click to edit...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="478"/>
<source>Add new evidence...</source>
<translation>Neues Beweisstück...</translation>
</message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="556"/>
+ <source>Evidence has been modified.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="557"/>
+ <source>Do you want to save your changes?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="619"/>
+ <source>Current evidence is global. Click to switch to private.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="629"/>
+ <source>Current evidence is private. Click to switch to global.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="659"/>
+ <source>&quot;%1&quot; has been transferred.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="721"/>
+ <source>Save Inventory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="721"/>
+ <location filename="../../src/evidence.cpp" line="747"/>
+ <source>Ini Files (*.ini)</source>
+ <translation>Ini Dateien (*.ini)</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="747"/>
+ <source>Open Inventory</source>
+ <translation>Inventar öffnen</translation>
+ </message>
</context>
<context>
<name>Discord</name>
@@ -1010,43 +1487,67 @@ Verfügbare Fälle: </translation>
<translation>Attorney Online 2</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="29"/>
+ <location filename="../../src/lobby.cpp" line="31"/>
+ <source>Search</source>
+ <translation>Suche</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="39"/>
<source>Name</source>
<translation>Name</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="82"/>
+ <location filename="../../src/lobby.cpp" line="94"/>
<source>It doesn&apos;t look like your client is set up correctly.
Did you download all resources correctly from tiny.cc/getao, including the large &apos;base&apos; folder?</source>
<translation>Dein Client ist nicht korrekt eingerichtet.
Hast du ALLES von tiny.cc/getao heruntergeladen und entpackt, auch den großen &apos;base&apos; Ordner?</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="111"/>
+ <location filename="../../src/lobby.cpp" line="123"/>
<source>Version: %1</source>
<translation>Version: %1</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="155"/>
+ <location filename="../../src/lobby.cpp" line="129"/>
+ <source>Settings</source>
+ <translation>Einstellungen</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="132"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation>Erlaubt es verschiedene Aspekte des Clients zu ändern.</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="176"/>
<source>Loading</source>
<translation>Laden</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="159"/>
+ <location filename="../../src/lobby.cpp" line="180"/>
<source>Cancel</source>
<translation>Abbrechen</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="279"/>
+ <location filename="../../src/lobby.cpp" line="360"/>
+ <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;2.8 Major Release development:&lt;/b&gt;&lt;br&gt;Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;2.8 Quality Assurance:&lt;/b&gt;&lt;br&gt;WillDean, Captain N, Mr M, Riel, Seimmet, Fury McFlurry,CedricDewitt, Chewable Tablets, Fantos, Futugaze,Geck, Minx, Pandae, Sierra, CrazyJC, CaseyMayCazy,GreenBowers, Robotic Overlord, Veritas, Gin-Gi&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, the AO2 community, server hosts, game masters,case makers, content creators and players!</source>
+ <translation>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;Der Gerichtsdrama Simulator&lt;p&gt;&lt;b&gt;Quelltext:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Leitende Entwicklung:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Version 2.8 Entwicklung:&lt;/b&gt;&lt;br&gt;Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;2.8 Qualitätskontrolle:&lt;/b&gt;&lt;br&gt;WillDean, Captain N, Mr M, Riel, Seimmet, Fury McFlurry,CedricDewitt, Chewable Tablets, Fantos, Futugaze,Geck, Minx, Pandae, Sierra, CrazyJC, CaseyMayCazy,GreenBowers, Robotic Overlord, Veritas, Gin-Gi&lt;p&gt;&lt;b&gt;Danksagungen:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, die AO2 Community, Serverbetreiber, Gamemaster, Fallersteller, Inhaltersteller und Spieler!</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="380"/>
+ <source>About</source>
+ <translation>Über</translation>
+ </message>
+ <message>
<source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</source>
- <translation>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;Der Gerichtsdrama Simulator&lt;p&gt;&lt;b&gt;Quelltext:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Leitende Entwicklung:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Danksagungen:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</translation>
+ <translation type="vanished">&lt;h2&gt;Attorney Online %1&lt;/h2&gt;Der Gerichtsdrama Simulator&lt;p&gt;&lt;b&gt;Quelltext:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Leitende Entwicklung:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Danksagungen:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</translation>
</message>
<message>
<source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy</source>
<translation type="vanished">&lt;h2&gt;Attorney Online %1&lt;/h2&gt;Der Gerichtsdrama Simulator&lt;p&gt;&lt;b&gt;Quelltext:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Leitende Entwicklung:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Danksagungen:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="395"/>
+ <location filename="../../src/lobby.cpp" line="521"/>
<source>Online: %1/%2</source>
<translation>Online: %1/%2</translation>
</message>
@@ -1091,13 +1592,28 @@ Noevain
Cronnicossy</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="121"/>
- <location filename="../../src/lobby.cpp" line="327"/>
+ <location filename="../../src/lobby.cpp" line="142"/>
+ <location filename="../../src/lobby.cpp" line="418"/>
<source>Offline</source>
<translation>Offline</translation>
</message>
</context>
<context>
+ <name>chatlogpiece</name>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="5"/>
+ <location filename="../../src/chatlogpiece.cpp" line="6"/>
+ <location filename="../../src/chatlogpiece.cpp" line="7"/>
+ <source>UNKNOWN</source>
+ <translation>UNBEKANNT</translation>
+ </message>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="55"/>
+ <source> has played a song: </source>
+ <translation> hat ein Lied gespielt: </translation>
+ </message>
+</context>
+<context>
<name>debug_functions</name>
<message>
<location filename="../../src/debug_functions.cpp" line="10"/>
@@ -1110,7 +1626,7 @@ Cronnicossy</translation>
<translation>Fehler</translation>
</message>
<message>
- <location filename="../../src/debug_functions.cpp" line="26"/>
+ <location filename="../../src/debug_functions.cpp" line="25"/>
<source>Notice</source>
<translation>Hinweis</translation>
</message>
diff --git a/resource/translations/ao_en.ts b/resource/translations/ao_en.ts
index 9719319f..ee104b9f 100644
--- a/resource/translations/ao_en.ts
+++ b/resource/translations/ao_en.ts
@@ -9,73 +9,67 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="151"/>
+ <location filename="../../src/aoapplication.cpp" line="152"/>
<source>Error connecting to master server. Will try again in %1 seconds.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="156"/>
+ <location filename="../../src/aoapplication.cpp" line="157"/>
<source>There was an error connecting to the master server.
We deploy multiple master servers to mitigate any possible downtime, but the client appears to have exhausted all possible methods of finding and connecting to one.
Please check your Internet connection and firewall, and please try again.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="108"/>
+ <location filename="../../src/packet_distribution.cpp" line="94"/>
<source>Outdated version! Your version: %1
Please go to aceattorneyonline.com to update.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="115"/>
- <source>You have been exiled from AO.
-Have a nice day.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/packet_distribution.cpp" line="258"/>
+ <location filename="../../src/packet_distribution.cpp" line="235"/>
<source>Attorney Online 2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="282"/>
+ <location filename="../../src/packet_distribution.cpp" line="263"/>
<source>Loading</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="373"/>
+ <location filename="../../src/packet_distribution.cpp" line="363"/>
<source>Loading evidence:
%1/%2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="408"/>
- <location filename="../../src/packet_distribution.cpp" line="506"/>
+ <location filename="../../src/packet_distribution.cpp" line="398"/>
+ <location filename="../../src/packet_distribution.cpp" line="492"/>
<source>Loading music:
%1/%2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="326"/>
- <location filename="../../src/packet_distribution.cpp" line="457"/>
+ <location filename="../../src/packet_distribution.cpp" line="316"/>
+ <location filename="../../src/packet_distribution.cpp" line="465"/>
<source>Loading chars:
%1/%2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="635"/>
+ <location filename="../../src/packet_distribution.cpp" line="674"/>
<source>You have been kicked from the server.
Reason: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="643"/>
+ <location filename="../../src/packet_distribution.cpp" line="682"/>
<source>You have been banned from the server.
Reason: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="651"/>
+ <location filename="../../src/packet_distribution.cpp" line="690"/>
<source>You are banned on this server.
Reason: %1</source>
<translation type="unfinished"></translation>
@@ -118,371 +112,371 @@ Reason: %1</source>
<source>Stenographer needed</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location filename="../../src/aocaseannouncerdialog.cpp" line="66"/>
- <source>Witness needed</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>AOOptionsDialog</name>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="11"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="12"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="48"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="46"/>
<source>Gameplay</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="61"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="62"/>
<source>Theme:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="63"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="64"/>
<source>Sets the theme used in-game. If the new theme changes the lobby&apos;s look as well, you&apos;ll need to reload the lobby for the changes to take effect, such as by joining a server and leaving it.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="109"/>
- <source>Gives the default value for the in-game &apos;Custom shownames&apos; checkbox, which in turn determines whether the client should display custom in-character names.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="95"/>
+ <source>Log goes downwards:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="305"/>
- <source>Sets the default volume for music.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="97"/>
+ <source>If ticked, new messages will appear at the bottom (like the OOC chatlog). The traditional (AO1) behaviour is equivalent to this being unticked.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="320"/>
- <source>Sets the default volume for SFX sounds, like interjections or other character sound effects.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="110"/>
+ <source>Log length:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="568"/>
- <source>IC Log</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="111"/>
+ <source>The amount of messages the IC chatlog will keep before deleting older messages. A value of 0 or below counts as &apos;infinite&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="581"/>
- <source>Colorful IC log:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="133"/>
+ <source>Default username:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="583"/>
- <source>Enables colored text in the log.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="135"/>
+ <source>Your OOC name will be automatically set to this value when you join a server.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="594"/>
- <source>Only inline coloring:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="148"/>
+ <source>Custom shownames:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="596"/>
- <source>Only inline coloring will be shown such as &lt;&gt;,|| etc.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="150"/>
+ <source>Gives the default value for the in-game &apos;Custom shownames&apos; tickbox, which in turn determines whether the client should display custom in-character names.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="606"/>
- <source>Mirror IC log:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="170"/>
+ <source>Backup MS:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="608"/>
- <source>IC log will mirror the IC box. Meaning that if somebody gets interrupted nobody will know what they wanted to say. Enable for a more realistic experience.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="172"/>
+ <source>If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="620"/>
- <source>Log goes downwards:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="185"/>
+ <source>Discord:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="622"/>
- <source>If ticked, new messages will appear at the bottom (like the OOC chatlog). The traditional (AO1) behaviour is equivalent to this being unticked.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="187"/>
+ <source>Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="634"/>
- <source>Log length:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="200"/>
+ <source>Language:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="635"/>
- <source>The amount of messages the IC chatlog will keep before deleting older messages. A value of 0 or below counts as &apos;infinite&apos;.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="202"/>
+ <source>Sets the language if you don&apos;t want to use your system language.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="93"/>
- <source>Default username:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="324"/>
+ <source>Callwords</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="95"/>
- <source>Your OOC name will be automatically set to this value when you join a server.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="351"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!&lt;br&gt;Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="107"/>
- <source>Custom shownames:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="361"/>
+ <source>Audio</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="127"/>
- <source>Backup MS:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="375"/>
+ <source>Audio device:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="129"/>
- <source>If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="376"/>
+ <source>Sets the audio device for all sounds.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="141"/>
- <source>Discord:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="419"/>
+ <source>Music:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="143"/>
- <source>Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="434"/>
+ <source>SFX:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="155"/>
- <source>Allow Shake/Flash:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="450"/>
+ <source>Blips:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="157"/>
- <source>Allows screenshaking and flashing. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="452"/>
+ <source>Sets the volume of the blips, the talking sound effects.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="168"/>
- <source>Language:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="474"/>
+ <source>Blip rate:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="170"/>
- <source>Sets the language if you don&apos;t want to use your system language.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="476"/>
+ <source>Sets the delay between playing the blip sounds.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="193"/>
- <source>Slower text speed:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="491"/>
+ <source>Blank blips:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="194"/>
- <source>Set the text speed to be the same as the AA games.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="493"/>
+ <source>If true, the game will play a blip sound even when a space is &apos;being said&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="201"/>
- <source>Blip delay on punctuations:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="505"/>
+ <source>Enable Looping SFX:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="202"/>
- <source>Punctuation delay modifier. Enable it for the blips to slow down on punctuations.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="506"/>
+ <source>If true, the game will allow looping sound effects to play on preanimations.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="212"/>
- <source>Callwords</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="518"/>
+ <source>Kill Music On Objection:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="239"/>
- <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!&lt;br&gt;Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.&lt;/body&gt;&lt;/html&gt;</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="208"/>
+ <source> - Keep current setting</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="249"/>
- <source>Audio</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="220"/>
+ <source>Allow Screenshake:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="262"/>
- <source>Audio device:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="222"/>
+ <source>Allows screenshaking. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="263"/>
- <source>Sets the audio device for all sounds.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="234"/>
+ <source>Allow Effects:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="304"/>
- <source>Music:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="236"/>
+ <source>Allows screen effects. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="318"/>
- <source>SFX:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="248"/>
+ <source>Network Frame Effects:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="333"/>
- <source>Blips:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="249"/>
+ <source>Send screen-shaking, flashes and sounds as defined in the char.ini over the network. Only works for servers that support this functionality.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="335"/>
- <source>Sets the volume of the blips, the talking sound effects.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="262"/>
+ <source>Colors in IC Log:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="354"/>
- <source>Blip rate:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="264"/>
+ <source>Use the markup colors in the server IC chatlog.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="356"/>
- <source>Sets the delay between playing the blip sounds.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="275"/>
+ <source>Sticky Sounds:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="367"/>
- <source>Blank blips:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="277"/>
+ <source>Turn this on to prevent the sound dropdown from clearing the sound after playing it.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="369"/>
- <source>If true, the game will play a blip sound even when a space is &apos;being said&apos;.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="289"/>
+ <source>Sticky Effects:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="380"/>
- <source>Enable Looping SFX:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="291"/>
+ <source>Turn this on to prevent the effects dropdown from clearing the effect after playing it.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="381"/>
- <source>If true, the game will allow looping sound effects to play on preanimations.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="304"/>
+ <source>Sticky Preanims:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="392"/>
- <source>Kill Music On Objection:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="306"/>
+ <source>Turn this on to prevent preanimation checkbox from clearing after playing the emote.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="420"/>
+ <source>Sets the music&apos;s default volume.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="394"/>
- <source>If true, the game will stop music when someone objects, like in the actual games.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="436"/>
+ <source>Sets the SFX&apos;s default volume. Interjections and actual sound effects count as &apos;SFX&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="408"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="484"/>
+ <source>Play a blip sound &quot;once per every X symbols&quot;, where X is the blip rate.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="520"/>
+ <source>If true, AO2 will stop the music for you when you or someone else does &apos;Objection!&apos;.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="532"/>
<source>Casing</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="424"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="549"/>
<source>This server supports case alerts.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="427"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="552"/>
<source>This server does not support case alerts.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="428"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="553"/>
<source>Pretty self-explanatory.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="436"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="562"/>
<source>Casing:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="438"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="564"/>
<source>If checked, you will get alerts about case announcements.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="451"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="580"/>
<source>Defense:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="452"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="581"/>
<source>If checked, you will get alerts about case announcements if a defense spot is open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="465"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="595"/>
<source>Prosecution:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="467"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="597"/>
<source>If checked, you will get alerts about case announcements if a prosecutor spot is open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="480"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="611"/>
<source>Judge:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="481"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="612"/>
<source>If checked, you will get alerts about case announcements if the judge spot is open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="494"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="626"/>
<source>Juror:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="495"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="627"/>
<source>If checked, you will get alerts about case announcements if a juror spot is open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="508"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="641"/>
<source>Stenographer:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="510"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="643"/>
<source>If checked, you will get alerts about case announcements if a stenographer spot is open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="523"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="657"/>
<source>CM:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="525"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="659"/>
<source>If checked, you will appear amongst the potential CMs on the server.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="536"/>
- <source>Witness:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="538"/>
- <source>If checked, you will appear amongst the potential witnesses on the server.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="551"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="673"/>
<source>Hosting cases:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="553"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="675"/>
<source>If you&apos;re a CM, enter what cases you are willing to host.</source>
<translation type="unfinished"></translation>
</message>
@@ -490,381 +484,736 @@ Reason: %1</source>
<context>
<name>Courtroom</name>
<message>
- <location filename="../../src/charselect.cpp" line="69"/>
+ <location filename="../../src/charselect.cpp" line="21"/>
<source>Password</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="75"/>
+ <location filename="../../src/charselect.cpp" line="27"/>
<source>Spectator</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="78"/>
- <location filename="../../src/courtroom.cpp" line="179"/>
+ <location filename="../../src/charselect.cpp" line="30"/>
+ <location filename="../../src/courtroom.cpp" line="175"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="83"/>
+ <location filename="../../src/charselect.cpp" line="35"/>
<source>Passworded</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="87"/>
+ <location filename="../../src/charselect.cpp" line="39"/>
<source>Taken</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="182"/>
- <source>Could not find %1</source>
+ <location filename="../../src/charselect.cpp" line="231"/>
+ <source>Generating chars:
+%1/%2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="149"/>
+ <location filename="../../src/courtroom.cpp" line="148"/>
<source>Showname</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="153"/>
+ <location filename="../../src/courtroom.cpp" line="152"/>
<source>Message</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="160"/>
- <source>OOC Message</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/courtroom.cpp" line="164"/>
+ <location filename="../../src/courtroom.cpp" line="167"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="224"/>
+ <location filename="../../src/courtroom.cpp" line="217"/>
<source>Pre</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="227"/>
+ <location filename="../../src/courtroom.cpp" line="220"/>
<source>Flip</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="238"/>
- <location filename="../../src/courtroom.cpp" line="720"/>
+ <location filename="../../src/courtroom.cpp" line="233"/>
+ <location filename="../../src/courtroom.cpp" line="815"/>
<source>Casing</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="243"/>
+ <location filename="../../src/courtroom.cpp" line="238"/>
<source>Shownames</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="246"/>
+ <location filename="../../src/courtroom.cpp" line="241"/>
<source>No Interrupt</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="264"/>
- <source>White</source>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
+ <source>You were granted the Disable Modcalls button.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="265"/>
- <source>Green</source>
+ <location filename="../../src/courtroom.cpp" line="3315"/>
+ <source>You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini.
+Cases you can load: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="266"/>
- <source>Red</source>
+ <location filename="../../src/courtroom.cpp" line="3343"/>
+ <source>Case made by %1.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="267"/>
- <source>Orange</source>
+ <location filename="../../src/courtroom.cpp" line="3353"/>
+ <source>Navigate to %1 for the CM doc.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="268"/>
- <source>Blue</source>
+ <location filename="../../src/courtroom.cpp" line="3377"/>
+ <source>Your case &quot;%1&quot; was loaded!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="269"/>
- <source>Yellow</source>
+ <location filename="../../src/courtroom.cpp" line="767"/>
+ <location filename="../../src/courtroom.cpp" line="3475"/>
+ <source>Server</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="1265"/>
- <location filename="../../src/courtroom.cpp" line="3492"/>
- <source>You were granted the Disable Modcalls button.</source>
+ <location filename="../../src/courtroom.cpp" line="913"/>
+ <source>Back to Lobby</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3500"/>
- <source>This does nothing, but there you go.</source>
+ <location filename="../../src/courtroom.cpp" line="274"/>
+ <source>% offset</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3641"/>
- <source>You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini.
-Cases you can load: %1</source>
+ <location filename="../../src/courtroom.cpp" line="742"/>
+ <source>Music</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3669"/>
- <source>Case made by %1.</source>
+ <location filename="../../src/courtroom.cpp" line="744"/>
+ <source>Sfx</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3679"/>
- <source>Navigate to %1 for the CM doc.</source>
+ <location filename="../../src/courtroom.cpp" line="746"/>
+ <source>Blips</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3702"/>
- <source>Your case &quot;%1&quot; was loaded!</source>
+ <location filename="../../src/courtroom.cpp" line="791"/>
+ <source>Change character</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3739"/>
- <source>Too many arguments to save a case! You only need a filename without extension and the courtroom status.</source>
+ <location filename="../../src/courtroom.cpp" line="797"/>
+ <source>Reload theme</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="664"/>
- <location filename="../../src/courtroom.cpp" line="3816"/>
- <source>Server</source>
+ <location filename="../../src/courtroom.cpp" line="803"/>
+ <source>Call mod</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="818"/>
- <source>Back to Lobby</source>
+ <location filename="../../src/courtroom.cpp" line="809"/>
+ <source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="270"/>
- <source>Rainbow</source>
+ <location filename="../../src/courtroom.cpp" line="822"/>
+ <source>A/M</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="232"/>
- <source>Disable Modcalls</source>
+ <location filename="../../src/courtroom.cpp" line="827"/>
+ <source>Preanim</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="271"/>
- <source>Pink</source>
+ <location filename="../../src/courtroom.cpp" line="2984"/>
+ <source>You have been banned.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="272"/>
- <source>Cyan</source>
+ <location filename="../../src/courtroom.cpp" line="3182"/>
+ <source>You opened the settings menu.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="295"/>
- <source>% offset</source>
+ <location filename="../../src/courtroom.cpp" line="143"/>
+ <source>None</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="646"/>
- <source>Music</source>
+ <location filename="../../src/courtroom.cpp" line="224"/>
+ <source>Guard</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="648"/>
- <source>Sfx</source>
+ <location filename="../../src/courtroom.cpp" line="228"/>
+ <source>Additive</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="650"/>
- <source>Blips</source>
+ <location filename="../../src/courtroom.cpp" line="277"/>
+ <source>To front</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="278"/>
+ <source>To behind</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="591"/>
+ <source>Select a character you wish to pair with.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="596"/>
+ <source>Change the percentage offset of your character&apos;s position from the center of the screen.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="653"/>
- <source>Log limit</source>
+ <location filename="../../src/courtroom.cpp" line="602"/>
+ <source>Change the order of appearance for your character.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="607"/>
+ <source>Display the list of characters to pair with.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="665"/>
+ <source>Oops, you&apos;re muted!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="679"/>
+ <source>Set your character&apos;s emote to play on your next message.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../src/courtroom.cpp" line="683"/>
- <source>Change character</source>
+ <source>Set your character&apos;s supplementary background.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="693"/>
- <source>Reload theme</source>
+ <location filename="../../src/courtroom.cpp" line="689"/>
+ <source>Set an &apos;iniswap&apos;, or an alternative character folder to refer to from your current character.
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/iniswaps.ini</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="702"/>
- <source>Call mod</source>
+ <location filename="../../src/courtroom.cpp" line="698"/>
+ <location filename="../../src/courtroom.cpp" line="715"/>
+ <source>Remove the currently selected iniswap from the list and return to the original character folder.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="711"/>
- <source>Settings</source>
+ <location filename="../../src/courtroom.cpp" line="706"/>
+ <source>Set a sound effect to play on your next &apos;Preanim&apos;. Leaving it on Default will use the emote-defined sound (if any).
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/soundlist.ini</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="729"/>
- <source>A/M</source>
+ <location filename="../../src/courtroom.cpp" line="722"/>
+ <source>Choose an effect to play on your next spoken message.
+The effects are defined in your theme/effects/effects.ini. Your character can define custom effects by
+char.ini [Options] category, effects = &apos;miscname&apos; where it referes to misc/&lt;miscname&gt;/effects.ini to read the effects.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="737"/>
- <source>Preanim</source>
+ <location filename="../../src/courtroom.cpp" line="749"/>
+ <source>Hold It!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3310"/>
- <source>You have been banned.</source>
+ <location filename="../../src/courtroom.cpp" line="750"/>
+ <location filename="../../src/courtroom.cpp" line="756"/>
+ <location filename="../../src/courtroom.cpp" line="762"/>
+ <source>When this is turned on, your next in-character message will be a shout!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3506"/>
- <source>You opened the settings menu.</source>
+ <location filename="../../src/courtroom.cpp" line="755"/>
+ <source>Objection!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="761"/>
+ <source>Take That!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="769"/>
+ <source>Toggle between server chat and global AO2 chat.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3519"/>
- <source>You will now pair up with </source>
+ <location filename="../../src/courtroom.cpp" line="773"/>
+ <location filename="../../src/courtroom.cpp" line="777"/>
+ <location filename="../../src/courtroom.cpp" line="783"/>
+ <location filename="../../src/courtroom.cpp" line="787"/>
+ <source>This will display the animation in the viewport as soon as it is pressed.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3521"/>
- <source> if they also choose your character in return.</source>
+ <location filename="../../src/courtroom.cpp" line="781"/>
+ <source>Guilty!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3527"/>
+ <location filename="../../src/courtroom.cpp" line="794"/>
+ <source>Bring up the Character Select Screen and change your character.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="800"/>
+ <source>Refresh the theme and update all of the ui elements to match.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="806"/>
+ <source>Request the attention of the current server&apos;s moderator.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="812"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="818"/>
+ <source>An interface to help you announce a case (you have to be a CM first to be able to announce cases)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="824"/>
+ <source>Switch between Areas and Music lists</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="829"/>
+ <source>Play a single-shot animation as defined by the emote when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="833"/>
+ <source>If preanim is checked, display the input text immediately as the animation plays concurrently.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="837"/>
+ <source>Mirror your character&apos;s emotes when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="841"/>
+ <source>Add text to your last spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="845"/>
+ <source>Do not listen to mod calls when checked, preventing them from playing sounds or focusing attention on the window.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="849"/>
+ <source>Lets you receive case alerts when enabled.
+(You can set your preferences in the Settings!)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="854"/>
+ <source>Display customized shownames for all users when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="857"/>
+ <source>Custom Shout!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="860"/>
+ <source>This will display the custom character-defined animation in the viewport as soon as it is pressed.
+To make one, your character&apos;s folder must contain custom.[webp/apng/gif/png] and custom.[wav/ogg/opus] sound effect</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="868"/>
+ <source>Play realization sound and animation in the viewport on the next spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="874"/>
+ <source>Shake the screen on next spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="880"/>
+ <source>Display the list of character folders you wish to mute.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="884"/>
+ <location filename="../../src/courtroom.cpp" line="892"/>
+ <source>Increase the health bar.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="888"/>
+ <location filename="../../src/courtroom.cpp" line="896"/>
+ <source>Decrease the health bar.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="900"/>
+ <source>Change the text color of the spoken message.
+You can also select a part of your currently typed message and use the dropdown to change its color!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="914"/>
+ <source>Return back to the server list.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="927"/>
+ <source>Become a spectator. You won&apos;t be able to interact with the in-character screen.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
+ <location filename="../../src/courtroom.cpp" line="3343"/>
+ <source>CLIENT</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3061"/>
+ <location filename="../../src/courtroom.cpp" line="4479"/>
+ <location filename="../../src/courtroom.cpp" line="4486"/>
+ <source>has played a song</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3195"/>
+ <source>You will now pair up with %1 if they also choose your character in return.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3201"/>
<source>You are no longer paired with anyone.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3532"/>
+ <location filename="../../src/courtroom.cpp" line="3206"/>
<source>Are you sure you typed that well? The char ID could not be recognised.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3547"/>
+ <location filename="../../src/courtroom.cpp" line="3221"/>
<source>You have set your offset to </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3554"/>
+ <location filename="../../src/courtroom.cpp" line="3228"/>
<source>Your offset must be between -100% and 100%!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3559"/>
+ <location filename="../../src/courtroom.cpp" line="3233"/>
<source>That offset does not look like one.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3565"/>
+ <location filename="../../src/courtroom.cpp" line="3239"/>
<source>You switched your music and area list.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3572"/>
+ <location filename="../../src/courtroom.cpp" line="3246"/>
<source>You have forcefully enabled features that the server may not support. You may not be able to talk IC, or worse, because of this.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3586"/>
+ <location filename="../../src/courtroom.cpp" line="3260"/>
<source>Your pre-animations interrupt again.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3589"/>
+ <location filename="../../src/courtroom.cpp" line="3263"/>
<source>Your pre-animations will not interrupt text.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3600"/>
+ <location filename="../../src/courtroom.cpp" line="3274"/>
<source>Couldn&apos;t open chatlog.txt to write into.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3613"/>
+ <location filename="../../src/courtroom.cpp" line="3287"/>
<source>The IC chatlog has been saved.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3626"/>
+ <location filename="../../src/courtroom.cpp" line="3300"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely the case file you&apos;re looking for can&apos;t be found in there.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3653"/>
+ <location filename="../../src/courtroom.cpp" line="3327"/>
<source>Too many arguments to load a case! You only need one filename, without extension.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3714"/>
+ <location filename="../../src/courtroom.cpp" line="3367"/>
+ <location filename="../../src/courtroom.cpp" line="3369"/>
+ <location filename="../../src/evidence.cpp" line="761"/>
+ <location filename="../../src/evidence.cpp" line="763"/>
+ <source>UNKNOWN</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3389"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely that you somehow deleted it.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3729"/>
+ <location filename="../../src/courtroom.cpp" line="3404"/>
<source>You need to give a filename to save (extension not needed) and the courtroom status!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3766"/>
+ <location filename="../../src/courtroom.cpp" line="3414"/>
+ <source>Too many arguments to save a case! You only need a filename without extension and the courtroom status!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3441"/>
<source>Succesfully saved, edit doc and cmdoc link on the ini!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3806"/>
+ <location filename="../../src/courtroom.cpp" line="3468"/>
<source>Master</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4309"/>
+ <location filename="../../src/courtroom.cpp" line="3968"/>
+ <source>Expand All Categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3970"/>
+ <source>Collapse All Categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3974"/>
+ <source>Fade Out Previous</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3980"/>
+ <source>Fade In</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3986"/>
+ <source>Synchronize</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4256"/>
+ <source>Default</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4417"/>
<source>Reason:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4310"/>
+ <location filename="../../src/courtroom.cpp" line="4418"/>
<source>Call Moderator</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4426"/>
+ <location filename="../../src/courtroom.cpp" line="4430"/>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
+ <location filename="../../src/courtroom.cpp" line="4426"/>
<source>You must provide a reason.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4430"/>
<source>The message is too long.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="25"/>
- <source>Choose...</source>
+ <location filename="../../src/evidence.cpp" line="17"/>
+ <source>Present this piece of evidence to everyone on your next spoken message</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="24"/>
+ <source>Save evidence to an .ini file.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="26"/>
+ <source>Load evidence from an .ini file.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="31"/>
+ <source>Destroy this piece of evidence</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="34"/>
+ <source>Choose..</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="37"/>
+ <source>Close the evidence display/editing overlay.
+You will be prompted if there&apos;s any unsaved changes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="40"/>
+ <source>Save any changes made to this piece of evidence and send them to server.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="48"/>
+ <source>Double-click to edit. Press [X] to update your changes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="104"/>
+ <source>Bring up the Evidence screen.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="147"/>
+ <source>Switch evidence to private inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="151"/>
+ <source>Switch evidence to global inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="158"/>
+ <location filename="../../src/evidence.cpp" line="617"/>
+ <source>Transfer evidence to private inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="163"/>
+ <location filename="../../src/evidence.cpp" line="627"/>
+ <source>Transfer evidence to global inventory.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="208"/>
+ <location filename="../../src/evidence.cpp" line="263"/>
+ <source>The piece of evidence you&apos;ve been editing has changed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="264"/>
+ <source>Do you wish to keep your changes?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="265"/>
+ <source>Name: %1
+Image: %2
+Description:
+%3</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="387"/>
<source>Images (*.png)</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="280"/>
+ <location filename="../../src/evidence.cpp" line="456"/>
+ <location filename="../../src/evidence.cpp" line="460"/>
+ <location filename="../../src/evidence.cpp" line="463"/>
+ <source>Double-click to edit...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="478"/>
<source>Add new evidence...</source>
<translation type="unfinished"></translation>
</message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="556"/>
+ <source>Evidence has been modified.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="557"/>
+ <source>Do you want to save your changes?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="619"/>
+ <source>Current evidence is global. Click to switch to private.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="629"/>
+ <source>Current evidence is private. Click to switch to global.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="659"/>
+ <source>&quot;%1&quot; has been transferred.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="721"/>
+ <source>Save Inventory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="721"/>
+ <location filename="../../src/evidence.cpp" line="747"/>
+ <source>Ini Files (*.ini)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="747"/>
+ <source>Open Inventory</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>Lobby</name>
@@ -874,49 +1223,84 @@ Cases you can load: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="29"/>
+ <location filename="../../src/lobby.cpp" line="31"/>
+ <source>Search</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="39"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="82"/>
+ <location filename="../../src/lobby.cpp" line="94"/>
<source>It doesn&apos;t look like your client is set up correctly.
Did you download all resources correctly from tiny.cc/getao, including the large &apos;base&apos; folder?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="111"/>
+ <location filename="../../src/lobby.cpp" line="123"/>
<source>Version: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="155"/>
+ <location filename="../../src/lobby.cpp" line="129"/>
+ <source>Settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="132"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="176"/>
<source>Loading</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="159"/>
+ <location filename="../../src/lobby.cpp" line="180"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="279"/>
- <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</source>
+ <location filename="../../src/lobby.cpp" line="360"/>
+ <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;2.8 Major Release development:&lt;/b&gt;&lt;br&gt;Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;2.8 Quality Assurance:&lt;/b&gt;&lt;br&gt;WillDean, Captain N, Mr M, Riel, Seimmet, Fury McFlurry,CedricDewitt, Chewable Tablets, Fantos, Futugaze,Geck, Minx, Pandae, Sierra, CrazyJC, CaseyMayCazy,GreenBowers, Robotic Overlord, Veritas, Gin-Gi&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, the AO2 community, server hosts, game masters,case makers, content creators and players!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="395"/>
+ <location filename="../../src/lobby.cpp" line="380"/>
+ <source>About</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="521"/>
<source>Online: %1/%2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="121"/>
- <location filename="../../src/lobby.cpp" line="327"/>
+ <location filename="../../src/lobby.cpp" line="142"/>
+ <location filename="../../src/lobby.cpp" line="418"/>
<source>Offline</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
+ <name>chatlogpiece</name>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="5"/>
+ <location filename="../../src/chatlogpiece.cpp" line="6"/>
+ <location filename="../../src/chatlogpiece.cpp" line="7"/>
+ <source>UNKNOWN</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="55"/>
+ <source> has played a song: </source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>debug_functions</name>
<message>
<location filename="../../src/debug_functions.cpp" line="10"/>
@@ -929,7 +1313,7 @@ Did you download all resources correctly from tiny.cc/getao, including the large
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/debug_functions.cpp" line="26"/>
+ <location filename="../../src/debug_functions.cpp" line="25"/>
<source>Notice</source>
<translation type="unfinished"></translation>
</message>
diff --git a/resource/translations/ao_es.qm b/resource/translations/ao_es.qm
index 42ca3a00..7b238e79 100644
--- a/resource/translations/ao_es.qm
+++ b/resource/translations/ao_es.qm
Binary files differ
diff --git a/resource/translations/ao_es.ts b/resource/translations/ao_es.ts
index 2cad7ce1..8e43d8ec 100644
--- a/resource/translations/ao_es.ts
+++ b/resource/translations/ao_es.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="es">
+<TS version="2.0" language="es">
<context>
<name>AOApplication</name>
<message>
@@ -9,12 +9,12 @@
<translation>Desconectado del servidor.</translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="151"/>
+ <location filename="../../src/aoapplication.cpp" line="152"/>
<source>Error connecting to master server. Will try again in %1 seconds.</source>
<translation>Error al conectarse a la lista de servidores. Se intentará nuevamente en %1 segundos.</translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="156"/>
+ <location filename="../../src/aoapplication.cpp" line="157"/>
<source>There was an error connecting to the master server.
We deploy multiple master servers to mitigate any possible downtime, but the client appears to have exhausted all possible methods of finding and connecting to one.
Please check your Internet connection and firewall, and please try again.</source>
@@ -22,68 +22,67 @@ Please check your Internet connection and firewall, and please try again.</sourc
<translation>Hubo un error al obtener la lista de servidores. Verifique su conexión a Internet y firewall, y vuelva a intentarlo.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="108"/>
+ <location filename="../../src/packet_distribution.cpp" line="94"/>
<source>Outdated version! Your version: %1
Please go to aceattorneyonline.com to update.</source>
<translation>¡Versión desactualizada! Su versión: %1
Ingrese a aceattorneyonline.com para actualizar.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="115"/>
<source>You have been exiled from AO.
Have a nice day.</source>
- <translation>Has sido exiliado de AO.
+ <translation type="obsolete">Has sido exiliado de AO.
Que tengas un buen día.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="258"/>
+ <location filename="../../src/packet_distribution.cpp" line="253"/>
<source>Attorney Online 2</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="282"/>
+ <location filename="../../src/packet_distribution.cpp" line="281"/>
<source>Loading</source>
<translation>Cargando</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="373"/>
+ <location filename="../../src/packet_distribution.cpp" line="381"/>
<source>Loading evidence:
%1/%2</source>
<translation>Cargando evidencia:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="408"/>
- <location filename="../../src/packet_distribution.cpp" line="506"/>
+ <location filename="../../src/packet_distribution.cpp" line="416"/>
+ <location filename="../../src/packet_distribution.cpp" line="510"/>
<source>Loading music:
%1/%2</source>
<translation>Cargando música:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="326"/>
- <location filename="../../src/packet_distribution.cpp" line="457"/>
+ <location filename="../../src/packet_distribution.cpp" line="334"/>
+ <location filename="../../src/packet_distribution.cpp" line="483"/>
<source>Loading chars:
%1/%2</source>
<translation>Cargando personajes:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="635"/>
+ <location filename="../../src/packet_distribution.cpp" line="692"/>
<source>You have been kicked from the server.
Reason: %1</source>
<translation>Has sido expulsado del servidor.
Razón: %1</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="643"/>
+ <location filename="../../src/packet_distribution.cpp" line="700"/>
<source>You have been banned from the server.
Reason: %1</source>
<translation>Has sido bloqueado de este servidor.
Razón: %1</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="651"/>
+ <location filename="../../src/packet_distribution.cpp" line="708"/>
<source>You are banned on this server.
Reason: %1</source>
<translation>Has sido bloqueado en este servidor.
@@ -140,392 +139,466 @@ Razón: </translation>
<translation>Se necesita taquígrafo</translation>
</message>
<message>
- <location filename="../../src/aocaseannouncerdialog.cpp" line="66"/>
<source>Witness needed</source>
- <translation>Se necesita testigo</translation>
+ <translation type="obsolete">Se necesita testigo</translation>
</message>
</context>
<context>
<name>AOOptionsDialog</name>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="11"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="12"/>
<source>Settings</source>
<translation>Ajustes</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="48"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="46"/>
<source>Gameplay</source>
<translation>Jugabilidad</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="61"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="62"/>
<source>Theme:</source>
<translation>Tema visual:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="63"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="64"/>
<source>Sets the theme used in-game. If the new theme changes the lobby&apos;s look as well, you&apos;ll need to reload the lobby for the changes to take effect, such as by joining a server and leaving it.</source>
<translation>Establece el tema visual utilizado en el juego. Si el nuevo tema también cambia el aspecto del lobby, deberá volver a cargar el lobby para que los cambios surtan efecto, como unirse a un servidor y volver al lobby.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="620"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="95"/>
<source>Log goes downwards:</source>
<translation>Invertir historial IC:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="622"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="97"/>
<source>If ticked, new messages will appear at the bottom (like the OOC chatlog). The traditional (AO1) behaviour is equivalent to this being unticked.</source>
<translation>Si está marcado, los nuevos mensajes aparecerán en la parte inferior (como el chat OOC).</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="634"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="110"/>
<source>Log length:</source>
<translation>Limite del historial:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="635"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="111"/>
<source>The amount of messages the IC chatlog will keep before deleting older messages. A value of 0 or below counts as &apos;infinite&apos;.</source>
<translation>La cantidad de mensajes que mantendrá el historial del chat IC antes de eliminar mensajes más antiguos. 0 significa &apos;infinito&apos;.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="93"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="133"/>
<source>Default username:</source>
<translation>Usuario predeterminado:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="95"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="135"/>
<source>Your OOC name will be automatically set to this value when you join a server.</source>
<translation>Su nombre OOC se establecerá automáticamente a este cuando se una a un servidor.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="107"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="148"/>
<source>Custom shownames:</source>
<translation>Mostrar nombres:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="150"/>
<source>Gives the default value for the in-game &apos;Custom shownames&apos; tickbox, which in turn determines whether the client should display custom in-character names.</source>
- <translation type="obsolete">Activa la casilla &apos;Mostrar nombres&apos; de forma predeterminada en el juego, que a su vez determina si el cliente debe mostrar nombres personalizados en los personajes.</translation>
+ <translation>Activa la casilla &apos;Mostrar nombres&apos; de forma predeterminada en el juego, que a su vez determina si el cliente debe mostrar nombres personalizados en los personajes.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="127"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="170"/>
<source>Backup MS:</source>
<translation>Master SV de respaldo:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="129"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="172"/>
<source>If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address.</source>
<translation>Si la lista de servidores predeterminada falla, el juego probará la dirección proporcionada aquí.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="141"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="185"/>
<source>Discord:</source>
<translation>Discord:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="143"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="187"/>
<source>Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for.</source>
<translation>Permite a otros en Discord ver en qué servidor estás, qué personaje juegas y cuánto tiempo has estado jugando.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="155"/>
<source>Allow Shake/Flash:</source>
- <translation>Permitir Shake/Flash:</translation>
+ <translation type="obsolete">Permitir Shake/Flash:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="157"/>
<source>Allows screenshaking and flashing. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
- <translation>Permite el movimiento de la pantalla y el parpadeo. Desactive esto si tiene inquietudes o problemas con la fotosensibilidad y/o convulsiones.</translation>
+ <translation type="obsolete">Permite el movimiento de la pantalla y el parpadeo. Desactive esto si tiene inquietudes o problemas con la fotosensibilidad y/o convulsiones.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="168"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="200"/>
<source>Language:</source>
<translation>Idioma:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="170"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="202"/>
<source>Sets the language if you don&apos;t want to use your system language.</source>
<translation>Establece el idioma si no desea utilizar el idioma de su sistema.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="202"/>
<source>Punctuation delay modifier. Enable it for the blips to slow down on punctuations.</source>
- <translation>Habilítelo para agregar una pequeña pausa en los signos de puntuación.</translation>
+ <translation type="obsolete">Habilítelo para agregar una pequeña pausa en los signos de puntuación.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="212"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="340"/>
<source>Callwords</source>
<translation>Palabras clave</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="239"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="367"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!&lt;br&gt;Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Ingrese tantas palabras de llamada como desee.&lt;br&gt;Esto no distingue entre mayúsculas y minúsculas. ¡Asegúrese de dejar cada palabra en su propia línea!&lt;br&gt;No deje una línea con un espacio al final; recibirá una alerta cada vez que alguien use un espacio en sus mensajes.&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="249"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="377"/>
<source>Audio</source>
<translation>Audio</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="262"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="391"/>
<source>Audio device:</source>
<translation>Dispositivo:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="263"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="392"/>
<source>Sets the audio device for all sounds.</source>
<translation>Establece el dispositivo de audio.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="304"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="435"/>
<source>Music:</source>
<translation>Música:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="436"/>
<source>Sets the music&apos;s default volume.</source>
- <translation type="obsolete">Establece el volumen predeterminado de la música.</translation>
+ <translation>Establece el volumen predeterminado de la música.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="318"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="450"/>
<source>SFX:</source>
<translation>SFX:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="452"/>
<source>Sets the SFX&apos;s default volume. Interjections and actual sound effects count as &apos;SFX&apos;.</source>
- <translation type="obsolete">Establece el volumen predeterminado de SFX. Las interjecciones y los efectos de sonido reales cuentan como &apos;SFX&apos;.</translation>
+ <translation>Establece el volumen predeterminado de SFX. Las interjecciones y los efectos de sonido reales cuentan como &apos;SFX&apos;.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="109"/>
<source>Gives the default value for the in-game &apos;Custom shownames&apos; checkbox, which in turn determines whether the client should display custom in-character names.</source>
- <translation>Activa la casilla &apos;Mostrar nombres&apos; de forma predeterminada en el juego, que a su vez determina si el cliente debe mostrar nombres personalizados en los personajes.</translation>
+ <translation type="obsolete">Activa la casilla &apos;Mostrar nombres&apos; de forma predeterminada en el juego, que a su vez determina si el cliente debe mostrar nombres personalizados en los personajes.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="193"/>
<source>Slower text speed:</source>
- <translation>Texto más lento:</translation>
+ <translation type="obsolete">Texto más lento:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="194"/>
<source>Set the text speed to be the same as the AA games.</source>
- <translation>La velocidad del texto será la misma que en los juegos de AA.</translation>
+ <translation type="obsolete">La velocidad del texto será la misma que en los juegos de AA.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="201"/>
<source>Blip delay on punctuations:</source>
- <translation>Retraso en puntuación:</translation>
+ <translation type="obsolete">Retraso en puntuación:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="305"/>
<source>Sets the default volume for music.</source>
- <translation>Establece el volumen predeterminado de la música.</translation>
+ <translation type="obsolete">Establece el volumen predeterminado de la música.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="320"/>
<source>Sets the default volume for SFX sounds, like interjections or other character sound effects.</source>
- <translation>Establece el volumen predeterminado para sonidos SFX, como las interjecciones y otros efectos de sonido de personajes.</translation>
+ <translation type="obsolete">Establece el volumen predeterminado para sonidos SFX, como las interjecciones y otros efectos de sonido de personajes.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="333"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="466"/>
<source>Blips:</source>
<translation>Blips:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="335"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="468"/>
<source>Sets the volume of the blips, the talking sound effects.</source>
<translation>Establece el volumen de los blips, el sonido al hablar.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="354"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="490"/>
<source>Blip rate:</source>
<translation>Tasa de blips:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="356"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="492"/>
<source>Sets the delay between playing the blip sounds.</source>
<translation>Establece el retraso entre la reproducción de los sonidos blip.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="367"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="507"/>
<source>Blank blips:</source>
<translation>Blips en blanco:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="369"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="509"/>
<source>If true, the game will play a blip sound even when a space is &apos;being said&apos;.</source>
<translation>Si está marcada, el juego reproducirá un sonido blip incluso cuando se &apos;dice&apos; un espacio.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="380"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="521"/>
<source>Enable Looping SFX:</source>
<translation>Habilitar repetición de SFX:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="381"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="522"/>
<source>If true, the game will allow looping sound effects to play on preanimations.</source>
<translation>Si está habilitado, el juego permitirá que se reproduzcan efectos de sonido en bucle en preanimaciones.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="392"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="534"/>
<source>Kill Music On Objection:</source>
<translation>Parar la música al objetar:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="394"/>
<source>If true, the game will stop music when someone objects, like in the actual games.</source>
- <translation>Si está habilitado, el juego detendrá la música cuando alguien haga una objeción, como en los juegos.</translation>
+ <translation type="obsolete">Si está habilitado, el juego detendrá la música cuando alguien haga una objeción, como en los juegos.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="208"/>
+ <source> - Keep current setting</source>
+ <translation> - Mantener la configuración actual</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="222"/>
+ <source>Allow Screenshake:</source>
+ <translation>Permitir screenshake:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="224"/>
+ <source>Allows screenshaking. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
+ <translation>Permite el movimiento de la pantalla (ADVERTENCIA: esto podría inducir convulsiones debido a imágenes parpadeantes).</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="236"/>
+ <source>Allow Effects:</source>
+ <translation>Permitir efectos:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="238"/>
+ <source>Allows screen effects. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
+ <translation>Permite efectos de pantalla (ADVERTENCIA: esto podría inducir convulsiones debido a imágenes parpadeantes).</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="250"/>
+ <source>Network Frame Effects:</source>
+ <translation>Enviar efectos al servidor:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="251"/>
+ <source>Send screen-shaking, flashes and sounds as defined in the char.ini over the network. Only works for servers that support this functionality.</source>
+ <translation>Envíe temblores de pantalla, destellos y sonidos como se define en char.ini a través de la red. Solo funciona para servidores que admiten esta funcionalidad.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="408"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="264"/>
+ <source>Colors in IC Log:</source>
+ <translation>Colores en el registro IC:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="266"/>
+ <source>Use the markup colors in the server IC chatlog.</source>
+ <translation>Permite colores en el chat IC del servidor.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="277"/>
+ <source>Sticky Sounds:</source>
+ <translation>Mantener sonidos:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="279"/>
+ <source>Turn this on to prevent the sound dropdown from clearing the sound after playing it.</source>
+ <translation>Actívelo para evitar que el menú desplegable de sonido borre el sonido después de reproducirlo.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="291"/>
+ <source>Sticky Effects:</source>
+ <translation>Mantener efectos:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="293"/>
+ <source>Turn this on to prevent the effects dropdown from clearing the effect after playing it.</source>
+ <translation>Actívelo para evitar que el menú desplegable de efectos elimine el efecto después de reproducirlo.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="306"/>
+ <source>Sticky Preanims:</source>
+ <translation>Mantener preanims:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="308"/>
+ <source>Turn this on to prevent preanimation checkbox from clearing after playing the emote.</source>
+ <translation>Actívelo para evitar que la casilla preanimation se desactive después de reproducir el emote.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="320"/>
+ <source>Custom Chatboxes:</source>
+ <translation>Chatboxes personalizados:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="322"/>
+ <source>Turn this on to allow characters to define their own custom chat box designs.</source>
+ <translation>Actívelo para permitir que los personajes definan sus propios diseños de cuadros de chat personalizados.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="500"/>
+ <source>Play a blip sound &quot;once per every X symbols&quot;, where X is the blip rate.</source>
+ <translation>Reproduce un sonido de blip &quot;una vez por cada X símbolos&quot;, donde X es la tasa de blip.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="536"/>
+ <source>If true, AO2 will stop the music for you when you or someone else does &apos;Objection!&apos;.</source>
+ <translation>Si es activado, AO2 detendrá la música por ti cuando tú u otra persona hagan un &apos;¡Protesto!&apos;.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="548"/>
<source>Casing</source>
<translation>Caso</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="424"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="565"/>
<source>This server supports case alerts.</source>
<translation>Este servidor admite alertas de casos.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="427"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="568"/>
<source>This server does not support case alerts.</source>
<translation>Este servidor no admite alertas de casos.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="428"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="569"/>
<source>Pretty self-explanatory.</source>
<translation>Bastante autoexplicativo.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="436"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="578"/>
<source>Casing:</source>
<translation>Caso:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="438"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="580"/>
<source>If checked, you will get alerts about case announcements.</source>
<translation>Si está marcado, recibirá anuncios de casos.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="451"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="596"/>
<source>Defense:</source>
<translation>Abogado:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="452"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="597"/>
<source>If checked, you will get alerts about case announcements if a defense spot is open.</source>
<translation>Si está marcado, recibirá alertas sobre anuncios de casos si hay un lugar de abogado libre.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="465"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="611"/>
<source>Prosecution:</source>
<translation>Fiscal:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="467"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="613"/>
<source>If checked, you will get alerts about case announcements if a prosecutor spot is open.</source>
<translation>Si está marcada, recibirá alertas sobre anuncios de casos si hay un puesto de fiscal libre.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="480"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="627"/>
<source>Judge:</source>
<translation>Juez:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="481"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="628"/>
<source>If checked, you will get alerts about case announcements if the judge spot is open.</source>
<translation>Si está marcado, recibirá alertas sobre anuncios de casos si el puesto de juez está libre.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="494"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="642"/>
<source>Juror:</source>
<translation>Jurado:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="495"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="643"/>
<source>If checked, you will get alerts about case announcements if a juror spot is open.</source>
<translation>Si está marcado, recibirá alertas sobre anuncios de casos si hay un puesto de jurado libre.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="508"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="657"/>
<source>Stenographer:</source>
<translation>Taquígrafo:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="510"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="659"/>
<source>If checked, you will get alerts about case announcements if a stenographer spot is open.</source>
<translation>Si está marcado, recibirá alertas sobre anuncios de casos si hay un lugar de taquígrafo libre.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="523"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="673"/>
<source>CM:</source>
<translation>CM:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="525"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="675"/>
<source>If checked, you will appear amongst the potential CMs on the server.</source>
<translation>Si está marcado, aparecerá entre los posibles CM en el servidor.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="536"/>
<source>Witness:</source>
- <translation>Testigo:</translation>
+ <translation type="obsolete">Testigo:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="538"/>
<source>If checked, you will appear amongst the potential witnesses on the server.</source>
- <translation>Si está marcado, aparecerá entre los posibles testigos en el servidor.</translation>
+ <translation type="obsolete">Si está marcado, aparecerá entre los posibles testigos en el servidor.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="551"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="689"/>
<source>Hosting cases:</source>
<translation>Casos:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="553"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="691"/>
<source>If you&apos;re a CM, enter what cases you are willing to host.</source>
<translation>Si eres un CM, ingresa qué casos estás dispuesto a organizar.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="568"/>
- <source>IC Log</source>
- <translation></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="596"/>
<source>Only inline coloring will be shown such as &lt;&gt;,|| etc.</source>
- <translation>Solo se mostrará el color en línea, como &lt;&gt;, ||, etc.</translation>
+ <translation type="obsolete">Solo se mostrará el color en línea, como &lt;&gt;, ||, etc.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="608"/>
<source>IC log will mirror the IC box. Meaning that if somebody gets interrupted nobody will know what they wanted to say. Enable for a more realistic experience.</source>
- <translation>El registro de IC reflejará el chat In-Character. Lo que significa que si alguien es interrumpido, nadie sabrá lo que se iba a decir. Habilitar para una experiencia más realista.</translation>
+ <translation type="obsolete">El registro de IC reflejará el chat In-Character. Lo que significa que si alguien es interrumpido, nadie sabrá lo que se iba a decir. Habilitar para una experiencia más realista.</translation>
</message>
<message>
<source>IC log will mirror the IC box. Meaning that if somebody gets interrupted nobody will know what they wanted to say. Enable for a more realistic experience</source>
<translation type="obsolete">El registro de IC reflejará el chat In-Character. Lo que significa que si alguien es interrumpido, nadie sabrá lo que se iba a decir. Habilitar para una experiencia más realista.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="581"/>
<source>Colorful IC log:</source>
- <translation>Log IC colorido:</translation>
+ <translation type="obsolete">Log IC colorido:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="583"/>
<source>Enables colored text in the log.</source>
- <translation>Habilita texto con color en el log.</translation>
+ <translation type="obsolete">Habilita texto con color en el log.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="594"/>
<source>Only inline coloring:</source>
- <translation>Solo coloración en línea:</translation>
+ <translation type="obsolete">Solo coloración en línea:</translation>
</message>
<message>
<source>Only inline coloring will be shown such as &lt;&gt;,|| etc</source>
<translation type="obsolete">Solo se mostrará el color en línea, como &lt;&gt;, ||, etc.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="606"/>
<source>Mirror IC log:</source>
- <translation>IC log refleja interrupciones:</translation>
+ <translation type="obsolete">IC log refleja interrupciones:</translation>
</message>
<message>
<source>IC log will mirror the IC box. Meaning that if somebody gets interupted nobody will know what they wanted to say. Enable for a more realistic expierence</source>
@@ -535,41 +608,41 @@ Razón: </translation>
<context>
<name>Courtroom</name>
<message>
- <location filename="../../src/charselect.cpp" line="69"/>
+ <location filename="../../src/charselect.cpp" line="21"/>
<source>Password</source>
<translation>Contraseña</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="75"/>
+ <location filename="../../src/charselect.cpp" line="27"/>
<source>Spectator</source>
<translation>Espectador</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="78"/>
- <location filename="../../src/courtroom.cpp" line="179"/>
+ <location filename="../../src/charselect.cpp" line="30"/>
+ <location filename="../../src/courtroom.cpp" line="175"/>
<source>Search</source>
<translation>Buscar</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="83"/>
+ <location filename="../../src/charselect.cpp" line="35"/>
<source>Passworded</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="87"/>
+ <location filename="../../src/charselect.cpp" line="39"/>
<source>Taken</source>
<translation>En uso</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="182"/>
<source>Could not find %1</source>
- <translation>No se pudo encontrar %1</translation>
+ <translation type="obsolete">No se pudo encontrar %1</translation>
</message>
<message>
+ <location filename="../../src/charselect.cpp" line="232"/>
<source>Generating chars:
%1/%2</source>
- <translation type="obsolete">Generando personajes:
+ <translation>Generando personajes:
%1/%2</translation>
</message>
<message>
@@ -579,170 +652,156 @@ Razón: </translation>
</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="149"/>
+ <location filename="../../src/courtroom.cpp" line="148"/>
<source>Showname</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="153"/>
+ <location filename="../../src/courtroom.cpp" line="152"/>
<source>Message</source>
<translation>Mensaje</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="164"/>
+ <location filename="../../src/courtroom.cpp" line="167"/>
<source>Name</source>
<translation>Nombre</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="224"/>
+ <location filename="../../src/courtroom.cpp" line="217"/>
<source>Pre</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="227"/>
+ <location filename="../../src/courtroom.cpp" line="220"/>
<source>Flip</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="224"/>
<source>Guard</source>
- <translation type="obsolete">Guardia</translation>
+ <translation>Guardia</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="238"/>
- <location filename="../../src/courtroom.cpp" line="720"/>
+ <location filename="../../src/courtroom.cpp" line="233"/>
+ <location filename="../../src/courtroom.cpp" line="815"/>
<source>Casing</source>
<translatorcomment>This could be translated as &apos;caso&apos; and it wouldn&apos;t get cut, but there are so many other buttons that can&apos;t be translated on the courtroom window that might as well leave this also untranslated so it&apos;s at least consistent.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="243"/>
+ <location filename="../../src/courtroom.cpp" line="238"/>
<source>Shownames</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="246"/>
+ <location filename="../../src/courtroom.cpp" line="241"/>
<source>No Interrupt</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="264"/>
<source>White</source>
- <translation>Blanco</translation>
+ <translation type="obsolete">Blanco</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="265"/>
<source>Green</source>
- <translation>Verde</translation>
+ <translation type="obsolete">Verde</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="266"/>
<source>Red</source>
- <translation>Rojo</translation>
+ <translation type="obsolete">Rojo</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="267"/>
<source>Orange</source>
- <translation>Naranja</translation>
+ <translation type="obsolete">Naranja</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="268"/>
<source>Blue</source>
- <translation>Azul</translation>
+ <translation type="obsolete">Azul</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="269"/>
<source>Yellow</source>
- <translation>Amarillo</translation>
+ <translation type="obsolete">Amarillo</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="270"/>
<source>Rainbow</source>
- <translation>Arcoíris</translation>
+ <translation type="obsolete">Arcoíris</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="271"/>
<source>Pink</source>
- <translation>Rosado</translation>
+ <translation type="obsolete">Rosado</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="272"/>
<source>Cyan</source>
- <translation>Cian</translation>
+ <translation type="obsolete">Cian</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="295"/>
+ <location filename="../../src/courtroom.cpp" line="274"/>
<source>% offset</source>
<translation>% desplazamiento</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="646"/>
+ <location filename="../../src/courtroom.cpp" line="742"/>
<source>Music</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="648"/>
+ <location filename="../../src/courtroom.cpp" line="744"/>
<source>Sfx</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="650"/>
+ <location filename="../../src/courtroom.cpp" line="746"/>
<source>Blips</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="653"/>
- <source>Log limit</source>
- <translation></translation>
- </message>
- <message>
- <location filename="../../src/courtroom.cpp" line="683"/>
+ <location filename="../../src/courtroom.cpp" line="791"/>
<source>Change character</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="693"/>
+ <location filename="../../src/courtroom.cpp" line="797"/>
<source>Reload theme</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="702"/>
+ <location filename="../../src/courtroom.cpp" line="803"/>
<source>Call mod</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="711"/>
+ <location filename="../../src/courtroom.cpp" line="809"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="729"/>
+ <location filename="../../src/courtroom.cpp" line="822"/>
<source>A/M</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="737"/>
+ <location filename="../../src/courtroom.cpp" line="827"/>
<source>Preanim</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="818"/>
+ <location filename="../../src/courtroom.cpp" line="913"/>
<source>Back to Lobby</source>
<translatorcomment>&apos;Volver al lobby&apos; got cut, changed to just Lobby</translatorcomment>
<translation>Lobby</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="1265"/>
- <location filename="../../src/courtroom.cpp" line="3492"/>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
<source>You were granted the Disable Modcalls button.</source>
<translation>Se le concedió el botón para deshabilitar llamadas a moderadores.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3310"/>
+ <location filename="../../src/courtroom.cpp" line="3011"/>
<source>You have been banned.</source>
<translation>Has sido vetado.</translation>
</message>
@@ -751,115 +810,416 @@ Razón: </translation>
<translation type="obsolete">Te ha sido otorgado el botón Guardia.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3500"/>
<source>This does nothing, but there you go.</source>
- <translation>Esto no hace nada, pero ahí lo tienes.</translation>
+ <translation type="obsolete">Esto no hace nada, pero ahí lo tienes.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3506"/>
+ <location filename="../../src/courtroom.cpp" line="3211"/>
<source>You opened the settings menu.</source>
<translation>Abriste el menú de configuración.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3519"/>
<source>You will now pair up with </source>
- <translation>Ahora te emparejarás con </translation>
+ <translation type="obsolete">Ahora te emparejarás con </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3521"/>
<source> if they also choose your character in return.</source>
- <translation> si ellos también eligen a tu personaje a cambio.</translation>
+ <translation type="obsolete"> si ellos también eligen a tu personaje a cambio.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="143"/>
+ <source>None</source>
+ <translation>Nada</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="228"/>
+ <source>Additive</source>
+ <translation>Aditivo</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="277"/>
+ <source>To front</source>
+ <translation>Al frente</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="278"/>
+ <source>To behind</source>
+ <translation>Al fondo</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="591"/>
+ <source>Select a character you wish to pair with.</source>
+ <translation>Seleccione un personaje con el que desee emparejarse.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="596"/>
+ <source>Change the percentage offset of your character&apos;s position from the center of the screen.</source>
+ <translation>Cambia el desplazamiento porcentual de la posición de tu personaje desde el centro de la pantalla.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="602"/>
+ <source>Change the order of appearance for your character.</source>
+ <translation>Cambia el orden de aparición de tu personaje.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="607"/>
+ <source>Display the list of characters to pair with.</source>
+ <translation>Muestra la lista de personajes para emparejar.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="665"/>
+ <source>Oops, you&apos;re muted!</source>
+ <translation>¡Ups, estas silenciado!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="679"/>
+ <source>Set your character&apos;s emote to play on your next message.</source>
+ <translation>Configura el emote de tu personaje para usar en tu próximo mensaje.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="683"/>
+ <source>Set your character&apos;s supplementary background.</source>
+ <translation>Establece el fondo suplementario de tu personaje.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="689"/>
+ <source>Set an &apos;iniswap&apos;, or an alternative character folder to refer to from your current character.
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/iniswaps.ini</source>
+ <translation>Establece un &apos;iniswap&apos;, o una carpeta de caracteres alternativa para consultar desde su personaje actual.
+Edite escribiendo y presionando Enter, [X] para eliminar. Esto es guardado en base/characters/&lt;charname&gt;/iniswaps.ini</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="698"/>
+ <location filename="../../src/courtroom.cpp" line="715"/>
+ <source>Remove the currently selected iniswap from the list and return to the original character folder.</source>
+ <translation>Elimina el iniswap seleccionado actualmente de la lista y regresa a la carpeta de caracteres original.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="706"/>
+ <source>Set a sound effect to play on your next &apos;Preanim&apos;. Leaving it on Default will use the emote-defined sound (if any).
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/soundlist.ini</source>
+ <translation>Establece un efecto de sonido para jugar en su próximo &apos;Preanim&apos;. Dejarlo en Predeterminado usará el sonido definido por emoticones (si hay).
+Edite escribiendo y presionando Enter, [X] para eliminar. Esto es guardado en base/characters/&lt;charname&gt;/iniswaps.ini</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="722"/>
+ <source>Choose an effect to play on your next spoken message.
+The effects are defined in your theme/effects/effects.ini. Your character can define custom effects by
+char.ini [Options] category, effects = &apos;miscname&apos; where it referes to misc/&lt;miscname&gt;/effects.ini to read the effects.</source>
+ <translation>Elije un efecto para reproducir en su próximo mensaje hablado.
+Los efectos se definen en theme/effects/effects.ini. Tu personaje puede definir efectos personalizados por
+char.ini [Opciones] categoría, effects = &apos;miscname&apos; donde se refiere a misc/&lt;miscname&gt;/effects.ini para leer los efectos.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="749"/>
+ <source>Hold It!</source>
+ <translation>¡Un Momento!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="750"/>
+ <location filename="../../src/courtroom.cpp" line="756"/>
+ <location filename="../../src/courtroom.cpp" line="762"/>
+ <source>When this is turned on, your next in-character message will be a shout!</source>
+ <translatorcomment>Why the exclamation?</translatorcomment>
+ <translation>Cuando esto es activado, tu próximo mensaje del personaje será un grito.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="755"/>
+ <source>Objection!</source>
+ <translation>¡Protesto!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="761"/>
+ <source>Take That!</source>
+ <translation>¡Toma Eso!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="769"/>
+ <source>Toggle between server chat and global AO2 chat.</source>
+ <translation>Alternar entre el chat del servidor y el chat global.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="773"/>
+ <location filename="../../src/courtroom.cpp" line="777"/>
+ <location filename="../../src/courtroom.cpp" line="783"/>
+ <location filename="../../src/courtroom.cpp" line="787"/>
+ <source>This will display the animation in the viewport as soon as it is pressed.</source>
+ <translation>Esto mostrará la animación en el viewport tan pronto como se presione.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="781"/>
+ <source>Guilty!</source>
+ <translation>¡Culpable!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="794"/>
+ <source>Bring up the Character Select Screen and change your character.</source>
+ <translation>Abre la pantalla de selección de personaje y cambia tu personaje.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="800"/>
+ <source>Refresh the theme and update all of the ui elements to match.</source>
+ <translation>Actualiza el tema y todos los elementos de la interfaz de usuario para que coincidan.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="806"/>
+ <source>Request the attention of the current server&apos;s moderator.</source>
+ <translation>Solicite la atención del moderador actual del servidor.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="812"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation>Le permite cambiar varios aspectos del cliente.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="818"/>
+ <source>An interface to help you announce a case (you have to be a CM first to be able to announce cases)</source>
+ <translation>Una interfaz para ayudarlo a anunciar un caso (debe ser un CM para poder anunciar casos)</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3527"/>
+ <location filename="../../src/courtroom.cpp" line="824"/>
+ <source>Switch between Areas and Music lists</source>
+ <translation>Cambiar entre áreas y listas de música</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="829"/>
+ <source>Play a single-shot animation as defined by the emote when checked.</source>
+ <translation>Reproduzca una animación de un solo disparo según lo definido por el emote cuando esté marcado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="833"/>
+ <source>If preanim is checked, display the input text immediately as the animation plays concurrently.</source>
+ <translation>Si se marca preanim, muestre el texto de entrada inmediatamente mientras la animación se reproduce simultáneamente.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="837"/>
+ <source>Mirror your character&apos;s emotes when checked.</source>
+ <translation>Refleja los gestos de tu personaje cuando esté marcado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="841"/>
+ <source>Add text to your last spoken message when checked.</source>
+ <translation>Agregar texto a su último mensaje hablado cuando esté marcado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="845"/>
+ <source>Do not listen to mod calls when checked, preventing them from playing sounds or focusing attention on the window.</source>
+ <translation>No escucha llamadas de moderación cuando esté marcado, evitando que reproduzcan sonidos o centrando la atención en la ventana.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="849"/>
+ <source>Lets you receive case alerts when enabled.
+(You can set your preferences in the Settings!)</source>
+ <translation>Le permite recibir alertas de casos cuando está habilitado.
+(¡Puedes configurar tus preferencias en la Configuración!)</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="854"/>
+ <source>Display customized shownames for all users when checked.</source>
+ <translation>Mostrar nombres personalizados para todos los usuarios cuando esté marcado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="857"/>
+ <source>Custom Shout!</source>
+ <translation>¡Grito personalizado!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="860"/>
+ <source>This will display the custom character-defined animation in the viewport as soon as it is pressed.
+To make one, your character&apos;s folder must contain custom.[webp/apng/gif/png] and custom.[wav/ogg/opus] sound effect</source>
+ <translation>Esto mostrará la animación de personaje personalizada definida en el viewport tan pronto como se presione.
+Para hacer una, la carpeta de tu personaje debe contener efectos personalizados [webp/apng/gif/png]. Y efectos personalizados de sonido [wav/ogg/opus]</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="868"/>
+ <source>Play realization sound and animation in the viewport on the next spoken message when checked.</source>
+ <translation>Reproduzca sonido y animación de realización en la ventana gráfica en el siguiente mensaje hablado cuando esté marcado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="874"/>
+ <source>Shake the screen on next spoken message when checked.</source>
+ <translation>Agite la pantalla en el siguiente mensaje hablado cuando esté marcado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="880"/>
+ <source>Display the list of character folders you wish to mute.</source>
+ <translation>Muestra la lista de carpetas de caracteres que desea silenciar.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="884"/>
+ <location filename="../../src/courtroom.cpp" line="892"/>
+ <source>Increase the health bar.</source>
+ <translation>Aumenta la barra de salud.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="888"/>
+ <location filename="../../src/courtroom.cpp" line="896"/>
+ <source>Decrease the health bar.</source>
+ <translation>Disminuye la barra de salud.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="900"/>
+ <source>Change the text color of the spoken message.
+You can also select a part of your currently typed message and use the dropdown to change its color!</source>
+ <translation>Cambia el color del texto en el chat IC.
+¡También puede seleccionar una parte de su mensaje escrito actualmente y usar el menú desplegable para cambiar su color!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="914"/>
+ <source>Return back to the server list.</source>
+ <translation>Regresar a la lista de servidores.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="927"/>
+ <source>Become a spectator. You won&apos;t be able to interact with the in-character screen.</source>
+ <translation>Conviértete en espectador. No podrás interactuar con la pantalla del personaje.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
+ <location filename="../../src/courtroom.cpp" line="3372"/>
+ <source>CLIENT</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3090"/>
+ <location filename="../../src/courtroom.cpp" line="4508"/>
+ <location filename="../../src/courtroom.cpp" line="4515"/>
+ <source>has played a song</source>
+ <translation>ha reproducido la canción</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3224"/>
+ <source>You will now pair up with %1 if they also choose your character in return.</source>
+ <translation>Ahora se emparejará con %1 si también eligen a su personaje.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3230"/>
<source>You are no longer paired with anyone.</source>
<translation>Ya no estás emparejado con nadie.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3532"/>
+ <location filename="../../src/courtroom.cpp" line="3235"/>
<source>Are you sure you typed that well? The char ID could not be recognised.</source>
<translation>¿Estás seguro de que lo escribiste bien? El ID de personaje no pudo ser reconocido.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3547"/>
+ <location filename="../../src/courtroom.cpp" line="3250"/>
<source>You have set your offset to </source>
<translation>Ha configurado su desplazamiento en </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3554"/>
+ <location filename="../../src/courtroom.cpp" line="3257"/>
<source>Your offset must be between -100% and 100%!</source>
<translation>¡Su desplazamiento debe estar entre -100% y 100%!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3559"/>
+ <location filename="../../src/courtroom.cpp" line="3262"/>
<source>That offset does not look like one.</source>
<translation>Ese desplazamiento no se parece a uno.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3565"/>
+ <location filename="../../src/courtroom.cpp" line="3268"/>
<source>You switched your music and area list.</source>
<translation>Cambiaste tu lista de música y área.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3572"/>
+ <location filename="../../src/courtroom.cpp" line="3275"/>
<source>You have forcefully enabled features that the server may not support. You may not be able to talk IC, or worse, because of this.</source>
<translation>Ha habilitado forzosamente funciones que el servidor puede no admitir. Es posible que no pueda hablar IC, o peor, debido a esto.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3586"/>
+ <location filename="../../src/courtroom.cpp" line="3289"/>
<source>Your pre-animations interrupt again.</source>
<translation>Sus pre-animaciones interrumpen de nuevo.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3589"/>
+ <location filename="../../src/courtroom.cpp" line="3292"/>
<source>Your pre-animations will not interrupt text.</source>
<translation>Sus pre-animaciones no interrumpirán el texto.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3600"/>
+ <location filename="../../src/courtroom.cpp" line="3303"/>
<source>Couldn&apos;t open chatlog.txt to write into.</source>
<translation>No se pudo abrir chatlog.txt para escribir.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3613"/>
+ <location filename="../../src/courtroom.cpp" line="3316"/>
<source>The IC chatlog has been saved.</source>
<translation>El chat IC se ha guardado.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3626"/>
+ <location filename="../../src/courtroom.cpp" line="3329"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely the case file you&apos;re looking for can&apos;t be found in there.</source>
<translation>¡No tienes una carpeta `base/cases /`! Ha sido creada para ti. Pero debido a que no existia la carpeta, tampoco habían casos guardados ahí.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3641"/>
+ <location filename="../../src/courtroom.cpp" line="3344"/>
<source>You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini.
Cases you can load: %1</source>
<translation>¡Debe dar un nombre de archivo para cargar (no se necesita extensión)! Asegúrese de que esté en la carpeta `base/cases/` y de que tenga el formato correcto.
Casos que puede cargar: %1</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3669"/>
+ <location filename="../../src/courtroom.cpp" line="3372"/>
<source>Case made by %1.</source>
<translation>Caso hecho por %1.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3679"/>
+ <location filename="../../src/courtroom.cpp" line="3382"/>
<source>Navigate to %1 for the CM doc.</source>
<translation>Navegue a %1 para el documento del CM.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3702"/>
+ <location filename="../../src/courtroom.cpp" line="3396"/>
+ <location filename="../../src/courtroom.cpp" line="3398"/>
+ <location filename="../../src/evidence.cpp" line="762"/>
+ <location filename="../../src/evidence.cpp" line="764"/>
+ <source>UNKNOWN</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3406"/>
<source>Your case &quot;%1&quot; was loaded!</source>
<translation>Su caso &quot;%1&quot; fue cargado!</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="3997"/>
+ <source>Expand All Categories</source>
+ <translation>Expandir todas las categorías</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3999"/>
+ <source>Collapse All Categories</source>
+ <translation>Contraer todas las categorías</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4003"/>
+ <source>Fade Out Previous</source>
+ <translation>Desvanecerse Anterior</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4009"/>
+ <source>Fade In</source>
+ <translation>Fundirse</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4015"/>
+ <source>Synchronize</source>
+ <translation>Sincronizar</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4285"/>
+ <source>Default</source>
+ <translation>Predeterminado</translation>
+ </message>
+ <message>
<source>You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini.
Cases you can load: </source>
<translation type="obsolete">¡Debe dar un nombre de archivo para cargar (no se necesita extensión)! Asegúrese de que esté en la carpeta `base/cases/` y de que tenga el formato correcto.
Casos que puede cargar: </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3653"/>
+ <location filename="../../src/courtroom.cpp" line="3356"/>
<source>Too many arguments to load a case! You only need one filename, without extension.</source>
<translation>¡Demasiados argumentos para cargar un caso! Solo necesita un nombre de archivo, sin extensión.</translation>
</message>
@@ -884,92 +1244,223 @@ Casos que puede cargar: </translation>
<translation type="obsolete">&quot; fue cargado!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3714"/>
+ <location filename="../../src/courtroom.cpp" line="3418"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely that you somehow deleted it.</source>
<translation>¡No tienes una carpeta `base/cases /`! Fue creada para ti.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3729"/>
+ <location filename="../../src/courtroom.cpp" line="3433"/>
<source>You need to give a filename to save (extension not needed) and the courtroom status!</source>
<translation>¡Debe dar un nombre de archivo para guardar (no se necesita la extensión) y el estado de la sala del tribunal!</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="3443"/>
<source>Too many arguments to save a case! You only need a filename without extension and the courtroom status!</source>
<translatorcomment>why two exclamations, seems excesive.</translatorcomment>
- <translation type="obsolete">¡Demasiados argumentos para salvar un caso! Solo necesita un nombre de archivo sin extensión y el estado de la sala del tribunal.</translation>
+ <translation>¡Demasiados argumentos para salvar un caso! Solo necesita un nombre de archivo sin extensión y el estado de la sala del tribunal.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3766"/>
+ <location filename="../../src/courtroom.cpp" line="3470"/>
<source>Succesfully saved, edit doc and cmdoc link on the ini!</source>
<translation>¡Guardado con éxito, puede editar el doc y doc link en el archivo ini!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3806"/>
+ <location filename="../../src/courtroom.cpp" line="3497"/>
<source>Master</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="664"/>
- <location filename="../../src/courtroom.cpp" line="3816"/>
+ <location filename="../../src/courtroom.cpp" line="767"/>
+ <location filename="../../src/courtroom.cpp" line="3504"/>
<source>Server</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="160"/>
<source>OOC Message</source>
- <translation>Mensaje OOC</translation>
+ <translation type="obsolete">Mensaje OOC</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="232"/>
- <source>Disable Modcalls</source>
- <translation></translation>
- </message>
- <message>
- <location filename="../../src/courtroom.cpp" line="3739"/>
<source>Too many arguments to save a case! You only need a filename without extension and the courtroom status.</source>
- <translation>¡Demasiados argumentos para salvar un caso! Solo necesita un nombre de archivo sin extensión y el estado de la sala del tribunal.</translation>
+ <translation type="obsolete">¡Demasiados argumentos para salvar un caso! Solo necesita un nombre de archivo sin extensión y el estado de la sala del tribunal.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4309"/>
+ <location filename="../../src/courtroom.cpp" line="4446"/>
<source>Reason:</source>
<translation>Razón:</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4310"/>
+ <location filename="../../src/courtroom.cpp" line="4447"/>
<source>Call Moderator</source>
<translation>Llamar Moderador</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4455"/>
+ <location filename="../../src/courtroom.cpp" line="4459"/>
<source>Error</source>
<translation>Error</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
+ <location filename="../../src/courtroom.cpp" line="4455"/>
<source>You must provide a reason.</source>
<translation>Debes proporcionar una razón.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4459"/>
<source>The message is too long.</source>
<translation>El mensaje es muy largo.</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="25"/>
<source>Choose...</source>
- <translation>Elegir...</translation>
+ <translation type="obsolete">Elegir...</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="17"/>
+ <source>Present this piece of evidence to everyone on your next spoken message</source>
+ <translation>Presente esta evidencia a todos en su próximo mensaje hablado</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="24"/>
+ <source>Save evidence to an .ini file.</source>
+ <translation>Guardar evidencia en un archivo .ini.</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="208"/>
+ <location filename="../../src/evidence.cpp" line="26"/>
+ <source>Load evidence from an .ini file.</source>
+ <translation>Cargar evidencia de un archivo .ini.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="31"/>
+ <source>Destroy this piece of evidence</source>
+ <translation>Destruye esta evidencia</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="34"/>
+ <source>Choose..</source>
+ <translation>Elegir..</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="37"/>
+ <source>Close the evidence display/editing overlay.
+You will be prompted if there&apos;s any unsaved changes.</source>
+ <translation>Cierra la superposición para visualizar/editar evidencia.
+Se le preguntará si hay cambios no guardados.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="40"/>
+ <source>Save any changes made to this piece of evidence and send them to server.</source>
+ <translation>Guardar los cambios realizados en esta evidencia y enviarlos al servidor.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="48"/>
+ <source>Double-click to edit. Press [X] to update your changes.</source>
+ <translation>Doble click para editar. Presione [X] para actualizar sus cambios.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="104"/>
+ <source>Bring up the Evidence screen.</source>
+ <translation>Abre la ventana para evidencia.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="147"/>
+ <source>Switch evidence to private inventory.</source>
+ <translation>Cambiar la evidencia al inventario privado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="151"/>
+ <source>Switch evidence to global inventory.</source>
+ <translation>Cambiar la evidencia al inventario global.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="158"/>
+ <location filename="../../src/evidence.cpp" line="617"/>
+ <source>Transfer evidence to private inventory.</source>
+ <translation>Transferir evidencia al inventario privado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="163"/>
+ <location filename="../../src/evidence.cpp" line="627"/>
+ <source>Transfer evidence to global inventory.</source>
+ <translation>Transferir evidencia al inventario global.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="263"/>
+ <source>The piece of evidence you&apos;ve been editing has changed.</source>
+ <translation>La evidencia que has estado editando ha cambiado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="264"/>
+ <source>Do you wish to keep your changes?</source>
+ <translation>¿Desea conservar sus cambios?</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="265"/>
+ <source>Name: %1
+Image: %2
+Description:
+%3</source>
+ <translation>Nombre: %1
+Imagen: %2
+Descripción:
+%3</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="387"/>
<source>Images (*.png)</source>
<translation>Imágenes (* .png)</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="280"/>
+ <location filename="../../src/evidence.cpp" line="456"/>
+ <location filename="../../src/evidence.cpp" line="460"/>
+ <location filename="../../src/evidence.cpp" line="463"/>
+ <source>Double-click to edit...</source>
+ <translation>Doble click para editar...</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="478"/>
<source>Add new evidence...</source>
<translation>Añadir nueva evidencia...</translation>
</message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="556"/>
+ <source>Evidence has been modified.</source>
+ <translation>La evidencia ha sido modificada.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="557"/>
+ <source>Do you want to save your changes?</source>
+ <translation>¿Quieres guardar tus cambios?</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="619"/>
+ <source>Current evidence is global. Click to switch to private.</source>
+ <translation>La evidencia actual es global. Haga clic para cambiar a privado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="629"/>
+ <source>Current evidence is private. Click to switch to global.</source>
+ <translation>La evidencia actual es privada. Haga clic para cambiar a global.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="659"/>
+ <source>&quot;%1&quot; has been transferred.</source>
+ <translation>&quot;%1&quot; ha sido transferido.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="722"/>
+ <source>Save Inventory</source>
+ <translation>Guardar inventario</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="722"/>
+ <location filename="../../src/evidence.cpp" line="748"/>
+ <source>Ini Files (*.ini)</source>
+ <translation>Archivos Ini (*.ini)</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="748"/>
+ <source>Open Inventory</source>
+ <translation>Abrir el inventario</translation>
+ </message>
</context>
<context>
<name>Lobby</name>
@@ -979,54 +1470,97 @@ Casos que puede cargar: </translation>
<translation></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="29"/>
+ <location filename="../../src/lobby.cpp" line="31"/>
+ <source>Search</source>
+ <translation>Buscar</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="39"/>
<source>Name</source>
<translation>Nombre</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="82"/>
+ <location filename="../../src/lobby.cpp" line="94"/>
<source>It doesn&apos;t look like your client is set up correctly.
Did you download all resources correctly from tiny.cc/getao, including the large &apos;base&apos; folder?</source>
<translation>No parece que su cliente esté configurado correctamente.
¿Descargó todos los recursos correctamente desde tiny.cc/getao, incluida la gran carpeta &apos;base&apos;?</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="111"/>
+ <location filename="../../src/lobby.cpp" line="123"/>
<source>Version: %1</source>
<translation>Versión: %1</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="155"/>
+ <location filename="../../src/lobby.cpp" line="129"/>
+ <source>Settings</source>
+ <translation>Ajustes</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="132"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation>Le permite cambiar varios aspectos del cliente.</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="176"/>
<source>Loading</source>
<translation>Cargando</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="159"/>
+ <location filename="../../src/lobby.cpp" line="180"/>
<source>Cancel</source>
<translation>Cancelar</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="279"/>
+ <location filename="../../src/lobby.cpp" line="365"/>
+ <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;Client development:&lt;/b&gt;&lt;br&gt;Cents02, in1tiate, raidensnake, windrammer&lt;p&gt;&lt;b&gt;QA testing:&lt;/b&gt;&lt;br&gt;CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;CrazyJC (2.8 release director) and MaximumVolty (2.8 release promotion); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!&lt;p&gt;The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.&lt;p&gt;Running on Qt version %2 with the %3 audio engine.&lt;p&gt;Built on %4</source>
+ <translation>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;El simulador de drama legal&lt;p&gt;&lt;b&gt;Código fuente:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Desarrollo mayor:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;Desarrollo del cliente:&lt;/b&gt;&lt;br&gt;Cents02, in1tiate, raidensnake, windrammer&lt;p&gt;&lt;b&gt;Prueba de control de calidad:&lt;/b&gt;&lt;br&gt;CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso&lt;p&gt;&lt;b&gt;Agradecimiento especial:&lt;/b&gt;&lt;br&gt;CrazyJC y MaximumVolty (versión 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, creadores de contenido y toda la comunidad AO2.&lt;p&gt;El proyecto Attorney Online novela visual en red tiene copyright (c) 2016-2020 Attorney Online developers. Se aplican licencias de código abierto. Todos los demás activos son propiedad de sus respectivos dueños.&lt;p&gt;Usando Qt versión %2 con el motor de audio %3.&lt;p&gt;Compilado el %4</translation>
+ </message>
+ <message>
+ <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;Client development:&lt;/b&gt;&lt;br&gt;Cents02, in1tiate, raidensnake, windrammer&lt;p&gt;&lt;b&gt;QA testing:&lt;/b&gt;&lt;br&gt;CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;CrazyJC and MaximumVolty (2.8 release); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!&lt;p&gt;The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.&lt;p&gt;Running on Qt version %2 with the %3 audio engine.&lt;p&gt;Built on %4</source>
+ <translation type="obsolete">&lt;h2&gt;Attorney Online %1&lt;/h2&gt;El simulador de drama legal&lt;p&gt;&lt;b&gt;Código fuente:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Desarrollo mayor:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;Desarrollo del cliente:&lt;/b&gt;&lt;br&gt;Cents02, in1tiate, raidensnake, windrammer&lt;p&gt;&lt;b&gt;Prueba de control de calidad:&lt;/b&gt;&lt;br&gt;CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso&lt;p&gt;&lt;b&gt;Agradecimiento especial:&lt;/b&gt;&lt;br&gt;CrazyJC y MaximumVolty (versión 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, creadores de contenido y toda la comunidad AO2.&lt;p&gt;El proyecto Attorney Online novela visual en red tiene copyright (c) 2016-2020 Attorney Online developers. Se aplican licencias de código abierto. Todos los demás activos son propiedad de sus respectivos dueños.&lt;p&gt;Usando Qt versión %2 con el motor de audio %3.&lt;p&gt;Compilado el %4</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="398"/>
+ <source>About</source>
+ <translation>Acerca de</translation>
+ </message>
+ <message>
<source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</source>
- <translation>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</translation>
+ <translation type="obsolete">&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</translation>
</message>
<message>
<source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy</source>
<translation type="obsolete">&lt;h2&gt;Attorney Online %1&lt;/h2&gt;El simulador de drama legal&lt;p&gt;&lt;b&gt;Código fuente:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https: //github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Desarrollo mayor:&lt;/b&gt; &lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Agradecimiento especial:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (diseño de interfaz de usuario), Draxirch (diseño de interfaz de usuario), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="395"/>
+ <location filename="../../src/lobby.cpp" line="540"/>
<source>Online: %1/%2</source>
<translation>En línea: %1/%2</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="121"/>
- <location filename="../../src/lobby.cpp" line="327"/>
+ <location filename="../../src/lobby.cpp" line="142"/>
+ <location filename="../../src/lobby.cpp" line="436"/>
<source>Offline</source>
<translation>Fuera de línea</translation>
</message>
</context>
<context>
+ <name>chatlogpiece</name>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="5"/>
+ <location filename="../../src/chatlogpiece.cpp" line="6"/>
+ <location filename="../../src/chatlogpiece.cpp" line="7"/>
+ <source>UNKNOWN</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="55"/>
+ <source> has played a song: </source>
+ <translation> ha comenzado a reproducir la canción: </translation>
+ </message>
+</context>
+<context>
<name>debug_functions</name>
<message>
<location filename="../../src/debug_functions.cpp" line="10"/>
@@ -1039,9 +1573,9 @@ Did you download all resources correctly from tiny.cc/getao, including the large
<translation></translation>
</message>
<message>
- <location filename="../../src/debug_functions.cpp" line="26"/>
+ <location filename="../../src/debug_functions.cpp" line="25"/>
<source>Notice</source>
- <translatorcomment>In spanish it would be &quot;Aviso&quot;, but i believe it&apos;s going to be more useful for bug reports to not translate any debug string.</translatorcomment>
+ <translatorcomment>In spanish it would be &quot;Aviso&quot;, but I believe it&apos;s going to be more useful for bug reports to not translate any debug strings.</translatorcomment>
<translation></translation>
</message>
</context>
diff --git a/resource/translations/ao_jp.ts b/resource/translations/ao_jp.ts
index 029e84ad..a6594dec 100644
--- a/resource/translations/ao_jp.ts
+++ b/resource/translations/ao_jp.ts
@@ -9,73 +9,67 @@
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="151"/>
+ <location filename="../../src/aoapplication.cpp" line="152"/>
<source>Error connecting to master server. Will try again in %1 seconds.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="156"/>
+ <location filename="../../src/aoapplication.cpp" line="157"/>
<source>There was an error connecting to the master server.
We deploy multiple master servers to mitigate any possible downtime, but the client appears to have exhausted all possible methods of finding and connecting to one.
Please check your Internet connection and firewall, and please try again.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="108"/>
+ <location filename="../../src/packet_distribution.cpp" line="94"/>
<source>Outdated version! Your version: %1
Please go to aceattorneyonline.com to update.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="115"/>
- <source>You have been exiled from AO.
-Have a nice day.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/packet_distribution.cpp" line="258"/>
+ <location filename="../../src/packet_distribution.cpp" line="235"/>
<source>Attorney Online 2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="282"/>
+ <location filename="../../src/packet_distribution.cpp" line="263"/>
<source>Loading</source>
<translation>ロード中</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="373"/>
+ <location filename="../../src/packet_distribution.cpp" line="363"/>
<source>Loading evidence:
%1/%2</source>
<translation>証拠がロード中: %1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="408"/>
- <location filename="../../src/packet_distribution.cpp" line="506"/>
+ <location filename="../../src/packet_distribution.cpp" line="398"/>
+ <location filename="../../src/packet_distribution.cpp" line="492"/>
<source>Loading music:
%1/%2</source>
<translation>音楽がロード中: %1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="326"/>
- <location filename="../../src/packet_distribution.cpp" line="457"/>
+ <location filename="../../src/packet_distribution.cpp" line="316"/>
+ <location filename="../../src/packet_distribution.cpp" line="465"/>
<source>Loading chars:
%1/%2</source>
<translation>キャラがロード中: %1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="635"/>
+ <location filename="../../src/packet_distribution.cpp" line="674"/>
<source>You have been kicked from the server.
Reason: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="643"/>
+ <location filename="../../src/packet_distribution.cpp" line="682"/>
<source>You have been banned from the server.
Reason: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="651"/>
+ <location filename="../../src/packet_distribution.cpp" line="690"/>
<source>You are banned on this server.
Reason: %1</source>
<translation type="unfinished"></translation>
@@ -118,371 +112,371 @@ Reason: %1</source>
<source>Stenographer needed</source>
<translation type="unfinished"></translation>
</message>
- <message>
- <location filename="../../src/aocaseannouncerdialog.cpp" line="66"/>
- <source>Witness needed</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>AOOptionsDialog</name>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="11"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="12"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="48"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="46"/>
<source>Gameplay</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="61"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="62"/>
<source>Theme:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="63"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="64"/>
<source>Sets the theme used in-game. If the new theme changes the lobby&apos;s look as well, you&apos;ll need to reload the lobby for the changes to take effect, such as by joining a server and leaving it.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="109"/>
- <source>Gives the default value for the in-game &apos;Custom shownames&apos; checkbox, which in turn determines whether the client should display custom in-character names.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="95"/>
+ <source>Log goes downwards:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="305"/>
- <source>Sets the default volume for music.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="97"/>
+ <source>If ticked, new messages will appear at the bottom (like the OOC chatlog). The traditional (AO1) behaviour is equivalent to this being unticked.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="320"/>
- <source>Sets the default volume for SFX sounds, like interjections or other character sound effects.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="110"/>
+ <source>Log length:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="568"/>
- <source>IC Log</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="111"/>
+ <source>The amount of messages the IC chatlog will keep before deleting older messages. A value of 0 or below counts as &apos;infinite&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="581"/>
- <source>Colorful IC log:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="133"/>
+ <source>Default username:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="583"/>
- <source>Enables colored text in the log.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="135"/>
+ <source>Your OOC name will be automatically set to this value when you join a server.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="594"/>
- <source>Only inline coloring:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="148"/>
+ <source>Custom shownames:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="596"/>
- <source>Only inline coloring will be shown such as &lt;&gt;,|| etc.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="150"/>
+ <source>Gives the default value for the in-game &apos;Custom shownames&apos; tickbox, which in turn determines whether the client should display custom in-character names.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="606"/>
- <source>Mirror IC log:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="170"/>
+ <source>Backup MS:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="608"/>
- <source>IC log will mirror the IC box. Meaning that if somebody gets interrupted nobody will know what they wanted to say. Enable for a more realistic experience.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="172"/>
+ <source>If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="620"/>
- <source>Log goes downwards:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="185"/>
+ <source>Discord:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="622"/>
- <source>If ticked, new messages will appear at the bottom (like the OOC chatlog). The traditional (AO1) behaviour is equivalent to this being unticked.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="187"/>
+ <source>Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="634"/>
- <source>Log length:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="200"/>
+ <source>Language:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="635"/>
- <source>The amount of messages the IC chatlog will keep before deleting older messages. A value of 0 or below counts as &apos;infinite&apos;.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="202"/>
+ <source>Sets the language if you don&apos;t want to use your system language.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="93"/>
- <source>Default username:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="324"/>
+ <source>Callwords</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="95"/>
- <source>Your OOC name will be automatically set to this value when you join a server.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="351"/>
+ <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!&lt;br&gt;Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="107"/>
- <source>Custom shownames:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="361"/>
+ <source>Audio</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="127"/>
- <source>Backup MS:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="375"/>
+ <source>Audio device:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="129"/>
- <source>If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="376"/>
+ <source>Sets the audio device for all sounds.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="141"/>
- <source>Discord:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="419"/>
+ <source>Music:</source>
+ <translation>音楽:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="434"/>
+ <source>SFX:</source>
+ <translation>効果音:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="450"/>
+ <source>Blips:</source>
+ <translation>ブリップ:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="452"/>
+ <source>Sets the volume of the blips, the talking sound effects.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="143"/>
- <source>Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="474"/>
+ <source>Blip rate:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="155"/>
- <source>Allow Shake/Flash:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="476"/>
+ <source>Sets the delay between playing the blip sounds.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="157"/>
- <source>Allows screenshaking and flashing. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="491"/>
+ <source>Blank blips:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="168"/>
- <source>Language:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="493"/>
+ <source>If true, the game will play a blip sound even when a space is &apos;being said&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="170"/>
- <source>Sets the language if you don&apos;t want to use your system language.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="505"/>
+ <source>Enable Looping SFX:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="193"/>
- <source>Slower text speed:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="506"/>
+ <source>If true, the game will allow looping sound effects to play on preanimations.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="194"/>
- <source>Set the text speed to be the same as the AA games.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="518"/>
+ <source>Kill Music On Objection:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="201"/>
- <source>Blip delay on punctuations:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="208"/>
+ <source> - Keep current setting</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="202"/>
- <source>Punctuation delay modifier. Enable it for the blips to slow down on punctuations.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="220"/>
+ <source>Allow Screenshake:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="212"/>
- <source>Callwords</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="222"/>
+ <source>Allows screenshaking. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="239"/>
- <source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!&lt;br&gt;Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.&lt;/body&gt;&lt;/html&gt;</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="234"/>
+ <source>Allow Effects:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="249"/>
- <source>Audio</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="236"/>
+ <source>Allows screen effects. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="262"/>
- <source>Audio device:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="248"/>
+ <source>Network Frame Effects:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="263"/>
- <source>Sets the audio device for all sounds.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="249"/>
+ <source>Send screen-shaking, flashes and sounds as defined in the char.ini over the network. Only works for servers that support this functionality.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="304"/>
- <source>Music:</source>
- <translation>音楽:</translation>
+ <location filename="../../src/aooptionsdialog.cpp" line="262"/>
+ <source>Colors in IC Log:</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="318"/>
- <source>SFX:</source>
- <translation>効果音:</translation>
+ <location filename="../../src/aooptionsdialog.cpp" line="264"/>
+ <source>Use the markup colors in the server IC chatlog.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="333"/>
- <source>Blips:</source>
- <translation>ブリップ:</translation>
+ <location filename="../../src/aooptionsdialog.cpp" line="275"/>
+ <source>Sticky Sounds:</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="335"/>
- <source>Sets the volume of the blips, the talking sound effects.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="277"/>
+ <source>Turn this on to prevent the sound dropdown from clearing the sound after playing it.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="354"/>
- <source>Blip rate:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="289"/>
+ <source>Sticky Effects:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="356"/>
- <source>Sets the delay between playing the blip sounds.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="291"/>
+ <source>Turn this on to prevent the effects dropdown from clearing the effect after playing it.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="367"/>
- <source>Blank blips:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="304"/>
+ <source>Sticky Preanims:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="369"/>
- <source>If true, the game will play a blip sound even when a space is &apos;being said&apos;.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="306"/>
+ <source>Turn this on to prevent preanimation checkbox from clearing after playing the emote.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="380"/>
- <source>Enable Looping SFX:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="420"/>
+ <source>Sets the music&apos;s default volume.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="381"/>
- <source>If true, the game will allow looping sound effects to play on preanimations.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="436"/>
+ <source>Sets the SFX&apos;s default volume. Interjections and actual sound effects count as &apos;SFX&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="392"/>
- <source>Kill Music On Objection:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="484"/>
+ <source>Play a blip sound &quot;once per every X symbols&quot;, where X is the blip rate.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="394"/>
- <source>If true, the game will stop music when someone objects, like in the actual games.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="520"/>
+ <source>If true, AO2 will stop the music for you when you or someone else does &apos;Objection!&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="408"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="532"/>
<source>Casing</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="424"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="549"/>
<source>This server supports case alerts.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="427"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="552"/>
<source>This server does not support case alerts.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="428"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="553"/>
<source>Pretty self-explanatory.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="436"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="562"/>
<source>Casing:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="438"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="564"/>
<source>If checked, you will get alerts about case announcements.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="451"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="580"/>
<source>Defense:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="452"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="581"/>
<source>If checked, you will get alerts about case announcements if a defense spot is open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="465"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="595"/>
<source>Prosecution:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="467"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="597"/>
<source>If checked, you will get alerts about case announcements if a prosecutor spot is open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="480"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="611"/>
<source>Judge:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="481"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="612"/>
<source>If checked, you will get alerts about case announcements if the judge spot is open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="494"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="626"/>
<source>Juror:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="495"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="627"/>
<source>If checked, you will get alerts about case announcements if a juror spot is open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="508"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="641"/>
<source>Stenographer:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="510"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="643"/>
<source>If checked, you will get alerts about case announcements if a stenographer spot is open.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="523"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="657"/>
<source>CM:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="525"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="659"/>
<source>If checked, you will appear amongst the potential CMs on the server.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="536"/>
- <source>Witness:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="538"/>
- <source>If checked, you will appear amongst the potential witnesses on the server.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="551"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="673"/>
<source>Hosting cases:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="553"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="675"/>
<source>If you&apos;re a CM, enter what cases you are willing to host.</source>
<translation type="unfinished"></translation>
</message>
@@ -490,385 +484,776 @@ Reason: %1</source>
<context>
<name>Courtroom</name>
<message>
- <location filename="../../src/charselect.cpp" line="69"/>
+ <location filename="../../src/charselect.cpp" line="21"/>
<source>Password</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="75"/>
+ <location filename="../../src/charselect.cpp" line="27"/>
<source>Spectator</source>
<translation>観客</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="78"/>
- <location filename="../../src/courtroom.cpp" line="179"/>
+ <location filename="../../src/charselect.cpp" line="30"/>
+ <location filename="../../src/courtroom.cpp" line="175"/>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="83"/>
+ <location filename="../../src/charselect.cpp" line="35"/>
<source>Passworded</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="87"/>
+ <location filename="../../src/charselect.cpp" line="39"/>
<source>Taken</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="182"/>
- <source>Could not find %1</source>
+ <location filename="../../src/charselect.cpp" line="231"/>
+ <source>Generating chars:
+%1/%2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="149"/>
+ <location filename="../../src/courtroom.cpp" line="148"/>
<source>Showname</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="153"/>
+ <location filename="../../src/courtroom.cpp" line="152"/>
<source>Message</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="164"/>
+ <location filename="../../src/courtroom.cpp" line="167"/>
<source>Name</source>
<translation>名前</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="224"/>
+ <location filename="../../src/courtroom.cpp" line="217"/>
<source>Pre</source>
<translation>前</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="227"/>
+ <location filename="../../src/courtroom.cpp" line="220"/>
<source>Flip</source>
<translation>フリップ</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="224"/>
<source>Guard</source>
- <translation type="vanished">ガード</translation>
+ <translation>ガード</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="238"/>
- <location filename="../../src/courtroom.cpp" line="720"/>
+ <location filename="../../src/courtroom.cpp" line="228"/>
+ <source>Additive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="233"/>
+ <location filename="../../src/courtroom.cpp" line="815"/>
<source>Casing</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="243"/>
+ <location filename="../../src/courtroom.cpp" line="238"/>
<source>Shownames</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="246"/>
+ <location filename="../../src/courtroom.cpp" line="241"/>
<source>No Interrupt</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="264"/>
<source>White</source>
- <translation>白</translation>
+ <translation type="vanished">白</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="265"/>
<source>Green</source>
- <translation>緑</translation>
+ <translation type="vanished">緑</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="266"/>
<source>Red</source>
- <translation>赤</translation>
+ <translation type="vanished">赤</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="267"/>
<source>Orange</source>
- <translation>オレンジ</translation>
+ <translation type="vanished">オレンジ</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="268"/>
<source>Blue</source>
- <translation>青</translation>
+ <translation type="vanished">青</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="269"/>
<source>Yellow</source>
- <translation>黄色</translation>
+ <translation type="vanished">黄色</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3500"/>
- <source>This does nothing, but there you go.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/courtroom.cpp" line="3641"/>
+ <location filename="../../src/courtroom.cpp" line="3315"/>
<source>You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini.
Cases you can load: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3669"/>
+ <location filename="../../src/courtroom.cpp" line="3343"/>
<source>Case made by %1.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3679"/>
+ <location filename="../../src/courtroom.cpp" line="3353"/>
<source>Navigate to %1 for the CM doc.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3702"/>
+ <location filename="../../src/courtroom.cpp" line="3377"/>
<source>Your case &quot;%1&quot; was loaded!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="664"/>
- <location filename="../../src/courtroom.cpp" line="3816"/>
+ <location filename="../../src/courtroom.cpp" line="767"/>
+ <location filename="../../src/courtroom.cpp" line="3475"/>
<source>Server</source>
<translation type="unfinished"></translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="143"/>
+ <source>None</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="749"/>
+ <source>Hold It!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="750"/>
+ <location filename="../../src/courtroom.cpp" line="756"/>
+ <location filename="../../src/courtroom.cpp" line="762"/>
+ <source>When this is turned on, your next in-character message will be a shout!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="755"/>
+ <source>Objection!</source>
+ <translation type="unfinished">意義あり!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="761"/>
+ <source>Take That!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="769"/>
+ <source>Toggle between server chat and global AO2 chat.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="773"/>
+ <location filename="../../src/courtroom.cpp" line="777"/>
+ <location filename="../../src/courtroom.cpp" line="783"/>
+ <location filename="../../src/courtroom.cpp" line="787"/>
+ <source>This will display the animation in the viewport as soon as it is pressed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="781"/>
+ <source>Guilty!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="794"/>
+ <source>Bring up the Character Select Screen and change your character.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="800"/>
+ <source>Refresh the theme and update all of the ui elements to match.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="806"/>
+ <source>Request the attention of the current server&apos;s moderator.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="812"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../../src/courtroom.cpp" line="818"/>
+ <source>An interface to help you announce a case (you have to be a CM first to be able to announce cases)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="824"/>
+ <source>Switch between Areas and Music lists</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="829"/>
+ <source>Play a single-shot animation as defined by the emote when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="833"/>
+ <source>If preanim is checked, display the input text immediately as the animation plays concurrently.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="837"/>
+ <source>Mirror your character&apos;s emotes when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="841"/>
+ <source>Add text to your last spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="845"/>
+ <source>Do not listen to mod calls when checked, preventing them from playing sounds or focusing attention on the window.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="849"/>
+ <source>Lets you receive case alerts when enabled.
+(You can set your preferences in the Settings!)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="854"/>
+ <source>Display customized shownames for all users when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="857"/>
+ <source>Custom Shout!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="860"/>
+ <source>This will display the custom character-defined animation in the viewport as soon as it is pressed.
+To make one, your character&apos;s folder must contain custom.[webp/apng/gif/png] and custom.[wav/ogg/opus] sound effect</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="868"/>
+ <source>Play realization sound and animation in the viewport on the next spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="874"/>
+ <source>Shake the screen on next spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="880"/>
+ <source>Display the list of character folders you wish to mute.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="884"/>
+ <location filename="../../src/courtroom.cpp" line="892"/>
+ <source>Increase the health bar.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="888"/>
+ <location filename="../../src/courtroom.cpp" line="896"/>
+ <source>Decrease the health bar.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="900"/>
+ <source>Change the text color of the spoken message.
+You can also select a part of your currently typed message and use the dropdown to change its color!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="913"/>
<source>Back to Lobby</source>
<translation>ロビーに戻る</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="270"/>
- <source>Rainbow</source>
- <translation>虹</translation>
+ <location filename="../../src/courtroom.cpp" line="3061"/>
+ <location filename="../../src/courtroom.cpp" line="4479"/>
+ <location filename="../../src/courtroom.cpp" line="4486"/>
+ <source>has played a song</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="160"/>
- <source>OOC Message</source>
+ <location filename="../../src/courtroom.cpp" line="3195"/>
+ <source>You will now pair up with %1 if they also choose your character in return.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="232"/>
- <source>Disable Modcalls</source>
- <translation type="unfinished"></translation>
+ <source>Rainbow</source>
+ <translation type="vanished">虹</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="271"/>
<source>Pink</source>
- <translation>ピンク</translation>
+ <translation type="vanished">ピンク</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="272"/>
<source>Cyan</source>
- <translation>シアン</translation>
+ <translation type="vanished">シアン</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="295"/>
+ <location filename="../../src/courtroom.cpp" line="274"/>
<source>% offset</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="646"/>
+ <location filename="../../src/courtroom.cpp" line="277"/>
+ <source>To front</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="278"/>
+ <source>To behind</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="591"/>
+ <source>Select a character you wish to pair with.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="596"/>
+ <source>Change the percentage offset of your character&apos;s position from the center of the screen.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="602"/>
+ <source>Change the order of appearance for your character.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="607"/>
+ <source>Display the list of characters to pair with.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="665"/>
+ <source>Oops, you&apos;re muted!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="679"/>
+ <source>Set your character&apos;s emote to play on your next message.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="683"/>
+ <source>Set your character&apos;s supplementary background.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="689"/>
+ <source>Set an &apos;iniswap&apos;, or an alternative character folder to refer to from your current character.
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/iniswaps.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="698"/>
+ <location filename="../../src/courtroom.cpp" line="715"/>
+ <source>Remove the currently selected iniswap from the list and return to the original character folder.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="706"/>
+ <source>Set a sound effect to play on your next &apos;Preanim&apos;. Leaving it on Default will use the emote-defined sound (if any).
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/soundlist.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="722"/>
+ <source>Choose an effect to play on your next spoken message.
+The effects are defined in your theme/effects/effects.ini. Your character can define custom effects by
+char.ini [Options] category, effects = &apos;miscname&apos; where it referes to misc/&lt;miscname&gt;/effects.ini to read the effects.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="742"/>
<source>Music</source>
<translation>音楽</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="648"/>
+ <location filename="../../src/courtroom.cpp" line="744"/>
<source>Sfx</source>
<translation>効果音</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="650"/>
+ <location filename="../../src/courtroom.cpp" line="746"/>
<source>Blips</source>
<translation>ブリップ</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="653"/>
- <source>Log limit</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/courtroom.cpp" line="683"/>
+ <location filename="../../src/courtroom.cpp" line="791"/>
<source>Change character</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="693"/>
+ <location filename="../../src/courtroom.cpp" line="797"/>
<source>Reload theme</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="702"/>
+ <location filename="../../src/courtroom.cpp" line="803"/>
<source>Call mod</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="711"/>
+ <location filename="../../src/courtroom.cpp" line="809"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="729"/>
+ <location filename="../../src/courtroom.cpp" line="822"/>
<source>A/M</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="737"/>
+ <location filename="../../src/courtroom.cpp" line="827"/>
<source>Preanim</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="1265"/>
- <location filename="../../src/courtroom.cpp" line="3492"/>
- <source>You were granted the Disable Modcalls button.</source>
+ <location filename="../../src/courtroom.cpp" line="914"/>
+ <source>Return back to the server list.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3310"/>
- <source>You have been banned.</source>
+ <location filename="../../src/courtroom.cpp" line="927"/>
+ <source>Become a spectator. You won&apos;t be able to interact with the in-character screen.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3739"/>
- <source>Too many arguments to save a case! You only need a filename without extension and the courtroom status.</source>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
+ <source>You were granted the Disable Modcalls button.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3506"/>
- <source>You opened the settings menu.</source>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
+ <location filename="../../src/courtroom.cpp" line="3343"/>
+ <source>CLIENT</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3519"/>
- <source>You will now pair up with </source>
+ <location filename="../../src/courtroom.cpp" line="2984"/>
+ <source>You have been banned.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3521"/>
- <source> if they also choose your character in return.</source>
+ <location filename="../../src/courtroom.cpp" line="3182"/>
+ <source>You opened the settings menu.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3527"/>
+ <location filename="../../src/courtroom.cpp" line="3201"/>
<source>You are no longer paired with anyone.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3532"/>
+ <location filename="../../src/courtroom.cpp" line="3206"/>
<source>Are you sure you typed that well? The char ID could not be recognised.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3547"/>
+ <location filename="../../src/courtroom.cpp" line="3221"/>
<source>You have set your offset to </source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3554"/>
+ <location filename="../../src/courtroom.cpp" line="3228"/>
<source>Your offset must be between -100% and 100%!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3559"/>
+ <location filename="../../src/courtroom.cpp" line="3233"/>
<source>That offset does not look like one.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3565"/>
+ <location filename="../../src/courtroom.cpp" line="3239"/>
<source>You switched your music and area list.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3572"/>
+ <location filename="../../src/courtroom.cpp" line="3246"/>
<source>You have forcefully enabled features that the server may not support. You may not be able to talk IC, or worse, because of this.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3586"/>
+ <location filename="../../src/courtroom.cpp" line="3260"/>
<source>Your pre-animations interrupt again.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3589"/>
+ <location filename="../../src/courtroom.cpp" line="3263"/>
<source>Your pre-animations will not interrupt text.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3600"/>
+ <location filename="../../src/courtroom.cpp" line="3274"/>
<source>Couldn&apos;t open chatlog.txt to write into.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3613"/>
+ <location filename="../../src/courtroom.cpp" line="3287"/>
<source>The IC chatlog has been saved.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3626"/>
+ <location filename="../../src/courtroom.cpp" line="3300"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely the case file you&apos;re looking for can&apos;t be found in there.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3653"/>
+ <location filename="../../src/courtroom.cpp" line="3327"/>
<source>Too many arguments to load a case! You only need one filename, without extension.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3714"/>
+ <location filename="../../src/courtroom.cpp" line="3367"/>
+ <location filename="../../src/courtroom.cpp" line="3369"/>
+ <location filename="../../src/evidence.cpp" line="761"/>
+ <location filename="../../src/evidence.cpp" line="763"/>
+ <source>UNKNOWN</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3389"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely that you somehow deleted it.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3729"/>
+ <location filename="../../src/courtroom.cpp" line="3404"/>
<source>You need to give a filename to save (extension not needed) and the courtroom status!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3766"/>
+ <location filename="../../src/courtroom.cpp" line="3414"/>
+ <source>Too many arguments to save a case! You only need a filename without extension and the courtroom status!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3441"/>
<source>Succesfully saved, edit doc and cmdoc link on the ini!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3806"/>
+ <location filename="../../src/courtroom.cpp" line="3468"/>
<source>Master</source>
<translation>マスター</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4309"/>
+ <location filename="../../src/courtroom.cpp" line="3968"/>
+ <source>Expand All Categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3970"/>
+ <source>Collapse All Categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3974"/>
+ <source>Fade Out Previous</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3980"/>
+ <source>Fade In</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3986"/>
+ <source>Synchronize</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4256"/>
+ <source>Default</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4417"/>
<source>Reason:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4310"/>
+ <location filename="../../src/courtroom.cpp" line="4418"/>
<source>Call Moderator</source>
<translation>モデレーターを呼ぶ</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4426"/>
+ <location filename="../../src/courtroom.cpp" line="4430"/>
<source>Error</source>
<translation>エラー</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
+ <location filename="../../src/courtroom.cpp" line="4426"/>
<source>You must provide a reason.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4430"/>
<source>The message is too long.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="25"/>
<source>Choose...</source>
- <translation>選択...</translation>
+ <translation type="vanished">選択...</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="17"/>
+ <source>Present this piece of evidence to everyone on your next spoken message</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="208"/>
+ <location filename="../../src/evidence.cpp" line="24"/>
+ <source>Save evidence to an .ini file.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="26"/>
+ <source>Load evidence from an .ini file.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="31"/>
+ <source>Destroy this piece of evidence</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="34"/>
+ <source>Choose..</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="37"/>
+ <source>Close the evidence display/editing overlay.
+You will be prompted if there&apos;s any unsaved changes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="40"/>
+ <source>Save any changes made to this piece of evidence and send them to server.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="48"/>
+ <source>Double-click to edit. Press [X] to update your changes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="104"/>
+ <source>Bring up the Evidence screen.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="147"/>
+ <source>Switch evidence to private inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="151"/>
+ <source>Switch evidence to global inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="158"/>
+ <location filename="../../src/evidence.cpp" line="617"/>
+ <source>Transfer evidence to private inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="163"/>
+ <location filename="../../src/evidence.cpp" line="627"/>
+ <source>Transfer evidence to global inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="263"/>
+ <source>The piece of evidence you&apos;ve been editing has changed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="264"/>
+ <source>Do you wish to keep your changes?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="265"/>
+ <source>Name: %1
+Image: %2
+Description:
+%3</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="387"/>
<source>Images (*.png)</source>
<translation>イメージ (*.png)</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="280"/>
+ <location filename="../../src/evidence.cpp" line="456"/>
+ <location filename="../../src/evidence.cpp" line="460"/>
+ <location filename="../../src/evidence.cpp" line="463"/>
+ <source>Double-click to edit...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="478"/>
<source>Add new evidence...</source>
<translation>新しい証拠を付け加える...</translation>
</message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="556"/>
+ <source>Evidence has been modified.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="557"/>
+ <source>Do you want to save your changes?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="619"/>
+ <source>Current evidence is global. Click to switch to private.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="629"/>
+ <source>Current evidence is private. Click to switch to global.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="659"/>
+ <source>&quot;%1&quot; has been transferred.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="721"/>
+ <source>Save Inventory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="721"/>
+ <location filename="../../src/evidence.cpp" line="747"/>
+ <source>Ini Files (*.ini)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="747"/>
+ <source>Open Inventory</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>Discord</name>
@@ -901,49 +1286,84 @@ Cases you can load: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="29"/>
+ <location filename="../../src/lobby.cpp" line="31"/>
+ <source>Search</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="39"/>
<source>Name</source>
<translation>名前</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="82"/>
+ <location filename="../../src/lobby.cpp" line="94"/>
<source>It doesn&apos;t look like your client is set up correctly.
Did you download all resources correctly from tiny.cc/getao, including the large &apos;base&apos; folder?</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="111"/>
+ <location filename="../../src/lobby.cpp" line="123"/>
<source>Version: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="155"/>
+ <location filename="../../src/lobby.cpp" line="129"/>
+ <source>Settings</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="132"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="176"/>
<source>Loading</source>
<translation>ロード中</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="159"/>
+ <location filename="../../src/lobby.cpp" line="180"/>
<source>Cancel</source>
<translation>キャンセル</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="279"/>
- <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</source>
+ <location filename="../../src/lobby.cpp" line="360"/>
+ <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;2.8 Major Release development:&lt;/b&gt;&lt;br&gt;Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;2.8 Quality Assurance:&lt;/b&gt;&lt;br&gt;WillDean, Captain N, Mr M, Riel, Seimmet, Fury McFlurry,CedricDewitt, Chewable Tablets, Fantos, Futugaze,Geck, Minx, Pandae, Sierra, CrazyJC, CaseyMayCazy,GreenBowers, Robotic Overlord, Veritas, Gin-Gi&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, the AO2 community, server hosts, game masters,case makers, content creators and players!</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="395"/>
+ <location filename="../../src/lobby.cpp" line="380"/>
+ <source>About</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="521"/>
<source>Online: %1/%2</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="121"/>
- <location filename="../../src/lobby.cpp" line="327"/>
+ <location filename="../../src/lobby.cpp" line="142"/>
+ <location filename="../../src/lobby.cpp" line="418"/>
<source>Offline</source>
<translation>オフライン</translation>
</message>
</context>
<context>
+ <name>chatlogpiece</name>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="5"/>
+ <location filename="../../src/chatlogpiece.cpp" line="6"/>
+ <location filename="../../src/chatlogpiece.cpp" line="7"/>
+ <source>UNKNOWN</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="55"/>
+ <source> has played a song: </source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>debug_functions</name>
<message>
<location filename="../../src/debug_functions.cpp" line="10"/>
@@ -956,7 +1376,7 @@ Did you download all resources correctly from tiny.cc/getao, including the large
<translation>エラー</translation>
</message>
<message>
- <location filename="../../src/debug_functions.cpp" line="26"/>
+ <location filename="../../src/debug_functions.cpp" line="25"/>
<source>Notice</source>
<translation>通知</translation>
</message>
diff --git a/resource/translations/ao_pl.qm b/resource/translations/ao_pl.qm
index 995a5bc9..04ec8348 100644
--- a/resource/translations/ao_pl.qm
+++ b/resource/translations/ao_pl.qm
Binary files differ
diff --git a/resource/translations/ao_pl.ts b/resource/translations/ao_pl.ts
index 2662fcf3..24cccf8a 100644
--- a/resource/translations/ao_pl.ts
+++ b/resource/translations/ao_pl.ts
@@ -9,83 +9,82 @@
<translation>Odłączono od serwera.</translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="151"/>
+ <location filename="../../src/aoapplication.cpp" line="152"/>
<source>Error connecting to master server. Will try again in %1 seconds.</source>
<translation>Błąd podczas łączenia się z głównym serwerem. Spróbuj ponownie za %1 sekundy.</translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="156"/>
+ <location filename="../../src/aoapplication.cpp" line="157"/>
<source>There was an error connecting to the master server.
We deploy multiple master servers to mitigate any possible downtime, but the client appears to have exhausted all possible methods of finding and connecting to one.
Please check your Internet connection and firewall, and please try again.</source>
<translation>Odkryto błąd podczas łączenia się z głównym serwerem.
-Używamy wielu głównych serwerów, aby zminimalizować każdą możliwą przerwę, ale klient wyczerpał jakąkolwiek możliwość znalezienia i połączenia się z jednym.
+Używamy wielu master serwerów, aby zminimalizować każdą możliwą przerwę, ale klient wyczerpał jakąkolwiek możliwość znalezienia i połączenia się z jednym.
Sprawdź swoje połączenie internetowe oraz zaporę ogniową i spróbuj ponownie.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="108"/>
+ <location filename="../../src/packet_distribution.cpp" line="94"/>
<source>Outdated version! Your version: %1
Please go to aceattorneyonline.com to update.</source>
<translation>Nieaktualna wersja! Twoja wersja: %1
Udaj się do aceattorneyonline.com, aby zaktualizować.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="115"/>
<source>You have been exiled from AO.
Have a nice day.</source>
- <translation>Zostałeś wygnany z AO.
+ <translation type="obsolete">Zostałeś wygnany z AO.
Życzymy miłego dnia.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="258"/>
+ <location filename="../../src/packet_distribution.cpp" line="253"/>
<source>Attorney Online 2</source>
<translatorcomment>Prawnik w Internecie 2</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="282"/>
+ <location filename="../../src/packet_distribution.cpp" line="281"/>
<source>Loading</source>
<translation>Ładowanie</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="373"/>
+ <location filename="../../src/packet_distribution.cpp" line="381"/>
<source>Loading evidence:
%1/%2</source>
<translation>Ładowanie dowodów:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="408"/>
- <location filename="../../src/packet_distribution.cpp" line="506"/>
+ <location filename="../../src/packet_distribution.cpp" line="416"/>
+ <location filename="../../src/packet_distribution.cpp" line="510"/>
<source>Loading music:
%1/%2</source>
<translation>Ładowanie muzyki:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="326"/>
- <location filename="../../src/packet_distribution.cpp" line="457"/>
+ <location filename="../../src/packet_distribution.cpp" line="334"/>
+ <location filename="../../src/packet_distribution.cpp" line="483"/>
<source>Loading chars:
%1/%2</source>
<translation>Ładowanie postaci:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="635"/>
+ <location filename="../../src/packet_distribution.cpp" line="692"/>
<source>You have been kicked from the server.
Reason: %1</source>
<translation>Zostałeś wyrzucony z tego serwera.
Powód: %1</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="643"/>
+ <location filename="../../src/packet_distribution.cpp" line="700"/>
<source>You have been banned from the server.
Reason: %1</source>
<translation>Zostałeś zbanowany z tego serwera.
Powód: %1</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="651"/>
+ <location filename="../../src/packet_distribution.cpp" line="708"/>
<source>You are banned on this server.
Reason: %1</source>
<translation>Jesteś zbanowany na tym serwerze.
@@ -130,383 +129,405 @@ Powód: %1</translation>
<translation>Potrzebny stenograf</translation>
</message>
<message>
- <location filename="../../src/aocaseannouncerdialog.cpp" line="66"/>
<source>Witness needed</source>
- <translation>Potrzebny świadek</translation>
+ <translation type="obsolete">Potrzebny świadek</translation>
</message>
</context>
<context>
<name>AOOptionsDialog</name>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="11"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="12"/>
<source>Settings</source>
<translation>Ustawienia</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="48"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="46"/>
<source>Gameplay</source>
<translation>Rozgrywka</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="61"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="62"/>
<source>Theme:</source>
<translation>Motyw:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="63"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="64"/>
<source>Sets the theme used in-game. If the new theme changes the lobby&apos;s look as well, you&apos;ll need to reload the lobby for the changes to take effect, such as by joining a server and leaving it.</source>
- <translation>Ustawia motyw używany w grze. Jeżeli nowy motyw równiesz zmienia wygląd poczekalni, musisz odświeżyć poczekalnię, aby zmiany zaczęły działać, np. poprzez dołączenie do serwera i wyjście z niego.</translation>
+ <translation>Ustawia motyw używany w grze. Jeżeli nowy motyw zmienia wygląd poczekalni, będziesz musiał ją również odświeżyć, aby zmiany zaczęły działać, np. poprzez dołączenie do serwera i wyjście z niego.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="109"/>
- <source>Gives the default value for the in-game &apos;Custom shownames&apos; checkbox, which in turn determines whether the client should display custom in-character names.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="305"/>
- <source>Sets the default volume for music.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="320"/>
- <source>Sets the default volume for SFX sounds, like interjections or other character sound effects.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="568"/>
- <source>IC Log</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="581"/>
- <source>Colorful IC log:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="583"/>
- <source>Enables colored text in the log.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="594"/>
- <source>Only inline coloring:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="596"/>
- <source>Only inline coloring will be shown such as &lt;&gt;,|| etc.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="606"/>
- <source>Mirror IC log:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="608"/>
- <source>IC log will mirror the IC box. Meaning that if somebody gets interrupted nobody will know what they wanted to say. Enable for a more realistic experience.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="620"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="95"/>
<source>Log goes downwards:</source>
<translation>Dziennik idzie w dół:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="622"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="97"/>
<source>If ticked, new messages will appear at the bottom (like the OOC chatlog). The traditional (AO1) behaviour is equivalent to this being unticked.</source>
<translation>Jeżeli zaznaczone, nowe wiadomości zaczną się pojawiać na dole (tak jak na czacie OOC). Tradycyjne (AO1) zachowanie jest równoważne do tego bycia nie zaznaczonym.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="634"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="110"/>
<source>Log length:</source>
<translation>Długość dziennika:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="635"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="111"/>
<source>The amount of messages the IC chatlog will keep before deleting older messages. A value of 0 or below counts as &apos;infinite&apos;.</source>
- <translation>Ilość wiadomości, jakie czat IC będzie zostawiał zanim usunie starsze wiadomości. Wartośc 0 albo niżej, liczy się jako &apos;nieskończone&apos;.</translation>
+ <translation>Ilość wiadomości, jakie dziennik IC będzie pokazywał zanim usunie starsze wiadomości. Wartość 0 albo niżej, liczy się jako &apos;nieskończone&apos;.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="93"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="133"/>
<source>Default username:</source>
<translation>Domyślna nazwa użytkownika:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="95"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="135"/>
<source>Your OOC name will be automatically set to this value when you join a server.</source>
<translation>Twoja nazwa OOC będzie ustawiana automatycznie do tej wartości, kiedy dołączysz na serwer.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="107"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="148"/>
<source>Custom shownames:</source>
<translation>Niestandardowe ksywki:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="150"/>
<source>Gives the default value for the in-game &apos;Custom shownames&apos; tickbox, which in turn determines whether the client should display custom in-character names.</source>
- <translation type="vanished">Daje domyślną wartość przyciskowi &apos;Niestandardowe ksywki&apos;, który określa, czy klient powinien pokazywać niestandardowe nazwy IC.</translation>
+ <translation>Daje domyślną wartość przyciskowi &apos;Niestandardowe ksywki&apos;, który określa, czy klient powinien pokazywać niestandardowe nazwy IC.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="127"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="170"/>
<source>Backup MS:</source>
- <translation>Kopia zapasowa głównego serwera:</translation>
+ <translation>Kopia zapasowa master serwera:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="129"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="172"/>
<source>If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address.</source>
- <translation>Jeśli wbudowane szukanie serwerów zawiedzie, gra spróbuje użyć adresu podanego tutaj i użyje go jako adresu zapasowego głównego serwera.</translation>
+ <translation>Jeśli wbudowane szukanie serwerów zawiedzie, gra spróbuje użyć adresu podanego tutaj i użyje go jako adresu zapasowego master serwera.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="141"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="185"/>
<source>Discord:</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="143"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="187"/>
<source>Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for.</source>
<translation>Pozwala innym na Discordzie zobaczyć na jakim serwerze się znajdujesz, jaką postać używasz i jak długo grałeś.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="155"/>
<source>Allow Shake/Flash:</source>
- <translation>Zezwalaj Wstrząśnięcia/Błyśnięcia:</translation>
+ <translation type="obsolete">Zezwalaj Wstrząśnięcia/Błyśnięcia:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="157"/>
<source>Allows screenshaking and flashing. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
- <translation>Pozwala na wstrząśnięcia ekranu i błyśnięcia. Wyłącz to, jeśli przejmujesz się lub masz problemy z światłoczułością oraz/lub napady padaczkowe.</translation>
+ <translation type="obsolete">Pozwala na wstrząśnięcia ekranu i błyśnięcia. Wyłącz to, jeśli przejmujesz się lub masz problemy z światłoczułością oraz/lub napady padaczkowe.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="168"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="200"/>
<source>Language:</source>
<translation>Język:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="170"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="202"/>
<source>Sets the language if you don&apos;t want to use your system language.</source>
<translation>Ustawia język, jeśli nie chcesz używać języka systemowego.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="193"/>
- <source>Slower text speed:</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/aooptionsdialog.cpp" line="208"/>
+ <source> - Keep current setting</source>
+ <translation> - Zostaw obecne ustawienia</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="194"/>
- <source>Set the text speed to be the same as the AA games.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/aooptionsdialog.cpp" line="222"/>
+ <source>Allow Screenshake:</source>
+ <translation>Zezwalaj Wstrząśnięcia:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="201"/>
- <source>Blip delay on punctuations:</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/aooptionsdialog.cpp" line="224"/>
+ <source>Allows screenshaking. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
+ <translation>Zezwala na wstrząśnięcia ekranu. Wyłącz to, jeśli przejmujesz się lub masz problemy z światłoczułością oraz/lub z napadami padaczkowymi.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="202"/>
- <source>Punctuation delay modifier. Enable it for the blips to slow down on punctuations.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/aooptionsdialog.cpp" line="236"/>
+ <source>Allow Effects:</source>
+ <translation>Zezwalaj Efekty:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="238"/>
+ <source>Allows screen effects. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
+ <translation>Zezwala na efekty ekranowe. Wyłącz to, jeśli przejmujesz się lub masz problemy z światłoczułością oraz/lub z napadami padaczkowymi.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="250"/>
+ <source>Network Frame Effects:</source>
+ <translation>Efekty Network Frame:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="212"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="251"/>
+ <source>Send screen-shaking, flashes and sounds as defined in the char.ini over the network. Only works for servers that support this functionality.</source>
+ <translation>Wysyła wstrząśnięcia ekranu, błyśnięcia i dźwięki, jak zdefiniowano w pliku char.ini, przez sieć. Działa tylko w przypadku serwerów, które obsługują tę funkcję.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="264"/>
+ <source>Colors in IC Log:</source>
+ <translation>Kolory w dzienniku IC:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="266"/>
+ <source>Use the markup colors in the server IC chatlog.</source>
+ <translation>Użyj znaczników kolorów w serwerowym dzienniku IC.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="277"/>
+ <source>Sticky Sounds:</source>
+ <translation>Lepkie Dźwięki:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="279"/>
+ <source>Turn this on to prevent the sound dropdown from clearing the sound after playing it.</source>
+ <translation>Włącz to, aby zapobiec listę dźwięków przed odznaczeniem zaznaczonego dźwięku po jego odtworzeniu.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="291"/>
+ <source>Sticky Effects:</source>
+ <translation>Lepkie Efekty:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="293"/>
+ <source>Turn this on to prevent the effects dropdown from clearing the effect after playing it.</source>
+ <translation>Włącz to, aby zapobiec listę efektów przed odznaczeniem zaznaczonego efektu po jego odtworzeniu.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="306"/>
+ <source>Sticky Preanims:</source>
+ <translation>Lepkie Przed-animacje:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="308"/>
+ <source>Turn this on to prevent preanimation checkbox from clearing after playing the emote.</source>
+ <translation>Włącz to, aby zapobiec przycisku wyboru przed-animacji od odznaczenia się po odegraniu emotki.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="320"/>
+ <source>Custom Chatboxes:</source>
+ <translation>Niestandardowe Okna Czatu:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="322"/>
+ <source>Turn this on to allow characters to define their own custom chat box designs.</source>
+ <translation>Włącz to, aby pozwolić postaciom definiować swoje własne designy okienek czatu.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="340"/>
<source>Callwords</source>
<translation>Zawołania</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="239"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="367"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!&lt;br&gt;Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Wpisz tyle zawołań, ile dusza zapragnie. Wielkość liter nie ma znaczenia. Miej na uwadze, aby każde zawołanie było w swojej lini!&lt;br&gt;Nie zostawiaj spacji na końcu -- zostaniesz zaalarmowany za każdym razem, kiedy ktoś użyje spacji w swojej wiadomości.&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="249"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="377"/>
<source>Audio</source>
<translation>Dźwięk</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="262"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="391"/>
<source>Audio device:</source>
<translation>Urządzenie dźwiękowe:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="263"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="392"/>
<source>Sets the audio device for all sounds.</source>
<translation>Ustawia urządzenie dźwiękowe dla wszystkich dźwięków.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="304"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="435"/>
<source>Music:</source>
<translation>Muzyka:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="436"/>
<source>Sets the music&apos;s default volume.</source>
- <translation type="vanished">Ustawia domyślną głośność muzyki.</translation>
+ <translation>Ustawia domyślną głośność muzyki.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="318"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="450"/>
<source>SFX:</source>
<translation>Efekty dźwiękowe (SFX):</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="452"/>
<source>Sets the SFX&apos;s default volume. Interjections and actual sound effects count as &apos;SFX&apos;.</source>
- <translation type="vanished">Ustawia domyślną głośność efektów dźwiękowych (SFX). Sprzeciwy i same efekty specjalne są zaliczane jako &apos;SFX&apos;.</translation>
+ <translation>Ustawia domyślną głośność efektów dźwiękowych (SFX). Sprzeciwy i same efekty specjalne są zaliczane jako &apos;SFX&apos;.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="333"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="466"/>
<source>Blips:</source>
<translation>Blipy:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="335"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="468"/>
<source>Sets the volume of the blips, the talking sound effects.</source>
<translation>Ustawia głośność blipów, efektów dźwiękowych mówienia.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="354"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="490"/>
<source>Blip rate:</source>
<translation>Szybkość blipów:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="356"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="492"/>
<source>Sets the delay between playing the blip sounds.</source>
<translation>Ustawia opóźnienie pomiędzy graniem blipów.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="367"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="500"/>
+ <source>Play a blip sound &quot;once per every X symbols&quot;, where X is the blip rate.</source>
+ <translation>Zagraj dźwięk blipa &quot;raz na X symboli&quot;, gdzie X to tempo blipów.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="507"/>
<source>Blank blips:</source>
<translatorcomment>The &apos;blip&apos; isn&apos;t an accurate polish representation of this english word.</translatorcomment>
<translation>Puste blipy:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="369"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="509"/>
<source>If true, the game will play a blip sound even when a space is &apos;being said&apos;.</source>
<translation>Jeżeli zaznaczone, gra zagra dźwięk blip za każdym razem spacja &apos;jest mówiona&apos;.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="380"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="521"/>
<source>Enable Looping SFX:</source>
<translation>Włącz pętlące się efekty dźwiękowe (SFX):</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="381"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="522"/>
<source>If true, the game will allow looping sound effects to play on preanimations.</source>
- <translation>Jeśli zaznaczone, gra zezwoli na pętlące się efekty dźwiękowe (SFX).</translation>
+ <translation>Jeśli zaznaczone, gra zezwoli na pętlące się efekty dźwiękowe (SFX) na odtwarzanie podczas animacji.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="392"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="534"/>
<source>Kill Music On Objection:</source>
- <translation>Przerwij muzykę w czasie sprzeciwu:</translation>
+ <translation>Przerwij muzykę na czas sprzeciwu:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="536"/>
+ <source>If true, AO2 will stop the music for you when you or someone else does &apos;Objection!&apos;.</source>
+ <translation>Jeśli zaznaczone, gra przerwie muzykę, kiedy ktoś się sprzeciwi (Objection!).</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="394"/>
<source>If true, the game will stop music when someone objects, like in the actual games.</source>
- <translation>Jeśli zaznaczone, gra przerwie muzykę, kiedy ktoś sprzeciwi się, tak jak w oryginalnych grach.</translation>
+ <translation type="obsolete">Jeśli zaznaczone, gra przerwie muzykę, kiedy ktoś sprzeciwi się, tak jak w oryginalnych grach.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="408"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="548"/>
<source>Casing</source>
<translation>Rozprawy</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="424"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="565"/>
<source>This server supports case alerts.</source>
<translation>Ten serwer wspiera komunikaty rozpraw.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="427"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="568"/>
<source>This server does not support case alerts.</source>
<translation>Ten serwer nie wspiera komunikatów rozpraw.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="428"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="569"/>
<source>Pretty self-explanatory.</source>
<translation>Dosyć oczywiste.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="436"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="578"/>
<source>Casing:</source>
<translation>Rozprawy:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="438"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="580"/>
<source>If checked, you will get alerts about case announcements.</source>
<translation>Jeżeli zaznaczone, dostaniesz komunikaty o ogłoszeniach rozpraw.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="451"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="596"/>
<source>Defense:</source>
<translation>Obrona:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="452"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="597"/>
<source>If checked, you will get alerts about case announcements if a defense spot is open.</source>
<translation>Jeśli zaznaczone, dostaniesz komunikaty o ogłoszeniach rozpraw, jeśli miejsce obrony jest otwarte.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="465"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="611"/>
<source>Prosecution:</source>
<translation>Prokuratura:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="467"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="613"/>
<source>If checked, you will get alerts about case announcements if a prosecutor spot is open.</source>
<translation>Jeśli zaznaczone, dostaniesz komunikaty o ogłoszeniach rozpraw, jeśli miejsce prokuratora jest otwarte.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="480"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="627"/>
<source>Judge:</source>
<translation>Sędzia:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="481"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="628"/>
<source>If checked, you will get alerts about case announcements if the judge spot is open.</source>
<translation>Jeśli zaznaczone, dostaniesz komunikaty o ogłoszeniach rozpraw, jeśli miejsce sędzi jest otwarte.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="494"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="642"/>
<source>Juror:</source>
<translation>Ławnik:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="495"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="643"/>
<source>If checked, you will get alerts about case announcements if a juror spot is open.</source>
<translation>Jeżeli zaznaczone, dostaniesz komunikaty o ogłoszeniach rozpraw, jeśli miejsce ławnika jest otwarte.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="508"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="657"/>
<source>Stenographer:</source>
<translation>Stenograf:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="510"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="659"/>
<source>If checked, you will get alerts about case announcements if a stenographer spot is open.</source>
<translation>Jeżeli zaznaczone, dostaniesz komunikaty o ogłoszeniach rozpraw, jeśli miejsce stenografa jest otwarte.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="523"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="673"/>
<source>CM:</source>
<translation>Zarządca rozpraw (CM):</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="525"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="675"/>
<source>If checked, you will appear amongst the potential CMs on the server.</source>
<translation>Jeśli zaznaczone, pojawisz się wśród potencjalnych zarządców rozpraw (CM) na serwerze.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="536"/>
<source>Witness:</source>
- <translation>Świadek:</translation>
+ <translation type="obsolete">Świadek:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="538"/>
<source>If checked, you will appear amongst the potential witnesses on the server.</source>
- <translation>Jeżeli zaznaczone, pojawisz się wśród potencjalnych świadków na serwerze.</translation>
+ <translation type="obsolete">Jeżeli zaznaczone, pojawisz się wśród potencjalnych świadków na serwerze.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="551"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="689"/>
<source>Hosting cases:</source>
<translation>Hostowane rozprawy:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="553"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="691"/>
<source>If you&apos;re a CM, enter what cases you are willing to host.</source>
<translation>Jeżeli jesteś zarządcą rozpraw (CM), wpisz jakie rozprawy jesteś chętny hostowania.</translation>
</message>
@@ -514,402 +535,820 @@ Powód: %1</translation>
<context>
<name>Courtroom</name>
<message>
- <location filename="../../src/charselect.cpp" line="69"/>
+ <location filename="../../src/charselect.cpp" line="21"/>
<source>Password</source>
<translation>Hasło</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="75"/>
+ <location filename="../../src/charselect.cpp" line="27"/>
<source>Spectator</source>
- <translation>Widz</translation>
+ <translation>Spektator</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="78"/>
- <location filename="../../src/courtroom.cpp" line="179"/>
+ <location filename="../../src/charselect.cpp" line="30"/>
+ <location filename="../../src/courtroom.cpp" line="175"/>
<source>Search</source>
<translation>Wyszukaj</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="83"/>
+ <location filename="../../src/charselect.cpp" line="35"/>
<source>Passworded</source>
<translation>Zahasłowany</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="87"/>
+ <location filename="../../src/charselect.cpp" line="39"/>
<source>Taken</source>
<translation>Zajęty</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="182"/>
<source>Could not find %1</source>
- <translation>Nie znaleziono %1</translation>
+ <translation type="obsolete">Nie znaleziono %1</translation>
</message>
<message>
+ <location filename="../../src/charselect.cpp" line="232"/>
<source>Generating chars:
%1/%2</source>
- <translation type="vanished">Generowanie postaci:
+ <translation>Generowanie postaci:
%1.%2</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="149"/>
+ <location filename="../../src/courtroom.cpp" line="148"/>
<source>Showname</source>
<translation>Ksywka</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="153"/>
+ <location filename="../../src/courtroom.cpp" line="152"/>
<source>Message</source>
<translation>Wiadomość</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="164"/>
+ <location filename="../../src/courtroom.cpp" line="167"/>
<source>Name</source>
<translation>Nazwa</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="224"/>
+ <location filename="../../src/courtroom.cpp" line="217"/>
<source>Pre</source>
<translation>przed-</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="227"/>
+ <location filename="../../src/courtroom.cpp" line="220"/>
<source>Flip</source>
<translation>Odwróć</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="224"/>
<source>Guard</source>
- <translation type="vanished">Na Służbie (mod)</translation>
+ <translation>Na Służbie (mod)</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="238"/>
- <location filename="../../src/courtroom.cpp" line="720"/>
+ <location filename="../../src/courtroom.cpp" line="228"/>
+ <source>Additive</source>
+ <translatorcomment>I&apos;m not sure about this one.</translatorcomment>
+ <translation>Dodatek</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="233"/>
+ <location filename="../../src/courtroom.cpp" line="815"/>
<source>Casing</source>
<translation>Rozprawa</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="243"/>
+ <location filename="../../src/courtroom.cpp" line="238"/>
<source>Shownames</source>
<translation>Ksywki</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="246"/>
+ <location filename="../../src/courtroom.cpp" line="241"/>
<source>No Interrupt</source>
<translation>Bez ociągania się</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="264"/>
<source>White</source>
- <translation>Biały</translation>
+ <translation type="obsolete">Biały</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="265"/>
<source>Green</source>
- <translation>Zielony</translation>
+ <translation type="obsolete">Zielony</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="266"/>
<source>Red</source>
- <translation>Czerwony</translation>
+ <translation type="obsolete">Czerwony</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="267"/>
<source>Orange</source>
- <translation>Pomarańczowy</translation>
+ <translation type="obsolete">Pomarańczowy</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="268"/>
<source>Blue</source>
- <translation>Niebieski</translation>
+ <translation type="obsolete">Niebieski</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="269"/>
<source>Yellow</source>
- <translation>Żółty</translation>
+ <translation type="obsolete">Żółty</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3500"/>
<source>This does nothing, but there you go.</source>
- <translation>To nic nie robi, ale proszę bardzo.</translation>
+ <translation type="obsolete">To nic nie robi, ale proszę bardzo.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3641"/>
+ <location filename="../../src/courtroom.cpp" line="3344"/>
<source>You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini.
Cases you can load: %1</source>
<translation>Musisz podać nazwę pliku, którego chcesz załadować (rozszerzenie nie potrzebne!) Upewnij się, że jest w folderze `base/cases/` i że jest to poprawnie sformatowane ini.
Rozprawy które możesz załadować: %1</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3669"/>
+ <location filename="../../src/courtroom.cpp" line="3372"/>
<source>Case made by %1.</source>
<translation>Rozprawa zrobiona przez %1.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3679"/>
+ <location filename="../../src/courtroom.cpp" line="3382"/>
<source>Navigate to %1 for the CM doc.</source>
<translation>Przejdź do %1, aby dojść do dokumentu CM.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3702"/>
+ <location filename="../../src/courtroom.cpp" line="3406"/>
<source>Your case &quot;%1&quot; was loaded!</source>
<translation>Twoja rozprawa &quot;%1&quot; została wczytana!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="664"/>
- <location filename="../../src/courtroom.cpp" line="3816"/>
+ <location filename="../../src/courtroom.cpp" line="767"/>
+ <location filename="../../src/courtroom.cpp" line="3504"/>
<source>Server</source>
<translation>Serwer</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="143"/>
+ <source>None</source>
+ <translation>Nic</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="749"/>
+ <source>Hold It!</source>
+ <translation>(Hold It)! Zaczekaj!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="750"/>
+ <location filename="../../src/courtroom.cpp" line="756"/>
+ <location filename="../../src/courtroom.cpp" line="762"/>
+ <source>When this is turned on, your next in-character message will be a shout!</source>
+ <translation>Kiedy to jest włączone, twoja następna wiadomość IC będzie krzykiem!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="755"/>
+ <source>Objection!</source>
+ <translation>(Objection!) Sprzeciw!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="761"/>
+ <source>Take That!</source>
+ <translation>(Take That!) Weź To!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="769"/>
+ <source>Toggle between server chat and global AO2 chat.</source>
+ <translation>Przełączaj pomiędzy czatem serwerowym i globalnym czatem AO2.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="773"/>
+ <location filename="../../src/courtroom.cpp" line="777"/>
+ <location filename="../../src/courtroom.cpp" line="783"/>
+ <location filename="../../src/courtroom.cpp" line="787"/>
+ <source>This will display the animation in the viewport as soon as it is pressed.</source>
+ <translation>To będzie wyświetlać animację w oknie, jak tylko zostanie to wciśnięte.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="781"/>
+ <source>Guilty!</source>
+ <translation>Winny!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="794"/>
+ <source>Bring up the Character Select Screen and change your character.</source>
+ <translation>Wyświetl ekran zmiany postaci i zmień swoją postać.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="800"/>
+ <source>Refresh the theme and update all of the ui elements to match.</source>
+ <translation>Odśwież motyw i uaktualnij wszystkie elementy UI, aby dopasować.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="806"/>
+ <source>Request the attention of the current server&apos;s moderator.</source>
+ <translation>Poproś o uwagę moderatora obecnego serwera.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="812"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation>Umożliwia zmianę różnych aspektów klienta.</translation>
+ </message>
+ <message>
<location filename="../../src/courtroom.cpp" line="818"/>
+ <source>An interface to help you announce a case (you have to be a CM first to be able to announce cases)</source>
+ <translation>Interfejs, który pomoże ci ogłosić rozprawę (musisz być zarządcą rozpraw (CM), aby móc ogłaszać rozprawy)</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="824"/>
+ <source>Switch between Areas and Music lists</source>
+ <translation>Przełącz pomiędzy listami Obszarów i Muzyki</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="829"/>
+ <source>Play a single-shot animation as defined by the emote when checked.</source>
+ <translation>Odegraj pojedyńczą animację, jak zdefiniowano przez emotkę, gdy zaznaczone.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="833"/>
+ <source>If preanim is checked, display the input text immediately as the animation plays concurrently.</source>
+ <translation>Jeśli przed-animacja jest zaznaczona, wyświetl wpisany tekst natychmiastowo, jednocześnie podczas odgrywania animacji.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="837"/>
+ <source>Mirror your character&apos;s emotes when checked.</source>
+ <translation>Odzwierciedlij emotki twojej postaci, gdy zaznaczone.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="841"/>
+ <source>Add text to your last spoken message when checked.</source>
+ <translation>Dodaj tekst do twojej ostatniej wiadomości, gdy zaznaczone.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="845"/>
+ <source>Do not listen to mod calls when checked, preventing them from playing sounds or focusing attention on the window.</source>
+ <translation>Nie słuchaj wezwań moda, gdy zaznaczone, zapobiegając grania dźwięków oraz skupiania uwagi na okienko.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="849"/>
+ <source>Lets you receive case alerts when enabled.
+(You can set your preferences in the Settings!)</source>
+ <translation>Pozwala ci otrzymywać komunikaty rozpraw, gdy włączone.
+(Możesz ustawić swoje preferencje w Ustawieniach!)</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="854"/>
+ <source>Display customized shownames for all users when checked.</source>
+ <translation>Wyświetl niestandardowe ksywki dla wszystkich użytkowników, gdy zaznaczone.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="857"/>
+ <source>Custom Shout!</source>
+ <translation>Niestandardowy Krzyk (sprzeciw)!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="860"/>
+ <source>This will display the custom character-defined animation in the viewport as soon as it is pressed.
+To make one, your character&apos;s folder must contain custom.[webp/apng/gif/png] and custom.[wav/ogg/opus] sound effect</source>
+ <translation>To będzie wyświetlać zdefiniowanej animacji niestandardowej postaci w oknie, jak tylko zostanie to wciśnięte.
+Aby zrobić coś takiego, folder twojej postaci musi zawierać niestandardowe [webp/apng/gif/png] i niestandardowe [wav/ogg/opus] efekty dźwiękowe</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="868"/>
+ <source>Play realization sound and animation in the viewport on the next spoken message when checked.</source>
+ <translation>Zagraj dźwięk realizacji i animację w oknie podczas następnej wiadomości, gdy zaznaczone.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="874"/>
+ <source>Shake the screen on next spoken message when checked.</source>
+ <translation>Wstrząśnij ekranem podczas następnej wiadomości, gdy zaznaczone.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="880"/>
+ <source>Display the list of character folders you wish to mute.</source>
+ <translation>Wyświetl listę folderów postaci, których chcesz zmutować.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="884"/>
+ <location filename="../../src/courtroom.cpp" line="892"/>
+ <source>Increase the health bar.</source>
+ <translation>Zwiększ pasek życia.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="888"/>
+ <location filename="../../src/courtroom.cpp" line="896"/>
+ <source>Decrease the health bar.</source>
+ <translation>Obniż pasek życia.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="900"/>
+ <source>Change the text color of the spoken message.
+You can also select a part of your currently typed message and use the dropdown to change its color!</source>
+ <translation>Zmień kolor tekstu dla twojej wiadomości.
+Możesz również zaznaczyć część twojej obecnie pisanej wiadomości i użyć listy aby zmienić jej kolor!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="913"/>
<source>Back to Lobby</source>
<translation>Powrót do poczekalni</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="270"/>
- <source>Rainbow</source>
- <translation>Tęczowy</translation>
+ <location filename="../../src/courtroom.cpp" line="3090"/>
+ <location filename="../../src/courtroom.cpp" line="4508"/>
+ <location filename="../../src/courtroom.cpp" line="4515"/>
+ <source>has played a song</source>
+ <translation>włączył piosenkę</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="160"/>
- <source>OOC Message</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/courtroom.cpp" line="3224"/>
+ <source>You will now pair up with %1 if they also choose your character in return.</source>
+ <translation>Będziesz teraz w parze z %1, jeśli oni również wybiorą twoją postać.</translation>
+ </message>
+ <message>
+ <source>Rainbow</source>
+ <translation type="obsolete">Tęczowy</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="232"/>
<source>Disable Modcalls</source>
- <translation>Wyłącz wezwania moda</translation>
+ <translation type="obsolete">Wyłącz wezwania moda</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="271"/>
<source>Pink</source>
- <translation>Różowy</translation>
+ <translation type="obsolete">Różowy</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="272"/>
<source>Cyan</source>
- <translation>Turkusowy</translation>
+ <translation type="obsolete">Turkusowy</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="295"/>
+ <location filename="../../src/courtroom.cpp" line="274"/>
<source>% offset</source>
<translation>% wyrówanie</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="646"/>
+ <location filename="../../src/courtroom.cpp" line="277"/>
+ <source>To front</source>
+ <translation>Do przodu</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="278"/>
+ <source>To behind</source>
+ <translation>Do tyłu</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="591"/>
+ <source>Select a character you wish to pair with.</source>
+ <translation>Zaznacz postać, z którą chcesz się sparować.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="596"/>
+ <source>Change the percentage offset of your character&apos;s position from the center of the screen.</source>
+ <translation>Zmień procentową odległość dla pozycji twojej postaci licząc od środka ekranu.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="602"/>
+ <source>Change the order of appearance for your character.</source>
+ <translation>Zmień kolejność występowania dla twojej postaci.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="607"/>
+ <source>Display the list of characters to pair with.</source>
+ <translation>Wyświetl listę postaci do sparowania się z.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="665"/>
+ <source>Oops, you&apos;re muted!</source>
+ <translation>Ups, jesteś zmutowany!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="679"/>
+ <source>Set your character&apos;s emote to play on your next message.</source>
+ <translation>Ustaw emotkę twojej postaci do odegrania podczas następnej wiadomości.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="683"/>
+ <source>Set your character&apos;s supplementary background.</source>
+ <translation>Ustaw uzupełniające tło twojej postaci.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="689"/>
+ <source>Set an &apos;iniswap&apos;, or an alternative character folder to refer to from your current character.
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/iniswaps.ini</source>
+ <translation>Ustaw &apos;iniswap&apos; albo alternatywny folder postaci, aby odnosił się do twojej obecnej postaci.
+Edytuj poprzez pisanie i naciśnięcie enter, [X] aby usunąć. To się zapisuje do base/characters/&lt;charname&gt;/iniswaps.ini</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="698"/>
+ <location filename="../../src/courtroom.cpp" line="715"/>
+ <source>Remove the currently selected iniswap from the list and return to the original character folder.</source>
+ <translation>Usuń obecne zaznaczony iniswap z listy i powróć do pierwotnego foldera postaci.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="706"/>
+ <source>Set a sound effect to play on your next &apos;Preanim&apos;. Leaving it on Default will use the emote-defined sound (if any).
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/soundlist.ini</source>
+ <translation>Ustaw efekt dźwiękowy do zagrania dla twojej następnej &apos;Animacji&apos; Zostawienie to jako domyślne, użyje dźwięku zdefiniowanego przez emotkę (jeśli istnieje).
+Edytuj poprzez pisanie i naciśnięcie enter, [X] aby usunąć. To się zapisuje do base/characters/&lt;charname&gt;/soundlist.ini</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="722"/>
+ <source>Choose an effect to play on your next spoken message.
+The effects are defined in your theme/effects/effects.ini. Your character can define custom effects by
+char.ini [Options] category, effects = &apos;miscname&apos; where it referes to misc/&lt;miscname&gt;/effects.ini to read the effects.</source>
+ <translation>Wybierz efekt dla twojej następnej wiadomości.
+Efekty są zdefiniowane w twoim pliku theme/effect/effects.ini. Twoja postać może zdefiniować niestandardowe efekty przez
+kategorię char.ini [Options], effects = &apos;miscname&apos; gdzie się odnosi do misc/&lt;miscname&gt;/effects.ini, aby przejrzeć efekty.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="742"/>
<source>Music</source>
<translation>Muzyka</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="648"/>
+ <location filename="../../src/courtroom.cpp" line="744"/>
<source>Sfx</source>
<translation>Sfx</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="650"/>
+ <location filename="../../src/courtroom.cpp" line="746"/>
<source>Blips</source>
<translation>Blipy</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="653"/>
<source>Log limit</source>
- <translation>Limit dziennika</translation>
+ <translation type="obsolete">Limit dziennika</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="683"/>
+ <location filename="../../src/courtroom.cpp" line="791"/>
<source>Change character</source>
<translation>Zmiana postaci</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="693"/>
+ <location filename="../../src/courtroom.cpp" line="797"/>
<source>Reload theme</source>
<translation>Odśwież motyw</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="702"/>
+ <location filename="../../src/courtroom.cpp" line="803"/>
<source>Call mod</source>
<translation>Wezwij moda</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="711"/>
+ <location filename="../../src/courtroom.cpp" line="809"/>
<source>Settings</source>
<translation>Ustawienia</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="729"/>
+ <location filename="../../src/courtroom.cpp" line="822"/>
<source>A/M</source>
<translatorcomment>O meaning &apos;Obszar&apos; and M meaning &apos;Muzyka&apos;.</translatorcomment>
<translation>O/M</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="737"/>
+ <location filename="../../src/courtroom.cpp" line="827"/>
<source>Preanim</source>
- <translatorcomment>Sounds weird but I don&apos;t know how to translate it other than this.</translatorcomment>
- <translation>przed-animacja</translation>
+ <translatorcomment>Whatever, I&apos;ll just call it an animation.</translatorcomment>
+ <translation>Animacja</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="914"/>
+ <source>Return back to the server list.</source>
+ <translation>Wróć z powrotem do listy serwerów.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="927"/>
+ <source>Become a spectator. You won&apos;t be able to interact with the in-character screen.</source>
+ <translation>Zostań spektatorem. Nie będziesz mógł wchodzić w interakcję z oknem IC.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="1265"/>
- <location filename="../../src/courtroom.cpp" line="3492"/>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
<source>You were granted the Disable Modcalls button.</source>
- <translation type="unfinished"></translation>
+ <translation>Zostałeś obdarzonym przyciskiem Wyłącz Wezwania Moda.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3310"/>
- <source>You have been banned.</source>
- <translation>Zostałeś zbanowany.</translation>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
+ <location filename="../../src/courtroom.cpp" line="3372"/>
+ <source>CLIENT</source>
+ <translation>KLIENT</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3739"/>
- <source>Too many arguments to save a case! You only need a filename without extension and the courtroom status.</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/courtroom.cpp" line="3011"/>
+ <source>You have been banned.</source>
+ <translation>Zostałeś zbanowany.</translation>
</message>
<message>
<source>You were granted the Guard button.</source>
- <translation type="vanished">Zostałeś obdarzonym przyciskiem Na Służbie.</translation>
+ <translation type="obsolete">Zostałeś obdarzonym przyciskiem Na Służbie.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3506"/>
+ <location filename="../../src/courtroom.cpp" line="3211"/>
<source>You opened the settings menu.</source>
- <translation>Otworzyłeś opcje.</translation>
+ <translation>Otworzyłeś ustawienia.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3519"/>
<source>You will now pair up with </source>
- <translation>Będzie teraz w parze z </translation>
+ <translation type="obsolete">Będzie teraz w parze z </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3521"/>
<source> if they also choose your character in return.</source>
- <translation> jeżeli oni również wybiorą ciebie spowrotem.</translation>
+ <translation type="obsolete"> jeżeli oni również wybiorą ciebie spowrotem.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3527"/>
+ <location filename="../../src/courtroom.cpp" line="3230"/>
<source>You are no longer paired with anyone.</source>
- <translation>Nie jesteś już w parze z kimkolwiek.</translation>
+ <translation>Nie jesteś już w parze z nikim.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3532"/>
+ <location filename="../../src/courtroom.cpp" line="3235"/>
<source>Are you sure you typed that well? The char ID could not be recognised.</source>
<translation>Czy jesteś pewien, że dobrze to napisałeś? ID postaci nie zostało rozpoznane.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3547"/>
+ <location filename="../../src/courtroom.cpp" line="3250"/>
<source>You have set your offset to </source>
<translation>Musisz ustawić swoje wyrównanie do </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3554"/>
+ <location filename="../../src/courtroom.cpp" line="3257"/>
<source>Your offset must be between -100% and 100%!</source>
<translation>Twoje wyrównanie musi być między -100%, a 100%!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3559"/>
+ <location filename="../../src/courtroom.cpp" line="3262"/>
<source>That offset does not look like one.</source>
- <translation>To wyrównanie nie wygląda na takie.</translation>
+ <translation>To wyrównanie nie wygląda na poprawne.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3565"/>
+ <location filename="../../src/courtroom.cpp" line="3268"/>
<source>You switched your music and area list.</source>
<translation>Przełączyłeś swoją listę obszarów i muzyki.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3572"/>
+ <location filename="../../src/courtroom.cpp" line="3275"/>
<source>You have forcefully enabled features that the server may not support. You may not be able to talk IC, or worse, because of this.</source>
- <translation>Włączyłeś funkcje, które ten serwer może nie wspierać. Możliwe że, nie możesz rozmawiać na czacie IC lub gorzej z powodu tego.</translation>
+ <translation>Włączyłeś funkcje, które ten serwer może nie wspierać. Możliwe że, nie możesz rozmawiać na czacie IC lub gorzej z tego powodu.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3586"/>
+ <location filename="../../src/courtroom.cpp" line="3289"/>
<source>Your pre-animations interrupt again.</source>
- <translation>Twoje przed-animacje przerywają tekst spowrotem.</translation>
+ <translation>Twoje animacje przerywają tekst spowrotem.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3589"/>
+ <location filename="../../src/courtroom.cpp" line="3292"/>
<source>Your pre-animations will not interrupt text.</source>
- <translation>Twoje przed-animacje nie będą przerywać tekstu.</translation>
+ <translation>Twoje animacje nie będą przerywać tekstu.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3600"/>
+ <location filename="../../src/courtroom.cpp" line="3303"/>
<source>Couldn&apos;t open chatlog.txt to write into.</source>
<translation>Nie można było otworzyć chatlog.txt, aby pisać w nim.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3613"/>
+ <location filename="../../src/courtroom.cpp" line="3316"/>
<source>The IC chatlog has been saved.</source>
<translation>Dziennik czatu IC został zapisany.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3626"/>
+ <location filename="../../src/courtroom.cpp" line="3329"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely the case file you&apos;re looking for can&apos;t be found in there.</source>
<translation>Nie masz folderu `base/cases/`! Został zrobiony tylko dla ciebie, ale widząc, że ZOSTAŁ zrobiony tylko dla ciebie, prawdopodobnie plik rozpraw, którego szukasz nie został znaleziony tutaj.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3653"/>
+ <location filename="../../src/courtroom.cpp" line="3356"/>
<source>Too many arguments to load a case! You only need one filename, without extension.</source>
<translation>Zbyt dużo parametrów, aby załadować rozprawę! Potrzebujesz tylko jedną nazwę pliku, bez rozszerzenia nazwy pliku.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3714"/>
+ <location filename="../../src/courtroom.cpp" line="3396"/>
+ <location filename="../../src/courtroom.cpp" line="3398"/>
+ <location filename="../../src/evidence.cpp" line="762"/>
+ <location filename="../../src/evidence.cpp" line="764"/>
+ <source>UNKNOWN</source>
+ <translation>NIEZNANE</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3418"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely that you somehow deleted it.</source>
<translation>Nie masz folderu `base/cases/`! Został zrobiony tylko dla ciebie, ale widząc, że ZOSTAŁ zrobiony tylko dla ciebie, prawdopodobnie jakoś usunąłeś go.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3729"/>
+ <location filename="../../src/courtroom.cpp" line="3433"/>
<source>You need to give a filename to save (extension not needed) and the courtroom status!</source>
<translation>Musisz podać nazwę pliku, aby go zapisać (rozszerzenie nie potrzebne) i status sali sądowej!</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="3443"/>
<source>Too many arguments to save a case! You only need a filename without extension and the courtroom status!</source>
- <translation type="vanished">Zbyt dużo parametrów, aby zapisać rozprawę! Potrzebujesz tylko jedną nazwę pliku, bez rozszerzenia nazwy pliku i statusu sali sądowej!</translation>
+ <translation>Zbyt dużo parametrów, aby zapisać rozprawę! Potrzebujesz tylko jedną nazwę pliku, bez rozszerzenia nazwy pliku i statusu sali sądowej!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3766"/>
+ <location filename="../../src/courtroom.cpp" line="3470"/>
<source>Succesfully saved, edit doc and cmdoc link on the ini!</source>
<translation>Zapisano pomyślnie, edytuj dokument i link cmdoc w .ini!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3806"/>
+ <location filename="../../src/courtroom.cpp" line="3497"/>
<source>Master</source>
- <translation>Główny</translation>
+ <translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4309"/>
+ <location filename="../../src/courtroom.cpp" line="3997"/>
+ <source>Expand All Categories</source>
+ <translation>Rozwiń Wszystkie Kategorie</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3999"/>
+ <source>Collapse All Categories</source>
+ <translation>Zwiń Wszystkie Kategorie</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4003"/>
+ <source>Fade Out Previous</source>
+ <translation>Zanikaj poprzednie</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4009"/>
+ <source>Fade In</source>
+ <translation>Rozjaśnij</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4015"/>
+ <source>Synchronize</source>
+ <translation>Zsynchronizuj</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4285"/>
+ <source>Default</source>
+ <translation>Domyślne</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4446"/>
<source>Reason:</source>
<translation>Powód:</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4310"/>
+ <location filename="../../src/courtroom.cpp" line="4447"/>
<source>Call Moderator</source>
<translation>Wezwij Moderatora</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4455"/>
+ <location filename="../../src/courtroom.cpp" line="4459"/>
<source>Error</source>
<translation>Błąd</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
+ <location filename="../../src/courtroom.cpp" line="4455"/>
<source>You must provide a reason.</source>
<translation>Musisz podać przyczynę.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4459"/>
<source>The message is too long.</source>
- <translation>Ta wiadomość jest za długa.</translation>
+ <translation>Ta wiadomość jest zbyt długa.</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="25"/>
<source>Choose...</source>
- <translation>Wybierz...</translation>
+ <translation type="obsolete">Wybierz...</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="17"/>
+ <source>Present this piece of evidence to everyone on your next spoken message</source>
+ <translation>Zaprezentuj ten dowód dla każdego podczas twojej następnej wiadomości</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="24"/>
+ <source>Save evidence to an .ini file.</source>
+ <translation>Zapisz dowody do pliku .ini.</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="208"/>
+ <location filename="../../src/evidence.cpp" line="26"/>
+ <source>Load evidence from an .ini file.</source>
+ <translation>Załaduj dowody z pliku .ini.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="31"/>
+ <source>Destroy this piece of evidence</source>
+ <translation>Zniszcz ten dowód</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="34"/>
+ <source>Choose..</source>
+ <translation>Wybierz..</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="37"/>
+ <source>Close the evidence display/editing overlay.
+You will be prompted if there&apos;s any unsaved changes.</source>
+ <translation>Zamknij wyświetlanie/edytowanie okienka dowodów.
+Zostaniesz poproszony, jeśli są jakieś niezapisane zmiany.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="40"/>
+ <source>Save any changes made to this piece of evidence and send them to server.</source>
+ <translation>Zapisz zmiany do tego dowodu i wyślij je do serwera.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="48"/>
+ <source>Double-click to edit. Press [X] to update your changes.</source>
+ <translation>Kliknij dwa razy, aby edytować. Naciśnij [X], by uaktualnić zmiany.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="104"/>
+ <source>Bring up the Evidence screen.</source>
+ <translation>Wyświetl ekran dowodów.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="147"/>
+ <source>Switch evidence to private inventory.</source>
+ <translation>Przełącz dowody do prywatnego ekwipunku.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="151"/>
+ <source>Switch evidence to global inventory.</source>
+ <translation>Przełącz dowody do globalnego ekwipunku.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="158"/>
+ <location filename="../../src/evidence.cpp" line="617"/>
+ <source>Transfer evidence to private inventory.</source>
+ <translation>Przenieś dowody do prywatnego ekwipunku.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="163"/>
+ <location filename="../../src/evidence.cpp" line="627"/>
+ <source>Transfer evidence to global inventory.</source>
+ <translation>Przenieś dowody do globalnego ekwipunku.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="263"/>
+ <source>The piece of evidence you&apos;ve been editing has changed.</source>
+ <translation>Ten dowód, który edytujesz, zmienił się.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="264"/>
+ <source>Do you wish to keep your changes?</source>
+ <translation>Czy chcesz zatrzymać zmiany?</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="265"/>
+ <source>Name: %1
+Image: %2
+Description:
+%3</source>
+ <translation>Nazwa: %1
+Obraz: %2
+Opis:
+%3</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="387"/>
<source>Images (*.png)</source>
- <translation>Plik obrazu (*.png)</translation>
+ <translation>Obrazy (*.png)</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="456"/>
+ <location filename="../../src/evidence.cpp" line="460"/>
+ <location filename="../../src/evidence.cpp" line="463"/>
+ <source>Double-click to edit...</source>
+ <translation>Kliknij dwa razy, aby edytować...</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="280"/>
+ <location filename="../../src/evidence.cpp" line="478"/>
<source>Add new evidence...</source>
<translation>Dodaj nowe dowody...</translation>
</message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="556"/>
+ <source>Evidence has been modified.</source>
+ <translation>Dowody zostały zmodyfikowane.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="557"/>
+ <source>Do you want to save your changes?</source>
+ <translation>Czy chcesz zapisać zmiany?</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="619"/>
+ <source>Current evidence is global. Click to switch to private.</source>
+ <translation>Obecne dowody są globalne. Kliknij, aby przełączyć na prywatne.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="629"/>
+ <source>Current evidence is private. Click to switch to global.</source>
+ <translation>Obecne dowody są prywatne. Kliknij, aby przełączyć na globalne.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="659"/>
+ <source>&quot;%1&quot; has been transferred.</source>
+ <translation>&quot;%1&quot; został przeniesiony.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="722"/>
+ <source>Save Inventory</source>
+ <translation>Zapisz ekwipunek</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="722"/>
+ <location filename="../../src/evidence.cpp" line="748"/>
+ <source>Ini Files (*.ini)</source>
+ <translation>Pliki ini (*.ini)</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="748"/>
+ <source>Open Inventory</source>
+ <translation>Otwórz ekwipunek</translation>
+ </message>
</context>
<context>
<name>Lobby</name>
@@ -919,54 +1358,93 @@ Rozprawy które możesz załadować: %1</translation>
<translation></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="29"/>
+ <location filename="../../src/lobby.cpp" line="31"/>
+ <source>Search</source>
+ <translation>Szukaj</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="39"/>
<source>Name</source>
<translation>Nazwa</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="82"/>
+ <location filename="../../src/lobby.cpp" line="94"/>
<source>It doesn&apos;t look like your client is set up correctly.
Did you download all resources correctly from tiny.cc/getao, including the large &apos;base&apos; folder?</source>
<translation>Wygłąda na to, że twój klient nie jest ustawiony poprawnie.
Czy pobrałeś wszystkie zasoby poprawnie z tiny.cc/getao, włączając duży folder &apos;base&apos;?</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="111"/>
+ <location filename="../../src/lobby.cpp" line="123"/>
<source>Version: %1</source>
<translation>Wersja: %1</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="155"/>
+ <location filename="../../src/lobby.cpp" line="129"/>
+ <source>Settings</source>
+ <translation>Ustawienia</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="132"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation>Umożliwia zmianę różnych aspektów klienta.</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="176"/>
<source>Loading</source>
<translation>Ładowanie</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="159"/>
+ <location filename="../../src/lobby.cpp" line="180"/>
<source>Cancel</source>
<translation>Anuluj</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="279"/>
- <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</source>
- <translation type="unfinished"></translation>
+ <location filename="../../src/lobby.cpp" line="365"/>
+ <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;Client development:&lt;/b&gt;&lt;br&gt;Cents02, in1tiate, raidensnake, windrammer&lt;p&gt;&lt;b&gt;QA testing:&lt;/b&gt;&lt;br&gt;CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;CrazyJC (2.8 release director) and MaximumVolty (2.8 release promotion); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!&lt;p&gt;The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.&lt;p&gt;Running on Qt version %2 with the %3 audio engine.&lt;p&gt;Built on %4</source>
+ <translation>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;Symulator dramy sądowej&lt;p&gt;&lt;b&gt;Kod źródłowy:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Główny rozwój:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;Rozwój Klienta:&lt;/b&gt;&lt;br&gt;Cents02, in1tiate, raidensnake, windrammer&lt;p&gt;&lt;b&gt;Testowanie QA:&lt;/b&gt;&lt;br&gt;CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso&lt;p&gt;&lt;b&gt;Szczególne podziękowania:&lt;/b&gt;&lt;br&gt;CrazyJC (dyrektor wydania 2.8) and MaximumVolty (promocja wydania 2.8); Remy, Hibiki, court-records.net (sprite&apos;y); Qubrick (webAO); Rue (strona internetowa); Draxirch (design UI); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); hostom serwerów, mistrzom gier, twórcom rozpraw, twórcom kontentu, i dla całej społeczności AO2!&lt;p&gt;Attorney Online sieciowy projekt wizualnej powieści ma prawa autorskie (c) 2016-2020 Attorney Online developerzy. Dotyczy licencji open-source. Wszystkie inne własności należą do ich odpiowiednich właścicieli.&lt;p&gt;Działa na wersji QT %2 z %3 silnikiem audio.&lt;p&gt;Zbudowany na %4</translation>
+ </message>
+ <message>
+ <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;2.8 Major Release development:&lt;/b&gt;&lt;br&gt;Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;2.8 Quality Assurance:&lt;/b&gt;&lt;br&gt;WillDean, Captain N, Mr M, Riel, Seimmet, Fury McFlurry,CedricDewitt, Chewable Tablets, Fantos, Futugaze,Geck, Minx, Pandae, Sierra, CrazyJC, CaseyMayCazy,GreenBowers, Robotic Overlord, Veritas, Gin-Gi&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, the AO2 community, server hosts, game masters,case makers, content creators and players!</source>
+ <translation type="obsolete">&lt;h2&gt;Attorney Online %1&lt;/h2&gt;Symulator dramy sądowej&lt;p&gt;&lt;b&gt;Kod źródłowy:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Główny rozwój:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Główny rozwój nad wydaniem 2.8:&lt;/b&gt;&lt;br&gt;Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;Zapewnienie jakości 2.8:&lt;/b&gt;&lt;br&gt;WillDean, Captain N, Mr M, Riel, Seimmet, Fury McFlurry,CedricDewitt, Chewable Tablets, Fantos, Futugaze,Geck, Minx, Pandae, Sierra, CrazyJC, CaseyMayCazy,GreenBowers, Robotic Overlord, Veritas, Gin-Gi&lt;p&gt;&lt;b&gt;Szczególne podziękowania:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, społeczności AO2, hostów serwerów, mistrzów gier, twórców rozpraw, twórców kontentu i dla graczy!</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="398"/>
+ <source>About</source>
+ <translation>Opis</translation>
</message>
<message>
<source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy</source>
- <translation type="vanished">&lt;h2&gt;Attorney Online: %1&lt;/h2&gt;Symulator dramy sądowej&lt;p&gt;&lt;b&gt;Kod żródłowy:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Główny rozwój:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Szczególne podziękowania:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy</translation>
+ <translation type="obsolete">&lt;h2&gt;Attorney Online: %1&lt;/h2&gt;Symulator dramy sądowej&lt;p&gt;&lt;b&gt;Kod żródłowy:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Główny rozwój:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Szczególne podziękowania:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="395"/>
+ <location filename="../../src/lobby.cpp" line="540"/>
<source>Online: %1/%2</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="121"/>
- <location filename="../../src/lobby.cpp" line="327"/>
+ <location filename="../../src/lobby.cpp" line="142"/>
+ <location filename="../../src/lobby.cpp" line="436"/>
<source>Offline</source>
<translation></translation>
</message>
</context>
<context>
+ <name>chatlogpiece</name>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="5"/>
+ <location filename="../../src/chatlogpiece.cpp" line="6"/>
+ <location filename="../../src/chatlogpiece.cpp" line="7"/>
+ <source>UNKNOWN</source>
+ <translation>NIEZNANE</translation>
+ </message>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="55"/>
+ <source> has played a song: </source>
+ <translation> włączył piosenkę: </translation>
+ </message>
+</context>
+<context>
<name>debug_functions</name>
<message>
<location filename="../../src/debug_functions.cpp" line="10"/>
@@ -979,7 +1457,7 @@ Czy pobrałeś wszystkie zasoby poprawnie z tiny.cc/getao, włączając duży fo
<translation>Błąd</translation>
</message>
<message>
- <location filename="../../src/debug_functions.cpp" line="26"/>
+ <location filename="../../src/debug_functions.cpp" line="25"/>
<source>Notice</source>
<translation>Ogłoszenie</translation>
</message>
diff --git a/resource/translations/ao_pt.qm b/resource/translations/ao_pt.qm
index 242917ff..dc8bc70d 100644
--- a/resource/translations/ao_pt.qm
+++ b/resource/translations/ao_pt.qm
Binary files differ
diff --git a/resource/translations/ao_pt.ts b/resource/translations/ao_pt.ts
index 824c81ee..a3991f8b 100644
--- a/resource/translations/ao_pt.ts
+++ b/resource/translations/ao_pt.ts
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
-<TS version="2.1" language="pt_BR">
+<TS version="2.0" language="pt_BR">
<context>
<name>AOApplication</name>
<message>
@@ -9,80 +9,79 @@
<translation>Desconectado do servidor.</translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="151"/>
+ <location filename="../../src/aoapplication.cpp" line="152"/>
<source>Error connecting to master server. Will try again in %1 seconds.</source>
<translation>Erro ao conectar ao servidor principal. Testando novamente em %1 segundos.</translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="156"/>
+ <location filename="../../src/aoapplication.cpp" line="157"/>
<source>There was an error connecting to the master server.
We deploy multiple master servers to mitigate any possible downtime, but the client appears to have exhausted all possible methods of finding and connecting to one.
Please check your Internet connection and firewall, and please try again.</source>
<translation>Ocorreu um erro ao obter a lista de servidores. Verifique sua conexão à Internet e firewall e tente novamente.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="108"/>
+ <location filename="../../src/packet_distribution.cpp" line="94"/>
<source>Outdated version! Your version: %1
Please go to aceattorneyonline.com to update.</source>
<translation>Versão desatualizada! Sua versão: %1
Acesse aceattorneyonline.com para atualizar.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="115"/>
<source>You have been exiled from AO.
Have a nice day.</source>
- <translation>Você foi exilado do Attorney Online.
+ <translation type="obsolete">Você foi exilado do Attorney Online.
Tenha um bom dia.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="258"/>
+ <location filename="../../src/packet_distribution.cpp" line="253"/>
<source>Attorney Online 2</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="282"/>
+ <location filename="../../src/packet_distribution.cpp" line="281"/>
<source>Loading</source>
<translation>Carregando</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="326"/>
- <location filename="../../src/packet_distribution.cpp" line="457"/>
+ <location filename="../../src/packet_distribution.cpp" line="334"/>
+ <location filename="../../src/packet_distribution.cpp" line="483"/>
<source>Loading chars:
%1/%2</source>
<translation>Carregando personagens:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="373"/>
+ <location filename="../../src/packet_distribution.cpp" line="381"/>
<source>Loading evidence:
%1/%2</source>
<translation>Carregando evidências:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="408"/>
- <location filename="../../src/packet_distribution.cpp" line="506"/>
+ <location filename="../../src/packet_distribution.cpp" line="416"/>
+ <location filename="../../src/packet_distribution.cpp" line="510"/>
<source>Loading music:
%1/%2</source>
<translation>Carregando músicas:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="635"/>
+ <location filename="../../src/packet_distribution.cpp" line="692"/>
<source>You have been kicked from the server.
Reason: %1</source>
<translation>Você foi expulso do servidor.
Motivo: %1</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="643"/>
+ <location filename="../../src/packet_distribution.cpp" line="700"/>
<source>You have been banned from the server.
Reason: %1</source>
<translation>Você foi banido do servidor.
Motivo: %1</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="651"/>
+ <location filename="../../src/packet_distribution.cpp" line="708"/>
<source>You are banned on this server.
Reason: %1</source>
<translation>Você foi banido neste servidor.
@@ -127,779 +126,1280 @@ Motivo: %1</translation>
<translation>Precisa-se de Estenógrafo</translation>
</message>
<message>
- <location filename="../../src/aocaseannouncerdialog.cpp" line="66"/>
<source>Witness needed</source>
- <translation>Precisa-se de Testemunha</translation>
+ <translation type="obsolete">Precisa-se de Testemunha</translation>
</message>
</context>
<context>
<name>AOOptionsDialog</name>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="11"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="12"/>
<source>Settings</source>
<translation>Configurações</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="48"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="46"/>
<source>Gameplay</source>
<translation>Jogabilidade</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="61"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="62"/>
<source>Theme:</source>
<translation>Tema visual:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="63"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="64"/>
<source>Sets the theme used in-game. If the new theme changes the lobby&apos;s look as well, you&apos;ll need to reload the lobby for the changes to take effect, such as by joining a server and leaving it.</source>
<translation>Define o tema usado no jogo. Se o novo tema alterar a aparência do lobby, será necessário recarregá-lo para que as alterações tenham efeito, como ingressar em um servidor e deixá-lo.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="620"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="95"/>
<source>Log goes downwards:</source>
<translation>Log vai para baixo:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="622"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="97"/>
<source>If ticked, new messages will appear at the bottom (like the OOC chatlog). The traditional (AO1) behaviour is equivalent to this being unticked.</source>
<translatorcomment>Removed the part about AO1 behaviour, nobody cares boomer.</translatorcomment>
<translation>Se selecionado, novas mensagens irão aparecer na parte inferior (assim como o chat OOC).</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="634"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="110"/>
<source>Log length:</source>
<translation>Tamanho do log:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="635"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="111"/>
<source>The amount of messages the IC chatlog will keep before deleting older messages. A value of 0 or below counts as &apos;infinite&apos;.</source>
<translation>A quantidade de mensagens que o chat do IC manterá antes de excluir as mensagens mais antigas. Um valor igual ou inferior a 0 conta como &apos;infinito&apos;.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="93"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="133"/>
<source>Default username:</source>
<translation>Nome de usuário padrão:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="95"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="135"/>
<source>Your OOC name will be automatically set to this value when you join a server.</source>
<translation>Seu nome OOC será automaticamente definido com esse valor quando você ingressar em um servidor.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="107"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="148"/>
<source>Custom shownames:</source>
<translation>Nomes personalizados:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="150"/>
<source>Gives the default value for the in-game &apos;Custom shownames&apos; tickbox, which in turn determines whether the client should display custom in-character names.</source>
<translatorcomment>&apos;Custom shownames&apos; changed to &apos;Shownames&apos; because that&apos;s the actual name</translatorcomment>
- <translation type="obsolete">Fornece o valor padrão para a caixa de seleção &apos;Shownames&apos; no jogo, que determina se o cliente deve exibir nomes personalizados nos caracteres.</translation>
+ <translation>Fornece o valor padrão para a caixa de seleção &apos;Shownames&apos; no jogo, que determina se o cliente deve exibir nomes personalizados nos personagens.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="127"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="170"/>
<source>Backup MS:</source>
<translation>MS de backup:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="129"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="172"/>
<source>If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address.</source>
<translation>Se as pesquisas internas do servidor falharem, o jogo tentará o endereço fornecido aqui e o usará como um endereço de servidor principal de backup.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="141"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="185"/>
<source>Discord:</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="143"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="187"/>
<source>Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for.</source>
<translation>Permite que outras pessoas no Discord vejam em que servidor você está, qual personagem está jogando e há quanto tempo está jogando.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="155"/>
<source>Allow Shake/Flash:</source>
- <translation>Permitir Shake/Flash:</translation>
+ <translation type="obsolete">Permitir Shake/Flash:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="157"/>
<source>Allows screenshaking and flashing. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
- <translation>Permite agitar e piscar. Desative isso se você tiver preocupações ou problemas com fotosensibilidade e/ou convulsões.</translation>
+ <translation type="obsolete">Permite agitar e piscar. Desative isso se você tiver preocupações ou problemas com fotosensibilidade e/ou convulsões.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="168"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="200"/>
<source>Language:</source>
<translation>Língua:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="170"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="202"/>
<source>Sets the language if you don&apos;t want to use your system language.</source>
<translation>Define o idioma se você não quiser usar o idioma do sistema.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="202"/>
<source>Punctuation delay modifier. Enable it for the blips to slow down on punctuations.</source>
- <translation>Habilite para adicionar uma pequena pausa nos sinais de pontuação.</translation>
+ <translation type="obsolete">Habilite para adicionar uma pequena pausa nos sinais de pontuação.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="212"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="340"/>
<source>Callwords</source>
<translation>Palavras-chave</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="239"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="367"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!&lt;br&gt;Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Digite quantas palavras-chave você desejar. Estes não diferenciam maiúsculas de minúsculas. Certifique-se de deixar cada palavra chave em sua própria linha!&lt;br&gt;Não deixe uma linha com um espaço no final - você será alertado toda vez que alguém usar um espaço em suas mensagens.&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="249"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="377"/>
<source>Audio</source>
<translation>Áudio</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="262"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="391"/>
<source>Audio device:</source>
<translation>Dispositivo de áudio:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="263"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="392"/>
<source>Sets the audio device for all sounds.</source>
<translation>Define o dispositivo de áudio para todos os sons.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="304"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="435"/>
<source>Music:</source>
<translation>Música:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="436"/>
<source>Sets the music&apos;s default volume.</source>
- <translation type="obsolete">Define o volume padrão da música.</translation>
+ <translation>Define o volume padrão da música.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="318"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="450"/>
<source>SFX:</source>
<translation>SFX:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="452"/>
<source>Sets the SFX&apos;s default volume. Interjections and actual sound effects count as &apos;SFX&apos;.</source>
- <translation type="obsolete">Define o volume padrão do SFX. Interjeições e efeitos sonoros reais contam como &apos;SFX&apos;.</translation>
+ <translation>Define o volume padrão do SFX. Interjeições e efeitos sonoros reais contam como &apos;SFX&apos;.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="109"/>
<source>Gives the default value for the in-game &apos;Custom shownames&apos; checkbox, which in turn determines whether the client should display custom in-character names.</source>
- <translation>Fornece o valor padrão para a caixa de seleção &apos;Shownames&apos; no jogo, que determina se o cliente deve exibir nomes personalizados nos caracteres.</translation>
+ <translation type="obsolete">Fornece o valor padrão para a caixa de seleção &apos;Shownames&apos; no jogo, que determina se o cliente deve exibir nomes personalizados nos caracteres.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="193"/>
<source>Slower text speed:</source>
- <translation>Texto mais lento:</translation>
+ <translation type="obsolete">Texto mais lento:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="194"/>
<source>Set the text speed to be the same as the AA games.</source>
- <translation>A velocidade do texto será a mesma dos jogos AA.</translation>
+ <translation type="obsolete">A velocidade do texto será a mesma dos jogos AA.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="201"/>
<source>Blip delay on punctuations:</source>
- <translation>Atraso na pontuação:</translation>
+ <translation type="obsolete">Atraso na pontuação:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="305"/>
<source>Sets the default volume for music.</source>
- <translation>Define o volume padrão da música.</translation>
+ <translation type="obsolete">Define o volume padrão da música.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="320"/>
<source>Sets the default volume for SFX sounds, like interjections or other character sound effects.</source>
- <translation>Define o volume padrão para sons SFX, como interjeições ou outros efeitos sonoros de personagens.</translation>
+ <translation type="obsolete">Define o volume padrão para sons SFX, como interjeições ou outros efeitos sonoros de personagens.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="333"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="466"/>
<source>Blips:</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="335"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="468"/>
<source>Sets the volume of the blips, the talking sound effects.</source>
<translation>Define o volume dos blips, os efeitos sonoros de fala.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="354"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="490"/>
<source>Blip rate:</source>
<translation>Taxa de blip:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="356"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="492"/>
<source>Sets the delay between playing the blip sounds.</source>
<translation>Define o atraso entre a reprodução dos sons de blip.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="367"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="507"/>
<source>Blank blips:</source>
<translation>Blips em branco:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="369"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="509"/>
<source>If true, the game will play a blip sound even when a space is &apos;being said&apos;.</source>
<translation>Se ativado, o jogo emitirá um sinal sonoro, mesmo quando um espaço estiver sendo &quot;dito&quot;.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="380"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="521"/>
<source>Enable Looping SFX:</source>
<translation>Ative o SFX em loop:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="381"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="522"/>
<source>If true, the game will allow looping sound effects to play on preanimations.</source>
<translation>Se ativado, o jogo permitirá que efeitos sonoros em loop sejam reproduzidos em pré-animações.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="392"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="534"/>
<source>Kill Music On Objection:</source>
<translation>Parar a música no protesto:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="394"/>
<source>If true, the game will stop music when someone objects, like in the actual games.</source>
- <translation>Se ativado, o jogo interrompe a música quando alguém protestar , como nos jogos reais.</translation>
+ <translation type="obsolete">Se ativado, o jogo interrompe a música quando alguém protestar , como nos jogos reais.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="208"/>
+ <source> - Keep current setting</source>
+ <translation> - Mantenha as configurações atuais</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="222"/>
+ <source>Allow Screenshake:</source>
+ <translation>Permitir screenshake:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="224"/>
+ <source>Allows screenshaking. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
+ <translation>Permite o tremor de tela (AVISO: Pode causar convulsões devido à imagens tremidas).</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="236"/>
+ <source>Allow Effects:</source>
+ <translation>Permitir efeitos:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="238"/>
+ <source>Allows screen effects. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
+ <translation>Permite efeitos de tela (AVISO: Pode causar convulsões devido à imagens tremidas)..</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="250"/>
+ <source>Network Frame Effects:</source>
+ <translation>Envie efeitos para o servidor:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="251"/>
+ <source>Send screen-shaking, flashes and sounds as defined in the char.ini over the network. Only works for servers that support this functionality.</source>
+ <translation>Envie vibrações, flashes e sons na tela, conforme definido no char.ini pela rede. Funciona apenas para servidores que suportam essa funcionalidade.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="264"/>
+ <source>Colors in IC Log:</source>
+ <translation>Cores no Log IC:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="408"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="266"/>
+ <source>Use the markup colors in the server IC chatlog.</source>
+ <translation>Permitir cores no chat do IC no servidor.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="277"/>
+ <source>Sticky Sounds:</source>
+ <translation type="unfinished">Manter sons:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="279"/>
+ <source>Turn this on to prevent the sound dropdown from clearing the sound after playing it.</source>
+ <translation type="unfinished">Marque para evitar que o som do menu suspenso apague o som após a reprodução.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="291"/>
+ <source>Sticky Effects:</source>
+ <translation type="unfinished">Manter efeitos:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="293"/>
+ <source>Turn this on to prevent the effects dropdown from clearing the effect after playing it.</source>
+ <translation type="unfinished">Ative-o para impedir que o menu suspenso de efeito exclua o efeito após reproduzi-lo.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="306"/>
+ <source>Sticky Preanims:</source>
+ <translation type="unfinished">Manter preanims:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="308"/>
+ <source>Turn this on to prevent preanimation checkbox from clearing after playing the emote.</source>
+ <translation type="unfinished">Ative-o para impedir que a caixa de seleção de pré-animação seja desmarcada após a execução do emote.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="320"/>
+ <source>Custom Chatboxes:</source>
+ <translation>Caixas de bate-papo personalizadas:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="322"/>
+ <source>Turn this on to allow characters to define their own custom chat box designs.</source>
+ <translation>Ative isso para permitir que os personagens tenham as suas próprias caixas de bate-papo personalizadas.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="500"/>
+ <source>Play a blip sound &quot;once per every X symbols&quot;, where X is the blip rate.</source>
+ <translation>Reproduz um som de blip &quot;uma vez para cada símbolo X&quot;, em que X é a taxa de blip.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="536"/>
+ <source>If true, AO2 will stop the music for you when you or someone else does &apos;Objection!&apos;.</source>
+ <translation>Se ativado, o AO2 interromperá a música quando você ou outra pessoa fizer uma &apos;Protesto!&apos;.</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="548"/>
<source>Casing</source>
<translation>Caso</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="424"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="565"/>
<source>This server supports case alerts.</source>
<translation>Este servidor suporta anúncios de casos.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="427"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="568"/>
<source>This server does not support case alerts.</source>
<translation>Este servidor não suporta alertas de caso.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="428"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="569"/>
<source>Pretty self-explanatory.</source>
<translation>Bastante auto-explicativo.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="436"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="578"/>
<source>Casing:</source>
<translation>Caso:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="438"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="580"/>
<source>If checked, you will get alerts about case announcements.</source>
<translation>Se marcado, você será alertado quando houverem anúncios de casos.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="451"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="596"/>
<source>Defense:</source>
<translation>Defesa:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="452"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="597"/>
<source>If checked, you will get alerts about case announcements if a defense spot is open.</source>
<translation>Se marcado, você receberá alertas sobre os anúncios de casos, se um ponto de defesa estiver aberto.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="465"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="611"/>
<source>Prosecution:</source>
<translation>Promotor:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="467"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="613"/>
<source>If checked, you will get alerts about case announcements if a prosecutor spot is open.</source>
<translation>Se marcado, você receberá alertas sobre os anúncios de casos, se uma posição de promotor estiver disponível.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="480"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="627"/>
<source>Judge:</source>
<translation>Juíz:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="481"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="628"/>
<source>If checked, you will get alerts about case announcements if the judge spot is open.</source>
<translation>Se marcado, você receberá alertas sobre os anúncios de casos, se o local do juíz: estiver aberto.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="494"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="642"/>
<source>Juror:</source>
<translation>Jurado:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="495"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="643"/>
<source>If checked, you will get alerts about case announcements if a juror spot is open.</source>
<translation>Se marcado, você receberá alertas sobre os anúncios de casos, se um local do jurado estiver aberto.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="508"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="657"/>
<source>Stenographer:</source>
<translation>Estenógrafo:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="510"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="659"/>
<source>If checked, you will get alerts about case announcements if a stenographer spot is open.</source>
<translation>Se marcado, você receberá alertas sobre anúncios de casos, se um local de estenógrafo estiver aberto.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="523"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="673"/>
<source>CM:</source>
<translation>CM:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="525"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="675"/>
<source>If checked, you will appear amongst the potential CMs on the server.</source>
<translation>Se marcado, você aparecerá entre os CMs possíveis no servidor.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="536"/>
<source>Witness:</source>
- <translation>Testemunha:</translation>
+ <translation type="obsolete">Testemunha:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="538"/>
<source>If checked, you will appear amongst the potential witnesses on the server.</source>
- <translation>Se marcado, você aparecerá entre as testemunhas em potencial no servidor.</translation>
+ <translation type="obsolete">Se marcado, você aparecerá entre as testemunhas em potencial no servidor.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="551"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="689"/>
<source>Hosting cases:</source>
<translation>Casos:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="553"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="691"/>
<source>If you&apos;re a CM, enter what cases you are willing to host.</source>
<translation>Se você é um CM, insira os casos que deseja hospedar.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="568"/>
- <source>IC Log</source>
- <translation></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="581"/>
<source>Colorful IC log:</source>
- <translation>Log IC colorido:</translation>
+ <translation type="obsolete">Log IC colorido:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="583"/>
<source>Enables colored text in the log.</source>
- <translation>Ativa o texto colorido no log.</translation>
+ <translation type="obsolete">Ativa o texto colorido no log.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="594"/>
<source>Only inline coloring:</source>
- <translation>Somente coloração em linha:</translation>
+ <translation type="obsolete">Somente coloração em linha:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="596"/>
<source>Only inline coloring will be shown such as &lt;&gt;,|| etc.</source>
- <translation>Somente a coloração em linha será mostrada como &lt;&gt;, ||, etc.</translation>
+ <translation type="obsolete">Somente a coloração em linha será mostrada como &lt;&gt;, ||, etc.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="606"/>
<source>Mirror IC log:</source>
- <translation>O log IC reflete interrupções:</translation>
+ <translation type="obsolete">O log IC reflete interrupções:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="608"/>
<source>IC log will mirror the IC box. Meaning that if somebody gets interrupted nobody will know what they wanted to say. Enable for a more realistic experience.</source>
- <translation>O log IC espelhará o chat IC Significando que se alguém for interrompido, ninguém saberá o que queria dizer. Habilite para uma experiência mais realista.</translation>
+ <translation type="obsolete">O log IC espelhará o chat IC Significando que se alguém for interrompido, ninguém saberá o que queria dizer. Habilite para uma experiência mais realista.</translation>
</message>
</context>
<context>
<name>Courtroom</name>
<message>
- <location filename="../../src/charselect.cpp" line="69"/>
+ <location filename="../../src/charselect.cpp" line="21"/>
<source>Password</source>
<translation>Senha</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="75"/>
+ <location filename="../../src/charselect.cpp" line="27"/>
<source>Spectator</source>
<translation>Espectador</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="78"/>
- <location filename="../../src/courtroom.cpp" line="179"/>
+ <location filename="../../src/charselect.cpp" line="30"/>
+ <location filename="../../src/courtroom.cpp" line="175"/>
<source>Search</source>
<translation>Pesquisar</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="83"/>
+ <location filename="../../src/charselect.cpp" line="35"/>
<source>Passworded</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="87"/>
+ <location filename="../../src/charselect.cpp" line="39"/>
<source>Taken</source>
<translation>Em uso</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="182"/>
+ <location filename="../../src/charselect.cpp" line="232"/>
+ <source>Generating chars:
+%1/%2</source>
+ <translation>Gerando personagens:
+%1/%2</translation>
+ </message>
+ <message>
<source>Could not find %1</source>
- <translation>Não foi possível encontrar %1</translation>
+ <translation type="obsolete">Não foi possível encontrar %1</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="149"/>
+ <location filename="../../src/courtroom.cpp" line="148"/>
<source>Showname</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="153"/>
+ <location filename="../../src/courtroom.cpp" line="152"/>
<source>Message</source>
<translation>Mensagem</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="160"/>
<source>OOC Message</source>
- <translation>Mensagem OOC</translation>
+ <translation type="obsolete">Mensagem OOC</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="164"/>
+ <location filename="../../src/courtroom.cpp" line="167"/>
<source>Name</source>
<translation>Nome</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="224"/>
+ <location filename="../../src/courtroom.cpp" line="217"/>
<source>Pre</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="227"/>
+ <location filename="../../src/courtroom.cpp" line="220"/>
<source>Flip</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="232"/>
- <source>Disable Modcalls</source>
- <translation></translation>
- </message>
- <message>
- <location filename="../../src/courtroom.cpp" line="238"/>
- <location filename="../../src/courtroom.cpp" line="720"/>
+ <location filename="../../src/courtroom.cpp" line="233"/>
+ <location filename="../../src/courtroom.cpp" line="815"/>
<source>Casing</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="243"/>
+ <location filename="../../src/courtroom.cpp" line="238"/>
<source>Shownames</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="246"/>
+ <location filename="../../src/courtroom.cpp" line="241"/>
<source>No Interrupt</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="264"/>
<source>White</source>
- <translation>Branco</translation>
+ <translation type="obsolete">Branco</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="265"/>
<source>Green</source>
- <translation>Verde</translation>
+ <translation type="obsolete">Verde</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="266"/>
<source>Red</source>
- <translation>Vermelho</translation>
+ <translation type="obsolete">Vermelho</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="267"/>
<source>Orange</source>
- <translation>Laranja</translation>
+ <translation type="obsolete">Laranja</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="268"/>
<source>Blue</source>
- <translation>Azul</translation>
+ <translation type="obsolete">Azul</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="269"/>
<source>Yellow</source>
- <translation>Amarelo</translation>
+ <translation type="obsolete">Amarelo</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="270"/>
<source>Rainbow</source>
- <translation>Arco Iris</translation>
+ <translation type="obsolete">Arco Iris</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="271"/>
<source>Pink</source>
- <translation>Rosa</translation>
+ <translation type="obsolete">Rosa</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="272"/>
<source>Cyan</source>
- <translation>Ciano</translation>
+ <translation type="obsolete">Ciano</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="295"/>
+ <location filename="../../src/courtroom.cpp" line="274"/>
<source>% offset</source>
<translation>% deslocamento</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="646"/>
+ <location filename="../../src/courtroom.cpp" line="742"/>
<source>Music</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="648"/>
+ <location filename="../../src/courtroom.cpp" line="744"/>
<source>Sfx</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="650"/>
+ <location filename="../../src/courtroom.cpp" line="746"/>
<source>Blips</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="653"/>
- <source>Log limit</source>
- <translation></translation>
- </message>
- <message>
- <location filename="../../src/courtroom.cpp" line="664"/>
- <location filename="../../src/courtroom.cpp" line="3816"/>
+ <location filename="../../src/courtroom.cpp" line="767"/>
+ <location filename="../../src/courtroom.cpp" line="3504"/>
<source>Server</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="683"/>
+ <location filename="../../src/courtroom.cpp" line="791"/>
<source>Change character</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="693"/>
+ <location filename="../../src/courtroom.cpp" line="797"/>
<source>Reload theme</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="702"/>
+ <location filename="../../src/courtroom.cpp" line="803"/>
<source>Call mod</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="711"/>
+ <location filename="../../src/courtroom.cpp" line="809"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="729"/>
+ <location filename="../../src/courtroom.cpp" line="822"/>
<source>A/M</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="737"/>
+ <location filename="../../src/courtroom.cpp" line="827"/>
<source>Preanim</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="818"/>
+ <location filename="../../src/courtroom.cpp" line="913"/>
<source>Back to Lobby</source>
<translatorcomment>A translation wouldn&apos;t fit because of the shitty theme system.</translatorcomment>
<translation>Lobby</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="1265"/>
- <location filename="../../src/courtroom.cpp" line="3492"/>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
<source>You were granted the Disable Modcalls button.</source>
<translation>Você recebeu o botão Desativar Modcalls.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3310"/>
+ <location filename="../../src/courtroom.cpp" line="3011"/>
<source>You have been banned.</source>
<translation>Você foi banido.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3500"/>
<source>This does nothing, but there you go.</source>
- <translation>Isso não faz nada, mas lá vai você.</translation>
+ <translation type="obsolete">Isso não faz nada, mas lá vai você.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3506"/>
+ <location filename="../../src/courtroom.cpp" line="3211"/>
<source>You opened the settings menu.</source>
<translation>Você abriu o menu de configurações.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3519"/>
<source>You will now pair up with </source>
- <translation>Agora você vai fazer par com </translation>
+ <translation type="obsolete">Agora você vai fazer par com </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3521"/>
<source> if they also choose your character in return.</source>
- <translation> se eles também escolherem seu personagem em troca.</translation>
+ <translation type="obsolete"> se eles também escolherem seu personagem em troca.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="143"/>
+ <source>None</source>
+ <translation>Nada</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="224"/>
+ <source>Guard</source>
+ <translation>Guarda</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="228"/>
+ <source>Additive</source>
+ <translation>Aditivo</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="277"/>
+ <source>To front</source>
+ <translation type="unfinished">Para frente</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="278"/>
+ <source>To behind</source>
+ <translation type="unfinished">Ao fundo</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="591"/>
+ <source>Select a character you wish to pair with.</source>
+ <translation type="unfinished">Selecione um personagem com o qual deseja parear.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="596"/>
+ <source>Change the percentage offset of your character&apos;s position from the center of the screen.</source>
+ <translation type="unfinished">Altere o deslocamento percentual da posição do seu personagem no centro da tela.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="602"/>
+ <source>Change the order of appearance for your character.</source>
+ <translation type="unfinished">Mude a ordem de aparência do seu personagem.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="607"/>
+ <source>Display the list of characters to pair with.</source>
+ <translation type="unfinished">Exibe a lista de caracteres para corresponder.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="665"/>
+ <source>Oops, you&apos;re muted!</source>
+ <translation type="unfinished">Opa, você está mudo!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="679"/>
+ <source>Set your character&apos;s emote to play on your next message.</source>
+ <translation type="unfinished">Defina o emote do seu personagem para usar na próxima mensagem.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="683"/>
+ <source>Set your character&apos;s supplementary background.</source>
+ <translation type="unfinished">Defina o plano de fundo suplementar para o seu personagem.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="689"/>
+ <source>Set an &apos;iniswap&apos;, or an alternative character folder to refer to from your current character.
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/iniswaps.ini</source>
+ <translation type="unfinished">Defina um &apos;iniswap&apos; ou uma pasta de caracteres alternativa para consultar seu personagem atual.
+Edite digitando e pressionando Enter, [X] para excluir. Isso é salvo em base/characters/&lt;charname&gt;/iniswaps.ini</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="698"/>
+ <location filename="../../src/courtroom.cpp" line="715"/>
+ <source>Remove the currently selected iniswap from the list and return to the original character folder.</source>
+ <translation type="unfinished">Remova o iniswap atualmente selecionado da lista e retorne à pasta de caracteres original.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="706"/>
+ <source>Set a sound effect to play on your next &apos;Preanim&apos;. Leaving it on Default will use the emote-defined sound (if any).
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/soundlist.ini</source>
+ <translation type="unfinished">Configure um efeito sonoro para tocar no seu próximo &apos;Preanim&apos;. Deixá-lo no padrão usará o som definido pelos emoticons (caso existam).
+Edite digitando e pressionando Enter, [X] para excluir. Isso é salvo em base/characters/&lt;charname&gt;/soundlist.ini</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="722"/>
+ <source>Choose an effect to play on your next spoken message.
+The effects are defined in your theme/effects/effects.ini. Your character can define custom effects by
+char.ini [Options] category, effects = &apos;miscname&apos; where it referes to misc/&lt;miscname&gt;/effects.ini to read the effects.</source>
+ <translation type="unfinished">Escolha um efeito para reproduzir na sua próxima mensagem falada.
+Os efeitos são definidos em theme / effects / effects.ini. Seu personagem pode definir efeitos personalizados ao
+categoria char.ini [Opções], effects = &apos;miscname&apos;, onde se refere a misc/&lt;miscname&gt;/effects.ini to read the effects.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="749"/>
+ <source>Hold It!</source>
+ <translation type="unfinished">Um momento!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="750"/>
+ <location filename="../../src/courtroom.cpp" line="756"/>
+ <location filename="../../src/courtroom.cpp" line="762"/>
+ <source>When this is turned on, your next in-character message will be a shout!</source>
+ <translation>Quando isso estiver ativado, sua próxima mensagem do personagem será um grito.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="755"/>
+ <source>Objection!</source>
+ <translation type="unfinished">Protesto!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="761"/>
+ <source>Take That!</source>
+ <translation type="unfinished">Tome isso!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="769"/>
+ <source>Toggle between server chat and global AO2 chat.</source>
+ <translation type="unfinished">Alterne entre o bate-papo do servidor e o global.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="773"/>
+ <location filename="../../src/courtroom.cpp" line="777"/>
+ <location filename="../../src/courtroom.cpp" line="783"/>
+ <location filename="../../src/courtroom.cpp" line="787"/>
+ <source>This will display the animation in the viewport as soon as it is pressed.</source>
+ <translation type="unfinished">Isso exibirá a animação na janela de visualização assim que for pressionada.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="781"/>
+ <source>Guilty!</source>
+ <translation type="unfinished">Culpado!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="794"/>
+ <source>Bring up the Character Select Screen and change your character.</source>
+ <translation type="unfinished">Abra a tela de seleção de personagem e mude seu personagem.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="800"/>
+ <source>Refresh the theme and update all of the ui elements to match.</source>
+ <translation type="unfinished">Atualize o tema e todos os elementos da interface do usuário para corresponder.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="806"/>
+ <source>Request the attention of the current server&apos;s moderator.</source>
+ <translation type="unfinished">Solicite a atenção do moderador do servidor atual.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="812"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation type="unfinished">Permite alterar vários aspectos do cliente.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="818"/>
+ <source>An interface to help you announce a case (you have to be a CM first to be able to announce cases)</source>
+ <translation type="unfinished">Uma interface para ajudá-lo a anunciar um caso (deve ser um CM para poder anunciar casos)</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="824"/>
+ <source>Switch between Areas and Music lists</source>
+ <translation type="unfinished">Alterne entre áreas e listas de músicas</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="829"/>
+ <source>Play a single-shot animation as defined by the emote when checked.</source>
+ <translation type="unfinished">Reproduza uma animação de tiro único, conforme definido pelo emote, quando marcada.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="833"/>
+ <source>If preanim is checked, display the input text immediately as the animation plays concurrently.</source>
+ <translation type="unfinished">Se pré-impressão estiver marcada, exiba o texto de entrada imediatamente enquanto a animação estiver sendo reproduzida simultaneamente.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="837"/>
+ <source>Mirror your character&apos;s emotes when checked.</source>
+ <translation type="unfinished">Reflita os gestos do seu personagem quando marcado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="841"/>
+ <source>Add text to your last spoken message when checked.</source>
+ <translation type="unfinished">Adicione texto à sua última mensagem falada quando marcado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="845"/>
+ <source>Do not listen to mod calls when checked, preventing them from playing sounds or focusing attention on the window.</source>
+ <translation type="unfinished">Você não ouve chamadas de moderação quando marcado, impedindo-os de tocar sons ou concentrando a atenção na janela.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="849"/>
+ <source>Lets you receive case alerts when enabled.
+(You can set your preferences in the Settings!)</source>
+ <translation type="unfinished">Permite que você receba alertas de caso quando ativado.
+(Você pode configurar suas preferências em Configurações!)</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="854"/>
+ <source>Display customized shownames for all users when checked.</source>
+ <translation type="unfinished">Mostrar nomes personalizados para todos os usuários quando marcado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="857"/>
+ <source>Custom Shout!</source>
+ <translation type="unfinished">Grito personalizado!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="860"/>
+ <source>This will display the custom character-defined animation in the viewport as soon as it is pressed.
+To make one, your character&apos;s folder must contain custom.[webp/apng/gif/png] and custom.[wav/ogg/opus] sound effect</source>
+ <translation type="unfinished">Isso exibirá a animação de caracteres personalizados definida na viewport assim que for pressionada.
+Para criar uma, a pasta do seu personagem deve conter efeitos personalizados [webp/apng/gif/png]. E efeitos sonoros personalizados [wav/ogg/opus]</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="868"/>
+ <source>Play realization sound and animation in the viewport on the next spoken message when checked.</source>
+ <translation type="unfinished">Tocar animação de som e performance na janela de desenho na seguinte mensagem falada quando marcada.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="874"/>
+ <source>Shake the screen on next spoken message when checked.</source>
+ <translation type="unfinished">Agite a tela na próxima mensagem falada quando marcada.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="880"/>
+ <source>Display the list of character folders you wish to mute.</source>
+ <translation type="unfinished">Exibe a lista de pastas de caracteres que você deseja silenciar.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="884"/>
+ <location filename="../../src/courtroom.cpp" line="892"/>
+ <source>Increase the health bar.</source>
+ <translation type="unfinished">Aumente a barra de saúde.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="888"/>
+ <location filename="../../src/courtroom.cpp" line="896"/>
+ <source>Decrease the health bar.</source>
+ <translation type="unfinished">Abaixe a barra de saúde.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="900"/>
+ <source>Change the text color of the spoken message.
+You can also select a part of your currently typed message and use the dropdown to change its color!</source>
+ <translation type="unfinished">Mude a cor do texto no chat IC.
+Você também pode selecionar uma parte da sua mensagem escrita no momento e usar o menu suspenso para alterar sua cor!</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="914"/>
+ <source>Return back to the server list.</source>
+ <translation type="unfinished">Retorne à lista de servidores.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="927"/>
+ <source>Become a spectator. You won&apos;t be able to interact with the in-character screen.</source>
+ <translation type="unfinished">Torne-se um espectador. Você não poderá interagir com a tela do personagem.</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
+ <location filename="../../src/courtroom.cpp" line="3372"/>
+ <source>CLIENT</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3090"/>
+ <location filename="../../src/courtroom.cpp" line="4508"/>
+ <location filename="../../src/courtroom.cpp" line="4515"/>
+ <source>has played a song</source>
+ <translation type="unfinished">tocou a música</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3224"/>
+ <source>You will now pair up with %1 if they also choose your character in return.</source>
+ <translation type="unfinished">Agora você será emparelhado com %1 se também escolher seu personagem.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3527"/>
+ <location filename="../../src/courtroom.cpp" line="3230"/>
<source>You are no longer paired with anyone.</source>
<translation>Você não está mais fazendo par com ninguém.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3532"/>
+ <location filename="../../src/courtroom.cpp" line="3235"/>
<source>Are you sure you typed that well? The char ID could not be recognised.</source>
<translation>Você tem certeza que você escreveu isso certo? O ID do personagem não pôde ser encontrado.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3547"/>
+ <location filename="../../src/courtroom.cpp" line="3250"/>
<source>You have set your offset to </source>
<translation>Você definiu seu deslocamento como </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3554"/>
+ <location filename="../../src/courtroom.cpp" line="3257"/>
<source>Your offset must be between -100% and 100%!</source>
<translation>Seu deslocamento deve estar entre -100% e 100%!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3559"/>
+ <location filename="../../src/courtroom.cpp" line="3262"/>
<source>That offset does not look like one.</source>
<translation>Esse deslocamento não se parece com um.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3565"/>
+ <location filename="../../src/courtroom.cpp" line="3268"/>
<source>You switched your music and area list.</source>
<translation>Você mudou sua lista de músicas e áreas.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3572"/>
+ <location filename="../../src/courtroom.cpp" line="3275"/>
<source>You have forcefully enabled features that the server may not support. You may not be able to talk IC, or worse, because of this.</source>
<translation>Você forçou recursos que o servidor pode não suportar. Você pode não conseguir falar de IC, ou pior, por causa disso.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3586"/>
+ <location filename="../../src/courtroom.cpp" line="3289"/>
<source>Your pre-animations interrupt again.</source>
<translation>Suas pré-animações interrompem novamente.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3589"/>
+ <location filename="../../src/courtroom.cpp" line="3292"/>
<source>Your pre-animations will not interrupt text.</source>
<translation>Suas pré-animações não interromperão o texto.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3600"/>
+ <location filename="../../src/courtroom.cpp" line="3303"/>
<source>Couldn&apos;t open chatlog.txt to write into.</source>
<translation>Não foi possível abrir o chatlog.txt para gravar.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3613"/>
+ <location filename="../../src/courtroom.cpp" line="3316"/>
<source>The IC chatlog has been saved.</source>
<translation>O chat do IC foi salvo.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3626"/>
+ <location filename="../../src/courtroom.cpp" line="3329"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely the case file you&apos;re looking for can&apos;t be found in there.</source>
<translation>Você não possui uma pasta `base/cases/`! Foi feito para você, mas, como foi feito para você, provavelmente o arquivo do caso que você está procurando não pode ser encontrado lá.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3641"/>
+ <location filename="../../src/courtroom.cpp" line="3344"/>
<source>You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini.
Cases you can load: %1</source>
<translation>Você precisa fornecer um nome de arquivo para carregar (extensão não necessária)! Verifique se está na pasta `base/cases/` e se é um ini formatado corretamente.
Casos que você pode carregar: %1</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3653"/>
+ <location filename="../../src/courtroom.cpp" line="3356"/>
<source>Too many arguments to load a case! You only need one filename, without extension.</source>
<translation>Muitos argumentos para carregar um caso! Você só precisa de um nome de arquivo, sem extensão.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3669"/>
+ <location filename="../../src/courtroom.cpp" line="3372"/>
<source>Case made by %1.</source>
<translation>Caso feito por %1.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3679"/>
+ <location filename="../../src/courtroom.cpp" line="3382"/>
<source>Navigate to %1 for the CM doc.</source>
<translation>Navegue para %1 para o documento do CM.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3702"/>
+ <location filename="../../src/courtroom.cpp" line="3396"/>
+ <location filename="../../src/courtroom.cpp" line="3398"/>
+ <location filename="../../src/evidence.cpp" line="762"/>
+ <location filename="../../src/evidence.cpp" line="764"/>
+ <source>UNKNOWN</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3406"/>
<source>Your case &quot;%1&quot; was loaded!</source>
<translation>Seu caso &quot;%1&quot; foi carregado!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3714"/>
+ <location filename="../../src/courtroom.cpp" line="3418"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely that you somehow deleted it.</source>
<translation>Você não possui uma pasta `base/cases/`! Foi feito para você, mas, como foi feito para você, é provável que você o tenha excluído.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3729"/>
+ <location filename="../../src/courtroom.cpp" line="3433"/>
<source>You need to give a filename to save (extension not needed) and the courtroom status!</source>
<translation>Você deve fornecer um nome de arquivo para salvar (sem extensão necessária) e o estado do tribunal!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3739"/>
<source>Too many arguments to save a case! You only need a filename without extension and the courtroom status.</source>
- <translation>Muitos argumentos para salvar um caso! Você só precisa de um nome de arquivo sem extensão e o estado do tribunal.</translation>
+ <translation type="obsolete">Muitos argumentos para salvar um caso! Você só precisa de um nome de arquivo sem extensão e o estado do tribunal.</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="3443"/>
<source>Too many arguments to save a case! You only need a filename without extension and the courtroom status!</source>
- <translation type="obsolete">Muitos argumentos para salvar um caso! Você só precisa de um nome de arquivo sem extensão e o estado do tribunal.</translation>
+ <translation>Muitos argumentos para salvar um caso! Você só precisa de um nome de arquivo sem extensão e o estado do tribunal.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3766"/>
+ <location filename="../../src/courtroom.cpp" line="3470"/>
<source>Succesfully saved, edit doc and cmdoc link on the ini!</source>
<translation>Salvo com sucesso, você pode editar o documento e o link do documento no arquivo ini!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3806"/>
+ <location filename="../../src/courtroom.cpp" line="3497"/>
<source>Master</source>
<translation></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4309"/>
+ <location filename="../../src/courtroom.cpp" line="3997"/>
+ <source>Expand All Categories</source>
+ <translation type="unfinished">Expandir todas as categorias</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3999"/>
+ <source>Collapse All Categories</source>
+ <translation type="unfinished">Recolher todas as categorias</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4003"/>
+ <source>Fade Out Previous</source>
+ <translation type="unfinished">Fade Anterior</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4009"/>
+ <source>Fade In</source>
+ <translation type="unfinished">Aparecimento gradual</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4015"/>
+ <source>Synchronize</source>
+ <translation type="unfinished">Sincronizar</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4285"/>
+ <source>Default</source>
+ <translation type="unfinished">Predeterminado</translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4446"/>
<source>Reason:</source>
<translation>Razão:</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4310"/>
+ <location filename="../../src/courtroom.cpp" line="4447"/>
<source>Call Moderator</source>
<translation>Chamar um Moderador</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4455"/>
+ <location filename="../../src/courtroom.cpp" line="4459"/>
<source>Error</source>
<translation>Erro</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
+ <location filename="../../src/courtroom.cpp" line="4455"/>
<source>You must provide a reason.</source>
<translation>Você deve fornecer um motivo.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4459"/>
<source>The message is too long.</source>
<translation>A mensagem é muito longa.</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="25"/>
<source>Choose...</source>
- <translation>Escolha...</translation>
+ <translation type="obsolete">Escolha...</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="17"/>
+ <source>Present this piece of evidence to everyone on your next spoken message</source>
+ <translation type="unfinished">Apresente essa evidência a todos na sua próxima mensagem falada</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="24"/>
+ <source>Save evidence to an .ini file.</source>
+ <translation type="unfinished">Salve evidências em um arquivo .ini.</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="208"/>
+ <location filename="../../src/evidence.cpp" line="26"/>
+ <source>Load evidence from an .ini file.</source>
+ <translation type="unfinished">Carregar evidências de um arquivo .ini.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="31"/>
+ <source>Destroy this piece of evidence</source>
+ <translation type="unfinished">Destrua esta evidência</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="34"/>
+ <source>Choose..</source>
+ <translation type="unfinished">Escolher..</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="37"/>
+ <source>Close the evidence display/editing overlay.
+You will be prompted if there&apos;s any unsaved changes.</source>
+ <translation type="unfinished">Feche a sobreposição para visualizar/editar evidências.
+Você será perguntado se existem alterações não salvas.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="40"/>
+ <source>Save any changes made to this piece of evidence and send them to server.</source>
+ <translation type="unfinished">Salve as alterações feitas nesta evidência e envie-as para o servidor.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="48"/>
+ <source>Double-click to edit. Press [X] to update your changes.</source>
+ <translation type="unfinished">Clique duas vezes para editar. Pressione [X] para atualizar suas alterações.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="104"/>
+ <source>Bring up the Evidence screen.</source>
+ <translation type="unfinished">Abra a tela para obter evidências.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="147"/>
+ <source>Switch evidence to private inventory.</source>
+ <translation type="unfinished">Alterar evidência para inventário privado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="151"/>
+ <source>Switch evidence to global inventory.</source>
+ <translation type="unfinished">Mude a evidência para o inventário global.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="158"/>
+ <location filename="../../src/evidence.cpp" line="617"/>
+ <source>Transfer evidence to private inventory.</source>
+ <translation type="unfinished">Transfira evidências para o inventário privado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="163"/>
+ <location filename="../../src/evidence.cpp" line="627"/>
+ <source>Transfer evidence to global inventory.</source>
+ <translation type="unfinished">Transfira evidências para o inventário global.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="263"/>
+ <source>The piece of evidence you&apos;ve been editing has changed.</source>
+ <translation type="unfinished">A evidência que você está editando mudou.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="264"/>
+ <source>Do you wish to keep your changes?</source>
+ <translation type="unfinished">Deseja manter suas alterações?</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="265"/>
+ <source>Name: %1
+Image: %2
+Description:
+%3</source>
+ <translation type="unfinished">Nome: %1
+Imagem: %2
+Descrição:
+%3</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="387"/>
<source>Images (*.png)</source>
<translation>Imagens (* .png)</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="280"/>
+ <location filename="../../src/evidence.cpp" line="456"/>
+ <location filename="../../src/evidence.cpp" line="460"/>
+ <location filename="../../src/evidence.cpp" line="463"/>
+ <source>Double-click to edit...</source>
+ <translation type="unfinished">Clique duas vezes para editar...</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="478"/>
<source>Add new evidence...</source>
<translation>Adicionar nova evidência...</translation>
</message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="556"/>
+ <source>Evidence has been modified.</source>
+ <translation type="unfinished">A evidência foi modificada.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="557"/>
+ <source>Do you want to save your changes?</source>
+ <translation type="unfinished">¿Quieres guardar tus cambios?</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="619"/>
+ <source>Current evidence is global. Click to switch to private.</source>
+ <translation type="unfinished">A evidência atual é global. Clique para mudar para privado.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="629"/>
+ <source>Current evidence is private. Click to switch to global.</source>
+ <translation type="unfinished">A evidência atual é privada. Clique para mudar para global.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="659"/>
+ <source>&quot;%1&quot; has been transferred.</source>
+ <translation type="unfinished">&quot;%1&quot; foi transferido.</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="722"/>
+ <source>Save Inventory</source>
+ <translation type="unfinished">Salvar inventário</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="722"/>
+ <location filename="../../src/evidence.cpp" line="748"/>
+ <source>Ini Files (*.ini)</source>
+ <translation type="unfinished">Arquivos INI (* .ini)</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="748"/>
+ <source>Open Inventory</source>
+ <translation type="unfinished">Abrir inventário</translation>
+ </message>
</context>
<context>
<name>Lobby</name>
@@ -909,54 +1409,97 @@ Casos que você pode carregar: %1</translation>
<translation></translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="29"/>
+ <location filename="../../src/lobby.cpp" line="31"/>
+ <source>Search</source>
+ <translation>Pesquisar</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="39"/>
<source>Name</source>
<translation>Nome</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="82"/>
+ <location filename="../../src/lobby.cpp" line="94"/>
<source>It doesn&apos;t look like your client is set up correctly.
Did you download all resources correctly from tiny.cc/getao, including the large &apos;base&apos; folder?</source>
<translation>Seu cliente não parece estar configurado corretamente.
Você baixou todos os recursos corretamente do tiny.cc/getao, incluindo a grande pasta &apos;base&apos;?</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="111"/>
+ <location filename="../../src/lobby.cpp" line="123"/>
<source>Version: %1</source>
<translation>Versão: %1</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="121"/>
- <location filename="../../src/lobby.cpp" line="327"/>
+ <location filename="../../src/lobby.cpp" line="129"/>
+ <source>Settings</source>
+ <translation>Configurações</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="132"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation>Permite alterar vários aspectos do cliente.</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="142"/>
+ <location filename="../../src/lobby.cpp" line="436"/>
<source>Offline</source>
<translation>Offline</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="155"/>
+ <location filename="../../src/lobby.cpp" line="176"/>
<source>Loading</source>
<translation>Carregando</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="159"/>
+ <location filename="../../src/lobby.cpp" line="180"/>
<source>Cancel</source>
<translation>Cancelar</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="279"/>
+ <location filename="../../src/lobby.cpp" line="365"/>
+ <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;Client development:&lt;/b&gt;&lt;br&gt;Cents02, in1tiate, raidensnake, windrammer&lt;p&gt;&lt;b&gt;QA testing:&lt;/b&gt;&lt;br&gt;CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;CrazyJC (2.8 release director) and MaximumVolty (2.8 release promotion); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!&lt;p&gt;The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.&lt;p&gt;Running on Qt version %2 with the %3 audio engine.&lt;p&gt;Built on %4</source>
+ <translation>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;O simulador de drama jurídico&lt;p&gt;&lt;b&gt;Código fonte:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Desenvolvimento principal:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;Desenvolvimento de cliente:&lt;/b&gt;&lt;br&gt;Cents02, in1tiate, raidensnake, windrammer&lt;p&gt;&lt;b&gt;Teste de controle de qualidade:&lt;/b&gt;&lt;br&gt;CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso&lt;p&gt;&lt;b&gt;Agradecimentos especiais:&lt;/b&gt;&lt;br&gt;CrazyJC y MaximumVolty (versão 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, criadores de conteúdo e toda a comunidade AO2.&lt;p&gt;O projeto Attorney Online possui direitos autorais (c) 2016-2020 Attorney Online developers. Aplicam-se licenças de código aberto. Todos os outros ativos são de propriedade de seus respectivos proprietários.&lt;p&gt;Usando a versão Qt %2 com o mecanismo de áudio %3.&lt;p&gt;Compilado em %4</translation>
+ </message>
+ <message>
+ <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;Client development:&lt;/b&gt;&lt;br&gt;Cents02, in1tiate, raidensnake, windrammer&lt;p&gt;&lt;b&gt;QA testing:&lt;/b&gt;&lt;br&gt;CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;CrazyJC and MaximumVolty (2.8 release); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!&lt;p&gt;The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.&lt;p&gt;Running on Qt version %2 with the %3 audio engine.&lt;p&gt;Built on %4</source>
+ <translation type="obsolete">&lt;h2&gt;Attorney Online %1&lt;/h2&gt;O simulador de drama jurídico&lt;p&gt;&lt;b&gt;Código fonte:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Desenvolvimento principal:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;Desenvolvimento de cliente:&lt;/b&gt;&lt;br&gt;Cents02, in1tiate, raidensnake, windrammer&lt;p&gt;&lt;b&gt;Teste de controle de qualidade:&lt;/b&gt;&lt;br&gt;CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso&lt;p&gt;&lt;b&gt;Agradecimentos especiais:&lt;/b&gt;&lt;br&gt;CrazyJC y MaximumVolty (versão 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, criadores de conteúdo e toda a comunidade AO2.&lt;p&gt;O projeto Attorney Online possui direitos autorais (c) 2016-2020 Attorney Online developers. Aplicam-se licenças de código aberto. Todos os outros ativos são de propriedade de seus respectivos proprietários.&lt;p&gt;Usando a versão Qt %2 com o mecanismo de áudio %3.&lt;p&gt;Compilado em %4</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="398"/>
+ <source>About</source>
+ <translation>Sobre</translation>
+ </message>
+ <message>
<source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</source>
- <translation>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</translation>
+ <translation type="obsolete">&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</translation>
</message>
<message>
<source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy</source>
<translation type="obsolete">&lt;h2&gt;Attorney Online %1&lt;/h2&gt;O simulador de drama jurídico&lt;p&gt;&lt;b&gt;Código fonte:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Desenvolvimento principal:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Agradecimentos especiais:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="395"/>
+ <location filename="../../src/lobby.cpp" line="540"/>
<source>Online: %1/%2</source>
<translation>Online: %1/%2</translation>
</message>
</context>
<context>
+ <name>chatlogpiece</name>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="5"/>
+ <location filename="../../src/chatlogpiece.cpp" line="6"/>
+ <location filename="../../src/chatlogpiece.cpp" line="7"/>
+ <source>UNKNOWN</source>
+ <translation></translation>
+ </message>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="55"/>
+ <source> has played a song: </source>
+ <translation> tocou a música: </translation>
+ </message>
+</context>
+<context>
<name>debug_functions</name>
<message>
<location filename="../../src/debug_functions.cpp" line="10"/>
@@ -969,7 +1512,7 @@ Você baixou todos os recursos corretamente do tiny.cc/getao, incluindo a grande
<translation></translation>
</message>
<message>
- <location filename="../../src/debug_functions.cpp" line="26"/>
+ <location filename="../../src/debug_functions.cpp" line="25"/>
<source>Notice</source>
<translation></translation>
</message>
diff --git a/resource/translations/ao_ru.ts b/resource/translations/ao_ru.ts
index 93a32956..3b0af42f 100644
--- a/resource/translations/ao_ru.ts
+++ b/resource/translations/ao_ru.ts
@@ -9,12 +9,12 @@
<translation>Соединение с сервером прервано.</translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="151"/>
+ <location filename="../../src/aoapplication.cpp" line="152"/>
<source>Error connecting to master server. Will try again in %1 seconds.</source>
<translation>Ошибка соединения с главным сервером. Попытка пересоединения будет через %1 с.</translation>
</message>
<message>
- <location filename="../../src/aoapplication.cpp" line="156"/>
+ <location filename="../../src/aoapplication.cpp" line="157"/>
<source>There was an error connecting to the master server.
We deploy multiple master servers to mitigate any possible downtime, but the client appears to have exhausted all possible methods of finding and connecting to one.
Please check your Internet connection and firewall, and please try again.</source>
@@ -22,67 +22,66 @@ Please check your Internet connection and firewall, and please try again.</sourc
Пожалуйста, проверьте ваши Интернет-соединение, настройки браундмауэра, и попробуйте перезайти.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="108"/>
+ <location filename="../../src/packet_distribution.cpp" line="94"/>
<source>Outdated version! Your version: %1
Please go to aceattorneyonline.com to update.</source>
<translation>Устаревшая версия! У вас установлена %1
Проследуйте на сайт aceattorneyonline.com для обновления.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="115"/>
<source>You have been exiled from AO.
Have a nice day.</source>
- <translation>Из AO вас отправили в жизнь.
+ <translation type="vanished">Из AO вас отправили в жизнь.
Хорошего дня.</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="258"/>
+ <location filename="../../src/packet_distribution.cpp" line="235"/>
<source>Attorney Online 2</source>
<translation>Attorney Online 2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="282"/>
+ <location filename="../../src/packet_distribution.cpp" line="263"/>
<source>Loading</source>
<translation>Загрузка</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="373"/>
+ <location filename="../../src/packet_distribution.cpp" line="363"/>
<source>Loading evidence:
%1/%2</source>
<translation>Загрузка вещдоков:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="408"/>
- <location filename="../../src/packet_distribution.cpp" line="506"/>
+ <location filename="../../src/packet_distribution.cpp" line="398"/>
+ <location filename="../../src/packet_distribution.cpp" line="492"/>
<source>Loading music:
%1/%2</source>
<translation>Загрузка музыки:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="326"/>
- <location filename="../../src/packet_distribution.cpp" line="457"/>
+ <location filename="../../src/packet_distribution.cpp" line="316"/>
+ <location filename="../../src/packet_distribution.cpp" line="465"/>
<source>Loading chars:
%1/%2</source>
<translation>Загрузка персонажей:
%1/%2</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="635"/>
+ <location filename="../../src/packet_distribution.cpp" line="674"/>
<source>You have been kicked from the server.
Reason: %1</source>
<translation>Вас выпнули с сервера.
Причина: %1</translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="643"/>
+ <location filename="../../src/packet_distribution.cpp" line="682"/>
<source>You have been banned from the server.
Reason: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/packet_distribution.cpp" line="651"/>
+ <location filename="../../src/packet_distribution.cpp" line="690"/>
<source>You are banned on this server.
Reason: %1</source>
<translation>Вас отправили в баню.
@@ -138,383 +137,371 @@ Reason: </source>
<source>Stenographer needed</source>
<translation>Нужен стенографист?</translation>
</message>
- <message>
- <location filename="../../src/aocaseannouncerdialog.cpp" line="66"/>
- <source>Witness needed</source>
- <translation type="unfinished"></translation>
- </message>
</context>
<context>
<name>AOOptionsDialog</name>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="11"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="12"/>
<source>Settings</source>
<translation>Настройки</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="48"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="46"/>
<source>Gameplay</source>
<translation>Игра</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="61"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="62"/>
<source>Theme:</source>
<translation>Тема:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="63"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="64"/>
<source>Sets the theme used in-game. If the new theme changes the lobby&apos;s look as well, you&apos;ll need to reload the lobby for the changes to take effect, such as by joining a server and leaving it.</source>
<translation>Устанавливает внешний вид игры. Может понадобиться перезайти на сервер.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="109"/>
- <source>Gives the default value for the in-game &apos;Custom shownames&apos; checkbox, which in turn determines whether the client should display custom in-character names.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="305"/>
- <source>Sets the default volume for music.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="320"/>
- <source>Sets the default volume for SFX sounds, like interjections or other character sound effects.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="568"/>
- <source>IC Log</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="581"/>
- <source>Colorful IC log:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="583"/>
- <source>Enables colored text in the log.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="594"/>
- <source>Only inline coloring:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="596"/>
- <source>Only inline coloring will be shown such as &lt;&gt;,|| etc.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="606"/>
- <source>Mirror IC log:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="608"/>
- <source>IC log will mirror the IC box. Meaning that if somebody gets interrupted nobody will know what they wanted to say. Enable for a more realistic experience.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="620"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="95"/>
<source>Log goes downwards:</source>
<translation>Портянку вниз:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="622"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="97"/>
<source>If ticked, new messages will appear at the bottom (like the OOC chatlog). The traditional (AO1) behaviour is equivalent to this being unticked.</source>
<translation>Отметьте галочку, если хотите, чтобы сообщения в игровом чате отображались снизу, а не сверху.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="634"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="110"/>
<source>Log length:</source>
<translation>Длина игрового чата:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="635"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="111"/>
<source>The amount of messages the IC chatlog will keep before deleting older messages. A value of 0 or below counts as &apos;infinite&apos;.</source>
<translation>Количество сообщений, максимально хранимых в игровом чате. Значение, равное 0 или меньше, будет расценено как снятие такого ограничения.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="93"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="133"/>
<source>Default username:</source>
<translation>Никнейм по умолчанию:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="95"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="135"/>
<source>Your OOC name will be automatically set to this value when you join a server.</source>
<translation>Псевдоним, используемый при соединении с сервером. В основном, его видно в чате сервера.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="107"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="148"/>
<source>Custom shownames:</source>
<translation>Произвольные имена:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="150"/>
<source>Gives the default value for the in-game &apos;Custom shownames&apos; tickbox, which in turn determines whether the client should display custom in-character names.</source>
- <translation type="vanished">Отображать произвольные имена персонажей, установленные самими игроками.</translation>
+ <translation>Отображать произвольные имена персонажей, установленные самими игроками.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="127"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="170"/>
<source>Backup MS:</source>
<translation>Запасной ГС:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="129"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="172"/>
<source>If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address.</source>
<translation>Отображать перечень серверов от главного сервера, указанного здесь, когда не удалось соединиться с первичным ГС.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="141"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="185"/>
<source>Discord:</source>
<translation>Discord:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="143"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="187"/>
<source>Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for.</source>
<translation>Показать в Discord сервер, на котором вы играете, каким персонажем управляете и время игры.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="155"/>
- <source>Allow Shake/Flash:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="200"/>
+ <source>Language:</source>
+ <translation>Язык:</translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="202"/>
+ <source>Sets the language if you don&apos;t want to use your system language.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="157"/>
- <source>Allows screenshaking and flashing. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="208"/>
+ <source> - Keep current setting</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="168"/>
- <source>Language:</source>
- <translation>Язык:</translation>
+ <location filename="../../src/aooptionsdialog.cpp" line="220"/>
+ <source>Allow Screenshake:</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="170"/>
- <source>Sets the language if you don&apos;t want to use your system language.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="222"/>
+ <source>Allows screenshaking. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="193"/>
- <source>Slower text speed:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="234"/>
+ <source>Allow Effects:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="194"/>
- <source>Set the text speed to be the same as the AA games.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="236"/>
+ <source>Allows screen effects. Disable this if you have concerns or issues with photosensitivity and/or seizures.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="201"/>
- <source>Blip delay on punctuations:</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="248"/>
+ <source>Network Frame Effects:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="202"/>
- <source>Punctuation delay modifier. Enable it for the blips to slow down on punctuations.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="249"/>
+ <source>Send screen-shaking, flashes and sounds as defined in the char.ini over the network. Only works for servers that support this functionality.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="262"/>
+ <source>Colors in IC Log:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="264"/>
+ <source>Use the markup colors in the server IC chatlog.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="275"/>
+ <source>Sticky Sounds:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="277"/>
+ <source>Turn this on to prevent the sound dropdown from clearing the sound after playing it.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="289"/>
+ <source>Sticky Effects:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="291"/>
+ <source>Turn this on to prevent the effects dropdown from clearing the effect after playing it.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="212"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="304"/>
+ <source>Sticky Preanims:</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="306"/>
+ <source>Turn this on to prevent preanimation checkbox from clearing after playing the emote.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="324"/>
<source>Callwords</source>
<translation>Позывные</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="239"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="351"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!&lt;br&gt;Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;Введите на отдельных строках свои позывные, при указании которых в сообщениях будет подан звуковой сигнал.&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="249"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="361"/>
<source>Audio</source>
<translation>Аудио</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="262"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="375"/>
<source>Audio device:</source>
<translation>Устройство воспроизведения:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="263"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="376"/>
<source>Sets the audio device for all sounds.</source>
<translation>Куда вещать звук из игры.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="304"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="419"/>
<source>Music:</source>
<translation>Музыка:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="420"/>
<source>Sets the music&apos;s default volume.</source>
- <translation type="vanished">Громкость музыки по умолчанию.</translation>
+ <translation>Громкость музыки по умолчанию.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="318"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="434"/>
<source>SFX:</source>
<translation>Звук. эффекты:</translation>
</message>
<message>
+ <location filename="../../src/aooptionsdialog.cpp" line="436"/>
<source>Sets the SFX&apos;s default volume. Interjections and actual sound effects count as &apos;SFX&apos;.</source>
- <translation type="vanished">Громкость звуковых эффектов по умолчанию.</translation>
+ <translation>Громкость звуковых эффектов по умолчанию.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="333"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="450"/>
<source>Blips:</source>
<translation>Сигналы:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="335"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="452"/>
<source>Sets the volume of the blips, the talking sound effects.</source>
<translation>Громкость сигналов, заменяющих голос, по умолчанию.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="354"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="474"/>
<source>Blip rate:</source>
<translation>Пер. сигналов:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="356"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="476"/>
<source>Sets the delay between playing the blip sounds.</source>
<translation>Период между сигналами, заменяющими голос, по умолчанию.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="367"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="484"/>
+ <source>Play a blip sound &quot;once per every X symbols&quot;, where X is the blip rate.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/aooptionsdialog.cpp" line="491"/>
<source>Blank blips:</source>
<translation>Пустые сигналы:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="369"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="493"/>
<source>If true, the game will play a blip sound even when a space is &apos;being said&apos;.</source>
<translation>Проигрывать сигналы даже для пробелов.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="380"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="505"/>
<source>Enable Looping SFX:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="381"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="506"/>
<source>If true, the game will allow looping sound effects to play on preanimations.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="392"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="518"/>
<source>Kill Music On Objection:</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="394"/>
- <source>If true, the game will stop music when someone objects, like in the actual games.</source>
+ <location filename="../../src/aooptionsdialog.cpp" line="520"/>
+ <source>If true, AO2 will stop the music for you when you or someone else does &apos;Objection!&apos;.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="408"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="532"/>
<source>Casing</source>
<translation>Заседание</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="424"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="549"/>
<source>This server supports case alerts.</source>
<translation>Этот сервер поддерживает объявление заседания.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="427"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="552"/>
<source>This server does not support case alerts.</source>
<translation>Этот сервер не поддерживает объявление заседания.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="428"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="553"/>
<source>Pretty self-explanatory.</source>
<translation>Весьма доходчиво.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="436"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="562"/>
<source>Casing:</source>
<translation>Новое дело:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="438"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="564"/>
<source>If checked, you will get alerts about case announcements.</source>
<translation>При заведении дела вы получите уведомление.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="451"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="580"/>
<source>Defense:</source>
<translation>Защита:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="452"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="581"/>
<source>If checked, you will get alerts about case announcements if a defense spot is open.</source>
<translation>При заведении дела, в котором нужна сторона защиты, вы получите уведомление.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="465"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="595"/>
<source>Prosecution:</source>
<translation>Обвинение:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="467"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="597"/>
<source>If checked, you will get alerts about case announcements if a prosecutor spot is open.</source>
<translation>При заведении дела, в котором нужна сторона обвинения, вы получите уведомление.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="480"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="611"/>
<source>Judge:</source>
<translation>Судья:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="481"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="612"/>
<source>If checked, you will get alerts about case announcements if the judge spot is open.</source>
<translation>При заведении дела, в котором нужен судья, вы получите уведомление.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="494"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="626"/>
<source>Juror:</source>
<translation>Присяжный:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="495"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="627"/>
<source>If checked, you will get alerts about case announcements if a juror spot is open.</source>
<translation>При заведении дела, в котором нужны присяжные заседатели, вы получите уведомление.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="508"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="641"/>
<source>Stenographer:</source>
<translation>Стенографист:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="510"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="643"/>
<source>If checked, you will get alerts about case announcements if a stenographer spot is open.</source>
<translation>При заведении дела, в котором нужна стенография, вы получите уведомление.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="523"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="657"/>
<source>CM:</source>
<translation>ПД:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="525"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="659"/>
<source>If checked, you will appear amongst the potential CMs on the server.</source>
<translation>Отметьте, если вы хотите состоять в числе производителей дел.</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="536"/>
- <source>Witness:</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="538"/>
- <source>If checked, you will appear amongst the potential witnesses on the server.</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/aooptionsdialog.cpp" line="551"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="673"/>
<source>Hosting cases:</source>
<translation>ПД акт.:</translation>
</message>
<message>
- <location filename="../../src/aooptionsdialog.cpp" line="553"/>
+ <location filename="../../src/aooptionsdialog.cpp" line="675"/>
<source>If you&apos;re a CM, enter what cases you are willing to host.</source>
<translation>Будучи производителем дела (ПД), вы можете войти в зону и заниматься её оркестровкой.</translation>
</message>
@@ -522,40 +509,36 @@ Reason: </source>
<context>
<name>Courtroom</name>
<message>
- <location filename="../../src/charselect.cpp" line="69"/>
+ <location filename="../../src/charselect.cpp" line="21"/>
<source>Password</source>
<translation>Пароль</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="75"/>
+ <location filename="../../src/charselect.cpp" line="27"/>
<source>Spectator</source>
<translation>Наблюдатель</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="78"/>
- <location filename="../../src/courtroom.cpp" line="179"/>
+ <location filename="../../src/charselect.cpp" line="30"/>
+ <location filename="../../src/courtroom.cpp" line="175"/>
<source>Search</source>
<translation>Поиск</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="83"/>
+ <location filename="../../src/charselect.cpp" line="35"/>
<source>Passworded</source>
<translation>Ограничен паролем</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="87"/>
+ <location filename="../../src/charselect.cpp" line="39"/>
<source>Taken</source>
<translation>Занят</translation>
</message>
<message>
- <location filename="../../src/charselect.cpp" line="182"/>
- <source>Could not find %1</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
+ <location filename="../../src/charselect.cpp" line="231"/>
<source>Generating chars:
%1/%2</source>
- <translation type="vanished">Генерация персонажей:
+ <translation>Генерация персонажей:
%1/%2</translation>
</message>
<message>
@@ -565,212 +548,440 @@ Reason: </source>
</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="149"/>
+ <location filename="../../src/courtroom.cpp" line="148"/>
<source>Showname</source>
<translation>Имя</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="153"/>
+ <location filename="../../src/courtroom.cpp" line="152"/>
<source>Message</source>
<translation>Сообщение</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="164"/>
+ <location filename="../../src/courtroom.cpp" line="167"/>
<source>Name</source>
<translation>Никнейм</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="224"/>
+ <location filename="../../src/courtroom.cpp" line="217"/>
<source>Pre</source>
<translation>Пред.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="227"/>
+ <location filename="../../src/courtroom.cpp" line="220"/>
<source>Flip</source>
<translation>Разв.</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="224"/>
<source>Guard</source>
- <translation type="vanished">Охрана</translation>
+ <translation>Охрана</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="238"/>
- <location filename="../../src/courtroom.cpp" line="720"/>
+ <location filename="../../src/courtroom.cpp" line="228"/>
+ <source>Additive</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="233"/>
+ <location filename="../../src/courtroom.cpp" line="815"/>
<source>Casing</source>
<translation>Дело</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="243"/>
+ <location filename="../../src/courtroom.cpp" line="238"/>
<source>Shownames</source>
<translation>Произв. имена</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="246"/>
+ <location filename="../../src/courtroom.cpp" line="241"/>
<source>No Interrupt</source>
<translation>Говорить сразу</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="264"/>
<source>White</source>
- <translation>Белый</translation>
+ <translation type="vanished">Белый</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="265"/>
<source>Green</source>
- <translation>Зелëный</translation>
+ <translation type="vanished">Зелëный</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="266"/>
<source>Red</source>
- <translation>Красный</translation>
+ <translation type="vanished">Красный</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="267"/>
<source>Orange</source>
- <translation>Оранжевый</translation>
+ <translation type="vanished">Оранжевый</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="268"/>
<source>Blue</source>
- <translation>Синий</translation>
+ <translation type="vanished">Синий</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="269"/>
<source>Yellow</source>
- <translation>Жëлтый</translation>
+ <translation type="vanished">Жëлтый</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3500"/>
<source>This does nothing, but there you go.</source>
- <translation>В общем-то, это ни на что не влияет...</translation>
+ <translation type="vanished">В общем-то, это ни на что не влияет...</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3641"/>
+ <location filename="../../src/courtroom.cpp" line="3315"/>
<source>You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini.
Cases you can load: %1</source>
<translation>Укажите имя файла с делом (без расширения) для загрузки. Убедитесь, что оно расположено в папке `base/cases`.
Были найдены: %1</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3669"/>
+ <location filename="../../src/courtroom.cpp" line="3343"/>
<source>Case made by %1.</source>
<translation>Дело завëл игрок: %1.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3679"/>
+ <location filename="../../src/courtroom.cpp" line="3353"/>
<source>Navigate to %1 for the CM doc.</source>
<translation>Перейдите к %1 для получения материалов дела.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3702"/>
+ <location filename="../../src/courtroom.cpp" line="3377"/>
<source>Your case &quot;%1&quot; was loaded!</source>
<translation>Дело под кодовым названием &quot;%1&quot; готово!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="664"/>
- <location filename="../../src/courtroom.cpp" line="3816"/>
+ <location filename="../../src/courtroom.cpp" line="767"/>
+ <location filename="../../src/courtroom.cpp" line="3475"/>
<source>Server</source>
<translation>Сервер</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="143"/>
+ <source>None</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="749"/>
+ <source>Hold It!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="750"/>
+ <location filename="../../src/courtroom.cpp" line="756"/>
+ <location filename="../../src/courtroom.cpp" line="762"/>
+ <source>When this is turned on, your next in-character message will be a shout!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="755"/>
+ <source>Objection!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="761"/>
+ <source>Take That!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="769"/>
+ <source>Toggle between server chat and global AO2 chat.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="773"/>
+ <location filename="../../src/courtroom.cpp" line="777"/>
+ <location filename="../../src/courtroom.cpp" line="783"/>
+ <location filename="../../src/courtroom.cpp" line="787"/>
+ <source>This will display the animation in the viewport as soon as it is pressed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="781"/>
+ <source>Guilty!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="794"/>
+ <source>Bring up the Character Select Screen and change your character.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="800"/>
+ <source>Refresh the theme and update all of the ui elements to match.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="806"/>
+ <source>Request the attention of the current server&apos;s moderator.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="812"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
<location filename="../../src/courtroom.cpp" line="818"/>
+ <source>An interface to help you announce a case (you have to be a CM first to be able to announce cases)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="824"/>
+ <source>Switch between Areas and Music lists</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="829"/>
+ <source>Play a single-shot animation as defined by the emote when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="833"/>
+ <source>If preanim is checked, display the input text immediately as the animation plays concurrently.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="837"/>
+ <source>Mirror your character&apos;s emotes when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="841"/>
+ <source>Add text to your last spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="845"/>
+ <source>Do not listen to mod calls when checked, preventing them from playing sounds or focusing attention on the window.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="849"/>
+ <source>Lets you receive case alerts when enabled.
+(You can set your preferences in the Settings!)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="854"/>
+ <source>Display customized shownames for all users when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="857"/>
+ <source>Custom Shout!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="860"/>
+ <source>This will display the custom character-defined animation in the viewport as soon as it is pressed.
+To make one, your character&apos;s folder must contain custom.[webp/apng/gif/png] and custom.[wav/ogg/opus] sound effect</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="868"/>
+ <source>Play realization sound and animation in the viewport on the next spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="874"/>
+ <source>Shake the screen on next spoken message when checked.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="880"/>
+ <source>Display the list of character folders you wish to mute.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="884"/>
+ <location filename="../../src/courtroom.cpp" line="892"/>
+ <source>Increase the health bar.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="888"/>
+ <location filename="../../src/courtroom.cpp" line="896"/>
+ <source>Decrease the health bar.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="900"/>
+ <source>Change the text color of the spoken message.
+You can also select a part of your currently typed message and use the dropdown to change its color!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="913"/>
<source>Back to Lobby</source>
<translation>Назад в лобби</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="270"/>
- <source>Rainbow</source>
- <translation>Радужный</translation>
+ <location filename="../../src/courtroom.cpp" line="3061"/>
+ <location filename="../../src/courtroom.cpp" line="4479"/>
+ <location filename="../../src/courtroom.cpp" line="4486"/>
+ <source>has played a song</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="160"/>
- <source>OOC Message</source>
+ <location filename="../../src/courtroom.cpp" line="3195"/>
+ <source>You will now pair up with %1 if they also choose your character in return.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="232"/>
- <source>Disable Modcalls</source>
- <translation type="unfinished"></translation>
+ <source>Rainbow</source>
+ <translation type="vanished">Радужный</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="271"/>
<source>Pink</source>
- <translation>Розовый</translation>
+ <translation type="vanished">Розовый</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="272"/>
<source>Cyan</source>
- <translation>Голубой</translation>
+ <translation type="vanished">Голубой</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="295"/>
+ <location filename="../../src/courtroom.cpp" line="274"/>
<source>% offset</source>
<translation>% сдвига</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="646"/>
+ <location filename="../../src/courtroom.cpp" line="277"/>
+ <source>To front</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="278"/>
+ <source>To behind</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="591"/>
+ <source>Select a character you wish to pair with.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="596"/>
+ <source>Change the percentage offset of your character&apos;s position from the center of the screen.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="602"/>
+ <source>Change the order of appearance for your character.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="607"/>
+ <source>Display the list of characters to pair with.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="665"/>
+ <source>Oops, you&apos;re muted!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="679"/>
+ <source>Set your character&apos;s emote to play on your next message.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="683"/>
+ <source>Set your character&apos;s supplementary background.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="689"/>
+ <source>Set an &apos;iniswap&apos;, or an alternative character folder to refer to from your current character.
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/iniswaps.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="698"/>
+ <location filename="../../src/courtroom.cpp" line="715"/>
+ <source>Remove the currently selected iniswap from the list and return to the original character folder.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="706"/>
+ <source>Set a sound effect to play on your next &apos;Preanim&apos;. Leaving it on Default will use the emote-defined sound (if any).
+Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/&lt;charname&gt;/soundlist.ini</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="722"/>
+ <source>Choose an effect to play on your next spoken message.
+The effects are defined in your theme/effects/effects.ini. Your character can define custom effects by
+char.ini [Options] category, effects = &apos;miscname&apos; where it referes to misc/&lt;miscname&gt;/effects.ini to read the effects.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="742"/>
<source>Music</source>
<translation>Музыка</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="648"/>
+ <location filename="../../src/courtroom.cpp" line="744"/>
<source>Sfx</source>
<translation>Звук. эффекты</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="650"/>
+ <location filename="../../src/courtroom.cpp" line="746"/>
<source>Blips</source>
<translation>Сигналы</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="653"/>
- <source>Log limit</source>
- <translation type="unfinished"></translation>
- </message>
- <message>
- <location filename="../../src/courtroom.cpp" line="683"/>
+ <location filename="../../src/courtroom.cpp" line="791"/>
<source>Change character</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="693"/>
+ <location filename="../../src/courtroom.cpp" line="797"/>
<source>Reload theme</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="702"/>
+ <location filename="../../src/courtroom.cpp" line="803"/>
<source>Call mod</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="711"/>
+ <location filename="../../src/courtroom.cpp" line="809"/>
<source>Settings</source>
<translation>Настройки</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="729"/>
+ <location filename="../../src/courtroom.cpp" line="822"/>
<source>A/M</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="737"/>
+ <location filename="../../src/courtroom.cpp" line="827"/>
<source>Preanim</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="1265"/>
- <location filename="../../src/courtroom.cpp" line="3492"/>
+ <location filename="../../src/courtroom.cpp" line="914"/>
+ <source>Return back to the server list.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="927"/>
+ <source>Become a spectator. You won&apos;t be able to interact with the in-character screen.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
<source>You were granted the Disable Modcalls button.</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3310"/>
- <source>You have been banned.</source>
+ <location filename="../../src/courtroom.cpp" line="1457"/>
+ <location filename="../../src/courtroom.cpp" line="3343"/>
+ <source>CLIENT</source>
<translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3739"/>
- <source>Too many arguments to save a case! You only need a filename without extension and the courtroom status.</source>
+ <location filename="../../src/courtroom.cpp" line="2984"/>
+ <source>You have been banned.</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -778,150 +989,320 @@ Cases you can load: %1</source>
<translation type="vanished">Теперь у вас есть кнопка &quot;Охрана&quot;.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3506"/>
+ <location filename="../../src/courtroom.cpp" line="3182"/>
<source>You opened the settings menu.</source>
<translation>Вы открыли меню настроек.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3519"/>
<source>You will now pair up with </source>
- <translation>Вы встанете парой с персонажем по имени </translation>
+ <translation type="vanished">Вы встанете парой с персонажем по имени </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3521"/>
<source> if they also choose your character in return.</source>
- <translation> (если он выберет вас в ответ).</translation>
+ <translation type="vanished"> (если он выберет вас в ответ).</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3527"/>
+ <location filename="../../src/courtroom.cpp" line="3201"/>
<source>You are no longer paired with anyone.</source>
<translation>Теперь вы не стоите в парах.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3532"/>
+ <location filename="../../src/courtroom.cpp" line="3206"/>
<source>Are you sure you typed that well? The char ID could not be recognised.</source>
<translation>Кажется, вам нужно поменять запрос: такой идентификатор персонажа не был найден.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3547"/>
+ <location filename="../../src/courtroom.cpp" line="3221"/>
<source>You have set your offset to </source>
<translation>Вы установили сдвиг персонажа на </translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3554"/>
+ <location filename="../../src/courtroom.cpp" line="3228"/>
<source>Your offset must be between -100% and 100%!</source>
<translation>Сдвиг персонажа должен быть между -100% и 100%!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3559"/>
+ <location filename="../../src/courtroom.cpp" line="3233"/>
<source>That offset does not look like one.</source>
<translation>Неверный сдвиг персонажа.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3565"/>
+ <location filename="../../src/courtroom.cpp" line="3239"/>
<source>You switched your music and area list.</source>
<translation>Вы переключили перечень зон и музыки.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3572"/>
+ <location filename="../../src/courtroom.cpp" line="3246"/>
<source>You have forcefully enabled features that the server may not support. You may not be able to talk IC, or worse, because of this.</source>
<translation>Из-за того, что вы включили не поддержимаемые сервером возможности, он может не принять ваши сообщения.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3586"/>
+ <location filename="../../src/courtroom.cpp" line="3260"/>
<source>Your pre-animations interrupt again.</source>
<translation>Персонаж будет говорить только после анимации.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3589"/>
+ <location filename="../../src/courtroom.cpp" line="3263"/>
<source>Your pre-animations will not interrupt text.</source>
<translation>Персонаж будет говорить и во время анимации.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3600"/>
+ <location filename="../../src/courtroom.cpp" line="3274"/>
<source>Couldn&apos;t open chatlog.txt to write into.</source>
<translation>Не могу открыть `chatlog.txt` для записи лога.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3613"/>
+ <location filename="../../src/courtroom.cpp" line="3287"/>
<source>The IC chatlog has been saved.</source>
<translation>Лог игрового чата сохранëн.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3626"/>
+ <location filename="../../src/courtroom.cpp" line="3300"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely the case file you&apos;re looking for can&apos;t be found in there.</source>
<translation>Файл с делом не найден. Если найдëте, положите его в папку `base/cases/`, которую мы для вас создали.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3653"/>
+ <location filename="../../src/courtroom.cpp" line="3327"/>
<source>Too many arguments to load a case! You only need one filename, without extension.</source>
<translation>Введите имя файла без расширения.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3714"/>
+ <location filename="../../src/courtroom.cpp" line="3367"/>
+ <location filename="../../src/courtroom.cpp" line="3369"/>
+ <location filename="../../src/evidence.cpp" line="761"/>
+ <location filename="../../src/evidence.cpp" line="763"/>
+ <source>UNKNOWN</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3389"/>
<source>You don&apos;t have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it&apos;s likely that you somehow deleted it.</source>
<translation>Папка `base/cases/` отсутствует!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3729"/>
+ <location filename="../../src/courtroom.cpp" line="3404"/>
<source>You need to give a filename to save (extension not needed) and the courtroom status!</source>
<translation>Введите имя файла (без расширения) и предоставьте статус зоны.</translation>
</message>
<message>
+ <location filename="../../src/courtroom.cpp" line="3414"/>
<source>Too many arguments to save a case! You only need a filename without extension and the courtroom status!</source>
- <translation type="vanished">Убедитесь, что имя файла не содержит расширение.</translation>
+ <translation>Убедитесь, что имя файла не содержит расширение.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3766"/>
+ <location filename="../../src/courtroom.cpp" line="3441"/>
<source>Succesfully saved, edit doc and cmdoc link on the ini!</source>
<translation>Сохранение прошло успешно!</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="3806"/>
+ <location filename="../../src/courtroom.cpp" line="3468"/>
<source>Master</source>
<translation>Мастер</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4309"/>
+ <location filename="../../src/courtroom.cpp" line="3968"/>
+ <source>Expand All Categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3970"/>
+ <source>Collapse All Categories</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3974"/>
+ <source>Fade Out Previous</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3980"/>
+ <source>Fade In</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="3986"/>
+ <source>Synchronize</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4256"/>
+ <source>Default</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/courtroom.cpp" line="4417"/>
<source>Reason:</source>
<translation>Причина:</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4310"/>
+ <location filename="../../src/courtroom.cpp" line="4418"/>
<source>Call Moderator</source>
<translation>Позвать модератора</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4426"/>
+ <location filename="../../src/courtroom.cpp" line="4430"/>
<source>Error</source>
<translation>Ошибка</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4318"/>
+ <location filename="../../src/courtroom.cpp" line="4426"/>
<source>You must provide a reason.</source>
<translation>Укажите причину.</translation>
</message>
<message>
- <location filename="../../src/courtroom.cpp" line="4322"/>
+ <location filename="../../src/courtroom.cpp" line="4430"/>
<source>The message is too long.</source>
<translation>Слишком длинный текст.</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="25"/>
<source>Choose...</source>
- <translation>Выбрать...</translation>
+ <translation type="vanished">Выбрать...</translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="17"/>
+ <source>Present this piece of evidence to everyone on your next spoken message</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="24"/>
+ <source>Save evidence to an .ini file.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="26"/>
+ <source>Load evidence from an .ini file.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="31"/>
+ <source>Destroy this piece of evidence</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="34"/>
+ <source>Choose..</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="37"/>
+ <source>Close the evidence display/editing overlay.
+You will be prompted if there&apos;s any unsaved changes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="40"/>
+ <source>Save any changes made to this piece of evidence and send them to server.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="48"/>
+ <source>Double-click to edit. Press [X] to update your changes.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="104"/>
+ <source>Bring up the Evidence screen.</source>
+ <translation type="unfinished"></translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="208"/>
+ <location filename="../../src/evidence.cpp" line="147"/>
+ <source>Switch evidence to private inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="151"/>
+ <source>Switch evidence to global inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="158"/>
+ <location filename="../../src/evidence.cpp" line="617"/>
+ <source>Transfer evidence to private inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="163"/>
+ <location filename="../../src/evidence.cpp" line="627"/>
+ <source>Transfer evidence to global inventory.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="263"/>
+ <source>The piece of evidence you&apos;ve been editing has changed.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="264"/>
+ <source>Do you wish to keep your changes?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="265"/>
+ <source>Name: %1
+Image: %2
+Description:
+%3</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="387"/>
<source>Images (*.png)</source>
<translation>Изображения (*.png)</translation>
</message>
<message>
- <location filename="../../src/evidence.cpp" line="280"/>
+ <location filename="../../src/evidence.cpp" line="456"/>
+ <location filename="../../src/evidence.cpp" line="460"/>
+ <location filename="../../src/evidence.cpp" line="463"/>
+ <source>Double-click to edit...</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="478"/>
<source>Add new evidence...</source>
<translation>Добавить новую улику...</translation>
</message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="556"/>
+ <source>Evidence has been modified.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="557"/>
+ <source>Do you want to save your changes?</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="619"/>
+ <source>Current evidence is global. Click to switch to private.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="629"/>
+ <source>Current evidence is private. Click to switch to global.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="659"/>
+ <source>&quot;%1&quot; has been transferred.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="721"/>
+ <source>Save Inventory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="721"/>
+ <location filename="../../src/evidence.cpp" line="747"/>
+ <source>Ini Files (*.ini)</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/evidence.cpp" line="747"/>
+ <source>Open Inventory</source>
+ <translation type="unfinished"></translation>
+ </message>
</context>
<context>
<name>Lobby</name>
@@ -931,35 +1312,55 @@ Cases you can load: %1</source>
<translation>Attorney Online 2</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="29"/>
+ <location filename="../../src/lobby.cpp" line="31"/>
+ <source>Search</source>
+ <translation type="unfinished">Поиск</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="39"/>
<source>Name</source>
<translation>Никнейм</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="82"/>
+ <location filename="../../src/lobby.cpp" line="94"/>
<source>It doesn&apos;t look like your client is set up correctly.
Did you download all resources correctly from tiny.cc/getao, including the large &apos;base&apos; folder?</source>
<translation>Не похоже, что ваш клиент установлен правильно.
Скачали ли вы все ресурсы (tiny.cc/getao), включая огромную папку `base`?</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="111"/>
+ <location filename="../../src/lobby.cpp" line="123"/>
<source>Version: %1</source>
<translation>Версия: %1</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="155"/>
+ <location filename="../../src/lobby.cpp" line="129"/>
+ <source>Settings</source>
+ <translation type="unfinished">Настройки</translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="132"/>
+ <source>Allows you to change various aspects of the client.</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="176"/>
<source>Loading</source>
<translation>Загрузка</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="159"/>
+ <location filename="../../src/lobby.cpp" line="180"/>
<source>Cancel</source>
<translation>Отмена</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="279"/>
- <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Cents02&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, Raidensnake</source>
+ <location filename="../../src/lobby.cpp" line="360"/>
+ <source>&lt;h2&gt;Attorney Online %1&lt;/h2&gt;The courtroom drama simulator&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Major development:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;2.8 Major Release development:&lt;/b&gt;&lt;br&gt;Crystalwarrior, Iamgoofball&lt;p&gt;&lt;b&gt;2.8 Quality Assurance:&lt;/b&gt;&lt;br&gt;WillDean, Captain N, Mr M, Riel, Seimmet, Fury McFlurry,CedricDewitt, Chewable Tablets, Fantos, Futugaze,Geck, Minx, Pandae, Sierra, CrazyJC, CaseyMayCazy,GreenBowers, Robotic Overlord, Veritas, Gin-Gi&lt;p&gt;&lt;b&gt;Special thanks:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, the AO2 community, server hosts, game masters,case makers, content creators and players!</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/lobby.cpp" line="380"/>
+ <source>About</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -967,18 +1368,33 @@ Did you download all resources correctly from tiny.cc/getao, including the large
<translation type="vanished">&lt;h2&gt;Attorney Online %1&lt;/h2&gt;Симулятор судебной драмы&lt;p&gt;&lt;b&gt;Исходный код:&lt;/b&gt; &lt;a href=&apos;https://github.com/AttorneyOnline/AO2-Client&apos;&gt;https://github.com/AttorneyOnline/AO2-Client&lt;/a&gt;&lt;p&gt;&lt;b&gt;Основной разработкой занимались:&lt;/b&gt;&lt;br&gt;OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter&lt;p&gt;&lt;b&gt;Особенная благодарность:&lt;/b&gt;&lt;br&gt;Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (дизайн интерфейса), Draxirch (дизайн интерфейса), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="395"/>
+ <location filename="../../src/lobby.cpp" line="521"/>
<source>Online: %1/%2</source>
<translation>Онлайн: %1/%2</translation>
</message>
<message>
- <location filename="../../src/lobby.cpp" line="121"/>
- <location filename="../../src/lobby.cpp" line="327"/>
+ <location filename="../../src/lobby.cpp" line="142"/>
+ <location filename="../../src/lobby.cpp" line="418"/>
<source>Offline</source>
<translation>Вне сети</translation>
</message>
</context>
<context>
+ <name>chatlogpiece</name>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="5"/>
+ <location filename="../../src/chatlogpiece.cpp" line="6"/>
+ <location filename="../../src/chatlogpiece.cpp" line="7"/>
+ <source>UNKNOWN</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../../src/chatlogpiece.cpp" line="55"/>
+ <source> has played a song: </source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>debug_functions</name>
<message>
<location filename="../../src/debug_functions.cpp" line="10"/>
@@ -991,7 +1407,7 @@ Did you download all resources correctly from tiny.cc/getao, including the large
<translation>Ошибка</translation>
</message>
<message>
- <location filename="../../src/debug_functions.cpp" line="26"/>
+ <location filename="../../src/debug_functions.cpp" line="25"/>
<source>Notice</source>
<translation>На заметку</translation>
</message>
diff --git a/resources.qrc b/resources.qrc
index 1229bc80..cca23ef6 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -1,13 +1,13 @@
<RCC>
<qresource prefix="/">
<file>resource/fonts/Ace-Attorney.ttf</file>
- <file>resource/logo.png</file>
+ <file>resource/logo_ao2.png</file>
<file>resource/translations/ao_de.qm</file>
<file>resource/translations/ao_en.qm</file>
- <file>resource/translations/ao_jp.qm</file>
<file>resource/translations/ao_es.qm</file>
+ <file>resource/translations/ao_jp.qm</file>
+ <file>resource/translations/ao_pl.qm</file>
<file>resource/translations/ao_pt.qm</file>
<file>resource/translations/ao_ru.qm</file>
- <file>resource/translations/ao_pl.qm</file>
</qresource>
</RCC>
diff --git a/scripts/macos_build.sh b/scripts/macos_build.sh
index efb7653f..fb631e9f 100755
--- a/scripts/macos_build.sh
+++ b/scripts/macos_build.sh
@@ -30,4 +30,4 @@ tar -xvf apng.tar.xz
cp clang_64/plugins/imageformats/libqapng.dylib ../lib
cd ..
-/usr/local/opt/qt/bin/qmake && make -j2
+/usr/local/opt/qt/bin/qmake "DEFINES += DISCORD QTAUDIO" && make -j2
diff --git a/scripts/macos_post_build.sh b/scripts/macos_post_build.sh
index df1475c4..2ed73649 100755
--- a/scripts/macos_post_build.sh
+++ b/scripts/macos_post_build.sh
@@ -20,5 +20,6 @@ cp ../lib/* ../bin/Attorney_Online.app/Contents/Frameworks
# libbass has a funny path for some reason, just use rpath
install_name_tool -change @loader_path/libbass.dylib @rpath/libbass.dylib ../bin/Attorney_Online.app/Contents/MacOS/Attorney_Online
+install_name_tool -change @loader_path/libbassopus.dylib @rpath/libbassopus.dylib ../bin/Attorney_Online.app/Contents/MacOS/Attorney_Online
-zip -r -9 ../bin/Attorney_Online_mac_x86_64.zip ../bin/ \ No newline at end of file
+zip -r -9 ../bin/Attorney_Online_macOS.zip ../bin/ \ No newline at end of file
diff --git a/scripts/release_macos.sh b/scripts/release_macos.sh
new file mode 100755
index 00000000..50acb408
--- /dev/null
+++ b/scripts/release_macos.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# This script prepares the compiled bundle for shipping as a standalone release
+# Assumes the Qt bin folder is in PATH
+# Should be used on a "Release" build from QT creator
+# Note that this DOES NOT add the base/ folder
+
+# Exit on errors and unset variables
+set -eu
+
+ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/"
+
+cd ${ROOT_DIR}
+
+# This thing basically does all the work
+macdeployqt ../bin/Attorney_Online.app
+
+# Need to add the dependencies
+cp ../lib/* ../bin/Attorney_Online.app/Contents/Frameworks
+
+# libbass has a funny path for some reason, just use rpath
+install_name_tool -change @loader_path/libbass.dylib @rpath/libbass.dylib ../bin/Attorney_Online.app/Contents/MacOS/Attorney_Online
diff --git a/src/aoapplication.cpp b/src/aoapplication.cpp
index 3b5e836d..e1e9e7fe 100644
--- a/src/aoapplication.cpp
+++ b/src/aoapplication.cpp
@@ -1,12 +1,13 @@
#include "aoapplication.h"
-#include "aocaseannouncerdialog.h"
-#include "aooptionsdialog.h"
#include "courtroom.h"
#include "debug_functions.h"
#include "lobby.h"
#include "networkmanager.h"
+#include "aocaseannouncerdialog.h"
+#include "aooptionsdialog.h"
+
AOApplication::AOApplication(int &argc, char **argv) : QApplication(argc, argv)
{
// Create the QSettings class that points to the config.ini.
@@ -125,7 +126,6 @@ void AOApplication::add_favorite_server(int p_server)
void AOApplication::server_disconnected()
{
if (courtroom_constructed) {
- beep();
call_notice(tr("Disconnected from server."));
construct_lobby();
destruct_courtroom();
@@ -135,6 +135,7 @@ void AOApplication::server_disconnected()
void AOApplication::loading_cancelled()
{
destruct_courtroom();
+
w_lobby->hide_loading_overlay();
}
diff --git a/src/aoblipplayer.cpp b/src/aoblipplayer.cpp
index 7d598b5f..57b2d278 100644
--- a/src/aoblipplayer.cpp
+++ b/src/aoblipplayer.cpp
@@ -9,13 +9,17 @@ AOBlipPlayer::AOBlipPlayer(QWidget *parent, AOApplication *p_ao_app)
void AOBlipPlayer::set_blips(QString p_sfx)
{
- QString f_path = ao_app->get_sounds_path(p_sfx);
+ QString f_path = ao_app->get_sfx_suffix(ao_app->get_sounds_path(p_sfx));
for (int n_stream = 0; n_stream < 5; ++n_stream) {
BASS_StreamFree(m_stream_list[n_stream]);
- m_stream_list[n_stream] = BASS_StreamCreateFile(
- FALSE, f_path.utf16(), 0, 0, BASS_UNICODE | BASS_ASYNCFILE);
+ if (f_path.endsWith(".opus"))
+ m_stream_list[n_stream] = BASS_OPUS_StreamCreateFile(
+ FALSE, f_path.utf16(), 0, 0, BASS_UNICODE | BASS_ASYNCFILE);
+ else
+ m_stream_list[n_stream] = BASS_StreamCreateFile(
+ FALSE, f_path.utf16(), 0, 0, BASS_UNICODE | BASS_ASYNCFILE);
}
set_volume_internal(m_volume);
@@ -23,6 +27,10 @@ void AOBlipPlayer::set_blips(QString p_sfx)
void AOBlipPlayer::blip_tick()
{
+ if (delay.isValid() && delay.elapsed() < max_blip_ms)
+ return;
+
+ delay.start();
int f_cycle = m_cycle++;
if (m_cycle == 5)
@@ -34,15 +42,15 @@ void AOBlipPlayer::blip_tick()
BASS_ChannelPlay(f_stream, false);
}
-void AOBlipPlayer::set_volume(qreal p_value)
+void AOBlipPlayer::set_volume(int p_value)
{
- m_volume = p_value / 100;
+ m_volume = static_cast<qreal>(p_value) / 100;
set_volume_internal(m_volume);
}
void AOBlipPlayer::set_volume_internal(qreal p_value)
{
- float volume = p_value;
+ float volume = static_cast<float>(p_value);
for (int n_stream = 0; n_stream < 5; ++n_stream) {
BASS_ChannelSetAttribute(m_stream_list[n_stream], BASS_ATTRIB_VOL, volume);
@@ -63,12 +71,12 @@ void AOBlipPlayer::set_blips(QString p_sfx)
m_blips.setSource(QUrl::fromLocalFile(f_path));
}
- set_volume_internal(m_volume);
+ set_volume(m_volume);
}
void AOBlipPlayer::blip_tick()
{
- m_cycle++;
+ int f_cycle = m_cycle++;
if (m_cycle == 5)
m_cycle = 0;
@@ -76,14 +84,9 @@ void AOBlipPlayer::blip_tick()
m_blips.play();
}
-void AOBlipPlayer::set_volume(qreal p_value)
-{
- m_volume = p_value / 100;
- set_volume_internal(m_volume);
-}
-
-void AOBlipPlayer::set_volume_internal(qreal p_value)
+void AOBlipPlayer::set_volume(int p_value)
{
+ m_volume = p_value;
m_blips.setVolume(m_volume);
}
#else // No audio
@@ -97,7 +100,7 @@ void AOBlipPlayer::set_blips(QString p_sfx) {}
void AOBlipPlayer::blip_tick() {}
-void AOBlipPlayer::set_volume(qreal p_value) {}
+void AOBlipPlayer::set_volume(int p_value) {}
void AOBlipPlayer::set_volume_internal(qreal p_value) {}
#endif
diff --git a/src/aobutton.cpp b/src/aobutton.cpp
index fee946a4..dc2d8817 100644
--- a/src/aobutton.cpp
+++ b/src/aobutton.cpp
@@ -13,11 +13,26 @@ AOButton::~AOButton() {}
void AOButton::set_image(QString p_image)
{
- QString image_path = ao_app->get_theme_path(p_image);
- QString default_image_path = ao_app->get_default_theme_path(p_image);
+ QString image_path =
+ ao_app->get_static_image_suffix(ao_app->get_theme_path(p_image));
+ QString default_image_path =
+ ao_app->get_static_image_suffix(ao_app->get_default_theme_path(p_image));
- if (file_exists(image_path))
- this->setStyleSheet("border-image:url(\"" + image_path + "\")");
+ if (file_exists(image_path)) {
+ this->setText("");
+ this->setStyleSheet("QPushButton { border-image: url(\"" + image_path +
+ "\") 0 0 0 0 stretch stretch; }"
+ "QToolTip { background-image: url(); color: #000000; "
+ "background-color: #ffffff; border: 0px; }");
+ }
+ else if (file_exists(default_image_path)) {
+ this->setText("");
+ this->setStyleSheet("QPushButton { border-image: url(\"" +
+ default_image_path +
+ "\"); }"
+ "QToolTip { background-image: url(); color: #000000; "
+ "background-color: #ffffff; border: 0px; }");
+ }
else
- this->setStyleSheet("border-image:url(\"" + default_image_path + "\")");
+ return;
}
diff --git a/src/aocaseannouncerdialog.cpp b/src/aocaseannouncerdialog.cpp
index 0a287c37..d91433a6 100644
--- a/src/aocaseannouncerdialog.cpp
+++ b/src/aocaseannouncerdialog.cpp
@@ -62,15 +62,12 @@ AOCaseAnnouncerDialog::AOCaseAnnouncerDialog(QWidget *parent,
ui_juror_needed->setText(tr("Jurors needed"));
ui_steno_needed = new QCheckBox(this);
ui_steno_needed->setText(tr("Stenographer needed"));
- ui_witness_needed = new QCheckBox(this);
- ui_witness_needed->setText(tr("Witness needed"));
ui_form_layout->setWidget(1, QFormLayout::FieldRole, ui_defense_needed);
ui_form_layout->setWidget(2, QFormLayout::FieldRole, ui_prosecutor_needed);
ui_form_layout->setWidget(3, QFormLayout::FieldRole, ui_judge_needed);
ui_form_layout->setWidget(4, QFormLayout::FieldRole, ui_juror_needed);
ui_form_layout->setWidget(5, QFormLayout::FieldRole, ui_steno_needed);
- ui_form_layout->setWidget(6, QFormLayout::FieldRole, ui_witness_needed);
setUpdatesEnabled(true);
}
@@ -80,8 +77,7 @@ void AOCaseAnnouncerDialog::ok_pressed()
court->announce_case(
ui_case_title_textbox->text(), ui_defense_needed->isChecked(),
ui_prosecutor_needed->isChecked(), ui_judge_needed->isChecked(),
- ui_juror_needed->isChecked(), ui_steno_needed->isChecked(),
- ui_witness_needed->isChecked());
+ ui_juror_needed->isChecked(), ui_steno_needed->isChecked());
done(0);
}
diff --git a/src/aocharbutton.cpp b/src/aocharbutton.cpp
index 5c8a73bb..844c9599 100644
--- a/src/aocharbutton.cpp
+++ b/src/aocharbutton.cpp
@@ -17,7 +17,7 @@ AOCharButton::AOCharButton(QWidget *parent, AOApplication *p_ao_app, int x_pos,
ui_taken = new AOImage(this, ao_app);
ui_taken->resize(60, 60);
- ui_taken->set_image("char_taken.png");
+ ui_taken->set_image("char_taken");
ui_taken->setAttribute(Qt::WA_TransparentForMouseEvents);
ui_taken->hide();
@@ -30,7 +30,7 @@ AOCharButton::AOCharButton(QWidget *parent, AOApplication *p_ao_app, int x_pos,
ui_selector = new AOImage(parent, ao_app);
ui_selector->resize(62, 62);
ui_selector->move(x_pos - 1, y_pos - 1);
- ui_selector->set_image("char_selector.png");
+ ui_selector->set_image("char_selector");
ui_selector->setAttribute(Qt::WA_TransparentForMouseEvents);
ui_selector->hide();
}
@@ -59,13 +59,21 @@ void AOCharButton::set_passworded() { ui_passworded->show(); }
void AOCharButton::set_image(QString p_character)
{
- QString image_path = ao_app->get_character_path(p_character, "char_icon.png");
+ QString image_path = ao_app->get_static_image_suffix(
+ ao_app->get_character_path(p_character, "char_icon"));
+
this->setText("");
- if (file_exists(image_path))
- this->setStyleSheet("border-image:url(\"" + image_path + "\")");
+ if (file_exists(image_path)) {
+ this->setStyleSheet("QPushButton { border-image: url(\"" + image_path +
+ "\") 0 0 0 0 stretch stretch; }"
+ "QToolTip { background-image: url(); color: #000000; "
+ "background-color: #ffffff; border: 0px; }");
+ }
else {
- this->setStyleSheet("border-image:url()");
+ this->setStyleSheet("QPushButton { border-image: url(); }"
+ "QToolTip { background-image: url(); color: #000000; "
+ "background-color: #ffffff; border: 0px; }");
this->setText(p_character);
}
}
diff --git a/src/aocharmovie.cpp b/src/aocharmovie.cpp
index 4252923a..252aab5d 100644
--- a/src/aocharmovie.cpp
+++ b/src/aocharmovie.cpp
@@ -8,248 +8,276 @@ AOCharMovie::AOCharMovie(QWidget *p_parent, AOApplication *p_ao_app)
: QLabel(p_parent)
{
ao_app = p_ao_app;
- m_movie = new QMovie(this);
preanim_timer = new QTimer(this);
- ticker = new QTimer(this);
preanim_timer->setSingleShot(true);
- ticker->setSingleShot(true);
+
+ ticker = new QTimer(this);
+ ticker->setTimerType(Qt::PreciseTimer);
+ ticker->setSingleShot(false);
connect(ticker, SIGNAL(timeout()), this, SLOT(movie_ticker()));
- this->setUpdatesEnabled(true);
+
+ // connect(m_movie, SIGNAL(frameChanged(int)), this,
+ // SLOT(frame_change(int)));
+ connect(preanim_timer, SIGNAL(timeout()), this, SLOT(preanim_done()));
}
-void AOCharMovie::play(QString p_char, QString p_emote, QString emote_prefix)
+void AOCharMovie::load_image(QString p_char, QString p_emote,
+ QString emote_prefix)
{
- apng = false;
-
- QString original_path =
- ao_app->get_character_path(p_char, emote_prefix + p_emote + ".gif");
- QString alt_path =
- ao_app->get_character_path(p_char, emote_prefix + p_emote + ".png");
- QString apng_path =
- ao_app->get_character_path(p_char, emote_prefix + p_emote + ".apng");
- QString alt_path_still = ao_app->get_character_path(p_char, p_emote + ".png");
-
- QString placeholder_path = ao_app->get_theme_path("placeholder.gif");
- QString placeholder_default_path =
- ao_app->get_default_theme_path("placeholder.gif");
- QString gif_path;
- current_emote = emote_prefix + p_emote;
- current_char = p_char;
- if (file_exists(apng_path)) {
- gif_path = apng_path;
- apng = true;
+#ifdef DEBUG_CHARMOVIE
+ actual_time.restart();
+#endif
+ QString emote_path;
+ QList<QString> pathlist;
+ pathlist = {
+ ao_app->get_image_suffix(ao_app->get_character_path(
+ p_char, emote_prefix + p_emote)), // Default path
+ ao_app->get_image_suffix(ao_app->get_character_path(
+ p_char, emote_prefix + "/" +
+ p_emote)), // Path check if it's categorized into a folder
+ ao_app->get_character_path(
+ p_char, p_emote + ".png"), // Non-animated path if emote_prefix fails
+ ao_app->get_image_suffix(
+ ao_app->get_theme_path("placeholder")), // Theme placeholder path
+ ao_app->get_image_suffix(ao_app->get_default_theme_path(
+ "placeholder")), // Default theme placeholder path
+ };
+
+ for (QString path : pathlist) {
+ if (file_exists(path)) {
+ emote_path = path;
+ break;
+ }
}
- else if (file_exists(original_path))
- gif_path = original_path;
- else if (file_exists(alt_path))
- gif_path = alt_path;
- else if (file_exists(alt_path_still))
- gif_path = alt_path_still;
- else if (file_exists(placeholder_path))
- gif_path = placeholder_path;
- else
- gif_path = placeholder_default_path;
- last_path = gif_path;
- delete m_movie;
- m_movie = new QMovie(this);
- m_movie->stop();
+
this->clear();
- m_movie->setFileName(gif_path);
- m_movie->jumpToFrame(0);
- this->LoadImageWithStupidMethodForFlipSupport(m_movie->currentImage());
+ ticker->stop();
+ preanim_timer->stop();
+ movie_frames.clear();
+ movie_delays.clear();
+ movie_effects.clear();
+
+ if (!file_exists(emote_path))
+ return;
+
+ m_reader->setFileName(emote_path);
+ QPixmap f_pixmap = this->get_pixmap(m_reader->read());
+ int f_delay = m_reader->nextImageDelay();
+
+ frame = 0;
+ max_frames = m_reader->imageCount();
+
+ this->set_frame(f_pixmap);
this->show();
- this->play_frame_sfx();
- // if the frame count is 0 (i.e. it's a static PNG) don't try to play the next
- // frame, ya goofus
- if (m_movie->frameCount() != 0) {
- ticker->start(m_movie->nextFrameDelay());
+ if (max_frames > 1) {
+ movie_frames.append(f_pixmap);
+ movie_delays.append(f_delay);
}
-}
-void AOCharMovie::play_frame_sfx()
-{
- int current_frame = m_movie->currentFrameNumber();
- QString sfx_to_play =
- ao_app->get_frame_sfx_name(current_char, current_emote, current_frame);
- QString screenshake_to_play =
- ao_app->get_screenshake_frame(current_char, current_emote, current_frame);
- QString realization_to_play =
- ao_app->get_realization_frame(current_char, current_emote, current_frame);
- if (sfx_to_play != "" && !use_networked_framehell) {
- frame_specific_sfx_player->play(ao_app->get_sfx_suffix(sfx_to_play));
- }
- else if (use_networked_framehell) {
- this->sfx_two_network_boogaloo();
- }
- if (screenshake_to_play != "" && !use_networked_framehell) {
- mycourtroom->doScreenShake();
- }
- else if (use_networked_framehell) {
- this->screenshake_two_network_boogaloo();
- }
- if (realization_to_play != "" && !use_networked_framehell) {
- mycourtroom->doRealization();
- }
- else if (use_networked_framehell) {
- this->realization_two_network_boogaloo();
- }
-}
+ m_char = p_char;
+ m_emote = emote_prefix + p_emote;
-void AOCharMovie::realization_two_network_boogaloo()
-{
- int current_frame = m_movie->currentFrameNumber();
- QStringList realizationList = this->frame_realization_hellstring.split("^");
- for (int i = 0; i < realizationList.length(); i++) {
- QString screenshakeList = realizationList.at(i);
- QStringList extra_garbage = screenshakeList.split("|");
- if (extra_garbage.at(0) != current_emote) {
- continue;
- }
- for (int ii = 1; ii < extra_garbage.length(); ii++) {
- QString levels_of_garbage = extra_garbage.at(ii);
- QStringList that_shouldnt_be_possible = levels_of_garbage.split("=");
- if (that_shouldnt_be_possible.at(0).toInt() == current_frame &&
- that_shouldnt_be_possible.at(1) != "") {
- mycourtroom->doRealization();
- }
- }
- }
+ if (network_strings.size() > 0) // our FX overwritten by networked ones
+ this->load_network_effects();
+ else // Use default ini FX
+ this->load_effects();
+#ifdef DEBUG_CHARMOVIE
+ qDebug() << max_frames << "Setting image to " << emote_path
+ << "Time taken to process image:" << actual_time.elapsed();
+
+ actual_time.restart();
+#endif
}
-void AOCharMovie::screenshake_two_network_boogaloo()
+void AOCharMovie::load_effects()
{
- int current_frame = m_movie->currentFrameNumber();
- QStringList realizationList = this->frame_screenshake_hellstring.split("^");
- for (int i = 0; i < realizationList.length(); i++) {
- QString screenshakeList = realizationList.at(i);
- QStringList extra_garbage = screenshakeList.split("|");
- if (extra_garbage.at(0) != current_emote) {
- continue;
- }
- for (int ii = 1; ii < extra_garbage.length(); ii++) {
- QString levels_of_garbage = extra_garbage.at(ii);
- QStringList that_shouldnt_be_possible = levels_of_garbage.split("=");
- if (that_shouldnt_be_possible.at(0).toInt() == current_frame &&
- that_shouldnt_be_possible.at(1) != "") {
- mycourtroom->doScreenShake();
- }
+ movie_effects.clear();
+ movie_effects.resize(max_frames);
+ for (int e_frame = 0; e_frame < max_frames; ++e_frame) {
+ QString effect = ao_app->get_screenshake_frame(m_char, m_emote, e_frame);
+ if (effect != "") {
+ movie_effects[e_frame].append("shake");
}
- }
-}
-void AOCharMovie::sfx_two_network_boogaloo()
-{
- int current_frame = m_movie->currentFrameNumber();
- QStringList realizationList = this->frame_sfx_hellstring.split("^");
- for (int i = 0; i < realizationList.length(); i++) {
- QString screenshakeList = realizationList.at(i);
- QStringList extra_garbage = screenshakeList.split("|");
- if (extra_garbage.at(0) != current_emote) {
- continue;
+ effect = ao_app->get_flash_frame(m_char, m_emote, e_frame);
+ if (effect != "") {
+ movie_effects[e_frame].append("flash");
}
- for (int ii = 1; ii < extra_garbage.length(); ii++) {
- QString levels_of_garbage = extra_garbage.at(ii);
- QStringList that_shouldnt_be_possible = levels_of_garbage.split("=");
- if (that_shouldnt_be_possible.at(0).toInt() == current_frame &&
- that_shouldnt_be_possible.at(1) != "") {
- frame_specific_sfx_player->play(
- ao_app->get_sfx_suffix(that_shouldnt_be_possible.at(1)));
- }
+
+ effect = ao_app->get_sfx_frame(m_char, m_emote, e_frame);
+ if (effect != "") {
+ movie_effects[e_frame].append("sfx^" + effect);
}
}
}
-void AOCharMovie::movie_ticker()
+void AOCharMovie::load_network_effects()
{
- if (m_movie->currentFrameNumber() == m_movie->frameCount() - 1) {
- delete m_movie;
- m_movie = new QMovie(this);
- m_movie->stop();
- this->clear();
- m_movie->setFileName(last_path);
- m_movie->jumpToFrame(0);
- if (play_once) {
- timer_done();
- }
- }
- else {
- m_movie->jumpToNextFrame();
- }
- this->LoadImageWithStupidMethodForFlipSupport(m_movie->currentImage());
- // imagine if QT had sane stuff like "mirror on QMovie" or "resize the image
- // on QT" or "interface with the current QMovie image" or anything else
+ movie_effects.clear();
+ movie_effects.resize(max_frames);
+ // Order is important!!!
+ QStringList effects_list = {"shake", "flash", "sfx^"};
- this->play_frame_sfx();
+ // Determines which list is smaller - effects_list or network_strings - and
+ // uses it as basis for the loop. This way, incomplete network_strings would
+ // still be parsed, and excess/unaccounted for networked information is
+ // omitted.
+ int effects_size = qMin(effects_list.size(), network_strings.size());
- if (m_movie->frameCount() == 0) {
- return;
- }
- else if (!apng) {
- ticker->start(m_movie->nextFrameDelay());
+ for (int i = 0; i < effects_size; ++i) {
+ QString netstring = network_strings.at(i);
+ QStringList emote_splits = netstring.split("^");
+ foreach (QString emote, emote_splits) {
+ QStringList parsed = emote.split("|");
+ if (parsed.size() <= 0 || parsed.at(0) != m_emote)
+ continue;
+ foreach (QString frame_data, parsed) {
+ QStringList frame_split = frame_data.split("=");
+ if (frame_split.size() <=
+ 1) // We might still be hanging at the emote itself (entry 0).
+ continue;
+ int f_frame = frame_split.at(0).toInt();
+ if (f_frame >= max_frames) {
+ qDebug() << "Warning: out of bounds" << effects_list[i] << "frame"
+ << f_frame << "out of" << max_frames << "for" << m_char
+ << m_emote;
+ continue;
+ }
+ QString f_data = frame_split.at(1);
+ if (f_data != "") {
+ QString effect = effects_list[i];
+ if (effect == "sfx^") // Currently the only frame result that feeds us
+ // data, let's yank it in.
+ effect += f_data;
+ qDebug() << effect << f_data << "frame" << f_frame << "for" << m_char
+ << m_emote;
+ movie_effects[f_frame].append(effect);
+ }
+ }
+ }
}
}
-void AOCharMovie::LoadImageWithStupidMethodForFlipSupport(QImage image)
+void AOCharMovie::play()
{
- QPixmap f_pixmap;
- if (m_flipped)
- f_pixmap = QPixmap::fromImage(image.mirrored(true, false));
- else
- f_pixmap = QPixmap::fromImage(image);
- auto aspect_ratio = Qt::KeepAspectRatio;
-
- if (f_pixmap.size().width() > f_pixmap.size().height())
- aspect_ratio = Qt::KeepAspectRatioByExpanding;
-
- if (f_pixmap.size().width() > this->size().width() ||
- f_pixmap.size().height() > this->size().height())
- this->setPixmap(f_pixmap.scaled(this->width(), this->height(), aspect_ratio,
- Qt::SmoothTransformation));
+ play_frame_effect(frame);
+ if (max_frames <= 1) {
+ if (play_once)
+ ticker->start(60);
+ }
else
- this->setPixmap(f_pixmap.scaled(this->width(), this->height(), aspect_ratio,
- Qt::FastTransformation));
-
- QLabel::move(x + (this->width() - this->pixmap()->width()) / 2, y);
+ ticker->start(this->get_frame_delay(movie_delays[frame]));
}
void AOCharMovie::play_pre(QString p_char, QString p_emote, int duration)
{
- QString gif_path = ao_app->get_character_path(p_char, p_emote);
-
- m_movie->stop();
- m_movie->setFileName(gif_path);
- m_movie->jumpToFrame(0);
+ load_image(p_char, p_emote, "");
+ // As much as I'd like to screw around with [Time] durations modifying the
+ // animation speed, I don't think I can reliably do that, not without looping
+ // through all frames in the image at least - which causes lag. So for now it
+ // simply ends the preanimation early instead.
play_once = true;
- play(p_char, p_emote, "");
+ if (duration >
+ 0) // It's -1 if there's no definition in [Time] for it. In which case, it
+ // will let the animation run out in full. Duration 0 does the same.
+ preanim_timer->start(duration *
+ time_mod); // This timer will not fire if the animation
+ // finishes earlier than that
+ play();
}
void AOCharMovie::play_talking(QString p_char, QString p_emote)
{
play_once = false;
- play(p_char, p_emote, "(b)");
+ load_image(p_char, p_emote, "(b)");
+ play();
}
void AOCharMovie::play_idle(QString p_char, QString p_emote)
{
play_once = false;
- play(p_char, p_emote, "(a)");
+ load_image(p_char, p_emote, "(a)");
+ play();
+}
+
+void AOCharMovie::play_frame_effect(int frame)
+{
+ if (frame < max_frames) {
+ foreach (QString effect, movie_effects[frame]) {
+ if (effect == "shake") {
+ shake();
+#ifdef DEBUG_CHARMOVIE
+ qDebug() << "Attempting to play shake on frame" << frame;
+#endif
+ }
+
+ if (effect == "flash") {
+ flash();
+#ifdef DEBUG_CHARMOVIE
+ qDebug() << "Attempting to play flash on frame" << frame;
+#endif
+ }
+
+ if (effect.startsWith("sfx^")) {
+ QString sfx = effect.section("^", 1);
+ play_sfx(sfx);
+#ifdef DEBUG_CHARMOVIE
+ qDebug() << "Attempting to play sfx" << sfx << "on frame" << frame;
+#endif
+ }
+ }
+ }
}
void AOCharMovie::stop()
{
// for all intents and purposes, stopping is the same as hiding. at no point
// do we want a frozen gif to display
- m_movie->stop();
- frame_specific_sfx_player->stop();
+ ticker->stop();
+ preanim_timer->stop();
this->hide();
}
+QPixmap AOCharMovie::get_pixmap(QImage image)
+{
+ QPixmap f_pixmap;
+ if (m_flipped)
+ f_pixmap = QPixmap::fromImage(image.mirrored(true, false));
+ else
+ f_pixmap = QPixmap::fromImage(image);
+ // auto aspect_ratio = Qt::KeepAspectRatio;
+ auto transform_mode = Qt::FastTransformation;
+ if (f_pixmap.height() > f_h) // We are downscaling, use anti-aliasing.
+ transform_mode = Qt::SmoothTransformation;
+
+ f_pixmap = f_pixmap.scaledToHeight(f_h, transform_mode);
+ this->resize(f_pixmap.size());
+
+ return f_pixmap;
+}
+
+void AOCharMovie::set_frame(QPixmap f_pixmap)
+{
+ this->setPixmap(f_pixmap);
+ QLabel::move(
+ x + (f_w - f_pixmap.width()) / 2,
+ y + (f_h - f_pixmap.height())); // Always center horizontally, always put
+ // at the bottom vertically
+}
+
void AOCharMovie::combo_resize(int w, int h)
{
QSize f_size(w, h);
+ f_w = w;
+ f_h = h;
this->resize(f_size);
- m_movie->setScaledSize(this->size());
}
+
+int AOCharMovie::get_frame_delay(int delay)
+{
+ return static_cast<int>(double(delay) * double(speed / 100));
+}
+
void AOCharMovie::move(int ax, int ay)
{
x = ax;
@@ -257,4 +285,39 @@ void AOCharMovie::move(int ax, int ay)
QLabel::move(x, y);
}
-void AOCharMovie::timer_done() { done(); }
+void AOCharMovie::movie_ticker()
+{
+ ++frame;
+ if (frame >= max_frames) {
+ if (play_once) {
+ preanim_done();
+ return;
+ }
+ else
+ frame = 0;
+ }
+ // qint64 difference = elapsed - movie_delays[frame];
+ if (frame >= movie_frames.size()) {
+ m_reader->jumpToImage(frame);
+ movie_frames.resize(frame + 1);
+ movie_frames[frame] = this->get_pixmap(m_reader->read());
+ movie_delays.resize(frame + 1);
+ movie_delays[frame] = m_reader->nextImageDelay();
+ }
+
+#ifdef DEBUG_CHARMOVIE
+ qDebug() << frame << movie_delays[frame]
+ << "actual time taken from last frame:" << actual_time.restart();
+#endif
+
+ this->set_frame(movie_frames[frame]);
+ play_frame_effect(frame);
+ ticker->setInterval(this->get_frame_delay(movie_delays[frame]));
+}
+
+void AOCharMovie::preanim_done()
+{
+ ticker->stop();
+ preanim_timer->stop();
+ done();
+}
diff --git a/src/aoemotebutton.cpp b/src/aoemotebutton.cpp
index 29329c98..90535607 100644
--- a/src/aoemotebutton.cpp
+++ b/src/aoemotebutton.cpp
@@ -1,34 +1,66 @@
#include "aoemotebutton.h"
-
#include "file_functions.h"
AOEmoteButton::AOEmoteButton(QWidget *p_parent, AOApplication *p_ao_app,
- int p_x, int p_y)
+ int p_x, int p_y, int p_w, int p_h)
: QPushButton(p_parent)
{
parent = p_parent;
ao_app = p_ao_app;
this->move(p_x, p_y);
- this->resize(40, 40);
+ this->resize(p_w, p_h);
connect(this, SIGNAL(clicked()), this, SLOT(on_clicked()));
}
-void AOEmoteButton::set_image(QString p_char, int p_emote, QString suffix)
+void AOEmoteButton::set_image(QString p_image, QString p_emote_comment)
{
- QString emotion_number = QString::number(p_emote + 1);
- QString image_path = ao_app->get_character_path(
- p_char, "emotions/button" + emotion_number + suffix);
+ QString tmp_p_image = p_image;
- if (file_exists(image_path)) {
+ if (file_exists(p_image)) {
this->setText("");
- this->setStyleSheet("border-image:url(\"" + image_path + "\")");
+ this->setStyleSheet(
+ "QPushButton { border-image: url(\"" + p_image +
+ "\") 0 0 0 0 stretch stretch; }"
+ "QToolTip { color: #000000; background-color: #ffffff; border: 0px; }");
+ }
+ else if (p_image.contains("_on") && file_exists(tmp_p_image.replace("_on", "_off"))) {
+ QImage tmpImage(tmp_p_image);
+ QPoint p1, p2;
+ p2.setY(tmpImage.height());
+
+ QLinearGradient gradient(p1, p2);
+ gradient.setColorAt(0, Qt::transparent);
+ gradient.setColorAt(1, QColor(0, 0, 0, 159));
+
+ QPainter p(&tmpImage);
+ p.fillRect(0, 0, tmpImage.width(), tmpImage.height(), gradient);
+
+ gradient.setColorAt(0, QColor(0, 0, 0, 159));
+ gradient.setColorAt(1, Qt::transparent);
+ p.fillRect(0, 0, tmpImage.width(), tmpImage.height(), gradient);
+
+ p.end();
+ tmpImage.save(p_image, "png");
+ set_image(p_image, p_emote_comment);
}
else {
- this->setText(ao_app->get_emote_comment(p_char, p_emote));
- this->setStyleSheet("border-image:url(\"\")");
+ this->setText(p_emote_comment);
+ this->setStyleSheet("QPushButton { border-image: url(); }"
+ "QToolTip { background-image: url(); color: #000000; "
+ "background-color: #ffffff; border: 0px; }");
}
}
+void AOEmoteButton::set_char_image(QString p_char, int p_emote, QString suffix)
+{
+ QString emotion_number = QString::number(p_emote + 1);
+ QString image_path =
+ ao_app->get_static_image_suffix(ao_app->get_character_path(
+ p_char, "emotions/button" + emotion_number + suffix));
+
+ this->set_image(image_path, ao_app->get_emote_comment(p_char, p_emote));
+}
+
void AOEmoteButton::on_clicked() { emote_clicked(m_id); }
diff --git a/src/aoevidencebutton.cpp b/src/aoevidencebutton.cpp
index d0a6ac1b..f85a223f 100644
--- a/src/aoevidencebutton.cpp
+++ b/src/aoevidencebutton.cpp
@@ -3,51 +3,55 @@
#include "file_functions.h"
AOEvidenceButton::AOEvidenceButton(QWidget *p_parent, AOApplication *p_ao_app,
- int p_x, int p_y)
+ int p_x, int p_y, int p_w, int p_h)
: QPushButton(p_parent)
{
ao_app = p_ao_app;
m_parent = p_parent;
- ui_selected = new AOImage(p_parent, ao_app);
- ui_selected->resize(70, 70);
- ui_selected->move(p_x, p_y);
- ui_selected->set_image("evidence_selected.png");
+ ui_selected = new AOImage(this, ao_app);
+ ui_selected->resize(p_w, p_h);
+ // ui_selected->move(p_x, p_y);
+ ui_selected->set_image("evidence_selected");
ui_selected->setAttribute(Qt::WA_TransparentForMouseEvents);
ui_selected->hide();
- ui_selector = new AOImage(p_parent, ao_app);
- ui_selector->resize(71, 71);
- ui_selector->move(p_x - 1, p_y - 1);
- ui_selector->set_image("evidence_selector.png");
+ ui_selector = new AOImage(this, ao_app);
+ ui_selector->resize(p_w, p_h);
+ // ui_selector->move(p_x - 1, p_y - 1);
+ ui_selector->set_image("evidence_selector");
ui_selector->setAttribute(Qt::WA_TransparentForMouseEvents);
ui_selector->hide();
this->move(p_x, p_y);
- this->resize(70, 70);
- this->setAcceptDrops(true);
+ this->resize(p_w, p_h);
+ // this->setAcceptDrops(true);
connect(this, SIGNAL(clicked()), this, SLOT(on_clicked()));
}
-void AOEvidenceButton::reset()
-{
- this->hide();
- ui_selected->hide();
- ui_selector->hide();
-}
-
void AOEvidenceButton::set_image(QString p_image)
{
QString image_path = ao_app->get_evidence_path(p_image);
-
- if (file_exists(image_path)) {
+ if (file_exists(p_image)) {
+ this->setText("");
+ this->setStyleSheet(
+ "QPushButton { border-image: url(\"" + p_image +
+ "\") 0 0 0 0 stretch stretch; }"
+ "QToolTip { color: #000000; background-color: #ffffff; border: 0px; }");
+ }
+ else if (file_exists(image_path)) {
this->setText("");
- this->setStyleSheet("border-image:url(\"" + image_path + "\")");
+ this->setStyleSheet(
+ "QPushButton { border-image: url(\"" + image_path +
+ "\") 0 0 0 0 stretch stretch; }"
+ "QToolTip { color: #000000; background-color: #ffffff; border: 0px; }");
}
else {
this->setText(p_image);
- this->setStyleSheet("");
+ this->setStyleSheet("QPushButton { border-image: url(); }"
+ "QToolTip { background-image: url(); color: #000000; "
+ "background-color: #ffffff; border: 0px; }");
}
}
@@ -63,8 +67,7 @@ void AOEvidenceButton::set_theme_image(QString p_image)
else
final_image_path = default_image_path;
- this->setText("");
- this->setStyleSheet("border-image:url(\"" + final_image_path + "\")");
+ this->set_image(final_image_path);
}
void AOEvidenceButton::set_selected(bool p_selected)
@@ -87,11 +90,15 @@ void AOEvidenceButton::mouseDoubleClickEvent(QMouseEvent *e)
void AOEvidenceButton::dragLeaveEvent(QMouseEvent *e)
{
//QWidget::dragLeaveEvent(e);
+
+ qDebug() << "drag leave event";
}
void AOEvidenceButton::dragEnterEvent(QMouseEvent *e)
{
//QWidget::dragEnterEvent(e);
+
+ qDebug() << "drag enter event";
}
*/
diff --git a/src/aoevidencedisplay.cpp b/src/aoevidencedisplay.cpp
index 9dd062b7..2ffea2c9 100644
--- a/src/aoevidencedisplay.cpp
+++ b/src/aoevidencedisplay.cpp
@@ -8,13 +8,12 @@ AOEvidenceDisplay::AOEvidenceDisplay(QWidget *p_parent, AOApplication *p_ao_app)
: QLabel(p_parent)
{
ao_app = p_ao_app;
-
- evidence_movie = new QMovie(this);
evidence_icon = new QLabel(this);
sfx_player = new AOSfxPlayer(this, ao_app);
- connect(evidence_movie, SIGNAL(frameChanged(int)), this,
- SLOT(frame_change(int)));
+ evidence_movie = new AOMovie(this, ao_app);
+
+ connect(evidence_movie, SIGNAL(done()), this, SLOT(show_done()));
}
void AOEvidenceDisplay::show_evidence(QString p_evidence_image,
@@ -24,64 +23,34 @@ void AOEvidenceDisplay::show_evidence(QString p_evidence_image,
sfx_player->set_volume(p_volume);
- QString f_evidence_path = ao_app->get_evidence_path(p_evidence_image);
-
- QPixmap f_pixmap(f_evidence_path);
-
QString final_gif_path;
QString gif_name;
QString icon_identifier;
if (is_left_side) {
icon_identifier = "left_evidence_icon";
- gif_name = "evidence_appear_left.gif";
+ gif_name = "evidence_appear_left";
}
else {
icon_identifier = "right_evidence_icon";
- gif_name = "evidence_appear_right.gif";
+ gif_name = "evidence_appear_right";
}
+ QString f_evidence_path = ao_app->get_evidence_path(p_evidence_image);
+ QPixmap f_pixmap(f_evidence_path);
+
pos_size_type icon_dimensions =
ao_app->get_element_dimensions(icon_identifier, "courtroom_design.ini");
+ f_pixmap = f_pixmap.scaled(icon_dimensions.width, icon_dimensions.height);
+ evidence_icon->setPixmap(f_pixmap);
+ evidence_icon->resize(f_pixmap.size());
evidence_icon->move(icon_dimensions.x, icon_dimensions.y);
- evidence_icon->resize(icon_dimensions.width, icon_dimensions.height);
-
- evidence_icon->setPixmap(f_pixmap.scaled(
- evidence_icon->width(), evidence_icon->height(), Qt::IgnoreAspectRatio));
-
- QString f_default_gif_path = ao_app->get_default_theme_path(gif_name);
- QString f_gif_path = ao_app->get_theme_path(gif_name);
-
- if (file_exists(f_gif_path))
- final_gif_path = f_gif_path;
- else
- final_gif_path = f_default_gif_path;
-
- evidence_movie->setFileName(final_gif_path);
- if (evidence_movie->frameCount() < 1)
- return;
-
- this->setMovie(evidence_movie);
-
- evidence_movie->start();
+ evidence_movie->play(gif_name);
sfx_player->play(ao_app->get_sfx("evidence_present"));
}
-void AOEvidenceDisplay::frame_change(int p_frame)
-{
- if (p_frame == (evidence_movie->frameCount() - 1)) {
- // we need this or else the last frame wont show
- delay(evidence_movie->nextFrameDelay());
-
- evidence_movie->stop();
- this->clear();
-
- evidence_icon->show();
- }
-}
-
void AOEvidenceDisplay::reset()
{
sfx_player->stop();
@@ -90,4 +59,13 @@ void AOEvidenceDisplay::reset()
this->clear();
}
+void AOEvidenceDisplay::show_done() { evidence_icon->show(); }
+
QLabel *AOEvidenceDisplay::get_evidence_icon() { return evidence_icon; }
+
+void AOEvidenceDisplay::combo_resize(int w, int h)
+{
+ QSize f_size(w, h);
+ this->resize(f_size);
+ evidence_movie->combo_resize(w, h);
+}
diff --git a/src/aoimage.cpp b/src/aoimage.cpp
index ffdf25aa..2663ba05 100644
--- a/src/aoimage.cpp
+++ b/src/aoimage.cpp
@@ -10,37 +10,42 @@ AOImage::AOImage(QWidget *parent, AOApplication *p_ao_app) : QLabel(parent)
AOImage::~AOImage() {}
-void AOImage::set_image(QString p_image)
+bool AOImage::set_image(QString p_image)
{
- QString theme_image_path = ao_app->get_theme_path(p_image);
- QString default_image_path = ao_app->get_default_theme_path(p_image);
+ QString theme_image_path =
+ ao_app->get_static_image_suffix(ao_app->get_theme_path(p_image));
+ QString default_image_path =
+ ao_app->get_static_image_suffix(ao_app->get_default_theme_path(p_image));
QString final_image_path;
if (file_exists(theme_image_path))
final_image_path = theme_image_path;
- else
+ else if (file_exists(default_image_path))
final_image_path = default_image_path;
+ else {
+ qDebug() << "Warning: Image" << p_image << "not found! Can't set!";
+ return false;
+ }
QPixmap f_pixmap(final_image_path);
this->setPixmap(
f_pixmap.scaled(this->width(), this->height(), Qt::IgnoreAspectRatio));
+ return true;
}
-void AOImage::set_image_from_path(QString p_path)
+bool AOImage::set_chatbox(QString p_path)
{
- QString default_path = ao_app->get_default_theme_path("chatmed.png");
+ p_path = ao_app->get_static_image_suffix(p_path);
+ if (!file_exists(p_path)) {
+ qDebug() << "Warning: Chatbox" << p_path << "not found! Can't set!";
+ return false;
+ }
- QString final_path;
-
- if (file_exists(p_path))
- final_path = p_path;
- else
- final_path = default_path;
-
- QPixmap f_pixmap(final_path);
+ QPixmap f_pixmap(p_path);
this->setPixmap(
f_pixmap.scaled(this->width(), this->height(), Qt::IgnoreAspectRatio));
+ return true;
}
diff --git a/src/aolineedit.cpp b/src/aolineedit.cpp
index 211d9f78..d80fa014 100644
--- a/src/aolineedit.cpp
+++ b/src/aolineedit.cpp
@@ -1,18 +1,22 @@
#include "aolineedit.h"
-AOLineEdit::AOLineEdit(QWidget *parent) : QLineEdit(parent)
-{
- this->setReadOnly(true);
- this->setFrame(false);
-
- connect(this, SIGNAL(returnPressed()), this, SLOT(on_enter_pressed()));
-}
+AOLineEdit::AOLineEdit(QWidget *parent) : QLineEdit(parent) {}
void AOLineEdit::mouseDoubleClickEvent(QMouseEvent *e)
{
QLineEdit::mouseDoubleClickEvent(e);
- this->setReadOnly(false);
+ double_clicked();
+}
+void AOLineEdit::focusOutEvent(QFocusEvent *ev)
+{
+ int start = selectionStart();
+#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
+ int len = selectionLength();
+#else
+ int len = selectedText().length();
+#endif
+ QLineEdit::focusOutEvent(ev);
+ if (p_selection && start != -1 && len != -1)
+ this->setSelection(start, len);
}
-
-void AOLineEdit::on_enter_pressed() { this->setReadOnly(true); }
diff --git a/src/aomovie.cpp b/src/aomovie.cpp
index 9ffd62f0..ac949219 100644
--- a/src/aomovie.cpp
+++ b/src/aomovie.cpp
@@ -1,116 +1,99 @@
-#include "aomovie.h"
-
-#include "courtroom.h"
-#include "file_functions.h"
-#include "misc_functions.h"
-
-AOMovie::AOMovie(QWidget *p_parent, AOApplication *p_ao_app) : QLabel(p_parent)
-{
- ao_app = p_ao_app;
-
- m_movie = new QMovie();
-
- this->setMovie(m_movie);
- timer = new QTimer(this);
- timer->setTimerType(Qt::PreciseTimer);
- timer->setSingleShot(true);
- connect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frame_change(int)));
- connect(timer, SIGNAL(timeout()), this, SLOT(timer_done()));
-}
-
-void AOMovie::set_play_once(bool p_play_once) { play_once = p_play_once; }
-void AOMovie::start_timer(int delay) { timer->start(delay); }
-
-void AOMovie::play(QString p_gif, QString p_char, QString p_custom_theme,
- int duration)
-{
-
- m_movie->stop();
- // this->timer_done();
- QString shout_path = p_gif;
- QList<QString> pathlist;
-
- if (ao_app->get_character_path(p_char, p_gif)
- .contains(
- "custom_objections")) // checks if the file is located within the
- // folder of custom objections
- pathlist << ao_app->get_character_path(
- p_char,
- p_gif); // get_image_suffix is unecessery as it is already given.
- else if (p_gif == "custom")
- pathlist << ao_app->get_image_suffix(
- ao_app->get_character_path(p_char, p_gif));
- else
- pathlist << ao_app->get_image_suffix(
- ao_app->get_character_path(p_char, p_gif + "_bubble"));
-
- QString misc_path = ao_app->get_base_path() + "misc/" + p_custom_theme + "/" +
- p_gif + "_bubble.gif";
- QString custom_theme_path =
- ao_app->get_custom_theme_path(p_custom_theme, p_gif + ".gif");
- QString theme_path = ao_app->get_theme_path(p_gif + ".gif");
- QString default_theme_path = ao_app->get_default_theme_path(p_gif + ".gif");
- QString placeholder_path = ao_app->get_theme_path("placeholder.gif");
- QString default_placeholder_path =
- ao_app->get_default_theme_path("placeholder.gif");
-
- pathlist << ao_app->get_image_suffix(ao_app->get_base_path() + "misc/" +
- p_custom_theme + "/" + p_gif + "_bubble")
- << // Misc path
- ao_app->get_image_suffix(
- ao_app->get_custom_theme_path(p_custom_theme, p_gif))
- << // Custom theme path
- ao_app->get_image_suffix(ao_app->get_theme_path(p_gif)) << // Theme path
- ao_app->get_image_suffix(ao_app->get_default_theme_path(p_gif))
- << // Default theme path
- ao_app->get_image_suffix(ao_app->get_theme_path("placeholder"))
- << // Placeholder path
- ao_app->get_image_suffix(ao_app->get_default_theme_path(
- "placeholder")); // Default placeholder path
-
- for (QString path : pathlist) {
- if (file_exists(path)) {
- shout_path = path;
- break;
- }
- }
- m_movie->setFileName(shout_path);
- if (m_movie->loopCount() == 0)
- play_once = true;
-
- this->show();
- m_movie->start();
- if (m_movie->frameCount() == 0 && duration > 0)
- timer->start(duration);
-}
-
-void AOMovie::stop()
-{
- m_movie->stop();
- this->hide();
-}
-
-void AOMovie::frame_change(int n_frame)
-{
- // If it's a "static movie" (only one frame - png image), we can't change
- // frames - ignore this function (use timer instead). If the frame didn't
- // reach the last frame or the movie is continuous, don't stop the movie.
- if (m_movie->frameCount() == 0 || n_frame < (m_movie->frameCount() - 1) ||
- !play_once)
- return;
- // we need this or else the last frame wont show
- timer->start(m_movie->nextFrameDelay());
-}
-
-void AOMovie::timer_done()
-{
- this->stop();
- done();
-}
-
-void AOMovie::combo_resize(int w, int h)
-{
- QSize f_size(w, h);
- this->resize(f_size);
- m_movie->setScaledSize(f_size);
-}
+#include "aomovie.h"
+
+#include "courtroom.h"
+#include "file_functions.h"
+#include "misc_functions.h"
+
+AOMovie::AOMovie(QWidget *p_parent, AOApplication *p_ao_app) : QLabel(p_parent)
+{
+ ao_app = p_ao_app;
+
+ m_movie = new QMovie();
+
+ this->setMovie(m_movie);
+
+ timer = new QTimer(this);
+ timer->setTimerType(Qt::PreciseTimer);
+ timer->setSingleShot(true);
+
+ connect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frame_change(int)));
+ connect(timer, SIGNAL(timeout()), this, SLOT(timer_done()));
+}
+
+void AOMovie::set_play_once(bool p_play_once) { play_once = p_play_once; }
+
+void AOMovie::play(QString p_image, QString p_char, QString p_custom_theme,
+ int duration)
+{
+ m_movie->stop();
+
+ QString shout_path = p_image;
+ if (!file_exists(p_image)) {
+ QList<QString> pathlist;
+
+ pathlist = {
+ ao_app->get_image_suffix(
+ ao_app->get_character_path(p_char, p_image)), // Character folder
+ ao_app->get_image_suffix(ao_app->get_base_path() + "misc/" +
+ p_custom_theme + "/" + p_image), // Misc path
+ ao_app->get_image_suffix(ao_app->get_custom_theme_path(
+ p_custom_theme, p_image)), // Custom theme path
+ ao_app->get_image_suffix(ao_app->get_theme_path(p_image)), // Theme path
+ ao_app->get_image_suffix(
+ ao_app->get_default_theme_path(p_image)), // Default theme path
+ ao_app->get_image_suffix(
+ ao_app->get_theme_path("placeholder")), // Placeholder path
+ ao_app->get_image_suffix(ao_app->get_default_theme_path(
+ "placeholder")), // Default placeholder path
+ };
+
+ for (QString path : pathlist) {
+ if (file_exists(path)) {
+ shout_path = path;
+ break;
+ }
+ }
+ }
+
+ m_movie->setFileName(shout_path);
+
+ if (m_movie->loopCount() == 0)
+ play_once = true;
+
+ this->show();
+ m_movie->start();
+ if (m_movie->frameCount() == 0 && duration > 0)
+ timer->start(duration);
+}
+
+void AOMovie::stop()
+{
+ m_movie->stop();
+ this->hide();
+}
+
+void AOMovie::frame_change(int n_frame)
+{
+ // If it's a "static movie" (only one frame - png image), we can't change
+ // frames - ignore this function (use timer instead). If the frame didn't reach
+ // the last frame or the movie is continuous, don't stop the movie.
+ if (m_movie->frameCount() == 0 || n_frame < (m_movie->frameCount() - 1) ||
+ !play_once)
+ return;
+ // we need this or else the last frame wont show
+ timer->start(m_movie->nextFrameDelay());
+}
+
+void AOMovie::timer_done()
+{
+ this->stop();
+ // signal connected to courtroom object, let it figure out what to do
+ done();
+}
+
+void AOMovie::combo_resize(int w, int h)
+{
+ QSize f_size(w, h);
+ this->resize(f_size);
+ m_movie->setScaledSize(f_size);
+}
diff --git a/src/aomusicplayer.cpp b/src/aomusicplayer.cpp
index 3ba9cf1d..249e01e5 100644
--- a/src/aomusicplayer.cpp
+++ b/src/aomusicplayer.cpp
@@ -1,107 +1,225 @@
#include "aomusicplayer.h"
-#if defined(BASSAUDIO)
+
AOMusicPlayer::AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app)
- : QObject()
{
m_parent = parent;
ao_app = p_ao_app;
}
-AOMusicPlayer::~AOMusicPlayer() { kill_loop(); }
+#ifdef BASSAUDIO
-void AOMusicPlayer::play(QString p_song)
+AOMusicPlayer::~AOMusicPlayer()
{
- BASS_ChannelStop(m_stream);
-
- f_path = ao_app->get_music_path(p_song);
-
- if (p_song.startsWith("http")) {
- m_stream = BASS_StreamCreateURL(f_path.toStdWString().c_str(), 0,
- BASS_STREAM_AUTOFREE | BASS_UNICODE |
- BASS_ASYNCFILE, NULL, NULL);
- } else {
- m_stream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0,
- BASS_STREAM_AUTOFREE | BASS_UNICODE |
- BASS_ASYNCFILE);
+ for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) {
+ BASS_ChannelStop(m_stream_list[n_stream]);
}
+}
+
+void AOMusicPlayer::play(QString p_song, int channel, bool loop,
+ int effect_flags)
+{
+ channel = channel % m_channelmax;
+ if (channel < 0) // wtf?
+ return;
+ QString f_path = ao_app->get_music_path(p_song);
- this->set_volume(m_volume);
+ unsigned int flags = BASS_STREAM_PRESCAN | BASS_STREAM_AUTOFREE |
+ BASS_UNICODE | BASS_ASYNCFILE;
+ if (loop)
+ flags |= BASS_SAMPLE_LOOP;
+
+ DWORD newstream;
+ if (f_path.endsWith(".opus"))
+ newstream = BASS_OPUS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags);
+ else
+ newstream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags);
if (ao_app->get_audio_output_device() != "default")
- BASS_ChannelSetDevice(m_stream, BASS_GetDevice());
- if (enable_looping) {
- BASS_ChannelFlags(m_stream, BASS_SAMPLE_LOOP, BASS_SAMPLE_LOOP);
+ BASS_ChannelSetDevice(m_stream_list[channel], BASS_GetDevice());
+
+ QString d_path = f_path + ".txt";
+
+ loop_start[channel] = 0;
+ loop_end[channel] = BASS_ChannelGetLength(newstream, BASS_POS_BYTE);
+ if (loop && file_exists(d_path)) // Contains loop/etc. information file
+ {
+ QStringList lines = ao_app->read_file(d_path).split("\n");
+ foreach (QString line, lines) {
+ QStringList args = line.split("=");
+ if (args.size() < 2)
+ continue;
+ QString arg = args[0].trimmed();
+
+ float sample_rate;
+ BASS_ChannelGetAttribute(newstream, BASS_ATTRIB_FREQ, &sample_rate);
+
+ // Grab number of bytes for sample size
+ int sample_size = 16 / 8;
+
+ // number of channels (stereo/mono)
+ int num_channels = 2;
+
+ // Calculate the bytes for loop_start/loop_end to use with the sync proc
+ QWORD bytes = static_cast<QWORD>(args[1].trimmed().toFloat() *
+ sample_size * num_channels);
+ if (arg == "loop_start")
+ loop_start[channel] = bytes;
+ else if (arg == "loop_length")
+ loop_end[channel] = loop_start[channel] + bytes;
+ else if (arg == "loop_end")
+ loop_end[channel] = bytes;
+ }
+ qDebug() << "Found data file for song" << p_song << "length"
+ << BASS_ChannelGetLength(newstream, BASS_POS_BYTE) << "loop start"
+ << loop_start << "loop end" << loop_end;
}
- else {
- BASS_ChannelFlags(m_stream, 0, BASS_SAMPLE_LOOP);
+
+ if (BASS_ChannelIsActive(m_stream_list[channel]) == BASS_ACTIVE_PLAYING) {
+ DWORD oldstream = m_stream_list[channel];
+
+ if (effect_flags & SYNC_POS) {
+ BASS_ChannelLock(oldstream, true);
+ // Sync it with the new sample
+ BASS_ChannelSetPosition(newstream,
+ BASS_ChannelGetPosition(oldstream, BASS_POS_BYTE),
+ BASS_POS_BYTE);
+ BASS_ChannelLock(oldstream, false);
+ }
+
+ if (effect_flags & FADE_OUT) {
+ // Fade out the other sample and stop it (due to -1)
+ BASS_ChannelSlideAttribute(oldstream, BASS_ATTRIB_VOL | BASS_SLIDE_LOG,
+ -1, 4000);
+ }
+ else
+ BASS_ChannelStop(
+ oldstream); // Stop the sample since we don't need it anymore
}
- BASS_ChannelPlay(m_stream, false);
+ else
+ BASS_ChannelStop(m_stream_list[channel]);
+
+ m_stream_list[channel] = newstream;
+ BASS_ChannelPlay(m_stream_list[channel], false);
+ if (effect_flags & FADE_IN) {
+ // Fade in our sample
+ BASS_ChannelSetAttribute(newstream, BASS_ATTRIB_VOL, 0);
+ BASS_ChannelSlideAttribute(newstream, BASS_ATTRIB_VOL,
+ static_cast<float>(m_volume[channel] / 100.0f),
+ 1000);
+ }
+ else
+ this->set_volume(m_volume[channel], channel);
+
+ this->set_looping(loop, channel); // Have to do this here due to any
+ // crossfading-related changes, etc.
}
-void AOMusicPlayer::set_volume(int p_value)
+void AOMusicPlayer::stop(int channel)
{
- m_volume = p_value;
- float volume = m_volume / 100.0f;
- BASS_ChannelSetAttribute(m_stream, BASS_ATTRIB_VOL, volume);
+ BASS_ChannelStop(m_stream_list[channel]);
}
-QString AOMusicPlayer::get_path() { return f_path; }
+void AOMusicPlayer::set_volume(int p_value, int channel)
+{
+ m_volume[channel] = p_value;
+ float volume = m_volume[channel] / 100.0f;
+ if (channel < 0) {
+ for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) {
+ BASS_ChannelSetAttribute(m_stream_list[n_stream], BASS_ATTRIB_VOL,
+ volume);
+ }
+ }
+ else {
+ BASS_ChannelSetAttribute(m_stream_list[channel], BASS_ATTRIB_VOL, volume);
+ }
+}
-void AOMusicPlayer::kill_loop() { BASS_ChannelStop(m_stream); }
+void CALLBACK loopProc(HSYNC handle, DWORD channel, DWORD data, void *user)
+{
+ QWORD loop_start = *(static_cast<unsigned *>(user));
+ BASS_ChannelLock(channel, true);
+ BASS_ChannelSetPosition(channel, loop_start, BASS_POS_BYTE);
+ BASS_ChannelLock(channel, false);
+}
-#elif defined(QTAUDIO)
-AOMusicPlayer::AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app)
- : QObject()
+void AOMusicPlayer::set_looping(bool toggle, int channel)
{
- m_parent = parent;
- ao_app = p_ao_app;
+ qDebug() << "Setting looping for channel" << channel << "to" << toggle;
+ m_looping = toggle;
+ if (!m_looping) {
+ if (BASS_ChannelFlags(m_stream_list[channel], 0, 0) & BASS_SAMPLE_LOOP)
+ BASS_ChannelFlags(m_stream_list[channel], 0,
+ BASS_SAMPLE_LOOP); // remove the LOOP flag
+ BASS_ChannelRemoveSync(m_stream_list[channel], loop_sync[channel]);
+ loop_sync[channel] = 0;
+ }
+ else {
+ BASS_ChannelFlags(m_stream_list[channel], BASS_SAMPLE_LOOP,
+ BASS_SAMPLE_LOOP); // set the LOOP flag
+ if (loop_sync[channel] != 0) {
+ BASS_ChannelRemoveSync(m_stream_list[channel],
+ loop_sync[channel]); // remove the sync
+ loop_sync[channel] = 0;
+ }
+ if (loop_start[channel] > 0) {
+ if (loop_end[channel] == 0)
+ loop_end[channel] = BASS_ChannelGetLength(m_stream_list[channel], BASS_POS_BYTE);
+ if (loop_end[channel] > 0) // Don't loop zero length songs even if we're asked to
+ loop_sync[channel] = BASS_ChannelSetSync(
+ m_stream_list[channel], BASS_SYNC_POS | BASS_SYNC_MIXTIME, loop_end[channel],
+ loopProc, &loop_start[channel]);
+ }
+ }
}
+#elif defined(QTAUDIO)
-AOMusicPlayer::~AOMusicPlayer() { m_player.stop(); }
+AOMusicPlayer::~AOMusicPlayer() {
+ for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) {
+ m_stream_list[n_stream].stop();
+ }
+}
-void AOMusicPlayer::play(QString p_song)
+void AOMusicPlayer::play(QString p_song, int channel, bool loop,
+ int effect_flags)
{
- m_player.stop();
-
+ channel = channel % m_channelmax;
+ if (channel < 0) // wtf?
+ return;
QString f_path = ao_app->get_music_path(p_song);
- m_player.setMedia(QUrl::fromLocalFile(f_path));
+ m_stream_list[channel].stop();
- this->set_volume(100);
+ m_stream_list[channel].setMedia(QUrl::fromLocalFile(f_path));
- m_player.play();
+ this->set_volume(m_volume[channel], channel);
+
+ m_stream_list[channel].play();
}
-void AOMusicPlayer::set_volume(int p_value)
+void AOMusicPlayer::stop(int channel)
{
- m_volume = p_value;
-
- qreal linearVolume = QAudio::convertVolume(m_volume / qreal(100),
- QAudio::LogarithmicVolumeScale,
- QAudio::LinearVolumeScale);
-
- m_player.setVolume(linearVolume * 100);
+ m_stream_list[channel].stop();
}
-QString AOMusicPlayer::get_path() { return f_path; }
-
-void AOMusicPlayer::kill_loop() { m_player.stop(); }
-#else
-AOMusicPlayer::AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app)
- : QObject()
+void AOMusicPlayer::set_volume(int p_value, int channel)
{
- m_parent = parent;
- ao_app = p_ao_app;
+ m_volume[channel] = p_value;
+ m_stream_list[channel].setVolume(m_volume[channel]);
}
+#else
+
AOMusicPlayer::~AOMusicPlayer() {}
-void AOMusicPlayer::play(QString p_song) {}
+void AOMusicPlayer::play(QString p_song, int channel, bool loop,
+ int effect_flags) {}
+
+void AOMusicPlayer::stop(int channel) {}
-void AOMusicPlayer::set_volume(int p_value) {}
+void AOMusicPlayer::set_volume(int p_value, int channel) {}
-QString AOMusicPlayer::get_path() { return f_path; }
+void loopProc(int handle, int channel, int data, int *user) {}
-void AOMusicPlayer::kill_loop() {}
+void AOMusicPlayer::set_looping(bool toggle, int channel) {}
#endif
diff --git a/src/aooptionsdialog.cpp b/src/aooptionsdialog.cpp
index e2c6ac8c..6cedee8d 100644
--- a/src/aooptionsdialog.cpp
+++ b/src/aooptionsdialog.cpp
@@ -1,5 +1,6 @@
#include "aooptionsdialog.h"
#include "aoapplication.h"
+#include "bass.h"
AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
: QDialog(parent)
@@ -9,11 +10,11 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
// Setting up the basics.
// setAttribute(Qt::WA_DeleteOnClose);
setWindowTitle(tr("Settings"));
- resize(398, 360);
+ resize(398, 320);
ui_settings_buttons = new QDialogButtonBox(this);
- QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Fixed);
+ QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::MinimumExpanding);
sizePolicy1.setHorizontalStretch(0);
sizePolicy1.setVerticalStretch(0);
sizePolicy1.setHeightForWidth(
@@ -39,16 +40,13 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_vertical_layout->addWidget(ui_settings_buttons);
// Let's add the tabs one by one.
-
- //
- // GAMEPLAY
- //
-
+ // First, we'll start with 'Gameplay'.
ui_gameplay_tab = new QWidget();
+ ui_gameplay_tab->setSizePolicy(sizePolicy1);
ui_settings_tabs->addTab(ui_gameplay_tab, tr("Gameplay"));
-
ui_form_layout_widget = new QWidget(ui_gameplay_tab);
- ui_form_layout_widget->setGeometry(QRect(10, 10, 361, 240));
+ ui_form_layout_widget->setGeometry(QRect(10, 10, 361, 361));
+ ui_form_layout_widget->setSizePolicy(sizePolicy1);
ui_gameplay_form = new QFormLayout(ui_form_layout_widget);
ui_gameplay_form->setLabelAlignment(Qt::AlignLeading | Qt::AlignLeft |
@@ -56,6 +54,9 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_gameplay_form->setFormAlignment(Qt::AlignLeading | Qt::AlignLeft |
Qt::AlignTop);
ui_gameplay_form->setContentsMargins(0, 0, 0, 0);
+ ui_gameplay_form->setSpacing(2);
+
+ int row = 0;
ui_theme_label = new QLabel(ui_form_layout_widget);
ui_theme_label->setText(tr("Theme:"));
@@ -64,8 +65,7 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
"the lobby's look as well, you'll need to reload the "
"lobby for the changes to take effect, such as by joining "
"a server and leaving it."));
- ui_gameplay_form->setWidget(0, QFormLayout::LabelRole, ui_theme_label);
-
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_theme_label);
ui_theme_combobox = new QComboBox(ui_form_layout_widget);
// Fill the combobox with the names of the themes.
@@ -79,64 +79,108 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_theme_combobox->setCurrentIndex(ui_theme_combobox->count() - 1);
}
- ui_gameplay_form->setWidget(0, QFormLayout::FieldRole, ui_theme_combobox);
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_theme_combobox);
+ row += 1;
ui_theme_log_divider = new QFrame(ui_form_layout_widget);
ui_theme_log_divider->setMidLineWidth(0);
ui_theme_log_divider->setFrameShape(QFrame::HLine);
ui_theme_log_divider->setFrameShadow(QFrame::Sunken);
- ui_gameplay_form->setWidget(1, QFormLayout::FieldRole, ui_theme_log_divider);
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole,
+ ui_theme_log_divider);
+
+ row += 1;
+ ui_downwards_lbl = new QLabel(ui_form_layout_widget);
+ ui_downwards_lbl->setText(tr("Log goes downwards:"));
+ ui_downwards_lbl->setToolTip(
+ tr("If ticked, new messages will appear at "
+ "the bottom (like the OOC chatlog). The traditional "
+ "(AO1) behaviour is equivalent to this being unticked."));
+
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_downwards_lbl);
+
+ ui_downwards_cb = new QCheckBox(ui_form_layout_widget);
+ ui_downwards_cb->setChecked(p_ao_app->get_log_goes_downwards());
+
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_downwards_cb);
+
+ row += 1;
+ ui_length_lbl = new QLabel(ui_form_layout_widget);
+ ui_length_lbl->setText(tr("Log length:"));
+ ui_length_lbl->setToolTip(tr(
+ "The amount of messages the IC chatlog will keep before "
+ "deleting older messages. A value of 0 or below counts as 'infinite'."));
+
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_length_lbl);
+
+ ui_length_spinbox = new QSpinBox(ui_form_layout_widget);
+ ui_length_spinbox->setMaximum(10000);
+ ui_length_spinbox->setValue(p_ao_app->get_max_log_size());
+
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_length_spinbox);
+
+ row += 1;
+ ui_log_names_divider = new QFrame(ui_form_layout_widget);
+ ui_log_names_divider->setFrameShape(QFrame::HLine);
+ ui_log_names_divider->setFrameShadow(QFrame::Sunken);
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole,
+ ui_log_names_divider);
+ row += 1;
ui_username_lbl = new QLabel(ui_form_layout_widget);
ui_username_lbl->setText(tr("Default username:"));
ui_username_lbl->setToolTip(
tr("Your OOC name will be automatically set to this value "
"when you join a server."));
- ui_gameplay_form->setWidget(2, QFormLayout::LabelRole, ui_username_lbl);
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_username_lbl);
ui_username_textbox = new QLineEdit(ui_form_layout_widget);
ui_username_textbox->setMaxLength(30);
ui_username_textbox->setText(p_ao_app->get_default_username());
- ui_gameplay_form->setWidget(2, QFormLayout::FieldRole, ui_username_textbox);
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_username_textbox);
+ row += 1;
ui_showname_lbl = new QLabel(ui_form_layout_widget);
ui_showname_lbl->setText(tr("Custom shownames:"));
ui_showname_lbl->setToolTip(
tr("Gives the default value for the in-game 'Custom shownames' "
- "checkbox, which in turn determines whether the client should "
+ "tickbox, which in turn determines whether the client should "
"display custom in-character names."));
- ui_gameplay_form->setWidget(3, QFormLayout::LabelRole, ui_showname_lbl);
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_showname_lbl);
ui_showname_cb = new QCheckBox(ui_form_layout_widget);
ui_showname_cb->setChecked(p_ao_app->get_showname_enabled_by_default());
- ui_gameplay_form->setWidget(3, QFormLayout::FieldRole, ui_showname_cb);
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_showname_cb);
+ row += 1;
ui_net_divider = new QFrame(ui_form_layout_widget);
ui_net_divider->setFrameShape(QFrame::HLine);
ui_net_divider->setFrameShadow(QFrame::Sunken);
- ui_gameplay_form->setWidget(4, QFormLayout::FieldRole, ui_net_divider);
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_net_divider);
+ row += 1;
ui_ms_lbl = new QLabel(ui_form_layout_widget);
ui_ms_lbl->setText(tr("Backup MS:"));
ui_ms_lbl->setToolTip(
tr("If the built-in server lookups fail, the game will try the "
"address given here and use it as a backup master server address."));
- ui_gameplay_form->setWidget(5, QFormLayout::LabelRole, ui_ms_lbl);
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_ms_lbl);
QSettings *configini = ao_app->configini;
ui_ms_textbox = new QLineEdit(ui_form_layout_widget);
ui_ms_textbox->setText(configini->value("master", "").value<QString>());
- ui_gameplay_form->setWidget(5, QFormLayout::FieldRole, ui_ms_textbox);
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_ms_textbox);
+ row += 1;
ui_discord_lbl = new QLabel(ui_form_layout_widget);
ui_discord_lbl->setText(tr("Discord:"));
ui_discord_lbl->setToolTip(
@@ -144,68 +188,152 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
"what character are you playing, and how long you have "
"been playing for."));
- ui_gameplay_form->setWidget(6, QFormLayout::LabelRole, ui_discord_lbl);
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_discord_lbl);
ui_discord_cb = new QCheckBox(ui_form_layout_widget);
ui_discord_cb->setChecked(ao_app->is_discord_enabled());
- ui_gameplay_form->setWidget(6, QFormLayout::FieldRole, ui_discord_cb);
-
- ui_epilepsy_lbl = new QLabel(ui_form_layout_widget);
- ui_epilepsy_lbl->setText(tr("Allow Shake/Flash:"));
- ui_epilepsy_lbl->setToolTip(
- tr("Allows screenshaking and flashing. Disable this if you have concerns "
- "or issues with photosensitivity and/or seizures."));
-
- ui_gameplay_form->setWidget(7, QFormLayout::LabelRole, ui_epilepsy_lbl);
-
- ui_epilepsy_cb = new QCheckBox(ui_form_layout_widget);
- ui_epilepsy_cb->setChecked(ao_app->is_shakeandflash_enabled());
-
- ui_gameplay_form->setWidget(7, QFormLayout::FieldRole, ui_epilepsy_cb);
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_discord_cb);
+ row += 1;
ui_language_label = new QLabel(ui_form_layout_widget);
ui_language_label->setText(tr("Language:"));
ui_language_label->setToolTip(
tr("Sets the language if you don't want to use your system language."));
- ui_gameplay_form->setWidget(8, QFormLayout::LabelRole, ui_language_label);
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_language_label);
ui_language_combobox = new QComboBox(ui_form_layout_widget);
ui_language_combobox->addItem(
configini->value("language", " ").value<QString>() +
- " - Keep current setting");
+ tr(" - Keep current setting"));
ui_language_combobox->addItem(" - Default");
ui_language_combobox->addItem("en - English");
ui_language_combobox->addItem("de - Deutsch");
ui_language_combobox->addItem("es - Español");
ui_language_combobox->addItem("pt - Português");
- ui_language_combobox->addItem("pl - Polski");
+ ui_language_combobox->addItem("pl - Polskie");
ui_language_combobox->addItem("jp - 日本語");
ui_language_combobox->addItem("ru - Русский");
- ui_gameplay_form->setWidget(8, QFormLayout::FieldRole, ui_language_combobox);
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole,
+ ui_language_combobox);
- ui_net_divider = new QFrame(ui_form_layout_widget);
- ui_net_divider->setFrameShape(QFrame::HLine);
- ui_net_divider->setFrameShadow(QFrame::Sunken);
- ui_gameplay_form->setWidget(9, QFormLayout::FieldRole, ui_net_divider);
-
- ui_slower_blips_lb = new QLabel(ui_form_layout_widget);
- ui_slower_blips_lb->setText(tr("Slower text speed:"));
- ui_slower_blips_lb->setToolTip(tr("Set the text speed to be the same as the AA games."));
- ui_slower_blips_cb = new QCheckBox(ui_form_layout_widget);
- ui_slower_blips_cb->setChecked(p_ao_app->get_slower_blips());
- ui_gameplay_form->setWidget(10, QFormLayout::FieldRole, ui_slower_blips_cb);
- ui_gameplay_form->setWidget(10, QFormLayout::LabelRole, ui_slower_blips_lb);
-
- ui_pun_delay = new QLabel(ui_form_layout_widget);
- ui_pun_delay->setText(tr("Blip delay on punctuations:"));
- ui_pun_delay->setToolTip(tr("Punctuation delay modifier."
- " Enable it for the blips to slow down on punctuations."));
- ui_pun_delay_cb = new QCheckBox(ui_form_layout_widget);
- ui_pun_delay_cb->setChecked(p_ao_app->get_pundelay());
- ui_gameplay_form->setWidget(11, QFormLayout::FieldRole, ui_pun_delay_cb);
- ui_gameplay_form->setWidget(11, QFormLayout::LabelRole, ui_pun_delay);
+ row += 1;
+ ui_shake_lbl = new QLabel(ui_form_layout_widget);
+ ui_shake_lbl->setText(tr("Allow Screenshake:"));
+ ui_shake_lbl->setToolTip(
+ tr("Allows screenshaking. Disable this if you have concerns or issues "
+ "with photosensitivity and/or seizures."));
+
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_shake_lbl);
+
+ ui_shake_cb = new QCheckBox(ui_form_layout_widget);
+ ui_shake_cb->setChecked(ao_app->is_shake_enabled());
+
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_shake_cb);
+
+ row += 1;
+ ui_effects_lbl = new QLabel(ui_form_layout_widget);
+ ui_effects_lbl->setText(tr("Allow Effects:"));
+ ui_effects_lbl->setToolTip(
+ tr("Allows screen effects. Disable this if you have concerns or issues "
+ "with photosensitivity and/or seizures."));
+
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_effects_lbl);
+
+ ui_effects_cb = new QCheckBox(ui_form_layout_widget);
+ ui_effects_cb->setChecked(ao_app->is_effects_enabled());
+
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_effects_cb);
+
+ row += 1;
+ ui_framenetwork_lbl = new QLabel(ui_form_layout_widget);
+ ui_framenetwork_lbl->setText(tr("Network Frame Effects:"));
+ ui_framenetwork_lbl->setToolTip(tr(
+ "Send screen-shaking, flashes and sounds as defined in the char.ini over "
+ "the network. Only works for servers that support this functionality."));
+
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_framenetwork_lbl);
+
+ ui_framenetwork_cb = new QCheckBox(ui_form_layout_widget);
+ ui_framenetwork_cb->setChecked(ao_app->is_frame_network_enabled());
+
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_framenetwork_cb);
+
+ row += 1;
+ ui_colorlog_lbl = new QLabel(ui_form_layout_widget);
+ ui_colorlog_lbl->setText(tr("Colors in IC Log:"));
+ ui_colorlog_lbl->setToolTip(
+ tr("Use the markup colors in the server IC chatlog."));
+
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_colorlog_lbl);
+
+ ui_colorlog_cb = new QCheckBox(ui_form_layout_widget);
+ ui_colorlog_cb->setChecked(ao_app->is_colorlog_enabled());
+
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_colorlog_cb);
+ row += 1;
+ ui_stickysounds_lbl = new QLabel(ui_form_layout_widget);
+ ui_stickysounds_lbl->setText(tr("Sticky Sounds:"));
+ ui_stickysounds_lbl->setToolTip(
+ tr("Turn this on to prevent the sound dropdown from clearing the sound "
+ "after playing it."));
+
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_stickysounds_lbl);
+
+ ui_stickysounds_cb = new QCheckBox(ui_form_layout_widget);
+ ui_stickysounds_cb->setChecked(ao_app->is_stickysounds_enabled());
+
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_stickysounds_cb);
+
+ row += 1;
+ ui_stickyeffects_lbl = new QLabel(ui_form_layout_widget);
+ ui_stickyeffects_lbl->setText(tr("Sticky Effects:"));
+ ui_stickyeffects_lbl->setToolTip(
+ tr("Turn this on to prevent the effects dropdown from clearing the "
+ "effect after playing it."));
+
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole,
+ ui_stickyeffects_lbl);
+
+ ui_stickyeffects_cb = new QCheckBox(ui_form_layout_widget);
+ ui_stickyeffects_cb->setChecked(ao_app->is_stickyeffects_enabled());
+
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_stickyeffects_cb);
+
+ row += 1;
+ ui_stickypres_lbl = new QLabel(ui_form_layout_widget);
+ ui_stickypres_lbl->setText(tr("Sticky Preanims:"));
+ ui_stickypres_lbl->setToolTip(
+ tr("Turn this on to prevent preanimation checkbox from clearing after "
+ "playing the emote."));
+
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_stickypres_lbl);
+
+ ui_stickypres_cb = new QCheckBox(ui_form_layout_widget);
+ ui_stickypres_cb->setChecked(ao_app->is_stickypres_enabled());
+
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_stickypres_cb);
+
+ row += 1;
+ ui_customchat_lbl = new QLabel(ui_form_layout_widget);
+ ui_customchat_lbl->setText(tr("Custom Chatboxes:"));
+ ui_customchat_lbl->setToolTip(
+ tr("Turn this on to allow characters to define their own "
+ "custom chat box designs."));
+
+ ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_customchat_lbl);
+
+ ui_customchat_cb = new QCheckBox(ui_form_layout_widget);
+ ui_customchat_cb->setChecked(ao_app->is_customchat_enabled());
+
+ ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_customchat_cb);
+
+ QScrollArea *scroll = new QScrollArea;
+ scroll->setWidget(ui_form_layout_widget);
+ ui_gameplay_tab->setLayout(new QVBoxLayout);
+ ui_gameplay_tab->layout()->addWidget(scroll);
+ ui_gameplay_tab->show();
// Here we start the callwords tab.
ui_callwords_tab = new QWidget();
@@ -257,24 +385,25 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_audio_layout->setFormAlignment(Qt::AlignLeading | Qt::AlignLeft |
Qt::AlignTop);
ui_audio_layout->setContentsMargins(0, 0, 0, 0);
+ row = 0;
ui_audio_device_lbl = new QLabel(ui_audio_widget);
ui_audio_device_lbl->setText(tr("Audio device:"));
ui_audio_device_lbl->setToolTip(tr("Sets the audio device for all sounds."));
- ui_audio_layout->setWidget(0, QFormLayout::LabelRole, ui_audio_device_lbl);
+ ui_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_audio_device_lbl);
ui_audio_device_combobox = new QComboBox(ui_audio_widget);
// Let's fill out the combobox with the available audio devices. Or don't if
// there is no audio
+ int a = 0;
if (needs_default_audiodev()) {
- ui_audio_device_combobox->addItem("default");
+ ui_audio_device_combobox->addItem("default"); //TODO translate this without breaking the default audio device
}
#ifdef BASSAUDIO
BASS_DEVICEINFO info;
- int a = 0;
for (a = 0; BASS_GetDeviceInfo(a, &info); a++) {
ui_audio_device_combobox->addItem(info.name);
if (p_ao_app->get_audio_output_device() == info.name)
@@ -290,120 +419,131 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_audio_device_combobox->count() - 1);
}
#endif
- ui_audio_layout->setWidget(0, QFormLayout::FieldRole,
+ ui_audio_layout->setWidget(row, QFormLayout::FieldRole,
ui_audio_device_combobox);
+ row += 1;
ui_audio_volume_divider = new QFrame(ui_audio_widget);
ui_audio_volume_divider->setFrameShape(QFrame::HLine);
ui_audio_volume_divider->setFrameShadow(QFrame::Sunken);
- ui_audio_layout->setWidget(1, QFormLayout::FieldRole,
+ ui_audio_layout->setWidget(row, QFormLayout::FieldRole,
ui_audio_volume_divider);
+ row += 1;
ui_music_volume_lbl = new QLabel(ui_audio_widget);
ui_music_volume_lbl->setText(tr("Music:"));
- ui_music_volume_lbl->setToolTip(tr("Sets the default volume for music."));
+ ui_music_volume_lbl->setToolTip(tr("Sets the music's default volume."));
- ui_audio_layout->setWidget(2, QFormLayout::LabelRole, ui_music_volume_lbl);
+ ui_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_music_volume_lbl);
ui_music_volume_spinbox = new QSpinBox(ui_audio_widget);
ui_music_volume_spinbox->setValue(p_ao_app->get_default_music());
ui_music_volume_spinbox->setMaximum(100);
ui_music_volume_spinbox->setSuffix("%");
- ui_audio_layout->setWidget(2, QFormLayout::FieldRole,
+ ui_audio_layout->setWidget(row, QFormLayout::FieldRole,
ui_music_volume_spinbox);
+ row += 1;
ui_sfx_volume_lbl = new QLabel(ui_audio_widget);
ui_sfx_volume_lbl->setText(tr("SFX:"));
ui_sfx_volume_lbl->setToolTip(
- tr("Sets the default volume for SFX sounds, "
- "like interjections or other character sound effects."));
-
- ui_audio_layout->setWidget(3, QFormLayout::LabelRole, ui_sfx_volume_lbl);
+ tr("Sets the SFX's default volume. "
+ "Interjections and actual sound effects count as 'SFX'."));
+ ui_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_sfx_volume_lbl);
ui_sfx_volume_spinbox = new QSpinBox(ui_audio_widget);
ui_sfx_volume_spinbox->setValue(p_ao_app->get_default_sfx());
ui_sfx_volume_spinbox->setMaximum(100);
ui_sfx_volume_spinbox->setSuffix("%");
- ui_audio_layout->setWidget(3, QFormLayout::FieldRole, ui_sfx_volume_spinbox);
+ ui_audio_layout->setWidget(row, QFormLayout::FieldRole,
+ ui_sfx_volume_spinbox);
+ row += 1;
ui_blips_volume_lbl = new QLabel(ui_audio_widget);
ui_blips_volume_lbl->setText(tr("Blips:"));
ui_blips_volume_lbl->setToolTip(
tr("Sets the volume of the blips, the talking sound effects."));
- ui_audio_layout->setWidget(4, QFormLayout::LabelRole, ui_blips_volume_lbl);
+ ui_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_blips_volume_lbl);
ui_blips_volume_spinbox = new QSpinBox(ui_audio_widget);
ui_blips_volume_spinbox->setValue(p_ao_app->get_default_blip());
ui_blips_volume_spinbox->setMaximum(100);
ui_blips_volume_spinbox->setSuffix("%");
- ui_audio_layout->setWidget(4, QFormLayout::FieldRole,
+ ui_audio_layout->setWidget(row, QFormLayout::FieldRole,
ui_blips_volume_spinbox);
+ row += 1;
ui_volume_blip_divider = new QFrame(ui_audio_widget);
ui_volume_blip_divider->setFrameShape(QFrame::HLine);
ui_volume_blip_divider->setFrameShadow(QFrame::Sunken);
- ui_audio_layout->setWidget(5, QFormLayout::FieldRole, ui_volume_blip_divider);
+ ui_audio_layout->setWidget(row, QFormLayout::FieldRole,
+ ui_volume_blip_divider);
+ row += 1;
ui_bliprate_lbl = new QLabel(ui_audio_widget);
ui_bliprate_lbl->setText(tr("Blip rate:"));
ui_bliprate_lbl->setToolTip(
tr("Sets the delay between playing the blip sounds."));
- ui_audio_layout->setWidget(6, QFormLayout::LabelRole, ui_bliprate_lbl);
+ ui_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_bliprate_lbl);
ui_bliprate_spinbox = new QSpinBox(ui_audio_widget);
ui_bliprate_spinbox->setValue(p_ao_app->read_blip_rate());
ui_bliprate_spinbox->setMinimum(1);
+ ui_bliprate_spinbox->setToolTip(
+ tr("Play a blip sound \"once per every X symbols\", where "
+ "X is the blip rate."));
- ui_audio_layout->setWidget(6, QFormLayout::FieldRole, ui_bliprate_spinbox);
+ ui_audio_layout->setWidget(row, QFormLayout::FieldRole, ui_bliprate_spinbox);
+ row += 1;
ui_blank_blips_lbl = new QLabel(ui_audio_widget);
ui_blank_blips_lbl->setText(tr("Blank blips:"));
ui_blank_blips_lbl->setToolTip(
tr("If true, the game will play a blip sound even "
"when a space is 'being said'."));
- ui_audio_layout->setWidget(7, QFormLayout::LabelRole, ui_blank_blips_lbl);
+ ui_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_blank_blips_lbl);
ui_blank_blips_cb = new QCheckBox(ui_audio_widget);
ui_blank_blips_cb->setChecked(p_ao_app->get_blank_blip());
- ui_audio_layout->setWidget(7, QFormLayout::FieldRole, ui_blank_blips_cb);
+ ui_audio_layout->setWidget(row, QFormLayout::FieldRole, ui_blank_blips_cb);
+ row += 1;
ui_loopsfx_lbl = new QLabel(ui_audio_widget);
ui_loopsfx_lbl->setText(tr("Enable Looping SFX:"));
ui_loopsfx_lbl->setToolTip(tr("If true, the game will allow looping sound "
"effects to play on preanimations."));
- ui_audio_layout->setWidget(8, QFormLayout::LabelRole, ui_loopsfx_lbl);
+ ui_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_loopsfx_lbl);
ui_loopsfx_cb = new QCheckBox(ui_audio_widget);
ui_loopsfx_cb->setChecked(p_ao_app->get_looping_sfx());
- ui_audio_layout->setWidget(8, QFormLayout::FieldRole, ui_loopsfx_cb);
+ ui_audio_layout->setWidget(row, QFormLayout::FieldRole, ui_loopsfx_cb);
+ row += 1;
ui_objectmusic_lbl = new QLabel(ui_audio_widget);
ui_objectmusic_lbl->setText(tr("Kill Music On Objection:"));
ui_objectmusic_lbl->setToolTip(
- tr("If true, the game will stop music when someone objects, like in the "
- "actual games."));
+ tr("If true, AO2 will stop the music for you when you or someone else "
+ "does 'Objection!'."));
- ui_audio_layout->setWidget(9, QFormLayout::LabelRole, ui_objectmusic_lbl);
+ ui_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_objectmusic_lbl);
ui_objectmusic_cb = new QCheckBox(ui_audio_widget);
- ui_objectmusic_cb->setChecked(p_ao_app->get_objectmusic());
+ ui_objectmusic_cb->setChecked(p_ao_app->objection_stop_music());
- ui_audio_layout->setWidget(9, QFormLayout::FieldRole, ui_objectmusic_cb);
+ ui_audio_layout->setWidget(row, QFormLayout::FieldRole, ui_objectmusic_cb);
- //
- // CASING
- //
+ // The casing tab!
ui_casing_tab = new QWidget();
ui_settings_tabs->addTab(ui_casing_tab, tr("Casing"));
@@ -416,6 +556,7 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_casing_layout->setFormAlignment(Qt::AlignLeading | Qt::AlignLeft |
Qt::AlignTop);
ui_casing_layout->setContentsMargins(0, 0, 0, 0);
+ row = 0;
// -- SERVER SUPPORTS CASING
@@ -427,222 +568,151 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
tr("This server does not support case alerts."));
ui_casing_supported_lbl->setToolTip(tr("Pretty self-explanatory."));
- ui_casing_layout->setWidget(0, QFormLayout::FieldRole,
+ ui_casing_layout->setWidget(row, QFormLayout::FieldRole,
ui_casing_supported_lbl);
// -- CASE ANNOUNCEMENTS
+ row += 1;
ui_casing_enabled_lbl = new QLabel(ui_casing_widget);
ui_casing_enabled_lbl->setText(tr("Casing:"));
ui_casing_enabled_lbl->setToolTip(
tr("If checked, you will get alerts about case "
"announcements."));
- ui_casing_layout->setWidget(1, QFormLayout::LabelRole, ui_casing_enabled_lbl);
+ ui_casing_layout->setWidget(row, QFormLayout::LabelRole,
+ ui_casing_enabled_lbl);
ui_casing_enabled_cb = new QCheckBox(ui_casing_widget);
ui_casing_enabled_cb->setChecked(ao_app->get_casing_enabled());
- ui_casing_layout->setWidget(1, QFormLayout::FieldRole, ui_casing_enabled_cb);
+ ui_casing_layout->setWidget(row, QFormLayout::FieldRole,
+ ui_casing_enabled_cb);
// -- DEFENSE ANNOUNCEMENTS
+ row += 1;
ui_casing_def_lbl = new QLabel(ui_casing_widget);
ui_casing_def_lbl->setText(tr("Defense:"));
ui_casing_def_lbl->setToolTip(tr("If checked, you will get alerts about case "
"announcements if a defense spot is open."));
- ui_casing_layout->setWidget(2, QFormLayout::LabelRole, ui_casing_def_lbl);
+ ui_casing_layout->setWidget(row, QFormLayout::LabelRole, ui_casing_def_lbl);
ui_casing_def_cb = new QCheckBox(ui_casing_widget);
ui_casing_def_cb->setChecked(ao_app->get_casing_defence_enabled());
- ui_casing_layout->setWidget(2, QFormLayout::FieldRole, ui_casing_def_cb);
+ ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_def_cb);
// -- PROSECUTOR ANNOUNCEMENTS
+ row += 1;
ui_casing_pro_lbl = new QLabel(ui_casing_widget);
ui_casing_pro_lbl->setText(tr("Prosecution:"));
ui_casing_pro_lbl->setToolTip(
tr("If checked, you will get alerts about case "
"announcements if a prosecutor spot is open."));
- ui_casing_layout->setWidget(3, QFormLayout::LabelRole, ui_casing_pro_lbl);
+ ui_casing_layout->setWidget(row, QFormLayout::LabelRole, ui_casing_pro_lbl);
ui_casing_pro_cb = new QCheckBox(ui_casing_widget);
ui_casing_pro_cb->setChecked(ao_app->get_casing_prosecution_enabled());
- ui_casing_layout->setWidget(3, QFormLayout::FieldRole, ui_casing_pro_cb);
+ ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_pro_cb);
// -- JUDGE ANNOUNCEMENTS
+ row += 1;
ui_casing_jud_lbl = new QLabel(ui_casing_widget);
ui_casing_jud_lbl->setText(tr("Judge:"));
ui_casing_jud_lbl->setToolTip(tr("If checked, you will get alerts about case "
"announcements if the judge spot is open."));
- ui_casing_layout->setWidget(4, QFormLayout::LabelRole, ui_casing_jud_lbl);
+ ui_casing_layout->setWidget(row, QFormLayout::LabelRole, ui_casing_jud_lbl);
ui_casing_jud_cb = new QCheckBox(ui_casing_widget);
ui_casing_jud_cb->setChecked(ao_app->get_casing_judge_enabled());
- ui_casing_layout->setWidget(4, QFormLayout::FieldRole, ui_casing_jud_cb);
+ ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_jud_cb);
// -- JUROR ANNOUNCEMENTS
+ row += 1;
ui_casing_jur_lbl = new QLabel(ui_casing_widget);
ui_casing_jur_lbl->setText(tr("Juror:"));
ui_casing_jur_lbl->setToolTip(tr("If checked, you will get alerts about case "
"announcements if a juror spot is open."));
- ui_casing_layout->setWidget(5, QFormLayout::LabelRole, ui_casing_jur_lbl);
+ ui_casing_layout->setWidget(row, QFormLayout::LabelRole, ui_casing_jur_lbl);
ui_casing_jur_cb = new QCheckBox(ui_casing_widget);
ui_casing_jur_cb->setChecked(ao_app->get_casing_juror_enabled());
- ui_casing_layout->setWidget(5, QFormLayout::FieldRole, ui_casing_jur_cb);
+ ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_jur_cb);
// -- STENO ANNOUNCEMENTS
+ row += 1;
ui_casing_steno_lbl = new QLabel(ui_casing_widget);
ui_casing_steno_lbl->setText(tr("Stenographer:"));
ui_casing_steno_lbl->setToolTip(
tr("If checked, you will get alerts about case "
"announcements if a stenographer spot is open."));
- ui_casing_layout->setWidget(6, QFormLayout::LabelRole, ui_casing_steno_lbl);
+ ui_casing_layout->setWidget(row, QFormLayout::LabelRole, ui_casing_steno_lbl);
ui_casing_steno_cb = new QCheckBox(ui_casing_widget);
ui_casing_steno_cb->setChecked(ao_app->get_casing_steno_enabled());
- ui_casing_layout->setWidget(6, QFormLayout::FieldRole, ui_casing_steno_cb);
+ ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_steno_cb);
// -- CM ANNOUNCEMENTS
+ row += 1;
ui_casing_cm_lbl = new QLabel(ui_casing_widget);
ui_casing_cm_lbl->setText(tr("CM:"));
ui_casing_cm_lbl->setToolTip(
tr("If checked, you will appear amongst the potential "
"CMs on the server."));
- ui_casing_layout->setWidget(7, QFormLayout::LabelRole, ui_casing_cm_lbl);
+ ui_casing_layout->setWidget(row, QFormLayout::LabelRole, ui_casing_cm_lbl);
ui_casing_cm_cb = new QCheckBox(ui_casing_widget);
ui_casing_cm_cb->setChecked(ao_app->get_casing_cm_enabled());
- ui_casing_layout->setWidget(7, QFormLayout::FieldRole, ui_casing_cm_cb);
-
- ui_casing_wit_lbl = new QLabel(ui_casing_widget);
- ui_casing_wit_lbl->setText(tr("Witness:"));
- ui_casing_wit_lbl->setToolTip(
- tr("If checked, you will appear amongst the potential "
- "witnesses on the server."));
-
- ui_casing_layout->setWidget(8, QFormLayout::LabelRole, ui_casing_wit_lbl);
-
- ui_casing_wit_cb = new QCheckBox(ui_casing_widget);
- ui_casing_wit_cb->setChecked(ao_app->get_casing_wit_enabled());
-
- ui_casing_layout->setWidget(8, QFormLayout::FieldRole, ui_casing_wit_cb);
+ ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_cm_cb);
// -- CM CASES ANNOUNCEMENTS
+ row += 1;
ui_casing_cm_cases_lbl = new QLabel(ui_casing_widget);
ui_casing_cm_cases_lbl->setText(tr("Hosting cases:"));
ui_casing_cm_cases_lbl->setToolTip(
tr("If you're a CM, enter what cases you are "
"willing to host."));
- ui_casing_layout->setWidget(9, QFormLayout::LabelRole,
+ ui_casing_layout->setWidget(row, QFormLayout::LabelRole,
ui_casing_cm_cases_lbl);
ui_casing_cm_cases_textbox = new QLineEdit(ui_casing_widget);
ui_casing_cm_cases_textbox->setText(ao_app->get_casing_can_host_cases());
- ui_casing_layout->setWidget(9, QFormLayout::FieldRole,
+ ui_casing_layout->setWidget(row, QFormLayout::FieldRole,
ui_casing_cm_cases_textbox);
+ //Check whether mass logging is enabled
+ row += 1;
+ ui_log_lbl = new QLabel(ui_casing_widget);
+ ui_log_lbl->setText(tr("Automatic Logging:"));
+ ui_log_lbl->setToolTip(
+ tr("If checked, all logs will be automatically written in the "
+ "/logs folder."));
- // ICLOG
+ ui_casing_layout->setWidget(row, QFormLayout::LabelRole, ui_log_lbl);
- ui_other_tab = new QWidget();
- ui_settings_tabs->addTab(ui_other_tab, tr("IC Log"));
+ ui_log_cb = new QCheckBox(ui_casing_widget);
+ ui_log_cb->setChecked(ao_app->get_auto_logging_enabled());
- ui_other_widget = new QWidget(ui_other_tab);
- ui_other_widget->setGeometry(QRect(10, 10, 361, 211));
-
- ui_other_layout = new QFormLayout(ui_other_widget);
- ui_other_layout->setLabelAlignment(Qt::AlignLeading | Qt::AlignLeft |
- Qt::AlignVCenter);
- ui_other_layout->setFormAlignment(Qt::AlignLeading | Qt::AlignLeft |
- Qt::AlignTop);
- ui_other_layout->setContentsMargins(0, 0, 0, 0);
-
- ui_other_fancy_icl_enabled_lb = new QLabel(ui_other_widget);
- ui_other_fancy_icl_enabled_lb->setText(tr("Colorful IC log:"));
- ui_other_fancy_icl_enabled_lb->setToolTip(
- tr("Enables colored text in the log."));
- ui_other_layout->setWidget(1, QFormLayout::LabelRole,
- ui_other_fancy_icl_enabled_lb);
-
- ui_other_fancy_icl_enabled_cb = new QCheckBox(ui_other_widget);
- ui_other_fancy_icl_enabled_cb->setChecked(
- ao_app->get_colored_iclog_enabled());
- ui_other_layout->setWidget(1, QFormLayout::FieldRole,
- ui_other_fancy_icl_enabled_cb);
-
- ui_other_fancy_icl_limit_lb = new QLabel(ui_other_widget);
- ui_other_fancy_icl_limit_lb->setText(tr("Only inline coloring:"));
- ui_other_fancy_icl_limit_lb->setToolTip(
- tr("Only inline coloring will be shown such as <>,|| etc."));
- ui_other_layout->setWidget(2, QFormLayout::LabelRole,
- ui_other_fancy_icl_limit_lb);
- ui_other_fancy_icl_limit_cb = new QCheckBox(ui_other_widget);
- ui_other_fancy_icl_limit_cb->setChecked(
- ao_app->colorlog_restricted_enabled());
- ui_other_layout->setWidget(2, QFormLayout::FieldRole,
- ui_other_fancy_icl_limit_cb);
-
- ui_other_mirror_icl_enabled_lb = new QLabel(ui_other_widget);
- ui_other_mirror_icl_enabled_lb->setText(tr("Mirror IC log:"));
- ui_other_mirror_icl_enabled_lb->setToolTip(
- tr("IC log will mirror the IC box. "
- "Meaning that if somebody gets interrupted nobody will know what they "
- "wanted to say. "
- "Enable for a more realistic experience."));
- ui_other_layout->setWidget(3, QFormLayout::LabelRole,
- ui_other_mirror_icl_enabled_lb);
- ui_other_mirror_icl_enabled_cb = new QCheckBox(ui_other_widget);
- ui_other_mirror_icl_enabled_cb->setChecked(ao_app->get_iclmir_enabled());
- ui_other_layout->setWidget(3, QFormLayout::FieldRole,
- ui_other_mirror_icl_enabled_cb);
-
- ui_downwards_lbl = new QLabel(ui_other_widget);
- ui_downwards_lbl->setText(tr("Log goes downwards:"));
- ui_downwards_lbl->setToolTip(
- tr("If ticked, new messages will appear at "
- "the bottom (like the OOC chatlog). The traditional "
- "(AO1) behaviour is equivalent to this being unticked."));
-
- ui_other_layout->setWidget(4, QFormLayout::LabelRole, ui_downwards_lbl);
-
- ui_downwards_cb = new QCheckBox(ui_other_widget);
- ui_downwards_cb->setChecked(p_ao_app->get_log_goes_downwards());
-
- ui_other_layout->setWidget(4, QFormLayout::FieldRole, ui_downwards_cb);
-
- ui_length_lbl = new QLabel(ui_other_widget);
- ui_length_lbl->setText(tr("Log length:"));
- ui_length_lbl->setToolTip(tr(
- "The amount of messages the IC chatlog will keep before "
- "deleting older messages. A value of 0 or below counts as 'infinite'."));
-
- ui_other_layout->setWidget(5, QFormLayout::LabelRole, ui_length_lbl);
-
- ui_length_spinbox = new QSpinBox(ui_other_widget);
- ui_length_spinbox->setMaximum(10000);
- ui_length_spinbox->setValue(p_ao_app->get_max_log_size());
-
- ui_other_layout->setWidget(5, QFormLayout::FieldRole, ui_length_spinbox);
+ ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_log_cb);
// When we're done, we should continue the updates!
setUpdatesEnabled(true);
@@ -660,17 +730,20 @@ void AOOptionsDialog::save_pressed()
configini->setValue("show_custom_shownames", ui_showname_cb->isChecked());
configini->setValue("master", ui_ms_textbox->text());
configini->setValue("discord", ui_discord_cb->isChecked());
- configini->setValue("shakeandflash", ui_epilepsy_cb->isChecked());
configini->setValue("language", ui_language_combobox->currentText().left(2));
- configini->setValue("punctuation_delay", ui_pun_delay_cb->isChecked());
- configini->setValue("slower_blips", ui_slower_blips_cb->isChecked());
+ configini->setValue("shake", ui_shake_cb->isChecked());
+ configini->setValue("effects", ui_effects_cb->isChecked());
+ configini->setValue("framenetwork", ui_framenetwork_cb->isChecked());
+ configini->setValue("colorlog", ui_colorlog_cb->isChecked());
+ configini->setValue("stickysounds", ui_stickysounds_cb->isChecked());
+ configini->setValue("stickyeffects", ui_stickyeffects_cb->isChecked());
+ configini->setValue("stickypres", ui_stickypres_cb->isChecked());
+ configini->setValue("customchat", ui_customchat_cb->isChecked());
+ configini->setValue("automatic_logging_enabled", ui_log_cb->isChecked());
QFile *callwordsini = new QFile(ao_app->get_base_path() + "callwords.ini");
- if (!callwordsini->open(QIODevice::WriteOnly | QIODevice::Truncate |
- QIODevice::Text)) {
- // Nevermind!
- }
- else {
+ if (callwordsini->open(QIODevice::WriteOnly | QIODevice::Truncate |
+ QIODevice::Text)) {
QTextStream out(callwordsini);
out << ui_callwords_textbox->toPlainText();
callwordsini->close();
@@ -684,7 +757,7 @@ void AOOptionsDialog::save_pressed()
configini->setValue("blip_rate", ui_bliprate_spinbox->value());
configini->setValue("blank_blip", ui_blank_blips_cb->isChecked());
configini->setValue("looping_sfx", ui_loopsfx_cb->isChecked());
- configini->setValue("kill_music_on_object", ui_objectmusic_cb->isChecked());
+ configini->setValue("objection_stop_music", ui_objectmusic_cb->isChecked());
configini->setValue("casing_enabled", ui_casing_enabled_cb->isChecked());
configini->setValue("casing_defence_enabled", ui_casing_def_cb->isChecked());
@@ -694,17 +767,9 @@ void AOOptionsDialog::save_pressed()
configini->setValue("casing_juror_enabled", ui_casing_jur_cb->isChecked());
configini->setValue("casing_steno_enabled", ui_casing_steno_cb->isChecked());
configini->setValue("casing_cm_enabled", ui_casing_cm_cb->isChecked());
- configini->setValue("casing_wit_enabled", ui_casing_wit_cb->isChecked());
configini->setValue("casing_can_host_cases",
ui_casing_cm_cases_textbox->text());
- configini->setValue("color_iclog_enabled",
- ui_other_fancy_icl_enabled_cb->isChecked());
- configini->setValue("mirror_iclog_enabled",
- ui_other_mirror_icl_enabled_cb->isChecked());
- configini->setValue("mirror_iclog_restricted",
- ui_other_fancy_icl_limit_cb->isChecked());
-
callwordsini->close();
done(0);
}
diff --git a/src/aoscene.cpp b/src/aoscene.cpp
index fc686336..594013a1 100644
--- a/src/aoscene.cpp
+++ b/src/aoscene.cpp
@@ -14,30 +14,55 @@ void AOScene::set_image(QString p_image)
{
QString background_path =
ao_app->get_image_suffix(ao_app->get_background_path(p_image));
- if (!file_exists(background_path))
- background_path = ao_app->get_image_suffix(
- ao_app->get_default_background_path(p_image)); // Default path
+ if (!file_exists(background_path)) // If image is missing, clear current image
+ {
+ this->clear();
+ this->setMovie(nullptr);
- if (file_exists(background_path) && background_path == last_image)
+ m_movie->stop();
+ last_image = "";
return;
+ }
- int w = this->width();
- int h = this->height();
+ if (!file_exists(background_path) || background_path != last_image)
+ {
+ this->clear();
+ this->setMovie(nullptr);
- this->clear();
- this->setMovie(nullptr);
-
- m_movie->stop();
- m_movie->setFileName(background_path);
- m_movie->setScaledSize(QSize(w, h));
+ m_movie->stop();
+ m_movie->setFileName(background_path);
+ }
- if (m_movie->isValid()) {
- this->setMovie(m_movie);
- m_movie->start();
+ if (m_movie->isValid() && m_movie->frameCount() > 1) {
+ m_movie->jumpToNextFrame();
+ float scale_factor = static_cast<float>(f_h) /
+ static_cast<float>(m_movie->frameRect().height());
+ // preserve aspect ratio
+ int n_w = static_cast<int>(m_movie->frameRect().width() * scale_factor);
+ int n_h = static_cast<int>(m_movie->frameRect().height() * scale_factor);
+
+ m_movie->setScaledSize(QSize(n_w, n_h));
+ this->resize(m_movie->scaledSize());
+ if (!file_exists(background_path) || background_path != last_image)
+ {
+ this->setMovie(m_movie);
+ m_movie->start();
+ }
+ QLabel::move(x + (f_w - n_w) / 2, y + (f_h - n_h) / 2); // Center
}
else {
QPixmap background(background_path);
- this->setPixmap(background.scaled(w, h));
+ auto transform_mode = Qt::FastTransformation;
+ if (background.height() > f_h) // We are downscaling, use anti-aliasing.
+ transform_mode = Qt::SmoothTransformation;
+
+ background = background.scaledToHeight(f_h, transform_mode);
+ this->resize(background.size());
+ this->setPixmap(background);
+ QLabel::move(
+ x + (f_w - background.width()) / 2,
+ y + (f_h - background.height()) /
+ 2); // Always center horizontally, always center vertically
}
last_image = background_path;
}
@@ -47,17 +72,23 @@ void AOScene::set_legacy_desk(QString p_image)
QString desk_path =
ao_app->get_image_suffix(ao_app->get_background_path(p_image));
- if (!file_exists(desk_path))
- desk_path = ao_app->get_image_suffix(
- ao_app->get_default_background_path(p_image)); // Default path
+ if (!file_exists(desk_path)) // If image is missing, clear current image
+ {
+ this->clear();
+ this->setMovie(nullptr);
+
+ m_movie->stop();
+ last_image = "";
+ return;
+ }
if (file_exists(desk_path) && desk_path == last_image)
return;
+
QPixmap f_desk(desk_path);
// vanilla desks vary in both width and height. in order to make that work
// with viewport rescaling, some INTENSE math is needed.
-
int vp_width = m_parent->width();
int vp_height = m_parent->height();
@@ -73,7 +104,7 @@ void AOScene::set_legacy_desk(QString p_image)
m_movie->setScaledSize(QSize(vp_width, final_h));
- if (m_movie->isValid()) {
+ if (m_movie->isValid() && m_movie->frameCount() > 1) {
this->setMovie(m_movie);
m_movie->start();
}
@@ -83,3 +114,18 @@ void AOScene::set_legacy_desk(QString p_image)
}
last_image = desk_path;
}
+
+void AOScene::combo_resize(int w, int h)
+{
+ QSize f_size(w, h);
+ f_w = w;
+ f_h = h;
+ this->resize(f_size);
+}
+
+void AOScene::move(int ax, int ay)
+{
+ x = ax;
+ y = ay;
+ QLabel::move(x, y);
+}
diff --git a/src/aosfxplayer.cpp b/src/aosfxplayer.cpp
index 4684acdb..127bda63 100644
--- a/src/aosfxplayer.cpp
+++ b/src/aosfxplayer.cpp
@@ -1,25 +1,52 @@
#include "aosfxplayer.h"
#include "file_functions.h"
-#if defined(BASSAUDIO) // Using bass.dll for sfx
-AOSfxPlayer::AOSfxPlayer(QWidget *parent, AOApplication *p_ao_app) : QObject()
+
+AOSfxPlayer::AOSfxPlayer(QWidget *parent, AOApplication *p_ao_app)
{
m_parent = parent;
ao_app = p_ao_app;
}
-void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout)
+#if defined(BASSAUDIO) // Using bass.dll for sfx
+void AOSfxPlayer::clear()
+{
+ for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) {
+ BASS_ChannelStop(m_stream_list[n_stream]);
+ }
+ set_volume_internal(m_volume);
+}
+
+void AOSfxPlayer::loop_clear()
{
- BASS_ChannelStop(m_stream);
+ for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) {
+ if ((BASS_ChannelFlags(m_stream_list[n_stream], 0, 0) & BASS_SAMPLE_LOOP))
+ BASS_ChannelStop(m_stream_list[n_stream]);
+ }
+ set_volume_internal(m_volume);
+}
+
+void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout,
+ int channel)
+{
+ if (channel == -1) {
+ if (BASS_ChannelIsActive(m_stream_list[channel]) == BASS_ACTIVE_PLAYING)
+ m_channel = (m_channel + 1) % m_channelmax;
+ channel = m_channel;
+ }
+
+ BASS_ChannelStop(m_stream_list[channel]);
QString misc_path = "";
QString char_path = "";
- QString sound_path = ao_app->get_sounds_path(p_sfx);
+ QString sound_path = ao_app->get_sfx_suffix(ao_app->get_sounds_path(p_sfx));
if (shout != "")
- misc_path = ao_app->get_base_path() + "misc/" + shout + "/" + p_sfx;
+ misc_path = ao_app->get_sfx_suffix(ao_app->get_base_path() + "misc/" +
+ shout + "/" + p_sfx);
if (p_char != "")
- char_path = ao_app->get_character_path(p_char, p_sfx);
+ char_path =
+ ao_app->get_sfx_suffix(ao_app->get_character_path(p_char, p_sfx));
QString f_path;
@@ -29,31 +56,31 @@ void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout)
f_path = misc_path;
else
f_path = sound_path;
- BASS_ChannelStop(m_stream);
- m_stream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0,
- BASS_STREAM_AUTOFREE | BASS_UNICODE |
- BASS_ASYNCFILE);
+
+ if (f_path.endsWith(".opus"))
+ m_stream_list[channel] = BASS_OPUS_StreamCreateFile(
+ FALSE, f_path.utf16(), 0, 0,
+ BASS_STREAM_AUTOFREE | BASS_UNICODE | BASS_ASYNCFILE);
+ else
+ m_stream_list[channel] = BASS_StreamCreateFile(
+ FALSE, f_path.utf16(), 0, 0,
+ BASS_STREAM_AUTOFREE | BASS_UNICODE | BASS_ASYNCFILE);
set_volume_internal(m_volume);
if (ao_app->get_audio_output_device() != "default")
- BASS_ChannelSetDevice(m_stream, BASS_GetDevice());
- BASS_ChannelPlay(m_stream, false);
- if (looping_sfx && ao_app->get_looping_sfx()) {
- BASS_ChannelFlags(m_stream, BASS_SAMPLE_LOOP, BASS_SAMPLE_LOOP);
- }
- else {
- BASS_ChannelFlags(m_stream, 0, BASS_SAMPLE_LOOP);
- }
+ BASS_ChannelSetDevice(m_stream_list[m_channel], BASS_GetDevice());
+ BASS_ChannelPlay(m_stream_list[m_channel], false);
}
-void AOSfxPlayer::setLooping(bool is_looping)
+void AOSfxPlayer::stop(int channel)
{
- this->looping_sfx = is_looping;
+ if (channel == -1) {
+ channel = m_channel;
+ }
+ BASS_ChannelStop(m_stream_list[channel]);
}
-void AOSfxPlayer::stop() { BASS_ChannelStop(m_stream); }
-
void AOSfxPlayer::set_volume(qreal p_value)
{
m_volume = p_value / 100;
@@ -62,19 +89,51 @@ void AOSfxPlayer::set_volume(qreal p_value)
void AOSfxPlayer::set_volume_internal(qreal p_value)
{
- float volume = p_value;
- BASS_ChannelSetAttribute(m_stream, BASS_ATTRIB_VOL, volume);
+ float volume = static_cast<float>(p_value);
+ for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) {
+ BASS_ChannelSetAttribute(m_stream_list[n_stream], BASS_ATTRIB_VOL, volume);
+ }
+}
+
+void AOSfxPlayer::set_looping(bool toggle, int channel)
+{
+ if (channel == -1) {
+ channel = m_channel;
+ }
+ m_looping = toggle;
+ if (BASS_ChannelFlags(m_stream_list[channel], 0, 0) & BASS_SAMPLE_LOOP) {
+ if (m_looping == false)
+ BASS_ChannelFlags(m_stream_list[channel], 0,
+ BASS_SAMPLE_LOOP); // remove the LOOP flag
+ }
+ else {
+ if (m_looping == true)
+ BASS_ChannelFlags(m_stream_list[channel], BASS_SAMPLE_LOOP,
+ BASS_SAMPLE_LOOP); // set the LOOP flag
+ }
}
#elif defined(QTAUDIO) // Using Qt's QSoundEffect class
-AOSfxPlayer::AOSfxPlayer(QWidget *parent, AOApplication *p_ao_app) : QObject()
+
+void AOSfxPlayer::clear()
{
- m_parent = parent;
- ao_app = p_ao_app;
+ for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) {
+ m_stream_list[n_stream].stop();
+ }
+ set_volume_internal(m_volume);
}
-void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout)
+void AOSfxPlayer::loop_clear()
{
- m_sfx.stop();
+ for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) {
+ m_stream_list[n_stream].stop();
+ }
+ set_volume_internal(m_volume);
+}
+
+void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout,
+ int channel)
+{
+ m_stream_list[channel].stop();
QString misc_path = "";
QString char_path = "";
@@ -96,21 +155,22 @@ void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout)
if (file_exists(f_path)) // if its missing, it will glitch out
{
- m_sfx.setSource(QUrl::fromLocalFile(f_path));
+ m_stream_list[channel].setSource(QUrl::fromLocalFile(f_path));
set_volume_internal(m_volume);
- m_sfx.play();
+ m_stream_list[channel].play();
}
}
-void AOSfxPlayer::setLooping(bool is_looping)
+void AOSfxPlayer::stop(int channel)
{
- this->looping_sfx = is_looping;
+ if (channel == -1) {
+ channel = m_channel;
+ }
+ m_stream_list[channel].stop();
}
-void AOSfxPlayer::stop() { m_sfx.stop(); }
-
void AOSfxPlayer::set_volume(qreal p_value)
{
m_volume = p_value / 100;
@@ -119,25 +179,33 @@ void AOSfxPlayer::set_volume(qreal p_value)
void AOSfxPlayer::set_volume_internal(qreal p_value)
{
- m_sfx.setVolume(m_volume);
+ float volume = static_cast<float>(p_value);
+ for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) {
+ m_stream_list[n_stream].setVolume(volume);
+ }
}
-#else
-AOSfxPlayer::AOSfxPlayer(QWidget *parent, AOApplication *p_ao_app) : QObject()
+
+void AOSfxPlayer::set_looping(bool toggle, int channel)
{
- m_parent = parent;
- ao_app = p_ao_app;
+ if (channel == -1) {
+ channel = m_channel;
+ }
+ m_looping = toggle;
+ // TODO
}
+#else
+void AOSfxPlayer::clear() {}
-void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout) {}
+void AOSfxPlayer::loop_clear() {}
-void AOSfxPlayer::setLooping(bool is_looping)
-{
- this->looping_sfx = is_looping;
-}
+void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout,
+ int channel) {}
-void AOSfxPlayer::stop() {}
+void AOSfxPlayer::stop(int channel) {}
void AOSfxPlayer::set_volume(qreal p_value) {}
void AOSfxPlayer::set_volume_internal(qreal p_value) {}
+
+void AOSfxPlayer::set_looping(bool toggle, int channel) {}
#endif
diff --git a/src/aotextarea.cpp b/src/aotextarea.cpp
index 04d44318..52e32f55 100644
--- a/src/aotextarea.cpp
+++ b/src/aotextarea.cpp
@@ -2,8 +2,16 @@
AOTextArea::AOTextArea(QWidget *p_parent) : QTextBrowser(p_parent) {}
+void AOTextArea::append_linked(QString p_message)
+{
+ QString result = p_message.toHtmlEscaped()
+ .replace("\n", "<br>")
+ .replace(url_parser_regex, "<a href='\\1'>\\1</a>");
+ this->insertHtml(result);
+}
+
void AOTextArea::append_chatmessage(QString p_name, QString p_message,
- QString p_colour, bool song)
+ QString p_colour)
{
const QTextCursor old_cursor = this->textCursor();
const int old_scrollbar_value = this->verticalScrollBar()->value();
@@ -13,18 +21,14 @@ void AOTextArea::append_chatmessage(QString p_name, QString p_message,
this->moveCursor(QTextCursor::End);
this->append("");
- if (song)
- this->insertHtml("<b><font color=" + p_colour + ">" +
- p_name.toHtmlEscaped() + "</font></b>&nbsp;");
- else
- this->insertHtml("<b><font color=" + p_colour + ">" +
- p_name.toHtmlEscaped() + "</font></b>:&nbsp;");
+ this->insertHtml("<b><font color=" + p_colour + ">" + p_name.toHtmlEscaped() +
+ "</font></b>:&nbsp;");
// cheap workarounds ahoy
p_message += " ";
QString result = p_message.toHtmlEscaped()
.replace("\n", "<br>")
- .replace(omnis_dank_url_regex, "<a href='\\1'>\\1</a>");
+ .replace(url_parser_regex, "<a href='\\1'>\\1</a>");
this->insertHtml(result);
@@ -44,7 +48,7 @@ void AOTextArea::append_error(QString p_message)
p_message += " ";
QString result = p_message.replace("\n", "<br>")
- .replace(omnis_dank_url_regex, "<a href='\\1'>\\1</a>");
+ .replace(url_parser_regex, "<a href='\\1'>\\1</a>");
this->insertHtml("<font color='red'>" + result + "</font>");
diff --git a/src/charselect.cpp b/src/charselect.cpp
index 9dee2373..8e0aab5e 100644
--- a/src/charselect.cpp
+++ b/src/charselect.cpp
@@ -5,54 +5,6 @@
#include "file_functions.h"
#include "hardware_functions.h"
-class AOCharSelectGenerationThreading : public QRunnable {
-public:
- Courtroom *thisCourtroom;
- int char_num;
- AOCharButton *char_button;
- AOCharSelectGenerationThreading(Courtroom *my_courtroom, int character_number)
- {
- thisCourtroom = my_courtroom;
- char_num = character_number;
- }
- void run()
- {
- // we take the button we are supposed to mess with, and not whatever comes
- // first
- AOCharButton *thisCharacterButton =
- thisCourtroom->ui_char_button_list.at(char_num);
- thisCharacterButton->reset();
- thisCharacterButton->hide();
- thisCharacterButton->set_image(thisCourtroom->char_list.at(char_num).name);
-
- thisCourtroom->connect(thisCharacterButton, SIGNAL(clicked()),
- thisCourtroom->char_button_mapper, SLOT(map()));
- thisCourtroom->char_button_mapper->setMapping(thisCharacterButton,
- char_num);
- }
-};
-
-void AOCharSelectFilter(Courtroom *thisCourtroom, int char_num)
-{
- AOCharButton *current_char = thisCourtroom->ui_char_button_list.at(char_num);
-
- if (!thisCourtroom->ui_char_taken->isChecked() &&
- thisCourtroom->char_list.at(char_num).taken)
- return;
-
- if (!thisCourtroom->char_list.at(char_num).name.contains(
- thisCourtroom->ui_char_search->text(), Qt::CaseInsensitive))
- return;
-
- // We only really need to update the fact that a character is taken
- // for the buttons that actually appear.
- // You'd also update the passwordedness and etc. here later.
- current_char->reset();
- current_char->set_taken(thisCourtroom->char_list.at(char_num).taken);
-
- thisCourtroom->ui_char_button_list_filtered.append(current_char);
-}
-
void Courtroom::construct_char_select()
{
ui_char_select_background = new AOImage(this, ao_app);
@@ -92,8 +44,6 @@ void Courtroom::construct_char_select()
set_size_and_pos(ui_char_buttons, "char_buttons");
- connect(char_button_mapper, SIGNAL(mapped(int)), this,
- SLOT(char_clicked(int)));
connect(ui_back_to_lobby, SIGNAL(clicked()), this,
SLOT(on_back_to_lobby_clicked()));
@@ -120,15 +70,15 @@ void Courtroom::set_char_select()
ao_app->get_element_dimensions("char_select", filename);
if (f_charselect.width < 0 || f_charselect.height < 0) {
- qDebug()
- << "W: did not find courtroom width or height in courtroom_design.ini!";
+ qDebug() << "W: did not find char_select width or height in "
+ "courtroom_design.ini!";
this->resize(714, 668);
}
else
this->resize(f_charselect.width, f_charselect.height);
ui_char_select_background->resize(f_charselect.width, f_charselect.height);
- ui_char_select_background->set_image("charselect_background.png");
+ ui_char_select_background->set_image("charselect_background");
filter_character_list();
@@ -173,28 +123,33 @@ void Courtroom::set_char_select_page()
void Courtroom::char_clicked(int n_char)
{
- QString char_ini_path =
- ao_app->get_character_path(char_list.at(n_char).name, "char.ini");
+ if (n_char != -1)
+ {
+ QString char_ini_path =
+ ao_app->get_character_path(char_list.at(n_char).name, "char.ini");
- qDebug() << "char_ini_path" << char_ini_path;
+ qDebug() << "char_ini_path" << char_ini_path;
- if (!file_exists(char_ini_path)) {
- call_notice(tr("Could not find %1").arg(char_ini_path, 1));
- return;
+ if (!file_exists(char_ini_path)) {
+ call_notice("Could not find " + char_ini_path);
+ return;
+ }
}
- if (n_char == m_cid) {
- enter_courtroom(m_cid);
- }
- else {
+ if (n_char != m_cid) {
ao_app->send_server_packet(
new AOPacket("PW#" + ui_char_password->text() + "#%"));
ao_app->send_server_packet(
new AOPacket("CC#" + QString::number(ao_app->s_pv) + "#" +
QString::number(n_char) + "#" + get_hdid() + "#%"));
}
+ else
+ update_character(n_char);
+
+ enter_courtroom();
- ui_ic_chat_name->setPlaceholderText(char_list.at(n_char).name);
+ if (n_char != -1)
+ ui_ic_chat_name->setPlaceholderText(char_list.at(n_char).name);
}
void Courtroom::put_button_in_place(int starting, int chars_on_this_page)
@@ -250,27 +205,40 @@ void Courtroom::character_loading_finished()
}
// First, we'll make all the character buttons in the very beginning.
- // Since we can't trust what will happen during the multi threading process,
- // we assign the buttons their locations in the list according to the
- // character list.
- for (int n = 0; n < char_list.size(); n++) {
- AOCharButton *characterButton =
- new AOCharButton(ui_char_buttons, ao_app, 0, 0, char_list.at(n).taken);
- ui_char_button_list.append(characterButton);
- }
-
// We also hide them all, so they can't be accidentally clicked.
// Later on, we'll be revealing buttons as we need them.
for (int n = 0; n < char_list.size(); n++) {
- AOCharSelectGenerationThreading *char_generate =
- new AOCharSelectGenerationThreading(this, n);
- QThreadPool::globalInstance()->start(char_generate);
- if (QThreadPool::globalInstance()->activeThreadCount() ==
- QThreadPool::globalInstance()->maxThreadCount()) {
- QThreadPool::globalInstance()->waitForDone();
+ AOCharButton *char_button =
+ new AOCharButton(ui_char_buttons, ao_app, 0, 0, char_list.at(n).taken);
+ char_button->reset();
+ char_button->hide();
+ char_button->set_image(char_list.at(n).name);
+ char_button->setToolTip(char_list.at(n).name);
+ ui_char_button_list.append(char_button);
+
+ connect(char_button, &AOCharButton::clicked,
+ [this, n]() { this->char_clicked(n); });
+
+ // This part here serves as a way of showing to the player that the game is
+ // still running, it is just loading the pictures of the characters.
+ if (ao_app->lobby_constructed) {
+ ao_app->generated_chars++;
+ int total_loading_size = ao_app->char_list_size * 2 +
+ ao_app->evidence_list_size +
+ ao_app->music_list_size;
+ int loading_value =
+ int(((ao_app->loaded_chars + ao_app->generated_chars +
+ ao_app->loaded_music + ao_app->loaded_evidence) /
+ static_cast<double>(total_loading_size)) *
+ 100);
+ ao_app->w_lobby->set_loading_value(loading_value);
+ ao_app->w_lobby->set_loading_text(
+ tr("Generating chars:\n%1/%2")
+ .arg(QString::number(ao_app->generated_chars))
+ .arg(QString::number(ao_app->char_list_size)));
}
}
- QThreadPool::globalInstance()->waitForDone();
+
filter_character_list();
}
@@ -278,7 +246,27 @@ void Courtroom::filter_character_list()
{
ui_char_button_list_filtered.clear();
for (int i = 0; i < char_list.size(); i++) {
- AOCharSelectFilter(this, i);
+ AOCharButton *current_char = ui_char_button_list.at(i);
+
+ // It seems passwording characters is unimplemented yet?
+ // Until then, this will stay here, I suppose.
+ // if (ui_char_passworded->isChecked() && character_is_passworded??)
+ // continue;
+
+ if (!ui_char_taken->isChecked() && char_list.at(i).taken)
+ continue;
+
+ if (!char_list.at(i).name.contains(ui_char_search->text(),
+ Qt::CaseInsensitive))
+ continue;
+
+ // We only really need to update the fact that a character is taken
+ // for the buttons that actually appear.
+ // You'd also update the passwordedness and etc. here later.
+ current_char->reset();
+ current_char->set_taken(char_list.at(i).taken);
+
+ ui_char_button_list_filtered.append(current_char);
}
current_char_page = 0;
diff --git a/src/chatlogpiece.cpp b/src/chatlogpiece.cpp
index 9017b961..2a041f13 100644
--- a/src/chatlogpiece.cpp
+++ b/src/chatlogpiece.cpp
@@ -2,11 +2,11 @@
chatlogpiece::chatlogpiece()
{
- name = "UNKNOWN";
- showname = "UNKNOWN";
- message = "UNKNOWN";
+ name = tr("UNKNOWN");
+ showname = tr("UNKNOWN");
+ message = tr("UNKNOWN");
color = 0;
- is_song = false;
+ p_is_song = false;
datetime = QDateTime::currentDateTime().toUTC();
}
@@ -16,7 +16,7 @@ chatlogpiece::chatlogpiece(QString p_name, QString p_showname,
name = p_name;
showname = p_showname;
message = p_message;
- is_song = p_song;
+ p_is_song = p_song;
color = p_color;
datetime = QDateTime::currentDateTime().toUTC();
}
@@ -28,7 +28,7 @@ chatlogpiece::chatlogpiece(QString p_name, QString p_showname,
name = p_name;
showname = p_showname;
message = p_message;
- is_song = p_song;
+ p_is_song = p_song;
color = p_color;
datetime = p_datetime.toUTC();
}
@@ -41,9 +41,10 @@ QString chatlogpiece::get_message() { return message; }
QDateTime chatlogpiece::get_datetime() { return datetime; }
-bool chatlogpiece::get_is_song() { return is_song; }
+bool chatlogpiece::is_song() { return p_is_song; }
QString chatlogpiece::get_datetime_as_string() { return datetime.toString(); }
+
int chatlogpiece::get_chat_color() { return color; }
QString chatlogpiece::get_full()
@@ -51,13 +52,15 @@ QString chatlogpiece::get_full()
QString full = "[";
full.append(get_datetime_as_string());
- full.append(" UTC] ");
+ full.append("] ");
full.append(get_showname());
full.append(" (");
full.append(get_name());
full.append(")");
- if (is_song)
- full.append(" has played a song: ");
+ if (p_is_song)
+ full.append(tr(" has played a song: "));
+ else
+ full.append(": ");
full.append(get_message());
return full;
diff --git a/src/courtroom.cpp b/src/courtroom.cpp
index 11c0bdab..98b6a9c3 100644
--- a/src/courtroom.cpp
+++ b/src/courtroom.cpp
@@ -1,4487 +1,4772 @@
-#include "courtroom.h"
-
-Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
-{
- ao_app = p_ao_app;
-#ifdef BASSAUDIO
- // Change the default audio output device to be the one the user has given
- // in his config.ini file for now.
- unsigned int a = 0;
- BASS_DEVICEINFO info;
-
- if (ao_app->get_audio_output_device() == "default") {
- BASS_Init(-1, 48000, BASS_DEVICE_LATENCY, nullptr, nullptr);
- load_bass_opus_plugin();
- }
- else {
- for (a = 0; BASS_GetDeviceInfo(a, &info); a++) {
- if (ao_app->get_audio_output_device() == info.name) {
- BASS_SetDevice(a);
- BASS_Init(static_cast<int>(a), 48000, BASS_DEVICE_LATENCY, nullptr,
- nullptr);
- load_bass_opus_plugin();
- qDebug() << info.name << "was set as the default audio output device.";
- break;
- }
- }
- }
-#elif defined QTAUDIO
-
- if (ao_app->get_audio_output_device() != "default") {
- foreach (const QAudioDeviceInfo &deviceInfo,
- QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) {
- if (ao_app->get_audio_output_device() == deviceInfo.deviceName()) {
- ao_app->QtAudioDevice = deviceInfo;
- qDebug() << deviceInfo.deviceName()
- << "was set as the default audio output device.";
- break;
- }
- }
- }
-#endif
-
- keepalive_timer = new QTimer(this);
- keepalive_timer->start(60000);
-
- chat_tick_timer = new QTimer(this);
-
- text_delay_timer = new QTimer(this);
- text_delay_timer->setSingleShot(true);
-
- sfx_delay_timer = new QTimer(this);
- sfx_delay_timer->setSingleShot(true);
-
- realization_timer = new QTimer(this);
- realization_timer->setSingleShot(true);
-
- char_button_mapper = new QSignalMapper(this);
-
- music_player = new AOMusicPlayer(this, ao_app);
- music_player->set_volume(0);
-
- sfx_player = new AOSfxPlayer(this, ao_app);
- sfx_player->set_volume(0);
-
- objection_player = new AOSfxPlayer(this, ao_app);
- objection_player->set_volume(0);
-
- misc_sfx_player = new AOSfxPlayer(this, ao_app);
- misc_sfx_player->set_volume(0);
- frame_emote_sfx_player = new AOSfxPlayer(this, ao_app);
- frame_emote_sfx_player->set_volume(0);
- pair_frame_emote_sfx_player = new AOSfxPlayer(this, ao_app);
- pair_frame_emote_sfx_player->set_volume(0);
-
- char_button_mapper = new QSignalMapper(this);
-
- blip_player = new AOBlipPlayer(this, ao_app);
- blip_player->set_volume(0);
-
- modcall_player = new AOSfxPlayer(this, ao_app);
- modcall_player->set_volume(50);
-
- ui_background = new AOImage(this, ao_app);
-
- ui_viewport = new QWidget(this);
- ui_vp_background = new AOScene(ui_viewport, ao_app);
- ui_vp_speedlines = new AOMovie(ui_viewport, ao_app);
- ui_vp_speedlines->set_play_once(false);
- ui_vp_player_char = new AOCharMovie(ui_viewport, ao_app);
- ui_vp_player_char->frame_specific_sfx_player = frame_emote_sfx_player;
- ui_vp_player_char->mycourtroom = this;
- ui_vp_sideplayer_char = new AOCharMovie(ui_viewport, ao_app);
- ui_vp_sideplayer_char->frame_specific_sfx_player =
- pair_frame_emote_sfx_player;
- ui_vp_sideplayer_char->mycourtroom = this;
- ui_vp_sideplayer_char->hide();
- ui_vp_desk = new AOScene(ui_viewport, ao_app);
- ui_vp_legacy_desk = new AOScene(ui_viewport, ao_app);
-
- ui_vp_evidence_display = new AOEvidenceDisplay(this, ao_app);
-
- ui_vp_chatbox = new AOImage(this, ao_app);
- ui_vp_showname = new QLabel(ui_vp_chatbox);
- ui_vp_message = new QTextEdit(ui_vp_chatbox);
- ui_vp_message->setFrameStyle(QFrame::NoFrame);
- ui_vp_message->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- ui_vp_message->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- ui_vp_message->setReadOnly(true);
-
- ui_vp_testimony = new AOMovie(this, ao_app);
- ui_vp_testimony->set_play_once(false);
- ui_vp_realization = new AOMovie(this, ao_app);
- ui_vp_wtce = new AOMovie(this, ao_app);
- ui_vp_objection = new AOMovie(this, ao_app);
-
- ui_ic_chatlog = new QTextEdit(this);
- ui_ic_chatlog->setReadOnly(true);
-
- log_maximum_blocks = ao_app->get_max_log_size();
- log_goes_downwards = ao_app->get_log_goes_downwards();
-
- ui_ms_chatlog = new AOTextArea(this);
- ui_ms_chatlog->setReadOnly(true);
- ui_ms_chatlog->setOpenExternalLinks(true);
- ui_ms_chatlog->hide();
-
- ui_server_chatlog = new AOTextArea(this);
- ui_server_chatlog->setReadOnly(true);
- ui_server_chatlog->setOpenExternalLinks(true);
-
- ui_area_list = new QListWidget(this);
-
- ui_music_list = new QTreeWidget(this);
- ui_music_list->setColumnCount(2);
- ui_music_list->hideColumn(1);
- ui_music_list->setHeaderHidden(true);
- ui_music_list->setContextMenuPolicy(Qt::CustomContextMenu);
- ui_music_list->setAutoFillBackground(true);
- ui_music_list->setExpandsOnDoubleClick(true);
- ui_music_list->setRootIsDecorated(true);
- ui_music_list->header()->setStretchLastSection(false);
- ui_music_list->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
- ui_music_list->setContextMenuPolicy(Qt::CustomContextMenu);
-
- ui_music_list->hide();
-
- ui_ic_chat_name = new QLineEdit(this);
- ui_ic_chat_name->setFrame(false);
- ui_ic_chat_name->setPlaceholderText(tr("Showname"));
-
- ui_ic_chat_message = new QLineEdit(this);
- ui_ic_chat_message->setFrame(false);
- ui_ic_chat_message->setPlaceholderText(tr("Message"));
-
- ui_muted = new AOImage(ui_ic_chat_message, ao_app);
- ui_muted->hide();
-
- ui_ooc_chat_message = new QLineEdit(this);
- ui_ooc_chat_message->setFrame(false);
- ui_ooc_chat_message->setPlaceholderText(tr("OOC Message"));
-
- ui_ooc_chat_name = new QLineEdit(this);
- ui_ooc_chat_name->setFrame(false);
- ui_ooc_chat_name->setPlaceholderText(tr("Name"));
- ui_ooc_chat_name->setMaxLength(30);
- ui_ooc_chat_name->setText(p_ao_app->get_default_username());
-
- punctuation_modifier = p_ao_app->get_pundelay();
- slower_blips = p_ao_app->get_slower_blips();
- colorf_iclog = p_ao_app->get_colored_iclog_enabled();
- mirror_iclog = p_ao_app->get_iclmir_enabled();
- colorf_limit = p_ao_app->colorlog_restricted_enabled();
- keep_evidence_display = p_ao_app->is_keepevi_enabled();
-
- // ui_area_password = new QLineEdit(this);
- // ui_area_password->setFrame(false);
- ui_music_search = new QLineEdit(this);
- ui_music_search->setFrame(false);
- ui_music_search->setPlaceholderText(tr("Search"));
-
- construct_emotes();
-
- ui_emote_left = new AOButton(this, ao_app);
- ui_emote_right = new AOButton(this, ao_app);
-
- ui_emote_dropdown = new QComboBox(this);
- ui_pos_dropdown = new QComboBox(this);
- ui_pos_dropdown->addItem("wit");
- ui_pos_dropdown->addItem("def");
- ui_pos_dropdown->addItem("pro");
- ui_pos_dropdown->addItem("jud");
- ui_pos_dropdown->addItem("hld");
- ui_pos_dropdown->addItem("hlp");
- ui_pos_dropdown->addItem("jur");
- ui_pos_dropdown->addItem("sea");
-
- ui_defense_bar = new AOImage(this, ao_app);
- ui_prosecution_bar = new AOImage(this, ao_app);
-
- ui_music_label = new QLabel(this);
- ui_sfx_label = new QLabel(this);
- ui_blip_label = new QLabel(this);
-
- ui_log_limit_label = new QLabel(this);
-
- ui_hold_it = new AOButton(this, ao_app);
- ui_objection = new AOButton(this, ao_app);
- ui_take_that = new AOButton(this, ao_app);
-
- ui_ooc_toggle = new AOButton(this, ao_app);
- ui_witness_testimony = new AOButton(this, ao_app);
- ui_cross_examination = new AOButton(this, ao_app);
- ui_guilty = new AOButton(this, ao_app);
- ui_not_guilty = new AOButton(this, ao_app);
-
- ui_change_character = new AOButton(this, ao_app);
- ui_reload_theme = new AOButton(this, ao_app);
- ui_call_mod = new AOButton(this, ao_app);
- ui_settings = new AOButton(this, ao_app);
- ui_announce_casing = new AOButton(this, ao_app);
- ui_switch_area_music = new AOButton(this, ao_app);
-
- ui_pre = new QCheckBox(this);
- ui_pre->setText(tr("Pre"));
-
- ui_flip = new QCheckBox(this);
- ui_flip->setText(tr("Flip"));
- ui_flip->hide();
-
- ui_guard = new QCheckBox(this);
-
- ui_guard->setText(tr("Disable Modcalls"));
-
- ui_guard->hide();
-
- ui_casing = new QCheckBox(this);
- ui_casing->setChecked(ao_app->get_casing_enabled());
- ui_casing->setText(tr("Casing"));
- ui_casing->hide();
-
- ui_showname_enable = new QCheckBox(this);
- ui_showname_enable->setChecked(ao_app->get_showname_enabled_by_default());
- ui_showname_enable->setText(tr("Shownames"));
-
- ui_pre_non_interrupt = new QCheckBox(this);
- ui_pre_non_interrupt->setText(tr("No Interrupt"));
- ui_pre_non_interrupt->hide();
-
- ui_custom_objection = new AOButton(this, ao_app);
- ui_custom_objection->setContextMenuPolicy(Qt::CustomContextMenu);
- custom_obj_menu = new QMenu;
-
- ui_realization = new AOButton(this, ao_app);
- ui_screenshake = new AOButton(this, ao_app);
- ui_mute = new AOButton(this, ao_app);
-
- ui_defense_plus = new AOButton(this, ao_app);
- ui_defense_minus = new AOButton(this, ao_app);
-
- ui_prosecution_plus = new AOButton(this, ao_app);
- ui_prosecution_minus = new AOButton(this, ao_app);
-
- ui_text_color = new QComboBox(this);
- ui_text_color->addItem(tr("White"));
- ui_text_color->addItem(tr("Green"));
- ui_text_color->addItem(tr("Red"));
- ui_text_color->addItem(tr("Orange"));
- ui_text_color->addItem(tr("Blue"));
- ui_text_color->addItem(tr("Yellow"));
- ui_text_color->addItem(tr("Rainbow"));
- ui_text_color->addItem(tr("Pink"));
- ui_text_color->addItem(tr("Cyan"));
-
- ui_music_slider = new QSlider(Qt::Horizontal, this);
- ui_music_slider->setRange(0, 100);
- ui_music_slider->setValue(ao_app->get_default_music());
-
- ui_sfx_slider = new QSlider(Qt::Horizontal, this);
- ui_sfx_slider->setRange(0, 100);
- ui_sfx_slider->setValue(ao_app->get_default_sfx());
-
- ui_blip_slider = new QSlider(Qt::Horizontal, this);
- ui_blip_slider->setRange(0, 100);
- ui_blip_slider->setValue(ao_app->get_default_blip());
-
- ui_log_limit_spinbox = new QSpinBox(this);
- ui_log_limit_spinbox->setRange(0, 10000);
- ui_log_limit_spinbox->setValue(ao_app->get_max_log_size());
-
- ui_mute_list = new QListWidget(this);
-
- ui_pair_list = new QListWidget(this);
- ui_pair_offset_spinbox = new QSpinBox(this);
- ui_pair_offset_spinbox->setRange(-100, 100);
- ui_pair_offset_spinbox->setSuffix(tr("% offset"));
- ui_pair_button = new AOButton(this, ao_app);
-
- ui_evidence_button = new AOButton(this, ao_app);
-
- construct_evidence();
-
- construct_char_select();
-
- connect(keepalive_timer, SIGNAL(timeout()), this, SLOT(ping_server()));
-
- connect(ui_vp_objection, SIGNAL(done()), this, SLOT(objection_done()));
- connect(ui_vp_player_char, SIGNAL(done()), this, SLOT(preanim_done()));
-
- connect(text_delay_timer, SIGNAL(timeout()), this,
- SLOT(start_chat_ticking()));
- connect(sfx_delay_timer, SIGNAL(timeout()), this, SLOT(play_sfx()));
-
- connect(chat_tick_timer, SIGNAL(timeout()), this, SLOT(chat_tick()));
- connect(realization_timer, SIGNAL(timeout()), this, SLOT(realization_done()));
-
- connect(ui_emote_left, SIGNAL(clicked()), this,
- SLOT(on_emote_left_clicked()));
- connect(ui_emote_right, SIGNAL(clicked()), this,
- SLOT(on_emote_right_clicked()));
-
- connect(ui_emote_dropdown, SIGNAL(activated(int)), this,
- SLOT(on_emote_dropdown_changed(int)));
- connect(ui_pos_dropdown, SIGNAL(currentIndexChanged(int)), this,
- SLOT(on_pos_dropdown_changed(int)));
-
- connect(ui_mute_list, SIGNAL(clicked(QModelIndex)), this,
- SLOT(on_mute_list_clicked(QModelIndex)));
-
- connect(ui_ic_chat_message, SIGNAL(returnPressed()), this,
- SLOT(on_chat_return_pressed()));
-
- connect(ui_ooc_chat_message, SIGNAL(returnPressed()), this,
- SLOT(on_ooc_return_pressed()));
-
- connect(ui_music_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
- this, SLOT(on_music_list_double_clicked(QTreeWidgetItem *, int)));
- connect(ui_area_list, SIGNAL(doubleClicked(QModelIndex)), this,
- SLOT(on_area_list_double_clicked(QModelIndex)));
- connect(ui_hold_it, SIGNAL(clicked()), this, SLOT(on_hold_it_clicked()));
- connect(ui_objection, SIGNAL(clicked()), this, SLOT(on_objection_clicked()));
- connect(ui_take_that, SIGNAL(clicked()), this, SLOT(on_take_that_clicked()));
- connect(ui_custom_objection, SIGNAL(clicked()), this,
- SLOT(on_custom_objection_clicked()));
- connect(ui_custom_objection,
- SIGNAL(customContextMenuRequested(const QPoint &)), this,
- SLOT(ShowContextMenu(const QPoint &)));
- connect(ui_realization, SIGNAL(clicked()), this,
- SLOT(on_realization_clicked()));
- connect(ui_screenshake, SIGNAL(clicked()), this,
- SLOT(on_screenshake_clicked()));
- connect(ui_mute, SIGNAL(clicked()), this, SLOT(on_mute_clicked()));
-
- connect(ui_defense_minus, SIGNAL(clicked()), this,
- SLOT(on_defense_minus_clicked()));
- connect(ui_defense_plus, SIGNAL(clicked()), this,
- SLOT(on_defense_plus_clicked()));
- connect(ui_prosecution_minus, SIGNAL(clicked()), this,
- SLOT(on_prosecution_minus_clicked()));
- connect(ui_prosecution_plus, SIGNAL(clicked()), this,
- SLOT(on_prosecution_plus_clicked()));
-
- connect(ui_text_color, SIGNAL(currentIndexChanged(int)), this,
- SLOT(on_text_color_changed(int)));
-
- connect(ui_music_slider, SIGNAL(valueChanged(int)), this,
- SLOT(on_music_slider_moved(int)));
- connect(ui_sfx_slider, SIGNAL(valueChanged(int)), this,
- SLOT(on_sfx_slider_moved(int)));
- connect(ui_blip_slider, SIGNAL(valueChanged(int)), this,
- SLOT(on_blip_slider_moved(int)));
-
- connect(ui_log_limit_spinbox, SIGNAL(valueChanged(int)), this,
- SLOT(on_log_limit_changed(int)));
-
- connect(ui_ooc_toggle, SIGNAL(clicked()), this,
- SLOT(on_ooc_toggle_clicked()));
-
- connect(ui_music_search, SIGNAL(returnPressed()), this,
- SLOT(on_music_search_keypr()));
- connect(ui_music_search, SIGNAL(textChanged(QString)), this,
- SLOT(on_music_search_edited(QString)));
-
- connect(ui_witness_testimony, SIGNAL(clicked()), this,
- SLOT(on_witness_testimony_clicked()));
- connect(ui_cross_examination, SIGNAL(clicked()), this,
- SLOT(on_cross_examination_clicked()));
- connect(ui_guilty, SIGNAL(clicked()), this, SLOT(on_guilty_clicked()));
- connect(ui_not_guilty, SIGNAL(clicked()), this,
- SLOT(on_not_guilty_clicked()));
-
- connect(ui_change_character, SIGNAL(clicked()), this,
- SLOT(on_change_character_clicked()));
- connect(ui_reload_theme, SIGNAL(clicked()), this,
- SLOT(on_reload_theme_clicked()));
- connect(ui_call_mod, SIGNAL(clicked()), this, SLOT(on_call_mod_clicked()));
- connect(ui_settings, SIGNAL(clicked()), this, SLOT(on_settings_clicked()));
- connect(ui_announce_casing, SIGNAL(clicked()), this,
- SLOT(on_announce_casing_clicked()));
- connect(ui_switch_area_music, SIGNAL(clicked()), this,
- SLOT(on_switch_area_music_clicked()));
-
- connect(ui_pre, SIGNAL(clicked()), this, SLOT(on_pre_clicked()));
- connect(ui_flip, SIGNAL(clicked()), this, SLOT(on_flip_clicked()));
- connect(ui_guard, SIGNAL(clicked()), this, SLOT(on_guard_clicked()));
- connect(ui_casing, SIGNAL(clicked()), this, SLOT(on_casing_clicked()));
-
- connect(ui_showname_enable, SIGNAL(clicked()), this,
- SLOT(on_showname_enable_clicked()));
-
- connect(ui_pair_button, SIGNAL(clicked()), this, SLOT(on_pair_clicked()));
- connect(ui_pair_list, SIGNAL(clicked(QModelIndex)), this,
- SLOT(on_pair_list_clicked(QModelIndex)));
- connect(ui_pair_offset_spinbox, SIGNAL(valueChanged(int)), this,
- SLOT(on_pair_offset_changed(int)));
-
- connect(ui_evidence_button, SIGNAL(clicked()), this,
- SLOT(on_evidence_button_clicked()));
-
- set_widgets();
-
- set_char_select();
- detect_fallback_text();
-}
-
-void Courtroom::set_mute_list()
-{
- mute_map.clear();
-
- // maps which characters are muted based on cid, none are muted by default
- for (int n_cid = 0; n_cid < char_list.size(); n_cid++) {
- mute_map.insert(n_cid, false);
- }
-
- QStringList sorted_mute_list;
-
- for (char_type i_char : char_list)
- sorted_mute_list.append(i_char.name);
-
- sorted_mute_list.sort();
-
- for (QString i_name : sorted_mute_list) {
- // mute_map.insert(i_name, false);
- ui_mute_list->addItem(i_name);
- }
-}
-
-void Courtroom::set_pair_list()
-{
- QStringList sorted_pair_list;
-
- for (char_type i_char : char_list)
- sorted_pair_list.append(i_char.name);
-
- sorted_pair_list.sort();
-
- for (QString i_name : sorted_pair_list) {
- ui_pair_list->addItem(i_name);
- }
-}
-
-void Courtroom::set_widgets()
-{
- blip_rate = ao_app->read_blip_rate();
- blank_blip = ao_app->get_blank_blip();
-
- QString filename = "courtroom_design.ini";
-
- pos_size_type f_courtroom =
- ao_app->get_element_dimensions("courtroom", filename);
-
- if (f_courtroom.width < 0 || f_courtroom.height < 0) {
- qDebug() << "W: did not find courtroom width or height in " << filename;
-
- this->resize(714, 668);
- }
- else {
- m_courtroom_width = f_courtroom.width;
- m_courtroom_height = f_courtroom.height;
-
- this->resize(f_courtroom.width, f_courtroom.height);
- }
-
- set_fonts();
-
- ui_background->move(0, 0);
- ui_background->resize(m_courtroom_width, m_courtroom_height);
- ui_background->set_image("courtroombackground.png");
-
- set_size_and_pos(ui_viewport, "viewport");
-
- // If there is a point to it, show all CCCC features.
- // We also do this this soon so that set_size_and_pos can hide them all later,
- // if needed.
- if (ao_app->cccc_ic_support_enabled) {
- ui_pair_button->show();
- ui_pre_non_interrupt->show();
- ui_showname_enable->show();
- ui_ic_chat_name->show();
- ui_ic_chat_name->setEnabled(true);
- }
- else {
- ui_pair_button->hide();
- ui_pre_non_interrupt->hide();
- ui_showname_enable->hide();
- ui_ic_chat_name->hide();
- ui_ic_chat_name->setEnabled(false);
- }
-
- if (ao_app->casing_alerts_enabled) {
- ui_announce_casing->show();
- }
- else {
- ui_announce_casing->hide();
- }
-
- // We also show the non-server-dependent client additions.
- // Once again, if the theme can't display it, set_move_and_pos will catch
- // them.
- ui_settings->show();
- ui_log_limit_label->show();
- ui_log_limit_spinbox->show();
-
- ui_vp_background->move(0, 0);
- ui_vp_background->resize(ui_viewport->width(), ui_viewport->height());
-
- ui_vp_speedlines->move(0, 0);
- ui_vp_speedlines->combo_resize(ui_viewport->width(), ui_viewport->height());
-
- ui_vp_player_char->move(0, 0);
- ui_vp_player_char->combo_resize(ui_viewport->width(), ui_viewport->height());
-
- ui_vp_sideplayer_char->move(0, 0);
- ui_vp_sideplayer_char->combo_resize(ui_viewport->width(),
- ui_viewport->height());
-
- // the AO2 desk element
- ui_vp_desk->move(0, 0);
- ui_vp_desk->resize(ui_viewport->width(), ui_viewport->height());
-
- // the size of the ui_vp_legacy_desk element relies on various factors and is
- // set in set_scene()
-
- double y_modifier = 147.0 / 192.0;
- int final_y = static_cast<int>(y_modifier * ui_viewport->height());
- ui_vp_legacy_desk->move(0, final_y);
- ui_vp_legacy_desk->hide();
-
- ui_vp_evidence_display->move(0, 0);
- ui_vp_evidence_display->resize(ui_viewport->width(), ui_viewport->height());
-
- set_size_and_pos(ui_vp_showname, "showname");
-
- set_size_and_pos(ui_vp_message, "message");
- ui_vp_message->setTextInteractionFlags(Qt::NoTextInteraction);
- ui_vp_message->setStyleSheet("background-color: rgba(0, 0, 0, 0);"
- "color: white");
-
- ui_vp_testimony->move(ui_viewport->x(), ui_viewport->y());
- ui_vp_testimony->combo_resize(ui_viewport->width(), ui_viewport->height());
-
- ui_vp_realization->move(ui_viewport->x(), ui_viewport->y());
- ui_vp_realization->combo_resize(ui_viewport->width(), ui_viewport->height());
-
- ui_vp_wtce->move(ui_viewport->x(), ui_viewport->y());
- ui_vp_wtce->combo_resize(ui_viewport->width(), ui_viewport->height());
-
- ui_vp_objection->move(ui_viewport->x(), ui_viewport->y());
- ui_vp_objection->combo_resize(ui_viewport->width(), ui_viewport->height());
-
- set_size_and_pos(ui_ic_chatlog, "ic_chatlog");
-
- set_size_and_pos(ui_ms_chatlog, "ms_chatlog");
-
- set_size_and_pos(ui_server_chatlog, "server_chatlog");
-
- set_size_and_pos(ui_mute_list, "mute_list");
- ui_mute_list->hide();
-
- set_size_and_pos(ui_pair_list, "pair_list");
- ui_pair_list->hide();
- set_size_and_pos(ui_pair_offset_spinbox, "pair_offset_spinbox");
- ui_pair_offset_spinbox->hide();
- set_size_and_pos(ui_pair_button, "pair_button");
- ui_pair_button->set_image("pair_button.png");
-
- set_size_and_pos(ui_area_list, "music_list");
- ui_area_list->setStyleSheet("background-color: rgba(0, 0, 0, 0);");
-
- ui_music_list->setStyleSheet("background-color: rgba(100, 103, 132, 225);");
-
- ui_music_list->collapseAll();
-
- set_size_and_pos(ui_music_list, "music_list");
-
- if (is_ao2_bg) {
- set_size_and_pos(ui_ic_chat_message, "ao2_ic_chat_message");
- set_size_and_pos(ui_vp_chatbox, "ao2_chatbox");
- set_size_and_pos(ui_ic_chat_name, "ao2_ic_chat_name");
- }
- else {
- set_size_and_pos(ui_ic_chat_message, "ic_chat_message");
- set_size_and_pos(ui_vp_chatbox, "chatbox");
- set_size_and_pos(ui_ic_chat_name, "ic_chat_name");
- }
-
- ui_ic_chat_message->setStyleSheet(
- "QLineEdit{background-color: rgba(100, 100, 100, 255);}");
- ui_ic_chat_name->setStyleSheet(
- "QLineEdit{background-color: rgba(180, 180, 180, 255);}");
-
- ui_vp_chatbox->set_image("chatmed.png");
- ui_vp_chatbox->hide();
-
- ui_muted->resize(ui_ic_chat_message->width(), ui_ic_chat_message->height());
- ui_muted->set_image("muted.png");
-
- set_size_and_pos(ui_ooc_chat_message, "ooc_chat_message");
- ui_ooc_chat_message->setStyleSheet("background-color: rgba(0, 0, 0, 0);");
-
- set_size_and_pos(ui_ooc_chat_name, "ooc_chat_name");
- ui_ooc_chat_name->setStyleSheet("background-color: rgba(0, 0, 0, 0);");
-
- // set_size_and_pos(ui_area_password, "area_password");
- set_size_and_pos(ui_music_search, "music_search");
-
- set_size_and_pos(ui_emotes, "emotes");
-
- set_size_and_pos(ui_emote_left, "emote_left");
- ui_emote_left->set_image("arrow_left.png");
-
- set_size_and_pos(ui_emote_right, "emote_right");
- ui_emote_right->set_image("arrow_right.png");
-
- set_size_and_pos(ui_emote_dropdown, "emote_dropdown");
- set_size_and_pos(ui_pos_dropdown, "pos_dropdown");
-
- set_size_and_pos(ui_defense_bar, "defense_bar");
- ui_defense_bar->set_image("defensebar" + QString::number(defense_bar_state) +
- ".png");
-
- set_size_and_pos(ui_prosecution_bar, "prosecution_bar");
- ui_prosecution_bar->set_image(
- "prosecutionbar" + QString::number(prosecution_bar_state) + ".png");
-
- set_size_and_pos(ui_music_label, "music_label");
- ui_music_label->setText(tr("Music"));
- set_size_and_pos(ui_sfx_label, "sfx_label");
- ui_sfx_label->setText(tr("Sfx"));
- set_size_and_pos(ui_blip_label, "blip_label");
- ui_blip_label->setText(tr("Blips"));
-
- set_size_and_pos(ui_log_limit_label, "log_limit_label");
- ui_log_limit_label->setText(tr("Log limit"));
-
- set_size_and_pos(ui_hold_it, "hold_it");
- ui_hold_it->set_image("holdit.png");
- set_size_and_pos(ui_objection, "objection");
- ui_objection->set_image("objection.png");
- set_size_and_pos(ui_take_that, "take_that");
- ui_take_that->set_image("takethat.png");
-
- set_size_and_pos(ui_ooc_toggle, "ooc_toggle");
- if (ooc_toggle_fallback) {
- ui_ooc_toggle->setText(tr("Server"));
- }
- else {
- ui_ooc_toggle->set_image("ooc_toggle_server.png");
- ui_ooc_toggle->setText(tr(""));
- }
-
- set_size_and_pos(ui_witness_testimony, "witness_testimony");
- ui_witness_testimony->set_image("witnesstestimony.png");
- set_size_and_pos(ui_cross_examination, "cross_examination");
- ui_cross_examination->set_image("crossexamination.png");
-
- set_size_and_pos(ui_guilty, "guilty");
- ui_guilty->set_image("guilty.png");
- set_size_and_pos(ui_not_guilty, "not_guilty");
- ui_not_guilty->set_image("notguilty.png");
-
- set_size_and_pos(ui_change_character, "change_character");
- if (change_char_fallback) {
- ui_change_character->setText(tr("Change character"));
- }
- else {
- ui_change_character->set_image("change_character.png");
- ui_change_character->setText(
- tr("")); // set text to empty otherwise it just sits there
- }
-
- set_size_and_pos(ui_reload_theme, "reload_theme");
- if (reload_theme_fallback) {
- ui_reload_theme->setText(tr("Reload theme"));
- }
- else {
- ui_reload_theme->set_image("reload_theme.png");
- ui_reload_theme->setText(tr(""));
- }
-
- set_size_and_pos(ui_call_mod, "call_mod");
- if (call_mod_fallback) {
- ui_call_mod->setText(tr("Call mod"));
- }
- else {
- ui_call_mod->set_image("call_mod.png");
- ui_call_mod->setText(tr(""));
- }
-
- set_size_and_pos(ui_settings, "settings");
- if (settings_fallback) {
- ui_settings->setText(tr("Settings"));
- }
- else {
- ui_settings->set_image("settings.png");
- ui_settings->setText(tr(""));
- }
-
- set_size_and_pos(ui_announce_casing, "casing_button");
- if (casing_fallback) {
- ui_announce_casing->setText(tr("Casing"));
- }
- else {
- ui_announce_casing->set_image("casing.png");
- ui_announce_casing->setText(tr(""));
- }
-
- set_size_and_pos(ui_switch_area_music, "switch_area_music");
- if (amswap_fallback) {
- ui_switch_area_music->setText(tr("A/M"));
- }
- else {
- ui_switch_area_music->set_image("amswap.png");
- ui_switch_area_music->setText(tr(""));
- }
-
- set_size_and_pos(ui_pre, "pre");
- ui_pre->setText(tr("Preanim"));
-
- set_size_and_pos(ui_pre_non_interrupt, "pre_no_interrupt");
- set_size_and_pos(ui_flip, "flip");
-
- set_size_and_pos(ui_guard, "guard");
-
- set_size_and_pos(ui_casing, "casing");
-
- set_size_and_pos(ui_showname_enable, "showname_enable");
-
- set_size_and_pos(ui_custom_objection, "custom_objection");
- ui_custom_objection->set_image("custom.png");
-
- set_size_and_pos(ui_realization, "realization");
- ui_realization->set_image("realization.png");
-
- set_size_and_pos(ui_screenshake, "screenshake");
- ui_screenshake->set_image("screenshake.png");
-
- set_size_and_pos(ui_mute, "mute_button");
- ui_mute->set_image("mute.png");
-
- set_size_and_pos(ui_defense_plus, "defense_plus");
- ui_defense_plus->set_image("defplus.png");
-
- set_size_and_pos(ui_defense_minus, "defense_minus");
- ui_defense_minus->set_image("defminus.png");
-
- set_size_and_pos(ui_prosecution_plus, "prosecution_plus");
- ui_prosecution_plus->set_image("proplus.png");
-
- set_size_and_pos(ui_prosecution_minus, "prosecution_minus");
- ui_prosecution_minus->set_image("prominus.png");
-
- set_size_and_pos(ui_text_color, "text_color");
-
- set_size_and_pos(ui_music_slider, "music_slider");
- set_size_and_pos(ui_sfx_slider, "sfx_slider");
- set_size_and_pos(ui_blip_slider, "blip_slider");
-
- set_size_and_pos(ui_log_limit_spinbox, "log_limit_spinbox");
-
- set_size_and_pos(ui_evidence_button, "evidence_button");
- ui_evidence_button->set_image("evidencebutton.png");
-
- set_size_and_pos(ui_evidence, "evidence_background");
- ui_evidence->set_image("evidencebackground.png");
-
- set_size_and_pos(ui_evidence_name, "evidence_name");
-
- set_size_and_pos(ui_evidence_buttons, "evidence_buttons");
-
- set_size_and_pos(ui_evidence_left, "evidence_left");
- ui_evidence_left->set_image("arrow_left.png");
-
- set_size_and_pos(ui_evidence_right, "evidence_right");
- ui_evidence_right->set_image("arrow_right.png");
-
- set_size_and_pos(ui_evidence_present, "evidence_present");
- ui_evidence_present->set_image("present_disabled.png");
-
- set_size_and_pos(ui_evidence_overlay, "evidence_overlay");
- ui_evidence_overlay->set_image("evidenceoverlay.png");
-
- set_size_and_pos(ui_evidence_delete, "evidence_delete");
- ui_evidence_delete->set_image("deleteevidence.png");
-
- set_size_and_pos(ui_evidence_image_name, "evidence_image_name");
-
- set_size_and_pos(ui_evidence_image_button, "evidence_image_button");
-
- set_size_and_pos(ui_evidence_x, "evidence_x");
- ui_evidence_x->set_image("evidencex.png");
-
- set_size_and_pos(ui_evidence_description, "evidence_description");
-
- ui_selector->set_image("char_selector.png");
- ui_selector->hide();
-
- set_size_and_pos(ui_back_to_lobby, "back_to_lobby");
- ui_back_to_lobby->setText(tr("Back to Lobby"));
-
- set_size_and_pos(ui_char_password, "char_password");
-
- set_size_and_pos(ui_char_buttons, "char_buttons");
-
- set_size_and_pos(ui_char_select_left, "char_select_left");
- ui_char_select_left->set_image("arrow_left.png");
-
- set_size_and_pos(ui_char_select_right, "char_select_right");
- ui_char_select_right->set_image("arrow_right.png");
-
- set_size_and_pos(ui_spectator, "spectator");
-}
-
-void Courtroom::set_fonts()
-{
- set_font(ui_vp_showname, "showname");
- set_font(ui_vp_message, "message");
- set_font(ui_ic_chatlog, "ic_chatlog");
- set_font(ui_ms_chatlog, "ms_chatlog");
- set_font(ui_server_chatlog, "server_chatlog");
- set_font(ui_music_list, "music_list");
- set_font(ui_area_list, "area_list");
-
- // Set color of labels and checkboxes
- const QString design_file = "courtroom_fonts.ini";
- QColor f_color = ao_app->get_color("label_color", design_file);
- QString color_string = "color: rgba(" + QString::number(f_color.red()) +
- ", " + QString::number(f_color.green()) + ", " +
- QString::number(f_color.blue()) + ", 255); }";
- QString style_sheet_string = "QLabel {" + color_string +
- "}"
- "QCheckBox {" +
- color_string + "}";
- setStyleSheet(style_sheet_string);
-}
-
-void Courtroom::set_font(QWidget *widget, QString p_identifier)
-{
- QString design_file = "courtroom_fonts.ini";
- int f_weight = ao_app->get_font_size(p_identifier, design_file);
- QString class_name = widget->metaObject()->className();
-
- QString fontt = ao_app->get_font_name(p_identifier + "_font", design_file);
- widget->setFont(QFont(fontt, f_weight));
-
- QColor f_color = ao_app->get_color(p_identifier + "_color", design_file);
-
- QString style_sheet_string =
- class_name + " { background-color: rgba(0, 0, 0, 0);\n" + "color: rgba(" +
- QString::number(f_color.red()) + ", " + QString::number(f_color.green()) +
- ", " + QString::number(f_color.blue()) + ", 255); }";
-
- widget->setStyleSheet(style_sheet_string);
-}
-
-void Courtroom::set_window_title(QString p_title)
-{
- this->setWindowTitle(p_title);
-}
-
-void Courtroom::set_size_and_pos(QWidget *p_widget, QString p_identifier)
-{
- QString filename = "courtroom_design.ini";
-
- pos_size_type design_ini_result =
- ao_app->get_element_dimensions(p_identifier, filename);
-
- if (design_ini_result.width < 0 || design_ini_result.height < 0) {
- qDebug() << "W: could not find \"" << p_identifier << "\" in " << filename;
- p_widget->hide();
- }
- else {
- p_widget->move(design_ini_result.x, design_ini_result.y);
- p_widget->resize(design_ini_result.width, design_ini_result.height);
- }
-}
-
-QPoint Courtroom::get_theme_pos(QString p_identifier)
-{
- QString filename = "courtroom_design.ini";
-
- pos_size_type design_ini_result =
- ao_app->get_element_dimensions(p_identifier, filename);
-
- if (design_ini_result.width < 0 || design_ini_result.height < 0) {
- qDebug() << "W: could not find \"" << p_identifier << "\" in " << filename;
- return QPoint(0, 0);
- }
- else {
- return QPoint(design_ini_result.x, design_ini_result.y);
- }
-}
-
-void Courtroom::set_taken(int n_char, bool p_taken)
-{
- if (n_char >= char_list.size()) {
- qDebug()
- << "W: set_taken attempted to set an index bigger than char_list size";
- return;
- }
-
- char_type f_char;
- f_char.name = char_list.at(n_char).name;
- f_char.description = char_list.at(n_char).description;
- f_char.taken = p_taken;
- f_char.evidence_string = char_list.at(n_char).evidence_string;
-
- char_list.replace(n_char, f_char);
-}
-
-void Courtroom::done_received()
-{
- m_cid = -1;
-
- music_player->set_volume(0);
- sfx_player->set_volume(0);
- objection_player->set_volume(0);
- blip_player->set_volume(0);
-
- set_char_select_page();
-
- set_mute_list();
- set_pair_list();
-
- set_char_select();
-
- show();
-
- ui_spectator->show();
-}
-
-void Courtroom::set_background(QString p_background)
-{
- ui_vp_testimony->stop();
-
- current_background = p_background;
-
- is_ao2_bg = file_exists(ao_app->get_background_path("defensedesk.png")) &&
- file_exists(ao_app->get_background_path("prosecutiondesk.png")) &&
- file_exists(ao_app->get_background_path("stand.png"));
-
- if (is_ao2_bg) {
- set_size_and_pos(ui_vp_chatbox, "ao2_chatbox");
- set_size_and_pos(ui_ic_chat_message, "ao2_ic_chat_message");
- }
- else {
- set_size_and_pos(ui_vp_chatbox, "chatbox");
- set_size_and_pos(ui_ic_chat_message, "ic_chat_message");
- }
-}
-
-void Courtroom::set_character(int char_id)
-{
- m_cid = char_id;
-
- QString f_char;
-
- if (m_cid == -1) {
- if (ao_app->is_discord_enabled())
- ao_app->discord->state_spectate();
- f_char = "";
- }
- else {
- f_char = ao_app->get_char_name(char_list.at(m_cid).name);
-
- if (ao_app->is_discord_enabled())
- ao_app->discord->state_character(f_char.toStdString());
- }
-
- current_char = f_char;
-
- current_emote_page = 0;
- current_emote = 0;
-
- if (m_cid == -1)
- ui_emotes->hide();
- else
- ui_emotes->show();
-
- set_emote_page();
- set_emote_dropdown();
-
- if (ao_app->custom_objection_enabled &&
- (file_exists(ao_app->get_character_path(current_char, "custom.gif")) ||
- file_exists(ao_app->get_character_path(current_char, "custom.apng"))) &&
- file_exists(ao_app->get_character_path(current_char, "custom.wav")))
- ui_custom_objection->show();
- else
- ui_custom_objection->hide();
-}
-
-void Courtroom::enter_courtroom(int p_cid)
-{
- this->set_character(p_cid);
- current_evidence_page = 0;
- current_evidence = 0;
-
- set_evidence_page();
-
- QString side = ao_app->get_char_side(current_char);
-
- // We block signals from ui_pos_dropdown to stop on_pos_dropdown_changed from
- // firing here. Per the Qt docs, QSignalBlocker only affects the rest of this
- // function, so it doesn't stop the dropdown from working once we finish here.
- const QSignalBlocker blocker(ui_pos_dropdown);
- ui_pos_dropdown->setCurrentText(side);
-
- if (side == "jud") {
-
- ui_witness_testimony->show();
- ui_cross_examination->show();
- ui_not_guilty->show();
- ui_guilty->show();
- ui_defense_minus->show();
- ui_defense_plus->show();
- ui_prosecution_minus->show();
- ui_prosecution_plus->show();
- }
- else {
- ui_witness_testimony->hide();
- ui_cross_examination->hide();
- ui_guilty->hide();
- ui_not_guilty->hide();
- ui_defense_minus->hide();
- ui_defense_plus->hide();
- ui_prosecution_minus->hide();
- ui_prosecution_plus->hide();
- }
-
- if (ao_app->custom_objection_enabled && // if setting is enabled
- (file_exists(ao_app->get_image_suffix(
- ao_app->get_character_path(current_char, "custom"))) &&
- file_exists(ao_app->get_character_path(current_char, "custom.wav")))) {
- ui_custom_objection->show();
- if (dir_exists(
- ao_app->get_character_path(current_char, "custom_objections"))) {
- custom_obj_menu->clear();
- QDir directory(
- ao_app->get_character_path(current_char, "custom_objections"));
- QStringList custom_obj = directory.entryList(QStringList() << "*.gif"
- << "*.apng",
- QDir::Files);
- for (const QString &filename : custom_obj) {
- custom_obj_menu->addAction(filename);
- }
- }
- }
- else
- ui_custom_objection->hide();
-
- if (ao_app->flipping_enabled)
- ui_flip->show();
- else
- ui_flip->hide();
-
- if (ao_app->casing_alerts_enabled)
- ui_casing->show();
- else
- ui_casing->hide();
-
- list_music();
- list_areas();
-
- music_player->set_volume(ui_music_slider->value());
- sfx_player->set_volume(ui_sfx_slider->value());
- objection_player->set_volume(ui_sfx_slider->value());
- misc_sfx_player->set_volume(ui_sfx_slider->value());
- frame_emote_sfx_player->set_volume(ui_sfx_slider->value());
- pair_frame_emote_sfx_player->set_volume(ui_sfx_slider->value());
- blip_player->set_volume(ui_blip_slider->value());
-
- misc_sfx_player->set_volume(ui_sfx_slider->value());
- frame_emote_sfx_player->set_volume(ui_sfx_slider->value());
- pair_frame_emote_sfx_player->set_volume(ui_sfx_slider->value());
-
- ui_vp_testimony->stop();
-
- set_widgets();
-
- // ui_server_chatlog->setHtml(ui_server_chatlog->toHtml());
-
- ui_char_select_background->hide();
-
- ui_ic_chat_message->setEnabled(m_cid != -1);
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::list_music()
-{
- ui_music_list->clear();
-
- QString f_file = "courtroom_design.ini";
-
- QBrush found_brush(ao_app->get_color("found_song_color", f_file));
- QBrush missing_brush(ao_app->get_color("missing_song_color", f_file));
-
- int n_listed_songs = 0;
-
- QTreeWidgetItem *parent = nullptr;
- for (int n_song = 0; n_song < music_list.size(); ++n_song) {
- QString i_song = music_list.at(n_song);
- QString i_song_listname = i_song.left(i_song.lastIndexOf("."));
- i_song_listname = i_song_listname.right(
- i_song_listname.length() - (i_song_listname.lastIndexOf("/") + 1));
-
- QTreeWidgetItem *treeItem;
- if (i_song_listname != i_song && parent != nullptr &&
- i_song.toLower().contains(
- ui_music_search->text().toLower())) // not a category, parent exists
- {
- treeItem = new QTreeWidgetItem(parent);
- treeItem->setText(0, i_song_listname);
- treeItem->setText(1, i_song);
-
- QString song_path = ao_app->get_music_path(i_song);
-
- if (file_exists(song_path))
- treeItem->setBackground(0, found_brush);
- else
- treeItem->setBackground(0, missing_brush);
-
- if (i_song_listname ==
- i_song) // Not supposed to be a song to begin with - a category?
- parent = treeItem;
- ++n_listed_songs;
- }
- else if (i_song_listname == i_song) {
- treeItem = new QTreeWidgetItem(ui_music_list);
- treeItem->setText(0, i_song_listname);
- treeItem->setText(1, i_song);
-
- QString song_path = ao_app->get_music_path(i_song);
-
- if (file_exists(song_path))
- treeItem->setBackground(0, found_brush);
- else
- treeItem->setBackground(0, missing_brush);
-
- if (i_song_listname ==
- i_song) // Not supposed to be a song to begin with - a category?
- parent = treeItem;
- ++n_listed_songs;
- }
- }
- ui_music_list->expandAll(); // Needs to somehow remember which categories were
- // expanded/collapsed if the music list didn't
- // change since last time
-}
-
-void Courtroom::list_areas()
-{
- ui_area_list->clear();
- area_row_to_number.clear();
-
- QString f_file = "courtroom_design.ini";
-
- QBrush free_brush(ao_app->get_color("area_free_color", f_file));
- QBrush lfp_brush(ao_app->get_color("area_lfp_color", f_file));
- QBrush casing_brush(ao_app->get_color("area_casing_color", f_file));
- QBrush recess_brush(ao_app->get_color("area_recess_color", f_file));
- QBrush rp_brush(ao_app->get_color("area_rp_color", f_file));
- QBrush gaming_brush(ao_app->get_color("area_gaming_color", f_file));
- QBrush locked_brush(ao_app->get_color("area_locked_color", f_file));
-
- int n_listed_areas = 0;
-
- for (int n_area = 0; n_area < area_list.size(); ++n_area) {
- QString i_area = "";
-
- // i_area.append("[");
- // i_area.append(QString::number(n_area));
- // i_area.append("] ");
-
- i_area.append(area_list.at(n_area));
-
- if (ao_app->arup_enabled) {
- i_area.append("\n ");
-
- i_area.append(arup_statuses.at(n_area));
- i_area.append(" | CM: ");
- i_area.append(arup_cms.at(n_area));
-
- i_area.append("\n ");
-
- i_area.append(QString::number(arup_players.at(n_area)));
- i_area.append(" users | ");
-
- i_area.append(arup_locks.at(n_area));
- }
-
- if (i_area.toLower().contains(ui_music_search->text().toLower())) {
- ui_area_list->addItem(i_area);
- area_row_to_number.append(n_area);
-
- if (ao_app->arup_enabled) {
- // Colouring logic here.
- ui_area_list->item(n_listed_areas)->setBackground(free_brush);
- if (arup_locks.at(n_area) == "LOCKED") {
- ui_area_list->item(n_listed_areas)->setBackground(locked_brush);
- }
- else {
- if (arup_statuses.at(n_area) == "LOOKING-FOR-PLAYERS")
- ui_area_list->item(n_listed_areas)->setBackground(lfp_brush);
- else if (arup_statuses.at(n_area) == "CASING")
- ui_area_list->item(n_listed_areas)->setBackground(casing_brush);
- else if (arup_statuses.at(n_area) == "RECESS")
- ui_area_list->item(n_listed_areas)->setBackground(recess_brush);
- else if (arup_statuses.at(n_area) == "RP")
- ui_area_list->item(n_listed_areas)->setBackground(rp_brush);
- else if (arup_statuses.at(n_area) == "GAMING")
- ui_area_list->item(n_listed_areas)->setBackground(gaming_brush);
- }
- }
- else {
- ui_area_list->item(n_listed_areas)->setBackground(free_brush);
- }
-
- ++n_listed_areas;
- }
- }
-}
-
-void Courtroom::append_ms_chatmessage(QString f_name, QString f_message)
-{
- ui_ms_chatlog->append_chatmessage(
- f_name, f_message,
- ao_app->get_color("ooc_default_color", "courtroom_design.ini").name(),
- false);
-}
-
-void Courtroom::append_server_chatmessage(QString p_name, QString p_message,
- QString p_colour)
-{
- QString colour = "#000000";
-
- if (p_colour == "0")
- colour =
- ao_app->get_color("ooc_default_color", "courtroom_design.ini").name();
- if (p_colour == "1")
-
- colour =
- ao_app->get_color("ooc_server_color", "courtroom_design.ini").name();
- if (p_message == "Logged in as a moderator.") {
- ui_guard->show();
- append_server_chatmessage(
- "CLIENT", tr("You were granted the Disable Modcalls button."), "1");
- }
-
- ui_server_chatlog->append_chatmessage(p_name, p_message, colour, false);
-}
-
-void Courtroom::detect_fallback_text()
-{
- QString change_char_path = ao_app->get_theme_path("change_character.png");
- QString reload_theme_path = ao_app->get_theme_path("reload_theme.png");
- QString settings_path = ao_app->get_theme_path("settings.png");
- QString call_mod_path = ao_app->get_theme_path("call_mod.png");
- QString casing_path = ao_app->get_theme_path("casing.png");
- QString amswap_path = ao_app->get_theme_path("amswap.png");
- QString ooc_toggle_path = ao_app->get_theme_path("ooc_toggle_ms.png");
-
- if (file_exists(change_char_path)) {
- change_char_fallback = false;
- }
- else {
- change_char_fallback = true;
- }
- if (file_exists(reload_theme_path)) {
- reload_theme_fallback = false;
- }
- else {
- reload_theme_fallback = true;
- }
- if (file_exists(settings_path)) {
- settings_fallback = false;
- }
- else {
- settings_fallback = true;
- }
- if (file_exists(call_mod_path)) {
- call_mod_fallback = false;
- }
- else {
- call_mod_fallback = true;
- }
- if (file_exists(casing_path)) {
- casing_fallback = false;
- }
- else {
- casing_fallback = true;
- }
- if (file_exists(amswap_path)) {
- amswap_fallback = false;
- }
- else {
- amswap_fallback = true;
- }
- if (file_exists(ooc_toggle_path)) {
- ooc_toggle_fallback = false;
- }
- else {
- ooc_toggle_fallback = true;
- }
-}
-
-class AOFrameThreadingPre : public QRunnable {
-public:
- Courtroom *thisCourtroom;
- int my_frameNumber;
- AOFrameThreadingPre(Courtroom *my_courtroom, int frameNumber)
- {
- thisCourtroom = my_courtroom;
- my_frameNumber = frameNumber;
- }
- void run()
- {
- qDebug() << my_frameNumber << " FRAME NUMBER"
- << " from" << QThread::currentThread();
- QString sfx_to_play = thisCourtroom->ao_app->get_frame_sfx_name(
- thisCourtroom->current_char,
- thisCourtroom->ao_app->get_pre_emote(thisCourtroom->current_char,
- thisCourtroom->current_emote),
- my_frameNumber);
- QString screenshake_to_play = thisCourtroom->ao_app->get_screenshake_frame(
- thisCourtroom->current_char,
- thisCourtroom->ao_app->get_pre_emote(thisCourtroom->current_char,
- thisCourtroom->current_emote),
- my_frameNumber);
- QString realization_to_play = thisCourtroom->ao_app->get_realization_frame(
- thisCourtroom->current_char,
- thisCourtroom->ao_app->get_pre_emote(thisCourtroom->current_char,
- thisCourtroom->current_emote),
- my_frameNumber);
- if (sfx_to_play != "") {
- thisCourtroom->threading_sfx +=
- "|" + QString::number(my_frameNumber) + "=" + sfx_to_play;
- }
- if (screenshake_to_play != "") {
- thisCourtroom->threading_shake +=
- "|" + QString::number(my_frameNumber) + "=" + screenshake_to_play;
- }
- if (realization_to_play != "") {
- thisCourtroom->threading_flash +=
- "|" + QString::number(my_frameNumber) + "=" + realization_to_play;
- }
- }
-};
-
-class AOFrameThreading : public QRunnable {
-public:
- Courtroom *thisCourtroom;
- int my_frameNumber;
- AOFrameThreading(Courtroom *my_courtroom, int frameNumber)
- {
- thisCourtroom = my_courtroom;
- my_frameNumber = frameNumber;
- }
- void run()
- {
- QString sfx_to_play = thisCourtroom->ao_app->get_frame_sfx_name(
- thisCourtroom->current_char,
- thisCourtroom->threading_prefix +
- thisCourtroom->ao_app->get_emote(thisCourtroom->current_char,
- thisCourtroom->current_emote),
- my_frameNumber);
- QString screenshake_to_play = thisCourtroom->ao_app->get_screenshake_frame(
- thisCourtroom->current_char,
- thisCourtroom->threading_prefix +
- thisCourtroom->ao_app->get_emote(thisCourtroom->current_char,
- thisCourtroom->current_emote),
- my_frameNumber);
- QString realization_to_play = thisCourtroom->ao_app->get_realization_frame(
- thisCourtroom->current_char,
- thisCourtroom->threading_prefix +
- thisCourtroom->ao_app->get_emote(thisCourtroom->current_char,
- thisCourtroom->current_emote),
- my_frameNumber);
- if (sfx_to_play != "") {
- thisCourtroom->threading_sfx +=
- "|" + QString::number(my_frameNumber) + "=" + sfx_to_play;
- }
- if (screenshake_to_play != "") {
- thisCourtroom->threading_shake +=
- "|" + QString::number(my_frameNumber) + "=" + screenshake_to_play;
- }
- if (realization_to_play != "") {
- thisCourtroom->threading_flash +=
- "|" + QString::number(my_frameNumber) + "=" + realization_to_play;
- }
- }
-};
-
-void Courtroom::on_chat_return_pressed()
-{
- if (ui_ic_chat_message->text() == "" || is_muted)
- return;
-
- if ((anim_state < 3 || text_state < 2) && objection_state == 0)
- return;
-
- // MS#
- // deskmod#
- // pre-emote#
- // character#
- // emote#
- // message#
- // side#
- // sfx-name#
- // emote_modifier#
- // char_id#
- // sfx_delay#
- // objection_modifier#
- // evidence#
- // placeholder#
- // realization#
- // text_color#%
-
- // Additionally, in our case:
-
- // showname#
- // other_charid#
- // self_offset#
- // noninterrupting_preanim#%
-
- QStringList packet_contents;
-
- QString f_side = ao_app->get_char_side(current_char);
-
- QString f_desk_mod = "chat";
-
- if (ao_app->desk_mod_enabled) {
- f_desk_mod =
- QString::number(ao_app->get_desk_mod(current_char, current_emote));
- if (f_desk_mod == "-1")
- f_desk_mod = "chat";
- }
-
- packet_contents.append(f_desk_mod);
-
- packet_contents.append(ao_app->get_pre_emote(current_char, current_emote));
-
- packet_contents.append(current_char);
-
- packet_contents.append(ao_app->get_emote(current_char, current_emote));
-
- packet_contents.append(ui_ic_chat_message->text());
-
- packet_contents.append(f_side);
-
- packet_contents.append(ao_app->get_sfx_name(current_char, current_emote));
-
- int f_emote_mod = ao_app->get_emote_mod(current_char, current_emote);
-
- // needed or else legacy won't understand what we're saying
- if (objection_state > 0) {
- if (ui_pre->isChecked()) {
- if (f_emote_mod == 5 || f_emote_mod == 4)
- f_emote_mod = 6;
- else
- f_emote_mod = 2;
- }
- }
- else if (ui_pre->isChecked() && !ui_pre_non_interrupt->isChecked()) {
- if (f_emote_mod == 0)
- f_emote_mod = 1;
- else if (f_emote_mod == 5 && ao_app->prezoom_enabled)
- f_emote_mod = 4;
- }
- else {
- if (f_emote_mod == 1)
- f_emote_mod = 0;
- else if (f_emote_mod == 4)
- f_emote_mod = 5;
- }
-
- packet_contents.append(QString::number(f_emote_mod));
- packet_contents.append(QString::number(m_cid));
-
- packet_contents.append(
- QString::number(ao_app->get_sfx_delay(current_char, current_emote)));
-
- QString f_obj_state;
-
- if ((objection_state == 4 && !ao_app->custom_objection_enabled) ||
- (objection_state < 0))
- f_obj_state = "0";
- else if (objection_custom != "" && objection_state == 4) {
- f_obj_state = QString::number(objection_state) + "&" +
- objection_custom; // we add the name of the objection so the
- // packet is like: 4&(name of custom obj)
- }
- else
- f_obj_state = QString::number(objection_state);
- packet_contents.append(f_obj_state);
- if (is_presenting_evidence)
- // the evidence index is shifted by 1 because 0 is no evidence per legacy
- // standards besides, older clients crash if we pass -1
- packet_contents.append(QString::number(current_evidence + 1));
- else
- packet_contents.append("0");
-
- QString f_flip;
-
- if (ao_app->flipping_enabled) {
- if (ui_flip->isChecked())
- f_flip = "1";
- else
- f_flip = "0";
- }
- else
- f_flip = QString::number(m_cid);
-
- packet_contents.append(f_flip);
-
- packet_contents.append(QString::number(realization_state));
-
- QString f_text_color;
-
- if (text_color < 0)
- f_text_color = "0";
- else if (text_color > 8)
- f_text_color = "0";
- else
- f_text_color = QString::number(text_color);
-
- packet_contents.append(f_text_color);
-
- // If the server we're on supports CCCC stuff, we should use it!
- if (ao_app->cccc_ic_support_enabled) {
- // If there is a showname entered, use that -- else, just send an empty
- // packet-part.
- if (!ui_ic_chat_name->text().isEmpty()) {
- packet_contents.append(ui_ic_chat_name->text());
- }
- else {
- packet_contents.append("");
- }
-
- // Similarly, we send over whom we're paired with, unless we have chosen
- // ourselves. Or a charid of -1 or lower, through some means.
- if (other_charid > -1 && other_charid != m_cid) {
- packet_contents.append(QString::number(other_charid));
- packet_contents.append(QString::number(offset_with_pair));
- }
- else {
- packet_contents.append("-1");
- packet_contents.append("0");
- }
-
- // Finally, we send over if we want our pres to not interrupt.
- if (ui_pre_non_interrupt->isChecked() && ui_pre->isChecked()) {
- packet_contents.append("1");
- }
- else {
- packet_contents.append("0");
- }
- }
- // If the server we're on supports Looping SFX and Screenshake, use it if the
- // emote uses it.
- if (ao_app->looping_sfx_support_enabled) {
- packet_contents.append(
- ao_app->get_sfx_looping(current_char, current_emote));
- qDebug() << "Are we looping this? "
- << ao_app->get_sfx_looping(current_char, current_emote);
- packet_contents.append(QString::number(screenshake_state));
- qDebug() << "Are we screen shaking this one? " << screenshake_state;
- qDebug() << "MAX THREAD COUNT "
- << QThreadPool::globalInstance()->maxThreadCount();
- QString frame_screenshake = "";
- QString frame_realization = "";
- QString frame_sfx = "";
-
- QString preemote_sfx = "";
- QString preemote_shake = "";
- QString preemote_flash = "";
-
- QString talkemote_sfx = "";
- QString talkemote_shake = "";
- QString talkemote_flash = "";
-
- QString idleemote_sfx = "";
- QString idleemote_shake = "";
- QString idleemote_flash = "";
-
- QString preemote = ao_app->get_image_suffix(ao_app->get_character_path(
- current_char, ao_app->get_pre_emote(current_char, current_emote)));
- QString talkemote_to_check =
- ao_app->get_image_suffix(ao_app->get_character_path(
- current_char,
- "(b)" + ao_app->get_emote(current_char, current_emote)));
- QString idleemote_to_check =
- ao_app->get_image_suffix(ao_app->get_character_path(
- current_char,
- "(a)" + ao_app->get_emote(current_char, current_emote)));
-
- frame_emote_checker = new QMovie(this);
- frame_emote_checker->setFileName(preemote);
- frame_emote_checker->jumpToFrame(0);
- qDebug() << "Premote: " << frame_emote_checker->frameCount();
-
- preemote_sfx += ao_app->get_pre_emote(current_char, current_emote);
- preemote_shake += ao_app->get_pre_emote(current_char, current_emote);
- preemote_flash += ao_app->get_pre_emote(current_char, current_emote);
-
- threading_sfx = preemote_sfx;
- threading_shake = preemote_shake;
- threading_flash = preemote_flash;
-
- for (int i = 0; i < frame_emote_checker->frameCount(); i++) {
- AOFrameThreadingPre *frame_thread = new AOFrameThreadingPre(this, i);
- QThreadPool::globalInstance()->start(frame_thread);
- frame_thread->setAutoDelete(true);
- }
- QThreadPool::globalInstance()->waitForDone();
- preemote_sfx = threading_sfx;
- preemote_shake = threading_shake;
- preemote_flash = threading_flash;
- preemote_sfx += "^";
- preemote_shake += "^";
- preemote_flash += "^";
- delete frame_emote_checker;
-
- talkemote_sfx += "(b)" + ao_app->get_emote(current_char, current_emote);
- talkemote_shake += "(b)" + ao_app->get_emote(current_char, current_emote);
- talkemote_flash += "(b)" + ao_app->get_emote(current_char, current_emote);
-
- frame_emote_checker = new QMovie(this);
- frame_emote_checker->setFileName(talkemote_to_check);
- frame_emote_checker->jumpToFrame(0);
- qDebug() << "Talk: " << frame_emote_checker->frameCount();
-
- threading_sfx = talkemote_sfx;
- threading_shake = talkemote_shake;
- threading_flash = talkemote_flash;
- threading_prefix = QString("(b)");
-
- for (int i = 0; i < frame_emote_checker->frameCount(); i++) {
- AOFrameThreading *frame_thread = new AOFrameThreading(this, i);
- QThreadPool::globalInstance()->start(frame_thread);
- frame_thread->setAutoDelete(true);
- }
- QThreadPool::globalInstance()->waitForDone();
-
- talkemote_sfx = threading_sfx;
- talkemote_shake = threading_shake;
- talkemote_flash = threading_flash;
- talkemote_sfx += "^";
- talkemote_shake += "^";
- talkemote_flash += "^";
- delete frame_emote_checker;
-
- idleemote_sfx += "(a)" + ao_app->get_emote(current_char, current_emote);
- idleemote_shake += "(a)" + ao_app->get_emote(current_char, current_emote);
- idleemote_flash += "(a)" + ao_app->get_emote(current_char, current_emote);
-
- frame_emote_checker = new QMovie(this);
- frame_emote_checker->setFileName(idleemote_to_check);
- frame_emote_checker->jumpToFrame(0);
- qDebug() << "idle: " << frame_emote_checker->frameCount();
-
- threading_sfx = idleemote_sfx;
- threading_shake = idleemote_shake;
- threading_flash = idleemote_flash;
- threading_prefix = QString("(a)");
- for (int i = 0; i < frame_emote_checker->frameCount(); i++) {
- AOFrameThreading *frame_thread = new AOFrameThreading(this, i);
- QThreadPool::globalInstance()->start(frame_thread);
- frame_thread->setAutoDelete(true);
- }
- QThreadPool::globalInstance()->waitForDone();
- idleemote_sfx = threading_sfx;
- idleemote_shake = threading_shake;
- idleemote_flash = threading_flash;
- delete frame_emote_checker;
-
- frame_screenshake += preemote_shake;
- frame_screenshake += talkemote_shake;
- frame_screenshake += idleemote_shake;
-
- frame_realization += preemote_flash;
- frame_realization += talkemote_flash;
- frame_realization += idleemote_flash;
-
- frame_sfx += preemote_sfx;
- frame_sfx += talkemote_sfx;
- frame_sfx += idleemote_sfx;
-
- packet_contents.append(frame_screenshake);
- packet_contents.append(frame_realization);
- packet_contents.append(frame_sfx);
- } // Honestly this is a copy paste dump and I have no idea what this does. If
- // this breaks blame aov thanks
- ao_app->send_server_packet(new AOPacket("MS", packet_contents));
-}
-void Courtroom::handle_chatmessage(QStringList *p_contents)
-{
- // Instead of checking for whether a message has at least chatmessage_size
- // amount of packages, we'll check if it has at least 15.
- // That was the original chatmessage_size.
- if (p_contents->size() < 15)
- return;
-
- for (int n_string = 0; n_string < chatmessage_size; ++n_string) {
- // m_chatmessage[n_string] = p_contents->at(n_string);
-
- // Note that we have added stuff that vanilla clients and servers simply
- // won't send. So now, we have to check if the thing we want even exists
- // amongst the packet's content. We also have to check if the server even
- // supports CCCC's IC features, or if it's just japing us. Also, don't
- // forget! A size 15 message will have indices from 0 to 14.
- if (n_string < p_contents->size() &&
- (n_string < 15 || ao_app->cccc_ic_support_enabled)) {
- m_chatmessage[n_string] = p_contents->at(n_string);
- }
- else {
- m_chatmessage[n_string] = "";
- }
- }
-
- int f_char_id = m_chatmessage[CHAR_ID].toInt();
-
- if (f_char_id < 0 || f_char_id >= char_list.size())
- return;
-
- if (mute_map.value(m_chatmessage[CHAR_ID].toInt()))
- return;
-
- QString f_showname;
- if (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked()) {
- f_showname = ao_app->get_showname(char_list.at(f_char_id).name);
- }
- else {
- f_showname = m_chatmessage[SHOWNAME];
- }
-
- QString f_message = f_showname + ": " + m_chatmessage[MESSAGE] + '\n';
-
- if (f_message == previous_ic_message)
- return;
-
- text_state = 0;
- anim_state = 0;
- ui_vp_objection->stop();
- // ui_vp_player_char->stop();
- chat_tick_timer->stop();
- if (!keep_evidence_display)
- ui_vp_evidence_display->reset();
-
- chatmessage_is_empty =
- m_chatmessage[MESSAGE] == " " || m_chatmessage[MESSAGE] == "";
- if (m_chatmessage[MESSAGE] == ui_ic_chat_message->text() &&
- m_chatmessage[CHAR_ID].toInt() == m_cid) {
- ui_ic_chat_message->clear();
- objection_state = 0;
- objection_custom = "";
- char_name = m_chatmessage[CHAR_NAME];
- realization_state = 0;
- screenshake_state = 0;
- is_presenting_evidence = false;
- ui_pre->setChecked(false);
- ui_hold_it->set_image("holdit.png");
- ui_objection->set_image("objection.png");
- ui_take_that->set_image("takethat.png");
- ui_custom_objection->set_image("custom.png");
- ui_realization->set_image("realization.png");
- ui_screenshake->set_image("screenshake.png");
- ui_evidence_present->set_image("present_disabled.png");
- ui_screenshake->set_image("screenshake.png");
- }
-
- QString tmpmsg = "";
- chatlogpiece *temp = new chatlogpiece(
- ao_app->get_showname(char_list.at(f_char_id).name), f_showname,
- ": " + m_chatmessage[MESSAGE], false, m_chatmessage[TEXT_COLOR].toInt());
-
- ic_chatlog_history.append(*temp);
-
- while (ic_chatlog_history.size() > log_maximum_blocks &&
- log_maximum_blocks > 0) {
- ic_chatlog_history.removeFirst();
- }
- refresh_iclog(true);
-
- if (f_showname == "")
- f_showname = m_chatmessage[CHAR_NAME];
- if (!mirror_iclog)
- append_ic_text(": " + m_chatmessage[MESSAGE], f_showname, false, true,
- false, m_chatmessage[TEXT_COLOR].toInt());
-
- previous_ic_message = f_message;
- bool ok;
- int objection_mod = m_chatmessage[OBJECTION_MOD].toInt(
- &ok, 10); // checks if its a custom obj.
- QString custom_objection = "";
- if (!ok && m_chatmessage[OBJECTION_MOD].contains("4&")) {
- objection_mod = 4;
- custom_objection = m_chatmessage[OBJECTION_MOD].split(
- "4&")[1]; // takes the name of custom objection.
- }
- QString f_char = char_name;
- f_char = m_chatmessage[CHAR_NAME];
- QString f_custom_theme = ao_app->get_char_shouts(f_char);
- ui_vp_message->clear();
- ui_vp_chatbox->hide();
- // if an objection is used
- if (objection_mod <= 4 && objection_mod >= 1) {
-
- switch (objection_mod) {
- case 1:
- ui_vp_objection->play("holdit", f_char, f_custom_theme, shout_stay_time);
- objection_player->play("holdit.wav", f_char, f_custom_theme);
- break;
- case 2:
- ui_vp_objection->play("objection", f_char, f_custom_theme,
- shout_stay_time);
- objection_player->play("objection.wav", f_char, f_custom_theme);
- if (ao_app->get_objectmusic())
- music_player->kill_loop();
- break;
- case 3:
- ui_vp_objection->play("takethat", f_char, f_custom_theme,
- shout_stay_time);
- objection_player->play("takethat.wav", f_char, f_custom_theme);
- break;
- // case 4 is AO2 only
- case 4:
- if (custom_objection != "") {
- ui_vp_objection->play("custom_objections/" + custom_objection, f_char,
- f_custom_theme, shout_stay_time);
- objection_player->play("custom_objections/" +
- custom_objection.split('.')[0] + ".wav",
- f_char, f_custom_theme);
- }
- else {
- ui_vp_objection->play("custom", f_char, f_custom_theme,
- shout_stay_time);
- objection_player->play("custom.wav", f_char, f_custom_theme);
- }
- break;
- default:
- qDebug() << "W: Logic error in objection switch statement!";
- }
-
- int emote_mod = m_chatmessage[EMOTE_MOD].toInt();
-
- if (emote_mod == 0)
- m_chatmessage[EMOTE_MOD] = 1;
- }
- else {
- handle_chatmessage_2();
- }
-}
-
-void Courtroom::objection_done() { handle_chatmessage_2(); }
-
-void Courtroom::handle_chatmessage_2()
-{
- ui_vp_speedlines->stop();
- // ui_vp_player_char->stop();
- ui_vp_player_char->frame_sfx_hellstring = m_chatmessage[FRAME_SFX];
- ui_vp_player_char->frame_realization_hellstring =
- m_chatmessage[FRAME_REALIZATION];
- ui_vp_player_char->frame_screenshake_hellstring =
- m_chatmessage[FRAME_SCREENSHAKE];
- ui_vp_player_char->use_networked_framehell = true;
- if (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked()) {
- QString real_name = char_list.at(m_chatmessage[CHAR_ID].toInt()).name;
-
- QString f_showname = ao_app->get_showname(m_chatmessage[CHAR_NAME]);
-
- ui_vp_showname->setText(f_showname);
- }
-
- else {
- ui_vp_showname->setText(m_chatmessage[SHOWNAME]);
- }
-
- QString f_char = m_chatmessage[CHAR_NAME];
- QString chatbox = ao_app->get_chat(f_char);
-
- if (chatbox == "") {
- ui_vp_chatbox->set_image("chatmed.png");
- }
- else {
- QString chatbox_path;
- QString misc_path =
- ao_app->get_base_path() + "misc/" + chatbox + "/chatbox.png";
- // support for 2.4 legacy chatboxes
- QString legacy_path = ao_app->get_base_path() + "misc/" + chatbox + ".png";
- if (file_exists(misc_path)) {
- chatbox_path = misc_path;
- }
- else if (file_exists(legacy_path))
- chatbox_path = legacy_path;
- else {
- QString default_chatbox_path = ao_app->get_theme_path("chatmed.png");
- chatbox_path = default_chatbox_path;
- }
- ui_vp_chatbox->set_image_from_path(chatbox_path);
- }
-
- ui_vp_showname->setStyleSheet(
- "QLabel { color : " + get_text_color("_showname").name() + "; }");
-
- set_scene();
- set_text_color();
-
- // Check if the message needs to be centered.
- QString f_message = m_chatmessage[MESSAGE];
- if (f_message.size() >= 2) {
- if (f_message.startsWith("~~")) {
- message_is_centered = true;
- }
- else {
- message_is_centered = false;
- }
- }
- else {
- ui_vp_message->setAlignment(Qt::AlignLeft);
- }
-
- int emote_mod = m_chatmessage[EMOTE_MOD].toInt();
-
- if (ao_app->flipping_enabled && m_chatmessage[FLIP].toInt() == 1)
- ui_vp_player_char->set_flipped(true);
- else
- ui_vp_player_char->set_flipped(false);
-
- QString side = m_chatmessage[SIDE];
- if (side != "wit")
- ui_vp_testimony->stop();
-
- // Making the second character appear.
- if (m_chatmessage[OTHER_CHARID].isEmpty()) {
- // If there is no second character, hide 'em, and center the first.
- ui_vp_sideplayer_char->hide();
- ui_vp_sideplayer_char->move(0, 0);
-
- ui_vp_player_char->move(0, 0);
- }
- else {
- bool ok;
- int got_other_charid = m_chatmessage[OTHER_CHARID].toInt(&ok);
- if (ok) {
- if (got_other_charid > -1) {
- // If there is, show them!
- ui_vp_sideplayer_char->show();
-
- // Depending on where we are, we offset the characters, and reorder
- // their stacking.
- if (side == "def") {
-
- // We also move the character down depending on how far the are to the
- // right.
- int hor_offset = m_chatmessage[SELF_OFFSET].toInt();
- int vert_offset = 0;
- if (hor_offset > 0) {
- vert_offset = hor_offset / 10;
- }
- ui_vp_player_char->move(ui_viewport->width() * hor_offset / 100,
- ui_viewport->height() * vert_offset / 100);
-
- // We do the same with the second character.
- int hor2_offset = m_chatmessage[OTHER_OFFSET].toInt();
- int vert2_offset = 0;
- if (hor2_offset > 0) {
- vert2_offset = hor2_offset / 10;
- }
- ui_vp_sideplayer_char->move(ui_viewport->width() * hor2_offset / 100,
- ui_viewport->height() * vert2_offset /
- 100);
-
- // Finally, we reorder them based on who is more to the left.
- // The person more to the left is more in the front.
- if (hor2_offset >= hor_offset) {
- ui_vp_sideplayer_char->raise();
- ui_vp_player_char->raise();
- }
- else {
- ui_vp_player_char->raise();
- ui_vp_sideplayer_char->raise();
- }
- ui_vp_desk->raise();
- ui_vp_legacy_desk->raise();
- }
- else if (side == "pro") {
- // Almost the same thing happens here, but in reverse.
- int hor_offset = m_chatmessage[SELF_OFFSET].toInt();
- int vert_offset = 0;
- if (hor_offset < 0) {
- // We don't want to RAISE the char off the floor.
- vert_offset = -1 * hor_offset / 10;
- }
- ui_vp_player_char->move(ui_viewport->width() * hor_offset / 100,
- ui_viewport->height() * vert_offset / 100);
-
- // We do the same with the second character.
- int hor2_offset = m_chatmessage[OTHER_OFFSET].toInt();
- int vert2_offset = 0;
- if (hor2_offset < 0) {
- vert2_offset = -1 * hor2_offset / 10;
- }
- ui_vp_sideplayer_char->move(ui_viewport->width() * hor2_offset / 100,
- ui_viewport->height() * vert2_offset /
- 100);
-
- // Finally, we reorder them based on who is more to the right.
- if (hor2_offset <= hor_offset) {
- ui_vp_sideplayer_char->raise();
- ui_vp_player_char->raise();
- }
- else {
- ui_vp_player_char->raise();
- ui_vp_sideplayer_char->raise();
- }
- ui_vp_desk->raise();
- ui_vp_legacy_desk->raise();
- }
- else {
- // In every other case, the person more to the left is on top.
- // These cases also don't move the characters down.
- int hor_offset = m_chatmessage[SELF_OFFSET].toInt();
- ui_vp_player_char->move(ui_viewport->width() * hor_offset / 100, 0);
-
- // We do the same with the second character.
- int hor2_offset = m_chatmessage[OTHER_OFFSET].toInt();
- ui_vp_sideplayer_char->move(ui_viewport->width() * hor2_offset / 100,
- 0);
-
- // Finally, we reorder them based on who is more to the left.
- // The person more to the left is more in the front.
- if (hor2_offset >= hor_offset) {
- ui_vp_sideplayer_char->raise();
- ui_vp_player_char->raise();
- }
- else {
- ui_vp_player_char->raise();
- ui_vp_sideplayer_char->raise();
- }
- ui_vp_desk->raise();
- ui_vp_legacy_desk->raise();
- }
- // We should probably also play the other character's idle emote.
- if (ao_app->flipping_enabled && m_chatmessage[OTHER_FLIP].toInt() == 1)
- ui_vp_sideplayer_char->set_flipped(true);
- else
- ui_vp_sideplayer_char->set_flipped(false);
- ui_vp_sideplayer_char->play_idle(m_chatmessage[OTHER_NAME],
- m_chatmessage[OTHER_EMOTE]);
- ui_vp_sideplayer_char->use_networked_framehell = false;
- }
- else {
- // If the server understands other characters, but there
- // really is no second character, hide 'em, and center the first.
- ui_vp_sideplayer_char->hide();
- ui_vp_sideplayer_char->stop();
- ui_vp_sideplayer_char->move(0, 0);
-
- ui_vp_player_char->move(0, 0);
- }
- }
- }
- if (m_chatmessage[SCREENSHAKE] == "1") {
- this->doScreenShake();
- }
- switch (emote_mod) {
- case 1:
- case 2:
- case 6:
- play_preanim(false);
- break;
- case 0:
- case 5:
- if (m_chatmessage[NONINTERRUPTING_PRE].toInt() == 0)
- handle_chatmessage_3();
- else {
-
- play_preanim(true);
- }
- break;
- default:
- qDebug() << "W: invalid emote mod: " << QString::number(emote_mod);
- }
-}
-void Courtroom::realization_done() { ui_vp_realization->hide(); }
-
-void Courtroom::doScreenShake()
-{
- if (!ao_app->is_shakeandflash_enabled())
- return;
- screenshake_group = new QParallelAnimationGroup;
- screenshake_animation = new QPropertyAnimation(ui_viewport, "pos", this);
- chatbox_screenshake_animation =
- new QPropertyAnimation(ui_vp_chatbox, "pos", this);
- int screen_x = get_theme_pos("viewport").x();
- int screen_y = get_theme_pos("viewport").y();
- QPoint pos_default = QPoint(screen_x, screen_y);
- QPoint pos1 = QPoint(screen_x + 3, screen_y + -5);
- QPoint pos2 = QPoint(screen_x + 3, screen_y + -5);
- QPoint pos3 = QPoint(screen_x + -3, screen_y + 5);
- QPoint pos4 = QPoint(screen_x + 3, screen_y + -5);
- QPoint pos5 = QPoint(screen_x + -3, screen_y + -5);
-
- int chatbox_x = get_theme_pos("ao2_chatbox").x();
- int chatbox_y = get_theme_pos("ao2_chatbox").y();
- QPoint chatbox_pos_default = QPoint(chatbox_x, chatbox_y);
- QPoint chatbox_pos1 = QPoint(chatbox_x + 3, chatbox_y + -5);
- QPoint chatbox_pos2 = QPoint(chatbox_x + 3, chatbox_y + -5);
- QPoint chatbox_pos3 = QPoint(chatbox_x + -3, chatbox_y + 5);
- QPoint chatbox_pos4 = QPoint(chatbox_x + 3, chatbox_y + -5);
- QPoint chatbox_pos5 = QPoint(chatbox_x + -3, chatbox_y + -5);
-
- screenshake_animation->setDuration(200);
- screenshake_animation->setKeyValueAt(0, pos_default);
- screenshake_animation->setKeyValueAt(0.1, pos1);
- screenshake_animation->setKeyValueAt(0.3, pos2);
- screenshake_animation->setKeyValueAt(0.5, pos3);
- screenshake_animation->setKeyValueAt(0.7, pos4);
- screenshake_animation->setKeyValueAt(0.9, pos5);
- screenshake_animation->setEndValue(pos_default);
- screenshake_animation->setEasingCurve(QEasingCurve::Linear);
- chatbox_screenshake_animation->setDuration(200);
- chatbox_screenshake_animation->setKeyValueAt(0, chatbox_pos_default);
- chatbox_screenshake_animation->setKeyValueAt(0.1, chatbox_pos3);
- chatbox_screenshake_animation->setKeyValueAt(0.3, chatbox_pos5);
- chatbox_screenshake_animation->setKeyValueAt(0.5, chatbox_pos2);
- chatbox_screenshake_animation->setKeyValueAt(0.7, chatbox_pos1);
- chatbox_screenshake_animation->setKeyValueAt(0.9, chatbox_pos4);
- chatbox_screenshake_animation->setEndValue(chatbox_pos_default);
- chatbox_screenshake_animation->setEasingCurve(QEasingCurve::Linear);
-
- screenshake_group->addAnimation(screenshake_animation);
- screenshake_group->addAnimation(chatbox_screenshake_animation);
- screenshake_group->start(
- QAbstractAnimation::DeletionPolicy::DeleteWhenStopped);
-}
-
-void Courtroom::handle_chatmessage_3()
-{
- if (!log_goes_downwards && mirror_iclog)
- ui_ic_chatlog->moveCursor(QTextCursor::Start);
- else if (mirror_iclog)
- ui_ic_chatlog->moveCursor(QTextCursor::End);
-
- ui_ic_chatlog->setTextInteractionFlags(Qt::TextSelectableByMouse);
-
- if (mirror_iclog) {
- if (!ui_showname_enable->isChecked() || m_chatmessage[SHOWNAME] == "") {
- if (first_message_sent && log_goes_downwards)
- ui_ic_chatlog->textCursor().insertHtml("<br>");
- else
- first_message_sent = true;
- QString char_name = char_list.at(m_chatmessage[CHAR_ID].toInt()).name;
- ui_ic_chatlog->textCursor().insertHtml("<b>" + char_name +
- ": </b>");
- }
- else {
- if (first_message_sent && log_goes_downwards)
- ui_ic_chatlog->textCursor().insertHtml("<br>");
- else
- first_message_sent = true;
-
- ui_ic_chatlog->textCursor().insertHtml("<b>" + m_chatmessage[SHOWNAME] +
- ": </b>");
- }
-
- QScrollBar *scroll = ui_vp_message->verticalScrollBar();
- scroll->setValue(scroll->maximum());
- if (chatmessage_is_empty && log_goes_downwards) {
- ui_ic_chatlog->moveCursor(QTextCursor::End);
- }
- }
- start_chat_ticking();
- int f_evi_id = m_chatmessage[EVIDENCE_ID].toInt();
- QString f_side = m_chatmessage[SIDE];
-
- if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size()) {
- // shifted by 1 because 0 is no evidence per legacy standards
- QString f_image = local_evidence_list.at(f_evi_id - 1).image;
- // def jud and hlp should display the evidence icon on the RIGHT side
- bool is_left_side = !(f_side == "def" || f_side == "hlp" ||
- f_side == "jud" || f_side == "jur");
- ui_vp_evidence_display->show_evidence(f_image, is_left_side,
- ui_sfx_slider->value());
- }
-
- int emote_mod = m_chatmessage[EMOTE_MOD].toInt();
-
- QString side = m_chatmessage[SIDE];
-
- if (emote_mod == 5 || emote_mod == 6) {
- ui_vp_desk->hide();
- ui_vp_legacy_desk->hide();
-
- // Since we're zooming, hide the second character, and centre the first.
- ui_vp_sideplayer_char->hide();
- ui_vp_player_char->move(0, 0);
-
- if (side == "pro" || side == "hlp" || side == "wit")
- ui_vp_speedlines->play("prosecution_speedlines");
- else
- ui_vp_speedlines->play("defense_speedlines");
- }
-
- int f_anim_state = 0;
- // BLUE is from an enum in datatypes.h
- bool text_is_blue = m_chatmessage[TEXT_COLOR].toInt() == BLUE;
-
- if (!text_is_blue && text_state == 1) {
- // talking
- f_anim_state = 2;
- entire_message_is_blue = false;
- }
- else {
- // idle
- f_anim_state = 3;
- entire_message_is_blue = true;
- }
-
- if (f_anim_state <= anim_state)
- return;
-
- ui_vp_player_char->stop();
-
- QString f_char = "";
- f_char = m_chatmessage[CHAR_NAME];
- QString f_emote = m_chatmessage[EMOTE];
-
- if (f_anim_state == 2) {
- ui_vp_player_char->play_talking(f_char, f_emote);
- anim_state = 2;
- }
- else {
- ui_vp_player_char->play_idle(f_char, f_emote);
- anim_state = 3;
- }
-
- QString f_message = m_chatmessage[MESSAGE];
- QStringList call_words = ao_app->get_call_words();
-
- for (QString word : call_words) {
- if (f_message.contains(word, Qt::CaseInsensitive)) {
- modcall_player->play(ao_app->get_sfx("word_call"));
- ao_app->alert(this);
-
- break;
- }
- }
-}
-
-QString Courtroom::filter_ic_text(QString p_text, bool skip_filter,
- int chat_color)
-{
- // BMKCOMMENT
- // Get rid of centering.
- if (p_text.startsWith(": ~~")) {
- // Don't forget, the p_text part actually everything after the name!
- // Hence why we check for ': ~~'.
-
- // Let's remove those two tildes, then.
- // : _ ~ ~
- // 0 1 2 3
- p_text.remove(2, 2);
- }
-
- // Get rid of the inline-colouring.
- // I know, I know, excessive code duplication.
- // Nobody looks in here, I'm fine.
- int trick_check_pos = 1;
- bool ic_next_is_not_special = false;
- QString f_character = p_text.at(trick_check_pos);
- std::stack<INLINE_COLOURS> ic_colour_stack;
- QString final_text = ": ";
- bool delay_pop = false;
- while (trick_check_pos < p_text.size()) {
- f_character = p_text.at(trick_check_pos);
- if (!skip_filter) {
- if (f_character == "<")
- f_character = "&lt;";
- else if (f_character == ">")
- f_character = "&gt;";
- }
- // Escape character.
- if (f_character == "\\" && !ic_next_is_not_special) {
- ic_next_is_not_special = true;
- p_text.remove(trick_check_pos, 1);
- f_character = "";
- if (p_text[trick_check_pos] == 'n') {
- p_text[trick_check_pos] = ' ';
- f_character = " ";
- }
- }
-
- // Text speed modifier.
- else if ((f_character == "{" || f_character == "}") &&
- !ic_next_is_not_special) {
- p_text.remove(trick_check_pos, 1);
- f_character = "";
- }
- else if (f_character == "$" && !ic_next_is_not_special) {
- p_text.remove(trick_check_pos, 1);
- f_character = "";
- }
- else if (f_character == "@" && !ic_next_is_not_special) {
- p_text.remove(trick_check_pos, 1);
- f_character = "";
- }
-
- // Orange inline colourisation.
- else if (f_character == "|" && !ic_next_is_not_special) {
- if (!ic_colour_stack.empty()) {
- if (ic_colour_stack.top() == INLINE_ORANGE) {
- ic_colour_stack.pop();
- p_text.remove(trick_check_pos, 1);
- }
- else {
- ic_colour_stack.push(INLINE_ORANGE);
- p_text.remove(trick_check_pos, 1);
- }
- }
- else {
- ic_colour_stack.push(INLINE_ORANGE);
- p_text.remove(trick_check_pos, 1);
- }
- f_character = "";
- }
-
- // Blue inline colourisation.
- else if (f_character == "(" && !ic_next_is_not_special) {
- ic_colour_stack.push(INLINE_BLUE);
- if (!colorf_iclog)
- trick_check_pos++;
- }
- else if (f_character == ")" && !ic_next_is_not_special &&
- !ic_colour_stack.empty()) {
- if (ic_colour_stack.top() == INLINE_BLUE) {
- // ic_colour_stack.pop();
- delay_pop = true;
- if (!colorf_iclog)
- trick_check_pos++;
- }
- else {
- ic_next_is_not_special = true;
- }
- }
-
- // Grey inline colourisation.
- else if (f_character == "[" && !ic_next_is_not_special) {
- ic_colour_stack.push(INLINE_GREY);
- if (!colorf_iclog)
- trick_check_pos++;
- }
- else if (f_character == "]" && !ic_next_is_not_special &&
- !ic_colour_stack.empty()) {
- if (ic_colour_stack.top() == INLINE_GREY) {
- // ic_colour_stack.pop();
- delay_pop = true;
- if (!colorf_iclog)
- trick_check_pos++;
- }
- else {
- ic_next_is_not_special = true;
- }
- }
-
- // Green inline colourisation.
- else if (f_character == "`" && !ic_next_is_not_special) {
- if (!ic_colour_stack.empty()) {
- if (ic_colour_stack.top() == INLINE_GREEN) {
- ic_colour_stack.pop();
- p_text.remove(trick_check_pos, 1);
- }
- else {
- ic_colour_stack.push(INLINE_GREEN);
- p_text.remove(trick_check_pos, 1);
- }
- }
- else {
- ic_colour_stack.push(INLINE_GREEN);
- p_text.remove(trick_check_pos, 1);
- }
- f_character = "";
- }
-
- if (colorf_iclog && f_character != "") {
- ic_next_is_not_special = false;
- if (!ic_colour_stack.empty()) {
- // p_text.remove(trick_check_pos,1);
- trick_check_pos++;
- switch (ic_colour_stack.top()) {
- case INLINE_ORANGE:
- final_text += "<font color=\"" +
- get_text_color(QString::number(ORANGE)).name() + "\">" +
- f_character + "</font>";
- break;
- case INLINE_BLUE:
- final_text += "<font color=\"" +
- get_text_color(QString::number(BLUE)).name() + "\">" +
- f_character + "</font>";
- break;
- case INLINE_GREEN:
- final_text += "<font color=\"" +
- get_text_color(QString::number(GREEN)).name() + "\">" +
- f_character + "</font>";
- break;
- case INLINE_GREY:
- final_text += "<font color=\"" +
- get_text_color("_inline_grey").name() + "\">" +
- f_character + "</font>";
- break;
- }
- if (delay_pop) {
- ic_colour_stack.pop();
- delay_pop = false;
- }
- }
- else if (!(chat_color == WHITE || chat_color == RAINBOW) &&
- !colorf_limit) {
- trick_check_pos++;
- QString html_color;
- switch (chat_color) {
- case 1:
- html_color = get_text_color(QString::number(GREEN)).name();
- break;
- case 2:
- html_color = get_text_color(QString::number(RED)).name();
- break;
- case 3:
- html_color = get_text_color(QString::number(ORANGE)).name();
- break;
- case 4:
- html_color = get_text_color(QString::number(BLUE)).name();
- break;
- case 5:
- html_color = get_text_color(QString::number(YELLOW)).name();
- break;
- case 7:
- html_color = get_text_color(QString::number(PINK)).name();
- break;
- case 8:
- html_color = get_text_color(QString::number(CYAN)).name();
- break;
- }
- final_text +=
- "<font color=\"" + html_color + "\">" + f_character + "</font>";
- }
- else if (chat_color == RAINBOW && !colorf_limit) {
- QString html_color;
-
- switch (rainbow_counter) {
- case 0:
- html_color = get_text_color(QString::number(RED)).name();
- break;
- case 1:
- html_color = get_text_color(QString::number(ORANGE)).name();
- break;
- case 2:
- html_color = get_text_color(QString::number(YELLOW)).name();
- break;
- case 3:
- html_color = get_text_color(QString::number(GREEN)).name();
- break;
- default:
- html_color = get_text_color(QString::number(BLUE)).name();
- rainbow_counter = -1;
- }
-
- ++rainbow_counter;
- final_text +=
- "<font color=\"" + html_color + "\">" + f_character + "</font>";
- trick_check_pos++;
- }
-
- else {
- final_text += f_character;
- trick_check_pos++;
- }
- }
- else if (f_character != "") {
- trick_check_pos++;
- }
- }
-
- if (colorf_iclog)
- return final_text;
- else {
- return p_text;
- }
-}
-/*
- * Appends text to the ic log.
- * \param p_text The text to be appended
- * \param p_name The name of the character/entity who sent said text
- * \param is_songchange Whether we are appending a song entry
- * \param force_filter If we are sending plain text and we want to force the
- * \param filtering regardless of its status (e.g chat entry, song change etc)
- * \param skip_filter If we are sending appending text such as html so we skip the
- * \param filter chat_color The color of the message sent
- */
-
-void Courtroom::append_ic_text(QString p_text, QString p_name,
- bool is_songchange, bool force_filter,
- bool skip_filter, int chat_color)
-{
-
- QTextCharFormat bold;
- QTextCharFormat normal;
- QTextCharFormat italics;
- bold.setFontWeight(QFont::Bold);
- normal.setFontWeight(QFont::Normal);
- italics.setFontItalic(true);
- const QTextCursor old_cursor = ui_ic_chatlog->textCursor();
- const int old_scrollbar_value = ui_ic_chatlog->verticalScrollBar()->value();
-
- if ((!is_songchange && !mirror_iclog) || force_filter)
- p_text = filter_ic_text(p_text, skip_filter, chat_color);
-
- if (log_goes_downwards) {
- const bool is_scrolled_down =
- old_scrollbar_value == ui_ic_chatlog->verticalScrollBar()->maximum();
-
- ui_ic_chatlog->moveCursor(QTextCursor::End);
- if (!(is_songchange && mirror_iclog)) {
- // The only case where no new log entry should be made is when there is a
- // music entry while mirror log is active This is to protect the log, as
- // if there is a songchange during a new message being typed, then they
- // will destructively interfere with eachother
-
- // If the first message hasn't been sent, and we are handling basic
- // text, we put the name without the newline.
- if (!first_message_sent)
- ui_ic_chatlog->textCursor().insertText(p_name, bold);
-
- else if (force_filter || is_songchange || !mirror_iclog) {
- // Otherwise we just add the plaintext with the new line.
- ui_ic_chatlog->textCursor().insertText('\n' + p_name, bold);
- }
- first_message_sent = true;
-
- if (is_songchange) {
- // If its a song with mirror mode enabled, we do not need to repeat it
- // as it is already shown in the ooc.
- ui_ic_chatlog->textCursor().insertText(" has played a song: ", normal);
- ui_ic_chatlog->textCursor().insertText(p_text + ".", italics);
- }
-
- else if (colorf_iclog && (!mirror_iclog || force_filter)) {
- // if we are handling already formatted text and we have enabled colors
- // in the iclog, then we insert the text
- ui_ic_chatlog->textCursor().insertHtml(p_text);
- }
-
- else if ((!colorf_iclog && !mirror_iclog) || force_filter) {
- // If html is not enabled then we insert it as plain text.
- ui_ic_chatlog->textCursor().insertText(p_text, normal);
- }
- }
- // If we got too many blocks in the current log, delete some from the top.
- while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks &&
- log_maximum_blocks > 0) {
- ui_ic_chatlog->moveCursor(QTextCursor::Start);
- ui_ic_chatlog->textCursor().select(QTextCursor::BlockUnderCursor);
- ui_ic_chatlog->textCursor().removeSelectedText();
- ui_ic_chatlog->textCursor().deleteChar();
- // qDebug() << ui_ic_chatlog->document()->blockCount() << " < " <<
- // log_maximum_blocks;
- }
-
- if (old_cursor.hasSelection() || !is_scrolled_down) {
- // The user has selected text or scrolled away from the bottom: maintain
- // position.
- ui_ic_chatlog->setTextCursor(old_cursor);
- ui_ic_chatlog->verticalScrollBar()->setValue(old_scrollbar_value);
- }
- else {
- // The user hasn't selected any text and the scrollbar is at the bottom:
- // scroll to the bottom.
- ui_ic_chatlog->moveCursor(QTextCursor::End);
- ui_ic_chatlog->verticalScrollBar()->setValue(
- ui_ic_chatlog->verticalScrollBar()->maximum());
- }
- }
- else {
- const bool is_scrolled_up =
- old_scrollbar_value == ui_ic_chatlog->verticalScrollBar()->minimum();
-
- ui_ic_chatlog->moveCursor(QTextCursor::Start);
- if (!(is_songchange && mirror_iclog)) {
- // The only case where no new log entry should be made is when there is a
- // music entry while mirror log is active This is to protect the log, as
- // if there is a songchange during a new message being typed, then they
- // will destructively interfere with eachother
-
- if ((force_filter || !mirror_iclog || is_songchange)) {
-
- if (mirror_iclog)
- // If mirror is enabled we need to make space on the top so the text
- // can be inserted without any interuptions If mirror mode is not
- // enabled, then we do not need to clear out the top line as the new
- // entry pushes it automatically down.
- p_name = '\n' + p_name;
-
- if (!first_message_sent)
- first_message_sent = true;
-
- ui_ic_chatlog->textCursor().insertText(p_name, bold);
- }
-
- if (is_songchange) {
- ui_ic_chatlog->textCursor().insertText(" has played a song: ", normal);
- ui_ic_chatlog->textCursor().insertText(p_text + "." + '\n', italics);
- }
-
- else if (colorf_iclog && (!mirror_iclog || force_filter)) {
- ui_ic_chatlog->textCursor().insertHtml(p_text);
- }
- else if ((!colorf_iclog && !mirror_iclog) || force_filter) {
- ui_ic_chatlog->textCursor().insertText(p_text, normal);
- }
- if (!mirror_iclog)
- ui_ic_chatlog->textCursor().insertHtml("<br>");
- }
- // If we got too many blocks in the current log, delete some from the
- // bottom.
- while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks &&
- log_maximum_blocks > 0) {
- ui_ic_chatlog->moveCursor(QTextCursor::End);
- ui_ic_chatlog->textCursor().select(QTextCursor::BlockUnderCursor);
- ui_ic_chatlog->textCursor().removeSelectedText();
- ui_ic_chatlog->textCursor().deletePreviousChar();
- // qDebug() << ui_ic_chatlog->document()->blockCount() << " < " <<
- // log_maximum_blocks;
- }
-
- if (old_cursor.hasSelection() || !is_scrolled_up) {
- // The user has selected text or scrolled away from the top: maintain
- // position.
- ui_ic_chatlog->setTextCursor(old_cursor);
- ui_ic_chatlog->verticalScrollBar()->setValue(old_scrollbar_value);
- }
- else {
- // The user hasn't selected any text and the scrollbar is at the top:
- // scroll to the top.
- ui_ic_chatlog->moveCursor(QTextCursor::Start);
- ui_ic_chatlog->verticalScrollBar()->setValue(
- ui_ic_chatlog->verticalScrollBar()->minimum());
- }
- }
-}
-
-void Courtroom::play_preanim(bool noninterrupting)
-{
- QString f_char = m_chatmessage[CHAR_NAME];
- QString f_preanim = m_chatmessage[PRE_EMOTE];
-
- // all time values in char.inis are multiplied by a constant(time_mod) to get
- // the actual time
- int ao2_duration = ao_app->get_ao2_preanim_duration(f_char, f_preanim);
- int text_delay = ao_app->get_text_delay(f_char, f_preanim) * time_mod;
- int sfx_delay = m_chatmessage[SFX_DELAY].toInt() * 60;
- bool looping_sfx = m_chatmessage[LOOPING_SFX] == "1";
- int preanim_duration;
-
- if (ao2_duration < 0)
- preanim_duration = ao_app->get_preanim_duration(f_char, f_preanim);
- else
- preanim_duration = ao2_duration;
- sfx_player->setLooping(looping_sfx);
- sfx_delay_timer->start(sfx_delay);
- QString anim_to_find =
- ao_app->get_image_suffix(ao_app->get_character_path(f_char, f_preanim));
- if (!file_exists(anim_to_find) || preanim_duration < 0) {
- if (noninterrupting)
- anim_state = 4;
- else
- anim_state = 1;
- preanim_done();
- qDebug() << "could not find " + anim_to_find;
- return;
- }
-
- ui_vp_player_char->play_pre(f_char, f_preanim, preanim_duration);
- if (noninterrupting)
- anim_state = 4;
- else
- anim_state = 1;
-
- if (text_delay >= 0)
- text_delay_timer->start(text_delay);
-
- if (noninterrupting)
- handle_chatmessage_3();
-}
-
-void Courtroom::preanim_done()
-{
- anim_state = 1;
- handle_chatmessage_3();
-}
-
-void Courtroom::doRealization()
-{
- realization_timer->stop();
- if (!ao_app->is_shakeandflash_enabled())
- return;
- ui_vp_realization->play("realizationflash", "", "", 90);
-}
-
-void Courtroom::start_chat_ticking()
-{
- // we need to ensure that the text isn't already ticking because this function
- // can be called by two logic paths
- if (text_state != 0)
- return;
-
- if (m_chatmessage[REALIZATION] == "1") {
- this->doRealization();
- misc_sfx_player->play(
- ao_app->get_custom_realization(m_chatmessage[CHAR_NAME]));
- }
- if (m_chatmessage[SCREENSHAKE] == "1") {
- this->doScreenShake();
- }
- if (m_chatmessage[SCREENSHAKE] == "1") {
- this->doScreenShake();
- }
- ui_vp_message->clear();
- set_text_color();
- rainbow_counter = 0;
-
- if (chatmessage_is_empty) {
- // since the message is empty, it's technically done ticking
- text_state = 2;
- return;
- }
-
- // At this point, we'd do well to clear the inline colour stack.
- // This stops it from flowing into next messages.
- while (!inline_colour_stack.empty()) {
- inline_colour_stack.pop();
- }
-
- ui_vp_chatbox->show();
-
- tick_pos = 0;
- blip_pos = 0;
-
- // Just in case we somehow got inline blue text left over from a previous
- // message, let's set it to false.
- inline_blue_depth = 0;
-
- // At the start of every new message, we set the text speed to the default.
- current_display_speed = 3;
- if (slower_blips)
- chat_tick_timer->start(message_display_speed_slow[current_display_speed]);
- else
- chat_tick_timer->start(message_display_speed[current_display_speed]);
-
- QString f_char = m_chatmessage[CHAR_NAME];
- QString f_gender = ao_app->get_gender(f_char);
-
- blip_player->set_blips(ao_app->get_sfx_suffix("sfx-blip" + f_gender));
-
- // means text is currently ticking
- text_state = 1;
-}
-
-void Courtroom::chat_tick()
-{
- // note: this is called fairly often(every 60 ms when char is talking)
- // do not perform heavy operations here
- QString timem = QString::number(realization_timer->remainingTime());
- qDebug() << "TIME: " << timem;
- QString f_message = m_chatmessage[MESSAGE];
-
- // f_message.remove(0, tick_pos); SAFECHECK
-
- // Due to our new text speed system, we always need to stop the timer now.
- chat_tick_timer->stop();
- int msg_delay = message_display_speed[current_display_speed];
- if (slower_blips)
- msg_delay = message_display_speed_slow[current_display_speed];
- // Stops blips from playing when we have a formatting option.
- bool formatting_char = false;
-
- // If previously, we have detected that the message is centered, now
- // is the time to remove those two tildes at the start.
- if (message_is_centered) {
- f_message.remove(0, 2);
- }
- QString f_char = m_chatmessage[CHAR_NAME];
- if (log_goes_downwards && mirror_iclog)
- ui_ic_chatlog->moveCursor(QTextCursor::End);
- else if (!log_goes_downwards && mirror_iclog)
- // ui_ic_chatlog->setTextCursor();
- ui_ic_chatlog->moveCursor(QTextCursor::EndOfLine);
-
- if (tick_pos >= f_message.size()) {
- text_state = 2;
- if (mirror_iclog) {
- // After we are finished printing the text we log it in the ic log.
- append_ic_text(m_chatmessage[MESSAGE], m_chatmessage[CHAR_NAME], false);
- if (log_goes_downwards)
- ui_ic_chatlog->moveCursor(QTextCursor::End);
- else
- ui_ic_chatlog->moveCursor(QTextCursor::Start);
- }
- if (anim_state != 4) {
- anim_state = 3;
- ui_vp_player_char->play_idle(f_char, m_chatmessage[EMOTE]);
- }
- }
-
- else {
- QString f_character = f_message.at(tick_pos);
-
- f_character = f_character.toHtmlEscaped();
- if (punctuation_chars.contains(f_character)) {
- msg_delay *= punctuation_modifier + 1; // Since we are handling a boolean, if its true its double (1 + 1) or false (1 + 0).
- // ui_vp_message->insertPlainText(f_character);
- }
-
- if (f_character == " ") {
- ui_vp_message->insertPlainText(" ");
- if (mirror_iclog)
- ui_ic_chatlog->insertPlainText(" ");
- }
- else if (f_character == "@" && !next_character_is_not_special) {
- this->doScreenShake();
- formatting_char = true;
- }
-
- else if (f_character == "^" && !next_character_is_not_special) {
- this->doRealization();
-
- formatting_char = true;
- }
- // Escape character.
- else if (f_character == "\\") {
- if (f_message[tick_pos + 1] == 'n') {
- ui_vp_message->insertHtml("<br>");
- ui_ic_chatlog->insertPlainText(" ");
-
- tick_pos += 1;
- next_character_is_not_special = false;
- formatting_char = true;
- }
- else
- next_character_is_not_special = true;
- formatting_char = true;
- msg_delay++;
- }
-
- // Text speed modifier.
- else if (f_character == "{" && !next_character_is_not_special) {
- // ++, because it INCREASES delay!
- current_display_speed++;
- msg_delay++;
- formatting_char = true;
- }
- else if (f_character == "}" && !next_character_is_not_special) {
- current_display_speed--;
- msg_delay++;
- formatting_char = true;
- }
-
- else if (f_character == "@" && !next_character_is_not_special) {
- this->doScreenShake();
- formatting_char = true;
- }
-
- else if (f_character == "$" && !next_character_is_not_special) {
- this->doRealization();
- formatting_char = true;
- }
-
- // Orange inline colourisation.
- else if (f_character == "|" && !next_character_is_not_special) {
- if (!inline_colour_stack.empty()) {
- if (inline_colour_stack.top() == INLINE_ORANGE) {
- inline_colour_stack.pop();
- }
- else {
- inline_colour_stack.push(INLINE_ORANGE);
- }
- }
- else {
- inline_colour_stack.push(INLINE_ORANGE);
- }
- formatting_char = true;
- msg_delay++;
- }
-
- // Blue inline colourisation.
- else if (f_character == "(" &&
- !next_character_is_not_special) // EXAMPLE HERE
- {
- inline_colour_stack.push(INLINE_BLUE);
- ui_vp_message->insertHtml("<font color=\"" +
- get_text_color(QString::number(BLUE)).name() +
- "\">" + f_character + "</font>");
- if (mirror_iclog && colorf_iclog)
- ui_ic_chatlog->insertHtml("<font color=\"" +
- get_text_color(QString::number(BLUE)).name() +
- "\">" + f_character + "</font>");
- // Increase how deep we are in inline blues.
- inline_blue_depth++;
-
- // Here, we check if the entire message is blue.
- // If it isn't, we stop talking.
- if (!entire_message_is_blue && anim_state != 4) {
- f_char = m_chatmessage[CHAR_NAME];
- QString f_emote = m_chatmessage[EMOTE];
- ui_vp_player_char->play_idle(f_char, f_emote);
- }
- }
- else if (f_character == ")" && !next_character_is_not_special &&
- !inline_colour_stack.empty()) {
- if (inline_colour_stack.top() == INLINE_BLUE) {
- inline_colour_stack.pop();
- ui_vp_message->insertHtml("<font color=\"" +
- get_text_color(QString::number(BLUE)).name() +
- "\">" + f_character + "</font>");
- if (mirror_iclog && colorf_iclog)
- ui_ic_chatlog->insertHtml(
- "<font color=\"" + get_text_color(QString::number(BLUE)).name() +
- "\">" + f_character + "</font>");
- // Decrease how deep we are in inline blues.
- // Just in case, we do a check if we're above zero, but we should be.
- if (inline_blue_depth > 0) {
- inline_blue_depth--;
- // Here, we check if the entire message is blue.
- // If it isn't, we start talking if we have completely climbed out of
- // inline blues.
- if (!entire_message_is_blue) {
- // We should only go back to talking if we're out of inline blues,
- // not during a non. int. pre, and not on the last character.
- if (inline_blue_depth == 0 && anim_state != 4 &&
- !(tick_pos + 1 >= f_message.size())) {
- QString f_char = char_name;
- f_char = m_chatmessage[CHAR_NAME];
- QString f_emote = m_chatmessage[EMOTE];
- ui_vp_player_char->play_talking(f_char, f_emote);
- }
- }
- }
- }
- else {
- next_character_is_not_special = true;
- tick_pos--;
- }
- }
-
- // Grey inline colourisation.
- else if (f_character == "[" && !next_character_is_not_special) {
- inline_colour_stack.push(INLINE_GREY);
- ui_vp_message->insertHtml("<font color=\"" +
- get_text_color("_inline_grey").name() + "\">" +
- f_character + "</font>");
- if (mirror_iclog && colorf_iclog)
- ui_ic_chatlog->insertHtml("<font color=\"" +
- get_text_color("_inline_grey").name() +
- "\">" + f_character + "</font>");
- }
- else if (f_character == "]" && !next_character_is_not_special &&
- !inline_colour_stack.empty()) {
- if (inline_colour_stack.top() == INLINE_GREY) {
- inline_colour_stack.pop();
- ui_vp_message->insertHtml("<font color=\"" +
- get_text_color("_inline_grey").name() +
- "\">" + f_character + "</font>");
- if (mirror_iclog && colorf_iclog)
- ui_ic_chatlog->insertHtml("<font color=\"" +
- get_text_color("_inline_grey").name() +
- "\">" + f_character + "</font>");
- }
- else {
- next_character_is_not_special = true;
- tick_pos--;
- }
- }
-
- // Green inline colourisation.
- else if (f_character == "`" && !next_character_is_not_special) {
- if (!inline_colour_stack.empty()) {
- if (inline_colour_stack.top() == INLINE_GREEN) {
- inline_colour_stack.pop();
- }
- else {
- inline_colour_stack.push(INLINE_GREEN);
- }
- }
- else {
- inline_colour_stack.push(INLINE_GREEN);
- }
- msg_delay++;
- formatting_char = true;
- }
- else {
-
- next_character_is_not_special = false;
- if (!inline_colour_stack.empty()) {
- switch (inline_colour_stack.top()) {
- case INLINE_ORANGE:
- ui_vp_message->insertHtml(
- "<font color=\"" +
- get_text_color(QString::number(ORANGE)).name() + "\">" +
- f_character + "</font>");
- if (mirror_iclog && colorf_iclog)
- ui_ic_chatlog->insertHtml(
- "<font color=\"" +
- get_text_color(QString::number(ORANGE)).name() + "\">" +
- f_character + "</font>");
- break;
- case INLINE_BLUE:
- ui_vp_message->insertHtml(
- "<font color=\"" + get_text_color(QString::number(BLUE)).name() +
- "\">" + f_character + "</font>");
- if (mirror_iclog && colorf_iclog)
- ui_ic_chatlog->insertHtml(
- "<font color=\"" +
- get_text_color(QString::number(BLUE)).name() + "\">" +
- f_character + "</font>");
- break;
- case INLINE_GREEN:
- ui_vp_message->insertHtml(
- "<font color=\"" + get_text_color(QString::number(GREEN)).name() +
- "\">" + f_character + "</font>");
- if (mirror_iclog && colorf_iclog)
- ui_ic_chatlog->insertHtml(
- "<font color=\"" +
- get_text_color(QString::number(GREEN)).name() + "\">" +
- f_character + "</font>");
- break;
- case INLINE_GREY:
- ui_vp_message->insertHtml("<font color=\"" +
- get_text_color("_inline_grey").name() +
- "\">" + f_character + "</font>");
- if (mirror_iclog && colorf_iclog)
- ui_ic_chatlog->insertHtml("<font color=\"" +
- get_text_color("_inline_grey").name() +
- "\">" + f_character + "</font>");
- break;
- }
- }
- else {
- if (m_chatmessage[TEXT_COLOR].toInt() == RAINBOW) {
- QString html_color;
-
- switch (rainbow_counter) {
- case 0:
- html_color = get_text_color(QString::number(RED)).name();
- break;
- case 1:
- html_color = get_text_color(QString::number(ORANGE)).name();
- break;
- case 2:
- html_color = get_text_color(QString::number(YELLOW)).name();
- break;
- case 3:
- html_color = get_text_color(QString::number(GREEN)).name();
- break;
- default:
- html_color = get_text_color(QString::number(BLUE)).name();
- rainbow_counter = -1;
- }
-
- ++rainbow_counter;
-
- ui_vp_message->insertHtml("<font color=\"" + html_color + "\">" +
- f_character + "</font>");
- if (mirror_iclog && colorf_iclog && !colorf_limit)
- ui_ic_chatlog->insertHtml("<font color=\"" + html_color + "\">" +
- f_character + "</font>");
- }
- else {
- ui_vp_message->insertHtml(f_character);
- if (mirror_iclog && colorf_iclog &&
- ((m_chatmessage[TEXT_COLOR].toInt() == WHITE) || colorf_limit))
- ui_ic_chatlog->insertHtml(f_character);
- }
-
- if (!(m_chatmessage[TEXT_COLOR].toInt() == WHITE) &&
- !(m_chatmessage[TEXT_COLOR].toInt() == RAINBOW) && !colorf_limit) {
-
- QString html_color =
- get_text_color(QString::number(m_chatmessage[TEXT_COLOR].toInt()))
- .name();
-
- if (mirror_iclog && colorf_iclog)
- ui_ic_chatlog->insertHtml("<font color=\"" + html_color + "\">" +
- f_character + "</font>");
- }
- }
-
- if (mirror_iclog && !colorf_iclog) {
- ui_ic_chatlog->textCursor().insertHtml(f_character);
- }
- if (message_is_centered) {
- ui_vp_message->setAlignment(Qt::AlignCenter);
- }
- else {
- ui_vp_message->setAlignment(Qt::AlignLeft);
- }
- }
-
- QScrollBar *scroll = ui_vp_message->verticalScrollBar();
- scroll->setValue(scroll->maximum());
-
- if (blank_blip)
- qDebug() << "blank_blip found true";
-
- if (f_message.at(tick_pos) != ' ' || blank_blip) {
-
- if (blip_pos % blip_rate == 0 && !formatting_char) {
- blip_pos = 0;
- blip_player->blip_tick();
- }
-
- ++blip_pos;
- }
-
- ++tick_pos;
-
- // Restart the timer, but according to the newly set speeds, if there were
- // any. Keep the speed at bay.
- if (current_display_speed < 0) {
- current_display_speed = 0;
- }
-
- if (current_display_speed > 6) {
- current_display_speed = 6;
- }
- if (formatting_char) {
- chat_tick_timer->start(1);
- }
- else {
- chat_tick_timer->start(msg_delay);
- }
- }
-}
-
-void Courtroom::play_sfx()
-{
- QString sfx_name = m_chatmessage[SFX_NAME];
-
- if (sfx_name == "1")
- return;
-
- sfx_player->play(ao_app->get_sfx_suffix(sfx_name));
-}
-
-void Courtroom::set_scene()
-{
-
- // witness is default if pos is invalid
- QString f_background = "witnessempty";
- QString f_desk_image = "stand";
- QString f_desk_mod = m_chatmessage[DESK_MOD];
- QString f_side = m_chatmessage[SIDE];
-
- if (f_side == "def") {
- f_background = "defenseempty";
- if (is_ao2_bg)
- f_desk_image = "defensedesk";
- else
- f_desk_image = "bancodefensa";
- }
- else if (f_side == "pro") {
- f_background = "prosecutorempty";
- if (is_ao2_bg)
- f_desk_image = "prosecutiondesk";
- else
- f_desk_image = "bancoacusacion";
- }
- else if (f_side == "jud") {
- f_background = "judgestand";
- f_desk_image = "judgedesk";
- }
- else if (f_side == "hld") {
- f_background = "helperstand";
- f_desk_image = "helperdesk";
- }
- else if (f_side == "hlp") {
- f_background = "prohelperstand";
- f_desk_image = "prohelperdesk";
- }
- else if (f_side == "jur" && (file_exists(ao_app->get_image_suffix(
- ao_app->get_background_path("jurystand"))))) {
- f_background = "jurystand";
- f_desk_image = "jurydesk";
- }
- else if (f_side == "sea" &&
- (file_exists(ao_app->get_image_suffix(
- ao_app->get_background_path("seancestand"))))) {
- f_background = "seancestand";
- f_desk_image = "seancedesk";
- }
- else {
- if (is_ao2_bg)
- f_desk_image = "stand";
- else
- f_desk_image = "estrado";
- }
-
- ui_vp_background->set_image(f_background);
- ui_vp_desk->set_image(f_desk_image);
- ui_vp_legacy_desk->set_legacy_desk(f_desk_image);
-
- if (f_desk_mod == "0" ||
- (f_desk_mod != "1" &&
- (f_side == "jud" || f_side == "hld" || f_side == "hlp"))) {
- ui_vp_desk->hide();
- ui_vp_legacy_desk->hide();
- }
- else if (is_ao2_bg ||
- (f_side == "jud" || f_side == "hld" || f_side == "hlp")) {
- ui_vp_legacy_desk->hide();
- ui_vp_desk->show();
- }
- else {
- if (f_side == "wit") {
- ui_vp_desk->show();
- ui_vp_legacy_desk->hide();
- }
- else {
- ui_vp_desk->hide();
- ui_vp_legacy_desk->show();
- }
- }
-}
-
-void Courtroom::set_text_color()
-{
- QString f_char = m_chatmessage[CHAR_NAME];
- QColor textcolor = ao_app->get_chat_color(m_chatmessage[TEXT_COLOR],
- ao_app->get_chat(f_char));
-
- ui_vp_message->setTextBackgroundColor(QColor(0, 0, 0, 0));
- ui_vp_message->setTextColor(textcolor);
-
- QString style = "background-color: rgba(0, 0, 0, 0);";
- style.append("color: rgb(");
- style.append(QString::number(textcolor.red()));
- style.append(", ");
- style.append(QString::number(textcolor.green()));
- style.append(", ");
- style.append(QString::number(textcolor.blue()));
- style.append(")");
-
- ui_vp_message->setStyleSheet(style);
-}
-
-QColor Courtroom::get_text_color(QString color)
-{
- QString f_char = m_chatmessage[CHAR_NAME];
- return ao_app->get_chat_color(color, ao_app->get_chat(f_char));
-}
-
-void Courtroom::set_ip_list(QString p_list)
-{
- QString f_list = p_list.replace("|", ":").replace("*", "\n");
-
- ui_server_chatlog->append(f_list);
-}
-
-void Courtroom::set_mute(bool p_muted, int p_cid)
-{
- if (p_cid != m_cid && p_cid != -1)
- return;
-
- if (p_muted)
- ui_muted->show();
- else {
- ui_muted->hide();
- ui_ic_chat_message->setFocus();
- }
-
- ui_muted->resize(ui_ic_chat_message->width(), ui_ic_chat_message->height());
- ui_muted->set_image("muted.png");
-
- is_muted = p_muted;
- ui_ic_chat_message->setEnabled(!p_muted);
-}
-
-void Courtroom::set_ban(int p_cid)
-{
- if (p_cid != m_cid && p_cid != -1)
- return;
-
- call_notice(tr("You have been banned."));
-
- ao_app->construct_lobby();
- ao_app->destruct_courtroom();
-}
-
-void Courtroom::handle_song(QStringList *p_contents)
-{
- QStringList f_contents = *p_contents;
-
- if (f_contents.size() < 2)
- return;
-
- QString f_song = f_contents.at(0);
- QString f_song_clear = f_song;
- int n_char = f_contents.at(1).toInt();
-
- qDebug() << "playing song " + ao_app->get_music_path(f_song);
-
- if (n_char < 0 || n_char >= char_list.size()) {
- music_player->play(ao_app->get_music_prefix(f_song));
- }
- else {
- QString str_char = char_list.at(n_char).name;
- QString str_show = char_list.at(n_char).name;
-
- if (p_contents->length() > 2) {
- if (p_contents->at(2) != "") {
- str_show = p_contents->at(2);
- }
- }
- if (p_contents->length() > 3) {
- if (p_contents->at(3) != "-1") {
- music_player->enable_looping = false;
- }
- else {
- music_player->enable_looping = true;
- }
- }
- if (!mute_map.value(n_char)) {
- chatlogpiece *temp = new chatlogpiece(str_char, str_show, f_song, true,
- m_chatmessage[TEXT_COLOR].toInt());
- ic_chatlog_history.append(*temp);
-
- while (ic_chatlog_history.size() > log_maximum_blocks &&
- log_maximum_blocks > 0) {
- ic_chatlog_history.removeFirst();
- }
- if (mirror_iclog) // If mirror is enabled, we display the song in the ooc
- // chat rather than ic log for a more realistic
- // expierence.
- {
- ui_server_chatlog->append_chatmessage(
- str_show, " has played a song: " + f_song_clear + ".",
- ao_app->get_color("ooc_server_color", "courtroom_design.ini")
- .name(),
- true);
- }
- append_ic_text(f_song_clear, str_show, true);
- music_player->play(ao_app->get_music_prefix(f_song));
- }
- }
-}
-void Courtroom::handle_failed_login()
-{
- modcall_player->play("./music/failed_login"); // aov memes
-}
-void Courtroom::handle_wtce(QString p_wtce, int variant)
-{
- QString sfx_file = "courtroom_sounds.ini";
-
- // witness testimony
- if (p_wtce == "testimony1") {
- misc_sfx_player->play(ao_app->get_sfx("witness_testimony"));
- ui_vp_wtce->play("witnesstestimony", "", "", wtce_stay_time);
- ui_vp_testimony->play("testimony");
- }
- // cross examination
- else if (p_wtce == "testimony2") {
- misc_sfx_player->play(ao_app->get_sfx("cross_examination"));
- ui_vp_wtce->play("crossexamination", "", "", wtce_stay_time);
- ui_vp_testimony->stop();
- }
- else if (p_wtce == "judgeruling") {
- if (variant == 0) {
- misc_sfx_player->play(ao_app->get_sfx("not_guilty"));
- ui_vp_wtce->play("notguilty", "", "", verdict_stay_time);
- ui_vp_testimony->stop();
- }
- else if (variant == 1) {
- misc_sfx_player->play(ao_app->get_sfx("guilty"));
- ui_vp_wtce->play("guilty", "", "", verdict_stay_time);
- ui_vp_testimony->stop();
- }
- }
-}
-
-void Courtroom::set_hp_bar(int p_bar, int p_state)
-{
- if (p_state < 0 || p_state > 10)
- return;
-
- if (p_bar == 1) {
- ui_defense_bar->set_image("defensebar" + QString::number(p_state) + ".png");
- defense_bar_state = p_state;
- }
- else if (p_bar == 2) {
- ui_prosecution_bar->set_image("prosecutionbar" + QString::number(p_state) +
- ".png");
- prosecution_bar_state = p_state;
- }
-}
-
-void Courtroom::toggle_judge_buttons(bool is_on)
-{
- if (is_on) {
- ui_witness_testimony->show();
- ui_cross_examination->show();
- ui_guilty->show();
- ui_not_guilty->show();
- ui_defense_minus->show();
- ui_defense_plus->show();
- ui_prosecution_minus->show();
- ui_prosecution_plus->show();
- }
- else {
- ui_witness_testimony->hide();
- ui_cross_examination->hide();
- ui_guilty->hide();
- ui_not_guilty->hide();
- ui_defense_minus->hide();
- ui_defense_plus->hide();
- ui_prosecution_minus->hide();
- ui_prosecution_plus->hide();
- }
-}
-
-void Courtroom::mod_called(QString p_ip)
-{
- ui_server_chatlog->append(p_ip);
- if (!ui_guard->isChecked()) {
- modcall_player->play(ao_app->get_sfx("mod_call"));
- ao_app->alert(this);
- }
-}
-
-void Courtroom::case_called(QString msg, bool def, bool pro, bool jud, bool jur,
- bool steno, bool witness)
-{
- if (ui_casing->isChecked()) {
- ui_server_chatlog->append(msg);
- if ((ao_app->get_casing_defence_enabled() && def) ||
- (ao_app->get_casing_prosecution_enabled() && pro) ||
- (ao_app->get_casing_judge_enabled() && jud) ||
- (ao_app->get_casing_juror_enabled() && jur) ||
- (ao_app->get_casing_steno_enabled() && steno) ||
- (ao_app->get_casing_wit_enabled() && witness)) {
- modcall_player->play(ao_app->get_sfx("case_call"));
- ao_app->alert(this);
- }
- }
-}
-
-void Courtroom::on_ooc_return_pressed()
-{
- QString ooc_message = ui_ooc_chat_message->text();
-
- if (ooc_message == "" || ui_ooc_chat_name->text() == "")
- return;
-
- if (ooc_message.startsWith("/pos")) {
- if (ooc_message == "/pos jud") {
- toggle_judge_buttons(true);
- }
- else {
- toggle_judge_buttons(false);
- }
- }
- else if (ooc_message.startsWith("/login")) {
- ui_guard->show();
-
- append_server_chatmessage(
- "CLIENT", tr("You were granted the Disable Modcalls button."), "1");
- }
- else if (ooc_message.startsWith("/rainbow") && ao_app->yellow_text_enabled &&
- !rainbow_appended) {
- // ui_text_color->addItem("Rainbow");
- ui_ooc_chat_message->clear();
- // rainbow_appended = true;
- append_server_chatmessage("CLIENT",
- tr("This does nothing, but there you go."), "1");
- return;
- }
- else if (ooc_message.startsWith("/settings")) {
- ui_ooc_chat_message->clear();
- ao_app->call_settings_menu();
- append_server_chatmessage("CLIENT", tr("You opened the settings menu."),
- "1");
- return;
- }
- else if (ooc_message.startsWith("/pair")) {
- ui_ooc_chat_message->clear();
- ooc_message.remove(0, 6);
-
- bool ok;
- int whom = ooc_message.toInt(&ok);
- if (ok) {
- if (whom > -1) {
- other_charid = whom;
- QString msg = tr("You will now pair up with ");
- msg.append(char_list.at(whom).name);
- msg.append(tr(" if they also choose your character in return."));
- append_server_chatmessage("CLIENT", msg, "1");
- }
- else {
- other_charid = -1;
- append_server_chatmessage(
- "CLIENT", tr("You are no longer paired with anyone."), "1");
- }
- }
- else {
- append_server_chatmessage("CLIENT",
- tr("Are you sure you typed that well? The char "
- "ID could not be recognised."),
- "1");
- }
- return;
- }
- else if (ooc_message.startsWith("/offset")) {
- ui_ooc_chat_message->clear();
- ooc_message.remove(0, 8);
-
- bool ok;
- int off = ooc_message.toInt(&ok);
- if (ok) {
- if (off >= -100 && off <= 100) {
- offset_with_pair = off;
- QString msg = tr("You have set your offset to ");
- msg.append(QString::number(off));
- msg.append("%.");
- append_server_chatmessage("CLIENT", msg, "1");
- }
- else {
- append_server_chatmessage(
- "CLIENT", tr("Your offset must be between -100% and 100%!"), "1");
- }
- }
- else {
- append_server_chatmessage("CLIENT",
- tr("That offset does not look like one."), "1");
- }
- return;
- }
- else if (ooc_message.startsWith("/switch_am")) {
- append_server_chatmessage(
- "CLIENT", tr("You switched your music and area list."), "1");
- on_switch_area_music_clicked();
- ui_ooc_chat_message->clear();
- return;
- }
- else if (ooc_message.startsWith("/enable_blocks")) {
- append_server_chatmessage("CLIENT",
- tr("You have forcefully enabled features that "
- "the server may not support. You may not be "
- "able to talk IC, or worse, because of this."),
- "1");
- ao_app->cccc_ic_support_enabled = true;
- ao_app->arup_enabled = true;
- ao_app->modcall_reason_enabled = true;
- on_reload_theme_clicked();
- ui_ooc_chat_message->clear();
- return;
- }
- else if (ooc_message.startsWith("/non_int_pre")) {
- if (ui_pre_non_interrupt->isChecked())
- append_server_chatmessage(
- "CLIENT", tr("Your pre-animations interrupt again."), "1");
- else
- append_server_chatmessage(
- "CLIENT", tr("Your pre-animations will not interrupt text."), "1");
- ui_pre_non_interrupt->setChecked(!ui_pre_non_interrupt->isChecked());
- ui_ooc_chat_message->clear();
- return;
- }
- else if (ooc_message.startsWith("/save_chatlog")) {
- QFile file("chatlog.txt");
-
- if (!file.open(QIODevice::WriteOnly | QIODevice::Text |
- QIODevice::Truncate)) {
- append_server_chatmessage(
- "CLIENT", tr("Couldn't open chatlog.txt to write into."), "1");
- ui_ooc_chat_message->clear();
- return;
- }
-
- QTextStream out(&file);
-
- foreach (chatlogpiece item, ic_chatlog_history) {
- out << item.get_full() << '\n';
- }
-
- file.close();
-
- append_server_chatmessage("CLIENT", tr("The IC chatlog has been saved."),
- "1");
- ui_ooc_chat_message->clear();
- return;
- }
- else if (ooc_message.startsWith("/load_case")) {
- QStringList command = ooc_message.split(" ", QString::SkipEmptyParts);
-
- QDir casefolder("base/cases");
- if (!casefolder.exists()) {
- QDir::current().mkdir("base/" + casefolder.dirName());
- append_server_chatmessage(
- "CLIENT",
- tr("You don't have a `base/cases/` folder! It was just made for you, "
- "but seeing as it WAS just made for you, it's likely the case "
- "file you're looking for can't be found in there."),
- "1");
- ui_ooc_chat_message->clear();
- return;
- }
- QStringList caseslist = casefolder.entryList();
- caseslist.removeOne(".");
- caseslist.removeOne("..");
- caseslist.replaceInStrings(".ini", "");
-
- if (command.size() < 2) {
- append_server_chatmessage(
- "CLIENT",
- tr("You need to give a filename to load (extension not needed)! Make "
- "sure that it is in the `base/cases/` folder, and that it is a "
- "correctly formatted ini.\nCases you can load: %1")
- .arg(caseslist.join(", ")),
- "1");
- ui_ooc_chat_message->clear();
- return;
- }
-
- if (command.size() > 2) {
- append_server_chatmessage(
- "CLIENT",
- tr("Too many arguments to load a case! You only need one filename, "
- "without extension."),
- "1");
- ui_ooc_chat_message->clear();
- return;
- }
-
- QSettings casefile("base/cases/" + command[1] + ".ini",
- QSettings::IniFormat);
-
- QString caseauth = casefile.value("author", "").value<QString>();
- QString casedoc = casefile.value("doc", "").value<QString>();
- QString cmdoc = casefile.value("cmdoc", "").value<QString>();
- QString casestatus = casefile.value("status", "").value<QString>();
-
- if (!caseauth.isEmpty())
- append_server_chatmessage("CLIENT", tr("Case made by %1.").arg(caseauth),
- "1");
- if (!casedoc.isEmpty())
- ao_app->send_server_packet(new AOPacket("CT#" + ui_ooc_chat_name->text() +
- "#/doc " + casedoc + "#%"));
- if (!casestatus.isEmpty())
- ao_app->send_server_packet(new AOPacket("CT#" + ui_ooc_chat_name->text() +
- "#/status " + casestatus + "#%"));
- if (!cmdoc.isEmpty())
- append_server_chatmessage(
- "CLIENT", tr("Navigate to %1 for the CM doc.").arg(cmdoc), "1");
-
- for (int i = local_evidence_list.size() - 1; i >= 0; i--) {
- ao_app->send_server_packet(
- new AOPacket("DE#" + QString::number(i) + "#%"));
- }
-
- foreach (QString evi, casefile.childGroups()) {
- if (evi == "General")
- continue;
-
- QStringList f_contents;
-
- f_contents.append(
- casefile.value(evi + "/name", "UNKNOWN").value<QString>());
- f_contents.append(
- casefile.value(evi + "/description", "UNKNOWN").value<QString>());
- f_contents.append(
- casefile.value(evi + "/image", "UNKNOWN.png").value<QString>());
-
- ao_app->send_server_packet(new AOPacket("PE", f_contents));
- }
- append_server_chatmessage(
- "CLIENT", tr("Your case \"%1\" was loaded!").arg(command[1]), "1");
- ui_ooc_chat_message->clear();
- return;
- }
- else if (ooc_message.startsWith("/save_case")) {
- QStringList command = ooc_message.split(" ", QString::SkipEmptyParts);
-
- QDir casefolder("base/cases");
- if (!casefolder.exists()) {
- QDir::current().mkdir("base/" + casefolder.dirName());
- append_server_chatmessage(
- "CLIENT",
- tr("You don't have a `base/cases/` folder! It was just made for you, "
- "but seeing as it WAS just made for you, it's likely that you "
- "somehow deleted it."),
- "1");
- ui_ooc_chat_message->clear();
- return;
- }
- QStringList caseslist = casefolder.entryList();
- caseslist.removeOne(".");
- caseslist.removeOne("..");
- caseslist.replaceInStrings(".ini", "");
-
- if (command.size() < 3) {
- append_server_chatmessage(
- "CLIENT",
- tr("You need to give a filename to save (extension not needed) and "
- "the courtroom status!"),
- "1");
- ui_ooc_chat_message->clear();
- return;
- }
-
- if (command.size() > 3) {
- append_server_chatmessage(
- "CLIENT",
- tr("Too many arguments to save a case! You only need a filename "
- "without extension and the courtroom status."),
- "1");
- ui_ooc_chat_message->clear();
- return;
- }
- QSettings casefile("base/cases/" + command[1] + ".ini",
- QSettings::IniFormat);
- casefile.setValue("author", ui_ooc_chat_name->text());
- casefile.setValue("cmdoc", "");
- casefile.setValue("doc", "");
- casefile.setValue("status", command[2]);
- casefile.sync();
- for (int i = local_evidence_list.size() - 1; i >= 0; i--) {
- QString clean_evidence_dsc = local_evidence_list[i].description.replace(
- QRegularExpression("<owner = ...>..."), "");
- clean_evidence_dsc = clean_evidence_dsc.replace(
- clean_evidence_dsc.lastIndexOf(">"), 1, "");
- casefile.beginGroup(QString::number(i));
- casefile.sync();
- casefile.setValue("name", local_evidence_list[i].name);
- casefile.setValue("description", local_evidence_list[i].description);
- casefile.setValue("image", local_evidence_list[i].image);
- casefile.endGroup();
- }
- casefile.sync();
- append_server_chatmessage(
- "CLIENT", tr("Succesfully saved, edit doc and cmdoc link on the ini!"),
- "1");
- ui_ooc_chat_message->clear();
- return;
- }
- else if (ooc_message.startsWith("/clearooc")) {
- ui_server_chatlog->clear();
- ui_ooc_chat_message->clear();
- return;
- }
- else if (ooc_message.startsWith("/version")) {
- append_server_chatmessage("CLIENT", ao_app->get_version_string(), "1");
- ui_ooc_chat_message->clear();
- return;
- }
-
- QStringList packet_contents;
- packet_contents.append(ui_ooc_chat_name->text());
- packet_contents.append(ooc_message);
-
- AOPacket *f_packet = new AOPacket("CT", packet_contents);
-
- if (server_ooc)
- ao_app->send_server_packet(f_packet);
- else
- ao_app->send_ms_packet(f_packet);
-
- ui_ooc_chat_message->clear();
-
- ui_ooc_chat_message->setFocus();
-}
-
-void Courtroom::on_ooc_toggle_clicked()
-{
- if (server_ooc) {
- ui_ms_chatlog->show();
- ui_server_chatlog->hide();
- ui_ooc_toggle->setText(tr(""));
- ui_ooc_toggle->set_image("ooc_toggle_ms.png");
- if (ooc_toggle_fallback) {
- ui_ooc_toggle->setText(tr("Master"));
- }
- server_ooc = false;
- }
- else {
- ui_ms_chatlog->hide();
- ui_server_chatlog->show();
- ui_ooc_toggle->setText(tr(""));
- ui_ooc_toggle->set_image("ooc_toggle_server.png");
- if (ooc_toggle_fallback) {
- ui_ooc_toggle->setText(tr("Server"));
- }
- server_ooc = true;
- }
-}
-
-void Courtroom::on_music_search_keypr()
-{
- if (ui_music_search->text() == "") {
- ui_music_list->collapseAll();
- }
-}
-
-void Courtroom::on_music_search_edited(QString p_text)
-{
- // preventing compiler warnings
- p_text += "a";
- list_music();
- list_areas();
-}
-
-void Courtroom::on_pos_dropdown_changed(int p_index)
-{
- ui_ic_chat_message->setFocus();
-
- if (p_index < 0 || p_index > 7)
- return;
-
- toggle_judge_buttons(false);
-
- QString f_pos;
-
- switch (p_index) {
- case 0:
- f_pos = "wit";
- break;
- case 1:
- f_pos = "def";
- break;
- case 2:
- f_pos = "pro";
- break;
- case 3:
- f_pos = "jud";
- toggle_judge_buttons(true);
- break;
- case 4:
- f_pos = "hld";
- break;
- case 5:
- f_pos = "hlp";
- break;
- case 6:
- f_pos = "jur";
- break;
- case 7:
- f_pos = "sea";
- break;
- default:
- f_pos = "";
- }
-
- if (f_pos == "" || ui_ooc_chat_name->text() == "")
- return;
-
- ao_app->send_server_packet(
- new AOPacket("CT#" + ui_ooc_chat_name->text() + "#/pos " + f_pos + "#%"));
-}
-
-void Courtroom::on_mute_list_clicked(QModelIndex p_index)
-{
- QListWidgetItem *f_item = ui_mute_list->item(p_index.row());
- QString f_char = f_item->text();
- QString real_char;
-
- if (f_char.endsWith(" [x]"))
- real_char = f_char.left(f_char.size() - 4);
- else
- real_char = f_char;
-
- int f_cid = -1;
-
- for (int n_char = 0; n_char < char_list.size(); n_char++) {
- if (char_list.at(n_char).name == real_char)
- f_cid = n_char;
- }
-
- if (f_cid < 0 || f_cid >= char_list.size()) {
- qDebug() << "W: " << real_char << " not present in char_list";
- return;
- }
-
- if (mute_map.value(f_cid)) {
- mute_map.insert(f_cid, false);
- f_item->setText(real_char);
- }
- else {
- mute_map.insert(f_cid, true);
- f_item->setText(real_char + " [x]");
- }
-}
-
-void Courtroom::on_pair_list_clicked(QModelIndex p_index)
-{
- QListWidgetItem *f_item = ui_pair_list->item(p_index.row());
- QString f_char = f_item->text();
- QString real_char;
- int f_cid = -1;
-
- if (f_char.endsWith(" [x]")) {
- real_char = f_char.left(f_char.size() - 4);
- f_item->setText(real_char);
- }
- else {
- real_char = f_char;
- for (int n_char = 0; n_char < char_list.size(); n_char++) {
- if (char_list.at(n_char).name == real_char)
- f_cid = n_char;
- }
- }
-
- if (f_cid < -2 || f_cid >= char_list.size()) {
- qDebug() << "W: " << real_char << " not present in char_list";
- return;
- }
-
- other_charid = f_cid;
-
- // Redo the character list.
- QStringList sorted_pair_list;
-
- for (char_type i_char : char_list)
- sorted_pair_list.append(i_char.name);
-
- sorted_pair_list.sort();
-
- for (int i = 0; i < ui_pair_list->count(); i++) {
- ui_pair_list->item(i)->setText(sorted_pair_list.at(i));
- }
- if (other_charid != -1) {
- f_item->setText(real_char + " [x]");
- }
-}
-
-void Courtroom::on_music_list_double_clicked(QTreeWidgetItem *p_item,
- int column)
-{
- if (is_muted)
- return;
-
- column = 1; // Column 1 is always the metadata (which we want)
- QString p_song = p_item->text(column);
- if (!ui_ic_chat_name->text().isEmpty() && ao_app->cccc_ic_support_enabled) {
- ao_app->send_server_packet(new AOPacket("MC#" + p_song + "#" +
- QString::number(m_cid) + "#" +
- ui_ic_chat_name->text() + "#%"),
- false);
- }
- else {
- ao_app->send_server_packet(
- new AOPacket("MC#" + p_song + "#" + QString::number(m_cid) + "#%"),
- false);
- }
-}
-
-void Courtroom::on_area_list_double_clicked(QModelIndex p_model)
-
-{
-
- QString p_area = area_list.at(area_row_to_number.at(p_model.row()));
-
- ao_app->send_server_packet(
- new AOPacket("MC#" + p_area + "#" + QString::number(m_cid) + "#%"),
- false);
-}
-
-void Courtroom::on_hold_it_clicked()
-{
- if (objection_state == 1) {
- ui_hold_it->set_image("holdit.png");
- objection_state = 0;
- }
- else {
- ui_objection->set_image("objection.png");
- ui_take_that->set_image("takethat.png");
- ui_custom_objection->set_image("custom.png");
-
- ui_hold_it->set_image("holdit_selected.png");
- objection_state = 1;
- }
-
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_objection_clicked()
-{
- if (objection_state == 2) {
- ui_objection->set_image("objection.png");
- objection_state = 0;
- }
- else {
- ui_hold_it->set_image("holdit.png");
- ui_take_that->set_image("takethat.png");
- ui_custom_objection->set_image("custom.png");
-
- ui_objection->set_image("objection_selected.png");
- objection_state = 2;
- }
-
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_take_that_clicked()
-{
- if (objection_state == 3) {
- ui_take_that->set_image("takethat.png");
- objection_state = 0;
- }
- else {
- ui_objection->set_image("objection.png");
- ui_hold_it->set_image("holdit.png");
- ui_custom_objection->set_image("custom.png");
-
- ui_take_that->set_image("takethat_selected.png");
- objection_state = 3;
- }
-
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_custom_objection_clicked()
-{
- if (objection_state == 4) {
- ui_custom_objection->set_image("custom.png");
- objection_state = 0;
- objection_custom = "";
- }
- else {
- ui_objection->set_image("objection.png");
- ui_take_that->set_image("takethat.png");
- ui_hold_it->set_image("holdit.png");
- ui_custom_objection->set_image("custom_selected.png");
- objection_state = 4;
- }
-
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::ShowContextMenu(const QPoint &pos)
-{
- QPoint globalPos = ui_custom_objection->mapToGlobal(pos);
- QAction *selecteditem = custom_obj_menu->exec(globalPos);
- if (selecteditem) {
- ui_objection->set_image("objection.png");
- ui_take_that->set_image("takethat.png");
- ui_hold_it->set_image("holdit.png");
- ui_custom_objection->set_image("custom_selected.png");
- objection_custom = selecteditem->text();
- objection_state = 4;
- }
-}
-
-void Courtroom::on_realization_clicked()
-{
- if (realization_state == 0) {
- realization_state = 1;
- ui_realization->set_image("realization_pressed.png");
- }
- else {
- realization_state = 0;
- ui_realization->set_image("realization.png");
- }
-
- ui_ic_chat_message->setFocus();
-}
-void Courtroom::on_screenshake_clicked()
-{
- if (screenshake_state == 0) {
- screenshake_state = 1;
- ui_screenshake->set_image("screenshake_pressed.png");
- }
- else {
- screenshake_state = 0;
- ui_screenshake->set_image("screenshake.png");
- }
-
- ui_ic_chat_message->setFocus();
-}
-void Courtroom::on_mute_clicked()
-{
- if (ui_mute_list->isHidden()) {
- ui_mute_list->show();
- ui_pair_list->hide();
- ui_pair_offset_spinbox->hide();
- ui_pair_button->set_image("pair_button.png");
- ui_mute->set_image("mute_pressed.png");
- }
- else {
- ui_mute_list->hide();
- ui_mute->set_image("mute.png");
- }
-}
-
-void Courtroom::on_pair_clicked()
-{
- if (ui_pair_list->isHidden()) {
- ui_pair_list->show();
- ui_pair_offset_spinbox->show();
- ui_mute_list->hide();
- ui_mute->set_image("mute.png");
- ui_pair_button->set_image("pair_button_pressed.png");
- }
- else {
- ui_pair_list->hide();
- ui_pair_offset_spinbox->hide();
- ui_pair_button->set_image("pair_button.png");
- }
-}
-
-void Courtroom::on_defense_minus_clicked()
-{
- int f_state = defense_bar_state - 1;
-
- if (f_state >= 0)
- ao_app->send_server_packet(
- new AOPacket("HP#1#" + QString::number(f_state) + "#%"));
-}
-
-void Courtroom::on_defense_plus_clicked()
-{
- int f_state = defense_bar_state + 1;
-
- if (f_state <= 10)
- ao_app->send_server_packet(
- new AOPacket("HP#1#" + QString::number(f_state) + "#%"));
-}
-
-void Courtroom::on_prosecution_minus_clicked()
-{
- int f_state = prosecution_bar_state - 1;
-
- if (f_state >= 0)
- ao_app->send_server_packet(
- new AOPacket("HP#2#" + QString::number(f_state) + "#%"));
-}
-
-void Courtroom::on_prosecution_plus_clicked()
-{
- int f_state = prosecution_bar_state + 1;
-
- if (f_state <= 10)
- ao_app->send_server_packet(
- new AOPacket("HP#2#" + QString::number(f_state) + "#%"));
-}
-
-void Courtroom::on_text_color_changed(int p_color)
-{
- text_color = p_color;
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_music_slider_moved(int p_value)
-{
- music_player->set_volume(p_value);
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_sfx_slider_moved(int p_value)
-{
- sfx_player->set_volume(p_value);
- objection_player->set_volume(p_value);
- misc_sfx_player->set_volume(p_value);
- frame_emote_sfx_player->set_volume(p_value);
- pair_frame_emote_sfx_player->set_volume(p_value);
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_blip_slider_moved(int p_value)
-{
- blip_player->set_volume(p_value);
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_log_limit_changed(int value) { log_maximum_blocks = value; }
-
-void Courtroom::on_pair_offset_changed(int value) { offset_with_pair = value; }
-
-void Courtroom::on_witness_testimony_clicked()
-{
- if (is_muted)
- return;
-
- ao_app->send_server_packet(new AOPacket("RT#testimony1#%"));
-
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_cross_examination_clicked()
-{
- if (is_muted)
- return;
-
- ao_app->send_server_packet(new AOPacket("RT#testimony2#%"));
-
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_not_guilty_clicked()
-{
- if (is_muted)
- return;
-
- ao_app->send_server_packet(new AOPacket("RT#judgeruling#0#%"));
-
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_guilty_clicked()
-{
- if (is_muted)
- return;
-
- ao_app->send_server_packet(new AOPacket("RT#judgeruling#1#%"));
-
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_change_character_clicked()
-{
- music_player->set_volume(0);
- sfx_player->set_volume(0);
- sfx_player->set_volume(0);
- blip_player->set_volume(0);
-
- set_char_select();
-
- ui_char_select_background->show();
- ui_spectator->hide();
-}
-
-void Courtroom::on_reload_theme_clicked()
-{
- ao_app->reload_theme();
- punctuation_modifier = ao_app->get_pundelay();
- slower_blips = ao_app->get_slower_blips();
- colorf_iclog = ao_app->get_colored_iclog_enabled();
- mirror_iclog = ao_app->get_iclmir_enabled();
- colorf_limit = ao_app->colorlog_restricted_enabled();
- keep_evidence_display = ao_app->is_keepevi_enabled();
- // to update status on the background
- set_background(current_background);
- // to update fallback text bools
- detect_fallback_text();
- enter_courtroom(m_cid);
-
- anim_state = 4;
- text_state = 3;
-}
-
-void Courtroom::on_back_to_lobby_clicked()
-{
- ao_app->construct_lobby();
- ao_app->destruct_courtroom();
-}
-
-void Courtroom::on_char_select_left_clicked()
-{
- --current_char_page;
- set_char_select_page();
-}
-
-void Courtroom::on_char_select_right_clicked()
-{
- ++current_char_page;
- set_char_select_page();
-}
-
-void Courtroom::on_spectator_clicked()
-{
- this->set_character(-1);
-
- ui_emotes->hide();
-
- ui_char_select_background->hide();
-}
-
-void Courtroom::on_call_mod_clicked()
-{
- if (ao_app->modcall_reason_enabled) {
- QMessageBox errorBox;
- QInputDialog input;
-
- input.setWindowFlags(Qt::WindowSystemMenuHint);
- input.setLabelText(tr("Reason:"));
- input.setWindowTitle(tr("Call Moderator"));
- auto code = input.exec();
-
- if (code != QDialog::Accepted)
- return;
-
- QString text = input.textValue();
- if (text.isEmpty()) {
- errorBox.critical(nullptr, tr("Error"), tr("You must provide a reason."));
- return;
- }
- else if (text.length() > 256) {
- errorBox.critical(nullptr, tr("Error"), tr("The message is too long."));
- return;
- }
-
- QStringList mod_reason;
- mod_reason.append(text);
-
- ao_app->send_server_packet(new AOPacket("ZZ", mod_reason));
- }
- else {
- ao_app->send_server_packet(new AOPacket("ZZ#%"));
- }
-
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_settings_clicked() { ao_app->call_settings_menu(); }
-
-void Courtroom::on_announce_casing_clicked()
-{
- ao_app->call_announce_menu(this);
-}
-
-void Courtroom::on_pre_clicked() { ui_ic_chat_message->setFocus(); }
-
-void Courtroom::on_flip_clicked() { ui_ic_chat_message->setFocus(); }
-
-void Courtroom::on_guard_clicked() { ui_ic_chat_message->setFocus(); }
-
-void Courtroom::on_showname_enable_clicked()
-{
-
- refresh_iclog(false);
- ui_ic_chat_message->setFocus();
-}
-
-void Courtroom::on_evidence_button_clicked()
-{
- if (ui_evidence->isHidden()) {
- ui_evidence->show();
- ui_evidence_overlay->hide();
- }
- else {
- ui_evidence->hide();
- }
-}
-
-void Courtroom::on_switch_area_music_clicked()
-{
-
- if (ui_area_list->isHidden()) {
- music_search_par = ui_music_search->text();
- ui_music_search->setText(area_search_par);
- ui_area_list->show();
- ui_music_list->hide();
- }
- else {
- area_search_par = ui_music_search->text();
- ui_music_search->setText(music_search_par);
- ui_area_list->hide();
- ui_music_list->show();
- }
-}
-
-void Courtroom::ping_server()
-{
- ao_app->send_server_packet(
- new AOPacket("CH#" + QString::number(m_cid) + "#%"));
-}
-
-void Courtroom::on_casing_clicked()
-{
- if (ao_app->casing_alerts_enabled) {
- if (ui_casing->isChecked()) {
- QStringList f_packet;
-
- f_packet.append(ao_app->get_casing_can_host_cases());
- f_packet.append(QString::number(ao_app->get_casing_cm_enabled()));
- f_packet.append(QString::number(ao_app->get_casing_defence_enabled()));
- f_packet.append(
- QString::number(ao_app->get_casing_prosecution_enabled()));
- f_packet.append(QString::number(ao_app->get_casing_judge_enabled()));
- f_packet.append(QString::number(ao_app->get_casing_juror_enabled()));
- f_packet.append(QString::number(ao_app->get_casing_steno_enabled()));
- f_packet.append(QString::number(ao_app->get_casing_wit_enabled()));
-
- ao_app->send_server_packet(new AOPacket("SETCASE", f_packet));
- }
- else
- ao_app->send_server_packet(new AOPacket("SETCASE#\"\"#0#0#0#0#0#0#0#%"));
- }
-}
-
-void Courtroom::announce_case(QString title, bool def, bool pro, bool jud,
- bool jur, bool steno, bool wit)
-{
- if (ao_app->casing_alerts_enabled) {
- QStringList f_packet;
-
- f_packet.append(title);
- f_packet.append(QString::number(def));
- f_packet.append(QString::number(pro));
- f_packet.append(QString::number(jud));
- f_packet.append(QString::number(jur));
- f_packet.append(QString::number(steno));
- f_packet.append(QString::number(wit));
-
- ao_app->send_server_packet(new AOPacket("CASEA", f_packet));
- }
-}
-
-Courtroom::~Courtroom()
-{
- delete music_player;
- delete sfx_player;
- delete objection_player;
- delete blip_player;
-}
-
-void Courtroom::refresh_iclog(bool skiplast)
-{
- ui_ic_chatlog->clear();
- first_message_sent = false;
-
- foreach (chatlogpiece item, ic_chatlog_history) {
- if (skiplast && ic_chatlog_history.last().get_full() == item.get_full()) {
- break;
- }
- if (ui_showname_enable->isChecked()) {
- if (item.get_is_song())
- append_ic_text(item.get_message(), item.get_showname(), true, false,
- false);
- else
- append_ic_text(item.get_message(), item.get_showname(), false, true,
- true, item.get_chat_color());
- }
- else {
- if (item.get_is_song())
- append_ic_text(item.get_message(), item.get_name(), true, false, true);
- else
- append_ic_text(item.get_message(), item.get_name(), false, true, false,
- item.get_chat_color());
- }
- }
-}
-
-#ifdef BASSAUDIO
-#if (defined(_WIN32) || defined(_WIN64))
-void Courtroom::load_bass_opus_plugin() { BASS_PluginLoad("bassopus.dll", 0); }
-#elif (defined(LINUX) || defined(__linux__))
-void Courtroom::load_bass_opus_plugin()
-{
- BASS_PluginLoad("libbassopus.so", 0);
-}
-#elif defined __APPLE__
-void Courtroom::load_bass_opus_plugin()
-{
- QString libpath =
- ao_app->get_base_path() + "../../Frameworks/libbassopus.dylib";
- QByteArray ba = libpath.toLocal8Bit();
- BASS_PluginLoad(ba.data(), 0);
-}
-#else
-#error This operating system is unsupported for bass plugins.
-#endif
-#endif
+#include "courtroom.h"
+
+Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
+{
+ ao_app = p_ao_app;
+#ifdef BASSAUDIO
+ // Change the default audio output device to be the one the user has given
+ // in his config.ini file for now.
+ unsigned int a = 0;
+ BASS_DEVICEINFO info;
+
+ if (ao_app->get_audio_output_device() == "default") {
+ BASS_Init(-1, 48000, BASS_DEVICE_LATENCY, nullptr, nullptr);
+ load_bass_opus_plugin();
+ }
+ else {
+ for (a = 0; BASS_GetDeviceInfo(a, &info); a++) {
+ if (ao_app->get_audio_output_device() == info.name) {
+ BASS_SetDevice(a);
+ BASS_Init(static_cast<int>(a), 48000, BASS_DEVICE_LATENCY, nullptr,
+ nullptr);
+ load_bass_opus_plugin();
+ qDebug() << info.name << "was set as the default audio output device.";
+ break;
+ }
+ }
+ }
+#elif defined QTAUDIO
+
+ if (ao_app->get_audio_output_device() != "default") {
+ foreach (const QAudioDeviceInfo &deviceInfo,
+ QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) {
+ if (ao_app->get_audio_output_device() == deviceInfo.deviceName()) {
+ ao_app->QtAudioDevice = deviceInfo;
+ qDebug() << deviceInfo.deviceName()
+ << "was set as the default audio output device.";
+ break;
+ }
+ }
+ }
+#endif
+
+ qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch() / 1000));
+
+ keepalive_timer = new QTimer(this);
+ keepalive_timer->start(60000);
+
+ chat_tick_timer = new QTimer(this);
+
+ text_delay_timer = new QTimer(this);
+ text_delay_timer->setSingleShot(true);
+
+ sfx_delay_timer = new QTimer(this);
+ sfx_delay_timer->setSingleShot(true);
+
+ music_player = new AOMusicPlayer(this, ao_app);
+ music_player->set_volume(0);
+
+ sfx_player = new AOSfxPlayer(this, ao_app);
+ sfx_player->set_volume(0);
+
+ objection_player = new AOSfxPlayer(this, ao_app);
+ objection_player->set_volume(0);
+
+ blip_player = new AOBlipPlayer(this, ao_app);
+ blip_player->set_volume(0);
+
+ modcall_player = new AOSfxPlayer(this, ao_app);
+ modcall_player->set_volume(50);
+
+ ui_background = new AOImage(this, ao_app);
+
+ ui_viewport = new QWidget(this);
+ ui_vp_background = new AOScene(ui_viewport, ao_app);
+ ui_vp_speedlines = new AOMovie(ui_viewport, ao_app);
+ ui_vp_speedlines->set_play_once(false);
+ ui_vp_player_char = new AOCharMovie(ui_viewport, ao_app);
+ ui_vp_sideplayer_char = new AOCharMovie(ui_viewport, ao_app);
+ ui_vp_sideplayer_char->hide();
+ ui_vp_desk = new AOScene(ui_viewport, ao_app);
+ ui_vp_legacy_desk = new AOScene(ui_viewport, ao_app);
+
+ ui_vp_evidence_display = new AOEvidenceDisplay(ui_viewport, ao_app);
+
+ ui_vp_chatbox = new AOImage(this, ao_app);
+ ui_vp_showname = new QLabel(ui_vp_chatbox);
+ ui_vp_showname->setAlignment(Qt::AlignLeft);
+ ui_vp_chat_arrow = new AOMovie(ui_vp_chatbox, ao_app);
+ ui_vp_chat_arrow->set_play_once(false);
+
+ ui_vp_message = new QTextEdit(this);
+ ui_vp_message->setFrameStyle(QFrame::NoFrame);
+ ui_vp_message->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ ui_vp_message->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ ui_vp_message->setReadOnly(true);
+
+ ui_vp_testimony = new AOMovie(this, ao_app);
+ ui_vp_testimony->set_play_once(false);
+ ui_vp_testimony->setAttribute(Qt::WA_TransparentForMouseEvents);
+ ui_vp_effect = new AOMovie(this, ao_app);
+ ui_vp_effect->setAttribute(Qt::WA_TransparentForMouseEvents);
+ ui_vp_wtce = new AOMovie(this, ao_app);
+ ui_vp_wtce->setAttribute(Qt::WA_TransparentForMouseEvents);
+ ui_vp_objection = new AOMovie(this, ao_app);
+ ui_vp_objection->setAttribute(Qt::WA_TransparentForMouseEvents);
+
+ ui_ic_chatlog = new QTextEdit(this);
+ ui_ic_chatlog->setReadOnly(true);
+
+ log_maximum_blocks = ao_app->get_max_log_size();
+ log_goes_downwards = ao_app->get_log_goes_downwards();
+
+ ui_ms_chatlog = new AOTextArea(this);
+ ui_ms_chatlog->setReadOnly(true);
+ ui_ms_chatlog->setOpenExternalLinks(true);
+ ui_ms_chatlog->hide();
+
+ ui_server_chatlog = new AOTextArea(this);
+ ui_server_chatlog->setReadOnly(true);
+ ui_server_chatlog->setOpenExternalLinks(true);
+
+ ui_area_list = new QTreeWidget(this);
+ ui_area_list->setColumnCount(2);
+ ui_area_list->hideColumn(0);
+ ui_area_list->setHeaderHidden(true);
+ ui_area_list->header()->setStretchLastSection(false);
+ ui_area_list->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
+ ui_area_list->hide();
+
+ ui_music_list = new QTreeWidget(this);
+ ui_music_list->setColumnCount(2);
+ ui_music_list->hideColumn(1);
+ ui_music_list->setHeaderHidden(true);
+ ui_music_list->header()->setStretchLastSection(false);
+ ui_music_list->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
+ ui_music_list->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ ui_music_display = new AOMovie(this, ao_app);
+ ui_music_display->set_play_once(false);
+ ui_music_display->setAttribute(Qt::WA_TransparentForMouseEvents);
+
+ ui_music_name = new ScrollText(ui_music_display);
+ ui_music_name->setText(tr("None"));
+ ui_music_name->setAttribute(Qt::WA_TransparentForMouseEvents);
+
+ ui_ic_chat_name = new QLineEdit(this);
+ ui_ic_chat_name->setFrame(false);
+ ui_ic_chat_name->setPlaceholderText(tr("Showname"));
+
+ ui_ic_chat_message = new AOLineEdit(this);
+ ui_ic_chat_message->setFrame(false);
+ ui_ic_chat_message->setPlaceholderText(tr("Message"));
+ ui_ic_chat_message->preserve_selection(true);
+ // ui_ic_chat_message->setValidator(new QRegExpValidator(QRegExp("^\\S+(?:
+ // \\S+)*$"), ui_ic_chat_message));
+ // todo: filter out \n from showing up as that commonly breaks the chatlog and
+ // can be spammed to hell
+
+ ui_muted = new AOImage(ui_ic_chat_message, ao_app);
+ ui_muted->hide();
+
+ ui_ooc_chat_message = new QLineEdit(this);
+ ui_ooc_chat_message->setFrame(false);
+
+ ui_ooc_chat_name = new QLineEdit(this);
+ ui_ooc_chat_name->setFrame(false);
+ ui_ooc_chat_name->setPlaceholderText(tr("Name"));
+ ui_ooc_chat_name->setMaxLength(30);
+ ui_ooc_chat_name->setText(p_ao_app->get_default_username());
+
+ // ui_area_password = new QLineEdit(this);
+ // ui_area_password->setFrame(false);
+ ui_music_search = new QLineEdit(this);
+ ui_music_search->setFrame(false);
+ ui_music_search->setPlaceholderText(tr("Search"));
+
+ initialize_emotes();
+
+ ui_pos_dropdown = new QComboBox(this);
+
+ ui_iniswap_dropdown = new QComboBox(this);
+ ui_iniswap_dropdown->setContextMenuPolicy(Qt::CustomContextMenu);
+ ui_iniswap_remove = new AOButton(this, ao_app);
+
+ ui_sfx_dropdown = new QComboBox(this);
+ ui_sfx_dropdown->setContextMenuPolicy(Qt::CustomContextMenu);
+ ui_sfx_remove = new AOButton(this, ao_app);
+
+ ui_effects_dropdown = new QComboBox(this);
+ ui_effects_dropdown->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ ui_defense_bar = new AOImage(this, ao_app);
+ ui_prosecution_bar = new AOImage(this, ao_app);
+
+ ui_music_label = new QLabel(this);
+ ui_sfx_label = new QLabel(this);
+ ui_blip_label = new QLabel(this);
+
+ ui_hold_it = new AOButton(this, ao_app);
+ ui_objection = new AOButton(this, ao_app);
+ ui_take_that = new AOButton(this, ao_app);
+
+ ui_ooc_toggle = new AOButton(this, ao_app);
+ ui_witness_testimony = new AOButton(this, ao_app);
+ ui_cross_examination = new AOButton(this, ao_app);
+ ui_guilty = new AOButton(this, ao_app);
+ ui_not_guilty = new AOButton(this, ao_app);
+
+ ui_change_character = new AOButton(this, ao_app);
+ ui_reload_theme = new AOButton(this, ao_app);
+ ui_call_mod = new AOButton(this, ao_app);
+ ui_settings = new AOButton(this, ao_app);
+ ui_announce_casing = new AOButton(this, ao_app);
+ ui_switch_area_music = new AOButton(this, ao_app);
+
+ ui_pre = new QCheckBox(this);
+ ui_pre->setText(tr("Pre"));
+
+ ui_flip = new QCheckBox(this);
+ ui_flip->setText(tr("Flip"));
+ ui_flip->hide();
+
+ ui_guard = new QCheckBox(this);
+ ui_guard->setText(tr("Guard"));
+ ui_guard->hide();
+
+ ui_additive = new QCheckBox(this);
+ ui_additive->setText(tr("Additive"));
+ ui_additive->hide();
+
+ ui_casing = new QCheckBox(this);
+ ui_casing->setChecked(ao_app->get_casing_enabled());
+ ui_casing->setText(tr("Casing"));
+ ui_casing->hide();
+
+ ui_showname_enable = new QCheckBox(this);
+ ui_showname_enable->setChecked(ao_app->get_showname_enabled_by_default());
+ ui_showname_enable->setText(tr("Shownames"));
+
+ ui_pre_non_interrupt = new QCheckBox(this);
+ ui_pre_non_interrupt->setText(tr("No Interrupt"));
+ ui_pre_non_interrupt->hide();
+
+ ui_custom_objection = new AOButton(this, ao_app);
+ ui_custom_objection->setContextMenuPolicy(Qt::CustomContextMenu);
+ custom_obj_menu = new QMenu(this);
+ ui_realization = new AOButton(this, ao_app);
+ ui_screenshake = new AOButton(this, ao_app);
+ ui_mute = new AOButton(this, ao_app);
+
+ ui_defense_plus = new AOButton(this, ao_app);
+ ui_defense_minus = new AOButton(this, ao_app);
+
+ ui_prosecution_plus = new AOButton(this, ao_app);
+ ui_prosecution_minus = new AOButton(this, ao_app);
+
+ ui_text_color = new QComboBox(this);
+
+ ui_music_slider = new QSlider(Qt::Horizontal, this);
+ ui_music_slider->setRange(0, 100);
+ ui_music_slider->setValue(ao_app->get_default_music());
+
+ ui_sfx_slider = new QSlider(Qt::Horizontal, this);
+ ui_sfx_slider->setRange(0, 100);
+ ui_sfx_slider->setValue(ao_app->get_default_sfx());
+
+ ui_blip_slider = new QSlider(Qt::Horizontal, this);
+ ui_blip_slider->setRange(0, 100);
+ ui_blip_slider->setValue(ao_app->get_default_blip());
+
+ ui_mute_list = new QListWidget(this);
+
+ ui_pair_list = new QListWidget(this);
+ ui_pair_offset_spinbox = new QSpinBox(this);
+ ui_pair_offset_spinbox->setRange(-100, 100);
+ ui_pair_offset_spinbox->setSuffix(tr("% offset"));
+
+ ui_pair_order_dropdown = new QComboBox(this);
+ ui_pair_order_dropdown->addItem(tr("To front"));
+ ui_pair_order_dropdown->addItem(tr("To behind"));
+
+ ui_pair_button = new AOButton(this, ao_app);
+
+ ui_evidence_button = new AOButton(this, ao_app);
+
+ initialize_evidence();
+
+ construct_char_select();
+
+ connect(keepalive_timer, SIGNAL(timeout()), this, SLOT(ping_server()));
+
+ connect(ui_vp_objection, SIGNAL(done()), this, SLOT(objection_done()));
+ connect(ui_vp_player_char, SIGNAL(done()), this, SLOT(preanim_done()));
+ connect(ui_vp_player_char, SIGNAL(shake()), this, SLOT(do_screenshake()));
+ connect(ui_vp_player_char, SIGNAL(flash()), this, SLOT(do_flash()));
+ connect(ui_vp_player_char, SIGNAL(play_sfx(QString)), this,
+ SLOT(play_char_sfx(QString)));
+
+ connect(text_delay_timer, SIGNAL(timeout()), this,
+ SLOT(start_chat_ticking()));
+ connect(sfx_delay_timer, SIGNAL(timeout()), this, SLOT(play_sfx()));
+
+ connect(chat_tick_timer, SIGNAL(timeout()), this, SLOT(chat_tick()));
+
+ connect(ui_pos_dropdown, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(on_pos_dropdown_changed(int)));
+
+ connect(ui_iniswap_dropdown, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(on_iniswap_dropdown_changed(int)));
+ connect(ui_iniswap_dropdown, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(on_iniswap_context_menu_requested(QPoint)));
+ connect(ui_iniswap_remove, SIGNAL(clicked()), this,
+ SLOT(on_iniswap_remove_clicked()));
+
+ connect(ui_sfx_dropdown, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(on_sfx_dropdown_changed(int)));
+ connect(ui_sfx_dropdown, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(on_sfx_context_menu_requested(QPoint)));
+ connect(ui_sfx_remove, SIGNAL(clicked()), this,
+ SLOT(on_sfx_remove_clicked()));
+
+ connect(ui_effects_dropdown, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(on_effects_dropdown_changed(int)));
+ connect(ui_effects_dropdown, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(on_effects_context_menu_requested(QPoint)));
+
+ connect(ui_music_search, SIGNAL(returnPressed()), this,
+ SLOT(on_music_search_return_pressed()));
+ connect(ui_mute_list, SIGNAL(clicked(QModelIndex)), this,
+ SLOT(on_mute_list_clicked(QModelIndex)));
+
+ connect(ui_ic_chat_message, SIGNAL(returnPressed()), this,
+ SLOT(on_chat_return_pressed()));
+
+ connect(ui_ooc_chat_message, SIGNAL(returnPressed()), this,
+ SLOT(on_ooc_return_pressed()));
+
+ connect(ui_music_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
+ this, SLOT(on_music_list_double_clicked(QTreeWidgetItem *, int)));
+ connect(ui_music_list, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(on_music_list_context_menu_requested(QPoint)));
+
+ connect(ui_area_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this,
+ SLOT(on_area_list_double_clicked(QTreeWidgetItem *, int)));
+
+ connect(ui_hold_it, SIGNAL(clicked()), this, SLOT(on_hold_it_clicked()));
+ connect(ui_objection, SIGNAL(clicked()), this, SLOT(on_objection_clicked()));
+ connect(ui_take_that, SIGNAL(clicked()), this, SLOT(on_take_that_clicked()));
+ connect(ui_custom_objection, SIGNAL(clicked()), this,
+ SLOT(on_custom_objection_clicked()));
+ connect(ui_custom_objection,
+ SIGNAL(customContextMenuRequested(const QPoint &)), this,
+ SLOT(show_custom_objection_menu(const QPoint &)));
+
+ connect(ui_realization, SIGNAL(clicked()), this,
+ SLOT(on_realization_clicked()));
+ connect(ui_screenshake, SIGNAL(clicked()), this,
+ SLOT(on_screenshake_clicked()));
+
+ connect(ui_mute, SIGNAL(clicked()), this, SLOT(on_mute_clicked()));
+
+ connect(ui_defense_minus, SIGNAL(clicked()), this,
+ SLOT(on_defense_minus_clicked()));
+ connect(ui_defense_plus, SIGNAL(clicked()), this,
+ SLOT(on_defense_plus_clicked()));
+ connect(ui_prosecution_minus, SIGNAL(clicked()), this,
+ SLOT(on_prosecution_minus_clicked()));
+ connect(ui_prosecution_plus, SIGNAL(clicked()), this,
+ SLOT(on_prosecution_plus_clicked()));
+
+ connect(ui_text_color, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(on_text_color_changed(int)));
+
+ connect(ui_music_slider, SIGNAL(valueChanged(int)), this,
+ SLOT(on_music_slider_moved(int)));
+ connect(ui_sfx_slider, SIGNAL(valueChanged(int)), this,
+ SLOT(on_sfx_slider_moved(int)));
+ connect(ui_blip_slider, SIGNAL(valueChanged(int)), this,
+ SLOT(on_blip_slider_moved(int)));
+
+ connect(ui_ooc_toggle, SIGNAL(clicked()), this,
+ SLOT(on_ooc_toggle_clicked()));
+
+ connect(ui_music_search, SIGNAL(textChanged(QString)), this,
+ SLOT(on_music_search_edited(QString)));
+
+ connect(ui_witness_testimony, SIGNAL(clicked()), this,
+ SLOT(on_witness_testimony_clicked()));
+ connect(ui_cross_examination, SIGNAL(clicked()), this,
+ SLOT(on_cross_examination_clicked()));
+ connect(ui_guilty, SIGNAL(clicked()), this, SLOT(on_guilty_clicked()));
+ connect(ui_not_guilty, SIGNAL(clicked()), this,
+ SLOT(on_not_guilty_clicked()));
+
+ connect(ui_change_character, SIGNAL(clicked()), this,
+ SLOT(on_change_character_clicked()));
+ connect(ui_reload_theme, SIGNAL(clicked()), this,
+ SLOT(on_reload_theme_clicked()));
+ connect(ui_call_mod, SIGNAL(clicked()), this, SLOT(on_call_mod_clicked()));
+ connect(ui_settings, SIGNAL(clicked()), this, SLOT(on_settings_clicked()));
+ connect(ui_announce_casing, SIGNAL(clicked()), this,
+ SLOT(on_announce_casing_clicked()));
+ connect(ui_switch_area_music, SIGNAL(clicked()), this,
+ SLOT(on_switch_area_music_clicked()));
+
+ connect(ui_pre, SIGNAL(clicked()), this, SLOT(on_pre_clicked()));
+ connect(ui_flip, SIGNAL(clicked()), this, SLOT(on_flip_clicked()));
+ connect(ui_additive, SIGNAL(clicked()), this, SLOT(on_additive_clicked()));
+ connect(ui_guard, SIGNAL(clicked()), this, SLOT(on_guard_clicked()));
+ connect(ui_casing, SIGNAL(clicked()), this, SLOT(on_casing_clicked()));
+
+ connect(ui_showname_enable, SIGNAL(clicked()), this,
+ SLOT(on_showname_enable_clicked()));
+
+ connect(ui_pair_button, SIGNAL(clicked()), this, SLOT(on_pair_clicked()));
+ connect(ui_pair_list, SIGNAL(clicked(QModelIndex)), this,
+ SLOT(on_pair_list_clicked(QModelIndex)));
+ connect(ui_pair_offset_spinbox, SIGNAL(valueChanged(int)), this,
+ SLOT(on_pair_offset_changed(int)));
+ connect(ui_pair_order_dropdown, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(on_pair_order_dropdown_changed(int)));
+
+ connect(ui_evidence_button, SIGNAL(clicked()), this,
+ SLOT(on_evidence_button_clicked()));
+
+ set_widgets();
+
+ set_char_select();
+}
+
+void Courtroom::set_mute_list()
+{
+ mute_map.clear();
+
+ // maps which characters are muted based on cid, none are muted by default
+ for (int n_cid = 0; n_cid < char_list.size(); n_cid++) {
+ mute_map.insert(n_cid, false);
+ }
+
+ QStringList sorted_mute_list;
+
+ for (char_type i_char : char_list)
+ sorted_mute_list.append(i_char.name);
+
+ sorted_mute_list.sort();
+
+ for (QString i_name : sorted_mute_list) {
+ // mute_map.insert(i_name, false);
+ ui_mute_list->addItem(i_name);
+ }
+}
+
+void Courtroom::set_pair_list()
+{
+ QStringList sorted_pair_list;
+
+ for (char_type i_char : char_list)
+ sorted_pair_list.append(i_char.name);
+
+ sorted_pair_list.sort();
+
+ for (QString i_name : sorted_pair_list) {
+ ui_pair_list->addItem(i_name);
+ }
+}
+
+void Courtroom::set_widgets()
+{
+ blip_rate = ao_app->read_blip_rate();
+ blank_blip = ao_app->get_blank_blip();
+
+ QString filename = "courtroom_design.ini";
+
+ pos_size_type f_courtroom =
+ ao_app->get_element_dimensions("courtroom", filename);
+
+ if (f_courtroom.width < 0 || f_courtroom.height < 0) {
+ qDebug() << "W: did not find courtroom width or height in " << filename;
+
+ this->resize(714, 668);
+ }
+ else {
+ m_courtroom_width = f_courtroom.width;
+ m_courtroom_height = f_courtroom.height;
+
+ this->resize(f_courtroom.width, f_courtroom.height);
+ }
+
+ set_fonts();
+
+ ui_background->move(0, 0);
+ ui_background->resize(m_courtroom_width, m_courtroom_height);
+ ui_background->set_image("courtroombackground");
+
+ set_size_and_pos(ui_viewport, "viewport");
+
+ // If there is a point to it, show all CCCC features.
+ // We also do this this soon so that set_size_and_pos can hide them all later,
+ // if needed.
+ if (ao_app->cccc_ic_support_enabled) {
+ ui_pair_button->show();
+ ui_pre_non_interrupt->show();
+ ui_showname_enable->show();
+ ui_ic_chat_name->show();
+ ui_ic_chat_name->setEnabled(true);
+ }
+ else {
+ ui_pair_button->hide();
+ ui_pre_non_interrupt->hide();
+ ui_showname_enable->hide();
+ ui_ic_chat_name->hide();
+ ui_ic_chat_name->setEnabled(false);
+ }
+
+ if (ao_app->casing_alerts_enabled) {
+ ui_announce_casing->show();
+ ui_casing->show();
+ }
+ else {
+ ui_announce_casing->hide();
+ ui_casing->hide();
+ }
+
+ // We also show the non-server-dependent client additions.
+ // Once again, if the theme can't display it, set_move_and_pos will catch
+ // them.
+ ui_settings->show();
+
+ ui_vp_background->move(0, 0);
+ ui_vp_background->combo_resize(ui_viewport->width(), ui_viewport->height());
+
+ ui_vp_speedlines->move(0, 0);
+ ui_vp_speedlines->combo_resize(ui_viewport->width(), ui_viewport->height());
+
+ ui_vp_player_char->move(0, 0);
+ ui_vp_player_char->combo_resize(ui_viewport->width(), ui_viewport->height());
+
+ ui_vp_sideplayer_char->move(0, 0);
+ ui_vp_sideplayer_char->combo_resize(ui_viewport->width(),
+ ui_viewport->height());
+
+ // the AO2 desk element
+ ui_vp_desk->move(0, 0);
+ ui_vp_desk->combo_resize(ui_viewport->width(), ui_viewport->height());
+
+ // the size of the ui_vp_legacy_desk element relies on various factors and is
+ // set in set_scene()
+
+ double y_modifier = 147.0 / 192.0;
+ int final_y = static_cast<int>(y_modifier * ui_viewport->height());
+ ui_vp_legacy_desk->move(0, final_y);
+ ui_vp_legacy_desk->hide();
+
+ ui_vp_evidence_display->move(0, 0);
+ ui_vp_evidence_display->combo_resize(ui_viewport->width(),
+ ui_viewport->height());
+
+ ui_vp_chat_arrow->move(0, 0);
+ pos_size_type design_ini_result =
+ ao_app->get_element_dimensions("chat_arrow", "courtroom_design.ini");
+
+ if (design_ini_result.width < 0 || design_ini_result.height < 0) {
+ qDebug() << "W: could not find \"chat_arrow\" in courtroom_design.ini";
+ ui_vp_chat_arrow->hide();
+ }
+ else {
+ ui_vp_chat_arrow->move(design_ini_result.x, design_ini_result.y);
+ ui_vp_chat_arrow->combo_resize(design_ini_result.width,
+ design_ini_result.height);
+ }
+
+ ui_vp_testimony->move(ui_viewport->x(), ui_viewport->y());
+ ui_vp_testimony->combo_resize(ui_viewport->width(), ui_viewport->height());
+
+ ui_vp_effect->move(ui_viewport->x(), ui_viewport->y());
+ ui_vp_effect->combo_resize(ui_viewport->width(), ui_viewport->height());
+
+ ui_vp_wtce->move(ui_viewport->x(), ui_viewport->y());
+ ui_vp_wtce->combo_resize(ui_viewport->width(), ui_viewport->height());
+
+ ui_vp_objection->move(ui_viewport->x(), ui_viewport->y());
+ ui_vp_objection->combo_resize(ui_viewport->width(), ui_viewport->height());
+
+ set_size_and_pos(ui_ic_chatlog, "ic_chatlog");
+ ui_ic_chatlog->setFrameShape(QFrame::NoFrame);
+
+ set_size_and_pos(ui_ms_chatlog, "ms_chatlog");
+ ui_ms_chatlog->setFrameShape(QFrame::NoFrame);
+
+ set_size_and_pos(ui_server_chatlog, "server_chatlog");
+ ui_server_chatlog->setFrameShape(QFrame::NoFrame);
+
+ set_size_and_pos(ui_mute_list, "mute_list");
+ ui_mute_list->hide();
+
+ set_size_and_pos(ui_pair_list, "pair_list");
+ ui_pair_list->hide();
+ ui_pair_list->setToolTip(tr("Select a character you wish to pair with."));
+
+ set_size_and_pos(ui_pair_offset_spinbox, "pair_offset_spinbox");
+ ui_pair_offset_spinbox->hide();
+ ui_pair_offset_spinbox->setToolTip(
+ tr("Change the percentage offset of your character's position from the "
+ "center of the screen."));
+
+ ui_pair_order_dropdown->hide();
+ set_size_and_pos(ui_pair_order_dropdown, "pair_order_dropdown");
+ ui_pair_offset_spinbox->setToolTip(
+ tr("Change the order of appearance for your character."));
+
+ set_size_and_pos(ui_pair_button, "pair_button");
+ ui_pair_button->set_image("pair_button");
+ ui_pair_button->setToolTip(
+ tr("Display the list of characters to pair with."));
+
+ set_size_and_pos(ui_area_list, "music_list");
+ ui_area_list->header()->setMinimumSectionSize(ui_area_list->width());
+
+ set_size_and_pos(ui_music_list, "music_list");
+ ui_music_list->header()->setMinimumSectionSize(ui_music_list->width());
+
+ set_size_and_pos(ui_music_name, "music_name");
+
+ ui_music_display->move(0, 0);
+ design_ini_result =
+ ao_app->get_element_dimensions("music_display", "courtroom_design.ini");
+
+ if (design_ini_result.width < 0 || design_ini_result.height < 0) {
+ qDebug() << "W: could not find \"music_name\" in courtroom_design.ini";
+ ui_music_display->hide();
+ }
+ else {
+ ui_music_display->move(design_ini_result.x, design_ini_result.y);
+ ui_music_display->combo_resize(design_ini_result.width,
+ design_ini_result.height);
+ }
+
+ ui_music_display->play("music_display");
+
+ if (is_ao2_bg) {
+ set_size_and_pos(ui_ic_chat_message, "ao2_ic_chat_message");
+ set_size_and_pos(ui_vp_chatbox, "ao2_chatbox");
+ set_size_and_pos(ui_ic_chat_name, "ao2_ic_chat_name");
+ }
+ else {
+ set_size_and_pos(ui_ic_chat_message, "ic_chat_message");
+ set_size_and_pos(ui_vp_chatbox, "chatbox");
+ set_size_and_pos(ui_ic_chat_name, "ic_chat_name");
+ }
+
+ ui_ic_chat_message->setStyleSheet(
+ "QLineEdit{background-color: rgba(100, 100, 100, 255);}");
+ ui_ic_chat_name->setStyleSheet(
+ "QLineEdit{background-color: rgba(180, 180, 180, 255);}");
+
+ ui_vp_chatbox->set_image("chatblank");
+ ui_vp_chatbox->hide();
+
+ set_size_and_pos(ui_vp_showname, "showname");
+
+ set_size_and_pos(ui_vp_message, "message");
+ ui_vp_message->hide();
+
+ // We detached the text as parent from the chatbox so it doesn't get affected
+ // by the screenshake.
+ ui_vp_message->move(ui_vp_message->x() + ui_vp_chatbox->x(),
+ ui_vp_message->y() + ui_vp_chatbox->y());
+ ui_vp_message->setTextInteractionFlags(Qt::NoTextInteraction);
+
+ ui_muted->resize(ui_ic_chat_message->width(), ui_ic_chat_message->height());
+ ui_muted->set_image("muted");
+ ui_muted->setToolTip(tr("Oops, you're muted!"));
+
+ set_size_and_pos(ui_ooc_chat_message, "ooc_chat_message");
+ ui_ooc_chat_message->setStyleSheet("background-color: rgba(0, 0, 0, 0);");
+
+ set_size_and_pos(ui_ooc_chat_name, "ooc_chat_name");
+ ui_ooc_chat_name->setStyleSheet("background-color: rgba(0, 0, 0, 0);");
+
+ // set_size_and_pos(ui_area_password, "area_password");
+ set_size_and_pos(ui_music_search, "music_search");
+ ui_music_search->setStyleSheet("background-color: rgba(0, 0, 0, 0);");
+
+ set_size_and_pos(ui_emote_dropdown, "emote_dropdown");
+ ui_emote_dropdown->setToolTip(
+ tr("Set your character's emote to play on your next message."));
+
+ set_size_and_pos(ui_pos_dropdown, "pos_dropdown");
+ ui_pos_dropdown->setToolTip(
+ tr("Set your character's supplementary background."));
+
+ set_size_and_pos(ui_iniswap_dropdown, "iniswap_dropdown");
+ ui_iniswap_dropdown->setEditable(true);
+ ui_iniswap_dropdown->setInsertPolicy(QComboBox::InsertAtBottom);
+ ui_iniswap_dropdown->setToolTip(
+ tr("Set an 'iniswap', or an alternative character folder to refer to "
+ "from your current character.\n"
+ "Edit by typing and pressing Enter, [X] to remove. This saves to your "
+ "base/characters/<charname>/iniswaps.ini"));
+
+ set_size_and_pos(ui_iniswap_remove, "iniswap_remove");
+ ui_iniswap_remove->setText("X");
+ ui_iniswap_remove->set_image("evidencex");
+ ui_iniswap_remove->setToolTip(
+ tr("Remove the currently selected iniswap from the list and return to "
+ "the original character folder."));
+ ui_iniswap_remove->hide();
+
+ set_size_and_pos(ui_sfx_dropdown, "sfx_dropdown");
+ ui_sfx_dropdown->setEditable(true);
+ ui_sfx_dropdown->setInsertPolicy(QComboBox::InsertAtBottom);
+ ui_sfx_dropdown->setToolTip(
+ tr("Set a sound effect to play on your next 'Preanim'. Leaving it on "
+ "Default will use the emote-defined sound (if any).\n"
+ "Edit by typing and pressing Enter, [X] to remove. This saves to your "
+ "base/characters/<charname>/soundlist.ini"));
+
+ set_size_and_pos(ui_sfx_remove, "sfx_remove");
+ ui_sfx_remove->setText("X");
+ ui_sfx_remove->set_image("evidencex");
+ ui_sfx_remove->setToolTip(
+ tr("Remove the currently selected iniswap from the list and return to "
+ "the original character folder."));
+ ui_sfx_remove->hide();
+
+ set_size_and_pos(ui_effects_dropdown, "effects_dropdown");
+ ui_effects_dropdown->setInsertPolicy(QComboBox::InsertAtBottom);
+ ui_effects_dropdown->setToolTip(
+ tr("Choose an effect to play on your next spoken message.\n"
+ "The effects are defined in your theme/effects/effects.ini. Your "
+ "character can define custom effects by\n"
+ "char.ini [Options] category, effects = 'miscname' where it referes "
+ "to misc/<miscname>/effects.ini to read the effects."));
+ // Todo: recode this entire fucking system with these dumbass goddamn ini's
+ // why is everything so specifically coded for all these purposes is ABSTRACT
+ // CODING not a thing now huh what the FUCK why do I gotta do this pleASE FOR
+ // THE LOVE OF GOD SPARE ME FROM THIS FRESH HELL btw i still love coding.
+ QPoint p_point = ao_app->get_button_spacing("effects_icon_size", filename);
+ ui_effects_dropdown->setIconSize(QSize(p_point.x(), p_point.y()));
+
+ set_size_and_pos(ui_defense_bar, "defense_bar");
+ ui_defense_bar->set_image("defensebar" + QString::number(defense_bar_state));
+
+ set_size_and_pos(ui_prosecution_bar, "prosecution_bar");
+ ui_prosecution_bar->set_image("prosecutionbar" +
+ QString::number(prosecution_bar_state));
+
+ set_size_and_pos(ui_music_label, "music_label");
+ ui_music_label->setText(tr("Music"));
+ set_size_and_pos(ui_sfx_label, "sfx_label");
+ ui_sfx_label->setText(tr("Sfx"));
+ set_size_and_pos(ui_blip_label, "blip_label");
+ ui_blip_label->setText(tr("Blips"));
+
+ set_size_and_pos(ui_hold_it, "hold_it");
+ ui_hold_it->setText(tr("Hold It!"));
+ ui_hold_it->setToolTip(tr("When this is turned on, your next in-character "
+ "message will be a shout!"));
+ ui_hold_it->set_image("holdit");
+
+ set_size_and_pos(ui_objection, "objection");
+ ui_objection->setText(tr("Objection!"));
+ ui_objection->setToolTip(tr("When this is turned on, your next in-character "
+ "message will be a shout!"));
+ ui_objection->set_image("objection");
+
+ set_size_and_pos(ui_take_that, "take_that");
+ ui_take_that->setText(tr("Take That!"));
+ ui_take_that->setToolTip(tr("When this is turned on, your next in-character "
+ "message will be a shout!"));
+ ui_take_that->set_image("takethat");
+
+ set_size_and_pos(ui_ooc_toggle, "ooc_toggle");
+ ui_ooc_toggle->setText(tr("Server"));
+ ui_ooc_toggle->setToolTip(
+ tr("Toggle between server chat and global AO2 chat."));
+
+ set_size_and_pos(ui_witness_testimony, "witness_testimony");
+ ui_witness_testimony->set_image("witnesstestimony");
+ ui_witness_testimony->setToolTip(tr("This will display the animation in the "
+ "viewport as soon as it is pressed."));
+ set_size_and_pos(ui_cross_examination, "cross_examination");
+ ui_cross_examination->set_image("crossexamination");
+ ui_cross_examination->setToolTip(tr("This will display the animation in the "
+ "viewport as soon as it is pressed."));
+
+ set_size_and_pos(ui_guilty, "guilty");
+ ui_guilty->setText(tr("Guilty!"));
+ ui_guilty->set_image("guilty");
+ ui_guilty->setToolTip(tr("This will display the animation in the viewport as "
+ "soon as it is pressed."));
+ set_size_and_pos(ui_not_guilty, "not_guilty");
+ ui_not_guilty->set_image("notguilty");
+ ui_not_guilty->setToolTip(tr("This will display the animation in the "
+ "viewport as soon as it is pressed."));
+
+ set_size_and_pos(ui_change_character, "change_character");
+ ui_change_character->setText(tr("Change character"));
+ ui_change_character->set_image("change_character");
+ ui_change_character->setToolTip(
+ tr("Bring up the Character Select Screen and change your character."));
+
+ set_size_and_pos(ui_reload_theme, "reload_theme");
+ ui_reload_theme->setText(tr("Reload theme"));
+ ui_reload_theme->set_image("reload_theme");
+ ui_reload_theme->setToolTip(
+ tr("Refresh the theme and update all of the ui elements to match."));
+
+ set_size_and_pos(ui_call_mod, "call_mod");
+ ui_call_mod->setText(tr("Call mod"));
+ ui_call_mod->set_image("call_mod");
+ ui_call_mod->setToolTip(
+ tr("Request the attention of the current server's moderator."));
+
+ set_size_and_pos(ui_settings, "settings");
+ ui_settings->setText(tr("Settings"));
+ ui_settings->set_image("settings");
+ ui_settings->setToolTip(
+ tr("Allows you to change various aspects of the client."));
+
+ set_size_and_pos(ui_announce_casing, "casing_button");
+ ui_announce_casing->setText(tr("Casing"));
+ ui_announce_casing->set_image("casing_button");
+ ui_announce_casing->setToolTip(
+ tr("An interface to help you announce a case (you have to be a CM first "
+ "to be able to announce cases)"));
+
+ set_size_and_pos(ui_switch_area_music, "switch_area_music");
+ ui_switch_area_music->setText(tr("A/M"));
+ ui_switch_area_music->set_image("switch_area_music");
+ ui_switch_area_music->setToolTip(tr("Switch between Areas and Music lists"));
+
+ set_size_and_pos(ui_pre, "pre");
+ ui_pre->setText(tr("Preanim"));
+ ui_pre->setToolTip(
+ tr("Play a single-shot animation as defined by the emote when checked."));
+
+ set_size_and_pos(ui_pre_non_interrupt, "pre_no_interrupt");
+ ui_pre_non_interrupt->setToolTip(
+ tr("If preanim is checked, display the input text immediately as the "
+ "animation plays concurrently."));
+
+ set_size_and_pos(ui_flip, "flip");
+ ui_flip->setToolTip(tr("Mirror your character's emotes when checked."));
+
+ set_size_and_pos(ui_additive, "additive");
+ ui_additive->setToolTip(
+ tr("Add text to your last spoken message when checked."));
+
+ set_size_and_pos(ui_guard, "guard");
+ ui_guard->setToolTip(
+ tr("Do not listen to mod calls when checked, preventing them from "
+ "playing sounds or focusing attention on the window."));
+
+ set_size_and_pos(ui_casing, "casing");
+ ui_casing->setToolTip(tr("Lets you receive case alerts when enabled.\n"
+ "(You can set your preferences in the Settings!)"));
+
+ set_size_and_pos(ui_showname_enable, "showname_enable");
+ ui_showname_enable->setToolTip(
+ tr("Display customized shownames for all users when checked."));
+
+ set_size_and_pos(ui_custom_objection, "custom_objection");
+ ui_custom_objection->setText(tr("Custom Shout!"));
+ ui_custom_objection->set_image("custom");
+ ui_custom_objection->setToolTip(
+ tr("This will display the custom character-defined animation in the "
+ "viewport as soon as it is pressed.\n"
+ "To make one, your character's folder must contain "
+ "custom.[webp/apng/gif/png] and custom.[wav/ogg/opus] sound effect"));
+
+ set_size_and_pos(ui_realization, "realization");
+ ui_realization->set_image("realization");
+ ui_realization->setToolTip(
+ tr("Play realization sound and animation in the viewport on the next "
+ "spoken message when checked."));
+
+ set_size_and_pos(ui_screenshake, "screenshake");
+ ui_screenshake->set_image("screenshake");
+ ui_screenshake->setToolTip(
+ tr("Shake the screen on next spoken message when checked."));
+
+ set_size_and_pos(ui_mute, "mute_button");
+ ui_mute->setText("Mute");
+ ui_mute->set_image("mute");
+ ui_mute->setToolTip(
+ tr("Display the list of character folders you wish to mute."));
+
+ set_size_and_pos(ui_defense_plus, "defense_plus");
+ ui_defense_plus->set_image("defplus");
+ ui_defense_plus->setToolTip(tr("Increase the health bar."));
+
+ set_size_and_pos(ui_defense_minus, "defense_minus");
+ ui_defense_minus->set_image("defminus");
+ ui_defense_minus->setToolTip(tr("Decrease the health bar."));
+
+ set_size_and_pos(ui_prosecution_plus, "prosecution_plus");
+ ui_prosecution_plus->set_image("proplus");
+ ui_prosecution_plus->setToolTip(tr("Increase the health bar."));
+
+ set_size_and_pos(ui_prosecution_minus, "prosecution_minus");
+ ui_prosecution_minus->set_image("prominus");
+ ui_prosecution_minus->setToolTip(tr("Decrease the health bar."));
+
+ set_size_and_pos(ui_text_color, "text_color");
+ ui_text_color->setToolTip(
+ tr("Change the text color of the spoken message.\n"
+ "You can also select a part of your currently typed message and use "
+ "the dropdown to change its color!"));
+ set_text_color_dropdown();
+
+ set_size_and_pos(ui_music_slider, "music_slider");
+ set_size_and_pos(ui_sfx_slider, "sfx_slider");
+ set_size_and_pos(ui_blip_slider, "blip_slider");
+
+ ui_selector->set_image("char_selector");
+ ui_selector->hide();
+
+ set_size_and_pos(ui_back_to_lobby, "back_to_lobby");
+ ui_back_to_lobby->setText(tr("Back to Lobby"));
+ ui_back_to_lobby->setToolTip(tr("Return back to the server list."));
+
+ set_size_and_pos(ui_char_password, "char_password");
+
+ set_size_and_pos(ui_char_buttons, "char_buttons");
+
+ set_size_and_pos(ui_char_select_left, "char_select_left");
+ ui_char_select_left->set_image("arrow_left");
+
+ set_size_and_pos(ui_char_select_right, "char_select_right");
+ ui_char_select_right->set_image("arrow_right");
+
+ set_size_and_pos(ui_spectator, "spectator");
+ ui_spectator->setToolTip(tr("Become a spectator. You won't be able to "
+ "interact with the in-character screen."));
+
+ refresh_evidence();
+}
+
+void Courtroom::set_fonts(QString p_char)
+{
+ set_font(ui_vp_showname, "", "showname", p_char);
+ set_font(ui_vp_message, "", "message", p_char);
+ set_font(ui_ic_chatlog, "", "ic_chatlog", p_char);
+ set_font(ui_ms_chatlog, "", "ms_chatlog", p_char);
+ set_font(ui_server_chatlog, "", "server_chatlog", p_char);
+ set_font(ui_music_list, "", "music_list", p_char);
+ set_font(ui_area_list, "", "area_list", p_char);
+ set_font(ui_music_name, "", "music_name", p_char);
+
+ set_dropdowns();
+}
+
+void Courtroom::set_font(QWidget *widget, QString class_name,
+ QString p_identifier, QString p_char,
+ QString font_name, int f_pointsize)
+{
+ QString design_file = "courtroom_fonts.ini";
+ if (f_pointsize <= 0)
+ f_pointsize = ao_app->get_design_element(p_identifier, design_file, p_char).toInt();
+ if (font_name == "")
+ font_name =
+ ao_app->get_design_element(p_identifier + "_font", design_file, p_char);
+ QString f_color_result = ao_app->get_design_element(p_identifier + "_color", design_file, p_char);
+ QColor f_color(0, 0, 0);
+ if (f_color_result != "")
+ {
+ QStringList color_list = f_color_result.split(",");
+
+ if (color_list.size() >= 3)
+ {
+ f_color.setRed(color_list.at(0).toInt());
+ f_color.setGreen(color_list.at(1).toInt());
+ f_color.setBlue(color_list.at(2).toInt());
+ }
+ }
+ bool bold = ao_app->get_design_element(p_identifier + "_bold", design_file, p_char) ==
+ 1; // is the font bold or not?
+ bool antialias =
+ ao_app->get_design_element(p_identifier + "_sharp", design_file, p_char) !=
+ "1"; // is the font anti-aliased or not?
+
+ this->set_qfont(widget, class_name,
+ get_qfont(font_name, f_pointsize, antialias), f_color, bold);
+}
+
+QFont Courtroom::get_qfont(QString font_name, int f_pointsize, bool antialias)
+{
+ QFont font;
+ if (font_name.isEmpty())
+ font_name = "Arial";
+
+ QFont::StyleStrategy style_strategy = QFont::PreferDefault;
+ if (!antialias)
+ style_strategy = QFont::NoAntialias;
+
+ font = QFont(font_name, f_pointsize);
+ font.setStyleHint(QFont::SansSerif, style_strategy);
+ return font;
+}
+
+void Courtroom::set_qfont(QWidget *widget, QString class_name, QFont font,
+ QColor f_color, bool bold)
+{
+ if (class_name.isEmpty())
+ class_name = widget->metaObject()->className();
+
+ font.setBold(bold);
+ widget->setFont(font);
+
+ QString style_sheet_string =
+ class_name + " { background-color: rgba(0, 0, 0, 0);\n" + "color: rgba(" +
+ QString::number(f_color.red()) + ", " + QString::number(f_color.green()) +
+ ", " + QString::number(f_color.blue()) + ", 255);}";
+ widget->setStyleSheet(style_sheet_string);
+}
+
+void Courtroom::set_dropdown(QWidget *widget)
+{
+ QString f_file = "courtroom_stylesheets.css";
+ QString style_sheet_string = ao_app->get_stylesheet(f_file);
+ if (style_sheet_string != "")
+ widget->setStyleSheet(style_sheet_string);
+}
+
+void Courtroom::set_dropdowns()
+{
+ set_dropdown(
+ this); // EXPERIMENTAL - Read the style-sheet as-is for maximum memeage
+ // set_dropdown(ui_text_color, "[TEXT COLOR]");
+ // set_dropdown(ui_pos_dropdown, "[POS DROPDOWN]");
+ // set_dropdown(ui_emote_dropdown, "[EMOTE DROPDOWN]");
+ // set_dropdown(ui_mute_list, "[MUTE LIST]");
+}
+
+void Courtroom::set_window_title(QString p_title)
+{
+ this->setWindowTitle(p_title);
+}
+
+void Courtroom::set_size_and_pos(QWidget *p_widget, QString p_identifier)
+{
+ QString filename = "courtroom_design.ini";
+
+ pos_size_type design_ini_result =
+ ao_app->get_element_dimensions(p_identifier, filename);
+
+ if (design_ini_result.width < 0 || design_ini_result.height < 0) {
+ qDebug() << "W: could not find \"" << p_identifier << "\" in " << filename;
+ p_widget->hide();
+ }
+ else {
+ p_widget->move(design_ini_result.x, design_ini_result.y);
+ p_widget->resize(design_ini_result.width, design_ini_result.height);
+ }
+}
+
+void Courtroom::set_taken(int n_char, bool p_taken)
+{
+ if (n_char >= char_list.size()) {
+ qDebug()
+ << "W: set_taken attempted to set an index bigger than char_list size";
+ return;
+ }
+
+ char_type f_char;
+ f_char.name = char_list.at(n_char).name;
+ f_char.description = char_list.at(n_char).description;
+ f_char.taken = p_taken;
+ f_char.evidence_string = char_list.at(n_char).evidence_string;
+
+ char_list.replace(n_char, f_char);
+}
+
+QPoint Courtroom::get_theme_pos(QString p_identifier)
+{
+ QString filename = "courtroom_design.ini";
+
+ pos_size_type design_ini_result =
+ ao_app->get_element_dimensions(p_identifier, filename);
+
+ if (design_ini_result.width < 0 || design_ini_result.height < 0) {
+ qDebug() << "W: could not find \"" << p_identifier << "\" in " << filename;
+ return QPoint(0, 0);
+ }
+ else {
+ return QPoint(design_ini_result.x, design_ini_result.y);
+ }
+}
+
+void Courtroom::done_received()
+{
+ m_cid = -1;
+
+ music_player->set_volume(0);
+ sfx_player->set_volume(0);
+ objection_player->set_volume(0);
+ blip_player->set_volume(0);
+
+ set_char_select_page();
+
+ set_mute_list();
+ set_pair_list();
+
+ set_char_select();
+
+ show();
+
+ ui_spectator->show();
+}
+
+void Courtroom::set_background(QString p_background, bool display)
+{
+ ui_vp_testimony->stop();
+ current_background = p_background;
+
+ // welcome to hardcode central may I take your order of regularly scheduled
+ // CBT
+ QMap<QString, QString> default_pos;
+ default_pos["defenseempty"] = "def";
+ default_pos["helperstand"] = "hld";
+ default_pos["prosecutorempty"] = "pro";
+ default_pos["prohelperstand"] = "hlp";
+ default_pos["witnessempty"] = "wit";
+ default_pos["judgestand"] = "jud";
+ default_pos["jurystand"] = "jur";
+ default_pos["seancestand"] = "sea";
+
+ // Populate the dropdown list with all pos that exist on this bg
+ QStringList pos_list = {};
+ for (QString key : default_pos.keys()) {
+ if (file_exists(ao_app->get_image_suffix(
+ ao_app->get_background_path(key)))) {
+ pos_list.append(default_pos[key]);
+ }
+ }
+
+ // TODO: search through extra/custom pos and add them to the pos dropdown as
+ // well
+
+ set_pos_dropdown(pos_list);
+
+ is_ao2_bg = true;
+
+ if (is_ao2_bg) {
+ set_size_and_pos(ui_vp_chatbox, "ao2_chatbox");
+ set_size_and_pos(ui_ic_chat_message, "ao2_ic_chat_message");
+ }
+ else {
+ set_size_and_pos(ui_vp_chatbox, "chatbox");
+ set_size_and_pos(ui_ic_chat_message, "ic_chat_message");
+ }
+
+ if (display) {
+ ui_vp_speedlines->stop();
+ ui_vp_player_char->stop();
+
+ ui_vp_sideplayer_char->stop();
+ ui_vp_effect->stop();
+ ui_vp_message->hide();
+ ui_vp_chatbox->hide();
+
+ // Stop the chat arrow from animating
+ ui_vp_chat_arrow->stop();
+
+ text_state = 2;
+ anim_state = 3;
+ ui_vp_objection->stop();
+ chat_tick_timer->stop();
+ ui_vp_evidence_display->reset();
+ set_scene(
+ QString::number(ao_app->get_desk_mod(current_char, current_emote)),
+ current_side);
+ }
+}
+
+void Courtroom::set_side(QString p_side)
+{
+ if (p_side == "")
+ current_side = ao_app->get_char_side(current_char);
+ else
+ current_side = p_side;
+
+ for (int i = 0; i < ui_pos_dropdown->count(); ++i) {
+ QString pos = ui_pos_dropdown->itemText(i);
+ if (pos == current_side) {
+ // Block the signals to prevent setCurrentIndex from triggering a pos
+ // change
+ ui_pos_dropdown->blockSignals(true);
+
+ // Set the index on dropdown ui element to let you know what pos you're on
+ // right now
+ ui_pos_dropdown->setCurrentIndex(i);
+
+ // Unblock the signals so the element can be used for setting pos again
+ ui_pos_dropdown->blockSignals(false);
+
+ // alright we dun, jobs done here boyos
+ break;
+ }
+ }
+}
+
+void Courtroom::set_pos_dropdown(QStringList pos_dropdowns)
+{
+ // Block the signals to prevent setCurrentIndex from triggering a pos change
+ ui_pos_dropdown->blockSignals(true);
+ pos_dropdown_list = pos_dropdowns;
+ ui_pos_dropdown->clear();
+ ui_pos_dropdown->addItems(pos_dropdown_list);
+ // Unblock the signals so the element can be used for setting pos again
+ ui_pos_dropdown->blockSignals(false);
+
+ qDebug() << pos_dropdown_list;
+}
+
+void Courtroom::update_character(int p_cid)
+{
+ bool newchar = m_cid != p_cid;
+
+ m_cid = p_cid;
+
+ QString f_char;
+
+ if (m_cid == -1) {
+ if (ao_app->is_discord_enabled())
+ ao_app->discord->state_spectate();
+ f_char = "";
+ }
+ else {
+ f_char = ao_app->get_char_name(char_list.at(m_cid).name);
+
+ if (ao_app->is_discord_enabled())
+ ao_app->discord->state_character(f_char.toStdString());
+ }
+
+ current_char = f_char;
+ current_side = ao_app->get_char_side(current_char);
+
+ current_emote_page = 0;
+ current_emote = 0;
+
+ if (m_cid == -1)
+ ui_emotes->hide();
+ else
+ ui_emotes->show();
+
+ refresh_emotes();
+ set_emote_page();
+ set_emote_dropdown();
+
+ set_sfx_dropdown();
+ set_effects_dropdown();
+
+ qDebug() << "update_character called";
+ if (newchar) // Avoid infinite loop of death and suffering
+ set_iniswap_dropdown();
+
+ if (current_side == "jud") {
+ ui_witness_testimony->show();
+ ui_cross_examination->show();
+ ui_not_guilty->show();
+ ui_guilty->show();
+ ui_defense_minus->show();
+ ui_defense_plus->show();
+ ui_prosecution_minus->show();
+ ui_prosecution_plus->show();
+ }
+ else {
+ ui_witness_testimony->hide();
+ ui_cross_examination->hide();
+ ui_guilty->hide();
+ ui_not_guilty->hide();
+ ui_defense_minus->hide();
+ ui_defense_plus->hide();
+ ui_prosecution_minus->hide();
+ ui_prosecution_plus->hide();
+ }
+
+ ui_custom_objection->hide();
+ if (ao_app->custom_objection_enabled) // if setting is enabled
+ {
+ custom_obj_menu->clear();
+ if (file_exists(ao_app->get_image_suffix(
+ ao_app->get_character_path(current_char, "custom"))))
+ {
+ ui_custom_objection->show();
+ QAction *action = custom_obj_menu->addAction("Default");
+ custom_obj_menu->setDefaultAction(action);
+ objection_custom = "";
+ }
+ if (dir_exists(
+ ao_app->get_character_path(current_char, "custom_objections"))) {
+ ui_custom_objection->show();
+ QDir directory(
+ ao_app->get_character_path(current_char, "custom_objections"));
+ QStringList custom_obj = directory.entryList(QStringList() << "*.png"
+ << "*.gif"
+ << "*.apng"
+ << "*.webp",
+ QDir::Files);
+ for (const QString &filename : custom_obj) {
+ QAction *action = custom_obj_menu->addAction(filename);
+ if (custom_obj_menu->defaultAction() == nullptr)
+ {
+ custom_obj_menu->setDefaultAction(action);
+ objection_custom = action->text();
+ }
+ }
+ }
+ }
+
+ if (m_cid != -1) // there is no name at char_list -1, and we crash if we try
+ // to find one
+ ui_ic_chat_name->setPlaceholderText(char_list.at(m_cid).name);
+ ui_char_select_background->hide();
+ ui_ic_chat_message->setEnabled(m_cid != -1);
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::enter_courtroom()
+{
+ set_widgets();
+
+ current_evidence_page = 0;
+ current_evidence = 0;
+
+ set_evidence_page();
+
+ if (ao_app->flipping_enabled)
+ ui_flip->show();
+ else
+ ui_flip->hide();
+
+ if (ao_app->additive_enabled)
+ ui_additive->show();
+ else
+ ui_additive->hide();
+
+ if (ao_app->casing_alerts_enabled)
+ ui_casing->show();
+ else
+ ui_casing->hide();
+
+ list_music();
+ list_areas();
+
+ switch (
+ objection_state) // no need to reset these as it was done in set_widgets()
+ {
+ case 1:
+ ui_hold_it->set_image("holdit_selected");
+ break;
+ case 2:
+ ui_objection->set_image("objection_selected");
+ break;
+ case 3:
+ ui_take_that->set_image("takethat_selected");
+ break;
+ case 4:
+ ui_custom_objection->set_image("custom_selected");
+ break;
+ default:
+ break;
+ }
+
+ music_player->set_volume(ui_music_slider->value(), 0); // set music
+ // Set the ambience and other misc. music layers
+ for (int i = 1; i < music_player->m_channelmax; ++i) {
+ music_player->set_volume(ui_sfx_slider->value(), i);
+ }
+ sfx_player->set_volume(ui_sfx_slider->value());
+ objection_player->set_volume(ui_sfx_slider->value());
+ blip_player->set_volume(ui_blip_slider->value());
+
+ ui_vp_testimony->stop();
+ // ui_server_chatlog->setHtml(ui_server_chatlog->toHtml());
+}
+
+// Todo: multithread this due to some servers having large as hell music list
+void Courtroom::list_music()
+{
+ ui_music_list->clear();
+ // ui_music_search->setText("");
+
+ QString f_file = "courtroom_design.ini";
+
+ QBrush found_brush(ao_app->get_color("found_song_color", f_file));
+ QBrush missing_brush(ao_app->get_color("missing_song_color", f_file));
+
+ int n_listed_songs = 0;
+
+ QTreeWidgetItem *parent = nullptr;
+ for (int n_song = 0; n_song < music_list.size(); ++n_song) {
+ QString i_song = music_list.at(n_song);
+ QString i_song_listname = i_song.left(i_song.lastIndexOf("."));
+ i_song_listname = i_song_listname.right(
+ i_song_listname.length() - (i_song_listname.lastIndexOf("/") + 1));
+
+ QTreeWidgetItem *treeItem;
+ if (i_song_listname != i_song &&
+ parent != nullptr) // not a category, parent exists
+ treeItem = new QTreeWidgetItem(parent);
+ else
+ treeItem = new QTreeWidgetItem(ui_music_list);
+ treeItem->setText(0, i_song_listname);
+ treeItem->setText(1, i_song);
+
+ QString song_path = ao_app->get_music_path(i_song);
+
+ if (file_exists(song_path))
+ treeItem->setBackground(0, found_brush);
+ else
+ treeItem->setBackground(0, missing_brush);
+
+ if (i_song_listname ==
+ i_song) // Not supposed to be a song to begin with - a category?
+ parent = treeItem;
+ ++n_listed_songs;
+ }
+
+ ui_music_list->expandAll(); // Needs to somehow remember which categories were
+ // expanded/collapsed if the music list didn't
+ // change since last time
+ if (ui_music_search->text() != "") {
+ on_music_search_edited(ui_music_search->text());
+ }
+}
+
+// Todo: multithread this due to some servers having large as hell area list
+void Courtroom::list_areas()
+{
+ ui_area_list->clear();
+ // ui_music_search->setText("");
+
+ QString f_file = "courtroom_design.ini";
+
+ QBrush free_brush(ao_app->get_color("area_free_color", f_file));
+ QBrush lfp_brush(ao_app->get_color("area_lfp_color", f_file));
+ QBrush casing_brush(ao_app->get_color("area_casing_color", f_file));
+ QBrush recess_brush(ao_app->get_color("area_recess_color", f_file));
+ QBrush rp_brush(ao_app->get_color("area_rp_color", f_file));
+ QBrush gaming_brush(ao_app->get_color("area_gaming_color", f_file));
+ QBrush locked_brush(ao_app->get_color("area_locked_color", f_file));
+
+ int n_listed_areas = 0;
+
+ for (int n_area = 0; n_area < area_list.size(); ++n_area) {
+ QString i_area = "";
+ i_area.append(area_list.at(n_area));
+
+ if (ao_app->arup_enabled) {
+ i_area.prepend("[" + QString::number(n_area) + "] "); // Give it the index
+
+ i_area.append("\n ");
+
+ i_area.append(arup_statuses.at(n_area));
+ i_area.append(" | CM: ");
+ i_area.append(arup_cms.at(n_area));
+
+ i_area.append("\n ");
+
+ i_area.append(QString::number(arup_players.at(n_area)));
+ i_area.append(" users | ");
+
+ i_area.append(arup_locks.at(n_area));
+ }
+
+ QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_area_list);
+ treeItem->setText(0, area_list.at(n_area));
+ treeItem->setText(1, i_area);
+
+ if (ao_app->arup_enabled) {
+ // Coloring logic here.
+ treeItem->setBackground(1, free_brush);
+ if (arup_locks.at(n_area) == "LOCKED") {
+ treeItem->setBackground(1, locked_brush);
+ }
+ else {
+ if (arup_statuses.at(n_area) == "LOOKING-FOR-PLAYERS")
+ treeItem->setBackground(1, lfp_brush);
+ else if (arup_statuses.at(n_area) == "CASING")
+ treeItem->setBackground(1, casing_brush);
+ else if (arup_statuses.at(n_area) == "RECESS")
+ treeItem->setBackground(1, recess_brush);
+ else if (arup_statuses.at(n_area) == "RP")
+ treeItem->setBackground(1, rp_brush);
+ else if (arup_statuses.at(n_area) == "GAMING")
+ treeItem->setBackground(1, gaming_brush);
+ }
+ }
+ else {
+ treeItem->setBackground(1, free_brush);
+ }
+
+ ++n_listed_areas;
+ }
+
+ if (ui_music_search->text() != "") {
+ on_music_search_edited(ui_music_search->text());
+ }
+}
+
+void Courtroom::append_ms_chatmessage(QString f_name, QString f_message)
+{
+ ui_ms_chatlog->append_chatmessage(
+ f_name, f_message,
+ ao_app->get_color("ms_chatlog_sender_color", "courtroom_fonts.ini")
+ .name());
+}
+
+void Courtroom::append_server_chatmessage(QString p_name, QString p_message,
+ QString p_color)
+{
+ QString color = "#000000";
+
+ if (p_color == "0")
+ color = ao_app->get_color("ms_chatlog_sender_color", "courtroom_fonts.ini")
+ .name();
+ if (p_color == "1")
+ color =
+ ao_app->get_color("server_chatlog_sender_color", "courtroom_fonts.ini")
+ .name();
+ if (p_message == "Logged in as a moderator.") {
+ ui_guard->show();
+ append_server_chatmessage(
+ tr("CLIENT"), tr("You were granted the Disable Modcalls button."), "1");
+ }
+
+ ui_server_chatlog->append_chatmessage(p_name, p_message, color);
+}
+
+void Courtroom::on_chat_return_pressed()
+{
+ if (ui_ic_chat_message->text() == "" || is_muted)
+ return;
+
+ if ((anim_state < 3 || text_state < 2) && objection_state == 0)
+ return;
+
+ // MS#
+ // deskmod#
+ // pre-emote#
+ // character#
+ // emote#
+ // message#
+ // side#
+ // sfx-name#
+ // emote_modifier#
+ // char_id#
+ // sfx_delay#
+ // objection_modifier#
+ // evidence#
+ // placeholder#
+ // realization#
+ // text_color#%
+
+ // Additionally, in our case:
+
+ // showname#
+ // other_charid#
+ // self_offset#
+ // noninterrupting_preanim#%
+
+ QStringList packet_contents;
+
+ if (current_side == "")
+ current_side = ao_app->get_char_side(current_char);
+
+ QString f_desk_mod = "chat";
+
+ if (ao_app->desk_mod_enabled) {
+ f_desk_mod =
+ QString::number(ao_app->get_desk_mod(current_char, current_emote));
+ if (f_desk_mod == "-1")
+ f_desk_mod = "chat";
+ }
+
+ packet_contents.append(f_desk_mod);
+
+ packet_contents.append(ao_app->get_pre_emote(current_char, current_emote));
+
+ packet_contents.append(current_char);
+
+ packet_contents.append(ao_app->get_emote(current_char, current_emote));
+
+ packet_contents.append(ui_ic_chat_message->text());
+
+ packet_contents.append(current_side);
+
+ packet_contents.append(get_char_sfx());
+ if (ui_pre->isChecked() && !ao_app->is_stickysounds_enabled()) {
+ ui_sfx_dropdown->blockSignals(true);
+ ui_sfx_dropdown->setCurrentIndex(0);
+ ui_sfx_dropdown->blockSignals(false);
+ ui_sfx_remove->hide();
+ }
+
+ int f_emote_mod = ao_app->get_emote_mod(current_char, current_emote);
+
+ // needed or else legacy won't understand what we're saying
+ if (objection_state > 0) {
+ if (ui_pre->isChecked()) {
+ if (f_emote_mod == 4 || f_emote_mod == 5)
+ f_emote_mod = 6;
+ else
+ f_emote_mod = 2;
+ }
+ }
+ else if (ui_pre->isChecked() && !ui_pre_non_interrupt->isChecked()) {
+ if (f_emote_mod == 0)
+ f_emote_mod = 1;
+ else if (f_emote_mod == 5 && ao_app->prezoom_enabled)
+ f_emote_mod = 4;
+ }
+ else {
+ if (f_emote_mod == 1)
+ f_emote_mod = 0;
+ else if (f_emote_mod == 4)
+ f_emote_mod = 5;
+ }
+
+ packet_contents.append(QString::number(f_emote_mod));
+ packet_contents.append(QString::number(m_cid));
+
+ packet_contents.append(QString::number(get_char_sfx_delay()));
+
+ QString f_obj_state;
+
+ if ((objection_state == 4 && !ao_app->custom_objection_enabled) ||
+ (objection_state < 0))
+ f_obj_state = "0";
+ else if (objection_custom != "" && objection_state == 4) {
+ f_obj_state = QString::number(objection_state) + "&" +
+ objection_custom; // we add the name of the objection so the
+ // packet is like: 4&(name of custom obj)
+ }
+ else
+ f_obj_state = QString::number(objection_state);
+
+ packet_contents.append(f_obj_state);
+
+ if (is_presenting_evidence)
+ // the evidence index is shifted by 1 because 0 is no evidence per legacy
+ // standards besides, older clients crash if we pass -1
+ packet_contents.append(QString::number(current_evidence + 1));
+ else
+ packet_contents.append("0");
+
+ QString f_flip;
+
+ if (ao_app->flipping_enabled) {
+ if (ui_flip->isChecked())
+ f_flip = "1";
+ else
+ f_flip = "0";
+ }
+ else
+ f_flip = QString::number(m_cid);
+
+ packet_contents.append(f_flip);
+
+ packet_contents.append(QString::number(realization_state));
+
+ QString f_text_color;
+
+ if (text_color < 0)
+ f_text_color = "0";
+ else if (text_color >= max_colors)
+ f_text_color = "0";
+ else
+ f_text_color = QString::number(text_color);
+
+ packet_contents.append(f_text_color);
+
+ // If the server we're on supports CCCC stuff, we should use it!
+ if (ao_app->cccc_ic_support_enabled) {
+ // If there is a showname entered, use that -- else, just send an empty
+ // packet-part.
+ if (!ui_ic_chat_name->text().isEmpty()) {
+ packet_contents.append(ui_ic_chat_name->text());
+ }
+ else {
+ packet_contents.append("");
+ }
+
+ // Similarly, we send over whom we're paired with, unless we have chosen
+ // ourselves. Or a charid of -1 or lower, through some means.
+ if (other_charid > -1 && other_charid != m_cid) {
+ QString packet = QString::number(other_charid);
+ if (ao_app->effects_enabled) // Only servers with effects enabled will
+ // support pair reordering
+ packet += "^" + QString::number(pair_order);
+ packet_contents.append(packet);
+ }
+ else {
+ packet_contents.append("-1");
+ }
+ // Send the offset as it's gonna be used regardless
+ packet_contents.append(QString::number(char_offset));
+
+ // Finally, we send over if we want our pres to not interrupt.
+ if (ui_pre_non_interrupt->isChecked() && ui_pre->isChecked()) {
+ packet_contents.append("1");
+ }
+ else {
+ packet_contents.append("0");
+ }
+ }
+
+ // If the server we're on supports Looping SFX and Screenshake, use it if the
+ // emote uses it.
+ if (ao_app->looping_sfx_support_enabled) {
+ packet_contents.append(
+ ao_app->get_sfx_looping(current_char, current_emote));
+ packet_contents.append(QString::number(screenshake_state));
+
+ QString pre_emote = ao_app->get_pre_emote(current_char, current_emote);
+ QString emote = ao_app->get_emote(current_char, current_emote);
+ QStringList emotes_to_check = {pre_emote, "(b)" + emote, "(a)" + emote};
+ QStringList effects_to_check = {"_FrameScreenshake", "_FrameRealization",
+ "_FrameSFX"};
+
+ foreach (QString f_effect, effects_to_check) {
+ QString packet;
+ foreach (QString f_emote, emotes_to_check) {
+ packet += f_emote;
+ if (ao_app->is_frame_network_enabled()) {
+ QString sfx_frames =
+ ao_app
+ ->read_ini_tags(
+ ao_app->get_character_path(current_char, "char.ini"),
+ f_emote.append(f_effect))
+ .join("|");
+ if (sfx_frames != "")
+ packet += "|" + sfx_frames;
+ }
+ packet += "^";
+ }
+ packet_contents.append(packet);
+ }
+ }
+
+ if (ao_app->additive_enabled) {
+ packet_contents.append(ui_additive->isChecked() ? "1" : "0");
+ }
+ if (ao_app->effects_enabled) {
+ QString fx_sound = ao_app->get_effect_sound(effect, current_char);
+ QString p_effect =
+ ao_app->read_char_ini(current_char, "effects", "Options");
+ packet_contents.append(effect + "|" + p_effect + "|" + fx_sound);
+ if (!ao_app->is_stickyeffects_enabled()) {
+ ui_effects_dropdown->blockSignals(true);
+ ui_effects_dropdown->setCurrentIndex(0);
+ ui_effects_dropdown->blockSignals(false);
+ effect = "";
+ }
+ }
+
+ ao_app->send_server_packet(new AOPacket("MS", packet_contents));
+}
+
+void Courtroom::handle_chatmessage(QStringList *p_contents)
+{
+ // Instead of checking for whether a message has at least chatmessage_size
+ // amount of packages, we'll check if it has at least 15.
+ // That was the original chatmessage_size.
+ if (p_contents->size() < 15)
+ return;
+
+ for (int n_string = 0; n_string < chatmessage_size; ++n_string) {
+ // m_chatmessage[n_string] = p_contents->at(n_string);
+
+ // Note that we have added stuff that vanilla clients and servers simply
+ // won't send. So now, we have to check if the thing we want even exists
+ // amongst the packet's content. We also have to check if the server even
+ // supports CCCC's IC features, or if it's just japing us. Also, don't
+ // forget! A size 15 message will have indices from 0 to 14.
+ if (n_string < p_contents->size() &&
+ (n_string < 15 || ao_app->cccc_ic_support_enabled)) {
+ m_chatmessage[n_string] = p_contents->at(n_string);
+ }
+ else {
+ m_chatmessage[n_string] = "";
+ }
+ }
+
+ int f_char_id = m_chatmessage[CHAR_ID].toInt();
+
+ if (f_char_id >= 0 && f_char_id >= char_list.size())
+ return;
+
+ if (mute_map.value(m_chatmessage[CHAR_ID].toInt()))
+ return;
+
+ QString f_showname;
+ if (f_char_id > -1 &&
+ (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) {
+ f_showname = ao_app->get_showname(char_list.at(f_char_id).name);
+ }
+ else {
+ f_showname = m_chatmessage[SHOWNAME];
+ }
+
+ if (f_showname.trimmed()
+ .isEmpty()) // Pure whitespace showname, get outta here.
+ f_showname = m_chatmessage[CHAR_NAME];
+
+ QString f_message = f_showname + ": " + m_chatmessage[MESSAGE] + '\n';
+ // Remove undesired newline chars
+ m_chatmessage[MESSAGE].remove("\n");
+ chatmessage_is_empty =
+ m_chatmessage[MESSAGE] == " " || m_chatmessage[MESSAGE] == "";
+
+ if (f_char_id >= 0 && !chatmessage_is_empty &&
+ f_message == previous_ic_message) // Not a system message
+ return;
+
+ if (f_char_id <= -1)
+ previous_ic_message =
+ ""; // System messages don't care about repeating themselves
+ else
+ previous_ic_message = f_message;
+ bool ok;
+ int objection_mod = m_chatmessage[OBJECTION_MOD].toInt(
+ &ok, 10); // checks if its a custom obj.
+ QString custom_objection = "";
+ if (!ok && m_chatmessage[OBJECTION_MOD].contains("4&")) {
+ objection_mod = 4;
+ custom_objection = m_chatmessage[OBJECTION_MOD].split(
+ "4&")[1]; // takes the name of custom objection.
+ }
+ // Stop the chat arrow from animating
+ ui_vp_chat_arrow->stop();
+
+ text_state = 0;
+ anim_state = 0;
+ ui_vp_objection->stop();
+ chat_tick_timer->stop();
+ ui_vp_evidence_display->reset();
+
+ // Hey, our message showed up! Cool!
+ if (m_chatmessage[MESSAGE] == ui_ic_chat_message->text().remove("\n") &&
+ m_chatmessage[CHAR_ID].toInt() == m_cid) {
+ ui_ic_chat_message->clear();
+ if (ui_additive->isChecked())
+ ui_ic_chat_message->insert(" ");
+ objection_state = 0;
+ realization_state = 0;
+ screenshake_state = 0;
+ is_presenting_evidence = false;
+ if (!ao_app->is_stickypres_enabled())
+ ui_pre->setChecked(false);
+ ui_hold_it->set_image("holdit");
+ ui_objection->set_image("objection");
+ ui_take_that->set_image("takethat");
+ ui_custom_objection->set_image("custom");
+ ui_realization->set_image("realization");
+ ui_screenshake->set_image("screenshake");
+ ui_evidence_present->set_image("present");
+ }
+
+ // Let the server handle actually checking if they're allowed to do this.
+ is_additive = m_chatmessage[ADDITIVE].toInt() == 1;
+
+ QString f_charname = "";
+ if (f_char_id >= 0)
+ f_charname = ao_app->get_showname(char_list.at(f_char_id).name);
+
+ chatlogpiece *temp =
+ new chatlogpiece(f_charname, f_showname, m_chatmessage[MESSAGE], false, m_chatmessage[TEXT_COLOR].toInt());
+ ic_chatlog_history.append(*temp);
+ if (ao_app->get_auto_logging_enabled())
+ ao_app->append_to_file(temp->get_full(), ao_app->log_filename, true);
+
+ while (ic_chatlog_history.size() > log_maximum_blocks &&
+ log_maximum_blocks > 0) {
+ ic_chatlog_history.removeFirst();
+ }
+
+ append_ic_text(m_chatmessage[MESSAGE], f_showname, "", m_chatmessage[TEXT_COLOR].toInt());
+
+ QString f_char = m_chatmessage[CHAR_NAME];
+ QString f_custom_theme = ao_app->get_char_shouts(f_char);
+
+ // if an objection is used
+ if (objection_mod <= 4 && objection_mod >= 1) {
+ switch (objection_mod) {
+ case 1:
+ ui_vp_objection->play("holdit_bubble", f_char, f_custom_theme, 724);
+ objection_player->play("holdit", f_char, f_custom_theme);
+ break;
+ case 2:
+ ui_vp_objection->play("objection_bubble", f_char, f_custom_theme, 724);
+ objection_player->play("objection", f_char, f_custom_theme);
+ if (ao_app->objection_stop_music())
+ music_player->stop();
+ break;
+ case 3:
+ ui_vp_objection->play("takethat_bubble", f_char, f_custom_theme, 724);
+ objection_player->play("takethat", f_char, f_custom_theme);
+ break;
+ // case 4 is AO2 only
+ case 4:
+ if (custom_objection != "") {
+ ui_vp_objection->play("custom_objections/" + custom_objection, f_char,
+ f_custom_theme, shout_stay_time);
+ objection_player->play("custom_objections/" +
+ custom_objection.split('.')[0],
+ f_char, f_custom_theme);
+ }
+ else {
+ ui_vp_objection->play("custom", f_char, f_custom_theme,
+ shout_stay_time);
+ objection_player->play("custom", f_char, f_custom_theme);
+ }
+ break;
+ default:
+ qDebug() << "W: Logic error in objection switch statement!";
+ }
+ sfx_player->clear(); // Objection played! Cut all sfx.
+ int emote_mod = m_chatmessage[EMOTE_MOD].toInt();
+
+ if (emote_mod == 0)
+ m_chatmessage[EMOTE_MOD] = 1;
+ }
+ else
+ handle_chatmessage_2();
+}
+
+void Courtroom::objection_done() { handle_chatmessage_2(); }
+
+void Courtroom::handle_chatmessage_2()
+{
+ ui_vp_speedlines->stop();
+ ui_vp_player_char->stop();
+ ui_vp_effect->stop();
+ // Clear all looping sfx to prevent obnoxiousness
+ sfx_player->loop_clear();
+
+ if (!m_chatmessage[FRAME_SFX].isEmpty() &&
+ ao_app->is_frame_network_enabled()) {
+ // ORDER IS IMPORTANT!!
+ QStringList netstrings = {m_chatmessage[FRAME_SCREENSHAKE],
+ m_chatmessage[FRAME_REALIZATION],
+ m_chatmessage[FRAME_SFX]};
+ ui_vp_player_char->network_strings = netstrings;
+ }
+ else
+ ui_vp_player_char->network_strings.clear();
+
+ int f_charid = m_chatmessage[CHAR_ID].toInt();
+ if (f_charid >= 0 &&
+ (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) {
+ QString real_name = char_list.at(f_charid).name;
+
+ QString f_showname = ao_app->get_showname(real_name);
+
+ ui_vp_showname->setText(f_showname);
+ }
+ else {
+ ui_vp_showname->setText(m_chatmessage[SHOWNAME]);
+ }
+
+ QString customchar;
+ if (ao_app->is_customchat_enabled())
+ customchar = m_chatmessage[CHAR_NAME];
+ if (ui_vp_showname->text().trimmed().isEmpty()) // Whitespace showname
+ {
+ ui_vp_chatbox->set_image("chatblank");
+ }
+ else // Aw yeah dude do some showname magic
+ {
+ if (!ui_vp_chatbox->set_image("chat"))
+ ui_vp_chatbox->set_image("chatbox");
+
+ QFontMetrics fm(ui_vp_showname->font());
+// Gotta support the slow paced ubuntu 18 STUCK IN 5.9.5!!
+#if QT_VERSION > QT_VERSION_CHECK(5, 11, 0)
+ int fm_width = fm.horizontalAdvance(ui_vp_showname->text());
+#else
+ int fm_width = fm.boundingRect((ui_vp_showname->text())).width();
+#endif
+ QString chatbox_path = ao_app->get_theme_path("chat");
+ QString chatbox = ao_app->get_chat(customchar);
+
+ if (chatbox != "" && ao_app->is_customchat_enabled()) {
+ chatbox_path = ao_app->get_base_path() + "misc/" + chatbox + "/chat";
+ if (!ui_vp_chatbox->set_chatbox(chatbox_path))
+ ui_vp_chatbox->set_chatbox(chatbox_path + "box");
+ }
+
+ // This should probably be called only if any change from the last chat
+ // arrow was actually detected.
+ pos_size_type design_ini_result = ao_app->get_element_dimensions(
+ "chat_arrow", "courtroom_design.ini", customchar);
+ if (design_ini_result.width < 0 || design_ini_result.height < 0) {
+ qDebug() << "W: could not find \"chat_arrow\" in courtroom_design.ini";
+ ui_vp_chat_arrow->hide();
+ }
+ else {
+ ui_vp_chat_arrow->move(design_ini_result.x, design_ini_result.y);
+ ui_vp_chat_arrow->combo_resize(design_ini_result.width,
+ design_ini_result.height);
+ }
+
+ pos_size_type default_width = ao_app->get_element_dimensions(
+ "showname", "courtroom_design.ini", customchar);
+ int extra_width =
+ ao_app
+ ->get_design_element("showname_extra_width", "courtroom_design.ini",
+ customchar)
+ .toInt();
+ QString align =
+ ao_app
+ ->get_design_element("showname_align", "courtroom_design.ini",
+ customchar)
+ .toLower();
+ if (align == "right")
+ ui_vp_showname->setAlignment(Qt::AlignRight);
+ else if (align == "center")
+ ui_vp_showname->setAlignment(Qt::AlignHCenter);
+ else if (align == "justify")
+ ui_vp_showname->setAlignment(Qt::AlignHCenter);
+ else
+ ui_vp_showname->setAlignment(Qt::AlignLeft);
+
+ if (extra_width > 0) {
+ if (fm_width > default_width.width &&
+ ui_vp_chatbox->set_chatbox(
+ chatbox_path +
+ "med")) // This text be big. Let's do some shenanigans.
+ {
+ ui_vp_showname->resize(default_width.width + extra_width,
+ ui_vp_showname->height());
+ if (fm_width > ui_vp_showname->width() &&
+ ui_vp_chatbox->set_chatbox(chatbox_path +
+ "big")) // Biggest possible size for us.
+ {
+ ui_vp_showname->resize(
+ static_cast<int>(default_width.width + (extra_width * 2)),
+ ui_vp_showname->height());
+ }
+ }
+ else
+ ui_vp_showname->resize(default_width.width, ui_vp_showname->height());
+
+ set_font(ui_vp_showname, "", "showname", customchar);
+ }
+ else
+ {
+ ui_vp_showname->resize(default_width.width, ui_vp_showname->height());
+ }
+ }
+
+ ui_vp_message->hide();
+ ui_vp_chatbox->hide();
+
+ QString font_name;
+ QString chatfont = ao_app->get_chat_font(m_chatmessage[CHAR_NAME]);
+ if (chatfont != "")
+ font_name = chatfont;
+
+ int f_pointsize = 0;
+ int chatsize = ao_app->get_chat_size(m_chatmessage[CHAR_NAME]);
+ if (chatsize > 0)
+ f_pointsize = chatsize;
+ set_font(ui_vp_message, "", "message", customchar, font_name, f_pointsize);
+
+ set_scene(m_chatmessage[DESK_MOD], m_chatmessage[SIDE]);
+
+ int emote_mod = m_chatmessage[EMOTE_MOD].toInt();
+
+ if (ao_app->flipping_enabled && m_chatmessage[FLIP].toInt() == 1)
+ ui_vp_player_char->set_flipped(true);
+ else
+ ui_vp_player_char->set_flipped(false);
+
+ QString side = m_chatmessage[SIDE];
+
+ // Making the second character appear.
+ if (m_chatmessage[OTHER_CHARID].isEmpty()) {
+ // If there is no second character, hide 'em
+ ui_vp_sideplayer_char->stop();
+ ui_vp_sideplayer_char->move(0, 0);
+ }
+ else {
+ bool ok;
+ int got_other_charid = m_chatmessage[OTHER_CHARID].split("^")[0].toInt(&ok);
+ if (ok) {
+ if (got_other_charid > -1) {
+ // If there is, show them!
+ ui_vp_sideplayer_char->show();
+
+ int other_offset = m_chatmessage[OTHER_OFFSET].toInt();
+ ui_vp_sideplayer_char->move(ui_viewport->width() * other_offset / 100,
+ 0);
+
+ QStringList args = m_chatmessage[OTHER_CHARID].split("^");
+ if (args.size() >
+ 1) // This ugly workaround is so we don't make an extra packet just
+ // for this purpose. Rewrite pairing when?
+ {
+ // Change the order of appearance based on the pair order variable
+ int order = args.at(1).toInt();
+ switch (order) {
+ case 0:
+ ui_vp_sideplayer_char->stackUnder(ui_vp_player_char);
+ break;
+ case 1:
+ ui_vp_player_char->stackUnder(ui_vp_sideplayer_char);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // We should probably also play the other character's idle emote.
+ if (ao_app->flipping_enabled && m_chatmessage[OTHER_FLIP].toInt() == 1)
+ ui_vp_sideplayer_char->set_flipped(true);
+ else
+ ui_vp_sideplayer_char->set_flipped(false);
+ ui_vp_sideplayer_char->play_idle(m_chatmessage[OTHER_NAME],
+ m_chatmessage[OTHER_EMOTE]);
+ }
+ else {
+ // If the server understands other characters, but there
+ // really is no second character, hide 'em, and center the first.
+ ui_vp_sideplayer_char->hide();
+ ui_vp_sideplayer_char->move(0, 0);
+ }
+ }
+ }
+ // Set ourselves according to SELF_OFFSET
+
+ bool ok;
+ int self_offset = m_chatmessage[SELF_OFFSET].toInt(&ok);
+ if (ok)
+ ui_vp_player_char->move(ui_viewport->width() * self_offset / 100, 0);
+ else
+ ui_vp_player_char->move(0, 0);
+
+ switch (emote_mod) {
+ case 1:
+ case 2:
+ case 6:
+ play_preanim(false);
+ break;
+ case 0:
+ case 5:
+ if (m_chatmessage[NONINTERRUPTING_PRE].toInt() == 0)
+ handle_chatmessage_3();
+ else
+ play_preanim(true);
+ break;
+ default:
+ qDebug() << "W: invalid emote mod: " << QString::number(emote_mod);
+ }
+}
+
+void Courtroom::do_screenshake()
+{
+ if (!ao_app->is_shake_enabled())
+ return;
+
+ // This way, the animation is reset in such a way that last played screenshake
+ // would return to its "final frame" properly. This properly resets all UI
+ // elements without having to bother keeping track of "origin" positions.
+ // Works great wit the chat text being detached from the chat box!
+ screenshake_animation_group->setCurrentTime(
+ screenshake_animation_group->duration());
+ screenshake_animation_group->clear();
+
+ QList<QWidget *> affected_list = {ui_vp_background, ui_vp_player_char,
+ ui_vp_sideplayer_char, ui_vp_chatbox};
+
+ // I would prefer if this was its own "shake" function to be honest.
+ foreach (QWidget *ui_element, affected_list) {
+ QPropertyAnimation *screenshake_animation =
+ new QPropertyAnimation(ui_element, "pos", this);
+ QPoint pos_default = QPoint(ui_element->x(), ui_element->y());
+
+ int duration = 300; // How long does the screenshake last
+ int frequency = 20; // How often in ms is there a "jolt" frame
+ int maxframes = duration / frequency;
+ int max_x = 7; // Max deviation from origin on x axis
+ int max_y = 7; // Max deviation from origin on y axis
+ screenshake_animation->setDuration(duration);
+ for (int frame = 0; frame < maxframes; frame++) {
+ double fraction = double(frame * frequency) / duration;
+ int rng = qrand(); // QRandomGenerator::global()->generate();
+ int rand_x = max_x - (int(rng) % (max_x * 2));
+ int rand_y = max_y - (int(rng + 100) % (max_y * 2));
+ screenshake_animation->setKeyValueAt(
+ fraction, QPoint(pos_default.x() + rand_x, pos_default.y() + rand_y));
+ }
+ screenshake_animation->setEndValue(pos_default);
+ screenshake_animation->setEasingCurve(QEasingCurve::Linear);
+ screenshake_animation_group->addAnimation(screenshake_animation);
+ }
+
+ screenshake_animation_group->start();
+}
+
+void Courtroom::do_flash()
+{
+ if (!ao_app->is_effects_enabled())
+ return;
+
+ QString f_char = m_chatmessage[CHAR_NAME];
+ QString f_custom_theme = ao_app->get_char_shouts(f_char);
+ ui_vp_effect->play("realizationflash", f_char, f_custom_theme, 60);
+}
+
+void Courtroom::do_effect(QString fx_name, QString fx_sound, QString p_char,
+ QString p_folder)
+{
+
+ QString effect = ao_app->get_effect(fx_name, p_char, p_folder);
+ if (effect == "")
+ return;
+
+ if (fx_sound != "")
+ sfx_player->play(fx_sound);
+
+ // Only check if effects are disabled after playing the sound if it exists
+ if (!ao_app->is_effects_enabled())
+ return;
+
+ ui_vp_effect->set_play_once(
+ false); // The effects themselves dictate whether or not they're looping.
+ // Static effects will linger.
+ ui_vp_effect->play(effect); // It will set_play_once to true if the filepath
+ // provided is not designed to loop more than once
+}
+
+void Courtroom::play_char_sfx(QString sfx_name)
+{
+ sfx_player->play(sfx_name);
+ // sfx_player->set_looping(false);
+ // if (ao_app->get_looping_sfx())
+ // sfx_player->set_looping(
+ // ao_app->get_sfx_looping(current_char, current_emote) == "1");
+}
+
+void Courtroom::handle_chatmessage_3()
+{
+ int f_evi_id = m_chatmessage[EVIDENCE_ID].toInt();
+ QString f_side = m_chatmessage[SIDE];
+
+ QString f_showname;
+ int f_char_id = m_chatmessage[CHAR_ID].toInt();
+ if (f_char_id > -1 &&
+ (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) {
+ f_showname = ao_app->get_showname(char_list.at(f_char_id).name);
+ }
+ else {
+ f_showname = m_chatmessage[SHOWNAME];
+ }
+ if (f_showname.trimmed()
+ .isEmpty()) // Pure whitespace showname, get outta here.
+ f_showname = m_chatmessage[CHAR_NAME];
+
+ if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size()) {
+ // shifted by 1 because 0 is no evidence per legacy standards
+ QString f_image = local_evidence_list.at(f_evi_id - 1).image;
+ QString f_name = local_evidence_list.at(f_evi_id - 1).name;
+ // def jud and hlp should display the evidence icon on the RIGHT side
+ bool is_left_side = !(f_side == "def" || f_side == "hlp" ||
+ f_side == "jud" || f_side == "jur");
+ ui_vp_evidence_display->show_evidence(f_image, is_left_side,
+ ui_sfx_slider->value());
+ append_ic_text(f_name, f_showname, "has presented evidence");
+ }
+
+ int emote_mod = m_chatmessage[EMOTE_MOD].toInt();
+
+ QString side = m_chatmessage[SIDE];
+
+ if (emote_mod == 5 || emote_mod == 6) {
+ ui_vp_desk->hide();
+ ui_vp_legacy_desk->hide();
+
+ // Since we're zooming, hide the second character, and centre the first.
+ ui_vp_sideplayer_char->hide();
+ ui_vp_player_char->move(0, 0);
+
+ QString f_char = m_chatmessage[CHAR_NAME];
+ QString f_custom_theme = ao_app->get_char_shouts(f_char);
+ if (side == "pro" || side == "hlp" || side == "wit")
+ ui_vp_speedlines->play("prosecution_speedlines", f_char, f_custom_theme);
+ else
+ ui_vp_speedlines->play("defense_speedlines", f_char, f_custom_theme);
+ }
+
+ // If this color is talking
+ color_is_talking =
+ color_markdown_talking_list.at(m_chatmessage[TEXT_COLOR].toInt());
+
+ if (color_is_talking && text_state == 1 &&
+ anim_state < 2) // Set it to talking as we're not on that already
+ {
+ ui_vp_player_char->stop();
+ ui_vp_player_char->play_talking(m_chatmessage[CHAR_NAME],
+ m_chatmessage[EMOTE]);
+ anim_state = 2;
+ }
+ else if (anim_state < 3) // Set it to idle as we're not on that already
+ {
+ ui_vp_player_char->stop();
+ ui_vp_player_char->play_idle(m_chatmessage[CHAR_NAME],
+ m_chatmessage[EMOTE]);
+ anim_state = 3;
+ }
+
+ QString f_message = m_chatmessage[MESSAGE];
+ QStringList call_words = ao_app->get_call_words();
+
+ for (QString word : call_words) {
+ if (f_message.contains(word, Qt::CaseInsensitive)) {
+ modcall_player->play(ao_app->get_sfx("word_call"));
+ ao_app->alert(this);
+
+ break;
+ }
+ }
+
+ start_chat_ticking();
+}
+
+QString Courtroom::filter_ic_text(QString p_text, bool html, int target_pos,
+ int default_color)
+{
+ QString p_text_escaped;
+
+ int check_pos = 0;
+ int check_pos_escaped = 0;
+ bool parse_escape_seq = false;
+ std::stack<int> ic_color_stack;
+
+ // Text alignment shenanigans. Could make a dropdown for this later, too!
+ QString align;
+ if (p_text.trimmed().startsWith("~~")) {
+ p_text.remove(p_text.indexOf("~~"), 2);
+ if (target_pos != -1) {
+ target_pos = qMax(0, target_pos - 2);
+ }
+ align = "center";
+ }
+ else if (p_text.trimmed().startsWith("~>")) {
+ p_text.remove(p_text.indexOf("~>"), 2);
+ if (target_pos != -1) {
+ target_pos = qMax(0, target_pos - 2);
+ }
+ align = "right";
+ }
+ else if (p_text.trimmed().startsWith("<>")) {
+ p_text.remove(p_text.indexOf("<>"), 2);
+ if (target_pos != -1) {
+ target_pos = qMax(0, target_pos - 2);
+ }
+ align = "justify";
+ }
+
+ // If html is enabled, prepare this text to be all ready for it.
+ if (html) {
+ ic_color_stack.push(default_color);
+ QString appendage = "<font color=\"" +
+ color_rgb_list.at(default_color).name(QColor::HexRgb) +
+ "\">";
+
+ if (!align.isEmpty())
+ appendage.prepend("<div align=" + align + ">");
+
+ p_text_escaped.insert(check_pos_escaped, appendage);
+ check_pos_escaped += appendage.size();
+ }
+
+ // Current issue: does not properly escape html stuff.
+ // Solution: probably parse p_text and export into a different string
+ // separately, perform some mumbo jumbo to properly adjust string indexes.
+ while (check_pos < p_text.size()) {
+ QString f_rest = p_text.right(p_text.size() - check_pos);
+ QTextBoundaryFinder tbf(QTextBoundaryFinder::Grapheme, f_rest);
+ QString f_character;
+ int f_char_length;
+ int f_char_bytes;
+
+ tbf.toNextBoundary();
+
+ if (tbf.position() == -1)
+ f_character = f_rest;
+ else
+ f_character = f_rest.left(tbf.position());
+
+ // if (f_character == "&") //oh shit it's probably an escaped html
+ // {
+ // //Skip escaped chars like you would graphemes
+ // QRegularExpression re("&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});",
+ // QRegularExpression::CaseInsensitiveOption); QRegularExpressionMatch
+ // match = re.match(f_rest); if (match.hasMatch()) //OH SHIT IT IS,
+ // PANIC, PANIC
+ // {
+ // f_character = match.captured(0); //Phew, we solved the big problem
+ // here.
+ // }
+ // }
+
+ f_char_bytes = f_char_length = f_character.length();
+
+ if (html) {
+ f_character = f_character.toHtmlEscaped();
+ f_char_length = f_character.length();
+ }
+
+ bool color_update = false;
+ bool is_end = false;
+ bool skip = false;
+
+ if (!parse_escape_seq) {
+ if (f_character == "\\") {
+ parse_escape_seq = true;
+ skip = true;
+ }
+ // Nothing related to colors here
+ else if (f_character == "{" ||
+ f_character ==
+ "}") //|| f_character == "@" || f_character == "$")
+ {
+ skip = true;
+ }
+ // Parse markdown colors
+ else {
+ for (int c = 0; c < max_colors; ++c) {
+ // Clear the stored optimization information
+ QString markdown_start = color_markdown_start_list.at(c);
+ QString markdown_end = color_markdown_end_list.at(c);
+ if (html) {
+ markdown_start = markdown_start.toHtmlEscaped();
+ markdown_end = markdown_end.toHtmlEscaped();
+ }
+ bool markdown_remove = color_markdown_remove_list.at(c);
+ if (markdown_start.isEmpty()) // Not defined
+ continue;
+
+ if (markdown_end.isEmpty() ||
+ markdown_end == markdown_start) //"toggle switch" type
+ {
+ if (f_character == markdown_start) {
+ if (html) {
+ if (!ic_color_stack.empty() && ic_color_stack.top() == c &&
+ default_color != c) {
+ ic_color_stack.pop(); // Cease our coloring
+ is_end = true;
+ }
+ else {
+ ic_color_stack.push(c); // Begin our coloring
+ }
+ color_update = true;
+ }
+ skip = markdown_remove;
+ break; // Prevent it from looping forward for whatever reason
+ }
+ }
+ else if (f_character == markdown_start ||
+ (f_character == markdown_end && !ic_color_stack.empty() &&
+ ic_color_stack.top() == c)) {
+ if (html) {
+ if (f_character == markdown_end) {
+ ic_color_stack.pop(); // Cease our coloring
+ is_end = true;
+ }
+ else if (f_character == markdown_start) {
+ ic_color_stack.push(c); // Begin our coloring
+ }
+ color_update = true;
+ }
+ skip = markdown_remove;
+ break; // Prevent it from looping forward for whatever reason
+ }
+ }
+ // Parse the newest color stack
+ if (color_update && (target_pos <= -1 || check_pos < target_pos)) {
+ if (!parse_escape_seq) {
+ QString appendage = "</font>";
+
+ if (!ic_color_stack.empty())
+ appendage +=
+ "<font color=\"" +
+ color_rgb_list.at(ic_color_stack.top()).name(QColor::HexRgb) +
+ "\">";
+
+ if (is_end && !skip) {
+ p_text_escaped.insert(check_pos_escaped,
+ f_character); // Add that char right now
+ check_pos_escaped +=
+ f_char_length; // So the closing char is captured too
+ skip = true;
+ }
+ p_text_escaped.insert(check_pos_escaped, appendage);
+ check_pos_escaped += appendage.size();
+ }
+ }
+ }
+ }
+ else {
+ if (f_character == "n") // \n, that's a line break son
+ {
+ QString appendage = "<br/>";
+ if (!html) {
+ // actual newline commented out
+ // appendage = "\n";
+ // size = 1; //yeah guess what \n is a "single character"
+ // apparently
+ appendage = "\\n "; // visual representation of a newline
+ }
+ p_text_escaped.insert(check_pos_escaped, appendage);
+ check_pos_escaped += appendage.size();
+ skip = true;
+ }
+ if (f_character == "s" || f_character == "f") // screenshake/flash
+ skip = true;
+
+ parse_escape_seq = false;
+ }
+
+ // Make all chars we're not supposed to see invisible
+ if (target_pos > -1 && check_pos == target_pos) {
+ QString appendage = "";
+ if (!ic_color_stack.empty()) {
+ if (!is_end) // Was our last coloring char ending the color stack or nah
+ {
+ // God forgive me for my transgressions but I have refactored this
+ // whole thing about 25 times and having to refactor it again to more
+ // elegantly support this will finally make me go insane.
+ color_is_talking =
+ color_markdown_talking_list.at(ic_color_stack.top());
+ }
+
+ // Clean it up, we're done here
+ while (!ic_color_stack.empty())
+ ic_color_stack.pop();
+
+ appendage += "</font>";
+ }
+ ic_color_stack.push(
+ -1); // Dummy colorstack push for maximum </font> appendage
+ appendage += "<font color=\"#00000000\">";
+ p_text_escaped.insert(check_pos_escaped, appendage);
+ check_pos_escaped += appendage.size();
+ }
+ if (!skip) {
+ p_text_escaped.insert(check_pos_escaped, f_character);
+ check_pos_escaped += f_char_length;
+ }
+ check_pos += f_char_bytes;
+ }
+
+ if (!ic_color_stack.empty() && html) {
+ p_text_escaped.append("</font>");
+ }
+
+ if (html) {
+ // Example: https://regex101.com/r/oL4nM9/37 - this replaces
+ // excessive/trailing/etc. whitespace with non-breaking space. I WOULD use
+ // white-space: pre; stylesheet tag, but for whataver reason it doesn't work
+ // no matter where I try it. If somoene else can get that piece of HTML
+ // memery to work, please do.
+ p_text_escaped.replace(QRegularExpression("^\\s|(?<=\\s)\\s"), "&nbsp;");
+ if (!align.isEmpty())
+ p_text_escaped.append("</div>");
+ }
+
+ return p_text_escaped;
+}
+
+void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action, int color)
+{
+ QTextCharFormat bold;
+ QTextCharFormat normal;
+ QTextCharFormat italics;
+ bold.setFontWeight(QFont::Bold);
+ normal.setFontWeight(QFont::Normal);
+ italics.setFontItalic(true);
+ const QTextCursor old_cursor = ui_ic_chatlog->textCursor();
+ const int old_scrollbar_value = ui_ic_chatlog->verticalScrollBar()->value();
+
+ if (p_action == "")
+ p_text = filter_ic_text(p_text, ao_app->is_colorlog_enabled(), -1,
+ color);
+
+ if (log_goes_downwards) {
+ const bool is_scrolled_down =
+ old_scrollbar_value == ui_ic_chatlog->verticalScrollBar()->maximum();
+
+ ui_ic_chatlog->moveCursor(QTextCursor::End);
+
+ if (!first_message_sent) {
+ ui_ic_chatlog->textCursor().insertText(p_name, bold);
+ first_message_sent = true;
+ }
+ else {
+ ui_ic_chatlog->textCursor().insertText('\n' + p_name, bold);
+ }
+
+ if (p_action != "") {
+ ui_ic_chatlog->textCursor().insertText(" " + p_action + ": ", normal);
+ ui_ic_chatlog->textCursor().insertText(p_text + ".", italics);
+ }
+ else {
+ ui_ic_chatlog->textCursor().insertText(": ", normal);
+ ui_ic_chatlog->textCursor().insertHtml(p_text);
+ }
+
+ // If we got too many blocks in the current log, delete some from the top.
+ while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks &&
+ log_maximum_blocks > 0) {
+ ui_ic_chatlog->moveCursor(QTextCursor::Start);
+ ui_ic_chatlog->textCursor().select(QTextCursor::BlockUnderCursor);
+ ui_ic_chatlog->textCursor().removeSelectedText();
+ ui_ic_chatlog->textCursor().deleteChar();
+ }
+
+ if (old_cursor.hasSelection() || !is_scrolled_down) {
+ // The user has selected text or scrolled away from the bottom: maintain
+ // position.
+ ui_ic_chatlog->setTextCursor(old_cursor);
+ ui_ic_chatlog->verticalScrollBar()->setValue(old_scrollbar_value);
+ }
+ else {
+ // The user hasn't selected any text and the scrollbar is at the bottom:
+ // scroll to the bottom.
+ ui_ic_chatlog->moveCursor(QTextCursor::End);
+ ui_ic_chatlog->verticalScrollBar()->setValue(
+ ui_ic_chatlog->verticalScrollBar()->maximum());
+ }
+ }
+ else {
+ const bool is_scrolled_up =
+ old_scrollbar_value == ui_ic_chatlog->verticalScrollBar()->minimum();
+
+ ui_ic_chatlog->moveCursor(QTextCursor::Start);
+
+ ui_ic_chatlog->textCursor().insertText(p_name, bold);
+
+ if (p_action != "") {
+ ui_ic_chatlog->textCursor().insertText(" " + p_action + ": ", normal);
+ ui_ic_chatlog->textCursor().insertText(p_text + "." + '\n', italics);
+ }
+ else {
+ ui_ic_chatlog->textCursor().insertText(": ", normal);
+ ui_ic_chatlog->textCursor().insertHtml(p_text + "<br>");
+ }
+
+ // If we got too many blocks in the current log, delete some from the
+ // bottom.
+ while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks &&
+ log_maximum_blocks > 0) {
+ ui_ic_chatlog->moveCursor(QTextCursor::End);
+ ui_ic_chatlog->textCursor().select(QTextCursor::BlockUnderCursor);
+ ui_ic_chatlog->textCursor().removeSelectedText();
+ ui_ic_chatlog->textCursor().deletePreviousChar();
+ }
+
+ if (old_cursor.hasSelection() || !is_scrolled_up) {
+ // The user has selected text or scrolled away from the top: maintain
+ // position.
+ ui_ic_chatlog->setTextCursor(old_cursor);
+ ui_ic_chatlog->verticalScrollBar()->setValue(old_scrollbar_value);
+ }
+ else {
+ // The user hasn't selected any text and the scrollbar is at the top:
+ // scroll to the top.
+ ui_ic_chatlog->moveCursor(QTextCursor::Start);
+ ui_ic_chatlog->verticalScrollBar()->setValue(
+ ui_ic_chatlog->verticalScrollBar()->minimum());
+ }
+ }
+}
+
+void Courtroom::play_preanim(bool noninterrupting)
+{
+ QString f_char = m_chatmessage[CHAR_NAME];
+ QString f_preanim = m_chatmessage[PRE_EMOTE];
+
+ // all time values in char.inis are multiplied by a constant(time_mod) to get
+ // the actual time
+ int ao2_duration = ao_app->get_ao2_preanim_duration(f_char, f_preanim);
+ int text_delay = ao_app->get_text_delay(f_char, f_preanim) * time_mod;
+ int sfx_delay = m_chatmessage[SFX_DELAY].toInt() * time_mod;
+
+ int preanim_duration;
+
+ if (ao2_duration < 0)
+ preanim_duration = ao_app->get_preanim_duration(f_char, f_preanim);
+ else
+ preanim_duration = ao2_duration;
+
+ sfx_delay_timer->start(sfx_delay);
+ QString anim_to_find =
+ ao_app->get_image_suffix(ao_app->get_character_path(f_char, f_preanim));
+ if (!file_exists(anim_to_find)) {
+ if (noninterrupting)
+ anim_state = 4;
+ else
+ anim_state = 1;
+ preanim_done();
+ qDebug() << "could not find " + anim_to_find;
+ return;
+ }
+
+ ui_vp_player_char->play_pre(f_char, f_preanim, preanim_duration);
+
+ if (noninterrupting)
+ anim_state = 4;
+ else
+ anim_state = 1;
+
+ if (text_delay >= 0)
+ text_delay_timer->start(text_delay);
+
+ if (noninterrupting)
+ handle_chatmessage_3();
+}
+
+void Courtroom::preanim_done()
+{
+ anim_state = 1;
+ handle_chatmessage_3();
+}
+
+void Courtroom::start_chat_ticking()
+{
+ // we need to ensure that the text isn't already ticking because this function
+ // can be called by two logic paths
+ if (text_state != 0)
+ return;
+
+ if (m_chatmessage[EFFECTS] != "") {
+ QStringList fx_list = m_chatmessage[EFFECTS].split("|");
+ QString fx = fx_list[0];
+ QString fx_sound;
+ QString fx_folder;
+
+ if (fx_list.length() > 1)
+ fx_sound = fx_list[1];
+
+ if (fx_list.length() > 2) {
+ fx_folder = fx_list[1];
+ fx_sound = fx_list[2];
+ }
+
+ this->do_effect(fx, fx_sound, m_chatmessage[CHAR_NAME], fx_folder);
+ }
+ else if (m_chatmessage[REALIZATION] == "1") {
+ this->do_flash();
+ sfx_player->play(ao_app->get_custom_realization(m_chatmessage[CHAR_NAME]));
+ }
+ if (chatmessage_is_empty) {
+ // since the message is empty, it's technically done ticking
+ text_state = 2;
+ return;
+ }
+
+ ui_vp_chatbox->show();
+ ui_vp_message->show();
+
+ if (!is_additive) {
+ ui_vp_message->clear();
+ real_tick_pos = 0;
+ additive_previous = "";
+ }
+
+ tick_pos = 0;
+ blip_ticker = 0;
+
+ // At the start of every new message, we set the text speed to the default.
+ current_display_speed = 3;
+ chat_tick_timer->start(0); // Display the first char right away
+
+ QString f_gender = ao_app->get_gender(m_chatmessage[CHAR_NAME]);
+
+ blip_player->set_blips(f_gender);
+
+ int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); // text meme bonanza
+ if ((emote_mod == 0 || emote_mod == 5) && m_chatmessage[SCREENSHAKE] == "1") {
+ this->do_screenshake();
+ }
+
+ // means text is currently ticking
+ text_state = 1;
+}
+
+void Courtroom::chat_tick()
+{
+ // note: this is called fairly often
+ // do not perform heavy operations here
+
+ QString f_message = m_chatmessage[MESSAGE];
+
+ // Due to our new text speed system, we always need to stop the timer now.
+ chat_tick_timer->stop();
+
+ if (tick_pos >= f_message.size()) {
+ text_state = 2;
+ if (anim_state < 3) {
+ anim_state = 3;
+ ui_vp_player_char->play_idle(m_chatmessage[CHAR_NAME],
+ m_chatmessage[EMOTE]);
+ }
+ QString f_char;
+ QString f_custom_theme;
+ if (ao_app->is_customchat_enabled())
+ {
+ f_char = m_chatmessage[CHAR_NAME];
+ f_custom_theme = ao_app->get_chat(f_char);
+ }
+ ui_vp_chat_arrow->play(
+ "chat_arrow", f_char,
+ f_custom_theme); // Chat stopped being processed, indicate that.
+ additive_previous =
+ additive_previous +
+ filter_ic_text(f_message, true, -1, m_chatmessage[TEXT_COLOR].toInt());
+ real_tick_pos = ui_vp_message->toPlainText().size();
+ return;
+ }
+
+ // Stops blips from playing when we have a formatting option.
+ bool formatting_char = false;
+
+ QString f_rest = f_message;
+
+ // Alignment characters
+ if (tick_pos < 2) {
+ if (f_rest.startsWith("~~")) {
+ tick_pos = f_rest.indexOf("~~");
+ f_rest.remove(tick_pos, 2);
+ tick_pos += 2;
+ }
+ else if (f_rest.startsWith("~>")) {
+ tick_pos = f_rest.indexOf("~>");
+ f_rest.remove(tick_pos, 2);
+ tick_pos += 2;
+ }
+ else if (f_rest.startsWith("<>")) {
+ tick_pos = f_rest.indexOf("<>");
+ f_rest.remove(tick_pos, 2);
+ tick_pos += 2;
+ }
+ }
+ f_rest.remove(0, tick_pos);
+ QTextBoundaryFinder tbf(QTextBoundaryFinder::Grapheme, f_rest);
+ QString f_character;
+ int f_char_length;
+
+ tbf.toNextBoundary();
+
+ if (tbf.position() == -1)
+ f_character = f_rest;
+ else
+ f_character = f_rest.left(tbf.position());
+
+ f_char_length = f_character.length();
+ tick_pos += f_char_length;
+
+ // Escape character.
+ if (!next_character_is_not_special) {
+ if (f_character == "\\") {
+ next_character_is_not_special = true;
+ formatting_char = true;
+ }
+
+ // Text speed modifier.
+ else if (f_character == "{") {
+ // ++, because it INCREASES delay!
+ current_display_speed++;
+ formatting_char = true;
+ }
+ else if (f_character == "}") {
+ current_display_speed--;
+ formatting_char = true;
+ }
+
+ else {
+ // Parse markdown colors
+ for (int c = 0; c < max_colors; ++c) {
+ QString markdown_start = color_markdown_start_list.at(c);
+ QString markdown_end = color_markdown_end_list.at(c);
+ bool markdown_remove = color_markdown_remove_list.at(c);
+ if (markdown_start.isEmpty())
+ continue;
+
+ if (f_character == markdown_start || f_character == markdown_end) {
+ if (markdown_remove)
+ formatting_char = true;
+ break;
+ }
+ }
+ }
+ }
+ else {
+ if (f_character == "n")
+ formatting_char = true; // it's a newline
+ if (f_character == "s") // Screenshake.
+ {
+ this->do_screenshake();
+ formatting_char = true;
+ }
+ if (f_character == "f") // Flash.
+ {
+ this->do_flash();
+ formatting_char = true;
+ }
+ next_character_is_not_special = false;
+ }
+
+ if ((message_display_speed[current_display_speed] <= 0 &&
+ tick_pos < f_message.size() - 1) ||
+ formatting_char) {
+ chat_tick_timer->start(0); // Don't bother rendering anything out as we're
+ // doing the SPEED. (there's latency otherwise)
+ if (!formatting_char || f_character == "n" || f_character == "f" ||
+ f_character == "s")
+ real_tick_pos += f_char_length; // Adjust the tick position for the
+ // scrollbar convenience
+ }
+ else {
+ int msg_delay = message_display_speed[current_display_speed];
+ // Do the colors, gradual showing, etc. in here
+ ui_vp_message->setHtml(additive_previous +
+ filter_ic_text(f_message, true, tick_pos,
+ m_chatmessage[TEXT_COLOR].toInt()));
+
+ // This should always be done AFTER setHtml. Scroll the chat window with the
+ // text.
+
+ // Make the cursor follow the message
+ QTextCursor cursor = ui_vp_message->textCursor();
+ cursor.setPosition(real_tick_pos);
+ ui_vp_message->setTextCursor(cursor);
+ real_tick_pos += f_char_length;
+
+ ui_vp_message->ensureCursorVisible();
+
+ // Keep the speed at bay.
+ if (current_display_speed < 0)
+ current_display_speed = 0;
+ else if (current_display_speed > 6)
+ current_display_speed = 6;
+
+ // Blip player and real tick pos ticker
+ if (!formatting_char && (f_character != ' ' || blank_blip)) {
+ if (blip_ticker % blip_rate == 0) {
+ blip_player->blip_tick();
+ }
+ ++blip_ticker;
+ }
+
+ // Punctuation delayer
+ if (punctuation_chars.contains(f_character)) {
+ msg_delay *= punctuation_modifier;
+ }
+
+ // If this color is talking
+ if (color_is_talking && anim_state != 2 &&
+ anim_state <
+ 4) // Set it to talking as we're not on that already (though we have
+ // to avoid interrupting a non-interrupted preanim)
+ {
+ ui_vp_player_char->stop();
+ ui_vp_player_char->play_talking(m_chatmessage[CHAR_NAME],
+ m_chatmessage[EMOTE]);
+ anim_state = 2;
+ }
+ else if (!color_is_talking && anim_state < 3 &&
+ anim_state != 3) // Set it to idle as we're not on that already
+ {
+ ui_vp_player_char->stop();
+ ui_vp_player_char->play_idle(m_chatmessage[CHAR_NAME],
+ m_chatmessage[EMOTE]);
+ anim_state = 3;
+ }
+ // Continue ticking
+ chat_tick_timer->start(msg_delay);
+ }
+}
+
+void Courtroom::play_sfx()
+{
+ QString sfx_name = m_chatmessage[SFX_NAME];
+ if (m_chatmessage[SCREENSHAKE] ==
+ "1") // Screenshake dependant on preanim sfx delay meme
+ {
+ this->do_screenshake();
+ }
+ if (sfx_name == "1")
+ return;
+
+ sfx_player->play(sfx_name);
+ if (ao_app->get_looping_sfx())
+ sfx_player->set_looping(
+ ao_app->get_sfx_looping(current_char, current_emote) == "1");
+}
+
+void Courtroom::set_scene(QString f_desk_mod, QString f_side)
+{
+ // witness is default if pos is invalid
+ QString f_background = "witnessempty";
+ QString f_desk_image = "stand";
+
+ if (f_side == "def" && file_exists(ao_app->get_image_suffix(
+ ao_app->get_background_path("defenseempty")))) {
+ f_background = "defenseempty";
+ f_desk_image = "defensedesk";
+ }
+ else if (f_side == "pro" &&
+ file_exists(ao_app->get_image_suffix(
+ ao_app->get_background_path("prosecutorempty")))) {
+ f_background = "prosecutorempty";
+ f_desk_image = "prosecutiondesk";
+ }
+ else if (f_side == "jud" && file_exists(ao_app->get_image_suffix(
+ ao_app->get_background_path("judgestand")))) {
+ f_background = "judgestand";
+ f_desk_image = "judgedesk";
+ }
+ else if (f_side == "hld" &&
+ file_exists(ao_app->get_image_suffix(
+ ao_app->get_background_path("helperstand")))) {
+ f_background = "helperstand";
+ f_desk_image = "helperdesk";
+ }
+ else if (f_side == "hlp" &&
+ file_exists(ao_app->get_image_suffix(
+ ao_app->get_background_path("prohelperstand")))) {
+ f_background = "prohelperstand";
+ f_desk_image = "prohelperdesk";
+ }
+ else if (f_side == "jur" && file_exists(ao_app->get_image_suffix(
+ ao_app->get_background_path("jurystand")))) {
+ f_background = "jurystand";
+ f_desk_image = "jurydesk";
+ }
+ else if (f_side == "sea" &&
+ file_exists(ao_app->get_image_suffix(
+ ao_app->get_background_path("seancestand")))) {
+ f_background = "seancestand";
+ f_desk_image = "seancedesk";
+ }
+
+ if (file_exists(ao_app->get_image_suffix(
+ ao_app->get_background_path(f_side)))) // Unique pos path
+ {
+ f_background = f_side;
+ f_desk_image = f_side + "_overlay";
+ }
+
+ ui_vp_background->set_image(f_background);
+ ui_vp_desk->set_image(f_desk_image);
+ ui_vp_legacy_desk->set_legacy_desk(f_desk_image);
+
+ if (f_desk_mod == "0" ||
+ (f_desk_mod != "1" &&
+ (f_side == "jud" || f_side == "hld" || f_side == "hlp"))) {
+ ui_vp_desk->hide();
+ ui_vp_legacy_desk->hide();
+ }
+ else {
+ ui_vp_legacy_desk->hide();
+ ui_vp_desk->show();
+ }
+}
+
+void Courtroom::set_ip_list(QString p_list)
+{
+ QString f_list = p_list.replace("|", ":").replace("*", "\n");
+
+ ui_server_chatlog->append(f_list);
+}
+
+void Courtroom::set_mute(bool p_muted, int p_cid)
+{
+ if (p_cid != m_cid && p_cid != -1)
+ return;
+
+ if (p_muted)
+ ui_muted->show();
+ else {
+ ui_muted->hide();
+ ui_ic_chat_message->setFocus();
+ }
+
+ ui_muted->resize(ui_ic_chat_message->width(), ui_ic_chat_message->height());
+ ui_muted->set_image("muted");
+
+ is_muted = p_muted;
+ ui_ic_chat_message->setEnabled(!p_muted);
+}
+
+void Courtroom::set_ban(int p_cid)
+{
+ if (p_cid != m_cid && p_cid != -1)
+ return;
+
+ call_notice(tr("You have been banned."));
+
+ ao_app->construct_lobby();
+ ao_app->destruct_courtroom();
+}
+
+void Courtroom::handle_song(QStringList *p_contents)
+{
+ QStringList f_contents = *p_contents;
+
+ if (f_contents.size() < 2)
+ return;
+
+ QString f_song = f_contents.at(0);
+ QString f_song_clear = f_song.left(f_song.lastIndexOf("."));
+ f_song_clear = f_song_clear.right(f_song_clear.length() -
+ (f_song_clear.lastIndexOf("/") + 1));
+ int n_char = f_contents.at(1).toInt();
+
+ // Assume the song doesn't loop unless told otherwise (due to most outdated
+ // servers handling looping through serverside)
+ bool looping = false;
+ // Channel 0 is the 'master music', other channels would commonly be used for
+ // ambience
+ int channel = 0;
+ // No effects assumed by default - vanilla functionality
+ int effect_flags = 0;
+
+ if (n_char < 0 || n_char >= char_list.size()) {
+ int channel = 0;
+ if (p_contents->length() > 3 && p_contents->at(3) == "1")
+ looping = true;
+
+ if (p_contents->length() >
+ 4) // eyyy we want to change this song's CHANNEL huh
+ channel = p_contents->at(4).toInt(); // let the music player handle it if
+ // it's bigger than the channel list
+
+ if (p_contents->length() > 5) // Flags provided to us by server such as Fade
+ // In, Fade Out, Sync Pos etc.
+ {
+ effect_flags = p_contents->at(5).toInt();
+ }
+
+ music_player->play(f_song, channel, looping, effect_flags);
+ if (channel == 0)
+ ui_music_name->setText(f_song_clear);
+ }
+ else {
+ QString str_char = char_list.at(n_char).name;
+ QString str_show = char_list.at(n_char).name;
+
+ if (p_contents->length() > 2) {
+ if (p_contents->at(2) != "") {
+ str_show = p_contents->at(2);
+ }
+ }
+ if (p_contents->length() > 3 && p_contents->at(3) == "1") {
+ looping = true;
+ }
+ if (p_contents->length() >
+ 4) // eyyy we want to change this song's CHANNEL huh
+ channel = p_contents->at(4).toInt(); // let the music player handle it if
+ // it's bigger than the channel list
+
+ if (p_contents->length() > 5) // Flags provided to us by server such as Fade
+ // In, Fade Out, Sync Pos etc.
+ {
+ effect_flags = p_contents->at(5).toInt();
+ }
+
+ if (!mute_map.value(n_char)) {
+ chatlogpiece *temp = new chatlogpiece(str_char, str_show, f_song, true, m_chatmessage[TEXT_COLOR].toInt());
+ ic_chatlog_history.append(*temp);
+ if (ao_app->get_auto_logging_enabled())
+ ao_app->append_to_file(temp->get_full(), ao_app->log_filename, true);
+
+ while (ic_chatlog_history.size() > log_maximum_blocks &&
+ log_maximum_blocks > 0) {
+ ic_chatlog_history.removeFirst();
+ }
+
+ append_ic_text(f_song_clear, str_show, tr("has played a song"));
+
+ music_player->play(f_song, channel, looping, effect_flags);
+ if (channel == 0)
+ ui_music_name->setText(f_song_clear);
+ }
+ }
+}
+
+void Courtroom::handle_wtce(QString p_wtce, int variant)
+{
+ QString sfx_file = "courtroom_sounds.ini";
+
+ // witness testimony
+ if (p_wtce == "testimony1") {
+ sfx_player->play(ao_app->get_sfx("witness_testimony"));
+ ui_vp_wtce->play("witnesstestimony", "", "", 1500);
+ ui_vp_testimony->play("testimony");
+ }
+ // cross examination
+ else if (p_wtce == "testimony2") {
+ sfx_player->play(ao_app->get_sfx("cross_examination"));
+ ui_vp_wtce->play("crossexamination", "", "", 1500);
+ ui_vp_testimony->stop();
+ }
+ else if (p_wtce == "judgeruling") {
+ if (variant == 0) {
+ sfx_player->play(ao_app->get_sfx("not_guilty"));
+ ui_vp_wtce->play("notguilty", "", "", 3000);
+ ui_vp_testimony->stop();
+ }
+ else if (variant == 1) {
+ sfx_player->play(ao_app->get_sfx("guilty"));
+ ui_vp_wtce->play("guilty", "", "", 3000);
+ ui_vp_testimony->stop();
+ }
+ }
+}
+
+void Courtroom::set_hp_bar(int p_bar, int p_state)
+{
+ if (p_state < 0 || p_state > 10)
+ return;
+
+ if (p_bar == 1) {
+ ui_defense_bar->set_image("defensebar" + QString::number(p_state));
+ defense_bar_state = p_state;
+ }
+ else if (p_bar == 2) {
+ ui_prosecution_bar->set_image("prosecutionbar" + QString::number(p_state));
+ prosecution_bar_state = p_state;
+ }
+}
+
+void Courtroom::toggle_judge_buttons(bool is_on)
+{
+ if (is_on) {
+ ui_witness_testimony->show();
+ ui_cross_examination->show();
+ ui_guilty->show();
+ ui_not_guilty->show();
+ ui_defense_minus->show();
+ ui_defense_plus->show();
+ ui_prosecution_minus->show();
+ ui_prosecution_plus->show();
+ }
+ else {
+ ui_witness_testimony->hide();
+ ui_cross_examination->hide();
+ ui_guilty->hide();
+ ui_not_guilty->hide();
+ ui_defense_minus->hide();
+ ui_defense_plus->hide();
+ ui_prosecution_minus->hide();
+ ui_prosecution_plus->hide();
+ }
+}
+
+void Courtroom::mod_called(QString p_ip)
+{
+ ui_server_chatlog->append(p_ip);
+ if (!ui_guard->isChecked()) {
+ modcall_player->play(ao_app->get_sfx("mod_call"));
+ ao_app->alert(this);
+ }
+}
+
+void Courtroom::case_called(QString msg, bool def, bool pro, bool jud, bool jur,
+ bool steno)
+{
+ if (ui_casing->isChecked()) {
+ ui_server_chatlog->append(msg);
+ if ((ao_app->get_casing_defence_enabled() && def) ||
+ (ao_app->get_casing_prosecution_enabled() && pro) ||
+ (ao_app->get_casing_judge_enabled() && jud) ||
+ (ao_app->get_casing_juror_enabled() && jur) ||
+ (ao_app->get_casing_steno_enabled() && steno)) {
+ modcall_player->play(ao_app->get_sfx("case_call"));
+ ao_app->alert(this);
+ }
+ }
+}
+
+void Courtroom::on_ooc_return_pressed()
+{
+ QString ooc_message = ui_ooc_chat_message->text();
+
+ if (ooc_message == "" || ui_ooc_chat_name->text() == "")
+ return;
+
+ if (ooc_message.startsWith("/pos")) {
+ if (ooc_message == "/pos jud") {
+ toggle_judge_buttons(true);
+ }
+ else {
+ toggle_judge_buttons(false);
+ }
+ }
+ else if (ooc_message.startsWith("/settings")) {
+ ui_ooc_chat_message->clear();
+ ao_app->call_settings_menu();
+ append_server_chatmessage("CLIENT", tr("You opened the settings menu."),
+ "1");
+ return;
+ }
+ else if (ooc_message.startsWith("/pair")) {
+ ui_ooc_chat_message->clear();
+ ooc_message.remove(0, 6);
+
+ bool ok;
+ int whom = ooc_message.toInt(&ok);
+ if (ok) {
+ if (whom > -1) {
+ other_charid = whom;
+ QString msg = tr("You will now pair up with %1 if they also choose "
+ "your character in return.")
+ .arg(char_list.at(whom).name);
+ append_server_chatmessage("CLIENT", msg, "1");
+ }
+ else {
+ other_charid = -1;
+ append_server_chatmessage(
+ "CLIENT", tr("You are no longer paired with anyone."), "1");
+ }
+ }
+ else {
+ append_server_chatmessage("CLIENT",
+ tr("Are you sure you typed that well? The char "
+ "ID could not be recognised."),
+ "1");
+ }
+ return;
+ }
+ else if (ooc_message.startsWith("/offset")) {
+ ui_ooc_chat_message->clear();
+ ooc_message.remove(0, 8);
+
+ bool ok;
+ int off = ooc_message.toInt(&ok);
+ if (ok) {
+ if (off >= -100 && off <= 100) {
+ char_offset = off;
+ QString msg = tr("You have set your offset to ");
+ msg.append(QString::number(off));
+ msg.append("%.");
+ append_server_chatmessage("CLIENT", msg, "1");
+ }
+ else {
+ append_server_chatmessage(
+ "CLIENT", tr("Your offset must be between -100% and 100%!"), "1");
+ }
+ }
+ else {
+ append_server_chatmessage("CLIENT",
+ tr("That offset does not look like one."), "1");
+ }
+ return;
+ }
+ else if (ooc_message.startsWith("/switch_am")) {
+ append_server_chatmessage(
+ "CLIENT", tr("You switched your music and area list."), "1");
+ on_switch_area_music_clicked();
+ ui_ooc_chat_message->clear();
+ return;
+ }
+ else if (ooc_message.startsWith("/enable_blocks")) {
+ append_server_chatmessage("CLIENT",
+ tr("You have forcefully enabled features that "
+ "the server may not support. You may not be "
+ "able to talk IC, or worse, because of this."),
+ "1");
+ ao_app->cccc_ic_support_enabled = true;
+ ao_app->arup_enabled = true;
+ ao_app->modcall_reason_enabled = true;
+ on_reload_theme_clicked();
+ ui_ooc_chat_message->clear();
+ return;
+ }
+ else if (ooc_message.startsWith("/non_int_pre")) {
+ if (ui_pre_non_interrupt->isChecked())
+ append_server_chatmessage(
+ "CLIENT", tr("Your pre-animations interrupt again."), "1");
+ else
+ append_server_chatmessage(
+ "CLIENT", tr("Your pre-animations will not interrupt text."), "1");
+ ui_pre_non_interrupt->setChecked(!ui_pre_non_interrupt->isChecked());
+ ui_ooc_chat_message->clear();
+ return;
+ }
+ else if (ooc_message.startsWith("/save_chatlog")) {
+ QFile file("chatlog.txt");
+
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text |
+ QIODevice::Truncate)) {
+ append_server_chatmessage(
+ "CLIENT", tr("Couldn't open chatlog.txt to write into."), "1");
+ ui_ooc_chat_message->clear();
+ return;
+ }
+
+ QTextStream out(&file);
+
+ foreach (chatlogpiece item, ic_chatlog_history) {
+ out << item.get_full() << '\n';
+ }
+
+ file.close();
+
+ append_server_chatmessage("CLIENT", tr("The IC chatlog has been saved."),
+ "1");
+ ui_ooc_chat_message->clear();
+ return;
+ }
+ else if (ooc_message.startsWith("/load_case")) {
+ QStringList command = ooc_message.split(" ", QString::SkipEmptyParts);
+
+ QDir casefolder("base/cases");
+ if (!casefolder.exists()) {
+ QDir::current().mkdir("base/" + casefolder.dirName());
+ append_server_chatmessage(
+ "CLIENT",
+ tr("You don't have a `base/cases/` folder! It was just made for you, "
+ "but seeing as it WAS just made for you, it's likely the case "
+ "file you're looking for can't be found in there."),
+ "1");
+ ui_ooc_chat_message->clear();
+ return;
+ }
+ QStringList caseslist = casefolder.entryList();
+ caseslist.removeOne(".");
+ caseslist.removeOne("..");
+ caseslist.replaceInStrings(".ini", "");
+
+ if (command.size() < 2) {
+ append_server_chatmessage(
+ "CLIENT",
+ tr("You need to give a filename to load (extension not needed)! Make "
+ "sure that it is in the `base/cases/` folder, and that it is a "
+ "correctly formatted ini.\nCases you can load: %1")
+ .arg(caseslist.join(", ")),
+ "1");
+ ui_ooc_chat_message->clear();
+ return;
+ }
+
+ if (command.size() > 2) {
+ append_server_chatmessage(
+ "CLIENT",
+ tr("Too many arguments to load a case! You only need one filename, "
+ "without extension."),
+ "1");
+ ui_ooc_chat_message->clear();
+ return;
+ }
+
+ QSettings casefile("base/cases/" + command[1] + ".ini",
+ QSettings::IniFormat);
+
+ QString caseauth = casefile.value("author", "").value<QString>();
+ QString casedoc = casefile.value("doc", "").value<QString>();
+ QString cmdoc = casefile.value("cmdoc", "").value<QString>();
+ QString casestatus = casefile.value("status", "").value<QString>();
+
+ if (!caseauth.isEmpty())
+ append_server_chatmessage(tr("CLIENT"),
+ tr("Case made by %1.").arg(caseauth), "1");
+ if (!casedoc.isEmpty())
+ ao_app->send_server_packet(new AOPacket("CT#" + ui_ooc_chat_name->text() +
+ "#/doc " + casedoc + "#%"));
+ if (!casestatus.isEmpty())
+ ao_app->send_server_packet(new AOPacket("CT#" + ui_ooc_chat_name->text() +
+ "#/status " + casestatus + "#%"));
+ if (!cmdoc.isEmpty())
+ append_server_chatmessage(
+ "CLIENT", tr("Navigate to %1 for the CM doc.").arg(cmdoc), "1");
+
+ for (int i = local_evidence_list.size() - 1; i >= 0; i--) {
+ ao_app->send_server_packet(
+ new AOPacket("DE#" + QString::number(i) + "#%"));
+ }
+
+ foreach (QString evi, casefile.childGroups()) {
+ if (evi == "General")
+ continue;
+
+ QStringList f_contents;
+
+ f_contents.append(
+ casefile.value(evi + "/name", tr("UNKNOWN")).value<QString>());
+ f_contents.append(
+ casefile.value(evi + "/description", tr("UNKNOWN")).value<QString>());
+ f_contents.append(
+ casefile.value(evi + "/image", "UNKNOWN.png").value<QString>());
+
+ ao_app->send_server_packet(new AOPacket("PE", f_contents));
+ }
+
+ append_server_chatmessage(
+ "CLIENT", tr("Your case \"%1\" was loaded!").arg(command[1]), "1");
+ ui_ooc_chat_message->clear();
+ return;
+ }
+ else if (ooc_message.startsWith("/save_case")) {
+ QStringList command = ooc_message.split(" ", QString::SkipEmptyParts);
+
+ QDir casefolder("base/cases");
+ if (!casefolder.exists()) {
+ QDir::current().mkdir("base/" + casefolder.dirName());
+ append_server_chatmessage(
+ "CLIENT",
+ tr("You don't have a `base/cases/` folder! It was just made for you, "
+ "but seeing as it WAS just made for you, it's likely that you "
+ "somehow deleted it."),
+ "1");
+ ui_ooc_chat_message->clear();
+ return;
+ }
+ QStringList caseslist = casefolder.entryList();
+ caseslist.removeOne(".");
+ caseslist.removeOne("..");
+ caseslist.replaceInStrings(".ini", "");
+
+ if (command.size() < 3) {
+ append_server_chatmessage(
+ "CLIENT",
+ tr("You need to give a filename to save (extension not needed) and "
+ "the courtroom status!"),
+ "1");
+ ui_ooc_chat_message->clear();
+ return;
+ }
+
+ if (command.size() > 3) {
+ append_server_chatmessage(
+ "CLIENT",
+ tr("Too many arguments to save a case! You only need a filename "
+ "without extension and the courtroom status!"),
+ "1");
+ ui_ooc_chat_message->clear();
+ return;
+ }
+ QSettings casefile("base/cases/" + command[1] + ".ini",
+ QSettings::IniFormat);
+ casefile.setValue("author", ui_ooc_chat_name->text());
+ casefile.setValue("cmdoc", "");
+ casefile.setValue("doc", "");
+ casefile.setValue("status", command[2]);
+ casefile.sync();
+ for (int i = 0; i < local_evidence_list.size(); i++) {
+ QString clean_evidence_dsc = local_evidence_list[i].description.replace(
+ QRegularExpression("<owner = ...>..."), "");
+ clean_evidence_dsc = clean_evidence_dsc.replace(
+ clean_evidence_dsc.lastIndexOf(">"), 1, "");
+ casefile.beginGroup(QString::number(i));
+ casefile.sync();
+ casefile.setValue("name", local_evidence_list[i].name);
+ casefile.setValue("description", local_evidence_list[i].description);
+ casefile.setValue("image", local_evidence_list[i].image);
+ casefile.endGroup();
+ }
+ casefile.sync();
+ append_server_chatmessage(
+ "CLIENT", tr("Succesfully saved, edit doc and cmdoc link on the ini!"),
+ "1");
+ ui_ooc_chat_message->clear();
+ return;
+ }
+
+ QStringList packet_contents;
+ packet_contents.append(ui_ooc_chat_name->text());
+ packet_contents.append(ooc_message);
+
+ AOPacket *f_packet = new AOPacket("CT", packet_contents);
+
+ if (server_ooc)
+ ao_app->send_server_packet(f_packet);
+ else
+ ao_app->send_ms_packet(f_packet);
+
+ ui_ooc_chat_message->clear();
+
+ ui_ooc_chat_message->setFocus();
+}
+
+void Courtroom::on_ooc_toggle_clicked()
+{
+ if (server_ooc) {
+ ui_ms_chatlog->show();
+ ui_server_chatlog->hide();
+ ui_ooc_toggle->setText(tr("Master"));
+
+ server_ooc = false;
+ }
+ else {
+ ui_ms_chatlog->hide();
+ ui_server_chatlog->show();
+ ui_ooc_toggle->setText(tr("Server"));
+
+ server_ooc = true;
+ }
+}
+
+// Todo: multithread this due to some servers having large as hell music list
+void Courtroom::on_music_search_edited(QString p_text)
+{
+ // Iterate through all QTreeWidgetItem items
+ if (!ui_music_list->isHidden()) {
+ QTreeWidgetItemIterator it(ui_music_list);
+ while (*it) {
+ (*it)->setHidden(p_text != "");
+ ++it;
+ }
+ }
+
+ if (!ui_area_list->isHidden()) {
+ QTreeWidgetItemIterator ait(ui_area_list);
+ while (*ait) {
+ (*ait)->setHidden(p_text != "");
+ ++ait;
+ }
+ }
+
+ if (p_text != "") {
+ if (!ui_music_list->isHidden()) {
+ // Search in metadata
+ QList<QTreeWidgetItem *> clist = ui_music_list->findItems(
+ ui_music_search->text(), Qt::MatchContains | Qt::MatchRecursive, 1);
+ foreach (QTreeWidgetItem *item, clist) {
+ if (item->parent() != nullptr) // So the category shows up too
+ item->parent()->setHidden(false);
+ item->setHidden(false);
+ }
+ }
+
+ if (!ui_area_list->isHidden()) {
+ // Search in metadata
+ QList<QTreeWidgetItem *> alist = ui_area_list->findItems(
+ ui_music_search->text(), Qt::MatchContains | Qt::MatchRecursive, 1);
+ foreach (QTreeWidgetItem *item, alist) {
+ if (item->parent() != nullptr) // So the category shows up too
+ item->parent()->setHidden(false);
+ item->setHidden(false);
+ }
+ }
+ }
+}
+
+void Courtroom::on_music_search_return_pressed()
+{
+ if (ui_music_search->text() == "") {
+ ui_music_list->collapseAll();
+ }
+}
+
+void Courtroom::on_pos_dropdown_changed(int p_index)
+{
+ if (p_index < 0 || p_index > 7)
+ return;
+
+ toggle_judge_buttons(false);
+
+ QString f_pos = ui_pos_dropdown->itemText(p_index);
+
+ if (f_pos == "")
+ return;
+
+ if (f_pos == "jud")
+ toggle_judge_buttons(true);
+
+ // YEAH SENDING LIKE 20 PACKETS IF THE USER SCROLLS THROUGH, GREAT IDEA
+ // how about this instead
+ set_side(f_pos);
+}
+
+void Courtroom::set_iniswap_dropdown()
+{
+ ui_iniswap_dropdown->blockSignals(true);
+ ui_iniswap_dropdown->clear();
+ if (m_cid == -1) {
+ ui_iniswap_dropdown->hide();
+ ui_iniswap_remove->hide();
+ return;
+ }
+ QStringList iniswaps = ao_app->get_list_file(
+ ao_app->get_character_path(char_list.at(m_cid).name, "iniswaps.ini"));
+ iniswaps.prepend(char_list.at(m_cid).name);
+ if (iniswaps.size() <= 0) {
+ ui_iniswap_dropdown->hide();
+ ui_iniswap_remove->hide();
+ return;
+ }
+ ui_iniswap_dropdown->show();
+ ui_iniswap_dropdown->addItems(iniswaps);
+
+ for (int i = 0; i < iniswaps.size(); ++i) {
+ if (iniswaps.at(i) == current_char) {
+ ui_iniswap_dropdown->setCurrentIndex(i);
+ if (i != 0)
+ ui_iniswap_remove->show();
+ else
+ ui_iniswap_remove->hide();
+ break;
+ }
+ }
+ ui_iniswap_dropdown->blockSignals(false);
+}
+
+void Courtroom::on_iniswap_dropdown_changed(int p_index)
+{
+ ui_ic_chat_message->setFocus();
+ QString iniswap = ui_iniswap_dropdown->itemText(p_index);
+ ao_app->set_char_ini(char_list.at(m_cid).name, iniswap, "name", "Options");
+
+ QStringList swaplist;
+ for (int i = 0; i < ui_iniswap_dropdown->count(); ++i) {
+ QString entry = ui_iniswap_dropdown->itemText(i);
+ if (!swaplist.contains(entry) && entry != char_list.at(m_cid).name)
+ swaplist.append(entry);
+ }
+ ao_app->write_to_file(
+ swaplist.join("\n"),
+ ao_app->get_character_path(char_list.at(m_cid).name, "iniswaps.ini"));
+ ui_iniswap_dropdown->blockSignals(true);
+ ui_iniswap_dropdown->setCurrentIndex(p_index);
+ ui_iniswap_dropdown->blockSignals(false);
+ update_character(m_cid);
+ if (p_index != 0)
+ ui_iniswap_remove->show();
+ else
+ ui_iniswap_remove->hide();
+}
+
+void Courtroom::on_iniswap_context_menu_requested(const QPoint &pos)
+{
+ QMenu *menu = ui_iniswap_dropdown->lineEdit()->createStandardContextMenu();
+
+ menu->addSeparator();
+ if (file_exists(ao_app->get_character_path(current_char, "char.ini")))
+ menu->addAction(QString("Edit " + current_char + "/char.ini"), this,
+ SLOT(on_iniswap_edit_requested()));
+ if (ui_iniswap_dropdown->itemText(ui_iniswap_dropdown->currentIndex()) !=
+ char_list.at(m_cid).name)
+ menu->addAction(QString("Remove " + current_char), this,
+ SLOT(on_iniswap_remove_clicked()));
+ menu->popup(ui_iniswap_dropdown->mapToGlobal(pos));
+}
+void Courtroom::on_iniswap_edit_requested()
+{
+ QString p_path = ao_app->get_character_path(current_char, "char.ini");
+ if (!file_exists(p_path))
+ return;
+ QDesktopServices::openUrl(QUrl::fromLocalFile(p_path));
+}
+
+void Courtroom::on_iniswap_remove_clicked()
+{
+ if (ui_iniswap_dropdown->count() <= 0) {
+ ui_iniswap_remove->hide(); // We're not supposed to see it. Do this or the
+ // client will crash
+ return;
+ }
+ if (ui_iniswap_dropdown->itemText(ui_iniswap_dropdown->currentIndex()) !=
+ char_list.at(m_cid).name) {
+ ui_iniswap_dropdown->removeItem(ui_iniswap_dropdown->currentIndex());
+ on_iniswap_dropdown_changed(0); // Reset back to original
+ update_character(m_cid);
+ }
+}
+
+void Courtroom::set_sfx_dropdown()
+{
+ ui_sfx_dropdown->blockSignals(true);
+ ui_sfx_dropdown->clear();
+ if (m_cid == -1) {
+ ui_sfx_dropdown->hide();
+ ui_sfx_remove->hide();
+ return;
+ }
+ QStringList soundlist = ao_app->get_list_file(
+ ao_app->get_character_path(current_char, "soundlist.ini"));
+
+ if (soundlist.size() <= 0) {
+ soundlist = ao_app->get_list_file(
+ ao_app->get_theme_path("character_soundlist.ini"));
+ if (soundlist.size() <= 0) {
+ soundlist = ao_app->get_list_file(
+ ao_app->get_default_theme_path("character_soundlist.ini"));
+ }
+ }
+
+ if (soundlist.size() <= 0) {
+ ui_sfx_dropdown->hide();
+ ui_sfx_remove->hide();
+ return;
+ }
+ soundlist.prepend("Default");
+
+ ui_sfx_dropdown->show();
+ ui_sfx_dropdown->addItems(soundlist);
+ ui_sfx_dropdown->setCurrentIndex(0);
+ ui_sfx_remove->hide();
+ ui_sfx_dropdown->blockSignals(false);
+}
+
+void Courtroom::on_sfx_dropdown_changed(int p_index)
+{
+ ui_ic_chat_message->setFocus();
+
+ QStringList soundlist;
+ for (int i = 0; i < ui_sfx_dropdown->count(); ++i) {
+ QString entry = ui_sfx_dropdown->itemText(i);
+ if (!soundlist.contains(entry) && entry != "Default")
+ soundlist.append(entry);
+ }
+
+ QStringList defaultlist =
+ ao_app->get_list_file(ao_app->get_theme_path("character_soundlist.ini"));
+ if (defaultlist.size() <= 0) {
+ defaultlist = ao_app->get_list_file(
+ ao_app->get_default_theme_path("character_soundlist.ini"));
+ }
+
+ if (defaultlist.size() > 0 &&
+ defaultlist.toSet().subtract(soundlist.toSet()).size() >
+ 0) // There's a difference from the default configuration
+ ao_app->write_to_file(
+ soundlist.join("\n"),
+ ao_app->get_character_path(current_char,
+ "soundlist.ini")); // Create a new sound list
+
+ ui_sfx_dropdown->blockSignals(true);
+ ui_sfx_dropdown->setCurrentIndex(p_index);
+ ui_sfx_dropdown->blockSignals(false);
+ if (p_index != 0)
+ ui_sfx_remove->show();
+ else
+ ui_sfx_remove->hide();
+}
+
+void Courtroom::on_sfx_context_menu_requested(const QPoint &pos)
+{
+ QMenu *menu = ui_sfx_dropdown->lineEdit()->createStandardContextMenu();
+
+ menu->addSeparator();
+ if (file_exists(ao_app->get_character_path(current_char, "soundlist.ini")))
+ menu->addAction(QString("Edit " + current_char + "/soundlist.ini"), this,
+ SLOT(on_sfx_edit_requested()));
+ else
+ menu->addAction(QString("Edit theme's character_soundlist.ini"), this,
+ SLOT(on_sfx_edit_requested()));
+ if (ui_sfx_dropdown->currentIndex() != 0)
+ menu->addAction(QString("Remove " + ui_sfx_dropdown->itemText(
+ ui_sfx_dropdown->currentIndex())),
+ this, SLOT(on_sfx_remove_clicked()));
+ menu->popup(ui_sfx_dropdown->mapToGlobal(pos));
+}
+void Courtroom::on_sfx_edit_requested()
+{
+ QString p_path = ao_app->get_character_path(current_char, "soundlist.ini");
+ if (!file_exists(p_path)) {
+ p_path = ao_app->get_theme_path("character_soundlist.ini");
+ if (!file_exists(p_path)) {
+ p_path = ao_app->get_default_theme_path("character_soundlist.ini");
+ if (!file_exists(p_path)) {
+ return;
+ }
+ }
+ }
+ QDesktopServices::openUrl(QUrl::fromLocalFile(p_path));
+}
+
+void Courtroom::on_sfx_remove_clicked()
+{
+ if (ui_sfx_dropdown->count() <= 0) {
+ ui_sfx_remove->hide(); // We're not supposed to see it. Do this or the
+ // client will crash
+ return;
+ }
+ if (ui_sfx_dropdown->itemText(ui_sfx_dropdown->currentIndex()) != "Default") {
+ ui_sfx_dropdown->removeItem(ui_sfx_dropdown->currentIndex());
+ on_sfx_dropdown_changed(0); // Reset back to original
+ }
+}
+
+void Courtroom::set_effects_dropdown()
+{
+ ui_effects_dropdown->blockSignals(true);
+ ui_effects_dropdown->clear();
+ if (m_cid == -1) {
+ ui_effects_dropdown->hide();
+ return;
+ }
+ QStringList effectslist = ao_app->get_effects(current_char);
+
+ if (effectslist.size() <= 0) {
+ ui_effects_dropdown->hide();
+ return;
+ }
+
+ effectslist.prepend("None");
+
+ ui_effects_dropdown->show();
+ ui_effects_dropdown->addItems(effectslist);
+
+ // ICON-MAKING HELL
+ QString p_effect = ao_app->read_char_ini(current_char, "effects", "Options");
+ QString custom_path =
+ ao_app->get_base_path() + "misc/" + p_effect + "/icons/";
+ QString theme_path = ao_app->get_theme_path("effects/icons/");
+ QString default_path = ao_app->get_default_theme_path("effects/icons/");
+ for (int i = 0; i < ui_effects_dropdown->count(); ++i) {
+ QString entry = ui_effects_dropdown->itemText(i);
+ QString iconpath = ao_app->get_static_image_suffix(custom_path + entry);
+ if (!file_exists(iconpath)) {
+ iconpath = ao_app->get_static_image_suffix(theme_path + entry);
+ if (!file_exists(iconpath)) {
+ iconpath = ao_app->get_static_image_suffix(default_path + entry);
+ if (!file_exists(iconpath))
+ continue;
+ }
+ }
+ ui_effects_dropdown->setItemIcon(i, QIcon(iconpath));
+ }
+
+ ui_effects_dropdown->setCurrentIndex(0);
+ ui_effects_dropdown->blockSignals(false);
+}
+
+void Courtroom::on_effects_context_menu_requested(const QPoint &pos)
+{
+ QMenu *menu = new QMenu();
+
+ if (!ao_app->read_char_ini(current_char, "effects", "Options").isEmpty())
+ menu->addAction(
+ QString("Open misc/" +
+ ao_app->read_char_ini(current_char, "effects", "Options") +
+ " folder"),
+ this, SLOT(on_character_effects_edit_requested()));
+ menu->addAction(QString("Open theme's effects folder"), this,
+ SLOT(on_effects_edit_requested()));
+ menu->popup(ui_effects_dropdown->mapToGlobal(pos));
+}
+void Courtroom::on_effects_edit_requested()
+{
+ QString p_path = ao_app->get_theme_path("effects/");
+ if (!dir_exists(p_path)) {
+ p_path = ao_app->get_default_theme_path("effects/");
+ if (!dir_exists(p_path)) {
+ return;
+ }
+ }
+ QDesktopServices::openUrl(QUrl::fromLocalFile(p_path));
+}
+void Courtroom::on_character_effects_edit_requested()
+{
+ QString p_effect = ao_app->read_char_ini(current_char, "effects", "Options");
+ QString p_path = ao_app->get_base_path() + "misc/" + p_effect + "/";
+ if (!dir_exists(p_path))
+ return;
+
+ QDesktopServices::openUrl(QUrl::fromLocalFile(p_path));
+}
+
+void Courtroom::on_effects_dropdown_changed(int p_index)
+{
+ effect = ui_effects_dropdown->itemText(p_index);
+ ui_ic_chat_message->setFocus();
+}
+
+bool Courtroom::effects_dropdown_find_and_set(QString effect)
+{
+ for (int i = 0; i < ui_effects_dropdown->count(); ++i) {
+ QString entry = ui_effects_dropdown->itemText(i);
+ if (entry == effect) {
+ ui_effects_dropdown->setCurrentIndex(i);
+ return true;
+ }
+ }
+ return false;
+}
+
+QString Courtroom::get_char_sfx()
+{
+ QString sfx = ui_sfx_dropdown->itemText(ui_sfx_dropdown->currentIndex());
+ if (sfx != "" && sfx != "Default")
+ return sfx;
+ return ao_app->get_sfx_name(current_char, current_emote);
+}
+
+int Courtroom::get_char_sfx_delay()
+{
+ // QString sfx = ui_sfx_dropdown->itemText(ui_sfx_dropdown->currentIndex());
+ // if (sfx != "" && sfx != "Default")
+ // return 0; //todo: a way to define this
+ return ao_app->get_sfx_delay(current_char, current_emote);
+}
+
+void Courtroom::on_mute_list_clicked(QModelIndex p_index)
+{
+ QListWidgetItem *f_item = ui_mute_list->item(p_index.row());
+ QString f_char = f_item->text();
+ QString real_char;
+
+ if (f_char.endsWith(" [x]"))
+ real_char = f_char.left(f_char.size() - 4);
+ else
+ real_char = f_char;
+
+ int f_cid = -1;
+
+ for (int n_char = 0; n_char < char_list.size(); n_char++) {
+ if (char_list.at(n_char).name == real_char)
+ f_cid = n_char;
+ }
+
+ if (f_cid < 0 || f_cid >= char_list.size()) {
+ qDebug() << "W: " << real_char << " not present in char_list";
+ return;
+ }
+
+ if (mute_map.value(f_cid)) {
+ mute_map.insert(f_cid, false);
+ f_item->setText(real_char);
+ }
+ else {
+ mute_map.insert(f_cid, true);
+ f_item->setText(real_char + " [x]");
+ }
+}
+
+void Courtroom::on_pair_list_clicked(QModelIndex p_index)
+{
+ QListWidgetItem *f_item = ui_pair_list->item(p_index.row());
+ QString f_char = f_item->text();
+ QString real_char;
+ int f_cid = -1;
+
+ if (f_char.endsWith(" [x]")) {
+ real_char = f_char.left(f_char.size() - 4);
+ f_item->setText(real_char);
+ }
+ else {
+ real_char = f_char;
+ for (int n_char = 0; n_char < char_list.size(); n_char++) {
+ if (char_list.at(n_char).name == real_char)
+ f_cid = n_char;
+ }
+ }
+
+ if (f_cid < -2 || f_cid >= char_list.size()) {
+ qDebug() << "W: " << real_char << " not present in char_list";
+ return;
+ }
+
+ other_charid = f_cid;
+
+ // Redo the character list.
+ QStringList sorted_pair_list;
+
+ for (char_type i_char : char_list)
+ sorted_pair_list.append(i_char.name);
+
+ sorted_pair_list.sort();
+
+ for (int i = 0; i < ui_pair_list->count(); i++) {
+ ui_pair_list->item(i)->setText(sorted_pair_list.at(i));
+ }
+ if (other_charid != -1) {
+ f_item->setText(real_char + " [x]");
+ }
+}
+
+void Courtroom::on_music_list_double_clicked(QTreeWidgetItem *p_item,
+ int column)
+{
+ if (is_muted)
+ return;
+
+ column = 1; // Column 1 is always the metadata (which we want)
+ QString p_song = p_item->text(column);
+
+ QStringList packet_contents;
+ packet_contents.append(p_song);
+ packet_contents.append(QString::number(m_cid));
+ if ((!ui_ic_chat_name->text().isEmpty() && ao_app->cccc_ic_support_enabled) ||
+ ao_app->effects_enabled)
+ packet_contents.append(ui_ic_chat_name->text());
+ if (ao_app->effects_enabled)
+ packet_contents.append(QString::number(music_flags));
+ ao_app->send_server_packet(new AOPacket("MC", packet_contents), false);
+}
+
+void Courtroom::on_music_list_context_menu_requested(const QPoint &pos)
+{
+ QMenu *menu = new QMenu();
+
+ menu->addAction(QString(tr("Play Random Song")), this,
+ SLOT(music_random()));
+ menu->addSeparator();
+ menu->addAction(QString(tr("Expand All Categories")), this,
+ SLOT(music_list_expand_all()));
+ menu->addAction(QString(tr("Collapse All Categories")), this,
+ SLOT(music_list_collapse_all()));
+ menu->addSeparator();
+
+ menu->addAction(new QAction(tr("Fade Out Previous"), this));
+ menu->actions().back()->setCheckable(true);
+ menu->actions().back()->setChecked(music_flags & FADE_OUT);
+ connect(menu->actions().back(), SIGNAL(toggled(bool)), this,
+ SLOT(music_fade_out(bool)));
+
+ menu->addAction(new QAction(tr("Fade In"), this));
+ menu->actions().back()->setCheckable(true);
+ menu->actions().back()->setChecked(music_flags & FADE_IN);
+ connect(menu->actions().back(), SIGNAL(toggled(bool)), this,
+ SLOT(music_fade_in(bool)));
+
+ menu->addAction(new QAction(tr("Synchronize"), this));
+ menu->actions().back()->setCheckable(true);
+ menu->actions().back()->setChecked(music_flags & SYNC_POS);
+ connect(menu->actions().back(), SIGNAL(toggled(bool)), this,
+ SLOT(music_synchronize(bool)));
+
+ menu->popup(ui_music_list->mapToGlobal(pos));
+}
+
+void Courtroom::music_fade_out(bool toggle)
+{
+ if (toggle)
+ music_flags |= FADE_OUT;
+ else
+ music_flags &= ~FADE_OUT;
+}
+
+void Courtroom::music_fade_in(bool toggle)
+{
+ if (toggle)
+ music_flags |= FADE_IN;
+ else
+ music_flags &= ~FADE_IN;
+}
+
+void Courtroom::music_synchronize(bool toggle)
+{
+ if (toggle)
+ music_flags |= SYNC_POS;
+ else
+ music_flags &= ~SYNC_POS;
+}
+
+void Courtroom::music_random()
+{
+ QList<QTreeWidgetItem *> clist;
+ QTreeWidgetItemIterator it(ui_music_list, QTreeWidgetItemIterator::NotHidden | QTreeWidgetItemIterator::NoChildren);
+ while (*it) {
+ clist += (*it);
+ ++it;
+ }
+ int i = qrand() % clist.length();
+ on_music_list_double_clicked(clist.at(i), 1);
+}
+
+void Courtroom::music_list_expand_all() { ui_music_list->expandAll(); }
+void Courtroom::music_list_collapse_all()
+{
+ ui_music_list->collapseAll();
+ QTreeWidgetItem *current = ui_music_list->selectedItems()[0];
+ if (current->parent() != nullptr)
+ current = current->parent();
+ ui_music_list->setCurrentItem(current);
+}
+
+void Courtroom::on_area_list_double_clicked(QTreeWidgetItem *p_item, int column)
+{
+ column = 0; // The metadata
+ QString p_area = p_item->text(0);
+
+ QStringList packet_contents;
+ packet_contents.append(p_area);
+ packet_contents.append(QString::number(m_cid));
+ qDebug() << packet_contents;
+ ao_app->send_server_packet(new AOPacket("MC", packet_contents), false);
+}
+
+void Courtroom::on_hold_it_clicked()
+{
+ if (objection_state == 1) {
+ ui_hold_it->set_image("holdit");
+ objection_state = 0;
+ }
+ else {
+ ui_objection->set_image("objection");
+ ui_take_that->set_image("takethat");
+ ui_custom_objection->set_image("custom");
+
+ ui_hold_it->set_image("holdit_selected");
+ objection_state = 1;
+ }
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_objection_clicked()
+{
+ if (objection_state == 2) {
+ ui_objection->set_image("objection");
+ objection_state = 0;
+ }
+ else {
+ ui_hold_it->set_image("holdit");
+ ui_take_that->set_image("takethat");
+ ui_custom_objection->set_image("custom");
+
+ ui_objection->set_image("objection_selected");
+ objection_state = 2;
+ }
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_take_that_clicked()
+{
+ if (objection_state == 3) {
+ ui_take_that->set_image("takethat");
+ objection_state = 0;
+ }
+ else {
+ ui_objection->set_image("objection");
+ ui_hold_it->set_image("holdit");
+ ui_custom_objection->set_image("custom");
+
+ ui_take_that->set_image("takethat_selected");
+ objection_state = 3;
+ }
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_custom_objection_clicked()
+{
+ if (objection_state == 4) {
+ ui_custom_objection->set_image("custom");
+ objection_state = 0;
+ }
+ else {
+ ui_objection->set_image("objection");
+ ui_take_that->set_image("takethat");
+ ui_hold_it->set_image("holdit");
+
+ ui_custom_objection->set_image("custom_selected");
+ objection_state = 4;
+ }
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::show_custom_objection_menu(const QPoint &pos)
+{
+ QPoint globalPos = ui_custom_objection->mapToGlobal(pos);
+ QAction *selecteditem = custom_obj_menu->exec(globalPos);
+ if (selecteditem) {
+ ui_objection->set_image("objection");
+ ui_take_that->set_image("takethat");
+ ui_hold_it->set_image("holdit");
+ ui_custom_objection->set_image("custom_selected");
+ if (selecteditem->text() == "Default")
+ objection_custom = "";
+ else
+ objection_custom = selecteditem->text();
+ objection_state = 4;
+ custom_obj_menu->setDefaultAction(selecteditem);
+ }
+}
+
+void Courtroom::on_realization_clicked()
+{
+ if (realization_state == 0) {
+ realization_state = 1;
+ if (effects_dropdown_find_and_set("realization"))
+ on_effects_dropdown_changed(ui_effects_dropdown->currentIndex());
+
+ ui_realization->set_image("realization_pressed");
+ }
+ else {
+ realization_state = 0;
+ ui_effects_dropdown->setCurrentIndex(0);
+ on_effects_dropdown_changed(ui_effects_dropdown->currentIndex());
+ ui_realization->set_image("realization");
+ }
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_screenshake_clicked()
+{
+ if (screenshake_state == 0) {
+ screenshake_state = 1;
+ ui_screenshake->set_image("screenshake_pressed");
+ }
+ else {
+ screenshake_state = 0;
+ ui_screenshake->set_image("screenshake");
+ }
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_mute_clicked()
+{
+ if (ui_mute_list->isHidden()) {
+ ui_mute_list->show();
+ ui_pair_list->hide();
+ ui_pair_offset_spinbox->hide();
+ ui_pair_order_dropdown->hide();
+ ui_pair_button->set_image("pair_button");
+ ui_mute->set_image("mute_pressed");
+ }
+ else {
+ ui_mute_list->hide();
+ ui_mute->set_image("mute");
+ }
+}
+
+void Courtroom::on_pair_clicked()
+{
+ if (ui_pair_list->isHidden()) {
+ ui_pair_list->show();
+ ui_pair_offset_spinbox->show();
+ ui_pair_order_dropdown->show();
+ ui_mute_list->hide();
+ ui_mute->set_image("mute");
+ ui_pair_button->set_image("pair_button_pressed");
+ }
+ else {
+ ui_pair_list->hide();
+ ui_pair_offset_spinbox->hide();
+ ui_pair_order_dropdown->hide();
+ ui_pair_button->set_image("pair_button");
+ }
+}
+
+void Courtroom::on_pair_order_dropdown_changed(int p_index)
+{
+ pair_order = p_index;
+}
+
+void Courtroom::on_defense_minus_clicked()
+{
+ int f_state = defense_bar_state - 1;
+
+ if (f_state >= 0)
+ ao_app->send_server_packet(
+ new AOPacket("HP#1#" + QString::number(f_state) + "#%"));
+}
+
+void Courtroom::on_defense_plus_clicked()
+{
+ int f_state = defense_bar_state + 1;
+
+ if (f_state <= 10)
+ ao_app->send_server_packet(
+ new AOPacket("HP#1#" + QString::number(f_state) + "#%"));
+}
+
+void Courtroom::on_prosecution_minus_clicked()
+{
+ int f_state = prosecution_bar_state - 1;
+
+ if (f_state >= 0)
+ ao_app->send_server_packet(
+ new AOPacket("HP#2#" + QString::number(f_state) + "#%"));
+}
+
+void Courtroom::on_prosecution_plus_clicked()
+{
+ int f_state = prosecution_bar_state + 1;
+
+ if (f_state <= 10)
+ ao_app->send_server_packet(
+ new AOPacket("HP#2#" + QString::number(f_state) + "#%"));
+}
+
+void Courtroom::set_text_color_dropdown()
+{
+ // Clear the lists
+ ui_text_color->clear();
+ color_row_to_number.clear();
+
+ // Clear the stored optimization information
+ color_rgb_list.clear();
+ color_markdown_start_list.clear();
+ color_markdown_end_list.clear();
+ color_markdown_remove_list.clear();
+ color_markdown_talking_list.clear();
+
+ // Update markdown colors. TODO: make a loading function that only loads the
+ // config file once instead of several times
+ for (int c = 0; c < max_colors; ++c) {
+ QColor color = ao_app->get_chat_color("c" + QString::number(c), current_char);
+ color_rgb_list.append(color);
+ color_markdown_start_list.append(ao_app->get_chat_markdown(
+ "c" + QString::number(c) + "_start", current_char));
+ color_markdown_end_list.append(ao_app->get_chat_markdown(
+ "c" + QString::number(c) + "_end", current_char));
+ color_markdown_remove_list.append(
+ ao_app->get_chat_markdown("c" + QString::number(c) + "_remove",
+ current_char) == "1");
+ color_markdown_talking_list.append(
+ ao_app->get_chat_markdown("c" + QString::number(c) + "_talking",
+ current_char) != "0");
+
+ QString color_name = ao_app->get_chat_markdown(
+ "c" + QString::number(c) + "_name", current_char);
+ if (color_name.isEmpty()) // Not defined
+ {
+ if (c > 0)
+ continue;
+ color_name = tr("Default");
+ }
+ ui_text_color->addItem(color_name);
+ QPixmap pixmap(16, 16);
+ pixmap.fill(color);
+ ui_text_color->setItemIcon(ui_text_color->count() - 1, QIcon(pixmap));
+ color_row_to_number.append(c);
+ }
+}
+
+void Courtroom::on_text_color_changed(int p_color)
+{
+ if (ui_ic_chat_message->selectionStart() != -1) // We have a selection!
+ {
+ int c = color_row_to_number.at(p_color);
+ QString markdown_start = color_markdown_start_list.at(c);
+ if (markdown_start.isEmpty()) {
+ qDebug() << "W: Color list dropdown selected a non-existent markdown "
+ "start character";
+ return;
+ }
+ QString markdown_end = color_markdown_end_list.at(c);
+ if (markdown_end.isEmpty())
+ markdown_end = markdown_start;
+ int start = ui_ic_chat_message->selectionStart();
+#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
+ int end = ui_ic_chat_message->selectionEnd() + 1;
+#else
+ int end = ui_ic_chat_message->selectedText().length() + 1;
+#endif
+
+ ui_ic_chat_message->setCursorPosition(start);
+ ui_ic_chat_message->insert(markdown_start);
+ ui_ic_chat_message->setCursorPosition(end);
+ ui_ic_chat_message->insert(markdown_end);
+ // ui_ic_chat_message->end(false);
+ ui_text_color->setCurrentIndex(0);
+ }
+ else {
+ if (p_color != -1 && p_color < color_row_to_number.size())
+ text_color = color_row_to_number.at(p_color);
+ else
+ text_color = 0;
+ }
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_music_slider_moved(int p_value)
+{
+ music_player->set_volume(p_value, 0); // Set volume on music layer
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_sfx_slider_moved(int p_value)
+{
+ sfx_player->set_volume(p_value);
+ // Set the ambience and other misc. music layers
+ for (int i = 1; i < music_player->m_channelmax; ++i) {
+ music_player->set_volume(p_value, i);
+ }
+ objection_player->set_volume(p_value);
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_blip_slider_moved(int p_value)
+{
+ blip_player->set_volume(p_value);
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_log_limit_changed(int value) { log_maximum_blocks = value; }
+
+void Courtroom::on_pair_offset_changed(int value) { char_offset = value; }
+
+void Courtroom::on_witness_testimony_clicked()
+{
+ if (is_muted)
+ return;
+
+ ao_app->send_server_packet(new AOPacket("RT#testimony1#%"));
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_cross_examination_clicked()
+{
+ if (is_muted)
+ return;
+
+ ao_app->send_server_packet(new AOPacket("RT#testimony2#%"));
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_not_guilty_clicked()
+{
+ if (is_muted)
+ return;
+
+ ao_app->send_server_packet(new AOPacket("RT#judgeruling#0#%"));
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_guilty_clicked()
+{
+ if (is_muted)
+ return;
+
+ ao_app->send_server_packet(new AOPacket("RT#judgeruling#1#%"));
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_change_character_clicked()
+{
+ sfx_player->set_volume(0);
+ blip_player->set_volume(0);
+
+ set_char_select();
+
+ ui_char_select_background->show();
+}
+
+void Courtroom::on_reload_theme_clicked()
+{
+ ao_app->reload_theme();
+
+ enter_courtroom();
+ update_character(m_cid);
+
+ anim_state = 4;
+ text_state = 3;
+ objection_custom = "";
+
+ // to update status on the background
+ set_background(current_background, true);
+}
+
+void Courtroom::on_back_to_lobby_clicked()
+{
+ ao_app->construct_lobby();
+ ao_app->destruct_courtroom();
+}
+
+void Courtroom::on_char_select_left_clicked()
+{
+ --current_char_page;
+ set_char_select_page();
+}
+
+void Courtroom::on_char_select_right_clicked()
+{
+ ++current_char_page;
+ set_char_select_page();
+}
+
+void Courtroom::on_spectator_clicked()
+{
+ char_clicked(-1);
+}
+
+void Courtroom::on_call_mod_clicked()
+{
+ if (ao_app->modcall_reason_enabled) {
+ QMessageBox errorBox;
+ QInputDialog input;
+
+ input.setWindowFlags(Qt::WindowSystemMenuHint);
+ input.setLabelText(tr("Reason:"));
+ input.setWindowTitle(tr("Call Moderator"));
+ auto code = input.exec();
+
+ if (code != QDialog::Accepted)
+ return;
+
+ QString text = input.textValue();
+ if (text.isEmpty()) {
+ errorBox.critical(nullptr, tr("Error"), tr("You must provide a reason."));
+ return;
+ }
+ else if (text.length() > 256) {
+ errorBox.critical(nullptr, tr("Error"), tr("The message is too long."));
+ return;
+ }
+
+ QStringList mod_reason;
+ mod_reason.append(text);
+
+ ao_app->send_server_packet(new AOPacket("ZZ", mod_reason));
+ }
+ else {
+ ao_app->send_server_packet(new AOPacket("ZZ#%"));
+ }
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_settings_clicked() { ao_app->call_settings_menu(); }
+
+void Courtroom::on_announce_casing_clicked()
+{
+ ao_app->call_announce_menu(this);
+}
+
+void Courtroom::on_pre_clicked() { ui_ic_chat_message->setFocus(); }
+
+void Courtroom::on_flip_clicked() { ui_ic_chat_message->setFocus(); }
+
+void Courtroom::on_additive_clicked()
+{
+ if (ui_additive->isChecked()) {
+ ui_ic_chat_message->home(false); // move cursor to the start of the message
+ ui_ic_chat_message->insert(" "); // preface the message by whitespace
+ ui_ic_chat_message->end(false); // move cursor to the end of the message
+ // without selecting anything
+ }
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_guard_clicked() { ui_ic_chat_message->setFocus(); }
+
+void Courtroom::on_showname_enable_clicked()
+{
+ ui_ic_chatlog->clear();
+ first_message_sent = false;
+
+ foreach (chatlogpiece item, ic_chatlog_history) {
+ if (ui_showname_enable->isChecked()) {
+ if (item.is_song())
+ append_ic_text(item.get_message(), item.get_showname(),
+ tr("has played a song"));
+ else
+ append_ic_text(item.get_message(), item.get_showname(), "", item.get_chat_color());
+ }
+ else {
+ if (item.is_song())
+ append_ic_text(item.get_message(), item.get_name(),
+ tr("has played a song"));
+ else
+ append_ic_text(item.get_message(), item.get_name(), "", item.get_chat_color());
+ }
+ }
+
+ ui_ic_chat_message->setFocus();
+}
+
+void Courtroom::on_evidence_button_clicked()
+{
+ if (ui_evidence->isHidden()) {
+ ui_evidence->show();
+ ui_evidence_overlay->hide();
+ }
+ else {
+ ui_evidence->hide();
+ }
+}
+
+void Courtroom::on_switch_area_music_clicked()
+{
+ ui_music_search->setText("");
+ on_music_search_edited(ui_music_search->text());
+ if (ui_area_list->isHidden()) {
+ ui_area_list->show();
+ ui_music_list->hide();
+ }
+ else {
+ ui_area_list->hide();
+ ui_music_list->show();
+ }
+}
+
+void Courtroom::ping_server()
+{
+ ao_app->send_server_packet(
+ new AOPacket("CH#" + QString::number(m_cid) + "#%"));
+}
+
+void Courtroom::on_casing_clicked()
+{
+ if (ao_app->casing_alerts_enabled) {
+ if (ui_casing->isChecked()) {
+ QStringList f_packet;
+
+ f_packet.append(ao_app->get_casing_can_host_cases());
+ f_packet.append(QString::number(ao_app->get_casing_cm_enabled()));
+ f_packet.append(QString::number(ao_app->get_casing_defence_enabled()));
+ f_packet.append(
+ QString::number(ao_app->get_casing_prosecution_enabled()));
+ f_packet.append(QString::number(ao_app->get_casing_judge_enabled()));
+ f_packet.append(QString::number(ao_app->get_casing_juror_enabled()));
+ f_packet.append(QString::number(ao_app->get_casing_steno_enabled()));
+
+ ao_app->send_server_packet(new AOPacket("SETCASE", f_packet));
+ }
+ else
+ ao_app->send_server_packet(new AOPacket("SETCASE#\"\"#0#0#0#0#0#0#%"));
+ }
+}
+
+void Courtroom::announce_case(QString title, bool def, bool pro, bool jud,
+ bool jur, bool steno)
+{
+ if (ao_app->casing_alerts_enabled) {
+ QStringList f_packet;
+
+ f_packet.append(title);
+ f_packet.append(QString::number(def));
+ f_packet.append(QString::number(pro));
+ f_packet.append(QString::number(jud));
+ f_packet.append(QString::number(jur));
+ f_packet.append(QString::number(steno));
+
+ ao_app->send_server_packet(new AOPacket("CASEA", f_packet));
+ }
+}
+
+Courtroom::~Courtroom()
+{
+ delete music_player;
+ delete sfx_player;
+ delete objection_player;
+ delete blip_player;
+}
+
+#if (defined(_WIN32) || defined(_WIN64))
+void Courtroom::load_bass_opus_plugin()
+{
+#ifdef BASSAUDIO
+ BASS_PluginLoad("bassopus.dll", 0);
+#endif
+}
+#elif (defined(LINUX) || defined(__linux__))
+void Courtroom::load_bass_opus_plugin()
+{
+#ifdef BASSAUDIO
+ BASS_PluginLoad("libbassopus.so", 0);
+#endif
+}
+#elif defined __APPLE__
+void Courtroom::load_bass_opus_plugin()
+{
+#ifdef BASSAUDIO
+ BASS_PluginLoad("libbassopus.dylib", 0);
+#endif
+}
+#else
+#error This operating system is unsupported for bass plugins.
+#endif
diff --git a/src/debug_functions.cpp b/src/debug_functions.cpp
index 6186b9da..b8321640 100644
--- a/src/debug_functions.cpp
+++ b/src/debug_functions.cpp
@@ -21,7 +21,6 @@ void call_notice(QString p_message)
QMessageBox *msgBox = new QMessageBox;
msgBox->setText(p_message);
-
msgBox->setWindowTitle(
QCoreApplication::translate("debug_functions", "Notice"));
diff --git a/src/emotes.cpp b/src/emotes.cpp
index bbe2f5c9..8de55244 100644
--- a/src/emotes.cpp
+++ b/src/emotes.cpp
@@ -2,20 +2,48 @@
#include "aoemotebutton.h"
-void Courtroom::construct_emotes()
+void Courtroom::initialize_emotes()
{
ui_emotes = new QWidget(this);
+ ui_emote_left = new AOButton(this, ao_app);
+ ui_emote_right = new AOButton(this, ao_app);
+
+ ui_emote_dropdown = new QComboBox(this);
+
+ connect(ui_emote_left, SIGNAL(clicked()), this,
+ SLOT(on_emote_left_clicked()));
+ connect(ui_emote_right, SIGNAL(clicked()), this,
+ SLOT(on_emote_right_clicked()));
+
+ connect(ui_emote_dropdown, SIGNAL(activated(int)), this,
+ SLOT(on_emote_dropdown_changed(int)));
+}
+
+void Courtroom::refresh_emotes()
+{
+ // Should properly refresh the emote list
+ qDeleteAll(ui_emote_list.begin(), ui_emote_list.end());
+ ui_emote_list.clear();
+
set_size_and_pos(ui_emotes, "emotes");
+ set_size_and_pos(ui_emote_left, "emote_left");
+ ui_emote_left->set_image("arrow_left");
+
+ set_size_and_pos(ui_emote_right, "emote_right");
+ ui_emote_right->set_image("arrow_right");
+
QPoint f_spacing = ao_app->get_button_spacing("emote_button_spacing",
"courtroom_design.ini");
+ QPoint p_point =
+ ao_app->get_button_spacing("emote_button_size", "courtroom_design.ini");
- const int button_width = 40;
+ const int button_width = p_point.x();
int x_spacing = f_spacing.x();
int x_mod_count = 0;
- const int button_height = 40;
+ const int button_height = p_point.y();
int y_spacing = f_spacing.y();
int y_mod_count = 0;
@@ -30,7 +58,8 @@ void Courtroom::construct_emotes()
int x_pos = (button_width + x_spacing) * x_mod_count;
int y_pos = (button_height + y_spacing) * y_mod_count;
- AOEmoteButton *f_emote = new AOEmoteButton(ui_emotes, ao_app, x_pos, y_pos);
+ AOEmoteButton *f_emote = new AOEmoteButton(ui_emotes, ao_app, x_pos, y_pos,
+ button_width, button_height);
ui_emote_list.append(f_emote);
@@ -82,16 +111,19 @@ void Courtroom::set_emote_page()
if (current_emote_page > 0)
ui_emote_left->show();
- for (int n_emote = 0; n_emote < emotes_on_page; ++n_emote) {
+ for (int n_emote = 0;
+ n_emote < emotes_on_page && n_emote < ui_emote_list.size(); ++n_emote) {
int n_real_emote = n_emote + current_emote_page * max_emotes_on_page;
AOEmoteButton *f_emote = ui_emote_list.at(n_emote);
if (n_real_emote == current_emote)
- f_emote->set_image(current_char, n_real_emote, "_on.png");
+ f_emote->set_char_image(current_char, n_real_emote, "_on");
else
- f_emote->set_image(current_char, n_real_emote, "_off.png");
+ f_emote->set_char_image(current_char, n_real_emote, "_off");
f_emote->show();
+ f_emote->setToolTip(QString::number(n_real_emote + 1) + ": " +
+ ao_app->get_emote_comment(current_char, n_real_emote));
}
}
@@ -103,7 +135,8 @@ void Courtroom::set_emote_dropdown()
QStringList emote_list;
for (int n = 0; n < total_emotes; ++n) {
- emote_list.append(ao_app->get_emote_comment(current_char, n));
+ emote_list.append(QString::number(n + 1) + ": " +
+ ao_app->get_emote_comment(current_char, n));
}
ui_emote_dropdown->addItems(emote_list);
@@ -116,7 +149,7 @@ void Courtroom::select_emote(int p_id)
if (current_emote >= min && current_emote <= max)
ui_emote_list.at(current_emote % max_emotes_on_page)
- ->set_image(current_char, current_emote, "_off.png");
+ ->set_char_image(current_char, current_emote, "_off");
int old_emote = current_emote;
@@ -124,17 +157,19 @@ void Courtroom::select_emote(int p_id)
if (current_emote >= min && current_emote <= max)
ui_emote_list.at(current_emote % max_emotes_on_page)
- ->set_image(current_char, current_emote, "_on.png");
+ ->set_char_image(current_char, current_emote, "_on");
int emote_mod = ao_app->get_emote_mod(current_char, current_emote);
if (old_emote == current_emote) {
ui_pre->setChecked(!ui_pre->isChecked());
}
- else if (emote_mod == 1)
- ui_pre->setChecked(true);
- else
- ui_pre->setChecked(false);
+ else if (!ao_app->is_stickypres_enabled()) {
+ if (emote_mod == 1 || emote_mod == 4)
+ ui_pre->setChecked(true);
+ else
+ ui_pre->setChecked(false);
+ }
ui_emote_dropdown->setCurrentIndex(current_emote);
diff --git a/src/evidence.cpp b/src/evidence.cpp
index 502fae76..a8f59135 100644
--- a/src/evidence.cpp
+++ b/src/evidence.cpp
@@ -1,45 +1,194 @@
#include "courtroom.h"
-void Courtroom::construct_evidence()
+void Courtroom::initialize_evidence()
{
ui_evidence = new AOImage(this, ao_app);
// ui_evidence_name = new QLabel(ui_evidence);
ui_evidence_name = new AOLineEdit(ui_evidence);
ui_evidence_name->setAlignment(Qt::AlignCenter);
- ui_evidence_name->setFont(QFont("Arial", 14, QFont::Bold));
- ui_evidence_name->setStyleSheet("background-color: rgba(0, 0, 0, 0);"
- "color: rgba(255, 128, 0, 255);");
+ ui_evidence_name->setFrame(false);
ui_evidence_buttons = new QWidget(ui_evidence);
ui_evidence_left = new AOButton(ui_evidence, ao_app);
ui_evidence_right = new AOButton(ui_evidence, ao_app);
ui_evidence_present = new AOButton(ui_evidence, ao_app);
+ ui_evidence_present->setToolTip(tr("Present this piece of evidence to "
+ "everyone on your next spoken message"));
+
+ ui_evidence_switch = new AOButton(ui_evidence, ao_app);
+ ui_evidence_transfer = new AOButton(ui_evidence, ao_app);
+
+ ui_evidence_save = new AOButton(ui_evidence, ao_app);
+ ui_evidence_save->setToolTip(tr("Save evidence to an .ini file."));
+ ui_evidence_load = new AOButton(ui_evidence, ao_app);
+ ui_evidence_load->setToolTip(tr("Load evidence from an .ini file."));
ui_evidence_overlay = new AOImage(ui_evidence, ao_app);
ui_evidence_delete = new AOButton(ui_evidence_overlay, ao_app);
+ ui_evidence_delete->setToolTip(tr("Destroy this piece of evidence"));
ui_evidence_image_name = new AOLineEdit(ui_evidence_overlay);
ui_evidence_image_button = new AOButton(ui_evidence_overlay, ao_app);
- ui_evidence_image_button->setText(tr("Choose..."));
+ ui_evidence_image_button->setText(tr("Choose.."));
ui_evidence_x = new AOButton(ui_evidence_overlay, ao_app);
+ ui_evidence_x->setToolTip(
+ tr("Close the evidence display/editing overlay.\n"
+ "You will be prompted if there's any unsaved changes."));
+ ui_evidence_ok = new AOButton(ui_evidence_overlay, ao_app);
+ ui_evidence_ok->setToolTip(tr("Save any changes made to this piece of "
+ "evidence and send them to server."));
ui_evidence_description = new AOTextEdit(ui_evidence_overlay);
ui_evidence_description->setStyleSheet("background-color: rgba(0, 0, 0, 0);"
"color: white;");
+ ui_evidence_description->setFrameStyle(QFrame::NoFrame);
+ ui_evidence_description->setToolTip(
+ tr("Double-click to edit. Press [X] to update your changes."));
+
+ connect(ui_evidence_name, SIGNAL(returnPressed()), this,
+ SLOT(on_evidence_name_edited()));
+ connect(ui_evidence_name, SIGNAL(double_clicked()), this,
+ SLOT(on_evidence_name_double_clicked()));
+ connect(ui_evidence_left, SIGNAL(clicked()), this,
+ SLOT(on_evidence_left_clicked()));
+ connect(ui_evidence_right, SIGNAL(clicked()), this,
+ SLOT(on_evidence_right_clicked()));
+ connect(ui_evidence_present, SIGNAL(clicked()), this,
+ SLOT(on_evidence_present_clicked()));
+ connect(ui_evidence_switch, SIGNAL(clicked()), this,
+ SLOT(on_evidence_switch_clicked()));
+ connect(ui_evidence_transfer, SIGNAL(clicked()), this,
+ SLOT(on_evidence_transfer_clicked()));
+ connect(ui_evidence_save, SIGNAL(clicked()), this,
+ SLOT(on_evidence_save_clicked()));
+ connect(ui_evidence_load, SIGNAL(clicked()), this,
+ SLOT(on_evidence_load_clicked()));
+
+ connect(ui_evidence_delete, SIGNAL(clicked()), this,
+ SLOT(on_evidence_delete_clicked()));
+ connect(ui_evidence_image_name, SIGNAL(returnPressed()), this,
+ SLOT(on_evidence_image_name_edited()));
+ connect(ui_evidence_image_name, SIGNAL(double_clicked()), this,
+ SLOT(on_evidence_image_name_double_clicked()));
+ connect(ui_evidence_image_button, SIGNAL(clicked()), this,
+ SLOT(on_evidence_image_button_clicked()));
+ connect(ui_evidence_x, SIGNAL(clicked()), this,
+ SLOT(on_evidence_x_clicked()));
+ connect(ui_evidence_ok, SIGNAL(clicked()), this,
+ SLOT(on_evidence_ok_clicked()));
+
+ connect(ui_evidence_name, SIGNAL(textChanged(QString)), this,
+ SLOT(on_evidence_edited()));
+ connect(ui_evidence_image_name, SIGNAL(textChanged(QString)), this,
+ SLOT(on_evidence_edited()));
+ connect(ui_evidence_description, SIGNAL(textChanged()), this,
+ SLOT(on_evidence_edited()));
+
+ ui_evidence->hide();
+}
+
+void Courtroom::refresh_evidence()
+{
+ set_font(ui_evidence_name, "", "evidence_name");
+ set_font(ui_evidence_image_name, "", "evidence_image_name");
+ set_font(ui_evidence_description, "", "evidence_description");
+
+ // Should properly refresh the evidence list
+ qDeleteAll(ui_evidence_list.begin(), ui_evidence_list.end());
+ ui_evidence_list.clear();
+
+ set_size_and_pos(ui_evidence_button, "evidence_button");
+ ui_evidence_button->set_image("evidence_button");
+ ui_evidence_button->setToolTip(tr("Bring up the Evidence screen."));
set_size_and_pos(ui_evidence, "evidence_background");
+ if (current_evidence_global)
+ ui_evidence->set_image("evidence_background");
+ else
+ ui_evidence->set_image("evidence_background_private");
+
+ set_size_and_pos(ui_evidence_name, "evidence_name");
+
set_size_and_pos(ui_evidence_buttons, "evidence_buttons");
+ set_size_and_pos(ui_evidence_left, "evidence_left");
+ ui_evidence_left->set_image("arrow_left");
+
+ set_size_and_pos(ui_evidence_right, "evidence_right");
+ ui_evidence_right->set_image("arrow_right");
+
+ set_size_and_pos(ui_evidence_present, "evidence_present");
+ ui_evidence_present->set_image("present");
+
+ set_size_and_pos(ui_evidence_overlay, "evidence_overlay");
+ if (current_evidence_global)
+ ui_evidence_overlay->set_image("evidence_overlay");
+ else
+ ui_evidence_overlay->set_image("evidence_overlay_private");
+
+ set_size_and_pos(ui_evidence_delete, "evidence_delete");
+ ui_evidence_delete->set_image("evidence_delete");
+
+ set_size_and_pos(ui_evidence_image_name, "evidence_image_name");
+
+ set_size_and_pos(ui_evidence_image_button, "evidence_image_button");
+
+ set_size_and_pos(ui_evidence_x, "evidence_x");
+ ui_evidence_x->set_image("evidence_x");
+
+ set_size_and_pos(ui_evidence_ok, "evidence_ok");
+ ui_evidence_ok->set_image("evidence_ok");
+
+ set_size_and_pos(ui_evidence_switch, "evidence_switch");
+ if (current_evidence_global) {
+ ui_evidence_switch->set_image("evidence_global");
+ ui_evidence_switch->setToolTip(tr("Switch evidence to private inventory."));
+ }
+ else {
+ ui_evidence_switch->set_image("evidence_private");
+ ui_evidence_switch->setToolTip(tr("Switch evidence to global inventory."));
+ }
+
+ set_size_and_pos(ui_evidence_transfer, "evidence_transfer");
+ if (current_evidence_global) {
+ ui_evidence_transfer->set_image("evidence_transfer");
+ ui_evidence_transfer->setToolTip(
+ tr("Transfer evidence to private inventory."));
+ }
+ else {
+ ui_evidence_transfer->set_image("evidence_transfer_private");
+ ui_evidence_transfer->setToolTip(
+ tr("Transfer evidence to global inventory."));
+ }
+
+ set_size_and_pos(ui_evidence_save, "evidence_save");
+ ui_evidence_save->set_image("evidence_save");
+ if (current_evidence_global)
+ ui_evidence_save->hide();
+ else
+ ui_evidence_save->show();
+
+ set_size_and_pos(ui_evidence_load, "evidence_load");
+ ui_evidence_load->set_image("evidence_load");
+ if (current_evidence_global)
+ ui_evidence_load->hide();
+ else
+ ui_evidence_load->show();
+
+ set_size_and_pos(ui_evidence_description, "evidence_description");
+
QPoint f_spacing = ao_app->get_button_spacing("evidence_button_spacing",
"courtroom_design.ini");
+ QPoint p_point = ao_app->get_button_spacing("evidence_button_size",
+ "courtroom_design.ini");
- const int button_width = 70;
+ const int button_width = p_point.x();
int x_spacing = f_spacing.x();
int x_mod_count = 0;
- const int button_height = 70;
+ const int button_height = p_point.y();
int y_spacing = f_spacing.y();
int y_mod_count = 0;
@@ -56,8 +205,8 @@ void Courtroom::construct_evidence()
int x_pos = (button_width + x_spacing) * x_mod_count;
int y_pos = (button_height + y_spacing) * y_mod_count;
- AOEvidenceButton *f_evidence =
- new AOEvidenceButton(ui_evidence_buttons, ao_app, x_pos, y_pos);
+ AOEvidenceButton *f_evidence = new AOEvidenceButton(
+ ui_evidence_buttons, ao_app, x_pos, y_pos, button_width, button_height);
ui_evidence_list.append(f_evidence);
@@ -77,33 +226,64 @@ void Courtroom::construct_evidence()
x_mod_count = 0;
}
}
-
- connect(ui_evidence_name, SIGNAL(returnPressed()), this,
- SLOT(on_evidence_name_edited()));
- connect(ui_evidence_left, SIGNAL(clicked()), this,
- SLOT(on_evidence_left_clicked()));
- connect(ui_evidence_right, SIGNAL(clicked()), this,
- SLOT(on_evidence_right_clicked()));
- connect(ui_evidence_present, SIGNAL(clicked()), this,
- SLOT(on_evidence_present_clicked()));
- connect(ui_evidence_delete, SIGNAL(clicked()), this,
- SLOT(on_evidence_delete_clicked()));
- connect(ui_evidence_image_name, SIGNAL(returnPressed()), this,
- SLOT(on_evidence_image_name_edited()));
- connect(ui_evidence_image_button, SIGNAL(clicked()), this,
- SLOT(on_evidence_image_button_clicked()));
- connect(ui_evidence_x, SIGNAL(clicked()), this,
- SLOT(on_evidence_x_clicked()));
-
- ui_evidence->hide();
}
void Courtroom::set_evidence_list(QVector<evi_type> &p_evi_list)
{
+ global_evidence_list = p_evi_list;
+ if (!current_evidence_global)
+ return; // We're on private evidence editing, wait for user to do their
+ // thing
+
+ QVector<evi_type> old_list = local_evidence_list;
local_evidence_list.clear();
local_evidence_list = p_evi_list;
set_evidence_page();
+
+ if (ui_evidence_overlay
+ ->isVisible()) // Update the currently edited evidence for this user
+ {
+ if (current_evidence >= local_evidence_list.size()) {
+ evidence_close();
+ ui_evidence_name->setText("");
+ }
+ else if (ui_evidence_description->isReadOnly()) // We haven't double clicked
+ // to edit it or anything
+ {
+ on_evidence_double_clicked(current_evidence);
+ }
+ // Todo: make a function that compares two pieces of evidence for any
+ // differences
+ else if (compare_evidence_changed(
+ old_list.at(current_evidence),
+ local_evidence_list.at(current_evidence))) {
+ QMessageBox *msgBox = new QMessageBox;
+
+ msgBox->setText(tr("The piece of evidence you've been editing has changed."));
+ msgBox->setInformativeText(tr("Do you wish to keep your changes?"));
+ msgBox->setDetailedText(tr(
+ "Name: %1\n"
+ "Image: %2\n"
+ "Description:\n%3").arg(local_evidence_list.at(current_evidence).name).arg(local_evidence_list.at(current_evidence).image).arg(local_evidence_list.at(current_evidence).description));
+ msgBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
+ msgBox->setDefaultButton(QMessageBox::LastButton);
+ // msgBox->setWindowModality(Qt::NonModal);
+ int ret = msgBox->exec();
+ switch (ret) {
+ case QMessageBox::Yes:
+ // "Keep changes"
+ break;
+ case QMessageBox::No:
+ // "Discard changes and keep theirs"
+ on_evidence_double_clicked(current_evidence);
+ break;
+ default:
+ // should never be reached
+ break;
+ }
+ }
+ }
}
void Courtroom::set_evidence_page()
@@ -114,7 +294,7 @@ void Courtroom::set_evidence_page()
ui_evidence_right->hide();
for (AOEvidenceButton *i_button : ui_evidence_list) {
- i_button->reset();
+ i_button->hide();
}
// to account for the "add evidence" button
@@ -147,17 +327,21 @@ void Courtroom::set_evidence_page()
AOEvidenceButton *f_evidence_button =
ui_evidence_list.at(n_evidence_button);
- // ie. the add evidence button
- if (n_real_evidence == (total_evidence - 1))
+ f_evidence_button->set_selected(false);
+ f_evidence_button->setToolTip("");
+ if (n_real_evidence == (total_evidence - 1)) {
f_evidence_button->set_theme_image("addevidence.png");
+ }
else if (n_real_evidence < (total_evidence - 1)) {
f_evidence_button->set_image(
local_evidence_list.at(n_real_evidence).image);
if (n_real_evidence == current_evidence)
f_evidence_button->set_selected(true);
- else
- f_evidence_button->set_selected(false);
+
+ f_evidence_button->setToolTip(
+ QString::number(n_real_evidence + 1) + ": " +
+ local_evidence_list.at(n_real_evidence).name);
}
else
f_evidence_button->set_image("");
@@ -168,36 +352,31 @@ void Courtroom::set_evidence_page()
void Courtroom::on_evidence_name_edited()
{
+ ui_evidence_name->setReadOnly(true);
if (current_evidence >= local_evidence_list.size())
return;
+}
- QStringList f_contents;
-
- evi_type f_evi = local_evidence_list.at(current_evidence);
-
- f_contents.append(QString::number(current_evidence));
- f_contents.append(ui_evidence_name->text());
- f_contents.append(f_evi.description);
- f_contents.append(f_evi.image);
+void Courtroom::on_evidence_name_double_clicked()
+{
+ if (ui_evidence_overlay->isVisible()) {
+ ui_evidence_name->setReadOnly(false);
+ }
+ else {
+ ui_evidence_name->setReadOnly(true);
+ }
+}
- ao_app->send_server_packet(new AOPacket("EE", f_contents));
+void Courtroom::on_evidence_image_name_double_clicked()
+{
+ ui_evidence_image_name->setReadOnly(false);
}
void Courtroom::on_evidence_image_name_edited()
{
+ ui_evidence_image_name->setReadOnly(true);
if (current_evidence >= local_evidence_list.size())
return;
-
- QStringList f_contents;
-
- evi_type f_evi = local_evidence_list.at(current_evidence);
-
- f_contents.append(QString::number(current_evidence));
- f_contents.append(f_evi.name);
- f_contents.append(f_evi.description);
- f_contents.append(ui_evidence_image_name->text());
-
- ao_app->send_server_packet(new AOPacket("EE", f_contents));
}
void Courtroom::on_evidence_image_button_clicked()
@@ -230,8 +409,19 @@ void Courtroom::on_evidence_clicked(int p_id)
int f_real_id = p_id + max_evidence_on_page * current_evidence_page;
if (f_real_id == local_evidence_list.size()) {
- ao_app->send_server_packet(
- new AOPacket("PE#<name>#<description>#empty.png#%"));
+ if (current_evidence_global)
+ ao_app->send_server_packet(
+ new AOPacket("PE#<name>#<description>#empty.png#%"));
+ else {
+ evi_type f_evi;
+ f_evi.name = "<name>";
+ f_evi.description = "<description>";
+ f_evi.image = "empty.png";
+
+ local_evidence_list.append(f_evi);
+ private_evidence_list = local_evidence_list;
+ set_evidence_page();
+ }
return;
}
else if (f_real_id > local_evidence_list.size())
@@ -246,7 +436,7 @@ void Courtroom::on_evidence_clicked(int p_id)
current_evidence = f_real_id;
- ui_ic_chat_message->setFocus();
+ // ui_ic_chat_message->setFocus();
}
void Courtroom::on_evidence_double_clicked(int p_id)
@@ -262,10 +452,18 @@ void Courtroom::on_evidence_double_clicked(int p_id)
ui_evidence_description->clear();
ui_evidence_description->appendPlainText(f_evi.description);
+ ui_evidence_description->setReadOnly(true);
+ ui_evidence_description->setToolTip(tr("Double-click to edit..."));
+ ui_evidence_name->setText(f_evi.name);
+ ui_evidence_name->setReadOnly(true);
+ ui_evidence_name->setToolTip(tr("Double-click to edit..."));
ui_evidence_image_name->setText(f_evi.image);
+ ui_evidence_image_name->setReadOnly(true);
+ ui_evidence_image_name->setToolTip(tr("Double-click to edit..."));
ui_evidence_overlay->show();
+ ui_evidence_ok->hide();
ui_ic_chat_message->setFocus();
}
@@ -307,10 +505,15 @@ void Courtroom::on_evidence_right_clicked()
void Courtroom::on_evidence_present_clicked()
{
+ if (!current_evidence_global) {
+ ui_evidence_present->hide();
+ is_presenting_evidence = false;
+ return; // otherwise we get force-disconnected
+ }
if (is_presenting_evidence)
- ui_evidence_present->set_image("present_disabled.png");
+ ui_evidence_present->set_image("present");
else
- ui_evidence_present->set_image("present.png");
+ ui_evidence_present->set_image("present_disabled");
is_presenting_evidence = !is_presenting_evidence;
@@ -319,11 +522,15 @@ void Courtroom::on_evidence_present_clicked()
void Courtroom::on_evidence_delete_clicked()
{
- ui_evidence_description->setReadOnly(true);
- ui_evidence_overlay->hide();
-
- ao_app->send_server_packet(
- new AOPacket("DE#" + QString::number(current_evidence) + "#%"));
+ evidence_close();
+ if (current_evidence_global)
+ ao_app->send_server_packet(
+ new AOPacket("DE#" + QString::number(current_evidence) + "#%"));
+ else {
+ local_evidence_list.remove(current_evidence);
+ private_evidence_list = local_evidence_list;
+ set_evidence_page();
+ }
current_evidence = 0;
@@ -332,22 +539,239 @@ void Courtroom::on_evidence_delete_clicked()
void Courtroom::on_evidence_x_clicked()
{
+ if (current_evidence >=
+ local_evidence_list.size()) // Should never happen but you never know.
+ return;
+
+ evi_type fake_evidence;
+ fake_evidence.name = ui_evidence_name->text();
+ fake_evidence.description = ui_evidence_description->toPlainText();
+ fake_evidence.image = ui_evidence_image_name->text();
+ if (!compare_evidence_changed(fake_evidence,
+ local_evidence_list.at(current_evidence))) {
+ evidence_close();
+ return;
+ }
+ QMessageBox *msgBox = new QMessageBox;
+ msgBox->setText(tr("Evidence has been modified."));
+ msgBox->setInformativeText(tr("Do you want to save your changes?"));
+ msgBox->setStandardButtons(QMessageBox::Save | QMessageBox::Discard |
+ QMessageBox::Cancel);
+ msgBox->setDefaultButton(QMessageBox::Save);
+ int ret = msgBox->exec();
+ switch (ret) {
+ case QMessageBox::Save:
+ evidence_close();
+ on_evidence_ok_clicked();
+ break;
+ case QMessageBox::Discard:
+ evidence_close();
+ break;
+ case QMessageBox::Cancel:
+ // Cancel was clicked, do nothing
+ break;
+ default:
+ // should never be reached
+ break;
+ }
+}
+
+void Courtroom::on_evidence_ok_clicked()
+{
+ ui_evidence_name->setReadOnly(true);
ui_evidence_description->setReadOnly(true);
- ui_evidence_overlay->hide();
+ ui_evidence_image_name->setReadOnly(true);
+ if (current_evidence < local_evidence_list.size()) {
+ evi_type f_evi = local_evidence_list.at(current_evidence);
+ if (current_evidence_global) {
+ QStringList f_contents;
+ f_contents.append(QString::number(current_evidence));
+ f_contents.append(ui_evidence_name->text());
+ f_contents.append(ui_evidence_description->toPlainText());
+ f_contents.append(ui_evidence_image_name->text());
+
+ ao_app->send_server_packet(new AOPacket("EE", f_contents));
+ }
+ else {
+ f_evi.name = ui_evidence_name->text();
+ f_evi.description = ui_evidence_description->toPlainText();
+ f_evi.image = ui_evidence_image_name->text();
+ local_evidence_list.replace(current_evidence, f_evi);
+ private_evidence_list = local_evidence_list;
+ ui_evidence_ok->hide();
+ set_evidence_page();
+ }
+ }
+}
+
+void Courtroom::on_evidence_switch_clicked()
+{
+ evidence_close();
+ evidence_switch(!current_evidence_global);
+ if (current_evidence_global) {
+ ui_evidence_switch->set_image("evidence_global");
+ ui_evidence->set_image("evidence_background");
+ ui_evidence_overlay->set_image("evidence_overlay");
+ ui_evidence_transfer->set_image("evidence_transfer");
+ ui_evidence_transfer->setToolTip(
+ tr("Transfer evidence to private inventory."));
+ ui_evidence_switch->setToolTip(
+ tr("Current evidence is global. Click to switch to private."));
+ }
+ else {
+ ui_evidence_switch->set_image("evidence_private");
+ ui_evidence->set_image("evidence_background_private");
+ ui_evidence_overlay->set_image("evidence_overlay_private");
+ ui_evidence_transfer->set_image("evidence_transfer_private");
+ ui_evidence_transfer->setToolTip(
+ tr("Transfer evidence to global inventory."));
+ ui_evidence_switch->setToolTip(
+ tr("Current evidence is private. Click to switch to global."));
+ }
+}
+void Courtroom::on_evidence_transfer_clicked()
+{
if (current_evidence >= local_evidence_list.size())
return;
- QStringList f_contents;
+ QString name;
+ if (!current_evidence_global) // Transfer private evidence to global
+ {
+ evi_type f_evi = local_evidence_list.at(current_evidence);
- evi_type f_evi = local_evidence_list.at(current_evidence);
+ QStringList f_contents;
+ f_contents.append(f_evi.name);
+ f_contents.append(f_evi.description);
+ f_contents.append(f_evi.image);
- f_contents.append(QString::number(current_evidence));
- f_contents.append(f_evi.name);
- f_contents.append(ui_evidence_description->toPlainText());
- f_contents.append(f_evi.image);
+ name = f_evi.name;
+ ao_app->send_server_packet(new AOPacket("PE", f_contents));
+ }
+ else // Transfer global evidence to private
+ {
+ evi_type f_evi = local_evidence_list.at(current_evidence);
+ name = f_evi.name;
+ private_evidence_list.append(f_evi);
+ }
+
+ QMessageBox *msgBox = new QMessageBox;
+ msgBox->setText(tr("\"%1\" has been transferred.").arg(name));
+ msgBox->setStandardButtons(QMessageBox::Ok);
+ msgBox->setDefaultButton(QMessageBox::Ok);
+ msgBox->exec();
+}
- ao_app->send_server_packet(new AOPacket("EE", f_contents));
+void Courtroom::on_evidence_edited()
+{
+ if (current_evidence >=
+ local_evidence_list.size()) // Should never happen but you never know.
+ return;
+ evi_type fake_evidence;
+ fake_evidence.name = ui_evidence_name->text();
+ fake_evidence.description = ui_evidence_description->toPlainText();
+ fake_evidence.image = ui_evidence_image_name->text();
+ if (compare_evidence_changed(fake_evidence,
+ local_evidence_list.at(current_evidence)))
+ ui_evidence_ok->show();
+ else
+ ui_evidence_ok->hide();
+}
+void Courtroom::evidence_close()
+{
+ ui_evidence_description->setReadOnly(true);
+ ui_evidence_description->setToolTip("");
+ ui_evidence_name->setReadOnly(true);
+ ui_evidence_name->setToolTip("");
+ ui_evidence_image_name->setReadOnly(true);
+ ui_evidence_image_name->setToolTip("");
+ ui_evidence_overlay->hide();
ui_ic_chat_message->setFocus();
}
+
+void Courtroom::evidence_switch(bool global)
+{
+ current_evidence_global = global;
+ is_presenting_evidence = false;
+ ui_evidence_present->set_image("present");
+ local_evidence_list.clear();
+ if (current_evidence_global) {
+ local_evidence_list = global_evidence_list;
+ ui_evidence_present->show();
+ ui_evidence_save->hide();
+ ui_evidence_load->hide();
+ }
+ else {
+ local_evidence_list = private_evidence_list;
+ ui_evidence_present->hide();
+ ui_evidence_save->show();
+ ui_evidence_load->show();
+ }
+ current_evidence_page = 0;
+ set_evidence_page();
+}
+
+void Courtroom::on_evidence_save_clicked()
+{
+ if (current_evidence_global)
+ return; // Don't allow saving/loading operations when in global inventory
+ // mode for now
+
+ QString p_path = QFileDialog::getSaveFileName(
+ this, tr("Save Inventory"), "base/inventories/", tr("Ini Files (*.ini)"));
+ if (p_path.isEmpty())
+ return;
+
+ evidence_close();
+ ui_evidence_name->setText("");
+
+ QSettings inventory(p_path, QSettings::IniFormat);
+ inventory.clear();
+ for (int i = 0; i < local_evidence_list.size(); i++) {
+ inventory.beginGroup(QString::number(i));
+ inventory.setValue("name", local_evidence_list[i].name);
+ inventory.setValue("description", local_evidence_list[i].description);
+ inventory.setValue("image", local_evidence_list[i].image);
+ inventory.endGroup();
+ }
+ inventory.sync();
+}
+
+void Courtroom::on_evidence_load_clicked()
+{
+ if (current_evidence_global)
+ return; // Don't allow saving/loading operations when in global inventory
+ // mode for now
+
+ QString p_path = QFileDialog::getOpenFileName(
+ this, tr("Open Inventory"), "base/inventories/", tr("Ini Files (*.ini)"));
+ if (p_path.isEmpty())
+ return;
+
+ evidence_close();
+ ui_evidence_name->setText("");
+
+ QSettings inventory(p_path, QSettings::IniFormat);
+ local_evidence_list.clear();
+ foreach (QString evi, inventory.childGroups()) {
+ if (evi == "General")
+ continue;
+
+ evi_type f_evi;
+ f_evi.name = inventory.value(evi + "/name", tr("UNKNOWN")).value<QString>();
+ f_evi.description =
+ inventory.value(evi + "/description", tr("UNKNOWN")).value<QString>();
+ f_evi.image =
+ inventory.value(evi + "/image", "UNKNOWN.png").value<QString>();
+ local_evidence_list.append(f_evi);
+ }
+ private_evidence_list = local_evidence_list;
+ set_evidence_page();
+}
+
+bool Courtroom::compare_evidence_changed(evi_type evi_a, evi_type evi_b)
+{
+ return evi_a.name != evi_b.name || evi_a.image != evi_b.image ||
+ evi_a.description != evi_b.description;
+}
diff --git a/src/hardware_functions.cpp b/src/hardware_functions.cpp
index 96c72eb5..2f3c44d3 100644
--- a/src/hardware_functions.cpp
+++ b/src/hardware_functions.cpp
@@ -1,6 +1,9 @@
#include "hardware_functions.h"
#include <QDebug>
+#include <QtGlobal>
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
#if (defined(_WIN32) || defined(_WIN64))
#include <windows.h>
@@ -49,6 +52,7 @@ QString get_hdid()
}
#elif defined __APPLE__
+
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
@@ -80,3 +84,16 @@ QString get_hdid()
#error This operating system is unsupported for hardware functions.
#endif
+
+#else
+#include <QSysInfo>
+
+QByteArray machineId;
+
+QString get_hdid()
+{
+ machineId = QSysInfo::machineUniqueId();
+ return QString(machineId);
+}
+
+#endif
diff --git a/src/lobby.cpp b/src/lobby.cpp
index 853b6ae7..3aa488ad 100644
--- a/src/lobby.cpp
+++ b/src/lobby.cpp
@@ -1,403 +1,548 @@
-#include "lobby.h"
-
-#include "aoapplication.h"
-#include "aosfxplayer.h"
-#include "debug_functions.h"
-#include "networkmanager.h"
-
-Lobby::Lobby(AOApplication *p_ao_app) : QMainWindow()
-{
- ao_app = p_ao_app;
-
- this->setWindowTitle(tr("Attorney Online 2"));
- this->setWindowIcon(QIcon(":/logo.png"));
-
- ui_background = new AOImage(this, ao_app);
- ui_public_servers = new AOButton(this, ao_app);
- ui_favorites = new AOButton(this, ao_app);
- ui_refresh = new AOButton(this, ao_app);
- ui_add_to_fav = new AOButton(this, ao_app);
- ui_connect = new AOButton(this, ao_app);
- ui_version = new QLabel(this);
- ui_about = new AOButton(this, ao_app);
- ui_server_list = new QListWidget(this);
- ui_player_count = new QLabel(this);
- ui_description = new AOTextArea(this);
- ui_chatbox = new AOTextArea(this);
- ui_chatbox->setOpenExternalLinks(true);
- ui_chatname = new QLineEdit(this);
- ui_chatname->setPlaceholderText(tr("Name"));
- ui_chatname->setText(ao_app->get_ooc_name());
- ui_chatmessage = new QLineEdit(this);
- ui_loading_background = new AOImage(this, ao_app);
- ui_loading_text = new QTextEdit(ui_loading_background);
- ui_progress_bar = new QProgressBar(ui_loading_background);
- ui_progress_bar->setMinimum(0);
- ui_progress_bar->setMaximum(100);
- ui_progress_bar->setStyleSheet("QProgressBar{ color: white; }");
- ui_cancel = new AOButton(ui_loading_background, ao_app);
-
- connect(ui_public_servers, SIGNAL(clicked()), this,
- SLOT(on_public_servers_clicked()));
- connect(ui_favorites, SIGNAL(clicked()), this, SLOT(on_favorites_clicked()));
- connect(ui_refresh, SIGNAL(pressed()), this, SLOT(on_refresh_pressed()));
- connect(ui_refresh, SIGNAL(released()), this, SLOT(on_refresh_released()));
- connect(ui_add_to_fav, SIGNAL(pressed()), this,
- SLOT(on_add_to_fav_pressed()));
- connect(ui_add_to_fav, SIGNAL(released()), this,
- SLOT(on_add_to_fav_released()));
- connect(ui_connect, SIGNAL(pressed()), this, SLOT(on_connect_pressed()));
- connect(ui_connect, SIGNAL(released()), this, SLOT(on_connect_released()));
- connect(ui_about, SIGNAL(clicked()), this, SLOT(on_about_clicked()));
- connect(ui_server_list, SIGNAL(clicked(QModelIndex)), this,
- SLOT(on_server_list_clicked(QModelIndex)));
- connect(ui_server_list, SIGNAL(activated(QModelIndex)), this,
- SLOT(on_server_list_doubleclicked(QModelIndex)));
- connect(ui_chatmessage, SIGNAL(returnPressed()), this,
- SLOT(on_chatfield_return_pressed()));
- connect(ui_cancel, SIGNAL(clicked()), ao_app, SLOT(loading_cancelled()));
-
- ui_connect->setEnabled(false);
-
- list_servers();
-
- set_widgets();
-}
-
-// sets images, position and size
-void Lobby::set_widgets()
-{
- ao_app->reload_theme();
-
- QString filename = "lobby_design.ini";
-
- pos_size_type f_lobby = ao_app->get_element_dimensions("lobby", filename);
-
- if (f_lobby.width < 0 || f_lobby.height < 0) {
- qDebug() << "W: did not find lobby width or height in "
- << ao_app->get_theme_path(filename);
-
- // Most common symptom of bad config files and missing assets.
- call_notice(
- tr("It doesn't look like your client is set up correctly.\n"
- "Did you download all resources correctly from tiny.cc/getao, "
- "including the large 'base' folder?"));
-
- this->resize(517, 666);
- }
- else {
- this->resize(f_lobby.width, f_lobby.height);
- }
-
- set_size_and_pos(ui_background, "lobby");
- ui_background->set_image("lobbybackground.png");
-
- set_size_and_pos(ui_public_servers, "public_servers");
- ui_public_servers->set_image("publicservers_selected.png");
-
- set_size_and_pos(ui_favorites, "favorites");
- ui_favorites->set_image("favorites.png");
-
- set_size_and_pos(ui_refresh, "refresh");
- ui_refresh->set_image("refresh.png");
-
- set_size_and_pos(ui_add_to_fav, "add_to_fav");
- ui_add_to_fav->set_image("addtofav.png");
-
- set_size_and_pos(ui_connect, "connect");
- ui_connect->set_image("connect.png");
-
- set_size_and_pos(ui_version, "version");
- ui_version->setText(tr("Version: %1").arg(ao_app->get_version_string()));
-
- set_size_and_pos(ui_about, "about");
- ui_about->set_image("about.png");
-
- set_size_and_pos(ui_server_list, "server_list");
- ui_server_list->setStyleSheet("background-color: rgba(0, 0, 0, 0);"
- "font: bold;");
-
- set_size_and_pos(ui_player_count, "player_count");
- ui_player_count->setText(tr("Offline"));
- ui_player_count->setStyleSheet("font: bold;"
- "color: white;"
- "qproperty-alignment: AlignCenter;");
-
- set_size_and_pos(ui_description, "description");
- ui_description->setReadOnly(true);
- ui_description->setStyleSheet("background-color: rgba(0, 0, 0, 0);"
- "color: white;");
-
- set_size_and_pos(ui_chatbox, "chatbox");
- ui_chatbox->setReadOnly(true);
- ui_chatbox->setStyleSheet(
- "QTextBrowser{background-color: rgba(0, 0, 0, 0);}");
-
- set_size_and_pos(ui_chatname, "chatname");
- ui_chatname->setStyleSheet("background-color: rgba(0, 0, 0, 0);"
- "selection-background-color: rgba(0, 0, 0, 0);");
-
- set_size_and_pos(ui_chatmessage, "chatmessage");
- ui_chatmessage->setStyleSheet(
- "background-color: rgba(0, 0, 0, 0);"
- "selection-background-color: rgba(0, 0, 0, 0);");
-
- ui_loading_background->resize(this->width(), this->height());
- ui_loading_background->set_image("loadingbackground.png");
-
- set_size_and_pos(ui_loading_text, "loading_label");
- ui_loading_text->setFont(QFont("Arial", 20, QFont::Bold));
- ui_loading_text->setReadOnly(true);
- ui_loading_text->setAlignment(Qt::AlignCenter);
- ui_loading_text->setFrameStyle(QFrame::NoFrame);
- ui_loading_text->setStyleSheet("background-color: rgba(0, 0, 0, 0);"
- "color: rgba(255, 128, 0, 255);");
- ui_loading_text->append(tr("Loading"));
-
- set_size_and_pos(ui_progress_bar, "progress_bar");
- set_size_and_pos(ui_cancel, "cancel");
- ui_cancel->setText(tr("Cancel"));
-
- ui_loading_background->hide();
-}
-
-void Lobby::lobbyThreadHandler(QString loadingText)
-{
- this->set_loading_text(loadingText);
-}
-
-void Lobby::set_size_and_pos(QWidget *p_widget, QString p_identifier)
-{
- QString filename = "lobby_design.ini";
-
- pos_size_type design_ini_result =
- ao_app->get_element_dimensions(p_identifier, filename);
-
- if (design_ini_result.width < 0 || design_ini_result.height < 0) {
- qDebug() << "W: could not find " << p_identifier << " in " << filename;
- p_widget->hide();
- }
- else {
- p_widget->move(design_ini_result.x, design_ini_result.y);
- p_widget->resize(design_ini_result.width, design_ini_result.height);
- }
-}
-
-void Lobby::set_loading_text(QString p_text)
-{
- ui_loading_text->clear();
- ui_loading_text->setAlignment(Qt::AlignCenter);
- ui_loading_text->append(p_text);
-}
-
-QString Lobby::get_chatlog()
-{
- QString return_value = ui_chatbox->toPlainText();
-
- return return_value;
-}
-
-int Lobby::get_selected_server() { return ui_server_list->currentRow(); }
-
-void Lobby::set_loading_value(int p_value)
-{
- ui_progress_bar->setValue(p_value);
-}
-
-void Lobby::on_public_servers_clicked()
-{
- ui_public_servers->set_image("publicservers_selected.png");
- ui_favorites->set_image("favorites.png");
-
- list_servers();
-
- public_servers_selected = true;
-}
-
-void Lobby::on_favorites_clicked()
-{
- ui_favorites->set_image("favorites_selected.png");
- ui_public_servers->set_image("publicservers.png");
-
- ao_app->set_favorite_list();
- // ao_app->favorite_list = read_serverlist_txt();
-
- list_favorites();
-
- public_servers_selected = false;
-}
-
-void Lobby::on_refresh_pressed()
-{
- ui_refresh->set_image("refresh_pressed.png");
-}
-
-void Lobby::on_refresh_released()
-{
- ui_refresh->set_image("refresh.png");
-
- AOPacket *f_packet = new AOPacket("ALL#%");
-
- ao_app->send_ms_packet(f_packet);
-}
-
-void Lobby::on_add_to_fav_pressed()
-{
- ui_add_to_fav->set_image("addtofav_pressed.png");
-}
-
-void Lobby::on_add_to_fav_released()
-{
- ui_add_to_fav->set_image("addtofav.png");
-
- // you cant add favorites from favorites m8
- if (!public_servers_selected)
- return;
-
- ao_app->add_favorite_server(ui_server_list->currentRow());
-}
-
-void Lobby::on_connect_pressed()
-{
- ui_connect->set_image("connect_pressed.png");
-}
-
-void Lobby::on_connect_released()
-{
- ui_connect->set_image("connect.png");
-
- AOPacket *f_packet;
-
- f_packet = new AOPacket("askchaa#%");
-
- ao_app->send_server_packet(f_packet);
-}
-
-void Lobby::on_about_clicked()
-{
- QString msg =
- tr("<h2>Attorney Online %1</h2>"
- "The courtroom drama simulator"
- "<p><b>Source code:</b> "
- "<a href='https://github.com/AttorneyOnline/AO2-Client'>"
- "https://github.com/AttorneyOnline/AO2-Client</a>"
- "<p><b>Major development:</b><br>"
- "OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, "
- "Cents02"
- "<p><b>Special thanks:</b><br>"
- "Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), "
- "Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, "
- "Noevain, Cronnicossy, Raidensnake")
- .arg(ao_app->get_version_string());
- QMessageBox::about(this, "About", msg);
-}
-
-// clicked on an item in the serverlist
-void Lobby::on_server_list_clicked(QModelIndex p_model)
-{
- if (p_model != last_model) {
- server_type f_server;
- last_model = p_model;
- int n_server = p_model.row();
-
- if (n_server < 0)
- return;
-
- if (public_servers_selected) {
- QVector<server_type> f_server_list = ao_app->get_server_list();
-
- if (n_server >= f_server_list.size())
- return;
-
- f_server = f_server_list.at(p_model.row());
- }
- else {
- if (n_server >= ao_app->get_favorite_list().size())
- return;
-
- f_server = ao_app->get_favorite_list().at(p_model.row());
- }
-
- ui_description->clear();
- ui_description->append(f_server.desc);
-
- ui_description->moveCursor(QTextCursor::Start);
- ui_description->ensureCursorVisible();
-
- ui_player_count->setText(tr("Offline"));
-
- ui_connect->setEnabled(false);
-
- ao_app->net_manager->connect_to_server(f_server);
- }
-}
-
-// doubleclicked on an item in the serverlist so we'll connect right away
-void Lobby::on_server_list_doubleclicked(QModelIndex p_model)
-{
- on_server_list_clicked(p_model);
- on_connect_released();
-}
-
-void Lobby::on_chatfield_return_pressed()
-{
- // no you can't send empty messages
- if (ui_chatname->text() == "" || ui_chatmessage->text() == "")
- return;
-
- QString f_header = "CT";
- QStringList f_contents{ui_chatname->text(), ui_chatmessage->text()};
-
- AOPacket *f_packet = new AOPacket(f_header, f_contents);
-
- ao_app->send_ms_packet(f_packet);
-
- ui_chatmessage->clear();
-}
-
-void Lobby::list_servers()
-{
- public_servers_selected = true;
- ui_favorites->set_image("favorites.png");
- ui_public_servers->set_image("publicservers_selected.png");
-
- ui_server_list->clear();
-
- for (server_type i_server : ao_app->get_server_list()) {
- ui_server_list->addItem(i_server.name);
- }
-}
-
-void Lobby::list_favorites()
-{
- ui_server_list->clear();
-
- for (server_type i_server : ao_app->get_favorite_list()) {
- ui_server_list->addItem(i_server.name);
- }
-}
-
-void Lobby::append_chatmessage(QString f_name, QString f_message)
-{
- ui_chatbox->append_chatmessage(
- f_name, f_message,
- ao_app->get_color("ooc_default_color", "courtroom_design.ini").name(),
- false);
-}
-
-void Lobby::append_error(QString f_message)
-{
- ui_chatbox->append_error(f_message);
-}
-
-void Lobby::set_player_count(int players_online, int max_players)
-{
- QString f_string = tr("Online: %1/%2")
- .arg(QString::number(players_online))
- .arg(QString::number(max_players));
- ui_player_count->setText(f_string);
-}
-
-void Lobby::enable_connect_button() { ui_connect->setEnabled(true); }
-
-Lobby::~Lobby() {}
+#include "lobby.h"
+
+#include "aoapplication.h"
+#include "aosfxplayer.h"
+#include "debug_functions.h"
+#include "networkmanager.h"
+
+Lobby::Lobby(AOApplication *p_ao_app) : QMainWindow()
+{
+ ao_app = p_ao_app;
+
+ this->setWindowTitle(tr("Attorney Online 2"));
+ this->setWindowIcon(QIcon(":/logo.png"));
+
+ ui_background = new AOImage(this, ao_app);
+ ui_public_servers = new AOButton(this, ao_app);
+ ui_favorites = new AOButton(this, ao_app);
+ ui_refresh = new AOButton(this, ao_app);
+ ui_add_to_fav = new AOButton(this, ao_app);
+ ui_connect = new AOButton(this, ao_app);
+ ui_version = new QLabel(this);
+ ui_about = new AOButton(this, ao_app);
+ ui_settings = new AOButton(this, ao_app);
+
+ ui_server_list = new QTreeWidget(this);
+ ui_server_list->setHeaderLabels({"#", "Name"}); //, "Players"});
+ ui_server_list->hideColumn(0);
+
+ ui_server_search = new QLineEdit(this);
+ ui_server_search->setFrame(false);
+ ui_server_search->setPlaceholderText(tr("Search"));
+
+ ui_player_count = new QLabel(this);
+ ui_description = new AOTextArea(this);
+ ui_description->setOpenExternalLinks(true);
+ ui_chatbox = new AOTextArea(this);
+ ui_chatbox->setOpenExternalLinks(true);
+ ui_chatname = new QLineEdit(this);
+ ui_chatname->setPlaceholderText(tr("Name"));
+ ui_chatname->setText(ao_app->get_ooc_name());
+ ui_chatmessage = new QLineEdit(this);
+ ui_loading_background = new AOImage(this, ao_app);
+ ui_loading_text = new QTextEdit(ui_loading_background);
+ ui_progress_bar = new QProgressBar(ui_loading_background);
+ ui_progress_bar->setMinimum(0);
+ ui_progress_bar->setMaximum(100);
+ ui_progress_bar->setStyleSheet("QProgressBar{ color: white; }");
+ ui_cancel = new AOButton(ui_loading_background, ao_app);
+
+ connect(ui_public_servers, SIGNAL(clicked()), this,
+ SLOT(on_public_servers_clicked()));
+ connect(ui_favorites, SIGNAL(clicked()), this, SLOT(on_favorites_clicked()));
+ connect(ui_refresh, SIGNAL(pressed()), this, SLOT(on_refresh_pressed()));
+ connect(ui_refresh, SIGNAL(released()), this, SLOT(on_refresh_released()));
+ connect(ui_add_to_fav, SIGNAL(pressed()), this,
+ SLOT(on_add_to_fav_pressed()));
+ connect(ui_add_to_fav, SIGNAL(released()), this,
+ SLOT(on_add_to_fav_released()));
+ connect(ui_connect, SIGNAL(pressed()), this, SLOT(on_connect_pressed()));
+ connect(ui_connect, SIGNAL(released()), this, SLOT(on_connect_released()));
+ connect(ui_about, SIGNAL(clicked()), this, SLOT(on_about_clicked()));
+ connect(ui_settings, SIGNAL(clicked()), this, SLOT(on_settings_clicked()));
+ connect(ui_server_list, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
+ SLOT(on_server_list_clicked(QTreeWidgetItem *, int)));
+ connect(ui_server_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
+ this, SLOT(on_server_list_doubleclicked(QTreeWidgetItem *, int)));
+ connect(ui_server_search, SIGNAL(textChanged(QString)), this,
+ SLOT(on_server_search_edited(QString)));
+ connect(ui_chatmessage, SIGNAL(returnPressed()), this,
+ SLOT(on_chatfield_return_pressed()));
+ connect(ui_cancel, SIGNAL(clicked()), ao_app, SLOT(loading_cancelled()));
+
+ ui_connect->setEnabled(false);
+
+ list_servers();
+
+ set_widgets();
+}
+
+// sets images, position and size
+void Lobby::set_widgets()
+{
+ ao_app->reload_theme();
+
+ QString filename = "lobby_design.ini";
+
+ pos_size_type f_lobby = ao_app->get_element_dimensions("lobby", filename);
+
+ if (f_lobby.width < 0 || f_lobby.height < 0) {
+ qDebug() << "W: did not find lobby width or height in " << filename;
+
+ // Most common symptom of bad config files and missing assets.
+ call_notice(
+ tr("It doesn't look like your client is set up correctly.\n"
+ "Did you download all resources correctly from tiny.cc/getao, "
+ "including the large 'base' folder?"));
+
+ this->resize(517, 666);
+ }
+ else {
+ this->resize(f_lobby.width, f_lobby.height);
+ }
+
+ set_size_and_pos(ui_background, "lobby");
+ ui_background->set_image("lobbybackground");
+
+ set_size_and_pos(ui_public_servers, "public_servers");
+ ui_public_servers->set_image("publicservers_selected");
+
+ set_size_and_pos(ui_favorites, "favorites");
+ ui_favorites->set_image("favorites");
+
+ set_size_and_pos(ui_refresh, "refresh");
+ ui_refresh->set_image("refresh");
+
+ set_size_and_pos(ui_add_to_fav, "add_to_fav");
+ ui_add_to_fav->set_image("addtofav");
+
+ set_size_and_pos(ui_connect, "connect");
+ ui_connect->set_image("connect");
+
+ set_size_and_pos(ui_version, "version");
+ ui_version->setText(tr("Version: %1").arg(ao_app->get_version_string()));
+
+ set_size_and_pos(ui_about, "about");
+ ui_about->set_image("about");
+
+ set_size_and_pos(ui_settings, "settings");
+ ui_settings->setText(tr("Settings"));
+ ui_settings->set_image("settings");
+ ui_settings->setToolTip(
+ tr("Allows you to change various aspects of the client."));
+
+ set_size_and_pos(ui_server_list, "server_list");
+ ui_server_list->setStyleSheet("background-color: rgba(0, 0, 0, 0);"
+ "font: bold;");
+
+ set_size_and_pos(ui_server_search, "server_search");
+ ui_server_search->setStyleSheet("background-color: rgba(0, 0, 0, 0);");
+
+ set_size_and_pos(ui_player_count, "player_count");
+ ui_player_count->setText(tr("Offline"));
+ ui_player_count->setStyleSheet("font: bold;"
+ "color: white;"
+ "qproperty-alignment: AlignCenter;");
+
+ set_size_and_pos(ui_description, "description");
+ ui_description->setReadOnly(true);
+ ui_description->setStyleSheet("background-color: rgba(0, 0, 0, 0);"
+ "color: white;");
+
+ set_size_and_pos(ui_chatbox, "chatbox");
+ ui_chatbox->setReadOnly(true);
+ ui_chatbox->setStyleSheet(
+ "QTextBrowser{background-color: rgba(0, 0, 0, 0);}");
+
+ set_size_and_pos(ui_chatname, "chatname");
+ ui_chatname->setStyleSheet("background-color: rgba(0, 0, 0, 0);"
+ "selection-background-color: rgba(0, 0, 0, 0);");
+
+ set_size_and_pos(ui_chatmessage, "chatmessage");
+ ui_chatmessage->setStyleSheet(
+ "background-color: rgba(0, 0, 0, 0);"
+ "selection-background-color: rgba(0, 0, 0, 0);");
+
+ ui_loading_background->resize(this->width(), this->height());
+ ui_loading_background->set_image("loadingbackground");
+
+ set_size_and_pos(ui_loading_text, "loading_label");
+ ui_loading_text->setFont(QFont("Arial", 20, QFont::Bold));
+ ui_loading_text->setReadOnly(true);
+ ui_loading_text->setAlignment(Qt::AlignCenter);
+ ui_loading_text->setFrameStyle(QFrame::NoFrame);
+ ui_loading_text->setStyleSheet("background-color: rgba(0, 0, 0, 0);"
+ "color: rgba(255, 128, 0, 255);");
+ ui_loading_text->append(tr("Loading"));
+
+ set_size_and_pos(ui_progress_bar, "progress_bar");
+ set_size_and_pos(ui_cancel, "cancel");
+ ui_cancel->setText(tr("Cancel"));
+
+ ui_loading_background->hide();
+
+ set_fonts();
+ set_stylesheets();
+}
+
+void Lobby::set_size_and_pos(QWidget *p_widget, QString p_identifier)
+{
+ QString filename = "lobby_design.ini";
+
+ pos_size_type design_ini_result =
+ ao_app->get_element_dimensions(p_identifier, filename);
+
+ if (design_ini_result.width < 0 || design_ini_result.height < 0) {
+ qDebug() << "W: could not find " << p_identifier << " in " << filename;
+ p_widget->hide();
+ }
+ else {
+ p_widget->move(design_ini_result.x, design_ini_result.y);
+ p_widget->resize(design_ini_result.width, design_ini_result.height);
+ }
+}
+
+void Lobby::set_fonts()
+{
+ set_font(ui_player_count, "player_count");
+ set_font(ui_description, "description");
+ set_font(ui_chatbox, "chatbox");
+ set_font(ui_chatname, "chatname");
+ set_font(ui_chatmessage, "chatmessage");
+ set_font(ui_loading_text, "loading_text");
+ set_font(ui_server_list, "server_list");
+}
+
+void Lobby::set_stylesheet(QWidget *widget, QString target_tag)
+{
+ QString f_file = "lobby_stylesheets.css";
+ QString style_sheet_string =
+ ao_app->get_tagged_stylesheet(target_tag, f_file);
+ if (style_sheet_string != "")
+ widget->setStyleSheet(style_sheet_string);
+}
+
+void Lobby::set_stylesheets()
+{
+ set_stylesheet(ui_player_count, "[PLAYER COUNT]");
+ set_stylesheet(ui_description, "[DESCRIPTION]");
+ set_stylesheet(ui_chatbox, "[CHAT BOX]");
+ set_stylesheet(ui_chatname, "[CHAT NAME]");
+ set_stylesheet(ui_chatmessage, "[CHAT MESSAGE]");
+ set_stylesheet(ui_loading_text, "[LOADING TEXT]");
+ set_stylesheet(ui_server_list, "[SERVER LIST]");
+}
+
+void Lobby::set_font(QWidget *widget, QString p_identifier)
+{
+ QString design_file = "lobby_fonts.ini";
+ int f_weight = ao_app->get_font_size(p_identifier, design_file);
+ QString class_name = widget->metaObject()->className();
+ QString font_name =
+ ao_app->get_font_name(p_identifier + "_font", design_file);
+ QFont font(font_name, f_weight);
+ bool use = ao_app->get_font_size("use_custom_fonts", design_file) == 1;
+ if (use) {
+ bool bold = ao_app->get_font_size(p_identifier + "_bold", design_file) ==
+ 1; // is the font bold or not?
+ font.setBold(bold);
+ widget->setFont(font);
+ QColor f_color = ao_app->get_color(p_identifier + "_color", design_file);
+ bool center =
+ ao_app->get_font_size(p_identifier + "_center", design_file) ==
+ 1; // should it be centered?
+ QString is_center = "";
+ if (center)
+ is_center = "qproperty-alignment: AlignCenter;";
+ QString style_sheet_string =
+ class_name + " { background-color: rgba(0, 0, 0, 0);\n" +
+ "color: rgba(" + QString::number(f_color.red()) + ", " +
+ QString::number(f_color.green()) + ", " +
+ QString::number(f_color.blue()) + ", 255);\n" + is_center + "}";
+ widget->setStyleSheet(style_sheet_string);
+ }
+ return;
+}
+
+void Lobby::set_loading_text(QString p_text)
+{
+ ui_loading_text->clear();
+ ui_loading_text->setAlignment(Qt::AlignCenter);
+ ui_loading_text->append(p_text);
+}
+
+QString Lobby::get_chatlog()
+{
+ QString return_value = ui_chatbox->toPlainText();
+
+ return return_value;
+}
+
+int Lobby::get_selected_server()
+{
+ return ui_server_list->currentItem()->text(0).toInt();
+}
+
+void Lobby::set_loading_value(int p_value)
+{
+ ui_progress_bar->setValue(p_value);
+}
+
+void Lobby::on_public_servers_clicked()
+{
+ ui_public_servers->set_image("publicservers_selected");
+ ui_favorites->set_image("favorites");
+
+ list_servers();
+
+ public_servers_selected = true;
+}
+
+void Lobby::on_favorites_clicked()
+{
+ ui_favorites->set_image("favorites_selected");
+ ui_public_servers->set_image("publicservers");
+
+ ao_app->set_favorite_list();
+ // ao_app->favorite_list = read_serverlist_txt();
+
+ list_favorites();
+
+ public_servers_selected = false;
+}
+
+void Lobby::on_refresh_pressed() { ui_refresh->set_image("refresh_pressed"); }
+
+void Lobby::on_refresh_released()
+{
+ ui_refresh->set_image("refresh");
+
+ AOPacket *f_packet = new AOPacket("ALL#%");
+
+ ao_app->send_ms_packet(f_packet);
+}
+
+void Lobby::on_add_to_fav_pressed()
+{
+ ui_add_to_fav->set_image("addtofav_pressed");
+}
+
+void Lobby::on_add_to_fav_released()
+{
+ ui_add_to_fav->set_image("addtofav");
+
+ // you cant add favorites from favorites m8
+ if (!public_servers_selected)
+ return;
+
+ ao_app->add_favorite_server(get_selected_server());
+}
+
+void Lobby::on_connect_pressed() { ui_connect->set_image("connect_pressed"); }
+
+void Lobby::on_connect_released()
+{
+ ui_connect->set_image("connect");
+
+ AOPacket *f_packet;
+
+ f_packet = new AOPacket("askchaa#%");
+
+ ao_app->send_server_packet(f_packet);
+}
+
+void Lobby::on_about_clicked()
+{
+#ifdef BASSAUDIO
+ const QString audio = "BASS";
+#elif defined(QTAUDIO)
+ const QString audio = "Qt Multimedia";
+#else
+ const QString audio = "null";
+#endif
+
+ QString msg =
+ tr("<h2>Attorney Online %1</h2>"
+ "The courtroom drama simulator"
+ "<p><b>Source code:</b> "
+ "<a href='https://github.com/AttorneyOnline/AO2-Client'>"
+ "https://github.com/AttorneyOnline/AO2-Client</a>"
+ "<p><b>Major development:</b><br>"
+ "OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, "
+ "Crystalwarrior, Iamgoofball"
+ "<p><b>Client development:</b><br>"
+ "Cents02, in1tiate, raidensnake, windrammer"
+ "<p><b>QA testing:</b><br>"
+ "CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, "
+ "Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, "
+ "Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, "
+ "Veritas, Wiso"
+ "<p><b>Special thanks:</b><br>"
+ "CrazyJC (2.8 release director) and MaximumVolty (2.8 release promotion); "
+ "Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); "
+ "Rue (website); Draxirch (UI design); "
+ "Lewdton and Argoneus (tsuserver); "
+ "Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); "
+ "server hosts, game masters, case makers, content creators, "
+ "and the whole AO2 community!"
+ "<p>The Attorney Online networked visual novel project "
+ "is copyright (c) 2016-2020 Attorney Online developers. Open-source "
+ "licenses apply. All other assets are the property of their "
+ "respective owners."
+ "<p>Running on Qt version %2 with the %3 audio engine."
+ "<p>Built on %4")
+ .arg(ao_app->get_version_string())
+ .arg(QLatin1String(QT_VERSION_STR))
+ .arg(audio)
+ .arg(QLatin1String(__DATE__));
+ QMessageBox::about(this, tr("About"), msg);
+}
+
+void Lobby::on_settings_clicked() { ao_app->call_settings_menu(); }
+
+// clicked on an item in the serverlist
+void Lobby::on_server_list_clicked(QTreeWidgetItem *p_item, int column)
+{
+ column = 0;
+ if (p_item->text(column).toInt() != last_index || !public_servers_selected) {
+ server_type f_server;
+ int n_server = p_item->text(column).toInt();
+ last_index = n_server;
+
+ if (n_server < 0)
+ return;
+
+ if (public_servers_selected) {
+ QVector<server_type> f_server_list = ao_app->get_server_list();
+
+ if (n_server >= f_server_list.size())
+ return;
+
+ f_server = f_server_list.at(n_server);
+ }
+ else {
+ if (n_server >= ao_app->get_favorite_list().size())
+ return;
+
+ f_server = ao_app->get_favorite_list().at(n_server);
+ }
+
+ ui_description->clear();
+ ui_description->append_linked(f_server.desc);
+
+ ui_description->moveCursor(QTextCursor::Start);
+ ui_description->ensureCursorVisible();
+
+ ui_player_count->setText(tr("Offline"));
+
+ ui_connect->setEnabled(false);
+
+ ao_app->net_manager->connect_to_server(f_server);
+ }
+}
+
+// doubleclicked on an item in the serverlist so we'll connect right away
+void Lobby::on_server_list_doubleclicked(QTreeWidgetItem *p_item, int column)
+{
+ on_server_list_clicked(p_item, column);
+ on_connect_released();
+}
+
+void Lobby::on_server_search_edited(QString p_text)
+{
+ // Iterate through all QTreeWidgetItem items
+ QTreeWidgetItemIterator it(ui_server_list);
+ while (*it) {
+ (*it)->setHidden(p_text != "");
+ ++it;
+ }
+
+ if (p_text != "") {
+ // Search in metadata
+ QList<QTreeWidgetItem *> clist = ui_server_list->findItems(
+ ui_server_search->text(), Qt::MatchContains | Qt::MatchRecursive, 1);
+ foreach (QTreeWidgetItem *item, clist) {
+ if (item->parent() != nullptr) // So the category shows up too
+ item->parent()->setHidden(false);
+ item->setHidden(false);
+ }
+ }
+}
+
+void Lobby::on_chatfield_return_pressed()
+{
+ // no you can't send empty messages
+ if (ui_chatname->text() == "" || ui_chatmessage->text() == "")
+ return;
+
+ QString f_header = "CT";
+ QStringList f_contents{ui_chatname->text(), ui_chatmessage->text()};
+
+ AOPacket *f_packet = new AOPacket(f_header, f_contents);
+
+ ao_app->send_ms_packet(f_packet);
+
+ ui_chatmessage->clear();
+}
+
+void Lobby::list_servers()
+{
+ public_servers_selected = true;
+ ui_favorites->set_image("favorites");
+ ui_public_servers->set_image("publicservers_selected");
+
+ ui_server_list->setSortingEnabled(false);
+ ui_server_list->clear();
+
+ ui_server_search->setText("");
+
+ int i = 0;
+ for (server_type i_server : ao_app->get_server_list()) {
+ QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_server_list);
+ treeItem->setData(0, Qt::DisplayRole, i);
+ treeItem->setText(1, i_server.name);
+ i++;
+ }
+ ui_server_list->setSortingEnabled(true);
+ ui_server_list->sortItems(0, Qt::SortOrder::AscendingOrder);
+}
+
+void Lobby::list_favorites()
+{
+ ui_server_list->setSortingEnabled(false);
+ ui_server_list->clear();
+
+ int i = 0;
+ for (server_type i_server : ao_app->get_favorite_list()) {
+ QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_server_list);
+ treeItem->setData(0, Qt::DisplayRole, i);
+ treeItem->setText(1, i_server.name);
+ // treeItem->setText(2, "-");
+ i++;
+ }
+ ui_server_list->setSortingEnabled(true);
+}
+
+void Lobby::append_chatmessage(QString f_name, QString f_message)
+{
+ ui_chatbox->append_chatmessage(
+ f_name, f_message,
+ ao_app->get_color("ooc_default_color", "courtroom_design.ini").name());
+}
+
+void Lobby::append_error(QString f_message)
+{
+ ui_chatbox->append_error(f_message);
+}
+
+void Lobby::set_player_count(int players_online, int max_players)
+{
+ QString f_string = tr("Online: %1/%2")
+ .arg(QString::number(players_online))
+ .arg(QString::number(max_players));
+ ui_player_count->setText(f_string);
+}
+
+void Lobby::enable_connect_button() { ui_connect->setEnabled(true); }
+
+Lobby::~Lobby() {}
diff --git a/src/main.cpp b/src/main.cpp
index 1b105c34..364377b5 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,3 +1,4 @@
+
#include "aoapplication.h"
#include "courtroom.h"
@@ -22,6 +23,14 @@ int main(int argc, char *argv[])
QSettings *configini = main_app.configini;
+ QPluginLoader apngPlugin("qapng");
+ if (!apngPlugin.load())
+ qCritical() << "QApng plugin could not be loaded";
+
+ QPluginLoader webpPlugin("qwebp");
+ if (!webpPlugin.load())
+ qCritical() << "QWebp plugin could not be loaded";
+
QString p_language =
configini->value("language", QLocale::system().name()).toString();
if (p_language == " " || p_language == "")
@@ -38,7 +47,7 @@ int main(int argc, char *argv[])
main_app.installTranslator(&appTranslator);
main_app.construct_lobby();
- main_app.w_lobby->show();
main_app.net_manager->connect_to_master();
+ main_app.w_lobby->show();
return main_app.exec();
}
diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp
index a110ec4b..b543cfb5 100644
--- a/src/packet_distribution.cpp
+++ b/src/packet_distribution.cpp
@@ -1,710 +1,769 @@
-#include "aoapplication.h"
-
-#include "courtroom.h"
-#include "debug_functions.h"
-#include "encryption_functions.h"
-#include "hardware_functions.h"
-#include "lobby.h"
-#include "networkmanager.h"
-
-void AOPacketLoadMusic(AOApplication *my_app, QString file_name, bool is_music)
-{
- if (is_music) {
- my_app->w_courtroom->append_music(file_name);
- }
- else {
- my_app->w_courtroom->append_area(file_name);
- my_app->area_count++;
- }
- for (int area_n = 0; area_n < my_app->area_count; area_n++) {
- my_app->w_courtroom->arup_append(0, "Unknown", "Unknown", "Unknown");
- }
-}
-
-void AOApplication::ms_packet_received(AOPacket *p_packet)
-{
- p_packet->net_decode();
-
- QString header = p_packet->get_header();
- QStringList f_contents = p_packet->get_contents();
-
-#ifdef DEBUG_NETWORK
- if (header != "CHECK")
- qDebug() << "R(ms):" << p_packet->to_string();
-#endif
-
- if (header == "ALL") {
- server_list.clear();
-
- for (QString i_string : p_packet->get_contents()) {
- server_type f_server;
- QStringList sub_contents = i_string.split("&");
-
- if (sub_contents.size() < 4) {
- qDebug() << "W: malformed packet";
- continue;
- }
-
- f_server.name = sub_contents.at(0);
- f_server.desc = sub_contents.at(1);
- f_server.ip = sub_contents.at(2);
- f_server.port = sub_contents.at(3).toInt();
-
- server_list.append(f_server);
- }
-
- if (lobby_constructed) {
- w_lobby->list_servers();
- }
- }
- else if (header == "CT") {
- QString f_name, f_message;
-
- if (f_contents.size() == 1) {
- f_name = "";
- f_message = f_contents.at(0);
- }
- else if (f_contents.size() >= 2) {
- f_name = f_contents.at(0);
- f_message = f_contents.at(1);
- }
- else
- goto end;
-
- if (lobby_constructed) {
- w_lobby->append_chatmessage(f_name, f_message);
- }
- if (courtroom_constructed && courtroom_loaded) {
- w_courtroom->append_ms_chatmessage(f_name, f_message);
- }
- }
- else if (header == "AO2CHECK") {
- send_ms_packet(new AOPacket("ID#AO2#" + get_version_string() + "#%"));
- send_ms_packet(new AOPacket("HI#" + get_hdid() + "#%"));
-
- if (f_contents.size() < 1)
- goto end;
-
- QStringList version_contents = f_contents.at(0).split(".");
-
- if (version_contents.size() < 3)
- goto end;
-
- int f_release = version_contents.at(0).toInt();
- int f_major = version_contents.at(1).toInt();
- int f_minor = version_contents.at(2).toInt();
-
- if (get_release() > f_release)
- goto end;
- else if (get_release() == f_release) {
- if (get_major_version() > f_major)
- goto end;
- else if (get_major_version() == f_major) {
- if (get_minor_version() >= f_minor)
- goto end;
- }
- }
-
- call_notice(tr("Outdated version! Your version: %1\n"
- "Please go to aceattorneyonline.com to update.")
- .arg(get_version_string()));
- destruct_courtroom();
- destruct_lobby();
- }
- else if (header == "DOOM") {
- call_notice(tr("You have been exiled from AO.\n"
- "Have a nice day."));
- destruct_courtroom();
- destruct_lobby();
- }
-
-end:
-
- delete p_packet;
-}
-
-bool AOApplication::is_music_track(QString trackname)
-{
- return (trackname.startsWith("==") || trackname.endsWith(".wav") ||
- trackname.endsWith(".mp3") || trackname.endsWith(".mp4") ||
- trackname.endsWith(".ogg") || trackname.endsWith(".opus"));
-}
-
-void AOApplication::server_packet_received(AOPacket *p_packet)
-{
- p_packet->net_decode();
-
- QString header = p_packet->get_header();
- QStringList f_contents = p_packet->get_contents();
- QString f_packet = p_packet->to_string();
-
-#ifdef DEBUG_NETWORK
- if (header != "checkconnection")
- qDebug() << "R:" << f_packet;
-#endif
-
- if (header == "decryptor") {
- if (f_contents.size() == 0)
- goto end;
-
- // you may ask where 322 comes from. that would be a good question.
- s_decryptor = fanta_decrypt(f_contents.at(0), 322).toUInt();
-
- // default(legacy) values
- encryption_needed = true;
- yellow_text_enabled = false;
- prezoom_enabled = false;
- flipping_enabled = false;
- custom_objection_enabled = false;
- improved_loading_enabled = false;
- desk_mod_enabled = false;
- evidence_enabled = false;
- cccc_ic_support_enabled = false;
- arup_enabled = false;
- casing_alerts_enabled = false;
- modcall_reason_enabled = false;
- looping_sfx_support_enabled = false;
-
- // workaround for tsuserver4
- if (f_contents.at(0) == "NOENCRYPT")
- encryption_needed = false;
-
- QString f_hdid;
- f_hdid = get_hdid();
-
- AOPacket *hi_packet = new AOPacket("HI#" + f_hdid + "#%");
- send_server_packet(hi_packet);
- }
- else if (header == "ID") {
- if (f_contents.size() < 2)
- goto end;
-
- s_pv = f_contents.at(0).toInt();
- server_software = f_contents.at(1);
-
- w_lobby->enable_connect_button();
-
- send_server_packet(new AOPacket("ID#AO2#" + get_version_string() + "#%"));
- }
- else if (header == "CT") {
- if (f_contents.size() < 2)
- goto end;
-
- if (courtroom_constructed) {
- if (f_contents.size() == 3)
- w_courtroom->append_server_chatmessage(
- f_contents.at(0), f_contents.at(1), f_contents.at(2));
- else
- w_courtroom->append_server_chatmessage(f_contents.at(0),
- f_contents.at(1), "0");
- }
- }
- else if (header == "FL") {
- if (f_packet.contains("yellowtext", Qt::CaseInsensitive))
- yellow_text_enabled = true;
- if (f_packet.contains("flipping", Qt::CaseInsensitive))
- flipping_enabled = true;
- if (f_packet.contains("customobjections", Qt::CaseInsensitive))
- custom_objection_enabled = true;
- if (f_packet.contains("fastloading", Qt::CaseInsensitive))
- improved_loading_enabled = true;
- if (f_packet.contains("noencryption", Qt::CaseInsensitive))
- encryption_needed = false;
- if (f_packet.contains("deskmod", Qt::CaseInsensitive))
- desk_mod_enabled = true;
- if (f_packet.contains("evidence", Qt::CaseInsensitive))
- evidence_enabled = true;
- if (f_packet.contains("cccc_ic_support", Qt::CaseInsensitive))
- cccc_ic_support_enabled = true;
- if (f_packet.contains("arup", Qt::CaseInsensitive))
- arup_enabled = true;
- if (f_packet.contains("casing_alerts", Qt::CaseInsensitive))
- casing_alerts_enabled = true;
- if (f_packet.contains("modcall_reason", Qt::CaseInsensitive))
- modcall_reason_enabled = true;
- if (f_packet.contains("looping_sfx", Qt::CaseInsensitive))
- looping_sfx_support_enabled = true;
-
- w_lobby->enable_connect_button();
- }
- else if (header == "PN") {
- if (f_contents.size() < 2)
- goto end;
-
- w_lobby->set_player_count(f_contents.at(0).toInt(),
- f_contents.at(1).toInt());
- }
- else if (header == "SI") {
- if (f_contents.size() != 3)
- goto end;
-
- char_list_size = f_contents.at(0).toInt();
- evidence_list_size = f_contents.at(1).toInt();
- music_list_size = f_contents.at(2).toInt();
-
- if (char_list_size < 1 || evidence_list_size < 0 || music_list_size < 0)
- goto end;
-
- loaded_chars = 0;
- loaded_evidence = 0;
- loaded_music = 0;
- generated_chars = 0;
-
- destruct_courtroom();
- construct_courtroom();
-
- courtroom_loaded = false;
-
- QString window_title = tr("Attorney Online 2");
- int selected_server = w_lobby->get_selected_server();
-
- QString server_address = "", server_name = "";
- if (w_lobby->public_servers_selected) {
- if (selected_server >= 0 && selected_server < server_list.size()) {
- auto info = server_list.at(selected_server);
- server_name = info.name;
- server_address = QString("%1:%2").arg(info.ip, info.port);
- window_title += ": " + server_name;
- }
- }
- else {
- if (selected_server >= 0 && selected_server < favorite_list.size()) {
- auto info = favorite_list.at(selected_server);
- server_name = info.name;
- server_address = info.ip + info.port;
- window_title += ": " + server_name;
- }
- }
-
- w_courtroom->set_window_title(window_title);
-
- w_lobby->show_loading_overlay();
- w_lobby->set_loading_text(tr("Loading"));
- w_lobby->set_loading_value(0);
-
- AOPacket *f_packet;
-
- if (improved_loading_enabled)
- f_packet = new AOPacket("RC#%");
- else
- f_packet = new AOPacket("askchar2#%");
-
- send_server_packet(f_packet);
-
- QCryptographicHash hash(QCryptographicHash::Algorithm::Sha256);
- hash.addData(server_address.toUtf8());
- if (is_discord_enabled())
- discord->state_server(server_name.toStdString(),
- hash.result().toBase64().toStdString());
- }
- else if (header == "CI") {
- if (!courtroom_constructed)
- goto end;
-
- for (int n_element = 0; n_element < f_contents.size(); n_element += 2) {
- if (f_contents.at(n_element).toInt() != loaded_chars)
- break;
-
- // this means we are on the last element and checking n + 1 element will
- // be game over so
- if (n_element == f_contents.size() - 1)
- break;
-
- QStringList sub_elements = f_contents.at(n_element + 1).split("&");
- if (sub_elements.size() < 2)
- break;
-
- char_type f_char;
- f_char.name = sub_elements.at(0);
- f_char.description = sub_elements.at(1);
- f_char.evidence_string = sub_elements.at(3);
- // temporary. the CharsCheck packet sets this properly
- f_char.taken = false;
-
- ++loaded_chars;
-
- w_lobby->set_loading_text(tr("Loading chars:\n%1/%2")
- .arg(QString::number(loaded_chars))
- .arg(QString::number(char_list_size)));
-
- w_courtroom->append_char(f_char);
-
- int total_loading_size =
- char_list_size * 2 + evidence_list_size + music_list_size;
- int loading_value = int(
- ((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
- static_cast<double>(total_loading_size)) *
- 100);
- w_lobby->set_loading_value(loading_value);
- }
-
- if (improved_loading_enabled)
- send_server_packet(new AOPacket("RE#%"));
- else {
- QString next_packet_number =
- QString::number(((loaded_chars - 1) / 10) + 1);
- send_server_packet(new AOPacket("AN#" + next_packet_number + "#%"));
- }
- }
- else if (header == "EI") {
- if (!courtroom_constructed)
- goto end;
-
- // +1 because evidence starts at 1 rather than 0 for whatever reason
- // enjoy fanta
- if (f_contents.at(0).toInt() != loaded_evidence + 1)
- goto end;
-
- if (f_contents.size() < 2)
- goto end;
-
- QStringList sub_elements = f_contents.at(1).split("&");
- if (sub_elements.size() < 4)
- goto end;
-
- evi_type f_evi;
- f_evi.name = sub_elements.at(0);
- f_evi.description = sub_elements.at(1);
- // no idea what the number at position 2 is. probably an identifier?
- f_evi.image = sub_elements.at(3);
-
- ++loaded_evidence;
-
- w_lobby->set_loading_text(tr("Loading evidence:\n%1/%2")
- .arg(QString::number(loaded_evidence))
- .arg(QString::number(evidence_list_size)));
-
- w_courtroom->append_evidence(f_evi);
-
- int total_loading_size =
- char_list_size * 2 + evidence_list_size + music_list_size;
- int loading_value =
- int(((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
- static_cast<double>(total_loading_size)) *
- 100);
- w_lobby->set_loading_value(loading_value);
-
- QString next_packet_number = QString::number(loaded_evidence);
- send_server_packet(new AOPacket("AE#" + next_packet_number + "#%"));
- }
- else if (header == "EM") {
- if (!courtroom_constructed)
- goto end;
-
- bool musiclist_start = false;
- int areas = 0;
-
- for (int n_element = 0; n_element < f_contents.size(); n_element += 2) {
- if (f_contents.at(n_element).toInt() != loaded_music)
- break;
-
- if (n_element == f_contents.size() - 1)
- break;
-
- QString f_music = f_contents.at(n_element + 1);
-
- ++loaded_music;
-
- w_lobby->set_loading_text(tr("Loading music:\n%1/%2")
- .arg(QString::number(loaded_music))
- .arg(QString::number(music_list_size)));
-
- for (int area_n = 0; area_n < areas; area_n++) {
- w_courtroom->arup_append(0, "Unknown", "Unknown", "Unknown");
- }
-
- int total_loading_size =
- char_list_size * 2 + evidence_list_size + music_list_size;
- int loading_value = int(
- ((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
- static_cast<double>(total_loading_size)) *
- 100);
- w_lobby->set_loading_value(loading_value);
- }
-
- QString next_packet_number = QString::number(((loaded_music - 1) / 10) + 1);
- send_server_packet(new AOPacket("AM#" + next_packet_number + "#%"));
- }
- else if (header == "CharsCheck") {
- if (!courtroom_constructed)
- goto end;
-
- for (int n_char = 0; n_char < f_contents.size(); ++n_char) {
- if (f_contents.at(n_char) == "-1")
- w_courtroom->set_taken(n_char, true);
- else
- w_courtroom->set_taken(n_char, false);
- }
- }
-
- else if (header == "SC") {
- if (!courtroom_constructed)
- goto end;
-
- for (int n_element = 0; n_element < f_contents.size(); ++n_element) {
- QStringList sub_elements = f_contents.at(n_element).split("&");
-
- char_type f_char;
- f_char.name = sub_elements.at(0);
- if (sub_elements.size() >= 2)
- f_char.description = sub_elements.at(1);
-
- // temporary. the CharsCheck packet sets this properly
- f_char.taken = false;
-
- ++loaded_chars;
-
- w_lobby->set_loading_text(tr("Loading chars:\n%1/%2")
- .arg(QString::number(loaded_chars))
- .arg(QString::number(char_list_size)));
-
- w_courtroom->append_char(f_char);
-
- int total_loading_size =
- char_list_size * 2 + evidence_list_size + music_list_size;
- int loading_value = int(
- ((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
- static_cast<double>(total_loading_size)) *
- 100);
- w_lobby->set_loading_value(loading_value);
- }
-
- send_server_packet(new AOPacket("RM#%"));
- }
-
- else if (header == "SM") {
- if (!courtroom_constructed)
- goto end;
-
- bool musics_time = false;
- area_count = 0;
-
- for (int n_element = 0; n_element < f_contents.size(); ++n_element) {
- int element2check = n_element + 1;
- if (element2check > f_contents.size()) {
- element2check = n_element; // I know this is very lazy code but cba
- }
- if (!musics_time && (f_contents.at(n_element).startsWith("==") ||
- f_contents.at(element2check).endsWith(".wav") ||
- f_contents.at(element2check).endsWith(".mp3") ||
- f_contents.at(element2check).endsWith(".mp4") ||
- f_contents.at(element2check).endsWith(".ogg") ||
- f_contents.at(element2check).endsWith(".opus"))) {
- musics_time = true;
- }
-
- // Not everything needs to have a thread.
- AOPacketLoadMusic(this, f_contents.at(n_element), musics_time);
- ++loaded_music;
- int total_loading_size =
- char_list_size * 2 + evidence_list_size + music_list_size;
- int loading_value = int(
- ((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
- static_cast<double>(total_loading_size)) *
- 100);
- w_lobby->set_loading_value(loading_value);
- w_lobby->set_loading_text(tr("Loading music:\n%1/%2")
- .arg(QString::number(loaded_music))
- .arg(QString::number(music_list_size)));
- }
-
- send_server_packet(new AOPacket("RD#%"));
- }
- else if (header == "DONE") {
-
- if (!courtroom_constructed)
- goto end;
-
- if (lobby_constructed)
- w_courtroom->append_ms_chatmessage("", w_lobby->get_chatlog());
-
- w_courtroom->character_loading_finished();
- w_courtroom->done_received();
-
- courtroom_loaded = true;
-
- destruct_lobby();
- }
- else if (header == "REFMUSIC") {
- if (courtroom_constructed)
- w_courtroom->reset_music_list();
- for (int n_element = 0; n_element < f_contents.size(); ++n_element) {
- w_courtroom->append_music(f_contents.at(n_element));
- }
- w_courtroom->list_music();
- }
- else if (header == "BN") {
-
- if (f_contents.size() < 1)
- goto end;
-
- if (courtroom_constructed)
- w_courtroom->set_background(f_contents.at(0));
- }
- // server accepting char request(CC) packet
- else if (header == "PV") {
- if (f_contents.size() < 3)
- goto end;
- if (f_contents.size() < 4) {
- if (courtroom_constructed)
- w_courtroom->enter_courtroom(f_contents.at(2).toInt());
- }
- else {
- if (courtroom_constructed) {
- if (f_contents.at(3) == "True") {
- w_courtroom->set_character(f_contents.at(2).toInt());
- }
- else {
- w_courtroom->enter_courtroom(f_contents.at(2).toInt());
- }
- }
- }
- }
- else if (header == "MS") {
- if (courtroom_constructed && courtroom_loaded)
- w_courtroom->handle_chatmessage(&p_packet->get_contents());
- }
- else if (header == "MC") {
- if (courtroom_constructed && courtroom_loaded)
- w_courtroom->handle_song(&p_packet->get_contents());
- }
- else if (header == "RT") {
- if (f_contents.size() < 1)
- goto end;
- if (courtroom_constructed) {
- if (f_contents.size() == 1)
- w_courtroom->handle_wtce(f_contents.at(0), 0);
- else if (f_contents.size() == 2) {
- w_courtroom->handle_wtce(f_contents.at(0), f_contents.at(1).toInt());
- }
- }
- }
- else if (header == "HP") {
- if (courtroom_constructed && f_contents.size() > 1)
- w_courtroom->set_hp_bar(f_contents.at(0).toInt(),
- f_contents.at(1).toInt());
- }
- else if (header == "LE") {
- if (courtroom_constructed) {
- QVector<evi_type> f_evi_list;
-
- for (QString f_string : f_contents) {
- QStringList sub_contents = f_string.split("&");
-
- if (sub_contents.size() < 3)
- continue;
-
- evi_type f_evi;
- f_evi.name = sub_contents.at(0);
- f_evi.description = sub_contents.at(1);
- f_evi.image = sub_contents.at(2);
-
- f_evi_list.append(f_evi);
- }
-
- w_courtroom->set_evidence_list(f_evi_list);
- }
- }
- else if (header == "ARUP") {
- if (courtroom_constructed) {
- int arup_type = f_contents.at(0).toInt();
- for (int n_element = 1; n_element < f_contents.size(); n_element++) {
- w_courtroom->arup_modify(arup_type, n_element - 1,
- f_contents.at(n_element));
- }
- }
- }
- else if (header == "FAILEDLOGIN") {
- if (courtroom_constructed)
- w_courtroom->handle_failed_login();
- }
- else if (header == "IL") {
- if (courtroom_constructed && f_contents.size() > 0)
- w_courtroom->set_ip_list(f_contents.at(0));
- }
- else if (header == "MU") {
- if (courtroom_constructed && f_contents.size() > 0)
- w_courtroom->set_mute(true, f_contents.at(0).toInt());
- }
- else if (header == "UM") {
- if (courtroom_constructed && f_contents.size() > 0)
- w_courtroom->set_mute(false, f_contents.at(0).toInt());
- }
- else if (header == "KK") {
- if (courtroom_constructed && f_contents.size() >= 1) {
- call_notice(tr("You have been kicked from the server.\nReason: %1")
- .arg(f_contents.at(0)));
- construct_lobby();
- destruct_courtroom();
- }
- }
- else if (header == "KB") {
- if (courtroom_constructed && f_contents.size() >= 1) {
- call_notice(tr("You have been banned from the server.\nReason: %1")
- .arg(f_contents.at(0)));
- construct_lobby();
- destruct_courtroom();
- }
- }
- else if (header == "BD") {
- call_notice(
- tr("You are banned on this server.\nReason: %1").arg(f_contents.at(0)));
- }
- else if (header == "ZZ") {
- if (courtroom_constructed && f_contents.size() > 0)
- w_courtroom->mod_called(f_contents.at(0));
- }
- else if (header == "CASEA") {
- if (courtroom_constructed && f_contents.size() > 7)
- w_courtroom->case_called(f_contents.at(0), f_contents.at(1) == "1",
- f_contents.at(2) == "1", f_contents.at(3) == "1",
- f_contents.at(4) == "1", f_contents.at(5) == "1",
- f_contents.at(6) == "1");
- }
-
-end:
-
- delete p_packet;
-}
-
-void AOApplication::send_ms_packet(AOPacket *p_packet)
-{
- p_packet->net_encode();
-
- QString f_packet = p_packet->to_string();
-
- net_manager->ship_ms_packet(f_packet);
-
-#ifdef DEBUG_NETWORK
- qDebug() << "S(ms):" << f_packet;
-#endif
-
- delete p_packet;
-}
-
-void AOApplication::send_server_packet(AOPacket *p_packet, bool encoded)
-{
- if (encoded)
- p_packet->net_encode();
-
- QString f_packet = p_packet->to_string();
-
- if (encryption_needed) {
-#ifdef DEBUG_NETWORK
- qDebug() << "S(e):" << f_packet;
-#endif
-
- p_packet->encrypt_header(s_decryptor);
- f_packet = p_packet->to_string();
- }
- else {
- qDebug() << "S:" << f_packet;
-#ifdef DEBUG_NETWORK
- qDebug() << "S:" << f_packet;
-#endif
- }
-
- net_manager->ship_server_packet(f_packet);
-
- delete p_packet;
-}
+#include "aoapplication.h"
+
+#include "courtroom.h"
+#include "debug_functions.h"
+#include "encryption_functions.h"
+#include "hardware_functions.h"
+#include "lobby.h"
+#include "networkmanager.h"
+
+void AOApplication::ms_packet_received(AOPacket *p_packet)
+{
+ p_packet->net_decode();
+
+ QString header = p_packet->get_header();
+ QStringList f_contents = p_packet->get_contents();
+
+#ifdef DEBUG_NETWORK
+ if (header != "CHECK")
+ qDebug() << "R(ms):" << p_packet->to_string();
+#endif
+
+ if (header == "ALL") {
+ server_list.clear();
+
+ for (QString i_string : p_packet->get_contents()) {
+ server_type f_server;
+ QStringList sub_contents = i_string.split("&");
+
+ if (sub_contents.size() < 4) {
+ qDebug() << "W: malformed packet";
+ continue;
+ }
+
+ f_server.name = sub_contents.at(0);
+ f_server.desc = sub_contents.at(1);
+ f_server.ip = sub_contents.at(2);
+ f_server.port = sub_contents.at(3).toInt();
+
+ server_list.append(f_server);
+ }
+
+ if (lobby_constructed) {
+ w_lobby->list_servers();
+ }
+ }
+ else if (header == "CT") {
+ QString f_name, f_message;
+
+ if (f_contents.size() == 1) {
+ f_name = "";
+ f_message = f_contents.at(0);
+ }
+ else if (f_contents.size() >= 2) {
+ f_name = f_contents.at(0);
+ f_message = f_contents.at(1);
+ }
+ else
+ goto end;
+
+ if (lobby_constructed) {
+ w_lobby->append_chatmessage(f_name, f_message);
+ }
+ if (courtroom_constructed && courtroom_loaded) {
+ w_courtroom->append_ms_chatmessage(f_name, f_message);
+ }
+ }
+ else if (header == "AO2CHECK") {
+ send_ms_packet(new AOPacket("ID#AO2#" + get_version_string() + "#%"));
+ send_ms_packet(new AOPacket("HI#" + get_hdid() + "#%"));
+
+ if (f_contents.size() < 1)
+ goto end;
+
+ QStringList version_contents = f_contents.at(0).split(".");
+
+ if (version_contents.size() < 3)
+ goto end;
+
+ int f_release = version_contents.at(0).toInt();
+ int f_major = version_contents.at(1).toInt();
+ int f_minor = version_contents.at(2).toInt();
+
+ if (get_release() > f_release)
+ goto end;
+ else if (get_release() == f_release) {
+ if (get_major_version() > f_major)
+ goto end;
+ else if (get_major_version() == f_major) {
+ if (get_minor_version() >= f_minor)
+ goto end;
+ }
+ }
+
+ call_notice(tr("Outdated version! Your version: %1\n"
+ "Please go to aceattorneyonline.com to update.")
+ .arg(get_version_string()));
+ destruct_courtroom();
+ destruct_lobby();
+ }
+
+end:
+
+ delete p_packet;
+}
+
+void AOApplication::server_packet_received(AOPacket *p_packet)
+{
+ p_packet->net_decode();
+
+ QString header = p_packet->get_header();
+ QStringList f_contents = p_packet->get_contents();
+ QString f_packet = p_packet->to_string();
+
+#ifdef DEBUG_NETWORK
+ if (header != "checkconnection")
+ qDebug() << "R:" << f_packet;
+#endif
+
+ if (header == "decryptor") {
+ if (f_contents.size() == 0)
+ goto end;
+
+ // you may ask where 322 comes from. that would be a good question.
+ s_decryptor = fanta_decrypt(f_contents.at(0), 322).toUInt();
+
+ // default(legacy) values
+ encryption_needed = true;
+ yellow_text_enabled = false;
+ prezoom_enabled = false;
+ flipping_enabled = false;
+ custom_objection_enabled = false;
+ improved_loading_enabled = false;
+ desk_mod_enabled = false;
+ evidence_enabled = false;
+ cccc_ic_support_enabled = false;
+ arup_enabled = false;
+ casing_alerts_enabled = false;
+ modcall_reason_enabled = false;
+ looping_sfx_support_enabled = false;
+ additive_enabled = false;
+ effects_enabled = false;
+
+ // workaround for tsuserver4
+ if (f_contents.at(0) == "NOENCRYPT")
+ encryption_needed = false;
+
+ QString f_hdid;
+ f_hdid = get_hdid();
+
+ AOPacket *hi_packet = new AOPacket("HI#" + f_hdid + "#%");
+ send_server_packet(hi_packet);
+ }
+ else if (header == "ID") {
+ if (f_contents.size() < 2)
+ goto end;
+
+ s_pv = f_contents.at(0).toInt();
+ server_software = f_contents.at(1);
+
+ if (lobby_constructed)
+ w_lobby->enable_connect_button();
+
+ send_server_packet(new AOPacket("ID#AO2#" + get_version_string() + "#%"));
+ }
+ else if (header == "CT") {
+ if (f_contents.size() < 2)
+ goto end;
+
+ if (courtroom_constructed) {
+ if (f_contents.size() == 3)
+ w_courtroom->append_server_chatmessage(
+ f_contents.at(0), f_contents.at(1), f_contents.at(2));
+ else
+ w_courtroom->append_server_chatmessage(f_contents.at(0),
+ f_contents.at(1), "0");
+ }
+ }
+ else if (header == "FL") {
+// encryption_needed = true;
+ yellow_text_enabled = false;
+ prezoom_enabled = false;
+ flipping_enabled = false;
+ custom_objection_enabled = false;
+ improved_loading_enabled = false;
+ desk_mod_enabled = false;
+ evidence_enabled = false;
+ cccc_ic_support_enabled = false;
+ arup_enabled = false;
+ casing_alerts_enabled = false;
+ modcall_reason_enabled = false;
+ looping_sfx_support_enabled = false;
+ additive_enabled = false;
+ effects_enabled = false;
+ if (f_packet.contains("yellowtext", Qt::CaseInsensitive))
+ yellow_text_enabled = true;
+ if (f_packet.contains("prezoom", Qt::CaseInsensitive))
+ prezoom_enabled = true;
+ if (f_packet.contains("flipping", Qt::CaseInsensitive))
+ flipping_enabled = true;
+ if (f_packet.contains("customobjections", Qt::CaseInsensitive))
+ custom_objection_enabled = true;
+ if (f_packet.contains("fastloading", Qt::CaseInsensitive))
+ improved_loading_enabled = true;
+ if (f_packet.contains("noencryption", Qt::CaseInsensitive))
+ encryption_needed = false;
+ if (f_packet.contains("deskmod", Qt::CaseInsensitive))
+ desk_mod_enabled = true;
+ if (f_packet.contains("evidence", Qt::CaseInsensitive))
+ evidence_enabled = true;
+ if (f_packet.contains("cccc_ic_support", Qt::CaseInsensitive))
+ cccc_ic_support_enabled = true;
+ if (f_packet.contains("arup", Qt::CaseInsensitive))
+ arup_enabled = true;
+ if (f_packet.contains("casing_alerts", Qt::CaseInsensitive))
+ casing_alerts_enabled = true;
+ if (f_packet.contains("modcall_reason", Qt::CaseInsensitive))
+ modcall_reason_enabled = true;
+ if (f_packet.contains("looping_sfx", Qt::CaseInsensitive))
+ looping_sfx_support_enabled = true;
+ if (f_packet.contains("additive", Qt::CaseInsensitive))
+ additive_enabled = true;
+ if (f_packet.contains("effects", Qt::CaseInsensitive))
+ effects_enabled = true;
+ }
+ else if (header == "PN") {
+ if (f_contents.size() < 2)
+ goto end;
+
+ w_lobby->set_player_count(f_contents.at(0).toInt(),
+ f_contents.at(1).toInt());
+ }
+ else if (header == "SI") {
+ if (f_contents.size() != 3)
+ goto end;
+
+ char_list_size = f_contents.at(0).toInt();
+ evidence_list_size = f_contents.at(1).toInt();
+ music_list_size = f_contents.at(2).toInt();
+
+ if (char_list_size < 1 || evidence_list_size < 0 || music_list_size < 0)
+ goto end;
+
+ loaded_chars = 0;
+ loaded_evidence = 0;
+ loaded_music = 0;
+ generated_chars = 0;
+
+ destruct_courtroom();
+ construct_courtroom();
+
+ courtroom_loaded = false;
+
+ QString window_title = tr("Attorney Online 2");
+ int selected_server = w_lobby->get_selected_server();
+
+ QString server_address = "", server_name = "";
+ if (w_lobby->public_servers_selected) {
+ if (selected_server >= 0 && selected_server < server_list.size()) {
+ auto info = server_list.at(selected_server);
+ server_name = info.name;
+ server_address =
+ QString("%1:%2").arg(info.ip, QString::number(info.port));
+ qDebug() << server_address;
+ window_title += ": " + server_name;
+ }
+ }
+ else {
+ if (selected_server >= 0 && selected_server < favorite_list.size()) {
+ auto info = favorite_list.at(selected_server);
+ server_name = info.name;
+ server_address =
+ QString("%1:%2").arg(info.ip, QString::number(info.port));
+ qDebug() << server_address;
+ window_title += ": " + server_name;
+ }
+ }
+
+ w_courtroom->set_window_title(window_title);
+
+ w_lobby->show_loading_overlay();
+ w_lobby->set_loading_text(tr("Loading"));
+ w_lobby->set_loading_value(0);
+
+ AOPacket *f_packet;
+
+ if (improved_loading_enabled)
+ f_packet = new AOPacket("RC#%");
+ else
+ f_packet = new AOPacket("askchar2#%");
+
+ send_server_packet(f_packet);
+
+ // Remove any characters not accepted in folder names for the server_name
+ // here
+ if (AOApplication::get_auto_logging_enabled()){
+ this->log_filename = QDateTime::currentDateTime().toUTC().toString(
+ "'logs/" + server_name.remove(QRegExp("[\\\\/:*?\"<>|\']")) +
+ "/'ddd MMMM yyyy hh.mm.ss t'.log'");
+ this->write_to_file("Joined server " + server_name + " on address " +
+ server_address + " on " +
+ QDateTime::currentDateTime().toUTC().toString(),
+ log_filename, true);
+ }
+
+ QCryptographicHash hash(QCryptographicHash::Algorithm::Sha256);
+ hash.addData(server_address.toUtf8());
+ if (is_discord_enabled())
+ discord->state_server(server_name.toStdString(),
+ hash.result().toBase64().toStdString());
+ }
+ else if (header == "CI") {
+ if (!courtroom_constructed)
+ goto end;
+
+ for (int n_element = 0; n_element < f_contents.size(); n_element += 2) {
+ if (f_contents.at(n_element).toInt() != loaded_chars)
+ break;
+
+ // this means we are on the last element and checking n + 1 element will
+ // be game over so
+ if (n_element == f_contents.size() - 1)
+ break;
+
+ QStringList sub_elements = f_contents.at(n_element + 1).split("&");
+ if (sub_elements.size() < 2)
+ break;
+
+ char_type f_char;
+ f_char.name = sub_elements.at(0);
+ f_char.description = sub_elements.at(1);
+ f_char.evidence_string = sub_elements.at(3);
+ // temporary. the CharsCheck packet sets this properly
+ f_char.taken = false;
+
+ ++loaded_chars;
+
+ w_lobby->set_loading_text(tr("Loading chars:\n%1/%2")
+ .arg(QString::number(loaded_chars))
+ .arg(QString::number(char_list_size)));
+
+ w_courtroom->append_char(f_char);
+
+ int total_loading_size =
+ char_list_size * 2 + evidence_list_size + music_list_size;
+ int loading_value = int(
+ ((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
+ static_cast<double>(total_loading_size)) *
+ 100);
+ w_lobby->set_loading_value(loading_value);
+ }
+
+ if (improved_loading_enabled)
+ send_server_packet(new AOPacket("RE#%"));
+ else {
+ QString next_packet_number =
+ QString::number(((loaded_chars - 1) / 10) + 1);
+ send_server_packet(new AOPacket("AN#" + next_packet_number + "#%"));
+ }
+ }
+ else if (header == "EI") {
+ if (!courtroom_constructed)
+ goto end;
+
+ // +1 because evidence starts at 1 rather than 0 for whatever reason
+ // enjoy fanta
+ if (f_contents.at(0).toInt() != loaded_evidence + 1)
+ goto end;
+
+ if (f_contents.size() < 2)
+ goto end;
+
+ QStringList sub_elements = f_contents.at(1).split("&");
+ if (sub_elements.size() < 4)
+ goto end;
+
+ evi_type f_evi;
+ f_evi.name = sub_elements.at(0);
+ f_evi.description = sub_elements.at(1);
+ // no idea what the number at position 2 is. probably an identifier?
+ f_evi.image = sub_elements.at(3);
+
+ ++loaded_evidence;
+
+ w_lobby->set_loading_text(tr("Loading evidence:\n%1/%2")
+ .arg(QString::number(loaded_evidence))
+ .arg(QString::number(evidence_list_size)));
+
+ w_courtroom->append_evidence(f_evi);
+
+ int total_loading_size =
+ char_list_size * 2 + evidence_list_size + music_list_size;
+ int loading_value =
+ int(((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
+ static_cast<double>(total_loading_size)) *
+ 100);
+ w_lobby->set_loading_value(loading_value);
+
+ QString next_packet_number = QString::number(loaded_evidence);
+ send_server_packet(new AOPacket("AE#" + next_packet_number + "#%"));
+ }
+ else if (header == "EM") {
+ if (!courtroom_constructed)
+ goto end;
+
+ bool musics_time = false;
+ int areas = 0;
+
+ for (int n_element = 0; n_element < f_contents.size(); n_element += 2) {
+ if (f_contents.at(n_element).toInt() != loaded_music)
+ break;
+
+ if (n_element == f_contents.size() - 1)
+ break;
+
+ QString f_music = f_contents.at(n_element + 1);
+
+ ++loaded_music;
+
+ w_lobby->set_loading_text(tr("Loading music:\n%1/%2")
+ .arg(QString::number(loaded_music))
+ .arg(QString::number(music_list_size)));
+
+ if (musics_time) {
+ w_courtroom->append_music(f_music);
+ }
+ else {
+ if (f_music.endsWith(".wav") || f_music.endsWith(".mp3") ||
+ f_music.endsWith(".mp4") || f_music.endsWith(".ogg") ||
+ f_music.endsWith(".opus")) {
+ musics_time = true;
+ areas--;
+ w_courtroom->fix_last_area();
+ w_courtroom->append_music(f_music);
+ }
+ else {
+ w_courtroom->append_area(f_music);
+ areas++;
+ }
+ }
+
+ for (int area_n = 0; area_n < areas; area_n++) {
+ w_courtroom->arup_append(0, "Unknown", "Unknown", "Unknown");
+ }
+
+ int total_loading_size =
+ char_list_size * 2 + evidence_list_size + music_list_size;
+ int loading_value = int(
+ ((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
+ static_cast<double>(total_loading_size)) *
+ 100);
+ w_lobby->set_loading_value(loading_value);
+ }
+
+ QString next_packet_number = QString::number(((loaded_music - 1) / 10) + 1);
+ send_server_packet(new AOPacket("AM#" + next_packet_number + "#%"));
+ }
+ else if (header == "CharsCheck") {
+ if (!courtroom_constructed)
+ goto end;
+
+ for (int n_char = 0; n_char < f_contents.size(); ++n_char) {
+ if (f_contents.at(n_char) == "-1")
+ w_courtroom->set_taken(n_char, true);
+ else
+ w_courtroom->set_taken(n_char, false);
+ }
+ }
+
+ else if (header == "SC") {
+ if (!courtroom_constructed)
+ goto end;
+
+ for (int n_element = 0; n_element < f_contents.size(); ++n_element) {
+ QStringList sub_elements = f_contents.at(n_element).split("&");
+
+ char_type f_char;
+ f_char.name = sub_elements.at(0);
+ if (sub_elements.size() >= 2)
+ f_char.description = sub_elements.at(1);
+
+ // temporary. the CharsCheck packet sets this properly
+ f_char.taken = false;
+
+ ++loaded_chars;
+
+ w_lobby->set_loading_text(tr("Loading chars:\n%1/%2")
+ .arg(QString::number(loaded_chars))
+ .arg(QString::number(char_list_size)));
+
+ w_courtroom->append_char(f_char);
+
+ int total_loading_size =
+ char_list_size * 2 + evidence_list_size + music_list_size;
+ int loading_value = int(
+ ((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
+ static_cast<double>(total_loading_size)) *
+ 100);
+ w_lobby->set_loading_value(loading_value);
+ }
+
+ send_server_packet(new AOPacket("RM#%"));
+ }
+ else if (header == "SM") {
+ if (!courtroom_constructed)
+ goto end;
+
+ bool musics_time = false;
+ int areas = 0;
+
+ for (int n_element = 0; n_element < f_contents.size(); ++n_element) {
+ ++loaded_music;
+
+ w_lobby->set_loading_text(tr("Loading music:\n%1/%2")
+ .arg(QString::number(loaded_music))
+ .arg(QString::number(music_list_size)));
+
+ if (musics_time) {
+ w_courtroom->append_music(f_contents.at(n_element));
+ }
+ else {
+ if (f_contents.at(n_element).endsWith(".wav") ||
+ f_contents.at(n_element).endsWith(".mp3") ||
+ f_contents.at(n_element).endsWith(".mp4") ||
+ f_contents.at(n_element).endsWith(".ogg") ||
+ f_contents.at(n_element).endsWith(".opus")) {
+ musics_time = true;
+ w_courtroom->fix_last_area();
+ w_courtroom->append_music(f_contents.at(n_element));
+ areas--;
+ }
+ else {
+ w_courtroom->append_area(f_contents.at(n_element));
+ areas++;
+ }
+ }
+
+ for (int area_n = 0; area_n < areas; area_n++) {
+ w_courtroom->arup_append(0, "Unknown", "Unknown", "Unknown");
+ }
+
+ int total_loading_size =
+ char_list_size * 2 + evidence_list_size + music_list_size;
+ int loading_value = int(
+ ((loaded_chars + generated_chars + loaded_music + loaded_evidence) /
+ static_cast<double>(total_loading_size)) *
+ 100);
+ w_lobby->set_loading_value(loading_value);
+ }
+
+ send_server_packet(new AOPacket("RD#%"));
+ }
+ else if (header == "FM") // Fetch music ONLY
+ {
+ if (!courtroom_constructed)
+ goto end;
+
+ w_courtroom->clear_music();
+
+ for (int n_element = 0; n_element < f_contents.size(); ++n_element) {
+ w_courtroom->append_music(f_contents.at(n_element));
+ }
+
+ w_courtroom->list_music();
+ }
+ else if (header == "FA") // Fetch areas ONLY
+ {
+ if (!courtroom_constructed)
+ goto end;
+
+ w_courtroom->clear_areas();
+
+ for (int n_element = 0; n_element < f_contents.size(); ++n_element) {
+ w_courtroom->append_area(f_contents.at(n_element));
+ }
+
+ w_courtroom->list_areas();
+ }
+ else if (header == "DONE") {
+ if (!courtroom_constructed)
+ goto end;
+
+ if (lobby_constructed)
+ w_courtroom->append_ms_chatmessage("", w_lobby->get_chatlog());
+
+ w_courtroom->character_loading_finished();
+ w_courtroom->done_received();
+
+ courtroom_loaded = true;
+
+ destruct_lobby();
+ }
+ else if (header == "BN") {
+ if (f_contents.size() < 1)
+ goto end;
+
+ if (courtroom_constructed) {
+ if (f_contents.size() >=
+ 2) // We have a pos included in the background packet!
+ w_courtroom->set_side(f_contents.at(1));
+ w_courtroom->set_background(f_contents.at(0), f_contents.size() >= 2);
+ }
+ }
+ else if (header == "SP") {
+ if (f_contents.size() < 1)
+ goto end;
+
+ if (courtroom_constructed) // We were sent a "set position" packet
+ {
+ w_courtroom->set_side(f_contents.at(0));
+ }
+ }
+ else if (header == "SD") // Send pos dropdown
+ {
+ if (f_contents.size() < 1)
+ goto end;
+
+ w_courtroom->set_pos_dropdown(f_contents.at(0).split("*"));
+ }
+ // server accepting char request(CC) packet
+ else if (header == "PV") {
+ if (f_contents.size() < 3)
+ goto end;
+
+ if (courtroom_constructed)
+ w_courtroom->update_character(f_contents.at(2).toInt());
+ }
+ else if (header == "MS") {
+ if (courtroom_constructed && courtroom_loaded)
+ w_courtroom->handle_chatmessage(&p_packet->get_contents());
+ }
+ else if (header == "MC") {
+ if (courtroom_constructed && courtroom_loaded)
+ w_courtroom->handle_song(&p_packet->get_contents());
+ }
+ else if (header == "RT") {
+ if (f_contents.size() < 1)
+ goto end;
+ if (courtroom_constructed) {
+ if (f_contents.size() == 1)
+ w_courtroom->handle_wtce(f_contents.at(0), 0);
+ else if (f_contents.size() == 2) {
+ w_courtroom->handle_wtce(f_contents.at(0), f_contents.at(1).toInt());
+ }
+ }
+ }
+ else if (header == "HP") {
+ if (courtroom_constructed && f_contents.size() > 1)
+ w_courtroom->set_hp_bar(f_contents.at(0).toInt(),
+ f_contents.at(1).toInt());
+ }
+ else if (header == "LE") {
+ if (courtroom_constructed) {
+ QVector<evi_type> f_evi_list;
+
+ for (QString f_string : f_contents) {
+ QStringList sub_contents = f_string.split("&");
+
+ if (sub_contents.size() < 3)
+ continue;
+
+ evi_type f_evi;
+ f_evi.name = sub_contents.at(0);
+ f_evi.description = sub_contents.at(1);
+ f_evi.image = sub_contents.at(2);
+
+ f_evi_list.append(f_evi);
+ }
+
+ w_courtroom->set_evidence_list(f_evi_list);
+ }
+ }
+ else if (header == "ARUP") {
+ if (courtroom_constructed) {
+ int arup_type = f_contents.at(0).toInt();
+ for (int n_element = 1; n_element < f_contents.size(); n_element++) {
+ w_courtroom->arup_modify(arup_type, n_element - 1,
+ f_contents.at(n_element));
+ }
+ }
+ }
+ else if (header == "IL") {
+ if (courtroom_constructed && f_contents.size() > 0)
+ w_courtroom->set_ip_list(f_contents.at(0));
+ }
+ else if (header == "MU") {
+ if (courtroom_constructed && f_contents.size() > 0)
+ w_courtroom->set_mute(true, f_contents.at(0).toInt());
+ }
+ else if (header == "UM") {
+ if (courtroom_constructed && f_contents.size() > 0)
+ w_courtroom->set_mute(false, f_contents.at(0).toInt());
+ }
+ else if (header == "KK") {
+ if (courtroom_constructed && f_contents.size() >= 1) {
+ call_notice(tr("You have been kicked from the server.\nReason: %1")
+ .arg(f_contents.at(0)));
+ construct_lobby();
+ destruct_courtroom();
+ }
+ }
+ else if (header == "KB") {
+ if (courtroom_constructed && f_contents.size() >= 1) {
+ call_notice(tr("You have been banned from the server.\nReason: %1")
+ .arg(f_contents.at(0)));
+ construct_lobby();
+ destruct_courtroom();
+ }
+ }
+ else if (header == "BD") {
+ call_notice(
+ tr("You are banned on this server.\nReason: %1").arg(f_contents.at(0)));
+ }
+ else if (header == "ZZ") {
+ if (courtroom_constructed && f_contents.size() > 0)
+ w_courtroom->mod_called(f_contents.at(0));
+ }
+ else if (header == "CASEA") {
+ if (courtroom_constructed && f_contents.size() > 6)
+ w_courtroom->case_called(f_contents.at(0), f_contents.at(1) == "1",
+ f_contents.at(2) == "1", f_contents.at(3) == "1",
+ f_contents.at(4) == "1",
+ f_contents.at(5) == "1");
+ }
+
+end:
+
+ delete p_packet;
+}
+
+void AOApplication::send_ms_packet(AOPacket *p_packet)
+{
+ p_packet->net_encode();
+
+ QString f_packet = p_packet->to_string();
+
+ net_manager->ship_ms_packet(f_packet);
+
+#ifdef DEBUG_NETWORK
+ qDebug() << "S(ms):" << f_packet;
+#endif
+
+ delete p_packet;
+}
+
+void AOApplication::send_server_packet(AOPacket *p_packet, bool encoded)
+{
+ if (encoded)
+ p_packet->net_encode();
+
+ QString f_packet = p_packet->to_string();
+
+ if (encryption_needed) {
+#ifdef DEBUG_NETWORK
+ qDebug() << "S(e):" << f_packet;
+#endif
+
+ p_packet->encrypt_header(s_decryptor);
+ f_packet = p_packet->to_string();
+ }
+ else {
+#ifdef DEBUG_NETWORK
+ qDebug() << "S:" << f_packet;
+#endif
+ }
+
+ net_manager->ship_server_packet(f_packet);
+
+ delete p_packet;
+}
diff --git a/src/path_functions.cpp b/src/path_functions.cpp
index 358f146b..10c8ae53 100644
--- a/src/path_functions.cpp
+++ b/src/path_functions.cpp
@@ -30,7 +30,7 @@ QString AOApplication::get_base_path()
QString external_storage = getenv("EXTERNAL_STORAGE");
base_path = external_storage + "/AO2/";
}
-#elif defined __APPLE__
+#elif defined(__APPLE__)
base_path = applicationDirPath() + "/../../../base/";
#else
base_path = applicationDirPath() + "/base/";
@@ -93,39 +93,11 @@ QString AOApplication::get_sounds_path(QString p_file)
QString AOApplication::get_music_path(QString p_song)
{
- QString withending_check = get_base_path() + "sounds/music/" + p_song;
- QString mp3_check = get_base_path() + "sounds/music/" + p_song + ".mp3";
- QString opus_check = get_base_path() + "sounds/music/" + p_song + ".opus";
- if (p_song.startsWith("http")) {
- //it's an URL
- return p_song;
- }
- else if (file_exists(opus_check)) {
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return opus_check;
-#else
- return get_case_sensitive_path(opus_check);
-#endif
- }
- else if (file_exists(mp3_check)) {
+ QString path = get_base_path() + "sounds/music/" + p_song;
#ifndef CASE_SENSITIVE_FILESYSTEM
- return mp3_check;
-#else
- return get_case_sensitive_path(mp3_check);
-#endif
- }
- else if (file_exists(withending_check)) {
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return withending_check;
-#else
- return get_case_sensitive_path(withending_check);
-#endif
- }
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return get_base_path() + "sounds/music/" + p_song + ".wav";
+ return path;
#else
- return get_case_sensitive_path(get_base_path() + "sounds/music/" + p_song +
- ".wav");
+ return get_case_sensitive_path(path);
#endif
}
diff --git a/src/scrolltext.cpp b/src/scrolltext.cpp
new file mode 100644
index 00000000..d5da6ce5
--- /dev/null
+++ b/src/scrolltext.cpp
@@ -0,0 +1,135 @@
+#include "scrolltext.h"
+
+ScrollText::ScrollText(QWidget *parent) : QWidget(parent), scrollPos(0)
+{
+ staticText.setTextFormat(Qt::PlainText);
+
+ // setFixedHeight(fontMetrics().height()*2); //The theme sets this
+ leftMargin = height() / 3;
+
+ setSeparator(" --- ");
+
+ connect(&timer, SIGNAL(timeout()), this, SLOT(timer_timeout()));
+ timer.setInterval(50);
+}
+
+QString ScrollText::text() const { return _text; }
+
+void ScrollText::setText(QString text)
+{
+ _text = text;
+ updateText();
+ update();
+}
+
+QString ScrollText::separator() const { return _separator; }
+
+void ScrollText::setSeparator(QString separator)
+{
+ _separator = separator;
+ updateText();
+ update();
+}
+
+void ScrollText::updateText()
+{
+ timer.stop();
+#if QT_VERSION > QT_VERSION_CHECK(5, 11, 0)
+ singleTextWidth = fontMetrics().horizontalAdvance(_text);
+#else
+ singleTextWidth = fontMetrics().boundingRect(_text).width();
+#endif
+
+ scrollEnabled = (singleTextWidth > width() - leftMargin * 2);
+
+ if (scrollEnabled) {
+ scrollPos = -64;
+ staticText.setText(_text + _separator);
+ timer.start();
+ }
+ else
+ staticText.setText(_text);
+
+ staticText.prepare(QTransform(), font());
+#if QT_VERSION > QT_VERSION_CHECK(5, 11, 0)
+ wholeTextSize = QSize(fontMetrics().horizontalAdvance(staticText.text()),
+ fontMetrics().height());
+#else
+ wholeTextSize = QSize(fontMetrics().boundingRect(staticText.text()).width(),
+ fontMetrics().height());
+#endif
+
+}
+
+void ScrollText::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+
+ if (scrollEnabled) {
+ buffer.fill(qRgba(0, 0, 0, 0));
+ QPainter pb(&buffer);
+ pb.setPen(p.pen());
+ pb.setFont(p.font());
+
+ int x = qMin(-scrollPos, 0) + leftMargin;
+ while (x < width()) {
+ pb.drawStaticText(QPointF(x, (height() - wholeTextSize.height()) / 2),
+ staticText);
+ x += wholeTextSize.width();
+ }
+
+ // Apply Alpha Channel
+ pb.setCompositionMode(QPainter::CompositionMode_DestinationIn);
+ pb.setClipRect(width() - 15, 0, 15, height());
+ pb.drawImage(0, 0, alphaChannel);
+ pb.setClipRect(0, 0, 15, height());
+ // initial situation: don't apply alpha channel in the left half of the
+ // image at all; apply it more and more until scrollPos gets positive
+ if (scrollPos < 0)
+ pb.setOpacity(static_cast<qreal>((qMax(-8, scrollPos) + 8) / 8.0));
+ pb.drawImage(0, 0, alphaChannel);
+
+ // pb.end();
+ p.drawImage(0, 0, buffer);
+ }
+ else {
+ p.drawStaticText(
+ QPointF(leftMargin, (height() - wholeTextSize.height()) / 2),
+ staticText);
+ }
+}
+
+void ScrollText::resizeEvent(QResizeEvent *)
+{
+ // When the widget is resized, we need to update the alpha channel.
+
+ alphaChannel = QImage(size(), QImage::Format_ARGB32_Premultiplied);
+ buffer = QImage(size(), QImage::Format_ARGB32_Premultiplied);
+
+ // Create Alpha Channel:
+ if (width() > 64) {
+ // create first scanline
+ QRgb *scanline1 = reinterpret_cast<QRgb *>(alphaChannel.scanLine(0));
+ for (int x = 1; x < 16; ++x)
+ scanline1[x - 1] = scanline1[width() - x] = qRgba(0, 0, 0, x << 4);
+ for (int x = 15; x < width() - 15; ++x)
+ scanline1[x] = qRgb(0, 0, 0);
+ // copy scanline to the other ones
+ for (int y = 1; y < height(); ++y)
+ memcpy(alphaChannel.scanLine(y), scanline1,
+ static_cast<uint>(width() * 4));
+ }
+ else
+ alphaChannel.fill(qRgb(0, 0, 0));
+
+ // Update scrolling state
+ bool newScrollEnabled = (singleTextWidth > width() - leftMargin);
+ if (newScrollEnabled != scrollEnabled)
+ updateText();
+}
+
+void ScrollText::timer_timeout()
+{
+ scrollPos = (scrollPos + 2) % wholeTextSize.width();
+ update();
+}
diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp
index 779765d7..39754f39 100644
--- a/src/text_file_functions.cpp
+++ b/src/text_file_functions.cpp
@@ -1,833 +1,1057 @@
-#include "text_file_functions.h"
-
-QString AOApplication::read_theme()
-{
- QString result = configini->value("theme", "default").value<QString>();
- return result;
-}
-
-int AOApplication::read_blip_rate()
-{
- int result = configini->value("blip_rate", 2).toInt();
-
- if (result < 1)
- return 1;
-
- return result;
-}
-
-QString AOApplication::get_ooc_name()
-{
- QString result = configini->value("ooc_name").value<QString>();
- return result;
-}
-
-int AOApplication::get_default_music()
-{
- int result = configini->value("default_music", 50).toInt();
- return result;
-}
-
-int AOApplication::get_default_sfx()
-{
- int result = configini->value("default_sfx", 50).toInt();
- return result;
-}
-
-int AOApplication::get_default_blip()
-{
- int result = configini->value("default_blip", 50).toInt();
- return result;
-}
-
-int AOApplication::get_max_log_size()
-{
- int result = configini->value("log_maximum", 200).toInt();
- return result;
-}
-
-bool AOApplication::get_slower_blips()
-{
- QString result =
- configini->value("slower_blips", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_pundelay()
-{
- QString result =
- configini->value("punctuation_delay", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_log_goes_downwards()
-{
- QString result =
- configini->value("log_goes_downwards", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_showname_enabled_by_default()
-{
- QString result =
- configini->value("show_custom_shownames", "true").value<QString>();
- return result.startsWith("true");
-}
-
-QString AOApplication::get_default_username()
-{
- QString result = configini->value("default_username", "").value<QString>();
- if (result.isEmpty())
- return get_ooc_name();
- else
- return result;
-}
-
-QString AOApplication::get_audio_output_device()
-{
- QString result =
- configini->value("default_audio_device", "default").value<QString>();
- return result;
-}
-
-QStringList AOApplication::get_call_words()
-{
- QStringList return_value;
-
- QFile callwords_ini;
-
- callwords_ini.setFileName(get_base_path() + "callwords.ini");
-
- if (!callwords_ini.open(QIODevice::ReadOnly))
- return return_value;
-
- QTextStream in(&callwords_ini);
-
- while (!in.atEnd()) {
- QString line = in.readLine();
- return_value.append(line);
- }
-
- return return_value;
-}
-
-void AOApplication::write_to_serverlist_txt(QString p_line)
-{
- QFile serverlist_txt;
- QString serverlist_txt_path = get_base_path() + "serverlist.txt";
-
- serverlist_txt.setFileName(serverlist_txt_path);
-
- if (!serverlist_txt.open(QIODevice::WriteOnly | QIODevice::Append)) {
- return;
- }
-
- QTextStream out(&serverlist_txt);
-
- out << "\r\n" << p_line;
-
- serverlist_txt.close();
-}
-
-QVector<server_type> AOApplication::read_serverlist_txt()
-{
- QVector<server_type> f_server_list;
-
- QFile serverlist_txt;
- QString serverlist_txt_path = get_base_path() + "serverlist.txt";
-
- serverlist_txt.setFileName(serverlist_txt_path);
-
- if (!serverlist_txt.open(QIODevice::ReadOnly)) {
- return f_server_list;
- }
-
- QTextStream in(&serverlist_txt);
-
- while (!in.atEnd()) {
- QString line = in.readLine();
- server_type f_server;
- QStringList line_contents = line.split(":");
-
- if (line_contents.size() < 3)
- continue;
-
- f_server.ip = line_contents.at(0);
- f_server.port = line_contents.at(1).toInt();
- f_server.name = line_contents.at(2);
- f_server.desc = "";
-
- f_server_list.append(f_server);
- }
-
- return f_server_list;
-}
-
-QString AOApplication::read_design_ini(QString p_identifier,
- QString p_design_path)
-{
- QSettings settings(p_design_path, QSettings::IniFormat);
- QVariant value = settings.value(p_identifier);
- if (value.isNull()) // Since the value wasn't found, maybe it uses the proper
- // config system
- {
- int last_underscore_index = p_identifier.lastIndexOf(
- '_'); // we will use this in order to check wether it is just showname
- // or showname_something
- if (last_underscore_index != -1) {
- p_identifier.replace(
- last_underscore_index, 1,
- '/'); // we replace the last dash in order to access the category, e.g
- // from showname_font -> showname/font
- value = settings.value(p_identifier);
- }
- else if (!settings.value(p_identifier + "/size")
- .isNull()) // This is to check whether showname/size exists,
- // because size is defined as widgetname = x
- {
- value = settings.value(p_identifier + "/size");
- }
- }
- if (value.type() == QVariant::StringList) {
- return value.toStringList().join(",");
- }
- else {
- return value.toString();
- }
-}
-
-QPoint AOApplication::get_button_spacing(QString p_identifier, QString p_file)
-{
- QString design_ini_path = get_theme_path(p_file);
- QString default_path = get_default_theme_path(p_file);
- QString f_result = read_design_ini(p_identifier, design_ini_path);
-
- QPoint return_value;
-
- return_value.setX(0);
- return_value.setY(0);
-
- if (f_result == "") {
- f_result = read_design_ini(p_identifier, default_path);
-
- if (f_result == "")
- return return_value;
- }
-
- QStringList sub_line_elements = f_result.split(",");
-
- if (sub_line_elements.size() < 2)
- return return_value;
-
- return_value.setX(sub_line_elements.at(0).toInt());
- return_value.setY(sub_line_elements.at(1).toInt());
-
- return return_value;
-}
-
-pos_size_type AOApplication::get_element_dimensions(QString p_identifier,
- QString p_file)
-{
- QString design_ini_path = get_theme_path(p_file);
- QString default_path = get_default_theme_path(p_file);
- QString f_result = read_design_ini(p_identifier, design_ini_path);
-
- pos_size_type return_value;
-
- return_value.x = 0;
- return_value.y = 0;
- return_value.width = -1;
- return_value.height = -1;
-
- if (f_result == "") {
- f_result = read_design_ini(p_identifier, default_path);
-
- if (f_result == "")
- return return_value;
- }
-
- QStringList sub_line_elements = f_result.split(",");
-
- if (sub_line_elements.size() < 4)
- return return_value;
-
- return_value.x = sub_line_elements.at(0).toInt();
- return_value.y = sub_line_elements.at(1).toInt();
- return_value.width = sub_line_elements.at(2).toInt();
- return_value.height = sub_line_elements.at(3).toInt();
-
- return return_value;
-}
-QString AOApplication::get_font_name(QString p_identifier, QString p_file)
-{
- QString design_ini_path = get_theme_path(p_file);
- QString f_result = read_design_ini(p_identifier, design_ini_path);
- QString default_path = get_default_theme_path(p_file);
- if (f_result == "") {
- f_result = read_design_ini(p_identifier, default_path);
- if (f_result == "")
- return "Sans";
- }
- return f_result;
-}
-int AOApplication::get_font_size(QString p_identifier, QString p_file)
-{
- QString design_ini_path = get_theme_path(p_file);
- QString default_path = get_default_theme_path(p_file);
- QString f_result = read_design_ini(p_identifier, design_ini_path);
-
- if (f_result == "") {
- f_result = read_design_ini(p_identifier, default_path);
-
- if (f_result == "")
- return 10;
- }
-
- return f_result.toInt();
-}
-
-QColor AOApplication::get_color(QString p_identifier, QString p_file)
-{
- QString design_ini_path = get_theme_path(p_file);
- QString default_path = get_default_theme_path(p_file);
- QString f_result = read_design_ini(p_identifier, design_ini_path);
-
- QColor return_color(0, 0, 0);
-
- if (f_result == "") {
- f_result = read_design_ini(p_identifier, default_path);
-
- if (f_result == "")
- return return_color;
- }
-
- QStringList color_list = f_result.split(",");
-
- if (color_list.size() < 3)
- return return_color;
-
- return_color.setRed(color_list.at(0).toInt());
- return_color.setGreen(color_list.at(1).toInt());
- return_color.setBlue(color_list.at(2).toInt());
-
- return return_color;
-}
-
-QColor AOApplication::get_chat_color(QString p_identifier, QString p_chat)
-{
- QColor return_color(255, 255, 255);
-
- if (p_identifier == "_inline_grey") {
- return_color = QColor(187, 187, 187);
- }
- else {
- switch (p_identifier.toInt()) {
- case 1:
- return_color = QColor(0, 255, 0);
- break;
- case 2:
- return_color = QColor(255, 0, 0);
- break;
- case 3:
- return_color = QColor(255, 165, 0);
- break;
- case 4:
- return_color = QColor(45, 150, 255);
- break;
- case 5:
- return_color = QColor(255, 255, 0);
- break;
- case 7:
- return_color = QColor(255, 192, 203);
- break;
- case 8:
- return_color = QColor(0, 255, 255);
- break;
- case 0:
- case 6: // 6 is rainbow.
- default:
- return_color = QColor(255, 255, 255);
- break;
- }
- }
-
- p_identifier = p_identifier.prepend("c");
- QString design_ini_path = get_base_path() + "misc/" + p_chat + "/config.ini";
- QString default_path = get_base_path() + "misc/default/config.ini";
- QString f_result = read_design_ini(p_identifier, design_ini_path);
-
- if (f_result == "") {
- f_result = read_design_ini(p_identifier, default_path);
-
- if (f_result == "")
- return return_color;
- }
-
- QStringList color_list = f_result.split(",");
-
- if (color_list.size() < 3)
- return return_color;
-
- return_color.setRed(color_list.at(0).toInt());
- return_color.setGreen(color_list.at(1).toInt());
- return_color.setBlue(color_list.at(2).toInt());
-
- return return_color;
-}
-
-QString AOApplication::get_sfx(QString p_identifier)
-{
- QString design_ini_path = get_theme_path("courtroom_sounds.ini");
- QString default_path = get_default_theme_path("courtroom_sounds.ini");
- QString f_result = read_design_ini(p_identifier, design_ini_path);
-
- QString return_sfx = "";
-
- if (f_result == "") {
- f_result = read_design_ini(p_identifier, default_path);
-
- if (f_result == "")
- return return_sfx;
- }
-
- return_sfx = f_result;
-
- return return_sfx;
-}
-
-QString AOApplication::get_music_prefix(QString song_to_check)
-{
- if (!file_exists(get_music_path(song_to_check))) {
- QString mp3_check = get_music_path(song_to_check + ".mp3");
- QString opus_check = get_music_path(song_to_check + ".opus");
- if (file_exists(opus_check)) {
- return song_to_check + ".opus";
- }
- else if (file_exists(mp3_check)) {
- return song_to_check + ".mp3";
- }
- return song_to_check + ".wav";
- }
- else {
- return song_to_check;
- }
-}
-
-QString AOApplication::get_sfx_suffix(QString sound_to_check)
-{
- if (!file_exists(get_sounds_path(sound_to_check))) {
- QString mp3_check = get_sounds_path(sound_to_check + ".mp3");
- QString opus_check = get_sounds_path(sound_to_check + ".opus");
- if (file_exists(opus_check)) {
- return sound_to_check + ".opus";
- }
- else if (file_exists(mp3_check)) {
- return sound_to_check + ".mp3";
- }
- return sound_to_check + ".wav";
- }
- else {
- return sound_to_check;
- }
-}
-
-QString AOApplication::get_image_suffix(QString path_to_check)
-{
- if (file_exists(path_to_check + ".webp"))
- return path_to_check + ".webp";
- if (file_exists(path_to_check + ".apng"))
- return path_to_check + ".apng";
- if (file_exists(path_to_check + ".gif"))
- return path_to_check + ".gif";
- return path_to_check + ".png";
-}
-
-// returns whatever is to the right of "search_line =" within target_tag and
-// terminator_tag, trimmed returns the empty string if the search line couldnt
-// be found
-QString AOApplication::read_char_ini(QString p_char, QString p_search_line,
- QString target_tag)
-{
- QSettings settings(get_character_path(p_char, "char.ini"),
- QSettings::IniFormat);
- settings.beginGroup(target_tag);
- QString value = settings.value(p_search_line).toString();
- settings.endGroup();
- return value;
-}
-
-QString AOApplication::get_char_name(QString p_char)
-{
- QString f_result = read_char_ini(p_char, "name", "Options");
-
- if (f_result == "")
- return p_char;
- else
- return f_result;
-}
-
-QString AOApplication::get_showname(QString p_char)
-{
- QString f_result = read_char_ini(p_char, "showname", "Options");
- QString f_needed = read_char_ini(p_char, "needs_showname", "Options");
-
- if (f_needed.startsWith("false"))
- return "";
- if (f_result == "")
- return p_char;
- else
- return f_result;
-}
-
-QString AOApplication::get_char_side(QString p_char)
-{
- QString f_result = read_char_ini(p_char, "side", "Options");
-
- if (f_result == "")
- return "wit";
- else
- return f_result;
-}
-
-QString AOApplication::get_gender(QString p_char)
-{
- QString f_result = read_char_ini(p_char, "gender", "Options");
-
- if (f_result == "")
- return "male";
- else
- return f_result;
-}
-
-QString AOApplication::get_chat(QString p_char)
-{
- QString f_result = read_char_ini(p_char, "chat", "Options");
-
- // handling the correct order of chat is a bit complicated, we let the caller
- // do it
- return f_result;
-}
-
-QString AOApplication::get_char_shouts(QString p_char)
-{
- QString f_result = read_char_ini(p_char, "shouts", "Options");
- if (f_result == "")
- return "default";
- else
- return f_result;
-}
-
-int AOApplication::get_preanim_duration(QString p_char, QString p_emote)
-{
- QString f_result = read_char_ini(p_char, p_emote, "Time");
-
- if (f_result == "")
- return -1;
- else
- return f_result.toInt();
-}
-
-int AOApplication::get_ao2_preanim_duration(QString p_char, QString p_emote)
-{
- QString f_result = read_char_ini(p_char, "%" + p_emote, "Time");
-
- if (f_result == "")
- return -1;
- else
- return f_result.toInt();
-}
-
-int AOApplication::get_emote_number(QString p_char)
-{
- QString f_result = read_char_ini(p_char, "number", "Emotions");
-
- if (f_result == "")
- return 0;
- else
- return f_result.toInt();
-}
-
-QString AOApplication::get_emote_comment(QString p_char, int p_emote)
-{
- QString f_result =
- read_char_ini(p_char, QString::number(p_emote + 1), "Emotions");
-
- QStringList result_contents = f_result.split("#");
-
- if (result_contents.size() < 4) {
- qDebug() << "W: misformatted char.ini: " << p_char << ", " << p_emote;
- return "normal";
- }
- else
- return result_contents.at(0);
-}
-
-QString AOApplication::get_pre_emote(QString p_char, int p_emote)
-{
- QString f_result =
- read_char_ini(p_char, QString::number(p_emote + 1), "Emotions");
-
- QStringList result_contents = f_result.split("#");
-
- if (result_contents.size() < 4) {
- qDebug() << "W: misformatted char.ini: " << p_char << ", " << p_emote;
- return "";
- }
- else
- return result_contents.at(1);
-}
-
-QString AOApplication::get_emote(QString p_char, int p_emote)
-{
- QString f_result =
- read_char_ini(p_char, QString::number(p_emote + 1), "Emotions");
-
- QStringList result_contents = f_result.split("#");
-
- if (result_contents.size() < 4) {
- qDebug() << "W: misformatted char.ini: " << p_char << ", " << p_emote;
- return "normal";
- }
- else
- return result_contents.at(2);
-}
-
-int AOApplication::get_emote_mod(QString p_char, int p_emote)
-{
- QString f_result =
- read_char_ini(p_char, QString::number(p_emote + 1), "Emotions");
-
- QStringList result_contents = f_result.split("#");
-
- if (result_contents.size() < 4) {
- qDebug() << "W: misformatted char.ini: " << p_char << ", "
- << QString::number(p_emote);
- return 0;
- }
- else
- return result_contents.at(3).toInt();
-}
-
-int AOApplication::get_desk_mod(QString p_char, int p_emote)
-{
- QString f_result =
- read_char_ini(p_char, QString::number(p_emote + 1), "Emotions");
-
- QStringList result_contents = f_result.split("#");
-
- if (result_contents.size() < 5)
- return -1;
-
- QString string_result = result_contents.at(4);
- if (string_result == "")
- return -1;
-
- else
- return string_result.toInt();
-}
-
-QString AOApplication::get_sfx_name(QString p_char, int p_emote)
-{
- QString f_result =
- read_char_ini(p_char, QString::number(p_emote + 1), "SoundN");
-
- if (f_result == "")
- return "1";
- else
- return f_result;
-}
-
-QString AOApplication::get_sfx_looping(QString p_char, int p_emote)
-{
- QString f_result =
- read_char_ini(p_char, QString::number(p_emote + 1), "SoundL");
-
- if (f_result == "")
- return "0";
- else
- return f_result;
-}
-
-QString AOApplication::get_frame_sfx_name(QString p_char, QString p_emote,
- int n_frame)
-{
- QString f_result = read_char_ini(p_char, QString::number(n_frame),
- p_emote.append("_FrameSFX"));
- if (f_result == "")
- return "";
- else
- return f_result;
-}
-
-QString AOApplication::get_screenshake_frame(QString p_char, QString p_emote,
- int n_frame)
-{
- QString f_result = read_char_ini(p_char, QString::number(n_frame),
- p_emote.append("_FrameScreenshake"));
- if (f_result == "")
- return "";
- else
- return f_result;
-}
-
-QString AOApplication::get_realization_frame(QString p_char, QString p_emote,
- int n_frame)
-{
- QString f_result = read_char_ini(p_char, QString::number(n_frame),
- p_emote.append("_FrameRealization"));
- if (f_result == "")
- return "";
- else
- return f_result;
-}
-
-int AOApplication::get_sfx_delay(QString p_char, int p_emote)
-{
- QString f_result =
- read_char_ini(p_char, QString::number(p_emote + 1), "SoundT");
-
- if (f_result == "")
- return 1;
- else
- return f_result.toInt();
-}
-
-int AOApplication::get_text_delay(QString p_char, QString p_emote)
-{
- QString f_result = read_char_ini(p_char, p_emote, "TextDelay");
-
- if (f_result == "")
- return -1;
- else
- return f_result.toInt();
-}
-
-QString AOApplication::get_custom_realization(QString p_char)
-{
- QString f_result = read_char_ini(p_char, "realization", "Options");
-
- if (f_result == "")
- return get_sfx("realization");
- else
- return get_sfx_suffix(f_result);
-}
-
-bool AOApplication::get_blank_blip()
-{
- QString result = configini->value("blank_blip", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_looping_sfx()
-{
- QString result = configini->value("looping_sfx", "true").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_objectmusic()
-{
- QString result =
- configini->value("kill_music_on_object", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::is_discord_enabled()
-{
- QString result = configini->value("discord", "true").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::is_keepevi_enabled()
-{
- QString result = configini->value("keep_evidence", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_casing_enabled()
-{
- QString result = configini->value("casing_enabled", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_casing_defence_enabled()
-{
- QString result =
- configini->value("casing_defence_enabled", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_casing_prosecution_enabled()
-{
- QString result =
- configini->value("casing_prosecution_enabled", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_casing_judge_enabled()
-{
- QString result =
- configini->value("casing_judge_enabled", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_casing_juror_enabled()
-{
- QString result =
- configini->value("casing_juror_enabled", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_casing_steno_enabled()
-{
- QString result =
- configini->value("casing_steno_enabled", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_casing_wit_enabled()
-{
- QString result =
- configini->value("casing_wit_enabled", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_casing_cm_enabled()
-{
- QString result =
- configini->value("casing_cm_enabled", "false").value<QString>();
- return result.startsWith("true");
-}
-
-QString AOApplication::get_casing_can_host_cases()
-{
- QString result =
- configini->value("casing_can_host_cases", "Turnabout Check Your Settings")
- .value<QString>();
- return result;
-}
-
-bool AOApplication::get_colored_iclog_enabled()
-{
- QString result =
- configini->value("color_iclog_enabled", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::get_iclmir_enabled()
-{
- QString result =
- configini->value("mirror_iclog_enabled", "false").value<QString>();
- return result.startsWith("true");
-}
-bool AOApplication::colorlog_restricted_enabled()
-{
- QString result =
- configini->value("mirror_iclog_restricted", "false").value<QString>();
- return result.startsWith("true");
-}
-
-bool AOApplication::is_shakeandflash_enabled()
-{
- QString result = configini->value("shakeandflash", "true").value<QString>();
- return result.startsWith("true");
-}
+#include "text_file_functions.h"
+
+QString AOApplication::read_theme()
+{
+ QString result = configini->value("theme", "default").value<QString>();
+ return result;
+}
+
+int AOApplication::read_blip_rate()
+{
+ int result = configini->value("blip_rate", 2).toInt();
+
+ if (result < 1)
+ return 1;
+
+ return result;
+}
+
+QString AOApplication::get_ooc_name()
+{
+ QString result = configini->value("ooc_name").value<QString>();
+ return result;
+}
+
+int AOApplication::get_default_music()
+{
+ int result = configini->value("default_music", 50).toInt();
+ return result;
+}
+
+int AOApplication::get_default_sfx()
+{
+ int result = configini->value("default_sfx", 50).toInt();
+ return result;
+}
+
+int AOApplication::get_default_blip()
+{
+ int result = configini->value("default_blip", 50).toInt();
+ return result;
+}
+
+int AOApplication::get_max_log_size()
+{
+ int result = configini->value("log_maximum", 200).toInt();
+ return result;
+}
+
+bool AOApplication::get_log_goes_downwards()
+{
+ QString result =
+ configini->value("log_goes_downwards", "true").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::get_showname_enabled_by_default()
+{
+ QString result =
+ configini->value("show_custom_shownames", "true").value<QString>();
+ return result.startsWith("true");
+}
+
+QString AOApplication::get_default_username()
+{
+ QString result = configini->value("default_username", "").value<QString>();
+ if (result.isEmpty())
+ return get_ooc_name();
+ else
+ return result;
+}
+
+QString AOApplication::get_audio_output_device()
+{
+ QString result =
+ configini->value("default_audio_device", "default").value<QString>();
+ return result;
+}
+
+QStringList AOApplication::get_call_words()
+{
+ return get_list_file(get_base_path() + "callwords.ini");
+}
+
+QStringList AOApplication::get_list_file(QString p_file)
+{
+ QStringList return_value;
+
+ QFile p_ini;
+
+ p_ini.setFileName(p_file);
+
+ if (!p_ini.open(QIODevice::ReadOnly))
+ return return_value;
+
+ QTextStream in(&p_ini);
+
+ while (!in.atEnd()) {
+ QString line = in.readLine();
+ return_value.append(line);
+ }
+
+ return return_value;
+}
+
+QString AOApplication::read_file(QString filename)
+{
+ QFile f_log(filename);
+
+ if (!f_log.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qDebug() << "Couldn't open" << filename;
+ return "";
+ }
+
+ QTextStream in(&f_log);
+ QString text = in.readAll();
+ f_log.close();
+ return text;
+}
+
+bool AOApplication::write_to_file(QString p_text, QString p_file, bool make_dir)
+{
+ QString path = QFileInfo(p_file).path();
+ if (make_dir) {
+ // Create the dir if it doesn't exist yet
+ QDir dir(path);
+ if (!dir.exists())
+ if (!dir.mkpath("."))
+ return false;
+ }
+
+ QFile f_log(p_file);
+ if (f_log.open(QIODevice::WriteOnly | QIODevice::Text |
+ QIODevice::Truncate)) {
+ QTextStream out(&f_log);
+
+ out << p_text;
+
+ f_log.flush();
+ f_log.close();
+ return true;
+ }
+ return false;
+}
+
+bool AOApplication::append_to_file(QString p_text, QString p_file,
+ bool make_dir)
+{
+ QString path = QFileInfo(p_file).path();
+ // Create the dir if it doesn't exist yet
+ if (make_dir) {
+ QDir dir(path);
+ if (!dir.exists())
+ if (!dir.mkpath("."))
+ return false;
+ }
+
+ QFile f_log(p_file);
+ if (f_log.open(QIODevice::WriteOnly | QIODevice::Append)) {
+ QTextStream out(&f_log);
+
+ out << "\r\n" << p_text;
+
+ f_log.flush();
+ f_log.close();
+ return true;
+ }
+ return false;
+}
+
+void AOApplication::write_to_serverlist_txt(QString p_line)
+{
+ QFile serverlist_txt;
+ QString serverlist_txt_path = get_base_path() + "serverlist.txt";
+
+ serverlist_txt.setFileName(serverlist_txt_path);
+
+ if (!serverlist_txt.open(QIODevice::WriteOnly | QIODevice::Append)) {
+ return;
+ }
+
+ QTextStream out(&serverlist_txt);
+
+ out << "\r\n" << p_line;
+
+ serverlist_txt.close();
+}
+
+QVector<server_type> AOApplication::read_serverlist_txt()
+{
+ QVector<server_type> f_server_list;
+
+ QFile serverlist_txt;
+ QString serverlist_txt_path = get_base_path() + "serverlist.txt";
+
+ serverlist_txt.setFileName(serverlist_txt_path);
+
+ if (!serverlist_txt.open(QIODevice::ReadOnly)) {
+ return f_server_list;
+ }
+
+ QTextStream in(&serverlist_txt);
+
+ while (!in.atEnd()) {
+ QString line = in.readLine();
+ server_type f_server;
+ QStringList line_contents = line.split(":");
+
+ if (line_contents.size() < 3)
+ continue;
+
+ f_server.ip = line_contents.at(0);
+ f_server.port = line_contents.at(1).toInt();
+ f_server.name = line_contents.at(2);
+ f_server.desc = "";
+
+ f_server_list.append(f_server);
+ }
+
+ return f_server_list;
+}
+
+QString AOApplication::read_design_ini(QString p_identifier,
+ QString p_design_path)
+{
+ QSettings settings(p_design_path, QSettings::IniFormat);
+ QVariant value = settings.value(p_identifier);
+ if (value.type() == QVariant::StringList) {
+ return value.toStringList().join(",");
+ }
+ else {
+ return value.toString();
+ }
+}
+
+QPoint AOApplication::get_button_spacing(QString p_identifier, QString p_file)
+{
+ QString design_ini_path = get_theme_path(p_file);
+ QString default_path = get_default_theme_path(p_file);
+ QString f_result = read_design_ini(p_identifier, design_ini_path);
+
+ QPoint return_value;
+
+ return_value.setX(0);
+ return_value.setY(0);
+
+ if (f_result == "") {
+ f_result = read_design_ini(p_identifier, default_path);
+
+ if (f_result == "")
+ return return_value;
+ }
+
+ QStringList sub_line_elements = f_result.split(",");
+
+ if (sub_line_elements.size() < 2)
+ return return_value;
+
+ return_value.setX(sub_line_elements.at(0).toInt());
+ return_value.setY(sub_line_elements.at(1).toInt());
+
+ return return_value;
+}
+
+pos_size_type AOApplication::get_element_dimensions(QString p_identifier,
+ QString p_file,
+ QString p_char)
+{
+ QString char_ini_path =
+ get_base_path() + "misc/" + get_chat(p_char) + "/" + p_file;
+ QString design_ini_path = get_theme_path(p_file);
+ QString default_path = get_default_theme_path(p_file);
+ QString f_result = read_design_ini(p_identifier, char_ini_path);
+
+ pos_size_type return_value;
+
+ return_value.x = 0;
+ return_value.y = 0;
+ return_value.width = -1;
+ return_value.height = -1;
+
+ if (f_result == "") {
+ f_result = read_design_ini(p_identifier, design_ini_path);
+ if (f_result == "") {
+ f_result = read_design_ini(p_identifier, default_path);
+
+ if (f_result == "")
+ return return_value;
+ }
+ }
+
+ QStringList sub_line_elements = f_result.split(",");
+
+ if (sub_line_elements.size() < 4)
+ return return_value;
+
+ return_value.x = sub_line_elements.at(0).toInt();
+ return_value.y = sub_line_elements.at(1).toInt();
+ return_value.width = sub_line_elements.at(2).toInt();
+ return_value.height = sub_line_elements.at(3).toInt();
+
+ return return_value;
+}
+QString AOApplication::get_design_element(QString p_identifier, QString p_file,
+ QString p_char)
+{
+ QString char_ini_path =
+ get_base_path() + "misc/" + get_chat(p_char) + "/" + p_file;
+ QString design_ini_path = get_theme_path(p_file);
+ QString default_path = get_default_theme_path(p_file);
+ QString f_result = read_design_ini(p_identifier, char_ini_path);
+ if (f_result == "") {
+ f_result = read_design_ini(p_identifier, design_ini_path);
+ if (f_result == "")
+ f_result = read_design_ini(p_identifier, default_path);
+ }
+ return f_result;
+}
+QString AOApplication::get_font_name(QString p_identifier, QString p_file)
+{
+ QString design_ini_path = get_theme_path(p_file);
+ QString f_result = read_design_ini(p_identifier, design_ini_path);
+ QString default_path = get_default_theme_path(p_file);
+ if (f_result == "") {
+ f_result = read_design_ini(p_identifier, default_path);
+ if (f_result == "")
+ return "";
+ }
+ return f_result;
+}
+int AOApplication::get_font_size(QString p_identifier, QString p_file)
+{
+ QString design_ini_path = get_theme_path(p_file);
+ QString default_path = get_default_theme_path(p_file);
+ QString f_result = read_design_ini(p_identifier, design_ini_path);
+
+ if (f_result == "") {
+ f_result = read_design_ini(p_identifier, default_path);
+
+ if (f_result == "")
+ return 10;
+ }
+
+ return f_result.toInt();
+}
+
+QColor AOApplication::get_color(QString p_identifier, QString p_file)
+{
+ QString design_ini_path = get_theme_path(p_file);
+ QString default_path = get_default_theme_path(p_file);
+ QString f_result = read_design_ini(p_identifier, design_ini_path);
+
+ QColor return_color(0, 0, 0);
+
+ if (f_result == "") {
+ f_result = read_design_ini(p_identifier, default_path);
+
+ if (f_result == "")
+ return return_color;
+ }
+
+ QStringList color_list = f_result.split(",");
+
+ if (color_list.size() < 3)
+ return return_color;
+
+ return_color.setRed(color_list.at(0).toInt());
+ return_color.setGreen(color_list.at(1).toInt());
+ return_color.setBlue(color_list.at(2).toInt());
+
+ return return_color;
+}
+
+QString AOApplication::get_stylesheet(QString p_file)
+{
+ QString design_ini_path = get_theme_path(p_file);
+ QString default_path = get_default_theme_path(p_file);
+
+ QFile design_ini;
+
+ design_ini.setFileName(design_ini_path);
+
+ if (!design_ini.open(QIODevice::ReadOnly)) {
+ design_ini.setFileName(default_path);
+ if (!design_ini.open(QIODevice::ReadOnly))
+ return "";
+ }
+
+ QTextStream in(&design_ini);
+
+ QString f_text;
+
+ while (!in.atEnd()) {
+ f_text.append(in.readLine());
+ }
+
+ design_ini.close();
+ return f_text;
+}
+
+QString AOApplication::get_tagged_stylesheet(QString target_tag, QString p_file)
+{
+ QString design_ini_path = get_theme_path(p_file);
+
+ QFile design_ini;
+
+ design_ini.setFileName(design_ini_path);
+
+ if (!design_ini.open(QIODevice::ReadOnly))
+ return "";
+
+ QTextStream in(&design_ini);
+
+ QString f_text;
+
+ bool tag_found = false;
+
+ while (!in.atEnd()) {
+ QString line = in.readLine();
+
+ if (line.startsWith(target_tag, Qt::CaseInsensitive)) {
+ tag_found = true;
+ continue;
+ }
+
+ if (tag_found) {
+ if ((line.startsWith("[") && line.endsWith("]")))
+ break;
+ f_text.append(line);
+ }
+ }
+
+ design_ini.close();
+ return f_text;
+}
+
+QString AOApplication::get_chat_markdown(QString p_identifier, QString p_chat)
+{
+ QString design_ini_path = get_base_path() + "misc/" + p_chat + "/config.ini";
+ QString default_path = get_base_path() + "misc/default/config.ini";
+ QString f_result = read_design_ini(p_identifier, design_ini_path);
+
+ if (f_result == "")
+ f_result = read_design_ini(p_identifier, default_path);
+
+ return f_result.toLatin1();
+}
+
+QColor AOApplication::get_chat_color(QString p_identifier, QString p_chat)
+{
+ QColor return_color(255, 255, 255);
+
+ QString design_ini_path = get_base_path() + "misc/" + p_chat + "/config.ini";
+ QString default_path = get_base_path() + "misc/default/config.ini";
+ QString f_result = read_design_ini("c" + p_identifier, design_ini_path);
+
+ if (f_result == "") {
+ f_result = read_design_ini(p_identifier, default_path);
+
+ if (f_result == "")
+ return return_color;
+ }
+
+ QStringList color_list = f_result.split(",");
+
+ if (color_list.size() < 3)
+ return return_color;
+
+ return_color.setRed(color_list.at(0).toInt());
+ return_color.setGreen(color_list.at(1).toInt());
+ return_color.setBlue(color_list.at(2).toInt());
+
+ return return_color;
+}
+
+QString AOApplication::get_sfx(QString p_identifier)
+{
+ QString design_ini_path = get_theme_path("courtroom_sounds.ini");
+ QString default_path = get_default_theme_path("courtroom_sounds.ini");
+ QString f_result = read_design_ini(p_identifier, design_ini_path);
+
+ QString return_sfx = "";
+
+ if (f_result == "") {
+ f_result = read_design_ini(p_identifier, default_path);
+
+ if (f_result == "")
+ return return_sfx;
+ }
+
+ return_sfx = f_result;
+
+ return return_sfx;
+}
+
+QString AOApplication::get_sfx_suffix(QString sound_to_check)
+{
+ if (file_exists(sound_to_check))
+ return sound_to_check;
+ if (file_exists(sound_to_check + ".opus"))
+ return sound_to_check + ".opus";
+ if (file_exists(sound_to_check + ".ogg"))
+ return sound_to_check + ".ogg";
+ if (file_exists(sound_to_check + ".mp3"))
+ return sound_to_check + ".mp3";
+ if (file_exists(sound_to_check + ".mp4"))
+ return sound_to_check + ".mp4";
+ return sound_to_check + ".wav";
+}
+
+QString AOApplication::get_image_suffix(QString path_to_check)
+{
+ if (file_exists(path_to_check))
+ return path_to_check;
+ if (file_exists(path_to_check + ".webp"))
+ return path_to_check + ".webp";
+ if (file_exists(path_to_check + ".apng"))
+ return path_to_check + ".apng";
+ if (file_exists(path_to_check + ".gif"))
+ return path_to_check + ".gif";
+ return path_to_check + ".png";
+}
+
+QString AOApplication::get_static_image_suffix(QString path_to_check)
+{
+ return path_to_check + ".png";
+}
+
+// returns whatever is to the right of "search_line =" within target_tag and
+// terminator_tag, trimmed returns the empty string if the search line couldnt
+// be found
+QString AOApplication::read_char_ini(QString p_char, QString p_search_line,
+ QString target_tag)
+{
+ QSettings settings(get_character_path(p_char, "char.ini"),
+ QSettings::IniFormat);
+ settings.beginGroup(target_tag);
+ QString value = settings.value(p_search_line).toString();
+ settings.endGroup();
+ return value;
+}
+
+void AOApplication::set_char_ini(QString p_char, QString value,
+ QString p_search_line, QString target_tag)
+{
+ QSettings settings(get_character_path(p_char, "char.ini"),
+ QSettings::IniFormat);
+ settings.beginGroup(target_tag);
+ settings.setValue(p_search_line, value);
+ settings.endGroup();
+}
+
+// returns all the values of target_tag
+QStringList AOApplication::read_ini_tags(QString p_path, QString target_tag)
+{
+ QStringList r_values;
+ QSettings settings(p_path, QSettings::IniFormat);
+ if (!target_tag.isEmpty())
+ settings.beginGroup(target_tag);
+ QStringList keys = settings.allKeys();
+ foreach (QString key, keys) {
+ QString value = settings.value(key).toString();
+ r_values << key + "=" + value;
+ }
+ if (!settings.group().isEmpty())
+ settings.endGroup();
+ return r_values;
+}
+
+QString AOApplication::get_char_name(QString p_char)
+{
+ QString f_result = read_char_ini(p_char, "name", "Options");
+
+ if (f_result == "")
+ return p_char;
+ return f_result;
+}
+
+QString AOApplication::get_showname(QString p_char)
+{
+ QString f_result = read_char_ini(p_char, "showname", "Options");
+ QString f_needed = read_char_ini(p_char, "needs_showname", "Options");
+
+ if (f_needed.startsWith("false"))
+ return "";
+ if (f_result == "")
+ return p_char;
+ return f_result;
+}
+
+QString AOApplication::get_char_side(QString p_char)
+{
+ QString f_result = read_char_ini(p_char, "side", "Options");
+
+ if (f_result == "")
+ return "wit";
+ return f_result;
+}
+
+QString AOApplication::get_gender(QString p_char)
+{
+ QString f_result = read_char_ini(p_char, "gender", "Options");
+
+ if (f_result == "")
+ f_result = "male";
+
+ if (!file_exists(get_sfx_suffix(get_sounds_path(f_result)))) {
+ if (file_exists(get_sfx_suffix(get_sounds_path("../blips/" + f_result))))
+ return "../blips/" + f_result; // Return the cool kids variant
+
+ return "sfx-blip" + f_result; // Return legacy variant
+ }
+ return f_result;
+}
+
+QString AOApplication::get_chat(QString p_char)
+{
+ QString f_result = read_char_ini(p_char, "chat", "Options");
+
+ // handling the correct order of chat is a bit complicated, we let the caller
+ // do it
+ return f_result;
+}
+
+QString AOApplication::get_chat_font(QString p_char)
+{
+ QString f_result = read_char_ini(p_char, "chat_font", "Options");
+
+ return f_result;
+}
+
+int AOApplication::get_chat_size(QString p_char)
+{
+ QString f_result = read_char_ini(p_char, "chat_size", "Options");
+
+ if (f_result == "")
+ return -1;
+ return f_result.toInt();
+}
+
+QString AOApplication::get_char_shouts(QString p_char)
+{
+ QString f_result = read_char_ini(p_char, "shouts", "Options");
+ if (f_result == "")
+ return current_theme; // The default option is the current theme.
+ return f_result;
+}
+
+int AOApplication::get_preanim_duration(QString p_char, QString p_emote)
+{
+ QString f_result = read_char_ini(p_char, p_emote, "Time");
+
+ if (f_result == "")
+ return -1;
+ return f_result.toInt();
+}
+
+int AOApplication::get_ao2_preanim_duration(QString p_char, QString p_emote)
+{
+ QString f_result = read_char_ini(p_char, "%" + p_emote, "Time");
+
+ if (f_result == "")
+ return -1;
+ return f_result.toInt();
+}
+
+int AOApplication::get_emote_number(QString p_char)
+{
+ QString f_result = read_char_ini(p_char, "number", "Emotions");
+
+ if (f_result == "")
+ return 0;
+ return f_result.toInt();
+}
+
+QString AOApplication::get_emote_comment(QString p_char, int p_emote)
+{
+ QString f_result =
+ read_char_ini(p_char, QString::number(p_emote + 1), "Emotions");
+
+ QStringList result_contents = f_result.split("#");
+
+ if (result_contents.size() < 4) {
+ qDebug() << "W: misformatted char.ini: " << p_char << ", " << p_emote;
+ return "normal";
+ }
+ return result_contents.at(0);
+}
+
+QString AOApplication::get_pre_emote(QString p_char, int p_emote)
+{
+ QString f_result =
+ read_char_ini(p_char, QString::number(p_emote + 1), "Emotions");
+
+ QStringList result_contents = f_result.split("#");
+
+ if (result_contents.size() < 4) {
+ qDebug() << "W: misformatted char.ini: " << p_char << ", " << p_emote;
+ return "";
+ }
+ return result_contents.at(1);
+}
+
+QString AOApplication::get_emote(QString p_char, int p_emote)
+{
+ QString f_result =
+ read_char_ini(p_char, QString::number(p_emote + 1), "Emotions");
+
+ QStringList result_contents = f_result.split("#");
+
+ if (result_contents.size() < 4) {
+ qDebug() << "W: misformatted char.ini: " << p_char << ", " << p_emote;
+ return "normal";
+ }
+ return result_contents.at(2);
+}
+
+int AOApplication::get_emote_mod(QString p_char, int p_emote)
+{
+ QString f_result =
+ read_char_ini(p_char, QString::number(p_emote + 1), "Emotions");
+
+ QStringList result_contents = f_result.split("#");
+
+ if (result_contents.size() < 4) {
+ qDebug() << "W: misformatted char.ini: " << p_char << ", "
+ << QString::number(p_emote);
+ return 0;
+ }
+ return result_contents.at(3).toInt();
+}
+
+int AOApplication::get_desk_mod(QString p_char, int p_emote)
+{
+ QString f_result =
+ read_char_ini(p_char, QString::number(p_emote + 1), "Emotions");
+
+ QStringList result_contents = f_result.split("#");
+
+ if (result_contents.size() < 5)
+ return -1;
+
+ QString string_result = result_contents.at(4);
+ if (string_result == "")
+ return -1;
+
+ return string_result.toInt();
+}
+
+QString AOApplication::get_sfx_name(QString p_char, int p_emote)
+{
+ QString f_result =
+ read_char_ini(p_char, QString::number(p_emote + 1), "SoundN");
+
+ if (f_result == "")
+ return "1";
+ return f_result;
+}
+
+QString AOApplication::get_emote_blip(QString p_char, int p_emote)
+{
+ QString f_result =
+ read_char_ini(p_char, QString::number(p_emote + 1), "SoundB");
+ return f_result;
+}
+
+int AOApplication::get_sfx_delay(QString p_char, int p_emote)
+{
+ QString f_result =
+ read_char_ini(p_char, QString::number(p_emote + 1), "SoundT");
+
+ if (f_result == "")
+ return 1;
+ return f_result.toInt();
+}
+
+QString AOApplication::get_sfx_looping(QString p_char, int p_emote)
+{
+ QString f_result =
+ read_char_ini(p_char, QString::number(p_emote + 1), "SoundL");
+
+ qDebug() << f_result;
+ if (f_result == "")
+ return "0";
+ else
+ return f_result;
+}
+
+QString AOApplication::get_sfx_frame(QString p_char, QString p_emote,
+ int n_frame)
+{
+ QString f_result = read_char_ini(p_char, QString::number(n_frame),
+ p_emote.append("_FrameSFX"));
+
+ if (f_result == "")
+ return "";
+ return f_result;
+}
+
+QString AOApplication::get_screenshake_frame(QString p_char, QString p_emote,
+ int n_frame)
+{
+ QString f_result = read_char_ini(p_char, QString::number(n_frame),
+ p_emote.append("_FrameScreenshake"));
+
+ if (f_result == "")
+ return "";
+ return f_result;
+}
+
+QString AOApplication::get_flash_frame(QString p_char, QString p_emote,
+ int n_frame)
+{
+ QString f_result = read_char_ini(p_char, QString::number(n_frame),
+ p_emote.append("_FrameRealization"));
+
+ if (f_result == "")
+ return "";
+ return f_result;
+}
+
+int AOApplication::get_text_delay(QString p_char, QString p_emote)
+{
+ QString f_result = read_char_ini(p_char, p_emote, "TextDelay");
+
+ if (f_result == "")
+ return -1;
+ return f_result.toInt();
+}
+
+QStringList AOApplication::get_theme_effects()
+{
+ QString p_path = get_theme_path("effects/effects.ini");
+ QString default_path = get_default_theme_path("effects/effects.ini");
+
+ QStringList effects;
+ if (!file_exists(p_path)) {
+ p_path = default_path;
+ if (!file_exists(p_path))
+ return effects;
+ }
+
+ QStringList lines = read_file(p_path).split("\n");
+ foreach (QString effect, lines) {
+ effect = effect.split("=")[0].trimmed();
+ if (!effect.isEmpty() && !effects.contains(effect))
+ effects.append(effect);
+ }
+ return effects;
+}
+
+QStringList AOApplication::get_effects(QString p_char)
+{
+ QString p_effect = read_char_ini(p_char, "effects", "Options");
+ QString p_path = get_base_path() + "misc/" + p_effect + "/effects.ini";
+
+ QStringList effects = get_theme_effects();
+ if (!file_exists(p_path))
+ return effects;
+
+ QStringList lines = read_file(p_path).split("\n");
+ foreach (QString effect, lines) {
+ effect = effect.split("=")[0].trimmed();
+ if (!effect.isEmpty() && !effects.contains(effect))
+ effects.append(effect);
+ }
+
+ return effects;
+}
+
+QString AOApplication::get_effect(QString effect, QString p_char,
+ QString p_folder)
+{
+ QString p_effect = p_folder;
+ if (p_folder == "")
+ p_effect = read_char_ini(p_char, "effects", "Options");
+
+ QString p_path =
+ get_image_suffix(get_base_path() + "misc/" + p_effect + "/" + effect);
+ QString design_ini_path =
+ get_image_suffix(get_theme_path("effects/" + effect));
+ QString default_path =
+ get_image_suffix(get_default_theme_path("effects/" + effect));
+
+ if (!file_exists(p_path)) {
+ p_path = design_ini_path;
+ if (!file_exists(p_path)) {
+ p_path = default_path;
+ if (!file_exists(p_path)) {
+ return "";
+ }
+ }
+ }
+
+ return p_path;
+}
+
+QString AOApplication::get_effect_sound(QString fx_name, QString p_char)
+{
+ QString p_effect = read_char_ini(p_char, "effects", "Options");
+ QString p_path = get_base_path() + "misc/" + p_effect + "/effects.ini";
+ QString design_ini_path = get_theme_path("effects/effects.ini");
+ QString default_path = get_default_theme_path("effects/effects.ini");
+
+ QString f_result = read_design_ini(fx_name, p_path);
+ if (f_result == "") {
+ f_result = read_design_ini(fx_name, design_ini_path);
+ if (f_result == "") {
+ f_result = read_design_ini(fx_name, default_path);
+ }
+ }
+ return f_result;
+}
+
+QString AOApplication::get_custom_realization(QString p_char)
+{
+ QString f_result = read_char_ini(p_char, "realization", "Options");
+
+ if (f_result == "")
+ return get_sfx("realization");
+ else
+ return get_sfx_suffix(get_sounds_path(f_result));
+}
+
+bool AOApplication::get_blank_blip()
+{
+ QString result = configini->value("blank_blip", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::get_looping_sfx()
+{
+ QString result = configini->value("looping_sfx", "true").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::objection_stop_music()
+{
+ QString result =
+ configini->value("objection_stop_music", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::is_discord_enabled()
+{
+ QString result = configini->value("discord", "true").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::is_shake_enabled()
+{
+ QString result = configini->value("shake", "true").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::is_effects_enabled()
+{
+ QString result = configini->value("effects", "true").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::is_frame_network_enabled()
+{
+ QString result = configini->value("framenetwork", "true").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::is_colorlog_enabled()
+{
+ QString result = configini->value("colorlog", "true").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::is_stickysounds_enabled()
+{
+ QString result = configini->value("stickysounds", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::is_stickyeffects_enabled()
+{
+ QString result = configini->value("stickyeffects", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::is_stickypres_enabled()
+{
+ QString result = configini->value("stickypres", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::is_customchat_enabled()
+{
+ QString result = configini->value("customchat", "true").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::get_casing_enabled()
+{
+ QString result = configini->value("casing_enabled", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::get_casing_defence_enabled()
+{
+ QString result =
+ configini->value("casing_defence_enabled", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::get_casing_prosecution_enabled()
+{
+ QString result =
+ configini->value("casing_prosecution_enabled", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::get_casing_judge_enabled()
+{
+ QString result =
+ configini->value("casing_judge_enabled", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::get_casing_juror_enabled()
+{
+ QString result =
+ configini->value("casing_juror_enabled", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::get_casing_steno_enabled()
+{
+ QString result =
+ configini->value("casing_steno_enabled", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+bool AOApplication::get_casing_cm_enabled()
+{
+ QString result =
+ configini->value("casing_cm_enabled", "false").value<QString>();
+ return result.startsWith("true");
+}
+
+QString AOApplication::get_casing_can_host_cases()
+{
+ QString result =
+ configini->value("casing_can_host_cases", "Turnabout Check Your Settings")
+ .value<QString>();
+ return result;
+}
+bool AOApplication::get_auto_logging_enabled()
+{
+ QString result =
+ configini->value("automatic_logging_enabled", "true").value<QString>();
+ return result.startsWith("true");
+}