//============================================================================== // 自動再振り by はにわ 2009/09/06 ver1.00 //============================================================================== // ■概要 // ステータス・スキルの保存と読込を行い、狩りや対人の切り替えを容易にします // // ■動作環境 // Auriga569 // Athena(たぶん動きます) // // ■仕様 // ・ステータス・スキルは1キャラにつきそれぞれ3つまで保存できる // ・ステータスの保存方法は手入力 // ・スキル操作時に装備は全て外すように制限(カードスキルを対象外とする為) // ・スキル読込前後でスキルポイントの差分がでない様にチェックしている // ・クエストスキルについて(面倒くさいので)考慮していない // ・スキル読込時にパケットバッファエラーでクライアントが強制切断される // ただ、スキルはきちんと読み込まれている // nextを挟むと解決するが、そうすると処理中に悪意のある操作を行い易くなる // ・職業変更(バード→ダンサー)について考慮していない // ・スキル読込はスキル習得条件を考慮していない // スキル習得条件を変更した場合、注意が必要 // // ■最後に // スクリプトだけで書いた場合、本スクリプトのようになります // もっとしっかり作りたい場合はサーバ本体に手を加えないといけないと思います //============================================================================== prontera.gat,164,146,4 script 自動再振り職員 861,{ //-------------------------------------------------------------------------- //CSV更新ロックを掛ける // 引数 getarg(0) :ロック対象(0:ステータス保存CSV 1:スキル保存CSV) // getarg(1) :アカウントID // 結果 'lock_st$ :ステータス保存CSVロックフラグ // 'lock_sk$ :スキル保存CSVロックフラグ //-------------------------------------------------------------------------- function Lock { set '@flg,getarg(0); set '@aid$,getarg(1) + ""; if ('@flg == 0) { //10秒間だけロックを掛けられるか試みる(100ms * 100回) for( set '@i,0; '@i < 100; set '@i,'@i+1 ) { //ロックされていなければロックする if ('lock_st$ == "0") { set 'lock_st$,'@aid$; } sleep2 100; //ロックしたユーザが自身のアカウントIDであるならロック成功 if ('lock_st$ == '@aid$) { break; } } } else if ('@flg == 1) { //10秒間だけロックを掛けられるか試みる(100ms * 100回) for( set '@i,0; '@i < 100; set '@i,'@i+1 ) { //ロックされていなければロックする if ('lock_sk$ == "0") { set 'lock_sk$,'@aid$; } sleep2 100; //ロックしたユーザが自身のアカウントIDであるならロック成功 if ('lock_sk$ == '@aid$) { break; } } } } //-------------------------------------------------------------------------- //CSV更新ロックを解除する // 引数 getarg(0) :ロック対象(0:ステータス保存CSV 1:スキル保存CSV) // 結果 'lock_st$ :ステータス保存CSVロックフラグ // 'lock_sk$ :スキル保存CSVロックフラグ //-------------------------------------------------------------------------- function UnLock { set '@flg,getarg(0); if ('@flg == 0) { set 'lock_st$,"0"; } else if ('@flg == 1) { set 'lock_sk$,"0"; } } //-------------------------------------------------------------------------- //ステータス入力 // 引数 getarg(0) :入力対象(STR/AGI/VIT/INT/DEX/LUK) // 結果 @num :入力値 //-------------------------------------------------------------------------- function InputStatus { set '@tag$,getarg(0); mes "[自動再振り職員]"; mes "設定するステータス(" + '@tag$ + ")を"; mes "入力して下さい。"; mes "(1〜" + 'status_max + ")"; next; //入力値が正しくなるまでループする while (1) { input @num; //入力値チェック if (@num < 1) { mes "[自動再振り職員]"; mes "設定するステータス(" + '@tag$ + ")を"; mes "入力して下さい。"; mes "(1〜" + 'status_max + ")"; mes "^ff00001以上にして下さい。^000000"; next; } else if (@num > 'status_max) { mes "[自動再振り職員]"; mes "設定するステータス(" + '@tag$ + ")を"; mes "入力して下さい。"; mes "(1〜" + 'status_max + ")"; mes "^ff0000" + 'status_max + "以下にして下さい。^000000"; next; } else { break; } } } //-------------------------------------------------------------------------- //メイン処理 //-------------------------------------------------------------------------- //キャラIDを保存 set '@cid,getcharid(0); //アカウントIDを保存 set '@aid,getcharid(3); mes "[自動再振り職員]"; mes "どちらを振り直しますか?"; next; switch (select("ステータス","スキル","やめる")) { case 1: //ステータス保存CSVをキャラIDで検索 set '@row,csvfind('fst$,'CST_CID,'@cid + "_1"); //ステータス保存CSVに該当データがない場合は作成する if ('@row == -1) { set '@dp$['CST_CID],'@cid + "_1"; set '@dp$['CST_STR],"1"; set '@dp$['CST_AGI],"1"; set '@dp$['CST_VIT],"1"; set '@dp$['CST_INT],"1"; set '@dp$['CST_DEX],"1"; set '@dp$['CST_LUK],"1"; set '@dp$['CST_MSG],"未設定"; Lock 0,'@aid; if ('lock_st$ == '@aid + "") { set '@row,csvgetrows('fst$); csvwritearray 'fst$,'@row,'@dp$; csvwritearray 'fst$,'@row+1,'@dp$; csvwritearray 'fst$,'@row+2,'@dp$; csvflush 'fst$; UnLock 0; } else { mes "[自動再振り職員]"; mes "混雑しているため処理が"; mes "キャンセルされました。"; next; break; } } switch (select("1:" + csvread('fst$,'@row,'CST_MSG), "2:" + csvread('fst$,'@row+1,'CST_MSG), "3:" + csvread('fst$,'@row+2,'CST_MSG), "4:やめる")) { case 4: break; default: //ステータス保存CSVからキャラデータを取得 csvreadarray 'fst$,'@row+@menu-1,'@dp; mes "[自動再振り職員]"; mes csvread('fst$,'@row+@menu-1,'CST_MSG); mes "STR:" + '@dp['CST_STR] + " AGI:" + '@dp['CST_AGI]; mes "VIT:" + '@dp['CST_VIT] + " INT:" + '@dp['CST_INT]; mes "DEX:" + '@dp['CST_DEX] + " LUK:" + '@dp['CST_LUK]; mes "--------------------------------"; mes "このステータスに振り直しますか?"; next; switch (select("振り直す","内容を再設定する","やめる")) { case 1: //ステータスリセット resetstatus; //ステータスUP for( set '@i,2; '@i <= '@dp['CST_STR]; set '@i,'@i+1 ) { statusup bStr; } for( set '@i,2; '@i <= '@dp['CST_AGI]; set '@i,'@i+1 ) { statusup bAgi; } for( set '@i,2; '@i <= '@dp['CST_VIT]; set '@i,'@i+1 ) { statusup bVit; } for( set '@i,2; '@i <= '@dp['CST_INT]; set '@i,'@i+1 ) { statusup bInt; } for( set '@i,2; '@i <= '@dp['CST_DEX]; set '@i,'@i+1 ) { statusup bDex; } for( set '@i,2; '@i <= '@dp['CST_LUK]; set '@i,'@i+1 ) { statusup bLuk; } break; case 2: set '@dp$['CST_CID],'@cid + "_1"; InputStatus "STR"; set '@dp$['CST_STR],@num; InputStatus "AGI"; set '@dp$['CST_AGI],@num; InputStatus "VIT"; set '@dp$['CST_VIT],@num; InputStatus "INT"; set '@dp$['CST_INT],@num; InputStatus "DEX"; set '@dp$['CST_DEX],@num; InputStatus "LUK"; set '@dp$['CST_LUK],@num; mes "[自動再振り職員]"; mes "設定名を入力して下さい。"; mes "(例:狩り用、Gv用)"; next; input '@dp$['CST_MSG]; Lock 0,'@aid; if ('lock_st$ == '@aid + "") { set '@row,csvfind('fst$,'CST_CID,'@cid + "_1"); csvwritearray 'fst$,'@row+@menu,'@dp$; csvflush 'fst$; Unlock 0; mes "[自動再振り職員]"; mes "再設定しました。"; next; } else { mes "[自動再振り職員]"; mes "混雑しているため処理が"; mes "キャンセルされました。"; next; } break; case 3: break; } } break; case 2: //スキル数チェック getskilllist; if (@skilllist_count > 128) { mes "[自動再振り職員]"; mes "スキルを129個以上覚えているため"; mes "本サービスはご利用できません。"; next; break; } //スキル保存CSVをキャラIDで検索 set '@row,csvfind('fsk$,'CST_CID,'@cid + "_2"); if ('@row >= 0) { csvreadarray 'fsk$,'@row+0,'@dsk_msg$[0][0]; csvreadarray 'fsk$,'@row+1,'@dsk_id[0][0]; csvreadarray 'fsk$,'@row+2,'@dsk_lv[0][0]; csvreadarray 'fsk$,'@row+3,'@dsk_msg$[1][0]; csvreadarray 'fsk$,'@row+4,'@dsk_id[1][0]; csvreadarray 'fsk$,'@row+5,'@dsk_lv[1][0]; csvreadarray 'fsk$,'@row+6,'@dsk_msg$[2][0]; csvreadarray 'fsk$,'@row+7,'@dsk_id[2][0]; csvreadarray 'fsk$,'@row+8,'@dsk_lv[2][0]; //スキル保存CSVに該当データがない場合は作成する } else { Lock 1,'@aid; if ('lock_sk$ == '@aid + "") { set '@row,csvgetrows('fsk$); for( set '@i,0; '@i < 3; set '@i,'@i+1 ) { set '@dsk_msg$['@i]['CSK_CID],'@cid + "_2"; set '@dsk_msg$['@i]['CSK_MSG],"未設定"; set '@dsk_id$['@i][0],"-"; set '@dsk_lv$['@i][0],"-"; csvwritearray 'fsk$,'@row+'@i*3+0,'@dsk_msg$['@i][0]; csvwritearray 'fsk$,'@row+'@i*3+1,'@dsk_id$['@i][0]; csvwritearray 'fsk$,'@row+'@i*3+2,'@dsk_lv$['@i][0]; } csvflush 'fsk$; Unlock 1; } else { mes "[自動再振り職員]"; mes "混雑しているため処理が"; mes "キャンセルされました。"; next; break; } } switch (select("1:" + '@dsk_msg$[0]['CSK_MSG], "2:" + '@dsk_msg$[1]['CSK_MSG], "3:" + '@dsk_msg$[2]['CSK_MSG], "4:やめる")) { case 4: break; default: set '@sel,@menu; mes "[自動再振り職員]"; mes '@dsk_msg$['@sel-1]['CSK_MSG]; mes "--------------------------------"; mes "このスキルに振り直しますか?"; next; switch (select("振り直す","現在のスキルを保存する","やめる")) { case 1: mes "[自動再振り職員]"; mes "スキルを振り直します。"; mes "装備を全て外した状態にして下さい。"; next; //装備状態チェック set '@chk,0; for( set '@i,1; '@i <= 10; set '@i,'@i+1 ) { if (getequipisequiped('@i) == 1) { set '@chk,1; } } if ('@chk == 1) { mes "[自動再振り職員]"; mes "装備は全て外れた状態ではないため"; mes "本サービスはご利用できません。"; next; break; } //スキルリスト取得 getskilllist; //使用スキルポイント合計値を計算 set '@i,0; set '@used_point,0; while (@skilllist_id['@i] != 0) { //恒久スキルのみを対象とする(カード効果によるスキルは対象外) if (@skilllist_flag == 0) { set '@used_point,'@used_point + @skilllist_lv['@i]; } set '@i,'@i+1; } //設定スキルポイント合計値を計算 set '@i,0; set '@setting_point,0; while ('@dsk_id['@sel-1]['@i] != 0) { set '@setting_point,'@setting_point + '@dsk_lv['@sel-1]['@i]; set '@i,'@i+1; } //再振り前後スキルポイント比較 if ('@used_point != '@setting_point) { mes "[自動再振り職員]"; mes "使用スキルポイントの計算が合わない為"; mes "本サービスはご利用できません。"; mes "設定時と同じ分だけスキルポイントを"; mes "使用した状態にして下さい。"; next; break; } //スキルリセット set '@i,0; while (@skilllist_id['@i] != 0) { skill @skilllist_id['@i],0,0; set '@i,'@i+1; } //スキル習得 set '@i,0; while ('@dsk_id['@sel-1]['@i] != 0) { skill '@dsk_id['@sel-1]['@i],'@dsk_lv['@sel-1]['@i],0; //パケットバッファエラー回避用(クライアント強制切断が嫌ならコメントを外す) //mes "[自動再振り職員]"; //mes "処理を実行中です。"; //mes "nextが消えるまでnextをクリックして下さい。"; //next; set '@i,'@i+1; } break; case 2: mes "[自動再振り職員]"; mes "設定名を入力して下さい。"; mes "(例:狩り用、Gv用)"; next; input '@dsk_msg$['@sel-1]['CSK_MSG]; mes "[自動再振り職員]"; mes "現在のスキルリストを読み込みます。"; mes "装備を全て外した状態にして下さい。"; next; //装備状態チェック set '@chk,0; for( set '@i,1; '@i <= 10; set '@i,'@i+1 ) { if (getequipisequiped('@i) == 1) { set '@chk,1; } } if ('@chk == 1) { mes "[自動再振り職員]"; mes "装備が全て外れた状態ではないため"; mes "本サービスはご利用できません。"; next; break; } //スキルリスト取得 getskilllist; //スキル数チェック if (@skilllist_count > 128) { mes "[自動再振り職員]"; mes "スキルを129個以上覚えているため"; mes "本サービスはご利用できません。"; next; break; } //恒久スキルのみ抽出 set '@i,0; set '@j,0; while (@skilllist_id['@i] != 0) { if (@skilllist_flag['@i] == 0) { set '@dsk_id_['@j],@skilllist_id['@i]; set '@dsk_lv_['@j],@skilllist_lv['@i]; set '@j,'@j+1; } set '@i,'@i+1; } Lock 1,'@aid; if ('lock_sk$ == '@aid + "") { csvwritearray 'fsk$,'@row+('@sel-1)*3+0,'@dsk_msg$['@sel-1][0]; csvwritearray 'fsk$,'@row+('@sel-1)*3+1,'@dsk_id_; csvwritearray 'fsk$,'@row+('@sel-1)*3+2,'@dsk_lv_; csvflush 'fsk$; Unlock 1; mes "[自動再振り職員]"; mes "現在のスキルを保存しました。"; next; } else { mes "[自動再振り職員]"; mes "混雑しているため処理が"; mes "キャンセルされました。"; next; } break; } break; } break; case 3: break; } mes "[自動再振り職員]"; mes "またご利用下さい。"; close; end; //-------------------------------------------------------------------------- //サーバ起動時処理 //-------------------------------------------------------------------------- OnInit: //ステータス保存CSV列定義 set 'CST_CID , 0; set 'CST_STR , 1; set 'CST_AGI , 2; set 'CST_VIT , 3; set 'CST_INT , 4; set 'CST_DEX , 5; set 'CST_LUK , 6; set 'CST_MSG , 7; set 'CST_CNT , 8; //スキル保存CSV列定義 set 'CSK_CID , 0; set 'CSK_MSG , 1; //ステータス保存CSV set 'fst$,"STATUS"; //スキル保存CSV set 'fsk$,"SKILL"; //ステータス最大値 set 'status_max,99; //スキル最大種類数 set 'skill_max,100; //ロックフラグを解除状態にする set 'lock_st$,"0"; set 'lock_sk$,"0"; }