bro3_tweak

unofficial minor improvements

当前为 2014-06-09 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name bro3_tweak
  3. // @version 1.5.0
  4. // @namespace http://bro3.blog90.fc2.com
  5. // @description unofficial minor improvements
  6. // @include http://*.3gokushi.jp/*
  7. // ==/UserScript==
  8.  
  9. // 簡易機能オフ(Beyondみたいな格好いい設定画面作りません or 作れません)
  10. var is_all_troop = true; // true: 兵士全数入力機能オン、false: オフ
  11. var is_trade_from_grain = true;// true: 資源三種一括変換機能オン、false: オフ
  12. var is_raid_attack = true; // true: 強襲スキルチェック機能オン、false: オフ
  13. var is_bookmark_plus = true; // true: ブックマーク編集機能オン、false: オフ
  14. var is_troop_dest = true; // true: 出兵先表示機能オン、false: オフ
  15. var is_draw_and_go = true; // true: ドローして即売却機能オン、false: オフ
  16. var is_yorozudas = true; // true: ヨロズダス関連機能オン、false: オフ
  17. var is_duel_lv_check = true; // true: ブショーダスレベルチェックオン、false: オフ
  18.  
  19.  
  20. // (未実装)同盟掲示板、ログをチェックして(もっと賢く)ピコピコする。
  21. // のは、重いかなあ。→別ツールとして作りたいな。
  22.  
  23.  
  24. // 出兵時に便利なリンクをつける。
  25. // 盾兵追加でレイアウトが乱れた。対応したら盾のないワールドでは動かなそう。
  26. // 大剣兵は上級だろうか。入れなくていいや。
  27. if (location.pathname.match(/\/facility\/castle_send_troop\.php/) && document.title.match(/出兵\(入力\)/) && is_all_troop){
  28.  
  29. var inner_tablebody = get_element('//table[@class="innerTables"]/tbody', document).snapshotItem(0)
  30. // クリア用のリンク作成
  31. var new_tr_element = document.createElement('tr');
  32. var new_span_element = document.createElement('span');
  33. new_span_element.textContent = "兵士全てクリア";
  34. new_span_element.setAttribute("onclick", "setObjectValue('infantry_count', '');setObjectValue('large_infantry_count', '');setObjectValue('shield_count', '');setObjectValue('heavy_shield_count', '');setObjectValue('spear_count', '');setObjectValue('halbert_count', '');setObjectValue('archer_count', '');setObjectValue('crossbow_count', '');setObjectValue('cavalry_count', '');setObjectValue('cavalry_guards_count', '');setObjectValue('scout_count', '');setObjectValue('cavalry_scout_count', '');setObjectValue('ram_count', '');setObjectValue('catapult_count', '');");
  35. new_span_element.style.cssText = "color: rgb(0, 0, 255); text-decoration: underline; cursor: pointer;";
  36. var new_td_element = document.createElement('td');
  37. new_td_element.setAttribute("colspan", "6");
  38. new_td_element.appendChild(new_span_element);
  39. new_tr_element.appendChild(new_td_element);
  40. // 下級兵、上級兵全部行けリンクの作成
  41. for (var i = 2; i >= 1; i--){
  42. var new_span_element = document.createElement('span');
  43. new_span_element.textContent = (i == 1 ? "槍/弓/騎兵全て" : "矛/弩/近衛兵全て");
  44. if (i == 1){
  45. var span_elements = get_element('tr/td[2]/span', inner_tablebody);
  46. }else{
  47. var span_elements = get_element('tr/td[4]/span', inner_tablebody);
  48. }
  49. var onclick_attribute = "";
  50. for (var j = 1; j < span_elements.snapshotLength; j++){//剣兵除くため1から
  51. var this_span = span_elements.snapshotItem(j);
  52. onclick_attribute += this_span.getAttribute("onclick") + ";";
  53. }
  54. new_span_element.setAttribute("onclick", onclick_attribute);
  55. new_span_element.style.cssText = "color: rgb(0, 0, 255); text-decoration: underline; cursor: pointer;";
  56. var new_td_element = document.createElement('td');
  57. new_td_element.setAttribute("colspan", "3");
  58. new_td_element.appendChild(new_span_element);
  59. new_tr_element.insertBefore(new_td_element, new_tr_element.firstElementChild);
  60. }
  61. inner_tablebody.insertBefore(new_tr_element, inner_tablebody.children[1]);
  62. }
  63.  
  64.  
  65. // 米の変換をやりやすくする。
  66. if (document.title.match(/^市場/) && is_trade_from_grain){// 拠点名に市場とか名付けないよね
  67. var head = document.getElementsByTagName('head')[0];
  68. var style = document.createElement('style');
  69. style.type = 'text/css';
  70. style.innerHTML = 'table.commonTables.w250 { width: 350px;}';
  71. head.appendChild(style);
  72. var inner_tbody = get_element('//table[@class="commonTables"]/tbody/tr/td/table/tbody', document).snapshotItem(0);
  73. if (get_element('tr', inner_tbody).snapshotLength >= 3){// (旧)確認画面では発動させない
  74. var inner_table = inner_tbody.parentNode;
  75. inner_tbody.style.display = 'none';
  76. var new_tbody_element = document.createElement('tbody');
  77. var new_tr_element = document.createElement('tr');
  78. var new_td_element = document.createElement('th');
  79. new_td_element.className = 'ttl2';
  80. new_td_element.textContent = '欲しい資源';
  81. new_tr_element.appendChild(new_td_element);
  82. var new_td_element = document.createElement('th');
  83. new_td_element.className = 'ttl2';
  84. new_td_element.textContent = '売り出す糧の量';
  85. new_tr_element.appendChild(new_td_element);
  86. var new_td_element = document.createElement('th');
  87. new_td_element.className = 'ttl2';
  88. new_td_element.textContent = '欲しい資源の量';
  89. new_tr_element.appendChild(new_td_element);
  90. new_tbody_element.appendChild(new_tr_element);
  91. var img_path = get_element('//img[contains(@src, "wood")]', document).snapshotItem(0).src;
  92. var icon_wood = img_path.replace(new RegExp('^.*' + location.hostname), '');
  93. var icon_stone = icon_wood.replace('wood', 'stone');
  94. var icon_ingot = icon_wood.replace('wood', 'ingot');
  95. var img_prop = {
  96. 101 : {"alt" : "木", "src" : icon_wood},
  97. 102 : {"alt" : "石", "src" : icon_stone},
  98. 103 : {"alt" : "鉄", "src" : icon_ingot}
  99. }
  100. for (var i = 101; i <= 103; i++){
  101. var new_tr_element = document.createElement('tr');
  102. var new_td_element = document.createElement('td');
  103. new_td_element.className = 'cost';
  104. var new_img_element = document.createElement('img');
  105. new_img_element.align = "middle";
  106. new_img_element.alt = img_prop[i]['alt'];
  107. new_img_element.src = img_prop[i]['src'];
  108. new_td_element.textContent = img_prop[i]['alt'];
  109. new_td_element.insertBefore(new_img_element, new_td_element.childNodes[0]);
  110. new_tr_element.appendChild(new_td_element);
  111. var new_td_element = document.createElement('td');
  112. var new_input_element = document.createElement('input');
  113. new_input_element.type = 'text';
  114. new_input_element.id = 'tt_id' + i;
  115. new_input_element.value = '';
  116. new_input_element.size = 8;
  117. new_input_element.name = 'tt_id' + i;
  118. new_input_element.addEventListener('change', function(){set_purchase(this);}, false);
  119. new_td_element.appendChild(new_input_element);
  120. new_tr_element.appendChild(new_td_element);
  121. var new_td_element = document.createElement('td');
  122. var new_span_element = document.createElement('span');
  123. new_span_element.className = 'buy_digit';
  124. new_span_element.id = 'tt_num_id' + i;
  125. new_span_element.textContent = '0';
  126. new_td_element.textContent = '購入する';
  127. new_td_element.insertBefore(new_span_element, new_td_element.childNodes[0]);
  128. new_tr_element.appendChild(new_td_element);
  129. new_tbody_element.appendChild(new_tr_element);
  130. inner_table.appendChild(new_tbody_element);
  131. }
  132. var new_tr_element = document.createElement('tr');
  133. var new_td_element = document.createElement('td');
  134. var new_input_element = document.createElement('input');
  135. new_input_element.type = 'submit';// テキストボックスの履歴保存のためにbuttonじゃなくsubmit
  136. new_input_element.value = 'はい';
  137. new_input_element.addEventListener('click', function(event){exec_trade(event, this);}, false);
  138. new_td_element.className = 'center';
  139. new_td_element.colSpan = 3;
  140. new_td_element.textContent = '取引してよろしいですか?';
  141. new_td_element.appendChild(new_input_element);
  142. new_tr_element.appendChild(new_td_element);
  143. new_tbody_element.appendChild(new_tr_element);
  144. var new_tr_element = document.createElement('tr');
  145. var new_td_element = document.createElement('td');
  146. new_td_element.className = 'center';
  147. new_td_element.colSpan = 3;
  148. var link_a_element = document.createElement('a');
  149. link_a_element.setAttribute("title", "元の画面");
  150. link_a_element.setAttribute("alt", "元の画面");
  151. link_a_element.href = '#';
  152. link_a_element.innerHTML = "糧以外を取引に出す(元の画面)";
  153. var listener = function(tbody){
  154. link_a_element.addEventListener('click',
  155. function (event){
  156. event.preventDefault();
  157. tbody.style.display = '';
  158. tbody.nextSibling.style.display = 'none';
  159. }, false);
  160. }
  161. listener(inner_tbody);
  162. new_td_element.appendChild(link_a_element);
  163. new_tr_element.appendChild(new_td_element);
  164. new_tbody_element.appendChild(new_tr_element);
  165. inner_table.appendChild(new_tbody_element);
  166. }
  167. }
  168.  
  169. function exec_trade(event, obj){
  170. event.preventDefault();
  171. obj.disabled = true;
  172. var trade_end = {};
  173. for (var i = 101; i <= 103; i++){
  174. trade_end[i] = 1;
  175. }
  176. //投げるべきデータ
  177. //POST
  178. //http://s5.3gokushi.jp/facility/facility.php
  179. //米100→木60
  180. //x=0&y=0&st=1&tf_id=104&tc=100&tt_id=101&change_btn=%E3%81%AF%E3%81%84
  181. //米100→石60
  182. //x=0&y=0&st=1&tf_id=104&tc=100&tt_id=102&change_btn=%E3%81%AF%E3%81%84
  183. //鉄100→米60
  184. //x=0&y=0&st=1&tf_id=103&tc=100&tt_id=104&change_btn=%E3%81%AF%E3%81%84
  185. var target_url = location.href.replace(/\?.+$/, '');
  186. var post_data_prefix = location.href.replace(target_url, '').replace(/\?([^?#]*)#?.*$/, '$1'); // この時点で x=0&y=0 みたいな感じ
  187. post_data_prefix += '&st=1&tf_id=104'; // tf_id=104 は売る資源が糧で固定
  188. var post_data_postfix = '&change_btn=%E3%81%AF%E3%81%84';
  189. for (var i = 101; i <= 103; i++){
  190. var input_element = document.getElementById('tt_id' + i);
  191. if (input_element.value){
  192. var post_data = post_data_prefix + '&tc=' + input_element.value;
  193. post_data += '&tt_id=' + i + post_data_postfix;
  194. trade_end[i] = 0;
  195. var trade = function(loop){
  196. GM_xmlhttpRequest({
  197. method: 'POST',
  198. headers: {'Content-type': 'application/x-www-form-urlencoded'},
  199. url: target_url,
  200. data: post_data,
  201. onload: function(){trade_end[loop] = 1;}
  202. });
  203. };
  204. trade(i);
  205. }
  206. }
  207. // 資源変換終了
  208. timerID = setInterval( function(){
  209. var num = 1;
  210. for (var i = 101; i <= 103; i++){
  211. num *= trade_end[i];
  212. }
  213. if(num == 1){
  214. location.reload();
  215. clearInterval(timerID);
  216. timerID = null;
  217. }
  218. },1000);
  219.  
  220. }
  221.  
  222. function set_purchase(obj){
  223. var facility_contents = get_element('//*[@class="commonTables"]', document).snapshotItem(0);
  224. var price_list = get_element('*//*[contains(text(), "%")]', facility_contents);
  225. // 通常は、
  226. //<td class="contents">60%</td>
  227. // だけど、市場繁栄・市場知識使用時は、
  228. //<td class="contents">60%<span title="スキルによるボーナス" class="color1">&nbsp;+&nbsp;3%(スキル効果)</span></td>
  229. // のようになる。ツールを作らせまいとする気迫が伝わってきます。
  230. // (龐統さんがいてすら、ボーナスが小数点を含む場合の検証できないなんて)
  231. var price = 0;
  232. for(var j=0;j<price_list.snapshotLength;j++){
  233. price += parseFloat(price_list.snapshotItem(j).textContent.replace(/^[^0-9.]*([0-9.]+)%.*$/, '$1'));
  234. }
  235. document.getElementById(obj.id.replace('tt_id', 'tt_num_id')).textContent = Math.floor(obj.value * price / 100);
  236. }
  237.  
  238.  
  239. // 引いてすぐにそのカードを売る。
  240. // 引いてすぐにそのカードを破棄する。
  241. // →保護解除だけになりました。
  242. //if (location.pathname.match(/\/busyodas\/busyodas_continuty_result\.php/) && is_draw_and_go){
  243. // 10連はひどい仕様で対応不可だった
  244. if (location.pathname.match(/\/busyodas\/busyodas_result\.php/) && is_draw_and_go){
  245. var card_list = get_element('//form[@id="busyodas"]/table/tbody/tr', document);
  246. var card = card_list.snapshotItem(0);
  247. var lock_img = get_element('td/img', card_list.snapshotItem(1));
  248. if (lock_img.snapshotLength){
  249. var card_name = get_element('td/a', card);
  250. card_name.snapshotItem(0).href.match(/cardWindow_(\d+)/);
  251. var card_no = RegExp.$1;
  252. // カーソルアイコン変わらなくてもいいよね
  253. var listener = function(k){
  254. lock_img.snapshotItem(0).addEventListener('click',
  255. function (event){deprotect(event, k, this);}, false);
  256. }
  257. listener(card_no);
  258. }
  259. }
  260. function deprotect (event, serial, obj){
  261. var mode = 'deprotect';
  262. // SSID取得
  263. var target_url = 'http://' + location.host + '/card/deck.php';
  264. var ssid = '';
  265. GM_xmlhttpRequest({
  266. method: 'GET',
  267. headers: {'Content-type': 'application/x-www-form-urlencoded'},
  268. url: target_url,
  269. onload: function(responseDetails) {
  270. var div = document.createElement('div');
  271. div.innerHTML = responseDetails.responseText;
  272. ssid = get_element('*//input[@id="ssid"]', div).snapshotItem(0).value;
  273. }
  274. });
  275. // SSID取得完了
  276. timerID = setInterval( function(){
  277. if(ssid){
  278. clearInterval(timerID);
  279. timerID = null;
  280. // 保護解除実行
  281. //投げるべきデータ
  282. //POST
  283. //http://s9.3gokushi.jp/card/deck.php
  284. //
  285. //mode=protect&target_card=(カードNo)&ssid=(セッションID)
  286. //modeはprotect/deprotect/delなど。
  287. var post_data = 'mode=' + mode + '&target_card=' + serial + '&ssid=' + ssid;
  288. var is_end = 0;
  289. GM_xmlhttpRequest({
  290. method: 'POST',
  291. headers: {'Content-type': 'application/x-www-form-urlencoded'},
  292. url: target_url,
  293. data: post_data,
  294. onload: function(){is_end = 1;}
  295. });
  296. // 保護解除終了→錠前のアイコン消しとく
  297. // 保護解除した後破棄も出品もできなくていいよね
  298. timerID = setInterval( function(){
  299. if(is_end == 1){
  300. clearInterval(timerID);
  301. timerID = null;
  302. obj.parentNode.removeChild(obj);
  303. }
  304. },1000);
  305. }
  306. },1000);
  307. }
  308.  
  309.  
  310. // (未実装)売る時に同じカードの出品具合を見る。
  311. // 自分の作った他のツールとの整合性取れないなんて格好悪すぎるしなあ。
  312. // →理由変更: トレード機能のバグがなくなるまでは作っても使い物にならない。
  313.  
  314.  
  315. // 強襲スキル使用時に強襲になってるかチェックする。
  316. if (location.pathname.match(/\/facility\/castle_send_troop\.php/) && document.title.match(/出兵\(確認\)/) && is_raid_attack){
  317. var use_skill = get_element('//div[@class="useSkill"]/p[@class="skillInfo"]', document);
  318. if (use_skill.snapshotLength){
  319. skill = use_skill.snapshotItem(0);
  320. if (skill.textContent.match(/強襲/)){
  321. var move_type = get_element('//table[@class="fighting_about"]/tbody/tr/th', document).snapshotItem(0);
  322. if (! move_type.textContent.match(/強襲/)){
  323. var form_element = get_element('//form[@name="input_troop"]', document).snapshotItem(0);
  324. var new_div_element = document.createElement('div');
  325. new_div_element.className = "infomation";
  326. var new_p_element = document.createElement('p');
  327. var new_span_element = document.createElement('span');
  328. new_span_element.className = "notice";
  329. new_span_element.innerHTML = "<strong>!! 注意 !!</strong></span><br>";
  330. new_p_element.appendChild(new_span_element);
  331. var new_span_element = document.createElement('span');
  332. new_span_element.className = "notice";
  333. new_span_element.textContent = "強襲スキルの無駄遣いです!!";
  334. new_p_element.appendChild(new_span_element);
  335. new_div_element.appendChild(new_p_element);
  336. form_element.insertBefore(new_div_element, form_element.lastElementChild);
  337. // 合成時に追加カードのスコアが多かった場合の注意書きと同じスタイルに。
  338. var link_element = get_element('//link[@media="screen,tv"]', document).snapshotItem(0);
  339. var new_link_element = link_element.cloneNode(true);
  340. new_link_element.href = new_link_element.href.replace(/\/[^/]+$/, '/union.css');
  341. var head = document.getElementsByTagName('head')[0];
  342. head.appendChild(new_link_element);
  343. }
  344. }
  345. }
  346. }
  347.  
  348.  
  349. // ブックマークを上下に移動できるようにする
  350. if (location.pathname.match(/\/user\/bookmark\.php/) && is_bookmark_plus){
  351. var bookmarks = get_element('//table[@class="tables"]', document);
  352. var items = get_element('tbody/tr/td[1][@class="center"]', bookmarks.snapshotItem(0));
  353. for (var i = 0; i < items.snapshotLength; i++){
  354. var td_element = items.snapshotItem(i);
  355. if (i == 0){
  356. var link_text_element = document.createTextNode(" "); // 本当は&nbsp;にしたい
  357. td_element.insertBefore(link_text_element, td_element.childNodes[0]);
  358. }else{
  359. var link_a_element = document.createElement('a');
  360. link_a_element.setAttribute("title", "上へ");
  361. link_a_element.setAttribute("alt", "上へ");
  362. link_a_element.href = '#';
  363. link_a_element.innerHTML = "▲";
  364. var listener = function(element){
  365. link_a_element.addEventListener('click',
  366. function (event){move_vertical(event, element, +1);}, false);
  367. }
  368. listener(td_element);
  369. td_element.insertBefore(link_a_element, td_element.childNodes[0]);
  370. }
  371. if (i == items.snapshotLength - 1){
  372. var link_text_element = document.createTextNode(" ");
  373. td_element.appendChild(link_text_element);
  374. }else{
  375. var link_a_element = document.createElement('a');
  376. link_a_element.setAttribute("title", "下へ");
  377. link_a_element.setAttribute("alt", "下へ");
  378. link_a_element.href = '#';
  379. link_a_element.innerHTML = "▼";
  380. var listener = function(element){
  381. link_a_element.addEventListener('click',
  382. function (event){move_vertical(event, element, -1);}, false);
  383. }
  384. listener(td_element);
  385. td_element.appendChild(link_a_element);
  386. }
  387. }
  388. }
  389. function move_vertical (event, element, direction){
  390. // ダブルクリック抑止はしなくても大丈夫かな
  391. event.preventDefault();
  392. var td_element = element;
  393. var tr_element = td_element.parentNode;
  394. var dst_tr_element;
  395. if (direction == 1){
  396. dst_tr_element = tr_element.previousElementSibling;
  397. }else{
  398. dst_tr_element = tr_element.nextElementSibling;
  399. }
  400. var src_bookmarks = get_element('*//input', tr_element); // ORDERED必須
  401. var dst_bookmarks = get_element('*//input', dst_tr_element);
  402. for (var i = 0; i < src_bookmarks.snapshotLength; i++){
  403. var src = src_bookmarks.snapshotItem(i);
  404. var dst = dst_bookmarks.snapshotItem(i);
  405. if (src.type != "checkbox"){
  406. src.value = [dst.value, dst.value = src.value][0];
  407. }else{
  408. src.checked = [dst.checked, dst.checked = src.checked][0];
  409. }
  410. }
  411. }
  412.  
  413.  
  414. // 出兵時に出兵先のグラフィックを表示する。
  415. if (location.pathname.match(/\/facility\/castle_send_troop\.php/) && document.title.match(/出兵\(確認\)/) && is_troop_dest){
  416. var tr_element = get_element('//table[@class="fighting_about"]/tbody/tr', document).snapshotItem(0);
  417. var village_x_value = get_element('*//input[@name="village_x_value"]', tr_element).snapshotItem(0).value;
  418. var village_y_value = get_element('*//input[@name="village_y_value"]', tr_element).snapshotItem(0).value;
  419. var map_url = "http://" + location.hostname + "/map.php?x=" + village_x_value + "&y=" + village_y_value;
  420. GM_xmlhttpRequest({
  421. method: 'GET',
  422. url: map_url,
  423. onload: function(responseDetails) {
  424. var div = document.createElement('div');
  425. div.innerHTML = responseDetails.responseText;
  426. var map_scale = get_element('*//div[@id="change-map-scale"]', div).snapshotItem(0);
  427. var li_scale = get_element('ul/li[contains(@class, "now")]', map_scale).snapshotItem(0);
  428. li_scale.className.match(/sort(\d+)/);
  429. var scale = RegExp.$1;
  430. var center = 0;
  431. if (scale == 11){
  432. center = 61;
  433. }else if (scale == 15){
  434. center = 113;
  435. }else if (scale == 21){
  436. center = 221;
  437. }else{
  438. //51x51はどうしよう。どうせ、使ってる人いないか
  439. }
  440. if (center != 0){
  441. center = "mapAll" + center;
  442. var new_td_element = document.createElement('td');
  443. //new_td_element.style.cssText = "position: relative;";
  444. var bg_img = document.createElement('img');
  445. //bg_img.src = 'data:image/gif;base64,R0lGODlhPAA8APcAANToas7fZsfjMElcEmh9Jaa%2FTqK6TaW8U6O5WHiNKYacNZOqO6nDR6G5RarCSqfAS6nBTam%2FUKe%2BUZKqKLHJP6jAPq7HQq%2FGRqzER67ESazDSqzCTaa%2FKbjPObPKQf%2F%2F%2FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAB8ALAAAAAA8ADwABwj%2FAD8IHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuXMGPKnEmzps2bOHPqzDmg54CbPn3S9KnAAQYFQl8S1SDhwAMMGCYkVUm0wIYLESREgHAAKtKeKKtmyICBgoYNGhwcWHvAwNefI4kysIDhggYLFDxQoHChQAEHEgowcDu1o9wLc41e2PBAAlS7ENRKYFAAAmGwG30meABBw1wIoDVEcPDAAQQMphkweFD5AIQMFt5i1GzBg%2B0LeCNrSDt6Awa8F%2FZSyHBBgoTTZBMUhqiZQgcPWDPkteAgwgENFzCUjpy3ru3v1C9c%2F%2BhAQTlmh5orGD1rQQMEx1wPIEAQgTUEBA8YAEbgwEH73XoZRVcF5sGlUHoeZBBBAQdM9oBT%2BvknngMaQHcXawj8pdZ8CPzGwHsPYPdAgQilhxpUW9XH2YcQUKBfBBfY1sGMM3qAlwcdYOUbhXZhsAECEGygF4kDpffcaBZgpZUGBwj2wJPyIXAAhXxlgCONHXhH3gVj4VZcU%2FRh0ACJPRHQAF8YcLVaBHrhiKN4XF61FmsW0IVBBBvUqMEDMOp1Z1amcSUlgw4QGNQACkBAWQFPzjdlbW8mCNUGq%2BH3AH0KQoAVdn4V4JgFDDrmgHjOYSABBbJ9QBR%2B%2FkkgpVORMf%2FQoKgR1DmeghFoUBZg4ul6wQERoGZXBqcx4FwHqRLk0wK1YtCkBKU9yWh%2FxOV1pV7OYWvbbxlsYF1%2B%2FFWn3wLLFbRsbe81yRoD2dWFgQfYwXYtvDHaiKVe8lHoALnnLUTUexkuWlmS7%2BoFmwZ8QZAVu3nJ%2B90GFkSQ7ENEXSWaew58GCN50tmYlYgSjPWbs3V1IFW%2FEi2721juAQrpc6il9aBrGWvnF78GXrTsVRlUd19loFlKWVNO9scAzh4RZQFxG4jK4KB07ZgWBBMn3ZMCS%2B%2BWJLFB4kjWVlWHtKym4p12ZQcKI53Ssg%2B0F9nSEajN0qqshj331XYrVa5FAQEAOw%3D%3D';
  446. bg_img.src = 'data:image/gif;base64,R0lGODlhPAA8APcAAExeFKS6RPz%2B%2FKS%2BVLTKPKS6THyOLKzGTLzOPKTCTISeNKzCPKS6XKzGRJSqLGx%2BJKy%2BVKS%2BTKzCTKzCRLTKRJSqPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAIALAAAAAA8ADwABwj%2FAAUIHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuXMGPKnEmzps2bOHPqzPkAAIAHNhX4HApAgUyhPhVMmIC0qEsHQxVIgDAggYQJUH1WUFkhagQJByJA%2BDpgadOtJZsqiHBAQgMCEuJKGEB3QAG1IrMWndCgr1sCFAA3iEA2woS7UT2qnXCAL9gGccv6vUp3wljEWjV29WkgQFzHXyWEtjpBAukEhQ80aOrAooGhBhpQmN0X7tW4oflSePtWdYQBVxu%2FTiqxqYEFCBAMPiB4gli3cq0C1h04MOS%2BCAgMd9rQ%2BALo4AcM%2F6bLgEEE1BIYJJiQgO56yHEDu20wYcF2tAg3AzhOwfJcCOwNYFhcfUHGXF8LJJCAeVaRV4BbpRHmVgTbtVbQdsdBxthXhH1VmgT9TSUbAcmVSMCJJDYAAXgNtDWXaBTYl5gA3gH2VV9UsSUgbqIxUMBYEhDQIgUlJtcXkUI%2BhiNdBZQVwHZIPRCAkOM5B0F12SnX1wEQNEAXYX4NJkFyFOA2ooq%2F4VbXb4b1RJQCD%2B74m48RvEWkbBC61d55AnKZwHIN7CneeHW6xZxyBRDQFI1RFXAjBE0CSdlvkNWJnZdVvSWihl4CCN56E5Co6IwC6VVBAX0JKCGHcqkGGJHZncYYa3WyBcrmBAxcBWAE%2Bhl10FkTUCCWgO21yBd9ZSJLIgKzuTUbciUGRhduvTKk1o%2BVdTgfc4GpFmRbYukG12zVSbBABHg9pFadLlpFoKhBCinhYF%2BpRp9kBOjla3FDVeAZY6Y9JxuRIcbV3o58ocYrqRWddRVkK5qnJpi%2FCehcXAHoZwBHUH4HmXiiQcCAgGF%2Bhi5sIEFJH4HwJXBohCdzRtJ9bPkVbImoaYxShXUSlkCZBei8EpQF%2BBiAcTBBifRM2%2F20UUAAOw%3D%3D';
  447. new_td_element.appendChild(bg_img);
  448. var center_img = document.createElement('img');
  449. var xpath = 'img[@class="' + center + '"]';
  450. var maps = get_element('*//div[@id="mapsAll"]', div).snapshotItem(0);
  451. if (get_element(xpath, maps).snapshotLength == 1){
  452. var center_img = get_element(xpath, maps).snapshotItem(0);
  453. }
  454. //center_img.style.cssText = "position: absolute;";
  455. center_img.style.cssText = "position: relative;left: -60px;top: -1px";// 妥協の産物;;
  456. new_td_element.appendChild(center_img);
  457. tr_element.appendChild(new_td_element);
  458. }
  459. }
  460. });
  461. }
  462.  
  463.  
  464. // 繰り返しクエストをまとめて受諾する
  465. if (location.pathname.match(/\/quest\//) && is_yorozudas){
  466. var attention_quest = get_element('//div[@id="questB3_table"]/table/tbody/tr[contains(@class, "attention")]', document);
  467. var copy_src;
  468. // 残ってる繰り返しクエストのidを取得する
  469. var quest_list = [];
  470.  
  471. var version; // クエストの新バージョン対応
  472. var is_exist_attention = 0;
  473.  
  474. for (var i = 0; i < attention_quest.snapshotLength; i++){
  475. if (get_element('td[contains(text(), "繰り返し")]', attention_quest.snapshotItem(i)).snapshotLength){
  476. is_exist_attention = 1;
  477. version = 0;
  478. }else if (get_element('td/a[contains(text(), "繰り返し")]', attention_quest.snapshotItem(i)).snapshotLength){
  479. is_exist_attention = 1;
  480. version = 1;
  481. }
  482. if(is_exist_attention == 1){
  483. var regexp = /takeQuest\((\d+)\)/;
  484. var quest_id = attention_quest.snapshotItem(i).innerHTML.match(regexp);
  485. if ( quest_id ){
  486. quest_list.push(quest_id[1]);
  487. if ( !copy_src ){ // 次々に上書きしていくと、classがlastつきになることがある
  488. copy_src = attention_quest.snapshotItem(i);
  489. }
  490. }
  491. }
  492. }
  493. // 一度に受諾できる行追加
  494. if ( quest_list.length > 1 ){ // 残り1つの時はまとめても意味がない
  495. var add_quest = copy_src.cloneNode(true);
  496. add_quest.children[0].firstElementChild.innerHTML = "9"; // 難易度は適当で
  497. add_quest.children[2-version].firstElementChild.href = "#"; // クエスト名のリンクはずす
  498. add_quest.children[2-version].firstElementChild.textContent
  499. = "【繰り返しクエスト】未受諾" + quest_list.length + "種";
  500. if (version == 1){
  501. add_quest.children[2-version].children[1].textContent = "寄付とか出兵とかデュエルする";
  502. }
  503. add_quest.children[3-version].textContent
  504. = add_quest.children[3-version].textContent.replace(/\+1/, '+' + quest_list.length);
  505. add_quest.children[4-version].firstElementChild.href = "#";
  506. add_quest.children[4-version].firstElementChild.removeAttribute("onclick");
  507. add_quest.children[4-version].firstElementChild.addEventListener('click', function(event){take_quest(event, quest_list);}, false);
  508. copy_src.parentNode.insertBefore(add_quest, attention_quest.snapshotItem(0));
  509. }
  510. }
  511. function take_quest(event, quest_list){ // クエスト受諾
  512. event.preventDefault();
  513. var accept_end = [];
  514. for (var i = 0 ; i < quest_list.length ; i++){
  515. //投げるべきデータ
  516. //GET
  517. //http://s1.3gokushi.jp/quest/index.php
  518. // action=take_quest&id=(クエストID)
  519. var target_url = "http://" + location.hostname + "/quest/index.php";
  520. var get_data = 'action=take_quest&id=' + quest_list[i];
  521. target_url += '?' + get_data;
  522. accept_end[i] = 0;
  523. var accept = function(loop){
  524. GM_xmlhttpRequest({
  525. method: 'GET',
  526. headers: {'Content-type': 'application/x-www-form-urlencoded'},
  527. url: target_url,
  528. onload: function(){accept_end[loop] = 1;}
  529. });
  530. }
  531. accept(i);
  532. }
  533. // 受諾完了
  534. timerID = setInterval( function(){
  535. var num = 1;
  536. for (var i = 0; i < quest_list.length; i++){
  537. num *= accept_end[i];
  538. }
  539. if(num == 1){
  540. location.reload();
  541. clearInterval(timerID);
  542. timerID = null;
  543. }
  544. },1000);
  545. }
  546. // クリアしたクエストの報酬がヨロズダス回数なら報酬を受け取る
  547. if (location.pathname.match(/\/quest\//) && !location.search.match(/\?c=1/) && is_yorozudas){
  548. var reward = get_element('//table[@summary="報酬"]/tbody/tr/td', document).snapshotItem(0);
  549. if (reward.textContent == "ヨロズダス回数"){
  550. location.href = 'http://' + location.host + '/quest/index.php?c=1';
  551. }
  552. }
  553. // クエストクリアで報酬としてヨロズダス回数を貰ったらそのままヨロズダスを引く
  554. if (location.pathname.match(/\/quest\/index\.php/) && location.search.match(/\?c=1/) && is_yorozudas){
  555. var reward = get_element('//table[@summary="報酬"]/tbody/tr/td', document).snapshotItem(0);
  556. if (reward.textContent == "ヨロズダス回数"){
  557. post_data = 'send=send&got_type=0';
  558. var target_url = 'http://' + location.host + '/reward_vendor/reward_vendor.php';
  559. GM_xmlhttpRequest({
  560. method: 'POST',
  561. headers: {'Content-type': 'application/x-www-form-urlencoded'},
  562. url: target_url,
  563. data: post_data,
  564. onload: function(responseDetails){
  565. var div = document.createElement('div');
  566. div.innerHTML = responseDetails.responseText;
  567. var reward_result;
  568. reward_result = get_element('*//table[@class="getBushodas"]/tbody/tr/td/p/strong', div);
  569. reward.textContent = reward_result.snapshotItem(0).textContent;
  570. }
  571. });
  572. }
  573. }
  574.  
  575.  
  576. // ブショーデュエル結果報告書から武将のレベルアップをチェックする
  577. if (location.pathname.match(/\/report\/detail\.php/) && is_duel_lv_check){
  578. if (get_element('//img[contains(@src, "icon_attack_pvp.gif")]', document).snapshotLength == 1){
  579. // ブショーデュエルの報告書かどうかの判定。もっとスマートにしたい
  580. var result_summary = get_element('//div[@id="gray02Wrapper"]/table/tbody[contains(tr/th/strong, "戦闘結果")]', document).snapshotItem(0);
  581. if (result_summary){ // リーグ昇格のお知らせを除外するの忘れてた
  582. var duel_busyo = get_element('tr/td/p/text()[last()]', result_summary).snapshotItem(0);
  583. var new_input_element = document.createElement('input');
  584. new_input_element.type = 'button';
  585. new_input_element.value = 'レベルアップをチェックする';
  586. new_input_element.addEventListener('click', function(event){level_check(event, this);}, false);
  587. duel_busyo.parentNode.appendChild(new_input_element);
  588. }
  589. }
  590. }
  591. function level_check(event, obj){
  592. event.preventDefault();
  593. obj.disabled = true;
  594. var target_url = 'http://' + location.host + '/card/duel_main.php';
  595. var duel_page = document.createElement('div');
  596. duel_page.innerHTML =
  597. GM_xmlhttpRequest({
  598. method: 'GET',
  599. headers: {'Content-type': 'application/x-www-form-urlencoded'},
  600. url: target_url,
  601. synchronous: true
  602. }).responseText;
  603. var busyo_list = get_element('//ul[@id="duelDeckList"]/li', duel_page);
  604. if (busyo_list.snapshotLength){
  605. var name = [];
  606. var card_no = [];
  607. var lv_flg = [];
  608. var role = [];
  609. var check_end = []; // 終了判定用フラグ
  610. for (var i = 0; i < busyo_list.snapshotLength; i++){
  611. var busyo = busyo_list.snapshotItem(i);
  612. var busyo_thumb = get_element('div[1]/a', busyo).snapshotItem(0);
  613. if (! busyo_thumb){ // 武将が外されている場合はスキップ
  614. continue;
  615. }
  616. busyo_thumb.href.match(/cardWindow_(\d+)/);
  617. card_no[i] = RegExp.$1;
  618. name[i] = busyo_thumb.firstChild.title;
  619. role[i] = get_element('div[last()]', busyo).snapshotItem(0).textContent;
  620. lv_flg[i] = 0;
  621. check_end[i] = 0;
  622. var target_url = 'http://' + location.host + '/card/status_info.php?cid=' + card_no[i];
  623. var check = function(loop){
  624. GM_xmlhttpRequest({
  625. method: 'GET',
  626. headers: {'Content-type': 'application/x-www-form-urlencoded'},
  627. url: target_url,
  628. onload: function(responseDetails) {
  629. var div = document.createElement('div');
  630. div.innerHTML = responseDetails.responseText;
  631. var header_tr = get_element('//table[@id="status_table"]/tbody/tr[th[contains(text(), "現ポイント")]]', div).snapshotItem(0);
  632. var point = header_tr.nextElementSibling.firstChild.textContent;
  633. if (point > 0){
  634. lv_flg[loop] = 1;
  635. }
  636. check_end[loop] = 1;
  637. }
  638. });
  639. };
  640. check(i);
  641. }
  642. timerID = setInterval( function(){
  643. var num = 1;
  644. for (var i = 0; i < busyo_list.snapshotLength; i++){
  645. if (! name[i]){
  646. continue;
  647. }
  648. num *= check_end[i];
  649. }
  650. if(num == 1){
  651. clearInterval(timerID);
  652. timerID = null;
  653. duel_busyo.parentNode.removeChild(new_input_element);
  654. duel_busyo.textContent = "\nデュエルデッキ:";
  655. for (var i = 0; i < busyo_list.snapshotLength; i++){
  656. if (! name[i]){
  657. continue;
  658. }
  659. if (lv_flg[i]){
  660. var link_a_element = document.createElement('a');
  661. link_a_element.setAttribute("title", name[i]);
  662. link_a_element.setAttribute("alt", name[i]);
  663. link_a_element.href = 'http://' + location.host + '/card/status_info.php?cid=' + card_no[i];
  664. link_a_element.innerHTML = name[i];
  665. duel_busyo.parentNode.appendChild(link_a_element);
  666. }else{
  667. add_text(duel_busyo.parentNode, name[i]);
  668. }
  669. add_text(duel_busyo.parentNode, "(" + role[i] + ")");
  670. add_text(duel_busyo.parentNode, "、");
  671. }
  672. duel_busyo.parentNode.lastChild.textContent =
  673. duel_busyo.parentNode.lastChild.textContent.replace(new RegExp('、$'), '');
  674. }
  675. },1000);
  676. }else{
  677. add_text(duel_busyo.parentNode, "エラーが発生しました。");
  678. }
  679.  
  680. }
  681. function add_text(element, text){
  682. if (element.lastChild.nodeName == "#text"){
  683. element.lastChild.textContent += text;
  684. }else{
  685. var text_element = document.createTextNode(text);
  686. element.appendChild(text_element);
  687. }
  688. }
  689.  
  690.  
  691. function get_element (xpath, element){
  692. return document.evaluate(xpath, element, null,
  693. XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  694. }