//===== eAthena Script ======================================= 
//= Kafra Express - Main Module
//===== By: ================================================== 
//= Skotlex 
//===== Current Version: ===================================== 
//= 5.4
//===== Compatible With: ===================================== 
//= eAthena SVN R3424+
//===== Description: ========================================= 
//= Part of the Kafra Express Script Package.
//= This module contains the main menu, plus the healing and 
//= storage services.
//===== Additional Comments: ================================= 
//= See <http://www.eathena.deltaanime.net/board/index.php?showtopic=20290>
//= for indepth explanation of the Kafra Express Script Package.
//= Services available: comment/uncomment what you want (lines 37-104)
//= See config.txt for per-module configuration.
//============================================================ 

// F_KafraExpress (String "Kafra's name", String "kafra image file",
//int location (0 = Town Kafra, 1 = Dungeon Kafra, 2 = Both),
//String "save map", int save x, int save y)
function	script	F_KafraExpress	{
	set @name$,getarg(0);
	set @ke_type,getarg(2);
	if ($@kekp_reset)
		set @kafraPass,0;
	if (getarg(1) != "")
		cutin getarg(1),2;
	callfunc "F_keIntro",-1,"";

M_INIT:
	set @discount, callfunc("F_keCost",1,100);
	
	if (@ke_type == 1) goto MD_INIT;
	menu
		"- Leave",L_END,
		"- Heal Service ("+($@keh_hpCost*@discount)+"z/10HP - "+($@keh_spCost*@discount)+"z/10SP)",L_HEAL,
		"- Warp Service",M_WARP,
		"- Use Storage ("+($@kes_cost*@discount)+"z)",L_STORAGE,
		"- Use Guild Storage ("+($@kegs_cost*@discount)+"z)",L_GUILD_STORAGE,
		"- Job Services",M_JOB,
		"- Other Services",M_OTHER,
		"- Save Respawn point",L_SAVE;

MD_INIT:
	menu
		"- Leave",L_END,
		"- Heal Service ("+($@keh_hpCost*@discount)+"z/10HP - "+($@keh_spCost*@discount)+"z/10SP)",L_HEAL,
		"- Warp Service",M_WARP,
		"- Use Storage ("+($@kes_cost*@discount)+"z)",L_STORAGE,
		"- Use Guild Storage ("+($@kegs_cost*@discount)+"z)",L_GUILD_STORAGE,
		"- Job Services",M_JOB,
		"- Other Services",M_OTHER,
		"- Save Respawn point",L_SAVE;

M_WARP:
	if (@ke_type == 3 && nif_q_done != 1)
		goto L_DENIED;
	if (@ke_type == 1)
		goto MD_WARP;
	menu
		"- Return",M_INIT,
		"- Dungeons",L_DUNGEON,
		"- PvP Arena",L_PVP,
		"- Guild Wars",L_GUILD_DUNGEON,
		"- Towns",L_TOWN;
	
MD_WARP:
	menu
		"- Return",M_INIT,
		"- Dungeons",L_DUNGEON,
		"- PvP Arena",L_PVP,
		"- Guild Wars",L_GUILD_DUNGEON,
		"- Towns",L_TOWN;

M_JOB:
	if (@ke_type == 1) goto MD_JOB;
	menu
		"- Return", M_INIT,
		"- Change Job",L_JOB_CHANGE,
		"- Swap Job",L_JOB_SWAP,
		"- Stat/Skill Services",L_STATS,
		"- Stat/Skill Market",L_STAT_MARKET,
		"- Rental Service",L_RENT;

MD_JOB:
	menu
		"- Return", M_INIT,
		"- Change Job",L_JOB_CHANGE,
		"- Swap Job",L_JOB_SWAP,
		"- Stat/Skill Services",L_STATS,
		"- Stat/Skill Market",L_STAT_MARKET,
		"- Rental Service",L_RENT;

M_OTHER:
	if (@ke_type == 1) goto MD_OTHER;
	menu
		"- Return",M_INIT,
		"- Bank Services",L_BANK,
		"- Use Kafra Shop",L_SHOP,
		"- Broadcast a message",L_BROADCAST,
		"- Refine Services",L_REFINE,
		"- Uncard Services",L_UNCARD,
		"- Stylist Service",L_STYLE,
		"- Use a Kafra Pass",L_PASS;

MD_OTHER:
	menu
		"- Return",M_INIT,
		"- Bank Services",L_BANK,
		"- Use Kafra Shop",L_SHOP,
		"- Broadcast a message",L_BROADCAST,
		"- Refine Services",L_REFINE,
		"- Uncard Services",L_UNCARD,
		"- Stylist Service",L_STYLE,
		"- Use a Kafra Pass",L_PASS;

L_HEAL:
	callfunc "F_keHeal";
	goto M_INIT;

L_TOWN:
	callfunc "F_keWarpTown";
	goto M_WARP;
	
L_DUNGEON:
	callfunc "F_keDungeonWarps", getarg(3);
	goto M_WARP;
	
L_GUILD_DUNGEON:
	callfunc "F_keWarpWOE";
	goto M_WARP;
	
L_PVP:
	callfunc "F_keWarpPvp";
	goto M_WARP;

L_STORAGE:
	callfunc "F_keStorage", getarg(1);
	goto M_INIT;

L_GUILD_STORAGE:
	callfunc "F_keGuildStorage", getarg(1);
	goto M_INIT;
	
L_BANK:
	callfunc "F_keBank";
	goto M_OTHER;
	
L_SHOP:
	callfunc "F_keShop",@ke_type, getarg(1);
	goto M_OTHER;
	
L_BROADCAST:
	callfunc "F_keBroadcast",getarg(3);
	goto M_OTHER;

L_PASS:
	callfunc "F_kePass";
	goto M_OTHER;

L_REFINE:
	callfunc "F_keRefine";
	goto M_OTHER;

L_UNCARD:
	callfunc "F_keUncard";
	goto M_OTHER;
	
L_STYLE:
	callfunc "F_keStylist";
	goto M_OTHER;

L_JOB_CHANGE:
	callfunc "F_keJobChange";
	goto M_JOB;

L_JOB_SWAP:
	callfunc "F_keJobSwap";
	goto M_JOB;

L_STATS:
	callfunc "F_keStats";
	goto M_JOB;

L_STAT_MARKET:
	callfunc "F_keStatMarket";
	goto M_JOB;

L_RENT:
	callfunc "F_keRent";
	goto M_JOB;

L_SAVE:
	if (@ke_type == 3 && nif_q_done != 1)
		goto L_DENIED;
	if ($@kewt_travel && @ke_type != 1) {
		callfunc "F_keAddTravelTown", getarg(3);
	}
	if ($@kewd_travel && @ke_type != 0) {
		callfunc "F_keAddTravelDungeon", getarg(3);
	}
	if ($@ke_saveOnSpot) {
		getmapxy @map$,@x,@y,0;
		savepoint @map$,@x,@y;
	} else {
		savepoint getarg(3),getarg(4),getarg(5);
	}
	emotion e_scissors;
	goto M_INIT;

L_DENIED:
	callfunc "F_keIntro", e_gg, "...no.";
	goto M_INIT;

L_END:
	mes "Thank you for using Kafra Services.";
	close2;
	cutin getarg(1), 255;
	end;
}

