// 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; } if (getskilllv(TMW2_FAKESKILL2) < 1) { skill TMW2_FAKESKILL2, 1, 0; } if (getskilllv(TMW2_DROPS) < REBIRTH+1) { skill TMW2_DROPS, (REBIRTH+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++) { if (getarg(.@i) == "") continue; mes col(getarg(.@i), 9); if (.@i < .@argc - 1) dnext; } if (.@flags & 0x4) dnext; 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) dnext; } if (.@flags & 0x4) dnext; 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( {, ...} ) function script any { return getarg(rand2(getargcount())); } // returns any member of the array // any_of( ) 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; } // 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$; } // Get unit BL from type // ( unittype ) function script getunitbl { switch (getarg(0)) { case UNITTYPE_PC: return BL_PC; case UNITTYPE_NPC: return BL_NPC; case UNITTYPE_PET: return BL_PET; case UNITTYPE_MOB: return BL_MOB; case UNITTYPE_HOM: return BL_HOM; case UNITTYPE_MER: return BL_MER; case UNITTYPE_ELEM: return BL_ELEM; default: consolewarn("Invalid unit type on getunitbl: %d", getarg(0)); return BL_ALL; } return 0; } // 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; } // isat( map, x, y ) function script isat { return isin(getarg(0), getarg(1), getarg(2), 0); } // 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); // Avoid self-errors if (!playerattached()) { if (.@gf & RB_DISPBOTTOM) .@gf = .@gf ^ RB_DISPBOTTOM; if (.@gf & RB_SPEECH) .@gf = .@gf ^ RB_SPEECH; } // Main protocols if (.@gf & RB_DISPBOTTOM) dispbottom("ERROR: "+.@msg$); if (.@gf & RB_DEBUGMES) consolewarn(.@msg$); //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) consolebug("Previous warning was fatal, halting execution."); //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); } // 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) + "|@@]"; }