Changed string_pos to return -1 on arg error

Added a check to PartyControl::OrderAttackPatch().
Updated function documents.
This commit is contained in:
NovaRain
2023-07-05 22:14:04 +08:00
parent 66559812bd
commit 321f8e1ab2
6 changed files with 34 additions and 23 deletions
+6 -6
View File
@@ -1098,7 +1098,7 @@
detail: string substr(string text, int start, int length)
doc: |
Cuts a substring from a string starting at "start" up to "length" characters. The first character position is 0 (zero).
- If start is negative - it indicates starting position from the end of the string (for example `substr("test", -2, 2)` will return last 2 charactes: "st").
- If start is negative - it indicates a position starting from the end of the string (for example `substr("test", -2, 2)` will return last 2 charactes: "st").
- If length is negative - it means so many characters will be omitted from the end of string (example: `substr("test", 0, -2)` will return string without last 2 characters: "te").
- If length is zero - it will return a string from the starting position to the end of the string. **New behavior** for sfall 4.2.2/3.8.22
opcode: 0x824e
@@ -1117,14 +1117,14 @@
- __NOTE:__ this function is intended for use only in `HOOK_DESCRIPTIONOBJ`. Starting from sfall 4.4/3.8.40, you can return normal strings directly in the hook without calling the function
macro: sfall.h
- name: string_pos
detail: string string_pos(string haystack, string needle)
doc: Returns position of a first occurance of a needle string in a haystack string, or -1 if not found.
detail: int string_pos(string haystack, string needle)
doc: Returns the position of the first occurrence of a `needle` string in a `haystack` string, or -1 if not found. The first character position is 0 (zero).
macro: sfall.h
- name: string_pos_from
detail: string string_pos_from(string haystack, string needle, int pos)
detail: int string_pos_from(string haystack, string needle, int pos)
doc: |
Returns position of a first occurance of a needle string in a haystack string (starting from a given 0-based position), or -1 if not found.
- If pos is negative - it indicates starting position from the end of the string, similar to substr().
Works the same as `string_pos`, except you can specify the position to start the search.
- If `pos` is negative - it indicates a position starting from the end of the string, similar to `substr()`.
macro: sfall.h
- name: string_format
detail: string string_format(string format, any val1, any val2, ...)
+14 -3
View File
@@ -327,11 +327,11 @@ FUNCTION REFERENCE
- You can use this to search for a substring in a string like this: `strlen(get_array(string_split(haystack, needle), 0))`
-----
##### `string substr(string text, start, length)`
##### `string substr(string text, int start, int length)`
- Cuts a substring from a string starting at `start` up to `length` characters. The first character position is 0 (zero).
- If `start` is negative - it indicates starting position from the end of the string (for example, `substr("test", -2, 2)` will return last 2 charactes: "st").
- If `start` is negative - it indicates a position starting from the end of the string (for example, `substr("test", -2, 2)` will return last 2 charactes: "st").
- If `length` is negative - it means so many characters will be omitted from the end of string (example: `substr("test", 0, -2)` will return string without last 2 characters: "te").
- If `length` is zero - it will return a string from the starting position to the end of the string (new behavior for sfall 4.2.2/3.8.22).
- If `length` is zero - it will return a string from the starting position to the end of the string (**new behavior** since sfall 4.2.2/3.8.22).
-----
##### `int strlen(string text)`
@@ -1107,6 +1107,7 @@ sfall_funcX metarule functions
- Allows changing "bonus move" points (yellow lights on the interface bar) that can only be used for movement, not attacking
- Can be called from `HOOK_COMBATTURN` at the start of the turn (will not work on `dude_obj`)
- Can be called from `HOOK_STDPROCEDURE` with `combat_proc` event (will work on both NPCs and `dude_obj`)
----
#### get_ini_config
`array sfall_func2("get_ini_config", string file, bool searchDB)`
@@ -1116,6 +1117,16 @@ sfall_funcX metarule functions
True - searches the file in database (DAT) files. If not found, then it will try the regular file system
- Subsequent calls for the same file will return the same array, unless it was disposed using `free_array`
----
#### string_pos
`int sfall_func2("string_pos", string haystack, string needle)`
`int sfall_func3("string_pos", string haystack, string needle, int pos)`
- Returns the position of the first occurrence of a `needle` string in a `haystack` string, or -1 if not found. The first character position is 0 (zero)
**Optional argument:**
- `pos`: the position at which to start the search. If negative, it indicates a position starting from the end of the string
****
_See other documentation files (arrays.md, hookscripts.md) for related functions reference._
+6 -6
View File
@@ -158,14 +158,14 @@ static void SetStatValue(long* proto, long offset, long amount) {
static void ModifyAllStats(const itProtoMem &mem) {
if (!mem->second.proto && !fo::util::CritterCopyProto(mem->second.pid, mem->second.proto)) return; // proto error
for (auto itBonus = s_bonusStatProto.begin(); itBonus != s_bonusStatProto.end(); itBonus++) {
for (auto itBonus = s_bonusStatProto.begin(); itBonus != s_bonusStatProto.end(); ++itBonus) {
if (itBonus->objID == mem->first && itBonus->objPID == mem->second.pid) {
itBonus->s_proto = mem->second.proto;
SetBonusStatValue(itBonus->s_proto, itBonus->stat, itBonus->amount);
mem->second.sharedCount++;
}
}
for (auto itBase = s_baseStatProto.begin(); itBase != s_baseStatProto.end(); itBase++) {
for (auto itBase = s_baseStatProto.begin(); itBase != s_baseStatProto.end(); ++itBase) {
if (itBase->objID == mem->first && itBase->objPID == mem->second.pid) {
itBase->s_proto = mem->second.proto;
SetBaseStatValue(itBase->s_proto, itBase->stat, itBase->amount);
@@ -189,7 +189,7 @@ static void AddStat(long stat, fo::GameObject* critter, long amount, long* defau
fo::func::dev_printf("[SFALL] Set bonus:%d stat:%d, to NPC pid: %d, saved:%d\n", (offset == OffsetStat::bonus), stat, (critter->protoId & 0xFFFF), isSaved);
offset += stat;
for (auto itStat = vec.begin(); itStat != vec.end(); itStat++) {
for (auto itStat = vec.begin(); itStat != vec.end(); ++itStat) {
if (itStat->objID == critter->id && itStat->objPID == critter->protoId && itStat->stat == stat) {
fo::func::dev_printf("[SFALL] Modify stat value old: %d to new: %d, ID: %d\n", itStat->s_proto[offset], amount, itStat->objID);
if (amount == itStat->defVal) { // set value and value in regular prototype are matched
@@ -222,7 +222,7 @@ static void __fastcall SetStatToProto(long stat, fo::GameObject* critter, long a
}
static void UpdateDefValue(std::vector<StatModify> &vec, long stat, long pid, long amount) {
for (auto itStat = vec.begin(); itStat != vec.end(); itStat++) {
for (auto itStat = vec.begin(); itStat != vec.end(); ++itStat) {
if (itStat->objPID == pid && itStat->stat == stat) {
fo::func::dev_printf("[SFALL] Replace stat default value: %d to: %d, NPC ID: %d\n", itStat->defVal, amount, itStat->objID);
itStat->defVal = amount;
@@ -387,10 +387,10 @@ static void ClearAllStats() {
}
static void FlushAllProtos() {
for (auto itBonus = s_bonusStatProto.begin(); itBonus != s_bonusStatProto.end(); itBonus++) {
for (auto itBonus = s_bonusStatProto.begin(); itBonus != s_bonusStatProto.end(); ++itBonus) {
itBonus->s_proto = nullptr;
}
for (auto itBase = s_baseStatProto.begin(); itBase != s_baseStatProto.end(); itBase++) {
for (auto itBase = s_baseStatProto.begin(); itBase != s_baseStatProto.end(); ++itBase) {
itBase->s_proto = nullptr;
}
for (auto& mem : protoMem) {
+4
View File
@@ -822,6 +822,9 @@ static void __declspec(naked) combat_ai_hook_target() {
}
void PartyControl::OrderAttackPatch() {
static bool orderAttackPatch = false;
if (orderAttackPatch) return;
MakeCall(0x44C4A7, gmouse_handle_event_hack, 2);
HookCall(0x44C75F, gmouse_handle_event_hook);
HookCall(0x44C69A, gmouse_handle_event_hook_restore);
@@ -831,6 +834,7 @@ void PartyControl::OrderAttackPatch() {
LoadGameHook::OnCombatEnd() += []() {
partyOrderAttackTarget.clear();
};
orderAttackPatch = true;
}
static void NpcAutoLevelPatch() {
@@ -160,7 +160,7 @@ static const SfallMetarule metarules[] = {
{"show_window", mf_show_window, 0, 1, -1, {ARG_STRING}},
{"spatial_radius", mf_spatial_radius, 1, 1, 0, {ARG_OBJECT}},
{"string_compare", mf_string_compare, 2, 3, 0, {ARG_STRING, ARG_STRING, ARG_INT}},
{"string_pos", mf_string_pos, 2, 3, 0, {ARG_STRING, ARG_STRING, ARG_INT}},
{"string_pos", mf_string_pos, 2, 3, -1, {ARG_STRING, ARG_STRING, ARG_INT}},
{"string_format", mf_string_format, 2, 8, 0, {ARG_STRING, ARG_ANY, ARG_ANY, ARG_ANY, ARG_ANY, ARG_ANY, ARG_ANY, ARG_ANY}},
{"string_to_case", mf_string_to_case, 2, 2, -1, {ARG_STRING, ARG_INT}},
{"tile_by_position", mf_tile_by_position, 2, 2, -1, {ARG_INT, ARG_INT}},
+3 -7
View File
@@ -200,20 +200,16 @@ void mf_string_compare(OpcodeContext& ctx) {
void mf_string_pos(OpcodeContext& ctx) {
const char* const haystack = ctx.arg(0).strValue();
int pos;
int pos = 0;
if (ctx.numArgs() > 2) {
int len = strlen(haystack);
pos = ctx.arg(2).intValue();
if (pos >= len) {
ctx.setReturn(-1);
return;
} else if (pos < 0) {
pos += len;
}
else if (pos < 0) {
pos = len + pos;
}
}
else {
pos = 0;
}
const char* needle = strstr(haystack + pos, ctx.arg(1).strValue());
ctx.setReturn(