map.c 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208
  1. // $Id: map.c,v 1.6 2004/09/25 17:37:01 MouseJstr Exp $
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdarg.h>
  6. #ifdef _WIN32
  7. #include <winsock.h>
  8. #else
  9. #include <netdb.h>
  10. #endif
  11. #include "core.h"
  12. #include "timer.h"
  13. #include "db.h"
  14. #include "grfio.h"
  15. #include "malloc.h"
  16. #include "map.h"
  17. #include "chrif.h"
  18. #include "clif.h"
  19. #include "intif.h"
  20. #include "npc.h"
  21. #include "pc.h"
  22. #include "mob.h"
  23. #include "chat.h"
  24. #include "itemdb.h"
  25. #include "storage.h"
  26. #include "skill.h"
  27. #include "trade.h"
  28. #include "party.h"
  29. #include "battle.h"
  30. #include "script.h"
  31. #include "guild.h"
  32. #include "pet.h"
  33. #include "atcommand.h"
  34. #include "nullpo.h"
  35. #include "socket.h"
  36. #include "log.h"
  37. #ifdef MEMWATCH
  38. #include "memwatch.h"
  39. #endif
  40. unsigned long ticks = 0; // by MC Cameri
  41. #ifndef TXT_ONLY
  42. #include "mail.h" // mail system [Valaris]
  43. MYSQL mmysql_handle;
  44. MYSQL_RES* sql_res ;
  45. MYSQL_ROW sql_row ;
  46. char tmp_sql[65535]="";
  47. MYSQL lmysql_handle;
  48. MYSQL_RES* lsql_res ;
  49. MYSQL_ROW lsql_row ;
  50. char tmp_lsql[65535]="";
  51. MYSQL mail_handle; // mail system [Valaris]
  52. MYSQL_RES* mail_res ;
  53. MYSQL_ROW mail_row ;
  54. char tmp_msql[65535]="";
  55. int map_server_port = 3306;
  56. char map_server_ip[16] = "127.0.0.1";
  57. char map_server_id[32] = "ragnarok";
  58. char map_server_pw[32] = "ragnarok";
  59. char map_server_db[32] = "ragnarok";
  60. int db_use_sqldbs = 0;
  61. int login_server_port = 3306;
  62. char login_server_ip[16] = "127.0.0.1";
  63. char login_server_id[32] = "ragnarok";
  64. char login_server_pw[32] = "ragnarok";
  65. char login_server_db[32] = "ragnarok";
  66. char item_db_db[32] = "item_db";
  67. char mob_db_db[32] = "mob_db";
  68. char login_db[32] = "login";
  69. char login_db_level[32] = "level";
  70. char login_db_account_id[32] = "account_id";
  71. char log_db[32] = "log";
  72. char log_db_ip[16] = "127.0.0.1";
  73. char log_db_id[32] = "ragnarok";
  74. char log_db_pw[32] = "ragnarok";
  75. int log_db_port = 3306;
  76. char gm_db[32] = "login";
  77. char gm_db_level[32] = "level";
  78. char gm_db_account_id[32] = "account_id";
  79. int lowest_gm_level = 1;
  80. int read_gm_interval = 600000;
  81. char char_db[32] = "char";
  82. static int online_timer(int,unsigned int,int,int);
  83. int CHECK_INTERVAL = 3600000; // [Valaris]
  84. int check_online_timer=0; // [Valaris]
  85. #endif /* not TXT_ONLY */
  86. // 極力 staticでローカルに収める
  87. static struct dbt * id_db=NULL;
  88. static struct dbt * map_db=NULL;
  89. static struct dbt * nick_db=NULL;
  90. static struct dbt * charid_db=NULL;
  91. static int users=0;
  92. static struct block_list *object[MAX_FLOORITEM];
  93. static int first_free_object_id=0,last_object_id=0;
  94. #define block_free_max 1048576
  95. static void *block_free[block_free_max];
  96. static int block_free_count = 0, block_free_lock = 0;
  97. #define BL_LIST_MAX 1048576
  98. static struct block_list *bl_list[BL_LIST_MAX];
  99. static int bl_list_count = 0;
  100. struct map_data map[MAX_MAP_PER_SERVER];
  101. int map_num = 0;
  102. int map_port=0;
  103. int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
  104. int agit_flag = 0;
  105. int night_flag = 0; // 0=day, 1=night [Yor]
  106. //Added for Mugendai's I'm Alive mod
  107. int imalive_on=0;
  108. int imalive_time=60;
  109. //Added by Mugendai for GUI
  110. int flush_on=1;
  111. int flush_time=100;
  112. struct charid2nick {
  113. char nick[24];
  114. int req_id;
  115. };
  116. char motd_txt[256] = "conf/motd.txt";
  117. char help_txt[256] = "conf/help.txt";
  118. char wisp_server_name[24] = "Server"; // can be modified in char-server configuration file
  119. int console = 0;
  120. /*==========================================
  121. * 全map鯖総計での接続数設定
  122. * (char鯖から送られてくる)
  123. *------------------------------------------
  124. */
  125. void map_setusers(int n) {
  126. users = n;
  127. }
  128. /*==========================================
  129. * 全map鯖総計での接続数取得 (/wへの応答用)
  130. *------------------------------------------
  131. */
  132. int map_getusers(void) {
  133. return users;
  134. }
  135. //
  136. // block削除の安全性確保処理
  137. //
  138. /*==========================================
  139. * blockをfreeするときfreeの変わりに呼ぶ
  140. * ロックされているときはバッファにためる
  141. *------------------------------------------
  142. */
  143. int map_freeblock( void *bl )
  144. {
  145. if(block_free_lock==0){
  146. free(bl);
  147. bl = NULL;
  148. }
  149. else{
  150. if( block_free_count>=block_free_max ) {
  151. if(battle_config.error_log)
  152. printf("map_freeblock: *WARNING* too many free block! %d %d\n",
  153. block_free_count,block_free_lock);
  154. }
  155. else
  156. block_free[block_free_count++]=bl;
  157. }
  158. return block_free_lock;
  159. }
  160. /*==========================================
  161. * blockのfreeを一時的に禁止する
  162. *------------------------------------------
  163. */
  164. int map_freeblock_lock(void) {
  165. return ++block_free_lock;
  166. }
  167. /*==========================================
  168. * blockのfreeのロックを解除する
  169. * このとき、ロックが完全になくなると
  170. * バッファにたまっていたblockを全部削除
  171. *------------------------------------------
  172. */
  173. int map_freeblock_unlock(void) {
  174. if ((--block_free_lock) == 0) {
  175. int i;
  176. // if(block_free_count>0) {
  177. // if(battle_config.error_log)
  178. // printf("map_freeblock_unlock: free %d object\n",block_free_count);
  179. // }
  180. for(i=0;i<block_free_count;i++){
  181. free(block_free[i]);
  182. block_free[i] = NULL;
  183. }
  184. block_free_count=0;
  185. }else if(block_free_lock<0){
  186. if(battle_config.error_log)
  187. printf("map_freeblock_unlock: lock count < 0 !\n");
  188. }
  189. return block_free_lock;
  190. }
  191. //
  192. // block化処理
  193. //
  194. /*==========================================
  195. * map[]のblock_listから繋がっている場合に
  196. * bl->prevにbl_headのアドレスを入れておく
  197. *------------------------------------------
  198. */
  199. static struct block_list bl_head;
  200. /*==========================================
  201. * map[]のblock_listに追加
  202. * mobは数が多いので別リスト
  203. *
  204. * 既にlink済みかの確認が無い。危険かも
  205. *------------------------------------------
  206. */
  207. int map_addblock(struct block_list *bl)
  208. {
  209. int m,x,y;
  210. nullpo_retr(0, bl);
  211. if(bl->prev != NULL){
  212. if(battle_config.error_log)
  213. printf("map_addblock error : bl->prev!=NULL\n");
  214. return 0;
  215. }
  216. m=bl->m;
  217. x=bl->x;
  218. y=bl->y;
  219. if(m<0 || m>=map_num ||
  220. x<0 || x>=map[m].xs ||
  221. y<0 || y>=map[m].ys)
  222. return 1;
  223. if(bl->type==BL_MOB){
  224. bl->next = map[m].block_mob[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs];
  225. bl->prev = &bl_head;
  226. if(bl->next) bl->next->prev = bl;
  227. map[m].block_mob[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs] = bl;
  228. map[m].block_mob_count[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs]++;
  229. } else {
  230. bl->next = map[m].block[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs];
  231. bl->prev = &bl_head;
  232. if(bl->next) bl->next->prev = bl;
  233. map[m].block[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs] = bl;
  234. map[m].block_count[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs]++;
  235. if(bl->type==BL_PC)
  236. map[m].users++;
  237. }
  238. return 0;
  239. }
  240. /*==========================================
  241. * map[]のblock_listから外す
  242. * prevがNULLの場合listに繋がってない
  243. *------------------------------------------
  244. */
  245. int map_delblock(struct block_list *bl)
  246. {
  247. int b;
  248. nullpo_retr(0, bl);
  249. // 既にblocklistから抜けている
  250. if(bl->prev==NULL){
  251. if(bl->next!=NULL){
  252. // prevがNULLでnextがNULLでないのは有ってはならない
  253. if(battle_config.error_log)
  254. printf("map_delblock error : bl->next!=NULL\n");
  255. }
  256. return 0;
  257. }
  258. b = bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs;
  259. if(bl->type==BL_PC)
  260. map[bl->m].users--;
  261. if(bl->next) bl->next->prev = bl->prev;
  262. if(bl->prev==&bl_head){
  263. // リストの頭なので、map[]のblock_listを更新する
  264. if(bl->type==BL_MOB){
  265. map[bl->m].block_mob[b] = bl->next;
  266. if((map[bl->m].block_mob_count[b]--) < 0)
  267. map[bl->m].block_mob_count[b] = 0;
  268. } else {
  269. map[bl->m].block[b] = bl->next;
  270. if((map[bl->m].block_count[b]--) < 0)
  271. map[bl->m].block_count[b] = 0;
  272. }
  273. } else {
  274. bl->prev->next = bl->next;
  275. }
  276. bl->next = NULL;
  277. bl->prev = NULL;
  278. return 0;
  279. }
  280. /*==========================================
  281. * 周囲のPC人数を数える (現在未使用)
  282. *------------------------------------------
  283. */
  284. int map_countnearpc(int m, int x, int y) {
  285. int bx,by,c=0;
  286. struct block_list *bl=NULL;
  287. if(map[m].users==0)
  288. return 0;
  289. for(by=y/BLOCK_SIZE-AREA_SIZE/BLOCK_SIZE-1;by<=y/BLOCK_SIZE+AREA_SIZE/BLOCK_SIZE+1;by++){
  290. if(by<0 || by>=map[m].bys)
  291. continue;
  292. for(bx=x/BLOCK_SIZE-AREA_SIZE/BLOCK_SIZE-1;bx<=x/BLOCK_SIZE+AREA_SIZE/BLOCK_SIZE+1;bx++){
  293. if(bx<0 || bx>=map[m].bxs)
  294. continue;
  295. bl = map[m].block[bx+by*map[m].bxs];
  296. for(;bl;bl=bl->next){
  297. if(bl->type==BL_PC)
  298. c++;
  299. }
  300. }
  301. }
  302. return c;
  303. }
  304. /*==========================================
  305. * セル上のPCとMOBの数を数える (グランドクロス用)
  306. *------------------------------------------
  307. */
  308. int map_count_oncell(int m, int x, int y) {
  309. int bx,by;
  310. struct block_list *bl=NULL;
  311. int i,c;
  312. int count = 0;
  313. if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys))
  314. return 1;
  315. bx = x/BLOCK_SIZE;
  316. by = y/BLOCK_SIZE;
  317. bl = map[m].block[bx+by*map[m].bxs];
  318. c = map[m].block_count[bx+by*map[m].bxs];
  319. for(i=0;i<c && bl;i++,bl=bl->next){
  320. if(bl->x == x && bl->y == y && bl->type == BL_PC) count++;
  321. }
  322. bl = map[m].block_mob[bx+by*map[m].bxs];
  323. c = map[m].block_mob_count[bx+by*map[m].bxs];
  324. for(i=0;i<c && bl;i++,bl=bl->next){
  325. if(bl->x == x && bl->y == y) count++;
  326. }
  327. if(!count) count = 1;
  328. return count;
  329. }
  330. /*==========================================
  331. * map m (x0,y0)-(x1,y1)内の全objに対して
  332. * funcを呼ぶ
  333. * type!=0 ならその種類のみ
  334. *------------------------------------------
  335. */
  336. void map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int type,...) {
  337. int bx,by;
  338. struct block_list *bl=NULL;
  339. va_list ap=NULL;
  340. int blockcount=bl_list_count,i,c;
  341. if(m < 0)
  342. return;
  343. va_start(ap,type);
  344. if (x0 < 0) x0 = 0;
  345. if (y0 < 0) y0 = 0;
  346. if (x1 >= map[m].xs) x1 = map[m].xs-1;
  347. if (y1 >= map[m].ys) y1 = map[m].ys-1;
  348. if (type == 0 || type != BL_MOB)
  349. for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) {
  350. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  351. bl = map[m].block[bx+by*map[m].bxs];
  352. c = map[m].block_count[bx+by*map[m].bxs];
  353. for(i=0;i<c && bl;i++,bl=bl->next){
  354. if(bl && type && bl->type!=type)
  355. continue;
  356. if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
  357. bl_list[bl_list_count++]=bl;
  358. }
  359. }
  360. }
  361. if(type==0 || type==BL_MOB)
  362. for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
  363. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  364. bl = map[m].block_mob[bx+by*map[m].bxs];
  365. c = map[m].block_mob_count[bx+by*map[m].bxs];
  366. for(i=0;i<c && bl;i++,bl=bl->next){
  367. if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
  368. bl_list[bl_list_count++]=bl;
  369. }
  370. }
  371. }
  372. if(bl_list_count>=BL_LIST_MAX) {
  373. if(battle_config.error_log)
  374. printf("map_foreachinarea: *WARNING* block count too many!\n");
  375. }
  376. map_freeblock_lock(); // メモリからの解放を禁止する
  377. for(i=blockcount;i<bl_list_count;i++)
  378. if(bl_list[i]->prev) // 有効かどうかチェック
  379. func(bl_list[i],ap);
  380. map_freeblock_unlock(); // 解放を許可する
  381. va_end(ap);
  382. bl_list_count = blockcount;
  383. }
  384. /*==========================================
  385. * 矩形(x0,y0)-(x1,y1)が(dx,dy)移動した時の
  386. * 領域外になる領域(矩形かL字形)内のobjに
  387. * 対してfuncを呼ぶ
  388. *
  389. * dx,dyは-1,0,1のみとする(どんな値でもいいっぽい?)
  390. *------------------------------------------
  391. */
  392. void map_foreachinmovearea(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int dx,int dy,int type,...) {
  393. int bx,by;
  394. struct block_list *bl=NULL;
  395. va_list ap=NULL;
  396. int blockcount=bl_list_count,i,c;
  397. va_start(ap,type);
  398. if(dx==0 || dy==0){
  399. // 矩形領域の場合
  400. if(dx==0){
  401. if(dy<0){
  402. y0=y1+dy+1;
  403. } else {
  404. y1=y0+dy-1;
  405. }
  406. } else if(dy==0){
  407. if(dx<0){
  408. x0=x1+dx+1;
  409. } else {
  410. x1=x0+dx-1;
  411. }
  412. }
  413. if(x0<0) x0=0;
  414. if(y0<0) y0=0;
  415. if(x1>=map[m].xs) x1=map[m].xs-1;
  416. if(y1>=map[m].ys) y1=map[m].ys-1;
  417. for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
  418. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  419. bl = map[m].block[bx+by*map[m].bxs];
  420. c = map[m].block_count[bx+by*map[m].bxs];
  421. for(i=0;i<c && bl;i++,bl=bl->next){
  422. if(bl && type && bl->type!=type)
  423. continue;
  424. if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
  425. bl_list[bl_list_count++]=bl;
  426. }
  427. bl = map[m].block_mob[bx+by*map[m].bxs];
  428. c = map[m].block_mob_count[bx+by*map[m].bxs];
  429. for(i=0;i<c && bl;i++,bl=bl->next){
  430. if(bl && type && bl->type!=type)
  431. continue;
  432. if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
  433. bl_list[bl_list_count++]=bl;
  434. }
  435. }
  436. }
  437. }else{
  438. // L字領域の場合
  439. if(x0<0) x0=0;
  440. if(y0<0) y0=0;
  441. if(x1>=map[m].xs) x1=map[m].xs-1;
  442. if(y1>=map[m].ys) y1=map[m].ys-1;
  443. for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
  444. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  445. bl = map[m].block[bx+by*map[m].bxs];
  446. c = map[m].block_count[bx+by*map[m].bxs];
  447. for(i=0;i<c && bl;i++,bl=bl->next){
  448. if(bl && type && bl->type!=type)
  449. continue;
  450. if((bl) && !(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1))
  451. continue;
  452. if((bl) && ((dx>0 && bl->x<x0+dx) || (dx<0 && bl->x>x1+dx) ||
  453. (dy>0 && bl->y<y0+dy) || (dy<0 && bl->y>y1+dy)) &&
  454. bl_list_count<BL_LIST_MAX)
  455. bl_list[bl_list_count++]=bl;
  456. }
  457. bl = map[m].block_mob[bx+by*map[m].bxs];
  458. c = map[m].block_mob_count[bx+by*map[m].bxs];
  459. for(i=0;i<c && bl;i++,bl=bl->next){
  460. if(bl && type && bl->type!=type)
  461. continue;
  462. if((bl) && !(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1))
  463. continue;
  464. if((bl) && ((dx>0 && bl->x<x0+dx) || (dx<0 && bl->x>x1+dx) ||
  465. (dy>0 && bl->y<y0+dy) || (dy<0 && bl->y>y1+dy)) &&
  466. bl_list_count<BL_LIST_MAX)
  467. bl_list[bl_list_count++]=bl;
  468. }
  469. }
  470. }
  471. }
  472. if(bl_list_count>=BL_LIST_MAX) {
  473. if(battle_config.error_log)
  474. printf("map_foreachinarea: *WARNING* block count too many!\n");
  475. }
  476. map_freeblock_lock(); // メモリからの解放を禁止する
  477. for(i=blockcount;i<bl_list_count;i++)
  478. if(bl_list[i]->prev) // 有効かどうかチェック
  479. func(bl_list[i],ap);
  480. map_freeblock_unlock(); // 解放を許可する
  481. va_end(ap);
  482. bl_list_count = blockcount;
  483. }
  484. // -- moonsoul (added map_foreachincell which is a rework of map_foreachinarea but
  485. // which only checks the exact single x/y passed to it rather than an
  486. // area radius - may be more useful in some instances)
  487. //
  488. void map_foreachincell(int (*func)(struct block_list*,va_list),int m,int x,int y,int type,...) {
  489. int bx,by;
  490. struct block_list *bl=NULL;
  491. va_list ap=NULL;
  492. int blockcount=bl_list_count,i,c;
  493. va_start(ap,type);
  494. by=y/BLOCK_SIZE;
  495. bx=x/BLOCK_SIZE;
  496. if(type==0 || type!=BL_MOB)
  497. {
  498. bl = map[m].block[bx+by*map[m].bxs];
  499. c = map[m].block_count[bx+by*map[m].bxs];
  500. for(i=0;i<c && bl;i++,bl=bl->next)
  501. {
  502. if(type && bl && bl->type!=type)
  503. continue;
  504. if(bl && bl->x==x && bl->y==y && bl_list_count<BL_LIST_MAX)
  505. bl_list[bl_list_count++]=bl;
  506. }
  507. }
  508. if(type==0 || type==BL_MOB)
  509. {
  510. bl = map[m].block_mob[bx+by*map[m].bxs];
  511. c = map[m].block_mob_count[bx+by*map[m].bxs];
  512. for(i=0;i<c && bl;i++,bl=bl->next)
  513. {
  514. if(bl && bl->x==x && bl->y==y && bl_list_count<BL_LIST_MAX)
  515. bl_list[bl_list_count++]=bl;
  516. }
  517. }
  518. if(bl_list_count>=BL_LIST_MAX) {
  519. if(battle_config.error_log)
  520. printf("map_foreachincell: *WARNING* block count too many!\n");
  521. }
  522. map_freeblock_lock(); // メモリからの解放を禁止する
  523. for(i=blockcount;i<bl_list_count;i++)
  524. if(bl_list[i]->prev) // 有効かどうかチェック
  525. func(bl_list[i],ap);
  526. map_freeblock_unlock(); // 解放を許可する
  527. va_end(ap);
  528. bl_list_count = blockcount;
  529. }
  530. /*==========================================
  531. * 床アイテムやエフェクト用の一時obj割り当て
  532. * object[]への保存とid_db登録まで
  533. *
  534. * bl->idもこの中で設定して問題無い?
  535. *------------------------------------------
  536. */
  537. int map_addobject(struct block_list *bl) {
  538. int i;
  539. if( bl == NULL ){
  540. printf("map_addobject nullpo?\n");
  541. return 0;
  542. }
  543. if(first_free_object_id<2 || first_free_object_id>=MAX_FLOORITEM)
  544. first_free_object_id=2;
  545. for(i=first_free_object_id;i<MAX_FLOORITEM;i++)
  546. if(object[i]==NULL)
  547. break;
  548. if(i>=MAX_FLOORITEM){
  549. if(battle_config.error_log)
  550. printf("no free object id\n");
  551. return 0;
  552. }
  553. first_free_object_id=i;
  554. if(last_object_id<i)
  555. last_object_id=i;
  556. object[i]=bl;
  557. numdb_insert(id_db,i,bl);
  558. return i;
  559. }
  560. /*==========================================
  561. * 一時objectの解放
  562. * map_delobjectのfreeしないバージョン
  563. *------------------------------------------
  564. */
  565. int map_delobjectnofree(int id) {
  566. if(object[id]==NULL)
  567. return 0;
  568. map_delblock(object[id]);
  569. numdb_erase(id_db,id);
  570. // map_freeblock(object[id]);
  571. object[id]=NULL;
  572. if(first_free_object_id>id)
  573. first_free_object_id=id;
  574. while(last_object_id>2 && object[last_object_id]==NULL)
  575. last_object_id--;
  576. return 0;
  577. }
  578. /*==========================================
  579. * 一時objectの解放
  580. * block_listからの削除、id_dbからの削除
  581. * object dataのfree、object[]へのNULL代入
  582. *
  583. * addとの対称性が無いのが気になる
  584. *------------------------------------------
  585. */
  586. int map_delobject(int id) {
  587. struct block_list *obj = object[id];
  588. if(obj==NULL)
  589. return 0;
  590. map_delobjectnofree(id);
  591. map_freeblock(obj);
  592. return 0;
  593. }
  594. /*==========================================
  595. * 全一時obj相手にfuncを呼ぶ
  596. *
  597. *------------------------------------------
  598. */
  599. void map_foreachobject(int (*func)(struct block_list*,va_list),int type,...) {
  600. int i;
  601. int blockcount=bl_list_count;
  602. va_list ap=NULL;
  603. va_start(ap,type);
  604. for(i=2;i<=last_object_id;i++){
  605. if(object[i]){
  606. if(type && object[i]->type!=type)
  607. continue;
  608. if(bl_list_count>=BL_LIST_MAX) {
  609. if(battle_config.error_log)
  610. printf("map_foreachobject: too many block !\n");
  611. }
  612. else
  613. bl_list[bl_list_count++]=object[i];
  614. }
  615. }
  616. map_freeblock_lock();
  617. for(i=blockcount;i<bl_list_count;i++)
  618. if( bl_list[i]->prev || bl_list[i]->next )
  619. func(bl_list[i],ap);
  620. map_freeblock_unlock();
  621. va_end(ap);
  622. bl_list_count = blockcount;
  623. }
  624. /*==========================================
  625. * 床アイテムを消す
  626. *
  627. * data==0の時はtimerで消えた時
  628. * data!=0の時は拾う等で消えた時として動作
  629. *
  630. * 後者は、map_clearflooritem(id)へ
  631. * map.h内で#defineしてある
  632. *------------------------------------------
  633. */
  634. int map_clearflooritem_timer(int tid,unsigned int tick,int id,int data) {
  635. struct flooritem_data *fitem=NULL;
  636. fitem = (struct flooritem_data *)object[id];
  637. if(fitem==NULL || fitem->bl.type!=BL_ITEM || (!data && fitem->cleartimer != tid)){
  638. if(battle_config.error_log)
  639. printf("map_clearflooritem_timer : error\n");
  640. return 1;
  641. }
  642. if(data)
  643. delete_timer(fitem->cleartimer,map_clearflooritem_timer);
  644. else if(fitem->item_data.card[0] == (short)0xff00)
  645. intif_delete_petdata(*((long *)(&fitem->item_data.card[1])));
  646. clif_clearflooritem(fitem,0);
  647. map_delobject(fitem->bl.id);
  648. return 0;
  649. }
  650. /*==========================================
  651. * (m,x,y)の周囲rangeマス内の空き(=侵入可能)cellの
  652. * 内から適当なマス目の座標をx+(y<<16)で返す
  653. *
  654. * 現状range=1でアイテムドロップ用途のみ
  655. *------------------------------------------
  656. */
  657. int map_searchrandfreecell(int m,int x,int y,int range) {
  658. int free_cell,i,j,c;
  659. for(free_cell=0,i=-range;i<=range;i++){
  660. if(i+y<0 || i+y>=map[m].ys)
  661. continue;
  662. for(j=-range;j<=range;j++){
  663. if(j+x<0 || j+x>=map[m].xs)
  664. continue;
  665. if((c=read_gat(m,j+x,i+y))==1 || c==5)
  666. continue;
  667. free_cell++;
  668. }
  669. }
  670. if(free_cell==0)
  671. return -1;
  672. free_cell=rand()%free_cell;
  673. for(i=-range;i<=range;i++){
  674. if(i+y<0 || i+y>=map[m].ys)
  675. continue;
  676. for(j=-range;j<=range;j++){
  677. if(j+x<0 || j+x>=map[m].xs)
  678. continue;
  679. if((c=read_gat(m,j+x,i+y))==1 || c==5)
  680. continue;
  681. if(free_cell==0){
  682. x+=j;
  683. y+=i;
  684. i=range+1;
  685. break;
  686. }
  687. free_cell--;
  688. }
  689. }
  690. return x+(y<<16);
  691. }
  692. /*==========================================
  693. * (m,x,y)を中心に3x3以内に床アイテム設置
  694. *
  695. * item_dataはamount以外をcopyする
  696. *------------------------------------------
  697. */
  698. int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,struct map_session_data *first_sd,
  699. struct map_session_data *second_sd,struct map_session_data *third_sd,int type) {
  700. int xy,r;
  701. unsigned int tick;
  702. struct flooritem_data *fitem=NULL;
  703. nullpo_retr(0, item_data);
  704. if((xy=map_searchrandfreecell(m,x,y,1))<0)
  705. return 0;
  706. r=rand();
  707. fitem = (struct flooritem_data *)aCalloc(1,sizeof(*fitem));
  708. fitem->bl.type=BL_ITEM;
  709. fitem->bl.prev = fitem->bl.next = NULL;
  710. fitem->bl.m=m;
  711. fitem->bl.x=xy&0xffff;
  712. fitem->bl.y=(xy>>16)&0xffff;
  713. fitem->first_get_id = 0;
  714. fitem->first_get_tick = 0;
  715. fitem->second_get_id = 0;
  716. fitem->second_get_tick = 0;
  717. fitem->third_get_id = 0;
  718. fitem->third_get_tick = 0;
  719. fitem->bl.id = map_addobject(&fitem->bl);
  720. if(fitem->bl.id==0){
  721. free(fitem);
  722. return 0;
  723. }
  724. tick = gettick();
  725. if(first_sd) {
  726. fitem->first_get_id = first_sd->bl.id;
  727. if(type)
  728. fitem->first_get_tick = tick + battle_config.mvp_item_first_get_time;
  729. else
  730. fitem->first_get_tick = tick + battle_config.item_first_get_time;
  731. }
  732. if(second_sd) {
  733. fitem->second_get_id = second_sd->bl.id;
  734. if(type)
  735. fitem->second_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time;
  736. else
  737. fitem->second_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time;
  738. }
  739. if(third_sd) {
  740. fitem->third_get_id = third_sd->bl.id;
  741. if(type)
  742. fitem->third_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time + battle_config.mvp_item_third_get_time;
  743. else
  744. fitem->third_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time + battle_config.item_third_get_time;
  745. }
  746. memcpy(&fitem->item_data,item_data,sizeof(*item_data));
  747. fitem->item_data.amount=amount;
  748. fitem->subx=(r&3)*3+3;
  749. fitem->suby=((r>>2)&3)*3+3;
  750. fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0);
  751. map_addblock(&fitem->bl);
  752. clif_dropflooritem(fitem);
  753. return fitem->bl.id;
  754. }
  755. /*==========================================
  756. * charid_dbへ追加(返信待ちがあれば返信)
  757. *------------------------------------------
  758. */
  759. void map_addchariddb(int charid, char *name) {
  760. struct charid2nick *p=NULL;
  761. int req=0;
  762. p=numdb_search(charid_db,charid);
  763. if(p==NULL){ // データベースにない
  764. p = (struct charid2nick *)aCalloc(1,sizeof(struct charid2nick));
  765. p->req_id=0;
  766. }else
  767. numdb_erase(charid_db,charid);
  768. req=p->req_id;
  769. memcpy(p->nick,name,24);
  770. p->req_id=0;
  771. numdb_insert(charid_db,charid,p);
  772. if(req){ // 返信待ちがあれば返信
  773. struct map_session_data *sd = map_id2sd(req);
  774. if(sd!=NULL)
  775. clif_solved_charname(sd,charid);
  776. }
  777. }
  778. /*==========================================
  779. * charid_dbへ追加(返信要求のみ)
  780. *------------------------------------------
  781. */
  782. int map_reqchariddb(struct map_session_data * sd,int charid) {
  783. struct charid2nick *p=NULL;
  784. nullpo_retr(0, sd);
  785. p=numdb_search(charid_db,charid);
  786. if(p!=NULL) // データベースにすでにある
  787. return 0;
  788. p = (struct charid2nick *)aCalloc(1,sizeof(struct charid2nick));
  789. p->req_id=sd->bl.id;
  790. numdb_insert(charid_db,charid,p);
  791. return 0;
  792. }
  793. /*==========================================
  794. * id_dbへblを追加
  795. *------------------------------------------
  796. */
  797. void map_addiddb(struct block_list *bl) {
  798. nullpo_retv(bl);
  799. numdb_insert(id_db,bl->id,bl);
  800. }
  801. /*==========================================
  802. * id_dbからblを削除
  803. *------------------------------------------
  804. */
  805. void map_deliddb(struct block_list *bl) {
  806. nullpo_retv(bl);
  807. numdb_erase(id_db,bl->id);
  808. }
  809. /*==========================================
  810. * nick_dbへsdを追加
  811. *------------------------------------------
  812. */
  813. void map_addnickdb(struct map_session_data *sd) {
  814. nullpo_retv(sd);
  815. strdb_insert(nick_db,sd->status.name,sd);
  816. }
  817. /*==========================================
  818. * PCのquit処理 map.c内分
  819. *
  820. * quit処理の主体が違うような気もしてきた
  821. *------------------------------------------
  822. */
  823. int map_quit(struct map_session_data *sd) {
  824. int i;
  825. nullpo_retr(0, sd);
  826. if(sd->chatID) // チャットから出る
  827. chat_leavechat(sd);
  828. if(sd->trade_partner) // 取引を中断する
  829. trade_tradecancel(sd);
  830. if(sd->party_invite>0) // パーティ勧誘を拒否する
  831. party_reply_invite(sd,sd->party_invite_account,0);
  832. if(sd->guild_invite>0) // ギルド勧誘を拒否する
  833. guild_reply_invite(sd,sd->guild_invite,0);
  834. if(sd->guild_alliance>0) // ギルド同盟勧誘を拒否する
  835. guild_reply_reqalliance(sd,sd->guild_alliance_account,0);
  836. party_send_logout(sd); // パーティのログアウトメッセージ送信
  837. guild_send_memberinfoshort(sd,0); // ギルドのログアウトメッセージ送信
  838. pc_cleareventtimer(sd); // イベントタイマを破棄する
  839. if(sd->state.storage_flag)
  840. storage_guild_storage_quit(sd,0);
  841. else
  842. storage_storage_quit(sd); // 倉庫を開いてるなら保存する
  843. skill_castcancel(&sd->bl,0); // 詠唱を中断する
  844. skill_stop_dancing(&sd->bl,1);// ダンス/演奏中断
  845. if(sd->sc_data && sd->sc_data[SC_BERSERK].timer!=-1) //バーサーク中の終了はHPを100に
  846. sd->status.hp = 100;
  847. skill_status_change_clear(&sd->bl,1); // ステータス異常を解除する
  848. skill_clear_unitgroup(&sd->bl); // スキルユニットグループの削除
  849. skill_cleartimerskill(&sd->bl);
  850. pc_stop_walking(sd,0);
  851. pc_stopattack(sd);
  852. pc_delinvincibletimer(sd);
  853. pc_delspiritball(sd,sd->spiritball,1);
  854. skill_gangsterparadise(sd,0);
  855. pc_calcstatus(sd,4);
  856. clif_clearchar_area(&sd->bl,2);
  857. if(sd->status.pet_id && sd->pd) {
  858. pet_lootitem_drop(sd->pd,sd);
  859. pet_remove_map(sd);
  860. if(sd->pet.intimate <= 0) {
  861. intif_delete_petdata(sd->status.pet_id);
  862. sd->status.pet_id = 0;
  863. sd->pd = NULL;
  864. sd->petDB = NULL;
  865. }
  866. else
  867. intif_save_petdata(sd->status.account_id,&sd->pet);
  868. }
  869. if(pc_isdead(sd))
  870. pc_setrestartvalue(sd,2);
  871. pc_makesavestatus(sd);
  872. //クローンスキルで覚えたスキルは消す
  873. for(i=0;i<MAX_SKILL;i++){
  874. if(sd->status.skill[i].flag == 13){
  875. sd->status.skill[i].id=0;
  876. sd->status.skill[i].lv=0;
  877. sd->status.skill[i].flag=0;
  878. }
  879. }
  880. chrif_save(sd);
  881. storage_storage_save(sd);
  882. if( sd->npc_stackbuf && sd->npc_stackbuf != NULL)
  883. free( sd->npc_stackbuf );
  884. map_delblock(&sd->bl);
  885. #ifndef TXT_ONLY
  886. chrif_char_offline(sd);
  887. #endif
  888. numdb_erase(id_db,sd->bl.id);
  889. strdb_erase(nick_db,sd->status.name);
  890. numdb_erase(charid_db,sd->status.char_id);
  891. return 0;
  892. }
  893. /*==========================================
  894. * id番号のPCを探す。居なければNULL
  895. *------------------------------------------
  896. */
  897. struct map_session_data * map_id2sd(int id) {
  898. // remove search from db, because:
  899. // 1 - all players, npc, items and mob are in this db (to search, it's not speed, and search in session is more sure)
  900. // 2 - DB seems not always correct. Sometimes, when a player disconnects, its id (account value) is not removed and structure
  901. // point to a memory area that is not more a session_data and value are incorrect (or out of available memory) -> crash
  902. // replaced by searching in all session.
  903. // by searching in session, we are sure that fd, session, and account exist.
  904. /*
  905. struct block_list *bl;
  906. bl=numdb_search(id_db,id);
  907. if(bl && bl->type==BL_PC)
  908. return (struct map_session_data*)bl;
  909. return NULL;
  910. */
  911. int i;
  912. struct map_session_data *sd=NULL;
  913. for(i = 0; i < fd_max; i++)
  914. if (session[i] && (sd = session[i]->session_data) && sd->bl.id == id)
  915. return sd;
  916. return NULL;
  917. }
  918. /*==========================================
  919. * char_id番号の名前を探す
  920. *------------------------------------------
  921. */
  922. char * map_charid2nick(int id) {
  923. struct charid2nick *p=numdb_search(charid_db,id);
  924. if(p==NULL)
  925. return NULL;
  926. if(p->req_id!=0)
  927. return NULL;
  928. return p->nick;
  929. }
  930. /*==========================================
  931. * Search session data from a nick name
  932. * (without sensitive case if necessary)
  933. * return map_session_data pointer or NULL
  934. *------------------------------------------
  935. */
  936. struct map_session_data * map_nick2sd(char *nick) {
  937. int i, quantity=0, nicklen;
  938. struct map_session_data *sd = NULL;
  939. struct map_session_data *pl_sd = NULL;
  940. if (nick == NULL)
  941. return NULL;
  942. nicklen = strlen(nick);
  943. for (i = 0; i < fd_max; i++) {
  944. if (session[i] && (pl_sd = session[i]->session_data) && pl_sd->state.auth)
  945. // Without case sensitive check (increase the number of similar character names found)
  946. if (strnicmp(pl_sd->status.name, nick, nicklen) == 0) {
  947. // Strict comparison (if found, we finish the function immediatly with correct value)
  948. if (strcmp(pl_sd->status.name, nick) == 0)
  949. return pl_sd;
  950. quantity++;
  951. sd = pl_sd;
  952. }
  953. }
  954. // Here, the exact character name is not found
  955. // We return the found index of a similar account ONLY if there is 1 similar character
  956. if (quantity == 1)
  957. return sd;
  958. // Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found
  959. return NULL;
  960. }
  961. /*==========================================
  962. * id番号の物を探す
  963. * 一時objectの場合は配列を引くのみ
  964. *------------------------------------------
  965. */
  966. struct block_list * map_id2bl(int id)
  967. {
  968. struct block_list *bl=NULL;
  969. if(id<sizeof(object)/sizeof(object[0]))
  970. bl = object[id];
  971. else
  972. bl = numdb_search(id_db,id);
  973. return bl;
  974. }
  975. /*==========================================
  976. * id_db内の全てにfuncを実行
  977. *------------------------------------------
  978. */
  979. int map_foreachiddb(int (*func)(void*,void*,va_list),...) {
  980. va_list ap=NULL;
  981. va_start(ap,func);
  982. numdb_foreach(id_db,func,ap);
  983. va_end(ap);
  984. return 0;
  985. }
  986. /*==========================================
  987. * map.npcへ追加 (warp等の領域持ちのみ)
  988. *------------------------------------------
  989. */
  990. int map_addnpc(int m,struct npc_data *nd) {
  991. int i;
  992. if(m<0 || m>=map_num)
  993. return -1;
  994. for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++)
  995. if(map[m].npc[i]==NULL)
  996. break;
  997. if(i==MAX_NPC_PER_MAP){
  998. if(battle_config.error_log)
  999. printf("too many NPCs in one map %s\n",map[m].name);
  1000. return -1;
  1001. }
  1002. if(i==map[m].npc_num){
  1003. map[m].npc_num++;
  1004. }
  1005. nullpo_retr(0, nd);
  1006. map[m].npc[i]=nd;
  1007. nd->n = i;
  1008. numdb_insert(id_db,nd->bl.id,nd);
  1009. return i;
  1010. }
  1011. void map_removenpc(void) {
  1012. int i,m,n=0;
  1013. for(m=0;m<map_num;m++) {
  1014. for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++) {
  1015. if(map[m].npc[i]!=NULL) {
  1016. clif_clearchar_area(&map[m].npc[i]->bl,2);
  1017. map_delblock(&map[m].npc[i]->bl);
  1018. numdb_erase(id_db,map[m].npc[i]->bl.id);
  1019. if(map[m].npc[i]->bl.subtype==SCRIPT) {
  1020. // free(map[m].npc[i]->u.scr.script);
  1021. // free(map[m].npc[i]->u.scr.label_list);
  1022. }
  1023. free(map[m].npc[i]);
  1024. map[m].npc[i] = NULL;
  1025. n++;
  1026. }
  1027. }
  1028. }
  1029. printf("%d NPCs removed.\n",n);
  1030. }
  1031. /*==========================================
  1032. * map名からmap番号へ変換
  1033. *------------------------------------------
  1034. */
  1035. int map_mapname2mapid(char *name) {
  1036. struct map_data *md=NULL;
  1037. md=strdb_search(map_db,name);
  1038. if(md==NULL || md->gat==NULL)
  1039. return -1;
  1040. return md->m;
  1041. }
  1042. /*==========================================
  1043. * 他鯖map名からip,port変換
  1044. *------------------------------------------
  1045. */
  1046. int map_mapname2ipport(char *name,int *ip,int *port) {
  1047. struct map_data_other_server *mdos=NULL;
  1048. mdos=strdb_search(map_db,name);
  1049. if(mdos==NULL || mdos->gat)
  1050. return -1;
  1051. *ip=mdos->ip;
  1052. *port=mdos->port;
  1053. return 0;
  1054. }
  1055. /*==========================================
  1056. *
  1057. *------------------------------------------
  1058. */
  1059. int map_check_dir(int s_dir,int t_dir) {
  1060. if(s_dir == t_dir)
  1061. return 0;
  1062. switch(s_dir) {
  1063. case 0:
  1064. if(t_dir == 7 || t_dir == 1 || t_dir == 0)
  1065. return 0;
  1066. break;
  1067. case 1:
  1068. if(t_dir == 0 || t_dir == 2 || t_dir == 1)
  1069. return 0;
  1070. break;
  1071. case 2:
  1072. if(t_dir == 1 || t_dir == 3 || t_dir == 2)
  1073. return 0;
  1074. break;
  1075. case 3:
  1076. if(t_dir == 2 || t_dir == 4 || t_dir == 3)
  1077. return 0;
  1078. break;
  1079. case 4:
  1080. if(t_dir == 3 || t_dir == 5 || t_dir == 4)
  1081. return 0;
  1082. break;
  1083. case 5:
  1084. if(t_dir == 4 || t_dir == 6 || t_dir == 5)
  1085. return 0;
  1086. break;
  1087. case 6:
  1088. if(t_dir == 5 || t_dir == 7 || t_dir == 6)
  1089. return 0;
  1090. break;
  1091. case 7:
  1092. if(t_dir == 6 || t_dir == 0 || t_dir == 7)
  1093. return 0;
  1094. break;
  1095. }
  1096. return 1;
  1097. }
  1098. /*==========================================
  1099. * 彼我の方向を計算
  1100. *------------------------------------------
  1101. */
  1102. int map_calc_dir( struct block_list *src,int x,int y) {
  1103. int dir=0;
  1104. int dx,dy;
  1105. nullpo_retr(0, src);
  1106. dx=x-src->x;
  1107. dy=y-src->y;
  1108. if( dx==0 && dy==0 ){ // 彼我の場所一致
  1109. dir=0; // 上
  1110. }else if( dx>=0 && dy>=0 ){ // 方向的に右上
  1111. dir=7; // 右上
  1112. if( dx*3-1<dy ) dir=0; // 上
  1113. if( dx>dy*3 ) dir=6; // 右
  1114. }else if( dx>=0 && dy<=0 ){ // 方向的に右下
  1115. dir=5; // 右下
  1116. if( dx*3-1<-dy ) dir=4; // 下
  1117. if( dx>-dy*3 ) dir=6; // 右
  1118. }else if( dx<=0 && dy<=0 ){ // 方向的に左下
  1119. dir=3; // 左下
  1120. if( dx*3+1>dy ) dir=4; // 下
  1121. if( dx<dy*3 ) dir=2; // 左
  1122. }else{ // 方向的に左上
  1123. dir=1; // 左上
  1124. if( -dx*3-1<dy ) dir=0; // 上
  1125. if( -dx>dy*3 ) dir=2; // 左
  1126. }
  1127. return dir;
  1128. }
  1129. // gat系
  1130. /*==========================================
  1131. * (m,x,y)の状態を調べる
  1132. *------------------------------------------
  1133. */
  1134. int map_getcell(int m,int x,int y) {
  1135. if(x<0 || x>=map[m].xs-1 || y<0 || y>=map[m].ys-1)
  1136. return 1;
  1137. return map[m].gat[x+y*map[m].xs];
  1138. }
  1139. /*==========================================
  1140. * (m,x,y)の状態をtにする
  1141. *------------------------------------------
  1142. */
  1143. int map_setcell(int m,int x,int y,int t) {
  1144. if(x<0 || x>=map[m].xs || y<0 || y>=map[m].ys)
  1145. return t;
  1146. return map[m].gat[x+y*map[m].xs]=t;
  1147. }
  1148. /*==========================================
  1149. * 他鯖管理のマップをdbに追加
  1150. *------------------------------------------
  1151. */
  1152. int map_setipport(char *name,unsigned long ip,int port) {
  1153. struct map_data *md=NULL;
  1154. struct map_data_other_server *mdos=NULL;
  1155. md=strdb_search(map_db,name);
  1156. if(md==NULL){ // not exist -> add new data
  1157. mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server));
  1158. memcpy(mdos->name,name,24);
  1159. mdos->gat = NULL;
  1160. mdos->ip = ip;
  1161. mdos->port = port;
  1162. strdb_insert(map_db,mdos->name,mdos);
  1163. } else {
  1164. if(md->gat){ // local -> check data
  1165. if(ip!=clif_getip() || port!=clif_getport()){
  1166. printf("from char server : %s -> %08lx:%d\n",name,ip,port);
  1167. return 1;
  1168. }
  1169. } else { // update
  1170. mdos=(struct map_data_other_server *)md;
  1171. mdos->ip = ip;
  1172. mdos->port = port;
  1173. }
  1174. }
  1175. return 0;
  1176. }
  1177. // 初期化周り
  1178. /*==========================================
  1179. * 水場高さ設定
  1180. *------------------------------------------
  1181. */
  1182. static struct {
  1183. char mapname[24];
  1184. int waterheight;
  1185. } *waterlist=NULL;
  1186. #define NO_WATER 1000000
  1187. static int map_waterheight(char *mapname) {
  1188. if(waterlist){
  1189. int i;
  1190. for(i=0;waterlist[i].mapname[0] && i < MAX_MAP_PER_SERVER;i++)
  1191. if(strcmp(waterlist[i].mapname,mapname)==0)
  1192. return waterlist[i].waterheight;
  1193. }
  1194. return NO_WATER;
  1195. }
  1196. static void map_readwater(char *watertxt) {
  1197. char line[1024],w1[1024];
  1198. FILE *fp=NULL;
  1199. int n=0;
  1200. fp=fopen(watertxt,"r");
  1201. if(fp==NULL){
  1202. printf("file not found: %s\n",watertxt);
  1203. return;
  1204. }
  1205. if(waterlist==NULL)
  1206. waterlist=aCalloc(MAX_MAP_PER_SERVER,sizeof(*waterlist));
  1207. while(fgets(line,1020,fp) && n < MAX_MAP_PER_SERVER){
  1208. int wh,count;
  1209. if(line[0] == '/' && line[1] == '/')
  1210. continue;
  1211. if((count=sscanf(line,"%s%d",w1,&wh)) < 1){
  1212. continue;
  1213. }
  1214. strcpy(waterlist[n].mapname,w1);
  1215. if(count >= 2)
  1216. waterlist[n].waterheight = wh;
  1217. else
  1218. waterlist[n].waterheight = 3;
  1219. n++;
  1220. }
  1221. fclose(fp);
  1222. }
  1223. /*==========================================
  1224. * マップ1枚読み込み
  1225. *------------------------------------------
  1226. */
  1227. static int map_readmap(int m,char *fn, char *alias) {
  1228. unsigned char *gat="";
  1229. int s;
  1230. int x,y,xs,ys;
  1231. struct gat_1cell {float high[4]; int type;} *p=NULL;
  1232. int wh;
  1233. size_t size;
  1234. // read & convert fn
  1235. gat=grfio_read(fn);
  1236. if(gat==NULL)
  1237. return -1;
  1238. printf("\rLoading Maps [%d/%d]: %-50s ",m,map_num,fn);
  1239. fflush(stdout);
  1240. map[m].m=m;
  1241. xs=map[m].xs=*(int*)(gat+6);
  1242. ys=map[m].ys=*(int*)(gat+10);
  1243. map[m].gat = (unsigned char *)aCalloc(s = map[m].xs * map[m].ys,sizeof(unsigned char));
  1244. map[m].npc_num=0;
  1245. map[m].users=0;
  1246. memset(&map[m].flag,0,sizeof(map[m].flag));
  1247. if(battle_config.pk_mode) map[m].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
  1248. wh=map_waterheight(map[m].name);
  1249. for(y=0;y<ys;y++){
  1250. p=(struct gat_1cell*)(gat+y*xs*20+14);
  1251. for(x=0;x<xs;x++){
  1252. if(wh!=NO_WATER && p->type==0){
  1253. // 水場判定
  1254. map[m].gat[x+y*xs]=(p->high[0]>wh || p->high[1]>wh || p->high[2]>wh || p->high[3]>wh) ? 3 : 0;
  1255. } else {
  1256. map[m].gat[x+y*xs]=p->type;
  1257. }
  1258. p++;
  1259. }
  1260. }
  1261. free(gat);
  1262. map[m].bxs=(xs+BLOCK_SIZE-1)/BLOCK_SIZE;
  1263. map[m].bys=(ys+BLOCK_SIZE-1)/BLOCK_SIZE;
  1264. size = map[m].bxs * map[m].bys * sizeof(struct block_list*);
  1265. map[m].block = (struct block_list **)aCalloc(1,size);
  1266. map[m].block_mob = (struct block_list **)aCalloc(1,size);
  1267. size = map[m].bxs*map[m].bys*sizeof(int);
  1268. map[m].block_count = (int *)aCalloc(1,size);
  1269. map[m].block_mob_count=(int *)aCalloc(1,size);
  1270. strdb_insert(map_db,map[m].name,&map[m]);
  1271. // printf("%s read done\n",fn);
  1272. return 0;
  1273. }
  1274. /*==========================================
  1275. * 全てのmapデータを読み込む
  1276. *------------------------------------------
  1277. */
  1278. int map_readallmap(void) {
  1279. int i,maps_removed=0;
  1280. char fn[256]="";
  1281. // 先に全部のャbプの存在を確認
  1282. for(i=0;i<map_num;i++){
  1283. if(strstr(map[i].name,".gat")==NULL)
  1284. continue;
  1285. sprintf(fn,"data\\%s",map[i].name);
  1286. if(grfio_size(fn) == -1) {
  1287. map_delmap(map[i].name);
  1288. maps_removed++;
  1289. }
  1290. }
  1291. for(i=0;i<map_num;i++){
  1292. if(strstr(map[i].name,".gat")!=NULL) {
  1293. char *p = strstr(map[i].name, ">"); // [MouseJstr]
  1294. if (p != NULL) {
  1295. char alias[64];
  1296. *p = '\0';
  1297. strcpy(alias, map[i].name);
  1298. strcpy(map[i].name, p + 1);
  1299. sprintf(fn,"data\\%s",map[i].name);
  1300. if(map_readmap(i,fn, alias) == -1) {
  1301. map_delmap(map[i].name);
  1302. maps_removed++;
  1303. }
  1304. } else {
  1305. sprintf(fn,"data\\%s",map[i].name);
  1306. if(map_readmap(i,fn, NULL) == -1) {
  1307. map_delmap(map[i].name);
  1308. maps_removed++;
  1309. }
  1310. }
  1311. }
  1312. }
  1313. free(waterlist);
  1314. printf("\rMaps Loaded: %d %60s\n",map_num,"");
  1315. printf("\rMaps Removed: %d \n",maps_removed);
  1316. return 0;
  1317. }
  1318. /*==========================================
  1319. * 読み込むmapを追加する
  1320. *------------------------------------------
  1321. */
  1322. int map_addmap(char *mapname) {
  1323. if (strcmpi(mapname,"clear")==0) {
  1324. map_num=0;
  1325. return 0;
  1326. }
  1327. if (map_num >= MAX_MAP_PER_SERVER - 1) {
  1328. printf("too many map\n");
  1329. return 1;
  1330. }
  1331. memcpy(map[map_num].name, mapname, 24);
  1332. map_num++;
  1333. return 0;
  1334. }
  1335. /*==========================================
  1336. * 読み込むmapを削除する
  1337. *------------------------------------------
  1338. */
  1339. int map_delmap(char *mapname) {
  1340. int i;
  1341. if (strcmpi(mapname, "all") == 0) {
  1342. map_num = 0;
  1343. return 0;
  1344. }
  1345. for(i = 0; i < map_num; i++) {
  1346. if (strcmp(map[i].name, mapname) == 0) {
  1347. printf("Removing map [ %s ] from maplist\n",map[i].name);
  1348. memmove(map+i, map+i+1, sizeof(map[0])*(map_num-i-1));
  1349. map_num--;
  1350. }
  1351. }
  1352. return 0;
  1353. }
  1354. static int map_ip_set_ = 0;
  1355. static int char_ip_set_ = 0;
  1356. /*==========================================
  1357. * Console Command Parser [Wizputer]
  1358. *------------------------------------------
  1359. */
  1360. int parse_console(char *buf) {
  1361. char *type,*command,*map, *buf2;
  1362. int x = 0, y = 0;
  1363. int m, n;
  1364. struct map_session_data *sd;
  1365. sd = calloc(sizeof(*sd), 1);
  1366. sd->fd = 0;
  1367. strcpy( sd->status.name , "console");
  1368. type = (char *)malloc(64);
  1369. command = (char *)malloc(64);
  1370. map = (char *)malloc(64);
  1371. buf2 = (char *)malloc(72);
  1372. memset(type,0,64);
  1373. memset(command,0,64);
  1374. memset(map,0,64);
  1375. memset(buf2,0,72);
  1376. if ( ( n = sscanf(buf, "%[^:]:%[^:]:%99s %d %d[^\n]", type , command , map , &x , &y )) < 5 )
  1377. if ( ( n = sscanf(buf, "%[^:]:%[^\n]", type , command )) < 2 )
  1378. n = sscanf(buf,"%[^\n]",type);
  1379. if ( n == 5 ) {
  1380. if (x <= 0) {
  1381. x = rand() % 399 + 1;
  1382. sd->bl.x = x;
  1383. } else {
  1384. sd->bl.x = x;
  1385. }
  1386. if (y <= 0) {
  1387. y = rand() % 399 + 1;
  1388. sd->bl.y = y;
  1389. } else {
  1390. sd->bl.y = y;
  1391. }
  1392. m = map_mapname2mapid(map);
  1393. if ( m >= 0 )
  1394. sd->bl.m = m;
  1395. else {
  1396. printf("Console: Unknown map\n");
  1397. goto end;
  1398. }
  1399. }
  1400. printf("Type of command: %s || Command: %s || Map: %s Coords: %d %d\n",type,command,map,x,y);
  1401. if ( strcmpi("admin",type) == 0 && n == 5 ) {
  1402. sprintf(buf2,"console: %s",command);
  1403. if( is_atcommand(sd->fd,sd,buf2,99) == AtCommand_None )
  1404. printf("Console: not atcommand\n");
  1405. } else if ( strcmpi("server",type) == 0 && n == 2 ) {
  1406. if ( strcmpi("shutdown", command) == 0 || strcmpi("exit",command) == 0 || strcmpi("quit",command) == 0 ) {
  1407. exit(0);
  1408. }
  1409. } else if ( strcmpi("help",type) == 0 ) {
  1410. printf("To use GM commands:\n");
  1411. printf("admin:<gm command>:<map of \"gm\"> <x> <y>\n");
  1412. printf("You can use any GM command that doesn't require the GM.\n");
  1413. printf("No using @item or @warp however you can use @charwarp\n");
  1414. printf("The <map of \"gm\"> <x> <y> is for commands that need coords of the GM\n");
  1415. printf("IE: @spawn\n");
  1416. printf("To shutdown the server:\n");
  1417. printf("server:shutdown\n");
  1418. }
  1419. end:
  1420. free(buf);
  1421. free(type);
  1422. free(command);
  1423. free(map);
  1424. free(buf2);
  1425. free(sd);
  1426. return 0;
  1427. }
  1428. /*==========================================
  1429. * 設定ファイルを読み込む
  1430. *------------------------------------------
  1431. */
  1432. int map_config_read(char *cfgName) {
  1433. char line[1024], w1[1024], w2[1024];
  1434. FILE *fp;
  1435. struct hostent *h = NULL;
  1436. fp = fopen(cfgName,"r");
  1437. if (fp == NULL) {
  1438. printf("Map configuration file not found at: %s\n", cfgName);
  1439. exit(1);
  1440. }
  1441. while(fgets(line, sizeof(line) -1, fp)) {
  1442. if (line[0] == '/' && line[1] == '/')
  1443. continue;
  1444. if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) {
  1445. if (strcmpi(w1, "userid")==0){
  1446. chrif_setuserid(w2);
  1447. } else if (strcmpi(w1, "passwd") == 0) {
  1448. chrif_setpasswd(w2);
  1449. } else if (strcmpi(w1, "char_ip") == 0) {
  1450. char_ip_set_ = 1;
  1451. h = gethostbyname (w2);
  1452. if(h != NULL) {
  1453. printf("Character server IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
  1454. sprintf(w2,"%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
  1455. }
  1456. chrif_setip(w2);
  1457. } else if (strcmpi(w1, "char_port") == 0) {
  1458. chrif_setport(atoi(w2));
  1459. } else if (strcmpi(w1, "map_ip") == 0) {
  1460. map_ip_set_ = 1;
  1461. h = gethostbyname (w2);
  1462. if (h != NULL) {
  1463. printf("Map server IP address : %s -> %d.%d.%d.%d\n", w2, (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
  1464. sprintf(w2, "%d.%d.%d.%d", (unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1], (unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
  1465. }
  1466. clif_setip(w2);
  1467. } else if (strcmpi(w1, "map_port") == 0) {
  1468. clif_setport(atoi(w2));
  1469. map_port = (atoi(w2));
  1470. } else if (strcmpi(w1, "water_height") == 0) {
  1471. map_readwater(w2);
  1472. } else if (strcmpi(w1, "map") == 0) {
  1473. map_addmap(w2);
  1474. } else if (strcmpi(w1, "delmap") == 0) {
  1475. map_delmap(w2);
  1476. } else if (strcmpi(w1, "npc") == 0) {
  1477. npc_addsrcfile(w2);
  1478. } else if (strcmpi(w1, "delnpc") == 0) {
  1479. npc_delsrcfile(w2);
  1480. } else if (strcmpi(w1, "data_grf") == 0) {
  1481. grfio_setdatafile(w2);
  1482. } else if (strcmpi(w1, "sdata_grf") == 0) {
  1483. grfio_setsdatafile(w2);
  1484. } else if (strcmpi(w1, "adata_grf") == 0) {
  1485. grfio_setadatafile(w2);
  1486. } else if (strcmpi(w1, "autosave_time") == 0) {
  1487. autosave_interval = atoi(w2) * 1000;
  1488. if (autosave_interval <= 0)
  1489. autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
  1490. } else if (strcmpi(w1, "motd_txt") == 0) {
  1491. strcpy(motd_txt, w2);
  1492. } else if (strcmpi(w1, "help_txt") == 0) {
  1493. strcpy(help_txt, w2);
  1494. } else if (strcmpi(w1, "mapreg_txt") == 0) {
  1495. strcpy(mapreg_txt, w2);
  1496. } else if (strcmpi(w1, "import") == 0) {
  1497. map_config_read(w2);
  1498. } else if (strcmpi(w1, "console") == 0) {
  1499. if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 )
  1500. console = 1;
  1501. } else if(strcmpi(w1,"imalive_on")==0){ //Added by Mugendai for I'm Alive mod
  1502. imalive_on = atoi(w2); //Added by Mugendai for I'm Alive mod
  1503. } else if(strcmpi(w1,"imalive_time")==0){ //Added by Mugendai for I'm Alive mod
  1504. imalive_time = atoi(w2); //Added by Mugendai for I'm Alive mod
  1505. } else if(strcmpi(w1,"flush_on")==0){ //Added by Mugendai for GUI
  1506. flush_on = atoi(w2); //Added by Mugendai for GUI
  1507. } else if(strcmpi(w1,"flush_time")==0){ //Added by Mugendai for GUI
  1508. flush_time = atoi(w2); //Added by Mugendai for GUI
  1509. }
  1510. }
  1511. }
  1512. fclose(fp);
  1513. return 0;
  1514. }
  1515. #ifndef TXT_ONLY
  1516. /*=======================================
  1517. * MySQL Init
  1518. *---------------------------------------
  1519. */
  1520. int map_sql_init(void){
  1521. mysql_init(&mmysql_handle);
  1522. //DB connection start
  1523. printf("Connect Map DB Server....\n");
  1524. if(!mysql_real_connect(&mmysql_handle, map_server_ip, map_server_id, map_server_pw,
  1525. map_server_db ,map_server_port, (char *)NULL, 0)) {
  1526. //pointer check
  1527. printf("%s\n",mysql_error(&mmysql_handle));
  1528. exit(1);
  1529. }
  1530. else {
  1531. printf ("connect success! (Map Server Connection)\n");
  1532. }
  1533. mysql_init(&lmysql_handle);
  1534. //DB connection start
  1535. printf("Connect Login DB Server....\n");
  1536. if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw,
  1537. login_server_db ,login_server_port, (char *)NULL, 0)) {
  1538. //pointer check
  1539. printf("%s\n",mysql_error(&lmysql_handle));
  1540. exit(1);
  1541. }
  1542. else {
  1543. printf ("connect success! (Login Server Connection)\n");
  1544. }
  1545. if(battle_config.mail_system) { // mail system [Valaris]
  1546. mysql_init(&mail_handle);
  1547. if(!mysql_real_connect(&mail_handle, map_server_ip, map_server_id, map_server_pw,
  1548. map_server_db ,map_server_port, (char *)NULL, 0)) {
  1549. printf("%s\n",mysql_error(&mail_handle));
  1550. exit(1);
  1551. }
  1552. }
  1553. return 0;
  1554. }
  1555. int map_sql_close(void){
  1556. mysql_close(&mmysql_handle);
  1557. printf("Close Map DB Connection....\n");
  1558. mysql_close(&lmysql_handle);
  1559. printf("Close Login DB Connection....\n");
  1560. return 0;
  1561. }
  1562. int log_sql_init(void){
  1563. mysql_init(&mmysql_handle);
  1564. //DB connection start
  1565. printf("\033[1;29m[SQL]\033[0;0m: Connecting to Log Database \033[1;29m%s\033[0;0m At \033[1;29m%s\033[0;0m...\n",log_db,log_db_ip);
  1566. if(!mysql_real_connect(&mmysql_handle, log_db_ip, log_db_id, log_db_pw,
  1567. log_db ,log_db_port, (char *)NULL, 0)) {
  1568. //pointer check
  1569. printf("\033[1;29m[SQL Error]\033[0;0m: %s\n",mysql_error(&mmysql_handle));
  1570. exit(1);
  1571. } else {
  1572. printf("\033[1;29m[SQL]\033[0;0m: Successfully \033[1;32mconnected\033[0;0m to Database \033[1;29m%s\033[0;0m.\n", log_db);
  1573. }
  1574. return 0;
  1575. }
  1576. int sql_config_read(char *cfgName)
  1577. {
  1578. int i;
  1579. char line[1024],w1[1024],w2[1024];
  1580. FILE *fp;
  1581. fp=fopen(cfgName,"r");
  1582. if(fp==NULL){
  1583. printf("file not found: %s\n",cfgName);
  1584. return 1;
  1585. }
  1586. while(fgets(line,1020,fp)){
  1587. if(line[0] == '/' && line[1] == '/')
  1588. continue;
  1589. i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
  1590. if(i!=2)
  1591. continue;
  1592. if(strcmpi(w1,"item_db_db")==0){
  1593. strcpy(item_db_db,w2);
  1594. } else if(strcmpi(w1,"mob_db_db")==0){
  1595. strcpy(mob_db_db,w2);
  1596. } else if(strcmpi(w1,"login_db_level")==0){
  1597. strcpy(login_db_level,w2);
  1598. } else if(strcmpi(w1,"login_db_account_id")==0){
  1599. strcpy(login_db_account_id,w2);
  1600. } else if(strcmpi(w1,"login_db")==0){
  1601. strcpy(login_db,w2);
  1602. } else if (strcmpi(w1, "char_db") == 0) {
  1603. strcpy(char_db, w2);
  1604. } else if(strcmpi(w1,"gm_db_level")==0){
  1605. strcpy(gm_db_level,w2);
  1606. } else if(strcmpi(w1,"gm_db_account_id")==0){
  1607. strcpy(gm_db_account_id,w2);
  1608. } else if(strcmpi(w1,"gm_db")==0){
  1609. strcpy(gm_db,w2);
  1610. //Map Server SQL DB
  1611. } else if(strcmpi(w1,"map_server_ip")==0){
  1612. strcpy(map_server_ip, w2);
  1613. printf ("set map_server_ip : %s\n",w2);
  1614. } else if(strcmpi(w1,"map_server_port")==0){
  1615. map_server_port=atoi(w2);
  1616. printf ("set map_server_port : %s\n",w2);
  1617. } else if(strcmpi(w1,"map_server_id")==0){
  1618. strcpy(map_server_id, w2);
  1619. printf ("set map_server_id : %s\n",w2);
  1620. } else if(strcmpi(w1,"map_server_pw")==0){
  1621. strcpy(map_server_pw, w2);
  1622. printf ("set map_server_pw : %s\n",w2);
  1623. } else if(strcmpi(w1,"map_server_db")==0){
  1624. strcpy(map_server_db, w2);
  1625. printf ("set map_server_db : %s\n",w2);
  1626. //Map server option to use SQL db or not
  1627. } else if(strcmpi(w1,"use_sql_db")==0){
  1628. if (strcmpi(w2,"yes")){db_use_sqldbs=0;} else if (strcmpi(w2,"no")){db_use_sqldbs=1;}
  1629. printf ("Using SQL dbs: %s\n",w2);
  1630. //Login Server SQL DB
  1631. } else if(strcmpi(w1,"login_server_ip")==0){
  1632. strcpy(login_server_ip, w2);
  1633. printf ("set login_server_ip : %s\n",w2);
  1634. } else if(strcmpi(w1,"login_server_port")==0){
  1635. login_server_port = atoi(w2);
  1636. printf ("set login_server_port : %s\n",w2);
  1637. } else if(strcmpi(w1,"login_server_id")==0){
  1638. strcpy(login_server_id, w2);
  1639. printf ("set login_server_id : %s\n",w2);
  1640. } else if(strcmpi(w1,"login_server_pw")==0){
  1641. strcpy(login_server_pw, w2);
  1642. printf ("set login_server_pw : %s\n",w2);
  1643. } else if(strcmpi(w1,"login_server_db")==0){
  1644. strcpy(login_server_db, w2);
  1645. printf ("set login_server_db : %s\n",w2);
  1646. } else if(strcmpi(w1,"lowest_gm_level")==0){
  1647. lowest_gm_level = atoi(w2);
  1648. printf ("set lowest_gm_level : %s\n",w2);
  1649. } else if(strcmpi(w1,"read_gm_interval")==0){
  1650. read_gm_interval = ( atoi(w2) * 60 * 1000 ); // Minutes multiplied by 60 secs per min by 1000 milliseconds per second
  1651. printf ("set read_gm_interval : %s\n",w2);
  1652. } else if(strcmpi(w1,"log_db")==0) {
  1653. strcpy(log_db, w2);
  1654. } else if(strcmpi(w1,"log_db_ip")==0) {
  1655. strcpy(log_db_ip, w2);
  1656. } else if(strcmpi(w1,"log_db")==0) {
  1657. strcpy(log_db, w2);
  1658. } else if(strcmpi(w1,"log_db_id")==0) {
  1659. strcpy(log_db_id, w2);
  1660. } else if(strcmpi(w1,"log_db_pw")==0) {
  1661. strcpy(log_db_pw, w2);
  1662. } else if(strcmpi(w1,"log_db_port")==0) {
  1663. log_db_port = atoi(w2);
  1664. }
  1665. }
  1666. fclose(fp);
  1667. return 0;
  1668. }
  1669. // sql online status checking [Valaris]
  1670. void char_offline(struct map_session_data *sd)
  1671. {
  1672. if(sd && sd->status.char_id) {
  1673. sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `char_id`='%d'", char_db, sd->status.char_id);
  1674. if(mysql_query(&mmysql_handle, tmp_sql) ) {
  1675. printf("DB server Error (update online `%s`)- %s\n", char_db, mysql_error(&mmysql_handle) );
  1676. }
  1677. }
  1678. }
  1679. void do_reset_online(void)
  1680. {
  1681. sprintf(tmp_sql,"UPDATE `%s` SET `online`='0' WHERE `online`='1'", char_db);
  1682. if(mysql_query(&mmysql_handle, tmp_sql) ) {
  1683. printf("DB server Error (reset_online `%s`)- %s\n", char_db, mysql_error(&mmysql_handle) );
  1684. }
  1685. }
  1686. int online_timer(int tid,unsigned int tick,int id,int data)
  1687. {
  1688. if(check_online_timer != tid)
  1689. return 0;
  1690. char_online_check();
  1691. check_online_timer=add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0);
  1692. return 0;
  1693. }
  1694. void char_online_check(void)
  1695. {
  1696. int i;
  1697. struct map_session_data *sd=NULL;
  1698. do_reset_online();
  1699. for(i=0;i<fd_max;i++){
  1700. if (session[i] && (sd = session[i]->session_data) && sd && sd->state.auth &&
  1701. !(battle_config.hide_GM_session && pc_isGM(sd)))
  1702. if(sd->status.char_id) {
  1703. sprintf(tmp_sql,"UPDATE `%s` SET `online`='1' WHERE `char_id`='%d'", char_db, sd->status.char_id);
  1704. if(mysql_query(&mmysql_handle, tmp_sql) ) {
  1705. printf("DB server Error (update online `%s`)- %s\n", char_db, mysql_error(&mmysql_handle) );
  1706. }
  1707. }
  1708. }
  1709. if(check_online_timer && check_online_timer != -1) {
  1710. delete_timer(check_online_timer,online_timer);
  1711. add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0);
  1712. }
  1713. }
  1714. #endif /* not TXT_ONLY */
  1715. //-----------------------------------------------------
  1716. //I'm Alive Alert
  1717. //Used to output 'I'm Alive' every few seconds
  1718. //Intended to let frontends know if the app froze
  1719. //-----------------------------------------------------
  1720. int imalive_timer(int tid, unsigned int tick, int id, int data){
  1721. printf("I'm Alive\n");
  1722. return 0;
  1723. }
  1724. //-----------------------------------------------------
  1725. //Flush stdout
  1726. //stdout buffer needs flushed to be seen in GUI
  1727. //-----------------------------------------------------
  1728. int flush_timer(int tid, unsigned int tick, int id, int data){
  1729. fflush(stdout);
  1730. return 0;
  1731. }
  1732. int id_db_final(void *k,void *d,va_list ap){ return 0; }
  1733. int map_db_final(void *k,void *d,va_list ap){ return 0; }
  1734. int nick_db_final(void *k,void *d,va_list ap){ return 0; }
  1735. int charid_db_final(void *k,void *d,va_list ap){ return 0; }
  1736. static int cleanup_sub(struct block_list *bl, va_list ap) {
  1737. nullpo_retr(0, bl);
  1738. switch(bl->type) {
  1739. case BL_PC:
  1740. map_delblock(bl); // There is something better...
  1741. break;
  1742. case BL_NPC:
  1743. npc_delete((struct npc_data *)bl);
  1744. break;
  1745. case BL_MOB:
  1746. mob_delete((struct mob_data *)bl);
  1747. break;
  1748. case BL_PET:
  1749. pet_remove_map((struct map_session_data *)bl);
  1750. break;
  1751. case BL_ITEM:
  1752. map_clearflooritem(bl->id);
  1753. break;
  1754. case BL_SKILL:
  1755. skill_delunit((struct skill_unit *) bl);
  1756. break;
  1757. }
  1758. return 0;
  1759. }
  1760. /*==========================================
  1761. * map鯖終了時処理
  1762. *------------------------------------------
  1763. */
  1764. void do_final(void) {
  1765. int map_id, i;
  1766. for (map_id = 0; map_id < map_num;map_id++) {
  1767. if(map[map_id].m)
  1768. map_foreachinarea(cleanup_sub, map_id, 0, 0, map[map_id].xs, map[map_id].ys, 0, 0);
  1769. }
  1770. for (i = 0; i < fd_max; i++)
  1771. delete_session(i);
  1772. map_removenpc();
  1773. timer_final();
  1774. numdb_final(id_db, id_db_final);
  1775. strdb_final(map_db, map_db_final);
  1776. strdb_final(nick_db, nick_db_final);
  1777. numdb_final(charid_db, charid_db_final);
  1778. for(i=0;i<=map_num;i++){
  1779. if(map[i].gat) free(map[i].gat);
  1780. if(map[i].block) free(map[i].block);
  1781. if(map[i].block_mob) free(map[i].block_mob);
  1782. if(map[i].block_count) free(map[i].block_count);
  1783. if(map[i].block_mob_count) free(map[i].block_mob_count);
  1784. }
  1785. do_final_script();
  1786. do_final_itemdb();
  1787. do_final_storage();
  1788. do_final_guild();
  1789. #ifndef TXT_ONLY
  1790. do_reset_online();
  1791. map_sql_close();
  1792. #endif /* not TXT_ONLY */
  1793. }
  1794. void map_helpscreen() {
  1795. exit(1);
  1796. }
  1797. /*======================================================
  1798. * Map-Server Init and Command-line Arguments [Valaris]
  1799. *------------------------------------------------------
  1800. */
  1801. int do_init(int argc, char *argv[]) {
  1802. int i;
  1803. #ifndef TXT_ONLY
  1804. unsigned char *SQL_CONF_NAME="conf/inter_athena.conf";
  1805. unsigned char *LOG_CONF_NAME="conf/log_athena.conf";
  1806. #endif
  1807. unsigned char *MAP_CONF_NAME = "conf/map_athena.conf";
  1808. unsigned char *BATTLE_CONF_FILENAME = "conf/battle_athena.conf";
  1809. unsigned char *ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf";
  1810. unsigned char *SCRIPT_CONF_NAME = "conf/script_athena.conf";
  1811. unsigned char *MSG_CONF_NAME = "conf/msg_athena.conf";
  1812. unsigned char *GRF_PATH_FILENAME = "conf/grf-files.txt";
  1813. srand(gettick());
  1814. for (i = 1; i < argc ; i++) {
  1815. if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "--h") == 0 || strcmp(argv[i], "--?") == 0 || strcmp(argv[i], "/?") == 0)
  1816. map_helpscreen();
  1817. else if (strcmp(argv[i], "--map_config") == 0)
  1818. MAP_CONF_NAME=argv[i+1];
  1819. else if (strcmp(argv[i],"--battle_config") == 0)
  1820. BATTLE_CONF_FILENAME = argv[i+1];
  1821. else if (strcmp(argv[i],"--atcommand_config") == 0)
  1822. ATCOMMAND_CONF_FILENAME = argv[i+1];
  1823. else if (strcmp(argv[i],"--script_config") == 0)
  1824. SCRIPT_CONF_NAME = argv[i+1];
  1825. else if (strcmp(argv[i],"--msg_config") == 0)
  1826. MSG_CONF_NAME = argv[i+1];
  1827. else if (strcmp(argv[i],"--grf_path_file") == 0)
  1828. GRF_PATH_FILENAME = argv[i+1];
  1829. #ifndef TXT_ONLY
  1830. else if (strcmp(argv[i],"--sql_config") == 0)
  1831. SQL_CONF_NAME = argv[i+1];
  1832. #endif /* not TXT_ONLY */
  1833. }
  1834. map_config_read(MAP_CONF_NAME);
  1835. if ((naddr_ == 0) && (map_ip_set_ == 0 || char_ip_set_ == 0)) {
  1836. printf("\nUnable to determine your IP address... please edit\n");
  1837. printf("the map_athena.conf file and set it.\n");
  1838. printf("(127.0.0.1 is valid if you have no network interface)\n");
  1839. }
  1840. if (map_ip_set_ == 0 || char_ip_set_ == 0) {
  1841. // The map server should know what IP address it is running on
  1842. // - MouseJstr
  1843. int localaddr = ntohl(addr_[0]);
  1844. unsigned char *ptr = (unsigned char *) &localaddr;
  1845. char buf[16];
  1846. sprintf(buf, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);;
  1847. if (naddr_ != 1)
  1848. printf("Multiple interfaces detected.. using %s as our IP address\n", buf);
  1849. else
  1850. printf("Defaulting to %s as our IP address\n", buf);
  1851. if (map_ip_set_ == 0)
  1852. clif_setip(buf);
  1853. if (char_ip_set_ == 0)
  1854. chrif_setip(buf);
  1855. if (ptr[0] == 192 && ptr[1] == 168)
  1856. printf("\nFirewall detected.. \n edit lan_support.conf and map_athena.conf\n\n");
  1857. }
  1858. battle_config_read(BATTLE_CONF_FILENAME);
  1859. atcommand_config_read(ATCOMMAND_CONF_FILENAME);
  1860. script_config_read(SCRIPT_CONF_NAME);
  1861. msg_config_read(MSG_CONF_NAME);
  1862. #ifndef TXT_ONLY
  1863. sql_config_read(SQL_CONF_NAME);
  1864. log_config_read(LOG_CONF_NAME);
  1865. #endif /* not TXT_ONLY */
  1866. atexit(do_final);
  1867. id_db = numdb_init();
  1868. map_db = strdb_init(16);
  1869. nick_db = strdb_init(24);
  1870. charid_db = numdb_init();
  1871. #ifndef TXT_ONLY
  1872. map_sql_init();
  1873. #endif /* not TXT_ONLY */
  1874. grfio_init(GRF_PATH_FILENAME);
  1875. map_readallmap();
  1876. add_timer_func_list(map_clearflooritem_timer, "map_clearflooritem_timer");
  1877. //Added by Mugendai for GUI support
  1878. if (flush_on)
  1879. {
  1880. add_timer_interval(gettick()+10, flush_timer,0,0,flush_time);
  1881. }
  1882. #ifndef TXT_ONLY // online status timer, checks every hour [Valaris]
  1883. add_timer_func_list(online_timer, "online_timer");
  1884. check_online_timer=add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0);
  1885. #endif /* not TXT_ONLY */
  1886. do_init_chrif();
  1887. do_init_clif();
  1888. do_init_itemdb();
  1889. do_init_mob(); // npcの初期化時内でmob_spawnして、mob_dbを参照するのでinit_npcより先
  1890. do_init_script();
  1891. do_init_npc();
  1892. do_init_pc();
  1893. do_init_party();
  1894. do_init_guild();
  1895. do_init_storage();
  1896. do_init_skill();
  1897. do_init_pet();
  1898. #ifndef TXT_ONLY /* mail system [Valaris] */
  1899. if(battle_config.mail_system)
  1900. do_init_mail();
  1901. if (log_config.branch || log_config.drop || log_config.mvpdrop ||
  1902. log_config.present || log_config.produce || log_config.refine ||
  1903. log_config.trade)
  1904. {
  1905. log_sql_init();
  1906. }
  1907. #endif /* not TXT_ONLY */
  1908. npc_event_do_oninit(); // npcのOnInitイベント実行
  1909. if ( console ) {
  1910. set_defaultconsoleparse(parse_console);
  1911. start_console();
  1912. }
  1913. if (battle_config.pk_mode == 1)
  1914. printf("The server is running in \033[1;31mPK Mode\033[0m.\n");
  1915. //Added for Mugendais I'm Alive mod
  1916. if (imalive_on)
  1917. add_timer_interval(gettick()+10, imalive_timer,0,0,imalive_time*1000);
  1918. printf("The map-server is \033[1;32mready\033[0m (Server is listening on the port %d).\n\n", map_port);
  1919. ticks = gettick();
  1920. return 0;
  1921. }