NEET Lib

NEET Bot Library

目前為 2019-08-11 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/383201/724094/NEET%20Lib.js

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         NEET Lib
// @namespace    http://tampermonkey.net/
// @version      1.1.1
// @description  NEET Bot Library
// @author       eterNEETy
// @match        http://game.granbluefantasy.jp/
// @grant        none
// @namespace    https://greasyfork.org/users/292830
// ==/UserScript==
// jshint esversion: 6
// jshint -W138


// environment info
const xhr = new XMLHttpRequest(),
	server = "http://localhost:2487",
	margin = {"top":91,"left":0},
	game_url = "http://game.granbluefantasy.jp/";

let debug = true,
	reload_counter;

let zoom = 1;

let my_profile = "Main: ";
let is_host = "false";
let battle;
let is_wiped = true;

let quests_id = [], monsters = [], monsters_name = [];

let reloadable_skill = ["Four-Sky's Sorrow", "Thunder Raid"];
let tracked_loot = [];

const kaguya = {"name":"Kaguya", "star":0},
	white_rabbit = {"name":"White Rabbit", "star":3},
	black_rabbit = {"name":"Black Rabbit", "star":3},
	huanglong = {"name":"Huanglong", "star":3},
	shiva = {"name":"Shiva", "star":3},
	shiva0 = {"name":"Shiva", "star":0},
	varuna = {"name":"Varuna", "star":3},
	bonito = {"name":"Bonito", "star":4},
	yggdrasil = {"name":"Yggdrasil Omega", "star":4},
	uriel = {"name":"Uriel", "star":0},
	tiamat = {"name":"Tiamat Omega", "star":4},
	bahamut = {"name":"Bahamut", "star":5},
	lucifer = {"name":"Lucifer", "star":5};
const leech_summons = [kaguya,white_rabbit,black_rabbit];

// const game variable
const trials_id = ["990011","990021","990031","990041","990051","990061","990071"],
	trial_id = "990011",
	select_summon_path = "supporter/";


// path
let path = {
	'main': '',
	"item":"#item",
	"quest":"#quest",
	"support":"#quest/supporter/",
	"assist":"#quest/assist",
	"unclaimed":"#quest/assist/unclaimed",
	"trial":"#quest/supporter/"+trial_id+"/17",
};

// element dom query selector
let skill_char = "#prt-command-top > div > div > div.lis-character";
let skill_abi = ".btn-command-character > div.prt-ability-state > div.lis-ability-state.ability";
let query = {
	"battle_ui": {
		"skill": {
			"char1": {
				"skill1": skill_char + "0" + skill_abi + "1",
				"skill2": skill_char + "0" + skill_abi + "2",
				"skill3": skill_char + "0" + skill_abi + "3",
				"skill4": skill_char + "0" + skill_abi + "4",
			},
			"char2": {
				"skill1": skill_char + "1" + skill_abi + "1",
				"skill2": skill_char + "1" + skill_abi + "2",
				"skill3": skill_char + "1" + skill_abi + "3",
				"skill4": skill_char + "1" + skill_abi + "4",
			},
			"char3": {
				"skill1": skill_char + "2" + skill_abi + "1",
				"skill2": skill_char + "2" + skill_abi + "2",
				"skill3": skill_char + "2" + skill_abi + "3",
				"skill4": skill_char + "2" + skill_abi + "4",
			},
			"char4": {
				"skill1": skill_char + "3" + skill_abi + "1",
				"skill2": skill_char + "3" + skill_abi + "2",
				"skill3": skill_char + "3" + skill_abi + "3",
				"skill4": skill_char + "3" + skill_abi + "4",
			},
		},
		"skill_pop_up": {
			"char1": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character0.btn-command-character > img",
			"char2": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character1.btn-command-character > img",
			"char3": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character2.btn-command-character > img",
			"char4": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character3.btn-command-character > img",
			"char5": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character4.btn-command-character > img",
			"char6": "div.pop-usual.pop-select-member > div.prt-popup-body > div.prt-wrapper > div.prt-character > div.lis-character5.btn-command-character > img",
		},
		"ougi": ".btn-lock",
		"toggle_ougi": {
			true: ".lock0",
			false: ".lock1",
		},
		"char_ico": ".prt-party>.prt-member>.btn-command-character>img.img-chara-command",
		"summon_panel": ".prt-summon-list>.prt-list-top.btn-command-summon",
		"chat":".btn-chat.comment.display-on",
		"chat_pop_up": {
			"dialog":".txt-chat-pop",
		},
		"heal":"#prt-sub-command-group>.btn-temporary",
		"heal_pop_up": {
			"green": ".lis-item.item-small",
			"blue": ".lis-item.item-large",
			"use": ".pop-usual.pop-raid-item.pop-show>.prt-popup-footer>.btn-usual-use",
			"cancel": ".pop-usual.pop-raid-item.pop-show>.prt-popup-footer>.btn-usual-cancel",
		},
		"trial_pop_up": {
			"close": ".pop-usual.pop-trialbattle-notice.pop-show>.prt-popup-footer>.btn-usual-close",
		},
		"backup_pop_up": {
			"request": ".pop-usual.pop-start-assist.pop-show>.prt-popup-footer>.btn-usual-text",
			"cancel": ".pop-usual.pop-start-assist.pop-show>.prt-popup-footer>.btn-usual-cancel",
		},
		"button": {
			"assist": ".prt-multi-buttons>.btn-assist",
		},
	},
	"assist_ui": {
		"tab_id": "#tab-id",
		"tab_multi": "#tab-multi",
		"tab_event": "#tab-event",
		"unclaimed": ".btn-unclaimed",
	},
	"poker": {
		"canvas": "#canv",
		"deal": ".prt-start",
		"ok": ".prt-ok",
		"yes": ".prt-yes",
		"no": ".prt-no",
		"low": ".prt-double-select>.prt-low-shine",
		"high": ".prt-double-select>.prt-high-shine",
	},
	"ok":".btn-usual-ok",
};

// general item variable
let tracked_item = false;

function getMessage(pilot) {
	const message = {
		"raid" : {
			"panel" : {
				"open" : pilot+"Opening quest/raid panel",
				"pick" : pilot+"Picking quest/raid difficulties",
			},
			"select_party" : pilot+"Selecting party",
			"finish" : pilot+"Raid finished",
			"trial" : {
				"close_pop_up" : pilot+"In trial, closing pop up",
				"open_menu" : pilot+ "In trial, click menu",
				"retreat" : pilot+ "In trial, click retreat",
				"ok" : pilot+ "In trial, click ok",
				"end" : pilot+"Retreated from trial, back to main raid",
			}
		},
		"summon" : {
			"select" : pilot+"Selecting summon",
			"pick_tab" : pilot+"Clicking summon element tab",
			"not_found" : pilot+"Support summon not found, going to trial",
		},
		"replenish" : {
			"elixir" : {
				"half_elixir" : {
					"use" : pilot+"Not enough AP, using half elixir",
					"used" : pilot+"Half elixir used",
				}
			},
			"soul" : {
				"soul_berry" : {
					"use" : pilot+"Not enough EP, using soul berry",
					"used" : pilot+"soul berry used",
				}
			}
		},
		"ok" : pilot+"Clicking ok",
	};
	return message;
}

