Raised This Month: $51 Target: $400
 12% 

TF2 Vote Usermessages


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 05-24-2011 , 20:27   TF2 Vote Usermessages
Reply With Quote #1

This is a continuation of something Afronanny and I were discussing in the Game Data thread

He informed me of 5 Usermessages:

Code:
VoteStart
    - Byte
    - Byte
    - String
    - String
    - Bool


VoteSetup
    - Byte
    * String (multiple strings, presumably the vote options. put "  (Disabled)" without the quotes after the option text to disable one of  the options?)


VotePass
    - Byte
    - String
    - String

CallVoteFailed
    - Byte
    - Short

VoteFailed
    - Byte
    - Byte
I've done some investigating via a simple plugin I wrote.

My first discovery was that the VoteSetup UserMessage event isn't for setting up a vote menu, but rather for displaying the main Vote menu.

Specifically, when I used a callvote, it returned this:
Code:
VoteSetup usermessage:
Byte = 5
String = Kick
String = RestartGame
String = ChangeLevel
String = NextLevel
String = ScrambleTeams
Which just happen to be the allowed vote types on my server.

Essentially, it returned the number of elements it was going to return, then the choices.

Choosing one of the vote types on my client also yielded some interesting results. I chose Change Level. It brought up a list of maps. I did not see any usermessages with the map list, so I am unsure how it was communicated. I chose cp_gravelpit from the list.

This is what I saw:

Code:
VoteStart usermessage
Byte = 255
Byte = 1
String = #TF_vote_changelevel
String = cp_gravelpit
Bool = true
I'm not sure what the bytes mean, but every map vote I've done has had the first byte as 255. The first string is the vote type translation phrase. The second string is the map. The boolean appears to true for votes that are yes/no.

The vote passed and gave me this usermessage:
Code:
VotePass usermessage
Byte = 255
String = #TF_vote_passed_changelevel
String = cp_gravelpit
Again, this one is easy. First byte is still unknown. The first String is the vote type translation phrase. The second String is the map that won. The map changed shortly afterwards.

More complicated is the end of map vote. End of map vote shows 5 voting choices rather than a yes/no vote for one.

The end of map vote comes quite late in a map, with just 1 minute remaining. This is what I captured:

Code:
VoteStart usermessage
Byte = 255
Byte = 99
String = #TF_vote_nextlevel_choices
String =
Bool = false
Notice that the second byte has changed. The first String is clearly the vote type translation string, the second String is blank, which came as a surprise. Nevertheless, the number of bytes came out correct, so I must assume this is accurate. The boolean is false here, because it is not a yes/no vote.

This raises an interesting question, though: Where does the list of maps to vote on come from? I was under the impression that they were sent from the server, but if they are, it is on a communication method that I was not watching.

Unless the second byte (and the first?) make up some sort of bitfield that represents the maps on the server. However, I find this rather unlikely, as 48 maps would require a many more than 2 bytes.

Unfortunately, I tabbed out to capture my server logs, and didn't vote.

Not voting gave me the following usermessage:
Code:
VoteFailed usermessage
Byte: 255
Byte: 4
Again, the first byte is unknown. The second byte is likely a status code of some sort.

After changing some things around, I waited around for an end of map vote again. I got the same vote thing as earlier.

The vote passed this time:
Code:
VotePass usermessage
Byte = 255
String = #TF_vote_passed_nextlevel
String = cp_mountainlab
Just as expected.

However, I can only draw the conclusion, particularly since no custom maps appeared in the map vote, that the list of maps is done entirely on the client side. I would need to compare notes with someone else on the same server to be sure.

It's possible, then, that the boolean value to VoteStart is actually the value of the sv_vote_issue_nextlevel_choicesmode cvar when it's an nextlevel choices vote.

This is all the farther I've gotten so far. If someone has any insights, I'd love to hear them.
__________________
Not currently working on SourceMod plugin development.

Last edited by Powerlord; 05-24-2011 at 21:06.
Powerlord is offline
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 05-24-2011 , 21:29   Re: TF2 Vote Usermessages
Reply With Quote #2

I had a friend help me do tests. We both waited until the map vote menu showed, then took screenshots.

What we found is that we had the same exact list of maps. So, somehow, the server is transmitting the list, but we aren't sure how.

I attached the two screenshots as proof.
Attached Thumbnails
Click image for larger version

Name:	IJ map vote list.jpg
Views:	894
Size:	64.0 KB
ID:	86588   Click image for larger version

Name:	Powerlord map vote list.jpg
Views:	1391
Size:	84.5 KB
ID:	86589  
__________________
Not currently working on SourceMod plugin development.

Last edited by Powerlord; 05-24-2011 at 21:35.
Powerlord is offline
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 05-24-2011 , 23:19   Re: TF2 Vote Usermessages
Reply With Quote #3

I still haven't discovered where the maplist is coming from, but I have discovered that, to vote in the end of round vote, the F1-F5 keys run the command vote option1 through vote option5 respectively.

The vote command appears to unhook itself when the vote completes.

