Skip to content

Commit

Permalink
Enable trigger collision fix for NPCs also
Browse files Browse the repository at this point in the history
  • Loading branch information
szapp committed Jan 12, 2019
1 parent 8e4ad5c commit f6de915
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 1 deletion.
51 changes: 50 additions & 1 deletion _work/data/Scripts/Content/GFA/_intern/collision.d
Expand Up @@ -561,7 +561,8 @@ func void GFA_ExtendCollisionCheck() {
};

// Ignore by refined collision check with NPCs
if (GFA_Flags & GFA_RANGED) && (hit) {
var C_Npc shooter; shooter = _^(MEM_ReadInt(arrowAI+oCAIArrow_origin_offset));
if (GFA_Flags & GFA_RANGED) && (hit) && (Npc_IsPlayer(shooter)) {
hit = GFA_RefinedProjectileCollisionCheck(vobPtr, arrowAI);
};
} else if (GFA_Flags & GFA_CUSTOM_COLLISIONS) && (GFA_TRIGGER_COLL_FIX) && (GOTHIC_BASE_VERSION == 2) {
Expand All @@ -583,3 +584,51 @@ func void GFA_ExtendCollisionCheck() {
ECX = 0;
};
};


/*
* Enable extended collision check for NPCs also. This function rewrites the opcode of oCAIArrow::CanThisCollideWith()
* such that the ignore list check and the hook GFA_ExtendCollisionCheck() are also executed for NPCs. This fixes the
* trigger collision bug for NPCs. Only implemented for Gothic 2, as the trigger bug does not exist in Gothic 1.
*/
func void GFA_ExtendCollisionCheckNpc() {
if (IsHooked(oCAIArrow__CanThisCollideWith_positive)) || (GOTHIC_BASE_VERSION != 2) {
return;
};

// Skip checks for shooter and target
MemoryProtectionOverride(oCAIArrow__CanThisCollideWith_skipCheck, 2);
MEM_WriteByte(oCAIArrow__CanThisCollideWith_skipCheck, /*EB*/ 235); // jmp 0x6A14F0
MEM_WriteByte(oCAIArrow__CanThisCollideWith_skipCheck+1, /*5A*/ 90); // 0x6A14F0-0x6A1494-2

// Re-add these checks later (after ignore list iteration and Daedalus hook)
ASM_Open(42);
// Check if extended detection returned zero
ASM_1(/*85*/ 133); ASM_1(/*C9*/ 201); // test ecx, ecx
ASM_1(/*74*/ 116); ASM_1(/*1D*/ 29); // jz .continue
// Check if shooter is player
ASM_1(/*51*/ 81); // push ecx
ASM_1(/*8B*/ 139); ASM_1(/*4F*/ 79); ASM_1(/*5C*/ 92); // mov ecx, [edi+0x5C]
ASM_1(/*8B*/ 139); ASM_1(/*01*/ 1); // mov eax, [ecx]
ASM_1(/*FF*/ 255); ASM_1(/*90*/ 144); ASM_4(/*100*/256); // call DWORD [eax+0x100]
ASM_1(/*59*/ 89); // pop ecx
ASM_1(/*85*/ 133); ASM_1(/*C0*/ 192); // test eax, eax
ASM_1(/*75*/ 117); ASM_1(/*0C*/ 12); // jnz .continue
// Check if arrow AI has target
ASM_1(/*8B*/ 139); ASM_1(/*47*/ 71); ASM_1(/*64*/ 100); // mov eax, [edi+0x64]
ASM_1(/*85*/ 133); ASM_1(/*C0*/ 192); // test eax, eax
ASM_1(/*74*/ 116); ASM_1(/*05*/ 5); // jz .continue
ASM_1(/*E9*/ 233); ASM_4(oCAIArrow__CanThisCollideWith_npcShooter-ASM_Here()-4); // jmp 0x6A14AA
// .continue:
ASM_1(/*5F*/ 95); // pop edi
ASM_1(/*5E*/ 94); // pop esi
ASM_1(/*8B*/ 139); ASM_1(/*C1*/ 193); // mov eax, ecx
ASM_1(/*C2*/ 194); ASM_1(/*04*/ 4); ASM_1(/*00*/ 0); // ret 4

// Need absolute jump here, because Daedalus hook later relocates this jump
MemoryProtectionOverride(oCAIArrow__CanThisCollideWith_positive, 7);
MEM_WriteByte(oCAIArrow__CanThisCollideWith_positive, /*B8*/ 184); // mov eax, newCheck
MEM_WriteInt(oCAIArrow__CanThisCollideWith_positive+1, ASM_Close());
MEM_WriteByte(oCAIArrow__CanThisCollideWith_positive+5, /*FF*/ 255); // jmp eax
MEM_WriteByte(oCAIArrow__CanThisCollideWith_positive+6, /*E0*/ 224);
};
2 changes: 2 additions & 0 deletions _work/data/Scripts/Content/GFA/_intern/init.d
Expand Up @@ -55,6 +55,7 @@ func void GFA_InitFeatureFreeAiming() {
HookEngineF(oCAIArrow__ReportCollisionToAI_hitChc, 6, GFA_OverwriteHitChance); // Manipulate hit chance
MemoryProtectionOverride(oCAIHuman__CheckFocusVob_ranged, 1); // Prevent toggling focus in ranged combat
HookEngineF(zCModel__CalcModelBBox3DWorld_rtn, 6, GFA_EnlargeHumanModelBBox); // Include head in model bbox
GFA_ExtendCollisionCheckNpc();
HookEngineF(oCAIArrow__CanThisCollideWith_positive, MEMINT_SwitchG1G2(6, 7), GFA_ExtendCollisionCheck);
if (GFA_STRAFING) {
HookEngineF(oCAIHuman__BowMode_rtn, 7, GFA_RangedLockMovement); // Allow strafing or not when falling
Expand Down Expand Up @@ -221,6 +222,7 @@ func void GFA_InitFeatureCustomCollisions() {

// Extend and refine collision detection on vobs
if ((GFA_COLL_PRIOR_NPC == -1) || ((GFA_TRIGGER_COLL_FIX) && (GOTHIC_BASE_VERSION == 2))) {
GFA_ExtendCollisionCheckNpc();
HookEngineF(oCAIArrow__CanThisCollideWith_positive, MEMINT_SwitchG1G2(6, 7), GFA_ExtendCollisionCheck);
};
};
Expand Down
2 changes: 2 additions & 0 deletions _work/data/Scripts/Content/GFA/_intern/offsets_G1.d
Expand Up @@ -103,6 +103,8 @@ const int oCAIArrowBase__ReportCollisionToAI_PFXon2 = 0;
const int oCAIArrowBase__ReportCollisionToAI_collNpc = 0; // Does not exist in Gothic 1
const int oCAIArrow__ReportCollisionToAI_destroyPrj = 6396025; //0x619879
const int oCAIArrow__ReportCollisionToAI_keepPlyStrp = 6395401; //0x619609
const int oCAIArrow__CanThisCollideWith_skipCheck = 0; // Not used for Gothic 1
const int oCAIArrow__CanThisCollideWith_npcShooter = 0; // Not used for Gothic 1
const int oCAIHuman__MagicMode_g2ctrlCheck = 0; // Does not exist in Gothic 1
const int oCAIHuman__BowMode_g2ctrlCheck = 0; // Does not exist in Gothic 1
const int oCAIHuman__BowMode_shootingKey = 6359374; //0x61094E // Not used for Gothic 1
Expand Down
2 changes: 2 additions & 0 deletions _work/data/Scripts/Content/GFA/_intern/offsets_G2.d
Expand Up @@ -103,6 +103,8 @@ const int oCAIArrowBase__ReportCollisionToAI_PFXon2 = 6949396; //0x6A0A14
const int oCAIArrowBase__ReportCollisionToAI_collNpc = 6949734; //0x6A0B66
const int oCAIArrow__ReportCollisionToAI_destroyPrj = 0; // Does not exist in Gothic 2
const int oCAIArrow__ReportCollisionToAI_keepPlyStrp = 0; // Does not exist in Gothic 2
const int oCAIArrow__CanThisCollideWith_skipCheck = 6952084; //0x6A1494
const int oCAIArrow__CanThisCollideWith_npcShooter = 6952106; //0x6A14AA
const int oCAIHuman__MagicMode_g2ctrlCheck = 4665380; //0x473024
const int oCAIHuman__BowMode_g2ctrlCheck = 6905643; //0x695F2B
const int oCAIHuman__BowMode_shootingKey = 6906610; //0x6962F2
Expand Down

0 comments on commit f6de915

Please sign in to comment.