Fixed a bug in 4.3.1 that caused AI to be unable to use some weapons

Code edits regarding AIpref in Enums.h.

Added GamePids.h (derived from ItemPid.h in mapper scripts)
This commit is contained in:
NovaRain
2022-01-13 10:14:25 +08:00
parent 7c0adc558a
commit f30558b091
10 changed files with 637 additions and 117 deletions
+13 -76
View File
@@ -18,6 +18,8 @@
#pragma once
#include "GamePids.h"
namespace fo
{
@@ -287,74 +289,6 @@ enum ArtType : char
OBJ_TYPE_SKILLDEX = 10
};
// Some FO2 PIDs possibly used by engine
enum ProtoID : unsigned long
{
PID_POWERED_ARMOR = 3,
// PID_ROCK = 19,
PID_SMALL_ENERGY_CELL = 38,
PID_MICRO_FUSION_CELL = 39,
PID_STIMPAK = 40,
PID_BOTTLE_CAPS = 41,
PID_FIRST_AID_KIT = 47,
PID_RADAWAY = 48,
PID_ANTIDOTE = 49,
PID_DYNAMITE = 51,
PID_GEIGER_COUNTER = 52,
PID_MENTATS = 53,
PID_STEALTH_BOY = 54,
// PID_WATER_CHIP = 55,
// PID_HOLODISK = 58,
PID_MOTION_SENSOR = 59,
PID_MUTATED_FRUIT = 71,
PID_BIG_BOOK_OF_SCIENCE = 73,
PID_DEANS_ELECTRONICS = 76,
PID_FLARE = 79,
PID_FIRST_AID_BOOK = 80,
PID_PLASTIC_EXPLOSIVES = 85,
PID_SCOUT_HANDBOOK = 86,
PID_BUFFOUT = 87,
PID_DOCTORS_BAG = 91,
// PID_PUMP_PARTS = 98,
PID_GUNS_AND_BULLETS = 102,
PID_NUKA_COLA = 106,
PID_RAD_X = 109,
PID_PSYCHO = 110,
PID_BEER = 124,
PID_BOOZE = 125,
PID_SUPER_STIMPAK = 144,
PID_ACTIVE_FLARE = 205,
PID_ACTIVE_DYNAMITE = 206,
PID_ACTIVE_GEIGER_COUNTER = 207,
PID_ACTIVE_MOTION_SENSOR = 208,
PID_ACTIVE_PLASTIC_EXPLOSIVE = 209,
PID_ACTIVE_STEALTH_BOY = 210,
PID_TECHNICAL_MANUAL = 228,
PID_HARDENED_POWER_ARMOR = 232,
PID_CHEMISTRY_MANUAL = 237,
PID_JET = 259,
PID_JET_ANTIDOTE = 260,
PID_HEALING_POWDER = 273,
PID_DECK_OF_TRAGIC_CARDS = 306,
PID_ADVANCED_POWER_ARMOR = 348,
PID_ADVANCED_POWER_ARMOR_MK2 = 349,
// PID_GECK = 366,
PID_SOLAR_SCORCHER = 390,
PID_CAR_TRUNK = 455,
PID_JESSE_CONTAINER = 467,
// critter
PID_Player = 0x01000000,
// scenery
PID_RAD_GOO_1 = 0x020003D9,
PID_RAD_GOO_4 = 0x020003DC,
PID_DRIVABLE_CAR = 0x020003F1, // index 1009
// misc type
PID_CORPSE_BLOOD = 0x05000004,
};
//XXXXXXXXXXXXXXXXXXXXX
//XX Critter defines XX
//XXXXXXXXXXXXXXXXXXXXX
@@ -888,8 +822,9 @@ namespace WinFlags {
}
namespace AIpref {
enum distance : long
enum class Distance : long
{
unset = -1,
stay_close = 0, // the attacker will stay at a distance no more than 5 hexes from the player (behavior only for party members, defined in ai_move_steps_closer, cai_perform_distance_prefs)
charge = 1, // AI will always try to get close to its target before or after attack
snipe = 2, // keep distance, when the distance between the attacker and the target decreases, the attacker will try to move away from the target to a distance of up to 10 hexes
@@ -898,7 +833,7 @@ namespace AIpref {
};
// presets for party members
enum disposition : long
enum class Disposition : long
{
none = -1,
custom = 0,
@@ -908,7 +843,7 @@ namespace AIpref {
berserk = 4
};
enum class attack_who : long
enum class AttackWho : long
{
no_attack_mode = -1,
whomever_attacking_me = 0, // attack the target that the player is attacking (only for party members)
@@ -918,7 +853,7 @@ namespace AIpref {
closest = 4, // only attack near targets
};
enum class run_away_mode : long
enum class RunAway : long
{
none = -1, // get the value from the cap.min_hp (in cai_get_min_hp_)
coward = 0, // 0%
@@ -929,9 +864,10 @@ namespace AIpref {
never = 5 // 100%
};
enum class weapon_pref : long
enum class WeaponPref : long
{
no_pref = 0,
unset = -1, // same as no_pref
no_pref = 0, // Guns > ...
melee = 1,
melee_over_ranged = 2,
ranged_over_melee = 3,
@@ -941,7 +877,7 @@ namespace AIpref {
random = 7 // not available for party member in control panel
};
enum class area_attack_mode : long
enum class AreaAttack : long
{
no_pref = -1, // special logic for NPC (not available for party member in control panel)
always = 0,
@@ -951,8 +887,9 @@ namespace AIpref {
be_absolutely_sure = 4, // 95% hit chance
};
enum class chem_use_mode : long
enum class ChemUse : long
{
unset = -1,
clean = 0,
stims_when_hurt_little = 1,
stims_when_hurt_lots = 2,
File diff suppressed because it is too large Load Diff
+12 -20
View File
@@ -184,11 +184,11 @@ struct GameObject {
union {
struct {
fo::MiscFlags miscFlags; // aka updated_flags
MiscFlags miscFlags; // aka updated_flags
// for weapons - ammo in magazine, for ammo - amount of ammo in last ammo pack
long charges;
// current type of ammo loaded in magazine
long ammoPid;
ProtoID ammoPid;
long unused[8]; // offset 0x44 (not saved)
} item;
@@ -240,13 +240,13 @@ struct GameObject {
} critter;
struct {
fo::MiscFlags sceneryFlags; // unused for scenery? (aka updated_flags)
fo::MiscFlags doorFlags; // used for doors states open/locked/jammed (aka cur_open_flags)
MiscFlags sceneryFlags; // unused for scenery? (aka updated_flags)
MiscFlags doorFlags; // used for doors states open/locked/jammed (aka cur_open_flags)
long unused[9]; // offset 0x40 (not saved)
} scenery;
};
DWORD protoId; // object PID
ProtoID protoId; // object PID
long cid; // combat ID (don't change while in combat)
long lightDistance;
long lightIntensity;
@@ -1000,24 +1000,16 @@ struct AIcap {
long outline_color;
long chance_message;
long combat_message_data[24];
long area_attack_mode;
long run_away_mode;
long best_weapon;
long distance;
long attack_who;
long chem_use;
AIpref::AreaAttack area_attack_mode;
AIpref::RunAway run_away_mode;
AIpref::WeaponPref pref_weapon;
AIpref::Distance distance;
AIpref::AttackWho attack_who;
AIpref::ChemUse chem_use;
long chem_primary_desire[3];
long disposition;
AIpref::Disposition disposition;
const char* body_type; // unused
const char* general_type; // unused
inline AIpref::distance getDistance() {
return (AIpref::distance)distance;
}
inline AIpref::run_away_mode getRunAwayMode() {
return (AIpref::run_away_mode)run_away_mode;
}
};
struct Queue {
+10 -10
View File
@@ -43,25 +43,25 @@ void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
long hpPercent = 50;
long chance = 0;
switch ((fo::AIpref::chem_use_mode)cap->chem_use) {
case fo::AIpref::chem_use_mode::stims_when_hurt_little: // use only healing drugs
switch (cap->chem_use) {
case fo::AIpref::ChemUse::stims_when_hurt_little: // use only healing drugs
hpPercent = 60;
break;
case fo::AIpref::chem_use_mode::stims_when_hurt_lots: // use only healing drugs
case fo::AIpref::ChemUse::stims_when_hurt_lots: // use only healing drugs
hpPercent = 30;
break;
case fo::AIpref::chem_use_mode::sometimes:
case fo::AIpref::ChemUse::sometimes:
if (!(fo::var::combatNumTurns % 3)) chance = 25; // every three turns
//hpPercent = 50;
break;
case fo::AIpref::chem_use_mode::anytime:
case fo::AIpref::ChemUse::anytime:
if (!(fo::var::combatNumTurns % 3)) chance = 75; // every three turns
//hpPercent = 50;
break;
case fo::AIpref::chem_use_mode::always:
case fo::AIpref::ChemUse::always:
chance = 100; // 99%
break;
case fo::AIpref::chem_use_mode::clean:
case fo::AIpref::ChemUse::clean:
return; // exit: don't use drugs
}
@@ -136,9 +136,9 @@ void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
source->critter.decreaseAP(aiUseItemAPCost);
slot = -1;
fo::AIpref::chem_use_mode chemUse = (fo::AIpref::chem_use_mode)cap->chem_use;
if (chemUse == fo::AIpref::chem_use_mode::sometimes ||
(chemUse == fo::AIpref::chem_use_mode::anytime && usedCount >= 2))
fo::AIpref::ChemUse chemUse = cap->chem_use;
if (chemUse == fo::AIpref::ChemUse::sometimes ||
(chemUse == fo::AIpref::ChemUse::anytime && usedCount >= 2))
{
break;
}
+1 -1
View File
@@ -282,7 +282,7 @@ static long __fastcall CheckDisableBurst(fo::GameObject* critter, fo::GameObject
return 10; // Disable Burst (area_attack_mode - non-existent value)
}
}
return cap->area_attack_mode; // default engine code
return (long)cap->area_attack_mode; // default engine code
}
static void __declspec(naked) ai_pick_hit_mode_hack_noBurst() {
+2 -2
View File
@@ -744,8 +744,8 @@ static void __fastcall action_attack_to(long unused, fo::GameObject* partyMember
validTarget->outline = outlineColor;
fo::AIcap* cap = fo::func::ai_cap(partyMember);
if (cap->disposition == fo::AIpref::disposition::custom) {
cap->attack_who = (long)fo::AIpref::attack_who::whomever;
if (cap->disposition == fo::AIpref::Disposition::custom) {
cap->attack_who = fo::AIpref::AttackWho::whomever;
}
// floating text messages
+8 -8
View File
@@ -241,7 +241,7 @@ void op_set_weapon_ammo_pid(OpcodeContext& ctx) {
if (fo::util::GetProto(obj->protoId, &proto)) {
long type = proto->item.type;
if (type == fo::ItemType::item_type_weapon || type == fo::ItemType::item_type_misc_item) {
obj->item.ammoPid = ctx.arg(1).rawValue();
obj->item.ammoPid = (fo::ProtoID)ctx.arg(1).rawValue();
}
} else {
ctx.printOpcodeError(protoFailedLoad, ctx.getOpcodeName(), obj->protoId);
@@ -490,22 +490,22 @@ void mf_get_object_ai_data(OpcodeContext& ctx) {
value = cap->aggression;
break;
case 1:
value = cap->area_attack_mode;
value = (long)cap->area_attack_mode;
break;
case 2:
value = cap->attack_who;
value = (long)cap->attack_who;
break;
case 3:
value = cap->best_weapon;
value = (long)cap->pref_weapon;
break;
case 4:
value = cap->chem_use;
value = (long)cap->chem_use;
break;
case 5:
value = cap->disposition;
value = (long)cap->disposition;
break;
case 6:
value = cap->distance;
value = (long)cap->distance;
break;
case 7:
value = cap->max_dist;
@@ -520,7 +520,7 @@ void mf_get_object_ai_data(OpcodeContext& ctx) {
value = cap->hurt_too_much; // DAM_BLIND/DAM_CRIP_* flags
break;
case 11:
value = cap->run_away_mode;
value = (long)cap->run_away_mode;
break;
case 12:
value = cap->secondary_freq;
+1
View File
@@ -64,6 +64,7 @@ static void __declspec(naked) ai_can_use_weapon_hack() {
using namespace fo;
using namespace Fields;
__asm {
mov ebp, ebx;
test dword ptr [esi + miscFlags], CantUse;
jnz cantUse;
mov eax, [edi + damageFlags];
+1
View File
@@ -292,6 +292,7 @@
<ClInclude Include="FalloutEngine\Fallout2.h" />
<ClInclude Include="FalloutEngine\FunctionOffsets.h" />
<ClInclude Include="FalloutEngine\FunctionOffsets_def.h" />
<ClInclude Include="FalloutEngine\GamePids.h" />
<ClInclude Include="FalloutEngine\Structs.h" />
<ClInclude Include="FalloutEngine\EngineUtils.h" />
<ClInclude Include="FalloutEngine\VariableOffsets.h" />
+3
View File
@@ -437,6 +437,9 @@
<ClInclude Include="Modules\SubModules\DirectDraw.h">
<Filter>Modules\SubModules</Filter>
</ClInclude>
<ClInclude Include="FalloutEngine\GamePids.h">
<Filter>FalloutEngine</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />