Skip to content

Commit

Permalink
Distribute code across multiple files
Browse files Browse the repository at this point in the history
  • Loading branch information
szapp committed Feb 19, 2017
1 parent cffc54a commit 1aa5eac
Show file tree
Hide file tree
Showing 29 changed files with 2,083 additions and 1,651 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Features

**Examples**

Here short list of some examples which are easily implementable (or already included) in `config.d`. There is a lot
Here short list of some examples which are easily implementable (or already included) in `config/`. There is a lot
more freedom, however.

- Change the way the draw force (projectile gravity) is calculated (by weapon stats, skill level, ..)
Expand Down Expand Up @@ -111,13 +111,13 @@ Customization
As the mechanisms of the script are rather complex, the script is divided into two parts in
`_work\data\Scripts\Content\freeAim\`. One part is the core functionality and should **not** be edited: `_intern.d`.
The other one holds all possible customizations and can be freely adjusted and changed: `config.d`.
The other one holds all possible customizations and can be freely adjusted and changed: `config/`.
The customization is mostly implemented by calling outsourced functions. These are functions you can freely adjust. The
only restrictions are the function signature and the type of return value. What happens inside the functions is fully up
to you. Other binary settings are offered as constants that can simply be changed.
In the file `config.d` the following things can be adjusted. For more details see `config.d` and read the in-line
In the files `config/` the following things can be adjusted. For more details see `config/` and read the in-line
comments of each listed function. There are a lot of possibilities and a lot of information is already provided to each
function (in form of function arguments). For some examples and ideas see **Examples** above.
Expand Down Expand Up @@ -344,7 +344,7 @@ Q: **Why does my game crash?**
A:
See **"It does not work? What now?"**. Additionally, it will be essential to describe your configuration, ideally by
attaching your `freeAim/config.d`.
attaching your files in `freeAim/config/`.
Q: **What is the deal with the license? May I use g2freeAim in my modification?**
Expand Down Expand Up @@ -397,7 +397,7 @@ include the following information:
- Output when entering `freeaim info` into the F2-ingame-console.
- zSpy Log.
- The Access Violation message (if applicable).
- Your configuration (attach the file `freeAim/config.d`).
- Your configuration (attach the files in `freeAim/config/`).
- Used versions of Ikarus/LeGo.
- If possible: Your own attempts to isolate and reproduce the bug.
Expand Down
1,297 changes: 0 additions & 1,297 deletions _work/data/Scripts/Content/freeAim/_intern.d

This file was deleted.

48 changes: 48 additions & 0 deletions _work/data/Scripts/Content/freeAim/_intern/activeSpell.d
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
};
182 changes: 182 additions & 0 deletions _work/data/Scripts/Content/freeAim/_intern/aimRay.d
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;
};
87 changes: 87 additions & 0 deletions _work/data/Scripts/Content/freeAim/_intern/aimVob.d
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;
};
Loading

0 comments on commit 1aa5eac

Please sign in to comment.