Skip to content
This repository has been archived by the owner on Oct 10, 2024. It is now read-only.

Commit

Permalink
#260: Reveal Votes (#317)
Browse files Browse the repository at this point in the history
* #260: Reveal Votes

* avoid duplicate votes
  • Loading branch information
cddjr authored Mar 30, 2022
1 parent db7d328 commit b99ea4e
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 7 deletions.
7 changes: 7 additions & 0 deletions appdata/il2cpp-functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ DO_APP_FUNC(Type*, Type_GetType, (String* typeName, MethodInfo* method), "mscorl

DO_APP_FUNC(GameObject*, Component_get_gameObject, (Component_1* __this, MethodInfo* method), "UnityEngine.CoreModule, UnityEngine.GameObject UnityEngine.Component::get_gameObject()");
DO_APP_FUNC(Transform*, Component_get_transform, (Component_1* __this, MethodInfo* method), "UnityEngine.CoreModule, UnityEngine.Transform UnityEngine.Component::get_transform()");

DO_APP_FUNC(void, Object_DestroyImmediate, (Object_1* obj, MethodInfo* method), "UnityEngine.CoreModule, System.Void UnityEngine.Object::DestroyImmediate(UnityEngine.Object)");
DO_APP_FUNC(Component_1*, Component_GetComponent, (Component_1* __this, Type* type, MethodInfo* method), "UnityEngine.CoreModule, UnityEngine.Component UnityEngine.Component::GetComponent(System.Type)");

DO_APP_FUNC(Transform*, GameObject_get_transform, (GameObject* __this, MethodInfo* method), "UnityEngine.CoreModule, UnityEngine.Transform UnityEngine.GameObject::get_transform()");
DO_APP_FUNC(String*, Component_get_tag, (Component_1* __this, MethodInfo* method), "UnityEngine.CoreModule, System.String UnityEngine.Component::get_tag()");
DO_APP_FUNC(void, GameObject_set_layer, (GameObject* __this, int32_t value, MethodInfo* method), "UnityEngine.CoreModule, System.Void UnityEngine.GameObject::set_layer(System.Int32)");
DO_APP_FUNC(int32_t, GameObject_get_layer, (GameObject* __this, MethodInfo* method), "UnityEngine.CoreModule, System.Int32 UnityEngine.GameObject::get_layer()");
Expand Down Expand Up @@ -61,6 +66,8 @@ DO_APP_FUNC(void, MainMenuManager_Start, (MainMenuManager* __this, MethodInfo* m
DO_APP_FUNC(void, MeetingHud_Awake, (MeetingHud* __this, MethodInfo* method), "Assembly-CSharp, System.Void MeetingHud::Awake()");
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, MovingPlatformBehaviour_SetSide, (MovingPlatformBehaviour* __this, bool isLeft, MethodInfo* method), "Assembly-CSharp, System.Void MovingPlatformBehaviour::SetSide(System.Boolean)");

Expand Down
59 changes: 59 additions & 0 deletions appdata/il2cpp-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -8751,6 +8751,65 @@ namespace app
};
#pragma endregion

#pragma region SpriteRenderer__Array
struct SpriteRenderer__Array
{
Il2CppObject obj;
Il2CppArrayBounds* bounds;
il2cpp_array_size_t max_length;
struct SpriteRenderer* vector[32];
};
#pragma endregion

#pragma region List_SpriteRenderer_
struct __declspec(align(4)) List_SpriteRenderer__Fields
{
struct SpriteRenderer__Array* _items;
int32_t _size;
int32_t _version;
struct Object* _syncRoot;
};

struct List_SpriteRenderer_
{
void* klass;
void* monitor;
struct List_SpriteRenderer__Fields fields;
};
#pragma endregion

#pragma region VoteSpreader
struct VoteSpreader__Fields {
struct MonoBehaviour__Fields _;
struct List_SpriteRenderer_* Votes;
void* VoteRange;
int32_t maxVotesBeforeSmoosh;
float CounterY;
float adjustRate;
};

struct VoteSpreader {
struct VoteSpreader__Class* klass;
void* monitor;
struct VoteSpreader__Fields fields;
};

struct VoteSpreader__VTable {
VirtualInvokeData Equals;
VirtualInvokeData Finalize;
VirtualInvokeData GetHashCode;
VirtualInvokeData ToString;
};

struct VoteSpreader__Class {
Il2CppClass_0 _0;
void* static_fields;
const Il2CppRGCTXData* rgctx_data;
Il2CppClass_1 _1;
struct VoteSpreader__VTable vtable;
};
#pragma endregion

#pragma region MeetingHud

#if defined(_CPLUSPLUS_)
Expand Down
4 changes: 4 additions & 0 deletions gui/tabs/self_tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ namespace SelfTab {
State.Save();
}

if (ImGui::Checkbox("Reveal Votes", &State.RevealVotes)) {
State.Save();
}

if (ImGui::Checkbox("See Ghosts", &State.ShowGhosts)) {
State.Save();
}
Expand Down
115 changes: 109 additions & 6 deletions hooks/MeetingHud.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@
#include "logger.h"
#include <chrono>

static app::Type* voteSpreaderType;

void dMeetingHud_Awake(MeetingHud* __this, MethodInfo* method) {
State.voteMonitor.reset();
State.voteMonitor.clear();
State.InMeeting = true;

if (!voteSpreaderType) {
voteSpreaderType = app::Type_GetType(convert_to_string(translate_type_name("VoteSpreader, Assembly-CSharp")), nullptr);
}

MeetingHud_Awake(__this, method);
}

Expand All @@ -23,6 +29,38 @@ void dMeetingHud_Close(MeetingHud* __this, MethodInfo* method) {
MeetingHud_Close(__this, method);
}

static void Transform_RemoveAllVotes(app::Transform* transform) {
auto voteSpreader = (VoteSpreader*)app::Component_GetComponent((app::Component_1*)transform, voteSpreaderType, nullptr);
if (!voteSpreader) return;
auto votes = voteSpreader->fields.Votes;
if (votes->fields._size == 0) return;
for (size_t j = 0; j < votes->fields._size; j++) {
auto spriteRenderer = votes->fields._items->vector[j];
app::Object_DestroyImmediate((app::Object_1*)spriteRenderer, nullptr);
}
//TODO: List_Clear
votes->fields._size = 0;
votes->fields._version++;
}

void dMeetingHud_PopulateResults(MeetingHud* __this, void* states, MethodInfo* method) {
// remove all votes before populating results
do {
PlayerVoteArea__Array* playerStates = __this->fields.playerStates;
for (size_t i = 0; i < playerStates->max_length; i++) {
auto votedForArea = playerStates->vector[i];
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);
}
} while (false);

MeetingHud_PopulateResults(__this, states, method);
}

