Compare commits

...
6 changed files with 74 additions and 6 deletions
+2 -1
View File
@@ -58,7 +58,8 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
| Direct memory access| read_byte,short,int,string<br>write_byte,short,int,string<br>call_offset_vX | đźš« | Not possible. Open an issue if you need functionality not covered by other opcodes. |
| Stats | get/set_pc_base_stat<br>get/set_pc_extra_stat<br>get/set_critter_base_stat<br>get/set_critter_extra_stat | âś… | CE uses engine stat helpers here instead of sfall's direct proto-field behavior, so derived-stat update behavior can differ. |
| Stats / Alter min/max | get/set_stat_min/max<br>set_pc_stat_min/max<br>set_npc_stat_min/max | not implemented | - |
| Skills | get/set_critter_skill_points<br>get/set_available_skill_points<br>set_skill_max<br>set_critter_skill_mod<br>set_base_skill_mod<br>mod_skill_points_per_level | not implemented | - |
| Skills | set_skill_max | âś… | - |
| Skills | get/set_critter_skill_points<br>get/set_available_skill_points<br>set_critter_skill_mod<br>set_base_skill_mod<br>mod_skill_points_per_level | not implemented | - |
| Graphics | graphics_funcs_available<br>force_graphics_refresh<br>get_screen_width<br>get_screen_height<br>set_palette | implemented: only get_screen_width, get_screen_height | - |
| Shaders | load_shader<br>free_shader<br>activate_shader<br>deactivate_shader<br>set/get_shader_* | đźš« | likely will not implement direct compatibility
| Perks and traits | set_perk_image<br>set_perk_*<br>set_pyromaniac_mod<br>apply_heaveho_fix<br>set_swiftlearner_mod<br>has/set_fake_perk<br>has/set_fake_trait<br>set_selectable_perk<br>set_perkbox_title<br>show/hide_real_perks<br>perk_add_mode<br>clear_selectable_perks<br>add/remove_trait<br>seq_perk_freq | not implemented | - |
+38
View File
@@ -0,0 +1,38 @@
#include "define_lite.h"
#include "define_extra.h"
#include "sfall.h"
#include "test_utils.h"
procedure start begin
variable skill_offset;
variable original_points;
variable original_value;
variable capped_points;
if (not game_loaded) then return;
display_msg("Testing set_skill_max...");
test_suite_errors := 0;
skill_offset := PROTO_CR_SKILLS + (SKILL_SMALL_GUNS * 4);
original_points := get_proto_data(obj_pid(dude_obj), skill_offset);
original_value := has_skill(dude_obj, SKILL_SMALL_GUNS);
set_skill_max(300);
critter_mod_skill(dude_obj, SKILL_SMALL_GUNS, 1000);
call assertEquals("skill raised to vanilla cap", has_skill(dude_obj, SKILL_SMALL_GUNS), 300);
capped_points := get_proto_data(obj_pid(dude_obj), skill_offset);
set_skill_max(200);
call assertEquals("existing skill clamped to 200", has_skill(dude_obj, SKILL_SMALL_GUNS), 200);
critter_mod_skill(dude_obj, SKILL_SMALL_GUNS, 1);
call assertEquals("skill points unchanged at cap", get_proto_data(obj_pid(dude_obj), skill_offset), capped_points);
set_skill_max(300);
set_proto_data(obj_pid(dude_obj), skill_offset, original_points);
call assertEquals("original skill restored", has_skill(dude_obj, SKILL_SMALL_GUNS), original_value);
call report_test_results("set_skill_max");
signal_close_game;
end
+10 -1
View File
@@ -802,8 +802,17 @@ static UseItemResultCode _obj_use_book(Object* book)
increase = 150 * increase / 100;
}
bool increased = false;
for (int i = 0; i < increase; i++) {
skillAddForce(gDude, skill);
if (skillAddForce(gDude, skill) != 0) {
break;
}
increased = true;
}
if (!increased) {
messageId = 801;
}
}
+7
View File
@@ -39,6 +39,7 @@
#include "sfall_lists.h"
#include "sfall_metarules.h"
#include "sfall_script_hooks.h"
#include "skill.h"
#include "stat.h"
#include "svga.h"
#include "tile.h"
@@ -160,6 +161,11 @@ static void op_set_critter_extra_stat(Program* program)
critterSetBonusStat(obj, stat, value);
}
static void op_set_skill_max(Program* program)
{
skillSetMaximum(programStackPopInteger(program));
}
// get_pc_base_stat
static void op_get_pc_base_stat(Program* program)
{
@@ -2045,6 +2051,7 @@ void sfallOpcodesInit()
// 0x81a0 - void set_pickpocket_max(int percentage)
// 0x81a1 - void set_hit_chance_max(int percentage)
// 0x81a2 - void set_skill_max(int value)
interpreterRegisterOpcode(0x81A2, op_set_skill_max);
// 0x81aa - void set_xp_mod(int percentage)
// 0x81ab - void set_perk_level_mod(int levels)
+16 -4
View File
@@ -116,6 +116,10 @@ static int _timesSkillUsed[SKILL_COUNT][SKILLS_MAX_USES_PER_DAY];
// 0x668070 tag_skill
static int gTaggedSkills[NUM_TAGGED_SKILLS];
// sfall's set_skill_max limit. Global scripts restore content-specific values
// after every game reset.
static int skillMaximum = 300;
// skill.msg
//
// 0x668080 skill_message_file
@@ -169,6 +173,8 @@ int skillsInit()
// 0x4AA448
void skillsReset()
{
skillMaximum = 300;
for (int index = 0; index < NUM_TAGGED_SKILLS; index++) {
gTaggedSkills[index] = -1;
}
@@ -271,13 +277,19 @@ int skillGetValue(Object* critter, int skill)
value += skillGetGameDifficultyModifier(skill);
}
if (value > 300) {
value = 300;
if (value > skillMaximum) {
value = skillMaximum;
}
return value;
}
void skillSetMaximum(int maximum)
{
// Match sfall: out-of-range values restore the vanilla ceiling.
skillMaximum = maximum >= 0 && maximum <= 300 ? maximum : 300;
}
// 0x4AA654
int skillGetDefaultValue(int skill)
{
@@ -301,7 +313,7 @@ int skillAdd(Object* obj, int skill)
}
int skillValue = skillGetValue(obj, skill);
if (skillValue >= 300) {
if (skillValue >= skillMaximum) {
return -3;
}
@@ -336,7 +348,7 @@ int skillAddForce(Object* obj, int skill)
return -5;
}
if (skillGetValue(obj, skill) >= 300) {
if (skillGetValue(obj, skill) >= skillMaximum) {
return -3;
}
+1
View File
@@ -28,6 +28,7 @@ void skillsSetTagged(int* skills, int count);
void skillsGetTagged(int* skills, int count);
bool skillIsTagged(int skill);
int skillGetValue(Object* critter, int skill);
void skillSetMaximum(int maximum);
int skillGetDefaultValue(int skill);
int skillAdd(Object* critter, int skill);
int skillAddForce(Object* critter, int skill);