You can download it here along with the Supply and Demand mod.
INSTRUCTIONS
The only requirement for this to work is that you have sfall.
To install you can make a folder titled Patch000.dat in the game directory, use Dat Explorer or another program to extract the original Patch000.dat file in that directory, then put the .int files in the scripts folder. If you don't want to override the dude_obj script, you can just copy the couple of lines at the top of map_enter_p_proc, combat_p_proc and critter_p_proc to your own obj_dude script.
INTRODUCTION
Everybody knows that Fallout is a horribly unbalanced game. The majority of perks, traits and skills are completely useless, and combat invariably goes from being a nailbitingly tense experience early on in a game to a boring untactical eye-critting slaughterfest by the end. This mod tries to address the latter problem by making the late game as tense as the early game. For the moment, the mod only does the chance to hit calculation and the weapon-related Action Point cost calculations for the game, though an extremely unrealistic end project of mine would entail doing all the relevant combat calculations (so also damage and the after hit roll stuff) via hookscripts.
Now, first off, why start out with chance to hit and not, say, the damage model to fix combat? This is because I'm convinced that the root of the balancing problem lies in the fact that whereas the chance to hit system works quite well in the beginning (e.g. if I have an 80% chance of hitting someone with an unaimed shot, then I have a 20% chance of hitting them in the eyes), it quickly veers off the tracks towards the end (e.g. if you're skilled enough, which you will be by mid-game, then an unaimed shot and an eye shot will invariably both end up as 95% hits). While fixing balance is my primary concern, I've also tried to address what are in my view unlogical (e.g. sniping) or boring (e.g. unarmed combat) aspects of the current combat system. I'll now start explaining all the new calculations and the reasoning behind them. The calculations proceed in three phases (two for melee and unarmed), and I'll deal with them one by one. After that I'll explain the changes to the AP cost system. And finally there'll be the scripts themselves for you to check out between spoiler tags.
TO HIT CHANCE FIRST STAGE
Unarmed and Melee Combat
The current system works like this:
Code: Select all
old:(unarmed skill attacker)-(AC target)
Code: Select all
new:(has_skill(attacker, SKILL_UNARMED_COMBAT))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-cripplepen-bodypen-attackerexhaustion-(has_skill(attacker, SKILL_UNARMED_COMBAT)-100)-(get_critter_stat(target, STAT_ag)*agilitymod)-(get_critter_stat(target, STAT_pe))
First, there's of course the unarmed skill of the attacker.
Next, the exhaustion of the target is added. Once the number of turns has exceeded the target's endurance (so after the first turn if your endurance is 1, after the tenth turn if it is 10), a potential 6 point bonus is added to your chance to hit for each consecutive turn, half of which is determined by the ratio of weight carried to maximum weight (that is to say, if you are lightly packed, the effects of exhaustion will be less severe). The same principle however also applies to the attacker's exhaustion, which results in a penalty to hit.
Checks are made for whether the attacker or the target have the Kamikaze trait. In the original, this trait was rarely useful; you sacrificed armor class in favor of a possible extra early turn. I've made the Kamikaze trait into what I originally expected it to be: sacrificing defense for offense. So, what the trait does now is add an agility*3 bonus to to hit and a agility*3 bonus to the opponent's to hit, on top of the old sequence bonus. Will probably have to be changed around a bit still, but I like the principle.
The One Hander trait is somewhat nerfed from the original: 10% bonus for one handed weapons, 20% penalty for two handed weapons.
Being crippled in one arm affects your accuracy by 50% if the weapon is in the relevant arm (or if you are carrying a two handed weapon). Being blind not only gives another 50% penalty, but also an additional gross distance modifier penalty (4 per hex).
The basic bodypart penalty is only slightly changed from the original. Now, the unaimed shot is what I originally imagined it to be: a snapshot. So it's faster than a precision strike, but often also less precise. This means that for melee/unarmed, an unaimed shot has a -20 basic penalty to hit, while for ranged combat it has a -10 basic penalty on top of a -1 per hex distance penalty. So now there's finally a reason to do an aimed blow to the body.
The opponent's unarmed and melee skill now also factors into the calculation. Where in the original system you would eventually always just slug it out, with each blow safely landing, now a superior pugilist will be able to dodge your blows. If the target is carrying a ranged weapon then the attacker gets a 20 point bonus.
Instead of Armor Class, which is now an entirely redundant stat (for more on that see one of the later posts in this thread), agility itself plays a large role. For now the agility bonus gets calculated as follows. As long as the target is not wearing hindering armor (starting with Metal Armor), the penalty is the target's agility*2, which becomes *4 with the dodger perk and even *7 with the hthevade perk on top (if you're not wielding a weapon at the moment that is ofcourse). Once the target is hindered by being armored (this also applies to critters such as Super Mutants), or heavily armored (starting with Power Armor), these penalties drop significantly (e.g. with Power Armor, the target's agility and dodge perk advantages dissappear and only a third of the hth evade perk still applies).
Finally, the target's perception also plays a (minor) roll, as it determines how well the target can anticipate attacker's blows.
Ranged Combat
Here's how the mod calculates ranged combat:
Code: Select all
new:(has_skill(attacker, SKILL_SMALL_GUNS))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-bodypen-attackerexhaustion-(get_critter_stat(target, STAT_ag)*agilitymod)+(get_critter_stat(attacker, STAT_pe)) - (strengthpen)
Code: Select all
minstrength:=(weaponweight/4)+recoil-((has_trait(TRAIT_PERK, attacker, PERK_weapon_handling_perk) > 0)*3);
Code: Select all
strengthpen:=((minstrength)-(get_critter_stat(attacker, STAT_st)))* (4+(exhaustion/4));
TO HIT CHANCE SECOND STAGE (RANGED ONLY)
The basics of determining distance modifiers are as follows:
Code: Select all
(hexes)*((10+lightmod)-perceptionmod);
The way light affects distance modifiers is that high light levels yield no penalty, medium one point, and low ones two points. What I have now is that, on top of their light adjustments, the night vision perk and the fn fal with nightsight now reduce the penalty by one. Hopefully this makes them a bit less useless.
Throwing weapons work more or less the same way as other ranged weapons, except that the distance modifier is not just impacted by perception, but agility as well. Also, the heave-ho perk is now also a throwing variant of the sharpshooter perk in that it gives a 2 point bonus to distance modifiers (might be a bit too big, but I don't know terribly much about the throwing skill to be honest).
As a side note, you now also get a slight penalty when using a melee weapon over two hexes; not sure if this was the case already.
TO HIT CHANCE THIRD PHASE
To further balance things out, the to hit chance that rolls out of the previous two phases is finally adjusted further based on the bodypart aimed at. This is done in a way akin to the skill progression system: progress becomes gradually more costly. The consequence is that, in addition to the basic penalty, the chance to hit the eyes progresses slower than the chance to hit the body (in the former it's the case that getting to 20% chance progresses normally, then to 40% the "cost" becomes two points per increase, then up to 60% three points, etc. while for the body it's simply the first 50% regular and the next double cost).
I could try to give a complicated rationale for this, but the main reason is balancing. The point of the system is that early combat stays more or less as difficult as it is, while crazy late-game eye-crit rampages stop. To even get above 75% for an eye hit you need to think in the range of a 250+ investment in the related (ranged) combat stat. Some might think this system sacrifices realism for the sake of balance, perhaps pointing out that a skilled marksman can easily reach 80+% hits on eyes during target practice. To that I'd just say I believe combat in Fallout should be thought of as much more dynamic than it looks through the trappings of turn-based combat; what seems like a stationary target in the middle of a dirt road is best thought of as actually someone maneuvering at speed from cover to cover (hence the emphasis on agility, endurance and perception in my system); try getting 80% eye-hits on a dynamic target like that.
Finally, the attacker gets a further 40% bonus if the target is lying down, just like in the original.
CHANGES TO AP COST
I've always felt the AP costs of the various weapons in Fallout were often extremely arbitrary (e.g. why is a .44 magnum faster to shoot than a 10 MM pistol?).
With my own approach, I've tried to keep things as simple and unarbitrary as possible. The base AP cost for an unaimed snapshot (remember that this now has a penalty, making the aimed bodyshot the new "safe" option) is now 3 points (the exception is 4 points for thrown), to which points are added for two handed weapons (1), for energy weapons (1), for big guns (2), for aimed shots (2, or 3 if with a scoped weapon), and for bursts as a secondary mode (2). The consequence is that whereas for instance the Minigun stays the same AP (3+1+2=6), the super sledge now costs 4 for the primary attack (3+1=4). Of course the old exceptions (like flares costing 1 AP) still apply. Unarmed has stayed the same as in the original, except that I've incorporated Magnus's common sense fix of making the secondary attacks cost only one additional AP. Having crippled arms also raises the AP cost, though only if the weapon is in the relevant arm or if you're using a two-handed weapon.
Of the AP-related perks and traits I needed to change at least one, given that I've already lowered the base cost for ranged weapons
from 4 to 3. I decided to make the fast shot trait something which makes you better at fast shots, so that the basic 10% penalty for snapshots now dissappears (the ranged penalty still applies however). The increased rate of fire/hth attacks perks still reduce the relevant AP costs, though (given that they are so incredibly overpowered at the moment), they also come with a base penalty of 10% to hit now. These perks are still huge advantages all the same of course.
SCRIPTS
The to hit script:
[spoiler]
Code: Select all
//hs_tohit.int
procedure start;
#include "C:\Program Files (x86)\GOG.com\Fallout 2 Mapper\scripts\HEADERS\sfall.h"
#include "C:\Program Files (x86)\GOG.com\Fallout 2 Mapper\scripts\HEADERS\define.h"
#include "C:\Program Files (x86)\GOG.com\Fallout 2 Mapper\scripts\HEADERS\command.h"
procedure start begin
variable hitchance;
variable target;
variable attacker;
variable bodypart;
variable weaponright;
variable weaponleft;
variable weaponrange;
variable weaponweight;
variable cripplepen;
variable hexes;
variable x;
variable perceptionmod;
variable snapshotpen;
variable bodypen;
variable onehander;
variable attackerkamikaze;
variable targetkamikaze;
variable agilitymod;
variable tmp;
variable tmphitchance;
variable tmphitchance2;
variable tmphitchance3;
variable tmphitchancemod;
variable attackerexhaustion;
variable targetexhaustion;
variable minstrength;
variable strengthpen;
variable recoil;
variable hthevade;
variable lightmod;
if(init_hook) then begin
end else begin
hitchance:=get_sfall_arg;
attacker:=get_sfall_arg;
target:=get_sfall_arg;
bodypart:=get_sfall_arg;
hexes:=tile_distance_objs(target, attacker);
if weapon_in_right_hand(attacker) and not (two_handed_in_right_hand(attacker)) then begin
cripplepen:=((critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT)*50)+((critter_state(dude_obj) bwand DAM_BLIND)*50);
end else if weapon_in_left_hand(attacker) and not (two_handed_in_left_hand(attacker)) then begin
cripplepen:=((critter_state(dude_obj) bwand DAM_CRIP_ARM_LEFT)*50)+((critter_state(dude_obj) bwand DAM_BLIND)*50);
end else begin
cripplepen:=((critter_state(dude_obj) bwand DAM_CRIP_ARM_LEFT)*50)+((critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT)*50)+((critter_state(dude_obj) bwand DAM_BLIND)*50);
end if get_sfall_global_int("combattu") > get_critter_stat(target, STAT_en) then begin
targetexhaustion:=((get_sfall_global_int("combattu") - get_critter_stat(target, STAT_en))*(3+(3*(get_critter_stat(target, STAT_carry_amt)/who_carry_amount(target)))));
end else begin
targetexhaustion:=0;
end if (get_sfall_global_int("combattu")) > (get_critter_stat(attacker, STAT_en)) then begin
attackerexhaustion:=((get_sfall_global_int("combattu") - get_critter_stat(attacker, STAT_en))*(3+(3*(get_critter_stat(attacker, STAT_carry_amt)/who_carry_amount(attacker)))));
end else begin
attackerexhaustion:=0;
end
hthevade:=(has_trait(TRAIT_PERK, target, PERK_hth_evade_perk) > 0)*((not weapon_in_left_hand(target) and not weapon_in_right_hand(target))*(1 + (get_critter_stat(attacker, STAT_dmg_thresh) ^ 4) + (get_critter_stat(attacker, STAT_dmg_thresh) ^ 12)));
if (two_handed_in_left_hand(attacker) or two_handed_in_right_hand(attacker)) and (has_trait(TRAIT_TRAIT, attacker, TRAIT_one_hander) > 0) then begin
onehander:=-20;
end else if (not(two_handed_in_left_hand(attacker) or two_handed_in_right_hand(attacker))) and (has_trait(TRAIT_TRAIT, attacker, TRAIT_one_hander) > 0) then begin
onehander:=10;
end else begin
onehander:=0;
end
if (ranged_in_left_hand(attacker) or ranged_in_right_hand(attacker)) then begin
if (bodypart==1) or (bodypart==2) or (bodypart==7) then begin
tmp := 35;
bodypen := 30 + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_rate_of_fire) > 0)*10);
snapshotpen := 0;
end else if (bodypart==8) then begin
tmp := 35;
bodypen := 10 - ((has_trait(TRAIT_TRAIT, attacker, TRAIT_fast_shot) > 0)*10) + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_rate_of_fire) > 0)*10);
snapshotpen := 1;
end else if (bodypart==4) or (bodypart==5) then begin
tmp := 40;
bodypen := 20 + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_rate_of_fire) > 0)*10);
snapshotpen := 0;
end else if (bodypart==0) then begin
tmp := 30;
bodypen := 40 + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_rate_of_fire) > 0)*10);
snapshotpen := 0;
end else if (bodypart==3) then begin
tmp := 50;
bodypen := 0 + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_rate_of_fire) > 0)*10);
snapshotpen := 0;
end else if (bodypart==6) then begin
tmp := 20;
bodypen := 60 + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_rate_of_fire) > 0)*10);
snapshotpen := 0;
end
end
else if (thrown_in_left_hand(attacker) or thrown_in_right_hand(attacker)) then begin
if (bodypart==1) or (bodypart==2) or (bodypart==7) then begin
tmp := 35;
bodypen := 30;
snapshotpen := 0;
end else if (bodypart==8) then begin
tmp := 35;
bodypen := 10;
snapshotpen := 1;
end else if (bodypart==4) or (bodypart==5) then begin
tmp := 40;
bodypen := 20;
snapshotpen := 0;
end else if (bodypart==0) then begin
tmp := 30;
bodypen := 40;
snapshotpen := 0;
end else if (bodypart==3) then begin
tmp := 50;
bodypen := 0;
snapshotpen := 0;
end else if (bodypart==6) then begin
tmp := 20;
bodypen := 60;
snapshotpen := 0;
end
end
else begin
if (bodypart==1) or (bodypart==2) or (bodypart==7) then begin
tmp := 35;
bodypen := 30 + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_hth_attacks) > 0)*10);
snapshotpen := 0;
end else if (bodypart==8) then begin
tmp := 35;
bodypen := 20 + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_hth_attacks) > 0)*10);
snapshotpen := 1;
end else if (bodypart==4) or (bodypart==5) then begin
tmp := 40;
bodypen := 20 + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_hth_attacks) > 0)*10);
snapshotpen := 0;
end else if (bodypart==0) then begin
tmp := 30;
bodypen := 40 + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_hth_attacks) > 0)*10);
snapshotpen := 0;
end else if (bodypart==3) then begin
tmp := 50;
bodypen := 0 + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_hth_attacks) > 0)*10);
snapshotpen := 0;
end else if (bodypart==6) then begin
tmp := 20;
bodypen := 60 + ((has_trait(TRAIT_PERK, attacker, PERK_bonus_hth_attacks) > 0)*10);
snapshotpen := 0;
end
end
if (thrown_in_left_hand(attacker) or thrown_in_right_hand(attacker) or melee_in_left_hand(attacker) or melee_in_right_hand(attacker)) then begin
perceptionmod:=((get_critter_stat(attacker, STAT_pe)+get_critter_stat(attacker, STAT_ag))/2)+((has_trait(TRAIT_PERK, attacker, PERK_heave_ho) > 0)*2) - ((critter_state(dude_obj) bwand DAM_BLIND)*4);
end else if (ranged_in_left_hand(attacker) or ranged_in_right_hand(attacker)) then begin
perceptionmod:=get_critter_stat(attacker, STAT_pe) + (has_trait(TRAIT_PERK, attacker, PERK_sharpshooter) > 0) - snapshotpen - ((critter_state(dude_obj) bwand DAM_BLIND)*4);
end
agilitymod:=(get_critter_stat(attacker, STAT_dmg_thresh) ^ 4) + (get_critter_stat(attacker, STAT_dmg_thresh) ^ 12) + ((has_trait(TRAIT_PERK, target, PERK_dodger) > 0)*((get_critter_stat(attacker, STAT_dmg_thresh) ^ 4) + (get_critter_stat(attacker, STAT_dmg_thresh) ^ 12))) + (hthevade);
attackerkamikaze:=(has_trait(TRAIT_TRAIT, attacker, TRAIT_kamikaze) > 0)*(get_critter_stat(attacker, STAT_ag)*2);
targetkamikaze:=(has_trait(TRAIT_TRAIT, target, TRAIT_kamikaze) > 0)*(get_critter_stat(target, STAT_ag)*3);
weaponleft:=obj_pid(critter_inven_obj(attacker,INVEN_TYPE_LEFT_HAND));
weaponright:=obj_pid(critter_inven_obj(attacker,INVEN_TYPE_RIGHT_HAND));
if weaponleft != -1 then begin
weaponrange:=pid_range(weaponleft);
weaponweight:=pid_weight(weaponleft);
end else if weaponright != -1 then begin
weaponrange:=pid_range(weaponright);
weaponweight:=pid_weight(weaponright);
end else begin
weaponrange:=0;
weaponweight:=0;
end
if heavy_weapon_left_hand(attacker) or heavy_weapon_right_hand(attacker) then begin
recoil:=3;
end else if medium_weapon_left_hand(attacker) or medium_weapon_right_hand(attacker) then begin
recoil:=3;
end else if light_weapon_left_hand(attacker) or light_weapon_right_hand(attacker) then begin
recoil:=2;
end
minstrength:=(weaponweight/4)+recoil-((has_trait(TRAIT_PERK, attacker, PERK_weapon_handling_perk) > 0)*3);
if minstrength > (get_critter_stat(attacker, STAT_st)) then begin
strengthpen:=((minstrength)-(get_critter_stat(attacker, STAT_st)))*(4+(attackerexhaustion/4));
end else begin
strengthpen:=0;
end if (get_light_level ^ 30000) and not ((obj_pid(critter_inven_obj(attacker,INVEN_TYPE_LEFT_HAND)) == PID_FN_FAL_NIGHT_SCOPE) or (obj_pid(critter_inven_obj(attacker,INVEN_TYPE_RIGHT_HAND)) == PID_FN_FAL_NIGHT_SCOPE) or (has_trait(TRAIT_PERK, attacker, PERK_night_vision) > 0)) then begin
lightmod:=2;
end else if ((get_light_level ^ 30000) and ((obj_pid(critter_inven_obj(attacker,INVEN_TYPE_LEFT_HAND)) == PID_FN_FAL_NIGHT_SCOPE) or (obj_pid(critter_inven_obj(attacker,INVEN_TYPE_RIGHT_HAND)) == PID_FN_FAL_NIGHT_SCOPE) or (has_trait(TRAIT_PERK, attacker, PERK_night_vision) > 0))) or (get_light_level ^ 45000) then begin
lightmod:=1;
end else begin
lightmod:=0;
end if (ranged_in_left_hand(attacker) or ranged_in_right_hand(attacker) or thrown_in_left_hand(attacker) or thrown_in_right_hand(attacker)) then begin
x:=(weaponrange/5);
end else begin
x:=3;
end if not ((weapon_in_left_hand(attacker)) or (weapon_in_right_hand(attacker))) then begin
if not (weapon_in_left_hand(target) or weapon_in_right_hand(target)) then begin
tmphitchance:=(has_skill(attacker, SKILL_UNARMED_COMBAT))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-bodypen-cripplepen-attackerexhaustion-(has_skill(attacker, SKILL_UNARMED_COMBAT)-100)-(get_critter_stat(target, STAT_ag)*agilitymod)-(get_critter_stat(target, STAT_pe));
end else if (melee_in_left_hand(target) or melee_in_right_hand(target)) then begin
tmphitchance:=(has_skill(attacker, SKILL_UNARMED_COMBAT))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-bodypen-cripplepen-attackerexhaustion-(has_skill(attacker, SKILL_MELEE)-100)-(get_critter_stat(target, STAT_ag)*agilitymod)-(get_critter_stat(target, STAT_pe));
end else begin
tmphitchance:=(has_skill(attacker, SKILL_UNARMED_COMBAT))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-bodypen-cripplepen-attackerexhaustion-(has_skill(attacker, SKILL_MELEE)-120)-(get_critter_stat(target, STAT_ag)*agilitymod)-(get_critter_stat(target, STAT_pe));
end
end else if (melee_in_left_hand(attacker) or melee_in_right_hand(attacker)) then begin
if not (weapon_in_left_hand(target) or weapon_in_right_hand(target)) then begin
tmphitchance:=(has_skill(attacker, SKILL_MELEE))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-bodypen-cripplepen-attackerexhaustion-(has_skill(attacker, SKILL_UNARMED_COMBAT)-100)-(get_critter_stat(target, STAT_ag)*agilitymod)-(get_critter_stat(target, STAT_pe)) - (strengthpen);
end else if (melee_in_left_hand(target) or melee_in_right_hand(target)) then begin
tmphitchance:=(has_skill(attacker, SKILL_MELEE))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-bodypen-cripplepen-attackerexhaustion-(has_skill(attacker, SKILL_MELEE)-100)-(get_critter_stat(target, STAT_ag)*agilitymod)-(get_critter_stat(target, STAT_pe)) - (strengthpen);
end else begin
tmphitchance:=(has_skill(attacker, SKILL_MELEE))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-bodypen-cripplepen-attackerexhaustion-(has_skill(attacker, SKILL_MELEE)-120)-(get_critter_stat(target, STAT_ag)*agilitymod)-(get_critter_stat(target, STAT_pe)) - (strengthpen);
end
end else if (small_arms_in_left_hand(attacker) or small_arms_in_right_hand(attacker)) then begin
tmphitchance:=(has_skill(attacker, SKILL_SMALL_GUNS))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-bodypen-cripplepen-attackerexhaustion-(get_critter_stat(target, STAT_ag)*agilitymod)+(get_critter_stat(attacker, STAT_pe)) - (strengthpen);
end else if (energy_weapon_in_left_hand(attacker) or energy_weapon_in_right_hand(attacker)) then begin
tmphitchance:=(has_skill(attacker, SKILL_ENERGY_WEAPONS))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-bodypen-cripplepen-attackerexhaustion-(get_critter_stat(target, STAT_ag)*agilitymod)+(get_critter_stat(attacker, STAT_pe)) - (strengthpen);
end else if (big_gun_in_left_hand(attacker) or big_gun_in_right_hand(attacker)) then begin
tmphitchance:=(has_skill(attacker, SKILL_BIG_GUNS))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-bodypen-cripplepen-attackerexhaustion-(get_critter_stat(target, STAT_ag)*agilitymod)+(get_critter_stat(attacker, STAT_pe)) - (strengthpen);
end else if (thrown_in_left_hand(attacker) or thrown_in_right_hand(attacker)) then begin
tmphitchance:=(has_skill(attacker, SKILL_THROWING))+targetexhaustion+attackerkamikaze+targetkamikaze+onehander-bodypen-cripplepen-attackerexhaustion-(get_critter_stat(target, STAT_ag)*agilitymod)+(get_critter_stat(attacker, STAT_pe)) - (strengthpen);
end
if ((weapon_in_left_hand(attacker) or weapon_in_right_hand(attacker)) and not ((scoped_rifle_in_left_hand(attacker) or scoped_rifle_in_right_hand(attacker)) and (bodypart != 8))) then begin
if (hexes>1) and (hexes^=x) then begin
tmphitchancemod:=(hexes)*((10+lightmod)-perceptionmod);
end else if (hexes>(x)) and (hexes^=x*2) then begin
tmphitchancemod:=((hexes-x)*((11+lightmod)-perceptionmod))+(x*((10+lightmod)-perceptionmod));
end else if (hexes>(x*2)) and (hexes^=x*3) then begin
tmphitchancemod:=((hexes-(x*2))*((12+lightmod)-perceptionmod))+(x*((10+lightmod)-perceptionmod))+(x*((11+lightmod)-perceptionmod));
end else if (hexes>(x*3)) and (hexes^=x*4) then begin
tmphitchancemod:=((hexes-(x*3))*((13+lightmod)-perceptionmod))+(x*((10+lightmod)-perceptionmod))+(x*((11+lightmod)-perceptionmod))+(x*((12+lightmod)-perceptionmod));
end else if (hexes>(x*4)) then begin
tmphitchancemod:=((hexes-(x*4))*((14+lightmod)-perceptionmod))+(x*((10+lightmod)-perceptionmod))+(x*((11+lightmod)-perceptionmod))+(x*((12+lightmod)-perceptionmod))+(x*((13+lightmod)-perceptionmod));
end else begin
tmphitchancemod:=0;
end
end else if (scoped_rifle_in_left_hand(attacker) or scoped_rifle_in_right_hand(attacker)) and (bodypart != 8) then begin
tmphitchancemod:=hexes*((10+lightmod)-perceptionmod);
end else begin
tmphitchancemod:=0;
end
tmphitchance2:=tmphitchance-tmphitchancemod;
if (tmphitchance2>(tmp*28)) then begin
tmphitchance3:=((tmphitchance2-(tmp*28))/8 + (tmp*7));
end else if (tmphitchance2>(tmp*21)) then begin
tmphitchance3:=((tmphitchance2-(tmp*21))/7 + (tmp*6));
end else if (tmphitchance2>(tmp*15)) then begin
tmphitchance3:=((tmphitchance2-(tmp*15))/6 + (tmp*5));
end else if (tmphitchance2>(tmp*10)) then begin
tmphitchance3:=((tmphitchance2-(tmp*10))/5 + (tmp*4));
end else if (tmphitchance2>(tmp*6)) then begin
tmphitchance3:=((tmphitchance2-(tmp*6))/4 + (tmp*3));
end else if (tmphitchance2>(tmp*3)) then begin
tmphitchance3:=((tmphitchance2-(tmp*3))/3 + (tmp*2));
end else if (tmphitchance2>(tmp)) then begin
tmphitchance3:=((tmphitchance2-tmp)/2 + tmp);
end else begin
tmphitchance3:=tmphitchance2;
end
if is_critter_prone(target) then begin
tmphitchance3+=40;
end if tmphitchance3 > 95 then begin
hitchance:=95;
end else begin
hitchance:=tmphitchance3;
end
//display_msg(" weaponleft " + weaponleft);
//display_msg(" weaponright " + weaponright);
//display_msg(" weaponrange " + weaponrange);
//display_msg(" weaponweight " + weaponweight);
//display_msg(" hexes " + hexes);
//display_msg(" x " + x);
//display_msg(" perceptionmod " + perceptionmod);
//display_msg(" agilitymod " + agilitymod);
//display_msg(" tmp " + tmp);
//display_msg(" tmphitchance " + tmphitchance);
//display_msg(" tmphitchance2 " + tmphitchance2);
//display_msg(" tmphitchance3 " + tmphitchance3);
//display_msg(" tmphitchancemod " + tmphitchancemod);
//display_msg(" onehander " + onehander);
//display_msg(" snapshotpen " + snapshotpen);
//display_msg(" attackerexhaustion " + attackerexhaustion);
//display_msg(" bodypen " + bodypen);
//display_msg(" targetexhaustion " + targetexhaustion);
//display_msg(" attackerkamikaze " + attackerkamikaze);
//display_msg(" targetkamikaze " + targetkamikaze);
//display_msg(" minstrength " + minstrength);
//display_msg(" strengthpen " + strengthpen);
//display_msg(" recoil " + recoil);
//display_msg(" hthevade " + hthevade);
//display_msg(" lightmod " + lightmod);
//display_msg(" prone " + is_critter_prone(target));
//display_msg(" cripplepen " + cripplepen);
//display_msg(" skill self " + has_skill(attacker, SKILL_UNARMED_COMBAT));
//display_msg(" skill opponent " + has_skill(target, SKILL_UNARMED_COMBAT));
set_sfall_return(hitchance);
end
end
The AP cost script:
[spoiler]
Code: Select all
procedure start;
#include "C:\Program Files (x86)\GOG.com\Fallout 2 Mapper\scripts\HEADERS\sfall.h"
#include "C:\Program Files (x86)\GOG.com\Fallout 2 Mapper\scripts\HEADERS\define.h"
procedure start begin
variable attacker, type, aimed, i;
if not init_hook then begin
attacker:=get_sfall_arg;
type:=get_sfall_arg;
aimed:=get_sfall_arg;
i:=-1;
if (type == ATKTYPE_LWEP1) or (type == ATKTYPE_LWEP2) then begin
if (ranged_in_left_hand(attacker)) then begin
i:= 3 + (two_handed_in_left_hand(attacker)) + (ranged_six_ap_left_hand(attacker)) + (small_energy_in_left_hand(attacker)) + (big_gun_in_left_hand(attacker) or big_energy_in_left_hand(attacker)) - (has_trait(TRAIT_PERK, attacker, PERK_bonus_rate_of_fire) > 0) + (((critter_state(dude_obj) bwand DAM_CRIP_ARM_LEFT) or ((critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT) and two_handed_in_left_hand(attacker)))*2);
end else if (thrown_in_left_hand(attacker)) then begin
i:= 3 + ((critter_state(dude_obj) bwand DAM_CRIP_ARM_LEFT)*2) - (((obj_pid(critter_inven_obj(attacker,INVEN_TYPE_LEFT_HAND)) == PID_ACTIVE_FLARE) or (obj_pid(critter_inven_obj(attacker,INVEN_TYPE_LEFT_HAND)) == PID_FLARE))*2);
end else if (melee_in_left_hand(attacker) or fist_enhanced_in_left_hand(attacker)) then begin
i:= 3 - (has_trait(TRAIT_PERK, dude_obj, PERK_bonus_hth_attacks) > 0) + (two_handed_in_left_hand(attacker)) + (((critter_state(dude_obj) bwand DAM_CRIP_ARM_LEFT) or ((critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT) and two_handed_in_left_hand(attacker)))*2) + (obj_pid(critter_inven_obj(attacker,INVEN_TYPE_LEFT_HAND)) == PID_MEGA_POWER_FIST);
end
end else if (type == ATKTYPE_RWEP1) or (type == ATKTYPE_RWEP2) then begin
if (ranged_in_right_hand(attacker)) then begin
i:= 3 + (two_handed_in_right_hand(attacker)) + (small_energy_in_right_hand(attacker)) + (big_gun_in_right_hand(attacker) or big_energy_in_right_hand(attacker)) + (ranged_six_ap_right_hand(attacker)) - (has_trait(TRAIT_PERK, attacker, PERK_bonus_rate_of_fire) > 0) + (((critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT) or ((critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT) and two_handed_in_right_hand(attacker)))*2);
end else if (thrown_in_right_hand(attacker)) then begin
i:= 3 + ((critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT)*2) - (((obj_pid(critter_inven_obj(attacker,INVEN_TYPE_RIGHT_HAND)) == PID_ACTIVE_FLARE) or (obj_pid(critter_inven_obj(attacker,INVEN_TYPE_RIGHT_HAND)) == PID_FLARE))*2);
end else if (melee_in_right_hand(attacker) or fist_enhanced_in_right_hand(attacker)) then begin
i:= 3 - (has_trait(TRAIT_PERK, dude_obj, PERK_bonus_hth_attacks) > 0) + (two_handed_in_right_hand(attacker)) + (((critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT) or ((critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT) and two_handed_in_right_hand(attacker)))*2) + (obj_pid(critter_inven_obj(attacker,INVEN_TYPE_RIGHT_HAND)) == PID_MEGA_POWER_FIST);
end
end else if (type == ATKTYPE_PUNCH) or (type == ATKTYPE_STRONGPUNCH) or (type == ATKTYPE_HAMMERPUNCH) or (type == ATKTYPE_HAYMAKER) then begin
i:= 3 - (has_trait(TRAIT_PERK, dude_obj, PERK_bonus_hth_attacks) > 0) + (critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT) + (critter_state(dude_obj) bwand DAM_CRIP_ARM_LEFT);
end else if (type == ATKTYPE_STRONGKICK) or (type == ATKTYPE_SNAPKICK) or (type == ATKTYPE_POWERKICK) or (type == ATKTYPE_KICK) then begin
i:= 4 - (has_trait(TRAIT_PERK, dude_obj, PERK_bonus_hth_attacks) > 0) + (critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT) + (critter_state(dude_obj) bwand DAM_CRIP_ARM_LEFT);
end else if (type == ATKTYPE_PALMSTRIKE) or (type == ATKTYPE_PIERCINGSTRIKE) or (type == ATKTYPE_JAB) then begin
i:= 4 - (has_trait(TRAIT_PERK, dude_obj, PERK_bonus_hth_attacks) > 0) + (critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT) + (critter_state(dude_obj) bwand DAM_CRIP_ARM_LEFT);
end else if (type == ATKTYPE_HIPKICK) or (type == ATKTYPE_HOOKKICK) or (type == ATKTYPE_PIERCINGKICK) then begin
i:= 5 - (has_trait(TRAIT_PERK, dude_obj, PERK_bonus_hth_attacks) > 0) + (critter_state(dude_obj) bwand DAM_CRIP_ARM_RIGHT) + (critter_state(dude_obj) bwand DAM_CRIP_ARM_LEFT);
end if (type == ATKTYPE_LWEP2) or (type == ATKTYPE_RWEP2) then begin
if (ranged_in_left_hand(attacker) or ranged_in_right_hand(attacker)) then begin
i+= 2;
end else if (thrown_in_left_hand(attacker) or thrown_in_right_hand(attacker)) then begin
i+= 0 - (has_trait(TRAIT_PERK, dude_obj, PERK_bonus_hth_attacks) > 0);
end else if (light_melee_in_left_hand(attacker) or light_melee_in_right_hand(attacker)) then begin
i+= 2;
end else if (heavy_melee_in_left_hand(attacker) or heavy_melee_in_right_hand(attacker)) then begin
i+= 1;
end
end if aimed then begin
i+=2+(scoped_rifle_in_left_hand(attacker) or scoped_rifle_in_right_hand(attacker))+(has_trait(TRAIT_TRAIT, attacker, TRAIT_fast_shot) > 0);
end if i > 10 then begin
i := 10;
end if i != -1 then begin
set_sfall_return(i);
end
end
end