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 "queue.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "scripts.h"
|
#include "scripts.h"
|
||||||
|
#include "sfall_config.h"
|
||||||
#include "skill.h"
|
#include "skill.h"
|
||||||
#include "stat.h"
|
#include "stat.h"
|
||||||
#include "text_font.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 void _draw_loc_(int eventCode, int color);
|
||||||
static int calledShotSelectHitLocation(Object* critter, int* hitLocation, int hitMode);
|
static int calledShotSelectHitLocation(Object* critter, int* hitLocation, int hitMode);
|
||||||
|
|
||||||
|
static void criticalsInit();
|
||||||
|
static void criticalsReset();
|
||||||
|
static void criticalsExit();
|
||||||
|
|
||||||
// 0x500B50
|
// 0x500B50
|
||||||
static char _a_1[] = ".";
|
static char _a_1[] = ".";
|
||||||
|
|
||||||
|
@ -129,7 +134,7 @@ static const int _hit_location_penalty[HIT_LOCATION_COUNT] = {
|
||||||
// Critical hit tables for every kill type.
|
// Critical hit tables for every kill type.
|
||||||
//
|
//
|
||||||
// 0x510978
|
// 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
|
// KILL_TYPE_MAN
|
||||||
{
|
{
|
||||||
// HIT_LOCATION_HEAD
|
// HIT_LOCATION_HEAD
|
||||||
|
@ -1907,6 +1912,19 @@ static Attack _shoot_ctd;
|
||||||
// 0x56D458
|
// 0x56D458
|
||||||
static Attack _explosion_ctd;
|
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
|
// combat_init
|
||||||
// 0x420CC0
|
// 0x420CC0
|
||||||
int combatInit()
|
int combatInit()
|
||||||
|
@ -1945,6 +1963,9 @@ int combatInit()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SFALL
|
||||||
|
criticalsInit();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1970,12 +1991,18 @@ void combatReset()
|
||||||
_combat_ending_guy = NULL;
|
_combat_ending_guy = NULL;
|
||||||
|
|
||||||
gDude->data.critter.combat.ap = max_action_points;
|
gDude->data.critter.combat.ap = max_action_points;
|
||||||
|
|
||||||
|
// SFALL
|
||||||
|
criticalsReset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x420E14
|
// 0x420E14
|
||||||
void combatExit()
|
void combatExit()
|
||||||
{
|
{
|
||||||
messageListFree(&gCombatMessageList);
|
messageListFree(&gCombatMessageList);
|
||||||
|
|
||||||
|
// SFALL
|
||||||
|
criticalsExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x420E24
|
// 0x420E24
|
||||||
|
@ -4023,8 +4050,12 @@ static int attackComputeCriticalFailure(Attack* attack)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attack->attacker == gDude) {
|
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();
|
unsigned int gameTime = gameTimeGetTime();
|
||||||
if (gameTime / GAME_TIME_TICKS_PER_DAY < 6) {
|
if (!criticalsTimeLimitsRemoved && gameTime / GAME_TIME_TICKS_PER_DAY < 6) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5826,3 +5857,263 @@ void _combatKillCritterOutsideCombat(Object* critter_obj, char* msg)
|
||||||
critterKill(critter_obj, -1, 1);
|
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 _combat_delete_critter(Object* obj);
|
||||||
void _combatKillCritterOutsideCombat(Object* critter_obj, char* msg);
|
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()
|
static inline bool isInCombat()
|
||||||
{
|
{
|
||||||
return (gCombatState & COMBAT_STATE_0x01) != 0;
|
return (gCombatState & COMBAT_STATE_0x01) != 0;
|
||||||
|
|
|
@ -121,8 +121,20 @@ typedef struct Attack {
|
||||||
int extrasKnockback[EXPLOSION_TARGET_COUNT];
|
int extrasKnockback[EXPLOSION_TARGET_COUNT];
|
||||||
} Attack;
|
} 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.
|
// Provides metadata about critical hit effect.
|
||||||
typedef struct CriticalHitDescription {
|
typedef union CriticalHitDescription {
|
||||||
|
struct {
|
||||||
int damageMultiplier;
|
int damageMultiplier;
|
||||||
|
|
||||||
// Damage flags that will be applied to defender.
|
// Damage flags that will be applied to defender.
|
||||||
|
@ -140,6 +152,10 @@ typedef struct CriticalHitDescription {
|
||||||
|
|
||||||
int messageId;
|
int messageId;
|
||||||
int massiveCriticalMessageId;
|
int massiveCriticalMessageId;
|
||||||
|
};
|
||||||
|
|
||||||
|
// SFALL: Allow indexed access to the data above.
|
||||||
|
int values[CRIT_DATA_MEMBER_COUNT];
|
||||||
} CriticalHitDescription;
|
} CriticalHitDescription;
|
||||||
|
|
||||||
#endif /* COMBAT_DEFS_H */
|
#endif /* COMBAT_DEFS_H */
|
||||||
|
|
|
@ -122,6 +122,11 @@ enum {
|
||||||
KILL_TYPE_GIANT_ANT,
|
KILL_TYPE_GIANT_ANT,
|
||||||
KILL_TYPE_BIG_BAD_BOSS,
|
KILL_TYPE_BIG_BAD_BOSS,
|
||||||
KILL_TYPE_COUNT,
|
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 {
|
enum {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "platform_compat.h"
|
#include "platform_compat.h"
|
||||||
#include "scripts.h"
|
#include "scripts.h"
|
||||||
|
#include "sfall_config.h"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -97,11 +98,15 @@ static int randomTranslateRoll(int delta, int criticalSuccessModifier)
|
||||||
{
|
{
|
||||||
int gameTime = gameTimeGetTime();
|
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;
|
int roll;
|
||||||
if (delta < 0) {
|
if (delta < 0) {
|
||||||
roll = ROLL_FAILURE;
|
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.
|
// 10% to become critical failure.
|
||||||
if (randomBetween(1, 100) <= -delta / 10) {
|
if (randomBetween(1, 100) <= -delta / 10) {
|
||||||
roll = ROLL_CRITICAL_FAILURE;
|
roll = ROLL_CRITICAL_FAILURE;
|
||||||
|
@ -110,7 +115,7 @@ static int randomTranslateRoll(int delta, int criticalSuccessModifier)
|
||||||
} else {
|
} else {
|
||||||
roll = ROLL_SUCCESS;
|
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.
|
// 10% + modifier to become critical success.
|
||||||
if (randomBetween(1, 100) <= delta / 10 + criticalSuccessModifier) {
|
if (randomBetween(1, 100) <= delta / 10 + criticalSuccessModifier) {
|
||||||
roll = ROLL_CRITICAL_SUCCESS;
|
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);
|
configSetInt(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_SKIP_OPENING_MOVIES_KEY, 0);
|
||||||
configSetString(&gSfallConfig, SFALL_CONFIG_MISC_KEY, SFALL_CONFIG_STARTING_MAP_KEY, "");
|
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_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 path[COMPAT_MAX_PATH];
|
||||||
char* executable = argv[0];
|
char* executable = argv[0];
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
#define SFALL_CONFIG_KARMA_FRMS_KEY "KarmaFRMs"
|
#define SFALL_CONFIG_KARMA_FRMS_KEY "KarmaFRMs"
|
||||||
#define SFALL_CONFIG_KARMA_POINTS_KEY "KarmaPoints"
|
#define SFALL_CONFIG_KARMA_POINTS_KEY "KarmaPoints"
|
||||||
#define SFALL_CONFIG_DISPLAY_KARMA_CHANGES_KEY "DisplayKarmaChanges"
|
#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 bool gSfallConfigInitialized;
|
||||||
extern Config gSfallConfig;
|
extern Config gSfallConfig;
|
||||||
|
|
Loading…
Reference in New Issue