void dMeetingHud_Update(MeetingHud* __this, MethodInfo* method) {
PlayerVoteArea__Array* playerStates = __this->fields.playerStates;
for (size_t i = 0; i < playerStates->max_length; i++) {
Expand Down Expand Up @@ -61,19 +99,84 @@ void dMeetingHud_Update(MeetingHud* __this, MethodInfo* method) {
bool didVote = (playerVoteArea->fields.VotedFor != 0xFF);
// 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[playerData->fields.PlayerId])
if (isVotingState && didVote && playerVoteArea->fields.VotedFor != -2 && State.voteMonitor.find(playerData->fields.PlayerId) == State.voteMonitor.end())
{
State.rawEvents.push_back(std::make_unique<CastVoteEvent>(GetEventPlayer(playerData).value(), GetEventPlayer(GetPlayerDataById(playerVoteArea->fields.VotedFor))));
State.liveReplayEvents.push_back(std::make_unique<CastVoteEvent>(GetEventPlayer(playerData).value(), GetEventPlayer(GetPlayerDataById(playerVoteArea->fields.VotedFor))));
State.voteMonitor[playerData->fields.PlayerId] = true;
State.voteMonitor[playerData->fields.PlayerId] = playerVoteArea->fields.VotedFor;
STREAM_DEBUG("Id " << +playerData->fields.PlayerId << " voted for " << +playerVoteArea->fields.VotedFor);

// 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) {
for (size_t j = 0; j < playerStates->max_length; j++) {
auto votedForArea = playerStates->vector[j];
if (votedForArea->fields.TargetPlayerId == playerVoteArea->fields.VotedFor) {
auto transform = app::Component_get_transform((app::Component_1*)votedForArea, nullptr);
MeetingHud_BloopAVoteIcon(__this, playerData, 0, transform, nullptr);
break;
}
}
}
else if (__this->fields.SkippedVoting) {
auto transform = app::GameObject_get_transform(__this->fields.SkippedVoting, nullptr);
MeetingHud_BloopAVoteIcon(__this, playerData, 0, transform, nullptr);
}
//(*Game::pGameOptionsData)->fields.AnonymousVotes = isAnonymousVotes;
}
}
else if (!didVote && State.voteMonitor[playerData->fields.PlayerId])
else if (!didVote && State.voteMonitor.find(playerData->fields.PlayerId) != State.voteMonitor.end())
{
State.voteMonitor[playerData->fields.PlayerId] = false; //Likely disconnected player
auto it = State.voteMonitor.find(playerData->fields.PlayerId);
auto votedFor = it->second;
State.voteMonitor.erase(it); //Likely disconnected player

// Remove all votes for disconnected player
for (size_t i = 0; i < playerStates->max_length; i++) {
auto votedForArea = playerStates->vector[i];
if (playerStates->vector[i]->fields.TargetPlayerId == votedFor) {
auto votedForArea = playerStates->vector[i];
auto transform = app::Component_get_transform((app::Component_1*)votedForArea, nullptr);
Transform_RemoveAllVotes(transform);
break;
}
}
}
}
}