No other commands are called before VoteStart, so it must be being passed through an event or usermessage.
__________________
Not currently working on SourceMod plugin development.
Powerlord is offline
Mecha the Slag
Veteran Member
Join Date: Jun 2009
Location: Denmark
Old 05-25-2011 , 02:27   Re: TF2 Vote Usermessages
Reply With Quote #4

Keep up the research! This is super interesting
__________________
Mecha the Slag is offline
Monkeys
Veteran Member
Join Date: Jan 2010
Old 05-25-2011 , 03:29   Re: TF2 Vote Usermessages
Reply With Quote #5

Are you sure the maplist is accompanied by the vote? Might be the maplist is sent on connect, after which the client simply calculates the vote, or at least queries the maplist another way.
__________________
Get a lid on that zombie,
he's never gonna be alri-i-ight.
Oooh get a lid on that zombie,
or he's gonna feed all night.
Monkeys is offline
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 05-25-2011 , 08:36   Re: TF2 Vote Usermessages
Reply With Quote #6

Quote:
Originally Posted by Monkeys View Post
Are you sure the maplist is accompanied by the vote? Might be the maplist is sent on connect, after which the client simply calculates the vote, or at least queries the maplist another way.
Strangely, I know this isn't the case because of a mistake I made.

I screwed up my CommandListener (activated via AddCommandListener at the end of the StartVote usermessage handler) and forgot to return Plugin_Continue... and the vote screen instead came up blank... but hitting F2 still chose a map (since it just sends "vote choice2" to the server when I hit F2)

The reason it has to be sent near when the vote takes place is the existence of the sv_vote_issue_nextlevel_choicesmode cvar, which affects the map list.

Anyway, the source code for my test plugin (or at least the last version I was using) is attached. I think the CommandListener is commented out at the moment.

Side note: RegConsoleCmd("vote", ...) did NOT work. I suspect this command is bound by TF2 only between VoteStart and VoteFailed/VoteSuccess messages. a CommandListener on it will likely work considerably better.

Edit: I'll clean up the code to that soon. The logic for VoteSetup is buggy (should have used new on that array), etc...
Attached Files
File Type: sp Get Plugin or Get Source (vote_message_test.sp - 774 views - 4.3 KB)
__________________
Not currently working on SourceMod plugin development.

Last edited by Powerlord; 05-25-2011 at 11:21.
Powerlord is offline
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 05-25-2011 , 21:08   Re: TF2 Vote Usermessages
Reply With Quote #7

I just tried sending a usermessage to all clients with the same parameters that Valve sends. It just brings up a blank vote panel... of the wrong type as it has Yes/No buttons showing. See the attached image.

This is my log:
L 05/25/2011 - 20:48:28: [vote_test.smx] Vote details. id: 44, player count: 1,reliable: 1, init: 0
L 05/25/2011 - 20:48:28: [vote_test.smx] Vote start arguments (31 bytes) were: 255, 99, #TF_vote_nextlevel_choices, , 0

Note: the built-in map vote had already executed on this map, and my new plugin logged this information:
L 05/25/2011 - 20:44:50: [vote_test.smx] Vote details. id: 44, player count: 1,reliable: 1, init: 0
L 05/25/2011 - 20:44:50: [vote_test.smx] Vote start arguments (31 bytes) were: 255, 99, #TF_vote_nextlevel_choices, , 0

As you can see, both are the same.

I have two things to try next before I next report in:
1. Try my custom vote before the built-in one fires.
2. Check to see if certain other usermessages are being sent, such as HudNotify or HudNotifyCustom.

Edit: Tried #1. See the second attachment for what I got.
Attached Thumbnails
Click image for larger version

Name:	2011-05-25_00001.jpg
Views:	614
Size:	86.1 KB
ID:	86635   Click image for larger version

Name:	2011-05-25_00002.jpg
Views:	557
Size:	88.4 KB
ID:	86639  
__________________
Not currently working on SourceMod plugin development.

Last edited by Powerlord; 05-25-2011 at 21:17.
Powerlord is offline
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 05-25-2011 , 23:00   Re: TF2 Vote Usermessages
Reply With Quote #8

More new information. If I duplicate the end of map vote after the start of a new map, it will bring up a map vote with the same maps that the builtin vote used during the last map.

I hooked all 55 TF2 events (0-54). None of them fire directly before or after VoteStart fires.

However TF2 is passing the map lists to the client isn't through a UserMessage.

This makes me wonder if it's being passed through a series of events or if there is some other way (file download?) that this is taking place.
__________________
Not currently working on SourceMod plugin development.
Powerlord is offline
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 05-25-2011 , 23:35   Re: TF2 Vote Usermessages
Reply With Quote #9

Afronanny said that the last value for VoteStart was a Bool. However, I've noticed that reading from it as a Byte instead of a Bool gives me a number that changes each map.

Of course, this could just be junk data; I have no way of knowing.
On one map, it gave me 108, on the next 116, then 108 again on a third map. I'm not sure if this is relevant or not.

