mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Moved some functions from AI.cpp to AIHelpers.cpp
This commit is contained in:
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user