Added new HOOK_ONEXPLOSION and a new mode "set_explosion_max_targets" to metarule2_explosions (from Mr.Stalin) (#35)

This commit is contained in:
NovaRain
2018-10-30 11:19:19 +08:00
parent 29ad288f52
commit 6319017186
8 changed files with 93 additions and 8 deletions
+2
View File
@@ -57,6 +57,7 @@
#define HOOK_EXPLOSIVETIMER (33) #define HOOK_EXPLOSIVETIMER (33)
#define HOOK_DESCRIPTIONOBJ (34) #define HOOK_DESCRIPTIONOBJ (34)
#define HOOK_USESKILLON (35) #define HOOK_USESKILLON (35)
#define HOOK_ONEXPLOSION (36)
//Valid arguments to list_begin //Valid arguments to list_begin
#define LIST_CRITTERS (0) #define LIST_CRITTERS (0)
@@ -148,6 +149,7 @@
#define get_explosion_damage(itemPid) metarule2_explosions(6, itemPid, 0) #define get_explosion_damage(itemPid) metarule2_explosions(6, itemPid, 0)
#define set_dynamite_damage(minDmg, maxDmg) metarule2_explosions(7, minDmg, maxDmg) #define set_dynamite_damage(minDmg, maxDmg) metarule2_explosions(7, minDmg, maxDmg)
#define set_plastic_damage(minDmg, maxDmg) metarule2_explosions(8, minDmg, maxDmg) #define set_plastic_damage(minDmg, maxDmg) metarule2_explosions(8, minDmg, maxDmg)
#define set_explosion_max_targets(x) metarule2_explosions(9, x, 0)
#define GAME_MSG_COMBAT (0) #define GAME_MSG_COMBAT (0)
+17
View File
@@ -561,3 +561,20 @@ int arg3 - skill being used
int ret1 - a new critter to override the user critter. Pass -1 to cancel the skill use, pass 0 to skip this return value int ret1 - a new critter to override the user critter. Pass -1 to cancel the skill use, pass 0 to skip this return value
int ret2 - pass 1 to allow the skill being used in combat (only for dude_obj or critter being controlled by the player) int ret2 - pass 1 to allow the skill being used in combat (only for dude_obj or critter being controlled by the player)
-------------------------------------------
HOOK_ONEXPLOSION (hs_onexplosion.int)
Runs when an explosion occurs and Fallout is checking all the tiles within the explosion radius for targets.
The tile checking will be interrupted when 6 additional targets (critters) are received.
int arg1 - event type: 1 - when the explosion is from an explosive item, 0 - otherwise
Critter arg2 - The attacker
int arg3 - The tile on which the explosion occurs
int arg4 - checked tile within the explosion radius
Obj arg5 - first found object on the checked tile as an additional target
Critter arg6 - The target critter, may be 0 or equal to the attacker
int arg7 - 1 when using throwing weapons (e.g. grenades), 0 otherwise
int ret1 - overrides the found object on the checked tile, pass 0 to skip the object
@@ -246,6 +246,9 @@ was made as a dirty easy hack to allow dynamically change some explosion paramet
- sets the minimum and maximum damage for Plastic Explosives. - sets the minimum and maximum damage for Plastic Explosives.
- changed damage will be reset each time the player reloads the game. - changed damage will be reset each time the player reloads the game.
> void set_explosion_max_targets(x)
- sets the maximum number of additional targets for an explosion, valid range: 1..6 (default is 6)
Some utility/math functions are available: Some utility/math functions are available:
+16 -1
View File
@@ -48,6 +48,7 @@ static bool onlyOnce = false;
static bool lightingEnabled = false; static bool lightingEnabled = false;
static bool explosionsMetaruleReset = false; static bool explosionsMetaruleReset = false;
static bool explosionsDamageReset = false; static bool explosionsDamageReset = false;
static bool explosionMaxTargetReset = false;
static const DWORD ranged_attack_lighting_fix_back = 0x4118F8; static const DWORD ranged_attack_lighting_fix_back = 0x4118F8;
@@ -363,7 +364,8 @@ enum MetaruleExplosionsMode {
EXPL_STATIC_EXPLOSION_RADIUS = 5, EXPL_STATIC_EXPLOSION_RADIUS = 5,
EXPL_GET_EXPLOSION_DAMAGE = 6, EXPL_GET_EXPLOSION_DAMAGE = 6,
EXPL_SET_DYNAMITE_EXPLOSION_DAMAGE = 7, EXPL_SET_DYNAMITE_EXPLOSION_DAMAGE = 7,
EXPL_SET_PLASTIC_EXPLOSION_DAMAGE = 8 EXPL_SET_PLASTIC_EXPLOSION_DAMAGE = 8,
EXPL_SET_EXPLOSION_MAX_TARGET = 9,
}; };
static void SetExplosionRadius(int arg1, int arg2) { static void SetExplosionRadius(int arg1, int arg2) {
@@ -444,6 +446,14 @@ int _stdcall ExplosionsMetaruleFunc(int mode, int arg1, int arg2) {
case EXPL_SET_PLASTIC_EXPLOSION_DAMAGE: case EXPL_SET_PLASTIC_EXPLOSION_DAMAGE:
SetExplosionDamage(fo::ProtoId::PID_PLASTIC_EXPLOSIVES, arg1, arg2); SetExplosionDamage(fo::ProtoId::PID_PLASTIC_EXPLOSIVES, arg1, arg2);
return 0; return 0;
case EXPL_SET_EXPLOSION_MAX_TARGET:
if (arg1 > 0 && arg1 < 7) {
SafeWrite8(0x423C93, arg1);
explosionMaxTargetReset = true;
} else {
return 0;
}
break;
default: default:
return -1; return -1;
} }
@@ -466,6 +476,11 @@ void ResetExplosionSettings() {
for (int i = 0; i < numDmgChecks; i++) { for (int i = 0; i < numDmgChecks; i++) {
SafeWrite8(explosion_dmg_check_adr[i], fo::DamageType::DMG_explosion); SafeWrite8(explosion_dmg_check_adr[i], fo::DamageType::DMG_explosion);
} }
// explosion max target count
if (explosionMaxTargetReset) {
SafeWrite8(0x423C93, 6);
explosionMaxTargetReset = false;
}
explosionsMetaruleReset = false; explosionsMetaruleReset = false;
} }
+1
View File
@@ -80,6 +80,7 @@ static HooksInjectInfo injectHooks[] = {
{HOOK_EXPLOSIVETIMER, Inject_ExplosiveTimerHook, false}, {HOOK_EXPLOSIVETIMER, Inject_ExplosiveTimerHook, false},
{HOOK_DESCRIPTIONOBJ, Inject_DescriptionObjHook, false}, {HOOK_DESCRIPTIONOBJ, Inject_DescriptionObjHook, false},
{HOOK_USESKILLON, Inject_UseSkillOnHook, false}, {HOOK_USESKILLON, Inject_UseSkillOnHook, false},
{HOOK_ONEXPLOSION, Inject_OnExplosionHook, false},
}; };
bool HookScripts::injectAllHooks; bool HookScripts::injectAllHooks;
+1
View File
@@ -62,6 +62,7 @@ enum HookType
HOOK_EXPLOSIVETIMER = 33, HOOK_EXPLOSIVETIMER = 33,
HOOK_DESCRIPTIONOBJ = 34, HOOK_DESCRIPTIONOBJ = 34,
HOOK_USESKILLON = 35, HOOK_USESKILLON = 35,
HOOK_ONEXPLOSION = 36,
HOOK_COUNT HOOK_COUNT
}; };
+52 -7
View File
@@ -40,7 +40,6 @@ static void __declspec(naked) ToHitHook() {
} }
static void __fastcall AfterHitRollHook_Script(fo::ComputeAttackResult &ctd, DWORD hitChance, DWORD hit) { static void __fastcall AfterHitRollHook_Script(fo::ComputeAttackResult &ctd, DWORD hitChance, DWORD hit) {
BeginHook(); BeginHook();
argCount = 5; argCount = 5;
@@ -125,7 +124,6 @@ static void __declspec(naked) CalcApCostHook2() {
} }
static void __fastcall ComputeDamageHook_Script(fo::ComputeAttackResult &ctd, DWORD rounds, DWORD multiply) { static void __fastcall ComputeDamageHook_Script(fo::ComputeAttackResult &ctd, DWORD rounds, DWORD multiply) {
BeginHook(); BeginHook();
argCount = 12; argCount = 12;
@@ -168,7 +166,7 @@ static void __declspec(naked) ComputeDamageHook() {
push eax; // store ctd push eax; // store ctd
call fo::funcoffs::compute_damage_; call fo::funcoffs::compute_damage_;
pop ecx; // restore ctd (eax) pop ecx; // restore ctd (eax)
pop edx; // restore num rounds pop edx; // restore num rounds
call ComputeDamageHook_Script; call ComputeDamageHook_Script;
pop ecx; pop ecx;
retn; retn;
@@ -176,7 +174,6 @@ static void __declspec(naked) ComputeDamageHook() {
} }
static void __fastcall FindTargetHook_Script(DWORD* target, DWORD attacker) { static void __fastcall FindTargetHook_Script(DWORD* target, DWORD attacker) {
BeginHook(); BeginHook();
argCount = 5; argCount = 5;
@@ -281,7 +278,7 @@ static void __declspec(naked) AmmoCostHook() {
cmp dword ptr [esp + 0x1C + 4], ANIM_fire_continuous; cmp dword ptr [esp + 0x1C + 4], ANIM_fire_continuous;
jg skip; jg skip;
mov ecx, 3; // hook type burst mov ecx, 3; // hook type burst
skip: skip:
xchg eax, edx; xchg eax, edx;
push eax; // rounds in attack push eax; // rounds in attack
call AmmoCostHook_Script; // edx - weapon call AmmoCostHook_Script; // edx - weapon
@@ -344,6 +341,51 @@ normalTurn:
} }
} }
fo::GameObject* __fastcall ComputeExplosionOnExtrasHook_Script(fo::GameObject* object, DWORD checkTile, fo::ComputeAttackResult* ctdSource, DWORD isCheck, DWORD isThrowing, fo::GameObject* who) {
fo::GameObject* result = object;
BeginHook();
argCount = 7;
args[0] = isCheck;
args[1] = (DWORD)ctdSource->attacker;
args[2] = ctdSource->targetTile;
args[3] = checkTile;
args[4] = (DWORD)object;
args[5] = (DWORD)who;
args[6] = isThrowing;
RunHookScript(HOOK_ONEXPLOSION);
if (cRet > 0) result = (fo::GameObject*)rets[0]; // override object
EndHook();
return result;
}
static void _declspec(naked) ComputeExplosionOnExtrasHook() {
__asm {
cmp dword ptr [esp + 0x34 + 4], 0x429533; // skip hook when AI assesses the situation in choosing the best weapon
jz end;
cmp dword ptr [esp + 0x34 + 4], 0x4296BC;
jnz hook;
end:
jmp fo::funcoffs::obj_blocking_at_;
hook:
push ecx;
push eax; // who (target/source)
call fo::funcoffs::obj_blocking_at_;
push [esp + 0x34 - 0x24 + 12]; // isThrowing
push [esp + 0x34 - 0x34 + 16]; // isCheck (bypass damage)
push esi; // source ctd
mov ecx, eax; // object
mov edx, edi; // check tile
call ComputeExplosionOnExtrasHook_Script;
pop ecx;
retn;
}
}
void Inject_ToHitHook() { void Inject_ToHitHook() {
HookCalls(ToHitHook, { HookCalls(ToHitHook, {
0x421686, // combat_safety_invalidate_weapon_func_ 0x421686, // combat_safety_invalidate_weapon_func_
@@ -407,8 +449,11 @@ void Inject_CombatTurnHook() {
HookCalls(CombatTurnHook, { 0x422D87, 0x422E20 }); HookCalls(CombatTurnHook, { 0x422D87, 0x422E20 });
} }
void InitCombatHookScripts() { void Inject_OnExplosionHook() {
HookCall(0x423D70, ComputeExplosionOnExtrasHook);
}
void InitCombatHookScripts() {
LoadHookScript("hs_tohit", HOOK_TOHIT); LoadHookScript("hs_tohit", HOOK_TOHIT);
LoadHookScript("hs_afterhitroll", HOOK_AFTERHITROLL); LoadHookScript("hs_afterhitroll", HOOK_AFTERHITROLL);
LoadHookScript("hs_calcapcost", HOOK_CALCAPCOST); LoadHookScript("hs_calcapcost", HOOK_CALCAPCOST);
@@ -417,7 +462,7 @@ void InitCombatHookScripts() {
LoadHookScript("hs_itemdamage", HOOK_ITEMDAMAGE); LoadHookScript("hs_itemdamage", HOOK_ITEMDAMAGE);
LoadHookScript("hs_ammocost", HOOK_AMMOCOST); LoadHookScript("hs_ammocost", HOOK_AMMOCOST);
LoadHookScript("hs_combatturn", HOOK_COMBATTURN); LoadHookScript("hs_combatturn", HOOK_COMBATTURN);
LoadHookScript("hs_onexplosion", HOOK_ONEXPLOSION);
} }
} }
+1
View File
@@ -15,5 +15,6 @@ void Inject_FindTargetHook();
void Inject_ItemDamageHook(); void Inject_ItemDamageHook();
void Inject_AmmoCostHook(); void Inject_AmmoCostHook();
void Inject_CombatTurnHook(); void Inject_CombatTurnHook();
void Inject_OnExplosionHook();
} }