Introducción
El código presentado es parte del sistema de movimiento de cámara y física en MU Online, un popular juego de rol multijugador. A continuación, desglosamos las secciones más relevantes del código para entender su funcionamiento y cómo impacta en la experiencia del jugador.
1. Cameramove.h
Directivas de Preprocesador
#pragma once
: Asegura que el archivo se incluya solo una vez durante la compilación.#define
: Define constantes y máscaras para diferentes propiedades físicas y de cámara, esenciales para el manejo de la jugabilidad.
Definiciones de Constantes
Se definen varios tipos de propiedades físicas y de cámara, como:
- Formas:
PCT_FLAT
,PCT_CURVED
. - Materiales:
PCT_COTTON
,PCT_RUBBER
.
Variables Globales
Se definen punteros a direcciones de memoria específicas para variables como FPS, tiempos de delta, y tipos de cámara, que son cruciales para el rendimiento del juego.
Funciones
Se declaran funciones que interactúan con la física del juego, como mover la cámara y actualizar fuerzas físicas, lo que es vital para la jugabilidad fluida.
Estructura PhysicsVertex
Define una estructura que almacena información sobre un vértice físico, incluyendo:
- Posición
- Velocidad
- Estado
Clase CCameraMove
Contiene métodos para inicializar la cámara, mover vértices físicos y reproducir animaciones 3D, mejorando la inmersión del jugador.
2. CameraMove.cpp
Inicialización
Se inicializan variables globales y se define el constructor y destructor de CCameraMove
, asegurando que los recursos se gestionen correctamente.
Cálculo de FPS
La función CalcFPS
actualiza el recuento de FPS y puede cambiar el título de la ventana del juego con información relevante, lo que ayuda a los jugadores a monitorear el rendimiento.
Funciones de Movimiento
CPhysicsCloth_InitForces
yCPhysicsVertex_Move
gestionan la física de los objetos en el juego, calculando fuerzas y actualizando posiciones basadas en el tiempo, lo que es esencial para el movimiento realista de personajes y objetos.
Renderizado de Personajes
Las funciones SpeedCharacterBackItem1
, SpeedCharacterBackItem2
, y SpeedCharacterBackItem3
ajustan la velocidad de los personajes en función de su tipo, mejorando la jugabilidad.
Animaciones
PlayAnimation3D
gestiona la reproducción de animaciones en 3D, aplicando la velocidad de animación calculada, lo que contribuye a una experiencia visual más rica.
Método Init
Configura varios hooks y ajustes en el comportamiento del juego, como arreglos en la interfaz y el movimiento de la cámara, optimizando la experiencia del jugador.
3. Hackcheck.cpp
Chequeo de Hack
CheckTickCount2
verifica modificaciones no autorizadas en el juego, comparando varios modificadores y valores de tiempo para mantener la integridad del juego.
4. gProtect.cpp
Control de FPS
FT_Nine2D
ajusta el límite de FPS basado en configuraciones predefinidas, asegurando una experiencia de juego fluida y sin interrupciones.
Cameramove.h #pragma once #define PVS_NORMAL ( 0x00) #define PVS_FIXEDPOS ( 0x01) #define RATE_SHORT_SHOULDER ( 0.6f) #define PCT_MASK_SHAPE ( 0x00000003) #define PCT_FLAT ( 0x00000000) #define PCT_CURVED ( 0x00000001) #define PCT_STICKED ( 0x00000002) #define PCT_MASK_SHAPE_EXT ( 0x0000000C) #define PCT_SHAPE_NORMAL ( 0x00000000) #define PCT_SHORT_SHOULDER ( 0x00000004) #define PCT_CYLINDER ( 0x00000008) #define PCT_MASK_SHAPE_EXT2 ( 0x00000030) #define PCT_SHAPE_HALLOWEEN ( 0x00000010) #define PCT_MASK_ELASTIC ( 0x00000300) #define PCT_COTTON ( 0x00000000) #define PCT_RUBBER ( 0x00000100) #define PCT_RUBBER2 ( 0x00000200) #define PCT_MASK_WEIGHT ( 0x00000C00) #define PCT_NORMAL_THICKNESS ( 0x00000000) #define PCT_HEAVY ( 0x00000400) #define PCT_MASK_DRAW ( 0x00003000) #define PCT_MASK_BLIT ( 0x00000000) #define PCT_MASK_ALPHA ( 0x00001000) #define PCT_MASK_BLEND ( 0x00002000) #define FPS_ *(float*)0x5EF5A18 #define DelTtime *(float*)0xE61610 #define CameraWalkCut *(int*)0xE8C83C #define CurrentCameraCount *(int*)0xE60AB0 #define CurrentCameraNumber *(int*)0xE8CB48 #define CurrentCameraWalkType *(int*)0xE8CB44 #define MoveSceneFrame *(int*)0xE8CB20 #define s_fInvOfMass *(float*)0xE614C8 #define listWayPoint_empty ((BOOL(__thiscall*)(void* This)) 0x004DEC50) #define listWayPoint_size ((int(__thiscall*)(int This)) 0x004DEC30) #define GetlistWayPoint ((unsigned int (__thiscall*)(int This, unsigned int index)) 0x004DEC70) #define sub_4DEB00 ((int(__thiscall*)(int This)) 0x004DEB00) #define CreateAngle ((double(__cdecl*)(float a1, float a2, float a3, float a4)) 0x00540C30) #define absf ((double(__cdecl*)(float a1)) 0x00639050) #define sub_959B10 ((double(__cdecl*)(int This, int v2)) 0x00959B10) #define MoveCharacterCamera ((void(__cdecl*)(vec3_t Origin,vec3_t Position,vec3_t Angle)) 0x004D66C0) #define UpdateForce ((void(__thiscall*)(int This, unsigned int iKey, DWORD dwType, float fWind)) 0x0051C890) #define CPhysicsVertex_Init ((void(__thiscall*)(int This, float fXPos, float fYPos, float fZPos, BOOL bFixed)) 0x0051C850) #define sub_9CF1C0 ((void(__cdecl*)(int a1, int a2, int a3)) 0x009CF1C0) #define PlayAnimation ((bool(__thiscall*)(int This, float *AnimationFrame,float *PriorAnimationFrame,unsigned short *PriorAction,float Speed,float * Origin,float * Angle)) 0x00545180) typedef struct { int byClass; float m_vForce[3]; float m_vVel[3]; float m_vPos[3]; BYTE m_byState; char sobrante[16]; }PhysicsVertex, * CPhysicsVertex; class CCameraMove { public: enum { CAMERAWALK_STATE_READY = 0, CAMERAWALK_STATE_MOVE, CAMERAWALK_STATE_DONE, }; CCameraMove(void); virtual ~CCameraMove(void); void Init(); static void __thiscall CPhysicsCloth_InitForces(int This); static void __thiscall CPhysicsVertex_Move(CPhysicsVertex This, float fTime); static bool __thiscall PlayAnimation3D(int This, float *AnimationFrame,float *PriorAnimationFrame,unsigned short *PriorAction,float Speed,float* Origin,float* Angle); }; extern CCameraMove g_CameraWalkInstance; CameraMove.cpp #include "StdAfx.h" #include "Util.h" #include "Camera.h" #include "Protect.h" #include "SEASON3B.h" #include "CustomMap.h" #include "CameraMove.h" int FpsCount = 0; int FpsTime = 0; int activespeedmove = 0; int AnimationFrameConstant = 30; CCameraMove g_CameraWalkInstance; CCameraMove::CCameraMove(void) { } CCameraMove::~CCameraMove(void) { } void CalcFPS() { ((void(__cdecl*)()) 0x00542EF0)(); FpsCount++; if(GetTickCount() >= (FpsTime + 999)) { AnimationFrameConstant = FpsCount; /*char szTitle[254] = {'\0',}; if(SceneFlag == MAIN_SCENE) { sprintf_s(szTitle, "%s [%s][Lvl: %d] - %s (%d %d) [FPS:%d]", gProtect->m_MainInfo.WindowName, (char*)(Hero + 56), *(WORD*)(*(DWORD*)0x8128AC8 + 14), GetMapName(World), *(int*)(Hero + 172), *(int*)(Hero + 176), FpsCount); } else if(SceneFlag == CHARACTER_SCENE) { sprintf_s(szTitle, "%s [SELECT CHARACTER SCENE] - [FPS: %d]", gProtect->m_MainInfo.WindowName, FpsCount); } else if(SceneFlag == LOG_IN_SCENE) { sprintf_s(szTitle, "%s [SERVER LOG IN SCENE] - [FPS: %d]", gProtect->m_MainInfo.WindowName, FpsCount); } if( szTitle[0] != '\0') { SetWindowText(g_hWnd, szTitle); }*/ FpsTime = GetTickCount(); FpsCount = 0; } gCamera.ZoomInFactor(); gCamera.RotateInFactor(); } void AnimationSpeed(float* Speed) { (*Speed) *= ((AnimationFrameConstant > 25) ? (1.f / (AnimationFrameConstant / 25.f)):1.f); } void RenderCharacterBackItem(int w, int o, int Type) { float PlaySpeed = 1.f; AnimationSpeed(&PlaySpeed); if( Type == 1 ) { if ( *(WORD *)(o + 18) != 34 && *(WORD *)(o + 18) != 35 ) *(float *)(w + 20) = 0.25 * PlaySpeed; else *(float *)(w + 20) = 1.0 * PlaySpeed; } if( Type == 2 ) { if ( *(WORD *)(o + 18) != 34 && *(WORD *)(o + 18) != 35 ) *(float *)(w + 20) = 0.25 * PlaySpeed; else *(float *)(w + 20) = 1.0 * PlaySpeed; } if( Type == 3 ) { if ( *(WORD *)(o + 18) != 34 && *(WORD *)(o + 18) != 35 ) { *(float *)(w + 20) = 0.25 * PlaySpeed; } else if ( *(WORD *)w == 7351 ) { *(float *)(w + 20) = 0.5 * PlaySpeed; } else { *(float *)(w + 20) = 1.0 * PlaySpeed; } } } void CCameraMove::CPhysicsCloth_InitForces(int This) { int m_iNumVertices = *(int *)(This + 52); int m_iNumHor = *(int *)(This + 44); int m_pVertices = *(int *)(This + 56); int iSeed = ((MoveSceneFrame / 10) * 101) % m_iNumVertices; int o = *(int *)(This + 4); int Type = *(int *)(o + 48); WORD CurrentAction = *(WORD*)(o + 18); activespeedmove = 0; if(Type == 1163 && ((CurrentAction >= 15 //-- PLAYER_WALK_MALE && CurrentAction <= 24) //-- PLAYER_WALK_SWIM || (CurrentAction >= 34 //-- PLAYER_FLY && CurrentAction <= 37) //-- PLAYER_RUN_RIDE_WEAPON || CurrentAction == 74 //-- PLAYER_FLY_RIDE || CurrentAction == 75 //-- PLAYER_FLY_RIDE_WEAPON || CurrentAction == 77 //-- PLAYER_DARKLORD_WALK || CurrentAction == 79 //-- PLAYER_RUN_RIDE_HORSE || (CurrentAction >= 110 //-- PLAYER_FENRIR_RUN && CurrentAction <= 121) //-- PLAYER_FENRIR_RUN || (CurrentAction >= 126 //-- PLAYER_FENRIR_WALK && CurrentAction <= 129) //-- PLAYER_FENRIR_WALK || CurrentAction == 143 //-- PLAYER_WALK_TWO_HAND_SWORD_TWO || CurrentAction == 144 //-- PLAYER_RUN_TWO_HAND_SWORD_TWO )) { activespeedmove = 1; } for ( int iVertex = 0; iVertex < m_iNumVertices; ++iVertex) { float m_fWind = *(float *)(This + 68); int m_dwType = *(DWORD *)(This + 20); UpdateForce(m_pVertices + iVertex * 60, abs( iSeed % m_iNumHor - iVertex % m_iNumHor) + abs( iSeed / m_iNumHor - iVertex / m_iNumHor), m_dwType, m_fWind ); } } void CCameraMove::CPhysicsVertex_Move(CPhysicsVertex This, float fTime) { float fSpeed = 1.f; float Time = fTime; AnimationSpeed(&fSpeed); if(AnimationFrameConstant > 25) { Time *= fSpeed; } if ( !(This->m_byState & PVS_FIXEDPOS) && activespeedmove == FALSE) { for (int i = 0; i < 3; ++i ) { This->m_vVel += (This->m_vForce * s_fInvOfMass * fTime) * fSpeed; This->m_vPos += (This->m_vVel * Time); } } } void __declspec(naked) SpeedCharacterBackItem1() { static DWORD JmpBack = 0x005882A5; _asm { push 1 mov edx, dword ptr ss:[ebp+0xC] push edx mov eax, dword ptr ss:[ebp-0x20] push eax call [RenderCharacterBackItem] Jmp JmpBack } } void __declspec(naked) SpeedCharacterBackItem2() { static DWORD JmpBack = 0x0058848E; _asm { push 2 mov edx, dword ptr ss:[ebp+0xC] push edx mov eax, dword ptr ss:[ebp-0x5C] push eax call [RenderCharacterBackItem] Jmp JmpBack } } void __declspec(naked) SpeedCharacterBackItem3() { static DWORD JmpBack = 0x005885AA; _asm { push 3 mov eax, dword ptr ss:[ebp+0xC] push eax mov ecx, dword ptr ss:[ebp-0x6C] push ecx call [RenderCharacterBackItem] Jmp JmpBack } } bool CCameraMove::PlayAnimation3D(int This, float *AnimationFrame,float *PriorAnimationFrame,unsigned short *PriorAction,float Speed,float * Origin,float * Angle) { AnimationSpeed(&Speed); return PlayAnimation(This, AnimationFrame, PriorAnimationFrame, PriorAction, Speed, Origin, Angle); } void CCameraMove::Init() { SetByte(0x00813BF1 + 3, 1); //-- Fix Tooltip SkillBar SetByte(0x004EBD01 + 6, 1); //-- Fix Tooltip Ancient //SetCompleteHook(0xE9, 0x005977E0, &RenderNotices); SetCompleteHook(0xE8, 0x004D9D0E, &CalcFPS); //ok SetByte(0x0059788E + 1, 0x14); //-- Fix Notice Midd SetByte(0x00597895 + 2, 0xA); //-- Fix Notice Midd SetCompleteHook(0xE9, 0x00588277, &SpeedCharacterBackItem1); SetCompleteHook(0xE9, 0x00588460, &SpeedCharacterBackItem2); SetCompleteHook(0xE9, 0x00588560, &SpeedCharacterBackItem3); SetCompleteHook(0xE8, 0x004F0356, &CCameraMove::PlayAnimation3D); SetCompleteHook(0xE9, 0x0051CB60, &CCameraMove::CPhysicsVertex_Move); SetCompleteHook(0xE9, 0x0051E440, &CCameraMove::CPhysicsCloth_InitForces);; } Hackcheck.cpp _declspec(naked) void CheckTickCount2() // OK { static DWORD CheckTickCountAddress1 = 0x004DA3F0; static DWORD FrameCount = 0x11; if(*(int*)0xE609E8 == 5) { FrameCount = gProtect->FT_Nine2D(); } else { FrameCount = 0x28; } _asm { Mov Ecx,Dword Ptr Ss:[Ebp-0x6C] Mov CountModifier,Ecx Mov Edx,Dword Ptr Ss:[Ebp-0x74] Mov DelayModifier,Edx Mov Ecx,Dword Ptr Ss:[Ebp-0x178] Mov HasteModifier,Ecx Mov Edx,Dword Ptr Ds:[MAIN_VIEWPORT_STRUCT] Mov Ecx,Dword Ptr Ds:[Edx+0x214] Mov SpeedModifier1,Ecx Mov Edx,Dword Ptr Ds:[MAIN_VIEWPORT_STRUCT] Mov Ecx,Dword Ptr Ds:[Edx+0x218] Mov SpeedModifier2,Ecx Mov Edx,Dword Ptr Ds:[MAIN_VIEWPORT_STRUCT] Mov Ecx,Dword Ptr Ds:[Edx+0x31A] Mov ModelModifier1,Ecx Mov Edx,Dword Ptr Ds:[MAIN_VIEWPORT_STRUCT] Mov Ecx,Dword Ptr Ds:[Edx+0x394] Mov ModelModifier2,Ecx Mov Edx,Dword Ptr Ds:[MAIN_VIEWPORT_STRUCT] Mov Ecx,Dword Ptr Ds:[Edx+0x398] Mov ModelModifier3,Ecx Mov Eax,MainTickCount Sub Eax,Dword Ptr Ss:[Ebp-0x74] Mov Dword Ptr Ss:[Ebp-0x68],Eax Mov Eax, FrameCount //-- fps Cmp Dword Ptr Ss:[Ebp-0x68],Eax Jge CONTINUE Mov Ecx, FrameCount Sub Ecx,Dword Ptr Ss:[Ebp-0x68] Mov Dword Ptr Ss:[Ebp-0x18C],Ecx Mov Edx,Dword Ptr Ss:[Ebp-0x18C] Mov SleepModifier,Edx NEXT: Push 1 Call Dword Ptr Ds:[Sleep] Call Dword Ptr Ds:[GetTickCount] Sub Eax,Dword Ptr Ss:[Ebp-0x074] Cmp Eax,Dword Ptr Ss:[Ebp-0x18C] Jl NEXT Mov Eax,MainTickCount Cmp SyncTickCount,Eax Jnz HACK Mov Ecx,Dword Ptr Ss:[Ebp-0x6C] Cmp CountModifier,Ecx Jnz HACK Mov Edx,Dword Ptr Ss:[Ebp-0x74] Cmp DelayModifier,Edx Jnz HACK Mov Ecx,Dword Ptr Ss:[Ebp-0x178] Cmp HasteModifier,Ecx Jnz HACK Mov Edx,Dword Ptr Ss:[Ebp-0x18C] Cmp SleepModifier,Edx Jnz HACK Mov Ecx,Dword Ptr Ds:[0x07BC4F04] Mov Edx,Dword Ptr Ds:[Ecx+0x214] Cmp SpeedModifier1,Edx Jnz HACK Mov Ecx,Dword Ptr Ds:[0x07BC4F04] Mov Edx,Dword Ptr Ds:[Ecx+0x218] Cmp SpeedModifier2,Edx Jnz HACK Mov Ecx,Dword Ptr Ds:[0x07BC4F04] Mov Edx,Dword Ptr Ds:[Ecx+0x31A] Cmp ModelModifier1,Edx Jnz HACK Mov Ecx,Dword Ptr Ds:[0x07BC4F04] Mov Edx,Dword Ptr Ds:[Ecx+0x394] Cmp ModelModifier2,Edx Jnz HACK Mov Ecx,Dword Ptr Ds:[0x07BC4F04] Mov Edx,Dword Ptr Ds:[Ecx+0x398] Cmp ModelModifier3,Edx Jnz HACK Add Eax,Dword Ptr Ss:[Ebp-0x18C] Mov MainTickCount,Eax Mov Eax, FrameCount //-- fps Mov Dword Ptr Ss:[Ebp-0x68],Eax CONTINUE: Mov Ecx,Dword Ptr Ss:[Ebp-0x178] Add Ecx,Dword Ptr Ss:[Ebp-0x68] Mov Dword Ptr Ss:[Ebp-0x6C],Ecx Jmp [CheckTickCountAddress1] HACK: Push 0 Call Dword Ptr Ds:[ExitProcess] } } gProtect.cpp int CProtect::FT_Nine2D() { int FrameLimit = this->m_MainInfo.LimitFPS; switch(FrameLimit) { case 0: FrameLimit = 0x28; //-- Default: (25FPS) break; case 1: FrameLimit = 0x22; //-- Max value: (30FPS) break; case 2: FrameLimit = 0x1A; //-- Max value: (40FPS) break; case 3: FrameLimit = 0x14; //-- Max value: (50FPS) break; case 4: FrameLimit = 0x11; //-- Max value: (60FPS) break; default: FrameLimit = 0x5; //-- Max value: (Unlimit) break; } return FrameLimit; } under : SetWord(0x00E609E4,(gProtect->m_MainInfo.IpAddressPort)); // IpAddressPort SetDword(0x004D597B, (DWORD)&MainTickCount); SetDword(0x004DA289, (DWORD)&MainTickCount); SetDword(0x004DA297, (DWORD)&MainTickCount); SetDword(0x004DA3A2, (DWORD)&MainTickCount); SetDword(0x004DA3CE, (DWORD)&MainTickCount); SetDword(0x004DA3D9, (DWORD)&MainTickCount); SetDword(0x0063D326, (DWORD)&MainTickCount); SetDword(0x00642112, (DWORD)&MainTickCount); SetCompleteHook(0xE9, 0x004DA280, &CheckTickCount1); SetCompleteHook(0xE9, 0x004DA3A1, &CheckTickCount2); VirtualizeOffset(0x004D9D39, 12); VirtualizeOffset(0x004D9D45, 7); VirtualizeOffset(0x004D9EFC, 15); VirtualizeOffset(0x004DAC5C, 8); VirtualizeOffset(0x005451F7, 5); VirtualizeOffset(0x00545230, 8); VirtualizeOffset(0x005A52E9, 8);
int RenderNotices() { int MoveY = 80; int result; // eax@1 if ( pPlayerState == 5 ) { result = (unsigned __int8)pCheckWindow((int *)GetInstance(), 65); if ( (unsigned __int8)result != 1 ) { EnableAlphaTest(1); pSetTextSize(pTextThis(), (HFONT)pFontBold); glColor3f(1.0, 1.0, 1.0); for (signed int i = 0; i < 6; ++i ){ if ( *((BYTE *)0x813DDD0 + 264 * i + 260) ) { pSetTextColor(pTextThis(), 0x64u, 0xFFu, 0xC8u, 0xFFu); pSetBackgroundTextColor(pTextThis(), 0, 0, 0, 0x80u); } else { pSetBackgroundTextColor(pTextThis(), 0, 0, 0, 0x80u); if ( NoticeInverse % 10 >= 5 ) { pSetTextColor(pTextThis(), 0xFFu, 0xC8u, 0x50u, 0xFFu); } else { pSetTextColor(pTextThis(), 0xFFu, 0xC8u, 0x50u, 0x80u); } } pDrawText(pTextThis(), 320, 3 * i + MoveY, (LPCTSTR)0x813DDD0 + 264 * i, 0, 0, (LPINT)8, 0); } result = NoticeInverse + 1; } return result; } } SetCompleteHook(0xE8, 0x004D5EC3, &RenderNotices);
Conclusión
Este código es fundamental para el control de la física y el movimiento en MU Online, asegurando que las animaciones y el comportamiento de los personajes sean fluidos y controlados. Además, incluye medidas de seguridad para prevenir trampas, lo que es crucial en un entorno competitivo.