From 739142f8ddd194b7f4ed42fe813979655d04262a Mon Sep 17 00:00:00 2001 From: Cerapter Date: Mon, 3 Sep 2018 03:52:16 +0200 Subject: [PATCH] Dual characters on screen Part I The basics have been laid out. - Communication about the second character established. - Pairing sytem made. - Placement system of the second character implemented. Needs: - More testing. - A workable UI. - Fix for zooms. --- courtroom.cpp | 180 ++++++++++++++++++++++++++++++++++++++- courtroom.h | 9 +- datatypes.h | 7 +- server/aoprotocol.py | 35 +++++++- server/client_manager.py | 6 ++ 5 files changed, 228 insertions(+), 9 deletions(-) diff --git a/courtroom.cpp b/courtroom.cpp index 3b9930b..c02f94e 100644 --- a/courtroom.cpp +++ b/courtroom.cpp @@ -80,6 +80,8 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() 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); @@ -379,6 +381,9 @@ void Courtroom::set_widgets() 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()); @@ -891,6 +896,12 @@ void Courtroom::on_chat_return_pressed() //realization# //text_color#% + // Additionally, in our case: + + //showname# + //other_charid# + //self_offset#% + QStringList packet_contents; QString f_side = ao_app->get_char_side(current_char); @@ -997,6 +1008,19 @@ void Courtroom::on_chat_return_pressed() packet_contents.append(ui_ic_chat_name->text()); } + // If there is someone this user would like to appear with. + if (other_charid > -1) + { + // First, we'll add a filler in case we haven't set an IC showname. + if (ui_ic_chat_name->text().isEmpty()) + { + packet_contents.append(""); + } + + packet_contents.append(QString::number(other_charid)); + packet_contents.append(QString::number(offset_with_pair)); + } + ao_app->send_server_packet(new AOPacket("MS", packet_contents)); } @@ -1184,6 +1208,125 @@ void Courtroom::handle_chatmessage_2() 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, 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 / 20; + } + 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 / 20; + } + 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 / 20; + } + 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 / 20; + } + ui_vp_sideplayer_char->move(ui_viewport->width() * hor2_offset, ui_viewport->height() * vert2_offset); + + // 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 talker is on top. + ui_vp_sideplayer_char->raise(); + ui_vp_player_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(char_list.at(got_other_charid).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); + + ui_vp_player_char->move(0,0); + } + } + } switch (emote_mod) { @@ -1216,10 +1359,11 @@ void Courtroom::handle_chatmessage_3() int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); + QString side = m_chatmessage[SIDE]; + if (emote_mod == 5 || emote_mod == 6) { - QString side = m_chatmessage[SIDE]; ui_vp_desk->hide(); ui_vp_legacy_desk->hide(); @@ -2305,9 +2449,37 @@ void Courtroom::on_ooc_return_pressed() } else if (ooc_message.startsWith("/settings")) { - ui_ooc_chat_message->clear(); - ao_app->call_settings_menu(); - return; + ui_ooc_chat_message->clear(); + ao_app->call_settings_menu(); + 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; + } + 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; + } + return; } QStringList packet_contents; diff --git a/courtroom.h b/courtroom.h index d618862..ad00b72 100644 --- a/courtroom.h +++ b/courtroom.h @@ -194,6 +194,12 @@ private: // 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 char_list; QVector evidence_list; QVector music_list; @@ -240,7 +246,7 @@ private: //every time point in char.inis times this equals the final time const int time_mod = 40; - static const int chatmessage_size = 16; + static const int chatmessage_size = 21; QString m_chatmessage[chatmessage_size]; bool chatmessage_is_empty = false; @@ -323,6 +329,7 @@ private: 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; diff --git a/datatypes.h b/datatypes.h index 4cb54cb..fdf91bd 100644 --- a/datatypes.h +++ b/datatypes.h @@ -93,7 +93,12 @@ enum CHAT_MESSAGE FLIP, REALIZATION, TEXT_COLOR, - SHOWNAME + SHOWNAME, + OTHER_CHARID, + OTHER_EMOTE, + SELF_OFFSET, + OTHER_OFFSET, + OTHER_FLIP }; enum COLOR diff --git a/server/aoprotocol.py b/server/aoprotocol.py index 8516c9f..800ae6a 100644 --- a/server/aoprotocol.py +++ b/server/aoprotocol.py @@ -342,12 +342,14 @@ class AOProtocol(asyncio.Protocol): self.ArgType.INT, self.ArgType.INT, self.ArgType.INT): msg_type, pre, folder, anim, text, pos, sfx, anim_type, cid, sfx_delay, button, evidence, flip, ding, color = args showname = "" + charid_pair = -1 + offset_pair = 0 elif self.validate_net_cmd(args, self.ArgType.STR, self.ArgType.STR_OR_EMPTY, self.ArgType.STR, self.ArgType.STR, self.ArgType.STR, self.ArgType.STR, self.ArgType.STR, self.ArgType.INT, self.ArgType.INT, self.ArgType.INT, self.ArgType.INT, self.ArgType.INT, - self.ArgType.INT, self.ArgType.INT, self.ArgType.INT, self.ArgType.STR): - msg_type, pre, folder, anim, text, pos, sfx, anim_type, cid, sfx_delay, button, evidence, flip, ding, color, showname = args + self.ArgType.INT, self.ArgType.INT, self.ArgType.INT, self.ArgType.STR_OR_EMPTY, self.ArgType.INT, self.ArgType.INT): + msg_type, pre, folder, anim, text, pos, sfx, anim_type, cid, sfx_delay, button, evidence, flip, ding, color, showname, charid_pair, offset_pair = args if len(showname) > 0 and not self.client.area.showname_changes_allowed: self.client.send_host_message("Showname changes are forbidden in this area!") return @@ -412,8 +414,35 @@ class AOProtocol(asyncio.Protocol): if self.client.area.evi_list.evidences[self.client.evi_list[evidence] - 1].pos != 'all': self.client.area.evi_list.evidences[self.client.evi_list[evidence] - 1].pos = 'all' self.client.area.broadcast_evidence_list() + + # Here, we check the pair stuff, and save info about it to the client. + # Notably, while we only get a charid_pair and an offset, we send back a chair_pair, an emote, a talker offset + # and an other offset. + self.client.charid_pair = charid_pair + self.client.offset_pair = offset_pair + self.client.last_sprite = anim + self.client.flip = flip + other_offset = 0 + other_emote = '' + other_flip = 0 + + confirmed = False + if charid_pair > -1: + for target in self.client.area.clients: + if target.char_id == self.client.charid_pair and target.charid_pair == self.client.char_id and target != self.client and target.pos == self.client.pos: + confirmed = True + other_offset = target.offset_pair + other_emote = target.last_sprite + other_flip = target.flip + break + + if not confirmed: + charid_pair = -1 + offset_pair = 0 + self.client.area.send_command('MS', msg_type, pre, folder, anim, msg, pos, sfx, anim_type, cid, - sfx_delay, button, self.client.evi_list[evidence], flip, ding, color, showname) + sfx_delay, button, self.client.evi_list[evidence], flip, ding, color, showname, + charid_pair, other_emote, offset_pair, other_offset, other_flip) self.client.area.set_next_msg_delay(len(msg)) logger.log_server('[IC][{}][{}]{}'.format(self.client.area.abbreviation, self.client.get_char_name(), msg), self.client) diff --git a/server/client_manager.py b/server/client_manager.py index 29caff0..ec9a26a 100644 --- a/server/client_manager.py +++ b/server/client_manager.py @@ -57,6 +57,12 @@ class ClientManager: self.in_rp = False self.ipid = ipid self.websocket = None + + # Pairing stuff + self.charid_pair = -1 + self.offset_pair = 0 + self.last_sprite = '' + self.flip = 0 #flood-guard stuff self.mus_counter = 0