Added "set_quest_failure_value" script function

This commit is contained in:
NovaRain
2021-03-24 21:22:18 +08:00
parent dc34655981
commit e441d405b5
9 changed files with 125 additions and 63 deletions
+1
View File
@@ -343,6 +343,7 @@
#define set_map_enter_position(tile, elev, rot) sfall_func3("set_map_enter_position", tile, elev, rot) #define set_map_enter_position(tile, elev, rot) sfall_func3("set_map_enter_position", tile, elev, rot)
#define set_object_data(obj, offset, value) sfall_func3("set_object_data", obj, offset, value) #define set_object_data(obj, offset, value) sfall_func3("set_object_data", obj, offset, value)
#define set_outline(obj, color) sfall_func2("set_outline", obj, color) #define set_outline(obj, color) sfall_func2("set_outline", obj, color)
#define set_quest_failure_value(gvar, threshold) sfall_func2("set_quest_failure_value", gvar, threshold)
#define set_terrain_name(x, y, name) sfall_func3("set_terrain_name", x, y, name) #define set_terrain_name(x, y, name) sfall_func3("set_terrain_name", x, y, name)
#define set_town_title(areaID, title) sfall_func2("set_town_title", areaID, title) #define set_town_title(areaID, title) sfall_func2("set_town_title", areaID, title)
#define set_unique_id(obj) sfall_func1("set_unique_id", obj) #define set_unique_id(obj) sfall_func1("set_unique_id", obj)
@@ -737,6 +737,11 @@ optional arguments:
2 - clears the overlay area or the specified rectangle defined by the x, y, width, height arguments 2 - clears the overlay area or the specified rectangle defined by the x, y, width, height arguments
0 - destroys the created overlay surface (frees up the memory allocated to the surface) 0 - destroys the created overlay surface (frees up the memory allocated to the surface)
> void sfall_func2("set_quest_failure_value", int gvarNumber, int thresholdValue)
- sets the threshold value (failure_threshold) for the quest at which the quest will be considered failed (its description in the pipboy will be crossed out and colored red)
- gvarNumber: the number of the global variable controlling the quest
- thresholdValue: the value of the global variable at which the quest is counted as a failure
------------------------ ------------------------
------ MORE INFO ------- ------ MORE INFO -------
------------------------ ------------------------
+1
View File
@@ -238,6 +238,7 @@
#define FO_VAR_ptable 0x59E934 #define FO_VAR_ptable 0x59E934
#define FO_VAR_pud 0x59E960 #define FO_VAR_pud 0x59E960
#define FO_VAR_quest_count 0x51C12C #define FO_VAR_quest_count 0x51C12C
#define FO_VAR_quests 0x51C128
#define FO_VAR_queue 0x6648C0 #define FO_VAR_queue 0x6648C0
#define FO_VAR_quick_done 0x5193BC #define FO_VAR_quick_done 0x5193BC
#define FO_VAR_read_callback 0x51DEEC #define FO_VAR_read_callback 0x51DEEC
+2
View File
@@ -42,6 +42,7 @@
#include "Objects.h" #include "Objects.h"
#include "PartyControl.h" #include "PartyControl.h"
#include "Perks.h" #include "Perks.h"
#include "QuestList.h"
#include "ScriptExtender.h" #include "ScriptExtender.h"
#include "Skills.h" #include "Skills.h"
#include "Sound.h" #include "Sound.h"
@@ -269,6 +270,7 @@ static bool __stdcall GameReset(DWORD isGameLoad) {
Combat_OnGameLoad(); Combat_OnGameLoad();
Skills_OnGameLoad(); Skills_OnGameLoad();
FileSystemReset(); FileSystemReset();
ResetQuests();
WipeSounds(); WipeSounds();
InventoryReset(); InventoryReset();
PartyControl_OnGameLoad(); PartyControl_OnGameLoad();
+67 -24
View File
@@ -338,30 +338,17 @@ skip:
} }
} }
static void RegisterButtonSoundFunc0() { static void RegisterButtonSound() {
__asm { __asm {
mov ebx, gsound_red_butt_release_; mov ebx, gsound_red_butt_release_;
mov edx, gsound_red_butt_press_; mov edx, gsound_red_butt_press_;
call win_register_button_sound_func_; call win_register_button_sound_func_; // eax - register button
} }
} }
static void __stdcall ArtButtonFunc(DWORD buttonKey, DWORD buttonMem, DWORD indexArt) { static void LoadArtButton(DWORD buttonKey, DWORD buttonMem, DWORD indexArt) { // indexArt - index from intrface.lst
__asm { long artId = fo_art_id(OBJ_TYPE_INTRFACE, indexArt, 0, 0, 0);
xor ecx, ecx; *(BYTE**)buttonMem = fo_art_ptr_lock_data(artId, 0, 0, (DWORD*)buttonKey); // first texture memory address
xor ebx, ebx;
mov edx, indexArt; // index from intrface.lst
mov eax, OBJ_TYPE_INTRFACE;
push ecx;
call art_id_;
//
mov ecx, buttonKey;
xor ebx, ebx;
xor edx, edx;
call art_ptr_lock_data_;
mov ecx, buttonMem;
mov dword ptr [ecx], eax; // first texture memory address
}
} }
// Create buttons // Create buttons
@@ -401,11 +388,11 @@ static void __declspec(naked) StartPipboy_hack() {
// Load new texture for first (up) button. I used memory address for texture from buttons at chracter screen. // Load new texture for first (up) button. I used memory address for texture from buttons at chracter screen.
// Everything fine, because this buttons can't use in one time, and they everytime recreating. // Everything fine, because this buttons can't use in one time, and they everytime recreating.
// Down // Down
ArtButtonFunc(FO_VAR_optionsButtonUpKey, FO_VAR_optionsButtonUp, indexUpArt0); LoadArtButton(FO_VAR_optionsButtonUpKey, FO_VAR_optionsButtonUp, indexUpArt0);
ArtButtonFunc(FO_VAR_optionsButtonDownKey, FO_VAR_optionsButtonDown, indexDownArt0); LoadArtButton(FO_VAR_optionsButtonDownKey, FO_VAR_optionsButtonDown, indexDownArt0);
// Up // Up
ArtButtonFunc(FO_VAR_optionsButtonUpKey, FO_VAR_optionsButtonUp1, indexUpArt1); LoadArtButton(FO_VAR_optionsButtonUpKey, FO_VAR_optionsButtonUp1, indexUpArt1);
ArtButtonFunc(FO_VAR_optionsButtonDownKey, FO_VAR_optionsButtonDown1, indexDownArt1); LoadArtButton(FO_VAR_optionsButtonDownKey, FO_VAR_optionsButtonDown1, indexDownArt1);
xPos = questsScrollButtonsX; xPos = questsScrollButtonsX;
yPos = questsScrollButtonsY; yPos = questsScrollButtonsY;
@@ -415,13 +402,13 @@ static void __declspec(naked) StartPipboy_hack() {
picDown = (BYTE*)*ptr_optionsButtonDown1; picDown = (BYTE*)*ptr_optionsButtonDown1;
picUp = (BYTE*)*ptr_optionsButtonUp1; picUp = (BYTE*)*ptr_optionsButtonUp1;
if (fo_win_register_button(winRef, xPos, yPos, width, height, -1, -1, -1, 0x300, picUp, picDown, 0, 32) != -1) { if (fo_win_register_button(winRef, xPos, yPos, width, height, -1, -1, -1, 0x300, picUp, picDown, 0, 32) != -1) {
RegisterButtonSoundFunc0(); RegisterButtonSound();
} }
picDown = (BYTE*)*ptr_optionsButtonDown; picDown = (BYTE*)*ptr_optionsButtonDown;
picUp = (BYTE*)*ptr_optionsButtonUp; picUp = (BYTE*)*ptr_optionsButtonUp;
if (fo_win_register_button(winRef, xPos, yPos + height, width, height, -1, -1, -1, 0x301, picUp, picDown, 0, 32) != -1) { if (fo_win_register_button(winRef, xPos, yPos + height, width, height, -1, -1, -1, 0x301, picUp, picDown, 0, 32) != -1) {
RegisterButtonSoundFunc0(); RegisterButtonSound();
} }
__asm { __asm {
@@ -498,7 +485,63 @@ void QuestListPatch() {
MakeCall(0x497A7D, pip_print_hack); MakeCall(0x497A7D, pip_print_hack);
} }
////////////////////////////////////////////////////////////////////////////////
struct QuestFailure {
long gvarNum;
long failureVal;
};
std::vector<QuestFailure> questFailures;
static long FindGVarQuestFailure(long globalVarNum) {
for (size_t i = 0; i < questFailures.size(); i++) {
if (questFailures[i].gvarNum == globalVarNum) return i;
}
return -1;
}
void __stdcall QuestList_AddQuestFailureValue(long globalVarNum, long failureThreshold) {
long index = FindGVarQuestFailure(globalVarNum);
if (index == -1) {
QuestFailure qf = { globalVarNum, failureThreshold };
questFailures.push_back(qf);
} else {
questFailures[index].failureVal = failureThreshold;
}
}
static BYTE __fastcall CheckQuestFailureState(QuestData* quest, BYTE completeColor) {
if (questFailures.empty()) return completeColor;
const BYTE failureColor = 137; // dark red
long index = FindGVarQuestFailure(quest->gvarIndex);
return (index != -1 && (*ptr_game_global_vars)[quest->gvarIndex] >= questFailures[index].failureVal) ? failureColor : completeColor;
}
static void __declspec(naked) PipStatus_hack() {
__asm {
push eax;
push ecx;
mov dl, ds:[0x6A5B34]; // completeColor (dark green)
mov ecx, ds:[FO_VAR_quests];
add ecx, [esp + 0x4BC - 0x28 + 12];
call CheckQuestFailureState;
mov bl, al;
pop ecx;
pop eax;
retn;
}
}
void ResetQuests() {
questFailures.clear();
}
void QuestList_Init() { void QuestList_Init() {
MakeCall(0x498222, PipStatus_hack, 1);
questsButtonsType = GetConfigInt("Misc", "UseScrollingQuestsList", 0); questsButtonsType = GetConfigInt("Misc", "UseScrollingQuestsList", 0);
if (questsButtonsType > 0) { if (questsButtonsType > 0) {
dlog("Applying quests list patch.", DL_INIT); dlog("Applying quests list patch.", DL_INIT);
+3
View File
@@ -19,3 +19,6 @@
#pragma once #pragma once
void QuestList_Init(); void QuestList_Init();
void ResetQuests();
void __stdcall QuestList_AddQuestFailureValue(long globalVarNum, long failureThreshold);
+1
View File
@@ -599,6 +599,7 @@ static const SfallOpcodeMetadata opcodeMetaArray[] = {
{mf_set_map_enter_position, "set_map_enter_position", {DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {mf_set_map_enter_position, "set_map_enter_position", {DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{mf_set_object_data, "set_object_data", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {mf_set_object_data, "set_object_data", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{mf_set_outline, "set_outline", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, {mf_set_outline, "set_outline", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
{mf_set_quest_failure_value, "set_quest_failure_value", {DATATYPE_MASK_INT, DATATYPE_MASK_INT}},
{mf_set_terrain_name, "set_terrain_name", {DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_STR}}, {mf_set_terrain_name, "set_terrain_name", {DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_STR}},
{mf_set_town_title, "set_town_title", {DATATYPE_MASK_INT, DATATYPE_MASK_STR}}, {mf_set_town_title, "set_town_title", {DATATYPE_MASK_INT, DATATYPE_MASK_STR}},
{mf_set_unique_id, "set_unique_id", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, {mf_set_unique_id, "set_unique_id", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}},
+1
View File
@@ -174,6 +174,7 @@ static const SfallMetarule metaruleArray[] = {
{"set_map_enter_position", mf_set_map_enter_position, 3, 3}, {"set_map_enter_position", mf_set_map_enter_position, 3, 3},
{"set_object_data", mf_set_object_data, 3, 3}, {"set_object_data", mf_set_object_data, 3, 3},
{"set_outline", mf_set_outline, 2, 2}, {"set_outline", mf_set_outline, 2, 2},
{"set_quest_failure_value", mf_set_quest_failure_value, 2, 2},
{"set_terrain_name", mf_set_terrain_name, 3, 3}, {"set_terrain_name", mf_set_terrain_name, 3, 3},
{"set_town_title", mf_set_town_title, 2, 2}, {"set_town_title", mf_set_town_title, 2, 2},
{"set_unique_id", mf_set_unique_id, 1, 2}, {"set_unique_id", mf_set_unique_id, 1, 2},
+5
View File
@@ -26,6 +26,7 @@
#include "HeroAppearance.h" #include "HeroAppearance.h"
#include "Movies.h" #include "Movies.h"
#include "PlayerModel.h" #include "PlayerModel.h"
#include "QuestList.h"
#include "ScriptExtender.h" #include "ScriptExtender.h"
#include "Sound.h" #include "Sound.h"
@@ -673,3 +674,7 @@ static void mf_get_ini_section() {
} }
opHandler.setReturn(arrayId); opHandler.setReturn(arrayId);
} }
static void mf_set_quest_failure_value() {
QuestList_AddQuestFailureValue(opHandler.arg(0).rawValue(), opHandler.arg(1).rawValue());
}