function reloadNow() {
	console.log(reloadNow.name);
	xhr.open('POST', server);
	xhr.send(JSON.stringify([{"cmd":"press","key":"f5"}]));
	window.location.reload();
}

function reload(mod_value=1) {
	clearInterval(reload_counter);
	let current_path = window.location.hash;
	let count = 1;
	reload_counter = setInterval(function() {
		if(window.location.hash != current_path){
			clearInterval(reload_counter);
		}
		console.log("reloading in "+(mod_value-count).toString());
		if (count%mod_value===0){
			clearInterval(reload_counter);
			reloadNow();
		}
		count += 1;
	}, 1000);
}

function setDebug() {
	if(!debug){
		console.log("DEBUG is turned OFF");
		if(!window.console) window.console = {};
		let methods = ["log", "debug", "warn", "info"];
		for(let i=0;i<methods.length;i++){
			console[methods[i]] = function(){};
		}
	}
}

function readBody(xhr) {
	let data;
	if (!xhr.responseType || xhr.responseType === "text") {
		data = xhr.responseText;
	} else if (xhr.responseType === "document") {
		data = xhr.responseXML;
	} else {
		data = xhr.response;
	}
	return data;
}

function gotoHash(key){
	let hash_path;
	if (path[key] !== undefined) {
		hash_path = path[key];
	}else{
		if (key.indexOf("#")!==0) {
			hash_path = "#"+key;
		}
	}
	window.location.href = game_url + hash_path;
}

function scrollTo(query,qid=0) {
	document.querySelectorAll(query)[qid].scrollIntoViewIfNeeded();
}

function checkExist(query,qid=0) {
	let el_exist = false;
	if (document.querySelectorAll(query).length > qid){
		if (document.querySelectorAll(query)[qid].getBoundingClientRect().width > 0 && document.querySelectorAll(query)[qid].getBoundingClientRect().height > 0) {
			el_exist = true;
		}
	}
	return el_exist;
}

function checkEl(query,qid=0,callback=false) {
	let old_top = -1;
	let old_left = -1;
	let loop_checkEl = setInterval(function() {
		console.log(checkEl.name + " " + query + "[" + qid + "]");
		if (checkExist(query,qid)) {
			if (old_top==document.querySelectorAll(query)[qid].getBoundingClientRect().top && old_left==document.querySelectorAll(query)[qid].getBoundingClientRect().left) {
				clearInterval(loop_checkEl);
				if (typeof callback == "function") {
					callback();
				}
			}else{
				old_top = document.querySelectorAll(query)[qid].getBoundingClientRect().top;
				old_left = document.querySelectorAll(query)[qid].getBoundingClientRect().left;
			}
		}
	}, 200);
}

function checkEls(queries,callback=false) {
	let exist_result;
	let loop_checkEls = setInterval(function() {
		exist_result = [];
		for (let i in queries) {
			console.log(checkEls.name + " " + queries[i].query + "[" + queries[i].qid + "]");
			exist_result.push(checkExist(queries[i].query,queries[i].qid));
		}
		if (exist_result.indexOf(false)===-1) {
			clearInterval(loop_checkEls);
			if (typeof callback == "function") {
				callback();
			}
		}
	}, 300);
}

function checkElsOR(queries,callback=false) {
	let exist_result;
	let loop_checkEls = setInterval(function() {
		exist_result = [];
		for (let i in queries) {
			console.log(checkElsOR.name + " " + queries[i].query + "[" + queries[i].qid + "]");
			exist_result.push(checkExist(queries[i].query,queries[i].qid));
		}
		if (exist_result.indexOf(true)>=0) {
			clearInterval(loop_checkEls);
			if (typeof callback == "function") {
				callback();
			}
		}
	}, 300);
}

function checkError() {
	let q_cnt_error = ".cnt-error";
    let q_pop_up = ".pop-usual.common-pop-error.pop-show";
    let q_abi_pop_up = ".pop-usual.pop-raid-ability-error.pop-show";
    let check_error = setInterval(function() {
		console.log(checkError.name);
		
		if (checkExist(q_pop_up,0) || checkExist(q_cnt_error,0) || checkExist(q_abi_pop_up,0)) {
			let cmd = [];
			console.log("error_found");
			let do_reload = false;
			let level = "notif";
			let msg = "Uncatagorized error found";
			// let msg = "Connection error, refreshing disabled"
			if (checkExist(q_abi_pop_up,0)) {
				do_reload = true;
				msg = my_profile + document.querySelector(q_abi_pop_up+">.prt-popup-body>.txt-popup-body").innerHTML;
				level = "process";
			} else {
				if (checkExist(q_pop_up+">.prt-popup-header",0)) {
					if (document.querySelector(q_pop_up+">.prt-popup-header").innerHTML=="Access Verification") {
						clearInterval(reload_counter);
						msg = my_profile+"Captcha detected";
						console.log("Captcha detected");
					}else if (document.querySelector(q_pop_up+">.prt-popup-header").innerHTML=="エラー") {
						if (checkExist(q_pop_up+">.prt-popup-body>.txt-popup-body>div",0)) {
							if (typeof document.querySelector(q_pop_up+">.prt-popup-body>.txt-popup-body>div").innerHTML == "string") {
								if (document.querySelector(q_pop_up+">.prt-popup-body>.txt-popup-body>div").innerHTML.indexOf("Network Error")>=0) {
									clearInterval(reload_counter);
									console.log("Error connection");
									do_reload = true;
									msg = my_profile+"Error connection, reloading";
									level = "process";
								}
							}
						}
					}
				}
				if (checkExist(q_pop_up+">.prt-popup-body>.txt-popup-body",0)) {
					if (document.querySelector(q_pop_up+">.prt-popup-body>.txt-popup-body").innerHTML=="Check your pending battles.") {
						console.log("check raid");
						level = "process";
						msg = my_profile+"Check your pending battle";
						clickEl(".prt-popup-footer>.btn-usual-ok",0,my_profile+"Clicking ok pop up pending battles");
					}
				}
			}
			if (do_reload){
				cmd.push({"cmd":"press","key":"f5"});
			}
			cmd.push({"cmd":"log","level":level,"msg":msg});
			xhr.open('POST', server);
			xhr.send(JSON.stringify(cmd));
			if (do_reload){
				window.location.reload();
			}
		}
	}, 5000);
}

