mumble/plugins/gw/gw.cpp
Stefan Hacker e5c564931d Fix zero terminations.
- With wchar_t arrays
- Where it was missing
2012-07-15 14:49:36 +02:00

198 lines
6.6 KiB
C++

/* Copyright (C) 2012, dark_skeleton (d-rez) <dark.skeleton@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- Neither the name of the Mumble Developers nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "../mumble_plugin_win32.h"
static BYTE *posptr;
static BYTE *camptr;
static BYTE *frontptr;
static BYTE *camfrontptr;
static BYTE *magicptr;
static BYTE *areaptr;
static BYTE *characternameptr;
static bool calcout(float *pos, float *front, float *cam, float *camfront, float *opos, float *ofront, float *ocam, float *ocamfront) {
// Seems Guild Wars is in... inches, yeah :) ---> same as in GW2, proof here: http://www.guildwars2guru.com/topic/21519-reddit-ama-all-questions-answers (question #31)
// coordinate Y is swapped with Z
// Y is negative (looks like somewhere underground is 0.00 and land is for example -120. When we climb up a hill, it goes down (e.g. -130), and when we walk downhill, it goes up (e.g. -100)
opos[0] = pos[0] / 39.37f;
opos[1] = -pos[2] / 39.37f;
opos[2] = pos[1] / 39.37f;
ocam[0] = cam[0] / 39.37f;
ocam[1] = -cam[2] / 39.37f;
ocam[2] = cam[1] / 39.37f;
ofront[0] = front[0];
ofront[1] = -front[2];
ofront[2] = front[1];
ocamfront[0] = camfront[0];
ocamfront[1] = -camfront[2];
ocamfront[2] = camfront[1];
return true;
}
static bool refreshPointers(void)
{
// We can find all vectors (camera position, camera front, avatar position, avatar front) in just one place, yay!
camfrontptr = camptr = posptr = frontptr = magicptr = characternameptr = areaptr = NULL;
camptr = (BYTE *) 0xd551b8;
posptr = (BYTE *) 0xd551c4; // camptr + 0xC
camfrontptr = (BYTE *) 0xd551d0; // posptr + 0xC
frontptr = (BYTE *) 0xd551dc; // camfrontptr + 0xC
/* Magic Pointer: 0xa3fad8
25/26/27 when ingame (differs for cities and explorable areas/missions). I don't know how it works exactly, because sometimes it's 26 for cities and 25 for explorables, while another time it's 27 for cities and 26 for explorables. Key fact: it is different for cities and explorable areas/missions :)
0 when logged in / in character select / in loading screen
1 when not logged in (in login screen)
*/
magicptr = (BYTE *) 0xa3fad8;
/* Area Pointer: 0xd54e54
This is a 4-byte decimal stating which area we are in. Note however, that some missions have the same area assigned as cities, therefore we need our Magic Pointer to distinguish where exactly we are to specify context properly.
*/
areaptr = (BYTE *) 0xd54e54;
/* Character Name Pointer: 0xa2a440
This is a 19-characters long unicode string which contains a player's character name. This is unique for every character, but can change while ingame (players can switch characters)
*/
characternameptr = (BYTE *) 0xa2a440;
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) {
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;
bool ok;
float cam[3], pos[3], front[3], camfront[3];
char state;
int areaid;
wchar_t charactername [20];
ok = peekProc(camptr,cam) &&
peekProc(posptr,pos) &&
peekProc(camfrontptr,camfront) &&
peekProc(frontptr,front) &&
peekProc(magicptr,&state,1) &&
peekProc(areaptr,&areaid,4) &&
peekProc(characternameptr, charactername);
if (!ok)
return false;
if (state == 0 || state == 1 || areaid == 0) { // Player not in world
context.clear();
identity.clear();
return true;
}
bool res = calcout(pos, front, cam, camfront, avatar_pos, avatar_front, camera_pos, camera_front);
if (!res)
return false;
camera_top[1] = avatar_top[1] = 1; // This isn't FPS, you can't tilt your head :)
std::ostringstream _context;
_context << "{\"areaid\": " << areaid << ","
<< "\"magic\": " << int(state) << "}";
context = _context.str();
charactername[sizeof(charactername) / sizeof(charactername[0])-1] = 0; // make sure string is null-terminated
identity = std::wstring(charactername);
return true;
}
static int trylock(const std::multimap<std::wstring, unsigned long long int> &pids) {
if (! initialize(pids, L"Gw.exe"))
return false;
// unlink plugin if this fails
if (!refreshPointers()) {
generic_unlock();
return false;
}
float cam[3], pos[3], front[3], camfront[3], top[3], camtop[3];
std::string context;
std::wstring identity;
if (fetch(pos,front,top,cam,camfront,camtop,context,identity)) {
return true;
} else {
generic_unlock();
return false;
}
}
static const std::wstring longdesc() {
return std::wstring(L"Supports Guild Wars build 35,787 with context and identity support.");
}
static std::wstring description(L"Guild Wars b35787");
static std::wstring shortname(L"Guild Wars");
static int trylock1() {
return trylock(std::multimap<std::wstring, unsigned long long int>());
}
static MumblePlugin gwplug = {
MUMBLE_PLUGIN_MAGIC ^ MUMBLE_PLUGIN_MAGIC,
description,
shortname,
NULL,
NULL,
trylock1,
generic_unlock,
longdesc,
fetch
};
static MumblePlugin2 gwplug2 = {
MUMBLE_PLUGIN_MAGIC_2,
MUMBLE_PLUGIN_VERSION,
trylock
};
extern "C" __declspec(dllexport) MumblePlugin *getMumblePlugin() {
return &gwplug;
}
extern "C" __declspec(dllexport) MumblePlugin2 *getMumblePlugin2() {
return &gwplug2;
}