//Function F_keIntro (emotion, message)
//Displays a message followed by an emotion, then a next button, and finally
//shows the intro message.
function	script	F_keIntro	{
	if (getarg(0) >= 0)
		emotion getarg(0);
	if (getarg(1) != "") {
		mes getarg(1);
		next;
	}
	mes "["+@name$+"]";
	mes "Welcome to Kafra Corp. Always by your side, wherever you go.";
	if(@kafraPass) mes "Your Kafra Pass is active,";
	mes "How may I be of help?";
	return;
}

//Function Heal, offers the heal subsystem.
function	script	F_keHeal	{
	set @qtyHP,MaxHp-Hp;
	set @qtySP,MaxSp-Sp;
	set @costHP, $@keh_hpCost*(MaxHp-Hp)/10;
	set @costSP, $@keh_spCost*(MaxSp-Sp)/10;
	set @costHPSP, @costHP+@costSP;
	set @discount, callfunc("F_keCost",1,100);
	
	if (@qtyHP + @qtySP == 0) {
		callfunc "F_keIntro", -1, "...you don't need to be healed.";
		return;
	}
	if (@qtyHP == 0) goto M_NO_HP;
	if (@qtySP == 0) goto M_NO_SP;
	menu "- Cancel",-,
	"- Heal HP ("+(@costHP*@discount)+"z)",L_HEAL_HP,
	"- Heal SP ("+(@costSP*@discount)+"z)",L_HEAL_SP,
	"- Heal Both ("+(@costHPSP*@discount)+"z)",L_HEAL_ALL;
	return;
	
M_NO_HP:
	menu "- Cancel",-,
	"- Heal SP ("+(@costSP*@discount)+"z)",L_HEAL_SP;
	return;
	
M_NO_SP:
	menu "- Cancel",-,
	"- Heal HP ("+(@costHP*@discount)+"z)",L_HEAL_HP;
	return;

L_HEAL_HP:
	if (!(callfunc("F_keCharge",@costHP,100,0))) {
		callfunc "F_keIntro", e_sry, "Sorry, you don't have enough to be healed.";
		return;
	}
	emotion e_no1;
	heal @qtyHP,0;
	return;
	
L_HEAL_SP:
	if (!(callfunc("F_keCharge",@costSP,100,0))) {
		callfunc "F_keIntro", e_sry, "Sorry, you don't have enough to be healed.";
		return;
	}
	emotion e_no1;
	heal 0,@qtySP;
	return;

L_HEAL_ALL:
	if (!(callfunc("F_keCharge",@costHPSP,100,0))) {
		callfunc "F_keIntro", e_sry, "Sorry, you don't have enough to be healed.";
		return; 
	}
	emotion e_no1;
	heal @qtyHP,@qtySP;
	return;
}

