The fix will be implemented through Wombat's gamex wrapper.
Basically one of MOHAA's biggest issues is the collision detection with the player model & brush.
After testing several hours, here is what I have come up with.
1. Player model collision is broken in MOHAA, because the player can only walk so far into a solid object, however what bypasses this is when the client pushes against the wall & leans at the same time. This causes some unstable clipping to occur and causes certain parts to clip through walls.
2. After testing MOHAA's leaning, I know that the angle the player leans at is a float value and ranges between -16 & 16. What I also noticed is that the player doesn't lean as far as the game should want him to, instead it makes him lean a constant -16,16.
In other words regard;ess of how close to "open" space the player model is the game forces the client to lean the full amount every time.
-16 when leaning right
16 when leaning left
The value is a float value that increments from 0.00 to 16\-16.00, but the incrementation is almost instant, so the model goes from 0 to the max lean in a second if not less.
Anywho as far as fixing the leaning in MOHAA, I had to figure out where all these variables are controlled\stored.
Using a memory search program I found the following information.
Code: Select all
int leanLeft = *(int*)0x12F7150;
int leanRight = *(int*)0x12F7168;
float value1 = *(float*)0xE5C5578;
float value2 = *(float*)0xDA301B0;
float value3 = *(float*)0xE5C5598;
The other 3 variables labeled value1-value3, are the offsets where the angle is stored.
So if the client leans left then those 3 values will all be set to -16 and 16 when they lean right. If those 3 values are 0, then they aren't leaning.
You need to set all those offsets for it to work properly.
What does this mean for us?
Well my hypothesis for fixing the model collision would work like this.
-If the player is up against a wall (we can test it using the trace_t function and checking if the fraction == 1.0), we need to calculate the distance the player is from the wall.
Once we have the distance calculated we store it in aa temporary place.
Next we need to detect whether or not the player is leaning. We can do so by having 3 checks something similar to this
Code: Select all
if((gi.SendConsoleCommand("+leanleft") || (gi.SendConsoleCommand("+leanright")))
if(leanLeft != 0 || leanRight != 0)// if value is 1 we're leaning, if it's 0 we're not
{
if(value1 != 0 && value2 != 0 && value3 != 0) //when we lean it is either -16 or 16 if it's 0, we're not leaning
2. We're checking if either of the 2 offsets are = to anything other than 0.
3. We're checking to see if the 3 values that hold the lean angles are not equal to 0.
If all these 3 pass, we know the client is leaning, so at that point what we want to do is take the distance we calculated above to see how far we're from the wall and check it to see if we have 16 units of space to lean.
If the distance is less than 16, we can do 1 of 2 things.
1. make the player lean only as much as he can (so if the distance is 9 units away from the wall force it only 9)
2. Don't let the player lean at all, instead print a message on the players screen telling them that they don't have space to lean.
This will fix the mode collision issue in the game as well as fix the clipping issue that is used as a glitch for STWH.
The issue I'm running into is figuring out where to do this checking. What function? We tried ClientThink(), ClientCommand(), ClientConnect(), all of which crash the game after a few minutes.
Here is the code I'm working with:
Code: Select all
{
int clientNum;
int leanLeft = *(int*)0x12F7150;
int leanRight = *(int*)0x12F7168;
float value1 = *(float*)0xE5C5578;
float value2 = *(float*)0xDA301B0;
float value3 = *(float*)0xE5C5598;
for(int i=0; i<32 && i!=clientNum;i++)
{
if((gi.SendConsoleCommand("+leanleft") || (gi.SendConsoleCommand("+leanright")))
if(leanLeft != 0 || leanRight != 0)// if value is 1 we're leaning, if it's 0 we're not
{
if(value1 != 0 && value2 != 0 && value3 != 0) //when we lean it is either -16 or 16 if it's 0, we're not leaning
{
gi.Printf("We are definitly leaning");
}
}
}
}
}
Code: Select all
typedef struct
{
public:
int apiversion;
void (*Init) (/* unknown */);
void (*Shutdown) (/* unknown */);
void (*Cleanup) (/* unknown */);
void (*Precache) (/* unknown */);
void (*SetMap) (/* unknown */);
void (*Restart) (/* unknown */);
void (*SetTime) (/* unknown */);
void (*SpawnEntities) (/* unknown */);
char *(*ClientConnect) (/* unknown */);
void (*ClientBegin) (/* unknown */);
void (*ClientUserinfoChanged) (/* unknown */);
void (*ClientDisconnect) (/* unknown */);
void (*ClientCommand) (/* unknown */);
void (*ClientThink) (/* unknown */);
void (*BotBegin) (/* unknown */);
void (*BotThink) (/* unknown */);
void (*PrepFrame) (/* unknown */);
void (*RunFrame) (/* unknown */);
void (*ServerSpawned) (/* unknown */);
void (*RegisterSounds) (/* unknown */);
qboolean (*AllowPaused) (/* unknown */);
qboolean (*ConsoleCommand) (/* unknown */);
void (*ArchivePersistant) (/* unknown */);
void (*WriteLevel) (/* unknown */);
qboolean (*ReadLevel) (/* unknown */);
qboolean (*LevelArchiveValid) (/* unknown */);
void (*ArchiveInteger) (/* unknown */);
void (*ArchiveFloat) (/* unknown */);
void (*ArchiveString) (/* unknown */);
void (*ArchiveSvsTime) (/* unknown */);
orientation_t (*TIKI_Orientation) (/* unknown */);
void (*DebugCircle) (/* unknown */);
void (*SetFrameNumber) (/* unknown */);
void (*SoundCallback) (/* unknown */);
class prof_game_s *prof_struct;
struct gentity_s *gentities;
int gentitySize;
int num_entities;
int max_entities;
char *error_message;
} game_export_t;



