diff --git a/_work/data/Scripts/Content/freeAim/_intern/aimRay.d b/_work/data/Scripts/Content/freeAim/_intern/aimRay.d index 8c5c3cb..81775be 100644 --- a/_work/data/Scripts/Content/freeAim/_intern/aimRay.d +++ b/_work/data/Scripts/Content/freeAim/_intern/aimRay.d @@ -24,121 +24,7 @@ /* Shoot aim-tailored trace ray. Do no use for other purposes. This function is customized for aiming. */ func int freeAimRay(var int distance, var int focusType, var int vobPtr, var int posPtr, var int distPtr, var int trueDistPtr) { - // Flags: VOB_IGNORE_NO_CD_DYN | POLY_IGNORE_TRANSP | POLY_TEST_WATER | VOB_IGNORE_PROJECTILES - var int flags; flags = (1<<0) | (1<<8) | (1<<9) | (1<<14); // Do not change (will make trace ray unstable) - var zMAT4 camPos; camPos = _^(MEM_ReadInt(MEM_ReadInt(MEMINT_oGame_Pointer_Address)+20)+60); //0=right, 2=out, 3=pos var int herPtr; herPtr = _@(hero); - // Shift the start point for the trace ray beyond the player model. Necessary, because if zooming out, - // (1) there might be something between camera and hero and (2) the maximum aiming distance is off. - var int dist; dist = sqrtf(addf(addf( // Distance between camera and player model (does not care about cam offset) - sqrf(subf(MEM_ReadInt(herPtr+72), camPos.v0[3])), - sqrf(subf(MEM_ReadInt(herPtr+88), camPos.v1[3]))), - sqrf(subf(MEM_ReadInt(herPtr+104), camPos.v2[3])))); - if (FREEAIM_CAMERA_X_SHIFT) { // Shifting the camera (shoulderview) is not recommended. Aiming is harder + less fps? - // This makes the distance mentioned above more complex and requires the calculation of a point-line distance - // For illustration: http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html - var int line[6]; // Line with two points along the camera right vector at the level of the player model - line[0] = subf(MEM_ReadInt(herPtr+72), mulf(camPos.v0[0], FLOAT1K)); // Left of player model - line[1] = subf(MEM_ReadInt(herPtr+88), mulf(camPos.v1[0], FLOAT1K)); - line[2] = subf(MEM_ReadInt(herPtr+104), mulf(camPos.v2[0], FLOAT1K)); - line[3] = addf(MEM_ReadInt(herPtr+72), mulf(camPos.v0[0], FLOAT1K)); // Right of player model - line[4] = addf(MEM_ReadInt(herPtr+88), mulf(camPos.v1[0], FLOAT1K)); - line[5] = addf(MEM_ReadInt(herPtr+104), mulf(camPos.v2[0], FLOAT1K)); - var int u[3]; var int v[3]; // Subtract both points of the line from the camera position - u[0] = subf(camPos.v0[3], line[0]); v[0] = subf(camPos.v0[3], line[3]); - u[1] = subf(camPos.v1[3], line[1]); v[1] = subf(camPos.v1[3], line[4]); - u[2] = subf(camPos.v2[3], line[2]); v[2] = subf(camPos.v2[3], line[5]); - var int crossProd[3]; // Cross-product - crossProd[0] = subf(mulf(u[1], v[2]), mulf(u[2], v[1])); - crossProd[1] = subf(mulf(u[2], v[0]), mulf(u[0], v[2])); - crossProd[2] = subf(mulf(u[0], v[1]), mulf(u[1], v[0])); - dist = sqrtf(addf(addf(sqrf(crossProd[0]), sqrf(crossProd[1])), sqrf(crossProd[2]))); - dist = divf(dist, mkf(2000)); // Divide area of triangle by length between the points on the line - }; - var int traceRayVec[6]; - traceRayVec[0] = addf(camPos.v0[3], mulf(camPos.v0[2], dist)); // Start ray from here - traceRayVec[1] = addf(camPos.v1[3], mulf(camPos.v1[2], dist)); - traceRayVec[2] = addf(camPos.v2[3], mulf(camPos.v2[2], dist)); - traceRayVec[3] = mulf(camPos.v0[2], mkf(distance)); // Direction-/to-vector of ray - traceRayVec[4] = mulf(camPos.v1[2], mkf(distance)); - traceRayVec[5] = mulf(camPos.v2[2], mkf(distance)); - var int fromPosPtr; fromPosPtr = _@(traceRayVec); - var int dirPosPtr; dirPosPtr = _@(traceRayVec)+12; - var int worldPtr; worldPtr = _@(MEM_World); - const int call = 0; - if (CALL_Begin(call)) { - CALL_IntParam(_@(flags)); // Trace ray flags - CALL_PtrParam(_@(herPtr)); // Ignore player model - CALL_PtrParam(_@(dirPosPtr)); // Trace ray direction - CALL__fastcall(_@(worldPtr), _@(fromPosPtr), zCWorld__TraceRayNearestHit_Vob); - call = CALL_End(); - }; - var int found; found = CALL_RetValAsInt(); // Did the trace ray hit - if (!found) && (!MEM_World.foundVob) { // Fix the intersection if there was no hit (trace ray is inconsistent) - MEM_World.foundIntersection[0] = addf(traceRayVec[0], traceRayVec[3]); - MEM_World.foundIntersection[1] = addf(traceRayVec[1], traceRayVec[4]); - MEM_World.foundIntersection[2] = addf(traceRayVec[2], traceRayVec[5]); - }; - var int foundFocus; foundFocus = 0; // Is the focus vob in the trace ray vob list - var int potentialVob; potentialVob = MEM_ReadInt(herPtr+2476); // oCNpc.focus_vob // Focus vob by focus collection - if (potentialVob) { // Check if collected focus matches the desired focus type - var int runDetailedTraceRay; runDetailedTraceRay = 0; // Second trace ray only if focus vob is reasonable - if (!focusType) { // No focus vob (still a trace ray though) - foundFocus = 0; - } else if (focusType != TARGET_TYPE_ITEMS) && (Hlp_Is_oCNpc(potentialVob)) { // Validate focus vob, if it is npc - var C_Npc target; target = _^(potentialVob); - MEM_PushInstParam(target); // Function is not defined yet at time of parsing: - MEM_Call(C_NpcIsUndead); // C_NpcIsUndead(target); - var int npcIsUndead; npcIsUndead = MEM_PopIntResult(); - if ((focusType == TARGET_TYPE_NPCS) // Any npc - || ((focusType == TARGET_TYPE_ORCS) && target.guild > GIL_SEPERATOR_ORC) // Only focus orcs - || ((focusType == TARGET_TYPE_HUMANS) && target.guild < GIL_SEPERATOR_HUM) // Only focus humans - || ((focusType == TARGET_TYPE_UNDEAD) && npcIsUndead)) // Only focus undead npcs - && (!Npc_IsInState(target, ZS_Unconscious)) // Do not allow focusing npcs that are down - && (!Npc_IsInState(target, ZS_MagicSleep)) - && (!Npc_IsDead(target)) { - var int potVobPtr; potVobPtr = _@(potentialVob); - var int voblist; voblist = _@(MEM_World.traceRayVobList_array); - const int call2 = 0; - if (CALL_Begin(call2)) { // More complicated for npcs: Check if npc is in trace ray vob list - CALL_PtrParam(_@(potVobPtr)); // Explanation: Npcs are never HIT by a trace ray (only collected) - CALL__thiscall(_@(voblist), zCArray_zCVob__IsInList); - call2 = CALL_End(); - }; - runDetailedTraceRay = CALL_RetValAsInt(); // Will perform detailed trace ray if npc was in vob list - }; - } else if (focusType <= TARGET_TYPE_ITEMS) && (Hlp_Is_oCItem(potentialVob)) { - runDetailedTraceRay = 1; // Will perform detailed trace ray - }; - if (runDetailedTraceRay) { // If focus collection is reasonable, run a more detailed examination - // zCWorld::TraceRayNearestHit (0x621D82 in g2) - flags = (1<<0) | (1<<2); // (zTRACERAY_VOB_IGNORE_NO_CD_DYN | zTRACERAY_VOB_BBOX) // Important! - var int trRep; trRep = MEM_Alloc(40); // sizeof_zTTraceRayReport - const int call3 = 0; - if (CALL_Begin(call3)) { - CALL_PtrParam(_@(trRep)); // zTTraceRayReport - CALL_IntParam(_@(flags)); // Trace ray flags - CALL_PtrParam(_@(dirPosPtr)); // Trace ray direction - CALL_PtrParam(_@(fromPosPtr)); // Start vector - CALL__thiscall(_@(potentialVob), zCVob__TraceRay); // This is a vob specific trace ray - call3 = CALL_End(); - }; - if (CALL_RetValAsInt()) { // Got a hit: Update trace ray report - MEM_World.foundVob = potentialVob; - MEM_CopyWords(trRep+12, _@(MEM_World.foundIntersection), 3); // 0x0C zVEC3 - foundFocus = potentialVob; // Confirmed focus vob - }; - MEM_Free(trRep); // Free the report - }; - }; - if (foundFocus != potentialVob) { // If focus vob changed by the validation above - const int call4 = 0; // Set the focus vob properly: reference counter - if (CALL_Begin(call4)) { - CALL_PtrParam(_@(foundFocus)); // If no valid focus was found, this will remove the focus (foundFocus == 0) - CALL__thiscall(_@(herPtr), oCNpc__SetFocusVob); - call4 = CALL_End(); - }; - }; if (MEM_ReadInt(herPtr+1176)) { //0x0498 oCNpc.enemy const int call5 = 0; var int null; // Remove the enemy properly: reference counter if (CALL_Begin(call5)) { @@ -147,36 +33,155 @@ func int freeAimRay(var int distance, var int focusType, var int vobPtr, var int call5 = CALL_End(); }; }; - // Debug visualization - if (FREEAIM_DEBUG_TRACERAY) { - freeAimDebugTRBBox[0] = subf(MEM_World.foundIntersection[0], mkf(5)); - freeAimDebugTRBBox[1] = subf(MEM_World.foundIntersection[1], mkf(5)); - freeAimDebugTRBBox[2] = subf(MEM_World.foundIntersection[2], mkf(5)); - freeAimDebugTRBBox[3] = addf(freeAimDebugTRBBox[0], mkf(10)); - freeAimDebugTRBBox[4] = addf(freeAimDebugTRBBox[1], mkf(10)); - freeAimDebugTRBBox[5] = addf(freeAimDebugTRBBox[2], mkf(10)); - MEM_CopyWords(_@(traceRayVec), _@(freeAimDebugTRTrj), 3); - freeAimDebugTRTrj[3] = addf(traceRayVec[0], traceRayVec[3]); - freeAimDebugTRTrj[4] = addf(traceRayVec[1], traceRayVec[4]); - freeAimDebugTRTrj[5] = addf(traceRayVec[2], traceRayVec[5]); - if (MEM_World.foundVob) { freeAimDebugTRPrevVob = MEM_World.foundVob+124; } else { freeAimDebugTRPrevVob = 0; }; + // Only run full trace ray machinery every so often (see freeAimTraceRayFreq) + var int curTime; curTime = MEM_Timer.totalTime; + if (curTime-prevCalculationTime >= freeAimTraceRayFreq) || (foundFocus != MEM_ReadInt(herPtr+2476)) { + var int prevCalculationTime; prevCalculationTime = curTime; + // Flags: VOB_IGNORE_NO_CD_DYN | POLY_IGNORE_TRANSP | POLY_TEST_WATER | VOB_IGNORE_PROJECTILES + var int flags; flags = (1<<0) | (1<<8) | (1<<9) | (1<<14); // Do not change (will make trace ray unstable) + var zMAT4 camPos; camPos = _^(MEM_ReadInt(MEM_ReadInt(MEMINT_oGame_Pointer_Address)+20)+60); + // Shift the start point for the trace ray beyond the player model. Necessary, because if zooming out, + // (1) there might be something between camera and hero and (2) the maximum aiming distance is off. + var int distCamToPlayer; distCamToPlayer = sqrtf(addf(addf( // Does not care about camera offset (camera shift) + sqrf(subf(MEM_ReadInt(herPtr+72), camPos.v0[3])), + sqrf(subf(MEM_ReadInt(herPtr+88), camPos.v1[3]))), + sqrf(subf(MEM_ReadInt(herPtr+104), camPos.v2[3])))); + if (FREEAIM_CAMERA_X_SHIFT) { // Shifting camera (shoulderview) is not recommended. Aiming is harder + less fps? + // This makes the distance mentioned above more complex and requires calculation of a point-line distance + // For illustration: http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html + var int line[6]; // Line with two points along the camera right vector at the level of the player model + line[0] = subf(MEM_ReadInt(herPtr+72), mulf(camPos.v0[0], FLOAT1K)); // Left of player model + line[1] = subf(MEM_ReadInt(herPtr+88), mulf(camPos.v1[0], FLOAT1K)); + line[2] = subf(MEM_ReadInt(herPtr+104), mulf(camPos.v2[0], FLOAT1K)); + line[3] = addf(MEM_ReadInt(herPtr+72), mulf(camPos.v0[0], FLOAT1K)); // Right of player model + line[4] = addf(MEM_ReadInt(herPtr+88), mulf(camPos.v1[0], FLOAT1K)); + line[5] = addf(MEM_ReadInt(herPtr+104), mulf(camPos.v2[0], FLOAT1K)); + var int u[3]; var int v[3]; // Subtract both points of the line from the camera position + u[0] = subf(camPos.v0[3], line[0]); v[0] = subf(camPos.v0[3], line[3]); + u[1] = subf(camPos.v1[3], line[1]); v[1] = subf(camPos.v1[3], line[4]); + u[2] = subf(camPos.v2[3], line[2]); v[2] = subf(camPos.v2[3], line[5]); + var int crossProd[3]; // Cross-product + crossProd[0] = subf(mulf(u[1], v[2]), mulf(u[2], v[1])); + crossProd[1] = subf(mulf(u[2], v[0]), mulf(u[0], v[2])); + crossProd[2] = subf(mulf(u[0], v[1]), mulf(u[1], v[0])); + distCamToPlayer = sqrtf(addf(addf(sqrf(crossProd[0]), sqrf(crossProd[1])), sqrf(crossProd[2]))); + distCamToPlayer = divf(distCamToPlayer, mkf(2000)); // Divide area of triangle by length between points + }; + distance = mkf(distance); + var int traceRayVec[6]; + traceRayVec[0] = addf(camPos.v0[3], mulf(camPos.v0[2], distCamToPlayer)); // Start ray from here + traceRayVec[1] = addf(camPos.v1[3], mulf(camPos.v1[2], distCamToPlayer)); + traceRayVec[2] = addf(camPos.v2[3], mulf(camPos.v2[2], distCamToPlayer)); + traceRayVec[3] = mulf(camPos.v0[2], distance); // Direction-/to-vector of ray + traceRayVec[4] = mulf(camPos.v1[2], distance); + traceRayVec[5] = mulf(camPos.v2[2], distance); + var int fromPosPtr; fromPosPtr = _@(traceRayVec); + var int dirPosPtr; dirPosPtr = _@(traceRayVec)+12; + var int worldPtr; worldPtr = _@(MEM_World); + const int call = 0; + if (CALL_Begin(call)) { + CALL_IntParam(_@(flags)); // Trace ray flags + CALL_PtrParam(_@(herPtr)); // Ignore player model + CALL_PtrParam(_@(dirPosPtr)); // Trace ray direction + CALL__fastcall(_@(worldPtr), _@(fromPosPtr), zCWorld__TraceRayNearestHit_Vob); + call = CALL_End(); + }; + var int hit; hit = CALL_RetValAsInt(); // Did the trace ray hit + var int foundVob; foundVob = MEM_World.foundVob; + var int intersection[3]; MEM_CopyWords(_@(MEM_World.foundIntersection), _@(intersection), 3); + var int distHitToPlayer; + if (!hit) && (!foundVob) { // Fix the intersection if there was no hit (trace ray is inconsistent) + intersection[0] = addf(traceRayVec[0], traceRayVec[3]); + intersection[1] = addf(traceRayVec[1], traceRayVec[4]); + intersection[2] = addf(traceRayVec[2], traceRayVec[5]); + distHitToPlayer = distance; // Maximum distance of trace ray + } else { + distHitToPlayer = sqrtf(addf(addf( + sqrf(subf(intersection[0], traceRayVec[0])), + sqrf(subf(intersection[1], traceRayVec[1]))), + sqrf(subf(intersection[2], traceRayVec[2])))); + }; + var int distHitToCam; distHitToCam = addf(distHitToPlayer, distCamToPlayer); + var int foundFocus; foundFocus = 0; // Is the focus vob in the trace ray vob list + var int potentialVob; potentialVob = MEM_ReadInt(herPtr+2476); // oCNpc.focus_vob // Focus vob by f-collection + if (potentialVob) { // Check if collected focus matches the desired focus type + var int runDetailedTraceRay; runDetailedTraceRay = 0; // Second trace ray only if focus vob is reasonable + if (!focusType) { // No focus vob (still a trace ray though) + foundFocus = 0; + } else if (focusType != TARGET_TYPE_ITEMS) && (Hlp_Is_oCNpc(potentialVob)) { // Validate focus vob, if npc + var C_Npc target; target = _^(potentialVob); + MEM_PushInstParam(target); // Function is not defined yet at time of parsing: + MEM_Call(C_NpcIsUndead); // C_NpcIsUndead(target); + var int npcIsUndead; npcIsUndead = MEM_PopIntResult(); + MEM_PushInstParam(target); // Function is not defined yet at time of parsing: + MEM_Call(C_NpcIsDown); // C_NpcIsDown(target); + var int npcIsDown; npcIsUndead = MEM_PopIntResult(); + if ((focusType == TARGET_TYPE_NPCS) // Any npc + || ((focusType == TARGET_TYPE_ORCS) && target.guild > GIL_SEPERATOR_ORC) // Only focus orcs + || ((focusType == TARGET_TYPE_HUMANS) && target.guild < GIL_SEPERATOR_HUM) // Only focus humans + || ((focusType == TARGET_TYPE_UNDEAD) && npcIsUndead)) // Only focus undead npcs + && (!npcIsDown) { + var int potVobPtr; potVobPtr = _@(potentialVob); + var int voblist; voblist = _@(MEM_World.traceRayVobList_array); + const int call2 = 0; + if (CALL_Begin(call2)) { // More complicated for npcs: Check if npc is in trace ray vob list + CALL_PtrParam(_@(potVobPtr)); // Explanation: Npcs are never HIT by a trace ray (only collected) + CALL__thiscall(_@(voblist), zCArray_zCVob__IsInList); + call2 = CALL_End(); + }; + runDetailedTraceRay = CALL_RetValAsInt(); // Will perform detailed trace ray if npc was in vob list + }; + } else if (focusType <= TARGET_TYPE_ITEMS) && (Hlp_Is_oCItem(potentialVob)) { + runDetailedTraceRay = 1; // Will perform detailed trace ray + }; + if (runDetailedTraceRay) { // If focus collection is reasonable, run a more detailed examination + // zCWorld::TraceRayNearestHit (0x621D82 in g2) + flags = (1<<0) | (1<<2); // (zTRACERAY_VOB_IGNORE_NO_CD_DYN | zTRACERAY_VOB_BBOX) // Important! + var int trRep; trRep = MEM_Alloc(40); // sizeof_zTTraceRayReport + const int call3 = 0; + if (CALL_Begin(call3)) { + CALL_PtrParam(_@(trRep)); // zTTraceRayReport + CALL_IntParam(_@(flags)); // Trace ray flags + CALL_PtrParam(_@(dirPosPtr)); // Trace ray direction + CALL_PtrParam(_@(fromPosPtr)); // Start vector + CALL__thiscall(_@(potentialVob), zCVob__TraceRay); // This is a vob specific trace ray + call3 = CALL_End(); + }; + if (CALL_RetValAsInt()) { // Got a hit: Update trace ray report + foundVob = potentialVob; + MEM_CopyWords(trRep+12, _@(intersection), 3); // 0x0C zVEC3 + foundFocus = potentialVob; // Confirmed focus vob + }; + MEM_Free(trRep); // Free the report + }; + }; + if (foundFocus != potentialVob) { // If focus vob changed by the validation above + const int call4 = 0; // Set the focus vob properly: reference counter + if (CALL_Begin(call4)) { + CALL_PtrParam(_@(foundFocus)); // If no valid focus found, this will remove the focus (foundFocus == 0) + CALL__thiscall(_@(herPtr), oCNpc__SetFocusVob); + call4 = CALL_End(); + }; + }; + // Debug visualization + if (FREEAIM_DEBUG_TRACERAY) { + freeAimDebugTRBBox[0] = subf(intersection[0], mkf(5)); + freeAimDebugTRBBox[1] = subf(intersection[1], mkf(5)); + freeAimDebugTRBBox[2] = subf(intersection[2], mkf(5)); + freeAimDebugTRBBox[3] = addf(freeAimDebugTRBBox[0], mkf(10)); + freeAimDebugTRBBox[4] = addf(freeAimDebugTRBBox[1], mkf(10)); + freeAimDebugTRBBox[5] = addf(freeAimDebugTRBBox[2], mkf(10)); + MEM_CopyWords(_@(traceRayVec), _@(freeAimDebugTRTrj), 3); + freeAimDebugTRTrj[3] = addf(traceRayVec[0], traceRayVec[3]); + freeAimDebugTRTrj[4] = addf(traceRayVec[1], traceRayVec[4]); + freeAimDebugTRTrj[5] = addf(traceRayVec[2], traceRayVec[5]); + if (foundVob) { freeAimDebugTRPrevVob = foundVob+124; } else { freeAimDebugTRPrevVob = 0; }; + }; }; // Write call-by-reference variables - if (vobPtr) { MEM_WriteInt(vobPtr, MEM_World.foundVob); }; - if (posPtr) { MEM_CopyWords(_@(MEM_World.foundIntersection), posPtr, 3); }; - if (distPtr) { // Distance between intersection and player model - distance = sqrtf(addf(addf( - sqrf(subf(MEM_World.foundIntersection[0], traceRayVec[0])), - sqrf(subf(MEM_World.foundIntersection[1], traceRayVec[1]))), - sqrf(subf(MEM_World.foundIntersection[2], traceRayVec[2])))); - MEM_WriteInt(distPtr, distance); - }; - if (trueDistPtr) { // Distance between intersection and camera - distance = sqrtf(addf(addf( - sqrf(subf(MEM_World.foundIntersection[0], camPos.v0[3])), - sqrf(subf(MEM_World.foundIntersection[1], camPos.v1[3]))), - sqrf(subf(MEM_World.foundIntersection[2], camPos.v2[3])))); - MEM_WriteInt(trueDistPtr, distance); - }; - return found; + if (vobPtr) { MEM_WriteInt(vobPtr, foundVob); }; + if (posPtr) { MEM_CopyWords(_@(intersection), posPtr, 3); }; + if (distPtr) { MEM_WriteInt(distPtr, distHitToPlayer); }; + if (trueDistPtr) { MEM_WriteInt(trueDistPtr, distHitToCam); }; + return hit; }; diff --git a/_work/data/Scripts/Content/freeAim/_intern/ccommands.d b/_work/data/Scripts/Content/freeAim/_intern/ccommands.d index 7be1b8d..df37584 100644 --- a/_work/data/Scripts/Content/freeAim/_intern/ccommands.d +++ b/_work/data/Scripts/Content/freeAim/_intern/ccommands.d @@ -55,7 +55,8 @@ func string freeAimInfo(var string command) { var int s; s = SB_New(); SB(FREEAIM_VERSION); SBc(13); SBc(10); SB("Enabled: "); SB(MEM_ReadStatStringArr(onOff, STR_ToInt(MEM_GetGothOpt("FREEAIM", "enabled")))); SBc(13);SBc(10); - SB("Focus: "); SB(MEM_ReadStatStringArr(onOff, FREEAIM_FOCUS_COLLECTION)); SBc(13); SBc(10); + SB("Focus: "); SB(MEM_ReadStatStringArr(onOff, FREEAIM_FOCUS_COLLECTION)); + SB(" ("); SBi(freeAimTraceRayFreq); SB(" ms collection frequency)"); SBc(13); SBc(10); SB("Reuse projectiles: "); SB(MEM_ReadStatStringArr(onOff, FREEAIM_REUSE_PROJECTILES)); SBc(13); SBc(10); SB("Free aim for spells: "); SB(MEM_ReadStatStringArr(onOff, !FREEAIM_DISABLE_SPELLS)); SBc(13); SBc(10); var string ret; ret = SB_ToString(); SB_Destroy(); diff --git a/_work/data/Scripts/Content/freeAim/_intern/const.d b/_work/data/Scripts/Content/freeAim/_intern/const.d index df1a6b9..f5a7cdd 100644 --- a/_work/data/Scripts/Content/freeAim/_intern/const.d +++ b/_work/data/Scripts/Content/freeAim/_intern/const.d @@ -37,6 +37,7 @@ const int FREEAIM_ARROWAI_REDIRECT = 0; // Used to redir const int FLOAT1C = 1120403456; // 100 as float const int FLOAT3C = 1133903872; // 300 as float const int FLOAT1K = 1148846080; // 1000 as float +var int freeAimTraceRayFreq; // Trace ray frequency (change in ini-file) var int freeAimDebugWSBBox[6]; // Weaksopt boundingbox for debug visualization var int freeAimDebugWSTrj[6]; // Projectile trajectory for debug visualization var int freeAimDebugTRBBox[6]; // Trace ray intersection for debug visualization @@ -80,7 +81,7 @@ const int mouseSensX = 9019720; //0x89A148 const int mouseDeltaX = 9246300; //0x8D165C const int projectileDeflectOffNpcAddr = 6949734; //0x6A0B66 const int zCWorld__AdvanceClock = 6447328; //0x6260E0 // Hook length 10 -const int oCAniCtrl_Human__InterpolateCombineAni = 7037296; //0x6B6170 // Hook length 5 +const int oCAIHuman__BowMode_696296 = 6906518; //0x696296 // Hook length 5 const int oCAIArrow__SetupAIVob = 6951136; //0x6A10E0 // Hook length 6 const int oCAIArrow__CanThisCollideWith = 6952080; //0x6A1490 // Hook length 7 const int oCAIHuman__BowMode = 6905600; //0x695F00 // Hook length 6 diff --git a/_work/data/Scripts/Content/freeAim/_intern/init.d b/_work/data/Scripts/Content/freeAim/_intern/init.d index 8603ceb..824ffc3 100644 --- a/_work/data/Scripts/Content/freeAim/_intern/init.d +++ b/_work/data/Scripts/Content/freeAim/_intern/init.d @@ -36,7 +36,7 @@ func void freeAim_Init() { CC_Register(freeAimVersion, "freeaim version", "print freeaim version info"); CC_Register(freeAimLicense, "freeaim license", "print freeaim license info"); CC_Register(freeAimInfo, "freeaim info", "print freeaim info"); - HookEngineF(oCAniCtrl_Human__InterpolateCombineAni, 5, freeAimAnimation); // Update aiming animation + HookEngineF(oCAIHuman__BowMode_696296, 5, freeAimAnimation); // Update aiming animation HookEngineF(oCAIArrow__SetupAIVob, 6, freeAimSetupProjectile); // Set projectile direction and trajectory HookEngineF(oCAIHuman__BowMode, 6, freeAimManageReticle); // Manage the reticle (on/off) HookEngineF(oCNpcFocus__SetFocusMode, 7, freeAimSwitchMode); // Manage the reticle (on/off) and draw force @@ -72,7 +72,10 @@ func void freeAim_Init() { if (!MEM_GothOptExists("FREEAIM", "enabled")) { MEM_SetGothOpt("FREEAIM", "enabled", "1"); }; // If not set if (!MEM_GothOptExists("FREEAIM", "focusEnabled")) { MEM_SetGothOpt("FREEAIM", "focusEnabled", "1"); } else if (!STR_ToInt(MEM_GetGothOpt("FREEAIM", "focusEnabled"))) { - FREEAIM_FOCUS_COLLECTION = 0; }; // No focuscollection (performance) not recommended + FREEAIM_FOCUS_COLLECTION = 0; }; // No focus collection (performance) not recommended + if (!MEM_GothOptExists("FREEAIM", "focusCollFreqMS")) { MEM_SetGothOpt("FREEAIM", "focusCollFreqMS", "10"); }; + freeAimTraceRayFreq = STR_ToInt(MEM_GetGothOpt("FREEAIM", "focusCollFreqMS")); + if (freeAimTraceRayFreq > 500) { freeAimTraceRayFreq = 500; }; // Recalculate trace ray intersection every x ms r_DefaultInit(); // Start rng for aiming accuracy hookFreeAim = 1; }; diff --git a/_work/data/Scripts/Content/freeAim/_intern/ranged.d b/_work/data/Scripts/Content/freeAim/_intern/ranged.d index 92fedf2..add0459 100644 --- a/_work/data/Scripts/Content/freeAim/_intern/ranged.d +++ b/_work/data/Scripts/Content/freeAim/_intern/ranged.d @@ -53,9 +53,10 @@ func void freeAimAnimation() { freeAimInsertReticle(_@(reticle)); // Draw/update reticle var zMAT4 camPos; camPos = _^(MEM_ReadInt(MEM_ReadInt(MEMINT_oGame_Pointer_Address)+20)+60); //0=right, 2=out, 3=pos var int pos[3]; // The position is calculated from the camera, not the player model - pos[0] = addf(camPos.v0[3], mulf(camPos.v0[2], mkf(FREEAIM_MAX_DIST))); - pos[1] = addf(camPos.v1[3], mulf(camPos.v1[2], mkf(FREEAIM_MAX_DIST))); - pos[2] = addf(camPos.v2[3], mulf(camPos.v2[2], mkf(FREEAIM_MAX_DIST))); + distance = mkf(FREEAIM_MAX_DIST); // Take the max distance, otherwise it looks strange on close range targets + pos[0] = addf(camPos.v0[3], mulf(camPos.v0[2], distance)); + pos[1] = addf(camPos.v1[3], mulf(camPos.v1[2], distance)); + pos[2] = addf(camPos.v2[3], mulf(camPos.v2[2], distance)); // Get aiming angles var int angleX; var int angXptr; angXptr = _@(angleX); var int angleY; var int angYptr; angYptr = _@(angleY); @@ -72,13 +73,13 @@ func void freeAimAnimation() { if (lf(angleY, FLOATNULL)) { angleY = -1098907648; } // -0.25 else { angleY = 1048576000; }; // 0.25 }; - // This following paragraph is essentially "copied" from oCAIHuman::BowMode (0x695F00 in g2) + // This following paragraph is inspired by oCAIHuman::BowMode (0x695F00 in g2) angleY = negf(subf(mulf(angleY, 1001786197), FLOATHALF)); // Scale and flip Y [-90° +90°] to [+1 0] if (lef(angleY, FLOATNULL)) { angleY = FLOATNULL; } // Maximum aim height (straight up) else if (gef(angleY, 1065353216)) { angleY = 1065353216; }; // Minimum aim height (down) - // New aiming coordinates. Overwrite the arguments passed to oCAniCtrl_Human::InterpolateCombineAni - MEM_WriteInt(ESP+4, FLOATHALF); // Always aim at center (x angle) - MEM_WriteInt(ESP+8, angleY); + // New aiming coordinates. Overwrite the arguments one and two passed to oCAniCtrl_Human::InterpolateCombineAni + MEM_WriteInt(ESP+20, FLOATHALF); // First argument: Always aim at center (azimuth) (esp+44h+30h) + ECX = angleY; // Second argument: New elevation }; /* Internal helper function for freeAimGetDrawForce() */