map.c 63 KB

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