Advertisement
Tornamic

Untitled

Feb 10th, 2025
33
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 22.17 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "COpCodeSync.h"
  3. #include <Commands/CCustomCommandMgr.h>
  4.  
  5. enum class eSyncedParamType
  6. {
  7.     NONE,
  8.  
  9.     // any `CPed` (aka actor, character), examples: `$ACTOR_SMOKE`
  10.     PED,
  11.  
  12.     // `$PLAYER_CHAR` (internal playerId for the `CWorld::Players` array)
  13.     // also used as `CPed` in cases where it is necessary to handle
  14.     // a player as a ped rather than a player (very often, e.g. `$PLAYER_ACTOR`)
  15.     PLAYER,
  16.  
  17.     // any `CVehicle` (aka car)
  18.     VEHICLE,
  19.  
  20.     // not in use yet
  21.     OBJECT,
  22.  
  23.     MAX_PARAMS
  24. };
  25.  
  26. struct SSyncedOpCode
  27. {
  28.     uint16_t m_wOpCode;
  29.  
  30.     // means the opcode has parameters that are hard to sync,
  31.     // like entities from the `eSyncedParamType`
  32.     bool m_bHasComplexParams = false;
  33.  
  34.     // yes, only the first 4 parameters contain entity handles,
  35.     // i checked and did not find any opcode where a handle is in
  36.     // the 5th or later parameters
  37.     eSyncedParamType m_aParamTypes[4] = { eSyncedParamType::NONE, eSyncedParamType::NONE, eSyncedParamType::NONE, eSyncedParamType::NONE };
  38. };
  39.  
  40. // Keep sorted!
  41. const SSyncedOpCode syncedOpcodes[] =
  42. {
  43.     // Messages
  44.     {0x00BA}, // show_text_styled GXT 'SWEET_5' time 1000 style 2
  45.     //{0x00BC}, // show_text_highpriority GXT 'MTIME3' time 1000 flag 1
  46.     {0x00BE}, // text_clear_all
  47.     //{0x01E3}, // show_text_1number_styled GXT 'M_PASSR' number 3 time 5000 style 1
  48.     {0x0318}, // set_latest_mission_passed 'INTRO_1'
  49.     {0x03E5}, // show_text_box 'HELP101'
  50.  
  51.     // Population managment
  52.     {0x01EB}, // set_traffic_density_multiplier_to 0.0
  53.     {0x0395}, // clear_area 1 at 2494.91 -1682.17 12.32 radius 50.0
  54.     {0x03DE}, // set_pedestrians_density_multiplier_to 0.2
  55.     {0x09D2}, // set_cops_chase_criminals 0
  56.     {0x06D0}, // enable_emergency_traffic 1
  57.  
  58.    
  59.     // Camera
  60.     {0x015F}, // set_camera_position 2498.947 -1690.0 14.4011 rotation 0.0 0.0 0.0
  61.     {0x0160}, // set_camera_point_at 2498.405 -1689.177 14.2309 switchstyle 2
  62.     {0x02EB}, // restore_camera_with_jumpcut
  63.     {0x0373}, // set_camera_directly_behind_player
  64.     {0x0920}, // point_camera 2359.521 -1246.843 28.7047 transverse_to 2359.276 -1247.129 28.7047 time 7000 smooth_transition 1
  65.     {0x0925}, // restore_camera_to_user_defined
  66.     {0x092F}, // lock_camera_target_point 1
  67.     {0x0930}, // lock_camera_position 1
  68.     {0x0936}, // set_camera 2358.656 -1246.348 28.7884 position_to 2358.656 -1246.348 28.7884 time 7000 smooth_transition 1
  69.     {0x0A0B}, // set_rendering_origin_at_3D_coord 2495.59 -1686.96 12.51 angle 32.2
  70.  
  71.  
  72.     // Scenes
  73.     {0x016A}, // fade 1 time 1000
  74.     {0x02A3}, // enable_widescreen 1
  75.     {0x02E4}, // load_cutscene_data 'PROLOG1'
  76.     {0x02E7}, // start_cutscene
  77.     {0x02EA}, // end_cutscene
  78.    
  79.     // World
  80.  
  81.     // Interiors
  82.     {0x04BB}, // select_interior 0
  83.     {0x07FB}, // set_interior 'CARLS' access 1
  84.  
  85.     // Weapons
  86.     {0x06AB, true, {eSyncedParamType::PED}}, // set_actor $NETWORK_PLAYER[2] all_weapons_hidden 1
  87.     {0x07A7, true, {eSyncedParamType::PED}}, // put_jetpack_on_actor $PLAYER_ACTOR
  88.  
  89.     // Tasks
  90.     {0x05C0, true, {eSyncedParamType::PED, eSyncedParamType::VEHICLE}}, // AS_actor 66@ look_at_car 51@ 4000 ms
  91.     {0x05D3, true, {eSyncedParamType::PED}}, //AS_actor $PLAYER_ACTOR goto_point 954.0 -1103.5 22.85 mode 4 time 20000 ms // versionA
  92.     {0x0647, true, {eSyncedParamType::PED}}, // AS_actor 66@ clear_look_task
  93.     {0x0687, true, {eSyncedParamType::PED}}, //clear_actor $PLAYER_ACTOR task
  94.     {0x0792, true, {eSyncedParamType::PED}}, //disembark_instantly_actor $PLAYER_ACTOR
  95.     {0x0673, true, {eSyncedParamType::PED}}, // AS_actor 66@ dive_to_offset 1.0 -3.0 time_on_ground 1000 ms
  96.     {0x0634, true, {eSyncedParamType::PED, eSyncedParamType::PED}}, // AS_actor 67@ attack_using_weapon_actor 50@ flags 4 perform_actions_after_time 2000 chance_of_action 100
  97.    
  98.     // Actors
  99.     {0x00A1, true, {eSyncedParamType::PED}}, // put_actor $PLAYER_ACTOR at 345.5621 306.2212 998.4484
  100.     {0x0350, true, {eSyncedParamType::PED}}, // set_actor 65@ maintain_position_when_attacked 1
  101.     {0x0173, true, {eSyncedParamType::PED}}, // set_actor $NETWORK_PLAYER[0] Z_angle_to 262.3977
  102.  
  103.     // Vehicles
  104.     {0x00AB, true, {eSyncedParamType::VEHICLE}}, // put_car 69@ at 1638.712 -1050.319 22.8984
  105.     {0x0175, true, {eSyncedParamType::VEHICLE}}, // set_car 69@ Z_angle_to 252.8
  106.  
  107.     // Explosions
  108.     {0x070C, true, {eSyncedParamType::VEHICLE}}, // explode_car_without_radius_damage 41@
  109.  
  110.     // Audio
  111.     {0x097A}, // play_audio_at -1000.0 -1000.0 -1000.0 event 1058
  112.  
  113.     // Blips
  114.     //{0x0164}, // disable_marker $MARKER_CATALINA
  115.     //{0x018A}, // 1@ = create_checkpoint_at 14@ 15@ 16@
  116.     //{0x02A7}, // $439 = create_icon_marker_and_sphere $ICON_CJ at $X_JOHNSON_HOUSE $Y_JOHNSON_HOUSE $Z_JOHNSON_HOUSE
  117. };
  118.  
  119. struct OpcodeSyncHeader
  120. {
  121.     uint16_t opcode;
  122.     uint8_t intParamCount : 4;
  123.     uint8_t stringParamCount : 4;
  124. };
  125.  
  126. struct OpcodeParameter
  127. {
  128.     union
  129.     {
  130.         struct
  131.         {
  132.             eSyncedParamType entityType : 4;
  133.             int entityId : 28;
  134.         };
  135.         int value;
  136.     };
  137. };
  138.  
  139.  
  140. static OpcodeParameter scriptParamsBuffer[10];
  141. static uint8_t textLengthBuffer[10];
  142. static char textParamBuffer[10][256];
  143.  
  144. static uint16_t scriptParamCount = 0;
  145. static uint16_t textParamCount = 0;
  146.  
  147. static uint32_t lastOpCodeProcessed;
  148. static CRunningScript* lastProcessedScript;
  149.  
  150. static uint8_t currentStringIdx = 0;
  151.  
  152. void __fastcall CRunningScript__CollectParameters_Hook_SwitchParametersContext(CRunningScript* script, int, uint16_t count)
  153. {
  154.     memcpy(ScriptParams, scriptParamsBuffer, sizeof scriptParamsBuffer);
  155. }
  156.  
  157. void __fastcall CRunningScript__ReadTextLabelFromScript_Hook_SwitchParametersContext(CRunningScript* script, int, char* ptr, uint8_t len)
  158. {
  159.     memset(ptr, 0, len);
  160.     strncpy(ptr, textParamBuffer[currentStringIdx], textLengthBuffer[currentStringIdx]);
  161.     currentStringIdx++;
  162. }
  163.  
  164. /// <param name="opcodeIdx">syncedOpcodes index</param>
  165. bool IsOpcodeSyncable(int* opcodeIdx = nullptr)
  166. {
  167.     if (CLocalPlayer::m_bIsHost
  168.         && COpCodeSync::ms_bSyncingEnabled
  169.         && (lastProcessedScript->m_bIsMission || (uintptr_t)lastProcessedScript->m_pBaseIP < 0xCB0600) // catch opcode calls only from the game memory
  170.         && !lastProcessedScript->m_bIsExternal)
  171.     {
  172.         for (int i = 0; i < ARRAY_SIZE(syncedOpcodes); i++)
  173.         {
  174.             if (syncedOpcodes[i].m_wOpCode == lastOpCodeProcessed)
  175.             {
  176.                 if (opcodeIdx)
  177.                 {
  178.                     *opcodeIdx = i;
  179.                 }
  180.  
  181.                 return true;
  182.             }
  183.         }
  184.     }
  185.     return false;
  186. }
  187.  
  188. void BuildAndSendOpcode()
  189. {
  190.     int idx = 0;
  191.     if (!IsOpcodeSyncable(&idx))
  192.         return;
  193.  
  194.     int dataSize =
  195.         sizeof(OpcodeSyncHeader)
  196.         + scriptParamCount * sizeof(int)
  197.         + textParamCount * sizeof(uint8_t);
  198.  
  199.     for (int i = 0; i < textParamCount; i++)
  200.     {
  201.         dataSize += textLengthBuffer[i];
  202.     }
  203.  
  204.     std::vector<uint8_t> buffer(dataSize);
  205.     uint8_t* current = buffer.data();
  206.  
  207.     OpcodeSyncHeader header;
  208.     header.opcode = lastOpCodeProcessed;
  209.     header.intParamCount = scriptParamCount;
  210.     header.stringParamCount = textParamCount;
  211.  
  212.     memcpy(current, &header, sizeof(header));
  213.     current += sizeof(header);
  214.  
  215.     if (scriptParamCount)
  216.     {
  217.         for (int i = 0; i < scriptParamCount; i++)
  218.         {
  219.             if (syncedOpcodes[idx].m_bHasComplexParams && i < 4)
  220.             {
  221.                 //CChat::AddMessage("Parsing complex opcode %04x parameter %d...", header.opcode, i);
  222.                 switch (syncedOpcodes[idx].m_aParamTypes[i])
  223.                 {
  224.                 case eSyncedParamType::PED:
  225.                 {
  226.                     //CChat::AddMessage("Trying to parse a ped handle %d...", scriptParamsBuffer[i].value);
  227.                     if (auto ped = CPools::GetPed(scriptParamsBuffer[i].value))
  228.                     {
  229.                         if (ped->m_nPedType > 3) // is a regular ped
  230.                         {
  231.                             if (auto networkPed = CNetworkPedManager::GetPed(ped))
  232.                             {
  233.                                 //CChat::AddMessage("Network id %d...", networkPed->m_nPedId);
  234.                                 if (networkPed->m_bSyncing)
  235.                                 {
  236.                                     scriptParamsBuffer[i].entityId = networkPed->m_nPedId;
  237.                                     scriptParamsBuffer[i].entityType = eSyncedParamType::PED;
  238.                                     //CChat::AddMessage("Parsed ped id %d...", networkPed->m_nPedId);
  239.                                 }
  240.                             }
  241.                         }
  242.                         else // is a player ped
  243.                         {
  244.                             if (ped == FindPlayerPed(0))
  245.                             {
  246.                                 scriptParamsBuffer[i].entityId = CNetworkPlayerManager::m_nMyId;
  247.                             }
  248.                             else if (auto networkPlayer = CNetworkPlayerManager::GetPlayer(ped))
  249.                             {
  250.                                 scriptParamsBuffer[i].entityId = networkPlayer->m_iPlayerId;
  251.                             }
  252.                             scriptParamsBuffer[i].entityType = eSyncedParamType::PLAYER;
  253.                         }
  254.                     }
  255.                    
  256.                     break;
  257.                 }
  258.                 case eSyncedParamType::PLAYER:
  259.                 {
  260.                     //CChat::AddMessage("Trying to parse a player...");
  261.                     if (!scriptParamsBuffer[i].value)
  262.                     {
  263.                         scriptParamsBuffer[i].entityType = eSyncedParamType::PLAYER;
  264.                         scriptParamsBuffer[i].entityId = CNetworkPlayerManager::m_nMyId;
  265.                         //CChat::AddMessage("Parsed player id %d (me)...", CNetworkPlayerManager::m_nMyId);
  266.                         break;
  267.                     }
  268.  
  269.                     if (auto player = CWorld::Players[scriptParamsBuffer[i].value].m_pPed)
  270.                     {
  271.                         if (auto networkPlayer = CNetworkPlayerManager::GetPlayer(player))
  272.                         {
  273.                             scriptParamsBuffer[i].entityType = eSyncedParamType::PLAYER;
  274.                             scriptParamsBuffer[i].entityId = networkPlayer->m_iPlayerId;
  275.                             //CChat::AddMessage("Parsed player id %d...", networkPlayer->m_iPlayerId);
  276.                         }
  277.                     }
  278.                     break;
  279.                 }
  280.                 case eSyncedParamType::VEHICLE:
  281.                 {
  282.                     //CChat::AddMessage("Trying to parse a vehicle...");
  283.                     if (auto vehicle = CPools::GetVehicle(scriptParamsBuffer[i].value))
  284.                     {
  285.                         if (auto networkVehicle = CNetworkVehicleManager::GetVehicle(vehicle))
  286.                         {
  287.                             scriptParamsBuffer[i].entityId = networkVehicle->m_nVehicleId;
  288.                             scriptParamsBuffer[i].entityType = eSyncedParamType::VEHICLE;
  289.                             //CChat::AddMessage("Parsed vehicle id %d...", networkVehicle->m_nVehicleId);
  290.                         }
  291.                     }
  292.  
  293.                     break;
  294.                 }
  295.                 default:
  296.                     break;
  297.                 }
  298.             }
  299.  
  300.             memcpy(current, &scriptParamsBuffer[i], sizeof(int));
  301.             current += sizeof(int);
  302.         }
  303.     }
  304.  
  305.     if(textParamCount)
  306.     {
  307.         for (int i = 0; i < textParamCount; i++)
  308.         {
  309.             *current = static_cast<uint8_t>(textLengthBuffer[i]);
  310.             current += sizeof(uint8_t);
  311.  
  312.             memcpy(current, textParamBuffer[i], textLengthBuffer[i]);
  313.             current += textLengthBuffer[i];
  314.         }
  315.     }
  316.  
  317.     CNetwork::SendPacket(CPacketsID::OPCODE_SYNC, buffer.data(), dataSize, ENET_PACKET_FLAG_RELIABLE);
  318.  
  319.     memset(textParamBuffer, 0, sizeof textParamBuffer);
  320.     memset(textLengthBuffer, 0, sizeof textLengthBuffer);
  321.     scriptParamCount = 0;
  322.     textParamCount = 0;
  323. }
  324.  
  325. void COpCodeSync::HandlePacket(const uint8_t* buffer, int bufferSize)
  326. {
  327.     if (!buffer || bufferSize < sizeof(OpcodeSyncHeader))
  328.     {
  329.         return;
  330.     }
  331.  
  332.     const uint8_t* current = buffer;
  333.  
  334.     OpcodeSyncHeader header;
  335.     memcpy(&header, current, sizeof(header));
  336.     current += sizeof(header);
  337.  
  338.     if (bufferSize < sizeof(header) + header.intParamCount * sizeof(int))
  339.     {
  340.         return;
  341.     }
  342.  
  343.     memset(scriptParamsBuffer, 0, sizeof(scriptParamsBuffer));
  344.     memset(textLengthBuffer, 0, sizeof(textLengthBuffer));
  345.     memset(textParamBuffer, 0, sizeof(textParamBuffer));
  346.     scriptParamCount = 0;
  347.     textParamCount = 0;
  348.     currentStringIdx = 0;
  349.  
  350.     scriptParamCount = header.intParamCount;
  351.     if (scriptParamCount > 10) scriptParamCount = 10;
  352.  
  353.     textParamCount = header.stringParamCount;
  354.     if (textParamCount > 10) textParamCount = 10;
  355.  
  356.     if (scriptParamCount)
  357.     {
  358.         memcpy(scriptParamsBuffer, current, scriptParamCount * sizeof(int));
  359.         current += scriptParamCount * sizeof(int);
  360.  
  361.         int idx = 0;
  362.         bool found = false;
  363.         for (; idx < ARRAY_SIZE(syncedOpcodes); idx++)
  364.         {
  365.             if (syncedOpcodes[idx].m_wOpCode == header.opcode)
  366.             {
  367.                 found = true;
  368.                 break;
  369.             }
  370.         }
  371.  
  372.         if(!found)
  373.             return;
  374.  
  375.         if (syncedOpcodes[idx].m_bHasComplexParams)
  376.         {
  377.             //CChat::AddMessage("Parsing complex opcode %04x...", header.opcode);
  378.             int max = min(scriptParamCount, 4);
  379.             for (int i = 0; i < max; i++)
  380.             {
  381.                 switch (syncedOpcodes[idx].m_aParamTypes[i])
  382.                 {
  383.                 case eSyncedParamType::PED:
  384.                 {
  385.                     //CChat::AddMessage("Parsing ped...");
  386.                     if (scriptParamsBuffer[i].entityType == eSyncedParamType::PED)
  387.                     {
  388.                         //CChat::AddMessage("Trying to parse as a regular ped...");
  389.                         if (auto networkPed = CNetworkPedManager::GetPed(scriptParamsBuffer[i].entityId))
  390.                         {
  391.                             //CChat::AddMessage("Network instance found...");
  392.                             if (auto ped = networkPed->m_pPed)
  393.                             {
  394.                                 scriptParamsBuffer[i].value = CPools::GetPedRef(ped);
  395.                                 //CChat::AddMessage("Parsed ped id %d...", networkPed->m_nPedId);
  396.                             }
  397.                             else return;
  398.                         }
  399.                         else return;
  400.  
  401.                     }
  402.                     else
  403.                     {
  404.                         if (scriptParamsBuffer[i].entityId == CNetworkPlayerManager::m_nMyId)
  405.                         {
  406.                             if (auto playerPed = FindPlayerPed(0))
  407.                             {
  408.                                 scriptParamsBuffer[i].value = CPools::GetPedRef(playerPed);
  409.                             }
  410.                         }
  411.                         else
  412.                         {
  413.                             //CChat::AddMessage("Trying to parse as a player ped... %d", scriptParamsBuffer[i].entityId);
  414.                             if (auto networkPlayer = CNetworkPlayerManager::GetPlayer(scriptParamsBuffer[i].entityId))
  415.                             {
  416.                                 //CChat::AddMessage("Network instance found...");
  417.                                 if (auto ped = networkPlayer->m_pPed)
  418.                                 {
  419.                                     scriptParamsBuffer[i].value = CPools::GetPedRef(ped);
  420.                                     //CChat::AddMessage("Parsed player id as ped %d...", networkPlayer->m_iPlayerId);
  421.                                 }
  422.                                 else return;
  423.                             }
  424.                             else return;
  425.                         }
  426.                     }
  427.  
  428.                     break;
  429.                 }
  430.                 case eSyncedParamType::PLAYER:
  431.                 {
  432.                     if (scriptParamsBuffer[i].entityId == CNetworkPlayerManager::m_nMyId)
  433.                     {
  434.                         scriptParamsBuffer[i].value = 0;
  435.                         //CChat::AddMessage("Parsed player id %d (me)...", CNetworkPlayerManager::m_nMyId);
  436.                         break;
  437.                     }
  438.  
  439.                     if (auto networkPlayer = CNetworkPlayerManager::GetPlayer(scriptParamsBuffer[i].entityId))
  440.                     {
  441.                         if (networkPlayer->m_pPed)
  442.                         {
  443.                             int playerNum = networkPlayer->GetInternalId();
  444.                             if (playerNum)
  445.                             {
  446.                                 scriptParamsBuffer[i].value = playerNum;
  447.                                 //CChat::AddMessage("Parsed player id %d...", networkPlayer->m_iPlayerId);
  448.                             }
  449.                             else return;
  450.                         }
  451.                         else return;
  452.                     }
  453.                     else return;
  454.  
  455.                     break;
  456.                 }
  457.                 case eSyncedParamType::VEHICLE:
  458.                 {
  459.                     if (auto networkVehicle = CNetworkVehicleManager::GetVehicle(scriptParamsBuffer[i].entityId))
  460.                     {
  461.                         if (auto vehicle = networkVehicle->m_pVehicle)
  462.                         {
  463.                             scriptParamsBuffer[i].value = CPools::GetVehicleRef(vehicle);
  464.                            // CChat::AddMessage("Parsed vehicle id %d...", networkVehicle->m_nVehicleId);
  465.                         }
  466.                         else return;
  467.                     }
  468.                     else return;
  469.  
  470.                     break;
  471.                 }
  472.                 default:
  473.                     break;
  474.                 }
  475.             }
  476.             //CChat::AddMessage("OK");
  477.         }
  478.     }
  479.  
  480.     if (textParamCount)
  481.     {
  482.         for (int i = 0; i < textParamCount; i++)
  483.         {
  484.             if (current >= buffer + bufferSize)
  485.             {
  486.                 return;
  487.             }
  488.  
  489.             textLengthBuffer[i] = *current;
  490.             current += sizeof(uint8_t);
  491.  
  492.             if (current + textLengthBuffer[i] > buffer + bufferSize || textLengthBuffer[i] > 255)
  493.             {
  494.                 return;
  495.             }
  496.  
  497.             memcpy(textParamBuffer[i], current, textLengthBuffer[i]);
  498.             textParamBuffer[i][textLengthBuffer[i]] = '\0';
  499.             current += textLengthBuffer[i];
  500.         }
  501.     }
  502.  
  503.  
  504.     static CRunningScript script;
  505.     memset(&script, 0, sizeof(CRunningScript));
  506.     script.Init();
  507.     script.m_bIsMission = true;
  508.     script.m_bUseMissionCleanup = false;
  509.     strcpy(script.m_szName, "coopand");
  510.     script.m_pBaseIP = script.m_pCurrentIP = (uint8_t*)&header.opcode;
  511.  
  512.     lastOpCodeProcessed = header.opcode;
  513.  
  514.     // TODO: refactor
  515.     if (lastOpCodeProcessed == 0x0701) // end_scene_skip
  516.     {
  517.         CHud::m_BigMessage[1][0] = 0;
  518.     }
  519.     else if (lastOpCodeProcessed == 0x02E7) // start_cutscene
  520.     {
  521.         if(CCutsceneMgr::ms_cutsceneLoadStatus != 2)
  522.         {
  523.             COpCodeSync::ms_bLoadingCutscene = true;
  524.             return; // dont process opcode
  525.         }
  526.     }
  527.  
  528.     patch::RedirectJump(0x464080, CRunningScript__CollectParameters_Hook_SwitchParametersContext, false);
  529.     patch::RedirectJump(0x463D50, CRunningScript__ReadTextLabelFromScript_Hook_SwitchParametersContext, false);
  530.  
  531.     if ((header.opcode & 0x7FFF) < CCustomCommandMgr::MIN_CUSTOM_COMMAND)
  532.     {
  533.         CRunningScript::CommandHandlerTable[(header.opcode & 0x7FFF) / 100](&script, header.opcode & 0x7FFF);
  534.     }
  535.     else
  536.     {
  537.         CCustomCommandMgr::ProcessCommand((header.opcode & 0x7FFF), &script);
  538.     }
  539.  
  540.     patch::SetRaw(0x464080, "\x66\x8B\x44\x24\x04", 5, false);
  541.     patch::SetRaw(0x463D50, "\x8B\x41\x14\x83\xEC\x08", 6, false);
  542. }
  543.  
  544. void __declspec(naked) OpcodeProcessingWellDone_Hook()
  545. {
  546.     __asm
  547.     {
  548.         mov lastOpCodeProcessed, ecx
  549.         mov lastProcessedScript, esi
  550.  
  551.         mov ecx, esi
  552.         call edx
  553.  
  554.         push eax
  555.         call BuildAndSendOpcode
  556.         pop eax
  557.  
  558.         test al, al
  559.  
  560.         push 0x469FF9
  561.         ret
  562.     }
  563. }
  564.  
  565. void __declspec(naked) CRunningScript__CollectParameters_Hook_GetSyncingParams()
  566. {
  567.     __asm
  568.     {
  569.         pop ebx
  570.         mov eax, [esp + 0x4]
  571.         mov scriptParamCount, ax
  572.  
  573.         pop eax
  574.         add esp, 4
  575.  
  576.         pushad
  577.     }
  578.  
  579.     if (lastProcessedScript
  580.         && IsOpcodeSyncable())
  581.     {
  582.         memcpy(scriptParamsBuffer, ScriptParams, scriptParamCount * sizeof(int));
  583.     }
  584.     else
  585.     {
  586.         scriptParamCount = 0;
  587.     }
  588.  
  589.     __asm
  590.     {
  591.         popad
  592.         jmp eax
  593.     }
  594. }
  595.  
  596. static char* textPointer;
  597. static uint8_t textLength;
  598. void CollectTextParameters()
  599. {
  600.     if (textPointer
  601.         && lastProcessedScript
  602.         && IsOpcodeSyncable())
  603.     {
  604.         textLengthBuffer[textParamCount] = min(textLength, strlen(textPointer));
  605.         strncpy_s(textParamBuffer[textParamCount], textPointer, textLengthBuffer[textParamCount]);
  606.         textParamCount++;
  607.     }
  608. }
  609.  
  610. void __declspec(naked) CRunningScript__ReadTextLabelFromScript_Hook_GetSyncingParams()
  611. {
  612.     __asm
  613.     {
  614.         add esp, 8
  615.  
  616.         mov eax, [esp + 0x4]
  617.         mov textPointer, eax
  618.  
  619.         mov eax, [esp + 0x8]
  620.         mov textLength, al
  621.  
  622.         call CollectTextParameters
  623.  
  624.         retn 8
  625.     }
  626. }
  627.  
  628.  
  629.  
  630. void COpCodeSync::Init()
  631. {
  632.     DWORD temp;
  633.     injector::UnprotectMemory(0x464080, 5, temp);
  634.     injector::UnprotectMemory(0x463D50, 6, temp);
  635.  
  636.     patch::RedirectJump(0x469FF3, OpcodeProcessingWellDone_Hook);
  637.  
  638.     std::vector<int> hookPositions = { 0x463D92, 0x463DBF, 0x463E1A, 0x463E6B, 0x463EAC, 0x463F2A, 0x463F7F, 0x463FA2, 0x463FDA, 0x463FFB, 0x464034 };
  639.     patch::RedirectJump(hookPositions, CRunningScript__ReadTextLabelFromScript_Hook_GetSyncingParams);
  640.     patch::RedirectJump(0x46421D, CRunningScript__CollectParameters_Hook_GetSyncingParams);
  641. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement