Moved some functions from AI.cpp to AIHelpers.cpp

This commit is contained in:
NovaRain
2021-09-06 07:44:38 +08:00
parent c047402dc9
commit 0a8a28b80c
10 changed files with 127 additions and 65 deletions
+4 -2
View File
@@ -143,7 +143,8 @@ int ret0 - The new AP cost
#### `HOOK_DEATHANIM1 (hs_deathanim1.int)`
Runs before Fallout tries to calculate the death animation. Lets you switch out which weapon Fallout sees.<br>
Runs before Fallout tries to calculate the death animation. Lets you switch out which weapon Fallout sees.
Does not run for critters in the knockdown/out state.
```
@@ -161,7 +162,8 @@ int ret0 - The pid of an object to override the attacking weapon with
#### `HOOK_DEATHANIM2 (hs_deathanim2.int)`
Runs after Fallout has calculated the death animation. Lets you set your own custom frame id, so more powerful than `HOOK_DEATHANIM1`, but performs no validation.<br>
When using `critter_dmg` function, this script will also run. In that case weapon pid will be -1 and attacker will point to an object with `obj_art_fid == 0x20001F5`.<br>
When using `critter_dmg` function, this script will also run. In that case weapon pid will be -1 and attacker will point to an object with `obj_art_fid == 0x20001F5`.
Does not run for critters in the knockdown/out state.
```
+13 -10
View File
@@ -525,15 +525,14 @@ enum class ScenerySubType : long
enum Stat : long
{
STAT_st = 0,
STAT_pe = 1,
STAT_en = 2,
STAT_ch = 3,
STAT_iq = 4,
STAT_ag = 5,
STAT_lu = 6,
/// strength, perception, endurance, charisma, intelligence, agility,
/// luck, // luck MUST be the last basic stat
STAT_st = 0, // strength
STAT_pe = 1, // perception
STAT_en = 2, // endurance
STAT_ch = 3, // charisma
STAT_iq = 4, // intelligence
STAT_ag = 5, // agility
STAT_lu = 6, // luck
// derived stats
STAT_max_hit_points = 7,
STAT_max_move_points = 8,
@@ -562,14 +561,18 @@ enum Stat : long
STAT_rad_resist = 31,
STAT_poison_resist = 32,
// poison_resist MUST be the last derived stat
// non-derived stats
STAT_age = 33,
STAT_gender = 34,
// gender MUST be the last non-derived stat
STAT_current_hp = 35,
STAT_current_poison = 36,
STAT_current_rad = 37,
STAT_real_max_stat = 38
STAT_real_max_stat = 38,
STAT_base_count = 7
};
namespace Scripts {
+57
View File
@@ -0,0 +1,57 @@
/*
* sfall
* Copyright (C) 2008-2021 The sfall team
*
*/
//#include "..\..\main.h"
#include "..\..\FalloutEngine\Fallout2.h"
#include "..\..\Modules\AI.h"
#include "..\items.h"
#include "AIHelpers.h"
namespace game
{
namespace ai
{
namespace sf = sfall;
// Returns the friendly critter or any blocking object in the line of fire
fo::GameObject* AIHelpers::CheckShootAndFriendlyInLineOfFire(fo::GameObject* object, long targetTile, long team) {
if (object && object->IsCritter() && object->critter.teamNum != team) { // is not friendly fire
long objTile = object->tile;
if (objTile == targetTile) return nullptr;
if (object->flags & fo::ObjectFlag::MultiHex) {
long dir = fo::func::tile_dir(objTile, targetTile);
objTile = fo::func::tile_num_in_direction(objTile, dir, 1);
if (objTile == targetTile) return nullptr; // just in case
}
// continue checking the line of fire from object tile to targetTile
fo::GameObject* obj = object; // for ignoring the object (multihex) when building the path
fo::func::make_straight_path_func(object, objTile, targetTile, 0, (DWORD*)&obj, 0x20, (void*)fo::funcoffs::obj_shoot_blocking_at_);
object = CheckShootAndFriendlyInLineOfFire(obj, targetTile, team);
}
return object; // friendly critter, any object or null
}
// Returns the friendly critter in the line of fire
fo::GameObject* AIHelpers::CheckFriendlyFire(fo::GameObject* target, fo::GameObject* attacker) {
fo::GameObject* object = nullptr;
fo::func::make_straight_path_func(attacker, attacker->tile, target->tile, 0, (DWORD*)&object, 0x20, (void*)fo::funcoffs::obj_shoot_blocking_at_);
object = CheckShootAndFriendlyInLineOfFire(object, target->tile, attacker->critter.teamNum);
return (object && object->IsCritter()) ? object : nullptr; // 0 - if there are no friendly critters
}
bool AIHelpers::AttackInRange(fo::GameObject* source, fo::GameObject* weapon, long distance) {
if (Items::item_weapon_range(source, weapon, fo::AttackType::ATKTYPE_RWEAPON_PRIMARY) >= distance) return true;
return (Items::item_weapon_range(source, weapon, fo::AttackType::ATKTYPE_RWEAPON_SECONDARY) >= distance);
}
}
}
+26
View File
@@ -0,0 +1,26 @@
/*
* sfall
* Copyright (C) 2008-2021 The sfall team
*
*/
#pragma once
namespace game
{
namespace ai
{
class AIHelpers {
public:
// Returns the friendly critter or any blocking object in the line of fire
static fo::GameObject* CheckShootAndFriendlyInLineOfFire(fo::GameObject* object, long targetTile, long team);
// Returns the friendly critter in the line of fire
static fo::GameObject* CheckFriendlyFire(fo::GameObject* target, fo::GameObject* attacker);
static bool AttackInRange(fo::GameObject* source, fo::GameObject* weapon, long distance);
};
}
}
+3 -35
View File
@@ -22,6 +22,7 @@
#include "..\FalloutEngine\Fallout2.h"
#include "LoadGameHook.h"
#include "..\Game\AI\AIHelpers.h"
#include "..\Game\combatAI.h"
#include "..\Game\items.h"
@@ -35,39 +36,6 @@ using namespace fo::Fields;
static std::unordered_map<fo::GameObject*, fo::GameObject*> targets;
static std::unordered_map<fo::GameObject*, fo::GameObject*> sources;
// Returns the friendly critter or any blocking object in the line of fire
fo::GameObject* AI::CheckShootAndFriendlyInLineOfFire(fo::GameObject* object, long targetTile, long team) {
if (object && object->IsCritter() && object->critter.teamNum != team) { // is not friendly fire
long objTile = object->tile;
if (objTile == targetTile) return nullptr;
if (object->flags & fo::ObjectFlag::MultiHex) {
long dir = fo::func::tile_dir(objTile, targetTile);
objTile = fo::func::tile_num_in_direction(objTile, dir, 1);
if (objTile == targetTile) return nullptr; // just in case
}
// continue checking the line of fire from object tile to targetTile
fo::GameObject* obj = object; // for ignoring the object (multihex) when building the path
fo::func::make_straight_path_func(object, objTile, targetTile, 0, (DWORD*)&obj, 0x20, (void*)fo::funcoffs::obj_shoot_blocking_at_);
object = CheckShootAndFriendlyInLineOfFire(obj, targetTile, team);
}
return object; // friendly critter, any object or null
}
// Returns the friendly critter in the line of fire
fo::GameObject* AI::CheckFriendlyFire(fo::GameObject* target, fo::GameObject* attacker) {
fo::GameObject* object = nullptr;
fo::func::make_straight_path_func(attacker, attacker->tile, target->tile, 0, (DWORD*)&object, 0x20, (void*)fo::funcoffs::obj_shoot_blocking_at_);
object = CheckShootAndFriendlyInLineOfFire(object, target->tile, attacker->critter.teamNum);
return (object && object->IsCritter()) ? object : nullptr; // 0 - if there are no friendly critters
}
bool AI::AttackInRange(fo::GameObject* source, fo::GameObject* weapon, long distance) {
if (game::Items::item_weapon_range(source, weapon, fo::AttackType::ATKTYPE_RWEAPON_PRIMARY) >= distance) return true;
return (game::Items::item_weapon_range(source, weapon, fo::AttackType::ATKTYPE_RWEAPON_SECONDARY) >= distance);
}
////////////////////////////////////////////////////////////////////////////////
static void __declspec(naked) ai_try_attack_hook_FleeFix() {
@@ -281,7 +249,7 @@ static long __fastcall ai_try_attack_switch_fix(fo::GameObject* target, long &hi
// is using a close range weapon?
long wType = fo::func::item_w_subtype(item, fo::AttackType::ATKTYPE_RWEAPON_PRIMARY);
if (wType <= fo::AttackSubType::MELEE) { // unarmed and melee weapons, check the distance before switching
if (!AI::AttackInRange(source, item, fo::func::obj_dist(source, target))) return -1; // target out of range, exit ai_try_attack_
if (!game::ai::AIHelpers::AttackInRange(source, item, fo::func::obj_dist(source, target))) return -1; // target out of range, exit ai_try_attack_
}
return 1; // all good, execute vanilla behavior of ai_switch_weapons_ function
}
@@ -526,7 +494,7 @@ fix:
////////////////////////////////////////////////////////////////////////////////
static bool __fastcall RollFriendlyFire(fo::GameObject* target, fo::GameObject* attacker) {
if (AI::CheckFriendlyFire(target, attacker)) {
if (game::ai::AIHelpers::CheckFriendlyFire(target, attacker)) {
long dice = fo::func::roll_random(1, 10);
return (fo::func::stat_level(attacker, fo::STAT_iq) >= dice); // true - is friendly
}
-5
View File
@@ -30,11 +30,6 @@ public:
const char* name() { return "AI"; }
void init();
static fo::GameObject* CheckShootAndFriendlyInLineOfFire(fo::GameObject* object, long targetTile, long team);
static fo::GameObject* CheckFriendlyFire(fo::GameObject* target, fo::GameObject* attacker);
static bool AttackInRange(fo::GameObject* source, fo::GameObject* weapon, long distance);
static fo::GameObject* __stdcall AIGetLastAttacker(fo::GameObject* target);
static fo::GameObject* __stdcall AIGetLastTarget(fo::GameObject* source);
};
+12
View File
@@ -15,3 +15,15 @@
#include "Game\skills.h"
#include "Game\stats.h"
#include "Game\tilemap.h"
__inline void InitReplacementHacks() {
game::gui::Render::init();
game::gui::Text::init();
game::CombatAI::init();
game::Inventory::init();
game::Items::init();
game::Skills::init();
game::Stats::init();
game::Tilemap::init();
}
+2
View File
@@ -292,6 +292,7 @@
<ClInclude Include="FalloutEngine\Variables.h" />
<ClInclude Include="FalloutEngine\Functions.h" />
<ClInclude Include="FalloutEngine\Functions_def.h" />
<ClInclude Include="Game\AI\AIHelpers.h" />
<ClInclude Include="Game\combatAI.h" />
<ClInclude Include="Game\GUI\render.h" />
<ClInclude Include="Game\GUI\Text.h" />
@@ -406,6 +407,7 @@
<ClCompile Include="FalloutEngine\FunctionOffsets.cpp" />
<ClCompile Include="FalloutEngine\Variables.cpp" />
<ClCompile Include="FalloutEngine\Functions.cpp" />
<ClCompile Include="Game\AI\AIHelpers.cpp" />
<ClCompile Include="Game\combatAI.cpp" />
<ClCompile Include="Game\GUI\render.cpp" />
<ClCompile Include="Game\GUI\Text.cpp" />
+9
View File
@@ -25,6 +25,9 @@
<Filter Include="Game\GUI">
<UniqueIdentifier>{e19ca1b6-f754-47a9-9a6d-5ce44592d8ab}</UniqueIdentifier>
</Filter>
<Filter Include="Game\AI">
<UniqueIdentifier>{6ce67248-1c25-4dae-967c-3078b65838e1}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h" />
@@ -358,6 +361,9 @@
<ClInclude Include="Game\GUI\render.h">
<Filter>Game\GUI</Filter>
</ClInclude>
<ClInclude Include="Game\AI\AIHelpers.h">
<Filter>Game\AI</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
@@ -660,6 +666,9 @@
<ClCompile Include="Game\GUI\render.cpp">
<Filter>Game\GUI</Filter>
</ClCompile>
<ClCompile Include="Game\AI\AIHelpers.cpp">
<Filter>Game\AI</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="version.rc" />
+1 -13
View File
@@ -100,19 +100,7 @@ DWORD HRPAddress(DWORD addr) {
return (hrpDLLBaseAddr | (addr & 0xFFFFF));
}
char falloutConfigName[65] = {0};
void InitReplacementHacks() {
game::gui::Render::init();
game::gui::Text::init();
game::CombatAI::init();
game::Inventory::init();
game::Items::init();
game::Skills::init();
game::Stats::init();
game::Tilemap::init();
}
char falloutConfigName[65];
static void InitModules() {
dlogr("In InitModules", DL_MAIN);