Skip to content

Commit

Permalink
#368: Feature/RevealAnonymousVotes (#369)
Browse files Browse the repository at this point in the history
  • Loading branch information
cddjr committed May 30, 2022
1 parent ce0fdc5 commit ed84685
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 25 deletions.
1 change: 1 addition & 0 deletions appdata/il2cpp-classes.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ DO_APP_CLASS(GameOptionsData, "Assembly-CSharp, GameOptionsData");
DO_APP_CLASS(Camera, "UnityEngine.CoreModule, UnityEngine.Camera");
DO_APP_CLASS(LobbyBehaviour, "Assembly-CSharp, LobbyBehaviour");
DO_APP_CLASS(SaveManager, "Assembly-CSharp, SaveManager");
DO_APP_CLASS(MeetingHud, "Assembly-CSharp, MeetingHud");
//DO_APP_CLASS(DestroyableSingleton_1_RoleManager_, "Assembly-CSharp, DestroyableSingleton_1_RoleManager_");
4 changes: 3 additions & 1 deletion appdata/il2cpp-functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ DO_APP_FUNC(void, MeetingHud_Awake, (MeetingHud* __this, MethodInfo* method), "A
DO_APP_FUNC(void, MeetingHud_Close, (MeetingHud* __this, MethodInfo* method), "Assembly-CSharp, System.Void MeetingHud::Close()");
DO_APP_FUNC(void, MeetingHud_Update, (MeetingHud* __this, MethodInfo* method), "Assembly-CSharp, System.Void MeetingHud::Update()");
DO_APP_FUNC(void, MeetingHud_BloopAVoteIcon, (MeetingHud* __this, GameData_PlayerInfo* voterPlayer, int index, Transform* parent, MethodInfo* method), "Assembly-CSharp, System.Void MeetingHud::BloopAVoteIcon(GameData.PlayerInfo, System.Int32, UnityEngine.Transform)");
DO_APP_FUNC(void, MeetingHud_PopulateResults, (MeetingHud* __this, void* states, MethodInfo* method), "Assembly-CSharp, System.Void MeetingHud::PopulateResults(MeetingHud.VoterState[])");
DO_APP_FUNC(void, MeetingHud_PopulateResults, (MeetingHud* __this, Il2CppArraySize* states, MethodInfo* method), "Assembly-CSharp, System.Void MeetingHud::PopulateResults(MeetingHud.VoterState[])");

DO_APP_FUNC(void, MovingPlatformBehaviour_SetSide, (MovingPlatformBehaviour* __this, bool isLeft, MethodInfo* method), "Assembly-CSharp, System.Void MovingPlatformBehaviour::SetSide(System.Boolean)");

Expand Down Expand Up @@ -108,6 +108,8 @@ DO_APP_FUNC(void, PlayerControl_RpcSetNamePlate, (PlayerControl* __this, String*
DO_APP_FUNC(bool, PlayerControl_RpcSendChat, (PlayerControl* __this, String* message, MethodInfo* method), "Assembly-CSharp, System.Boolean PlayerControl::RpcSendChat(System.String)");
DO_APP_FUNC(void, PlayerControl_Shapeshift, (PlayerControl* __this, PlayerControl* target, bool animate, MethodInfo* method), "Assembly-CSharp, System.Void PlayerControl::Shapeshift(PlayerControl, System.Boolean)");
DO_APP_FUNC(void, PlayerControl_ProtectPlayer, (PlayerControl* __this, PlayerControl* target, int32_t colorId, MethodInfo* method), "Assembly-CSharp, System.Void PlayerControl::ProtectPlayer(PlayerControl, System.Int32)");
DO_APP_FUNC(void, PlayerControl_SetPlayerMaterialColors_1, (int32_t colorId, Renderer* rend, MethodInfo* method), "Assembly-CSharp, System.Void PlayerControl::SetPlayerMaterialColors(System.Int32, UnityEngine.Renderer)");
DO_APP_FUNC(void, PlayerControl_SetPlayerMaterialColors_2, (Color color, Renderer* rend, MethodInfo* method), "Assembly-CSharp, System.Void PlayerControl::SetPlayerMaterialColors(UnityEngine.Color, UnityEngine.Renderer)");

DO_APP_FUNC(void, PolusShipStatus_OnEnable, (PolusShipStatus* __this, MethodInfo* method), "Assembly-CSharp, System.Void PolusShipStatus::OnEnable()");

Expand Down
7 changes: 7 additions & 0 deletions gui/tabs/self_tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "state.hpp"
#include "logger.h"

extern void RevealAnonymousVotes(); // in MeetingHud.cpp

namespace SelfTab {
void _SeeProtect();
void Render() {
Expand Down Expand Up @@ -65,6 +67,11 @@ namespace SelfTab {
if (ImGui::Checkbox("Reveal Votes", &State.RevealVotes)) {
State.Save();
}
ImGui::SameLine();
if (ImGui::Checkbox("Reveal Anonymous Votes", &State.RevealAnonymousVotes)) {
State.Save();
RevealAnonymousVotes();
}

if (ImGui::Checkbox("See Ghosts", &State.ShowGhosts)) {
State.Save();
Expand Down
101 changes: 79 additions & 22 deletions hooks/MeetingHud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <chrono>

static app::Type* voteSpreaderType;
constexpr Settings::VotedFor HasNotVoted = 255, MissedVote = 254, SkippedVote = 253, DeadVote = 252;

void dMeetingHud_Awake(MeetingHud* __this, MethodInfo* method) {
State.voteMonitor.clear();
Expand Down Expand Up @@ -40,20 +41,75 @@ static void Transform_RemoveAllVotes(app::Transform* transform) {
votes.clear();
}

void dMeetingHud_PopulateResults(MeetingHud* __this, void* states, MethodInfo* method) {
// remove all votes before populating results
do {
for (auto votedForArea : il2cpp::Array(__this->fields.playerStates)) {
auto transform = app::Component_get_transform((app::Component_1*)votedForArea, nullptr);
Transform_RemoveAllVotes(transform);
static void Transform_RevealAnonymousVotes(app::Transform* transform, Settings::VotedFor votedFor) {
if (!transform) return;
auto voteSpreader = (VoteSpreader*)app::Component_GetComponent((app::Component_1*)transform, voteSpreaderType, nullptr);
if (!voteSpreader) return;
auto votes = il2cpp::List(voteSpreader->fields.Votes);
if (State.RevealAnonymousVotes) {
size_t idx = 0;
for (auto& pair : State.voteMonitor) {
if (pair.second == votedFor) {
if (idx >= votes.size()) {
STREAM_ERROR("votedFor " << +votedFor << ", index " << idx << ", expected less than " << votes.size());
break;
}
auto outfit = GetPlayerOutfit(GetPlayerDataById(pair.first));
if (!outfit)
continue;
auto ColorId = outfit->fields.ColorId;
auto spriteRenderer = votes[idx++];
app::PlayerControl_SetPlayerMaterialColors_1(ColorId, (app::Renderer*)spriteRenderer, nullptr);
}
}
if (__this->fields.SkippedVoting) {
auto transform = app::GameObject_get_transform(__this->fields.SkippedVoting, nullptr);
Transform_RemoveAllVotes(transform);
}
else {
for (auto spriteRenderer : votes) {
app::PlayerControl_SetPlayerMaterialColors_2(
app::Palette__TypeInfo->static_fields->DisabledGrey,
(app::Renderer*)spriteRenderer, nullptr);
}
} while (false);
}
}

void dMeetingHud_PopulateResults(MeetingHud* __this, Il2CppArraySize* states, MethodInfo* method) {
// remove all votes before populating results
for (auto votedForArea : il2cpp::Array(__this->fields.playerStates)) {
auto transform = app::Component_get_transform((app::Component_1*)votedForArea, nullptr);
Transform_RemoveAllVotes(transform);
}
if (__this->fields.SkippedVoting) {
auto transform = app::GameObject_get_transform(__this->fields.SkippedVoting, nullptr);
Transform_RemoveAllVotes(transform);
}

MeetingHud_PopulateResults(__this, states, method);
auto prevAnonymousVotes = (*Game::pGameOptionsData)->fields.AnonymousVotes;
if (prevAnonymousVotes && State.RevealAnonymousVotes)
(*Game::pGameOptionsData)->fields.AnonymousVotes = false;
__try {
MeetingHud_PopulateResults(__this, states, method);
}
__finally {
(*Game::pGameOptionsData)->fields.AnonymousVotes = prevAnonymousVotes;
}
}

void RevealAnonymousVotes() {
if (!State.InMeeting
|| !app::MeetingHud__TypeInfo
|| !app::MeetingHud__TypeInfo->static_fields->Instance
|| !(*Game::pGameOptionsData)->fields.AnonymousVotes)
return;
auto meetingHud = app::MeetingHud__TypeInfo->static_fields->Instance;
for (auto votedForArea : il2cpp::Array(meetingHud->fields.playerStates)) {
if (!votedForArea) continue;
auto transform = app::Component_get_transform((app::Component_1*)votedForArea, nullptr);
Transform_RevealAnonymousVotes(transform, votedForArea->fields.TargetPlayerId);
}
if (meetingHud->fields.SkippedVoting) {
auto transform = app::GameObject_get_transform(meetingHud->fields.SkippedVoting, nullptr);
Transform_RevealAnonymousVotes(transform, SkippedVote);
}
}

void dMeetingHud_Update(MeetingHud* __this, MethodInfo* method) {
Expand Down Expand Up @@ -91,10 +147,10 @@ void dMeetingHud_Update(MeetingHud* __this, MethodInfo* method) {

if (playerVoteArea && playerData)
{
bool didVote = (playerVoteArea->fields.VotedFor != 0xFF);
bool didVote = (playerVoteArea->fields.VotedFor != HasNotVoted);
// We are goign to check to see if they voted, then we are going to check to see who they voted for, finally we are going to check to see if we already recorded a vote for them
// votedFor will either contain the id of the person they voted for, -1 if they skipped, or -2 if they didn't vote. We don't want to record people who didn't vote
if (isVotingState && didVote && playerVoteArea->fields.VotedFor != -2 && State.voteMonitor.find(playerData->fields.PlayerId) == State.voteMonitor.end())
// votedFor will either contain the id of the person they voted for, 254 if they missed, or 255 if they didn't vote. We don't want to record people who didn't vote
if (isVotingState && didVote && playerVoteArea->fields.VotedFor != MissedVote && State.voteMonitor.find(playerData->fields.PlayerId) == State.voteMonitor.end())
{
std::lock_guard<std::mutex> replayLock(Replay::replayEventMutex);
State.rawEvents.push_back(std::make_unique<CastVoteEvent>(GetEventPlayer(playerData).value(), GetEventPlayer(GetPlayerDataById(playerVoteArea->fields.VotedFor))));
Expand All @@ -104,9 +160,10 @@ void dMeetingHud_Update(MeetingHud* __this, MethodInfo* method) {

// avoid duplicate votes
if (__this->fields.state < app::MeetingHud_VoteStates__Enum::Results) {
//auto isAnonymousVotes = (*Game::pGameOptionsData)->fields.AnonymousVotes;
//(*Game::pGameOptionsData)->fields.AnonymousVotes = false;
if (playerVoteArea->fields.VotedFor != 253) {
auto prevAnonymousVotes = (*Game::pGameOptionsData)->fields.AnonymousVotes;
if (prevAnonymousVotes && State.RevealAnonymousVotes)
(*Game::pGameOptionsData)->fields.AnonymousVotes = false;
if (playerVoteArea->fields.VotedFor != SkippedVote) {
for (auto votedForArea : playerStates) {
if (votedForArea->fields.TargetPlayerId == playerVoteArea->fields.VotedFor) {
auto transform = app::Component_get_transform((app::Component_1*)votedForArea, nullptr);
Expand All @@ -119,18 +176,18 @@ void dMeetingHud_Update(MeetingHud* __this, MethodInfo* method) {
auto transform = app::GameObject_get_transform(__this->fields.SkippedVoting, nullptr);
MeetingHud_BloopAVoteIcon(__this, playerData, 0, transform, nullptr);
}
//(*Game::pGameOptionsData)->fields.AnonymousVotes = isAnonymousVotes;
(*Game::pGameOptionsData)->fields.AnonymousVotes = prevAnonymousVotes;
}
}
else if (!didVote && State.voteMonitor.find(playerData->fields.PlayerId) != State.voteMonitor.end())
{
auto it = State.voteMonitor.find(playerData->fields.PlayerId);
auto votedFor = it->second;
auto dcPlayer = it->second;
State.voteMonitor.erase(it); //Likely disconnected player

// Remove all votes for disconnected player
for (auto votedForArea : playerStates) {
if (votedForArea->fields.TargetPlayerId == votedFor) {
if (votedForArea->fields.TargetPlayerId == dcPlayer) {
auto transform = app::Component_get_transform((app::Component_1*)votedForArea, nullptr);
Transform_RemoveAllVotes(transform);
break;
Expand Down Expand Up @@ -159,8 +216,8 @@ void dMeetingHud_Update(MeetingHud* __this, MethodInfo* method) {

if (__this->fields.SkippedVoting) {
bool showSkipped = false;
for (auto pair : State.voteMonitor) {
if (pair.second == 253) {
for (const auto& pair : State.voteMonitor) {
if (pair.second == SkippedVote) {
showSkipped = State.RevealVotes;
break;
}
Expand Down
2 changes: 1 addition & 1 deletion hooks/_hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ void dScreenJoystick_FixedUpdate(ScreenJoystick* __this, MethodInfo* method);
void dMeetingHud_Awake(MeetingHud* __this, MethodInfo* method);
void dMeetingHud_Close(MeetingHud* __this, MethodInfo* method);
void dMeetingHud_Update(MeetingHud* __this, MethodInfo* method);
void dMeetingHud_PopulateResults(MeetingHud* __this, void* states, MethodInfo* method);
void dMeetingHud_PopulateResults(MeetingHud* __this, Il2CppArraySize* states, MethodInfo* method);
void dPlainDoor_SetDoorway(PlainDoor* __this, bool open, MethodInfo* method);
void dPlayerControl_CompleteTask(PlayerControl* __this, uint32_t idx, MethodInfo* method);
void dPlayerControl_FixedUpdate(PlayerControl* __this, MethodInfo* method);
Expand Down
3 changes: 3 additions & 0 deletions user/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ void Settings::Load() {

j.at("ShowConsole").get_to(this->ShowConsole);
j.at("ShowUnityLogs").get_to(this->ShowUnityLogs);

j.at("RevealAnonymousVotes").get_to(this->RevealAnonymousVotes);
} catch (...) {
Log.Info("Unable to load settings.json");
}
Expand Down Expand Up @@ -130,6 +132,7 @@ void Settings::Save() {
{"MoveInVent", this->MoveInVent},

{"RevealVotes", this->RevealVotes},
{"RevealAnonymousVotes", this->RevealAnonymousVotes},
{"AdjustByDPI", this->AdjustByDPI},
{"ShowProtections", this->ShowProtections},

Expand Down
5 changes: 4 additions & 1 deletion user/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class Settings {
std::mutex protectMutex;

bool RevealVotes = false;
bool RevealAnonymousVotes = false;

bool RevealRoles = false;
bool AbbreviatedRoleNames = false;
Expand Down Expand Up @@ -113,7 +114,9 @@ class Settings {
bool Replay_IsPlaying = true;
bool Replay_IsLive = true;

std::map<uint8_t, uint8_t> voteMonitor;
using Voter = uint8_t;
using VotedFor = uint8_t;
std::map<Voter, VotedFor> voteMonitor;

std::vector<int32_t> aumUsers;
int32_t rpcCooldown = 15;
Expand Down

0 comments on commit ed84685

Please sign in to comment.