maxorator

Katana attack source code (GTA:VC)

Apr 27th, 2011
534
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.51 KB | None | 0 0
  1. //video: http://www.youtube.com/watch?v=0aZBceWVXz8
  2.  
  3. #define KATSTATUS_INHAND 0
  4. #define KATSTATUS_INAIR 1
  5. #define KATSTATUS_INTARGET 2
  6.  
  7. struct KatanaInfo {
  8.     RpAtomic* pKat;
  9.     float fAcc;
  10.     float fSpeed;
  11.     CQuaternion qtStatus;
  12.     CPedVC* pTarget;
  13.     RwMatrix matFinal;
  14.     DWORD dwStatus;
  15. };
  16.  
  17. KatanaInfo pKatInfos[100];
  18.  
  19. void KatanaAttack_AcquireSlot(int nSlot) {
  20.     if(!pKatInfos[nSlot].pKat) {
  21.         //if this slot has not been initialized, create the atomic
  22.         UtilMakeSureModelIsLoaded(CWeaponModelInfo_KATANA, 0);
  23.         pKatInfos[nSlot].pKat = CBaseModelInfoMethod_CreateInstance(lpModelList.x[CWeaponModelInfo_KATANA]);
  24.         CBaseModelInfo_AddRef(lpModelList.x[CWeaponModelInfo_KATANA]);
  25.     }
  26.     else {
  27.         if(pKatInfos[nSlot].pTarget) {
  28.             //if target is already specified, remove the reference
  29.             CEntity_RemoveReference(ENT(pKatInfos[nSlot].pTarget), (CEntity**)&pKatInfos[nSlot].pTarget);
  30.         }
  31.     }
  32.  
  33.     //initialize new slot
  34.     pKatInfos[nSlot].pTarget = NULL;
  35.     pKatInfos[nSlot].dwStatus = KATSTATUS_INHAND;
  36.     pKatInfos[nSlot].fAcc = 0.3f;
  37.     pKatInfos[nSlot].fSpeed = 0.3f;
  38. }
  39.  
  40. void KatanaAttack_Process(CPedVC* pPed) {
  41.     static int nUsed = -1;
  42.     static DWORD dwLastThrow = 0;
  43.     int nNew = -1;
  44.  
  45.     CVector vecPos, vecDistance;
  46.     RwMatrix matInvert;
  47.     matInvert.dwFlags=0;
  48.  
  49.     CMatrix stMatrix;
  50.     RwMatrix *pRwMatrix;
  51.     RwMatrix matReal;
  52.  
  53.     if(nUsed == -1) {
  54.         //initialize first katana
  55.         KatanaAttack_AcquireSlot(++nUsed);
  56.     }
  57.  
  58.     //iterate through all katana slots
  59.     for(int m=0; m<100; m++) {
  60.         //unused slot, ignore
  61.         if(!pKatInfos[m].pKat) continue;
  62.  
  63.         //freshly created slot, ignore
  64.         if(m == nNew) continue;
  65.  
  66.         if(pKatInfos[m].dwStatus == KATSTATUS_INHAND) {
  67.             //katana is still in player's hand
  68.  
  69.             //only process for the player
  70.             if(pPed != stPlInf.pPlayerPed) continue;
  71.  
  72.             //check if the player is pressing SHIFT+4 and that there is no target assigned to this slot already
  73.             if(!(GetKeyState('4') & 0x80) || !(GetKeyState(VK_SHIFT) & 0x80) || pKatInfos[m].pTarget != NULL) continue;
  74.            
  75.             //make sure the player is wielding a katana
  76.             if(pPed->dwWepModelID != CWeaponModelInfo_KATANA) continue;
  77.  
  78.             //do not allow throwing katanas more often than once per 100ms
  79.             if(dwLastThrow + 100 >= dwGameCount) continue;
  80.  
  81.             //get katana's atomic's matrix
  82.             pRwMatrix = &RpAtomicGetFrame(pKatInfos[m].pKat)->matFrameRelative;
  83.  
  84.             //find a suitable target from near peds list
  85.             for(int i=0; i<10; i++) {
  86.                 if(pPed->pNearPeds[i] && pPed->pNearPeds[i]->fCurHealth > 0.0f && pPed->pNearPeds[i]->byteIsInVehicle == 0) {
  87.                     pKatInfos[m].pTarget = pPed->pNearPeds[i];
  88.                     break;
  89.                 }
  90.             }
  91.  
  92.             //target was not found, aborting
  93.             if(pKatInfos[m].pTarget == NULL) continue;
  94.  
  95.             //register a reference, so that it is NULLed when the target ped is destroyed
  96.             CEntity_RegisterReference(ENT(pKatInfos[m].pTarget), (CEntity**)&pKatInfos[m].pTarget);
  97.  
  98.             //initialize matrix
  99.             stMatrix.pAttached = NULL;
  100.             stMatrix.dwDeleteOnDetach = false;
  101.  
  102.             CMatrix_Attach(&stMatrix, pRwMatrix, false);
  103.             CMatrix_SetScale(&stMatrix, 1.0f);
  104.             CMatrix_SetRotate(&stMatrix, 0.0f, 0.0f, 0.0f);
  105.             CMatrix_UpdateRW(&stMatrix);
  106.             CMatrix_DCMatrix(&stMatrix);
  107.  
  108.             RwMatrix* pRwBase;
  109.             DWORD dwIndex;
  110.  
  111.             //find the matrix for player's right hand
  112.             RpHAnimHierarchy* pAnimHierarchy = RpClumpGetSkinHAnimHierarchy(ENT(pPed)->pModel);
  113.             RwMatrix* pRwMatrixArray = RpHAnimHierarchyGetMatrixArray(pAnimHierarchy);
  114.             dwIndex = RpHAnimIDGetIndex(pAnimHierarchy, pPed->pFrames[AFRAMEID_RHAND]->dwFrameNodeId);
  115.             pRwBase = &pRwMatrixArray[dwIndex];
  116.  
  117.             //initialize katana's matrix
  118.             RwMatrixTransform(pRwMatrix, pRwBase, rwCOMBINEPOSTCONCAT);
  119.  
  120.             //get katana's current rotation as a quaternion (for easier interpolation)
  121.             QtMatrixToQuaternion(&pKatInfos[m].qtStatus, pRwMatrix);
  122.  
  123.             pKatInfos[m].dwStatus = KATSTATUS_INAIR;
  124.  
  125.             //initialize new slot for the katana in hand, recycle slots
  126.             nUsed = (nUsed+1) % 100;
  127.             KatanaAttack_AcquireSlot(nUsed);
  128.  
  129.             nNew = nUsed;
  130.             dwLastThrow = dwGameCount;
  131.         }
  132.         else if(pKatInfos[m].dwStatus == KATSTATUS_INAIR) {
  133.             //katana is in air
  134.  
  135.             //only process for player's render function, also check if the target is still active (might have been destroyed)
  136.             if(pPed != stPlInf.pPlayerPed || pKatInfos[m].pTarget == NULL || ENT(pKatInfos[m].pTarget)->pModel == NULL) continue;
  137.  
  138.             //get katana's atomic's matrix
  139.             pRwMatrix = &RpAtomicGetFrame(pKatInfos[m].pKat)->matFrameRelative;
  140.  
  141.             RwMatrix* pRwBase;
  142.             DWORD dwIndex;
  143.  
  144.             //get the matrix for the spine of the target ped
  145.             RpHAnimHierarchy* pAnimHierarchy = RpClumpGetSkinHAnimHierarchy(ENT(pKatInfos[m].pTarget)->pModel);
  146.             RwMatrix* pRwMatrixArray = RpHAnimHierarchyGetMatrixArray(pAnimHierarchy);
  147.             dwIndex = RpHAnimIDGetIndex(pAnimHierarchy, pPed->pFrames[AFRAMEID_SPINE1]->dwFrameNodeId);
  148.             pRwBase = &pRwMatrixArray[dwIndex];
  149.  
  150.             //initialize matrix
  151.             stMatrix.pAttached = NULL;
  152.             stMatrix.dwDeleteOnDetach = false;
  153.  
  154.             //save katana's position (matrix functions tend to reset position)
  155.             VecCopy(&vecPos, &pRwMatrix->vPos);
  156.  
  157.             //calculate heading matrix from current position to target
  158.             CMatrix_Attach(&stMatrix, &matReal, false);
  159.             CMatrix_SetScale(&stMatrix, 1.0f);
  160.             CMatrix_SetRotate(&stMatrix, 0.0f, 0.0f, 0.0f);
  161.             CVector *v1 = &vecPos, *v2 = &pRwBase->vPos;
  162.  
  163.             float XY = atan2(v2->Y-v1->Y,v2->X-v1->X);
  164.             float XYZ = atan2(sqrt((v2->X-v1->X)*(v2->X-v1->X) + (v2->Y-v1->Y)*(v2->Y-v1->Y)), v2->Z-v1->Z);
  165.  
  166.             CMatrix_Rotate(&stMatrix, 0.0f, XYZ, XY);
  167.             CMatrix_UpdateRW(&stMatrix);
  168.             CMatrix_DCMatrix(&stMatrix);
  169.  
  170.             CQuaternion qtExa, qtRes;
  171.  
  172.             //interpolate between current rotation and desired rotation
  173.             QtMatrixToQuaternion(&qtExa, &matReal);
  174.             QtSlerp(&qtRes, &pKatInfos[m].qtStatus, &qtExa, pKatInfos[m].fAcc);
  175.  
  176.             //increase the interpolation degree for next frames
  177.             pKatInfos[m].fAcc = min(pKatInfos[m].fAcc+0.03f, 1.0f);
  178.  
  179.             //store the new rotation
  180.             QtQuaternionToMatrix(&qtRes, pRwMatrix);
  181.  
  182.             //calculate distance from katana to target
  183.             VecCopy(&vecDistance, &vecPos);
  184.             VecSubVec(&vecDistance, &pRwBase->vPos);
  185.  
  186.             float fLen = CVector_GetLength(&vecDistance);
  187.  
  188.             //only really necessary if there is some extra rotation applied here...
  189.             memcpy(&matReal, pRwMatrix, sizeof(RwMatrix));
  190.  
  191.             CMatrix_Attach(&stMatrix, &matReal, false);
  192.             CMatrix_Rotate(&stMatrix, 0.0f, 0.0f, 0.0f);
  193.             CMatrix_UpdateRW(&stMatrix);
  194.             CMatrix_DCMatrix(&stMatrix);
  195.  
  196.             if(fLen > pKatInfos[m].fSpeed) {
  197.                 //katana is on its way
  198.  
  199.                 //move according to the rotation
  200.                 vecPos.X += matReal.vLookUp.X * pKatInfos[m].fSpeed;
  201.                 vecPos.Y += matReal.vLookUp.Y * pKatInfos[m].fSpeed;
  202.                 vecPos.Z += matReal.vLookUp.Z * pKatInfos[m].fSpeed;
  203.  
  204.                 VecCopy(&pRwMatrix->vPos, &vecPos);
  205.  
  206.                 //gradually increase movement speed
  207.                 pKatInfos[m].fSpeed += 0.001f;
  208.             }
  209.             else {
  210.                 //katana arrived at target
  211.  
  212.                 //move according to the rotation
  213.                 vecPos.X += matReal.vLookUp.X * fLen;
  214.                 vecPos.Y += matReal.vLookUp.Y * fLen;
  215.                 vecPos.Z += matReal.vLookUp.Z * fLen;
  216.                 VecCopy(&pRwMatrix->vPos, &vecPos);
  217.  
  218.                 //get the inverted matrix of target's spine
  219.                 RwMatrixInvert(&matInvert, pRwBase);
  220.  
  221.                 //store katana's current rotation
  222.                 memcpy(&pKatInfos[m].matFinal, pRwMatrix, sizeof(RwMatrix));
  223.  
  224.                 //transform rotation to local space of target
  225.                 RwMatrixTransform(&pKatInfos[m].matFinal, &matInvert, rwCOMBINEPOSTCONCAT);
  226.                 VecSetFloat(&pKatInfos[m].matFinal.vPos, 0.0f);
  227.  
  228.                 //kill target and do some blood effects
  229.                 CPed_SpawnFlyingComponent(pKatInfos[m].pTarget, 1, 0);
  230.                 pKatInfos[m].pTarget->fCurHealth = 0.0f;
  231.  
  232.                 //choose a death animation for the target
  233.                 DWORD dwAnimID = 16;
  234.  
  235.                 if(rand() & 0x1000) {
  236.                     dwAnimID = 18;
  237.                 }
  238.  
  239.                 //start death animation
  240.                 CPed_SetDie(pKatInfos[m].pTarget, dwAnimID, 4.0f, 0.0f);
  241.  
  242.                 pKatInfos[m].dwStatus = KATSTATUS_INTARGET;
  243.             }
  244.  
  245.             //make the RW engine aware of the rotation/position changes
  246.             RwMatrixUpdate(pRwMatrix);
  247.             RwFrameUpdateObjects(RpAtomicGetFrame(pKatInfos[m].pKat));
  248.  
  249.             //render katana's atomic
  250.             pKatInfos[m].pKat->pRenderCallback(pKatInfos[m].pKat);
  251.         }
  252.         else if(pKatInfos[m].dwStatus == KATSTATUS_INTARGET) {
  253.             //katana is in the target
  254.  
  255.             //only process this when rendering the target
  256.             if(pPed != pKatInfos[m].pTarget) continue;
  257.  
  258.             DWORD dwIndex;
  259.             RwMatrix* pRwBase;
  260.  
  261.             //get the matrix for the spine of the target ped
  262.             RpHAnimHierarchy* pAnimHierarchy = RpClumpGetSkinHAnimHierarchy(ENT(pKatInfos[m].pTarget)->pModel);
  263.             RwMatrix* pRwMatrixArray = RpHAnimHierarchyGetMatrixArray(pAnimHierarchy);
  264.             dwIndex = RpHAnimIDGetIndex(pAnimHierarchy, pPed->pFrames[AFRAMEID_SPINE1]->dwFrameNodeId);
  265.             pRwBase = &pRwMatrixArray[dwIndex];
  266.  
  267.             //get katana's atomic's matrix
  268.             pRwMatrix = &RpAtomicGetFrame(pKatInfos[m].pKat)->matFrameRelative;
  269.  
  270.             memcpy(pRwMatrix, &pKatInfos[m].matFinal, sizeof(RwMatrix));
  271.  
  272.             //calculate world coords and rotation of the katana atomic
  273.             RwMatrixTransform(pRwMatrix, pRwBase, rwCOMBINEPOSTCONCAT);
  274.  
  275.             //make the RW engine aware of the rotation/position changes
  276.             RwMatrixUpdate(pRwMatrix);
  277.             RwFrameUpdateObjects(RpAtomicGetFrame(pKatInfos[m].pKat));
  278.  
  279.             //render katana's atomic
  280.             pKatInfos[m].pKat->pRenderCallback(pKatInfos[m].pKat);
  281.         }
  282.     }
  283. }
  284.  
  285. CPedVC* _pHookPed;
  286.  
  287. void _declspec(naked) Hook_CPed_Render() {
  288.     _asm mov _pHookPed,ecx
  289.     _asm pushad
  290.    
  291.     KatanaAttack_Process(_pHookPed);
  292.    
  293.     _asm popad
  294.     _asm push ebx
  295.     _asm push esi
  296.     _asm mov ebx,ecx
  297.     _asm push ebp
  298.     _asm sub esp,0D8h
  299.     _asm mov eax,4FE0FBh
  300.     _asm jmp eax
  301. }
  302.  
  303. void InstallHook(DWORD dwInstallAddress, DWORD dwHookFunction, DWORD dwHookStorage) {
  304.     *(PDWORD)dwHookStorage = (DWORD)dwHookFunction;
  305.     *((PWORD)dwInstallAddress) = 0x25FF;
  306.     *((PDWORD)(dwInstallAddress+2)) = dwHookStorage;
  307. }
  308.  
  309. InstallHook(0x4FE0F0, (DWORD)Hook_CPed_Render, 0x4FE4B4);
Add Comment
Please, Sign In to add comment