alliedmodders / sourcemod

SourceMod - Source Engine Scripting and Administration
http://www.sourcemod.net/
985 stars 423 forks source link

Implement array element parameter on GameRules_SetPropString #1386

Closed Mart-User closed 3 years ago

Mart-User commented 3 years ago

Environment

Description

In L4D2, there is a feature called EMS (Extended Mutation System) that allows us to use some available huds (15 in total) to draw things on the screen. The netprops related to this are on CTerrorGameRules, but one of them ("m_szScriptedHUDStringSet") seems to be a string array.

Currently the "GameRules_SetPropString" function doesn't support passing an element (from array) in its parameters, unlike the others (e.g: GameRules_SetProp, GameRules_SetPropFloat)

https://sourcemod.dev/#/sdktools_gamerules/function.GameRules_SetPropString https://sm.alliedmods.net/new-api/sdktools_gamerules/GameRules_SetPropString

I'm not sure but maybe having this implementation also on GameRules_SetPropString, I could use the element parameter to set the text from the HUD [1-15].

Currently, the only way that I achieved that was by setting

  GameRules_SetPropString("m_szScriptedHUDStringSet", "some string here");

Seems that at every strlen of 128 the text goes to the next hud, but the engine has a limit of networking a strlen of 512. If I pass a higher value, the game crashes. (also, probably is the reason that in the core, the buffer is limited to strlen of 512) So, I can only set the text of 4 huds in the best scenario.

This is all the info that I got:

It all started here https://forums.alliedmods.net/showpost.php?p=2725233&postcount=14, where is mentioned that the EMS system has some netprops related to the GameRules, then I did several tests.

I was able to set most of the netprops to their specific huds but the text.

From a discord talk, according to asherkin:

looks like array support isn't there just because there were no string arrays when it was implemented the netprop dump output is odd, they don't appear to be any different than the other fixed arrays" it looks like this is just the pattern for this kind of array prop, there just really aren't that many of them (18 in l4d2) most of the array props we deal with, use something called SendPropArray3, but these use SendPropArray which looks like an older implementation that is possibly more flexible but is encoded as two props it is of course Valve, so I can't find anything explaining it https://developer.valvesoftware.com/wiki/SendPropArray3() SendPropArray3() looks like there are probably several bits of work here: 1) SDKTools' netprop dumper has no idea what to do with these props and outputs the internal impl detail 2) SM probably can't read these in any form currently (interestingly one of them is m_hViewModel on players - I wonder what that 2nd index is used for...) 3) The gamerules string prop will need array support on the upside it doesn't look like there is any sdk hackery to do, it's all covered in the public SDK heh, and pose params are one of the other ones MVM has a couple of string_t ones that will probably be hairy (m_iszMannVsMachineWaveClassNames)

Some info from netprop dump:

  Member: m_szScriptedHUDStringSet (offset 1656) (type string) (bits 0) (InsideArray)
  Member: m_szScriptedHUDStringSet (offset 0) (type array) (bits 0) ()

Which probably on SM would look like that:

  char m_szScriptedHUDStringSet[15][128];

Some info found by asherkin:

CTerrorGameRules::ResetScriptedHUD has useful info about the data layout InternalSendPropArray((int)&unk_F66154, 15, (char *)0x80, "m_szScriptedHUDStringSet", 0);

Some valve wiki related to the EMS: https://developer.valvesoftware.com/wiki/L4D2_EMS/Appendix:_HUD

Mart-User commented 3 years ago

L4D2 netprops dump

dump_netprops_20201124.txt

nosoop commented 3 years ago

The heuristics seem straightforward enough; I've written up a basic implementation here that reports the correct offset / element count / element stride: https://github.com/nosoop/sourcemod/tree/legacy-array-props

The main issue I'm seeing is that there isn't currently a way to retrieve both SendProp* instances matching that name, as each stores important details that the other does not. Not without more invasive modifications to SourceMod, anyways. This should be completely feasible with SendProp::GetArrayProp().

asherkin commented 3 years ago

I really enjoyed working on this one, thanks for the feature req @MartLegion!