function getCoord(el){
	zoom = parseInt(document.getElementById("mobage-game-container").style.zoom);
	let x, y, output;
	el = el.getBoundingClientRect();
	if (el.width>0 && el.height>0) {
		x = (el.width / 2) + el.left;
		y = (el.height / 2) + el.top;
		if(el.width>40){
			x += Math.floor(Math.random() * 41)-20;
		}else if(el.width>20){
			x += Math.floor(Math.random() * 21)-10;
		}else if(el.width>10){
			x += Math.floor(Math.random() * 11)-5;
		}
		if(el.height>10){
			y += Math.floor(Math.random() * 11)-5;
		}
		output = [(x*zoom)+margin.left,(y*zoom)+margin.top];
	}else{
		output = 0;
	}
	return output;
}

function getMarginCoord(query,qid){
	let el = document.querySelectorAll(query)[qid].getBoundingClientRect();
	return {"top":el.top+margin.top,"left":el.left+margin.left};
}

function clickNow(query,qid=0,msg=my_profile+"clickNow called",callback=false){
	let el = document.querySelectorAll(query)[qid];
	let output = false;
	if (checkExist(query,qid)) {
		output = true;
		let cmd = [];
		cmd.push({"cmd":"clickIt","param":getCoord(el)});
		cmd.push({"cmd":"log","level":"process","msg":msg});
		xhr.open("POST", server);
		xhr.send(JSON.stringify(cmd));
		if (typeof callback == "function") {
			callback();
		}
	}
	return output;
}

function clickEl(query,qid=0,msg=my_profile+"clickEl called",callback=false){
	let init_clickEl = function() {
		clickNow(query,qid,msg,callback);
	};
	checkEl(query,qid,init_clickEl);
}

function clickObject(obj){
	if (obj == "ok"){
		clickEl(".btn-usual-ok",0,message.ok);
	}
}

function clickAndNegCheck(query,qid=0,msg="clickAndNegCheck called",callback=false,ticks=5){
	let old_href = window.location.href;
	let old_top = -1;
	let old_left = -1;
	let match = ticks-1;
	let str_clickAndNegCheck = clickAndNegCheck.name + ", el: " + query + "["+(qid.toString())+"] \n- match = ";
	let init_clickAndNegCheck = function() {
		let loop_clickAndNegCheck = setInterval(function() {
			console.log(str_clickAndNegCheck+(match.toString()));
			if (!(checkExist(query,qid))) {
				clearInterval(loop_clickAndNegCheck);
				if (typeof callback == "function") {
					callback();
				}
			}else if (old_href != window.location.href) {
				clearInterval(loop_clickAndNegCheck);
			}else{
				if (checkExist(query,qid)) {
					if (old_top==document.querySelectorAll(query)[qid].getBoundingClientRect().top && old_left==document.querySelectorAll(query)[qid].getBoundingClientRect().left) {
						if (match % ticks == 0) {
							clickNow(query,qid,msg);
						}
						match += 1;
					}else{
						old_top = document.querySelectorAll(query)[qid].getBoundingClientRect().top;
						old_left = document.querySelectorAll(query)[qid].getBoundingClientRect().left;
					}
				}
			}
		}, 100);
	};
	checkEl(query,qid,init_clickAndNegCheck);
}

function clickAndCheck(query1,qid1=0,query2,qid2=0,msg="clickAndCheck called",callback=false,ticks=5){
	let old_href = window.location.href;
	let old_top = -1;
	let old_left = -1;
	let match = ticks-1;
	let str_clickAndCheck = clickAndCheck.name + ", check: " + query2 + "["+(qid2.toString())+"], click: " + query1 + "["+(qid1.toString())+"] \n- match = ";
	let loop_clickAndCheck = setInterval(function() {
		console.log(str_clickAndCheck+(match.toString()));
		if (checkExist(query2,qid2)) {
			clearInterval(loop_clickAndCheck);
			if (typeof callback == "function") {
				callback();
			}
		}else if (old_href != window.location.href) {
			clearInterval(loop_clickAndCheck);
		}else{
			if (checkExist(query1,qid1)) {
				if (old_top==document.querySelectorAll(query1)[qid1].getBoundingClientRect().top && old_left==document.querySelectorAll(query1)[qid1].getBoundingClientRect().left) {
					if (match % ticks == 0) {
						clickNow(query1,qid1,msg);
					}
					match += 1;
				}else{
					old_top = document.querySelectorAll(query1)[qid1].getBoundingClientRect().top;
					old_left = document.querySelectorAll(query1)[qid1].getBoundingClientRect().left;
				}
			}
		}
	}, 100);
}

function popUpNotEnough(rep) {
	const query = ".btn-use-full.index-1",
		qid = 0,
		msg = message.replenish.elixir.half_elixir.use;
	let cmd = [], coordinate, consumable_data;
	consumable_data = my_profile+"Consumable Status:";
	for (let i = 0; i < rep.length; i++) {
		consumable_data += ("\n- "+rep[i].name+": "+rep[i].number);
	}
	let init_popUpNotEnough = function() {
		coordinate = getCoord(document.querySelectorAll(query)[qid]);
		if (coordinate!==0){
			cmd.push({"cmd":"clickIt","param":coordinate});
			cmd.push({"cmd":"log","level":"process","msg":msg});
			cmd.push({"cmd":"log","level":"summary","msg":consumable_data,"split":0});
			xhr.open('POST', server);
			xhr.send(JSON.stringify(cmd));
		}
	};
	checkEl(query,qid,init_popUpNotEnough);

}

function clickAndCheckSkill(query,qid=0,msg="clickAndCheckSkill called",callback=false,special_case=false){
	console.log(clickAndCheckSkill.name);
	console.log(callback);
	console.log(query);
	console.log(qid);
	let old_class = document.querySelectorAll(query)[qid].parentNode.classList[0];
	console.log(old_class);
	let loop_clickAndCheckSkill = setInterval(function() {
		console.log(checkEl.name + " " + query + "[" + qid + "]");
		if (Array.from(document.querySelectorAll(query)[qid].parentNode.parentNode.classList).indexOf("tmp-mask")>=0 || Array.from(document.querySelectorAll(query)[qid].parentNode.parentNode.classList).indexOf("btn-ability-unavailable")>=0){
			clearInterval(loop_clickAndCheckSkill);
			console.log(clickAndCheckSkill.name + " case normal");
			if (typeof callback == "function") {
				callback();
			}
		// Bea skill
		}else if(special_case===1 && document.querySelectorAll(query)[qid].parentNode.classList[0] != old_class){
			clearInterval(loop_clickAndCheckSkill);
			console.log(clickAndCheckSkill.name + " case " + special_case.toString());
			if (typeof callback == "function") {
				callback();
			}
		// Out of sight & sage of eternity
		}else if(special_case===2){
			let do_click = true;
			console.log(clickAndCheckSkill.name + " case " + special_case.toString());
			let popup_query = "#wrapper > div.contents > div.pop-usual.pop-select-member > div.prt-popup-header";
			if (checkExist(popup_query,0)) {
				if (document.querySelector("#wrapper > div.contents > div.pop-usual.pop-select-member > div.prt-popup-header").innerHTML == "Use Skill"){
					clearInterval(loop_clickAndCheckSkill);
					do_click = false;
					if (typeof callback == "function") {
						callback();
					}
				}
			}
			if (do_click) {
				if (checkExist(query,qid)) {
					clickNow(query,qid,msg);
				}
			}
		}else{
			if (checkExist(query,qid)) {
				clickNow(query,qid,msg);
			}
		}

	}, 500);
}