do {
bool isVotingState = __this->fields.state == app::MeetingHud_VoteStates__Enum::NotVoted
|| __this->fields.state == app::MeetingHud_VoteStates__Enum::Voted;
if (!isVotingState) {
break;
}

for (size_t i = 0; i < playerStates->max_length; i++) {
auto votedForArea = playerStates->vector[i];
auto transform = app::Component_get_transform((app::Component_1*)votedForArea, nullptr);
auto voteSpreader = (VoteSpreader*)app::Component_GetComponent((app::Component_1*)transform, voteSpreaderType, nullptr);
if (!voteSpreader) continue;
auto votes = voteSpreader->fields.Votes;
for (size_t j = 0; j < votes->fields._size; j++) {
auto spriteRenderer = votes->fields._items->vector[j];
auto gameObject = app::Component_get_gameObject((app::Component_1*)spriteRenderer, nullptr);
app::GameObject_SetActive(gameObject, State.RevealVotes, nullptr);
}
}

if (__this->fields.SkippedVoting) {
bool showSkipped = false;
for (auto pair : State.voteMonitor) {
if (pair.second == 253) {
showSkipped = State.RevealVotes;
break;
}
}
app::GameObject_SetActive(__this->fields.SkippedVoting, showSkipped, nullptr);
}
} while (false);
MeetingHud_Update(__this, method);
}
2 changes: 2 additions & 0 deletions hooks/_hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ void DetourInitilization() {
HOOKFUNC(PlayerControl_Shapeshift);
HOOKFUNC(PlayerControl_ProtectPlayer);
HOOKFUNC(MeetingHud_Update);
HOOKFUNC(MeetingHud_PopulateResults);
HOOKFUNC(ShipStatus_CalculateLightRadius);
HOOKFUNC(AirshipStatus_CalculateLightRadius);
HOOKFUNC(ShipStatus_OnEnable);
Expand Down Expand Up @@ -151,6 +152,7 @@ void DetourUninitialization()
UNHOOKFUNC(PlayerControl_Shapeshift);
UNHOOKFUNC(PlayerControl_ProtectPlayer);
UNHOOKFUNC(MeetingHud_Update);
UNHOOKFUNC(MeetingHud_PopulateResults);
UNHOOKFUNC(AirshipStatus_CalculateLightRadius);
UNHOOKFUNC(ShipStatus_CalculateLightRadius);
UNHOOKFUNC(ShipStatus_OnEnable);
Expand Down
1 change: 1 addition & 0 deletions hooks/_hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,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 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
4 changes: 4 additions & 0 deletions user/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ void Settings::Load() {
j.at("AutoOpenDoors").get_to(this->AutoOpenDoors);
j.at("MoveInVent").get_to(this->MoveInVent);

j.at("RevealVotes").get_to(this->RevealVotes);

j.at("ShowConsole").get_to(this->ShowConsole);
j.at("ShowUnityLogs").get_to(this->ShowUnityLogs);
} catch (...) {
Expand Down Expand Up @@ -124,6 +126,8 @@ void Settings::Save() {
{"AutoOpenDoors", this->AutoOpenDoors},
{"MoveInVent", this->MoveInVent},

{"RevealVotes", this->RevealVotes},

{"ShowConsole", this->ShowConsole},
{"ShowUnityLogs", this->ShowUnityLogs}
};
Expand Down
4 changes: 3 additions & 1 deletion user/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class Settings {
bool UnlockVents = false;
bool ShowGhosts = false;

bool RevealVotes = false;

bool RevealRoles = false;
bool AbbreviatedRoleNames = false;
int PrevKillDistance = 0;
Expand Down Expand Up @@ -100,7 +102,7 @@ class Settings {
bool Replay_IsPlaying = true;
bool Replay_IsLive = true;

std::bitset<0xFF> voteMonitor;
std::map<uint8_t, uint8_t> voteMonitor;

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

0 comments on commit b99ea4e

Please sign in to comment.