mirror of
https://github.com/mumble-voip/mumble.git
synced 2025-10-26 11:19:16 +00:00
Merge PR #2248: Fix Left 4 Dead 2 plugin and clean up plugin code
This commit is contained in:
commit
c8d136febc
@ -1,3 +1,8 @@
|
||||
// Copyright 2005-2016 The Mumble Developers. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file at the root of the
|
||||
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
|
||||
|
||||
/* Copyright (C) 2005-2012, Thorvald Natvig <thorvald@natvig.com>
|
||||
Copyright (C) 2012, dark_skeleton (d-rez) <dark.skeleton@gmail.com>
|
||||
|
||||
@ -31,48 +36,29 @@
|
||||
|
||||
#include "../mumble_plugin_win32.h"
|
||||
|
||||
/* DESCRIPTION ADDRESS TYPE VALUE
|
||||
|
||||
position tuple: client.dll+0x774B40 float (x, y, z location in inches)
|
||||
front tuple: client.dll+0x774BA0 float (x, y, z as unit vector in direction you are facing)
|
||||
top tuple: client.dll+0x774BD0 float (x, y, z as unit vector pointing out top of head)
|
||||
state: client.dll+0x772ACC byte (0 in menu; non-zero in game)
|
||||
context: client.dll+0x772ACC str (see context support below for its possible values)
|
||||
*/
|
||||
|
||||
static BYTE *posptr;
|
||||
static BYTE *rotptr;
|
||||
static BYTE *frontptr;
|
||||
static BYTE *topptr;
|
||||
static BYTE *stateptr;
|
||||
static BYTE *contextptr;
|
||||
|
||||
static bool calcout(float *pos, float *rot, float *opos, float *front, float *top) {
|
||||
float h = rot[0];
|
||||
float v = rot[1];
|
||||
|
||||
if ((v < -180.0f) || (v > 180.0f) || (h < -180.0f) || (h > 180.0f))
|
||||
return false;
|
||||
|
||||
h *= static_cast<float>(M_PI / 180.0f);
|
||||
v *= static_cast<float>(M_PI / 180.0f);
|
||||
|
||||
// Seems L4D is in inches. INCHES?!?
|
||||
opos[0] = pos[0] / 39.37f;
|
||||
opos[1] = pos[2] / 39.37f;
|
||||
opos[2] = pos[1] / 39.37f;
|
||||
|
||||
front[0] = cos(v) * cos(h);
|
||||
front[1] = -sin(h);
|
||||
front[2] = sin(v) * cos(h);
|
||||
|
||||
h -= static_cast<float>(M_PI / 2.0f);
|
||||
|
||||
top[0] = cos(v) * cos(h);
|
||||
top[1] = -sin(h);
|
||||
top[2] = sin(v) * cos(h);
|
||||
/*
|
||||
printf("Poll\n");
|
||||
printf("%f %f %f : %f %f\n",pos[0],pos[1],pos[2], rot[0], rot[1]);
|
||||
printf("%f %f %f :: %.2f %.2f %.2f :: %.2f %.2f %.2f\n", opos[0], opos[1], opos[2], front[0], front[1], front[2], top[0], top[1], top[2]);
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, float *camera_pos, float *camera_front, float *camera_top, std::string &context, std::wstring &/*identity*/);
|
||||
|
||||
static int trylock(const std::multimap<std::wstring, unsigned long long int> &pids) {
|
||||
posptr = rotptr = stateptr = contextptr = NULL;
|
||||
posptr = frontptr = topptr = stateptr = contextptr = NULL;
|
||||
|
||||
if (! initialize(pids, L"left4dead2.exe", L"client.dll"))
|
||||
return false;
|
||||
|
||||
/*
|
||||
Some hints to make things easier next time valve updates this game:
|
||||
use Cheat Engine (non-network single player or non VAC-secured servers to be safe)
|
||||
@ -82,32 +68,24 @@ static int trylock(const std::multimap<std::wstring, unsigned long long int> &pi
|
||||
speed things up by limiting the scan range to 40000000 to 90000000 (hex number)
|
||||
you need addresses relative to client.dll. You can get address by double clicking on the address.
|
||||
|
||||
pos: float likely in a range of 0 to 10000 (changes if you move. constant if you view around)
|
||||
rot: float in range of -180 to 180. If you look up the value is -89.0 . If you look down it is 89.0 (changes if you viewaround. constant if you only move)
|
||||
state: single player: search for loopback. Go back to menu. There is likely only one instance which has the string when having a game running and empty when not running a game.
|
||||
context: same as state appearantly
|
||||
pos: float likely in a range of 0 to 10000 (changes if you move. constant if you view around.)
|
||||
front: float in range of -1 to 1. (changes if you move your camera. constant if you do not.)
|
||||
top: float in range of -1 to 1. (changes if you move your camera. constant if you do not.)
|
||||
state: single player -> search for "loopback:0"
|
||||
public game -> search for server ip "xxx.xxx.xxx.xxx:yyyyy"
|
||||
menu -> empty string ""
|
||||
context: same as state (they are used differently)
|
||||
|
||||
*/
|
||||
posptr = pModule + 0x8217D0;
|
||||
rotptr = pModule + 0x762E04;
|
||||
stateptr = pModule + 0x81CB4C;
|
||||
contextptr = pModule + 0x81CB4C;
|
||||
float apos[3], afront[3], atop[3];
|
||||
float cpos[3], cfront[3], ctop[3];
|
||||
std::string context;
|
||||
std::wstring identity;
|
||||
|
||||
float pos[3];
|
||||
float rot[3];
|
||||
char state, _context[21];
|
||||
bool ok = peekProc(posptr, pos, 12) &&
|
||||
peekProc(rotptr, rot, 12) &&
|
||||
peekProc(stateptr, &state, 1) &&
|
||||
peekProc(contextptr, _context);
|
||||
|
||||
if (ok) {
|
||||
float opos[3], top[3], front[3];
|
||||
return calcout(pos, rot, opos, top, front);
|
||||
}
|
||||
if (fetch(apos, afront, atop, cpos, cfront, ctop, context, identity))
|
||||
return true;
|
||||
|
||||
generic_unlock();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -115,60 +93,85 @@ static int fetch(float *avatar_pos, float *avatar_front, float *avatar_top, floa
|
||||
for (int i=0;i<3;i++)
|
||||
avatar_pos[i] = avatar_front[i] = avatar_top[i] = camera_pos[i] = camera_front[i] = camera_top[i] = 0.0f;
|
||||
|
||||
float ipos[3], rot[3];
|
||||
float pos[3], front[3], top[3];
|
||||
bool ok;
|
||||
char state;
|
||||
char _context[21];
|
||||
|
||||
// when valve updates the game and breaks the plugin, these following 5 addresses will need changed
|
||||
// nothing else should need to be modified
|
||||
posptr = pModule + 0x774B40;
|
||||
frontptr = pModule + 0x774BA0;
|
||||
topptr = pModule + 0x774BD0;
|
||||
stateptr = pModule + 0x772ACC;
|
||||
contextptr = pModule + 0x772ACC;
|
||||
|
||||
// stateptr returns byte values: 0 when map is not loaded; first character in hostname when map is loaded
|
||||
ok = peekProc(posptr, ipos, 12) &&
|
||||
peekProc(rotptr, rot, 12) &&
|
||||
ok = peekProc(posptr, pos, 12) &&
|
||||
peekProc(frontptr, front, 12) &&
|
||||
peekProc(topptr, top, 12) &&
|
||||
peekProc(stateptr, &state, 1) &&
|
||||
peekProc(contextptr, _context);
|
||||
|
||||
// in menu -> disable plugin
|
||||
if (state == 0) {
|
||||
context = std::string(""); // clear context
|
||||
return true; // This results in all vectors beeing zero which tells Mumble to ignore them.
|
||||
return true; // This results in all vectors being zero which tells Mumble to ignore them.
|
||||
}
|
||||
|
||||
if(!ok)
|
||||
return false;
|
||||
|
||||
// convert all vectors from right handed coordinate system to left handed coordinate system
|
||||
// L4D2 is in inches so convert to meters
|
||||
avatar_pos[0] = pos[0] / 39.37f;
|
||||
avatar_pos[1] = pos[2] / 39.37f;
|
||||
avatar_pos[2] = pos[1] / 39.37f;
|
||||
|
||||
avatar_front[0] = front[0];
|
||||
avatar_front[1] = front[2];
|
||||
avatar_front[2] = front[1];
|
||||
|
||||
avatar_top[0] = top[0];
|
||||
avatar_top[1] = top[2];
|
||||
avatar_top[2] = top[1];
|
||||
|
||||
for (int i=0;i<3;++i) {
|
||||
camera_pos[i] = avatar_pos[i];
|
||||
camera_front[i] = avatar_front[i];
|
||||
camera_top[i] = avatar_top[i];
|
||||
|
||||
if (ok) {
|
||||
int res = calcout(ipos, rot, avatar_pos, avatar_front, avatar_top);
|
||||
if (res) {
|
||||
for (int i=0;i<3;++i) {
|
||||
camera_pos[i] = avatar_pos[i];
|
||||
camera_front[i] = avatar_front[i];
|
||||
camera_top[i] = avatar_top[i];
|
||||
|
||||
// Example only -- only set these when you have sane values, and make sure they're pretty constant (every change causes a sever message).
|
||||
//context = std::string("server/map/blah");
|
||||
//identity = std::wstring(L"STEAM_1:2:3456789");
|
||||
}
|
||||
|
||||
_context[sizeof(_context) - 1] = '\0';
|
||||
std::string sHost(_context);
|
||||
// This string can be either "xxx.xxx.xxx.xxx:yyyyy" (or shorter), "loopback:0" or "" (empty) when in menus. Hence 21 size for char.
|
||||
if (!sHost.empty())
|
||||
{
|
||||
if (sHost.find("loopback") == std::string::npos)
|
||||
{
|
||||
std::ostringstream newcontext;
|
||||
newcontext << "{\"ipport\": \"" << sHost << "\"}";
|
||||
context = newcontext.str();
|
||||
}
|
||||
|
||||
}
|
||||
return res;
|
||||
// Example only -- only set these when you have sane values, and make sure they're pretty constant (every change causes a sever message).
|
||||
//context = std::string("server/map/blah");
|
||||
//identity = std::wstring(L"STEAM_1:2:3456789");
|
||||
}
|
||||
|
||||
// context support
|
||||
// used to disable positional audio when people are on different servers
|
||||
_context[sizeof(_context) - 1] = '\0';
|
||||
std::string sHost(_context);
|
||||
// this string will change depending on your context:
|
||||
// if in public game then server ip -> "xxx.xxx.xxx.xxx:yyyyy"
|
||||
// if in single player then loopback -> "loopback:0"
|
||||
// if in menu then empty -> ""
|
||||
if (!sHost.empty())
|
||||
{
|
||||
if (sHost.find("loopback") == std::string::npos)
|
||||
{
|
||||
std::ostringstream newcontext;
|
||||
newcontext << "{\"ipport\": \"" << sHost << "\"}";
|
||||
context = newcontext.str();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static const std::wstring longdesc() {
|
||||
return std::wstring(L"Supports L4D2 version 2.1.4.4 with context support. No identity support yet.");
|
||||
return std::wstring(L"Supports L4D2 version 2.1.4.5 with context support. No identity support yet.");
|
||||
}
|
||||
|
||||
static std::wstring description(L"Left 4 Dead 2 (version 2.1.4.4)");
|
||||
static std::wstring description(L"Left 4 Dead 2 (version 2.1.4.5)");
|
||||
static std::wstring shortname(L"Left 4 Dead 2");
|
||||
|
||||
static int trylock1() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user