function getCharStr(char_id){
	let char;
	if (char_id==1){
		char = "MC";
	}else{
		char = "NPC"+((char_id-1).toString());
	}
	return char;
}

function useSkill(char_id,abi_id,callback=false,special_case=false){
	console.log(useSkill.name + ", char: "+char_id+", ability: " + (abi_id.toString()) + ", case: "+special_case);
	let char = getCharStr(char_id);
	abi_id = parseInt(abi_id)-1;
	console.log(".prt-command-chara.chara"+(char_id.toString())+">div>div.lis-ability");
	if (Array.from(document.querySelectorAll(".prt-command-chara.chara"+(char_id.toString())+">div>div.lis-ability")[abi_id].classList).indexOf("btn-ability-available")>=0 && document.querySelectorAll(".prt-command-chara.chara"+(char_id.toString())+">div>div.lis-ability")[abi_id].getBoundingClientRect().width>0){
		clickAndCheckSkill(".prt-command-chara.chara"+(char_id.toString())+">div>div>div>.img-ability-icon",abi_id,my_profile+"Clicking "+char+" skill"+((abi_id+1).toString()),callback,special_case);
	}else{
		if (typeof callback == "function") {
			callback();
		}
	}
}

function useSkills(char_id, skill_list, callback=false, special_case=[false]) {
	console.log(useSkills.name);
	if (skill_list.length>0) {
		console.log(useSkills.name + ", char: "+char_id+", ability: " + (skill_list[0].toString()) + ", case: "+special_case[0]);
		let new_skill_list = Object.values(skill_list);
		new_skill_list.splice(0,1);
		console.log("dari useSkills");
		console.log(new_skill_list);
		console.log("---");
		let abi_id = parseInt(skill_list[0])-1;
		let char = battle.player.param[char_id-1].name;
		let next_skill = function(){console.log("dari next_skill");useSkills(char_id, new_skill_list, callback, special_case);};
		console.log(next_skill);
		console.log(abi_id);
		if (Array.from(document.querySelectorAll(".prt-command-chara.chara"+(char_id.toString())+">div>div.lis-ability")[abi_id].classList).indexOf("btn-ability-available")>=0 && document.querySelectorAll(".prt-command-chara.chara"+(char_id.toString())+">div>div.lis-ability")[abi_id].getBoundingClientRect().width>0){
			console.log(".prt-command-chara.chara"+(char_id.toString())+">div>div>div>.img-ability-icon");
			console.log(abi_id);
			console.log(my_profile+"Clicking "+char+" skill"+((abi_id+1).toString()));
			console.log(next_skill);
			console.log(special_case[0]);
			clickAndCheckSkill(".prt-command-chara.chara"+(char_id.toString())+">div>div>div>.img-ability-icon",abi_id,my_profile+"Clicking "+char+" skill"+((abi_id+1).toString()),next_skill,special_case[0]);
		}else{
			if (typeof callback == "function") {
				next_skill();
			}
		}
	} else {
		if (typeof callback == "function") {
			callback();
		}
	}

}

function clickBackup(callback=false) {
	let check_backup = function() {
		let el_btn, backup_msg;
		if (Array.from(document.querySelector(query.battle_ui.backup_pop_up.request).classList).indexOf("disable") >= 0) {
			el_btn = query.battle_ui.backup_pop_up.cancel;
			backup_msg = "cancel";
		} else {
			el_btn = query.battle_ui.backup_pop_up.request;
			backup_msg = "request";
		}
		clickAndNegCheck(el_btn,0,my_profile+"Clicking "+backup_msg,callback,10);
	};
	clickAndCheck(query.battle_ui.button.assist,0,query.battle_ui.backup_pop_up.request,0,my_profile+"Clicking backup",check_backup,10);
}

function clickBack(callback=false){
	clickAndCheck(".btn-command-back.display-on",0,"div.prt-member",0,my_profile+"Clicking back",callback,10);
}

function clickSummonPanel(callback=false){
	console.log(clickSummonPanel.name);
	let query1 = ".prt-list-top.btn-command-summon.summon-on";
	let query2 = ".prt-summon-list.opened";
	let query3 = ".prt-list-top.btn-command-summon.summon-off";
	let qid1 = 0, qid2 = 0, qid3 = 0;
	let msg = my_profile+"Clicking summon panel";
	let old_top = -1;
	let old_left = -1;
	let loop_clickAndCheck = setInterval(function() {
		console.log(clickAndCheck.name + ", check: " + query2 + "["+(qid2.toString())+"], click: " + query1 + "["+(qid1.toString())+"]");
		if (checkExist(query2,qid2) || checkExist(query3,qid3)) {
			clearInterval(loop_clickAndCheck);
			if (typeof callback == "function") {
				callback();
			}
		}else{
			if (checkExist(query1,qid1)) {
				if (old_top==document.querySelectorAll(query1)[qid1].getBoundingClientRect().top && old_left==document.querySelectorAll(query1)[qid1].getBoundingClientRect().left) {
					clickNow(query1,qid1,msg);
				}else{
					old_top = document.querySelectorAll(query1)[qid1].getBoundingClientRect().top;
					old_left = document.querySelectorAll(query1)[qid1].getBoundingClientRect().left;
				}
			}
		}
	}, 200);
}

function clickSummon(summon_id,callback1=false,callback2=false){
	console.log(clickSummon.name);
	summon_id = summon_id-1;
	if (Array.from(document.querySelectorAll(".lis-summon")[summon_id].classList).indexOf("btn-summon-available")>=0){
		let loop_clickSummon = setInterval(function() {
			if (document.querySelectorAll(".lis-summon>img")[summon_id].getBoundingClientRect().x === document.querySelectorAll(".lis-summon>img")[0].getBoundingClientRect().x + (summon_id * (document.querySelectorAll(".lis-summon>img")[0].getBoundingClientRect().width+2))){
				clearInterval(loop_clickSummon);
				clickAndCheck(".lis-summon>img",summon_id,".pop-usual.pop-summon-detail>div>.btn-usual-ok.btn-summon-use",0,my_profile+"Clicking summon "+((summon_id+1).toString()),callback1);
			}
		}, 300);
	}else{
		if (typeof callback2 == "function") {
			callback2();
		}
	}
}

