// 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) < 6) {
skill NV_BASIC, 6, 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( <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;
}
// 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) + "|@@]";
}