summaryrefslogtreecommitdiff
path: root/world/map/npc/commands
diff options
context:
space:
mode:
Diffstat (limited to 'world/map/npc/commands')
-rw-r--r--world/map/npc/commands/_import.txt10
-rw-r--r--world/map/npc/commands/_procedures.txt53
-rw-r--r--world/map/npc/commands/changesex.txt32
-rw-r--r--world/map/npc/commands/class.txt31
-rw-r--r--world/map/npc/commands/debug.txt992
-rw-r--r--world/map/npc/commands/destroynpc.txt35
-rw-r--r--world/map/npc/commands/marry.txt69
-rw-r--r--world/map/npc/commands/numa.txt132
-rw-r--r--world/map/npc/commands/pullrabbit.txt25
-rw-r--r--world/map/npc/commands/remotecmd.txt62
-rw-r--r--world/map/npc/commands/zeny.txt79
11 files changed, 1520 insertions, 0 deletions
diff --git a/world/map/npc/commands/_import.txt b/world/map/npc/commands/_import.txt
new file mode 100644
index 00000000..3cabe0b7
--- /dev/null
+++ b/world/map/npc/commands/_import.txt
@@ -0,0 +1,10 @@
+npc: npc/commands/_procedures.txt
+npc: npc/commands/zeny.txt
+npc: npc/commands/marry.txt
+npc: npc/commands/debug.txt
+npc: npc/commands/changesex.txt
+npc: npc/commands/class.txt
+npc: npc/commands/pullrabbit.txt
+npc: npc/commands/numa.txt
+npc: npc/commands/destroynpc.txt
+npc: npc/commands/remotecmd.txt
diff --git a/world/map/npc/commands/_procedures.txt b/world/map/npc/commands/_procedures.txt
new file mode 100644
index 00000000..732b496f
--- /dev/null
+++ b/world/map/npc/commands/_procedures.txt
@@ -0,0 +1,53 @@
+// ARGV Splitter
+// takes @args$ and splits it properly so that '@cmd "foo bar" baz' is ['foo bar','baz'] instead of ['"foo','bar"','baz']
+// input: @args$ (string)
+// output: @argv$ (array) and @argv (array)
+function|script|argv_splitter
+{
+ explode .@fragments$, @args$, " ";
+ set .@e, 0;
+ set .@total, getarraysize(.@fragments$);
+ set .@NULL$, chr(3); // HACK: we use .@NULL$ as a workaround because we can't do "\0"
+ goto L_Check;
+
+L_Check:
+ setarray .@check$[0], "", .@NULL$, .@NULL$;
+ explode .@check$, .@fragments$[.@e], "\""; // check if the fragment contains a quote
+ if (.@check$[0] == "" && .@check$[1] != .@NULL$ && .@check$[1] != "" && .@check$[2] == .@NULL$)
+ set .@string$, .@check$[1]; // begin substring
+ elif (.@check$[0] != "" && .@check$[1] == "" && .@check$[2] == .@NULL$)
+ goto L_EndSubString; // end substring
+ elif (.@string$ != "" && .@check$[0] != "" && .@check$[1] == .@NULL$ && .@check$[2] == .@NULL$)
+ set .@string$, .@string$ +" "+ .@check$[0]; // part of the substring
+ elif (.@check$[2] != .@NULL$) goto L_Set2; // the the argument is quoted but there is no space
+ else goto L_Set;
+ goto L_CheckAfter;
+
+L_Set:
+ setarray @argv$[.@t], .@check$[0]; // not in a substring so push right away
+ setarray @argv[.@t], .@check$[0]; // not in a substring so push right away
+ set .@t, .@t + 1;
+ goto L_CheckAfter;
+
+L_Set2:
+ setarray @argv$[.@t], .@check$[1]; // not in a substring so push right away
+ setarray @argv[.@t], .@check$[1]; // not in a substring so push right away
+ set .@t, .@t + 1;
+ goto L_CheckAfter;
+
+L_EndSubString:
+ set .@string$, .@string$ + " " + .@check$[0];
+ setarray @argv$[.@t], .@string$; // push in the array
+ setarray @argv[.@t], .@string$; // push in the array
+ set .@t, .@t + 1;
+ set .@string$, ""; // clean
+ goto L_CheckAfter;
+
+L_CheckAfter:
+ set .@e, .@e + 1;
+ if (.@e > .@total) goto L_Done; // the @argv$ array is built
+ goto L_Check; // not done yet
+
+L_Done:
+ return;
+}
diff --git a/world/map/npc/commands/changesex.txt b/world/map/npc/commands/changesex.txt
new file mode 100644
index 00000000..fca27645
--- /dev/null
+++ b/world/map/npc/commands/changesex.txt
@@ -0,0 +1,32 @@
+-|script|@changesex|32767
+{
+ callfunc "argv_splitter";
+ set .@n$, if_then_else(@argv$[1] != "", "char", "") + "changesex";
+ if (GM < CMD_CHANGESEX && GM < G_SYSOP) goto L_GM; // check if you can use it on self
+ set .@target_id, BL_ID;
+ if (@argv$[1] != "") set .@target_id, getcharid(3, @argv$[1]);
+ if (@argv$[1] != "" && !(isloggedin(.@target_id))) goto L_Failed; // do NOT fallback to self
+ if (@argv$[1] != "" && GM < CMD_CHARCHANGESEX && GM < G_SYSOP) goto L_GM; // when target is not self, use charchangesex permission
+
+ set .@s, 3; // default to non-binary
+ if (@argv$[0] == "M" || @argv$[0] == "m") set .@s, 1;
+ if (@argv$[0] == "F" || @argv$[0] == "f") set .@s, 0;
+ set Sex, .@s, .@target_id;
+ gmlog "@"+.@n$+" " + @args$;
+ message strcharinfo(0), .@n$+" : The operation succeeded.";
+ end;
+
+L_Failed:
+ // XXX: should we allow GMs to change sex of users that are not logged in?
+ message strcharinfo(0), .@n$+" : Impossible to attach to the target player. Did you try putting the name in \"quotation marks\"?";
+ end;
+
+L_GM:
+ message strcharinfo(0), .@n$+" : GM command is level "+ if_then_else(@argv$[1] != "", CMD_CHARCHANGESEX, CMD_CHANGESEX) +", but you are level " + GM;
+ end;
+
+OnInit:
+ registercmd chr(ATCMD_SYMBOL) + "changesex", strnpcinfo(0);
+ registercmd chr(ATCMD_SYMBOL) + "charchangesex", strnpcinfo(0);
+ end;
+}
diff --git a/world/map/npc/commands/class.txt b/world/map/npc/commands/class.txt
new file mode 100644
index 00000000..9143e08a
--- /dev/null
+++ b/world/map/npc/commands/class.txt
@@ -0,0 +1,31 @@
+-|script|@class|32767
+{
+ callfunc "argv_splitter";
+ set .@n$, if_then_else(@argv$[1] != "", "char", "") + "class";
+ if (GM < CMD_CLASS && GM < G_SYSOP) goto L_GM; // check if you can use it on self
+ set .@target_id, BL_ID;
+ if (@argv$[1] != "") set .@target_id, getcharid(3, @argv$[1]);
+ if (@argv$[1] != "" && !(isloggedin(.@target_id))) goto L_Failed; // do NOT fallback to self
+ if (@argv$[1] != "" && GM < CMD_CHARCLASS && GM < G_SYSOP) goto L_GM; // when target is not self, use charclass permission
+
+ set .@c, 1; // default to human
+ if (@argv[0] >= 1 || @argv[0] <= 32767) set .@c, @argv[0];
+ set Class, .@c, .@target_id;
+ gmlog "@"+.@n$+" " + @args$;
+ message strcharinfo(0), .@n$+" : The operation succeeded.";
+ end;
+
+L_Failed:
+ // XXX: should we allow GMs to change class of users that are not logged in?
+ message strcharinfo(0), .@n$+" : Impossible to attach to the target player. Did you try putting the name in \"quotation marks\"?";
+ end;
+
+L_GM:
+ message strcharinfo(0), .@n$+" : GM command is level "+ if_then_else(@argv$[1] != "", CMD_CHARCLASS, CMD_CLASS) +", but you are level " + GM;
+ end;
+
+OnInit:
+ registercmd chr(ATCMD_SYMBOL) + "class", strnpcinfo(0);
+ registercmd chr(ATCMD_SYMBOL) + "charclass", strnpcinfo(0);
+ end;
+}
diff --git a/world/map/npc/commands/debug.txt b/world/map/npc/commands/debug.txt
new file mode 100644
index 00000000..19ac4114
--- /dev/null
+++ b/world/map/npc/commands/debug.txt
@@ -0,0 +1,992 @@
+// Authors: alastrim, Jenalya, Ali-G
+
+function|script|Debug
+{
+ if(!@debug_npc) goto L_Begin;
+ mes "The debug NPCs have been deprecated. Please use this command instead:";
+ mes "";
+ mes "%%E ##a@debug##0";
+ set @debug_npc, 0;
+ goto L_Close;
+
+L_Begin:
+ set @debug_mask, 65535;
+ set @debug_shift, 0;
+ set @mexp, ((MAGIC_EXPERIENCE & @debug_mask) >> @debug_shift);
+ mes "What do you want to do?";
+ menu
+ "Change my level.", L_Level,
+ "Change my stats.", L_Status,
+ "Change my basic skills.", L_BasicSkills,
+ "Change my focus skills.", L_FocusSkills,
+ "Change my magic skills.", L_MagicSkills,
+ "Add everything.", L_AddAll,
+ "Reset everything.", L_ResetAll,
+ "Close.", L_Close;
+
+L_Level:
+ mes "What level do you want to be (min: 1 - max: 99)?";
+ input @lvl;
+ if (@lvl < 1)
+ goto L_LevelTooLow;
+ if (@lvl > 99)
+ goto L_LevelTooHigh;
+ if (BaseLevel == @lvl)
+ goto L_SameLevel;
+ set BaseLevel, @lvl;
+ resetstatus;
+ mes "You are now level " + BaseLevel + ".";
+ goto L_Begin;
+
+L_LevelTooLow:
+ mes "Bad choice. Minimum level is 1.";
+ next;
+ goto L_Begin;
+
+L_LevelTooHigh:
+ mes "Bad choice. Maximum level is 99.";
+ next;
+ goto L_Begin;
+
+L_SameLevel:
+ mes "You already are level " + @lvl + ".";
+ next;
+ goto L_Begin;
+
+L_Status:
+ mes "What do you want to do?";
+ menu
+ "Set all of my stats myself.", L_ChangeStrength,
+ "Set one of my stats myself.", L_ChangeSingleStat,
+ "Get maximum points in all stats.", L_ChangeAllStats,
+ "Reset my status points.", L_ResetStatusPoints,
+ "Back to the main menu.", L_Begin,
+ "Close.", L_Close;
+
+L_ChangeAllStats:
+ set Str, 99;
+ set Agi, 99;
+ set Vit, 99;
+ set Int, 99;
+ set Dex, 99;
+ set Luk, 99;
+ mes "You now have 99 in all stats.";
+ next;
+ goto L_Begin;
+
+L_ChangeStrength:
+ mes "How much strength do you want to have (min: 1 - max: 99)?";
+ input @str;
+ if (@str < 1)
+ goto L_StatTooLow;
+ if (@str > 99)
+ goto L_StatTooHigh;
+ set Str, @str;
+ goto L_ChangeAgility;
+
+L_ChangeAgility:
+ mes "How much agility do you want to have (min: 1 - max: 99)?";
+ input @agi;
+ if (@agi < 1)
+ goto L_StatTooLow;
+ if (@agi > 99)
+ goto L_StatTooHigh;
+ set Agi, @agi;
+ goto L_ChangeVitality;
+
+L_ChangeVitality:
+ mes "How much vitality do you want to have (min: 1 - max: 99)?";
+ input @vit;
+ if (@vit < 1)
+ goto L_StatTooLow;
+ if (@vit > 99)
+ goto L_StatTooHigh;
+ set Vit, @vit;
+ goto L_ChangeIntelligence;
+
+L_ChangeIntelligence:
+ mes "How much intelligence do you want to have (min: 1 - max: 99)?";
+ input @int;
+ if (@int < 1)
+ goto L_StatTooLow;
+ if (@int > 99)
+ goto L_StatTooHigh;
+ set Int, @int;
+ goto L_ChangeDexterity;
+
+L_ChangeDexterity:
+ mes "How much dexterity do you want to have (min: 1 - max: 99)?";
+ input @dex;
+ if (@dex < 1)
+ goto L_StatTooLow;
+ if (@dex > 99)
+ goto L_StatTooHigh;
+ set Dex, @dex;
+ goto L_ChangeLuck;
+
+L_ChangeLuck:
+ mes "How much luck do you want to have (min: 1 - max: 99)?";
+ input @luk;
+ if (@luk < 1)
+ goto L_StatTooLow;
+ if (@luk > 99)
+ goto L_StatTooHigh;
+ set Luk, @luk;
+ mes "You now have " + Str + " in strength.";
+ mes "You now have " + Agi + " in agility.";
+ mes "You now have " + Vit + " in vitality.";
+ mes "You now have " + Int + " in intelligence.";
+ mes "You now have " + Dex + " in dexterity.";
+ mes "You now have " + Luk + " in luck.";
+ next;
+ goto L_Begin;
+
+L_StatTooLow:
+ mes "Bad choice. Minimum stat value is 1. Aborting.";
+ next;
+ goto L_Status;
+
+L_StatTooHigh:
+ mes "Bad choice. Maximum stat value is 99. Aborting.";
+ next;
+ goto L_Status;
+
+L_ChangeSingleStat:
+ mes "Which stat do you want to change?";
+ menu
+ "Strength.", L_ChangeStrengthSingle,
+ "Agility.", L_ChangeAgilitySingle,
+ "Vitality.", L_ChangeVitalitySingle,
+ "Intelligence.", L_ChangeIntelligenceSingle,
+ "Dexterity.", L_ChangeDexteritySingle,
+ "Luck.", L_ChangeLuckSingle,
+ "Back to the main menu.", L_Begin,
+ "Close.", L_Close;
+
+L_ChangeStrengthSingle:
+ mes "How much strength do you want to have (min: 1 - max: 99)?";
+ input @str;
+ if (@str < 1)
+ goto L_StatTooLow;
+ if (@str > 99)
+ goto L_StatTooHigh;
+ set Str, @str;
+ mes "You now have " + Str + " in strength.";
+ next;
+ goto L_Begin;
+
+L_ChangeAgilitySingle:
+ mes "How much agility do you want to have (min: 1 - max: 99)?";
+ input @agi;
+ if (@agi < 1)
+ goto L_StatTooLow;
+ if (@agi > 99)
+ goto L_StatTooHigh;
+ set Agi, @agi;
+ mes "You now have " + Agi + " in agility.";
+ next;
+ goto L_Begin;
+
+L_ChangeVitalitySingle:
+ mes "How much vitality do you want to have (min: 1 - max: 99)?";
+ input @vit;
+ if (@vit < 1)
+ goto L_StatTooLow;
+ if (@vit > 99)
+ goto L_StatTooHigh;
+ set Vit, @vit;
+ mes "You now have " + Vit + " in vitality.";
+ next;
+ goto L_Begin;
+
+L_ChangeIntelligenceSingle:
+ mes "How much intelligence do you want to have (min: 1 - max: 99)?";
+ input @int;
+ if (@int < 1)
+ goto L_StatTooLow;
+ if (@int > 99)
+ goto L_StatTooHigh;
+ set Int, @int;
+ mes "You now have " + Int + " in intelligence.";
+ next;
+ goto L_Begin;
+
+L_ChangeDexteritySingle:
+ mes "How much dexterity do you want to have (min: 1 - max: 99)?";
+ input @dex;
+ if (@dex < 1)
+ goto L_StatTooLow;
+ if (@dex > 99)
+ goto L_StatTooHigh;
+ set Dex, @dex;
+ mes "You now have " + Dex + " in dexterity.";
+ next;
+ goto L_Begin;
+
+L_ChangeLuckSingle:
+ mes "How much luck do you want to have (min: 1 - max: 99)?";
+ input @luk;
+ if (@luk < 1)
+ goto L_StatTooLow;
+ if (@luk > 99)
+ goto L_StatTooHigh;
+ set Luk, @luk;
+ mes "You now have " + Luk + " in luck.";
+ next;
+ goto L_Begin;
+
+L_ResetStatusPoints:
+ resetstatus;
+ mes "Stats successfully resetted.";
+ next;
+ goto L_Begin;
+
+L_BasicSkills:
+ set @emote, getskilllv(SKILL_EMOTE);
+ set @trade, getskilllv(SKILL_TRADE);
+ set @party, getskilllv(SKILL_PARTY);
+ menu
+ "Overview of my basic skills.", L_BasicSkillsOverview,
+ "Add basic skills.", L_AddBasicSkills,
+ "Reset basic skills.", L_ResetBasicSkills,
+ "Back to main menu.", L_Begin,
+ "Close.", L_Close;
+
+L_BasicSkillsOverview:
+ mes "Your level in the emote skill is " + @emote + ".";
+ mes "Your level in the trade skill is " + @trade + ".";
+ mes "Your level in the party skill is " + @party + ".";
+ next;
+ goto L_BasicSkills;
+
+L_AddBasicSkills:
+ menu
+ "Emote", L_ChangeEmoteSkill,
+ "Trade.", L_ChangeTradeSkill,
+ "Party.", L_ChangePartySkill,
+ "All basic skills to their maximum level.", L_AllBasicSkills,
+ "Back to the basic skills menu.", L_BasicSkills,
+ "Close.", L_Close;
+
+L_ChangeEmoteSkill:
+ mes "Your level in the emote skill is " + @emote + ". What do you want to do?";
+ menu
+ "Get level 0.", L_Next,
+ "Get level 1.", L_ChangeEmoteSkill1;
+
+L_Next:
+ if (@menu == 1)
+ setskill SKILL_EMOTE, 0;
+ mes "Emote skill changed to level 0.";
+ next;
+ goto L_BasicSkills;
+
+L_ChangeEmoteSkill1:
+ setskill SKILL_EMOTE, 1;
+ mes "Emote skill changed to level 1.";
+ next;
+ goto L_BasicSkills;
+
+L_ChangeTradeSkill:
+ mes "Your level in the trade skill is " + @trade + ". What do you want to do?";
+ menu
+ "Get level 0.", L_Next1,
+ "Get level 1.", L_ChangeTradeSkill1;
+
+L_Next1:
+ if (@menu == 1)
+ setskill SKILL_TRADE, 0;
+ mes "Trade skill changed to level 0.";
+ next;
+ goto L_BasicSkills;
+
+L_ChangeTradeSkill1:
+ setskill SKILL_TRADE, 1;
+ mes "Trade skill changed to level 1.";
+ next;
+ goto L_BasicSkills;
+
+L_ChangePartySkill:
+ mes "Your level in the party skill is " + @trade + ". What do you want to do?";
+ menu
+ "Get level 0.", L_Next2,
+ "Get level 1.", L_ChangePartySkill1,
+ "Get level 2.", L_ChangePartySkill2;
+
+L_Next2:
+ if (@menu == 1)
+ setskill SKILL_PARTY, 0;
+ mes "Party skill changed to level 0.";
+ next;
+ goto L_BasicSkills;
+
+L_ChangePartySkill1:
+ setskill SKILL_PARTY, 1;
+ mes "Party skill changed to level 1.";
+ next;
+ goto L_BasicSkills;
+
+L_ChangePartySkill2:
+ setskill SKILL_PARTY, 2;
+ mes "Party skill changed to level 2.";
+ next;
+ goto L_BasicSkills;
+
+L_AllBasicSkills:
+ setskill SKILL_EMOTE, 1;
+ setskill SKILL_TRADE, 1;
+ setskill SKILL_PARTY, 2;
+ mes "Basic skills added.";
+ next;
+ goto L_BasicSkills;
+
+L_ResetBasicSkills:
+ setskill SKILL_EMOTE, 0;
+ setskill SKILL_TRADE, 0;
+ setskill SKILL_PARTY, 0;
+ mes "Basic skills removed.";
+ next;
+ goto L_BasicSkills;
+
+L_FocusSkills:
+ set @pool, getskilllv(SKILL_POOL);
+ set @mallard, getskilllv(SKILL_MALLARDS_EYE);
+ set @brawling, getskilllv(SKILL_BRAWLING);
+ set @speed, getskilllv(SKILL_SPEED);
+ set @poison, getskilllv(SKILL_RESIST_POISON);
+ set @astralsoul, getskilllv(SKILL_ASTRAL_SOUL);
+ set @raging, getskilllv(SKILL_RAGING);
+ menu
+ "Overview of my focus skills.", L_SeeFocusSkills,
+ "Focus or unfocus.", L_Unfocus,
+ "Add focus skills.", L_ChangeFocusSkills,
+ "Reset focus skills.", L_ResetFocusSkills,
+ "Back to the main menu.", L_Begin,
+ "Close.", L_Close;
+
+L_SeeFocusSkills:
+ cleararray @skilllist_name$[0], "", 8;
+ cleararray @skilllist_id[0], 0, 8;
+ cleararray @skilllist_count[0], 0, 8;
+ getactivatedpoolskilllist;
+ if (@skilllist_count == 0)
+ goto L_NotFocusedMessage;
+ if (@skilllist_count != 0)
+ mes "You are currently focused on the " + @skilllist_name$[@skilllist_count-1] + " skill.";
+ goto L_FocusSkills;
+
+L_NotFocusedMessage:
+ mes "You are not focused on any skill right now.";
+ goto L_FocusSkillsOverview;
+
+L_FocusSkillsOverview:
+ mes "Your focusing skill level is " + @pool + ".";
+ mes "Your mallard's eye skill level is " + @mallard + ".";
+ mes "Your brawling skill level is " + @brawling + ".";
+ mes "Your speed skill level is " + @speed + ".";
+ mes "Your resist poison skill level is " + @poison + ".";
+ mes "Your astral soul skill level is " + @astralsoul + ".";
+ mes "Your raging skill level is " + @raging + ".";
+ next;
+ goto L_FocusSkills;
+
+L_Unfocus:
+ cleararray @skilllist_name$[0], "", 8;
+ cleararray @skilllist_id[0], 0, 8;
+ cleararray @skilllist_count[0], 0, 8;
+ if (getskilllv(SKILL_POOL) == 0)
+ setskill SKILL_POOL, 1;
+ getactivatedpoolskilllist;
+ if (@skilllist_count == 0)
+ goto L_Focus;
+ getactivatedpoolskilllist;
+ if (@skilllist_count != 0)
+ goto L_AskUnfocus;
+ mes "You are not focused on a skill at the moment.";
+ goto L_FocusSkills;
+
+L_Focus:
+ cleararray @skilllist_name$[0], "", 8;
+ cleararray @skilllist_id[0], 0, 8;
+ cleararray @skilllist_count[0], 0, 8;
+ getunactivatedpoolskilllist;
+ if (@skilllist_count == 0)
+ goto L_NoFocusSkills;
+ set @skilllist_id[@skilllist_count], 0;
+ set @skilllist_name$[@skilllist_count], "Back to the focus skills menu.";
+ mes "You are not focused on any focus skill right now. Which one do you want to focus on?";
+ menu
+ @skilllist_name$[0], L_MenuItems,
+ @skilllist_name$[1], L_MenuItems,
+ @skilllist_name$[2], L_MenuItems,
+ @skilllist_name$[3], L_MenuItems,
+ @skilllist_name$[4], L_MenuItems,
+ @skilllist_name$[5], L_MenuItems,
+ @skilllist_name$[6], L_MenuItems,
+ @skilllist_name$[7], L_MenuItems;
+
+L_MenuItems:
+ set @menu, @menu - 1;
+ poolskill @skilllist_id[@menu];
+ goto L_FocusSkills;
+
+L_NoFocusSkills:
+ mes "You have no skills to focus on or unfocus from.";
+ goto L_FocusSkills;
+
+L_AskUnfocus:
+ mes "Unfocus " + @skilllist_name$[@skilllist_count-1] + "?";
+ menu
+ "Yes.", L_Next3,
+ "No.", L_FocusSkills;
+
+L_Next3:
+ unpoolskill @skilllist_id[@skilllist_count-1];
+ goto L_FocusSkills;
+
+L_ChangeFocusSkills:
+ menu
+ "Focusing.", L_ChangeFocusingSkill,
+ "Mallard's Eye.", L_ChangeMallardsEyeSkill,
+ "Brawling.", L_ChangeBrawlingSkill,
+ "Speed.", L_ChangeSpeedSkill,
+ "Resist Poison.", L_ChangeResistPoisonSkill,
+ "Astral Soul.", L_ChangeAstralSoulSkill,
+ "Raging.", L_ChangeRagingSkill,
+ "All focus skills to their maximum level.", L_AllFocusSkills,
+ "Back to the focus skills menu.", L_FocusSkills,
+ "Close.", L_Close;
+
+L_BadSkillLevel:
+ mes "Invalid skill level.";
+ next;
+ goto L_ChangeFocusSkills;
+
+L_ChangeFocusingSkill:
+ mes "Enter the level you want to be in this skill (min: 0 - max: 1).";
+ input @lvl;
+ if (@lvl > 1)
+ goto L_BadSkillLevel;
+ setskill SKILL_POOL, @lvl;
+ next;
+ goto L_FocusSkills;
+
+L_ChangeMallardsEyeSkill:
+ mes "Enter the level you want to be in this skill (min: 0 - max: 9).";
+ input @lvl;
+ if (@lvl > 9)
+ goto L_BadSkillLevel;
+ setskill SKILL_MALLARDS_EYE, @lvl;
+ next;
+ goto L_FocusSkills;
+
+L_ChangeBrawlingSkill:
+ mes "Enter the lvl you want to be in this skill (min: 0 - max: 9).";
+ input @lvl;
+ if (@lvl > 9)
+ goto L_BadSkillLevel;
+ setskill SKILL_BRAWLING, @lvl;
+ next;
+ goto L_FocusSkills;
+
+L_ChangeSpeedSkill:
+ mes "Enter the lvl you want to be in this skill (min: 0 - max: 9).";
+ input @lvl;
+ if (@lvl > 9)
+ goto L_BadSkillLevel;
+ setskill SKILL_SPEED, @lvl;
+ next;
+ goto L_FocusSkills;
+
+L_ChangeResistPoisonSkill:
+ mes "Enter the lvl you want to be in this skill (min: 0 - max: 9).";
+ input @lvl;
+ if (@lvl > 9)
+ goto L_BadSkillLevel;
+ setskill SKILL_RESIST_POISON, @lvl;
+ next;
+ goto L_FocusSkills;
+
+L_ChangeAstralSoulSkill:
+ mes "Enter the lvl you want to be in this skill (min: 0 - max: 9).";
+ input @lvl;
+ if (@lvl > 9)
+ goto L_BadSkillLevel;
+ setskill SKILL_ASTRAL_SOUL, @lvl;
+ next;
+ goto L_FocusSkills;
+
+L_ChangeRagingSkill:
+ mes "Enter the lvl you want to be in this skill (min: 0 - max: 9).";
+ input @lvl;
+ if (@lvl > 9)
+ goto L_BadSkillLevel;
+ setskill SKILL_RAGING, @lvl;
+ next;
+ goto L_FocusSkills;
+
+L_AllFocusSkills:
+ setskill SKILL_POOL, 1;
+ setskill SKILL_MALLARDS_EYE, 9;
+ setskill SKILL_BRAWLING, 9;
+ setskill SKILL_SPEED, 9;
+ setskill SKILL_RESIST_POISON, 9;
+ setskill SKILL_ASTRAL_SOUL, 9;
+ setskill SKILL_RAGING, 9;
+ mes "Focus skills added.";
+ next;
+ goto L_FocusSkills;
+
+L_ResetFocusSkills:
+ setskill SKILL_POOL, 0;
+ setskill SKILL_MALLARDS_EYE, 0;
+ setskill SKILL_BRAWLING, 0;
+ setskill SKILL_SPEED, 0;
+ setskill SKILL_RESIST_POISON, 0;
+ setskill SKILL_ASTRAL_SOUL, 0;
+ setskill SKILL_RAGING, 0;
+ mes "Focus skills removed.";
+ next;
+ goto L_FocusSkills;
+
+L_MagicSkills:
+ set @general, getskilllv(SKILL_MAGIC);
+ set @life, getskilllv(SKILL_MAGIC_LIFE);
+ set @war, getskilllv(SKILL_MAGIC_WAR);
+ set @trans, getskilllv(SKILL_MAGIC_TRANSMUTE);
+ set @nature, getskilllv(SKILL_MAGIC_NATURE);
+ set @astral, getskilllv(SKILL_MAGIC_ASTRAL);
+ set @dark, getskilllv(SKILL_MAGIC_DARK);
+ menu
+ "Overview of my magical skills.", L_MagicSkillsOverview,
+ "Get magic skills.", L_ChangeMagicSkills,
+ "Get magic experience.", L_MagicExperience,
+ "All magic skills to their maximum level and maximum magic experience.", L_GetAllMagic,
+ "Reset magic skills and experience.", L_ResetMagicSkills,
+ "Back to the main menu.", L_Begin,
+ "Close.", L_Close;
+
+L_MagicSkillsOverview:
+ mes "Your current magic experience skill is " + @mexp + ".";
+ mes "Your level in the general magic skill is " + @general + ".";
+ mes "Your level in the life magic skill is " + @life + ".";
+ mes "Your level in the war magic skill is " + @war + ".";
+ mes "Your level in the transmutation magic skill is " + @trans + ".";
+ mes "Your level in the nature magic skill is " + @nature + ".";
+ mes "Your level in the astral magic skill is " + @astral + ".";
+ mes "Your level in the dark magic skill is " + @dark + ".";
+ next;
+ goto L_MagicSkills;
+
+L_MagicExperience:
+ mes "Your current magic experience is " + @mexp + ".";
+ if (@general == 0
+ && @life == 0
+ && @war == 0
+ && @trans == 0
+ && @nature == 0
+ && @astral == 0
+ && @dark == 0)
+ goto L_NoMagicSkills;
+
+ goto L_ChangeMagicExperience;
+
+L_NoMagicSkills:
+ mes "You can't have magic experience, since you have no magic skills yet.";
+ goto L_MagicSkills;
+
+L_ChangeMagicExperience:
+ mes "Set the desired magic experience (min: 0 - max: 8000).";
+ input @value;
+ if (@value < 0 || @value > 8000)
+ goto L_WrongMagicExperience;
+ set @mexp, @value;
+ callsub S_Update_Mask;
+ mes "You now have " + @mexp + " magic experience points.";
+ goto L_MagicSkills;
+
+L_WrongMagicExperience:
+ mes "Wrong value informed. Aborting.";
+ goto L_MagicSkills;
+
+L_ChangeMagicSkills:
+ menu
+ "General Magic.", L_ChangeGeneralMagicSkill,
+ "Life Magic.", L_ChangeLifeMagicSkill,
+ "War Magic.", L_ChangeWarMagicSkill,
+ "Transmutation Magic.", L_ChangeTransmutationMagicSkill,
+ "Nature Magic.", L_ChangeNatureMagicSkill,
+ "Astral Magic.", L_ChangeAstralMagicSkill,
+ "Dark Magic.", L_ChangeDarkMagicSkill,
+ "Back to the magic skills menu.", L_MagicSkills,
+ "Close.", L_Close;
+
+L_ChangeGeneralMagicSkill:
+ mes "Your level in the general magic skill is " + @general + ". What do you want to do?";
+ menu
+ "Get level 0.", L_Next4,
+ "Get level 1.", L_ChangeGeneralMagicSkill1,
+ "Get level 2.", L_ChangeGeneralMagicSkill2;
+
+L_Next4:
+ if (@menu == 1)
+ setskill SKILL_MAGIC, 0;
+ mes "General Magic skill changed to level 0.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeGeneralMagicSkill1:
+ setskill SKILL_MAGIC, 1;
+ mes "General Magic skill changed to level 1.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeGeneralMagicSkill2:
+ setskill SKILL_MAGIC, 2;
+ if (@mexp < 100)
+ set @mexp, 100;
+ callsub S_Update_Mask;
+ mes "General Magic skill changed to level 2.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeLifeMagicSkill:
+ mes "Your level in the life magic skill is " + @life + ". What do you want to do?";
+ menu
+ "Get level 0.", L_Next5,
+ "Get level 1.", L_ChangeLifeMagicSkill1,
+ "Get level 2.", L_ChangeLifeMagicSkill2;
+
+L_Next5:
+ if (@menu == 1)
+ setskill SKILL_MAGIC_LIFE, 0;
+ mes "Life Magic skill changed to level 0.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeLifeMagicSkill1:
+ setskill SKILL_MAGIC_LIFE, 1;
+ mes "Life Magic skill changed to level 1.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeLifeMagicSkill2:
+ setskill SKILL_MAGIC_LIFE, 2;
+ if (@mexp < 100)
+ set @mexp, 100;
+ callsub S_Update_Mask;
+ mes "Life Magic skill changed to level 2.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeWarMagicSkill:
+ mes "Your level in the war magic skill is " + @war + ". What do you want to do?";
+ menu
+ "Get level 0.", L_Next6,
+ "Get level 1.", L_ChangeWarMagicSkill1,
+ "Get level 2.", L_ChangeWarMagicSkill2;
+
+L_Next6:
+ if (@menu == 1)
+ setskill SKILL_MAGIC_WAR, 0;
+ mes "War Magic skill changed to level 0.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeWarMagicSkill1:
+ setskill SKILL_MAGIC_WAR, 1;
+ mes "War Magic skill changed to level 1.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeWarMagicSkill2:
+ setskill SKILL_MAGIC_WAR, 2;
+ if (@mexp < 100)
+ set @mexp, 100;
+ callsub S_Update_Mask;
+ mes "War Magic skill changed to level 2.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeTransmutationMagicSkill:
+ mes "Your level in the transmutation magic skill is " + @trans + ". What do you want to do?";
+ menu
+ "Get level 0.", L_Next7,
+ "Get level 1.", L_ChangeTransmutationMagicSkill1,
+ "Get level 2.", L_ChangeTransmutationMagicSkill2;
+
+L_Next7:
+ if (@menu == 1)
+ setskill SKILL_MAGIC_TRANSMUTE, 0;
+ mes "Transmutation Magic skill changed to level 0.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeTransmutationMagicSkill1:
+ setskill SKILL_MAGIC_TRANSMUTE, 1;
+ mes "Transmutation Magic skill changed to level 1.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeTransmutationMagicSkill2:
+ setskill SKILL_MAGIC_TRANSMUTE, 2;
+ if (@mexp < 100)
+ set @mexp, 100;
+ callsub S_Update_Mask;
+ mes "Transmutation Magic skill changed to level 2.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeNatureMagicSkill:
+ mes "Your level in the nature magic skill is " + @nature + ". What do you want to do?";
+ menu
+ "Get level 0.", L_Next8,
+ "Get level 1.", L_ChangeNatureMagicSkill1,
+ "Get level 2.", L_ChangeNatureMagicSkill2;
+
+L_Next8:
+ if (@menu == 1)
+ setskill SKILL_MAGIC_NATURE, 0;
+ mes "Nature Magic skill changed to level 0.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeNatureMagicSkill1:
+ setskill SKILL_MAGIC_NATURE, 1;
+ mes "Nature Magic skill changed to level 1.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeNatureMagicSkill2:
+ setskill SKILL_MAGIC_NATURE, 2;
+ if (@mexp < 100)
+ set @mexp, 100;
+ callsub S_Update_Mask;
+ mes "Nature Magic skill changed to level 2.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeAstralMagicSkill:
+ mes "Your level in the astral magic skill is " + @astral + ". What do you want to do?";
+ menu
+ "Get level 0.", L_Next9,
+ "Get level 1.", L_ChangeAstralMagicSkill1,
+ "Get level 2.", L_ChangeAstralMagicSkill2;
+
+L_Next9:
+ if (@menu == 1)
+ setskill SKILL_MAGIC_ASTAL, 0;
+ mes "Astral Magic skill changed to level 0.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeAstralMagicSkill1:
+ setskill SKILL_MAGIC_ASTRAL, 1;
+ mes "Astral Magic skill changed to level 1.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeAstralMagicSkill2:
+ setskill SKILL_MAGIC_ASTRAL, 2;
+ if (@mexp < 100)
+ set @mexp, 100;
+ callsub S_Update_Mask;
+ mes "Astral Magic skill changed to level 2.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeDarkMagicSkill:
+ mes "Your level in the dark magic skill is " + @dark + ". What do you want to do?";
+ menu
+ "Get level 0.", L_Next10,
+ "Get level 1.", L_ChangeDarkMagicSkill1,
+ "Get level 2.", L_ChangeDarkMagicSkill2;
+
+L_Next10:
+ if (@menu == 1)
+ setskill SKILL_MAGIC_DARK, 0;
+ mes "Dark Magic skill changed to level 0.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeDarkMagicSkill1:
+ setskill SKILL_MAGIC_DARK, 1;
+ mes "Dark Magic skill changed to level 1.";
+ next;
+ goto L_MagicSkills;
+
+L_ChangeDarkMagicSkill2:
+ setskill SKILL_MAGIC_DARK, 2;
+ if (@mexp < 100)
+ set @mexp, 100;
+ callsub S_Update_Mask;
+ mes "Dark Magic skill changed to level 2.";
+ next;
+ goto L_MagicSkills;
+
+S_Update_Mask:
+ set MAGIC_EXPERIENCE,
+ (MAGIC_EXPERIENCE & ~(@debug_mask))
+ | (@mexp << @debug_shift);
+ return;
+
+L_GetAllMagic:
+ setskill SKILL_MAGIC, 5;
+ setskill SKILL_MAGIC_LIFE, 5;
+ setskill SKILL_MAGIC_WAR, 5;
+ setskill SKILL_MAGIC_TRANSMUTE, 5;
+ setskill SKILL_MAGIC_NATURE, 5;
+ setskill SKILL_MAGIC_ASTRAL, 5;
+ setskill SKILL_MAGIC_DARK, 5;
+ set @mexp, 8000;
+ callsub S_Update_Mask;
+ mes "Magic skills added.";
+ next;
+ goto L_MagicSkills;
+
+L_ResetMagicSkills:
+ setskill SKILL_MAGIC, 0;
+ setskill SKILL_MAGIC_LIFE, 0;
+ setskill SKILL_MAGIC_WAR, 0;
+ setskill SKILL_MAGIC_TRANSMUTE, 0;
+ setskill SKILL_MAGIC_NATURE, 0;
+ setskill SKILL_MAGIC_ASTRAL, 0;
+ setskill SKILL_MAGIC_DARK, 0;
+ set @mexp, 0;
+ callsub S_Update_Mask;
+ mes "Magic skills removed.";
+ next;
+ goto L_MagicSkills;
+
+L_AddAll:
+ setskill SKILL_EMOTE, 1;
+ setskill SKILL_TRADE, 1;
+ setskill SKILL_PARTY, 2;
+ setskill SKILL_POOL, 1;
+ setskill SKILL_MALLARDS_EYE, 9;
+ setskill SKILL_BRAWLING, 9;
+ setskill SKILL_SPEED, 9;
+ setskill SKILL_RESIST_POISON, 9;
+ setskill SKILL_ASTRAL_SOUL, 9;
+ setskill SKILL_RAGING, 9;
+ setskill SKILL_MAGIC, 5;
+ setskill SKILL_MAGIC_LIFE, 5;
+ setskill SKILL_MAGIC_WAR, 5;
+ setskill SKILL_MAGIC_TRANSMUTE, 5;
+ setskill SKILL_MAGIC_NATURE, 5;
+ setskill SKILL_MAGIC_ASTRAL, 5;
+ setskill SKILL_MAGIC_DARK, 5;
+ set @mexp, 8000;
+ resetstatus;
+ set BaseLevel, 99;
+ mes "All skills added to their maximum level.";
+ mes "Maximum number of Magic Experience points.";
+ mes "You are now level " + BaseLevel + ".";
+ next;
+ goto L_Begin;
+
+L_ResetAll:
+ cleararray @skilllist_name$[0], "", 8;
+ cleararray @skilllist_id[0], 0, 8;
+ cleararray @skilllist_count[0], 0, 8;
+ setskill SKILL_EMOTE, 0;
+ setskill SKILL_TRADE, 0;
+ setskill SKILL_PARTY, 0;
+ setskill SKILL_POOL, 0;
+ setskill SKILL_MALLARDS_EYE, 0;
+ setskill SKILL_BRAWLING, 0;
+ setskill SKILL_SPEED, 0;
+ setskill SKILL_RESIST_POISON, 0;
+ setskill SKILL_ASTRAL_SOUL, 0;
+ setskill SKILL_RAGING, 0;
+ setskill SKILL_MAGIC, 0;
+ setskill SKILL_MAGIC_LIFE, 0;
+ setskill SKILL_MAGIC_WAR, 0;
+ setskill SKILL_MAGIC_TRANSMUTE, 0;
+ setskill SKILL_MAGIC_NATURE, 0;
+ setskill SKILL_MAGIC_ASTRAL, 0;
+ setskill SKILL_MAGIC_DARK, 0;
+ set @mexp, 0;
+ callsub S_Update_Mask;
+ resetstatus;
+ set BaseLevel, 1;
+ mes "All skills removed.";
+ mes "Minimum number of Magic Experience points.";
+ mes "You are now level " + BaseLevel + ".";
+ next;
+ goto L_Begin;
+
+L_Close:
+ close2;
+ return;
+
+}
+
+-|script|Debug Spell|32767
+{
+ if(!debug && getgmlevel() < CMD_DEBUG) end;
+ callfunc "Debug";
+ end;
+OnDeprecated:
+ message strcharinfo(0), "Debug : ##3The #debug spell has been superseded by the ##B@debug##b command.";
+ end;
+OnInit:
+ registercmd "@debug", "Debug Spell";
+ registercmd "#debug", "Debug Spell::OnDeprecated";
+ end;
+}
+
+029-2,30,26,0|script|Debug#0|154
+{
+ set @debug_npc, 1;
+ callfunc "Debug";
+ end;
+OnInit:
+ if (!debug)
+ disablenpc "Debug#0";
+ end;
+}
+
+001-1,53,47,0|script|Debug#1|154
+{
+ set @debug_npc, 1;
+ callfunc "Debug";
+ end;
+OnInit:
+ if (!debug)
+ disablenpc "Debug#1";
+ end;
+}
+
+009-1,45,33,0|script|Debug#2|154
+{
+ set @debug_npc, 1;
+ callfunc "Debug";
+ end;
+OnInit:
+ if (!debug)
+ disablenpc "Debug#2";
+ end;
+}
+
+020-1,75,85,0|script|Debug#3|154
+{
+ set @debug_npc, 1;
+ callfunc "Debug";
+ end;
+OnInit:
+ if (!debug)
+ disablenpc "Debug#3";
+ end;
+}
+
+027-2,125,103,0|script|Debug#5|154
+{
+ set @debug_npc, 1;
+ callfunc "Debug";
+ end;
+OnInit:
+ if (!debug)
+ disablenpc "Debug#5";
+ end;
+}
diff --git a/world/map/npc/commands/destroynpc.txt b/world/map/npc/commands/destroynpc.txt
new file mode 100644
index 00000000..1ebede9e
--- /dev/null
+++ b/world/map/npc/commands/destroynpc.txt
@@ -0,0 +1,35 @@
+-|script|@destroynpc|32767
+{
+ callfunc "argv_splitter";
+ if (GM < CMD_DESTROYNPC && GM < G_SYSOP)
+ goto L_GM;
+
+ set .@id, getnpcid(@argv$[0]);
+ if (@argv$[0] == "" || .@id < 1)
+ goto L_Failed;
+ if (gettimetick(2) - @destroynpc[0] > 300 || @destroynpc[1] != .@id)
+ goto L_Confirm;
+
+ gmlog "@destroynpc " + @args$;
+ message strcharinfo(0), "destroynpc : The operation succeeded.";
+ debugmes "!!! => npc destroyed: `"+@argv$[0]+"` ("+.@id+")";
+ if (1==1) destroy .@id; // FIXME: allow destroy to work as a non-terminator when arg0 is given (TMWA)
+ end;
+
+L_Confirm:
+ message strcharinfo(0), "destroynpc : ##BDANGER ZONE!##b This command permanently destroys a npc and its puppets (if any). Use the command again to confirm.";
+ setarray @destroynpc[0], gettimetick(2), .@id;
+ end;
+
+L_Failed:
+ message strcharinfo(0), "destroynpc : Impossible to find the target npc. Did you try putting the name in \"quotation marks\"? Some npcs also have an invisible postfix in their name, ie `#_M`.";
+ end;
+
+L_GM:
+ message strcharinfo(0), "destroynpc : GM command is level "+ CMD_DESTROYNPC +", but you are level " + GM;
+ end;
+
+OnInit:
+ registercmd chr(ATCMD_SYMBOL) + "destroynpc", strnpcinfo(0);
+ end;
+}
diff --git a/world/map/npc/commands/marry.txt b/world/map/npc/commands/marry.txt
new file mode 100644
index 00000000..39efe6b8
--- /dev/null
+++ b/world/map/npc/commands/marry.txt
@@ -0,0 +1,69 @@
+-|script|special-marry|32767
+{
+ set .@target_id, getcharid(3, @args$);
+ if (.@target_id < 1 || !(isloggedin(.@target_id)) || .@target_id == BL_ID) goto L_NotFound;
+ if (PARTNER || get(PARTNER, .@target_id)) goto L_AlreadyMarried;
+ if (isin("014-1",29,36,34,39) == 0 && isin("001-1",20,27,22,27) == 0) goto L_NotInArea;
+ if (distance(BL_ID, .@target_id) != 1) goto L_AwayFromPartner;
+ if (BaseLevel < WEDDING_MIN_LEVEL || get(BaseLevel, .@target_id) < WEDDING_MIN_LEVEL) goto L_TooYoung;
+ if (getequipid(equip_shield) != 702 || getequipid(equip_shield, @args$) != 702) goto L_NoRing;
+
+ if (get(@marriage[0], .@target_id) == BL_ID) goto L_Proceed;
+
+ setarray @marriage[0], .@target_id, gettimetick(2);
+ addtimer (.timeout * 1000), strnpcinfo(0) + "::OnTimeout";
+ announce strcharinfo(0) + " is asking " + strcharinfo(0, .@target_id) + " for marriage.", 2;
+ message strcharinfo(0, .@target_id), "Marriage : ##3##B" + strcharinfo(0) + " wishes to marry you. To accept, write `##1#marry "+strcharinfo(0)+"##3` within the next "+.timeout+" seconds.";
+ end;
+
+L_NotFound:
+ message strcharinfo(0), "Marriage : ##3##BThe target player is either not found or yourself.";
+ end;
+
+L_TooYoung:
+ message strcharinfo(0), "Marriage : ##3##BYou and your partner need to be at least level "+ WEDDING_MIN_LEVEL +".";
+ end;
+
+L_NoRing:
+ message strcharinfo(0), "Marriage : ##3##BYou and your partner need to have ["+ getitemlink("WeddingRing") +"] equipped.";
+ end;
+
+L_AwayFromPartner:
+ message strcharinfo(0), "Marriage : ##3##BYou and your partner need to be standing next to each other.";
+ end;
+
+L_NotInArea:
+ message strcharinfo(0), "Marriage : ##3##BYou are not standing in a designated marriage area.";
+ end;
+
+L_Proceed:
+ if ((gettimetick(2) - .timeout) > get(@marriage[1], .@target_id)) goto L_TooLate;
+ set PARTNER, CHAR_ID, .@target_id;
+ if (PARTNER == get(CHAR_ID, .@target_id)) goto L_Success;
+ set PARTNER, 0, .@target_id;
+ set PARTNER, 0;
+ end;
+
+L_Success:
+ announce strcharinfo(0) + " and " + strcharinfo(0, .@target_id) + " are now married.", 2;
+ end;
+
+OnTimeout:
+ goto L_TooLate;
+
+L_TooLate:
+ message strcharinfo(0), "Marriage : ##3##BThe proposal expired. Please try again.";
+ message strcharinfo(0, @marriage[0]), "Marriage : ##3##BThe proposal expired. Please try again.";
+ set @marriage[0], 0, @marriage[0];
+ set @marriage[0], 0;
+ end;
+
+L_AlreadyMarried:
+ message strcharinfo(0), "Marriage : ##3##BYou"+ if_then_else(PARTNER, " are", "r partner is") +" already married.";
+ end;
+
+OnInit:
+ set .timeout, 30; // timeout for proposal
+ registercmd "#marry", strnpcinfo(0); // we NEED to use a # before `marry` because otherwise manaplus does not strip colors
+ end;
+}
diff --git a/world/map/npc/commands/numa.txt b/world/map/npc/commands/numa.txt
new file mode 100644
index 00000000..e8e8cabd
--- /dev/null
+++ b/world/map/npc/commands/numa.txt
@@ -0,0 +1,132 @@
+// all-in-one debug
+// author: meko
+
+-|script|SuperDebug|32767
+{
+ if (GM < MAP_LOUNGE && GM < G_SYSOP && !debug) goto L_GM2; // make sure you can enter the gm lounge
+ if (target(BL_ID,getnpcid("Numa"),1)) goto L_Main;
+ npcaction 6, 12;
+ title "Numa";
+ goto L_Main;
+
+L_GM2:
+ message strcharinfo(0), "numa : GM command is level "+ MAP_LOUNGE +", but you are level " + GM;
+ end;
+
+L_Main:
+ mes "How may I help you?";
+ next;
+ menu
+ "Announcements", L_StoneBoard,
+ "MOTD", L_MOTD,
+ "Holiday debug", L_Holiday,
+ "Event debug", L_Event,
+ "Quest debug", L_Quest,
+ "Who are you?", L_WhoAmI,
+ "Close", L_Close;
+ // todo: generic npcs
+ // todo: map list
+
+L_WhoAmI:
+ mes "I am Numa, also known as `SuperDebug`.";
+ mes "My sole purpose is to assist TMW staff from behind-the-scene.";
+ mes "Using me, you can access several debug menus.";
+ mes "You can call me from anywhere using the ##B@numa##b spell, or you can come see me in person.";
+ next;
+ goto L_Main;
+
+L_Holiday:
+ if (GM < DBG_HOLIDAY && GM < G_SYSOP) goto L_GM;
+ mes "What holiday do you want to debug?";
+ next;
+ menu
+ "Xmas.", L_XmasDebug,
+ "Halloween.", L_HalloweenDebug,
+ "Easter.", L_EasterDebug;
+
+L_XmasDebug:
+ gmlog strcharinfo(0) + " accessed the Xmas debug.";
+ callfunc "XmasDebug";
+ goto L_Close;
+
+L_HalloweenDebug:
+ gmlog strcharinfo(0) + " accessed the Halloween debug.";
+ callfunc "HalloweenDebug";
+ goto L_Close;
+
+L_EasterDebug:
+ gmlog strcharinfo(0) + " accessed the Easter debug.";
+ callfunc "Easter Debug";
+ goto L_Close;
+
+L_Event:
+ if (GM < EVT_DEBUG && GM < G_EVENT) goto L_GM;
+ gmlog strcharinfo(0) + " accessed the GM event debug.";
+ callfunc "GmDebug";
+ goto L_Close;
+
+L_StoneBoard:
+ if (GM < DBG_SCHEDULED && GM < G_SYSOP) goto L_GM;
+ callfunc "SBConfig";
+ goto L_Close;
+
+L_MOTD:
+ if (GM < DBG_MOTD && GM < G_SYSOP) goto L_GM;
+ callfunc "MOTDConfig";
+ goto L_Close;
+
+L_GM:
+ mes "I'm awfully sorry.";
+ mes "You do not have the required GM level to perform this action.";
+ goto L_Close;
+
+L_Quest:
+ callfunc "QuestDebug";
+ goto L_Close;
+
+L_Close:
+ close;
+
+OnInit:
+ registercmd chr(ATCMD_SYMBOL) + "numa", strnpcinfo(0);
+ registercmd chr(ATCMD_SYMBOL) + "superdebug", strnpcinfo(0);
+ void puppet("017-9", 30, 28, "Numa", 393);
+ end;
+}
+
+function|script|QuestDebug
+{
+ goto L_ChooseContinent;
+
+L_ChooseContinent:
+ mes "Choose a continent.";
+ next;
+ menu
+ "Argeas", L_Argeas,
+ "Close", L_Return;
+
+L_Argeas:
+ mes "Choose an area.";
+ next;
+ menu
+ "Woodland", L_Woodland,
+ "Choose a continent", L_ChooseContinent,
+ "Close", L_Return;
+
+L_Woodland:
+ mes "Choose a quest.";
+ next;
+ menu
+ "Illia Sisters", L_Valia,
+ "Choose an area", L_Argeas,
+ "Close", L_Return;
+
+L_Return:
+ return;
+
+//////////////////////////////
+
+L_Valia:
+ callfunc "IlliaDebug";
+ goto L_Return;
+}
diff --git a/world/map/npc/commands/pullrabbit.txt b/world/map/npc/commands/pullrabbit.txt
new file mode 100644
index 00000000..022f3753
--- /dev/null
+++ b/world/map/npc/commands/pullrabbit.txt
@@ -0,0 +1,25 @@
+-|script|@pullrabbit|32767
+{
+ if (GM < EVT_KILLTHEGM && GM < G_SYSOP) end;
+ if (getequipid(equip_head) != 888) end;
+ getinventorylist;
+ if ((checkweight("MurdererCrown", 1) == 0) || (@inventorylist_count == 100))
+ goto L_Inventory;
+ // Get the current reward of the event. This may be changed later
+ getitem "MurdererCrown", 1;
+ // Set HP and SP to max
+ heal MaxHp, MaxSp;
+ // Display an effect
+ misceffect FX_CHANNELLING_CAST, strcharinfo(0);
+ // Log the usage of this spell
+ gmlog strcharinfo(0)+" used the Magic GM Top Hat.";
+ end;
+
+L_Inventory:
+ message strcharinfo(0), "You cannot create this item. You're too heavy or you don't have a free slot.";
+ end;
+
+OnInit:
+ registercmd chr(ATCMD_SYMBOL) + "pullrabbit", strnpcinfo(0);
+ end;
+}
diff --git a/world/map/npc/commands/remotecmd.txt b/world/map/npc/commands/remotecmd.txt
new file mode 100644
index 00000000..b8c47f35
--- /dev/null
+++ b/world/map/npc/commands/remotecmd.txt
@@ -0,0 +1,62 @@
+-|script|@remotecmd|32767
+{
+ callfunc "argv_splitter";
+ if (GM < CMD_REMOTECMD && GM < G_SYSOP) goto L_GM; // check if you can use it on self
+ set .@target_id, BL_ID;
+ set .@t$, @argv$[1];
+ setarray @remotecmd[0], 0, 1, 1; // nr, to_self, multi_target
+ if (.@t$ == "map") goto L_Map;
+ if (.@t$ == "map!") goto L_AllMap;
+ if (.@t$ == "area") goto L_Area;
+ if (.@t$ == "area!") goto L_AllArea;
+ if (.@t$ != "") set .@target_id, getcharid(3, @argv$[1]);
+ if (.@t$ != "" && !(isloggedin(.@target_id))) goto L_Failed; // do NOT fallback to self
+
+ set @target_id, .@target_id;
+ set @remotecmd[2], 0; // only one target
+ addtimer 0, strnpcinfo(0) + "::OnPC";
+ end;
+
+L_Map:
+ set @remotecmd[1], 0; // do not include self
+ goto L_AllMap;
+
+L_AllMap:
+ foreach 0, getmap(), 0, 0, 32767, 32767, strnpcinfo(0)+"::OnPC";
+ goto L_Success;
+
+L_Area:
+ set @remotecmd[1], 0; // do not include self
+ goto L_AllMap;
+
+L_AllArea:
+ foreach 0, getmap(), (POS_X - .range), (POS_Y - .range), (POS_X + .range), (POS_Y + .range), strnpcinfo(0)+"::OnPC";
+ goto L_Success;
+
+OnPC:
+ if (@target_id == BL_ID && @remotecmd[1] < 1)
+ end;
+ remotecmd @argv$[0], strcharinfo(0, @target_id);
+ set @remotecmd[0], @remotecmd[0] + 1;
+ if (@remotecmd[2] < 1)
+ goto L_Success;
+ end;
+
+L_Success:
+ gmlog "@remotecmd " + @args$;
+ message strcharinfo(0), "remotecmd : The operation succeeded. ["+ @remotecmd[0] + "]";
+ end;
+
+L_Failed:
+ message strcharinfo(0), "remotecmd : Impossible to attach to the target player. Did you try putting the name in \"quotation marks\"?";
+ end;
+
+L_GM:
+ message strcharinfo(0), "remotecmd : GM command is level "+ CMD_REMOTECMD +", but you are level " + GM;
+ end;
+
+OnInit:
+ set .range, 14; // visible range
+ registercmd chr(ATCMD_SYMBOL) + "remotecmd", strnpcinfo(0);
+ end;
+}
diff --git a/world/map/npc/commands/zeny.txt b/world/map/npc/commands/zeny.txt
new file mode 100644
index 00000000..513330b5
--- /dev/null
+++ b/world/map/npc/commands/zeny.txt
@@ -0,0 +1,79 @@
+-|script|@zeny|32767
+{
+ callfunc "argv_splitter";
+ set .@n$, if_then_else(@argv$[1] != "", "char", "") + "zeny";
+ if (GM < CMD_ZENY && GM < G_SYSOP) goto L_GM; // check if you can use it on self
+ set .@target_id, BL_ID;
+ if (@argv$[1] != "") set .@target_id, getcharid(3, @argv$[1]);
+ if (@argv$[1] != "" && !(isloggedin(.@target_id))) goto L_Failed; // do NOT fallback to self
+ if (@argv$[1] != "" && GM < CMD_CHARZENY && GM < G_SYSOP) goto L_GM; // when target is not self, use charzeny permission
+ if (@argv$[0] == "--") goto L_Remove;
+ if (@argv$[0] == "---") goto L_RemoveAll;
+ if (@argv$[0] == "++") goto L_Max;
+ if (@argv$[0] == "+++") goto L_MaxAll;
+ set .@delta, @argv[0]; // ± zeny
+ set .@zeny, get(Zeny, .@target_id); // get the number of zeny in char
+ set .@bank, get(#BankAccount, .@target_id); // get number of zeny in (world) account
+ set .@new_zeny, .@zeny + .@delta; // new balance in char
+ if (.@new_zeny < 0) goto L_MaybeRemoveBank; // zeny would be below 0 so check if we can take from bank
+ if (.@new_zeny > .max_zeny) goto L_MaybeAddBank; // zeny would be over the limit so check if we can store in bank
+ set Zeny, (.@zeny + .@delta), .@target_id;
+ goto L_Success;
+
+L_Remove:
+ set Zeny, 0, .@target_id;
+ goto L_Success;
+
+L_RemoveAll:
+ set Zeny, 0, .@target_id;
+ set #BankAccount, 0, .@target_id;
+ goto L_Success;
+
+L_Max:
+ set Zeny, .max_zeny, .@target_id;
+ goto L_Success;
+
+L_MaxAll:
+ set Zeny, .max_zeny, .@target_id;
+ set #BankAccount, .max_int, .@target_id;
+ goto L_Success;
+
+L_MaybeAddBank:
+ set .@new_bank, (.@bank + (.@new_zeny - .max_zeny));
+ if (.@new_bank > .max_int || .@new_bank < 0) goto L_OutOfBounds;
+ set Zeny, .max_zeny, .@target_id;
+ set #BankAccount, .@new_bank, .@target_id;
+ goto L_Success;
+
+L_MaybeRemoveBank:
+ if ((.@bank + .@new_zeny) < 0) goto L_OutOfBounds;
+ set Zeny, 0, .@target_id;
+ set #BankAccount, (.@bank + .@new_zeny), .@target_id;
+ goto L_Success;
+
+L_OutOfBounds:
+ // XXX: maybe we could also take from other chars from the same accout?
+ message strcharinfo(0), .@n$+" : Impossible to proceed! This would cause the player to have less than 0 zeny or more than " + .max_int + ".";
+ end;
+
+L_Failed:
+ // XXX: should we allow GMs to change zeny of users that are not logged in?
+ message strcharinfo(0), .@n$+" : Impossible to attach to the target player. Did you try putting the name in \"quotation marks\"?";
+ end;
+
+L_Success:
+ gmlog "@zeny " + @args$;
+ message strcharinfo(0), .@n$+" : The operation succeeded.";
+ end;
+
+L_GM:
+ message strcharinfo(0), .@n$+" : GM command is level "+ if_then_else(@argv$[1] != "", CMD_CHARZENY, CMD_ZENY) +", but you are level " + GM;
+ end;
+
+OnInit:
+ set .max_zeny, 1000000000; // hardcoded in tmwa
+ set .max_int, 2147483647; // max int32 value
+ registercmd chr(ATCMD_SYMBOL) + "zeny", strnpcinfo(0);
+ registercmd chr(ATCMD_SYMBOL) + "charzeny", strnpcinfo(0);
+ end;
+}