function clickOkSummon(callback=false){
	console.log(clickOkSummon.name);
	let el_ok = ".pop-usual.pop-summon-detail>div>.btn-usual-ok.btn-summon-use";
	if (document.querySelector(el_ok) !== null){
		clickAndCheck(el_ok,0,"div.prt-member",0,my_profile+"Clicking summon ok",callback);
	}else{
		if (typeof callback == "function") {
			callback();
		}
	}
}
function clickOkSummon2(summon_id,callback=false){
	let el_ok = ".pop-usual.pop-summon-detail>div>.btn-usual-ok.btn-summon-use";
	let summon_el = '.lis-summon[pos="'+(summon_id.toString())+'"]';
	if (document.querySelector(el_ok) !== null){
		let loop_clickOkSummon2 = setInterval(function() {
			console.log(clickOkSummon2.name + ", click: " + el_ok + "[0]");
			if (Array.from(document.querySelector(summon_el).classList).indexOf("tmp-mask")>=0 || Array.from(document.querySelector(summon_el).classList).indexOf("btn-summon-unavailable")>=0) {
				clearInterval(loop_clickOkSummon2);
				if (typeof callback == "function") {
					callback();
				}
			}else{
				if (checkExist(el_ok,0)) {
					clickNow(el_ok,0,my_profile+"Clicking summon ok2");
				}
			}
		}, 1000);
	}else{
		if (typeof callback == "function") {
			callback();
		}
	}
}

function selectSummon(preferred_summon,is_trial=false){
	reload(20);

	let init_selectSummon = function() {
		console.log(init_selectSummon.name);
		reload(10);
		const attrib_list = [6,0,1,2,3,4,5];
		let query_summon_list = ".btn-supporter.lis-supporter";
		let el_summon_list = document.querySelectorAll(query_summon_list);
		let preferred_summon_id = false;
		let picked_attrib_id = false;
		let picked_summon_id = false;
		let picked_is_friend = false;
		let is_friend;
		let picked_summon_stars = false;
		let picked_summon_level = false;
		let picked_summon_plus = false;
		let msg;
		let cmd = [], summon_list = {};
		if (el_summon_list.length>50 && document.querySelector(".prt-supporter-battle-announce")===null && document.querySelector(".txt-confirm-comment")===null && document.querySelector(".prt-check-auth")===null && document.querySelector(".btn-check-auth")===null){
			msg = my_profile+"Verify not appear, summon list length is "+(el_summon_list.length.toString());
			console.log(msg);

			// check if raid is trial
			if (!is_trial){
				console.log("not trial");
				for (let i = 0; i < el_summon_list.length; i++) {
					let match_preferred = false, replace = false;
					let temp_var, summon_detail, summon_name, summon_level, summon_stars, summon_plus;
					temp_var = el_summon_list[i].querySelector(".prt-supporter-summon");
					summon_detail = temp_var.innerHTML.trim();
					temp_var = el_summon_list[i].querySelector(".prt-supporter-summon");
					summon_detail = temp_var.innerHTML.trim();
					summon_name = summon_detail.substring(summon_detail.indexOf("</span>")+8,summon_detail.length);
					summon_level = parseInt(temp_var.children[0].innerHTML.replace("Lvl ",""));
					temp_var = Array.from(el_summon_list[i].querySelector(".prt-summon-skill").classList);
					if (temp_var.indexOf("bless-rank3-style")>=0){
						summon_stars = 5;
					}else if (temp_var.indexOf("bless-rank2-style")>=0){
						summon_stars = 4;
					}else if (temp_var.indexOf("bless-rank1-style")>=0){
						summon_stars = 3;
					}else{
						summon_stars = 0;
					}
					temp_var = el_summon_list[i].querySelector(".prt-summon-quality");
					if (temp_var !== null){
						summon_plus = parseInt(temp_var.innerHTML.replace("+",""));
					}else{
						summon_plus = 0;
					}
					temp_var = false;
					is_friend = Array.from(el_summon_list[i].querySelector(".prt-supporter-name").classList).indexOf("ico-friend")>=0;

					// loop preferred summon list (specified in parameter)
					for (let j = 0; j < preferred_summon.length; j++) {
						if (preferred_summon[j].name==summon_name && preferred_summon[j].star<=summon_stars){
							match_preferred = true;
							temp_var = j;
						}
					}


					if (match_preferred){
						if (picked_attrib_id===false && picked_summon_id===false){
							replace = true;
						}else{
							if (preferred_summon_id>temp_var){
								replace = true;
							}else if(preferred_summon_id==temp_var){
								if (summon_stars>picked_summon_stars){
									replace = true;
								}else if(summon_stars==picked_summon_stars){
									if (!picked_is_friend && is_friend){
										replace = true;
									}else if(picked_is_friend && is_friend){
										if (summon_level>picked_summon_level){
											replace = true;
										}else if(summon_level==picked_summon_level){
											if (summon_plus>picked_summon_plus){
												replace = true;
											}
										}
									}
								}
							}
						}
					}
					if (replace){
						picked_attrib_id = Array.from(document.querySelectorAll(".prt-supporter-attribute")).indexOf(el_summon_list[i].parentElement);
						picked_summon_id = i;
						preferred_summon_id = temp_var;
						picked_summon_stars = summon_stars;
						picked_is_friend = is_friend;
						picked_summon_level = summon_level;
						picked_summon_plus = summon_plus;
					}
				}
				console.log([picked_attrib_id,picked_summon_id,preferred_summon_id]);
				if (picked_summon_id===false){
					console.log("go to trial");
					cmd.push({"cmd":"log","level":"process","msg":message.summon.not_found});
					xhr.open("POST", server);
					xhr.send(JSON.stringify(cmd));
					gotoHash("trial");
				}else{
					console.log("summon_found");
					let pickSummon = function() {
						scrollTo(query_summon_list,picked_summon_id);
						clickEl(query_summon_list,picked_summon_id,message.summon.select);
					};
					let clickAndCheckSummon = function(callback=false){
						let el_tab_ele_ico = ".prt-type-text";
						let el_summon_container = ".prt-supporter-attribute";
						let loop_clickAndCheckSummon = setInterval(function() {
							console.log(clickAndCheckSummon.name + ", check: " + el_summon_container + "[" + picked_attrib_id + "], click: " + el_tab_ele_ico + "["+(attrib_list[picked_attrib_id].toString())+"]");
							if (Array.from(document.querySelectorAll(el_summon_container)[picked_attrib_id].classList).indexOf("disableView") == -1) {
								clearInterval(loop_clickAndCheckSummon);
								if (typeof callback == "function") {
									callback();
								}
							}else{
								if (checkExist(el_tab_ele_ico, attrib_list[picked_attrib_id])) {
									clickNow(el_tab_ele_ico, attrib_list[picked_attrib_id], message.summon.pick_tab);
								}
							}
						}, 300);
					};
					clickAndCheckSummon(pickSummon);
				}
			}else{
				console.log("is trial");
				query_summon_list = ".prt-supporter-attribute:not(.disableView)>.btn-supporter.lis-supporter";
				el_summon_list = document.querySelectorAll(query_summon_list);
				for (let i = 0; i < el_summon_list.length; i++) {
					is_friend = Array.from(el_summon_list[i].querySelector(".prt-supporter-name").classList).indexOf("ico-friend")>=0;
					if (!is_friend){
						if (picked_summon_id===false){
							picked_summon_id = i;
						}
					}
				}
				if (picked_summon_id!==false){
					scrollTo(".prt-supporter-attribute:not(.disableView)>.btn-supporter.lis-supporter",picked_summon_id);
					clickEl(".prt-supporter-attribute:not(.disableView)>.btn-supporter.lis-supporter",picked_summon_id,message.summon.select);
				}
			}
		}else{
			msg = my_profile+"Verify might appear, summon list length is "+(el_summon_list.length.toString());
			clearInterval(reload_counter);
			console.log(msg);
			cmd.push({"cmd":"log","level":"process","msg":msg});
			cmd.push({"cmd":"log","level":"notif","msg":msg});
			xhr.open("POST", server);
			xhr.send(JSON.stringify(cmd));
		}
	};
	checkEl(".prt-supporter-title",0,init_selectSummon);
}

