summaryrefslogtreecommitdiff
path: root/npc/functions/main.txt
diff options
context:
space:
mode:
Diffstat (limited to 'npc/functions/main.txt')
-rw-r--r--npc/functions/main.txt750
1 files changed, 750 insertions, 0 deletions
diff --git a/npc/functions/main.txt b/npc/functions/main.txt
new file mode 100644
index 00000000..d072ff60
--- /dev/null
+++ b/npc/functions/main.txt
@@ -0,0 +1,750 @@
+// TMW2 Script
+// Evol functions.
+// Authors:
+// 4144
+// Travolta
+// gumi
+// Jesusalva
+// Description:
+// Built-in essential functions.
+
+function script menuimage {
+ return getarg(0) + "|" + getarg(1);
+}
+
+function script dnext {
+ if (@dnext >= GSET_LONGMENU_DENSITY) {
+ @dnext=0;
+ next;
+ } else {
+ @dnext+=1;
+ }
+ return;
+}
+
+function script menuaction {
+ return "[" + getarg(0) + "]";
+}
+
+function script setq1 {
+ // Quest, val1 , val2 , val3 , time
+ setq getarg(0), getarg(1), getq2(getarg(0)), getq3(getarg(0)), getqtime(getarg(0));
+ return;
+}
+
+function script setq2 {
+ // Quest, val1 , val2 , val3 , time
+ setq getarg(0), getq(getarg(0)), getarg(1), getq3(getarg(0)), getqtime(getarg(0));
+ return;
+}
+
+function script setq3 {
+ // Quest, val1 , val2 , val3 , time
+ setq getarg(0), getq(getarg(0)), getq2(getarg(0)), getarg(1), getqtime(getarg(0));
+ return;
+}
+
+function script setqtime {
+ // Quest, val1 , val2 , val3 , time
+ setq getarg(0), getq(getarg(0)), getq2(getarg(0)), getq3(getarg(0)), getarg(1);
+ return;
+}
+
+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 b {
+ return "##B" + getarg(0) + "##b";
+}
+
+function script col {
+ .@color = getarg(1,9);
+ if (.@color < 0) .@color = 0;
+ if (.@color > 9) .@color = 9;
+ return "##" + .@color + getarg(0) + "##0";
+}
+
+function script adddefaultskills {
+ if (getskilllv(NV_BASIC) < 7) {
+ skill NV_BASIC, 7, 0;
+ }
+ if (getskilllv(TMW2_FAKESKILL) < 1) {
+ skill TMW2_FAKESKILL, 1, 0;
+ }
+ return;
+}
+
+function script addremovemapmask {
+ setmapmask getarg(0), (getmapmask(getarg(0)) | (getarg(1) + getarg(2))) ^ getarg(2);
+ return;
+}
+
+function script mesc {
+ mes col(getarg(0),getarg(1,9));
+ return;
+}
+
+function script get_race {
+ .@g=getarg(0, Class);
+ return l($@allraces$[.@g]);
+}
+
+// tutmes (message, {header=Tutorial, headerfirst=True})
+function script tutmes {
+ .@header$=getarg(1, l("TUTORIAL"));
+ .@showheader=getarg(2, true);
+ .@tcol=9; // Tutorial color code
+
+ if (TUTORIAL) {
+ dnext;
+ if (.@showheader) {
+ mesf(".:: %s ::.", .@header$);
+ mesc getarg(0), .@tcol;
+ } else {
+ mesc .@header$+": "+getarg(0), .@tcol;
+ }
+ }
+ 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
+// TODO: Use temp player var, because NPC var affect other players
+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()])
+ return false;
+ @NPC_TALK_LOCK[getnpcid()] = 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;
+}
+
+// Randomizer functions
+/////////////////////////////////////////////
+
+// pseudo-fix randomness
+// rand2( min, max )
+function script rand2 {
+ if (getargcount() == 2) {
+ .@min=getarg(0)*100;
+ .@max=getarg(1)*100+99;
+ } else {
+ .@min=0;
+ .@max=getarg(0)*100-1;
+ }
+ return rand(.@min, .@max)/100;
+}
+
+// returns one argument randomly
+// any( <arg>{, ...<arg>} )
+function script any {
+ return getarg(rand2(getargcount()));
+}
+
+// returns any member of the array
+// any_of( <array> )
+function script any_of {
+ return getelementofarray(getarg(0), getarrayindex(getarg(0)) + rand2(getarraysize(getarg(0)) - getarrayindex(getarg(0))));
+}
+
+function script die {
+ if ($HARDCORE) {
+ @grace=true;
+ percentheal -100, -100;
+ //setparam(Hp, 1);
+ //warp "000-1", 22, 22;
+ //end; // MUST be end; to mimic official behavior
+ } else {
+ percentheal -100, -100;
+ }
+ return;
+}
+
+// Returns if a map is on PVP Mode or Not
+// ispvpmap( {mapid} )
+function script ispvpmap {
+ .@mapa$=getarg(0, getmapname());
+ return (getmapflag(.@mapa$, mf_pvp) || getmapflag(.@mapa$, mf_pvp_noparty) || getmapflag(.@mapa$, mf_pvpnoguild));
+}
+
+// TMW2 Custom Functions
+/////////////////////////////////////////////
+
+// Function meant to be used by Main Storyline Quest
+// msObjective ( condition , message )
+function script msObjective {
+ if (getarg(0))
+ mesc getarg(1), 2;
+ else
+ mesc getarg(1), 9;
+ return;
+}
+
+function script getmap {
+ if (getmapxy(.@mapName$, .@xpos, .@ypos, getarg(0,0)) != 0)
+ return false;
+ // TODO: Maybe use getmapname() instead of getmapxy?
+ return .@mapName$;
+}
+
+// isin( map, x1, y1, {[x2, y2][radius]} )
+function script isin {
+ if (getmapxy(.@mapName$, .@xpos, .@ypos, 0) != 0)
+ return false;
+ if (.@mapName$ != getarg(0))
+ return false;
+
+ if (getarg(4,-1) < 0) {
+ // Radius Based
+ if (.@xpos >= getarg(1)-getarg(3) && .@xpos <= getarg(1)+getarg(3) && .@ypos >= getarg(2)-getarg(3) && .@ypos <= getarg(2)+getarg(3))
+ return true;
+ } else {
+ // Coordinate based
+ if (.@xpos >= getarg(1) && .@xpos <= getarg(3) && .@ypos >= getarg(2) && .@ypos <= getarg(4))
+ return true;
+ }
+ return false;
+}
+
+// Clear output of getinventorylist()
+// delinventorylist()
+function script delinventorylist {
+ deletearray @inventorylist_id;
+ deletearray @inventorylist_amount;
+ deletearray @inventorylist_equip;
+ deletearray @inventorylist_refine;
+ deletearray @inventorylist_identify;
+ deletearray @inventorylist_attribute;
+ deletearray @inventorylist_card1;
+ deletearray @inventorylist_card2;
+ deletearray @inventorylist_card3;
+ deletearray @inventorylist_card4;
+ deletearray @inventorylist_expire;
+ deletearray @inventorylist_bound;
+ @inventorylist_count=0;
+ return;
+}
+
+// Get some acc id, even if offline
+// ( Name )
+function script gf_accid {
+ .@nb = query_sql("SELECT `account_id` FROM `char` WHERE `name`='"+escape_sql(getarg(0))+"' LIMIT 1", .@value);
+ return .@value[0];
+}
+
+// Get some char id, even if offline
+// ( Name )
+function script gf_charnameid {
+ .@nb = query_sql("SELECT `char_id` FROM `char` WHERE `name`='"+escape_sql(getarg(0))+"' LIMIT 1", .@value);
+ return .@value[0];
+}
+
+// Get some char name from char ID, even if offline
+// ( Name )
+function script gf_charname {
+ .@nb = query_sql("SELECT `name` FROM `char` WHERE `char_id`="+escape_sql(getarg(0))+" LIMIT 1", .@value$);
+ return .@value$[0];
+}
+
+// Get some char ID from account ID, even if offline
+// ( Name )
+function script gf_charid {
+ .@nb = query_sql("SELECT `char_id` FROM `char` WHERE `account_id`="+escape_sql(getarg(0))+" LIMIT 1", .@value$);
+ return .@value$[0];
+}
+
+// Request pincode and validate it. Use any non-4-digits code to cancel. Failure will dc you.
+// Returns 1 if pin check is OK.
+function script validatepin {
+ if (#FIRST_TIME < 2) {
+ mesc l("ERROR: You must set a PinCode to make use of this function."), 1;
+ return 0;
+ }
+ mesc l("Please insert your pincode."), 1;
+ mesc l("WARNING: If you insert wrong pincode, you'll be disconnected.");
+ mesc l("Use @@ to cancel.", "##B-1##b");
+ mes "";
+ input .@pin$;
+ if (getstrlen(.@pin$) != 4)
+ return 0;
+ query_sql("SELECT userid FROM `login` WHERE account_id="+escape_sql(getcharid(3))+" AND pincode='"+escape_sql(.@pin$)+"' LIMIT 2", .@value$);
+ if (getarraysize(.@value$) != 1) {
+ atcommand "@kick "+strcharinfo(0);
+ return 0;
+ }
+ // Enforce some cooldown to prevent an eventual exploit/abuse
+ sleep2(rand2(150, 400));
+ mesc l("Thanks, @@. We just wanted to be sure it was you.", .@value$[0]);
+ mes "";
+ return true;
+}
+
+// Something went wrong and must be reported (named after raise Exception in python)
+// Exception( BugID, {Flags{, Return Code}} )
+function script Exception {
+ // Fill variable
+ .@msg$=getarg(0);
+ .@gf=getarg(1,RB_DEFAULT);
+
+ if (.@gf & RB_DISPBOTTOM)
+ dispbottom("ERROR: "+.@msg$);
+
+ if (.@gf & RB_DEBUGMES)
+ debugmes("[Warning] "+.@msg$);
+
+ if (.@gf & RB_SPEECH)
+ mesc("ERROR, REPORT ME! "+.@msg$, 1);
+
+ if (.@gf & RB_IRCBROADCAST)
+ channelmes("#world", "Error in script: "+.@msg$);
+
+ if (.@gf & RB_GLOBALANNOUNCE)
+ announce("Error in script: "+.@msg$, bc_all);
+
+ if (.@gf & RB_PLEASEREPORT) {
+ if (.@gf & RB_DISPBOTTOM)
+ dispbottom("Please take a screenshot and report this bug, explaining how it happened.");
+
+ if (.@gf & RB_SPEECH)
+ mesc("Please take a screenshot and report this bug, explaining how it happened."), 1;
+ }
+
+ if (.@gf & RB_ISFATAL) {
+ if (.@gf & RB_DISPBOTTOM)
+ dispbottom("This error is fatal, we stop execution.");
+
+ if (.@gf & RB_DEBUGMES)
+ debugmes("[Error] The error is fatal.");
+
+ if (.@gf & RB_SPEECH) {
+ mesc l("This error is fatal, we stop execution."), 1;
+ close;
+ }
+ end;
+ }
+
+ return getarg(2, 0);
+}
+
+// mescordialog(text, color, {dialog=1})
+function script mescordialog {
+ if (getarg(2, true))
+ mesc getarg(0), getarg(1);
+ else
+ dispbottom col(getarg(0), getarg(1));
+ return;
+}
+
+// Delayed healing. Takes 3~5 seconds. Variates with Vit up to +100%.
+// The vit can have an additional 20% bonus as well.
+function script itheal {
+ .@bas=getarg(0);
+ .@vit=readbattleparam(getcharid(3), UDT_VIT);
+ .@vit=cap_value(.@vit-1, 0, 100);
+ if (getargcount() > 2)
+ .@tim=getarg(3);
+ else
+ .@tim=rand2(3,5);
+ .@min=.@bas*(100+.@vit)/100;
+ .@max=.@bas*(100+.@vit*120/100)/100;
+ // Now divide the HP values by the time
+ .@min=max(1, .@min/.@tim);
+ .@max=max(1, .@max/.@tim);
+ callfunc("SC_Bonus", .@tim, SC_S_LIFEPOTION, .@min, .@max);
+ if (getarg(1,0) > 0)
+ heal 0, getarg(1, 0);
+ return;
+}
+
+// sqldate({day variation, month variation})
+function script sqldate {
+ .@d=gettime(GETTIME_DAYOFMONTH)+getarg(0, 0);
+ .@m=gettime(GETTIME_MONTH)+getarg(1, 0);
+ .@y=gettime(GETTIME_YEAR);
+ // Overflow prevention
+ if (.@d <= 0) {
+ .@d=1;
+ }
+ while (.@m > 12) {
+ .@y+=1;
+ .@m-=12;
+ }
+ while (.@m < 1) {
+ .@y-=1;
+ .@m+=12;
+ }
+ .@strdate$=sprintf("%04d-%02d-%02d %02d:%02d:%02d", .@y, .@m, .@d, gettime(GETTIME_HOUR), gettime(GETTIME_MINUTE), gettime(GETTIME_SECOND));
+ return .@strdate$;
+}
+
+// Makes a monster aggro
+// set_aggro( monster{, mode=MD_AGGRESSIVE} )
+function script set_aggro {
+ .@m=getarg(0);
+ .@x=getarg(1, MD_AGGRESSIVE);
+ .@op=getunitdata(.@m, UDT_MODE);
+ .@op=.@op|.@x;
+ setunitdata(.@m, UDT_MODE, .@op);
+ return;
+}
+
+// Special function which makes a date as a number
+// numdate( - )
+function script numdate {
+ .@strdate$=sprintf("%04d%02d%02d", gettime(GETTIME_YEAR), gettime(GETTIME_MONTH), gettime(GETTIME_DAYOFMONTH));
+ // Debug payload
+ if ($@OVERRIDE_NUMDATE)
+ return $@OVERRIDE_NUMDATE;
+ return atoi(.@strdate$);
+}
+
+// json_encode( {varname, varvalue}, {varname 2, varvalue 2}... )
+// returns string
+function script json_encode {
+ if (getargcount() < 2 || getargcount() % 2 != 0)
+ return Exception("json_encode arguments must be paired");
+
+ .@json$="{";
+ .@tab=true;
+
+ // For arguments
+ for (.@i=0;.@i < getargcount(); .@i++) {
+ // Close previous item
+ if (.@tab)
+ .@tab=false;
+ else
+ .@json$+=",";
+
+ // Input variable name
+ .@json$+="\""+getarg(.@i)+"\": ";
+
+ // Input variable value
+ if (isstr(getarg(.@i+1)))
+ .@json$+="\""+getarg(.@i+1)+"\"";
+ else
+ .@json$+=getarg(.@i+1);
+
+ // Advance
+ .@i++;
+ }
+
+ // Close the JSON
+ .@json$+="}";
+ return .@json$;
+}
+
+
+// api_send( code, data )
+// sends to API
+function script api_send {
+ .@cde=getarg(0);
+ .@fm$=escape_sql(getarg(1));
+ query_sql("INSERT INTO `api_export` (`type`, `data`) VALUES ('"+.@cde+"', \""+.@fm$+"\")");
+ return;
+}
+
+// Linking functions
+/////////////////////////////////////////////
+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) + "|@@]";
+}
+
+// Legacy functions
+/////////////////////////////////////////////
+function script mapexit {
+ debugmes "TRYING TO MAPEXIT IS DEPRECATED";
+ return;
+}
+
+function script destroy {
+ disablenpc strnpcinfo(0);
+ return;
+}
+
+function script npcaction {
+ debugmes "Deprecated unitaction (did you mean npcsit; or whatever?)";
+ .@a=getarg(0, 0);
+ if (.@a == 9)
+ clear;
+ return;
+}
+
+function script gmlog {
+ logmes(getarg(0), LOGMES_ATCOMMAND);
+ return;
+}
+
+function script getx {
+ getmapxy(.@m$, .@x, .@y, 0);
+ return .@x;
+}
+
+function script gety {
+ getmapxy(.@m$, .@x, .@y, 0);
+ return .@y;
+}
+
+function script getnpcx {
+ return .x;
+}
+
+function script getnpcy {
+ return .y;
+}
+
+function script title {
+ setnpcdialogtitle getarg(0);
+ return;
+}
+
+function script camera {
+ if (getarg(0, "") != "")
+ setcamnpc getarg(0);
+ else
+ restorecam;
+ return;
+}
+
+function script mapmask {
+ sendmapmask getarg(0);
+ return;
+}
+
+function script getmask {
+ return 1; //getmapmask(getmapname()); // TODO: Return original map masks
+}
+
+// isat( map, x, y )
+function script isat {
+ return isin(getarg(0), getarg(1), getarg(2), 0);
+}
+
+function script if_then_else {
+ return (getarg(0) ? getarg(1) : getarg(2));
+}
+
+function script misceffect {
+ // or SELF + something
+ return specialeffect(getarg(0), AREA, getarg(1, strnpcinfo(0)));
+}
+
+function script fakenpcname {
+ if (getargcount() > 2)
+ setnpcdisplay(getarg(0), getarg(1), getarg(2));
+ else
+ setnpcdisplay(getarg(0), getarg(1));
+ return;
+}
+
+function script npcwarp {
+ if (getargcount() > 2)
+ .@id=getnpcid(getarg(3));
+ else
+ .@id=getnpcid();
+
+ getmapxy(.@m$, .@x, .@y, UNITTYPE_NPC, strnpcinfo(0, "", .@id));
+ unitwarp(.@id, .@m$, getarg(0), getarg(1));
+ return;
+}
+
+function script get {
+ return getvariableofnpc(getarg(0), getarg(1));
+}
+
+function script sc_check {
+ return getstatus(getarg(0), getarg(1, 0));
+}
+
+function script wgm {
+ charcommand("@request "+getarg(0));
+ return;
+}
+
+function script registercmd {
+ // Remove "@" from command start
+ .@cmd$=getarg(1);
+ if (charat(.@cmd$, 0) == "@")
+ delchar(.@cmd$, 0);
+ bindatcmd getarg(0), .@cmd$, getarg(2, 0);
+ return;
+}
+
+function script iscollision {
+ return checknpccell(getarg(0), getarg(1), getarg(2), cell_chkpass);
+}
+
+function script readparam2 {
+ return readbattleparam(getcharid(3), getarg(0));
+}
+
+function script updateskill {
+ skill getarg(0), getarg(1), 0;
+ return;
+}
+
+function script learnskill {
+ if (getskilllv(getarg(0)) < getarg(1, 1))
+ skill getarg(0), getarg(1, 1), 0;
+ return;
+}
+