diff options
38 files changed, 1910 insertions, 661 deletions
@@ -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> @@ -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/db/re/mob_db.conf b/db/re/mob_db.conf index 99518c461..b80008028 100644 --- a/db/re/mob_db.conf +++ b/db/re/mob_db.conf @@ -4816,7 +4816,7 @@ mob_db: ( Drops: { Runstone_Ancient: 10 Healing_Staff: 10 - White_Wing_Suits: 100 + White_Wing_Suits: 50 Oridecon: 105 Sacred_Masque: 4365 Mitten_Of_Presbyter: 1 @@ -75437,7 +75437,7 @@ mob_db: ( Drops: { Sprint_Ring: 2 Bradium: 1 - Black_Wing_Suits: 9000 + Black_Wing_Suits: 25 Honey: 300 Wind_Of_Verdure: 160 Royal_Jelly: 200 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/mob_db_re.sql b/sql-files/mob_db_re.sql index 4864affb2..ff2bd6304 100644 --- a/sql-files/mob_db_re.sql +++ b/sql-files/mob_db_re.sql @@ -178,7 +178,7 @@ REPLACE INTO `mob_db` VALUES (1094,'AMBERNITE','Ambernite','Ambernite',19,340,1, REPLACE INTO `mob_db` VALUES (1095,'ANDRE','Andre','Andre',33,724,1,216,243,1,51,21,55,16,11,20,40,10,24,10,10,12,0,4,22,4481,300,1288,288,384,0,0,0,0,0,0,0,955,9000,910,1000,938,500,993,50,1001,4,1002,350,757,28,0,0,0,0,4043,1); REPLACE INTO `mob_db` VALUES (1096,'ANGELING','Angeling','Angeling',77,19800,1,3366,2693,1,391,145,72,238,58,50,33,105,80,200,10,12,1,8,86,14261,200,1072,672,672,0,0,0,0,0,0,0,2254,100,2324,60,610,500,2282,1,509,2000,512,28,714,40,0,0,0,0,4054,1); REPLACE INTO `mob_db` VALUES (1097,'ANT_EGG','Ant Egg','Ant Egg',28,530,1,180,203,0,1,1,68,45,5,1,65,5,10,30,10,12,0,0,60,0,1000,1001,199,1,0,0,0,0,0,0,0,1010,320,935,2000,909,2000,938,650,713,2000,1002,200,0,0,0,0,0,0,4013,1); -REPLACE INTO `mob_db` VALUES (1098,'ANUBIS','Anubis','Anubis',105,38826,1,6026,2725,1,984,415,103,48,88,67,40,128,107,55,10,12,2,7,49,13973,150,1250,720,576,0,0,0,0,0,0,0,12735,10,1625,10,15042,100,984,105,1045,4365,2617,1,1614,3,0,0,0,0,4138,1); +REPLACE INTO `mob_db` VALUES (1098,'ANUBIS','Anubis','Anubis',105,38826,1,6026,2725,1,984,415,103,48,88,67,40,128,107,55,10,12,2,7,49,13973,150,1250,720,576,0,0,0,0,0,0,0,12735,10,1625,10,15042,50,984,105,1045,4365,2617,1,1614,3,0,0,0,0,4138,1); REPLACE INTO `mob_db` VALUES (1099,'ARGIOPE','Argiope','Argiope',75,3105,1,890,912,1,321,50,88,32,60,23,40,30,24,30,10,12,2,4,25,14229,300,1792,792,336,0,0,0,0,0,0,0,1042,5335,912,1200,757,175,2406,5,511,1500,719,10,0,0,0,0,0,0,4114,1); REPLACE INTO `mob_db` VALUES (1100,'ARGOS','Argos','Argos',47,1005,1,360,405,1,96,33,58,8,38,17,25,5,26,15,10,12,2,4,25,12693,300,1468,468,768,0,0,0,0,0,0,0,1025,9000,911,1200,1042,500,757,61,511,670,508,250,10017,15,0,0,0,0,4075,1); REPLACE INTO `mob_db` VALUES (1101,'BAPHOMET_','Baphomet Jr.','Baphomet Jr.',57,2035,1,510,548,1,195,33,70,25,52,60,36,17,57,25,10,12,0,6,27,14229,100,868,480,120,0,0,0,0,0,0,0,923,500,984,63,1464,2,607,50,610,100,508,1300,2405,50,0,0,0,0,4129,1); @@ -1634,7 +1634,7 @@ REPLACE INTO `mob_db` VALUES (2769,'C1_MAGMARING','Swift Magmaring','Swift Magma REPLACE INTO `mob_db` VALUES (2770,'C2_LUNATIC','Solid Lunatic','Solid Lunatic',3,550,1,90,195,1,23,5,18,0,10,3,3,0,8,5,10,12,0,2,60,129,200,1456,456,336,0,0,0,0,0,0,0,705,6500,949,1000,512,10000,601,5000,515,10000,2262,1100,622,20,0,0,0,0,4006,1); REPLACE INTO `mob_db` VALUES (2771,'C3_LUNATIC','Lunatic Ringleader','Lunatic Ringleader',3,275,1,90,195,1,23,5,18,0,10,3,3,0,8,5,10,12,0,2,60,129,200,1456,456,336,0,0,0,0,0,0,0,705,6500,949,1000,2262,4,512,2000,601,600,515,1100,622,20,0,0,0,0,4006,1); REPLACE INTO `mob_db` VALUES (2772,'C4_LUDE','Furious Lude','Furious Lude',101,57870,1,5075,11400,2,468,135,90,53,97,49,55,82,83,55,10,12,0,1,29,14469,150,960,960,480,0,0,0,0,0,0,0,7225,3200,7220,5723,1059,1000,2282,10,757,10,12001,100,6246,300,0,0,0,0,4193,1); -REPLACE INTO `mob_db` VALUES (2773,'C5_LUCIOLA_VESPA','Elusive Luciola Vespa','Elusive Luciola Vespa',109,62330,1,7365,16245,1,761,283,59,55,88,89,55,32,143,59,10,12,1,4,24,30613,110,1000,864,432,0,0,0,0,0,0,0,2744,2,6224,1,15043,9000,518,300,992,160,526,200,943,3000,0,0,0,0,4445,1); +REPLACE INTO `mob_db` VALUES (2773,'C5_LUCIOLA_VESPA','Elusive Luciola Vespa','Elusive Luciola Vespa',109,62330,1,7365,16245,1,761,283,59,55,88,89,55,32,143,59,10,12,1,4,24,30613,110,1000,864,432,0,0,0,0,0,0,0,2744,2,6224,1,15043,25,518,300,992,160,526,200,943,3000,0,0,0,0,4445,1); REPLACE INTO `mob_db` VALUES (2774,'C1_LOLI_RURI','Swift Loli Ruri','Swift Loli Ruri',109,76400,1,8370,18825,2,1297,539,53,44,111,50,47,79,95,79,10,12,2,6,87,14725,125,1632,1632,576,0,0,0,0,0,0,0,7206,800,7219,3000,7214,5044,985,100,7019,1,2718,5,15038,100,0,0,0,0,4191,1); REPLACE INTO `mob_db` VALUES (2775,'C2_LIVE_PEACH_TREE','Solid Enchanted Peach T','Solid Enchanted Peach T',92,87770,1,4495,12930,7,504,169,109,40,76,52,55,40,92,50,10,12,1,3,42,8325,410,672,672,480,0,0,0,0,0,0,0,7164,4365,7939,100,526,1000,604,400,532,100,603,5,0,0,0,0,0,0,4217,1); REPLACE INTO `mob_db` VALUES (2776,'C3_LITTLE_PORING','Baby Poring Ringleader','Baby Poring Ringleader',1,200,1,90,150,1,14,3,2,5,6,1,1,0,6,5,10,12,0,3,21,131,400,1872,672,480,0,0,0,0,0,0,0,909,9000,1202,100,938,1000,512,5000,507,1000,512,500,507,1000,0,0,0,0,4545,100); 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 7fe9bbbb5..796e0de68 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 2778c0f03..477894805 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 f2eca0b89..dfc1f886e 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -630,10 +630,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 14db20549..069b98eef 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 *------------------------------------------*/ @@ -27429,6 +27680,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 @@ -27440,7 +27693,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; @@ -27451,6 +27704,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++; } @@ -27869,6 +28123,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); @@ -28262,6 +28517,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; @@ -28366,6 +28622,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 ceb979c1f..8c83e57a3 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -12556,7 +12556,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; } @@ -12672,7 +12672,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. */ @@ -12978,7 +12978,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: @@ -16665,7 +16665,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; } @@ -17313,7 +17313,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; } @@ -17372,7 +17372,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; } @@ -17411,18 +17411,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); @@ -17554,7 +17549,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 1e92bbd6a..a6e6b24c0 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); } @@ -10787,7 +10787,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; @@ -10957,23 +10957,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]; @@ -10989,19 +10975,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) @@ -11105,7 +11082,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: @@ -11124,7 +11101,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: @@ -11222,7 +11199,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: @@ -11230,7 +11207,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 54e5c2da3..107d0cc33 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 c5be1529e..97997f7b8 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; @@ -71748,14 +71960,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; @@ -71763,13 +71975,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; @@ -72624,6 +72836,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; @@ -78234,15 +78473,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; @@ -78250,13 +78489,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___; @@ -85815,15 +86054,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; @@ -85831,13 +86070,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 |