function doChat(callback=false) {
	console.log(doChat.name);
	let clickDialog = function() {
		console.log(clickDialog.name);
		clickAndNegCheck(query.battle_ui.chat_pop_up.dialog,0,my_profile+"Clicking chat dialog",callback);
	};
	let clickChat = function() {
		console.log(clickChat.name);
		if (checkExist(query.battle_ui.chat+">.ico-attention",0)) {
			clickAndCheck(query.battle_ui.chat,0,query.battle_ui.chat_pop_up.dialog,0,my_profile+"Clicking chat pop up",clickDialog,20);
		}else{
			if (typeof callback == "function") {
				callback();
			}
		}
	};
	checkEl(query.battle_ui.chat,0,clickChat);
}

function backFromTrial(){
	let cmd = [];
	cmd.push({"cmd":"log","level":"process","msg":message.raid.trial.end});
	xhr.open("POST", server);
	xhr.send(JSON.stringify(cmd));
	gotoHash("main");
}

function gotoResult() {
	console.log(gotoResult.name);
	console.log(is_host);
	if (is_host || window.location.hash.indexOf("#raid/")>=0) {
		gotoHash("quest");
	}else if (window.location.hash.indexOf("#raid_multi")>=0) {
		reloadNow();
	}
}

function attack(rep){
	console.log(attack.name);
	let cmd = [];
	let reps = rep.scenario;
	let win = false;
	let is_last_raid = false;
	let ougi = 0;
	let msg = "";
	for (let i = 0; i < reps.length; i++) {
		if (reps[i].cmd =="win"){
			if (reps[i].is_last_raid){is_last_raid=true;}
			win=true;
		}else if (reps[i].cmd=="special" || reps[i].cmd=="special_npc"){
			const char_name = battle.player.param[parseInt(battle.formation[reps[i].pos])].name;
			msg += my_profile+char_name+" used ougi \""+reps[i].name+"\".\n";
			if (reps[i].total){msg += my_profile+char_name+" dealt "+reps[i].total[0].split.join("")+" damage.\n";}
			ougi++;
		}else if (reps[i].cmd=="attack" && reps[i].from=="player"){
			const char_name = battle.player.param[parseInt(battle.formation[reps[i].pos])].name;
			if (reps[i].damage.length==3){
				msg += my_profile+char_name+" made a triple attack.\n";
			}else if (reps[i].damage.length==2){
				msg += my_profile+char_name+" made a double attack.\n";
			}
			msg += my_profile+char_name+ " dealt ";
			for (let ii=0; ii<reps[i].damage.length; ii++){
				msg += reps[i].damage[ii][0].value.toString();
				if (ii<reps[i].damage.length-1){
					msg += ", ";
				}else{
					msg += " damage.\n";
				}
			}
		}
	}

	if(win){
		cmd.push({"cmd":"log","level":"process","msg":msg+my_profile+"Foe defeated."});
	}else{
		cmd.push({"cmd":"log","level":"process","msg":msg+my_profile+"Foe is still alive."});
		cmd.push({"cmd":"press","key":"f5"});
	}
	xhr.open('POST', server);
	xhr.send(JSON.stringify(cmd));
	if(win && is_last_raid){
		gotoResult();
	}else if(win){
		clickEl(".btn-result",0,my_profile+"Go to next round");
	}
}

function skillUsed(rep){
	console.log(skillUsed.name);
	let do_reload = false;
	let reps = rep.scenario;
	let win = false, is_last_raid = false;
	console.log(reps);
	for (let i = 0; i < reps.length; i++) {
		const scenario = reps[i];
		if (scenario.cmd =="ability"){
			if (reloadable_skill.indexOf(scenario.name)>= 0) {
				do_reload = true;
			}
		}else if (scenario.cmd =="damage") {
			if (scenario.to == "player") {
				for (let j = 0; j < scenario.list.length; j++) {
					const s = scenario.list[j];
					if (s.hp !== undefined && s.pos !== undefined) {
						battle.player.param[s.pos].hp = s.hp;
					}
				}
			}
		}else if (scenario.cmd =="finished"){
			win=true;
			is_last_raid=true;
		}else if (scenario.cmd == "win"){
			if (scenario.is_last_raid) {
				is_last_raid=true;
			}
			win=true;
		}
		
	}
	if(win && is_last_raid){
		gotoResult();
	}else if(do_reload){
		reloadNow();
	}
}

function summonUsed(rep){
	console.log(summonUsed.name);
	let do_reload = false;
	let reps = rep.scenario;
	let win = false,
		is_last_raid = false;
	for (let i = 0; i < reps.length; i++) {
		const scenario = reps[i];
		if (scenario.cmd == "finished"){
			win=true;
			is_last_raid=true;
		}else if (scenario.cmd == "win"){
			if (scenario.is_last_raid){
				is_last_raid=true;
			}
			win=true;
		}	
	}
	if (battle.lyria_pos >= 0) {
		do_reload = true;
	}
	if(win && is_last_raid){
		gotoResult();
	}else if(do_reload){
		reloadNow();
	}
}

