/* qwh - Enemy Territory: Quake Wars hack for linux http://www.nixcoders.org/ Copyright (C) 2007 - *nixCoders team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "qwh.h" DEFVFUNC(orig_idGameLocal_Draw2D, bool, (idGameLocal *this_idGameLocal)); DEFVFUNC(orig_idGameLocal_InitFromNewMap, void, (idGameLocal *this_idGameLocal, const char* mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randSeed, int startTime, bool isUserChange)); //DEFVFUNC(orig_idRenderSystem_AllocRenderWorld, idRenderWorld *, (idRenderSystem *this_idRenderSystem)); DEFVFUNC(orig_idRenderWorld_AddEntityDef, qhandle_t, (idRenderWorld *this_renderWorld, renderEntity_t *re)); Qw::Qw() { this->orig_GetGameAPI = NULL; this->gameLibHandle = NULL; // Hook system functions pltHook("dlopen", (void *)qwh_dlopen); pltHook("dlsym", (void *)qwh_dlsym); pltHook("dlclose", (void *)qwh_dlclose); // Workaround for french keyboard open console key char *envLang = getenv("LANG"); if (envLang && strstr(envLang, "fr_FR")) pltHook("SDL_PollEvent", (void *)qwh_SDL_PollEvent); } Qw::~Qw() { } void *Qw::dlopen(const char *filename, int flag) { void *handle = ::dlopen(filename, flag); LOG_DEBUG("Qw::dlopen(): " << filename << " handle:" << handle); if (!strcmp(basename(strdupa(filename)), QW_GAMELIB_NAME)) this->gameLibHandle = handle; return handle; } void *Qw::dlsym(void *handle, const char *symbol) { void *addr = ::dlsym(handle, symbol); LOG_DEBUG("Qw::dlsym(): handle:" << handle << " " << symbol << " addr:" << addr); if ((handle == this->gameLibHandle) && (!strcmp(symbol, QW_GETGAMEAPI_SYMBOL))) { this->orig_GetGameAPI = (_GetGameAPI_t *)addr; return (void *)qwh_GetGameAPI; } return addr; } int Qw::dlclose(void *handle) { int result = ::dlclose(handle); LOG_DEBUG("Qw::dlclose(): handle:" << handle << " " << result); return result; } void Qw::drawPlayersEsp() { idVec2 position; for ( int i = 0; i < MAX_CLIENTS; i++ ) { idPlayer* player = gLocal->GetClient( i ); if(i == gLocal->localClientNum) { if(player->CheckDetected(750.0f)) { deviceContext->DrawText(va( L"Detected!"), sdBounds2D(0, 45, 640, 0), DTF_CENTER | DTF_NOCLIPPING); } continue; } if ( player == NULL || player->IsInLimbo()) continue; //LOG_DEBUG(gLocal->entities[i]->GetSkin()->DefaultDefinition()); idVec3 enemy = player->GetPlayerPhysics().GetOrigin(); idVec3 enemy2 = enemy - (enemy * gLocal->GetLocalPlayer()->GetPlayerPhysics().GetGravityNormal ( )) * gLocal->GetLocalPlayer()->GetPlayerPhysics().GetGravityNormal ( ); idVec3 pos2 = gLocal->GetLocalPlayer()->GetPlayerPhysics().GetOrigin(); pos2 = pos2 - (pos2 * gLocal->GetLocalPlayer()->GetPlayerPhysics().GetGravityNormal ( )) * gLocal->GetLocalPlayer()->GetPlayerPhysics().GetGravityNormal ( ); float fdist = (enemy2 - pos2).LengthFast ( ); int fdist2 = static_cast(fdist); int size = (fdist2/1500)*6; if(size <= 8) size = 8; if(size < 20) { idVec3 coord = player->GetEyeOffset(player->eyePosition) + idVec3(0,0,10); this->w2s(gLocal->playerView.GetCurrentView(), coord, position); deviceContext->SetFontSize(size); deviceContext->SetColor(1, 1, 1, 1); //virtual void DrawText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align = 1, const int lifetime = 0) = 0; //rWorld->DrawText(va( "%s", player->userInfo.name.c_str()), player->firstPersonViewOrigin, 1.0f, idVec4(1.0f, 1.0f, 5.0f, 1.0f), gLocal->playerView.GetCurrentView().viewaxis); deviceContext->DrawText(va( L"%s", player->userInfo.name.c_str()), sdBounds2D(position.x, position.y, 0, 0), DTF_CENTER | DTF_NOCLIPPING); //deviceContext->DrawText(L"someone", sdBounds2D(position.x, position.y, 0, 0), DTF_CENTER); //LOG_DEBUG("fini"); } //idBox b = idBox( player->GetPhysics()->GetBounds(), player->GetPhysics()->GetOrigin(), gLocal->playerView.GetCurrentView().viewaxis); //player->GetPhysics()->GetAxis() ); //rWorld->DebugBox(idVec4(0.0f, 1.0f, 1.0f, 1.0f), b); // virtual void DebugBounds( const idVec4 &color, const idBounds &bounds, const idVec3 &org = vec3_origin, const idMat3& axes = mat3_identity, const int lifetime = 0 ) = 0; rWorld->DebugBounds(idVec4(0.0f, 1.0f, 1.0f, 1.0f), player->GetPhysics()->GetBounds(), player->GetPhysics()->GetOrigin(), gLocal->playerView.GetCurrentView().viewaxis); // // idVec3 org = player->GetPhysics()->GetOrigin(); // idMat3 axes = player->GetAxis(); // idBounds bounds = player->GetPhysics()->GetBounds(); // sdWorldToScreenConverter converter(gLocal->playerView.GetCurrentView()); // // sdBounds2D bracketBounds; // converter.Transform(bounds, axes, org, bracketBounds); // // idVec4 v = bracketBounds.ToVec4(); //deviceContext->DrawRect( 0, 0, SCREEN_WIDTH * 1.0f / aspectRatio, SCREEN_HEIGHT, 0.0f, 0.0f, 1.0f, 1.0f, declHolder.declMaterialType.LocalFind( "_white" ) ); //virtual void DrawRect( float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial* material, float angle = 0.0f ) = 0; //deviceContext->DrawRect(v.x, v.y, v.z, v.w, 0.0f, 0.0f, 1.0f, 1.0f, whiteMat); } } bool Qw::idGameLocal_Draw2D(idGameLocal *this_idGameLocal) { bool result = orig_idGameLocal_Draw2D(this_idGameLocal); this->drawPlayersEsp(); // Advert deviceContext->SetColor(1, 0, 0, 1); //deviceContext->DrawRect( 0, 0, SCREEN_WIDTH * 1.0f / aspectRatio, SCREEN_HEIGHT, 0.0f, 0.0f, 1.0f, 1.0f, declHolder.declMaterialType.LocalFind( "_white" ) ); deviceContext->DrawText(va( L"QWHACK! v0.1"), sdBounds2D(0, 30, 640, 0), DTF_CENTER | DTF_NOCLIPPING); return result; } void Qw::idGameLocal_InitFromNewMap(idGameLocal *this_idGameLocal, const char *mapName, idRenderWorld *renderWorld, idSoundWorld *soundWorld, bool isServer, bool isClient, int randSeed, int startTime, bool isUserChange) { LOG_DEBUG("Qw::idGameLocal_InitFromNewMap() " << rWorld); rWorld = renderWorld; HOOKVFUNC(rWorld, &idRenderWorld::AddEntityDef, orig_idRenderWorld_AddEntityDef, qwh_idRenderWorld_AddEntityDef); this->whiteMat = declHolder.declMaterialType.LocalFind( "_white" ); orig_idGameLocal_InitFromNewMap(this_idGameLocal, mapName, renderWorld, soundWorld, isServer, isClient, randSeed, startTime, isUserChange); } //virtual qhandle_t AddEntityDef( const renderEntity_t *re ) = 0; qhandle_t Qw::idRenderWorld_AddEntityDef(idRenderWorld *this_renderWorld, renderEntity_t *re) { if(!(gLocal->GetClient(re->spawnID)->GetHealth() <= 0)) { LOG_DEBUG("Not dead."); if(strstr(re->hModel->Name(), "models/characters/animations/strogg/") || strstr(re->hModel->Name(), "models/characters/animations/initial_edf/")) { if(gLocal->entities[gLocal->localClientNum]->GetEntityAllegiance(gLocal->entities[re->spawnID]) == TA_ENEMY) { LOG_DEBUG("Enemy"); re->modelDepthHack = 1.0f; re->shaderParms[ SHADERPARM_RED ] = 1.0f; re->shaderParms[ SHADERPARM_GREEN ] = 0.0f; re->shaderParms[ SHADERPARM_BLUE ] = 1.0f; re->shaderParms[ SHADERPARM_ALPHA ] = 0.5f; re->customShader = whiteMat; } else if(gLocal->entities[gLocal->localClientNum]->GetEntityAllegiance(gLocal->entities[re->spawnID]) == TA_FRIEND) { LOG_DEBUG("Friend"); re->modelDepthHack = 1.0f; re->shaderParms[ SHADERPARM_RED ] = 1.0f; re->shaderParms[ SHADERPARM_GREEN ] = 1.0f; re->shaderParms[ SHADERPARM_BLUE ] = 0.0f; re->shaderParms[ SHADERPARM_ALPHA ] = 0.5f; re->customShader = whiteMat; } } } qhandle_t qh = orig_idRenderWorld_AddEntityDef(this_renderWorld, re); return qh; } //virtual idRenderWorld * AllocRenderWorld( void ) = 0; /* idRenderWorld *Qw::idRenderSystem_AllocRenderWorld(idRenderSystem *this_idRenderSystem) { //idRenderWorld *renderWorld = orig_idRenderSystem_AllocRenderWorld(this_idRenderSystem); LOG_DEBUG("Qw::idRenderSystem_AllocRenderWorld() " << renderWorld); //if(!rWorld || rWorld == NULL) { rWorld = renderWorld; LOG_DEBUG("Qw::idRenderSystem_AllocRenderWorld() rWorld = " << renderWorld); //} return renderWorld; } */ //void sdUIRenderModel::SetRenderWorld( idRenderWorld* world ) //void gameExport_t *Qw::qw_GetGameAPI(gameImport_t *import) { gameExport_t *gameExport = this->orig_GetGameAPI(import); LOG_DEBUG("Qw::GetGameAPI(): export:" << gameExport << " import:" << import); gLocal = (idGameLocal *)gameExport->game; sys = import->sys; common = import->common; cmdSystem = import->cmdSystem; cvarSystem = import->cvarSystem; fileSystem = import->fileSystem; networkSystem = import->networkSystem; renderSystem = import->renderSystem; deviceContext = import->deviceContext; soundSystem = import->soundSystem; renderModelManager = import->renderModelManager; declManager = import->declManager; collisionModelManager = import->collisionModelManager; // bse = import->bse; networkService = import->networkService; // adManager = import->adManager; // keyInputManager = import->keyInputManager; AASFileManager = import->AASFileManager; notificationSystem = import->notificationSystem; graphManager = import->graphManager; idDict::SetGlobalPools(import->globalKeys, import->globalValues); idStr::SetStringAllocator(import->stringAllocator); idWStr::SetStringAllocator(import->wideStringAllocator); // set interface pointers used by idLib idLib::sys = sys; idLib::common = common; idLib::cvarSystem = cvarSystem; idLib::fileSystem = fileSystem; //rWorld = renderSystem->AllocRenderWorld(); HOOKVFUNC(gLocal, &idGameLocal::InitFromNewMap, orig_idGameLocal_InitFromNewMap, qwh_idGameLocal_InitFromNewMap); HOOKVFUNC(gLocal, &idGameLocal::Draw2D, orig_idGameLocal_Draw2D, qwh_idGameLocal_Draw2D); //HOOKVFUNC(renderSystem, &idRenderSystem::AllocRenderWorld, orig_idRenderSystem_AllocRenderWorld, qwh_idRenderSystem_AllocRenderWorld); LOG_DEBUG("Qw::GetGameAPI(): done"); return gameExport; } //void Qw::w2sTransform(const idBounds& src, const idMat3& axes, const idVec3& origin, sdBounds2D& dst) const { // //Constructor // const float width = SCREEN_WIDTH * 1.0f / deviceContext->GetAspectRatioCorrection(); // w2s_extents.Set( width, SCREEN_HEIGHT ); // //Setup( view ); // // //Setup // w2s_projectionMatrix = w2s_projectionMatrixArray; // w2s_modelViewMatrix = w2s_modelViewMatrixArray; // rWorld->SetupMatrices( &view, w2s_projectionMatrix, w2s_modelViewMatrix ); // // idVec3 point; // idVec2 screenPoint; // // dst.Clear(); // // int i; // for ( i = 0; i < 8; i++ ) { // point[ 0 ] = src[ ( i & 1 ) >> 0 ][ 0 ]; // point[ 1 ] = src[ ( i & 2 ) >> 1 ][ 1 ]; // point[ 2 ] = src[ ( i & 4 ) >> 2 ][ 2 ]; // // point *= axes; // point += origin; // // Transform( point, screenPoint ); // // dst.AddPoint( screenPoint ); // } //} void Qw::w2s( const renderView_t& view, const idVec3& src, idVec2& dst ) { //Constructor const float width = SCREEN_WIDTH * 1.0f / deviceContext->GetAspectRatioCorrection(); w2s_extents.Set( width, SCREEN_HEIGHT ); //Setup( view ); //Setup w2s_projectionMatrix = w2s_projectionMatrixArray; w2s_modelViewMatrix = w2s_modelViewMatrixArray; rWorld->SetupMatrices( &view, w2s_projectionMatrix, w2s_modelViewMatrix ); //Transform int i; idPlane eye, clip; for ( i = 0 ; i < 4 ; i++ ) { eye[i] = src[0] * w2s_modelViewMatrix[ i + 0 * 4 ] + src[1] * w2s_modelViewMatrix[ i + 1 * 4 ] + src[2] * w2s_modelViewMatrix[ i + 2 * 4 ] + w2s_modelViewMatrix[ i + 3 * 4 ]; } for ( i = 0 ; i < 4 ; i++ ) { clip[i] = eye[0] * w2s_projectionMatrix[ i + 0 * 4 ] + eye[1] * w2s_projectionMatrix[ i + 1 * 4 ] + eye[2] * w2s_projectionMatrix[ i + 2 * 4 ] + eye[3] * w2s_projectionMatrix[ i + 3 * 4 ]; } if( clip[ 3 ] <= 0.01f ) { clip[ 3 ] = 0.01f; } dst[ 0 ] = clip[ 0 ] / clip[ 3 ]; dst[ 1 ] = clip[ 1 ] / clip[ 3 ]; dst[ 0 ] = ( 0.5f * ( 1.0f + dst[ 0 ] ) * w2s_extents[ 0 ] ); dst[ 1 ] = ( 0.5f * ( 1.0f - dst[ 1 ] ) * w2s_extents[ 1 ] ); }