//Function storage: allows access to the storage facility
//The sent argument is the displaying image, so we can clear it afterwards.
function	script	F_keStorage	{
	if(basicskillcheck(0) > 0 && getskilllv(1) < 6) {
		callfunc "F_keIntro", -1, "I am sorry, but you beed basic skill level 6 to use the storage.";
		return;
	}
	if (!(callfunc("F_keCharge",$@kes_cost,100,1))) {
		callfunc "F_keIntro", e_an, "Sorry, but you don't have enough Zeny.";
		return;
	}
	mes "Thank for you using Kafra services.";
	emotion e_thx;
	close2;
	openstorage;
	cutin getarg(0), 255;
	end;
}

//Function G Storage: Allows access to the Guild Storage
function	script	F_keGuildStorage	{
	if(basicskillcheck(0) > 0 && getskilllv(1) < 6) {
		callfunc "F_keIntro", -1, "I am sorry, but you beed basic skill level 6 to use the storage.";
		return;
	}
	if(getcharid(2) < 1) {
		callfunc "F_keIntro", e_swt, "You can't use the Guild Storage if you don't belong to a guild!";
		return;
	}
	if (callfunc("F_keCost",$@kegs_cost,100) > Zeny) {
		callfunc "F_keIntro", e_an, "Sorry, but you don't have enough Zeny.";
		return;
	}
	if (guildopenstorage(0) == 1) {
		callfunc "F_keIntro", -1, "Sorry, the guild storage is currently in use by someone else. Try again later.";
		return;
	}
	callfunc "F_keCharge",$@kegs_cost,100,1;
	mes "Thank for you using Kafra services.";
	emotion e_thx;
	close2;
	cutin getarg(0), 255;
	end;
}

function	script	F_kePass	{
	if (@kafraPass) {
		callfunc "F_keIntro", -1, "You already are using a Kafra Pass...";
		return;
	}
	if (countitem(1084)<1) {
		callfunc "F_keIntro", -1, "You obviously need a 'Kafra Pass' if you want to activate it.";
		return;
	}
	delitem 1084,1;
	set @kafraPass,1;
	callfunc "F_keIntro", e_lv, "Your Kafra Pass has been activated.";
	return;
}

//F_keCost(int cost, int discount%)
//Returns what would be the cost of a service considering the KafraPass.
//The discount value should be between 0 and 100
function	script	F_keCost	{
	if (@kafraPass) {
		return getarg(0)*(100-getarg(1))/100;
	}
	return getarg(0);	
}

//F_keCharge(int cost, int discount%, bool appliesKP)
//Charges for a service, using the KafraPass state and discount value.
//appliesKP marks if the cost savings apply for stocking Kafra Reserve Points
//Function returns 1 if successful, 0 if there's not enough zeny.
function	script	F_keCharge	{
	set @savings, 0;
	if (@kafraPass)
		set @savings, getarg(0)*getarg(1)/100;
	set @cost, getarg(0)-@savings;
	if (@cost > Zeny || @cost < 0) { // (@cost < 0) for overflow protection
		return 0;
	}
	set Zeny, Zeny-@cost;
	
	if (getarg(2) && @savings > 0 && $@kekp_reserveCost > 0) {
		set @savings, @savings/$@kekp_reserveCost;
		if (@savings < $@kekp_minReserve)
			set @savings, $@kekp_minReserve;
		if (@savings > $@kekp_maxReserve)
			set @savings, $@kekp_maxReserve;

		set RESRVPTS, RESRVPTS + @savings;
	}
	return 1;
}

//Function F_keWarp (int cost, int discount, int emotion, String map, int x, int y)
function	script	F_keWarp	{
	if (!(callfunc("F_keCharge",getarg(0),getarg(1),1))) {
		callfunc "F_keIntro", e_an, "You don't have enough Zeny...";
		return;
	}
	emotion getarg(2);
	warp getarg(3),getarg(4),getarg(5);
	end;
}
