-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Distribute code across multiple files
- Loading branch information
Showing
29 changed files
with
2,083 additions
and
1,651 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/* | ||
* Identifying active spell instances and determine if they are eligible for free aiming | ||
* | ||
* G2 Free Aim v0.1.2 - Free aiming for the video game Gothic 2 by Piranha Bytes | ||
* Copyright (C) 2016 mud-freak (@szapp) | ||
* | ||
* This file is part of G2 Free Aim. | ||
* <http://github.com/szapp/g2freeAim> | ||
* | ||
* G2 Free Aim is free software: you can redistribute it and/or modify | ||
* it under the terms of the MIT License. | ||
* On redistribution this notice must remain intact and all copies must | ||
* identify the original author. | ||
* | ||
* G2 Free Aim 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 | ||
* MIT License for more details. | ||
* | ||
* You should have received a copy of the MIT License | ||
* along with G2 Free Aim. If not, see <http://opensource.org/licenses/MIT>. | ||
*/ | ||
|
||
/* Return the active spell instance */ | ||
func MEMINT_HelperClass freeAimGetActiveSpellInst(var C_Npc npc) { | ||
if (Npc_GetActiveSpell(npc) == -1) { | ||
var C_Spell ret; ret = MEM_NullToInst(); | ||
MEMINT_StackPushInst(ret); | ||
return; | ||
}; | ||
var int magBookPtr; magBookPtr = MEM_ReadInt(_@(npc)+2324); //0x0914 oCNpc.mag_book | ||
const int call = 0; | ||
if (CALL_Begin(call)) { | ||
CALL__thiscall(_@(magBookPtr), oCMag_Book__GetSelectedSpell); | ||
call = CALL_End(); | ||
}; | ||
_^(CALL_RetValAsPtr()+128); //0x0080 oCSpell.C_Spell | ||
}; | ||
|
||
/* Return whether a spell is eligible for free aiming */ | ||
func int freeAimSpellEligible(var C_Spell spell) { | ||
if (FREEAIM_DISABLE_SPELLS) || (!_@(spell)) { return FALSE; }; | ||
if (spell.targetCollectAlgo != TARGET_COLLECT_FOCUS_FALLBACK_NONE) | ||
|| (!spell.canTurnDuringInvest) || (!spell.canChangeTargetDuringInvest) { | ||
return FALSE; | ||
}; | ||
return TRUE; // All other cases | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
/* | ||
* Aim-specific trace ray and focus collection | ||
* | ||
* G2 Free Aim v0.1.2 - Free aiming for the video game Gothic 2 by Piranha Bytes | ||
* Copyright (C) 2016 mud-freak (@szapp) | ||
* | ||
* This file is part of G2 Free Aim. | ||
* <http://github.com/szapp/g2freeAim> | ||
* | ||
* G2 Free Aim is free software: you can redistribute it and/or modify | ||
* it under the terms of the MIT License. | ||
* On redistribution this notice must remain intact and all copies must | ||
* identify the original author. | ||
* | ||
* G2 Free Aim 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 | ||
* MIT License for more details. | ||
* | ||
* You should have received a copy of the MIT License | ||
* along with G2 Free Aim. If not, see <http://opensource.org/licenses/MIT>. | ||
*/ | ||
|
||
/* 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)) { | ||
CALL_PtrParam(_@(null)); // Always remove oCNpc.enemy. Target will be set to aimvob when shooting | ||
CALL__thiscall(_@(herPtr), oCNpc__SetEnemy); | ||
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; }; | ||
}; | ||
// 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; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Definition and manipulation of aim vob (targeting system) | ||
* | ||
* G2 Free Aim v0.1.2 - Free aiming for the video game Gothic 2 by Piranha Bytes | ||
* Copyright (C) 2016 mud-freak (@szapp) | ||
* | ||
* This file is part of G2 Free Aim. | ||
* <http://github.com/szapp/g2freeAim> | ||
* | ||
* G2 Free Aim is free software: you can redistribute it and/or modify | ||
* it under the terms of the MIT License. | ||
* On redistribution this notice must remain intact and all copies must | ||
* identify the original author. | ||
* | ||
* G2 Free Aim 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 | ||
* MIT License for more details. | ||
* | ||
* You should have received a copy of the MIT License | ||
* along with G2 Free Aim. If not, see <http://opensource.org/licenses/MIT>. | ||
*/ | ||
|
||
/* Attach an FX to the aim vob */ | ||
func void freeAimAttachFX(var string effectInst) { | ||
var int vobPtr; vobPtr = MEM_SearchVobByName("AIMVOB"); | ||
if (!vobPtr) { return; }; | ||
MEM_WriteString(vobPtr+564, effectInst); // oCItem.effect | ||
const int call = 0; | ||
if (CALL_Begin(call)) { | ||
CALL__thiscall(_@(vobPtr), oCItem__InsertEffect); | ||
call = CALL_End(); | ||
}; | ||
}; | ||
|
||
/* Detach the FX of the aim vob */ | ||
func void freeAimDetachFX() { | ||
var int vobPtr; vobPtr = MEM_SearchVobByName("AIMVOB"); | ||
if (!vobPtr) { return; }; | ||
if (Hlp_StrCmp(MEM_ReadString(vobPtr+564), "")) { return; }; | ||
const int call = 0; | ||
if (CALL_Begin(call)) { | ||
CALL__thiscall(_@(vobPtr), oCItem__RemoveEffect); | ||
call = CALL_End(); | ||
}; | ||
MEM_WriteString(vobPtr+564, ""); // oCItem.effect | ||
}; | ||
|
||
/* Manipulate the position of the aim vob (only for spells) */ | ||
func void freeAimManipulateAimVobPos(var int posPtr) { | ||
var int spell; spell = Npc_GetActiveSpell(hero); | ||
if (spell == -1) { return; }; | ||
MEM_PushIntParam(spell); | ||
MEM_Call(freeAimShiftAimVob); | ||
var int pushed; pushed = MEM_PopIntResult(); | ||
if (pushed) { | ||
pushed = mkf(pushed); // Amount to push the aim vob along the out vector of the camera | ||
var zMAT4 camPos; camPos = _^(MEM_ReadInt(MEM_ReadInt(MEMINT_oGame_Pointer_Address)+20)+60); | ||
MEM_WriteInt(posPtr+0, addf(MEM_ReadInt(posPtr+0), mulf(camPos.v0[2], pushed))); | ||
MEM_WriteInt(posPtr+4, addf(MEM_ReadInt(posPtr+4), mulf(camPos.v1[2], pushed))); | ||
MEM_WriteInt(posPtr+8, addf(MEM_ReadInt(posPtr+8), mulf(camPos.v2[2], pushed))); | ||
}; | ||
}; | ||
|
||
/* Create and set aim vob to position */ | ||
func int freeAimSetupAimVob(var int posPtr) { | ||
var int vobPtr; vobPtr = MEM_SearchVobByName("AIMVOB"); // Arrow needs target vob | ||
if (!vobPtr) { // Does not exist | ||
MEM_Info("freeAimSetupAimVob: Creating aim vob."); // Should be printed only once ever | ||
CALL__cdecl(oCItem___CreateNewInstance); // This actually allocates the memory, so no need to care about freeing | ||
vobPtr = CALL_RetValAsPtr(); | ||
MEM_WriteString(vobPtr+16, "AIMVOB"); // zCVob._zCObject_objectName | ||
CALL_PtrParam(_@(MEM_Vobtree)); | ||
CALL_PtrParam(vobPtr); | ||
CALL__thiscall(_@(MEM_World), oCWorld__AddVobAsChild); | ||
MEM_WriteInt(vobPtr+260, 3105); // zCVob.bitfield[0] (ignored by trace ray, no collision) | ||
}; | ||
MEM_CopyBytes(_@(hero)+60, vobPtr+60, 64); // Include rotation | ||
freeAimManipulateAimVobPos(posPtr); // Shift the aim vob (if desired) | ||
const int call4 = 0; // Set position to aim vob | ||
if (CALL_Begin(call4)) { | ||
CALL_PtrParam(_@(posPtr)); // Update aim vob position | ||
CALL__thiscall(_@(vobPtr), zCVob__SetPositionWorld); | ||
call4 = CALL_End(); | ||
}; | ||
return vobPtr; | ||
}; |
Oops, something went wrong.