summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mailmap8
-rw-r--r--AUTHORS218
-rw-r--r--conf/common/inter-server.conf4
-rw-r--r--conf/map/script.conf10
-rw-r--r--doc/constants.md1
-rw-r--r--doc/mob_skill_db.md1
-rw-r--r--doc/script_commands.txt89
-rw-r--r--npc/dev/test.txt40
-rw-r--r--npc/re/quests/quests_brasilis.txt6
-rw-r--r--sql-files/main.sql22
-rw-r--r--sql-files/upgrades/2020-05-10--23-11.sql43
-rw-r--r--sql-files/upgrades/index.txt1
-rw-r--r--src/map/battle.c12
-rw-r--r--src/map/chrif.c2
-rw-r--r--src/map/clif.c19
-rw-r--r--src/map/guild.c4
-rw-r--r--src/map/map.c9
-rw-r--r--src/map/map.h8
-rw-r--r--src/map/mapreg.h67
-rw-r--r--src/map/mapreg_sql.c816
-rw-r--r--src/map/mob.c4
-rw-r--r--src/map/mob.h1
-rw-r--r--src/map/npc.c13
-rw-r--r--src/map/npc.h6
-rw-r--r--src/map/pc.h4
-rw-r--r--src/map/script.c554
-rw-r--r--src/map/script.h21
-rw-r--r--src/map/skill.c21
-rw-r--r--src/map/skill.h2
-rw-r--r--src/map/status.c37
-rw-r--r--src/map/status.h4
-rw-r--r--src/plugins/HPMHooking/HPMHooking.Defs.inc42
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc60
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc15
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc395
-rwxr-xr-xtools/authors.sh4
36 files changed, 1906 insertions, 657 deletions
diff --git a/.mailmap b/.mailmap
index 4a9b49d2d..111831380 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1,3 +1,11 @@
+# hercules aliases
+
+Jenkijo <jenkijo@hrzn.community> <phongtruongit@gmail.com>
+Kenpachi <Kenpachi.Developer@gmx.de> kenpachi2k11 <Kenpachi.Developer@gmx.de>
+Kenpachi <Kenpachi.Developer@gmx.de> Kenpachi2k13 <3476227+Kenpachi2k13@users.noreply.github.com>
+Kenpachi <Kenpachi.Developer@gmx.de> Kenpachi2k13 <Kenpachi.Developer@gmx.de>
+Kenpachi <Kenpachi.Developer@gmx.de> Kenpachi Developer <Kenpachi.Developer@gmx.de>
+
# SVN -> git mailmap
<kisuka@kisuka.com> <Kisuka@54d463be-8e91-2dee-dedb-b68131a5f0ec>
diff --git a/AUTHORS b/AUTHORS
index 73fbbaa27..f6b65eaba 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,3 +1,221 @@
+Hercules/RAthena contributors/developers
+
+ai4rei <ai4rei@users.noreply.github.com>
+Akkarinage <mike.langford@live.co.uk>
+akrus <akrus@flygroup.st>
+akshat157 <ancientfuture1337@gmail.com>
+Alexander Kozlov <landergate@landergate.com>
+Alige <gauvain.dauchy@free.fr>
+Amir El Sayed <aes@basecom.de>
+Ancyker <ancyker@gmail.com>
+Andrei Karas <akaras@inbox.ru>
+Angelmelody <Angelmelody@gmail.com>
+Angelmelody <cutepeipei@hotmail.com.tw>
+AnnieRuru <jeankofannie2@gmail.com>
+AnnieRuru <jeankof@ymail.com>
+Asheraf <Asheraf@users.noreply.github.com>
+Atemo <capucrath@gmail.com>
+AtlantisRO <atlas@atlantis-ro.net>
+BinaryCrochet <43975470+BinaryCrochet@users.noreply.github.com>
+blacksirius <fw@f-ws.de>
+brianluau <brianluau@users.noreply.github.com>
+CairoLee <cairoliyu@gmail.com>
+calciumkid <harrison@isabarwon.com>
+cannelle <cannelle@users.noreply.github.com>
+cannelle <starfish2700@gmail.com>
+Carlos Henrique <carloshlfzanon@gmail.com>
+Christian <txandy@gmail.com>
+csnv <ctt@csnv.es>
+daegaladh <Daegaladh@users.noreply.github.com>
+Darren <darrensapalo@users.noreply.github.com>
+dastgir <dastgirp@gmail.com>
+Dastgir <dastgirp@gmail.com>
+dastgirpojee <dastgirp@gmail.com>
+Dastgir Pojee <dastgirp@gmail.com>
+Earisu <bruant.bastien@gmail.com>
+Edwin <edwin@yohanesedwin.com>
+Emistry <equinox1991@gmail.com>
+Emistry <Equinox1991@gmail.com>
+Emistry Haoyan <equinox1991@gmail.com>
+Emistry Haoyan <Equinox1991@gmail.com>
+epuncker <gm.perflex@gmail.com>
+EPuncker <gm.perflex@gmail.com>
+Er_Maqui <er_maqui@darkbolt.net>
+Euphy <euphy@rathena.org>
+euphyy <euphy@rathena.org>
+Evil Puncker <gm.perflex@gmail.com>
+EyesOfAHawk <blackoutro2006@gmail.com>
+Fisune <fisuned@gmail.com>
+flaviojs2005 <flaviojs2005@gmail.com>
+flaviojs <flaviojs2005@gmail.com>
+FlavioJS <flaviojs2005@gmail.com>
+Flipp <mysteriousragnarok@hotmail.com>
+Florian Wilkemeyer <fw@f-ws.de>
+FreddieFatso <slg@xyz.de>
+Frost <jedzkie13@rocketmail.com>
+Gabriel Mejia <elgartoinf@gmail.com>
+GammCrucis <HaxD64@live.ca>
+Gde Mahardhikha Satrigraha <gde.satrigraha@gmail.com>
+Geniks <geniks34@gmail.com>
+gepard1984 <piotr.halaczkiewicz@gmail.com>
+Gepard <piotr.halaczkiewicz@gmail.com>
+glighta <lightaisme@gmail.com>
+GmOcean <hyperassassin@gmail.com>
+greenboxal2 <greenboxal@gmail.com>
+GrumpyLittlePanda <samuli.vaara@yahoo.com>
+Guilherme G. Menaldo <guilherme.menaldo@outlook.com>
+Guilherme G. M <guilherme.menaldo@outlook.com>
+Guilherme Guiguer Menaldo <guilherme.menaldo@outlook.com>
+Guilherme <guilherme_mith@hotmail.com>
+Guilherme Menaldo <guilherme.menaldo@outlook.com>
+gumi <git@gumi.ca>
+Habilya <ciuvilin.co@gmail.com>
+Habilya <hercuser@prdcrazyserver>
+Happy <markaizer@gmail.com>
+Haru <haru@dotalux.com>
+Haruna <haru@dotalux.com>
+hemagx <ibrahem.h.basyone@gmail.com>
+HerculesUser <Hercules@mail.com>
+Hercules.ws <dev@herc.ws>
+Ibrahem Hossam <ibrahem.h.basyone@gmail.com>
+Ibrahem Zidan <brahem@aotsw.com>
+Ibrahim Hossam <ibrahem.h.basyone@gmail.com>
+Ibrahim Zidan <brahem@aotsw.com>
+inhyositsu <inhyositsu@gmail.com>
+Inzianity <inzianity@gmail.com>
+jaBote <jaBote@fake-emails-rock.com>
+jaBote <jaBote@users.noreply.github.com>
+jaBote <javote91@hotmail.com>
+jaBote <j@bot.e>
+Jackson <chadfield.jackson@gmail.com>
+Jedzkie <jedzkie13@rocketmail.com>
+Jenkijo <jenkijo@hrzn.community>
+jmanfffreak <jmish1987@gmail.com>
+Jônatas Andreta <jonataandretta@hotmail.com>
+Jorge C <ctt@csnv.es>
+Jose Luis Rivera Flores <jose-pro_h4kr@hotmail.com>
+j-tkay <joseph.tk.ea@gmail.com>
+Kenpachi <Kenpachi.Developer@gmx.de>
+Kerubael <keru@ro-mina.net>
+KirieZ <guilherme_kiriez@hotmail.com>
+KirieZ <guilherme.menaldo@outlook.com>
+kisuka <kisuka@kisuka.com>
+Kisuka <kisuka@kisuka.com>
+Kolkka <lmiranda@lumigo.net>
+Kpy! <ouroboros.ai@gmail.com>
+landergate <landergate@landergate.com>
+lemongrass3110 <lemongrass@kstp.at>
+Lemongrass3110 <lemongrass@kstp.at>
+Leo Pflug <skyleo@skyleo.de>
+linton-dawson <pushkarkukde@gmail.com>
+LiYu <cairoliyu@gmail.com>
+louisplag <42522191+louisplag@users.noreply.github.com>
+Lucas Brito <lucasljsb@gmail.com>
+M45T3Ryu <jose-pro_h4kr@hotmail.com>
+malufett <malufett.eat.my.binaries@gmail.com>
+maqc1 <alex--223@hotmail.com>
+Marcelo Liberato <marceloll@outlook.com>
+Mark Hester <Marky360@live.ie>
+marky291 <Marky360@live.ie>
+Marvin Lamart <m.lamart@agence-passerelle.com>
+masao87 <masao@gmx.ch>
+Masao87 <masao@gmx.ch>
+Masao <masao@gmx.ch>
+MasterOfMuppets <masterofmuppets89@gmail.com>
+Matej Pristak <matej.pristak@gmail.com>
+Matheus Macabu <mkbu95@gmail.com>
+Mathy <MathyM@users.noreply.github.com>
+Matias <matiassw@gmail.com>
+Maytichai Saowa <nightcoremax@gmail.com>
+mekolat <git@gumi.ca>
+Mhalicot <sevenzz23@yahoo.com>
+michaelforge <landergate@landergate.com>
+michieru <michieru-kun@hotmail.com>
+Michieru <michieru-kun@hotmail.com>
+Milchdealer <jocker300@hotmail.de>
+Milk <welcomerooot@gmail.com>
+milky-milk <welcomerooot@gmail.com>
+Miniack <Redemer_Braulio@hotmail.com>
+moguri85 <ikke85@gmail.com>
+momacabu <macabu.matheus@gmail.com>
+MordekaiserGod <mordekaiser@iwillgetaproperemail.com>
+MrKeiKun <the.keikun@gmail.com>
+Mr.Postman <MrPostman@windowslive.com>
+Mumbles <datmumbles@icloud.com>
+Mumbles <icelestial@outlook.com>
+Mumbles <mumbles@qt-ro.com>
+Mumbles <mumbles@rhythm.ro>
+Murilo_Bio <murilopereti@gmail.com>
+Murilo Pereti Tavares <murilopereti@gmail.com>
+Mysteries <mysteriousragnarok@hotmail.com>
+Mysterious <mysteriousragnarok@hotmail.com>
+nadiyama <ctt@csnv.es>
+nadiyama <jorgecsnova@gmail.com>
+Nihadm89 <nihadm89@hotmail.com>
+Noil <senpainoil@gmail.com>
+Normynator <Norman.Ziebal@web.de>
+ossi0110 <asmodus1@web.de>
+ossi0110 <maikkempkes@alice.de>
+panikon <panikon@zoho.com>
+Paradox924x <paradox924x@gmail.com>
+Paradox924X <paradox924x@gmail.com>
+Patskie <escalona3413@gmail.com>
+Piotr Hałaczkiewicz <piotr.halaczkiewicz@gmail.com>
+playtester <Kenji.Ito@gmx.de>
+Playtester <Kenji.Ito@gmx.de>
+Poison <poison.lethaliagaming@gmail.com>
+Potte <the.keikun@gmail.com>
+Ragno <gerquicira@hotmail.com>
+Rajat Verma <verma.rajatk@gmail.com>
+Reid <reidyaro@gmail.com>
+Ridley8819 <ridley8819@gmail.com>
+Ridley <ridley8819@gmail.com>
+Robbie <crgarvey@gmail.com>
+rud0lp20 <malufett.eat.my.binaries@gmail.com>
+sagunkho <sagunkho@hotmail.com>
+SagunKho <sagunkho@hotmail.com>
+SamuelHercules <exhilaratero@gmail.com>
+seifert10 <luis.seifert@gmail.com>
+sevenzz23 <sevenzz23@yahoo.com>
+Shaktoh <shakto@hotmail.fr>
+shenhuyong <shenhuyong@hotmail.com>
+shennetsind <ind@henn.et>
+Shido <the.keikun@gmail.com>
+Shizuke <matiasdvt@hotmail.com>
+sigtus <vantimothy@openmailbox.org>
+sirius <fw@f-ws.de>
+Sirius <zopokx@gmail.com>
+skyleo <leo-pflug@web.de>
+skyleo <skyleo@skyleo.de>
+smokexyz <sagunkho@hotmail.com>
+Smokexyz <sagunkho@hotmail.com>
+Streusel <streusel@gravity.co.kr>
+Susu <bruant.bastien@gmail.com>
+Susu <susu-@live.fr>
+Taylor Locke <kisuka@kisuka.com>
+TeMPlatonic <gerquicira@hotmail.com>
+themon <themon1666@gmail.com>
+Thibault Payet <monwarez@gmail.com>
+trojal <trojal@gmail.com>
+Trojal <trojal@gmail.com>
+tungsinpei <sinpeiton@hotmail.com>
+TungSinpei <TungSinpei@hotmail.com>
+ultramage <umage@netvor.sk>
+Unknown <nightcoremax@gmail.com>
+Victor <victor.lombardi@insa-rouen.fr>
+Vincent Thibault <vthibault.mobile@gmail.com>
+Wolf <vitinho.senos@live.com>
+xantara <missxantara@gmail.com>
+Xantara <missxantara@gmail.com>
+Xavier RENE-CORAIL <xavier.renecorail@gmail.com>
+Yommy <yomanda@gmail.com>
+Your Name <ibrahem.h.basyone@gmail.com>
+zackdreaver <zackdreaver@gmail.com>
+Zarbony <justonlinegames@web.de>
+
+
+
+
The following people & communities have contributed to the development of Athena through the years.
Thank you for all your hard work.
diff --git a/conf/common/inter-server.conf b/conf/common/inter-server.conf
index 7696774d6..9960c46d6 100644
--- a/conf/common/inter-server.conf
+++ b/conf/common/inter-server.conf
@@ -76,9 +76,10 @@ inter_configuration: {
acc_reg_str_db: "acc_reg_str_db"
char_reg_str_db: "char_reg_str_db"
char_reg_num_db: "char_reg_num_db"
-
global_acc_reg_num_db: "global_acc_reg_num_db"
global_acc_reg_str_db: "global_acc_reg_str_db"
+ map_reg_num_db: "map_reg_num_db"
+ map_reg_str_db: "map_reg_str_db"
}
pc: {
hotkey_db: "hotkey"
@@ -113,7 +114,6 @@ inter_configuration: {
position_db: "guild_position"
storage_db: "guild_storage"
}
- mapreg_db: "mapreg"
autotrade_merchants_db: "autotrade_merchants"
autotrade_data_db: "autotrade_data"
npc_market_data_db: "npc_market_data"
diff --git a/conf/map/script.conf b/conf/map/script.conf
index fc4f26965..4eb84edf4 100644
--- a/conf/map/script.conf
+++ b/conf/map/script.conf
@@ -59,6 +59,16 @@ script_configuration: {
// Defaults to INT_MAX.
//input_max_value: 2147483647
input_max_value: 10000000
+
+ // Specifies whether functions not explicitly marked with a "private" or
+ // "public" keyword should be treated as "private" by default.
+ // Default: true
+ functions_private_by_default: true
+
+ // Specifies whether public functions can be invoked as NPC events. This
+ // allows, for example, to use a `public function OnDeath { ... }` instead
+ // of a `OnDeath:` label for mob death events.
+ functions_as_events: false
}
import: "conf/import/script.conf"
diff --git a/doc/constants.md b/doc/constants.md
index 09ff61381..5feb3736d 100644
--- a/doc/constants.md
+++ b/doc/constants.md
@@ -5095,6 +5095,7 @@
- `MSC_MASTERATTACKED`: 20
- `MSC_ALCHEMIST`: 21
- `MSC_SPAWN`: 22
+- `MSC_MAGICATTACKED`: 23
### monster skill targets
diff --git a/doc/mob_skill_db.md b/doc/mob_skill_db.md
index 12d3649de..8198446d3 100644
--- a/doc/mob_skill_db.md
+++ b/doc/mob_skill_db.md
@@ -175,6 +175,7 @@ MSC_MASTERHPLTMAXRATE | The monster master's HP in percent is less than `Conditi
MSC_MASTERATTACKED | The monster's master is attacked.
MSC_ALCHEMIST | The monster was summoned by an Alchemist class character.
MSC_SPAWN | The monster spawns.
+MSC_MAGICATTACKED | The monster has received magic damage.
### ConditionData
Additional cast condition data. Meaning depends on the situation. See `CastCondition` table.
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index 3c0b37a85..a597dfaa2 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -1945,58 +1945,64 @@ will result in error and termination of the script.
---------------------------------------
-*function <function name>;
-*<function name>{(<argument>, ...<argument>)};
-*function <function name> {
+{public | private} *function <function name>;
+{public | private} *function <function name> {
<code>
}
-This works like callfunc(), and is used for cleaner and faster scripting.
-The function must be defined and used within a script, and works like a
-label with arguments.
-Note that the name may only contain alphanumeric characters and underscore.
+In its first form, this syntax declares a local function so it can later be
+defined. In its second form, the syntax both declares and defines a local
+function. Local functions must be defined before being used. Note that the name
+may only contain alphanumeric characters and underscore. Once defined, they can
+be called from the current script as if they were regular built-in commands, and
+can also be called from other scripts if they are marked as public. Local
+functions may be marked as public by simply adding "public" prior to the
+function definition. Functions not marked as public are private by default and
+cannot be called from another script.
Usage:
1. Declare the function.
function <function name>;
2. Call the function anywhere within the script.
- It can also return a value when used with parentheses.
- <function name>;
- 3. Define the function within the script.
+ <function name>();
+ 3. Define the function by adding its script.
<function name> {<code>}
+ Step 1 is optional if the function is defined prior to being called.
+
Example:
-prontera,154,189,4 script Item Seller 767,{
/* Function declaration */
- function SF_Selling;
+ function MyFunction;
- if (Zeny > 50) {
- mes("Welcome!");
- /* Function call */
- SF_Selling();
- } else {
- mes("You need 50z, sorry!");
- }
- close();
+ /* Function call */
+ MyFunction();
/* Function definition */
- function SF_Selling {
- mes("Would you like to buy a phracon for 50z?");
- next();
- if (select("Yes", "No, thanks") == 1) {
- Zeny -= 50;
- getitem(Phracon, 1);
- mes("Thank you!");
- }
+ function MyFunction {
+ // (do something)
return;
}
-}
+
+
+Example with public functions:
+
+ /* Function declaration + definition */
+ public function myFunction {
+ /* notice the "public" before the "function" keyword */
+ return;
+ }
+
+ /* Local call */
+ myFunction();
+
+ /* Call from another script */
+ "npc name"::myFunction();
+
Example with parameters and return value:
-prontera,150,150,0 script TestNPC 123,{
/* Function declaration */
function MyAdd;
@@ -2005,18 +2011,35 @@ prontera,150,150,0 script TestNPC 123,{
input(.@a);
input(.@b);
/* Function call */
- mes(.@a+" + "+.@b+" = "+MyAdd(.@a, .@b));
+ mesf("%i + %i = %i", .@a, .@b, MyAdd(.@a, .@b));
close();
/* Function definition */
function MyAdd {
- return(getarg(0)+getarg(1));
+ return (getarg(0) + getarg(1));
}
-}
---------------------------------------
+*<function name>({<arg>...})
+*"<npc name>"::<function name>({<arg>...})
+*callfunctionofnpc("<function name>", "<npc name>"{, <arg>...});
+
+In its first form, calls a previously defined local function. In its second
+form, calls a previously defined public local function of another NPC. If the
+name of the target NPC or the name of the local function is not known
+beforehand, callfunctionofnpc() can be used instead of the second form.
+See function() above for more details.
+
+Example:
+
+ MyFunction(arg1, arg2, arg3);
+ "MyNPC"::MyFunction(arg1, arg2, arg3);
+ callfunctionofnpc("MyNPC", "MyFunction", arg1, arg2, arg3);
+
+---------------------------------------
+
*is_function("<function name>")
This command checks whether or not a function exists and returns its type.
diff --git a/npc/dev/test.txt b/npc/dev/test.txt
index a9e78489a..c8c842055 100644
--- a/npc/dev/test.txt
+++ b/npc/dev/test.txt
@@ -116,6 +116,40 @@ function script F_TestVarOfAnotherNPC {
end;
}
+- script export test FAKE_NPC,{
+
+ function OnInit {
+ // functions labels should not be able to be called as events
+ // if a regression occurs, this function could end up being called when
+ // Hercules processes OnInit event calls (issue #2137)
+
+ // NOTE: If script_config.functions_as_events is enabled (defaults: off)
+ // and this this function is marked as public, it will trigger the
+ // warning and fail the unit test regardless.
+
+ $@something_bad_happened[0] = true;
+ end;
+ }
+
+ private function Private {
+ // function explicitly marked as private
+ return;
+ }
+
+ public function Public {
+ // this is for testing public local functions and ownership of the
+ // script
+
+ return getnpcid();
+ }
+
+ public function RefTest {
+ // this is to check if references are passed around properly
+
+ return set(getarg(0), 1337);
+ }
+}
+
function script HerculesSelfTestHelper {
if (.once > 0)
return .errors;
@@ -785,6 +819,12 @@ function script HerculesSelfTestHelper {
callsub(OnCheck, "data_to_string (string variable)", data_to_string(.@x$), ".@x$");
callsub(OnCheck, "data_to_string (integer variable)", data_to_string(.@x), ".@x");
+ "export test"::RefTest(.@refTest = 69);
+ callsub(OnCheck, "function as event (regression)", $@something_bad_happened[0], false);
+ callsub(OnCheck, "public local function ownership", "export test"::Public(), getnpcid());
+ callsub(OnCheck, "public local function var reference test", .@refTest, 1337);
+ callsub(OnCheck, "programatic public local call", callfunctionofnpc("export test", "RefTest", .@refTest = 1), 1337);
+
if (.errors) {
consolemes(CONSOLEMES_DEBUG, "Script engine self-test [ \033[0;31mFAILED\033[0m ]");
consolemes(CONSOLEMES_DEBUG, "**** The test was completed with " + .errors + " errors. ****");
diff --git a/npc/re/quests/quests_brasilis.txt b/npc/re/quests/quests_brasilis.txt
index debaba2e5..1d5578fa0 100644
--- a/npc/re/quests/quests_brasilis.txt
+++ b/npc/re/quests/quests_brasilis.txt
@@ -124,10 +124,10 @@ OnGo:
mes "Ah... who's a good puppy?";
mes "Ok, where are the others?";
}
- if (compare(strnpcinfo(NPC_NAME_UNIQUE),"1")) setarray .@i[0],2,3;
- else if (compare(strnpcinfo(NPC_NAME_UNIQUE),"2")) setarray .@i[0],1,3;
+ if (compare(strnpcinfo(NPC_NAME_HIDDEN),"1")) setarray .@i[0],2,3;
+ else if (compare(strnpcinfo(NPC_NAME_HIDDEN),"2")) setarray .@i[0],1,3;
else setarray .@i[0],1,2;
- donpcevent "Puppy#"+charat(strnpcinfo(NPC_NAME_UNIQUE),0)+.@i[rand(2)]+"::OnEnable";
+ donpcevent "Puppy#"+charat(strnpcinfo(NPC_NAME_HIDDEN),0)+.@i[rand(2)]+"::OnEnable";
hideonnpc strnpcinfo(NPC_NAME);
close;
}
diff --git a/sql-files/main.sql b/sql-files/main.sql
index d5b7735fc..7aebd73fd 100644
--- a/sql-files/main.sql
+++ b/sql-files/main.sql
@@ -655,14 +655,25 @@ CREATE TABLE IF NOT EXISTS `login` (
INSERT IGNORE INTO `login` (`account_id`, `userid`, `user_pass`, `sex`, `email`) VALUES ('1', 's1', 'p1', 'S','athena@athena.com');
--
--- Table structure for table `mapreg`
+-- Table structure for table `map_reg_num_db`
--
-CREATE TABLE IF NOT EXISTS `mapreg` (
- `varname` VARCHAR(32) BINARY NOT NULL,
+CREATE TABLE IF NOT EXISTS `map_reg_num_db` (
+ `key` VARCHAR(32) BINARY NOT NULL DEFAULT '',
+ `index` INT UNSIGNED NOT NULL DEFAULT '0',
+ `value` INT NOT NULL DEFAULT '0',
+ PRIMARY KEY (`key`, `index`)
+) ENGINE=MyISAM;
+
+--
+-- Table structure for table `map_reg_str_db`
+--
+
+CREATE TABLE IF NOT EXISTS `map_reg_str_db` (
+ `key` VARCHAR(32) BINARY NOT NULL DEFAULT '',
`index` INT UNSIGNED NOT NULL DEFAULT '0',
- `value` VARCHAR(255) NOT NULL,
- PRIMARY KEY (`varname`,`index`)
+ `value` VARCHAR(255) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`key`, `index`)
) ENGINE=MyISAM;
--
@@ -939,6 +950,7 @@ INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1579817630); -- 2020-01-2
INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1584838560); -- 2020-03-22--01-56.sql
INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1584842940); -- 2020-03-22--03-09.sql
INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1588301040); -- 2020-05-01--04-44.sql
+INSERT IGNORE INTO `sql_updates` (`timestamp`) VALUES (1589145060); -- 2020-05-10--23-11.sql
--
-- Table structure for table `storage`
diff --git a/sql-files/upgrades/2020-05-10--23-11.sql b/sql-files/upgrades/2020-05-10--23-11.sql
new file mode 100644
index 000000000..9f2755e76
--- /dev/null
+++ b/sql-files/upgrades/2020-05-10--23-11.sql
@@ -0,0 +1,43 @@
+#1589145060
+
+-- This file is part of Hercules.
+-- http://herc.ws - http://github.com/HerculesWS/Hercules
+--
+-- Copyright (C) 2019-2020 Hercules Dev Team
+--
+-- Hercules is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+-- Add separate tables for global integer and string variables.
+CREATE TABLE IF NOT EXISTS `map_reg_num_db` (
+ `key` VARCHAR(32) BINARY NOT NULL DEFAULT '',
+ `index` INT UNSIGNED NOT NULL DEFAULT '0',
+ `value` INT NOT NULL DEFAULT '0',
+ PRIMARY KEY (`key`, `index`)
+) ENGINE=MyISAM;
+CREATE TABLE IF NOT EXISTS `map_reg_str_db` (
+ `key` VARCHAR(32) BINARY NOT NULL DEFAULT '',
+ `index` INT UNSIGNED NOT NULL DEFAULT '0',
+ `value` VARCHAR(255) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`key`, `index`)
+) ENGINE=MyISAM;
+
+-- Copy data from mapreg table to new map_reg_*_db tables.
+INSERT INTO `map_reg_num_db` (`key`, `index`, `value`) SELECT `varname`, `index`, CAST(`value` AS SIGNED) FROM `mapreg` WHERE NOT RIGHT(`varname`, 1)='$';
+INSERT INTO `map_reg_str_db` (`key`, `index`, `value`) SELECT `varname`, `index`, `value` FROM `mapreg` WHERE RIGHT(`varname`, 1)='$';
+
+-- Remove mapreg table.
+DROP TABLE IF EXISTS `mapreg`;
+
+-- Add update timestamp.
+INSERT INTO `sql_updates` (`timestamp`) VALUES (1589145060);
diff --git a/sql-files/upgrades/index.txt b/sql-files/upgrades/index.txt
index 64a7793f8..fb889c280 100644
--- a/sql-files/upgrades/index.txt
+++ b/sql-files/upgrades/index.txt
@@ -63,3 +63,4 @@
2020-03-22--01-56.sql
2020-03-22--03-09.sql
2020-05-01--04-44.sql
+2020-05-10--23-11.sql
diff --git a/src/map/battle.c b/src/map/battle.c
index c8cd71b94..a8193d24a 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -2832,18 +2832,18 @@ static int64 battle_calc_damage(struct block_list *src, struct block_list *bl, s
d->dmg_lv = ATK_BLOCK;
if(src_skill_id == MH_STEINWAND){
if (--group->val2<=0)
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
if( (group->val3 - damage) > 0 )
group->val3 -= (int)cap_value(damage, INT_MIN, INT_MAX);
else
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
return 0;
}
if( skill_id == SO_ELEMENTAL_SHIELD ) {
if ( ( group->val2 - damage) > 0 ) {
group->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX);
} else
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
return 0;
}
/**
@@ -2853,12 +2853,12 @@ static int64 battle_calc_damage(struct block_list *src, struct block_list *bl, s
if ( ( group->val2 - damage) > 0 ) {
group->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX);
} else
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
if (--group->val3<=0)
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
#else
if (--group->val2<=0)
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
#endif
return 0;
}
diff --git a/src/map/chrif.c b/src/map/chrif.c
index b131907e0..ac5fb4dd0 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -863,6 +863,8 @@ static bool chrif_changesex(struct map_session_data *sd, bool change_account)
nullpo_retr(false, sd);
chrif_check(false);
+ chrif->save(sd, 0);
+
WFIFOHEAD(chrif->fd,44);
WFIFOW(chrif->fd,0) = 0x2b0e;
WFIFOL(chrif->fd,2) = sd->status.account_id;
diff --git a/src/map/clif.c b/src/map/clif.c
index ab13ffe1f..a0ec1fdf6 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -10389,7 +10389,8 @@ static const char *clif_process_chat_message(struct map_session_data *sd, const
* @param[in] sd The source character.
* @param[in] packet The packet data.
* @param[out] out_name The parsed target name buffer (must be a valid
- * buffer of size NAME_LENGTH).
+ * buffer of size NAME_LENGTH + 1 because the client
+ * can send 24 characters without NULL terminator).
* @param[out] out_message The output message buffer (must be a valid buffer).
* @param[in] out_messagelen The size of out_message.
* @retval true if the validation succeeded and the message is a chat message.
@@ -10399,7 +10400,7 @@ static const char *clif_process_chat_message(struct map_session_data *sd, const
*/
static bool clif_process_whisper_message(struct map_session_data *sd, const struct packet_whisper_message *packet, char *out_name, char *out_message, int out_messagelen)
{
- int namelen = 0, messagelen = 0;
+ int messagelen = 0;
nullpo_retr(false, sd);
nullpo_retr(false, packet);
@@ -10412,15 +10413,6 @@ static bool clif_process_whisper_message(struct map_session_data *sd, const stru
return false;
}
- // validate name
- namelen = (int)strnlen(packet->name, NAME_LENGTH-1); // name length (w/o zero byte)
-
- if (packet->name[namelen] != '\0') {
- // only restriction is that the name must be zero-terminated
- ShowWarning("clif_process_whisper_message: Player '%s' sent an unterminated name!\n", sd->status.name);
- return false;
- }
-
#if PACKETVER >= 20151001
// Packet doesn't include a NUL terminator
messagelen = packet->packet_len - NAME_LENGTH - 4;
@@ -10439,7 +10431,7 @@ static bool clif_process_whisper_message(struct map_session_data *sd, const stru
return false;
}
- safestrncpy(out_name, packet->name, namelen+1); // [!] packet->name is not NUL terminated
+ safestrncpy(out_name, packet->name, NAME_LENGTH + 1); // [!] packet->name is not NUL terminated
safestrncpy(out_message, packet->message, messagelen+1); // [!] packet->message is not necessarily NUL terminated
if (!pc->process_chat_message(sd, out_message))
@@ -11778,7 +11770,8 @@ static void clif_parse_WisMessage(int fd, struct map_session_data *sd)
struct map_session_data* dstsd;
int i;
- char target[NAME_LENGTH], message[CHAT_SIZE_MAX + 1];
+ char target[NAME_LENGTH + 1]; // Client can send 24 characters without NULL terminator.
+ char message[CHAT_SIZE_MAX + 1];
const struct packet_whisper_message *packet = RP2PTR(fd);
if (!clif->process_whisper_message(sd, packet, target, message, sizeof message))
diff --git a/src/map/guild.c b/src/map/guild.c
index f344878e1..90f870f1c 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -1519,7 +1519,7 @@ static void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id
if( !skill_lv )
return;
if (sd->sc.data[type] && (group = skill->id2group(sd->sc.data[type]->val4)) != NULL) {
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
status_change_end(&sd->bl,type,INVALID_TIMER);
}
group = skill->unitsetting(&sd->bl,skill_id,skill_lv,sd->bl.x,sd->bl.y,0);
@@ -2069,7 +2069,7 @@ static int guild_break(struct map_session_data *sd, const char *name)
}
}
for(i = 0; i < count; i++) { // FIXME: Why is this not done in the above loop?
- skill->del_unitgroup(groups[i],ALC_MARK);
+ skill->del_unitgroup(groups[i]);
}
}
diff --git a/src/map/map.c b/src/map/map.c
index f66f40dfc..63d05c1c0 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -4459,7 +4459,6 @@ static bool inter_config_read_connection(const char *filename, const struct conf
static bool inter_config_read_database_names(const char *filename, const struct config_t *config, bool imported)
{
const struct config_setting_t *setting = NULL;
- bool retval = true;
nullpo_retr(false, filename);
nullpo_retr(false, config);
@@ -4477,16 +4476,14 @@ static bool inter_config_read_database_names(const char *filename, const struct
libconfig->setting_lookup_mutable_string(setting, "npc_barter_data_db", map->npc_barter_data_db, sizeof(map->npc_barter_data_db));
libconfig->setting_lookup_mutable_string(setting, "npc_expanded_barter_data_db", map->npc_expanded_barter_data_db, sizeof(map->npc_expanded_barter_data_db));
- if (!mapreg->config_read(filename, setting, imported))
- retval = false;
-
if ((setting = libconfig->lookup(config, "inter_configuration/database_names/registry")) == NULL) {
if (imported)
- return retval;
+ return true;
ShowError("inter_config_read: inter_configuration/database_names/registry was not found in %s!\n", filename);
return false;
}
- return retval;
+
+ return mapreg->config_read_registry(filename, setting, imported);
}
/*=======================================
diff --git a/src/map/map.h b/src/map/map.h
index 64736a6f5..17f210bc3 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -329,6 +329,14 @@ enum bl_type {
enum npc_subtype { WARP, SHOP, SCRIPT, CASHSHOP, TOMB };
+/** optional flags for script labels, used by the label db */
+enum script_label_flags {
+ /** the label can be called from outside the local scope of the NPC */
+ LABEL_IS_EXTERN = 0x1,
+ /** the label is a public or private local NPC function */
+ LABEL_IS_USERFUNC = 0x2,
+};
+
/**
* Race type IDs.
*
diff --git a/src/map/mapreg.h b/src/map/mapreg.h
index b3b89e1b2..4318eaea8 100644
--- a/src/map/mapreg.h
+++ b/src/map/mapreg.h
@@ -21,55 +21,66 @@
#ifndef MAP_MAPREG_H
#define MAP_MAPREG_H
-#include "map/script.h" // struct reg_db
-#include "common/hercules.h"
+#include "map/script.h"
#include "common/db.h"
+#include "common/hercules.h"
-/* Forward Declarations */
-struct config_setting_t; // common/conf.h
+/** Forward Declarations **/
+struct config_setting_t;
struct eri;
-/** Container for a mapreg value */
+#ifndef MAPREG_AUTOSAVE_INTERVAL
+#define MAPREG_AUTOSAVE_INTERVAL (300 * 1000) //!< Interval for auto-saving permanent global variables to the database in milliseconds.
+#endif /** MAPREG_AUTOSAVE_INTERVAL **/
+
+/** Global variable structure. **/
struct mapreg_save {
- int64 uid; ///< Unique ID
- union {
- int i; ///< Numeric value
- char *str; ///< String value
+ int64 uid; //!< The variable's unique ID.
+ union value { //!< The variable's value container.
+ int i; //!< The variable's integer value.
+ char *str; //!< The variable's string value.
} u;
- bool is_string; ///< true if it's a string, false if it's a number
- bool save; ///< Whether a save operation is pending
+ bool is_string; //!< Whether the variable's value is a string.
+ bool save; //!< Whether the variable's save operation is pending.
};
+/** The mapreg interface structure. **/
struct mapreg_interface {
- struct reg_db regs;
- /* */
- bool skip_insert;
- /* */
- struct eri *ers; //[Ind/Hercules]
- /* */
- char table[32];
- /* */
- bool dirty; ///< Whether there are modified regs to be saved
- /* */
- void (*init) (void);
- void (*final) (void);
- /* */
+ /** Interface variables. **/
+ struct eri *ers; //!< Entry manager for global variables.
+ struct reg_db regs; //!< Generic database for global variables.
+ bool dirty; //!< Whether there are modified global variables to be saved.
+ bool skip_insert; //!< Whether to skip inserting the variable into the SQL database in mapreg_set_*_db().
+ char num_db[32]; //!< Name of SQL table which holds permanent global integer variables.
+ char str_db[32]; //!< Name of SQL table which holds permanent global string variables.
+
+ /** Interface functions. **/
int (*readreg) (int64 uid);
- char* (*readregstr) (int64 uid);
+ char *(*readregstr) (int64 uid);
+ bool (*set_num_db) (int64 uid, const char *name, unsigned int index, int value);
+ bool (*delete_num_db) (int64 uid, const char *name, unsigned int index);
bool (*setreg) (int64 uid, int val);
+ bool (*set_str_db) (int64 uid, const char *name, unsigned int index, const char *value);
+ bool (*delete_str_db) (int64 uid, const char *name, unsigned int index);
bool (*setregstr) (int64 uid, const char *str);
+ void (*load_num_db) (void);
+ void (*load_str_db) (void);
void (*load) (void);
+ void (*save_num_db) (const char *name, unsigned int index, int value);
+ void (*save_str_db) (const char *name, unsigned int index, const char *value);
void (*save) (void);
int (*save_timer) (int tid, int64 tick, int id, intptr_t data);
int (*destroyreg) (union DBKey key, struct DBData *data, va_list ap);
void (*reload) (void);
- bool (*config_read) (const char *filename, const struct config_setting_t *config, bool imported);
+ bool (*config_read_registry) (const char *filename, const struct config_setting_t *config, bool imported);
+ void (*final) (void);
+ void (*init) (void);
};
#ifdef HERCULES_CORE
void mapreg_defaults(void);
-#endif // HERCULES_CORE
+#endif /** HERCULES_CORE **/
HPShared struct mapreg_interface *mapreg;
-#endif /* MAP_MAPREG_H */
+#endif /** MAP_MAPREG_H **/
diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c
index 2963637da..16d8b0ff6 100644
--- a/src/map/mapreg_sql.c
+++ b/src/map/mapreg_sql.c
@@ -22,7 +22,7 @@
#include "mapreg.h"
-#include "map/map.h" // map-"mysql_handle
+#include "map/map.h"
#include "map/script.h"
#include "common/cbasetypes.h"
#include "common/conf.h"
@@ -38,289 +38,596 @@
#include <stdlib.h>
#include <string.h>
-static struct mapreg_interface mapreg_s;
-struct mapreg_interface *mapreg;
-
-#define MAPREG_AUTOSAVE_INTERVAL (300*1000)
+static struct mapreg_interface mapreg_s; //!< Private interface structure.
+struct mapreg_interface *mapreg; //!< Public interface structure.
/**
- * Looks up the value of an integer variable using its uid.
+ * Looks up the value of a global integer variable using its unique ID.
*
- * @param uid variable's unique identifier.
- * @return variable's integer value
- */
-static int mapreg_readreg(int64 uid)
+ * @param uid The variable's unique ID.
+ * @return The variable's value or 0 if the variable does not exist.
+ *
+ **/
+static int mapreg_get_num_reg(int64 uid)
{
- struct mapreg_save *m = i64db_get(mapreg->regs.vars, uid);
- return m?m->u.i:0;
+ struct mapreg_save *var = i64db_get(mapreg->regs.vars, uid);
+ return (var != NULL) ? var->u.i : 0;
}
/**
- * Looks up the value of a string variable using its uid.
+ * Looks up the value of a global string variable using its unique ID.
*
- * @param uid variable's unique identifier
- * @return variable's string value
- */
-static char *mapreg_readregstr(int64 uid)
+ * @param uid The variable's unique ID.
+ * @return The variable's value or NULL if the variable does not exist.
+ *
+ **/
+static char *mapreg_get_str_reg(int64 uid)
{
- struct mapreg_save *m = i64db_get(mapreg->regs.vars, uid);
- return m?m->u.str:NULL;
+ struct mapreg_save *var = i64db_get(mapreg->regs.vars, uid);
+ return (var != NULL) ? var->u.str : NULL;
}
/**
- * Modifies the value of an integer variable.
+ * Sets the value of a global integer variable.
*
- * @param uid variable's unique identifier
- * @param val new value
- * @retval true value was successfully set
- */
-static bool mapreg_setreg(int64 uid, int val)
+ * @param uid The variable's unique ID.
+ * @param name The variable's name.
+ * @param index The variable's array index.
+ * @param value The variable's new value.
+ * @return True on success, otherwise false.
+ *
+ **/
+static bool mapreg_set_num_db(int64 uid, const char *name, unsigned int index, int value)
{
- struct mapreg_save *m;
- int num = script_getvarid(uid);
- unsigned int i = script_getvaridx(uid);
- const char* name = script->get_str(num);
-
- nullpo_retr(true, name);
- if( val != 0 ) {
- if( (m = i64db_get(mapreg->regs.vars, uid)) ) {
- m->u.i = val;
- if(name[1] != '@') {
- m->save = true;
- mapreg->dirty = true;
- }
- } else {
- if( i )
- script->array_update(&mapreg->regs, uid, false);
-
- m = ers_alloc(mapreg->ers, struct mapreg_save);
-
- m->u.i = val;
- m->uid = uid;
- m->save = false;
- m->is_string = false;
-
- if (name[1] != '@' && !mapreg->skip_insert) {// write new variable to database
- char tmp_str[(SCRIPT_VARNAME_LENGTH+1)*2+1];
- SQL->EscapeStringLen(map->mysql_handle, tmp_str, name, strnlen(name, SCRIPT_VARNAME_LENGTH+1));
- if( SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%u','%d')", mapreg->table, tmp_str, i, val) )
- Sql_ShowDebug(map->mysql_handle);
- }
- i64db_put(mapreg->regs.vars, uid, m);
+ nullpo_retr(false, name);
+ Assert_retr(false, *name != '\0');
+ Assert_retr(false, strlen(name) <= SCRIPT_VARNAME_LENGTH);
+
+ if (value == 0)
+ return mapreg->delete_num_db(uid, name, index);
+
+ struct mapreg_save *var = i64db_get(mapreg->regs.vars, uid);
+
+ // Update variable.
+ if (var != NULL) {
+ var->u.i = value;
+
+ if (script->is_permanent_variable(name)) {
+ var->save = true;
+ mapreg->dirty = true;
}
- } else { // val == 0
- if( i )
- script->array_update(&mapreg->regs, uid, true);
- if( (m = i64db_get(mapreg->regs.vars, uid)) ) {
- ers_free(mapreg->ers, m);
+
+ return true;
+ }
+
+ // Add new variable.
+ if (index != 0)
+ script->array_update(&mapreg->regs, uid, false);
+
+ var = ers_alloc(mapreg->ers, struct mapreg_save);
+ var->u.i = value;
+ var->uid = uid;
+ var->save = false;
+ var->is_string = false;
+ i64db_put(mapreg->regs.vars, uid, var);
+
+ if (script->is_permanent_variable(name) && !mapreg->skip_insert) {
+ struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
+
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return false;
}
- i64db_remove(mapreg->regs.vars, uid);
- if( name[1] != '@' ) {// Remove from database because it is unused.
- if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%u'", mapreg->table, name, i) )
- Sql_ShowDebug(map->mysql_handle);
+ const char *query = "INSERT INTO `%s` (`key`, `index`, `value`) VALUES (?, ?, ?)";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, mapreg->num_db)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_STRING, name, strlen(name))
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_UINT32, &index, sizeof(index))
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 2, SQLDT_INT32, &value, sizeof(value))
+ || SQL_ERROR == SQL->StmtExecute(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return false;
}
+
+ SQL->StmtFree(stmt);
}
return true;
}
/**
- * Modifies the value of a string variable.
+ * Deletes a global integer variable.
*
- * @param uid variable's unique identifier
- * @param str new value
- * @retval true value was successfully set
- */
-static bool mapreg_setregstr(int64 uid, const char *str)
+ * @param uid The variable's unique ID.
+ * @param name The variable's name.
+ * @param index The variable's array index.
+ * @return True on success, otherwise false.
+ *
+ **/
+static bool mapreg_delete_num_db(int64 uid, const char *name, unsigned int index)
{
- struct mapreg_save *m;
- int num = script_getvarid(uid);
- unsigned int i = script_getvaridx(uid);
- const char* name = script->get_str(num);
-
- nullpo_retr(true, name);
-
- if( str == NULL || *str == 0 ) {
- if( i )
- script->array_update(&mapreg->regs, uid, true);
- if(name[1] != '@') {
- if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%u'", mapreg->table, name, i))
- Sql_ShowDebug(map->mysql_handle);
+ nullpo_retr(false, name);
+ Assert_retr(false, *name != '\0');
+ Assert_retr(false, strlen(name) <= SCRIPT_VARNAME_LENGTH);
+
+ struct mapreg_save *var = i64db_get(mapreg->regs.vars, uid);
+
+ if (var != NULL)
+ ers_free(mapreg->ers, var);
+
+ if (index != 0)
+ script->array_update(&mapreg->regs, uid, true);
+
+ i64db_remove(mapreg->regs.vars, uid);
+
+ if (script->is_permanent_variable(name)) {
+ struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
+
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return false;
}
- if( (m = i64db_get(mapreg->regs.vars, uid)) ) {
- if( m->u.str != NULL )
- aFree(m->u.str);
- ers_free(mapreg->ers, m);
+
+ const char *query = "DELETE FROM `%s` WHERE `key`=? AND `index`=?";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, mapreg->num_db)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_STRING, name, strlen(name))
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_UINT32, &index, sizeof(index))
+ || SQL_ERROR == SQL->StmtExecute(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return false;
}
- i64db_remove(mapreg->regs.vars, uid);
- } else {
- if( (m = i64db_get(mapreg->regs.vars, uid)) ) {
- if( m->u.str != NULL )
- aFree(m->u.str);
- m->u.str = aStrdup(str);
- if(name[1] != '@') {
- mapreg->dirty = true;
- m->save = true;
- }
- } else {
- if( i )
- script->array_update(&mapreg->regs, uid, false);
-
- m = ers_alloc(mapreg->ers, struct mapreg_save);
-
- m->uid = uid;
- m->u.str = aStrdup(str);
- m->save = false;
- m->is_string = true;
-
- if(name[1] != '@' && !mapreg->skip_insert) { //put returned null, so we must insert.
- char tmp_str[(SCRIPT_VARNAME_LENGTH+1)*2+1];
- char tmp_str2[SCRIPT_STRING_VAR_LENGTH * 2 + 1];
- SQL->EscapeStringLen(map->mysql_handle, tmp_str, name, strnlen(name, SCRIPT_VARNAME_LENGTH+1));
- SQL->EscapeStringLen(map->mysql_handle, tmp_str2, str, strnlen(str, SCRIPT_STRING_VAR_LENGTH));
- if( SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%u','%s')", mapreg->table, tmp_str, i, tmp_str2) )
- Sql_ShowDebug(map->mysql_handle);
- }
- i64db_put(mapreg->regs.vars, uid, m);
+
+ SQL->StmtFree(stmt);
+ }
+
+ return true;
+}
+
+/**
+ * Sets the value of a global integer variable or deletes it if passed value is 0.
+ *
+ * @param uid The variable's unique ID.
+ * @param val The variable's new value.
+ * @return True on success, otherwise false.
+ *
+ **/
+static bool mapreg_set_num(int64 uid, int val)
+{
+ unsigned int index = script_getvaridx(uid);
+ const char *name = script->get_str(script_getvarid(uid));
+
+ if (val != 0)
+ return mapreg->set_num_db(uid, name, index, val);
+ else
+ return mapreg->delete_num_db(uid, name, index);
+}
+
+/**
+ * Sets the value of a global string variable.
+ *
+ * @param uid The variable's unique ID.
+ * @param name The variable's name.
+ * @param index The variable's array index.
+ * @param value The variable's new value.
+ * @return True on success, otherwise false.
+ *
+ **/
+static bool mapreg_set_str_db(int64 uid, const char *name, unsigned int index, const char *value)
+{
+ nullpo_retr(false, name);
+ Assert_retr(false, *name != '\0');
+ Assert_retr(false, strlen(name) <= SCRIPT_VARNAME_LENGTH);
+
+ if (value == NULL || *value == '\0')
+ return mapreg->delete_str_db(uid, name, index);
+
+ if (script->is_permanent_variable(name))
+ Assert_retr(false, strlen(value) <= SCRIPT_STRING_VAR_LENGTH);
+
+ struct mapreg_save *var = i64db_get(mapreg->regs.vars, uid);
+
+ // Update variable.
+ if (var != NULL) {
+ if (var->u.str != NULL)
+ aFree(var->u.str);
+
+ var->u.str = aStrdup(value);
+
+ if (script->is_permanent_variable(name)) {
+ var->save = true;
+ mapreg->dirty = true;
}
+
+ return true;
+ }
+
+ // Add new variable.
+ if (index != 0)
+ script->array_update(&mapreg->regs, uid, false);
+
+ var = ers_alloc(mapreg->ers, struct mapreg_save);
+ var->u.str = aStrdup(value);
+ var->uid = uid;
+ var->save = false;
+ var->is_string = true;
+ i64db_put(mapreg->regs.vars, uid, var);
+
+ if (script->is_permanent_variable(name) && !mapreg->skip_insert) {
+ struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
+
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return false;
+ }
+
+ const char *query = "INSERT INTO `%s` (`key`, `index`, `value`) VALUES (?, ?, ?)";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, mapreg->str_db)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_STRING, name, strlen(name))
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_UINT32, &index, sizeof(index))
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 2, SQLDT_STRING, value, strlen(value))
+ || SQL_ERROR == SQL->StmtExecute(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return false;
+ }
+
+ SQL->StmtFree(stmt);
}
return true;
}
/**
- * Loads permanent variables from database.
- */
-static void script_load_mapreg(void)
+ * Deletes a global string variable.
+ *
+ * @param uid The variable's unique ID.
+ * @param name The variable's name.
+ * @param index The variable's array index.
+ * @return True on success, otherwise false.
+ *
+ **/
+static bool mapreg_delete_str_db(int64 uid, const char *name, unsigned int index)
+{
+ nullpo_retr(false, name);
+ Assert_retr(false, *name != '\0');
+ Assert_retr(false, strlen(name) <= SCRIPT_VARNAME_LENGTH);
+
+ struct mapreg_save *var = i64db_get(mapreg->regs.vars, uid);
+
+ if (var != NULL) {
+ if (var->u.str != NULL)
+ aFree(var->u.str);
+
+ ers_free(mapreg->ers, var);
+ }
+
+ if (index != 0)
+ script->array_update(&mapreg->regs, uid, true);
+
+ i64db_remove(mapreg->regs.vars, uid);
+
+ if (script->is_permanent_variable(name)) {
+ struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
+
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return false;
+ }
+
+ const char *query = "DELETE FROM `%s` WHERE `key`=? AND `index`=?";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, mapreg->str_db)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_STRING, name, strlen(name))
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_UINT32, &index, sizeof(index))
+ || SQL_ERROR == SQL->StmtExecute(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return false;
+ }
+
+ SQL->StmtFree(stmt);
+ }
+
+ return true;
+}
+
+/**
+ * Sets the value of a global string variable or deletes it if passed value is NULL or an empty string.
+ *
+ * @param uid The variable's unique ID.
+ * @param str The variable's new value.
+ * @return True on success, otherwise false.
+ *
+ **/
+static bool mapreg_set_str(int64 uid, const char *str)
+{
+ unsigned int index = script_getvaridx(uid);
+ const char *name = script->get_str(script_getvarid(uid));
+
+ if (str != NULL && *str != '\0')
+ return mapreg->set_str_db(uid, name, index, str);
+ else
+ return mapreg->delete_str_db(uid, name, index);
+}
+
+/**
+ * Loads permanent global interger variables from the database.
+ *
+ **/
+static void mapreg_load_num_db(void)
{
- /*
- 0 1 2
- +-------------------------+
- | varname | index | value |
- +-------------------------+
- */
struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
- char varname[SCRIPT_VARNAME_LENGTH+1];
- int index;
- char value[SCRIPT_STRING_VAR_LENGTH + 1];
- uint32 length;
- if ( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `varname`, `index`, `value` FROM `%s`", mapreg->table)
- || SQL_ERROR == SQL->StmtExecute(stmt)
- ) {
+ if (stmt == NULL) {
SqlStmt_ShowDebug(stmt);
- SQL->StmtFree(stmt);
return;
}
- mapreg->skip_insert = true;
+ const char *query = "SELECT `key`, `index`, `value` FROM `%s`";
+ char name[SCRIPT_VARNAME_LENGTH + 1];
+ unsigned int index;
+ int value;
- SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &varname, sizeof varname, &length, NULL);
- SQL->StmtBindColumn(stmt, 1, SQLDT_INT, &index, sizeof index, NULL, NULL);
- SQL->StmtBindColumn(stmt, 2, SQLDT_STRING, &value, sizeof value, NULL, NULL);
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, mapreg->num_db)
+ || SQL_ERROR == SQL->StmtExecute(stmt)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name, sizeof(name), NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_UINT32, &index, sizeof(index), NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_INT32, &value, sizeof(value), NULL, NULL)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return;
+ }
- while ( SQL_SUCCESS == SQL->StmtNextRow(stmt) ) {
- int s = script->add_variable(varname);
- int i = index;
+ if (SQL->StmtNumRows(stmt) < 1) {
+ SQL->StmtFree(stmt);
+ return;
+ }
+ mapreg->skip_insert = true;
+
+ while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
+ int var_key = script->add_variable(name);
+ int64 uid = reference_uid(var_key, index);
- if( i64db_exists(mapreg->regs.vars, reference_uid(s, i)) ) {
- ShowWarning("load_mapreg: duplicate! '%s' => '%s' skipping...\n",varname,value);
+ if (i64db_exists(mapreg->regs.vars, uid)) {
+ ShowWarning("mapreg_load_num_db: Duplicate! '%s' => '%d' Skipping...\n", name, value);
continue;
}
- if( varname[length-1] == '$' ) {
- mapreg->setregstr(reference_uid(s, i),value);
- } else {
- mapreg->setreg(reference_uid(s, i),atoi(value));
- }
+
+ mapreg->setreg(uid, value);
}
+ mapreg->skip_insert = false;
SQL->StmtFree(stmt);
+}
+
+/**
+ * Loads permanent global string variables from the database.
+ *
+ **/
+static void mapreg_load_str_db(void)
+{
+ struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
+
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return;
+ }
+
+ const char *query = "SELECT `key`, `index`, `value` FROM `%s`";
+ char name[SCRIPT_VARNAME_LENGTH + 1];
+ unsigned int index;
+ char value[SCRIPT_STRING_VAR_LENGTH + 1];
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, mapreg->str_db)
+ || SQL_ERROR == SQL->StmtExecute(stmt)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_STRING, &name, sizeof(name), NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 1, SQLDT_UINT32, &index, sizeof(index), NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 2, SQLDT_STRING, &value, sizeof(value), NULL, NULL)) {
+ SqlStmt_ShowDebug(stmt);
+ SQL->StmtFree(stmt);
+ return;
+ }
+
+ if (SQL->StmtNumRows(stmt) < 1) {
+ SQL->StmtFree(stmt);
+ return;
+ }
+
+ mapreg->skip_insert = true;
+
+ while (SQL_SUCCESS == SQL->StmtNextRow(stmt)) {
+ int var_key = script->add_variable(name);
+ int64 uid = reference_uid(var_key, index);
+
+ if (i64db_exists(mapreg->regs.vars, uid)) {
+ ShowWarning("mapreg_load_str_db: Duplicate! '%s' => '%s' Skipping...\n", name, value);
+ continue;
+ }
+
+ mapreg->setregstr(uid, value);
+ }
mapreg->skip_insert = false;
+ SQL->StmtFree(stmt);
+}
+/**
+ * Loads permanent global variables from the database.
+ *
+ **/
+static void mapreg_load(void)
+{
+ mapreg->load_num_db();
+ mapreg->load_str_db();
mapreg->dirty = false;
}
/**
- * Saves permanent variables to database.
- */
-static void script_save_mapreg(void)
+ * Saves a permanent global integer variable to the database.
+ *
+ * @param name The variable's name.
+ * @param index The variable's array index.
+ * @param value The variable's value.
+ *
+ **/
+static void mapreg_save_num_db(const char *name, unsigned int index, int value)
+{
+ nullpo_retv(name);
+ Assert_retv(*name != '\0');
+ Assert_retv(strlen(name) <= SCRIPT_VARNAME_LENGTH);
+
+ struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
+
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return;
+ }
+
+ const char *query = "UPDATE `%s` SET `value`=? WHERE `key`=? AND `index`=? LIMIT 1";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, mapreg->num_db)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT32, &value, sizeof(value))
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_STRING, name, strlen(name))
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 2, SQLDT_UINT32, &index, sizeof(index))
+ || SQL_ERROR == SQL->StmtExecute(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ }
+
+ SQL->StmtFree(stmt);
+}
+
+/**
+ * Saves a permanent global string variable to the database.
+ *
+ * @param name The variable's name.
+ * @param index The variable's array index.
+ * @param value The variable's value.
+ *
+ **/
+static void mapreg_save_str_db(const char *name, unsigned int index, const char *value)
+{
+ nullpo_retv(name);
+ nullpo_retv(value);
+ Assert_retv(*name != '\0');
+ Assert_retv(strlen(name) <= SCRIPT_VARNAME_LENGTH);
+ Assert_retv(*value != '\0');
+ Assert_retv(strlen(value) <= SCRIPT_STRING_VAR_LENGTH);
+
+ struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
+
+ if (stmt == NULL) {
+ SqlStmt_ShowDebug(stmt);
+ return;
+ }
+
+ const char *query = "UPDATE `%s` SET `value`=? WHERE `key`=? AND `index`=? LIMIT 1";
+
+ if (SQL_ERROR == SQL->StmtPrepare(stmt, query, mapreg->str_db)
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_STRING, value, strlen(value))
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 1, SQLDT_STRING, name, strlen(name))
+ || SQL_ERROR == SQL->StmtBindParam(stmt, 2, SQLDT_UINT32, &index, sizeof(index))
+ || SQL_ERROR == SQL->StmtExecute(stmt)) {
+ SqlStmt_ShowDebug(stmt);
+ }
+
+ SQL->StmtFree(stmt);
+}
+
+/**
+ * Saves permanent global variables to the database.
+ *
+ **/
+static void mapreg_save(void)
{
if (mapreg->dirty) {
struct DBIterator *iter = db_iterator(mapreg->regs.vars);
- struct mapreg_save *m = NULL;
- for (m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter)) {
- if (m->save) {
- int num = script_getvarid(m->uid);
- int i = script_getvaridx(m->uid);
- const char* name = script->get_str(num);
- nullpo_retv(name);
- if (!m->is_string) {
- if( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg->table, m->u.i, name, i) )
- Sql_ShowDebug(map->mysql_handle);
- } else {
- char tmp_str2[SCRIPT_STRING_VAR_LENGTH * 2 + 1];
- SQL->EscapeStringLen(map->mysql_handle, tmp_str2, m->u.str, safestrnlen(m->u.str, SCRIPT_STRING_VAR_LENGTH));
- if( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE `%s` SET `value`='%s' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg->table, tmp_str2, name, i) )
- Sql_ShowDebug(map->mysql_handle);
- }
- m->save = false;
+ struct mapreg_save *var = NULL;
+
+ for (var = dbi_first(iter); dbi_exists(iter); var = dbi_next(iter)) {
+ if (var->save) {
+ int index = script_getvaridx(var->uid);
+ const char *name = script->get_str(script_getvarid(var->uid));
+
+ if (!var->is_string)
+ mapreg->save_num_db(name, index, var->u.i);
+ else
+ mapreg->save_str_db(name, index, var->u.str);
+
+ var->save = false;
}
}
+
dbi_destroy(iter);
mapreg->dirty = false;
}
}
/**
- * Timer event to auto-save permanent variables.
+ * Timer event to auto-save permanent global variables.
*
- * @see timer->do_timer
- */
-static int script_autosave_mapreg(int tid, int64 tick, int id, intptr_t data)
+ * @see timer->do_timer()
+ *
+ * @param tid Unused.
+ * @param tick Unused.
+ * @param id Unused.
+ * @param data Unused.
+ * @return Always 0.
+ *
+ **/
+static int mapreg_save_timer(int tid, int64 tick, int id, intptr_t data)
{
mapreg->save();
return 0;
}
/**
- * Destroys a mapreg_save structure, freeing the contained string, if any.
+ * Destroys a mapreg_save structure and frees the contained string, if any.
*
* @see DBApply
- */
-static int mapreg_destroyreg(union DBKey key, struct DBData *data, va_list ap)
+ *
+ * @param key Unused.
+ * @param data The DB data holding the mapreg_save data.
+ * @param ap Unused.
+ * @return 0 on success, otherwise 1.
+ *
+ **/
+static int mapreg_destroy_reg(union DBKey key, struct DBData *data, va_list ap)
{
- struct mapreg_save *m = NULL;
+ nullpo_retr(1, data);
if (data->type != DB_DATA_PTR) // Sanity check
- return 0;
+ return 1;
- m = DB->data2ptr(data);
+ struct mapreg_save *var = DB->data2ptr(data);
- if (m->is_string) {
- if (m->u.str)
- aFree(m->u.str);
- }
- ers_free(mapreg->ers, m);
+ if (var == NULL)
+ return 1;
+
+ if (var->is_string && var->u.str != NULL)
+ aFree(var->u.str);
+ ers_free(mapreg->ers, var);
return 0;
}
/**
- * Reloads mapregs, saving to database beforehand.
+ * Reloads permanent global variables, saving them to the database beforehand.
*
- * This has the effect of clearing the temporary variables, and
- * reloading the permanent ones.
- */
+ * This has the effect of clearing the temporary global variables and reloading the permanent ones.
+ *
+ **/
static void mapreg_reload(void)
{
mapreg->save();
-
mapreg->regs.vars->clear(mapreg->regs.vars, mapreg->destroyreg);
- if( mapreg->regs.arrays ) {
+ if (mapreg->regs.arrays != NULL) {
mapreg->regs.arrays->destroy(mapreg->regs.arrays, script->array_free_db);
mapreg->regs.arrays = NULL;
}
@@ -329,86 +636,105 @@ static void mapreg_reload(void)
}
/**
- * Finalizer.
- */
+ * Loads the mapreg database table names from configuration file.
+ *
+ * @param filename Path to configuration file. (Used in error and warning messages).
+ * @param config The current config being parsed.
+ * @param imported Whether the current config is imported from another file.
+ * @return True on success, otherwise false.
+ *
+ **/
+static bool mapreg_config_read_registry(const char *filename, const struct config_setting_t *config, bool imported)
+{
+ nullpo_retr(false, filename);
+ nullpo_retr(false, config);
+
+ bool ret_val = true;
+ size_t sz = sizeof(mapreg->num_db);
+ int result = libconfig->setting_lookup_mutable_string(config, "map_reg_num_db", mapreg->num_db, sz);
+
+ if (result != CONFIG_TRUE && !imported) {
+ ShowError("%s: inter_configuration/database_names/registry/map_reg_num_db was not found in %s!\n",
+ __func__, filename);
+ ret_val = false;
+ }
+
+ sz = sizeof(mapreg->str_db);
+ result = libconfig->setting_lookup_mutable_string(config, "map_reg_str_db", mapreg->str_db, sz);
+
+ if (result != CONFIG_TRUE && !imported) {
+ ShowError("%s: inter_configuration/database_names/registry/map_reg_str_db was not found in %s!\n",
+ __func__, filename);
+ ret_val = false;
+ }
+
+ return ret_val;
+}
+
+/**
+ * Saves permanent global variables to the database and frees all the memory they use afterwards.
+ *
+ **/
static void mapreg_final(void)
{
mapreg->save();
-
mapreg->regs.vars->destroy(mapreg->regs.vars, mapreg->destroyreg);
-
ers_destroy(mapreg->ers);
- if( mapreg->regs.arrays )
+ if (mapreg->regs.arrays != NULL)
mapreg->regs.arrays->destroy(mapreg->regs.arrays, script->array_free_db);
}
/**
- * Initializer.
- */
+ * Allocates memory for permanent global variables, loads them from the database and initializes the auto-save timer.
+ *
+ **/
static void mapreg_init(void)
{
mapreg->regs.vars = i64db_alloc(DB_OPT_BASE);
mapreg->ers = ers_new(sizeof(struct mapreg_save), "mapreg_sql.c::mapreg_ers", ERS_OPT_CLEAN);
-
mapreg->load();
-
- timer->add_func_list(mapreg->save_timer, "mapreg_script_autosave_mapreg");
+ timer->add_func_list(mapreg->save_timer, "mapreg_save_timer");
timer->add_interval(timer->gettick() + MAPREG_AUTOSAVE_INTERVAL, mapreg->save_timer, 0, 0, MAPREG_AUTOSAVE_INTERVAL);
}
/**
- * Loads the mapreg configuration file.
- *
- * @param filename Path to configuration file (used in error and warning messages).
- * @param config The current config being parsed.
- * @param imported Whether the current config is imported from another file.
+ * Initializes the mapreg interface defaults.
*
- * @retval false in case of error.
- */
-static bool mapreg_config_read(const char *filename, const struct config_setting_t *config, bool imported)
-{
- nullpo_retr(false, filename);
- nullpo_retr(false, config);
-
- if (libconfig->setting_lookup_mutable_string(config, "mapreg_db", mapreg->table, sizeof(mapreg->table)) != CONFIG_TRUE)
- return false;
-
- return true;
-}
-
-/**
- * Interface defaults initializer.
- */
+ **/
void mapreg_defaults(void)
{
+ /** Interface structure. **/
mapreg = &mapreg_s;
- /* */
- mapreg->regs.vars = NULL;
+ /** Interface variables. **/
mapreg->ers = NULL;
- mapreg->skip_insert = false;
-
- safestrncpy(mapreg->table, "mapreg", sizeof(mapreg->table));
- mapreg->dirty = false;
-
- /* */
+ mapreg->regs.vars = NULL;
mapreg->regs.arrays = NULL;
-
- /* */
- mapreg->init = mapreg_init;
- mapreg->final = mapreg_final;
-
- /* */
- mapreg->readreg = mapreg_readreg;
- mapreg->readregstr = mapreg_readregstr;
- mapreg->setreg = mapreg_setreg;
- mapreg->setregstr = mapreg_setregstr;
- mapreg->load = script_load_mapreg;
- mapreg->save = script_save_mapreg;
- mapreg->save_timer = script_autosave_mapreg;
- mapreg->destroyreg = mapreg_destroyreg;
+ mapreg->dirty = false;
+ mapreg->skip_insert = false;
+ safestrncpy(mapreg->num_db, "map_reg_num_db", sizeof(mapreg->num_db));
+ safestrncpy(mapreg->str_db, "map_reg_str_db", sizeof(mapreg->str_db));
+
+ /** Interface functions. **/
+ mapreg->readreg = mapreg_get_num_reg;
+ mapreg->readregstr = mapreg_get_str_reg;
+ mapreg->set_num_db = mapreg_set_num_db;
+ mapreg->delete_num_db = mapreg_delete_num_db;
+ mapreg->setreg = mapreg_set_num;
+ mapreg->set_str_db = mapreg_set_str_db;
+ mapreg->delete_str_db = mapreg_delete_str_db;
+ mapreg->setregstr = mapreg_set_str;
+ mapreg->load_num_db = mapreg_load_num_db;
+ mapreg->load_str_db = mapreg_load_str_db;
+ mapreg->load = mapreg_load;
+ mapreg->save_num_db = mapreg_save_num_db;
+ mapreg->save_str_db = mapreg_save_str_db;
+ mapreg->save = mapreg_save;
+ mapreg->save_timer = mapreg_save_timer;
+ mapreg->destroyreg = mapreg_destroy_reg;
mapreg->reload = mapreg_reload;
- mapreg->config_read = mapreg_config_read;
-
+ mapreg->config_read_registry = mapreg_config_read_registry;
+ mapreg->final = mapreg_final;
+ mapreg->init = mapreg_init;
}
diff --git a/src/map/mob.c b/src/map/mob.c
index dcbdccedd..b6ba5e5a9 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -3758,6 +3758,8 @@ static int mobskill_event(struct mob_data *md, struct block_list *src, int64 tic
res = mob->skill_use(md, tick, MSC_CLOSEDATTACKED);
else if (flag&BF_LONG && !(flag&BF_MAGIC)) //Long-attacked should not include magic.
res = mob->skill_use(md, tick, MSC_LONGRANGEATTACKED);
+ else if ((flag & BF_MAGIC) != 0)
+ res = mob->skill_use(md, tick, MSC_MAGICATTACKED);
if (res != 0)
//Restore previous target only if skill condition failed to trigger. [Skotlex]
@@ -5679,7 +5681,7 @@ static bool mob_skill_db_libconfig_sub_skill(struct config_setting_t *it, int n,
}
i32 = MSC_ALWAYS;
- if (mob->lookup_const(it, "CastCondition", &i32) && (i32 < MSC_ALWAYS || i32 > MSC_SPAWN)) {
+ if (mob->lookup_const(it, "CastCondition", &i32) && (i32 < MSC_ALWAYS || i32 > MSC_MAGICATTACKED)) {
ShowWarning("%s: Invalid skill condition %d for skill id %d (%s) in %s %d, defaulting to MSC_ALWAYS.\n",
__func__, i32, skill_id, skill_name, mob_str, mob_id);
i32 = MSC_ALWAYS;
diff --git a/src/map/mob.h b/src/map/mob.h
index 6ad1ce705..59b288fcc 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -321,6 +321,7 @@ enum {
MSC_MASTERATTACKED,
MSC_ALCHEMIST,
MSC_SPAWN,
+ MSC_MAGICATTACKED,
};
/** Special monster(-name) constants used to assign skills to a group of monsters. **/
diff --git a/src/map/npc.c b/src/map/npc.c
index 40ec380ee..2f03623e4 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -389,7 +389,10 @@ static int npc_event_export(struct npc_data *nd, int i)
Assert_ret(i >= 0 && i < nd->u.scr.label_list_num);
lname = nd->u.scr.label_list[i].name;
pos = nd->u.scr.label_list[i].pos;
- if ((lname[0] == 'O' || lname[0] == 'o') && (lname[1] == 'N' || lname[1] == 'n')) {
+
+ if ((nd->u.scr.label_list[i].flags & LABEL_IS_EXTERN) != 0
+ && ((nd->u.scr.label_list[i].flags & LABEL_IS_USERFUNC) == 0
+ || script->config.functions_as_events)) {
struct event_data *ev;
struct linkdb_node **label_linkdb = NULL;
char buf[EVENT_NAME_LENGTH];
@@ -3054,11 +3057,11 @@ static int npc_unload(struct npc_data *nd, bool single, bool unload_mobs)
aFree(nd->u.shop.shop_item); /// src check for duplicate shops. [Orcao]
} else if (nd->subtype == SCRIPT) {
char evname[EVENT_NAME_LENGTH];
-
+
snprintf(evname, ARRAYLENGTH(evname), "%s::OnNPCUnload", nd->exname);
struct event_data *ev = strdb_get(npc->ev_db, evname);
-
+
if (ev != NULL)
script->run_npc(nd->u.scr.script, ev->pos, 0, nd->bl.id); /// Run OnNPCUnload.
@@ -3665,6 +3668,7 @@ static void npc_convertlabel_db(struct npc_label_list *label_list, const char *f
for( i = 0; i < script->label_count; i++ ) {
const char* lname = script->get_str(script->labels[i].key);
int lpos = script->labels[i].pos;
+ enum script_label_flags flags = script->labels[i].flags;
struct npc_label_list* label;
const char *p;
size_t len;
@@ -3686,6 +3690,7 @@ static void npc_convertlabel_db(struct npc_label_list *label_list, const char *f
safestrncpy(label->name, lname, sizeof(label->name));
label->pos = lpos;
+ label->flags = flags;
}
}
@@ -5606,7 +5611,7 @@ static int npc_reload(void)
npc->npc_last_npd = NULL;
npc->npc_last_path = NULL;
npc->npc_last_ref = NULL;
-
+
const int npc_new_min = npc->npc_id;
struct s_mapiterator *iter = mapit_geteachiddb();
diff --git a/src/map/npc.h b/src/map/npc.h
index 1585a2bc8..16d7a984b 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -56,9 +56,15 @@ enum npc_shop_types {
struct npc_timerevent_list {
int timer,pos;
};
+
+/** list of labels within a NPC (used internally by the label db) */
struct npc_label_list {
+ /** label name */
char name[NAME_LENGTH];
+ /** start point within the script */
int pos;
+ /** optional label flags */
+ enum script_label_flags flags;
};
struct npc_barter_currency {
diff --git a/src/map/pc.h b/src/map/pc.h
index e560df549..8d1cd0ca4 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -629,10 +629,6 @@ END_ZEROED_BLOCK;
uint8 lang_id;
- // temporary debugging of bug #3504
- const char* delunit_prevfile;
- int delunit_prevline;
-
// HatEffect
VECTOR_DECL(int) hatEffectId;
diff --git a/src/map/script.c b/src/map/script.c
index 347ef3d2a..e4a57194d 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -848,79 +848,134 @@ static const char *parse_callfunc(const char *p, int require_paren, int is_custo
nullpo_retr(NULL, p);
// is need add check for arg null pointer below?
- func = script->add_word(p);
- if (script->str_data[func].type == C_FUNC) {
- script->syntax.nested_call++;
- if (script->syntax.last_func != -1) {
- if (script->str_data[func].val == script->buildin_lang_macro_offset) {
- script->syntax.lang_macro_active = true;
- macro = true;
- } else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset) {
- script->syntax.lang_macro_fmtstring_active = true;
- macro = true;
- }
+
+ if (*p == '"') {
+ p2 = ++p; // jump to the start of the word
+
+ // find the closing quote
+ while (*p2 != '"') {
+ ++p2;
}
- if( !macro ) {
- // buildin function
+ if (p2[1] == ':' && p2[2] == ':') {
+ func = script->add_str("callfunctionofnpc");
+ arg = "*"; // we already take care of the "vs" part of "vs*"
+
+ script->syntax.nested_call++;
script->syntax.last_func = script->str_data[func].val;
script->addl(func);
script->addc(C_ARG);
- }
- arg = script->buildin[script->str_data[func].val];
- if (script->str_data[func].deprecated)
- DeprecationWarning(p);
- if( !arg ) arg = &null_arg; // Use a dummy, null string
- } else if( script->str_data[func].type == C_USERFUNC || script->str_data[func].type == C_USERFUNC_POS ) {
- // script defined function
- script->addl(script->buildin_callsub_ref);
- script->addc(C_ARG);
- script->addl(func);
- arg = script->buildin[script->str_data[script->buildin_callsub_ref].val];
- if( *arg == 0 )
- disp_error_message("parse_callfunc: callsub has no arguments, please review its definition",p);
- if( *arg != '*' )
- ++arg; // count func as argument
+ script->addc(C_STR);
+ do {
+ script->addb(*p++); // npc name
+ } while (p < p2);
+ script->addb(0);
+
+ p = p2 + 3; // skip to start of func name
+ p2 = script->skip_word(p);
+
+ script->addc(C_STR);
+ do {
+ script->addb(*p++); // func name
+ } while (p < p2);
+ script->addb(0);
+
+ p = p2; // skip to just before the ()
+ } else {
+ disp_error_message("script:parse_callfunc: invalid public function call syntax!", p2 + 1);
+ }
} else {
+ func = script->add_word(p);
+ if (script->str_data[func].type == C_FUNC) {
+ script->syntax.nested_call++;
+
+ if (script->syntax.last_func != -1) {
+ if (script->str_data[func].val == script->buildin_lang_macro_offset) {
+ script->syntax.lang_macro_active = true;
+ macro = true;
+ } else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset) {
+ script->syntax.lang_macro_fmtstring_active = true;
+ macro = true;
+ }
+ }
+
+ if (!macro) {
+ // buildin function
+ script->syntax.last_func = script->str_data[func].val;
+ script->addl(func);
+ script->addc(C_ARG);
+ }
+
+ arg = script->buildin[script->str_data[func].val];
+
+ if (script->str_data[func].deprecated == 1) {
+ DeprecationWarning(p);
+ }
+
+ if (arg == NULL) {
+ arg = &null_arg; // Use a dummy, null string
+ }
+ } else if (script->str_data[func].type == C_USERFUNC || script->str_data[func].type == C_USERFUNC_POS) {
+ // script defined function
+ script->addl(script->buildin_callsub_ref);
+ script->addc(C_ARG);
+ script->addl(func);
+ arg = script->buildin[script->str_data[script->buildin_callsub_ref].val];
+
+ if (*arg == 0) {
+ disp_error_message("script:parse_callfunc: callsub has no arguments, please review its definition", p);
+ }
+
+ if (*arg != '*') {
+ ++arg; // count func as argument
+ }
+ } else {
#ifdef SCRIPT_CALLFUNC_CHECK
- const char* name = script->get_str(func);
- if( !is_custom && strdb_get(script->userfunc_db, name) == NULL ) {
+ const char *name = script->get_str(func);
+ if (is_custom == 0 && strdb_get(script->userfunc_db, name) == NULL) {
#endif
- disp_error_message("parse_line: expect command, missing function name or calling undeclared function",p);
+ disp_error_message("script:parse_callfunc: expect command, missing function name or calling undeclared function", p);
#ifdef SCRIPT_CALLFUNC_CHECK
- } else {;
- script->addl(script->buildin_callfunc_ref);
- script->addc(C_ARG);
- script->addc(C_STR);
- while( *name ) script->addb(*name ++);
- script->addb(0);
- arg = script->buildin[script->str_data[script->buildin_callfunc_ref].val];
- if( *arg != '*' ) ++ arg;
- }
+ } else {
+ script->addl(script->buildin_callfunc_ref);
+ script->addc(C_ARG);
+ script->addc(C_STR);
+
+ while (*name != '\0') {
+ script->addb(*name++);
+ }
+
+ script->addb(0);
+ arg = script->buildin[script->str_data[script->buildin_callfunc_ref].val];
+
+ if (*arg != '*') {
+ ++ arg;
+ }
+ }
#endif
+ }
}
p = script->skip_word(p);
p = script->skip_space(p);
script->syntax.curly[script->syntax.curly_count].type = TYPE_ARGLIST;
script->syntax.curly[script->syntax.curly_count].count = 0;
- if( *p == ';' )
- {// <func name> ';'
+
+ if (*p == ';') {
+ // <func name> ';'
script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_NO_PAREN;
- } else if( *p == '(' && *(p2=script->skip_space(p+1)) == ')' )
- {// <func name> '(' ')'
+ } else if (*p == '(' && *(p2 = script->skip_space(p + 1)) == ')') {
+ // <func name> '(' ')'
script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_PAREN;
p = p2;
- /*
- } else if( 0 && require_paren && *p != '(' )
- {// <func name>
- script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_NO_PAREN;
- */
- } else {// <func name> <arg list>
- if( require_paren ) {
- if( *p != '(' )
- disp_error_message("need '('",p);
+ } else {
+ // <func name> <arg list>
+ if (require_paren == 1) {
+ if (*p != '(') {
+ disp_error_message("script:parse_callfunc: need '('", p);
+ }
+
++p; // skip '('
script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_PAREN;
} else if( *p == '(' ) {
@@ -928,41 +983,65 @@ static const char *parse_callfunc(const char *p, int require_paren, int is_custo
} else {
script->syntax.curly[script->syntax.curly_count].flag = ARGLIST_NO_PAREN;
}
+
++script->syntax.curly_count;
- while( *arg ) {
- p2=script->parse_subexpr(p,-1);
- if( p == p2 )
- break; // not an argument
- if( *arg != '*' )
- ++arg; // next argument
- p=script->skip_space(p2);
- if( *arg == 0 || *p != ',' )
- break; // no more arguments
+ while (*arg != '\0') {
+ p2 = script->parse_subexpr(p, -1);
+
+ if (p == p2) {
+ // not an argument
+ break;
+ }
+
+ if (*arg != '*') {
+ // next argument
+ ++arg;
+ }
+
+ p = script->skip_space(p2);
+
+ if (*arg == 0 || *p != ',') {
+ // no more arguments
+ break;
+ }
+
++p; // skip comma
}
+
--script->syntax.curly_count;
}
- if( arg && *arg && *arg != '?' && *arg != '*' )
- disp_error_message2("parse_callfunc: not enough arguments, expected ','", p, script->config.warn_func_mismatch_paramnum);
- if( script->syntax.curly[script->syntax.curly_count].type != TYPE_ARGLIST )
- disp_error_message("parse_callfunc: DEBUG last curly is not an argument list",p);
- if( script->syntax.curly[script->syntax.curly_count].flag == ARGLIST_PAREN ) {
- if( *p != ')' )
- disp_error_message("parse_callfunc: expected ')' to close argument list",p);
+
+ if (arg != NULL && *arg != '\0' && *arg != '?' && *arg != '*') {
+ disp_error_message2("script:parse_callfunc: not enough arguments, expected ','", p, script->config.warn_func_mismatch_paramnum);
+ }
+
+ if (script->syntax.curly[script->syntax.curly_count].type != TYPE_ARGLIST) {
+ disp_error_message("parse_callfunc: DEBUG last curly is not an argument list", p);
+ }
+
+ if (script->syntax.curly[script->syntax.curly_count].flag == ARGLIST_PAREN) {
+ if (*p != ')') {
+ disp_error_message("script:parse_callfunc: expected ')' to close argument list", p);
+ }
+
++p;
- if (script->str_data[func].val == script->buildin_lang_macro_offset)
+ if (script->str_data[func].val == script->buildin_lang_macro_offset) {
script->syntax.lang_macro_active = false;
- else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset)
+ } else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset) {
script->syntax.lang_macro_fmtstring_active = false;
+ }
}
if (!macro) {
- if (0 == --script->syntax.nested_call)
+ if (0 == --script->syntax.nested_call) {
script->syntax.last_func = -1;
+ }
+
script->addc(C_FUNC);
}
+
return p;
}
@@ -1230,16 +1309,29 @@ static int script_string_dup(char *str)
*------------------------------------------*/
static const char *parse_simpleexpr(const char *p)
{
- p=script->skip_space(p);
+ p = script->skip_space(p);
nullpo_retr(NULL, p);
- if (*p == ';' || *p == ',')
- disp_error_message("parse_simpleexpr: unexpected end of expression",p);
+
+ if (*p == ';' || *p == ',') {
+ disp_error_message("script:parse_simpleexpr: unexpected end of expression", p);
+ }
+
if (*p == '(') {
return script->parse_simpleexpr_paren(p);
} else if (is_number(p)) {
return script->parse_simpleexpr_number(p);
} else if(*p == '"') {
+ const char *p2 = p + 1;
+
+ while (*p2 != '"') {
+ ++p2;
+ }
+
+ if (p2[1] == ':' && p2[2] == ':') {
+ return script->parse_callfunc(p, 1, 0); // XXX: why does callfunc use int for booleans?
+ }
+
return script->parse_simpleexpr_string(p);
} else {
return script->parse_simpleexpr_name(p);
@@ -1577,6 +1669,85 @@ static const char *parse_line(const char *p)
return p;
}
+/**
+ * parses a local function expression
+ *
+ * expects these formats:
+ * function <name>;
+ * function <name> { <script> }
+ *
+ * this is invoked by script->parse_syntax() after checking whether the function
+ * is public or not
+ *
+ * @param p - a pointer to the start of the function expression
+ * @param is_public - whether this function should be accessible from outside the NPC scope
+ */
+static const char *parse_syntax_function (const char *p, bool is_public)
+{
+ const char *func_name = script->skip_space(p); // the name of the local function
+ p = script->skip_word(func_name);
+
+ if (p == func_name) {
+ disp_error_message("script:parse_syntax_function: function name is missing or invalid", p);
+ }
+
+ const char *p2 = script->skip_space(p);
+
+ if (*p2 == ';') {
+ // function <name> ;
+ // function declaration - just register the name
+ int l = script->add_word(func_name);
+
+ if (script->str_data[l].type == C_NOP) {
+ // register only, if the name was not used by something else
+ script->str_data[l].type = C_USERFUNC;
+ } else if (script->str_data[l].type != C_USERFUNC) {
+ disp_error_message("script:parse_syntax_function: function name is already in use", func_name);
+ }
+
+ // Close condition of if, for, while
+ p = script->parse_syntax_close(p2 + 1);
+ return p;
+ } else if (*p2 == '{') {
+ // function <name> <line/block of code>
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_USERFUNC;
+ script->syntax.curly[script->syntax.curly_count].count = 1;
+ script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++;
+ script->syntax.curly[script->syntax.curly_count].flag = 0;
+ ++script->syntax.curly_count;
+
+ // Jump over the function code
+ char label[256];
+ sprintf(label, "goto __FN%x_FIN;", (unsigned int)script->syntax.curly[script->syntax.curly_count - 1].index);
+ script->syntax.curly[script->syntax.curly_count].type = TYPE_NULL;
+ ++script->syntax.curly_count;
+ script->parse_line(label);
+ --script->syntax.curly_count;
+
+ // Set the position of the function (label)
+ int l = script->add_word(func_name);
+
+ if (script->str_data[l].type == C_NOP || script->str_data[l].type == C_USERFUNC) {
+ // register only, if the name was not used by something else
+ script->str_data[l].type = C_USERFUNC;
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
+
+ if ((script->parse_options & SCRIPT_USE_LABEL_DB) != 0) {
+ script->label_add(l, VECTOR_LENGTH(script->buf),
+ LABEL_IS_USERFUNC | (is_public ? LABEL_IS_EXTERN : 0));
+ }
+ } else {
+ disp_error_message("script:parse_syntax_function: function name is already in use", func_name);
+ }
+
+ return script->skip_space(p);
+ } else {
+ disp_error_message("script:parse_syntax_function: expected ';' or '{' at function syntax", p);
+ }
+
+ return p;
+}
+
// { ... } Closing process
static const char *parse_curly_close(const char *p)
{
@@ -1920,65 +2091,11 @@ static const char *parse_syntax(const char *p)
script->set_label(l, VECTOR_LENGTH(script->buf), p);
return p;
} else if( p2 - p == 8 && strncmp(p, "function", 8) == 0 ) {
- // internal script function
- const char *func_name;
-
- func_name = script->skip_space(p2);
- p = script->skip_word(func_name);
- if( p == func_name )
- disp_error_message("parse_syntax:function: function name is missing or invalid", p);
- p2 = script->skip_space(p);
- if( *p2 == ';' )
- {// function <name> ;
- // function declaration - just register the name
- int l;
- l = script->add_word(func_name);
- if( script->str_data[l].type == C_NOP )// register only, if the name was not used by something else
- script->str_data[l].type = C_USERFUNC;
- else if( script->str_data[l].type == C_USERFUNC )
- ; // already registered
- else
- disp_error_message("parse_syntax:function: function name is invalid", func_name);
-
- // Close condition of if, for, while
- p = script->parse_syntax_close(p2 + 1);
- return p;
- }
- else if(*p2 == '{')
- {// function <name> <line/block of code>
- char label[256];
- int l;
-
- script->syntax.curly[script->syntax.curly_count].type = TYPE_USERFUNC;
- script->syntax.curly[script->syntax.curly_count].count = 1;
- script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++;
- script->syntax.curly[script->syntax.curly_count].flag = 0;
- ++script->syntax.curly_count;
-
- // Jump over the function code
- sprintf(label, "goto __FN%x_FIN;", (unsigned int)script->syntax.curly[script->syntax.curly_count-1].index);
- script->syntax.curly[script->syntax.curly_count].type = TYPE_NULL;
- ++script->syntax.curly_count;
- script->parse_line(label);
- --script->syntax.curly_count;
-
- // Set the position of the function (label)
- l=script->add_word(func_name);
- if( script->str_data[l].type == C_NOP || script->str_data[l].type == C_USERFUNC )// register only, if the name was not used by something else
- {
- script->str_data[l].type = C_USERFUNC;
- script->set_label(l, VECTOR_LENGTH(script->buf), p);
- if( script->parse_options&SCRIPT_USE_LABEL_DB )
- script->label_add(l, VECTOR_LENGTH(script->buf));
- }
- else
- disp_error_message("parse_syntax:function: function name is invalid", func_name);
-
- return script->skip_space(p);
- }
- else
- {
- disp_error_message("expect ';' or '{' at function syntax",p);
+ // local function not marked as public or private
+ if (script->config.functions_private_by_default) {
+ return script->parse_syntax_function(p2, false);
+ } else {
+ return script->parse_syntax_function(p2, true);
}
}
break;
@@ -2006,6 +2123,26 @@ static const char *parse_syntax(const char *p)
return p;
}
break;
+ case 'p':
+ case 'P':
+ if (p2 - p == 6 && strncmp(p, "public", 6) == 0) {
+ p2 = script->skip_space(p2);
+ const char *p3 = script->skip_word(p2);
+
+ if (p3 - p2 == 8 && strncmp(p2, "function", 8) == 0) {
+ // local function explicitly marked as public
+ return script->parse_syntax_function(p3, true);
+ }
+ } else if (p2 - p == 7 && strncmp(p, "private", 7) == 0) {
+ p2 = script->skip_space(p2);
+ const char *p3 = script->skip_word(p2);
+
+ if (p3 - p2 == 8 && strncmp(p2, "function", 8) == 0) {
+ // local function explicitly marked as private
+ return script->parse_syntax_function(p3, false);
+ }
+ }
+ break;
case 's':
case 'S':
if( p2 - p == 6 && strncmp(p, "switch", 6) == 0 ) {
@@ -2668,25 +2805,32 @@ static struct script_code *parse_script(const char *src, const char *file, int l
}
}
- while( script->syntax.curly_count != 0 || *p != end )
- {
- if( *p == '\0' )
- disp_error_message("unexpected end of script",p);
+ while (script->syntax.curly_count != 0 || *p != end) {
+ if (*p == '\0') {
+ disp_error_message("script:parse_script: unexpected end of script", p);
+ }
+
// Special handling only label
- tmpp=script->skip_space(script->skip_word(p));
- if(*tmpp==':' && !(strncmp(p,"default:",8) == 0 && p + 7 == tmpp)) {
- i=script->add_word(p);
+ tmpp = script->skip_space(script->skip_word(p));
+
+ if (*tmpp == ':' && !(strncmp(p, "default:", 8) == 0 && p + 7 == tmpp)
+ && !(strncmp(p, "function", 8) == 0 && script->skip_space(p + 8) == tmpp)) {
+ i = script->add_word(p);
script->set_label(i, VECTOR_LENGTH(script->buf), p);
- if( script->parse_options&SCRIPT_USE_LABEL_DB )
- script->label_add(i, VECTOR_LENGTH(script->buf));
- p=tmpp+1;
- p=script->skip_space(p);
+
+ if ((script->parse_options & SCRIPT_USE_LABEL_DB) != 0) {
+ bool is_extern = ((p[0] == 'O' || p[0] == 'o') && (p[1] == 'N' || p[1] == 'n'));
+ script->label_add(i, VECTOR_LENGTH(script->buf), is_extern ? LABEL_IS_EXTERN : 0);
+ }
+
+ p = tmpp + 1;
+ p = script->skip_space(p);
continue;
}
// All other lumped
- p=script->parse_line(p);
- p=script->skip_space(p);
+ p = script->parse_line(p);
+ p = script->skip_space(p);
script->parse_nextline(false, p);
}
@@ -4866,6 +5010,8 @@ static bool script_config_read(const char *filename, bool imported)
libconfig->setting_lookup_bool_real(setting, "warn_func_mismatch_paramnum", &script->config.warn_func_mismatch_paramnum);
libconfig->setting_lookup_bool_real(setting, "warn_func_mismatch_argtypes", &script->config.warn_func_mismatch_argtypes);
+ libconfig->setting_lookup_bool_real(setting, "functions_private_by_default", &script->config.functions_private_by_default);
+ libconfig->setting_lookup_bool_real(setting, "functions_as_events", &script->config.functions_as_events);
libconfig->setting_lookup_int(setting, "check_cmdcount", &script->config.check_cmdcount);
libconfig->setting_lookup_int(setting, "check_gotocount", &script->config.check_gotocount);
libconfig->setting_lookup_int(setting, "input_min_value", &script->config.input_min_value);
@@ -6435,6 +6581,111 @@ static BUILDIN(callfunc)
return true;
}
+
+/**
+ * Calls a local function within a NPC as if it was part of the current scope.
+ * Resumes execution in the previous scope once the NPC function returns. This
+ * is essentially a clone of buildin_callsub that can run in arbitrary NPCs.
+ *
+ * Usage:
+ * callfunctionofnpc("<npc name>", "<function name>"{, <arg>...})
+ * callfunctionofnpc(<npc id>, "<function name>"{, <arg>...})
+ *
+ * This buildin is also used internally by this syntax:
+ * "<npc name>"::<function name>({<arg>...})
+ */
+static BUILDIN(callfunctionofnpc) {
+ struct npc_data *nd = NULL;
+
+ if (script_isstring(st, 2)) {
+ nd = npc->name2id(script_getstr(st, 2));
+ } else {
+ nd = map->id2nd(script_getnum(st, 2));
+ }
+
+ if (nd == NULL) {
+ ShowError("script:callfunctionofnpc: NPC not found.\n");
+ st->state = END;
+ return false;
+ }
+
+ const char *function_name = script_getstr(st, 3);
+ int pos = -1;
+
+ // find the function label within the label list of the NPC
+ for (int i = 0; i < nd->u.scr.label_list_num; ++i) {
+ if (strcmp(nd->u.scr.label_list[i].name, function_name) == 0) {
+ if ((nd->u.scr.label_list[i].flags & LABEL_IS_EXTERN) != 0
+ && (nd->u.scr.label_list[i].flags & LABEL_IS_USERFUNC) != 0) {
+ // function label found: set the start location
+ pos = nd->u.scr.label_list[i].pos;
+ } else if ((nd->u.scr.label_list[i].flags & LABEL_IS_USERFUNC) != 0) {
+ ShowError("script:callfunctionofnpc: function '%s' is not marked as public in NPC '%s'.\n", function_name, nd->name);
+ st->state = END;
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (pos < 0) {
+ ShowError("script:callfunctionofnpc: function '%s' not found in NPC '%s'!\n", function_name, nd->name);
+ st->state = END;
+ return false;
+ }
+
+ // alloc a reg_db reference of the current scope for the new scope
+ struct reg_db *ref = (struct reg_db *)aCalloc(sizeof(struct reg_db), 2);
+ // scope variables (.@var)
+ ref[0].vars = st->stack->scope.vars;
+ ref[0].arrays = st->stack->scope.arrays;
+ // npc variables (.var)
+ ref[1].vars = st->script->local.vars;
+ ref[1].arrays = st->script->local.arrays;
+
+ int i = 0;
+
+ // make sure the arguments we push retain their current reg_db references:
+ // this allows to do things like set(getarg(0), ...)
+ for (i = st->start + 4; i < st->end; i++) {
+ struct script_data *data = script->push_copy(st->stack, i);
+
+ if (data_isreference(data) && data->ref == NULL) {
+ const char *name = reference_getname(data);
+
+ if (name[0] == '.') {
+ data->ref = (name[1] == '@' ? &ref[0] : &ref[1]);
+ }
+ }
+ }
+
+ // save the previous scope
+ struct script_retinfo *ri = NULL;
+ CREATE(ri, struct script_retinfo, 1);
+ ri->script = st->script; // script code
+ ri->scope.vars = st->stack->scope.vars; // scope variables
+ ri->scope.arrays = st->stack->scope.arrays; // scope arrays
+ ri->pos = st->pos; // script location
+ ri->nargs = i - st->start - 4; // argument count
+ ri->defsp = st->stack->defsp; // default stack pointer
+ script->push_retinfo(st->stack, ri, ref);
+
+ // change the current scope to the scope of the function
+ st->pos = pos;
+ st->script = nd->u.scr.script;
+ st->stack->defsp = st->stack->sp;
+ st->state = GOTO;
+ st->stack->scope.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+ st->stack->scope.arrays = idb_alloc(DB_OPT_BASE);
+
+ // make sure local reg_db of the other NPC is initialized
+ if (st->script->local.vars == NULL) {
+ st->script->local.vars = i64db_alloc(DB_OPT_RELEASE_DATA);
+ }
+
+ return true;
+}
+
/*==========================================
* subroutine call
*------------------------------------------*/
@@ -27428,6 +27679,8 @@ static void script_parse_builtin(void)
BUILDIN_DEF(identify, "i"),
BUILDIN_DEF(identifyidx, "i"),
BUILDIN_DEF(openlapineddukddakboxui, "i"),
+
+ BUILDIN_DEF(callfunctionofnpc, "vs*"),
};
int i, len = ARRAYLENGTH(BUILDIN);
RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up
@@ -27439,7 +27692,7 @@ static void script_parse_builtin(void)
#undef BUILDIN_DEF
#undef BUILDIN_DEF2
-static void script_label_add(int key, int pos)
+static void script_label_add(int key, int pos, enum script_label_flags flags)
{
int idx = script->label_count;
@@ -27450,6 +27703,7 @@ static void script_label_add(int key, int pos)
script->labels[idx].key = key;
script->labels[idx].pos = pos;
+ script->labels[idx].flags = flags;
script->label_count++;
}
@@ -27868,6 +28122,7 @@ static void script_hardcoded_constants(void)
script->set_constant("MSC_MASTERATTACKED", MSC_MASTERATTACKED, false, false);
script->set_constant("MSC_ALCHEMIST", MSC_ALCHEMIST, false, false);
script->set_constant("MSC_SPAWN", MSC_SPAWN, false, false);
+ script->set_constant("MSC_MAGICATTACKED", MSC_MAGICATTACKED, false, false);
script->constdb_comment("monster skill targets");
script->set_constant("MST_TARGET", MST_TARGET, false, false);
@@ -28261,6 +28516,7 @@ void script_defaults(void)
script->parse_syntax_close = parse_syntax_close;
script->parse_syntax_close_sub = parse_syntax_close_sub;
script->parse_syntax = parse_syntax;
+ script->parse_syntax_function = parse_syntax_function;
script->get_com = get_com;
script->get_num = get_num;
script->op2name = script_op2name;
@@ -28365,6 +28621,8 @@ void script_defaults(void)
script->config.ontouch_name = "OnTouch_"; //ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves)
script->config.ontouch2_name = "OnTouch"; //ontouch2_name (run whenever a char walks into the OnTouch area)
script->config.onuntouch_name = "OnUnTouch"; //onuntouch_name (run whenever a char walks from the OnTouch area)
+ script->config.functions_private_by_default = true;
+ script->config.functions_as_events = false;
// for ENABLE_CASE_CHECK
script->calc_hash_ci = calc_hash_ci;
diff --git a/src/map/script.h b/src/map/script.h
index 5fa81dc0e..df5297ac0 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -584,6 +584,8 @@ enum itemskill_flag {
struct Script_Config {
bool warn_func_mismatch_argtypes;
bool warn_func_mismatch_paramnum;
+ bool functions_private_by_default;
+ bool functions_as_events;
int check_cmdcount;
int check_gotocount;
int input_min_value;
@@ -725,8 +727,14 @@ struct str_data_struct {
uint8 deprecated : 1;
};
+/** a label within a script (does not use the label db) */
struct script_label_entry {
- int key,pos;
+ /** label name (held within str_data) */
+ int key;
+ /** position within the script */
+ int pos;
+ /** optional flags for the label */
+ enum script_label_flags flags;
};
struct script_syntax_data {
@@ -917,7 +925,7 @@ struct script_interface {
void (*set_constant) (const char *name, int value, bool is_parameter, bool is_deprecated);
void (*set_constant2) (const char *name, int value, bool is_parameter, bool is_deprecated);
bool (*get_constant) (const char* name, int* value);
- void (*label_add)(int key, int pos);
+ void (*label_add)(int key, int pos, enum script_label_flags flags);
void (*run) (struct script_code *rootscript, int pos, int rid, int oid);
void (*run_npc) (struct script_code *rootscript, int pos, int rid, int oid);
void (*run_pet) (struct script_code *rootscript, int pos, int rid, int oid);
@@ -948,10 +956,11 @@ struct script_interface {
int (*queue_create) (void);
bool (*queue_clear) (int idx);
/* */
- const char * (*parse_curly_close) (const char *p);
- const char * (*parse_syntax_close) (const char *p);
- const char * (*parse_syntax_close_sub) (const char *p, int *flag);
- const char * (*parse_syntax) (const char *p);
+ const char *(*parse_curly_close) (const char *p);
+ const char *(*parse_syntax_close) (const char *p);
+ const char *(*parse_syntax_close_sub) (const char *p, int *flag);
+ const char *(*parse_syntax) (const char *p);
+ const char *(*parse_syntax_function) (const char *p, bool is_public);
c_op (*get_com) (const struct script_buf *scriptbuf, int *pos);
int (*get_num) (const struct script_buf *scriptbuf, int *pos);
const char* (*op2name) (int op);
diff --git a/src/map/skill.c b/src/map/skill.c
index caa1a0f29..e3fa6b0a1 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -12535,7 +12535,7 @@ static struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16
if (!group->alive_count) {
//No cells? Something that was blocked completely by Land Protector?
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
return NULL;
}
@@ -12651,7 +12651,7 @@ static int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int
unsigned short m = sg->val3;
if( --count <= 0 )
- skill->del_unitgroup(sg,ALC_MARK);
+ skill->del_unitgroup(sg);
if ( map->mapindex2mapid(sg->val3) == sd->bl.m && x == sd->bl.x && y == sd->bl.y )
working = 1;/* we break it because officials break it, lovely stuff. */
@@ -12957,7 +12957,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b
sg->val1--;
}
if (sg->val1 <= 0)
- skill->del_unitgroup(sg, ALC_MARK);
+ skill->del_unitgroup(sg);
break;
case UNT_EVILLAND:
@@ -16644,7 +16644,7 @@ static int skill_clear_group(struct block_list *bl, int flag)
}
for (i=0;i<count;i++)
- skill->del_unitgroup(group[i],ALC_MARK);
+ skill->del_unitgroup(group[i]);
return count;
}
@@ -17292,7 +17292,7 @@ static int skill_delunit(struct skill_unit *su)
map->deliddb(&su->bl);
idb_remove(skill->unit_db, su->bl.id);
if(--group->alive_count==0)
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
return 0;
}
@@ -17351,7 +17351,7 @@ static struct skill_unit_group *skill_initunitgroup(struct block_list *src, int
j = i;
}
}
- skill->del_unitgroup(ud->skillunit[j],ALC_MARK);
+ skill->del_unitgroup(ud->skillunit[j]);
//Since elements must have shifted, we use the last slot.
i = MAX_SKILLUNITGROUP-1;
}
@@ -17390,18 +17390,13 @@ static struct skill_unit_group *skill_initunitgroup(struct block_list *src, int
/*==========================================
*
*------------------------------------------*/
-static int skill_delunitgroup(struct skill_unit_group *group, const char *file, int line, const char *func)
+static int skill_delunitgroup(struct skill_unit_group *group)
{
struct block_list* src;
struct unit_data *ud;
int i,j;
struct map_session_data *sd = NULL;
- if( group == NULL ) {
- ShowDebug("skill_delunitgroup: group is NULL (source=%s:%d, %s)! Please report this! (#3504)\n", file, line, func);
- return 0;
- }
-
src = map->id2bl(group->src_id);
ud = unit->bl2ud(src);
sd = BL_CAST(BL_PC, src);
@@ -17533,7 +17528,7 @@ static int skill_clear_unitgroup(struct block_list *src)
nullpo_ret(ud);
while (ud->skillunit[0])
- skill->del_unitgroup(ud->skillunit[0],ALC_MARK);
+ skill->del_unitgroup(ud->skillunit[0]);
return 1;
}
diff --git a/src/map/skill.h b/src/map/skill.h
index 4dbbaf147..651a355cf 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -2020,7 +2020,7 @@ struct skill_interface {
struct skill_unit *(*initunit) (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2);
int (*delunit) (struct skill_unit *su);
struct skill_unit_group *(*init_unitgroup) (struct block_list* src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval);
- int (*del_unitgroup) (struct skill_unit_group *group, const char* file, int line, const char* func);
+ int (*del_unitgroup) (struct skill_unit_group *group);
int (*clear_unitgroup) (struct block_list *src);
int (*clear_group) (struct block_list *bl, int flag);
int (*unit_onplace) (struct skill_unit *src, struct block_list *bl, int64 tick);
diff --git a/src/map/status.c b/src/map/status.c
index dc49f7e4e..b0cb07d11 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -1201,7 +1201,7 @@ static int status_damage(struct block_list *src, struct block_list *target, int6
if ((sce=sc->data[SC_GRAVITATION]) && sce->val3 == BCT_SELF) {
struct skill_unit_group* sg = skill->id2group(sce->val4);
if (sg) {
- skill->del_unitgroup(sg, ALC_MARK);
+ skill->del_unitgroup(sg);
sce->val4 = 0;
status_change_end(target, SC_GRAVITATION, INVALID_TIMER);
}
@@ -10788,7 +10788,7 @@ static int status_change_clear(struct block_list *bl, int type)
/*==========================================
* Special condition we want to effectuate, check before ending a status.
*------------------------------------------*/
-static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, const char *file, int line)
+static int status_change_end_(struct block_list *bl, enum sc_type type, int tid)
{
struct map_session_data *sd;
struct status_change *sc;
@@ -10958,23 +10958,9 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid,
break;
case SC_DANCING:
{
- const char* prevfile = "<unknown>";
- int prevline = 0;
struct map_session_data *dsd;
struct status_change_entry *dsc;
- if (sd) {
- if (sd->delunit_prevfile) {
- // initially this is NULL, when a character logs in
- prevfile = sd->delunit_prevfile;
- prevline = sd->delunit_prevline;
- } else {
- prevfile = "<none>";
- }
- sd->delunit_prevfile = file;
- sd->delunit_prevline = line;
- }
-
if (sce->val4 && sce->val4 != BCT_SELF && (dsd=map->id2sd(sce->val4)) != NULL) {
// end status on partner as well
dsc = dsd->sc.data[SC_DANCING];
@@ -10990,19 +10976,10 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid,
// erase associated land skill
struct skill_unit_group *group = skill->id2group(sce->val2);
- if (group == NULL) {
- ShowDebug("status_change_end: SC_DANCING is missing skill unit group (val1=%d, val2=%d, val3=%d, val4=%d, timer=%d, tid=%d, char_id=%d, map=%s, x=%d, y=%d, prev=%s:%d, from=%s:%d). Please report this! (#3504)\n",
- sce->val1, sce->val2, sce->val3, sce->val4, sce->timer, tid,
- sd ? sd->status.char_id : 0,
- mapindex_id2name(map_id2index(bl->m)), bl->x, bl->y,
- prevfile, prevline,
- file, line);
- }
-
sce->val2 = 0;
if( group )
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
}
if ((sce->val1&0xFFFF) == CG_MOONLIT)
@@ -11106,7 +11083,7 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid,
struct skill_unit_group* group = skill->id2group(sce->val3);
sce->val3 = 0;
if( group )
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
}
break;
case SC_HERMODE:
@@ -11125,7 +11102,7 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid,
struct skill_unit_group* group = skill->id2group(sce->val4);
sce->val4 = 0;
if( group ) /* might have been cleared before status ended, e.g. land protector */
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
}
break;
case SC_KAAHI:
@@ -11223,7 +11200,7 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid,
struct skill_unit_group* group = skill->id2group(sce->val2);
sce->val2 = 0;
if (group) /* might have been cleared before status ended, e.g. land protector */
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
}
break;
case SC_BANDING:
@@ -11231,7 +11208,7 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid,
struct skill_unit_group *group = skill->id2group(sce->val4);
sce->val4 = 0;
if( group ) /* might have been cleared before status ended, e.g. land protector */
- skill->del_unitgroup(group,ALC_MARK);
+ skill->del_unitgroup(group);
}
break;
case SC_CURSEDCIRCLE_ATKER:
diff --git a/src/map/status.h b/src/map/status.h
index d5cb3da75..43cfd6931 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -1214,7 +1214,7 @@ struct status_change {
#define sc_start2(src, bl, type, rate, val1, val2, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),0,0,(tick),SCFLAG_NONE))
#define sc_start4(src, bl, type, rate, val1, val2, val3, val4, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),(val3),(val4),(tick),SCFLAG_NONE))
-#define status_change_end(bl,type,tid) (status->change_end_((bl),(type),(tid),__FILE__,__LINE__))
+#define status_change_end(bl,type,tid) (status->change_end_((bl),(type),(tid)))
#define status_calc_bl(bl, flag) (status->calc_bl_((bl), (enum scb_flag)(flag), SCO_NONE))
#define status_calc_mob(md, opt) (status->calc_bl_(&(md)->bl, SCB_ALL, (opt)))
@@ -1308,7 +1308,7 @@ struct status_interface {
int (*get_sc_def) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag);
int (*change_start) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag);
int (*change_start_sub) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int total_tick, int flag);
- int (*change_end_) (struct block_list* bl, enum sc_type type, int tid, const char* file, int line);
+ int (*change_end_) (struct block_list* bl, enum sc_type type, int tid);
bool (*is_immune_to_status) (struct status_change* sc, enum sc_type type);
bool (*is_boss_resist_sc) (enum sc_type type);
bool (*end_sc_before_start) (struct block_list *bl, struct status_data *st, struct status_change* sc, enum sc_type type, int undead_flag, int val1, int val2, int val3, int val4);
diff --git a/src/plugins/HPMHooking/HPMHooking.Defs.inc b/src/plugins/HPMHooking/HPMHooking.Defs.inc
index ef71f1967..363727d46 100644
--- a/src/plugins/HPMHooking/HPMHooking.Defs.inc
+++ b/src/plugins/HPMHooking/HPMHooking.Defs.inc
@@ -5224,20 +5224,32 @@ typedef bool (*HPMHOOK_pre_mapit_exists) (struct s_mapiterator **iter);
typedef bool (*HPMHOOK_post_mapit_exists) (bool retVal___, struct s_mapiterator *iter);
#endif // MAP_MAP_H
#ifdef MAP_MAPREG_H /* mapreg */
-typedef void (*HPMHOOK_pre_mapreg_init) (void);
-typedef void (*HPMHOOK_post_mapreg_init) (void);
-typedef void (*HPMHOOK_pre_mapreg_final) (void);
-typedef void (*HPMHOOK_post_mapreg_final) (void);
typedef int (*HPMHOOK_pre_mapreg_readreg) (int64 *uid);
typedef int (*HPMHOOK_post_mapreg_readreg) (int retVal___, int64 uid);
typedef char* (*HPMHOOK_pre_mapreg_readregstr) (int64 *uid);
typedef char* (*HPMHOOK_post_mapreg_readregstr) (char* retVal___, int64 uid);
+typedef bool (*HPMHOOK_pre_mapreg_set_num_db) (int64 *uid, const char **name, unsigned int *index, int *value);
+typedef bool (*HPMHOOK_post_mapreg_set_num_db) (bool retVal___, int64 uid, const char *name, unsigned int index, int value);
+typedef bool (*HPMHOOK_pre_mapreg_delete_num_db) (int64 *uid, const char **name, unsigned int *index);
+typedef bool (*HPMHOOK_post_mapreg_delete_num_db) (bool retVal___, int64 uid, const char *name, unsigned int index);
typedef bool (*HPMHOOK_pre_mapreg_setreg) (int64 *uid, int *val);
typedef bool (*HPMHOOK_post_mapreg_setreg) (bool retVal___, int64 uid, int val);
+typedef bool (*HPMHOOK_pre_mapreg_set_str_db) (int64 *uid, const char **name, unsigned int *index, const char **value);
+typedef bool (*HPMHOOK_post_mapreg_set_str_db) (bool retVal___, int64 uid, const char *name, unsigned int index, const char *value);
+typedef bool (*HPMHOOK_pre_mapreg_delete_str_db) (int64 *uid, const char **name, unsigned int *index);
+typedef bool (*HPMHOOK_post_mapreg_delete_str_db) (bool retVal___, int64 uid, const char *name, unsigned int index);
typedef bool (*HPMHOOK_pre_mapreg_setregstr) (int64 *uid, const char **str);
typedef bool (*HPMHOOK_post_mapreg_setregstr) (bool retVal___, int64 uid, const char *str);
+typedef void (*HPMHOOK_pre_mapreg_load_num_db) (void);
+typedef void (*HPMHOOK_post_mapreg_load_num_db) (void);
+typedef void (*HPMHOOK_pre_mapreg_load_str_db) (void);
+typedef void (*HPMHOOK_post_mapreg_load_str_db) (void);
typedef void (*HPMHOOK_pre_mapreg_load) (void);
typedef void (*HPMHOOK_post_mapreg_load) (void);
+typedef void (*HPMHOOK_pre_mapreg_save_num_db) (const char **name, unsigned int *index, int *value);
+typedef void (*HPMHOOK_post_mapreg_save_num_db) (const char *name, unsigned int index, int value);
+typedef void (*HPMHOOK_pre_mapreg_save_str_db) (const char **name, unsigned int *index, const char **value);
+typedef void (*HPMHOOK_post_mapreg_save_str_db) (const char *name, unsigned int index, const char *value);
typedef void (*HPMHOOK_pre_mapreg_save) (void);
typedef void (*HPMHOOK_post_mapreg_save) (void);
typedef int (*HPMHOOK_pre_mapreg_save_timer) (int *tid, int64 *tick, int *id, intptr_t *data);
@@ -5246,8 +5258,12 @@ typedef int (*HPMHOOK_pre_mapreg_destroyreg) (union DBKey *key, struct DBData **
typedef int (*HPMHOOK_post_mapreg_destroyreg) (int retVal___, union DBKey key, struct DBData *data, va_list ap);
typedef void (*HPMHOOK_pre_mapreg_reload) (void);
typedef void (*HPMHOOK_post_mapreg_reload) (void);
-typedef bool (*HPMHOOK_pre_mapreg_config_read) (const char **filename, const struct config_setting_t **config, bool *imported);
-typedef bool (*HPMHOOK_post_mapreg_config_read) (bool retVal___, const char *filename, const struct config_setting_t *config, bool imported);
+typedef bool (*HPMHOOK_pre_mapreg_config_read_registry) (const char **filename, const struct config_setting_t **config, bool *imported);
+typedef bool (*HPMHOOK_post_mapreg_config_read_registry) (bool retVal___, const char *filename, const struct config_setting_t *config, bool imported);
+typedef void (*HPMHOOK_pre_mapreg_final) (void);
+typedef void (*HPMHOOK_post_mapreg_final) (void);
+typedef void (*HPMHOOK_pre_mapreg_init) (void);
+typedef void (*HPMHOOK_post_mapreg_init) (void);
#endif // MAP_MAPREG_H
#ifdef COMMON_MD5CALC_H /* md5 */
typedef void (*HPMHOOK_pre_md5_string) (const char **string, char **output);
@@ -6858,8 +6874,8 @@ typedef void (*HPMHOOK_pre_script_set_constant2) (const char **name, int *value,
typedef void (*HPMHOOK_post_script_set_constant2) (const char *name, int value, bool is_parameter, bool is_deprecated);
typedef bool (*HPMHOOK_pre_script_get_constant) (const char **name, int **value);
typedef bool (*HPMHOOK_post_script_get_constant) (bool retVal___, const char *name, int *value);
-typedef void (*HPMHOOK_pre_script_label_add) (int *key, int *pos);
-typedef void (*HPMHOOK_post_script_label_add) (int key, int pos);
+typedef void (*HPMHOOK_pre_script_label_add) (int *key, int *pos, enum script_label_flags *flags);
+typedef void (*HPMHOOK_post_script_label_add) (int key, int pos, enum script_label_flags flags);
typedef void (*HPMHOOK_pre_script_run) (struct script_code **rootscript, int *pos, int *rid, int *oid);
typedef void (*HPMHOOK_post_script_run) (struct script_code *rootscript, int pos, int rid, int oid);
typedef void (*HPMHOOK_pre_script_run_npc) (struct script_code **rootscript, int *pos, int *rid, int *oid);
@@ -6924,6 +6940,8 @@ typedef const char* (*HPMHOOK_pre_script_parse_syntax_close_sub) (const char **p
typedef const char* (*HPMHOOK_post_script_parse_syntax_close_sub) (const char* retVal___, const char *p, int *flag);
typedef const char* (*HPMHOOK_pre_script_parse_syntax) (const char **p);
typedef const char* (*HPMHOOK_post_script_parse_syntax) (const char* retVal___, const char *p);
+typedef const char* (*HPMHOOK_pre_script_parse_syntax_function) (const char **p, bool *is_public);
+typedef const char* (*HPMHOOK_post_script_parse_syntax_function) (const char* retVal___, const char *p, bool is_public);
typedef c_op (*HPMHOOK_pre_script_get_com) (const struct script_buf **scriptbuf, int **pos);
typedef c_op (*HPMHOOK_post_script_get_com) (c_op retVal___, const struct script_buf *scriptbuf, int *pos);
typedef int (*HPMHOOK_pre_script_get_num) (const struct script_buf **scriptbuf, int **pos);
@@ -7338,8 +7356,8 @@ typedef int (*HPMHOOK_pre_skill_delunit) (struct skill_unit **su);
typedef int (*HPMHOOK_post_skill_delunit) (int retVal___, struct skill_unit *su);
typedef struct skill_unit_group* (*HPMHOOK_pre_skill_init_unitgroup) (struct block_list **src, int *count, uint16 *skill_id, uint16 *skill_lv, int *unit_id, int *limit, int *interval);
typedef struct skill_unit_group* (*HPMHOOK_post_skill_init_unitgroup) (struct skill_unit_group* retVal___, struct block_list *src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval);
-typedef int (*HPMHOOK_pre_skill_del_unitgroup) (struct skill_unit_group **group, const char **file, int *line, const char **func);
-typedef int (*HPMHOOK_post_skill_del_unitgroup) (int retVal___, struct skill_unit_group *group, const char *file, int line, const char *func);
+typedef int (*HPMHOOK_pre_skill_del_unitgroup) (struct skill_unit_group **group);
+typedef int (*HPMHOOK_post_skill_del_unitgroup) (int retVal___, struct skill_unit_group *group);
typedef int (*HPMHOOK_pre_skill_clear_unitgroup) (struct block_list **src);
typedef int (*HPMHOOK_post_skill_clear_unitgroup) (int retVal___, struct block_list *src);
typedef int (*HPMHOOK_pre_skill_clear_group) (struct block_list **bl, int *flag);
@@ -7898,8 +7916,8 @@ typedef int (*HPMHOOK_pre_status_change_start) (struct block_list **src, struct
typedef int (*HPMHOOK_post_status_change_start) (int retVal___, struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag);
typedef int (*HPMHOOK_pre_status_change_start_sub) (struct block_list **src, struct block_list **bl, enum sc_type *type, int *rate, int *val1, int *val2, int *val3, int *val4, int *tick, int *total_tick, int *flag);
typedef int (*HPMHOOK_post_status_change_start_sub) (int retVal___, struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int total_tick, int flag);
-typedef int (*HPMHOOK_pre_status_change_end_) (struct block_list **bl, enum sc_type *type, int *tid, const char **file, int *line);
-typedef int (*HPMHOOK_post_status_change_end_) (int retVal___, struct block_list *bl, enum sc_type type, int tid, const char *file, int line);
+typedef int (*HPMHOOK_pre_status_change_end_) (struct block_list **bl, enum sc_type *type, int *tid);
+typedef int (*HPMHOOK_post_status_change_end_) (int retVal___, struct block_list *bl, enum sc_type type, int tid);
typedef bool (*HPMHOOK_pre_status_is_immune_to_status) (struct status_change **sc, enum sc_type *type);
typedef bool (*HPMHOOK_post_status_is_immune_to_status) (bool retVal___, struct status_change *sc, enum sc_type type);
typedef bool (*HPMHOOK_pre_status_is_boss_resist_sc) (enum sc_type *type);
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
index e8cb41240..df3a28bcb 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
@@ -3828,20 +3828,32 @@ struct {
struct HPMHookPoint *HP_mapit_prev_post;
struct HPMHookPoint *HP_mapit_exists_pre;
struct HPMHookPoint *HP_mapit_exists_post;
- struct HPMHookPoint *HP_mapreg_init_pre;
- struct HPMHookPoint *HP_mapreg_init_post;
- struct HPMHookPoint *HP_mapreg_final_pre;
- struct HPMHookPoint *HP_mapreg_final_post;
struct HPMHookPoint *HP_mapreg_readreg_pre;
struct HPMHookPoint *HP_mapreg_readreg_post;
struct HPMHookPoint *HP_mapreg_readregstr_pre;
struct HPMHookPoint *HP_mapreg_readregstr_post;
+ struct HPMHookPoint *HP_mapreg_set_num_db_pre;
+ struct HPMHookPoint *HP_mapreg_set_num_db_post;
+ struct HPMHookPoint *HP_mapreg_delete_num_db_pre;
+ struct HPMHookPoint *HP_mapreg_delete_num_db_post;
struct HPMHookPoint *HP_mapreg_setreg_pre;
struct HPMHookPoint *HP_mapreg_setreg_post;
+ struct HPMHookPoint *HP_mapreg_set_str_db_pre;
+ struct HPMHookPoint *HP_mapreg_set_str_db_post;
+ struct HPMHookPoint *HP_mapreg_delete_str_db_pre;
+ struct HPMHookPoint *HP_mapreg_delete_str_db_post;
struct HPMHookPoint *HP_mapreg_setregstr_pre;
struct HPMHookPoint *HP_mapreg_setregstr_post;
+ struct HPMHookPoint *HP_mapreg_load_num_db_pre;
+ struct HPMHookPoint *HP_mapreg_load_num_db_post;
+ struct HPMHookPoint *HP_mapreg_load_str_db_pre;
+ struct HPMHookPoint *HP_mapreg_load_str_db_post;
struct HPMHookPoint *HP_mapreg_load_pre;
struct HPMHookPoint *HP_mapreg_load_post;
+ struct HPMHookPoint *HP_mapreg_save_num_db_pre;
+ struct HPMHookPoint *HP_mapreg_save_num_db_post;
+ struct HPMHookPoint *HP_mapreg_save_str_db_pre;
+ struct HPMHookPoint *HP_mapreg_save_str_db_post;
struct HPMHookPoint *HP_mapreg_save_pre;
struct HPMHookPoint *HP_mapreg_save_post;
struct HPMHookPoint *HP_mapreg_save_timer_pre;
@@ -3850,8 +3862,12 @@ struct {
struct HPMHookPoint *HP_mapreg_destroyreg_post;
struct HPMHookPoint *HP_mapreg_reload_pre;
struct HPMHookPoint *HP_mapreg_reload_post;
- struct HPMHookPoint *HP_mapreg_config_read_pre;
- struct HPMHookPoint *HP_mapreg_config_read_post;
+ struct HPMHookPoint *HP_mapreg_config_read_registry_pre;
+ struct HPMHookPoint *HP_mapreg_config_read_registry_post;
+ struct HPMHookPoint *HP_mapreg_final_pre;
+ struct HPMHookPoint *HP_mapreg_final_post;
+ struct HPMHookPoint *HP_mapreg_init_pre;
+ struct HPMHookPoint *HP_mapreg_init_post;
struct HPMHookPoint *HP_md5_string_pre;
struct HPMHookPoint *HP_md5_string_post;
struct HPMHookPoint *HP_md5_binary_pre;
@@ -5454,6 +5470,8 @@ struct {
struct HPMHookPoint *HP_script_parse_syntax_close_sub_post;
struct HPMHookPoint *HP_script_parse_syntax_pre;
struct HPMHookPoint *HP_script_parse_syntax_post;
+ struct HPMHookPoint *HP_script_parse_syntax_function_pre;
+ struct HPMHookPoint *HP_script_parse_syntax_function_post;
struct HPMHookPoint *HP_script_get_com_pre;
struct HPMHookPoint *HP_script_get_com_post;
struct HPMHookPoint *HP_script_get_num_pre;
@@ -10729,20 +10747,32 @@ struct {
int HP_mapit_prev_post;
int HP_mapit_exists_pre;
int HP_mapit_exists_post;
- int HP_mapreg_init_pre;
- int HP_mapreg_init_post;
- int HP_mapreg_final_pre;
- int HP_mapreg_final_post;
int HP_mapreg_readreg_pre;
int HP_mapreg_readreg_post;
int HP_mapreg_readregstr_pre;
int HP_mapreg_readregstr_post;
+ int HP_mapreg_set_num_db_pre;
+ int HP_mapreg_set_num_db_post;
+ int HP_mapreg_delete_num_db_pre;
+ int HP_mapreg_delete_num_db_post;
int HP_mapreg_setreg_pre;
int HP_mapreg_setreg_post;
+ int HP_mapreg_set_str_db_pre;
+ int HP_mapreg_set_str_db_post;
+ int HP_mapreg_delete_str_db_pre;
+ int HP_mapreg_delete_str_db_post;
int HP_mapreg_setregstr_pre;
int HP_mapreg_setregstr_post;
+ int HP_mapreg_load_num_db_pre;
+ int HP_mapreg_load_num_db_post;
+ int HP_mapreg_load_str_db_pre;
+ int HP_mapreg_load_str_db_post;
int HP_mapreg_load_pre;
int HP_mapreg_load_post;
+ int HP_mapreg_save_num_db_pre;
+ int HP_mapreg_save_num_db_post;
+ int HP_mapreg_save_str_db_pre;
+ int HP_mapreg_save_str_db_post;
int HP_mapreg_save_pre;
int HP_mapreg_save_post;
int HP_mapreg_save_timer_pre;
@@ -10751,8 +10781,12 @@ struct {
int HP_mapreg_destroyreg_post;
int HP_mapreg_reload_pre;
int HP_mapreg_reload_post;
- int HP_mapreg_config_read_pre;
- int HP_mapreg_config_read_post;
+ int HP_mapreg_config_read_registry_pre;
+ int HP_mapreg_config_read_registry_post;
+ int HP_mapreg_final_pre;
+ int HP_mapreg_final_post;
+ int HP_mapreg_init_pre;
+ int HP_mapreg_init_post;
int HP_md5_string_pre;
int HP_md5_string_post;
int HP_md5_binary_pre;
@@ -12355,6 +12389,8 @@ struct {
int HP_script_parse_syntax_close_sub_post;
int HP_script_parse_syntax_pre;
int HP_script_parse_syntax_post;
+ int HP_script_parse_syntax_function_pre;
+ int HP_script_parse_syntax_function_post;
int HP_script_get_com_pre;
int HP_script_get_com_post;
int HP_script_get_num_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
index 6b89841ad..3720e8a51 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
@@ -1960,18 +1960,26 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(mapit->prev, HP_mapit_prev) },
{ HP_POP(mapit->exists, HP_mapit_exists) },
/* mapreg_interface */
- { HP_POP(mapreg->init, HP_mapreg_init) },
- { HP_POP(mapreg->final, HP_mapreg_final) },
{ HP_POP(mapreg->readreg, HP_mapreg_readreg) },
{ HP_POP(mapreg->readregstr, HP_mapreg_readregstr) },
+ { HP_POP(mapreg->set_num_db, HP_mapreg_set_num_db) },
+ { HP_POP(mapreg->delete_num_db, HP_mapreg_delete_num_db) },
{ HP_POP(mapreg->setreg, HP_mapreg_setreg) },
+ { HP_POP(mapreg->set_str_db, HP_mapreg_set_str_db) },
+ { HP_POP(mapreg->delete_str_db, HP_mapreg_delete_str_db) },
{ HP_POP(mapreg->setregstr, HP_mapreg_setregstr) },
+ { HP_POP(mapreg->load_num_db, HP_mapreg_load_num_db) },
+ { HP_POP(mapreg->load_str_db, HP_mapreg_load_str_db) },
{ HP_POP(mapreg->load, HP_mapreg_load) },
+ { HP_POP(mapreg->save_num_db, HP_mapreg_save_num_db) },
+ { HP_POP(mapreg->save_str_db, HP_mapreg_save_str_db) },
{ HP_POP(mapreg->save, HP_mapreg_save) },
{ HP_POP(mapreg->save_timer, HP_mapreg_save_timer) },
{ HP_POP(mapreg->destroyreg, HP_mapreg_destroyreg) },
{ HP_POP(mapreg->reload, HP_mapreg_reload) },
- { HP_POP(mapreg->config_read, HP_mapreg_config_read) },
+ { HP_POP(mapreg->config_read_registry, HP_mapreg_config_read_registry) },
+ { HP_POP(mapreg->final, HP_mapreg_final) },
+ { HP_POP(mapreg->init, HP_mapreg_init) },
/* md5_interface */
{ HP_POP(md5->string, HP_md5_string) },
{ HP_POP(md5->binary, HP_md5_binary) },
@@ -2793,6 +2801,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(script->parse_syntax_close, HP_script_parse_syntax_close) },
{ HP_POP(script->parse_syntax_close_sub, HP_script_parse_syntax_close_sub) },
{ HP_POP(script->parse_syntax, HP_script_parse_syntax) },
+ { HP_POP(script->parse_syntax_function, HP_script_parse_syntax_function) },
{ HP_POP(script->get_com, HP_script_get_com) },
{ HP_POP(script->get_num, HP_script_get_num) },
{ HP_POP(script->op2name, HP_script_op2name) },
diff --git a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index 02d55228e..c1ee157af 100644
--- a/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -50618,58 +50618,6 @@ bool HP_mapit_exists(struct s_mapiterator *iter) {
return retVal___;
}
/* mapreg_interface */
-void HP_mapreg_init(void) {
- int hIndex = 0;
- if (HPMHooks.count.HP_mapreg_init_pre > 0) {
- void (*preHookFunc) (void);
- *HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_init_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_mapreg_init_pre[hIndex].func;
- preHookFunc();
- }
- if (*HPMforce_return) {
- *HPMforce_return = false;
- return;
- }
- }
- {
- HPMHooks.source.mapreg.init();
- }
- if (HPMHooks.count.HP_mapreg_init_post > 0) {
- void (*postHookFunc) (void);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_init_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_mapreg_init_post[hIndex].func;
- postHookFunc();
- }
- }
- return;
-}
-void HP_mapreg_final(void) {
- int hIndex = 0;
- if (HPMHooks.count.HP_mapreg_final_pre > 0) {
- void (*preHookFunc) (void);
- *HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_final_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_mapreg_final_pre[hIndex].func;
- preHookFunc();
- }
- if (*HPMforce_return) {
- *HPMforce_return = false;
- return;
- }
- }
- {
- HPMHooks.source.mapreg.final();
- }
- if (HPMHooks.count.HP_mapreg_final_post > 0) {
- void (*postHookFunc) (void);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_final_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_mapreg_final_post[hIndex].func;
- postHookFunc();
- }
- }
- return;
-}
int HP_mapreg_readreg(int64 uid) {
int hIndex = 0;
int retVal___ = 0;
@@ -50724,6 +50672,60 @@ char* HP_mapreg_readregstr(int64 uid) {
}
return retVal___;
}
+bool HP_mapreg_set_num_db(int64 uid, const char *name, unsigned int index, int value) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if (HPMHooks.count.HP_mapreg_set_num_db_pre > 0) {
+ bool (*preHookFunc) (int64 *uid, const char **name, unsigned int *index, int *value);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_set_num_db_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_mapreg_set_num_db_pre[hIndex].func;
+ retVal___ = preHookFunc(&uid, &name, &index, &value);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.mapreg.set_num_db(uid, name, index, value);
+ }
+ if (HPMHooks.count.HP_mapreg_set_num_db_post > 0) {
+ bool (*postHookFunc) (bool retVal___, int64 uid, const char *name, unsigned int index, int value);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_set_num_db_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_mapreg_set_num_db_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, uid, name, index, value);
+ }
+ }
+ return retVal___;
+}
+bool HP_mapreg_delete_num_db(int64 uid, const char *name, unsigned int index) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if (HPMHooks.count.HP_mapreg_delete_num_db_pre > 0) {
+ bool (*preHookFunc) (int64 *uid, const char **name, unsigned int *index);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_delete_num_db_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_mapreg_delete_num_db_pre[hIndex].func;
+ retVal___ = preHookFunc(&uid, &name, &index);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.mapreg.delete_num_db(uid, name, index);
+ }
+ if (HPMHooks.count.HP_mapreg_delete_num_db_post > 0) {
+ bool (*postHookFunc) (bool retVal___, int64 uid, const char *name, unsigned int index);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_delete_num_db_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_mapreg_delete_num_db_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, uid, name, index);
+ }
+ }
+ return retVal___;
+}
bool HP_mapreg_setreg(int64 uid, int val) {
int hIndex = 0;
bool retVal___ = false;
@@ -50751,6 +50753,60 @@ bool HP_mapreg_setreg(int64 uid, int val) {
}
return retVal___;
}
+bool HP_mapreg_set_str_db(int64 uid, const char *name, unsigned int index, const char *value) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if (HPMHooks.count.HP_mapreg_set_str_db_pre > 0) {
+ bool (*preHookFunc) (int64 *uid, const char **name, unsigned int *index, const char **value);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_set_str_db_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_mapreg_set_str_db_pre[hIndex].func;
+ retVal___ = preHookFunc(&uid, &name, &index, &value);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.mapreg.set_str_db(uid, name, index, value);
+ }
+ if (HPMHooks.count.HP_mapreg_set_str_db_post > 0) {
+ bool (*postHookFunc) (bool retVal___, int64 uid, const char *name, unsigned int index, const char *value);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_set_str_db_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_mapreg_set_str_db_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, uid, name, index, value);
+ }
+ }
+ return retVal___;
+}
+bool HP_mapreg_delete_str_db(int64 uid, const char *name, unsigned int index) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if (HPMHooks.count.HP_mapreg_delete_str_db_pre > 0) {
+ bool (*preHookFunc) (int64 *uid, const char **name, unsigned int *index);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_delete_str_db_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_mapreg_delete_str_db_pre[hIndex].func;
+ retVal___ = preHookFunc(&uid, &name, &index);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.mapreg.delete_str_db(uid, name, index);
+ }
+ if (HPMHooks.count.HP_mapreg_delete_str_db_post > 0) {
+ bool (*postHookFunc) (bool retVal___, int64 uid, const char *name, unsigned int index);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_delete_str_db_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_mapreg_delete_str_db_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, uid, name, index);
+ }
+ }
+ return retVal___;
+}
bool HP_mapreg_setregstr(int64 uid, const char *str) {
int hIndex = 0;
bool retVal___ = false;
@@ -50778,6 +50834,58 @@ bool HP_mapreg_setregstr(int64 uid, const char *str) {
}
return retVal___;
}
+void HP_mapreg_load_num_db(void) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_mapreg_load_num_db_pre > 0) {
+ void (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_load_num_db_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_mapreg_load_num_db_pre[hIndex].func;
+ preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.mapreg.load_num_db();
+ }
+ if (HPMHooks.count.HP_mapreg_load_num_db_post > 0) {
+ void (*postHookFunc) (void);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_load_num_db_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_mapreg_load_num_db_post[hIndex].func;
+ postHookFunc();
+ }
+ }
+ return;
+}
+void HP_mapreg_load_str_db(void) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_mapreg_load_str_db_pre > 0) {
+ void (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_load_str_db_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_mapreg_load_str_db_pre[hIndex].func;
+ preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.mapreg.load_str_db();
+ }
+ if (HPMHooks.count.HP_mapreg_load_str_db_post > 0) {
+ void (*postHookFunc) (void);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_load_str_db_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_mapreg_load_str_db_post[hIndex].func;
+ postHookFunc();
+ }
+ }
+ return;
+}
void HP_mapreg_load(void) {
int hIndex = 0;
if (HPMHooks.count.HP_mapreg_load_pre > 0) {
@@ -50804,6 +50912,58 @@ void HP_mapreg_load(void) {
}
return;
}
+void HP_mapreg_save_num_db(const char *name, unsigned int index, int value) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_mapreg_save_num_db_pre > 0) {
+ void (*preHookFunc) (const char **name, unsigned int *index, int *value);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_save_num_db_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_mapreg_save_num_db_pre[hIndex].func;
+ preHookFunc(&name, &index, &value);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.mapreg.save_num_db(name, index, value);
+ }
+ if (HPMHooks.count.HP_mapreg_save_num_db_post > 0) {
+ void (*postHookFunc) (const char *name, unsigned int index, int value);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_save_num_db_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_mapreg_save_num_db_post[hIndex].func;
+ postHookFunc(name, index, value);
+ }
+ }
+ return;
+}
+void HP_mapreg_save_str_db(const char *name, unsigned int index, const char *value) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_mapreg_save_str_db_pre > 0) {
+ void (*preHookFunc) (const char **name, unsigned int *index, const char **value);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_save_str_db_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_mapreg_save_str_db_pre[hIndex].func;
+ preHookFunc(&name, &index, &value);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.mapreg.save_str_db(name, index, value);
+ }
+ if (HPMHooks.count.HP_mapreg_save_str_db_post > 0) {
+ void (*postHookFunc) (const char *name, unsigned int index, const char *value);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_save_str_db_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_mapreg_save_str_db_post[hIndex].func;
+ postHookFunc(name, index, value);
+ }
+ }
+ return;
+}
void HP_mapreg_save(void) {
int hIndex = 0;
if (HPMHooks.count.HP_mapreg_save_pre > 0) {
@@ -50916,14 +51076,14 @@ void HP_mapreg_reload(void) {
}
return;
}
-bool HP_mapreg_config_read(const char *filename, const struct config_setting_t *config, bool imported) {
+bool HP_mapreg_config_read_registry(const char *filename, const struct config_setting_t *config, bool imported) {
int hIndex = 0;
bool retVal___ = false;
- if (HPMHooks.count.HP_mapreg_config_read_pre > 0) {
+ if (HPMHooks.count.HP_mapreg_config_read_registry_pre > 0) {
bool (*preHookFunc) (const char **filename, const struct config_setting_t **config, bool *imported);
*HPMforce_return = false;
- for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_config_read_pre; hIndex++) {
- preHookFunc = HPMHooks.list.HP_mapreg_config_read_pre[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_config_read_registry_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_mapreg_config_read_registry_pre[hIndex].func;
retVal___ = preHookFunc(&filename, &config, &imported);
}
if (*HPMforce_return) {
@@ -50932,17 +51092,69 @@ bool HP_mapreg_config_read(const char *filename, const struct config_setting_t *
}
}
{
- retVal___ = HPMHooks.source.mapreg.config_read(filename, config, imported);
+ retVal___ = HPMHooks.source.mapreg.config_read_registry(filename, config, imported);
}
- if (HPMHooks.count.HP_mapreg_config_read_post > 0) {
+ if (HPMHooks.count.HP_mapreg_config_read_registry_post > 0) {
bool (*postHookFunc) (bool retVal___, const char *filename, const struct config_setting_t *config, bool imported);
- for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_config_read_post; hIndex++) {
- postHookFunc = HPMHooks.list.HP_mapreg_config_read_post[hIndex].func;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_config_read_registry_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_mapreg_config_read_registry_post[hIndex].func;
retVal___ = postHookFunc(retVal___, filename, config, imported);
}
}
return retVal___;
}
+void HP_mapreg_final(void) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_mapreg_final_pre > 0) {
+ void (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_final_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_mapreg_final_pre[hIndex].func;
+ preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.mapreg.final();
+ }
+ if (HPMHooks.count.HP_mapreg_final_post > 0) {
+ void (*postHookFunc) (void);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_final_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_mapreg_final_post[hIndex].func;
+ postHookFunc();
+ }
+ }
+ return;
+}
+void HP_mapreg_init(void) {
+ int hIndex = 0;
+ if (HPMHooks.count.HP_mapreg_init_pre > 0) {
+ void (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_init_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_mapreg_init_pre[hIndex].func;
+ preHookFunc();
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.mapreg.init();
+ }
+ if (HPMHooks.count.HP_mapreg_init_post > 0) {
+ void (*postHookFunc) (void);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_mapreg_init_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_mapreg_init_post[hIndex].func;
+ postHookFunc();
+ }
+ }
+ return;
+}
/* md5_interface */
void HP_md5_string(const char *string, char *output) {
int hIndex = 0;
@@ -71749,14 +71961,14 @@ bool HP_script_get_constant(const char *name, int *value) {
}
return retVal___;
}
-void HP_script_label_add(int key, int pos) {
+void HP_script_label_add(int key, int pos, enum script_label_flags flags) {
int hIndex = 0;
if (HPMHooks.count.HP_script_label_add_pre > 0) {
- void (*preHookFunc) (int *key, int *pos);
+ void (*preHookFunc) (int *key, int *pos, enum script_label_flags *flags);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_script_label_add_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_script_label_add_pre[hIndex].func;
- preHookFunc(&key, &pos);
+ preHookFunc(&key, &pos, &flags);
}
if (*HPMforce_return) {
*HPMforce_return = false;
@@ -71764,13 +71976,13 @@ void HP_script_label_add(int key, int pos) {
}
}
{
- HPMHooks.source.script.label_add(key, pos);
+ HPMHooks.source.script.label_add(key, pos, flags);
}
if (HPMHooks.count.HP_script_label_add_post > 0) {
- void (*postHookFunc) (int key, int pos);
+ void (*postHookFunc) (int key, int pos, enum script_label_flags flags);
for (hIndex = 0; hIndex < HPMHooks.count.HP_script_label_add_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_script_label_add_post[hIndex].func;
- postHookFunc(key, pos);
+ postHookFunc(key, pos, flags);
}
}
return;
@@ -72625,6 +72837,33 @@ const char* HP_script_parse_syntax(const char *p) {
}
return retVal___;
}
+const char* HP_script_parse_syntax_function(const char *p, bool is_public) {
+ int hIndex = 0;
+ const char* retVal___ = NULL;
+ if (HPMHooks.count.HP_script_parse_syntax_function_pre > 0) {
+ const char* (*preHookFunc) (const char **p, bool *is_public);
+ *HPMforce_return = false;
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_script_parse_syntax_function_pre; hIndex++) {
+ preHookFunc = HPMHooks.list.HP_script_parse_syntax_function_pre[hIndex].func;
+ retVal___ = preHookFunc(&p, &is_public);
+ }
+ if (*HPMforce_return) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.script.parse_syntax_function(p, is_public);
+ }
+ if (HPMHooks.count.HP_script_parse_syntax_function_post > 0) {
+ const char* (*postHookFunc) (const char* retVal___, const char *p, bool is_public);
+ for (hIndex = 0; hIndex < HPMHooks.count.HP_script_parse_syntax_function_post; hIndex++) {
+ postHookFunc = HPMHooks.list.HP_script_parse_syntax_function_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, p, is_public);
+ }
+ }
+ return retVal___;
+}
c_op HP_script_get_com(const struct script_buf *scriptbuf, int *pos) {
int hIndex = 0;
c_op retVal___ = C_NOP;
@@ -78235,15 +78474,15 @@ struct skill_unit_group* HP_skill_init_unitgroup(struct block_list *src, int cou
}
return retVal___;
}
-int HP_skill_del_unitgroup(struct skill_unit_group *group, const char *file, int line, const char *func) {
+int HP_skill_del_unitgroup(struct skill_unit_group *group) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_skill_del_unitgroup_pre > 0) {
- int (*preHookFunc) (struct skill_unit_group **group, const char **file, int *line, const char **func);
+ int (*preHookFunc) (struct skill_unit_group **group);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_del_unitgroup_pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_skill_del_unitgroup_pre[hIndex].func;
- retVal___ = preHookFunc(&group, &file, &line, &func);
+ retVal___ = preHookFunc(&group);
}
if (*HPMforce_return) {
*HPMforce_return = false;
@@ -78251,13 +78490,13 @@ int HP_skill_del_unitgroup(struct skill_unit_group *group, const char *file, int
}
}
{
- retVal___ = HPMHooks.source.skill.del_unitgroup(group, file, line, func);
+ retVal___ = HPMHooks.source.skill.del_unitgroup(group);
}
if (HPMHooks.count.HP_skill_del_unitgroup_post > 0) {
- int (*postHookFunc) (int retVal___, struct skill_unit_group *group, const char *file, int line, const char *func);
+ int (*postHookFunc) (int retVal___, struct skill_unit_group *group);
for (hIndex = 0; hIndex < HPMHooks.count.HP_skill_del_unitgroup_post; hIndex++) {
postHookFunc = HPMHooks.list.HP_skill_del_unitgroup_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, group, file, line, func);
+ retVal___ = postHookFunc(retVal___, group);
}
}
return retVal___;
@@ -85816,15 +86055,15 @@ int HP_status_change_start_sub(struct block_list *src, struct block_list *bl, en
}
return retVal___;
}
-int HP_status_change_end_(struct block_list *bl, enum sc_type type, int tid, const char *file, int line) {
+int HP_status_change_end_(struct block_list *bl, enum sc_type type, int tid) {
int hIndex = 0;
int retVal___ = 0;
if (HPMHooks.count.HP_status_change_end__pre > 0) {
- int (*preHookFunc) (struct block_list **bl, enum sc_type *type, int *tid, const char **file, int *line);
+ int (*preHookFunc) (struct block_list **bl, enum sc_type *type, int *tid);
*HPMforce_return = false;
for (hIndex = 0; hIndex < HPMHooks.count.HP_status_change_end__pre; hIndex++) {
preHookFunc = HPMHooks.list.HP_status_change_end__pre[hIndex].func;
- retVal___ = preHookFunc(&bl, &type, &tid, &file, &line);
+ retVal___ = preHookFunc(&bl, &type, &tid);
}
if (*HPMforce_return) {
*HPMforce_return = false;
@@ -85832,13 +86071,13 @@ int HP_status_change_end_(struct block_list *bl, enum sc_type type, int tid, con
}
}
{
- retVal___ = HPMHooks.source.status.change_end_(bl, type, tid, file, line);
+ retVal___ = HPMHooks.source.status.change_end_(bl, type, tid);
}
if (HPMHooks.count.HP_status_change_end__post > 0) {
- int (*postHookFunc) (int retVal___, struct block_list *bl, enum sc_type type, int tid, const char *file, int line);
+ int (*postHookFunc) (int retVal___, struct block_list *bl, enum sc_type type, int tid);
for (hIndex = 0; hIndex < HPMHooks.count.HP_status_change_end__post; hIndex++) {
postHookFunc = HPMHooks.list.HP_status_change_end__post[hIndex].func;
- retVal___ = postHookFunc(retVal___, bl, type, tid, file, line);
+ retVal___ = postHookFunc(retVal___, bl, type, tid);
}
}
return retVal___;
diff --git a/tools/authors.sh b/tools/authors.sh
new file mode 100755
index 000000000..da4a576c6
--- /dev/null
+++ b/tools/authors.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+
+# grep -v "kenpachi2k11" as workaround for avoid .mailmap issue
+git log --format=format:"%aN <%aE>"|grep -v "54d463be-8e91-2dee-dedb-b68131a5f0ec"|grep -v "kenpachi2k11"|sort|uniq