map.c 96 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455
  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 <math.h>
  12. #include "core.h"
  13. #include "timer.h"
  14. #include "db.h"
  15. #include "grfio.h"
  16. #include "malloc.h"
  17. #include "version.h"
  18. #include "map.h"
  19. #include "chrif.h"
  20. #include "clif.h"
  21. #include "intif.h"
  22. #include "npc.h"
  23. #include "pc.h"
  24. #include "status.h"
  25. #include "mob.h"
  26. #include "chat.h"
  27. #include "itemdb.h"
  28. #include "storage.h"
  29. #include "skill.h"
  30. #include "trade.h"
  31. #include "party.h"
  32. #include "battle.h"
  33. #include "script.h"
  34. #include "guild.h"
  35. #include "pet.h"
  36. #include "atcommand.h"
  37. #include "charcommand.h"
  38. #include "nullpo.h"
  39. #include "socket.h"
  40. #include "log.h"
  41. #include "showmsg.h"
  42. #ifdef MEMWATCH
  43. #include "memwatch.h"
  44. #endif
  45. // maybe put basic macros to somewhere else
  46. #define swap(a,b) ((a == b) || ((a ^= b), (b ^= a), (a ^= b)))
  47. #ifndef TXT_ONLY
  48. #include "mail.h" // mail system [Valaris]
  49. MYSQL mmysql_handle;
  50. MYSQL_RES* sql_res ;
  51. MYSQL_ROW sql_row ;
  52. char tmp_sql[65535]="";
  53. MYSQL lmysql_handle;
  54. MYSQL_RES* lsql_res ;
  55. MYSQL_ROW lsql_row ;
  56. char tmp_lsql[65535]="";
  57. MYSQL mail_handle; // mail system [Valaris]
  58. MYSQL_RES* mail_res ;
  59. MYSQL_ROW mail_row ;
  60. char tmp_msql[65535]="";
  61. int map_server_port = 3306;
  62. char map_server_ip[16] = "127.0.0.1";
  63. char map_server_id[32] = "ragnarok";
  64. char map_server_pw[32] = "ragnarok";
  65. char map_server_db[32] = "ragnarok";
  66. int db_use_sqldbs = 0;
  67. int login_server_port = 3306;
  68. char login_server_ip[16] = "127.0.0.1";
  69. char login_server_id[32] = "ragnarok";
  70. char login_server_pw[32] = "ragnarok";
  71. char login_server_db[32] = "ragnarok";
  72. char item_db_db[32] = "item_db";
  73. char mob_db_db[32] = "mob_db";
  74. char login_db[32] = "login";
  75. char login_db_level[32] = "level";
  76. char login_db_account_id[32] = "account_id";
  77. char log_db[32] = "log";
  78. char log_db_ip[16] = "127.0.0.1";
  79. char log_db_id[32] = "ragnarok";
  80. char log_db_pw[32] = "ragnarok";
  81. int log_db_port = 3306;
  82. char gm_db[32] = "login";
  83. char gm_db_level[32] = "level";
  84. char gm_db_account_id[32] = "account_id";
  85. int lowest_gm_level = 1;
  86. int read_gm_interval = 600000;
  87. char char_db[32] = "char";
  88. static int online_timer(int,unsigned int,int,int);
  89. int CHECK_INTERVAL = 3600000; // [Valaris]
  90. int check_online_timer=0; // [Valaris]
  91. #endif /* not TXT_ONLY */
  92. char *INTER_CONF_NAME;
  93. char *LOG_CONF_NAME;
  94. char *MAP_CONF_NAME;
  95. char *BATTLE_CONF_FILENAME;
  96. char *ATCOMMAND_CONF_FILENAME;
  97. char *CHARCOMMAND_CONF_FILENAME;
  98. char *SCRIPT_CONF_NAME;
  99. char *MSG_CONF_NAME;
  100. char *GRF_PATH_FILENAME;
  101. #define USE_AFM
  102. #define USE_AF2
  103. // 極力 staticでロ?カルに?める
  104. static struct dbt * id_db=NULL;
  105. static struct dbt * map_db=NULL;
  106. static struct dbt * nick_db=NULL;
  107. static struct dbt * charid_db=NULL;
  108. static int users=0;
  109. static struct block_list *objects[MAX_FLOORITEM];
  110. static int first_free_object_id=0,last_object_id=0;
  111. #define block_free_max 1048576
  112. static void *block_free[block_free_max];
  113. static int block_free_count = 0, block_free_lock = 0;
  114. #define BL_LIST_MAX 1048576
  115. static struct block_list *bl_list[BL_LIST_MAX];
  116. static int bl_list_count = 0;
  117. static char afm_dir[1024] = ""; // [Valaris]
  118. struct map_data map[MAX_MAP_PER_SERVER];
  119. int map_num = 0;
  120. int map_port=0;
  121. int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
  122. int agit_flag = 0;
  123. int night_flag = 0; // 0=day, 1=night [Yor]
  124. //Added for Mugendai's I'm Alive mod
  125. int imalive_on=0;
  126. int imalive_time=60;
  127. //Added by Mugendai for GUI
  128. int flush_on=1;
  129. int flush_time=100;
  130. struct charid2nick {
  131. char nick[24];
  132. int req_id;
  133. };
  134. // ォ゙ォテォラォュォ罩テォキォ袮ラ鯑ォユォ鬮ー(map_athana.conf?ェホread_map_from_cacheェヌ�・)
  135. // 0:ララ鯑ェキェハェ、 1:゙ェ?�ワチ� 2:?�ワチ�
  136. int map_read_flag = READ_FROM_GAT;
  137. char map_cache_file[256]="db/map.info"; // ォ゙ォテォラォュォ罩テォキォ雖ユォ。ォ、ォ・」
  138. char motd_txt[256] = "conf/motd.txt";
  139. char help_txt[256] = "conf/help.txt";
  140. char wisp_server_name[24] = "Server"; // can be modified in char-server configuration file
  141. int console = 0;
  142. /*==========================================
  143. * 全map鯖?計での接??設定
  144. * (char鯖から送られてくる)
  145. *------------------------------------------
  146. */
  147. void map_setusers(int fd)
  148. {
  149. users = RFIFOL(fd,2);
  150. // send some anser
  151. WFIFOW(fd,0) = 0x2718;
  152. WFIFOSET(fd,2);
  153. }
  154. /*==========================================
  155. * 全map鯖?計での接??取得 (/wへの?答用)
  156. *------------------------------------------
  157. */
  158. int map_getusers(void) {
  159. return users;
  160. }
  161. //
  162. // block削除の安全性確保?理
  163. //
  164. /*==========================================
  165. * blockをfreeするときfreeの?わりに呼ぶ
  166. * ロックされているときはバッファにためる
  167. *------------------------------------------
  168. */
  169. int map_freeblock( void *bl )
  170. {
  171. if(block_free_lock==0){
  172. aFree(bl);
  173. bl = NULL;
  174. }
  175. else{
  176. if( block_free_count>=block_free_max ) {
  177. if(battle_config.error_log)
  178. printf("map_freeblock: *WARNING* too many free block! %d %d\n",
  179. block_free_count,block_free_lock);
  180. }
  181. else
  182. block_free[block_free_count++]=bl;
  183. }
  184. return block_free_lock;
  185. }
  186. /*==========================================
  187. * blockのfreeを一時的に禁止する
  188. *------------------------------------------
  189. */
  190. int map_freeblock_lock(void) {
  191. return ++block_free_lock;
  192. }
  193. /*==========================================
  194. * blockのfreeのロックを解除する
  195. * このとき、ロックが完全になくなると
  196. * バッファにたまっていたblockを全部削除
  197. *------------------------------------------
  198. */
  199. int map_freeblock_unlock(void) {
  200. if ((--block_free_lock) == 0) {
  201. int i;
  202. // if(block_free_count>0) {
  203. // if(battle_config.error_log)
  204. // printf("map_freeblock_unlock: free %d object\n",block_free_count);
  205. // }
  206. for(i=0;i<block_free_count;i++){
  207. aFree(block_free[i]);
  208. block_free[i] = NULL;
  209. }
  210. block_free_count=0;
  211. }else if(block_free_lock<0){
  212. if(battle_config.error_log)
  213. printf("map_freeblock_unlock: lock count < 0 !\n");
  214. block_free_lock = 0; // 次回以降のロックに支障が出てくるのでリセット
  215. }
  216. return block_free_lock;
  217. }
  218. // map_freeblock_lock() を呼んで map_freeblock_unlock() を呼ばない
  219. // 関数があったので、定期的にblock_free_lockをリセットするようにする。
  220. // この関数は、do_timer() のトップレベルから呼ばれるので、
  221. // block_free_lock を直接いじっても支障無いはず。
  222. int map_freeblock_timer(int tid,unsigned int tick,int id,int data) {
  223. if(block_free_lock > 0) {
  224. printf("map_freeblock_timer: block_free_lock(%d) is invalid.\n",block_free_lock);
  225. block_free_lock = 1;
  226. map_freeblock_unlock();
  227. }
  228. // else {
  229. // printf("map_freeblock_timer: check ok\n");
  230. // }
  231. return 0;
  232. }
  233. //
  234. // block化?理
  235. //
  236. /*==========================================
  237. * map[]のblock_listから?がっている場合に
  238. * bl->prevにbl_headのアドレスを入れておく
  239. *------------------------------------------
  240. */
  241. static struct block_list bl_head;
  242. /*==========================================
  243. * map[]のblock_listに追加
  244. * mobは?が多いので別リスト
  245. *
  246. * ?にlink?みかの確認が無い。危?かも
  247. *------------------------------------------
  248. */
  249. int map_addblock(struct block_list *bl)
  250. {
  251. int m,x,y;
  252. nullpo_retr(0, bl);
  253. if(bl->prev != NULL){
  254. if(battle_config.error_log)
  255. printf("map_addblock error : bl->prev!=NULL\n");
  256. return 0;
  257. }
  258. m=bl->m;
  259. x=bl->x;
  260. y=bl->y;
  261. if(m<0 || m>=map_num ||
  262. x<0 || x>=map[m].xs ||
  263. y<0 || y>=map[m].ys)
  264. return 1;
  265. if(bl->type==BL_MOB){
  266. bl->next = map[m].block_mob[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs];
  267. bl->prev = &bl_head;
  268. if(bl->next) bl->next->prev = bl;
  269. map[m].block_mob[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs] = bl;
  270. map[m].block_mob_count[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs]++;
  271. } else {
  272. bl->next = map[m].block[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs];
  273. bl->prev = &bl_head;
  274. if(bl->next) bl->next->prev = bl;
  275. map[m].block[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs] = bl;
  276. map[m].block_count[x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs]++;
  277. if(bl->type==BL_PC)
  278. map[m].users++;
  279. }
  280. return 0;
  281. }
  282. /*==========================================
  283. * map[]のblock_listから外す
  284. * prevがNULLの場合listに?がってない
  285. *------------------------------------------
  286. */
  287. int map_delblock(struct block_list *bl)
  288. {
  289. int b;
  290. nullpo_retr(0, bl);
  291. // ?にblocklistから?けている
  292. if(bl->prev==NULL){
  293. if(bl->next!=NULL){
  294. // prevがNULLでnextがNULLでないのは有ってはならない
  295. if(battle_config.error_log)
  296. printf("map_delblock error : bl->next!=NULL\n");
  297. }
  298. return 0;
  299. }
  300. b = bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs;
  301. if(bl->type==BL_PC)
  302. map[bl->m].users--;
  303. if(bl->next)
  304. bl->next->prev = bl->prev;
  305. if(bl->prev==&bl_head){
  306. // リストの頭なので、map[]のblock_listを更新する
  307. if(bl->type==BL_MOB){
  308. map[bl->m].block_mob[b] = bl->next;
  309. if((map[bl->m].block_mob_count[b]--) < 0)
  310. map[bl->m].block_mob_count[b] = 0;
  311. } else {
  312. map[bl->m].block[b] = bl->next;
  313. if((map[bl->m].block_count[b]--) < 0)
  314. map[bl->m].block_count[b] = 0;
  315. }
  316. } else {
  317. bl->prev->next = bl->next;
  318. }
  319. bl->next = NULL;
  320. bl->prev = NULL;
  321. return 0;
  322. }
  323. /*==========================================
  324. * 周?のPC人?を?える (現在未使用)
  325. *------------------------------------------
  326. */
  327. int map_countnearpc(int m, int x, int y) {
  328. int bx,by,c=0;
  329. struct block_list *bl=NULL;
  330. if(map[m].users==0)
  331. return 0;
  332. for(by=y/BLOCK_SIZE-AREA_SIZE/BLOCK_SIZE-1;by<=y/BLOCK_SIZE+AREA_SIZE/BLOCK_SIZE+1;by++){
  333. if(by<0 || by>=map[m].bys)
  334. continue;
  335. for(bx=x/BLOCK_SIZE-AREA_SIZE/BLOCK_SIZE-1;bx<=x/BLOCK_SIZE+AREA_SIZE/BLOCK_SIZE+1;bx++){
  336. if(bx<0 || bx>=map[m].bxs)
  337. continue;
  338. bl = map[m].block[bx+by*map[m].bxs];
  339. for(;bl;bl=bl->next){
  340. if(bl->type==BL_PC)
  341. c++;
  342. }
  343. }
  344. }
  345. return c;
  346. }
  347. /*==========================================
  348. * セル上のPCとMOBの?を?える (グランドクロス用)
  349. *------------------------------------------
  350. */
  351. int map_count_oncell(int m, int x, int y) {
  352. int bx,by;
  353. struct block_list *bl=NULL;
  354. int i,c;
  355. int count = 0;
  356. if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys))
  357. return 1;
  358. bx = x/BLOCK_SIZE;
  359. by = y/BLOCK_SIZE;
  360. bl = map[m].block[bx+by*map[m].bxs];
  361. c = map[m].block_count[bx+by*map[m].bxs];
  362. for(i=0;i<c && bl;i++,bl=bl->next){
  363. if(bl->x == x && bl->y == y && bl->type == BL_PC) count++;
  364. }
  365. bl = map[m].block_mob[bx+by*map[m].bxs];
  366. c = map[m].block_mob_count[bx+by*map[m].bxs];
  367. for(i=0;i<c && bl;i++,bl=bl->next){
  368. if(bl->x == x && bl->y == y) count++;
  369. }
  370. if(!count) count = 1;
  371. return count;
  372. }
  373. /*
  374. * ォサォ・セェホ��ェヒフクェトェアェソォケォュォ・讚ヒォテォネェ��ケ
  375. */
  376. struct skill_unit *map_find_skill_unit_oncell(struct block_list *target,int x,int y,int skill_id,struct skill_unit *out_unit)
  377. {
  378. int m,bx,by;
  379. struct block_list *bl;
  380. int i,c;
  381. struct skill_unit *unit;
  382. m = target->m;
  383. if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys))
  384. return NULL;
  385. bx = x/BLOCK_SIZE;
  386. by = y/BLOCK_SIZE;
  387. bl = map[m].block[bx+by*map[m].bxs];
  388. c = map[m].block_count[bx+by*map[m].bxs];
  389. for(i=0;i<c && bl;i++,bl=bl->next){
  390. if (bl->x != x || bl->y != y || bl->type != BL_SKILL)
  391. continue;
  392. unit = (struct skill_unit *) bl;
  393. if (unit==out_unit || !unit->alive ||
  394. !unit->group || unit->group->skill_id!=skill_id)
  395. continue;
  396. if (battle_check_target(&unit->bl,target,unit->group->target_flag)>0)
  397. return unit;
  398. }
  399. return NULL;
  400. }
  401. /*==========================================
  402. * map m (x0,y0)-(x1,y1)?の全objに?して
  403. * funcを呼ぶ
  404. * type!=0 ならその種類のみ
  405. *------------------------------------------
  406. */
  407. void map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int type,...) {
  408. va_list ap;
  409. int bx,by;
  410. struct block_list *bl=NULL;
  411. int blockcount=bl_list_count,i,c;
  412. if(m < 0)
  413. return;
  414. va_start(ap,type);
  415. if (x0 < 0) x0 = 0;
  416. if (y0 < 0) y0 = 0;
  417. if (x1 >= map[m].xs) x1 = map[m].xs-1;
  418. if (y1 >= map[m].ys) y1 = map[m].ys-1;
  419. if (type == 0 || type != BL_MOB)
  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. }
  431. }
  432. if(type==0 || type==BL_MOB)
  433. for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
  434. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  435. bl = map[m].block_mob[bx+by*map[m].bxs];
  436. c = map[m].block_mob_count[bx+by*map[m].bxs];
  437. for(i=0;i<c && bl;i++,bl=bl->next){
  438. if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
  439. bl_list[bl_list_count++]=bl;
  440. }
  441. }
  442. }
  443. if(bl_list_count>=BL_LIST_MAX) {
  444. if(battle_config.error_log)
  445. printf("map_foreachinarea: *WARNING* block count too many!\n");
  446. }
  447. map_freeblock_lock(); // メモリからの解放を禁止する
  448. for(i=blockcount;i<bl_list_count;i++)
  449. if(bl_list[i]->prev) // 有?かどうかチェック
  450. func(bl_list[i],ap);
  451. map_freeblock_unlock(); // 解放を許可する
  452. va_end(ap);
  453. bl_list_count = blockcount;
  454. }
  455. /*==========================================
  456. * 矩形(x0,y0)-(x1,y1)が(dx,dy)移動した時の
  457. * 領域外になる領域(矩形かL字形)?のobjに
  458. * ?してfuncを呼ぶ
  459. *
  460. * dx,dyは-1,0,1のみとする(どんな値でもいいっぽい?)
  461. *------------------------------------------
  462. */
  463. 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,...) {
  464. int bx,by;
  465. struct block_list *bl=NULL;
  466. va_list ap;
  467. int blockcount=bl_list_count,i,c;
  468. va_start(ap,type);
  469. if(dx==0 || dy==0){
  470. // 矩形領域の場合
  471. if(dx==0){
  472. if(dy<0){
  473. y0=y1+dy+1;
  474. } else {
  475. y1=y0+dy-1;
  476. }
  477. } else if(dy==0){
  478. if(dx<0){
  479. x0=x1+dx+1;
  480. } else {
  481. x1=x0+dx-1;
  482. }
  483. }
  484. if(x0<0) x0=0;
  485. if(y0<0) y0=0;
  486. if(x1>=map[m].xs) x1=map[m].xs-1;
  487. if(y1>=map[m].ys) y1=map[m].ys-1;
  488. for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
  489. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  490. bl = map[m].block[bx+by*map[m].bxs];
  491. c = map[m].block_count[bx+by*map[m].bxs];
  492. for(i=0;i<c && bl;i++,bl=bl->next){
  493. if(bl && type && bl->type!=type)
  494. continue;
  495. if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
  496. bl_list[bl_list_count++]=bl;
  497. }
  498. bl = map[m].block_mob[bx+by*map[m].bxs];
  499. c = map[m].block_mob_count[bx+by*map[m].bxs];
  500. for(i=0;i<c && bl;i++,bl=bl->next){
  501. if(bl && type && bl->type!=type)
  502. continue;
  503. if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
  504. bl_list[bl_list_count++]=bl;
  505. }
  506. }
  507. }
  508. }else{
  509. // L字領域の場合
  510. if(x0<0) x0=0;
  511. if(y0<0) y0=0;
  512. if(x1>=map[m].xs) x1=map[m].xs-1;
  513. if(y1>=map[m].ys) y1=map[m].ys-1;
  514. for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
  515. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  516. bl = map[m].block[bx+by*map[m].bxs];
  517. c = map[m].block_count[bx+by*map[m].bxs];
  518. for(i=0;i<c && bl;i++,bl=bl->next){
  519. if(bl && type && bl->type!=type)
  520. continue;
  521. if((bl) && !(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1))
  522. continue;
  523. if((bl) && ((dx>0 && bl->x<x0+dx) || (dx<0 && bl->x>x1+dx) ||
  524. (dy>0 && bl->y<y0+dy) || (dy<0 && bl->y>y1+dy)) &&
  525. bl_list_count<BL_LIST_MAX)
  526. bl_list[bl_list_count++]=bl;
  527. }
  528. bl = map[m].block_mob[bx+by*map[m].bxs];
  529. c = map[m].block_mob_count[bx+by*map[m].bxs];
  530. for(i=0;i<c && bl;i++,bl=bl->next){
  531. if(bl && type && bl->type!=type)
  532. continue;
  533. if((bl) && !(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1))
  534. continue;
  535. if((bl) && ((dx>0 && bl->x<x0+dx) || (dx<0 && bl->x>x1+dx) ||
  536. (dy>0 && bl->y<y0+dy) || (dy<0 && bl->y>y1+dy)) &&
  537. bl_list_count<BL_LIST_MAX)
  538. bl_list[bl_list_count++]=bl;
  539. }
  540. }
  541. }
  542. }
  543. if(bl_list_count>=BL_LIST_MAX) {
  544. if(battle_config.error_log)
  545. printf("map_foreachinarea: *WARNING* block count too many!\n");
  546. }
  547. map_freeblock_lock(); // メモリからの解放を禁止する
  548. for(i=blockcount;i<bl_list_count;i++)
  549. if(bl_list[i]->prev) { // 有?かどうかチェック
  550. if (bl_list[i]->type == BL_PC
  551. && session[((struct map_session_data *) bl_list[i])->fd] == NULL)
  552. continue;
  553. func(bl_list[i],ap);
  554. }
  555. map_freeblock_unlock(); // 解放を許可する
  556. va_end(ap);
  557. bl_list_count = blockcount;
  558. }
  559. // -- moonsoul (added map_foreachincell which is a rework of map_foreachinarea but
  560. // which only checks the exact single x/y passed to it rather than an
  561. // area radius - may be more useful in some instances)
  562. //
  563. void map_foreachincell(int (*func)(struct block_list*,va_list),int m,int x,int y,int type,...) {
  564. int bx,by;
  565. struct block_list *bl=NULL;
  566. va_list ap;
  567. int blockcount=bl_list_count,i,c;
  568. va_start(ap,type);
  569. by=y/BLOCK_SIZE;
  570. bx=x/BLOCK_SIZE;
  571. if(type==0 || type!=BL_MOB)
  572. {
  573. bl = map[m].block[bx+by*map[m].bxs];
  574. c = map[m].block_count[bx+by*map[m].bxs];
  575. for(i=0;i<c && bl;i++,bl=bl->next)
  576. {
  577. if(type && bl && bl->type!=type)
  578. continue;
  579. if(bl && bl->x==x && bl->y==y && bl_list_count<BL_LIST_MAX)
  580. bl_list[bl_list_count++]=bl;
  581. }
  582. }
  583. if(type==0 || type==BL_MOB)
  584. {
  585. bl = map[m].block_mob[bx+by*map[m].bxs];
  586. c = map[m].block_mob_count[bx+by*map[m].bxs];
  587. for(i=0;i<c && bl;i++,bl=bl->next)
  588. {
  589. if(bl && bl->x==x && bl->y==y && bl_list_count<BL_LIST_MAX)
  590. bl_list[bl_list_count++]=bl;
  591. }
  592. }
  593. if(bl_list_count>=BL_LIST_MAX) {
  594. if(battle_config.error_log)
  595. printf("map_foreachincell: *WARNING* block count too many!\n");
  596. }
  597. map_freeblock_lock(); // メモリからの解放を禁止する
  598. for(i=blockcount;i<bl_list_count;i++)
  599. if(bl_list[i]->prev) // 有?かどうかチェック
  600. func(bl_list[i],ap);
  601. map_freeblock_unlock(); // 解放を許可する
  602. va_end(ap);
  603. bl_list_count = blockcount;
  604. }
  605. /*============================================================
  606. * For checking a path between two points (x0, y0) and (x1, y1)
  607. *------------------------------------------------------------
  608. */
  609. void map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int range,int type,...)
  610. {
  611. /* va_list ap;
  612. double deltax = 0.0;
  613. double deltay = 0.0;
  614. int t, bx, by;
  615. int *xs, *ys;
  616. int blockcount = bl_list_count, i, c;
  617. struct block_list *bl = NULL;
  618. if(m < 0)
  619. return;
  620. va_start(ap,type);
  621. if (x0 < 0) x0 = 0;
  622. if (y0 < 0) y0 = 0;
  623. if (x1 >= map[m].xs) x1 = map[m].xs-1;
  624. if (y1 >= map[m].ys) y1 = map[m].ys-1;
  625. // I'm not finished thinking on it
  626. // but first it might better use a parameter equation
  627. // x=(x1-x0)*t+x0; y=(y1-y0)*t+y0; t=[0,1]
  628. // would not need special case aproximating for infinity/zero slope
  629. // so maybe this way:
  630. // find maximum runindex
  631. int tmax = abs(y1-y0);
  632. if(tmax < abs(x1-x0))
  633. tmax = abs(x1-x0);
  634. xs = (int *)aCallocA(tmax + 1, sizeof(int));
  635. ys = (int *)aCallocA(tmax + 1, sizeof(int));
  636. // pre-calculate delta values for x and y destination
  637. // should speed up cause you don't need to divide in the loop
  638. if(tmax>0)
  639. {
  640. deltax = ((double)(x1-x0)) / ((double)tmax);
  641. deltay = ((double)(y1-y0)) / ((double)tmax);
  642. }
  643. // go along the index
  644. for(t=0; t<=tmax; t++)
  645. {
  646. int x = (int)floor(deltax * (double)t +0.5)+x0;
  647. int y = (int)floor(deltay * (double)t +0.5)+y0;
  648. // the xy pairs of points in line between x0y0 and x1y1
  649. // including start and end point
  650. xs[t] = x;
  651. ys[t] = y;
  652. }
  653. if (type == 0 || type != BL_MOB)
  654. this here is wrong,
  655. there is no check if x0<x1 and y0<y1
  656. but this is not valid in 3 of 4 cases,
  657. so in this case here you check only blocks when shooting to a positive direction
  658. shooting in other directions just do nothing like the skill has failed
  659. if you want to keep this that way then check and swap x0,y0 with x1,y1
  660. for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) {
  661. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  662. bl = map[m].block[bx+by*map[m].bxs];
  663. c = map[m].block_count[bx+by*map[m].bxs];
  664. for(i=0;i<c && bl;i++,bl=bl->next){
  665. if(bl) {
  666. if (type && bl->type!=type)
  667. continue;
  668. for(t=0; t<=tmax; t++)
  669. if(bl->x==xs[t] && bl->y==ys[t] && bl_list_count<BL_LIST_MAX)
  670. bl_list[bl_list_count++]=bl;
  671. }
  672. }
  673. }
  674. }
  675. if(type==0 || type==BL_MOB)
  676. for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
  677. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  678. bl = map[m].block_mob[bx+by*map[m].bxs];
  679. c = map[m].block_mob_count[bx+by*map[m].bxs];
  680. for(i=0;i<c && bl;i++,bl=bl->next){
  681. if(bl) {
  682. for(t=0; t<=tmax; t++)
  683. if(bl->x==xs[t] && bl->y==ys[t] && bl_list_count<BL_LIST_MAX)
  684. bl_list[bl_list_count++]=bl;
  685. }
  686. }
  687. }
  688. }
  689. if(bl_list_count>=BL_LIST_MAX) {
  690. if(battle_config.error_log)
  691. printf("map_foreachinarea: *WARNING* block count too many!\n");
  692. }
  693. map_freeblock_lock(); // メモリからの解放を禁止する
  694. for(i=blockcount;i<bl_list_count;i++)
  695. if(bl_list[i]->prev) // 有?かどうかチェック
  696. func(bl_list[i],ap);
  697. map_freeblock_unlock(); // 解放を許可する
  698. bl_list_count = blockcount;
  699. aFree (xs);
  700. aFree (ys);
  701. va_end(ap);
  702. */
  703. /*
  704. //////////////////////////////////////////////////////////////
  705. //
  706. // sharp shooting 1
  707. //
  708. //////////////////////////////////////////////////////////////
  709. // problem:
  710. // finding targets standing on and within some range of a line
  711. // (t1,t2 t3 and t4 get hit)
  712. //
  713. // target 1
  714. // x t4
  715. // t2
  716. // t3 x
  717. // x
  718. // S
  719. //////////////////////////////////////////////////////////////
  720. // solution 1 (straight forward, but a bit calculation expensive)
  721. // calculating perpendiculars from quesionable mobs to the straight line
  722. // if the mob is hit then depends on the distance to the line
  723. //
  724. // solution 2 (complex, need to handle many cases, but maybe faster)
  725. // make a formula to deside if a given (x,y) is within a shooting area
  726. // the shape can be ie. rectangular or triangular
  727. // if the mob is hit then depends on if the mob is inside or outside the area
  728. // I'm not going to implement this, but if somebody is interested
  729. // in vector algebra, it might be some fun
  730. //////////////////////////////////////////////////////////////
  731. // possible shooting ranges (I prefer the second one)
  732. //////////////////////////////////////////////////////////////
  733. //
  734. // ---------------- ------
  735. // ---------------- ------------
  736. // Sxxxxxxxxxxxxxxxxtarget Sxxxxxxxxxxxxxxxxtarget
  737. // ---------------- ------------
  738. // ---------------- -----
  739. //
  740. // the original code implemented the left structure
  741. // might be not that realistic, so I changed to the other one
  742. // I take "range" as max distance from the line
  743. //////////////////////////////////////////////////////////////
  744. va_list ap;
  745. int i, blockcount = bl_list_count;
  746. struct block_list *bl;
  747. int c1,c2;
  748. ///////////
  749. double deltax,deltay;
  750. double k,kfact,knorm;
  751. double v1,v2,distance;
  752. double xm,ym,rd;
  753. int bx,by,bx0,bx1,by0,by1;
  754. //////////////
  755. // no map
  756. if(m < 0) return;
  757. // xy out of range
  758. if (x0 < 0) x0 = 0;
  759. if (y0 < 0) y0 = 0;
  760. if (x1 >= map[m].xs) x1 = map[m].xs-1;
  761. if (y1 >= map[m].ys) y1 = map[m].ys-1;
  762. ///////////////////////////////
  763. // stuff for a linear equation in xy coord to calculate
  764. // the perpendicular from a block xy to the straight line
  765. deltax = (x1-x0);
  766. deltay = (y1-y0);
  767. kfact = (deltax*deltax+deltay*deltay); // the sqare length of the line
  768. knorm = -deltax*x0-deltay*y0; // the offset vector param
  769. //printf("(%i,%i)(%i,%i) range: %i\n",x0,y0,x1,y1,range);
  770. if(kfact==0) return; // shooting at the standing position should not happen
  771. kfact = 1/kfact; // divide here and multiply in the loop
  772. range *= range; // compare with range^2 so we can skip a sqrt and signs
  773. ///////////////////////////////
  774. // prepare shooting area check
  775. xm = (x1+x0)/2.0;
  776. ym = (y1+y0)/2.0;// middle point on the shooting line
  777. // the sqared radius of a circle around the shooting range
  778. // plus the sqared radius of a block
  779. rd = (x0-xm)*(x0-xm) + (y0-ym)*(y0-ym) + (range*range)
  780. +BLOCK_SIZE*BLOCK_SIZE/2;
  781. // so whenever a block midpoint is within this circle
  782. // some of the block area is possibly within the shooting range
  783. ///////////////////////////////
  784. // what blocks we need to test
  785. // blocks covered by the xy position of begin and end of the line
  786. bx0 = x0/BLOCK_SIZE;
  787. bx1 = x1/BLOCK_SIZE;
  788. by0 = y0/BLOCK_SIZE;
  789. by1 = y1/BLOCK_SIZE;
  790. // swap'em for a smallest-to-biggest run
  791. if(bx0>bx1) swap(bx0,bx1);
  792. if(by0>by1) swap(by0,by1);
  793. // enlarge the block area by a range value and 1
  794. // so we can be sure to process all blocks that might touch the shooting area
  795. // in this case here with BLOCK_SIZE=8 and range=2 it will be only enlarged by 1
  796. // but I implement it anyway just in case that ranges will be larger
  797. // or BLOCK_SIZE smaller in future
  798. i = (range/BLOCK_SIZE+1);//temp value
  799. if(bx0>i) bx0 -=i; else bx0=0;
  800. if(by0>i) by0 -=i; else by0=0;
  801. if(bx1+i<map[m].bxs) bx1 +=i; else bx1=map[m].bxs-1;
  802. if(by1+i<map[m].bys) by1 +=i; else by1=map[m].bys-1;
  803. //printf("run for (%i,%i)(%i,%i)\n",bx0,by0,bx1,by1);
  804. for(bx=bx0; bx<=bx1; bx++)
  805. for(by=by0; by<=by1; by++)
  806. { // block xy
  807. c1 = map[m].block_count[bx+by*map[m].bxs]; // number of elements in the block
  808. c2 = map[m].block_mob_count[bx+by*map[m].bxs]; // number of mobs in the mob block
  809. if( (c1==0) && (c2==0) ) continue; // skip if nothing in the blocks
  810. //printf("block(%i,%i) %i %i\n",bx,by,c1,c2);fflush(stdout);
  811. // test if the mid-point of the block is too far away
  812. // so we could skip the whole block in this case
  813. v1 = (bx*BLOCK_SIZE+BLOCK_SIZE/2-xm)*(bx*BLOCK_SIZE+BLOCK_SIZE/2-xm)
  814. +(by*BLOCK_SIZE+BLOCK_SIZE/2-ym)*(by*BLOCK_SIZE+BLOCK_SIZE/2-ym);
  815. //printf("block(%i,%i) v1=%f rd=%f\n",bx,by,v1,rd);fflush(stdout);
  816. // check for the worst case scenario
  817. if(v1 > rd) continue;
  818. // it seems that the block is at least partially covered by the shooting range
  819. // so we go into it
  820. if(type==0 || type!=BL_MOB) {
  821. bl = map[m].block[bx+by*map[m].bxs]; // a block with the elements
  822. for(i=0;i<c1 && bl;i++,bl=bl->next){ // go through all elements
  823. if( bl && ( !type || bl->type==type ) && bl_list_count<BL_LIST_MAX )
  824. {
  825. // calculate the perpendicular from block xy to the straight line
  826. k = kfact*(deltax*bl->x + deltay*bl->y + knorm);
  827. // check if the perpendicular is within start and end of our line
  828. if(k>=0 && k<=1)
  829. { // calculate the distance
  830. v1 = deltax*k+x0 - bl->x;
  831. v2 = deltay*k+y0 - bl->y;
  832. distance = v1*v1+v2*v2;
  833. // triangular shooting range
  834. if( distance <= range*k )
  835. bl_list[bl_list_count++]=bl;
  836. }
  837. }
  838. }//end for elements
  839. }
  840. if(type==0 || type==BL_MOB) {
  841. bl = map[m].block_mob[bx+by*map[m].bxs]; // and the mob block
  842. for(i=0;i<c2 && bl;i++,bl=bl->next){
  843. if(bl && bl_list_count<BL_LIST_MAX) {
  844. // calculate the perpendicular from block xy to the straight line
  845. k = kfact*(deltax*bl->x + deltay*bl->y + knorm);
  846. //printf("mob: (%i,%i) k=%f ",bl->x,bl->y, k);
  847. // check if the perpendicular is within start and end of our line
  848. if(k>=0 && k<=1)
  849. {
  850. v1 = deltax*k+x0 - bl->x;
  851. v2 = deltay*k+y0 - bl->y;
  852. distance = v1*v1+v2*v2;
  853. //printf("dist: %f",distance);
  854. // triangular shooting range
  855. if( distance <= range*k )
  856. {
  857. //printf(" hit");
  858. bl_list[bl_list_count++]=bl;
  859. }
  860. }
  861. //printf("\n");
  862. }
  863. }//end for mobs
  864. }
  865. }//end for(bx,by)
  866. if(bl_list_count>=BL_LIST_MAX) {
  867. if(battle_config.error_log)
  868. printf("map_foreachinarea: *WARNING* block count too many!\n");
  869. }
  870. va_start(ap,type);
  871. map_freeblock_lock(); // メモリからの解放を禁止する
  872. for(i=blockcount;i<bl_list_count;i++)
  873. if(bl_list[i]->prev) // 有?かどうかチェック
  874. func(bl_list[i],ap);
  875. map_freeblock_unlock(); // 解放を許可する
  876. va_end(ap);
  877. bl_list_count = blockcount;
  878. */
  879. //////////////////////////////////////////////////////////////
  880. //
  881. // sharp shooting 2
  882. //
  883. //////////////////////////////////////////////////////////////
  884. // problem:
  885. // finding targets standing exactly on a line
  886. // (only t1 and t2 get hit)
  887. //
  888. // target 1
  889. // x t4
  890. // t2
  891. // t3 x
  892. // x
  893. // S
  894. //////////////////////////////////////////////////////////////
  895. va_list ap;
  896. int i, blockcount = bl_list_count;
  897. struct block_list *bl;
  898. int c1,c2;
  899. //////////////////////////////////////////////////////////////
  900. // linear parametric equation
  901. // x=(x1-x0)*t+x0; y=(y1-y0)*t+y0; t=[0,1]
  902. //////////////////////////////////////////////////////////////
  903. // linear equation for finding a single line between (x0,y0)->(x1,y1)
  904. // independent of the given xy-values
  905. double dx = 0.0;
  906. double dy = 0.0;
  907. int bx=-1; // initialize block coords to some impossible value
  908. int by=-1;
  909. int t;
  910. ///////////////////////////////
  911. // find maximum runindex
  912. int tmax = abs(y1-y0);
  913. if(tmax < abs(x1-x0))
  914. tmax = abs(x1-x0);
  915. // pre-calculate delta values for x and y destination
  916. // should speed up cause you don't need to divide in the loop
  917. if(tmax>0)
  918. {
  919. dx = ((double)(x1-x0)) / ((double)tmax);
  920. dy = ((double)(y1-y0)) / ((double)tmax);
  921. }
  922. // go along the index
  923. for(t=0; t<=tmax; t++)
  924. { // xy-values of the line including start and end point
  925. int x = (int)floor(dx * (double)t +0.5)+x0;
  926. int y = (int)floor(dy * (double)t +0.5)+y0;
  927. // check the block index of the calculated xy
  928. if( (bx!=x/BLOCK_SIZE) || (by!=y/BLOCK_SIZE) )
  929. { // we have reached a new block
  930. // so we store the current block coordinates
  931. bx = x/BLOCK_SIZE;
  932. by = y/BLOCK_SIZE;
  933. // and process the data
  934. c1 = map[m].block_count[bx+by*map[m].bxs]; // number of elements in the block
  935. c2 = map[m].block_mob_count[bx+by*map[m].bxs]; // number of mobs in the mob block
  936. if( (c1==0) && (c2==0) ) continue; // skip if nothing in the block
  937. if(type==0 || type!=BL_MOB) {
  938. bl = map[m].block[bx+by*map[m].bxs]; // a block with the elements
  939. for(i=0;i<c1 && bl;i++,bl=bl->next){ // go through all elements
  940. if( bl && ( !type || bl->type==type ) && bl_list_count<BL_LIST_MAX )
  941. {
  942. // check if block xy is on the line
  943. if( (bl->x-x0)*(y1-y0) == (bl->y-y0)*(x1-x0) )
  944. // and if it is within start and end point
  945. if( (((x0<=x1)&&(x0<=bl->x)&&(bl->x<=x1)) || ((x0>=x1)&&(x0>=bl->x)&&(bl->x>=x1))) &&
  946. (((y0<=y1)&&(y0<=bl->y)&&(bl->y<=y1)) || ((y0>=y1)&&(y0>=bl->y)&&(bl->y>=y1))) )
  947. bl_list[bl_list_count++]=bl;
  948. }
  949. }//end for elements
  950. }
  951. if(type==0 || type==BL_MOB) {
  952. bl = map[m].block_mob[bx+by*map[m].bxs]; // and the mob block
  953. for(i=0;i<c2 && bl;i++,bl=bl->next){
  954. if(bl && bl_list_count<BL_LIST_MAX) {
  955. // check if mob xy is on the line
  956. if( (bl->x-x0)*(y1-y0) == (bl->y-y0)*(x1-x0) )
  957. // and if it is within start and end point
  958. if( (((x0<=x1)&&(x0<=bl->x)&&(bl->x<=x1)) || ((x0>=x1)&&(x0>=bl->x)&&(bl->x>=x1))) &&
  959. (((y0<=y1)&&(y0<=bl->y)&&(bl->y<=y1)) || ((y0>=y1)&&(y0>=bl->y)&&(bl->y>=y1))) )
  960. bl_list[bl_list_count++]=bl;
  961. }
  962. }//end for mobs
  963. }
  964. }
  965. }//end for index
  966. if(bl_list_count>=BL_LIST_MAX) {
  967. if(battle_config.error_log)
  968. printf("map_foreachinarea: *WARNING* block count too many!\n");
  969. }
  970. va_start(ap,type);
  971. map_freeblock_lock(); // メモリからの解放を禁止する
  972. for(i=blockcount;i<bl_list_count;i++)
  973. if(bl_list[i]->prev) // 有?かどうかチェック
  974. func(bl_list[i],ap);
  975. map_freeblock_unlock(); // 解放を許可する
  976. va_end(ap);
  977. bl_list_count = blockcount;
  978. }
  979. /*==========================================
  980. * 床アイテムやエフェクト用の一時obj割り?て
  981. * object[]への保存とid_db登?まで
  982. *
  983. * bl->idもこの中で設定して問題無い?
  984. *------------------------------------------
  985. */
  986. int map_addobject(struct block_list *bl) {
  987. int i;
  988. if( bl == NULL ){
  989. printf("map_addobject nullpo?\n");
  990. return 0;
  991. }
  992. if(first_free_object_id<2 || first_free_object_id>=MAX_FLOORITEM)
  993. first_free_object_id=2;
  994. for(i=first_free_object_id;i<MAX_FLOORITEM;i++)
  995. if(objects[i]==NULL)
  996. break;
  997. if(i>=MAX_FLOORITEM){
  998. if(battle_config.error_log)
  999. printf("no free object id\n");
  1000. return 0;
  1001. }
  1002. first_free_object_id=i;
  1003. if(last_object_id<i)
  1004. last_object_id=i;
  1005. objects[i]=bl;
  1006. numdb_insert(id_db,i,bl);
  1007. return i;
  1008. }
  1009. /*==========================================
  1010. * 一時objectの解放
  1011. * map_delobjectのfreeしないバ?ジョン
  1012. *------------------------------------------
  1013. */
  1014. int map_delobjectnofree(int id) {
  1015. if(objects[id]==NULL)
  1016. return 0;
  1017. map_delblock(objects[id]);
  1018. numdb_erase(id_db,id);
  1019. // map_freeblock(objects[id]);
  1020. objects[id]=NULL;
  1021. if(first_free_object_id>id)
  1022. first_free_object_id=id;
  1023. while(last_object_id>2 && objects[last_object_id]==NULL)
  1024. last_object_id--;
  1025. return 0;
  1026. }
  1027. /*==========================================
  1028. * 一時objectの解放
  1029. * block_listからの削除、id_dbからの削除
  1030. * object dataのfree、object[]へのNULL代入
  1031. *
  1032. * addとの??性が無いのが?になる
  1033. *------------------------------------------
  1034. */
  1035. int map_delobject(int id) {
  1036. struct block_list *obj = objects[id];
  1037. if(obj==NULL)
  1038. return 0;
  1039. map_delobjectnofree(id);
  1040. map_freeblock(obj);
  1041. return 0;
  1042. }
  1043. /*==========================================
  1044. * 全一時obj相手にfuncを呼ぶ
  1045. *
  1046. *------------------------------------------
  1047. */
  1048. void map_foreachobject(int (*func)(struct block_list*,va_list),int type,...) {
  1049. int i;
  1050. int blockcount=bl_list_count;
  1051. va_list ap;
  1052. va_start(ap,type);
  1053. for(i=2;i<=last_object_id;i++){
  1054. if(objects[i]){
  1055. if(type && objects[i]->type!=type)
  1056. continue;
  1057. if(bl_list_count>=BL_LIST_MAX) {
  1058. if(battle_config.error_log)
  1059. printf("map_foreachobject: too many block !\n");
  1060. }
  1061. else
  1062. bl_list[bl_list_count++]=objects[i];
  1063. }
  1064. }
  1065. map_freeblock_lock();
  1066. for(i=blockcount;i<bl_list_count;i++)
  1067. if( bl_list[i]->prev || bl_list[i]->next )
  1068. func(bl_list[i],ap);
  1069. map_freeblock_unlock();
  1070. va_end(ap);
  1071. bl_list_count = blockcount;
  1072. }
  1073. /*==========================================
  1074. * 床アイテムを消す
  1075. *
  1076. * data==0の時はtimerで消えた時
  1077. * data!=0の時は拾う等で消えた時として動作
  1078. *
  1079. * 後者は、map_clearflooritem(id)へ
  1080. * map.h?で#defineしてある
  1081. *------------------------------------------
  1082. */
  1083. int map_clearflooritem_timer(int tid,unsigned int tick,int id,int data) {
  1084. struct flooritem_data *fitem=NULL;
  1085. fitem = (struct flooritem_data *)objects[id];
  1086. if(fitem==NULL || fitem->bl.type!=BL_ITEM || (!data && fitem->cleartimer != tid)){
  1087. if(battle_config.error_log)
  1088. printf("map_clearflooritem_timer : error\n");
  1089. return 1;
  1090. }
  1091. if(data)
  1092. delete_timer(fitem->cleartimer,map_clearflooritem_timer);
  1093. else if(fitem->item_data.card[0] == (short)0xff00)
  1094. intif_delete_petdata(*((long *)(&fitem->item_data.card[1])));
  1095. clif_clearflooritem(fitem,0);
  1096. map_delobject(fitem->bl.id);
  1097. return 0;
  1098. }
  1099. /*==========================================
  1100. * (m,x,y)の周?rangeマス?の空き(=侵入可能)cellの
  1101. * ?から適?なマス目の座標をx+(y<<16)で返す
  1102. *
  1103. * 現?range=1でアイテムドロップ用途のみ
  1104. *------------------------------------------
  1105. */
  1106. int map_searchrandfreecell(int m,int x,int y,int range) {
  1107. int free_cell,i,j;
  1108. for(free_cell=0,i=-range;i<=range;i++){
  1109. if(i+y<0 || i+y>=map[m].ys)
  1110. continue;
  1111. for(j=-range;j<=range;j++){
  1112. if(j+x<0 || j+x>=map[m].xs)
  1113. continue;
  1114. if(map_getcell(m,j+x,i+y,CELL_CHKNOPASS))
  1115. continue;
  1116. free_cell++;
  1117. }
  1118. }
  1119. if(free_cell==0)
  1120. return -1;
  1121. free_cell=rand()%free_cell;
  1122. for(i=-range;i<=range;i++){
  1123. if(i+y<0 || i+y>=map[m].ys)
  1124. continue;
  1125. for(j=-range;j<=range;j++){
  1126. if(j+x<0 || j+x>=map[m].xs)
  1127. continue;
  1128. if(map_getcell(m,j+x,i+y,CELL_CHKNOPASS))
  1129. continue;
  1130. if(free_cell==0){
  1131. x+=j;
  1132. y+=i;
  1133. i=range+1;
  1134. break;
  1135. }
  1136. free_cell--;
  1137. }
  1138. }
  1139. return x+(y<<16);
  1140. }
  1141. /*==========================================
  1142. * (m,x,y)を中心に3x3以?に床アイテム設置
  1143. *
  1144. * item_dataはamount以外をcopyする
  1145. *------------------------------------------
  1146. */
  1147. int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,struct map_session_data *first_sd,
  1148. struct map_session_data *second_sd,struct map_session_data *third_sd,int type) {
  1149. int xy,r;
  1150. unsigned int tick;
  1151. struct flooritem_data *fitem=NULL;
  1152. nullpo_retr(0, item_data);
  1153. if((xy=map_searchrandfreecell(m,x,y,1))<0)
  1154. return 0;
  1155. r=rand();
  1156. fitem = (struct flooritem_data *)aCalloc(1,sizeof(*fitem));
  1157. fitem->bl.type=BL_ITEM;
  1158. fitem->bl.prev = fitem->bl.next = NULL;
  1159. fitem->bl.m=m;
  1160. fitem->bl.x=xy&0xffff;
  1161. fitem->bl.y=(xy>>16)&0xffff;
  1162. fitem->first_get_id = 0;
  1163. fitem->first_get_tick = 0;
  1164. fitem->second_get_id = 0;
  1165. fitem->second_get_tick = 0;
  1166. fitem->third_get_id = 0;
  1167. fitem->third_get_tick = 0;
  1168. fitem->bl.id = map_addobject(&fitem->bl);
  1169. if(fitem->bl.id==0){
  1170. aFree(fitem);
  1171. return 0;
  1172. }
  1173. tick = gettick();
  1174. if(first_sd) {
  1175. fitem->first_get_id = first_sd->bl.id;
  1176. if(type)
  1177. fitem->first_get_tick = tick + battle_config.mvp_item_first_get_time;
  1178. else
  1179. fitem->first_get_tick = tick + battle_config.item_first_get_time;
  1180. }
  1181. if(second_sd) {
  1182. fitem->second_get_id = second_sd->bl.id;
  1183. if(type)
  1184. fitem->second_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time;
  1185. else
  1186. fitem->second_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time;
  1187. }
  1188. if(third_sd) {
  1189. fitem->third_get_id = third_sd->bl.id;
  1190. if(type)
  1191. 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;
  1192. else
  1193. fitem->third_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time + battle_config.item_third_get_time;
  1194. }
  1195. memcpy(&fitem->item_data,item_data,sizeof(*item_data));
  1196. fitem->item_data.amount=amount;
  1197. fitem->subx=(r&3)*3+3;
  1198. fitem->suby=((r>>2)&3)*3+3;
  1199. fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0);
  1200. map_addblock(&fitem->bl);
  1201. clif_dropflooritem(fitem);
  1202. return fitem->bl.id;
  1203. }
  1204. /*==========================================
  1205. * charid_dbへ追加(返信待ちがあれば返信)
  1206. *------------------------------------------
  1207. */
  1208. void map_addchariddb(int charid, char *name) {
  1209. struct charid2nick *p=NULL;
  1210. int req=0;
  1211. p = (struct charid2nick*)numdb_search(charid_db,charid);
  1212. if(p==NULL){ // デ?タベ?スにない
  1213. p = (struct charid2nick *)aCallocA(1,sizeof(struct charid2nick));
  1214. p->req_id=0;
  1215. }else
  1216. numdb_erase(charid_db,charid);
  1217. req=p->req_id;
  1218. memcpy(p->nick,name,24);
  1219. p->req_id=0;
  1220. numdb_insert(charid_db,charid,p);
  1221. if(req){ // 返信待ちがあれば返信
  1222. struct map_session_data *sd = map_id2sd(req);
  1223. if(sd!=NULL)
  1224. clif_solved_charname(sd,charid);
  1225. }
  1226. }
  1227. /*==========================================
  1228. * charid_dbへ追加(返信要求のみ)
  1229. *------------------------------------------
  1230. */
  1231. int map_reqchariddb(struct map_session_data * sd,int charid) {
  1232. struct charid2nick *p=NULL;
  1233. nullpo_retr(0, sd);
  1234. p = (struct charid2nick*)numdb_search(charid_db,charid);
  1235. if(p!=NULL) // デ?タベ?スにすでにある
  1236. return 0;
  1237. p = (struct charid2nick *)aCalloc(1,sizeof(struct charid2nick));
  1238. p->req_id=sd->bl.id;
  1239. numdb_insert(charid_db,charid,p);
  1240. return 0;
  1241. }
  1242. /*==========================================
  1243. * id_dbへblを追加
  1244. *------------------------------------------
  1245. */
  1246. void map_addiddb(struct block_list *bl) {
  1247. nullpo_retv(bl);
  1248. numdb_insert(id_db,bl->id,bl);
  1249. }
  1250. /*==========================================
  1251. * id_dbからblを削除
  1252. *------------------------------------------
  1253. */
  1254. void map_deliddb(struct block_list *bl) {
  1255. nullpo_retv(bl);
  1256. numdb_erase(id_db,bl->id);
  1257. }
  1258. /*==========================================
  1259. * nick_dbへsdを追加
  1260. *------------------------------------------
  1261. */
  1262. void map_addnickdb(struct map_session_data *sd) {
  1263. nullpo_retv(sd);
  1264. strdb_insert(nick_db,sd->status.name,sd);
  1265. }
  1266. /*==========================================
  1267. * PCのquit?理 map.c?分
  1268. *
  1269. * quit?理の主?が違うような?もしてきた
  1270. *------------------------------------------
  1271. */
  1272. int map_quit(struct map_session_data *sd) {
  1273. nullpo_retr(0, sd);
  1274. if(!sd->state.waitingdisconnect) {
  1275. if (sd->state.event_disconnect) {
  1276. if (script_config.event_script_type == 0) {
  1277. struct npc_data *npc;
  1278. if ((npc = npc_name2id(script_config.logout_event_name))) {
  1279. run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLogoutNPC
  1280. sprintf (tmp_output, "Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.logout_event_name);
  1281. ShowStatus(tmp_output);
  1282. }
  1283. } else {
  1284. sprintf (tmp_output, "%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
  1285. npc_event_doall_id(script_config.logout_event_name, sd->bl.id), script_config.logout_event_name);
  1286. ShowStatus(tmp_output);
  1287. }
  1288. }
  1289. if(sd->chatID) // チャットから出る
  1290. chat_leavechat(sd);
  1291. if(sd->trade_partner) // 取引を中?する
  1292. trade_tradecancel(sd);
  1293. if(sd->party_invite>0) // パ?ティ?誘を拒否する
  1294. party_reply_invite(sd,sd->party_invite_account,0);
  1295. if(sd->guild_invite>0) // ギルド?誘を拒否する
  1296. guild_reply_invite(sd,sd->guild_invite,0);
  1297. if(sd->guild_alliance>0) // ギルド同盟?誘を拒否する
  1298. guild_reply_reqalliance(sd,sd->guild_alliance_account,0);
  1299. party_send_logout(sd); // パ?ティのログアウトメッセ?ジ送信
  1300. guild_send_memberinfoshort(sd,0); // ギルドのログアウトメッセ?ジ送信
  1301. pc_cleareventtimer(sd); // イベントタイマを破棄する
  1302. if(sd->state.storage_flag)
  1303. storage_guild_storage_quit(sd,0);
  1304. else
  1305. storage_storage_quit(sd); // 倉庫を開いてるなら保存する
  1306. // check if we've been authenticated [celest]
  1307. if (sd->state.auth)
  1308. skill_castcancel(&sd->bl,0); // 詠唱を中?する
  1309. skill_stop_dancing(&sd->bl,1);// ダンス/演奏中?
  1310. if(sd->sc_data && sd->sc_data[SC_BERSERK].timer!=-1) //バ?サ?ク中の終了はHPを100に
  1311. sd->status.hp = 100;
  1312. status_change_clear(&sd->bl,1); // ステ?タス異常を解除する
  1313. skill_clear_unitgroup(&sd->bl); // スキルユニットグル?プの削除
  1314. skill_cleartimerskill(&sd->bl);
  1315. // check if we've been authenticated [celest]
  1316. if (sd->state.auth) {
  1317. pc_stop_walking(sd,0);
  1318. pc_stopattack(sd);
  1319. pc_delinvincibletimer(sd);
  1320. }
  1321. pc_delspiritball(sd,sd->spiritball,1);
  1322. skill_gangsterparadise(sd,0);
  1323. skill_unit_move(&sd->bl,gettick(),0);
  1324. if (sd->state.auth)
  1325. status_calc_pc(sd,4);
  1326. // skill_clear_unitgroup(&sd->bl); // [Sara-chan]
  1327. clif_clearchar_area(&sd->bl,2);
  1328. if(sd->status.pet_id && sd->pd) {
  1329. pet_lootitem_drop(sd->pd,sd);
  1330. pet_remove_map(sd);
  1331. if(sd->pet.intimate <= 0) {
  1332. intif_delete_petdata(sd->status.pet_id);
  1333. sd->status.pet_id = 0;
  1334. sd->pd = NULL;
  1335. sd->petDB = NULL;
  1336. }
  1337. else
  1338. intif_save_petdata(sd->status.account_id,&sd->pet);
  1339. }
  1340. if(pc_isdead(sd))
  1341. pc_setrestartvalue(sd,2);
  1342. pc_makesavestatus(sd);
  1343. chrif_save(sd);
  1344. storage_storage_dirty(sd);
  1345. storage_storage_save(sd);
  1346. map_delblock(&sd->bl);
  1347. }
  1348. if( sd->npc_stackbuf && sd->npc_stackbuf != NULL) {
  1349. aFree( sd->npc_stackbuf );
  1350. sd->npc_stackbuf = NULL;
  1351. }
  1352. #ifndef TXT_ONLY
  1353. chrif_char_offline(sd);
  1354. #endif
  1355. {
  1356. void *p = numdb_search(charid_db,sd->status.char_id);
  1357. if(p) {
  1358. numdb_erase(charid_db,sd->status.char_id);
  1359. aFree(p);
  1360. }
  1361. }
  1362. strdb_erase(nick_db,sd->status.name);
  1363. numdb_erase(charid_db,sd->status.char_id);
  1364. numdb_erase(id_db,sd->bl.id);
  1365. aFree(sd->reg);
  1366. aFree(sd->regstr);
  1367. return 0;
  1368. }
  1369. /*==========================================
  1370. * id番?のPCを探す。居なければNULL
  1371. *------------------------------------------
  1372. */
  1373. struct map_session_data * map_id2sd(int id) {
  1374. // remove search from db, because:
  1375. // 1 - all players, npc, items and mob are in this db (to search, it's not speed, and search in session is more sure)
  1376. // 2 - DB seems not always correct. Sometimes, when a player disconnects, its id (account value) is not removed and structure
  1377. // point to a memory area that is not more a session_data and value are incorrect (or out of available memory) -> crash
  1378. // replaced by searching in all session.
  1379. // by searching in session, we are sure that fd, session, and account exist.
  1380. /*
  1381. struct block_list *bl;
  1382. bl=numdb_search(id_db,id);
  1383. if(bl && bl->type==BL_PC)
  1384. return (struct map_session_data*)bl;
  1385. return NULL;
  1386. */
  1387. int i;
  1388. struct map_session_data *sd;
  1389. if (id <= 0) return 0;
  1390. for(i = 0; i < fd_max; i++)
  1391. if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd->bl.id == id)
  1392. return sd;
  1393. return NULL;
  1394. }
  1395. /*==========================================
  1396. * char_id番?の名前を探す
  1397. *------------------------------------------
  1398. */
  1399. char * map_charid2nick(int id) {
  1400. struct charid2nick *p = (struct charid2nick*)numdb_search(charid_db,id);
  1401. if(p==NULL)
  1402. return NULL;
  1403. if(p->req_id!=0)
  1404. return NULL;
  1405. return p->nick;
  1406. }
  1407. struct map_session_data * map_charid2sd(int id) {
  1408. int i;
  1409. struct map_session_data *sd;
  1410. if (id <= 0) return 0;
  1411. for(i = 0; i < fd_max; i++)
  1412. if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd->status.char_id == id)
  1413. return sd;
  1414. return NULL;
  1415. }
  1416. /*==========================================
  1417. * Search session data from a nick name
  1418. * (without sensitive case if necessary)
  1419. * return map_session_data pointer or NULL
  1420. *------------------------------------------
  1421. */
  1422. struct map_session_data * map_nick2sd(char *nick) {
  1423. int i, quantity=0, nicklen;
  1424. struct map_session_data *sd = NULL;
  1425. struct map_session_data *pl_sd = NULL;
  1426. if (nick == NULL)
  1427. return NULL;
  1428. nicklen = strlen(nick);
  1429. for (i = 0; i < fd_max; i++) {
  1430. if (session[i] && (pl_sd = (struct map_session_data*)session[i]->session_data) && pl_sd->state.auth)
  1431. // Without case sensitive check (increase the number of similar character names found)
  1432. if (strnicmp(pl_sd->status.name, nick, nicklen) == 0) {
  1433. // Strict comparison (if found, we finish the function immediatly with correct value)
  1434. if (strcmp(pl_sd->status.name, nick) == 0)
  1435. return pl_sd;
  1436. quantity++;
  1437. sd = pl_sd;
  1438. }
  1439. }
  1440. // Here, the exact character name is not found
  1441. // We return the found index of a similar account ONLY if there is 1 similar character
  1442. if (quantity == 1)
  1443. return sd;
  1444. // Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found
  1445. return NULL;
  1446. }
  1447. /*==========================================
  1448. * id番?の物を探す
  1449. * 一時objectの場合は配列を引くのみ
  1450. *------------------------------------------
  1451. */
  1452. struct block_list * map_id2bl(int id)
  1453. {
  1454. struct block_list *bl=NULL;
  1455. if(id >= 0 && id < sizeof(objects)/sizeof(objects[0]))
  1456. bl = objects[id];
  1457. else
  1458. bl = (struct block_list*)numdb_search(id_db,id);
  1459. return bl;
  1460. }
  1461. /*==========================================
  1462. * id_db?の全てにfuncを?行
  1463. *------------------------------------------
  1464. */
  1465. int map_foreachiddb(int (*func)(void*,void*,va_list),...) {
  1466. va_list ap;
  1467. va_start(ap,func);
  1468. numdb_foreach(id_db,func,ap);
  1469. va_end(ap);
  1470. return 0;
  1471. }
  1472. /*==========================================
  1473. * map.npcへ追加 (warp等の領域持ちのみ)
  1474. *------------------------------------------
  1475. */
  1476. int map_addnpc(int m,struct npc_data *nd) {
  1477. int i;
  1478. if(m<0 || m>=map_num)
  1479. return -1;
  1480. for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++)
  1481. if(map[m].npc[i]==NULL)
  1482. break;
  1483. if(i==MAX_NPC_PER_MAP){
  1484. if(battle_config.error_log)
  1485. printf("too many NPCs in one map %s\n",map[m].name);
  1486. return -1;
  1487. }
  1488. if(i==map[m].npc_num){
  1489. map[m].npc_num++;
  1490. }
  1491. nullpo_retr(0, nd);
  1492. map[m].npc[i]=nd;
  1493. nd->n = i;
  1494. numdb_insert(id_db,nd->bl.id,nd);
  1495. return i;
  1496. }
  1497. void map_removenpc(void) {
  1498. int i,m,n=0;
  1499. for(m=0;m<map_num;m++) {
  1500. for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++) {
  1501. if(map[m].npc[i]!=NULL) {
  1502. clif_clearchar_area(&map[m].npc[i]->bl,2);
  1503. map_delblock(&map[m].npc[i]->bl);
  1504. numdb_erase(id_db,map[m].npc[i]->bl.id);
  1505. if(map[m].npc[i]->bl.subtype==SCRIPT) {
  1506. aFree(map[m].npc[i]->u.scr.script);
  1507. aFree(map[m].npc[i]->u.scr.label_list);
  1508. }
  1509. aFree(map[m].npc[i]);
  1510. map[m].npc[i] = NULL;
  1511. n++;
  1512. }
  1513. }
  1514. }
  1515. sprintf(tmp_output,"Successfully removed and freed from memory '"CL_WHITE"%d"CL_RESET"' NPCs.\n",n);
  1516. ShowStatus(tmp_output);
  1517. }
  1518. /*==========================================
  1519. * map名からmap番?へ?換
  1520. *------------------------------------------
  1521. */
  1522. int map_mapname2mapid(char *name) {
  1523. struct map_data *md=NULL;
  1524. md = (struct map_data*)strdb_search(map_db,name);
  1525. #ifdef USE_AFM
  1526. // If we can't find the .gat map try .afm instead [celest]
  1527. if(md==NULL && strstr(name,".gat")) {
  1528. char *afm_name = strdup(name);
  1529. strcpy(&afm_name[strlen(name) - 3], "afm");
  1530. md = (struct map_data*)strdb_search(map_db,afm_name);
  1531. }
  1532. #endif
  1533. if(md==NULL || md->gat==NULL)
  1534. return -1;
  1535. return md->m;
  1536. }
  1537. /*==========================================
  1538. * 他鯖map名からip,port?換
  1539. *------------------------------------------
  1540. */
  1541. int map_mapname2ipport(char *name,int *ip,int *port) {
  1542. struct map_data_other_server *mdos=NULL;
  1543. mdos = (struct map_data_other_server*)strdb_search(map_db,name);
  1544. if(mdos==NULL || mdos->gat)
  1545. return -1;
  1546. *ip=mdos->ip;
  1547. *port=mdos->port;
  1548. return 0;
  1549. }
  1550. /*==========================================
  1551. *
  1552. *------------------------------------------
  1553. */
  1554. int map_check_dir(int s_dir,int t_dir) {
  1555. if(s_dir == t_dir)
  1556. return 0;
  1557. switch(s_dir) {
  1558. case 0:
  1559. if(t_dir == 7 || t_dir == 1 || t_dir == 0)
  1560. return 0;
  1561. break;
  1562. case 1:
  1563. if(t_dir == 0 || t_dir == 2 || t_dir == 1)
  1564. return 0;
  1565. break;
  1566. case 2:
  1567. if(t_dir == 1 || t_dir == 3 || t_dir == 2)
  1568. return 0;
  1569. break;
  1570. case 3:
  1571. if(t_dir == 2 || t_dir == 4 || t_dir == 3)
  1572. return 0;
  1573. break;
  1574. case 4:
  1575. if(t_dir == 3 || t_dir == 5 || t_dir == 4)
  1576. return 0;
  1577. break;
  1578. case 5:
  1579. if(t_dir == 4 || t_dir == 6 || t_dir == 5)
  1580. return 0;
  1581. break;
  1582. case 6:
  1583. if(t_dir == 5 || t_dir == 7 || t_dir == 6)
  1584. return 0;
  1585. break;
  1586. case 7:
  1587. if(t_dir == 6 || t_dir == 0 || t_dir == 7)
  1588. return 0;
  1589. break;
  1590. }
  1591. return 1;
  1592. }
  1593. /*==========================================
  1594. * 彼我の方向を計算
  1595. *------------------------------------------
  1596. */
  1597. int map_calc_dir( struct block_list *src,int x,int y) {
  1598. int dir=0;
  1599. int dx,dy;
  1600. nullpo_retr(0, src);
  1601. dx=x-src->x;
  1602. dy=y-src->y;
  1603. if( dx==0 && dy==0 ){ // 彼我の場所一致
  1604. dir=0; // 上
  1605. }else if( dx>=0 && dy>=0 ){ // 方向的に右上
  1606. dir=7; // 右上
  1607. if( dx*3-1<dy ) dir=0; // 上
  1608. if( dx>dy*3 ) dir=6; // 右
  1609. }else if( dx>=0 && dy<=0 ){ // 方向的に右下
  1610. dir=5; // 右下
  1611. if( dx*3-1<-dy ) dir=4; // 下
  1612. if( dx>-dy*3 ) dir=6; // 右
  1613. }else if( dx<=0 && dy<=0 ){ // 方向的に左下
  1614. dir=3; // 左下
  1615. if( dx*3+1>dy ) dir=4; // 下
  1616. if( dx<dy*3 ) dir=2; // 左
  1617. }else{ // 方向的に左上
  1618. dir=1; // 左上
  1619. if( -dx*3-1<dy ) dir=0; // 上
  1620. if( -dx>dy*3 ) dir=2; // 左
  1621. }
  1622. return dir;
  1623. }
  1624. // gat系
  1625. /*==========================================
  1626. * (m,x,y)の状態を調べる
  1627. *------------------------------------------
  1628. */
  1629. int map_getcell(int m,int x,int y,cell_t cellchk)
  1630. {
  1631. return (m < 0 || m > MAX_MAP_PER_SERVER) ? 0 : map_getcellp(&map[m],x,y,cellchk);
  1632. }
  1633. int map_getcellp(struct map_data* m,int x,int y,cell_t cellchk)
  1634. {
  1635. int type;
  1636. nullpo_ret(m);
  1637. if(x<0 || x>=m->xs-1 || y<0 || y>=m->ys-1)
  1638. {
  1639. if(cellchk==CELL_CHKNOPASS) return 1;
  1640. return 0;
  1641. }
  1642. type = m->gat[x+y*m->xs];
  1643. if (cellchk<0x10)
  1644. type &= CELL_MASK;
  1645. switch(cellchk)
  1646. {
  1647. case CELL_CHKPASS:
  1648. return (type!=1 && type!=5);
  1649. case CELL_CHKNOPASS:
  1650. return (type==1 || type==5);
  1651. case CELL_CHKWALL:
  1652. return (type==1);
  1653. case CELL_CHKWATER:
  1654. return (type==3);
  1655. case CELL_CHKGROUND:
  1656. return (type==5);
  1657. case CELL_GETTYPE:
  1658. return type;
  1659. case CELL_CHKNPC:
  1660. return (type&CELL_NPC);
  1661. case CELL_CHKBASILICA:
  1662. return (type&CELL_BASILICA);
  1663. default:
  1664. return 0;
  1665. }
  1666. }
  1667. /*==========================================
  1668. * (m,x,y)の状態を設定する
  1669. *------------------------------------------
  1670. */
  1671. void map_setcell(int m,int x,int y,int cell)
  1672. {
  1673. int j;
  1674. if(x<0 || x>=map[m].xs || y<0 || y>=map[m].ys)
  1675. return;
  1676. j=x+y*map[m].xs;
  1677. switch (cell) {
  1678. case CELL_SETNPC:
  1679. map[m].gat[j] |= CELL_NPC;
  1680. break;
  1681. case CELL_SETBASILICA:
  1682. map[m].gat[j] |= CELL_BASILICA;
  1683. break;
  1684. case CELL_CLRBASILICA:
  1685. map[m].gat[j] &= ~CELL_BASILICA;
  1686. break;
  1687. default:
  1688. map[m].gat[j] = (map[m].gat[j]&~CELL_MASK) + cell;
  1689. break;
  1690. }
  1691. }
  1692. /*==========================================
  1693. * 他鯖管理のマップをdbに追加
  1694. *------------------------------------------
  1695. */
  1696. int map_setipport(char *name,unsigned long ip,int port) {
  1697. struct map_data *md=NULL;
  1698. struct map_data_other_server *mdos=NULL;
  1699. md = (struct map_data*)strdb_search(map_db,name);
  1700. if(md==NULL){ // not exist -> add new data
  1701. mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server));
  1702. memcpy(mdos->name,name,24);
  1703. mdos->gat = NULL;
  1704. mdos->ip = ip;
  1705. mdos->port = port;
  1706. mdos->map = NULL;
  1707. strdb_insert(map_db,mdos->name,mdos);
  1708. } else if(md->gat){
  1709. if(ip!=clif_getip() || port!=clif_getport()){
  1710. // 読み込んでいたけど、担当外になったマップ
  1711. mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server));
  1712. memcpy(mdos->name,name,24);
  1713. mdos->gat = NULL;
  1714. mdos->ip = ip;
  1715. mdos->port = port;
  1716. mdos->map = md;
  1717. strdb_insert(map_db,mdos->name,mdos);
  1718. // printf("from char server : %s -> %08lx:%d\n",name,ip,port);
  1719. } else {
  1720. // 読み込んでいて、担当になったマップ(何もしない)
  1721. ;
  1722. }
  1723. } else {
  1724. mdos=(struct map_data_other_server *)md;
  1725. if(ip == clif_getip() && port == clif_getport()) {
  1726. // 自分の担当になったマップ
  1727. if(mdos->map == NULL) {
  1728. // 読み込んでいないので終了する
  1729. printf("map_setipport : %s is not loaded.\n",name);
  1730. exit(1);
  1731. } else {
  1732. // 読み込んでいるので置き換える
  1733. md = mdos->map;
  1734. aFree(mdos);
  1735. strdb_insert(map_db,md->name,md);
  1736. }
  1737. } else {
  1738. // 他の鯖の担当マップなので置き換えるだけ
  1739. mdos->ip = ip;
  1740. mdos->port = port;
  1741. }
  1742. }
  1743. return 0;
  1744. }
  1745. /*==========================================
  1746. * 他鯖管理のマップを全て削除
  1747. *------------------------------------------
  1748. */
  1749. int map_eraseallipport_sub(void *key,void *data,va_list va) {
  1750. struct map_data_other_server *mdos = (struct map_data_other_server*)data;
  1751. if(mdos->gat == NULL && mdos->map == NULL) {
  1752. strdb_erase(map_db,key);
  1753. aFree(mdos);
  1754. }
  1755. return 0;
  1756. }
  1757. int map_eraseallipport(void) {
  1758. strdb_foreach(map_db,map_eraseallipport_sub);
  1759. return 1;
  1760. }
  1761. /*==========================================
  1762. * 他鯖管理のマップをdbから削除
  1763. *------------------------------------------
  1764. */
  1765. int map_eraseipport(char *name,unsigned long ip,int port)
  1766. {
  1767. struct map_data *md;
  1768. struct map_data_other_server *mdos;
  1769. // unsigned char *p=(unsigned char *)&ip;
  1770. md=(struct map_data *) strdb_search(map_db,name);
  1771. if(md){
  1772. if(md->gat) // local -> check data
  1773. return 0;
  1774. else {
  1775. mdos=(struct map_data_other_server *)md;
  1776. if(mdos->ip==ip && mdos->port == port) {
  1777. if(mdos->map) {
  1778. // このマップ鯖でも読み込んでいるので移動できる
  1779. return 1; // 呼び出し元で chrif_sendmap() をする
  1780. } else {
  1781. strdb_erase(map_db,name);
  1782. aFree(mdos);
  1783. }
  1784. // if(battle_config.etc_log)
  1785. // printf("erase map %s %d.%d.%d.%d:%d\n",name,p[0],p[1],p[2],p[3],port);
  1786. }
  1787. }
  1788. }
  1789. return 0;
  1790. }
  1791. // 初期化周り
  1792. /*==========================================
  1793. * 水場高さ設定
  1794. *------------------------------------------
  1795. */
  1796. static struct waterlist_ {
  1797. char mapname[24];
  1798. int waterheight;
  1799. } *waterlist=NULL;
  1800. #define NO_WATER 1000000
  1801. static int map_waterheight(char *mapname) {
  1802. if(waterlist){
  1803. int i;
  1804. for(i=0;waterlist[i].mapname[0] && i < MAX_MAP_PER_SERVER;i++)
  1805. if(strcmp(waterlist[i].mapname,mapname)==0)
  1806. return waterlist[i].waterheight;
  1807. }
  1808. return NO_WATER;
  1809. }
  1810. static void map_readwater(char *watertxt) {
  1811. char line[1024],w1[1024];
  1812. FILE *fp=NULL;
  1813. int n=0;
  1814. fp=fopen(watertxt,"r");
  1815. if(fp==NULL){
  1816. printf("file not found: %s\n",watertxt);
  1817. return;
  1818. }
  1819. if(waterlist==NULL)
  1820. waterlist = (struct waterlist_*)aCallocA(MAX_MAP_PER_SERVER,sizeof(*waterlist));
  1821. while(fgets(line,1020,fp) && n < MAX_MAP_PER_SERVER){
  1822. int wh,count;
  1823. if(line[0] == '/' && line[1] == '/')
  1824. continue;
  1825. if((count=sscanf(line,"%s%d",w1,&wh)) < 1){
  1826. continue;
  1827. }
  1828. strcpy(waterlist[n].mapname,w1);
  1829. if(count >= 2)
  1830. waterlist[n].waterheight = wh;
  1831. else
  1832. waterlist[n].waterheight = 3;
  1833. n++;
  1834. }
  1835. fclose(fp);
  1836. }
  1837. /*==========================================
  1838. * マップキャッシュに追加する
  1839. *===========================================*/
  1840. // マップキャッシュの最大値
  1841. #define MAX_MAP_CACHE 768
  1842. //各マップごとの最小限情報を入れるもの、READ_FROM_BITMAP用
  1843. struct map_cache_info {
  1844. char fn[32];//ファイル名
  1845. int xs,ys; //幅と高さ
  1846. int water_height;
  1847. int pos; // データが入れてある場所
  1848. int compressed; // zilb通せるようにする為の予約
  1849. int compressed_len; // zilb通せるようにする為の予約
  1850. }; // 56 byte
  1851. struct map_cache_head {
  1852. int sizeof_header;
  1853. int sizeof_map;
  1854. // 上の2つ改変不可
  1855. int nmaps; // マップの個数
  1856. int filesize;
  1857. };
  1858. struct {
  1859. struct map_cache_head head;
  1860. struct map_cache_info *map;
  1861. FILE *fp;
  1862. int dirty;
  1863. } map_cache;
  1864. static int map_cache_open(char *fn);
  1865. static void map_cache_close(void);
  1866. static int map_cache_read(struct map_data *m);
  1867. static int map_cache_write(struct map_data *m);
  1868. static int map_cache_open(char *fn)
  1869. {
  1870. atexit(map_cache_close);
  1871. if(map_cache.fp) {
  1872. map_cache_close();
  1873. }
  1874. map_cache.fp = fopen(fn,"r+b");
  1875. if(map_cache.fp) {
  1876. fread(&map_cache.head,1,sizeof(struct map_cache_head),map_cache.fp);
  1877. fseek(map_cache.fp,0,SEEK_END);
  1878. if(
  1879. map_cache.head.sizeof_header == sizeof(struct map_cache_head) &&
  1880. map_cache.head.sizeof_map == sizeof(struct map_cache_info) &&
  1881. map_cache.head.nmaps == MAX_MAP_CACHE &&
  1882. map_cache.head.filesize == ftell(map_cache.fp)
  1883. ) {
  1884. // キャッシュ読み込み成功
  1885. map_cache.map = (struct map_cache_info *) aMalloc(sizeof(struct map_cache_info) * map_cache.head.nmaps);
  1886. fseek(map_cache.fp,sizeof(struct map_cache_head),SEEK_SET);
  1887. fread(map_cache.map,sizeof(struct map_cache_info),map_cache.head.nmaps,map_cache.fp);
  1888. return 1;
  1889. }
  1890. fclose(map_cache.fp);
  1891. }
  1892. // 読み込みに失敗したので新規に作成する
  1893. map_cache.fp = fopen(fn,"wb");
  1894. if(map_cache.fp) {
  1895. memset(&map_cache.head,0,sizeof(struct map_cache_head));
  1896. map_cache.map = (struct map_cache_info *) aCalloc(sizeof(struct map_cache_info),MAX_MAP_CACHE);
  1897. map_cache.head.nmaps = MAX_MAP_CACHE;
  1898. map_cache.head.sizeof_header = sizeof(struct map_cache_head);
  1899. map_cache.head.sizeof_map = sizeof(struct map_cache_info);
  1900. map_cache.head.filesize = sizeof(struct map_cache_head);
  1901. map_cache.head.filesize += sizeof(struct map_cache_info) * map_cache.head.nmaps;
  1902. map_cache.dirty = 1;
  1903. return 1;
  1904. }
  1905. return 0;
  1906. }
  1907. static void map_cache_close(void)
  1908. {
  1909. if(!map_cache.fp) { return; }
  1910. if(map_cache.dirty) {
  1911. fseek(map_cache.fp,0,SEEK_SET);
  1912. fwrite(&map_cache.head,1,sizeof(struct map_cache_head),map_cache.fp);
  1913. fwrite(map_cache.map,map_cache.head.nmaps,sizeof(struct map_cache_info),map_cache.fp);
  1914. }
  1915. fclose(map_cache.fp);
  1916. aFree(map_cache.map);
  1917. map_cache.fp = NULL;
  1918. return;
  1919. }
  1920. int map_cache_read(struct map_data *m)
  1921. {
  1922. int i;
  1923. if(!map_cache.fp) { return 0; }
  1924. for(i = 0;i < map_cache.head.nmaps ; i++) {
  1925. if(!strcmp(m->name,map_cache.map[i].fn)) {
  1926. if(map_cache.map[i].water_height != map_waterheight(m->name)) {
  1927. // 水場の高さが違うので読み直し
  1928. return 0;
  1929. } else if(map_cache.map[i].compressed == 0) {
  1930. // 非圧縮ファイル
  1931. int size = map_cache.map[i].xs * map_cache.map[i].ys;
  1932. m->xs = map_cache.map[i].xs;
  1933. m->ys = map_cache.map[i].ys;
  1934. m->gat = (unsigned char *)aCalloc(m->xs * m->ys,sizeof(unsigned char));
  1935. fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET);
  1936. if(fread(m->gat,1,size,map_cache.fp) == size) {
  1937. // 成功
  1938. return 1;
  1939. } else {
  1940. // なぜかファイル後半が欠けてるので読み直し
  1941. m->xs = 0; m->ys = 0; m->gat = NULL; aFree(m->gat);
  1942. return 0;
  1943. }
  1944. } else if(map_cache.map[i].compressed == 1) {
  1945. // 圧縮フラグ=1 : zlib
  1946. unsigned char *buf;
  1947. unsigned long dest_len;
  1948. int size_compress = map_cache.map[i].compressed_len;
  1949. m->xs = map_cache.map[i].xs;
  1950. m->ys = map_cache.map[i].ys;
  1951. m->gat = (unsigned char *)aMalloc(m->xs * m->ys * sizeof(unsigned char));
  1952. buf = (unsigned char*)aMalloc(size_compress);
  1953. fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET);
  1954. if(fread(buf,1,size_compress,map_cache.fp) != size_compress) {
  1955. // なぜかファイル後半が欠けてるので読み直し
  1956. printf("fread error\n");
  1957. aFree(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL;
  1958. aFree(buf);
  1959. return 0;
  1960. }
  1961. dest_len = m->xs * m->ys;
  1962. decode_zip(m->gat,&dest_len,buf,size_compress);
  1963. if(dest_len != map_cache.map[i].xs * map_cache.map[i].ys) {
  1964. // 正常に解凍が出来てない
  1965. aFree(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL;
  1966. aFree(buf);
  1967. return 0;
  1968. }
  1969. aFree(buf);
  1970. return 1;
  1971. }
  1972. }
  1973. }
  1974. return 0;
  1975. }
  1976. static int map_cache_write(struct map_data *m)
  1977. {
  1978. int i;
  1979. unsigned long len_new , len_old;
  1980. char *write_buf;
  1981. if(!map_cache.fp) { return 0; }
  1982. for(i = 0;i < map_cache.head.nmaps ; i++) {
  1983. if(!strcmp(m->name,map_cache.map[i].fn)) {
  1984. // 同じエントリーがあれば上書き
  1985. if(map_cache.map[i].compressed == 0) {
  1986. len_old = map_cache.map[i].xs * map_cache.map[i].ys;
  1987. } else if(map_cache.map[i].compressed == 1) {
  1988. len_old = map_cache.map[i].compressed_len;
  1989. } else {
  1990. // サポートされてない形式なので長さ0
  1991. len_old = 0;
  1992. }
  1993. if(map_read_flag == 2) {
  1994. // 圧縮保存
  1995. // さすがに2倍に膨れる事はないという事で
  1996. write_buf = (char *) aMalloc(m->xs * m->ys * 2);
  1997. len_new = m->xs * m->ys * 2;
  1998. encode_zip((unsigned char *) write_buf,&len_new,m->gat,m->xs * m->ys);
  1999. map_cache.map[i].compressed = 1;
  2000. map_cache.map[i].compressed_len = len_new;
  2001. } else {
  2002. len_new = m->xs * m->ys;
  2003. write_buf = (char *) m->gat;
  2004. map_cache.map[i].compressed = 0;
  2005. map_cache.map[i].compressed_len = 0;
  2006. }
  2007. if(len_new <= len_old) {
  2008. // サイズが同じか小さくなったので場所は変わらない
  2009. fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET);
  2010. fwrite(write_buf,1,len_new,map_cache.fp);
  2011. } else {
  2012. // 新しい場所に登録
  2013. fseek(map_cache.fp,map_cache.head.filesize,SEEK_SET);
  2014. fwrite(write_buf,1,len_new,map_cache.fp);
  2015. map_cache.map[i].pos = map_cache.head.filesize;
  2016. map_cache.head.filesize += len_new;
  2017. }
  2018. map_cache.map[i].xs = m->xs;
  2019. map_cache.map[i].ys = m->ys;
  2020. map_cache.map[i].water_height = map_waterheight(m->name);
  2021. map_cache.dirty = 1;
  2022. if(map_read_flag == 2) {
  2023. aFree(write_buf);
  2024. }
  2025. return 0;
  2026. }
  2027. }
  2028. // 同じエントリが無ければ書き込める場所を探す
  2029. for(i = 0;i < map_cache.head.nmaps ; i++) {
  2030. if(map_cache.map[i].fn[0] == 0) {
  2031. // 新しい場所に登録
  2032. if(map_read_flag == 2) {
  2033. write_buf = (char *) aMalloc(m->xs * m->ys * 2);
  2034. len_new = m->xs * m->ys * 2;
  2035. encode_zip((unsigned char *) write_buf,&len_new,m->gat,m->xs * m->ys);
  2036. map_cache.map[i].compressed = 1;
  2037. map_cache.map[i].compressed_len = len_new;
  2038. } else {
  2039. len_new = m->xs * m->ys;
  2040. write_buf = (char *) m->gat;
  2041. map_cache.map[i].compressed = 0;
  2042. map_cache.map[i].compressed_len = 0;
  2043. }
  2044. strncpy(map_cache.map[i].fn,m->name,sizeof(map_cache.map[0].fn));
  2045. fseek(map_cache.fp,map_cache.head.filesize,SEEK_SET);
  2046. fwrite(write_buf,1,len_new,map_cache.fp);
  2047. map_cache.map[i].pos = map_cache.head.filesize;
  2048. map_cache.map[i].xs = m->xs;
  2049. map_cache.map[i].ys = m->ys;
  2050. map_cache.map[i].water_height = map_waterheight(m->name);
  2051. map_cache.head.filesize += len_new;
  2052. map_cache.dirty = 1;
  2053. if(map_read_flag == 2) {
  2054. aFree(write_buf);
  2055. }
  2056. return 0;
  2057. }
  2058. }
  2059. // 書き込めなかった
  2060. return 1;
  2061. }
  2062. #ifdef USE_AFM
  2063. static int map_readafm(int m,char *fn) {
  2064. /*
  2065. Advanced Fusion Maps Support
  2066. (c) 2003-2004, The Fusion Project
  2067. - AlexKreuz
  2068. The following code has been provided by me for eAthena
  2069. under the GNU GPL. It provides Advanced Fusion
  2070. Map, the map format desgined by me for Fusion, support
  2071. for the eAthena emulator.
  2072. I understand that because it is under the GPL
  2073. that other emulators may very well use this code in their
  2074. GNU project as well.
  2075. The AFM map format was not originally a part of the GNU
  2076. GPL. It originated from scratch by my own hand. I understand
  2077. that distributing this code to read the AFM maps with eAthena
  2078. causes the GPL to apply to this code. But the actual AFM
  2079. maps are STILL copyrighted to the Fusion Project. By choosing
  2080. In exchange for that 'act of faith' I ask for the following.
  2081. A) Give credit where it is due. If you use this code, do not
  2082. place your name on the changelog. Credit should be given
  2083. to AlexKreuz.
  2084. B) As an act of courtesy, ask me and let me know that you are putting
  2085. AFM support in your project. You will have my blessings if you do.
  2086. C) Use the code in its entirety INCLUDING the copyright message.
  2087. Although the code provided may now be GPL, the AFM maps are not
  2088. and so I ask you to display the copyright message on the STARTUP
  2089. SCREEN as I have done here. (refer to core.c)
  2090. "Advanced Fusion Maps (c) 2003-2004 The Fusion Project"
  2091. Without this copyright, you are NOT entitled to bundle or distribute
  2092. the AFM maps at all. On top of that, your "support" for AFM maps
  2093. becomes just as shady as your "support" for Gravity GRF files.
  2094. The bottom line is this. I know that there are those of you who
  2095. would like to use this code but aren't going to want to provide the
  2096. proper credit. I know this because I speak frome experience. If
  2097. you are one of those people who is going to try to get around my
  2098. requests, then save your breath because I don't want to hear it.
  2099. I have zero faith in GPL and I know and accept that if you choose to
  2100. not display the copyright for the AFMs then there is absolutely nothing
  2101. I can do about it. I am not about to start a legal battle over something
  2102. this silly.
  2103. Provide the proper credit because you believe in the GPL. If you choose
  2104. not to and would rather argue about it, consider the GPL failed.
  2105. October 18th, 2004
  2106. - AlexKreuz
  2107. - The Fusion Project
  2108. */
  2109. int s;
  2110. int x,y,xs,ys;
  2111. size_t size;
  2112. char afm_line[65535];
  2113. int afm_size[2];
  2114. FILE *afm_file;
  2115. char *str;
  2116. afm_file = fopen(fn, "r");
  2117. if (afm_file != NULL) {
  2118. // printf("\rLoading Maps [%d/%d]: %-50s ",m,map_num,fn);
  2119. // fflush(stdout);
  2120. str=fgets(afm_line, sizeof(afm_line)-1, afm_file);
  2121. str=fgets(afm_line, sizeof(afm_line)-1, afm_file);
  2122. str=fgets(afm_line, sizeof(afm_line)-1, afm_file);
  2123. sscanf(str , "%d%d", &afm_size[0], &afm_size[1]);
  2124. map[m].m = m;
  2125. xs = map[m].xs = afm_size[0];
  2126. ys = map[m].ys = afm_size[1];
  2127. // check this, unsigned where it might not need to be
  2128. map[m].gat = (unsigned char*)aCallocA(s = map[m].xs * map[m].ys, 1);
  2129. if(map[m].gat==NULL){
  2130. printf("out of memory : map_readmap gat\n");
  2131. exit(1);
  2132. }
  2133. map[m].npc_num=0;
  2134. map[m].users=0;
  2135. memset(&map[m].flag,0,sizeof(map[m].flag));
  2136. if(battle_config.pk_mode) map[m].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
  2137. for (y = 0; y < ys; y++) {
  2138. str=fgets(afm_line, sizeof(afm_line)-1, afm_file);
  2139. for (x = 0; x < xs; x++) {
  2140. map[m].gat[x+y*xs] = str[x]-48;
  2141. }
  2142. }
  2143. map[m].bxs=(xs+BLOCK_SIZE-1)/BLOCK_SIZE;
  2144. map[m].bys=(ys+BLOCK_SIZE-1)/BLOCK_SIZE;
  2145. size = map[m].bxs * map[m].bys * sizeof(struct block_list*);
  2146. map[m].block = (struct block_list**)aCalloc(size, 1);
  2147. if(map[m].block == NULL){
  2148. printf("out of memory : map_readmap block\n");
  2149. exit(1);
  2150. }
  2151. map[m].block_mob = (struct block_list**)aCalloc(size, 1);
  2152. if (map[m].block_mob == NULL) {
  2153. printf("out of memory : map_readmap block_mob\n");
  2154. exit(1);
  2155. }
  2156. size = map[m].bxs*map[m].bys*sizeof(int);
  2157. map[m].block_count = (int*)aCallocA(size, 1);
  2158. if(map[m].block_count==NULL){
  2159. printf("out of memory : map_readmap block\n");
  2160. exit(1);
  2161. }
  2162. memset(map[m].block_count,0,size);
  2163. map[m].block_mob_count = (int*)aCallocA(size, 1);
  2164. if(map[m].block_mob_count==NULL){
  2165. printf("out of memory : map_readmap block_mob\n");
  2166. exit(1);
  2167. }
  2168. memset(map[m].block_mob_count,0,size);
  2169. strdb_insert(map_db,map[m].name,&map[m]);
  2170. fclose(afm_file);
  2171. }
  2172. return 0;
  2173. }
  2174. #endif
  2175. /*==========================================
  2176. * マップ1枚読み込み
  2177. * ===================================================*/
  2178. static int map_readmap(int m,char *fn, char *alias, int *map_cache, int maxmap) {
  2179. char *gat="";
  2180. size_t size;
  2181. int i = 0;
  2182. int e = 0;
  2183. char progress[21] = " ";
  2184. //printf("\rLoading Maps [%d/%d]: %-50s ",m,map_num,fn);
  2185. if (maxmap) { //avoid map-server crashing if there are 0 maps
  2186. char c = '-';
  2187. static int lasti = -1;
  2188. static int last_time = -1;
  2189. i=m*20/maxmap;
  2190. if ((i != lasti) || (last_time != time(0))) {
  2191. lasti = i;
  2192. printf("\r");
  2193. ShowStatus("Progress: ");
  2194. printf("[");
  2195. for (e=0;e<i;e++) progress[e] = '#';
  2196. printf(progress);
  2197. printf("] Working: [");
  2198. last_time = time(0);
  2199. switch(last_time % 4) {
  2200. case 0: c='\\'; break;
  2201. case 1: c='|'; break;
  2202. case 2: c='/'; break;
  2203. case 3: c='-'; break;
  2204. }
  2205. printf("%c]",c);
  2206. fflush(stdout);
  2207. }
  2208. }
  2209. if(map_cache_read(&map[m])) {
  2210. // キャッシュから読み込めた
  2211. (*map_cache)++;
  2212. } else {
  2213. int s;
  2214. int wh;
  2215. int x,y,xs,ys;
  2216. struct gat_1cell {float high[4]; int type;} *p=NULL;
  2217. // read & convert fn
  2218. // again, might not need to be unsigned char
  2219. gat = (char*)grfio_read(fn);
  2220. if(gat==NULL) {
  2221. return -1;
  2222. // さすがにマップが読めないのはまずいので終了する
  2223. //printf("Can't load map %s\n",fn);
  2224. //exit(1);
  2225. }
  2226. xs=map[m].xs=*(int*)(gat+6);
  2227. ys=map[m].ys=*(int*)(gat+10);
  2228. map[m].gat = (unsigned char *)aCallocA(s = map[m].xs * map[m].ys,sizeof(unsigned char));
  2229. wh=map_waterheight(map[m].name);
  2230. for(y=0;y<ys;y++){
  2231. p=(struct gat_1cell*)(gat+y*xs*20+14);
  2232. for(x=0;x<xs;x++){
  2233. if(wh!=NO_WATER && p->type==0){
  2234. // 水場判定
  2235. map[m].gat[x+y*xs]=(p->high[0]>wh || p->high[1]>wh || p->high[2]>wh || p->high[3]>wh) ? 3 : 0;
  2236. } else {
  2237. map[m].gat[x+y*xs]=p->type;
  2238. }
  2239. p++;
  2240. }
  2241. }
  2242. map_cache_write(&map[m]);
  2243. aFree(gat);
  2244. }
  2245. map[m].m=m;
  2246. map[m].npc_num=0;
  2247. map[m].users=0;
  2248. memset(&map[m].flag,0,sizeof(map[m].flag));
  2249. if(battle_config.pk_mode)
  2250. map[m].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
  2251. map[m].bxs=(map[m].xs+BLOCK_SIZE-1)/BLOCK_SIZE;
  2252. map[m].bys=(map[m].ys+BLOCK_SIZE-1)/BLOCK_SIZE;
  2253. size = map[m].bxs * map[m].bys * sizeof(struct block_list*);
  2254. map[m].block = (struct block_list **)aCalloc(1,size);
  2255. map[m].block_mob = (struct block_list **)aCalloc(1,size);
  2256. size = map[m].bxs*map[m].bys*sizeof(int);
  2257. map[m].block_count = (int *)aCallocA(1,size);
  2258. map[m].block_mob_count=(int *)aCallocA(1,size);
  2259. if (alias)
  2260. strdb_insert(map_db,alias,&map[m]);
  2261. else
  2262. strdb_insert(map_db,map[m].name,&map[m]);
  2263. // printf("%s read done\n",fn);
  2264. return 0;
  2265. }
  2266. /*==========================================
  2267. * 全てのmapデ?タを?み?む
  2268. *------------------------------------------
  2269. */
  2270. int map_readallmap(void) {
  2271. int i,maps_removed=0;
  2272. char fn[256];
  2273. #ifdef USE_AFM
  2274. FILE *afm_file;
  2275. #endif
  2276. int map_cache = 0;
  2277. // マップキャッシュを開く
  2278. if(map_read_flag >= READ_FROM_BITMAP) {
  2279. map_cache_open(map_cache_file);
  2280. }
  2281. sprintf(tmp_output, "Loading Maps%s...\n",
  2282. (map_read_flag == CREATE_BITMAP_COMPRESSED ? " (Generating Map Cache w/ Compression)" :
  2283. map_read_flag == CREATE_BITMAP ? " (Generating Map Cache)" :
  2284. map_read_flag >= READ_FROM_BITMAP ? " (w/ Map Cache)" :
  2285. map_read_flag == READ_FROM_AFM ? " (w/ AFM)" : ""));
  2286. ShowStatus(tmp_output);
  2287. // 先に全部のャbプの存在を確認
  2288. for(i=0;i<map_num;i++){
  2289. #ifdef USE_AFM
  2290. char afm_name[256] = "";
  2291. char *p;
  2292. if(!strstr(map[i].name,".afm")) {
  2293. // check if it's necessary to replace the extension - speeds up loading abit
  2294. strncpy(afm_name, map[i].name, strlen(map[i].name) - 4);
  2295. strcat(afm_name, ".afm");
  2296. }
  2297. map[i].alias = NULL;
  2298. sprintf(fn,"%s\\%s",afm_dir,afm_name);
  2299. for(p=&fn[0];*p!=0;p++) if (*p=='\\') *p = '/'; // * At the time of Unix
  2300. afm_file = fopen(fn, "r");
  2301. if (afm_file != NULL) {
  2302. map_readafm(i,fn);
  2303. fclose(afm_file);
  2304. }
  2305. else if(strstr(map[i].name,".gat")!=NULL) {
  2306. #else
  2307. if(strstr(map[i].name,".gat")!=NULL) {
  2308. #endif
  2309. char *p = strstr(map[i].name, "<"); // [MouseJstr]
  2310. if (p != NULL) {
  2311. char buf[64];
  2312. *p++ = '\0';
  2313. sprintf(buf,"data\\%s", p);
  2314. map[i].alias = aStrdup(buf);
  2315. } else
  2316. map[i].alias = NULL;
  2317. sprintf(fn,"data\\%s",map[i].name);
  2318. if(map_readmap(i,fn, p, &map_cache, map_num) == -1) {
  2319. map_delmap(map[i].name);
  2320. maps_removed++;
  2321. i--;
  2322. }
  2323. }
  2324. }
  2325. aFree(waterlist);
  2326. printf("\r");
  2327. snprintf(tmp_output,sizeof(tmp_output),"Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps.%30s\n",map_num,"");
  2328. ShowInfo(tmp_output);
  2329. map_cache_close();
  2330. if(map_read_flag == CREATE_BITMAP || map_read_flag == CREATE_BITMAP_COMPRESSED) {
  2331. --map_read_flag;
  2332. }
  2333. if (maps_removed) {
  2334. snprintf(tmp_output,sizeof(tmp_output),"Maps Removed: '"CL_WHITE"%d"CL_RESET"'\n",maps_removed);
  2335. ShowNotice(tmp_output);
  2336. }
  2337. return 0;
  2338. }
  2339. /*==========================================
  2340. * ?み?むmapを追加する
  2341. *------------------------------------------
  2342. */
  2343. int map_addmap(char *mapname) {
  2344. if (strcmpi(mapname,"clear")==0) {
  2345. map_num=0;
  2346. return 0;
  2347. }
  2348. if (map_num >= MAX_MAP_PER_SERVER - 1) {
  2349. snprintf(tmp_output,sizeof(tmp_output),"Could not add map '"
  2350. CL_WHITE"%s"CL_RESET"', the limit of maps has been reached.\n",mapname);
  2351. ShowError(tmp_output);
  2352. return 1;
  2353. }
  2354. memcpy(map[map_num].name, mapname, 24);
  2355. map_num++;
  2356. return 0;
  2357. }
  2358. /*==========================================
  2359. * ?み?むmapを削除する
  2360. *------------------------------------------
  2361. */
  2362. int map_delmap(char *mapname) {
  2363. int i;
  2364. if (strcmpi(mapname, "all") == 0) {
  2365. map_num = 0;
  2366. return 0;
  2367. }
  2368. for(i = 0; i < map_num; i++) {
  2369. if (strcmp(map[i].name, mapname) == 0) {
  2370. printf("Removing map [ %s ] from maplist\n",map[i].name);
  2371. memmove(map+i, map+i+1, sizeof(map[0])*(map_num-i-1));
  2372. map_num--;
  2373. }
  2374. }
  2375. return 0;
  2376. }
  2377. static int map_ip_set_ = 0;
  2378. static int char_ip_set_ = 0;
  2379. //static int bind_ip_set_ = 0;
  2380. /*==========================================
  2381. * Console Command Parser [Wizputer]
  2382. *------------------------------------------
  2383. */
  2384. int parse_console(char *buf) {
  2385. char *type,*command,*map, *buf2;
  2386. int x = 0, y = 0;
  2387. int m, n;
  2388. struct map_session_data *sd;
  2389. sd = (struct map_session_data*)aCalloc(sizeof(*sd), 1);
  2390. sd->fd = 0;
  2391. strcpy( sd->status.name , "console");
  2392. type = (char *)aMallocA(64);
  2393. command = (char *)aMallocA(64);
  2394. map = (char *)aMallocA(64);
  2395. buf2 = (char *)aMallocA(72);
  2396. memset(type,0,64);
  2397. memset(command,0,64);
  2398. memset(map,0,64);
  2399. memset(buf2,0,72);
  2400. if ( ( n = sscanf(buf, "%[^:]:%[^:]:%99s %d %d[^\n]", type , command , map , &x , &y )) < 5 )
  2401. if ( ( n = sscanf(buf, "%[^:]:%[^\n]", type , command )) < 2 )
  2402. n = sscanf(buf,"%[^\n]",type);
  2403. if ( n == 5 ) {
  2404. if (x <= 0) {
  2405. x = rand() % 399 + 1;
  2406. sd->bl.x = x;
  2407. } else {
  2408. sd->bl.x = x;
  2409. }
  2410. if (y <= 0) {
  2411. y = rand() % 399 + 1;
  2412. sd->bl.y = y;
  2413. } else {
  2414. sd->bl.y = y;
  2415. }
  2416. m = map_mapname2mapid(map);
  2417. if ( m >= 0 )
  2418. sd->bl.m = m;
  2419. else {
  2420. printf("Console: Unknown map\n");
  2421. goto end;
  2422. }
  2423. }
  2424. printf("Type of command: %s || Command: %s || Map: %s Coords: %d %d\n",type,command,map,x,y);
  2425. if ( strcmpi("admin",type) == 0 && n == 5 ) {
  2426. sprintf(buf2,"console: %s",command);
  2427. if( is_atcommand(sd->fd,sd,buf2,99) == AtCommand_None )
  2428. printf("Console: not atcommand\n");
  2429. } else if ( strcmpi("server",type) == 0 && n == 2 ) {
  2430. if ( strcmpi("shutdown", command) == 0 || strcmpi("exit",command) == 0 || strcmpi("quit",command) == 0 ) {
  2431. exit(0);
  2432. }
  2433. } else if ( strcmpi("help",type) == 0 ) {
  2434. printf("To use GM commands:\n");
  2435. printf("admin:<gm command>:<map of \"gm\"> <x> <y>\n");
  2436. printf("You can use any GM command that doesn't require the GM.\n");
  2437. printf("No using @item or @warp however you can use @charwarp\n");
  2438. printf("The <map of \"gm\"> <x> <y> is for commands that need coords of the GM\n");
  2439. printf("IE: @spawn\n");
  2440. printf("To shutdown the server:\n");
  2441. printf("server:shutdown\n");
  2442. }
  2443. end:
  2444. aFree(buf);
  2445. aFree(type);
  2446. aFree(command);
  2447. aFree(map);
  2448. aFree(buf2);
  2449. aFree(sd);
  2450. return 0;
  2451. }
  2452. /*==========================================
  2453. * 設定ファイルを?み?む
  2454. *------------------------------------------
  2455. */
  2456. int map_config_read(char *cfgName) {
  2457. char line[1024], w1[1024], w2[1024];
  2458. FILE *fp;
  2459. struct hostent *h = NULL;
  2460. fp = fopen(cfgName,"r");
  2461. if (fp == NULL) {
  2462. printf("Map configuration file not found at: %s\n", cfgName);
  2463. exit(1);
  2464. }
  2465. while(fgets(line, sizeof(line) -1, fp)) {
  2466. if (line[0] == '/' && line[1] == '/')
  2467. continue;
  2468. if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) {
  2469. if (strcmpi(w1, "userid")==0){
  2470. chrif_setuserid(w2);
  2471. } else if (strcmpi(w1, "passwd") == 0) {
  2472. chrif_setpasswd(w2);
  2473. } else if (strcmpi(w1, "char_ip") == 0) {
  2474. char_ip_set_ = 1;
  2475. h = gethostbyname (w2);
  2476. if(h != NULL) {
  2477. snprintf(tmp_output,sizeof(tmp_output),"Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\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]);
  2478. ShowInfo(tmp_output);
  2479. 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]);
  2480. }
  2481. chrif_setip(w2);
  2482. } else if (strcmpi(w1, "char_port") == 0) {
  2483. chrif_setport(atoi(w2));
  2484. } else if (strcmpi(w1, "map_ip") == 0) {
  2485. map_ip_set_ = 1;
  2486. h = gethostbyname (w2);
  2487. if (h != NULL) {
  2488. snprintf(tmp_output,sizeof(tmp_output),"Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\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]);
  2489. ShowInfo(tmp_output);
  2490. 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]);
  2491. }
  2492. clif_setip(w2);
  2493. } else if (strcmpi(w1, "bind_ip") == 0) {
  2494. //bind_ip_set_ = 1;
  2495. h = gethostbyname (w2);
  2496. if (h != NULL) {
  2497. snprintf(tmp_output,sizeof(tmp_output),"Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'.\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]);
  2498. ShowInfo(tmp_output);
  2499. 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]);
  2500. }
  2501. clif_setbindip(w2);
  2502. } else if (strcmpi(w1, "map_port") == 0) {
  2503. clif_setport(atoi(w2));
  2504. map_port = (atoi(w2));
  2505. } else if (strcmpi(w1, "water_height") == 0) {
  2506. map_readwater(w2);
  2507. } else if (strcmpi(w1, "map") == 0) {
  2508. map_addmap(w2);
  2509. } else if (strcmpi(w1, "delmap") == 0) {
  2510. map_delmap(w2);
  2511. } else if (strcmpi(w1, "npc") == 0) {
  2512. npc_addsrcfile(w2);
  2513. } else if (strcmpi(w1, "delnpc") == 0) {
  2514. npc_delsrcfile(w2);
  2515. } else if (strcmpi(w1, "data_grf") == 0) {
  2516. grfio_setdatafile(w2);
  2517. } else if (strcmpi(w1, "sdata_grf") == 0) {
  2518. grfio_setsdatafile(w2);
  2519. } else if (strcmpi(w1, "adata_grf") == 0) {
  2520. grfio_setadatafile(w2);
  2521. } else if (strcmpi(w1, "autosave_time") == 0) {
  2522. autosave_interval = atoi(w2) * 1000;
  2523. if (autosave_interval <= 0)
  2524. autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
  2525. } else if (strcmpi(w1, "motd_txt") == 0) {
  2526. strcpy(motd_txt, w2);
  2527. } else if (strcmpi(w1, "help_txt") == 0) {
  2528. strcpy(help_txt, w2);
  2529. } else if (strcmpi(w1, "mapreg_txt") == 0) {
  2530. strcpy(mapreg_txt, w2);
  2531. }else if(strcmpi(w1,"read_map_from_cache")==0){
  2532. if (atoi(w2) == 2)
  2533. map_read_flag = READ_FROM_BITMAP_COMPRESSED;
  2534. else if (atoi(w2) == 1)
  2535. map_read_flag = READ_FROM_BITMAP;
  2536. else
  2537. map_read_flag = READ_FROM_GAT;
  2538. }else if(strcmpi(w1,"map_cache_file")==0){
  2539. strncpy(map_cache_file,w2,255);
  2540. } else if (strcmpi(w1, "import") == 0) {
  2541. map_config_read(w2);
  2542. } else if (strcmpi(w1, "console") == 0) {
  2543. if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ) {
  2544. console = 1;
  2545. ShowNotice("Console Commands is enabled.\n");
  2546. }
  2547. } else if(strcmpi(w1,"imalive_on")==0){ //Added by Mugendai for I'm Alive mod
  2548. imalive_on = atoi(w2); //Added by Mugendai for I'm Alive mod
  2549. } else if(strcmpi(w1,"imalive_time")==0){ //Added by Mugendai for I'm Alive mod
  2550. imalive_time = atoi(w2); //Added by Mugendai for I'm Alive mod
  2551. } else if(strcmpi(w1,"flush_on")==0){ //Added by Mugendai for GUI
  2552. flush_on = atoi(w2); //Added by Mugendai for GUI
  2553. } else if(strcmpi(w1,"flush_time")==0){ //Added by Mugendai for GUI
  2554. flush_time = atoi(w2); //Added by Mugendai for GUI
  2555. }
  2556. }
  2557. }
  2558. fclose(fp);
  2559. return 0;
  2560. }
  2561. int inter_config_read(char *cfgName)
  2562. {
  2563. int i;
  2564. char line[1024],w1[1024],w2[1024];
  2565. FILE *fp;
  2566. fp=fopen(cfgName,"r");
  2567. if(fp==NULL){
  2568. snprintf(tmp_output,sizeof(tmp_output),"File not found: '%s'.\n",cfgName);
  2569. ShowError(tmp_output);
  2570. return 1;
  2571. }
  2572. while(fgets(line,1020,fp)){
  2573. if(line[0] == '/' && line[1] == '/')
  2574. continue;
  2575. i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
  2576. if(i!=2)
  2577. continue;
  2578. //support the import command, just like any other config
  2579. if(strcmpi(w1,"import")==0){
  2580. inter_config_read(w2);
  2581. #ifndef TXT_ONLY
  2582. } else if(strcmpi(w1,"item_db_db")==0){
  2583. strcpy(item_db_db,w2);
  2584. } else if(strcmpi(w1,"mob_db_db")==0){
  2585. strcpy(mob_db_db,w2);
  2586. } else if(strcmpi(w1,"login_db_level")==0){
  2587. strcpy(login_db_level,w2);
  2588. } else if(strcmpi(w1,"login_db_account_id")==0){
  2589. strcpy(login_db_account_id,w2);
  2590. } else if(strcmpi(w1,"login_db")==0){
  2591. strcpy(login_db,w2);
  2592. } else if (strcmpi(w1, "char_db") == 0) {
  2593. strcpy(char_db, w2);
  2594. } else if(strcmpi(w1,"gm_db_level")==0){
  2595. strcpy(gm_db_level,w2);
  2596. } else if(strcmpi(w1,"gm_db_account_id")==0){
  2597. strcpy(gm_db_account_id,w2);
  2598. } else if(strcmpi(w1,"gm_db")==0){
  2599. strcpy(gm_db,w2);
  2600. //Map Server SQL DB
  2601. } else if(strcmpi(w1,"map_server_ip")==0){
  2602. strcpy(map_server_ip, w2);
  2603. } else if(strcmpi(w1,"map_server_port")==0){
  2604. map_server_port=atoi(w2);
  2605. } else if(strcmpi(w1,"map_server_id")==0){
  2606. strcpy(map_server_id, w2);
  2607. } else if(strcmpi(w1,"map_server_pw")==0){
  2608. strcpy(map_server_pw, w2);
  2609. } else if(strcmpi(w1,"map_server_db")==0){
  2610. strcpy(map_server_db, w2);
  2611. } else if(strcmpi(w1,"use_sql_db")==0){
  2612. db_use_sqldbs = battle_config_switch(w2);
  2613. printf ("Using SQL dbs: %s\n",w2);
  2614. //Login Server SQL DB
  2615. } else if(strcmpi(w1,"login_server_ip")==0){
  2616. strcpy(login_server_ip, w2);
  2617. } else if(strcmpi(w1,"login_server_port")==0){
  2618. login_server_port = atoi(w2);
  2619. } else if(strcmpi(w1,"login_server_id")==0){
  2620. strcpy(login_server_id, w2);
  2621. } else if(strcmpi(w1,"login_server_pw")==0){
  2622. strcpy(login_server_pw, w2);
  2623. } else if(strcmpi(w1,"login_server_db")==0){
  2624. strcpy(login_server_db, w2);
  2625. } else if(strcmpi(w1,"lowest_gm_level")==0){
  2626. lowest_gm_level = atoi(w2);
  2627. } else if(strcmpi(w1,"read_gm_interval")==0){
  2628. read_gm_interval = ( atoi(w2) * 60 * 1000 ); // Minutes multiplied by 60 secs per min by 1000 milliseconds per second
  2629. } else if(strcmpi(w1,"log_db")==0) {
  2630. strcpy(log_db, w2);
  2631. } else if(strcmpi(w1,"log_db_ip")==0) {
  2632. strcpy(log_db_ip, w2);
  2633. } else if(strcmpi(w1,"log_db")==0) {
  2634. strcpy(log_db, w2);
  2635. } else if(strcmpi(w1,"log_db_id")==0) {
  2636. strcpy(log_db_id, w2);
  2637. } else if(strcmpi(w1,"log_db_pw")==0) {
  2638. strcpy(log_db_pw, w2);
  2639. } else if(strcmpi(w1,"log_db_port")==0) {
  2640. log_db_port = atoi(w2);
  2641. #endif
  2642. }
  2643. }
  2644. fclose(fp);
  2645. return 0;
  2646. }
  2647. #ifndef TXT_ONLY
  2648. /*=======================================
  2649. * MySQL Init
  2650. *---------------------------------------
  2651. */
  2652. int map_sql_init(void){
  2653. mysql_init(&mmysql_handle);
  2654. //DB connection start
  2655. printf("Connect Map DB Server....\n");
  2656. if(!mysql_real_connect(&mmysql_handle, map_server_ip, map_server_id, map_server_pw,
  2657. map_server_db ,map_server_port, (char *)NULL, 0)) {
  2658. //pointer check
  2659. printf("%s\n",mysql_error(&mmysql_handle));
  2660. exit(1);
  2661. }
  2662. else {
  2663. printf ("connect success! (Map Server Connection)\n");
  2664. }
  2665. mysql_init(&lmysql_handle);
  2666. //DB connection start
  2667. printf("Connect Login DB Server....\n");
  2668. if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw,
  2669. login_server_db ,login_server_port, (char *)NULL, 0)) {
  2670. //pointer check
  2671. printf("%s\n",mysql_error(&lmysql_handle));
  2672. exit(1);
  2673. }
  2674. else {
  2675. printf ("connect success! (Login Server Connection)\n");
  2676. }
  2677. if(battle_config.mail_system) { // mail system [Valaris]
  2678. mysql_init(&mail_handle);
  2679. if(!mysql_real_connect(&mail_handle, map_server_ip, map_server_id, map_server_pw,
  2680. map_server_db ,map_server_port, (char *)NULL, 0)) {
  2681. printf("%s\n",mysql_error(&mail_handle));
  2682. exit(1);
  2683. }
  2684. }
  2685. return 0;
  2686. }
  2687. int map_sql_close(void){
  2688. mysql_close(&mmysql_handle);
  2689. printf("Close Map DB Connection....\n");
  2690. mysql_close(&lmysql_handle);
  2691. printf("Close Login DB Connection....\n");
  2692. return 0;
  2693. }
  2694. int log_sql_init(void){
  2695. mysql_init(&mmysql_handle);
  2696. //DB connection start
  2697. printf(""CL_WHITE"[SQL]"CL_RESET": Connecting to Log Database "CL_WHITE"%s"CL_RESET" At "CL_WHITE"%s"CL_RESET"...\n",log_db,log_db_ip);
  2698. if(!mysql_real_connect(&mmysql_handle, log_db_ip, log_db_id, log_db_pw,
  2699. log_db ,log_db_port, (char *)NULL, 0)) {
  2700. //pointer check
  2701. printf(""CL_WHITE"[SQL Error]"CL_RESET": %s\n",mysql_error(&mmysql_handle));
  2702. exit(1);
  2703. } else {
  2704. printf(""CL_WHITE"[SQL]"CL_RESET": Successfully '"CL_GREEN"connected"CL_RESET"' to Database '"CL_WHITE"%s"CL_RESET"'.\n", log_db);
  2705. }
  2706. return 0;
  2707. }
  2708. int online_timer(int tid,unsigned int tick,int id,int data)
  2709. {
  2710. if(check_online_timer != tid)
  2711. return 0;
  2712. char_online_check();
  2713. check_online_timer=add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0);
  2714. return 0;
  2715. }
  2716. void char_online_check(void)
  2717. {
  2718. int i;
  2719. struct map_session_data *sd=NULL;
  2720. chrif_char_reset_offline();
  2721. for(i=0;i<fd_max;i++){
  2722. if (session[i] && (sd = (struct map_session_data*)session[i]->session_data) && sd && sd->state.auth &&
  2723. !(battle_config.hide_GM_session && pc_isGM(sd)))
  2724. if(sd->status.char_id) {
  2725. chrif_char_online(sd);
  2726. }
  2727. }
  2728. if(check_online_timer && check_online_timer != -1) {
  2729. delete_timer(check_online_timer,online_timer);
  2730. add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0);
  2731. }
  2732. }
  2733. #endif /* not TXT_ONLY */
  2734. //-----------------------------------------------------
  2735. //I'm Alive Alert
  2736. //Used to output 'I'm Alive' every few seconds
  2737. //Intended to let frontends know if the app froze
  2738. //-----------------------------------------------------
  2739. int imalive_timer(int tid, unsigned int tick, int id, int data){
  2740. printf("I'm Alive\n");
  2741. return 0;
  2742. }
  2743. //-----------------------------------------------------
  2744. //Flush stdout
  2745. //stdout buffer needs flushed to be seen in GUI
  2746. //-----------------------------------------------------
  2747. int flush_timer(int tid, unsigned int tick, int id, int data){
  2748. fflush(stdout);
  2749. return 0;
  2750. }
  2751. int id_db_final(void *k,void *d,va_list ap) { return 0; }
  2752. int map_db_final(void *k,void *d,va_list ap) { return 0; }
  2753. int nick_db_final(void *k,void *d,va_list ap)
  2754. {
  2755. char *p = (char *) d;
  2756. if (p) aFree(p);
  2757. return 0;
  2758. }
  2759. int charid_db_final(void *k,void *d,va_list ap)
  2760. {
  2761. struct charid2nick *p = (struct charid2nick *) d;
  2762. if (p) aFree(p);
  2763. return 0;
  2764. }
  2765. int cleanup_sub(struct block_list *bl, va_list ap) {
  2766. nullpo_retr(0, bl);
  2767. switch(bl->type) {
  2768. case BL_PC:
  2769. map_quit((struct map_session_data *) bl);
  2770. break;
  2771. case BL_NPC:
  2772. npc_delete((struct npc_data *)bl);
  2773. break;
  2774. case BL_MOB:
  2775. mob_delete((struct mob_data *)bl);
  2776. break;
  2777. case BL_PET:
  2778. pet_remove_map((struct map_session_data *)bl);
  2779. break;
  2780. case BL_ITEM:
  2781. map_clearflooritem(bl->id);
  2782. break;
  2783. case BL_SKILL:
  2784. skill_delunit((struct skill_unit *) bl);
  2785. break;
  2786. }
  2787. return 0;
  2788. }
  2789. /*==========================================
  2790. * map鯖終了時?理
  2791. *------------------------------------------
  2792. */
  2793. void do_final(void) {
  2794. int i;
  2795. ShowStatus("Terminating...\n");
  2796. for (i = 0; i < map_num; i++)
  2797. if(map[i].m)
  2798. map_foreachinarea(cleanup_sub, i, 0, 0, map[i].xs, map[i].ys, 0, 0);
  2799. #ifndef TXT_ONLY
  2800. chrif_char_reset_offline();
  2801. #endif
  2802. chrif_flush_fifo();
  2803. //#if 0 // why is this here? >_>
  2804. do_final_chrif(); // この内部でキャラを全て切断する
  2805. do_final_npc();
  2806. // map_removenpc();
  2807. do_final_script();
  2808. do_final_itemdb();
  2809. do_final_storage();
  2810. do_final_guild();
  2811. do_final_party();
  2812. do_final_pc();
  2813. do_final_pet();
  2814. do_final_msg();
  2815. for (i=0; i<map_num; i++) {
  2816. if(map[i].gat) aFree(map[i].gat);
  2817. if(map[i].block) aFree(map[i].block);
  2818. if(map[i].block_mob) aFree(map[i].block_mob);
  2819. if(map[i].block_count) aFree(map[i].block_count);
  2820. if(map[i].block_mob_count) aFree(map[i].block_mob_count);
  2821. }
  2822. // do_final_timer(); (we used timer_final() instead)
  2823. timer_final();
  2824. numdb_final(id_db, id_db_final);
  2825. strdb_final(map_db, map_db_final);
  2826. strdb_final(nick_db, nick_db_final);
  2827. numdb_final(charid_db, charid_db_final);
  2828. exit_dbn();
  2829. //#endif
  2830. #ifndef TXT_ONLY
  2831. map_sql_close();
  2832. #endif /* not TXT_ONLY */
  2833. ShowStatus("Successfully terminated.\n");
  2834. }
  2835. /*======================================================
  2836. * Map-Server Version Screen [MC Cameri]
  2837. *------------------------------------------------------
  2838. */
  2839. void map_helpscreen(int flag) { // by MC Cameri
  2840. puts("Usage: map-server [options]");
  2841. puts("Options:");
  2842. puts(CL_WHITE" Commands\t\t\tDescription"CL_RESET);
  2843. puts("-----------------------------------------------------------------------------");
  2844. puts(" --help, --h, --?, /? Displays this help screen");
  2845. puts(" --map-config <file> Load map-server configuration from <file>");
  2846. puts(" --battle-config <file> Load battle configuration from <file>");
  2847. puts(" --atcommand-config <file> Load atcommand configuration from <file>");
  2848. puts(" --charcommand-config <file> Load charcommand configuration from <file>");
  2849. puts(" --script-config <file> Load script configuration from <file>");
  2850. puts(" --msg-config <file> Load message configuration from <file>");
  2851. puts(" --grf-path-file <file> Load grf path file configuration from <file>");
  2852. puts(" --sql-config <file> Load inter-server configuration from <file>");
  2853. puts(" (SQL Only)");
  2854. puts(" --log-config <file> Load logging configuration from <file>");
  2855. puts(" (SQL Only)");
  2856. puts(" --version, --v, -v, /v Displays the server's version");
  2857. puts("\n");
  2858. if (flag) exit(1);
  2859. }
  2860. /*======================================================
  2861. * Map-Server Version Screen [MC Cameri]
  2862. *------------------------------------------------------
  2863. */
  2864. void map_versionscreen(int flag) {
  2865. printf("CL_WHITE" "eAthena version %d.%02d.%02d, Athena Mod version %d" CL_RESET"\n",
  2866. ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION,
  2867. ATHENA_MOD_VERSION);
  2868. puts(CL_GREEN "Website/Forum:" CL_RESET "\thttp://eathena.deltaanime.net/");
  2869. puts(CL_GREEN "Download URL:" CL_RESET "\thttp://eathena.systeminplace.net/");
  2870. puts(CL_GREEN "IRC Channel:" CL_RESET "\tirc://irc.deltaanime.net/#athena");
  2871. puts("\nOpen " CL_WHITE "readme.html" CL_RESET " for more information.");
  2872. if (ATHENA_RELEASE_FLAG) ShowNotice("This version is not for release.\n");
  2873. if (flag) exit(1);
  2874. }
  2875. /*======================================================
  2876. * Map-Server Init and Command-line Arguments [Valaris]
  2877. *------------------------------------------------------
  2878. */
  2879. int do_init(int argc, char *argv[]) {
  2880. int i;
  2881. FILE *data_conf;
  2882. char line[1024], w1[1024], w2[1024];
  2883. #ifdef GCOLLECT
  2884. GC_enable_incremental();
  2885. #endif
  2886. INTER_CONF_NAME="conf/inter_athena.conf";
  2887. LOG_CONF_NAME="conf/log_athena.conf";
  2888. MAP_CONF_NAME = "conf/map_athena.conf";
  2889. BATTLE_CONF_FILENAME = "conf/battle_athena.conf";
  2890. ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf";
  2891. CHARCOMMAND_CONF_FILENAME = "conf/charcommand_athena.conf";
  2892. SCRIPT_CONF_NAME = "conf/script_athena.conf";
  2893. MSG_CONF_NAME = "conf/msg_athena.conf";
  2894. GRF_PATH_FILENAME = "conf/grf-files.txt";
  2895. chrif_connected = 0;
  2896. srand(gettick());
  2897. for (i = 1; i < argc ; i++) {
  2898. if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "--h") == 0 || strcmp(argv[i], "--?") == 0 || strcmp(argv[i], "/?") == 0)
  2899. map_helpscreen(1);
  2900. if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "--v") == 0 || strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "/v") == 0)
  2901. map_versionscreen(1);
  2902. else if (strcmp(argv[i], "--map_config") == 0 || strcmp(argv[i], "--map-config") == 0)
  2903. MAP_CONF_NAME=argv[i+1];
  2904. else if (strcmp(argv[i],"--battle_config") == 0 || strcmp(argv[i],"--battle-config") == 0)
  2905. BATTLE_CONF_FILENAME = argv[i+1];
  2906. else if (strcmp(argv[i],"--atcommand_config") == 0 || strcmp(argv[i],"--atcommand-config") == 0)
  2907. ATCOMMAND_CONF_FILENAME = argv[i+1];
  2908. else if (strcmp(argv[i],"--charcommand_config") == 0 || strcmp(argv[i],"--charcommand-config") == 0)
  2909. CHARCOMMAND_CONF_FILENAME = argv[i+1];
  2910. else if (strcmp(argv[i],"--script_config") == 0 || strcmp(argv[i],"--script-config") == 0)
  2911. SCRIPT_CONF_NAME = argv[i+1];
  2912. else if (strcmp(argv[i],"--msg_config") == 0 || strcmp(argv[i],"--msg-config") == 0)
  2913. MSG_CONF_NAME = argv[i+1];
  2914. else if (strcmp(argv[i],"--grf_path_file") == 0 || strcmp(argv[i],"--grf-path-file") == 0)
  2915. GRF_PATH_FILENAME = argv[i+1];
  2916. #ifndef TXT_ONLY
  2917. else if (strcmp(argv[i],"--inter_config") == 0 || strcmp(argv[i],"--inter-config") == 0)
  2918. INTER_CONF_NAME = argv[i+1];
  2919. #endif /* not TXT_ONLY */
  2920. else if (strcmp(argv[i],"--log_config") == 0 || strcmp(argv[i],"--log-config") == 0)
  2921. LOG_CONF_NAME = argv[i+1];
  2922. else if (strcmp(argv[i],"--run_once") == 0) // close the map-server as soon as its done.. for testing [Celest]
  2923. runflag = 0;
  2924. }
  2925. map_config_read(MAP_CONF_NAME);
  2926. if ((naddr_ == 0) && (map_ip_set_ == 0 || char_ip_set_ == 0)) {
  2927. printf("\nUnable to determine your IP address... please edit\n");
  2928. printf("the map_athena.conf file and set it.\n");
  2929. printf("(127.0.0.1 is valid if you have no network interface)\n");
  2930. }
  2931. if (map_ip_set_ == 0 || char_ip_set_ == 0) {
  2932. // The map server should know what IP address it is running on
  2933. // - MouseJstr
  2934. int localaddr = ntohl(addr_[0]);
  2935. unsigned char *ptr = (unsigned char *) &localaddr;
  2936. char buf[16];
  2937. sprintf(buf, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);;
  2938. if (naddr_ != 1)
  2939. printf("Multiple interfaces detected.. using %s as our IP address\n", buf);
  2940. else
  2941. printf("Defaulting to %s as our IP address\n", buf);
  2942. if (map_ip_set_ == 0)
  2943. clif_setip(buf);
  2944. if (char_ip_set_ == 0)
  2945. chrif_setip(buf);
  2946. if (ptr[0] == 192 && ptr[1] == 168)
  2947. printf("\nFirewall detected.. \n edit lan_support.conf and map_athena.conf\n\n");
  2948. }
  2949. if (SHOW_DEBUG_MSG) ShowNotice("Server running in '"CL_WHITE"Debug Mode"CL_RESET"'.\n");
  2950. battle_config_read(BATTLE_CONF_FILENAME);
  2951. msg_config_read(MSG_CONF_NAME);
  2952. atcommand_config_read(ATCOMMAND_CONF_FILENAME);
  2953. charcommand_config_read(CHARCOMMAND_CONF_FILENAME);
  2954. script_config_read(SCRIPT_CONF_NAME);
  2955. inter_config_read(INTER_CONF_NAME);
  2956. log_config_read(LOG_CONF_NAME);
  2957. atexit(do_final);
  2958. id_db = numdb_init();
  2959. map_db = strdb_init(16);
  2960. nick_db = strdb_init(24);
  2961. charid_db = numdb_init();
  2962. #ifndef TXT_ONLY
  2963. map_sql_init();
  2964. #endif /* not TXT_ONLY */
  2965. grfio_init(GRF_PATH_FILENAME);
  2966. data_conf = fopen(GRF_PATH_FILENAME, "r");
  2967. // It will read, if there is grf-files.txt.
  2968. if (data_conf) {
  2969. while(fgets(line, 1020, data_conf)) {
  2970. if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) {
  2971. if(strcmp(w1,"afm_dir") == 0)
  2972. strcpy(afm_dir, w2);
  2973. }
  2974. }
  2975. fclose(data_conf);
  2976. } // end of reading grf-files.txt for AFMs
  2977. map_readallmap();
  2978. add_timer_func_list(map_freeblock_timer,"map_freeblock_timer");
  2979. add_timer_func_list(map_clearflooritem_timer, "map_clearflooritem_timer");
  2980. add_timer_interval(gettick()+1000,map_freeblock_timer,0,0,60*1000);
  2981. //Added by Mugendai for GUI support
  2982. if (flush_on)
  2983. add_timer_interval(gettick()+10, flush_timer,0,0,flush_time);
  2984. //Added for Mugendais I'm Alive mod
  2985. if (imalive_on)
  2986. add_timer_interval(gettick()+10, imalive_timer,0,0,imalive_time*1000);
  2987. #ifndef TXT_ONLY // online status timer, checks every hour [Valaris]
  2988. add_timer_func_list(online_timer, "online_timer");
  2989. check_online_timer=add_timer(gettick()+CHECK_INTERVAL,online_timer,0,0);
  2990. #endif /* not TXT_ONLY */
  2991. do_init_chrif();
  2992. do_init_clif();
  2993. do_init_itemdb();
  2994. do_init_mob(); // npcの初期化時?でmob_spawnして、mob_dbを?照するのでinit_npcより先
  2995. do_init_script();
  2996. do_init_pc();
  2997. do_init_status();
  2998. do_init_party();
  2999. do_init_guild();
  3000. do_init_storage();
  3001. do_init_skill();
  3002. do_init_pet();
  3003. do_init_npc();
  3004. #ifndef TXT_ONLY /* mail system [Valaris] */
  3005. if(battle_config.mail_system)
  3006. do_init_mail();
  3007. if (log_config.sql_logs && (log_config.branch || log_config.drop || log_config.mvpdrop ||
  3008. log_config.present || log_config.produce || log_config.refine || log_config.trade))
  3009. {
  3010. log_sql_init();
  3011. }
  3012. #endif /* not TXT_ONLY */
  3013. npc_event_do_oninit(); // npcのOnInitイベント?行
  3014. if ( console ) {
  3015. set_defaultconsoleparse(parse_console);
  3016. start_console();
  3017. }
  3018. if (battle_config.pk_mode == 1)
  3019. ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n");
  3020. sprintf(tmp_output,"Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map_port);
  3021. ShowStatus(tmp_output);
  3022. return 0;
  3023. }
  3024. int compare_item(struct item *a, struct item *b) {
  3025. return (
  3026. (a->nameid == b->nameid) &&
  3027. (a->identify == b->identify) &&
  3028. (a->refine == b->refine) &&
  3029. (a->attribute == b->attribute) &&
  3030. (a->card[0] == b->card[0]) &&
  3031. (a->card[1] == b->card[1]) &&
  3032. (a->card[2] == b->card[2]) &&
  3033. (a->card[3] == b->card[3]));
  3034. }