diff options
Diffstat (limited to 'npc/functions')
72 files changed, 5364 insertions, 0 deletions
diff --git a/npc/functions/RNGesus.txt b/npc/functions/RNGesus.txt new file mode 100644 index 000000000..f71c2f28a --- /dev/null +++ b/npc/functions/RNGesus.txt @@ -0,0 +1,23 @@ +// Evol functions. +// Authors: +// gumi +// Description: +// Randomization helper functions. + + + +// any(<arg>{, ...<arg>}) +// returns one argument randomly + +function script any { + return getarg(rand(getargcount())); +} + + + +// any_of(<array>) +// returns any member of the array + +function script any_of { + return getelementofarray(getarg(0), getarrayindex(getarg(0)) + rand(getarraysize(getarg(0)) - getarrayindex(getarg(0)))); +} diff --git a/npc/functions/array.txt b/npc/functions/array.txt new file mode 100644 index 000000000..d9d649921 --- /dev/null +++ b/npc/functions/array.txt @@ -0,0 +1,410 @@ +// array_pad(<array>, <size>, <value>) +// prepend or append <value> until the array is of <size> size +// returns the amount added on success, or false (0) if nothing changed + +function script array_pad { + .@index = getarrayindex(getarg(0)); // passed index + .@count = getarraysize(getarg(0)) - .@index; // actual size + .@size = getarg(1); // desired size + .@absolute = (.@size >= 0 ? .@size : -(.@size)); // |size| + .@delta = .@absolute - .@count; // amount to fill + + if (.@absolute <= .@count) { + return false; // nothing to do + } + + if (.@size < 0) { + copyarray(getelementofarray(getarg(0), .@index + .@delta), getarg(0), .@count); // shift to the right + cleararray(getarg(0), getarg(2), .@delta); // prepend + } else { + cleararray(getelementofarray(getarg(0), .@index + .@count), getarg(2), .@delta); // append + } + + return .@delta; +} + + + +// array_replace(<array>, <needle>, <replace>{, <neq>}) +// replace every occurence of <needle> with <replace> +// returns the number of replaced elements + +function script array_replace { + .@size = getarraysize(getarg(0)); + .@neq = getarg(3, false); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) || + (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) { + set(getelementofarray(getarg(0), .@i), getarg(2)); + ++.@count; + } + } + + freeloop(false); + return .@count; +} + + + +// array_find(<array>, <needle>{, <neq>}) +// return the index of the first occurence of <needle> in <array> +// if not found it returns -1 + +function script array_find { + .@size = getarraysize(getarg(0)); + .@neq = getarg(2, false); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) || + (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) { + freeloop(false); + return .@i; + } + } + + freeloop(false); + return -1; +} + + + +// array_rfind(<array>, <needle>{, <neq>}) +// return the index of the last occurence of <needle> in <array> +// if not found it returns -1 + +function script array_rfind { + .@min = getarrayindex(getarg(0)); + .@neq = getarg(2, false); + freeloop(true); + + for (.@i = (getarraysize(getarg(0)) - 1); .@i >= .@min; --.@i) { + if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) || + (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) { + freeloop(false); + return .@i; + } + } + + freeloop(false); + return -1; +} + + + +// array_exists(<array>, <needle>{, <neq>}) +// return true or false accordingly if <needle> is found in <array> + +function script array_exists { + return array_find(getarg(0), getarg(1), getarg(2, false)) > -1; +} + + + +// array_count(<array>, <needle>{, <neq>}) +// counts the number of occurrence of <needle> in the <array> + +function script array_count { + .@size = getarraysize(getarg(0)); + .@neq = getarg(2, false); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) || + (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) { + ++.@count; + } + } + + freeloop(false); + return .@count; +} + + + +// array_entries(<array>) +// returns the number of non-empty entries + +function script array_entries { + if (isstr(getarg(0)) == 1) { + return array_count(getarg(0), "", true); + } + return array_count(getarg(0), 0, true); +} + + + +// array_remove(<array>, <needle>{, <neq>}) +// removes every occurrence of <needle> in the <array> while shifting left + +function script array_remove { + .@size = getarraysize(getarg(0)); + .@neq = getarg(2, false); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + if ((.@neq && (getelementofarray(getarg(0), .@i) != getarg(1))) || + (!(.@neq) && (getelementofarray(getarg(0), .@i) == getarg(1)))) { + deletearray(getelementofarray(getarg(0), .@i), 1); // shift left + ++.@count; // increase the counter + --.@size; // reduce the size + --.@i; // step back + } + } + + freeloop(false); + return .@count; +} + + + +// array_reverse(<array>) +// reverses the array + +function script array_reverse { + .@index = getarrayindex(getarg(0)); + .@size = getarraysize(getarg(0)); + freeloop(true); + + for (.@i = .@index; .@i < ((.@size + .@index) / 2); ++.@i) { + swap(getelementofarray(getarg(0), .@i), getelementofarray(getarg(0), .@size + .@index - 1 - .@i)); // a <> b + } + + freeloop(false); + return true; +} + + + +// array_sum(<array>) +// return the sum of every element of the array + +function script array_sum { + .@size = getarraysize(getarg(0)); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + .@sum += getelementofarray(getarg(0), .@i); + } + + freeloop(false); + return .@sum; +} + + + +// array_difference(<array>) +// return the difference of every element of the array + +function script array_difference { + .@size = getarraysize(getarg(0)); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + .@diff -= getelementofarray(getarg(0), .@i); + } + + freeloop(false); + return .@diff; +} + + + +// array_product(<array>) +// return the product of every element of the array + +function script array_product { + .@size = getarraysize(getarg(0)); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + .@prod *= getelementofarray(getarg(0), .@i); + } + + freeloop(false); + return .@prod; +} + + + +// array_quotient(<array>) +// return the product of every element of the array + +function script array_quotient { + .@size = getarraysize(getarg(0)); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + .@quot /= getelementofarray(getarg(0), .@i); + } + + freeloop(false); + return .@quot; +} + + + +// array_shift(<array>) +// returns the first element of the array and removes it, while shifting left + +function script array_shift { + if (isstr(getarg(0)) == 1) { + .@val$ = getarg(0); + } else { + .@int = true; + .@val = getarg(0); + } + + deletearray(getarg(0), 1); // shift left + + return .@int ? .@val : .@val$; +} + + + +// array_unshift(<array>, <value>) +// adds <value> to the start of the array, while shifting right +// returns the new size + +function script array_unshift { + .@size = getarraysize(getarg(0)) + 1; + array_pad(getarg(0), -(.@size - getarrayindex(getarg(0))), getarg(1)); + return .@size; +} + + + +// array_pop(<array>) +// returns the last element of the array and removes it + +function script array_pop { + .@last = getarraysize(getarg(0)) - 1; + + if (isstr(getelementofarray(getarg(0), .@last)) == 1) { + .@val$ = getelementofarray(getarg(0), .@last); + } else { + .@int = true; + .@val = getelementofarray(getarg(0), .@last); + } + + deletearray(getelementofarray(getarg(0), .@last), 1); + + return .@int ? .@val : .@val$; +} + + + +// array_push(<array>, <value>) +// adds <value> to the end of the array +// returns the new size + +function script array_push { + .@size = getarraysize(getarg(0)); + set(getelementofarray(getarg(0), .@size), getarg(1)); + return .@size + 1; +} + + + +// array_shuffle(<array>) +// shuffles the array + +function script array_shuffle { + .@index = getarrayindex(getarg(0)); + .@size = getarraysize(getarg(0)) - .@index; + freeloop(true); + + if (isstr(getarg(0)) == 1) { + copyarray(.@tmp$[0], getarg(0), .@size); + for (; .@size >= 1; --.@size) { + set(getelementofarray(getarg(0), .@index + .@size - 1), array_shift(.@tmp$[rand(.@size)])); + } + } else { + copyarray(.@tmp[0], getarg(0), .@size); + for (; .@size >= 1; --.@size) { + set(getelementofarray(getarg(0), .@index + .@size - 1), array_shift(.@tmp[rand(.@size)])); + } + } + + freeloop(false); + return true; +} + + + +// array_unique(<array>{, <threshold>}) +// allows entries to appear up to <threshold> in the array + +function script array_unique { + .@size = getarraysize(getarg(0)); + .@max = getarg(1, 1); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + .@count = 1; + for (.@e = .@i + 1; .@e < .@size; ++.@e) { + if (getelementofarray(getarg(0), .@i) == getelementofarray(getarg(0), .@e)) { + if (++.@count >= .@max) { + deletearray(getelementofarray(getarg(0), .@e), 1); + ++.@removed; // increase counter + --.@size; // reduce size + --.@e; // step back + } + } + } + } + + freeloop(false); + return .@removed; +} + + + +// array_diff(<array1>, <array2>{, <array>...}, <array>) +// compares array1 against one or more other arrays and fills the last array +// with the values in array1 that are not present in any of the other arrays +// returns the number of entries not matching + +function script array_diff { + .@size = getarraysize(getarg(0)); + .@index = getarrayindex(getarg(0)); + freeloop(true); + + for (.@a = 1; .@a < (getargcount() - 1); ++.@a) { + for (.@i = .@index; .@i < .@size; ++.@i) { + if (!array_exists(getarg(.@a), getelementofarray(getarg(0), .@i))) { + array_push(getarg(getargcount() - 1), getelementofarray(getarg(0), .@i)); + ++.@count; + } + } + } + + freeloop(false); + return .@count; +} + + + +// array_filter(<array>, "<function>") +// filters the array using a callback function + +function script array_filter { + .@size = getarraysize(getarg(0)); + .@neq = getarg(2, false); + freeloop(true); + + for (.@i = getarrayindex(getarg(0)); .@i < .@size; ++.@i) { + .@eq = callfunc(getarg(1), getelementofarray(getarg(0), .@i)) != false; + if ((.@neq && .@eq) || (!(.@neq) && !(.@eq))) { + deletearray(getelementofarray(getarg(0), .@i), 1); // shift left + ++.@count; // increase the counter + --.@size; // reduce the size + --.@i; // step back + } + } + + freeloop(false); + return .@count; +} diff --git a/npc/functions/asklanguage.txt b/npc/functions/asklanguage.txt new file mode 100644 index 000000000..4bea4bd11 --- /dev/null +++ b/npc/functions/asklanguage.txt @@ -0,0 +1,80 @@ +// Evol functions. +// Author: +// Reid +// Description: +// Function setting the player language + +function script asklanguage { + + .@nb_language = 11; + + switch (getarg(0, 0)) + { + case LANG_ON_SEA: + setarray .@messages$[0], "I hear you... (English)", // English + "Je vous entends... (Français)", // French + "Да я вас слышу... (Русский)", // Russian + "Te oigo... (Español)", // Spanish + "Eu te ouço... (Português)", // Portuguese + "Ich höre euch... (Deutsch)", // German + "'k hoar ui wel... (Vlaams)", // Flemish + "Słyszę cię... (Polski)", // Polish + "Vi sento... (Italiano)", // Italian + "Ik kan je horen... (Nederlands)", // Dutch + "Et escolto (Català)", // Catalan + "Mi aŭdas vin... (Angle)"; // Esperanto + break; + case LANG_IN_SHIP: + setarray .@messages$[0], "I speak English.", // English + "Je parle français.", // French + "Я говорю на русском.", // Russian + "Hablo Español.", // Spanish + "Eu falo Português.", // Portuguese + "Ich spreche Deutsch.", // German + "'k klappe Vloams", // Flemish + "Mówię po polsku.", // Polish + "Parlo Italiano.", // Italian + "Ik spreek Nederlands.", // Dutch + "Parlo català.", // Catalan + "Mi parolas Esperanton."; // Esperanto + break; + default: + return; + } + + setarray .@flags$[0], "flags/en", + "flags/fr", + "flags/ru", + "flags/es", + "flags/pt_BR", + "flags/de", + "flags/vls", + "flags/pl", + "flags/it", + "flags/nl_BE", + "flags/ca", + "flags/eo"; + + .@menustr$ = ""; + .@separator$ = ":"; + + for (.@i = 0; .@i <= .@nb_language; .@i++) + { + if (.@i == .@nb_language) + { + .@separator$ = ""; + } + .@menustr$ = .@menustr$ + .@flags$[.@i] + "|" + .@messages$[.@i] + .@separator$; + } + + select(.@menustr$); + + .@lang = @menu - 1; + + if (.@lang >= 0 || .@lang <= .@nb_language) + { + Lang = .@lang; + } + + return; +} diff --git a/npc/functions/asleep.txt b/npc/functions/asleep.txt new file mode 100644 index 000000000..aa5abd635 --- /dev/null +++ b/npc/functions/asleep.txt @@ -0,0 +1,19 @@ +// Evol functions. +// Authors: +// Alige +// Reid +// Description: +// Tell a random sleeping sound. +// Variables: +// .@rand = Random number between the number of "sleeping" choice. + +function script asleep { + switch(rand(5)) { + case 0: npctalkonce(l("Zzzzzzzzz...")); break; + case 1: npctalkonce(l("Rrrr... Pchhhh...")); break; + case 2: npctalkonce(l("Ggrmm... Grmmmm...")); break; + case 3: npctalkonce(l("Hm... Shhhh...")); break; + default: emotion(E_SLEEPY); + } + end; +} diff --git a/npc/functions/bank.txt b/npc/functions/bank.txt new file mode 100644 index 000000000..5b2813797 --- /dev/null +++ b/npc/functions/bank.txt @@ -0,0 +1,134 @@ +// Evol scripts. +// Authors: +// gumi +// Reid + +function script MerchantGuild_Bank { + do + { + if (BankVault > 0) + { + speech S_FIRST_BLANK_LINE | S_LAST_NEXT, + l("You currently have @@ Esperin on your bank account.", + format_number(BankVault)), + l("What do you want to do with your money?"); + } + else + { + speech S_FIRST_BLANK_LINE | S_LAST_NEXT, + l("What do you want to do with your money?"); + } + + select + rif(Zeny > 0, l("Deposit.")), + rif(BankVault > 0, l("Withdraw.")), + l("I'm done."); + + switch (@menu) + { + case 1: + speech S_FIRST_BLANK_LINE | S_LAST_NEXT, + l("How much do you want to deposit?"); + + menuint + l("Other."), -1, + rif(Zeny >= 5000, format_number(5000) + " E."), 5000, + rif(Zeny >= 10000, format_number(10000) + " E."), 10000, + rif(Zeny >= 25000, format_number(25000) + " E."), 25000, + rif(Zeny >= 50000, format_number(50000) + " E."), 50000, + rif(Zeny >= 100000, format_number(100000) + " E."), 100000, + rif(Zeny >= 250000, format_number(250000) + " E."), 250000, + rif(Zeny >= 500000, format_number(500000) + " E."), 500000, + rif(Zeny >= 1000000, format_number(1000000) + " E."), 1000000, + l("All of my money."), -2, + l("I changed my mind."), -3; + + switch (@menuret) + { + case -1: + input @menuret; + break; + case -2: + @menuret = Zeny; + } + + if (@menuret > 0) + { + if (@menuret > Zeny) + { + speech S_FIRST_BLANK_LINE | S_LAST_NEXT, + l("You do not have enough Esperin on yourself."); + break; + } + + @menuret = min(MAX_BANK_ZENY, @menuret); // make sure the variable can't overflow + .@before = BankVault; // amount before the deposit + .@max = MAX_BANK_ZENY - BankVault; // maximum possible deposit + .@deposit = min(.@max, @menuret); // actual deposit + + if (.@deposit > 0) + { + BankVault += .@deposit; // add to bank + Zeny -= .@deposit; // remove from inventory + + speech S_FIRST_BLANK_LINE | S_LAST_NEXT, + l("You made a cash deposit of @@ E.", format_number(.@deposit)); + } + } + break; + + case 2: + speech S_FIRST_BLANK_LINE | S_LAST_NEXT, + l("How much do you want to withdraw?"); + + menuint + l("Other."), -1, + rif(BankVault >= 5000, format_number(5000) + " E."), 5000, + rif(BankVault >= 10000, format_number(10000) + " E."), 10000, + rif(BankVault >= 25000, format_number(25000) + " E."), 25000, + rif(BankVault >= 50000, format_number(50000) + " E."), 50000, + rif(BankVault >= 100000, format_number(100000) + " E."), 100000, + rif(BankVault >= 250000, format_number(250000) + " E."), 250000, + rif(BankVault >= 500000, format_number(500000) + " E."), 500000, + rif(BankVault >= 1000000, format_number(1000000) + " E."), 1000000, + l("All of my money."), -2, + l("I changed my mind."), -3; + + switch (@menuret) + { + case -1: + input @menuret; + break; + case -2: + @menuret = BankVault; + } + + if (@menuret > 0) + { + if (@menuret > BankVault) + { + speech S_FIRST_BLANK_LINE | S_LAST_NEXT, + l("You do not have enough Esperin on your bank account."); + break; + } + + @menuret = min(MAX_ZENY, @menuret); // make sure the variable can't overflow + .@before = Zeny; // amount before the withdrawal + .@max = MAX_ZENY - Zeny; // maximum possible withdrawal + .@withdrawal = min(.@max, @menuret); // actual withdrawal + + if (.@withdrawal > 0) + { + Zeny += .@withdrawal; // add to inventory + BankVault -= .@withdrawal; // remove from bank + + speech S_FIRST_BLANK_LINE | S_LAST_NEXT, + l("You withdrew a total of @@ E.", format_number(.@withdrawal)); + } + } + break; + + default: return; + } + } while (true); +} diff --git a/npc/functions/barber.txt b/npc/functions/barber.txt new file mode 100644 index 000000000..370285b76 --- /dev/null +++ b/npc/functions/barber.txt @@ -0,0 +1,110 @@ +// Evol scripts. +// Authors: +// omatt +// Reid +// Travolta +// Description: +// Function for supporting barber NPC. + +function script BarberSayStyle { + + .@get_color = getlook(LOOK_HAIR_COLOR); + .@get_look = getlook(LOOK_HAIR); + .@style_name$ = $@hairstyle$[.@get_look]; + .@color_name$ = $@haircolor$[.@get_color]; + + switch (getarg(0)) + { + case 1: + message strcharinfo(0), l("@@", .@style_name$); + break; + case 2: + message strcharinfo(0), l("@@", .@color_name$); + break; + case 3: + speech S_FIRST_BLANK_LINE | S_LAST_NEXT, + l("Your hairstyle is @@ and its color is @@.", .@style_name$, .@color_name$); + break; + } + return; +} +function script BarberChangeStyle { + do + { + .@hairsizearray = getarraysize($@hairstyle$); + .@get_look = getlook(LOOK_HAIR); + + // Here .@i starts from 1 because hairstyle 0 doesn't exist. + for (.@i = 1; .@i < .@hairsizearray; .@i++) + { + .@menustr$ = .@menustr$ + + rif(.@get_look != .@i, l("" + $@hairstyle$[.@i] + "")) + + ":"; + } + + .@menustr$ = .@menustr$ + l("I'm fine for now, thank you."); + + .@idx = select(l("As you want!"),.@menustr$); + + if (.@idx == .@i + 1) return; // last choice to quit dialog + + switch (@menu) + { + case 1: + do + { + // here "- 1" because i don't use the 0 of array + .@rand_hair = rand(1,(.@hairsizearray - 1)); + } while (.@rand_hair == getlook(LOOK_HAIR)); + setlook LOOK_HAIR, .@rand_hair; + setlook LOOK_HAIR_COLOR, getlook(LOOK_HAIR_COLOR); + BarberSayStyle 1; + break; + default: + // and here "- 1" because the first choice is taken by the random + setlook LOOK_HAIR, (@menu - 1); + setlook LOOK_HAIR_COLOR, getlook(LOOK_HAIR_COLOR); + break; + } + .@menustr$ = ""; + } while (1); +} + +function script BarberChangeColor { + do + { + .@get_look = getlook(LOOK_HAIR_COLOR); + .@hairsizearray = getarraysize($@haircolor$); + + for (.@i = 0; .@i < .@hairsizearray; .@i++) + { + .@menustr$ = .@menustr$ + + rif(.@get_look != .@i, l("" + $@haircolor$[.@i] + "")) + + ":"; + } + + .@menustr$ = l("Surprise me!") + ":" + .@menustr$ + l("I'm fine for now, thank you."); + + .@idx = select(.@menustr$); + + if (.@idx == .@i + 2) return; + + switch (@menu) + { + case 1: + do + { + .@rand_color = rand(0, .@hairsizearray); + } while (.@rand_color == getlook(LOOK_HAIR_COLOR)); + setlook LOOK_HAIR_COLOR, .@rand_color; + BarberSayStyle 2; + break; + default: + setlook LOOK_HAIR_COLOR, (@menu - 2); + break; + } + .@menustr$ = ""; + } while (1); + + return; +} diff --git a/npc/functions/beds.txt b/npc/functions/beds.txt new file mode 100644 index 000000000..4ab8b6a77 --- /dev/null +++ b/npc/functions/beds.txt @@ -0,0 +1,30 @@ +// Evol functions. +// Authors: +// 4144 +// Reid +// Description: +// Beds utility functions + +function script bedTouch { + if (PC_IS_DEAD) + { + PC_IS_DEAD = 0; + if (INN_REGISTER == REDPLUSH_INN) + { + INN_REGISTER = NO_INN; + percentheal 100,100; + } + } + close; +} + +function script bedClic { + narrator S_LAST_NEXT, l("Do you want to use this place as save point?"); + + if (askyesno() == ASK_YES) + { + savepointparticle getarg(0, ""), getarg(1, -1), getarg(2, -1), getarg(3, NO_INN); + } + closedialog; + close; +} diff --git a/npc/functions/clientversion.txt b/npc/functions/clientversion.txt new file mode 100644 index 000000000..9d502be3d --- /dev/null +++ b/npc/functions/clientversion.txt @@ -0,0 +1,20 @@ +// Evol functions. +// Author: +// 4144 +// Description: +// Function checking the client version and reports if it is too old. + +function script checkclientversion { + if (ClientVersion > 20) return; + + mesn "Narrator"; + mes col("Warning.", 9); + mes col("Warning.", 9); + mes col("Warning: You are using an old client.", 9); + next; + mes col("Not all features will work.", 9); + next; + mes col("Please install the new client from http://www.evolonline.org/ or http://manaplus.org/", 9); + next; + return; +} diff --git a/npc/functions/confused-tree-dict.txt b/npc/functions/confused-tree-dict.txt new file mode 100644 index 000000000..4250ec35d --- /dev/null +++ b/npc/functions/confused-tree-dict.txt @@ -0,0 +1,560 @@ +// Evol scripts. +// Author: +// gumi +// rein +// Based on CrazyTree, originally made by: +// gumi +// pclouds +// veryape +// wushin +// Description: +// dictionaries for confused tree + +// Built-in variables: +// ~t lowercase hot word regex +// ~n npc name +// ~p player name or special name +// ~P player name only +// +// Custom variables: +// {{var}} random from array .D_var$ +// {{^var}} same but capitalize +// {{+var}} same but title case +// {{!var}} same but all caps +// You can also specify multiple variables, separated by a comma (,) +// +// Example: +// "*drops a {{! size }} {{ color }} {{^ sizeable object, someone }} on ~p's head*" + +function script TREE_dictionaries { + .npc$ = strnpcinfo(0); + + // special aliases below (regex of lowercase char names) + // the substitutions are an array separated by backticks (`) + // XXX: this could become a hashtable at some point if it gets too big + + setarray getvariableofnpc(.alias$[0], .npc$), + "^veryape(?:gm)?$", "hairyape", + + "^wu-?shin$", "Dwarven Princess`" + "She-Ra", + + "^reid$", "Borg Queen`" + "Mistress`" + "Milady`" + "R'eid", + + "^(?:slicer|madcamel)$", "Camel Toe", + + "^4144(?:4d494e)?$", "NPC", + + "^omatt$", "@@https://youtu.be/S2qiZoqH9OY|omatt@@`" + "o'matt", + + "^prsm$", "Refractor`" + "Overlord"; + set getvariableofnpc(.alias, .npc$), getarraysize(getvariableofnpc(.alias$, .npc$)); + + + + // special drops below (regex of lowercase char names) + // the substitutions are an array of standard replies separated by backticks (`) + // and allow {{variables}} + // XXX: this could become a hashtable at some point if it gets too big + + setarray getvariableofnpc(.sdrops$[0], .npc$), + "^reid$", "*drops an empty jar of Nutella on ~p*", + "^omatt$", "*drops Elisabeth Granneman on ~p*"; + set getvariableofnpc(.sdrops, .npc$), getarraysize(getvariableofnpc(.sdrops$, .npc$)); + + + // variables below + + setarray getvariableofnpc(.D_size$[0], .npc$), // {{size}} + "tiny", + "small", + "perfectly sized", + "large", + "huge", + "humongous", + "ginormous"; + set getvariableofnpc(.D_size, .npc$), getarraysize(getvariableofnpc(.D_size$, .npc$)); + + setarray getvariableofnpc(.D_color$[0], .npc$), // {{color}} + "red", + "orange", + "yellow", + "pink", + "aqua", + "cyan", + "blue", + "indigo", + "violet", + "purple", + "magenta", + "pink", + "black", + "white", + "grey", + "greyscale", + "brown", + "maroon", + "turquoise", + "lime", + "sky blue", + "invisible"; + set getvariableofnpc(.D_color, .npc$), getarraysize(getvariableofnpc(.D_color$, .npc$)); + + setarray getvariableofnpc(.D_violentadverb$[0], .npc$), // {{violent adverb}} + "violently", + "repeatedly", + "casually", + "forcefully", + "slowly", + "carefully", + "hopefully", + "dangerously", + "shockingly", + "religiously"; + set getvariableofnpc(.D_violentadverb, .npc$), getarraysize(getvariableofnpc(.D_violentadverb$, .npc$)); + + setarray getvariableofnpc(.D_hello$[0], .npc$), // {{hello}} + "hi", + "hi", + "hi", + "hi", + "hey", + "hey", + "hey", + "yo", + "yo", + "hello", + "hello", + "hello", + "hello", + "hello", + "hello", + "hello", + "hello", + "hello", + "hello", + "howdy", + "bonjour"; + set getvariableofnpc(.D_hello, .npc$), getarraysize(getvariableofnpc(.D_hello$, .npc$)); + + setarray getvariableofnpc(.D_violentverb$[0], .npc$), // {{violent verb}} + "slaps", + "slaps", + "slaps", + "slaps", + "slaps", // yeah the tree likes to slap a lot + "hits", + "pummels", + "beats", + "flattens", + "taunts", + "liquidates", + "spanks", + "affronts", + "tranquilizes", + "atomizes", + "impales", + "dismembers"; + set getvariableofnpc(.D_violentverb, .npc$), getarraysize(getvariableofnpc(.D_violentverb$, .npc$)); + + setarray getvariableofnpc(.D_location$[0], .npc$), // {{location}} + "Artis", + "Hurnscald", + "Tulimshar", + "Nivalis", + "Candor", + "Drasil"; + set getvariableofnpc(.D_location, .npc$), getarraysize(getvariableofnpc(.D_location$, .npc$)); + + setarray getvariableofnpc(.D_sizeableobject$[0], .npc$), // {{sizeable object}} + "trout", + "whale", + "space whale", + "penguin", + "coelacanth", + "squid", + "shrimp", + "crab", + "tentacle", + "dictionary", + "grammar book", + "textbook", + "dinosaur", + "t-rex", + "star-nosed mole", + "chimpanzee", + "mermaid", + "merman", + "piano", + "prince", + "princess", + "pinkie", + "squirrel", + "mouboo", + "wet mop", + "drunken pirate", + "cake", + "cookie", + "chocobo", + "restraining order", + "freight train", + "carnival hammer", + "crate", + "bomb", + "bowl of petinuas", + "box", + "platypus", + "magic eightball", + "vase"; + set getvariableofnpc(.D_sizeableobject, .npc$), getarraysize(getvariableofnpc(.D_sizeableobject$, .npc$)); + + setarray getvariableofnpc(.D_nsizeableobject$[0], .npc$), // {{n sizeable object}} + "octopus", + "elephant", + "angry cat", + "anvil", + "encyclopedia set"; + set getvariableofnpc(.D_nsizeableobject, .npc$), getarraysize(getvariableofnpc(.D_nsizeableobject$, .npc$)); + + setarray getvariableofnpc(.D_someone$[0], .npc$), // {{someone}} + "Voldemort", + "Cthulhu", + "Platyna", + "Hitler", + "Luvia", + "General Krukan", + "Borg Queen", + "Freeyorp", + "MadCamel"; + set getvariableofnpc(.D_someone, .npc$), getarraysize(getvariableofnpc(.D_someone$, .npc$)); + + // replies below + + setarray getvariableofnpc(.greetings$[0], .npc$), + "{{^ hello }} ~p!", + "{{^ hello }} ~p!", + "{{^ hello }} ~p!", + "{{^ hello }} ~p!", + "{{^ hello }} ~p.", + "{{^ hello }} ~p.", + "{{^ hello }} ~p.", + "{{^ hello }} ~p.", + "{{^ hello }} ~p.", + "{{^ hello }} ~p.", + "{{^ hello }} ~p, what's up?", + "{{^ hello }} ~p, anything new?", + "{{^ hello }} ~p, how are you?", + "~p!!!!", + "~p!!!", + "~p!!", + "{{^ hello }} ~p! You are looking lovely today!", + "Welcome back, ~p.", + "Welcome back, ~p.", + "Welcome back, ~p.", + "~p is back!!", + "Hello and welcome to the Aperture Science computer-aided enrichment center.", + "Greetings ~p.", + "What's up ~p?", + "What's up ~p?", + "How are you ~p?"; + set getvariableofnpc(.greetings, .npc$), getarraysize(getvariableofnpc(.greetings$, .npc$)); + + setarray getvariableofnpc(.jokes$[0], .npc$), + "How did the tree get drunk? On root beer.", + "Do you think I'm lazy?", + "I miss CrazyTree %%S.", + "I miss LazyTree %%S.", + "I'm not telling you!", + "*sighs.*", + "If I do it for you, then I have to do it for everybody.", + "What did the beaver say to the tree? It's been nice gnawing you.", + "What did the little tree say to the big tree? Leaf me alone.", + "What did the tree wear to the pool party? Swimming trunks.", + "What do trees give to their dogs? Treets.", + "What do you call a tree that only eats meat? Carniforous.", + "What do you call a tree who's always envious? Evergreen.", + "What is the tree's least favourite month? Sep-timber!", + "What kind of tree can fit into your hand? A palm-tree.", + "What was the tree's favorite subject in school? Chemistree.", + "Why did the leaf go to the doctor? It was feeling green.", + "Why doesn't the tree need sudo? Because it has root.", + "Why was the cat afraid of the tree? Because of its bark.", + "Why was the tree executed? For treeson.", + "How do trees get on the internet? They log in.", + "Why did the pine tree get into trouble? Because it was being knotty.", + "Did you hear the one about the oak tree? It's a corn-y one!", + "What do you call a blonde in a tree with a briefcase? Branch Manager.", + "How is an apple like a lawyer? They both look good hanging from a tree.", + "Why did the sheriff arrest the tree? Because its leaves rustled.", + "I'm too tired, ask someone else.", + "If you are trying to get me to tell jokes you are barking up the wrong tree!", + "You wooden think they were funny anyhow. Leaf me alone!", + "What is brown and sticky? A stick.", + "What's the best way to carve wood? Whittle by whittle.", + "What did the tree do when the bank closed? It started its own branch.", + "Do you want a brief explanation of an acorn? In a nutshell, it’s an oak tree.", + "A snare drum and a crash cymbal fell out of a tree. *BA-DUM TSSSHH*", + "How do you properly identify a dogwood tree? By the bark!", + "Where do saplings go to learn? Elementree school.", + "Why do trees make great thieves? Sticky fingers.", + "What is green, has leaves, and a trunk? A houseplant going on vacation.", + "Where can Adansonia trees go for a quick trim? To the baobarber.", + "What looks like half a spruce tree? The other half.", + "What do you give to a sick citrus tree? Lemon aid.", + "What did the tree say to the drill? You bore me.", + "What happened to the wooden car with wooden wheels and a wooden engine? It wooden go.", + "How do trees keep you in suspense? I'll tell you tomorrow.", + "Where do birch trees keep their valuables? In a river bank.", + "What kind of stories do giant sequoia trees tell? Tall tales.", + "What is the most frustrating thing about being a tree? Having so many limbs and not being able to walk.", + "What's black, highly dangerous, and lives in a tree? A crow with a machine gun.", + "What kind of wood doesn't float? Natalie Wood.", + "Two men passed a sign while looking for work. It was for tree fellers. They said: “what a shame, there are only two of us”."; + set getvariableofnpc(.jokes, .npc$), getarraysize(getvariableofnpc(.jokes$, .npc$)); + + setarray getvariableofnpc(.healing$[0], .npc$), + "Eat an apple, they're good for you.", + "If I do it for you, then I have to do it for everybody.", + "Oh, go drink a potion or something.", + "Whoops! I lost my spellbook.", + "No mana."; + set getvariableofnpc(.healing, .npc$), getarraysize(getvariableofnpc(.healing$, .npc$)); + + setarray getvariableofnpc(.whoami$[0], .npc$), + "An undercover GM.", + "An exiled GM.", + "I'm not telling you!", + "I'm a bot! I'll be level 99 one day! Mwahahahaaha!!!111!", + "Somebody said I'm a Chinese copy of CrazyTree.", + "I am your evil twin.", + "I don't remember anything after I woke up! What happened to me?", + "I don't know. Why am I here??", + "Who are you?", + "On the 8th day, God was bored and said 'There will be bots'. So here I am.", + "♪ I'm your hell, I'm your dream, I'm nothing in between ♪♪", + "♪♪ Aperture Science. We do what we must, because... we can ♪", + "I'm just a reincarnation of a copy."; + set getvariableofnpc(.whoami, .npc$), getarraysize(getvariableofnpc(.whoami$, .npc$)); + + setarray getvariableofnpc(.drops$[0], .npc$), + "*drops a {{ sizeable object }} on ~p's head.*", + "*drops a {{ sizeable object }} on ~p's head.*", + "*drops a {{ sizeable object }} on ~p's head.*", + "*drops a {{ sizeable object }} on ~p's head.*", + "*drops a {{ sizeable object }} on ~p's head.*", + "*drops a {{ sizeable object }} on ~p's head.*", + "*drops a {{ sizeable object }} on ~p's head.*", + "*drops a {{ sizeable object }} on ~p's head.*", + "*drops an {{ n sizeable object }} on ~p's head.*", + "*drops an {{ n sizeable object }} on ~p's head.*", + "*drops {{ someone }} on ~p's head.*", + "*drops a coin on ~p's head.*", + "*drops a fruit on ~p's head.*", + "*drops an apple on ~p's head.*", + "*drops an iten on ~p's head.*", + "*drops a GM on ~p.*", + "*drops a piece of moon rock on ~p's head.*", + "*drops a pin on ~p's head.*", + "*drops a rock on ~p's head.*", + "*drops a tub of paint on ~p's head.*", + "*drops a sandworm on ~p.*", + "*drops an idea in ~p's head.*", + "*drops The Hitchhiker's Guide to the Galaxy on ~p's head.*", + "Ouch.", + "Ouchy.", + "*drops dead.*", + "*sighs.*", + "Leaf me alone.", + "Stop it! I doesn't drop branches, try the Druid tree for once!"; + set getvariableofnpc(.drops, .npc$), getarraysize(getvariableofnpc(.drops$, .npc$)); + + setarray getvariableofnpc(.die$[0], .npc$), + "*drops an iten on ~p's head.*", + "*drops a piece of moon rock on ~p's head.*", + "*drops {{ someone }} on ~p's head.*", + "*drops a {{ sizeable object }} on ~p's head.*", + "*drops a {{ sizeable object }} on ~p's head.*", + "*drops a {{ sizeable object }} on ~p's head.*", + "*drops an {{ n sizeable object }} on ~p's head.*", + "*drops a {{ size }} {{ sizeable object, n sizeable object }} on ~p's head.*", + "*drops a {{ size }} {{ color }} {{ sizeable object, n sizeable object }} on ~p's head.*", + "*{{ violent adverb }} {{ violent verb }} ~p.*", + "*drops dead.*", + "*sighs.*", + "Avada Kedavra!", + "Make me!", + "Never!!", + "You die, ~p!", + "You die, ~p!", + "You die, ~p!", + "You die, ~p!", + "No!", + "In a minute.", + "Suuure... I'll get right on it..."; + set getvariableofnpc(.die, .npc$), getarraysize(getvariableofnpc(.die$, .npc$)); + + setarray getvariableofnpc(.poke$[0], .npc$), + "*tickles.*"; + set getvariableofnpc(.poke, .npc$), getarraysize(getvariableofnpc(.poke$, .npc$)); + + setarray getvariableofnpc(.disgusting$[0], .npc$), + "Ewwwww %%^."; + set getvariableofnpc(.disgusting, .npc$), getarraysize(getvariableofnpc(.disgusting$, .npc$)); + + setarray getvariableofnpc(.answer$[0], .npc$), + "42.", + "Kittens."; + set getvariableofnpc(.answer, .npc$), getarraysize(getvariableofnpc(.answer$, .npc$)); + + setarray getvariableofnpc(.burning$[0], .npc$), + "*curses ~p and dies %%c.*", + "Help! I'm on fire!", + "Oh hot.. hot hot!", + "*is glowing.*", + "*is flaming.*", + "Ehemm. Where are firefighters? I need them now!", + "*is so hot!.*", + "*slowly catches fire.*", + "*trembles with trepidation.*", + "*is immune to fire.*"; + set getvariableofnpc(.burning, .npc$), getarraysize(getvariableofnpc(.burning$, .npc$)); + + setarray getvariableofnpc(.kill$[0], .npc$), + "*curses ~p and dies %%c.*"; + set getvariableofnpc(.kill, .npc$), getarraysize(getvariableofnpc(.kill$, .npc$)); + + setarray getvariableofnpc(.silly$[0], .npc$), + "Hahaha, good one!"; + set getvariableofnpc(.silly, .npc$), getarraysize(getvariableofnpc(.silly$, .npc$)); + + setarray getvariableofnpc(.love$[0], .npc$), + "♪♪ and IIII.. will alwayyyys loooovvve youuuuu. ♪♪ %%]", + "♪♪ nothing's gonna change my love for you, you oughta know by now how much I love you.. ♪ %%]", + "♪ ..and then I go and spoil it all, by saying something stupid like: “I love you.” ♪", + "♪ ..won't you find a place for me? somewhere in your heart... ♪♪", + "Thank you.", + "♪♪ ..I can't love another when my heart is somewhere far away.. ♪", + "%%]"; + set getvariableofnpc(.love, .npc$), getarraysize(getvariableofnpc(.love$, .npc$)); + + setarray getvariableofnpc(.dance$[0], .npc$), + "I would but I am rooted to the ground.", + "Have you ever seen a tree dance before?", + "Hahaha, good one!"; + set getvariableofnpc(.dance, .npc$), getarraysize(getvariableofnpc(.dance$, .npc$)); + + setarray getvariableofnpc(.hate$[0], .npc$), + "Right back at you!", + "Ok...", + "*pats ~p, let it go...*", + "Hu hu hu, ~p hates me."; + set getvariableofnpc(.hate, .npc$), getarraysize(getvariableofnpc(.hate$, .npc$)); + + setarray getvariableofnpc(.bye$[0], .npc$), + "*waves goodbye to ~p in tears, come back soon!*"; + set getvariableofnpc(.bye, .npc$), getarraysize(getvariableofnpc(.bye$, .npc$)); + + setarray getvariableofnpc(.pain$[0], .npc$), + "Ouch.", + "Ouchy.", + "Argh.", + "Eek.", + "*howls.*", + "*screams.*", + "*groans.*", + "*cries.*", + "*faints.*", + "*shrieks.*", + "*hides behind itself.*", + "%%k", + "Why, what did I do to you? %%i"; + set getvariableofnpc(.pain, .npc$), getarraysize(getvariableofnpc(.pain$, .npc$)); + + setarray getvariableofnpc(.eightball$[0], .npc$), + "It is possible.", + "Yes!", + "Of course.", + "Naturally.", + "Obviously.", + "It shall be.", + "The outlook is good.", + "It is so.", + "One would be wise to think so.", + "The answer is certainly yes.", + "In your dreams.", + "I doubt it very much.", + "No chance.", + "The outlook is very poor.", + "Unlikely.", + "About as likely as pigs flying.", + "You're kidding, right?", + "NO!", + "NO.", + "No.", + "Maybe...", + "No clue.", + "I don't know.", + "The outlook is hazy, please ask again later.", + "What are you asking me for?", + "Come again?", + "You know the answer better than I.", + "The answer is def-- oooh! shiny thing!", + "No idea.", + "Perhaps.", + "I think it is better not to tell you.", + "Error 417: Expectation failed."; + set getvariableofnpc(.eightball, .npc$), getarraysize(getvariableofnpc(.eightball$, .npc$)); + + setarray getvariableofnpc(.bad$[0], .npc$), + "I'm not bad! You are bad!", + "OK, I'm bad.", + "I'm just a littttle bad.", + "Not as bad as the people that made me."; + set getvariableofnpc(.bad, .npc$), getarraysize(getvariableofnpc(.bad$, .npc$)); + + setarray getvariableofnpc(.no_idea$[0], .npc$), + "What?", + "What??", + "What?", + "Whatever.", + "Hmm...", + "Hmm...", + "Huh?", + "*yawns.*", + "Wait a minute...", + "What are you talking about?", + "Who are you?", + "What about me?", + "I don't know what you are talking about", + "Excuse me?", + "Very interesting.", + "Really?", + "Go on...", + "*scratches its leafy head.*", + "*feels a disturbance in the force.*", + "%%j", + "*senses a disturbance in the force.*", + "I'm bored...", + "%%U", + "%%["; + set getvariableofnpc(.no_idea, .npc$), getarraysize(getvariableofnpc(.no_idea$, .npc$)); + + setarray getvariableofnpc(.shut_up$[0], .npc$), + "*goes hide in a corner %%S.*"; + set getvariableofnpc(.shut_up, .npc$), getarraysize(getvariableofnpc(.shut_up$, .npc$)); + + setarray getvariableofnpc(.climb$[0], .npc$), + "*sways violently.*", + "*bends all the way to the ground.*", + "*creaks and bends.*", + "*welcomes those who come to play %%I.*", + "*beams with pride.*"; + set getvariableofnpc(.climb, .npc$), getarraysize(getvariableofnpc(.climb$, .npc$)); + + return; +} diff --git a/npc/functions/doors.txt b/npc/functions/doors.txt new file mode 100644 index 000000000..c1b6565ef --- /dev/null +++ b/npc/functions/doors.txt @@ -0,0 +1,59 @@ +// Evol functions. +// Author: +// 4144 +// Description: +// Doors utility functions +// Variables: +// none + +function script doorTouch { + if (getareausers() <= 1) + { + .dir = 2; + stopnpctimer; + initnpctimer; + } + close; +} + +function script doorUnTouch { + if (getareausers(.map$) == 0) + { + .dir = 4; + initnpctimer; + startnpctimer; + } + close; +} + +function script doorTimer { + stopnpctimer; + if (.dir == 2) .dir = 6; + if (.dir == 4) .dir = 8; + end; +} + +function script doorInit { + .distance = 5; + .alwaysVisible = true; + .sex = G_OTHER; + end; +} + +function script open_door { + .@door$ = getarg(0); + setnpcdir.@door$, 2; + sleep 300; + setnpcdir .@door$, 6; + sleep 300; + return 0; +} + +function script close_door { + .@door$ = getarg(0); + setnpcdir .@door$, 4; + sleep 300; + setnpcdir .@door$, 8; + sleep 300; + return 0; +} diff --git a/npc/functions/fishing.txt b/npc/functions/fishing.txt new file mode 100644 index 000000000..3d719ac78 --- /dev/null +++ b/npc/functions/fishing.txt @@ -0,0 +1,294 @@ +// Evol functions. +// Authors: +// gumi +// omatt +// Travolta +// Description: +// Fishing functions. +// Variable +// .dir +// DOWN Never try or pulled too late +// UP Bait dropped +// LEFT Fish bite bait +// +// player log on .dir is DOWN, start by choose bait menu +// player chooses bait, script addtimer in npc .dir is UP +// if player pulls before signal npc, bait is lost, set .bait to DOWN goto choose bait +// if player pulls after pull delay max, bait is lost, set .bait to DOWN goto choose bait +// npc signal .dir is LEFT +// player pulls between npc signal and pulls delay max, got the fish, set .dir to DOWN goto choose bait + +function script fishing_cleanup { + .@npc$ = getarg(0, ""); + if (.@npc$ == "") end; + + set getvariableofnpc(.char_id, .@npc$), 0; // clean acc id + set getvariableofnpc(.account_id, .@npc$), 0; // clean char id + set getvariableofnpc(.last_used, .@npc$), gettimetick(2); // set last used time + setnpcdir .@npc$, DOWN; // reset direction + return; +} + +- script global fishing handler 32767,{ + end; + +OnBite: + if (getnpcdir(@fishing_spot$) != UP) + end; + + setnpcdir @fishing_spot$, LEFT; + @fishing_tick = gettimetick(0); + specialeffect(getvariableofnpc(.bite_fx, @fishing_spot$), SELF, playerattached()); + end; + +OnCleanUp: + dispbottom l("You waited too long and lost the bait..."); + specialeffect(getvariableofnpc(.failure_fx, @fishing_spot$), SELF, playerattached()); // event fail +OnPCLogoutEvent: + fishing_cleanup @fishing_spot$; + @fishing_spot$ = ""; // unbind fishing npc + end; +} + +function script fishing { + +/////////////////////////////////////////// +// Var initialization + + .@npc$ = strnpcinfo(0); // the full name of the fishing spot + + .@account_id = getvariableofnpc(.account_id, .@npc$); // the account id of the player using the fishing spot + .@char_id = getvariableofnpc(.char_id, .@npc$); // the char id of the player using the fishing spot + .@dir = getnpcdir(.@npc$); // direction of the fishing spot + .@last_used = getvariableofnpc(.last_used, .@npc$); // when this fishing spot was last used + .@baits = getvariableofnpc(.baits, .@npc$); // bait count + + .@rod = getvariableofnpc(.fishing_rod, .@npc$); // the fishing rod required for this spot + .@rod = (.@rod ? .@rod : FishingRod); + + .@regen_time = getvariableofnpc(.cooldown, .@npc$); // cooldown for the fishing spot + .@regen_time = (.@regen_time ? .@regen_time : 20); + + .@success_fx = getvariableofnpc(.success_fx, .@npc$); // effect to show on success + .@success_fx = (.@success_fx ? .@success_fx : 27); + + .@failure_fx = getvariableofnpc(.failure_fx, .@npc$); // effect to show on failure + if (.@failure_fx < 1) + { + .@failure_fx = 28; + set getvariableofnpc(.failure_fx, .@npc$), .@failure_fx; // needed by global handler + } + + .@initial_fx = getvariableofnpc(.initial_fx, .@npc$); // effect to show when throwing the bait + .@initial_fx = (.@initial_fx ? .@initial_fx : 29); + + .@bite_fx = getvariableofnpc(.bite_fx, .@npc$); // effect to show when something bites + if (.@bite_fx < 1) + { + .@bite_fx = 30; + set getvariableofnpc(.bite_fx, .@npc$), .@bite_fx; // needed by global handler + } + + .@wait_time_min = getvariableofnpc(.wait_time_min, .@npc$); // min amount of time to wait for the line to sink + .@wait_time_min = (.@wait_time_min ? .@wait_time_min : 4000); + + .@wait_time_max = getvariableofnpc(.wait_time_max, .@npc$); // max amount of time to wait for the line to sink + .@wait_time_max = (.@wait_time_max ? .@wait_time_max : 18000); + + .@catch_time = getvariableofnpc(.catch_time, .@npc$); // the player must catch the fish within X ms after the line sinks + .@catch_time = (.@catch_time ? .@catch_time : 5000); + + .@pull_rand_max = getvariableofnpc(.pull_rand_max, .@npc$); + .@pull_rand_max = (.@pull_rand_max ? .@pull_rand_max : 800); + + .@fish_id = getvariableofnpc(.common_fish, .@npc$); + .@fish_id = (.@fish_id ? .@fish_id : CommonCarp); + + .@rare_id = getvariableofnpc(.rare_fish, .@npc$); + .@rare_fish = (.@rare_fish ? .@rare_fish : GrassCarp); + + .@rare_fish_chance = getvariableofnpc(.rare_fish_chance, .@npc$); + .@rare_fish_chance = (.@rare_fish_chance ? .@rare_fish_chance : 25); + + if (getvariableofnpc(.bait_ids[0], .@npc$) < 1) + { + // default baits (bait, chance booster) + setarray getvariableofnpc(.bait_ids[0], .@npc$), + SmallTentacles, 0, + Bread, 0, + Aquada, 1, + UrchinMeat, 0, + TortugaTongue, 2, + Tentacles, 0; + } + + if (.@baits < 1) + { + // only count it once + .@baits = getarraysize(getvariableofnpc(.bait_ids[0], .@npc$)); + set getvariableofnpc(.baits, .@npc$), .@baits; + } + + +/////////////////////////////////////////// +// Logic below + + if (countitem(.@rod) < 1) + { + dispbottom l("You don't have any @@.", getitemlink(.@rod)); + return -1; + } + + if (.@account_id > 0 && !isloggedin(.@account_id, .@char_id)) + { + fishing_cleanup .@npc$; // reset + .@dir = DOWN; + } + + if (.@char_id != getcharid(CHAR_ID_CHAR) && .@dir != DOWN) + { + dispbottom l("This fishing spot is already being used!"); + return -2; + } + + + // pull too soon + if (.@dir == UP) + { + deltimer "global fishing handler::OnCleanUp"; // cancel auto cleanup + deltimer "global fishing handler::OnBite"; + specialeffect(.@failure_fx, SELF, playerattached()); // event fail + fishing_cleanup .@npc$; // do it manually instead + dispbottom l("You pulled too soon and lost the bait."); + return -3; + } + + // pull maybe on time + else if (.@dir == LEFT) + { + deltimer "global fishing handler::OnCleanUp"; // cancel auto cleanup + fishing_cleanup .@npc$; // do it manually instead + + getmapxy .@mapbis$, .@xbis, .@ybis, UNITTYPE_PC; // get current char location + + // Leave spot, lost the bait + if (.@mapbis$ != @fishing_loc$[0] || .@xbis != @fishing_loc[0] || .@ybis != @fishing_loc[1] || @fishing_spot$ != .@npc$) + { + dispbottom l("You left your fishing spot!"); + return -4; + } + + // RNG to obtain a rare fish + // TODO: chance booster + if (rand(.@rare_fish_chance) == 0) + { + // TODO: rare fish array + .@fish_id = .@rare_id; + } + // TODO: else common fish array + + // RNG to obtain a fish + if (rand(gettimetick(0) - @fishing_tick) <= .@pull_rand_max) + { + specialeffect(.@success_fx, SELF, playerattached()); // event success + + if(!checkweight(.@fish_id, 1)) + { + dispbottom l("You caught a @@ but had no room in your inventory to carry it.", getitemlink(.@fish_id)); + makeitem .@fish_id, 1, .@mapbis$, .@xbis, .@ybis; // drop on the ground + return 0; + } + + //dispbottom l("You caught a @@!", getitemlink(.@fish_id)); <= already shows "you picked up [...]" + getitem .@fish_id, 1; + } + else + { + dispbottom l("You pulled too late and lost the bait..."); + specialeffect(.@failure_fx, SELF, playerattached()); // event fail + .@fish_id = 0; + } + + return .@fish_id; + } + + + + if (gettimetick(2) - .@last_used < .@regen_time) + { + dispbottom l("This fishing spot has just been used, give it a rest."); + return -5; + } + + + // begin fishing + narrator S_LAST_NEXT, + l("You see some fish reflecting the sun on the surface of the water."), + l("What will be the bait for the fish?"); + + mes "##B" + l("Drag and drop an item from your inventory.") + "##b"; + + .@bait = requestitem(); + .@bait_c = false; + + if (.@bait < 1) + { + narrator S_FIRST_BLANK_LINE, + l("You take your fishing rod and leave."); + + return -6; + } + + if (countitem(.@bait) < 1) + { + return -6; + } + + for (.@i = 0; .@i < .@baits; .@i += 2) + { + if (getvariableofnpc(.bait_ids[.@i], .@npc$) == .@bait) + { + .@bait_c = true; + break; + } + } + + if (.@bait_c != true) + { + narrator S_FIRST_BLANK_LINE, + l("This item cannot be used as bait here."); + + return -6; + } + + if (getvariableofnpc(.char_id, .@npc$) > 0) + { + narrator S_FIRST_BLANK_LINE, + l("Somebody took your place on this spot!"), + l("You take your fishing rod and leave."); + return -8; + } + + @fishing_spot$ = .@npc$; // bind player to fishing spot + set getvariableofnpc(.account_id, .@npc$), getcharid(CHAR_ID_ACCOUNT); // record account id + set getvariableofnpc(.char_id, .@npc$), getcharid(CHAR_ID_CHAR); // record char id + set getvariableofnpc(.last_used, .@npc$), gettimetick(2); + getmapxy(@fishing_loc$[0], @fishing_loc[0], @fishing_loc[1], 0); // record char pos + delitem .@bait, 1; + + // The player uses this spot, his bait is ready, he just has to wait for the signal. + closedialog; + + specialeffect(.@initial_fx, SELF); // throw the bait + sleep2 800; // wait 0.8s for synchronize the sound of "plop" in water with the npc dir UP. + setnpcdir .@npc$, UP; + + dispbottom l("Wait for the bait to sink underwater."); + + .@delay = rand(.@wait_time_min, .@wait_time_max); + + addtimer .@delay, "global fishing handler::OnBite"; // bite logic + addtimer (.@delay + .@catch_time), "global fishing handler::OnCleanUp"; // auto clean up + + return 0; +} diff --git a/npc/functions/game-rules.txt b/npc/functions/game-rules.txt new file mode 100644 index 000000000..f633ee5f3 --- /dev/null +++ b/npc/functions/game-rules.txt @@ -0,0 +1,59 @@ +// Evol scripts. +// Authors: +// gumi +// Qwerty Dragon +// Reid +// WildX +// Description: +// 7 main rules of Evol Online. + +function script GameRules { + if (checkweight(BookOfLaws, 1) == true && countitem(BookOfLaws) < 1) + getitem BookOfLaws, 1; // give the book if the player lost it + + narrator getarg(0, 0), + l("1. ##BDo not bot##b, this means you are not allowed to perform any AFK (away from keyboard) activity, apart from standing idle."), + l("2. ##BDo not use offensive/rude language##b in the chats or in your character(s) name(s)."), + l("3. ##BDo not spam/flood other players.##b This includes chat spam and spam by trade requests."), + l("4. ##BSpeak only English in public areas.##b You can speak whatever language you want through whispers or whenever everyone in the area can speak said language."), + l("5. ##BDo not beg others##b for money, items or favours of any kind. If you want to ask for something, do it politely and only once. Try not to annoy other players."), + l("6. ##BFollow the [@@http://wiki.evolonline.org/rules/esc|ESC@@]##b (Evol Social Convention)."), + l("7. ##BDo not multibox.##b You are not allowed to engage in combat while controlling more than one character at a time."); + return; +} + + +- script @rules 32767,{ + end; + + function read_book { + narrator S_FIRST_BLANK_LINE | S_LAST_NEXT, + l("This book outlines the laws of every city and holding in Gasaron."), + l("The first page contains the universal rules that have been agreed upon throughout the land."); + + GameRules S_NO_NPC_NAME | S_LAST_NEXT; + + narrator S_NO_NPC_NAME, + l("The next page begins to list the complex trading laws of the City of Esperia"), + l("All this seems unimportant to you right now."); + close; + } + +OnCall: + GameRules; + close; + +OnUseBook: + if (openbook()) + read_book; + bye; + +OnShelfUse: + if (openbookshelf()) + read_book; + bye; + +OnInit: + .book_name$ = "The Book of Laws"; + bindatcmd "rules", "@rules::OnCall", 0, 2, 0; +} diff --git a/npc/functions/goodbye.txt b/npc/functions/goodbye.txt new file mode 100644 index 000000000..620883b8c --- /dev/null +++ b/npc/functions/goodbye.txt @@ -0,0 +1,152 @@ +// Evol functions. +// Authors: +// gumi +// Reid +// Description: +// script terminator functions + + + +// goodbye_msg +// Tell a random goodbye sentence. +// Variables: +// .@rand = Random number between the number of "goodbye" choice. + +function script goodbye_msg { + setarray .byemsg$[0], + l("See you!"), + l("See you later!"), + l("See you soon!"), + l("Bye!"), + l("Farewell."), + l("Bye then!"), + l("Goodbye."), + l("Bye for now."), + l("Talk to you soon!"), + l("Talk to you later!"), + l("Have a good day!"), + l("Cheers!"), + l("Take care!"); + + return .byemsg$[rand(getarraysize(.byemsg$))]; +} + + + +// cwarp +// Closes the dialog, then warps the player. +// You almost always want to use this instead of `warp`. +// usage: +// cwarp; +// cwarp x, y; +// cwarp map, x, y; + +function script cwarp { + .@map$ = getarg(0, ""); + .@x = getarg(1, 0); + .@y = getarg(2, 0); + + if (getargcount() > 0 && getargcount() < 3) + { + .@npc$ = strnpcinfo(0); + .@map$ = getvariableofnpc(.map$, .@npc$); + .@x = getarg(0); + .@y = getarg(1); + } + + getmapxy .@pc_map$, .@pc_x, .@pc_y, UNITTYPE_PC; // get char location + + closedialog; // XXX: maybe send closeclientdialog in the future + + if (getargcount() < 1) + { + warp .@pc_map$, .@pc_x, .@pc_y; // no arguments, just refresh + close; + } + + if (.@map$ == .@pc_map$) + { + if (.@pc_x == .@x && .@pc_y == .@y) + { + close; // same location, don't move + } + + else + { + slide .@x, .@y; // same map, slide instead of full warp + close; + } + } + + warp .@map$, .@x, .@y; // different map, warp to given location + close; +} + + + +// cshop +// closes the dialog, then opens a shop +// if no npc is given, calls "#<npc> $" + +function script cshop { + closedialog; // XXX: maybe send closeclientdialog in the future + shop getarg(0, "#" + strnpcinfo(0) + " $"); + //close; => the shop buildin already sends close, and is a terminator itself +} + + + +// cstorage +// closes the dialog, then opens storage + +function script cstorage { + closedialog; // XXX: maybe send closeclientdialog in the future + openstorage; + close; +} + + + +// bye +// closes the dialog without waiting for the player to press close +// can also display an emote + +function script bye { + .@emote = getarg(0, -1); + closedialog; // XXX: maybe send closeclientdialog in the future + + if (.@emote >= 0) + emotion .@emote; + + close; +} + + + +// goodbye +// same as bye, but also displays a canned message +// can also display an emote + +function script goodbye { + npctalkonce(goodbye_msg()); + bye getarg(0, -1); +} + + + +// goodbye2 +// Waits for the player to press close, displays a canned message, +// ends execution. +// Can also display an emote + +function script goodbye2 { + .@emote = getarg(0, -1); + + close2; + npctalkonce(goodbye_msg()); + + if (.@emote >= 0) + emotion .@emote; + + end; +} diff --git a/npc/functions/hammocks.txt b/npc/functions/hammocks.txt new file mode 100644 index 000000000..8e1c2fec4 --- /dev/null +++ b/npc/functions/hammocks.txt @@ -0,0 +1,50 @@ +// Evol functions. +// Authors: +// 4144 +// Reid +// Description: +// Hammocks utility functions +// Variables: +// none + +function script hamTouchLeft { + if (getareausers() <= 1) + { + .dir = 0; + stopnpctimer; + initnpctimer; + } + close; +} + +function script hamUnTouch { + if (getareausers() == 0) + { + .dir = 2; + initnpctimer; + startnpctimer; + } + close; +} + +function script hamTimerLeft { + stopnpctimer; + if (.dir == 2) .dir = 0; + end; +} + +function script hamTouchRight { + if (getareausers() <= 1) + { + .dir = 0; + stopnpctimer; + initnpctimer; + } + close; +} + +function script hamTimerRight { + stopnpctimer; + if (.dir == 2) .dir = 0; + end; +} diff --git a/npc/functions/harbours.txt b/npc/functions/harbours.txt new file mode 100644 index 000000000..63d58076b --- /dev/null +++ b/npc/functions/harbours.txt @@ -0,0 +1,39 @@ +// Evol scripts. +// Author: +// Reid +// Description: +// Harbour utility functions +// Animation: +// Length: 1680 +// Values: +// 2 Hook moving down. +// 4 Hook moving up. +// 6 Hook down. +// 8 Hook up. + +function script harbourClic { + if (.dir == 0) + { + .dir = 2; + + initnpctimer; + startnpctimer; + close; + } + + if (.dir == 6) + { + .dir = 4; + + initnpctimer; + startnpctimer; + close; + } +} + +function script harbourTimer { + stopnpctimer; + if (.dir == 2) .dir = 6; + if (.dir == 4) .dir = 0; + end; +} diff --git a/npc/functions/hello.txt b/npc/functions/hello.txt new file mode 100644 index 000000000..9399b3b58 --- /dev/null +++ b/npc/functions/hello.txt @@ -0,0 +1,23 @@ +// Evol functions. +// Author: +// Reid +// Description: +// Tell a random greeting sentence. + +function script hello { + + switch (rand(3)) + { + case 0: + npctalkonce(l("Heya!")); + break; + case 1: + npctalkonce(l("Hi.")); + break; + case 2: + npctalkonce(l("Nice day to you.")); + break; + } + + return; +} diff --git a/npc/functions/input.txt b/npc/functions/input.txt new file mode 100644 index 000000000..cf0382d25 --- /dev/null +++ b/npc/functions/input.txt @@ -0,0 +1,66 @@ +// Evol functions. +// Author: +// 4144 +// Description: +// Input utility functions +// Variables: +// none + +function script menuint { + deletearray .@vals; + .@menustr$ = ""; + .@cnt = 0; + + for (.@f = 0; .@f < getargcount(); .@f = .@f + 2) + { + if (getarg(.@f) != "") + { + .@menustr$ = .@menustr$ + getarg(.@f) + ":"; + .@vals[.@cnt] = getarg(.@f + 1); + .@cnt ++; + } + } + + .@vals[.@cnt] = -1; + @menu = 255; + @menuret = -1; + select(.@menustr$); + if (@menu == 255) + return -1; + + @menu --; + if (@menu < 0 || @menu >= getarraysize(.@vals) - 1) + return -1; + + @menuret = .@vals[@menu]; + return @menuret; +} + +function script menustr { + deletearray .@vals$; + .@menustr$ = ""; + .@cnt = 0; + + for (.@f = 0; .@f < getargcount(); .@f = .@f + 2) + { + if (getarg(.@f) != "") + { + .@menustr$ = .@menustr$ + getarg(.@f) + ":"; + .@vals$[.@cnt] = getarg(.@f + 1); + .@cnt ++; + } + } + + @menu = 255; + @menuret = -1; + select(.@menustr$); + if (@menu == 255) + return ""; + + @menu --; + if (@menu < 0 || @menu >= getarraysize(.@vals$)) + return ""; + + @menuret$ = .@vals$[@menu]; + return @menuret$; +} diff --git a/npc/functions/inventoryplace.txt b/npc/functions/inventoryplace.txt new file mode 100644 index 000000000..4a5e08cad --- /dev/null +++ b/npc/functions/inventoryplace.txt @@ -0,0 +1,37 @@ +// Evol functions. +// Authors: +// Qwerty Dragon +// Reid +// Description: +// Check if the player have enough place on his inventory to accept new items with arguments: +// getarg(even numbers) item ID, +// getarg(odd numbers) number of items, + +function script inventoryplace { + + .@argc = getargcount(); + + if (.@argc % 2 != 0) + { + debugmes "inventoryplace: Wrong argument count."; + close; + } + + for (.@i = .@j = 0; .@i < .@argc; .@i += 2) + { + setarray .@item[.@j], getarg(.@i); + setarray .@amount[.@j], getarg(.@i + 1); + ++.@j; + } + + if (!checkweight2(.@item, .@amount)) + { + narrator S_FIRST_BLANK_LINE, + l("It looks like you can't carry anything else for now."), + l("You should come back when you have some free space."); + + close; + } + + return true; +} diff --git a/npc/functions/legiontalk.txt b/npc/functions/legiontalk.txt new file mode 100644 index 000000000..fbc35e1f7 --- /dev/null +++ b/npc/functions/legiontalk.txt @@ -0,0 +1,66 @@ +// Evol functions. +// Authors: +// Akko Teru +// Reid +// Qwerty Dragon +// Description: +// Tell a random sentence suited to Aemil's Legion in Artis. + +function script legiontalk { + + switch (rand(15)) + { + case 0: + npctalkonce(l("Do I look like a tree? I feel like one.")); + //speech( + // l("Do you feel too weak even to do damage to this areas wishy-washy wildlife?"), + // l("Then concentrate your anger upon the trees hereabouts, you will gain experience whilst leveling your sword skill on them."), + // l("Oh, and a fruit may even fall for you if you are lucky! But stay alert to pick up your drops.")); + //close; + break; + case 1: + npctalkonce(l("I'm a little busy right now.")); + break; + case 2: + npctalkonce(l("Not in the mood to chat.")); + break; + case 3: + npctalkonce(l("My breath smells bad.")); + break; + case 4: + npctalkonce(l("Don't distract me, I have to stay alert.")); + break; + case 5: + npctalkonce(l("Give me some space.")); + break; + case 6: + npctalkonce(l("Can you please go away?")); + break; + case 7: + npctalkonce(l("Can't talk right now, I'm on patrol duty.")); + break; + case 8: + npctalkonce(l("What're you looking at?!")); + break; + case 9: + npctalkonce(l("I can't stay here and talk all day. I have a job to do.")); + break; + case 10: + npctalkonce(lg("Keep moving girl.", "Keep moving boy.")); + break; + case 11: + npctalkonce(lg("So you think you're tough? A warrior must also be loyal and patient.")); + break; + case 12: + emotion E_LOOKAWAY; + break; + case 13: + npctalkonce(l("Practice! There are no secrets to becoming a warrior.")); + break; + case 14: + npctalkonce(l("There is no honor in fighting a weak opponent.")); + break; + } + + return; +} diff --git a/npc/functions/main.txt b/npc/functions/main.txt new file mode 100644 index 000000000..243ae383d --- /dev/null +++ b/npc/functions/main.txt @@ -0,0 +1,215 @@ +// Evol functions. +// Authors: +// 4144 +// Travolta +// Description: +// Build in functions. + +function script menuimage { + return getarg(0) + "|" + getarg(1); +} + +function script menuaction { + return "[" + getarg(0) + "]"; +} + +function script mesn { + if (getargcount() > 0) + { + .@s$ = "[" + getarg(0) + "]"; + } + else + { + .@s$ = "[" + strnpcinfo(1) + "]"; + } + mes .@s$; + return; +} + +function script mesq { + mes "\"" + getarg(0)+ "\""; + return; +} + +function script g { + return Sex == 0 ? getarg(0) : getarg(1); +} + +function script col { + .@color = getarg(1); + if (.@color < 0) .@color = 0; + if (.@color > 9) .@color = 9; + return "##" + .@color + getarg(0) + "##0"; +} + +function script adddefaultskills { + if (getskilllv(NV_BASIC) < 6) + { + skill NV_BASIC, 6, 0; + } + return; +} + +function script addremovemapmask { + setmapmask getarg(0), (getmapmask(getarg(0)) | (getarg(1) + getarg(2))) ^ getarg(2); + return; +} + +// Function to show narrator text. Accepts string args. +// If first arg is a number N, then it represents bit flags. +// Bit flags : +// 0x1 -- blank line at beginning +// 0x2 -- blank line at the end +// 0x4 -- use last "next;" +// 0x8 -- don't use first "mesn;" +function script narrator { + .@start = 0; + .@argc = getargcount(); + .@flags = 0; + + if (.@argc > 1 && !isstr(getarg(0))) + { + .@start = 1; + .@flags = getarg(0); + } + + if (.@flags & 0x1) + mes ""; + + if (!(.@flags & 0x8)) + mesn l("Narrator"); + + for (.@i = .@start; .@i < .@argc; .@i++) + { + mes col(getarg(.@i), 9); + if (.@i < .@argc - 1) + next; + } + + if (.@flags & 0x4) + next; + else if (.@flags & 0x2) + mes ""; + + return; +} + +// Function to show NPC speech. Accepts string args. +// If first arg is a number N, then it represents bit flags. +// Bit flags : +// 0x1 -- blank line at beginning +// 0x2 -- blank line at the end +// 0x4 -- use last "next;" +// 0x8 -- don't use first "mesn;" +function script speech { + .@start = 0; + .@argc = getargcount(); + .@flags = 0; + + if (.@argc > 1 && !isstr(getarg(0))) + { + .@start = 1; + .@flags = getarg(0); + } + + if (.@flags & 0x1) + mes ""; + + if (!(.@flags & 0x8)) + mesn; + + for (.@i = .@start; .@i < .@argc; .@i++) + { + mesq getarg(.@i); + + if (.@i < .@argc - 1) + next; + } + + if (.@flags & 0x4) + next; + else if (.@flags & 0x2) + mes ""; + + return; +} + +// Show debug message if .debug variable of NPC is set to 1 +function script npcdebug { + if (getvariableofnpc(.debug, strnpcinfo(3))) + debugmes strnpcinfo(3) + ": " + getarg(0); + return; +} + +function script askyesno { + return select(menuaction(l("Yes")), + menuaction(l("No"))); +} + +// Argument: +// 0 Quest variable +// 1 Current value +// 2 Next value +function script compareandsetq { + if (getq(getarg(0)) == getarg(1)) + { + setq getarg(0), getarg(2); + return true; + } + return false; +} + +// Use a delay to prevent spams from NPC that display text without the +// use of (a) close/next function(s). +// Argument: +// 0 Text to display +// 1 Lock delay (default = 1) +// 2 Message function: (default = 0) +// 0 = npctalk3 +// 1 = npctalk +// 2 = message +function script npctalkonce { + // lock mechanism + switch (getarg(2, 0)) + { + case 1: + if (gettimetick(2) <= getvariableofnpc(.talk_lock, strnpcinfo(NPC_NAME_UNIQUE))) + return false; + set(getvariableofnpc(.talk_lock, strnpcinfo(NPC_NAME_UNIQUE)), gettimetick(2) + getarg(1, 1)); + break; + default: + if (gettimetick(2) <= @NPC_TALK_LOCK[getnpcid(0)]) + return false; + @NPC_TALK_LOCK[getnpcid(0)] = gettimetick(2) + getarg(1, 1); + } + + // talk mechanism + switch (getarg(2, 0)) + { + case 0: npctalk3(getarg(0)); break; + case 1: npctalk(getarg(0)); break; + case 2: message(strcharinfo(0), getarg(0)); + } + + return true; +} + +function script getquestlink { + return "[@@q" + getarg(0) + "|@@]"; +} + +function script getmonsterlink { + return "[@@m" + getarg(0) + "|@@]"; +} + +function script getpetlink { + return "[@@p" + getarg(0) + "|@@]"; +} + +function script getmercenarylink { + return "[@@M" + getarg(0) + "|@@]"; +} + +function script gethomunculuslink { + return "[@@h" + getarg(0) + "|@@]"; +} diff --git a/npc/functions/marriage.txt b/npc/functions/marriage.txt new file mode 100644 index 000000000..d9e48bf54 --- /dev/null +++ b/npc/functions/marriage.txt @@ -0,0 +1,293 @@ +// Evol functions. +// Author: +// 4144 +// Description: +// Functions for marriage + +// check is player is near marriage npc +// args: +// 0 - player name +// returns: +// true if player located near npc. +function script marriagecheckname { + .@name$ = getarg(0); + if (.@name$ == "") + { + // no other registrand + return false; + } + .@id = getcharid(0, .@name$); + .@accoundId = getcharid(3, .@name$); + if (isloggedin(.@accoundId, .@id) == false) + { + // registrant not logged in + return false; + } + getmapxy(.@mapname$, .@x, .@y, 0, .@name$); + if (.@mapname$ != strnpcinfo(4)) + { + // registrant on other map + return false; + } + if (distance(.@x, .@y, .x, .y) > .distance) + { + // registrant too far + return false; + } + return true; +} + +// return player name registered with same gender like attached player +function script getmarriageregistrant { + if (Sex) + { + .@name$ = getvariableofnpc(.maleName$, strnpcinfo(3)); + } + else + { + .@name$ = getvariableofnpc(.femaleName$, strnpcinfo(3)); + } + return .@name$; +} + +// return registered marriage partner name +function script getmarriagepartner { + if (Sex) + { + .@name$ = getvariableofnpc(.femaleName$, strnpcinfo(3)); + } + else + { + .@name$ = getvariableofnpc(.maleName$, strnpcinfo(3)); + } + if (marriagecheckname(.@name$)) + return .@name$; + return ""; +} + +// register attached player as partner for marriage +function script marriageregisterself { + if (Sex) + { + set getvariableofnpc(.maleName$, strnpcinfo(3)), strcharinfo(0); + set getvariableofnpc(.maleName_partner$, strnpcinfo(3)), ""; + } + else + { + set getvariableofnpc(.femaleName$, strnpcinfo(3)), strcharinfo(0); + set getvariableofnpc(.femaleName_partner$, strnpcinfo(3)), ""; + } + return; +} + +// return player name what was accepted by partner +function script getmarriagepartneraccepted { + if (Sex) + { + .@name$ = getvariableofnpc(.femaleName_partner$, strnpcinfo(3)); + } + else + { + .@name$ = getvariableofnpc(.maleName_partner$, strnpcinfo(3)); + } + return .@name$; +} + +// return true if partner present near and partner accepted you +function script ismarriagepartneraccepted { + .@partner$ = getmarriagepartner(); + if (.@partner$ == "") + return false; + .@name$ = getmarriagepartneraccepted(); + if (.@name$ == strcharinfo(0)) + return true; + return false; +} + +// accept for attached player his/her partner +// args: +// 0 - partner name +function script marriageacceptpartner { + .@name$ = getarg(0); + if (Sex) + { + set getvariableofnpc(.maleName_partner$, strnpcinfo(3)), .@name$; + } + else + { + set getvariableofnpc(.femaleName_partner$, strnpcinfo(3)), .@name$; + } + return; +} + +function script askmarry { + speech l("Do you want to marry @@?", getarg(0)); + if (askyesno() == ASK_YES) + return true; + return false; +} + +// start marriage registration process +function script marriageregister { + .@partner$ = getmarriagepartner(); + if (.@partner$ == "") + { // no partner registered + speech l("Ok I add your name... @@...", strcharinfo(0)); + marriageregisterself(); + next; + speech lg("Now wait for your partner, then talk to me again."); + npctalk l("@@ registered for marriage. Waiting for partner...", strcharinfo(0)); + close; + } + else + { // partner already registered + if (askmarry(.@partner$) == true) + { + marriageregisterself(); + marriageacceptpartner(.@partner$); + npctalk l("@@ registered for marriage and accepted partner @@!", strcharinfo(0), .@partner$); + npctalk l("Waiting for @@...", .@partner$); + close; + } + else + { + close; + } + } + return; +} + +// remove all marriage registations +function script marriageclear { + set getvariableofnpc(.maleName$, strnpcinfo(3)), ""; + set getvariableofnpc(.femaleName$, strnpcinfo(3)), ""; + set getvariableofnpc(.maleName_partner$, strnpcinfo(3)), ""; + set getvariableofnpc(.femaleName_partner$, strnpcinfo(3)), ""; + return; +} + +// do actual marriage +function script domarriage { + .@name$ = strcharinfo(0); + .@partner$ = getarg(0); + if (marriage(.@partner$)) + { + speech l("You got married to @@!", .@partner$); + npctalk l("@@ and @@ just got married!", .@name$, .@partner$); + } + else + { + npctalk l("Marriage failed."); + } + marriageclear(); + return; +} + +// marry main code +function script marriagemarry { + .@registrant$ = getmarriageregistrant(); + if (marriagecheckname(.@registrant$) == true) + { + if (.@registrant$ == strcharinfo(0)) + { + if (ismarriagepartneraccepted()) + { + .@partner$ = getmarriagepartner(); + if (marriagecheckname(.@partner$) == false) + { + speech l("Partner not ready."); + } + else if (askmarry(.@partner$) == true) + { + domarriage(.@partner$); + } + } + else + { + speech l("You already registered. Waiting for your partner..."); + } + } + else + { + speech l("Sorry, I'm busy with other registrations."), + l("Come after a little while."); + } + close; + } + + speech l("What can I do for you?"); + switch (select(l("I want to register for marriage."), + l("Nothing"))) + { + case 1: + marriageregister; + break; + case 2: + break; + } + return; +} + +// divorce main code +function script marriagedivorce { + speech l("What can I do for you?"); + switch (select(l("I want to divorce."), + l("Nothing"))) + { + case 1: + speech lg("Are you sure?"); + if (askyesno() == ASK_YES) + { + if (divorce()) + { + speech l("You are now divorced!"), + l("Good look."); + npctalk l("@@ divorced!", strcharinfo(0)); + } + else + { + speech l("Divorce error!"); + } + } + break; + case 2: + break; + } + return; +} + +// main function for marriage +function script marriagemain { + if (Sex > 1) + { + speech l("Sorry i can't help you. Go away!"); + close; + } + + if (getpartnerid() != 0) + { // have partner + marriagedivorce(); + } + else + { // no partner + marriagemarry(); + } + + return; +} + +// check registration list by timer +function script marriagecheck { + .@name$ = getvariableofnpc(.maleName$, strnpcinfo(3)); + if (.@name$ != "" && marriagecheckname(.@name) == false) + { + set getvariableofnpc(.maleName$, strnpcinfo(3)), ""; + set getvariableofnpc(.maleName_partner$, strnpcinfo(3)), ""; + } + .@name$ = getvariableofnpc(.femaleName$, strnpcinfo(3)); + if (.@name$ != "" && marriagecheckname(.@name) == false) + { + set getvariableofnpc(.femaleName$, strnpcinfo(3)), ""; + set getvariableofnpc(.femaleName_partner$, strnpcinfo(3)), ""; + } +} diff --git a/npc/functions/masks.txt b/npc/functions/masks.txt new file mode 100644 index 000000000..98e8bdf87 --- /dev/null +++ b/npc/functions/masks.txt @@ -0,0 +1,68 @@ +// Evol functions. +// Author: +// Reid +// Description: +// Triggers functions to add and remove masks. +// Variables: +// none + +// Artis Aemil's Legion + +function script artisALRemTopMask { + if ((getareausers("001-2-33", 23, 27, 45, 31) >= 1) || + (getareausers("001-2-33", 23, 32, 26, 38) >= 1) || + (getareausers("001-2-33", 42, 32, 45, 38) >= 1)) + { + removemapmask "001-2-33", 4; + } + return 0; +} + +function script artisALAddTopMask { + if ((getareausers("001-2-33", 23, 27, 45, 31) == 0) && + (getareausers("001-2-33", 23, 32, 26, 38) == 0) && + (getareausers("001-2-33", 42, 32, 45, 38) == 0)) + { + addmapmask "001-2-33", 4; + } + return 0; +} + +function script artisALRemBotMask { + if (getareausers("001-2-33", 23, 32, 45, 46) >= 1) + { + removemapmask "001-2-33", 8; + } + return 0; +} + +function script artisALAddBotMask { + if (getareausers("001-2-33", 23, 32, 45, 46) == 0) + { + addmapmask "001-2-33", 8; + } + return 0; +} + +function script artisALUpdateMask { + if (getareausers("001-2-33", 23, 32, 45, 46) >= 1) + { + removemapmask "001-2-33", 8; + } + else + { + addmapmask "001-2-33", 8; + } + if ((getareausers("001-2-33", 23, 27, 45, 31) >= 1) || + (getareausers("001-2-33", 23, 32, 26, 38) >= 1) || + (getareausers("001-2-33", 42, 32, 45, 38) >= 1)) + { + removemapmask "001-2-33", 4; + } + else + { + addmapmask "001-2-33", 4; + } + + return 0; +} diff --git a/npc/functions/math.txt b/npc/functions/math.txt new file mode 100644 index 000000000..004125c7b --- /dev/null +++ b/npc/functions/math.txt @@ -0,0 +1,40 @@ +// Evol functions. +// Authors: +// 4144 +// Reid +// Description: +// Math functions + + +// abs(<int>) +// returns the absolute value of the passed integer + +function script abs { + .@n = getarg(0); + return .@n >= 0 ? .@n : -.@n; +} + + + +// lognbaselvl({<multiplicator>{, <min value>}}) +// returns BaseLevel * logn (BaseLevel * alpha). + +function script lognbaselvl { + .@alpha = getarg(0, 1); + .@min = getarg(1, 1); + .@ret = 0; + .@pc_level = BaseLevel * .@alpha; + + while (.@pc_level >>= 1) + { + ++.@ret; + } + .@ret *= BaseLevel; + + if (.@ret <= .@min) + { + .@ret = .@min; + } + + return .@ret; +} diff --git a/npc/functions/mouboofunc.txt b/npc/functions/mouboofunc.txt new file mode 100644 index 000000000..6129c083e --- /dev/null +++ b/npc/functions/mouboofunc.txt @@ -0,0 +1,89 @@ +// Evol functions. +// Author: +// Reid +// Description: +// Various scripts used in walking mouboo NPCs. + +function script moubootalk { + switch (rand(4)) + { + case 0: + npctalkonce(l("Moooooo!")); + break; + case 1: + npctalkonce(l("Moo!")); + break; + case 2: + npctalkonce(l("Moooooooooooo!")); + break; + case 3: + npctalkonce(l("Moooo!")); + break; + } + return; +} + +function script mouboocheckxy { + setarray .nearnpc$[0], "Mouboo#Artis0", + "Mouboo#Artis1", + "Mouboo#Artis2", + "Mouboo#Artis3", + "Taree"; + for (.@size = 0; .@size < getarraysize(.nearnpc$); .@size++) + { + if (strcmp(.name$, .nearnpc$[.@size]) == 0) + { + continue; + } + + .@npc_x = getvariableofnpc(.x, .nearnpc$[.@size]); + .@npc_y = getvariableofnpc(.y, .nearnpc$[.@size]); + + if (.@npc_x == .x && .@npc_y == .y) + { + return 1; + } + } + + return 0; +} + +function script moubootimer { + if (mouboocheckxy() && !isunitwalking()) + { + movetonextpoint; + } + else if (rand(0,6) == 5) + { + if (!isunitwalking()) + { + movetonextpoint; + } + } + initnpctimer; + end; +} + +function script mouboograph { + initmovegraph "down_pos", 66, 79, 75, 86, + "left_pos", 66, 79, 75, 86, + "up_pos", 66, 79, 75, 86, + "right_pos", 66, 79, 75, 86; + + setmovegraphcmd "down_pos", "left_pos", 1, "dir 2", + "down_pos", "up_pos", 1, "dir 4", + "down_pos", "right_pos", 1, "dir 6", + "left_pos", "down_pos", 1, "dir 0", + "left_pos", "up_pos", 1, "dir 4", + "left_pos", "right_pos", 1, "dir 6", + "up_pos", "down_pos", 1, "dir 0", + "up_pos", "left_pos", 1, "dir 2", + "up_pos", "right_pos", 1, "dir 6", + "right_pos", "down_pos", 1, "dir 0", + "right_pos", "left_pos", 1, "dir 2", + "right_pos", "up_pos", 1, "dir 4"; + + firstmove "wait 2", "down_pos"; + initnpctimer; + end; +} diff --git a/npc/functions/npcmove.txt b/npc/functions/npcmove.txt new file mode 100644 index 000000000..eb6acded0 --- /dev/null +++ b/npc/functions/npcmove.txt @@ -0,0 +1,142 @@ +// Evol functions. +// Author: +// 4144 +// Description: +// Moving npc utility functions +// Variables: +// none + +function script initpath { + deletearray getvariableofnpc(.movepathcmd$, strnpcinfo(3)); + deletearray getvariableofnpc(.movepathy, strnpcinfo(3)); + deletearray getvariableofnpc(.movepathx, strnpcinfo(3)); + .@cnt = 0; + + for (.@f = 0; .@f < getargcount(); .@f = .@f + 3) + { + set getvariableofnpc(.movepathcmd$[.@cnt], strnpcinfo(3)), getarg(.@f); + set getvariableofnpc(.movepathx[.@cnt], strnpcinfo(3)), getarg(.@f + 1); + set getvariableofnpc(.movepathy[.@cnt], strnpcinfo(3)), getarg(.@f + 2); + .@cnt ++; + } + //debugmes "array size: " + str(getarraysize(getvariableofnpc(.movepath, strnpcinfo(3)))); + return; +} + +function script domoveaction { + //debugmes "domoveaction: " + str(getvariableofnpc(.movepos, strnpcinfo(3))); + .@pos = getvariableofnpc(.movepos, strnpcinfo(3)); + if (.@pos >= getarraysize(getvariableofnpc(.movepathx, strnpcinfo(3))) || .@pos < 0) + return; + //debugmes "walking"; + .@cmd$ = getvariableofnpc(.movepathcmd$[.@pos], strnpcinfo(3)); + //debugmes "cmd: " + .@cmd$; + + if (.@cmd$ == "move") + { + npcwalkto getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)), getvariableofnpc(.movepathy[.@pos], strnpcinfo(3)); + } + else if (.@cmd$ == "dir") + { + setnpcdir getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)); + return 2; + } + else if (.@cmd$ == "wait") + { + set getvariableofnpc(.waitticks, strnpcinfo(3)), getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)); + } + else if (.@cmd$ == "emote") + { + unitemote getnpcid(0), getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)); + return 2; + } + else if (.@cmd$ == "class") + { + .class = getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)); + return 2; + } + else if (.@cmd$ == "warp") + { + movenpc strnpcinfo(3), getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)), getvariableofnpc(.movepathy[.@pos], strnpcinfo(3)); + } + else if (.@cmd$ == "goto") + { + set getvariableofnpc(.movepos, strnpcinfo(3)), getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)); + return 0; + } + else if (.@cmd$ == "rmove") + { + getmapxy(.@mapName$, .@x, .@y, 1); + npcwalkto .@x + getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)), .@y + getvariableofnpc(.movepathy[.@pos], strnpcinfo(3)); + } + else if (.@cmd$ == "speed") + { + .speed = getvariableofnpc(.movepathx[.@pos], strnpcinfo(3)); + return 2; + } + else if (.@cmd$ == "sit") + { + npcsit; + } + else if (.@cmd$ == "stand") + { + npcstand; + } + return 1; +} + +function script movetonextpos { + .@wait = getvariableofnpc(.waitticks, strnpcinfo(3)); + if (.@wait > 0) + { + .@wait --; + //debugmes "wait"; + set getvariableofnpc(.waitticks, strnpcinfo(3)), .@wait; + return; + } + .@true = 1; + while (.@true) + { + .@true = 0; + .@pos = getvariableofnpc(.movepos, strnpcinfo(3)); + //debugmes "movetonextpos: " + str(.@pos); + .@res = domoveaction(.@pos); + if (.@res == 1 || .@res == 2) + { + .@pos++; + if (.@pos >= getarraysize(getvariableofnpc(.movepathx, strnpcinfo(3)))) + .@pos = 0; + set getvariableofnpc(.movepos, strnpcinfo(3)), .@pos; + } + if (.@res == 0 || .@res == 2) + { + .@true = 1; + } + } + return; +} + +function script initialmove { + set getvariableofnpc(.movepos, strnpcinfo(3)), 0; + set getvariableofnpc(.waitticks, strnpcinfo(3)), -1; + movetonextpos; + return; +} + +function script getmovecmd { + .@pos = getvariableofnpc(.movepos, strnpcinfo(3)); + if (.@pos >= getarraysize(getvariableofnpc(.movepathx, strnpcinfo(3))) || .@pos < 0) + return ""; + return getvariableofnpc(.movepathcmd$[.@pos], strnpcinfo(3)); +} + +function script domovestep { + if (isunitwalking()) + { + initnpctimer; + end; + } + movetonextpos; + initnpctimer; + end; +} diff --git a/npc/functions/npcmovegraph.txt b/npc/functions/npcmovegraph.txt new file mode 100644 index 000000000..b26f9a162 --- /dev/null +++ b/npc/functions/npcmovegraph.txt @@ -0,0 +1,485 @@ +// Evol functions. +// Author: +// Travolta +// Description: +// Moving npc utility functions (graph-based) +// Variables: +// none + +function script initmovegraph { + deletearray getvariableofnpc(.movegraphcmd$, strnpcinfo(3)); + deletearray getvariableofnpc(.movegraphlabels$, strnpcinfo(3)); + deletearray getvariableofnpc(.movegraphweight, strnpcinfo(3)); + deletearray getvariableofnpc(.movegraphflags, strnpcinfo(3)); + deletearray getvariableofnpc(.movepos_y1, strnpcinfo(3)); + deletearray getvariableofnpc(.movepos_x1, strnpcinfo(3)); + deletearray getvariableofnpc(.movepos_x2, strnpcinfo(3)); + deletearray getvariableofnpc(.movepos_y2, strnpcinfo(3)); + .@cnt = 0; + + for (.@f = 0; .@f < getargcount();) + { + set getvariableofnpc(.movegraphlabels$[.@cnt], strnpcinfo(3)), getarg(.@f++); + set getvariableofnpc(.movepos_x1[.@cnt], strnpcinfo(3)), getarg(.@f++); + set getvariableofnpc(.movepos_y1[.@cnt], strnpcinfo(3)), getarg(.@f++); + if (!isstr(getarg(.@f, "label"))) + { + set getvariableofnpc(.movepos_x2[.@cnt], strnpcinfo(3)), getarg(.@f++); + set getvariableofnpc(.movepos_y2[.@cnt], strnpcinfo(3)), getarg(.@f++); + } + .@cnt ++; + } + return; +} + +function script findmovegraphlabel { + if (!getargcount()) + { + debugmes "findmovegraphlabel: no argument"; + return -1; + } + if (!isstr(getarg(0))) + { + debugmes "findmovegraphlabel: need string argument"; + return -1; + } + + .@arg$ = getarg(0); + for (.@i = 0; .@i < getarraysize(getvariableofnpc(.movegraphlabels$, strnpcinfo(3))); .@i++) + { + if (getvariableofnpc(.movegraphlabels$[.@i], strnpcinfo(3)) == .@arg$) + return .@i; + } + + npcdebug "findmovegraphlabel: label not found: " + getarg(0); + return -1; +} + +/* setmovegraphcmd(fromPositionLabel,toPositionLabel[,moveChanceWeight[,moveFlags]],postCommand, ...); + * This function manipulates NPC moving graph. Before calling it, make sure + * `initmovegraph' was called. The function accepts 3-5 parameters (many times): + * fromPositionLabel, toPositionLabel -- starting and ending position of NPC move + * moveChanceWeight -- positive integer, represents the chance of moving in given direction. (optional) + * moveFlags -- if .mg_flags & moveFlags != 0, move is possible. (optional) + * postCommand -- either "moveon" (start moving to next location straight after arriving from + * fromPositionLabel to toPositionLabel) or a semicolon-separated set of commands + * ("wait 3", "emote 5" etc, see `execmovecmd') that will be executed after arrival. + * The commands don't have to end with ";moveon", it's executed in the end by default. + */ +function script setmovegraphcmd { + .@size = getarraysize(getvariableofnpc(.movepos_x1, strnpcinfo(3))); + + for (.@f = 0; .@f < getargcount();) + { + .@from = findmovegraphlabel(getarg(.@f++)); + .@to = findmovegraphlabel(getarg(.@f++)); + .@weight = 1; + if (!isstr(getarg(.@f))) + .@weight = getarg(.@f++); + .@flags = 0xffff; + if (!isstr(getarg(.@f))) + .@flags = getarg(.@f++); + .@cmd$ = getarg(.@f++); + .@index = .@from * .@size + .@to; // emulation of 2d array + set getvariableofnpc(.movegraphcmd$[.@index], strnpcinfo(3)), .@cmd$; + set getvariableofnpc(.movegraphweight[.@index], strnpcinfo(3)), .@weight; + set getvariableofnpc(.movegraphflags[.@index], strnpcinfo(3)), .@flags; + } + return; +} + +function script execmovecmd { + + explode(.@cmd$, getarg(0), " "); + + if (.@cmd$[0] == "moveon") + { + return 0; + } + else if (.@cmd$[0] == "dir") + { + .dir = atoi(.@cmd$[1]); + } + else if (.@cmd$[0] == "sit") + { + npcsit; + } + else if (.@cmd$[0] == "stand") + { + npcstand; + } + else if (.@cmd$[0] == "wait") + { + set getvariableofnpc(.waitticks, strnpcinfo(3)), atoi(.@cmd$[1]); + return 1; + } + else if (.@cmd$[0] == "emote") + { + unitemote getnpcid(0), atoi(.@cmd$[1]); + } + else if (.@cmd$[0] == "class") + { + .class = atoi(.@cmd$[1]); + } + else if (.@cmd$[0] == "warp") + { + .@pos = -1; + .@map$ = ""; + .@pos_idx = 1; + if (getarraysize(.@cmd$) == 3) + { + .@map$ = .@cmd$[1]; + .@pos_idx = 2; + } + .@pos = findmovegraphlabel(.@cmd$[.@pos_idx]); + if (.@pos != -1) + { + .@x = getvariableofnpc(.movepos_x1[.@pos], strnpcinfo(3)); + .@y = getvariableofnpc(.movepos_y1[.@pos], strnpcinfo(3)); + if (getstrlen(.@map$) > 0) + unitwarp getnpcid(0), .@map$, .@x, .@y; + else + movenpc strnpcinfo(3), .@x, .@y; + set getvariableofnpc(.movepos, strnpcinfo(3)), .@pos; + } + else + { + debugmes "execmovecmd: unknown WARP destination label: " + .@cmd$[1]; + } + } + else if (.@cmd$[0] == "call") + { + switch (getarraysize(.@cmd$)) + { + case 1: + debugmes "execmovecmd: CALL command needs some parameters"; + return 0; + case 2: + return callfunc(.@cmd$[1]); + break; + case 3: + return callfunc(.@cmd$[1], .@cmd$[2]); + case 4: + default: + return callfunc(.@cmd$[1], .@cmd$[2], .@cmd$[3]); + } + } + else if (.@cmd$[0] == "speed") + { + .speed = atoi(.@cmd$[1]); + } + else if (.@cmd$[0] == "say") + { + deletearray .@cmd$[0], 1; + npctalk implode(.@cmd$, " "); + } + else if (.@cmd$[0] == "debugmes") + { + deletearray .@cmd$[0], 1; + debugmes implode(.@cmd$, " "); + } + else if (.@cmd$[0] == "flags") + { + set getvariableofnpc(.mg_flags, strnpcinfo(3)), axtoi(.@cmd$[1]); + } + else if (.@cmd$[0] == "flags_0") + { + .@flags = getvariableofnpc(.mg_flags, strnpcinfo(3)); + .@flags &= ~axtoi(.@cmd$[1]); + set getvariableofnpc(.mg_flags, strnpcinfo(3)), .@flags; + } + else if (.@cmd$[0] == "flags_1") + { + .@flags = getvariableofnpc(.mg_flags, strnpcinfo(3)); + .@flags |= axtoi(.@cmd$[1]); + set getvariableofnpc(.mg_flags, strnpcinfo(3)), .@flags; + } + else + { + debugmes "Unknown move graph cmd: " + .@cmd$[0]; + } + return 0; +} + +function script getnextmovecmd { + .@cmds$ = getvariableofnpc(.nextcmd$, strnpcinfo(3)); + .@firstCmd$ = .@cmds$; + .@restCmd$ = "moveon"; + .@index = strpos(.@cmds$, ";"); + if (.@index >= 0) + { + .@firstCmd$ = substr(.@cmds$, 0, .@index - 1); + .@restCmd$ = substr(.@cmds$, .@index + 1, getstrlen(.@cmds$) - 1); + } + // npcdebug "firstCmd = " + .@firstCmd$ + " restCmd = " + .@restCmd$; + set getvariableofnpc(.nextcmd$, strnpcinfo(3)), .@restCmd$; + return strip(.@firstCmd$); +} + +// getrandompoint(x1,y1,x2,y2) +// -- Get a random walkable point within a map rectangle +// x1, y1 -- top-left corner of rectangle +// x2, y2 -- bottom-right corner of rectangle +// Returns 0 on success and -1 on error; +// Since we cannot return multiple values, the random +// coordinates are stored in NPC variables .move__rand_x, .move__rand_y +function script getrandompoint { + if (getargcount() < 4) + { + debugmes "error: getrandompoint(x1, y1, x2, y2) takes 4 arguments"; + return -1; + } + + .@max_pokes = 10; + .@x1 = getarg(0); + .@y1 = getarg(1); + .@x2 = getarg(2); + .@y2 = getarg(3); + .@rx = -1; .@ry = -1; + + getmapxy(.@map$, .@cx, .@cy, 1); // npc location + + // let's try max_pokes random cells + for (.@poke = 0; .@poke < .@max_pokes; .@poke++) + { + .@rx = rand(.@x1, .@x2); + .@ry = rand(.@y1, .@y2); + if (checknpccell(.@map$, .@rx, .@ry, cell_chkpass)) + goto L_Found; + } + + // we check each cell from random middle point to the end + for (;.@rx <= .@x2; .@rx++) + { + for (;.@ry <= .@y2; .@ry++) + if (checknpccell(.@map$, .@rx, .@ry, cell_chkpass)) + goto L_Found; + .@ry = .@y1; + } + + // we check the rectangle from beginning to end + for (.@rx = .@x1; .@rx <= .@x2; .@rx++) + for (.@ry = .@y1; .@ry <= .@y2; .@ry++) + if (checknpccell(.@map$, .@rx, .@ry, cell_chkpass)) + goto L_Found; + + // finally, if we don't find anything + debugmes "error: getrandompoint: cannot find walkable cell in rectangle [(" + .@x1 + "," + .@y1 + ") , (" + .@x2 + "," + .@y2 + ")]"; + return -1; + +L_Found: + set getvariableofnpc(.move__rand_x, strnpcinfo(3)), .@rx; + set getvariableofnpc(.move__rand_y, strnpcinfo(3)), .@ry; + return 0; +} + +// wrapper function for npcwalkto. It can accept 4 parameters. +// If #3 and #4 params are set, the walkto location is chosen +// from rectangle (x1,y1,x2,y2). +// It sets the npc variables .move_target_x, .move_target_y +// that are used to resume NPC walking +// Returns 1 if walking is possible, 0 otherwise; +function script mg_npcwalkto { + if (getargcount() < 2) + { + debugmes "usage: mg_npcwalkto(x1,y1[,x2,y2])"; + return -1; + } + + .@x = getarg(0); + .@y = getarg(1); + .@x2 = getarg(2); + .@y2 = getarg(3); + + if (getargcount() >= 4 && .@x2 > 0 && .@y2 > 0) + if (!getrandompoint(.@x, .@y, .@x2, .@y2)) + { + .@x = getvariableofnpc(.move__rand_x, strnpcinfo(3)); + .@y = getvariableofnpc(.move__rand_y, strnpcinfo(3)); + } + else + return 0; + + if (npcwalkto(.@x, .@y)) + { + set getvariableofnpc(.move_target_x, strnpcinfo(3)), .@x; + set getvariableofnpc(.move_target_y, strnpcinfo(3)), .@y; + return 1; + } + return 0; +} + +function script movetonextpoint { + .@wait = getvariableofnpc(.waitticks, strnpcinfo(3)); + if (.@wait > 0) + { + .@wait--; + set getvariableofnpc(.waitticks, strnpcinfo(3)), .@wait; + return; + } + + .@nextcmd$ = ""; + while (.@nextcmd$ != "moveon") + { + .@nextcmd$ = getnextmovecmd(); + npcdebug " " + .@nextcmd$; + if (execmovecmd(.@nextcmd$)) + return; + } + + // choose a random path from all possible paths + .@size = getarraysize(getvariableofnpc(.movepos_x1, strnpcinfo(3))); + .@pos = getvariableofnpc(.movepos, strnpcinfo(3)); + .@curr_flags = getvariableofnpc(.mg_flags, strnpcinfo(3)); + .@cur = 0; + .@weight_sum = 0; + // .@dbg$ = getvariableofnpc(.movegraphlabels$[.@pos], strnpcinfo(3)) + ": "; + + for (.@i = 0; .@i < .@size; .@i++) + { + .@index = .@pos * .@size + .@i; + .@cmd$ = getvariableofnpc(.movegraphcmd$[.@index], strnpcinfo(3)); + .@flags = getvariableofnpc(.movegraphflags[.@index], strnpcinfo(3)); + if (.@cmd$ != "" && + .@curr_flags & .@flags) + { + .@nextpos[.@cur] = .@i; + .@weights[.@cur] = getvariableofnpc(.movegraphweight[.@index], strnpcinfo(3)); + // .@dbg$ += getvariableofnpc(.movegraphlabels$[.@i], strnpcinfo(3)) + "=" + .@weights[.@cur] + " "; + .@weight_sum += .@weights[.@cur]; + .@cur++; + } + } + // npcdebug .@dbg$; + + if (!.@weight_sum) + { + npcdebug("error: cannot pick next walk point. flags=" + + getvariableofnpc(.mg_flags, strnpcinfo(3))); + return; + } + + .@pick_tries = 0; +L_TryPick: + // pick a random number based on weight_sum + .@rnd = rand(.@weight_sum); + .@k = -1; .@weight_sum = 0; + while (.@rnd >= .@weight_sum) + { + .@k++; + .@weight_sum += .@weights[.@k]; + } + + .@next_idx = .@nextpos[.@k]; + .@next_x1 = getvariableofnpc(.movepos_x1[.@next_idx], strnpcinfo(3)); + .@next_y1 = getvariableofnpc(.movepos_y1[.@next_idx], strnpcinfo(3)); + .@next_x2 = getvariableofnpc(.movepos_x2[.@next_idx], strnpcinfo(3)); + .@next_y2 = getvariableofnpc(.movepos_y2[.@next_idx], strnpcinfo(3)); + + if (!mg_npcwalkto(.@next_x1, .@next_y1, .@next_x2, .@next_y2)) + { + if (.@pick_tries < 10) + { + .@pick_tries++; + goto L_TryPick; + } + + // move to a nearby position + .@x1 = getvariableofnpc(.movepos_x1[.@pos], strnpcinfo(3)); + .@y1 = getvariableofnpc(.movepos_y1[.@pos], strnpcinfo(3)); + .@x2 = getvariableofnpc(.movepos_x2[.@pos], strnpcinfo(3)); + .@y2 = getvariableofnpc(.movepos_y2[.@pos], strnpcinfo(3)); + mg_npcwalkto(.@x1, .@y1, .@x2, .@y2); + set getvariableofnpc(.nextcmd$, strnpcinfo(3)), "wait 1"; + + return; + } + + if (getvariableofnpc(.debug, strnpcinfo(3))) + { + getmapxy(.@map$, .@cx, .@cy, 1); + .@dist = distance(.@cx, .@cy, .@next_x1, .@next_y1); + npcdebug("moving to " + getvariableofnpc(.movegraphlabels$[.@next_idx], strnpcinfo(3)) + + " ("+ getvariableofnpc(.move_target_x, strnpcinfo(3)) + + "," + getvariableofnpc(.move_target_y, strnpcinfo(3)) + + ") [distance=" + .@dist + + "] flags=" + getvariableofnpc(.mg_flags, strnpcinfo(3))); + } + + .@nextcmd$ = getvariableofnpc(.movegraphcmd$[.@pos * .@size + .@next_idx], strnpcinfo(3)); + set getvariableofnpc(.nextcmd$, strnpcinfo(3)), .@nextcmd$; + set getvariableofnpc(.movepos, strnpcinfo(3)), .@next_idx; + return; +} + +// initial actions for npc when using move graphs. +// function can accept 2 arguments: +// 1: action sequence, for example "speed 200; dir 4". Default is "moveon" +// 2: start point label. Default is #0 from move graph labels +function script firstmove { + .@nextcmd$ = getarg(0, "moveon"); + .@initpos = findmovegraphlabel(getarg(1, "")); + if (.@initpos < 0) .@initpos = 0; + + set getvariableofnpc(.movepos, strnpcinfo(3)), .@initpos; + movenpc strnpcinfo(3), getvariableofnpc(.movepos_x1[.@initpos], strnpcinfo(3)), + getvariableofnpc(.movepos_y1[.@initpos], strnpcinfo(3)); + set getvariableofnpc(.nextcmd$, strnpcinfo(3)), .@nextcmd$; + set getvariableofnpc(.waitticks, strnpcinfo(3)), -1; + set getvariableofnpc(.mg_flags, strnpcinfo(3)), 0xffff; + movetonextpoint; + return; +} + +function script npc_pausemove { + stopnpctimer; + .@move_after = 0; + + if (isunitwalking()) + { + .@move_after = 1; + npcwalkto .x, .y; + npcstop; + } + set getvariableofnpc(.move_after_pause, strnpcinfo(3)), .@move_after; + + return 0; +} + +function script npc_resumemove { + startnpctimer; + + if (getvariableofnpc(.move_after_pause, strnpcinfo(3))) + { + .@x = getvariableofnpc(.move_target_x, strnpcinfo(3)); + .@y = getvariableofnpc(.move_target_y, strnpcinfo(3)); + npcwalkto .@x, .@y; + } + + return 0; +} + +// npc_turntoxy(x,y) +// turn npc toward an object at position (x,y) +function script npc_turntoxy { + .@target_x = getarg(0); + .@target_y = getarg(1); + .@dx = abs(.@target_x - .x); + .@dy = abs(.@target_y - .y); + + if (.@dx > .@dy) + .dir = .@target_x >= .x ? 6 : 2; + else + .dir = .@target_y >= .y ? 0 : 4; + + return 0; +} + +function script dographmovestep { + if (!isunitwalking()) + { + movetonextpoint; + } + initnpctimer; + end; +} diff --git a/npc/functions/openbook.txt b/npc/functions/openbook.txt new file mode 100644 index 000000000..0278415ce --- /dev/null +++ b/npc/functions/openbook.txt @@ -0,0 +1,36 @@ +// Evol functions. +// Author: +// Reid +// Description: +// Narrator dialogue to show the selected book. +// Variables: +// @book_name$ = The name of the book to read. + +function script openbook { + .@book_name$ = "\"" + l(getarg(0, getvariableofnpc(.book_name$, strnpcinfo(0)))) + "\""; + + narrator S_LAST_NEXT, + l("You open a book named @@.", .@book_name$), + l("Do you want to read it?"); + + return (select("Yes.", "No.") == 1); +} + +function script openbookshelf { + .@book_name$ = "\"" + l(getarg(0, getvariableofnpc(.book_name$, strnpcinfo(0)))) + "\""; + + narrator S_LAST_NEXT, + l("You see a dust covered book on the shelf..."), + l("The name of the book is @@.", .@book_name$), + l("Do you want to read it?"); + + return (select("Yes.", "No.") == 1); +} + +function script openoldbook { + narrator S_LAST_NEXT, + l("You open the book, but it looks like the sea water and time damaged it severely. Some pages are not readable anymore. Some others are simply missing."), + l("The old book seems to tell about the legend of Aemil. Would you like to read it?"); + + return (select("Yes.", "No.") == 1); +} diff --git a/npc/functions/permissions.txt b/npc/functions/permissions.txt new file mode 100644 index 000000000..62e0da6b7 --- /dev/null +++ b/npc/functions/permissions.txt @@ -0,0 +1,35 @@ +// Evol scripts. +// Author: +// gumi +// Description: +// checks player permissions +// ** admins are implicitly everything + +// administrator +function script is_admin { + return has_permission(PERM_USE_ALL_COMMANDS, getarg(0, getcharid(CHAR_ID_ACCOUNT))); +} + +// any staff member +function script is_trusted { + return is_admin(getarg(0, getcharid(CHAR_ID_ACCOUNT))) || + has_permission("show_client_version", getarg(0, getcharid(CHAR_ID_ACCOUNT))); +} + +// developer +function script is_dev { + return is_admin(getarg(0, getcharid(CHAR_ID_ACCOUNT))) || + has_permission(PERM_RECEIVE_REQUESTS, getarg(0, getcharid(CHAR_ID_ACCOUNT))); +} + +// event coordinator +function script is_evtc { + return is_admin(getarg(0, getcharid(CHAR_ID_ACCOUNT))) || + can_use_command("@monster", getarg(0, getcharid(CHAR_ID_ACCOUNT))); +} + +// game master +function script is_gm { + return is_admin(getarg(0, getcharid(CHAR_ID_ACCOUNT))) || + has_permission("send_gm", getarg(0, getcharid(CHAR_ID_ACCOUNT))); +} diff --git a/npc/functions/quest-debug/000-ShipQuests_Julia.txt b/npc/functions/quest-debug/000-ShipQuests_Julia.txt new file mode 100644 index 000000000..e4e0ec2cd --- /dev/null +++ b/npc/functions/quest-debug/000-ShipQuests_Julia.txt @@ -0,0 +1,37 @@ +// Julia quest debug +// Author: +// gumi + +function script QuestDebug0 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Julia"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Julia)); + mes "---"; + mes l("Related quests:"); + mes "ShipQuests_Nard: " + getq(ShipQuests_Nard); + mes "ShipQuests_ChefGado: " + getq(ShipQuests_ChefGado); + mes "General_Narrator: " + getq(General_Narrator); + next; + + GenericQuestDebug ShipQuests_Julia, + menuimage("actions/manage", l("Debug Nard quest")), -1, + menuimage("actions/manage", l("Debug Gado quest")), -2, + menuimage("actions/manage", l("Debug Narrator")), -3, + l("Does not have the quest"), 0, + l("Got the quest"), 1, + l("Completed"), 2; + + switch (@menuret) + { + case -1: callfunc "QuestDebug4"; break; + case -2: callfunc "QuestDebug17"; break; + case -3: callfunc "QuestDebug28"; break; + default: if (@menuret < 0) return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/001-ShipQuests_Arpan.txt b/npc/functions/quest-debug/001-ShipQuests_Arpan.txt new file mode 100644 index 000000000..26c496466 --- /dev/null +++ b/npc/functions/quest-debug/001-ShipQuests_Arpan.txt @@ -0,0 +1,27 @@ +// Arpan quest debug +// Author: +// gumi + +function script QuestDebug1 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Arpan"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Arpan)); + next; + + GenericQuestDebug ShipQuests_Arpan, + l("Arpan is waiting for you"), 0, + l("Arpan told you to open the chest"), 1, + l("You opened the chest"), 2, + l("Completed"), 3; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/002-ShipQuests_Alige.txt b/npc/functions/quest-debug/002-ShipQuests_Alige.txt new file mode 100644 index 000000000..36d0ce23e --- /dev/null +++ b/npc/functions/quest-debug/002-ShipQuests_Alige.txt @@ -0,0 +1,27 @@ +// Alige quest debug +// Author: +// gumi + +function script QuestDebug2 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Alige"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Alige)); + next; + + GenericQuestDebug ShipQuests_Alige, + l("Does not have the quest"), 0, + l("First encounter"), 1, + l("Alige asks for food"), 2, + l("Completed"), 3; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/003-ShipQuests_Peter.txt b/npc/functions/quest-debug/003-ShipQuests_Peter.txt new file mode 100644 index 000000000..e08e1eb24 --- /dev/null +++ b/npc/functions/quest-debug/003-ShipQuests_Peter.txt @@ -0,0 +1,30 @@ +// Peter quest debug +// Author: +// gumi + +function script QuestDebug3 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Peter"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Peter)); + next; + + GenericQuestDebug ShipQuests_Peter, + l("Does not have the quest"), 0, + l("Peter needs help"), 6, + l("Peter asks to kill rattos"), 1, + l("Killed rattos"), 2, + l("Got no reward"), 3, + l("Peter asks to kill rattos again"), 4, + l("Peter gave reward"), 5; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/004-ShipQuests_Nard.txt b/npc/functions/quest-debug/004-ShipQuests_Nard.txt new file mode 100644 index 000000000..9ec51cd87 --- /dev/null +++ b/npc/functions/quest-debug/004-ShipQuests_Nard.txt @@ -0,0 +1,38 @@ +// Nard quest debug +// Author: +// gumi + +function script QuestDebug4 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Nard"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Nard)); + mes "---"; + mes l("Subquests:"); + mes "ShipQuests_Gugli: " + getq(ShipQuests_Gugli); + mes "ShipQuests_ChefGado: " + getq(ShipQuests_ChefGado); + next; + + GenericQuestDebug ShipQuests_Nard, + l("Does not have the quest"), 0, + l("Nard asks to help crew"), 1, + menuimage("actions/manage", l("Debug Gugli quest")), -1, + l("Completed Gugli's task"), 2, + l("Nard asks to solve conflict"), 3, + menuimage("actions/manage", l("Debug Gado quest")), -2, + l("Solved conflict"), 4, + l("Official crew member"), 5, + l("Talked to narrator"), 6; + + switch (@menuret) + { + case -1: callfunc "QuestDebug16"; break; + case -2: callfunc "QuestDebug17"; break; + default: if (@menuret < 0) return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/005-ShipQuests_Knife.txt b/npc/functions/quest-debug/005-ShipQuests_Knife.txt new file mode 100644 index 000000000..a5ec1ae86 --- /dev/null +++ b/npc/functions/quest-debug/005-ShipQuests_Knife.txt @@ -0,0 +1,25 @@ +// Knife quest debug +// Author: +// gumi + +function script QuestDebug5 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Knife"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Knife)); + next; + + GenericQuestDebug ShipQuests_Knife, + l("Does not have the quest"), 0, + l("Got the knife"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/006-ShipQuests_ArpanMoney.txt b/npc/functions/quest-debug/006-ShipQuests_ArpanMoney.txt new file mode 100644 index 000000000..00e2fbea8 --- /dev/null +++ b/npc/functions/quest-debug/006-ShipQuests_ArpanMoney.txt @@ -0,0 +1,26 @@ +// Money quest debug +// Author: +// gumi + +function script QuestDebug6 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_ArpanMoney"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_ArpanMoney)); + next; + + GenericQuestDebug ShipQuests_ArpanMoney, + l("Does not have the quest"), 0, + l("Elmo told about money"), 1, + l("Arpan gave money"), 2; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/007-ShipQuests_Door.txt b/npc/functions/quest-debug/007-ShipQuests_Door.txt new file mode 100644 index 000000000..88aa00abe --- /dev/null +++ b/npc/functions/quest-debug/007-ShipQuests_Door.txt @@ -0,0 +1,25 @@ +// Door quest debug +// Author: +// gumi + +function script QuestDebug7 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Door"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Door)); + next; + + GenericQuestDebug ShipQuests_Door, + l("Does not have the quest"), 0, + l("Heard conversation"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/008-ShipQuests_Couwan.txt b/npc/functions/quest-debug/008-ShipQuests_Couwan.txt new file mode 100644 index 000000000..3df0cdbf0 --- /dev/null +++ b/npc/functions/quest-debug/008-ShipQuests_Couwan.txt @@ -0,0 +1,26 @@ +// Couwan quest debug +// Author: +// gumi + +function script QuestDebug8 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Couwan"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Couwan)); + next; + + GenericQuestDebug ShipQuests_Couwan, + l("Does not have the quest"), 0, + l("Couwan asks to deliver box"), 1, + l("Delivered box, got reward"), 2; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/009-ShipQuests_TreasureChest.txt b/npc/functions/quest-debug/009-ShipQuests_TreasureChest.txt new file mode 100644 index 000000000..97adef46f --- /dev/null +++ b/npc/functions/quest-debug/009-ShipQuests_TreasureChest.txt @@ -0,0 +1,25 @@ +// Treasure chest quest debug +// Author: +// gumi + +function script QuestDebug9 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_TreasureChest"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_TreasureChest)); + next; + + GenericQuestDebug ShipQuests_TreasureChest, + l("Does not have the quest"), 0, + l("Opened treasure chest"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/010-ShipQuests_Ale.txt b/npc/functions/quest-debug/010-ShipQuests_Ale.txt new file mode 100644 index 000000000..e54221224 --- /dev/null +++ b/npc/functions/quest-debug/010-ShipQuests_Ale.txt @@ -0,0 +1,25 @@ +// Part of Gugli quest debug +// Author: +// gumi + +function script QuestDebug10 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Ale"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Ale)); + next; + + GenericQuestDebug ShipQuests_Ale, + l("Does not have the quest"), 0, + l("Got the package"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/011-ShipQuests_Astapolos.txt b/npc/functions/quest-debug/011-ShipQuests_Astapolos.txt new file mode 100644 index 000000000..aca065edb --- /dev/null +++ b/npc/functions/quest-debug/011-ShipQuests_Astapolos.txt @@ -0,0 +1,25 @@ +// Part of Gugli quest debug +// Author: +// gumi + +function script QuestDebug11 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Astapolos"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Astapolos)); + next; + + GenericQuestDebug ShipQuests_Astapolos, + l("Does not have the quest"), 0, + l("Got the package"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/012-ShipQuests_Gulukan.txt b/npc/functions/quest-debug/012-ShipQuests_Gulukan.txt new file mode 100644 index 000000000..fac7ccded --- /dev/null +++ b/npc/functions/quest-debug/012-ShipQuests_Gulukan.txt @@ -0,0 +1,25 @@ +// Part of Gugli quest debug +// Author: +// gumi + +function script QuestDebug12 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Gulukan"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Gulukan)); + next; + + GenericQuestDebug ShipQuests_Gulukan, + l("Does not have the quest"), 0, + l("Got the package"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/013-ShipQuests_Jalad.txt b/npc/functions/quest-debug/013-ShipQuests_Jalad.txt new file mode 100644 index 000000000..9ae6ed2a2 --- /dev/null +++ b/npc/functions/quest-debug/013-ShipQuests_Jalad.txt @@ -0,0 +1,25 @@ +// Part of Gugli quest debug +// Author: +// gumi + +function script QuestDebug13 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Jalad"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Jalad)); + next; + + GenericQuestDebug ShipQuests_Jalad, + l("Does not have the quest"), 0, + l("Got the package"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/014-ShipQuests_QMuller.txt b/npc/functions/quest-debug/014-ShipQuests_QMuller.txt new file mode 100644 index 000000000..8a25ee653 --- /dev/null +++ b/npc/functions/quest-debug/014-ShipQuests_QMuller.txt @@ -0,0 +1,25 @@ +// Part of Gugli quest debug +// Author: +// gumi + +function script QuestDebug14 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_QMuller"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_QMuller)); + next; + + GenericQuestDebug ShipQuests_QMuller, + l("Does not have the quest"), 0, + l("Got the package"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/015-ShipQuests_Tibbo.txt b/npc/functions/quest-debug/015-ShipQuests_Tibbo.txt new file mode 100644 index 000000000..84280ebfe --- /dev/null +++ b/npc/functions/quest-debug/015-ShipQuests_Tibbo.txt @@ -0,0 +1,25 @@ +// Part of Gugli quest debug +// Author: +// gumi + +function script QuestDebug15 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Tibbo"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Tibbo)); + next; + + GenericQuestDebug ShipQuests_Tibbo, + l("Does not have the quest"), 0, + l("Got the package"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/016-ShipQuests_Gugli.txt b/npc/functions/quest-debug/016-ShipQuests_Gugli.txt new file mode 100644 index 000000000..e4868ff48 --- /dev/null +++ b/npc/functions/quest-debug/016-ShipQuests_Gugli.txt @@ -0,0 +1,48 @@ +// Part of Gugli quest debug +// Author: +// gumi + +function script QuestDebug16 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_Gugli"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_Gugli)); + mes "---"; + mes l("Subquests:"); + mes "ShipQuests_Ale: " + getq(ShipQuests_Ale); + mes "ShipQuests_Astapolos: " + getq(ShipQuests_Astapolos); + mes "ShipQuests_Gulukan: " + getq(ShipQuests_Gulukan); + mes "ShipQuests_Jalad: " + getq(ShipQuests_Jalad); + mes "ShipQuests_QMuller: " + getq(ShipQuests_QMuller); + mes "ShipQuests_Tibbo: " + getq(ShipQuests_Tibbo); + next; + + GenericQuestDebug ShipQuests_Gugli, + l("Does not have the quest"), 0, + l("Gugli asks to collect packages"), 1, + menuimage("actions/manage", l("Reset subquests")), -1, + menuimage("actions/manage", l("Set subquests as completed")), -2, + l("Got reward from gugli"), 2; + + switch (@menuret) + { + case 0: + case 2: + case -1: + case -2: + .@v = (@menuret == -2 || @menuret == 2); + setq ShipQuests_Ale, .@v; + setq ShipQuests_Astapolos, .@v; + setq ShipQuests_Gulukan, .@v; + setq ShipQuests_Jalad, .@v; + setq ShipQuests_QMuller, .@v; + setq ShipQuests_Tibbo, .@v; + break; + default: if (@menuret < 0) return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/017-ShipQuests_ChefGado.txt b/npc/functions/quest-debug/017-ShipQuests_ChefGado.txt new file mode 100644 index 000000000..05e8cdb09 --- /dev/null +++ b/npc/functions/quest-debug/017-ShipQuests_ChefGado.txt @@ -0,0 +1,30 @@ +// Gado quest debug +// Author: +// gumi + +function script QuestDebug17 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ShipQuests_ChefGado"; + mes "---"; + mes l("Quest state: @@", getq(ShipQuests_ChefGado)); + next; + + GenericQuestDebug ShipQuests_ChefGado, + l("Does not have the quest"), 0, + l("Nard asks to solve conflict"), 1, + l("Got poison from Gado"), 2, + l("Poisoned Julia"), 3, + l("Completed, Gado wins"), 4, + l("Completed, Julia wins (returned poison)"), 5, + l("Completed, Julia wins"), 6; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/018-General_Cookies.txt b/npc/functions/quest-debug/018-General_Cookies.txt new file mode 100644 index 000000000..16c7bcd75 --- /dev/null +++ b/npc/functions/quest-debug/018-General_Cookies.txt @@ -0,0 +1,25 @@ +// Cookie quest debug +// Author: +// gumi + +function script QuestDebug18 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "General_Cookies"; + mes "---"; + mes l("Quest state: @@", getq(General_Cookies)); + next; + + GenericQuestDebug General_Cookies, + l("Does not have the quest"), 0, + l("Got a cookie"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/019-ArtisQuests_LazyBrother.txt b/npc/functions/quest-debug/019-ArtisQuests_LazyBrother.txt new file mode 100644 index 000000000..41733adf8 --- /dev/null +++ b/npc/functions/quest-debug/019-ArtisQuests_LazyBrother.txt @@ -0,0 +1,28 @@ +// Lazy brother quest debug +// Author: +// gumi + +function script QuestDebug19 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ArtisQuests_LazyBrother"; + mes "---"; + mes l("Quest state: @@", getq(ArtisQuests_LazyBrother)); + next; + + GenericQuestDebug ArtisQuests_LazyBrother, + l("Does not have the quest"), 0, + l("Katja asked for help"), 1, + l("Found bobo, didn't tell Katja"), 2, + l("Told bobo to go home"), 3, + l("Katja gave reward"), 4; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/020-ArtisQuests_Urchin.txt b/npc/functions/quest-debug/020-ArtisQuests_Urchin.txt new file mode 100644 index 000000000..3a092e478 --- /dev/null +++ b/npc/functions/quest-debug/020-ArtisQuests_Urchin.txt @@ -0,0 +1,26 @@ +// Urchin quest debug +// Author: +// gumi + +function script QuestDebug20 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ArtisQuests_Urchin"; + mes "---"; + mes l("Quest state: @@", getq(ArtisQuests_Urchin)); + next; + + GenericQuestDebug ArtisQuests_Urchin, + l("Does not have the quest"), 0, + l("Moon needs @@", l("Croc Claw")), 1, + l("Found @@, got exp", l("Croc Claw")), 2; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/021-ArtisQuests_CatchPiou.txt b/npc/functions/quest-debug/021-ArtisQuests_CatchPiou.txt new file mode 100644 index 000000000..f9c45339e --- /dev/null +++ b/npc/functions/quest-debug/021-ArtisQuests_CatchPiou.txt @@ -0,0 +1,26 @@ +// Piou quest debug +// Author: +// gumi + +function script QuestDebug21 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ArtisQuests_CatchPiou"; + mes "---"; + mes l("Quest state: @@", getq(ArtisQuests_CatchPiou)); + next; + + GenericQuestDebug ArtisQuests_CatchPiou, + l("Does not have the quest"), 0, + l("Salem asks to catch piou"), 1, + l("Returned piou to Salem"), 2; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/022-ArtisQuests_Fishman.txt b/npc/functions/quest-debug/022-ArtisQuests_Fishman.txt new file mode 100644 index 000000000..0a193e6fe --- /dev/null +++ b/npc/functions/quest-debug/022-ArtisQuests_Fishman.txt @@ -0,0 +1,26 @@ +// Eugene quest debug +// Author: +// gumi + +function script QuestDebug22 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ArtisQuests_Fishman"; + mes "---"; + mes l("Quest state: @@", getq(ArtisQuests_Fishman)); + next; + + GenericQuestDebug ArtisQuests_Fishman, + l("Does not have the quest"), 0, + l("Eugene needs tentacles"), 1, + l("Gave tentacles, got reward"), 2; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/023-ArtisQuests_QOnan.txt b/npc/functions/quest-debug/023-ArtisQuests_QOnan.txt new file mode 100644 index 000000000..02eaa8f60 --- /dev/null +++ b/npc/functions/quest-debug/023-ArtisQuests_QOnan.txt @@ -0,0 +1,27 @@ +// Q'Onan quest debug +// Author: +// gumi + +function script QuestDebug23 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ArtisQuests_QOnan"; + mes "---"; + mes l("Quest state: @@", getq(ArtisQuests_QOnan)); + next; + + GenericQuestDebug ArtisQuests_QOnan, + l("Does not have the quest"), 0, + l("Q'Onan asks to find chest"), 1, + l("Found the chest"), 2, + l("Gave to Q'Onan, got reward"), 3; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/026-General_Rumly.txt b/npc/functions/quest-debug/026-General_Rumly.txt new file mode 100644 index 000000000..c533c27a0 --- /dev/null +++ b/npc/functions/quest-debug/026-General_Rumly.txt @@ -0,0 +1,27 @@ +// Rumly quest debug +// Author: +// gumi + +function script QuestDebug26 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "General_Rumly"; + mes "---"; + mes l("Quest state: @@", getq(General_Rumly)); + next; + + GenericQuestDebug General_Rumly, + l("Does not have the quest"), 0, + l("Rumly needs your help"), 1, + l("Rumly wants @@", l("Plushroom")), 2, + l("Gave @@ to Rumly", l("Plushroom")), 3; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/027-ArtisQuests_Enora.txt b/npc/functions/quest-debug/027-ArtisQuests_Enora.txt new file mode 100644 index 000000000..9121ceb30 --- /dev/null +++ b/npc/functions/quest-debug/027-ArtisQuests_Enora.txt @@ -0,0 +1,49 @@ +// Newbie quest debug +// Author: +// gumi + +function script QuestDebug27 { + do + { + clear(); + setnpcdialogtitle(l("Quest debug")); + mes("ArtisQuests_Enora"); + mes("---"); + mes(l("Quest state: @@, @@", + getq(ArtisQuests_Enora), + getq2(ArtisQuests_Enora))); + next(); + + GenericQuestDebug(ArtisQuests_Enora, + l("Does not have the quest"), 0, + l("Enora asks to visit Chelios"), 1, + l("Chelios asks to visit Lloyd"), 2, + l("Lloyd gave package"), 3, + l("Chelios made sword"), 4, + l("Enora asks to visit Resa"), 5, + l("Resa gave package"), 6, + l("Enora asks to visit Q'Pid"), 7, + l("Lost the riddle"), 8, + l("Ivan gave package"), 9, + l("Enora asks to kill fluffies"), 10, + l("Completed, got reward"), 11); + + switch (@menuret) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: setq(ArtisQuests_Enora, getq(ArtisQuests_Enora), 0); break; + case 11: setq(ArtisQuests_Enora, getq(ArtisQuests_Enora), 10); break; + default: if (@menuret < 0) return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/028-General_Narrator.txt b/npc/functions/quest-debug/028-General_Narrator.txt new file mode 100644 index 000000000..408668b7a --- /dev/null +++ b/npc/functions/quest-debug/028-General_Narrator.txt @@ -0,0 +1,25 @@ +// Narrator debug +// Author: +// gumi + +function script QuestDebug28 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "General_Narrator"; + mes "---"; + mes l("Quest state: @@", getq(General_Narrator)); + next; + + GenericQuestDebug General_Narrator, + l("Game introduction"), 0, + l("Visited Artis at least once"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/029-ArtisQuests_Fexil.txt b/npc/functions/quest-debug/029-ArtisQuests_Fexil.txt new file mode 100644 index 000000000..9c0d7945d --- /dev/null +++ b/npc/functions/quest-debug/029-ArtisQuests_Fexil.txt @@ -0,0 +1,27 @@ +// Fexil quest debug +// Author: +// gumi + +function script QuestDebug29 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ArtisQuests_Fexil"; + mes "---"; + mes l("Quest state: @@", getq(ArtisQuests_Fexil)); + next; + + GenericQuestDebug ArtisQuests_Fexil, + l("Does not have the quest"), 0, + l("Lloyd gave pass"), 1, + l("Fexil needs help"), 2, + l("Fexil wants to buy fur"), 3; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/030-ArtisQuests_Lloyd.txt b/npc/functions/quest-debug/030-ArtisQuests_Lloyd.txt new file mode 100644 index 000000000..0afb019c8 --- /dev/null +++ b/npc/functions/quest-debug/030-ArtisQuests_Lloyd.txt @@ -0,0 +1,25 @@ +// Lloyd quest debug +// Author: +// gumi + +function script QuestDebug30 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ArtisQuests_Lloyd"; + mes "---"; + mes l("Quest state: @@", getq(ArtisQuests_Lloyd)); + next; + + GenericQuestDebug ArtisQuests_Lloyd, + l("Does not have the quest"), 0, + l("Registered"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/031-General_Janus.txt b/npc/functions/quest-debug/031-General_Janus.txt new file mode 100644 index 000000000..f97b4fbeb --- /dev/null +++ b/npc/functions/quest-debug/031-General_Janus.txt @@ -0,0 +1,31 @@ +// Janus quest debug +// Author: +// gumi + +function script QuestDebug31 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "General_Janus"; + mes "---"; + mes l("Quest state: @@", getq(General_Janus)); + next; + + GenericQuestDebug General_Janus, + l("Does not have the quest"), 0, + l("Talked to Janus"), 1, + l("Can create party"), 2, + l("Can create guild"), 3; + + switch (@menuret) + { + case 0: + case 1: skill NV_BASIC, min(6, getskilllv(NV_BASIC)), 0; break; + case 2: + case 3: skill NV_BASIC, max(7, getskilllv(NV_BASIC)), 0; break; + default: if (@menuret < 0) return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/032-ArtisQuests_MonaDad.txt b/npc/functions/quest-debug/032-ArtisQuests_MonaDad.txt new file mode 100644 index 000000000..68ba67fe9 --- /dev/null +++ b/npc/functions/quest-debug/032-ArtisQuests_MonaDad.txt @@ -0,0 +1,25 @@ +// Mona quest debug +// Author: +// gumi + +function script QuestDebug32 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "ArtisQuests_MonaDad"; + mes "---"; + mes l("Quest state: @@", getq(ArtisQuests_MonaDad)); + next; + + GenericQuestDebug ArtisQuests_MonaDad, + l("Does not have the quest"), 0, + l("Mona's dad is missing"), 1; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/033-Artis_Legion_Progress.txt b/npc/functions/quest-debug/033-Artis_Legion_Progress.txt new file mode 100644 index 000000000..c4ea5558a --- /dev/null +++ b/npc/functions/quest-debug/033-Artis_Legion_Progress.txt @@ -0,0 +1,30 @@ +// Mona quest debug +// Authors: +// gumi +// monwarez + +function script QuestDebug33 { + do + { + clear; + setnpcdialogtitle l("Quest debug"); + mes "Artis_Legion_Progress"; + mes "---"; + mes l("Quest state: @@", getq(Artis_Legion_Progress)); + next; + + GenericQuestDebug Artis_Legion_Progress, + l("Does not have the quest"), 0, + l("Sent to training"), 1, + l("Finished training"), 2, + l("Sent to battle"), 3, + l("Finished battle"), 4, + l("Sent to Q'Anon"), 5; + + if (@menuret < 0) + { + return; + } + + } while (1); +} diff --git a/npc/functions/quest-debug/functions.txt b/npc/functions/quest-debug/functions.txt new file mode 100644 index 000000000..f89adfab7 --- /dev/null +++ b/npc/functions/quest-debug/functions.txt @@ -0,0 +1,109 @@ +// Evol functions. +// Author: +// gumi +// Description: +// generic quest debug functions + + + +// GenericQuestDebug +// makes a generic quest debug menu for the given quest when the server +// is in debug mode. + +function script GenericQuestDebug { + if (!debug && !is_admin()) + { + select + menuimage("actions/back", l("Go back")); + + @menuret = -0x7FFFFFFF; + return 1; + } + + mes l("Choose desired quest state:"); + + deletearray .@vals; + .@menustr$ = menuimage("actions/abort", l("Do nothing")) + ":"; + .@vals[0] = -0x7FFFFFFF; + .@cnt = 1; + + for (.@f = 1; .@f < getargcount(); .@f += 2) + { + if (getarg(.@f) != "") + { + .@qv = getarg(.@f + 1); + .@s$ = menuimage("actions/" + (.@qv ? "edit" : "reset"), "[" + .@qv + "] " + getarg(.@f)); + .@menustr$ += (.@qv < 0 ? getarg(.@f) : .@s$) + ":"; + .@vals[.@cnt] = .@qv; + ++.@cnt; + } + } + + if (is_admin()) + { + .@menustr$ += menuimage("actions/nuke", l("Set state manually")); + .@vals[.@cnt] = -0x7FFFFFFE; + } + + + @menu = 255; + @menuret = -1; + select(.@menustr$); + if (@menu == 255) + return -1; + + --@menu; + if (@menu < 0 || @menu >= getarraysize(.@vals)) + return -1; + + @menuret = .@vals[@menu]; + + switch (@menuret) + { + case -0x7FFFFFFE: input @menuret; setq getarg(0,0), @menuret; + case -0x7FFFFFFF: return 1; + } + + if (@menuret >= 0) + { + setq getarg(0,0), @menuret; + } + return; +} + + + +// selectd +// like a normal select() but gives access to quest debug +// +// quest id can either be passed as first argument +// or as the .quest_debug npc variable + +function script selectd { + .@menustr$ = rif(debug, menuaction(l("debug"))); + .@count = getargcount(); + .@f = 0; + .@questID = getvariableofnpc(.quest_debug, strnpcinfo(0)); + + if (.@count > 1 && !isstr(getarg(0))) + { + ++.@f; + .@questID = getarg(0); + } + + for (; .@f < .@count; ++.@f) + { + .@menustr$ += ":" + getarg(.@f); + } + + @menu = 255; + select .@menustr$; + + switch (@menu) + { + case -1: + case 255: return -1; + default: @menu -= 1; return @menu; // FIXME: here I would have done `return --@menu;` but hercules prevents this + case 1: callfunc "QuestDebug" + .@questID; closedialog; end; + } +} diff --git a/npc/functions/questgen.txt b/npc/functions/questgen.txt new file mode 100644 index 000000000..285924cbd --- /dev/null +++ b/npc/functions/questgen.txt @@ -0,0 +1,38 @@ +// Evol functions. +// Authors: +// monwarez +// Reid +// Description: +// Generate a random quest type and location. +// Variables: +// @quests : 2D array containing quest type and location availability +// with @nb_type rows and @nb_location columns. +// boolean value determine if the connection is possible between +// the quest type and location selected. +// @nb_difficulty : difficulty value from 0 to N-1. +// Argument: +// 0 : quest type +// 1 : quest location +// 2 : quest difficulty +// Return : Tridimentional array value; + +function script questgen { + + .@argc = getargcount(); + @q_type = getarg(0, rand(@nb_type * 10) / 10); + + do + { + @q_location = getarg(1, rand(@nb_location * 10) / 10); + .@cell = @q_type * @nb_location + @q_location; + + if (!@quests[.@cell] && .@argc >= 2) + { + return false; + } + } while (!@quests[.@cell]); + + @q_difficulty = getarg(2, rand(@nb_difficulty * 10) / 10); + + return true; +} diff --git a/npc/functions/riddle.txt b/npc/functions/riddle.txt new file mode 100644 index 000000000..fb503e3b3 --- /dev/null +++ b/npc/functions/riddle.txt @@ -0,0 +1,74 @@ +// Evol functions. +// Author: +// Reid +// Description: +// Riddle enigma validator +// +// Arguments +// 0 PC answer +// 1 English correct answer +// 2 Translated correct answer + +// TODO: levenshtein(), similar_text(), and maybe even soundex() + +function script riddlevalidation { + .@answer$ = strtolower(getarg(0)); + .@good$ = strtolower(getarg(1)); + .@good_translated$ = strtolower(getarg(2)); + + .@size_answer = getstrlen(.@answer$); + .@size_good = getstrlen(.@good$); + .@size_good_translated = getstrlen(.@good_translated$); + + .@max = max(.@size_answer, .@size_good_translated, .@size_good); + + // Input is too long. + if (.@max > 20) + { + return false; + } + + .@size_good *= 70; + .@size_good_translated *= 70; + + for (.@i = 0; .@i < .@max; .@i++) + { + .@correct = 0; + .@correct_translated = 0; + + for (.@k = .@k_translated = .@j = .@i; .@j < .@max; .@j++) + { + if (charat(.@answer$, .@j) == charat(.@good$, .@k)) + { + .@correct++; + .@k++; + } + else + { + .@correct--; + } + + if (charat(.@answer$, .@j) == + charat(.@good_translated$, .@k_translated)) + { + .@correct_translated++; + .@k_translated++; + } + else + { + .@correct_translated--; + } + } + // if 70% of the word is correct + .@correct *= 100; + .@correct_translated *= 100; + + if (.@correct >= .@size_good || + .@correct_translated >= .@size_good_translated) + { + return true; + } + } + + return false; +} diff --git a/npc/functions/sailordialogue.txt b/npc/functions/sailordialogue.txt new file mode 100644 index 000000000..281246f7f --- /dev/null +++ b/npc/functions/sailordialogue.txt @@ -0,0 +1,53 @@ +// Evol functions. +// Authors: +// Qwerty Dragon +// Reid +// Description: +// Random sailor dialogues between two categories of NPCs. + +function script sailorfood { + mesn; + + .@q = rand(0, 400) / 100; + if (.@q == 0) goto L_RandomA; + if (.@q == 1) goto L_RandomB; + if (.@q > 1) goto L_RandomC; + +L_RandomA: + mesq l("Hey."); + next; + mesq l("What did Gugli say about the box? Was it ok?"); + next; + + menu + l("It's ok."), L_Fine, + l("He needs more food."), -; + + mes ""; + mesn; + mesq l("Oh really? I'll put more food in the next box then."); + + close; + +L_Fine: + mes ""; + mesn; + mesq l("It's alright! Just one more box and it'll be ok."); + + close; + +L_RandomB: + mesq l("Thanks for the help!"); + next; + mesq l("These boxes are way too heavy to be lifted by only one person, all the way onto the ship."); + + close; + +L_RandomC: + mesq l("I think I'll be done soon, since I almost have a box full of @@s!", getitemlink(CrocClaw)); + next; + mesq l("And you? How's it going on your side?"); + next; + + return; +} diff --git a/npc/functions/sailortalk.txt b/npc/functions/sailortalk.txt new file mode 100644 index 000000000..73145768b --- /dev/null +++ b/npc/functions/sailortalk.txt @@ -0,0 +1,37 @@ +// Evol functions. +// Author: +// Reid +// Description: +// Tell a random sentence. +// Variables: +// .@rand = Random number between the number of sentence choice. + +function script sailortalk { + + .@rand = rand(8); + if (.@rand == 0) goodbye; + if (.@rand == 1) + { + speech( + l("These purple mushrooms are called @@s. There are plenty of 'em on this island!", getitemlink(Plushroom)), + l("It's a kind of mushroom that tastes like a marshmallow and looks like a plush! @@, get it?", getitemlink(Plushroom)), + l("These funny fungi are mushrooming all around this island. Just pick some @@s and have a try.", getitemlink(Plushroom))); + close; + } + if (.@rand == 2) npctalkonce(l("Good to hear from you!")); + if (.@rand == 3) npctalkonce(l("So finally someone has came to visit me?")); + if (.@rand == 4) + { + speech( + l("A sunny and hot day,"), + l("a quiet place,"), + l("a ground!"), + l("What else do you need?")); + close; + } + if (.@rand == 5) npctalkonce(l("A-hoy matey!")); + if (.@rand == 6) npctalkonce(l("We are glad captain Nard has let you join the crew!")); + if (.@rand == 7) npctalkonce(l("Howdy?")); + + end; +} diff --git a/npc/functions/savepoint.txt b/npc/functions/savepoint.txt new file mode 100644 index 000000000..0e0b6f908 --- /dev/null +++ b/npc/functions/savepoint.txt @@ -0,0 +1,48 @@ +// Evol functions. +// Authors: +// gumi +// Reid +// Description: +// Adds a new save point location. +// Usage: +// savepointparticle; +// savepointparticle NO_INN; +// savepointparticle map, x, y, NO_INN; +// Description: +// Save location with arguments: +// getarg(0) map name, +// getarg(1) x's value, +// getarg(2) y's value, +// getarg(3) INN flag. + +function script savepointparticle { + + if (gettimetick(2) - @lastSave < 5) + return; + + .@mapname$ = getarg(0, ""); + .@mapx = getarg(1, -1); + .@mapy = getarg(2, -1); + .@i = 3; + + if (.@mapy < 1) + { + .@npc$ = strnpcinfo(0); + .@mapname$ = getvariableofnpc(.map$, .@npc$); + .@mapx = getvariableofnpc(.x, .@npc$); + .@mapy = getvariableofnpc(.y, .@npc$); + .@i = 0; + } + + message strcharinfo(0), l("Your position has been saved."); + + if (getarg(.@i, NO_INN) == NO_INN) + { + INN_REGISTER = NO_INN; + } + savepoint .@mapname$, .@mapx, .@mapy; + specialeffect(4, SELF, getcharid(3)); + @lastSave = gettimetick(2); + + return; +} diff --git a/npc/functions/shops.txt b/npc/functions/shops.txt new file mode 100644 index 000000000..79890e815 --- /dev/null +++ b/npc/functions/shops.txt @@ -0,0 +1,13 @@ +// Evol functions. +// Author: +// 4144 +// Description: +// Shops utility functions +// Variables: +// none + +function script restoreshopitem { + if (shopcount(getarg(0)) < getarg(1)) + sellitem getarg(0), -1, getarg(1); + return; +} diff --git a/npc/functions/string.txt b/npc/functions/string.txt new file mode 100644 index 000000000..efeaf476d --- /dev/null +++ b/npc/functions/string.txt @@ -0,0 +1,195 @@ +// safe string manipulation functions +// ** does not require PCRE + + +// str(<int>) +// returns whatever is passed, converted to string + +function script str { + return "" + getarg(0); +} + + + +// startswith("<string>", "<search>") +// returns true if <string> begins with <search> + +function script startswith { + return substr(getarg(0), 0, getstrlen(getarg(1)) - 1) == getarg(1); +} + + + +// endswith("<string>", "<search>") +// returns true if <string> ends with <search> + +function script endswith { + .@t = getstrlen(getarg(0)); // total length + .@n = getstrlen(getarg(1)); // substring length + return substr(getarg(0), .@t - .@n, .@t - 1) == getarg(1); +} + + + +// capitalize("<string>") +// returns <string> with its first letter capitalized + +function script capitalize { + return setchar(getarg(0), strtoupper(charat(getarg(0), 0)), 0); +} + + + +// titlecase("<string>" {, "<delimiter>" {, <camel>}}) +// returns <string> with the first letter of each word capitalized +// if <camel> is true, the string is joined in a camelCase fashion + +function script titlecase { + .@delimiter$ = getarg(1, " "); + .@c = getarg(2, 0); + explode(.@words$, getarg(0), .@delimiter$); + + for (.@i = (.@c ? 1 : 0); .@i < 255; ++.@i) + { + if (.@words$[.@i] == "") + { + break; + } + + .@words$[.@i] = setchar(.@words$[.@i], strtoupper(charat(.@words$[.@i], 0)), 0); + } + + return implode(.@words$, (.@c ? "" : .@delimiter$)); +} + + + +// camelcase("<string" {, "<delimiter>"}) + +function script camelcase { + return titlecase(getarg(0), getarg(1, " "), true); +} + + + +// zfill("<string>" {, <width> {, "<padding>"}}) +// returns <string> padded to the left with <padding> up to width + +function script zfill { + .@str$ = getarg(0); + .@width = getarg(1, 8); + .@padding$ = getarg(2, "0"); + + for (.@s = getstrlen(.@str$); .@s < .@width; ++.@s) + { + .@str$ = .@padding$ + .@str$; + } + + return .@str$; +} + + + +// format_number(<integer> {, "<separator>"}) +// formats a number properly + +function script format_number { + .@number$ = str(getarg(0)); + .@len = getstrlen(.@number$); + .@separator$ = getarg(1, ","); + + if (getargcount() < 2 && playerattached()) { + // get from user language + switch (Lang) { + case 1: .@separator$ = " "; break; // French + default: .@separator$ = ","; // English (default) + } + } + + for (.@i = .@len - 3; .@i > 0; .@i -= 3) { + .@number$ = insertchar(.@number$, .@separator$, .@i); + } + + return .@number$; +} + + + +// strip("<string>") +// removes spaces at the start and end + +function script strip { + .@s$ = getarg(0); + if (.@s$ == "") { + return ""; + } + .@start = 0; + .@end = getstrlen(.@s$) - 1; + for (.@i = .@start; .@i < .@end; .@i++) + { + if (charat(.@s$, .@i) != " ") { + break; + } else { + .@start++; + } + } + for (.@i = .@end; .@i >= .@start; .@i--) + { + if (charat(.@s$, .@i) != " ") { + break; + } else { + .@end--; + } + } + return substr(.@s$, .@start, .@end); +} + + + +// reverse("<string>") +// returns <string> reversed + +function script reverse { + .@str$ = getarg(0); + .@len = getstrlen(.@str$); + + for (.@i = 0; .@i < (.@len / 2); ++.@i) { + .@tmp$ = charat(.@str$, .@i); + .@str$ = setchar(.@str$, charat(.@str$, (.@len - 1 - .@i)), .@i); // a <= b + .@str$ = setchar(.@str$, .@tmp$, (.@len - 1 - .@i)); // b <= a + } + + return .@str$; +} + + + +// repeat("<string>", <multiplier>) +// repeats <string> many times and returns it + +function script repeat { + .@mul = getarg(1); + + for (.@i = 0; .@i < .@mul; ++.@i) { + .@str$ += getarg(0); + } + + return .@str$; +} + + + +// shuffle("<string>") +// returns <string> shuffled + +function script shuffle { + .@str$ = getarg(0); + + for (.@len = getstrlen(.@str$); .@len > 0; --.@len) { + .@rnd = rand(.@len); + .@out$ += charat(.@str$, .@rnd); + .@str$ = delchar(.@str$, .@rnd); + } + + return .@out$; +} diff --git a/npc/functions/time.txt b/npc/functions/time.txt new file mode 100644 index 000000000..30ab9f469 --- /dev/null +++ b/npc/functions/time.txt @@ -0,0 +1,108 @@ +function script now { + return gettimetick(2); +} + + +function script time_from_ms { + return now() + (getarg(0) / 1000); +} + +function script time_from_seconds { + return now() + getarg(0); +} + +function script time_from_minutes { + return now() + (getarg(0) * 60); +} + +function script time_from_hours { + return now() + (getarg(0) * 3600); +} + +function script time_from_days { + return now() + (getarg(0) * 86400); +} + + +// FuzzyTime(<unix timestamp>{, <options>{, <precision>}}) +// gives time in a human-readable format +// +// <options> is bitmasked: +// 1 do not show "ago" when in past +// 2 do not show "in" when in the future +// 4 show "from now" instead of "in" when in the future +// +// <precision> is the number of units to show, +// by default uses max precision + +function script FuzzyTime { + .@future = getarg(0, now()); + .@options = getarg(1, 0); + .@precision = getarg(2, 99); + .@diff = (.@future - now()); + + // check if in the past, or in the future + if (.@diff < 0) { + .@diff *= -1; + .@past = true; + } + + .@diff = max(1, .@diff); + + if (.@diff >= 31536000) { + .@years = (.@diff / 31536000); + .@diff = (++.@s == .@precision ? 0 : (.@diff % 31536000)); + .@ret$ += sprintf("%d %s", .@years, (.@years > 1 ? "years" : "year")); + } + + if (.@diff >= 86400) { + .@days = (.@diff / 86400); + .@diff = (++.@s == .@precision ? 0 : (.@diff % 86400)); + + if (.@s > 1) { + .@ret$ += (.@diff > 0 ? ", " : " and "); + } + + .@ret$ += sprintf("%d %s", .@days, (.@days > 1 ? "days" : "day")); + } + + if (.@diff >= 3600) { + .@hours = (.@diff / 3600); + .@diff = (++.@s == .@precision ? 0 : (.@diff % 3600)); + + if (.@s > 1) { + .@ret$ += (.@diff > 0 ? ", " : (.@s >= 3 ? ", " : " ") + "and "); + } + + .@ret$ += sprintf("%d %s", .@hours, (.@hours > 1 ? "hours" : "hour")); + } + + if (.@diff >= 60) { + .@minutes = (.@diff / 60); + .@diff = (++.@s == .@precision ? 0 : (.@diff % 60)); + + if (.@s > 1) { + .@ret$ += (.@diff > 0 ? ", " : (.@s >= 3 ? ", " : " ") + "and "); + } + + .@ret$ += sprintf("%d %s", .@minutes, (.@minutes > 1 ? "minutes" : "minute")); + } + + if (.@diff >= 1) { + if (++.@s > 1) { + .@ret$ += (.@s >= 3 ? ", " : " ") + "and "; + } + + .@ret$ += sprintf("%d %s", .@diff, (.@diff > 1 ? "seconds" : "second")); + } + + if (.@past && !(.@options & 1)) { + .@ret$ += " ago"; + } + + if (!(.@past) && !(.@options & 2)) { + .@ret$ = ((.@options & 4) ? sprintf("%s from now", .@ret$) : sprintf("in %s", .@ret$)); + } + + return .@ret$; +} diff --git a/npc/functions/timer.txt b/npc/functions/timer.txt new file mode 100644 index 000000000..e79070f3b --- /dev/null +++ b/npc/functions/timer.txt @@ -0,0 +1,56 @@ +// areatimer("<map>", <x1>, <y1>, <x2>, <y2>, <tick>, "<npc>::<event>") +function script areatimer { + .@c = getunits(BL_PC, .@players, false, getarg(0), getarg(1), getarg(2), getarg(3), getarg(4)); + for (.@i = 0; .@i < .@c; .@i++) { + addtimer(getarg(5), getarg(6), .@players[.@i]); + } + return .@i; +} + +// areadeltimer("<map>", <x1>, <y1>, <x2>, <y2>, "<npc>::<event>") +function script areadeltimer { + .@c = getunits(BL_PC, .@players, false, getarg(0), getarg(1), getarg(2), getarg(3), getarg(4)); + for (.@i = 0; .@i < .@c; .@i++) { + deltimer(getarg(5), .@players[.@i]); + } + return .@i; +} + +// areatimer2("<map>", <x1>, <y1>, <x2>, <y2>, <tick>, "<npc>::<event>") +function script areatimer2 { + .@c = getunits(BL_PC, .@players, false, getarg(0), getarg(1), getarg(2), getarg(3), getarg(4)); + for (.@i = 0; .@i < .@c; .@i++) { + deltimer(getarg(6), .@players[.@i]); + addtimer(getarg(5), getarg(6), .@players[.@i]); + } + return .@i; +} + + +// maptimer("<map>", <tick>, "<npc>::<event>") +function script maptimer { + .@c = getunits(BL_PC, .@players, false, getarg(0)); + for (.@i = 0; .@i < .@c; .@i++) { + addtimer(getarg(1), getarg(2), .@players[.@i]); + } + return .@i; +} + +// maptimer2("<map>", <tick>, "<npc>::<event>") +function script maptimer2 { + .@c = getunits(BL_PC, .@players, false, getarg(0)); + for (.@i = 0; .@i < .@c; .@i++) { + deltimer(getarg(2), .@players[.@i]); + addtimer(getarg(1), getarg(2), .@players[.@i]); + } + return .@i; +} + +// mapdeltimer("<map>", "<npc>::<event>") +function script mapdeltimer { + .@c = getunits(BL_PC, .@players, false, getarg(0)); + for (.@i = 0; .@i < .@c; .@i++) { + deltimer(getarg(1), .@players[.@i]); + } + return .@i; +} diff --git a/npc/functions/util.txt b/npc/functions/util.txt new file mode 100644 index 000000000..ae70b233d --- /dev/null +++ b/npc/functions/util.txt @@ -0,0 +1,35 @@ +// Evol functions. +// Authors: +// Reid +// Description: +// Util functions + + +// season_direction({day, month}) +// returns the direction that represents our current season (approximation) +// DOWN: Winter, 21/12 +// DOWNLEFT: Spring, 20/03 +// LEFT: Summer, 21/06 +// UPLEFT: Autumn, 22/09 + +function script season_direction { + .@current_month = getarg(0, gettime(GETTIME_MONTH)); + + if (.@current_month % 3 == 0) + { + .@current_day = getarg(1, gettime(GETTIME_DAYOFMONTH)); + + switch (.@current_month) + { + case MARCH: .@season_day = 20; break; + case JUNE: .@season_day = 21; break; + case SEPTEMBER: .@season_day = 22; break; + case DECEMBER: .@season_day = 21; break; + default: break; + } + + .@is_after_season_day = .@current_day >= .@season_day ? 0 : -1; + } + + return (.@current_month / 3 + .@is_after_season_day) % 4; +} diff --git a/npc/functions/villagertalk.txt b/npc/functions/villagertalk.txt new file mode 100644 index 000000000..371a9f20b --- /dev/null +++ b/npc/functions/villagertalk.txt @@ -0,0 +1,53 @@ +// Evol functions. +// Authors: +// Akko Teru +// Qwerty Dragon +// Reid +// Description: +// Tell a random sentence. || There ought to be a law! + +function script villagertalk { + + function darn_or_smile + { + .@darn = rand(42); + + if (.@darn < 26) + { + emotion E_JOY; + hello; + } + else if (.@darn > 26) + { + emotion E_LOOKAWAY; + goodbye; + } + else + { + npctalkonce(l("Stop it!")); + } + + return; + } + + switch (rand(4)) + { + case 0: + darn_or_smile(); + break; + case 1: + npctalkonce(l("It is a sunny day, don't you think?")); + break; + case 2: + npctalkonce(l("Go fly a kite.")); + break; + case 3: + npctalkonce(l("I just want to live my life in peace.")); + break; + default: + emotion E_HAPPY; + break; + } + + return; +} |