The data structure for VoteStart is 31 bytes long. Of those, for a map end vote, the first two bytes are always 255 and 99, followed by a 27-byte string (26 characters plus null terminator) and a 1 byte string (null terminator). This leaves just the last byte that may or may not change.

Sadly, it's time for bed for me, so no more updates tonight. Tomorrow after work I get to start in searching through events and trying to figure out if that last byte means something.
__________________
Not currently working on SourceMod plugin development.

Last edited by Powerlord; 05-26-2011 at 00:19.
Powerlord is offline
Powerlord
AlliedModders Donor
Join Date: Jun 2008
Location: Seduce Me!
Old 05-26-2011 , 01:31   Re: TF2 Vote Usermessages
Reply With Quote #10

Wow, I'm up much later than expected.

I think I made a breakthrough, but I don't really have time to check.

I was looking around at other ways of passing data in TF2, when I ran across some references to Entities.

Well, I did a sm_dump_netprops and took a quick look through it... It turns out that there's a CVoteController entity.

This is from the netprops dump:
Code:
CVoteController:
 Sub-Class Table (1 Deep): DT_VoteController
  Sub-Class Table (2 Deep): DT_BaseEntity
   Sub-Class Table (3 Deep): DT_AnimTimeMustBeFirst
   -Member: m_flAnimTime (offset 132) (type integer) (bits 8)
  -Member: m_flSimulationTime (offset 136) (type integer) (bits 8)
  -Member: m_vecOrigin (offset 740) (type vector) (bits 0)
  -Member: m_ubInterpolationFrame (offset 140) (type integer) (bits 2)
  -Member: m_nModelIndex (offset 122) (type integer) (bits 12)
   Sub-Class Table (3 Deep): DT_CollisionProperty
   -Member: m_vecMins (offset 8) (type vector) (bits 0)
   -Member: m_vecMaxs (offset 20) (type vector) (bits 0)
   -Member: m_nSolidType (offset 41) (type integer) (bits 3)
   -Member: m_usSolidFlags (offset 36) (type integer) (bits 10)
   -Member: m_nSurroundType (offset 40) (type integer) (bits 3)
   -Member: m_triggerBloat (offset 42) (type integer) (bits 8)
   -Member: m_vecSpecifiedSurroundingMins (offset 44) (type vector) (bits 0)
   -Member: m_vecSpecifiedSurroundingMaxs (offset 56) (type vector) (bits 0)
  -Member: m_nRenderFX (offset 120) (type integer) (bits 8)
  -Member: m_nRenderMode (offset 121) (type integer) (bits 8)
  -Member: m_fEffects (offset 204) (type integer) (bits 10)
  -Member: m_clrRender (offset 124) (type integer) (bits 32)
  -Member: m_iTeamNum (offset 464) (type integer) (bits 6)
  -Member: m_CollisionGroup (offset 444) (type integer) (bits 5)
  -Member: m_flElasticity (offset 584) (type float) (bits 0)
  -Member: m_flShadowCastDistance (offset 452) (type float) (bits 12)
  -Member: m_hOwnerEntity (offset 436) (type integer) (bits 21)
  -Member: m_hEffectEntity (offset 440) (type integer) (bits 21)
  -Member: moveparent (offset 332) (type integer) (bits 21)
  -Member: m_iParentAttachment (offset 329) (type integer) (bits 6)
  -Member: movetype (offset 330) (type integer) (bits 4)
  -Member: movecollide (offset 331) (type integer) (bits 3)
  -Member: m_angRotation (offset 752) (type vector) (bits 13)
  -Member: m_iTextureFrameIndex (offset 628) (type integer) (bits 8)
   Sub-Class Table (3 Deep): DT_PredictableId
   -Member: m_PredictableID (offset 148) (type integer) (bits 31)
   -Member: m_bIsPlayerSimulated (offset 780) (type integer) (bits 1)
  -Member: m_bSimulatedEveryTick (offset 629) (type integer) (bits 1)
  -Member: m_bAnimatedEveryTick (offset 630) (type integer) (bits 1)
  -Member: m_bAlternateSorting (offset 631) (type integer) (bits 1)
 -Member: m_iActiveIssueIndex (offset 792) (type integer) (bits 32)
 -Member: m_iOnlyTeamToVote (offset 796) (type integer) (bits 32)
  Sub-Class Table (2 Deep): m_nVoteOptionCount
  -Member: 000 (offset 0) (type integer) (bits 8)
  -Member: 001 (offset 4) (type integer) (bits 8)
  -Member: 002 (offset 8) (type integer) (bits 8)
  -Member: 003 (offset 12) (type integer) (bits 8)
  -Member: 004 (offset 16) (type integer) (bits 8)
 -Member: m_nPotentialVotes (offset 820) (type integer) (bits 32)
 -Member: m_bIsYesNoVote (offset 824) (type integer) (bits 1)
I have no idea how to manipulate entities. I guess it's time to learn!

Most of these don't look that interesting, but there's a few interesting things in there, such as m_nVoteOptionCount and its children.
__________________
Not currently working on SourceMod plugin development.

Last edited by Powerlord; 05-26-2011 at 01:33.
Powerlord is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 19:27.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode