Add damage mod (#29)
This commit is contained in:
parent
5b2a1d13a1
commit
d86a887cf9
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "art.h"
|
#include "art.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
#include "combat.h"
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "critter.h"
|
#include "critter.h"
|
||||||
#include "cycle.h"
|
#include "cycle.h"
|
||||||
|
@ -2801,7 +2802,13 @@ static void characterEditorDrawDerivedStats()
|
||||||
sprintf(t, "%s", messageListItemText);
|
sprintf(t, "%s", messageListItemText);
|
||||||
fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 194, t, 640, 640, color);
|
fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 194, t, 640, 640, color);
|
||||||
|
|
||||||
compat_itoa(critterGetStat(gDude, STAT_MELEE_DAMAGE), t, 10);
|
// SFALL: Display melee damage without "Bonus HtH Damage" bonus.
|
||||||
|
int meleeDamage = critterGetStat(gDude, STAT_MELEE_DAMAGE);
|
||||||
|
if (!damageModGetDisplayBonusDamage()) {
|
||||||
|
meleeDamage -= 2 * perkGetRank(gDude, PERK_BONUS_HTH_DAMAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
compat_itoa(meleeDamage, t, 10);
|
||||||
fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 288, t, 640, 640, color);
|
fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 288, t, 640, 640, color);
|
||||||
|
|
||||||
// Damage Resistance
|
// Damage Resistance
|
||||||
|
@ -4404,13 +4411,19 @@ static int characterPrintToFile(const char* fileName)
|
||||||
fileWriteString(title1, stream);
|
fileWriteString(title1, stream);
|
||||||
fileWriteString("\n", stream);
|
fileWriteString("\n", stream);
|
||||||
|
|
||||||
|
// SFALL: Display melee damage without "Bonus HtH Damage" bonus.
|
||||||
|
int meleeDamage = critterGetStat(gDude, STAT_MELEE_DAMAGE);
|
||||||
|
if (!damageModGetDisplayBonusDamage()) {
|
||||||
|
meleeDamage -= 2 * perkGetRank(gDude, PERK_BONUS_HTH_DAMAGE);
|
||||||
|
}
|
||||||
|
|
||||||
// Charisma / Melee Damage / Carry Weight
|
// Charisma / Melee Damage / Carry Weight
|
||||||
sprintf(title1,
|
sprintf(title1,
|
||||||
"%s %.2d %s %.2d %s %.3d lbs.",
|
"%s %.2d %s %.2d %s %.3d lbs.",
|
||||||
getmsg(&gCharacterEditorMessageList, &gCharacterEditorMessageListItem, 633),
|
getmsg(&gCharacterEditorMessageList, &gCharacterEditorMessageListItem, 633),
|
||||||
critterGetStat(gDude, STAT_CHARISMA),
|
critterGetStat(gDude, STAT_CHARISMA),
|
||||||
getmsg(&gCharacterEditorMessageList, &gCharacterEditorMessageListItem, 634),
|
getmsg(&gCharacterEditorMessageList, &gCharacterEditorMessageListItem, 634),
|
||||||
critterGetStat(gDude, STAT_MELEE_DAMAGE),
|
meleeDamage,
|
||||||
getmsg(&gCharacterEditorMessageList, &gCharacterEditorMessageListItem, 635),
|
getmsg(&gCharacterEditorMessageList, &gCharacterEditorMessageListItem, 635),
|
||||||
critterGetStat(gDude, STAT_CARRY_WEIGHT));
|
critterGetStat(gDude, STAT_CARRY_WEIGHT));
|
||||||
fileWriteString(title1, stream);
|
fileWriteString(title1, stream);
|
||||||
|
|
275
src/combat.cc
275
src/combat.cc
|
@ -47,6 +47,13 @@
|
||||||
#define CALLED_SHOT_WINDOW_WIDTH (504)
|
#define CALLED_SHOT_WINDOW_WIDTH (504)
|
||||||
#define CALLED_SHOT_WINDOW_HEIGHT (309)
|
#define CALLED_SHOT_WINDOW_HEIGHT (309)
|
||||||
|
|
||||||
|
typedef enum DamageCalculationType {
|
||||||
|
DAMAGE_CALCULATION_TYPE_VANILLA = 0,
|
||||||
|
DAMAGE_CALCULATION_TYPE_GLOVZ = 1,
|
||||||
|
DAMAGE_CALCULATION_TYPE_GLOVZ_WITH_DAMAGE_MULTIPLIER_TWEAK = 2,
|
||||||
|
DAMAGE_CALCULATION_TYPE_YAAM = 5,
|
||||||
|
} DamageCalculationType;
|
||||||
|
|
||||||
typedef struct CombatAiInfo {
|
typedef struct CombatAiInfo {
|
||||||
Object* friendlyDead;
|
Object* friendlyDead;
|
||||||
Object* lastTarget;
|
Object* lastTarget;
|
||||||
|
@ -67,6 +74,17 @@ typedef struct UnarmedHitDescription {
|
||||||
bool isSecondary;
|
bool isSecondary;
|
||||||
} UnarmedHitDescription;
|
} UnarmedHitDescription;
|
||||||
|
|
||||||
|
typedef struct DamageCalculationContext {
|
||||||
|
Attack* attack;
|
||||||
|
int* damagePtr;
|
||||||
|
int ammoQuantity;
|
||||||
|
int damageResistance;
|
||||||
|
int damageThreshold;
|
||||||
|
int damageBonus;
|
||||||
|
int bonusDamageMultiplier;
|
||||||
|
int combatDifficultyDamageModifier;
|
||||||
|
} DamageCalculationContext;
|
||||||
|
|
||||||
static bool _combat_safety_invalidate_weapon_func(Object* critter, Object* weapon, int hitMode, Object* a4, int* a5, Object* a6);
|
static bool _combat_safety_invalidate_weapon_func(Object* critter, Object* weapon, int hitMode, Object* a4, int* a5, Object* a6);
|
||||||
static int aiInfoCopy(int srcIndex, int destIndex);
|
static int aiInfoCopy(int srcIndex, int destIndex);
|
||||||
static void _combat_begin(Object* a1);
|
static void _combat_begin(Object* a1);
|
||||||
|
@ -113,6 +131,10 @@ static void unarmedInit();
|
||||||
static void unarmedInitVanilla();
|
static void unarmedInitVanilla();
|
||||||
static void unarmedInitCustom();
|
static void unarmedInitCustom();
|
||||||
static int unarmedGetHitModeInRange(int firstHitMode, int lastHitMode, bool isSecondary);
|
static int unarmedGetHitModeInRange(int firstHitMode, int lastHitMode, bool isSecondary);
|
||||||
|
static void damageModInit();
|
||||||
|
static void damageModCalculateGlovz(DamageCalculationContext* context);
|
||||||
|
static int damageModGlovzDivRound(int dividend, int divisor);
|
||||||
|
static void damageModCalculateYaam(DamageCalculationContext* context);
|
||||||
|
|
||||||
// 0x500B50
|
// 0x500B50
|
||||||
static char _a_1[] = ".";
|
static char _a_1[] = ".";
|
||||||
|
@ -1950,6 +1972,9 @@ static int gBurstModCenterDivisor = SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_DIVISO
|
||||||
static int gBurstModTargetMultiplier = SFALL_CONFIG_BURST_MOD_DEFAULT_TARGET_MULTIPLIER;
|
static int gBurstModTargetMultiplier = SFALL_CONFIG_BURST_MOD_DEFAULT_TARGET_MULTIPLIER;
|
||||||
static int gBurstModTargetDivisor = SFALL_CONFIG_BURST_MOD_DEFAULT_TARGET_DIVISOR;
|
static int gBurstModTargetDivisor = SFALL_CONFIG_BURST_MOD_DEFAULT_TARGET_DIVISOR;
|
||||||
static UnarmedHitDescription gUnarmedHitDescriptions[HIT_MODE_COUNT];
|
static UnarmedHitDescription gUnarmedHitDescriptions[HIT_MODE_COUNT];
|
||||||
|
static int gDamageCalculationType;
|
||||||
|
static bool gBonusHthDamageFix;
|
||||||
|
static bool gDisplayBonusDamage;
|
||||||
|
|
||||||
// combat_init
|
// combat_init
|
||||||
// 0x420CC0
|
// 0x420CC0
|
||||||
|
@ -1993,6 +2018,7 @@ int combatInit()
|
||||||
criticalsInit();
|
criticalsInit();
|
||||||
burstModInit();
|
burstModInit();
|
||||||
unarmedInit();
|
unarmedInit();
|
||||||
|
damageModInit();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -4464,41 +4490,57 @@ static void attackComputeDamage(Attack* attack, int ammoQuantity, int bonusDamag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
damageResistance += weaponGetAmmoDamageResistanceModifier(attack->weapon);
|
// SFALL: Damage mod.
|
||||||
if (damageResistance > 100) {
|
DamageCalculationContext context;
|
||||||
damageResistance = 100;
|
context.attack = attack;
|
||||||
} else if (damageResistance < 0) {
|
context.damagePtr = damagePtr;
|
||||||
damageResistance = 0;
|
context.damageResistance = damageResistance;
|
||||||
}
|
context.damageThreshold = damageThreshold;
|
||||||
|
context.damageBonus = damageBonus;
|
||||||
|
context.bonusDamageMultiplier = bonusDamageMultiplier;
|
||||||
|
context.combatDifficultyDamageModifier = combatDifficultyDamageModifier;
|
||||||
|
|
||||||
int damageMultiplier = bonusDamageMultiplier * weaponGetAmmoDamageMultiplier(attack->weapon);
|
if (gDamageCalculationType == DAMAGE_CALCULATION_TYPE_GLOVZ || gDamageCalculationType == DAMAGE_CALCULATION_TYPE_GLOVZ_WITH_DAMAGE_MULTIPLIER_TWEAK) {
|
||||||
int damageDivisor = weaponGetAmmoDamageDivisor(attack->weapon);
|
damageModCalculateGlovz(&context);
|
||||||
|
} else if (gDamageCalculationType == DAMAGE_CALCULATION_TYPE_YAAM) {
|
||||||
for (int index = 0; index < ammoQuantity; index++) {
|
damageModCalculateYaam(&context);
|
||||||
int damage = weaponGetMeleeDamage(attack->attacker, attack->hitMode);
|
} else {
|
||||||
|
damageResistance += weaponGetAmmoDamageResistanceModifier(attack->weapon);
|
||||||
damage += damageBonus;
|
if (damageResistance > 100) {
|
||||||
|
damageResistance = 100;
|
||||||
damage *= damageMultiplier;
|
} else if (damageResistance < 0) {
|
||||||
|
damageResistance = 0;
|
||||||
if (damageDivisor != 0) {
|
|
||||||
damage /= damageDivisor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Why we're halving it?
|
int damageMultiplier = bonusDamageMultiplier * weaponGetAmmoDamageMultiplier(attack->weapon);
|
||||||
damage /= 2;
|
int damageDivisor = weaponGetAmmoDamageDivisor(attack->weapon);
|
||||||
|
|
||||||
damage *= combatDifficultyDamageModifier;
|
for (int index = 0; index < ammoQuantity; index++) {
|
||||||
damage /= 100;
|
int damage = weaponGetMeleeDamage(attack->attacker, attack->hitMode);
|
||||||
|
|
||||||
damage -= damageThreshold;
|
damage += damageBonus;
|
||||||
|
|
||||||
if (damage > 0) {
|
damage *= damageMultiplier;
|
||||||
damage -= damage * damageResistance / 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (damage > 0) {
|
if (damageDivisor != 0) {
|
||||||
*damagePtr += damage;
|
damage /= damageDivisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Why we're halving it?
|
||||||
|
damage /= 2;
|
||||||
|
|
||||||
|
damage *= combatDifficultyDamageModifier;
|
||||||
|
damage /= 100;
|
||||||
|
|
||||||
|
damage -= damageThreshold;
|
||||||
|
|
||||||
|
if (damage > 0) {
|
||||||
|
damage -= damage * damageResistance / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (damage > 0) {
|
||||||
|
*damagePtr += damage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6508,3 +6550,180 @@ static int unarmedGetHitModeInRange(int firstHitMode, int lastHitMode, bool isSe
|
||||||
|
|
||||||
return hitMode;
|
return hitMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void damageModInit()
|
||||||
|
{
|
||||||
|
gDamageCalculationType = DAMAGE_CALCULATION_TYPE_VANILLA;
|
||||||
|
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DAMAGE_MOD_FORMULA_KEY, &gDamageCalculationType);
|
||||||
|
|
||||||
|
gBonusHthDamageFix = true;
|
||||||
|
configGetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_BONUS_HTH_DAMAGE_FIX_KEY, &gBonusHthDamageFix);
|
||||||
|
|
||||||
|
gDisplayBonusDamage = false;
|
||||||
|
configGetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DISPLAY_BONUS_DAMAGE_KEY, &gDisplayBonusDamage);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool damageModGetBonusHthDamageFix()
|
||||||
|
{
|
||||||
|
return gBonusHthDamageFix;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool damageModGetDisplayBonusDamage()
|
||||||
|
{
|
||||||
|
return gDisplayBonusDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void damageModCalculateGlovz(DamageCalculationContext* context)
|
||||||
|
{
|
||||||
|
int ammoX = weaponGetAmmoDamageMultiplier(context->attack->weapon);
|
||||||
|
if (ammoX <= 0) {
|
||||||
|
ammoX = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ammoY = weaponGetAmmoDamageDivisor(context->attack->weapon);
|
||||||
|
if (ammoY <= 0) {
|
||||||
|
ammoY = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ammoDamageResistance = weaponGetAmmoDamageResistanceModifier(context->attack->weapon);
|
||||||
|
if (ammoDamageResistance > 0) {
|
||||||
|
ammoDamageResistance = -ammoDamageResistance;
|
||||||
|
}
|
||||||
|
|
||||||
|
int calculatedDamageThreshold = context->damageThreshold;
|
||||||
|
if (calculatedDamageThreshold > 0) {
|
||||||
|
calculatedDamageThreshold = damageModGlovzDivRound(calculatedDamageThreshold, ammoY);
|
||||||
|
}
|
||||||
|
|
||||||
|
int calculatedDamageResistance = context->damageResistance;
|
||||||
|
if (calculatedDamageResistance > 0) {
|
||||||
|
if (context->combatDifficultyDamageModifier > 100) {
|
||||||
|
calculatedDamageResistance -= 20;
|
||||||
|
} else if (context->combatDifficultyDamageModifier < 100) {
|
||||||
|
calculatedDamageResistance += 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculatedDamageResistance += ammoDamageResistance;
|
||||||
|
|
||||||
|
calculatedDamageResistance = damageModGlovzDivRound(calculatedDamageResistance, ammoX);
|
||||||
|
|
||||||
|
if (calculatedDamageResistance >= 100) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < context->ammoQuantity; index++) {
|
||||||
|
int damage = weaponGetMeleeDamage(context->attack->attacker, context->attack->hitMode);
|
||||||
|
|
||||||
|
damage += context->damageBonus;
|
||||||
|
if (damage <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->damageThreshold > 0) {
|
||||||
|
damage -= calculatedDamageThreshold;
|
||||||
|
if (damage <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->damageResistance > 0) {
|
||||||
|
damage -= damageModGlovzDivRound(damage * calculatedDamageResistance, 100);
|
||||||
|
if (damage <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context->damageThreshold <= 0 && context->damageResistance <= 0) {
|
||||||
|
if (ammoX > 1 && ammoY > 1) {
|
||||||
|
damage += damageModGlovzDivRound(damage * 15, 100);
|
||||||
|
} else if (ammoX > 1) {
|
||||||
|
damage += damageModGlovzDivRound(damage * 20, 100);
|
||||||
|
} else if (ammoY > 1) {
|
||||||
|
damage += damageModGlovzDivRound(damage * 10, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gDamageCalculationType == DAMAGE_CALCULATION_TYPE_GLOVZ_WITH_DAMAGE_MULTIPLIER_TWEAK) {
|
||||||
|
damage += damageModGlovzDivRound(damage * context->bonusDamageMultiplier * 25, 100);
|
||||||
|
} else {
|
||||||
|
damage += damage * context->bonusDamageMultiplier / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (damage > 0) {
|
||||||
|
*context->damagePtr += damage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int damageModGlovzDivRound(int dividend, int divisor)
|
||||||
|
{
|
||||||
|
if (dividend < divisor) {
|
||||||
|
return dividend != divisor && dividend * 2 <= divisor ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int quotient = dividend / divisor;
|
||||||
|
dividend %= divisor;
|
||||||
|
|
||||||
|
if (dividend == 0) {
|
||||||
|
return quotient;
|
||||||
|
}
|
||||||
|
|
||||||
|
dividend *= 2;
|
||||||
|
|
||||||
|
if (dividend > divisor || (dividend == divisor && (quotient & 1) != 0)) {
|
||||||
|
quotient += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return quotient;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void damageModCalculateYaam(DamageCalculationContext* context)
|
||||||
|
{
|
||||||
|
int damageMultiplier = context->bonusDamageMultiplier * weaponGetAmmoDamageMultiplier(context->attack->weapon);
|
||||||
|
int damageDivisor = weaponGetAmmoDamageDivisor(context->attack->weapon);
|
||||||
|
|
||||||
|
int ammoDamageResistance = weaponGetAmmoDamageResistanceModifier(context->attack->weapon);
|
||||||
|
|
||||||
|
int calculatedDamageThreshold = context->damageThreshold - ammoDamageResistance;
|
||||||
|
int damageResistance = calculatedDamageThreshold;
|
||||||
|
|
||||||
|
if (calculatedDamageThreshold >= 0) {
|
||||||
|
damageResistance = 0;
|
||||||
|
} else {
|
||||||
|
calculatedDamageThreshold = 0;
|
||||||
|
damageResistance *= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
int calculatedDamageResistance = context->damageResistance + damageResistance;
|
||||||
|
if (calculatedDamageResistance < 0) {
|
||||||
|
calculatedDamageResistance = 0;
|
||||||
|
} else if (calculatedDamageResistance >= 100) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 0; index < context->ammoQuantity; index++) {
|
||||||
|
int damage = weaponGetMeleeDamage(context->attack->weapon, context->attack->hitMode);
|
||||||
|
damage += context->damageBonus;
|
||||||
|
|
||||||
|
damage -= calculatedDamageThreshold;
|
||||||
|
if (damage <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
damage *= damageMultiplier;
|
||||||
|
if (damageDivisor != 0) {
|
||||||
|
damage /= damageDivisor;
|
||||||
|
}
|
||||||
|
|
||||||
|
damage /= 2;
|
||||||
|
damage *= context->combatDifficultyDamageModifier;
|
||||||
|
damage /= 100;
|
||||||
|
|
||||||
|
damage -= damage * damageResistance / 100;
|
||||||
|
|
||||||
|
if (damage > 0) {
|
||||||
|
context->damagePtr += damage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -66,6 +66,8 @@ bool unarmedIsPenetrating(int hitMode);
|
||||||
int unarmedGetPunchHitMode(bool isSecondary);
|
int unarmedGetPunchHitMode(bool isSecondary);
|
||||||
int unarmedGetKickHitMode(bool isSecondary);
|
int unarmedGetKickHitMode(bool isSecondary);
|
||||||
bool unarmedIsPenetrating(int hitMode);
|
bool unarmedIsPenetrating(int hitMode);
|
||||||
|
bool damageModGetBonusHthDamageFix();
|
||||||
|
bool damageModGetDisplayBonusDamage();
|
||||||
|
|
||||||
static inline bool isInCombat()
|
static inline bool isInCombat()
|
||||||
{
|
{
|
||||||
|
|
|
@ -2544,6 +2544,11 @@ static void inventoryRenderSummary()
|
||||||
int meleeDamage;
|
int meleeDamage;
|
||||||
if (attackType == ATTACK_TYPE_MELEE || attackType == ATTACK_TYPE_UNARMED) {
|
if (attackType == ATTACK_TYPE_MELEE || attackType == ATTACK_TYPE_UNARMED) {
|
||||||
meleeDamage = critterGetStat(_stack[0], STAT_MELEE_DAMAGE);
|
meleeDamage = critterGetStat(_stack[0], STAT_MELEE_DAMAGE);
|
||||||
|
|
||||||
|
// SFALL: Display melee damage without "Bonus HtH Damage" bonus.
|
||||||
|
if (damageModGetBonusHthDamageFix() && !damageModGetDisplayBonusDamage()) {
|
||||||
|
meleeDamage -= 2 * perkGetRank(gDude, PERK_BONUS_HTH_DAMAGE);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
meleeDamage = 0;
|
meleeDamage = 0;
|
||||||
}
|
}
|
||||||
|
@ -2551,11 +2556,33 @@ static void inventoryRenderSummary()
|
||||||
messageListItem.num = 15; // Dmg:
|
messageListItem.num = 15; // Dmg:
|
||||||
if (messageListGetItem(&gInventoryMessageList, &messageListItem)) {
|
if (messageListGetItem(&gInventoryMessageList, &messageListItem)) {
|
||||||
if (attackType != 4 && range <= 1) {
|
if (attackType != 4 && range <= 1) {
|
||||||
|
// SFALL: Display bonus damage.
|
||||||
|
if (damageModGetBonusHthDamageFix() && damageModGetDisplayBonusDamage()) {
|
||||||
|
// CE: Just in case check for attack type, however it looks
|
||||||
|
// like we cannot be here with anything besides melee or
|
||||||
|
// unarmed.
|
||||||
|
if (_stack[0] == gDude && (attackType == ATTACK_TYPE_MELEE || attackType == ATTACK_TYPE_UNARMED)) {
|
||||||
|
// See explanation in `weaponGetMeleeDamage`.
|
||||||
|
damageMin += 2 * perkGetRank(gDude, PERK_BONUS_HTH_DAMAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
sprintf(formattedText, "%s %d-%d", messageListItem.text, damageMin, damageMax + meleeDamage);
|
sprintf(formattedText, "%s %d-%d", messageListItem.text, damageMin, damageMax + meleeDamage);
|
||||||
} else {
|
} else {
|
||||||
MessageListItem rangeMessageListItem;
|
MessageListItem rangeMessageListItem;
|
||||||
rangeMessageListItem.num = 16; // Rng:
|
rangeMessageListItem.num = 16; // Rng:
|
||||||
if (messageListGetItem(&gInventoryMessageList, &rangeMessageListItem)) {
|
if (messageListGetItem(&gInventoryMessageList, &rangeMessageListItem)) {
|
||||||
|
// SFALL: Display bonus damage.
|
||||||
|
if (damageModGetDisplayBonusDamage()) {
|
||||||
|
// CE: There is a bug in Sfall diplaying wrong damage
|
||||||
|
// bonus for melee weapons with range > 1 (spears,
|
||||||
|
// sledgehammers) and throwables (secondary mode).
|
||||||
|
if (_stack[0] == gDude && attackType == ATTACK_TYPE_RANGED) {
|
||||||
|
int damageBonus = 2 * perkGetRank(gDude, PERK_BONUS_RANGED_DAMAGE);
|
||||||
|
damageMin += damageBonus;
|
||||||
|
damageMax += damageBonus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sprintf(formattedText, "%s %d-%d %s %d", messageListItem.text, damageMin, damageMax + meleeDamage, rangeMessageListItem.text, range);
|
sprintf(formattedText, "%s %d-%d %s %d", messageListItem.text, damageMin, damageMax + meleeDamage, rangeMessageListItem.text, range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
25
src/item.cc
25
src/item.cc
|
@ -1267,20 +1267,35 @@ int weaponGetMeleeDamage(Object* critter, int hitMode)
|
||||||
Object* weapon = critterGetWeaponForHitMode(critter, hitMode);
|
Object* weapon = critterGetWeaponForHitMode(critter, hitMode);
|
||||||
|
|
||||||
if (weapon != NULL) {
|
if (weapon != NULL) {
|
||||||
Proto* proto;
|
// NOTE: Uninline.
|
||||||
protoGetProto(weapon->pid, &proto);
|
weaponGetDamageMinMax(weapon, &minDamage, &maxDamage);
|
||||||
|
|
||||||
minDamage = proto->item.data.weapon.minDamage;
|
|
||||||
maxDamage = proto->item.data.weapon.maxDamage;
|
|
||||||
|
|
||||||
int attackType = weaponGetAttackTypeForHitMode(weapon, hitMode);
|
int attackType = weaponGetAttackTypeForHitMode(weapon, hitMode);
|
||||||
if (attackType == ATTACK_TYPE_MELEE || attackType == ATTACK_TYPE_UNARMED) {
|
if (attackType == ATTACK_TYPE_MELEE || attackType == ATTACK_TYPE_UNARMED) {
|
||||||
meleeDamage = critterGetStat(critter, STAT_MELEE_DAMAGE);
|
meleeDamage = critterGetStat(critter, STAT_MELEE_DAMAGE);
|
||||||
|
|
||||||
|
// SFALL: Bonus HtH Damage fix.
|
||||||
|
if (damageModGetBonusHthDamageFix()) {
|
||||||
|
if (critter == gDude) {
|
||||||
|
// See explanation below.
|
||||||
|
minDamage += 2 * perkGetRank(gDude, PERK_BONUS_HTH_DAMAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// SFALL
|
// SFALL
|
||||||
bonusDamage = unarmedGetDamage(hitMode, &minDamage, &maxDamage);
|
bonusDamage = unarmedGetDamage(hitMode, &minDamage, &maxDamage);
|
||||||
meleeDamage = critterGetStat(critter, STAT_MELEE_DAMAGE);
|
meleeDamage = critterGetStat(critter, STAT_MELEE_DAMAGE);
|
||||||
|
|
||||||
|
// SFALL: Bonus HtH Damage fix.
|
||||||
|
if (damageModGetBonusHthDamageFix()) {
|
||||||
|
if (critter == gDude) {
|
||||||
|
// Increase only min damage. Max damage should not be changed.
|
||||||
|
// It is calculated later by adding `meleeDamage` which already
|
||||||
|
// includes damage bonus (via `perkAddEffect`).
|
||||||
|
minDamage += 2 * perkGetRank(gDude, PERK_BONUS_HTH_DAMAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return randomBetween(bonusDamage + minDamage, bonusDamage + meleeDamage + maxDamage);
|
return randomBetween(bonusDamage + minDamage, bonusDamage + meleeDamage + maxDamage);
|
||||||
|
|
|
@ -42,6 +42,9 @@
|
||||||
#define SFALL_CONFIG_EXPLOSION_EMITS_LIGHT_KEY "ExplosionsEmitLight"
|
#define SFALL_CONFIG_EXPLOSION_EMITS_LIGHT_KEY "ExplosionsEmitLight"
|
||||||
#define SFALL_CONFIG_CITY_REPUTATION_LIST_KEY "CityRepsList"
|
#define SFALL_CONFIG_CITY_REPUTATION_LIST_KEY "CityRepsList"
|
||||||
#define SFALL_CONFIG_UNARMED_FILE_KEY "UnarmedFile"
|
#define SFALL_CONFIG_UNARMED_FILE_KEY "UnarmedFile"
|
||||||
|
#define SFALL_CONFIG_DAMAGE_MOD_FORMULA_KEY "DamageFormula"
|
||||||
|
#define SFALL_CONFIG_BONUS_HTH_DAMAGE_FIX_KEY "BonusHtHDamageFix"
|
||||||
|
#define SFALL_CONFIG_DISPLAY_BONUS_DAMAGE_KEY "DisplayBonusDamage"
|
||||||
|
|
||||||
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_MULTIPLIER 1
|
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_MULTIPLIER 1
|
||||||
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_DIVISOR 3
|
#define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_DIVISOR 3
|
||||||
|
|
Loading…
Reference in New Issue