function potUsed(rep) {
	console.log(potUsed.name);
	let reps = rep.scenario;
	for (let i = 0; i < reps.length; i++) {
		const scenario = reps[i];
		if (scenario.cmd == "heal") {
			for (let j = 0; j < scenario.list.length; j++) {
				const s = scenario.list[j];
				if (s.hp !== undefined && s.pos !== undefined) {
					battle.player.param[s.pos].hp = s.hp;
				}
			}
		}
	}
}

function clickAttack(callback=false) {
	let hp = ((parseInt(battle.boss.param[0].hp) / parseInt(battle.boss.param[0].hpmax)) * 100).toString();
	if (hp.indexOf(".")>=0){
		hp = hp.substring(0,hp.indexOf("."));
	}
	console.log(hp);
	let attack_msg = my_profile+"Foe hp is "+hp+"% left, commencing attack";
	clickAndCheck(".btn-attack-start.display-on",0,".btn-attack-cancel.btn-cancel.display-on",0,attack_msg,callback,20);
}

function charMoveSet(cid,skill_list,callback) {
	console.log(charMoveSet.name + ': ' + cid);
	let char = battle.player.param[cid];
	console.log(char.name);
	if (char !== undefined) {
		let can_use_skill = true;
		if (skill_list.length>0) {
			let new_skill_list = Object.values(skill_list);
			for (let i = 0; i < skill_list.length; i++) {
				const skill = skill_list[i];
				if (document.querySelector(query.battle_ui.skill['char'+(cid+1).toString()]['skill'+(skill.toString())]).attributes.state.value != "2") {
					new_skill_list.splice(new_skill_list.indexOf(skill),1);
				}
			}
			skill_list = new_skill_list;
			if ("debuff" in char.condition) {
				for (let i = 0; i < char.condition.debuff.length; i++) {
					const debuff = char.condition.debuff[i];
					if (debuff.status == "1111") {
						can_use_skill = false;
					}
				}
			}
		}
		if (char.alive===1 && skill_list.length>0 && can_use_skill) {
			let click_back = function(){clickBack(callback);};
			let use_skills = function(){useSkills(cid+1,skill_list,click_back);};
			let click_char = function(){clickChar(cid+1,use_skills);};
			click_char();
		} else {
			if (typeof callback == "function") {
				callback();
			}
		}
	} else {
		if (typeof callback == "function") {
			callback();
		}
	}
}


function toggleOugi(ougi, callback=false) {
	let init_toggleOugi = function() {
		let current_ougi = "."+document.querySelector(query.battle_ui.ougi).classList[1];
		if (query.battle_ui.toggle_ougi[ougi] != current_ougi){
			clickAndCheck(query.battle_ui.ougi + current_ougi, 0, query.battle_ui.ougi + query.battle_ui.toggle_ougi[ougi], 0, my_profile+"Set toggle ougi to "+(ougi.toString()), callback);
		}else{
			if (typeof callback == "function") {
				callback();
			}
		}
	};
	checkEl(query.battle_ui.ougi,0,init_toggleOugi);
}

function summoning(summon_id,callback=false) {
	console.log(summoning.name);
	let summon_cd;
	console.log('test 1');
	if (summon_id === 5) {
		console.log('test 2');
		summon_cd = battle.supporter.recast;
		console.log('test 3');
	} else if (battle.summon[summon_id] !== undefined) {
		console.log('test 4');
		summon_cd = battle.summon[summon_id].recast;
		console.log('test 5');
	}
	console.log('test 6');
	if (summon_cd === "0") {
		console.log('test 7');
		let summon_ok = function(){clickOkSummon(callback);};
		let summon = function(){clickSummon(summon_id+1,summon_ok,callback);};
		let summon_p = function(){clickSummonPanel(summon);};
		summon_p();
	} else {
		console.log('test 8');
		if (typeof callback == "function") {
			callback();
		}
	}
}

