mirror of
https://github.com/alexbatalov/fallout2-ce.git
synced 2024-09-03 13:29:15 +00:00
Add critical hits improvements (#29)
This commit is contained in:
parent
df5bceaf2a
commit
63bcb2d009
295
src/combat.cc
295
src/combat.cc
@ -31,6 +31,7 @@
|
||||
#include "queue.h"
|
||||
#include "random.h"
|
||||
#include "scripts.h"
|
||||
#include "sfall_config.h"
|
||||
#include "skill.h"
|
||||
#include "stat.h"
|
||||
#include "text_font.h"
|
||||
@ -90,6 +91,10 @@ static void _draw_loc_on_(int a1, int a2);
|
||||
static void _draw_loc_(int eventCode, int color);
|
||||
static int calledShotSelectHitLocation(Object* critter, int* hitLocation, int hitMode);
|
||||
|
||||
static void criticalsInit();
|
||||
static void criticalsReset();
|
||||
static void criticalsExit();
|
||||
|
||||
// 0x500B50
|
||||
static char _a_1[] = ".";
|
||||
|
||||
@ -129,7 +134,7 @@ static const int _hit_location_penalty[HIT_LOCATION_COUNT] = {
|
||||
// Critical hit tables for every kill type.
|
||||
//
|
||||
// 0x510978
|
||||
static CriticalHitDescription gCriticalHitTables[KILL_TYPE_COUNT][HIT_LOCATION_COUNT][CRTICIAL_EFFECT_COUNT] = {
|
||||
static CriticalHitDescription gCriticalHitTables[SFALL_KILL_TYPE_COUNT][HIT_LOCATION_COUNT][CRTICIAL_EFFECT_COUNT] = {
|
||||
// KILL_TYPE_MAN
|
||||
{
|
||||
// HIT_LOCATION_HEAD
|
||||
@ -1907,6 +1912,19 @@ static Attack _shoot_ctd;
|
||||
// 0x56D458
|
||||
static Attack _explosion_ctd;
|
||||
|
||||
static CriticalHitDescription gBaseCriticalHitTables[SFALL_KILL_TYPE_COUNT][HIT_LOCATION_COUNT][CRTICIAL_EFFECT_COUNT];
|
||||
static CriticalHitDescription gBasePlayerCriticalHitTable[HIT_LOCATION_COUNT][CRTICIAL_EFFECT_COUNT];
|
||||
|
||||
static const char* gCritDataMemberKeys[CRIT_DATA_MEMBER_COUNT] = {
|
||||
"DamageMultiplier",
|
||||
"EffectFlags",
|
||||
"StatCheck",
|
||||
"StatMod",
|
||||
"FailureEffect",
|
||||
"Message",
|
||||
"FailMessage",
|
||||
};
|
||||
|
||||
// combat_init
|
||||
// 0x420CC0
|
||||
int combatInit()
|
||||
@ -1945,6 +1963,9 @@ int combatInit()
|
||||
return -1;
|
||||
}
|
||||
|
||||
// SFALL
|
||||
criticalsInit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1970,12 +1991,18 @@ void combatReset()
|
||||
_combat_ending_guy = NULL;
|
||||
|
||||
gDude->data.critter.combat.ap = max_action_points;
|
||||
|
||||
// SFALL
|
||||
criticalsReset();
|
||||
}
|
||||
|
||||
// 0x420E14
|
||||
void combatExit()
|
||||
{
|
||||
messageListFree(&gCombatMessageList);
|
||||
|
||||
// SFALL
|
||||
criticalsExit();
|
||||
}
|
||||
|
||||
// 0x420E24
|
||||
@ -4023,8 +4050,12 @@ static int attackComputeCriticalFailure(Attack* attack)
|
||||
}
|
||||
|
||||
if (attack->attacker == gDude) {
|
||||
// SFALL: Remove criticals time limits.
|
||||
bool criticalsTimeLimitsRemoved = false;
|
||||
configGetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_REMOVE_CRITICALS_TIME_LIMITS_KEY, &criticalsTimeLimitsRemoved);
|
||||
|
||||
unsigned int gameTime = gameTimeGetTime();
|
||||
if (gameTime / GAME_TIME_TICKS_PER_DAY < 6) {
|
||||
if (!criticalsTimeLimitsRemoved && gameTime / GAME_TIME_TICKS_PER_DAY < 6) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -5826,3 +5857,263 @@ void _combatKillCritterOutsideCombat(Object* critter_obj, char* msg)
|
||||
critterKill(critter_obj, -1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void criticalsInit()
|
||||
{
|
||||
int mode = 2;
|
||||
configGetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_OVERRIDE_CRITICALS_MODE_KEY, &mode);
|
||||
if (mode < 0 || mode > 3) {
|
||||
mode = 0;
|
||||
}
|
||||
|
||||
if (mode == 2 || mode == 3) {
|
||||
// Men
|
||||
criticalsSetValue(KILL_TYPE_MAN, HIT_LOCATION_UNCALLED, 2, CRIT_DATA_MEMBER_FLAGS, DAM_KNOCKED_DOWN | DAM_BYPASS);
|
||||
criticalsSetValue(KILL_TYPE_MAN, HIT_LOCATION_UNCALLED, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 5019);
|
||||
|
||||
// Children
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_RIGHT_LEG, 1, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, 0);
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_RIGHT_LEG, 1, CRIT_DATA_MEMBER_MESSAGE_ID, 5216);
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_RIGHT_LEG, 1, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 5000);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_RIGHT_LEG, 2, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, 0);
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_RIGHT_LEG, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 5216);
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_RIGHT_LEG, 2, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 5000);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_LEFT_LEG, 1, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, 0);
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_LEFT_LEG, 1, CRIT_DATA_MEMBER_MESSAGE_ID, 5216);
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_LEFT_LEG, 1, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 5000);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_LEFT_LEG, 2, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, 0);
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_LEFT_LEG, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 5216);
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_LEFT_LEG, 2, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 5000);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_UNCALLED, 1, CRIT_DATA_MEMBER_DAMAGE_MULTIPLIER, 4);
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_UNCALLED, 2, CRIT_DATA_MEMBER_FLAGS, DAM_KNOCKED_DOWN | DAM_BYPASS);
|
||||
criticalsSetValue(KILL_TYPE_CHILD, HIT_LOCATION_UNCALLED, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 5212);
|
||||
|
||||
// Super Mutants
|
||||
criticalsSetValue(KILL_TYPE_SUPER_MUTANT, HIT_LOCATION_LEFT_LEG, 1, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 5306);
|
||||
|
||||
// Ghouls
|
||||
criticalsSetValue(KILL_TYPE_GHOUL, HIT_LOCATION_HEAD, 4, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_STAT, -1);
|
||||
|
||||
// Brahmin
|
||||
criticalsSetValue(KILL_TYPE_BRAHMIN, HIT_LOCATION_HEAD, 4, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_STAT, -1);
|
||||
|
||||
// Radscorpions
|
||||
criticalsSetValue(KILL_TYPE_RADSCORPION, HIT_LOCATION_RIGHT_LEG, 1, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, DAM_KNOCKED_DOWN);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_RADSCORPION, HIT_LOCATION_LEFT_LEG, 1, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, DAM_KNOCKED_DOWN);
|
||||
criticalsSetValue(KILL_TYPE_RADSCORPION, HIT_LOCATION_LEFT_LEG, 2, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 5608);
|
||||
|
||||
// Centaurs
|
||||
criticalsSetValue(KILL_TYPE_CENTAUR, HIT_LOCATION_TORSO, 3, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, DAM_KNOCKED_DOWN);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_CENTAUR, HIT_LOCATION_UNCALLED, 3, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, DAM_KNOCKED_DOWN);
|
||||
|
||||
// Deathclaws
|
||||
criticalsSetValue(KILL_TYPE_DEATH_CLAW, HIT_LOCATION_LEFT_LEG, 1, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, DAM_CRIP_LEG_LEFT);
|
||||
criticalsSetValue(KILL_TYPE_DEATH_CLAW, HIT_LOCATION_LEFT_LEG, 2, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, DAM_CRIP_LEG_LEFT);
|
||||
criticalsSetValue(KILL_TYPE_DEATH_CLAW, HIT_LOCATION_LEFT_LEG, 3, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, DAM_CRIP_LEG_LEFT);
|
||||
criticalsSetValue(KILL_TYPE_DEATH_CLAW, HIT_LOCATION_LEFT_LEG, 4, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, DAM_CRIP_LEG_LEFT);
|
||||
criticalsSetValue(KILL_TYPE_DEATH_CLAW, HIT_LOCATION_LEFT_LEG, 5, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS, DAM_CRIP_LEG_LEFT);
|
||||
|
||||
// Geckos
|
||||
criticalsSetValue(KILL_TYPE_GECKO, HIT_LOCATION_UNCALLED, 0, CRIT_DATA_MEMBER_MESSAGE_ID, 6701);
|
||||
criticalsSetValue(KILL_TYPE_GECKO, HIT_LOCATION_UNCALLED, 1, CRIT_DATA_MEMBER_MESSAGE_ID, 6701);
|
||||
criticalsSetValue(KILL_TYPE_GECKO, HIT_LOCATION_UNCALLED, 2, CRIT_DATA_MEMBER_FLAGS, DAM_KNOCKED_DOWN | DAM_BYPASS);
|
||||
criticalsSetValue(KILL_TYPE_GECKO, HIT_LOCATION_UNCALLED, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 6704);
|
||||
criticalsSetValue(KILL_TYPE_GECKO, HIT_LOCATION_UNCALLED, 3, CRIT_DATA_MEMBER_MESSAGE_ID, 6704);
|
||||
criticalsSetValue(KILL_TYPE_GECKO, HIT_LOCATION_UNCALLED, 4, CRIT_DATA_MEMBER_MESSAGE_ID, 6704);
|
||||
criticalsSetValue(KILL_TYPE_GECKO, HIT_LOCATION_UNCALLED, 5, CRIT_DATA_MEMBER_MESSAGE_ID, 6704);
|
||||
|
||||
// Aliens
|
||||
criticalsSetValue(16, HIT_LOCATION_UNCALLED, 2, CRIT_DATA_MEMBER_FLAGS, DAM_KNOCKED_DOWN | DAM_BYPASS);
|
||||
|
||||
// Giant Ants
|
||||
criticalsSetValue(17, HIT_LOCATION_UNCALLED, 2, CRIT_DATA_MEMBER_FLAGS, DAM_KNOCKED_DOWN | DAM_BYPASS);
|
||||
|
||||
// Big Bad Boss
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_HEAD, 0, CRIT_DATA_MEMBER_MESSAGE_ID, 5001);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_HEAD, 1, CRIT_DATA_MEMBER_MESSAGE_ID, 5001);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_HEAD, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 5001);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_HEAD, 3, CRIT_DATA_MEMBER_MESSAGE_ID, 7105);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_HEAD, 4, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_HEAD, 4, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 7104);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_HEAD, 5, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_ARM, 0, CRIT_DATA_MEMBER_MESSAGE_ID, 5008);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_ARM, 1, CRIT_DATA_MEMBER_MESSAGE_ID, 5008);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_ARM, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 5009);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_ARM, 3, CRIT_DATA_MEMBER_MESSAGE_ID, 5009);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_ARM, 4, CRIT_DATA_MEMBER_MESSAGE_ID, 7102);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_ARM, 5, CRIT_DATA_MEMBER_MESSAGE_ID, 7102);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_ARM, 0, CRIT_DATA_MEMBER_MESSAGE_ID, 5008);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_ARM, 1, CRIT_DATA_MEMBER_MESSAGE_ID, 5008);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_ARM, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 5009);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_ARM, 3, CRIT_DATA_MEMBER_MESSAGE_ID, 5009);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_ARM, 4, CRIT_DATA_MEMBER_MESSAGE_ID, 7102);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_ARM, 5, CRIT_DATA_MEMBER_MESSAGE_ID, 7102);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_TORSO, 4, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_TORSO, 5, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_LEG, 0, CRIT_DATA_MEMBER_MESSAGE_ID, 5023);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_LEG, 1, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_LEG, 1, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 7103);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_LEG, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_LEG, 2, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 7103);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_LEG, 3, CRIT_DATA_MEMBER_MESSAGE_ID, 7103);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_LEG, 4, CRIT_DATA_MEMBER_MESSAGE_ID, 7103);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_RIGHT_LEG, 5, CRIT_DATA_MEMBER_MESSAGE_ID, 7103);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_LEG, 0, CRIT_DATA_MEMBER_MESSAGE_ID, 5023);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_LEG, 1, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_LEG, 1, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 7103);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_LEG, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_LEG, 2, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 7103);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_LEG, 3, CRIT_DATA_MEMBER_MESSAGE_ID, 7103);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_LEG, 4, CRIT_DATA_MEMBER_MESSAGE_ID, 7103);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_LEFT_LEG, 5, CRIT_DATA_MEMBER_MESSAGE_ID, 7103);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_EYES, 0, CRIT_DATA_MEMBER_MESSAGE_ID, 5027);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_EYES, 1, CRIT_DATA_MEMBER_MESSAGE_ID, 5027);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_EYES, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 5027);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_EYES, 3, CRIT_DATA_MEMBER_MESSAGE_ID, 5027);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_EYES, 4, CRIT_DATA_MEMBER_MESSAGE_ID, 7104);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_EYES, 5, CRIT_DATA_MEMBER_MESSAGE_ID, 7104);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_GROIN, 0, CRIT_DATA_MEMBER_MESSAGE_ID, 5033);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_GROIN, 1, CRIT_DATA_MEMBER_MESSAGE_ID, 5027);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_GROIN, 1, CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID, 7101);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_GROIN, 2, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_GROIN, 3, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_GROIN, 4, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_GROIN, 5, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_UNCALLED, 2, CRIT_DATA_MEMBER_DAMAGE_MULTIPLIER, 3);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_UNCALLED, 4, CRIT_DATA_MEMBER_DAMAGE_MULTIPLIER, 4);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_UNCALLED, 4, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
criticalsSetValue(KILL_TYPE_BIG_BAD_BOSS, HIT_LOCATION_UNCALLED, 5, CRIT_DATA_MEMBER_MESSAGE_ID, 7101);
|
||||
}
|
||||
|
||||
if (mode == 1 || mode == 3) {
|
||||
Config criticalsConfig;
|
||||
if (configInit(&criticalsConfig)) {
|
||||
char* criticalsConfigFilePath;
|
||||
configGetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_OVERRIDE_CRITICALS_FILE_KEY, &criticalsConfigFilePath);
|
||||
if (criticalsConfigFilePath != NULL && *criticalsConfigFilePath == '\0') {
|
||||
criticalsConfigFilePath = NULL;
|
||||
}
|
||||
|
||||
if (configRead(&criticalsConfig, criticalsConfigFilePath, false)) {
|
||||
if (mode == 1) {
|
||||
char sectionKey[16];
|
||||
|
||||
// Read original kill types (19) plus one for the player.
|
||||
for (int killType = 0; killType < KILL_TYPE_COUNT + 1; killType++) {
|
||||
for (int hitLocation = 0; hitLocation < HIT_LOCATION_COUNT; hitLocation++) {
|
||||
for (int effect = 0; effect < CRTICIAL_EFFECT_COUNT; effect++) {
|
||||
sprintf_s(sectionKey, "c_%02d_%d_%d", killType, hitLocation, effect);
|
||||
|
||||
// Update player kill type if needed.
|
||||
int newKillType = killType == KILL_TYPE_COUNT ? SFALL_KILL_TYPE_COUNT : killType;
|
||||
for (int dataMember = 0; dataMember < CRIT_DATA_MEMBER_COUNT; dataMember++) {
|
||||
int value = criticalsGetValue(newKillType, hitLocation, effect, dataMember);
|
||||
if (configGetInt(&criticalsConfig, sectionKey, gCritDataMemberKeys[dataMember], &value)) {
|
||||
criticalsSetValue(newKillType, hitLocation, effect, dataMember, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (mode == 3) {
|
||||
char ktSectionKey[32];
|
||||
char hitLocationSectionKey[32];
|
||||
char key[32];
|
||||
|
||||
// Read Sfall kill types (38) plus one for the player.
|
||||
for (int killType = 0; killType < SFALL_KILL_TYPE_COUNT + 1; killType++) {
|
||||
sprintf_s(ktSectionKey, "c_%02d", killType);
|
||||
|
||||
int enabled = 0;
|
||||
configGetInt(&criticalsConfig, ktSectionKey, "Enabled", &enabled);
|
||||
if (enabled == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int hitLocation = 0; hitLocation < HIT_LOCATION_COUNT; hitLocation++) {
|
||||
if (enabled < 2) {
|
||||
bool hitLocationChanged = false;
|
||||
|
||||
sprintf_s(key, "Part_%d", hitLocation);
|
||||
configGetBool(&criticalsConfig, ktSectionKey, key, &hitLocationChanged);
|
||||
|
||||
if (!hitLocationChanged) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf_s(hitLocationSectionKey, "c_%02d_%d", killType, hitLocation);
|
||||
|
||||
for (int effect = 0; effect < CRTICIAL_EFFECT_COUNT; effect++) {
|
||||
for (int dataMember = 0; dataMember < CRIT_DATA_MEMBER_COUNT; dataMember++) {
|
||||
int value = criticalsGetValue(killType, hitLocation, effect, dataMember);
|
||||
sprintf_s(key, "e%d_%s", effect, gCritDataMemberKeys[dataMember]);
|
||||
if (configGetInt(&criticalsConfig, hitLocationSectionKey, key, &value)) {
|
||||
criticalsSetValue(killType, hitLocation, effect, dataMember, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configFree(&criticalsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(gBaseCriticalHitTables, gCriticalHitTables, sizeof(gCriticalHitTables));
|
||||
memcpy(gBasePlayerCriticalHitTable, gPlayerCriticalHitTable, sizeof(gPlayerCriticalHitTable));
|
||||
}
|
||||
|
||||
static void criticalsReset()
|
||||
{
|
||||
memcpy(gCriticalHitTables, gBaseCriticalHitTables, sizeof(gBaseCriticalHitTables));
|
||||
memcpy(gPlayerCriticalHitTable, gBasePlayerCriticalHitTable, sizeof(gBasePlayerCriticalHitTable));
|
||||
}
|
||||
|
||||
static void criticalsExit()
|
||||
{
|
||||
criticalsReset();
|
||||
}
|
||||
|
||||
int criticalsGetValue(int killType, int hitLocation, int effect, int dataMember)
|
||||
{
|
||||
if (killType == SFALL_KILL_TYPE_COUNT) {
|
||||
return gPlayerCriticalHitTable[hitLocation][effect].values[dataMember];
|
||||
} else {
|
||||
return gCriticalHitTables[killType][hitLocation][effect].values[dataMember];
|
||||
}
|
||||
}
|
||||
|
||||
void criticalsSetValue(int killType, int hitLocation, int effect, int dataMember, int value)
|
||||
{
|
||||
if (killType == SFALL_KILL_TYPE_COUNT) {
|
||||
gPlayerCriticalHitTable[hitLocation][effect].values[dataMember] = value;
|
||||
} else {
|
||||
gCriticalHitTables[killType][hitLocation][effect].values[dataMember] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void criticalsResetValue(int killType, int hitLocation, int effect, int dataMember)
|
||||
{
|
||||
if (killType == SFALL_KILL_TYPE_COUNT) {
|
||||
gPlayerCriticalHitTable[hitLocation][effect].values[dataMember] = gBasePlayerCriticalHitTable[hitLocation][effect].values[dataMember];
|
||||
} else {
|
||||
gCriticalHitTables[killType][hitLocation][effect].values[dataMember] = gBaseCriticalHitTables[killType][hitLocation][effect].values[dataMember];
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,10 @@ int _combat_explode_scenery(Object* a1, Object* a2);
|
||||
void _combat_delete_critter(Object* obj);
|
||||
void _combatKillCritterOutsideCombat(Object* critter_obj, char* msg);
|
||||
|
||||
int criticalsGetValue(int killType, int hitLocation, int effect, int dataMember);
|
||||
void criticalsSetValue(int killType, int hitLocation, int effect, int dataMember, int value);
|
||||
void criticalsResetValue(int killType, int hitLocation, int effect, int dataMember);
|
||||
|
||||
static inline bool isInCombat()
|
||||
{
|
||||
return (gCombatState & COMBAT_STATE_0x01) != 0;
|
||||
|
@ -121,25 +121,41 @@ typedef struct Attack {
|
||||
int extrasKnockback[EXPLOSION_TARGET_COUNT];
|
||||
} Attack;
|
||||
|
||||
typedef enum CriticalHitDescriptionDataMember {
|
||||
CRIT_DATA_MEMBER_DAMAGE_MULTIPLIER,
|
||||
CRIT_DATA_MEMBER_FLAGS,
|
||||
CRIT_DATA_MEMBER_MASSIVE_CRITICAL_STAT,
|
||||
CRIT_DATA_MEMBER_MASSIVE_CRITICAL_STAT_MODIFIER,
|
||||
CRIT_DATA_MEMBER_MASSIVE_CRITICAL_FLAGS,
|
||||
CRIT_DATA_MEMBER_MESSAGE_ID,
|
||||
CRIT_DATA_MEMBER_MASSIVE_CRITICAL_MESSAGE_ID,
|
||||
CRIT_DATA_MEMBER_COUNT,
|
||||
} CriticalHitDescriptionDataMember;
|
||||
|
||||
// Provides metadata about critical hit effect.
|
||||
typedef struct CriticalHitDescription {
|
||||
int damageMultiplier;
|
||||
typedef union CriticalHitDescription {
|
||||
struct {
|
||||
int damageMultiplier;
|
||||
|
||||
// Damage flags that will be applied to defender.
|
||||
int flags;
|
||||
// Damage flags that will be applied to defender.
|
||||
int flags;
|
||||
|
||||
// Stat to check to upgrade this critical hit to massive critical hit or
|
||||
// -1 if there is no massive critical hit.
|
||||
int massiveCriticalStat;
|
||||
// Stat to check to upgrade this critical hit to massive critical hit or
|
||||
// -1 if there is no massive critical hit.
|
||||
int massiveCriticalStat;
|
||||
|
||||
// Bonus/penalty to massive critical stat.
|
||||
int massiveCriticalStatModifier;
|
||||
// Bonus/penalty to massive critical stat.
|
||||
int massiveCriticalStatModifier;
|
||||
|
||||
// Additional damage flags if this critical hit become massive critical.
|
||||
int massiveCriticalFlags;
|
||||
// Additional damage flags if this critical hit become massive critical.
|
||||
int massiveCriticalFlags;
|
||||
|
||||
int messageId;
|
||||
int massiveCriticalMessageId;
|
||||
int messageId;
|
||||
int massiveCriticalMessageId;
|
||||
};
|
||||
|
||||
// SFALL: Allow indexed access to the data above.
|
||||
int values[CRIT_DATA_MEMBER_COUNT];
|
||||
} CriticalHitDescription;
|
||||
|
||||
#endif /* COMBAT_DEFS_H */
|
||||
|
@ -122,6 +122,11 @@ enum {
|
||||
KILL_TYPE_GIANT_ANT,
|
||||
KILL_TYPE_BIG_BAD_BOSS,
|
||||
KILL_TYPE_COUNT,
|
||||
|
||||
// Sfall has the option to treat kill type numbers as shorts, thus doubling
|
||||
// number of kill types it can deal with without breaking backwards
|
||||
// compatibility.
|
||||
SFALL_KILL_TYPE_COUNT = KILL_TYPE_COUNT * 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "debug.h"
|
||||
#include "platform_compat.h"
|
||||
#include "scripts.h"
|
||||
#include "sfall_config.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
@ -97,11 +98,15 @@ static int randomTranslateRoll(int delta, int criticalSuccessModifier)
|
||||
{
|
||||
int gameTime = gameTimeGetTime();
|
||||
|
||||
// SFALL: Remove criticals time limits.
|
||||
bool criticalsTimeLimitsRemoved = false;
|
||||
configGetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_REMOVE_CRITICALS_TIME_LIMITS_KEY, &criticalsTimeLimitsRemoved);
|
||||
|
||||
int roll;
|
||||
if (delta < 0) {
|
||||
roll = ROLL_FAILURE;
|
||||
|
||||
if ((gameTime / GAME_TIME_TICKS_PER_DAY) >= 1) {
|
||||
if (criticalsTimeLimitsRemoved || (gameTime / GAME_TIME_TICKS_PER_DAY) >= 1) {
|
||||
// 10% to become critical failure.
|
||||
if (randomBetween(1, 100) <= -delta / 10) {
|
||||
roll = ROLL_CRITICAL_FAILURE;
|
||||
@ -110,7 +115,7 @@ static int randomTranslateRoll(int delta, int criticalSuccessModifier)
|
||||
} else {
|
||||
roll = ROLL_SUCCESS;
|
||||
|
||||
if ((gameTime / GAME_TIME_TICKS_PER_DAY) >= 1) {
|
||||
if (criticalsTimeLimitsRemoved || (gameTime / GAME_TIME_TICKS_PER_DAY) >= 1) {
|
||||
// 10% + modifier to become critical success.
|
||||
if (randomBetween(1, 100) <= delta / 10 + criticalSuccessModifier) {
|
||||
roll = ROLL_CRITICAL_SUCCESS;
|
||||
|
@ -34,6 +34,7 @@ bool sfallConfigInit(int argc, char** argv)
|
||||
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_SKIP_OPENING_MOVIES_KEY, 0);
|
||||
configSetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_STARTING_MAP_KEY, "");
|
||||
configSetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_DISPLAY_KARMA_CHANGES_KEY, false);
|
||||
configSetBool(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_REMOVE_CRITICALS_TIME_LIMITS_KEY, false);
|
||||
|
||||
char path[COMPAT_MAX_PATH];
|
||||
char* executable = argv[0];
|
||||
|
@ -22,6 +22,9 @@
|
||||
#define SFALL_CONFIG_KARMA_FRMS_KEY "KarmaFRMs"
|
||||
#define SFALL_CONFIG_KARMA_POINTS_KEY "KarmaPoints"
|
||||
#define SFALL_CONFIG_DISPLAY_KARMA_CHANGES_KEY "DisplayKarmaChanges"
|
||||
#define SFALL_CONFIG_OVERRIDE_CRITICALS_MODE_KEY "OverrideCriticalTable"
|
||||
#define SFALL_CONFIG_OVERRIDE_CRITICALS_FILE_KEY "OverrideCriticalFile"
|
||||
#define SFALL_CONFIG_REMOVE_CRITICALS_TIME_LIMITS_KEY "RemoveCriticalTimelimits"
|
||||
|
||||
extern bool gSfallConfigInitialized;
|
||||
extern Config gSfallConfig;
|
||||
|
Loading…
Reference in New Issue
Block a user