diff options
36 files changed, 5224 insertions, 2019 deletions
diff --git a/Changelog-SVN.txt b/Changelog-SVN.txt index f6c7813ce..0703d2cb9 100644 --- a/Changelog-SVN.txt +++ b/Changelog-SVN.txt @@ -1,5 +1,25 @@ Date Added +02/23 + * Corrected Spiral Pierce's hits in the skill_db [celest] + * Moved /common/*.o into a obj folder when compiling [celest] + * Updated core and map server to jA 1094~1115 [celest] + - Added End_of_exam's Memory Manager for detecting memory problems. + To enable remove the // in malloc.c line 11 + // #define USE_MEMMGR + - Added @npctalk and @pettalk + - Added support for jA's local zlib + - Fixed a bug with path search long + - Updated malloc.c to support Memwatch + - Added DB data loss detection + - Added db/skill_unit_db.txt + - Updated skill unit system + - Changed Waterball to the new timerskill system + ~ For more detailed logs check 'Readme-jap' (knowledge in japanese required, + obviously ^^;) + Please test if there's any skills that might have suddenly stopped working, + thanks ^^; + 02/22 * Revised New Cards, added missing effects, fixed bugs [Lupus] ~20 cards to check left 8) But in 22 Feb some new cards have been announced T__T' diff --git a/Readme-jap b/Readme-jap index 6bf23c87b..9956e4bd0 100644 --- a/Readme-jap +++ b/Readme-jap @@ -1,4 +1,2924 @@ -------------------- +//1114-fix1 by 稀枝 + +・zlibをmap-server内部に取り込めるオプションを追加 +・makeがMinGW+Msysで正常に通るよう修正 +・win32_start.batにチェック追加 + + (src/common/zlib) + trees.h - anybody's guess上のzlib_1_2_1_staticlibより取り込み + inffixed.h - 同上 + inffast.h - 同上 + crc32.h - 同上 + compress.c - 同上 + deflate.h - 同上 + inftrees.h - 同上 + zutil.c - 同上 + crc32.c - 同上 + inflate.h - 同上 + inffast.c - 同上 + trees.c - 同上 + inflate.c - 同上 + zconf.h - 同上 + deflate.c - 同上 + inftrees.c - 同上 + zutil.h - 同上 + zlib.h - 同上 + adler32.c - 同上 + Makefile - LOCALZLIBが指定されている時のみコンパイルします。 + + (src/map/) + Makefile - MinGWの場合、引数-wsock32を追加します。 + - LOCALZLIBが指定されている場合リンクします。 + - LOCALZLIBが無い場合だけzlib.aをリンクします。 + (src/char/) + Makefile - MinGWの場合、引数-wsock32を追加します。 + (src/login/) + Makefile - MinGWの場合、引数-wsock32を追加します。 + (src/common/grfio.c) - Zlibを内包した際に_WIN32と競合しないよう変更 + - zlib_win32.h zconf_win32.hを廃止 + + (./) + Makefile - #Link Zlib(NOTrecommended)、zlibを内包します。 + win32_start.bat - athena-startの半クローン化。初期起動でこけなくなるはずです。 + +-------------------- +//1113 by End_of_exam + +・linux 環境で大量のwarning が出ていたのを修正(malloc.h) +・map_quit() でcharid_db のデータを削除しないように変更(map.c thanks to lemitさん) +・pc_eventtimer(), npc_event_timer() のfree()で警告が出ていたのを修正(pc.c npc.c) +・map_eraseipport() がメモリリークしていたバグを修正(map.c) +・addtimer 命令に指定するイベント名が23文字に制限されていたのを無制限にする(pc.c) +・pc_cleareventtimer() , pc_deleventtimer() がメモリリークしていたバグを修正 + (pc.c thanks to Shinomoriさん) + + (src/common/) + malloc.h - "#undef strdup" を追加 + + (src/map/) + npc.c - npc_event_timer() 修正 + pc.c - pc_eventtimer() , pc_addeventtimer() , pc_cleareventtimer(), + pc_deleventtimer() 修正 + map.c - map_quit() , map_eraseipport() 修正 + +-------------------- +//1112 by lizorett +・PCがマップ移動中に、そのPCが設置したスキルユニットのskill_unit_onoutが呼ばれ +ない問題(map-severが落ちる可能性あり)を修正 +・バジリカを仕様に併せて修正 +・正常終了時にchar-serverがコアダンプする問題を修正 +・mobがウォータボール使用時のヒット数を修正(skill_db.txtに指定した数ヒット) +・コーティングされている場合にはストリップできないよう変更 +・属性場を使用した際、前に出していた属性場が消えないことがある問題を修正 + + (db) + skill_db.txt + - mobのウォータボールのカウント数をDBにいれた + skill_unit_db.txt + - バジリカを修正 + (char) + char.c - do_final()のchar_datのメモリ開放位置を変更 + (map) + clif.c - バジリカ時に攻撃などができないよう変更 + map.c - バジリカ位置をセルのフラグに入れるよう変更 + map.h - バジリカ用のセルフラグ追加 + mob.c - バジリカに進入できないように変更 + pc.c - 移動時(蝿など)にバジリカを消すよう修正 + skill.c - バジリカ修正 + - ウォータボール修正 + - skill_unit_onoutの呼び出しを修正 + - コーティングされている箇所はストリップ不可に変更 + +-------------------- +//1111 by Toshi^2 +・pc系mobに転生&養子を指定できるように変更。 + db/mob_avail.txtに説明文を追加したので、それを参照してください。 + + (db) + mob_avail.txt - 引数の説明を追加。 + (src/map) + clif.c - clif_mob0078() clif_mob007b() clif_pet0078() clif_pet007b() 修正 + mob.c - mob_readdb_mobavail() 修正 + mob.h - 構造体mob_dbに「short trans」を追加、mob_availのtransフラグを格納。 + +-------------------- +//1110 by lizorett +・ユニット系スキル(ニュマ、ダンス等)でmap_server.exeが落ちる問題を修正 + (トレースではskill_unit_onplace/skill_unit_onoutで落ちる) +・サンクチュアリの人数カウント方法を変更(本鯖仕様) +・マグヌスの範囲を広げ、使用したユニットが削除されるようにする(本鯖仕様) +・デボーションの距離が短くなる問題を修正(バグ報告スレッド part8 >>15) +・デボーションでnullpoが出る問題を修正 +・mobのインティミデイトが成功するとmap-serverが落ちる問題を修正(バグ報告スレッ +ド part8 >>42) +・ウォーターボールの仕様を本鯖に近づける(水場が少ない場合にはhit数が減る、 +デリュージ上で実行するとユニットが欠ける) +・ファーマシーの製造成功確率のコードを変更 + + (db) + skill_unit_db.txt + - ユニットID/配置などをdb化しています + (src/map) + map.h - skill_unit_groupのメンバ変更 + mob.c - 移動時にスキルユニット判断(skill_unit_out_all/skill_unit_move) + を追加 + - 足元置き/重複置き判断を変更 + pc.c - 移動時にスキルユニット判断(同上)を追加 + - 無敵時間が終わる際にスキルユニット判断(同上)を追加 + skill.h - skill_dbの参照関数をdefineに変更 + - スキル配置を入れるskill_unit_layout構造体を定義 + - SC_WATERBALL削除 + skill.c - unit_idをdb化(skill_unit_db.txt) + - スキルユニットのレイアウトを起動時に定義 + - 移動時にスキルユニット判断(同上)を追加 + - 足元置き/重複置き判断を変更 + - スキルユニットの移動処理を変更 + - デボーションの修正 + - mobのインティミデイトで落ちる問題を修正 + - ウォータボールの仕様変更 + status.c- SC_WATERBALLの処理を削除 + +-------------------- +//1109 by End_of_exam + +1108に引き続きメモリリークのバグ修正です。2つ共に深刻なバグなので、 +最新版に更新しない方でも修正することをおすすめします。 + +・ペットが床にアイテムを落とす時、ペットを卵に戻す時にメモリリークが発生 + していたバグを修正。(pet.c) + +・キャラクター依存一時変数の利用したキャラがログアウトするとメモリリークが + 発生していたバグを修正(map.c) + + (src/map) + map.c - map_quit() 修正 + pet.c - pet_remove_map(), pet_return_egg() pet_lootitem_drop() 修正 + +-------------------- +//1108 by End_of_exam + +・以前作ったメモリマネージャーを統合。(malloc.c core.c) + 有効にするには、malloc.c内部のコメントを外す必要があります。開発に協力して + 頂ける方は、メモリマネージャを有効にして、チェック結果(map-server.logなど)を + アップロードしてくれると助かります。 + + 1. guild.c がコンパイルエラーになったので修正(guild.c) + 2. pet.c がメモリ解放し忘れていたので、do_final_pet() を追加(pet.c) + 3. do_final_socket を追加して、終了時に全ての接続を切断する(socket.c) + 4. deplicate の元スクリプトが終了時にfreeされないバグを修正(npc.c) + 5. do_final_script で開放されないメモリがあるバグを修正(script.c) + 6. do_init_*** の呼ばれる順番がおかしかったのを修正(map.c) + 7. イベント名が重複したときにメッセージを出すように変更(npc.c) + 8. map_quit() 内部でcharid_db をfreeし忘れているバグを修正(map.c) + + 特に8.は最重要で、キャラがログアウトする度にメモリリークが発生するという、 + 最悪な結果になっていました。気になる方は修正しておきましょう。 + +・delete_session でNULLチェックを怠っていたバグを修正(socket.c) +・chrif_disconnect_sub でdelete_session を呼ぶように変更(chrif.c) +・マルチラインコメント(/* 〜 */)の解析を忘れていたバグを修正(npc.c) +・銀行などのNPC でZenyがMAX_ZENYにならないバグを修正(pc.c) +・1107の製造確率が一部消されていたのを修正(skill.c thanks to lizorettさん) +・セージ転職試験のイベントが衝突を起こしていたのを修正(npc.c) + npc_parse_script : dup event jobsage_2nd::OnTimer150000 + npc_parse_script : dup event jobsage_2nd::OnTimer30000 + npc_parse_script : dup event jobsage_success::OnTimer7000 + npc_parse_script : dup event jobsage_success::OnTimer3000 + + (src/common) + core.c - do_init_memmgr() 追加 + malloc.c - メモリマネージャの追加 + malloc.h - メモリマネージャの追加 + socket.c - delete_sessionのバグ、do_final_socketの追加 + + (src/map) + chrif.c - chrif_disconnect_sub() を修正 + guild.c - guild_recv_info(), guild_castledataloadack() 修正 + map.c - map_quit() のメモリリーク、do_final,do_init 修正 + npc.c - npc_parse_script_line() , npc_parse_script() 他修正 + pc.c - pc_setparam() 修正 + pet.c - do_final_pet() 追加 + pet.h - do_final_pet() 追加 + script.c - do_init_script(), do_final_script() 修正 + skill.c - skill_produce_mix() 修正 + +-------------------- +//1107 by code +・@npctalk, @pettalkコマンド追加 +・ダメージの遅延を実装 +・@mesを全体発言に修正 +・ファーマシーの製造成功確率修正 +・@storageで倉庫が二重で開くことがないよう修正 +・scriptに globalmes, getmapmobs 関数を追加 + + (/src/map) + atcommand.c + atcommand.h + battle.c + clif.c + clif.h + npc.c + npc.h + script.c + skill.c + storage.c + +-------------------- +//1106 by sylpheed + +・item_rate_details:1が動かなかったのを修正 + + (src/map/) + mob.c + +-------------------- +//1105 by End_of_exam + +・1101のマップの再分配が上手くいかないバグを修正(char.c thanks to Mystleさん) + + (src/char/) + char.c - parse_frommap() 修正 + +-------------------- +//1104 by nameless +・BCC32のコンパイルオプションなどの最適化 +・BCC32/VC++で最適な最適化オプションを見つけるためのベンチ +・bcc32_clean.batとbcc32_make.batを統合、クリーンビルドの失敗をしないように。 + +※P4だからとかOpteronだから特定オプションで早いということではないようです。 +※P4でもロットによっては-5が最適だったり-3 -O2が最適だったりするものがあるようです +※思い込みでオプションをつけないようにするために作りました。 +※少しでもレスポンスを上げて運用したいという人は活用してください。 + + (/) + bcc32_make.bat + + 最適化オプションの追加と警告メッセージで深刻ではないものを + 完全に表示しないように設定、bcc32_clean.batをmakeに統合した + ので確実にクリーンビルドできるようになりました + + bench.bat + bench.c + + 最適なコンパイルオプションを見つけるためのベンチです。 + bench.batでコンパイル&実行が行われます。 + 結果はbench.txtに格納されますので数値の一番小さいものを選ん + でbcc32_make.batの23行目に追加・修正してあげてください。 + ※初期状態ではbcc32用になっていますので +-------------------- +//1103 by End_of_exam + +・char_athena.conf のdefault_map_typeが0 になっている時に、PVPガイドで + セーブした後、PVPエリア内でログアウトしたキャラがログインできなくなる + バグを修正。(npc_etc_pvp.txt) 多くの方々からの情報提供感謝します。 + (npc_etc_pvp.txt 内部の ".gat" の付け忘れと、このミスに対応していない + pc.c のバグです。このパッチを当てないでこのバグを修正したい場合、 + 添付した修正ファイルを参考にしながら、npc_etc_pvp.txtに".gat"を + 付加してください。) + +・do_final内部で不正な処理を行う場合があるのを修正(map.c thanks to lizorettさん) +・マップキャッシュの読み込みに失敗したときにメモリリークしていたバグを修正(map.c) + + (src/map) + pc.c - pc_setsavepoint() 修正 + map.c - do_final(), map_cache_read() 修正 + + (src/char) + char.c - search_mapserver() , parse_char() 修正 + + (script/npc/etc) + npc_etc_pvp.txt - ".gat" を付加する + +-------------------- +//1102 by 人柱さんA +・バグ報告スレ >>35-37にあった修正版 + 詳しいことはスレを見てください + (src/map) + pc.c + +-------------------- +//1101 by End_of_exam + +・socket関連の修正(socket.c socket.h) + + 1. FIFO関連をfd が不正(fd<=0)の時にも正常に動作するように変更 + 2. socket.h の内部を色々と整理 + 3. make_connection() が接続に失敗した時にエラーを返さないバグを修正 + その変更に合わせて、chrif.c check_connect_char_server() , char.c + check_connect_login_server() を修正。これでサーバーゾンビ化のバグは + 解決したと思いますが、再発したら報告をお願いします。 + +・char - map 間のコネクションを見直し(char.c chrif.c map.c map.h) + + 1. char - map 間のコネクションが切れたら、map 鯖に接続しているキャラを + 全て切断するようにする。これは、同期を取るのが難しいのと、char鯖との + 通信が必要な処理(パーティ、ギルド、ペット他)ができなくなるためです。 + 2. 複数のmap 鯖で同じマップを担当することがあるバグを修正 + 3. map 鯖の割り当て方法の見直し + 複数のmap 鯖で同じマップを読み込めば、どれか1つが落ちている時でも、 + 正常なmap 鯖にログインできるようになりました。例えば、同じマップを + map鯖AとBに読み込ませておけば、Aが落ちている時にはBに、Bが落ちている + 時にはAに転送されます。ただし、優先順位の指定はまだ出来てないので、 + 1つのmap 鯖に人数が集中しすぎる可能性があります。 + + (src/map) + chrif.c - map 鯖の割り当て方法の見直し + map.c - map 鯖の割り当て方法の見直し + map.h - map 鯖の割り当て方法の見直し + + (src/char) + char.c - map 鯖の割り当て方法の見直し + + (src/common) + socket.c - 色々修正(上記参照) + socket.h - 色々修正(上記参照) + +-------------------- +//1100 by nyankochan +・1098の修正 + (src/map) + pc.c + +-------------------- +//1099 by End_of_exam + +・mapflag nosave が不正な時に起動を中断させるようにする(npc.c) +・pc_autosave が呼ばれる回数が異常に高くなるバグを修正(pc.c) + +pc_autosave() の内部が、 + +> interval = autosave_interval/(clif_countusers()+1); +> if(interval <= 0) +> interval = 1; + +という風になっているので、1マップサーバーに200人のキャラが接続してると、 +autosave_interval(def:15 * 1000) / 200 = 0.075 秒ごとに関数が呼ばれます。 +さすがにこの状態だとchar鯖が厳しくなるので、関数を呼び出す最小間隔を +0.2 秒に変更しました。 + + (src/map) + pc.c - pc_autosave が呼ばれる回数が異常に高くなるバグを修正 + npc.c - mapflag nosave が不正な時に起動を中断させる + +-------------------- +//1098 by nyankochan +・入手装備品の個数1固定 + (src/map) + pc.c + +-------------------- +//1097 by End_of_exam + +主にバグ修正です。バグ報告してくれた皆様に感謝、感謝。 + +・Zeny増殖対策(pc.c trade.c script.c) + 1. 交換、pc_setparam でMAX_ZENY を超える場合があるバグを修正 + 2. スクリプトにオーバーフロー対策を追加 + +・ログイン成功時・アカウント変数更新時に無条件にmmo_auth_sync を + 呼んでいたのをタイマーを使用した定期更新に変更(login.c login_athena.conf) + +・db関係にバグが潜んでいる模様なので、チェック機構を追加する(db.c db.h) + 一部アカウントのみログイン不可、倉庫ロスト、@whoで表示されるキャラが + 一部消えるなどのバグの原因がdb関連にある模様です。 + 「db_foreach : data lost %d of %d item(s)」というメッセージが表示 + された場合はバグがある(dbに入っているはずのデータが消えた)ので、 + 報告をお願いします。 + +・ある方法で通常より強いキャラが作れてしまうバグの修正(char.c) +・ギルドの役職名に不正な文字が使えるバグを修正(int_guild.c) +・スクリプト内で0での除算時が起こった時にINT_MAXを返すようにする(script.c) + + (conf/) + login_athena.conf - autosave_time の追加 + + (src/common) + db.h - チェック機構の追加 + db.c - チェック機構の追加 + + (src/login) + login.c - mmo_auth_sync にタイマーを適用 + + (src/char) + char.c - 通常より強いキャラが作れてしまうバグの修正 + int_guild.c - ギルドの役職名に不正な文字が使えるバグを修正 + + (src/map) + trade.c - MAX_ZENY を超える場合があるバグを修正 + pc.c - MAX_ZENY を超える場合があるバグを修正 + script.c - オーバーフロー対策、0での除算時の処理を追加 + +-------------------- +//1096 by lizorett +・壁越しにスキルが撃ててしまうバグを修正(バグ報告スレッド part8 >>28) + + (src/map) + path.c - 壁越しにスキルが撃ててしまうバグを修正 + +-------------------- +//1095 by lizorett +・スクリプトのエスケープ判断を変更 +・スキルユニットグループのgroup_idの範囲を変更 +・skill_unitsetting()で全てのスキルでskill_get_time()を使用するよう変更 +・サイトラッシャーをユニットスキルから範囲攻撃魔法に変更(本鯖仕様) + + (src/map) + skill.c - skill_unitgrouptickset_* で skill_id/group_idが重ならないよう + にgroup_idの範囲を制限 + - SkillStatusChangeTableにSC_SAFETYWALL,SC_PNEUMA追加 + - skill_unitsetting()で全てのスキルでskill_get_time()を使用する + よう変更 + - サイトラッシャーを範囲攻撃魔法に変更 + npc.c - エスケープ判断をparse_simpleexpr()と同様にし、全角判断を削除 + (db) + skill_cast_db.txt + - TS/MS/LoV/FN/SG/HD/GXにupkeep_timeを設定 + +-------------------- +//1094 by End_of_exam + +・サブルーチン呼び出し構文の追加(script.c npc.c npc_convertlabel_db()) +・逆アセンブル処理の追加(script.c , DEBUG_DISASM を有効にしてください。) +・switch の一時変数消去位置を変更(script.c) +・RERUNLINEの衝動が怪しかったので修正(script.c / h , map.h) +・ソースを読みやすくするためにbuildin_*をファイル最後に移動(script.c) +・新しく加わった構文のサンプルとして「ハノイの塔」を追加(npc_test_hanoi.txt) +・buildin_getitemname 修正(script.c , 質問スレッド Part14 >>129-130) + +・bcc でコンパイルした時に落ちるバグを修正(map.c map_id2bl 内部) +・Windowsでコンパイルした時に、gettick()のキャッシュが無効になっていたのを + 修正(timer.c , thanks to Shinomori) + + (src/common) + timer.c gettick() のバグ修正 + + (src/map) + script.c 色々変更(上記参照) + script.h struct script_state 修正 + npc.c npc_convertlabel_db() で落ちるのを修正 + map.c map_id2bl() を修正(落ちるのはbcc だけ?) + map.h map_session_data 修正 + + (doc/) + script_ref.txt function 構文の追加 + + (script/sample/) + npc_test_hanoi.txt ハノイの塔 + +-------------------- +//1093 by いど + +・サーバースナップショット + +-------------------- +//1092 by lizorett +・遠距離攻撃のパス検索アルゴリズムを本鯖と同じになるよう変更 +・ストームガスト、ロードオブヴァーミリオンを重ねた場合、片方からだけダメージを +受けるよう修正(仕様が不明なので先に見つけたユニットから攻撃するようにしています) +・アイテムが一つしかない場合、アイテムを使用してもエフェクトが表示されない問題 +を修正 +・セーフティーウォール使用時にアドレス不正となる場合がある問題を修正 +・map_getcell/map_setcellの仕様変更 +・1085のビットマップ対応の痕跡の消去 +・1088のアイスウォールの変更を巻き戻し(本鯖に合わせる) +・全角判断(npc.c)を修正(For English User Forum >>54) + + (注意) map_athena.confのマップキャッシュ指定を行うパラメータ名を変更しています + + (conf) + map_athena.conf - read_map_from_bitmapをread_map_from_cache に変更 + - map_bitmap_pathをmap_cache_fileに変更 + (src/map) + map.h - セルタイプ名称変更(CELL_CHKHIGH,CELL_CHKTYPE)、 + 削除(CELL_SET*) + - skill_unit_group_ticksetメンバ名変更(group_id -> id) + - ビットマップ関連の記述の痕跡を削除 + map.c - map_getcell() セルタイプ名称変更と若干のコード変更 + - map_setcell()を1084以前の仕様に戻し、CELL_SETNPCの + フラグを追加 + - map_cache関連の細かな修正 + npc.c - 全角判断(is_zenkaku)を正確に行うよう変更 + - map_getcell()のセルタイプ名称変更に追従 + pc.c - アイテムが一つしかない場合、使用時のエフェクトが表示 + されない問題を修正 + - map_getcell()のセルタイプ名称変更に追従 + skill.c - ストームガスト、ロードオブヴァーミリオンを重ねた場合 + 片方からだけダメージを受けるよう修正 + - セーフティーウォール使用時にアドレス不正となる場合が + ある問題を修正 + - map_getcell()のセルタイプ名称変更に追従 + skill.h - 関数定義変更 + path.c - 遠距離攻撃のパス検索処理を追加(path_search_long) + - map_getcell()のセルタイプ名称変更に追従 + battle.c - 遠距離攻撃のパス検索を使用するよう変更 + +-------------------- +//1091 by End_of_exam + +** 注意 ** + + 今回のパッチは改造内容が複雑なので、導入は慎重に行ってください。 + status.c / h への分離は、関数名の置き換えだけに留めたつもりですが、 + 思わぬバグが潜んでいる可能性があります。 + +・スパゲティ対策の一環として、ステータス計算、状態異常に関わる部分を + status.c / h として分離。battle.c から39KB程 , skill.c から41KB程 , + pc.c から38KB程移動できました。少々強引ですが、スキル使用や攻撃などの + 処理の流れをつかみやすくするためには、battle.c / skill.c の中身を + 減らす必要があると考えたためです。 + + battle_get_* => status_get_* + skill_status_change_* => status_change_* + pc_calcstatus => status_calc_pc + pc_calc_sigma => status_calc_sigma + pc_getrefinebonus => status_getrefinebonus + pc_percentrefinery => status_percentrefinery + +・battle.c , script.c の巻き戻りを戻す +・npc.c の怪しい変更を戻し、きちんとNUL を付け加えるようにする +・script.c のミスを直す(jump_non_zero => jump_zero 意味が逆になってました…) +・skill.c の武器修理 のコメントミスを修正 +・WIN32でコンパイルした時、最大接続人数が60人程に制限されていたバグを修正 + + (/) + athena.dsw , athena.dsp , bcc32_make.bat , src/login/login.dsp + src/char/char.dsp , src/map/map.dsp + コンパイル条件の変更 + + (src/map/) + 上の分離に合わせてコンパイルエラーの出ないように修正 + +-------------------- +//1090 by Sapientia +・チャットの便利さのために叫ぶ追加 (ギルドチャットと区分するためにウェチギシの前に [叫ぶこと]が付き) +・atcomand_athena.conf で onlymes を 0で設定して皆使うように活性化 + オリジナルなのでデフォルトで GMだけ使うことができるように設定しました. +・@mes [言うこと] で使用 + + (src/map) + atcommand.c atcommand_charkami 追加 + atcommand.h + clif.c clif_onlymessage 追加 + clif.h + (src/conf) + atcommand_athena.conf onlymes 追加 + help.txt @mes 説明追加 + + +-------------------- +//1089 by 聖 +・VC.NET2003でコンパイルすると大量に警告が出るのを修正 +・その他バッファオーバーフロー等の細かいバグ修正 + + (src/char) + int_guild.c 警告箇所を修正 + + (src/map) + atcommand.c, battle.c, clif.c, itemdb.c, pc.c, pc.h, script.c, skill.c + 警告箇所を修正 + npc.c 警告箇所とバッファオーバーフロー修正 + +-------------------- +//1088 by Sapientia +・ウィザドスキル Icewall このキャラクターやモンスター足もとに設置されることを防止 +・ロードナイトスキル Berserk 使用の時 HPが 1/3になれば回復するバグ修正 + + (src/map) + pc.c Berserk 修正 + skill.c Icewall 修正 + +-------------------- +//1087 by End_of_exam + +・マップキャッシュに圧縮機能を追加(1MB程に縮まるようです) +・npc.c の巻き戻りを修正(質問スレッド Part14 , 111) +・map_athena.conf のコメントアウトを修正(Athena雑談スレッドPart7 , 146) +・Windows 用の起動スクリプトを追加してみる(eAthena のを元に改造) + + (/) + win32_start.bat Windows 用の起動ファイル + + (src/map) + map.c 圧縮機能の追加 + npc.c 巻き戻りを修正 + + (src/common) + grfio.c decode_zip , encode_zip のエクスポート + grfio.h decode_zip , encode_zip のエクスポート + + (conf/) + map_athena.conf 修正 + +-------------------- +//1086 by End_of_exam + +主に1085のバグ修正だったりもします。 +「てめー、1から書き直しやがって」という突っ込みだけは勘弁してくださいませ。 + +・データ構造の大変更(map.c) + マップを削除&追加しても正しく動くように変更 + マップキャッシュ作成中に強制終了すると再起動時に不安定になるバグを修正 + 圧縮フラグの追加(需要あるのか不明。compressを真にすると、現在のソースで + 読めなくなります。) + +・なんか衝動があやしすぎるので、ビットマップ処理を撤廃する(map.c map.h) + npc_touch_areanpc : some bug がたくさん出てくる -> 原因不明? + 恐らく通行可能判定が正しく設定されていないっぽいんですが謎です。 + #read_map_from_bitmap の設定を省くとログイン時に落ちるバグを修正 + +・キャッシュ内に全てのマップがあれば、grf 無しでも動作するように変更。(grfio.c map.c) + + (src/map) + map.c バグ修正他 + map.h バグ修正他 + + (src/common) + grfio.c ファイルが見つからない時にexit を呼ばないように修正 + +-------------------- +//1085 by zalem +・マップデータの読み込みはビットマップファイルから行なえるような機能追加 + + grfファイルから一度ビットマップファイルを作成して以後はその + 作成されたビットマップフォーマットのファイルからマップ情報を読み込む + という方法を採ることによって、map-serverが立ち上がる時マップ情報を読み取る + のに掛かる時間がほとんどなくなる、また1intに32個のセル情報が格納できるの + で、map情報に関するメモリ使用量も3割り近くまで減るので(そのかわりに + ある程度CPUの負担が大きくなる)、追加してみた。 + conf/map_athena.confのread_map_from_bitmapオプションで利用する + かどうかを指定でき、その下にあるmap_bitmap_pathでファイル名を変更する + (デフォルトでdb/map.info) + まだテスト段階なので、導入はご慎重に(一応Linuxで、いろいろと + テストしてみたが...) + +・map_getcell()に4番目引数の追加とmap_setcell()の4番目引数の変更 + + 関数の利用意図がわかりやすいように、そしてこれからの変更を容易にする + ために、map_getcell()とmap_setcell()のそれぞれ4番目の引数を追加、変更してみた、 + map_getcell()の4番目の引数はmap.hで定義されてるCELL_CHK列挙型、map_setcell() + の4番目の引数はmap.hで定義されてるCELL_SET列挙型をとるように変更.また、上の + Featureに対応するため、map_getcell()をポインタに変更した。 + + 主な変更点: + + src/map/map.h read_gat(),read_gatp()マクロの変更 + 列挙型 CELL_CHK,CELL_SETを追加,map_getcell(),map_setcel()用 + map_data構造体にメンバーint* gat_fileused[MAX_CELL_TYPE+2]追加 + src/map/map.c map_getcell()を関数型ポインタに変更,map_getcellp()をread_gatp() + のために追加,実際に下の四つの関数のどっちに指すかはmap_read_flagによる + map_getcell_gat(),map_getcell_bitmap() 追加 + map_getcellp_gat(),map_getcellp_bitmap() 追加 + map_setcell() 変更 + map_createbitmap() 追加 + map_readmapfromfile() 追加 + map_readallmap() 変更 + map_config_read() 変更 + do_final() 変更 + 以下の*.cファイル内のmap_getcell(),map_setcell(),read_gat(),read_gatp()を呼出した部分をすべて変更 + src/map/atcommand.c + src/map/mob.c + src/map/npc.c + src/map/path.c + src/map/pc.c + src/map/pet.c + src/map/skill.c + + conf/map_athena.conf read_map_from_bitmap,map_bitmap_path 追加 + +-------------------- +//1084 by lizorett +・経験値獲得のバグ修正(バグ報告スレッド part7 >>134) + (src/map) + mob.c 経験値計算修正 + +-------------------- +//1083 by End_of_exam special thanks to lizorettさん +・ソケットのデストラクタ処理の追加 + (common/socket.c common/socket.h login/login.c char/char.c map/clif.c map/chrif.c) + ソケットを閉じる時の処理の流れが変更になります。今までソケットを閉じる場合は、 + まずsession[fd]->eof を真にした後、パーズルーチン内で後処理(メモリ解放など) + していました。ですが、close(fd); が2重に実行されてサーバーが落ちるなどの + バグが発生していたり、処理の流れがつかみにくいといった理由から、socket.c 内部で + 全て処理するように変更しました。ソケットを閉じる時の主な流れは次の通りです。 + + 1. ソース内からsession[fd]->eof = 1; をする + 2. socket.c 内からsession[fd]->destruct() が呼ばれる + 3. メモリの解放&後処理(socket.c delete_session内部) + + close(fd) は、session[fd]->eof = 1; に置き換えました(#define)。 + また、delete_session() を明示的に呼ぶ必要はありません。 + +・マップ鯖分配時のアイテムdupe問題修正(map/map.c map/pc.c map/chrif.c) + ソケット切断時に倉庫データのキャッシュを消すように変更 + 2重ログイン時にマップサーバーが違った場合にも切断できるように修正 + +・古いバージョンでログインした時にmap鯖が落ちるバグを修正(map/clif.c) + clif_parse() 内部 + + if(packet_db[cmd].len==0) { + -> if(cmd<MAX_PACKET_DB && packet_db[cmd].len==0) { + +・gcc でコンパイルした時にtimer.c でwarning が出たのを修正(common/timer.c) + timer.c:116: warning: `check_timer_heap' defined but not used + + (src/common/) + socket.c ソケットのデストラクタ処理を追加 + socket.h ソケットのデストラクタ処理を追加 + timer.c warning 修正 + + (src/map/) + clif.c ソケットのデストラクタ処理を追加 + chrif.c ソケットのデストラクタ処理を追加 + map.c マップ鯖分配時のアイテムdupe問題修正 + pc.c マップ鯖分配時のアイテムdupe問題修正 + + (src/char/) + char.c ソケットのデストラクタ処理を追加 + + (src/login/) + login.c ソケットのデストラクタ処理を追加 + +-------------------- +//1082 by lizorett (2004/12/18) special thanks to 名無し様@g@me +・白刃取りをボスに無効に変更 +・1079の変更部分にNULLチェックを追加 +・カードの効果が乗らないスキルにエンチャントデッドリーポイズン効果が乗らないよ + うに変更 +・エンチャントデッドリーポイズンの効果に左手が載らないように変更 +・サクリファイスを実装 +・ストームガストのノックバックがスキル指定位置を中心とするよう変更 +・スキルの射程距離から1セル離れた場所を指定してスキルを使うと何も起こらない問題 + を修正 +・経験値の配分を修正(ダメージを与えた人がいない場合や、毒ダメージがある場合に経 + 験値が少なくなっていた) +・装備していない箇所へのストリップスキルが失敗するよう変更 +・パッチアップスレッド Part 6?の>>116,>>125,>>126 のファイルを念のためマージ + + (db/) + skill_db.txt, skill_cast_db.txt, skill_require_db.txt + - サクリファイスの記述を修正/追加 + (src/map/) + battle.c - エンチャントデッドリーポイズンの変更 + - サクリファイスの実装 + - ストームガストのノックバック方向を変更 + - 白刃取りをボスに無効に変更 + skill.h - SC_SACRIFICEを追加 + skill.c - サクリファイスの実装 + - skill_castend_damage_id()のMG_FROSTDIVER/MG_STONECURSEに + NULLチェックを追加 + mob.c - 経験値の配分を修正 + script.c - 個別に出されていたファイルをマージ(>>125) + npc.c - 個別に出されていたファイルをマージ(>>126) + (src/common) + core.c - 個別に出されていたファイルをマージ(>>116) + +-------------------- +//1081 by End_of_exam +・「ループ構文の方も実装してください」という要望を貰ったので、 + for , while , do - while 構文を導入。個人的に余り需要は無いと思うのですが…。 + +・elseが完全に解析できてなかったバグを修正。 +・switch のbreak; が場所によってはコンパイルエラーになるバグを修正。 + + (src/map/) + script.c : 構文を拡張。色々整理。 + + (doc/) + script_ref.txt : 上の修正に合わせて変更。 + +-------------------- +//1080 by End_of_exam + +・スクリプトを if - else if - else 構文 , switch 構文に対応させました。 + 多重ネストが可能ですので、今までより見やすいスクリプトが書けると思います。 + if(aa) { aaa(); } else if(bb) { cc; if(dd) { ee() } else { ff(); } } + それに伴い、__ から始まる変数やラベルを用いると、不都合が生じる可能性があります。 + +・スクリプトに新しい関数(select関数・menu命令の関数版)を追加しました。 + + (src/map/) + script.c : 構文を拡張 + npc.c : npc_perse_script の修正( { , } のネストに対応 ) + + (script/) + npc/town/npc_town_alberta.txt : 一カ所 goto が抜けてたので修正 + sample/npc_debug_pota.txt : switch , select を使って書き直し + (デバッグに使わせて貰いました) + + (doc/) + script_ref.txt : 上の修正に合わせて変更 +-------------------- +//1079 by Yuuki +・石化中にストーンカースを使うと石化解除 +・FDでスキル追加効果を使うと氷化中ダメージ判定で先に割れてもう一度氷化判定がくるのでスキル追加効果つかわず +・BBで睡眠石化氷化が割れないバグの修正(独自のダメージ判定使ってたので消して正規のダメージ判定に戻した) +・ディレイ0のスキルにadelay/2追加(G鯖でTS使って検証した結果最もこれが近かった通常攻撃よりはやかったので) + + (src/map) + skill.c + +-------------------- +//1078 by End_of_exam + +・Visual C++ 6.0 / bcc32 でコンパイル出来るように修正(別途zlib.dll が必要) +・1074は欠番にします。色々とご迷惑をかけた事をお詫びします。 + +** 注意 ** + 今回のバージョンの完全な動作確認はしていません(人柱版扱いにしてください)。 + 本格的な運用に踏み切る前には、必ず動作確認をするようにしてください。 + 場合によっては、コンパイル出来ない、不正な動作になる…等々の問題が起こるかも + しれませんが、そのときは、騒がず、慌てずに、ネ申の降臨を待つようお願いします。 + +** お願い ** + このパッチを完全版にしてくれる方、使用感レポートを投稿してくれる方を募集します。 + パッチを公開するついでに、大量のwarning を修正してくれたら嬉しいな〜、と思ってみたり。 + + (/) + bcc32_make.bat , bcc32_clean.bat + bcc32 でコンパイル / クリーン を簡単にするためのバッチファイル。 + + athena.dsp , athena.dsw , src/login/login.dsp , src/char/char.dsp , + src/map/map.dsp + Visual C++ 用のプロジェクトファイル & ワークスペース + + (src/) + コンパイル出来るように色々修正。 + + (src/common/timer.c) + 独自の手抜きアルゴリズム(2分ソート)を採用したバージョン。 + +-------------------- +//1077 by sylpheed +・サーバースナップショット +・下記二つを取り込み +質問スレッド Part14-41 Plalaさん +バグ報告スレッド part7-68 ...さん + +1074は取り込んでいません。 + +-------------------- +//1076 by mare +・韓国公知の通りアリスとジルタスのエサの変更。 +・GMのアブラカタブラ専用スキルのフラグが消えてたので復活。 +・ブラックスミスギルド員にプリーストの場合のセリフを追加。 +・クラスチェンジで全ての指定IDボスが出るように(なってるといいなぁ) + (db) + pet_db.txt + (conf) + battle_athena.conf + (script/npc/job) + npc_job_10blacksmith.txt + (src/map) + mob.c +-------------------- +//1075 by kag +・弓手用の指貫の効果実装の布石 +・効果がはっきりとしないのでitem_dbの修正はいれていません。 +・1075番でいいのかなぁと思ったり。 + + (db) + const.txt + bWeponAtk=1073とbWeponAtkRate=1074を追加 + + (src/map) + battle.c + int battle_get_baseatk()修正 + static struct Damage battle_calc_pc_weapon_attack()修正 + map.h + int weapon_atk[16],weapon_atk_rate[16]; + SP_WEPON_ATK,SP_WEPON_ATK_RATE, // 1073-1074を追加 + pc.c + memset(sd->weapon_atk,0,sizeof(sd->weapon_atk)); + memset(sd->weapon_atk_rate,0,sizeof(sd->weapon_atk_rate));を追加 + + pc_bonus2() 修正 + (doc) + item_bonus.txt + bWeponAtk,bWeponAtkRate,bHPDrainValue,bSPDrainValue 追加。 + +-------------------- +//1073 by LP@@ +・アコスキルの一部及びサイトスキルの修正(日本には今月末に来る筈?@2004/12/06) +速度減少は移動速度減少量が、シグナムクルシスは成功率、DEF減少量の増加量が +はっきりしなかったので弄っていません。 + (src/map) + battle.c + デーモンベイン、ディバインプロテクション計算式を修正。 + skill.c + ルアフ、サイトの有効範囲を修正(両方10x10→ルアフ5x5,サイト7x7)。 + + (db) + skill_cast.db + アクアベネディクタの詠唱及びディレイを修正。 + +//1072 by kag +・転生スキルを中心に修正 + (src/map) + battle.c + 魔法力増幅をスキルレベル*5%に修正。 + 矢撃ちに矢のATKが乗らなくなるように修正。 + オーラブレードの追加ダメージを100に修正。 + バーサークの与ダメを2倍になるように修正。 + ヘッドクラッシュの計算式を修正。 + スパイラルピアースの計算式だけ修正。 + プレッシャーの計算式を修正。 + 連柱崩撃の計算式を修正。 + ソードリジェクトの反射率をスキルレベル*15%に修正。 + アローバルカンの計算式を修正。矢の属性が乗るように修正。 + ファルコンアサルトの計算式を修正。頑強フラグで1ダメになるように修正。 + ブリッツビートを頑強フラグで1ダメになるように修正。 + デモンストレーションを必中、カードを乗らないように修正。 + アシッドテラーを防御無視、必中、無属性、カードを乗らないように修正。 + skill.c + 魔法力増幅に0.7秒の固定詠唱追加。 + LP@@ さんのアスムキリエ重複不可を追加。 + + (db) + skill_db.txt + 狂気孔を詠唱妨害できるように修正。 + skill_cast_db.txt + プレッシャーの詠唱、ディレイを追加。 + 猛虎硬派山のディレイを追加。 + ライフ置き換えのディレイを追加。 + ファルコンアサルトの詠唱、ディレイを追加。 + ウインドウォークのディレイ、持続時間を変更。 + アローバルカンの詠唱、ディレイを追加。 + クリエイトデッドリーポイズンのディレイを追加。 + skill_require_db.txt + オーラブレードの消費SPを修正。 + コンセントレーションの消費SPを修正。 + 魔法力増幅の消費SPを修正。 + ナパームバルカンの消費SPを修正。 + プレッシャーの消費SPを修正。 + サクリファイスの消費SPを修正。 + 猛虎硬派山の消費SPを修正。 + リジェクトソードの消費SPを修正。 + +//1071 by ICO +・npc_job_09wizard.txt,npc_job_16sage.txtを修正 +・取り巻きが召喚系スキルを使用する際の挙動を修正 + + (src/map) + mob.c + 取り巻きの召喚系スキルを規制するタイミングを変更 + skill.c + 召喚系スキルの発動条件を修正 + +//1070 by sylpheed +・ドロップ率のレートごとの調整を追加 + ドロップ設定1〜9 10〜99 100〜999 1000〜10000で個別に倍率と最低/最高値の設定が可能です +・@weather 0 が動かないのを修正 +・転生二次職のHP/SP25%上昇実装 +ドロップ倍率はeAthenaのアイテム種類毎の設定を移植しても良かったのですが +種類毎だとレートの開きが大きい場合があり、あまり意味がないため +このような形でレート詳細設定を追加してみました。 +mob_dbを弄るより楽にドロップ率の変更ができると思います。 + +weather 0が動かないのは理由が良くわからなかったので +動くように修正するついでに、雨フラグ消去時に +虹が出るように追加してみました。 + +転生のHP/SPに関しては、転生していても二次職になってない場合 +増加はしないようなので、そのように実装してみました。 +wedding_modifydisplay: yes の時にドレス/タキシードを装備解除すると +増加分が消えてしまいます・・・ +わかる方いたら修正お願いしますorz + + (src/map) + atcommand.c + @weather関連の修正(case 0を実行するように修正) + 雨フラグを消した場合虹が出るようにしてみました(JP蔵で使えるか不明) + (マップ移動しないと天候が消えないのはragexeの仕様かな?) + battle.c + battle.h + mob.c + item_rate_details関連を追加 + pc.c + 転生二次職時のHP/SP最大値25%増加を追加 + 転生していても二次職でない場合はHP/SP増加は無しのようです + (conf) + help.txt 修正 + msg_athena.conf 112追加 + + (doc) + conf_ref.txt 修正 + help.txt 修正 + +//1069 by lizorett (2004/11/26) special thanks to 名無し様@g@me +・メルトダウンの実装 +・魔法力増幅が詠唱のある魔法で有効にならなかった問題を修正 +・map-serverがダウンする問題の修正(質問スレッド Part13 >>55) +・map-serverに不正IDでログインするとchar-serverがダウンする問題の修正 +・サフラギウムが無詠唱スキルで取り消されない問題を修正 +・重複して猛毒状態とならないよう修正 +・マグナムブレイクのダメージを修正 +・バーサク中にHP/SP吸収、毒などのダメージを受けるよう修正 +・月光剣のSP吸収量が増加していく問題を修正(暫定) +・@helpにキーワード検索機能を追加 + + (src/map) + battle.c - マジックパワーによるMATK増加の実装 + - 武器鎧破壊をpc_break_equip()に書き換え + - HP/SP吸収を修正 + map.h - 装備破壊の定義を追加 + pc.c - pc_break_armor()/pc_break_weapon()を、新規の装備破壊の + 関数pc_break_equip()に統合 + - 魔法力増幅のコードを削除(battle.cで行う) + - HP/SP吸収関係の変数の初期化を追加 + pc.h - 関数定義を修正 + skill.c - メルトダウンによる装備破壊を実装 + - 魔法力増幅に関する修正 + - 重複して猛毒状態とならないよう修正 + clif.c - map-serverがダウンする問題の修正 + atcommand.c - @helpにキーワード検索を追加("@help jobchange"など) + (src/char) + char.c - char-serverがダウンする問題の修正 + (db) + const.txt - bUnbreakableHelm, bUnbreakableShield追加 + skill_cast_db.txt + - メルトダウンの状態異常時間を設定 + +//1068 by huge +・atcommandをいくつか追加と、eAthenaからいくつか移植。(help.txt参照) +・非GMキャラが@で始まる発言をした時、そのまま表示するようにした。(GMレベル0のコマンドは実行) +・天気コマンドに合わせて、mapflag設定できるように。 +・scriptをいくつか追加と、eAthenaから一つ移植。 +・初期HP倍率とSP倍率をbattle_athenaで設定できるようにした。 +・全キャラが、GMには位置・HPを通知させるようbattle_athenaで設定できるようにした。 +・ドクロドロップについて、battle_athenaで設定できるようにした。 +・GMのアイテムドロップや交換についてGMレベルを制限できるようにした。 +・ディテクティングスキル修正。 +※デフォルトの日本クライアントだと、雨で落ちます。 + + (conf/) + atcommand_athena.conf 修正 + battle_athena.conf 修正 + help.txt 修正 + msg_athena.conf 修正 + + (doc/) + help.txt 修正 + script_ref.txt 修正 + conf_ref.txt 修正 + + (src/map/) + atcommand.c + atcommnad.h + guild.h party.hを読む様に修正 + is_atcommand() 修正 + atcommand() 修正 + ※移植・新規コマンドについては help.txt を確認して下さい。 + battle.c + battle.h + hp_rate,sp_rate,hp_meter,bone_drop 追加 + clif.c + clif.h + clif_spawnpc() 修正 + clif_hpmeter() 追加 + guild.c + guild.h + guild_searchname() 追加 + guild_searchname_sub() 追加 + map.h + 天候に関するflag追加 + npc.c + npc_parse_mapflag() 修正 + party.c + party.h + party_searchname() 追加 + party_searchname_sub() 追加 + pc.c + pc.h + pc_calcstatus() 修正 + pc_damage() 修正 + pc_walk() 修正 + pc_can_drop() 追加 + script.c + gmcommand 移植追加 + dispbottom 追加 + getusersname 追加 + recovery 追加 + petinfo 追加 + checkequipedcard 追加 + getexp 削除(setを使うようにして下さい) + skill.c + skill.h + skill_castend_pos2() 修正 + + +Athena雑談スレッドPart7 >>54 もっさりさんの分 + 記述漏れがあったらすいません。 +-------------------- +//1067 by kai +・メディテイティオによるヒール回復量増加の効果を修正 +・アドバンスドカタール研究の修正 +・PvP時におけるアスムプティオの効果を修正 + + (src/map) + skill.c + 2120行 heal += heal*(skill*2)/100; //メディテイティオの修正 + + battle.c + 1723行 damage += dmg*(10+(skill * 2))/100; //アドバンスドカタール研究の修正 + + 2598〜2599、3580〜3582行 アスムプティオの修正 + if(map[target->m].flag.pvp)としダメージ計算を2/3に修正 + +-------------------- +//1066 by lizorett (2004/11/17) special thanks to 名無し様@g@me +・デッドリーポイズン作成実装 +・エンチャントデッドリーポイズン実装 +・ソウルブレイカー実装 +・battle_weapon_attackで未初期化の値が戻されるバグ修正 +・他使用SPの変更等の細かい修正 + + (db) + const.txt - 猛毒(SC_DPoison)を追加 + item_db.txt - 緑ハーブ,緑ポーション,万能薬に猛毒を治す効果を追加 + produce_db.txt - デッドリーポイズンの材料の定義を追加 + skill_cast_db.txtエンチャントデッドリーポイズン、ソウルブレイカー + の定義を修正/追加 + skill_db.txt - ソウルブレイカー/エンチャントデッドリーポイズン/ + デッドリーポイズン作成の定義を修正 + - ナパームバルカンのヒット数修正 + skill_require_db.txt + - エンチャントデッドリーポイズンが毒薬の瓶を使用する + ように修正 + - ソウルブレーカー/メテオアサルトの使用SPを修正 + (src/map) + battle.h - battle_config.cdp_rateを追加 + battle.c - ソウルブレーカー実装 + - メテオアサルトにカード効果がかからないよう変更 + - 4213行の条件で未初期化の値が戻されるバグ修正 + - battle_config.cdp_rateを追加 + skill.h - デッドリーポイズン作成の材料が7つなので、テーブル + を追加。材料の最大数をdefineで変更できるよう修正 + - SC_DPOISON(182)/SC_EDP(183)を追加 + skill.c - 猛毒効果を追加 + - デッドリーポイズン作成を実装 +-------------------- +//1065 by End_of_exam + +・サーバーゾンビ化に暫定対処 +・calc_index(path.c)の不都合を修正 + + (common/) + timer.c + TIMER_MIN_INTERVEL(タイマーの最小インターバル)を追加しました。 + それに伴い、do_timer() の戻り値の最低を 10ms から 50ms に変更しました。 + + selectが10ms以内に終わらない環境だと、モンスターを大量召還した時などに、 + クライアントからのパケットに反応しなくなる模様です。 + ローカルテスト(モンスター大量召還)をしてみたところ、25msに変更した時点で + 改善しましたが、環境によっては50msでも不十分かもしれません。 + その場合は、TIMER_MIN_INTERVELを増やして様子を見てください。 + + 同様の現象として、多数のクライアントが接続するとサーバーが反応しなくなる + というのがありますが、このパッチによってある程度改善されるかもしれません。 + + (map/) + map.h : MAX_WALKPATH + path.c 内の calc_indexが不都合を起こす(48*48-1 = 1000 1111 1111(b)) ため、 + MAX_WALKPATHを 48 から 32 に変更しました。(32*32-1 = 0011 1111 1111(b)) + + #define calc_index(x,y) (((x)+(y)*MAX_WALKPATH) & (MAX_WALKPATH*MAX_WALKPATH-1)) +-------------------- +//1064 by nameless +・GCC 3.3.0/3.3.1が内包する0/0=変数最大値の問題対策(int:65535/long:4294967294) +・魔法防御・防御・属性防御が正しく適用されない問題を修正 +・ナパームバルカンを単体魔法のコードに修正し、呪い効果を実装 + + (src/map) + skill.c + 442〜448行 不等号[<]を[>]に修正 + 512〜519行 不等号[>]を[<]に修正 + 529〜538行 コンパイラバグの訂正方法と例/*〜*/の部分を + gccのバージョンに合わせて生かしたり殺したり + してください。3.3.2からは直っているようです + 1857行 ナパームバルカンを追加 + 660〜664行 ナパームバルカンの呪い効果を追加 + (src/char) + char.c + 修正しきれていなかった部分を修正しました。 + +-------------------- +//1063 by 七誌 +・月光剣の効果実装 +・左手カードによる、武器攻撃時のHP/SP吸収効果が右手に影響する様に修正(本鯖仕様) + (left_cardfix_to_rightがyesの時のみ。noだと従来通り) + + (db) + const.txt + bHPDrainValue=1071とbSPDrainValue=1072を追加 + item_db.txt + 月光剣のEquipScriptにbonus2 bSPDrainValue,100,3を追加 + + (src/map) + battle.c + battle_weapon_attack() 修正 + map.h + short hp_drain_value,sp_drain_value,hp_drain_value_,sp_drain_value_;を追加 + SP_HP_DRAIN_VALUE,SP_SP_DRAIN_VALUE, // 1071-1072を追加 + pc.c + pc_bonus2() 修正 + +-------------------- +//1062 by nameless +・パケット送受信での誤送信修正 +・バグ報告スレッド part7 からの取り込み・修正 >> 56,57,58 +・fix1059の取り込み +・ハイウィズのネイパームバルカンの実装(eA取り込み) +・CPU最適化コードの修正(athlon系)・追加(玄人箱/Linux Zaurus) + + (/) + Makefile + athlon系最適化の修正 + 玄人箱(Kuro-Box 200MHz版[PPC 603x]) + 玄人箱(Kuro-Box 266MHz版[PPC 604x]) + Linux Zaurus (SL-C7xx) + の最適化コードを記述 + + (db) + skill_cast_db.txt + 400,500,1200:1600:2000:2400:2500,0,0 //HW_NAPALMVULCAN#ナパームバルカン# + (src/map) + clif.c + clif_parse() 修正 + (src/char) + char.c + 1367行 cmd = RFIFOW(fd,0);追加 + (src/map) + skill.c + switch(skillid)にcase HW_NAPALMVULCAN:以下20行ほど追加 +-------------------- +//1061 by lizorett (2004/11/9) +・不正なギルドスキルパケットを受けた場合にmap/charサーバが落ちる現象を修正 +・不正なパケットを受けた場合にcharサーバが落ちる現象を修正 +・結婚したキャラを削除するとcharサーバが落ちる現象を修正 +・青箱を一つだけ持った状態で青箱から青箱がでると、青箱が消えるたように見える + (リログすると見える)問題を修正 +・スナッチャーのスキル失敗を表示しないようにできる設定を追加 +・デボーションのレベル制限(10レベル差)を変更できる設定を追加 + + (src/common) + mmo.h + ギルドスキルのenumを追加(src/map/skill.hから移動) + (src/map) + skill.h + ギルドスキルのenumを削除(src/common/mmo.hに移動) + guild.c + guild_checkskill スキルの範囲チェックを追加 + guild_skillup スキルの範囲チェックを追加 + skill.c + skill_additional_effect display_snatcher_skill_failの処理を追加 + skill_castend_nodamage_id devotion_level_differenceの処理を追加 + battle.c + display_snatcher_skill_fail,devotion_level_differenceの初期化を追加 + (src/char) + int_guild.c + guild_checkskill スキルの範囲チェックを追加 + mapif_parse_GuildSkillUp スキルの範囲チェックを追加 + char.c + parse_char 不正なパケットを受けた場合にはダンプするよう修正 + char_divorce i<MAX_INVENTORYをj<MAX_INVENTORYに変更 + (conf) + battle_athena.conf + display_snatcher_skill_fail,devotion_level_differenceを追加 +-------------------- +//1060 by mosya +・モンスターがスキル詠唱中に座標ズレを起こす問題を修正 +・MOBのAI変更。前衛がタゲを取っているのに、後衛に攻撃をしにゆくのを修正 + (src/map) + mob.c + mob_ai_sub_hard() 変更 + mobskill_castend_id() 変更 + mobskill_castend_pos() 変更 + mobskill_use_id() 変更 + mobskill_use_pos() 変更 +-------------------- +//1059 by SPDFMember +・eAthenaを参考にリロードDB系統を追加しました。 + (conf/) + atcommand_athena.conf + reloaditemdb + reloadmobdb + reloadskilldbを追加 + help.txt + reloaditemdb + reloadmobdb + reloadskilldbの説明を追加 + msg_athena.conf + 89 + 90 + 91を追加 + (src/map) + atcommand.c + reloaditemdb + reloadmobdb + reloadskilldbを追加。 + atcommand.h + AtCommand_ReloadItemDB, + AtCommand_ReloadMobDB, + AtCommand_ReloadSkillDB,を追加 + itemdb.c + static int itemdb_readdb(void);追加 + itemdb.h + void itemdb_reload(void);追加 + mob.c + void mob_reload(void)追加 + mob.h + void mob_reload(void);追加 + skill.c + void skill_reload(void)追加 + skill.h + void skill_reload(void);追加 +-------------------- +//1058 by lizorett +・ギルド倉庫アイテムがMAX_STORAGE個以上あると取り出せないものがある問題を修正 + (src/map) + clif.c + clif_parse_DropItem item_index/item_amountの範囲チェックを削除 + (pc_dropitem でチェックする) + clif_parse_MoveToKafra item_amountのチェックを削除 + (storage_*storageaddでチェックされている) + clif_parse_MoveFromKafra item_index/item_amountのチェックを削除 + (storage_*storagegetでチェックされている) + pc.c + pc_dropitem n/amountの範囲チェックを追加 +-------------------- +//1057 by BDPQ銀 +・ウォーターボールのダメージを本鯖告知値→実測値に修正。 + [ MATK+SkillLv*30 → MATK*(1+SkillLv*0.3) ] + + (src/map) + battle.c + battle_calc_magic_attack 変更 [ 3848行目あたり ] + +-------------------- +//1056 by robert +順番を検査するのは不法かどうか + (src/map) + clif.c + clif_parse_DropItem + clif_parse_MoveToKafra + clif_parse_MoveFromKafra +-------------------- +//1055 by Nameless +・各種CPUに対するコード最適化オプションを設定(全27種) ※GCC 3.3.1 準拠 +・Pentium 3のオプションがSSE2になっていたのを訂正 +・稀枝さん、robertさんのPacket情報の取り込み(お二人に感謝) + + (/) + makefile + i486/586/p54c/mmx/P3/P4/Cele + k6/k6-2/k6-3/athlon系 + Via C3(Eden) + PowerPC/G4系 + + (src/map/) + clif.c + clif_parse_MoveToKafra{} + コード取り込み + +-------------------- +//1054 by Nameless +・Cygwinでコンパイルしたathenaが接続53〜58人付近で接続不能になるバグを解消 + + (src/common/) + socket.h + #ifdef CYGWIN + #undef FD_SETSIZE + #define FD_SETSIZE 4096 + #endif + 以上の行を削除 + (/) + makefile + OS_TYPE = -DCYGWIN + ↓ + OS_TYPE = -DCYGWIN -DFD_SETSIZE=4096 + に修正 + + #optimize for Athlon-4(mobile Athlon) + #CFLAGS += -march=athlon -mcpu=athlon-4 -mfpmath=sse + + #optimize for Athlon-mp + #CFLAGS += -march=athlon -mcpu=athlon-mp -mfpmath=sse + + #optimize for Athlon-xp + #CFLAGS += -march=athlon -mcpu=athlon-xp -mfpmath=sse + + #optimize for pentium3 + #CFLAGS += -march=i686 -mcpu=pentium3 -mfpmath=sse -mmmx -msse2 + + 各種CPUの最適化を追加gcc3.1以上を使っている場合は#を外し + て最適化を行うことができると思います。 + + ※makefileでセットしておかないと、コンパイルの際に一部 + FD_SETSIZEが小さくなってしまうバグ(?)があるらしく、接続人数が + 60人弱で接続不能が発生してしまいます。 + +-------------------- +//1053 by TEILU +・パケットパーサーをタイマー呼出しに変更できる設定の追加 +・精錬の可否判定でDBにどのような設定を入れてもアクセサリは + 精錬できなかった不具合を修正 + + (conf/) + map_athena.conf + packet_parse_time: 0 追加 + (src/common/) + core.c + packet_parse_time 追加 + main() 変更 + socket.c + parsepacket_timer() 追加 + socket.h + parsepacket_timer() 追加 + (src/map/) + map.c + packet_parse_time 追加 + map_config_read() 変更 + script.c + buildin_getequipisenableref() 変更 + +-------------------- +//1052 by +居場所つきで検索コマンド追加。 + GMコマンド追加 + @who+ 居場所つき検索 + + (conf/) + atcommand_athena.conf + who+: 1 追加 + (/src/common/) + version.h + Ver 1051->1052 変更 + (/src/map) + atcommand.c + ATCOMMAND_FUNC(whop); 追加 + { AtCommand_WhoP,"@who+",0, atcommand_whop }, 追加 + atcommand.h + AtCommand_WhoP, 追加 +-------------------- +//1051 by Plala +・ペコペコ騎乗時MAX Weightを増やせるようにしました。 +battle_athena.confで設定可能です。 + + (conf/) + battle_athena.conf + riding_weight 追加 + (map/) + battle.c + battle_config.riding_weight 追加 + battle.h + int riding_weight; 追加 + clif.c + clif_parse_RemoveOption 変更 + pc.c + int pc_calcstatus 変更 + 1415にsd->max_weight +=battle_config.riding_weight; を追加 + (common/) + version.h + Ver 1050->1051 変更 +-------------------- +//1050 by code +・各種天候操作コマンドの見直し +※いちいち@misceffectで呼び出さずに簡単に天候操作を行えるように +※クライアント依存は落ち葉ではなく雨でした、間違いました(^-^; + + (src/common/) + version.h + Ver 1049->1050 変更 + (/src/map) + atcommand.c + AtCommand_Rain{} 変更 + AtCommand_Snow{} 変更 + AtCommand_Cherry{} 変更 + AtCommand_Fog{} 変更 + AtCommand_Maple{} 変更 + +-------------------- +//1049 by code +・霧、落葉の2つの天候操作コマンドを追加しました。 +※落ち葉に関してはクライアント依存なのでjROだと落ちるかも… + + GMコマンド追加 + @fog 霧 + @maple 落葉 + + (conf/) + atcommand_athena.conf + fog: 1 追加 + maple: 1 追加 + + msg_athena.conf + 87: 霧が立ち込めました。 追加 + 88: 落ち葉が降ってきました。 追加 + (/src/common/) + version.h + Ver 1048->1049 変更 + (/src/map) + atcommand.c + ATCOMMAND_FUNC(fog); 追加 + ATCOMMAND_FUNC(maple); 追加 + { AtCommand_fog,"@fog",0, atcommand_fog }, 追加 + { AtCommand_maple,"@maple",0, atcommand_maple }, 追加 + + atcommand.h + AtCommand_Fog, 追加 + AtCommand_Maple, 追加 + +-------------------- +//1048 by code +・雨、雪、サクラ吹雪の3つの天候操作コマンドを追加しました。 +※衝動的に追加してしまったのでバグがあるかも知れません(汗 + + GMコマンド追加 + @rain 雨 + @snow 雪 + @cherry サクラ吹雪 + + (conf/) + atcommand_athena.conf + rain: 1 追加 + snow: 1 追加 + cherry: 1 追加 + + msg_athena.conf + 84: 雨が降り出しました。 追加 + 85: 雪が降り出しました。 追加 + 86: サクラ吹雪を降らせます。 追加 + (/src/common/) + version.h + Ver 1047->1048 変更 + (/src/map) + atcommand.c + ATCOMMAND_FUNC(rain); 追加 + ATCOMMAND_FUNC(snow); 追加 + ATCOMMAND_FUNC(cherry); 追加 + { AtCommand_rain,"@rain",0, atcommand_rain }, 追加 + { AtCommand_snow,"@snow",0, atcommand_snow }, 追加 + { AtCommand_cherry,"@cherry",0, atcommand_cherry }, 追加 + + atcommand.h + AtCommand_Rain, 追加 + AtCommand_Snow, 追加 + AtCommand_Cherry, 追加 + +-------------------- +//1047 by SVN +・製造アイテムの製作者の名前を引くmap←→charのパケットが間違っていたのを修正 +・二重ログインをした時にchar-serverが落ちる可能性があったのを修正 +・ガーディアンをGv時間外に殴れた、ID指定のスキルが当たった、skill_unitなスキル攻撃が当たったのを修正 +・グラフィティのRangeをとりあえず3にしてみた + (db/) + skill_db.txt + (char/) + char.c + parse_frommap() + (map/) + clif.c + clif_parse_ActionRequest() 変更 + clif_parse_UseSkillToId() 変更 + mob.c + mob_gvmobcheck() 追加 + mob.h + mob_gvmobcheck() 定義追加 + skill.c + skill_attack() 変更 + +-------------------- +//1046 by SVN +※db/packet_db.txtは2004-09-06aSakexe用なので、jROクライアントで使用する際は「//jROはここまで」以下をコメントアウトするか削除してください + +・変更点が多いので詳細はファイル、関数ごとに記述しています +・1045にそのまま上書きしても動作しますが、使われないファイルがいくつか残ります +・script/以下は名前が変更されているファイルが大量にあるのでscript/の変更点を参考にしてください +・スクリプト用の関数や命令が増えたり仕様が変更されているものがあります + 基本的には互換性があるはずですが、getgdskilllv()だけは第二引数を数字ではなくスキル名(GD_APPROVALなど)に置き換える必要があります + getgdskilllv()が使われている/script/npc/gvg_big5/*.* は中国語で必要ないので削除してください + 追加や変更に関しては概ねscript_ref.txtに反映してありますが、詳細はscript.cの変更点を読んでください +・追加された@コマンドについては@helpとatcommand.cの変更点を読んでください +・追加された設定はconf_ref.txtを参照してください +・記述漏れの変更点もあるかもしれません + +追加したファイルは「A」 +変更したファイルは「C」 +削除したファイルは「D」 +移動したファイルは「M」 + / + C athena-start + ./conf/import 以下を起動時に自動作成するように変更 + seqコマンドを使わないようにしてFreeBSDでも動作するように変更 + start + すでにAthenaが起動している時は何もしないように変更 + execで ./ がダブっていたので削除 + stop + FreeBSDでもシェルに戻るように変更 + kill + 同上 + C Makefile + PACKETDEF に PACKETVER=6 を追加 + FreeBSDを判定して make と gmake を切り替えるように変更 + CFLAGS を分解して弄りやすいように変更 + C start + 1行目のシェル指定が正しくなかったのを変更 + すでにAthenaが起動している時は何もしないように変更 + 起動確認の条件式を athena-start と同じ物に変更 + bin/tool/ + シェルスクリプトの改行コードを CRLF から LF のみに変更 + C getlogincount + ログインバージョンを $loginversion として変更できるように変更 + C ladmin + アカウント名に「-」を使えるように変更 + + conf/ + D import/ + 配布物から削除(athena-start start で自動作成される) + C atcommand_athena.conf + shuffle maintenance misceffect 追加 + C char_athena.conf + default_map_type default_map_name 追加 + C help.txt + 説明追加 + C login_athena.conf + login_version login_type 追加 + C map_athena.conf + npc map 色々変更 + C mapflag.txt + 最新版に更新 + C msg_athena.conf + 81以降追加 + C water_height.txt + 最新版に更新 + db/ + C castle_db.txt + ギルド解体時に発生する OnGuildBreak イベントのために <Event_Name> 追加 + C const.txt + GvGの開始時間等を設定できるように追加 + マップフラグ mf_notrade mf_noskill 追加 + パラメータ PartnerId Cart 追加 + ボーナス bBreakWeaponRate bBreakArmorRate bAddStealRate bUnbreakableWeapon bUnbreakableArmor 追加 + ステータス変化 SC_WEDDING 追加 + スクリプト命令 getgdskilllv 用に GD_APPROVAL など追加 + C exp.txt + 転生二次職がBaseLv12になるときに必要な経験値を41→481に修正 + C item_db.txt + C mob_db.txt + C mob_skill_db.txt + C skill_cast_db.txt + C skill_db.txt + C skill_require_db.txt + C skill_tree.txt + 最新版に更新 + A packet_db.txt + パケット定義ファイル追加 + doc/ + C client_packet.txt + 新しく判明したパケットをいくつか追加 + C conf_ref.txt + 新しく追加した設定の説明を追加 + C db_ref.txt + skill_cast_db.txt の list_hp_rate list_sp_rate で負数を指定した時の挙動を追加 + C help.txt + conf/help.txt 同様に変更 + C inter_server_packet.txt + 新規で追加したパケットを追加と実態とあっていなかった部分を修正 + C item.txt + 最新版に更新 + C item_bonus.txt + 新規で追加されたボーナスを追加 + C script_ref.txt + 新規命令の追加と既存命令の変更など + C serverlink_packet.txt + 新規で追加したパケットを追加と既存で書かれていなかったパケットの追加 + script/ + mob/ + C npc_monster.txt + 最新版に更新 + ニブルヘイムのMobはnpc_parse_mob()の変更サンプルになってます + npc/ + ほぼすべてのNPCをnpc_function.txtを使ったユーザー定義関数と複製などで書き換え + 移動したファイルに関しては移動後のファイルが含まれているので移動前のファイルのみ削除してください + 例) etc/npc_etc_cTower.txt は含まれているので npc_cTower.txt を削除 + M npc_cTower.txt + →etc/npc_etc_cTower.txt + A npc_function.txt + M npc_pota.txt + →../sample/npc_debug_pota.txt + M npc_pvp.txt + M npc_pvproom.txt + 2ファイル合体 + →etc/npc_etc_pvp.txt + M npc_resetJ.txt + →../sample/npc_debug_reset.txt + A etc/ + A npc_etc_gefenia.txt + C gvg/ + すべてev_agit_common.txtを使ったユーザー定義関数で書き換え + すべて削除してからこのパッチを当ててください + ギルド解散時に砦を放棄するためにev_agit_砦.txtにOnGuildBreakイベントを追加 + D test/ + A ev_agit_common.txt + D ev_agit_event.txt + D TEST_prtg_cas01_AbraiJ.txt + D TEST_prtg_cas01_mob.txt + D gvg_big5/ + C job/ + 転職スクリプトの名前をnpc_job_[JOB番号][ジョブ名].txtに変更 + すべて削除してからこのパッチを当ててください + C quest/ + M npc_event_arrow.txt + →../../sample/npc_debug_arrow.txt + A npc_event_hat2.txt + ニブル同時実装の新頭装備スクリプトを追加 + src/ + calloc() realloc() を極力各型にキャストするように変更 + calloc() 後に memset() で \0 を埋めていたのを削除 + calloc() なのに(サイズ*個数,1)で指定していたのを(個数,サイズ)に変更 + メモリ確保をエラー処理をまとめた関数に書き換え + malloc() → aMalloc() + calloc() → aCalloc() + realloc() → aRealloc() + strcpy() を strncpy() に極力変更 + + char/ + C char.c + スペースでインデントされていたところをタブで統一 + A isGM() + A read_gm_account() + GMアカウントが必要になったので追加 + C mmo_char_tostr() + C mmo_char_fromstr() + nullpoチェック追加 + C count_users() + 必要ない{}を削除 + C char_delete() + nullチェック追加 + 削除メッセージをコンソールに表示するようにした + 削除時に接続しているキャラを切断するようmap-serverに通知(0x2b19パケット)するようにした + C parse_tologin() + C 0x2713 + char-serverメンテナンス設定時はGM以外入れないようにした + 接続数制限で最大値でもGMは接続できるようにした + C 0x272a + 0x2730を0x272aに変更して番号を詰めた + アカウント削除した時にキャラが一部消されない問題を修正 + A 0x272c + 受信時にlogin-serverに通知(0x2b15パケット)してメンテナンス状態になるようにした + A char_erasemap() + map-server切断時に他map-serverにマップの削除を通知(0x2b16パケット)するようにした + これにより他map-server管轄のマップに移動しようとして、そのmap-serverが切断されていたら、 + pc_setpos()で存在しないマップということで移動しようとしなくなるので、 + クライアントが「永遠にお待ちください状態」にならないようになります + C parse_frommap() + map-server切断時にchar_erasemap()を実行するようにした + map-server切断時に管轄のマップにキャラが残っていたら切断を他map-serverに通知(0x2b17パケット)するようにした + C 0x2afc + 認証失敗時に char_dat[].mapip/mapport を 0 にするようにした + 認証成功時に char_dat[].mapip/mapport をmap-serverのIPアドレスとポートにするようにした + 認証成功時に他map-serverにキャラがログインしたことを通知(0x2b09パケット)するようにした + C 0x2b02 + C 0x2b05 + コンソールへの出力にパケット番号を記述するようにした + C 0x2b08 + パケット仕様を変更して account_id mapip mapport も通知するように変更 + map-serverに接続していない時はすべて 0 が入ります + A 0x2b13 + map-server起動途中などでキャラがログインできないようにする server[].active フラグを操作する + active = 0 でキャラはログインできずに切断される + map-serverが起動を完了したときに active = 1 にするパケットが送られてくる + A 0x2b14 + char-serverをメンテナンス状態にする char_maintenance フラグを操作する + login-serverにも通知(0x272bパケット)してワールド選択画面でメンテナンス表示をする + メンテナンス状態ではGM以外のユーザーはログインできません + A 0x2b18 + キャラクターの切断を他map-serverに通知(0x2b17パケット)するようにした + C search_mapserver() + 引数に struct mmo_charstatus *cd を追加 + cdが渡された&探しているマップが接続しているmap-serverに無かったときに、最初に見つけたmap-serverの最初に見つけたマップに接続するようにした + これは char_athena.conf default_map_type: 2 の時の挙動です + C parse_char() + C 0x65 + メンテナンス状態の時にGM以外を切断するようにした + 最大接続数が設定されていて最大接続数のときもGMは接続できるようにした + C 0x66 + char-serverに接続しているmap-serverにlast_pointが見つけられなかったときに、 + default_map_type&1 の時は default_map_name に接続する + default_map_type&2 の時は 最初に見つけたmap-serverの最初に見つけたマップに接続する + それでも見つからない時は切断するようにした + コンソールへの出力にパケット番号を記述するようにした + C 0x2af8 + 他マップに接続しているキャラ情報を通知(0x2b09パケット)するようにした + C 0x187 + S 0187パケットを返信するようにした + C check_connect_login_server() + char_portをWFIFOLで送っていたのをWFIFOWに修正 + 80と82の間が空いていたのを詰めてパケット長を86→84に変更 + C char_config_read() + default_map_type default_map_name を読み込むようにした + A gm_account_db_final() + 確保した gm_account_db のメモリを終了時に開放するようにした + C do_final() + inter.c など他ファイルの終了処理(do_final_*)を追加した + exit_dbn() でdb用のメモリを開放するようにした + 接続されているmap-serverのセッションを削除するようにした + do_final_timer()でtimerを終了させるようにした + C do_init() + server[].active = 0 で初期化 + read_gm_account() でGMアカウントファイルを読み込むようにした + C char.h + mmo_map_server に active フラグを追加した + C int_guild.c + C mapif_parse_GuildSkillUp() + ギルドポイントを消費しないでギルドスキルを上げるために int flag を追加 + C inter_guild_parse_frommap() + 0x303C + パケット定義を変更してflagを追加した + A guild_db_final() + A castle_db_final() + A do_final_int_guild() + 終了時にメモリを開放するようにした + C int_guild.h + A do_final_int_guild() + 定義を追加 + C int_party.c + A party_db_final() + A do_final_int_party() + 終了時にメモリを開放するようにした + C int_party.h + A do_final_int_party() + 定義を追加 + C int_pet.c + A pet_db_final() + A do_final_int_pet() + 終了時にメモリを開放するようにした + C int_pet.h + A do_final_int_pet() + 定義を追加 + C int_storage.c + A storage_db_final() + A guild_storage_db_final() + A do_final_int_storage() + 終了時にメモリを開放するようにした + C int_storage.h + A do_final_int_storage() + 定義を追加 + C inter.c + パケット長定義を変更 + A mapif_parse_CharPosReq() + 0x3090パケットへの対応 + キャラの位置要求をmap-serverに通知(0x3890パケット)する + A mapif_parse_CharPos() + 0x3091パケットへの対応 + キャラの位置要求をしたキャラに位置情報を通知(0x3891パケット)する + A mapif_parse_CharMoveReq() + 0x3092パケットへの対応 + 要求したキャラまで対象のキャラを飛ばす要求を通知(0x3892パケット)をする + A mapif_parse_DisplayMessage() + 0x3093パケットへの対応 + キャラにメッセージを送信(0x3893パケット)する + C inter_parse_frommap() + 各追加パケットへの対応を追加した + A wis_db_final() + A accreg_db_final() + A do_final_inter() + 終了時にメモリを開放するようにした + C inter.h + A do_final_inter() + 定義を追加 + C Makefile + A nullpo.o nullpo.h を追加 + A malloc.o malloc.h を追加 + common/ + C db.c + A exit_dbn() + 終了時にメモリを開放するために追加 + C db.h + A exit_dbn() + 定義追加 + A malloc.h + A malloc.c + メモリ確保関数のまとめ + C mmo.h + C mmp_charstatus + mapip mapport 追加 + C guild_castle + castle_event 追加 + C Makefile + A malloc.o malloc.h malloc.c を追加 + C nullpo.h + 古いgccでコンパイルできるように\を削除 + C socket.c + C recv_to_fifo() + 汎用性を高めるために read() を recv() に変更 + C send_from_fifo() + 汎用性を高めるために write() を send() に変更 + C timer.c + A do_final_timer() + 終了時にメモリを開放するようにした + C timer.h + A do_final_timer() + 定義追加 + login/ + C login.c + A login_version login_type + clientinfo.xmlで指定する login_version login_type でログインを規制するときに使います + C parse_fromchar() + A 0x272b + server[].maintenance フラグを変更する + 変更した内容をchar-serverに返信(0x272cパケット)する + C parse_admin() + C 0x7932 + 0x2730→0x272a に変更 + C parse_login() + C 0x64 0x01dd + login_version login_type を判定するようにした + C 0x2710 + パケット長の定義が正しくなかったのを修正した + char.c check_connect_login_server の変更を反映 + C login_config_read() + login_version login_typeの読み込みを追加 + A gm_account_db_final() + C do_final() + 終了時にメモリを開放するように変更 + C Makefile + A malloc.o malloc.h を追加 + map/ + C atcommand.c + コンパイルオプションでmemwatchを読み込めるようにした + C atcommand_where() + 他map-serverにいるキャラの居場所も表示できるようにした + C atcommand_jumpto() + 他map-serverにいるキャラにも飛べるようにした + C atcommand_who() + ワールド内のすべてにいるキャラを表示するようにした + C atcommand_go() + ニブルヘルムの移動ポイントを変更 + C atcommand_recall() + 他map-serverにいるキャラも呼び出せるようにした + A atshuffle_sub() + A atcommand_shuffle() + PCとMOBのシャッフルを行う @shuffle を追加 + A atcommand_maintenance() + char-serverをメンテナンス状態にする @maintenance を追加 + A atcommand_misceffect() + 実行したキャラから0x1f3パケットを発信してエフェクトを表示する @misceffect を追加 + A atcommand_summon() + コールホムンクルスと叫んで指定したMobを召喚する @summon を追加 + 召喚されたMobは他のMob(Pv等では敵対PC含む)を攻撃します + 召喚されたMobに攻撃されたMobは召喚主を攻撃します(バイオプラントのフローラと同じ挙動) + 召喚されたMobは1分後に消滅します + ネタなので隠しコマンドとしてhelp.txtには記述してません + C atcommand.h + 追加した@コマンドを AtCommandType に追加 + C msg_table[] を外から使えるようにするためにexternした + C battle.c + コンパイルオプションでmemwatchを読み込めるようにした + A battle_config.castle_defense_rate + 本鯖で防御値がどのように影響するか具体的には分からなかったので、砦の防御値を反映させる率を設定できるようにした + C battle_get_opt1() + C battle_get_opt2() + C battle_get_option() + NPCのオプションも返すようにした + A battle_get_opt3() + opt3を返すように追加 + C battle_calc_damage() + 砦内のMobへのダメージは防御値で減算(ダメージ*(防御値/100)*(castle_defense_rate/100))されるようにした + ガーディアンにはスキルが効くようにした + C battle_calc_pet_weapon_attack() + C battle_calc_mob_weapon_attack() + C battle_calc_pc_weapon_attack() + ベナムスプラッシャーのダメージ計算をするようにした + C battle_weapon_attack() + 武器攻撃による即死の仕様を変更 + 武器、鎧破壊の確率計算をするように変更 + ベナムスプラッシャーが解除されるように変更 + C battle_check_target() + src じゃなくて ss からparty_id guild_idを取得するように修正 + target=BCT_NOENEMY なスキル 口笛、ハミングなどがPvP、GvGの時にも他PCに影響するようにした + Mobがspecial_aiならMobを敵とみなすようにした + C battle_config_read() + castle_defense_rate を読み込むようにした + C battle.h + A battle_get_opt3() + 定義追加 + C Battle_Config + castle_defense_rate 追加 + C chat.c + C chat_createnpcchat() + 引数に int pub を追加 + pub=3 ではチャットの看板に(0/20)のような表示がされなくなります + A do_final_chat() + 何もしてないけどとりあえず追加 + C chat.h + C chat_createnpcchat() + 定義を変更 + A do_final_chat() + 定義を追加 + C chrif.c + パケット長テーブルを拡張 + C chrif_connect() + C chrif_changemapserver() + WFIFOLでポートを送っていたのをWFIFOWに修正 + A chrif_recverasemap() + 他map-serverが切断されたことがchar-serverより通知された時に、そのmap-serverが管理していたマップの情報を削除するようにした + A chrif_mapactive() + map-server起動準備中に0、完了時に1をchar-serverに通知(0x2b13)して起動途中にユーザーがログインできないようにした + A chrif_maintenance() + char-serverをメンテナンス状態にしたり解除したりを通知(0x2b14)する + A chrif_maintenanceack() + char-serverをメンテナンス状態にした時の応答 + メンテナンス状態にした旨をマップ内に通知する + A chrif_chardisconnect() + char-serverにキャラが切断されたことを通知(0x2b18)する + A chrif_parse_chardisconnectreq() + char-serverからのキャラ切断要求を受けて、対象キャラがいる場合には切断する + C chrif_parse() + C 0x2b09 + map_addchariddb() の引数増加に対応 + A 0x2b15 + A 0x2b16 + A 0x2b17 + A 0x2b19 + 各新規パケットに対応 + C check_connect_char_server() + 接続時char-serverにmap-serverの準備が出来たことを通知するようにした + A do_final_chrif() + 終了時にchar-serverとの接続を削除するようにした + C chrif.h + A chrif_mapactive() + A chrif_maintenance() + A chrif_chardisconnect() + A do_final_chrif() + 定義を追加 + C clif.c + すべてのパケット定義を packet_db から読み込むように変更 + packet_db.txtを変更することで、度々変更される韓国クライアントのパケット定義に対応しやすくなります + packet_len_table[] は packet_db[].len に置き換わりました + <time.h> をinclude + clif_parse_*を先頭で宣言するようにした + clif_parse_*内のRFIFO系で使われている第2引数は packet_db[cmd].pos[] で表記されるようになりました + パケット番号の最大値を MAX_PACKET_DB で定義するようにした + C clif_set0078() + C clif_set007b() + パケットの内容が本鯖と違っていたのでguild_emblem_id,manner,opt3を正しく送るように変更 + C clif_class_change() + Mob以外のNPCでも使えるようにした + C clif_mob0078() + C clif_mob007b() + ガーディアンにギルドエンブレムを表示するように変更 + C clif_npc0078() + ワープポータルをギルドフラッグにするオプションを有効にした時にmap-serverが落ちる問題を修正 + C clif_spawnnpc() + NPCが無効でもHide状態の時はパケットを送るように変更 + C clif_quitsave() + キャラ終了時にchar-serverに切断を通知するようにした + C clif_scriptmenu() + C clif_dispchat() + C clif_changechatstatus() + lenに1バイト追加 + C clif_updatestatus() + マナーポイントを送信するようにした + A clif_changestatus() + 周囲に赤エモ状態であることを送信 + A clif_misceffect2() + エフェクトを発生させるパケットを送信 + @misceffect, misceffect命令で使用 + C clif_changeoption() + 状態異常時以外は状態異常アイコン表示パケットを送らないようにした + PCの時は clif_changelook() を送信するようにした(結婚衣裳表示用?) + C clif_traderequest() + 取引パケットの 0xe5 → 0x1f4 に仮対応(本鯖での算出式は不明なのでとりあえず char_id を送信) + C clif_tradestart() + 取引パケットの 0xe7 → 0x1f5 に仮対応(本鯖での算出式は不明なのでとりあえず char_id を送信) + C clif_getareachar_pc() + マナーポイントが負数の時には赤エモ表示パケットを送信するようにした + C clif_getareachar_npc() + NPCのHide状態に対応 + C clif_getareachar_skillunit() + C clif_skill_nodamage() + 自爆の時はhealを負数にできるようにした + C clif_skill_setunit() + グラフィティに対応 + A clif_item_repair_list() + 武器修理スキルに対応しようとしたけどパケットが分からないので頓挫中 + C clif_produceeffect() + map_addchariddb() の引数増加に対応 + C clif_guild_skillinfo() + 未実装ギルドスキル カリスマを表示しないようにした + C clif_callpartner() + あなたに逢いたい 使用時に相手の名前を叫ぶようにした + C clif_sitting() + 引数 fd は不要なので削除 + C clif_GM_kick() + フラグを0にするようにした + A clif_wisexin() + Wis拒否許可の応答を送信 + A clif_wisall() + Wis全拒否許可の応答を送信 + A clif_soundeffect() + SEを鳴らすパケットを送信 + soundeffect命令で使用 + C clif_parse_LoadEndAck() + 結婚後のウェディングドレスやタキシードの状態をログアウトしても1時間は継続されるようにした + 赤エモ状態はログアウトしてもログインした時からまた継続するようにした + C clif_parse_QuitGame() + C clif_parse_Restart() + 終了できない条件を pc_isquitable() にまとめた + C clif_parse_GlobalMessage() + C clif_parse_Wis() + C clif_parse_PartyMessage() + C clif_parse_GuildMessage() + 赤エモ状態では発言できないようにした + C clif_parse_ActionRequest() + ギルド未加入などの場合はガーディアンやエンペリウムを殴れないようにした + clif_sitting()の引数変更に対応 + C clif_parse_UseItem() + 赤エモ状態ではアイテムを使えないようにした + C clif_parse_EquipItem() + アイテムが破壊されている時は装備できないようにした + C clif_parse_TradeRequest() + C clif_parse_TradeAck() + notradeマップでは取引要請を送れないようにした + C clif_parse_UseSkillToId() + C clif_parse_UseSkillToPos() + C clif_parse_UseSkillMap() + noskillマップではスキルを使用できないようにした + チャット中はスキルを使用できないようにした + 赤エモ中はスキルを使用できないようにした + ウェディング状態ではスキルを使用できないようにした + C clif_parse_MoveToKafra() + itemdb_isdropable()==0 は倉庫に入れられないようにした + C clif_parse_GMReqNoChat() + GM右クリックで赤エモを付与・解除できるようにした + C clif_parse_GMReqNoChatCount() + 本鯖での返答パケットがよく分からないので仮対応 + 本当はアカウント名が返るのかな? + C clif_parse_sn_explosionspirits() + クライアントからパケットが来た時にコンソールにログを表示するようにした + BaseLv99以上の時に0で除算する可能性があるのを回避 + A pstrcmp() + clif_parse_wisexin()のqsort()で使用 + A clif_parse_wisexin() + Wis拒否許可に対応 + A clif_parse_wisexlist() + Wis拒否リスト表示に対応 + A clif_parse_wisall() + Wis全拒否許可に対応 + A clif_parse_GMkillall() + GMコマンド/killall(=@kickall)に対応 + A clif_parse_GMsummon() + GMコマンド/summon(=@recall)に対応 + A clif_parse_GMshift() + GMコマンド/shift(=@jumpto)に対応 + A clif_parse_debug() + packet_db.txtのデバグ用に追加 + パケット内容をダンプします + C clif_parse() + clif_parse_func_table を削除(packet_db[cmd].funcに入るようになりました) + A packetdb_readdb() + packet_db.txtを読み込みます + フォーマットは パケット番号,パケット長[,コマンド,コマンド引数の位置(:区切りで複数指定)] + コマンド引数の位置は各コマンドに対応する関数内で設定されているのでclif.cを読まないと分からない難解なフォーマットです + 変更されたパケットはpacket_db.txtの末尾に追加します + 古いクライアントを利用する場合には不要な定義を末尾から削除すればよいようにします + A do_final_clif() + 終了時にセッションを削除するようにした + C do_init_clif() + packet_dbを読み込むようにした + 終了時にセッションを削除できるように make_listen_port() の戻り値を map_fd に入れるようにした + C clif.h + A MAX_PACKET_DB + A struct packet_db + A clif_changestatus() + A clif_misceffect2() + A clif_callpartner() + A clif_sitting() + A clif_soundeffect() + A clif_item_repair_list() + A do_final_clif() + 定義を追加 + C clif_class_change + clif_mob_class_change() から変更 + C guild.c + C guild_read_castledb() + castle_event を読み込むようにした + C guild_skillup() + 引数を変更 + flag=1 でギルドポイントを使用しないようにした + C guild_broken() + ギルド解散時に所有砦を破棄するための OnGuildBreak イベントを追加 + A guild_db_final() + A castle_db_final() + A guild_expcache_db_final() + A guild_infoevent_db_final() + A do_final_guild() + 終了時にメモリを開放するようにした + C guild.h + C guild_skillup() + 定義を変更 + A do_final_guild() + 定義を追加 + C intif.c + atcommand.h をinclude + packet_len_table[] 拡張 + C intif_guild_skillup() + 引数 flag 追加 + A intif_charposreq() + キャラの場所要求パケットを送信 + flag=1 @jumpto + flag=0 @where + A intif_jumpto() + 他map-serverのキャラに @jumpto 出来るようにした + A intif_where() + 他map-serverのキャラに @where 出来るようにした + A intif_charmovereq() + キャラを呼び寄せる + flag=1 @recall + flag=0 あなたに逢いたい + A intif_displaymessage() + 他map-serverのキャラにメッセージを送れるようにした + (Wisではなくて送りっぱなし。@recall 成功時用) + C intif_parse_WisMessage() + Wis拒否の判定をするようにした + A intif_parse_CharPosReq() + キャラの居場所をInterへ返答 + A intif_parse_CharPos() + キャラの居場所がInterから送られてきたので + flag=1 キャラの場所へ移動(@jumpto) + flag=0 キャラの場所を表示(@where) + A intif_parse_CharMoveReq() + キャラがいたら指定位置に移動させる + flag=1 @recall なのでGMレベルを比較、メッセージを表示 + A intif_parse_DisplayMessage() + 指定キャラにメッセージを送信 + C intif_parse() + 新パケットを追加 + C intif.h + C intif_guild_skillup() + 定義変更 + A intif_jumpto() + A intif_where() + A intif_charmovereq() + A intif_displaymessage() + 定義の追加 + C itemdb.c + A itemdb_isdropable() + アイテムが捨てられるかどうかの判定をする + A itemdb_read_cardillustnametable() + grfファイルから num2cardillustnametable.txt を読み込む + cutincard命令で使用 + C do_init_itemdb() + itemdb_read_cardillustnametable() を追加 + C itemdb.h + C struct item_data + char cardillustname[64] 追加 + A itemdb_isdropable() + 定義の追加 + C Makefile + A malloc.o malloc.h を追加 + C map.c + C struct charid2nick + @whoで他map-serverのキャラも表示できるように account_id ip port を追加 + C map_freeblock() + C map_freeblock_unlock() + 二重free()対策でNULLを代入するようにした + C map_delblock() + 見やすいように繰り返し使用される変数をまとめた + C map_addchariddb() + charid2nick の拡張にあわせて引数を増やした + A map_delchariddb() + charid_db からキャラを削除(実際にはip portを0に)する + C map_quit() + 結婚状態中はログアウトしても1時間は状態が続くようにPCグローバル変数 PC_WEDDING_TIME に開始時間を記録するようにした + C map_id2bl() + 見やすいように書き換え + A map_eraseipport() + 他map-server管理のマップを map_db から削除する + A map_who_sub() + A map_who() + 他map-serverにいるキャラも @who で表示されるようにした + 表示上キャラが残ることがあるのは調査中 + A id_db_final() + A map_db_final() + A nick_db_final() + A charid_db_final() + C do_final() + 終了時にメモリを開放するように変更 + C map.h + A MAX_WIS_REFUSAL + Wis拒否リストの保存最大値 + C struct map_session_data + C special_state + A unbreakable_weapon + 武器が絶対に壊れない + A unbreakable_armor + 鎧が絶対に壊れない + A opt3 + 画面外から入ってきたキャラの状態 + A areanpc_id + OnTouchイベントを実行したNPCのID + A wis_refusal[][] + Wis拒否リスト + A wis_all + Wis全拒否フラグ + A break_weapon_rate + 武器破壊率 + A break_armor_rate + 鎧破壊率 + A add_steal_rate + 追加スティール率 + C struct npc_data + A opt1,opt2,opt3,option + PCと同じ + C u.scr + A src_id + 終了時のメモリ開放用 + C struct mob_data + A opt3 + PCと同じ + A guild_id + ガーディアンなどで使用 + D exclusion_* + 関連関数を消したので削除した + C struct map_data + C flag + A notrade + 取引禁止マップフラグ + A noskill + スキル使用禁止マップフラグ + 定数の追加 + SP_PARTNER SP_CART + SP_BREAK_WEAPON_RATE SP_BREAK_ARMOR_RATE SP_ADD_STEAL_RATE + SP_UNBREAKABLE_WEAPON SP_UNBREAKABLE_ARMOR + D talkie_mes[] + 定義削除 + C map_addchariddb() + 定義変更 + A map_delchariddb() + A map_eraseipport() + A map_who() + 定義追加 + C mob.c + D mob_exclusion_add() + D mob_exclusion_check() + 意味がある使用をされていないのとbattle_check_target()で代用できるので削除した + C mob_stop_walking() + type&4で目的の場所まで距離があれば1歩進んで止まるようにした + C mob_attack() + MobがMobを攻撃できるようにした + C mob_target() + C mob_ai_sub_hard_slavemob() + mob_exclusion_check()を削除 + C mob_ai_sub_hard_activesearch() + C mob_ai_sub_hard() + special_mob_aiな場合はMobも索敵するようにした + ルートモンスターが目標のアイテムを見失った時は目的の場所まで歩かないようにした + C mob_damage() + スフィアマインが殴られた時に自爆しなかったのを修正した + スフィアマインが殴られて自爆する時に移動するようにした + srcがMobの時はsrcのターゲットを外すようにした + C mob_skillid2skillidx() + インデックスが0から始まるのにエラーも0を返すしていたのを修正した + スフィアマインが殴られても自爆しない原因はこれ + C mobskill_use() + 自爆状態ではスキルを使用できないようにした + C mob_spawn() + ガーディアンとエンペリウムが砦で発生した場合は guild_id を設定 + opt3 を 0 で初期化 + C mob_can_reach() + GvG以外ではガーディアンは何もしないようにした + C mob_catch_delete() + Mobが消えるときのエフェクトを type で指定できるようにした + C mob_timer_delete() + スフィアマインとバイオプラントが消えるときはテレポエフェクトで消えるようにした + C mob_deleteslave_sub() + nullチェック前に代入している部分を修正 + C mob_class_change() + clif_class_change() の変更に対応 + C mob.h + C mob_catch_delete() + 定義変更 + D mob_exclusion_add() + D mob_exclusion_check() + 定義削除 + C npc.c + C struct npc_src_list + A prev + 終了時のメモリ開放用に追加 + C npc_checknear() + イベントPCの場合に常にOKを返していなかったのを修正 + A npc_enable_sub() + npc_enable() から呼ばれて周囲のPCにOnTouchイベントを実行する + C npc_enable() + flag による挙動を追加 + flag=2 NPCのHide状態を解除する + flag=4 NPCをHide状態にする + HideしているNPCは無効になります + 有効にした時に npc_enable_sub() を呼ぶようにした + C npc_event() + エラー時は1を返すように変更 + OnTouchイベントから呼ばれたときはイベントが見つからないエラーを返さないようにした + C npc_touch_areanpc() + PCがエリア内を通った時に何度も実行されるのを修正 + NPCにOnTouchイベントがあった場合には実行するようにした + 互換性を保つためにOnTouchイベントが無い場合は今までと同じように動きます + C npc_parse_warp() + option,opt1,opt2,opt3 を 0 で初期化 + C npc_parse_warp() + C npc_parse_shop() + IDをnpc_get_new_npc_id()で取得するようにした + option,opt1,opt2,opt3 を 0 で初期化 + C npc_convertlabel_db() + メモリ確保後にnullかどうか確認していないのを修正 + C npc_parse_script() + bad duplicate name!エラー表示が改行されていなかったのを修正 + 終了時メモリ開放用にduplicateで src_id を挿入 + IDをnpc_get_new_npc_id()で取得するようにした + option,opt1,opt2,opt3 を 0 で初期化 + C npc_parse_mob() + memwatch対策でメモリを一括確保しないようにした + モンスター名に --ja-- --en-- を指定するとmob_dbの名前を使うようにした + IDをnpc_get_new_npc_id()で取得するようにした + C npc_parse_mapflag() + notrade noskill を読み込むようにした + A ev_db_final() + A npcname_db_final() + A do_final_npc() + 終了時にメモリを開放するようにした + C do_init_npc() + メモリを開放するようにした + C npc.h + A do_final_npc() + 定義の追加 + C party.c + A party_db_final() + A do_final_party() + 終了時にメモリを開放するようにした + C party.h + A do_final_party() + 定義の追加 + C pc.c + A pc_numisGM() + account_idでGMかどうか判断する + A pc_isquitable() + PCが終了できる状態にあるかどうか判断する + 1を返すときは終了できない + C pc_counttargeted_sub() + Mob状態によって値を正しく返さないような気がするので条件を仮変更 + C pc_makesavestatus() + マナーポイントが正数の場合は 0 にする + C pc_authok() + wis_all を 0 で初期化 + map_addchariddb() の変更に対応と常に実行するようにした + C pc_calcstatus() + break_weapon_rate break_armor_rate add_steal_rate を 0 で初期化 + 結婚状態では歩く速度が半分になるようにした + C pc_bonus() + SP_UNBREAKABLE_WEAPON SP_UNBREAKABLE_ARMOR SP_BREAK_WEAPON_RATE SP_BREAK_ARMOR_RATE SP_ADD_STEAL_RATE + 処理を追加 + C pc_dropitem() + アイテムを捨てられるかどうか判定するようにした + C pc_putitemtocart() + アイテムをカートに移動できるか判定するようにした + C pc_steal_item() + スティール率に add_steal_rate を加算するようにした + C pc_walk() + C pc_movepos() + 範囲NPCがいないときには areanpc_id=0 にした + C pc_checkbaselevelup() + スパノビがレベルアップした時にかかるスキルのレベルを本鯖にあわせた + C pc_skillup() + guild_skillup() の変更に対応 + C pc_damage() + スパノビがExp99%でHPが0になるとHPが回復して金剛状態になるようにした + C pc_readparam() + nullチェック前にsdを使っていたのを修正 + A SP_PARTNER + 結婚相手のchar_id + A SP_CART + カートを引いている場合は0以上が返る + C pc_jobchange() + マナーポイントが負数の場合は赤エモ表示するようにした + A pc_break_weapon() + 武器破壊をする + A pc_break_armor() + 鎧破壊をする + C pc_natural_heal_sp() + スパノビは爆裂状態でもSPが自然回復するようにした + A gm_account_db_final() + A do_final_pc() + 終了時にメモリ開放するようにした + C pc.h + A pc_numisGM() + A pc_isquitable() + A pc_break_weapon() + A pc_break_armor() + A do_final_pc() + 定義追加 + C pet.c + C pet_data_init() + C pet_lootitem_drop() + メモリ確保できたかどうか確認していなかったので修正 + C pet_catch_process2() + mob_catch_delete() の変更に対応 + C script.c + 追加した関数のプロトタイプを先頭に追加 + buildin_func[]に追加した命令や関数を追加 + 演算子に C_R_SHIFT C_L_SHIFT を追加 + C parse_subexpr() + 演算子 >> << 追加 + C get_val() + PC主体の変数でPCがアタッチされていなかったらエラーを出すようにした + PC主体の変数でsd=NULLだった場合にはpc_read*で取得に行かないようにした + A buildin_close2() + スクリプトを中断してCloseボタンを表示します + C buildin_areawarp_sub() + RandomだけでなくSavePointにも飛ばせるようにした + A buildin_cutincard() + カードのアイテムIDを指定することでカード画像を表示します + C buildin_getitem() + 引数を変更して鑑定した状態で渡すかどうかを指定できるようにした + account_idを指定することで、そのPCにアイテムを渡せるようにした(結婚用拡張) + C buildin_getitem2() + account_idを指定することで、そのPCにアイテムを渡せるようにした(結婚用拡張) + C buildin_readparam() + キャラ名を指定することで、そのPCのパラメータを読み取れるようにした + C buildin_getcharid() + キャラ名を指定することで、そのPCの関係IDを取得できるようにした + A buildin_getpartymember() + 指定IDのパーティ人数の取得とパーティーメンバーのIDを配列で取得できます + A buildin_guildskill() + ギルドスキルを覚えることができます + C buildin_getgdskilllv() + ギルドスキルIDをGD_APPROVALのようなスキル名で指定するようにした + A buildin_hideoffnpc() + Hide状態のNPCを表示する + A buildin_hideonnpc() + NPCをHide状態にする + C buildin_sc_start() + ID指定したキャラを状態異常にできるようにした + A buildin_sc_start2() + 確率指定でキャラを状態異常にできます(アイス、おもち等で使用) + A buildin_getscrate() + 状態異常耐性を計算した確率を返す + C buildin_changebase() + IDで指定したキャラの見た目を変更することができるようにした + C buildin_waitingroom() + limit=0の時は(1/10)を表示しないようにした + C buildin_setmapflag() + MF_NOTRADE MF_NOSKILL を追加 + C buildin_flagemblem() + NPCが特定できなかったときにmap-serverが落ちる問題を修正 + A buildin_getinventorylist() + 配列で所持品を返します + A buildin_getskilllist() + 配列で所有スキルを返します + A buildin_clearitem() + 所持アイテムを削除します + A buildin_getrepairableitemcount() + 壊れているアイテムを数えます + A buildin_repairitem() + 壊れているアイテムをすべて修理します + A buildin_classchange() + NPCをクラスチェンジします + A buildin_misceffect() + エフェクトを表示します + A buildin_soundeffect() + 指定したSEを鳴らします + C op_2num() + C run_script_main() + シフト演算子を追加 + A mapreg_db_final() + A mapregstr_db_final() + A scriptlabel_db_final() + A userfunc_db_final() + C do_final_script() + 終了時にメモリを開放するようにした + C skill.c + <timer.h> intif.h をinclude + コメントのスキル名をjRO仕様に書き換え + C SkillStatusChangeTable[] + ベナムスプラッシャー グラフィティ 自爆 自爆2 を追加 + C skill_additional_effect() + ベナムスプラッシャー追加 + アンクルスネアを削除 + C skill_attack() + チャット中にスキルが影響しないようにした(チャットキャンセル) + ベナムスプラッシャーはSkillLv=-1でclif_skill_damage()するようにした + 自爆はダメージ表示しないようにした + C skill_castend_damage_id() + アシッドテラーで武器破壊をするようにした + ベナムスプラッシャーが3*3の範囲攻撃をするようにした + 自爆の処理を変更した + C skill_castend_nodamage_id() + sdとdstsdでPCかどうかを判定するようにした + スパノビの嫁がヒールを使うと回復量が2倍になるようにした + clif_sitting()の変更に対応 + 武器修理はパケットが分からないのでコメントアウト + ストリップ〜、ケミカル〜をスキルユニットに使用した場合、map-serverが落ちる問題を修正 + 君だけは護るよ、あなたの為に犠牲になりますの計算をMAX_HPまたはMAX_SPからするようにした + あなたに逢いたい を相手の名前を叫ぶ、複数設置できない等、本鯖風にした + アンクルスネアでPCが引っかかっている時にリムーブトラップしてもPCが動けるようにならなかったのを修正 + アンコールを叫ぶようにした + ベナムスプラッシャーを実装した + 自爆で自爆状態を開始するようにした + C skill_castend_pos2() + バイオプラント、スフィアマイン + パケット順番を変更 + 指定した場所に設置するようにした + 効果時間をskill_cast_db.txtで指定するようにした + mob_exclusion_add()を削除 + グラフィティを実装、1個しか置けません + C skill_castend_map() + ワープポータルは実際の設置時にブルージェムストーンを消費するようにした + C skill_unitsetting() + グラフィティのスキルユニットを1個に修正 + トーキーボックス、グラフィティの文字列は sd->message に格納するようにした + C skill_unit_onplace() + チャット時はスキルユニットが動作しないようにした(チャットキャンセル) + アンクルスネアにかかる処理をskill_additional_effect()から移動 + ワープポータルに術者が乗ったら消えるようにした + デモンストレーションによる武器破壊をするようにした + アンクルスネア、スパイダーウェッブでメモリアクセス違反が起きる可能性があったのを修正 + C skill_unit_onout() + アンクルスネアで「}」が足りなかったために近くを通りかかっただけで1秒後罠に戻ってしまったのを修正 + C skill_unit_onlimit() + ワープポータル発動前の処理を削除 + あなたに逢いたいを他map-serverにいても呼べるようにした + A skill_check_condition_mob_master_sub() + マップ内で同じPCから出たバイオプラントやスフィアマインの数を数える + C skill_check_condition() + hp_rateとsp_rateに負数を指定すると消費計算をMax値からするようにした + あなたに逢いたいを結婚していない状態で使ったら使用失敗を表示するようにした + バイオプラントとスフィアマインの設置数をskill_cast_db.txtで設定できるようにした + ファイアーウォールの数制限を skill_use_pos() から移動 + C skill_use_id() + バジリカをGvGでは使用できないようにした + ベナムスプラッシャーは対象が毒状態でなければ使用失敗 + C skill_use_pos() + ファイアーウォールの数制限を skill_check_condition() に移動 + C skill_status_change_end() + opt3の処理を追加 + 結婚状態の終了を追加 + ベナムスプラッシャーを追加 + 自爆を追加 + C skill_status_change_timer() + 結婚状態と赤エモ状態のタイマー再設定を追加 + 自爆状態では1秒ごとに速度が変化するようにした + C skill_status_change_start() + opt3の処理を追加 + グラフィティは追加で置いたら前のは消えるようにした + 結婚状態と赤エモ状態を追加 + グラフィティは状態異常開始時にスキルユニットを設置するようにした + ベナムスプラッシャーは特に何も追加はなし + 自爆は詠唱パケットをここで送るようにした + C skill_status_change_clear() + opt3の処理を追加 + C skill_unit_timer_sub() + ワープポータル発動前が時間切れになるときに見た目を変更して本鯖のように効果音が出るようにした + ブラストマイン以外の罠は時間切れで罠に戻るようにした + C skill.h + 状態異常にスキル名をいくつかつけたり、新規の状態異常を増やした + C storage.c + A storage_db_final() + A guild_storage_db_final() + C do_final_storage() + 終了時にメモリを開放するようにした + C trade.c + C trade_tradeadditem() + C trade_tradecommit() + itemdb_isdropable()で交換できないアイテムを判定するようにした + C vending.c + vending_purchasereq() + 金額計算をdoubleでするようにしてintで桁あふれしないようにした + +-------------------- +//1045 by TEILU + +・スティール、スティールコイン、スナッチャーの失敗メッセージが + レベルが1〜9の時に変だったので修正。 + (map/) + skill.c + +・精錬の可否を情報サイトを元にDBに設定。(頭装備はrusiさん作成分を使用) + (db/) + item_db.txt + +・ファイアーウォールが制限数を超えたときにスキル使用失敗が + 出るタイミングを変更。 + (map/) + skill.c + +・アブラカタブラ専用スキルをgm_all_skill設定時に表示できるように変更。 + battle_athena.confのgm_all_skill_add_abraにyesを設定すれば + スキルリストに表示されるようになります。 + (conf/) + battle_athena.conf + (db/) + skill_require_db.txt + (map/) + battle.c + battle.h + pc.c + +-------------------- +//1044 by TEILU + +・1042で@itemidentifyの権限の設定を忘れていたので追加。 + (conf/) + atcommand_athena.conf + +・スティール、スティールコイン、スナッチャーの失敗時に + 失敗メッセージを表示するように変更。 + (map/) + skill.c + +・アイテムDBに精錬可否フラグのカラムを追加 + 精錬の可否をDBを参照するように修正 + ※とりあえず中段、下段、中下段の頭装備とアクセサリ以外の + 装備品はすべて精錬可の設定でDBを作りました。 + DBは修正が必要になります。 + (db/) + item_db.txt + (map/) + itemdb.c + itemdb.h + script.c + +-------------------- +//1043 by dusk +・docフォルダ・confフォルダ内のhelp.txtに1042(TEILUさん)の説明追加 + @itemidentifyの説明は72行目の@itemresetの下に。 + +・Valkyrie Realms 5 (右上)の旗の修正 + Valkyrie Realms 5 (右上)の旗を見ると未取得状態コメントばっかり出ていたのを + ちゃんと確認できるように。 + ※ Valkyrie Realmsの各砦に戻る旗とは違います。 + prtg_cas05.txt内のギルドダンジョンに入るレバー以外の + getcastledata "prtg_cas05.gat",1,@GIDp5;を + set @GIDp5,getcastledata("prtg_cas05.gat",1);に修正。 + +-------------------- +//1042 by TEILU + +・@healコマンドに何も渡さないと完全回復するように変更。 + (map/) + atcommand.c + +・@itemitemidentifyコマンドの追加 + 未鑑定の所持アイテムを全て鑑定します。 + (conf/) + msg_athena.conf + (map/) + atcommand.c + atcommand.h + +-------------------- +//1041 by mare + FIX NPC Script Command - buildin_getgdskilllv() + Add NPC Sctipt Command - buildin_agitcheck() + (script/npc/job/) + npc_job_wizard.txt + ラウレルさんの台詞、ノビとプリの場合の分追加 +------------------- +//1040 by 胡蝶蘭 + +・サーバー間接続のパケット表追加 + (doc/) + serverlink_packet.txt + inter<->map 以外のサーバー間接続のパケット表 + +・仕様スレの Login_ID2 関係でごにょごにょ +・サーバー間接続のパケット一部変更 + (login/) + login.c + auth_fifo に ip メンバ追加 + パケット変更に伴う変更他 + (char/) + char.c + auth_fifo に login_id2, ip メンバ追加 + パケット変更に伴う変更他 + (map/) + chrif.c + chrif_authok()追加 + パケット変更に伴う変更他 + +・自動再起動スクリプト start にコメントで簡単な説明追加 + start + コメント追加 + +-------------------- +//1039 by Ni+S + ・ギルド関係のスクリプト + 所有者の居ないアジトから、ギルドに所属してないキャラなら + ギルドダンジョンに入れてしまうという不具合がありました + + これは、所有者の居ないアジトの値が0であり、 + getcharid(2)でギルドIDを返すのですが、 + ギルドに所属していないキャラはgetcharid(2)で0を返す為、 + 値が一致してしまい起こっていた現象でした + 未所属キャラが入れないように修正しました + + ・ファーマシー/ポーション作成DB + レッドスリムポーション + イエロースリムポーション + ホワイトスリムポーション + の材料を、空のポーション瓶から試験管に修正 + +-------------------- +//1038 by Plala +・転職NPC関連の重大なバグ修正 + (script/npc/job) + npc_job_aco.txt 修正 + npc_job_merchant.txt 修正 + npc_job_thief.txt 修正 + + ・上記NPCで途中までクエストを進めて他の職に転職すると、 + 再び転職可能だった点を修正しました + + +-------------------- +//1037 by 胡蝶蘭 + +** FOR ENGLISH DEVELOPERS ** +DO NOT UPLOAD IF YOU DON'T USE JAPANESE ENCODE (SHIFT-JIS) ! +WHY WE(JAPANESE) REPAIR ERROR CHARACTER AFTER EVERY YOUR UPLOADING ? +BREAKING IS EASY, REPAIRING IS VERY DIFFICULT ! + +** 英語圏の開発者の方へ(日本語訳) ** +日本語エンコード(シフトJIS)を使う気が無いならアップロードしないてください! +なぜ我々(日本人)があなた方のアップロードのたびに文字化けを直さなければならないんですか? +壊すのは簡単ですが、直すのはとても難しいんです! + +・文字化けを根性で修正 + (map/) + script.c + +・ladminがPOSIX必須に。Digest::MD5が無くても実行できるように修正 +・serverstatus.cgiで、Net::Pingが無くても実行できるように修正 + (bin/tool/) + ladmin + (bin/tool/cgi/) + serverstatus.cgi + +・script_refで抜けてるものでわかるものを修正 + 何故かscript_refから抜けてるもの(getargなど)の一部を再び追加 + ** アップロードするときは最新パッチからの差分をアップロードしましょう ** + (doc/) + script_ref.txt + +・account_making.txt修正 + ladminスクリプトのパス + (doc/) + accoun_tmaking.txt + +-------------------- +//1036 by Michael +・追加 Script Command: + getequipid(EquipPos); EquipPos: 1-10 + gettimetick(Type); Type: 0 SystemTick, 1 TimeSecondTick(0-86399) + gettime(Type); Type: 1 Sec, 2 Min, 3 Hour, 4 Weekday, 5, Monthday, 6 Month, 7 Year + gettimestr("TimeFMT", Len); TimeFMT: Time format strinf / Len: String Length + + (map/) + script.c + buildin_getequipid(); 追加 + buildin_gettimetick(); 追加 + buildin_gettime(); 追加 + buildin_gettimestr(); 追加 + +-------------------- +//1035 by Michael +・追加 GVG Script NPC edit from Aegis NPC(Chinese-big5 version), Please someone translate to Japanese. +・修正 NPC Script Command - buildin_getgdskilllv() + getgdskilllv(Guild_ID, Skill_ID); + + (map/) + script.c + buildin_getgdskilllv() 修正 + +-------------------- +//1034 by (Pepermint) + FIX NPC Script Command - buildin_getgdskilllv() + Add NPC Sctipt Command - buildin_agitcheck() + (map/) + script.c + buildin_getgdskilllv() 修正 + buildin_agitcheck() 追加 + +-------------------- +//1033 by Michael +・追加 NPC Script Command - buildin_getgdskilllv() + getgdskilllv(Guild_ID, Skill_ID); + skill_id = 1:GD_APPROVAL,2:GD_KAFRACONTACT,3:GD_GUARDIANRESEARCH,4:GD_CHARISMA,5:GD_EXTENSION + + (map/) + script.c + buildin_getgdskilllv() 追加 + +-------------------- //1032 by (凸) ・1031で何故か削除されていたbuildin_getitemname()を復活 ・バグスレなどに出た修正を反映 @@ -17,7 +2937,7 @@ script.c buildin_getitemname() 復活 ----------------------------------------- +-------------------- //1031 by huge ・NPCのscriptに、makepetを追加。 makepet 卵ID; で、ペットを作成します。 @@ -110,11 +3030,11 @@ pc.c pc_calcstatus() 変更 skill.c - + skill_status_change_end() 変更 skill_status_change_start() 変更とNULLチェック修正 skill.h 変更 - + -------------------- //1027 by Ni+S ・getitemname関数追加 @@ -125,7 +3045,7 @@ script.c getitemname()追加 ----------------------------------------- +-------------------- //1026 by (凸) ・1023で入れてなかったclif.hを同梱 ・バイオプラントとスフィアーマインで出したmobを倒すとmob_timer_delete()でnullpoが出る問題を解決したつもり @@ -150,7 +3070,6 @@ ・オーラブレード武器制限を素手以外全てに修正 ・コンセントレーション武器制限を両手槍のみから片手槍+両手槍へ修正 ・トゥルーサイト効果時間を修正 -・ファルコンアサルト武器制限を解除、素手を含めた全てで使用可能に (db/) job_db2-2.txt 変更 @@ -164,7 +3083,7 @@ (db/) produce_db.txt 変更 ----------------------------------------- +-------------------- //1023 by (凸) ・1022でエンバグしたnpc_parse_script()を戻し ・スパイラルピアースの重量追加ダメージ計算式をちょっと変更 @@ -403,14 +3322,18 @@ -------------------- //1014 by (Pepermint) -I fixed again the problem if you put minus sign(-) in front of digits, +I fixed again the problem if you put minus sign(-) in front of digits, the error comes up when you puchase a item. -When you put a minus sign(-), the error sign will be changed shrotage of +When you put a minus sign(-), the error sign will be changed shrotage of amount as original server dose. I tested with it in ver. 1013, it was working -------------------- +//1013 by (凸) +・サーバースナップショット + +-------------------- //1012 by (凸) ・help.txtにある@goの説明から13と14を削除 機能は消えてないので使えることは使えますが、helpに載せるのはjROに来てからということで diff --git a/db/skill_cast_db.txt b/db/skill_cast_db.txt index 92e458588..93badb7a2 100644 --- a/db/skill_cast_db.txt +++ b/db/skill_cast_db.txt @@ -16,7 +16,7 @@ 18,2000:1850:1700:1550:1400:1250:1100:950:800:650,0,5000:6000:7000:8000:9000:10000:11000:12000:13000:14000,0 //MG_FIREWALL#ファイアーウォール# 19,700:1400:2100:2800:3500:4200:4900:5600:6300:7000,1000:1200:1400:1600:1800:2000:2200:2400:2600:2800,0,0 //MG_FIREBOLT#ファイアーボルト# 20,700:1400:2100:2800:3500:4200:4900:5600:6300:7000,1000:1200:1400:1600:1800:2000:2200:2400:2600:2800,0,0 //MG_LIGHTNINGBOLT#ライトニングボルト# -21,1000:2000:3000:4000:5000:6000:7000:8000:9000:10000,2000,0,0 //MG_THUNDERSTORM#サンダーストーム# +21,1000:2000:3000:4000:5000:6000:7000:8000:9000:10000,2000,500,0 //MG_THUNDERSTORM#サンダーストーム# 24,0,0,10000,0 //AL_RUWACH#ルアフ# 25,0,0,10000,0 //AL_PNEUMA#ニューマ# @@ -62,17 +62,17 @@ 78,0,3000,600000,0 //PR_LEXAETERNA#レックスエーテルナ# 79,15000,4000,5000:6000:7000:8000:9000:10000:11000:12000:13000:14000,0 //PR_MAGNUS#マグヌスエクソシズム# 80,3000:2700:2400:2100:1800:1500:1200:900:600:300,2000,30000,0 //WZ_FIREPILLAR#ファイアーピラー# -81,700,2000,0,0 //WZ_SIGHTRASHER#サイトラッシャー# +81,700,2000,500,0 //WZ_SIGHTRASHER#サイトラッシャー# -83,15000,2000:3000:3000:4000:4000:5000:5000:6000:6000:7000,0,3200:3400:3600:3800:4000:4200:4400:4600:4800:5000 //WZ_METEOR#メテオストーム# +83,15000,2000:3000:3000:4000:4000:5000:5000:6000:6000:7000,500,3200:3400:3600:3800:4000:4200:4400:4600:4800:5000 //WZ_METEOR#メテオストーム# 84,2500:3000:3500:4000:4500:5000:5500:6000:6500:7000,0,0,0 //WZ_JUPITEL#ユピテルサンダー# -85,15000:14500:14000:13500:13000:12500:12000:11500:11000:10500,5000,0,5500:6000:6500:7000:7500:8000:8500:9000:9500:10000 //WZ_VERMILION#ロードオブヴァーミリオン# +85,15000:14500:14000:13500:13000:12500:12000:11500:11000:10500,5000,4100,5500:6000:6500:7000:7500:8000:8500:9000:9500:10000 //WZ_VERMILION#ロードオブヴァーミリオン# 86,1000:2000:3000:4000:5000,0,0,0 //WZ_WATERBALL#ウォーターボール# 87,0,0,5000:10000:15000:20000:25000:30000:35000:40000:45000:50000,0 //WZ_ICEWALL#アイスウォール# 88,5000:4700:4400:4100:3800:3500:3200:2900:2700:2500,1000,0,3000:3500:4000:4500:5000:5500:6000:6500:7000:7500 //WZ_FROSTNOVA#フロストノヴァ# -89,6000:7000:8000:9000:10000:11000:12000:13000:14000:15000,5000,0,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000 //WZ_STORMGUST#ストームガスト# +89,6000:7000:8000:9000:10000:11000:12000:13000:14000:15000,5000,4600,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000 //WZ_STORMGUST#ストームガスト# 90,1000:2000:3000:4000:5000,700,0,0 //WZ_EARTHSPIKE#アーススパイク# -91,1000:2000:3000:4000:5000,700,0,0 //WZ_HEAVENDRIVE#ヘヴンズドライブ# +91,1000:2000:3000:4000:5000,700,500,0 //WZ_HEAVENDRIVE#ヘヴンズドライブ# 92,0,1000,5000:10000:15000:20000:25000,5000:10000:15000:20000:25000 //WZ_QUAGMIRE#クァグマイア# 110,0,0,0,6000:7000:8000:9000:10000:11000 //BS_HAMMERFALL#ハンマーフォール# @@ -155,7 +155,7 @@ 251,0,700,0,0 //CR_SHIELDBOOMERANG#シールドブーメラン# 252,0,0,300000,0 //CR_REFLECTSHIELD#リフレクトシールド# 253,0,0,0,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000 //CR_HOLYCROSS#ホーリークロス# -254,3000,1500,0,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000 //CR_GRANDCROSS#グランドクロス# +254,3000,1500,1000,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000 //CR_GRANDCROSS#グランドクロス# 256,3000,0,180000,0 //CR_PROVIDENCE#プロヴィデンス# 257,0,800,180000,0 //CR_DEFENDER#ディフェンダー# @@ -218,6 +218,8 @@ 335,3000,0,0,0 //WE_FEMALE#あなたに尽くします# 336,0,0,10000,0 //WE_CALLPARTNER#あなたに逢いたい# +339,3000,1500,1000,10000:11000:12000:13000:14000:15000:16000:17000:18000:19000 //NPC_DARKGRANDCROSS#闇グランドクロス + 355,0,0,40000:60000:80000:100000:120000,0 //LK_AURABLADE#オーラブレード# 356,0,0,15000:20000:25000:30000:35000:40000:45000:50000:55000:60000,0 //LK_PARRYING#パリイング# 357,0,0,25000:30000:35000:40000:45000,0 //LK_CONCENTRATION#コンセントレーション# @@ -270,6 +272,10 @@ 476,1000,1000,75000:90000:105000:120000:135000,0 //ST_FULLSTRIP## 479,2000,0,120000:240000:360000:480000:600000,0 //CR_FULLPROTECTION## +10006,0,0,300000,0 //GD_LEADERSHIP## +10007,0,0,300000,0 //GD_GLORYWOUNDS## +10008,0,0,300000,0 //GD_SOULCOLD## +10009,0,0,300000,0 //GD_HAWKEYES## 10010,100,1000,60000,0 //GD_BATTLEORDER## 10011,100,1000,60000,0 //GD_REGENERATION## 10012,100,1000,0,0 //GD_RESTORE## diff --git a/db/skill_db.txt b/db/skill_db.txt index d7b4fd9d0..c66c43a33 100644 --- a/db/skill_db.txt +++ b/db/skill_db.txt @@ -454,7 +454,7 @@ 394,8,8,1,0,0,10,9,no,0,0,0,weapon,0 //CG_ARROWVULCAN#アロ?バルカン# 395,0,0,4,0,1,1,1,yes,0,0,0,magic,0 //CG_MOONLIT#月明りの泉に落ちる花びら# 396,0,6,16,0,1,1,1,yes,0,0,0,magic,1 //CG_MARIONETTE#?リオネットコントロ?ル# -397,4,8,1,0,0,5,1,no,0,0,0,weapon,0 //LK_SPIRALPIERCE#スパイラルピア?ス# +397,4,8,1,0,0,5,5,no,0,0,0,weapon,0 //LK_SPIRALPIERCE#スパイラルピア?ス# 398,4,6,1,0,0,5,1,no,0,0,0,weapon,0 //LK_HEADCRUSH#ヘッドクラッシュ# 399,4,6,1,0,0,10,1,no,0,0,0,weapon,0 //LK_JOINTBEAT#ジョイントビ?ト# 400,8,8,1,8,0,5,1:2:3:4:5,yes,0,0,0,magic,0 //HW_NAPALMVULCAN#ナパ??バルカン# diff --git a/db/skill_unit_db.txt b/db/skill_unit_db.txt new file mode 100644 index 000000000..9c0616e30 --- /dev/null +++ b/db/skill_unit_db.txt @@ -0,0 +1,78 @@ +// id,unit,unit,layout,range,interval,target,flag +// position -1:特殊, 0:1*1, 1:3*3, 2:5*5,..., 5:11*11 +// target friend:NOENEMY, party:PARTY, 0x20000:BCT_ALL, enemy:ENEMY +// flag 0x001(UF_DEFNOTENEMY) defunit_not_enemyの影響を受ける +// 0x002(UF_NOREITERRATION) 重ね置き不可 +// 0x004(UF_NOFOOTSET) 足元置き不可 +// 0x008(UF_NOOVERLAP) 効果が重複しない +// 0x100(UF_DANCE) ダンススキル +// 0x200(UF_ENSEMBLE) 合奏スキル +// +// 0x89,0x8a,0x8b 表示無し +// 0x9a 炎属性の詠唱みたいなエフェクト +// 0x9b 水属性の詠唱みたいなエフェクト +// 0x9c 風属性の詠唱みたいなエフェクト +// 0x9d 白い小さなエフェクト +// +// u1 u2 lay r intr target flag + 12,0x7e, , 0, 0, -1,all, 0x003 //MG_SAFETYWALL#セイフティウォール + 18,0x7f, , -1, 0, 1,enemy, 0x000 //MG_FIREWALL#ファイアーウォール + 21,0x86, , 0, 1,1000,enemy, 0x008 //MG_THUNDERSTORM#サンダーストーム + 25,0x85, , 1, 0, -1,all, 0x003 //AL_PNEUMA#ニューマ + 27,0x81,0x80, 0, 0, -1,all, 0x002 //AL_WARP#ワープポータル + 70,0x83, , -1, 1,1000,all, 0x000 //PR_SANCTUARY#サンクチュアリ + 79,0x84, , -1, 1,3000,enemy, 0x000 //PR_MAGNUS#マグヌスエクソシズム + 80,0x87,0x88, 0, 1,2000,enemy, 0x002 //WZ_FIREPILLAR#ファイアーピラー + 83,0x86, , 0, 3,1000,enemy, 0x000 //WZ_METEOR#メテオストーム + 85,0x86, , 0, 6,1000,enemy, 0x008 //WZ_VERMILION#ロードオブヴァーミリオン + 87,0x8d, , -1, 0, -1,all, 0x000 //WZ_ICEWALL#アイスウォール + 88,0x86, , 0, 2,1000,enemy, 0x000 //WZ_FROSTNOVA#フロストノヴァ + 89,0x86, , 0, 5, 450,enemy, 0x000 //WZ_STORMGUST#ストームガスト + 91,0x86, , 0, 2,1000,enemy, 0x000 //WZ_HEAVENDRIVE#ヘヴンズドライブ + 92,0x8e, , 2, 0, -1,enemy, 0x000 //WZ_QUAGMIRE#クァグマイア +115,0x90, , 0, 1,1000,enemy, 0x002 //HT_SKIDTRAP#スキッドトラップ +116,0x93, , 0, 1,1000,enemy, 0x002 //HT_LANDMINE#ランドマイン +117,0x91, , 0, 1,1000,enemy, 0x002 //HT_ANKLESNARE#アンクルスネア +118,0x94, , 0, 1,1000,enemy, 0x002 //HT_SHOCKWAVE#ショックウェーブトラップ +119,0x95, , 0, 2,1000,enemy, 0x002 //HT_SANDMAN#サンドマン +120,0x96, , 0, 1,1000,enemy, 0x002 //HT_FLASHER#フラッシャー +121,0x97, , 0, 1,1000,enemy, 0x002 //HT_FREEZINGTRAP#フリージングトラップ +122,0x8f, , 0, 1,1000,enemy, 0x002 //HT_BLASTMINE#ブラストマイン +123,0x98, , 0, 2,1000,enemy, 0x002 //HT_CLAYMORETRAP#クレイモアトラップ +125,0x99, , 0, 1,1000,all, 0x002 //HT_TALKIEBOX#トーキーボックス +140,0x92, , -1, 0,1000,enemy, 0x000 //AS_VENOMDUST#ベナムダスト +220,0xb0, , 0, 0, -1,all, 0x002 //RG_GRAFFITI#グラフィティ +229,0xb1, , 0, 1,1000,enemy, 0x000 //AM_DEMONSTRATION#デモンストレーション +254,0x86, , -1, 0, 300,enemy, 0x000 //CR_GRANDCROSS#グランドクロス +285,0x9a, , 3, 0, -1,all, 0x000 //SA_VOLCANO#ボルケーノ +286,0x9b, , 3, 0, -1,all, 0x000 //SA_DELUGE#デリュージ +287,0x9c, , 3, 0, -1,all, 0x000 //SA_VIOLENTGALE#バイオレントゲイル +288,0x9d, , 3, 0, -1,all, 0x000 //SA_LANDPROTECTOR#ランドプロテクター +306,0x9e, , 4, 0, -1,all, 0x300 //BD_LULLABY#子守歌 +307,0x9f, , 4, 0, -1,party, 0x300 //BD_RICHMANKIM#ニヨルドの宴 +308,0xa0, , 4, 0, -1,enemy, 0x300 //BD_ETERNALCHAOS#永遠の混沌 +309,0xa1, , 4, 0, -1,party, 0x300 //BD_DRUMBATTLEFIELD#戦太鼓の響き +310,0xa2, , 4, 0, -1,party, 0x300 //BD_RINGNIBELUNGEN#ニーベルングの指輪 +311,0xa3, , 4, 0, -1,all, 0x300 //BD_ROKISWEIL#ロキの叫び +312,0xa4, , 4, 0, -1,party, 0x300 //BD_INTOABYSS#深淵の中に +313,0xa5, , 4, 0, -1,party, 0x300 //BD_SIEGFRIED#不死身のジークフリード +317,0xa6, , 3, 0, -1,enemy, 0x100 //BA_DISSONANCE#不協和音 +319,0xa7, , 3, 0, -1,friend,0x100 //BA_WHISTLE#口笛 +320,0xa8, , 3, 0, -1,friend,0x100 //BA_ASSASSINCROSS#夕陽のアサシンクロス +321,0xa9, , 3, 0, -1,friend,0x100 //BA_POEMBRAGI#ブラギの詩 +322,0xaa, , 3, 0, -1,friend,0x100 //BA_APPLEIDUN#イドゥンの林檎 +325,0xab, , 3, 0, -1,enemy, 0x100 //DC_UGLYDANCE#自分勝手なダンス +327,0xac, , 3, 0, -1,friend,0x100 //DC_HUMMING#ハミング +328,0xad, , 3, 0, -1,enemy, 0x100,0 //DC_DONTFORGETME#私を忘れないで… +329,0xae, , 3, 0, -1,friend,0x100,0 //DC_FORTUNEKISS#幸運のキス +330,0xaf, , 3, 0, -1,party, 0x100,0 //DC_SERVICEFORYOU#サービスフォーユー +336,0xb2, , 0,-1, -1,all, 0x000,0 //WE_CALLPARTNER#あなたに逢いたい +339,0x86, , -1, 0, 300,enemy, 0x000,0 //NPC_DARKGRANDCROSS#闇グランドクロス +362,0xb4, , 0, 3, 300,all, 0x000,0 //HP_BASILICA#バジリカ +369,0xb3, , 3, 0, -1,all, 0x000,0 //PA_GOSPEL#ゴスペル +404,0xb6, , -1, 0, -1,all, 0x000,0 //PF_FOGWALL#フォグウォール +405,0xb7, , 0, 1,1000,enemy, 0x002,0 //PF_SPIDERWEB#スパイダーウェッブ +10006,0xc1, , 0, 2, -1,all, 0x000,0 //GD_LEADERSHIP +10007,0xc2, , 0, 2, -1,all, 0x000,0 //GD_GLORYWOUNDS +10008,0xc3, , 0, 2, -1,all, 0x000,0 //GD_SOULCOLD +10009,0xc4, , 0, 2, -1,all, 0x000,0 //GD_HAWKEYES diff --git a/src/char/Makefile b/src/char/Makefile index 3c09db92c..aee0e69e2 100644 --- a/src/char/Makefile +++ b/src/char/Makefile @@ -1,7 +1,7 @@ all: char-server txt: char-server -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/lock.o ../common/malloc.o ../common/showmsg.o ../common/strlib.o +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/lock.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/lock.h ../common/timer.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h char-server: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o $(COMMON_OBJ) $(CC) -o ../../$@ $> $(LIB_S) diff --git a/src/char_sql/Makefile b/src/char_sql/Makefile index e206dd211..1741b5ab6 100644 --- a/src/char_sql/Makefile +++ b/src/char_sql/Makefile @@ -1,7 +1,7 @@ all: char-server_sql sql: char-server_sql -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o ../common/utils.o ../common/strlib.o +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o ../common/obj/strlib.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h char-server_sql: char.o inter.o int_party.o int_guild.o int_storage.o int_pet.o itemdb.o $(COMMON_OBJ) diff --git a/src/common/Makefile b/src/common/Makefile index eaa7205d2..c387c2e01 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -1,15 +1,23 @@ -txt sql all: core.o socket.o timer.o grfio.o db.o lock.o nullpo.o malloc.o showmsg.o - -core.o: core.c core.h showmsg.h -socket.o: socket.c socket.h mmo.h showmsg.h -timer.o: timer.c timer.h showmsg.h -grfio.o: grfio.c grfio.h showmsg.h -db.o: db.c db.h showmsg.h -lock.o: lock.h showmsg.h -nullpo.o: nullpo.c nullpo.h showmsg.h -malloc.o: malloc.c malloc.h showmsg.h -showmsg.o: showmsg.c showmsg.h -strlib.o: strlib.c strlib.h utils.h +txt sql all: obj common + +obj: + mkdir obj + +common: obj/core.o obj/socket.o obj/timer.o obj/grfio.o obj/db.o obj/lock.o obj/nullpo.o obj/malloc.o obj/showmsg.o obj/strlib.o obj/utils.o + +obj/%.o: %.c + $(COMPILE.c) $(OUTPUT_OPTION) $< + +obj/core.o: core.c core.h showmsg.h +obj/socket.o: socket.c socket.h mmo.h showmsg.h +obj/timer.o: timer.c timer.h showmsg.h +obj/grfio.o: grfio.c grfio.h showmsg.h +obj/db.o: db.c db.h showmsg.h +obj/lock.o: lock.h showmsg.h +obj/nullpo.o: nullpo.c nullpo.h showmsg.h +obj/malloc.o: malloc.c malloc.h showmsg.h +obj/showmsg.o: showmsg.c showmsg.h +obj/strlib.o: strlib.c strlib.h utils.h clean: - rm -f *.o + rm -f *.o obj diff --git a/src/common/core.c b/src/common/core.c index fbd607080..016ade08d 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -9,10 +9,13 @@ #include <signal.h> #include <string.h> #ifdef DUMPSTACK -#include <execinfo.h> + #ifndef _WIN32 // HAVE_EXECINFO_H + #include <execinfo.h> + #endif #endif #include "../common/mmo.h" +#include "malloc.h" #include "core.h" #include "socket.h" #include "timer.h" @@ -92,44 +95,44 @@ static void sig_proc(int sn) * Dumps the stack using glibc's backtrace *----------------------------------------- */ -#ifdef DUMPSTACK static void sig_dump(int sn) { - FILE *fp; - void* array[20]; + #ifdef DUMPSTACK + FILE *fp; + void* array[20]; - char **stack; - size_t size; - int no = 0; - char tmp[256]; + char **stack; + size_t size; + int no = 0; + char tmp[256]; - // search for a usable filename - do { - sprintf(tmp,"save/stackdump_%04d.txt", ++no); - } while((fp = fopen(tmp,"r")) && (fclose(fp), no < 9999)); - // dump the trace into the file - if ((fp = fopen (tmp,"w")) != NULL) { + // search for a usable filename + do { + sprintf(tmp,"save/stackdump_%04d.txt", ++no); + } while((fp = fopen(tmp,"r")) && (fclose(fp), no < 9999)); + // dump the trace into the file + if ((fp = fopen (tmp,"w")) != NULL) { - fprintf(fp,"Exception: %s\n", strsignal(sn)); - fprintf(fp,"Stack trace:\n"); - size = backtrace (array, 20); - stack = backtrace_symbols (array, size); + fprintf(fp,"Exception: %s\n", strsignal(sn)); + fprintf(fp,"Stack trace:\n"); + size = backtrace (array, 20); + stack = backtrace_symbols (array, size); - for (no = 0; no < size; no++) { + for (no = 0; no < size; no++) { - fprintf(fp, "%s\n", stack[no]); + fprintf(fp, "%s\n", stack[no]); - } - fprintf(fp,"End of stack trace\n"); + } + fprintf(fp,"End of stack trace\n"); - fclose(fp); - free(stack); - } + fclose(fp); + free(stack); + } + #endif // When pass the signal to the system's default handler compat_signal(sn, SIG_DFL); raise(sn); } -#endif int get_svn_revision(char *svnentry) { // Warning: minor syntax checking char line[1024]; @@ -204,28 +207,20 @@ int main(int argc,char **argv) compat_signal(SIGPIPE,SIG_IGN); compat_signal(SIGTERM,sig_proc); compat_signal(SIGINT,sig_proc); - -#ifndef DUMPSTACK - // Signal to create coredumps by system when necessary (crash) - compat_signal(SIGSEGV, SIG_DFL); - compat_signal(SIGFPE, SIG_DFL); - compat_signal(SIGILL, SIG_DFL); - #ifndef _WIN32 - compat_signal(SIGBUS, SIG_DFL); - compat_signal(SIGTRAP, SIG_DFL); - #endif -#else + + // Signal to create coredumps by system when necessary (crash) compat_signal(SIGSEGV, sig_dump); compat_signal(SIGFPE, sig_dump); compat_signal(SIGILL, sig_dump); #ifndef _WIN32 compat_signal(SIGBUS, sig_dump); - compat_signal(SIGTRAP, SIG_DFL); + compat_signal(SIGTRAP, SIG_DFL); #endif -#endif display_title(); + do_init_memmgr(argv[0]); // 一番最初に実行する必要がある + tick_ = time(0); do_init(argc,argv); @@ -234,5 +229,6 @@ int main(int argc,char **argv) do_sendrecv(next); do_parsepacket(); } + return 0; } diff --git a/src/common/db.c b/src/common/db.c index 12d54176c..9f2c75a68 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -65,7 +65,7 @@ static unsigned int strdb_hash(struct dbt* table,void* a) return h; } -struct dbt* strdb_init(int maxlen) +struct dbt* strdb_init_(int maxlen,const char *file,int line) { int i; struct dbt* table; @@ -77,6 +77,9 @@ struct dbt* strdb_init(int maxlen) table->maxlen=maxlen; for(i=0;i<HASH_SIZE;i++) table->ht[i]=NULL; + table->alloc_file = file; + table->alloc_line = line; + table->item_count = 0; return table; } @@ -98,7 +101,7 @@ static unsigned int numdb_hash(struct dbt* table,void* a) return (unsigned int)a; } -struct dbt* numdb_init(void) +struct dbt* numdb_init_(const char *file,int line) { int i; struct dbt* table; @@ -110,6 +113,9 @@ struct dbt* numdb_init(void) table->maxlen=sizeof(int); for(i=0;i<HASH_SIZE;i++) table->ht[i]=NULL; + table->alloc_file = file; + table->alloc_line = line; + table->item_count = 0; return table; } @@ -400,6 +406,7 @@ struct dbn* db_insert(struct dbt *table,void* key,void* data) db_rebalance(p,&table->ht[hash]); } } + table->item_count++; return p; } @@ -428,12 +435,14 @@ void* db_erase(struct dbt *table,void* key) #else aFree(p); #endif + table->item_count--; return data; } void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) { int i,sp; + int count = 0; // red-black treeなので64個stackがあれば2^32個ノードまで大丈夫 struct dbn *p,*pn,*stack[64]; va_list ap; @@ -449,6 +458,7 @@ void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) // printf("Warning: no data for key %d in db_foreach (db.c) !\n",(int)p->key); //} else { func(p->key, p->data, ap); + count++; //} if((pn=p->left)!=NULL){ if(p->right){ @@ -466,6 +476,12 @@ void db_foreach(struct dbt *table,int (*func)(void*,void*,va_list),...) } } } + if(count != table->item_count) { + printf( + "db_foreach : data lost %d of %d item(s) allocated from %s line %d\n", + table->item_count - count,count,table->alloc_file,table->alloc_line + ); + } va_end(ap); } diff --git a/src/common/db.h b/src/common/db.h index ea9aceab0..c31f5bfaa 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -22,6 +22,9 @@ struct dbt { void (*release)(struct dbn*,int which); int maxlen; struct dbn *ht[HASH_SIZE]; + int item_count; // vf? + const char* alloc_file; // DB?t@C + int alloc_line; // DB?s }; #define strdb_search(t,k) db_search((t),(void*)(k)) @@ -34,9 +37,12 @@ struct dbt { #define numdb_erase(t,k) db_erase ((t),(void*)(k)) #define numdb_foreach db_foreach #define numdb_final db_final +#define strdb_init(a) strdb_init_(a,__FILE__,__LINE__) +#define numdb_init() numdb_init_(__FILE__,__LINE__) + +struct dbt* strdb_init_(int maxlen,const char *file,int line); +struct dbt* numdb_init_(const char *file,int line); -struct dbt* strdb_init(int maxlen); -struct dbt* numdb_init(void); void* db_search(struct dbt *table,void* key); void* db_search2(struct dbt *table, const char *key); // [MouseJstr] struct dbn* db_insert(struct dbt *table,void* key,void* data); diff --git a/src/common/grfio.c b/src/common/grfio.c index 0c628d163..224ea909e 100644 --- a/src/common/grfio.c +++ b/src/common/grfio.c @@ -32,21 +32,36 @@ #include "malloc.h" #ifdef _WIN32 - #include <windows.h> - #include "../lib/zlib_win32.h" - HINSTANCE zlib_dll; - #define zlib_inflateInit(strm) zlib_inflateInit_((strm),ZLIB_VERSION, sizeof(z_stream)) - #define zlib_deflateInit(strm, level) zlib_deflateInit_((strm),(level),ZLIB_VERSION,sizeof(z_stream)) - - int (WINAPI* zlib_inflateInit_) (z_streamp strm, const char *version, int stream_size); - int (WINAPI* zlib_inflate) (z_streamp strm, int flush); - int (WINAPI* zlib_inflateEnd) (z_streamp strm); - - int (WINAPI* zlib_deflateInit_) (z_streamp strm, int level, const char *version, int stream_size); - int (WINAPI* zlib_deflate) (z_streamp strm, int flush); - int (WINAPI* zlib_deflateEnd) (z_streamp strm); + #ifdef LOCALZLIB + #include "../lib/zlib/zlib.h" + #define zlib_inflateInit inflateInit + #define zlib_inflate inflate + #define zlib_inflateEnd inflateEnd + #define zlib_deflateInit deflateInit + #define zlib_deflate deflate + #define zlib_deflateEnd deflateEnd + #else + #include <windows.h> + #include "../lib/zlib_win32.h" + HINSTANCE zlib_dll; + #define zlib_inflateInit(strm) zlib_inflateInit_((strm),ZLIB_VERSION, sizeof(z_stream)) + #define zlib_deflateInit(strm, level) zlib_deflateInit_((strm),(level),ZLIB_VERSION,sizeof(z_stream)) + + int (WINAPI* zlib_inflateInit_) (z_streamp strm, const char *version, int stream_size); + int (WINAPI* zlib_inflate) (z_streamp strm, int flush); + int (WINAPI* zlib_inflateEnd) (z_streamp strm); + + int (WINAPI* zlib_deflateInit_) (z_streamp strm, int level, const char *version, int stream_size); + int (WINAPI* zlib_deflate) (z_streamp strm, int flush); + int (WINAPI* zlib_deflateEnd) (z_streamp strm); + #endif #else - #include <zlib.h> + #ifdef LOCALZLIB + #include "zlib/zlib.h" + #else + #include <zlib.h> + #endif + #define zlib_inflateInit inflateInit #define zlib_inflate inflate #define zlib_inflateEnd inflateEnd @@ -966,6 +981,16 @@ void grfio_final(void) } gentry_table = NULL; gentry_entrys = gentry_maxentry = 0; + +#ifdef _WIN32 + #ifndef LOCALZLIB + FreeLibrary(zlib_dll); + zlib_inflateInit_ = NULL; + zlib_inflate = NULL; + zlib_inflateEnd = NULL; + #endif +#endif + } /*========================================== @@ -979,6 +1004,7 @@ void grfio_init(char *fname) int result = 0, result2 = 0, result3 = 0, result4 = 0; #ifdef _WIN32 + #ifndef LOCALZLIB if(!zlib_dll) { zlib_dll = LoadLibrary("zlib.dll"); (FARPROC)zlib_inflateInit_ = GetProcAddress(zlib_dll,"inflateInit_"); @@ -992,6 +1018,7 @@ void grfio_init(char *fname) exit(1); } } + #endif #endif data_conf = fopen(fname, "r"); diff --git a/src/common/malloc.c b/src/common/malloc.c index 089a9db18..40c9f34bf 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -3,14 +3,25 @@ #include <string.h> #include "malloc.h" -#if !defined(DMALLOC) && !defined(GCOLLECT) && !defined(BCHECK) +#ifdef MEMWATCH +#include "memwatch.h" +#endif + +// 独自メモリマネージャを使用する場合、次のコメントを外してください。 +// #define USE_MEMMGR + +#if !defined(DMALLOC) && !defined(GCOLLECT) && !defined(BCHECK) && !defined(USE_MEMMGR) void* aMalloc_( size_t size, const char *file, int line, const char *func ) { void *ret; // printf("%s:%d: in func %s: malloc %d\n",file,line,func,size); +#ifdef MEMWATCH + ret=mwMalloc(size,file,line); +#else ret=malloc(size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: malloc error out of memory!\n",file,line,func); exit(1); @@ -23,7 +34,11 @@ void* aCalloc_( size_t num, size_t size, const char *file, int line, const char void *ret; // printf("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size); +#ifdef MEMWATCH + ret=mwCalloc(num,size,file,line); +#else ret=calloc(num,size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: calloc error out of memory!\n",file,line,func); exit(1); @@ -37,7 +52,11 @@ void* aRealloc_( void *p, size_t size, const char *file, int line, const char *f void *ret; // printf("%s:%d: in func %s: realloc %p %d\n",file,line,func,p,size); +#ifdef MEMWATCH + ret=mwRealloc(p,size,file,line); +#else ret=realloc(p,size); +#endif if(ret==NULL){ printf("%s:%d: in func %s: realloc error out of memory!\n",file,line,func); exit(1); @@ -46,10 +65,39 @@ void* aRealloc_( void *p, size_t size, const char *file, int line, const char *f return ret; } +void* aStrdup_( const void *p, const char *file, int line, const char *func ) +{ + void *ret; + + // printf("%s:%d: in func %s: strdup %p\n",file,line,func,p); +#ifdef MEMWATCH + ret=mwStrdup(p,file,line); +#else + ret=strdup(p); +#endif + if(ret==NULL){ + printf("%s:%d: in func %s: strdup error out of memory!\n",file,line,func); + exit(1); + + } + return ret; +} + +void aFree_( void *p, const char *file, int line, const char *func ) +{ + // printf("%s:%d: in func %s: free %p\n",file,line,func,p); +#ifdef MEMWATCH + mwFree(p,file,line); +#else + free(p); #endif +} +int do_init_memmgr(const char* file) { + return 0; +} -#if defined(GCOLLECT) +#elif defined(GCOLLECT) void * _bcallocA(size_t size, size_t cnt) { void *ret = aMallocA(size * cnt); @@ -62,7 +110,6 @@ void * _bcalloc(size_t size, size_t cnt) { memset(ret, 0, size * cnt); return ret; } -#endif char * _bstrdup(const char *chr) { int len = strlen(chr); @@ -70,3 +117,434 @@ char * _bstrdup(const char *chr) { strcpy(ret, chr); return ret; } + +#elif defined(USE_MEMMGR) + +/* USE_MEMMGR */ + +/* + * メモリマネージャ + * malloc , free の処理を効率的に出来るようにしたもの。 + * 複雑な処理を行っているので、若干重くなるかもしれません。 + * + * データ構造など(説明下手ですいません^^; ) + * ・メモリを複数の「ブロック」に分けて、さらにブロックを複数の「ユニット」 + * に分けています。ユニットのサイズは、1ブロックの容量を複数個に均等配分 + * したものです。たとえば、1ユニット32KBの場合、ブロック1つは32Byteのユ + * ニットが、1024個集まって出来ていたり、64Byteのユニットが 512個集まって + * 出来ていたりします。(padding,unit_head を除く) + * + * ・ユニット同士はリンクリスト(block_prev,block_next) でつながり、同じサイ + * ズを持つユニット同士もリンクリスト(samesize_prev,samesize_nect) でつな + * がっています。それにより、不要となったメモリの再利用が効率的に行えます。 + */ + +/* ブロックに入るデータ量 */ +#define BLOCK_DATA_SIZE 80*1024 + +/* 一度に確保するブロックの数。 */ +#define BLOCK_ALLOC 32 + +/* ブロックのアライメント */ +#define BLOCK_ALIGNMENT 64 + +/* ブロック */ +struct block { + int block_no; /* ブロック番号 */ + struct block* block_prev; /* 前に確保した領域 */ + struct block* block_next; /* 次に確保した領域 */ + int samesize_no; /* 同じサイズの番号 */ + struct block* samesize_prev; /* 同じサイズの前の領域 */ + struct block* samesize_next; /* 同じサイズの次の領域 */ + int unit_size; /* ユニットのバイト数 0=未使用 */ + int unit_hash; /* ユニットのハッシュ */ + int unit_count; /* ユニットの数 */ + int unit_used; /* 使用済みユニット */ + char data[BLOCK_DATA_SIZE]; +}; + +struct unit_head { + struct block* block; + int size; + const char* file; + int line; +}; + +static struct block* block_first = NULL; +static struct block* block_last = NULL; +static struct block* block_unused = NULL; + +/* ユニットへのハッシュ。80KB/64Byte = 1280個 */ +static struct block* unit_first[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 最初 */ +static struct block* unit_unfill[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 埋まってない */ +static struct block* unit_last[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 最後 */ + +/* メモリを使い回せない領域用のデータ */ +struct unit_head_large { + struct unit_head_large* prev; + struct unit_head_large* next; + struct unit_head unit_head; +}; +static struct unit_head_large *unit_head_large_first = NULL; + +static struct block* block_malloc(void); +static void block_free(struct block* p); +static void memmgr_info(void); + +void* aMalloc_(size_t size, const char *file, int line, const char *func ) { + int i; + struct block *block; + int size_hash = (size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT; + size = size_hash * BLOCK_ALIGNMENT; /* アライメントの倍数に切り上げ */ + + if(size == 0) { + return NULL; + } + + /* ブロック長を超える領域の確保には、malloc() を用いる */ + /* その際、unit_head.block に NULL を代入して区別する */ + if(size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { +#ifdef MEMWATCH + struct unit_head_large* p = (struct unit_head_large*)mwMalloc(sizeof(struct unit_head_large) + size,file,line); +#else + struct unit_head_large* p = (struct unit_head_large*)malloc(sizeof(struct unit_head_large) + size); +#endif + if(p != NULL) { + p->unit_head.block = NULL; + p->unit_head.size = size; + p->unit_head.file = file; + p->unit_head.line = line; + if(unit_head_large_first == NULL) { + unit_head_large_first = p; + p->next = NULL; + p->prev = NULL; + } else { + unit_head_large_first->prev = p; + p->prev = NULL; + p->next = unit_head_large_first; + unit_head_large_first = p; + } + return (char *)p + sizeof(struct unit_head_large); + } else { + printf("MEMMGR::memmgr_alloc failed.\n"); + exit(1); + } + } + + /* 同一サイズのブロックが確保されていない時、新たに確保する */ + if(unit_unfill[size_hash] == NULL) { + block = block_malloc(); + if(unit_first[size_hash] == NULL) { + /* 初回確保 */ + unit_first[size_hash] = block; + unit_last[size_hash] = block; + block->samesize_no = 0; + block->samesize_prev = NULL; + block->samesize_next = NULL; + } else { + /* 連結作業 */ + unit_last[size_hash]->samesize_next = block; + block->samesize_no = unit_last[size_hash]->samesize_no + 1; + block->samesize_prev = unit_last[size_hash]; + block->samesize_next = NULL; + unit_last[size_hash] = block; + } + unit_unfill[size_hash] = block; + block->unit_size = size + sizeof(struct unit_head); + block->unit_count = BLOCK_DATA_SIZE / block->unit_size; + block->unit_used = 0; + block->unit_hash = size_hash; + /* 未使用Flagを立てる */ + for(i=0;i<block->unit_count;i++) { + ((struct unit_head*)(&block->data[block->unit_size * i]))->block = NULL; + } + } + /* ユニット使用個数加算 */ + block = unit_unfill[size_hash]; + block->unit_used++; + + /* ユニット内を全て使い果たした */ + if(block->unit_count == block->unit_used) { + do { + unit_unfill[size_hash] = unit_unfill[size_hash]->samesize_next; + } while( + unit_unfill[size_hash] != NULL && + unit_unfill[size_hash]->unit_count == unit_unfill[size_hash]->unit_used + ); + } + + /* ブロックの中の空きユニット捜索 */ + for(i=0;i<block->unit_count;i++) { + struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]); + if(head->block == NULL) { + head->block = block; + head->size = size; + head->line = line; + head->file = file; + return (char *)head + sizeof(struct unit_head); + } + } + // ここに来てはいけない。 + printf("MEMMGR::memmgr_malloc() serious error.\n"); + memmgr_info(); + exit(1); + return NULL; +}; + +void* aCalloc_(size_t num, size_t size, const char *file, int line, const char *func ) { + void *p = aMalloc_(num * size,file,line,func); + memset(p,0,num * size); + return p; +} + +void* aRealloc_(void *memblock, size_t size, const char *file, int line, const char *func ) { + size_t old_size; + if(memblock == NULL) { + return aMalloc_(size,file,line,func); + } + + old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head)))->size; + if(old_size > size) { + // サイズ縮小 -> そのまま返す(手抜き) + return memblock; + } else { + // サイズ拡大 + void *p = aMalloc_(size,file,line,func); + if(p != NULL) { + memcpy(p,memblock,old_size); + } + aFree_(memblock,file,line,func); + return p; + } +} + +void* aStrdup_(const void* string, const char *file, int line, const char *func ) { + if(string == NULL) { + return NULL; + } else { + int len = strlen(string); + char *p = (char *)aMalloc_(len + 1,file,line,func); + memcpy(p,string,len+1); + return p; + } +} + +void aFree_(void *ptr, const char *file, int line, const char *func ) { + struct unit_head *head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head)); + if(ptr == NULL) { + return; + } else if(head->block == NULL && head->size > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { + /* malloc() で直に確保された領域 */ + struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large)); + if(head_large->prev) { + head_large->prev->next = head_large->next; + } else { + unit_head_large_first = head_large->next; + } + if(head_large->next) { + head_large->next->prev = head_large->prev; + } + free(head_large); + return; + } else { + /* ユニット解放 */ + struct block *block = head->block; + if(head->block == NULL) { + printf("memmgr: args of aFree is freed pointer %s line %d\n",file,line); + } else { + head->block = NULL; + if(--block->unit_used == 0) { + /* ブロックの解放 */ + if(unit_unfill[block->unit_hash] == block) { + /* 空きユニットに指定されている */ + do { + unit_unfill[block->unit_hash] = unit_unfill[block->unit_hash]->samesize_next; + } while( + unit_unfill[block->unit_hash] != NULL && + unit_unfill[block->unit_hash]->unit_count == unit_unfill[block->unit_hash]->unit_used + ); + } + if(block->samesize_prev == NULL && block->samesize_next == NULL) { + /* 独立ブロックの解放 */ + unit_first[block->unit_hash] = NULL; + unit_last[block->unit_hash] = NULL; + unit_unfill[block->unit_hash] = NULL; + } else if(block->samesize_prev == NULL) { + /* 先頭ブロックの解放 */ + unit_first[block->unit_hash] = block->samesize_next; + (block->samesize_next)->samesize_prev = NULL; + } else if(block->samesize_next == NULL) { + /* 末端ブロックの解放 */ + unit_last[block->unit_hash] = block->samesize_prev; + (block->samesize_prev)->samesize_next = NULL; + } else { + /* 中間ブロックの解放 */ + (block->samesize_next)->samesize_prev = block->samesize_prev; + (block->samesize_prev)->samesize_next = block->samesize_next; + } + block_free(block); + } else { + /* 空きユニットの再設定 */ + if( + unit_unfill[block->unit_hash] == NULL || + unit_unfill[block->unit_hash]->samesize_no > block->samesize_no + ) { + unit_unfill[block->unit_hash] = block; + } + } + } + } +} + +/* 現在の状況を表示する */ +static void memmgr_info(void) { + int i; + struct block *p; + printf("** Memory Maneger Information **\n"); + if(block_first == NULL) { + printf("Uninitialized.\n"); + return; + } + printf( + "Blocks: %04u , BlockSize: %06u Byte , Used: %08uKB\n", + block_last->block_no+1,sizeof(struct block), + (block_last->block_no+1) * sizeof(struct block) / 1024 + ); + p = block_first; + for(i=0;i<=block_last->block_no;i++) { + printf(" Block #%04u : ",p->block_no); + if(p->unit_size == 0) { + printf("unused.\n"); + } else { + printf( + "size: %05u byte. used: %04u/%04u prev:", + p->unit_size - sizeof(struct unit_head),p->unit_used,p->unit_count + ); + if(p->samesize_prev == NULL) { + printf("NULL"); + } else { + printf("%04u",(p->samesize_prev)->block_no); + } + printf(" next:"); + if(p->samesize_next == NULL) { + printf("NULL"); + } else { + printf("%04u",(p->samesize_next)->block_no); + } + printf("\n"); + } + p = p->block_next; + } +} + +/* ブロックを確保する */ +static struct block* block_malloc(void) { + if(block_unused != NULL) { + /* ブロック用の領域は確保済み */ + struct block* ret = block_unused; + do { + block_unused = block_unused->block_next; + } while(block_unused != NULL && block_unused->unit_size != 0); + return ret; + } else { + /* ブロック用の領域を新たに確保する */ + int i; + int block_no; + struct block* p = (struct block *)calloc(sizeof(struct block),BLOCK_ALLOC); + if(p == NULL) { + printf("MEMMGR::block_alloc failed.\n"); + exit(1); + } + if(block_first == NULL) { + /* 初回確保 */ + block_no = 0; + block_first = p; + } else { + block_no = block_last->block_no + 1; + block_last->block_next = p; + p->block_prev = block_last; + } + block_last = &p[BLOCK_ALLOC - 1]; + /* ブロックを連結させる */ + for(i=0;i<BLOCK_ALLOC;i++) { + if(i != 0) { + p[i].block_prev = &p[i-1]; + } + if(i != BLOCK_ALLOC -1) { + p[i].block_next = &p[i+1]; + } + p[i].block_no = block_no + i; + } + + /* 未使用ブロックへのポインタを更新 */ + block_unused = &p[1]; + p->unit_size = 1; + return p; + } +} + +static void block_free(struct block* p) { + /* free() せずに、未使用フラグを付けるだけ */ + p->unit_size = 0; + /* 未使用ポインターを更新する */ + if(block_unused == NULL) { + block_unused = p; + } else if(block_unused->block_no > p->block_no) { + block_unused = p; + } +} + +static char memmer_logfile[128]; + +static FILE* memmgr_log(void) { + FILE *fp = fopen(memmer_logfile,"w"); + if(!fp) { fp = stdout; } + fprintf(fp,"memmgr: memory leaks found\n"); + return fp; +} + +static void memmer_exit(void) { + FILE *fp = NULL; + int i; + int count = 0; + struct block *block = block_first; + struct unit_head_large *large = unit_head_large_first; + while(block) { + if(block->unit_size) { + if(!fp) { fp = memmgr_log(); } + for(i=0;i<block->unit_count;i++) { + struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]); + if(head->block != NULL) { + fprintf( + fp,"%04d : %s line %d size %d\n",++count, + head->file,head->line,head->size + ); + } + } + } + block = block->block_next; + } + while(large) { + if(!fp) { fp = memmgr_log(); } + fprintf( + fp,"%04d : %s line %d size %d\n",++count, + large->unit_head.file, + large->unit_head.line,large->unit_head.size + ); + large = large->next; + } + if(!fp) { + printf("memmgr: no memory leaks found.\n"); + } else { + printf("memmgr: memory leaks found.\n"); + } +} + +int do_init_memmgr(const char* file) { + sprintf(memmer_logfile,"%s.log",file); + atexit(memmer_exit); + printf("memmgr: initialised: %s\n",memmer_logfile); + return 0; +} + +#endif diff --git a/src/common/malloc.h b/src/common/malloc.h index d90665487..45451c9e0 100644 --- a/src/common/malloc.h +++ b/src/common/malloc.h @@ -59,15 +59,19 @@ void* aMalloc_( size_t size, const char *file, int line, const char *func ); void* aCalloc_( size_t num, size_t size, const char *file, int line, const char *func ); void* aRealloc_( void *p, size_t size, const char *file, int line, const char *func ); + void aFree_( void *p, const char *file, int line, const char *func ); + void* aStrdup_( const void *p, const char *file, int line, const char *func ); # define aMalloc(n) aMalloc_(n,ALC_MARK) # define aMallocA(n) aMalloc_(n,ALC_MARK) # define aCalloc(m,n) aCalloc_(m,n,ALC_MARK) # define aCallocA(m,n) aCalloc_(m,n,ALC_MARK) # define aRealloc(p,n) aRealloc_(p,n,ALC_MARK) -# define aFree(ptr) free(ptr) -# define aStrdup(ptr) strdup(ptr) +# define aStrdup(p) aStrdup_(p,ALC_MARK) +# define aFree(p) do { aFree_(p,ALC_MARK); if(p != NULL) { p = NULL; } } while(0) #endif +int do_init_memmgr(const char* file); + #endif diff --git a/src/ladmin/Makefile b/src/ladmin/Makefile index ebe67a349..20722350b 100644 --- a/src/ladmin/Makefile +++ b/src/ladmin/Makefile @@ -2,7 +2,7 @@ all: ladmin txt: ladmin sql: ladmin -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o ../common/strlib.o +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h ladmin: ladmin.o md5calc.o $(COMMON_OBJ) diff --git a/src/login/Makefile b/src/login/Makefile index 482503969..01810b1d1 100644 --- a/src/login/Makefile +++ b/src/login/Makefile @@ -1,7 +1,7 @@ all: login-server txt: login-server -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/lock.o ../common/malloc.o ../common/showmsg.o ../common/strlib.o +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/lock.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/lock.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h login-server: login.o md5calc.o $(COMMON_OBJ) diff --git a/src/login_sql/Makefile b/src/login_sql/Makefile index 18b023fe6..20b01c66d 100644 --- a/src/login_sql/Makefile +++ b/src/login_sql/Makefile @@ -2,7 +2,7 @@ all: login-server_sql sql: login-server_sql shared_libs=all -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/db.o ../common/malloc.o ../common/showmsg.o ../common/strlib.o +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/db.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/strlib.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/db.h ../common/malloc.h ../common/showmsg.h ../common/strlib.h login-server_sql: login.o md5calc.o $(COMMON_OBJ) diff --git a/src/map/Makefile b/src/map/Makefile index 884e8b902..b413c8a62 100644 --- a/src/map/Makefile +++ b/src/map/Makefile @@ -10,7 +10,9 @@ txtobj: sqlobj: mkdir sqlobj -COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/grfio.o ../common/db.o ../common/lock.o ../common/nullpo.o ../common/malloc.o ../common/showmsg.o ../common/utils.o ../common/strlib.o +COMMON_OBJ = ../common/obj/core.o ../common/obj/socket.o ../common/obj/timer.o ../common/obj/grfio.o ../common/obj/db.o ../common/obj/lock.o ../common/obj/nullpo.o ../common/obj/malloc.o ../common/obj/showmsg.o ../common/obj/utils.o ../common/obj/strlib.o + +COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/grfio.h ../common/db.h ../common/lock.h ../common/nullpo.h ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h LIBS = -lz -lm map-server: txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/status.o txtobj/npc.o txtobj/npc_chat.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/charcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o txtobj/log.o $(COMMON_OBJ) @@ -25,56 +27,56 @@ txtobj/%.o: %.c sqlobj/%.o: %.c $(COMPILE.c) $(OUTPUT_OPTION) $< -txtobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h ../common/core.h ../common/timer.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -txtobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/showmsg.h -txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -txtobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h -txtobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h -txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -txtobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h ../common/timer.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -txtobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h ../common/timer.h ../common/socket.h ../common/db.h ../common/mmo.h ../common/lock.h ../common/showmsg.h -txtobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h ../common/mmo.h ../common/db.h ../common/showmsg.h -txtobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -txtobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h ../common/mmo.h ../common/showmsg.h -txtobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h ../common/mmo.h ../common/showmsg.h -txtobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -txtobj/log.o: log.c log.h map.h ../common/nullpo.h -txtobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h +txtobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h $(COMMON_H) +txtobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H) +txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h $(COMMON_H) +txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h $(COMMON_H) +txtobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_H) +txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +txtobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +txtobj/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_H) +txtobj/path.o: path.c map.h battle.h $(COMMON_H) +txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_H) +txtobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h $(COMMON_H) +txtobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h $(COMMON_H) +txtobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_H) +txtobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h $(COMMON_H) +txtobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) +txtobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_H) +txtobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_H) +txtobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h $(COMMON_H) +txtobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_H) +txtobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h $(COMMON_H) +txtobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h $(COMMON_H) +txtobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_H) +txtobj/log.o: log.c log.h map.h $(COMMON_H) +txtobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) -sqlobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h ../common/core.h ../common/timer.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -sqlobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/version.h ../common/showmsg.h -sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -sqlobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h -sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h -sqlobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h -sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h -sqlobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h log.h ../common/timer.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -sqlobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h ../common/timer.h ../common/socket.h ../common/db.h ../common/mmo.h ../common/lock.h ../common/showmsg.h -sqlobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h ../common/mmo.h ../common/db.h ../common/showmsg.h -sqlobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h log.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h ../common/socket.h ../common/mmo.h ../common/showmsg.h -sqlobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h log.h ../common/mmo.h ../common/showmsg.h -sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h ../common/mmo.h ../common/showmsg.h -sqlobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h ../common/db.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h -sqlobj/mail.o: mail.c mail.h ../common/showmsg.h ../common/strlib.h ../common/utils.h -sqlobj/log.o: log.c log.h map.h ../common/nullpo.h -sqlobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h ../common/socket.h ../common/timer.h ../common/mmo.h ../common/showmsg.h +sqlobj/map.o: map.c map.h chrif.h clif.h npc.h pc.h mob.h chat.h skill.h itemdb.h storage.h party.h pet.h atcommand.h log.h $(COMMON_H) +sqlobj/chrif.o: chrif.c map.h battle.h chrif.h clif.h intif.h pc.h npc.h $(COMMON_H) +sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h chat.h script.h storage.h party.h guild.h atcommand.h pet.h charcommand.h $(COMMON_H) +sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h $(COMMON_H) +sqlobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h $(COMMON_H) +sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +sqlobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h $(COMMON_H) +sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h $(COMMON_H) +sqlobj/path.o: path.c map.h battle.h $(COMMON_H) +sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h $(COMMON_H) +sqlobj/mob.o: mob.c map.h clif.h intif.h pc.h mob.h skill.h battle.h npc.h itemdb.h log.h $(COMMON_H) +sqlobj/script.o: script.c itemdb.h map.h pc.h mob.h clif.h intif.h npc.h script.h storage.h skill.h pet.h battle.h log.h $(COMMON_H) +sqlobj/storage.o: storage.c itemdb.h pc.h clif.h intif.h storage.h guild.h $(COMMON_H) +sqlobj/skill.o: skill.c skill.h map.h clif.h pc.h mob.h battle.h itemdb.h script.h log.h $(COMMON_H) +sqlobj/atcommand.o: atcommand.c atcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) +sqlobj/battle.o: battle.c battle.h skill.h map.h mob.h pc.h pet.h guild.h $(COMMON_H) +sqlobj/intif.o: intif.c intif.h chrif.h clif.h party.h guild.h storage.h map.h battle.h pet.h $(COMMON_H) +sqlobj/trade.o: trade.c trade.h clif.h itemdb.h map.h pc.h npc.h log.h $(COMMON_H) +sqlobj/party.o: party.c party.h clif.h intif.h pc.h map.h battle.h $(COMMON_H) +sqlobj/vending.o: vending.c vending.h clif.h itemdb.h map.h pc.h log.h $(COMMON_H) +sqlobj/guild.o: guild.c guild.h storage.h battle.h clif.h intif.h pc.h npc.h map.h $(COMMON_H) +sqlobj/pet.o: pet.c pet.h map.h clif.h chrif.h intif.h pc.h itemdb.h battle.h mob.h npc.h script.h $(COMMON_H) +sqlobj/mail.o: mail.c mail.h $(COMMON_H) +sqlobj/log.o: log.c log.h map.h $(COMMON_H) +sqlobj/charcommand.o: charcommand.c charcommand.h itemdb.h pc.h map.h skill.h clif.h mob.h intif.h battle.h storage.h guild.h pet.h log.h $(COMMON_H) clean: rm -rf *.o ../../map-server ../../map-server_sql sqlobj txtobj diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 12e6c2306..3169c75ab 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -9,6 +9,7 @@ #include "../common/timer.h" #include "../common/nullpo.h" #include "../common/mmo.h" +#include "../common/db.h" #include "log.h" #include "clif.h" @@ -210,6 +211,8 @@ ACMD_FUNC(gmotd); // Added by MC Cameri, created by davidsiaw ACMD_FUNC(misceffect); // by MC Cameri ACMD_FUNC(mobsearch); ACMD_FUNC(cleanmap); +ACMD_FUNC(npctalk); +ACMD_FUNC(pettalk); ACMD_FUNC(autoloot); // by Upa-Kun #ifndef TXT_ONLY @@ -484,6 +487,8 @@ static AtCommandInfo atcommand_info[] = { { AtCommand_MiscEffect, "@misceffect", 50, atcommand_misceffect }, // by MC Cameri { AtCommand_MobSearch, "@mobsearch", 0, atcommand_mobsearch }, { AtCommand_CleanMap, "@cleanmap", 0, atcommand_cleanmap }, + { AtCommand_NpcTalk, "@npctalk", 0, atcommand_npctalk }, + { AtCommand_PetTalk, "@pettalk", 0, atcommand_pettalk }, #ifndef TXT_ONLY // sql-only commands { AtCommand_CheckMail, "@checkmail", 1, atcommand_listmail }, // [Valaris] @@ -1743,8 +1748,8 @@ int atcommand_whozeny( clif_displaymessage(fd, output); } - free(zeny); - free(counted); + aFree(zeny); + aFree(counted); return 0; } @@ -7790,6 +7795,49 @@ atcommand_cleanmap( } /*========================================== + * NPC/PETに話させる + *------------------------------------------ + */ +int +atcommand_npctalk( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char name[100],mes[100]; + struct npc_data *nd; + + if (sscanf(message, "%s %99[^\n]", name, mes) < 2) + return -1; + + if (!(nd = npc_name2id(name))) + return -1; + + clif_message(&nd->bl, mes); + return 0; +} +int +atcommand_pettalk( + const int fd, struct map_session_data* sd, + const char* command, const char* message) +{ + char mes[100],temp[100]; + struct pet_data *pd; + + nullpo_retr(-1, sd); + + if(!sd->status.pet_id || !(pd=sd->pd)) + return -1; + + if (sscanf(message, "%99[^\n]", mes) < 1) + return -1; + + snprintf(temp, sizeof temp ,"%s : %s",sd->pet.name,mes); + clif_message(&pd->bl, temp); + + return 0; +} + +/*========================================== * *------------------------------------------ */ diff --git a/src/map/atcommand.h b/src/map/atcommand.h index cb260db19..ea6849476 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -196,6 +196,8 @@ enum AtCommandType { AtCommand_MiscEffect, // by MC Cameri AtCommand_MobSearch, AtCommand_CleanMap, + AtCommand_NpcTalk, + AtCommand_PetTalk, // SQL-only commands start #ifndef TXT_ONLY diff --git a/src/map/battle.c b/src/map/battle.c index 707362f7f..605fd30e0 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -59,15 +59,17 @@ int battle_counttargeted(struct block_list *bl,struct block_list *src,int target // ダメージの遅延 struct battle_delay_damage_ { - struct block_list *src,*target; + struct block_list *src; + int target; int damage; int flag; }; int battle_delay_damage_sub(int tid,unsigned int tick,int id,int data) { struct battle_delay_damage_ *dat=(struct battle_delay_damage_ *)data; - if( dat && map_id2bl(id)==dat->src && dat->target->prev!=NULL) - battle_damage(dat->src,dat->target,dat->damage,dat->flag); + struct block_list *target=map_id2bl(dat->target); + if( dat && map_id2bl(id)==dat->src && target && target->prev!=NULL) + battle_damage(dat->src,target,dat->damage,dat->flag); aFree(dat); return 0; } @@ -80,7 +82,7 @@ int battle_delay_damage(unsigned int tick,struct block_list *src,struct block_li dat->src=src; - dat->target=target; + dat->target=target->id; dat->damage=damage; dat->flag=flag; add_timer(tick,battle_delay_damage_sub,src->id,(int)dat); @@ -256,7 +258,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i flag&BF_SHORT && skill_num != NPC_GUIDEDATTACK) { // セーフティウォール struct skill_unit *unit; - unit = map_find_skill_unit_oncell(bl->m,bl->x,bl->y,MG_SAFETYWALL); + unit = (struct skill_unit *)sc_data[SC_SAFETYWALL].val2; if (unit) { if (unit->group && (--unit->group->val2)<=0) skill_delunit(unit); @@ -3501,7 +3503,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, if(sd && sd->splash_range > 0 && (wd.damage > 0 || wd.damage2 > 0) ) skill_castend_damage_id(src,target,0,-1,tick,0); map_freeblock_lock(); - battle_damage(src,target,(wd.damage+wd.damage2),0); + battle_delay_damage(tick+wd.amotion,src,target,(wd.damage+wd.damage2),0); if(target->prev != NULL && (target->type != BL_PC || (target->type == BL_PC && !pc_isdead((struct map_session_data *)target) ) ) ) { if(wd.damage > 0 || wd.damage2 > 0) { @@ -3652,7 +3654,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, } if(rdamage > 0) - battle_damage(target,src,rdamage,0); + battle_delay_damage(tick+wd.amotion,src,target,rdamage,0); if(t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1 && t_sc_data[SC_AUTOCOUNTER].val4 > 0) { if(t_sc_data[SC_AUTOCOUNTER].val3 == src->id) battle_weapon_attack(target,src,tick,0x8000|t_sc_data[SC_AUTOCOUNTER].val1); diff --git a/src/map/chrif.c b/src/map/chrif.c index a04c483d5..bbc6a51e5 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -1011,6 +1011,8 @@ int chrif_disconnect(int fd) { ShowWarning(tmp_output); clif_foreachclient(chrif_disconnect_sub); chrif_connected = 0; + // 他のmap 鯖のデータを消す + map_eraseallipport(); } close(fd); return 0; @@ -1146,6 +1148,15 @@ int check_connect_char_server(int tid, unsigned int tick, int id, int data) { if (chrif_isconnect()) displayed = 0; return 0; } +/*========================================== + * 終了 + *------------------------------------------ + */ +int do_final_chrif(void) +{ + delete_session(char_fd); + return 0; +} /*========================================== * diff --git a/src/map/chrif.h b/src/map/chrif.h index 7f55d23d6..03ff83f6a 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -31,6 +31,7 @@ int chrif_changesex(int id, int sex); int chrif_chardisconnect(struct map_session_data *sd); int check_connect_char_server(int tid, unsigned int tick, int id, int data); +int do_final_chrif(void); int do_init_chrif(void); int chrif_flush_fifo(void); diff --git a/src/map/guild.c b/src/map/guild.c index d0d7f14dd..ea9c3795f 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -477,8 +477,11 @@ int guild_recv_info(struct guild *sg) // イベントの発生 if( (ev=numdb_search(guild_infoevent_db,sg->guild_id))!=NULL ){ numdb_erase(guild_infoevent_db,sg->guild_id); - for(;ev;ev2=ev->next,aFree(ev),ev=ev2){ + while(ev){ npc_event_do(ev->name); + ev2=ev->next; + aFree(ev); + ev=ev2; } } @@ -1400,8 +1403,11 @@ int guild_castledataloadack(int castle_id,int index,int value) } if( (ev=numdb_search(guild_castleinfoevent_db,code))!=NULL ){ numdb_erase(guild_castleinfoevent_db,code); - for(;ev;ev2=ev->next,aFree(ev),ev=ev2){ + while(ev){ npc_event_do(ev->name); + ev2=ev->next; + aFree(ev); + ev=ev2; } } return 1; diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 41e2e2a75..82149946d 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -379,8 +379,10 @@ static int itemdb_readdb(void) id->equip_script = parse_script((unsigned char *) p,lines); } fclose(fp); - sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,filename[i]); - ShowStatus(tmp_output); + if (ln > 0) { + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,filename[i]); + ShowStatus(tmp_output); + } ln=0; // reset to 0 } return 0; @@ -456,8 +458,10 @@ static int itemdb_read_randomitem() ln++; } fclose(fp); - sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",*pc,fn); - ShowStatus(tmp_output); + if (*pc > 0) { + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",*pc,fn); + ShowStatus(tmp_output); + } } return 0; @@ -699,8 +703,10 @@ static int itemdb_read_noequip(void) } fclose(fp); - sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/item_noequip.txt"); - ShowStatus(tmp_output); + if (ln > 0) { + sprintf(tmp_output,"Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"db/item_noequip.txt"); + ShowStatus(tmp_output); + } return 0; } diff --git a/src/map/map.c b/src/map/map.c index ee597789c..d402ac06c 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -403,12 +403,13 @@ int map_count_oncell(int m, int x, int y) { /* * ォサォ・セェホフェヒフクェトェアェソォケォュォ・讚ヒォテォネェレェケ */ -struct skill_unit *map_find_skill_unit_oncell(int m,int x,int y,int skill_id) +struct skill_unit *map_find_skill_unit_oncell(struct block_list *target,int x,int y,int skill_id,struct skill_unit *out_unit) { - int bx,by; + int m,bx,by; struct block_list *bl; int i,c; struct skill_unit *unit; + m = target->m; if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys)) return NULL; @@ -421,7 +422,10 @@ struct skill_unit *map_find_skill_unit_oncell(int m,int x,int y,int skill_id) if (bl->x != x || bl->y != y || bl->type != BL_SKILL) continue; unit = (struct skill_unit *) bl; - if (unit->alive && unit->group->skill_id == skill_id) + if (unit==out_unit || !unit->alive || + !unit->group || unit->group->skill_id!=skill_id) + continue; + if (battle_check_target(&unit->bl,target,unit->group->target_flag)>0) return unit; } return NULL; @@ -1622,7 +1626,7 @@ struct map_session_data * map_nick2sd(char *nick) { struct block_list * map_id2bl(int id) { struct block_list *bl=NULL; - if(id<sizeof(objects)/sizeof(objects[0])) + if(id >= 0 && id < sizeof(objects)/sizeof(objects[0])) bl = objects[id]; else bl = (struct block_list*)numdb_search(id_db,id); @@ -1826,7 +1830,7 @@ int map_getcell(int m,int x,int y,cell_t cellchk) int map_getcellp(struct map_data* m,int x,int y,cell_t cellchk) { - int j; + int type; nullpo_ret(m); if(x<0 || x>=m->xs-1 || y<0 || y>=m->ys-1) @@ -1834,24 +1838,28 @@ int map_getcellp(struct map_data* m,int x,int y,cell_t cellchk) if(cellchk==CELL_CHKNOPASS) return 1; return 0; } - j=x+y*m->xs; + type = m->gat[x+y*m->xs]; + if (cellchk<0x10) + type &= CELL_MASK; switch(cellchk) { case CELL_CHKPASS: - return (m->gat[j] != 1 && m->gat[j] != 5); + return (type!=1 && type!=5); case CELL_CHKNOPASS: - return (m->gat[j] == 1 || m->gat[j] == 5); + return (type==1 || type==5); case CELL_CHKWALL: - return (m->gat[j] == 1); - case CELL_CHKNPC: - return (m->gat[j]&0x80); + return (type==1); case CELL_CHKWATER: - return (m->gat[j] == 3); + return (type==3); case CELL_CHKGROUND: - return (m->gat[j] == 5); + return (type==5); case CELL_GETTYPE: - return m->gat[j]; + return type; + case CELL_CHKNPC: + return (type&CELL_NPC); + case CELL_CHKBASILICA: + return (type&CELL_BASILICA); default: return 0; } @@ -1868,10 +1876,20 @@ void map_setcell(int m,int x,int y,int cell) return; j=x+y*map[m].xs; - if (cell == CELL_SETNPC) - map[m].gat[j] |= 0x80; - else - map[m].gat[j] = cell; + switch (cell) { + case CELL_SETNPC: + map[m].gat[j] |= CELL_NPC; + break; + case CELL_SETBASILICA: + map[m].gat[j] |= CELL_BASILICA; + break; + case CELL_CLRBASILICA: + map[m].gat[j] &= ~CELL_BASILICA; + break; + default: + map[m].gat[j] = (map[m].gat[j]&~CELL_MASK) + cell; + break; + } } /*========================================== @@ -1889,15 +1907,39 @@ int map_setipport(char *name,unsigned long ip,int port) { mdos->gat = NULL; mdos->ip = ip; mdos->port = port; + mdos->map = NULL; strdb_insert(map_db,mdos->name,mdos); + } else if(md->gat){ + if(ip!=clif_getip() || port!=clif_getport()){ + // 読み込んでいたけど、担当外になったマップ + mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server)); + memcpy(mdos->name,name,24); + mdos->gat = NULL; + mdos->ip = ip; + mdos->port = port; + mdos->map = md; + strdb_insert(map_db,mdos->name,mdos); + // printf("from char server : %s -> %08lx:%d\n",name,ip,port); + } else { + // 読み込んでいて、担当になったマップ(何もしない) + ; + } } else { - if(md->gat){ // local -> check data - if(ip!=clif_getip() || port!=clif_getport()){ - printf("from char server : %s -> %08lx:%d\n",name,ip,port); - return 1; + mdos=(struct map_data_other_server *)md; + if(ip == clif_getip() && port == clif_getport()) { + // 自分の担当になったマップ + if(mdos->map == NULL) { + // 読み込んでいないので終了する + printf("map_setipport : %s is not loaded.\n",name); + exit(1); + } else { + // 読み込んでいるので置き換える + md = mdos->map; + free(mdos); + strdb_insert(map_db,md->name,md); } - } else { // update - mdos=(struct map_data_other_server *)md; + } else { + // 他の鯖の担当マップなので置き換えるだけ mdos->ip = ip; mdos->port = port; } @@ -1905,6 +1947,56 @@ int map_setipport(char *name,unsigned long ip,int port) { return 0; } +/*========================================== + * 他鯖管理のマップを全て削除 + *------------------------------------------ + */ +int map_eraseallipport_sub(void *key,void *data,va_list va) { + struct map_data_other_server *mdos = (struct map_data_other_server*)data; + if(mdos->gat == NULL && mdos->map == NULL) { + strdb_erase(map_db,key); + free(mdos); + } + return 0; +} + +int map_eraseallipport(void) { + strdb_foreach(map_db,map_eraseallipport_sub); + return 1; +} + +/*========================================== + * 他鯖管理のマップをdbから削除 + *------------------------------------------ + */ +int map_eraseipport(char *name,unsigned long ip,int port) +{ + struct map_data *md; + struct map_data_other_server *mdos; +// unsigned char *p=(unsigned char *)&ip; + + md=strdb_search(map_db,name); + if(md){ + if(md->gat) // local -> check data + return 0; + else { + mdos=(struct map_data_other_server *)md; + if(mdos->ip==ip && mdos->port == port) { + if(mdos->map) { + // このマップ鯖でも読み込んでいるので移動できる + return 1; // 呼び出し元で chrif_sendmap() をする + } else { + strdb_erase(map_db,name); + free(mdos); + } +// if(battle_config.etc_log) +// printf("erase map %s %d.%d.%d.%d:%d\n",name,p[0],p[1],p[2],p[3],port); + } + } + } + return 0; +} + // 初期化周り /*========================================== * 水場高さ設定 @@ -2043,7 +2135,7 @@ static void map_cache_close(void) fwrite(map_cache.map,map_cache.head.nmaps,sizeof(struct map_cache_info),map_cache.fp); } fclose(map_cache.fp); - free(map_cache.map); + aFree(map_cache.map); map_cache.fp = NULL; return; } @@ -2085,16 +2177,16 @@ int map_cache_read(struct map_data *m) if(fread(buf,1,size_compress,map_cache.fp) != size_compress) { // なぜかファイル後半が欠けてるので読み直し printf("fread error\n"); - m->xs = 0; m->ys = 0; m->gat = NULL; - free(m->gat); free(buf); + free(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL; + free(buf); return 0; } dest_len = m->xs * m->ys; decode_zip(m->gat,&dest_len,buf,size_compress); if(dest_len != map_cache.map[i].xs * map_cache.map[i].ys) { // 正常に解凍が出来てない - m->xs = 0; m->ys = 0; m->gat = NULL; - free(m->gat); free(buf); + free(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL; + free(buf); return 0; } free(buf); @@ -3069,7 +3161,7 @@ void do_final(void) { strdb_final(nick_db, nick_db_final); numdb_final(charid_db, charid_db_final); - + do_final_chrif(); // この内部でキャラを全て切断する do_final_script(); do_final_itemdb(); do_final_storage(); diff --git a/src/map/map.h b/src/map/map.h index 2963a316e..96cbc9fb3 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -20,7 +20,7 @@ #define MAX_STATUSCHANGE 210 #define MAX_SKILLUNITGROUP 32 #define MAX_MOBSKILLUNITGROUP 8 -#define MAX_SKILLUNITGROUPTICKSET 128 +#define MAX_SKILLUNITGROUPTICKSET 32 #define MAX_SKILLTIMERSKILL 32 #define MAX_MOBSKILLTIMERSKILL 10 #define MAX_MOBSKILL 32 @@ -85,13 +85,13 @@ struct skill_unit_group { int src_id; int party_id; int guild_id; - int map,range; + int map; int target_flag; unsigned int tick; int limit,interval; int skill_id,skill_lv; - int val1,val2; + int val1,val2,val3; char *valstr; int unit_id; int group_id; @@ -582,6 +582,7 @@ struct map_data_other_server { unsigned char *gat; // NULL固定にして判断 unsigned long ip; unsigned int port; + struct map_data* map; }; struct flooritem_data { @@ -646,20 +647,29 @@ enum { LOOK_BASE,LOOK_HAIR,LOOK_WEAPON,LOOK_HEAD_BOTTOM,LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HAIR_COLOR,LOOK_CLOTHES_COLOR,LOOK_SHIELD,LOOK_SHOES }; +// CELL +#define CELL_MASK 0x0f +#define CELL_NPC 0x80 // NPCセル +#define CELL_BASILICA 0x40 // BASILICAセル /* - * map_getcell()ェヌ゙ナ鯑ェオェェォユォ鬮ー + * map_getcell()で使用されるフラグ */ typedef enum { - CELL_CHKWALL=1, // ロ(ォサォォソォ、ォラ1) - CELL_CHKWATER=3, // 筰゙(ォサォォソォ、ォラ3) - CELL_CHKGROUND=5, // 「リ。ェレェ(ォサォォソォ、ォラ5) - CELL_CHKNPC=0x80, // ォソォテォチォソォ、ォラェホNPC(ォサォォソォ、ォラ0x80ォユォ鬮ー) - CELL_CHKPASS, // ラホヲハヲメ(ォサォォソォ、ォラ1,5、鞣) - CELL_CHKNOPASS, // ラホヲワハヲ(ォサォォソォ、ォラ1,5) - CELL_GETTYPE // ォサォォソォ、ォラェレェケ + CELL_CHKWALL=0, // 壁(セルタイプ1) + CELL_CHKWATER, // 水場(セルタイプ3) + CELL_CHKGROUND, // 地面障害物(セルタイプ5) + CELL_CHKPASS, // 通過可能(セルタイプ1,5以外) + CELL_CHKNOPASS, // 通過不可(セルタイプ1,5) + CELL_GETTYPE, // セルタイプを返す + CELL_CHKNPC=0x10, // タッチタイプのNPC(セルタイプ0x80フラグ) + CELL_CHKBASILICA, // バジリカ(セルタイプ0x40フラグ) } cell_t; -// map_setcell()ェヌ゙ナ鯑ェオェェォユォ鬮ー -#define CELL_SETNPC 0x80 // ォソォテォチォソォ、ォラェホNPCェォサォテォネ +// map_setcell()で使用されるフラグ +enum { + CELL_SETNPC=0x10, // タッチタイプのNPCをセット + CELL_SETBASILICA, // バジリカをセット + CELL_CLRBASILICA, // バジリカをクリア +}; struct chat_data { struct block_list bl; @@ -718,7 +728,7 @@ void map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int int map_countnearpc(int,int,int); //block関連に追加 int map_count_oncell(int m,int x,int y); -struct skill_unit *map_find_skill_unit_oncell(int m,int x,int y,int skill_id); +struct skill_unit *map_find_skill_unit_oncell(struct block_list *,int x,int y,int skill_id,struct skill_unit *); // 一時的object関連 int map_addobject(struct block_list *); int map_delobject(int); @@ -747,6 +757,7 @@ int map_mapname2mapid(char*); int map_mapname2ipport(char*,int*,int*); int map_setipport(char *name,unsigned long ip,int port); int map_eraseipport(char *name,unsigned long ip,int port); +int map_eraseallipport(void); void map_addiddb(struct block_list *); void map_deliddb(struct block_list *bl); int map_foreachiddb(int (*)(void*,void*,va_list),...); diff --git a/src/map/mob.c b/src/map/mob.c index 74a1c5889..9b2f91da1 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -496,10 +496,16 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data) dx = dirx[md->dir]; dy = diry[md->dir]; - if(map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKNOPASS)) { + if (map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKBASILICA) && !(status_get_mode(&md->bl)&0x20)) { + mob_stop_walking(md,1); + return 0; + } + + if (map_getcell(md->bl.m,x+dx,y+dy,CELL_CHKNOPASS)) { mob_walktoxy_sub(md); return 0; } + if (skill_check_basilica (&md->bl,x+dx,y+dy) || skill_check_moonlit (&md->bl,x+dx,y+dy)) { mob_walktoxy_sub(md); @@ -515,18 +521,18 @@ static int mob_walk(struct mob_data *md,unsigned int tick,int data) if(md->min_chase>13) md->min_chase--; + skill_unit_move(&md->bl,tick,0); if(moveblock) map_delblock(&md->bl); md->bl.x = x; md->bl.y = y; if(moveblock) map_addblock(&md->bl); + skill_unit_move(&md->bl,tick,1); map_foreachinmovearea(clif_mobinsight,md->bl.m,x-AREA_SIZE,y-AREA_SIZE,x+AREA_SIZE,y+AREA_SIZE,-dx,-dy,BL_PC,md); md->state.state=MS_IDLE; if(md->option&4) skill_check_cloaking(&md->bl); - - skill_unit_move(&md->bl,tick,1); // スキルユニットの検査 } if((i=calc_next_walk_step(md))>0){ i = i>>1; @@ -712,7 +718,7 @@ int mob_changestate(struct mob_data *md,int state,int type) md->last_deadtime=gettick(); // Since it died, all aggressors' attack to this mob is stopped. clif_foreachclient(mob_stopattacked,md->bl.id); - skill_unit_out_all(&md->bl,gettick(),1); + skill_unit_move(&md->bl,gettick(),0); status_change_clear(&md->bl,2); // ステータス異常を解除する skill_clear_unitgroup(&md->bl); // 全てのスキルユニットグループを削除する skill_cleartimerskill(&md->bl); @@ -789,11 +795,21 @@ static int mob_timer(int tid,unsigned int tick,int id,int data) static int mob_walktoxy_sub(struct mob_data *md) { struct walkpath_data wpd; + int x,y; + static int dirx[8]={0,-1,-1,-1,0,1,1,1}; + static int diry[8]={1,1,0,-1,-1,-1,0,1}; nullpo_retr(0, md); if(path_search(&wpd,md->bl.m,md->bl.x,md->bl.y,md->to_x,md->to_y,md->state.walk_easy)) return 1; + x = md->bl.x+dirx[wpd.path[0]]; + y = md->bl.y+diry[wpd.path[0]]; + if (map_getcell(md->bl.m,x,y,CELL_CHKBASILICA) && !(status_get_mode(&md->bl)&0x20)) { + md->state.change_walk_target=0; + return 1; + } + memcpy(&md->walkpath,&wpd,sizeof(wpd)); md->state.change_walk_target=0; @@ -909,7 +925,7 @@ int mob_spawn(int id) md->last_spawntime=tick; if( md->bl.prev!=NULL ){ // clif_clearchar_area(&md->bl,3); - skill_unit_out_all(&md->bl,gettick(),1); +// skill_unit_move(&md->bl,tick,0); map_delblock(&md->bl); } else @@ -939,8 +955,6 @@ int mob_spawn(int id) md->dir=0; md->target_dir=0; - map_addblock(&md->bl); - memset(&md->state,0,sizeof(md->state)); md->attacked_id = 0; md->target_id = 0; @@ -1003,6 +1017,9 @@ int mob_spawn(int id) md->hp = status_get_max_hp(&md->bl); } + map_addblock(&md->bl); + skill_unit_move(&md->bl,tick,1); + clif_spawnmob(md); return 0; @@ -2876,6 +2893,7 @@ int mob_warpslave(struct mob_data *md,int x, int y) int mob_warp(struct mob_data *md,int m,int x,int y,int type) { int i=0,xs=0,ys=0,bx=x,by=y; + int tick = gettick(); nullpo_retr(0, md); @@ -2889,7 +2907,7 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type) return 0; clif_clearchar_area(&md->bl,type); } - skill_unit_out_all(&md->bl,gettick(),1); + skill_unit_move(&md->bl,tick,0); map_delblock(&md->bl); if(bx>0 && by>0){ // 位置指定の場合周囲9セルを探索 @@ -2928,6 +2946,7 @@ int mob_warp(struct mob_data *md,int m,int x,int y,int type) } map_addblock(&md->bl); + skill_unit_move(&md->bl,tick,1); if(type>0) { clif_spawnmob(md); @@ -3241,59 +3260,16 @@ int mobskill_castend_pos( int tid, unsigned int tick, int id,int data ) return 0; } - if(battle_config.monster_skill_reiteration == 0) { - range = -1; - switch(md->skillid) { - case MG_SAFETYWALL: - case WZ_FIREPILLAR: - case HT_SKIDTRAP: - case HT_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case PF_SPIDERWEB: /* スパイダーウェッブ */ - range = 0; - break; - case AL_PNEUMA: - case AL_WARP: - range = 1; - break; - } - if(range >= 0) { - if(skill_check_unit_range(md->bl.m,md->skillx,md->skilly,range,md->skillid) > 0) - return 0; - } - } - if(battle_config.monster_skill_nofootset) { - range = -1; - switch(md->skillid) { - case WZ_FIREPILLAR: - case HT_SKIDTRAP: - case HT_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case AM_DEMONSTRATION: - case PF_SPIDERWEB: /* スパイダーウェッブ */ - range = 1; - break; - case AL_WARP: - range = 0; - break; - } - if(range >= 0) { - if(skill_check_unit_range2(md->bl.m,md->skillx,md->skilly,range) > 0) - return 0; - } - } + if (!battle_config.monster_skill_reiteration && + skill_get_unit_flag(md->skillid)&UF_NOREITERATION && + skill_check_unit_range(md->bl.m,md->skillx,md->skilly,md->skillid,md->skilllv)) + return 0; + + if(battle_config.monster_skill_nofootset && + skill_get_unit_flag(md->skillid)&UF_NOFOOTSET && + skill_check_unit_range2(md->bl.m,md->skillx,md->skilly,md->skillid,md->skilllv)) + return 0; + if(battle_config.monster_land_skill_limit) { maxcount = skill_get_maxcount(md->skillid); diff --git a/src/map/path.c b/src/map/path.c index dae7fc59a..92ea4941e 100644 --- a/src/map/path.c +++ b/src/map/path.c @@ -273,7 +273,7 @@ int path_search_long(int m,int x0,int y0,int x1,int y1) else weight = abs(y1 - y0); - while (x0 != x1 && y0 != y1) { + while (x0 != x1 || y0 != y1) { if (map_getcellp(md,x0,y0,CELL_CHKWALL)) return 0; wx += dx; diff --git a/src/map/pc.c b/src/map/pc.c index 416e05f97..0a5ef8a67 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -140,6 +140,7 @@ static int pc_invincible_timer(int tid,unsigned int tick,int id,int data) { return 0; } sd->invincible_timer=-1; + skill_unit_move(&sd->bl,tick,1); return 0; } @@ -160,6 +161,7 @@ int pc_delinvincibletimer(struct map_session_data *sd) { delete_timer(sd->invincible_timer,pc_invincible_timer); sd->invincible_timer = -1; } + skill_unit_move(&sd->bl,gettick(),1); return 0; } @@ -2244,7 +2246,12 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount) i = pc_search_inventory(sd,0); if(i >= 0) { memcpy(&sd->status.inventory[i],item_data,sizeof(sd->status.inventory[0])); - sd->status.inventory[i].amount=amount; + if(itemdb_isequip2(data)){ + sd->status.inventory[i].amount=1; + amount=1; + } else { + sd->status.inventory[i].amount=amount; + } sd->inventory_data[i]=data; clif_additem(sd,i,amount,0); } @@ -2480,7 +2487,12 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun for(i=0;i<MAX_CART;i++){ if(sd->status.cart[i].nameid==0){ memcpy(&sd->status.cart[i],item_data,sizeof(sd->status.cart[0])); - sd->status.cart[i].amount=amount; + if(itemdb_isequip2(data)){ + sd->status.inventory[i].amount=1; + amount=1; + } else { + sd->status.inventory[i].amount=amount; + } sd->cart_num++; clif_cart_additem(sd,i,amount,0); break; @@ -2877,6 +2889,13 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt status_change_end(&sd->bl,SC_BLADESTOP,-1); if(sd->sc_data[SC_DANCING].timer!=-1) // clear dance effect when warping [Valaris] skill_stop_dancing(&sd->bl,0); + if (sd->sc_data[SC_BASILICA].timer!=-1) { + int i; + for (i=0;i<MAX_SKILLUNITGROUP;i++) + if (sd->skillunit[i].skill_id==HP_BASILICA) + skill_delunitgroup(&sd->skillunit[i]); + status_change_end(&sd->bl,SC_BASILICA,-1); + } } if(sd->status.option&2) @@ -2910,7 +2929,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt int ip,port; if(map_mapname2ipport(mapname,&ip,&port)==0){ skill_stop_dancing(&sd->bl,1); - skill_unit_out_all(&sd->bl,gettick(),1); + skill_unit_move(&sd->bl,gettick(),0); clif_clearchar_area(&sd->bl,clrtype&0xffff); skill_gangsterparadise(sd,0); map_delblock(&sd->bl); @@ -2966,7 +2985,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt } if(sd->mapname[0] && sd->bl.prev != NULL){ - skill_unit_out_all(&sd->bl,gettick(),1); + skill_unit_move(&sd->bl,gettick(),0); clif_clearchar_area(&sd->bl,clrtype&0xffff); skill_gangsterparadise(sd,0); map_delblock(&sd->bl); @@ -3199,10 +3218,12 @@ static int pc_walk(int tid,unsigned int tick,int id,int data) x += dx; y += dy; + skill_unit_move(&sd->bl,tick,0); if(moveblock) map_delblock(&sd->bl); sd->bl.x = x; sd->bl.y = y; if(moveblock) map_addblock(&sd->bl); + skill_unit_move(&sd->bl,tick,1); #if 0 if (sd->status.guild_id > 0) { @@ -3250,20 +3271,15 @@ static int pc_walk(int tid,unsigned int tick,int id,int data) if (sd->sc_data[SC_DEVOTION].val1) skill_devotion2(&sd->bl,sd->sc_data[SC_DEVOTION].val1); - if (sd->sc_data[SC_BASILICA].timer != -1) { // Basilica cancels if caster moves [celest] - struct skill_unit *su; - if ((su = (struct skill_unit *)sd->sc_data[SC_BASILICA].val4)) { - struct skill_unit_group *sg; - if ((sg = su->group) && sg->src_id == sd->bl.id) { - status_change_end(&sd->bl,SC_BASILICA,-1); - skill_delunitgroup (sg); - } - } + if (sd->sc_data[SC_BASILICA].timer!=-1) { // Basilica cancels if caster moves [celest] + int i; + for (i=0;i<MAX_SKILLUNITGROUP;i++) + if (sd->skillunit[i].skill_id==HP_BASILICA) + skill_delunitgroup(&sd->skillunit[i]); + status_change_end(&sd->bl,SC_BASILICA,-1); } } - skill_unit_move(&sd->bl,tick,1); // スキルユニットの?査 - if(map_getcell(sd->bl.m,x,y,CELL_CHKNPC)) npc_touch_areanpc(sd,sd->bl.m,x,y); else @@ -3420,7 +3436,8 @@ int pc_randomwalk(struct map_session_data *sd,int tick) int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y) { int moveblock; - int dx,dy,dist; + int dx,dy; + int tick = gettick(); struct walkpath_data wpd; @@ -3433,16 +3450,17 @@ int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y) dx = dst_x - sd->bl.x; dy = dst_y - sd->bl.y; - dist = distance(sd->bl.x,sd->bl.y,dst_x,dst_y); moveblock = ( sd->bl.x/BLOCK_SIZE != dst_x/BLOCK_SIZE || sd->bl.y/BLOCK_SIZE != dst_y/BLOCK_SIZE); map_foreachinmovearea(clif_pcoutsight,sd->bl.m,sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,dx,dy,0,sd); + skill_unit_move(&sd->bl,tick,0); if(moveblock) map_delblock(&sd->bl); sd->bl.x = dst_x; sd->bl.y = dst_y; if(moveblock) map_addblock(&sd->bl); + skill_unit_move(&sd->bl,tick,1); map_foreachinmovearea(clif_pcinsight,sd->bl.m,sd->bl.x-AREA_SIZE,sd->bl.y-AREA_SIZE,sd->bl.x+AREA_SIZE,sd->bl.y+AREA_SIZE,-dx,-dy,0,sd); @@ -3459,8 +3477,6 @@ int pc_movepos(struct map_session_data *sd,int dst_x,int dst_y) if(sd->status.option&4) // クロ?キングの消滅?査 skill_check_cloaking(&sd->bl); - skill_unit_move(&sd->bl,gettick(),dist+7); // スキルユニットの?査 - if(map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNPC)) npc_touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y); else @@ -3781,7 +3797,7 @@ int pc_attack(struct map_session_data *sd,int target_id,int type) return 0; } - if(!battle_check_target(&sd->bl,bl,BCT_ENEMY)) + if(battle_check_target(&sd->bl,bl,BCT_ENEMY) <= 0) return 1; if(sd->attacktimer != -1) pc_stopattack(sd); @@ -4612,7 +4628,7 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) skill_castcancel(&sd->bl,0); // 詠唱の中止 clif_clearchar_area(&sd->bl,1); pc_setdead(sd); - skill_unit_out_all(&sd->bl,gettick(),1); + skill_unit_move(&sd->bl,gettick(),0); if(sd->sc_data[SC_BLADESTOP].timer!=-1)//白刃は事前に解除 status_change_end(&sd->bl,SC_BLADESTOP,-1); pc_setglobalreg(sd,"PC_DIE_COUNTER",++sd->die_counter); //死にカウンタ?書き?み @@ -4967,7 +4983,21 @@ int pc_setparam(struct map_session_data *sd,int type,int val) sd->status.status_point = val; break; case SP_ZENY: - sd->status.zeny = val; + if(val <= MAX_ZENY) { + // MAX_ZENY 以下なら代入 + sd->status.zeny = val; + } else { + if(sd->status.zeny > val) { + // Zeny が減少しているなら代入 + sd->status.zeny = val; + } else if(sd->status.zeny <= MAX_ZENY) { + // Zeny が増加していて、現在の値がMAX_ZENY 以下ならMAX_ZENY + sd->status.zeny = MAX_ZENY; + } else { + // Zeny が増加していて、現在の値がMAX_ZENY より下なら増加分を無視 + ; + } + } break; case SP_BASEEXP: if(pc_nextbaseexp(sd) > 0) { @@ -5761,6 +5791,7 @@ int pc_setaccountreg2(struct map_session_data *sd,char *reg,int val) int pc_eventtimer(int tid,unsigned int tick,int id,int data) { struct map_session_data *sd=map_id2sd(id); + char *p = (char *)data; int i; if(sd==NULL) return 0; @@ -5768,11 +5799,11 @@ int pc_eventtimer(int tid,unsigned int tick,int id,int data) for(i=0;i<MAX_EVENTTIMER;i++){ if( sd->eventtimer[i]==tid ){ sd->eventtimer[i]=-1; - npc_event(sd,(const char *)data,0); + npc_event(sd,p,0); break; } } - aFree((void *)data); + aFree(p); if(i==MAX_EVENTTIMER) { if(battle_config.error_log) printf("pc_eventtimer: no such event timer\n"); @@ -5795,8 +5826,9 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name) if( sd->eventtimer[i]==-1 ) break; if(i<MAX_EVENTTIMER){ - char *evname=(char *)aMallocA((strlen(name)+1)*sizeof(char)); - memcpy(evname,name,(strlen(name)+1)); + char *evname=strdup(name); + //char *evname=(char *)aMallocA((strlen(name)+1)*sizeof(char)); + //memcpy(evname,name,(strlen(name)+1)); sd->eventtimer[i]=add_timer(gettick()+tick, pc_eventtimer,sd->bl.id,(int)evname); sd->eventcount++; @@ -5819,12 +5851,15 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name) return 0; for(i=0;i<MAX_EVENTTIMER;i++) - if( sd->eventtimer[i]!=-1 && strcmp( - (char *)(get_timer(sd->eventtimer[i])->data), name)==0 ){ + if( sd->eventtimer[i]!=-1 ) { + char *p = (char *)(get_timer(sd->eventtimer[i])->data); + if(strcmp(p, name)==0) { delete_timer(sd->eventtimer[i],pc_eventtimer); sd->eventtimer[i]=-1; sd->eventcount--; + free(p); break; + } } return 0; @@ -5865,8 +5900,10 @@ int pc_cleareventtimer(struct map_session_data *sd) for(i=0;i<MAX_EVENTTIMER;i++) if( sd->eventtimer[i]!=-1 ){ + char *p = (char *)(get_timer(sd->eventtimer[i])->data); delete_timer(sd->eventtimer[i],pc_eventtimer); sd->eventtimer[i]=-1; + free(p); } return 0; diff --git a/src/map/skill.c b/src/map/skill.c index 9ae3e2ba4..3d3411b16 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -556,6 +556,12 @@ int skill_get_mhp( int id ,int lv ){ skill_get (skill_db[id].mhp[lv-1], id, lv); int skill_get_castnodex( int id ,int lv ){ skill_get (skill_db[id].castnodex[lv-1], id, lv); } int skill_get_delaynodex( int id ,int lv ){ skill_get (skill_db[id].delaynodex[lv-1], id, lv); } int skill_get_nocast ( int id ){ skill_get (skill_db[id].nocast, id, 1); } +int skill_get_unit_id ( int id, int flag ){ skill_get (skill_db[id].unit_id[flag], id, 1); } +int skill_get_unit_layout_type( int id ,int lv ){ skill_get (skill_db[id].unit_layout_type[lv-1], id, lv); } +int skill_get_unit_interval( int id ){ skill_get (skill_db[id].unit_interval, id, 1); } +int skill_get_unit_range( int id ){ skill_get (skill_db[id].unit_range, id, 1); } +int skill_get_unit_target( int id ){ skill_get (skill_db[id].unit_target, id, 1); } +int skill_get_unit_flag( int id ){ skill_get (skill_db[id].unit_flag, id, 1); } int skill_tree_get_max(int id, int b_class){ struct pc_base_job s_class = pc_calc_base_job(b_class); @@ -577,6 +583,9 @@ int skill_clear_element_field(struct block_list *bl); int skill_landprotector(struct block_list *bl, va_list ap ); int skill_trap_splash(struct block_list *bl, va_list ap ); int skill_count_target(struct block_list *bl, va_list ap ); +struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg,int tick); +int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int tick); +int skill_unit_effect(struct block_list *bl,va_list ap); // [MouseJstr] - skill ok to cast? and when? int skillnotok(int skillid, struct map_session_data *sd) @@ -635,96 +644,53 @@ static int distance(int x0,int y0,int x1,int y1) return dx>dy ? dx : dy; } -/* スキルユニットIDを返す(これもデ?タベ?スに入れたいな) */ -int skill_get_unit_id(int id,int flag) +/* スキルユニットの配置情報を返す */ +struct skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT]; +int firewall_unit_pos; +int icewall_unit_pos; + +struct skill_unit_layout *skill_get_unit_layout(int skillid,int skilllv,struct block_list *src,int x,int y) { + + int pos = skill_get_unit_layout_type(skillid,skilllv); + int dir; - switch(id){ - case MG_SAFETYWALL: return 0x7e; /* セイフティウォ?ル */ - case MG_FIREWALL: return 0x7f; /* ファイア?ウォ?ル */ - case AL_WARP: return (flag==0)?0x81:0x80; /* ワ?プポ?タル */ - case PR_BENEDICTIO: return 0x82; /* 聖?降福 */ - case PR_SANCTUARY: return 0x83; /* サンクチュアリ */ - case PR_MAGNUS: return 0x84; /* マグヌスエクソシズム */ - case AL_PNEUMA: return 0x85; /* ニュ?マ */ - case MG_THUNDERSTORM: return 0x86; /* サンダ?スト?ム */ - case WZ_HEAVENDRIVE: return 0x86; /* ヘヴンズドライブ */ - case WZ_SIGHTRASHER: return 0x86; /* サイトラッシャ? */ - case WZ_METEOR: return 0x86; /* メテオスト?ム */ - case WZ_VERMILION: return 0x86; /* ロ?ドオブヴァ?ミリオン */ - //case WZ_FROSTNOVA: return 0x86; /* フロストノヴァ */ - case WZ_STORMGUST: return 0x86; /* スト?ムガスト(とりあえずLoVと同じで?理) */ - case CR_GRANDCROSS: return 0x86; /* グランドクロス */ - case NPC_DARKGRANDCROSS: return 0x86; /*闇グランドクロス*/ - case WZ_FIREPILLAR: return (flag==0)?0x87:0x88; /* ファイア?ピラ? */ - case HT_TALKIEBOX: return 0x99; /* ト?キ?ボックス */ - case WZ_ICEWALL: return 0x8d; /* アイスウォ?ル */ - case WZ_QUAGMIRE: return 0x8e; /* クァグマイア */ - case HT_BLASTMINE: return 0x8f; /* ブラストマイン */ - case HT_SKIDTRAP: return 0x90; /* スキッドトラップ */ - case HT_ANKLESNARE: return 0x91; /* アンクルスネア */ - case AS_VENOMDUST: return 0x92; /* ベノムダスト */ - case HT_LANDMINE: return 0x93; /* ランドマイン */ - case HT_SHOCKWAVE: return 0x94; /* ショックウェ?ブトラップ */ - case HT_SANDMAN: return 0x95; /* サンドマン */ - case HT_FLASHER: return 0x96; /* フラッシャ? */ - case HT_FREEZINGTRAP: return 0x97; /* フリ?ジングトラップ */ - case HT_CLAYMORETRAP: return 0x98; /* クレイモア?トラップ */ - case SA_VOLCANO: return 0x9a; /* ボルケ?ノ */ - case SA_DELUGE: return 0x9b; /* デリュ?ジ */ - case SA_VIOLENTGALE: return 0x9c; /* バイオレントゲイル */ - case SA_LANDPROTECTOR: return 0x9d; /* ランドプロテクタ? */ - case BD_LULLABY: return 0x9e; /* 子守歌 */ - case BD_RICHMANKIM: return 0x9f; /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: return 0xa0; /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD:return 0xa1; /* ?太鼓の響き */ - case BD_RINGNIBELUNGEN: return 0xa2; /* ニ?ベルングの指輪 */ - case BD_ROKISWEIL: return 0xa3; /* ロキの叫び */ - case BD_INTOABYSS: return 0xa4; /* 深淵の中に */ - case BD_SIEGFRIED: return 0xa5; /* 不死身のジ?クフリ?ド */ - case BA_DISSONANCE: return 0xa6; /* 不協和音 */ - case BA_WHISTLE: return 0xa7; /* 口笛 */ - case BA_ASSASSINCROSS: return 0xa8; /* 夕陽のアサシンクロス */ - case BA_POEMBRAGI: return 0xa9; /* ブラギの詩 */ - case BA_APPLEIDUN: return 0xaa; /* イドゥンの林檎 */ - case DC_UGLYDANCE: return 0xab; /* 自分勝手なダンス */ - case DC_HUMMING: return 0xac; /* ハミング */ - case DC_DONTFORGETME: return 0xad; /* 私を忘れないで… */ - case DC_FORTUNEKISS: return 0xae; /* 幸運のキス */ - case DC_SERVICEFORYOU: return 0xaf; /* サ?ビスフォ?ユ? */ - case RG_GRAFFITI: return 0xb0; /* グラフィティ */ - case AM_DEMONSTRATION: return 0xb1; /* デモンストレ?ション */ - case WE_CALLPARTNER: return 0xb2; /* あなたに逢いたい */ - case PA_GOSPEL: return 0xb3; /* ゴスペル */ - case HP_BASILICA: return 0xb4; /* バジリカ */ -// case CG_MOONLIT: return 0xb5; - case PF_FOGWALL: return 0xb6; /* フォグウォ?ル */ - case PF_SPIDERWEB: return 0xb7; /* スパイダ?ウェッブ */ - // temporary unit ID's [Celest] - case GD_LEADERSHIP: return 0xc1; - case GD_GLORYWOUNDS: return 0xc2; - case GD_SOULCOLD: return 0xc3; - case GD_HAWKEYES: return 0xc4; - } - return 0; - /* - 0x89,0x8a,0x8b 表示無し - 0x9a 炎?性の詠唱みたいなエフェクト - 0x9b 水?性の詠唱みたいなエフェクト - 0x9c 風?性の詠唱みたいなエフェクト - 0x9d 白い小さなエフェクト - 0xb1 Alchemist Demonstration - 0xb2 = Pink Warp Portal - 0xb3 = Gospel For Paladin - 0xb4 = Basilica - 0xb5 = Empty - 0xb6 = Fog Wall for Professor - 0xb7 = Spider Web for Professor - 0xb8 = Empty - 0xb9 = - */ + if (pos!=-1) + return &skill_unit_layout[pos]; + + if (src->x==x && src->y==y) + dir = 2; + else + dir = map_calc_dir(src,x,y); + + if (skillid==MG_FIREWALL) + return &skill_unit_layout[firewall_unit_pos+dir]; + else if (skillid==WZ_ICEWALL) + return &skill_unit_layout[icewall_unit_pos+dir]; + + printf("unknown unit layout for skill %d, %d\n",skillid,skilllv); + return &skill_unit_layout[0]; } +// case GD_LEADERSHIP: return 0xc1; +// case GD_GLORYWOUNDS: return 0xc2; +// case GD_SOULCOLD: return 0xc3; +// case GD_HAWKEYES: return 0xc4; +// 0x89,0x8a,0x8b 表示無し +// 0x9a 炎?性の詠唱みたいなエフェクト +// 0x9b 水?性の詠唱みたいなエフェクト +// 0x9c 風?性の詠唱みたいなエフェクト +// 0x9d 白い小さなエフェクト +// 0xb1 Alchemist Demonstration +// 0xb2 = Pink Warp Portal +// 0xb3 = Gospel For Paladin +// 0xb4 = Basilica +// 0xb5 = Empty +// 0xb6 = Fog Wall for Professor +// 0xb7 = Spider Web for Professor +// 0xb8 = Empty +// 0xb9 = + /*========================================== * スキル追加?果 *------------------------------------------ @@ -1162,16 +1128,16 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) nullpo_retr(0, target); if(target->type==BL_PC){ - nullpo_retr(0, sd=(struct map_session_data *)target); + sd=(struct map_session_data *)target; }else if(target->type==BL_MOB){ - nullpo_retr(0, md=(struct mob_data *)target); + md=(struct mob_data *)target; }else if(target->type==BL_PET){ - nullpo_retr(0, pd=(struct pet_data *)target); + pd=(struct pet_data *)target; }else if(target->type==BL_SKILL){ - nullpo_retr(0, su=(struct skill_unit *)target); + su=(struct skill_unit *)target; }else return 0; - if(!(count&0x10000 && (sd||md||pd||su))){ /* 指定なしなら位置?係から方向を求める */ + if(!(count&0x10000)){ /* 指定なしなら位置関係から方向を求める */ dx=target->x-src->x; dx=(dx>0)?1:((dx<0)?-1: 0); dy=target->y-src->y; dy=(dy>0)?1:((dy<0)?-1: 0); } @@ -1228,18 +1194,13 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) if(su){ skill_unit_move_unit_group(su->group,target->m,dx,dy); }else{ -// struct status_change *sc_data=status_get_sc_data(target); - if(moveblock) map_delblock(target); - target->x=nx; - target->y=ny; - if(moveblock) map_addblock(target); -/*ダンス中にエフェクトは移動しないらしい - if(sc_data && sc_data[SC_DANCING].timer!=-1){ //?象がダンス中なのでエフェクトも移動 - struct skill_unit_group *sg=(struct skill_unit_group *)sc_data[SC_DANCING].val2; - if(sg) - skill_unit_move_unit_group(sg,target->m,dx,dy); - } -*/ + int tick = gettick(); + skill_unit_move(target,tick,0); + if(moveblock) map_delblock(target); + target->x=nx; + target->y=ny; + if(moveblock) map_addblock(target); + skill_unit_move(target,tick,1); } if(sd) { /* ?面?に入ってきたので表示 */ @@ -1258,8 +1219,6 @@ int skill_blown( struct block_list *src, struct block_list *target,int count) pd->state.state = prev_state; } - skill_unit_move(target,gettick(),(count&0xffff)+7); /* スキルユニットの判定 */ - return 0; } @@ -1480,9 +1439,6 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds //武器スキル?ここまで switch(skillid){ - case WZ_SIGHTRASHER: - clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, 5); - break; case AS_SPLASHER: clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, -1, 5); break; @@ -1495,11 +1451,9 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds default: clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, skillid, (lv!=0)?lv:skilllv, (skillid==0)? 5:type ); } - if(dmg.blewcount > 0 && !map[src->m].flag.gvg) { /* 吹き飛ばし?理とそのパケット */ - if(skillid == WZ_SIGHTRASHER) - skill_blown(src,bl,dmg.blewcount); - else - skill_blown(dsrc,bl,dmg.blewcount); + /* 吹き飛ばし処理とそのパケット */ + if (dmg.blewcount > 0 && bl->type!=BL_SKILL && !map[src->m].flag.gvg) { + skill_blown(dsrc,bl,dmg.blewcount); if(bl->type == BL_MOB) clif_fixmobpos((struct mob_data *)bl); else if(bl->type == BL_PET) @@ -1510,8 +1464,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds map_freeblock_lock(); /* ?際にダメ?ジ?理を行う */ - if(skillid || flag) - battle_damage(src,bl,damage,0); + if (skillid || flag) { + if (attack_type&BF_WEAPON) + battle_delay_damage(tick+dmg.amotion,src,bl,damage,0); + else + battle_damage(src,bl,damage,0); + } if(skillid == RG_INTIMIDATE && damage > 0 && !(status_get_mode(bl)&0x20) && !map[src->m].flag.gvg ) { int s_lv = status_get_lv(src),t_lv = status_get_lv(bl); int rate = 50 + skilllv * 5; @@ -1594,8 +1552,12 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds battle_heal(NULL,bl,0,-sp,0); } - if((skillid || flag) && rdamage > 0) - battle_damage(bl,src,rdamage,0); + if ((skillid || flag) && rdamage>0) { + if (attack_type&BF_WEAPON) + battle_delay_damage(tick+dmg.amotion,bl,src,rdamage,0); + else + battle_damage(bl,src,rdamage,0); + } if(attack_type&BF_WEAPON && sc_data && sc_data[SC_AUTOCOUNTER].timer != -1 && sc_data[SC_AUTOCOUNTER].val4 > 0) { if(sc_data[SC_AUTOCOUNTER].val3 == dsrc->id) @@ -1647,9 +1609,8 @@ int skill_area_sub( struct block_list *bl,va_list ap ) static int skill_check_unit_range_sub( struct block_list *bl,va_list ap ) { struct skill_unit *unit; - int *c,x,y,range,sx[4],sy[4]; - int t_range,tx[4],ty[4]; - int i,r_flag,skillid; + int *c; + int skillid,unit_id; nullpo_retr(0, bl); nullpo_retr(0, ap); @@ -1662,57 +1623,46 @@ static int skill_check_unit_range_sub( struct block_list *bl,va_list ap ) if(!unit->alive) return 0; - x = va_arg(ap,int); - y = va_arg(ap,int); - range = va_arg(ap,int); skillid = va_arg(ap,int); + unit_id = unit->group->unit_id; - if(skillid == MG_SAFETYWALL || skillid == AL_PNEUMA) { - if(unit->group->unit_id != 0x7e && unit->group->unit_id != 0x85) + if (skillid==MG_SAFETYWALL || skillid==AL_PNEUMA) { + if(unit_id != 0x7e && unit_id != 0x85) return 0; - } - else if(skillid == AL_WARP) { - if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92) + } else if (skillid==AL_WARP) { + if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92) return 0; - } - else if((skillid >= HT_SKIDTRAP && skillid <= HT_CLAYMORETRAP) || skillid == HT_TALKIEBOX) { - if((unit->group->unit_id < 0x8f || unit->group->unit_id > 0x99) && unit->group->unit_id != 0x92) + } else if ((skillid>=HT_SKIDTRAP && skillid<=HT_CLAYMORETRAP) || skillid==HT_TALKIEBOX) { + if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92) return 0; - } - else if(skillid == WZ_FIREPILLAR) { - if(unit->group->unit_id != 0x87) + } else if (skillid==WZ_FIREPILLAR) { + if (unit_id!=0x87) return 0; - } - else return 0; - t_range=(unit->range!=0)? unit->range:unit->group->range; - tx[0] = tx[3] = unit->bl.x - t_range; - tx[1] = tx[2] = unit->bl.x + t_range; - ty[0] = ty[1] = unit->bl.y - t_range; - ty[2] = ty[3] = unit->bl.y + t_range; - sx[0] = sx[3] = x - range; - sx[1] = sx[2] = x + range; - sy[0] = sy[1] = y - range; - sy[2] = sy[3] = y + range; - for(i=r_flag=0;i<4;i++) { - if(sx[i] >= tx[0] && sx[i] <= tx[1] && sy[i] >= ty[0] && sy[i] <= ty[2]) { - r_flag = 1; - break; - } - if(tx[i] >= sx[0] && tx[i] <= sx[1] && ty[i] >= sy[0] && ty[i] <= sy[2]) { - r_flag = 1; - break; - } - } - if(r_flag) (*c)++; + } else if (skillid==HP_BASILICA) { + if ((unit_id<0x8f || unit_id>0x99) && unit_id!=0x92 && unit_id!=0x83) + return 0; + } else + return 0; + + (*c)++; return 0; } -int skill_check_unit_range(int m,int x,int y,int range,int skillid) +int skill_check_unit_range(int m,int x,int y,int skillid,int skilllv) { int c = 0; + int range = skill_get_unit_range(skillid); + int layout_type = skill_get_unit_layout_type(skillid,skilllv); + if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) { + printf("skill_check_unit_range: unsupported layout type %d for skill %d\n",layout_type,skillid); + return 0; + } - map_foreachinarea(skill_check_unit_range_sub,m,x-10,y-10,x+10,y+10,BL_SKILL,&c,x,y,range,skillid); + // とりあえず正方形のユニットレイアウトのみ対応 + range += layout_type; + map_foreachinarea(skill_check_unit_range_sub,m, + x-range,y-range,x+range,y+range,BL_SKILL,&c,skillid); return c; } @@ -1720,6 +1670,8 @@ int skill_check_unit_range(int m,int x,int y,int range,int skillid) static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap ) { int *c; + int skillid; + nullpo_retr(0, bl); nullpo_retr(0, ap); @@ -1731,16 +1683,29 @@ static int skill_check_unit_range2_sub( struct block_list *bl,va_list ap ) if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl)) return 0; + skillid = va_arg(ap,int); + if (skillid==HP_BASILICA && bl->type==BL_PC) + return 0; + (*c)++; return 0; } -int skill_check_unit_range2(int m,int x,int y,int range) +int skill_check_unit_range2(int m,int x,int y,int skillid, int skilllv) { int c = 0; + int range = skill_get_unit_range(skillid); + int layout_type = skill_get_unit_layout_type(skillid,skilllv); + if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) { + printf("skill_check_unit_range2: unsupported layout type %d for skill %d\n",layout_type,skillid); + return 0; + } - map_foreachinarea(skill_check_unit_range2_sub,m,x-range,y-range,x+range,y+range,0,&c); + // とりあえず正方形のユニットレイアウトのみ対応 + range += layout_type; + map_foreachinarea(skill_check_unit_range2_sub,m, + x-range,y-range,x+range,y+range,0,&c,skillid); return c; } @@ -1758,6 +1723,27 @@ int skill_area_sub_count(struct block_list *src,struct block_list *target,int sk return 0; } +int skill_count_water(struct block_list *src,int range) +{ + int i,x,y,cnt = 0,size = range*2+1; + struct skill_unit *unit; + + for (i=0;i<size*size;i++) { + x = src->x+(i%size-range); + y = src->y+(i/size-range); + if (map_getcell(src->m,x,y,CELL_CHKWATER)) { + cnt++; + continue; + } + unit = map_find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL); + if (unit) { + cnt++; + skill_delunit(unit); + } + } + return cnt; +} + /*========================================== * *------------------------------------------ @@ -1877,6 +1863,14 @@ static int skill_timerskill(int tid, unsigned int tick, int id,int data ) src->x+range,src->y+range,0,src,skl->skill_id,skl->skill_lv,tick); break; + case WZ_WATERBALL: + if (skl->type>1) { + skl->timer = 0; // skill_addtimerskillで使用されないように + skill_addtimerskill(src,tick+150,target->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); + skl->timer = -1; + } + skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); + break; default: skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); break; @@ -2047,7 +2041,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s if(sd && pc_isdead(sd)) return 1; - if((skillid == WZ_SIGHTRASHER || skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl) + if((skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl) bl = src; if(bl->prev == NULL) return 1; @@ -2445,8 +2439,17 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s case WZ_WATERBALL: /* ウォ?タ?ボ?ル */ skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag); - if(skilllv>1) - status_change_start(src,SC_WATERBALL,skilllv,bl->id,0,0,0,0); + if (skilllv>1) { + int cnt,range; + range = skilllv>5?2:skilllv/2; + if (sd) + cnt = skill_count_water(src,range)-1; + else + cnt = skill_get_num(skillid,skilllv)-1; + if (cnt>0) + skill_addtimerskill(src,tick+150,bl->id,0,0, + skillid,skilllv,cnt,flag); + } break; case PR_BENEDICTIO: /* 聖?降福 */ @@ -2457,6 +2460,7 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s /* 魔法系範?攻?スキル */ case MG_NAPALMBEAT: /* ナパ?ムビ?ト */ case MG_FIREBALL: /* ファイヤ?ボ?ル */ + case WZ_SIGHTRASHER: /* サイトラッシャー */ if(flag&1){ /* 個別にダメ?ジを?える */ if(bl->id!=skill_area_temp[1]){ @@ -2469,27 +2473,46 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s skill_area_temp[0]| 0x0500); } }else{ - int ar=(skillid==MG_NAPALMBEAT)?1:2; + int ar; + skill_area_temp[0]=0; skill_area_temp[1]=bl->id; - if(skillid==MG_NAPALMBEAT){ /* ナパ?ムでは先に?える */ - skill_area_temp[0]=0; - map_foreachinarea(skill_area_sub, - bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY , - skill_area_sub_count); - }else{ - skill_area_temp[0]=0; - skill_area_temp[2]=bl->x; - skill_area_temp[3]=bl->y; + switch (skillid) { + case MG_NAPALMBEAT: + ar = 1; + /* ナパームビートは分散ダメージなので敵の数を数える */ + map_foreachinarea(skill_area_sub, + bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0, + src,skillid,skilllv,tick,flag|BCT_ENEMY, + skill_area_sub_count); + break; + case MG_FIREBALL: + ar = 2; + skill_area_temp[2]=bl->x; + skill_area_temp[3]=bl->y; + /* ターゲットに攻撃を加える(スキルエフェクト表示) */ + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick, + skill_area_temp[0]); + break; + case WZ_SIGHTRASHER: + default: + ar = 3; + bl = src; + status_change_end(src,SC_SIGHT,-1); + break; } - /* まずタ?ゲットに攻?を加える */ - skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick, - skill_area_temp[0] ); - /* その後タ?ゲット以外の範??の敵全?に?理を行う */ + if (skillid==WZ_SIGHTRASHER) { + /* スキルエフェクト表示 */ + clif_skill_nodamage(src,bl,skillid,skilllv,1); + } else { + /* ターゲットに攻撃を加える(スキルエフェクト表示) */ + skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick, + skill_area_temp[0]); + } + /* ターゲット以外の範囲内の敵全体に処理を行う */ map_foreachinarea(skill_area_sub, - bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0, - src,skillid,skilllv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); + bl->m,bl->x-ar,bl->y-ar,bl->x+ar,bl->y+ar,0, + src,skillid,skilllv,tick, flag|BCT_ENEMY|1, + skill_castend_damage_id); } break; @@ -2528,12 +2551,6 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s map_foreachinarea(skill_attack_area,src->m,src->x-5,bl->y-5,bl->x+5,bl->y+5,0,BF_MAGIC,src,src,skillid,skilllv,tick,flag,BCT_ENEMY); break; - case WZ_SIGHTRASHER: - clif_skill_nodamage(src,bl,skillid,skilllv,1); - skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0); - status_change_end(src,SC_SIGHT,-1); - break; - /* その他 */ case HT_BLITZBEAT: /* ブリッツビ?ト */ if(flag&1){ @@ -4688,7 +4705,6 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil nullpo_retr(0, sd=(struct map_session_data *)src); } if( skillid != WZ_METEOR && - skillid != WZ_SIGHTRASHER && skillid != AM_CANNIBALIZE && skillid != AM_SPHEREMINE) clif_skill_poseffect(src,skillid,skilllv,x,y,tick); @@ -4739,7 +4755,6 @@ int skill_castend_pos2( struct block_list *src, int x,int y,int skillid,int skil case AL_PNEUMA: /* ニュ?マ */ case WZ_ICEWALL: /* アイスウォ?ル */ case WZ_FIREPILLAR: /* ファイアピラ? */ - case WZ_SIGHTRASHER: case WZ_QUAGMIRE: /* クァグマイア */ case WZ_VERMILION: /* ロ?ドオブヴァ?ミリオン */ //case WZ_FROSTNOVA: /* フロストノヴァ */ @@ -5007,349 +5022,137 @@ int skill_castend_map( struct map_session_data *sd,int skill_num, const char *ma struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,int skilllv,int x,int y,int flag) { struct skill_unit_group *group; - int i,count=1,limit=10000,val1=0,val2=0; - int target=BCT_ENEMY,interval=1000,range=0; - int dir=0,aoe_diameter=0; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills + int i,limit,val1=0,val2=0,val3=0; + int count=0; + int target,interval,range,unit_flag; + struct skill_unit_layout *layout; struct status_change *sc_data; nullpo_retr(0, src); + limit = skill_get_time(skillid,skilllv); + range = skill_get_unit_range(skillid); + interval = skill_get_unit_interval(skillid); + target = skill_get_unit_target(skillid); + unit_flag = skill_get_unit_flag(skillid); + layout = skill_get_unit_layout(skillid,skilllv,src,x,y); + + if (unit_flag&UF_DEFNOTENEMY && battle_config.defnotenemy) + target = BCT_NOENEMY; + sc_data = status_get_sc_data(src); // for firewall and fogwall - celest switch(skillid){ /* 設定 */ case MG_SAFETYWALL: /* セイフティウォ?ル */ - limit=skill_get_time(skillid,skilllv); val2=skilllv+1; - interval = -1; - target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL; break; - case MG_FIREWALL: /* ファイヤ?ウォ?ル */ - if(src->x == x && src->y == y) - dir = 2; - else - dir=map_calc_dir(src,x,y); - if(dir&1) count=5; - else count=3; - limit=skill_get_time(skillid,skilllv); - if(sc_data) { - if (sc_data[SC_VIOLENTGALE].timer!=-1) limit = limit*3/2; - } - // check for sc_data first - Celest - // if (((struct map_session_data *)src)->sc_data[SC_VIOLENTGALE].timer!=-1) - // limit *= 1.5; + if(sc_data && sc_data[SC_VIOLENTGALE].timer!=-1) + limit = limit*3/2; val2=4+skilllv; - interval=1; - break; - - case AL_PNEUMA: /* ニュ?マ */ - limit=skill_get_time(skillid,skilllv); - interval = -1; - target=(battle_config.defnotenemy)?BCT_NOENEMY:BCT_ALL; - count = 9; break; case AL_WARP: /* ワ?プポ?タル */ - target=BCT_ALL; val1=skilllv+6; if(flag==0) limit=2000; - else - limit=skill_get_time(skillid,skilllv); break; case PR_SANCTUARY: /* サンクチュアリ */ - count=21; - limit=skill_get_time(skillid,skilllv); val1=(skilllv+3)*2; val2=(skilllv>6)?777:skilllv*100; - target=BCT_ALL; - range=1; - break; - - case PR_MAGNUS: /* マグヌスエクソシズム */ - count=33; - limit=skill_get_time(skillid,skilllv); - interval=3000; + interval += 500; break; case WZ_FIREPILLAR: /* ファイア?ピラ? */ - if(flag==0) - limit=skill_get_time(skillid,skilllv); - else + if(flag!=0) limit=1000; - interval=2000; val1=skilllv+2; - if(skilllv < 6) - range=1; - else + if(skilllv >= 6) range=2; break; - case MG_THUNDERSTORM: /* サンダ?スト?ム */ - limit=500; - range=1; - break; - - //case WZ_FROSTNOVA: /* フロストノヴァ */ - // limit=500; - // range=5; - // break; - - case WZ_HEAVENDRIVE: /* ヘヴンズドライブ */ - limit=500; - range=2; - break; - - case WZ_METEOR: /* メテオスト?ム */ - limit=500; - range=3; - break; - - case WZ_SIGHTRASHER: - limit=500; - count=41; - break; - - case WZ_VERMILION: /* ロ?ドオブヴァ?ミリオン */ - limit=4100; - interval=1000; - range=6; - break; - - case WZ_ICEWALL: /* アイスウォ?ル */ - limit=skill_get_time(skillid,skilllv); - count=5; - break; - - case WZ_STORMGUST: /* スト?ムガスト */ - limit=4600; - interval=450; - range=5; - break; - - case WZ_QUAGMIRE: /* クァグマイア */ - limit=skill_get_time(skillid,skilllv); - interval=200; - count=25; - break; - case HT_SANDMAN: /* サンドマン */ case HT_CLAYMORETRAP: /* クレイモア?トラップ */ - limit=skill_get_time(skillid,skilllv); - // longer trap times in WOE [celest] - if (map[src->m].flag.gvg) limit *= 4; - range=2; - break; case HT_SKIDTRAP: /* スキッドトラップ */ case HT_LANDMINE: /* ランドマイン */ case HT_ANKLESNARE: /* アンクルスネア */ - case PF_SPIDERWEB: /* スパイダ?ウェッブ */ case HT_FLASHER: /* フラッシャ? */ case HT_FREEZINGTRAP: /* フリ?ジングトラップ */ case HT_BLASTMINE: /* ブラストマイン */ - limit=skill_get_time(skillid,skilllv); // longer trap times in WOE [celest] - if (skillid != PF_SPIDERWEB && map[src->m].flag.gvg) - limit *= 4; - range=1; - break; - - case HT_TALKIEBOX: /* ト?キ?ボックス */ - limit=skill_get_time(skillid,skilllv); - range=1; - target=BCT_ALL; + if (map[src->m].flag.gvg) limit *= 4; break; - case HT_SHOCKWAVE: /* ショックウェ?ブトラップ */ - limit=skill_get_time(skillid,skilllv); - range=1; val1=skilllv*15+10; break; - case AS_VENOMDUST: /* ベノムダスト */ - limit=skill_get_time(skillid,skilllv); - interval=1000; - count=5; - break; - - case CR_GRANDCROSS: /* グランドクロス */ - case NPC_DARKGRANDCROSS: /*闇グランドクロス*/ - count=29; - limit=1000; - interval=300; - break; - - case SA_VOLCANO: /* ボルケ?ノ */ - case SA_DELUGE: /* デリュ?ジ */ - case SA_VIOLENTGALE: /* バイオレントゲイル */ - limit=skill_get_time(skillid,skilllv); - //count=skilllv<=2?25:(skilllv<=4?49:81); - count=49; - target=BCT_ALL; - break; - case SA_LANDPROTECTOR: /* グランドクロス */ - limit=skill_get_time(skillid,skilllv); // changed to get duration from cast_db (moonsoul) - val1=skilllv*15+10; - aoe_diameter=skilllv+skilllv%2+5; - target=BCT_ALL; - count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul) - break; - - case BD_LULLABY: /* 子守唄 */ - case BD_ETERNALCHAOS: /* エタ?ナルカオス */ - case BD_ROKISWEIL: /* ロキの叫び */ - count=81; - limit=skill_get_time(skillid,skilllv); - range=5; - target=(skillid==BD_ETERNALCHAOS ? BCT_ENEMY : BCT_ALL); - break; - case BD_RICHMANKIM: - case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */ - count=81; - limit=skill_get_time(skillid,skilllv); - range=5; - target=BCT_PARTY; + { + int aoe_diameter; // -- aoe_diameter (moonsoul) added for sage Area Of Effect skills + val1=skilllv*15+10; + aoe_diameter=skilllv+skilllv%2+5; + count=aoe_diameter*aoe_diameter; // -- this will not function if changed to ^2 (moonsoul) + } break; case BA_WHISTLE: /* 口笛 */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1; val2 = ((status_get_agi(src)/10)&0xffff)<<16; val2 |= (status_get_luk(src)/10)&0xffff; break; case DC_HUMMING: /* ハミング */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; val2 = status_get_dex(src)/10; break; - - case BA_DISSONANCE: /* 不協和音 */ - case DC_UGLYDANCE: /* 自分勝手なダンス */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_ENEMY; - break; - case DC_DONTFORGETME: /* 私を忘れないで… */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_ENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; val2 = ((status_get_str(src)/20)&0xffff)<<16; val2 |= (status_get_agi(src)/10)&0xffff; break; case BA_POEMBRAGI: /* ブラギの詩 */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON); val2 = ((status_get_dex(src)/10)&0xffff)<<16; val2 |= (status_get_int(src)/5)&0xffff; break; case BA_APPLEIDUN: /* イドゥンの林檎 */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = ((pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON))&0xffff)<<16; - else - val1 = 0; - val1 |= (status_get_vit(src))&0xffff; - val2 = 0;//回復用タイムカウンタ(6秒?に1?加) + val2 |= (status_get_vit(src))&0xffff; + val3 = 0;//回復用タイムカウンタ(6秒?に1?加) break; case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_PARTY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; val2 = status_get_int(src)/10; break; case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,BA_MUSICALLESSON)+1)>>1; val2 = status_get_agi(src)/20; break; case DC_FORTUNEKISS: /* 幸運のキス */ - count=49; - limit=skill_get_time(skillid,skilllv); - range=3; - target=BCT_NOENEMY; if(src->type == BL_PC) val1 = (pc_checkskill((struct map_session_data *)src,DC_DANCINGLESSON)+1)>>1; val2 = status_get_luk(src)/10; break; - case AM_DEMONSTRATION: /* デモンストレ?ション */ - limit=skill_get_time(skillid,skilllv); - interval=1000; - range=1; - target=BCT_ENEMY; - break; - - case WE_CALLPARTNER: /* あなたに逢いたい */ - limit=skill_get_time(skillid,skilllv); - range=-1; - break; - case HP_BASILICA: /* バジリカ */ - limit=skill_get_time(skillid,skilllv); - target=BCT_ALL; - range=3; //Fix to prevent the priest from walking while Basilica is up. battle_stopwalking(src,1); - //status_change_start(src,SC_ANKLE,skilllv,0,0,0,limit,0); - //sd->canmove_tick = gettick() + limit; // added later [celest] - break; - - case PA_GOSPEL: /* ゴスペル */ - count=49; - target=BCT_PARTY; - limit=skill_get_time(skillid,skilllv); break; -/* case CG_MOONLIT: - range=1; - target=BCT_ALL; - limit=skill_get_time(skillid,skilllv); - break;*/ - case PF_FOGWALL: /* フォグウォ?ル */ - count=15; - limit=skill_get_time(skillid,skilllv); - if(sc_data) { - if (sc_data[SC_DELUGE].timer!=-1) limit *= 2; - } + if(sc_data && sc_data[SC_DELUGE].timer!=-1) limit *= 2; break; case RG_GRAFFITI: /* Graffiti */ count=1; // Leave this at 1 [Valaris] - limit=600000; // Time length [Valaris] break; case GD_LEADERSHIP: @@ -5360,20 +5163,16 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid, target=BCT_ALL; limit=300000; break; - - default: - if(battle_config.error_log) - printf ("skill_unitsetting: Unknown skill id = %d\n",skillid); - return 0; } - nullpo_retr(NULL, group=skill_initunitgroup(src,count,skillid,skilllv,skill_get_unit_id(skillid,flag&1))); + nullpo_retr(NULL, group=skill_initunitgroup(src,(count > 0 ? count : layout->count), + skillid,skilllv,skill_get_unit_id(skillid,flag&1))); group->limit=limit; group->val1=val1; group->val2=val2; + group->val3=val3; group->target_flag=target; group->interval=interval; - group->range=range; if(skillid==HT_TALKIEBOX || skillid==RG_GRAFFITI){ group->valstr=aCallocA(80, 1); @@ -5383,200 +5182,20 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid, } memcpy(group->valstr,talkie_mes,80); } - for(i=0;i<count;i++){ + for(i=0;i<layout->count;i++){ struct skill_unit *unit; - int ux=x,uy=y,val1=skilllv,val2=0,limit=group->limit,alive=1; - int range=group->range; - switch(skillid){ /* 設定 */ - case AL_PNEUMA: /* ニュ?マ */ - { - static const int dx[9]={-1, 0, 1,-1, 0, 1,-1, 0, 1}; - static const int dy[9]={-1,-1,-1, 0, 0, 0, 1, 1, 1}; - ux+=dx[i]; - uy+=dy[i]; - } - break; + int ux,uy,val1=skilllv,val2=0,limit=group->limit,alive=1; + ux = x + layout->dx[i]; + uy = y + layout->dy[i]; + switch (skillid) { case MG_FIREWALL: /* ファイヤ?ウォ?ル */ - { - if(dir&1){ /* 斜め配置 */ - static const int dx[][5]={ - { 1,1,0,0,-1 }, { -1,-1,0,0,1 }, - },dy[][5]={ - { 1,0,0,-1,-1 }, { 1,0,0,-1,-1 }, - }; - ux+=dx[(dir>>1)&1][i]; - uy+=dy[(dir>>1)&1][i]; - }else{ /* 上下配置 */ - if(dir%4==0) /* 上下 */ - ux+=i-1; - else /* 左右 */ - uy+=i-1; - } - val2=group->val2; - } - break; - - case PR_SANCTUARY: /* サンクチュアリ */ - { - static const int dx[]={ - -1,0,1, -2,-1,0,1,2, -2,-1,0,1,2, -2,-1,0,1,2, -1,0,1 }; - static const int dy[]={ - -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0, 1,1,1,1,1, 2,2,2, }; - ux+=dx[i]; - uy+=dy[i]; - } - break; - - case PR_MAGNUS: /* マグヌスエクソシズム */ - { - static const int dx[]={ -1,0,1, -1,0,1, -3,-2,-1,0,1,2,3, - -3,-2,-1,0,1,2,3, -3,-2,-1,0,1,2,3, -1,0,1, -1,0,1, }; - static const int dy[]={ - -3,-3,-3, -2,-2,-2, -1,-1,-1,-1,-1,-1,-1, - 0,0,0,0,0,0,0, 1,1,1,1,1,1,1, 2,2,2, 3,3,3 }; - ux+=dx[i]; - uy+=dy[i]; - } + val2=group->val2; break; - - case WZ_SIGHTRASHER: - { - static const int dx[]={ - -5, 0, 5, -4, 0, 4, -3, 0, 3, -2, 0, 2, -1, 0, 1, -5,-4,-3,-2,-1, 0, 1, 2, 3, 4, 5, -1, 0, 1, -2, 0, 2, -3, 0, 3, -4, 0, 4, -5, 0, 5 }; - static const int dy[]={ - -5,-5,-5, -4,-4,-4, -3,-3,-3, -2,-2,-2, -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5 }; - ux+=dx[i]; - uy+=dy[i]; - } - break; - case WZ_ICEWALL: /* アイスウォ?ル */ - { - static const int dirx[8]={0,-1,-1,-1,0,1,1,1}; - static const int diry[8]={1,1,0,-1,-1,-1,0,1}; if(skilllv <= 1) val1 = 500; else val1 = 200 + 200*skilllv; - if(src->x == x && src->y == y) - dir = 2; - else - dir=map_calc_dir(src,x,y); - ux+=(2-i)*diry[dir]; - uy+=(i-2)*dirx[dir]; - } - break; - - case WZ_QUAGMIRE: /* クァグマイア */ - ux+=(i%5-2); - uy+=(i/5-2); - if(i==12) - range=2; - else - range=-1; - - break; - - case AS_VENOMDUST: /* ベノムダスト */ - { - static const int dx[]={-1,0,0,0,1}; - static const int dy[]={0,-1,0,1,0}; - ux+=dx[i]; - uy+=dy[i]; - } - break; - - case CR_GRANDCROSS: /* グランドクロス */ - case NPC_DARKGRANDCROSS: /*闇グランドクロス*/ - { - static const int dx[]={ - 0, 0, -1,0,1, -2,-1,0,1,2, -4,-3,-2,-1,0,1,2,3,4, -2,-1,0,1,2, -1,0,1, 0, 0, }; - static const int dy[]={ - -4, -3, -2,-2,-2, -1,-1,-1,-1,-1, 0,0,0,0,0,0,0,0,0, 1,1,1,1,1, 2,2,2, 3, 4, }; - ux+=dx[i]; - uy+=dy[i]; - } - break; - case SA_VOLCANO: /* ボルケ?ノ */ - case SA_DELUGE: /* デリュ?ジ */ - case SA_VIOLENTGALE: /* バイオレントゲイル */ - { - int u_range=0,central=0; - if(skilllv<=2){ - u_range=2; - central=12; - }else if(skilllv<=4){ - u_range=3; - central=24; - }else if(skilllv>=5){ - u_range=4; - central=40; - } - ux+=(i%(u_range*2+1)-u_range); - uy+=(i/(u_range*2+1)-u_range); - - if(i==central) - range=u_range;//中央のユニットの?果範?は全範? - else - range=-1;//中央以外のユニットは飾り - } - break; - case SA_LANDPROTECTOR: /* ランドプロテクタ? */ - { - int u_range=0; - - if(skilllv<=2) u_range=3; - else if(skilllv<=4) u_range=4; - else if(skilllv>=5) u_range=5; - - ux+=(i%(u_range*2+1)-u_range); - uy+=(i/(u_range*2+1)-u_range); - - range=0; - } - break; - - /* ダンスなど */ - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD:/* ?太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */ - ux+=(i%9-4); - uy+=(i/9-4); - if(i==40) - range=4; /* 中心の場合は範?を4にオ?バ?ライド */ - else - range=-1; /* 中心じゃない場合は範?を-1にオ?バ?ライド */ - break; - case BA_DISSONANCE: /* 不協和音 */ - case BA_WHISTLE: /* 口笛 */ - case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ - case BA_POEMBRAGI: /* ブラギの詩 */ - case BA_APPLEIDUN: /* イドゥンの林檎 */ - case DC_UGLYDANCE: /* 自分勝手なダンス */ - case DC_HUMMING: /* ハミング */ - case DC_DONTFORGETME: /* 私を忘れないで… */ - case DC_FORTUNEKISS: /* 幸運のキス */ - case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */ -// case CG_MOONLIT: - ux+=(i%7-3); - uy+=(i/7-3); - if(i==40) - range=4; /* 中心の場合は範?を4にオ?バ?ライド */ - else - range=-1; /* 中心じゃない場合は範?を-1にオ?バ?ライド */ - break; - case PA_GOSPEL: /* ゴスペル */ - ux+=(i%7-3); - uy+=(i/7-3); - break; - case PF_FOGWALL: /* フォグウォ?ル */ - ux+=(i%5-2); - uy+=(i/5-1); break; case RG_GRAFFITI: /* Graffiti [Valaris] */ ux+=(i%5-2); @@ -5603,7 +5222,7 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid, unit->val2=val2; unit->limit=limit; unit->range=range; - + // [celest] if (sc_data) { // attach the unit's id to the caster @@ -5642,6 +5261,10 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid, break; } } + if (range==0) + map_foreachinarea(skill_unit_effect,unit->bl.m + ,unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y + ,0,&unit->bl,gettick(),1); } } return group; @@ -5655,123 +5278,284 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int { struct skill_unit_group *sg; struct block_list *ss; - struct skill_unit_group_tickset *ts; - struct map_session_data *srcsd=NULL; - int diff,goflag,splash_count=0; + struct skill_unit *unit2; struct status_change *sc_data; + int type; nullpo_retr(0, src); nullpo_retr(0, bl); - sc_data = status_get_sc_data(bl); - - if( bl->prev==NULL || !src->alive || (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl) ) ) + + if(bl->prev==NULL || !src->alive || + (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))) return 0; nullpo_retr(0, sg=src->group); nullpo_retr(0, ss=map_id2bl(sg->src_id)); + + sc_data = status_get_sc_data(bl); + type = SkillStatusChangeTable[sg->skill_id]; - if(ss->type == BL_PC) - nullpo_retr(0, srcsd=(struct map_session_data *)ss); - if(srcsd && srcsd->chatID) + if (battle_check_target(&src->bl,bl,sg->target_flag)<=0) return 0; - if( bl->type != BL_PC && bl->type != BL_MOB ) + // 対象がLP上に居る場合は無効 + if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL)) return 0; - nullpo_retr(0, ts = skill_unitgrouptickset_search(bl, sg)); - diff=DIFF_TICK(tick,ts->tick); - goflag=(diff>sg->interval || diff<0); - if (sg->skill_id == CR_GRANDCROSS && !battle_config.gx_allhit) // 重なっていたら3HITしない - goflag = (diff>sg->interval*map_count_oncell(bl->m,bl->x,bl->y) || diff<0); - //?象がLP上に居る場合は無? - map_foreachinarea(skill_landprotector,bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,0,&goflag); + switch (sg->unit_id) { + case 0x85: /* ニューマ */ + case 0x7e: /* セイフティウォール */ + if (sc_data && sc_data[type].timer == -1) + status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); + break; - if(!goflag) - return 0; - ts->tick=tick; + case 0x80: /* ワープポータル(発動後) */ + if(bl->type==BL_PC){ + struct map_session_data *sd = (struct map_session_data *)bl; + if(sd && src->bl.m == bl->m && src->bl.x == bl->x && src->bl.y == bl->y && + src->bl.x == sd->to_x && src->bl.y == sd->to_y) { + if( battle_config.chat_warpportal || !sd->chatID ){ + pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3); + if(sg->src_id == bl->id || (strcmp(map[src->bl.m].name,sg->valstr) == 0 && + src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) )) + skill_delunitgroup(sg); + if (--sg->val1<=0) + skill_delunitgroup(sg); + } + } + } else if(bl->type==BL_MOB && battle_config.mob_warpportal){ + int m = map_mapname2mapid(sg->valstr); + mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3); + } + break; - switch(sg->unit_id){ - case 0x83: /* サンクチュアリ */ - { - int race=status_get_race(bl); - int damage_flag = (battle_check_undead(race,status_get_elem_type(bl)) || race == 6)? 1:0; + case 0x8e: /* クァグマイア */ + if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) + break; + if(sc_data && sc_data[type].timer==-1) + status_change_start(bl,type,sg->skill_lv,(int)src,0,0, + skill_get_time2(sg->skill_id,sg->skill_lv),0); + break; - if( status_get_hp(bl)>=status_get_max_hp(bl) && !damage_flag) + case 0x9a: /* ボルケ?ノ */ + case 0x9b: /* デリュ?ジ */ + case 0x9c: /* バイオレントゲイル */ + if (sc_data && sc_data[type].timer!=-1) { + unit2 = (struct skill_unit *)sc_data[type].val4; + if (unit2 && unit2->group && + (unit2==src || DIFF_TICK(sg->tick,unit2->group->tick)<=0)) break; - - if((sg->val1--)<=0){ - skill_delunitgroup(sg); - return 0; - } - if(!damage_flag) { - int heal=sg->val2; - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage) - heal=0; /* ?金蟲カ?ド(ヒ?ル量0) */ - clif_skill_nodamage(&src->bl,bl,AL_HEAL,heal,1); - battle_heal(NULL,bl,heal,0,0); - } - else { - // reduce healing count if this was meant for damaging [celest] - sg->val1 /= 2; - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - } } + status_change_start(bl,type,sg->skill_lv,(int)src,0,0, + skill_get_time2(sg->skill_id,sg->skill_lv),0); break; - case 0x84: /* マグヌスエクソシズム */ - { - int race=status_get_race(bl); - int damage_flag = (battle_check_undead(race,status_get_elem_type(bl)) || race == 6)? 1:0; + case 0x9e: /* 子守唄 */ + case 0x9f: /* ニヨルドの宴 */ + case 0xa0: /* 永遠の混沌 */ + case 0xa1: /* ?太鼓の響き */ + case 0xa2: /* ニ?ベルングの指輪 */ + case 0xa3: /* ロキの叫び */ + case 0xa4: /* 深淵の中に */ + case 0xa5: /* 不死身のジ?クフリ?ド */ + case 0xa6: /* 不協和音 */ + case 0xa7: /* 口笛 */ + case 0xa8: /* 夕陽のアサシンクロス */ + case 0xa9: /* ブラギの詩 */ + case 0xaa: /* イドゥンの林檎 */ + case 0xab: /* 自分勝手なダンス */ + case 0xac: /* ハミング */ + case 0xad: /* 私を忘れないで… */ + case 0xae: /* 幸運のキス */ + case 0xaf: /* サ?ビスフォ?ユ? */ + case 0xb4: + if (sg->src_id==bl->id) + break; + if (sc_data && sc_data[type].timer!=-1) { + unit2 = (struct skill_unit *)sc_data[type].val4; + if (unit2 && unit2->group && + (unit2 == src || DIFF_TICK(sg->tick,unit2->group->tick)<=0)) + break; + } + status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, + (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); + break; - if(!damage_flag) - return 0; - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + case 0xb6: /* フォグウォ?ル */ + if (sc_data && sc_data[type].timer!=-1) { + unit2 = (struct skill_unit *)sc_data[type].val4; + if (unit2 && unit2->group && + (unit2 == src || DIFF_TICK(sg->tick,unit2->group->tick)<=0)) + break; } + status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, + (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); + skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick); break; - case 0x85: /* ニュ?マ */ + // New guild skills [Celest] + case 0xc1: // GD_LEADERSHIP { - struct skill_unit *unit2; - int type=SC_PNEUMA; - if(sc_data) { - if (sc_data[type].timer==-1) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - else if((unit2 = (struct skill_unit *)sc_data[type].val2) && unit2 != src){ - if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick) > 0) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,0,0); - ts->tick-=sg->interval; + struct map_session_data *sd, *tsd; + tsd=(struct map_session_data *)ss; + if (tsd && (sd=(struct map_session_data *)bl) && + sd->status.guild_id == tsd->status.guild_id && + sd != tsd) { + sd->state.leadership_flag = (int)src; + status_calc_pc (sd, 0); } - } } break; - case 0x7e: /* セイフティウォ?ル */ - if (sc_data) { - status_change_start(bl,SC_SAFETYWALL,sg->skill_lv,(int)src,0,0,0,0); - ts->tick-=sg->interval; + case 0xc2: // GD_GLORYWOUNDS + { + struct map_session_data *sd, *tsd; + tsd=(struct map_session_data *)ss; + if (tsd && (sd=(struct map_session_data *)bl) && + sd->status.guild_id == tsd->status.guild_id && + sd != tsd) { + sd->state.glorywounds_flag = (int)src; + status_calc_pc (sd, 0); + } + } + break; + case 0xc3: // GD_SOULCOLD + { + struct map_session_data *sd, *tsd; + tsd=(struct map_session_data *)ss; + if (tsd && (sd=(struct map_session_data *)bl) && + sd->status.guild_id == tsd->status.guild_id && + sd != tsd) { + sd->state.soulcold_flag = (int)src; + status_calc_pc (sd, 0); + } + } + break; + case 0xc4: // GD_HAWKEYES + { + struct map_session_data *sd, *tsd; + tsd=(struct map_session_data *)ss; + if (tsd && (sd=(struct map_session_data *)bl) && + sd->status.guild_id == tsd->status.guild_id && + sd != tsd) { + sd->state.hawkeyes_flag = (int)src; + status_calc_pc (sd, 0); + } } break; - case 0x86: /* ロ?ドオブヴァ?ミリオン(&スト?ムガスト &グランドクロス) */ - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + case 0xb2: /* あなたを_?いたいです */ + case 0xb3: /* ゴスペル */ + //case 0xb6: /* フォグウォ?ル */ - moved [celest] + //とりあえず何もしない break; + /* default: + if(battle_config.error_log) + printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); + break;*/ + } + + return 0; +} + +/*========================================== + * スキルユニットの発動イベント(タイマー発動) + *------------------------------------------ + */ +int skill_unit_onplace_timer(struct skill_unit *src,struct block_list *bl,unsigned int tick) +{ + struct skill_unit_group *sg; + struct block_list *ss; + int splash_count=0; + struct status_change *sc_data; + struct skill_unit_group_tickset *ts; + int type; + int diff=0; + + nullpo_retr(0, src); + nullpo_retr(0, bl); + + if (bl->type!=BL_PC && bl->type!=BL_MOB) + return 0; + + if (bl->prev==NULL || !src->alive || + (bl->type==BL_PC && pc_isdead((struct map_session_data *)bl))) + return 0; + + nullpo_retr(0, sg=src->group); + nullpo_retr(0, ss=map_id2bl(sg->src_id)); + sc_data = status_get_sc_data(bl); + type = SkillStatusChangeTable[sg->skill_id]; + + // 対象がLP上に居る場合は無効 + if (map_find_skill_unit_oncell(bl,bl->x,bl->y,SA_LANDPROTECTOR,NULL)) + return 0; + + // 前に影響を受けてからintervalの間は影響を受けない + nullpo_retr(0,ts = skill_unitgrouptickset_search(bl,sg,tick)); + diff = DIFF_TICK(tick,ts->tick); + if (sg->skill_id == PR_SANCTUARY) + diff += 500; // 新規に回復したユニットだけカウントするための仕掛け + if (diff < 0) + return 0; + ts->tick = tick+sg->interval; + // GXは重なっていたら3HITしない + if (sg->skill_id==CR_GRANDCROSS && !battle_config.gx_allhit) + ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y)-1); + + switch (sg->unit_id) { + case 0x83: /* サンクチュアリ */ + { + int race=status_get_race(bl); - case 0x7f: /* ファイヤ?ウォ?ル */ - if( (src->val2--)>0) - skill_attack(BF_MAGIC,ss,&src->bl,bl, - sg->skill_id,sg->skill_lv,tick,0); - if( src->val2<=0 ) + if (battle_check_undead(race,status_get_elem_type(bl)) || race==6) { + if (skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0)) { + // reduce healing count if this was meant for damaging [celest] + // sg->val1 /= 2; + sg->val1--; // チャットキャンセルに対応 + } + } else { + int heal = sg->val2; + if (status_get_hp(bl)>=status_get_max_hp(bl)) + break; + if(bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage) + heal=0; /* 黄金蟲カード(ヒール量0) */ + clif_skill_nodamage(&src->bl,bl,AL_HEAL,heal,1); + battle_heal(NULL,bl,heal,0,0); + if (diff>=500) + sg->val1--; // 新規に入ったユニットだけカウント + } + if (sg->val1<=0) + skill_delunitgroup(sg); + break; + } + + case 0x84: /* マグヌスエクソシズム */ + { + int race = status_get_race(bl); + if (!battle_check_undead(race,status_get_elem_type(bl)) && race!=6) + return 0; + skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + src->val2++; + break; + } + + case 0x7f: /* ファイヤーウォール */ + skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + if (--src->val2<=0) skill_delunit(src); break; - - case 0x87: /* ファイア?ピラ?(?動前) */ + case 0x86: /* ロードオブヴァーミリオン(TS,MS,FN,SG,HD,GX,闇GX) */ + skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + break; + case 0x87: /* ファイアーピラー(発動前) */ skill_delunit(src); skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1); break; - case 0x88: /* ファイア?ピラ?(?動後) */ - if(DIFF_TICK(tick,sg->tick) < 150) - //skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); - map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0,BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest] + case 0x88: /* ファイアーピラー(発動後) */ + map_foreachinarea(skill_attack_area,bl->m,bl->x-1,bl->y-1,bl->x+1,bl->y+1,0, + BF_MAGIC,ss,&src->bl,sg->skill_id,sg->skill_lv,tick,0,BCT_ENEMY); // area damage [Celest] + //skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; case 0x90: /* スキッドトラップ */ @@ -5784,7 +5568,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int clif_changelook(&src->bl,LOOK_BASE,sg->unit_id); sg->limit=DIFF_TICK(tick,sg->tick)+1500; } - break; + break; case 0x93: /* ランドマイン */ skill_attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); @@ -5813,22 +5597,22 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int break; case 0x91: /* アンクルスネア */ - { - struct status_change *sc_data=status_get_sc_data(bl); - if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){ - int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE); - int sec = skill_get_time2(sg->skill_id,sg->skill_lv) - status_get_agi(bl)*100; - if(status_get_mode(bl)&0x20) - sec = sec/5; - if (sec < 3000) // minimum time of 3 seconds [celest] - sec = 3000; - battle_stopwalking(bl,1); - status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0); - + if(sg->val2==0 && sc_data && sc_data[SC_ANKLE].timer==-1){ + int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE); + int sec = skill_get_time2(sg->skill_id,sg->skill_lv) - status_get_agi(bl)*100; + if(status_get_mode(bl)&0x20) + sec = sec/5; + if (sec < 3000) // minimum time of 3 seconds [celest] + sec = 3000; + battle_stopwalking(bl,1); + status_change_start(bl,SC_ANKLE,sg->skill_lv,0,0,0,sec,0); + + skill_unit_move(bl,tick,0); if(moveblock) map_delblock(bl); bl->x = src->bl.x; bl->y = src->bl.y; if(moveblock) map_addblock(bl); + skill_unit_move(bl,tick,1); if(bl->type == BL_MOB) clif_fixmobpos((struct mob_data *)bl); else if(bl->type == BL_PET) @@ -5836,156 +5620,26 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int else clif_fixpos(bl); clif_01ac(&src->bl); - sg->limit=DIFF_TICK(tick,sg->tick) + sec; + sg->limit=DIFF_TICK(tick,sg->tick) + sec; sg->val2=bl->id; - } - } - break; - - case 0x80: /* ワ?プポ?タル(?動後) */ - if(bl->type==BL_PC){ - struct map_session_data *sd = (struct map_session_data *)bl; - if(sd && src->bl.m == bl->m && src->bl.x == bl->x && src->bl.y == bl->y && src->bl.x == sd->to_x && src->bl.y == sd->to_y) { - if( battle_config.chat_warpportal || !sd->chatID ){ - if((sg->val1--)>0){ - pc_setpos(sd,sg->valstr,sg->val2>>16,sg->val2&0xffff,3); - if(sg->src_id == bl->id ||( strcmp(map[src->bl.m].name,sg->valstr) == 0 && src->bl.x == (sg->val2>>16) && src->bl.y == (sg->val2&0xffff) )) - skill_delunitgroup(sg); - }else - skill_delunitgroup(sg); - } - } - }else if(bl->type==BL_MOB && battle_config.mob_warpportal){ - int m=map_mapname2mapid(sg->valstr); - struct mob_data *md; - md=(struct mob_data *)bl; - mob_warp((struct mob_data *)bl,m,sg->val2>>16,sg->val2&0xffff,3); + sg->interval = -1; + src->range = 0; } break; - case 0x8e: /* クァグマイア */ - { - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if( bl->type==BL_PC && ((struct map_session_data *)bl)->special_state.no_magic_damage ) - break; - if(sc_data && sc_data[type].timer==-1) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - } - break; case 0x92: /* ベノムダスト */ - { - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sc_data && sc_data[type].timer==-1 ) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - } + if(sc_data && sc_data[type].timer==-1 ) + status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); break; - case 0x9a: /* ボルケ?ノ */ - case 0x9b: /* デリュ?ジ */ - case 0x9c: /* バイオレントゲイル */ - { - struct skill_unit *unit2; - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sc_data) { - if (sc_data[type].timer==-1) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if((unit2=(struct skill_unit *)sc_data[type].val2) && unit2 != src ){ - if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - status_change_start(bl,type,sg->skill_lv,(int)src,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } - } break; - - case 0x9e: /* 子守唄 */ - case 0x9f: /* ニヨルドの宴 */ - case 0xa0: /* 永遠の混沌 */ - case 0xa1: /* ?太鼓の響き */ - case 0xa2: /* ニ?ベルングの指輪 */ - case 0xa3: /* ロキの叫び */ - case 0xa4: /* 深淵の中に */ - case 0xa5: /* 不死身のジ?クフリ?ド */ - case 0xa6: /* 不協和音 */ - case 0xa7: /* 口笛 */ - case 0xa8: /* 夕陽のアサシンクロス */ - case 0xa9: /* ブラギの詩 */ - case 0xab: /* 自分勝手なダンス */ - case 0xac: /* ハミング */ - case 0xad: /* 私を忘れないで… */ - case 0xae: /* 幸運のキス */ - case 0xaf: /* サ?ビスフォ?ユ? */ - case 0xb4: -// case 0xb6: /* フォグウォ?ル */ - { - struct skill_unit *unit2; - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sg->src_id == bl->id) - break; - if(sc_data) { - if (sc_data[type].timer==-1) - status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if( (unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){ - if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } - } break; - - case 0xaa: /* イドゥンの林檎 */ - { - struct skill_unit *unit2; - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sg->src_id == bl->id) - break; - if(sc_data) { - if (sc_data[type].timer==-1) - status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - else if((unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){ - if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) - status_change_start(bl,type,sg->skill_lv,(sg->val1)>>16,(sg->val1)&0xffff, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - ts->tick-=sg->interval; - } - } - } break; - - case 0xb6: /* フォグウォ?ル */ - { - struct skill_unit *unit2; - struct status_change *sc_data=status_get_sc_data(bl); - int type=SkillStatusChangeTable[sg->skill_id]; - if(sc_data) { - if (sc_data[type].timer==-1) { - status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick); - } - else if( (unit2=(struct skill_unit *)sc_data[type].val4) && unit2 != src ){ - if(unit2 && unit2->group && DIFF_TICK(sg->tick,unit2->group->tick)>0 ) { - status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, - (int)src,skill_get_time2(sg->skill_id,sg->skill_lv),0); - skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick); - } -// ts->tick-=sg->interval; - } - } - } break; case 0xb1: /* デモンストレ?ション */ skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); if(bl->type == BL_PC && rand()%100 < sg->skill_lv && battle_config.equipment_breaking) pc_breakweapon((struct map_session_data *)bl); break; - case 0x99: /* ト?キ?ボックス */ - if(sg->src_id == bl->id) //自分が踏んでも?動しない + + case 0x99: /* トーキーボックス */ + if(sg->src_id == bl->id) //自分が踏んでも発動しない break; if(sg->val2==0){ clif_talkiebox(&src->bl,sg->valstr); @@ -5994,76 +5648,41 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int sg->limit=DIFF_TICK(tick,sg->tick)+5000; sg->val2=-1; //踏んだ } - break; - case 0xb2: /* あなたを_?いたいです */ - case 0xb3: /* ゴスペル */ - //case 0xb6: /* フォグウォ?ル */ - moved [celest] - //とりあえず何もしない - break; + break; + + //case 0xb4: /* バジリカ */ + /*if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0 && + !(status_get_mode(bl)&0x20)) + skill_blown(&src->bl,bl,1); + if (sg->src_id==bl->id) + break; + if (battle_check_target(&src->bl,bl,BCT_NOENEMY)>0) { + type = SkillStatusChangeTable[sg->skill_id]; + status_change_start(bl,type,sg->skill_lv,sg->val1,sg->val2, + (int)src,sg->interval+100,0); + } + break;*/ case 0xb7: /* スパイダ?ウェッブ */ if(sg->val2==0){ int moveblock = ( bl->x/BLOCK_SIZE != src->bl.x/BLOCK_SIZE || bl->y/BLOCK_SIZE != src->bl.y/BLOCK_SIZE); skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,tick); + skill_unit_move(bl,tick,0); if(moveblock) map_delblock(bl); - bl->x = (&src->bl)->x; - bl->y = (&src->bl)->y; + bl->x = src->bl.x; + bl->y = src->bl.y; if(moveblock) map_addblock(bl); - if(bl->type == BL_MOB) - clif_fixmobpos((struct mob_data *)bl); - else if(bl->type == BL_PET) - clif_fixpetpos((struct pet_data *)bl); - else - clif_fixpos(bl); - clif_01ac(&src->bl); - sg->limit=DIFF_TICK(tick,sg->tick) + skill_get_time2(sg->skill_id,sg->skill_lv); + skill_unit_move(bl,tick,1); + if(bl->type == BL_MOB) + clif_fixmobpos((struct mob_data *)bl); + else if(bl->type == BL_PET) + clif_fixpetpos((struct pet_data *)bl); + else + clif_fixpos(bl); + sg->limit = DIFF_TICK(tick,sg->tick)+skill_get_time2(sg->skill_id,sg->skill_lv); sg->val2=bl->id; - } - break; - - // New guild skills [Celest] - case 0xc1: // GD_LEADERSHIP - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd != srcsd) { - sd->state.leadership_flag = (int)src; - status_calc_pc (sd, 0); - } - } - break; - case 0xc2: // GD_GLORYWOUNDS - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd != srcsd) { - sd->state.glorywounds_flag = (int)src; - status_calc_pc (sd, 0); - } - } - break; - case 0xc3: // GD_SOULCOLD - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd != srcsd) { - sd->state.soulcold_flag = (int)src; - status_calc_pc (sd, 0); - } - } - break; - case 0xc4: // GD_HAWKEYES - { - struct map_session_data *sd; - if (srcsd && bl->type == BL_PC && (sd=(struct map_session_data *)bl) && - sd->status.guild_id == srcsd->status.guild_id && - sd != srcsd) { - sd->state.hawkeyes_flag = (int)src; - status_calc_pc (sd, 0); - } + sg->interval = -1; + src->range = 0; } break; @@ -6072,6 +5691,7 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int printf("skill_unit_onplace: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); break;*/ } + if(bl->type==BL_MOB && ss!=bl) /* スキル使用?件のMOBスキル */ { if(battle_config.mob_changetarget_byskill == 1) @@ -6095,77 +5715,41 @@ int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int tick) { struct skill_unit_group *sg; + struct status_change *sc_data; + int type; nullpo_retr(0, src); nullpo_retr(0, bl); nullpo_retr(0, sg=src->group); + sc_data = status_get_sc_data(bl); + type = SkillStatusChangeTable[sg->skill_id]; - if( bl->prev==NULL || !src->alive ) - return 0; - - if( bl->type!=BL_PC && bl->type!=BL_MOB ) + if (bl->prev==NULL || !src->alive || + (bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))) return 0; switch(sg->unit_id){ - case 0x7e: /* セイフティウォ?ル */ - case 0x85: /* ニュ?マ */ + case 0x7e: /* セイフティウォール */ + case 0x85: /* ニューマ */ case 0x8e: /* クァグマイア */ - { - struct status_change *sc_data=status_get_sc_data(bl); - int type= - (sg->unit_id==0x85)?SC_PNEUMA: - ((sg->unit_id==0x7e)?SC_SAFETYWALL: - SC_QUAGMIRE); - if((type != SC_QUAGMIRE || bl->type != BL_MOB) && - sc_data && sc_data[type].timer!=-1 && ((struct skill_unit *)sc_data[type].val2)==src){ - status_change_end(bl,type,-1); - } - } break; - - case 0x91: /* アンクルスネア */ - { - struct block_list *target=map_id2bl(sg->val2); - if( target && target==bl ){ - status_change_end(bl,SC_ANKLE,-1); - sg->limit=DIFF_TICK(tick,sg->tick)+1000; - } + case 0x9a: /* ボルケーノ */ + case 0x9b: /* デリュージ */ + case 0x9c: /* バイオレントゲイル */ + if (type==SC_QUAGMIRE && bl->type==BL_MOB) + break; + if (sc_data && sc_data[type].timer!=-1 && sc_data[type].val2==(int)src) { + status_change_end(bl,type,-1); } break; -// case 0xb5: - case 0xb8: - { - struct block_list *target=map_id2bl(sg->val2); - if( target==bl ) - status_change_end(bl,SC_SPIDERWEB,-1); + case 0x91: /* アンクルスネア */ + { + struct block_list *target = map_id2bl(sg->val2); + if(target && target == bl){ + status_change_end(bl,SC_ANKLE,-1); sg->limit=DIFF_TICK(tick,sg->tick)+1000; } break; - case 0xb6: - { - struct block_list *target=map_id2bl(sg->val2); - struct status_change *sc_data=status_get_sc_data(bl); - if( target==bl ) { - status_change_end(bl,SC_FOGWALL,-1); - if (sc_data && sc_data[SC_BLIND].timer!=-1) - sc_data[SC_BLIND].timer = add_timer( - gettick() + 30000, status_change_timer, bl->id, 0); - } - //sg->limit=DIFF_TICK(tick,sg->tick)+1000; - } - break; - case 0x9a: /* ボルケ?ノ */ - case 0x9b: /* デリュ?ジ */ - case 0x9c: /* バイオレントゲイル */ - { - struct status_change *sc_data=status_get_sc_data(bl); - struct skill_unit *su; - int type=SkillStatusChangeTable[sg->skill_id]; - if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val2)) && su == src ){ - status_change_end(bl,type,-1); - } - } - break; - + } case 0x9e: /* 子守唄 */ case 0x9f: /* ニヨルドの宴 */ case 0xa0: /* 永遠の混沌 */ @@ -6185,24 +5769,32 @@ int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int t case 0xae: /* 幸運のキス */ case 0xaf: /* サ?ビスフォ?ユ? */ case 0xb4: - { - struct status_change *sc_data=status_get_sc_data(bl); - struct skill_unit *su; - int type=SkillStatusChangeTable[sg->skill_id]; - if( sc_data && sc_data[type].timer!=-1 && (su=((struct skill_unit *)sc_data[type].val4)) && su == src ){ - status_change_end(bl,type,-1); - } + if (sc_data[type].timer!=-1 && sc_data[type].val4==(int)src) { + status_change_end(bl,type,-1); } break; + + case 0xb6: + { + struct block_list *target = map_id2bl(sg->val2); + if(target && target==bl) { + status_change_end(bl,SC_FOGWALL,-1); + if (sc_data && sc_data[SC_BLIND].timer!=-1) + sc_data[SC_BLIND].timer = add_timer( + gettick() + 30000, status_change_timer, bl->id, 0); + } + break; + } + case 0xb7: /* スパイダ?ウェッブ */ { - struct block_list *target=map_id2bl(sg->val2); - if( target && target==bl ) + struct block_list *target = map_id2bl(sg->val2); + if (target && target==bl) status_change_end(bl,SC_SPIDERWEB,-1); - sg->limit=DIFF_TICK(tick,sg->tick)+1000; + sg->limit = DIFF_TICK(tick,sg->tick)+1000; + break; } - break; - // New guild skills [Celest] + // New guild skills [Celest] case 0xc1: // GD_LEADERSHIP { struct map_session_data *sd; @@ -6231,73 +5823,53 @@ int skill_unit_onout(struct skill_unit *src,struct block_list *bl,unsigned int t sd->state.hawkeyes_flag = 0; } break; - /* default: if(battle_config.error_log) printf("skill_unit_onout: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); break;*/ } - skill_unitgrouptickset_delete(bl,sg); + return 0; } + /*========================================== - * スキルユニットの削除イベント + * スキルユニット効果発動/離脱処理(foreachinarea) + * bl: ユニット(BL_PC/BL_MOB) *------------------------------------------ */ -int skill_unit_ondelete(struct skill_unit *src,struct block_list *bl,unsigned int tick) +int skill_unit_effect(struct block_list *bl,va_list ap) { - struct skill_unit_group *sg; + struct skill_unit *unit; + struct skill_unit_group *group; + int flag; + unsigned int tick; - nullpo_retr(0, src); nullpo_retr(0, bl); - nullpo_retr(0, sg = src->group); + nullpo_retr(0, ap); + nullpo_retr(0, unit=va_arg(ap,struct skill_unit*)); + tick = va_arg(ap,unsigned int); + flag = va_arg(ap,unsigned int); - if( bl->prev==NULL || !src->alive ) + if (bl->type!=BL_PC && bl->type!=BL_MOB) return 0; - if( bl->type!=BL_PC && bl->type!=BL_MOB ) + if (!unit->alive || bl->prev==NULL) return 0; - switch(sg->unit_id){ - case 0x85: /* ニュ?マ */ - case 0x7e: /* セイフティウォ?ル */ - case 0x8e: /* クァグマイヤ */ - case 0x9a: /* ボルケ?ノ */ - case 0x9b: /* デリュ?ジ */ - case 0x9c: /* バイオレントゲイル */ - case 0x9e: /* 子守唄 */ - case 0x9f: /* ニヨルドの宴 */ - case 0xa0: /* 永遠の混沌 */ - case 0xa1: /* ?太鼓の響き */ - case 0xa2: /* ニ?ベルングの指輪 */ - case 0xa3: /* ロキの叫び */ - case 0xa4: /* 深淵の中に */ - case 0xa5: /* 不死身のジ?クフリ?ド */ - case 0xa6: /* 不協和音 */ - case 0xa7: /* 口笛 */ - case 0xa8: /* 夕陽のアサシンクロス */ - case 0xa9: /* ブラギの詩 */ - case 0xaa: /* イドゥンの林檎 */ - case 0xab: /* 自分勝手なダンス */ - case 0xac: /* ハミング */ - case 0xad: /* 私を忘れないで… */ - case 0xae: /* 幸運のキス */ - case 0xaf: /* サ?ビスフォ?ユ? */ - case 0xb4: - case 0xc1: - case 0xc2: - case 0xc3: - case 0xc4: - return skill_unit_onout(src,bl,tick); + nullpo_retr(0, group=unit->group); -/* default: - if(battle_config.error_log) - printf("skill_unit_ondelete: Unknown skill unit id=%d block=%d\n",sg->unit_id,bl->id); - break;*/ + if (flag) + skill_unit_onplace(unit,bl,tick); + else { + skill_unit_onout(unit,bl,tick); + unit = map_find_skill_unit_oncell(bl,bl->x,bl->y,group->skill_id,unit); + if (unit) + skill_unit_onplace(unit,bl,tick); } - skill_unitgrouptickset_delete(bl,sg); + return 0; } + /*========================================== * スキルユニットの限界イベント *------------------------------------------ @@ -6435,10 +6007,7 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) return 0; } - if(battle_config.pc_skill_reiteration == 0) { - range = -1; - switch(sd->skillid) { - case MG_SAFETYWALL: + /*case MG_SAFETYWALL: case WZ_FIREPILLAR: case HT_SKIDTRAP: case HT_LANDMINE: @@ -6451,28 +6020,23 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) case HT_CLAYMORETRAP: case HT_TALKIEBOX: case AL_WARP: - case PF_SPIDERWEB: /* スパイダ?ウェッブ */ - case RG_GRAFFITI: /* グラフィティ */ + case PF_SPIDERWEB: + case RG_GRAFFITI: range = 0; break; case AL_PNEUMA: range = 1; - break; - } - if(range >= 0) { - if(skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,range,sd->skillid) > 0) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } + break;*/ + if (!battle_config.pc_skill_reiteration && + skill_get_unit_flag(sd->skillid)&UF_NOREITERATION && + skill_check_unit_range(sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; } - if(battle_config.pc_skill_nofootset) { - range = -1; - switch(sd->skillid) { - case WZ_FIREPILLAR: + /*case WZ_FIREPILLAR: case HT_SKIDTRAP: case HT_LANDMINE: case HT_ANKLESNARE: @@ -6483,25 +6047,22 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) case HT_BLASTMINE: case HT_CLAYMORETRAP: case HT_TALKIEBOX: - case PF_SPIDERWEB: /* スパイダ?ウェッブ */ + case PF_SPIDERWEB: case WZ_ICEWALL: range = 2; break; case AL_WARP: range = 0; - break; - } - if(range >= 0) { - if(skill_check_unit_range2(sd->bl.m,sd->skillx,sd->skilly,range) > 0) { - clif_skill_fail(sd,sd->skillid,0,0); - sd->canact_tick = tick; - sd->canmove_tick = tick; - sd->skillitem = sd->skillitemlv = -1; - return 0; - } - } + break;*/ + if (battle_config.pc_skill_nofootset && + skill_get_unit_flag(sd->skillid)&UF_NOFOOTSET && + skill_check_unit_range2(sd->bl.m,sd->skillx,sd->skilly,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + sd->canact_tick = tick; + sd->canmove_tick = tick; + sd->skillitem = sd->skillitemlv = -1; + return 0; } - if(battle_config.pc_land_skill_limit) { maxcount = skill_get_maxcount(sd->skillid); if(maxcount > 0) { @@ -7523,22 +7084,22 @@ int skill_use_id( struct map_session_data *sd, int target_id, return 0; } break; - // removed on 12/14's patch [celest] - //case AS_SPLASHER: /* ベナムスプラッシャ? */ - /* { - struct status_change *t_sc_data = status_get_sc_data(bl); - if(t_sc_data && t_sc_data[SC_POISON].timer==-1){ - clif_skill_fail(sd,skill_num,0,10); - return 0; - } - } - break;*/ case PF_MEMORIZE: /* メモライズ */ casttime = 12000; break; case HW_MAGICPOWER: casttime = 700; break; + case HP_BASILICA: /* バジリカ */ + if (skill_check_unit_range(sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + return 0; + } + if (skill_check_unit_range2(sd->bl.m,sd->bl.x,sd->bl.y,sd->skillid,sd->skilllv)) { + clif_skill_fail(sd,sd->skillid,0,0); + return 0; + } + break; case GD_BATTLEORDER: case GD_REGENERATION: case GD_RESTORE: @@ -7991,13 +7552,14 @@ int skill_devotion3(struct block_list *bl,int target) int n,r=0; nullpo_retr(1, bl); + md = (struct map_session_data *)bl; - if( (md = (struct map_session_data *)bl) == NULL || (sd = map_id2sd(target)) == NULL ) + if ((sd = map_id2sd(target))==NULL) return 1; else r = distance(bl->x,bl->y,sd->bl.x,sd->bl.y); - if(pc_checkskill(sd,CR_DEVOTION)+6 < r){ // 許容範?を超えてた + if(pc_checkskill(md,CR_DEVOTION)+6 < r){ // 許容範?を超えてた for(n=0;n<5;n++) if(md->dev.val1[n]==target) md->dev.val2[n]=0; // 離れた時は、?を切るだけ @@ -8249,12 +7811,28 @@ int skill_abra_dataset(int skilllv) //NPCスキルはダメ if(skill >= NPC_PIERCINGATT && skill <= NPC_SUMMONMONSTER) return 0; //演奏スキルはダメ - if(skill_is_danceskill(skill)) return 0; + if (skill_get_unit_flag(skill)&UF_DANCE) return 0; return skill; } /*========================================== + * バジリカのセルを設定する + *------------------------------------------ + */ +void skill_basilica_cell(struct skill_unit *unit,int flag) +{ + int i,x,y,range = skill_get_unit_range(HP_BASILICA); + int size = range*2+1; + + for (i=0;i<size*size;i++) { + x = unit->bl.x+(i%size-range); + y = unit->bl.y+(i/size-range); + map_setcell(unit->bl.m,x,y,flag); + } +} + +/*========================================== * *------------------------------------------ */ @@ -8293,16 +7871,20 @@ int skill_clear_element_field(struct block_list *bl) { struct mob_data *md=NULL; struct map_session_data *sd=NULL; - int i,skillid; + int i,max,skillid; nullpo_retr(0, bl); - if(bl->type==BL_MOB) - md=(struct mob_data *)bl; - if(bl->type==BL_PC) - sd=(struct map_session_data *)bl; + if (bl->type==BL_MOB) { + max = MAX_MOBSKILLUNITGROUP; + md = (struct mob_data *)bl; + } else if(bl->type==BL_PC) { + max = MAX_SKILLUNITGROUP; + sd = (struct map_session_data *)bl; + } else + return 0; - for(i=0;i<MAX_MOBSKILLUNITGROUP;i++){ + for (i=0;i<max;i++) { if(sd){ skillid=sd->skillunit[i].skill_id; if(skillid==SA_DELUGE||skillid==SA_VOLCANO||skillid==SA_VIOLENTGALE||skillid==SA_LANDPROTECTOR) @@ -8372,7 +7954,8 @@ int skill_idun_heal(struct block_list *bl, va_list ap ) * 指定範??でsrcに?して有?なタ?ゲットのblの?を?える(foreachinarea) *------------------------------------------ */ -int skill_count_target(struct block_list *bl, va_list ap ){ +int skill_count_target(struct block_list *bl, va_list ap) +{ struct block_list *src; int *c; @@ -8528,48 +8111,6 @@ int skill_type_cloaking(struct block_list *bl) */ /*========================================== - * 演奏/ダンススキルかどうか判定 - * 引? スキルID - * ?り ダンスじゃない=0 合奏=2 それ以外のダンス=1 - *------------------------------------------ - */ -int skill_is_danceskill(int id) -{ - int i; - switch(id){ - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */ - case BD_RAGNAROK: /* 神?の?昏 */ - case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ - i=2; - break; - case BA_DISSONANCE: /* 不協和音 */ - case BA_FROSTJOKE: /* 寒いジョ?ク */ - case BA_WHISTLE: /* 口笛 */ - case BA_ASSASSINCROSS: /* 夕陽のアサシンクロス */ - case BA_POEMBRAGI: /* ブラギの詩 */ - case BA_APPLEIDUN: /* イドゥンの林檎 */ - case DC_UGLYDANCE: /* 自分勝手なダンス */ - case DC_SCREAM: /* スクリ?ム */ - case DC_HUMMING: /* ハミング */ - case DC_DONTFORGETME: /* 私を忘れないで… */ - case DC_FORTUNEKISS: /* 幸運のキス */ - case DC_SERVICEFORYOU: /* サ?ビスフォ?ユ? */ - i=1; - break; - default: - i=0; - } - return i; -} - -/*========================================== * 演奏/ダンスをやめる * flag 1で合奏中なら相方にユニットを任せる * @@ -8650,10 +8191,13 @@ struct skill_unit *skill_initunit(struct skill_unit_group *group,int idx,int x,i map_addblock(&unit->bl); clif_skill_setunit(unit); + +// if (group->skill_id==HP_BASILICA) +// skill_basilica_cell(unit,CELL_SETBASILICA); + return unit; } -int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap ); /*========================================== * スキルユニット削除 *------------------------------------------ @@ -8661,7 +8205,6 @@ int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap ); int skill_delunit(struct skill_unit *unit) { struct skill_unit_group *group; - int range; nullpo_retr(0, unit); if(!unit->alive) @@ -8671,11 +8214,15 @@ int skill_delunit(struct skill_unit *unit) /* onlimitイベント呼び出し */ skill_unit_onlimit( unit,gettick() ); - /* ondeleteイベント呼び出し */ - range=group->range; - map_foreachinarea( skill_unit_timer_sub_ondelete, unit->bl.m, - unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0, - &unit->bl,gettick() ); + /* onoutイベント呼び出し */ + if (!unit->range) { + map_foreachinarea(skill_unit_effect,unit->bl.m, + unit->bl.x,unit->bl.y,unit->bl.x,unit->bl.y,0, + &unit->bl,gettick(),0); + } + +// if (group->skill_id==HP_BASILICA) +// skill_basilica_cell(unit,CELL_CLRBASILICA); clif_skill_delunit(unit); @@ -8691,7 +8238,7 @@ int skill_delunit(struct skill_unit *unit) * スキルユニットグル?プ初期化 *------------------------------------------ */ -static int skill_unit_group_newid=10; +static int skill_unit_group_newid = MAX_SKILL_DB; struct skill_unit_group *skill_initunitgroup(struct block_list *src, int count,int skillid,int skilllv,int unit_id) { @@ -8743,7 +8290,7 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src, group->guild_id=status_get_guild_id(src); group->group_id=skill_unit_group_newid++; if(skill_unit_group_newid<=0) - skill_unit_group_newid=10; + skill_unit_group_newid = MAX_SKILL_DB; group->unit=(struct skill_unit *)aCalloc(count,sizeof(struct skill_unit)); group->unit_count=count; group->val1=group->val2=0; @@ -8751,39 +8298,23 @@ struct skill_unit_group *skill_initunitgroup(struct block_list *src, group->skill_lv=skilllv; group->unit_id=unit_id; group->map=src->m; - group->range=0; group->limit=10000; group->interval=1000; group->tick=gettick(); group->valstr=NULL; - if( skill_is_danceskill(skillid) ){ + if (skill_get_unit_flag(skillid)&UF_DANCE) { struct map_session_data *sd = NULL; if(src->type==BL_PC && (sd=(struct map_session_data *)src) ){ sd->skillid_dance=skillid; sd->skilllv_dance=skilllv; } status_change_start(src,SC_DANCING,skillid,(int)group,0,0,skill_get_time(skillid,skilllv)+1000,0); - switch(skillid){ //合奏スキルは相方をダンス?態にする - case BD_LULLABY: /* 子守歌 */ - case BD_RICHMANKIM: /* ニヨルドの宴 */ - case BD_ETERNALCHAOS: /* 永遠の混沌 */ - case BD_DRUMBATTLEFIELD: /* ?太鼓の響き */ - case BD_RINGNIBELUNGEN: /* ニ?ベルングの指輪 */ - case BD_ROKISWEIL: /* ロキの叫び */ - case BD_INTOABYSS: /* 深淵の中に */ - case BD_SIEGFRIED: /* 不死身のジ?クフリ?ド */ - case BD_RAGNAROK: /* 神?の?昏 */ - case CG_MOONLIT: /* 月明りの泉に落ちる花びら */ - { - int range=1; - int c=0; - if(sd){ - map_foreachinarea(skill_check_condition_use_sub,sd->bl.m, - sd->bl.x-range,sd->bl.y-range, - sd->bl.x+range,sd->bl.y+range,BL_PC,&sd->bl,&c); - } - } + //合奏スキルは相方をダンス状態にする + if (sd && skill_get_unit_flag(skillid)&UF_ENSEMBLE) { + int c=0; + map_foreachinarea(skill_check_condition_use_sub,sd->bl.m, + sd->bl.x-1,sd->bl.y-1,sd->bl.x+1,sd->bl.y+1,BL_PC,&sd->bl,&c); } } return group; @@ -8803,7 +8334,8 @@ int skill_delunitgroup(struct skill_unit_group *group) return 0; src=map_id2bl(group->src_id); - if( skill_is_danceskill(group->skill_id) ){ //ダンススキルはダンス?態を解除する + //ダンススキルはダンス状態を解除する + if (skill_get_unit_flag(group->skill_id)&UF_DANCE) { if(src) status_change_end(src,SC_DANCING,-1); } @@ -8841,13 +8373,14 @@ int skill_clear_unitgroup(struct block_list *src) if(src->type==BL_PC){ group=((struct map_session_data *)src)->skillunit; maxsug=MAX_SKILLUNITGROUP; - }else if(src->type==BL_MOB){ + } else if(src->type==BL_MOB){ group=((struct mob_data *)src)->skillunit; maxsug=MAX_MOBSKILLUNITGROUP; - }else if(src->type==BL_PET){ // [Valaris] + } else if(src->type==BL_PET){ // [Valaris] group=((struct pet_data *)src)->skillunit; maxsug=MAX_MOBSKILLUNITGROUP; - } + } else + return 0; if(group){ int i; for(i=0;i<maxsug;i++) @@ -8857,31 +8390,19 @@ int skill_clear_unitgroup(struct block_list *src) return 0; } -/* - * 珞ヌォケォュォェェヘヌェュェキェゾェホヤムツ - */ -int skill_unit_overlap_type(int skill_id) -{ - switch (skill_id) { - case WZ_STORMGUST: - case WZ_VERMILION: - return 1; // ェノェチェ鬪ォ鰥ーェォェ鬮タォ?ォクェ磑ェアェ - default: - return 0; // ?ローェォェ鬮タォ?ォクェ磑ェアェ - } -} - /*========================================== * スキルユニットグル?プの被影響tick?索 *------------------------------------------ */ struct skill_unit_group_tickset *skill_unitgrouptickset_search( - struct block_list *bl, struct skill_unit_group *sg) + struct block_list *bl,struct skill_unit_group *group,int tick) { int i,j=-1,k,s,id; struct skill_unit_group_tickset *set; nullpo_retr(0, bl); + if (group->interval==-1) + return NULL; if (bl->type == BL_PC) set = ((struct map_session_data *)bl)->skillunittick; @@ -8890,16 +8411,16 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search( else return 0; - if (skill_unit_overlap_type(sg->skill_id)) - id = s = sg->skill_id; + if (skill_get_unit_flag(group->skill_id)&UF_NOOVERLAP) + id = s = group->skill_id; else - id = s = sg->group_id; + id = s = group->group_id; for (i=0; i<MAX_SKILLUNITGROUPTICKSET; i++) { k = (i+s) % MAX_SKILLUNITGROUPTICKSET; if (set[k].id == id) return &set[k]; - else if (j == -1 && set[k].id == 0) + else if (j==-1 && (DIFF_TICK(tick,set[k].tick)>0 || set[k].id==0)) j=k; } @@ -8908,101 +8429,41 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search( sprintf (tmp_output, "skill_unitgrouptickset_search: tickset is full\n"); ShowWarning (tmp_output); } - for (i = 0; i<MAX_SKILLUNITGROUPTICKSET; i++) - set[k].id = 0; j = id % MAX_SKILLUNITGROUPTICKSET; } set[j].id = id; + set[j].tick = tick; return &set[j]; } /*========================================== - * スキルユニットグル?プの被影響tick削除 - *------------------------------------------ - */ -int skill_unitgrouptickset_delete( - struct block_list *bl, struct skill_unit_group *sg) -{ - int i, k, s, id; - struct skill_unit_group_tickset *set=NULL; - - nullpo_retr(0, bl); - if (bl->type == BL_PC) - set=((struct map_session_data *)bl)->skillunittick; - else if (bl->type == BL_MOB) - set=((struct mob_data *)bl)->skillunittick; - else - return 0; - - if (skill_unit_overlap_type(sg->skill_id)) - id = s = sg->skill_id; - else - id = s = sg->group_id; - - for(i=0; i<MAX_SKILLUNITGROUPTICKSET; i++) { - k = (i+s) % MAX_SKILLUNITGROUPTICKSET; - if (set[k].id == id) { - set[k].id = 0; - break; - } - } -// if (i == MAX_SKILLUNITGROUPTICKSET && battle_config.error_log) { -// printf("skill_unitgrouptickset_delete: tickset not found\n"); -// } - - return 0; -} - -/*========================================== * スキルユニットタイマ??動?理用(foreachinarea) *------------------------------------------ */ int skill_unit_timer_sub_onplace( struct block_list *bl, va_list ap ) { - struct block_list *src; - struct skill_unit *su; + struct skill_unit *unit; + struct skill_unit_group *group; unsigned int tick; nullpo_retr(0, bl); nullpo_retr(0, ap); - src=va_arg(ap,struct block_list*); + unit = va_arg(ap,struct skill_unit *); + tick = va_arg(ap,unsigned int); - tick=va_arg(ap,unsigned int); - su = (struct skill_unit *)src; - - if( su && su->alive ) { - struct skill_unit_group *sg; - sg = su->group; - if(sg && battle_check_target(src,bl,sg->target_flag )>0) - skill_unit_onplace( su, bl, tick ); - } - return 0; -} + if (bl->type!=BL_PC && bl->type!=BL_MOB) + return 0; + if (!unit->alive || bl->prev==NULL) + return 0; -/*========================================== - * スキルユニットタイマ?削除?理用(foreachinarea) - *------------------------------------------ - */ -int skill_unit_timer_sub_ondelete( struct block_list *bl, va_list ap ) -{ - struct block_list *src; - struct skill_unit *su; - unsigned int tick; + nullpo_retr(0, group=unit->group); - nullpo_retr(0, bl); - nullpo_retr(0, ap); - src=va_arg(ap,struct block_list*); + if (battle_check_target(&unit->bl,bl,group->target_flag)<=0) + return 0; - tick=va_arg(ap,unsigned int); - su = (struct skill_unit *)src; + skill_unit_onplace_timer(unit,bl,tick); - if( su && su->alive ){ - struct skill_unit_group *sg; - sg = su->group; - if( sg && battle_check_target(src,bl,sg->target_flag )>0 ) - skill_unit_ondelete( su, bl, tick ); - } return 0; } @@ -9020,28 +8481,37 @@ int skill_unit_timer_sub( struct block_list *bl, va_list ap ) nullpo_retr(0, bl); nullpo_retr(0, ap); nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, group=unit->group); tick=va_arg(ap,unsigned int); if(!unit->alive) return 0; - range=(unit->range!=0)?unit->range:group->range; + nullpo_retr(0, group=unit->group); + range = unit->range; - /* onplaceイベント呼び出し */ - if(unit->alive && unit->range>=0){ - map_foreachinarea( skill_unit_timer_sub_onplace, bl->m, - bl->x-range,bl->y-range,bl->x+range,bl->y+range,0, - bl,tick); - if(group->unit_id == 0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val2){ - map_foreachinarea( skill_idun_heal, bl->m, - bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,unit); - group->val2++; + /* onplace_timerイベント呼び出し */ + if (range>=0 && group->interval!=-1) { + map_foreachinarea(skill_unit_timer_sub_onplace, bl->m, + bl->x-range,bl->y-range,bl->x+range,bl->y+range,0,bl,tick); + if (!unit->alive) + return 0; + // マグヌスは発動したユニットは削除する + if (group->skill_id==PR_MAGNUS && unit->val2) { + skill_delunit(unit); + return 0; } } + // イドゥンの林檎による回復 + if (group->unit_id==0xaa && DIFF_TICK(tick,group->tick)>=6000*group->val3) { + struct block_list *src = map_id2bl(group->src_id); + int range = skill_get_unit_layout_type(group->skill_id,group->skill_lv); + nullpo_retr(0, src); + map_foreachinarea(skill_idun_heal,src->m, + src->x-range,src->y-range,src->x+range,src->y+range,0,unit); + group->val3++; + } /* 時間切れ削除 */ - if(unit->alive && - (DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit) ){ + if((DIFF_TICK(tick,group->tick)>=group->limit || DIFF_TICK(tick,group->tick)>=unit->limit)){ switch(group->unit_id){ case 0x8f: /* ブラストマイン */ group->unit_id = 0x8c; @@ -9117,92 +8587,33 @@ int skill_unit_timer( int tid,unsigned int tick,int id,int data) * スキルユニット移動時?理用(foreachinarea) *------------------------------------------ */ -int skill_unit_out_all_sub( struct block_list *bl, va_list ap ) -{ - struct skill_unit *unit; - struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, group=unit->group); - - tick=va_arg(ap,unsigned int); - - if(!unit->alive || src->prev==NULL) - return 0; - - range=(unit->range!=0)?unit->range:group->range; - - if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 ) - return 0; - - if( src->x >= bl->x-range && src->x <= bl->x+range && - src->y >= bl->y-range && src->y <= bl->y+range ) - skill_unit_onout( unit, src, tick ); - - return 0; -} - - -/*========================================== - * スキルユニット移動時?理 - *------------------------------------------ - */ -int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range) -{ - nullpo_retr(0, bl); - - if( bl->prev==NULL ) - return 0; - - if(range<7) - range=7; - map_foreachinarea( skill_unit_out_all_sub, - bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL, - bl,tick ); - - return 0; -} - -/*========================================== - * スキルユニット移動時?理用(foreachinarea) - *------------------------------------------ - */ int skill_unit_move_sub( struct block_list *bl, va_list ap ) { - struct skill_unit *unit; + struct skill_unit *unit = (struct skill_unit *)bl; struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; + struct block_list *target; + unsigned int tick,flag; nullpo_retr(0, bl); nullpo_retr(0, ap); - nullpo_retr(0, unit=(struct skill_unit *)bl); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - - tick=va_arg(ap,unsigned int); + nullpo_retr(0, target=va_arg(ap,struct block_list*)); + tick = va_arg(ap,unsigned int); + flag = va_arg(ap,int); - if(!unit->alive || src->prev==NULL) + if (target->type!=BL_PC && target->type!=BL_MOB) return 0; - if((group=unit->group) == NULL) + nullpo_retr(0, group=unit->group); + if (group->interval!=-1) return 0; - range=(unit->range!=0)?unit->range:group->range; - if( range<0 || battle_check_target(bl,src,group->target_flag )<=0 ) + if (!unit->alive || target->prev==NULL) return 0; - if( src->x >= bl->x-range && src->x <= bl->x+range && - src->y >= bl->y-range && src->y <= bl->y+range ) - skill_unit_onplace( unit, src, tick ); + if (flag) + skill_unit_onplace(unit,target,tick); else - skill_unit_onout( unit, src, tick ); + skill_unit_onout(unit,target,tick); return 0; } @@ -9211,54 +8622,16 @@ int skill_unit_move_sub( struct block_list *bl, va_list ap ) * スキルユニット移動時?理 *------------------------------------------ */ -int skill_unit_move( struct block_list *bl,unsigned int tick,int range) +int skill_unit_move(struct block_list *bl,unsigned int tick,int flag) { nullpo_retr(0, bl); - if( bl->prev==NULL ) + if(bl->prev==NULL ) return 0; - if(range<7) - range=7; - map_foreachinarea( skill_unit_move_sub, - bl->m,bl->x-range,bl->y-range,bl->x+range,bl->y+range,BL_SKILL, - bl,tick ); - - return 0; -} + map_foreachinarea(skill_unit_move_sub, + bl->m,bl->x,bl->y,bl->x,bl->y,BL_SKILL,bl,tick,flag); -/*========================================== - * スキルユニット自?の移動時?理(foreachinarea) - *------------------------------------------ - */ -int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap ) -{ - struct skill_unit *unit; - struct skill_unit_group *group; - struct block_list *src; - int range; - unsigned int tick; - - nullpo_retr(0, bl); - nullpo_retr(0, ap); - nullpo_retr(0, src=va_arg(ap,struct block_list*)); - nullpo_retr(0, unit=(struct skill_unit *)src); - nullpo_retr(0, group=unit->group); - - tick=va_arg(ap,unsigned int); - - if(!unit->alive || bl->prev==NULL) - return 0; - - range=(unit->range!=0)?unit->range:group->range; - - if( range<0 || battle_check_target(src,bl,group->target_flag )<=0 ) - return 0; - if( bl->x >= src->x-range && bl->x <= src->x+range && - bl->y >= src->y-range && bl->y <= src->y+range ) - skill_unit_onplace( unit, bl, tick ); - else - skill_unit_onout( unit, bl, tick ); return 0; } @@ -9269,115 +8642,97 @@ int skill_unit_move_unit_group_sub( struct block_list *bl, va_list ap ) */ int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy) { + int i,j; + int tick = gettick(); + int *m_flag; + struct skill_unit *unit1; + struct skill_unit *unit2; + nullpo_retr(0, group); + if (group->unit_count<=0) + return 0; + if (group->unit==NULL) + return 0; - if( group->unit_count<=0) + // 移動可能なスキルはダンス系と、ブラストマイン、クレイモアートラップのみ + if (!(skill_get_unit_flag(group->skill_id)&UF_DANCE) && + group->skill_id!=HT_CLAYMORETRAP && group->skill_id!=HT_BLASTMINE) return 0; - if(group->unit!=NULL){ - if(!battle_config.unit_movement_type){ - int i; - for(i=0;i<group->unit_count;i++){ - struct skill_unit *unit=&group->unit[i]; - if(unit->alive && !(m==unit->bl.m && dx==0 && dy==0)){ - int range=unit->range; - map_delblock(&unit->bl); - unit->bl.m = m; - unit->bl.x += dx; - unit->bl.y += dy; - map_addblock(&unit->bl); - clif_skill_setunit(unit); - if(range>0){ - if(range<7) - range=7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit->bl.m, - unit->bl.x-range,unit->bl.y-range,unit->bl.x+range,unit->bl.y+range,0, - &unit->bl,gettick() ); - } - } + m_flag = malloc(sizeof(int)*group->unit_count); + memset(m_flag,0,sizeof(int)*group->unit_count);// 移動フラグ + // 先にフラグを全部決める + // m_flag + // 0: 単純移動 + // 1: ユニットを移動する(現位置からユニットがなくなる) + // 2: 残留&新位置が移動先となる(移動先にユニットが存在しない) + // 3: 残留 + for(i=0;i<group->unit_count;i++){ + unit1=&group->unit[i]; + if (!unit1->alive || unit1->bl.m!=m) + continue; + for(j=0;j<group->unit_count;j++){ + unit2=&group->unit[j]; + if (!unit2->alive) + continue; + if (unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){ + // 移動先にユニットがかぶっている + m_flag[i] |= 0x1; } - }else{ - int i,j, *r_flag, *s_flag, *m_flag; - struct skill_unit *unit1; - struct skill_unit *unit2; - r_flag = (int *) aMallocA(sizeof(int) * group->unit_count); - s_flag = (int *) aMallocA(sizeof(int) * group->unit_count); - m_flag = (int *) aMallocA(sizeof(int) * group->unit_count); - memset(r_flag,0, sizeof(int) * group->unit_count);// ?承フラグ - memset(s_flag,0, sizeof(int) * group->unit_count);// ?承フラグ - memset(m_flag,0, sizeof(int) * group->unit_count);// ?承フラグ - - //先にフラグを全部決める - for(i=0;i<group->unit_count;i++){ - int move_check=0;// かぶりフラグ - unit1=&group->unit[i]; - for(j=0;j<group->unit_count;j++){ - unit2=&group->unit[j]; - if(unit1->bl.m==m && unit1->bl.x+dx==unit2->bl.x && unit1->bl.y+dy==unit2->bl.y){ - //移動先にユニットがかぶってたら - s_flag[i]=1;// 移動前のユニットナンバ?の?承フラグon - r_flag[j]=1;// かぶるユニットナンバ?の?留フラグon - move_check=1;//ユニットがかぶった。 - break; - } - } - if(!move_check)// ユニットがかぶってなかったら - m_flag[i]=1;// 移動前ユニットナンバ?の移動フラグon - } - - //フラグに基づいてユニット移動 - for(i=0;i<group->unit_count;i++){ - unit1=&group->unit[i]; - if(m_flag[i]){// 移動フラグがonで - if(!r_flag[i]){// ?留フラグがoffなら - //?純移動(rangeも?承の必要無し) - int range=unit1->range; - map_delblock(&unit1->bl); - unit1->bl.m = m; - unit1->bl.x += dx; - unit1->bl.y += dy; - map_addblock(&unit1->bl); - clif_skill_setunit(unit1); - if(range > 0){ - if(range < 7) - range = 7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit1->bl.m, - unit1->bl.x-range,unit1->bl.y-range,unit1->bl.x+range,unit1->bl.y+range,0, - &unit1->bl,gettick() ); - } - }else{// ?留フラグがonなら - //空ユニットになるので、?承可能なユニットを探す - for(j=0;j<group->unit_count;j++){ - unit2=&group->unit[j]; - if(s_flag[j] && !r_flag[j]){ - // ?承移動(range?承付き) - int range=unit1->range; - map_delblock(&unit2->bl); - unit2->bl.m = m; - unit2->bl.x = unit1->bl.x + dx; - unit2->bl.y = unit1->bl.y + dy; - unit2->range = unit1->range; - map_addblock(&unit2->bl); - clif_skill_setunit(unit2); - if(range > 0){ - if(range < 7) - range = 7; - map_foreachinarea( skill_unit_move_unit_group_sub, unit2->bl.m, - unit2->bl.x-range,unit2->bl.y-range,unit2->bl.x+range,unit2->bl.y+range,0, - &unit2->bl,gettick() ); - } - s_flag[j]=0;// ?承完了したのでoff - break; - } - } - } + if (unit1->bl.x-dx==unit2->bl.x && unit1->bl.y-dy==unit2->bl.y){ + // ユニットがこの場所にやってくる + m_flag[i] |= 0x2; + } + } + } + // フラグに基づいてユニット移動 + // フラグが1のunitを探し、フラグが2のunitの移動先に移す + j = 0; + for (i=0;i<group->unit_count;i++) { + unit1=&group->unit[i]; + if (!unit1->alive) + continue; + if (!(m_flag[i]&0x2)) { + // ユニットがなくなる場所でスキルユニット影響を消す + map_foreachinarea(skill_unit_effect,unit1->bl.m, + unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0, + &unit1->bl,tick,0); + } + if (m_flag[i]==0) { + // 単純移動 + map_delblock(&unit1->bl); + unit1->bl.m = m; + unit1->bl.x += dx; + unit1->bl.y += dy; + map_addblock(&unit1->bl); + clif_skill_setunit(unit1); + } else if (m_flag[i]==1) { + // フラグが2のものを探してそのユニットの移動先に移動 + for(;j<group->unit_count;j++) { + if (m_flag[j]==2) { + // 継承移動 + unit2 = &group->unit[j]; + if (!unit2->alive) + continue; + map_delblock(&unit1->bl); + unit1->bl.m = m; + unit1->bl.x = unit2->bl.x+dx; + unit1->bl.y = unit2->bl.y+dy; + map_addblock(&unit1->bl); + clif_skill_setunit(unit1); + j++; + break; } } - aFree(r_flag); - aFree(s_flag); - aFree(m_flag); + } + if (!(m_flag[i]&0x2)) { + // 移動後の場所でスキルユニットを発動 + map_foreachinarea(skill_unit_effect,unit1->bl.m, + unit1->bl.x,unit1->bl.y,unit1->bl.x,unit1->bl.y,0, + &unit1->bl,tick,1); } } + free(m_flag); return 0; } @@ -9505,25 +8860,29 @@ int skill_produce_mix( struct map_session_data *sd, if(!equip) { // Corrected rates [DracoRPG] --------------------------// if(skill_produce_db[idx].req_skill==AM_PHARMACY) { + make_per = pc_checkskill(sd,AM_LEARNINGPOTION)*100 + + pc_checkskill(sd,AM_PHARMACY)*300 + sd->status.job_level*20 + + sd->status.dex*10+sd->status.int_*5; + if(nameid >= 501 && nameid <= 505) // Normal potions - make_per = 2000 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_POTIONPITCHER)*100; - if(nameid >= 605 && nameid <= 606) // Anodyne & Aloevera (not sure of the formula, I put the same base value as normal pots but without the Aid Potion bonus since they are not throwable pots ^^) - make_per = 2000 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300; + make_per += 2000 + pc_checkskill(sd,AM_POTIONPITCHER)*100; + else if(nameid >= 605 && nameid <= 606) // Anodyne & Aloevera (not sure of the formula, I put the same base value as normal pots but without the Aid Potion bonus since they are not throwable pots ^^) + make_per += 2000; else if(nameid >= 545 && nameid <= 547) // Concentrated potions - make_per = sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300; + ; else if(nameid == 970) // Alcohol - make_per = 1000 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300; + make_per += 1000; else if(nameid == 7135) // Bottle Grenade - make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_DEMONSTRATION)*100; + make_per += 500 + pc_checkskill(sd,AM_DEMONSTRATION)*100; else if(nameid == 7136) // Acid Bottle - make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_ACIDTERROR)*100; + make_per += 500 + pc_checkskill(sd,AM_ACIDTERROR)*100; else if(nameid == 7137) // Plant Bottle - make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CANNIBALIZE)*100; + make_per += 500 + pc_checkskill(sd,AM_CANNIBALIZE)*100; else if(nameid == 7138) // Marine Sphere Bottle - make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_SPHEREMINE)*100; + make_per += 500 + pc_checkskill(sd,AM_SPHEREMINE)*100; else if(nameid == 7139) // Glistening Coat - make_per = 500 + sd->status.job_level*20 + sd->paramc[4]*10 + sd->paramc[5]*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300 + pc_checkskill(sd,AM_CP_WEAPON)*100 + - pc_checkskill(sd,AM_CP_SHIELD)*100 + pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100; + make_per += 500 + pc_checkskill(sd,AM_CP_WEAPON)*100 + pc_checkskill(sd,AM_CP_SHIELD)*100 + + pc_checkskill(sd,AM_CP_ARMOR)*100 + pc_checkskill(sd,AM_CP_HELM)*100; else make_per = 1000 + sd->status.base_level*30 + sd->paramc[3]*20 + sd->paramc[4]*15 + pc_checkskill(sd,AM_LEARNINGPOTION)*100 + pc_checkskill(sd,AM_PHARMACY)*300; } else if (skill_produce_db[idx].req_skill == ASC_CDP) { @@ -9604,8 +8963,7 @@ int skill_produce_mix( struct map_session_data *sd, clif_additem(sd,0,0,flag); map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,NULL,NULL,NULL,0); } - } - else { + } else { if(log_config.produce > 0) log_produce(sd,nameid,slot1,slot2,slot3,0); @@ -9675,6 +9033,213 @@ int skill_arrow_create( struct map_session_data *sd,int nameid) * 初期化系 */ +/*---------------------------------------------------------------------------- + * 初期化系 + */ + +/* + * 文字列処理 + * ',' で区切って val に戻す + */ +int skill_split_str(char *str,char **val,int num) +{ + int i; + + for (i=0; i<num && str; i++){ + val[i] = str; + str = strchr(str,','); + if (str) + *str++=0; + } + return i; +} +/* + * 文字列処理 + * ':' で区切ってatoiしてvalに戻す + */ +int skill_split_atoi(char *str,int *val) +{ + int i, max = 0; + + for (i=0; i<MAX_SKILL_LEVEL; i++) { + if (str) { + val[i] = max = atoi(str); + str = strchr(str,':'); + if (str) + *str++=0; + } else { + val[i] = max; + } + } + return i; +} + +/* + * スキルユニットの配置情報作成 + */ +void skill_init_unit_layout() +{ + int i,j,size,pos = 0; + + memset(skill_unit_layout,0,sizeof(skill_unit_layout)); + // 矩形のユニット配置を作成する + for (i=0; i<=MAX_SQUARE_LAYOUT; i++) { + size = i*2+1; + skill_unit_layout[i].count = size*size; + for (j=0; j<size*size; j++) { + skill_unit_layout[i].dx[j] = (j%size-i); + skill_unit_layout[i].dy[j] = (j/size-i); + } + } + pos = i; + // 矩形以外のユニット配置を作成する + for (i=0;i<MAX_SKILL_DB;i++) { + if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1) + continue; + switch (i) { + case MG_FIREWALL: + case WZ_ICEWALL: + // ファイアーウォール、アイスウォールは方向で変わるので別処理 + break; + case PR_SANCTUARY: + { + static const int dx[] = { + -1, 0, 1,-2,-1, 0, 1, 2,-2,-1, + 0, 1, 2,-2,-1, 0, 1, 2,-1, 0, 1}; + static const int dy[]={ + -2,-2,-2,-1,-1,-1,-1,-1, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2}; + skill_unit_layout[pos].count = 21; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case PR_MAGNUS: + { + static const int dx[] = { + -1, 0, 1,-1, 0, 1,-3,-2,-1, 0, + 1, 2, 3,-3,-2,-1, 0, 1, 2, 3, + -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,-1, 0, 1}; + static const int dy[] = { + -3,-3,-3,-2,-2,-2,-1,-1,-1,-1, + -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3}; + skill_unit_layout[pos].count = 33; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case AS_VENOMDUST: + { + static const int dx[] = {-1, 0, 0, 0, 1}; + static const int dy[] = { 0,-1, 0, 1, 0}; + skill_unit_layout[pos].count = 5; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case CR_GRANDCROSS: + case NPC_DARKGRANDCROSS: + { + static const int dx[] = { + 0, 0,-1, 0, 1,-2,-1, 0, 1, 2, + -4,-3,-2,-1, 0, 1, 2, 3, 4,-2, + -1, 0, 1, 2,-1, 0, 1, 0, 0}; + static const int dy[] = { + -4,-3,-2,-2,-2,-1,-1,-1,-1,-1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 2, 2, 2, 3, 4}; + skill_unit_layout[pos].count = 29; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + case PF_FOGWALL: + { + static const int dx[] = { + -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; + static const int dy[] = { + -1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}; + skill_unit_layout[pos].count = 15; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + break; + } + default: + printf("unknown unit layout at skill %d\n",i); + break; + } + if (!skill_unit_layout[pos].count) + continue; + for (j=0;j<MAX_SKILL_LEVEL;j++) + skill_db[i].unit_layout_type[j] = pos; + pos++; + } + // ファイヤーウォール + firewall_unit_pos = pos; + for (i=0;i<8;i++) { + if (i&1) { /* 斜め配置 */ + skill_unit_layout[pos].count = 5; + if (i&0x2) { + int dx[] = {-1,-1, 0, 0, 1}; + int dy[] = { 1, 0, 0,-1,-1}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { + int dx[] = { 1, 1 ,0, 0,-1}; + int dy[] = { 1, 0, 0,-1,-1}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } else { /* 縦横配置 */ + skill_unit_layout[pos].count = 3; + if (i%4==0) { /* 上下 */ + int dx[] = {-1, 0, 1}; + int dy[] = { 0, 0, 0}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { /* 左右 */ + int dx[] = { 0, 0, 0}; + int dy[] = {-1, 0, 1}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } + pos++; + } + // アイスウォール + icewall_unit_pos = pos; + for (i=0;i<8;i++) { + skill_unit_layout[pos].count = 5; + if (i&1) { /* 斜め配置 */ + if (i&0x2) { + int dx[] = {-2,-1, 0, 1, 2}; + int dy[] = { 2,-1, 0,-1,-2}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { + int dx[] = { 2, 1 ,0,-1,-2}; + int dy[] = { 2, 1, 0,-1,-2}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } else { /* 縦横配置 */ + if (i%4==0) { /* 上下 */ + int dx[] = {-2,-1, 0, 1, 2}; + int dy[] = { 0, 0, 0, 0, 0}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } else { /* 左右 */ + int dx[] = { 0, 0, 0, 0, 0}; + int dy[] = {-2,-1, 0, 1, 2}; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + } + pos++; + } +} + /*========================================== * スキル?係ファイル?み?み * skill_db.txt スキルデ?タ @@ -9699,14 +9264,10 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; + char *split[50]; if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<14 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,14); if(split[13]==NULL || j<14) continue; @@ -9717,28 +9278,13 @@ int skill_readdb(void) continue; /* printf("skill id=%d\n",i); */ - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].range[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[1],skill_db[i].range); skill_db[i].hit=atoi(split[2]); skill_db[i].inf=atoi(split[3]); skill_db[i].pl=atoi(split[4]); skill_db[i].nk=atoi(split[5]); skill_db[i].max=atoi(split[6]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[7];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].num[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[1],skill_db[i].num); if(strcmpi(split[8],"yes") == 0) skill_db[i].castcancel=1; @@ -9755,14 +9301,7 @@ int skill_readdb(void) skill_db[i].skill_type=BF_MISC; else skill_db[i].skill_type=0; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[13];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].blewcount[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[13],skill_db[i].blewcount); } fclose(fp); sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_db.txt"); @@ -9774,14 +9313,10 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[51], *split2[MAX_SKILL_LEVEL]; + char *split[50]; if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<30 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,30); if(split[29]==NULL || j<30) continue; @@ -9791,74 +9326,26 @@ int skill_readdb(void) else if(i<=0 || i>MAX_SKILL_DB) continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].hp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].mhp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].sp[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].hp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[5];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].sp_rate[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[6];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].zeny[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[7];j<32 && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<32 && split2[k];k++) { - l = atoi(split2[k]); - if(l == 99) { + skill_split_atoi(split[1],skill_db[i].hp); + skill_split_atoi(split[2],skill_db[i].mhp); + skill_split_atoi(split[3],skill_db[i].sp); + skill_split_atoi(split[4],skill_db[i].hp_rate); + skill_split_atoi(split[5],skill_db[i].sp_rate); + skill_split_atoi(split[6],skill_db[i].zeny); + + p = split[7]; + for(j=0;j<32;j++){ + l = atoi(p); + if (l==99) { skill_db[i].weapon = 0xffffffff; break; } else skill_db[i].weapon |= 1<<l; + p=strchr(p,':'); + if(!p) + break; + p++; } if( strcmpi(split[8],"hiding")==0 ) skill_db[i].state=ST_HIDING; @@ -9875,14 +9362,7 @@ int skill_readdb(void) else if( strcmpi(split[8],"water")==0 ) skill_db[i].state=ST_WATER; else skill_db[i].state=ST_NONE; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[9];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].spiritball[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[9],skill_db[i].spiritball); skill_db[i].itemid[0]=atoi(split[10]); skill_db[i].amount[0]=atoi(split[11]); skill_db[i].itemid[1]=atoi(split[12]); @@ -9915,15 +9395,11 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; + char *split[50]; memset(split,0,sizeof(split)); // [Valaris] thanks to fov if(line[0]=='/' && line[1]=='/') continue; - for(j=0,p=line;j<5 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,5); if(split[4]==NULL || j<5) continue; @@ -9933,45 +9409,55 @@ int skill_readdb(void) else if(i<=0 || i>MAX_SKILL_DB) continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].cast[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - - memset(split2,0,sizeof(split2)); - for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].delay[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[1],skill_db[i].cast); + skill_split_atoi(split[2],skill_db[i].delay); + skill_split_atoi(split[3],skill_db[i].upkeep_time); + skill_split_atoi(split[4],skill_db[i].upkeep_time2); + } + fclose(fp); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_cast_db.txt"); + ShowStatus(tmp_output); - memset(split2,0,sizeof(split2)); - for(j=0,p=split[3];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].upkeep_time[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + /* スキルユニットデータベース */ + fp = fopen("db/skill_unit_db.txt","r"); + if (fp==NULL) { + printf("can't read db/skill_unit_db.txt\n"); + return 1; + } + while (fgets(line,1020,fp)) { + char *split[50]; + if (line[0]=='/' && line[1]=='/') + continue; + j = skill_split_str(line,split,8); + if (split[7]==NULL || j<8) + continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[4];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].upkeep_time2[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + i=atoi(split[0]); + if (i>=10000 && i<10015) // for guild skills [Celest] + i -= 9500; + else if(i<=0 || i>MAX_SKILL_DB) + continue; + skill_db[i].unit_id[0] = strtol(split[1],NULL,16); + skill_db[i].unit_id[1] = strtol(split[2],NULL,16); + skill_split_atoi(split[3],skill_db[i].unit_layout_type); + skill_db[i].unit_range = atoi(split[4]); + skill_db[i].unit_interval = atoi(split[5]); + + if( strcmpi(split[6],"noenemy")==0 ) skill_db[i].unit_target=BCT_NOENEMY; + else if( strcmpi(split[6],"friend")==0 ) skill_db[i].unit_target=BCT_NOENEMY; + else if( strcmpi(split[6],"party")==0 ) skill_db[i].unit_target=BCT_PARTY; + else if( strcmpi(split[6],"all")==0 ) skill_db[i].unit_target=BCT_ALL; + else if( strcmpi(split[6],"enemy")==0 ) skill_db[i].unit_target=BCT_ENEMY; + else if( strcmpi(split[6],"self")==0 ) skill_db[i].unit_target=BCT_SELF; + else skill_db[i].unit_target = strtol(split[6],NULL,16); + + skill_db[i].unit_flag = strtol(split[7],NULL,16); + k++; } fclose(fp); - sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_cast_db.txt"); + sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_unit_db.txt"); ShowStatus(tmp_output); + skill_init_unit_layout(); /* 製造系スキルデ?タベ?ス */ memset(skill_produce_db,0,sizeof(skill_produce_db)); @@ -9990,16 +9476,11 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<3 + MAX_PRODUCE_RESOURCE * 2 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,(3 + MAX_PRODUCE_RESOURCE * 2)); if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); - if(i<=0) - continue; + if(i<=0) continue; skill_produce_db[k].nameid=i; skill_produce_db[k].itemlv=atoi(split[1]); @@ -10031,11 +9512,7 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<13 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,13); if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); @@ -10068,11 +9545,7 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<13 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,13); if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); @@ -10096,15 +9569,11 @@ int skill_readdb(void) return 1; } while(fgets(line,1020,fp)){ - char *split[50], *split2[MAX_SKILL_LEVEL]; + char *split[50]; if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<3 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,3); if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); @@ -10113,25 +9582,10 @@ int skill_readdb(void) else if(i<=0 || i>MAX_SKILL_DB) continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[1];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].castnodex[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); - + skill_split_atoi(split[1],skill_db[i].castnodex); if (!split[2]) continue; - memset(split2,0,sizeof(split2)); - for(j=0,p=split[2];j<MAX_SKILL_LEVEL && p;j++){ - split2[j]=p; - p=strchr(p,':'); - if(p) *p++=0; - } - for(k=0;k<MAX_SKILL_LEVEL;k++) - skill_db[i].delaynodex[k]=(split2[k])? atoi(split2[k]):atoi(split2[0]); + skill_split_atoi(split[2],skill_db[i].delaynodex); } fclose(fp); sprintf(tmp_output,"Done reading '"CL_WHITE"%s"CL_RESET"'.\n","db/skill_castnodex_db.txt"); @@ -10148,11 +9602,7 @@ int skill_readdb(void) if(line[0]=='/' && line[1]=='/') continue; memset(split,0,sizeof(split)); - for(j=0,p=line;j<2 && p;j++){ - split[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } + j = skill_split_str(line,split,2); if(split[0]==0) //fixed by Lupus continue; i=atoi(split[0]); diff --git a/src/map/skill.h b/src/map/skill.h index dc789aa4a..72653e9a9 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -25,6 +25,12 @@ struct skill_db { int castnodex[MAX_SKILL_LEVEL]; int delaynodex[MAX_SKILL_LEVEL]; int nocast; + int unit_id[2]; + int unit_layout_type[MAX_SKILL_LEVEL]; + int unit_range; + int unit_interval; + int unit_target; + int unit_flag; }; extern struct skill_db skill_db[MAX_SKILL_DB]; @@ -35,6 +41,24 @@ struct skill_name_db { }; extern const struct skill_name_db skill_names[]; +#define MAX_SKILL_UNIT_LAYOUT 50 +#define MAX_SQUARE_LAYOUT 5 // 11*11のユニット配置が最大 +#define MAX_SKILL_UNIT_COUNT ((MAX_SQUARE_LAYOUT*2+1)*(MAX_SQUARE_LAYOUT*2+1)) +struct skill_unit_layout { + int count; + int dx[MAX_SKILL_UNIT_COUNT]; + int dy[MAX_SKILL_UNIT_COUNT]; +}; + +enum { + UF_DEFNOTENEMY = 0x0001, // defnotenemy 設定でBCT_NOENEMYに切り替え + UF_NOREITERATION = 0x0002, // 重複置き禁止 + UF_NOFOOTSET = 0x0004, // 足元置き禁止 + UF_NOOVERLAP = 0x0008, // ユニット効果が重複しない + UF_DANCE = 0x0100, // ダンススキル + UF_ENSEMBLE = 0x0200, // 合奏スキル +}; + // アイテム作成デ?タベ?ス struct skill_produce_db { int nameid, trigger; @@ -87,6 +111,7 @@ int skill_get_unit_id(int id,int flag); int skill_get_inf2( int id ); int skill_get_maxcount( int id ); int skill_get_blewcount( int id ,int lv ); +int skill_get_unit_flag( int id ); int skill_tree_get_max( int id, int b_class ); // Celest // スキルの使用 @@ -110,10 +135,6 @@ int skill_delunit(struct skill_unit *unit); struct skill_unit_group *skill_initunitgroup(struct block_list *src, int count,int skillid,int skilllv,int unit_id); int skill_delunitgroup(struct skill_unit_group *group); - -struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg); -int skill_unitgrouptickset_delete(struct block_list *bl,struct skill_unit_group *sg); - int skill_clear_unitgroup(struct block_list *src); int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl, @@ -121,12 +142,12 @@ int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl, int skill_castfix( struct block_list *bl, int time ); int skill_delayfix( struct block_list *bl, int time ); -int skill_check_unit_range(int m,int x,int y,int range,int skillid); -int skill_check_unit_range2(int m,int x,int y,int range); +int skill_check_unit_range(int m,int x,int y,int skillid, int skilllv); +int skill_check_unit_range2(int m,int x,int y,int skillid, int skilllv); // -- moonsoul (added skill_check_unit_cell) int skill_check_unit_cell(int skillid,int m,int x,int y,int unit_id); int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range); -int skill_unit_move( struct block_list *bl,unsigned int tick,int range); +int skill_unit_move(struct block_list *bl,unsigned int tick,int flag); int skill_unit_move_unit_group( struct skill_unit_group *group, int m,int dx,int dy); struct skill_unit_group *skill_check_dancing( struct block_list *src ); @@ -151,7 +172,6 @@ void skill_devotion_end(struct map_session_data *md,struct map_session_data *sd, // その他 int skill_check_cloaking(struct block_list *bl); int skill_type_cloaking(struct block_list *bl); -int skill_is_danceskill(int id); // ステ?タス異常 int skill_encchant_eremental_end(struct block_list *bl, int type); diff --git a/src/map/status.c b/src/map/status.c index 0d35572d0..5275be42a 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -31,14 +31,17 @@ int SkillStatusChangeTable[]={ /* status.hのenumのSC_***とあわせること */ -1, 1,-1, /* 10- */ SC_SIGHT, /* サイト */ - -1,-1,-1,-1, + -1, + SC_SAFETYWALL, /* セーフティーウォール */ + -1,-1,-1, SC_FREEZE, /* フロストダイバ? */ SC_STONE, /* スト?ンカ?ス */ -1,-1,-1, /* 20- */ -1,-1,-1,-1, SC_RUWACH, /* ルアフ */ - -1,-1,-1,-1, + SC_PNEUMA, /* ニューマ */ + -1,-1,-1, SC_INCREASEAGI, /* 速度?加 */ /* 30- */ SC_DECREASEAGI, /* 速度減少 */ @@ -3585,15 +3588,6 @@ int status_change_start(struct block_list *bl,int type,int val1,int val2,int val case SC_ANKLE: break; - /* ウォ?タ?ボ?ル */ - case SC_WATERBALL: - tick=150; - if(val1>5) //レベルが5以上の場合は25?に制限(1?目はすでに打ってるので-1) - val3=5*5-1; - else - val3= (val1|1)*(val1|1)-1; - break; - /* スキルじゃない/時間に?係しない */ case SC_RIDING: calc_flag = 1; @@ -4361,21 +4355,6 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) } break; - case SC_WATERBALL: /* ウォ?タ?ボ?ル */ - { - struct block_list *target=map_id2bl(sc_data[type].val2); - if (!target || !target->prev) - break; // target has been killed in previous hits, no need to raise an alarm ^^; - // nullpo_retb(target); - // nullpo_retb(target->prev); - skill_attack(BF_MAGIC,bl,bl,target,WZ_WATERBALL,sc_data[type].val1,tick,0); - if((--sc_data[type].val3)>0) { - sc_data[type].timer=add_timer( 150+tick,status_change_timer, bl->id, data ); - return 0; - } - } - break; - case SC_ENDURE: /* インデュア */ case SC_AUTOBERSERK: // Celest if(sd && sd->special_state.infinite_endure) { diff --git a/src/map/status.h b/src/map/status.h index d788c7b50..fbeee7300 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -111,7 +111,7 @@ enum { // struct map_session_data の status_changeの番?テ?ブル //-- 137-139 SC_SAFETYWALL = 140, SC_PNEUMA = 141, - SC_WATERBALL = 142, +//-- 142 SC_ANKLE = 143, SC_DANCING = 144, SC_KEEPING = 145, diff --git a/src/txt-converter/char/Makefile b/src/txt-converter/char/Makefile index a4cca87fd..6b85a04db 100644 --- a/src/txt-converter/char/Makefile +++ b/src/txt-converter/char/Makefile @@ -1,7 +1,7 @@ all: char-converter sql: char-converter -COMMON_OBJ = ../../common/core.o ../../common/socket.o ../../common/timer.o ../../common/grfio.o ../../common/db.o ../../common/lock.o ../../common/nullpo.o ../../common/malloc.o ../../common/showmsg.o ../../common/strlib.o +COMMON_OBJ = ../../common/obj/core.o ../../common/obj/socket.o ../../common/obj/timer.o ../../common/obj/grfio.o ../../common/obj/db.o ../../common/obj/lock.o ../../common/obj/nullpo.o ../../common/obj/malloc.o ../../common/obj/showmsg.o ../../common/obj/strlib.o char-converter: char-converter.o $(COMMON_OBJ) $(CC) -o ../../../$@ $^ $(LIB_S) diff --git a/src/txt-converter/login/Makefile b/src/txt-converter/login/Makefile index 56b97e772..7158931d0 100644 --- a/src/txt-converter/login/Makefile +++ b/src/txt-converter/login/Makefile @@ -1,7 +1,7 @@ all: login-converter sql: login-converter -COMMON_OBJ = ../../common/core.o ../../common/socket.o ../../common/timer.o ../../common/grfio.o ../../common/db.o ../../common/lock.o ../../common/nullpo.o ../../common/malloc.o ../../common/showmsg.o ../../common/strlib.o +COMMON_OBJ = ../../common/obj/core.o ../../common/obj/socket.o ../../common/obj/timer.o ../../common/obj/grfio.o ../../common/obj/db.o ../../common/obj/lock.o ../../common/obj/nullpo.o ../../common/obj/malloc.o ../../common/obj/showmsg.o ../../common/obj/strlib.o COMMON_H = ../../common/core.h ../../common/socket.h ../../common/timer.h ../../common/mmo.h ../../common/version.h ../../common/db.h ../../common/malloc.h ../../common/strlib.h |