function startRaid(rep){
	reload(15);
	battle = rep;
	is_host = rep.is_host;
	for (let i = 0; i < battle.player.param.length; i++) {
		const c = battle.player.param[i];
		if (c.alive === 1) {
			is_wiped = false;
		}
	}
	let usePot = function(pot_type,char_id=false,callback=false) {
		console.log(usePot.name);
		let is_front_healable = [];
		let is_player_reviveable = [];
		let is_player_healable = [];
		for (const i in battle.player.param) {
			if (battle.player.param.hasOwnProperty(i)) {
				if (battle.player.param[i].alive === 1) {
					is_player_reviveable.push(false);
					is_player_healable.push(battle.player.param[i].hpmax - battle.player.param[i].hp !== 0);
				}else{
					is_player_reviveable.push(true);
					is_player_healable.push(false);
				}
			}
		}
		for (const i in rep.formation) {
			if (rep.formation.hasOwnProperty(i)) {
				const alive_id = parseInt(rep.formation[i]);
				is_front_healable.push(battle.player.param[alive_id].hpmax - battle.player.param[alive_id].hp !== 0);
			}
		}
		let query_qty = ">.txt-having>.having-num";
		let clickUse = function() {
			clickAndNegCheck(query.battle_ui.heal_pop_up.use,0,my_profile+"Clicking use from pot pop up",callback);
		};
		let clickFront = function() {
			clickAndCheck(query.battle_ui.char_ico,char_id,query.battle_ui.summon_panel+":not(.mask-black)",0,my_profile+"Clicking char_ico from pot pop up",callback);
		};
		let clickCancel = function() {
			clickAndNegCheck(query.battle_ui.heal_pop_up.cancel,0,my_profile+"Clicking cancel from pot pop up",callback);
		};
		let clickPot = function() {
			console.log(clickPot.name);
			if (checkExist(query.battle_ui.heal_pop_up[pot_type]+query_qty)) {
				if ( parseInt(document.querySelector(query.battle_ui.heal_pop_up[pot_type]+query_qty).innerHTML) > 0 ) {
					if (pot_type == "blue") {
						clickAndNegCheck(query.battle_ui.heal_pop_up[pot_type]+">img",0,my_profile+"Clicking "+ pot_type +" pot",clickUse);
					}else if (pot_type == "green") {
						clickAndNegCheck(query.battle_ui.heal_pop_up[pot_type]+">img",0,my_profile+"Clicking "+ pot_type +" pot",clickFront);
					}else{
						console.log("pot_type unknown");
						clickCancel();
					}
				}else{
					console.log("pot qty not > 0");
					clickCancel();
				}
			}else{
				console.log("element not exist");
				clickCancel();
			}
		};
		let clickHeal = function() {
			console.log(clickHeal.name);
			clickAndCheck(query.battle_ui.heal,0,query.battle_ui.heal_pop_up[pot_type]+">img",0,my_profile+"Clicking heal pop up",clickPot,20);
		};
		let do_heal = false;
		if (pot_type=="blue" && is_front_healable.indexOf(true)>=0) {
			do_heal = true;
		}else if (pot_type=="green" && is_player_healable[char_id]) {
			do_heal = true;
		}else{
			if (typeof callback == "function") {
				callback();
			}
		}
		if (do_heal) {
			checkEl(query.battle_ui.heal,0,clickHeal);
		}
	};

	let check_exist = setInterval(function() {
		console.log("querying enemy name to appear");
		if (document.querySelector("a.btn-targeting.enemy-1:not(.invisible)") !== null || document.querySelector("a.btn-targeting.enemy-2:not(.invisible)") !== null || document.querySelector("a.btn-targeting.enemy-3:not(.invisible)") !== null){
			console.log("check width enemy name");
			if (document.querySelector("a.btn-targeting.enemy-1:not(.invisible)").getBoundingClientRect().width>0 || document.querySelector("a.btn-targeting.enemy-2:not(.invisible)").getBoundingClientRect().width>0 || document.querySelector("a.btn-targeting.enemy-3:not(.invisible)").getBoundingClientRect().width>0){
				console.log("found enemy name");
				clearInterval(check_exist);
				let is_quest_id_valid = false;
				let is_twitter_valid = false;
				try{
					console.log(rep.quest_id);
					if (rep.quest_id!==undefined) {
						is_quest_id_valid = true;
					}
				}
				catch(err){
					console.log(err.message);
				}
				console.log("is_quest_id_valid:" +(is_quest_id_valid).toString());
				try{
					console.log(rep.twitter.monster);
					if (rep.twitter.monster!==undefined) {
						is_twitter_valid = true;
					}
				}
				catch(err){
					console.log(err.message);
				}
				console.log("is_twitter_valid:" +(is_twitter_valid).toString());
				let case_battle = false;
				if (is_quest_id_valid){
					if (trials_id.indexOf(rep.quest_id)>=0) {
						case_battle = 99;
					}else{
						for (let i in quests_id) {
							if (rep.quest_id == quests_id[i] && case_battle === false) {
								case_battle = parseInt(i)+1;
							}
						}
					}
				}
				if (case_battle === false && is_twitter_valid){
					for (let i in monsters_name) {
						if (rep.twitter.monster==monsters_name[i] && case_battle === false) {
							case_battle = parseInt(i)+1;
						}
					}
				}
				console.log("case_battle:" + case_battle.toString());
				let hp = ((parseInt(rep.boss.param[0].hp) / parseInt(rep.boss.param[0].hpmax)) * 100).toString();
				if (hp.indexOf(".")>=0){
					hp = hp.substring(0,hp.indexOf("."));
				}
				battleLogic(case_battle);
			}
		}
	}, 300);
}

function clickChar(param,callback=false) {
	clickAndCheck("div.prt-member>div.btn-command-character>img.img-chara-command",param-1,".prt-command-chara.chara"+(param.toString()),0,my_profile+"Clicking "+battle.player.param[param-1].name,callback);
}

function clickBoss(boss_id,callback=false) {
	const boss_id_str = (boss_id+1).toString();
	if (battle.boss.param[boss_id] !== undefined || battle.boss.param[boss_id].alive === 1) {
		clickAndCheck('.enemy-info>.name',boss_id,'.btn-targeting.enemy-'+boss_id_str+'.lock-on',0,my_profile+'Clicking Boss '+boss_id_str,callback);
	} else {
		if (typeof callback == "function") {
			callback();
		}
	}
}

function raidFinish(rep,send_all_loot=false){
	console.log(raidFinish.name);
	reload(10);
	let cmd = [];
	let check_timer = true;
	cmd.push({"cmd":"log","level":"process","msg":message.raid.finish});

	let all_loot = {};
	let important_loot = {};
	for (const i in rep.rewards.reward_list) {
		if (rep.rewards.reward_list.hasOwnProperty(i)) {
			const loots = rep.rewards.reward_list[i];
			for (const j in loots) {
				if (loots.hasOwnProperty(j)) {
					const loot = loots[j];
					if ( ( ['weapon','summon'].indexOf(loot.type) >= 0 ) && loot.rarity=='4') {
						if (tracked_loot.indexOf(loot.name)===-1) {
							tracked_loot.push(loot.name);
						}
					}
					if (all_loot[loot.name]===undefined) {
						all_loot[loot.name] = parseInt(loot.count);
					} else {
						all_loot[loot.name] += parseInt(loot.count);
					}
				}
			}
		}
	}
	if (send_all_loot) {
		important_loot = all_loot;
	} else {
		for (const loot in all_loot) {
			if (all_loot.hasOwnProperty(loot)) {
				const qty = all_loot[loot];
				if (tracked_loot.indexOf(loot)>=0) {
					important_loot[loot] = qty;
				}
			}
		}
	}
	console.log(important_loot);
	if (Object.keys(important_loot).length > 0) {
		cmd.push({"cmd":"reward","payload":important_loot});
		cmd.push({"cmd":"log","level":"summary","msg":Object.keys(important_loot).length});
	}

	if (tracked_item !== false){
		let track_item = my_profile+"Current Status:";
		let temp_str;
		for (let item in tracked_item){
			if (tracked_item.hasOwnProperty(item)) {
				let item_qty = parseInt(tracked_item[item].number);
				let drop_qty = 0;
				if (all_loot[tracked_item[item].name] !== undefined) {
					drop_qty = all_loot[tracked_item[item].name];
				}
				temp_str = "\n- "+tracked_item[item].name+": "+(item_qty + drop_qty).toString();
				if (all_loot[tracked_item[item].name] !== undefined) {
					temp_str += '  ( +'+(drop_qty).toString()+' )';
				}
		        track_item += temp_str;
		    }
		}
		cmd.push({"cmd":"log","level":"summary","msg":track_item,"split":0});
	}
	if (check_timer){
		cmd.push({"cmd":"check_timer"});
	}
	xhr.open('POST', server);
	xhr.send(JSON.stringify(cmd));
	let gotoMain = function() {gotoHash("main");};
	checkEl(".mask",0,gotoMain);
}

function init() {
	"use strict";
	console.log(init.name);
	reload(5);
	setDebug();
	listenNetwork();
	let checkBody = setInterval(function() {
		console.log(checkBody.name);
		if(document.body !== null){
			clearInterval(checkBody);
			if(document.body.children[0].tagName == "DIV"){
				// reload(30);
				checkError();
			}else{
				console.log("DOM Error");
				reloadNow();
			}
		}
	}, 300);
}