map.c 114 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <stdarg.h>
  7. #ifdef _WIN32
  8. #include <winsock.h>
  9. #else
  10. #include <netdb.h>
  11. #include <unistd.h>
  12. #endif
  13. #include <math.h>
  14. #include "../common/core.h"
  15. #include "../common/timer.h"
  16. #include "../common/grfio.h"
  17. #include "../common/malloc.h"
  18. #include "../common/socket.h"
  19. #include "../common/showmsg.h"
  20. #include "../common/version.h"
  21. #include "../common/nullpo.h"
  22. #include "map.h"
  23. #include "chrif.h"
  24. #include "clif.h"
  25. #include "intif.h"
  26. #include "npc.h"
  27. #include "pc.h"
  28. #include "status.h"
  29. #include "mob.h"
  30. #include "chat.h"
  31. #include "itemdb.h"
  32. #include "storage.h"
  33. #include "skill.h"
  34. #include "trade.h"
  35. #include "party.h"
  36. #include "battle.h"
  37. #include "script.h"
  38. #include "guild.h"
  39. #include "pet.h"
  40. #include "atcommand.h"
  41. #include "charcommand.h"
  42. #include "log.h"
  43. #include "charsave.h"
  44. #include "irc.h"
  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. MYSQL logmysql_handle; //For the log database - fix by [Maeki]
  57. MYSQL_RES* logsql_res ;
  58. MYSQL_ROW logsql_row ;
  59. MYSQL mail_handle; // mail system [Valaris]
  60. MYSQL_RES* mail_res ;
  61. MYSQL_ROW mail_row ;
  62. int map_server_port = 3306;
  63. char map_server_ip[16] = "127.0.0.1";
  64. char map_server_id[32] = "ragnarok";
  65. char map_server_pw[32] = "ragnarok";
  66. char map_server_db[32] = "ragnarok";
  67. char default_codepage[32] = ""; //Feature by irmin.
  68. int db_use_sqldbs = 0;
  69. int login_server_port = 3306;
  70. char login_server_ip[16] = "127.0.0.1";
  71. char login_server_id[32] = "ragnarok";
  72. char login_server_pw[32] = "ragnarok";
  73. char login_server_db[32] = "ragnarok";
  74. char item_db_db[32] = "item_db";
  75. char item_db2_db[32] = "item_db2";
  76. char mob_db_db[32] = "mob_db";
  77. char mob_db2_db[32] = "mob_db2";
  78. char login_db[32] = "login";
  79. char login_db_level[32] = "level";
  80. char login_db_account_id[32] = "account_id";
  81. int log_db_port = 3306;
  82. char log_db_ip[16] = "127.0.0.1";
  83. char log_db_id[32] = "ragnarok";
  84. char log_db_pw[32] = "ragnarok";
  85. char log_db[32] = "log";
  86. int mail_server_port = 3306;
  87. char mail_server_ip[16] = "127.0.0.1";
  88. char mail_server_id[32] = "ragnarok";
  89. char mail_server_pw[32] = "ragnarok";
  90. char mail_server_db[32] = "ragnarok";
  91. int mail_server_enable = 0;
  92. char gm_db[32] = "login";
  93. char gm_db_level[32] = "level";
  94. char gm_db_account_id[32] = "account_id";
  95. int read_gm_interval = 600000;
  96. char char_db[32] = "char";
  97. char mail_db[32] = "mail";
  98. char charsql_host[40] = "localhost";
  99. int charsql_port = 3306;
  100. char charsql_user[32] = "ragnarok";
  101. char charsql_pass[32] = "eAthena";
  102. char charsql_db[40] = "ragnarok";
  103. MYSQL charsql_handle;
  104. MYSQL_RES* charsql_res;
  105. MYSQL_ROW charsql_row;
  106. #ifdef MAPREGSQL
  107. // [zBuffer] SQL Mapreg
  108. MYSQL mapregsql_handle;
  109. MYSQL_RES* mapregsql_res ;
  110. MYSQL_ROW mapregsql_row;
  111. #endif
  112. #endif /* not TXT_ONLY */
  113. int lowest_gm_level = 1;
  114. // This param using for sending mainchat
  115. // messages like whispers to this nick. [LuzZza]
  116. char main_chat_nick[16] = "Main";
  117. char *INTER_CONF_NAME;
  118. char *LOG_CONF_NAME;
  119. char *MAP_CONF_NAME;
  120. char *BATTLE_CONF_FILENAME;
  121. char *ATCOMMAND_CONF_FILENAME;
  122. char *CHARCOMMAND_CONF_FILENAME;
  123. char *SCRIPT_CONF_NAME;
  124. char *MSG_CONF_NAME;
  125. char *GRF_PATH_FILENAME;
  126. // 極力 staticでロ?カルに?める
  127. static struct dbt * id_db=NULL;
  128. static struct dbt * pc_db=NULL;
  129. static struct dbt * map_db=NULL;
  130. static struct dbt * charid_db=NULL;
  131. static int map_users=0;
  132. static struct block_list *objects[MAX_FLOORITEM];
  133. static int first_free_object_id=0,last_object_id=0;
  134. #define block_free_max 1048576
  135. struct block_list *block_free[block_free_max];
  136. static int block_free_count = 0, block_free_lock = 0;
  137. #define BL_LIST_MAX 1048576
  138. static struct block_list *bl_list[BL_LIST_MAX];
  139. static int bl_list_count = 0;
  140. static char afm_dir[1024] = ""; // [Valaris]
  141. struct map_data map[MAX_MAP_PER_SERVER];
  142. int map_num = 0;
  143. int map_port=0;
  144. int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
  145. int charsave_method = 0; //Default 'OLD' Save method (SQL ONLY!) [Sirius]
  146. int agit_flag = 0;
  147. int night_flag = 0; // 0=day, 1=night [Yor]
  148. int kick_on_disconnect = 1;
  149. struct charid2nick {
  150. char nick[NAME_LENGTH];
  151. int req_id;
  152. };
  153. // ォ゙ォテォラォュォ罩テォキォ袮ラ鯑ォユォ鬮ー(map_athana.conf?ェホread_map_from_cacheェヌ�・)
  154. // 0:ララ鯑ェキェハェ、 1:゙ェ?�ワチ� 2:?�ワチ�
  155. int map_read_flag = READ_FROM_GAT;
  156. char map_cache_file[256]="db/map.info"; // ォ゙ォテォラォュォ罩テォキォ雖ユォ。ォ、ォ・」
  157. char db_path[256] = "db";
  158. char motd_txt[256] = "conf/motd.txt";
  159. char help_txt[256] = "conf/help.txt";
  160. char help2_txt[256] = "conf/help2.txt";
  161. char charhelp_txt[256] = "conf/charhelp.txt";
  162. char wisp_server_name[NAME_LENGTH] = "Server"; // can be modified in char-server configuration file
  163. int console = 0;
  164. int enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex]
  165. static const int dirx[8]={0,-1,-1,-1,0,1,1,1};
  166. static const int diry[8]={1,1,0,-1,-1,-1,0,1};
  167. /*==========================================
  168. * 全map鯖?計での接??設定
  169. * (char鯖から送られてくる)
  170. *------------------------------------------
  171. */
  172. void map_setusers(int fd)
  173. {
  174. RFIFOHEAD(fd);
  175. WFIFOHEAD(fd, 2);
  176. map_users = RFIFOL(fd,2);
  177. // send some anser
  178. WFIFOW(fd,0) = 0x2718;
  179. WFIFOSET(fd,2);
  180. }
  181. /*==========================================
  182. * 全map鯖?計での接??取得 (/wへの?答用)
  183. *------------------------------------------
  184. */
  185. int map_getusers(void) {
  186. return map_users;
  187. }
  188. //Distance functions, taken from http://www.flipcode.com/articles/article_fastdistance.shtml
  189. int check_distance(int dx, int dy, int distance) {
  190. //In this case, we just do a square comparison. Add 1 tile grace for diagonal range checks.
  191. return (dx*dx + dy*dy <= distance*distance + (dx&&dy?1:0));
  192. }
  193. unsigned int distance(int dx, int dy) {
  194. unsigned int min, max;
  195. if ( dx < 0 ) dx = -dx;
  196. if ( dy < 0 ) dy = -dy;
  197. //There appears to be something wrong with the aproximation below when either dx/dy is 0! [Skotlex]
  198. if ( dx == 0 ) return dy;
  199. if ( dy == 0 ) return dx;
  200. if ( dx < dy )
  201. {
  202. min = dx;
  203. max = dy;
  204. } else {
  205. min = dy;
  206. max = dx;
  207. }
  208. // coefficients equivalent to ( 123/128 * max ) and ( 51/128 * min )
  209. return ((( max << 8 ) + ( max << 3 ) - ( max << 4 ) - ( max << 1 ) +
  210. ( min << 7 ) - ( min << 5 ) + ( min << 3 ) - ( min << 1 )) >> 8 );
  211. }
  212. //
  213. // block削除の安全性確保?理
  214. //
  215. /*==========================================
  216. * blockをfreeするときfreeの?わりに呼ぶ
  217. * ロックされているときはバッファにためる
  218. *------------------------------------------
  219. */
  220. int map_freeblock (struct block_list *bl)
  221. {
  222. if (block_free_lock == 0 || block_free_count >= block_free_max)
  223. {
  224. aFree(bl);
  225. bl = NULL;
  226. if (block_free_count >= block_free_max)
  227. if (battle_config.error_log)
  228. ShowWarning("map_freeblock: too many free block! %d %d\n",
  229. block_free_count, block_free_lock);
  230. } else
  231. block_free[block_free_count++] = bl;
  232. return block_free_lock;
  233. }
  234. /*==========================================
  235. * blockのfreeを一市Iに禁止する
  236. *------------------------------------------
  237. */
  238. int map_freeblock_lock (void)
  239. {
  240. return ++block_free_lock;
  241. }
  242. /*==========================================
  243. * blockのfreeのロックを解除する
  244. * このとき、ロックが完全になくなると
  245. * バッファにたまっていたblockを全部削除
  246. *------------------------------------------
  247. */
  248. int map_freeblock_unlock (void)
  249. {
  250. if ((--block_free_lock) == 0) {
  251. int i;
  252. for (i = 0; i < block_free_count; i++)
  253. { //Directly calling aFree shouldn't be a leak, as Free remembers the size the original pointed to memory was allocated with? [Skotlex]
  254. aFree(block_free[i]);
  255. block_free[i] = NULL;
  256. }
  257. block_free_count = 0;
  258. } else if (block_free_lock < 0) {
  259. if (battle_config.error_log)
  260. ShowError("map_freeblock_unlock: lock count < 0 !\n");
  261. block_free_lock = 0; // 次回以降のロックに支障が出てくるのでリセット
  262. }
  263. return block_free_lock;
  264. }
  265. // map_freeblock_lock() を呼んで map_freeblock_unlock() を呼ばない
  266. // 関数があったので、定期的にblock_free_lockをリセットするようにする。
  267. // この関数は、do_timer() のトップレベルから呼ばれるので、
  268. // block_free_lock を直接いじっても支障無いはず。
  269. int map_freeblock_timer (int tid, unsigned int tick, int id, int data)
  270. {
  271. if (block_free_lock > 0) {
  272. ShowError("map_freeblock_timer: block_free_lock(%d) is invalid.\n", block_free_lock);
  273. block_free_lock = 1;
  274. map_freeblock_unlock();
  275. }
  276. return 0;
  277. }
  278. //
  279. // block化?理
  280. //
  281. /*==========================================
  282. * map[]のblock_listから?がっている場合に
  283. * bl->prevにbl_headのアドレスを入れておく
  284. *------------------------------------------
  285. */
  286. static struct block_list bl_head;
  287. #ifdef CELL_NOSTACK
  288. /*==========================================
  289. * These pair of functions update the counter of how many objects
  290. * lie on a tile.
  291. *------------------------------------------
  292. */
  293. void map_addblcell(struct block_list *bl)
  294. {
  295. if(bl->m<0 || bl->x<0 || bl->x>=map[bl->m].xs
  296. || bl->y<0 || bl->y>=map[bl->m].ys || !(bl->type&BL_CHAR))
  297. return;
  298. map[bl->m].cell_bl[bl->x+bl->y*map[bl->m].xs]++;
  299. return;
  300. }
  301. void map_delblcell(struct block_list *bl)
  302. {
  303. if(bl->m <0 || bl->x<0 || bl->x>=map[bl->m].xs
  304. || bl->y<0 || bl->y>=map[bl->m].ys || !(bl->type&BL_CHAR))
  305. return;
  306. map[bl->m].cell_bl[bl->x+bl->y*map[bl->m].xs]--;
  307. }
  308. #endif
  309. /*==========================================
  310. * Adds a block to the map.
  311. * If flag is 1, then the block was just added
  312. * otherwise it is part of a transition.
  313. *------------------------------------------
  314. */
  315. int map_addblock_sub (struct block_list *bl, int flag)
  316. {
  317. int m, x, y, pos;
  318. nullpo_retr(0, bl);
  319. if (bl->prev != NULL) {
  320. if(battle_config.error_log)
  321. ShowError("map_addblock error : bl->prev != NULL\n");
  322. return 0;
  323. }
  324. m = bl->m;
  325. x = bl->x;
  326. y = bl->y;
  327. if (m < 0 || m >= map_num ||
  328. x < 0 || x >= map[m].xs ||
  329. y < 0 || y >= map[m].ys)
  330. return 1;
  331. #ifdef CELL_NOSTACK
  332. map_addblcell(bl);
  333. #endif
  334. pos = x/BLOCK_SIZE+(y/BLOCK_SIZE)*map[m].bxs;
  335. if (bl->type == BL_MOB) {
  336. bl->next = map[m].block_mob[pos];
  337. bl->prev = &bl_head;
  338. if (bl->next) bl->next->prev = bl;
  339. map[m].block_mob[pos] = bl;
  340. map[m].block_mob_count[pos]++;
  341. } else {
  342. bl->next = map[m].block[pos];
  343. bl->prev = &bl_head;
  344. if (bl->next) bl->next->prev = bl;
  345. map[m].block[pos] = bl;
  346. map[m].block_count[pos]++;
  347. if (bl->type == BL_PC && flag)
  348. {
  349. struct map_session_data* sd;
  350. if (map[m].users++ == 0 && battle_config.dynamic_mobs) //Skotlex
  351. map_spawnmobs(m);
  352. sd = (struct map_session_data*)bl;
  353. if (battle_config.pet_no_gvg && map_flag_gvg(m) && sd->pd)
  354. { //Return the pet to egg. [Skotlex]
  355. clif_displaymessage(sd->fd, "Pets are not allowed in Guild Wars.");
  356. pet_menu(sd, 3); //Option 3 is return to egg.
  357. }
  358. }
  359. }
  360. return 0;
  361. }
  362. /*==========================================
  363. * Removes a block from the map.
  364. * If flag is 1, then the block is removed for good
  365. * otherwise it is part of a transition.
  366. *------------------------------------------
  367. */
  368. int map_delblock_sub (struct block_list *bl, int flag)
  369. {
  370. int b;
  371. nullpo_retr(0, bl);
  372. // ?にblocklistから?けている
  373. if (bl->prev == NULL) {
  374. if (bl->next != NULL) {
  375. // prevがNULLでnextがNULLでないのは有ってはならない
  376. if(battle_config.error_log)
  377. ShowError("map_delblock error : bl->next!=NULL\n");
  378. }
  379. return 0;
  380. }
  381. #ifdef CELL_NOSTACK
  382. map_delblcell(bl);
  383. #endif
  384. b = bl->x/BLOCK_SIZE+(bl->y/BLOCK_SIZE)*map[bl->m].bxs;
  385. if (bl->type == BL_PC && flag)
  386. if (--map[bl->m].users == 0 && battle_config.dynamic_mobs) //[Skotlex]
  387. map_removemobs(bl->m);
  388. if (bl->next)
  389. bl->next->prev = bl->prev;
  390. if (bl->prev == &bl_head) {
  391. // リストの頭なので、map[]のblock_listを更新する
  392. if (bl->type == BL_MOB) {
  393. map[bl->m].block_mob[b] = bl->next;
  394. if ((map[bl->m].block_mob_count[b]--) < 0)
  395. map[bl->m].block_mob_count[b] = 0;
  396. } else {
  397. map[bl->m].block[b] = bl->next;
  398. if((map[bl->m].block_count[b]--) < 0)
  399. map[bl->m].block_count[b] = 0;
  400. }
  401. } else {
  402. bl->prev->next = bl->next;
  403. }
  404. bl->next = NULL;
  405. bl->prev = NULL;
  406. return 0;
  407. }
  408. /*==========================================
  409. * Moves a block a x/y target position. [Skotlex]
  410. * Pass flag as 1 to prevent doing skill_unit_move checks
  411. * (which are executed by default on BL_CHAR types)
  412. *------------------------------------------
  413. */
  414. int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) {
  415. int x0 = bl->x, y0 = bl->y;
  416. struct status_change *sc = NULL;
  417. int moveblock = ( x0/BLOCK_SIZE != x1/BLOCK_SIZE || y0/BLOCK_SIZE != y1/BLOCK_SIZE);
  418. if (!bl->prev) {
  419. //Block not in map, just update coordinates, but do naught else.
  420. bl->x = x1;
  421. bl->y = y1;
  422. return 0;
  423. }
  424. //TODO: Perhaps some outs of bounds checking should be placed here?
  425. if (bl->type&BL_CHAR) {
  426. skill_unit_move(bl,tick,2);
  427. sc = status_get_sc(bl);
  428. if (sc && sc->count) {
  429. if (sc->data[SC_CLOSECONFINE].timer != -1)
  430. status_change_end(bl, SC_CLOSECONFINE, -1);
  431. if (sc->data[SC_CLOSECONFINE2].timer != -1)
  432. status_change_end(bl, SC_CLOSECONFINE2, -1);
  433. }
  434. }
  435. if (moveblock) map_delblock_sub(bl,0);
  436. #ifdef CELL_NOSTACK
  437. else map_delblcell(bl);
  438. #endif
  439. bl->x = x1;
  440. bl->y = y1;
  441. if (moveblock) map_addblock_sub(bl,0);
  442. #ifdef CELL_NOSTACK
  443. else map_addblcell(bl);
  444. #endif
  445. if (bl->type&BL_CHAR) {
  446. skill_unit_move(bl,tick,3);
  447. if (sc) {
  448. if (sc->option&OPTION_CLOAK)
  449. skill_check_cloaking(bl);
  450. if (sc->count) {
  451. if (sc->data[SC_DANCING].timer != -1) {
  452. //Cancel Moonlight Petals if moved from casting position. [Skotlex]
  453. if (sc->data[SC_DANCING].val1 == CG_MOONLIT)
  454. skill_stop_dancing(bl);
  455. else
  456. skill_unit_move_unit_group((struct skill_unit_group *)sc->data[SC_DANCING].val2, bl->m, x1-x0, y1-y0);
  457. }
  458. }
  459. }
  460. }
  461. return 0;
  462. }
  463. /*==========================================
  464. * 周?のPC人?を?える (unused)
  465. *------------------------------------------
  466. */
  467. int map_countnearpc (int m, int x, int y)
  468. {
  469. int bx, by, c = 0;
  470. struct block_list *bl=NULL;
  471. if (map[m].users == 0)
  472. return 0;
  473. for (by = y/BLOCK_SIZE-AREA_SIZE/BLOCK_SIZE-1; by<=y/BLOCK_SIZE+AREA_SIZE/BLOCK_SIZE+1; by++) {
  474. if (by < 0 || by >= map[m].bys)
  475. continue;
  476. for (bx = x/BLOCK_SIZE-AREA_SIZE/BLOCK_SIZE-1; bx <= x/BLOCK_SIZE+AREA_SIZE/BLOCK_SIZE+1; bx++) {
  477. if (bx < 0 || bx >= map[m].bxs)
  478. continue;
  479. bl = map[m].block[bx+by*map[m].bxs];
  480. while(bl) {
  481. if (bl->type == BL_PC)
  482. c++;
  483. bl = bl->next;
  484. }
  485. }
  486. }
  487. return c;
  488. }
  489. /*==========================================
  490. * Counts specified number of objects on given cell.
  491. *------------------------------------------
  492. */
  493. int map_count_oncell(int m, int x, int y, int type) {
  494. int bx,by;
  495. struct block_list *bl=NULL;
  496. int i,c;
  497. int count = 0;
  498. if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys))
  499. return 0;
  500. bx = x/BLOCK_SIZE;
  501. by = y/BLOCK_SIZE;
  502. if (type == 0 || type != BL_MOB)
  503. {
  504. bl = map[m].block[bx+by*map[m].bxs];
  505. c = map[m].block_count[bx+by*map[m].bxs];
  506. for(i=0;i<c && bl;i++,bl=bl->next)
  507. if(bl->x == x && bl->y == y && bl->type == (type?type:BL_PC)) count++;
  508. }
  509. if (type == 0 || type == BL_MOB)
  510. {
  511. bl = map[m].block_mob[bx+by*map[m].bxs];
  512. c = map[m].block_mob_count[bx+by*map[m].bxs];
  513. for(i=0;i<c && bl;i++,bl=bl->next){
  514. if(bl->x == x && bl->y == y) count++;
  515. }
  516. }
  517. return count;
  518. }
  519. /*
  520. * ォサォ・セェホ��ェヒフクェトェアェソォケォュォ・讚ヒォテォネェ��ケ
  521. */
  522. struct skill_unit *map_find_skill_unit_oncell(struct block_list *target,int x,int y,int skill_id,struct skill_unit *out_unit)
  523. {
  524. int m,bx,by;
  525. struct block_list *bl;
  526. int i,c;
  527. struct skill_unit *unit;
  528. m = target->m;
  529. if (x < 0 || y < 0 || (x >= map[m].xs) || (y >= map[m].ys))
  530. return NULL;
  531. bx = x/BLOCK_SIZE;
  532. by = y/BLOCK_SIZE;
  533. bl = map[m].block[bx+by*map[m].bxs];
  534. c = map[m].block_count[bx+by*map[m].bxs];
  535. for(i=0;i<c && bl;i++,bl=bl->next){
  536. if (bl->x != x || bl->y != y || bl->type != BL_SKILL)
  537. continue;
  538. unit = (struct skill_unit *) bl;
  539. if (unit==out_unit || !unit->alive ||
  540. !unit->group || unit->group->skill_id!=skill_id)
  541. continue;
  542. if (battle_check_target(&unit->bl,target,unit->group->target_flag)>0)
  543. return unit;
  544. }
  545. return NULL;
  546. }
  547. /*==========================================
  548. * Adapted from foreachinarea for an easier invocation. [Skotlex]
  549. *------------------------------------------
  550. */
  551. int map_foreachinrange(int (*func)(struct block_list*,va_list),struct block_list *center, int range,int type,...) {
  552. va_list ap;
  553. int bx,by,m;
  554. int returnCount =0; //total sum of returned values of func() [Skotlex]
  555. struct block_list *bl=NULL;
  556. int blockcount=bl_list_count,i,c;
  557. int x0,x1,y0,y1;
  558. m = center->m;
  559. if (m < 0)
  560. return 0;
  561. va_start(ap,type);
  562. x0 = center->x-range;
  563. x1 = center->x+range;
  564. y0 = center->y-range;
  565. y1 = center->y+range;
  566. if (x0 < 0) x0 = 0;
  567. if (y0 < 0) y0 = 0;
  568. if (x1 >= map[m].xs) x1 = map[m].xs-1;
  569. if (y1 >= map[m].ys) y1 = map[m].ys-1;
  570. if (type&~BL_MOB)
  571. for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) {
  572. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  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. if(bl && bl->type&type
  577. && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1
  578. //For speed purposes, it does not checks actual range by default.
  579. //Feel free to uncomment if you want a more "exact" approach.
  580. // && check_distance_bl(center, bl, range)
  581. && bl_list_count<BL_LIST_MAX)
  582. bl_list[bl_list_count++]=bl;
  583. }
  584. }
  585. }
  586. if(type&BL_MOB)
  587. for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
  588. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  589. bl = map[m].block_mob[bx+by*map[m].bxs];
  590. c = map[m].block_mob_count[bx+by*map[m].bxs];
  591. for(i=0;i<c && bl;i++,bl=bl->next){
  592. if(bl
  593. && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1
  594. && check_distance_bl(center, bl, range)
  595. && bl_list_count<BL_LIST_MAX)
  596. bl_list[bl_list_count++]=bl;
  597. }
  598. }
  599. }
  600. if(bl_list_count>=BL_LIST_MAX) {
  601. if(battle_config.error_log)
  602. ShowWarning("map_foreachinrange: block count too many!\n");
  603. }
  604. map_freeblock_lock(); // メモリからの解放を禁止する
  605. for(i=blockcount;i<bl_list_count;i++)
  606. if(bl_list[i]->prev) // 有?かどうかチェック
  607. returnCount += func(bl_list[i],ap);
  608. map_freeblock_unlock(); // 解放を許可する
  609. va_end(ap);
  610. bl_list_count = blockcount;
  611. return returnCount; //[Skotlex]
  612. }
  613. /*==========================================
  614. * map m (x0,y0)-(x1,y1)?の全objに?して
  615. * funcを呼ぶ
  616. * type!=0 ならその種類のみ
  617. *------------------------------------------
  618. */
  619. int map_foreachinarea(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int type,...) {
  620. va_list ap;
  621. int bx,by;
  622. int returnCount =0; //total sum of returned values of func() [Skotlex]
  623. struct block_list *bl=NULL;
  624. int blockcount=bl_list_count,i,c;
  625. if (m < 0)
  626. return 0;
  627. va_start(ap,type);
  628. if (x1 < x0)
  629. { //Swap range
  630. bx = x0;
  631. x0 = x1;
  632. x1 = bx;
  633. }
  634. if (y1 < y0)
  635. {
  636. bx = y0;
  637. y0 = y1;
  638. y1 = bx;
  639. }
  640. if (x0 < 0) x0 = 0;
  641. if (y0 < 0) y0 = 0;
  642. if (x1 >= map[m].xs) x1 = map[m].xs-1;
  643. if (y1 >= map[m].ys) y1 = map[m].ys-1;
  644. if (type&~BL_MOB)
  645. for (by = y0 / BLOCK_SIZE; by <= y1 / BLOCK_SIZE; by++) {
  646. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  647. bl = map[m].block[bx+by*map[m].bxs];
  648. c = map[m].block_count[bx+by*map[m].bxs];
  649. for(i=0;i<c && bl;i++,bl=bl->next){
  650. if(bl && bl->type&type && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
  651. bl_list[bl_list_count++]=bl;
  652. }
  653. }
  654. }
  655. if(type&BL_MOB)
  656. for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
  657. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  658. bl = map[m].block_mob[bx+by*map[m].bxs];
  659. c = map[m].block_mob_count[bx+by*map[m].bxs];
  660. for(i=0;i<c && bl;i++,bl=bl->next){
  661. if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
  662. bl_list[bl_list_count++]=bl;
  663. }
  664. }
  665. }
  666. if(bl_list_count>=BL_LIST_MAX) {
  667. if(battle_config.error_log)
  668. ShowWarning("map_foreachinarea: block count too many!\n");
  669. }
  670. map_freeblock_lock(); // メモリからの解放を禁止する
  671. for(i=blockcount;i<bl_list_count;i++)
  672. if(bl_list[i]->prev) // 有?かどうかチェック
  673. returnCount += func(bl_list[i],ap);
  674. map_freeblock_unlock(); // 解放を許可する
  675. va_end(ap);
  676. bl_list_count = blockcount;
  677. return returnCount; //[Skotlex]
  678. }
  679. /*==========================================
  680. * 矩形(x0,y0)-(x1,y1)が(dx,dy)移動した暫フ
  681. * 領域外になる領域(矩形かL字形)?のobjに
  682. * ?してfuncを呼ぶ
  683. *
  684. * dx,dyは-1,0,1のみとする(どんな値でもいいっぽい?)
  685. *------------------------------------------
  686. */
  687. int 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,...) {
  688. int bx,by;
  689. int returnCount =0; //total sum of returned values of func() [Skotlex]
  690. struct block_list *bl=NULL;
  691. va_list ap;
  692. int blockcount=bl_list_count,i,c;
  693. va_start(ap,type);
  694. if (x1 < x0)
  695. { //Swap range
  696. bx = x0;
  697. x0 = x1;
  698. x1 = bx;
  699. }
  700. if (y1 < y0)
  701. {
  702. bx = y0;
  703. y0 = y1;
  704. y1 = bx;
  705. }
  706. if(dx==0 || dy==0){
  707. // 矩形領域の場合
  708. if(dx==0){
  709. if(dy<0){
  710. y0=y1+dy+1;
  711. } else {
  712. y1=y0+dy-1;
  713. }
  714. } else if(dy==0){
  715. if(dx<0){
  716. x0=x1+dx+1;
  717. } else {
  718. x1=x0+dx-1;
  719. }
  720. }
  721. if(x0<0) x0=0;
  722. if(y0<0) y0=0;
  723. if(x1>=map[m].xs) x1=map[m].xs-1;
  724. if(y1>=map[m].ys) y1=map[m].ys-1;
  725. for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
  726. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  727. if (type&~BL_MOB) {
  728. bl = map[m].block[bx+by*map[m].bxs];
  729. c = map[m].block_count[bx+by*map[m].bxs];
  730. for(i=0;i<c && bl;i++,bl=bl->next){
  731. if(bl && bl->type&type && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
  732. bl_list[bl_list_count++]=bl;
  733. }
  734. }
  735. if (type&BL_MOB) {
  736. bl = map[m].block_mob[bx+by*map[m].bxs];
  737. c = map[m].block_mob_count[bx+by*map[m].bxs];
  738. for(i=0;i<c && bl;i++,bl=bl->next){
  739. if(bl && bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1 && bl_list_count<BL_LIST_MAX)
  740. bl_list[bl_list_count++]=bl;
  741. }
  742. }
  743. }
  744. }
  745. }else{
  746. // L字領域の場合
  747. if(x0<0) x0=0;
  748. if(y0<0) y0=0;
  749. if(x1>=map[m].xs) x1=map[m].xs-1;
  750. if(y1>=map[m].ys) y1=map[m].ys-1;
  751. for(by=y0/BLOCK_SIZE;by<=y1/BLOCK_SIZE;by++){
  752. for(bx=x0/BLOCK_SIZE;bx<=x1/BLOCK_SIZE;bx++){
  753. if (type & ~BL_MOB) {
  754. bl = map[m].block[bx+by*map[m].bxs];
  755. c = map[m].block_count[bx+by*map[m].bxs];
  756. for(i=0;i<c && bl;i++,bl=bl->next){
  757. if(!bl || !(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1))
  758. continue;
  759. if(bl && bl->type&type && ((dx>0 && bl->x<x0+dx) || (dx<0 && bl->x>x1+dx) ||
  760. (dy>0 && bl->y<y0+dy) || (dy<0 && bl->y>y1+dy)) &&
  761. bl_list_count<BL_LIST_MAX)
  762. bl_list[bl_list_count++]=bl;
  763. }
  764. }
  765. if (type & BL_MOB) {
  766. bl = map[m].block_mob[bx+by*map[m].bxs];
  767. c = map[m].block_mob_count[bx+by*map[m].bxs];
  768. for(i=0;i<c && bl;i++,bl=bl->next){
  769. if(!bl || !(bl->x>=x0 && bl->x<=x1 && bl->y>=y0 && bl->y<=y1))
  770. continue;
  771. if(bl && ((dx>0 && bl->x<x0+dx) || (dx<0 && bl->x>x1+dx) ||
  772. (dy>0 && bl->y<y0+dy) || (dy<0 && bl->y>y1+dy)) &&
  773. bl_list_count<BL_LIST_MAX)
  774. bl_list[bl_list_count++]=bl;
  775. }
  776. }
  777. }
  778. }
  779. }
  780. if(bl_list_count>=BL_LIST_MAX) {
  781. if(battle_config.error_log)
  782. ShowWarning("map_foreachinmovearea: block count too many!\n");
  783. }
  784. map_freeblock_lock(); // メモリからの解放を禁止する
  785. for(i=blockcount;i<bl_list_count;i++)
  786. if(bl_list[i]->prev) { // 有?かどうかチェック
  787. if (bl_list[i]->type == BL_PC
  788. && session[((struct map_session_data *) bl_list[i])->fd] == NULL)
  789. continue;
  790. returnCount += func(bl_list[i],ap);
  791. }
  792. map_freeblock_unlock(); // 解放を許可する
  793. va_end(ap);
  794. bl_list_count = blockcount;
  795. return returnCount;
  796. }
  797. // -- moonsoul (added map_foreachincell which is a rework of map_foreachinarea but
  798. // which only checks the exact single x/y passed to it rather than an
  799. // area radius - may be more useful in some instances)
  800. //
  801. int map_foreachincell(int (*func)(struct block_list*,va_list),int m,int x,int y,int type,...) {
  802. int bx,by;
  803. int returnCount =0; //total sum of returned values of func() [Skotlex]
  804. struct block_list *bl=NULL;
  805. va_list ap;
  806. int blockcount=bl_list_count,i,c;
  807. va_start(ap,type);
  808. by=y/BLOCK_SIZE;
  809. bx=x/BLOCK_SIZE;
  810. if(type&~BL_MOB)
  811. {
  812. bl = map[m].block[bx+by*map[m].bxs];
  813. c = map[m].block_count[bx+by*map[m].bxs];
  814. for(i=0;i<c && bl;i++,bl=bl->next)
  815. {
  816. if(bl && bl->type&type && bl->x==x && bl->y==y && bl_list_count<BL_LIST_MAX)
  817. bl_list[bl_list_count++]=bl;
  818. }
  819. }
  820. if(type&BL_MOB)
  821. {
  822. bl = map[m].block_mob[bx+by*map[m].bxs];
  823. c = map[m].block_mob_count[bx+by*map[m].bxs];
  824. for(i=0;i<c && bl;i++,bl=bl->next)
  825. {
  826. if(bl && bl->x==x && bl->y==y && bl_list_count<BL_LIST_MAX)
  827. bl_list[bl_list_count++]=bl;
  828. }
  829. }
  830. if(bl_list_count>=BL_LIST_MAX) {
  831. if(battle_config.error_log)
  832. ShowWarning("map_foreachincell: block count too many!\n");
  833. }
  834. map_freeblock_lock(); // メモリからの解放を禁止する
  835. for(i=blockcount;i<bl_list_count;i++)
  836. if(bl_list[i]->prev) // 有?かどうかチェック
  837. returnCount += func(bl_list[i],ap);
  838. map_freeblock_unlock(); // 解放を許可する
  839. va_end(ap);
  840. bl_list_count = blockcount;
  841. return returnCount;
  842. }
  843. /*============================================================
  844. * For checking a path between two points (x0, y0) and (x1, y1)
  845. *------------------------------------------------------------
  846. */
  847. int map_foreachinpath(int (*func)(struct block_list*,va_list),int m,int x0,int y0,int x1,int y1,int range,int type,...)
  848. {
  849. int returnCount =0; //total sum of returned values of func() [Skotlex]
  850. //////////////////////////////////////////////////////////////
  851. //
  852. // sharp shooting 3 [Skotlex]
  853. //
  854. //////////////////////////////////////////////////////////////
  855. // problem:
  856. // Same as Sharp Shooting 1. Hits all targets within range of
  857. // the line.
  858. // (t1,t2 t3 and t4 get hit)
  859. //
  860. // target 1
  861. // x t4
  862. // t2
  863. // t3 x
  864. // x
  865. // S
  866. //////////////////////////////////////////////////////////////
  867. // Methodology:
  868. // My trigonometrics and math is a little rusty... so the approach I am writing
  869. // here is basicly do a double for to check for all targets in the square that
  870. // contains the initial and final positions (area range increased to match the
  871. // radius given), then for each object to test, calculate the distance to the
  872. // path and include it if the range fits and the target is in the line (0<k<1,
  873. // as they call it).
  874. // The implementation I took as reference is found at
  875. // http://astronomy.swin.edu.au/~pbourke/geometry/pointline/
  876. // (they have a link to a C implementation, too)
  877. // This approach is a lot like #2 commented on this function, which I have no
  878. // idea why it was commented. I won't use doubles/floats, but pure int math for speed purposes
  879. // The range considered is always the same no matter how close/far the target is because that's
  880. // how SharpShooting works currently in kRO.
  881. //Generic map_foreach* variables.
  882. va_list ap;
  883. int i, blockcount = bl_list_count;
  884. struct block_list *bl;
  885. int c, bx, by;
  886. //method specific variables
  887. int magnitude2; //The square of the magnitude
  888. int k, xi, yi, xu, yu;
  889. int mx0 = x0, mx1 = x1, my0 = y0, my1 = y1;
  890. //Avoid needless calculations by not getting the sqrt right away.
  891. #define MAGNITUDE2(x0, y0, x1, y1) (((x1)-(x0))*((x1)-(x0)) + ((y1)-(y0))*((y1)-(y0)))
  892. if (m < 0)
  893. return 0;
  894. va_start(ap,type);
  895. //Expand target area to cover range.
  896. if (mx0 > mx1)
  897. {
  898. mx0+=range;
  899. mx1-=range;
  900. } else {
  901. mx0-=range;
  902. mx1+=range;
  903. }
  904. if (my0 > my1)
  905. {
  906. my0+=range;
  907. my1-=range;
  908. } else {
  909. my0-=range;
  910. my1+=range;
  911. }
  912. //The two fors assume mx0 < mx1 && my0 < my1
  913. if (mx0 > mx1)
  914. {
  915. k = mx1;
  916. mx1 = mx0;
  917. mx0 = k;
  918. }
  919. if (my0 > my1)
  920. {
  921. k = my1;
  922. my1 = my0;
  923. my0 = k;
  924. }
  925. if (mx0 < 0) mx0 = 0;
  926. if (my0 < 0) my0 = 0;
  927. if (mx1 >= map[m].xs) mx1 = map[m].xs-1;
  928. if (my1 >= map[m].ys) my1 = map[m].ys-1;
  929. range*=range<<8; //Values are shifted later on for higher precision using int math.
  930. magnitude2 = MAGNITUDE2(x0,y0, x1,y1);
  931. if (magnitude2 < 1) //Same begin and ending point, can't trace path.
  932. return 0;
  933. if (type & ~BL_MOB)
  934. for (by = my0 / BLOCK_SIZE; by <= my1 / BLOCK_SIZE; by++) {
  935. for(bx=mx0/BLOCK_SIZE;bx<=mx1/BLOCK_SIZE;bx++){
  936. bl = map[m].block[bx+by*map[m].bxs];
  937. c = map[m].block_count[bx+by*map[m].bxs];
  938. for(i=0;i<c && bl;i++,bl=bl->next){
  939. if(bl && bl->type&type && bl_list_count<BL_LIST_MAX)
  940. {
  941. xi = bl->x;
  942. yi = bl->y;
  943. k = (xi-x0)*(x1-x0) + (yi-y0)*(y1-y0);
  944. if (k < 0)// || k > magnitude2) //No check to see if it lies after the target's point.
  945. continue;
  946. //All these shifts are to increase the precision of the intersection point and distance considering how it's
  947. //int math.
  948. k = (k<<4)/magnitude2; //k will be between 1~16 instead of 0~1
  949. xi<<=4;
  950. yi<<=4;
  951. xu= (x0<<4) +k*(x1-x0);
  952. yu= (y0<<4) +k*(y1-y0);
  953. k = MAGNITUDE2(xi, yi, xu, yu);
  954. //If all dot coordinates were <<4 the square of the magnitude is <<8
  955. if (k > range)
  956. continue;
  957. bl_list[bl_list_count++]=bl;
  958. }
  959. }
  960. }
  961. }
  962. if(type&BL_MOB)
  963. for(by=my0/BLOCK_SIZE;by<=my1/BLOCK_SIZE;by++){
  964. for(bx=mx0/BLOCK_SIZE;bx<=mx1/BLOCK_SIZE;bx++){
  965. bl = map[m].block_mob[bx+by*map[m].bxs];
  966. c = map[m].block_mob_count[bx+by*map[m].bxs];
  967. for(i=0;i<c && bl;i++,bl=bl->next){
  968. if(bl && bl_list_count<BL_LIST_MAX)
  969. {
  970. xi = bl->x;
  971. yi = bl->y;
  972. k = (xi-x0)*(x1-x0) + (yi-y0)*(y1-y0);
  973. if (k < 0)// || k > magnitude2) //No check to see if it lies after the target's point.
  974. continue;
  975. k = (k<<4)/magnitude2; //k will be between 1~16 instead of 0~1
  976. xi<<=4;
  977. yi<<=4;
  978. xu= (x0<<4) +k*(x1-x0);
  979. yu= (y0<<4) +k*(y1-y0);
  980. k = MAGNITUDE2(xi, yi, xu, yu);
  981. //If all dot coordinates were <<4 the square of the magnitude is <<8
  982. if (k > range)
  983. continue;
  984. bl_list[bl_list_count++]=bl;
  985. }
  986. }
  987. }
  988. }
  989. if(bl_list_count>=BL_LIST_MAX) {
  990. if(battle_config.error_log)
  991. ShowWarning("map_foreachinpath: block count too many!\n");
  992. }
  993. map_freeblock_lock(); // メモリからの解放を禁止する
  994. for(i=blockcount;i<bl_list_count;i++)
  995. if(bl_list[i]->prev) // 有?かどうかチェック
  996. returnCount += func(bl_list[i],ap);
  997. map_freeblock_unlock(); // 解放を許可する
  998. va_end(ap);
  999. bl_list_count = blockcount;
  1000. return returnCount; //[Skotlex]
  1001. }
  1002. // Copy of map_foreachincell, but applied to the whole map. [Skotlex]
  1003. int map_foreachinmap(int (*func)(struct block_list*,va_list),int m,int type,...) {
  1004. int b, bsize;
  1005. int returnCount =0; //total sum of returned values of func() [Skotlex]
  1006. struct block_list *bl=NULL;
  1007. va_list ap;
  1008. int blockcount=bl_list_count,i,c;
  1009. va_start(ap,type);
  1010. bsize = map[m].bxs * map[m].bys;
  1011. if(type&~BL_MOB)
  1012. {
  1013. for(b=0;b<bsize;b++){
  1014. bl = map[m].block[b];
  1015. c = map[m].block_count[b];
  1016. for(i=0;i<c && bl;i++,bl=bl->next)
  1017. {
  1018. if(bl && bl->type&type && bl_list_count<BL_LIST_MAX)
  1019. bl_list[bl_list_count++]=bl;
  1020. }
  1021. }
  1022. }
  1023. if(type&BL_MOB)
  1024. {
  1025. for(b=0;b<bsize;b++){
  1026. bl = map[m].block_mob[b];
  1027. c = map[m].block_mob_count[b];
  1028. for(i=0;i<c && bl;i++,bl=bl->next)
  1029. {
  1030. if(bl && bl_list_count<BL_LIST_MAX)
  1031. bl_list[bl_list_count++]=bl;
  1032. }
  1033. }
  1034. }
  1035. if(bl_list_count>=BL_LIST_MAX) {
  1036. if(battle_config.error_log)
  1037. ShowWarning("map_foreachinmap: block count too many!\n");
  1038. }
  1039. map_freeblock_lock(); // メモリからの解放を禁止する
  1040. for(i=blockcount;i<bl_list_count;i++)
  1041. if(bl_list[i]->prev) // 有?かどうかチェック
  1042. returnCount += func(bl_list[i],ap);
  1043. map_freeblock_unlock(); // 解放を許可する
  1044. va_end(ap);
  1045. bl_list_count = blockcount;
  1046. return returnCount;
  1047. }
  1048. /*==========================================
  1049. * 床アイテムやエフェクト用の一三bj割り?て
  1050. * object[]への保存とid_db登?まで
  1051. *
  1052. * bl->idもこの中で設定して問題無い?
  1053. *------------------------------------------
  1054. */
  1055. int map_addobject(struct block_list *bl) {
  1056. int i;
  1057. if( bl == NULL ){
  1058. ShowWarning("map_addobject nullpo?\n");
  1059. return 0;
  1060. }
  1061. if(first_free_object_id<2 || first_free_object_id>=MAX_FLOORITEM)
  1062. first_free_object_id=2;
  1063. for(i=first_free_object_id;i<MAX_FLOORITEM && objects[i];i++);
  1064. if(i>=MAX_FLOORITEM){
  1065. if(battle_config.error_log)
  1066. ShowWarning("no free object id\n");
  1067. return 0;
  1068. }
  1069. first_free_object_id=i;
  1070. if(last_object_id<i)
  1071. last_object_id=i;
  1072. objects[i]=bl;
  1073. idb_put(id_db,i,bl);
  1074. return i;
  1075. }
  1076. /*==========================================
  1077. * 一三bjectの解放
  1078. * map_delobjectのfreeしないバ?ジョン
  1079. *------------------------------------------
  1080. */
  1081. int map_delobjectnofree(int id) {
  1082. if(objects[id]==NULL)
  1083. return 0;
  1084. map_delblock(objects[id]);
  1085. idb_remove(id_db,id);
  1086. objects[id]=NULL;
  1087. if(first_free_object_id>id)
  1088. first_free_object_id=id;
  1089. while(last_object_id>2 && objects[last_object_id]==NULL)
  1090. last_object_id--;
  1091. return 0;
  1092. }
  1093. /*==========================================
  1094. * 一三bjectの解放
  1095. * block_listからの削除、id_dbからの削除
  1096. * object dataのfree、object[]へのNULL代入
  1097. *
  1098. * addとの??性が無いのが?になる
  1099. *------------------------------------------
  1100. */
  1101. int map_delobject(int id) {
  1102. struct block_list *obj = objects[id];
  1103. if(obj==NULL)
  1104. return 0;
  1105. map_delobjectnofree(id);
  1106. map_freeblock(obj);
  1107. return 0;
  1108. }
  1109. /*==========================================
  1110. * 全一三bj相手にfuncを呼ぶ
  1111. *
  1112. *------------------------------------------
  1113. */
  1114. void map_foreachobject(int (*func)(struct block_list*,va_list),int type,...) {
  1115. int i;
  1116. int blockcount=bl_list_count;
  1117. va_list ap;
  1118. va_start(ap,type);
  1119. for(i=2;i<=last_object_id;i++){
  1120. if(objects[i]){
  1121. if(!(objects[i]->type&type))
  1122. continue;
  1123. if(bl_list_count>=BL_LIST_MAX) {
  1124. if(battle_config.error_log)
  1125. ShowWarning("map_foreachobject: too many blocks !\n");
  1126. break;
  1127. }
  1128. bl_list[bl_list_count++]=objects[i];
  1129. }
  1130. }
  1131. map_freeblock_lock();
  1132. for(i=blockcount;i<bl_list_count;i++)
  1133. if( bl_list[i]->prev || bl_list[i]->next )
  1134. func(bl_list[i],ap);
  1135. map_freeblock_unlock();
  1136. va_end(ap);
  1137. bl_list_count = blockcount;
  1138. }
  1139. /*==========================================
  1140. * 床アイテムを消す
  1141. *
  1142. * data==0の暫ヘtimerで消えた殊 * data!=0の暫ヘ拾う等で消えた暫ニして動作
  1143. *
  1144. * 後者は、map_clearflooritem(id)へ
  1145. * map.h?で#defineしてある
  1146. *------------------------------------------
  1147. */
  1148. int map_clearflooritem_timer(int tid,unsigned int tick,int id,int data) {
  1149. struct flooritem_data *fitem=NULL;
  1150. fitem = (struct flooritem_data *)objects[id];
  1151. if(fitem==NULL || fitem->bl.type!=BL_ITEM || (!data && fitem->cleartimer != tid)){
  1152. if(battle_config.error_log)
  1153. ShowError("map_clearflooritem_timer : error\n");
  1154. return 1;
  1155. }
  1156. if(data)
  1157. delete_timer(fitem->cleartimer,map_clearflooritem_timer);
  1158. else if(fitem->item_data.card[0] == (short)0xff00)
  1159. intif_delete_petdata( MakeDWord(fitem->item_data.card[1],fitem->item_data.card[2]) );
  1160. clif_clearflooritem(fitem,0);
  1161. map_delobject(fitem->bl.id);
  1162. return 0;
  1163. }
  1164. /*==========================================
  1165. * (m,x,y) locates a random available free cell around the given coordinates
  1166. * to place an BL_ITEM object. Scan area is 9x9, returns 1 on success.
  1167. * x and y are modified with the target cell when successful.
  1168. *------------------------------------------
  1169. */
  1170. int map_searchrandfreecell(int m,int *x,int *y,int stack) {
  1171. int free_cell,i,j;
  1172. int free_cells[9][2];
  1173. for(free_cell=0,i=-1;i<=1;i++){
  1174. if(i+*y<0 || i+*y>=map[m].ys)
  1175. continue;
  1176. for(j=-1;j<=1;j++){
  1177. if(j+*x<0 || j+*x>=map[m].xs)
  1178. continue;
  1179. if(map_getcell(m,j+*x,i+*y,CELL_CHKNOPASS))
  1180. continue;
  1181. //Avoid item stacking to prevent against exploits. [Skotlex]
  1182. if(stack && map_count_oncell(m,j+*x,i+*y, BL_ITEM) > stack)
  1183. continue;
  1184. free_cells[free_cell][0] = j+*x;
  1185. free_cells[free_cell++][1] = i+*y;
  1186. }
  1187. }
  1188. if(free_cell==0)
  1189. return 0;
  1190. free_cell = rand()%free_cell;
  1191. *x = free_cells[free_cell][0];
  1192. *y = free_cells[free_cell][1];
  1193. return 1;
  1194. }
  1195. /*==========================================
  1196. * (m,x,y)を中心に3x3以?に床アイテム設置
  1197. *
  1198. * item_dataはamount以外をcopyする
  1199. * type flag: &1 MVP item. &2 do stacking check.
  1200. *------------------------------------------
  1201. */
  1202. int map_addflooritem(struct item *item_data,int amount,int m,int x,int y,struct map_session_data *first_sd,
  1203. struct map_session_data *second_sd,struct map_session_data *third_sd,int type) {
  1204. int r;
  1205. unsigned int tick;
  1206. struct flooritem_data *fitem=NULL;
  1207. nullpo_retr(0, item_data);
  1208. if(!map_searchrandfreecell(m,&x,&y,type&2?1:0))
  1209. return 0;
  1210. r=rand();
  1211. fitem = (struct flooritem_data *)aCalloc(1,sizeof(*fitem));
  1212. fitem->bl.type=BL_ITEM;
  1213. fitem->bl.prev = fitem->bl.next = NULL;
  1214. fitem->bl.m=m;
  1215. fitem->bl.x=x;
  1216. fitem->bl.y=y;
  1217. fitem->bl.id = map_addobject(&fitem->bl);
  1218. if(fitem->bl.id==0){
  1219. aFree(fitem);
  1220. return 0;
  1221. }
  1222. tick = gettick();
  1223. if(first_sd) {
  1224. fitem->first_get_id = first_sd->bl.id;
  1225. if(type&1)
  1226. fitem->first_get_tick = tick + battle_config.mvp_item_first_get_time;
  1227. else
  1228. fitem->first_get_tick = tick + battle_config.item_first_get_time;
  1229. }
  1230. if(second_sd) {
  1231. fitem->second_get_id = second_sd->bl.id;
  1232. if(type&1)
  1233. fitem->second_get_tick = tick + battle_config.mvp_item_first_get_time + battle_config.mvp_item_second_get_time;
  1234. else
  1235. fitem->second_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time;
  1236. }
  1237. if(third_sd) {
  1238. fitem->third_get_id = third_sd->bl.id;
  1239. if(type&1)
  1240. 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;
  1241. else
  1242. fitem->third_get_tick = tick + battle_config.item_first_get_time + battle_config.item_second_get_time + battle_config.item_third_get_time;
  1243. }
  1244. memcpy(&fitem->item_data,item_data,sizeof(*item_data));
  1245. fitem->item_data.amount=amount;
  1246. fitem->subx=(r&3)*3+3;
  1247. fitem->suby=((r>>2)&3)*3+3;
  1248. fitem->cleartimer=add_timer(gettick()+battle_config.flooritem_lifetime,map_clearflooritem_timer,fitem->bl.id,0);
  1249. map_addblock(&fitem->bl);
  1250. clif_dropflooritem(fitem);
  1251. return fitem->bl.id;
  1252. }
  1253. static void* create_charid2nick(DBKey key, va_list args) {
  1254. struct charid2nick *p;
  1255. p = (struct charid2nick *)aCallocA(1, sizeof (struct charid2nick));
  1256. return p;
  1257. }
  1258. /*==========================================
  1259. * charid_dbへ追加(返信待ちがあれば返信)
  1260. *------------------------------------------
  1261. */
  1262. void map_addchariddb(int charid, char *name) {
  1263. struct charid2nick *p;
  1264. int req = 0;
  1265. p = idb_ensure(charid_db,charid,create_charid2nick);
  1266. req = p->req_id;
  1267. p->req_id = 0;
  1268. //We overwrite the nick anyway in case a different one arrived.
  1269. memcpy(p->nick, name, NAME_LENGTH);
  1270. if (req) {
  1271. struct map_session_data *sd = map_id2sd(req);
  1272. if (sd) clif_solved_charname(sd,charid);
  1273. }
  1274. }
  1275. /*==========================================
  1276. * charid_dbへ追加(返信要求のみ)
  1277. *------------------------------------------
  1278. */
  1279. int map_reqchariddb(struct map_session_data * sd,int charid) {
  1280. struct charid2nick *p=NULL;
  1281. nullpo_retr(0, sd);
  1282. p = (struct charid2nick*)idb_get(charid_db,charid);
  1283. if(p) return 0; //Nothing to request, we already have the name!
  1284. p = (struct charid2nick *)aCalloc(1,sizeof(struct charid2nick));
  1285. p->req_id=sd->bl.id;
  1286. idb_put(charid_db,charid,p);
  1287. return 0;
  1288. }
  1289. /*==========================================
  1290. * id_dbへblを追加
  1291. *------------------------------------------
  1292. */
  1293. void map_addiddb(struct block_list *bl) {
  1294. nullpo_retv(bl);
  1295. if (bl->type == BL_PC)
  1296. idb_put(pc_db,bl->id,bl);
  1297. idb_put(id_db,bl->id,bl);
  1298. }
  1299. /*==========================================
  1300. * id_dbからblを削除
  1301. *------------------------------------------
  1302. */
  1303. void map_deliddb(struct block_list *bl) {
  1304. nullpo_retv(bl);
  1305. if (bl->type == BL_PC)
  1306. idb_remove(pc_db,bl->id);
  1307. idb_remove(id_db,bl->id);
  1308. }
  1309. /*==========================================
  1310. * PCのquit?理 map.c?分
  1311. *
  1312. * quit?理の主?が違うような?もしてきた
  1313. *------------------------------------------
  1314. */
  1315. int map_quit(struct map_session_data *sd) {
  1316. //nullpo_retr(0, sd); //Utterly innecessary, all invokations to this function already have an SD non-null check.
  1317. //Learn to use proper coding and stop relying on nullpo_'s for safety :P [Skotlex]
  1318. if(!sd->state.waitingdisconnect) {
  1319. if (sd->npc_timer_id != -1) //Cancel the event timer.
  1320. npc_timerevent_quit(sd);
  1321. if (sd->state.event_disconnect) {
  1322. if (script_config.event_script_type == 0) {
  1323. struct npc_data *npc;
  1324. if ((npc = npc_name2id(script_config.logout_event_name))) {
  1325. run_script(npc->u.scr.script,0,sd->bl.id,npc->bl.id); // PCLogoutNPC
  1326. ShowStatus("Event '"CL_WHITE"%s"CL_RESET"' executed.\n", script_config.logout_event_name);
  1327. }
  1328. } else {
  1329. ShowStatus("%d '"CL_WHITE"%s"CL_RESET"' events executed.\n",
  1330. npc_event_doall_id(script_config.logout_event_name, sd->bl.id), script_config.logout_event_name);
  1331. }
  1332. }
  1333. if(sd->chatID) // チャットから出る
  1334. chat_leavechat(sd);
  1335. if(sd->trade_partner) // 取引を中?する
  1336. trade_tradecancel(sd);
  1337. if(sd->party_invite>0) // パ?ティ?誘を拒否する
  1338. party_reply_invite(sd,sd->party_invite_account,0);
  1339. if(sd->guild_invite>0) // ギルド?誘を拒否する
  1340. guild_reply_invite(sd,sd->guild_invite,0);
  1341. if(sd->guild_alliance>0) // ギルド同盟?誘を拒否する
  1342. guild_reply_reqalliance(sd,sd->guild_alliance_account,0);
  1343. // Force exiting from duel and rejecting
  1344. // all duel invitations when player quit [LuzZza]
  1345. if(sd->duel_group > 0)
  1346. duel_leave(sd->duel_group, sd);
  1347. if(sd->duel_invite > 0)
  1348. duel_reject(sd->duel_invite, sd);
  1349. party_send_logout(sd); // パ?ティのログアウトメッセ?ジ送信
  1350. party_send_dot_remove(sd);//minimap dot fix [Kevin]
  1351. guild_send_memberinfoshort(sd,0); // ギルドのログアウトメッセ?ジ送信
  1352. guild_send_dot_remove(sd);
  1353. pc_cleareventtimer(sd); // イベントタイマを破棄する
  1354. // check if we've been authenticated [celest]
  1355. if (sd->state.auth)
  1356. skill_castcancel(&sd->bl,0); // 詠唱を中?する
  1357. skill_stop_dancing(&sd->bl);// ダンス/演奏中?
  1358. //Status that are not saved...
  1359. if(sd->sc.count) {
  1360. if(sd->sc.data[SC_HIDING].timer!=-1)
  1361. status_change_end(&sd->bl,SC_HIDING,-1);
  1362. if(sd->sc.data[SC_CLOAKING].timer!=-1)
  1363. status_change_end(&sd->bl,SC_CLOAKING,-1);
  1364. if(sd->sc.data[SC_RUN].timer!=-1)
  1365. status_change_end(&sd->bl,SC_RUN,-1);
  1366. if(sd->sc.data[SC_SPURT].timer!=-1)
  1367. status_change_end(&sd->bl,SC_SPURT,-1);
  1368. if(sd->sc.data[SC_BERSERK].timer!=-1)
  1369. status_change_end(&sd->bl,SC_BERSERK,-1);
  1370. }
  1371. skill_clear_unitgroup(&sd->bl); // スキルユニットグル?プの削除
  1372. // check if we've been authenticated [celest]
  1373. if (sd->state.auth) {
  1374. skill_cleartimerskill(&sd->bl);
  1375. pc_stop_walking(sd,0);
  1376. pc_stopattack(sd);
  1377. pc_stop_following(sd);
  1378. pc_delinvincibletimer(sd);
  1379. }
  1380. pc_delspiritball(sd,sd->spiritball,1);
  1381. skill_gangsterparadise(sd,0);
  1382. skill_unit_move(&sd->bl,gettick(),4);
  1383. if (sd->state.auth)
  1384. status_calc_pc(sd,4);
  1385. // skill_clear_unitgroup(&sd->bl); // [Sara-chan]
  1386. if (!(sd->sc.option & OPTION_INVISIBLE))
  1387. clif_clearchar_area(&sd->bl,2);
  1388. chrif_save_scdata(sd); //Save status changes, then clear'em out from memory. [Skotlex]
  1389. status_change_clear(&sd->bl,1);
  1390. if(sd->status.pet_id && sd->pd) {
  1391. pet_lootitem_drop(sd->pd,sd);
  1392. pet_remove_map(sd);
  1393. if(sd->pet.intimate <= 0) {
  1394. intif_delete_petdata(sd->status.pet_id);
  1395. sd->status.pet_id = 0;
  1396. sd->pd = NULL;
  1397. sd->petDB = NULL;
  1398. }
  1399. else
  1400. intif_save_petdata(sd->status.account_id,&sd->pet);
  1401. }
  1402. if(pc_isdead(sd))
  1403. pc_setrestartvalue(sd,2);
  1404. pc_clean_skilltree(sd);
  1405. //The storage closing routines will save the char if needed. [Skotlex]
  1406. if (!sd->state.storage_flag)
  1407. chrif_save(sd,1);
  1408. else if (sd->state.storage_flag == 1)
  1409. storage_storage_quit(sd,1);
  1410. else if (sd->state.storage_flag == 2)
  1411. storage_guild_storage_quit(sd,1);
  1412. map_delblock(&sd->bl);
  1413. } else { //Try to free some data, without saving anything (this could be invoked on map server change. [Skotlex]
  1414. if (sd->bl.prev != NULL)
  1415. { //Remove from map...
  1416. if (!(sd->sc.option & OPTION_INVISIBLE))
  1417. clif_clearchar_area(&sd->bl,2);
  1418. map_delblock(&sd->bl);
  1419. }
  1420. if (sd->pd)
  1421. pet_remove_map(sd);
  1422. }
  1423. if (sd->stack) {
  1424. script_free_stack(sd->stack);
  1425. sd->stack= NULL;
  1426. }
  1427. // chrif_char_offline(sd); //chrif_save handles this now.
  1428. //Do we really need to remove the name?
  1429. idb_remove(charid_db,sd->status.char_id);
  1430. idb_remove(id_db,sd->bl.id);
  1431. idb_remove(pc_db,sd->bl.id);
  1432. // Notify friends that this char logged out. [Skotlex]
  1433. clif_foreachclient(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0);
  1434. if(sd->reg)
  1435. { //Double logout already freed pointer fix... [Skotlex]
  1436. aFree(sd->reg);
  1437. sd->reg = NULL;
  1438. sd->reg_num = 0;
  1439. }
  1440. if(sd->regstr)
  1441. {
  1442. aFree(sd->regstr);
  1443. sd->regstr = NULL;
  1444. sd->regstr_num = 0;
  1445. }
  1446. if(!sd->fd) //There is no session connected, and as such socket.c won't free the data, we must do it. [Skotlex]
  1447. aFree(sd);
  1448. return 0;
  1449. }
  1450. /*==========================================
  1451. * id番?のPCを探す。居なければNULL
  1452. *------------------------------------------
  1453. */
  1454. struct map_session_data * map_id2sd(int id) {
  1455. // Now using pc_db to handle all players, should be quicker than both previous methods at a small expense of more memory. [Skotlex]
  1456. if (id <= 0) return NULL;
  1457. return (struct map_session_data*)idb_get(pc_db,id);
  1458. }
  1459. /*==========================================
  1460. * char_id番?の名前を探す
  1461. *------------------------------------------
  1462. */
  1463. char * map_charid2nick(int id) {
  1464. struct charid2nick *p = (struct charid2nick*)idb_get(charid_db,id);
  1465. if(p==NULL)
  1466. return NULL;
  1467. return p->nick;
  1468. }
  1469. struct map_session_data * map_charid2sd(int id) {
  1470. int i, users;
  1471. struct map_session_data **all_sd;
  1472. if (id <= 0) return 0;
  1473. all_sd = map_getallusers(&users);
  1474. for(i = 0; i < users; i++)
  1475. if (all_sd[i] && all_sd[i]->status.char_id == id)
  1476. return all_sd[i];
  1477. return NULL;
  1478. }
  1479. /*==========================================
  1480. * Search session data from a nick name
  1481. * (without sensitive case if necessary)
  1482. * return map_session_data pointer or NULL
  1483. *------------------------------------------
  1484. */
  1485. struct map_session_data * map_nick2sd(char *nick) {
  1486. int i, quantity=0, nicklen, users;
  1487. struct map_session_data *sd = NULL;
  1488. struct map_session_data *pl_sd = NULL, **pl_allsd;
  1489. if (nick == NULL)
  1490. return NULL;
  1491. nicklen = strlen(nick);
  1492. pl_allsd = map_getallusers(&users);
  1493. for (i = 0; i < users; i++) {
  1494. pl_sd = pl_allsd[i];
  1495. // Without case sensitive check (increase the number of similar character names found)
  1496. if (strnicmp(pl_sd->status.name, nick, nicklen) == 0) {
  1497. // Strict comparison (if found, we finish the function immediatly with correct value)
  1498. if (strcmp(pl_sd->status.name, nick) == 0)
  1499. return pl_sd;
  1500. quantity++;
  1501. sd = pl_sd;
  1502. }
  1503. }
  1504. // Here, the exact character name is not found
  1505. // We return the found index of a similar account ONLY if there is 1 similar character
  1506. if (quantity == 1)
  1507. return sd;
  1508. // Exact character name is not found and 0 or more than 1 similar characters have been found ==> we say not found
  1509. return NULL;
  1510. }
  1511. /*==========================================
  1512. * id番?の物を探す
  1513. * 一三bjectの場合は配列を引くのみ
  1514. *------------------------------------------
  1515. */
  1516. struct block_list * map_id2bl(int id)
  1517. {
  1518. struct block_list *bl=NULL;
  1519. if(id >= 0 && id < sizeof(objects)/sizeof(objects[0]))
  1520. bl = objects[id];
  1521. else
  1522. bl = idb_get(id_db,id);
  1523. return bl;
  1524. }
  1525. static int map_getallpc_sub(DBKey key,void * data,va_list ap)
  1526. {
  1527. struct map_session_data *sd = (struct map_session_data*) data;
  1528. if (!sd->state.auth || sd->state.waitingdisconnect || sd->state.finalsave)
  1529. return 1; //Do not count in not-yet authenticated characters or ready to disconnect ones.
  1530. return 0;
  1531. }
  1532. /*==========================================
  1533. * Returns an array of all players in the server (includes non connected ones) [Skotlex]
  1534. * The int pointer given returns the count of elements in the array.
  1535. * If null is passed, it is requested that the memory be freed (for shutdown), and null is returned.
  1536. *------------------------------------------
  1537. */
  1538. struct map_session_data** map_getallusers(int *users) {
  1539. static struct map_session_data **all_sd=NULL;
  1540. static unsigned int all_count = 0;
  1541. if (users == NULL)
  1542. { //Free up data
  1543. if (all_sd) aFree(all_sd);
  1544. all_sd = NULL;
  1545. return NULL;
  1546. }
  1547. if (all_sd == NULL)
  1548. { //Init data
  1549. all_count = pc_db->size(pc_db); //This is the real number of chars in the db, better use this than the actual "online" count.
  1550. if (all_count < 1)
  1551. all_count = 10; //Allow room for at least 10 chars.
  1552. all_sd = aCalloc(all_count, sizeof(struct map_session_data*)); //it's actually just the size of a pointer.
  1553. }
  1554. if (all_count < pc_db->size(pc_db))
  1555. {
  1556. all_count = pc_db->size(pc_db)+10; //Give some room to prevent doing reallocs often.
  1557. all_sd = aRealloc(all_sd, all_count*sizeof(struct map_session_data*));
  1558. }
  1559. *users = pc_db->getall(pc_db,(void**)all_sd,all_count,map_getallpc_sub);
  1560. if (*users > (signed int)all_count) //Which should be impossible...
  1561. *users = all_count;
  1562. return all_sd;
  1563. }
  1564. /*==========================================
  1565. * id_db?の全てにfuncを?行
  1566. *------------------------------------------
  1567. */
  1568. int map_foreachiddb(int (*func)(DBKey,void*,va_list),...) {
  1569. va_list ap;
  1570. va_start(ap,func);
  1571. id_db->foreach(id_db,func,ap);
  1572. va_end(ap);
  1573. return 0;
  1574. }
  1575. /*==========================================
  1576. * map.npcへ追加 (warp等の領域持ちのみ)
  1577. *------------------------------------------
  1578. */
  1579. int map_addnpc(int m,struct npc_data *nd) {
  1580. int i;
  1581. if(m<0 || m>=map_num)
  1582. return -1;
  1583. for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++)
  1584. if(map[m].npc[i]==NULL)
  1585. break;
  1586. if(i==MAX_NPC_PER_MAP){
  1587. if(battle_config.error_log)
  1588. ShowWarning("too many NPCs in one map %s\n",map[m].name);
  1589. return -1;
  1590. }
  1591. if(i==map[m].npc_num){
  1592. map[m].npc_num++;
  1593. }
  1594. nullpo_retr(0, nd);
  1595. map[m].npc[i]=nd;
  1596. nd->n = i;
  1597. idb_put(id_db,nd->bl.id,nd);
  1598. return i;
  1599. }
  1600. void map_removenpc(void) {
  1601. int i,m,n=0;
  1602. for(m=0;m<map_num;m++) {
  1603. for(i=0;i<map[m].npc_num && i<MAX_NPC_PER_MAP;i++) {
  1604. if(map[m].npc[i]!=NULL) {
  1605. clif_clearchar_area(&map[m].npc[i]->bl,2);
  1606. map_delblock(&map[m].npc[i]->bl);
  1607. idb_remove(id_db,map[m].npc[i]->bl.id);
  1608. if(map[m].npc[i]->bl.subtype==SCRIPT) {
  1609. aFree(map[m].npc[i]->u.scr.script);
  1610. aFree(map[m].npc[i]->u.scr.label_list);
  1611. }
  1612. aFree(map[m].npc[i]);
  1613. map[m].npc[i] = NULL;
  1614. n++;
  1615. }
  1616. }
  1617. }
  1618. ShowStatus("Successfully removed and freed from memory '"CL_WHITE"%d"CL_RESET"' NPCs.\n",n);
  1619. }
  1620. /*=========================================
  1621. * Dynamic Mobs [Wizputer]
  1622. *-----------------------------------------
  1623. */
  1624. // allocates a struct when it there is place free in the cache,
  1625. // and returns NULL otherwise
  1626. // -- i'll just leave the old code in case it's needed ^^;
  1627. struct mob_list* map_addmobtolist(unsigned short m)
  1628. {
  1629. size_t i;
  1630. for (i = 0; i < MAX_MOB_LIST_PER_MAP; i++) {
  1631. if (map[m].moblist[i] == NULL) {
  1632. map[m].moblist[i] = (struct mob_list *) aMalloc (sizeof(struct mob_list));
  1633. return map[m].moblist[i];
  1634. }
  1635. }
  1636. return NULL;
  1637. }
  1638. void map_spawnmobs(int m)
  1639. {
  1640. int i, k=0;
  1641. if (map[m].mob_delete_timer != -1)
  1642. { //Mobs have not been removed yet [Skotlex]
  1643. delete_timer(map[m].mob_delete_timer, map_removemobs_timer);
  1644. map[m].mob_delete_timer = -1;
  1645. return;
  1646. }
  1647. for(i=0; i<MAX_MOB_LIST_PER_MAP; i++)
  1648. if(map[m].moblist[i]!=NULL)
  1649. {
  1650. k+=map[m].moblist[i]->num;
  1651. npc_parse_mob2(map[m].moblist[i],1);
  1652. }
  1653. if (battle_config.etc_log && k > 0)
  1654. {
  1655. ShowStatus("Map %s: Spawned '"CL_WHITE"%d"CL_RESET"' mobs.\n",map[m].name, k);
  1656. }
  1657. }
  1658. int mob_cache_cleanup_sub(struct block_list *bl, va_list ap) {
  1659. struct mob_data *md = (struct mob_data *)bl;
  1660. nullpo_retr(0, md);
  1661. //When not to remove:
  1662. //Mob has the cached flag on 0
  1663. if (!md->special_state.cached)
  1664. return 0;
  1665. if (!battle_config.mob_remove_damaged &&
  1666. md->hp < md->db->max_hp) //don't use status_get_maxhp for speed (by the time you have to remove a mob, their status changes should have expired anyway)
  1667. return 0; //Do not remove damaged mobs.
  1668. mob_remove_map(md, 0);
  1669. map_deliddb(&md->bl);
  1670. aFree(md);
  1671. md = NULL;
  1672. return 1;
  1673. }
  1674. int map_removemobs_timer(int tid, unsigned int tick, int id, int data)
  1675. {
  1676. int k;
  1677. if (id < 0 || id >= MAX_MAP_PER_SERVER)
  1678. { //Incorrect map id!
  1679. if (battle_config.error_log)
  1680. ShowError("map_removemobs_timer error: timer %d points to invalid map %d\n",tid, id);
  1681. return 0;
  1682. }
  1683. if (map[id].mob_delete_timer != tid)
  1684. { //Incorrect timer call!
  1685. if (battle_config.error_log)
  1686. ShowError("map_removemobs_timer mismatch: %d != %d (map %s)\n",map[id].mob_delete_timer, tid, map[id].name);
  1687. return 0;
  1688. }
  1689. map[id].mob_delete_timer = -1;
  1690. if (map[id].users > 0) //Map not empty!
  1691. return 1;
  1692. k = map_foreachinmap(mob_cache_cleanup_sub, id, BL_MOB);
  1693. if (battle_config.etc_log && k > 0)
  1694. ShowStatus("Map %s: Removed '"CL_WHITE"%d"CL_RESET"' mobs.\n",map[id].name, k);
  1695. return 1;
  1696. }
  1697. void map_removemobs(int m)
  1698. {
  1699. if (map[m].mob_delete_timer != -1)
  1700. return; //Mobs are already scheduled for removal
  1701. map[m].mob_delete_timer = add_timer(gettick()+battle_config.mob_remove_delay, map_removemobs_timer, m, 0);
  1702. }
  1703. /*==========================================
  1704. * map名からmap番?へ?換
  1705. *------------------------------------------
  1706. */
  1707. int map_mapname2mapid(char *name) {
  1708. unsigned short map_index;
  1709. map_index = mapindex_name2id(name);
  1710. if (!map_index)
  1711. return -1;
  1712. return map_mapindex2mapid(map_index);
  1713. }
  1714. /*==========================================
  1715. * Returns the map of the given mapindex. [Skotlex]
  1716. *------------------------------------------
  1717. */
  1718. int map_mapindex2mapid(unsigned short mapindex) {
  1719. struct map_data *md=NULL;
  1720. if (!mapindex)
  1721. return -1;
  1722. md = (struct map_data*)uidb_get(map_db,(unsigned int)mapindex);
  1723. if(md==NULL || md->gat==NULL)
  1724. return -1;
  1725. return md->m;
  1726. }
  1727. /*==========================================
  1728. * 他鯖map名からip,port?換
  1729. *------------------------------------------
  1730. */
  1731. int map_mapname2ipport(unsigned short name,int *ip,int *port) {
  1732. struct map_data_other_server *mdos=NULL;
  1733. mdos = (struct map_data_other_server*)uidb_get(map_db,(unsigned int)name);
  1734. if(mdos==NULL || mdos->gat) //If gat isn't null, this is a local map.
  1735. return -1;
  1736. *ip=mdos->ip;
  1737. *port=mdos->port;
  1738. return 0;
  1739. }
  1740. /*==========================================
  1741. * Checks if both dirs point in the same direction.
  1742. *------------------------------------------
  1743. */
  1744. int map_check_dir(int s_dir,int t_dir) {
  1745. if(s_dir == t_dir)
  1746. return 0;
  1747. switch(s_dir) {
  1748. case 0:
  1749. if(t_dir == 7 || t_dir == 1 || t_dir == 0)
  1750. return 0;
  1751. break;
  1752. case 1:
  1753. if(t_dir == 0 || t_dir == 2 || t_dir == 1)
  1754. return 0;
  1755. break;
  1756. case 2:
  1757. if(t_dir == 1 || t_dir == 3 || t_dir == 2)
  1758. return 0;
  1759. break;
  1760. case 3:
  1761. if(t_dir == 2 || t_dir == 4 || t_dir == 3)
  1762. return 0;
  1763. break;
  1764. case 4:
  1765. if(t_dir == 3 || t_dir == 5 || t_dir == 4)
  1766. return 0;
  1767. break;
  1768. case 5:
  1769. if(t_dir == 4 || t_dir == 6 || t_dir == 5)
  1770. return 0;
  1771. break;
  1772. case 6:
  1773. if(t_dir == 5 || t_dir == 7 || t_dir == 6)
  1774. return 0;
  1775. break;
  1776. case 7:
  1777. if(t_dir == 6 || t_dir == 0 || t_dir == 7)
  1778. return 0;
  1779. break;
  1780. }
  1781. return 1;
  1782. }
  1783. /*==========================================
  1784. * Returns the direction of the given cell in absolute relation to the char
  1785. * (regardless of where the char is facing)
  1786. *------------------------------------------
  1787. */
  1788. int map_calc_dir( struct block_list *src,int x,int y) {
  1789. int dir=0;
  1790. int dx,dy;
  1791. nullpo_retr(0, src);
  1792. dx=x-src->x;
  1793. dy=y-src->y;
  1794. if( dx==0 && dy==0 ){ // 彼我の場所一致
  1795. dir=0; // 上
  1796. }else if( dx>=0 && dy>=0 ){ // 方向的に右上
  1797. dir=7; // 右上
  1798. if( dx*2-1<dy ) dir=0; // 上
  1799. if( dx>dy*2 ) dir=6; // 右
  1800. }else if( dx>=0 && dy<=0 ){ // 方向的に右下
  1801. dir=5; // 右下
  1802. if( dx*2-1<-dy ) dir=4; // 下
  1803. if( dx>-dy*2 ) dir=6; // 右
  1804. }else if( dx<=0 && dy<=0 ){ // 方向的に左下
  1805. dir=3; // 左下
  1806. if( dx*2+1>dy ) dir=4; // 下
  1807. if( dx<dy*2 ) dir=2; // 左
  1808. }else{ // 方向的に左上
  1809. dir=1; // 左上
  1810. if( -dx*2-1<dy ) dir=0; // 上
  1811. if( -dx>dy*2 ) dir=2; // 左
  1812. }
  1813. return dir;
  1814. }
  1815. /*==========================================
  1816. * Randomizes target cell x,y to a random walkable cell that
  1817. * has the same distance from object as given coordinates do. [Skotlex]
  1818. *------------------------------------------
  1819. */
  1820. int map_random_dir(struct block_list *bl, short *x, short *y) {
  1821. short xi = *x-bl->x;
  1822. short yi = *y-bl->y;
  1823. short i=0, j;
  1824. int dist2 = xi*xi + yi*yi;
  1825. short dist = (short)sqrt(dist2);
  1826. short segment;
  1827. if (dist < 1) dist =1;
  1828. do {
  1829. j = rand()%8; //Pick a random direction
  1830. segment = rand()%dist; //Pick a random interval from the whole vector in that direction
  1831. xi = bl->x + segment*dirx[j];
  1832. segment = (short)sqrt(dist2 - segment*segment); //The complement of the previously picked segment
  1833. yi = bl->y + segment*diry[j];
  1834. } while (map_getcell(bl->m,xi,yi,CELL_CHKNOPASS) && (++i)<100);
  1835. if (i < 100) {
  1836. *x = xi;
  1837. *y = yi;
  1838. return 1;
  1839. }
  1840. return 0;
  1841. }
  1842. // gat系
  1843. /*==========================================
  1844. * (m,x,y)の状態を調べる
  1845. *------------------------------------------
  1846. */
  1847. int map_getcell(int m,int x,int y,cell_t cellchk)
  1848. {
  1849. return (m < 0 || m >= MAX_MAP_PER_SERVER) ? 0 : map_getcellp(&map[m],x,y,cellchk);
  1850. }
  1851. int map_getcellp(struct map_data* m,int x,int y,cell_t cellchk)
  1852. {
  1853. int type, type2;
  1854. #ifdef CELL_NOSTACK
  1855. int type3;
  1856. #endif
  1857. nullpo_ret(m);
  1858. if(x<0 || x>=m->xs-1 || y<0 || y>=m->ys-1)
  1859. {
  1860. if(cellchk==CELL_CHKNOPASS) return 1;
  1861. return 0;
  1862. }
  1863. type = m->gat[x+y*m->xs];
  1864. type2 = m->cell[x+y*m->xs];
  1865. #ifdef CELL_NOSTACK
  1866. type3 = m->cell_bl[x+y*m->xs];
  1867. #endif
  1868. switch(cellchk)
  1869. {
  1870. case CELL_CHKPASS:
  1871. #ifdef CELL_NOSTACK
  1872. if (type3 >= battle_config.cell_stack_limit) return 0;
  1873. #endif
  1874. case CELL_CHKREACH:
  1875. return (type!=1 && type!=5 && !(type2&(CELL_MOONLIT|CELL_ICEWALL)));
  1876. case CELL_CHKNOPASS:
  1877. #ifdef CELL_NOSTACK
  1878. if (type3 >= battle_config.cell_stack_limit) return 1;
  1879. #endif
  1880. case CELL_CHKNOREACH:
  1881. return (type==1 || type==5 || type2&(CELL_MOONLIT|CELL_ICEWALL));
  1882. case CELL_CHKSTACK:
  1883. #ifdef CELL_NOSTACK
  1884. return (type3 >= battle_config.cell_stack_limit);
  1885. #else
  1886. return 0;
  1887. #endif
  1888. case CELL_CHKWALL:
  1889. return (type==1/* || type2&CELL_ICEWALL*/); //Uncomment to prevent sniping/casting through the icewall. [Skotlex]
  1890. case CELL_CHKWATER:
  1891. return (type==3);
  1892. case CELL_CHKGROUND:
  1893. return (type==5 || type2&CELL_ICEWALL);
  1894. case CELL_GETTYPE:
  1895. return type;
  1896. case CELL_GETCELLTYPE:
  1897. return type2;
  1898. case CELL_CHKNPC:
  1899. return (type2&CELL_NPC);
  1900. case CELL_CHKPNEUMA:
  1901. return (type2&CELL_PNEUMA);
  1902. case CELL_CHKSAFETYWALL:
  1903. return (type2&CELL_SAFETYWALL);
  1904. case CELL_CHKBASILICA:
  1905. return (type2&CELL_BASILICA);
  1906. case CELL_CHKLANDPROTECTOR:
  1907. return (type2&CELL_LANDPROTECTOR);
  1908. case CELL_CHKMOONLIT:
  1909. return (type2&CELL_MOONLIT);
  1910. case CELL_CHKREGEN:
  1911. return (type2&CELL_REGEN);
  1912. case CELL_CHKICEWALL:
  1913. return (type2&CELL_ICEWALL);
  1914. default:
  1915. return 0;
  1916. }
  1917. }
  1918. /*==========================================
  1919. * (m,x,y)の状態を設定する
  1920. *------------------------------------------
  1921. */
  1922. void map_setcell(int m,int x,int y,int cell)
  1923. {
  1924. int j;
  1925. if(x<0 || x>=map[m].xs || y<0 || y>=map[m].ys)
  1926. return;
  1927. j=x+y*map[m].xs;
  1928. switch (cell) {
  1929. case CELL_SETNPC:
  1930. map[m].cell[j] |= CELL_NPC;
  1931. break;
  1932. case CELL_CLRNPC:
  1933. map[m].cell[j] &= ~CELL_NPC;
  1934. break;
  1935. case CELL_SETICEWALL:
  1936. map[m].cell[j] |= CELL_ICEWALL;
  1937. break;
  1938. case CELL_CLRICEWALL:
  1939. map[m].cell[j] &= ~CELL_ICEWALL;
  1940. break;
  1941. case CELL_SETBASILICA:
  1942. map[m].cell[j] |= CELL_BASILICA;
  1943. break;
  1944. case CELL_CLRBASILICA:
  1945. map[m].cell[j] &= ~CELL_BASILICA;
  1946. break;
  1947. case CELL_SETPNEUMA:
  1948. map[m].cell[j] |= CELL_PNEUMA;
  1949. break;
  1950. case CELL_CLRPNEUMA:
  1951. map[m].cell[j] &= ~CELL_PNEUMA;
  1952. break;
  1953. case CELL_SETSAFETYWALL:
  1954. map[m].cell[j] |= CELL_SAFETYWALL;
  1955. break;
  1956. case CELL_CLRSAFETYWALL:
  1957. map[m].cell[j] &= ~CELL_SAFETYWALL;
  1958. break;
  1959. case CELL_SETMOONLIT:
  1960. map[m].cell[j] |= CELL_MOONLIT;
  1961. break;
  1962. case CELL_CLRMOONLIT:
  1963. map[m].cell[j] &= ~CELL_MOONLIT;
  1964. break;
  1965. case CELL_SETLANDPROTECTOR:
  1966. map[m].cell[j] |= CELL_LANDPROTECTOR;
  1967. break;
  1968. case CELL_CLRLANDPROTECTOR:
  1969. map[m].cell[j] &= ~CELL_LANDPROTECTOR;
  1970. break;
  1971. case CELL_SETREGEN:
  1972. map[m].cell[j] |= CELL_REGEN;
  1973. break;
  1974. default:
  1975. map[m].gat[j] = cell;
  1976. break;
  1977. }
  1978. }
  1979. static void* create_map_data_other_server(DBKey key, va_list args) {
  1980. struct map_data_other_server *mdos;
  1981. unsigned short mapindex = (unsigned short)key.ui;
  1982. mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server));
  1983. mdos->index = mapindex;
  1984. memcpy(mdos->name, mapindex_id2name(mapindex), MAP_NAME_LENGTH);
  1985. return mdos;
  1986. }
  1987. /*==========================================
  1988. * 他鯖管理のマップをdbに追加
  1989. *------------------------------------------
  1990. */
  1991. int map_setipport(unsigned short mapindex,unsigned long ip,int port) {
  1992. struct map_data_other_server *mdos=NULL;
  1993. mdos=(struct map_data_other_server *)uidb_ensure(map_db,(unsigned int)mapindex, create_map_data_other_server);
  1994. if(mdos->gat) //Local map,Do nothing. Give priority to our own local maps over ones from another server. [Skotlex]
  1995. return 0;
  1996. if(ip == clif_getip() && port == clif_getport()) {
  1997. //That's odd, we received info that we are the ones with this map, but... we don't have it.
  1998. ShowFatalError("map_setipport : received info that this map-server SHOULD have map '%s', but it is not loaded.\n",mapindex_id2name(mapindex));
  1999. exit(1);
  2000. }
  2001. mdos->ip = ip;
  2002. mdos->port = port;
  2003. return 1;
  2004. }
  2005. /*==========================================
  2006. * 他鯖管理のマップを全て削除
  2007. *------------------------------------------
  2008. */
  2009. int map_eraseallipport_sub(DBKey key,void *data,va_list va) {
  2010. struct map_data_other_server *mdos = (struct map_data_other_server*)data;
  2011. if(mdos->gat == NULL) {
  2012. db_remove(map_db,key);
  2013. aFree(mdos);
  2014. }
  2015. return 0;
  2016. }
  2017. int map_eraseallipport(void) {
  2018. map_db->foreach(map_db,map_eraseallipport_sub);
  2019. return 1;
  2020. }
  2021. /*==========================================
  2022. * 他鯖管理のマップをdbから削除
  2023. *------------------------------------------
  2024. */
  2025. int map_eraseipport(unsigned short mapindex,unsigned long ip,int port)
  2026. {
  2027. struct map_data_other_server *mdos;
  2028. // unsigned char *p=(unsigned char *)&ip;
  2029. mdos = uidb_get(map_db,(unsigned int)mapindex);
  2030. if(!mdos || mdos->gat) //Map either does not exists or is a local map.
  2031. return 0;
  2032. if(mdos->ip==ip && mdos->port == port) {
  2033. uidb_remove(map_db,(unsigned int)mapindex);
  2034. aFree(mdos);
  2035. return 1;
  2036. }
  2037. return 0;
  2038. }
  2039. // 初期化周り
  2040. /*==========================================
  2041. * 水場高さ設定
  2042. *------------------------------------------
  2043. */
  2044. static struct waterlist_ {
  2045. char mapname[MAP_NAME_LENGTH];
  2046. int waterheight;
  2047. } *waterlist=NULL;
  2048. #define NO_WATER 1000000
  2049. static int map_setwaterheight_sub(int m, int wh) {
  2050. char fn[256];
  2051. char *gat;
  2052. int x,y;
  2053. struct gat_1cell {float high[4]; int type;} *p = NULL;
  2054. if (m < 0)
  2055. return 0;
  2056. sprintf(fn,"data\\%s",mapindex_id2name(map[m].index));
  2057. // read & convert fn
  2058. // again, might not need to be unsigned char
  2059. gat = (char *) grfio_read (fn);
  2060. if (gat == NULL)
  2061. return 0;
  2062. for (y = 0; y < map[m].ys; y++) {
  2063. p = (struct gat_1cell*)(gat+y*map[m].xs*20+14);
  2064. for (x = 0; x < map[m].xs; x++) {
  2065. if (wh != NO_WATER && p->type == 0) //Set water cell
  2066. map[m].gat[x+y*map[m].xs] = (p->high[0]>wh || p->high[1]>wh || p->high[2]>wh || p->high[3]>wh) ? 3 : 0;
  2067. else //Remove water cell
  2068. map[m].gat[x+y*map[m].xs] = p->type==3?0:p->type;
  2069. p++;
  2070. }
  2071. }
  2072. aFree(gat);
  2073. return 1;
  2074. }
  2075. int map_setwaterheight(int m, char *mapname, int height) {
  2076. int i=0;
  2077. if (height < 0)
  2078. height = NO_WATER;
  2079. if(waterlist){
  2080. for(i=0;waterlist[i].mapname[0] && i < MAX_MAP_PER_SERVER;i++)
  2081. if(strcmp(waterlist[i].mapname,mapname)==0) {
  2082. waterlist[i].waterheight = height;
  2083. }
  2084. }
  2085. if (i < MAX_MAP_PER_SERVER) {
  2086. memcpy(waterlist[i].mapname,mapname, MAP_NAME_LENGTH-1);
  2087. waterlist[i].waterheight = height;
  2088. }
  2089. return map_setwaterheight_sub(m, height);
  2090. }
  2091. int map_waterheight(char *mapname) {
  2092. if(waterlist){
  2093. int i;
  2094. for(i=0;waterlist[i].mapname[0] && i < MAX_MAP_PER_SERVER;i++)
  2095. if(strcmp(waterlist[i].mapname,mapname)==0)
  2096. return waterlist[i].waterheight;
  2097. }
  2098. return NO_WATER;
  2099. }
  2100. static void map_readwater(char *watertxt) {
  2101. char line[1024],w1[1024];
  2102. FILE *fp=NULL;
  2103. int n=0;
  2104. fp=fopen(watertxt,"r");
  2105. if(fp==NULL){
  2106. ShowError("file not found: %s\n",watertxt);
  2107. return;
  2108. }
  2109. if(waterlist==NULL)
  2110. waterlist = (struct waterlist_*)aCallocA(MAX_MAP_PER_SERVER,sizeof(*waterlist));
  2111. while(fgets(line,1020,fp) && n < MAX_MAP_PER_SERVER){
  2112. int wh,count;
  2113. if(line[0] == '/' && line[1] == '/')
  2114. continue;
  2115. if((count=sscanf(line,"%s%d",w1,&wh)) < 1){
  2116. continue;
  2117. }
  2118. memcpy(waterlist[n].mapname,w1, MAP_NAME_LENGTH-1);
  2119. if(count >= 2)
  2120. waterlist[n].waterheight = wh;
  2121. else
  2122. waterlist[n].waterheight = 3;
  2123. n++;
  2124. }
  2125. fclose(fp);
  2126. }
  2127. /*==========================================
  2128. * マップキャッシュに追加する
  2129. *===========================================*/
  2130. // マップキャッシュの最大値
  2131. #define MAX_MAP_CACHE 768
  2132. //各マップごとの最小限情報を入れるもの、READ_FROM_BITMAP用
  2133. struct map_cache_info {
  2134. char fn[32];//ファイル名
  2135. int xs,ys; //幅と高さ
  2136. int water_height;
  2137. int pos; // データが入れてある場所
  2138. int compressed; // zilb通せるようにする為の予約
  2139. int compressed_len; // zilb通せるようにする為の予約
  2140. }; // 56 byte
  2141. struct map_cache_head {
  2142. int sizeof_header;
  2143. int sizeof_map;
  2144. // 上の2つ改変不可
  2145. int nmaps; // マップの個数
  2146. int filesize;
  2147. };
  2148. struct {
  2149. struct map_cache_head head;
  2150. struct map_cache_info *map;
  2151. FILE *fp;
  2152. int dirty;
  2153. } map_cache;
  2154. static int map_cache_open(char *fn);
  2155. static void map_cache_close(void);
  2156. static int map_cache_read(struct map_data *m);
  2157. static int map_cache_write(struct map_data *m);
  2158. static int map_cache_open(char *fn)
  2159. {
  2160. if (map_cache.fp)
  2161. map_cache_close();
  2162. map_cache.fp = fopen(fn, "r+b");
  2163. if (map_cache.fp) {
  2164. fread(&map_cache.head,1,sizeof(struct map_cache_head),map_cache.fp);
  2165. fseek(map_cache.fp,0,SEEK_END);
  2166. if(
  2167. map_cache.head.sizeof_header == sizeof(struct map_cache_head) &&
  2168. map_cache.head.sizeof_map == sizeof(struct map_cache_info) &&
  2169. map_cache.head.filesize == ftell(map_cache.fp)
  2170. ) {
  2171. // キャッシュ読み甲ン成功
  2172. map_cache.map = (struct map_cache_info *) aMalloc(sizeof(struct map_cache_info) * map_cache.head.nmaps);
  2173. fseek(map_cache.fp,sizeof(struct map_cache_head),SEEK_SET);
  2174. fread(map_cache.map,sizeof(struct map_cache_info),map_cache.head.nmaps,map_cache.fp);
  2175. return 1;
  2176. }
  2177. fclose(map_cache.fp);
  2178. }
  2179. // 読み甲ンに失敗したので新規に作成する
  2180. map_cache.fp = fopen(fn,"wb");
  2181. if(map_cache.fp) {
  2182. memset(&map_cache.head,0,sizeof(struct map_cache_head));
  2183. map_cache.map = (struct map_cache_info *) aCalloc(sizeof(struct map_cache_info),MAX_MAP_CACHE);
  2184. map_cache.head.nmaps = MAX_MAP_CACHE;
  2185. map_cache.head.sizeof_header = sizeof(struct map_cache_head);
  2186. map_cache.head.sizeof_map = sizeof(struct map_cache_info);
  2187. map_cache.head.filesize = sizeof(struct map_cache_head);
  2188. map_cache.head.filesize += sizeof(struct map_cache_info) * map_cache.head.nmaps;
  2189. map_cache.dirty = 1;
  2190. return 1;
  2191. }
  2192. return 0;
  2193. }
  2194. static void map_cache_close(void)
  2195. {
  2196. if(!map_cache.fp) { return; }
  2197. if(map_cache.dirty) {
  2198. fseek(map_cache.fp,0,SEEK_SET);
  2199. fwrite(&map_cache.head,1,sizeof(struct map_cache_head),map_cache.fp);
  2200. fwrite(map_cache.map,map_cache.head.nmaps,sizeof(struct map_cache_info),map_cache.fp);
  2201. }
  2202. fclose(map_cache.fp);
  2203. aFree(map_cache.map);
  2204. map_cache.fp = NULL;
  2205. return;
  2206. }
  2207. int map_cache_read(struct map_data *m)
  2208. {
  2209. int i;
  2210. if(!map_cache.fp) { return 0; }
  2211. for(i = 0;i < map_cache.head.nmaps ; i++) {
  2212. if(!strcmp(m->name,map_cache.map[i].fn)) {
  2213. if(map_cache.map[i].water_height != map_waterheight(m->name)) {
  2214. // 水場の高さが違うので読み直し
  2215. return 0;
  2216. } else if(map_cache.map[i].compressed == 0) {
  2217. // 非圧縮ファイル
  2218. int size = map_cache.map[i].xs * map_cache.map[i].ys;
  2219. m->xs = map_cache.map[i].xs;
  2220. m->ys = map_cache.map[i].ys;
  2221. m->gat = (unsigned char *)aCalloc(m->xs * m->ys,sizeof(unsigned char));
  2222. fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET);
  2223. if(fread(m->gat,1,size,map_cache.fp) == size) {
  2224. // 成功
  2225. return 1;
  2226. } else {
  2227. // なぜかファイル後半が欠けてるので読み直し
  2228. m->xs = 0; m->ys = 0; aFree(m->gat); m->gat = NULL;
  2229. return 0;
  2230. }
  2231. } else if(map_cache.map[i].compressed == 1) {
  2232. // 圧縮フラグ=1 : zlib
  2233. unsigned char *buf;
  2234. unsigned long dest_len;
  2235. int size_compress = map_cache.map[i].compressed_len;
  2236. m->xs = map_cache.map[i].xs;
  2237. m->ys = map_cache.map[i].ys;
  2238. m->gat = (unsigned char *)aMalloc(m->xs * m->ys * sizeof(unsigned char));
  2239. buf = (unsigned char*)aMalloc(size_compress);
  2240. fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET);
  2241. if(fread(buf,1,size_compress,map_cache.fp) != size_compress) {
  2242. // なぜかファイル後半が欠けてるので読み直し
  2243. ShowError("fread error\n");
  2244. aFree(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL;
  2245. aFree(buf);
  2246. return 0;
  2247. }
  2248. dest_len = m->xs * m->ys;
  2249. decode_zip(m->gat,&dest_len,buf,size_compress);
  2250. if(dest_len != map_cache.map[i].xs * map_cache.map[i].ys) {
  2251. // 正常に解凍が出来てない
  2252. aFree(m->gat); m->xs = 0; m->ys = 0; m->gat = NULL;
  2253. aFree(buf);
  2254. return 0;
  2255. }
  2256. aFree(buf);
  2257. return 1;
  2258. }
  2259. }
  2260. }
  2261. return 0;
  2262. }
  2263. static int map_cache_write(struct map_data *m)
  2264. {
  2265. int i;
  2266. unsigned long len_new , len_old;
  2267. char *write_buf;
  2268. if(!map_cache.fp) { return 0; }
  2269. for(i = 0;i < map_cache.head.nmaps ; i++) {
  2270. if(!strcmp(m->name,map_cache.map[i].fn)) {
  2271. // 同じエントリーがあれば上書き
  2272. if(map_cache.map[i].compressed == 0) {
  2273. len_old = map_cache.map[i].xs * map_cache.map[i].ys;
  2274. } else if(map_cache.map[i].compressed == 1) {
  2275. len_old = map_cache.map[i].compressed_len;
  2276. } else {
  2277. // サポートされてない形式なので長さ0
  2278. len_old = 0;
  2279. }
  2280. if(map_read_flag == 2) {
  2281. // 圧縮保存
  2282. // さすがに2倍に膨れる事はないという事で
  2283. write_buf = (char *) aMalloc(m->xs * m->ys * 2);
  2284. len_new = m->xs * m->ys * 2;
  2285. encode_zip((unsigned char *) write_buf,&len_new,m->gat,m->xs * m->ys);
  2286. map_cache.map[i].compressed = 1;
  2287. map_cache.map[i].compressed_len = len_new;
  2288. } else {
  2289. len_new = m->xs * m->ys;
  2290. write_buf = (char *) m->gat;
  2291. map_cache.map[i].compressed = 0;
  2292. map_cache.map[i].compressed_len = 0;
  2293. }
  2294. if(len_new <= len_old) {
  2295. // サイズが同じか小さくなったので場所は変わらない
  2296. fseek(map_cache.fp,map_cache.map[i].pos,SEEK_SET);
  2297. fwrite(write_buf,1,len_new,map_cache.fp);
  2298. } else {
  2299. // 新しい場所に登録
  2300. fseek(map_cache.fp,map_cache.head.filesize,SEEK_SET);
  2301. fwrite(write_buf,1,len_new,map_cache.fp);
  2302. map_cache.map[i].pos = map_cache.head.filesize;
  2303. map_cache.head.filesize += len_new;
  2304. }
  2305. map_cache.map[i].xs = m->xs;
  2306. map_cache.map[i].ys = m->ys;
  2307. map_cache.map[i].water_height = map_waterheight(m->name);
  2308. map_cache.dirty = 1;
  2309. if(map_read_flag == 2) {
  2310. aFree(write_buf);
  2311. }
  2312. return 0;
  2313. }
  2314. }
  2315. // 同じエントリが無ければ書き甲゚る場所を探す
  2316. for(i = 0;i < map_cache.head.nmaps ; i++) {
  2317. if(map_cache.map[i].fn[0] == 0) {
  2318. // 新しい場所に登録
  2319. if(map_read_flag == 2) {
  2320. write_buf = (char *) aMalloc(m->xs * m->ys * 2);
  2321. len_new = m->xs * m->ys * 2;
  2322. encode_zip((unsigned char *) write_buf,&len_new,m->gat,m->xs * m->ys);
  2323. map_cache.map[i].compressed = 1;
  2324. map_cache.map[i].compressed_len = len_new;
  2325. } else {
  2326. len_new = m->xs * m->ys;
  2327. write_buf = (char *) m->gat;
  2328. map_cache.map[i].compressed = 0;
  2329. map_cache.map[i].compressed_len = 0;
  2330. }
  2331. strncpy(map_cache.map[i].fn,m->name,sizeof(map_cache.map[0].fn));
  2332. fseek(map_cache.fp,map_cache.head.filesize,SEEK_SET);
  2333. fwrite(write_buf,1,len_new,map_cache.fp);
  2334. map_cache.map[i].pos = map_cache.head.filesize;
  2335. map_cache.map[i].xs = m->xs;
  2336. map_cache.map[i].ys = m->ys;
  2337. map_cache.map[i].water_height = map_waterheight(m->name);
  2338. map_cache.head.filesize += len_new;
  2339. map_cache.dirty = 1;
  2340. if(map_read_flag == 2) {
  2341. aFree(write_buf);
  2342. }
  2343. return 0;
  2344. }
  2345. }
  2346. // 書き甲゚なかった
  2347. return 1;
  2348. }
  2349. /*==========================================
  2350. * ?み?むmapを追加する
  2351. *------------------------------------------
  2352. */
  2353. int map_addmap(char *mapname) {
  2354. if (strcmpi(mapname,"clear")==0) {
  2355. map_num=0;
  2356. return 0;
  2357. }
  2358. if (map_num >= MAX_MAP_PER_SERVER - 1) {
  2359. ShowError("Could not add map '"
  2360. CL_WHITE"%s"CL_RESET"', the limit of maps has been reached.\n",mapname);
  2361. return 1;
  2362. }
  2363. memcpy(map[map_num].name, mapname, MAP_NAME_LENGTH-1);
  2364. map_num++;
  2365. return 0;
  2366. }
  2367. /*==========================================
  2368. * Removes the map in the index passed.
  2369. *------------------------------------------
  2370. */
  2371. static void map_delmapid(int id)
  2372. {
  2373. ShowNotice("Removing map [ %s ] from maplist\n",map[id].name);
  2374. memmove(map+id, map+id+1, sizeof(map[0])*(map_num-id-1));
  2375. map_num--;
  2376. }
  2377. /*==========================================
  2378. * ?み?むmapを削除する
  2379. *------------------------------------------
  2380. */
  2381. int map_delmap(char *mapname) {
  2382. int i;
  2383. if (strcmpi(mapname, "all") == 0) {
  2384. map_num = 0;
  2385. return 0;
  2386. }
  2387. for(i = 0; i < map_num; i++) {
  2388. if (strcmp(map[i].name, mapname) == 0) {
  2389. map_delmapid(i);
  2390. return 1;
  2391. }
  2392. }
  2393. return 0;
  2394. }
  2395. ////////////////////////////////////////////////
  2396. /*
  2397. Advanced Fusion Maps Support
  2398. (c) 2003-2004, The Fusion Project
  2399. - AlexKreuz
  2400. The following code has been provided by me for eAthena
  2401. under the GNU GPL. It provides Advanced Fusion
  2402. Map, the map format desgined by me for Fusion, support
  2403. for the eAthena emulator.
  2404. I understand that because it is under the GPL
  2405. that other emulators may very well use this code in their
  2406. GNU project as well.
  2407. The AFM map format was not originally a part of the GNU
  2408. GPL. It originated from scratch by my own hand. I understand
  2409. that distributing this code to read the AFM maps with eAthena
  2410. causes the GPL to apply to this code. But the actual AFM
  2411. maps are STILL copyrighted to the Fusion Project. By choosing
  2412. In exchange for that 'act of faith' I ask for the following.
  2413. A) Give credit where it is due. If you use this code, do not
  2414. place your name on the changelog. Credit should be given
  2415. to AlexKreuz.
  2416. B) As an act of courtesy, ask me and let me know that you are putting
  2417. AFM support in your project. You will have my blessings if you do.
  2418. C) Use the code in its entirety INCLUDING the copyright message.
  2419. Although the code provided may now be GPL, the AFM maps are not
  2420. and so I ask you to display the copyright message on the STARTUP
  2421. SCREEN as I have done here. (refer to core.c)
  2422. "Advanced Fusion Maps (c) 2003-2004 The Fusion Project"
  2423. Without this copyright, you are NOT entitled to bundle or distribute
  2424. the AFM maps at all. On top of that, your "support" for AFM maps
  2425. becomes just as shady as your "support" for Gravity GRF files.
  2426. The bottom line is this. I know that there are those of you who
  2427. would like to use this code but aren't going to want to provide the
  2428. proper credit. I know this because I speak frome experience. If
  2429. you are one of those people who is going to try to get around my
  2430. requests, then save your breath because I don't want to hear it.
  2431. I have zero faith in GPL and I know and accept that if you choose to
  2432. not display the copyright for the AFMs then there is absolutely nothing
  2433. I can do about it. I am not about to start a legal battle over something
  2434. this silly.
  2435. Provide the proper credit because you believe in the GPL. If you choose
  2436. not to and would rather argue about it, consider the GPL failed.
  2437. October 18th, 2004
  2438. - AlexKreuz
  2439. - The Fusion Project
  2440. */
  2441. static int map_loadafm (struct map_data *m, char *fn)
  2442. {
  2443. // check if .afm file exists
  2444. FILE *afm_file = fopen(fn, "r");
  2445. if (afm_file != NULL) {
  2446. int x,y,xs,ys;
  2447. char afm_line[65535];
  2448. int afm_size[2];
  2449. char *str;
  2450. str = fgets(afm_line, sizeof(afm_line)-1, afm_file);
  2451. str = fgets(afm_line, sizeof(afm_line)-1, afm_file);
  2452. str = fgets(afm_line, sizeof(afm_line)-1, afm_file);
  2453. sscanf(str , "%d%d", &afm_size[0], &afm_size[1]);
  2454. xs = m->xs = afm_size[0];
  2455. ys = m->ys = afm_size[1];
  2456. // check this, unsigned where it might not need to be
  2457. m->gat = (unsigned char*)aCallocA(xs * ys, 1);
  2458. for (y = 0; y < ys; y++) {
  2459. str = fgets(afm_line, sizeof(afm_line)-1, afm_file);
  2460. for (x = 0; x < xs; x++)
  2461. m->gat[x+y*xs] = str[x]-48;
  2462. }
  2463. fclose(afm_file);
  2464. return 1;
  2465. }
  2466. return 0;
  2467. }
  2468. /*==================================
  2469. * .AFM format
  2470. *----------------------------------
  2471. */
  2472. int map_readafm (struct map_data *m)
  2473. {
  2474. char afm_name[256] = "";
  2475. char fn[256], *p;
  2476. // convert map name to .afm
  2477. if(!strstr(m->name, ".afm")) {
  2478. // check if it's necessary to replace the extension - speeds up loading a bit
  2479. strncpy(afm_name, m->name, strlen(m->name) - 4);
  2480. strcat(afm_name, ".afm");
  2481. }
  2482. sprintf(fn, "%s\\%s", afm_dir, afm_name);
  2483. for (p = &fn[0]; *p != 0; p++)
  2484. if (*p == '\\') *p = '/'; // * At the time of Unix
  2485. return map_loadafm(m, fn);
  2486. }
  2487. /*==================================
  2488. * .AF2 format
  2489. *----------------------------------
  2490. */
  2491. int map_readaf2 (struct map_data *m)
  2492. {
  2493. FILE *af2_file;
  2494. char af2_name[256] = "";
  2495. char fn[256], *p, *out;
  2496. // convert map name to .af2
  2497. p = out = m->name;
  2498. while ((p = strchr(p, '/')) != NULL)
  2499. out = ++p;
  2500. strncpy (af2_name, out, strlen(out));
  2501. // grr, this is so troublesome >.< [celest]
  2502. p = strrchr (af2_name, '.');
  2503. if (p) *p++ = 0;
  2504. strcat(af2_name, ".af2");
  2505. sprintf(fn, "%s\\%s", afm_dir, af2_name);
  2506. for (p = &fn[0]; *p != 0; p++)
  2507. if (*p == '\\') *p = '/'; // * At the time of Unix
  2508. // check if .af2 file exists
  2509. af2_file = fopen(fn, "r");
  2510. if (af2_file != NULL) {
  2511. char out_file[256];
  2512. fclose(af2_file);
  2513. // convert map name to .out
  2514. strncpy (out_file, out, strlen(out));
  2515. p = strrchr (out_file, '.');
  2516. if (p) *p++ = 0;
  2517. strcat(out_file, ".out");
  2518. // unzip .out file and use loadafm()
  2519. if (deflate_file(fn, out_file) &&
  2520. map_loadafm(m, out_file))
  2521. {
  2522. unlink (out_file);
  2523. return 1;
  2524. }
  2525. }
  2526. return 0;
  2527. }
  2528. /*==========================================
  2529. * マップ1枚読み甲ン
  2530. * ===================================================*/
  2531. //static int map_readmap(int m,char *fn, char *alias, int *map_cache, int maxmap) {
  2532. /*==================================
  2533. * .GAT format
  2534. *----------------------------------
  2535. */
  2536. int map_readgat (struct map_data *m)
  2537. {
  2538. char fn[256], *pt;
  2539. char *gat;
  2540. int wh,x,y,xs,ys;
  2541. struct gat_1cell {float high[4]; int type;} *p = NULL;
  2542. if (strstr(m->name,".gat") == NULL)
  2543. return 0;
  2544. if ((pt = strstr(m->name,"<")) != NULL) { // [MouseJstr]
  2545. char buf[64];
  2546. *pt++ = '\0';
  2547. sprintf(buf,"data\\%s", pt);
  2548. m->alias = aStrdup(buf);
  2549. }
  2550. sprintf(fn,"data\\%s",m->name);
  2551. // read & convert fn
  2552. // again, might not need to be unsigned char
  2553. gat = (char *) grfio_read (fn);
  2554. if (gat == NULL)
  2555. return 0;
  2556. xs = m->xs = *(int*)(gat+6);
  2557. ys = m->ys = *(int*)(gat+10);
  2558. m->gat = (unsigned char *)aCallocA(m->xs * m->ys, sizeof(unsigned char));
  2559. wh = map_waterheight(m->name);
  2560. for (y = 0; y < ys; y++) {
  2561. p = (struct gat_1cell*)(gat+y*xs*20+14);
  2562. for (x = 0; x < xs; x++) {
  2563. if (wh != NO_WATER && p->type == 0)
  2564. // 水場判定
  2565. m->gat[x+y*xs] = (p->high[0]>wh || p->high[1]>wh || p->high[2]>wh || p->high[3]>wh) ? 3 : 0;
  2566. else
  2567. m->gat[x+y*xs] = p->type;
  2568. p++;
  2569. }
  2570. }
  2571. aFree(gat);
  2572. return 1;
  2573. }
  2574. //////////////////////////////////////////////////////
  2575. static int map_cache_init (void);
  2576. static int map_readafm_init (void);
  2577. static int map_readaf2_init (void);
  2578. static int map_readgat_init (void);
  2579. // Todo: Properly implement this system as plugins/safer code [Celest]
  2580. enum {
  2581. MAP_CACHE = 0, // jAthena map cache
  2582. MAP_AFM, // Advanced Fusion Map
  2583. MAP_AF2, // Advanced Fusion Map
  2584. MAP_GAT, // GRF map
  2585. MAP_MAXSOURCE
  2586. };
  2587. // in descending order
  2588. int (*mapsource_init[MAP_MAXSOURCE])(void) = {
  2589. map_cache_init,
  2590. map_readafm_init,
  2591. map_readaf2_init,
  2592. map_readgat_init
  2593. };
  2594. int (*mapsource_read[MAP_MAXSOURCE])(struct map_data *) = {
  2595. map_cache_read,
  2596. map_readafm,
  2597. map_readaf2,
  2598. map_readgat
  2599. };
  2600. void (*mapsource_final[MAP_MAXSOURCE])(void) = {
  2601. map_cache_close,
  2602. NULL,
  2603. NULL,
  2604. NULL
  2605. };
  2606. static int map_cache_init (void)
  2607. {
  2608. if (map_read_flag >= READ_FROM_BITMAP && map_cache_open(map_cache_file)) {
  2609. ShowMessage("[cache] ");
  2610. return 1;
  2611. }
  2612. return 0;
  2613. }
  2614. static int map_readafm_init (void)
  2615. {
  2616. ShowMessage("[afm] ");
  2617. return 1;
  2618. }
  2619. static int map_readaf2_init (void)
  2620. {
  2621. // check if AFM loading is available,
  2622. // otherwise disable AF2 loading
  2623. if (mapsource_read[1] != NULL) {
  2624. ShowMessage("[af2] ");
  2625. return 1;
  2626. }
  2627. return 0;
  2628. }
  2629. static int map_readgat_init (void)
  2630. {
  2631. ShowMessage("[gat] ");
  2632. return 1;
  2633. }
  2634. /*======================================
  2635. * Initiate maps loading stage
  2636. *--------------------------------------
  2637. */
  2638. int map_readallmaps (void)
  2639. {
  2640. // pre-loading stage
  2641. int i;
  2642. int maps_removed = 0;
  2643. int maps_cached = 0;
  2644. ShowMessage(CL_GREEN"[Status]"CL_RESET": Loading Maps with... "CL_WHITE);
  2645. for (i = 0; i < MAP_MAXSOURCE; i++) {
  2646. if (mapsource_init[i] && // check if source requires initialisation
  2647. mapsource_init[i]() == 0) // if init failed
  2648. {
  2649. // remove all loading methods associated with this source
  2650. mapsource_init[i] = NULL;
  2651. mapsource_read[i] = NULL;
  2652. mapsource_final[i] = NULL;
  2653. }
  2654. }
  2655. ShowMessage(CL_RESET"\n");
  2656. // initiate map loading
  2657. for (i = 0; i < map_num; i++)
  2658. {
  2659. int success = 0;
  2660. static int lasti = -1;
  2661. static int last_time = -1;
  2662. int j = i*20/map_num;
  2663. // show progress
  2664. if (map_num && //avoid map-server crashing if there are 0 maps
  2665. (j != lasti || last_time != time(0)))
  2666. {
  2667. char progress[21] = " ";
  2668. char c = '-';
  2669. int k;
  2670. lasti = j;
  2671. printf("\r");
  2672. ShowStatus("Progress: [");
  2673. for (k=0; k < j; k++) progress[k] = '#';
  2674. printf(progress);
  2675. last_time = (int)time(0);
  2676. switch(last_time % 4) {
  2677. case 0: c='\\'; break;
  2678. case 1: c='|'; break;
  2679. case 2: c='/'; break;
  2680. case 3: c='-'; break;
  2681. }
  2682. printf("] Working: [%c]",c);
  2683. fflush(stdout);
  2684. }
  2685. // pre-init some data
  2686. map[i].alias = NULL;
  2687. map[i].m = i;
  2688. memset (map[i].moblist, 0, sizeof(map[i].moblist)); //Initialize moblist [Skotlex]
  2689. map[i].mob_delete_timer = -1; //Initialize timer [Skotlex]
  2690. if (battle_config.pk_mode)
  2691. map[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris]
  2692. for (j = 0; j < MAP_MAXSOURCE; j++)
  2693. {
  2694. if (mapsource_read[j] && // check if map source is valid
  2695. mapsource_read[j](&map[i])) // check if map source is available
  2696. {
  2697. // successful, now initialise map
  2698. size_t size;
  2699. char *alias;
  2700. if (map[i].alias && (alias = strstr(map[i].name, "<")) != NULL) { // alias has been set by one of the sources
  2701. *alias++ = '\0';
  2702. }
  2703. if (map[i].alias)
  2704. map[i].index = mapindex_name2id(map[i].alias);
  2705. else
  2706. map[i].index = mapindex_name2id(map[i].name);
  2707. if (!map[i].index) {
  2708. if (map[i].alias)
  2709. ShowWarning("Map %s (alias %s) is not in the map-index cache!\n", map[i].name, map[i].alias);
  2710. else
  2711. ShowWarning("Map %s is not in the map-index cache!\n", map[i].name);
  2712. success = 0; //Can't load a map that isn't in our cache.
  2713. if (map[i].gat) {
  2714. aFree(map[i].gat);
  2715. map[i].gat = NULL;
  2716. }
  2717. break;
  2718. }
  2719. if (uidb_get(map_db,(unsigned int)map[i].index) != NULL) {
  2720. ShowWarning("Map %s already loaded!\n", map[i].name);
  2721. success = 0; //Can't load a map already in the db
  2722. if (map[i].gat) {
  2723. aFree(map[i].gat);
  2724. map[i].gat = NULL;
  2725. }
  2726. break;
  2727. }
  2728. map[i].cell = (unsigned char *)aCalloc(map[i].xs * map[i].ys, sizeof(unsigned char));
  2729. #ifdef CELL_NOSTACK
  2730. map[i].cell_bl = (unsigned char *)aCalloc(map[i].xs * map[i].ys, sizeof(unsigned char));
  2731. #endif
  2732. map[i].bxs = (map[i].xs + BLOCK_SIZE - 1) / BLOCK_SIZE;
  2733. map[i].bys = (map[i].ys + BLOCK_SIZE - 1) / BLOCK_SIZE;
  2734. size = map[i].bxs * map[i].bys * sizeof(struct block_list*);
  2735. map[i].block = (struct block_list**)aCalloc(size, 1);
  2736. map[i].block_mob = (struct block_list**)aCalloc(size, 1);
  2737. size = map[i].bxs * map[i].bys * sizeof(int);
  2738. map[i].block_count = (int*)aCallocA(size, 1);
  2739. memset(map[i].block_count, 0, size);
  2740. map[i].block_mob_count = (int*)aCallocA(size, 1);
  2741. memset(map[i].block_mob_count, 0, size);
  2742. uidb_put(map_db, (unsigned int)map[i].index, &map[i]);
  2743. // cache our map if necessary
  2744. if (j != MAP_CACHE && mapsource_read[MAP_CACHE] != NULL) { // map data is not cached yet
  2745. map_cache_write(&map[i]);
  2746. maps_cached++;
  2747. }
  2748. // next map
  2749. success = 1;
  2750. break;
  2751. }
  2752. }
  2753. // no sources have been found, so remove map from list
  2754. if (!success) {
  2755. map_delmapid(i);
  2756. maps_removed++;
  2757. i--;
  2758. }
  2759. }
  2760. // unload map sources
  2761. for (i = 0; i < MAP_MAXSOURCE; i++) {
  2762. if (mapsource_final[i])
  2763. mapsource_final[i]();
  2764. }
  2765. // finished map loading
  2766. aFree(waterlist);
  2767. printf("\r");
  2768. ShowInfo("Successfully loaded '"CL_WHITE"%d"CL_RESET"' maps.%30s\n",map_num,"");
  2769. if (maps_removed)
  2770. ShowNotice("Maps Removed: '"CL_WHITE"%d"CL_RESET"'\n",maps_removed);
  2771. if (maps_cached)
  2772. ShowNotice("Maps Added to Cache: '"CL_WHITE"%d"CL_RESET"'\n",maps_cached);
  2773. return 0;
  2774. }
  2775. ////////////////////////////////////////////////////////////////////////
  2776. static int map_ip_set_ = 0;
  2777. static int char_ip_set_ = 0;
  2778. //static int bind_ip_set_ = 0;
  2779. /*==========================================
  2780. * Console Command Parser [Wizputer]
  2781. *------------------------------------------
  2782. */
  2783. int parse_console(char *buf) {
  2784. char *type,*command,*map, *buf2;
  2785. int x = 0, y = 0;
  2786. int m, n;
  2787. struct map_session_data *sd;
  2788. sd = (struct map_session_data*)aCalloc(sizeof(*sd), 1);
  2789. sd->fd = 0;
  2790. strcpy( sd->status.name , "console");
  2791. type = (char *)aMallocA(64);
  2792. command = (char *)aMallocA(64);
  2793. map = (char *)aMallocA(64);
  2794. buf2 = (char *)aMallocA(72);
  2795. memset(type,0,64);
  2796. memset(command,0,64);
  2797. memset(map,0,64);
  2798. memset(buf2,0,72);
  2799. if ( ( n = sscanf(buf, "%[^:]:%[^:]:%99s %d %d[^\n]", type , command , map , &x , &y )) < 5 )
  2800. if ( ( n = sscanf(buf, "%[^:]:%[^\n]", type , command )) < 2 )
  2801. n = sscanf(buf,"%[^\n]",type);
  2802. if ( n == 5 ) {
  2803. if (x <= 0) {
  2804. x = rand() % 399 + 1;
  2805. sd->bl.x = x;
  2806. } else {
  2807. sd->bl.x = x;
  2808. }
  2809. if (y <= 0) {
  2810. y = rand() % 399 + 1;
  2811. sd->bl.y = y;
  2812. } else {
  2813. sd->bl.y = y;
  2814. }
  2815. m = map_mapname2mapid(map);
  2816. if ( m >= 0 )
  2817. sd->bl.m = m;
  2818. else {
  2819. ShowWarning("Console: Unknown map\n");
  2820. goto end;
  2821. }
  2822. }
  2823. ShowInfo("Type of command: %s || Command: %s || Map: %s Coords: %d %d\n",type,command,map,x,y);
  2824. if ( strcmpi("admin",type) == 0 && n == 5 ) {
  2825. sprintf(buf2,"console: %s",command);
  2826. if( is_atcommand(sd->fd,sd,buf2,99) == AtCommand_None )
  2827. printf("Console: not atcommand\n");
  2828. } else if ( strcmpi("server",type) == 0 && n == 2 ) {
  2829. if ( strcmpi("shutdown", command) == 0 || strcmpi("exit",command) == 0 || strcmpi("quit",command) == 0 ) {
  2830. runflag = 0;
  2831. }
  2832. } else if ( strcmpi("help",type) == 0 ) {
  2833. ShowNotice("To use GM commands:\n");
  2834. printf("admin:<gm command>:<map of \"gm\"> <x> <y>\n");
  2835. printf("You can use any GM command that doesn't require the GM.\n");
  2836. printf("No using @item or @warp however you can use @charwarp\n");
  2837. printf("The <map of \"gm\"> <x> <y> is for commands that need coords of the GM\n");
  2838. printf("IE: @spawn\n");
  2839. printf("To shutdown the server:\n");
  2840. printf("server:shutdown\n");
  2841. }
  2842. end:
  2843. aFree(buf);
  2844. aFree(type);
  2845. aFree(command);
  2846. aFree(map);
  2847. aFree(buf2);
  2848. aFree(sd);
  2849. return 0;
  2850. }
  2851. /*==========================================
  2852. * 設定ファイルを?み?む
  2853. *------------------------------------------
  2854. */
  2855. int map_config_read(char *cfgName) {
  2856. char line[1024], w1[1024], w2[1024];
  2857. FILE *fp;
  2858. struct hostent *h = NULL;
  2859. fp = fopen(cfgName,"r");
  2860. if (fp == NULL) {
  2861. ShowFatalError("Map configuration file not found at: %s\n", cfgName);
  2862. exit(1);
  2863. }
  2864. while(fgets(line, sizeof(line) -1, fp)) {
  2865. if (line[0] == '/' && line[1] == '/')
  2866. continue;
  2867. if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2) {
  2868. if(strcmpi(w1,"timestamp_format")==0){
  2869. strncpy(timestamp_format, w2, 20);
  2870. } else if(strcmpi(w1,"console_silent")==0){
  2871. msg_silent = 0; //To always allow the next line to show up.
  2872. ShowInfo("Console Silent Setting: %d\n", atoi(w2));
  2873. msg_silent = atoi(w2);
  2874. } else if (strcmpi(w1, "userid")==0){
  2875. chrif_setuserid(w2);
  2876. } else if (strcmpi(w1, "passwd") == 0) {
  2877. chrif_setpasswd(w2);
  2878. } else if (strcmpi(w1, "char_ip") == 0) {
  2879. char_ip_set_ = 1;
  2880. h = gethostbyname (w2);
  2881. if(h != NULL) {
  2882. ShowInfo("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]);
  2883. 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]);
  2884. }
  2885. chrif_setip(w2);
  2886. } else if (strcmpi(w1, "char_port") == 0) {
  2887. chrif_setport(atoi(w2));
  2888. } else if (strcmpi(w1, "map_ip") == 0) {
  2889. map_ip_set_ = 1;
  2890. h = gethostbyname (w2);
  2891. if (h != NULL) {
  2892. ShowInfo("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]);
  2893. 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]);
  2894. }
  2895. clif_setip(w2);
  2896. } else if (strcmpi(w1, "bind_ip") == 0) {
  2897. //bind_ip_set_ = 1;
  2898. h = gethostbyname (w2);
  2899. if (h != NULL) {
  2900. ShowInfo("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]);
  2901. 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]);
  2902. }
  2903. clif_setbindip(w2);
  2904. } else if (strcmpi(w1, "map_port") == 0) {
  2905. clif_setport(atoi(w2));
  2906. map_port = (atoi(w2));
  2907. } else if (strcmpi(w1, "water_height") == 0) {
  2908. map_readwater(w2);
  2909. } else if (strcmpi(w1, "map") == 0) {
  2910. map_addmap(w2);
  2911. } else if (strcmpi(w1, "delmap") == 0) {
  2912. map_delmap(w2);
  2913. } else if (strcmpi(w1, "npc") == 0) {
  2914. npc_addsrcfile(w2);
  2915. } else if (strcmpi(w1, "delnpc") == 0) {
  2916. npc_delsrcfile(w2);
  2917. } else if (strcmpi(w1, "autosave_time") == 0) {
  2918. autosave_interval = atoi(w2) * 1000;
  2919. if (autosave_interval <= 0)
  2920. autosave_interval = DEFAULT_AUTOSAVE_INTERVAL;
  2921. } else if (strcmpi(w1, "motd_txt") == 0) {
  2922. strcpy(motd_txt, w2);
  2923. } else if (strcmpi(w1, "help_txt") == 0) {
  2924. strcpy(help_txt, w2);
  2925. } else if (strcmpi(w1, "help2_txt") == 0) {
  2926. strcpy(help2_txt, w2);
  2927. } else if (strcmpi(w1, "charhelp_txt") == 0) {
  2928. strcpy(charhelp_txt, w2);
  2929. } else if (strcmpi(w1, "mapreg_txt") == 0) {
  2930. strcpy(mapreg_txt, w2);
  2931. } else if(strcmpi(w1,"read_map_from_cache") == 0){
  2932. if (atoi(w2) == 2)
  2933. map_read_flag = READ_FROM_BITMAP_COMPRESSED;
  2934. else if (atoi(w2) == 1)
  2935. map_read_flag = READ_FROM_BITMAP;
  2936. else
  2937. map_read_flag = READ_FROM_GAT;
  2938. } else if(strcmpi(w1,"map_cache_file") == 0) {
  2939. strncpy(map_cache_file,w2,255);
  2940. } else if(strcmpi(w1,"db_path") == 0) {
  2941. strncpy(db_path,w2,255);
  2942. } else if(strcmpi(w1,"afm_dir") == 0) {
  2943. strcpy(afm_dir, w2);
  2944. } else if (strcmpi(w1, "console") == 0) {
  2945. if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 ) {
  2946. console = 1;
  2947. ShowNotice("Console Commands are enabled.\n");
  2948. }
  2949. } else if (strcmpi(w1, "enable_spy") == 0) {
  2950. if(strcmpi(w2,"on") == 0 || strcmpi(w2,"yes") == 0 )
  2951. enable_spy = 1;
  2952. else
  2953. enable_spy = 0;
  2954. } else if (strcmpi(w1, "import") == 0) {
  2955. map_config_read(w2);
  2956. }
  2957. }
  2958. }
  2959. fclose(fp);
  2960. return 0;
  2961. }
  2962. int inter_config_read(char *cfgName)
  2963. {
  2964. int i;
  2965. char line[1024],w1[1024],w2[1024];
  2966. FILE *fp;
  2967. fp=fopen(cfgName,"r");
  2968. if(fp==NULL){
  2969. ShowError("File not found: '%s'.\n",cfgName);
  2970. return 1;
  2971. }
  2972. while(fgets(line,1020,fp)){
  2973. if(line[0] == '/' && line[1] == '/')
  2974. continue;
  2975. i=sscanf(line,"%[^:]: %[^\r\n]",w1,w2);
  2976. if(i!=2)
  2977. continue;
  2978. if(strcmpi(w1,"kick_on_disconnect")==0){
  2979. kick_on_disconnect = battle_config_switch(w2);
  2980. } else if(strcmpi(w1,"party_share_level")==0){
  2981. party_share_level = battle_config_switch(w2);
  2982. } else if(strcmpi(w1,"lowest_gm_level")==0){
  2983. lowest_gm_level = atoi(w2);
  2984. /* Main chat nick [LuzZza] */
  2985. } else if(strcmpi(w1, "main_chat_nick")==0){
  2986. strcpy(main_chat_nick, w2);
  2987. #ifndef TXT_ONLY
  2988. } else if(strcmpi(w1,"charsave_method")==0){
  2989. charsave_method = atoi(w2); //New char saving method.
  2990. } else if(strcmpi(w1,"item_db_db")==0){
  2991. strcpy(item_db_db,w2);
  2992. } else if(strcmpi(w1,"mob_db_db")==0){
  2993. strcpy(mob_db_db,w2);
  2994. } else if(strcmpi(w1,"item_db2_db")==0){
  2995. strcpy(item_db2_db,w2);
  2996. } else if(strcmpi(w1,"mob_db2_db")==0){
  2997. strcpy(mob_db2_db,w2);
  2998. } else if(strcmpi(w1,"login_db_level")==0){
  2999. strcpy(login_db_level,w2);
  3000. } else if(strcmpi(w1,"login_db_account_id")==0){
  3001. strcpy(login_db_account_id,w2);
  3002. } else if(strcmpi(w1,"login_db")==0){
  3003. strcpy(login_db,w2);
  3004. } else if (strcmpi(w1, "char_db") == 0) {
  3005. strcpy(char_db, w2);
  3006. } else if(strcmpi(w1,"gm_db_level")==0){
  3007. strcpy(gm_db_level,w2);
  3008. } else if(strcmpi(w1,"gm_db_account_id")==0){
  3009. strcpy(gm_db_account_id,w2);
  3010. } else if(strcmpi(w1,"gm_db")==0){
  3011. strcpy(gm_db,w2);
  3012. //Map Server SQL DB
  3013. } else if(strcmpi(w1,"map_server_ip")==0){
  3014. strcpy(map_server_ip, w2);
  3015. } else if(strcmpi(w1,"map_server_port")==0){
  3016. map_server_port=atoi(w2);
  3017. } else if(strcmpi(w1,"map_server_id")==0){
  3018. strcpy(map_server_id, w2);
  3019. } else if(strcmpi(w1,"map_server_pw")==0){
  3020. strcpy(map_server_pw, w2);
  3021. } else if(strcmpi(w1,"map_server_db")==0){
  3022. strcpy(map_server_db, w2);
  3023. } else if(strcmpi(w1,"default_codepage")==0){
  3024. strcpy(default_codepage, w2);
  3025. } else if(strcmpi(w1,"use_sql_db")==0){
  3026. db_use_sqldbs = battle_config_switch(w2);
  3027. ShowStatus ("Using SQL dbs: %s\n",w2);
  3028. //Login Server SQL DB
  3029. } else if(strcmpi(w1,"login_server_ip")==0){
  3030. strcpy(login_server_ip, w2);
  3031. } else if(strcmpi(w1,"login_server_port")==0){
  3032. login_server_port = atoi(w2);
  3033. } else if(strcmpi(w1,"login_server_id")==0){
  3034. strcpy(login_server_id, w2);
  3035. } else if(strcmpi(w1,"login_server_pw")==0){
  3036. strcpy(login_server_pw, w2);
  3037. } else if(strcmpi(w1,"login_server_db")==0){
  3038. strcpy(login_server_db, w2);
  3039. } else if(strcmpi(w1,"read_gm_interval")==0){
  3040. read_gm_interval = ( atoi(w2) * 60 * 1000 ); // Minutes multiplied by 60 secs per min by 1000 milliseconds per second
  3041. }else if(strcmpi(w1, "char_server_ip") == 0){
  3042. strcpy(charsql_host, w2);
  3043. }else if(strcmpi(w1, "char_server_port") == 0){
  3044. charsql_port = atoi(w2);
  3045. }else if(strcmpi(w1, "char_server_id") == 0){
  3046. strcpy(charsql_user, w2);
  3047. }else if(strcmpi(w1, "char_server_pw") == 0){
  3048. strcpy(charsql_pass, w2);
  3049. }else if(strcmpi(w1, "char_server_db") == 0){
  3050. strcpy(charsql_db, w2);
  3051. } else if(strcmpi(w1,"log_db")==0) {
  3052. strcpy(log_db, w2);
  3053. } else if(strcmpi(w1,"log_db_ip")==0) {
  3054. strcpy(log_db_ip, w2);
  3055. } else if(strcmpi(w1,"log_db")==0) {
  3056. strcpy(log_db, w2);
  3057. } else if(strcmpi(w1,"log_db_id")==0) {
  3058. strcpy(log_db_id, w2);
  3059. } else if(strcmpi(w1,"log_db_pw")==0) {
  3060. strcpy(log_db_pw, w2);
  3061. } else if(strcmpi(w1,"log_db_port")==0) {
  3062. log_db_port = atoi(w2);
  3063. // Mail Server SQL
  3064. } else if(strcmpi(w1,"mail_server_enable")==0){
  3065. mail_server_enable = battle_config_switch(w2);
  3066. ShowStatus ("Using Mail Server: %s\n",w2);
  3067. } else if(strcmpi(w1,"mail_server_ip")==0){
  3068. strcpy(mail_server_ip, w2);
  3069. } else if(strcmpi(w1,"mail_server_port")==0){
  3070. mail_server_port=atoi(w2);
  3071. } else if(strcmpi(w1,"mail_server_id")==0){
  3072. strcpy(mail_server_id, w2);
  3073. } else if(strcmpi(w1,"mail_server_pw")==0){
  3074. strcpy(mail_server_pw, w2);
  3075. } else if(strcmpi(w1,"mail_server_db")==0){
  3076. strcpy(mail_server_db, w2);
  3077. } else if(strcmpi(w1,"mail_db")==0) {
  3078. strcpy(mail_db, w2);
  3079. #endif
  3080. //support the import command, just like any other config
  3081. } else if(strcmpi(w1,"import")==0){
  3082. inter_config_read(w2);
  3083. }
  3084. }
  3085. fclose(fp);
  3086. return 0;
  3087. }
  3088. #ifndef TXT_ONLY
  3089. /*=======================================
  3090. * MySQL Init
  3091. *---------------------------------------
  3092. */
  3093. int map_sql_init(void){
  3094. mysql_init(&mmysql_handle);
  3095. //DB connection start
  3096. ShowInfo("Connecting to the Map DB Server....\n");
  3097. if(!mysql_real_connect(&mmysql_handle, map_server_ip, map_server_id, map_server_pw,
  3098. map_server_db ,map_server_port, (char *)NULL, 0)) {
  3099. //pointer check
  3100. ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle));
  3101. exit(1);
  3102. }
  3103. else {
  3104. ShowStatus("connect success! (Map Server Connection)\n");
  3105. }
  3106. mysql_init(&lmysql_handle);
  3107. //DB connection start
  3108. ShowInfo("Connecting to the Login DB Server....\n");
  3109. if(!mysql_real_connect(&lmysql_handle, login_server_ip, login_server_id, login_server_pw,
  3110. login_server_db ,login_server_port, (char *)NULL, 0)) {
  3111. //pointer check
  3112. ShowSQL("DB error - %s\n",mysql_error(&lmysql_handle));
  3113. exit(1);
  3114. }
  3115. else {
  3116. ShowStatus ("connect success! (Login Server Connection)\n");
  3117. }
  3118. #ifdef MAPREGSQL
  3119. // [zBuffer] SQL Mapreg connection start
  3120. ShowInfo("Connect Mapreg DB Server....\n");
  3121. mysql_init(&mapregsql_handle);
  3122. if(!mysql_real_connect(&mapregsql_handle, map_server_ip, map_server_id, map_server_pw,
  3123. map_server_db ,map_server_port, (char *)NULL, 0)) {
  3124. //pointer check
  3125. ShowSQL("DB error - %s\n",mysql_error(&mapregsql_handle));
  3126. exit(1);
  3127. } else {
  3128. ShowStatus ("Connect success! (Mapreg DB Connection)\n");
  3129. if( strlen(default_codepage) > 0 ) {
  3130. sprintf( tmp_sql, "SET NAMES %s", default_codepage );
  3131. if (mysql_query(&mapregsql_handle, tmp_sql)) {
  3132. ShowSQL("DB error - %s\n",mysql_error(&mapregsql_handle));
  3133. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  3134. }
  3135. }
  3136. }
  3137. #endif
  3138. if(mail_server_enable) { // mail system [Valaris]
  3139. mysql_init(&mail_handle);
  3140. ShowInfo("Connecting to the Mail DB Server....\n");
  3141. if(!mysql_real_connect(&mail_handle, mail_server_ip, mail_server_id, mail_server_pw,
  3142. mail_server_db ,mail_server_port, (char *)NULL, 0)) {
  3143. ShowSQL("DB error - %s\n",mysql_error(&mail_handle));
  3144. exit(1);
  3145. }
  3146. if( strlen(default_codepage) > 0 ) {
  3147. sprintf( tmp_sql, "SET NAMES %s", default_codepage );
  3148. if (mysql_query(&mail_handle, tmp_sql)) {
  3149. ShowSQL("DB error - %s\n",mysql_error(&mail_handle));
  3150. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  3151. }
  3152. }
  3153. }
  3154. if( strlen(default_codepage) > 0 ) {
  3155. sprintf( tmp_sql, "SET NAMES %s", default_codepage );
  3156. if (mysql_query(&mmysql_handle, tmp_sql)) {
  3157. ShowSQL("DB error - %s\n",mysql_error(&mmysql_handle));
  3158. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  3159. }
  3160. if (mysql_query(&lmysql_handle, tmp_sql)) {
  3161. ShowSQL("DB error - %s\n",mysql_error(&lmysql_handle));
  3162. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  3163. }
  3164. }
  3165. return 0;
  3166. }
  3167. int map_sql_close(void){
  3168. mysql_close(&mmysql_handle);
  3169. ShowStatus("Close Map DB Connection....\n");
  3170. mysql_close(&lmysql_handle);
  3171. ShowStatus("Close Login DB Connection....\n");
  3172. #ifdef MAPREGSQL
  3173. // [zBuffer] SQL Mapreg connection stop
  3174. mysql_close(&mapregsql_handle);
  3175. ShowStatus("Close Mapreg DB Connection....\n");
  3176. #endif
  3177. if (log_config.sql_logs)
  3178. //Updating this if each time there's a log_config addition is too much of a hassle. [Skotlex]
  3179. /*&& (log_config.branch || log_config.drop || log_config.mvpdrop ||
  3180. log_config.present || log_config.produce || log_config.refine || log_config.trade))*/
  3181. {
  3182. mysql_close(&logmysql_handle);
  3183. ShowStatus("Close Log DB Connection....\n");
  3184. }
  3185. return 0;
  3186. }
  3187. int log_sql_init(void){
  3188. mysql_init(&logmysql_handle);
  3189. //DB connection start
  3190. ShowInfo(""CL_WHITE"[SQL]"CL_RESET": Connecting to the Log Database "CL_WHITE"%s"CL_RESET" At "CL_WHITE"%s"CL_RESET"...\n",log_db,log_db_ip);
  3191. if(!mysql_real_connect(&logmysql_handle, log_db_ip, log_db_id, log_db_pw,
  3192. log_db ,log_db_port, (char *)NULL, 0)) {
  3193. //pointer check
  3194. ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle));
  3195. exit(1);
  3196. }
  3197. ShowStatus(""CL_WHITE"[SQL]"CL_RESET": Successfully '"CL_GREEN"connected"CL_RESET"' to Database '"CL_WHITE"%s"CL_RESET"'.\n", log_db);
  3198. if( strlen(default_codepage) > 0 ) {
  3199. sprintf( tmp_sql, "SET NAMES %s", default_codepage );
  3200. if (mysql_query(&logmysql_handle, tmp_sql)) {
  3201. ShowSQL("DB error - %s\n",mysql_error(&logmysql_handle));
  3202. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  3203. }
  3204. }
  3205. return 0;
  3206. }
  3207. #endif /* not TXT_ONLY */
  3208. int map_db_final(DBKey k,void *d,va_list ap)
  3209. {
  3210. // Not needed actually, these are already freed. [Lance]
  3211. //struct map_data_other_server *mdos = (struct map_data_other_server*)d;
  3212. //if(mdos->gat == NULL)
  3213. // aFree(mdos);
  3214. return 0;
  3215. }
  3216. int nick_db_final(void *k,void *d,va_list ap)
  3217. {
  3218. char *p = (char *) d;
  3219. if (p) aFree(p);
  3220. return 0;
  3221. }
  3222. int cleanup_sub(struct block_list *bl, va_list ap) {
  3223. nullpo_retr(0, bl);
  3224. switch(bl->type) {
  3225. case BL_PC:
  3226. map_quit((struct map_session_data *) bl);
  3227. break;
  3228. case BL_NPC:
  3229. npc_unload((struct npc_data *)bl);
  3230. break;
  3231. case BL_MOB:
  3232. mob_unload((struct mob_data *)bl);
  3233. break;
  3234. case BL_PET:
  3235. //There is no need for this, the pet is removed together with the player. [Skotlex]
  3236. // pet_remove_map(((struct pet_data *)bl)->msd);
  3237. break;
  3238. case BL_ITEM:
  3239. map_clearflooritem(bl->id);
  3240. break;
  3241. case BL_SKILL:
  3242. skill_delunit((struct skill_unit *) bl);
  3243. break;
  3244. }
  3245. return 0;
  3246. }
  3247. /*==========================================
  3248. * map鯖終了・理
  3249. *------------------------------------------
  3250. */
  3251. void do_final(void) {
  3252. int i, j;
  3253. struct map_session_data **pl_allsd;
  3254. ShowStatus("Terminating...\n");
  3255. // we probably don't need the cache open at all times 'yet', so this is closed by mapsource_final [celest]
  3256. //map_cache_close();
  3257. grfio_final();
  3258. for (i = 0; i < map_num; i++)
  3259. if (map[i].m >= 0)
  3260. map_foreachinmap(cleanup_sub, i, BL_ALL);
  3261. //Scan any remaining players (between maps?) to kick them out. [Skotlex]
  3262. pl_allsd = map_getallusers(&j);
  3263. for (i = 0; i < j; i++)
  3264. map_quit(pl_allsd[i]);
  3265. chrif_char_reset_offline();
  3266. chrif_flush_fifo();
  3267. do_final_atcommand();
  3268. do_final_battle();
  3269. do_final_chrif(); // この内部でキャラを全て切断する
  3270. do_final_npc();
  3271. // map_removenpc();
  3272. do_final_script();
  3273. do_final_itemdb();
  3274. do_final_storage();
  3275. do_final_guild();
  3276. do_final_party();
  3277. do_final_pc();
  3278. do_final_pet();
  3279. do_final_mob();
  3280. do_final_msg();
  3281. if(use_irc)
  3282. do_final_irc();
  3283. map_getallusers(NULL); //Clear the memory allocated for this array.
  3284. map_db->destroy(map_db, map_db_final);
  3285. for (i=0; i<map_num; i++) {
  3286. if(map[i].gat) aFree(map[i].gat);
  3287. if(map[i].cell) aFree(map[i].cell);
  3288. #ifdef CELL_NOSTACK
  3289. if(map[i].cell_bl) aFree(map[i].cell_bl);
  3290. #endif
  3291. if(map[i].block) aFree(map[i].block);
  3292. if(map[i].block_mob) aFree(map[i].block_mob);
  3293. if(map[i].block_count) aFree(map[i].block_count);
  3294. if(map[i].block_mob_count) aFree(map[i].block_mob_count);
  3295. if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random]
  3296. for (j=0; j<MAX_MOB_LIST_PER_MAP; j++)
  3297. if (map[i].moblist[j]) aFree(map[i].moblist[j]);
  3298. }
  3299. }
  3300. mapindex_final();
  3301. id_db->destroy(id_db, NULL);
  3302. pc_db->destroy(pc_db, NULL);
  3303. charid_db->destroy(charid_db, NULL);
  3304. //#endif
  3305. #ifndef TXT_ONLY
  3306. map_sql_close();
  3307. if(charsave_method)
  3308. charsql_db_init(0); //Connecting to chardb
  3309. #endif /* not TXT_ONLY */
  3310. ShowStatus("Successfully terminated.\n");
  3311. }
  3312. /*======================================================
  3313. * Map-Server Version Screen [MC Cameri]
  3314. *------------------------------------------------------
  3315. */
  3316. void map_helpscreen(int flag) { // by MC Cameri
  3317. puts("Usage: map-server [options]");
  3318. puts("Options:");
  3319. puts(CL_WHITE" Commands\t\t\tDescription"CL_RESET);
  3320. puts("-----------------------------------------------------------------------------");
  3321. puts(" --help, --h, --?, /? Displays this help screen");
  3322. puts(" --map-config <file> Load map-server configuration from <file>");
  3323. puts(" --battle-config <file> Load battle configuration from <file>");
  3324. puts(" --atcommand-config <file> Load atcommand configuration from <file>");
  3325. puts(" --charcommand-config <file> Load charcommand configuration from <file>");
  3326. puts(" --script-config <file> Load script configuration from <file>");
  3327. puts(" --msg-config <file> Load message configuration from <file>");
  3328. puts(" --grf-path-file <file> Load grf path file configuration from <file>");
  3329. puts(" --sql-config <file> Load inter-server configuration from <file>");
  3330. puts(" (SQL Only)");
  3331. puts(" --log-config <file> Load logging configuration from <file>");
  3332. puts(" (SQL Only)");
  3333. puts(" --version, --v, -v, /v Displays the server's version");
  3334. puts("\n");
  3335. if (flag) exit(1);
  3336. }
  3337. /*======================================================
  3338. * Map-Server Version Screen [MC Cameri]
  3339. *------------------------------------------------------
  3340. */
  3341. void map_versionscreen(int flag) {
  3342. printf("CL_WHITE" "eAthena version %d.%02d.%02d, Athena Mod version %d" CL_RESET"\n",
  3343. ATHENA_MAJOR_VERSION, ATHENA_MINOR_VERSION, ATHENA_REVISION,
  3344. ATHENA_MOD_VERSION);
  3345. puts(CL_GREEN "Website/Forum:" CL_RESET "\thttp://eathena.deltaanime.net/");
  3346. puts(CL_GREEN "Download URL:" CL_RESET "\thttp://eathena.systeminplace.net/");
  3347. puts(CL_GREEN "IRC Channel:" CL_RESET "\tirc://irc.deltaanime.net/#athena");
  3348. puts("\nOpen " CL_WHITE "readme.html" CL_RESET " for more information.");
  3349. if (ATHENA_RELEASE_FLAG) ShowNotice("This version is not for release.\n");
  3350. if (flag) exit(1);
  3351. }
  3352. /*======================================================
  3353. * Map-Server Init and Command-line Arguments [Valaris]
  3354. *------------------------------------------------------
  3355. */
  3356. void set_server_type(void)
  3357. {
  3358. SERVER_TYPE = ATHENA_SERVER_MAP;
  3359. }
  3360. int do_init(int argc, char *argv[]) {
  3361. int i;
  3362. #ifdef GCOLLECT
  3363. GC_enable_incremental();
  3364. #endif
  3365. INTER_CONF_NAME="conf/inter_athena.conf";
  3366. LOG_CONF_NAME="conf/log_athena.conf";
  3367. MAP_CONF_NAME = "conf/map_athena.conf";
  3368. BATTLE_CONF_FILENAME = "conf/battle_athena.conf";
  3369. ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf";
  3370. CHARCOMMAND_CONF_FILENAME = "conf/charcommand_athena.conf";
  3371. SCRIPT_CONF_NAME = "conf/script_athena.conf";
  3372. MSG_CONF_NAME = "conf/msg_athena.conf";
  3373. GRF_PATH_FILENAME = "conf/grf-files.txt";
  3374. chrif_connected = 0;
  3375. srand(gettick());
  3376. for (i = 1; i < argc ; i++) {
  3377. if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "--h") == 0 || strcmp(argv[i], "--?") == 0 || strcmp(argv[i], "/?") == 0)
  3378. map_helpscreen(1);
  3379. else if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "--v") == 0 || strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "/v") == 0)
  3380. map_versionscreen(1);
  3381. else if (strcmp(argv[i], "--map_config") == 0 || strcmp(argv[i], "--map-config") == 0)
  3382. MAP_CONF_NAME=argv[i+1];
  3383. else if (strcmp(argv[i],"--battle_config") == 0 || strcmp(argv[i],"--battle-config") == 0)
  3384. BATTLE_CONF_FILENAME = argv[i+1];
  3385. else if (strcmp(argv[i],"--atcommand_config") == 0 || strcmp(argv[i],"--atcommand-config") == 0)
  3386. ATCOMMAND_CONF_FILENAME = argv[i+1];
  3387. else if (strcmp(argv[i],"--charcommand_config") == 0 || strcmp(argv[i],"--charcommand-config") == 0)
  3388. CHARCOMMAND_CONF_FILENAME = argv[i+1];
  3389. else if (strcmp(argv[i],"--script_config") == 0 || strcmp(argv[i],"--script-config") == 0)
  3390. SCRIPT_CONF_NAME = argv[i+1];
  3391. else if (strcmp(argv[i],"--msg_config") == 0 || strcmp(argv[i],"--msg-config") == 0)
  3392. MSG_CONF_NAME = argv[i+1];
  3393. else if (strcmp(argv[i],"--grf_path_file") == 0 || strcmp(argv[i],"--grf-path-file") == 0)
  3394. GRF_PATH_FILENAME = argv[i+1];
  3395. #ifndef TXT_ONLY
  3396. else if (strcmp(argv[i],"--inter_config") == 0 || strcmp(argv[i],"--inter-config") == 0)
  3397. INTER_CONF_NAME = argv[i+1];
  3398. #endif
  3399. else if (strcmp(argv[i],"--log_config") == 0 || strcmp(argv[i],"--log-config") == 0)
  3400. LOG_CONF_NAME = argv[i+1];
  3401. else if (strcmp(argv[i],"--run_once") == 0) // close the map-server as soon as its done.. for testing [Celest]
  3402. runflag = 0;
  3403. }
  3404. map_config_read(MAP_CONF_NAME);
  3405. chrif_checkdefaultlogin();
  3406. if ((naddr_ == 0) && (map_ip_set_ == 0 || char_ip_set_ == 0)) {
  3407. ShowError("\nUnable to determine your IP address... please edit the map_athena.conf file and set it.\n");
  3408. ShowError("(127.0.0.1 is valid if you have no network interface)\n");
  3409. }
  3410. if (map_ip_set_ == 0 || char_ip_set_ == 0) {
  3411. // The map server should know what IP address it is running on
  3412. // - MouseJstr
  3413. int localaddr = ntohl(addr_[0]);
  3414. unsigned char *ptr = (unsigned char *) &localaddr;
  3415. char buf[16];
  3416. sprintf(buf, "%d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);;
  3417. if (naddr_ != 1)
  3418. ShowNotice("Multiple interfaces detected.. using %s as our IP address\n", buf);
  3419. else
  3420. ShowInfo("Defaulting to %s as our IP address\n", buf);
  3421. if (map_ip_set_ == 0)
  3422. clif_setip(buf);
  3423. if (char_ip_set_ == 0)
  3424. chrif_setip(buf);
  3425. if (ptr[0] == 192 && ptr[1] == 168)
  3426. ShowError("\nFirewall detected.. \n edit lan_support.conf and map_athena.conf\n\n");
  3427. }
  3428. if (SHOW_DEBUG_MSG)
  3429. ShowNotice("Server running in '"CL_WHITE"Debug Mode"CL_RESET"'.\n");
  3430. battle_config_read(BATTLE_CONF_FILENAME);
  3431. msg_config_read(MSG_CONF_NAME);
  3432. atcommand_config_read(ATCOMMAND_CONF_FILENAME);
  3433. charcommand_config_read(CHARCOMMAND_CONF_FILENAME);
  3434. script_config_read(SCRIPT_CONF_NAME);
  3435. inter_config_read(INTER_CONF_NAME);
  3436. log_config_read(LOG_CONF_NAME);
  3437. id_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int));
  3438. pc_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_BASE,sizeof(int)); //Added for reliable map_id2sd() use. [Skotlex]
  3439. map_db = db_alloc(__FILE__,__LINE__,DB_UINT,DB_OPT_BASE,sizeof(int));
  3440. charid_db = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int));
  3441. #ifndef TXT_ONLY
  3442. map_sql_init();
  3443. if(charsave_method)
  3444. charsql_db_init(1); //Connecting to chardb
  3445. #endif /* not TXT_ONLY */
  3446. mapindex_init();
  3447. grfio_init(GRF_PATH_FILENAME);
  3448. map_readallmaps();
  3449. add_timer_func_list(map_freeblock_timer, "map_freeblock_timer");
  3450. add_timer_func_list(map_clearflooritem_timer, "map_clearflooritem_timer");
  3451. add_timer_func_list(map_removemobs_timer, "map_removemobs_timer");
  3452. add_timer_interval(gettick()+1000, map_freeblock_timer, 0, 0, 60*1000);
  3453. if(use_irc)
  3454. do_init_irc();
  3455. do_init_atcommand();
  3456. do_init_battle();
  3457. do_init_chrif();
  3458. do_init_clif();
  3459. do_init_script();
  3460. do_init_itemdb();
  3461. do_init_mob(); // npcの初期化・でmob_spawnして、mob_dbを?照するのでinit_npcより先
  3462. do_init_pc();
  3463. do_init_status();
  3464. do_init_party();
  3465. do_init_guild();
  3466. do_init_storage();
  3467. do_init_skill();
  3468. do_init_pet();
  3469. do_init_npc();
  3470. #ifndef TXT_ONLY /* mail system [Valaris] */
  3471. if(mail_server_enable)
  3472. do_init_mail();
  3473. if (log_config.sql_logs)
  3474. {
  3475. log_sql_init();
  3476. }
  3477. #endif /* not TXT_ONLY */
  3478. npc_event_do_oninit(); // npcのOnInitイベント?行
  3479. if ( console ) {
  3480. set_defaultconsoleparse(parse_console);
  3481. start_console();
  3482. }
  3483. if (battle_config.pk_mode == 1)
  3484. ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n");
  3485. ShowStatus("Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map_port);
  3486. return 0;
  3487. }
  3488. int compare_item(struct item *a, struct item *b) {
  3489. if (a->nameid == b->nameid &&
  3490. a->identify == b->identify &&
  3491. a->refine == b->refine &&
  3492. a->attribute == b->attribute)
  3493. {
  3494. int i;
  3495. for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++);
  3496. return (i == MAX_SLOTS);
  3497. }
  3498. return 0;
  3499. }
  3500. #ifndef TXT_ONLY
  3501. int charsql_db_init(int method){
  3502. if(method == 1){ //'INIT / START'
  3503. ShowInfo("Connecting to 'character' Database... ");
  3504. mysql_init(&charsql_handle);
  3505. if(!mysql_real_connect(&charsql_handle, charsql_host, charsql_user, charsql_pass, charsql_db, charsql_port, (char *)NULL, 0)){
  3506. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  3507. exit(1);
  3508. }else{
  3509. printf("success.\n");
  3510. if( strlen(default_codepage) > 0 ) {
  3511. sprintf( tmp_sql, "SET NAMES %s", default_codepage );
  3512. if (mysql_query(&charsql_handle, tmp_sql)) {
  3513. ShowSQL("DB error - %s\n",mysql_error(&charsql_handle));
  3514. ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
  3515. }
  3516. }
  3517. }
  3518. }else if(method == 0){ //'FINAL' / Shutdown
  3519. ShowInfo("Closing 'character' Database connection ... ");
  3520. mysql_close(&charsql_handle);
  3521. printf("done.\n");
  3522. }
  3523. return 0;
  3524. }
  3525. #endif